// Copyright 2023 The Chromium Authors // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "base/test/test_proto_loader.h" #include "base/check.h" #include "base/files/file_util.h" #include "base/memory/ptr_util.h" #include "base/memory/raw_ptr.h" #include "base/path_service.h" #include "base/strings/string_split.h" #include "base/strings/string_util.h" #include "third_party/protobuf/src/google/protobuf/descriptor.h" #include "third_party/protobuf/src/google/protobuf/descriptor.pb.h" #include "third_party/protobuf/src/google/protobuf/descriptor_database.h" #include "third_party/protobuf/src/google/protobuf/dynamic_message.h" #include "third_party/protobuf/src/google/protobuf/message.h" #include "third_party/protobuf/src/google/protobuf/text_format.h" namespace base { class TestProtoSetLoader::State { public: explicit State(std::string_view descriptor_binary_proto) { CHECK(descriptor_set_.ParseFromArray(descriptor_binary_proto.data(), descriptor_binary_proto.size())) << "Couldn't parse descriptor"; for (auto& file : descriptor_set_.file()) { descriptor_database_.Add(file); } descriptor_pool_ = std::make_unique( &descriptor_database_); } std::unique_ptr NewMessage( std::string_view full_type_name) { const google::protobuf::Descriptor* message_type = descriptor_pool_->FindMessageTypeByName(std::string(full_type_name)); CHECK(message_type) << "Couldn't find proto message type " << full_type_name; return base::WrapUnique( dynamic_message_factory_.GetPrototype(message_type)->New()); } private: google::protobuf::FileDescriptorSet descriptor_set_; google::protobuf::SimpleDescriptorDatabase descriptor_database_; std::unique_ptr descriptor_pool_; google::protobuf::DynamicMessageFactory dynamic_message_factory_; }; TestProtoSetLoader::TestProtoSetLoader(std::string_view descriptor_binary_proto) : state_(std::make_unique(descriptor_binary_proto)) {} TestProtoSetLoader::TestProtoSetLoader(const base::FilePath& descriptor_path) { std::string file_contents; CHECK(base::ReadFileToString(descriptor_path, &file_contents)) << "Couldn't load contents of " << descriptor_path; state_ = std::make_unique(file_contents); } TestProtoSetLoader::~TestProtoSetLoader() = default; std::string TestProtoSetLoader::ParseFromText( const std::string_view type_name, const std::string& proto_text) const { // Create a message of the given type, parse, and return. std::unique_ptr message = state_->NewMessage(type_name); CHECK( google::protobuf::TextFormat::ParseFromString(proto_text, message.get())); return message->SerializeAsString(); } std::string TestProtoSetLoader::PrintToText( const std::string_view type_name, const std::string& serialized_message) const { // Create a message of the given type, read the serialized message, and // print to text format. std::unique_ptr message = state_->NewMessage(type_name); CHECK(message->ParseFromString(serialized_message)); std::string proto_text; CHECK(google::protobuf::TextFormat::PrintToString(*message, &proto_text)); return proto_text; } TestProtoLoader::TestProtoLoader(std::string_view descriptor_binary_proto, std::string_view type_name) : set_loader_(descriptor_binary_proto), type_name_(type_name) {} TestProtoLoader::TestProtoLoader(const base::FilePath& descriptor_path, std::string_view type_name) : set_loader_(descriptor_path), type_name_(type_name) {} TestProtoLoader::~TestProtoLoader() = default; void TestProtoLoader::ParseFromText(const std::string& proto_text, std::string& serialized_message) const { serialized_message = set_loader_.ParseFromText(type_name_, proto_text); } void TestProtoLoader::PrintToText(const std::string& serialized_message, std::string& proto_text) const { proto_text = set_loader_.PrintToText(type_name_, serialized_message); } } // namespace base