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


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