blob: 1c03c4438efdef98c56b972dd6f7633c100727d5 [file] [log] [blame]
temporal40ee5512008-07-10 02:12:20 +00001// Protocol Buffers - Google's data interchange format
kenton@google.com24bf56f2008-09-24 20:31:01 +00002// Copyright 2008 Google Inc. All rights reserved.
Feng Xiaoe4288622014-10-01 16:26:23 -07003// https://developers.google.com/protocol-buffers/
temporal40ee5512008-07-10 02:12:20 +00004//
kenton@google.com24bf56f2008-09-24 20:31:01 +00005// Redistribution and use in source and binary forms, with or without
6// modification, are permitted provided that the following conditions are
7// met:
temporal40ee5512008-07-10 02:12:20 +00008//
kenton@google.com24bf56f2008-09-24 20:31:01 +00009// * Redistributions of source code must retain the above copyright
10// notice, this list of conditions and the following disclaimer.
11// * Redistributions in binary form must reproduce the above
12// copyright notice, this list of conditions and the following disclaimer
13// in the documentation and/or other materials provided with the
14// distribution.
15// * Neither the name of Google Inc. nor the names of its
16// contributors may be used to endorse or promote products derived from
17// this software without specific prior written permission.
temporal40ee5512008-07-10 02:12:20 +000018//
kenton@google.com24bf56f2008-09-24 20:31:01 +000019// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
temporal40ee5512008-07-10 02:12:20 +000030
31// Author: kenton@google.com (Kenton Varda)
32// Based on original Protocol Buffers design by
33// Sanjay Ghemawat, Jeff Dean, and others.
34//
35// This file makes extensive use of RFC 3092. :)
36
kenton@google.com50ede8b2009-04-27 22:28:10 +000037#include <algorithm>
38
temporal40ee5512008-07-10 02:12:20 +000039#include <google/protobuf/descriptor_database.h>
40#include <google/protobuf/descriptor.h>
41#include <google/protobuf/descriptor.pb.h>
42#include <google/protobuf/text_format.h>
43#include <google/protobuf/stubs/strutil.h>
44
45#include <google/protobuf/stubs/common.h>
46#include <google/protobuf/testing/googletest.h>
47#include <gtest/gtest.h>
48
49namespace google {
50namespace protobuf {
51namespace {
52
temporal40ee5512008-07-10 02:12:20 +000053static void AddToDatabase(SimpleDescriptorDatabase* database,
54 const char* file_text) {
55 FileDescriptorProto file_proto;
56 EXPECT_TRUE(TextFormat::ParseFromString(file_text, &file_proto));
57 database->Add(file_proto);
58}
59
60static void ExpectContainsType(const FileDescriptorProto& proto,
61 const string& type_name) {
62 for (int i = 0; i < proto.message_type_size(); i++) {
63 if (proto.message_type(i).name() == type_name) return;
64 }
65 ADD_FAILURE() << "\"" << proto.name()
66 << "\" did not contain expected type \""
67 << type_name << "\".";
68}
69
70// ===================================================================
71
kenton@google.comd37d46d2009-04-25 02:53:47 +000072#if GTEST_HAS_PARAM_TEST
73
74// SimpleDescriptorDatabase, EncodedDescriptorDatabase, and
75// DescriptorPoolDatabase call for very similar tests. Instead of writing
76// three nearly-identical sets of tests, we use parameterized tests to apply
77// the same code to all three.
78
79// The parameterized test runs against a DescriptarDatabaseTestCase. We have
80// implementations for each of the three classes we want to test.
81class DescriptorDatabaseTestCase {
82 public:
83 virtual ~DescriptorDatabaseTestCase() {}
84
85 virtual DescriptorDatabase* GetDatabase() = 0;
86 virtual bool AddToDatabase(const FileDescriptorProto& file) = 0;
87};
88
89// Factory function type.
90typedef DescriptorDatabaseTestCase* DescriptorDatabaseTestCaseFactory();
91
92// Specialization for SimpleDescriptorDatabase.
93class SimpleDescriptorDatabaseTestCase : public DescriptorDatabaseTestCase {
94 public:
95 static DescriptorDatabaseTestCase* New() {
96 return new SimpleDescriptorDatabaseTestCase;
97 }
98
99 virtual ~SimpleDescriptorDatabaseTestCase() {}
100
101 virtual DescriptorDatabase* GetDatabase() {
102 return &database_;
103 }
104 virtual bool AddToDatabase(const FileDescriptorProto& file) {
105 return database_.Add(file);
106 }
107
108 private:
109 SimpleDescriptorDatabase database_;
110};
111
112// Specialization for EncodedDescriptorDatabase.
113class EncodedDescriptorDatabaseTestCase : public DescriptorDatabaseTestCase {
114 public:
115 static DescriptorDatabaseTestCase* New() {
116 return new EncodedDescriptorDatabaseTestCase;
117 }
118
119 virtual ~EncodedDescriptorDatabaseTestCase() {}
120
121 virtual DescriptorDatabase* GetDatabase() {
122 return &database_;
123 }
124 virtual bool AddToDatabase(const FileDescriptorProto& file) {
125 string data;
126 file.SerializeToString(&data);
127 return database_.AddCopy(data.data(), data.size());
128 }
129
130 private:
131 EncodedDescriptorDatabase database_;
132};
133
134// Specialization for DescriptorPoolDatabase.
135class DescriptorPoolDatabaseTestCase : public DescriptorDatabaseTestCase {
136 public:
137 static DescriptorDatabaseTestCase* New() {
138 return new EncodedDescriptorDatabaseTestCase;
139 }
140
141 DescriptorPoolDatabaseTestCase() : database_(pool_) {}
142 virtual ~DescriptorPoolDatabaseTestCase() {}
143
144 virtual DescriptorDatabase* GetDatabase() {
145 return &database_;
146 }
147 virtual bool AddToDatabase(const FileDescriptorProto& file) {
148 return pool_.BuildFile(file);
149 }
150
151 private:
152 DescriptorPool pool_;
153 DescriptorPoolDatabase database_;
154};
155
156// -------------------------------------------------------------------
157
158class DescriptorDatabaseTest
159 : public testing::TestWithParam<DescriptorDatabaseTestCaseFactory*> {
160 protected:
161 virtual void SetUp() {
162 test_case_.reset(GetParam()());
163 database_ = test_case_->GetDatabase();
164 }
165
166 void AddToDatabase(const char* file_descriptor_text) {
167 FileDescriptorProto file_proto;
168 EXPECT_TRUE(TextFormat::ParseFromString(file_descriptor_text, &file_proto));
169 EXPECT_TRUE(test_case_->AddToDatabase(file_proto));
170 }
171
172 void AddToDatabaseWithError(const char* file_descriptor_text) {
173 FileDescriptorProto file_proto;
174 EXPECT_TRUE(TextFormat::ParseFromString(file_descriptor_text, &file_proto));
175 EXPECT_FALSE(test_case_->AddToDatabase(file_proto));
176 }
177
178 scoped_ptr<DescriptorDatabaseTestCase> test_case_;
179 DescriptorDatabase* database_;
180};
181
182TEST_P(DescriptorDatabaseTest, FindFileByName) {
183 AddToDatabase(
temporal40ee5512008-07-10 02:12:20 +0000184 "name: \"foo.proto\" "
185 "message_type { name:\"Foo\" }");
kenton@google.comd37d46d2009-04-25 02:53:47 +0000186 AddToDatabase(
temporal40ee5512008-07-10 02:12:20 +0000187 "name: \"bar.proto\" "
188 "message_type { name:\"Bar\" }");
189
190 {
191 FileDescriptorProto file;
kenton@google.comd37d46d2009-04-25 02:53:47 +0000192 EXPECT_TRUE(database_->FindFileByName("foo.proto", &file));
temporal40ee5512008-07-10 02:12:20 +0000193 EXPECT_EQ("foo.proto", file.name());
194 ExpectContainsType(file, "Foo");
195 }
196
197 {
198 FileDescriptorProto file;
kenton@google.comd37d46d2009-04-25 02:53:47 +0000199 EXPECT_TRUE(database_->FindFileByName("bar.proto", &file));
temporal40ee5512008-07-10 02:12:20 +0000200 EXPECT_EQ("bar.proto", file.name());
201 ExpectContainsType(file, "Bar");
202 }
203
204 {
205 // Fails to find undefined files.
206 FileDescriptorProto file;
kenton@google.comd37d46d2009-04-25 02:53:47 +0000207 EXPECT_FALSE(database_->FindFileByName("baz.proto", &file));
temporal40ee5512008-07-10 02:12:20 +0000208 }
209}
210
kenton@google.comd37d46d2009-04-25 02:53:47 +0000211TEST_P(DescriptorDatabaseTest, FindFileContainingSymbol) {
212 AddToDatabase(
temporal40ee5512008-07-10 02:12:20 +0000213 "name: \"foo.proto\" "
214 "message_type { "
215 " name: \"Foo\" "
216 " field { name:\"qux\" }"
217 " nested_type { name: \"Grault\" } "
218 " enum_type { name: \"Garply\" } "
219 "} "
220 "enum_type { "
221 " name: \"Waldo\" "
222 " value { name:\"FRED\" } "
223 "} "
224 "extension { name: \"plugh\" } "
225 "service { "
226 " name: \"Xyzzy\" "
227 " method { name: \"Thud\" } "
228 "}"
229 );
kenton@google.comd37d46d2009-04-25 02:53:47 +0000230 AddToDatabase(
temporal40ee5512008-07-10 02:12:20 +0000231 "name: \"bar.proto\" "
232 "package: \"corge\" "
233 "message_type { name: \"Bar\" }");
234
235 {
236 FileDescriptorProto file;
kenton@google.comd37d46d2009-04-25 02:53:47 +0000237 EXPECT_TRUE(database_->FindFileContainingSymbol("Foo", &file));
temporal40ee5512008-07-10 02:12:20 +0000238 EXPECT_EQ("foo.proto", file.name());
239 }
240
241 {
242 // Can find fields.
243 FileDescriptorProto file;
kenton@google.comd37d46d2009-04-25 02:53:47 +0000244 EXPECT_TRUE(database_->FindFileContainingSymbol("Foo.qux", &file));
temporal40ee5512008-07-10 02:12:20 +0000245 EXPECT_EQ("foo.proto", file.name());
246 }
247
248 {
249 // Can find nested types.
250 FileDescriptorProto file;
kenton@google.comd37d46d2009-04-25 02:53:47 +0000251 EXPECT_TRUE(database_->FindFileContainingSymbol("Foo.Grault", &file));
temporal40ee5512008-07-10 02:12:20 +0000252 EXPECT_EQ("foo.proto", file.name());
253 }
254
255 {
256 // Can find nested enums.
257 FileDescriptorProto file;
kenton@google.comd37d46d2009-04-25 02:53:47 +0000258 EXPECT_TRUE(database_->FindFileContainingSymbol("Foo.Garply", &file));
temporal40ee5512008-07-10 02:12:20 +0000259 EXPECT_EQ("foo.proto", file.name());
260 }
261
262 {
263 // Can find enum types.
264 FileDescriptorProto file;
kenton@google.comd37d46d2009-04-25 02:53:47 +0000265 EXPECT_TRUE(database_->FindFileContainingSymbol("Waldo", &file));
temporal40ee5512008-07-10 02:12:20 +0000266 EXPECT_EQ("foo.proto", file.name());
267 }
268
269 {
270 // Can find enum values.
271 FileDescriptorProto file;
kenton@google.comd37d46d2009-04-25 02:53:47 +0000272 EXPECT_TRUE(database_->FindFileContainingSymbol("Waldo.FRED", &file));
temporal40ee5512008-07-10 02:12:20 +0000273 EXPECT_EQ("foo.proto", file.name());
274 }
275
276 {
277 // Can find extensions.
278 FileDescriptorProto file;
kenton@google.comd37d46d2009-04-25 02:53:47 +0000279 EXPECT_TRUE(database_->FindFileContainingSymbol("plugh", &file));
temporal40ee5512008-07-10 02:12:20 +0000280 EXPECT_EQ("foo.proto", file.name());
281 }
282
283 {
284 // Can find services.
285 FileDescriptorProto file;
kenton@google.comd37d46d2009-04-25 02:53:47 +0000286 EXPECT_TRUE(database_->FindFileContainingSymbol("Xyzzy", &file));
temporal40ee5512008-07-10 02:12:20 +0000287 EXPECT_EQ("foo.proto", file.name());
288 }
289
290 {
291 // Can find methods.
292 FileDescriptorProto file;
kenton@google.comd37d46d2009-04-25 02:53:47 +0000293 EXPECT_TRUE(database_->FindFileContainingSymbol("Xyzzy.Thud", &file));
temporal40ee5512008-07-10 02:12:20 +0000294 EXPECT_EQ("foo.proto", file.name());
295 }
296
297 {
298 // Can find things in packages.
299 FileDescriptorProto file;
kenton@google.comd37d46d2009-04-25 02:53:47 +0000300 EXPECT_TRUE(database_->FindFileContainingSymbol("corge.Bar", &file));
temporal40ee5512008-07-10 02:12:20 +0000301 EXPECT_EQ("bar.proto", file.name());
302 }
303
304 {
305 // Fails to find undefined symbols.
306 FileDescriptorProto file;
kenton@google.comd37d46d2009-04-25 02:53:47 +0000307 EXPECT_FALSE(database_->FindFileContainingSymbol("Baz", &file));
temporal40ee5512008-07-10 02:12:20 +0000308 }
309
310 {
311 // Names must be fully-qualified.
312 FileDescriptorProto file;
kenton@google.comd37d46d2009-04-25 02:53:47 +0000313 EXPECT_FALSE(database_->FindFileContainingSymbol("Bar", &file));
temporal40ee5512008-07-10 02:12:20 +0000314 }
315}
316
kenton@google.comd37d46d2009-04-25 02:53:47 +0000317TEST_P(DescriptorDatabaseTest, FindFileContainingExtension) {
318 AddToDatabase(
temporal40ee5512008-07-10 02:12:20 +0000319 "name: \"foo.proto\" "
320 "message_type { "
321 " name: \"Foo\" "
322 " extension_range { start: 1 end: 1000 } "
323 " extension { name:\"qux\" label:LABEL_OPTIONAL type:TYPE_INT32 number:5 "
324 " extendee: \".Foo\" }"
325 "}");
kenton@google.comd37d46d2009-04-25 02:53:47 +0000326 AddToDatabase(
temporal40ee5512008-07-10 02:12:20 +0000327 "name: \"bar.proto\" "
328 "package: \"corge\" "
329 "dependency: \"foo.proto\" "
330 "message_type { "
331 " name: \"Bar\" "
332 " extension_range { start: 1 end: 1000 } "
333 "} "
334 "extension { name:\"grault\" extendee: \".Foo\" number:32 } "
335 "extension { name:\"garply\" extendee: \".corge.Bar\" number:70 } "
336 "extension { name:\"waldo\" extendee: \"Bar\" number:56 } ");
337
338 {
339 FileDescriptorProto file;
kenton@google.comd37d46d2009-04-25 02:53:47 +0000340 EXPECT_TRUE(database_->FindFileContainingExtension("Foo", 5, &file));
temporal40ee5512008-07-10 02:12:20 +0000341 EXPECT_EQ("foo.proto", file.name());
342 }
343
344 {
345 FileDescriptorProto file;
kenton@google.comd37d46d2009-04-25 02:53:47 +0000346 EXPECT_TRUE(database_->FindFileContainingExtension("Foo", 32, &file));
temporal40ee5512008-07-10 02:12:20 +0000347 EXPECT_EQ("bar.proto", file.name());
348 }
349
350 {
351 // Can find extensions for qualified type names.
352 FileDescriptorProto file;
kenton@google.comd37d46d2009-04-25 02:53:47 +0000353 EXPECT_TRUE(database_->FindFileContainingExtension("corge.Bar", 70, &file));
temporal40ee5512008-07-10 02:12:20 +0000354 EXPECT_EQ("bar.proto", file.name());
355 }
356
357 {
358 // Can't find extensions whose extendee was not fully-qualified in the
359 // FileDescriptorProto.
360 FileDescriptorProto file;
kenton@google.comd37d46d2009-04-25 02:53:47 +0000361 EXPECT_FALSE(database_->FindFileContainingExtension("Bar", 56, &file));
362 EXPECT_FALSE(
363 database_->FindFileContainingExtension("corge.Bar", 56, &file));
temporal40ee5512008-07-10 02:12:20 +0000364 }
365
366 {
367 // Can't find non-existent extension numbers.
368 FileDescriptorProto file;
kenton@google.comd37d46d2009-04-25 02:53:47 +0000369 EXPECT_FALSE(database_->FindFileContainingExtension("Foo", 12, &file));
temporal40ee5512008-07-10 02:12:20 +0000370 }
371
372 {
373 // Can't find extensions for non-existent types.
374 FileDescriptorProto file;
kenton@google.comd37d46d2009-04-25 02:53:47 +0000375 EXPECT_FALSE(
376 database_->FindFileContainingExtension("NoSuchType", 5, &file));
temporal40ee5512008-07-10 02:12:20 +0000377 }
378
379 {
380 // Can't find extensions for unqualified type names.
381 FileDescriptorProto file;
kenton@google.comd37d46d2009-04-25 02:53:47 +0000382 EXPECT_FALSE(database_->FindFileContainingExtension("Bar", 70, &file));
temporal40ee5512008-07-10 02:12:20 +0000383 }
384}
385
kenton@google.comd37d46d2009-04-25 02:53:47 +0000386TEST_P(DescriptorDatabaseTest, FindAllExtensionNumbers) {
387 AddToDatabase(
temporal40ee5512008-07-10 02:12:20 +0000388 "name: \"foo.proto\" "
389 "message_type { "
390 " name: \"Foo\" "
391 " extension_range { start: 1 end: 1000 } "
392 " extension { name:\"qux\" label:LABEL_OPTIONAL type:TYPE_INT32 number:5 "
kenton@google.comd37d46d2009-04-25 02:53:47 +0000393 " extendee: \".Foo\" }"
394 "}");
395 AddToDatabase(
temporal40ee5512008-07-10 02:12:20 +0000396 "name: \"bar.proto\" "
397 "package: \"corge\" "
398 "dependency: \"foo.proto\" "
399 "message_type { "
400 " name: \"Bar\" "
401 " extension_range { start: 1 end: 1000 } "
402 "} "
kenton@google.comd37d46d2009-04-25 02:53:47 +0000403 "extension { name:\"grault\" extendee: \".Foo\" number:32 } "
404 "extension { name:\"garply\" extendee: \".corge.Bar\" number:70 } "
405 "extension { name:\"waldo\" extendee: \"Bar\" number:56 } ");
temporal40ee5512008-07-10 02:12:20 +0000406
407 {
kenton@google.comd37d46d2009-04-25 02:53:47 +0000408 vector<int> numbers;
409 EXPECT_TRUE(database_->FindAllExtensionNumbers("Foo", &numbers));
410 ASSERT_EQ(2, numbers.size());
Jisi Liu885b6122015-02-28 14:51:22 -0800411 std::sort(numbers.begin(), numbers.end());
kenton@google.comd37d46d2009-04-25 02:53:47 +0000412 EXPECT_EQ(5, numbers[0]);
413 EXPECT_EQ(32, numbers[1]);
temporal40ee5512008-07-10 02:12:20 +0000414 }
415
416 {
kenton@google.comd37d46d2009-04-25 02:53:47 +0000417 vector<int> numbers;
418 EXPECT_TRUE(database_->FindAllExtensionNumbers("corge.Bar", &numbers));
419 // Note: won't find extension 56 due to the name not being fully qualified.
420 ASSERT_EQ(1, numbers.size());
421 EXPECT_EQ(70, numbers[0]);
temporal40ee5512008-07-10 02:12:20 +0000422 }
423
424 {
425 // Can't find extensions for non-existent types.
kenton@google.comd37d46d2009-04-25 02:53:47 +0000426 vector<int> numbers;
427 EXPECT_FALSE(database_->FindAllExtensionNumbers("NoSuchType", &numbers));
temporal40ee5512008-07-10 02:12:20 +0000428 }
429
430 {
kenton@google.comd37d46d2009-04-25 02:53:47 +0000431 // Can't find extensions for unqualified types.
432 vector<int> numbers;
433 EXPECT_FALSE(database_->FindAllExtensionNumbers("Bar", &numbers));
temporal40ee5512008-07-10 02:12:20 +0000434 }
435}
436
kenton@google.comd37d46d2009-04-25 02:53:47 +0000437TEST_P(DescriptorDatabaseTest, ConflictingFileError) {
438 AddToDatabase(
439 "name: \"foo.proto\" "
440 "message_type { "
441 " name: \"Foo\" "
442 "}");
443 AddToDatabaseWithError(
444 "name: \"foo.proto\" "
445 "message_type { "
446 " name: \"Bar\" "
447 "}");
448}
449
450TEST_P(DescriptorDatabaseTest, ConflictingTypeError) {
451 AddToDatabase(
452 "name: \"foo.proto\" "
453 "message_type { "
454 " name: \"Foo\" "
455 "}");
456 AddToDatabaseWithError(
457 "name: \"bar.proto\" "
458 "message_type { "
459 " name: \"Foo\" "
460 "}");
461}
462
463TEST_P(DescriptorDatabaseTest, ConflictingExtensionError) {
464 AddToDatabase(
465 "name: \"foo.proto\" "
466 "extension { name:\"foo\" label:LABEL_OPTIONAL type:TYPE_INT32 number:5 "
467 " extendee: \".Foo\" }");
468 AddToDatabaseWithError(
469 "name: \"bar.proto\" "
470 "extension { name:\"bar\" label:LABEL_OPTIONAL type:TYPE_INT32 number:5 "
471 " extendee: \".Foo\" }");
472}
473
474INSTANTIATE_TEST_CASE_P(Simple, DescriptorDatabaseTest,
475 testing::Values(&SimpleDescriptorDatabaseTestCase::New));
476INSTANTIATE_TEST_CASE_P(MemoryConserving, DescriptorDatabaseTest,
477 testing::Values(&EncodedDescriptorDatabaseTestCase::New));
478INSTANTIATE_TEST_CASE_P(Pool, DescriptorDatabaseTest,
479 testing::Values(&DescriptorPoolDatabaseTestCase::New));
480
481#endif // GTEST_HAS_PARAM_TEST
482
kenton@google.comfccb1462009-12-18 02:11:36 +0000483TEST(EncodedDescriptorDatabaseExtraTest, FindNameOfFileContainingSymbol) {
484 // Create two files, one of which is in two parts.
485 FileDescriptorProto file1, file2a, file2b;
486 file1.set_name("foo.proto");
487 file1.set_package("foo");
488 file1.add_message_type()->set_name("Foo");
489 file2a.set_name("bar.proto");
490 file2b.set_package("bar");
491 file2b.add_message_type()->set_name("Bar");
492
493 // Normal serialization allows our optimization to kick in.
494 string data1 = file1.SerializeAsString();
495
496 // Force out-of-order serialization to test slow path.
497 string data2 = file2b.SerializeAsString() + file2a.SerializeAsString();
498
499 // Create EncodedDescriptorDatabase containing both files.
500 EncodedDescriptorDatabase db;
501 db.Add(data1.data(), data1.size());
502 db.Add(data2.data(), data2.size());
503
504 // Test!
505 string filename;
506 EXPECT_TRUE(db.FindNameOfFileContainingSymbol("foo.Foo", &filename));
507 EXPECT_EQ("foo.proto", filename);
508 EXPECT_TRUE(db.FindNameOfFileContainingSymbol("foo.Foo.Blah", &filename));
509 EXPECT_EQ("foo.proto", filename);
510 EXPECT_TRUE(db.FindNameOfFileContainingSymbol("bar.Bar", &filename));
511 EXPECT_EQ("bar.proto", filename);
512 EXPECT_FALSE(db.FindNameOfFileContainingSymbol("foo", &filename));
513 EXPECT_FALSE(db.FindNameOfFileContainingSymbol("bar", &filename));
514 EXPECT_FALSE(db.FindNameOfFileContainingSymbol("baz.Baz", &filename));
515}
516
temporal40ee5512008-07-10 02:12:20 +0000517// ===================================================================
518
519class MergedDescriptorDatabaseTest : public testing::Test {
520 protected:
521 MergedDescriptorDatabaseTest()
522 : forward_merged_(&database1_, &database2_),
523 reverse_merged_(&database2_, &database1_) {}
524
525 virtual void SetUp() {
526 AddToDatabase(&database1_,
527 "name: \"foo.proto\" "
528 "message_type { name:\"Foo\" extension_range { start: 1 end: 100 } } "
529 "extension { name:\"foo_ext\" extendee: \".Foo\" number:3 "
530 " label:LABEL_OPTIONAL type:TYPE_INT32 } ");
531 AddToDatabase(&database2_,
532 "name: \"bar.proto\" "
533 "message_type { name:\"Bar\" extension_range { start: 1 end: 100 } } "
534 "extension { name:\"bar_ext\" extendee: \".Bar\" number:5 "
535 " label:LABEL_OPTIONAL type:TYPE_INT32 } ");
536
537 // baz.proto exists in both pools, with different definitions.
538 AddToDatabase(&database1_,
539 "name: \"baz.proto\" "
540 "message_type { name:\"Baz\" extension_range { start: 1 end: 100 } } "
541 "message_type { name:\"FromPool1\" } "
542 "extension { name:\"baz_ext\" extendee: \".Baz\" number:12 "
543 " label:LABEL_OPTIONAL type:TYPE_INT32 } "
544 "extension { name:\"database1_only_ext\" extendee: \".Baz\" number:13 "
545 " label:LABEL_OPTIONAL type:TYPE_INT32 } ");
546 AddToDatabase(&database2_,
547 "name: \"baz.proto\" "
548 "message_type { name:\"Baz\" extension_range { start: 1 end: 100 } } "
549 "message_type { name:\"FromPool2\" } "
550 "extension { name:\"baz_ext\" extendee: \".Baz\" number:12 "
551 " label:LABEL_OPTIONAL type:TYPE_INT32 } ");
552 }
553
554 SimpleDescriptorDatabase database1_;
555 SimpleDescriptorDatabase database2_;
556
557 MergedDescriptorDatabase forward_merged_;
558 MergedDescriptorDatabase reverse_merged_;
559};
560
561TEST_F(MergedDescriptorDatabaseTest, FindFileByName) {
562 {
563 // Can find file that is only in database1_.
564 FileDescriptorProto file;
565 EXPECT_TRUE(forward_merged_.FindFileByName("foo.proto", &file));
566 EXPECT_EQ("foo.proto", file.name());
567 ExpectContainsType(file, "Foo");
568 }
569
570 {
571 // Can find file that is only in database2_.
572 FileDescriptorProto file;
573 EXPECT_TRUE(forward_merged_.FindFileByName("bar.proto", &file));
574 EXPECT_EQ("bar.proto", file.name());
575 ExpectContainsType(file, "Bar");
576 }
577
578 {
579 // In forward_merged_, database1_'s baz.proto takes precedence.
580 FileDescriptorProto file;
581 EXPECT_TRUE(forward_merged_.FindFileByName("baz.proto", &file));
582 EXPECT_EQ("baz.proto", file.name());
583 ExpectContainsType(file, "FromPool1");
584 }
585
586 {
587 // In reverse_merged_, database2_'s baz.proto takes precedence.
588 FileDescriptorProto file;
589 EXPECT_TRUE(reverse_merged_.FindFileByName("baz.proto", &file));
590 EXPECT_EQ("baz.proto", file.name());
591 ExpectContainsType(file, "FromPool2");
592 }
593
594 {
595 // Can't find non-existent file.
596 FileDescriptorProto file;
597 EXPECT_FALSE(forward_merged_.FindFileByName("no_such.proto", &file));
598 }
599}
600
601TEST_F(MergedDescriptorDatabaseTest, FindFileContainingSymbol) {
602 {
603 // Can find file that is only in database1_.
604 FileDescriptorProto file;
605 EXPECT_TRUE(forward_merged_.FindFileContainingSymbol("Foo", &file));
606 EXPECT_EQ("foo.proto", file.name());
607 ExpectContainsType(file, "Foo");
608 }
609
610 {
611 // Can find file that is only in database2_.
612 FileDescriptorProto file;
613 EXPECT_TRUE(forward_merged_.FindFileContainingSymbol("Bar", &file));
614 EXPECT_EQ("bar.proto", file.name());
615 ExpectContainsType(file, "Bar");
616 }
617
618 {
619 // In forward_merged_, database1_'s baz.proto takes precedence.
620 FileDescriptorProto file;
621 EXPECT_TRUE(forward_merged_.FindFileContainingSymbol("Baz", &file));
622 EXPECT_EQ("baz.proto", file.name());
623 ExpectContainsType(file, "FromPool1");
624 }
625
626 {
627 // In reverse_merged_, database2_'s baz.proto takes precedence.
628 FileDescriptorProto file;
629 EXPECT_TRUE(reverse_merged_.FindFileContainingSymbol("Baz", &file));
630 EXPECT_EQ("baz.proto", file.name());
631 ExpectContainsType(file, "FromPool2");
632 }
633
634 {
635 // FromPool1 only shows up in forward_merged_ because it is masked by
636 // database2_'s baz.proto in reverse_merged_.
637 FileDescriptorProto file;
638 EXPECT_TRUE(forward_merged_.FindFileContainingSymbol("FromPool1", &file));
639 EXPECT_FALSE(reverse_merged_.FindFileContainingSymbol("FromPool1", &file));
640 }
641
642 {
643 // Can't find non-existent symbol.
644 FileDescriptorProto file;
645 EXPECT_FALSE(
646 forward_merged_.FindFileContainingSymbol("NoSuchType", &file));
647 }
648}
649
650TEST_F(MergedDescriptorDatabaseTest, FindFileContainingExtension) {
651 {
652 // Can find file that is only in database1_.
653 FileDescriptorProto file;
654 EXPECT_TRUE(
655 forward_merged_.FindFileContainingExtension("Foo", 3, &file));
656 EXPECT_EQ("foo.proto", file.name());
657 ExpectContainsType(file, "Foo");
658 }
659
660 {
661 // Can find file that is only in database2_.
662 FileDescriptorProto file;
663 EXPECT_TRUE(
664 forward_merged_.FindFileContainingExtension("Bar", 5, &file));
665 EXPECT_EQ("bar.proto", file.name());
666 ExpectContainsType(file, "Bar");
667 }
668
669 {
670 // In forward_merged_, database1_'s baz.proto takes precedence.
671 FileDescriptorProto file;
672 EXPECT_TRUE(
673 forward_merged_.FindFileContainingExtension("Baz", 12, &file));
674 EXPECT_EQ("baz.proto", file.name());
675 ExpectContainsType(file, "FromPool1");
676 }
677
678 {
679 // In reverse_merged_, database2_'s baz.proto takes precedence.
680 FileDescriptorProto file;
681 EXPECT_TRUE(
682 reverse_merged_.FindFileContainingExtension("Baz", 12, &file));
683 EXPECT_EQ("baz.proto", file.name());
684 ExpectContainsType(file, "FromPool2");
685 }
686
687 {
688 // Baz's extension 13 only shows up in forward_merged_ because it is
689 // masked by database2_'s baz.proto in reverse_merged_.
690 FileDescriptorProto file;
691 EXPECT_TRUE(forward_merged_.FindFileContainingExtension("Baz", 13, &file));
692 EXPECT_FALSE(reverse_merged_.FindFileContainingExtension("Baz", 13, &file));
693 }
694
695 {
696 // Can't find non-existent extension.
697 FileDescriptorProto file;
698 EXPECT_FALSE(
699 forward_merged_.FindFileContainingExtension("Foo", 6, &file));
700 }
701}
702
kenton@google.comd37d46d2009-04-25 02:53:47 +0000703TEST_F(MergedDescriptorDatabaseTest, FindAllExtensionNumbers) {
704 {
705 // Message only has extension in database1_
706 vector<int> numbers;
707 EXPECT_TRUE(forward_merged_.FindAllExtensionNumbers("Foo", &numbers));
708 ASSERT_EQ(1, numbers.size());
709 EXPECT_EQ(3, numbers[0]);
710 }
711
712 {
713 // Message only has extension in database2_
714 vector<int> numbers;
715 EXPECT_TRUE(forward_merged_.FindAllExtensionNumbers("Bar", &numbers));
716 ASSERT_EQ(1, numbers.size());
717 EXPECT_EQ(5, numbers[0]);
718 }
719
720 {
721 // Merge results from the two databases.
722 vector<int> numbers;
723 EXPECT_TRUE(forward_merged_.FindAllExtensionNumbers("Baz", &numbers));
724 ASSERT_EQ(2, numbers.size());
Jisi Liu885b6122015-02-28 14:51:22 -0800725 std::sort(numbers.begin(), numbers.end());
kenton@google.comd37d46d2009-04-25 02:53:47 +0000726 EXPECT_EQ(12, numbers[0]);
727 EXPECT_EQ(13, numbers[1]);
728 }
729
730 {
731 vector<int> numbers;
732 EXPECT_TRUE(reverse_merged_.FindAllExtensionNumbers("Baz", &numbers));
733 ASSERT_EQ(2, numbers.size());
Jisi Liu885b6122015-02-28 14:51:22 -0800734 std::sort(numbers.begin(), numbers.end());
kenton@google.comd37d46d2009-04-25 02:53:47 +0000735 EXPECT_EQ(12, numbers[0]);
736 EXPECT_EQ(13, numbers[1]);
737 }
738
739 {
740 // Can't find extensions for a non-existent message.
741 vector<int> numbers;
742 EXPECT_FALSE(reverse_merged_.FindAllExtensionNumbers("Blah", &numbers));
743 }
744}
745
temporal40ee5512008-07-10 02:12:20 +0000746} // anonymous namespace
747} // namespace protobuf
748} // namespace google