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