Skip to content

Commit

Permalink
[NetKAT] Finish (initial, inefficient) symbolic packet implementation.
Browse files Browse the repository at this point in the history
PiperOrigin-RevId: 700572230
  • Loading branch information
smolkaj authored and copybara-github committed Nov 28, 2024
1 parent c9e97ef commit ca4c503
Show file tree
Hide file tree
Showing 24 changed files with 3,163 additions and 109 deletions.
149 changes: 149 additions & 0 deletions gutil/BUILD.bazel
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@


package(
default_applicable_licenses = ["//:license"],
default_visibility = ["//visibility:private"],
)

cc_library(
name = "testing",
testonly = True,
srcs = ["testing.cc"],
hdrs = ["testing.h"],
visibility = ["//:__subpackages__"],
deps = [
":proto",
":status",
"@com_google_absl//absl/log",
"@com_google_absl//absl/log:check",
"@com_google_absl//absl/status",
"@com_google_absl//absl/strings",
],
)

cc_test(
name = "testing_test",
srcs = ["testing_test.cc"],
deps = [
":testing",
"@com_google_absl//absl/strings",
"@com_google_googletest//:gtest_main",
],
)

cc_library(
name = "status",
srcs = ["status.cc"],
hdrs = ["status.h"],
visibility = ["//:__subpackages__"],
deps = [
"@com_google_absl//absl/base:core_headers",
"@com_google_absl//absl/status",
"@com_google_absl//absl/status:statusor",
"@com_google_absl//absl/strings",
"@com_google_absl//absl/strings:cord",
],
)

cc_library(
name = "status_matchers",
testonly = True,
hdrs = ["status_matchers.h"],
visibility = ["//:__subpackages__"],
deps = [
":status",
"@com_google_absl//absl/status",
"@com_google_absl//absl/status:statusor",
"@com_google_absl//absl/strings",
"@com_google_absl//absl/strings:str_format",
"@com_google_googletest//:gtest",
],
)

cc_test(
name = "status_matchers_test",
srcs = ["status_matchers_test.cc"],
deps = [
":status",
":status_matchers",
"@com_google_absl//absl/memory",
"@com_google_absl//absl/status",
"@com_google_absl//absl/status:statusor",
"@com_google_googletest//:gtest_main",
],
)

cc_library(
name = "proto_string_error_collector",
hdrs = ["proto_string_error_collector.h"],
deps = [
"@com_google_absl//absl/strings",
"@com_google_protobuf//:protobuf",
],
)

cc_library(
name = "proto",
srcs = ["proto.cc"],
hdrs = ["proto.h"],
visibility = ["//:__subpackages__"],
deps = [
":proto_string_error_collector",
":status",
"@com_google_absl//absl/status",
"@com_google_absl//absl/status:statusor",
"@com_google_absl//absl/strings",
"@com_google_protobuf//:protobuf",
],
)

cc_test(
name = "proto_test",
srcs = ["proto_test.cc"],
deps = [
":proto",
":proto_matchers",
":proto_test_cc_proto",
":status",
":status_matchers",
"@com_google_absl//absl/status",
"@com_google_absl//absl/status:statusor",
"@com_google_absl//absl/strings",
"@com_google_googletest//:gtest_main",
],
)

proto_library(
name = "proto_test_proto",
srcs = ["proto_test.proto"],
)

cc_proto_library(
name = "proto_test_cc_proto",
deps = [":proto_test_proto"],
)

cc_library(
name = "proto_matchers",
testonly = True,
hdrs = ["proto_matchers.h"],
visibility = ["//:__subpackages__"],
deps = [
":proto",
"@com_google_absl//absl/log",
"@com_google_absl//absl/strings",
"@com_google_googletest//:gtest",
"@com_google_protobuf//:protobuf",
],
)

cc_test(
name = "proto_matchers_test",
srcs = ["proto_matchers_test.cc"],
deps = [
":proto_matchers",
":proto_test_cc_proto",
":testing",
"@com_google_googletest//:gtest_main",
],
)
7 changes: 7 additions & 0 deletions gutil/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# Gutil

Code in this folder has been copied/modified from
https://github.com/google/gutil.

THIS IS A TEMPORARY WORKAROUND until we can depend on the gutil repository
directly, which is tracked in b/380957915.
198 changes: 198 additions & 0 deletions gutil/proto.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,198 @@
// Copyright 2020 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
//
// http://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 "gutil/proto.h"

#include <fcntl.h>

#include <string>

#include "absl/status/status.h"
#include "absl/status/statusor.h"
#include "absl/strings/string_view.h"
#include "google/protobuf/descriptor.h"
#include "google/protobuf/io/zero_copy_stream_impl.h"
#include "google/protobuf/message.h"
#include "google/protobuf/text_format.h"
#include "google/protobuf/util/json_util.h"
#include "gutil/proto_string_error_collector.h"
#include "gutil/status.h"

namespace netkat {

bool IsEmptyProto(const google::protobuf::Message &message) {
return message.ByteSizeLong() == 0;
}

absl::Status ReadProtoFromFile(absl::string_view filename,
google::protobuf::Message *message) {
// Verifies that the version of the library that we linked against is
// compatible with the version of the headers we compiled against.
GOOGLE_PROTOBUF_VERIFY_VERSION;

int fd = open(std::string(filename).c_str(), O_RDONLY);
if (fd < 0) {
return InvalidArgumentErrorBuilder()
<< "Error opening the file " << filename;
}

google::protobuf::io::FileInputStream file_stream(fd);
file_stream.SetCloseOnDelete(true);

if (!google::protobuf::TextFormat::Parse(&file_stream, message)) {
return InvalidArgumentErrorBuilder() << "Failed to parse file " << filename;
}

return absl::OkStatus();
}

absl::Status ReadProtoFromString(absl::string_view proto_string,
google::protobuf::Message *message) {
// Verifies that the version of the library that we linked against is
// compatible with the version of the headers we compiled against.
GOOGLE_PROTOBUF_VERIFY_VERSION;

google::protobuf::TextFormat::Parser parser;
std::string all_errors;
StringErrorCollector collector(&all_errors);
parser.RecordErrorsTo(&collector);

if (!parser.ParseFromString(std::string(proto_string), message)) {
return InvalidArgumentErrorBuilder()
<< "string <" << proto_string << "> did not parse as a "
<< message->GetTypeName() << ":\n"
<< all_errors;
}

return absl::OkStatus();
}

absl::Status SaveProtoToFile(absl::string_view filename,
const google::protobuf::Message &message) {
// Verifies that the version of the library that we linked against is
// compatible with the version of the headers we compiled against.
GOOGLE_PROTOBUF_VERIFY_VERSION;
int fd =
open(std::string(filename).c_str(), O_WRONLY | O_CREAT | O_TRUNC, 0644);
if (fd < 0) {
return InvalidArgumentErrorBuilder()
<< "Error opening the file " << filename;
}

google::protobuf::io::FileOutputStream file_stream(fd);
file_stream.SetCloseOnDelete(true);

if (!google::protobuf::TextFormat::Print(message, &file_stream)) {
return InvalidArgumentErrorBuilder()
<< "Failed to print proto to file " << filename;
}

file_stream.Flush();
return absl::OkStatus();
}

absl::StatusOr<std::string> ProtoDiff(
const google::protobuf::Message &message1,
const google::protobuf::Message &message2,
google::protobuf::util::MessageDifferencer &differ) {
if (message1.GetDescriptor() != message2.GetDescriptor()) {
return netkat::InvalidArgumentErrorBuilder()
<< "cannot compute diff for messages of incompatible descriptors `"
<< message1.GetDescriptor()->full_name() << "' vs '"
<< message2.GetDescriptor()->full_name() << "'";
}

std::string diff;
differ.ReportDifferencesToString(&diff);
ProtoEqual(message1, message2, differ);
return diff;
}

// Calls `ProtoDiff` with default `MessageDifferencer`.
absl::StatusOr<std::string> ProtoDiff(
const google::protobuf::Message &message1,
const google::protobuf::Message &message2) {
google::protobuf::util::MessageDifferencer differ =
google::protobuf::util::MessageDifferencer();
return ProtoDiff(message1, message2, differ);
}

bool ProtoEqual(const google::protobuf::Message &message1,
const google::protobuf::Message &message2,
google::protobuf::util::MessageDifferencer &differ) {
if (message1.GetDescriptor() != message2.GetDescriptor()) {
return false;
}

return differ.Compare(message1, message2);
}

// Calls `ProtoEqual` with default `MessageDifferencer`.
bool ProtoEqual(const google::protobuf::Message &message1,
const google::protobuf::Message &message2) {
google::protobuf::util::MessageDifferencer differ =
google::protobuf::util::MessageDifferencer();
return ProtoEqual(message1, message2, differ);
}

absl::StatusOr<std::string> GetOneOfFieldName(
const google::protobuf::Message &message, const std::string &oneof_name) {
const auto *oneof_descriptor =
message.GetDescriptor()->FindOneofByName(oneof_name);
const auto *field = message.GetReflection()->GetOneofFieldDescriptor(
message, oneof_descriptor);
if (!field) {
return netkat::NotFoundErrorBuilder()
<< "Oneof field \"" << oneof_name << "\" is not set";
}
return std::string(field->name());
}

std::string PrintTextProto(const google::protobuf::Message &message) {
std::string message_text;

google::protobuf::TextFormat::Printer printer;
printer.SetExpandAny(true);

printer.PrintToString(message, &message_text);

return message_text;
}

// Print proto in TextFormat with single line mode enabled.
std::string PrintShortTextProto(const google::protobuf::Message &message) {
std::string message_short_text;

google::protobuf::TextFormat::Printer printer;
printer.SetSingleLineMode(true);
printer.SetExpandAny(true);

printer.PrintToString(message, &message_short_text);
// Single line mode currently might have an extra space at the end.
if (!message_short_text.empty() && message_short_text.back() == ' ') {
message_short_text.pop_back();
}

return message_short_text;
}

absl::StatusOr<std::string> SerializeProtoAsJson(
const google::protobuf::Message &proto) {
std::string json;
RETURN_IF_ERROR(netkat::ToAbslStatus(
google::protobuf::util::MessageToJsonString(proto, &json)));
return json;
}

} // namespace netkat
Loading

0 comments on commit ca4c503

Please sign in to comment.