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