descriptor_database_unittest.cc 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753
  1. // Protocol Buffers - Google's data interchange format
  2. // Copyright 2008 Google Inc. All rights reserved.
  3. // https://developers.google.com/protocol-buffers/
  4. //
  5. // Redistribution and use in source and binary forms, with or without
  6. // modification, are permitted provided that the following conditions are
  7. // met:
  8. //
  9. // * Redistributions of source code must retain the above copyright
  10. // notice, this list of conditions and the following disclaimer.
  11. // * Redistributions in binary form must reproduce the above
  12. // copyright notice, this list of conditions and the following disclaimer
  13. // in the documentation and/or other materials provided with the
  14. // distribution.
  15. // * Neither the name of Google Inc. nor the names of its
  16. // contributors may be used to endorse or promote products derived from
  17. // this software without specific prior written permission.
  18. //
  19. // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  20. // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  21. // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  22. // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  23. // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  24. // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  25. // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  26. // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  27. // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  28. // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  29. // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  30. // Author: kenton@google.com (Kenton Varda)
  31. // Based on original Protocol Buffers design by
  32. // Sanjay Ghemawat, Jeff Dean, and others.
  33. //
  34. // This file makes extensive use of RFC 3092. :)
  35. #include <algorithm>
  36. #include <memory>
  37. #include <google/protobuf/descriptor.pb.h>
  38. #include <google/protobuf/descriptor.h>
  39. #include <google/protobuf/descriptor_database.h>
  40. #include <google/protobuf/text_format.h>
  41. #include <google/protobuf/stubs/logging.h>
  42. #include <google/protobuf/stubs/common.h>
  43. #include <google/protobuf/testing/googletest.h>
  44. #include <gtest/gtest.h>
  45. namespace google {
  46. namespace protobuf {
  47. namespace {
  48. static void AddToDatabase(SimpleDescriptorDatabase* database,
  49. const char* file_text) {
  50. FileDescriptorProto file_proto;
  51. EXPECT_TRUE(TextFormat::ParseFromString(file_text, &file_proto));
  52. database->Add(file_proto);
  53. }
  54. static void ExpectContainsType(const FileDescriptorProto& proto,
  55. const string& type_name) {
  56. for (int i = 0; i < proto.message_type_size(); i++) {
  57. if (proto.message_type(i).name() == type_name) return;
  58. }
  59. ADD_FAILURE() << "\"" << proto.name()
  60. << "\" did not contain expected type \""
  61. << type_name << "\".";
  62. }
  63. // ===================================================================
  64. #if GTEST_HAS_PARAM_TEST
  65. // SimpleDescriptorDatabase, EncodedDescriptorDatabase, and
  66. // DescriptorPoolDatabase call for very similar tests. Instead of writing
  67. // three nearly-identical sets of tests, we use parameterized tests to apply
  68. // the same code to all three.
  69. // The parameterized test runs against a DescriptarDatabaseTestCase. We have
  70. // implementations for each of the three classes we want to test.
  71. class DescriptorDatabaseTestCase {
  72. public:
  73. virtual ~DescriptorDatabaseTestCase() {}
  74. virtual DescriptorDatabase* GetDatabase() = 0;
  75. virtual bool AddToDatabase(const FileDescriptorProto& file) = 0;
  76. };
  77. // Factory function type.
  78. typedef DescriptorDatabaseTestCase* DescriptorDatabaseTestCaseFactory();
  79. // Specialization for SimpleDescriptorDatabase.
  80. class SimpleDescriptorDatabaseTestCase : public DescriptorDatabaseTestCase {
  81. public:
  82. static DescriptorDatabaseTestCase* New() {
  83. return new SimpleDescriptorDatabaseTestCase;
  84. }
  85. virtual ~SimpleDescriptorDatabaseTestCase() {}
  86. virtual DescriptorDatabase* GetDatabase() {
  87. return &database_;
  88. }
  89. virtual bool AddToDatabase(const FileDescriptorProto& file) {
  90. return database_.Add(file);
  91. }
  92. private:
  93. SimpleDescriptorDatabase database_;
  94. };
  95. // Specialization for EncodedDescriptorDatabase.
  96. class EncodedDescriptorDatabaseTestCase : public DescriptorDatabaseTestCase {
  97. public:
  98. static DescriptorDatabaseTestCase* New() {
  99. return new EncodedDescriptorDatabaseTestCase;
  100. }
  101. virtual ~EncodedDescriptorDatabaseTestCase() {}
  102. virtual DescriptorDatabase* GetDatabase() {
  103. return &database_;
  104. }
  105. virtual bool AddToDatabase(const FileDescriptorProto& file) {
  106. string data;
  107. file.SerializeToString(&data);
  108. return database_.AddCopy(data.data(), data.size());
  109. }
  110. private:
  111. EncodedDescriptorDatabase database_;
  112. };
  113. // Specialization for DescriptorPoolDatabase.
  114. class DescriptorPoolDatabaseTestCase : public DescriptorDatabaseTestCase {
  115. public:
  116. static DescriptorDatabaseTestCase* New() {
  117. return new EncodedDescriptorDatabaseTestCase;
  118. }
  119. DescriptorPoolDatabaseTestCase() : database_(pool_) {}
  120. virtual ~DescriptorPoolDatabaseTestCase() {}
  121. virtual DescriptorDatabase* GetDatabase() {
  122. return &database_;
  123. }
  124. virtual bool AddToDatabase(const FileDescriptorProto& file) {
  125. return pool_.BuildFile(file);
  126. }
  127. private:
  128. DescriptorPool pool_;
  129. DescriptorPoolDatabase database_;
  130. };
  131. // -------------------------------------------------------------------
  132. class DescriptorDatabaseTest
  133. : public testing::TestWithParam<DescriptorDatabaseTestCaseFactory*> {
  134. protected:
  135. virtual void SetUp() {
  136. test_case_.reset(GetParam()());
  137. database_ = test_case_->GetDatabase();
  138. }
  139. void AddToDatabase(const char* file_descriptor_text) {
  140. FileDescriptorProto file_proto;
  141. EXPECT_TRUE(TextFormat::ParseFromString(file_descriptor_text, &file_proto));
  142. EXPECT_TRUE(test_case_->AddToDatabase(file_proto));
  143. }
  144. void AddToDatabaseWithError(const char* file_descriptor_text) {
  145. FileDescriptorProto file_proto;
  146. EXPECT_TRUE(TextFormat::ParseFromString(file_descriptor_text, &file_proto));
  147. EXPECT_FALSE(test_case_->AddToDatabase(file_proto));
  148. }
  149. std::unique_ptr<DescriptorDatabaseTestCase> test_case_;
  150. DescriptorDatabase* database_;
  151. };
  152. TEST_P(DescriptorDatabaseTest, FindFileByName) {
  153. AddToDatabase(
  154. "name: \"foo.proto\" "
  155. "message_type { name:\"Foo\" }");
  156. AddToDatabase(
  157. "name: \"bar.proto\" "
  158. "message_type { name:\"Bar\" }");
  159. {
  160. FileDescriptorProto file;
  161. EXPECT_TRUE(database_->FindFileByName("foo.proto", &file));
  162. EXPECT_EQ("foo.proto", file.name());
  163. ExpectContainsType(file, "Foo");
  164. }
  165. {
  166. FileDescriptorProto file;
  167. EXPECT_TRUE(database_->FindFileByName("bar.proto", &file));
  168. EXPECT_EQ("bar.proto", file.name());
  169. ExpectContainsType(file, "Bar");
  170. }
  171. {
  172. // Fails to find undefined files.
  173. FileDescriptorProto file;
  174. EXPECT_FALSE(database_->FindFileByName("baz.proto", &file));
  175. }
  176. }
  177. TEST_P(DescriptorDatabaseTest, FindFileContainingSymbol) {
  178. AddToDatabase(
  179. "name: \"foo.proto\" "
  180. "message_type { "
  181. " name: \"Foo\" "
  182. " field { name:\"qux\" }"
  183. " nested_type { name: \"Grault\" } "
  184. " enum_type { name: \"Garply\" } "
  185. "} "
  186. "enum_type { "
  187. " name: \"Waldo\" "
  188. " value { name:\"FRED\" } "
  189. "} "
  190. "extension { name: \"plugh\" } "
  191. "service { "
  192. " name: \"Xyzzy\" "
  193. " method { name: \"Thud\" } "
  194. "}"
  195. );
  196. AddToDatabase(
  197. "name: \"bar.proto\" "
  198. "package: \"corge\" "
  199. "message_type { name: \"Bar\" }");
  200. {
  201. FileDescriptorProto file;
  202. EXPECT_TRUE(database_->FindFileContainingSymbol("Foo", &file));
  203. EXPECT_EQ("foo.proto", file.name());
  204. }
  205. {
  206. // Can find fields.
  207. FileDescriptorProto file;
  208. EXPECT_TRUE(database_->FindFileContainingSymbol("Foo.qux", &file));
  209. EXPECT_EQ("foo.proto", file.name());
  210. // Non-existent field under a valid top level symbol can also be
  211. // found.
  212. EXPECT_TRUE(database_->FindFileContainingSymbol("Foo.none_field.none",
  213. &file));
  214. }
  215. {
  216. // Can find nested types.
  217. FileDescriptorProto file;
  218. EXPECT_TRUE(database_->FindFileContainingSymbol("Foo.Grault", &file));
  219. EXPECT_EQ("foo.proto", file.name());
  220. }
  221. {
  222. // Can find nested enums.
  223. FileDescriptorProto file;
  224. EXPECT_TRUE(database_->FindFileContainingSymbol("Foo.Garply", &file));
  225. EXPECT_EQ("foo.proto", file.name());
  226. }
  227. {
  228. // Can find enum types.
  229. FileDescriptorProto file;
  230. EXPECT_TRUE(database_->FindFileContainingSymbol("Waldo", &file));
  231. EXPECT_EQ("foo.proto", file.name());
  232. }
  233. {
  234. // Can find enum values.
  235. FileDescriptorProto file;
  236. EXPECT_TRUE(database_->FindFileContainingSymbol("Waldo.FRED", &file));
  237. EXPECT_EQ("foo.proto", file.name());
  238. }
  239. {
  240. // Can find extensions.
  241. FileDescriptorProto file;
  242. EXPECT_TRUE(database_->FindFileContainingSymbol("plugh", &file));
  243. EXPECT_EQ("foo.proto", file.name());
  244. }
  245. {
  246. // Can find services.
  247. FileDescriptorProto file;
  248. EXPECT_TRUE(database_->FindFileContainingSymbol("Xyzzy", &file));
  249. EXPECT_EQ("foo.proto", file.name());
  250. }
  251. {
  252. // Can find methods.
  253. FileDescriptorProto file;
  254. EXPECT_TRUE(database_->FindFileContainingSymbol("Xyzzy.Thud", &file));
  255. EXPECT_EQ("foo.proto", file.name());
  256. }
  257. {
  258. // Can find things in packages.
  259. FileDescriptorProto file;
  260. EXPECT_TRUE(database_->FindFileContainingSymbol("corge.Bar", &file));
  261. EXPECT_EQ("bar.proto", file.name());
  262. }
  263. {
  264. // Fails to find undefined symbols.
  265. FileDescriptorProto file;
  266. EXPECT_FALSE(database_->FindFileContainingSymbol("Baz", &file));
  267. }
  268. {
  269. // Names must be fully-qualified.
  270. FileDescriptorProto file;
  271. EXPECT_FALSE(database_->FindFileContainingSymbol("Bar", &file));
  272. }
  273. }
  274. TEST_P(DescriptorDatabaseTest, FindFileContainingExtension) {
  275. AddToDatabase(
  276. "name: \"foo.proto\" "
  277. "message_type { "
  278. " name: \"Foo\" "
  279. " extension_range { start: 1 end: 1000 } "
  280. " extension { name:\"qux\" label:LABEL_OPTIONAL type:TYPE_INT32 number:5 "
  281. " extendee: \".Foo\" }"
  282. "}");
  283. AddToDatabase(
  284. "name: \"bar.proto\" "
  285. "package: \"corge\" "
  286. "dependency: \"foo.proto\" "
  287. "message_type { "
  288. " name: \"Bar\" "
  289. " extension_range { start: 1 end: 1000 } "
  290. "} "
  291. "extension { name:\"grault\" extendee: \".Foo\" number:32 } "
  292. "extension { name:\"garply\" extendee: \".corge.Bar\" number:70 } "
  293. "extension { name:\"waldo\" extendee: \"Bar\" number:56 } ");
  294. {
  295. FileDescriptorProto file;
  296. EXPECT_TRUE(database_->FindFileContainingExtension("Foo", 5, &file));
  297. EXPECT_EQ("foo.proto", file.name());
  298. }
  299. {
  300. FileDescriptorProto file;
  301. EXPECT_TRUE(database_->FindFileContainingExtension("Foo", 32, &file));
  302. EXPECT_EQ("bar.proto", file.name());
  303. }
  304. {
  305. // Can find extensions for qualified type names.
  306. FileDescriptorProto file;
  307. EXPECT_TRUE(database_->FindFileContainingExtension("corge.Bar", 70, &file));
  308. EXPECT_EQ("bar.proto", file.name());
  309. }
  310. {
  311. // Can't find extensions whose extendee was not fully-qualified in the
  312. // FileDescriptorProto.
  313. FileDescriptorProto file;
  314. EXPECT_FALSE(database_->FindFileContainingExtension("Bar", 56, &file));
  315. EXPECT_FALSE(
  316. database_->FindFileContainingExtension("corge.Bar", 56, &file));
  317. }
  318. {
  319. // Can't find non-existent extension numbers.
  320. FileDescriptorProto file;
  321. EXPECT_FALSE(database_->FindFileContainingExtension("Foo", 12, &file));
  322. }
  323. {
  324. // Can't find extensions for non-existent types.
  325. FileDescriptorProto file;
  326. EXPECT_FALSE(
  327. database_->FindFileContainingExtension("NoSuchType", 5, &file));
  328. }
  329. {
  330. // Can't find extensions for unqualified type names.
  331. FileDescriptorProto file;
  332. EXPECT_FALSE(database_->FindFileContainingExtension("Bar", 70, &file));
  333. }
  334. }
  335. TEST_P(DescriptorDatabaseTest, FindAllExtensionNumbers) {
  336. AddToDatabase(
  337. "name: \"foo.proto\" "
  338. "message_type { "
  339. " name: \"Foo\" "
  340. " extension_range { start: 1 end: 1000 } "
  341. " extension { name:\"qux\" label:LABEL_OPTIONAL type:TYPE_INT32 number:5 "
  342. " extendee: \".Foo\" }"
  343. "}");
  344. AddToDatabase(
  345. "name: \"bar.proto\" "
  346. "package: \"corge\" "
  347. "dependency: \"foo.proto\" "
  348. "message_type { "
  349. " name: \"Bar\" "
  350. " extension_range { start: 1 end: 1000 } "
  351. "} "
  352. "extension { name:\"grault\" extendee: \".Foo\" number:32 } "
  353. "extension { name:\"garply\" extendee: \".corge.Bar\" number:70 } "
  354. "extension { name:\"waldo\" extendee: \"Bar\" number:56 } ");
  355. {
  356. std::vector<int> numbers;
  357. EXPECT_TRUE(database_->FindAllExtensionNumbers("Foo", &numbers));
  358. ASSERT_EQ(2, numbers.size());
  359. std::sort(numbers.begin(), numbers.end());
  360. EXPECT_EQ(5, numbers[0]);
  361. EXPECT_EQ(32, numbers[1]);
  362. }
  363. {
  364. std::vector<int> numbers;
  365. EXPECT_TRUE(database_->FindAllExtensionNumbers("corge.Bar", &numbers));
  366. // Note: won't find extension 56 due to the name not being fully qualified.
  367. ASSERT_EQ(1, numbers.size());
  368. EXPECT_EQ(70, numbers[0]);
  369. }
  370. {
  371. // Can't find extensions for non-existent types.
  372. std::vector<int> numbers;
  373. EXPECT_FALSE(database_->FindAllExtensionNumbers("NoSuchType", &numbers));
  374. }
  375. {
  376. // Can't find extensions for unqualified types.
  377. std::vector<int> numbers;
  378. EXPECT_FALSE(database_->FindAllExtensionNumbers("Bar", &numbers));
  379. }
  380. }
  381. TEST_P(DescriptorDatabaseTest, ConflictingFileError) {
  382. AddToDatabase(
  383. "name: \"foo.proto\" "
  384. "message_type { "
  385. " name: \"Foo\" "
  386. "}");
  387. AddToDatabaseWithError(
  388. "name: \"foo.proto\" "
  389. "message_type { "
  390. " name: \"Bar\" "
  391. "}");
  392. }
  393. TEST_P(DescriptorDatabaseTest, ConflictingTypeError) {
  394. AddToDatabase(
  395. "name: \"foo.proto\" "
  396. "message_type { "
  397. " name: \"Foo\" "
  398. "}");
  399. AddToDatabaseWithError(
  400. "name: \"bar.proto\" "
  401. "message_type { "
  402. " name: \"Foo\" "
  403. "}");
  404. }
  405. TEST_P(DescriptorDatabaseTest, ConflictingExtensionError) {
  406. AddToDatabase(
  407. "name: \"foo.proto\" "
  408. "extension { name:\"foo\" label:LABEL_OPTIONAL type:TYPE_INT32 number:5 "
  409. " extendee: \".Foo\" }");
  410. AddToDatabaseWithError(
  411. "name: \"bar.proto\" "
  412. "extension { name:\"bar\" label:LABEL_OPTIONAL type:TYPE_INT32 number:5 "
  413. " extendee: \".Foo\" }");
  414. }
  415. INSTANTIATE_TEST_CASE_P(Simple, DescriptorDatabaseTest,
  416. testing::Values(&SimpleDescriptorDatabaseTestCase::New));
  417. INSTANTIATE_TEST_CASE_P(MemoryConserving, DescriptorDatabaseTest,
  418. testing::Values(&EncodedDescriptorDatabaseTestCase::New));
  419. INSTANTIATE_TEST_CASE_P(Pool, DescriptorDatabaseTest,
  420. testing::Values(&DescriptorPoolDatabaseTestCase::New));
  421. #endif // GTEST_HAS_PARAM_TEST
  422. TEST(EncodedDescriptorDatabaseExtraTest, FindNameOfFileContainingSymbol) {
  423. // Create two files, one of which is in two parts.
  424. FileDescriptorProto file1, file2a, file2b;
  425. file1.set_name("foo.proto");
  426. file1.set_package("foo");
  427. file1.add_message_type()->set_name("Foo");
  428. file2a.set_name("bar.proto");
  429. file2b.set_package("bar");
  430. file2b.add_message_type()->set_name("Bar");
  431. // Normal serialization allows our optimization to kick in.
  432. string data1 = file1.SerializeAsString();
  433. // Force out-of-order serialization to test slow path.
  434. string data2 = file2b.SerializeAsString() + file2a.SerializeAsString();
  435. // Create EncodedDescriptorDatabase containing both files.
  436. EncodedDescriptorDatabase db;
  437. db.Add(data1.data(), data1.size());
  438. db.Add(data2.data(), data2.size());
  439. // Test!
  440. string filename;
  441. EXPECT_TRUE(db.FindNameOfFileContainingSymbol("foo.Foo", &filename));
  442. EXPECT_EQ("foo.proto", filename);
  443. EXPECT_TRUE(db.FindNameOfFileContainingSymbol("foo.Foo.Blah", &filename));
  444. EXPECT_EQ("foo.proto", filename);
  445. EXPECT_TRUE(db.FindNameOfFileContainingSymbol("bar.Bar", &filename));
  446. EXPECT_EQ("bar.proto", filename);
  447. EXPECT_FALSE(db.FindNameOfFileContainingSymbol("foo", &filename));
  448. EXPECT_FALSE(db.FindNameOfFileContainingSymbol("bar", &filename));
  449. EXPECT_FALSE(db.FindNameOfFileContainingSymbol("baz.Baz", &filename));
  450. }
  451. // ===================================================================
  452. class MergedDescriptorDatabaseTest : public testing::Test {
  453. protected:
  454. MergedDescriptorDatabaseTest()
  455. : forward_merged_(&database1_, &database2_),
  456. reverse_merged_(&database2_, &database1_) {}
  457. virtual void SetUp() {
  458. AddToDatabase(&database1_,
  459. "name: \"foo.proto\" "
  460. "message_type { name:\"Foo\" extension_range { start: 1 end: 100 } } "
  461. "extension { name:\"foo_ext\" extendee: \".Foo\" number:3 "
  462. " label:LABEL_OPTIONAL type:TYPE_INT32 } ");
  463. AddToDatabase(&database2_,
  464. "name: \"bar.proto\" "
  465. "message_type { name:\"Bar\" extension_range { start: 1 end: 100 } } "
  466. "extension { name:\"bar_ext\" extendee: \".Bar\" number:5 "
  467. " label:LABEL_OPTIONAL type:TYPE_INT32 } ");
  468. // baz.proto exists in both pools, with different definitions.
  469. AddToDatabase(&database1_,
  470. "name: \"baz.proto\" "
  471. "message_type { name:\"Baz\" extension_range { start: 1 end: 100 } } "
  472. "message_type { name:\"FromPool1\" } "
  473. "extension { name:\"baz_ext\" extendee: \".Baz\" number:12 "
  474. " label:LABEL_OPTIONAL type:TYPE_INT32 } "
  475. "extension { name:\"database1_only_ext\" extendee: \".Baz\" number:13 "
  476. " label:LABEL_OPTIONAL type:TYPE_INT32 } ");
  477. AddToDatabase(&database2_,
  478. "name: \"baz.proto\" "
  479. "message_type { name:\"Baz\" extension_range { start: 1 end: 100 } } "
  480. "message_type { name:\"FromPool2\" } "
  481. "extension { name:\"baz_ext\" extendee: \".Baz\" number:12 "
  482. " label:LABEL_OPTIONAL type:TYPE_INT32 } ");
  483. }
  484. SimpleDescriptorDatabase database1_;
  485. SimpleDescriptorDatabase database2_;
  486. MergedDescriptorDatabase forward_merged_;
  487. MergedDescriptorDatabase reverse_merged_;
  488. };
  489. TEST_F(MergedDescriptorDatabaseTest, FindFileByName) {
  490. {
  491. // Can find file that is only in database1_.
  492. FileDescriptorProto file;
  493. EXPECT_TRUE(forward_merged_.FindFileByName("foo.proto", &file));
  494. EXPECT_EQ("foo.proto", file.name());
  495. ExpectContainsType(file, "Foo");
  496. }
  497. {
  498. // Can find file that is only in database2_.
  499. FileDescriptorProto file;
  500. EXPECT_TRUE(forward_merged_.FindFileByName("bar.proto", &file));
  501. EXPECT_EQ("bar.proto", file.name());
  502. ExpectContainsType(file, "Bar");
  503. }
  504. {
  505. // In forward_merged_, database1_'s baz.proto takes precedence.
  506. FileDescriptorProto file;
  507. EXPECT_TRUE(forward_merged_.FindFileByName("baz.proto", &file));
  508. EXPECT_EQ("baz.proto", file.name());
  509. ExpectContainsType(file, "FromPool1");
  510. }
  511. {
  512. // In reverse_merged_, database2_'s baz.proto takes precedence.
  513. FileDescriptorProto file;
  514. EXPECT_TRUE(reverse_merged_.FindFileByName("baz.proto", &file));
  515. EXPECT_EQ("baz.proto", file.name());
  516. ExpectContainsType(file, "FromPool2");
  517. }
  518. {
  519. // Can't find non-existent file.
  520. FileDescriptorProto file;
  521. EXPECT_FALSE(forward_merged_.FindFileByName("no_such.proto", &file));
  522. }
  523. }
  524. TEST_F(MergedDescriptorDatabaseTest, FindFileContainingSymbol) {
  525. {
  526. // Can find file that is only in database1_.
  527. FileDescriptorProto file;
  528. EXPECT_TRUE(forward_merged_.FindFileContainingSymbol("Foo", &file));
  529. EXPECT_EQ("foo.proto", file.name());
  530. ExpectContainsType(file, "Foo");
  531. }
  532. {
  533. // Can find file that is only in database2_.
  534. FileDescriptorProto file;
  535. EXPECT_TRUE(forward_merged_.FindFileContainingSymbol("Bar", &file));
  536. EXPECT_EQ("bar.proto", file.name());
  537. ExpectContainsType(file, "Bar");
  538. }
  539. {
  540. // In forward_merged_, database1_'s baz.proto takes precedence.
  541. FileDescriptorProto file;
  542. EXPECT_TRUE(forward_merged_.FindFileContainingSymbol("Baz", &file));
  543. EXPECT_EQ("baz.proto", file.name());
  544. ExpectContainsType(file, "FromPool1");
  545. }
  546. {
  547. // In reverse_merged_, database2_'s baz.proto takes precedence.
  548. FileDescriptorProto file;
  549. EXPECT_TRUE(reverse_merged_.FindFileContainingSymbol("Baz", &file));
  550. EXPECT_EQ("baz.proto", file.name());
  551. ExpectContainsType(file, "FromPool2");
  552. }
  553. {
  554. // FromPool1 only shows up in forward_merged_ because it is masked by
  555. // database2_'s baz.proto in reverse_merged_.
  556. FileDescriptorProto file;
  557. EXPECT_TRUE(forward_merged_.FindFileContainingSymbol("FromPool1", &file));
  558. EXPECT_FALSE(reverse_merged_.FindFileContainingSymbol("FromPool1", &file));
  559. }
  560. {
  561. // Can't find non-existent symbol.
  562. FileDescriptorProto file;
  563. EXPECT_FALSE(
  564. forward_merged_.FindFileContainingSymbol("NoSuchType", &file));
  565. }
  566. }
  567. TEST_F(MergedDescriptorDatabaseTest, FindFileContainingExtension) {
  568. {
  569. // Can find file that is only in database1_.
  570. FileDescriptorProto file;
  571. EXPECT_TRUE(
  572. forward_merged_.FindFileContainingExtension("Foo", 3, &file));
  573. EXPECT_EQ("foo.proto", file.name());
  574. ExpectContainsType(file, "Foo");
  575. }
  576. {
  577. // Can find file that is only in database2_.
  578. FileDescriptorProto file;
  579. EXPECT_TRUE(
  580. forward_merged_.FindFileContainingExtension("Bar", 5, &file));
  581. EXPECT_EQ("bar.proto", file.name());
  582. ExpectContainsType(file, "Bar");
  583. }
  584. {
  585. // In forward_merged_, database1_'s baz.proto takes precedence.
  586. FileDescriptorProto file;
  587. EXPECT_TRUE(
  588. forward_merged_.FindFileContainingExtension("Baz", 12, &file));
  589. EXPECT_EQ("baz.proto", file.name());
  590. ExpectContainsType(file, "FromPool1");
  591. }
  592. {
  593. // In reverse_merged_, database2_'s baz.proto takes precedence.
  594. FileDescriptorProto file;
  595. EXPECT_TRUE(
  596. reverse_merged_.FindFileContainingExtension("Baz", 12, &file));
  597. EXPECT_EQ("baz.proto", file.name());
  598. ExpectContainsType(file, "FromPool2");
  599. }
  600. {
  601. // Baz's extension 13 only shows up in forward_merged_ because it is
  602. // masked by database2_'s baz.proto in reverse_merged_.
  603. FileDescriptorProto file;
  604. EXPECT_TRUE(forward_merged_.FindFileContainingExtension("Baz", 13, &file));
  605. EXPECT_FALSE(reverse_merged_.FindFileContainingExtension("Baz", 13, &file));
  606. }
  607. {
  608. // Can't find non-existent extension.
  609. FileDescriptorProto file;
  610. EXPECT_FALSE(
  611. forward_merged_.FindFileContainingExtension("Foo", 6, &file));
  612. }
  613. }
  614. TEST_F(MergedDescriptorDatabaseTest, FindAllExtensionNumbers) {
  615. {
  616. // Message only has extension in database1_
  617. std::vector<int> numbers;
  618. EXPECT_TRUE(forward_merged_.FindAllExtensionNumbers("Foo", &numbers));
  619. ASSERT_EQ(1, numbers.size());
  620. EXPECT_EQ(3, numbers[0]);
  621. }
  622. {
  623. // Message only has extension in database2_
  624. std::vector<int> numbers;
  625. EXPECT_TRUE(forward_merged_.FindAllExtensionNumbers("Bar", &numbers));
  626. ASSERT_EQ(1, numbers.size());
  627. EXPECT_EQ(5, numbers[0]);
  628. }
  629. {
  630. // Merge results from the two databases.
  631. std::vector<int> numbers;
  632. EXPECT_TRUE(forward_merged_.FindAllExtensionNumbers("Baz", &numbers));
  633. ASSERT_EQ(2, numbers.size());
  634. std::sort(numbers.begin(), numbers.end());
  635. EXPECT_EQ(12, numbers[0]);
  636. EXPECT_EQ(13, numbers[1]);
  637. }
  638. {
  639. std::vector<int> numbers;
  640. EXPECT_TRUE(reverse_merged_.FindAllExtensionNumbers("Baz", &numbers));
  641. ASSERT_EQ(2, numbers.size());
  642. std::sort(numbers.begin(), numbers.end());
  643. EXPECT_EQ(12, numbers[0]);
  644. EXPECT_EQ(13, numbers[1]);
  645. }
  646. {
  647. // Can't find extensions for a non-existent message.
  648. std::vector<int> numbers;
  649. EXPECT_FALSE(reverse_merged_.FindAllExtensionNumbers("Blah", &numbers));
  650. }
  651. }
  652. } // anonymous namespace
  653. } // namespace protobuf
  654. } // namespace google