~ubuntu-branches/ubuntu/oneiric/protobuf/oneiric

« back to all changes in this revision

Viewing changes to src/google/protobuf/descriptor_unittest.cc

  • Committer: Bazaar Package Importer
  • Author(s): Iustin Pop
  • Date: 2008-08-03 11:01:44 UTC
  • Revision ID: james.westby@ubuntu.com-20080803110144-uyiw41bf1m2oe17t
Tags: upstream-2.0.0~b
ImportĀ upstreamĀ versionĀ 2.0.0~b

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
// Protocol Buffers - Google's data interchange format
 
2
// Copyright 2008 Google Inc.
 
3
// http://code.google.com/p/protobuf/
 
4
//
 
5
// Licensed under the Apache License, Version 2.0 (the "License");
 
6
// you may not use this file except in compliance with the License.
 
7
// You may obtain a copy of the License at
 
8
//
 
9
//      http://www.apache.org/licenses/LICENSE-2.0
 
10
//
 
11
// Unless required by applicable law or agreed to in writing, software
 
12
// distributed under the License is distributed on an "AS IS" BASIS,
 
13
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 
14
// See the License for the specific language governing permissions and
 
15
// limitations under the License.
 
16
 
 
17
// Author: kenton@google.com (Kenton Varda)
 
18
//  Based on original Protocol Buffers design by
 
19
//  Sanjay Ghemawat, Jeff Dean, and others.
 
20
//
 
21
// This file makes extensive use of RFC 3092.  :)
 
22
 
 
23
#include <vector>
 
24
 
 
25
#include <google/protobuf/descriptor.h>
 
26
#include <google/protobuf/descriptor_database.h>
 
27
#include <google/protobuf/descriptor.pb.h>
 
28
#include <google/protobuf/text_format.h>
 
29
#include <google/protobuf/unittest.pb.h>
 
30
#include <google/protobuf/stubs/strutil.h>
 
31
#include <google/protobuf/stubs/substitute.h>
 
32
 
 
33
#include <google/protobuf/stubs/common.h>
 
34
#include <google/protobuf/testing/googletest.h>
 
35
#include <gtest/gtest.h>
 
36
 
 
37
namespace google {
 
38
namespace protobuf {
 
39
 
 
40
namespace {
 
41
 
 
42
// Some helpers to make assembling descriptors faster.
 
43
DescriptorProto* AddMessage(FileDescriptorProto* file, const string& name) {
 
44
  DescriptorProto* result = file->add_message_type();
 
45
  result->set_name(name);
 
46
  return result;
 
47
}
 
48
 
 
49
DescriptorProto* AddNestedMessage(DescriptorProto* parent, const string& name) {
 
50
  DescriptorProto* result = parent->add_nested_type();
 
51
  result->set_name(name);
 
52
  return result;
 
53
}
 
54
 
 
55
EnumDescriptorProto* AddEnum(FileDescriptorProto* file, const string& name) {
 
56
  EnumDescriptorProto* result = file->add_enum_type();
 
57
  result->set_name(name);
 
58
  return result;
 
59
}
 
60
 
 
61
EnumDescriptorProto* AddNestedEnum(DescriptorProto* parent,
 
62
                                   const string& name) {
 
63
  EnumDescriptorProto* result = parent->add_enum_type();
 
64
  result->set_name(name);
 
65
  return result;
 
66
}
 
67
 
 
68
ServiceDescriptorProto* AddService(FileDescriptorProto* file,
 
69
                                   const string& name) {
 
70
  ServiceDescriptorProto* result = file->add_service();
 
71
  result->set_name(name);
 
72
  return result;
 
73
}
 
74
 
 
75
FieldDescriptorProto* AddField(DescriptorProto* parent,
 
76
                               const string& name, int number,
 
77
                               FieldDescriptorProto::Label label,
 
78
                               FieldDescriptorProto::Type type) {
 
79
  FieldDescriptorProto* result = parent->add_field();
 
80
  result->set_name(name);
 
81
  result->set_number(number);
 
82
  result->set_label(label);
 
83
  result->set_type(type);
 
84
  return result;
 
85
}
 
86
 
 
87
FieldDescriptorProto* AddExtension(FileDescriptorProto* file,
 
88
                                   const string& extendee,
 
89
                                   const string& name, int number,
 
90
                                   FieldDescriptorProto::Label label,
 
91
                                   FieldDescriptorProto::Type type) {
 
92
  FieldDescriptorProto* result = file->add_extension();
 
93
  result->set_name(name);
 
94
  result->set_number(number);
 
95
  result->set_label(label);
 
96
  result->set_type(type);
 
97
  result->set_extendee(extendee);
 
98
  return result;
 
99
}
 
100
 
 
101
FieldDescriptorProto* AddNestedExtension(DescriptorProto* parent,
 
102
                                         const string& extendee,
 
103
                                         const string& name, int number,
 
104
                                         FieldDescriptorProto::Label label,
 
105
                                         FieldDescriptorProto::Type type) {
 
106
  FieldDescriptorProto* result = parent->add_extension();
 
107
  result->set_name(name);
 
108
  result->set_number(number);
 
109
  result->set_label(label);
 
110
  result->set_type(type);
 
111
  result->set_extendee(extendee);
 
112
  return result;
 
113
}
 
114
 
 
115
DescriptorProto::ExtensionRange* AddExtensionRange(DescriptorProto* parent,
 
116
                                                   int start, int end) {
 
117
  DescriptorProto::ExtensionRange* result = parent->add_extension_range();
 
118
  result->set_start(start);
 
119
  result->set_end(end);
 
120
  return result;
 
121
}
 
122
 
 
123
EnumValueDescriptorProto* AddEnumValue(EnumDescriptorProto* enum_proto,
 
124
                                       const string& name, int number) {
 
125
  EnumValueDescriptorProto* result = enum_proto->add_value();
 
126
  result->set_name(name);
 
127
  result->set_number(number);
 
128
  return result;
 
129
}
 
130
 
 
131
MethodDescriptorProto* AddMethod(ServiceDescriptorProto* service,
 
132
                                 const string& name,
 
133
                                 const string& input_type,
 
134
                                 const string& output_type) {
 
135
  MethodDescriptorProto* result = service->add_method();
 
136
  result->set_name(name);
 
137
  result->set_input_type(input_type);
 
138
  result->set_output_type(output_type);
 
139
  return result;
 
140
}
 
141
 
 
142
// Empty enums technically aren't allowed.  We need to insert a dummy value
 
143
// into them.
 
144
void AddEmptyEnum(FileDescriptorProto* file, const string& name) {
 
145
  AddEnumValue(AddEnum(file, name), name + "_DUMMY", 1);
 
146
}
 
147
 
 
148
// ===================================================================
 
149
 
 
150
// Test simple files.
 
151
class FileDescriptorTest : public testing::Test {
 
152
 protected:
 
153
  virtual void SetUp() {
 
154
    // Build descriptors for the following definitions:
 
155
    //
 
156
    //   // in "foo.proto"
 
157
    //   message FooMessage { extensions 1; }
 
158
    //   enum FooEnum {FOO_ENUM_VALUE = 1;}
 
159
    //   service FooService {}
 
160
    //   extend FooMessage { optional int32 foo_extension = 1; }
 
161
    //
 
162
    //   // in "bar.proto"
 
163
    //   package bar_package;
 
164
    //   message BarMessage { extensions 1; }
 
165
    //   enum BarEnum {BAR_ENUM_VALUE = 1;}
 
166
    //   service BarService {}
 
167
    //   extend BarMessage { optional int32 bar_extension = 1; }
 
168
    //
 
169
    // Also, we have an empty file "baz.proto".  This file's purpose is to
 
170
    // make sure that even though it has the same package as foo.proto,
 
171
    // searching it for members of foo.proto won't work.
 
172
 
 
173
    FileDescriptorProto foo_file;
 
174
    foo_file.set_name("foo.proto");
 
175
    AddExtensionRange(AddMessage(&foo_file, "FooMessage"), 1, 2);
 
176
    AddEnumValue(AddEnum(&foo_file, "FooEnum"), "FOO_ENUM_VALUE", 1);
 
177
    AddService(&foo_file, "FooService");
 
178
    AddExtension(&foo_file, "FooMessage", "foo_extension", 1,
 
179
                 FieldDescriptorProto::LABEL_OPTIONAL,
 
180
                 FieldDescriptorProto::TYPE_INT32);
 
181
 
 
182
    FileDescriptorProto bar_file;
 
183
    bar_file.set_name("bar.proto");
 
184
    bar_file.set_package("bar_package");
 
185
    bar_file.add_dependency("foo.proto");
 
186
    AddExtensionRange(AddMessage(&bar_file, "BarMessage"), 1, 2);
 
187
    AddEnumValue(AddEnum(&bar_file, "BarEnum"), "BAR_ENUM_VALUE", 1);
 
188
    AddService(&bar_file, "BarService");
 
189
    AddExtension(&bar_file, "bar_package.BarMessage", "bar_extension", 1,
 
190
                 FieldDescriptorProto::LABEL_OPTIONAL,
 
191
                 FieldDescriptorProto::TYPE_INT32);
 
192
 
 
193
    FileDescriptorProto baz_file;
 
194
    baz_file.set_name("baz.proto");
 
195
 
 
196
    // Build the descriptors and get the pointers.
 
197
    foo_file_ = pool_.BuildFile(foo_file);
 
198
    ASSERT_TRUE(foo_file_ != NULL);
 
199
 
 
200
    bar_file_ = pool_.BuildFile(bar_file);
 
201
    ASSERT_TRUE(bar_file_ != NULL);
 
202
 
 
203
    baz_file_ = pool_.BuildFile(baz_file);
 
204
    ASSERT_TRUE(baz_file_ != NULL);
 
205
 
 
206
    ASSERT_EQ(1, foo_file_->message_type_count());
 
207
    foo_message_ = foo_file_->message_type(0);
 
208
    ASSERT_EQ(1, foo_file_->enum_type_count());
 
209
    foo_enum_ = foo_file_->enum_type(0);
 
210
    ASSERT_EQ(1, foo_enum_->value_count());
 
211
    foo_enum_value_ = foo_enum_->value(0);
 
212
    ASSERT_EQ(1, foo_file_->service_count());
 
213
    foo_service_ = foo_file_->service(0);
 
214
    ASSERT_EQ(1, foo_file_->extension_count());
 
215
    foo_extension_ = foo_file_->extension(0);
 
216
 
 
217
    ASSERT_EQ(1, bar_file_->message_type_count());
 
218
    bar_message_ = bar_file_->message_type(0);
 
219
    ASSERT_EQ(1, bar_file_->enum_type_count());
 
220
    bar_enum_ = bar_file_->enum_type(0);
 
221
    ASSERT_EQ(1, bar_enum_->value_count());
 
222
    bar_enum_value_ = bar_enum_->value(0);
 
223
    ASSERT_EQ(1, bar_file_->service_count());
 
224
    bar_service_ = bar_file_->service(0);
 
225
    ASSERT_EQ(1, bar_file_->extension_count());
 
226
    bar_extension_ = bar_file_->extension(0);
 
227
  }
 
228
 
 
229
  DescriptorPool pool_;
 
230
 
 
231
  const FileDescriptor* foo_file_;
 
232
  const FileDescriptor* bar_file_;
 
233
  const FileDescriptor* baz_file_;
 
234
 
 
235
  const Descriptor*          foo_message_;
 
236
  const EnumDescriptor*      foo_enum_;
 
237
  const EnumValueDescriptor* foo_enum_value_;
 
238
  const ServiceDescriptor*   foo_service_;
 
239
  const FieldDescriptor*     foo_extension_;
 
240
 
 
241
  const Descriptor*          bar_message_;
 
242
  const EnumDescriptor*      bar_enum_;
 
243
  const EnumValueDescriptor* bar_enum_value_;
 
244
  const ServiceDescriptor*   bar_service_;
 
245
  const FieldDescriptor*     bar_extension_;
 
246
};
 
247
 
 
248
TEST_F(FileDescriptorTest, Name) {
 
249
  EXPECT_EQ("foo.proto", foo_file_->name());
 
250
  EXPECT_EQ("bar.proto", bar_file_->name());
 
251
  EXPECT_EQ("baz.proto", baz_file_->name());
 
252
}
 
253
 
 
254
TEST_F(FileDescriptorTest, Package) {
 
255
  EXPECT_EQ("", foo_file_->package());
 
256
  EXPECT_EQ("bar_package", bar_file_->package());
 
257
}
 
258
 
 
259
TEST_F(FileDescriptorTest, Dependencies) {
 
260
  EXPECT_EQ(0, foo_file_->dependency_count());
 
261
  EXPECT_EQ(1, bar_file_->dependency_count());
 
262
  EXPECT_EQ(foo_file_, bar_file_->dependency(0));
 
263
}
 
264
 
 
265
TEST_F(FileDescriptorTest, FindMessageTypeByName) {
 
266
  EXPECT_EQ(foo_message_, foo_file_->FindMessageTypeByName("FooMessage"));
 
267
  EXPECT_EQ(bar_message_, bar_file_->FindMessageTypeByName("BarMessage"));
 
268
 
 
269
  EXPECT_TRUE(foo_file_->FindMessageTypeByName("BarMessage") == NULL);
 
270
  EXPECT_TRUE(bar_file_->FindMessageTypeByName("FooMessage") == NULL);
 
271
  EXPECT_TRUE(baz_file_->FindMessageTypeByName("FooMessage") == NULL);
 
272
 
 
273
  EXPECT_TRUE(foo_file_->FindMessageTypeByName("NoSuchMessage") == NULL);
 
274
  EXPECT_TRUE(foo_file_->FindMessageTypeByName("FooEnum") == NULL);
 
275
}
 
276
 
 
277
TEST_F(FileDescriptorTest, FindEnumTypeByName) {
 
278
  EXPECT_EQ(foo_enum_, foo_file_->FindEnumTypeByName("FooEnum"));
 
279
  EXPECT_EQ(bar_enum_, bar_file_->FindEnumTypeByName("BarEnum"));
 
280
 
 
281
  EXPECT_TRUE(foo_file_->FindEnumTypeByName("BarEnum") == NULL);
 
282
  EXPECT_TRUE(bar_file_->FindEnumTypeByName("FooEnum") == NULL);
 
283
  EXPECT_TRUE(baz_file_->FindEnumTypeByName("FooEnum") == NULL);
 
284
 
 
285
  EXPECT_TRUE(foo_file_->FindEnumTypeByName("NoSuchEnum") == NULL);
 
286
  EXPECT_TRUE(foo_file_->FindEnumTypeByName("FooMessage") == NULL);
 
287
}
 
288
 
 
289
TEST_F(FileDescriptorTest, FindEnumValueByName) {
 
290
  EXPECT_EQ(foo_enum_value_, foo_file_->FindEnumValueByName("FOO_ENUM_VALUE"));
 
291
  EXPECT_EQ(bar_enum_value_, bar_file_->FindEnumValueByName("BAR_ENUM_VALUE"));
 
292
 
 
293
  EXPECT_TRUE(foo_file_->FindEnumValueByName("BAR_ENUM_VALUE") == NULL);
 
294
  EXPECT_TRUE(bar_file_->FindEnumValueByName("FOO_ENUM_VALUE") == NULL);
 
295
  EXPECT_TRUE(baz_file_->FindEnumValueByName("FOO_ENUM_VALUE") == NULL);
 
296
 
 
297
  EXPECT_TRUE(foo_file_->FindEnumValueByName("NO_SUCH_VALUE") == NULL);
 
298
  EXPECT_TRUE(foo_file_->FindEnumValueByName("FooMessage") == NULL);
 
299
}
 
300
 
 
301
TEST_F(FileDescriptorTest, FindServiceByName) {
 
302
  EXPECT_EQ(foo_service_, foo_file_->FindServiceByName("FooService"));
 
303
  EXPECT_EQ(bar_service_, bar_file_->FindServiceByName("BarService"));
 
304
 
 
305
  EXPECT_TRUE(foo_file_->FindServiceByName("BarService") == NULL);
 
306
  EXPECT_TRUE(bar_file_->FindServiceByName("FooService") == NULL);
 
307
  EXPECT_TRUE(baz_file_->FindServiceByName("FooService") == NULL);
 
308
 
 
309
  EXPECT_TRUE(foo_file_->FindServiceByName("NoSuchService") == NULL);
 
310
  EXPECT_TRUE(foo_file_->FindServiceByName("FooMessage") == NULL);
 
311
}
 
312
 
 
313
TEST_F(FileDescriptorTest, FindExtensionByName) {
 
314
  EXPECT_EQ(foo_extension_, foo_file_->FindExtensionByName("foo_extension"));
 
315
  EXPECT_EQ(bar_extension_, bar_file_->FindExtensionByName("bar_extension"));
 
316
 
 
317
  EXPECT_TRUE(foo_file_->FindExtensionByName("bar_extension") == NULL);
 
318
  EXPECT_TRUE(bar_file_->FindExtensionByName("foo_extension") == NULL);
 
319
  EXPECT_TRUE(baz_file_->FindExtensionByName("foo_extension") == NULL);
 
320
 
 
321
  EXPECT_TRUE(foo_file_->FindExtensionByName("no_such_extension") == NULL);
 
322
  EXPECT_TRUE(foo_file_->FindExtensionByName("FooMessage") == NULL);
 
323
}
 
324
 
 
325
TEST_F(FileDescriptorTest, FindExtensionByNumber) {
 
326
  EXPECT_EQ(foo_extension_, pool_.FindExtensionByNumber(foo_message_, 1));
 
327
  EXPECT_EQ(bar_extension_, pool_.FindExtensionByNumber(bar_message_, 1));
 
328
 
 
329
  EXPECT_TRUE(pool_.FindExtensionByNumber(foo_message_, 2) == NULL);
 
330
}
 
331
 
 
332
// ===================================================================
 
333
 
 
334
// Test simple flat messages and fields.
 
335
class DescriptorTest : public testing::Test {
 
336
 protected:
 
337
  virtual void SetUp() {
 
338
    // Build descriptors for the following definitions:
 
339
    //
 
340
    //   // in "foo.proto"
 
341
    //   message TestForeign {}
 
342
    //   enum TestEnum {}
 
343
    //
 
344
    //   message TestMessage {
 
345
    //     required string      foo = 1;
 
346
    //     optional TestEnum    bar = 6;
 
347
    //     repeated TestForeign baz = 500000000;
 
348
    //     optional group       qux = 15 {}
 
349
    //   }
 
350
    //
 
351
    //   // in "bar.proto"
 
352
    //   package corge.grault;
 
353
    //   message TestMessage2 {
 
354
    //     required string foo = 1;
 
355
    //     required string bar = 2;
 
356
    //     required string quux = 6;
 
357
    //   }
 
358
    //
 
359
    // We cheat and use TestForeign as the type for qux rather than create
 
360
    // an actual nested type.
 
361
    //
 
362
    // Since all primitive types (including string) use the same building
 
363
    // code, there's no need to test each one individually.
 
364
    //
 
365
    // TestMessage2 is primarily here to test FindFieldByName and friends.
 
366
    // All messages created from the same DescriptorPool share the same lookup
 
367
    // table, so we need to insure that they don't interfere.
 
368
 
 
369
    FileDescriptorProto foo_file;
 
370
    foo_file.set_name("foo.proto");
 
371
    AddMessage(&foo_file, "TestForeign");
 
372
    AddEmptyEnum(&foo_file, "TestEnum");
 
373
 
 
374
    DescriptorProto* message = AddMessage(&foo_file, "TestMessage");
 
375
    AddField(message, "foo", 1,
 
376
             FieldDescriptorProto::LABEL_REQUIRED,
 
377
             FieldDescriptorProto::TYPE_STRING);
 
378
    AddField(message, "bar", 6,
 
379
             FieldDescriptorProto::LABEL_OPTIONAL,
 
380
             FieldDescriptorProto::TYPE_ENUM)
 
381
      ->set_type_name("TestEnum");
 
382
    AddField(message, "baz", 500000000,
 
383
             FieldDescriptorProto::LABEL_REPEATED,
 
384
             FieldDescriptorProto::TYPE_MESSAGE)
 
385
      ->set_type_name("TestForeign");
 
386
    AddField(message, "qux", 15,
 
387
             FieldDescriptorProto::LABEL_OPTIONAL,
 
388
             FieldDescriptorProto::TYPE_GROUP)
 
389
      ->set_type_name("TestForeign");
 
390
 
 
391
    FileDescriptorProto bar_file;
 
392
    bar_file.set_name("bar.proto");
 
393
    bar_file.set_package("corge.grault");
 
394
 
 
395
    DescriptorProto* message2 = AddMessage(&bar_file, "TestMessage2");
 
396
    AddField(message2, "foo", 1,
 
397
             FieldDescriptorProto::LABEL_REQUIRED,
 
398
             FieldDescriptorProto::TYPE_STRING);
 
399
    AddField(message2, "bar", 2,
 
400
             FieldDescriptorProto::LABEL_REQUIRED,
 
401
             FieldDescriptorProto::TYPE_STRING);
 
402
    AddField(message2, "quux", 6,
 
403
             FieldDescriptorProto::LABEL_REQUIRED,
 
404
             FieldDescriptorProto::TYPE_STRING);
 
405
 
 
406
    // Build the descriptors and get the pointers.
 
407
    foo_file_ = pool_.BuildFile(foo_file);
 
408
    ASSERT_TRUE(foo_file_ != NULL);
 
409
 
 
410
    bar_file_ = pool_.BuildFile(bar_file);
 
411
    ASSERT_TRUE(bar_file_ != NULL);
 
412
 
 
413
    ASSERT_EQ(1, foo_file_->enum_type_count());
 
414
    enum_ = foo_file_->enum_type(0);
 
415
 
 
416
    ASSERT_EQ(2, foo_file_->message_type_count());
 
417
    foreign_ = foo_file_->message_type(0);
 
418
    message_ = foo_file_->message_type(1);
 
419
 
 
420
    ASSERT_EQ(4, message_->field_count());
 
421
    foo_ = message_->field(0);
 
422
    bar_ = message_->field(1);
 
423
    baz_ = message_->field(2);
 
424
    qux_ = message_->field(3);
 
425
 
 
426
    ASSERT_EQ(1, bar_file_->message_type_count());
 
427
    message2_ = bar_file_->message_type(0);
 
428
 
 
429
    ASSERT_EQ(3, message2_->field_count());
 
430
    foo2_  = message2_->field(0);
 
431
    bar2_  = message2_->field(1);
 
432
    quux2_ = message2_->field(2);
 
433
  }
 
434
 
 
435
  DescriptorPool pool_;
 
436
 
 
437
  const FileDescriptor* foo_file_;
 
438
  const FileDescriptor* bar_file_;
 
439
 
 
440
  const Descriptor* message_;
 
441
  const Descriptor* message2_;
 
442
  const Descriptor* foreign_;
 
443
  const EnumDescriptor* enum_;
 
444
 
 
445
  const FieldDescriptor* foo_;
 
446
  const FieldDescriptor* bar_;
 
447
  const FieldDescriptor* baz_;
 
448
  const FieldDescriptor* qux_;
 
449
 
 
450
  const FieldDescriptor* foo2_;
 
451
  const FieldDescriptor* bar2_;
 
452
  const FieldDescriptor* quux2_;
 
453
};
 
454
 
 
455
TEST_F(DescriptorTest, Name) {
 
456
  EXPECT_EQ("TestMessage", message_->name());
 
457
  EXPECT_EQ("TestMessage", message_->full_name());
 
458
  EXPECT_EQ(foo_file_, message_->file());
 
459
 
 
460
  EXPECT_EQ("TestMessage2", message2_->name());
 
461
  EXPECT_EQ("corge.grault.TestMessage2", message2_->full_name());
 
462
  EXPECT_EQ(bar_file_, message2_->file());
 
463
}
 
464
 
 
465
TEST_F(DescriptorTest, ContainingType) {
 
466
  EXPECT_TRUE(message_->containing_type() == NULL);
 
467
  EXPECT_TRUE(message2_->containing_type() == NULL);
 
468
}
 
469
 
 
470
TEST_F(DescriptorTest, FieldsByIndex) {
 
471
  ASSERT_EQ(4, message_->field_count());
 
472
  EXPECT_EQ(foo_, message_->field(0));
 
473
  EXPECT_EQ(bar_, message_->field(1));
 
474
  EXPECT_EQ(baz_, message_->field(2));
 
475
  EXPECT_EQ(qux_, message_->field(3));
 
476
}
 
477
 
 
478
TEST_F(DescriptorTest, FindFieldByName) {
 
479
  // All messages in the same DescriptorPool share a single lookup table for
 
480
  // fields.  So, in addition to testing that FindFieldByName finds the fields
 
481
  // of the message, we need to test that it does *not* find the fields of
 
482
  // *other* messages.
 
483
 
 
484
  EXPECT_EQ(foo_, message_->FindFieldByName("foo"));
 
485
  EXPECT_EQ(bar_, message_->FindFieldByName("bar"));
 
486
  EXPECT_EQ(baz_, message_->FindFieldByName("baz"));
 
487
  EXPECT_EQ(qux_, message_->FindFieldByName("qux"));
 
488
  EXPECT_TRUE(message_->FindFieldByName("no_such_field") == NULL);
 
489
  EXPECT_TRUE(message_->FindFieldByName("quux") == NULL);
 
490
 
 
491
  EXPECT_EQ(foo2_ , message2_->FindFieldByName("foo" ));
 
492
  EXPECT_EQ(bar2_ , message2_->FindFieldByName("bar" ));
 
493
  EXPECT_EQ(quux2_, message2_->FindFieldByName("quux"));
 
494
  EXPECT_TRUE(message2_->FindFieldByName("baz") == NULL);
 
495
  EXPECT_TRUE(message2_->FindFieldByName("qux") == NULL);
 
496
}
 
497
 
 
498
TEST_F(DescriptorTest, FindFieldByNumber) {
 
499
  EXPECT_EQ(foo_, message_->FindFieldByNumber(1));
 
500
  EXPECT_EQ(bar_, message_->FindFieldByNumber(6));
 
501
  EXPECT_EQ(baz_, message_->FindFieldByNumber(500000000));
 
502
  EXPECT_EQ(qux_, message_->FindFieldByNumber(15));
 
503
  EXPECT_TRUE(message_->FindFieldByNumber(837592) == NULL);
 
504
  EXPECT_TRUE(message_->FindFieldByNumber(2) == NULL);
 
505
 
 
506
  EXPECT_EQ(foo2_ , message2_->FindFieldByNumber(1));
 
507
  EXPECT_EQ(bar2_ , message2_->FindFieldByNumber(2));
 
508
  EXPECT_EQ(quux2_, message2_->FindFieldByNumber(6));
 
509
  EXPECT_TRUE(message2_->FindFieldByNumber(15) == NULL);
 
510
  EXPECT_TRUE(message2_->FindFieldByNumber(500000000) == NULL);
 
511
}
 
512
 
 
513
TEST_F(DescriptorTest, FieldName) {
 
514
  EXPECT_EQ("foo", foo_->name());
 
515
  EXPECT_EQ("bar", bar_->name());
 
516
  EXPECT_EQ("baz", baz_->name());
 
517
  EXPECT_EQ("qux", qux_->name());
 
518
}
 
519
 
 
520
TEST_F(DescriptorTest, FieldFullName) {
 
521
  EXPECT_EQ("TestMessage.foo", foo_->full_name());
 
522
  EXPECT_EQ("TestMessage.bar", bar_->full_name());
 
523
  EXPECT_EQ("TestMessage.baz", baz_->full_name());
 
524
  EXPECT_EQ("TestMessage.qux", qux_->full_name());
 
525
 
 
526
  EXPECT_EQ("corge.grault.TestMessage2.foo", foo2_->full_name());
 
527
  EXPECT_EQ("corge.grault.TestMessage2.bar", bar2_->full_name());
 
528
  EXPECT_EQ("corge.grault.TestMessage2.quux", quux2_->full_name());
 
529
}
 
530
 
 
531
TEST_F(DescriptorTest, FieldFile) {
 
532
  EXPECT_EQ(foo_file_, foo_->file());
 
533
  EXPECT_EQ(foo_file_, bar_->file());
 
534
  EXPECT_EQ(foo_file_, baz_->file());
 
535
  EXPECT_EQ(foo_file_, qux_->file());
 
536
 
 
537
  EXPECT_EQ(bar_file_, foo2_->file());
 
538
  EXPECT_EQ(bar_file_, bar2_->file());
 
539
  EXPECT_EQ(bar_file_, quux2_->file());
 
540
}
 
541
 
 
542
TEST_F(DescriptorTest, FieldIndex) {
 
543
  EXPECT_EQ(0, foo_->index());
 
544
  EXPECT_EQ(1, bar_->index());
 
545
  EXPECT_EQ(2, baz_->index());
 
546
  EXPECT_EQ(3, qux_->index());
 
547
}
 
548
 
 
549
TEST_F(DescriptorTest, FieldNumber) {
 
550
  EXPECT_EQ(        1, foo_->number());
 
551
  EXPECT_EQ(        6, bar_->number());
 
552
  EXPECT_EQ(500000000, baz_->number());
 
553
  EXPECT_EQ(       15, qux_->number());
 
554
}
 
555
 
 
556
TEST_F(DescriptorTest, FieldType) {
 
557
  EXPECT_EQ(FieldDescriptor::TYPE_STRING , foo_->type());
 
558
  EXPECT_EQ(FieldDescriptor::TYPE_ENUM   , bar_->type());
 
559
  EXPECT_EQ(FieldDescriptor::TYPE_MESSAGE, baz_->type());
 
560
  EXPECT_EQ(FieldDescriptor::TYPE_GROUP  , qux_->type());
 
561
}
 
562
 
 
563
TEST_F(DescriptorTest, FieldLabel) {
 
564
  EXPECT_EQ(FieldDescriptor::LABEL_REQUIRED, foo_->label());
 
565
  EXPECT_EQ(FieldDescriptor::LABEL_OPTIONAL, bar_->label());
 
566
  EXPECT_EQ(FieldDescriptor::LABEL_REPEATED, baz_->label());
 
567
  EXPECT_EQ(FieldDescriptor::LABEL_OPTIONAL, qux_->label());
 
568
 
 
569
  EXPECT_TRUE (foo_->is_required());
 
570
  EXPECT_FALSE(foo_->is_optional());
 
571
  EXPECT_FALSE(foo_->is_repeated());
 
572
 
 
573
  EXPECT_FALSE(bar_->is_required());
 
574
  EXPECT_TRUE (bar_->is_optional());
 
575
  EXPECT_FALSE(bar_->is_repeated());
 
576
 
 
577
  EXPECT_FALSE(baz_->is_required());
 
578
  EXPECT_FALSE(baz_->is_optional());
 
579
  EXPECT_TRUE (baz_->is_repeated());
 
580
}
 
581
 
 
582
TEST_F(DescriptorTest, FieldHasDefault) {
 
583
  EXPECT_FALSE(foo_->has_default_value());
 
584
  EXPECT_FALSE(bar_->has_default_value());
 
585
  EXPECT_FALSE(baz_->has_default_value());
 
586
  EXPECT_FALSE(qux_->has_default_value());
 
587
}
 
588
 
 
589
TEST_F(DescriptorTest, FieldContainingType) {
 
590
  EXPECT_EQ(message_, foo_->containing_type());
 
591
  EXPECT_EQ(message_, bar_->containing_type());
 
592
  EXPECT_EQ(message_, baz_->containing_type());
 
593
  EXPECT_EQ(message_, qux_->containing_type());
 
594
 
 
595
  EXPECT_EQ(message2_, foo2_ ->containing_type());
 
596
  EXPECT_EQ(message2_, bar2_ ->containing_type());
 
597
  EXPECT_EQ(message2_, quux2_->containing_type());
 
598
}
 
599
 
 
600
TEST_F(DescriptorTest, FieldMessageType) {
 
601
  EXPECT_TRUE(foo_->message_type() == NULL);
 
602
  EXPECT_TRUE(bar_->message_type() == NULL);
 
603
 
 
604
  EXPECT_EQ(foreign_, baz_->message_type());
 
605
  EXPECT_EQ(foreign_, qux_->message_type());
 
606
}
 
607
 
 
608
TEST_F(DescriptorTest, FieldEnumType) {
 
609
  EXPECT_TRUE(foo_->enum_type() == NULL);
 
610
  EXPECT_TRUE(baz_->enum_type() == NULL);
 
611
  EXPECT_TRUE(qux_->enum_type() == NULL);
 
612
 
 
613
  EXPECT_EQ(enum_, bar_->enum_type());
 
614
}
 
615
 
 
616
// ===================================================================
 
617
 
 
618
// Test enum descriptors.
 
619
class EnumDescriptorTest : public testing::Test {
 
620
 protected:
 
621
  virtual void SetUp() {
 
622
    // Build descriptors for the following definitions:
 
623
    //
 
624
    //   // in "foo.proto"
 
625
    //   enum TestEnum {
 
626
    //     FOO = 1;
 
627
    //     BAR = 2;
 
628
    //   }
 
629
    //
 
630
    //   // in "bar.proto"
 
631
    //   package corge.grault;
 
632
    //   enum TestEnum2 {
 
633
    //     FOO = 1;
 
634
    //     BAZ = 3;
 
635
    //   }
 
636
    //
 
637
    // TestEnum2 is primarily here to test FindValueByName and friends.
 
638
    // All enums created from the same DescriptorPool share the same lookup
 
639
    // table, so we need to insure that they don't interfere.
 
640
 
 
641
    // TestEnum
 
642
    FileDescriptorProto foo_file;
 
643
    foo_file.set_name("foo.proto");
 
644
 
 
645
    EnumDescriptorProto* enum_proto = AddEnum(&foo_file, "TestEnum");
 
646
    AddEnumValue(enum_proto, "FOO", 1);
 
647
    AddEnumValue(enum_proto, "BAR", 2);
 
648
 
 
649
    // TestEnum2
 
650
    FileDescriptorProto bar_file;
 
651
    bar_file.set_name("bar.proto");
 
652
    bar_file.set_package("corge.grault");
 
653
 
 
654
    EnumDescriptorProto* enum2_proto = AddEnum(&bar_file, "TestEnum2");
 
655
    AddEnumValue(enum2_proto, "FOO", 1);
 
656
    AddEnumValue(enum2_proto, "BAZ", 3);
 
657
 
 
658
    // Build the descriptors and get the pointers.
 
659
    foo_file_ = pool_.BuildFile(foo_file);
 
660
    ASSERT_TRUE(foo_file_ != NULL);
 
661
 
 
662
    bar_file_ = pool_.BuildFile(bar_file);
 
663
    ASSERT_TRUE(bar_file_ != NULL);
 
664
 
 
665
    ASSERT_EQ(1, foo_file_->enum_type_count());
 
666
    enum_ = foo_file_->enum_type(0);
 
667
 
 
668
    ASSERT_EQ(2, enum_->value_count());
 
669
    foo_ = enum_->value(0);
 
670
    bar_ = enum_->value(1);
 
671
 
 
672
    ASSERT_EQ(1, bar_file_->enum_type_count());
 
673
    enum2_ = bar_file_->enum_type(0);
 
674
 
 
675
    ASSERT_EQ(2, enum2_->value_count());
 
676
    foo2_ = enum2_->value(0);
 
677
    baz2_ = enum2_->value(1);
 
678
  }
 
679
 
 
680
  DescriptorPool pool_;
 
681
 
 
682
  const FileDescriptor* foo_file_;
 
683
  const FileDescriptor* bar_file_;
 
684
 
 
685
  const EnumDescriptor* enum_;
 
686
  const EnumDescriptor* enum2_;
 
687
 
 
688
  const EnumValueDescriptor* foo_;
 
689
  const EnumValueDescriptor* bar_;
 
690
 
 
691
  const EnumValueDescriptor* foo2_;
 
692
  const EnumValueDescriptor* baz2_;
 
693
};
 
694
 
 
695
TEST_F(EnumDescriptorTest, Name) {
 
696
  EXPECT_EQ("TestEnum", enum_->name());
 
697
  EXPECT_EQ("TestEnum", enum_->full_name());
 
698
  EXPECT_EQ(foo_file_, enum_->file());
 
699
 
 
700
  EXPECT_EQ("TestEnum2", enum2_->name());
 
701
  EXPECT_EQ("corge.grault.TestEnum2", enum2_->full_name());
 
702
  EXPECT_EQ(bar_file_, enum2_->file());
 
703
}
 
704
 
 
705
TEST_F(EnumDescriptorTest, ContainingType) {
 
706
  EXPECT_TRUE(enum_->containing_type() == NULL);
 
707
  EXPECT_TRUE(enum2_->containing_type() == NULL);
 
708
}
 
709
 
 
710
TEST_F(EnumDescriptorTest, ValuesByIndex) {
 
711
  ASSERT_EQ(2, enum_->value_count());
 
712
  EXPECT_EQ(foo_, enum_->value(0));
 
713
  EXPECT_EQ(bar_, enum_->value(1));
 
714
}
 
715
 
 
716
TEST_F(EnumDescriptorTest, FindValueByName) {
 
717
  EXPECT_EQ(foo_ , enum_ ->FindValueByName("FOO"));
 
718
  EXPECT_EQ(bar_ , enum_ ->FindValueByName("BAR"));
 
719
  EXPECT_EQ(foo2_, enum2_->FindValueByName("FOO"));
 
720
  EXPECT_EQ(baz2_, enum2_->FindValueByName("BAZ"));
 
721
 
 
722
  EXPECT_TRUE(enum_ ->FindValueByName("NO_SUCH_VALUE") == NULL);
 
723
  EXPECT_TRUE(enum_ ->FindValueByName("BAZ"          ) == NULL);
 
724
  EXPECT_TRUE(enum2_->FindValueByName("BAR"          ) == NULL);
 
725
}
 
726
 
 
727
TEST_F(EnumDescriptorTest, FindValueByNumber) {
 
728
  EXPECT_EQ(foo_ , enum_ ->FindValueByNumber(1));
 
729
  EXPECT_EQ(bar_ , enum_ ->FindValueByNumber(2));
 
730
  EXPECT_EQ(foo2_, enum2_->FindValueByNumber(1));
 
731
  EXPECT_EQ(baz2_, enum2_->FindValueByNumber(3));
 
732
 
 
733
  EXPECT_TRUE(enum_ ->FindValueByNumber(416) == NULL);
 
734
  EXPECT_TRUE(enum_ ->FindValueByNumber(3) == NULL);
 
735
  EXPECT_TRUE(enum2_->FindValueByNumber(2) == NULL);
 
736
}
 
737
 
 
738
TEST_F(EnumDescriptorTest, ValueName) {
 
739
  EXPECT_EQ("FOO", foo_->name());
 
740
  EXPECT_EQ("BAR", bar_->name());
 
741
}
 
742
 
 
743
TEST_F(EnumDescriptorTest, ValueFullName) {
 
744
  EXPECT_EQ("FOO", foo_->full_name());
 
745
  EXPECT_EQ("BAR", bar_->full_name());
 
746
  EXPECT_EQ("corge.grault.FOO", foo2_->full_name());
 
747
  EXPECT_EQ("corge.grault.BAZ", baz2_->full_name());
 
748
}
 
749
 
 
750
TEST_F(EnumDescriptorTest, ValueIndex) {
 
751
  EXPECT_EQ(0, foo_->index());
 
752
  EXPECT_EQ(1, bar_->index());
 
753
}
 
754
 
 
755
TEST_F(EnumDescriptorTest, ValueNumber) {
 
756
  EXPECT_EQ(1, foo_->number());
 
757
  EXPECT_EQ(2, bar_->number());
 
758
}
 
759
 
 
760
TEST_F(EnumDescriptorTest, ValueType) {
 
761
  EXPECT_EQ(enum_ , foo_ ->type());
 
762
  EXPECT_EQ(enum_ , bar_ ->type());
 
763
  EXPECT_EQ(enum2_, foo2_->type());
 
764
  EXPECT_EQ(enum2_, baz2_->type());
 
765
}
 
766
 
 
767
// ===================================================================
 
768
 
 
769
// Test service descriptors.
 
770
class ServiceDescriptorTest : public testing::Test {
 
771
 protected:
 
772
  virtual void SetUp() {
 
773
    // Build descriptors for the following messages and service:
 
774
    //    // in "foo.proto"
 
775
    //    message FooRequest  {}
 
776
    //    message FooResponse {}
 
777
    //    message BarRequest  {}
 
778
    //    message BarResponse {}
 
779
    //    message BazRequest  {}
 
780
    //    message BazResponse {}
 
781
    //
 
782
    //    service TestService {
 
783
    //      rpc Foo(FooRequest) returns (FooResponse);
 
784
    //      rpc Bar(BarRequest) returns (BarResponse);
 
785
    //    }
 
786
    //
 
787
    //    // in "bar.proto"
 
788
    //    package corge.grault
 
789
    //    service TestService2 {
 
790
    //      rpc Foo(FooRequest) returns (FooResponse);
 
791
    //      rpc Baz(BazRequest) returns (BazResponse);
 
792
    //    }
 
793
 
 
794
    FileDescriptorProto foo_file;
 
795
    foo_file.set_name("foo.proto");
 
796
 
 
797
    AddMessage(&foo_file, "FooRequest");
 
798
    AddMessage(&foo_file, "FooResponse");
 
799
    AddMessage(&foo_file, "BarRequest");
 
800
    AddMessage(&foo_file, "BarResponse");
 
801
    AddMessage(&foo_file, "BazRequest");
 
802
    AddMessage(&foo_file, "BazResponse");
 
803
 
 
804
    ServiceDescriptorProto* service = AddService(&foo_file, "TestService");
 
805
    AddMethod(service, "Foo", "FooRequest", "FooResponse");
 
806
    AddMethod(service, "Bar", "BarRequest", "BarResponse");
 
807
 
 
808
    FileDescriptorProto bar_file;
 
809
    bar_file.set_name("bar.proto");
 
810
    bar_file.set_package("corge.grault");
 
811
    bar_file.add_dependency("foo.proto");
 
812
 
 
813
    ServiceDescriptorProto* service2 = AddService(&bar_file, "TestService2");
 
814
    AddMethod(service2, "Foo", "FooRequest", "FooResponse");
 
815
    AddMethod(service2, "Baz", "BazRequest", "BazResponse");
 
816
 
 
817
    // Build the descriptors and get the pointers.
 
818
    foo_file_ = pool_.BuildFile(foo_file);
 
819
    ASSERT_TRUE(foo_file_ != NULL);
 
820
 
 
821
    bar_file_ = pool_.BuildFile(bar_file);
 
822
    ASSERT_TRUE(bar_file_ != NULL);
 
823
 
 
824
    ASSERT_EQ(6, foo_file_->message_type_count());
 
825
    foo_request_  = foo_file_->message_type(0);
 
826
    foo_response_ = foo_file_->message_type(1);
 
827
    bar_request_  = foo_file_->message_type(2);
 
828
    bar_response_ = foo_file_->message_type(3);
 
829
    baz_request_  = foo_file_->message_type(4);
 
830
    baz_response_ = foo_file_->message_type(5);
 
831
 
 
832
    ASSERT_EQ(1, foo_file_->service_count());
 
833
    service_ = foo_file_->service(0);
 
834
 
 
835
    ASSERT_EQ(2, service_->method_count());
 
836
    foo_ = service_->method(0);
 
837
    bar_ = service_->method(1);
 
838
 
 
839
    ASSERT_EQ(1, bar_file_->service_count());
 
840
    service2_ = bar_file_->service(0);
 
841
 
 
842
    ASSERT_EQ(2, service2_->method_count());
 
843
    foo2_ = service2_->method(0);
 
844
    baz2_ = service2_->method(1);
 
845
  }
 
846
 
 
847
  DescriptorPool pool_;
 
848
 
 
849
  const FileDescriptor* foo_file_;
 
850
  const FileDescriptor* bar_file_;
 
851
 
 
852
  const Descriptor* foo_request_;
 
853
  const Descriptor* foo_response_;
 
854
  const Descriptor* bar_request_;
 
855
  const Descriptor* bar_response_;
 
856
  const Descriptor* baz_request_;
 
857
  const Descriptor* baz_response_;
 
858
 
 
859
  const ServiceDescriptor* service_;
 
860
  const ServiceDescriptor* service2_;
 
861
 
 
862
  const MethodDescriptor* foo_;
 
863
  const MethodDescriptor* bar_;
 
864
 
 
865
  const MethodDescriptor* foo2_;
 
866
  const MethodDescriptor* baz2_;
 
867
};
 
868
 
 
869
TEST_F(ServiceDescriptorTest, Name) {
 
870
  EXPECT_EQ("TestService", service_->name());
 
871
  EXPECT_EQ("TestService", service_->full_name());
 
872
  EXPECT_EQ(foo_file_, service_->file());
 
873
 
 
874
  EXPECT_EQ("TestService2", service2_->name());
 
875
  EXPECT_EQ("corge.grault.TestService2", service2_->full_name());
 
876
  EXPECT_EQ(bar_file_, service2_->file());
 
877
}
 
878
 
 
879
TEST_F(ServiceDescriptorTest, MethodsByIndex) {
 
880
  ASSERT_EQ(2, service_->method_count());
 
881
  EXPECT_EQ(foo_, service_->method(0));
 
882
  EXPECT_EQ(bar_, service_->method(1));
 
883
}
 
884
 
 
885
TEST_F(ServiceDescriptorTest, FindMethodByName) {
 
886
  EXPECT_EQ(foo_ , service_ ->FindMethodByName("Foo"));
 
887
  EXPECT_EQ(bar_ , service_ ->FindMethodByName("Bar"));
 
888
  EXPECT_EQ(foo2_, service2_->FindMethodByName("Foo"));
 
889
  EXPECT_EQ(baz2_, service2_->FindMethodByName("Baz"));
 
890
 
 
891
  EXPECT_TRUE(service_ ->FindMethodByName("NoSuchMethod") == NULL);
 
892
  EXPECT_TRUE(service_ ->FindMethodByName("Baz"         ) == NULL);
 
893
  EXPECT_TRUE(service2_->FindMethodByName("Bar"         ) == NULL);
 
894
}
 
895
 
 
896
TEST_F(ServiceDescriptorTest, MethodName) {
 
897
  EXPECT_EQ("Foo", foo_->name());
 
898
  EXPECT_EQ("Bar", bar_->name());
 
899
}
 
900
 
 
901
TEST_F(ServiceDescriptorTest, MethodFullName) {
 
902
  EXPECT_EQ("TestService.Foo", foo_->full_name());
 
903
  EXPECT_EQ("TestService.Bar", bar_->full_name());
 
904
  EXPECT_EQ("corge.grault.TestService2.Foo", foo2_->full_name());
 
905
  EXPECT_EQ("corge.grault.TestService2.Baz", baz2_->full_name());
 
906
}
 
907
 
 
908
TEST_F(ServiceDescriptorTest, MethodIndex) {
 
909
  EXPECT_EQ(0, foo_->index());
 
910
  EXPECT_EQ(1, bar_->index());
 
911
}
 
912
 
 
913
TEST_F(ServiceDescriptorTest, MethodParent) {
 
914
  EXPECT_EQ(service_, foo_->service());
 
915
  EXPECT_EQ(service_, bar_->service());
 
916
}
 
917
 
 
918
TEST_F(ServiceDescriptorTest, MethodInputType) {
 
919
  EXPECT_EQ(foo_request_, foo_->input_type());
 
920
  EXPECT_EQ(bar_request_, bar_->input_type());
 
921
}
 
922
 
 
923
TEST_F(ServiceDescriptorTest, MethodOutputType) {
 
924
  EXPECT_EQ(foo_response_, foo_->output_type());
 
925
  EXPECT_EQ(bar_response_, bar_->output_type());
 
926
}
 
927
 
 
928
// ===================================================================
 
929
 
 
930
// Test nested types.
 
931
class NestedDescriptorTest : public testing::Test {
 
932
 protected:
 
933
  virtual void SetUp() {
 
934
    // Build descriptors for the following definitions:
 
935
    //
 
936
    //   // in "foo.proto"
 
937
    //   message TestMessage {
 
938
    //     message Foo {}
 
939
    //     message Bar {}
 
940
    //     enum Baz { A = 1; }
 
941
    //     enum Qux { B = 1; }
 
942
    //   }
 
943
    //
 
944
    //   // in "bar.proto"
 
945
    //   package corge.grault;
 
946
    //   message TestMessage2 {
 
947
    //     message Foo {}
 
948
    //     message Baz {}
 
949
    //     enum Qux  { A = 1; }
 
950
    //     enum Quux { C = 1; }
 
951
    //   }
 
952
    //
 
953
    // TestMessage2 is primarily here to test FindNestedTypeByName and friends.
 
954
    // All messages created from the same DescriptorPool share the same lookup
 
955
    // table, so we need to insure that they don't interfere.
 
956
    //
 
957
    // We add enum values to the enums in order to test searching for enum
 
958
    // values across a message's scope.
 
959
 
 
960
    FileDescriptorProto foo_file;
 
961
    foo_file.set_name("foo.proto");
 
962
 
 
963
    DescriptorProto* message = AddMessage(&foo_file, "TestMessage");
 
964
    AddNestedMessage(message, "Foo");
 
965
    AddNestedMessage(message, "Bar");
 
966
    EnumDescriptorProto* baz = AddNestedEnum(message, "Baz");
 
967
    AddEnumValue(baz, "A", 1);
 
968
    EnumDescriptorProto* qux = AddNestedEnum(message, "Qux");
 
969
    AddEnumValue(qux, "B", 1);
 
970
 
 
971
    FileDescriptorProto bar_file;
 
972
    bar_file.set_name("bar.proto");
 
973
    bar_file.set_package("corge.grault");
 
974
 
 
975
    DescriptorProto* message2 = AddMessage(&bar_file, "TestMessage2");
 
976
    AddNestedMessage(message2, "Foo");
 
977
    AddNestedMessage(message2, "Baz");
 
978
    EnumDescriptorProto* qux2 = AddNestedEnum(message2, "Qux");
 
979
    AddEnumValue(qux2, "A", 1);
 
980
    EnumDescriptorProto* quux2 = AddNestedEnum(message2, "Quux");
 
981
    AddEnumValue(quux2, "C", 1);
 
982
 
 
983
    // Build the descriptors and get the pointers.
 
984
    foo_file_ = pool_.BuildFile(foo_file);
 
985
    ASSERT_TRUE(foo_file_ != NULL);
 
986
 
 
987
    bar_file_ = pool_.BuildFile(bar_file);
 
988
    ASSERT_TRUE(bar_file_ != NULL);
 
989
 
 
990
    ASSERT_EQ(1, foo_file_->message_type_count());
 
991
    message_ = foo_file_->message_type(0);
 
992
 
 
993
    ASSERT_EQ(2, message_->nested_type_count());
 
994
    foo_ = message_->nested_type(0);
 
995
    bar_ = message_->nested_type(1);
 
996
 
 
997
    ASSERT_EQ(2, message_->enum_type_count());
 
998
    baz_ = message_->enum_type(0);
 
999
    qux_ = message_->enum_type(1);
 
1000
 
 
1001
    ASSERT_EQ(1, baz_->value_count());
 
1002
    a_ = baz_->value(0);
 
1003
    ASSERT_EQ(1, qux_->value_count());
 
1004
    b_ = qux_->value(0);
 
1005
 
 
1006
    ASSERT_EQ(1, bar_file_->message_type_count());
 
1007
    message2_ = bar_file_->message_type(0);
 
1008
 
 
1009
    ASSERT_EQ(2, message2_->nested_type_count());
 
1010
    foo2_ = message2_->nested_type(0);
 
1011
    baz2_ = message2_->nested_type(1);
 
1012
 
 
1013
    ASSERT_EQ(2, message2_->enum_type_count());
 
1014
    qux2_ = message2_->enum_type(0);
 
1015
    quux2_ = message2_->enum_type(1);
 
1016
 
 
1017
    ASSERT_EQ(1, qux2_->value_count());
 
1018
    a2_ = qux2_->value(0);
 
1019
    ASSERT_EQ(1, quux2_->value_count());
 
1020
    c2_ = quux2_->value(0);
 
1021
  }
 
1022
 
 
1023
  DescriptorPool pool_;
 
1024
 
 
1025
  const FileDescriptor* foo_file_;
 
1026
  const FileDescriptor* bar_file_;
 
1027
 
 
1028
  const Descriptor* message_;
 
1029
  const Descriptor* message2_;
 
1030
 
 
1031
  const Descriptor* foo_;
 
1032
  const Descriptor* bar_;
 
1033
  const EnumDescriptor* baz_;
 
1034
  const EnumDescriptor* qux_;
 
1035
  const EnumValueDescriptor* a_;
 
1036
  const EnumValueDescriptor* b_;
 
1037
 
 
1038
  const Descriptor* foo2_;
 
1039
  const Descriptor* baz2_;
 
1040
  const EnumDescriptor* qux2_;
 
1041
  const EnumDescriptor* quux2_;
 
1042
  const EnumValueDescriptor* a2_;
 
1043
  const EnumValueDescriptor* c2_;
 
1044
};
 
1045
 
 
1046
TEST_F(NestedDescriptorTest, MessageName) {
 
1047
  EXPECT_EQ("Foo", foo_ ->name());
 
1048
  EXPECT_EQ("Bar", bar_ ->name());
 
1049
  EXPECT_EQ("Foo", foo2_->name());
 
1050
  EXPECT_EQ("Baz", baz2_->name());
 
1051
 
 
1052
  EXPECT_EQ("TestMessage.Foo", foo_->full_name());
 
1053
  EXPECT_EQ("TestMessage.Bar", bar_->full_name());
 
1054
  EXPECT_EQ("corge.grault.TestMessage2.Foo", foo2_->full_name());
 
1055
  EXPECT_EQ("corge.grault.TestMessage2.Baz", baz2_->full_name());
 
1056
}
 
1057
 
 
1058
TEST_F(NestedDescriptorTest, MessageContainingType) {
 
1059
  EXPECT_EQ(message_ , foo_ ->containing_type());
 
1060
  EXPECT_EQ(message_ , bar_ ->containing_type());
 
1061
  EXPECT_EQ(message2_, foo2_->containing_type());
 
1062
  EXPECT_EQ(message2_, baz2_->containing_type());
 
1063
}
 
1064
 
 
1065
TEST_F(NestedDescriptorTest, NestedMessagesByIndex) {
 
1066
  ASSERT_EQ(2, message_->nested_type_count());
 
1067
  EXPECT_EQ(foo_, message_->nested_type(0));
 
1068
  EXPECT_EQ(bar_, message_->nested_type(1));
 
1069
}
 
1070
 
 
1071
TEST_F(NestedDescriptorTest, FindFieldByNameDoesntFindNestedTypes) {
 
1072
  EXPECT_TRUE(message_->FindFieldByName("Foo") == NULL);
 
1073
  EXPECT_TRUE(message_->FindFieldByName("Qux") == NULL);
 
1074
  EXPECT_TRUE(message_->FindExtensionByName("Foo") == NULL);
 
1075
  EXPECT_TRUE(message_->FindExtensionByName("Qux") == NULL);
 
1076
}
 
1077
 
 
1078
TEST_F(NestedDescriptorTest, FindNestedTypeByName) {
 
1079
  EXPECT_EQ(foo_ , message_ ->FindNestedTypeByName("Foo"));
 
1080
  EXPECT_EQ(bar_ , message_ ->FindNestedTypeByName("Bar"));
 
1081
  EXPECT_EQ(foo2_, message2_->FindNestedTypeByName("Foo"));
 
1082
  EXPECT_EQ(baz2_, message2_->FindNestedTypeByName("Baz"));
 
1083
 
 
1084
  EXPECT_TRUE(message_ ->FindNestedTypeByName("NoSuchType") == NULL);
 
1085
  EXPECT_TRUE(message_ ->FindNestedTypeByName("Baz"       ) == NULL);
 
1086
  EXPECT_TRUE(message2_->FindNestedTypeByName("Bar"       ) == NULL);
 
1087
 
 
1088
  EXPECT_TRUE(message_->FindNestedTypeByName("Qux") == NULL);
 
1089
}
 
1090
 
 
1091
TEST_F(NestedDescriptorTest, EnumName) {
 
1092
  EXPECT_EQ("Baz" , baz_ ->name());
 
1093
  EXPECT_EQ("Qux" , qux_ ->name());
 
1094
  EXPECT_EQ("Qux" , qux2_->name());
 
1095
  EXPECT_EQ("Quux", quux2_->name());
 
1096
 
 
1097
  EXPECT_EQ("TestMessage.Baz", baz_->full_name());
 
1098
  EXPECT_EQ("TestMessage.Qux", qux_->full_name());
 
1099
  EXPECT_EQ("corge.grault.TestMessage2.Qux" , qux2_ ->full_name());
 
1100
  EXPECT_EQ("corge.grault.TestMessage2.Quux", quux2_->full_name());
 
1101
}
 
1102
 
 
1103
TEST_F(NestedDescriptorTest, EnumContainingType) {
 
1104
  EXPECT_EQ(message_ , baz_  ->containing_type());
 
1105
  EXPECT_EQ(message_ , qux_  ->containing_type());
 
1106
  EXPECT_EQ(message2_, qux2_ ->containing_type());
 
1107
  EXPECT_EQ(message2_, quux2_->containing_type());
 
1108
}
 
1109
 
 
1110
TEST_F(NestedDescriptorTest, NestedEnumsByIndex) {
 
1111
  ASSERT_EQ(2, message_->nested_type_count());
 
1112
  EXPECT_EQ(foo_, message_->nested_type(0));
 
1113
  EXPECT_EQ(bar_, message_->nested_type(1));
 
1114
}
 
1115
 
 
1116
TEST_F(NestedDescriptorTest, FindEnumTypeByName) {
 
1117
  EXPECT_EQ(baz_  , message_ ->FindEnumTypeByName("Baz" ));
 
1118
  EXPECT_EQ(qux_  , message_ ->FindEnumTypeByName("Qux" ));
 
1119
  EXPECT_EQ(qux2_ , message2_->FindEnumTypeByName("Qux" ));
 
1120
  EXPECT_EQ(quux2_, message2_->FindEnumTypeByName("Quux"));
 
1121
 
 
1122
  EXPECT_TRUE(message_ ->FindEnumTypeByName("NoSuchType") == NULL);
 
1123
  EXPECT_TRUE(message_ ->FindEnumTypeByName("Quux"      ) == NULL);
 
1124
  EXPECT_TRUE(message2_->FindEnumTypeByName("Baz"       ) == NULL);
 
1125
 
 
1126
  EXPECT_TRUE(message_->FindEnumTypeByName("Foo") == NULL);
 
1127
}
 
1128
 
 
1129
TEST_F(NestedDescriptorTest, FindEnumValueByName) {
 
1130
  EXPECT_EQ(a_ , message_ ->FindEnumValueByName("A"));
 
1131
  EXPECT_EQ(b_ , message_ ->FindEnumValueByName("B"));
 
1132
  EXPECT_EQ(a2_, message2_->FindEnumValueByName("A"));
 
1133
  EXPECT_EQ(c2_, message2_->FindEnumValueByName("C"));
 
1134
 
 
1135
  EXPECT_TRUE(message_ ->FindEnumValueByName("NO_SUCH_VALUE") == NULL);
 
1136
  EXPECT_TRUE(message_ ->FindEnumValueByName("C"            ) == NULL);
 
1137
  EXPECT_TRUE(message2_->FindEnumValueByName("B"            ) == NULL);
 
1138
 
 
1139
  EXPECT_TRUE(message_->FindEnumValueByName("Foo") == NULL);
 
1140
}
 
1141
 
 
1142
// ===================================================================
 
1143
 
 
1144
// Test extensions.
 
1145
class ExtensionDescriptorTest : public testing::Test {
 
1146
 protected:
 
1147
  virtual void SetUp() {
 
1148
    // Build descriptors for the following definitions:
 
1149
    //
 
1150
    //   enum Baz {}
 
1151
    //   message Qux {}
 
1152
    //
 
1153
    //   message Foo {
 
1154
    //     extensions 10 to 19;
 
1155
    //     extensions 30 to 39;
 
1156
    //   }
 
1157
    //   extends Foo with optional int32 foo_int32 = 10;
 
1158
    //   extends Foo with repeated TestEnum foo_enum = 19;
 
1159
    //   message Bar {
 
1160
    //     extends Foo with optional Qux foo_message = 30;
 
1161
    //     // (using Qux as the group type)
 
1162
    //     extends Foo with repeated group foo_group = 39;
 
1163
    //   }
 
1164
 
 
1165
    FileDescriptorProto foo_file;
 
1166
    foo_file.set_name("foo.proto");
 
1167
 
 
1168
    AddEmptyEnum(&foo_file, "Baz");
 
1169
    AddMessage(&foo_file, "Qux");
 
1170
 
 
1171
    DescriptorProto* foo = AddMessage(&foo_file, "Foo");
 
1172
    AddExtensionRange(foo, 10, 20);
 
1173
    AddExtensionRange(foo, 30, 40);
 
1174
 
 
1175
    AddExtension(&foo_file, "Foo", "foo_int32", 10,
 
1176
                 FieldDescriptorProto::LABEL_OPTIONAL,
 
1177
                 FieldDescriptorProto::TYPE_INT32);
 
1178
    AddExtension(&foo_file, "Foo", "foo_enum", 19,
 
1179
                 FieldDescriptorProto::LABEL_REPEATED,
 
1180
                 FieldDescriptorProto::TYPE_ENUM)
 
1181
      ->set_type_name("Baz");
 
1182
 
 
1183
    DescriptorProto* bar = AddMessage(&foo_file, "Bar");
 
1184
    AddNestedExtension(bar, "Foo", "foo_message", 30,
 
1185
                       FieldDescriptorProto::LABEL_OPTIONAL,
 
1186
                       FieldDescriptorProto::TYPE_MESSAGE)
 
1187
      ->set_type_name("Qux");
 
1188
    AddNestedExtension(bar, "Foo", "foo_group", 39,
 
1189
                       FieldDescriptorProto::LABEL_REPEATED,
 
1190
                       FieldDescriptorProto::TYPE_GROUP)
 
1191
      ->set_type_name("Qux");
 
1192
 
 
1193
    // Build the descriptors and get the pointers.
 
1194
    foo_file_ = pool_.BuildFile(foo_file);
 
1195
    ASSERT_TRUE(foo_file_ != NULL);
 
1196
 
 
1197
    ASSERT_EQ(1, foo_file_->enum_type_count());
 
1198
    baz_ = foo_file_->enum_type(0);
 
1199
 
 
1200
    ASSERT_EQ(3, foo_file_->message_type_count());
 
1201
    qux_ = foo_file_->message_type(0);
 
1202
    foo_ = foo_file_->message_type(1);
 
1203
    bar_ = foo_file_->message_type(2);
 
1204
  }
 
1205
 
 
1206
  DescriptorPool pool_;
 
1207
 
 
1208
  const FileDescriptor* foo_file_;
 
1209
 
 
1210
  const Descriptor* foo_;
 
1211
  const Descriptor* bar_;
 
1212
  const EnumDescriptor* baz_;
 
1213
  const Descriptor* qux_;
 
1214
};
 
1215
 
 
1216
TEST_F(ExtensionDescriptorTest, ExtensionRanges) {
 
1217
  EXPECT_EQ(0, bar_->extension_range_count());
 
1218
  ASSERT_EQ(2, foo_->extension_range_count());
 
1219
 
 
1220
  EXPECT_EQ(10, foo_->extension_range(0)->start);
 
1221
  EXPECT_EQ(30, foo_->extension_range(1)->start);
 
1222
 
 
1223
  EXPECT_EQ(20, foo_->extension_range(0)->end);
 
1224
  EXPECT_EQ(40, foo_->extension_range(1)->end);
 
1225
};
 
1226
 
 
1227
TEST_F(ExtensionDescriptorTest, Extensions) {
 
1228
  EXPECT_EQ(0, foo_->extension_count());
 
1229
  ASSERT_EQ(2, foo_file_->extension_count());
 
1230
  ASSERT_EQ(2, bar_->extension_count());
 
1231
 
 
1232
  EXPECT_TRUE(foo_file_->extension(0)->is_extension());
 
1233
  EXPECT_TRUE(foo_file_->extension(1)->is_extension());
 
1234
  EXPECT_TRUE(bar_->extension(0)->is_extension());
 
1235
  EXPECT_TRUE(bar_->extension(1)->is_extension());
 
1236
 
 
1237
  EXPECT_EQ("foo_int32"  , foo_file_->extension(0)->name());
 
1238
  EXPECT_EQ("foo_enum"   , foo_file_->extension(1)->name());
 
1239
  EXPECT_EQ("foo_message", bar_->extension(0)->name());
 
1240
  EXPECT_EQ("foo_group"  , bar_->extension(1)->name());
 
1241
 
 
1242
  EXPECT_EQ(10, foo_file_->extension(0)->number());
 
1243
  EXPECT_EQ(19, foo_file_->extension(1)->number());
 
1244
  EXPECT_EQ(30, bar_->extension(0)->number());
 
1245
  EXPECT_EQ(39, bar_->extension(1)->number());
 
1246
 
 
1247
  EXPECT_EQ(FieldDescriptor::TYPE_INT32  , foo_file_->extension(0)->type());
 
1248
  EXPECT_EQ(FieldDescriptor::TYPE_ENUM   , foo_file_->extension(1)->type());
 
1249
  EXPECT_EQ(FieldDescriptor::TYPE_MESSAGE, bar_->extension(0)->type());
 
1250
  EXPECT_EQ(FieldDescriptor::TYPE_GROUP  , bar_->extension(1)->type());
 
1251
 
 
1252
  EXPECT_EQ(baz_, foo_file_->extension(1)->enum_type());
 
1253
  EXPECT_EQ(qux_, bar_->extension(0)->message_type());
 
1254
  EXPECT_EQ(qux_, bar_->extension(1)->message_type());
 
1255
 
 
1256
  EXPECT_EQ(FieldDescriptor::LABEL_OPTIONAL, foo_file_->extension(0)->label());
 
1257
  EXPECT_EQ(FieldDescriptor::LABEL_REPEATED, foo_file_->extension(1)->label());
 
1258
  EXPECT_EQ(FieldDescriptor::LABEL_OPTIONAL, bar_->extension(0)->label());
 
1259
  EXPECT_EQ(FieldDescriptor::LABEL_REPEATED, bar_->extension(1)->label());
 
1260
 
 
1261
  EXPECT_EQ(foo_, foo_file_->extension(0)->containing_type());
 
1262
  EXPECT_EQ(foo_, foo_file_->extension(1)->containing_type());
 
1263
  EXPECT_EQ(foo_, bar_->extension(0)->containing_type());
 
1264
  EXPECT_EQ(foo_, bar_->extension(1)->containing_type());
 
1265
 
 
1266
  EXPECT_TRUE(foo_file_->extension(0)->extension_scope() == NULL);
 
1267
  EXPECT_TRUE(foo_file_->extension(1)->extension_scope() == NULL);
 
1268
  EXPECT_EQ(bar_, bar_->extension(0)->extension_scope());
 
1269
  EXPECT_EQ(bar_, bar_->extension(1)->extension_scope());
 
1270
};
 
1271
 
 
1272
TEST_F(ExtensionDescriptorTest, IsExtensionNumber) {
 
1273
  EXPECT_FALSE(foo_->IsExtensionNumber( 9));
 
1274
  EXPECT_TRUE (foo_->IsExtensionNumber(10));
 
1275
  EXPECT_TRUE (foo_->IsExtensionNumber(19));
 
1276
  EXPECT_FALSE(foo_->IsExtensionNumber(20));
 
1277
  EXPECT_FALSE(foo_->IsExtensionNumber(29));
 
1278
  EXPECT_TRUE (foo_->IsExtensionNumber(30));
 
1279
  EXPECT_TRUE (foo_->IsExtensionNumber(39));
 
1280
  EXPECT_FALSE(foo_->IsExtensionNumber(40));
 
1281
}
 
1282
 
 
1283
TEST_F(ExtensionDescriptorTest, FindExtensionByName) {
 
1284
  // Note that FileDescriptor::FindExtensionByName() is tested by
 
1285
  // FileDescriptorTest.
 
1286
  ASSERT_EQ(2, bar_->extension_count());
 
1287
 
 
1288
  EXPECT_EQ(bar_->extension(0), bar_->FindExtensionByName("foo_message"));
 
1289
  EXPECT_EQ(bar_->extension(1), bar_->FindExtensionByName("foo_group"  ));
 
1290
 
 
1291
  EXPECT_TRUE(bar_->FindExtensionByName("no_such_extension") == NULL);
 
1292
  EXPECT_TRUE(foo_->FindExtensionByName("foo_int32") == NULL);
 
1293
  EXPECT_TRUE(foo_->FindExtensionByName("foo_message") == NULL);
 
1294
}
 
1295
 
 
1296
// ===================================================================
 
1297
 
 
1298
class MiscTest : public testing::Test {
 
1299
 protected:
 
1300
  // Function which makes a field of the given type just to find out what its
 
1301
  // cpp_type is.
 
1302
  FieldDescriptor::CppType GetCppTypeForFieldType(FieldDescriptor::Type type) {
 
1303
    FileDescriptorProto file_proto;
 
1304
    file_proto.set_name("foo.proto");
 
1305
    AddEmptyEnum(&file_proto, "DummyEnum");
 
1306
 
 
1307
    DescriptorProto* message = AddMessage(&file_proto, "TestMessage");
 
1308
    FieldDescriptorProto* field =
 
1309
      AddField(message, "foo", 1, FieldDescriptorProto::LABEL_OPTIONAL,
 
1310
               static_cast<FieldDescriptorProto::Type>(type));
 
1311
 
 
1312
    if (type == FieldDescriptor::TYPE_MESSAGE ||
 
1313
        type == FieldDescriptor::TYPE_GROUP) {
 
1314
      field->set_type_name("TestMessage");
 
1315
    } else if (type == FieldDescriptor::TYPE_ENUM) {
 
1316
      field->set_type_name("DummyEnum");
 
1317
    }
 
1318
 
 
1319
    // Build the descriptors and get the pointers.
 
1320
    DescriptorPool pool;
 
1321
    const FileDescriptor* file = pool.BuildFile(file_proto);
 
1322
 
 
1323
    if (file != NULL &&
 
1324
        file->message_type_count() == 1 &&
 
1325
        file->message_type(0)->field_count() == 1) {
 
1326
      return file->message_type(0)->field(0)->cpp_type();
 
1327
    } else {
 
1328
      return static_cast<FieldDescriptor::CppType>(0);
 
1329
    }
 
1330
  }
 
1331
};
 
1332
 
 
1333
TEST_F(MiscTest, CppTypes) {
 
1334
  // Test that CPP types are assigned correctly.
 
1335
 
 
1336
  typedef FieldDescriptor FD;  // avoid ugly line wrapping
 
1337
 
 
1338
  EXPECT_EQ(FD::CPPTYPE_DOUBLE , GetCppTypeForFieldType(FD::TYPE_DOUBLE  ));
 
1339
  EXPECT_EQ(FD::CPPTYPE_FLOAT  , GetCppTypeForFieldType(FD::TYPE_FLOAT   ));
 
1340
  EXPECT_EQ(FD::CPPTYPE_INT64  , GetCppTypeForFieldType(FD::TYPE_INT64   ));
 
1341
  EXPECT_EQ(FD::CPPTYPE_UINT64 , GetCppTypeForFieldType(FD::TYPE_UINT64  ));
 
1342
  EXPECT_EQ(FD::CPPTYPE_INT32  , GetCppTypeForFieldType(FD::TYPE_INT32   ));
 
1343
  EXPECT_EQ(FD::CPPTYPE_UINT64 , GetCppTypeForFieldType(FD::TYPE_FIXED64 ));
 
1344
  EXPECT_EQ(FD::CPPTYPE_UINT32 , GetCppTypeForFieldType(FD::TYPE_FIXED32 ));
 
1345
  EXPECT_EQ(FD::CPPTYPE_BOOL   , GetCppTypeForFieldType(FD::TYPE_BOOL    ));
 
1346
  EXPECT_EQ(FD::CPPTYPE_STRING , GetCppTypeForFieldType(FD::TYPE_STRING  ));
 
1347
  EXPECT_EQ(FD::CPPTYPE_MESSAGE, GetCppTypeForFieldType(FD::TYPE_GROUP   ));
 
1348
  EXPECT_EQ(FD::CPPTYPE_MESSAGE, GetCppTypeForFieldType(FD::TYPE_MESSAGE ));
 
1349
  EXPECT_EQ(FD::CPPTYPE_STRING , GetCppTypeForFieldType(FD::TYPE_BYTES   ));
 
1350
  EXPECT_EQ(FD::CPPTYPE_UINT32 , GetCppTypeForFieldType(FD::TYPE_UINT32  ));
 
1351
  EXPECT_EQ(FD::CPPTYPE_ENUM   , GetCppTypeForFieldType(FD::TYPE_ENUM    ));
 
1352
  EXPECT_EQ(FD::CPPTYPE_INT32  , GetCppTypeForFieldType(FD::TYPE_SFIXED32));
 
1353
  EXPECT_EQ(FD::CPPTYPE_INT64  , GetCppTypeForFieldType(FD::TYPE_SFIXED64));
 
1354
  EXPECT_EQ(FD::CPPTYPE_INT32  , GetCppTypeForFieldType(FD::TYPE_SINT32  ));
 
1355
  EXPECT_EQ(FD::CPPTYPE_INT64  , GetCppTypeForFieldType(FD::TYPE_SINT64  ));
 
1356
}
 
1357
 
 
1358
TEST_F(MiscTest, DefaultValues) {
 
1359
  // Test that setting default values works.
 
1360
  FileDescriptorProto file_proto;
 
1361
  file_proto.set_name("foo.proto");
 
1362
 
 
1363
  EnumDescriptorProto* enum_type_proto = AddEnum(&file_proto, "DummyEnum");
 
1364
  AddEnumValue(enum_type_proto, "A", 1);
 
1365
  AddEnumValue(enum_type_proto, "B", 2);
 
1366
 
 
1367
  DescriptorProto* message_proto = AddMessage(&file_proto, "TestMessage");
 
1368
 
 
1369
  typedef FieldDescriptorProto FD;  // avoid ugly line wrapping
 
1370
  const FD::Label label = FD::LABEL_OPTIONAL;
 
1371
 
 
1372
  // Create fields of every CPP type with default values.
 
1373
  AddField(message_proto, "int32" , 1, label, FD::TYPE_INT32 )
 
1374
    ->set_default_value("-1");
 
1375
  AddField(message_proto, "int64" , 2, label, FD::TYPE_INT64 )
 
1376
    ->set_default_value("-1000000000000");
 
1377
  AddField(message_proto, "uint32", 3, label, FD::TYPE_UINT32)
 
1378
    ->set_default_value("42");
 
1379
  AddField(message_proto, "uint64", 4, label, FD::TYPE_UINT64)
 
1380
    ->set_default_value("2000000000000");
 
1381
  AddField(message_proto, "float" , 5, label, FD::TYPE_FLOAT )
 
1382
    ->set_default_value("4.5");
 
1383
  AddField(message_proto, "double", 6, label, FD::TYPE_DOUBLE)
 
1384
    ->set_default_value("10e100");
 
1385
  AddField(message_proto, "bool"  , 7, label, FD::TYPE_BOOL  )
 
1386
    ->set_default_value("true");
 
1387
  AddField(message_proto, "string", 8, label, FD::TYPE_STRING)
 
1388
    ->set_default_value("hello");
 
1389
  AddField(message_proto, "data"  , 9, label, FD::TYPE_BYTES )
 
1390
    ->set_default_value("\\001\\002\\003");
 
1391
 
 
1392
  FieldDescriptorProto* enum_field =
 
1393
    AddField(message_proto, "enum", 10, label, FD::TYPE_ENUM);
 
1394
  enum_field->set_type_name("DummyEnum");
 
1395
  enum_field->set_default_value("B");
 
1396
 
 
1397
  // Strings are allowed to have empty defaults.  (At one point, due to
 
1398
  // a bug, empty defaults for strings were rejected.  Oops.)
 
1399
  AddField(message_proto, "empty_string", 11, label, FD::TYPE_STRING)
 
1400
    ->set_default_value("");
 
1401
 
 
1402
  // Add a second set of fields with implicit defalut values.
 
1403
  AddField(message_proto, "implicit_int32" , 21, label, FD::TYPE_INT32 );
 
1404
  AddField(message_proto, "implicit_int64" , 22, label, FD::TYPE_INT64 );
 
1405
  AddField(message_proto, "implicit_uint32", 23, label, FD::TYPE_UINT32);
 
1406
  AddField(message_proto, "implicit_uint64", 24, label, FD::TYPE_UINT64);
 
1407
  AddField(message_proto, "implicit_float" , 25, label, FD::TYPE_FLOAT );
 
1408
  AddField(message_proto, "implicit_double", 26, label, FD::TYPE_DOUBLE);
 
1409
  AddField(message_proto, "implicit_bool"  , 27, label, FD::TYPE_BOOL  );
 
1410
  AddField(message_proto, "implicit_string", 28, label, FD::TYPE_STRING);
 
1411
  AddField(message_proto, "implicit_data"  , 29, label, FD::TYPE_BYTES );
 
1412
  AddField(message_proto, "implicit_enum"  , 30, label, FD::TYPE_ENUM)
 
1413
    ->set_type_name("DummyEnum");
 
1414
 
 
1415
  // Build it.
 
1416
  DescriptorPool pool;
 
1417
  const FileDescriptor* file = pool.BuildFile(file_proto);
 
1418
  ASSERT_TRUE(file != NULL);
 
1419
 
 
1420
  ASSERT_EQ(1, file->enum_type_count());
 
1421
  const EnumDescriptor* enum_type = file->enum_type(0);
 
1422
  ASSERT_EQ(2, enum_type->value_count());
 
1423
  const EnumValueDescriptor* enum_value_a = enum_type->value(0);
 
1424
  const EnumValueDescriptor* enum_value_b = enum_type->value(1);
 
1425
 
 
1426
  ASSERT_EQ(1, file->message_type_count());
 
1427
  const Descriptor* message = file->message_type(0);
 
1428
 
 
1429
  ASSERT_EQ(21, message->field_count());
 
1430
 
 
1431
  // Check the default values.
 
1432
  ASSERT_TRUE(message->field(0)->has_default_value());
 
1433
  ASSERT_TRUE(message->field(1)->has_default_value());
 
1434
  ASSERT_TRUE(message->field(2)->has_default_value());
 
1435
  ASSERT_TRUE(message->field(3)->has_default_value());
 
1436
  ASSERT_TRUE(message->field(4)->has_default_value());
 
1437
  ASSERT_TRUE(message->field(5)->has_default_value());
 
1438
  ASSERT_TRUE(message->field(6)->has_default_value());
 
1439
  ASSERT_TRUE(message->field(7)->has_default_value());
 
1440
  ASSERT_TRUE(message->field(8)->has_default_value());
 
1441
  ASSERT_TRUE(message->field(9)->has_default_value());
 
1442
  ASSERT_TRUE(message->field(10)->has_default_value());
 
1443
 
 
1444
  EXPECT_EQ(-1              , message->field(0)->default_value_int32 ());
 
1445
  EXPECT_EQ(-GOOGLE_ULONGLONG(1000000000000),
 
1446
            message->field(1)->default_value_int64 ());
 
1447
  EXPECT_EQ(42              , message->field(2)->default_value_uint32());
 
1448
  EXPECT_EQ(GOOGLE_ULONGLONG(2000000000000),
 
1449
            message->field(3)->default_value_uint64());
 
1450
  EXPECT_EQ(4.5             , message->field(4)->default_value_float ());
 
1451
  EXPECT_EQ(10e100          , message->field(5)->default_value_double());
 
1452
  EXPECT_EQ(true            , message->field(6)->default_value_bool  ());
 
1453
  EXPECT_EQ("hello"         , message->field(7)->default_value_string());
 
1454
  EXPECT_EQ("\001\002\003"  , message->field(8)->default_value_string());
 
1455
  EXPECT_EQ(enum_value_b    , message->field(9)->default_value_enum  ());
 
1456
  EXPECT_EQ(""              , message->field(10)->default_value_string());
 
1457
 
 
1458
  ASSERT_FALSE(message->field(11)->has_default_value());
 
1459
  ASSERT_FALSE(message->field(12)->has_default_value());
 
1460
  ASSERT_FALSE(message->field(13)->has_default_value());
 
1461
  ASSERT_FALSE(message->field(14)->has_default_value());
 
1462
  ASSERT_FALSE(message->field(15)->has_default_value());
 
1463
  ASSERT_FALSE(message->field(16)->has_default_value());
 
1464
  ASSERT_FALSE(message->field(17)->has_default_value());
 
1465
  ASSERT_FALSE(message->field(18)->has_default_value());
 
1466
  ASSERT_FALSE(message->field(19)->has_default_value());
 
1467
  ASSERT_FALSE(message->field(20)->has_default_value());
 
1468
 
 
1469
  EXPECT_EQ(0    , message->field(11)->default_value_int32 ());
 
1470
  EXPECT_EQ(0    , message->field(12)->default_value_int64 ());
 
1471
  EXPECT_EQ(0    , message->field(13)->default_value_uint32());
 
1472
  EXPECT_EQ(0    , message->field(14)->default_value_uint64());
 
1473
  EXPECT_EQ(0.0f , message->field(15)->default_value_float ());
 
1474
  EXPECT_EQ(0.0  , message->field(16)->default_value_double());
 
1475
  EXPECT_EQ(false, message->field(17)->default_value_bool  ());
 
1476
  EXPECT_EQ(""   , message->field(18)->default_value_string());
 
1477
  EXPECT_EQ(""   , message->field(19)->default_value_string());
 
1478
  EXPECT_EQ(enum_value_a, message->field(20)->default_value_enum());
 
1479
}
 
1480
 
 
1481
TEST_F(MiscTest, FieldOptions) {
 
1482
  // Try setting field options.
 
1483
 
 
1484
  FileDescriptorProto file_proto;
 
1485
  file_proto.set_name("foo.proto");
 
1486
 
 
1487
  DescriptorProto* message_proto = AddMessage(&file_proto, "TestMessage");
 
1488
  AddField(message_proto, "foo", 1,
 
1489
           FieldDescriptorProto::LABEL_OPTIONAL,
 
1490
           FieldDescriptorProto::TYPE_INT32);
 
1491
  FieldDescriptorProto* bar_proto =
 
1492
    AddField(message_proto, "bar", 2,
 
1493
             FieldDescriptorProto::LABEL_OPTIONAL,
 
1494
             FieldDescriptorProto::TYPE_INT32);
 
1495
 
 
1496
  FieldOptions* options = bar_proto->mutable_options();
 
1497
  options->set_ctype(FieldOptions::CORD);
 
1498
 
 
1499
  // Build the descriptors and get the pointers.
 
1500
  DescriptorPool pool;
 
1501
  const FileDescriptor* file = pool.BuildFile(file_proto);
 
1502
  ASSERT_TRUE(file != NULL);
 
1503
 
 
1504
  ASSERT_EQ(1, file->message_type_count());
 
1505
  const Descriptor* message = file->message_type(0);
 
1506
 
 
1507
  ASSERT_EQ(2, message->field_count());
 
1508
  const FieldDescriptor* foo = message->field(0);
 
1509
  const FieldDescriptor* bar = message->field(1);
 
1510
 
 
1511
  // "foo" had no options set, so it should return the default options.
 
1512
  EXPECT_EQ(&FieldOptions::default_instance(), &foo->options());
 
1513
 
 
1514
  // "bar" had options set.
 
1515
  EXPECT_NE(&FieldOptions::default_instance(), options);
 
1516
  EXPECT_TRUE(bar->options().has_ctype());
 
1517
  EXPECT_EQ(FieldOptions::CORD, bar->options().ctype());
 
1518
}
 
1519
 
 
1520
// ===================================================================
 
1521
 
 
1522
// The tests below trigger every unique call to AddError() in descriptor.cc,
 
1523
// in the order in which they appear in that file.  I'm using TextFormat here
 
1524
// to specify the input descriptors because building them using code would
 
1525
// be too bulky.
 
1526
 
 
1527
class MockErrorCollector : public DescriptorPool::ErrorCollector {
 
1528
 public:
 
1529
  MockErrorCollector() {}
 
1530
  ~MockErrorCollector() {}
 
1531
 
 
1532
  string text_;
 
1533
 
 
1534
  // implements ErrorCollector ---------------------------------------
 
1535
  void AddError(const string& filename,
 
1536
                const string& element_name, const Message* descriptor,
 
1537
                ErrorLocation location, const string& message) {
 
1538
    const char* location_name = NULL;
 
1539
    switch (location) {
 
1540
      case NAME         : location_name = "NAME"         ; break;
 
1541
      case NUMBER       : location_name = "NUMBER"       ; break;
 
1542
      case TYPE         : location_name = "TYPE"         ; break;
 
1543
      case EXTENDEE     : location_name = "EXTENDEE"     ; break;
 
1544
      case DEFAULT_VALUE: location_name = "DEFAULT_VALUE"; break;
 
1545
      case INPUT_TYPE   : location_name = "INPUT_TYPE"   ; break;
 
1546
      case OUTPUT_TYPE  : location_name = "OUTPUT_TYPE"  ; break;
 
1547
      case OTHER        : location_name = "OTHER"        ; break;
 
1548
    }
 
1549
 
 
1550
    strings::SubstituteAndAppend(
 
1551
      &text_, "$0: $1: $2: $3\n",
 
1552
      filename, element_name, location_name, message);
 
1553
  }
 
1554
};
 
1555
 
 
1556
class ValidationErrorTest : public testing::Test {
 
1557
 protected:
 
1558
  // Parse file_text as a FileDescriptorProto in text format and add it
 
1559
  // to the DescriptorPool.  Expect no errors.
 
1560
  void BuildFile(const string& file_text) {
 
1561
    FileDescriptorProto file_proto;
 
1562
    ASSERT_TRUE(TextFormat::ParseFromString(file_text, &file_proto));
 
1563
    ASSERT_TRUE(pool_.BuildFile(file_proto) != NULL);
 
1564
  }
 
1565
 
 
1566
  // Parse file_text as a FileDescriptorProto in text format and add it
 
1567
  // to the DescriptorPool.  Expect errors to be produced which match the
 
1568
  // given error text.
 
1569
  void BuildFileWithErrors(const string& file_text,
 
1570
                           const string& expected_errors) {
 
1571
    FileDescriptorProto file_proto;
 
1572
    ASSERT_TRUE(TextFormat::ParseFromString(file_text, &file_proto));
 
1573
 
 
1574
    MockErrorCollector error_collector;
 
1575
    EXPECT_TRUE(
 
1576
      pool_.BuildFileCollectingErrors(file_proto, &error_collector) == NULL);
 
1577
    EXPECT_EQ(expected_errors, error_collector.text_);
 
1578
  }
 
1579
 
 
1580
  DescriptorPool pool_;
 
1581
};
 
1582
 
 
1583
TEST_F(ValidationErrorTest, AlreadyDefined) {
 
1584
  BuildFileWithErrors(
 
1585
    "name: \"foo.proto\" "
 
1586
    "message_type { name: \"Foo\" }"
 
1587
    "message_type { name: \"Foo\" }",
 
1588
 
 
1589
    "foo.proto: Foo: NAME: \"Foo\" is already defined.\n");
 
1590
}
 
1591
 
 
1592
TEST_F(ValidationErrorTest, AlreadyDefinedInPackage) {
 
1593
  BuildFileWithErrors(
 
1594
    "name: \"foo.proto\" "
 
1595
    "package: \"foo.bar\" "
 
1596
    "message_type { name: \"Foo\" }"
 
1597
    "message_type { name: \"Foo\" }",
 
1598
 
 
1599
    "foo.proto: foo.bar.Foo: NAME: \"Foo\" is already defined in "
 
1600
      "\"foo.bar\".\n");
 
1601
}
 
1602
 
 
1603
TEST_F(ValidationErrorTest, AlreadyDefinedInOtherFile) {
 
1604
  BuildFile(
 
1605
    "name: \"foo.proto\" "
 
1606
    "message_type { name: \"Foo\" }");
 
1607
 
 
1608
  BuildFileWithErrors(
 
1609
    "name: \"bar.proto\" "
 
1610
    "message_type { name: \"Foo\" }",
 
1611
 
 
1612
    "bar.proto: Foo: NAME: \"Foo\" is already defined in file "
 
1613
      "\"foo.proto\".\n");
 
1614
}
 
1615
 
 
1616
TEST_F(ValidationErrorTest, PackageAlreadyDefined) {
 
1617
  BuildFile(
 
1618
    "name: \"foo.proto\" "
 
1619
    "message_type { name: \"foo\" }");
 
1620
  BuildFileWithErrors(
 
1621
    "name: \"bar.proto\" "
 
1622
    "package: \"foo.bar\"",
 
1623
 
 
1624
    "bar.proto: foo: NAME: \"foo\" is already defined (as something other "
 
1625
      "than a package) in file \"foo.proto\".\n");
 
1626
}
 
1627
 
 
1628
TEST_F(ValidationErrorTest, MissingName) {
 
1629
  BuildFileWithErrors(
 
1630
    "name: \"foo.proto\" "
 
1631
    "message_type { }",
 
1632
 
 
1633
    "foo.proto: : NAME: Missing name.\n");
 
1634
}
 
1635
 
 
1636
TEST_F(ValidationErrorTest, InvalidName) {
 
1637
  BuildFileWithErrors(
 
1638
    "name: \"foo.proto\" "
 
1639
    "message_type { name: \"$\" }",
 
1640
 
 
1641
    "foo.proto: $: NAME: \"$\" is not a valid identifier.\n");
 
1642
}
 
1643
 
 
1644
TEST_F(ValidationErrorTest, InvalidPackageName) {
 
1645
  BuildFileWithErrors(
 
1646
    "name: \"foo.proto\" "
 
1647
    "package: \"foo.$\"",
 
1648
 
 
1649
    "foo.proto: foo.$: NAME: \"$\" is not a valid identifier.\n");
 
1650
}
 
1651
 
 
1652
TEST_F(ValidationErrorTest, MissingFileName) {
 
1653
  BuildFileWithErrors(
 
1654
    "",
 
1655
 
 
1656
    ": : OTHER: Missing field: FileDescriptorProto.name.\n");
 
1657
}
 
1658
 
 
1659
TEST_F(ValidationErrorTest, DupeDependency) {
 
1660
  BuildFile("name: \"foo.proto\"");
 
1661
  BuildFileWithErrors(
 
1662
    "name: \"bar.proto\" "
 
1663
    "dependency: \"foo.proto\" "
 
1664
    "dependency: \"foo.proto\" ",
 
1665
 
 
1666
    "bar.proto: bar.proto: OTHER: Import \"foo.proto\" was listed twice.\n");
 
1667
}
 
1668
 
 
1669
TEST_F(ValidationErrorTest, UnknownDependency) {
 
1670
  BuildFileWithErrors(
 
1671
    "name: \"bar.proto\" "
 
1672
    "dependency: \"foo.proto\" ",
 
1673
 
 
1674
    "bar.proto: bar.proto: OTHER: Import \"foo.proto\" has not been loaded.\n");
 
1675
}
 
1676
 
 
1677
TEST_F(ValidationErrorTest, DupeFile) {
 
1678
  BuildFile(
 
1679
    "name: \"foo.proto\" "
 
1680
    "message_type { name: \"Foo\" }");
 
1681
  // Note:  We should *not* get redundant errors about "Foo" already being
 
1682
  //   defined.
 
1683
  BuildFileWithErrors(
 
1684
    "name: \"foo.proto\" "
 
1685
    "message_type { name: \"Foo\" }",
 
1686
 
 
1687
    "foo.proto: foo.proto: OTHER: A file with this name is already in the "
 
1688
      "pool.\n");
 
1689
}
 
1690
 
 
1691
TEST_F(ValidationErrorTest, FieldInExtensionRange) {
 
1692
  BuildFileWithErrors(
 
1693
    "name: \"foo.proto\" "
 
1694
    "message_type {"
 
1695
    "  name: \"Foo\""
 
1696
    "  field { name: \"foo\" number:  9 label:LABEL_OPTIONAL type:TYPE_INT32 }"
 
1697
    "  field { name: \"bar\" number: 10 label:LABEL_OPTIONAL type:TYPE_INT32 }"
 
1698
    "  field { name: \"baz\" number: 19 label:LABEL_OPTIONAL type:TYPE_INT32 }"
 
1699
    "  field { name: \"qux\" number: 20 label:LABEL_OPTIONAL type:TYPE_INT32 }"
 
1700
    "  extension_range { start: 10 end: 20 }"
 
1701
    "}",
 
1702
 
 
1703
    "foo.proto: Foo.bar: NUMBER: Extension range 10 to 19 includes field "
 
1704
      "\"bar\" (10).\n"
 
1705
    "foo.proto: Foo.baz: NUMBER: Extension range 10 to 19 includes field "
 
1706
      "\"baz\" (19).\n");
 
1707
}
 
1708
 
 
1709
TEST_F(ValidationErrorTest, OverlappingExtensionRanges) {
 
1710
  BuildFileWithErrors(
 
1711
    "name: \"foo.proto\" "
 
1712
    "message_type {"
 
1713
    "  name: \"Foo\""
 
1714
    "  extension_range { start: 10 end: 20 }"
 
1715
    "  extension_range { start: 20 end: 30 }"
 
1716
    "  extension_range { start: 19 end: 21 }"
 
1717
    "}",
 
1718
 
 
1719
    "foo.proto: Foo: NUMBER: Extension range 19 to 20 overlaps with "
 
1720
      "already-defined range 10 to 19.\n"
 
1721
    "foo.proto: Foo: NUMBER: Extension range 19 to 20 overlaps with "
 
1722
      "already-defined range 20 to 29.\n");
 
1723
}
 
1724
 
 
1725
TEST_F(ValidationErrorTest, InvalidDefaults) {
 
1726
  BuildFileWithErrors(
 
1727
    "name: \"foo.proto\" "
 
1728
    "message_type {"
 
1729
    "  name: \"Foo\""
 
1730
 
 
1731
    // Invalid number.
 
1732
    "  field { name: \"foo\" number: 1 label: LABEL_OPTIONAL type: TYPE_INT32"
 
1733
    "          default_value: \"abc\" }"
 
1734
 
 
1735
    // Empty default value.
 
1736
    "  field { name: \"bar\" number: 2 label: LABEL_OPTIONAL type: TYPE_INT32"
 
1737
    "          default_value: \"\" }"
 
1738
 
 
1739
    // Invalid boolean.
 
1740
    "  field { name: \"baz\" number: 3 label: LABEL_OPTIONAL type: TYPE_BOOL"
 
1741
    "          default_value: \"abc\" }"
 
1742
 
 
1743
    // Messages can't have defaults.
 
1744
    "  field { name: \"qux\" number: 4 label: LABEL_OPTIONAL type: TYPE_MESSAGE"
 
1745
    "          default_value: \"abc\" type_name: \"Foo\" }"
 
1746
 
 
1747
    // Same thing, but we don't know that this field has message type until
 
1748
    // we look up the type name.
 
1749
    "  field { name: \"quux\" number: 5 label: LABEL_OPTIONAL"
 
1750
    "          default_value: \"abc\" type_name: \"Foo\" }"
 
1751
    "}",
 
1752
 
 
1753
    "foo.proto: Foo.foo: DEFAULT_VALUE: Couldn't parse default value.\n"
 
1754
    "foo.proto: Foo.bar: DEFAULT_VALUE: Couldn't parse default value.\n"
 
1755
    "foo.proto: Foo.baz: DEFAULT_VALUE: Boolean default must be true or "
 
1756
      "false.\n"
 
1757
    "foo.proto: Foo.qux: DEFAULT_VALUE: Messages can't have default values.\n"
 
1758
    "foo.proto: Foo.quux: DEFAULT_VALUE: Messages can't have default "
 
1759
      "values.\n");
 
1760
}
 
1761
 
 
1762
TEST_F(ValidationErrorTest, NegativeFieldNumber) {
 
1763
  BuildFileWithErrors(
 
1764
    "name: \"foo.proto\" "
 
1765
    "message_type {"
 
1766
    "  name: \"Foo\""
 
1767
    "  field { name: \"foo\" number: -1 label:LABEL_OPTIONAL type:TYPE_INT32 }"
 
1768
    "}",
 
1769
 
 
1770
    "foo.proto: Foo.foo: NUMBER: Field numbers must be positive integers.\n");
 
1771
}
 
1772
 
 
1773
TEST_F(ValidationErrorTest, HugeFieldNumber) {
 
1774
  BuildFileWithErrors(
 
1775
    "name: \"foo.proto\" "
 
1776
    "message_type {"
 
1777
    "  name: \"Foo\""
 
1778
    "  field { name: \"foo\" number: 0x70000000 "
 
1779
    "          label:LABEL_OPTIONAL type:TYPE_INT32 }"
 
1780
    "}",
 
1781
 
 
1782
    "foo.proto: Foo.foo: NUMBER: Field numbers cannot be greater than "
 
1783
      "536870911.\n");
 
1784
}
 
1785
 
 
1786
TEST_F(ValidationErrorTest, ReservedFieldNumber) {
 
1787
  BuildFileWithErrors(
 
1788
    "name: \"foo.proto\" "
 
1789
    "message_type {"
 
1790
    "  name: \"Foo\""
 
1791
    "  field {name:\"foo\" number: 18999 label:LABEL_OPTIONAL type:TYPE_INT32 }"
 
1792
    "  field {name:\"bar\" number: 19000 label:LABEL_OPTIONAL type:TYPE_INT32 }"
 
1793
    "  field {name:\"baz\" number: 19999 label:LABEL_OPTIONAL type:TYPE_INT32 }"
 
1794
    "  field {name:\"qux\" number: 20000 label:LABEL_OPTIONAL type:TYPE_INT32 }"
 
1795
    "}",
 
1796
 
 
1797
    "foo.proto: Foo.bar: NUMBER: Field numbers 19000 through 19999 are "
 
1798
      "reserved for the protocol buffer library implementation.\n"
 
1799
    "foo.proto: Foo.baz: NUMBER: Field numbers 19000 through 19999 are "
 
1800
      "reserved for the protocol buffer library implementation.\n");
 
1801
}
 
1802
 
 
1803
TEST_F(ValidationErrorTest, ExtensionMissingExtendee) {
 
1804
  BuildFileWithErrors(
 
1805
    "name: \"foo.proto\" "
 
1806
    "message_type {"
 
1807
    "  name: \"Foo\""
 
1808
    "  extension { name: \"foo\" number: 1 label: LABEL_OPTIONAL"
 
1809
    "              type_name: \"Foo\" }"
 
1810
    "}",
 
1811
 
 
1812
    "foo.proto: Foo.foo: EXTENDEE: FieldDescriptorProto.extendee not set for "
 
1813
      "extension field.\n");
 
1814
}
 
1815
 
 
1816
TEST_F(ValidationErrorTest, NonExtensionWithExtendee) {
 
1817
  BuildFileWithErrors(
 
1818
    "name: \"foo.proto\" "
 
1819
    "message_type {"
 
1820
    "  name: \"Bar\""
 
1821
    "  extension_range { start: 1 end: 2 }"
 
1822
    "}"
 
1823
    "message_type {"
 
1824
    "  name: \"Foo\""
 
1825
    "  field { name: \"foo\" number: 1 label: LABEL_OPTIONAL"
 
1826
    "          type_name: \"Foo\" extendee: \"Bar\" }"
 
1827
    "}",
 
1828
 
 
1829
    "foo.proto: Foo.foo: EXTENDEE: FieldDescriptorProto.extendee set for "
 
1830
      "non-extension field.\n");
 
1831
}
 
1832
 
 
1833
TEST_F(ValidationErrorTest, FieldNumberConflict) {
 
1834
  BuildFileWithErrors(
 
1835
    "name: \"foo.proto\" "
 
1836
    "message_type {"
 
1837
    "  name: \"Foo\""
 
1838
    "  field { name: \"foo\" number: 1 label:LABEL_OPTIONAL type:TYPE_INT32 }"
 
1839
    "  field { name: \"bar\" number: 1 label:LABEL_OPTIONAL type:TYPE_INT32 }"
 
1840
    "}",
 
1841
 
 
1842
    "foo.proto: Foo.bar: NUMBER: Field number 1 has already been used in "
 
1843
      "\"Foo\" by field \"foo\".\n");
 
1844
}
 
1845
 
 
1846
TEST_F(ValidationErrorTest, BadMessageSetExtensionType) {
 
1847
  BuildFileWithErrors(
 
1848
    "name: \"foo.proto\" "
 
1849
    "message_type {"
 
1850
    "  name: \"MessageSet\""
 
1851
    "  options { message_set_wire_format: true }"
 
1852
    "  extension_range { start: 4 end: 5 }"
 
1853
    "}"
 
1854
    "message_type {"
 
1855
    "  name: \"Foo\""
 
1856
    "  extension { name:\"foo\" number:4 label:LABEL_OPTIONAL type:TYPE_INT32"
 
1857
    "              extendee: \"MessageSet\" }"
 
1858
    "}",
 
1859
 
 
1860
    "foo.proto: Foo.foo: TYPE: Extensions of MessageSets must be optional "
 
1861
      "messages.\n");
 
1862
}
 
1863
 
 
1864
TEST_F(ValidationErrorTest, BadMessageSetExtensionLabel) {
 
1865
  BuildFileWithErrors(
 
1866
    "name: \"foo.proto\" "
 
1867
    "message_type {"
 
1868
    "  name: \"MessageSet\""
 
1869
    "  options { message_set_wire_format: true }"
 
1870
    "  extension_range { start: 4 end: 5 }"
 
1871
    "}"
 
1872
    "message_type {"
 
1873
    "  name: \"Foo\""
 
1874
    "  extension { name:\"foo\" number:4 label:LABEL_REPEATED type:TYPE_MESSAGE"
 
1875
    "              type_name: \"Foo\" extendee: \"MessageSet\" }"
 
1876
    "}",
 
1877
 
 
1878
    "foo.proto: Foo.foo: TYPE: Extensions of MessageSets must be optional "
 
1879
      "messages.\n");
 
1880
}
 
1881
 
 
1882
TEST_F(ValidationErrorTest, FieldInMessageSet) {
 
1883
  BuildFileWithErrors(
 
1884
    "name: \"foo.proto\" "
 
1885
    "message_type {"
 
1886
    "  name: \"Foo\""
 
1887
    "  options { message_set_wire_format: true }"
 
1888
    "  field { name: \"foo\" number: 1 label:LABEL_OPTIONAL type:TYPE_INT32 }"
 
1889
    "}",
 
1890
 
 
1891
    "foo.proto: Foo.foo: NAME: MessageSets cannot have fields, only "
 
1892
      "extensions.\n");
 
1893
}
 
1894
 
 
1895
TEST_F(ValidationErrorTest, NegativeExtensionRangeNumber) {
 
1896
  BuildFileWithErrors(
 
1897
    "name: \"foo.proto\" "
 
1898
    "message_type {"
 
1899
    "  name: \"Foo\""
 
1900
    "  extension_range { start: -10 end: -1 }"
 
1901
    "}",
 
1902
 
 
1903
    "foo.proto: Foo: NUMBER: Extension numbers must be positive integers.\n");
 
1904
}
 
1905
 
 
1906
TEST_F(ValidationErrorTest, HugeExtensionRangeNumber) {
 
1907
  BuildFileWithErrors(
 
1908
    "name: \"foo.proto\" "
 
1909
    "message_type {"
 
1910
    "  name: \"Foo\""
 
1911
    "  extension_range { start: 1 end: 0x70000000 }"
 
1912
    "}",
 
1913
 
 
1914
    "foo.proto: Foo: NUMBER: Extension numbers cannot be greater than "
 
1915
      "536870911.\n");
 
1916
}
 
1917
 
 
1918
TEST_F(ValidationErrorTest, ExtensionRangeEndBeforeStart) {
 
1919
  BuildFileWithErrors(
 
1920
    "name: \"foo.proto\" "
 
1921
    "message_type {"
 
1922
    "  name: \"Foo\""
 
1923
    "  extension_range { start: 10 end: 10 }"
 
1924
    "  extension_range { start: 10 end: 5 }"
 
1925
    "}",
 
1926
 
 
1927
    "foo.proto: Foo: NUMBER: Extension range end number must be greater than "
 
1928
      "start number.\n"
 
1929
    "foo.proto: Foo: NUMBER: Extension range end number must be greater than "
 
1930
      "start number.\n");
 
1931
}
 
1932
 
 
1933
TEST_F(ValidationErrorTest, EmptyEnum) {
 
1934
  BuildFileWithErrors(
 
1935
    "name: \"foo.proto\" "
 
1936
    "enum_type { name: \"Foo\" }"
 
1937
    // Also use the empty enum in a message to make sure there are no crashes
 
1938
    // during validation (possible if the code attempts to derive a default
 
1939
    // value for the field).
 
1940
    "message_type {"
 
1941
    "  name: \"Bar\""
 
1942
    "  field { name: \"foo\" number: 1 label:LABEL_OPTIONAL type_name:\"Foo\" }"
 
1943
    "  field { name: \"bar\" number: 2 label:LABEL_OPTIONAL type_name:\"Foo\" "
 
1944
    "          default_value: \"NO_SUCH_VALUE\" }"
 
1945
    "}",
 
1946
 
 
1947
    "foo.proto: Foo: NAME: Enums must contain at least one value.\n"
 
1948
    "foo.proto: Bar.bar: DEFAULT_VALUE: Enum type \"Foo\" has no value named "
 
1949
      "\"NO_SUCH_VALUE\".\n");
 
1950
}
 
1951
 
 
1952
TEST_F(ValidationErrorTest, UndefinedExtendee) {
 
1953
  BuildFileWithErrors(
 
1954
    "name: \"foo.proto\" "
 
1955
    "message_type {"
 
1956
    "  name: \"Foo\""
 
1957
    "  extension { name:\"foo\" number:1 label:LABEL_OPTIONAL type:TYPE_INT32"
 
1958
    "              extendee: \"Bar\" }"
 
1959
    "}",
 
1960
 
 
1961
    "foo.proto: Foo.foo: EXTENDEE: \"Bar\" is not defined.\n");
 
1962
}
 
1963
 
 
1964
TEST_F(ValidationErrorTest, NonMessageExtendee) {
 
1965
  BuildFileWithErrors(
 
1966
    "name: \"foo.proto\" "
 
1967
    "enum_type { name: \"Bar\" value { name:\"DUMMY\" number:0 } }"
 
1968
    "message_type {"
 
1969
    "  name: \"Foo\""
 
1970
    "  extension { name:\"foo\" number:1 label:LABEL_OPTIONAL type:TYPE_INT32"
 
1971
    "              extendee: \"Bar\" }"
 
1972
    "}",
 
1973
 
 
1974
    "foo.proto: Foo.foo: EXTENDEE: \"Bar\" is not a message type.\n");
 
1975
}
 
1976
 
 
1977
TEST_F(ValidationErrorTest, NotAnExtensionNumber) {
 
1978
  BuildFileWithErrors(
 
1979
    "name: \"foo.proto\" "
 
1980
    "message_type {"
 
1981
    "  name: \"Bar\""
 
1982
    "}"
 
1983
    "message_type {"
 
1984
    "  name: \"Foo\""
 
1985
    "  extension { name:\"foo\" number:1 label:LABEL_OPTIONAL type:TYPE_INT32"
 
1986
    "              extendee: \"Bar\" }"
 
1987
    "}",
 
1988
 
 
1989
    "foo.proto: Foo.foo: NUMBER: \"Bar\" does not declare 1 as an extension "
 
1990
      "number.\n");
 
1991
}
 
1992
 
 
1993
TEST_F(ValidationErrorTest, UndefinedFieldType) {
 
1994
  BuildFileWithErrors(
 
1995
    "name: \"foo.proto\" "
 
1996
    "message_type {"
 
1997
    "  name: \"Foo\""
 
1998
    "  field { name:\"foo\" number:1 label:LABEL_OPTIONAL type_name:\"Bar\" }"
 
1999
    "}",
 
2000
 
 
2001
    "foo.proto: Foo.foo: TYPE: \"Bar\" is not defined.\n");
 
2002
}
 
2003
 
 
2004
TEST_F(ValidationErrorTest, FieldTypeDefinedInUndeclaredDependency) {
 
2005
  BuildFile(
 
2006
    "name: \"bar.proto\" "
 
2007
    "message_type { name: \"Bar\" } ");
 
2008
 
 
2009
  BuildFileWithErrors(
 
2010
    "name: \"foo.proto\" "
 
2011
    "message_type {"
 
2012
    "  name: \"Foo\""
 
2013
    "  field { name:\"foo\" number:1 label:LABEL_OPTIONAL type_name:\"Bar\" }"
 
2014
    "}",
 
2015
    "foo.proto: Foo.foo: TYPE: \"Bar\" seems to be defined in \"bar.proto\", "
 
2016
      "which is not imported by \"foo.proto\".  To use it here, please add the "
 
2017
      "necessary import.\n");
 
2018
}
 
2019
 
 
2020
TEST_F(ValidationErrorTest, SearchMostLocalFirst) {
 
2021
  // The following should produce an error that Bar.Baz is not defined:
 
2022
  //   message Bar { message Baz {} }
 
2023
  //   message Foo {
 
2024
  //     message Bar {
 
2025
  //       // Placing "message Baz{}" here, or removing Foo.Bar altogether,
 
2026
  //       // would fix the error.
 
2027
  //     }
 
2028
  //     optional Bar.Baz baz = 1;
 
2029
  //   }
 
2030
  // An one point the lookup code incorrectly did not produce an error in this
 
2031
  // case, because when looking for Bar.Baz, it would try "Foo.Bar.Baz" first,
 
2032
  // fail, and ten try "Bar.Baz" and succeed, even though "Bar" should actually
 
2033
  // refer to the inner Bar, not the outer one.
 
2034
  BuildFileWithErrors(
 
2035
    "name: \"foo.proto\" "
 
2036
    "message_type {"
 
2037
    "  name: \"Bar\""
 
2038
    "  nested_type { name: \"Baz\" }"
 
2039
    "}"
 
2040
    "message_type {"
 
2041
    "  name: \"Foo\""
 
2042
    "  nested_type { name: \"Bar\" }"
 
2043
    "  field { name:\"baz\" number:1 label:LABEL_OPTIONAL"
 
2044
    "          type_name:\"Bar.Baz\" }"
 
2045
    "}",
 
2046
 
 
2047
    "foo.proto: Foo.baz: TYPE: \"Bar.Baz\" is not defined.\n");
 
2048
}
 
2049
 
 
2050
TEST_F(ValidationErrorTest, PackageOriginallyDeclaredInTransitiveDependent) {
 
2051
  // Imagine we have the following:
 
2052
  //
 
2053
  // foo.proto:
 
2054
  //   package foo.bar;
 
2055
  // bar.proto:
 
2056
  //   package foo.bar;
 
2057
  //   import "foo.proto";
 
2058
  //   message Bar {}
 
2059
  // baz.proto:
 
2060
  //   package foo;
 
2061
  //   import "bar.proto"
 
2062
  //   message Baz { optional bar.Bar qux = 1; }
 
2063
  //
 
2064
  // When validating baz.proto, we will look up "bar.Bar".  As part of this
 
2065
  // lookup, we first lookup "bar" then try to find "Bar" within it.  "bar"
 
2066
  // should resolve to "foo.bar".  Note, though, that "foo.bar" was originally
 
2067
  // defined in foo.proto, which is not a direct dependency of baz.proto.  The
 
2068
  // implementation of FindSymbol() normally only returns symbols in direct
 
2069
  // dependencies, not indirect ones.  This test insures that this does not
 
2070
  // prevent it from finding "foo.bar".
 
2071
 
 
2072
  BuildFile(
 
2073
    "name: \"foo.proto\" "
 
2074
    "package: \"foo.bar\" ");
 
2075
  BuildFile(
 
2076
    "name: \"bar.proto\" "
 
2077
    "package: \"foo.bar\" "
 
2078
    "dependency: \"foo.proto\" "
 
2079
    "message_type { name: \"Bar\" }");
 
2080
  BuildFile(
 
2081
    "name: \"baz.proto\" "
 
2082
    "package: \"foo\" "
 
2083
    "dependency: \"bar.proto\" "
 
2084
    "message_type { "
 
2085
    "  name: \"Baz\" "
 
2086
    "  field { name:\"qux\" number:1 label:LABEL_OPTIONAL "
 
2087
    "          type_name:\"bar.Bar\" }"
 
2088
    "}");
 
2089
}
 
2090
 
 
2091
TEST_F(ValidationErrorTest, FieldTypeNotAType) {
 
2092
  BuildFileWithErrors(
 
2093
    "name: \"foo.proto\" "
 
2094
    "message_type {"
 
2095
    "  name: \"Foo\""
 
2096
    "  field { name:\"foo\" number:1 label:LABEL_OPTIONAL type_name:\"bar\" }"
 
2097
    "  field { name:\"bar\" number:2 label:LABEL_OPTIONAL type:TYPE_INT32 }"
 
2098
    "}",
 
2099
 
 
2100
    "foo.proto: Foo.foo: TYPE: \"bar\" is not a type.\n");
 
2101
}
 
2102
 
 
2103
TEST_F(ValidationErrorTest, EnumFieldTypeIsMessage) {
 
2104
  BuildFileWithErrors(
 
2105
    "name: \"foo.proto\" "
 
2106
    "message_type { name: \"Bar\" } "
 
2107
    "message_type {"
 
2108
    "  name: \"Foo\""
 
2109
    "  field { name:\"foo\" number:1 label:LABEL_OPTIONAL type:TYPE_ENUM"
 
2110
    "          type_name:\"Bar\" }"
 
2111
    "}",
 
2112
 
 
2113
    "foo.proto: Foo.foo: TYPE: \"Bar\" is not an enum type.\n");
 
2114
}
 
2115
 
 
2116
TEST_F(ValidationErrorTest, MessageFieldTypeIsEnum) {
 
2117
  BuildFileWithErrors(
 
2118
    "name: \"foo.proto\" "
 
2119
    "enum_type { name: \"Bar\" value { name:\"DUMMY\" number:0 } } "
 
2120
    "message_type {"
 
2121
    "  name: \"Foo\""
 
2122
    "  field { name:\"foo\" number:1 label:LABEL_OPTIONAL type:TYPE_MESSAGE"
 
2123
    "          type_name:\"Bar\" }"
 
2124
    "}",
 
2125
 
 
2126
    "foo.proto: Foo.foo: TYPE: \"Bar\" is not a message type.\n");
 
2127
}
 
2128
 
 
2129
TEST_F(ValidationErrorTest, BadEnumDefaultValue) {
 
2130
  BuildFileWithErrors(
 
2131
    "name: \"foo.proto\" "
 
2132
    "enum_type { name: \"Bar\" value { name:\"DUMMY\" number:0 } } "
 
2133
    "message_type {"
 
2134
    "  name: \"Foo\""
 
2135
    "  field { name:\"foo\" number:1 label:LABEL_OPTIONAL type_name:\"Bar\""
 
2136
    "          default_value:\"NO_SUCH_VALUE\" }"
 
2137
    "}",
 
2138
 
 
2139
    "foo.proto: Foo.foo: DEFAULT_VALUE: Enum type \"Bar\" has no value named "
 
2140
      "\"NO_SUCH_VALUE\".\n");
 
2141
}
 
2142
 
 
2143
TEST_F(ValidationErrorTest, PrimitiveWithTypeName) {
 
2144
  BuildFileWithErrors(
 
2145
    "name: \"foo.proto\" "
 
2146
    "message_type {"
 
2147
    "  name: \"Foo\""
 
2148
    "  field { name:\"foo\" number:1 label:LABEL_OPTIONAL type:TYPE_INT32"
 
2149
    "          type_name:\"Foo\" }"
 
2150
    "}",
 
2151
 
 
2152
    "foo.proto: Foo.foo: TYPE: Field with primitive type has type_name.\n");
 
2153
}
 
2154
 
 
2155
TEST_F(ValidationErrorTest, NonPrimitiveWithoutTypeName) {
 
2156
  BuildFileWithErrors(
 
2157
    "name: \"foo.proto\" "
 
2158
    "message_type {"
 
2159
    "  name: \"Foo\""
 
2160
    "  field { name:\"foo\" number:1 label:LABEL_OPTIONAL type:TYPE_MESSAGE }"
 
2161
    "}",
 
2162
 
 
2163
    "foo.proto: Foo.foo: TYPE: Field with message or enum type missing "
 
2164
      "type_name.\n");
 
2165
}
 
2166
 
 
2167
TEST_F(ValidationErrorTest, InputTypeNotDefined) {
 
2168
  BuildFileWithErrors(
 
2169
    "name: \"foo.proto\" "
 
2170
    "message_type { name: \"Foo\" } "
 
2171
    "service {"
 
2172
    "  name: \"TestService\""
 
2173
    "  method { name: \"A\" input_type: \"Bar\" output_type: \"Foo\" }"
 
2174
    "}",
 
2175
 
 
2176
    "foo.proto: TestService.A: INPUT_TYPE: \"Bar\" is not defined.\n");
 
2177
}
 
2178
 
 
2179
TEST_F(ValidationErrorTest, InputTypeNotAMessage) {
 
2180
  BuildFileWithErrors(
 
2181
    "name: \"foo.proto\" "
 
2182
    "message_type { name: \"Foo\" } "
 
2183
    "enum_type { name: \"Bar\" value { name:\"DUMMY\" number:0 } } "
 
2184
    "service {"
 
2185
    "  name: \"TestService\""
 
2186
    "  method { name: \"A\" input_type: \"Bar\" output_type: \"Foo\" }"
 
2187
    "}",
 
2188
 
 
2189
    "foo.proto: TestService.A: INPUT_TYPE: \"Bar\" is not a message type.\n");
 
2190
}
 
2191
 
 
2192
TEST_F(ValidationErrorTest, OutputTypeNotDefined) {
 
2193
  BuildFileWithErrors(
 
2194
    "name: \"foo.proto\" "
 
2195
    "message_type { name: \"Foo\" } "
 
2196
    "service {"
 
2197
    "  name: \"TestService\""
 
2198
    "  method { name: \"A\" input_type: \"Foo\" output_type: \"Bar\" }"
 
2199
    "}",
 
2200
 
 
2201
    "foo.proto: TestService.A: OUTPUT_TYPE: \"Bar\" is not defined.\n");
 
2202
}
 
2203
 
 
2204
TEST_F(ValidationErrorTest, OutputTypeNotAMessage) {
 
2205
  BuildFileWithErrors(
 
2206
    "name: \"foo.proto\" "
 
2207
    "message_type { name: \"Foo\" } "
 
2208
    "enum_type { name: \"Bar\" value { name:\"DUMMY\" number:0 } } "
 
2209
    "service {"
 
2210
    "  name: \"TestService\""
 
2211
    "  method { name: \"A\" input_type: \"Foo\" output_type: \"Bar\" }"
 
2212
    "}",
 
2213
 
 
2214
    "foo.proto: TestService.A: OUTPUT_TYPE: \"Bar\" is not a message type.\n");
 
2215
}
 
2216
 
 
2217
TEST_F(ValidationErrorTest, RollbackAfterError) {
 
2218
  // Build a file which contains every kind of construct but references an
 
2219
  // undefined type.  All these constructs will be added to the symbol table
 
2220
  // before the undefined type error is noticed.  The DescriptorPool will then
 
2221
  // have to roll everything back.
 
2222
  BuildFileWithErrors(
 
2223
    "name: \"foo.proto\" "
 
2224
    "message_type {"
 
2225
    "  name: \"TestMessage\""
 
2226
    "  field { name:\"foo\" label:LABEL_OPTIONAL type:TYPE_INT32 number:1 }"
 
2227
    "} "
 
2228
    "enum_type {"
 
2229
    "  name: \"TestEnum\""
 
2230
    "  value { name:\"BAR\" number:1 }"
 
2231
    "} "
 
2232
    "service {"
 
2233
    "  name: \"TestService\""
 
2234
    "  method {"
 
2235
    "    name: \"Baz\""
 
2236
    "    input_type: \"NoSuchType\""    // error
 
2237
    "    output_type: \"TestMessage\""
 
2238
    "  }"
 
2239
    "}",
 
2240
 
 
2241
    "foo.proto: TestService.Baz: INPUT_TYPE: \"NoSuchType\" is not defined.\n");
 
2242
 
 
2243
  // Make sure that if we build the same file again with the error fixed,
 
2244
  // it works.  If the above rollback was incomplete, then some symbols will
 
2245
  // be left defined, and this second attempt will fail since it tries to
 
2246
  // re-define the same symbols.
 
2247
  BuildFile(
 
2248
    "name: \"foo.proto\" "
 
2249
    "message_type {"
 
2250
    "  name: \"TestMessage\""
 
2251
    "  field { name:\"foo\" label:LABEL_OPTIONAL type:TYPE_INT32 number:1 }"
 
2252
    "} "
 
2253
    "enum_type {"
 
2254
    "  name: \"TestEnum\""
 
2255
    "  value { name:\"BAR\" number:1 }"
 
2256
    "} "
 
2257
    "service {"
 
2258
    "  name: \"TestService\""
 
2259
    "  method { name:\"Baz\""
 
2260
    "           input_type:\"TestMessage\""
 
2261
    "           output_type:\"TestMessage\" }"
 
2262
    "}");
 
2263
}
 
2264
 
 
2265
TEST_F(ValidationErrorTest, ErrorsReportedToLogError) {
 
2266
  // Test that errors are reported to GOOGLE_LOG(ERROR) if no error collector is
 
2267
  // provided.
 
2268
 
 
2269
  FileDescriptorProto file_proto;
 
2270
  ASSERT_TRUE(TextFormat::ParseFromString(
 
2271
    "name: \"foo.proto\" "
 
2272
    "message_type { name: \"Foo\" } "
 
2273
    "message_type { name: \"Foo\" } ",
 
2274
    &file_proto));
 
2275
 
 
2276
  vector<string> errors;
 
2277
 
 
2278
  {
 
2279
    ScopedMemoryLog log;
 
2280
    EXPECT_TRUE(pool_.BuildFile(file_proto) == NULL);
 
2281
    errors = log.GetMessages(ERROR);
 
2282
  }
 
2283
 
 
2284
  ASSERT_EQ(2, errors.size());
 
2285
 
 
2286
  EXPECT_EQ("Invalid proto descriptor for file \"foo.proto\":", errors[0]);
 
2287
  EXPECT_EQ("  Foo: \"Foo\" is already defined.", errors[1]);
 
2288
}
 
2289
 
 
2290
// ===================================================================
 
2291
// DescriptorDatabase
 
2292
 
 
2293
static void AddToDatabase(SimpleDescriptorDatabase* database,
 
2294
                          const char* file_text) {
 
2295
  FileDescriptorProto file_proto;
 
2296
  EXPECT_TRUE(TextFormat::ParseFromString(file_text, &file_proto));
 
2297
  database->Add(file_proto);
 
2298
}
 
2299
 
 
2300
class DatabaseBackedPoolTest : public testing::Test {
 
2301
 protected:
 
2302
  DatabaseBackedPoolTest() {}
 
2303
 
 
2304
  SimpleDescriptorDatabase database_;
 
2305
 
 
2306
  virtual void SetUp() {
 
2307
    AddToDatabase(&database_,
 
2308
      "name: \"foo.proto\" "
 
2309
      "message_type { name:\"Foo\" extension_range { start: 1 end: 100 } } "
 
2310
      "enum_type { name:\"TestEnum\" value { name:\"DUMMY\" number:0 } } "
 
2311
      "service { name:\"TestService\" } ");
 
2312
    AddToDatabase(&database_,
 
2313
      "name: \"bar.proto\" "
 
2314
      "dependency: \"foo.proto\" "
 
2315
      "message_type { name:\"Bar\" } "
 
2316
      "extension { name:\"foo_ext\" extendee: \".Foo\" number:5 "
 
2317
      "            label:LABEL_OPTIONAL type:TYPE_INT32 } ");
 
2318
  }
 
2319
 
 
2320
  // We can't inject a file containing errors into a DescriptorPool, so we
 
2321
  // need an actual mock DescriptorDatabase to test errors.
 
2322
  class ErrorDescriptorDatabase : public DescriptorDatabase {
 
2323
   public:
 
2324
    ErrorDescriptorDatabase() {}
 
2325
    ~ErrorDescriptorDatabase() {}
 
2326
 
 
2327
    // implements DescriptorDatabase ---------------------------------
 
2328
    bool FindFileByName(const string& filename,
 
2329
                        FileDescriptorProto* output) {
 
2330
      // error.proto and error2.proto cyclically import each other.
 
2331
      if (filename == "error.proto") {
 
2332
        output->Clear();
 
2333
        output->set_name("error.proto");
 
2334
        output->add_dependency("error2.proto");
 
2335
        return true;
 
2336
      } else if (filename == "error2.proto") {
 
2337
        output->Clear();
 
2338
        output->set_name("error2.proto");
 
2339
        output->add_dependency("error.proto");
 
2340
        return true;
 
2341
      } else {
 
2342
        return false;
 
2343
      }
 
2344
    }
 
2345
    bool FindFileContainingSymbol(const string& symbol_name,
 
2346
                                  FileDescriptorProto* output) {
 
2347
      return false;
 
2348
    }
 
2349
    bool FindFileContainingExtension(const string& containing_type,
 
2350
                                     int field_number,
 
2351
                                     FileDescriptorProto* output) {
 
2352
      return false;
 
2353
    }
 
2354
  };
 
2355
 
 
2356
  // A DescriptorDatabase that counts how many times each method has been
 
2357
  // called and forwards to some other DescriptorDatabase.
 
2358
  class CallCountingDatabase : public DescriptorDatabase {
 
2359
   public:
 
2360
    CallCountingDatabase(DescriptorDatabase* wrapped_db)
 
2361
      : wrapped_db_(wrapped_db) {
 
2362
      Clear();
 
2363
    }
 
2364
    ~CallCountingDatabase() {}
 
2365
 
 
2366
    DescriptorDatabase* wrapped_db_;
 
2367
 
 
2368
    int call_count_;
 
2369
 
 
2370
    void Clear() {
 
2371
      call_count_ = 0;
 
2372
    }
 
2373
 
 
2374
    // implements DescriptorDatabase ---------------------------------
 
2375
    bool FindFileByName(const string& filename,
 
2376
                        FileDescriptorProto* output) {
 
2377
      ++call_count_;
 
2378
      return wrapped_db_->FindFileByName(filename, output);
 
2379
    }
 
2380
    bool FindFileContainingSymbol(const string& symbol_name,
 
2381
                                  FileDescriptorProto* output) {
 
2382
      ++call_count_;
 
2383
      return wrapped_db_->FindFileContainingSymbol(symbol_name, output);
 
2384
    }
 
2385
    bool FindFileContainingExtension(const string& containing_type,
 
2386
                                     int field_number,
 
2387
                                     FileDescriptorProto* output) {
 
2388
      ++call_count_;
 
2389
      return wrapped_db_->FindFileContainingExtension(
 
2390
        containing_type, field_number, output);
 
2391
    }
 
2392
  };
 
2393
 
 
2394
  // A DescriptorDatabase which falsely always returns foo.proto when searching
 
2395
  // for any symbol or extension number.  This shouldn't cause the
 
2396
  // DescriptorPool to reload foo.proto if it is already loaded.
 
2397
  class FalsePositiveDatabase : public DescriptorDatabase {
 
2398
   public:
 
2399
    FalsePositiveDatabase(DescriptorDatabase* wrapped_db)
 
2400
      : wrapped_db_(wrapped_db) {}
 
2401
    ~FalsePositiveDatabase() {}
 
2402
 
 
2403
    DescriptorDatabase* wrapped_db_;
 
2404
 
 
2405
    // implements DescriptorDatabase ---------------------------------
 
2406
    bool FindFileByName(const string& filename,
 
2407
                        FileDescriptorProto* output) {
 
2408
      return wrapped_db_->FindFileByName(filename, output);
 
2409
    }
 
2410
    bool FindFileContainingSymbol(const string& symbol_name,
 
2411
                                  FileDescriptorProto* output) {
 
2412
      return FindFileByName("foo.proto", output);
 
2413
    }
 
2414
    bool FindFileContainingExtension(const string& containing_type,
 
2415
                                     int field_number,
 
2416
                                     FileDescriptorProto* output) {
 
2417
      return FindFileByName("foo.proto", output);
 
2418
    }
 
2419
  };
 
2420
};
 
2421
 
 
2422
TEST_F(DatabaseBackedPoolTest, FindFileByName) {
 
2423
  DescriptorPool pool(&database_);
 
2424
 
 
2425
  const FileDescriptor* foo = pool.FindFileByName("foo.proto");
 
2426
  ASSERT_TRUE(foo != NULL);
 
2427
  EXPECT_EQ("foo.proto", foo->name());
 
2428
  ASSERT_EQ(1, foo->message_type_count());
 
2429
  EXPECT_EQ("Foo", foo->message_type(0)->name());
 
2430
 
 
2431
  EXPECT_EQ(foo, pool.FindFileByName("foo.proto"));
 
2432
 
 
2433
  EXPECT_TRUE(pool.FindFileByName("no_such_file.proto") == NULL);
 
2434
}
 
2435
 
 
2436
TEST_F(DatabaseBackedPoolTest, FindDependencyBeforeDependent) {
 
2437
  DescriptorPool pool(&database_);
 
2438
 
 
2439
  const FileDescriptor* foo = pool.FindFileByName("foo.proto");
 
2440
  ASSERT_TRUE(foo != NULL);
 
2441
  EXPECT_EQ("foo.proto", foo->name());
 
2442
  ASSERT_EQ(1, foo->message_type_count());
 
2443
  EXPECT_EQ("Foo", foo->message_type(0)->name());
 
2444
 
 
2445
  const FileDescriptor* bar = pool.FindFileByName("bar.proto");
 
2446
  ASSERT_TRUE(bar != NULL);
 
2447
  EXPECT_EQ("bar.proto", bar->name());
 
2448
  ASSERT_EQ(1, bar->message_type_count());
 
2449
  EXPECT_EQ("Bar", bar->message_type(0)->name());
 
2450
 
 
2451
  ASSERT_EQ(1, bar->dependency_count());
 
2452
  EXPECT_EQ(foo, bar->dependency(0));
 
2453
}
 
2454
 
 
2455
TEST_F(DatabaseBackedPoolTest, FindDependentBeforeDependency) {
 
2456
  DescriptorPool pool(&database_);
 
2457
 
 
2458
  const FileDescriptor* bar = pool.FindFileByName("bar.proto");
 
2459
  ASSERT_TRUE(bar != NULL);
 
2460
  EXPECT_EQ("bar.proto", bar->name());
 
2461
  ASSERT_EQ(1, bar->message_type_count());
 
2462
  ASSERT_EQ("Bar", bar->message_type(0)->name());
 
2463
 
 
2464
  const FileDescriptor* foo = pool.FindFileByName("foo.proto");
 
2465
  ASSERT_TRUE(foo != NULL);
 
2466
  EXPECT_EQ("foo.proto", foo->name());
 
2467
  ASSERT_EQ(1, foo->message_type_count());
 
2468
  ASSERT_EQ("Foo", foo->message_type(0)->name());
 
2469
 
 
2470
  ASSERT_EQ(1, bar->dependency_count());
 
2471
  EXPECT_EQ(foo, bar->dependency(0));
 
2472
}
 
2473
 
 
2474
TEST_F(DatabaseBackedPoolTest, FindFileContainingSymbol) {
 
2475
  DescriptorPool pool(&database_);
 
2476
 
 
2477
  const FileDescriptor* file = pool.FindFileContainingSymbol("Foo");
 
2478
  ASSERT_TRUE(file != NULL);
 
2479
  EXPECT_EQ("foo.proto", file->name());
 
2480
  EXPECT_EQ(file, pool.FindFileByName("foo.proto"));
 
2481
 
 
2482
  EXPECT_TRUE(pool.FindFileContainingSymbol("NoSuchSymbol") == NULL);
 
2483
}
 
2484
 
 
2485
TEST_F(DatabaseBackedPoolTest, FindMessageTypeByName) {
 
2486
  DescriptorPool pool(&database_);
 
2487
 
 
2488
  const Descriptor* type = pool.FindMessageTypeByName("Foo");
 
2489
  ASSERT_TRUE(type != NULL);
 
2490
  EXPECT_EQ("Foo", type->name());
 
2491
  EXPECT_EQ(type->file(), pool.FindFileByName("foo.proto"));
 
2492
 
 
2493
  EXPECT_TRUE(pool.FindMessageTypeByName("NoSuchType") == NULL);
 
2494
}
 
2495
 
 
2496
TEST_F(DatabaseBackedPoolTest, FindExtensionByNumber) {
 
2497
  DescriptorPool pool(&database_);
 
2498
 
 
2499
  const Descriptor* foo = pool.FindMessageTypeByName("Foo");
 
2500
  ASSERT_TRUE(foo != NULL);
 
2501
 
 
2502
  const FieldDescriptor* extension = pool.FindExtensionByNumber(foo, 5);
 
2503
  ASSERT_TRUE(extension != NULL);
 
2504
  EXPECT_EQ("foo_ext", extension->name());
 
2505
  EXPECT_EQ(extension->file(), pool.FindFileByName("bar.proto"));
 
2506
 
 
2507
  EXPECT_TRUE(pool.FindExtensionByNumber(foo, 12) == NULL);
 
2508
}
 
2509
 
 
2510
TEST_F(DatabaseBackedPoolTest, ErrorWithoutErrorCollector) {
 
2511
  ErrorDescriptorDatabase error_database;
 
2512
  DescriptorPool pool(&error_database);
 
2513
 
 
2514
  vector<string> errors;
 
2515
 
 
2516
  {
 
2517
    ScopedMemoryLog log;
 
2518
    EXPECT_TRUE(pool.FindFileByName("error.proto") == NULL);
 
2519
    errors = log.GetMessages(ERROR);
 
2520
  }
 
2521
 
 
2522
  EXPECT_FALSE(errors.empty());
 
2523
}
 
2524
 
 
2525
TEST_F(DatabaseBackedPoolTest, ErrorWithErrorCollector) {
 
2526
  ErrorDescriptorDatabase error_database;
 
2527
  MockErrorCollector error_collector;
 
2528
  DescriptorPool pool(&error_database, &error_collector);
 
2529
 
 
2530
  EXPECT_TRUE(pool.FindFileByName("error.proto") == NULL);
 
2531
  EXPECT_EQ(
 
2532
    "error.proto: error.proto: OTHER: File recursively imports itself: "
 
2533
      "error.proto -> error2.proto -> error.proto\n"
 
2534
    "error2.proto: error2.proto: OTHER: Import \"error.proto\" was not "
 
2535
      "found or had errors.\n"
 
2536
    "error.proto: error.proto: OTHER: Import \"error2.proto\" was not "
 
2537
      "found or had errors.\n",
 
2538
    error_collector.text_);
 
2539
}
 
2540
 
 
2541
TEST_F(DatabaseBackedPoolTest, UnittestProto) {
 
2542
  // Try to load all of unittest.proto from a DescriptorDatabase.  This should
 
2543
  // thoroughly test all paths through DescriptorBuilder to insure that there
 
2544
  // are no deadlocking problems when pool_->mutex_ is non-NULL.
 
2545
  const FileDescriptor* original_file =
 
2546
    protobuf_unittest::TestAllTypes::descriptor()->file();
 
2547
 
 
2548
  DescriptorPoolDatabase database(*DescriptorPool::generated_pool());
 
2549
  DescriptorPool pool(&database);
 
2550
  const FileDescriptor* file_from_database =
 
2551
    pool.FindFileByName(original_file->name());
 
2552
 
 
2553
  ASSERT_TRUE(file_from_database != NULL);
 
2554
 
 
2555
  FileDescriptorProto original_file_proto;
 
2556
  original_file->CopyTo(&original_file_proto);
 
2557
 
 
2558
  FileDescriptorProto file_from_database_proto;
 
2559
  file_from_database->CopyTo(&file_from_database_proto);
 
2560
 
 
2561
  EXPECT_EQ(original_file_proto.DebugString(),
 
2562
            file_from_database_proto.DebugString());
 
2563
}
 
2564
 
 
2565
TEST_F(DatabaseBackedPoolTest, DoesntRetryDbUnnecessarily) {
 
2566
  // Searching for a child of an existing descriptor should never fall back
 
2567
  // to the DescriptorDatabase even if it isn't found, because we know all
 
2568
  // children are already loaded.
 
2569
  CallCountingDatabase call_counter(&database_);
 
2570
  DescriptorPool pool(&call_counter);
 
2571
 
 
2572
  const FileDescriptor* file = pool.FindFileByName("foo.proto");
 
2573
  ASSERT_TRUE(file != NULL);
 
2574
  const Descriptor* foo = pool.FindMessageTypeByName("Foo");
 
2575
  ASSERT_TRUE(foo != NULL);
 
2576
  const EnumDescriptor* test_enum = pool.FindEnumTypeByName("TestEnum");
 
2577
  ASSERT_TRUE(test_enum != NULL);
 
2578
  const ServiceDescriptor* test_service = pool.FindServiceByName("TestService");
 
2579
  ASSERT_TRUE(test_service != NULL);
 
2580
 
 
2581
  EXPECT_NE(0, call_counter.call_count_);
 
2582
  call_counter.Clear();
 
2583
 
 
2584
  EXPECT_TRUE(foo->FindFieldByName("no_such_field") == NULL);
 
2585
  EXPECT_TRUE(foo->FindExtensionByName("no_such_extension") == NULL);
 
2586
  EXPECT_TRUE(foo->FindNestedTypeByName("NoSuchMessageType") == NULL);
 
2587
  EXPECT_TRUE(foo->FindEnumTypeByName("NoSuchEnumType") == NULL);
 
2588
  EXPECT_TRUE(foo->FindEnumValueByName("NO_SUCH_VALUE") == NULL);
 
2589
  EXPECT_TRUE(test_enum->FindValueByName("NO_SUCH_VALUE") == NULL);
 
2590
  EXPECT_TRUE(test_service->FindMethodByName("NoSuchMethod") == NULL);
 
2591
 
 
2592
  EXPECT_TRUE(file->FindMessageTypeByName("NoSuchMessageType") == NULL);
 
2593
  EXPECT_TRUE(file->FindEnumTypeByName("NoSuchEnumType") == NULL);
 
2594
  EXPECT_TRUE(file->FindEnumValueByName("NO_SUCH_VALUE") == NULL);
 
2595
  EXPECT_TRUE(file->FindServiceByName("NO_SUCH_VALUE") == NULL);
 
2596
  EXPECT_TRUE(file->FindExtensionByName("no_such_extension") == NULL);
 
2597
  EXPECT_EQ(0, call_counter.call_count_);
 
2598
}
 
2599
 
 
2600
TEST_F(DatabaseBackedPoolTest, DoesntReloadFilesUncesessarily) {
 
2601
  // If FindFileContainingSymbol() or FindFileContainingExtension() return a
 
2602
  // file that is already in the DescriptorPool, it should not attempt to
 
2603
  // reload the file.
 
2604
  FalsePositiveDatabase false_positive_database(&database_);
 
2605
  MockErrorCollector error_collector;
 
2606
  DescriptorPool pool(&false_positive_database, &error_collector);
 
2607
 
 
2608
  // First make sure foo.proto is loaded.
 
2609
  const Descriptor* foo = pool.FindMessageTypeByName("Foo");
 
2610
  ASSERT_TRUE(foo != NULL);
 
2611
 
 
2612
  // Try inducing false positives.
 
2613
  EXPECT_TRUE(pool.FindMessageTypeByName("NoSuchSymbol") == NULL);
 
2614
  EXPECT_TRUE(pool.FindExtensionByNumber(foo, 22) == NULL);
 
2615
 
 
2616
  // No errors should have been reported.  (If foo.proto was incorrectly
 
2617
  // loaded multiple times, errors would have been reported.)
 
2618
  EXPECT_EQ("", error_collector.text_);
 
2619
}
 
2620
 
 
2621
TEST_F(DatabaseBackedPoolTest, DoesntReloadKnownBadFiles) {
 
2622
  ErrorDescriptorDatabase error_database;
 
2623
  MockErrorCollector error_collector;
 
2624
  DescriptorPool pool(&error_database, &error_collector);
 
2625
 
 
2626
  EXPECT_TRUE(pool.FindFileByName("error.proto") == NULL);
 
2627
  error_collector.text_.clear();
 
2628
  EXPECT_TRUE(pool.FindFileByName("error.proto") == NULL);
 
2629
  EXPECT_EQ("", error_collector.text_);
 
2630
}
 
2631
 
 
2632
}  // anonymous namespace
 
2633
}  // namespace protobuf
 
2634
}  // namespace google