2135
2135
EXPECT_EQ(FileOptions::SPEED, file->options().optimize_for());
2138
TEST(CustomOptions, MessageOptionThreeFieldsSet) {
2139
// This tests a bug which previously existed in custom options parsing. The
2140
// bug occurred when you defined a custom option with message type and then
2141
// set three fields of that option on a single definition (see the example
2142
// below). The bug is a bit hard to explain, so check the change history if
2143
// you want to know more.
2144
DescriptorPool pool;
2146
FileDescriptorProto file_proto;
2147
FileDescriptorProto::descriptor()->file()->CopyTo(&file_proto);
2148
ASSERT_TRUE(pool.BuildFile(file_proto) != NULL);
2150
protobuf_unittest::TestMessageWithCustomOptions::descriptor()
2151
->file()->CopyTo(&file_proto);
2152
ASSERT_TRUE(pool.BuildFile(file_proto) != NULL);
2154
// The following represents the definition:
2156
// import "google/protobuf/unittest_custom_options.proto"
2157
// package protobuf_unittest;
2159
// option (complex_opt1).foo = 1234;
2160
// option (complex_opt1).foo2 = 1234;
2161
// option (complex_opt1).foo3 = 1234;
2163
ASSERT_TRUE(TextFormat::ParseFromString(
2164
"name: \"custom_options_import.proto\" "
2165
"package: \"protobuf_unittest\" "
2166
"dependency: \"google/protobuf/unittest_custom_options.proto\" "
2170
" uninterpreted_option { "
2172
" name_part: \"complex_opt1\" "
2173
" is_extension: true "
2176
" name_part: \"foo\" "
2177
" is_extension: false "
2179
" positive_int_value: 1234 "
2181
" uninterpreted_option { "
2183
" name_part: \"complex_opt1\" "
2184
" is_extension: true "
2187
" name_part: \"foo2\" "
2188
" is_extension: false "
2190
" positive_int_value: 1234 "
2192
" uninterpreted_option { "
2194
" name_part: \"complex_opt1\" "
2195
" is_extension: true "
2198
" name_part: \"foo3\" "
2199
" is_extension: false "
2201
" positive_int_value: 1234 "
2207
const FileDescriptor* file = pool.BuildFile(file_proto);
2208
ASSERT_TRUE(file != NULL);
2209
ASSERT_EQ(1, file->message_type_count());
2211
const MessageOptions& options = file->message_type(0)->options();
2212
EXPECT_EQ(1234, options.GetExtension(protobuf_unittest::complex_opt1).foo());
2139
2216
// ===================================================================
2335
2412
"bar.proto: bar.proto: OTHER: Import \"foo.proto\" has not been loaded.\n");
2415
TEST_F(ValidationErrorTest, ForeignUnimportedPackageNoCrash) {
2416
// Used to crash: If we depend on a non-existent file and then refer to a
2417
// package defined in a file that we didn't import, and that package is
2418
// nested within a parent package which this file is also in, and we don't
2419
// include that parent package in the name (i.e. we do a relative lookup)...
2422
"name: 'foo.proto' "
2423
"package: 'outer.foo' ");
2424
BuildFileWithErrors(
2425
"name: 'bar.proto' "
2426
"dependency: 'baz.proto' "
2427
"package: 'outer.bar' "
2430
" field { name:'bar' number:1 label:LABEL_OPTIONAL type_name:'foo.Foo' }"
2433
"bar.proto: bar.proto: OTHER: Import \"baz.proto\" has not been loaded.\n"
2434
"bar.proto: outer.bar.Bar.bar: TYPE: \"outer.foo\" seems to be defined in "
2435
"\"foo.proto\", which is not imported by \"bar.proto\". To use it here, "
2436
"please add the necessary import.\n");
2338
2439
TEST_F(ValidationErrorTest, DupeFile) {
2340
2441
"name: \"foo.proto\" "
3345
3446
"message type.\n");
3449
TEST_F(ValidationErrorTest, NotLiteImportsLite) {
3451
"name: \"bar.proto\" "
3452
"options { optimize_for: LITE_RUNTIME } ");
3454
BuildFileWithErrors(
3455
"name: \"foo.proto\" "
3456
"dependency: \"bar.proto\" ",
3458
"foo.proto: foo.proto: OTHER: Files that do not use optimize_for = "
3459
"LITE_RUNTIME cannot import files which do use this option. This file "
3460
"is not lite, but it imports \"bar.proto\" which is.\n");
3463
TEST_F(ValidationErrorTest, LiteExtendsNotLite) {
3465
"name: \"bar.proto\" "
3468
" extension_range { start: 1 end: 1000 }"
3471
BuildFileWithErrors(
3472
"name: \"foo.proto\" "
3473
"dependency: \"bar.proto\" "
3474
"options { optimize_for: LITE_RUNTIME } "
3475
"extension { name: \"ext\" number: 123 label: LABEL_OPTIONAL "
3476
" type: TYPE_INT32 extendee: \"Bar\" }",
3478
"foo.proto: ext: EXTENDEE: Extensions to non-lite types can only be "
3479
"declared in non-lite files. Note that you cannot extend a non-lite "
3480
"type to contain a lite type, but the reverse is allowed.\n");
3483
TEST_F(ValidationErrorTest, NoLiteServices) {
3484
BuildFileWithErrors(
3485
"name: \"foo.proto\" "
3486
"options { optimize_for: LITE_RUNTIME } "
3487
"service { name: \"Foo\" }",
3489
"foo.proto: Foo: NAME: Files with optimize_for = LITE_RUNTIME cannot "
3490
"define services.\n");
3348
3493
TEST_F(ValidationErrorTest, RollbackAfterError) {
3349
3494
// Build a file which contains every kind of construct but references an
3350
3495
// undefined type. All these constructs will be added to the symbol table