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