diff --git a/dvaas/BUILD.bazel b/dvaas/BUILD.bazel index c38cc3f04..08cd346d0 100644 --- a/dvaas/BUILD.bazel +++ b/dvaas/BUILD.bazel @@ -256,3 +256,54 @@ cc_test( "@com_google_googletest//:gtest_main", ], ) + +cc_library( + name = "user_provided_packet_test_vector", + testonly = True, + srcs = ["user_provided_packet_test_vector.cc"], + hdrs = ["user_provided_packet_test_vector.h"], + deps = [ + ":test_vector", + ":test_vector_cc_proto", + "//gutil:proto", + "//gutil:status", + "//p4_pdpi/packetlib", + "@com_google_absl//absl/status", + "@com_google_absl//absl/status:statusor", + "@com_google_absl//absl/strings", + "@com_google_absl//absl/types:span", + ], +) + +# go/golden-test-with-coverage +cc_test( + name = "user_provided_packet_test_vector_test", + srcs = ["user_provided_packet_test_vector_test.cc"], + linkstatic = True, + deps = [ + ":test_vector", + ":test_vector_cc_proto", + ":user_provided_packet_test_vector", + "//gutil:collections", + "//gutil:proto", + "//gutil:status_matchers", + "//gutil:testing", + "//p4_pdpi/packetlib:packetlib_cc_proto", + "@com_google_absl//absl/status", + "@com_google_absl//absl/status:statusor", + "@com_google_absl//absl/strings", + "@com_google_googletest//:gtest_main", + ], +) + +cmd_diff_test( + name = "user_provided_packet_test_vector_diff_test", + actual_cmd = " | ".join([ + "$(execpath :user_provided_packet_test_vector_test)", + # Strip unnecessary lines for golden testing. + "sed '1,/^\\[ RUN/d'", # Strip everything up to a line beginning with '[ RUN'. + "sed '/^\\[/d'", # Strip every line beginning with '['. + ]), + expected = "user_provided_packet_test_vector_test.expected", + tools = [":user_provided_packet_test_vector_test"], +) diff --git a/dvaas/user_provided_packet_test_vector.cc b/dvaas/user_provided_packet_test_vector.cc new file mode 100644 index 000000000..a2f11d7ff --- /dev/null +++ b/dvaas/user_provided_packet_test_vector.cc @@ -0,0 +1,113 @@ +#include "dvaas/user_provided_packet_test_vector.h" + +#include +#include + +#include "absl/status/status.h" +#include "absl/status/statusor.h" +#include "absl/strings/escaping.h" +#include "absl/types/span.h" +#include "dvaas/test_vector.h" +#include "dvaas/test_vector.pb.h" +#include "gutil/proto.h" +#include "gutil/status.h" +#include "p4_pdpi/packetlib/packetlib.h" + +namespace dvaas { + +namespace { + +// Checks that the given `input_packet` is well-formed, returning it with +// omittable fields filled in if that is the case, or an error otherwise. +absl::StatusOr LegitimizePacket(Packet packet) { + RETURN_IF_ERROR( + packetlib::UpdateMissingComputedFields(*packet.mutable_parsed()) + .status()); + RETURN_IF_ERROR(packetlib::ValidatePacket(packet.parsed())); + ASSIGN_OR_RETURN(std::string raw_packet, + packetlib::RawSerializePacket(packet.parsed())); + packet.set_hex(absl::BytesToHexString(raw_packet)); + return packet; +} + +// Checks that the given `vector` is well-formed and if so adds it to +// `legitimized_test_vectors_by_id`, or returns error otherwise. +absl::Status LegitimizeTestVector( + PacketTestVector vector, + PacketTestVectorById& legitimized_test_vectors_by_id) { + if (vector.input().type() != SwitchInput::DATAPLANE) { + return gutil::UnimplementedErrorBuilder() + << "only supported input type is DATAPLANE; found " + << SwitchInput::Type_Name(vector.input().type()); + } + + // Legitimize input packet. + Packet& input_packet = *vector.mutable_input()->mutable_packet(); + ASSIGN_OR_RETURN(int tag, ExtractTestPacketTag(input_packet.parsed()), + _.SetPrepend() << "invalid input packet: "); + ASSIGN_OR_RETURN(input_packet, LegitimizePacket(input_packet), + _.SetPrepend() << "invalid input packet: "); + + // Legitimize acceptable outputs. + if (vector.acceptable_outputs().empty()) { + return gutil::InvalidArgumentErrorBuilder() + << "must specify at least 1 acceptable output, but 0 were found"; + } + for (SwitchOutput& output : *vector.mutable_acceptable_outputs()) { + // Punted output packets are not supported for now. + if (!output.packet_ins().empty()) { + return gutil::UnimplementedErrorBuilder() + << "TODO: support vectors expecting `packet_ins` " + "(punting)"; + } + // Legitimize forwarded output packets. + for (int i = 0; i < output.packets().size(); ++i) { + Packet& output_packet = *output.mutable_packets(i); + ASSIGN_OR_RETURN( + int output_tag, ExtractTestPacketTag(output_packet.parsed()), + _.SetPrepend() << "output packet #" << (i + 1) << " invalid: "); + ASSIGN_OR_RETURN(output_packet, LegitimizePacket(output_packet), + _.SetPrepend() + << "output packet #" << (i + 1) << " invalid: "); + if (output_tag != tag) { + return gutil::InvalidArgumentErrorBuilder() + << "mismatch of input packet tag vs output packet tag for " + "output packet #" + << (i + 1) << ": " << tag << " vs " << output_tag; + } + } + } + + // Add internalized vector to result. + const auto& [it, inserted] = + legitimized_test_vectors_by_id.insert({tag, vector}); + if (!inserted) { + return gutil::InvalidArgumentErrorBuilder() + << "user-provided packet test vectors must be tagged with unique " + "IDs in their payload, but found multiple test vectors with ID " + << tag << ". Dumping offending test vectors:\n<" + << gutil::PrintTextProto(it->second) << ">\n<" + << gutil::PrintTextProto(vector) << ">\n"; + } + return absl::OkStatus(); +} + +} // namespace + +absl::StatusOr LegitimizeUserProvidedTestVectors( + absl::Span user_provided_test_vectors) { + PacketTestVectorById legitimized_test_vectors_by_id; + for (const PacketTestVector& vector : user_provided_test_vectors) { + absl::Status status = + LegitimizeTestVector(vector, legitimized_test_vectors_by_id); + if (!status.ok()) { + return gutil::StatusBuilder(status.code()) + << "problem in user-provided packet test vector: " + << status.message() << "\nDumping offending test vector:\n" + << gutil::PrintTextProto(vector); + } + } + return legitimized_test_vectors_by_id; +} + +} // namespace dvaas diff --git a/dvaas/user_provided_packet_test_vector.h b/dvaas/user_provided_packet_test_vector.h new file mode 100644 index 000000000..c368f0f89 --- /dev/null +++ b/dvaas/user_provided_packet_test_vector.h @@ -0,0 +1,59 @@ +// Empowers users to specify custom packet test vectors that can be validated +// by DVaaS or Arriba. + +// Copyright 2024 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef PINS_DVAAS_USER_PROVIDED_PACKET_TEST_VECTOR_H_ +#define PINS_DVAAS_USER_PROVIDED_PACKET_TEST_VECTOR_H_ + +#include + +#include "absl/status/statusor.h" +#include "absl/types/span.h" +#include "dvaas/test_vector.h" +#include "dvaas/test_vector.pb.h" + +namespace dvaas { + +// Checks user-provided test vectors for well-formedness and prepares them for +// internal use by DVaaS/Arriba: +// * Fills in "omittable fields", see definition below. +// * Checks that each test vector is "well-formed", see definition below. +// * Returns updated, well-formed test vectors organized by ID, or returns an +// actionable, user-facing error if a test vector is not well-formed. +// +// The following `dvaas::Packet` message fields can be omitted by the user: +// * All `hex` fields. +// * All subfields of `packetlib::Packet` messages that are considered "computed +// fields" by packetlib. This includes checksum and length fields. See the +// packetlib library for the exact definition. +// +// To be "well-formed", a test vector must meet the following requirements: +// * Must specify at least 1 acceptable output. +// * Each input and output packet must: +// * Be valid according to `packetlib::ValidatePacket` after computed fields +// have been filled in. +// * Contain a test packet ID/tag according to `ExtractTestPacketTag`. +// This ID must be: +// * Shared among all packets within the test vector. +// * Unique among all test vectors. +// * The input must be of type `DATAPLANE` (other types may be supported in the +// future). +absl::StatusOr LegitimizeUserProvidedTestVectors( + absl::Span user_provided_test_vectors); + +} // namespace dvaas + +#endif // PINS_DVAAS_USER_PROVIDED_PACKET_TEST_VECTOR_H_ diff --git a/dvaas/user_provided_packet_test_vector_test.cc b/dvaas/user_provided_packet_test_vector_test.cc new file mode 100644 index 000000000..4b45c797b --- /dev/null +++ b/dvaas/user_provided_packet_test_vector_test.cc @@ -0,0 +1,452 @@ +// Empowers users to specify custom packet test vectors that can be validated +// by DVaaS or Arriba. + +// Copyright 2024 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "dvaas/user_provided_packet_test_vector.h" + +#include +#include +#include + +#include "absl/status/status.h" +#include "absl/status/statusor.h" +#include "absl/strings/string_view.h" +#include "dvaas/test_vector.h" +#include "dvaas/test_vector.pb.h" +#include "gmock/gmock.h" +#include "gtest/gtest.h" +#include "gutil/collections.h" +#include "gutil/proto.h" +#include "gutil/status_matchers.h" +#include "gutil/testing.h" +#include "p4_pdpi/packetlib/packetlib.pb.h" + +namespace dvaas { +namespace { + +using ::gutil::IsOk; +using ::gutil::PrintTextProto; +using ::testing::Not; + +struct TestCase { + std::string description; + std::vector vectors; +}; + +void RunTestCase(const TestCase& test_case) { + // Print header. + std::cout << std::string(80, '=') << "\n" + << "InternalizeUserProvidedTestVectors Test: " + << test_case.description << "\n" + << std::string(80, '=') << "\n"; + + // Print input. + std::cout << "-- Input ---------------------------------------------------\n"; + for (int i = 0; i < test_case.vectors.size(); ++i) { + std::cout << "-- Input Packet Test Vector #" << (i + 1) << " --\n" + << PrintTextProto(test_case.vectors[i]); + } + std::cout << "\n"; + + // Print output. + std::cout << "-- Output --------------------------------------------------\n"; + absl::StatusOr output = + LegitimizeUserProvidedTestVectors(test_case.vectors); + if (!output.ok()) { + // Print error without stack trace, for golden testing. + std::cout << "ERROR: " + << output.status().ToString( + absl::StatusToStringMode::kWithNoExtraData) + << "\n\n"; + return; + } + + // Print output vectors in order of input vectors. + for (int i = 0; i < test_case.vectors.size(); ++i) { + const PacketTestVector& original_vector = test_case.vectors[i]; + ASSERT_OK_AND_ASSIGN( + int tag, + ExtractTestPacketTag(original_vector.input().packet().parsed())); + ASSERT_OK_AND_ASSIGN(const PacketTestVector* internalized_vector, + gutil::FindPtrOrStatus(*output, tag)); + ASSERT_OK_AND_ASSIGN( + std::string diff, + gutil::ProtoDiff(original_vector, *internalized_vector)); + std::cout << "-- Internalized Packet Test Vector #" << (i + 1) << " --\n" + << "test packet ID extracted from payload: " << tag << "\n" + << "diff of internalized vector vs input vector:\n" + << diff << "\n"; + } + std::cout << "\n"; +} + +std::vector GetPositiveTestCases() { + std::vector test_cases; + + test_cases.emplace_back() = TestCase{ + .description = "empty list of vectors", + .vectors = {}, + }; + + test_cases.emplace_back() = TestCase{ + .description = "single Ethernet packet expected to be dropped", + .vectors = + { + gutil::ParseProtoOrDie(R"pb( + input { + type: DATAPLANE + packet { + port: "1" + parsed { + headers { + ethernet_header { + ethernet_destination: "ff:ee:dd:cc:bb:aa" + ethernet_source: "55:44:33:22:11:00" + ethertype: "0x000f" + } + } + payload: "test packet #42" + } + } + } + acceptable_outputs {} + )pb"), + }, + }; + + test_cases.emplace_back() = TestCase{ + .description = "single IPv6 packet expected to be forwarded", + .vectors = + { + gutil::ParseProtoOrDie(R"pb( + input { + type: DATAPLANE + packet { + port: "1" + parsed { + headers { + ethernet_header { + ethernet_destination: "ff:ee:dd:cc:bb:aa" + ethernet_source: "55:44:33:22:11:00" + ethertype: "0x86dd" + } + } + headers { + ipv6_header { + version: "0x6" + dscp: "0x1b" + ecn: "0x1" + flow_label: "0x12345" + next_header: "0xfd" + hop_limit: "0xf2" + ipv6_source: "2001::2" + ipv6_destination: "2001::4" + } + } + payload: "test packet #42" + } + } + } + acceptable_outputs { + packets { + port: "8" + parsed { + headers { + ethernet_header { + ethernet_destination: "1:2:3:4:5:6" + ethernet_source: "6:5:4:3:2:1" + ethertype: "0x86dd" + } + } + headers { + ipv6_header { + version: "0x6" + dscp: "0x1b" + ecn: "0x1" + flow_label: "0x12345" + next_header: "0xfd" + hop_limit: "0xf1" + ipv6_source: "2001::2" + ipv6_destination: "2001::4" + } + } + payload: "test packet #42" + } + } + } + )pb"), + }, + }; + + test_cases.emplace_back() = TestCase{ + .description = "several packets with different IDs", + .vectors = + { + gutil::ParseProtoOrDie(R"pb( + input { + type: DATAPLANE + packet { + port: "1" + parsed { + headers { + ethernet_header { + ethernet_destination: "42:42:42:42:42:42" + ethernet_source: "42:42:42:42:42:42" + ethertype: "0x000f" + } + } + payload: "test packet #42" + } + } + } + acceptable_outputs {} + )pb"), + gutil::ParseProtoOrDie(R"pb( + input { + type: DATAPLANE + packet { + port: "1" + parsed { + headers { + ethernet_header { + ethernet_destination: "5:5:5:5:5:5" + ethernet_source: "5:5:5:5:5:5" + ethertype: "0x000e" + } + } + payload: "test packet #5" + } + } + } + acceptable_outputs {} + )pb"), + }, + }; + + return test_cases; +} // namespace + +std::vector GetNegativeTestCases() { + std::vector test_cases; + + test_cases.emplace_back() = TestCase{ + .description = "input type != DATAPLANE", + .vectors = + { + gutil::ParseProtoOrDie(R"pb( + input { + type: SUBMIT_TO_INGRESS + packet { + port: "1" + parsed { + headers { + ethernet_header { + ethernet_destination: "ff:ee:dd:cc:bb:aa" + ethernet_source: "55:44:33:22:11:00" + ethertype: "0x000f" + } + } + payload: "test packet #42" + } + } + } + acceptable_outputs {} + )pb"), + }, + }; + + test_cases.emplace_back() = TestCase{ + .description = "missing expectation", + .vectors = + { + gutil::ParseProtoOrDie(R"pb( + input { + type: DATAPLANE + packet { + port: "1" + parsed { + headers { + ethernet_header { + ethernet_destination: "42:42:42:42:42:42" + ethernet_source: "42:42:42:42:42:42" + ethertype: "0x000f" + } + } + payload: "test packet #42" + } + } + } + )pb"), + }, + }; + + test_cases.emplace_back() = TestCase{ + .description = "missing test packet ID", + .vectors = + { + gutil::ParseProtoOrDie(R"pb( + input { + type: DATAPLANE + packet { + port: "1" + parsed { + headers { + ethernet_header { + ethernet_destination: "42:42:42:42:42:42" + ethernet_source: "42:42:42:42:42:42" + ethertype: "0x0002" + } + } + payload: "Hi" + } + } + } + )pb"), + }, + }; + + test_cases.emplace_back() = TestCase{ + .description = "inconsistent test packet ID in input vs output", + .vectors = + { + gutil::ParseProtoOrDie(R"pb( + input { + type: DATAPLANE + packet { + port: "1" + parsed { + headers { + ethernet_header { + ethernet_destination: "42:42:42:42:42:42" + ethernet_source: "42:42:42:42:42:42" + ethertype: "0x000f" + } + } + payload: "test packet #42" + } + } + } + acceptable_outputs { + packets { + port: "8" + parsed { + headers { + ethernet_header { + ethernet_destination: "5:5:5:5:5:5" + ethernet_source: "5:5:5:5:5:5" + ethertype: "0x000f" + } + } + payload: "test packet #24" + } + } + } + )pb"), + }, + }; + + test_cases.emplace_back() = TestCase{ + .description = "several packets with same test packet ID", + .vectors = + { + gutil::ParseProtoOrDie(R"pb( + input { + type: DATAPLANE + packet { + port: "1" + parsed { + headers { + ethernet_header { + ethernet_destination: "42:42:42:42:42:42" + ethernet_source: "42:42:42:42:42:42" + ethertype: "0x000f" + } + } + payload: "test packet #42" + } + } + } + acceptable_outputs {} + )pb"), + gutil::ParseProtoOrDie(R"pb( + input { + type: DATAPLANE + packet { + port: "1" + parsed { + headers { + ethernet_header { + ethernet_destination: "5:5:5:5:5:5" + ethernet_source: "5:5:5:5:5:5" + ethertype: "0x000f" + } + } + payload: "test packet #42" + } + } + } + acceptable_outputs {} + )pb"), + }, + }; + + test_cases.emplace_back() = TestCase{ + .description = "invalid input packet", + .vectors = + { + gutil::ParseProtoOrDie(R"pb( + input { + type: DATAPLANE + packet { + port: "1" + parsed { + headers { + ethernet_header { + ethernet_destination: "5:5:5:5:5:5" + ethernet_source: "5:5:5:5:5:5" + ethertype: "0x86dd" # IPv6. + } + } + # Missing IPv6 header. + payload: "test packet #42" + } + } + } + acceptable_outputs {} + )pb"), + }, + }; + + return test_cases; +} + +TEST(InternalizeUserProvidedTestVectorsTest, PositiveTestCases) { + for (TestCase test_case : GetPositiveTestCases()) { + EXPECT_THAT(LegitimizeUserProvidedTestVectors(test_case.vectors), IsOk()); + RunTestCase(test_case); + } +} + +TEST(InternalizeUserProvidedTestVectorsTest, NegativeTestCases) { + for (TestCase test_case : GetNegativeTestCases()) { + EXPECT_THAT(LegitimizeUserProvidedTestVectors(test_case.vectors), + Not(IsOk())); + RunTestCase(test_case); + } +} + +} // namespace +} // namespace dvaas diff --git a/dvaas/user_provided_packet_test_vector_test.expected b/dvaas/user_provided_packet_test_vector_test.expected new file mode 100644 index 000000000..47929a7d7 --- /dev/null +++ b/dvaas/user_provided_packet_test_vector_test.expected @@ -0,0 +1,533 @@ +================================================================================ +InternalizeUserProvidedTestVectors Test: empty list of vectors +================================================================================ +-- Input --------------------------------------------------- + +-- Output -------------------------------------------------- + +================================================================================ +InternalizeUserProvidedTestVectors Test: single Ethernet packet expected to be dropped +================================================================================ +-- Input --------------------------------------------------- +-- Input Packet Test Vector #1 -- +input { + type: DATAPLANE + packet { + port: "1" + parsed { + headers { + ethernet_header { + ethernet_destination: "ff:ee:dd:cc:bb:aa" + ethernet_source: "55:44:33:22:11:00" + ethertype: "0x000f" + } + } + payload: "test packet #42" + } + } +} +acceptable_outputs { +} + +-- Output -------------------------------------------------- +-- Internalized Packet Test Vector #1 -- +test packet ID extracted from payload: 42 +diff of internalized vector vs input vector: +added: input.packet.hex: "ffeeddccbbaa554433221100000f74657374207061636b657420233432" + + +================================================================================ +InternalizeUserProvidedTestVectors Test: single IPv6 packet expected to be forwarded +================================================================================ +-- Input --------------------------------------------------- +-- Input Packet Test Vector #1 -- +input { + type: DATAPLANE + packet { + port: "1" + parsed { + headers { + ethernet_header { + ethernet_destination: "ff:ee:dd:cc:bb:aa" + ethernet_source: "55:44:33:22:11:00" + ethertype: "0x86dd" + } + } + headers { + ipv6_header { + version: "0x6" + dscp: "0x1b" + ecn: "0x1" + flow_label: "0x12345" + next_header: "0xfd" + hop_limit: "0xf2" + ipv6_source: "2001::2" + ipv6_destination: "2001::4" + } + } + payload: "test packet #42" + } + } +} +acceptable_outputs { + packets { + port: "8" + parsed { + headers { + ethernet_header { + ethernet_destination: "1:2:3:4:5:6" + ethernet_source: "6:5:4:3:2:1" + ethertype: "0x86dd" + } + } + headers { + ipv6_header { + version: "0x6" + dscp: "0x1b" + ecn: "0x1" + flow_label: "0x12345" + next_header: "0xfd" + hop_limit: "0xf1" + ipv6_source: "2001::2" + ipv6_destination: "2001::4" + } + } + payload: "test packet #42" + } + } +} + +-- Output -------------------------------------------------- +-- Internalized Packet Test Vector #1 -- +test packet ID extracted from payload: 42 +diff of internalized vector vs input vector: +added: input.packet.parsed.headers[1].ipv6_header.payload_length: "0x000f" +added: input.packet.hex: "ffeeddccbbaa55443322110086dd66d12345000ffdf2200100000000000000000000000000022001000000000000000000000000000474657374207061636b657420233432" +added: acceptable_outputs[0].packets[0].parsed.headers[1].ipv6_header.payload_length: "0x000f" +added: acceptable_outputs[0].packets[0].hex: "01020304050606050403020186dd66d12345000ffdf1200100000000000000000000000000022001000000000000000000000000000474657374207061636b657420233432" + + +================================================================================ +InternalizeUserProvidedTestVectors Test: several packets with different IDs +================================================================================ +-- Input --------------------------------------------------- +-- Input Packet Test Vector #1 -- +input { + type: DATAPLANE + packet { + port: "1" + parsed { + headers { + ethernet_header { + ethernet_destination: "42:42:42:42:42:42" + ethernet_source: "42:42:42:42:42:42" + ethertype: "0x000f" + } + } + payload: "test packet #42" + } + } +} +acceptable_outputs { +} +-- Input Packet Test Vector #2 -- +input { + type: DATAPLANE + packet { + port: "1" + parsed { + headers { + ethernet_header { + ethernet_destination: "5:5:5:5:5:5" + ethernet_source: "5:5:5:5:5:5" + ethertype: "0x000e" + } + } + payload: "test packet #5" + } + } +} +acceptable_outputs { +} + +-- Output -------------------------------------------------- +-- Internalized Packet Test Vector #1 -- +test packet ID extracted from payload: 42 +diff of internalized vector vs input vector: +added: input.packet.hex: "424242424242424242424242000f74657374207061636b657420233432" + +-- Internalized Packet Test Vector #2 -- +test packet ID extracted from payload: 5 +diff of internalized vector vs input vector: +added: input.packet.hex: "050505050505050505050505000e74657374207061636b6574202335" + + +================================================================================ +InternalizeUserProvidedTestVectors Test: input type != DATAPLANE +================================================================================ +-- Input --------------------------------------------------- +-- Input Packet Test Vector #1 -- +input { + type: SUBMIT_TO_INGRESS + packet { + port: "1" + parsed { + headers { + ethernet_header { + ethernet_destination: "ff:ee:dd:cc:bb:aa" + ethernet_source: "55:44:33:22:11:00" + ethertype: "0x000f" + } + } + payload: "test packet #42" + } + } +} +acceptable_outputs { +} + +-- Output -------------------------------------------------- +ERROR: UNIMPLEMENTED: problem in user-provided packet test vector: only supported input type is DATAPLANE; found SUBMIT_TO_INGRESS +Dumping offending test vector: +input { + type: SUBMIT_TO_INGRESS + packet { + port: "1" + parsed { + headers { + ethernet_header { + ethernet_destination: "ff:ee:dd:cc:bb:aa" + ethernet_source: "55:44:33:22:11:00" + ethertype: "0x000f" + } + } + payload: "test packet #42" + } + } +} +acceptable_outputs { +} + + +================================================================================ +InternalizeUserProvidedTestVectors Test: missing expectation +================================================================================ +-- Input --------------------------------------------------- +-- Input Packet Test Vector #1 -- +input { + type: DATAPLANE + packet { + port: "1" + parsed { + headers { + ethernet_header { + ethernet_destination: "42:42:42:42:42:42" + ethernet_source: "42:42:42:42:42:42" + ethertype: "0x000f" + } + } + payload: "test packet #42" + } + } +} + +-- Output -------------------------------------------------- +ERROR: INVALID_ARGUMENT: problem in user-provided packet test vector: must specify at least 1 acceptable output, but 0 were found +Dumping offending test vector: +input { + type: DATAPLANE + packet { + port: "1" + parsed { + headers { + ethernet_header { + ethernet_destination: "42:42:42:42:42:42" + ethernet_source: "42:42:42:42:42:42" + ethertype: "0x000f" + } + } + payload: "test packet #42" + } + } +} + + +================================================================================ +InternalizeUserProvidedTestVectors Test: missing test packet ID +================================================================================ +-- Input --------------------------------------------------- +-- Input Packet Test Vector #1 -- +input { + type: DATAPLANE + packet { + port: "1" + parsed { + headers { + ethernet_header { + ethernet_destination: "42:42:42:42:42:42" + ethernet_source: "42:42:42:42:42:42" + ethertype: "0x0002" + } + } + payload: "Hi" + } + } +} + +-- Output -------------------------------------------------- +ERROR: INVALID_ARGUMENT: problem in user-provided packet test vector: invalid input packet: test packets must contain a tag of the form 'test packet #([0-9]+)' in their payload, but the given packet with payload 'Hi' does not: +headers { + ethernet_header { + ethernet_destination: "42:42:42:42:42:42" + ethernet_source: "42:42:42:42:42:42" + ethertype: "0x0002" + } +} +payload: "Hi" + +Dumping offending test vector: +input { + type: DATAPLANE + packet { + port: "1" + parsed { + headers { + ethernet_header { + ethernet_destination: "42:42:42:42:42:42" + ethernet_source: "42:42:42:42:42:42" + ethertype: "0x0002" + } + } + payload: "Hi" + } + } +} + + +================================================================================ +InternalizeUserProvidedTestVectors Test: inconsistent test packet ID in input vs output +================================================================================ +-- Input --------------------------------------------------- +-- Input Packet Test Vector #1 -- +input { + type: DATAPLANE + packet { + port: "1" + parsed { + headers { + ethernet_header { + ethernet_destination: "42:42:42:42:42:42" + ethernet_source: "42:42:42:42:42:42" + ethertype: "0x000f" + } + } + payload: "test packet #42" + } + } +} +acceptable_outputs { + packets { + port: "8" + parsed { + headers { + ethernet_header { + ethernet_destination: "5:5:5:5:5:5" + ethernet_source: "5:5:5:5:5:5" + ethertype: "0x000f" + } + } + payload: "test packet #24" + } + } +} + +-- Output -------------------------------------------------- +ERROR: INVALID_ARGUMENT: problem in user-provided packet test vector: mismatch of input packet tag vs output packet tag for output packet #1: 42 vs 24 +Dumping offending test vector: +input { + type: DATAPLANE + packet { + port: "1" + parsed { + headers { + ethernet_header { + ethernet_destination: "42:42:42:42:42:42" + ethernet_source: "42:42:42:42:42:42" + ethertype: "0x000f" + } + } + payload: "test packet #42" + } + } +} +acceptable_outputs { + packets { + port: "8" + parsed { + headers { + ethernet_header { + ethernet_destination: "5:5:5:5:5:5" + ethernet_source: "5:5:5:5:5:5" + ethertype: "0x000f" + } + } + payload: "test packet #24" + } + } +} + + +================================================================================ +InternalizeUserProvidedTestVectors Test: several packets with same test packet ID +================================================================================ +-- Input --------------------------------------------------- +-- Input Packet Test Vector #1 -- +input { + type: DATAPLANE + packet { + port: "1" + parsed { + headers { + ethernet_header { + ethernet_destination: "42:42:42:42:42:42" + ethernet_source: "42:42:42:42:42:42" + ethertype: "0x000f" + } + } + payload: "test packet #42" + } + } +} +acceptable_outputs { +} +-- Input Packet Test Vector #2 -- +input { + type: DATAPLANE + packet { + port: "1" + parsed { + headers { + ethernet_header { + ethernet_destination: "5:5:5:5:5:5" + ethernet_source: "5:5:5:5:5:5" + ethertype: "0x000f" + } + } + payload: "test packet #42" + } + } +} +acceptable_outputs { +} + +-- Output -------------------------------------------------- +ERROR: INVALID_ARGUMENT: problem in user-provided packet test vector: user-provided packet test vectors must be tagged with unique IDs in their payload, but found multiple test vectors with ID 42. Dumping offending test vectors: + + + +Dumping offending test vector: +input { + type: DATAPLANE + packet { + port: "1" + parsed { + headers { + ethernet_header { + ethernet_destination: "5:5:5:5:5:5" + ethernet_source: "5:5:5:5:5:5" + ethertype: "0x000f" + } + } + payload: "test packet #42" + } + } +} +acceptable_outputs { +} + + +================================================================================ +InternalizeUserProvidedTestVectors Test: invalid input packet +================================================================================ +-- Input --------------------------------------------------- +-- Input Packet Test Vector #1 -- +input { + type: DATAPLANE + packet { + port: "1" + parsed { + headers { + ethernet_header { + ethernet_destination: "5:5:5:5:5:5" + ethernet_source: "5:5:5:5:5:5" + ethertype: "0x86dd" + } + } + payload: "test packet #42" + } + } +} +acceptable_outputs { +} + +-- Output -------------------------------------------------- +ERROR: INVALID_ARGUMENT: problem in user-provided packet test vector: invalid input packet: Packet invalid for the following reasons: +- in EthernetHeader headers[0]: expected at least 46 bytes of Ethernet payload, but got only 15 +- headers[1]: header missing - expected Ipv6Header +Dumping offending test vector: +input { + type: DATAPLANE + packet { + port: "1" + parsed { + headers { + ethernet_header { + ethernet_destination: "5:5:5:5:5:5" + ethernet_source: "5:5:5:5:5:5" + ethertype: "0x86dd" + } + } + payload: "test packet #42" + } + } +} +acceptable_outputs { +} diff --git a/tests/gnoi/BUILD.bazel b/tests/gnoi/BUILD.bazel index d86c11c48..fa89d2b27 100644 --- a/tests/gnoi/BUILD.bazel +++ b/tests/gnoi/BUILD.bazel @@ -39,7 +39,6 @@ cc_library( "@com_google_absl//absl/container:flat_hash_set", "@com_google_absl//absl/flags:flag", "@com_google_absl//absl/random", - "@com_github_grpc_grpc//:grpc++", "@com_google_absl//absl/strings", "@com_google_absl//absl/time", "@com_google_googletest//:gtest",