| OLD | NEW |
| 1 // Protocol Buffers - Google's data interchange format | 1 // Protocol Buffers - Google's data interchange format |
| 2 // Copyright 2008 Google Inc. All rights reserved. | 2 // Copyright 2008 Google Inc. All rights reserved. |
| 3 // http://code.google.com/p/protobuf/ | 3 // https://developers.google.com/protocol-buffers/ |
| 4 // | 4 // |
| 5 // Redistribution and use in source and binary forms, with or without | 5 // Redistribution and use in source and binary forms, with or without |
| 6 // modification, are permitted provided that the following conditions are | 6 // modification, are permitted provided that the following conditions are |
| 7 // met: | 7 // met: |
| 8 // | 8 // |
| 9 // * Redistributions of source code must retain the above copyright | 9 // * Redistributions of source code must retain the above copyright |
| 10 // notice, this list of conditions and the following disclaimer. | 10 // notice, this list of conditions and the following disclaimer. |
| 11 // * Redistributions in binary form must reproduce the above | 11 // * Redistributions in binary form must reproduce the above |
| 12 // copyright notice, this list of conditions and the following disclaimer | 12 // copyright notice, this list of conditions and the following disclaimer |
| 13 // in the documentation and/or other materials provided with the | 13 // in the documentation and/or other materials provided with the |
| (...skipping 11 matching lines...) Expand all Loading... |
| 25 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | 25 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
| 26 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 26 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| 27 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 27 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| 28 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 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. | 29 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 30 | 30 |
| 31 // Author: kenton@google.com (Kenton Varda) | 31 // Author: kenton@google.com (Kenton Varda) |
| 32 // Based on original Protocol Buffers design by | 32 // Based on original Protocol Buffers design by |
| 33 // Sanjay Ghemawat, Jeff Dean, and others. | 33 // Sanjay Ghemawat, Jeff Dean, and others. |
| 34 | 34 |
| 35 #include <memory> |
| 36 #ifndef _SHARED_PTR_H |
| 37 #include <google/protobuf/stubs/shared_ptr.h> |
| 38 #endif |
| 35 #include <vector> | 39 #include <vector> |
| 36 #include <algorithm> | 40 #include <algorithm> |
| 37 #include <map> | 41 #include <map> |
| 38 | 42 |
| 39 #include <google/protobuf/compiler/parser.h> | 43 #include <google/protobuf/compiler/parser.h> |
| 40 | 44 |
| 41 #include <google/protobuf/io/tokenizer.h> | 45 #include <google/protobuf/io/tokenizer.h> |
| 42 #include <google/protobuf/io/zero_copy_stream_impl.h> | 46 #include <google/protobuf/io/zero_copy_stream_impl.h> |
| 43 #include <google/protobuf/descriptor.pb.h> | 47 #include <google/protobuf/descriptor.pb.h> |
| 44 #include <google/protobuf/wire_format.h> | 48 #include <google/protobuf/wire_format.h> |
| 45 #include <google/protobuf/text_format.h> | 49 #include <google/protobuf/text_format.h> |
| 46 #include <google/protobuf/unittest.pb.h> | 50 #include <google/protobuf/unittest.pb.h> |
| 47 #include <google/protobuf/unittest_custom_options.pb.h> | 51 #include <google/protobuf/unittest_custom_options.pb.h> |
| 48 #include <google/protobuf/stubs/strutil.h> | 52 #include <google/protobuf/stubs/strutil.h> |
| 49 #include <google/protobuf/stubs/substitute.h> | 53 #include <google/protobuf/stubs/substitute.h> |
| 50 #include <google/protobuf/stubs/map-util.h> | 54 #include <google/protobuf/stubs/map_util.h> |
| 51 | 55 |
| 52 #include <google/protobuf/testing/googletest.h> | 56 #include <google/protobuf/testing/googletest.h> |
| 53 #include <gtest/gtest.h> | 57 #include <gtest/gtest.h> |
| 54 | 58 |
| 55 namespace google { | 59 namespace google { |
| 56 namespace protobuf { | 60 namespace protobuf { |
| 57 namespace compiler { | 61 namespace compiler { |
| 58 | 62 |
| 59 namespace { | 63 namespace { |
| 60 | 64 |
| (...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 167 MockValidationErrorCollector validation_error_collector( | 171 MockValidationErrorCollector validation_error_collector( |
| 168 source_locations, &error_collector_); | 172 source_locations, &error_collector_); |
| 169 EXPECT_TRUE(pool_.BuildFileCollectingErrors( | 173 EXPECT_TRUE(pool_.BuildFileCollectingErrors( |
| 170 file, &validation_error_collector) == NULL); | 174 file, &validation_error_collector) == NULL); |
| 171 EXPECT_EQ(expected_errors, error_collector_.text_); | 175 EXPECT_EQ(expected_errors, error_collector_.text_); |
| 172 } | 176 } |
| 173 | 177 |
| 174 MockErrorCollector error_collector_; | 178 MockErrorCollector error_collector_; |
| 175 DescriptorPool pool_; | 179 DescriptorPool pool_; |
| 176 | 180 |
| 177 scoped_ptr<io::ZeroCopyInputStream> raw_input_; | 181 google::protobuf::scoped_ptr<io::ZeroCopyInputStream> raw_input_; |
| 178 scoped_ptr<io::Tokenizer> input_; | 182 google::protobuf::scoped_ptr<io::Tokenizer> input_; |
| 179 scoped_ptr<Parser> parser_; | 183 google::protobuf::scoped_ptr<Parser> parser_; |
| 180 bool require_syntax_identifier_; | 184 bool require_syntax_identifier_; |
| 181 }; | 185 }; |
| 182 | 186 |
| 183 // =================================================================== | 187 // =================================================================== |
| 184 | 188 |
| 185 TEST_F(ParserTest, StopAfterSyntaxIdentifier) { | 189 TEST_F(ParserTest, StopAfterSyntaxIdentifier) { |
| 186 SetupParser( | 190 SetupParser( |
| 187 "// blah\n" | 191 "// blah\n" |
| 188 "syntax = \"foobar\";\n" | 192 "syntax = \"foobar\";\n" |
| 189 "this line will not be parsed\n"); | 193 "this line will not be parsed\n"); |
| (...skipping 15 matching lines...) Expand all Loading... |
| 205 | 209 |
| 206 TEST_F(ParserTest, StopAfterSyntaxIdentifierWithErrors) { | 210 TEST_F(ParserTest, StopAfterSyntaxIdentifierWithErrors) { |
| 207 SetupParser( | 211 SetupParser( |
| 208 "// blah\n" | 212 "// blah\n" |
| 209 "syntax = error;\n"); | 213 "syntax = error;\n"); |
| 210 parser_->SetStopAfterSyntaxIdentifier(true); | 214 parser_->SetStopAfterSyntaxIdentifier(true); |
| 211 EXPECT_FALSE(parser_->Parse(input_.get(), NULL)); | 215 EXPECT_FALSE(parser_->Parse(input_.get(), NULL)); |
| 212 EXPECT_EQ("1:9: Expected syntax identifier.\n", error_collector_.text_); | 216 EXPECT_EQ("1:9: Expected syntax identifier.\n", error_collector_.text_); |
| 213 } | 217 } |
| 214 | 218 |
| 219 TEST_F(ParserTest, WarnIfSyntaxIdentifierOmmitted) { |
| 220 SetupParser("message A {}"); |
| 221 FileDescriptorProto file; |
| 222 CaptureTestStderr(); |
| 223 EXPECT_TRUE(parser_->Parse(input_.get(), &file)); |
| 224 EXPECT_TRUE( |
| 225 GetCapturedTestStderr().find("No syntax specified") != string::npos); |
| 226 } |
| 227 |
| 215 // =================================================================== | 228 // =================================================================== |
| 216 | 229 |
| 217 typedef ParserTest ParseMessageTest; | 230 typedef ParserTest ParseMessageTest; |
| 218 | 231 |
| 232 TEST_F(ParseMessageTest, IgnoreBOM) { |
| 233 char input[] = " message TestMessage {\n" |
| 234 " required int32 foo = 1;\n" |
| 235 "}\n"; |
| 236 // Set UTF-8 BOM. |
| 237 input[0] = (char)0xEF; |
| 238 input[1] = (char)0xBB; |
| 239 input[2] = (char)0xBF; |
| 240 ExpectParsesTo(input, |
| 241 "message_type {" |
| 242 " name: \"TestMessage\"" |
| 243 " field { name:\"foo\" label:LABEL_REQUIRED type:TYPE_INT32 number:1 }" |
| 244 "}"); |
| 245 } |
| 246 |
| 247 TEST_F(ParseMessageTest, BOMError) { |
| 248 char input[] = " message TestMessage {\n" |
| 249 " required int32 foo = 1;\n" |
| 250 "}\n"; |
| 251 input[0] = (char)0xEF; |
| 252 ExpectHasErrors(input, |
| 253 "0:1: Proto file starts with 0xEF but not UTF-8 BOM. " |
| 254 "Only UTF-8 is accepted for proto file.\n" |
| 255 "0:0: Expected top-level statement (e.g. \"message\").\n"); |
| 256 } |
| 257 |
| 219 TEST_F(ParseMessageTest, SimpleMessage) { | 258 TEST_F(ParseMessageTest, SimpleMessage) { |
| 220 ExpectParsesTo( | 259 ExpectParsesTo( |
| 221 "message TestMessage {\n" | 260 "message TestMessage {\n" |
| 222 " required int32 foo = 1;\n" | 261 " required int32 foo = 1;\n" |
| 223 "}\n", | 262 "}\n", |
| 224 | 263 |
| 225 "message_type {" | 264 "message_type {" |
| 226 " name: \"TestMessage\"" | 265 " name: \"TestMessage\"" |
| 227 " field { name:\"foo\" label:LABEL_REQUIRED type:TYPE_INT32 number:1 }" | 266 " field { name:\"foo\" label:LABEL_REQUIRED type:TYPE_INT32 number:1 }" |
| 228 "}"); | 267 "}"); |
| (...skipping 13 matching lines...) Expand all Loading... |
| 242 EXPECT_EQ("proto2", parser_->GetSyntaxIdentifier()); | 281 EXPECT_EQ("proto2", parser_->GetSyntaxIdentifier()); |
| 243 } | 282 } |
| 244 | 283 |
| 245 TEST_F(ParseMessageTest, ExplicitSyntaxIdentifier) { | 284 TEST_F(ParseMessageTest, ExplicitSyntaxIdentifier) { |
| 246 ExpectParsesTo( | 285 ExpectParsesTo( |
| 247 "syntax = \"proto2\";\n" | 286 "syntax = \"proto2\";\n" |
| 248 "message TestMessage {\n" | 287 "message TestMessage {\n" |
| 249 " required int32 foo = 1;\n" | 288 " required int32 foo = 1;\n" |
| 250 "}\n", | 289 "}\n", |
| 251 | 290 |
| 291 "syntax: 'proto2' " |
| 252 "message_type {" | 292 "message_type {" |
| 253 " name: \"TestMessage\"" | 293 " name: \"TestMessage\"" |
| 254 " field { name:\"foo\" label:LABEL_REQUIRED type:TYPE_INT32 number:1 }" | 294 " field { name:\"foo\" label:LABEL_REQUIRED type:TYPE_INT32 number:1 }" |
| 255 "}"); | 295 "}"); |
| 256 EXPECT_EQ("proto2", parser_->GetSyntaxIdentifier()); | 296 EXPECT_EQ("proto2", parser_->GetSyntaxIdentifier()); |
| 257 } | 297 } |
| 258 | 298 |
| 259 TEST_F(ParseMessageTest, ExplicitRequiredSyntaxIdentifier) { | 299 TEST_F(ParseMessageTest, ExplicitRequiredSyntaxIdentifier) { |
| 260 require_syntax_identifier_ = true; | 300 require_syntax_identifier_ = true; |
| 261 ExpectParsesTo( | 301 ExpectParsesTo( |
| 262 "syntax = \"proto2\";\n" | 302 "syntax = \"proto2\";\n" |
| 263 "message TestMessage {\n" | 303 "message TestMessage {\n" |
| 264 " required int32 foo = 1;\n" | 304 " required int32 foo = 1;\n" |
| 265 "}\n", | 305 "}\n", |
| 266 | 306 |
| 307 "syntax: 'proto2' " |
| 267 "message_type {" | 308 "message_type {" |
| 268 " name: \"TestMessage\"" | 309 " name: \"TestMessage\"" |
| 269 " field { name:\"foo\" label:LABEL_REQUIRED type:TYPE_INT32 number:1 }" | 310 " field { name:\"foo\" label:LABEL_REQUIRED type:TYPE_INT32 number:1 }" |
| 270 "}"); | 311 "}"); |
| 271 EXPECT_EQ("proto2", parser_->GetSyntaxIdentifier()); | 312 EXPECT_EQ("proto2", parser_->GetSyntaxIdentifier()); |
| 272 } | 313 } |
| 273 | 314 |
| 274 TEST_F(ParseMessageTest, SimpleFields) { | 315 TEST_F(ParseMessageTest, SimpleFields) { |
| 275 ExpectParsesTo( | 316 ExpectParsesTo( |
| 276 "message TestMessage {\n" | 317 "message TestMessage {\n" |
| (...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 357 " required uint32 foo = 1 [default= 0xFFFFFFFF];\n" | 398 " required uint32 foo = 1 [default= 0xFFFFFFFF];\n" |
| 358 " required int64 foo = 1 [default= 0x7FFFFFFFFFFFFFFF];\n" | 399 " required int64 foo = 1 [default= 0x7FFFFFFFFFFFFFFF];\n" |
| 359 " required int64 foo = 1 [default=-0x8000000000000000];\n" | 400 " required int64 foo = 1 [default=-0x8000000000000000];\n" |
| 360 " required uint64 foo = 1 [default= 0xFFFFFFFFFFFFFFFF];\n" | 401 " required uint64 foo = 1 [default= 0xFFFFFFFFFFFFFFFF];\n" |
| 361 " required double foo = 1 [default= 0xabcd];\n" | 402 " required double foo = 1 [default= 0xabcd];\n" |
| 362 "}\n", | 403 "}\n", |
| 363 | 404 |
| 364 #define ETC "name:\"foo\" label:LABEL_REQUIRED number:1" | 405 #define ETC "name:\"foo\" label:LABEL_REQUIRED number:1" |
| 365 "message_type {" | 406 "message_type {" |
| 366 " name: \"TestMessage\"" | 407 " name: \"TestMessage\"" |
| 367 " field { type:TYPE_INT32 default_value:\"1\" "ETC" }" | 408 " field { type:TYPE_INT32 default_value:\"1\" " ETC " }" |
| 368 " field { type:TYPE_INT32 default_value:\"-2\" "ETC" }" | 409 " field { type:TYPE_INT32 default_value:\"-2\" " ETC " }" |
| 369 " field { type:TYPE_INT64 default_value:\"3\" "ETC" }" | 410 " field { type:TYPE_INT64 default_value:\"3\" " ETC " }" |
| 370 " field { type:TYPE_INT64 default_value:\"-4\" "ETC" }" | 411 " field { type:TYPE_INT64 default_value:\"-4\" " ETC " }" |
| 371 " field { type:TYPE_UINT32 default_value:\"5\" "ETC" }" | 412 " field { type:TYPE_UINT32 default_value:\"5\" " ETC " }" |
| 372 " field { type:TYPE_UINT64 default_value:\"6\" "ETC" }" | 413 " field { type:TYPE_UINT64 default_value:\"6\" " ETC " }" |
| 373 " field { type:TYPE_FLOAT default_value:\"7.5\" "ETC" }" | 414 " field { type:TYPE_FLOAT default_value:\"7.5\" " ETC " }" |
| 374 " field { type:TYPE_FLOAT default_value:\"-8.5\" "ETC" }" | 415 " field { type:TYPE_FLOAT default_value:\"-8.5\" " ETC " }" |
| 375 " field { type:TYPE_FLOAT default_value:\"9\" "ETC" }" | 416 " field { type:TYPE_FLOAT default_value:\"9\" " ETC " }" |
| 376 " field { type:TYPE_DOUBLE default_value:\"10.5\" "ETC" }" | 417 " field { type:TYPE_DOUBLE default_value:\"10.5\" " ETC " }" |
| 377 " field { type:TYPE_DOUBLE default_value:\"-11.5\" "ETC" }" | 418 " field { type:TYPE_DOUBLE default_value:\"-11.5\" " ETC " }" |
| 378 " field { type:TYPE_DOUBLE default_value:\"12\" "ETC" }" | 419 " field { type:TYPE_DOUBLE default_value:\"12\" " ETC " }" |
| 379 " field { type:TYPE_DOUBLE default_value:\"inf\" "ETC" }" | 420 " field { type:TYPE_DOUBLE default_value:\"inf\" " ETC " }" |
| 380 " field { type:TYPE_DOUBLE default_value:\"-inf\" "ETC" }" | 421 " field { type:TYPE_DOUBLE default_value:\"-inf\" " ETC " }" |
| 381 " field { type:TYPE_DOUBLE default_value:\"nan\" "ETC" }" | 422 " field { type:TYPE_DOUBLE default_value:\"nan\" " ETC " }" |
| 382 " field { type:TYPE_STRING default_value:\"13\\001\" "ETC" }" | 423 " field { type:TYPE_STRING default_value:\"13\\001\" " ETC " }" |
| 383 " field { type:TYPE_STRING default_value:\"abc\" "ETC" }" | 424 " field { type:TYPE_STRING default_value:\"abc\" " ETC " }" |
| 384 " field { type:TYPE_BYTES default_value:\"14\\\\002\" "ETC" }" | 425 " field { type:TYPE_BYTES default_value:\"14\\\\002\" " ETC " }" |
| 385 " field { type:TYPE_BYTES default_value:\"abc\" "ETC" }" | 426 " field { type:TYPE_BYTES default_value:\"abc\" " ETC " }" |
| 386 " field { type:TYPE_BOOL default_value:\"true\" "ETC" }" | 427 " field { type:TYPE_BOOL default_value:\"true\" " ETC " }" |
| 387 " field { type_name:\"Foo\" default_value:\"FOO\" "ETC" }" | 428 " field { type_name:\"Foo\" default_value:\"FOO\" " ETC " }" |
| 388 | 429 |
| 389 " field { type:TYPE_INT32 default_value:\"2147483647\" "ETC" }" | 430 " field {" |
| 390 " field { type:TYPE_INT32 default_value:\"-2147483648\" "ETC" }" | 431 " type:TYPE_INT32 default_value:\"2147483647\" " ETC |
| 391 " field { type:TYPE_UINT32 default_value:\"4294967295\" "ETC" }" | 432 " }" |
| 392 " field { type:TYPE_INT64 default_value:\"9223372036854775807\" "ETC" }" | 433 " field {" |
| 393 " field { type:TYPE_INT64 default_value:\"-9223372036854775808\" "ETC" }" | 434 " type:TYPE_INT32 default_value:\"-2147483648\" " ETC |
| 394 " field { type:TYPE_UINT64 default_value:\"18446744073709551615\" "ETC" }" | 435 " }" |
| 395 " field { type:TYPE_DOUBLE default_value:\"43981\" "ETC" }" | 436 " field {" |
| 437 " type:TYPE_UINT32 default_value:\"4294967295\" " ETC |
| 438 " }" |
| 439 " field {" |
| 440 " type:TYPE_INT64 default_value:\"9223372036854775807\" " ETC |
| 441 " }" |
| 442 " field {" |
| 443 " type:TYPE_INT64 default_value:\"-9223372036854775808\" " ETC |
| 444 " }" |
| 445 " field {" |
| 446 " type:TYPE_UINT64 default_value:\"18446744073709551615\" " ETC |
| 447 " }" |
| 448 " field {" |
| 449 " type:TYPE_DOUBLE default_value:\"43981\" " ETC |
| 450 " }" |
| 396 "}"); | 451 "}"); |
| 397 #undef ETC | 452 #undef ETC |
| 398 } | 453 } |
| 399 | 454 |
| 455 TEST_F(ParseMessageTest, FieldJsonName) { |
| 456 ExpectParsesTo( |
| 457 "message TestMessage {\n" |
| 458 " optional string foo = 1 [json_name = \"@type\"];\n" |
| 459 "}\n", |
| 460 "message_type {" |
| 461 " name: \"TestMessage\"" |
| 462 " field {\n" |
| 463 " name: \"foo\" label: LABEL_OPTIONAL type: TYPE_STRING number: 1" |
| 464 " json_name: \"@type\"\n" |
| 465 " }\n" |
| 466 "}\n"); |
| 467 } |
| 468 |
| 400 TEST_F(ParseMessageTest, FieldOptions) { | 469 TEST_F(ParseMessageTest, FieldOptions) { |
| 401 ExpectParsesTo( | 470 ExpectParsesTo( |
| 402 "message TestMessage {\n" | 471 "message TestMessage {\n" |
| 403 " optional string foo = 1\n" | 472 " optional string foo = 1\n" |
| 404 " [ctype=CORD, (foo)=7, foo.(.bar.baz).qux.quux.(corge)=-33, \n" | 473 " [ctype=CORD, (foo)=7, foo.(.bar.baz).qux.quux.(corge)=-33, \n" |
| 405 " (quux)=\"x\040y\", (baz.qux)=hey];\n" | 474 " (quux)=\"x\040y\", (baz.qux)=hey];\n" |
| 406 "}\n", | 475 "}\n", |
| 407 | 476 |
| 408 "message_type {" | 477 "message_type {" |
| 409 " name: \"TestMessage\"" | 478 " name: \"TestMessage\"" |
| (...skipping 19 matching lines...) Expand all Loading... |
| 429 " is_extension: true } " | 498 " is_extension: true } " |
| 430 " string_value: \"x y\" }" | 499 " string_value: \"x y\" }" |
| 431 " uninterpreted_option: { name { name_part: \"baz.qux\" " | 500 " uninterpreted_option: { name { name_part: \"baz.qux\" " |
| 432 " is_extension: true } " | 501 " is_extension: true } " |
| 433 " identifier_value: \"hey\" }" | 502 " identifier_value: \"hey\" }" |
| 434 " }" | 503 " }" |
| 435 " }" | 504 " }" |
| 436 "}"); | 505 "}"); |
| 437 } | 506 } |
| 438 | 507 |
| 508 TEST_F(ParseMessageTest, Oneof) { |
| 509 ExpectParsesTo( |
| 510 "message TestMessage {\n" |
| 511 " oneof foo {\n" |
| 512 " int32 a = 1;\n" |
| 513 " string b = 2;\n" |
| 514 " TestMessage c = 3;\n" |
| 515 " group D = 4 { optional int32 i = 5; }\n" |
| 516 " }\n" |
| 517 "}\n", |
| 518 |
| 519 "message_type {" |
| 520 " name: \"TestMessage\"" |
| 521 " field { name:\"a\" label:LABEL_OPTIONAL type:TYPE_INT32 number:1 " |
| 522 " oneof_index:0 }" |
| 523 " field { name:\"b\" label:LABEL_OPTIONAL type:TYPE_STRING number:2 " |
| 524 " oneof_index:0 }" |
| 525 " field { name:\"c\" label:LABEL_OPTIONAL type_name:\"TestMessage\" " |
| 526 " number:3 oneof_index:0 }" |
| 527 " field { name:\"d\" label:LABEL_OPTIONAL type:TYPE_GROUP " |
| 528 " type_name:\"D\" number:4 oneof_index:0 }" |
| 529 " oneof_decl {" |
| 530 " name: \"foo\"" |
| 531 " }" |
| 532 " nested_type {" |
| 533 " name: \"D\"" |
| 534 " field { name:\"i\" label:LABEL_OPTIONAL type:TYPE_INT32 number:5 }" |
| 535 " }" |
| 536 "}"); |
| 537 } |
| 538 |
| 539 TEST_F(ParseMessageTest, MultipleOneofs) { |
| 540 ExpectParsesTo( |
| 541 "message TestMessage {\n" |
| 542 " oneof foo {\n" |
| 543 " int32 a = 1;\n" |
| 544 " string b = 2;\n" |
| 545 " }\n" |
| 546 " oneof bar {\n" |
| 547 " int32 c = 3;\n" |
| 548 " string d = 4;\n" |
| 549 " }\n" |
| 550 "}\n", |
| 551 |
| 552 "message_type {" |
| 553 " name: \"TestMessage\"" |
| 554 " field { name:\"a\" label:LABEL_OPTIONAL type:TYPE_INT32 number:1 " |
| 555 " oneof_index:0 }" |
| 556 " field { name:\"b\" label:LABEL_OPTIONAL type:TYPE_STRING number:2 " |
| 557 " oneof_index:0 }" |
| 558 " field { name:\"c\" label:LABEL_OPTIONAL type:TYPE_INT32 number:3 " |
| 559 " oneof_index:1 }" |
| 560 " field { name:\"d\" label:LABEL_OPTIONAL type:TYPE_STRING number:4 " |
| 561 " oneof_index:1 }" |
| 562 " oneof_decl {" |
| 563 " name: \"foo\"" |
| 564 " }" |
| 565 " oneof_decl {" |
| 566 " name: \"bar\"" |
| 567 " }" |
| 568 "}"); |
| 569 } |
| 570 |
| 571 TEST_F(ParseMessageTest, Maps) { |
| 572 ExpectParsesTo( |
| 573 "message TestMessage {\n" |
| 574 " map<int32, string> primitive_type_map = 1;\n" |
| 575 " map<KeyType, ValueType> composite_type_map = 2;\n" |
| 576 "}\n", |
| 577 |
| 578 "message_type {" |
| 579 " name: \"TestMessage\"" |
| 580 " nested_type {" |
| 581 " name: \"PrimitiveTypeMapEntry\"" |
| 582 " field { " |
| 583 " name: \"key\" number: 1 label:LABEL_OPTIONAL" |
| 584 " type:TYPE_INT32" |
| 585 " }" |
| 586 " field { " |
| 587 " name: \"value\" number: 2 label:LABEL_OPTIONAL" |
| 588 " type:TYPE_STRING" |
| 589 " }" |
| 590 " options { map_entry: true }" |
| 591 " }" |
| 592 " nested_type {" |
| 593 " name: \"CompositeTypeMapEntry\"" |
| 594 " field { " |
| 595 " name: \"key\" number: 1 label:LABEL_OPTIONAL" |
| 596 " type_name: \"KeyType\"" |
| 597 " }" |
| 598 " field { " |
| 599 " name: \"value\" number: 2 label:LABEL_OPTIONAL" |
| 600 " type_name: \"ValueType\"" |
| 601 " }" |
| 602 " options { map_entry: true }" |
| 603 " }" |
| 604 " field {" |
| 605 " name: \"primitive_type_map\"" |
| 606 " label: LABEL_REPEATED" |
| 607 " type_name: \"PrimitiveTypeMapEntry\"" |
| 608 " number: 1" |
| 609 " }" |
| 610 " field {" |
| 611 " name: \"composite_type_map\"" |
| 612 " label: LABEL_REPEATED" |
| 613 " type_name: \"CompositeTypeMapEntry\"" |
| 614 " number: 2" |
| 615 " }" |
| 616 "}"); |
| 617 } |
| 618 |
| 439 TEST_F(ParseMessageTest, Group) { | 619 TEST_F(ParseMessageTest, Group) { |
| 440 ExpectParsesTo( | 620 ExpectParsesTo( |
| 441 "message TestMessage {\n" | 621 "message TestMessage {\n" |
| 442 " optional group TestGroup = 1 {};\n" | 622 " optional group TestGroup = 1 {};\n" |
| 443 "}\n", | 623 "}\n", |
| 444 | 624 |
| 445 "message_type {" | 625 "message_type {" |
| 446 " name: \"TestMessage\"" | 626 " name: \"TestMessage\"" |
| 447 " nested_type { name: \"TestGroup\" }" | 627 " nested_type { name: \"TestGroup\" }" |
| 448 " field { name:\"testgroup\" label:LABEL_OPTIONAL number:1" | 628 " field { name:\"testgroup\" label:LABEL_OPTIONAL number:1" |
| (...skipping 24 matching lines...) Expand all Loading... |
| 473 "}\n", | 653 "}\n", |
| 474 | 654 |
| 475 "message_type {" | 655 "message_type {" |
| 476 " name: \"TestMessage\"" | 656 " name: \"TestMessage\"" |
| 477 " enum_type { name: \"NestedEnum\" }" | 657 " enum_type { name: \"NestedEnum\" }" |
| 478 " field { name:\"test_enum\" label:LABEL_OPTIONAL number:1" | 658 " field { name:\"test_enum\" label:LABEL_OPTIONAL number:1" |
| 479 " type_name: \"NestedEnum\" }" | 659 " type_name: \"NestedEnum\" }" |
| 480 "}"); | 660 "}"); |
| 481 } | 661 } |
| 482 | 662 |
| 663 TEST_F(ParseMessageTest, ReservedRange) { |
| 664 ExpectParsesTo( |
| 665 "message TestMessage {\n" |
| 666 " required int32 foo = 1;\n" |
| 667 " reserved 2, 15, 9 to 11, 3;\n" |
| 668 "}\n", |
| 669 |
| 670 "message_type {" |
| 671 " name: \"TestMessage\"" |
| 672 " field { name:\"foo\" label:LABEL_REQUIRED type:TYPE_INT32 number:1 }" |
| 673 " reserved_range { start:2 end:3 }" |
| 674 " reserved_range { start:15 end:16 }" |
| 675 " reserved_range { start:9 end:12 }" |
| 676 " reserved_range { start:3 end:4 }" |
| 677 "}"); |
| 678 } |
| 679 |
| 680 TEST_F(ParseMessageTest, ReservedNames) { |
| 681 ExpectParsesTo( |
| 682 "message TestMessage {\n" |
| 683 " reserved \"foo\", \"bar\";\n" |
| 684 "}\n", |
| 685 |
| 686 "message_type {" |
| 687 " name: \"TestMessage\"" |
| 688 " reserved_name: \"foo\"" |
| 689 " reserved_name: \"bar\"" |
| 690 "}"); |
| 691 } |
| 692 |
| 483 TEST_F(ParseMessageTest, ExtensionRange) { | 693 TEST_F(ParseMessageTest, ExtensionRange) { |
| 484 ExpectParsesTo( | 694 ExpectParsesTo( |
| 485 "message TestMessage {\n" | 695 "message TestMessage {\n" |
| 486 " extensions 10 to 19;\n" | 696 " extensions 10 to 19;\n" |
| 487 " extensions 30 to max;\n" | 697 " extensions 30 to max;\n" |
| 488 "}\n", | 698 "}\n", |
| 489 | 699 |
| 490 "message_type {" | 700 "message_type {" |
| 491 " name: \"TestMessage\"" | 701 " name: \"TestMessage\"" |
| 492 " extension_range { start:10 end:20 }" | 702 " extension_range { start:10 end:20 }" |
| (...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 568 " optional int32 foo = 12;\n" | 778 " optional int32 foo = 12;\n" |
| 569 " repeated TestMessage bar = 22;\n" | 779 " repeated TestMessage bar = 22;\n" |
| 570 "}\n", | 780 "}\n", |
| 571 | 781 |
| 572 "extension { name:\"foo\" label:LABEL_OPTIONAL type:TYPE_INT32 number:12" | 782 "extension { name:\"foo\" label:LABEL_OPTIONAL type:TYPE_INT32 number:12" |
| 573 " extendee: \"Extendee1\" } " | 783 " extendee: \"Extendee1\" } " |
| 574 "extension { name:\"bar\" label:LABEL_REPEATED number:22" | 784 "extension { name:\"bar\" label:LABEL_REPEATED number:22" |
| 575 " type_name:\"TestMessage\" extendee: \"Extendee1\" }"); | 785 " type_name:\"TestMessage\" extendee: \"Extendee1\" }"); |
| 576 } | 786 } |
| 577 | 787 |
| 788 TEST_F(ParseMessageTest, OptionalLabelProto3) { |
| 789 ExpectParsesTo( |
| 790 "syntax = \"proto3\";\n" |
| 791 "message TestMessage {\n" |
| 792 " int32 foo = 1;\n" |
| 793 "}\n", |
| 794 |
| 795 "syntax: \"proto3\" " |
| 796 "message_type {" |
| 797 " name: \"TestMessage\"" |
| 798 " field { name:\"foo\" label:LABEL_OPTIONAL type:TYPE_INT32 number:1 } }"); |
| 799 } |
| 800 |
| 578 // =================================================================== | 801 // =================================================================== |
| 579 | 802 |
| 580 typedef ParserTest ParseEnumTest; | 803 typedef ParserTest ParseEnumTest; |
| 581 | 804 |
| 582 TEST_F(ParseEnumTest, SimpleEnum) { | 805 TEST_F(ParseEnumTest, SimpleEnum) { |
| 583 ExpectParsesTo( | 806 ExpectParsesTo( |
| 584 "enum TestEnum {\n" | 807 "enum TestEnum {\n" |
| 585 " FOO = 0;\n" | 808 " FOO = 0;\n" |
| 586 "}\n", | 809 "}\n", |
| 587 | 810 |
| (...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 674 "}\n", | 897 "}\n", |
| 675 | 898 |
| 676 "service {" | 899 "service {" |
| 677 " name: \"TestService\"" | 900 " name: \"TestService\"" |
| 678 " method { name:\"Foo\" input_type:\"In1\" output_type:\"Out1\" }" | 901 " method { name:\"Foo\" input_type:\"In1\" output_type:\"Out1\" }" |
| 679 " method { name:\"Bar\" input_type:\"In2\" output_type:\"Out2\" }" | 902 " method { name:\"Bar\" input_type:\"In2\" output_type:\"Out2\" }" |
| 680 " method { name:\"Baz\" input_type:\"In3\" output_type:\"Out3\" }" | 903 " method { name:\"Baz\" input_type:\"In3\" output_type:\"Out3\" }" |
| 681 "}"); | 904 "}"); |
| 682 } | 905 } |
| 683 | 906 |
| 907 |
| 908 |
| 684 // =================================================================== | 909 // =================================================================== |
| 685 // imports and packages | 910 // imports and packages |
| 686 | 911 |
| 687 typedef ParserTest ParseMiscTest; | 912 typedef ParserTest ParseMiscTest; |
| 688 | 913 |
| 689 TEST_F(ParseMiscTest, ParseImport) { | 914 TEST_F(ParseMiscTest, ParseImport) { |
| 690 ExpectParsesTo( | 915 ExpectParsesTo( |
| 691 "import \"foo/bar/baz.proto\";\n", | 916 "import \"foo/bar/baz.proto\";\n", |
| 692 "dependency: \"foo/bar/baz.proto\""); | 917 "dependency: \"foo/bar/baz.proto\""); |
| 693 } | 918 } |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 754 // report, so it's infeasible to test every single one of them. Instead, | 979 // 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 | 980 // 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 | 981 // 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 | 982 // each variant of the Consume() helper only counts as one unique call to |
| 758 // AddError(). | 983 // AddError(). |
| 759 | 984 |
| 760 typedef ParserTest ParseErrorTest; | 985 typedef ParserTest ParseErrorTest; |
| 761 | 986 |
| 762 TEST_F(ParseErrorTest, MissingSyntaxIdentifier) { | 987 TEST_F(ParseErrorTest, MissingSyntaxIdentifier) { |
| 763 require_syntax_identifier_ = true; | 988 require_syntax_identifier_ = true; |
| 764 ExpectHasEarlyExitErrors( | 989 ExpectHasEarlyExitErrors("message TestMessage {}", |
| 765 "message TestMessage {}", | 990 "0:0: File must begin with a syntax statement, e.g. " |
| 766 "0:0: File must begin with 'syntax = \"proto2\";'.\n"); | 991 "'syntax = \"proto2\";'.\n"); |
| 767 EXPECT_EQ("", parser_->GetSyntaxIdentifier()); | 992 EXPECT_EQ("", parser_->GetSyntaxIdentifier()); |
| 768 } | 993 } |
| 769 | 994 |
| 770 TEST_F(ParseErrorTest, UnknownSyntaxIdentifier) { | 995 TEST_F(ParseErrorTest, UnknownSyntaxIdentifier) { |
| 771 ExpectHasEarlyExitErrors( | 996 ExpectHasEarlyExitErrors( |
| 772 "syntax = \"no_such_syntax\";", | 997 "syntax = \"no_such_syntax\";", |
| 773 "0:9: Unrecognized syntax identifier \"no_such_syntax\". This parser " | 998 "0:9: Unrecognized syntax identifier \"no_such_syntax\". This parser " |
| 774 "only recognizes \"proto2\".\n"); | 999 "only recognizes \"proto2\" and \"proto3\".\n"); |
| 775 EXPECT_EQ("no_such_syntax", parser_->GetSyntaxIdentifier()); | 1000 EXPECT_EQ("no_such_syntax", parser_->GetSyntaxIdentifier()); |
| 776 } | 1001 } |
| 777 | 1002 |
| 778 TEST_F(ParseErrorTest, SimpleSyntaxError) { | 1003 TEST_F(ParseErrorTest, SimpleSyntaxError) { |
| 779 ExpectHasErrors( | 1004 ExpectHasErrors( |
| 780 "message TestMessage @#$ { blah }", | 1005 "message TestMessage @#$ { blah }", |
| 781 "0:20: Expected \"{\".\n"); | 1006 "0:20: Expected \"{\".\n"); |
| 782 EXPECT_EQ("proto2", parser_->GetSyntaxIdentifier()); | 1007 EXPECT_EQ("proto2", parser_->GetSyntaxIdentifier()); |
| 783 } | 1008 } |
| 784 | 1009 |
| (...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 863 " optional uint32 foo = 1 [.foo=1];\n" | 1088 " optional uint32 foo = 1 [.foo=1];\n" |
| 864 "}\n", | 1089 "}\n", |
| 865 "1:27: Expected identifier.\n"); | 1090 "1:27: Expected identifier.\n"); |
| 866 } | 1091 } |
| 867 | 1092 |
| 868 TEST_F(ParseErrorTest, DefaultValueTypeMismatch) { | 1093 TEST_F(ParseErrorTest, DefaultValueTypeMismatch) { |
| 869 ExpectHasErrors( | 1094 ExpectHasErrors( |
| 870 "message TestMessage {\n" | 1095 "message TestMessage {\n" |
| 871 " optional uint32 foo = 1 [default=true];\n" | 1096 " optional uint32 foo = 1 [default=true];\n" |
| 872 "}\n", | 1097 "}\n", |
| 873 "1:35: Expected integer.\n"); | 1098 "1:35: Expected integer for field default value.\n"); |
| 874 } | 1099 } |
| 875 | 1100 |
| 876 TEST_F(ParseErrorTest, DefaultValueNotBoolean) { | 1101 TEST_F(ParseErrorTest, DefaultValueNotBoolean) { |
| 877 ExpectHasErrors( | 1102 ExpectHasErrors( |
| 878 "message TestMessage {\n" | 1103 "message TestMessage {\n" |
| 879 " optional bool foo = 1 [default=blah];\n" | 1104 " optional bool foo = 1 [default=blah];\n" |
| 880 "}\n", | 1105 "}\n", |
| 881 "1:33: Expected \"true\" or \"false\".\n"); | 1106 "1:33: Expected \"true\" or \"false\".\n"); |
| 882 } | 1107 } |
| 883 | 1108 |
| 884 TEST_F(ParseErrorTest, DefaultValueNotString) { | 1109 TEST_F(ParseErrorTest, DefaultValueNotString) { |
| 885 ExpectHasErrors( | 1110 ExpectHasErrors( |
| 886 "message TestMessage {\n" | 1111 "message TestMessage {\n" |
| 887 " optional string foo = 1 [default=1];\n" | 1112 " optional string foo = 1 [default=1];\n" |
| 888 "}\n", | 1113 "}\n", |
| 889 "1:35: Expected string.\n"); | 1114 "1:35: Expected string for field default value.\n"); |
| 890 } | 1115 } |
| 891 | 1116 |
| 892 TEST_F(ParseErrorTest, DefaultValueUnsignedNegative) { | 1117 TEST_F(ParseErrorTest, DefaultValueUnsignedNegative) { |
| 893 ExpectHasErrors( | 1118 ExpectHasErrors( |
| 894 "message TestMessage {\n" | 1119 "message TestMessage {\n" |
| 895 " optional uint32 foo = 1 [default=-1];\n" | 1120 " optional uint32 foo = 1 [default=-1];\n" |
| 896 "}\n", | 1121 "}\n", |
| 897 "1:36: Unsigned field can't have negative default value.\n"); | 1122 "1:36: Unsigned field can't have negative default value.\n"); |
| 898 } | 1123 } |
| 899 | 1124 |
| 900 TEST_F(ParseErrorTest, DefaultValueTooLarge) { | 1125 TEST_F(ParseErrorTest, DefaultValueTooLarge) { |
| 901 ExpectHasErrors( | 1126 ExpectHasErrors( |
| 902 "message TestMessage {\n" | 1127 "message TestMessage {\n" |
| 903 " optional int32 foo = 1 [default= 0x80000000];\n" | 1128 " optional int32 foo = 1 [default= 0x80000000];\n" |
| 904 " optional int32 foo = 1 [default=-0x80000001];\n" | 1129 " optional int32 foo = 1 [default=-0x80000001];\n" |
| 905 " optional uint32 foo = 1 [default= 0x100000000];\n" | 1130 " optional uint32 foo = 1 [default= 0x100000000];\n" |
| 906 " optional int64 foo = 1 [default= 0x80000000000000000];\n" | 1131 " optional int64 foo = 1 [default= 0x80000000000000000];\n" |
| 907 " optional int64 foo = 1 [default=-0x80000000000000001];\n" | 1132 " optional int64 foo = 1 [default=-0x80000000000000001];\n" |
| 908 " optional uint64 foo = 1 [default= 0x100000000000000000];\n" | 1133 " optional uint64 foo = 1 [default= 0x100000000000000000];\n" |
| 909 "}\n", | 1134 "}\n", |
| 910 "1:36: Integer out of range.\n" | 1135 "1:36: Integer out of range.\n" |
| 911 "2:36: Integer out of range.\n" | 1136 "2:36: Integer out of range.\n" |
| 912 "3:36: Integer out of range.\n" | 1137 "3:36: Integer out of range.\n" |
| 913 "4:36: Integer out of range.\n" | 1138 "4:36: Integer out of range.\n" |
| 914 "5:36: Integer out of range.\n" | 1139 "5:36: Integer out of range.\n" |
| 915 "6:36: Integer out of range.\n"); | 1140 "6:36: Integer out of range.\n"); |
| 916 } | 1141 } |
| 917 | 1142 |
| 1143 TEST_F(ParseErrorTest, JsonNameNotString) { |
| 1144 ExpectHasErrors( |
| 1145 "message TestMessage {\n" |
| 1146 " optional string foo = 1 [json_name=1];\n" |
| 1147 "}\n", |
| 1148 "1:37: Expected string for JSON name.\n"); |
| 1149 } |
| 1150 |
| 1151 TEST_F(ParseErrorTest, DuplicateJsonName) { |
| 1152 ExpectHasErrors( |
| 1153 "message TestMessage {\n" |
| 1154 " optional uint32 foo = 1 [json_name=\"a\",json_name=\"b\"];\n" |
| 1155 "}\n", |
| 1156 "1:41: Already set option \"json_name\".\n"); |
| 1157 } |
| 1158 |
| 918 TEST_F(ParseErrorTest, EnumValueOutOfRange) { | 1159 TEST_F(ParseErrorTest, EnumValueOutOfRange) { |
| 919 ExpectHasErrors( | 1160 ExpectHasErrors( |
| 920 "enum TestEnum {\n" | 1161 "enum TestEnum {\n" |
| 921 " HEX_TOO_BIG = 0x80000000;\n" | 1162 " HEX_TOO_BIG = 0x80000000;\n" |
| 922 " HEX_TOO_SMALL = -0x80000001;\n" | 1163 " HEX_TOO_SMALL = -0x80000001;\n" |
| 923 " INT_TOO_BIG = 2147483648;\n" | 1164 " INT_TOO_BIG = 2147483648;\n" |
| 924 " INT_TOO_SMALL = -2147483649;\n" | 1165 " INT_TOO_SMALL = -2147483649;\n" |
| 925 "}\n", | 1166 "}\n", |
| 926 "1:19: Integer out of range.\n" | 1167 "1:19: Integer out of range.\n" |
| 927 "2:19: Integer out of range.\n" | 1168 "2:19: Integer out of range.\n" |
| 928 "3:19: Integer out of range.\n" | 1169 "3:19: Integer out of range.\n" |
| 929 "4:19: Integer out of range.\n"); | 1170 "4:19: Integer out of range.\n"); |
| 930 } | 1171 } |
| 931 | 1172 |
| 1173 TEST_F(ParseErrorTest, EnumAllowAliasFalse) { |
| 1174 ExpectHasErrors( |
| 1175 "enum Foo {\n" |
| 1176 " option allow_alias = false;\n" |
| 1177 " BAR = 1;\n" |
| 1178 " BAZ = 2;\n" |
| 1179 "}\n", |
| 1180 "5:0: \"Foo\" declares 'option allow_alias = false;' which has no effect. " |
| 1181 "Please remove the declaration.\n"); |
| 1182 } |
| 1183 |
| 1184 TEST_F(ParseErrorTest, UnnecessaryEnumAllowAlias) { |
| 1185 ExpectHasErrors( |
| 1186 "enum Foo {\n" |
| 1187 " option allow_alias = true;\n" |
| 1188 " BAR = 1;\n" |
| 1189 " BAZ = 2;\n" |
| 1190 "}\n", |
| 1191 "5:0: \"Foo\" declares support for enum aliases but no enum values share " |
| 1192 "field numbers. Please remove the unnecessary 'option allow_alias = true;' " |
| 1193 "declaration.\n"); |
| 1194 } |
| 1195 |
| 932 TEST_F(ParseErrorTest, DefaultValueMissing) { | 1196 TEST_F(ParseErrorTest, DefaultValueMissing) { |
| 933 ExpectHasErrors( | 1197 ExpectHasErrors( |
| 934 "message TestMessage {\n" | 1198 "message TestMessage {\n" |
| 935 " optional uint32 foo = 1 [default=];\n" | 1199 " optional uint32 foo = 1 [default=];\n" |
| 936 "}\n", | 1200 "}\n", |
| 937 "1:35: Expected integer.\n"); | 1201 "1:35: Expected integer for field default value.\n"); |
| 938 } | 1202 } |
| 939 | 1203 |
| 940 TEST_F(ParseErrorTest, DefaultValueForGroup) { | 1204 TEST_F(ParseErrorTest, DefaultValueForGroup) { |
| 941 ExpectHasErrors( | 1205 ExpectHasErrors( |
| 942 "message TestMessage {\n" | 1206 "message TestMessage {\n" |
| 943 " optional group Foo = 1 [default=blah] {}\n" | 1207 " optional group Foo = 1 [default=blah] {}\n" |
| 944 "}\n", | 1208 "}\n", |
| 945 "1:34: Messages can't have default values.\n"); | 1209 "1:34: Messages can't have default values.\n"); |
| 946 } | 1210 } |
| 947 | 1211 |
| 948 TEST_F(ParseErrorTest, DuplicateDefaultValue) { | 1212 TEST_F(ParseErrorTest, DuplicateDefaultValue) { |
| 949 ExpectHasErrors( | 1213 ExpectHasErrors( |
| 950 "message TestMessage {\n" | 1214 "message TestMessage {\n" |
| 951 " optional uint32 foo = 1 [default=1,default=2];\n" | 1215 " optional uint32 foo = 1 [default=1,default=2];\n" |
| 952 "}\n", | 1216 "}\n", |
| 953 "1:37: Already set option \"default\".\n"); | 1217 "1:37: Already set option \"default\".\n"); |
| 954 } | 1218 } |
| 955 | 1219 |
| 1220 TEST_F(ParseErrorTest, MissingOneofName) { |
| 1221 ExpectHasErrors( |
| 1222 "message TestMessage {\n" |
| 1223 " oneof {\n" |
| 1224 " int32 bar = 1;\n" |
| 1225 " }\n" |
| 1226 "}\n", |
| 1227 "1:8: Expected oneof name.\n"); |
| 1228 } |
| 1229 |
| 1230 TEST_F(ParseErrorTest, LabelInOneof) { |
| 1231 ExpectHasErrors( |
| 1232 "message TestMessage {\n" |
| 1233 " oneof foo {\n" |
| 1234 " optional int32 bar = 1;\n" |
| 1235 " }\n" |
| 1236 "}\n", |
| 1237 "2:4: Fields in oneofs must not have labels (required / optional " |
| 1238 "/ repeated).\n"); |
| 1239 } |
| 1240 |
| 1241 TEST_F(ParseErrorTest, MapInOneof) { |
| 1242 ExpectHasErrors( |
| 1243 "message TestMessage {\n" |
| 1244 " oneof foo {\n" |
| 1245 " map<int32, int32> foo_map = 1;\n" |
| 1246 " map message_field = 2;\n" // a normal message field is OK |
| 1247 " }\n" |
| 1248 "}\n", |
| 1249 "2:7: Map fields are not allowed in oneofs.\n"); |
| 1250 } |
| 1251 |
| 1252 TEST_F(ParseErrorTest, LabelForMap) { |
| 1253 ExpectHasErrors( |
| 1254 "message TestMessage {\n" |
| 1255 " optional map<int32, int32> int_map = 1;\n" |
| 1256 " required map<int32, int32> int_map2 = 2;\n" |
| 1257 " repeated map<int32, int32> int_map3 = 3;\n" |
| 1258 " optional map map_message = 4;\n" // a normal message field is OK |
| 1259 "}\n", |
| 1260 "1:14: Field labels (required/optional/repeated) are not allowed on map " |
| 1261 "fields.\n" |
| 1262 "2:14: Field labels (required/optional/repeated) are not allowed on map " |
| 1263 "fields.\n" |
| 1264 "3:14: Field labels (required/optional/repeated) are not allowed on map " |
| 1265 "fields.\n"); |
| 1266 } |
| 1267 |
| 1268 TEST_F(ParseErrorTest, MalformedMaps) { |
| 1269 ExpectHasErrors( |
| 1270 "message TestMessage {\n" |
| 1271 " map map_message = 1;\n" // a normal message field lacking label |
| 1272 " map<string> str_map = 2;\n" |
| 1273 " map<string,> str_map2 = 3;\n" |
| 1274 " map<,string> str_map3 = 4;\n" |
| 1275 " map<> empty_map = 5;\n" |
| 1276 " map<string,string str_map6 = 6;\n" |
| 1277 "}" |
| 1278 "extend SomeMessage {\n" |
| 1279 " map<int32, int32> int_map = 1;\n" |
| 1280 "}", |
| 1281 "1:6: Expected \"required\", \"optional\", or \"repeated\".\n" |
| 1282 "2:12: Expected \",\".\n" |
| 1283 "3:13: Expected type name.\n" |
| 1284 "4:6: Expected type name.\n" |
| 1285 "5:6: Expected type name.\n" |
| 1286 "6:20: Expected \">\".\n" |
| 1287 "8:5: Map fields are not allowed to be extensions.\n"); |
| 1288 } |
| 1289 |
| 956 TEST_F(ParseErrorTest, GroupNotCapitalized) { | 1290 TEST_F(ParseErrorTest, GroupNotCapitalized) { |
| 957 ExpectHasErrors( | 1291 ExpectHasErrors( |
| 958 "message TestMessage {\n" | 1292 "message TestMessage {\n" |
| 959 " optional group foo = 1 {}\n" | 1293 " optional group foo = 1 {}\n" |
| 960 "}\n", | 1294 "}\n", |
| 961 "1:17: Group names must start with a capital letter.\n"); | 1295 "1:17: Group names must start with a capital letter.\n"); |
| 962 } | 1296 } |
| 963 | 1297 |
| 964 TEST_F(ParseErrorTest, GroupMissingBody) { | 1298 TEST_F(ParseErrorTest, GroupMissingBody) { |
| 965 ExpectHasErrors( | 1299 ExpectHasErrors( |
| (...skipping 30 matching lines...) Expand all Loading... |
| 996 "2:2: Expected type name.\n" | 1330 "2:2: Expected type name.\n" |
| 997 "3:25: Expected \";\".\n"); | 1331 "3:25: Expected \";\".\n"); |
| 998 } | 1332 } |
| 999 | 1333 |
| 1000 TEST_F(ParseErrorTest, EofInAggregateValue) { | 1334 TEST_F(ParseErrorTest, EofInAggregateValue) { |
| 1001 ExpectHasErrors( | 1335 ExpectHasErrors( |
| 1002 "option (fileopt) = { i:100\n", | 1336 "option (fileopt) = { i:100\n", |
| 1003 "1:0: Unexpected end of stream while parsing aggregate value.\n"); | 1337 "1:0: Unexpected end of stream while parsing aggregate value.\n"); |
| 1004 } | 1338 } |
| 1005 | 1339 |
| 1340 TEST_F(ParseErrorTest, ExplicitOptionalLabelProto3) { |
| 1341 ExpectHasErrors( |
| 1342 "syntax = 'proto3';\n" |
| 1343 "message TestMessage {\n" |
| 1344 " optional int32 foo = 1;\n" |
| 1345 "}\n", |
| 1346 "2:11: Explicit 'optional' labels are disallowed in the Proto3 syntax. " |
| 1347 "To define 'optional' fields in Proto3, simply remove the 'optional' " |
| 1348 "label, as fields are 'optional' by default.\n"); |
| 1349 } |
| 1350 |
| 1351 |
| 1006 // ------------------------------------------------------------------- | 1352 // ------------------------------------------------------------------- |
| 1007 // Enum errors | 1353 // Enum errors |
| 1008 | 1354 |
| 1009 TEST_F(ParseErrorTest, EofInEnum) { | 1355 TEST_F(ParseErrorTest, EofInEnum) { |
| 1010 ExpectHasErrors( | 1356 ExpectHasErrors( |
| 1011 "enum TestEnum {", | 1357 "enum TestEnum {", |
| 1012 "0:15: Reached end of input in enum definition (missing '}').\n"); | 1358 "0:15: Reached end of input in enum definition (missing '}').\n"); |
| 1013 } | 1359 } |
| 1014 | 1360 |
| 1015 TEST_F(ParseErrorTest, EnumValueMissingNumber) { | 1361 TEST_F(ParseErrorTest, EnumValueMissingNumber) { |
| 1016 ExpectHasErrors( | 1362 ExpectHasErrors( |
| 1017 "enum TestEnum {\n" | 1363 "enum TestEnum {\n" |
| 1018 " FOO;\n" | 1364 " FOO;\n" |
| 1019 "}\n", | 1365 "}\n", |
| 1020 "1:5: Missing numeric value for enum constant.\n"); | 1366 "1:5: Missing numeric value for enum constant.\n"); |
| 1021 } | 1367 } |
| 1022 | 1368 |
| 1023 // ------------------------------------------------------------------- | 1369 // ------------------------------------------------------------------- |
| 1370 // Reserved field number errors |
| 1371 |
| 1372 TEST_F(ParseErrorTest, ReservedMaxNotAllowed) { |
| 1373 ExpectHasErrors( |
| 1374 "message Foo {\n" |
| 1375 " reserved 10 to max;\n" |
| 1376 "}\n", |
| 1377 "1:17: Expected integer.\n"); |
| 1378 } |
| 1379 |
| 1380 TEST_F(ParseErrorTest, ReservedMixNameAndNumber) { |
| 1381 ExpectHasErrors( |
| 1382 "message Foo {\n" |
| 1383 " reserved 10, \"foo\";\n" |
| 1384 "}\n", |
| 1385 "1:15: Expected field number range.\n"); |
| 1386 } |
| 1387 |
| 1388 TEST_F(ParseErrorTest, ReservedMissingQuotes) { |
| 1389 ExpectHasErrors( |
| 1390 "message Foo {\n" |
| 1391 " reserved foo;\n" |
| 1392 "}\n", |
| 1393 "1:11: Expected field name or number range.\n"); |
| 1394 } |
| 1395 |
| 1396 // ------------------------------------------------------------------- |
| 1024 // Service errors | 1397 // Service errors |
| 1025 | 1398 |
| 1026 TEST_F(ParseErrorTest, EofInService) { | 1399 TEST_F(ParseErrorTest, EofInService) { |
| 1027 ExpectHasErrors( | 1400 ExpectHasErrors( |
| 1028 "service TestService {", | 1401 "service TestService {", |
| 1029 "0:21: Reached end of input in service definition (missing '}').\n"); | 1402 "0:21: Reached end of input in service definition (missing '}').\n"); |
| 1030 } | 1403 } |
| 1031 | 1404 |
| 1032 TEST_F(ParseErrorTest, ServiceMethodPrimitiveParams) { | 1405 TEST_F(ParseErrorTest, ServiceMethodPrimitiveParams) { |
| 1033 ExpectHasErrors( | 1406 ExpectHasErrors( |
| (...skipping 203 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1237 TEST_F(ParserValidationErrorTest, MethodOutputTypeError) { | 1610 TEST_F(ParserValidationErrorTest, MethodOutputTypeError) { |
| 1238 ExpectHasValidationErrors( | 1611 ExpectHasValidationErrors( |
| 1239 "message Baz {}\n" | 1612 "message Baz {}\n" |
| 1240 "service Foo {\n" | 1613 "service Foo {\n" |
| 1241 " rpc Bar(Baz) returns(Qux);\n" | 1614 " rpc Bar(Baz) returns(Qux);\n" |
| 1242 "}\n", | 1615 "}\n", |
| 1243 "2:23: \"Qux\" is not defined.\n"); | 1616 "2:23: \"Qux\" is not defined.\n"); |
| 1244 } | 1617 } |
| 1245 | 1618 |
| 1246 | 1619 |
| 1620 TEST_F(ParserValidationErrorTest, ResovledUndefinedError) { |
| 1621 // Create another file which defines symbol ".base.bar". |
| 1622 FileDescriptorProto other_file; |
| 1623 other_file.set_name("base.proto"); |
| 1624 other_file.set_package("base"); |
| 1625 other_file.add_message_type()->set_name("bar"); |
| 1626 EXPECT_TRUE(pool_.BuildFile(other_file) != NULL); |
| 1627 |
| 1628 // Define "foo.base" and try "base.bar". |
| 1629 // "base.bar" is resolved to "foo.base.bar" which is not defined. |
| 1630 ExpectHasValidationErrors( |
| 1631 "package foo.base;\n" |
| 1632 "import \"base.proto\";\n" |
| 1633 "message qux {\n" |
| 1634 " optional base.bar baz = 1;\n" |
| 1635 " optional .base.bar quz = 2;\n" |
| 1636 "}\n", |
| 1637 "3:11: \"base.bar\" is resolved to \"foo.base.bar\"," |
| 1638 " which is not defined. The innermost scope is searched first " |
| 1639 "in name resolution. Consider using a leading '.'(i.e., \".base.bar\")" |
| 1640 " to start from the outermost scope.\n"); |
| 1641 } |
| 1642 |
| 1643 TEST_F(ParserValidationErrorTest, ResovledUndefinedOptionError) { |
| 1644 // Build descriptor message in test pool |
| 1645 FileDescriptorProto descriptor_proto; |
| 1646 DescriptorProto::descriptor()->file()->CopyTo(&descriptor_proto); |
| 1647 ASSERT_TRUE(pool_.BuildFile(descriptor_proto) != NULL); |
| 1648 |
| 1649 // base2.proto: |
| 1650 // package baz |
| 1651 // import google/protobuf/descriptor.proto |
| 1652 // message Bar { optional int32 foo = 1; } |
| 1653 // extend FileOptions { optional Bar bar = 7672757; } |
| 1654 FileDescriptorProto other_file; |
| 1655 other_file.set_name("base2.proto"); |
| 1656 other_file.set_package("baz"); |
| 1657 other_file.add_dependency(); |
| 1658 other_file.set_dependency(0, descriptor_proto.name()); |
| 1659 |
| 1660 DescriptorProto* message(other_file.add_message_type()); |
| 1661 message->set_name("Bar"); |
| 1662 FieldDescriptorProto* field(message->add_field()); |
| 1663 field->set_name("foo"); |
| 1664 field->set_number(1); |
| 1665 field->set_label(FieldDescriptorProto_Label_LABEL_OPTIONAL); |
| 1666 field->set_type(FieldDescriptorProto_Type_TYPE_INT32); |
| 1667 |
| 1668 FieldDescriptorProto* extension(other_file.add_extension()); |
| 1669 extension->set_name("bar"); |
| 1670 extension->set_number(7672757); |
| 1671 extension->set_label(FieldDescriptorProto_Label_LABEL_OPTIONAL); |
| 1672 extension->set_type(FieldDescriptorProto_Type_TYPE_MESSAGE); |
| 1673 extension->set_type_name("Bar"); |
| 1674 extension->set_extendee("google.protobuf.FileOptions"); |
| 1675 |
| 1676 EXPECT_TRUE(pool_.BuildFile(other_file) != NULL); |
| 1677 |
| 1678 // qux.proto: |
| 1679 // package qux.baz |
| 1680 // option (baz.bar).foo = 1; |
| 1681 // |
| 1682 // Although "baz.bar" is already defined, the lookup code will try |
| 1683 // "qux.baz.bar", since it's the match from the innermost scope, |
| 1684 // which will cause a symbol not defined error. |
| 1685 ExpectHasValidationErrors( |
| 1686 "package qux.baz;\n" |
| 1687 "import \"base2.proto\";\n" |
| 1688 "option (baz.bar).foo = 1;\n", |
| 1689 "2:7: Option \"(baz.bar)\" is resolved to \"(qux.baz.bar)\"," |
| 1690 " which is not defined. The innermost scope is searched first " |
| 1691 "in name resolution. Consider using a leading '.'(i.e., \"(.baz.bar)\")" |
| 1692 " to start from the outermost scope.\n"); |
| 1693 } |
| 1694 |
| 1247 // =================================================================== | 1695 // =================================================================== |
| 1248 // Test that the output from FileDescriptor::DebugString() (and all other | 1696 // Test that the output from FileDescriptor::DebugString() (and all other |
| 1249 // descriptor types) is parseable, and results in the same Descriptor | 1697 // descriptor types) is parseable, and results in the same Descriptor |
| 1250 // definitions again afoter parsing (not, however, that the order of messages | 1698 // definitions again afoter parsing (note, however, that the order of messages |
| 1251 // cannot be guaranteed to be the same) | 1699 // cannot be guaranteed to be the same) |
| 1252 | 1700 |
| 1253 typedef ParserTest ParseDecriptorDebugTest; | 1701 typedef ParserTest ParseDescriptorDebugTest; |
| 1254 | 1702 |
| 1255 class CompareDescriptorNames { | 1703 class CompareDescriptorNames { |
| 1256 public: | 1704 public: |
| 1257 bool operator()(const DescriptorProto* left, const DescriptorProto* right) { | 1705 bool operator()(const DescriptorProto* left, |
| 1706 const DescriptorProto* right) const { |
| 1258 return left->name() < right->name(); | 1707 return left->name() < right->name(); |
| 1259 } | 1708 } |
| 1260 }; | 1709 }; |
| 1261 | 1710 |
| 1262 // Sorts nested DescriptorProtos of a DescriptoProto, by name. | 1711 // Sorts nested DescriptorProtos of a DescriptoProto, by name. |
| 1263 void SortMessages(DescriptorProto *descriptor_proto) { | 1712 void SortMessages(DescriptorProto *descriptor_proto) { |
| 1264 int size = descriptor_proto->nested_type_size(); | 1713 int size = descriptor_proto->nested_type_size(); |
| 1265 // recursively sort; we can't guarantee the order of nested messages either | 1714 // recursively sort; we can't guarantee the order of nested messages either |
| 1266 for (int i = 0; i < size; ++i) { | 1715 for (int i = 0; i < size; ++i) { |
| 1267 SortMessages(descriptor_proto->mutable_nested_type(i)); | 1716 SortMessages(descriptor_proto->mutable_nested_type(i)); |
| 1268 } | 1717 } |
| 1269 DescriptorProto **data = | 1718 DescriptorProto **data = |
| 1270 descriptor_proto->mutable_nested_type()->mutable_data(); | 1719 descriptor_proto->mutable_nested_type()->mutable_data(); |
| 1271 sort(data, data + size, CompareDescriptorNames()); | 1720 std::sort(data, data + size, CompareDescriptorNames()); |
| 1272 } | 1721 } |
| 1273 | 1722 |
| 1274 // Sorts DescriptorProtos belonging to a FileDescriptorProto, by name. | 1723 // Sorts DescriptorProtos belonging to a FileDescriptorProto, by name. |
| 1275 void SortMessages(FileDescriptorProto *file_descriptor_proto) { | 1724 void SortMessages(FileDescriptorProto *file_descriptor_proto) { |
| 1276 int size = file_descriptor_proto->message_type_size(); | 1725 int size = file_descriptor_proto->message_type_size(); |
| 1277 // recursively sort; we can't guarantee the order of nested messages either | 1726 // recursively sort; we can't guarantee the order of nested messages either |
| 1278 for (int i = 0; i < size; ++i) { | 1727 for (int i = 0; i < size; ++i) { |
| 1279 SortMessages(file_descriptor_proto->mutable_message_type(i)); | 1728 SortMessages(file_descriptor_proto->mutable_message_type(i)); |
| 1280 } | 1729 } |
| 1281 DescriptorProto **data = | 1730 DescriptorProto **data = |
| 1282 file_descriptor_proto->mutable_message_type()->mutable_data(); | 1731 file_descriptor_proto->mutable_message_type()->mutable_data(); |
| 1283 sort(data, data + size, CompareDescriptorNames()); | 1732 std::sort(data, data + size, CompareDescriptorNames()); |
| 1284 } | 1733 } |
| 1285 | 1734 |
| 1286 TEST_F(ParseDecriptorDebugTest, TestAllDescriptorTypes) { | 1735 // Strips the message and enum field type names for comparison purpose only. |
| 1736 void StripFieldTypeName(DescriptorProto* proto) { |
| 1737 for (int i = 0; i < proto->field_size(); ++i) { |
| 1738 string type_name = proto->field(i).type_name(); |
| 1739 string::size_type pos = type_name.find_last_of("."); |
| 1740 if (pos != string::npos) { |
| 1741 proto->mutable_field(i)->mutable_type_name()->assign( |
| 1742 type_name.begin() + pos + 1, type_name.end()); |
| 1743 } |
| 1744 } |
| 1745 for (int i = 0; i < proto->nested_type_size(); ++i) { |
| 1746 StripFieldTypeName(proto->mutable_nested_type(i)); |
| 1747 } |
| 1748 } |
| 1749 |
| 1750 void StripFieldTypeName(FileDescriptorProto* file_proto) { |
| 1751 for (int i = 0; i < file_proto->message_type_size(); ++i) { |
| 1752 StripFieldTypeName(file_proto->mutable_message_type(i)); |
| 1753 } |
| 1754 } |
| 1755 |
| 1756 TEST_F(ParseDescriptorDebugTest, TestAllDescriptorTypes) { |
| 1287 const FileDescriptor* original_file = | 1757 const FileDescriptor* original_file = |
| 1288 protobuf_unittest::TestAllTypes::descriptor()->file(); | 1758 protobuf_unittest::TestAllTypes::descriptor()->file(); |
| 1289 FileDescriptorProto expected; | 1759 FileDescriptorProto expected; |
| 1290 original_file->CopyTo(&expected); | 1760 original_file->CopyTo(&expected); |
| 1291 | 1761 |
| 1292 // Get the DebugString of the unittest.proto FileDecriptor, which includes | 1762 // Get the DebugString of the unittest.proto FileDecriptor, which includes |
| 1293 // all other descriptor types | 1763 // all other descriptor types |
| 1294 string debug_string = original_file->DebugString(); | 1764 string debug_string = original_file->DebugString(); |
| 1295 | 1765 |
| 1296 // Parse the debug string | 1766 // Parse the debug string |
| 1297 SetupParser(debug_string.c_str()); | 1767 SetupParser(debug_string.c_str()); |
| 1298 FileDescriptorProto parsed; | 1768 FileDescriptorProto parsed; |
| 1299 parser_->Parse(input_.get(), &parsed); | 1769 parser_->Parse(input_.get(), &parsed); |
| 1300 EXPECT_EQ(io::Tokenizer::TYPE_END, input_->current().type); | 1770 EXPECT_EQ(io::Tokenizer::TYPE_END, input_->current().type); |
| 1301 ASSERT_EQ("", error_collector_.text_); | 1771 ASSERT_EQ("", error_collector_.text_) |
| 1772 << "Failed to parse:\n" << debug_string; |
| 1302 | 1773 |
| 1303 // We now have a FileDescriptorProto, but to compare with the expected we | 1774 // 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 | 1775 // 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. | 1776 // also need to give it the same name as the original. |
| 1306 parsed.set_name("google/protobuf/unittest.proto"); | 1777 parsed.set_name("google/protobuf/unittest.proto"); |
| 1307 // We need the imported dependency before we can build our parsed proto | 1778 // We need the imported dependency before we can build our parsed proto |
| 1308 const FileDescriptor* public_import = | 1779 const FileDescriptor* public_import = |
| 1309 protobuf_unittest_import::PublicImportMessage::descriptor()->file(); | 1780 protobuf_unittest_import::PublicImportMessage::descriptor()->file(); |
| 1310 FileDescriptorProto public_import_proto; | 1781 FileDescriptorProto public_import_proto; |
| 1311 public_import->CopyTo(&public_import_proto); | 1782 public_import->CopyTo(&public_import_proto); |
| 1312 ASSERT_TRUE(pool_.BuildFile(public_import_proto) != NULL); | 1783 ASSERT_TRUE(pool_.BuildFile(public_import_proto) != NULL); |
| 1313 const FileDescriptor* import = | 1784 const FileDescriptor* import = |
| 1314 protobuf_unittest_import::ImportMessage::descriptor()->file(); | 1785 protobuf_unittest_import::ImportMessage::descriptor()->file(); |
| 1315 FileDescriptorProto import_proto; | 1786 FileDescriptorProto import_proto; |
| 1316 import->CopyTo(&import_proto); | 1787 import->CopyTo(&import_proto); |
| 1317 ASSERT_TRUE(pool_.BuildFile(import_proto) != NULL); | 1788 ASSERT_TRUE(pool_.BuildFile(import_proto) != NULL); |
| 1318 const FileDescriptor* actual = pool_.BuildFile(parsed); | 1789 const FileDescriptor* actual = pool_.BuildFile(parsed); |
| 1319 parsed.Clear(); | 1790 parsed.Clear(); |
| 1791 ASSERT_TRUE(actual != NULL) |
| 1792 << "Failed to validate:\n" << debug_string; |
| 1320 actual->CopyTo(&parsed); | 1793 actual->CopyTo(&parsed); |
| 1321 ASSERT_TRUE(actual != NULL); | 1794 ASSERT_TRUE(actual != NULL); |
| 1322 | 1795 |
| 1323 // The messages might be in different orders, making them hard to compare. | 1796 // The messages might be in different orders, making them hard to compare. |
| 1324 // So, sort the messages in the descriptor protos (including nested messages, | 1797 // So, sort the messages in the descriptor protos (including nested messages, |
| 1325 // recursively). | 1798 // recursively). |
| 1326 SortMessages(&expected); | 1799 SortMessages(&expected); |
| 1327 SortMessages(&parsed); | 1800 SortMessages(&parsed); |
| 1328 | 1801 |
| 1329 // I really wanted to use StringDiff here for the debug output on fail, | 1802 // 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, | 1803 // but the strings are too long for it, and if I increase its max size, |
| 1331 // we get a memory allocation failure :( | 1804 // we get a memory allocation failure :( |
| 1332 EXPECT_EQ(expected.DebugString(), parsed.DebugString()); | 1805 EXPECT_EQ(expected.DebugString(), parsed.DebugString()); |
| 1333 } | 1806 } |
| 1334 | 1807 |
| 1335 TEST_F(ParseDecriptorDebugTest, TestCustomOptions) { | 1808 TEST_F(ParseDescriptorDebugTest, TestCustomOptions) { |
| 1336 const FileDescriptor* original_file = | 1809 const FileDescriptor* original_file = |
| 1337 protobuf_unittest::AggregateMessage::descriptor()->file(); | 1810 protobuf_unittest::AggregateMessage::descriptor()->file(); |
| 1338 FileDescriptorProto expected; | 1811 FileDescriptorProto expected; |
| 1339 original_file->CopyTo(&expected); | 1812 original_file->CopyTo(&expected); |
| 1340 | 1813 |
| 1341 string debug_string = original_file->DebugString(); | 1814 string debug_string = original_file->DebugString(); |
| 1342 | 1815 |
| 1343 // Parse the debug string | 1816 // Parse the debug string |
| 1344 SetupParser(debug_string.c_str()); | 1817 SetupParser(debug_string.c_str()); |
| 1345 FileDescriptorProto parsed; | 1818 FileDescriptorProto parsed; |
| (...skipping 18 matching lines...) Expand all Loading... |
| 1364 | 1837 |
| 1365 // The messages might be in different orders, making them hard to compare. | 1838 // The messages might be in different orders, making them hard to compare. |
| 1366 // So, sort the messages in the descriptor protos (including nested messages, | 1839 // So, sort the messages in the descriptor protos (including nested messages, |
| 1367 // recursively). | 1840 // recursively). |
| 1368 SortMessages(&expected); | 1841 SortMessages(&expected); |
| 1369 SortMessages(&parsed); | 1842 SortMessages(&parsed); |
| 1370 | 1843 |
| 1371 EXPECT_EQ(expected.DebugString(), parsed.DebugString()); | 1844 EXPECT_EQ(expected.DebugString(), parsed.DebugString()); |
| 1372 } | 1845 } |
| 1373 | 1846 |
| 1847 // Ensure that DebugStringWithOptions(), with |include_comments| set to true, |
| 1848 // includes comments from the original parser input in all of the appropriate |
| 1849 // places. |
| 1850 TEST_F(ParseDescriptorDebugTest, TestCommentsInDebugString) { |
| 1851 SetupParser( |
| 1852 "// Detached comment before syntax.\n" |
| 1853 "\n" |
| 1854 "// Syntax comment.\n" |
| 1855 "syntax = \"proto2\";\n" |
| 1856 "\n" |
| 1857 "// Detached comment before package.\n" |
| 1858 "\n" |
| 1859 "// Package comment.\n" |
| 1860 "package comment_test;\n" |
| 1861 "\n" |
| 1862 "// Detached comment before TestMessage1.\n" |
| 1863 "\n" |
| 1864 "// Message comment.\n" |
| 1865 "//\n" |
| 1866 "// More detail in message comment.\n" |
| 1867 "message TestMessage1 {\n" |
| 1868 "\n" |
| 1869 " // Detached comment before foo.\n" |
| 1870 "\n" |
| 1871 " // Field comment.\n" |
| 1872 " optional int32 foo = 1;\n" |
| 1873 "\n" |
| 1874 " // Detached comment before NestedMessage.\n" |
| 1875 "\n" |
| 1876 " // Nested-message comment.\n" |
| 1877 " message NestedMessage {\n" |
| 1878 " optional int32 bar = 1;\n" |
| 1879 " }\n" |
| 1880 "}\n" |
| 1881 "\n" |
| 1882 "// Detached comment before MyEnumType.\n" |
| 1883 "\n" |
| 1884 "// Enum comment.\n" |
| 1885 "enum MyEnumType {\n" |
| 1886 "\n" |
| 1887 " // Detached comment before ASDF.\n" |
| 1888 "\n" |
| 1889 " // Enum-value comment.\n" |
| 1890 " ASDF = 1;\n" |
| 1891 "}\n" |
| 1892 "\n" |
| 1893 "// Detached comment before MyService.\n" |
| 1894 "\n" |
| 1895 "// Service comment.\n" |
| 1896 "service MyService {\n" |
| 1897 "\n" |
| 1898 " // Detached comment before MyRPCCall.\n" |
| 1899 "\n" |
| 1900 " // RPC comment.\n" |
| 1901 " rpc MyRPCCall(TestMessage1) returns (TestMessage1) { }\n" |
| 1902 "}\n"); |
| 1903 |
| 1904 FileDescriptorProto parsed_desc; |
| 1905 parsed_desc.set_name("foo.proto"); |
| 1906 SourceLocationTable source_locations; |
| 1907 parser_->RecordSourceLocationsTo(&source_locations); |
| 1908 parser_->Parse(input_.get(), &parsed_desc); |
| 1909 EXPECT_EQ(io::Tokenizer::TYPE_END, input_->current().type); |
| 1910 ASSERT_EQ("", error_collector_.text_); |
| 1911 |
| 1912 // We need to import the FileDescriptorProto to get a FileDescriptor. |
| 1913 MockValidationErrorCollector collector(source_locations, &error_collector_); |
| 1914 const FileDescriptor* descriptor = |
| 1915 pool_.BuildFileCollectingErrors(parsed_desc, &collector); |
| 1916 ASSERT_TRUE(descriptor != NULL); |
| 1917 |
| 1918 // Ensure that each of the comments appears somewhere in the DebugString(). |
| 1919 // We don't test the exact comment placement or formatting, because we do not |
| 1920 // want to be too fragile here. |
| 1921 const char* expected_comments[] = { |
| 1922 "Detached comment before syntax.", |
| 1923 "Syntax comment.", |
| 1924 "Detached comment before package.", |
| 1925 "Package comment.", |
| 1926 "Detached comment before TestMessage1.", |
| 1927 "Message comment.", |
| 1928 "More detail in message comment.", |
| 1929 "Detached comment before foo.", |
| 1930 "Field comment", |
| 1931 "Detached comment before NestedMessage.", |
| 1932 "Nested-message comment", |
| 1933 "Detached comment before MyEnumType.", |
| 1934 "Enum comment", |
| 1935 "Detached comment before ASDF.", |
| 1936 "Enum-value comment", |
| 1937 "Detached comment before MyService.", |
| 1938 "Service comment", |
| 1939 "Detached comment before MyRPCCall.", |
| 1940 "RPC comment", |
| 1941 }; |
| 1942 |
| 1943 DebugStringOptions debug_string_options; |
| 1944 debug_string_options.include_comments = true; |
| 1945 |
| 1946 { |
| 1947 const string debug_string = |
| 1948 descriptor->DebugStringWithOptions(debug_string_options); |
| 1949 |
| 1950 for (int i = 0; i < GOOGLE_ARRAYSIZE(expected_comments); ++i) { |
| 1951 string::size_type found_pos = debug_string.find(expected_comments[i]); |
| 1952 EXPECT_TRUE(found_pos != string::npos) |
| 1953 << "\"" << expected_comments[i] << "\" not found."; |
| 1954 } |
| 1955 |
| 1956 // Result of DebugStringWithOptions should be parseable. |
| 1957 SetupParser(debug_string.c_str()); |
| 1958 FileDescriptorProto parsed; |
| 1959 parser_->Parse(input_.get(), &parsed); |
| 1960 EXPECT_EQ(io::Tokenizer::TYPE_END, input_->current().type); |
| 1961 ASSERT_EQ("", error_collector_.text_) |
| 1962 << "Failed to parse:\n" << debug_string; |
| 1963 } |
| 1964 |
| 1965 } |
| 1966 |
| 1967 TEST_F(ParseDescriptorDebugTest, TestMaps) { |
| 1968 SetupParser( |
| 1969 "syntax = \"proto3\"; " |
| 1970 "message Foo { " |
| 1971 " message Bar { } " |
| 1972 " map<int32, Bar> enum_message_map = 1; " |
| 1973 " map<string, float> primitive_map = 2; " |
| 1974 "} "); |
| 1975 FileDescriptorProto original; |
| 1976 EXPECT_TRUE(parser_->Parse(input_.get(), &original)); |
| 1977 original.set_name("foo.proto"); |
| 1978 const FileDescriptor* file = pool_.BuildFile(original); |
| 1979 ASSERT_TRUE(file != NULL); |
| 1980 |
| 1981 // Make sure the debug string uses map syntax and does not have the auto |
| 1982 // generated entry. |
| 1983 string debug_string = file->DebugString(); |
| 1984 EXPECT_TRUE(debug_string.find("map<") != string::npos); |
| 1985 EXPECT_TRUE(debug_string.find("option map_entry") == string::npos); |
| 1986 EXPECT_TRUE(debug_string.find("MapEntry") == string::npos); |
| 1987 |
| 1988 // Make sure the descriptor debug string is parsable. |
| 1989 FileDescriptorProto parsed; |
| 1990 SetupParser(debug_string.c_str()); |
| 1991 parsed.set_name("foo.proto"); |
| 1992 ASSERT_TRUE(parser_->Parse(input_.get(), &parsed)); |
| 1993 |
| 1994 original.clear_source_code_info(); |
| 1995 parsed.clear_source_code_info(); |
| 1996 StripFieldTypeName(&original); |
| 1997 StripFieldTypeName(&parsed); |
| 1998 EXPECT_EQ(original.DebugString(), parsed.DebugString()); |
| 1999 } |
| 2000 |
| 1374 // =================================================================== | 2001 // =================================================================== |
| 1375 // SourceCodeInfo tests. | 2002 // SourceCodeInfo tests. |
| 1376 | 2003 |
| 1377 // Follows a path -- as defined by SourceCodeInfo.Location.path -- from a | 2004 // Follows a path -- as defined by SourceCodeInfo.Location.path -- from a |
| 1378 // message to a particular sub-field. | 2005 // message to a particular sub-field. |
| 1379 // * If the target is itself a message, sets *output_message to point at it, | 2006 // * If the target is itself a message, sets *output_message to point at it, |
| 1380 // *output_field to NULL, and *output_index to -1. | 2007 // *output_field to NULL, and *output_index to -1. |
| 1381 // * Otherwise, if the target is an element of a repeated field, sets | 2008 // * Otherwise, if the target is an element of a repeated field, sets |
| 1382 // *output_message to the containing message, *output_field to the descriptor | 2009 // *output_message to the containing message, *output_field to the descriptor |
| 1383 // of the field, and *output_index to the index of the element. | 2010 // of the field, and *output_index to the index of the element. |
| (...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1496 for (int i = 0; i < source_info.location_size(); i++) { | 2123 for (int i = 0; i < source_info.location_size(); i++) { |
| 1497 const SourceCodeInfo::Location& location = source_info.location(i); | 2124 const SourceCodeInfo::Location& location = source_info.location(i); |
| 1498 const Message* descriptor_proto = NULL; | 2125 const Message* descriptor_proto = NULL; |
| 1499 const FieldDescriptor* field = NULL; | 2126 const FieldDescriptor* field = NULL; |
| 1500 int index = 0; | 2127 int index = 0; |
| 1501 if (!FollowPath(file_, location.path().begin(), location.path().end(), | 2128 if (!FollowPath(file_, location.path().begin(), location.path().end(), |
| 1502 &descriptor_proto, &field, &index)) { | 2129 &descriptor_proto, &field, &index)) { |
| 1503 return false; | 2130 return false; |
| 1504 } | 2131 } |
| 1505 | 2132 |
| 1506 spans_.insert(make_pair(SpanKey(*descriptor_proto, field, index), | 2133 spans_.insert( |
| 1507 &location)); | 2134 std::make_pair(SpanKey(*descriptor_proto, field, index), &location)); |
| 1508 } | 2135 } |
| 1509 | 2136 |
| 1510 return true; | 2137 return true; |
| 1511 } | 2138 } |
| 1512 | 2139 |
| 1513 virtual void TearDown() { | 2140 virtual void TearDown() { |
| 1514 EXPECT_TRUE(spans_.empty()) | 2141 EXPECT_TRUE(spans_.empty()) |
| 1515 << "Forgot to call HasSpan() for:\n" | 2142 << "Forgot to call HasSpan() for:\n" |
| 1516 << spans_.begin()->second->DebugString(); | 2143 << spans_.begin()->second->DebugString(); |
| 1517 } | 2144 } |
| 1518 | 2145 |
| 1519 // ----------------------------------------------------------------- | 2146 // ----------------------------------------------------------------- |
| 1520 // HasSpan() checks that the span of source code delimited by the given | 2147 // HasSpan() checks that the span of source code delimited by the given |
| 1521 // tags (comments) correspond via the SourceCodeInfo table to the given | 2148 // tags (comments) correspond via the SourceCodeInfo table to the given |
| 1522 // part of the FileDescriptorProto. (If unclear, look at the actual tests; | 2149 // part of the FileDescriptorProto. (If unclear, look at the actual tests; |
| 1523 // it should quickly become obvious.) | 2150 // it should quickly become obvious.) |
| 1524 | 2151 |
| 1525 bool HasSpan(char start_marker, char end_marker, | 2152 bool HasSpan(char start_marker, char end_marker, |
| 1526 const Message& descriptor_proto) { | 2153 const Message& descriptor_proto) { |
| 1527 return HasSpanWithComment( | 2154 return HasSpanWithComment( |
| 1528 start_marker, end_marker, descriptor_proto, NULL, -1, NULL, NULL); | 2155 start_marker, end_marker, descriptor_proto, NULL, -1, NULL, NULL, NULL); |
| 1529 } | 2156 } |
| 1530 | 2157 |
| 1531 bool HasSpanWithComment(char start_marker, char end_marker, | 2158 bool HasSpanWithComment(char start_marker, char end_marker, |
| 1532 const Message& descriptor_proto, | 2159 const Message& descriptor_proto, |
| 1533 const char* expected_leading_comments, | 2160 const char* expected_leading_comments, |
| 1534 const char* expected_trailing_comments) { | 2161 const char* expected_trailing_comments, |
| 2162 const char* expected_leading_detached_comments) { |
| 1535 return HasSpanWithComment( | 2163 return HasSpanWithComment( |
| 1536 start_marker, end_marker, descriptor_proto, NULL, -1, | 2164 start_marker, end_marker, descriptor_proto, NULL, -1, |
| 1537 expected_leading_comments, expected_trailing_comments); | 2165 expected_leading_comments, expected_trailing_comments, |
| 2166 expected_leading_detached_comments); |
| 1538 } | 2167 } |
| 1539 | 2168 |
| 1540 bool HasSpan(char start_marker, char end_marker, | 2169 bool HasSpan(char start_marker, char end_marker, |
| 1541 const Message& descriptor_proto, const string& field_name) { | 2170 const Message& descriptor_proto, const string& field_name) { |
| 1542 return HasSpan(start_marker, end_marker, descriptor_proto, field_name, -1); | 2171 return HasSpan(start_marker, end_marker, descriptor_proto, field_name, -1); |
| 1543 } | 2172 } |
| 1544 | 2173 |
| 1545 bool HasSpan(char start_marker, char end_marker, | 2174 bool HasSpan(char start_marker, char end_marker, |
| 1546 const Message& descriptor_proto, const string& field_name, | 2175 const Message& descriptor_proto, const string& field_name, |
| 1547 int index) { | 2176 int index) { |
| 1548 return HasSpan(start_marker, end_marker, descriptor_proto, | 2177 return HasSpan(start_marker, end_marker, descriptor_proto, |
| 1549 field_name, index, NULL, NULL); | 2178 field_name, index, NULL, NULL, NULL); |
| 1550 } | 2179 } |
| 1551 | 2180 |
| 1552 bool HasSpan(char start_marker, char end_marker, | 2181 bool HasSpan(char start_marker, char end_marker, |
| 1553 const Message& descriptor_proto, | 2182 const Message& descriptor_proto, |
| 1554 const string& field_name, int index, | 2183 const string& field_name, int index, |
| 1555 const char* expected_leading_comments, | 2184 const char* expected_leading_comments, |
| 1556 const char* expected_trailing_comments) { | 2185 const char* expected_trailing_comments, |
| 2186 const char* expected_leading_detached_comments) { |
| 1557 const FieldDescriptor* field = | 2187 const FieldDescriptor* field = |
| 1558 descriptor_proto.GetDescriptor()->FindFieldByName(field_name); | 2188 descriptor_proto.GetDescriptor()->FindFieldByName(field_name); |
| 1559 if (field == NULL) { | 2189 if (field == NULL) { |
| 1560 ADD_FAILURE() << descriptor_proto.GetDescriptor()->name() | 2190 ADD_FAILURE() << descriptor_proto.GetDescriptor()->name() |
| 1561 << " has no such field: " << field_name; | 2191 << " has no such field: " << field_name; |
| 1562 return false; | 2192 return false; |
| 1563 } | 2193 } |
| 1564 | 2194 |
| 1565 return HasSpanWithComment( | 2195 return HasSpanWithComment( |
| 1566 start_marker, end_marker, descriptor_proto, field, index, | 2196 start_marker, end_marker, descriptor_proto, field, index, |
| 1567 expected_leading_comments, expected_trailing_comments); | 2197 expected_leading_comments, expected_trailing_comments, |
| 2198 expected_leading_detached_comments); |
| 1568 } | 2199 } |
| 1569 | 2200 |
| 1570 bool HasSpan(const Message& descriptor_proto) { | 2201 bool HasSpan(const Message& descriptor_proto) { |
| 1571 return HasSpanWithComment( | 2202 return HasSpanWithComment( |
| 1572 '\0', '\0', descriptor_proto, NULL, -1, NULL, NULL); | 2203 '\0', '\0', descriptor_proto, NULL, -1, NULL, NULL, NULL); |
| 1573 } | 2204 } |
| 1574 | 2205 |
| 1575 bool HasSpan(const Message& descriptor_proto, const string& field_name) { | 2206 bool HasSpan(const Message& descriptor_proto, const string& field_name) { |
| 1576 return HasSpan('\0', '\0', descriptor_proto, field_name, -1); | 2207 return HasSpan('\0', '\0', descriptor_proto, field_name, -1); |
| 1577 } | 2208 } |
| 1578 | 2209 |
| 1579 bool HasSpan(const Message& descriptor_proto, const string& field_name, | 2210 bool HasSpan(const Message& descriptor_proto, const string& field_name, |
| 1580 int index) { | 2211 int index) { |
| 1581 return HasSpan('\0', '\0', descriptor_proto, field_name, index); | 2212 return HasSpan('\0', '\0', descriptor_proto, field_name, index); |
| 1582 } | 2213 } |
| 1583 | 2214 |
| 1584 bool HasSpanWithComment(char start_marker, char end_marker, | 2215 bool HasSpanWithComment( |
| 1585 const Message& descriptor_proto, | 2216 char start_marker, char end_marker, const Message& descriptor_proto, |
| 1586 const FieldDescriptor* field, int index, | 2217 const FieldDescriptor* field, int index, |
| 1587 const char* expected_leading_comments, | 2218 const char* expected_leading_comments, |
| 1588 const char* expected_trailing_comments) { | 2219 const char* expected_trailing_comments, |
| 2220 const char* expected_leading_detached_comments) { |
| 1589 pair<SpanMap::iterator, SpanMap::iterator> range = | 2221 pair<SpanMap::iterator, SpanMap::iterator> range = |
| 1590 spans_.equal_range(SpanKey(descriptor_proto, field, index)); | 2222 spans_.equal_range(SpanKey(descriptor_proto, field, index)); |
| 1591 | 2223 |
| 1592 if (start_marker == '\0') { | 2224 if (start_marker == '\0') { |
| 1593 if (range.first == range.second) { | 2225 if (range.first == range.second) { |
| 1594 return false; | 2226 return false; |
| 1595 } else { | 2227 } else { |
| 1596 spans_.erase(range.first); | 2228 spans_.erase(range.first); |
| 1597 return true; | 2229 return true; |
| 1598 } | 2230 } |
| (...skipping 18 matching lines...) Expand all Loading... |
| 1617 EXPECT_EQ(expected_leading_comments, | 2249 EXPECT_EQ(expected_leading_comments, |
| 1618 iter->second->leading_comments()); | 2250 iter->second->leading_comments()); |
| 1619 } | 2251 } |
| 1620 if (expected_trailing_comments == NULL) { | 2252 if (expected_trailing_comments == NULL) { |
| 1621 EXPECT_FALSE(iter->second->has_trailing_comments()); | 2253 EXPECT_FALSE(iter->second->has_trailing_comments()); |
| 1622 } else { | 2254 } else { |
| 1623 EXPECT_TRUE(iter->second->has_trailing_comments()); | 2255 EXPECT_TRUE(iter->second->has_trailing_comments()); |
| 1624 EXPECT_EQ(expected_trailing_comments, | 2256 EXPECT_EQ(expected_trailing_comments, |
| 1625 iter->second->trailing_comments()); | 2257 iter->second->trailing_comments()); |
| 1626 } | 2258 } |
| 2259 if (expected_leading_detached_comments == NULL) { |
| 2260 EXPECT_EQ(0, iter->second->leading_detached_comments_size()); |
| 2261 } else { |
| 2262 EXPECT_EQ( |
| 2263 expected_leading_detached_comments, |
| 2264 Join(iter->second->leading_detached_comments(), "\n")); |
| 2265 } |
| 1627 | 2266 |
| 1628 spans_.erase(iter); | 2267 spans_.erase(iter); |
| 1629 return true; | 2268 return true; |
| 1630 } | 2269 } |
| 1631 } | 2270 } |
| 1632 | 2271 |
| 1633 return false; | 2272 return false; |
| 1634 } | 2273 } |
| 1635 } | 2274 } |
| 1636 | 2275 |
| (...skipping 30 matching lines...) Expand all Loading... |
| 1667 int line = 0; | 2306 int line = 0; |
| 1668 int column = 0; | 2307 int column = 0; |
| 1669 while (*text != '\0') { | 2308 while (*text != '\0') { |
| 1670 if (*text == '$') { | 2309 if (*text == '$') { |
| 1671 ++text; | 2310 ++text; |
| 1672 GOOGLE_CHECK_NE('\0', *text); | 2311 GOOGLE_CHECK_NE('\0', *text); |
| 1673 if (*text == '$') { | 2312 if (*text == '$') { |
| 1674 text_without_markers_ += '$'; | 2313 text_without_markers_ += '$'; |
| 1675 ++column; | 2314 ++column; |
| 1676 } else { | 2315 } else { |
| 1677 markers_[*text] = make_pair(line, column); | 2316 markers_[*text] = std::make_pair(line, column); |
| 1678 ++text; | 2317 ++text; |
| 1679 GOOGLE_CHECK_EQ('$', *text); | 2318 GOOGLE_CHECK_EQ('$', *text); |
| 1680 } | 2319 } |
| 1681 } else if (*text == '\n') { | 2320 } else if (*text == '\n') { |
| 1682 ++line; | 2321 ++line; |
| 1683 column = 0; | 2322 column = 0; |
| 1684 text_without_markers_ += *text; | 2323 text_without_markers_ += *text; |
| 1685 } else { | 2324 } else { |
| 1686 text_without_markers_ += *text; | 2325 text_without_markers_ += *text; |
| 1687 ++column; | 2326 ++column; |
| 1688 } | 2327 } |
| 1689 ++text; | 2328 ++text; |
| 1690 } | 2329 } |
| 1691 } | 2330 } |
| 1692 }; | 2331 }; |
| 1693 | 2332 |
| 1694 TEST_F(SourceInfoTest, BasicFileDecls) { | 2333 TEST_F(SourceInfoTest, BasicFileDecls) { |
| 1695 EXPECT_TRUE(Parse( | 2334 EXPECT_TRUE(Parse( |
| 1696 "$a$syntax = \"proto2\";\n" | 2335 "$a$syntax = \"proto2\";$i$\n" |
| 1697 "package $b$foo.bar$c$;\n" | 2336 "package $b$foo.bar$c$;\n" |
| 1698 "import $d$\"baz.proto\"$e$;\n" | 2337 "import $d$\"baz.proto\"$e$;\n" |
| 1699 "import $f$\"qux.proto\"$g$;$h$\n" | 2338 "import $f$\"qux.proto\"$g$;$h$\n" |
| 1700 "\n" | 2339 "\n" |
| 1701 "// comment ignored\n")); | 2340 "// comment ignored\n")); |
| 1702 | 2341 |
| 1703 EXPECT_TRUE(HasSpan('a', 'h', file_)); | 2342 EXPECT_TRUE(HasSpan('a', 'h', file_)); |
| 1704 EXPECT_TRUE(HasSpan('b', 'c', file_, "package")); | 2343 EXPECT_TRUE(HasSpan('b', 'c', file_, "package")); |
| 1705 EXPECT_TRUE(HasSpan('d', 'e', file_, "dependency", 0)); | 2344 EXPECT_TRUE(HasSpan('d', 'e', file_, "dependency", 0)); |
| 1706 EXPECT_TRUE(HasSpan('f', 'g', file_, "dependency", 1)); | 2345 EXPECT_TRUE(HasSpan('f', 'g', file_, "dependency", 1)); |
| 2346 EXPECT_TRUE(HasSpan('a', 'i', file_, "syntax")); |
| 1707 } | 2347 } |
| 1708 | 2348 |
| 1709 TEST_F(SourceInfoTest, Messages) { | 2349 TEST_F(SourceInfoTest, Messages) { |
| 1710 EXPECT_TRUE(Parse( | 2350 EXPECT_TRUE(Parse( |
| 1711 "$a$message $b$Foo$c$ {}$d$\n" | 2351 "$a$message $b$Foo$c$ {}$d$\n" |
| 1712 "$e$message $f$Bar$g$ {}$h$\n")); | 2352 "$e$message $f$Bar$g$ {}$h$\n")); |
| 1713 | 2353 |
| 1714 EXPECT_TRUE(HasSpan('a', 'd', file_.message_type(0))); | 2354 EXPECT_TRUE(HasSpan('a', 'd', file_.message_type(0))); |
| 1715 EXPECT_TRUE(HasSpan('b', 'c', file_.message_type(0), "name")); | 2355 EXPECT_TRUE(HasSpan('b', 'c', file_.message_type(0), "name")); |
| 1716 EXPECT_TRUE(HasSpan('e', 'h', file_.message_type(1))); | 2356 EXPECT_TRUE(HasSpan('e', 'h', file_.message_type(1))); |
| (...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1864 EXPECT_TRUE(HasSpan('j', 'm', range3)); | 2504 EXPECT_TRUE(HasSpan('j', 'm', range3)); |
| 1865 EXPECT_TRUE(HasSpan('j', 'k', range3, "start")); | 2505 EXPECT_TRUE(HasSpan('j', 'k', range3, "start")); |
| 1866 EXPECT_TRUE(HasSpan('l', 'm', range3, "end")); | 2506 EXPECT_TRUE(HasSpan('l', 'm', range3, "end")); |
| 1867 | 2507 |
| 1868 // Ignore these. | 2508 // Ignore these. |
| 1869 EXPECT_TRUE(HasSpan(file_)); | 2509 EXPECT_TRUE(HasSpan(file_)); |
| 1870 EXPECT_TRUE(HasSpan(file_.message_type(0))); | 2510 EXPECT_TRUE(HasSpan(file_.message_type(0))); |
| 1871 EXPECT_TRUE(HasSpan(file_.message_type(0), "name")); | 2511 EXPECT_TRUE(HasSpan(file_.message_type(0), "name")); |
| 1872 } | 2512 } |
| 1873 | 2513 |
| 2514 TEST_F(SourceInfoTest, Oneofs) { |
| 2515 EXPECT_TRUE(Parse( |
| 2516 "message Foo {\n" |
| 2517 " $a$oneof $c$foo$d$ {\n" |
| 2518 " $e$int32$f$ $g$a$h$ = $i$1$j$;$k$\n" |
| 2519 " }$r$\n" |
| 2520 "}\n")); |
| 2521 |
| 2522 const OneofDescriptorProto& oneof_decl = file_.message_type(0).oneof_decl(0); |
| 2523 const FieldDescriptorProto& field = file_.message_type(0).field(0); |
| 2524 |
| 2525 EXPECT_TRUE(HasSpan('a', 'r', oneof_decl)); |
| 2526 EXPECT_TRUE(HasSpan('c', 'd', oneof_decl, "name")); |
| 2527 |
| 2528 EXPECT_TRUE(HasSpan('e', 'k', field)); |
| 2529 EXPECT_TRUE(HasSpan('e', 'f', field, "type")); |
| 2530 EXPECT_TRUE(HasSpan('g', 'h', field, "name")); |
| 2531 EXPECT_TRUE(HasSpan('i', 'j', field, "number")); |
| 2532 |
| 2533 // Ignore these. |
| 2534 EXPECT_TRUE(HasSpan(file_)); |
| 2535 EXPECT_TRUE(HasSpan(file_.message_type(0))); |
| 2536 EXPECT_TRUE(HasSpan(file_.message_type(0), "name")); |
| 2537 } |
| 2538 |
| 1874 TEST_F(SourceInfoTest, NestedMessages) { | 2539 TEST_F(SourceInfoTest, NestedMessages) { |
| 1875 EXPECT_TRUE(Parse( | 2540 EXPECT_TRUE(Parse( |
| 1876 "message Foo {\n" | 2541 "message Foo {\n" |
| 1877 " $a$message $b$Bar$c$ {\n" | 2542 " $a$message $b$Bar$c$ {\n" |
| 1878 " $d$message $e$Baz$f$ {}$g$\n" | 2543 " $d$message $e$Baz$f$ {}$g$\n" |
| 1879 " }$h$\n" | 2544 " }$h$\n" |
| 1880 " $i$message $j$Qux$k$ {}$l$\n" | 2545 " $i$message $j$Qux$k$ {}$l$\n" |
| 1881 "}\n")); | 2546 "}\n")); |
| 1882 | 2547 |
| 1883 const DescriptorProto& bar = file_.message_type(0).nested_type(0); | 2548 const DescriptorProto& bar = file_.message_type(0).nested_type(0); |
| (...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2022 EXPECT_TRUE(HasSpan('j', 'k', baz, "name")); | 2687 EXPECT_TRUE(HasSpan('j', 'k', baz, "name")); |
| 2023 EXPECT_TRUE(HasSpan('l', 'm', baz, "input_type")); | 2688 EXPECT_TRUE(HasSpan('l', 'm', baz, "input_type")); |
| 2024 EXPECT_TRUE(HasSpan('n', 'o', baz, "output_type")); | 2689 EXPECT_TRUE(HasSpan('n', 'o', baz, "output_type")); |
| 2025 | 2690 |
| 2026 // Ignore these. | 2691 // Ignore these. |
| 2027 EXPECT_TRUE(HasSpan(file_)); | 2692 EXPECT_TRUE(HasSpan(file_)); |
| 2028 EXPECT_TRUE(HasSpan(file_.service(0))); | 2693 EXPECT_TRUE(HasSpan(file_.service(0))); |
| 2029 EXPECT_TRUE(HasSpan(file_.service(0), "name")); | 2694 EXPECT_TRUE(HasSpan(file_.service(0), "name")); |
| 2030 } | 2695 } |
| 2031 | 2696 |
| 2697 |
| 2032 TEST_F(SourceInfoTest, Options) { | 2698 TEST_F(SourceInfoTest, Options) { |
| 2033 EXPECT_TRUE(Parse( | 2699 EXPECT_TRUE(Parse( |
| 2034 "$a$option $b$foo$c$.$d$($e$bar.baz$f$)$g$ = " | 2700 "$a$option $b$foo$c$.$d$($e$bar.baz$f$)$g$ = " |
| 2035 "$h$123$i$;$j$\n" | 2701 "$h$123$i$;$j$\n" |
| 2036 "$k$option qux = $l$-123$m$;$n$\n" | 2702 "$k$option qux = $l$-123$m$;$n$\n" |
| 2037 "$o$option corge = $p$abc$q$;$r$\n" | 2703 "$o$option corge = $p$abc$q$;$r$\n" |
| 2038 "$s$option grault = $t$'blah'$u$;$v$\n" | 2704 "$s$option grault = $t$'blah'$u$;$v$\n" |
| 2039 "$w$option garply = $x${ yadda yadda }$y$;$z$\n" | 2705 "$w$option garply = $x${ yadda yadda }$y$;$z$\n" |
| 2040 "$0$option waldo = $1$123.0$2$;$3$\n" | 2706 "$0$option waldo = $1$123.0$2$;$3$\n" |
| 2041 )); | 2707 )); |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2101 " $a$option mopt = 1;$b$\n" | 2767 " $a$option mopt = 1;$b$\n" |
| 2102 "}\n" | 2768 "}\n" |
| 2103 "enum Bar {\n" | 2769 "enum Bar {\n" |
| 2104 " $c$option eopt = 1;$d$\n" | 2770 " $c$option eopt = 1;$d$\n" |
| 2105 "}\n" | 2771 "}\n" |
| 2106 "service Baz {\n" | 2772 "service Baz {\n" |
| 2107 " $e$option sopt = 1;$f$\n" | 2773 " $e$option sopt = 1;$f$\n" |
| 2108 " rpc M(X) returns(Y) {\n" | 2774 " rpc M(X) returns(Y) {\n" |
| 2109 " $g$option mopt = 1;$h$\n" | 2775 " $g$option mopt = 1;$h$\n" |
| 2110 " }\n" | 2776 " }\n" |
| 2777 " rpc MS4($1$stream$2$ X) returns($3$stream$4$ Y) {\n" |
| 2778 " $k$option mopt = 1;$l$\n" |
| 2779 " }\n" |
| 2111 "}\n")); | 2780 "}\n")); |
| 2112 | 2781 |
| 2113 EXPECT_TRUE(HasSpan('a', 'b', file_.message_type(0).options())); | 2782 EXPECT_TRUE(HasSpan('a', 'b', file_.message_type(0).options())); |
| 2114 EXPECT_TRUE(HasSpan('c', 'd', file_.enum_type(0).options())); | 2783 EXPECT_TRUE(HasSpan('c', 'd', file_.enum_type(0).options())); |
| 2115 EXPECT_TRUE(HasSpan('e', 'f', file_.service(0).options())); | 2784 EXPECT_TRUE(HasSpan('e', 'f', file_.service(0).options())); |
| 2116 EXPECT_TRUE(HasSpan('g', 'h', file_.service(0).method(0).options())); | 2785 EXPECT_TRUE(HasSpan('g', 'h', file_.service(0).method(0).options())); |
| 2117 | 2786 |
| 2118 // Ignore these. | 2787 // Ignore these. |
| 2119 EXPECT_TRUE(HasSpan(file_)); | 2788 EXPECT_TRUE(HasSpan(file_)); |
| 2120 EXPECT_TRUE(HasSpan(file_.message_type(0))); | 2789 EXPECT_TRUE(HasSpan(file_.message_type(0))); |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2160 EXPECT_TRUE(HasSpan(file_.service(0).method(0).options() | 2829 EXPECT_TRUE(HasSpan(file_.service(0).method(0).options() |
| 2161 .uninterpreted_option(0))); | 2830 .uninterpreted_option(0))); |
| 2162 EXPECT_TRUE(HasSpan(file_.service(0).method(0).options() | 2831 EXPECT_TRUE(HasSpan(file_.service(0).method(0).options() |
| 2163 .uninterpreted_option(0), "name")); | 2832 .uninterpreted_option(0), "name")); |
| 2164 EXPECT_TRUE(HasSpan(file_.service(0).method(0).options() | 2833 EXPECT_TRUE(HasSpan(file_.service(0).method(0).options() |
| 2165 .uninterpreted_option(0).name(0))); | 2834 .uninterpreted_option(0).name(0))); |
| 2166 EXPECT_TRUE(HasSpan(file_.service(0).method(0).options() | 2835 EXPECT_TRUE(HasSpan(file_.service(0).method(0).options() |
| 2167 .uninterpreted_option(0).name(0), "name_part")); | 2836 .uninterpreted_option(0).name(0), "name_part")); |
| 2168 EXPECT_TRUE(HasSpan(file_.service(0).method(0).options() | 2837 EXPECT_TRUE(HasSpan(file_.service(0).method(0).options() |
| 2169 .uninterpreted_option(0), "positive_int_value")); | 2838 .uninterpreted_option(0), "positive_int_value")); |
| 2839 |
| 2840 EXPECT_TRUE(HasSpan('k', 'l', file_.service(0).method(1).options())); |
| 2841 EXPECT_TRUE(HasSpan(file_.service(0).method(1))); |
| 2842 EXPECT_TRUE(HasSpan(file_.service(0).method(1), "name")); |
| 2843 EXPECT_TRUE(HasSpan(file_.service(0).method(1), "input_type")); |
| 2844 EXPECT_TRUE(HasSpan(file_.service(0).method(1), "output_type")); |
| 2845 EXPECT_TRUE(HasSpan(file_.service(0).method(1).options() |
| 2846 .uninterpreted_option(0))); |
| 2847 EXPECT_TRUE(HasSpan(file_.service(0).method(1).options() |
| 2848 .uninterpreted_option(0), "name")); |
| 2849 EXPECT_TRUE(HasSpan(file_.service(0).method(1).options() |
| 2850 .uninterpreted_option(0).name(0))); |
| 2851 EXPECT_TRUE(HasSpan(file_.service(0).method(1).options() |
| 2852 .uninterpreted_option(0).name(0), "name_part")); |
| 2853 EXPECT_TRUE(HasSpan(file_.service(0).method(1).options() |
| 2854 .uninterpreted_option(0), "positive_int_value")); |
| 2855 EXPECT_TRUE(HasSpan('1', '2', file_.service(0).method(1), |
| 2856 "client_streaming")); |
| 2857 EXPECT_TRUE(HasSpan('3', '4', file_.service(0).method(1), |
| 2858 "server_streaming")); |
| 2170 } | 2859 } |
| 2171 | 2860 |
| 2172 TEST_F(SourceInfoTest, FieldOptions) { | 2861 TEST_F(SourceInfoTest, FieldOptions) { |
| 2173 // The actual "name = value" pairs are parsed by the same code as for | 2862 // 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 | 2863 // top-level options so we won't re-test that -- just make sure that the |
| 2175 // syntax used for field options is understood. | 2864 // syntax used for field options is understood. |
| 2176 EXPECT_TRUE(Parse( | 2865 EXPECT_TRUE(Parse( |
| 2177 "message Foo {" | 2866 "message Foo {" |
| 2178 " optional int32 bar = 1 " | 2867 " optional int32 bar = 1 " |
| 2179 "$a$[default=$b$123$c$,$d$opt1=123$e$," | 2868 "$a$[default=$b$123$c$,$d$opt1=123$e$," |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2245 } | 2934 } |
| 2246 | 2935 |
| 2247 TEST_F(SourceInfoTest, DocComments) { | 2936 TEST_F(SourceInfoTest, DocComments) { |
| 2248 EXPECT_TRUE(Parse( | 2937 EXPECT_TRUE(Parse( |
| 2249 "// Foo leading\n" | 2938 "// Foo leading\n" |
| 2250 "// line 2\n" | 2939 "// line 2\n" |
| 2251 "$a$message Foo {\n" | 2940 "$a$message Foo {\n" |
| 2252 " // Foo trailing\n" | 2941 " // Foo trailing\n" |
| 2253 " // line 2\n" | 2942 " // line 2\n" |
| 2254 "\n" | 2943 "\n" |
| 2255 " // ignored\n" | 2944 " // detached\n" |
| 2256 "\n" | 2945 "\n" |
| 2257 " // bar leading\n" | 2946 " // bar leading\n" |
| 2258 " $b$optional int32 bar = 1;$c$\n" | 2947 " $b$optional int32 bar = 1;$c$\n" |
| 2259 " // bar trailing\n" | 2948 " // bar trailing\n" |
| 2260 "}$d$\n" | 2949 "}$d$\n" |
| 2261 "// ignored\n" | 2950 "// ignored\n" |
| 2262 )); | 2951 )); |
| 2263 | 2952 |
| 2264 const DescriptorProto& foo = file_.message_type(0); | 2953 const DescriptorProto& foo = file_.message_type(0); |
| 2265 const FieldDescriptorProto& bar = foo.field(0); | 2954 const FieldDescriptorProto& bar = foo.field(0); |
| 2266 | 2955 |
| 2267 EXPECT_TRUE(HasSpanWithComment('a', 'd', foo, | 2956 EXPECT_TRUE(HasSpanWithComment('a', 'd', foo, |
| 2268 " Foo leading\n line 2\n", | 2957 " Foo leading\n line 2\n", |
| 2269 " Foo trailing\n line 2\n")); | 2958 " Foo trailing\n line 2\n", |
| 2959 NULL)); |
| 2270 EXPECT_TRUE(HasSpanWithComment('b', 'c', bar, | 2960 EXPECT_TRUE(HasSpanWithComment('b', 'c', bar, |
| 2271 " bar leading\n", | 2961 " bar leading\n", |
| 2272 " bar trailing\n")); | 2962 " bar trailing\n", |
| 2963 " detached\n")); |
| 2273 | 2964 |
| 2274 // Ignore these. | 2965 // Ignore these. |
| 2275 EXPECT_TRUE(HasSpan(file_)); | 2966 EXPECT_TRUE(HasSpan(file_)); |
| 2276 EXPECT_TRUE(HasSpan(foo, "name")); | 2967 EXPECT_TRUE(HasSpan(foo, "name")); |
| 2277 EXPECT_TRUE(HasSpan(bar, "label")); | 2968 EXPECT_TRUE(HasSpan(bar, "label")); |
| 2278 EXPECT_TRUE(HasSpan(bar, "type")); | 2969 EXPECT_TRUE(HasSpan(bar, "type")); |
| 2279 EXPECT_TRUE(HasSpan(bar, "name")); | 2970 EXPECT_TRUE(HasSpan(bar, "name")); |
| 2280 EXPECT_TRUE(HasSpan(bar, "number")); | 2971 EXPECT_TRUE(HasSpan(bar, "number")); |
| 2281 } | 2972 } |
| 2282 | 2973 |
| 2283 TEST_F(SourceInfoTest, DocComments2) { | 2974 TEST_F(SourceInfoTest, DocComments2) { |
| 2284 EXPECT_TRUE(Parse( | 2975 EXPECT_TRUE(Parse( |
| 2285 "// ignored\n" | 2976 "// detached before message.\n" |
| 2286 "syntax = \"proto2\";\n" | 2977 "\n" |
| 2287 "// Foo leading\n" | 2978 "// Foo leading\n" |
| 2288 "// line 2\n" | 2979 "// line 2\n" |
| 2289 "$a$message Foo {\n" | 2980 "$a$message Foo {\n" |
| 2290 " /* Foo trailing\n" | 2981 " /* Foo trailing\n" |
| 2291 " * line 2 */\n" | 2982 " * line 2 */\n" |
| 2292 " // ignored\n" | 2983 " // detached\n" |
| 2293 " /* bar leading\n" | 2984 " /* bar leading\n" |
| 2294 " */" | 2985 " */" |
| 2295 " $b$optional int32 bar = 1;$c$ // bar trailing\n" | 2986 " $b$optional int32 bar = 1;$c$ // bar trailing\n" |
| 2296 " // ignored\n" | 2987 " // ignored detached\n" |
| 2297 "}$d$\n" | 2988 "}$d$\n" |
| 2298 "// ignored\n" | 2989 "// ignored\n" |
| 2299 "\n" | 2990 "\n" |
| 2991 "// detached before option\n" |
| 2992 "\n" |
| 2300 "// option leading\n" | 2993 "// option leading\n" |
| 2301 "$e$option baz = 123;$f$\n" | 2994 "$e$option baz = 123;$f$\n" |
| 2302 "// option trailing\n" | 2995 "// option trailing\n" |
| 2303 )); | 2996 )); |
| 2304 | 2997 |
| 2305 const DescriptorProto& foo = file_.message_type(0); | 2998 const DescriptorProto& foo = file_.message_type(0); |
| 2306 const FieldDescriptorProto& bar = foo.field(0); | 2999 const FieldDescriptorProto& bar = foo.field(0); |
| 2307 const UninterpretedOption& baz = file_.options().uninterpreted_option(0); | 3000 const UninterpretedOption& baz = file_.options().uninterpreted_option(0); |
| 2308 | 3001 |
| 2309 EXPECT_TRUE(HasSpanWithComment('a', 'd', foo, | 3002 EXPECT_TRUE(HasSpanWithComment('a', 'd', foo, |
| 2310 " Foo leading\n line 2\n", | 3003 " Foo leading\n line 2\n", |
| 2311 " Foo trailing\n line 2 ")); | 3004 " Foo trailing\n line 2 ", |
| 3005 " detached before message.\n")); |
| 2312 EXPECT_TRUE(HasSpanWithComment('b', 'c', bar, | 3006 EXPECT_TRUE(HasSpanWithComment('b', 'c', bar, |
| 2313 " bar leading\n", | 3007 " bar leading\n", |
| 2314 " bar trailing\n")); | 3008 " bar trailing\n", |
| 3009 " detached\n")); |
| 2315 EXPECT_TRUE(HasSpanWithComment('e', 'f', baz, | 3010 EXPECT_TRUE(HasSpanWithComment('e', 'f', baz, |
| 2316 " option leading\n", | 3011 " option leading\n", |
| 2317 " option trailing\n")); | 3012 " option trailing\n", |
| 3013 " detached before option\n")); |
| 2318 | 3014 |
| 2319 // Ignore these. | 3015 // Ignore these. |
| 2320 EXPECT_TRUE(HasSpan(file_)); | 3016 EXPECT_TRUE(HasSpan(file_)); |
| 2321 EXPECT_TRUE(HasSpan(foo, "name")); | 3017 EXPECT_TRUE(HasSpan(foo, "name")); |
| 2322 EXPECT_TRUE(HasSpan(bar, "label")); | 3018 EXPECT_TRUE(HasSpan(bar, "label")); |
| 2323 EXPECT_TRUE(HasSpan(bar, "type")); | 3019 EXPECT_TRUE(HasSpan(bar, "type")); |
| 2324 EXPECT_TRUE(HasSpan(bar, "name")); | 3020 EXPECT_TRUE(HasSpan(bar, "name")); |
| 2325 EXPECT_TRUE(HasSpan(bar, "number")); | 3021 EXPECT_TRUE(HasSpan(bar, "number")); |
| 2326 EXPECT_TRUE(HasSpan(file_.options())); | 3022 EXPECT_TRUE(HasSpan(file_.options())); |
| 2327 EXPECT_TRUE(HasSpan(baz, "name")); | 3023 EXPECT_TRUE(HasSpan(baz, "name")); |
| (...skipping 10 matching lines...) Expand all Loading... |
| 2338 " // bar trailing\n" | 3034 " // bar trailing\n" |
| 2339 "}$d$\n" | 3035 "}$d$\n" |
| 2340 "// ignored\n" | 3036 "// ignored\n" |
| 2341 )); | 3037 )); |
| 2342 | 3038 |
| 2343 const DescriptorProto& foo = file_.message_type(0); | 3039 const DescriptorProto& foo = file_.message_type(0); |
| 2344 const FieldDescriptorProto& bar = foo.field(0); | 3040 const FieldDescriptorProto& bar = foo.field(0); |
| 2345 | 3041 |
| 2346 EXPECT_TRUE(HasSpanWithComment('b', 'c', bar, | 3042 EXPECT_TRUE(HasSpanWithComment('b', 'c', bar, |
| 2347 " bar leading\n", | 3043 " bar leading\n", |
| 2348 " bar trailing\n")); | 3044 " bar trailing\n", |
| 3045 NULL)); |
| 2349 | 3046 |
| 2350 // Ignore these. | 3047 // Ignore these. |
| 2351 EXPECT_TRUE(HasSpan(file_)); | 3048 EXPECT_TRUE(HasSpan(file_)); |
| 2352 EXPECT_TRUE(HasSpan(foo)); | 3049 EXPECT_TRUE(HasSpan(foo)); |
| 2353 EXPECT_TRUE(HasSpan(foo, "name")); | 3050 EXPECT_TRUE(HasSpan(foo, "name")); |
| 2354 EXPECT_TRUE(HasSpan(bar, "label")); | 3051 EXPECT_TRUE(HasSpan(bar, "label")); |
| 2355 EXPECT_TRUE(HasSpan(bar, "type")); | 3052 EXPECT_TRUE(HasSpan(bar, "type")); |
| 2356 EXPECT_TRUE(HasSpan(bar, "name")); | 3053 EXPECT_TRUE(HasSpan(bar, "name")); |
| 2357 EXPECT_TRUE(HasSpan(bar, "number")); | 3054 EXPECT_TRUE(HasSpan(bar, "number")); |
| 2358 EXPECT_TRUE(HasSpan(bar.options())); | 3055 EXPECT_TRUE(HasSpan(bar.options())); |
| 2359 EXPECT_TRUE(HasSpan(bar.options().uninterpreted_option(0))); | 3056 EXPECT_TRUE(HasSpan(bar.options().uninterpreted_option(0))); |
| 2360 EXPECT_TRUE(HasSpan(bar.options().uninterpreted_option(0), "name")); | 3057 EXPECT_TRUE(HasSpan(bar.options().uninterpreted_option(0), "name")); |
| 2361 EXPECT_TRUE(HasSpan(bar.options().uninterpreted_option(0).name(0))); | 3058 EXPECT_TRUE(HasSpan(bar.options().uninterpreted_option(0).name(0))); |
| 2362 EXPECT_TRUE(HasSpan( | 3059 EXPECT_TRUE(HasSpan( |
| 2363 bar.options().uninterpreted_option(0).name(0), "name_part")); | 3060 bar.options().uninterpreted_option(0).name(0), "name_part")); |
| 2364 EXPECT_TRUE(HasSpan( | 3061 EXPECT_TRUE(HasSpan( |
| 2365 bar.options().uninterpreted_option(0), "aggregate_value")); | 3062 bar.options().uninterpreted_option(0), "aggregate_value")); |
| 2366 } | 3063 } |
| 2367 | 3064 |
| 3065 TEST_F(SourceInfoTest, DocCommentsTopLevel) { |
| 3066 EXPECT_TRUE(Parse( |
| 3067 "// detached before syntax paragraph 1\n" |
| 3068 "\n" |
| 3069 "// detached before syntax paragraph 2\n" |
| 3070 "\n" |
| 3071 "// syntax leading\n" |
| 3072 "$a$syntax = \"proto2\";$b$\n" |
| 3073 "// syntax trailing\n" |
| 3074 "\n" |
| 3075 "// syntax-package detached comments\n" |
| 3076 "\n" |
| 3077 ";\n" |
| 3078 "\n" |
| 3079 "// detached after empty before package\n" |
| 3080 "\n" |
| 3081 "// package leading\n" |
| 3082 "package $c$foo$d$;\n" |
| 3083 "// package trailing\n" |
| 3084 "\n" |
| 3085 "// ignored detach\n" |
| 3086 "\n")); |
| 3087 |
| 3088 EXPECT_TRUE(HasSpan('a', 'b', file_, "syntax", -1, |
| 3089 " syntax leading\n", |
| 3090 " syntax trailing\n", |
| 3091 " detached before syntax paragraph 1\n" |
| 3092 "\n" |
| 3093 " detached before syntax paragraph 2\n")); |
| 3094 EXPECT_TRUE(HasSpan('c', 'd', file_, "package", -1, |
| 3095 " package leading\n", |
| 3096 " package trailing\n", |
| 3097 " syntax-package detached comments\n" |
| 3098 "\n" |
| 3099 " detached after empty before package\n")); |
| 3100 |
| 3101 // ignore these. |
| 3102 EXPECT_TRUE(HasSpan(file_)); |
| 3103 } |
| 3104 |
| 3105 TEST_F(SourceInfoTest, DocCommentsOneof) { |
| 3106 EXPECT_TRUE(Parse( |
| 3107 "// Foo leading\n" |
| 3108 "$a$message Foo {\n" |
| 3109 " /* Foo trailing\n" |
| 3110 " */\n" |
| 3111 " // detached before oneof\n" |
| 3112 " /* bar leading\n" |
| 3113 " * line 2 */\n" |
| 3114 " $b$oneof bar {\n" |
| 3115 " /* bar trailing\n" |
| 3116 " * line 2 */\n" |
| 3117 " // detached before bar_int\n" |
| 3118 " /* bar_int leading\n" |
| 3119 " */\n" |
| 3120 " $c$int32 bar_int = 1;$d$ // bar_int trailing\n" |
| 3121 " // detach comment ignored\n" |
| 3122 " }$e$\n" |
| 3123 "}$f$\n")); |
| 3124 |
| 3125 const DescriptorProto& foo = file_.message_type(0); |
| 3126 const OneofDescriptorProto& bar = foo.oneof_decl(0); |
| 3127 const FieldDescriptorProto& bar_int = foo.field(0); |
| 3128 |
| 3129 EXPECT_TRUE(HasSpanWithComment('a', 'f', foo, |
| 3130 " Foo leading\n", |
| 3131 " Foo trailing\n", |
| 3132 NULL)); |
| 3133 EXPECT_TRUE(HasSpanWithComment('b', 'e', bar, |
| 3134 " bar leading\n line 2 ", |
| 3135 " bar trailing\n line 2 ", |
| 3136 " detached before oneof\n")); |
| 3137 EXPECT_TRUE(HasSpanWithComment('c', 'd', bar_int, |
| 3138 " bar_int leading\n", |
| 3139 " bar_int trailing\n", |
| 3140 " detached before bar_int\n")); |
| 3141 |
| 3142 // Ignore these. |
| 3143 EXPECT_TRUE(HasSpan(file_)); |
| 3144 EXPECT_TRUE(HasSpan(foo, "name")); |
| 3145 EXPECT_TRUE(HasSpan(bar, "name")); |
| 3146 EXPECT_TRUE(HasSpan(bar_int, "type")); |
| 3147 EXPECT_TRUE(HasSpan(bar_int, "name")); |
| 3148 EXPECT_TRUE(HasSpan(bar_int, "number")); |
| 3149 } |
| 3150 |
| 2368 // =================================================================== | 3151 // =================================================================== |
| 2369 | 3152 |
| 2370 } // anonymous namespace | 3153 } // anonymous namespace |
| 2371 | 3154 |
| 2372 } // namespace compiler | 3155 } // namespace compiler |
| 2373 } // namespace protobuf | 3156 } // namespace protobuf |
| 2374 } // namespace google | 3157 } // namespace google |
| OLD | NEW |