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