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