• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2023 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "base/test/test_proto_loader.h"
6 
7 #include "base/files/file_util.h"
8 #include "base/notreached.h"
9 #include "base/path_service.h"
10 #include "base/strings/string_split.h"
11 #include "base/strings/string_util.h"
12 #include "third_party/protobuf/src/google/protobuf/message.h"
13 #include "third_party/protobuf/src/google/protobuf/text_format.h"
14 
15 namespace base {
16 
TestProtoLoader(const base::FilePath & descriptor_path,base::StringPiece type_name)17 TestProtoLoader::TestProtoLoader(const base::FilePath& descriptor_path,
18                                  base::StringPiece type_name) {
19   // Load the descriptors and find the one for |type_name|.
20   std::string package, name;
21   std::vector<std::string> type_name_parts = base::SplitString(
22       type_name, ".", base::KEEP_WHITESPACE, base::SPLIT_WANT_ALL);
23   DCHECK_GE(type_name_parts.size(), 2U) << "|type_name| should include package";
24 
25   prototype_ = GetPrototype(
26       descriptor_path, /*package =*/
27       base::JoinString(
28           base::make_span(type_name_parts.begin(), type_name_parts.size() - 1),
29           "."),
30       /* name = */ type_name_parts.back());
31   DCHECK_NE(nullptr, prototype_);
32 }
33 
34 TestProtoLoader::~TestProtoLoader() = default;
35 
GetPrototype(base::FilePath descriptor_path,base::StringPiece package,base::StringPiece name)36 const google::protobuf::Message* TestProtoLoader::GetPrototype(
37     base::FilePath descriptor_path,
38     base::StringPiece package,
39     base::StringPiece name) {
40   std::string file_contents;
41 
42   if (!base::ReadFileToString(descriptor_path, &file_contents)) {
43     NOTREACHED() << "Couldn't load contents of " << descriptor_path;
44     return nullptr;
45   }
46 
47   if (!descriptor_set_.ParseFromString(file_contents)) {
48     NOTREACHED() << "Couldn't parse descriptor from " << descriptor_path;
49     return nullptr;
50   }
51 
52   for (int file_i = 0; file_i < descriptor_set_.file_size(); ++file_i) {
53     const google::protobuf::FileDescriptorProto& file =
54         descriptor_set_.file(file_i);
55     if (file.package() != package) {
56       continue;
57     }
58     const google::protobuf::FileDescriptor* descriptor =
59         descriptor_pool_.BuildFile(file);
60     for (int message_type_i = 0;
61          message_type_i < descriptor->message_type_count(); ++message_type_i) {
62       const google::protobuf::Descriptor* message_type =
63           descriptor->message_type(message_type_i);
64       if (message_type->name() != name) {
65         continue;
66       }
67       return dynamic_message_factory_.GetPrototype(message_type);
68     }
69   }
70   NOTREACHED() << "Couldn't find " << package << "." << name << "in "
71                << descriptor_path;
72   return nullptr;
73 }
74 
ParseFromText(const std::string & proto_text,std::string & serialized_message)75 void TestProtoLoader::ParseFromText(const std::string& proto_text,
76                                     std::string& serialized_message) {
77   // Parse the text using the descriptor-generated message and send it to
78   // |destination|.
79   std::unique_ptr<google::protobuf::Message> message(prototype_->New());
80   bool success =
81       google::protobuf::TextFormat::ParseFromString(proto_text, message.get());
82   success |= message->SerializeToString(&serialized_message);
83   DCHECK(success);
84 }
85 
PrintToText(const std::string & serialized_message,std::string & proto_text)86 void TestProtoLoader::PrintToText(const std::string& serialized_message,
87                                   std::string& proto_text) {
88   // Parse the text using the descriptor-generated message and send it to
89   // |destination|.
90   std::unique_ptr<google::protobuf::Message> message(prototype_->New());
91   bool success = message->ParseFromString(serialized_message);
92   success |= google::protobuf::TextFormat::PrintToString(*message, &proto_text);
93   DCHECK(success);
94 }
95 
96 }  // namespace base
97