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