protobuf/src/google/protobuf/compiler/parser_unittest.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 // Based on original Protocol Buffers design by
33 // Sanjay Ghemawat, Jeff Dean, and others.
34 
35 #include <google/protobuf/compiler/parser.h>
36 
37 #include <algorithm>
38 #include <map>
39 #include <memory>
40 #include <vector>
41 
42 #include <google/protobuf/test_util2.h>
43 #include <google/protobuf/unittest.pb.h>
44 #include <google/protobuf/any.pb.h>
45 #include <google/protobuf/unittest_custom_options.pb.h>
46 #include <google/protobuf/io/tokenizer.h>
47 #include <google/protobuf/io/zero_copy_stream_impl.h>
48 #include <google/protobuf/descriptor.pb.h>
49 #include <google/protobuf/text_format.h>
50 #include <google/protobuf/wire_format.h>
51 #include <google/protobuf/testing/googletest.h>
52 #include <gtest/gtest.h>
53 #include <google/protobuf/stubs/substitute.h>
54 #include <google/protobuf/stubs/map_util.h>
55 
56 namespace google {
57 namespace protobuf {
58 namespace compiler {
59 
60 namespace {
61 
62 class MockErrorCollector : public io::ErrorCollector {
63  public:
64  MockErrorCollector() = default;
65  ~MockErrorCollector() override = default;
66 
69 
70  // implements ErrorCollector ---------------------------------------
71  void AddWarning(int line, int column, const std::string& message) override {
72  strings::SubstituteAndAppend(&warning_, "$0:$1: $2\n", line, column, message);
73  }
74 
75  void AddError(int line, int column, const std::string& message) override {
76  strings::SubstituteAndAppend(&text_, "$0:$1: $2\n", line, column, message);
77  }
78 };
79 
80 class MockValidationErrorCollector : public DescriptorPool::ErrorCollector {
81  public:
82  MockValidationErrorCollector(const SourceLocationTable& source_locations,
83  io::ErrorCollector* wrapped_collector)
84  : source_locations_(source_locations),
85  wrapped_collector_(wrapped_collector) {}
86  ~MockValidationErrorCollector() {}
87 
88  // implements ErrorCollector ---------------------------------------
89  void AddError(const std::string& filename, const std::string& element_name,
90  const Message* descriptor, ErrorLocation location,
91  const std::string& message) override {
92  int line, column;
94  source_locations_.FindImport(descriptor, element_name, &line, &column);
95  } else {
96  source_locations_.Find(descriptor, location, &line, &column);
97  }
98  wrapped_collector_->AddError(line, column, message);
99  }
100 
101  private:
102  const SourceLocationTable& source_locations_;
103  io::ErrorCollector* wrapped_collector_;
104 };
105 
106 class ParserTest : public testing::Test {
107  protected:
108  ParserTest() : require_syntax_identifier_(false) {}
109 
110  // Set up the parser to parse the given text.
111  void SetupParser(const char* text) {
112  raw_input_.reset(new io::ArrayInputStream(text, strlen(text)));
113  input_.reset(new io::Tokenizer(raw_input_.get(), &error_collector_));
114  parser_.reset(new Parser());
115  parser_->RecordErrorsTo(&error_collector_);
116  parser_->SetRequireSyntaxIdentifier(require_syntax_identifier_);
117  }
118 
119  // Parse the input and expect that the resulting FileDescriptorProto matches
120  // the given output. The output is a FileDescriptorProto in protocol buffer
121  // text format.
122  void ExpectParsesTo(const char* input, const char* output) {
123  SetupParser(input);
124  FileDescriptorProto actual, expected;
125 
126  parser_->Parse(input_.get(), &actual);
127  EXPECT_EQ(io::Tokenizer::TYPE_END, input_->current().type);
128  ASSERT_EQ("", error_collector_.text_);
129 
130  // We don't cover SourceCodeInfo in these tests.
131  actual.clear_source_code_info();
132 
133  // Parse the ASCII representation in order to canonicalize it. We could
134  // just compare directly to actual.DebugString(), but that would require
135  // that the caller precisely match the formatting that DebugString()
136  // produces.
138 
139  // Compare by comparing debug strings.
140  // TODO(kenton): Use differencer, once it is available.
141  EXPECT_EQ(expected.DebugString(), actual.DebugString());
142  }
143 
144  // Parse the text and expect that the given errors are reported.
145  void ExpectHasErrors(const char* text, const char* expected_errors) {
146  ExpectHasEarlyExitErrors(text, expected_errors);
147  EXPECT_EQ(io::Tokenizer::TYPE_END, input_->current().type);
148  }
149 
150  // Same as above but does not expect that the parser parses the complete
151  // input.
152  void ExpectHasEarlyExitErrors(const char* text, const char* expected_errors) {
153  SetupParser(text);
155  parser_->Parse(input_.get(), &file);
156  EXPECT_EQ(expected_errors, error_collector_.text_);
157  }
158 
159  // Parse the text as a file and validate it (with a DescriptorPool), and
160  // expect that the validation step reports the given errors.
161  void ExpectHasValidationErrors(const char* text,
162  const char* expected_errors) {
163  SetupParser(text);
164  SourceLocationTable source_locations;
165  parser_->RecordSourceLocationsTo(&source_locations);
166 
168  file.set_name("foo.proto");
169  parser_->Parse(input_.get(), &file);
170  EXPECT_EQ(io::Tokenizer::TYPE_END, input_->current().type);
171  ASSERT_EQ("", error_collector_.text_);
172 
173  MockValidationErrorCollector validation_error_collector(source_locations,
175  EXPECT_TRUE(pool_.BuildFileCollectingErrors(
176  file, &validation_error_collector) == NULL);
177  EXPECT_EQ(expected_errors, error_collector_.text_);
178  }
179 
180  MockErrorCollector error_collector_;
182 
183  std::unique_ptr<io::ZeroCopyInputStream> raw_input_;
184  std::unique_ptr<io::Tokenizer> input_;
185  std::unique_ptr<Parser> parser_;
187 };
188 
189 // ===================================================================
190 
191 TEST_F(ParserTest, StopAfterSyntaxIdentifier) {
192  SetupParser(
193  "// blah\n"
194  "syntax = \"foobar\";\n"
195  "this line will not be parsed\n");
196  parser_->SetStopAfterSyntaxIdentifier(true);
197  EXPECT_TRUE(parser_->Parse(input_.get(), NULL));
198  EXPECT_EQ("", error_collector_.text_);
199  EXPECT_EQ("foobar", parser_->GetSyntaxIdentifier());
200 }
201 
202 TEST_F(ParserTest, StopAfterOmittedSyntaxIdentifier) {
203  SetupParser(
204  "// blah\n"
205  "this line will not be parsed\n");
206  parser_->SetStopAfterSyntaxIdentifier(true);
207  EXPECT_TRUE(parser_->Parse(input_.get(), NULL));
208  EXPECT_EQ("", error_collector_.text_);
209  EXPECT_EQ("", parser_->GetSyntaxIdentifier());
210 }
211 
212 TEST_F(ParserTest, StopAfterSyntaxIdentifierWithErrors) {
213  SetupParser(
214  "// blah\n"
215  "syntax = error;\n");
216  parser_->SetStopAfterSyntaxIdentifier(true);
217  EXPECT_FALSE(parser_->Parse(input_.get(), NULL));
218  EXPECT_EQ("1:9: Expected syntax identifier.\n", error_collector_.text_);
219 }
220 
221 TEST_F(ParserTest, WarnIfSyntaxIdentifierOmmitted) {
222  SetupParser("message A {}");
225  EXPECT_TRUE(parser_->Parse(input_.get(), &file));
226  EXPECT_TRUE(GetCapturedTestStderr().find("No syntax specified") !=
227  std::string::npos);
228 }
229 
230 TEST_F(ParserTest, WarnIfFieldNameIsNotUpperCamel) {
231  SetupParser(
232  "syntax = \"proto2\";"
233  "message abc {}");
235  EXPECT_TRUE(parser_->Parse(input_.get(), &file));
236  EXPECT_TRUE(error_collector_.warning_.find(
237  "Message name should be in UpperCamelCase. Found: abc.") !=
238  std::string::npos);
239 }
240 
241 TEST_F(ParserTest, WarnIfFieldNameIsNotLowerUnderscore) {
242  SetupParser(
243  "syntax = \"proto2\";"
244  "message A {"
245  " optional string SongName = 1;"
246  "}");
248  EXPECT_TRUE(parser_->Parse(input_.get(), &file));
249  EXPECT_TRUE(error_collector_.warning_.find(
250  "Field name should be lowercase. Found: SongName") !=
251  std::string::npos);
252 }
253 
254 TEST_F(ParserTest, WarnIfFieldNameContainsNumberImmediatelyFollowUnderscore) {
255  SetupParser(
256  "syntax = \"proto2\";"
257  "message A {"
258  " optional string song_name_1 = 1;"
259  "}");
261  EXPECT_TRUE(parser_->Parse(input_.get(), &file));
262  EXPECT_TRUE(error_collector_.warning_.find(
263  "Number should not come right after an underscore. Found: "
264  "song_name_1.") != std::string::npos);
265 }
266 
267 // ===================================================================
268 
269 typedef ParserTest ParseMessageTest;
270 
271 TEST_F(ParseMessageTest, IgnoreBOM) {
272  char input[] =
273  " message TestMessage {\n"
274  " required int32 foo = 1;\n"
275  "}\n";
276  // Set UTF-8 BOM.
277  input[0] = (char)0xEF;
278  input[1] = (char)0xBB;
279  input[2] = (char)0xBF;
280  ExpectParsesTo(
281  input,
282  "message_type {"
283  " name: \"TestMessage\""
284  " field { name:\"foo\" label:LABEL_REQUIRED type:TYPE_INT32 number:1 }"
285  "}");
286 }
287 
288 TEST_F(ParseMessageTest, BOMError) {
289  char input[] =
290  " message TestMessage {\n"
291  " required int32 foo = 1;\n"
292  "}\n";
293  input[0] = (char)0xEF;
294  ExpectHasErrors(input,
295  "0:1: Proto file starts with 0xEF but not UTF-8 BOM. "
296  "Only UTF-8 is accepted for proto file.\n"
297  "0:0: Expected top-level statement (e.g. \"message\").\n");
298 }
299 
300 TEST_F(ParseMessageTest, SimpleMessage) {
301  ExpectParsesTo(
302  "message TestMessage {\n"
303  " required int32 foo = 1;\n"
304  "}\n",
305 
306  "message_type {"
307  " name: \"TestMessage\""
308  " field { name:\"foo\" label:LABEL_REQUIRED type:TYPE_INT32 number:1 }"
309  "}");
310 }
311 
312 TEST_F(ParseMessageTest, ImplicitSyntaxIdentifier) {
314  ExpectParsesTo(
315  "message TestMessage {\n"
316  " required int32 foo = 1;\n"
317  "}\n",
318 
319  "message_type {"
320  " name: \"TestMessage\""
321  " field { name:\"foo\" label:LABEL_REQUIRED type:TYPE_INT32 number:1 }"
322  "}");
323  EXPECT_EQ("proto2", parser_->GetSyntaxIdentifier());
324 }
325 
326 TEST_F(ParseMessageTest, ExplicitSyntaxIdentifier) {
327  ExpectParsesTo(
328  "syntax = \"proto2\";\n"
329  "message TestMessage {\n"
330  " required int32 foo = 1;\n"
331  "}\n",
332 
333  "syntax: 'proto2' "
334  "message_type {"
335  " name: \"TestMessage\""
336  " field { name:\"foo\" label:LABEL_REQUIRED type:TYPE_INT32 number:1 }"
337  "}");
338  EXPECT_EQ("proto2", parser_->GetSyntaxIdentifier());
339 }
340 
341 TEST_F(ParseMessageTest, ExplicitRequiredSyntaxIdentifier) {
343  ExpectParsesTo(
344  "syntax = \"proto2\";\n"
345  "message TestMessage {\n"
346  " required int32 foo = 1;\n"
347  "}\n",
348 
349  "syntax: 'proto2' "
350  "message_type {"
351  " name: \"TestMessage\""
352  " field { name:\"foo\" label:LABEL_REQUIRED type:TYPE_INT32 number:1 }"
353  "}");
354  EXPECT_EQ("proto2", parser_->GetSyntaxIdentifier());
355 }
356 
357 TEST_F(ParseMessageTest, SimpleFields) {
358  ExpectParsesTo(
359  "message TestMessage {\n"
360  " required int32 foo = 15;\n"
361  " optional int32 bar = 34;\n"
362  " repeated int32 baz = 3;\n"
363  "}\n",
364 
365  "message_type {"
366  " name: \"TestMessage\""
367  " field { name:\"foo\" label:LABEL_REQUIRED type:TYPE_INT32 number:15 }"
368  " field { name:\"bar\" label:LABEL_OPTIONAL type:TYPE_INT32 number:34 }"
369  " field { name:\"baz\" label:LABEL_REPEATED type:TYPE_INT32 number:3 }"
370  "}");
371 }
372 
373 TEST_F(ParseMessageTest, PrimitiveFieldTypes) {
374  ExpectParsesTo(
375  "message TestMessage {\n"
376  " required int32 foo = 1;\n"
377  " required int64 foo = 1;\n"
378  " required uint32 foo = 1;\n"
379  " required uint64 foo = 1;\n"
380  " required sint32 foo = 1;\n"
381  " required sint64 foo = 1;\n"
382  " required fixed32 foo = 1;\n"
383  " required fixed64 foo = 1;\n"
384  " required sfixed32 foo = 1;\n"
385  " required sfixed64 foo = 1;\n"
386  " required float foo = 1;\n"
387  " required double foo = 1;\n"
388  " required string foo = 1;\n"
389  " required bytes foo = 1;\n"
390  " required bool foo = 1;\n"
391  "}\n",
392 
393  "message_type {"
394  " name: \"TestMessage\""
395  " field { name:\"foo\" label:LABEL_REQUIRED type:TYPE_INT32 number:1 "
396  "}"
397  " field { name:\"foo\" label:LABEL_REQUIRED type:TYPE_INT64 number:1 "
398  "}"
399  " field { name:\"foo\" label:LABEL_REQUIRED type:TYPE_UINT32 number:1 "
400  "}"
401  " field { name:\"foo\" label:LABEL_REQUIRED type:TYPE_UINT64 number:1 "
402  "}"
403  " field { name:\"foo\" label:LABEL_REQUIRED type:TYPE_SINT32 number:1 "
404  "}"
405  " field { name:\"foo\" label:LABEL_REQUIRED type:TYPE_SINT64 number:1 "
406  "}"
407  " field { name:\"foo\" label:LABEL_REQUIRED type:TYPE_FIXED32 number:1 "
408  "}"
409  " field { name:\"foo\" label:LABEL_REQUIRED type:TYPE_FIXED64 number:1 "
410  "}"
411  " field { name:\"foo\" label:LABEL_REQUIRED type:TYPE_SFIXED32 number:1 "
412  "}"
413  " field { name:\"foo\" label:LABEL_REQUIRED type:TYPE_SFIXED64 number:1 "
414  "}"
415  " field { name:\"foo\" label:LABEL_REQUIRED type:TYPE_FLOAT number:1 "
416  "}"
417  " field { name:\"foo\" label:LABEL_REQUIRED type:TYPE_DOUBLE number:1 "
418  "}"
419  " field { name:\"foo\" label:LABEL_REQUIRED type:TYPE_STRING number:1 "
420  "}"
421  " field { name:\"foo\" label:LABEL_REQUIRED type:TYPE_BYTES number:1 "
422  "}"
423  " field { name:\"foo\" label:LABEL_REQUIRED type:TYPE_BOOL number:1 "
424  "}"
425  "}");
426 }
427 
428 TEST_F(ParseMessageTest, FieldDefaults) {
429  ExpectParsesTo(
430  "message TestMessage {\n"
431  " required int32 foo = 1 [default= 1 ];\n"
432  " required int32 foo = 1 [default= -2 ];\n"
433  " required int64 foo = 1 [default= 3 ];\n"
434  " required int64 foo = 1 [default= -4 ];\n"
435  " required uint32 foo = 1 [default= 5 ];\n"
436  " required uint64 foo = 1 [default= 6 ];\n"
437  " required float foo = 1 [default= 7.5];\n"
438  " required float foo = 1 [default= -8.5];\n"
439  " required float foo = 1 [default= 9 ];\n"
440  " required double foo = 1 [default= 10.5];\n"
441  " required double foo = 1 [default=-11.5];\n"
442  " required double foo = 1 [default= 12 ];\n"
443  " required double foo = 1 [default= inf ];\n"
444  " required double foo = 1 [default=-inf ];\n"
445  " required double foo = 1 [default= nan ];\n"
446  " required string foo = 1 [default='13\\001'];\n"
447  " required string foo = 1 [default='a' \"b\" \n \"c\"];\n"
448  " required bytes foo = 1 [default='14\\002'];\n"
449  " required bytes foo = 1 [default='a' \"b\" \n 'c'];\n"
450  " required bool foo = 1 [default=true ];\n"
451  " required Foo foo = 1 [default=FOO ];\n"
452 
453  " required int32 foo = 1 [default= 0x7FFFFFFF];\n"
454  " required int32 foo = 1 [default=-0x80000000];\n"
455  " required uint32 foo = 1 [default= 0xFFFFFFFF];\n"
456  " required int64 foo = 1 [default= 0x7FFFFFFFFFFFFFFF];\n"
457  " required int64 foo = 1 [default=-0x8000000000000000];\n"
458  " required uint64 foo = 1 [default= 0xFFFFFFFFFFFFFFFF];\n"
459  " required double foo = 1 [default= 0xabcd];\n"
460  "}\n",
461 
462 #define ETC "name:\"foo\" label:LABEL_REQUIRED number:1"
463  "message_type {"
464  " name: \"TestMessage\""
465  " field { type:TYPE_INT32 default_value:\"1\" " ETC
466  " }"
467  " field { type:TYPE_INT32 default_value:\"-2\" " ETC
468  " }"
469  " field { type:TYPE_INT64 default_value:\"3\" " ETC
470  " }"
471  " field { type:TYPE_INT64 default_value:\"-4\" " ETC
472  " }"
473  " field { type:TYPE_UINT32 default_value:\"5\" " ETC
474  " }"
475  " field { type:TYPE_UINT64 default_value:\"6\" " ETC
476  " }"
477  " field { type:TYPE_FLOAT default_value:\"7.5\" " ETC
478  " }"
479  " field { type:TYPE_FLOAT default_value:\"-8.5\" " ETC
480  " }"
481  " field { type:TYPE_FLOAT default_value:\"9\" " ETC
482  " }"
483  " field { type:TYPE_DOUBLE default_value:\"10.5\" " ETC
484  " }"
485  " field { type:TYPE_DOUBLE default_value:\"-11.5\" " ETC
486  " }"
487  " field { type:TYPE_DOUBLE default_value:\"12\" " ETC
488  " }"
489  " field { type:TYPE_DOUBLE default_value:\"inf\" " ETC
490  " }"
491  " field { type:TYPE_DOUBLE default_value:\"-inf\" " ETC
492  " }"
493  " field { type:TYPE_DOUBLE default_value:\"nan\" " ETC
494  " }"
495  " field { type:TYPE_STRING default_value:\"13\\001\" " ETC
496  " }"
497  " field { type:TYPE_STRING default_value:\"abc\" " ETC
498  " }"
499  " field { type:TYPE_BYTES default_value:\"14\\\\002\" " ETC
500  " }"
501  " field { type:TYPE_BYTES default_value:\"abc\" " ETC
502  " }"
503  " field { type:TYPE_BOOL default_value:\"true\" " ETC
504  " }"
505  " field { type_name:\"Foo\" default_value:\"FOO\" " ETC
506  " }"
507 
508  " field {"
509  " type:TYPE_INT32 default_value:\"2147483647\" " ETC
510  " }"
511  " field {"
512  " type:TYPE_INT32 default_value:\"-2147483648\" " ETC
513  " }"
514  " field {"
515  " type:TYPE_UINT32 default_value:\"4294967295\" " ETC
516  " }"
517  " field {"
518  " type:TYPE_INT64 default_value:\"9223372036854775807\" " ETC
519  " }"
520  " field {"
521  " type:TYPE_INT64 default_value:\"-9223372036854775808\" " ETC
522  " }"
523  " field {"
524  " type:TYPE_UINT64 default_value:\"18446744073709551615\" " ETC
525  " }"
526  " field {"
527  " type:TYPE_DOUBLE default_value:\"43981\" " ETC
528  " }"
529  "}");
530 #undef ETC
531 }
532 
533 TEST_F(ParseMessageTest, FieldJsonName) {
534  ExpectParsesTo(
535  "message TestMessage {\n"
536  " optional string foo = 1 [json_name = \"@type\"];\n"
537  "}\n",
538  "message_type {"
539  " name: \"TestMessage\""
540  " field {\n"
541  " name: \"foo\" label: LABEL_OPTIONAL type: TYPE_STRING number: 1"
542  " json_name: \"@type\"\n"
543  " }\n"
544  "}\n");
545 }
546 
547 TEST_F(ParseMessageTest, FieldOptions) {
548  ExpectParsesTo(
549  "message TestMessage {\n"
550  " optional string foo = 1\n"
551  " [ctype=CORD, (foo)=7, foo.(.bar.baz).qux.quux.(corge)=-33, \n"
552  " (quux)=\"x\040y\", (baz.qux)=hey];\n"
553  "}\n",
554 
555  "message_type {"
556  " name: \"TestMessage\""
557  " field { name: \"foo\" label: LABEL_OPTIONAL type: TYPE_STRING number: "
558  "1"
559  " options { uninterpreted_option: { name { name_part: \"ctype\" "
560  " is_extension: false "
561  "} "
562  " identifier_value: \"CORD\" "
563  "}"
564  " uninterpreted_option: { name { name_part: \"foo\" "
565  " is_extension: true } "
566  " positive_int_value: 7 }"
567  " uninterpreted_option: { name { name_part: \"foo\" "
568  " is_extension: false "
569  "} "
570  " name { name_part: "
571  "\".bar.baz\""
572  " is_extension: true } "
573  " name { name_part: \"qux\" "
574  " is_extension: false "
575  "} "
576  " name { name_part: \"quux\" "
577  " is_extension: false "
578  "} "
579  " name { name_part: \"corge\" "
580  " is_extension: true } "
581  " negative_int_value: -33 }"
582  " uninterpreted_option: { name { name_part: \"quux\" "
583  " is_extension: true } "
584  " string_value: \"x y\" }"
585  " uninterpreted_option: { name { name_part: "
586  "\"baz.qux\" "
587  " is_extension: true } "
588  " identifier_value: \"hey\" }"
589  " }"
590  " }"
591  "}");
592 }
593 
594 TEST_F(ParseMessageTest, Oneof) {
595  ExpectParsesTo(
596  "message TestMessage {\n"
597  " oneof foo {\n"
598  " int32 a = 1;\n"
599  " string b = 2;\n"
600  " TestMessage c = 3;\n"
601  " group D = 4 { optional int32 i = 5; }\n"
602  " }\n"
603  "}\n",
604 
605  "message_type {"
606  " name: \"TestMessage\""
607  " field { name:\"a\" label:LABEL_OPTIONAL type:TYPE_INT32 number:1 "
608  " oneof_index:0 }"
609  " field { name:\"b\" label:LABEL_OPTIONAL type:TYPE_STRING number:2 "
610  " oneof_index:0 }"
611  " field { name:\"c\" label:LABEL_OPTIONAL type_name:\"TestMessage\" "
612  " number:3 oneof_index:0 }"
613  " field { name:\"d\" label:LABEL_OPTIONAL type:TYPE_GROUP "
614  " type_name:\"D\" number:4 oneof_index:0 }"
615  " oneof_decl {"
616  " name: \"foo\""
617  " }"
618  " nested_type {"
619  " name: \"D\""
620  " field { name:\"i\" label:LABEL_OPTIONAL type:TYPE_INT32 number:5 }"
621  " }"
622  "}");
623 }
624 
625 TEST_F(ParseMessageTest, MultipleOneofs) {
626  ExpectParsesTo(
627  "message TestMessage {\n"
628  " oneof foo {\n"
629  " int32 a = 1;\n"
630  " string b = 2;\n"
631  " }\n"
632  " oneof bar {\n"
633  " int32 c = 3;\n"
634  " string d = 4;\n"
635  " }\n"
636  "}\n",
637 
638  "message_type {"
639  " name: \"TestMessage\""
640  " field { name:\"a\" label:LABEL_OPTIONAL type:TYPE_INT32 number:1 "
641  " oneof_index:0 }"
642  " field { name:\"b\" label:LABEL_OPTIONAL type:TYPE_STRING number:2 "
643  " oneof_index:0 }"
644  " field { name:\"c\" label:LABEL_OPTIONAL type:TYPE_INT32 number:3 "
645  " oneof_index:1 }"
646  " field { name:\"d\" label:LABEL_OPTIONAL type:TYPE_STRING number:4 "
647  " oneof_index:1 }"
648  " oneof_decl {"
649  " name: \"foo\""
650  " }"
651  " oneof_decl {"
652  " name: \"bar\""
653  " }"
654  "}");
655 }
656 
657 TEST_F(ParseMessageTest, Maps) {
658  ExpectParsesTo(
659  "message TestMessage {\n"
660  " map<int32, string> primitive_type_map = 1;\n"
661  " map<KeyType, ValueType> composite_type_map = 2;\n"
662  "}\n",
663 
664  "message_type {"
665  " name: \"TestMessage\""
666  " nested_type {"
667  " name: \"PrimitiveTypeMapEntry\""
668  " field { "
669  " name: \"key\" number: 1 label:LABEL_OPTIONAL"
670  " type:TYPE_INT32"
671  " }"
672  " field { "
673  " name: \"value\" number: 2 label:LABEL_OPTIONAL"
674  " type:TYPE_STRING"
675  " }"
676  " options { map_entry: true }"
677  " }"
678  " nested_type {"
679  " name: \"CompositeTypeMapEntry\""
680  " field { "
681  " name: \"key\" number: 1 label:LABEL_OPTIONAL"
682  " type_name: \"KeyType\""
683  " }"
684  " field { "
685  " name: \"value\" number: 2 label:LABEL_OPTIONAL"
686  " type_name: \"ValueType\""
687  " }"
688  " options { map_entry: true }"
689  " }"
690  " field {"
691  " name: \"primitive_type_map\""
692  " label: LABEL_REPEATED"
693  " type_name: \"PrimitiveTypeMapEntry\""
694  " number: 1"
695  " }"
696  " field {"
697  " name: \"composite_type_map\""
698  " label: LABEL_REPEATED"
699  " type_name: \"CompositeTypeMapEntry\""
700  " number: 2"
701  " }"
702  "}");
703 }
704 
705 TEST_F(ParseMessageTest, Group) {
706  ExpectParsesTo(
707  "message TestMessage {\n"
708  " optional group TestGroup = 1 {};\n"
709  "}\n",
710 
711  "message_type {"
712  " name: \"TestMessage\""
713  " nested_type { name: \"TestGroup\" }"
714  " field { name:\"testgroup\" label:LABEL_OPTIONAL number:1"
715  " type:TYPE_GROUP type_name: \"TestGroup\" }"
716  "}");
717 }
718 
719 TEST_F(ParseMessageTest, NestedMessage) {
720  ExpectParsesTo(
721  "message TestMessage {\n"
722  " message Nested {}\n"
723  " optional Nested test_nested = 1;\n"
724  "}\n",
725 
726  "message_type {"
727  " name: \"TestMessage\""
728  " nested_type { name: \"Nested\" }"
729  " field { name:\"test_nested\" label:LABEL_OPTIONAL number:1"
730  " type_name: \"Nested\" }"
731  "}");
732 }
733 
734 TEST_F(ParseMessageTest, NestedEnum) {
735  ExpectParsesTo(
736  "message TestMessage {\n"
737  " enum NestedEnum {}\n"
738  " optional NestedEnum test_enum = 1;\n"
739  "}\n",
740 
741  "message_type {"
742  " name: \"TestMessage\""
743  " enum_type { name: \"NestedEnum\" }"
744  " field { name:\"test_enum\" label:LABEL_OPTIONAL number:1"
745  " type_name: \"NestedEnum\" }"
746  "}");
747 }
748 
749 TEST_F(ParseMessageTest, ReservedRange) {
750  ExpectParsesTo(
751  "message TestMessage {\n"
752  " required int32 foo = 1;\n"
753  " reserved 2, 15, 9 to 11, 3, 20 to max;\n"
754  "}\n",
755 
756  "message_type {"
757  " name: \"TestMessage\""
758  " field { name:\"foo\" label:LABEL_REQUIRED type:TYPE_INT32 number:1 }"
759  " reserved_range { start:2 end:3 }"
760  " reserved_range { start:15 end:16 }"
761  " reserved_range { start:9 end:12 }"
762  " reserved_range { start:3 end:4 }"
763  " reserved_range { start:20 end:536870912 }"
764  "}");
765 }
766 
767 TEST_F(ParseMessageTest, ReservedRangeOnMessageSet) {
768  ExpectParsesTo(
769  "message TestMessage {\n"
770  " option message_set_wire_format = true;\n"
771  " reserved 20 to max;\n"
772  "}\n",
773 
774  "message_type {"
775  " name: \"TestMessage\""
776  " options {"
777  " uninterpreted_option {"
778  " name {"
779  " name_part: \"message_set_wire_format\""
780  " is_extension: false"
781  " }"
782  " identifier_value: \"true\""
783  " }"
784  " }"
785  " reserved_range { start:20 end:2147483647 }"
786  "}");
787 }
788 
789 TEST_F(ParseMessageTest, ReservedNames) {
790  ExpectParsesTo(
791  "message TestMessage {\n"
792  " reserved \"foo\", \"bar\";\n"
793  "}\n",
794 
795  "message_type {"
796  " name: \"TestMessage\""
797  " reserved_name: \"foo\""
798  " reserved_name: \"bar\""
799  "}");
800 }
801 
802 TEST_F(ParseMessageTest, ExtensionRange) {
803  ExpectParsesTo(
804  "message TestMessage {\n"
805  " extensions 10 to 19;\n"
806  " extensions 30 to max;\n"
807  "}\n",
808 
809  "message_type {"
810  " name: \"TestMessage\""
811  " extension_range { start:10 end:20 }"
812  " extension_range { start:30 end:536870912 }"
813  "}");
814 }
815 
816 TEST_F(ParseMessageTest, ExtensionRangeWithOptions) {
817  ExpectParsesTo(
818  "message TestMessage {\n"
819  " extensions 10 to 19 [(i) = 5];\n"
820  "}\n",
821 
822  "message_type {"
823  " name: \"TestMessage\""
824  " extension_range {"
825  " start:10"
826  " end:20"
827  " options {"
828  " uninterpreted_option {"
829  " name {"
830  " name_part: \"i\""
831  " is_extension: true"
832  " }"
833  " positive_int_value: 5"
834  " }"
835  " }"
836  " }"
837  "}");
838 }
839 
840 TEST_F(ParseMessageTest, CompoundExtensionRange) {
841  ExpectParsesTo(
842  "message TestMessage {\n"
843  " extensions 2, 15, 9 to 11, 100 to max, 3;\n"
844  "}\n",
845 
846  "message_type {"
847  " name: \"TestMessage\""
848  " extension_range { start:2 end:3 }"
849  " extension_range { start:15 end:16 }"
850  " extension_range { start:9 end:12 }"
851  " extension_range { start:100 end:536870912 }"
852  " extension_range { start:3 end:4 }"
853  "}");
854 }
855 
856 TEST_F(ParseMessageTest, CompoundExtensionRangeWithOptions) {
857  ExpectParsesTo(
858  "message TestMessage {\n"
859  " extensions 2, 15, 9 to 11, 100 to max, 3 [(i) = 5];\n"
860  "}\n",
861 
862  "message_type {"
863  " name: \"TestMessage\""
864  " extension_range {"
865  " start:2"
866  " end:3"
867  " options {"
868  " uninterpreted_option {"
869  " name {"
870  " name_part: \"i\""
871  " is_extension: true"
872  " }"
873  " positive_int_value: 5"
874  " }"
875  " }"
876  " }"
877  " extension_range {"
878  " start:15"
879  " end:16"
880  " options {"
881  " uninterpreted_option {"
882  " name {"
883  " name_part: \"i\""
884  " is_extension: true"
885  " }"
886  " positive_int_value: 5"
887  " }"
888  " }"
889  " }"
890  " extension_range {"
891  " start:9"
892  " end:12"
893  " options {"
894  " uninterpreted_option {"
895  " name {"
896  " name_part: \"i\""
897  " is_extension: true"
898  " }"
899  " positive_int_value: 5"
900  " }"
901  " }"
902  " }"
903  " extension_range {"
904  " start:100"
905  " end:536870912"
906  " options {"
907  " uninterpreted_option {"
908  " name {"
909  " name_part: \"i\""
910  " is_extension: true"
911  " }"
912  " positive_int_value: 5"
913  " }"
914  " }"
915  " }"
916  " extension_range {"
917  " start:3"
918  " end:4"
919  " options {"
920  " uninterpreted_option {"
921  " name {"
922  " name_part: \"i\""
923  " is_extension: true"
924  " }"
925  " positive_int_value: 5"
926  " }"
927  " }"
928  " }"
929  "}");
930 }
931 
932 TEST_F(ParseMessageTest, LargerMaxForMessageSetWireFormatMessages) {
933  // Messages using the message_set_wire_format option can accept larger
934  // extension numbers, as the numbers are not encoded as int32 field values
935  // rather than tags.
936  ExpectParsesTo(
937  "message TestMessage {\n"
938  " extensions 4 to max;\n"
939  " option message_set_wire_format = true;\n"
940  "}\n",
941 
942  "message_type {"
943  " name: \"TestMessage\""
944  " extension_range { start:4 end: 0x7fffffff }"
945  " options {\n"
946  " uninterpreted_option { \n"
947  " name {\n"
948  " name_part: \"message_set_wire_format\"\n"
949  " is_extension: false\n"
950  " }\n"
951  " identifier_value: \"true\"\n"
952  " }\n"
953  " }\n"
954  "}");
955 }
956 
957 TEST_F(ParseMessageTest, Extensions) {
958  ExpectParsesTo(
959  "extend Extendee1 { optional int32 foo = 12; }\n"
960  "extend Extendee2 { repeated TestMessage bar = 22; }\n",
961 
962  "extension { name:\"foo\" label:LABEL_OPTIONAL type:TYPE_INT32 number:12"
963  " extendee: \"Extendee1\" } "
964  "extension { name:\"bar\" label:LABEL_REPEATED number:22"
965  " type_name:\"TestMessage\" extendee: \"Extendee2\" }");
966 }
967 
968 TEST_F(ParseMessageTest, ExtensionsInMessageScope) {
969  ExpectParsesTo(
970  "message TestMessage {\n"
971  " extend Extendee1 { optional int32 foo = 12; }\n"
972  " extend Extendee2 { repeated TestMessage bar = 22; }\n"
973  "}\n",
974 
975  "message_type {"
976  " name: \"TestMessage\""
977  " extension { name:\"foo\" label:LABEL_OPTIONAL type:TYPE_INT32 "
978  "number:12"
979  " extendee: \"Extendee1\" }"
980  " extension { name:\"bar\" label:LABEL_REPEATED number:22"
981  " type_name:\"TestMessage\" extendee: \"Extendee2\" }"
982  "}");
983 }
984 
985 TEST_F(ParseMessageTest, MultipleExtensionsOneExtendee) {
986  ExpectParsesTo(
987  "extend Extendee1 {\n"
988  " optional int32 foo = 12;\n"
989  " repeated TestMessage bar = 22;\n"
990  "}\n",
991 
992  "extension { name:\"foo\" label:LABEL_OPTIONAL type:TYPE_INT32 number:12"
993  " extendee: \"Extendee1\" } "
994  "extension { name:\"bar\" label:LABEL_REPEATED number:22"
995  " type_name:\"TestMessage\" extendee: \"Extendee1\" }");
996 }
997 
998 TEST_F(ParseMessageTest, OptionalLabelProto3) {
999  ExpectParsesTo(
1000  "syntax = \"proto3\";\n"
1001  "message TestMessage {\n"
1002  " int32 foo = 1;\n"
1003  "}\n",
1004 
1005  "syntax: \"proto3\" "
1006  "message_type {"
1007  " name: \"TestMessage\""
1008  " field { name:\"foo\" label:LABEL_OPTIONAL type:TYPE_INT32 number:1 } "
1009  "}");
1010 }
1011 
1012 TEST_F(ParseMessageTest, ExplicitOptionalLabelProto3) {
1013  ExpectParsesTo(
1014  "syntax = 'proto3';\n"
1015  "message TestMessage {\n"
1016  " optional int32 foo = 1;\n"
1017  "}\n",
1018 
1019  "syntax: \"proto3\" "
1020  "message_type {"
1021  " name: \"TestMessage\""
1022  " field { name:\"foo\" label:LABEL_OPTIONAL type:TYPE_INT32 number:1 "
1023  " proto3_optional: true oneof_index: 0 } "
1024  " oneof_decl { name:\"_foo\" } "
1025  "}");
1026 
1027  // Handle collisions in the synthetic oneof name.
1028  ExpectParsesTo(
1029  "syntax = 'proto3';\n"
1030  "message TestMessage {\n"
1031  " optional int32 foo = 1;\n"
1032  " oneof _foo {\n"
1033  " int32 __foo = 2;\n"
1034  " }\n"
1035  "}\n",
1036 
1037  "syntax: \"proto3\" "
1038  "message_type {"
1039  " name: \"TestMessage\""
1040  " field { name:\"foo\" label:LABEL_OPTIONAL type:TYPE_INT32 number:1 "
1041  " proto3_optional: true oneof_index: 1 } "
1042  " field { name:\"__foo\" label:LABEL_OPTIONAL type:TYPE_INT32 number:2 "
1043  " oneof_index: 0 } "
1044  " oneof_decl { name:\"_foo\" } "
1045  " oneof_decl { name:\"X_foo\" } "
1046  "}");
1047 }
1048 
1049 // ===================================================================
1050 
1051 typedef ParserTest ParseEnumTest;
1052 
1053 TEST_F(ParseEnumTest, SimpleEnum) {
1054  ExpectParsesTo(
1055  "enum TestEnum {\n"
1056  " FOO = 0;\n"
1057  "}\n",
1058 
1059  "enum_type {"
1060  " name: \"TestEnum\""
1061  " value { name:\"FOO\" number:0 }"
1062  "}");
1063 }
1064 
1065 TEST_F(ParseEnumTest, Values) {
1066  ExpectParsesTo(
1067  "enum TestEnum {\n"
1068  " FOO = 13;\n"
1069  " BAR = -10;\n"
1070  " BAZ = 500;\n"
1071  " HEX_MAX = 0x7FFFFFFF;\n"
1072  " HEX_MIN = -0x80000000;\n"
1073  " INT_MAX = 2147483647;\n"
1074  " INT_MIN = -2147483648;\n"
1075  "}\n",
1076 
1077  "enum_type {"
1078  " name: \"TestEnum\""
1079  " value { name:\"FOO\" number:13 }"
1080  " value { name:\"BAR\" number:-10 }"
1081  " value { name:\"BAZ\" number:500 }"
1082  " value { name:\"HEX_MAX\" number:2147483647 }"
1083  " value { name:\"HEX_MIN\" number:-2147483648 }"
1084  " value { name:\"INT_MAX\" number:2147483647 }"
1085  " value { name:\"INT_MIN\" number:-2147483648 }"
1086  "}");
1087 }
1088 
1089 TEST_F(ParseEnumTest, ValueOptions) {
1090  ExpectParsesTo(
1091  "enum TestEnum {\n"
1092  " FOO = 13;\n"
1093  " BAR = -10 [ (something.text) = 'abc' ];\n"
1094  " BAZ = 500 [ (something.text) = 'def', other = 1 ];\n"
1095  "}\n",
1096 
1097  "enum_type {"
1098  " name: \"TestEnum\""
1099  " value { name: \"FOO\" number: 13 }"
1100  " value { name: \"BAR\" number: -10 "
1101  " options { "
1102  " uninterpreted_option { "
1103  " name { name_part: \"something.text\" is_extension: true } "
1104  " string_value: \"abc\" "
1105  " } "
1106  " } "
1107  " } "
1108  " value { name: \"BAZ\" number: 500 "
1109  " options { "
1110  " uninterpreted_option { "
1111  " name { name_part: \"something.text\" is_extension: true } "
1112  " string_value: \"def\" "
1113  " } "
1114  " uninterpreted_option { "
1115  " name { name_part: \"other\" is_extension: false } "
1116  " positive_int_value: 1 "
1117  " } "
1118  " } "
1119  " } "
1120  "}");
1121 }
1122 
1123 TEST_F(ParseEnumTest, ReservedRange) {
1124  ExpectParsesTo(
1125  "enum TestEnum {\n"
1126  " FOO = 0;\n"
1127  " reserved -2147483648, -6 to -4, -1 to 1, 2, 15, 9 to 11, 3, 20 to "
1128  "max;\n"
1129  "}\n",
1130 
1131  "enum_type {"
1132  " name: \"TestEnum\""
1133  " value { name:\"FOO\" number:0 }"
1134  " reserved_range { start:-2147483648 end:-2147483648 }"
1135  " reserved_range { start:-6 end:-4 }"
1136  " reserved_range { start:-1 end:1 }"
1137  " reserved_range { start:2 end:2 }"
1138  " reserved_range { start:15 end:15 }"
1139  " reserved_range { start:9 end:11 }"
1140  " reserved_range { start:3 end:3 }"
1141  " reserved_range { start:20 end:2147483647 }"
1142  "}");
1143 }
1144 
1145 TEST_F(ParseEnumTest, ReservedNames) {
1146  ExpectParsesTo(
1147  "enum TestEnum {\n"
1148  " FOO = 0;\n"
1149  " reserved \"foo\", \"bar\";\n"
1150  "}\n",
1151 
1152  "enum_type {"
1153  " name: \"TestEnum\""
1154  " value { name:\"FOO\" number:0 }"
1155  " reserved_name: \"foo\""
1156  " reserved_name: \"bar\""
1157  "}");
1158 }
1159 
1160 // ===================================================================
1161 
1162 typedef ParserTest ParseServiceTest;
1163 
1164 TEST_F(ParseServiceTest, SimpleService) {
1165  ExpectParsesTo(
1166  "service TestService {\n"
1167  " rpc Foo(In) returns (Out);\n"
1168  "}\n",
1169 
1170  "service {"
1171  " name: \"TestService\""
1172  " method { name:\"Foo\" input_type:\"In\" output_type:\"Out\" }"
1173  "}");
1174 }
1175 
1176 TEST_F(ParseServiceTest, MethodsAndStreams) {
1177  ExpectParsesTo(
1178  "service TestService {\n"
1179  " rpc Foo(In1) returns (Out1);\n"
1180  " rpc Bar(In2) returns (Out2);\n"
1181  " rpc Baz(In3) returns (Out3);\n"
1182  "}\n",
1183 
1184  "service {"
1185  " name: \"TestService\""
1186  " method { name:\"Foo\" input_type:\"In1\" output_type:\"Out1\" }"
1187  " method { name:\"Bar\" input_type:\"In2\" output_type:\"Out2\" }"
1188  " method { name:\"Baz\" input_type:\"In3\" output_type:\"Out3\" }"
1189  "}");
1190 }
1191 
1192 
1193 // ===================================================================
1194 // imports and packages
1195 
1196 typedef ParserTest ParseMiscTest;
1197 
1198 TEST_F(ParseMiscTest, ParseImport) {
1199  ExpectParsesTo("import \"foo/bar/baz.proto\";\n",
1200  "dependency: \"foo/bar/baz.proto\"");
1201 }
1202 
1203 TEST_F(ParseMiscTest, ParseMultipleImports) {
1204  ExpectParsesTo(
1205  "import \"foo.proto\";\n"
1206  "import \"bar.proto\";\n"
1207  "import \"baz.proto\";\n",
1208  "dependency: \"foo.proto\""
1209  "dependency: \"bar.proto\""
1210  "dependency: \"baz.proto\"");
1211 }
1212 
1213 TEST_F(ParseMiscTest, ParsePublicImports) {
1214  ExpectParsesTo(
1215  "import \"foo.proto\";\n"
1216  "import public \"bar.proto\";\n"
1217  "import \"baz.proto\";\n"
1218  "import public \"qux.proto\";\n",
1219  "dependency: \"foo.proto\""
1220  "dependency: \"bar.proto\""
1221  "dependency: \"baz.proto\""
1222  "dependency: \"qux.proto\""
1223  "public_dependency: 1 "
1224  "public_dependency: 3 ");
1225 }
1226 
1227 TEST_F(ParseMiscTest, ParsePackage) {
1228  ExpectParsesTo("package foo.bar.baz;\n", "package: \"foo.bar.baz\"");
1229 }
1230 
1231 TEST_F(ParseMiscTest, ParsePackageWithSpaces) {
1232  ExpectParsesTo(
1233  "package foo . bar. \n"
1234  " baz;\n",
1235  "package: \"foo.bar.baz\"");
1236 }
1237 
1238 // ===================================================================
1239 // options
1240 
1241 TEST_F(ParseMiscTest, ParseFileOptions) {
1242  ExpectParsesTo(
1243  "option java_package = \"com.google.foo\";\n"
1244  "option optimize_for = CODE_SIZE;",
1245 
1246  "options {"
1247  "uninterpreted_option { name { name_part: \"java_package\" "
1248  " is_extension: false }"
1249  " string_value: \"com.google.foo\"} "
1250  "uninterpreted_option { name { name_part: \"optimize_for\" "
1251  " is_extension: false }"
1252  " identifier_value: \"CODE_SIZE\" } "
1253  "}");
1254 }
1255 
1256 // ===================================================================
1257 // Error tests
1258 //
1259 // There are a very large number of possible errors that the parser could
1260 // report, so it's infeasible to test every single one of them. Instead,
1261 // we test each unique call to AddError() in parser.h. This does not mean
1262 // we are testing every possible error that Parser can generate because
1263 // each variant of the Consume() helper only counts as one unique call to
1264 // AddError().
1265 
1266 typedef ParserTest ParseErrorTest;
1267 
1268 TEST_F(ParseErrorTest, MissingSyntaxIdentifier) {
1270  ExpectHasEarlyExitErrors("message TestMessage {}",
1271  "0:0: File must begin with a syntax statement, e.g. "
1272  "'syntax = \"proto2\";'.\n");
1273  EXPECT_EQ("", parser_->GetSyntaxIdentifier());
1274 }
1275 
1276 TEST_F(ParseErrorTest, UnknownSyntaxIdentifier) {
1277  ExpectHasEarlyExitErrors(
1278  "syntax = \"no_such_syntax\";",
1279  "0:9: Unrecognized syntax identifier \"no_such_syntax\". This parser "
1280  "only recognizes \"proto2\" and \"proto3\".\n");
1281  EXPECT_EQ("no_such_syntax", parser_->GetSyntaxIdentifier());
1282 }
1283 
1284 TEST_F(ParseErrorTest, SimpleSyntaxError) {
1285  ExpectHasErrors("message TestMessage @#$ { blah }",
1286  "0:20: Expected \"{\".\n");
1287  EXPECT_EQ("proto2", parser_->GetSyntaxIdentifier());
1288 }
1289 
1290 TEST_F(ParseErrorTest, ExpectedTopLevel) {
1291  ExpectHasErrors("blah;",
1292  "0:0: Expected top-level statement (e.g. \"message\").\n");
1293 }
1294 
1295 TEST_F(ParseErrorTest, UnmatchedCloseBrace) {
1296  // This used to cause an infinite loop. Doh.
1297  ExpectHasErrors("}",
1298  "0:0: Expected top-level statement (e.g. \"message\").\n"
1299  "0:0: Unmatched \"}\".\n");
1300 }
1301 
1302 // -------------------------------------------------------------------
1303 // Message errors
1304 
1305 TEST_F(ParseErrorTest, MessageMissingName) {
1306  ExpectHasErrors("message {}", "0:8: Expected message name.\n");
1307 }
1308 
1309 TEST_F(ParseErrorTest, MessageMissingBody) {
1310  ExpectHasErrors("message TestMessage;", "0:19: Expected \"{\".\n");
1311 }
1312 
1313 TEST_F(ParseErrorTest, EofInMessage) {
1314  ExpectHasErrors(
1315  "message TestMessage {",
1316  "0:21: Reached end of input in message definition (missing '}').\n");
1317 }
1318 
1319 TEST_F(ParseErrorTest, MissingFieldNumber) {
1320  ExpectHasErrors(
1321  "message TestMessage {\n"
1322  " optional int32 foo;\n"
1323  "}\n",
1324  "1:20: Missing field number.\n");
1325 }
1326 
1327 TEST_F(ParseErrorTest, ExpectedFieldNumber) {
1328  ExpectHasErrors(
1329  "message TestMessage {\n"
1330  " optional int32 foo = ;\n"
1331  "}\n",
1332  "1:23: Expected field number.\n");
1333 }
1334 
1335 TEST_F(ParseErrorTest, FieldNumberOutOfRange) {
1336  ExpectHasErrors(
1337  "message TestMessage {\n"
1338  " optional int32 foo = 0x100000000;\n"
1339  "}\n",
1340  "1:23: Integer out of range.\n");
1341 }
1342 
1343 TEST_F(ParseErrorTest, MissingLabel) {
1344  ExpectHasErrors(
1345  "message TestMessage {\n"
1346  " int32 foo = 1;\n"
1347  "}\n",
1348  "1:2: Expected \"required\", \"optional\", or \"repeated\".\n");
1349 }
1350 
1351 TEST_F(ParseErrorTest, ExpectedOptionName) {
1352  ExpectHasErrors(
1353  "message TestMessage {\n"
1354  " optional uint32 foo = 1 [];\n"
1355  "}\n",
1356  "1:27: Expected identifier.\n");
1357 }
1358 
1359 TEST_F(ParseErrorTest, NonExtensionOptionNameBeginningWithDot) {
1360  ExpectHasErrors(
1361  "message TestMessage {\n"
1362  " optional uint32 foo = 1 [.foo=1];\n"
1363  "}\n",
1364  "1:27: Expected identifier.\n");
1365 }
1366 
1367 TEST_F(ParseErrorTest, DefaultValueTypeMismatch) {
1368  ExpectHasErrors(
1369  "message TestMessage {\n"
1370  " optional uint32 foo = 1 [default=true];\n"
1371  "}\n",
1372  "1:35: Expected integer for field default value.\n");
1373 }
1374 
1375 TEST_F(ParseErrorTest, DefaultValueNotBoolean) {
1376  ExpectHasErrors(
1377  "message TestMessage {\n"
1378  " optional bool foo = 1 [default=blah];\n"
1379  "}\n",
1380  "1:33: Expected \"true\" or \"false\".\n");
1381 }
1382 
1383 TEST_F(ParseErrorTest, DefaultValueNotString) {
1384  ExpectHasErrors(
1385  "message TestMessage {\n"
1386  " optional string foo = 1 [default=1];\n"
1387  "}\n",
1388  "1:35: Expected string for field default value.\n");
1389 }
1390 
1391 TEST_F(ParseErrorTest, DefaultValueUnsignedNegative) {
1392  ExpectHasErrors(
1393  "message TestMessage {\n"
1394  " optional uint32 foo = 1 [default=-1];\n"
1395  "}\n",
1396  "1:36: Unsigned field can't have negative default value.\n");
1397 }
1398 
1399 TEST_F(ParseErrorTest, DefaultValueTooLarge) {
1400  ExpectHasErrors(
1401  "message TestMessage {\n"
1402  " optional int32 foo = 1 [default= 0x80000000];\n"
1403  " optional int32 foo = 1 [default=-0x80000001];\n"
1404  " optional uint32 foo = 1 [default= 0x100000000];\n"
1405  " optional int64 foo = 1 [default= 0x80000000000000000];\n"
1406  " optional int64 foo = 1 [default=-0x80000000000000001];\n"
1407  " optional uint64 foo = 1 [default= 0x100000000000000000];\n"
1408  "}\n",
1409  "1:36: Integer out of range.\n"
1410  "2:36: Integer out of range.\n"
1411  "3:36: Integer out of range.\n"
1412  "4:36: Integer out of range.\n"
1413  "5:36: Integer out of range.\n"
1414  "6:36: Integer out of range.\n");
1415 }
1416 
1417 TEST_F(ParseErrorTest, JsonNameNotString) {
1418  ExpectHasErrors(
1419  "message TestMessage {\n"
1420  " optional string foo = 1 [json_name=1];\n"
1421  "}\n",
1422  "1:37: Expected string for JSON name.\n");
1423 }
1424 
1425 TEST_F(ParseErrorTest, DuplicateJsonName) {
1426  ExpectHasErrors(
1427  "message TestMessage {\n"
1428  " optional uint32 foo = 1 [json_name=\"a\",json_name=\"b\"];\n"
1429  "}\n",
1430  "1:41: Already set option \"json_name\".\n");
1431 }
1432 
1433 TEST_F(ParseErrorTest, EnumValueOutOfRange) {
1434  ExpectHasErrors(
1435  "enum TestEnum {\n"
1436  " HEX_TOO_BIG = 0x80000000;\n"
1437  " HEX_TOO_SMALL = -0x80000001;\n"
1438  " INT_TOO_BIG = 2147483648;\n"
1439  " INT_TOO_SMALL = -2147483649;\n"
1440  "}\n",
1441  "1:19: Integer out of range.\n"
1442  "2:19: Integer out of range.\n"
1443  "3:19: Integer out of range.\n"
1444  "4:19: Integer out of range.\n");
1445 }
1446 
1447 TEST_F(ParseErrorTest, EnumAllowAliasFalse) {
1448  ExpectHasErrors(
1449  "enum Foo {\n"
1450  " option allow_alias = false;\n"
1451  " BAR = 1;\n"
1452  " BAZ = 2;\n"
1453  "}\n",
1454  "5:0: \"Foo\" declares 'option allow_alias = false;' which has no "
1455  "effect. "
1456  "Please remove the declaration.\n");
1457 }
1458 
1459 TEST_F(ParseErrorTest, UnnecessaryEnumAllowAlias) {
1460  ExpectHasErrors(
1461  "enum Foo {\n"
1462  " option allow_alias = true;\n"
1463  " BAR = 1;\n"
1464  " BAZ = 2;\n"
1465  "}\n",
1466  "5:0: \"Foo\" declares support for enum aliases but no enum values share "
1467  "field numbers. Please remove the unnecessary 'option allow_alias = "
1468  "true;' "
1469  "declaration.\n");
1470 }
1471 
1472 TEST_F(ParseErrorTest, DefaultValueMissing) {
1473  ExpectHasErrors(
1474  "message TestMessage {\n"
1475  " optional uint32 foo = 1 [default=];\n"
1476  "}\n",
1477  "1:35: Expected integer for field default value.\n");
1478 }
1479 
1480 TEST_F(ParseErrorTest, DefaultValueForGroup) {
1481  ExpectHasErrors(
1482  "message TestMessage {\n"
1483  " optional group Foo = 1 [default=blah] {}\n"
1484  "}\n",
1485  "1:34: Messages can't have default values.\n");
1486 }
1487 
1488 TEST_F(ParseErrorTest, DuplicateDefaultValue) {
1489  ExpectHasErrors(
1490  "message TestMessage {\n"
1491  " optional uint32 foo = 1 [default=1,default=2];\n"
1492  "}\n",
1493  "1:37: Already set option \"default\".\n");
1494 }
1495 
1496 TEST_F(ParseErrorTest, MissingOneofName) {
1497  ExpectHasErrors(
1498  "message TestMessage {\n"
1499  " oneof {\n"
1500  " int32 bar = 1;\n"
1501  " }\n"
1502  "}\n",
1503  "1:8: Expected oneof name.\n");
1504 }
1505 
1506 TEST_F(ParseErrorTest, LabelInOneof) {
1507  ExpectHasErrors(
1508  "message TestMessage {\n"
1509  " oneof foo {\n"
1510  " optional int32 bar = 1;\n"
1511  " }\n"
1512  "}\n",
1513  "2:4: Fields in oneofs must not have labels (required / optional "
1514  "/ repeated).\n");
1515 }
1516 
1517 TEST_F(ParseErrorTest, MapInOneof) {
1518  ExpectHasErrors(
1519  "message TestMessage {\n"
1520  " oneof foo {\n"
1521  " map<int32, int32> foo_map = 1;\n"
1522  " map message_field = 2;\n" // a normal message field is OK
1523  " }\n"
1524  "}\n",
1525  "2:7: Map fields are not allowed in oneofs.\n");
1526 }
1527 
1528 TEST_F(ParseErrorTest, LabelForMap) {
1529  ExpectHasErrors(
1530  "message TestMessage {\n"
1531  " optional map<int32, int32> int_map = 1;\n"
1532  " required map<int32, int32> int_map2 = 2;\n"
1533  " repeated map<int32, int32> int_map3 = 3;\n"
1534  " optional map map_message = 4;\n" // a normal message field is OK
1535  "}\n",
1536  "1:14: Field labels (required/optional/repeated) are not allowed on map "
1537  "fields.\n"
1538  "2:14: Field labels (required/optional/repeated) are not allowed on map "
1539  "fields.\n"
1540  "3:14: Field labels (required/optional/repeated) are not allowed on map "
1541  "fields.\n");
1542 }
1543 
1544 TEST_F(ParseErrorTest, MalformedMaps) {
1545  ExpectHasErrors(
1546  "message TestMessage {\n"
1547  " map map_message = 1;\n" // a normal message field lacking label
1548  " map<string> str_map = 2;\n"
1549  " map<string,> str_map2 = 3;\n"
1550  " map<,string> str_map3 = 4;\n"
1551  " map<> empty_map = 5;\n"
1552  " map<string,string str_map6 = 6;\n"
1553  "}"
1554  "extend SomeMessage {\n"
1555  " map<int32, int32> int_map = 1;\n"
1556  "}",
1557  "1:6: Expected \"required\", \"optional\", or \"repeated\".\n"
1558  "2:12: Expected \",\".\n"
1559  "3:13: Expected type name.\n"
1560  "4:6: Expected type name.\n"
1561  "5:6: Expected type name.\n"
1562  "6:20: Expected \">\".\n"
1563  "8:5: Map fields are not allowed to be extensions.\n");
1564 }
1565 
1566 TEST_F(ParseErrorTest, GroupNotCapitalized) {
1567  ExpectHasErrors(
1568  "message TestMessage {\n"
1569  " optional group foo = 1 {}\n"
1570  "}\n",
1571  "1:17: Group names must start with a capital letter.\n");
1572 }
1573 
1574 TEST_F(ParseErrorTest, GroupMissingBody) {
1575  ExpectHasErrors(
1576  "message TestMessage {\n"
1577  " optional group Foo = 1;\n"
1578  "}\n",
1579  "1:24: Missing group body.\n");
1580 }
1581 
1582 TEST_F(ParseErrorTest, ExtendingPrimitive) {
1583  ExpectHasErrors("extend int32 { optional string foo = 4; }\n",
1584  "0:7: Expected message type.\n");
1585 }
1586 
1587 TEST_F(ParseErrorTest, ErrorInExtension) {
1588  ExpectHasErrors(
1589  "message Foo { extensions 100 to 199; }\n"
1590  "extend Foo { optional string foo; }\n",
1591  "1:32: Missing field number.\n");
1592 }
1593 
1594 TEST_F(ParseErrorTest, MultipleParseErrors) {
1595  // When a statement has a parse error, the parser should be able to continue
1596  // parsing at the next statement.
1597  ExpectHasErrors(
1598  "message TestMessage {\n"
1599  " optional int32 foo;\n"
1600  " !invalid statement ending in a block { blah blah { blah } blah }\n"
1601  " optional int32 bar = 3 {}\n"
1602  "}\n",
1603  "1:20: Missing field number.\n"
1604  "2:2: Expected \"required\", \"optional\", or \"repeated\".\n"
1605  "2:2: Expected type name.\n"
1606  "3:25: Expected \";\".\n");
1607 }
1608 
1609 TEST_F(ParseErrorTest, EofInAggregateValue) {
1610  ExpectHasErrors(
1611  "option (fileopt) = { i:100\n",
1612  "1:0: Unexpected end of stream while parsing aggregate value.\n");
1613 }
1614 
1615 // -------------------------------------------------------------------
1616 // Enum errors
1617 
1618 TEST_F(ParseErrorTest, EofInEnum) {
1619  ExpectHasErrors(
1620  "enum TestEnum {",
1621  "0:15: Reached end of input in enum definition (missing '}').\n");
1622 }
1623 
1624 TEST_F(ParseErrorTest, EnumValueMissingNumber) {
1625  ExpectHasErrors(
1626  "enum TestEnum {\n"
1627  " FOO;\n"
1628  "}\n",
1629  "1:5: Missing numeric value for enum constant.\n");
1630 }
1631 
1632 TEST_F(ParseErrorTest, EnumReservedStandaloneMaxNotAllowed) {
1633  ExpectHasErrors(
1634  "enum TestEnum {\n"
1635  " FOO = 1;\n"
1636  " reserved max;\n"
1637  "}\n",
1638  "2:11: Expected enum value or number range.\n");
1639 }
1640 
1641 TEST_F(ParseErrorTest, EnumReservedMixNameAndNumber) {
1642  ExpectHasErrors(
1643  "enum TestEnum {\n"
1644  " FOO = 1;\n"
1645  " reserved 10, \"foo\";\n"
1646  "}\n",
1647  "2:15: Expected enum number range.\n");
1648 }
1649 
1650 TEST_F(ParseErrorTest, EnumReservedPositiveNumberOutOfRange) {
1651  ExpectHasErrors(
1652  "enum TestEnum {\n"
1653  "FOO = 1;\n"
1654  " reserved 2147483648;\n"
1655  "}\n",
1656  "2:11: Integer out of range.\n");
1657 }
1658 
1659 TEST_F(ParseErrorTest, EnumReservedNegativeNumberOutOfRange) {
1660  ExpectHasErrors(
1661  "enum TestEnum {\n"
1662  "FOO = 1;\n"
1663  " reserved -2147483649;\n"
1664  "}\n",
1665  "2:12: Integer out of range.\n");
1666 }
1667 
1668 TEST_F(ParseErrorTest, EnumReservedMissingQuotes) {
1669  ExpectHasErrors(
1670  "enum TestEnum {\n"
1671  " FOO = 1;\n"
1672  " reserved foo;\n"
1673  "}\n",
1674  "2:11: Expected enum value or number range.\n");
1675 }
1676 
1677 // -------------------------------------------------------------------
1678 // Reserved field number errors
1679 
1680 TEST_F(ParseErrorTest, ReservedStandaloneMaxNotAllowed) {
1681  ExpectHasErrors(
1682  "message Foo {\n"
1683  " reserved max;\n"
1684  "}\n",
1685  "1:11: Expected field name or number range.\n");
1686 }
1687 
1688 TEST_F(ParseErrorTest, ReservedMixNameAndNumber) {
1689  ExpectHasErrors(
1690  "message Foo {\n"
1691  " reserved 10, \"foo\";\n"
1692  "}\n",
1693  "1:15: Expected field number range.\n");
1694 }
1695 
1696 TEST_F(ParseErrorTest, ReservedMissingQuotes) {
1697  ExpectHasErrors(
1698  "message Foo {\n"
1699  " reserved foo;\n"
1700  "}\n",
1701  "1:11: Expected field name or number range.\n");
1702 }
1703 
1704 TEST_F(ParseErrorTest, ReservedNegativeNumber) {
1705  ExpectHasErrors(
1706  "message Foo {\n"
1707  " reserved -10;\n"
1708  "}\n",
1709  "1:11: Expected field name or number range.\n");
1710 }
1711 
1712 TEST_F(ParseErrorTest, ReservedNumberOutOfRange) {
1713  ExpectHasErrors(
1714  "message Foo {\n"
1715  " reserved 2147483648;\n"
1716  "}\n",
1717  "1:11: Integer out of range.\n");
1718 }
1719 
1720 // -------------------------------------------------------------------
1721 // Service errors
1722 
1723 TEST_F(ParseErrorTest, EofInService) {
1724  ExpectHasErrors(
1725  "service TestService {",
1726  "0:21: Reached end of input in service definition (missing '}').\n");
1727 }
1728 
1729 TEST_F(ParseErrorTest, ServiceMethodPrimitiveParams) {
1730  ExpectHasErrors(
1731  "service TestService {\n"
1732  " rpc Foo(int32) returns (string);\n"
1733  "}\n",
1734  "1:10: Expected message type.\n"
1735  "1:26: Expected message type.\n");
1736 }
1737 
1738 
1739 TEST_F(ParseErrorTest, EofInMethodOptions) {
1740  ExpectHasErrors(
1741  "service TestService {\n"
1742  " rpc Foo(Bar) returns(Bar) {",
1743  "1:29: Reached end of input in method options (missing '}').\n"
1744  "1:29: Reached end of input in service definition (missing '}').\n");
1745 }
1746 
1747 
1748 TEST_F(ParseErrorTest, PrimitiveMethodInput) {
1749  ExpectHasErrors(
1750  "service TestService {\n"
1751  " rpc Foo(int32) returns(Bar);\n"
1752  "}\n",
1753  "1:10: Expected message type.\n");
1754 }
1755 
1756 
1757 TEST_F(ParseErrorTest, MethodOptionTypeError) {
1758  // This used to cause an infinite loop.
1759  ExpectHasErrors(
1760  "message Baz {}\n"
1761  "service Foo {\n"
1762  " rpc Bar(Baz) returns(Baz) { option invalid syntax; }\n"
1763  "}\n",
1764  "2:45: Expected \"=\".\n");
1765 }
1766 
1767 
1768 // -------------------------------------------------------------------
1769 // Import and package errors
1770 
1771 TEST_F(ParseErrorTest, ImportNotQuoted) {
1772  ExpectHasErrors("import foo;\n",
1773  "0:7: Expected a string naming the file to import.\n");
1774 }
1775 
1776 TEST_F(ParseErrorTest, MultiplePackagesInFile) {
1777  ExpectHasErrors(
1778  "package foo;\n"
1779  "package bar;\n",
1780  "1:0: Multiple package definitions.\n");
1781 }
1782 
1783 // ===================================================================
1784 // Test that errors detected by DescriptorPool correctly report line and
1785 // column numbers. We have one test for every call to RecordLocation() in
1786 // parser.cc.
1787 
1788 typedef ParserTest ParserValidationErrorTest;
1789 
1790 TEST_F(ParserValidationErrorTest, PackageNameError) {
1791  // Create another file which defines symbol "foo".
1792  FileDescriptorProto other_file;
1793  other_file.set_name("bar.proto");
1794  other_file.add_message_type()->set_name("foo");
1795  EXPECT_TRUE(pool_.BuildFile(other_file) != NULL);
1796 
1797  // Now try to define it as a package.
1798  ExpectHasValidationErrors(
1799  "package foo.bar;",
1800  "0:0: \"foo\" is already defined (as something other than a package) "
1801  "in file \"bar.proto\".\n");
1802 }
1803 
1804 TEST_F(ParserValidationErrorTest, ImportUnloadedError) {
1805  ExpectHasValidationErrors(
1806  "package test;\n"
1807  "\n"
1808  "import \"unloaded.proto\";",
1809  "2:0: Import \"unloaded.proto\" has not been loaded.\n");
1810 }
1811 
1812 TEST_F(ParserValidationErrorTest, ImportTwice) {
1813  FileDescriptorProto other_file;
1814  other_file.set_name("bar.proto");
1815  other_file.add_message_type()->set_name("foo");
1816  EXPECT_TRUE(pool_.BuildFile(other_file) != nullptr);
1817 
1818  ExpectHasValidationErrors(
1819  "package test;\n"
1820  "\n"
1821  "import \"bar.proto\";\n"
1822  " import \"bar.proto\";",
1823  "3:2: Import \"bar.proto\" was listed twice.\n");
1824 }
1825 
1826 TEST_F(ParserValidationErrorTest, DuplicateFileError) {
1827  FileDescriptorProto other_file;
1828  other_file.set_name("foo.proto");
1829  EXPECT_TRUE(pool_.BuildFile(other_file) != nullptr);
1830 
1831  ExpectHasValidationErrors(
1832  "package test;", "0:0: A file with this name is already in the pool.\n");
1833 }
1834 
1835 TEST_F(ParserValidationErrorTest, MessageNameError) {
1836  ExpectHasValidationErrors(
1837  "message Foo {}\n"
1838  "message Foo {}\n",
1839  "1:8: \"Foo\" is already defined.\n");
1840 }
1841 
1842 TEST_F(ParserValidationErrorTest, FieldNameError) {
1843  ExpectHasValidationErrors(
1844  "message Foo {\n"
1845  " optional int32 bar = 1;\n"
1846  " optional int32 bar = 2;\n"
1847  "}\n",
1848  "2:17: \"bar\" is already defined in \"Foo\".\n");
1849 }
1850 
1851 TEST_F(ParserValidationErrorTest, FieldTypeError) {
1852  ExpectHasValidationErrors(
1853  "message Foo {\n"
1854  " optional Baz bar = 1;\n"
1855  "}\n",
1856  "1:11: \"Baz\" is not defined.\n");
1857 }
1858 
1859 TEST_F(ParserValidationErrorTest, FieldNumberError) {
1860  ExpectHasValidationErrors(
1861  "message Foo {\n"
1862  " optional int32 bar = 0;\n"
1863  "}\n",
1864  "1:23: Field numbers must be positive integers.\n");
1865 }
1866 
1867 TEST_F(ParserValidationErrorTest, FieldExtendeeError) {
1868  ExpectHasValidationErrors("extend Baz { optional int32 bar = 1; }\n",
1869  "0:7: \"Baz\" is not defined.\n");
1870 }
1871 
1872 TEST_F(ParserValidationErrorTest, ExtensionJsonNameError) {
1873  ExpectHasValidationErrors(
1874  "message TestMessage {\n"
1875  " extensions 1 to 100;\n"
1876  "}\n"
1877  "extend TestMessage {\n"
1878  " optional int32 foo = 12 [json_name = \"bar\"];\n"
1879  "}",
1880  "4:27: option json_name is not allowed on extension fields.\n");
1881 }
1882 
1883 TEST_F(ParserValidationErrorTest, FieldDefaultValueError) {
1884  ExpectHasValidationErrors(
1885  "enum Baz { QUX = 1; }\n"
1886  "message Foo {\n"
1887  " optional Baz bar = 1 [default=NO_SUCH_VALUE];\n"
1888  "}\n",
1889  "2:32: Enum type \"Baz\" has no value named \"NO_SUCH_VALUE\".\n");
1890 }
1891 
1892 TEST_F(ParserValidationErrorTest, FileOptionNameError) {
1893  ExpectHasValidationErrors(
1894  "option foo = 5;",
1895  "0:7: Option \"foo\" unknown. Ensure that your proto definition file "
1896  "imports the proto which defines the option.\n");
1897 }
1898 
1899 TEST_F(ParserValidationErrorTest, FileOptionValueError) {
1900  ExpectHasValidationErrors(
1901  "option java_outer_classname = 5;",
1902  "0:30: Value must be quoted string for string option "
1903  "\"google.protobuf.FileOptions.java_outer_classname\".\n");
1904 }
1905 
1906 TEST_F(ParserValidationErrorTest, FieldOptionNameError) {
1907  ExpectHasValidationErrors(
1908  "message Foo {\n"
1909  " optional bool bar = 1 [foo=1];\n"
1910  "}\n",
1911  "1:25: Option \"foo\" unknown. Ensure that your proto definition file "
1912  "imports the proto which defines the option.\n");
1913 }
1914 
1915 TEST_F(ParserValidationErrorTest, FieldOptionValueError) {
1916  ExpectHasValidationErrors(
1917  "message Foo {\n"
1918  " optional int32 bar = 1 [ctype=1];\n"
1919  "}\n",
1920  "1:32: Value must be identifier for enum-valued option "
1921  "\"google.protobuf.FieldOptions.ctype\".\n");
1922 }
1923 
1924 TEST_F(ParserValidationErrorTest, ExtensionRangeNumberError) {
1925  ExpectHasValidationErrors(
1926  "message Foo {\n"
1927  " extensions 0;\n"
1928  "}\n",
1929  "1:13: Extension numbers must be positive integers.\n");
1930 }
1931 
1932 TEST_F(ParserValidationErrorTest, Proto3ExtensionError) {
1933  ExpectHasValidationErrors(
1934  "syntax = 'proto3';\n"
1935  "message Foo { \n"
1936  " extensions 100 to 199;\n"
1937  "}\n"
1938  "extend Foo { string foo = 101; }\n",
1939  "4:7: Extensions in proto3 are only allowed for defining options.\n"
1940  "2:13: Extension ranges are not allowed in proto3.\n");
1941 }
1942 
1943 TEST_F(ParserValidationErrorTest, Proto3MessageSet) {
1944  ExpectHasValidationErrors(
1945  "syntax = 'proto3';\n"
1946  "message Foo { \n"
1947  " option message_set_wire_format = true;\n"
1948  "}\n",
1949  "1:8: MessageSet is not supported in proto3.\n");
1950 }
1951 
1952 TEST_F(ParserValidationErrorTest, Proto3Required) {
1953  ExpectHasValidationErrors(
1954  "syntax = 'proto3';\n"
1955  "message Foo { \n"
1956  " required int32 field = 1;"
1957  "}\n",
1958  "2:11: Required fields are not allowed in proto3.\n");
1959 }
1960 
1961 TEST_F(ParserValidationErrorTest, Proto3Default) {
1962  ExpectHasValidationErrors(
1963  "syntax = 'proto3';\n"
1964  "message Foo { \n"
1965  " int32 field = 1 [default = 12];"
1966  "}\n",
1967  "2:29: Explicit default values are not allowed in proto3.\n");
1968 }
1969 
1970 TEST_F(ParserValidationErrorTest, Proto3JsonConflictError) {
1971  ExpectHasValidationErrors(
1972  "syntax = 'proto3';\n"
1973  "message TestMessage {\n"
1974  " uint32 foo = 1;\n"
1975  " uint32 Foo = 2;\n"
1976  "}\n",
1977  "3:9: The JSON camel-case name of field \"Foo\" conflicts with field "
1978  "\"foo\". This is not allowed in proto3.\n");
1979 }
1980 
1981 TEST_F(ParserValidationErrorTest, EnumNameError) {
1982  ExpectHasValidationErrors(
1983  "enum Foo {A = 1;}\n"
1984  "enum Foo {B = 1;}\n",
1985  "1:5: \"Foo\" is already defined.\n");
1986 }
1987 
1988 TEST_F(ParserValidationErrorTest, Proto3EnumError) {
1989  ExpectHasValidationErrors(
1990  "syntax = 'proto3';\n"
1991  "enum Foo {A = 1;}\n",
1992  "1:14: The first enum value must be zero in proto3.\n");
1993 }
1994 
1995 TEST_F(ParserValidationErrorTest, EnumValueNameError) {
1996  ExpectHasValidationErrors(
1997  "enum Foo {\n"
1998  " BAR = 1;\n"
1999  " BAR = 1;\n"
2000  "}\n",
2001  "2:2: \"BAR\" is already defined.\n");
2002 }
2003 
2004 TEST_F(ParserValidationErrorTest, EnumValueAliasError) {
2005  ExpectHasValidationErrors(
2006  "enum Foo {\n"
2007  " BAR = 1;\n"
2008  " BAZ = 1;\n"
2009  "}\n",
2010  "2:8: \"BAZ\" uses the same enum value as \"BAR\". If this is "
2011  "intended, set 'option allow_alias = true;' to the enum "
2012  "definition.\n");
2013 }
2014 
2015 TEST_F(ParserValidationErrorTest, ExplicitlyMapEntryError) {
2016  ExpectHasValidationErrors(
2017  "message Foo {\n"
2018  " message ValueEntry {\n"
2019  " option map_entry = true;\n"
2020  " optional int32 key = 1;\n"
2021  " optional int32 value = 2;\n"
2022  " extensions 99 to 999;\n"
2023  " }\n"
2024  " repeated ValueEntry value = 1;\n"
2025  "}",
2026  "7:11: map_entry should not be set explicitly. Use "
2027  "map<KeyType, ValueType> instead.\n");
2028 }
2029 
2030 TEST_F(ParserValidationErrorTest, ServiceNameError) {
2031  ExpectHasValidationErrors(
2032  "service Foo {}\n"
2033  "service Foo {}\n",
2034  "1:8: \"Foo\" is already defined.\n");
2035 }
2036 
2037 TEST_F(ParserValidationErrorTest, MethodNameError) {
2038  ExpectHasValidationErrors(
2039  "message Baz {}\n"
2040  "service Foo {\n"
2041  " rpc Bar(Baz) returns(Baz);\n"
2042  " rpc Bar(Baz) returns(Baz);\n"
2043  "}\n",
2044  "3:6: \"Bar\" is already defined in \"Foo\".\n");
2045 }
2046 
2047 
2048 TEST_F(ParserValidationErrorTest, MethodInputTypeError) {
2049  ExpectHasValidationErrors(
2050  "message Baz {}\n"
2051  "service Foo {\n"
2052  " rpc Bar(Qux) returns(Baz);\n"
2053  "}\n",
2054  "2:10: \"Qux\" is not defined.\n");
2055 }
2056 
2057 
2058 TEST_F(ParserValidationErrorTest, MethodOutputTypeError) {
2059  ExpectHasValidationErrors(
2060  "message Baz {}\n"
2061  "service Foo {\n"
2062  " rpc Bar(Baz) returns(Qux);\n"
2063  "}\n",
2064  "2:23: \"Qux\" is not defined.\n");
2065 }
2066 
2067 
2068 TEST_F(ParserValidationErrorTest, ResolvedUndefinedError) {
2069  // Create another file which defines symbol ".base.bar".
2070  FileDescriptorProto other_file;
2071  other_file.set_name("base.proto");
2072  other_file.set_package("base");
2073  other_file.add_message_type()->set_name("bar");
2074  EXPECT_TRUE(pool_.BuildFile(other_file) != NULL);
2075 
2076  // Define "foo.base" and try "base.bar".
2077  // "base.bar" is resolved to "foo.base.bar" which is not defined.
2078  ExpectHasValidationErrors(
2079  "package foo.base;\n"
2080  "import \"base.proto\";\n"
2081  "message qux {\n"
2082  " optional base.bar baz = 1;\n"
2083  " optional .base.bar quz = 2;\n"
2084  "}\n",
2085  "3:11: \"base.bar\" is resolved to \"foo.base.bar\","
2086  " which is not defined. The innermost scope is searched first "
2087  "in name resolution. Consider using a leading '.'(i.e., \".base.bar\")"
2088  " to start from the outermost scope.\n");
2089 }
2090 
2091 TEST_F(ParserValidationErrorTest, ResovledUndefinedOptionError) {
2092  // Build descriptor message in test pool
2094  DescriptorProto::descriptor()->file()->CopyTo(&descriptor_proto);
2095  ASSERT_TRUE(pool_.BuildFile(descriptor_proto) != NULL);
2096 
2097  // base2.proto:
2098  // package baz
2099  // import net/proto2/proto/descriptor.proto
2100  // message Bar { optional int32 foo = 1; }
2101  // extend FileOptions { optional Bar bar = 7672757; }
2102  FileDescriptorProto other_file;
2103  other_file.set_name("base2.proto");
2104  other_file.set_package("baz");
2105  other_file.add_dependency();
2106  other_file.set_dependency(0, descriptor_proto.name());
2107 
2108  DescriptorProto* message(other_file.add_message_type());
2109  message->set_name("Bar");
2110  FieldDescriptorProto* field(message->add_field());
2111  field->set_name("foo");
2112  field->set_number(1);
2115 
2117  extension->set_name("bar");
2118  extension->set_number(7672757);
2121  extension->set_type_name("Bar");
2122  extension->set_extendee("google.protobuf.FileOptions");
2123 
2124  EXPECT_TRUE(pool_.BuildFile(other_file) != NULL);
2125 
2126  // qux.proto:
2127  // package qux.baz
2128  // option (baz.bar).foo = 1;
2129  //
2130  // Although "baz.bar" is already defined, the lookup code will try
2131  // "qux.baz.bar", since it's the match from the innermost scope,
2132  // which will cause a symbol not defined error.
2133  ExpectHasValidationErrors(
2134  "package qux.baz;\n"
2135  "import \"base2.proto\";\n"
2136  "option (baz.bar).foo = 1;\n",
2137  "2:7: Option \"(baz.bar)\" is resolved to \"(qux.baz.bar)\","
2138  " which is not defined. The innermost scope is searched first "
2139  "in name resolution. Consider using a leading '.'(i.e., \"(.baz.bar)\")"
2140  " to start from the outermost scope.\n");
2141 }
2142 
2143 // ===================================================================
2144 // Test that the output from FileDescriptor::DebugString() (and all other
2145 // descriptor types) is parseable, and results in the same Descriptor
2146 // definitions again afoter parsing (note, however, that the order of messages
2147 // cannot be guaranteed to be the same)
2148 
2149 typedef ParserTest ParseDescriptorDebugTest;
2150 
2151 class CompareDescriptorNames {
2152  public:
2153  bool operator()(const DescriptorProto* left,
2154  const DescriptorProto* right) const {
2155  return left->name() < right->name();
2156  }
2157 };
2158 
2159 // Sorts nested DescriptorProtos of a DescriptoProto, by name.
2160 void SortMessages(DescriptorProto* descriptor_proto) {
2161  int size = descriptor_proto->nested_type_size();
2162  // recursively sort; we can't guarantee the order of nested messages either
2163  for (int i = 0; i < size; ++i) {
2164  SortMessages(descriptor_proto->mutable_nested_type(i));
2165  }
2166  DescriptorProto** data =
2167  descriptor_proto->mutable_nested_type()->mutable_data();
2168  std::sort(data, data + size, CompareDescriptorNames());
2169 }
2170 
2171 // Sorts DescriptorProtos belonging to a FileDescriptorProto, by name.
2172 void SortMessages(FileDescriptorProto* file_descriptor_proto) {
2173  int size = file_descriptor_proto->message_type_size();
2174  // recursively sort; we can't guarantee the order of nested messages either
2175  for (int i = 0; i < size; ++i) {
2176  SortMessages(file_descriptor_proto->mutable_message_type(i));
2177  }
2178  DescriptorProto** data =
2179  file_descriptor_proto->mutable_message_type()->mutable_data();
2180  std::sort(data, data + size, CompareDescriptorNames());
2181 }
2182 
2183 // Strips the message and enum field type names for comparison purpose only.
2184 void StripFieldTypeName(DescriptorProto* proto) {
2185  for (int i = 0; i < proto->field_size(); ++i) {
2186  std::string type_name = proto->field(i).type_name();
2187  std::string::size_type pos = type_name.find_last_of('.');
2188  if (pos != std::string::npos) {
2189  proto->mutable_field(i)->mutable_type_name()->assign(
2190  type_name.begin() + pos + 1, type_name.end());
2191  }
2192  }
2193  for (int i = 0; i < proto->nested_type_size(); ++i) {
2194  StripFieldTypeName(proto->mutable_nested_type(i));
2195  }
2196 }
2197 
2198 void StripFieldTypeName(FileDescriptorProto* file_proto) {
2199  for (int i = 0; i < file_proto->message_type_size(); ++i) {
2200  StripFieldTypeName(file_proto->mutable_message_type(i));
2201  }
2202 }
2203 
2204 TEST_F(ParseDescriptorDebugTest, TestAllDescriptorTypes) {
2205  const FileDescriptor* original_file =
2207  FileDescriptorProto expected;
2208  original_file->CopyTo(&expected);
2209 
2210  // Get the DebugString of the unittest.proto FileDecriptor, which includes
2211  // all other descriptor types
2212  std::string debug_string = original_file->DebugString();
2213 
2214  // Parse the debug string
2215  SetupParser(debug_string.c_str());
2216  FileDescriptorProto parsed;
2217  parser_->Parse(input_.get(), &parsed);
2218  EXPECT_EQ(io::Tokenizer::TYPE_END, input_->current().type);
2219  ASSERT_EQ("", error_collector_.text_) << "Failed to parse:\n" << debug_string;
2220 
2221  // We now have a FileDescriptorProto, but to compare with the expected we
2222  // need to link to a FileDecriptor, then output back to a proto. We'll
2223  // also need to give it the same name as the original.
2224  parsed.set_name(
2225  TestUtil::MaybeTranslatePath("net/proto2/internal/unittest.proto"));
2226  // We need the imported dependency before we can build our parsed proto
2227  const FileDescriptor* public_import =
2229  FileDescriptorProto public_import_proto;
2230  public_import->CopyTo(&public_import_proto);
2231  ASSERT_TRUE(pool_.BuildFile(public_import_proto) != NULL);
2232  const FileDescriptor* import =
2234  FileDescriptorProto import_proto;
2235  import->CopyTo(&import_proto);
2236  ASSERT_TRUE(pool_.BuildFile(import_proto) != NULL);
2237  const FileDescriptor* actual = pool_.BuildFile(parsed);
2238  parsed.Clear();
2239  ASSERT_TRUE(actual != NULL) << "Failed to validate:\n" << debug_string;
2240  actual->CopyTo(&parsed);
2241  ASSERT_TRUE(actual != NULL);
2242 
2243  // The messages might be in different orders, making them hard to compare.
2244  // So, sort the messages in the descriptor protos (including nested messages,
2245  // recursively).
2246  SortMessages(&expected);
2247  SortMessages(&parsed);
2248 
2249  // I really wanted to use StringDiff here for the debug output on fail,
2250  // but the strings are too long for it, and if I increase its max size,
2251  // we get a memory allocation failure :(
2252  EXPECT_EQ(expected.DebugString(), parsed.DebugString());
2253 }
2254 
2255 TEST_F(ParseDescriptorDebugTest, TestCustomOptions) {
2256  const FileDescriptor* original_file =
2258  FileDescriptorProto expected;
2259  original_file->CopyTo(&expected);
2260 
2261  std::string debug_string = original_file->DebugString();
2262 
2263  // Parse the debug string
2264  SetupParser(debug_string.c_str());
2265  FileDescriptorProto parsed;
2266  parser_->Parse(input_.get(), &parsed);
2267  EXPECT_EQ(io::Tokenizer::TYPE_END, input_->current().type);
2268  ASSERT_EQ("", error_collector_.text_);
2269 
2270  // We now have a FileDescriptorProto, but to compare with the expected we
2271  // need to link to a FileDecriptor, then output back to a proto. We'll
2272  // also need to give it the same name as the original.
2273  parsed.set_name(original_file->name());
2274 
2275  // unittest_custom_options.proto depends on descriptor.proto.
2276  const FileDescriptor* import = FileDescriptorProto::descriptor()->file();
2277  FileDescriptorProto import_proto;
2278  import->CopyTo(&import_proto);
2279  ASSERT_TRUE(pool_.BuildFile(import_proto) != NULL);
2280 
2281  FileDescriptorProto any_import;
2282  google::protobuf::Any::descriptor()->file()->CopyTo(&any_import);
2283  ASSERT_TRUE(pool_.BuildFile(any_import) != nullptr);
2284 
2285  const FileDescriptor* actual = pool_.BuildFile(parsed);
2286  ASSERT_TRUE(actual != NULL);
2287  parsed.Clear();
2288  actual->CopyTo(&parsed);
2289 
2290  // The messages might be in different orders, making them hard to compare.
2291  // So, sort the messages in the descriptor protos (including nested messages,
2292  // recursively).
2293  SortMessages(&expected);
2294  SortMessages(&parsed);
2295 
2296  EXPECT_EQ(expected.DebugString(), parsed.DebugString());
2297 }
2298 
2299 // Ensure that DebugStringWithOptions(), with |include_comments| set to true,
2300 // includes comments from the original parser input in all of the appropriate
2301 // places.
2302 TEST_F(ParseDescriptorDebugTest, TestCommentsInDebugString) {
2303  SetupParser(
2304  "// Detached comment before syntax.\n"
2305  "\n"
2306  "// Syntax comment.\n"
2307  "syntax = \"proto2\";\n"
2308  "\n"
2309  "// Detached comment before package.\n"
2310  "\n"
2311  "// Package comment.\n"
2312  "package comment_test;\n"
2313  "\n"
2314  "// Detached comment before TestMessage1.\n"
2315  "\n"
2316  "// Message comment.\n"
2317  "//\n"
2318  "// More detail in message comment.\n"
2319  "message TestMessage1 {\n"
2320  "\n"
2321  " // Detached comment before foo.\n"
2322  "\n"
2323  " // Field comment.\n"
2324  " optional int32 foo = 1;\n"
2325  "\n"
2326  " // Detached comment before NestedMessage.\n"
2327  "\n"
2328  " // Nested-message comment.\n"
2329  " message NestedMessage {\n"
2330  " optional int32 bar = 1;\n"
2331  " }\n"
2332  "}\n"
2333  "\n"
2334  "// Detached comment before MyEnumType.\n"
2335  "\n"
2336  "// Enum comment.\n"
2337  "enum MyEnumType {\n"
2338  "\n"
2339  " // Detached comment before ASDF.\n"
2340  "\n"
2341  " // Enum-value comment.\n"
2342  " ASDF = 1;\n"
2343  "}\n"
2344  "\n"
2345  "// Detached comment before MyService.\n"
2346  "\n"
2347  "// Service comment.\n"
2348  "service MyService {\n"
2349  "\n"
2350  " // Detached comment before MyRPCCall.\n"
2351  "\n"
2352  " // RPC comment.\n"
2353  " rpc MyRPCCall(TestMessage1) returns (TestMessage1) { }\n"
2354  "}\n");
2355 
2356  FileDescriptorProto parsed_desc;
2357  parsed_desc.set_name("foo.proto");
2358  SourceLocationTable source_locations;
2359  parser_->RecordSourceLocationsTo(&source_locations);
2360  parser_->Parse(input_.get(), &parsed_desc);
2361  EXPECT_EQ(io::Tokenizer::TYPE_END, input_->current().type);
2362  ASSERT_EQ("", error_collector_.text_);
2363 
2364  // We need to import the FileDescriptorProto to get a FileDescriptor.
2365  MockValidationErrorCollector collector(source_locations, &error_collector_);
2366  const FileDescriptor* descriptor =
2367  pool_.BuildFileCollectingErrors(parsed_desc, &collector);
2368  ASSERT_TRUE(descriptor != NULL);
2369 
2370  // Ensure that each of the comments appears somewhere in the DebugString().
2371  // We don't test the exact comment placement or formatting, because we do not
2372  // want to be too fragile here.
2373  const char* expected_comments[] = {
2374  "Detached comment before syntax.",
2375  "Syntax comment.",
2376  "Detached comment before package.",
2377  "Package comment.",
2378  "Detached comment before TestMessage1.",
2379  "Message comment.",
2380  "More detail in message comment.",
2381  "Detached comment before foo.",
2382  "Field comment",
2383  "Detached comment before NestedMessage.",
2384  "Nested-message comment",
2385  "Detached comment before MyEnumType.",
2386  "Enum comment",
2387  "Detached comment before ASDF.",
2388  "Enum-value comment",
2389  "Detached comment before MyService.",
2390  "Service comment",
2391  "Detached comment before MyRPCCall.",
2392  "RPC comment",
2393  };
2394 
2395  DebugStringOptions debug_string_options;
2396  debug_string_options.include_comments = true;
2397 
2398  {
2399  const std::string debug_string =
2400  descriptor->DebugStringWithOptions(debug_string_options);
2401 
2402  for (int i = 0; i < GOOGLE_ARRAYSIZE(expected_comments); ++i) {
2403  std::string::size_type found_pos =
2404  debug_string.find(expected_comments[i]);
2405  EXPECT_TRUE(found_pos != std::string::npos)
2406  << "\"" << expected_comments[i] << "\" not found.";
2407  }
2408 
2409  // Result of DebugStringWithOptions should be parseable.
2410  SetupParser(debug_string.c_str());
2411  FileDescriptorProto parsed;
2412  parser_->Parse(input_.get(), &parsed);
2413  EXPECT_EQ(io::Tokenizer::TYPE_END, input_->current().type);
2414  ASSERT_EQ("", error_collector_.text_) << "Failed to parse:\n"
2415  << debug_string;
2416  }
2417 
2418 }
2419 
2420 TEST_F(ParseDescriptorDebugTest, TestMaps) {
2421  SetupParser(
2422  "syntax = \"proto3\"; "
2423  "message Foo { "
2424  " message Bar { } "
2425  " map<int32, Bar> enum_message_map = 1; "
2426  " map<string, float> primitive_map = 2; "
2427  "} ");
2428  FileDescriptorProto original;
2429  EXPECT_TRUE(parser_->Parse(input_.get(), &original));
2430  original.set_name("foo.proto");
2431  const FileDescriptor* file = pool_.BuildFile(original);
2432  ASSERT_TRUE(file != NULL);
2433 
2434  // Make sure the debug string uses map syntax and does not have the auto
2435  // generated entry.
2436  std::string debug_string = file->DebugString();
2437  EXPECT_TRUE(debug_string.find("map<") != std::string::npos);
2438  EXPECT_TRUE(debug_string.find("option map_entry") == std::string::npos);
2439  EXPECT_TRUE(debug_string.find("MapEntry") == std::string::npos);
2440 
2441  // Make sure the descriptor debug string is parsable.
2442  FileDescriptorProto parsed;
2443  SetupParser(debug_string.c_str());
2444  parsed.set_name("foo.proto");
2445  ASSERT_TRUE(parser_->Parse(input_.get(), &parsed));
2446 
2447  original.clear_source_code_info();
2448  parsed.clear_source_code_info();
2449  StripFieldTypeName(&original);
2450  StripFieldTypeName(&parsed);
2451  EXPECT_EQ(original.DebugString(), parsed.DebugString());
2452 }
2453 
2454 // ===================================================================
2455 // SourceCodeInfo tests.
2456 
2457 // Follows a path -- as defined by SourceCodeInfo.Location.path -- from a
2458 // message to a particular sub-field.
2459 // * If the target is itself a message, sets *output_message to point at it,
2460 // *output_field to NULL, and *output_index to -1.
2461 // * Otherwise, if the target is an element of a repeated field, sets
2462 // *output_message to the containing message, *output_field to the descriptor
2463 // of the field, and *output_index to the index of the element.
2464 // * Otherwise, the target is a field (possibly a repeated field, but not any
2465 // one element). Sets *output_message to the containing message,
2466 // *output_field to the descriptor of the field, and *output_index to -1.
2467 // Returns true if the path was valid, false otherwise. A gTest failure is
2468 // recorded before returning false.
2469 bool FollowPath(const Message& root, const int* path_begin, const int* path_end,
2470  const Message** output_message,
2471  const FieldDescriptor** output_field, int* output_index) {
2472  if (path_begin == path_end) {
2473  // Path refers to this whole message.
2474  *output_message = &root;
2475  *output_field = NULL;
2476  *output_index = -1;
2477  return true;
2478  }
2479 
2480  const Descriptor* descriptor = root.GetDescriptor();
2481  const Reflection* reflection = root.GetReflection();
2482 
2483  const FieldDescriptor* field = descriptor->FindFieldByNumber(*path_begin);
2484 
2485  if (field == NULL) {
2486  ADD_FAILURE() << descriptor->name()
2487  << " has no field number: " << *path_begin;
2488  return false;
2489  }
2490 
2491  ++path_begin;
2492 
2493  if (field->is_repeated()) {
2494  if (path_begin == path_end) {
2495  // Path refers to the whole repeated field.
2496  *output_message = &root;
2497  *output_field = field;
2498  *output_index = -1;
2499  return true;
2500  }
2501 
2502  int index = *path_begin++;
2503  int size = reflection->FieldSize(root, field);
2504 
2505  if (index >= size) {
2506  ADD_FAILURE() << descriptor->name() << "." << field->name()
2507  << " has size " << size
2508  << ", but path contained index: " << index;
2509  return false;
2510  }
2511 
2512  if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
2513  // Descend into child message.
2514  const Message& child = reflection->GetRepeatedMessage(root, field, index);
2515  return FollowPath(child, path_begin, path_end, output_message,
2516  output_field, output_index);
2517  } else if (path_begin == path_end) {
2518  // Path refers to this element.
2519  *output_message = &root;
2520  *output_field = field;
2521  *output_index = index;
2522  return true;
2523  } else {
2524  ADD_FAILURE() << descriptor->name() << "." << field->name()
2525  << " is not a message; cannot descend into it.";
2526  return false;
2527  }
2528  } else {
2529  if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
2530  const Message& child = reflection->GetMessage(root, field);
2531  return FollowPath(child, path_begin, path_end, output_message,
2532  output_field, output_index);
2533  } else if (path_begin == path_end) {
2534  // Path refers to this field.
2535  *output_message = &root;
2536  *output_field = field;
2537  *output_index = -1;
2538  return true;
2539  } else {
2540  ADD_FAILURE() << descriptor->name() << "." << field->name()
2541  << " is not a message; cannot descend into it.";
2542  return false;
2543  }
2544  }
2545 }
2546 
2547 // Check if two spans are equal.
2548 bool CompareSpans(const RepeatedField<int>& span1,
2549  const RepeatedField<int>& span2) {
2550  if (span1.size() != span2.size()) return false;
2551  for (int i = 0; i < span1.size(); i++) {
2552  if (span1.Get(i) != span2.Get(i)) return false;
2553  }
2554  return true;
2555 }
2556 
2557 // Test fixture for source info tests, which check that source locations are
2558 // recorded correctly in FileDescriptorProto.source_code_info.location.
2559 class SourceInfoTest : public ParserTest {
2560  protected:
2561  // The parsed file (initialized by Parse()).
2563 
2564  // Parse the given text as a .proto file and populate the spans_ map with
2565  // all the source location spans in its SourceCodeInfo table.
2566  bool Parse(const char* text) {
2567  ExtractMarkers(text);
2568  SetupParser(text_without_markers_.c_str());
2569  if (!parser_->Parse(input_.get(), &file_)) {
2570  return false;
2571  }
2572 
2573  const SourceCodeInfo& source_info = file_.source_code_info();
2574  for (int i = 0; i < source_info.location_size(); i++) {
2575  const SourceCodeInfo::Location& location = source_info.location(i);
2576  const Message* descriptor_proto = NULL;
2577  const FieldDescriptor* field = NULL;
2578  int index = 0;
2579  if (!FollowPath(file_, location.path().begin(), location.path().end(),
2580  &descriptor_proto, &field, &index)) {
2581  return false;
2582  }
2583 
2584  spans_.insert(
2585  std::make_pair(SpanKey(*descriptor_proto, field, index), &location));
2586  }
2587 
2588  return true;
2589  }
2590 
2591  void TearDown() override {
2592  EXPECT_TRUE(spans_.empty()) << "Forgot to call HasSpan() for:\n"
2593  << spans_.begin()->second->DebugString();
2594  }
2595 
2596  // -----------------------------------------------------------------
2597  // HasSpan() checks that the span of source code delimited by the given
2598  // tags (comments) correspond via the SourceCodeInfo table to the given
2599  // part of the FileDescriptorProto. (If unclear, look at the actual tests;
2600  // it should quickly become obvious.)
2601 
2602  bool HasSpan(char start_marker, char end_marker,
2603  const Message& descriptor_proto) {
2604  return HasSpanWithComment(start_marker, end_marker, descriptor_proto, NULL,
2605  -1, NULL, NULL, NULL);
2606  }
2607 
2608  bool HasSpanWithComment(char start_marker, char end_marker,
2609  const Message& descriptor_proto,
2610  const char* expected_leading_comments,
2611  const char* expected_trailing_comments,
2612  const char* expected_leading_detached_comments) {
2613  return HasSpanWithComment(start_marker, end_marker, descriptor_proto, NULL,
2614  -1, expected_leading_comments,
2615  expected_trailing_comments,
2616  expected_leading_detached_comments);
2617  }
2618 
2619  bool HasSpan(char start_marker, char end_marker,
2620  const Message& descriptor_proto, const std::string& field_name) {
2621  return HasSpan(start_marker, end_marker, descriptor_proto, field_name, -1);
2622  }
2623 
2624  bool HasSpan(char start_marker, char end_marker,
2625  const Message& descriptor_proto, const std::string& field_name,
2626  int index) {
2627  return HasSpan(start_marker, end_marker, descriptor_proto, field_name,
2628  index, NULL, NULL, NULL);
2629  }
2630 
2631  bool HasSpan(char start_marker, char end_marker,
2632  const Message& descriptor_proto, const std::string& field_name,
2633  int index, const char* expected_leading_comments,
2634  const char* expected_trailing_comments,
2635  const char* expected_leading_detached_comments) {
2636  const FieldDescriptor* field =
2637  descriptor_proto.GetDescriptor()->FindFieldByName(field_name);
2638  if (field == NULL) {
2639  ADD_FAILURE() << descriptor_proto.GetDescriptor()->name()
2640  << " has no such field: " << field_name;
2641  return false;
2642  }
2643 
2644  return HasSpanWithComment(start_marker, end_marker, descriptor_proto, field,
2645  index, expected_leading_comments,
2646  expected_trailing_comments,
2647  expected_leading_detached_comments);
2648  }
2649 
2650  bool HasSpan(const Message& descriptor_proto) {
2651  return HasSpanWithComment('\0', '\0', descriptor_proto, NULL, -1, NULL,
2652  NULL, NULL);
2653  }
2654 
2655  bool HasSpan(const Message& descriptor_proto, const std::string& field_name) {
2656  return HasSpan('\0', '\0', descriptor_proto, field_name, -1);
2657  }
2658 
2659  bool HasSpanWithComment(char start_marker, char end_marker,
2660  const Message& descriptor_proto,
2661  const FieldDescriptor* field, int index,
2662  const char* expected_leading_comments,
2663  const char* expected_trailing_comments,
2664  const char* expected_leading_detached_comments) {
2665  std::pair<SpanMap::iterator, SpanMap::iterator> range =
2666  spans_.equal_range(SpanKey(descriptor_proto, field, index));
2667 
2668  if (start_marker == '\0') {
2669  if (range.first == range.second) {
2670  return false;
2671  } else {
2672  spans_.erase(range.first);
2673  return true;
2674  }
2675  } else {
2676  std::pair<int, int> start_pos = FindOrDie(markers_, start_marker);
2677  std::pair<int, int> end_pos = FindOrDie(markers_, end_marker);
2678 
2679  RepeatedField<int> expected_span;
2680  expected_span.Add(start_pos.first);
2681  expected_span.Add(start_pos.second);
2682  if (end_pos.first != start_pos.first) {
2683  expected_span.Add(end_pos.first);
2684  }
2685  expected_span.Add(end_pos.second);
2686 
2687  for (SpanMap::iterator iter = range.first; iter != range.second; ++iter) {
2688  if (CompareSpans(expected_span, iter->second->span())) {
2689  if (expected_leading_comments == NULL) {
2690  EXPECT_FALSE(iter->second->has_leading_comments());
2691  } else {
2692  EXPECT_TRUE(iter->second->has_leading_comments());
2693  EXPECT_EQ(expected_leading_comments,
2694  iter->second->leading_comments());
2695  }
2696  if (expected_trailing_comments == NULL) {
2697  EXPECT_FALSE(iter->second->has_trailing_comments());
2698  } else {
2699  EXPECT_TRUE(iter->second->has_trailing_comments());
2700  EXPECT_EQ(expected_trailing_comments,
2701  iter->second->trailing_comments());
2702  }
2703  if (expected_leading_detached_comments == NULL) {
2704  EXPECT_EQ(0, iter->second->leading_detached_comments_size());
2705  } else {
2706  EXPECT_EQ(
2707  expected_leading_detached_comments,
2708  Join(iter->second->leading_detached_comments(), "\n"));
2709  }
2710 
2711  spans_.erase(iter);
2712  return true;
2713  }
2714  }
2715 
2716  return false;
2717  }
2718  }
2719 
2720  private:
2721  struct SpanKey {
2724  int index;
2725 
2726  inline SpanKey() {}
2727  inline SpanKey(const Message& descriptor_proto_param,
2728  const FieldDescriptor* field_param, int index_param)
2729  : descriptor_proto(&descriptor_proto_param),
2730  field(field_param),
2731  index(index_param) {}
2732 
2733  inline bool operator<(const SpanKey& other) const {
2734  if (descriptor_proto < other.descriptor_proto) return true;
2735  if (descriptor_proto > other.descriptor_proto) return false;
2736  if (field < other.field) return true;
2737  if (field > other.field) return false;
2738  return index < other.index;
2739  }
2740  };
2741 
2742  typedef std::multimap<SpanKey, const SourceCodeInfo::Location*> SpanMap;
2743  SpanMap spans_;
2744  std::map<char, std::pair<int, int> > markers_;
2746 
2747  void ExtractMarkers(const char* text) {
2748  markers_.clear();
2749  text_without_markers_.clear();
2750  int line = 0;
2751  int column = 0;
2752  while (*text != '\0') {
2753  if (*text == '$') {
2754  ++text;
2755  GOOGLE_CHECK_NE('\0', *text);
2756  if (*text == '$') {
2757  text_without_markers_ += '$';
2758  ++column;
2759  } else {
2760  markers_[*text] = std::make_pair(line, column);
2761  ++text;
2762  GOOGLE_CHECK_EQ('$', *text);
2763  }
2764  } else if (*text == '\n') {
2765  ++line;
2766  column = 0;
2768  } else {
2770  ++column;
2771  }
2772  ++text;
2773  }
2774  }
2775 };
2776 
2777 TEST_F(SourceInfoTest, BasicFileDecls) {
2778  EXPECT_TRUE(
2779  Parse("$a$syntax = \"proto2\";$i$\n"
2780  "$b$package foo.bar;$c$\n"
2781  "$d$import \"baz.proto\";$e$\n"
2782  "$f$import\"qux.proto\";$h$\n"
2783  "$j$import $k$public$l$ \"bar.proto\";$m$\n"
2784  "$n$import $o$weak$p$ \"bar.proto\";$q$\n"
2785  "\n"
2786  "// comment ignored\n"));
2787 
2788  EXPECT_TRUE(HasSpan('a', 'q', file_));
2789  EXPECT_TRUE(HasSpan('b', 'c', file_, "package"));
2790  EXPECT_TRUE(HasSpan('d', 'e', file_, "dependency", 0));
2791  EXPECT_TRUE(HasSpan('f', 'h', file_, "dependency", 1));
2792  EXPECT_TRUE(HasSpan('j', 'm', file_, "dependency", 2));
2793  EXPECT_TRUE(HasSpan('k', 'l', file_, "public_dependency", 0));
2794  EXPECT_TRUE(HasSpan('n', 'q', file_, "dependency", 3));
2795  EXPECT_TRUE(HasSpan('o', 'p', file_, "weak_dependency", 0));
2796  EXPECT_TRUE(HasSpan('a', 'i', file_, "syntax"));
2797 }
2798 
2799 TEST_F(SourceInfoTest, Messages) {
2800  EXPECT_TRUE(
2801  Parse("$a$message $b$Foo$c$ {}$d$\n"
2802  "$e$message $f$Bar$g$ {}$h$\n"));
2803 
2804  EXPECT_TRUE(HasSpan('a', 'd', file_.message_type(0)));
2805  EXPECT_TRUE(HasSpan('b', 'c', file_.message_type(0), "name"));
2806  EXPECT_TRUE(HasSpan('e', 'h', file_.message_type(1)));
2807  EXPECT_TRUE(HasSpan('f', 'g', file_.message_type(1), "name"));
2808 
2809  // Ignore these.
2810  EXPECT_TRUE(HasSpan(file_));
2811 }
2812 
2813 TEST_F(SourceInfoTest, Fields) {
2814  EXPECT_TRUE(
2815  Parse("message Foo {\n"
2816  " $a$optional$b$ $c$int32$d$ $e$bar$f$ = $g$1$h$;$i$\n"
2817  " $j$repeated$k$ $l$X.Y$m$ $n$baz$o$ = $p$2$q$;$r$\n"
2818  "}\n"));
2819 
2820  const FieldDescriptorProto& field1 = file_.message_type(0).field(0);
2821  const FieldDescriptorProto& field2 = file_.message_type(0).field(1);
2822 
2823  EXPECT_TRUE(HasSpan('a', 'i', field1));
2824  EXPECT_TRUE(HasSpan('a', 'b', field1, "label"));
2825  EXPECT_TRUE(HasSpan('c', 'd', field1, "type"));
2826  EXPECT_TRUE(HasSpan('e', 'f', field1, "name"));
2827  EXPECT_TRUE(HasSpan('g', 'h', field1, "number"));
2828 
2829  EXPECT_TRUE(HasSpan('j', 'r', field2));
2830  EXPECT_TRUE(HasSpan('j', 'k', field2, "label"));
2831  EXPECT_TRUE(HasSpan('l', 'm', field2, "type_name"));
2832  EXPECT_TRUE(HasSpan('n', 'o', field2, "name"));
2833  EXPECT_TRUE(HasSpan('p', 'q', field2, "number"));
2834 
2835  // Ignore these.
2836  EXPECT_TRUE(HasSpan(file_));
2837  EXPECT_TRUE(HasSpan(file_.message_type(0)));
2838  EXPECT_TRUE(HasSpan(file_.message_type(0), "name"));
2839 }
2840 
2841 TEST_F(SourceInfoTest, Proto3Fields) {
2842  EXPECT_TRUE(
2843  Parse("syntax = \"proto3\";\n"
2844  "message Foo {\n"
2845  " $a$int32$b$ $c$bar$d$ = $e$1$f$;$g$\n"
2846  " $h$repeated$i$ $j$X.Y$k$ $l$baz$m$ = $n$2$o$;$p$\n"
2847  "}\n"));
2848 
2849  const FieldDescriptorProto& field1 = file_.message_type(0).field(0);
2850  const FieldDescriptorProto& field2 = file_.message_type(0).field(1);
2851 
2852  EXPECT_TRUE(HasSpan('a', 'g', field1));
2853  EXPECT_TRUE(HasSpan('a', 'b', field1, "type"));
2854  EXPECT_TRUE(HasSpan('c', 'd', field1, "name"));
2855  EXPECT_TRUE(HasSpan('e', 'f', field1, "number"));
2856 
2857  EXPECT_TRUE(HasSpan('h', 'p', field2));
2858  EXPECT_TRUE(HasSpan('h', 'i', field2, "label"));
2859  EXPECT_TRUE(HasSpan('j', 'k', field2, "type_name"));
2860  EXPECT_TRUE(HasSpan('l', 'm', field2, "name"));
2861  EXPECT_TRUE(HasSpan('n', 'o', field2, "number"));
2862 
2863  // Ignore these.
2864  EXPECT_TRUE(HasSpan(file_));
2865  EXPECT_TRUE(HasSpan(file_, "syntax"));
2866  EXPECT_TRUE(HasSpan(file_.message_type(0)));
2867  EXPECT_TRUE(HasSpan(file_.message_type(0), "name"));
2868 }
2869 
2870 TEST_F(SourceInfoTest, Extensions) {
2871  EXPECT_TRUE(
2872  Parse("$a$extend $b$Foo$c$ {\n"
2873  " $d$optional$e$ int32 bar = 1;$f$\n"
2874  " $g$repeated$h$ X.Y baz = 2;$i$\n"
2875  "}$j$\n"
2876  "$k$extend $l$Bar$m$ {\n"
2877  " $n$optional int32 qux = 1;$o$\n"
2878  "}$p$\n"));
2879 
2880  const FieldDescriptorProto& field1 = file_.extension(0);
2881  const FieldDescriptorProto& field2 = file_.extension(1);
2882  const FieldDescriptorProto& field3 = file_.extension(2);
2883 
2884  EXPECT_TRUE(HasSpan('a', 'j', file_, "extension"));
2885  EXPECT_TRUE(HasSpan('k', 'p', file_, "extension"));
2886 
2887  EXPECT_TRUE(HasSpan('d', 'f', field1));
2888  EXPECT_TRUE(HasSpan('d', 'e', field1, "label"));
2889  EXPECT_TRUE(HasSpan('b', 'c', field1, "extendee"));
2890 
2891  EXPECT_TRUE(HasSpan('g', 'i', field2));
2892  EXPECT_TRUE(HasSpan('g', 'h', field2, "label"));
2893  EXPECT_TRUE(HasSpan('b', 'c', field2, "extendee"));
2894 
2895  EXPECT_TRUE(HasSpan('n', 'o', field3));
2896  EXPECT_TRUE(HasSpan('l', 'm', field3, "extendee"));
2897 
2898  // Ignore these.
2899  EXPECT_TRUE(HasSpan(file_));
2900  EXPECT_TRUE(HasSpan(field1, "type"));
2901  EXPECT_TRUE(HasSpan(field1, "name"));
2902  EXPECT_TRUE(HasSpan(field1, "number"));
2903  EXPECT_TRUE(HasSpan(field2, "type_name"));
2904  EXPECT_TRUE(HasSpan(field2, "name"));
2905  EXPECT_TRUE(HasSpan(field2, "number"));
2906  EXPECT_TRUE(HasSpan(field3, "label"));
2907  EXPECT_TRUE(HasSpan(field3, "type"));
2908  EXPECT_TRUE(HasSpan(field3, "name"));
2909  EXPECT_TRUE(HasSpan(field3, "number"));
2910 }
2911 
2912 TEST_F(SourceInfoTest, NestedExtensions) {
2913  EXPECT_TRUE(
2914  Parse("message Message {\n"
2915  " $a$extend $b$Foo$c$ {\n"
2916  " $d$optional$e$ int32 bar = 1;$f$\n"
2917  " $g$repeated$h$ X.Y baz = 2;$i$\n"
2918  " }$j$\n"
2919  " $k$extend $l$Bar$m$ {\n"
2920  " $n$optional int32 qux = 1;$o$\n"
2921  " }$p$\n"
2922  "}\n"));
2923 
2924  const FieldDescriptorProto& field1 = file_.message_type(0).extension(0);
2925  const FieldDescriptorProto& field2 = file_.message_type(0).extension(1);
2926  const FieldDescriptorProto& field3 = file_.message_type(0).extension(2);
2927 
2928  EXPECT_TRUE(HasSpan('a', 'j', file_.message_type(0), "extension"));
2929  EXPECT_TRUE(HasSpan('k', 'p', file_.message_type(0), "extension"));
2930 
2931  EXPECT_TRUE(HasSpan('d', 'f', field1));
2932  EXPECT_TRUE(HasSpan('d', 'e', field1, "label"));
2933  EXPECT_TRUE(HasSpan('b', 'c', field1, "extendee"));
2934 
2935  EXPECT_TRUE(HasSpan('g', 'i', field2));
2936  EXPECT_TRUE(HasSpan('g', 'h', field2, "label"));
2937  EXPECT_TRUE(HasSpan('b', 'c', field2, "extendee"));
2938 
2939  EXPECT_TRUE(HasSpan('n', 'o', field3));
2940  EXPECT_TRUE(HasSpan('l', 'm', field3, "extendee"));
2941 
2942  // Ignore these.
2943  EXPECT_TRUE(HasSpan(file_));
2944  EXPECT_TRUE(HasSpan(file_.message_type(0)));
2945  EXPECT_TRUE(HasSpan(file_.message_type(0), "name"));
2946  EXPECT_TRUE(HasSpan(field1, "type"));
2947  EXPECT_TRUE(HasSpan(field1, "name"));
2948  EXPECT_TRUE(HasSpan(field1, "number"));
2949  EXPECT_TRUE(HasSpan(field2, "type_name"));
2950  EXPECT_TRUE(HasSpan(field2, "name"));
2951  EXPECT_TRUE(HasSpan(field2, "number"));
2952  EXPECT_TRUE(HasSpan(field3, "label"));
2953  EXPECT_TRUE(HasSpan(field3, "type"));
2954  EXPECT_TRUE(HasSpan(field3, "name"));
2955  EXPECT_TRUE(HasSpan(field3, "number"));
2956 }
2957 
2958 TEST_F(SourceInfoTest, ExtensionRanges) {
2959  EXPECT_TRUE(
2960  Parse("message Message {\n"
2961  " $a$extensions $b$1$c$ to $d$4$e$, $f$6$g$;$h$\n"
2962  " $i$extensions $j$8$k$ to $l$max$m$;$n$\n"
2963  "}\n"));
2964 
2965  const DescriptorProto::ExtensionRange& range1 =
2966  file_.message_type(0).extension_range(0);
2967  const DescriptorProto::ExtensionRange& range2 =
2968  file_.message_type(0).extension_range(1);
2969  const DescriptorProto::ExtensionRange& range3 =
2970  file_.message_type(0).extension_range(2);
2971 
2972  EXPECT_TRUE(HasSpan('a', 'h', file_.message_type(0), "extension_range"));
2973  EXPECT_TRUE(HasSpan('i', 'n', file_.message_type(0), "extension_range"));
2974 
2975  EXPECT_TRUE(HasSpan('b', 'e', range1));
2976  EXPECT_TRUE(HasSpan('b', 'c', range1, "start"));
2977  EXPECT_TRUE(HasSpan('d', 'e', range1, "end"));
2978 
2979  EXPECT_TRUE(HasSpan('f', 'g', range2));
2980  EXPECT_TRUE(HasSpan('f', 'g', range2, "start"));
2981  EXPECT_TRUE(HasSpan('f', 'g', range2, "end"));
2982 
2983  EXPECT_TRUE(HasSpan('j', 'm', range3));
2984  EXPECT_TRUE(HasSpan('j', 'k', range3, "start"));
2985  EXPECT_TRUE(HasSpan('l', 'm', range3, "end"));
2986 
2987  // Ignore these.
2988  EXPECT_TRUE(HasSpan(file_));
2989  EXPECT_TRUE(HasSpan(file_.message_type(0)));
2990  EXPECT_TRUE(HasSpan(file_.message_type(0), "name"));
2991 }
2992 
2993 TEST_F(SourceInfoTest, ReservedRanges) {
2994  EXPECT_TRUE(
2995  Parse("message Message {\n"
2996  " $a$reserved $b$1$c$ to $d$4$e$, $f$6$g$;$h$\n"
2997  "}\n"));
2998 
2999  const DescriptorProto::ReservedRange& range1 =
3000  file_.message_type(0).reserved_range(0);
3001  const DescriptorProto::ReservedRange& range2 =
3002  file_.message_type(0).reserved_range(1);
3003 
3004  EXPECT_TRUE(HasSpan('a', 'h', file_.message_type(0), "reserved_range"));
3005 
3006  EXPECT_TRUE(HasSpan('b', 'e', range1));
3007  EXPECT_TRUE(HasSpan('b', 'c', range1, "start"));
3008  EXPECT_TRUE(HasSpan('d', 'e', range1, "end"));
3009 
3010  EXPECT_TRUE(HasSpan('f', 'g', range2));
3011  EXPECT_TRUE(HasSpan('f', 'g', range2, "start"));
3012  EXPECT_TRUE(HasSpan('f', 'g', range2, "end"));
3013 
3014  // Ignore these.
3015  EXPECT_TRUE(HasSpan(file_));
3016  EXPECT_TRUE(HasSpan(file_.message_type(0)));
3017  EXPECT_TRUE(HasSpan(file_.message_type(0), "name"));
3018 }
3019 
3020 TEST_F(SourceInfoTest, Oneofs) {
3021  EXPECT_TRUE(
3022  Parse("message Foo {\n"
3023  " $a$oneof $c$foo$d$ {\n"
3024  " $e$int32$f$ $g$a$h$ = $i$1$j$;$k$\n"
3025  " }$r$\n"
3026  "}\n"));
3027 
3028  const OneofDescriptorProto& oneof_decl = file_.message_type(0).oneof_decl(0);
3029  const FieldDescriptorProto& field = file_.message_type(0).field(0);
3030 
3031  EXPECT_TRUE(HasSpan('a', 'r', oneof_decl));
3032  EXPECT_TRUE(HasSpan('c', 'd', oneof_decl, "name"));
3033 
3034  EXPECT_TRUE(HasSpan('e', 'k', field));
3035  EXPECT_TRUE(HasSpan('e', 'f', field, "type"));
3036  EXPECT_TRUE(HasSpan('g', 'h', field, "name"));
3037  EXPECT_TRUE(HasSpan('i', 'j', field, "number"));
3038 
3039  // Ignore these.
3040  EXPECT_TRUE(HasSpan(file_));
3041  EXPECT_TRUE(HasSpan(file_.message_type(0)));
3042  EXPECT_TRUE(HasSpan(file_.message_type(0), "name"));
3043 }
3044 
3045 TEST_F(SourceInfoTest, NestedMessages) {
3046  EXPECT_TRUE(
3047  Parse("message Foo {\n"
3048  " $a$message $b$Bar$c$ {\n"
3049  " $d$message $e$Baz$f$ {}$g$\n"
3050  " }$h$\n"
3051  " $i$message $j$Qux$k$ {}$l$\n"
3052  "}\n"));
3053 
3054  const DescriptorProto& bar = file_.message_type(0).nested_type(0);
3055  const DescriptorProto& baz = bar.nested_type(0);
3056  const DescriptorProto& qux = file_.message_type(0).nested_type(1);
3057 
3058  EXPECT_TRUE(HasSpan('a', 'h', bar));
3059  EXPECT_TRUE(HasSpan('b', 'c', bar, "name"));
3060  EXPECT_TRUE(HasSpan('d', 'g', baz));
3061  EXPECT_TRUE(HasSpan('e', 'f', baz, "name"));
3062  EXPECT_TRUE(HasSpan('i', 'l', qux));
3063  EXPECT_TRUE(HasSpan('j', 'k', qux, "name"));
3064 
3065  // Ignore these.
3066  EXPECT_TRUE(HasSpan(file_));
3067  EXPECT_TRUE(HasSpan(file_.message_type(0)));
3068  EXPECT_TRUE(HasSpan(file_.message_type(0), "name"));
3069 }
3070 
3071 TEST_F(SourceInfoTest, Groups) {
3072  EXPECT_TRUE(
3073  Parse("message Foo {\n"
3074  " message Bar {}\n"
3075  " $a$optional$b$ $c$group$d$ $e$Baz$f$ = $g$1$h$ {\n"
3076  " $i$message Qux {}$j$\n"
3077  " }$k$\n"
3078  "}\n"));
3079 
3080  const DescriptorProto& bar = file_.message_type(0).nested_type(0);
3081  const DescriptorProto& baz = file_.message_type(0).nested_type(1);
3082  const DescriptorProto& qux = baz.nested_type(0);
3083  const FieldDescriptorProto& field = file_.message_type(0).field(0);
3084 
3085  EXPECT_TRUE(HasSpan('a', 'k', field));
3086  EXPECT_TRUE(HasSpan('a', 'b', field, "label"));
3087  EXPECT_TRUE(HasSpan('c', 'd', field, "type"));
3088  EXPECT_TRUE(HasSpan('e', 'f', field, "name"));
3089  EXPECT_TRUE(HasSpan('e', 'f', field, "type_name"));
3090  EXPECT_TRUE(HasSpan('g', 'h', field, "number"));
3091 
3092  EXPECT_TRUE(HasSpan('a', 'k', baz));
3093  EXPECT_TRUE(HasSpan('e', 'f', baz, "name"));
3094  EXPECT_TRUE(HasSpan('i', 'j', qux));
3095 
3096  // Ignore these.
3097  EXPECT_TRUE(HasSpan(file_));
3098  EXPECT_TRUE(HasSpan(file_.message_type(0)));
3099  EXPECT_TRUE(HasSpan(file_.message_type(0), "name"));
3100  EXPECT_TRUE(HasSpan(bar));
3101  EXPECT_TRUE(HasSpan(bar, "name"));
3102  EXPECT_TRUE(HasSpan(qux, "name"));
3103 }
3104 
3105 TEST_F(SourceInfoTest, Enums) {
3106  EXPECT_TRUE(
3107  Parse("$a$enum $b$Foo$c$ {}$d$\n"
3108  "$e$enum $f$Bar$g$ {}$h$\n"));
3109 
3110  EXPECT_TRUE(HasSpan('a', 'd', file_.enum_type(0)));
3111  EXPECT_TRUE(HasSpan('b', 'c', file_.enum_type(0), "name"));
3112  EXPECT_TRUE(HasSpan('e', 'h', file_.enum_type(1)));
3113  EXPECT_TRUE(HasSpan('f', 'g', file_.enum_type(1), "name"));
3114 
3115  // Ignore these.
3116  EXPECT_TRUE(HasSpan(file_));
3117 }
3118 
3119 TEST_F(SourceInfoTest, EnumValues) {
3120  EXPECT_TRUE(
3121  Parse("enum Foo {\n"
3122  " $a$BAR$b$ = $c$1$d$;$e$\n"
3123  " $f$BAZ$g$ = $h$2$i$;$j$\n"
3124  "}"));
3125 
3126  const EnumValueDescriptorProto& bar = file_.enum_type(0).value(0);
3127  const EnumValueDescriptorProto& baz = file_.enum_type(0).value(1);
3128 
3129  EXPECT_TRUE(HasSpan('a', 'e', bar));
3130  EXPECT_TRUE(HasSpan('a', 'b', bar, "name"));
3131  EXPECT_TRUE(HasSpan('c', 'd', bar, "number"));
3132  EXPECT_TRUE(HasSpan('f', 'j', baz));
3133  EXPECT_TRUE(HasSpan('f', 'g', baz, "name"));
3134  EXPECT_TRUE(HasSpan('h', 'i', baz, "number"));
3135 
3136  // Ignore these.
3137  EXPECT_TRUE(HasSpan(file_));
3138  EXPECT_TRUE(HasSpan(file_.enum_type(0)));
3139  EXPECT_TRUE(HasSpan(file_.enum_type(0), "name"));
3140 }
3141 
3142 TEST_F(SourceInfoTest, EnumReservedRange) {
3143  EXPECT_TRUE(
3144  Parse("enum TestEnum {\n"
3145  " $a$reserved $b$1$c$ to $d$10$e$;$f$\n"
3146  "}"));
3147 
3149  file_.enum_type(0).reserved_range(0);
3150 
3151  EXPECT_TRUE(HasSpan('a', 'f', file_.enum_type(0), "reserved_range"));
3152  EXPECT_TRUE(HasSpan('b', 'e', bar));
3153  EXPECT_TRUE(HasSpan('b', 'c', bar, "start"));
3154  EXPECT_TRUE(HasSpan('d', 'e', bar, "end"));
3155 
3156  // Ignore these.
3157  EXPECT_TRUE(HasSpan(file_));
3158  EXPECT_TRUE(HasSpan(file_.enum_type(0)));
3159  EXPECT_TRUE(HasSpan(file_.enum_type(0), "name"));
3160 }
3161 
3162 TEST_F(SourceInfoTest, EnumReservedName) {
3163  EXPECT_TRUE(
3164  Parse("enum TestEnum {\n"
3165  " $a$reserved $b$'foo'$c$;$d$\n"
3166  "}"));
3167 
3168  const EnumDescriptorProto& bar = file_.enum_type(0);
3169 
3170  EXPECT_TRUE(HasSpan('a', 'd', bar, "reserved_name"));
3171  EXPECT_TRUE(HasSpan('b', 'c', bar, "reserved_name", 0));
3172 
3173  // Ignore these.
3174  EXPECT_TRUE(HasSpan(file_));
3175  EXPECT_TRUE(HasSpan(file_.enum_type(0)));
3176  EXPECT_TRUE(HasSpan(file_.enum_type(0), "name"));
3177 }
3178 
3179 TEST_F(SourceInfoTest, NestedEnums) {
3180  EXPECT_TRUE(
3181  Parse("message Foo {\n"
3182  " $a$enum $b$Bar$c$ {}$d$\n"
3183  " $e$enum $f$Baz$g$ {}$h$\n"
3184  "}\n"));
3185 
3186  const EnumDescriptorProto& bar = file_.message_type(0).enum_type(0);
3187  const EnumDescriptorProto& baz = file_.message_type(0).enum_type(1);
3188 
3189  EXPECT_TRUE(HasSpan('a', 'd', bar));
3190  EXPECT_TRUE(HasSpan('b', 'c', bar, "name"));
3191  EXPECT_TRUE(HasSpan('e', 'h', baz));
3192  EXPECT_TRUE(HasSpan('f', 'g', baz, "name"));
3193 
3194  // Ignore these.
3195  EXPECT_TRUE(HasSpan(file_));
3196  EXPECT_TRUE(HasSpan(file_.message_type(0)));
3197  EXPECT_TRUE(HasSpan(file_.message_type(0), "name"));
3198 }
3199 
3200 TEST_F(SourceInfoTest, Services) {
3201  EXPECT_TRUE(
3202  Parse("$a$service $b$Foo$c$ {}$d$\n"
3203  "$e$service $f$Bar$g$ {}$h$\n"));
3204 
3205  EXPECT_TRUE(HasSpan('a', 'd', file_.service(0)));
3206  EXPECT_TRUE(HasSpan('b', 'c', file_.service(0), "name"));
3207  EXPECT_TRUE(HasSpan('e', 'h', file_.service(1)));
3208  EXPECT_TRUE(HasSpan('f', 'g', file_.service(1), "name"));
3209 
3210  // Ignore these.
3211  EXPECT_TRUE(HasSpan(file_));
3212 }
3213 
3214 TEST_F(SourceInfoTest, MethodsAndStreams) {
3215  EXPECT_TRUE(
3216  Parse("service Foo {\n"
3217  " $a$rpc $b$Bar$c$($d$X$e$) returns($f$Y$g$);$h$"
3218  " $i$rpc $j$Baz$k$($l$Z$m$) returns($n$W$o$);$p$"
3219  "}"));
3220 
3221  const MethodDescriptorProto& bar = file_.service(0).method(0);
3222  const MethodDescriptorProto& baz = file_.service(0).method(1);
3223 
3224  EXPECT_TRUE(HasSpan('a', 'h', bar));
3225  EXPECT_TRUE(HasSpan('b', 'c', bar, "name"));
3226  EXPECT_TRUE(HasSpan('d', 'e', bar, "input_type"));
3227  EXPECT_TRUE(HasSpan('f', 'g', bar, "output_type"));
3228 
3229  EXPECT_TRUE(HasSpan('i', 'p', baz));
3230  EXPECT_TRUE(HasSpan('j', 'k', baz, "name"));
3231  EXPECT_TRUE(HasSpan('l', 'm', baz, "input_type"));
3232  EXPECT_TRUE(HasSpan('n', 'o', baz, "output_type"));
3233 
3234  // Ignore these.
3235  EXPECT_TRUE(HasSpan(file_));
3236  EXPECT_TRUE(HasSpan(file_.service(0)));
3237  EXPECT_TRUE(HasSpan(file_.service(0), "name"));
3238 }
3239 
3240 
3241 TEST_F(SourceInfoTest, Options) {
3242  EXPECT_TRUE(
3243  Parse("$a$option $b$foo$c$.$d$($e$bar.baz$f$)$g$ = "
3244  "$h$123$i$;$j$\n"
3245  "$k$option qux = $l$-123$m$;$n$\n"
3246  "$o$option corge = $p$abc$q$;$r$\n"
3247  "$s$option grault = $t$'blah'$u$;$v$\n"
3248  "$w$option garply = $x${ yadda yadda }$y$;$z$\n"
3249  "$0$option waldo = $1$123.0$2$;$3$\n"));
3250 
3251  const UninterpretedOption& option1 = file_.options().uninterpreted_option(0);
3252  const UninterpretedOption& option2 = file_.options().uninterpreted_option(1);
3253  const UninterpretedOption& option3 = file_.options().uninterpreted_option(2);
3254  const UninterpretedOption& option4 = file_.options().uninterpreted_option(3);
3255  const UninterpretedOption& option5 = file_.options().uninterpreted_option(4);
3256  const UninterpretedOption& option6 = file_.options().uninterpreted_option(5);
3257 
3258  EXPECT_TRUE(HasSpan('a', 'j', file_.options()));
3259  EXPECT_TRUE(HasSpan('a', 'j', option1));
3260  EXPECT_TRUE(HasSpan('b', 'g', option1, "name"));
3261  EXPECT_TRUE(HasSpan('b', 'c', option1.name(0)));
3262  EXPECT_TRUE(HasSpan('b', 'c', option1.name(0), "name_part"));
3263  EXPECT_TRUE(HasSpan('d', 'g', option1.name(1)));
3264  EXPECT_TRUE(HasSpan('e', 'f', option1.name(1), "name_part"));
3265  EXPECT_TRUE(HasSpan('h', 'i', option1, "positive_int_value"));
3266 
3267  EXPECT_TRUE(HasSpan('k', 'n', file_.options()));
3268  EXPECT_TRUE(HasSpan('l', 'm', option2, "negative_int_value"));
3269 
3270  EXPECT_TRUE(HasSpan('o', 'r', file_.options()));
3271  EXPECT_TRUE(HasSpan('p', 'q', option3, "identifier_value"));
3272 
3273  EXPECT_TRUE(HasSpan('s', 'v', file_.options()));
3274  EXPECT_TRUE(HasSpan('t', 'u', option4, "string_value"));
3275 
3276  EXPECT_TRUE(HasSpan('w', 'z', file_.options()));
3277  EXPECT_TRUE(HasSpan('x', 'y', option5, "aggregate_value"));
3278 
3279  EXPECT_TRUE(HasSpan('0', '3', file_.options()));
3280  EXPECT_TRUE(HasSpan('1', '2', option6, "double_value"));
3281 
3282  // Ignore these.
3283  EXPECT_TRUE(HasSpan(file_));
3284  EXPECT_TRUE(HasSpan(option2));
3285  EXPECT_TRUE(HasSpan(option3));
3286  EXPECT_TRUE(HasSpan(option4));
3287  EXPECT_TRUE(HasSpan(option5));
3288  EXPECT_TRUE(HasSpan(option6));
3289  EXPECT_TRUE(HasSpan(option2, "name"));
3290  EXPECT_TRUE(HasSpan(option3, "name"));
3291  EXPECT_TRUE(HasSpan(option4, "name"));
3292  EXPECT_TRUE(HasSpan(option5, "name"));
3293  EXPECT_TRUE(HasSpan(option6, "name"));
3294  EXPECT_TRUE(HasSpan(option2.name(0)));
3295  EXPECT_TRUE(HasSpan(option3.name(0)));
3296  EXPECT_TRUE(HasSpan(option4.name(0)));
3297  EXPECT_TRUE(HasSpan(option5.name(0)));
3298  EXPECT_TRUE(HasSpan(option6.name(0)));
3299  EXPECT_TRUE(HasSpan(option2.name(0), "name_part"));
3300  EXPECT_TRUE(HasSpan(option3.name(0), "name_part"));
3301  EXPECT_TRUE(HasSpan(option4.name(0), "name_part"));
3302  EXPECT_TRUE(HasSpan(option5.name(0), "name_part"));
3303  EXPECT_TRUE(HasSpan(option6.name(0), "name_part"));
3304 }
3305 
3306 TEST_F(SourceInfoTest, ScopedOptions) {
3307  EXPECT_TRUE(
3308  Parse("message Foo {\n"
3309  " $a$option mopt = 1;$b$\n"
3310  "}\n"
3311  "enum Bar {\n"
3312  " $c$option eopt = 1;$d$\n"
3313  "}\n"
3314  "service Baz {\n"
3315  " $e$option sopt = 1;$f$\n"
3316  " rpc M(X) returns(Y) {\n"
3317  " $g$option mopt = 1;$h$\n"
3318  " }\n"
3319  " rpc MS4($1$stream$2$ X) returns($3$stream$4$ Y) {\n"
3320  " $k$option mopt = 1;$l$\n"
3321  " }\n"
3322  "}\n"));
3323 
3324  EXPECT_TRUE(HasSpan('a', 'b', file_.message_type(0).options()));
3325  EXPECT_TRUE(HasSpan('c', 'd', file_.enum_type(0).options()));
3326  EXPECT_TRUE(HasSpan('e', 'f', file_.service(0).options()));
3327  EXPECT_TRUE(HasSpan('g', 'h', file_.service(0).method(0).options()));
3328 
3329  // Ignore these.
3330  EXPECT_TRUE(HasSpan(file_));
3331  EXPECT_TRUE(HasSpan(file_.message_type(0)));
3332  EXPECT_TRUE(HasSpan(file_.message_type(0), "name"));
3333  EXPECT_TRUE(HasSpan(file_.message_type(0).options().uninterpreted_option(0)));
3334  EXPECT_TRUE(
3335  HasSpan(file_.message_type(0).options().uninterpreted_option(0), "name"));
3336  EXPECT_TRUE(
3337  HasSpan(file_.message_type(0).options().uninterpreted_option(0).name(0)));
3338  EXPECT_TRUE(
3339  HasSpan(file_.message_type(0).options().uninterpreted_option(0).name(0),
3340  "name_part"));
3341  EXPECT_TRUE(HasSpan(file_.message_type(0).options().uninterpreted_option(0),
3342  "positive_int_value"));
3343  EXPECT_TRUE(HasSpan(file_.enum_type(0)));
3344  EXPECT_TRUE(HasSpan(file_.enum_type(0), "name"));
3345  EXPECT_TRUE(HasSpan(file_.enum_type(0).options().uninterpreted_option(0)));
3346  EXPECT_TRUE(
3347  HasSpan(file_.enum_type(0).options().uninterpreted_option(0), "name"));
3348  EXPECT_TRUE(
3349  HasSpan(file_.enum_type(0).options().uninterpreted_option(0).name(0)));
3350  EXPECT_TRUE(
3351  HasSpan(file_.enum_type(0).options().uninterpreted_option(0).name(0),
3352  "name_part"));
3353  EXPECT_TRUE(HasSpan(file_.enum_type(0).options().uninterpreted_option(0),
3354  "positive_int_value"));
3355  EXPECT_TRUE(HasSpan(file_.service(0)));
3356  EXPECT_TRUE(HasSpan(file_.service(0), "name"));
3357  EXPECT_TRUE(HasSpan(file_.service(0).method(0)));
3358  EXPECT_TRUE(HasSpan(file_.service(0).options().uninterpreted_option(0)));
3359  EXPECT_TRUE(
3360  HasSpan(file_.service(0).options().uninterpreted_option(0), "name"));
3361  EXPECT_TRUE(
3362  HasSpan(file_.service(0).options().uninterpreted_option(0).name(0)));
3363  EXPECT_TRUE(HasSpan(
3364  file_.service(0).options().uninterpreted_option(0).name(0), "name_part"));
3365  EXPECT_TRUE(HasSpan(file_.service(0).options().uninterpreted_option(0),
3366  "positive_int_value"));
3367  EXPECT_TRUE(HasSpan(file_.service(0).method(0), "name"));
3368  EXPECT_TRUE(HasSpan(file_.service(0).method(0), "input_type"));
3369  EXPECT_TRUE(HasSpan(file_.service(0).method(0), "output_type"));
3370  EXPECT_TRUE(
3371  HasSpan(file_.service(0).method(0).options().uninterpreted_option(0)));
3372  EXPECT_TRUE(HasSpan(
3373  file_.service(0).method(0).options().uninterpreted_option(0), "name"));
3374  EXPECT_TRUE(HasSpan(
3375  file_.service(0).method(0).options().uninterpreted_option(0).name(0)));
3376  EXPECT_TRUE(HasSpan(
3377  file_.service(0).method(0).options().uninterpreted_option(0).name(0),
3378  "name_part"));
3379  EXPECT_TRUE(
3380  HasSpan(file_.service(0).method(0).options().uninterpreted_option(0),
3381  "positive_int_value"));
3382 
3383  EXPECT_TRUE(HasSpan('k', 'l', file_.service(0).method(1).options()));
3384  EXPECT_TRUE(HasSpan(file_.service(0).method(1)));
3385  EXPECT_TRUE(HasSpan(file_.service(0).method(1), "name"));
3386  EXPECT_TRUE(HasSpan(file_.service(0).method(1), "input_type"));
3387  EXPECT_TRUE(HasSpan(file_.service(0).method(1), "output_type"));
3388  EXPECT_TRUE(
3389  HasSpan(file_.service(0).method(1).options().uninterpreted_option(0)));
3390  EXPECT_TRUE(HasSpan(
3391  file_.service(0).method(1).options().uninterpreted_option(0), "name"));
3392  EXPECT_TRUE(HasSpan(
3393  file_.service(0).method(1).options().uninterpreted_option(0).name(0)));
3394  EXPECT_TRUE(HasSpan(
3395  file_.service(0).method(1).options().uninterpreted_option(0).name(0),
3396  "name_part"));
3397  EXPECT_TRUE(
3398  HasSpan(file_.service(0).method(1).options().uninterpreted_option(0),
3399  "positive_int_value"));
3400  EXPECT_TRUE(
3401  HasSpan('1', '2', file_.service(0).method(1), "client_streaming"));
3402  EXPECT_TRUE(
3403  HasSpan('3', '4', file_.service(0).method(1), "server_streaming"));
3404 }
3405 
3406 TEST_F(SourceInfoTest, FieldOptions) {
3407  // The actual "name = value" pairs are parsed by the same code as for
3408  // top-level options so we won't re-test that -- just make sure that the
3409  // syntax used for field options is understood.
3410  EXPECT_TRUE(
3411  Parse("message Foo {"
3412  " optional int32 bar = 1 "
3413  "$a$[default=$b$123$c$,$d$opt1=123$e$,"
3414  "$f$opt2='hi'$g$]$h$;"
3415  "}\n"));
3416 
3417  const FieldDescriptorProto& field = file_.message_type(0).field(0);
3418  const UninterpretedOption& option1 = field.options().uninterpreted_option(0);
3419  const UninterpretedOption& option2 = field.options().uninterpreted_option(1);
3420 
3421  EXPECT_TRUE(HasSpan('a', 'h', field.options()));
3422  EXPECT_TRUE(HasSpan('b', 'c', field, "default_value"));
3423  EXPECT_TRUE(HasSpan('d', 'e', option1));
3424  EXPECT_TRUE(HasSpan('f', 'g', option2));
3425 
3426  // Ignore these.
3427  EXPECT_TRUE(HasSpan(file_));
3428  EXPECT_TRUE(HasSpan(file_.message_type(0)));
3429  EXPECT_TRUE(HasSpan(file_.message_type(0), "name"));
3430  EXPECT_TRUE(HasSpan(field));
3431  EXPECT_TRUE(HasSpan(field, "label"));
3432  EXPECT_TRUE(HasSpan(field, "type"));
3433  EXPECT_TRUE(HasSpan(field, "name"));
3434  EXPECT_TRUE(HasSpan(field, "number"));
3435  EXPECT_TRUE(HasSpan(option1, "name"));
3436  EXPECT_TRUE(HasSpan(option2, "name"));
3437  EXPECT_TRUE(HasSpan(option1.name(0)));
3438  EXPECT_TRUE(HasSpan(option2.name(0)));
3439  EXPECT_TRUE(HasSpan(option1.name(0), "name_part"));
3440  EXPECT_TRUE(HasSpan(option2.name(0), "name_part"));
3441  EXPECT_TRUE(HasSpan(option1, "positive_int_value"));
3442  EXPECT_TRUE(HasSpan(option2, "string_value"));
3443 }
3444 
3445 TEST_F(SourceInfoTest, EnumValueOptions) {
3446  // The actual "name = value" pairs are parsed by the same code as for
3447  // top-level options so we won't re-test that -- just make sure that the
3448  // syntax used for enum options is understood.
3449  EXPECT_TRUE(
3450  Parse("enum Foo {"
3451  " BAR = 1 $a$[$b$opt1=123$c$,$d$opt2='hi'$e$]$f$;"
3452  "}\n"));
3453 
3454  const EnumValueDescriptorProto& value = file_.enum_type(0).value(0);
3455  const UninterpretedOption& option1 = value.options().uninterpreted_option(0);
3456  const UninterpretedOption& option2 = value.options().uninterpreted_option(1);
3457 
3458  EXPECT_TRUE(HasSpan('a', 'f', value.options()));
3459  EXPECT_TRUE(HasSpan('b', 'c', option1));
3460  EXPECT_TRUE(HasSpan('d', 'e', option2));
3461 
3462  // Ignore these.
3463  EXPECT_TRUE(HasSpan(file_));
3464  EXPECT_TRUE(HasSpan(file_.enum_type(0)));
3465  EXPECT_TRUE(HasSpan(file_.enum_type(0), "name"));
3466  EXPECT_TRUE(HasSpan(value));
3467  EXPECT_TRUE(HasSpan(value, "name"));
3468  EXPECT_TRUE(HasSpan(value, "number"));
3469  EXPECT_TRUE(HasSpan(option1, "name"));
3470  EXPECT_TRUE(HasSpan(option2, "name"));
3471  EXPECT_TRUE(HasSpan(option1.name(0)));
3472  EXPECT_TRUE(HasSpan(option2.name(0)));
3473  EXPECT_TRUE(HasSpan(option1.name(0), "name_part"));
3474  EXPECT_TRUE(HasSpan(option2.name(0), "name_part"));
3475  EXPECT_TRUE(HasSpan(option1, "positive_int_value"));
3476  EXPECT_TRUE(HasSpan(option2, "string_value"));
3477 }
3478 
3479 TEST_F(SourceInfoTest, DocComments) {
3480  EXPECT_TRUE(
3481  Parse("// Foo leading\n"
3482  "// line 2\n"
3483  "$a$message Foo {\n"
3484  " // Foo trailing\n"
3485  " // line 2\n"
3486  "\n"
3487  " // detached\n"
3488  "\n"
3489  " // bar leading\n"
3490  " $b$optional int32 bar = 1;$c$\n"
3491  " // bar trailing\n"
3492  "}$d$\n"
3493  "// ignored\n"));
3494 
3495  const DescriptorProto& foo = file_.message_type(0);
3496  const FieldDescriptorProto& bar = foo.field(0);
3497 
3498  EXPECT_TRUE(HasSpanWithComment('a', 'd', foo, " Foo leading\n line 2\n",
3499  " Foo trailing\n line 2\n", NULL));
3500  EXPECT_TRUE(HasSpanWithComment('b', 'c', bar, " bar leading\n",
3501  " bar trailing\n", " detached\n"));
3502 
3503  // Ignore these.
3504  EXPECT_TRUE(HasSpan(file_));
3505  EXPECT_TRUE(HasSpan(foo, "name"));
3506  EXPECT_TRUE(HasSpan(bar, "label"));
3507  EXPECT_TRUE(HasSpan(bar, "type"));
3508  EXPECT_TRUE(HasSpan(bar, "name"));
3509  EXPECT_TRUE(HasSpan(bar, "number"));
3510 }
3511 
3512 TEST_F(SourceInfoTest, DocComments2) {
3513  EXPECT_TRUE(
3514  Parse("// detached before message.\n"
3515  "\n"
3516  "// Foo leading\n"
3517  "// line 2\n"
3518  "$a$message Foo {\n"
3519  " /* Foo trailing\n"
3520  " * line 2 */\n"
3521  " // detached\n"
3522  " /* bar leading\n"
3523  " */"
3524  " $b$optional int32 bar = 1;$c$ // bar trailing\n"
3525  " // ignored detached\n"
3526  "}$d$\n"
3527  "// ignored\n"
3528  "\n"
3529  "// detached before option\n"
3530  "\n"
3531  "// option leading\n"
3532  "$e$option baz = 123;$f$\n"
3533  "// option trailing\n"));
3534 
3535  const DescriptorProto& foo = file_.message_type(0);
3536  const FieldDescriptorProto& bar = foo.field(0);
3537  const UninterpretedOption& baz = file_.options().uninterpreted_option(0);
3538 
3539  EXPECT_TRUE(HasSpanWithComment('a', 'd', foo, " Foo leading\n line 2\n",
3540  " Foo trailing\n line 2 ",
3541  " detached before message.\n"));
3542  EXPECT_TRUE(HasSpanWithComment('b', 'c', bar, " bar leading\n",
3543  " bar trailing\n", " detached\n"));
3544  EXPECT_TRUE(HasSpanWithComment('e', 'f', baz, " option leading\n",
3545  " option trailing\n",
3546  " detached before option\n"));
3547 
3548  // Ignore these.
3549  EXPECT_TRUE(HasSpan(file_));
3550  EXPECT_TRUE(HasSpan(foo, "name"));
3551  EXPECT_TRUE(HasSpan(bar, "label"));
3552  EXPECT_TRUE(HasSpan(bar, "type"));
3553  EXPECT_TRUE(HasSpan(bar, "name"));
3554  EXPECT_TRUE(HasSpan(bar, "number"));
3555  EXPECT_TRUE(HasSpan(file_.options()));
3556  EXPECT_TRUE(HasSpan(baz, "name"));
3557  EXPECT_TRUE(HasSpan(baz.name(0)));
3558  EXPECT_TRUE(HasSpan(baz.name(0), "name_part"));
3559  EXPECT_TRUE(HasSpan(baz, "positive_int_value"));
3560 }
3561 
3562 TEST_F(SourceInfoTest, DocComments3) {
3563  EXPECT_TRUE(
3564  Parse("$a$message Foo {\n"
3565  " // bar leading\n"
3566  " $b$optional int32 bar = 1 [(baz.qux) = {}];$c$\n"
3567  " // bar trailing\n"
3568  "}$d$\n"
3569  "// ignored\n"));
3570 
3571  const DescriptorProto& foo = file_.message_type(0);
3572  const FieldDescriptorProto& bar = foo.field(0);
3573 
3574  EXPECT_TRUE(HasSpanWithComment('b', 'c', bar, " bar leading\n",
3575  " bar trailing\n", NULL));
3576 
3577  // Ignore these.
3578  EXPECT_TRUE(HasSpan(file_));
3579  EXPECT_TRUE(HasSpan(foo));
3580  EXPECT_TRUE(HasSpan(foo, "name"));
3581  EXPECT_TRUE(HasSpan(bar, "label"));
3582  EXPECT_TRUE(HasSpan(bar, "type"));
3583  EXPECT_TRUE(HasSpan(bar, "name"));
3584  EXPECT_TRUE(HasSpan(bar, "number"));
3585  EXPECT_TRUE(HasSpan(bar.options()));
3586  EXPECT_TRUE(HasSpan(bar.options().uninterpreted_option(0)));
3587  EXPECT_TRUE(HasSpan(bar.options().uninterpreted_option(0), "name"));
3588  EXPECT_TRUE(HasSpan(bar.options().uninterpreted_option(0).name(0)));
3589  EXPECT_TRUE(
3590  HasSpan(bar.options().uninterpreted_option(0).name(0), "name_part"));
3591  EXPECT_TRUE(
3592  HasSpan(bar.options().uninterpreted_option(0), "aggregate_value"));
3593 }
3594 
3595 TEST_F(SourceInfoTest, DocCommentsTopLevel) {
3596  EXPECT_TRUE(
3597  Parse("// detached before syntax paragraph 1\n"
3598  "\n"
3599  "// detached before syntax paragraph 2\n"
3600  "\n"
3601  "// syntax leading\n"
3602  "$a$syntax = \"proto2\";$b$\n"
3603  "// syntax trailing\n"
3604  "\n"
3605  "// syntax-package detached comments\n"
3606  "\n"
3607  ";\n"
3608  "\n"
3609  "// detached after empty before package\n"
3610  "\n"
3611  "// package leading\n"
3612  "$c$package foo;$d$\n"
3613  "// package trailing\n"
3614  "\n"
3615  "// ignored detach\n"
3616  "\n"));
3617 
3618  EXPECT_TRUE(HasSpan('a', 'b', file_, "syntax", -1, " syntax leading\n",
3619  " syntax trailing\n",
3620  " detached before syntax paragraph 1\n"
3621  "\n"
3622  " detached before syntax paragraph 2\n"));
3623  EXPECT_TRUE(HasSpan('c', 'd', file_, "package", -1, " package leading\n",
3624  " package trailing\n",
3625  " syntax-package detached comments\n"
3626  "\n"
3627  " detached after empty before package\n"));
3628 
3629  // ignore these.
3630  EXPECT_TRUE(HasSpan(file_));
3631 }
3632 
3633 TEST_F(SourceInfoTest, DocCommentsOneof) {
3634  EXPECT_TRUE(
3635  Parse("// Foo leading\n"
3636  "$a$message Foo {\n"
3637  " /* Foo trailing\n"
3638  " */\n"
3639  " // detached before oneof\n"
3640  " /* bar leading\n"
3641  " * line 2 */\n"
3642  " $b$oneof bar {\n"
3643  " /* bar trailing\n"
3644  " * line 2 */\n"
3645  " // detached before bar_int\n"
3646  " /* bar_int leading\n"
3647  " */\n"
3648  " $c$int32 bar_int = 1;$d$ // bar_int trailing\n"
3649  " // detach comment ignored\n"
3650  " }$e$\n"
3651  "}$f$\n"));
3652 
3653  const DescriptorProto& foo = file_.message_type(0);
3654  const OneofDescriptorProto& bar = foo.oneof_decl(0);
3655  const FieldDescriptorProto& bar_int = foo.field(0);
3656 
3657  EXPECT_TRUE(HasSpanWithComment('a', 'f', foo, " Foo leading\n",
3658  " Foo trailing\n", NULL));
3659  EXPECT_TRUE(HasSpanWithComment('b', 'e', bar, " bar leading\n line 2 ",
3660  " bar trailing\n line 2 ",
3661  " detached before oneof\n"));
3662  EXPECT_TRUE(HasSpanWithComment('c', 'd', bar_int, " bar_int leading\n",
3663  " bar_int trailing\n",
3664  " detached before bar_int\n"));
3665 
3666  // Ignore these.
3667  EXPECT_TRUE(HasSpan(file_));
3668  EXPECT_TRUE(HasSpan(foo, "name"));
3669  EXPECT_TRUE(HasSpan(bar, "name"));
3670  EXPECT_TRUE(HasSpan(bar_int, "type"));
3671  EXPECT_TRUE(HasSpan(bar_int, "name"));
3672  EXPECT_TRUE(HasSpan(bar_int, "number"));
3673 }
3674 
3675 // ===================================================================
3676 
3677 } // anonymous namespace
3678 
3679 } // namespace compiler
3680 } // namespace protobuf
3681 } // namespace google
EXPECT_FALSE
#define EXPECT_FALSE(condition)
Definition: bloaty/third_party/googletest/googletest/include/gtest/gtest.h:1970
text_
std::string text_
Definition: protobuf/src/google/protobuf/compiler/parser_unittest.cc:68
FileDescriptorProto::add_message_type
PROTOBUF_NAMESPACE_ID::DescriptorProto * add_message_type()
Definition: bloaty/third_party/protobuf/src/google/protobuf/descriptor.pb.h:7692
require_syntax_identifier_
bool require_syntax_identifier_
Definition: protobuf/src/google/protobuf/compiler/parser_unittest.cc:186
filename
const char * filename
Definition: bloaty/third_party/zlib/contrib/minizip/ioapi.h:135
google::protobuf::value
const Descriptor::ReservedRange value
Definition: bloaty/third_party/protobuf/src/google/protobuf/descriptor.h:1954
error_collector_
MockErrorCollector error_collector_
Definition: protobuf/src/google/protobuf/compiler/parser_unittest.cc:180
pos
int pos
Definition: libuv/docs/code/tty-gravity/main.c:11
find
static void ** find(grpc_chttp2_stream_map *map, uint32_t key)
Definition: stream_map.cc:99
google::protobuf::extension
const Descriptor::ReservedRange const EnumValueDescriptor const MethodDescriptor extension
Definition: bloaty/third_party/protobuf/src/google/protobuf/descriptor.h:2001
file
const grpc_generator::File * file
Definition: python_private_generator.h:38
FileDescriptorProto::clear_source_code_info
void clear_source_code_info()
Definition: bloaty/third_party/protobuf/src/google/protobuf/descriptor.pb.h:7896
markers_
std::map< char, std::pair< int, int > > markers_
Definition: protobuf/src/google/protobuf/compiler/parser_unittest.cc:2744
element_name
std::string element_name
Definition: bloaty/third_party/protobuf/src/google/protobuf/descriptor.cc:3096
google::protobuf::DescriptorPool::ErrorCollector::IMPORT
@ IMPORT
Definition: bloaty/third_party/protobuf/src/google/protobuf/descriptor.h:1648
FileDescriptorProto::source_code_info
const PROTOBUF_NAMESPACE_ID::SourceCodeInfo & source_code_info() const
Definition: bloaty/third_party/protobuf/src/google/protobuf/descriptor.pb.h:7905
Group
TypeAndValue Group(UnknownFields nested)
Definition: upb/upb/util/compare_test.cc:101
capstone.range
range
Definition: third_party/bloaty/third_party/capstone/bindings/python/capstone/__init__.py:6
FieldOptions
Definition: bloaty/third_party/protobuf/src/google/protobuf/descriptor.pb.h:4590
bar
Definition: bloaty/third_party/googletest/googletest/test/googletest-output-test_.cc:562
DescriptorProto::nested_type_size
int nested_type_size() const
Definition: bloaty/third_party/protobuf/src/google/protobuf/descriptor.pb.h:8415
input_
std::unique_ptr< io::Tokenizer > input_
Definition: protobuf/src/google/protobuf/compiler/parser_unittest.cc:184
DescriptorProto::descriptor
static const ::PROTOBUF_NAMESPACE_ID::Descriptor * descriptor()
Definition: bloaty/third_party/protobuf/src/google/protobuf/descriptor.pb.h:1350
text_without_markers_
std::string text_without_markers_
Definition: protobuf/src/google/protobuf/compiler/parser_unittest.cc:2745
UninterpretedOption
Definition: bloaty/third_party/protobuf/src/google/protobuf/descriptor.pb.h:6089
FieldDescriptorProto
Definition: bloaty/third_party/protobuf/src/google/protobuf/descriptor.pb.h:1851
FileDescriptor
Definition: bloaty/third_party/protobuf/ruby/ext/google/protobuf_c/protobuf.h:128
GOOGLE_CHECK_EQ
#define GOOGLE_CHECK_EQ(A, B)
Definition: bloaty/third_party/protobuf/src/google/protobuf/stubs/logging.h:156
testing::internal::string
::std::string string
Definition: bloaty/third_party/protobuf/third_party/googletest/googletest/include/gtest/internal/gtest-port.h:881
pool_
DescriptorPool pool_
Definition: protobuf/src/google/protobuf/compiler/parser_unittest.cc:181
UninterpretedOption::name
const PROTOBUF_NAMESPACE_ID::UninterpretedOption_NamePart & name(int index) const
Definition: bloaty/third_party/protobuf/src/google/protobuf/descriptor.pb.h:12945
FileDescriptorProto::service
const PROTOBUF_NAMESPACE_ID::ServiceDescriptorProto & service(int index) const
Definition: bloaty/third_party/protobuf/src/google/protobuf/descriptor.pb.h:7763
file
Definition: bloaty/third_party/zlib/examples/gzappend.c:170
google::protobuf
Definition: bloaty/third_party/protobuf/benchmarks/util/data_proto2_to_proto3_util.h:12
foo
Definition: bloaty/third_party/googletest/googletest/test/googletest-output-test_.cc:546
FileDescriptorProto::add_dependency
std::string * add_dependency()
Definition: bloaty/third_party/protobuf/src/google/protobuf/descriptor.pb.h:7505
MethodDescriptorProto
Definition: bloaty/third_party/protobuf/src/google/protobuf/descriptor.pb.h:3405
SourceCodeInfo::location_size
int location_size() const
Definition: bloaty/third_party/protobuf/src/google/protobuf/descriptor.pb.h:13691
iterator
const typedef MCPhysReg * iterator
Definition: MCRegisterInfo.h:27
DescriptorProto::mutable_nested_type
PROTOBUF_NAMESPACE_ID::DescriptorProto * mutable_nested_type(int index)
Definition: bloaty/third_party/protobuf/src/google/protobuf/descriptor.pb.h:8421
message
char * message
Definition: libuv/docs/code/tty-gravity/main.c:12
EnumValueDescriptorProto
Definition: bloaty/third_party/protobuf/src/google/protobuf/descriptor.pb.h:2972
Descriptor
Definition: bloaty/third_party/protobuf/ruby/ext/google/protobuf_c/protobuf.h:121
testing::Test
Definition: bloaty/third_party/googletest/googletest/include/gtest/gtest.h:402
RepeatedField::size
int size
Definition: bloaty/third_party/protobuf/ruby/ext/google/protobuf_c/protobuf.h:407
EXPECT_EQ
#define EXPECT_EQ(a, b)
Definition: iomgr/time_averaged_stats_test.cc:27
EnumDescriptorProto_EnumReservedRange
Definition: bloaty/third_party/protobuf/src/google/protobuf/descriptor.pb.h:2527
Oneof
struct Oneof Oneof
Definition: bloaty/third_party/protobuf/php/ext/google/protobuf/protobuf.h:664
FieldDescriptor
Definition: bloaty/third_party/protobuf/ruby/ext/google/protobuf_c/protobuf.h:133
google::protobuf.internal.python_message.Extensions
Extensions
Definition: bloaty/third_party/protobuf/python/google/protobuf/internal/python_message.py:584
FileDescriptorProto::message_type_size
int message_type_size() const
Definition: bloaty/third_party/protobuf/src/google/protobuf/descriptor.pb.h:7667
FieldDescriptorProto::LABEL_OPTIONAL
static constexpr Label LABEL_OPTIONAL
Definition: bloaty/third_party/protobuf/src/google/protobuf/descriptor.pb.h:2044
gen_server_registered_method_bad_client_test_body.text
def text
Definition: gen_server_registered_method_bad_client_test_body.py:50
DescriptorProto_ExtensionRange
Definition: bloaty/third_party/protobuf/src/google/protobuf/descriptor.pb.h:936
FileDescriptorProto::options
const PROTOBUF_NAMESPACE_ID::FileOptions & options() const
Definition: bloaty/third_party/protobuf/src/google/protobuf/descriptor.pb.h:7837
FileDescriptorProto::message_type
const PROTOBUF_NAMESPACE_ID::DescriptorProto & message_type(int index) const
Definition: bloaty/third_party/protobuf/src/google/protobuf/descriptor.pb.h:7685
google::protobuf::CaptureTestStderr
void CaptureTestStderr()
Definition: bloaty/third_party/protobuf/src/google/protobuf/testing/googletest.cc:215
FieldDescriptorProto::TYPE_INT32
static constexpr Type TYPE_INT32
Definition: bloaty/third_party/protobuf/src/google/protobuf/descriptor.pb.h:1990
google::protobuf::GetCapturedTestStderr
string GetCapturedTestStderr()
Definition: bloaty/third_party/protobuf/src/google/protobuf/testing/googletest.cc:245
gmock_output_test.output
output
Definition: bloaty/third_party/googletest/googlemock/test/gmock_output_test.py:175
root
RefCountedPtr< grpc_tls_certificate_provider > root
Definition: xds_server_config_fetcher.cc:223
file_
FileDescriptorProto file_
Definition: protobuf/src/google/protobuf/compiler/parser_unittest.cc:2562
spans_
SpanMap spans_
Definition: protobuf/src/google/protobuf/compiler/parser_unittest.cc:2743
FileDescriptorProto::set_name
void set_name(const std::string &value)
Definition: bloaty/third_party/protobuf/src/google/protobuf/descriptor.pb.h:7325
FileDescriptorProto::set_package
void set_package(const std::string &value)
Definition: bloaty/third_party/protobuf/src/google/protobuf/descriptor.pb.h:7418
google::protobuf::TextFormat::ParseFromString
static bool ParseFromString(const std::string &input, Message *output)
Definition: bloaty/third_party/protobuf/src/google/protobuf/text_format.cc:1485
source_locations_
const SourceLocationTable & source_locations_
Definition: protobuf/src/google/protobuf/compiler/parser_unittest.cc:102
google::protobuf::TestUtil::MaybeTranslatePath
std::string MaybeTranslatePath(const std::string &google3_path)
Definition: bloaty/third_party/protobuf/src/google/protobuf/test_util2.h:55
googletest-filter-unittest.child
child
Definition: bloaty/third_party/googletest/googletest/test/googletest-filter-unittest.py:62
FileDescriptorProto::descriptor
static const ::PROTOBUF_NAMESPACE_ID::Descriptor * descriptor()
Definition: bloaty/third_party/protobuf/src/google/protobuf/descriptor.pb.h:539
absl::flags_internal::Parse
bool Parse(FlagOpFn op, absl::string_view text, void *dst, std::string *error)
Definition: abseil-cpp/absl/flags/internal/flag.h:125
data
char data[kBufferLength]
Definition: abseil-cpp/absl/strings/internal/str_format/float_conversion.cc:1006
FileDescriptorProto
Definition: bloaty/third_party/protobuf/src/google/protobuf/descriptor.pb.h:501
ADD_FAILURE
#define ADD_FAILURE()
Definition: bloaty/third_party/googletest/googletest/include/gtest/gtest.h:1911
FileDescriptorProto::Clear
PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final
Definition: bloaty/third_party/protobuf/src/google/protobuf/descriptor.pb.cc:1753
SourceCodeInfo_Location::path
::PROTOBUF_NAMESPACE_ID::int32 path(int index) const
Definition: bloaty/third_party/protobuf/src/google/protobuf/descriptor.pb.h:13342
FileDescriptorProto::extension
const PROTOBUF_NAMESPACE_ID::FieldDescriptorProto & extension(int index) const
Definition: bloaty/third_party/protobuf/src/google/protobuf/descriptor.pb.h:7802
parser_
std::unique_ptr< Parser > parser_
Definition: protobuf/src/google/protobuf/compiler/parser_unittest.cc:185
FileDescriptorProto::set_dependency
void set_dependency(int index, const std::string &value)
Definition: bloaty/third_party/protobuf/src/google/protobuf/descriptor.pb.h:7520
FileDescriptorProto::mutable_message_type
PROTOBUF_NAMESPACE_ID::DescriptorProto * mutable_message_type(int index)
Definition: bloaty/third_party/protobuf/src/google/protobuf/descriptor.pb.h:7673
FileDescriptorProto::add_extension
PROTOBUF_NAMESPACE_ID::FieldDescriptorProto * add_extension()
Definition: bloaty/third_party/protobuf/src/google/protobuf/descriptor.pb.h:7809
FieldDescriptorProto::TYPE_MESSAGE
static constexpr Type TYPE_MESSAGE
Definition: bloaty/third_party/protobuf/src/google/protobuf/descriptor.pb.h:2002
testing::Values
internal::ValueArray< T... > Values(T... v)
Definition: bloaty/third_party/googletest/googletest/include/gtest/gtest-param-test.h:335
EnumDescriptorProto
Definition: bloaty/third_party/protobuf/src/google/protobuf/descriptor.pb.h:2705
EnumValueOptions
Definition: bloaty/third_party/protobuf/src/google/protobuf/descriptor.pb.h:5287
SourceCodeInfo_Location
Definition: bloaty/third_party/protobuf/src/google/protobuf/descriptor.pb.h:6397
google::protobuf::TEST_F
TEST_F(DynamicMessageTest, Descriptor)
Definition: bloaty/third_party/protobuf/src/google/protobuf/dynamic_message_unittest.cc:126
GOOGLE_ARRAYSIZE
#define GOOGLE_ARRAYSIZE(a)
Definition: bloaty/third_party/protobuf/src/google/protobuf/stubs/macros.h:88
SourceCodeInfo
Definition: bloaty/third_party/protobuf/src/google/protobuf/descriptor.pb.h:6683
ETC
#define ETC
regen-readme.line
line
Definition: regen-readme.py:30
ASSERT_TRUE
#define ASSERT_TRUE(condition)
Definition: bloaty/third_party/googletest/googletest/include/gtest/gtest.h:1973
OneofDescriptorProto
Definition: bloaty/third_party/protobuf/src/google/protobuf/descriptor.pb.h:2328
DescriptorProto
Definition: bloaty/third_party/protobuf/src/google/protobuf/descriptor.pb.h:1312
wrapped_collector_
io::ErrorCollector * wrapped_collector_
Definition: protobuf/src/google/protobuf/compiler/parser_unittest.cc:103
raw_input_
std::unique_ptr< io::ZeroCopyInputStream > raw_input_
Definition: protobuf/src/google/protobuf/compiler/parser_unittest.cc:183
input
std::string input
Definition: bloaty/third_party/protobuf/src/google/protobuf/io/tokenizer_unittest.cc:197
field
const FieldDescriptor * field
Definition: protobuf/src/google/protobuf/compiler/parser_unittest.cc:2723
EXPECT_TRUE
#define EXPECT_TRUE(condition)
Definition: bloaty/third_party/googletest/googletest/include/gtest/gtest.h:1967
FileDescriptorProto::enum_type
const PROTOBUF_NAMESPACE_ID::EnumDescriptorProto & enum_type(int index) const
Definition: bloaty/third_party/protobuf/src/google/protobuf/descriptor.pb.h:7724
descriptor_proto
const Message * descriptor_proto
Definition: protobuf/src/google/protobuf/compiler/parser_unittest.cc:2722
GOOGLE_CHECK_NE
#define GOOGLE_CHECK_NE(A, B)
Definition: bloaty/third_party/protobuf/src/google/protobuf/stubs/logging.h:157
iter
Definition: test_winkernel.cpp:47
google::protobuf::FieldDescriptor::CPPTYPE_MESSAGE
@ CPPTYPE_MESSAGE
Definition: bloaty/third_party/protobuf/src/google/protobuf/descriptor.h:563
google::protobuf::Join
void Join(Iterator start, Iterator end, const char *delim, string *result)
Definition: bloaty/third_party/protobuf/src/google/protobuf/stubs/strutil.h:769
google::protobuf::io::Tokenizer::TYPE_END
@ TYPE_END
Definition: bloaty/third_party/protobuf/src/google/protobuf/io/tokenizer.h:103
SourceCodeInfo::location
const PROTOBUF_NAMESPACE_ID::SourceCodeInfo_Location & location(int index) const
Definition: bloaty/third_party/protobuf/src/google/protobuf/descriptor.pb.h:13709
DescriptorProto::name
const std::string & name() const
Definition: bloaty/third_party/protobuf/src/google/protobuf/descriptor.pb.h:8252
DescriptorProto::field_size
int field_size() const
Definition: bloaty/third_party/protobuf/src/google/protobuf/descriptor.pb.h:8337
size
voidpf void uLong size
Definition: bloaty/third_party/zlib/contrib/minizip/ioapi.h:136
google::protobuf::operator<
bool operator<(StringPiece x, StringPiece y)
Definition: bloaty/third_party/protobuf/src/google/protobuf/stubs/stringpiece.h:412
DescriptorProto::mutable_field
PROTOBUF_NAMESPACE_ID::FieldDescriptorProto * mutable_field(int index)
Definition: bloaty/third_party/protobuf/src/google/protobuf/descriptor.pb.h:8343
DescriptorPool
Definition: bloaty/third_party/protobuf/ruby/ext/google/protobuf_c/protobuf.h:110
descriptor
static const char descriptor[1336]
Definition: certs.upbdefs.c:16
index
int index
Definition: protobuf/src/google/protobuf/compiler/parser_unittest.cc:2724
compiler
Definition: bloaty/third_party/protobuf/src/google/protobuf/compiler/plugin.pb.cc:21
google
Definition: bloaty/third_party/protobuf/benchmarks/util/data_proto2_to_proto3_util.h:11
DescriptorProto::nested_type
const PROTOBUF_NAMESPACE_ID::DescriptorProto & nested_type(int index) const
Definition: bloaty/third_party/protobuf/src/google/protobuf/descriptor.pb.h:8433
Message
Definition: protobuf/php/ext/google/protobuf/message.c:53
i
uint64_t i
Definition: abseil-cpp/absl/container/btree_benchmark.cc:230
warning_
std::string warning_
Definition: protobuf/src/google/protobuf/compiler/parser_unittest.cc:67
google::protobuf::FindOrDie
const Collection::value_type::second_type & FindOrDie(const Collection &collection, const typename Collection::value_type::first_type &key)
Definition: bloaty/third_party/protobuf/src/google/protobuf/stubs/map_util.h:74
type_name
static const char * type_name(int type)
Definition: adig.c:889
DescriptorProto_ReservedRange
Definition: bloaty/third_party/protobuf/src/google/protobuf/descriptor.pb.h:1134
DescriptorProto::field
const PROTOBUF_NAMESPACE_ID::FieldDescriptorProto & field(int index) const
Definition: bloaty/third_party/protobuf/src/google/protobuf/descriptor.pb.h:8355
ASSERT_EQ
#define ASSERT_EQ(val1, val2)
Definition: bloaty/third_party/googletest/googletest/include/gtest/gtest.h:2056
google::protobuf::strings::SubstituteAndAppend
void SubstituteAndAppend(string *output, 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: bloaty/third_party/protobuf/src/google/protobuf/stubs/substitute.cc:68
RepeatedField
Definition: bloaty/third_party/protobuf/ruby/ext/google/protobuf_c/protobuf.h:403


grpc
Author(s):
autogenerated on Fri May 16 2025 02:59:40