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