mock_code_generator.cc
Go to the documentation of this file.
1 // Protocol Buffers - Google's data interchange format
2 // Copyright 2008 Google Inc. All rights reserved.
3 // https://developers.google.com/protocol-buffers/
4 //
5 // Redistribution and use in source and binary forms, with or without
6 // modification, are permitted provided that the following conditions are
7 // met:
8 //
9 // * Redistributions of source code must retain the above copyright
10 // notice, this list of conditions and the following disclaimer.
11 // * Redistributions in binary form must reproduce the above
12 // copyright notice, this list of conditions and the following disclaimer
13 // in the documentation and/or other materials provided with the
14 // distribution.
15 // * Neither the name of Google Inc. nor the names of its
16 // contributors may be used to endorse or promote products derived from
17 // this software without specific prior written permission.
18 //
19 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 
31 // Author: kenton@google.com (Kenton Varda)
32 
34 
35 #include <stdlib.h>
36 #include <iostream>
37 #include <memory>
38 #include <vector>
40 
41 
42 
55 #include <gtest/gtest.h>
56 
57 #ifdef major
58 #undef major
59 #endif
60 #ifdef minor
61 #undef minor
62 #endif
63 
64 namespace google {
65 namespace protobuf {
66 namespace compiler {
67 
68 // Returns the list of the names of files in all_files in the form of a
69 // comma-separated string.
71  const std::vector<const FileDescriptor*>& all_files) {
72  std::vector<std::string> names;
73  for (size_t i = 0; i < all_files.size(); i++) {
74  names.push_back(all_files[i]->name());
75  }
76  return Join(names, ",");
77 }
78 
79 static const char* kFirstInsertionPointName = "first_mock_insertion_point";
80 static const char* kSecondInsertionPointName = "second_mock_insertion_point";
81 static const char* kFirstInsertionPoint =
82  "# @@protoc_insertion_point(first_mock_insertion_point) is here\n";
83 static const char* kSecondInsertionPoint =
84  " # @@protoc_insertion_point(second_mock_insertion_point) is here\n";
85 
87 
89 
91  const std::string& name, const std::string& parameter,
92  const std::string& insertions, const std::string& file,
93  const std::string& first_message_name,
94  const std::string& first_parsed_file_name,
95  const std::string& output_directory) {
96  std::string content;
98  File::GetContents(output_directory + "/" + GetOutputFileName(name, file),
99  &content, true));
100 
101  std::vector<std::string> lines =
102  Split(content, "\n", true);
103 
104  while (!lines.empty() && lines.back().empty()) {
105  lines.pop_back();
106  }
107  for (size_t i = 0; i < lines.size(); i++) {
108  lines[i] += "\n";
109  }
110 
111  std::vector<std::string> insertion_list;
112  if (!insertions.empty()) {
113  SplitStringUsing(insertions, ",", &insertion_list);
114  }
115 
116  EXPECT_EQ(lines.size(), 3 + insertion_list.size() * 2);
117  EXPECT_EQ(GetOutputFileContent(name, parameter, file, first_parsed_file_name,
118  first_message_name),
119  lines[0]);
120 
121  EXPECT_EQ(kFirstInsertionPoint, lines[1 + insertion_list.size()]);
122  EXPECT_EQ(kSecondInsertionPoint, lines[2 + insertion_list.size() * 2]);
123 
124  for (size_t i = 0; i < insertion_list.size(); i++) {
125  EXPECT_EQ(GetOutputFileContent(insertion_list[i], "first_insert", file,
126  file, first_message_name),
127  lines[1 + i]);
128  // Second insertion point is indented, so the inserted text should
129  // automatically be indented too.
130  EXPECT_EQ(" " + GetOutputFileContent(insertion_list[i], "second_insert",
131  file, file, first_message_name),
132  lines[2 + insertion_list.size() + i]);
133  }
134 }
135 
136 namespace {
137 void CheckSingleAnnotation(const std::string& expected_file,
138  const std::string& expected_text,
139  const std::string& file_content,
140  const GeneratedCodeInfo::Annotation& annotation) {
141  EXPECT_EQ(expected_file, annotation.source_file());
142  ASSERT_GE(file_content.size(), annotation.begin());
143  ASSERT_GE(file_content.size(), annotation.end());
144  ASSERT_LE(annotation.begin(), annotation.end());
145  EXPECT_EQ(expected_text.size(), annotation.end() - annotation.begin());
146  EXPECT_EQ(expected_text,
147  file_content.substr(annotation.begin(), expected_text.size()));
148 }
149 } // anonymous namespace
150 
152  const string& name, const std::string& file,
153  const std::string& output_directory) {
154  std::string file_content;
156  File::GetContents(output_directory + "/" + GetOutputFileName(name, file),
157  &file_content, true));
158  std::string meta_content;
160  output_directory + "/" + GetOutputFileName(name, file) + ".meta",
161  &meta_content, true));
162  GeneratedCodeInfo annotations;
163  GOOGLE_CHECK(TextFormat::ParseFromString(meta_content, &annotations));
164  ASSERT_EQ(3, annotations.annotation_size());
165  CheckSingleAnnotation("first_annotation", "first", file_content,
166  annotations.annotation(0));
167  CheckSingleAnnotation("second_annotation", "second", file_content,
168  annotations.annotation(1));
169  CheckSingleAnnotation("third_annotation", "third", file_content,
170  annotations.annotation(2));
171 }
172 
174  const std::string& parameter,
175  GeneratorContext* context,
176  std::string* error) const {
177  bool annotate = false;
178  for (int i = 0; i < file->message_type_count(); i++) {
179  if (HasPrefixString(file->message_type(i)->name(), "MockCodeGenerator_")) {
181  file->message_type(i)->name(), "MockCodeGenerator_");
182  if (command == "Error") {
183  *error = "Saw message type MockCodeGenerator_Error.";
184  return false;
185  } else if (command == "Exit") {
186  std::cerr << "Saw message type MockCodeGenerator_Exit." << std::endl;
187  exit(123);
188  } else if (command == "Abort") {
189  std::cerr << "Saw message type MockCodeGenerator_Abort." << std::endl;
190  abort();
191  } else if (command == "HasSourceCodeInfo") {
192  FileDescriptorProto file_descriptor_proto;
193  file->CopySourceCodeInfoTo(&file_descriptor_proto);
194  bool has_source_code_info =
195  file_descriptor_proto.has_source_code_info() &&
196  file_descriptor_proto.source_code_info().location_size() > 0;
197  std::cerr << "Saw message type MockCodeGenerator_HasSourceCodeInfo: "
198  << has_source_code_info << "." << std::endl;
199  abort();
200  } else if (command == "HasJsonName") {
201  FieldDescriptorProto field_descriptor_proto;
202  file->message_type(i)->field(0)->CopyTo(&field_descriptor_proto);
203  std::cerr << "Saw json_name: " << field_descriptor_proto.has_json_name()
204  << std::endl;
205  abort();
206  } else if (command == "Annotate") {
207  annotate = true;
208  } else if (command == "ShowVersionNumber") {
209  Version compiler_version;
210  context->GetCompilerVersion(&compiler_version);
211  std::cerr << "Saw compiler_version: "
212  << compiler_version.major() * 1000000 +
213  compiler_version.minor() * 1000 +
214  compiler_version.patch()
215  << " " << compiler_version.suffix() << std::endl;
216  abort();
217  } else {
218  GOOGLE_LOG(FATAL) << "Unknown MockCodeGenerator command: " << command;
219  }
220  }
221  }
222 
223  if (HasPrefixString(parameter, "insert=")) {
224  std::vector<std::string> insert_into;
225  SplitStringUsing(StripPrefixString(parameter, "insert="), ",",
226  &insert_into);
227 
228  for (size_t i = 0; i < insert_into.size(); i++) {
229  {
230  std::unique_ptr<io::ZeroCopyOutputStream> output(context->OpenForInsert(
231  GetOutputFileName(insert_into[i], file), kFirstInsertionPointName));
232  io::Printer printer(output.get(), '$');
233  printer.PrintRaw(
234  GetOutputFileContent(name_, "first_insert", file, context));
235  if (printer.failed()) {
236  *error = "MockCodeGenerator detected write error.";
237  return false;
238  }
239  }
240 
241  {
242  std::unique_ptr<io::ZeroCopyOutputStream> output(
243  context->OpenForInsert(GetOutputFileName(insert_into[i], file),
245  io::Printer printer(output.get(), '$');
246  printer.PrintRaw(
247  GetOutputFileContent(name_, "second_insert", file, context));
248  if (printer.failed()) {
249  *error = "MockCodeGenerator detected write error.";
250  return false;
251  }
252  }
253  }
254  } else {
255  std::unique_ptr<io::ZeroCopyOutputStream> output(
256  context->Open(GetOutputFileName(name_, file)));
257 
258  GeneratedCodeInfo annotations;
260  &annotations);
261  io::Printer printer(output.get(), '$',
262  annotate ? &annotation_collector : NULL);
263  printer.PrintRaw(GetOutputFileContent(name_, parameter, file, context));
264  std::string annotate_suffix = "_annotation";
265  if (annotate) {
266  printer.Print("$p$", "p", "first");
267  printer.Annotate("p", "first" + annotate_suffix);
268  }
270  if (annotate) {
271  printer.Print("$p$", "p", "second");
272  printer.Annotate("p", "second" + annotate_suffix);
273  }
275  if (annotate) {
276  printer.Print("$p$", "p", "third");
277  printer.Annotate("p", "third" + annotate_suffix);
278  }
279 
280  if (printer.failed()) {
281  *error = "MockCodeGenerator detected write error.";
282  return false;
283  }
284  if (annotate) {
285  std::unique_ptr<io::ZeroCopyOutputStream> meta_output(
286  context->Open(GetOutputFileName(name_, file) + ".meta"));
287  if (!TextFormat::Print(annotations, meta_output.get())) {
288  *error = "MockCodeGenerator couldn't write .meta";
289  return false;
290  }
291  }
292  }
293 
294  return true;
295 }
296 
298  const std::string& generator_name, const FileDescriptor* file) {
299  return GetOutputFileName(generator_name, file->name());
300 }
301 
303  const std::string& generator_name, const std::string& file) {
304  return file + ".MockCodeGenerator." + generator_name;
305 }
306 
308  const std::string& generator_name, const std::string& parameter,
309  const FileDescriptor* file, GeneratorContext* context) {
310  std::vector<const FileDescriptor*> all_files;
311  context->ListParsedFiles(&all_files);
312  return GetOutputFileContent(
313  generator_name, parameter, file->name(), CommaSeparatedList(all_files),
314  file->message_type_count() > 0 ? file->message_type(0)->name()
315  : "(none)");
316 }
317 
319  const std::string& generator_name, const std::string& parameter,
320  const std::string& file, const std::string& parsed_file_list,
321  const std::string& first_message_name) {
322  return strings::Substitute("$0: $1, $2, $3, $4\n", generator_name, parameter,
323  file, first_message_name, parsed_file_list);
324 }
325 
326 } // namespace compiler
327 } // namespace protobuf
328 } // namespace google
zero_copy_stream.h
google::protobuf::io::Printer::Print
void Print(const std::map< std::string, std::string > &variables, const char *text)
Definition: printer.cc:112
name
GLuint const GLchar * name
Definition: glcorearb.h:3055
google::protobuf::TextFormat::Print
static bool Print(const Message &message, io::ZeroCopyOutputStream *output)
Definition: text_format.cc:2388
google::protobuf::compiler::kSecondInsertionPointName
static const char * kSecondInsertionPointName
Definition: mock_code_generator.cc:80
google::protobuf::compiler::GeneratorContext::GetCompilerVersion
virtual void GetCompilerVersion(Version *version) const
Definition: code_generator.cc:93
ASSERT_LE
#define ASSERT_LE(val1, val2)
Definition: gtest.h:2090
NULL
NULL
Definition: test_security_zap.cpp:405
google::protobuf::compiler::CommaSeparatedList
std::string CommaSeparatedList(const std::vector< const FileDescriptor * > &all_files)
Definition: mock_code_generator.cc:70
FATAL
const int FATAL
Definition: log_severity.h:60
gtest.h
GeneratedCodeInfo_Annotation::begin
::PROTOBUF_NAMESPACE_ID::int32 begin() const
Definition: descriptor.pb.h:11852
FieldDescriptorProto
Definition: descriptor.pb.h:1678
google::protobuf::compiler::GeneratorContext::Open
virtual io::ZeroCopyOutputStream * Open(const std::string &filename)=0
command
ROSLIB_DECL std::string command(const std::string &cmd)
EXPECT_EQ
#define EXPECT_EQ(val1, val2)
Definition: glog/src/googletest.h:155
google::protobuf::io::Printer::PrintRaw
void PrintRaw(const std::string &data)
Definition: printer.cc:196
string
GLsizei const GLchar *const * string
Definition: glcorearb.h:3083
google::protobuf::compiler::GeneratorContext::ListParsedFiles
virtual void ListParsedFiles(std::vector< const FileDescriptor * > *output)
Definition: code_generator.cc:88
GeneratedCodeInfo_Annotation::source_file
const std::string & source_file() const
Definition: descriptor.pb.h:11772
GeneratedCodeInfo::annotation_size
int annotation_size() const
Definition: descriptor.pb.h:11885
error
Definition: cJSON.c:88
google::protobuf::FieldDescriptor::CopyTo
void CopyTo(FieldDescriptorProto *proto) const
Definition: src/google/protobuf/descriptor.cc:2120
mock_code_generator.h
ASSERT_EQ
#define ASSERT_EQ(val1, val2)
Definition: gtest.h:2082
google::protobuf::Descriptor::field
const FieldDescriptor * field(int index) const
google::protobuf::compiler::kSecondInsertionPoint
static const char * kSecondInsertionPoint
Definition: mock_code_generator.cc:83
GeneratedCodeInfo::annotation
const PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo_Annotation & annotation(int index) const
Definition: descriptor.pb.h:11900
strutil.h
google::protobuf::File::GetContents
static bool GetContents(const string &name, string *output, bool)
Definition: file.h:83
google::protobuf::compiler::MockCodeGenerator::GetOutputFileContent
static std::string GetOutputFileContent(const std::string &generator_name, const std::string &parameter, const FileDescriptor *file, GeneratorContext *context)
Definition: mock_code_generator.cc:307
google::protobuf::TextFormat::ParseFromString
static bool ParseFromString(const std::string &input, Message *output)
Definition: text_format.cc:1496
GeneratedCodeInfo_Annotation
Definition: descriptor.pb.h:6147
google::protobuf::StripPrefixString
string StripPrefixString(const string &str, const string &prefix)
Definition: strutil.h:121
google::protobuf::compiler::GeneratorContext::OpenForInsert
virtual io::ZeroCopyOutputStream * OpenForInsert(const std::string &filename, const std::string &insertion_point)
Definition: code_generator.cc:82
google::protobuf::FileDescriptor::CopySourceCodeInfoTo
void CopySourceCodeInfoTo(FileDescriptorProto *proto) const
Definition: src/google/protobuf/descriptor.cc:2060
printer.h
GOOGLE_LOG
#define GOOGLE_LOG(LEVEL)
Definition: logging.h:146
google::protobuf::io::Printer::failed
bool failed() const
Definition: printer.h:288
google::protobuf::strings::Substitute
string Substitute(const char *format, const SubstituteArg &arg0, const SubstituteArg &arg1, const SubstituteArg &arg2, const SubstituteArg &arg3, const SubstituteArg &arg4, const SubstituteArg &arg5, const SubstituteArg &arg6, const SubstituteArg &arg7, const SubstituteArg &arg8, const SubstituteArg &arg9)
Definition: substitute.cc:55
text_format.h
FileDescriptorProto
Definition: descriptor.pb.h:501
name_
string name_
Definition: googletest.cc:182
google::protobuf::HasPrefixString
bool HasPrefixString(const string &str, const string &prefix)
Definition: strutil.h:115
google::protobuf::compiler::MockCodeGenerator::MockCodeGenerator
MockCodeGenerator(const std::string &name)
Definition: mock_code_generator.cc:86
google::protobuf::compiler::MockCodeGenerator::ExpectGenerated
static void ExpectGenerated(const std::string &name, const std::string &parameter, const std::string &insertions, const std::string &file, const std::string &first_message_name, const std::string &parsed_file_list, const std::string &output_directory)
Definition: mock_code_generator.cc:90
google::protobuf::io::Printer::Annotate
void Annotate(const char *varname, const SomeDescriptor *descriptor)
Definition: printer.h:199
GOOGLE_CHECK
#define GOOGLE_CHECK(EXPRESSION)
Definition: logging.h:153
google::protobuf::io::Printer
Definition: printer.h:181
google::protobuf::compiler::MockCodeGenerator::name_
std::string name_
Definition: mock_code_generator.h:114
i
int i
Definition: gmock-matchers_test.cc:764
google::protobuf::FileDescriptor::name
const std::string & name() const
google::protobuf::compiler::kFirstInsertionPoint
static const char * kFirstInsertionPoint
Definition: mock_code_generator.cc:81
FileDescriptorProto::source_code_info
const PROTOBUF_NAMESPACE_ID::SourceCodeInfo & source_code_info() const
Definition: descriptor.pb.h:7041
google::protobuf.internal.api_implementation.Version
def Version()
Definition: api_implementation.py:147
google::protobuf::SplitStringUsing
void SplitStringUsing(const string &full, const char *delim, std::vector< string > *result)
Definition: strutil.cc:229
common.h
google::protobuf::FileDescriptor::message_type
const Descriptor * message_type(int index) const
google::protobuf::compiler::kFirstInsertionPointName
static const char * kFirstInsertionPointName
Definition: mock_code_generator.cc:79
google::protobuf::compiler::MockCodeGenerator::GetOutputFileName
static std::string GetOutputFileName(const std::string &generator_name, const FileDescriptor *file)
Definition: mock_code_generator.cc:297
GOOGLE_CHECK_OK
#define GOOGLE_CHECK_OK(A)
Definition: logging.h:155
google::protobuf::compiler::MockCodeGenerator::Generate
virtual bool Generate(const FileDescriptor *file, const std::string &parameter, GeneratorContext *context, std::string *error) const
Definition: mock_code_generator.cc:173
google::protobuf::Descriptor::name
const std::string & name() const
logging.h
google::protobuf::Split
std::vector< string > Split(const string &full, const char *delim, bool skip_empty=true)
Definition: strutil.h:235
descriptor.h
substitute.h
google::protobuf::FileDescriptor
Definition: src/google/protobuf/descriptor.h:1320
google::protobuf::compiler::MockCodeGenerator::~MockCodeGenerator
virtual ~MockCodeGenerator()
Definition: mock_code_generator.cc:88
ASSERT_GE
#define ASSERT_GE(val1, val2)
Definition: gtest.h:2098
google::protobuf::io::AnnotationProtoCollector
Definition: printer.h:76
file.h
FileDescriptorProto::has_source_code_info
bool has_source_code_info() const
Definition: descriptor.pb.h:7034
google::protobuf::Join
void Join(Iterator start, Iterator end, const char *delim, string *result)
Definition: strutil.h:769
GeneratedCodeInfo_Annotation::end
::PROTOBUF_NAMESPACE_ID::int32 end() const
Definition: descriptor.pb.h:11870
descriptor.pb.h
output
const upb_json_parsermethod const upb_symtab upb_sink * output
Definition: ruby/ext/google/protobuf_c/upb.h:10503
GeneratedCodeInfo
Definition: descriptor.pb.h:6355
google::protobuf::compiler::GeneratorContext
Definition: code_generator.h:119
google::protobuf::FileDescriptor::message_type_count
int message_type_count() const
google::protobuf::compiler::MockCodeGenerator::CheckGeneratedAnnotations
static void CheckGeneratedAnnotations(const std::string &name, const std::string &file, const std::string &output_directory)
Definition: mock_code_generator.cc:151
compiler
Definition: plugin.pb.cc:22
google
Definition: data_proto2_to_proto3_util.h:11
plugin.pb.h


libaditof
Author(s):
autogenerated on Wed May 21 2025 02:06:57