PageRenderTime 39ms CodeModel.GetById 22ms RepoModel.GetById 0ms app.codeStats 1ms

/src/google/protobuf/descriptor_unittest.cc

http://protobuf.googlecode.com/
C++ | 4656 lines | 3487 code | 698 blank | 471 comment | 216 complexity | 7280232872d931e5bd7f3d311cdaa6b9 MD5 | raw file
Possible License(s): BSD-3-Clause
  1. // Protocol Buffers - Google's data interchange format
  2. // Copyright 2008 Google Inc. All rights reserved.
  3. // http://code.google.com/p/protobuf/
  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 <vector>
  36. #include <google/protobuf/compiler/importer.h>
  37. #include <google/protobuf/unittest.pb.h>
  38. #include <google/protobuf/unittest_custom_options.pb.h>
  39. #include <google/protobuf/io/zero_copy_stream_impl.h>
  40. #include <google/protobuf/descriptor.pb.h>
  41. #include <google/protobuf/descriptor.h>
  42. #include <google/protobuf/descriptor_database.h>
  43. #include <google/protobuf/dynamic_message.h>
  44. #include <google/protobuf/text_format.h>
  45. #include <google/protobuf/stubs/strutil.h>
  46. #include <google/protobuf/stubs/substitute.h>
  47. #include <google/protobuf/stubs/common.h>
  48. #include <google/protobuf/testing/googletest.h>
  49. #include <gtest/gtest.h>
  50. namespace google {
  51. namespace protobuf {
  52. // Can't use an anonymous namespace here due to brokenness of Tru64 compiler.
  53. namespace descriptor_unittest {
  54. // Some helpers to make assembling descriptors faster.
  55. DescriptorProto* AddMessage(FileDescriptorProto* file, const string& name) {
  56. DescriptorProto* result = file->add_message_type();
  57. result->set_name(name);
  58. return result;
  59. }
  60. DescriptorProto* AddNestedMessage(DescriptorProto* parent, const string& name) {
  61. DescriptorProto* result = parent->add_nested_type();
  62. result->set_name(name);
  63. return result;
  64. }
  65. EnumDescriptorProto* AddEnum(FileDescriptorProto* file, const string& name) {
  66. EnumDescriptorProto* result = file->add_enum_type();
  67. result->set_name(name);
  68. return result;
  69. }
  70. EnumDescriptorProto* AddNestedEnum(DescriptorProto* parent,
  71. const string& name) {
  72. EnumDescriptorProto* result = parent->add_enum_type();
  73. result->set_name(name);
  74. return result;
  75. }
  76. ServiceDescriptorProto* AddService(FileDescriptorProto* file,
  77. const string& name) {
  78. ServiceDescriptorProto* result = file->add_service();
  79. result->set_name(name);
  80. return result;
  81. }
  82. FieldDescriptorProto* AddField(DescriptorProto* parent,
  83. const string& name, int number,
  84. FieldDescriptorProto::Label label,
  85. FieldDescriptorProto::Type type) {
  86. FieldDescriptorProto* result = parent->add_field();
  87. result->set_name(name);
  88. result->set_number(number);
  89. result->set_label(label);
  90. result->set_type(type);
  91. return result;
  92. }
  93. FieldDescriptorProto* AddExtension(FileDescriptorProto* file,
  94. const string& extendee,
  95. const string& name, int number,
  96. FieldDescriptorProto::Label label,
  97. FieldDescriptorProto::Type type) {
  98. FieldDescriptorProto* result = file->add_extension();
  99. result->set_name(name);
  100. result->set_number(number);
  101. result->set_label(label);
  102. result->set_type(type);
  103. result->set_extendee(extendee);
  104. return result;
  105. }
  106. FieldDescriptorProto* AddNestedExtension(DescriptorProto* parent,
  107. const string& extendee,
  108. const string& name, int number,
  109. FieldDescriptorProto::Label label,
  110. FieldDescriptorProto::Type type) {
  111. FieldDescriptorProto* result = parent->add_extension();
  112. result->set_name(name);
  113. result->set_number(number);
  114. result->set_label(label);
  115. result->set_type(type);
  116. result->set_extendee(extendee);
  117. return result;
  118. }
  119. DescriptorProto::ExtensionRange* AddExtensionRange(DescriptorProto* parent,
  120. int start, int end) {
  121. DescriptorProto::ExtensionRange* result = parent->add_extension_range();
  122. result->set_start(start);
  123. result->set_end(end);
  124. return result;
  125. }
  126. EnumValueDescriptorProto* AddEnumValue(EnumDescriptorProto* enum_proto,
  127. const string& name, int number) {
  128. EnumValueDescriptorProto* result = enum_proto->add_value();
  129. result->set_name(name);
  130. result->set_number(number);
  131. return result;
  132. }
  133. MethodDescriptorProto* AddMethod(ServiceDescriptorProto* service,
  134. const string& name,
  135. const string& input_type,
  136. const string& output_type) {
  137. MethodDescriptorProto* result = service->add_method();
  138. result->set_name(name);
  139. result->set_input_type(input_type);
  140. result->set_output_type(output_type);
  141. return result;
  142. }
  143. // Empty enums technically aren't allowed. We need to insert a dummy value
  144. // into them.
  145. void AddEmptyEnum(FileDescriptorProto* file, const string& name) {
  146. AddEnumValue(AddEnum(file, name), name + "_DUMMY", 1);
  147. }
  148. // ===================================================================
  149. // Test simple files.
  150. class FileDescriptorTest : public testing::Test {
  151. protected:
  152. virtual void SetUp() {
  153. // Build descriptors for the following definitions:
  154. //
  155. // // in "foo.proto"
  156. // message FooMessage { extensions 1; }
  157. // enum FooEnum {FOO_ENUM_VALUE = 1;}
  158. // service FooService {}
  159. // extend FooMessage { optional int32 foo_extension = 1; }
  160. //
  161. // // in "bar.proto"
  162. // package bar_package;
  163. // message BarMessage { extensions 1; }
  164. // enum BarEnum {BAR_ENUM_VALUE = 1;}
  165. // service BarService {}
  166. // extend BarMessage { optional int32 bar_extension = 1; }
  167. //
  168. // Also, we have an empty file "baz.proto". This file's purpose is to
  169. // make sure that even though it has the same package as foo.proto,
  170. // searching it for members of foo.proto won't work.
  171. FileDescriptorProto foo_file;
  172. foo_file.set_name("foo.proto");
  173. AddExtensionRange(AddMessage(&foo_file, "FooMessage"), 1, 2);
  174. AddEnumValue(AddEnum(&foo_file, "FooEnum"), "FOO_ENUM_VALUE", 1);
  175. AddService(&foo_file, "FooService");
  176. AddExtension(&foo_file, "FooMessage", "foo_extension", 1,
  177. FieldDescriptorProto::LABEL_OPTIONAL,
  178. FieldDescriptorProto::TYPE_INT32);
  179. FileDescriptorProto bar_file;
  180. bar_file.set_name("bar.proto");
  181. bar_file.set_package("bar_package");
  182. bar_file.add_dependency("foo.proto");
  183. AddExtensionRange(AddMessage(&bar_file, "BarMessage"), 1, 2);
  184. AddEnumValue(AddEnum(&bar_file, "BarEnum"), "BAR_ENUM_VALUE", 1);
  185. AddService(&bar_file, "BarService");
  186. AddExtension(&bar_file, "bar_package.BarMessage", "bar_extension", 1,
  187. FieldDescriptorProto::LABEL_OPTIONAL,
  188. FieldDescriptorProto::TYPE_INT32);
  189. FileDescriptorProto baz_file;
  190. baz_file.set_name("baz.proto");
  191. // Build the descriptors and get the pointers.
  192. foo_file_ = pool_.BuildFile(foo_file);
  193. ASSERT_TRUE(foo_file_ != NULL);
  194. bar_file_ = pool_.BuildFile(bar_file);
  195. ASSERT_TRUE(bar_file_ != NULL);
  196. baz_file_ = pool_.BuildFile(baz_file);
  197. ASSERT_TRUE(baz_file_ != NULL);
  198. ASSERT_EQ(1, foo_file_->message_type_count());
  199. foo_message_ = foo_file_->message_type(0);
  200. ASSERT_EQ(1, foo_file_->enum_type_count());
  201. foo_enum_ = foo_file_->enum_type(0);
  202. ASSERT_EQ(1, foo_enum_->value_count());
  203. foo_enum_value_ = foo_enum_->value(0);
  204. ASSERT_EQ(1, foo_file_->service_count());
  205. foo_service_ = foo_file_->service(0);
  206. ASSERT_EQ(1, foo_file_->extension_count());
  207. foo_extension_ = foo_file_->extension(0);
  208. ASSERT_EQ(1, bar_file_->message_type_count());
  209. bar_message_ = bar_file_->message_type(0);
  210. ASSERT_EQ(1, bar_file_->enum_type_count());
  211. bar_enum_ = bar_file_->enum_type(0);
  212. ASSERT_EQ(1, bar_enum_->value_count());
  213. bar_enum_value_ = bar_enum_->value(0);
  214. ASSERT_EQ(1, bar_file_->service_count());
  215. bar_service_ = bar_file_->service(0);
  216. ASSERT_EQ(1, bar_file_->extension_count());
  217. bar_extension_ = bar_file_->extension(0);
  218. }
  219. DescriptorPool pool_;
  220. const FileDescriptor* foo_file_;
  221. const FileDescriptor* bar_file_;
  222. const FileDescriptor* baz_file_;
  223. const Descriptor* foo_message_;
  224. const EnumDescriptor* foo_enum_;
  225. const EnumValueDescriptor* foo_enum_value_;
  226. const ServiceDescriptor* foo_service_;
  227. const FieldDescriptor* foo_extension_;
  228. const Descriptor* bar_message_;
  229. const EnumDescriptor* bar_enum_;
  230. const EnumValueDescriptor* bar_enum_value_;
  231. const ServiceDescriptor* bar_service_;
  232. const FieldDescriptor* bar_extension_;
  233. };
  234. TEST_F(FileDescriptorTest, Name) {
  235. EXPECT_EQ("foo.proto", foo_file_->name());
  236. EXPECT_EQ("bar.proto", bar_file_->name());
  237. EXPECT_EQ("baz.proto", baz_file_->name());
  238. }
  239. TEST_F(FileDescriptorTest, Package) {
  240. EXPECT_EQ("", foo_file_->package());
  241. EXPECT_EQ("bar_package", bar_file_->package());
  242. }
  243. TEST_F(FileDescriptorTest, Dependencies) {
  244. EXPECT_EQ(0, foo_file_->dependency_count());
  245. EXPECT_EQ(1, bar_file_->dependency_count());
  246. EXPECT_EQ(foo_file_, bar_file_->dependency(0));
  247. }
  248. TEST_F(FileDescriptorTest, FindMessageTypeByName) {
  249. EXPECT_EQ(foo_message_, foo_file_->FindMessageTypeByName("FooMessage"));
  250. EXPECT_EQ(bar_message_, bar_file_->FindMessageTypeByName("BarMessage"));
  251. EXPECT_TRUE(foo_file_->FindMessageTypeByName("BarMessage") == NULL);
  252. EXPECT_TRUE(bar_file_->FindMessageTypeByName("FooMessage") == NULL);
  253. EXPECT_TRUE(baz_file_->FindMessageTypeByName("FooMessage") == NULL);
  254. EXPECT_TRUE(foo_file_->FindMessageTypeByName("NoSuchMessage") == NULL);
  255. EXPECT_TRUE(foo_file_->FindMessageTypeByName("FooEnum") == NULL);
  256. }
  257. TEST_F(FileDescriptorTest, FindEnumTypeByName) {
  258. EXPECT_EQ(foo_enum_, foo_file_->FindEnumTypeByName("FooEnum"));
  259. EXPECT_EQ(bar_enum_, bar_file_->FindEnumTypeByName("BarEnum"));
  260. EXPECT_TRUE(foo_file_->FindEnumTypeByName("BarEnum") == NULL);
  261. EXPECT_TRUE(bar_file_->FindEnumTypeByName("FooEnum") == NULL);
  262. EXPECT_TRUE(baz_file_->FindEnumTypeByName("FooEnum") == NULL);
  263. EXPECT_TRUE(foo_file_->FindEnumTypeByName("NoSuchEnum") == NULL);
  264. EXPECT_TRUE(foo_file_->FindEnumTypeByName("FooMessage") == NULL);
  265. }
  266. TEST_F(FileDescriptorTest, FindEnumValueByName) {
  267. EXPECT_EQ(foo_enum_value_, foo_file_->FindEnumValueByName("FOO_ENUM_VALUE"));
  268. EXPECT_EQ(bar_enum_value_, bar_file_->FindEnumValueByName("BAR_ENUM_VALUE"));
  269. EXPECT_TRUE(foo_file_->FindEnumValueByName("BAR_ENUM_VALUE") == NULL);
  270. EXPECT_TRUE(bar_file_->FindEnumValueByName("FOO_ENUM_VALUE") == NULL);
  271. EXPECT_TRUE(baz_file_->FindEnumValueByName("FOO_ENUM_VALUE") == NULL);
  272. EXPECT_TRUE(foo_file_->FindEnumValueByName("NO_SUCH_VALUE") == NULL);
  273. EXPECT_TRUE(foo_file_->FindEnumValueByName("FooMessage") == NULL);
  274. }
  275. TEST_F(FileDescriptorTest, FindServiceByName) {
  276. EXPECT_EQ(foo_service_, foo_file_->FindServiceByName("FooService"));
  277. EXPECT_EQ(bar_service_, bar_file_->FindServiceByName("BarService"));
  278. EXPECT_TRUE(foo_file_->FindServiceByName("BarService") == NULL);
  279. EXPECT_TRUE(bar_file_->FindServiceByName("FooService") == NULL);
  280. EXPECT_TRUE(baz_file_->FindServiceByName("FooService") == NULL);
  281. EXPECT_TRUE(foo_file_->FindServiceByName("NoSuchService") == NULL);
  282. EXPECT_TRUE(foo_file_->FindServiceByName("FooMessage") == NULL);
  283. }
  284. TEST_F(FileDescriptorTest, FindExtensionByName) {
  285. EXPECT_EQ(foo_extension_, foo_file_->FindExtensionByName("foo_extension"));
  286. EXPECT_EQ(bar_extension_, bar_file_->FindExtensionByName("bar_extension"));
  287. EXPECT_TRUE(foo_file_->FindExtensionByName("bar_extension") == NULL);
  288. EXPECT_TRUE(bar_file_->FindExtensionByName("foo_extension") == NULL);
  289. EXPECT_TRUE(baz_file_->FindExtensionByName("foo_extension") == NULL);
  290. EXPECT_TRUE(foo_file_->FindExtensionByName("no_such_extension") == NULL);
  291. EXPECT_TRUE(foo_file_->FindExtensionByName("FooMessage") == NULL);
  292. }
  293. TEST_F(FileDescriptorTest, FindExtensionByNumber) {
  294. EXPECT_EQ(foo_extension_, pool_.FindExtensionByNumber(foo_message_, 1));
  295. EXPECT_EQ(bar_extension_, pool_.FindExtensionByNumber(bar_message_, 1));
  296. EXPECT_TRUE(pool_.FindExtensionByNumber(foo_message_, 2) == NULL);
  297. }
  298. TEST_F(FileDescriptorTest, BuildAgain) {
  299. // Test that if te call BuildFile again on the same input we get the same
  300. // FileDescriptor back.
  301. FileDescriptorProto file;
  302. foo_file_->CopyTo(&file);
  303. EXPECT_EQ(foo_file_, pool_.BuildFile(file));
  304. // But if we change the file then it won't work.
  305. file.set_package("some.other.package");
  306. EXPECT_TRUE(pool_.BuildFile(file) == NULL);
  307. }
  308. // ===================================================================
  309. // Test simple flat messages and fields.
  310. class DescriptorTest : public testing::Test {
  311. protected:
  312. virtual void SetUp() {
  313. // Build descriptors for the following definitions:
  314. //
  315. // // in "foo.proto"
  316. // message TestForeign {}
  317. // enum TestEnum {}
  318. //
  319. // message TestMessage {
  320. // required string foo = 1;
  321. // optional TestEnum bar = 6;
  322. // repeated TestForeign baz = 500000000;
  323. // optional group qux = 15 {}
  324. // }
  325. //
  326. // // in "bar.proto"
  327. // package corge.grault;
  328. // message TestMessage2 {
  329. // required string foo = 1;
  330. // required string bar = 2;
  331. // required string quux = 6;
  332. // }
  333. //
  334. // We cheat and use TestForeign as the type for qux rather than create
  335. // an actual nested type.
  336. //
  337. // Since all primitive types (including string) use the same building
  338. // code, there's no need to test each one individually.
  339. //
  340. // TestMessage2 is primarily here to test FindFieldByName and friends.
  341. // All messages created from the same DescriptorPool share the same lookup
  342. // table, so we need to insure that they don't interfere.
  343. FileDescriptorProto foo_file;
  344. foo_file.set_name("foo.proto");
  345. AddMessage(&foo_file, "TestForeign");
  346. AddEmptyEnum(&foo_file, "TestEnum");
  347. DescriptorProto* message = AddMessage(&foo_file, "TestMessage");
  348. AddField(message, "foo", 1,
  349. FieldDescriptorProto::LABEL_REQUIRED,
  350. FieldDescriptorProto::TYPE_STRING);
  351. AddField(message, "bar", 6,
  352. FieldDescriptorProto::LABEL_OPTIONAL,
  353. FieldDescriptorProto::TYPE_ENUM)
  354. ->set_type_name("TestEnum");
  355. AddField(message, "baz", 500000000,
  356. FieldDescriptorProto::LABEL_REPEATED,
  357. FieldDescriptorProto::TYPE_MESSAGE)
  358. ->set_type_name("TestForeign");
  359. AddField(message, "qux", 15,
  360. FieldDescriptorProto::LABEL_OPTIONAL,
  361. FieldDescriptorProto::TYPE_GROUP)
  362. ->set_type_name("TestForeign");
  363. FileDescriptorProto bar_file;
  364. bar_file.set_name("bar.proto");
  365. bar_file.set_package("corge.grault");
  366. DescriptorProto* message2 = AddMessage(&bar_file, "TestMessage2");
  367. AddField(message2, "foo", 1,
  368. FieldDescriptorProto::LABEL_REQUIRED,
  369. FieldDescriptorProto::TYPE_STRING);
  370. AddField(message2, "bar", 2,
  371. FieldDescriptorProto::LABEL_REQUIRED,
  372. FieldDescriptorProto::TYPE_STRING);
  373. AddField(message2, "quux", 6,
  374. FieldDescriptorProto::LABEL_REQUIRED,
  375. FieldDescriptorProto::TYPE_STRING);
  376. // Build the descriptors and get the pointers.
  377. foo_file_ = pool_.BuildFile(foo_file);
  378. ASSERT_TRUE(foo_file_ != NULL);
  379. bar_file_ = pool_.BuildFile(bar_file);
  380. ASSERT_TRUE(bar_file_ != NULL);
  381. ASSERT_EQ(1, foo_file_->enum_type_count());
  382. enum_ = foo_file_->enum_type(0);
  383. ASSERT_EQ(2, foo_file_->message_type_count());
  384. foreign_ = foo_file_->message_type(0);
  385. message_ = foo_file_->message_type(1);
  386. ASSERT_EQ(4, message_->field_count());
  387. foo_ = message_->field(0);
  388. bar_ = message_->field(1);
  389. baz_ = message_->field(2);
  390. qux_ = message_->field(3);
  391. ASSERT_EQ(1, bar_file_->message_type_count());
  392. message2_ = bar_file_->message_type(0);
  393. ASSERT_EQ(3, message2_->field_count());
  394. foo2_ = message2_->field(0);
  395. bar2_ = message2_->field(1);
  396. quux2_ = message2_->field(2);
  397. }
  398. DescriptorPool pool_;
  399. const FileDescriptor* foo_file_;
  400. const FileDescriptor* bar_file_;
  401. const Descriptor* message_;
  402. const Descriptor* message2_;
  403. const Descriptor* foreign_;
  404. const EnumDescriptor* enum_;
  405. const FieldDescriptor* foo_;
  406. const FieldDescriptor* bar_;
  407. const FieldDescriptor* baz_;
  408. const FieldDescriptor* qux_;
  409. const FieldDescriptor* foo2_;
  410. const FieldDescriptor* bar2_;
  411. const FieldDescriptor* quux2_;
  412. };
  413. TEST_F(DescriptorTest, Name) {
  414. EXPECT_EQ("TestMessage", message_->name());
  415. EXPECT_EQ("TestMessage", message_->full_name());
  416. EXPECT_EQ(foo_file_, message_->file());
  417. EXPECT_EQ("TestMessage2", message2_->name());
  418. EXPECT_EQ("corge.grault.TestMessage2", message2_->full_name());
  419. EXPECT_EQ(bar_file_, message2_->file());
  420. }
  421. TEST_F(DescriptorTest, ContainingType) {
  422. EXPECT_TRUE(message_->containing_type() == NULL);
  423. EXPECT_TRUE(message2_->containing_type() == NULL);
  424. }
  425. TEST_F(DescriptorTest, FieldsByIndex) {
  426. ASSERT_EQ(4, message_->field_count());
  427. EXPECT_EQ(foo_, message_->field(0));
  428. EXPECT_EQ(bar_, message_->field(1));
  429. EXPECT_EQ(baz_, message_->field(2));
  430. EXPECT_EQ(qux_, message_->field(3));
  431. }
  432. TEST_F(DescriptorTest, FindFieldByName) {
  433. // All messages in the same DescriptorPool share a single lookup table for
  434. // fields. So, in addition to testing that FindFieldByName finds the fields
  435. // of the message, we need to test that it does *not* find the fields of
  436. // *other* messages.
  437. EXPECT_EQ(foo_, message_->FindFieldByName("foo"));
  438. EXPECT_EQ(bar_, message_->FindFieldByName("bar"));
  439. EXPECT_EQ(baz_, message_->FindFieldByName("baz"));
  440. EXPECT_EQ(qux_, message_->FindFieldByName("qux"));
  441. EXPECT_TRUE(message_->FindFieldByName("no_such_field") == NULL);
  442. EXPECT_TRUE(message_->FindFieldByName("quux") == NULL);
  443. EXPECT_EQ(foo2_ , message2_->FindFieldByName("foo" ));
  444. EXPECT_EQ(bar2_ , message2_->FindFieldByName("bar" ));
  445. EXPECT_EQ(quux2_, message2_->FindFieldByName("quux"));
  446. EXPECT_TRUE(message2_->FindFieldByName("baz") == NULL);
  447. EXPECT_TRUE(message2_->FindFieldByName("qux") == NULL);
  448. }
  449. TEST_F(DescriptorTest, FindFieldByNumber) {
  450. EXPECT_EQ(foo_, message_->FindFieldByNumber(1));
  451. EXPECT_EQ(bar_, message_->FindFieldByNumber(6));
  452. EXPECT_EQ(baz_, message_->FindFieldByNumber(500000000));
  453. EXPECT_EQ(qux_, message_->FindFieldByNumber(15));
  454. EXPECT_TRUE(message_->FindFieldByNumber(837592) == NULL);
  455. EXPECT_TRUE(message_->FindFieldByNumber(2) == NULL);
  456. EXPECT_EQ(foo2_ , message2_->FindFieldByNumber(1));
  457. EXPECT_EQ(bar2_ , message2_->FindFieldByNumber(2));
  458. EXPECT_EQ(quux2_, message2_->FindFieldByNumber(6));
  459. EXPECT_TRUE(message2_->FindFieldByNumber(15) == NULL);
  460. EXPECT_TRUE(message2_->FindFieldByNumber(500000000) == NULL);
  461. }
  462. TEST_F(DescriptorTest, FieldName) {
  463. EXPECT_EQ("foo", foo_->name());
  464. EXPECT_EQ("bar", bar_->name());
  465. EXPECT_EQ("baz", baz_->name());
  466. EXPECT_EQ("qux", qux_->name());
  467. }
  468. TEST_F(DescriptorTest, FieldFullName) {
  469. EXPECT_EQ("TestMessage.foo", foo_->full_name());
  470. EXPECT_EQ("TestMessage.bar", bar_->full_name());
  471. EXPECT_EQ("TestMessage.baz", baz_->full_name());
  472. EXPECT_EQ("TestMessage.qux", qux_->full_name());
  473. EXPECT_EQ("corge.grault.TestMessage2.foo", foo2_->full_name());
  474. EXPECT_EQ("corge.grault.TestMessage2.bar", bar2_->full_name());
  475. EXPECT_EQ("corge.grault.TestMessage2.quux", quux2_->full_name());
  476. }
  477. TEST_F(DescriptorTest, FieldFile) {
  478. EXPECT_EQ(foo_file_, foo_->file());
  479. EXPECT_EQ(foo_file_, bar_->file());
  480. EXPECT_EQ(foo_file_, baz_->file());
  481. EXPECT_EQ(foo_file_, qux_->file());
  482. EXPECT_EQ(bar_file_, foo2_->file());
  483. EXPECT_EQ(bar_file_, bar2_->file());
  484. EXPECT_EQ(bar_file_, quux2_->file());
  485. }
  486. TEST_F(DescriptorTest, FieldIndex) {
  487. EXPECT_EQ(0, foo_->index());
  488. EXPECT_EQ(1, bar_->index());
  489. EXPECT_EQ(2, baz_->index());
  490. EXPECT_EQ(3, qux_->index());
  491. }
  492. TEST_F(DescriptorTest, FieldNumber) {
  493. EXPECT_EQ( 1, foo_->number());
  494. EXPECT_EQ( 6, bar_->number());
  495. EXPECT_EQ(500000000, baz_->number());
  496. EXPECT_EQ( 15, qux_->number());
  497. }
  498. TEST_F(DescriptorTest, FieldType) {
  499. EXPECT_EQ(FieldDescriptor::TYPE_STRING , foo_->type());
  500. EXPECT_EQ(FieldDescriptor::TYPE_ENUM , bar_->type());
  501. EXPECT_EQ(FieldDescriptor::TYPE_MESSAGE, baz_->type());
  502. EXPECT_EQ(FieldDescriptor::TYPE_GROUP , qux_->type());
  503. }
  504. TEST_F(DescriptorTest, FieldLabel) {
  505. EXPECT_EQ(FieldDescriptor::LABEL_REQUIRED, foo_->label());
  506. EXPECT_EQ(FieldDescriptor::LABEL_OPTIONAL, bar_->label());
  507. EXPECT_EQ(FieldDescriptor::LABEL_REPEATED, baz_->label());
  508. EXPECT_EQ(FieldDescriptor::LABEL_OPTIONAL, qux_->label());
  509. EXPECT_TRUE (foo_->is_required());
  510. EXPECT_FALSE(foo_->is_optional());
  511. EXPECT_FALSE(foo_->is_repeated());
  512. EXPECT_FALSE(bar_->is_required());
  513. EXPECT_TRUE (bar_->is_optional());
  514. EXPECT_FALSE(bar_->is_repeated());
  515. EXPECT_FALSE(baz_->is_required());
  516. EXPECT_FALSE(baz_->is_optional());
  517. EXPECT_TRUE (baz_->is_repeated());
  518. }
  519. TEST_F(DescriptorTest, FieldHasDefault) {
  520. EXPECT_FALSE(foo_->has_default_value());
  521. EXPECT_FALSE(bar_->has_default_value());
  522. EXPECT_FALSE(baz_->has_default_value());
  523. EXPECT_FALSE(qux_->has_default_value());
  524. }
  525. TEST_F(DescriptorTest, FieldContainingType) {
  526. EXPECT_EQ(message_, foo_->containing_type());
  527. EXPECT_EQ(message_, bar_->containing_type());
  528. EXPECT_EQ(message_, baz_->containing_type());
  529. EXPECT_EQ(message_, qux_->containing_type());
  530. EXPECT_EQ(message2_, foo2_ ->containing_type());
  531. EXPECT_EQ(message2_, bar2_ ->containing_type());
  532. EXPECT_EQ(message2_, quux2_->containing_type());
  533. }
  534. TEST_F(DescriptorTest, FieldMessageType) {
  535. EXPECT_TRUE(foo_->message_type() == NULL);
  536. EXPECT_TRUE(bar_->message_type() == NULL);
  537. EXPECT_EQ(foreign_, baz_->message_type());
  538. EXPECT_EQ(foreign_, qux_->message_type());
  539. }
  540. TEST_F(DescriptorTest, FieldEnumType) {
  541. EXPECT_TRUE(foo_->enum_type() == NULL);
  542. EXPECT_TRUE(baz_->enum_type() == NULL);
  543. EXPECT_TRUE(qux_->enum_type() == NULL);
  544. EXPECT_EQ(enum_, bar_->enum_type());
  545. }
  546. // ===================================================================
  547. class StylizedFieldNamesTest : public testing::Test {
  548. protected:
  549. void SetUp() {
  550. FileDescriptorProto file;
  551. file.set_name("foo.proto");
  552. AddExtensionRange(AddMessage(&file, "ExtendableMessage"), 1, 1000);
  553. DescriptorProto* message = AddMessage(&file, "TestMessage");
  554. AddField(message, "foo_foo", 1,
  555. FieldDescriptorProto::LABEL_OPTIONAL,
  556. FieldDescriptorProto::TYPE_INT32);
  557. AddField(message, "FooBar", 2,
  558. FieldDescriptorProto::LABEL_OPTIONAL,
  559. FieldDescriptorProto::TYPE_INT32);
  560. AddField(message, "fooBaz", 3,
  561. FieldDescriptorProto::LABEL_OPTIONAL,
  562. FieldDescriptorProto::TYPE_INT32);
  563. AddField(message, "fooFoo", 4, // Camel-case conflict with foo_foo.
  564. FieldDescriptorProto::LABEL_OPTIONAL,
  565. FieldDescriptorProto::TYPE_INT32);
  566. AddField(message, "foobar", 5, // Lower-case conflict with FooBar.
  567. FieldDescriptorProto::LABEL_OPTIONAL,
  568. FieldDescriptorProto::TYPE_INT32);
  569. AddNestedExtension(message, "ExtendableMessage", "bar_foo", 1,
  570. FieldDescriptorProto::LABEL_OPTIONAL,
  571. FieldDescriptorProto::TYPE_INT32);
  572. AddNestedExtension(message, "ExtendableMessage", "BarBar", 2,
  573. FieldDescriptorProto::LABEL_OPTIONAL,
  574. FieldDescriptorProto::TYPE_INT32);
  575. AddNestedExtension(message, "ExtendableMessage", "BarBaz", 3,
  576. FieldDescriptorProto::LABEL_OPTIONAL,
  577. FieldDescriptorProto::TYPE_INT32);
  578. AddNestedExtension(message, "ExtendableMessage", "barFoo", 4, // Conflict
  579. FieldDescriptorProto::LABEL_OPTIONAL,
  580. FieldDescriptorProto::TYPE_INT32);
  581. AddNestedExtension(message, "ExtendableMessage", "barbar", 5, // Conflict
  582. FieldDescriptorProto::LABEL_OPTIONAL,
  583. FieldDescriptorProto::TYPE_INT32);
  584. AddExtension(&file, "ExtendableMessage", "baz_foo", 11,
  585. FieldDescriptorProto::LABEL_OPTIONAL,
  586. FieldDescriptorProto::TYPE_INT32);
  587. AddExtension(&file, "ExtendableMessage", "BazBar", 12,
  588. FieldDescriptorProto::LABEL_OPTIONAL,
  589. FieldDescriptorProto::TYPE_INT32);
  590. AddExtension(&file, "ExtendableMessage", "BazBaz", 13,
  591. FieldDescriptorProto::LABEL_OPTIONAL,
  592. FieldDescriptorProto::TYPE_INT32);
  593. AddExtension(&file, "ExtendableMessage", "bazFoo", 14, // Conflict
  594. FieldDescriptorProto::LABEL_OPTIONAL,
  595. FieldDescriptorProto::TYPE_INT32);
  596. AddExtension(&file, "ExtendableMessage", "bazbar", 15, // Conflict
  597. FieldDescriptorProto::LABEL_OPTIONAL,
  598. FieldDescriptorProto::TYPE_INT32);
  599. file_ = pool_.BuildFile(file);
  600. ASSERT_TRUE(file_ != NULL);
  601. ASSERT_EQ(2, file_->message_type_count());
  602. message_ = file_->message_type(1);
  603. ASSERT_EQ("TestMessage", message_->name());
  604. ASSERT_EQ(5, message_->field_count());
  605. ASSERT_EQ(5, message_->extension_count());
  606. ASSERT_EQ(5, file_->extension_count());
  607. }
  608. DescriptorPool pool_;
  609. const FileDescriptor* file_;
  610. const Descriptor* message_;
  611. };
  612. TEST_F(StylizedFieldNamesTest, LowercaseName) {
  613. EXPECT_EQ("foo_foo", message_->field(0)->lowercase_name());
  614. EXPECT_EQ("foobar" , message_->field(1)->lowercase_name());
  615. EXPECT_EQ("foobaz" , message_->field(2)->lowercase_name());
  616. EXPECT_EQ("foofoo" , message_->field(3)->lowercase_name());
  617. EXPECT_EQ("foobar" , message_->field(4)->lowercase_name());
  618. EXPECT_EQ("bar_foo", message_->extension(0)->lowercase_name());
  619. EXPECT_EQ("barbar" , message_->extension(1)->lowercase_name());
  620. EXPECT_EQ("barbaz" , message_->extension(2)->lowercase_name());
  621. EXPECT_EQ("barfoo" , message_->extension(3)->lowercase_name());
  622. EXPECT_EQ("barbar" , message_->extension(4)->lowercase_name());
  623. EXPECT_EQ("baz_foo", file_->extension(0)->lowercase_name());
  624. EXPECT_EQ("bazbar" , file_->extension(1)->lowercase_name());
  625. EXPECT_EQ("bazbaz" , file_->extension(2)->lowercase_name());
  626. EXPECT_EQ("bazfoo" , file_->extension(3)->lowercase_name());
  627. EXPECT_EQ("bazbar" , file_->extension(4)->lowercase_name());
  628. }
  629. TEST_F(StylizedFieldNamesTest, CamelcaseName) {
  630. EXPECT_EQ("fooFoo", message_->field(0)->camelcase_name());
  631. EXPECT_EQ("fooBar", message_->field(1)->camelcase_name());
  632. EXPECT_EQ("fooBaz", message_->field(2)->camelcase_name());
  633. EXPECT_EQ("fooFoo", message_->field(3)->camelcase_name());
  634. EXPECT_EQ("foobar", message_->field(4)->camelcase_name());
  635. EXPECT_EQ("barFoo", message_->extension(0)->camelcase_name());
  636. EXPECT_EQ("barBar", message_->extension(1)->camelcase_name());
  637. EXPECT_EQ("barBaz", message_->extension(2)->camelcase_name());
  638. EXPECT_EQ("barFoo", message_->extension(3)->camelcase_name());
  639. EXPECT_EQ("barbar", message_->extension(4)->camelcase_name());
  640. EXPECT_EQ("bazFoo", file_->extension(0)->camelcase_name());
  641. EXPECT_EQ("bazBar", file_->extension(1)->camelcase_name());
  642. EXPECT_EQ("bazBaz", file_->extension(2)->camelcase_name());
  643. EXPECT_EQ("bazFoo", file_->extension(3)->camelcase_name());
  644. EXPECT_EQ("bazbar", file_->extension(4)->camelcase_name());
  645. }
  646. TEST_F(StylizedFieldNamesTest, FindByLowercaseName) {
  647. EXPECT_EQ(message_->field(0),
  648. message_->FindFieldByLowercaseName("foo_foo"));
  649. EXPECT_EQ(message_->field(1),
  650. message_->FindFieldByLowercaseName("foobar"));
  651. EXPECT_EQ(message_->field(2),
  652. message_->FindFieldByLowercaseName("foobaz"));
  653. EXPECT_TRUE(message_->FindFieldByLowercaseName("FooBar") == NULL);
  654. EXPECT_TRUE(message_->FindFieldByLowercaseName("fooBaz") == NULL);
  655. EXPECT_TRUE(message_->FindFieldByLowercaseName("bar_foo") == NULL);
  656. EXPECT_TRUE(message_->FindFieldByLowercaseName("nosuchfield") == NULL);
  657. EXPECT_EQ(message_->extension(0),
  658. message_->FindExtensionByLowercaseName("bar_foo"));
  659. EXPECT_EQ(message_->extension(1),
  660. message_->FindExtensionByLowercaseName("barbar"));
  661. EXPECT_EQ(message_->extension(2),
  662. message_->FindExtensionByLowercaseName("barbaz"));
  663. EXPECT_TRUE(message_->FindExtensionByLowercaseName("BarBar") == NULL);
  664. EXPECT_TRUE(message_->FindExtensionByLowercaseName("barBaz") == NULL);
  665. EXPECT_TRUE(message_->FindExtensionByLowercaseName("foo_foo") == NULL);
  666. EXPECT_TRUE(message_->FindExtensionByLowercaseName("nosuchfield") == NULL);
  667. EXPECT_EQ(file_->extension(0),
  668. file_->FindExtensionByLowercaseName("baz_foo"));
  669. EXPECT_EQ(file_->extension(1),
  670. file_->FindExtensionByLowercaseName("bazbar"));
  671. EXPECT_EQ(file_->extension(2),
  672. file_->FindExtensionByLowercaseName("bazbaz"));
  673. EXPECT_TRUE(file_->FindExtensionByLowercaseName("BazBar") == NULL);
  674. EXPECT_TRUE(file_->FindExtensionByLowercaseName("bazBaz") == NULL);
  675. EXPECT_TRUE(file_->FindExtensionByLowercaseName("nosuchfield") == NULL);
  676. }
  677. TEST_F(StylizedFieldNamesTest, FindByCamelcaseName) {
  678. EXPECT_EQ(message_->field(0),
  679. message_->FindFieldByCamelcaseName("fooFoo"));
  680. EXPECT_EQ(message_->field(1),
  681. message_->FindFieldByCamelcaseName("fooBar"));
  682. EXPECT_EQ(message_->field(2),
  683. message_->FindFieldByCamelcaseName("fooBaz"));
  684. EXPECT_TRUE(message_->FindFieldByCamelcaseName("foo_foo") == NULL);
  685. EXPECT_TRUE(message_->FindFieldByCamelcaseName("FooBar") == NULL);
  686. EXPECT_TRUE(message_->FindFieldByCamelcaseName("barFoo") == NULL);
  687. EXPECT_TRUE(message_->FindFieldByCamelcaseName("nosuchfield") == NULL);
  688. EXPECT_EQ(message_->extension(0),
  689. message_->FindExtensionByCamelcaseName("barFoo"));
  690. EXPECT_EQ(message_->extension(1),
  691. message_->FindExtensionByCamelcaseName("barBar"));
  692. EXPECT_EQ(message_->extension(2),
  693. message_->FindExtensionByCamelcaseName("barBaz"));
  694. EXPECT_TRUE(message_->FindExtensionByCamelcaseName("bar_foo") == NULL);
  695. EXPECT_TRUE(message_->FindExtensionByCamelcaseName("BarBar") == NULL);
  696. EXPECT_TRUE(message_->FindExtensionByCamelcaseName("fooFoo") == NULL);
  697. EXPECT_TRUE(message_->FindExtensionByCamelcaseName("nosuchfield") == NULL);
  698. EXPECT_EQ(file_->extension(0),
  699. file_->FindExtensionByCamelcaseName("bazFoo"));
  700. EXPECT_EQ(file_->extension(1),
  701. file_->FindExtensionByCamelcaseName("bazBar"));
  702. EXPECT_EQ(file_->extension(2),
  703. file_->FindExtensionByCamelcaseName("bazBaz"));
  704. EXPECT_TRUE(file_->FindExtensionByCamelcaseName("baz_foo") == NULL);
  705. EXPECT_TRUE(file_->FindExtensionByCamelcaseName("BazBar") == NULL);
  706. EXPECT_TRUE(file_->FindExtensionByCamelcaseName("nosuchfield") == NULL);
  707. }
  708. // ===================================================================
  709. // Test enum descriptors.
  710. class EnumDescriptorTest : public testing::Test {
  711. protected:
  712. virtual void SetUp() {
  713. // Build descriptors for the following definitions:
  714. //
  715. // // in "foo.proto"
  716. // enum TestEnum {
  717. // FOO = 1;
  718. // BAR = 2;
  719. // }
  720. //
  721. // // in "bar.proto"
  722. // package corge.grault;
  723. // enum TestEnum2 {
  724. // FOO = 1;
  725. // BAZ = 3;
  726. // }
  727. //
  728. // TestEnum2 is primarily here to test FindValueByName and friends.
  729. // All enums created from the same DescriptorPool share the same lookup
  730. // table, so we need to insure that they don't interfere.
  731. // TestEnum
  732. FileDescriptorProto foo_file;
  733. foo_file.set_name("foo.proto");
  734. EnumDescriptorProto* enum_proto = AddEnum(&foo_file, "TestEnum");
  735. AddEnumValue(enum_proto, "FOO", 1);
  736. AddEnumValue(enum_proto, "BAR", 2);
  737. // TestEnum2
  738. FileDescriptorProto bar_file;
  739. bar_file.set_name("bar.proto");
  740. bar_file.set_package("corge.grault");
  741. EnumDescriptorProto* enum2_proto = AddEnum(&bar_file, "TestEnum2");
  742. AddEnumValue(enum2_proto, "FOO", 1);
  743. AddEnumValue(enum2_proto, "BAZ", 3);
  744. // Build the descriptors and get the pointers.
  745. foo_file_ = pool_.BuildFile(foo_file);
  746. ASSERT_TRUE(foo_file_ != NULL);
  747. bar_file_ = pool_.BuildFile(bar_file);
  748. ASSERT_TRUE(bar_file_ != NULL);
  749. ASSERT_EQ(1, foo_file_->enum_type_count());
  750. enum_ = foo_file_->enum_type(0);
  751. ASSERT_EQ(2, enum_->value_count());
  752. foo_ = enum_->value(0);
  753. bar_ = enum_->value(1);
  754. ASSERT_EQ(1, bar_file_->enum_type_count());
  755. enum2_ = bar_file_->enum_type(0);
  756. ASSERT_EQ(2, enum2_->value_count());
  757. foo2_ = enum2_->value(0);
  758. baz2_ = enum2_->value(1);
  759. }
  760. DescriptorPool pool_;
  761. const FileDescriptor* foo_file_;
  762. const FileDescriptor* bar_file_;
  763. const EnumDescriptor* enum_;
  764. const EnumDescriptor* enum2_;
  765. const EnumValueDescriptor* foo_;
  766. const EnumValueDescriptor* bar_;
  767. const EnumValueDescriptor* foo2_;
  768. const EnumValueDescriptor* baz2_;
  769. };
  770. TEST_F(EnumDescriptorTest, Name) {
  771. EXPECT_EQ("TestEnum", enum_->name());
  772. EXPECT_EQ("TestEnum", enum_->full_name());
  773. EXPECT_EQ(foo_file_, enum_->file());
  774. EXPECT_EQ("TestEnum2", enum2_->name());
  775. EXPECT_EQ("corge.grault.TestEnum2", enum2_->full_name());
  776. EXPECT_EQ(bar_file_, enum2_->file());
  777. }
  778. TEST_F(EnumDescriptorTest, ContainingType) {
  779. EXPECT_TRUE(enum_->containing_type() == NULL);
  780. EXPECT_TRUE(enum2_->containing_type() == NULL);
  781. }
  782. TEST_F(EnumDescriptorTest, ValuesByIndex) {
  783. ASSERT_EQ(2, enum_->value_count());
  784. EXPECT_EQ(foo_, enum_->value(0));
  785. EXPECT_EQ(bar_, enum_->value(1));
  786. }
  787. TEST_F(EnumDescriptorTest, FindValueByName) {
  788. EXPECT_EQ(foo_ , enum_ ->FindValueByName("FOO"));
  789. EXPECT_EQ(bar_ , enum_ ->FindValueByName("BAR"));
  790. EXPECT_EQ(foo2_, enum2_->FindValueByName("FOO"));
  791. EXPECT_EQ(baz2_, enum2_->FindValueByName("BAZ"));
  792. EXPECT_TRUE(enum_ ->FindValueByName("NO_SUCH_VALUE") == NULL);
  793. EXPECT_TRUE(enum_ ->FindValueByName("BAZ" ) == NULL);
  794. EXPECT_TRUE(enum2_->FindValueByName("BAR" ) == NULL);
  795. }
  796. TEST_F(EnumDescriptorTest, FindValueByNumber) {
  797. EXPECT_EQ(foo_ , enum_ ->FindValueByNumber(1));
  798. EXPECT_EQ(bar_ , enum_ ->FindValueByNumber(2));
  799. EXPECT_EQ(foo2_, enum2_->FindValueByNumber(1));
  800. EXPECT_EQ(baz2_, enum2_->FindValueByNumber(3));
  801. EXPECT_TRUE(enum_ ->FindValueByNumber(416) == NULL);
  802. EXPECT_TRUE(enum_ ->FindValueByNumber(3) == NULL);
  803. EXPECT_TRUE(enum2_->FindValueByNumber(2) == NULL);
  804. }
  805. TEST_F(EnumDescriptorTest, ValueName) {
  806. EXPECT_EQ("FOO", foo_->name());
  807. EXPECT_EQ("BAR", bar_->name());
  808. }
  809. TEST_F(EnumDescriptorTest, ValueFullName) {
  810. EXPECT_EQ("FOO", foo_->full_name());
  811. EXPECT_EQ("BAR", bar_->full_name());
  812. EXPECT_EQ("corge.grault.FOO", foo2_->full_name());
  813. EXPECT_EQ("corge.grault.BAZ", baz2_->full_name());
  814. }
  815. TEST_F(EnumDescriptorTest, ValueIndex) {
  816. EXPECT_EQ(0, foo_->index());
  817. EXPECT_EQ(1, bar_->index());
  818. }
  819. TEST_F(EnumDescriptorTest, ValueNumber) {
  820. EXPECT_EQ(1, foo_->number());
  821. EXPECT_EQ(2, bar_->number());
  822. }
  823. TEST_F(EnumDescriptorTest, ValueType) {
  824. EXPECT_EQ(enum_ , foo_ ->type());
  825. EXPECT_EQ(enum_ , bar_ ->type());
  826. EXPECT_EQ(enum2_, foo2_->type());
  827. EXPECT_EQ(enum2_, baz2_->type());
  828. }
  829. // ===================================================================
  830. // Test service descriptors.
  831. class ServiceDescriptorTest : public testing::Test {
  832. protected:
  833. virtual void SetUp() {
  834. // Build descriptors for the following messages and service:
  835. // // in "foo.proto"
  836. // message FooRequest {}
  837. // message FooResponse {}
  838. // message BarRequest {}
  839. // message BarResponse {}
  840. // message BazRequest {}
  841. // message BazResponse {}
  842. //
  843. // service TestService {
  844. // rpc Foo(FooRequest) returns (FooResponse);
  845. // rpc Bar(BarRequest) returns (BarResponse);
  846. // }
  847. //
  848. // // in "bar.proto"
  849. // package corge.grault
  850. // service TestService2 {
  851. // rpc Foo(FooRequest) returns (FooResponse);
  852. // rpc Baz(BazRequest) returns (BazResponse);
  853. // }
  854. FileDescriptorProto foo_file;
  855. foo_file.set_name("foo.proto");
  856. AddMessage(&foo_file, "FooRequest");
  857. AddMessage(&foo_file, "FooResponse");
  858. AddMessage(&foo_file, "BarRequest");
  859. AddMessage(&foo_file, "BarResponse");
  860. AddMessage(&foo_file, "BazRequest");
  861. AddMessage(&foo_file, "BazResponse");
  862. ServiceDescriptorProto* service = AddService(&foo_file, "TestService");
  863. AddMethod(service, "Foo", "FooRequest", "FooResponse");
  864. AddMethod(service, "Bar", "BarRequest", "BarResponse");
  865. FileDescriptorProto bar_file;
  866. bar_file.set_name("bar.proto");
  867. bar_file.set_package("corge.grault");
  868. bar_file.add_dependency("foo.proto");
  869. ServiceDescriptorProto* service2 = AddService(&bar_file, "TestService2");
  870. AddMethod(service2, "Foo", "FooRequest", "FooResponse");
  871. AddMethod(service2, "Baz", "BazRequest", "BazResponse");
  872. // Build the descriptors and get the pointers.
  873. foo_file_ = pool_.BuildFile(foo_file);
  874. ASSERT_TRUE(foo_file_ != NULL);
  875. bar_file_ = pool_.BuildFile(bar_file);
  876. ASSERT_TRUE(bar_file_ != NULL);
  877. ASSERT_EQ(6, foo_file_->message_type_count());
  878. foo_request_ = foo_file_->message_type(0);
  879. foo_response_ = foo_file_->message_type(1);
  880. bar_request_ = foo_file_->message_type(2);
  881. bar_response_ = foo_file_->message_type(3);
  882. baz_request_ = foo_file_->message_type(4);
  883. baz_response_ = foo_file_->message_type(5);
  884. ASSERT_EQ(1, foo_file_->service_count());
  885. service_ = foo_file_->service(0);
  886. ASSERT_EQ(2, service_->method_count());
  887. foo_ = service_->method(0);
  888. bar_ = service_->method(1);
  889. ASSERT_EQ(1, bar_file_->service_count());
  890. service2_ = bar_file_->service(0);
  891. ASSERT_EQ(2, service2_->method_count());
  892. foo2_ = service2_->method(0);
  893. baz2_ = service2_->method(1);
  894. }
  895. DescriptorPool pool_;
  896. const FileDescriptor* foo_file_;
  897. const FileDescriptor* bar_file_;
  898. const Descriptor* foo_request_;
  899. const Descriptor* foo_response_;
  900. const Descriptor* bar_request_;
  901. const Descriptor* bar_response_;
  902. const Descriptor* baz_request_;
  903. const Descriptor* baz_response_;
  904. const ServiceDescriptor* service_;
  905. const ServiceDescriptor* service2_;
  906. const MethodDescriptor* foo_;
  907. const MethodDescriptor* bar_;
  908. const MethodDescriptor* foo2_;
  909. const MethodDescriptor* baz2_;
  910. };
  911. TEST_F(ServiceDescriptorTest, Name) {
  912. EXPECT_EQ("TestService", service_->name());
  913. EXPECT_EQ("TestService", service_->full_name());
  914. EXPECT_EQ(foo_file_, service_->file());
  915. EXPECT_EQ("TestService2", service2_->name());
  916. EXPECT_EQ("corge.grault.TestService2", service2_->full_name());
  917. EXPECT_EQ(bar_file_, service2_->file());
  918. }
  919. TEST_F(ServiceDescriptorTest, MethodsByIndex) {
  920. ASSERT_EQ(2, service_->method_count());
  921. EXPECT_EQ(foo_, service_->method(0));
  922. EXPECT_EQ(bar_, service_->method(1));
  923. }
  924. TEST_F(ServiceDescriptorTest, FindMethodByName) {
  925. EXPECT_EQ(foo_ , service_ ->FindMethodByName("Foo"));
  926. EXPECT_EQ(bar_ , service_ ->FindMethodByName("Bar"));
  927. EXPECT_EQ(foo2_, service2_->FindMethodByName("Foo"));
  928. EXPECT_EQ(baz2_, service2_->FindMethodByName("Baz"));
  929. EXPECT_TRUE(service_ ->FindMethodByName("NoSuchMethod") == NULL);
  930. EXPECT_TRUE(service_ ->FindMethodByName("Baz" ) == NULL);
  931. EXPECT_TRUE(service2_->FindMethodByName("Bar" ) == NULL);
  932. }
  933. TEST_F(ServiceDescriptorTest, MethodName) {
  934. EXPECT_EQ("Foo", foo_->name());
  935. EXPECT_EQ("Bar", bar_->name());
  936. }
  937. TEST_F(ServiceDescriptorTest, MethodFullName) {
  938. EXPECT_EQ("TestService.Foo", foo_->full_name());
  939. EXPECT_EQ("TestService.Bar", bar_->full_name());
  940. EXPECT_EQ("corge.grault.TestService2.Foo", foo2_->full_name());
  941. EXPECT_EQ("corge.grault.TestService2.Baz", baz2_->full_name());
  942. }
  943. TEST_F(ServiceDescriptorTest, MethodIndex) {
  944. EXPECT_EQ(0, foo_->index());
  945. EXPECT_EQ(1, bar_->index());
  946. }
  947. TEST_F(ServiceDescriptorTest, MethodParent) {
  948. EXPECT_EQ(service_, foo_->service());
  949. EXPECT_EQ(service_, bar_->service());
  950. }
  951. TEST_F(ServiceDescriptorTest, MethodInputType) {
  952. EXPECT_EQ(foo_request_, foo_->input_type());
  953. EXPECT_EQ(bar_request_, bar_->input_type());
  954. }
  955. TEST_F(ServiceDescriptorTest, MethodOutputType) {
  956. EXPECT_EQ(foo_response_, foo_->output_type());
  957. EXPECT_EQ(bar_response_, bar_->output_type());
  958. }
  959. // ===================================================================
  960. // Test nested types.
  961. class NestedDescriptorTest : public testing::Test {
  962. protected:
  963. virtual void SetUp() {
  964. // Build descriptors for the following definitions:
  965. //
  966. // // in "foo.proto"
  967. // message TestMessage {
  968. // message Foo {}
  969. // message Bar {}
  970. // enum Baz { A = 1; }
  971. // enum Qux { B = 1; }
  972. // }
  973. //
  974. // // in "bar.proto"
  975. // package corge.grault;
  976. // message TestMessage2 {
  977. // message Foo {}
  978. // message Baz {}
  979. // enum Qux { A = 1; }
  980. // enum Quux { C = 1; }
  981. // }
  982. //
  983. // TestMessage2 is primarily here to test FindNestedTypeByName and friends.
  984. // All messages created from the same DescriptorPool share the same lookup
  985. // table, so we need to insure that they don't interfere.
  986. //
  987. // We add enum values to the enums in order to test searching for enum
  988. // values across a message's scope.
  989. FileDescriptorProto foo_file;
  990. foo_file.set_name("foo.proto");
  991. DescriptorProto* message = AddMessage(&foo_file, "TestMessage");
  992. AddNestedMessage(message, "Foo");
  993. AddNestedMessage(message, "Bar");
  994. EnumDescriptorProto* baz = AddNestedEnum(message, "Baz");
  995. AddEnumValue(baz, "A", 1);
  996. EnumDescriptorProto* qux = AddNestedEnum(message, "Qux");
  997. AddEnumValue(qux, "B", 1);
  998. FileDescriptorProto bar_file;
  999. bar_file.set_name("bar.proto");
  1000. bar_file.set_package("corge.grault");
  1001. DescriptorProto* message2 = AddMessage(&bar_file, "TestMessage2");
  1002. AddNestedMessage(message2, "Foo");
  1003. AddNestedMessage(message2, "Baz");
  1004. EnumDescriptorProto* qux2 = AddNestedEnum(message2, "Qux");
  1005. AddEnumValue(qux2, "A", 1);
  1006. EnumDescriptorProto* quux2 = AddNestedEnum(message2, "Quux");
  1007. AddEnumValue(quux2, "C", 1);
  1008. // Build the descriptors and get the pointers.
  1009. foo_file_ = pool_.BuildFile(foo_file);
  1010. ASSERT_TRUE(foo_file_ != NULL);
  1011. bar_file_ = pool_.BuildFile(bar_file);
  1012. ASSERT_TRUE(bar_file_ != NULL);
  1013. ASSERT_EQ(1, foo_file_->message_type_count());
  1014. message_ = foo_file_->message_type(0);
  1015. ASSERT_EQ(2, message_->nested_type_count());
  1016. foo_ = message_->nested_type(0);
  1017. bar_ = message_->nested_type(1);
  1018. ASSERT_EQ(2, message_->enum_type_count());
  1019. baz_ = message_->enum_type(0);
  1020. qux_ = message_->enum_type(1);
  1021. ASSERT_EQ(1, baz_->value_count());
  1022. a_ = baz_->value(0);
  1023. ASSERT_EQ(1, qux_->value_count());
  1024. b_ = qux_->value(0);
  1025. ASSERT_EQ(1, bar_file_->message_type_count());
  1026. message2_ = bar_file_->message_type(0);
  1027. ASSERT_EQ(2, message2_->nested_type_count());
  1028. foo2_ = message2_->nested_type(0);
  1029. baz2_ = message2_->nested_type(1);
  1030. ASSERT_EQ(2, message2_->enum_type_count());
  1031. qux2_ = message2_->enum_type(0);
  1032. quux2_ = message2_->enum_type(1);
  1033. ASSERT_EQ(1, qux2_->value_count());
  1034. a2_ = qux2_->value(0);
  1035. ASSERT_EQ(1, quux2_->value_count());
  1036. c2_ = quux2_->value(0);
  1037. }
  1038. DescriptorPool pool_;
  1039. const FileDescriptor* foo_file_;
  1040. const FileDescriptor* bar_file_;
  1041. const Descriptor* message_;
  1042. const Descriptor* message2_;
  1043. const Descriptor* foo_;
  1044. const Descriptor* bar_;
  1045. const EnumDescriptor* baz_;
  1046. const EnumDescriptor* qux_;
  1047. const EnumValueDescriptor* a_;
  1048. const EnumValueDescriptor* b_;
  1049. const Descriptor* foo2_;
  1050. const Descriptor* baz2_;
  1051. const EnumDescriptor* qux2_;
  1052. const EnumDescriptor* quux2_;
  1053. const EnumValueDescriptor* a2_;
  1054. const EnumValueDescriptor* c2_;
  1055. };
  1056. TEST_F(NestedDescriptorTest, MessageName) {
  1057. EXPECT_EQ("Foo", foo_ ->name());
  1058. EXPECT_EQ("Bar", bar_ ->name());
  1059. EXPECT_EQ("Foo", foo2_->name());
  1060. EXPECT_EQ("Baz", baz2_->name());
  1061. EXPECT_EQ("TestMessage.Foo", foo_->full_name());
  1062. EXPECT_EQ("TestMessage.Bar", bar_->full_name());
  1063. EXPECT_EQ("corge.grault.TestMessage2.Foo", foo2_->full_name());
  1064. EXPECT_EQ("corge.grault.TestMessage2.Baz", baz2_->full_name());
  1065. }
  1066. TEST_F(NestedDescriptorTest, MessageContainingType) {
  1067. EXPECT_EQ(message_ , foo_ ->containing_type());
  1068. EXPECT_EQ(message_ , bar_ ->containing_type());
  1069. EXPECT_EQ(message2_, foo2_->containing_type());
  1070. EXPECT_EQ(message2_, baz2_->containing_type());
  1071. }
  1072. TEST_F(NestedDescriptorTest, NestedMessagesByIndex) {
  1073. ASSERT_EQ(2, message_->nested_type_count());
  1074. EXPECT_EQ(foo_, message_->nested_type(0));
  1075. EXPECT_EQ(bar_, message_->nested_type(1));
  1076. }
  1077. TEST_F(NestedDescriptorTest, FindFieldByNameDoesntFindNestedTypes) {
  1078. EXPECT_TRUE(message_->FindFieldByName("Foo") == NULL);
  1079. EXPECT_TRUE(message_->FindFieldByName("Qux") == NULL);
  1080. EXPECT_TRUE(message_->FindExtensionByName("Foo") == NULL);
  1081. EXPECT_TRUE(message_->FindExtensionByName("Qux") == NULL);
  1082. }
  1083. TEST_F(NestedDescriptorTest, FindNestedTypeByName) {
  1084. EXPECT_EQ(foo_ , message_ ->FindNestedTypeByName("Foo"));
  1085. EXPECT_EQ(bar_ , message_ ->FindNestedTypeByName("Bar"));
  1086. EXPECT_EQ(foo2_, message2_->FindNestedTypeByName("Foo"));
  1087. EXPECT_EQ(baz2_, message2_->FindNestedTypeByName("Baz"));
  1088. EXPECT_TRUE(message_ ->FindNestedTypeByName("NoSuchType") == NULL);
  1089. EXPECT_TRUE(message_ ->FindNestedTypeByName("Baz" ) == NULL);
  1090. EXPECT_TRUE(message2_->FindNestedTypeByName("Bar" ) == NULL);
  1091. EXPECT_TRUE(message_->FindNestedTypeByName("Qux") == NULL);
  1092. }
  1093. TEST_F(NestedDescriptorTest, EnumName) {
  1094. EXPECT_EQ("Baz" , baz_ ->name());
  1095. EXPECT_EQ("Qux" , qux_ ->name());
  1096. EXPECT_EQ("Qux" , qux2_->name());
  1097. EXPECT_EQ("Quux", quux2_->name());
  1098. EXPECT_EQ("TestMessage.Baz", baz_->full_name());
  1099. EXPECT_EQ("TestMessage.Qux", qux_->full_name());
  1100. EXPECT_EQ("corge.grault.TestMessage2.Qux" , qux2_ ->full_name());
  1101. EXPECT_EQ("corge.grault.TestMessage2.Quux", quux2_->full_name());
  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. TEST_F(NestedDescriptorTest, NestedEnumsByIndex) {
  1110. ASSERT_EQ(2, message_->nested_type_count());
  1111. EXPECT_EQ(foo_, message_->nested_type(0));
  1112. EXPECT_EQ(bar_, message_->nested_type(1));
  1113. }
  1114. TEST_F(NestedDescriptorTest, FindEnumTypeByName) {
  1115. EXPECT_EQ(baz_ , message_ ->FindEnumTypeByName("Baz" ));
  1116. EXPECT_EQ(qux_ , message_ ->FindEnumTypeByName("Qux" ));
  1117. EXPECT_EQ(qux2_ , message2_->FindEnumTypeByName("Qux" ));
  1118. EXPECT_EQ(quux2_, message2_->FindEnumTypeByName("Quux"));
  1119. EXPECT_TRUE(message_ ->FindEnumTypeByName("NoSuchType") == NULL);
  1120. EXPECT_TRUE(message_ ->FindEnumTypeByName("Quux" ) == NULL);
  1121. EXPECT_TRUE(message2_->FindEnumTypeByName("Baz" ) == NULL);
  1122. EXPECT_TRUE(message_->FindEnumTypeByName("Foo") == NULL);
  1123. }
  1124. TEST_F(NestedDescriptorTest, FindEnumValueByName) {
  1125. EXPECT_EQ(a_ , message_ ->FindEnumValueByName("A"));
  1126. EXPECT_EQ(b_ , message_ ->FindEnumValueByName("B"));
  1127. EXPECT_EQ(a2_, message2_->FindEnumValueByName("A"));
  1128. EXPECT_EQ(c2_, message2_->FindEnumValueByName("C"));
  1129. EXPECT_TRUE(message_ ->FindEnumValueByName("NO_SUCH_VALUE") == NULL);
  1130. EXPECT_TRUE(message_ ->FindEnumValueByName("C" ) == NULL);
  1131. EXPECT_TRUE(message2_->FindEnumValueByName("B" ) == NULL);
  1132. EXPECT_TRUE(message_->FindEnumValueByName("Foo") == NULL);
  1133. }
  1134. // ===================================================================
  1135. // Test extensions.
  1136. class ExtensionDescriptorTest : public testing::Test {
  1137. protected:
  1138. virtual void SetUp() {
  1139. // Build descriptors for the following definitions:
  1140. //
  1141. // enum Baz {}
  1142. // message Qux {}
  1143. //
  1144. // message Foo {
  1145. // extensions 10 to 19;
  1146. // extensions 30 to 39;
  1147. // }
  1148. // extends Foo with optional int32 foo_int32 = 10;
  1149. // extends Foo with repeated TestEnum foo_enum = 19;
  1150. // message Bar {
  1151. // extends Foo with optional Qux foo_message = 30;
  1152. // // (using Qux as the group type)
  1153. // extends Foo with repeated group foo_group = 39;
  1154. // }
  1155. FileDescriptorProto foo_file;
  1156. foo_file.set_name("foo.proto");
  1157. AddEmptyEnum(&foo_file, "Baz");
  1158. AddMessage(&foo_file, "Qux");
  1159. DescriptorProto* foo = AddMessage(&foo_file, "Foo");
  1160. AddExtensionRange(foo, 10, 20);
  1161. AddExtensionRange(foo, 30, 40);
  1162. AddExtension(&foo_file, "Foo", "foo_int32", 10,
  1163. FieldDescriptorProto::LABEL_OPTIONAL,
  1164. FieldDescriptorProto::TYPE_INT32);
  1165. AddExtension(&foo_file, "Foo", "foo_enum", 19,
  1166. FieldDescriptorProto::LABEL_REPEATED,
  1167. FieldDescriptorProto::TYPE_ENUM)
  1168. ->set_type_name("Baz");
  1169. DescriptorProto* bar = AddMessage(&foo_file, "Bar");
  1170. AddNestedExtension(bar, "Foo", "foo_message", 30,
  1171. FieldDescriptorProto::LABEL_OPTIONAL,
  1172. FieldDescriptorProto::TYPE_MESSAGE)
  1173. ->set_type_name("Qux");
  1174. AddNestedExtension(bar, "Foo", "foo_group", 39,
  1175. FieldDescriptorProto::LABEL_REPEATED,
  1176. FieldDescriptorProto::TYPE_GROUP)
  1177. ->set_type_name("Qux");
  1178. // Build the descriptors and get the pointers.
  1179. foo_file_ = pool_.BuildFile(foo_file);
  1180. ASSERT_TRUE(foo_file_ != NULL);
  1181. ASSERT_EQ(1, foo_file_->enum_type_count());
  1182. baz_ = foo_file_->enum_type(0);
  1183. ASSERT_EQ(3, foo_file_->message_type_count());
  1184. qux_ = foo_file_->message_type(0);
  1185. foo_ = foo_file_->message_type(1);
  1186. bar_ = foo_file_->message_type(2);
  1187. }
  1188. DescriptorPool pool_;
  1189. const FileDescriptor* foo_file_;
  1190. const Descriptor* foo_;
  1191. const Descriptor* bar_;
  1192. const EnumDescriptor* baz_;
  1193. const Descriptor* qux_;
  1194. };
  1195. TEST_F(ExtensionDescriptorTest, ExtensionRanges) {
  1196. EXPECT_EQ(0, bar_->extension_range_count());
  1197. ASSERT_EQ(2, foo_->extension_range_count());
  1198. EXPECT_EQ(10, foo_->extension_range(0)->start);
  1199. EXPECT_EQ(30, foo_->extension_range(1)->start);
  1200. EXPECT_EQ(20, foo_->extension_range(0)->end);
  1201. EXPECT_EQ(40, foo_->extension_range(1)->end);
  1202. };
  1203. TEST_F(ExtensionDescriptorTest, Extensions) {
  1204. EXPECT_EQ(0, foo_->extension_count());
  1205. ASSERT_EQ(2, foo_file_->extension_count());
  1206. ASSERT_EQ(2, bar_->extension_count());
  1207. EXPECT_TRUE(foo_file_->extension(0)->is_extension());
  1208. EXPECT_TRUE(foo_file_->extension(1)->is_extension());
  1209. EXPECT_TRUE(bar_->extension(0)->is_extension());
  1210. EXPECT_TRUE(bar_->extension(1)->is_extension());
  1211. EXPECT_EQ("foo_int32" , foo_file_->extension(0)->name());
  1212. EXPECT_EQ("foo_enum" , foo_file_->extension(1)->name());
  1213. EXPECT_EQ("foo_message", bar_->extension(0)->name());
  1214. EXPECT_EQ("foo_group" , bar_->extension(1)->name());
  1215. EXPECT_EQ(10, foo_file_->extension(0)->number());
  1216. EXPECT_EQ(19, foo_file_->extension(1)->number());
  1217. EXPECT_EQ(30, bar_->extension(0)->number());
  1218. EXPECT_EQ(39, bar_->extension(1)->number());
  1219. EXPECT_EQ(FieldDescriptor::TYPE_INT32 , foo_file_->extension(0)->type());
  1220. EXPECT_EQ(FieldDescriptor::TYPE_ENUM , foo_file_->extension(1)->type());
  1221. EXPECT_EQ(FieldDescriptor::TYPE_MESSAGE, bar_->extension(0)->type());
  1222. EXPECT_EQ(FieldDescriptor::TYPE_GROUP , bar_->extension(1)->type());
  1223. EXPECT_EQ(baz_, foo_file_->extension(1)->enum_type());
  1224. EXPECT_EQ(qux_, bar_->extension(0)->message_type());
  1225. EXPECT_EQ(qux_, bar_->extension(1)->message_type());
  1226. EXPECT_EQ(FieldDescriptor::LABEL_OPTIONAL, foo_file_->extension(0)->label());
  1227. EXPECT_EQ(FieldDescriptor::LABEL_REPEATED, foo_file_->extension(1)->label());
  1228. EXPECT_EQ(FieldDescriptor::LABEL_OPTIONAL, bar_->extension(0)->label());
  1229. EXPECT_EQ(FieldDescriptor::LABEL_REPEATED, bar_->extension(1)->label());
  1230. EXPECT_EQ(foo_, foo_file_->extension(0)->containing_type());
  1231. EXPECT_EQ(foo_, foo_file_->extension(1)->containing_type());
  1232. EXPECT_EQ(foo_, bar_->extension(0)->containing_type());
  1233. EXPECT_EQ(foo_, bar_->extension(1)->containing_type());
  1234. EXPECT_TRUE(foo_file_->extension(0)->extension_scope() == NULL);
  1235. EXPECT_TRUE(foo_file_->extension(1)->extension_scope() == NULL);
  1236. EXPECT_EQ(bar_, bar_->extension(0)->extension_scope());
  1237. EXPECT_EQ(bar_, bar_->extension(1)->extension_scope());
  1238. };
  1239. TEST_F(ExtensionDescriptorTest, IsExtensionNumber) {
  1240. EXPECT_FALSE(foo_->IsExtensionNumber( 9));
  1241. EXPECT_TRUE (foo_->IsExtensionNumber(10));
  1242. EXPECT_TRUE (foo_->IsExtensionNumber(19));
  1243. EXPECT_FALSE(foo_->IsExtensionNumber(20));
  1244. EXPECT_FALSE(foo_->IsExtensionNumber(29));
  1245. EXPECT_TRUE (foo_->IsExtensionNumber(30));
  1246. EXPECT_TRUE (foo_->IsExtensionNumber(39));
  1247. EXPECT_FALSE(foo_->IsExtensionNumber(40));
  1248. }
  1249. TEST_F(ExtensionDescriptorTest, FindExtensionByName) {
  1250. // Note that FileDescriptor::FindExtensionByName() is tested by
  1251. // FileDescriptorTest.
  1252. ASSERT_EQ(2, bar_->extension_count());
  1253. EXPECT_EQ(bar_->extension(0), bar_->FindExtensionByName("foo_message"));
  1254. EXPECT_EQ(bar_->extension(1), bar_->FindExtensionByName("foo_group" ));
  1255. EXPECT_TRUE(bar_->FindExtensionByName("no_such_extension") == NULL);
  1256. EXPECT_TRUE(foo_->FindExtensionByName("foo_int32") == NULL);
  1257. EXPECT_TRUE(foo_->FindExtensionByName("foo_message") == NULL);
  1258. }
  1259. TEST_F(ExtensionDescriptorTest, FindAllExtensions) {
  1260. vector<const FieldDescriptor*> extensions;
  1261. pool_.FindAllExtensions(foo_, &extensions);
  1262. ASSERT_EQ(4, extensions.size());
  1263. EXPECT_EQ(10, extensions[0]->number());
  1264. EXPECT_EQ(19, extensions[1]->number());
  1265. EXPECT_EQ(30, extensions[2]->number());
  1266. EXPECT_EQ(39, extensions[3]->number());
  1267. }
  1268. // ===================================================================
  1269. class MiscTest : public testing::Test {
  1270. protected:
  1271. // Function which makes a field descriptor of the given type.
  1272. const FieldDescriptor* GetFieldDescriptorOfType(FieldDescriptor::Type type) {
  1273. FileDescriptorProto file_proto;
  1274. file_proto.set_name("foo.proto");
  1275. AddEmptyEnum(&file_proto, "DummyEnum");
  1276. DescriptorProto* message = AddMessage(&file_proto, "TestMessage");
  1277. FieldDescriptorProto* field =
  1278. AddField(message, "foo", 1, FieldDescriptorProto::LABEL_OPTIONAL,
  1279. static_cast<FieldDescriptorProto::Type>(static_cast<int>(type)));
  1280. if (type == FieldDescriptor::TYPE_MESSAGE ||
  1281. type == FieldDescriptor::TYPE_GROUP) {
  1282. field->set_type_name("TestMessage");
  1283. } else if (type == FieldDescriptor::TYPE_ENUM) {
  1284. field->set_type_name("DummyEnum");
  1285. }
  1286. // Build the descriptors and get the pointers.
  1287. pool_.reset(new DescriptorPool());
  1288. const FileDescriptor* file = pool_->BuildFile(file_proto);
  1289. if (file != NULL &&
  1290. file->message_type_count() == 1 &&
  1291. file->message_type(0)->field_count() == 1) {
  1292. return file->message_type(0)->field(0);
  1293. } else {
  1294. return NULL;
  1295. }
  1296. }
  1297. const char* GetTypeNameForFieldType(FieldDescriptor::Type type) {
  1298. const FieldDescriptor* field = GetFieldDescriptorOfType(type);
  1299. return field != NULL ? field->type_name() : "";
  1300. }
  1301. FieldDescriptor::CppType GetCppTypeForFieldType(FieldDescriptor::Type type) {
  1302. const FieldDescriptor* field = GetFieldDescriptorOfType(type);
  1303. return field != NULL ? field->cpp_type() :
  1304. static_cast<FieldDescriptor::CppType>(0);
  1305. }
  1306. const char* GetCppTypeNameForFieldType(FieldDescriptor::Type type) {
  1307. const FieldDescriptor* field = GetFieldDescriptorOfType(type);
  1308. return field != NULL ? field->cpp_type_name() : "";
  1309. }
  1310. scoped_ptr<DescriptorPool> pool_;
  1311. };
  1312. TEST_F(MiscTest, TypeNames) {
  1313. // Test that correct type names are returned.
  1314. typedef FieldDescriptor FD; // avoid ugly line wrapping
  1315. EXPECT_STREQ("double" , GetTypeNameForFieldType(FD::TYPE_DOUBLE ));
  1316. EXPECT_STREQ("float" , GetTypeNameForFieldType(FD::TYPE_FLOAT ));
  1317. EXPECT_STREQ("int64" , GetTypeNameForFieldType(FD::TYPE_INT64 ));
  1318. EXPECT_STREQ("uint64" , GetTypeNameForFieldType(FD::TYPE_UINT64 ));
  1319. EXPECT_STREQ("int32" , GetTypeNameForFieldType(FD::TYPE_INT32 ));
  1320. EXPECT_STREQ("fixed64" , GetTypeNameForFieldType(FD::TYPE_FIXED64 ));
  1321. EXPECT_STREQ("fixed32" , GetTypeNameForFieldType(FD::TYPE_FIXED32 ));
  1322. EXPECT_STREQ("bool" , GetTypeNameForFieldType(FD::TYPE_BOOL ));
  1323. EXPECT_STREQ("string" , GetTypeNameForFieldType(FD::TYPE_STRING ));
  1324. EXPECT_STREQ("group" , GetTypeNameForFieldType(FD::TYPE_GROUP ));
  1325. EXPECT_STREQ("message" , GetTypeNameForFieldType(FD::TYPE_MESSAGE ));
  1326. EXPECT_STREQ("bytes" , GetTypeNameForFieldType(FD::TYPE_BYTES ));
  1327. EXPECT_STREQ("uint32" , GetTypeNameForFieldType(FD::TYPE_UINT32 ));
  1328. EXPECT_STREQ("enum" , GetTypeNameForFieldType(FD::TYPE_ENUM ));
  1329. EXPECT_STREQ("sfixed32", GetTypeNameForFieldType(FD::TYPE_SFIXED32));
  1330. EXPECT_STREQ("sfixed64", GetTypeNameForFieldType(FD::TYPE_SFIXED64));
  1331. EXPECT_STREQ("sint32" , GetTypeNameForFieldType(FD::TYPE_SINT32 ));
  1332. EXPECT_STREQ("sint64" , GetTypeNameForFieldType(FD::TYPE_SINT64 ));
  1333. }
  1334. TEST_F(MiscTest, CppTypes) {
  1335. // Test that CPP types are assigned correctly.
  1336. typedef FieldDescriptor FD; // avoid ugly line wrapping
  1337. EXPECT_EQ(FD::CPPTYPE_DOUBLE , GetCppTypeForFieldType(FD::TYPE_DOUBLE ));
  1338. EXPECT_EQ(FD::CPPTYPE_FLOAT , GetCppTypeForFieldType(FD::TYPE_FLOAT ));
  1339. EXPECT_EQ(FD::CPPTYPE_INT64 , GetCppTypeForFieldType(FD::TYPE_INT64 ));
  1340. EXPECT_EQ(FD::CPPTYPE_UINT64 , GetCppTypeForFieldType(FD::TYPE_UINT64 ));
  1341. EXPECT_EQ(FD::CPPTYPE_INT32 , GetCppTypeForFieldType(FD::TYPE_INT32 ));
  1342. EXPECT_EQ(FD::CPPTYPE_UINT64 , GetCppTypeForFieldType(FD::TYPE_FIXED64 ));
  1343. EXPECT_EQ(FD::CPPTYPE_UINT32 , GetCppTypeForFieldType(FD::TYPE_FIXED32 ));
  1344. EXPECT_EQ(FD::CPPTYPE_BOOL , GetCppTypeForFieldType(FD::TYPE_BOOL ));
  1345. EXPECT_EQ(FD::CPPTYPE_STRING , GetCppTypeForFieldType(FD::TYPE_STRING ));
  1346. EXPECT_EQ(FD::CPPTYPE_MESSAGE, GetCppTypeForFieldType(FD::TYPE_GROUP ));
  1347. EXPECT_EQ(FD::CPPTYPE_MESSAGE, GetCppTypeForFieldType(FD::TYPE_MESSAGE ));
  1348. EXPECT_EQ(FD::CPPTYPE_STRING , GetCppTypeForFieldType(FD::TYPE_BYTES ));
  1349. EXPECT_EQ(FD::CPPTYPE_UINT32 , GetCppTypeForFieldType(FD::TYPE_UINT32 ));
  1350. EXPECT_EQ(FD::CPPTYPE_ENUM , GetCppTypeForFieldType(FD::TYPE_ENUM ));
  1351. EXPECT_EQ(FD::CPPTYPE_INT32 , GetCppTypeForFieldType(FD::TYPE_SFIXED32));
  1352. EXPECT_EQ(FD::CPPTYPE_INT64 , GetCppTypeForFieldType(FD::TYPE_SFIXED64));
  1353. EXPECT_EQ(FD::CPPTYPE_INT32 , GetCppTypeForFieldType(FD::TYPE_SINT32 ));
  1354. EXPECT_EQ(FD::CPPTYPE_INT64 , GetCppTypeForFieldType(FD::TYPE_SINT64 ));
  1355. }
  1356. TEST_F(MiscTest, CppTypeNames) {
  1357. // Test that correct CPP type names are returned.
  1358. typedef FieldDescriptor FD; // avoid ugly line wrapping
  1359. EXPECT_STREQ("double" , GetCppTypeNameForFieldType(FD::TYPE_DOUBLE ));
  1360. EXPECT_STREQ("float" , GetCppTypeNameForFieldType(FD::TYPE_FLOAT ));
  1361. EXPECT_STREQ("int64" , GetCppTypeNameForFieldType(FD::TYPE_INT64 ));
  1362. EXPECT_STREQ("uint64" , GetCppTypeNameForFieldType(FD::TYPE_UINT64 ));
  1363. EXPECT_STREQ("int32" , GetCppTypeNameForFieldType(FD::TYPE_INT32 ));
  1364. EXPECT_STREQ("uint64" , GetCppTypeNameForFieldType(FD::TYPE_FIXED64 ));
  1365. EXPECT_STREQ("uint32" , GetCppTypeNameForFieldType(FD::TYPE_FIXED32 ));
  1366. EXPECT_STREQ("bool" , GetCppTypeNameForFieldType(FD::TYPE_BOOL ));
  1367. EXPECT_STREQ("string" , GetCppTypeNameForFieldType(FD::TYPE_STRING ));
  1368. EXPECT_STREQ("message", GetCppTypeNameForFieldType(FD::TYPE_GROUP ));
  1369. EXPECT_STREQ("message", GetCppTypeNameForFieldType(FD::TYPE_MESSAGE ));
  1370. EXPECT_STREQ("string" , GetCppTypeNameForFieldType(FD::TYPE_BYTES ));
  1371. EXPECT_STREQ("uint32" , GetCppTypeNameForFieldType(FD::TYPE_UINT32 ));
  1372. EXPECT_STREQ("enum" , GetCppTypeNameForFieldType(FD::TYPE_ENUM ));
  1373. EXPECT_STREQ("int32" , GetCppTypeNameForFieldType(FD::TYPE_SFIXED32));
  1374. EXPECT_STREQ("int64" , GetCppTypeNameForFieldType(FD::TYPE_SFIXED64));
  1375. EXPECT_STREQ("int32" , GetCppTypeNameForFieldType(FD::TYPE_SINT32 ));
  1376. EXPECT_STREQ("int64" , GetCppTypeNameForFieldType(FD::TYPE_SINT64 ));
  1377. }
  1378. TEST_F(MiscTest, DefaultValues) {
  1379. // Test that setting default values works.
  1380. FileDescriptorProto file_proto;
  1381. file_proto.set_name("foo.proto");
  1382. EnumDescriptorProto* enum_type_proto = AddEnum(&file_proto, "DummyEnum");
  1383. AddEnumValue(enum_type_proto, "A", 1);
  1384. AddEnumValue(enum_type_proto, "B", 2);
  1385. DescriptorProto* message_proto = AddMessage(&file_proto, "TestMessage");
  1386. typedef FieldDescriptorProto FD; // avoid ugly line wrapping
  1387. const FD::Label label = FD::LABEL_OPTIONAL;
  1388. // Create fields of every CPP type with default values.
  1389. AddField(message_proto, "int32" , 1, label, FD::TYPE_INT32 )
  1390. ->set_default_value("-1");
  1391. AddField(message_proto, "int64" , 2, label, FD::TYPE_INT64 )
  1392. ->set_default_value("-1000000000000");
  1393. AddField(message_proto, "uint32", 3, label, FD::TYPE_UINT32)
  1394. ->set_default_value("42");
  1395. AddField(message_proto, "uint64", 4, label, FD::TYPE_UINT64)
  1396. ->set_default_value("2000000000000");
  1397. AddField(message_proto, "float" , 5, label, FD::TYPE_FLOAT )
  1398. ->set_default_value("4.5");
  1399. AddField(message_proto, "double", 6, label, FD::TYPE_DOUBLE)
  1400. ->set_default_value("10e100");
  1401. AddField(message_proto, "bool" , 7, label, FD::TYPE_BOOL )
  1402. ->set_default_value("true");
  1403. AddField(message_proto, "string", 8, label, FD::TYPE_STRING)
  1404. ->set_default_value("hello");
  1405. AddField(message_proto, "data" , 9, label, FD::TYPE_BYTES )
  1406. ->set_default_value("\\001\\002\\003");
  1407. FieldDescriptorProto* enum_field =
  1408. AddField(message_proto, "enum", 10, label, FD::TYPE_ENUM);
  1409. enum_field->set_type_name("DummyEnum");
  1410. enum_field->set_default_value("B");
  1411. // Strings are allowed to have empty defaults. (At one point, due to
  1412. // a bug, empty defaults for strings were rejected. Oops.)
  1413. AddField(message_proto, "empty_string", 11, label, FD::TYPE_STRING)
  1414. ->set_default_value("");
  1415. // Add a second set of fields with implicit defalut values.
  1416. AddField(message_proto, "implicit_int32" , 21, label, FD::TYPE_INT32 );
  1417. AddField(message_proto, "implicit_int64" , 22, label, FD::TYPE_INT64 );
  1418. AddField(message_proto, "implicit_uint32", 23, label, FD::TYPE_UINT32);
  1419. AddField(message_proto, "implicit_uint64", 24, label, FD::TYPE_UINT64);
  1420. AddField(message_proto, "implicit_float" , 25, label, FD::TYPE_FLOAT );
  1421. AddField(message_proto, "implicit_double", 26, label, FD::TYPE_DOUBLE);
  1422. AddField(message_proto, "implicit_bool" , 27, label, FD::TYPE_BOOL );
  1423. AddField(message_proto, "implicit_string", 28, label, FD::TYPE_STRING);
  1424. AddField(message_proto, "implicit_data" , 29, label, FD::TYPE_BYTES );
  1425. AddField(message_proto, "implicit_enum" , 30, label, FD::TYPE_ENUM)
  1426. ->set_type_name("DummyEnum");
  1427. // Build it.
  1428. DescriptorPool pool;
  1429. const FileDescriptor* file = pool.BuildFile(file_proto);
  1430. ASSERT_TRUE(file != NULL);
  1431. ASSERT_EQ(1, file->enum_type_count());
  1432. const EnumDescriptor* enum_type = file->enum_type(0);
  1433. ASSERT_EQ(2, enum_type->value_count());
  1434. const EnumValueDescriptor* enum_value_a = enum_type->value(0);
  1435. const EnumValueDescriptor* enum_value_b = enum_type->value(1);
  1436. ASSERT_EQ(1, file->message_type_count());
  1437. const Descriptor* message = file->message_type(0);
  1438. ASSERT_EQ(21, message->field_count());
  1439. // Check the default values.
  1440. ASSERT_TRUE(message->field(0)->has_default_value());
  1441. ASSERT_TRUE(message->field(1)->has_default_value());
  1442. ASSERT_TRUE(message->field(2)->has_default_value());
  1443. ASSERT_TRUE(message->field(3)->has_default_value());
  1444. ASSERT_TRUE(message->field(4)->has_default_value());
  1445. ASSERT_TRUE(message->field(5)->has_default_value());
  1446. ASSERT_TRUE(message->field(6)->has_default_value());
  1447. ASSERT_TRUE(message->field(7)->has_default_value());
  1448. ASSERT_TRUE(message->field(8)->has_default_value());
  1449. ASSERT_TRUE(message->field(9)->has_default_value());
  1450. ASSERT_TRUE(message->field(10)->has_default_value());
  1451. EXPECT_EQ(-1 , message->field(0)->default_value_int32 ());
  1452. EXPECT_EQ(-GOOGLE_ULONGLONG(1000000000000),
  1453. message->field(1)->default_value_int64 ());
  1454. EXPECT_EQ(42 , message->field(2)->default_value_uint32());
  1455. EXPECT_EQ(GOOGLE_ULONGLONG(2000000000000),
  1456. message->field(3)->default_value_uint64());
  1457. EXPECT_EQ(4.5 , message->field(4)->default_value_float ());
  1458. EXPECT_EQ(10e100 , message->field(5)->default_value_double());
  1459. EXPECT_TRUE( message->field(6)->default_value_bool ());
  1460. EXPECT_EQ("hello" , message->field(7)->default_value_string());
  1461. EXPECT_EQ("\001\002\003" , message->field(8)->default_value_string());
  1462. EXPECT_EQ(enum_value_b , message->field(9)->default_value_enum ());
  1463. EXPECT_EQ("" , message->field(10)->default_value_string());
  1464. ASSERT_FALSE(message->field(11)->has_default_value());
  1465. ASSERT_FALSE(message->field(12)->has_default_value());
  1466. ASSERT_FALSE(message->field(13)->has_default_value());
  1467. ASSERT_FALSE(message->field(14)->has_default_value());
  1468. ASSERT_FALSE(message->field(15)->has_default_value());
  1469. ASSERT_FALSE(message->field(16)->has_default_value());
  1470. ASSERT_FALSE(message->field(17)->has_default_value());
  1471. ASSERT_FALSE(message->field(18)->has_default_value());
  1472. ASSERT_FALSE(message->field(19)->has_default_value());
  1473. ASSERT_FALSE(message->field(20)->has_default_value());
  1474. EXPECT_EQ(0 , message->field(11)->default_value_int32 ());
  1475. EXPECT_EQ(0 , message->field(12)->default_value_int64 ());
  1476. EXPECT_EQ(0 , message->field(13)->default_value_uint32());
  1477. EXPECT_EQ(0 , message->field(14)->default_value_uint64());
  1478. EXPECT_EQ(0.0f , message->field(15)->default_value_float ());
  1479. EXPECT_EQ(0.0 , message->field(16)->default_value_double());
  1480. EXPECT_FALSE( message->field(17)->default_value_bool ());
  1481. EXPECT_EQ("" , message->field(18)->default_value_string());
  1482. EXPECT_EQ("" , message->field(19)->default_value_string());
  1483. EXPECT_EQ(enum_value_a, message->field(20)->default_value_enum());
  1484. }
  1485. TEST_F(MiscTest, FieldOptions) {
  1486. // Try setting field options.
  1487. FileDescriptorProto file_proto;
  1488. file_proto.set_name("foo.proto");
  1489. DescriptorProto* message_proto = AddMessage(&file_proto, "TestMessage");
  1490. AddField(message_proto, "foo", 1,
  1491. FieldDescriptorProto::LABEL_OPTIONAL,
  1492. FieldDescriptorProto::TYPE_INT32);
  1493. FieldDescriptorProto* bar_proto =
  1494. AddField(message_proto, "bar", 2,
  1495. FieldDescriptorProto::LABEL_OPTIONAL,
  1496. FieldDescriptorProto::TYPE_INT32);
  1497. FieldOptions* options = bar_proto->mutable_options();
  1498. options->set_ctype(FieldOptions::CORD);
  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. ASSERT_EQ(1, file->message_type_count());
  1504. const Descriptor* message = file->message_type(0);
  1505. ASSERT_EQ(2, message->field_count());
  1506. const FieldDescriptor* foo = message->field(0);
  1507. const FieldDescriptor* bar = message->field(1);
  1508. // "foo" had no options set, so it should return the default options.
  1509. EXPECT_EQ(&FieldOptions::default_instance(), &foo->options());
  1510. // "bar" had options set.
  1511. EXPECT_NE(&FieldOptions::default_instance(), options);
  1512. EXPECT_TRUE(bar->options().has_ctype());
  1513. EXPECT_EQ(FieldOptions::CORD, bar->options().ctype());
  1514. }
  1515. // ===================================================================
  1516. enum DescriptorPoolMode {
  1517. NO_DATABASE,
  1518. FALLBACK_DATABASE
  1519. };
  1520. class AllowUnknownDependenciesTest
  1521. : public testing::TestWithParam<DescriptorPoolMode> {
  1522. protected:
  1523. DescriptorPoolMode mode() {
  1524. return GetParam();
  1525. }
  1526. virtual void SetUp() {
  1527. FileDescriptorProto foo_proto, bar_proto;
  1528. switch (mode()) {
  1529. case NO_DATABASE:
  1530. pool_.reset(new DescriptorPool);
  1531. break;
  1532. case FALLBACK_DATABASE:
  1533. pool_.reset(new DescriptorPool(&db_));
  1534. break;
  1535. }
  1536. pool_->AllowUnknownDependencies();
  1537. ASSERT_TRUE(TextFormat::ParseFromString(
  1538. "name: 'foo.proto'"
  1539. "dependency: 'bar.proto'"
  1540. "dependency: 'baz.proto'"
  1541. "message_type {"
  1542. " name: 'Foo'"
  1543. " field { name:'bar' number:1 label:LABEL_OPTIONAL type_name:'Bar' }"
  1544. " field { name:'baz' number:2 label:LABEL_OPTIONAL type_name:'Baz' }"
  1545. " field { name:'qux' number:3 label:LABEL_OPTIONAL"
  1546. " type_name: '.corge.Qux'"
  1547. " type: TYPE_ENUM"
  1548. " options {"
  1549. " uninterpreted_option {"
  1550. " name {"
  1551. " name_part: 'grault'"
  1552. " is_extension: true"
  1553. " }"
  1554. " positive_int_value: 1234"
  1555. " }"
  1556. " }"
  1557. " }"
  1558. "}",
  1559. &foo_proto));
  1560. ASSERT_TRUE(TextFormat::ParseFromString(
  1561. "name: 'bar.proto'"
  1562. "message_type { name: 'Bar' }",
  1563. &bar_proto));
  1564. // Collect pointers to stuff.
  1565. bar_file_ = BuildFile(bar_proto);
  1566. ASSERT_TRUE(bar_file_ != NULL);
  1567. ASSERT_EQ(1, bar_file_->message_type_count());
  1568. bar_type_ = bar_file_->message_type(0);
  1569. foo_file_ = BuildFile(foo_proto);
  1570. ASSERT_TRUE(foo_file_ != NULL);
  1571. ASSERT_EQ(1, foo_file_->message_type_count());
  1572. foo_type_ = foo_file_->message_type(0);
  1573. ASSERT_EQ(3, foo_type_->field_count());
  1574. bar_field_ = foo_type_->field(0);
  1575. baz_field_ = foo_type_->field(1);
  1576. qux_field_ = foo_type_->field(2);
  1577. }
  1578. const FileDescriptor* BuildFile(const FileDescriptorProto& proto) {
  1579. switch (mode()) {
  1580. case NO_DATABASE:
  1581. return pool_->BuildFile(proto);
  1582. break;
  1583. case FALLBACK_DATABASE: {
  1584. EXPECT_TRUE(db_.Add(proto));
  1585. return pool_->FindFileByName(proto.name());
  1586. }
  1587. }
  1588. GOOGLE_LOG(FATAL) << "Can't get here.";
  1589. return NULL;
  1590. }
  1591. const FileDescriptor* bar_file_;
  1592. const Descriptor* bar_type_;
  1593. const FileDescriptor* foo_file_;
  1594. const Descriptor* foo_type_;
  1595. const FieldDescriptor* bar_field_;
  1596. const FieldDescriptor* baz_field_;
  1597. const FieldDescriptor* qux_field_;
  1598. SimpleDescriptorDatabase db_; // used if in FALLBACK_DATABASE mode.
  1599. scoped_ptr<DescriptorPool> pool_;
  1600. };
  1601. TEST_P(AllowUnknownDependenciesTest, PlaceholderFile) {
  1602. ASSERT_EQ(2, foo_file_->dependency_count());
  1603. EXPECT_EQ(bar_file_, foo_file_->dependency(0));
  1604. const FileDescriptor* baz_file = foo_file_->dependency(1);
  1605. EXPECT_EQ("baz.proto", baz_file->name());
  1606. EXPECT_EQ(0, baz_file->message_type_count());
  1607. // Placeholder files should not be findable.
  1608. EXPECT_EQ(bar_file_, pool_->FindFileByName(bar_file_->name()));
  1609. EXPECT_TRUE(pool_->FindFileByName(baz_file->name()) == NULL);
  1610. }
  1611. TEST_P(AllowUnknownDependenciesTest, PlaceholderTypes) {
  1612. ASSERT_EQ(FieldDescriptor::TYPE_MESSAGE, bar_field_->type());
  1613. EXPECT_EQ(bar_type_, bar_field_->message_type());
  1614. ASSERT_EQ(FieldDescriptor::TYPE_MESSAGE, baz_field_->type());
  1615. const Descriptor* baz_type = baz_field_->message_type();
  1616. EXPECT_EQ("Baz", baz_type->name());
  1617. EXPECT_EQ("Baz", baz_type->full_name());
  1618. EXPECT_EQ("Baz.placeholder.proto", baz_type->file()->name());
  1619. EXPECT_EQ(0, baz_type->extension_range_count());
  1620. ASSERT_EQ(FieldDescriptor::TYPE_ENUM, qux_field_->type());
  1621. const EnumDescriptor* qux_type = qux_field_->enum_type();
  1622. EXPECT_EQ("Qux", qux_type->name());
  1623. EXPECT_EQ("corge.Qux", qux_type->full_name());
  1624. EXPECT_EQ("corge.Qux.placeholder.proto", qux_type->file()->name());
  1625. // Placeholder types should not be findable.
  1626. EXPECT_EQ(bar_type_, pool_->FindMessageTypeByName(bar_type_->full_name()));
  1627. EXPECT_TRUE(pool_->FindMessageTypeByName(baz_type->full_name()) == NULL);
  1628. EXPECT_TRUE(pool_->FindEnumTypeByName(qux_type->full_name()) == NULL);
  1629. }
  1630. TEST_P(AllowUnknownDependenciesTest, CopyTo) {
  1631. // FieldDescriptor::CopyTo() should write non-fully-qualified type names
  1632. // for placeholder types which were not originally fully-qualified.
  1633. FieldDescriptorProto proto;
  1634. // Bar is not a placeholder, so it is fully-qualified.
  1635. bar_field_->CopyTo(&proto);
  1636. EXPECT_EQ(".Bar", proto.type_name());
  1637. EXPECT_EQ(FieldDescriptorProto::TYPE_MESSAGE, proto.type());
  1638. // Baz is an unqualified placeholder.
  1639. proto.Clear();
  1640. baz_field_->CopyTo(&proto);
  1641. EXPECT_EQ("Baz", proto.type_name());
  1642. EXPECT_FALSE(proto.has_type());
  1643. // Qux is a fully-qualified placeholder.
  1644. proto.Clear();
  1645. qux_field_->CopyTo(&proto);
  1646. EXPECT_EQ(".corge.Qux", proto.type_name());
  1647. EXPECT_EQ(FieldDescriptorProto::TYPE_ENUM, proto.type());
  1648. }
  1649. TEST_P(AllowUnknownDependenciesTest, CustomOptions) {
  1650. // Qux should still have the uninterpreted option attached.
  1651. ASSERT_EQ(1, qux_field_->options().uninterpreted_option_size());
  1652. const UninterpretedOption& option =
  1653. qux_field_->options().uninterpreted_option(0);
  1654. ASSERT_EQ(1, option.name_size());
  1655. EXPECT_EQ("grault", option.name(0).name_part());
  1656. }
  1657. TEST_P(AllowUnknownDependenciesTest, UnknownExtendee) {
  1658. // Test that we can extend an unknown type. This is slightly tricky because
  1659. // it means that the placeholder type must have an extension range.
  1660. FileDescriptorProto extension_proto;
  1661. ASSERT_TRUE(TextFormat::ParseFromString(
  1662. "name: 'extension.proto'"
  1663. "extension { extendee: 'UnknownType' name:'some_extension' number:123"
  1664. " label:LABEL_OPTIONAL type:TYPE_INT32 }",
  1665. &extension_proto));
  1666. const FileDescriptor* file = BuildFile(extension_proto);
  1667. ASSERT_TRUE(file != NULL);
  1668. ASSERT_EQ(1, file->extension_count());
  1669. const Descriptor* extendee = file->extension(0)->containing_type();
  1670. EXPECT_EQ("UnknownType", extendee->name());
  1671. ASSERT_EQ(1, extendee->extension_range_count());
  1672. EXPECT_EQ(1, extendee->extension_range(0)->start);
  1673. EXPECT_EQ(FieldDescriptor::kMaxNumber + 1, extendee->extension_range(0)->end);
  1674. }
  1675. TEST_P(AllowUnknownDependenciesTest, CustomOption) {
  1676. // Test that we can use a custom option without having parsed
  1677. // descriptor.proto.
  1678. FileDescriptorProto option_proto;
  1679. ASSERT_TRUE(TextFormat::ParseFromString(
  1680. "name: \"unknown_custom_options.proto\" "
  1681. "dependency: \"google/protobuf/descriptor.proto\" "
  1682. "extension { "
  1683. " extendee: \"google.protobuf.FileOptions\" "
  1684. " name: \"some_option\" "
  1685. " number: 123456 "
  1686. " label: LABEL_OPTIONAL "
  1687. " type: TYPE_INT32 "
  1688. "} "
  1689. "options { "
  1690. " uninterpreted_option { "
  1691. " name { "
  1692. " name_part: \"some_option\" "
  1693. " is_extension: true "
  1694. " } "
  1695. " positive_int_value: 1234 "
  1696. " } "
  1697. " uninterpreted_option { "
  1698. " name { "
  1699. " name_part: \"unknown_option\" "
  1700. " is_extension: true "
  1701. " } "
  1702. " positive_int_value: 1234 "
  1703. " } "
  1704. " uninterpreted_option { "
  1705. " name { "
  1706. " name_part: \"optimize_for\" "
  1707. " is_extension: false "
  1708. " } "
  1709. " identifier_value: \"SPEED\" "
  1710. " } "
  1711. "}",
  1712. &option_proto));
  1713. const FileDescriptor* file = BuildFile(option_proto);
  1714. ASSERT_TRUE(file != NULL);
  1715. // Verify that no extension options were set, but they were left as
  1716. // uninterpreted_options.
  1717. vector<const FieldDescriptor*> fields;
  1718. file->options().GetReflection()->ListFields(file->options(), &fields);
  1719. ASSERT_EQ(2, fields.size());
  1720. EXPECT_TRUE(file->options().has_optimize_for());
  1721. EXPECT_EQ(2, file->options().uninterpreted_option_size());
  1722. }
  1723. TEST_P(AllowUnknownDependenciesTest,
  1724. UndeclaredDependencyTriggersBuildOfDependency) {
  1725. // Crazy case: suppose foo.proto refers to a symbol without declaring the
  1726. // dependency that finds it. In the event that the pool is backed by a
  1727. // DescriptorDatabase, the pool will attempt to find the symbol in the
  1728. // database. If successful, it will build the undeclared dependency to verify
  1729. // that the file does indeed contain the symbol. If that file fails to build,
  1730. // then its descriptors must be rolled back. However, we still want foo.proto
  1731. // to build successfully, since we are allowing unknown dependencies.
  1732. FileDescriptorProto undeclared_dep_proto;
  1733. // We make this file fail to build by giving it two fields with tag 1.
  1734. ASSERT_TRUE(TextFormat::ParseFromString(
  1735. "name: \"invalid_file_as_undeclared_dep.proto\" "
  1736. "package: \"undeclared\" "
  1737. "message_type: { "
  1738. " name: \"Quux\" "
  1739. " field { "
  1740. " name:'qux' number:1 label:LABEL_OPTIONAL type: TYPE_INT32 "
  1741. " }"
  1742. " field { "
  1743. " name:'quux' number:1 label:LABEL_OPTIONAL type: TYPE_INT64 "
  1744. " }"
  1745. "}",
  1746. &undeclared_dep_proto));
  1747. // We can't use the BuildFile() helper because we don't actually want to build
  1748. // it into the descriptor pool in the fallback database case: it just needs to
  1749. // be sitting in the database so that it gets built during the building of
  1750. // test.proto below.
  1751. switch (mode()) {
  1752. case NO_DATABASE: {
  1753. ASSERT_TRUE(pool_->BuildFile(undeclared_dep_proto) == NULL);
  1754. break;
  1755. }
  1756. case FALLBACK_DATABASE: {
  1757. ASSERT_TRUE(db_.Add(undeclared_dep_proto));
  1758. }
  1759. }
  1760. FileDescriptorProto test_proto;
  1761. ASSERT_TRUE(TextFormat::ParseFromString(
  1762. "name: \"test.proto\" "
  1763. "message_type: { "
  1764. " name: \"Corge\" "
  1765. " field { "
  1766. " name:'quux' number:1 label: LABEL_OPTIONAL "
  1767. " type_name:'undeclared.Quux' type: TYPE_MESSAGE "
  1768. " }"
  1769. "}",
  1770. &test_proto));
  1771. const FileDescriptor* file = BuildFile(test_proto);
  1772. ASSERT_TRUE(file != NULL);
  1773. GOOGLE_LOG(INFO) << file->DebugString();
  1774. EXPECT_EQ(0, file->dependency_count());
  1775. ASSERT_EQ(1, file->message_type_count());
  1776. const Descriptor* corge_desc = file->message_type(0);
  1777. ASSERT_EQ("Corge", corge_desc->name());
  1778. ASSERT_EQ(1, corge_desc->field_count());
  1779. const FieldDescriptor* quux_field = corge_desc->field(0);
  1780. ASSERT_EQ(FieldDescriptor::TYPE_MESSAGE, quux_field->type());
  1781. ASSERT_EQ("Quux", quux_field->message_type()->name());
  1782. ASSERT_EQ("undeclared.Quux", quux_field->message_type()->full_name());
  1783. EXPECT_EQ("undeclared.Quux.placeholder.proto",
  1784. quux_field->message_type()->file()->name());
  1785. // The place holder type should not be findable.
  1786. ASSERT_TRUE(pool_->FindMessageTypeByName("undeclared.Quux") == NULL);
  1787. }
  1788. INSTANTIATE_TEST_CASE_P(DatabaseSource,
  1789. AllowUnknownDependenciesTest,
  1790. testing::Values(NO_DATABASE, FALLBACK_DATABASE));
  1791. // ===================================================================
  1792. TEST(CustomOptions, OptionLocations) {
  1793. const Descriptor* message =
  1794. protobuf_unittest::TestMessageWithCustomOptions::descriptor();
  1795. const FileDescriptor* file = message->file();
  1796. const FieldDescriptor* field = message->FindFieldByName("field1");
  1797. const EnumDescriptor* enm = message->FindEnumTypeByName("AnEnum");
  1798. // TODO(benjy): Support EnumValue options, once the compiler does.
  1799. const ServiceDescriptor* service =
  1800. file->FindServiceByName("TestServiceWithCustomOptions");
  1801. const MethodDescriptor* method = service->FindMethodByName("Foo");
  1802. EXPECT_EQ(GOOGLE_LONGLONG(9876543210),
  1803. file->options().GetExtension(protobuf_unittest::file_opt1));
  1804. EXPECT_EQ(-56,
  1805. message->options().GetExtension(protobuf_unittest::message_opt1));
  1806. EXPECT_EQ(GOOGLE_LONGLONG(8765432109),
  1807. field->options().GetExtension(protobuf_unittest::field_opt1));
  1808. EXPECT_EQ(42, // Check that we get the default for an option we don't set.
  1809. field->options().GetExtension(protobuf_unittest::field_opt2));
  1810. EXPECT_EQ(-789,
  1811. enm->options().GetExtension(protobuf_unittest::enum_opt1));
  1812. EXPECT_EQ(123,
  1813. enm->value(1)->options().GetExtension(
  1814. protobuf_unittest::enum_value_opt1));
  1815. EXPECT_EQ(GOOGLE_LONGLONG(-9876543210),
  1816. service->options().GetExtension(protobuf_unittest::service_opt1));
  1817. EXPECT_EQ(protobuf_unittest::METHODOPT1_VAL2,
  1818. method->options().GetExtension(protobuf_unittest::method_opt1));
  1819. // See that the regular options went through unscathed.
  1820. EXPECT_TRUE(message->options().has_message_set_wire_format());
  1821. EXPECT_EQ(FieldOptions::CORD, field->options().ctype());
  1822. }
  1823. TEST(CustomOptions, OptionTypes) {
  1824. const MessageOptions* options = NULL;
  1825. options =
  1826. &protobuf_unittest::CustomOptionMinIntegerValues::descriptor()->options();
  1827. EXPECT_FALSE( options->GetExtension(protobuf_unittest::bool_opt));
  1828. EXPECT_EQ(kint32min, options->GetExtension(protobuf_unittest::int32_opt));
  1829. EXPECT_EQ(kint64min, options->GetExtension(protobuf_unittest::int64_opt));
  1830. EXPECT_EQ(0 , options->GetExtension(protobuf_unittest::uint32_opt));
  1831. EXPECT_EQ(0 , options->GetExtension(protobuf_unittest::uint64_opt));
  1832. EXPECT_EQ(kint32min, options->GetExtension(protobuf_unittest::sint32_opt));
  1833. EXPECT_EQ(kint64min, options->GetExtension(protobuf_unittest::sint64_opt));
  1834. EXPECT_EQ(0 , options->GetExtension(protobuf_unittest::fixed32_opt));
  1835. EXPECT_EQ(0 , options->GetExtension(protobuf_unittest::fixed64_opt));
  1836. EXPECT_EQ(kint32min, options->GetExtension(protobuf_unittest::sfixed32_opt));
  1837. EXPECT_EQ(kint64min, options->GetExtension(protobuf_unittest::sfixed64_opt));
  1838. options =
  1839. &protobuf_unittest::CustomOptionMaxIntegerValues::descriptor()->options();
  1840. EXPECT_TRUE( options->GetExtension(protobuf_unittest::bool_opt));
  1841. EXPECT_EQ(kint32max , options->GetExtension(protobuf_unittest::int32_opt));
  1842. EXPECT_EQ(kint64max , options->GetExtension(protobuf_unittest::int64_opt));
  1843. EXPECT_EQ(kuint32max, options->GetExtension(protobuf_unittest::uint32_opt));
  1844. EXPECT_EQ(kuint64max, options->GetExtension(protobuf_unittest::uint64_opt));
  1845. EXPECT_EQ(kint32max , options->GetExtension(protobuf_unittest::sint32_opt));
  1846. EXPECT_EQ(kint64max , options->GetExtension(protobuf_unittest::sint64_opt));
  1847. EXPECT_EQ(kuint32max, options->GetExtension(protobuf_unittest::fixed32_opt));
  1848. EXPECT_EQ(kuint64max, options->GetExtension(protobuf_unittest::fixed64_opt));
  1849. EXPECT_EQ(kint32max , options->GetExtension(protobuf_unittest::sfixed32_opt));
  1850. EXPECT_EQ(kint64max , options->GetExtension(protobuf_unittest::sfixed64_opt));
  1851. options =
  1852. &protobuf_unittest::CustomOptionOtherValues::descriptor()->options();
  1853. EXPECT_EQ(-100, options->GetExtension(protobuf_unittest::int32_opt));
  1854. EXPECT_FLOAT_EQ(12.3456789,
  1855. options->GetExtension(protobuf_unittest::float_opt));
  1856. EXPECT_DOUBLE_EQ(1.234567890123456789,
  1857. options->GetExtension(protobuf_unittest::double_opt));
  1858. EXPECT_EQ("Hello, \"World\"",
  1859. options->GetExtension(protobuf_unittest::string_opt));
  1860. EXPECT_EQ(string("Hello\0World", 11),
  1861. options->GetExtension(protobuf_unittest::bytes_opt));
  1862. EXPECT_EQ(protobuf_unittest::DummyMessageContainingEnum::TEST_OPTION_ENUM_TYPE2,
  1863. options->GetExtension(protobuf_unittest::enum_opt));
  1864. options =
  1865. &protobuf_unittest::SettingRealsFromPositiveInts::descriptor()->options();
  1866. EXPECT_FLOAT_EQ(12, options->GetExtension(protobuf_unittest::float_opt));
  1867. EXPECT_DOUBLE_EQ(154, options->GetExtension(protobuf_unittest::double_opt));
  1868. options =
  1869. &protobuf_unittest::SettingRealsFromNegativeInts::descriptor()->options();
  1870. EXPECT_FLOAT_EQ(-12, options->GetExtension(protobuf_unittest::float_opt));
  1871. EXPECT_DOUBLE_EQ(-154, options->GetExtension(protobuf_unittest::double_opt));
  1872. }
  1873. TEST(CustomOptions, ComplexExtensionOptions) {
  1874. const MessageOptions* options =
  1875. &protobuf_unittest::VariousComplexOptions::descriptor()->options();
  1876. EXPECT_EQ(options->GetExtension(protobuf_unittest::complex_opt1).foo(), 42);
  1877. EXPECT_EQ(options->GetExtension(protobuf_unittest::complex_opt1).
  1878. GetExtension(protobuf_unittest::quux), 324);
  1879. EXPECT_EQ(options->GetExtension(protobuf_unittest::complex_opt1).
  1880. GetExtension(protobuf_unittest::corge).qux(), 876);
  1881. EXPECT_EQ(options->GetExtension(protobuf_unittest::complex_opt2).baz(), 987);
  1882. EXPECT_EQ(options->GetExtension(protobuf_unittest::complex_opt2).
  1883. GetExtension(protobuf_unittest::grault), 654);
  1884. EXPECT_EQ(options->GetExtension(protobuf_unittest::complex_opt2).bar().foo(),
  1885. 743);
  1886. EXPECT_EQ(options->GetExtension(protobuf_unittest::complex_opt2).bar().
  1887. GetExtension(protobuf_unittest::quux), 1999);
  1888. EXPECT_EQ(options->GetExtension(protobuf_unittest::complex_opt2).bar().
  1889. GetExtension(protobuf_unittest::corge).qux(), 2008);
  1890. EXPECT_EQ(options->GetExtension(protobuf_unittest::complex_opt2).
  1891. GetExtension(protobuf_unittest::garply).foo(), 741);
  1892. EXPECT_EQ(options->GetExtension(protobuf_unittest::complex_opt2).
  1893. GetExtension(protobuf_unittest::garply).
  1894. GetExtension(protobuf_unittest::quux), 1998);
  1895. EXPECT_EQ(options->GetExtension(protobuf_unittest::complex_opt2).
  1896. GetExtension(protobuf_unittest::garply).
  1897. GetExtension(protobuf_unittest::corge).qux(), 2121);
  1898. EXPECT_EQ(options->GetExtension(
  1899. protobuf_unittest::ComplexOptionType2::ComplexOptionType4::complex_opt4).
  1900. waldo(), 1971);
  1901. EXPECT_EQ(options->GetExtension(protobuf_unittest::complex_opt2).
  1902. fred().waldo(), 321);
  1903. EXPECT_EQ(9, options->GetExtension(protobuf_unittest::complex_opt3).qux());
  1904. EXPECT_EQ(22, options->GetExtension(protobuf_unittest::complex_opt3).
  1905. complexoptiontype5().plugh());
  1906. EXPECT_EQ(24, options->GetExtension(protobuf_unittest::complexopt6).xyzzy());
  1907. }
  1908. TEST(CustomOptions, OptionsFromOtherFile) {
  1909. // Test that to use a custom option, we only need to import the file
  1910. // defining the option; we do not also have to import descriptor.proto.
  1911. DescriptorPool pool;
  1912. FileDescriptorProto file_proto;
  1913. FileDescriptorProto::descriptor()->file()->CopyTo(&file_proto);
  1914. ASSERT_TRUE(pool.BuildFile(file_proto) != NULL);
  1915. protobuf_unittest::TestMessageWithCustomOptions::descriptor()
  1916. ->file()->CopyTo(&file_proto);
  1917. ASSERT_TRUE(pool.BuildFile(file_proto) != NULL);
  1918. ASSERT_TRUE(TextFormat::ParseFromString(
  1919. "name: \"custom_options_import.proto\" "
  1920. "package: \"protobuf_unittest\" "
  1921. "dependency: \"google/protobuf/unittest_custom_options.proto\" "
  1922. "options { "
  1923. " uninterpreted_option { "
  1924. " name { "
  1925. " name_part: \"file_opt1\" "
  1926. " is_extension: true "
  1927. " } "
  1928. " positive_int_value: 1234 "
  1929. " } "
  1930. // Test a non-extension option too. (At one point this failed due to a
  1931. // bug.)
  1932. " uninterpreted_option { "
  1933. " name { "
  1934. " name_part: \"java_package\" "
  1935. " is_extension: false "
  1936. " } "
  1937. " string_value: \"foo\" "
  1938. " } "
  1939. // Test that enum-typed options still work too. (At one point this also
  1940. // failed due to a bug.)
  1941. " uninterpreted_option { "
  1942. " name { "
  1943. " name_part: \"optimize_for\" "
  1944. " is_extension: false "
  1945. " } "
  1946. " identifier_value: \"SPEED\" "
  1947. " } "
  1948. "}"
  1949. ,
  1950. &file_proto));
  1951. const FileDescriptor* file = pool.BuildFile(file_proto);
  1952. ASSERT_TRUE(file != NULL);
  1953. EXPECT_EQ(1234, file->options().GetExtension(protobuf_unittest::file_opt1));
  1954. EXPECT_TRUE(file->options().has_java_package());
  1955. EXPECT_EQ("foo", file->options().java_package());
  1956. EXPECT_TRUE(file->options().has_optimize_for());
  1957. EXPECT_EQ(FileOptions::SPEED, file->options().optimize_for());
  1958. }
  1959. TEST(CustomOptions, MessageOptionThreeFieldsSet) {
  1960. // This tests a bug which previously existed in custom options parsing. The
  1961. // bug occurred when you defined a custom option with message type and then
  1962. // set three fields of that option on a single definition (see the example
  1963. // below). The bug is a bit hard to explain, so check the change history if
  1964. // you want to know more.
  1965. DescriptorPool pool;
  1966. FileDescriptorProto file_proto;
  1967. FileDescriptorProto::descriptor()->file()->CopyTo(&file_proto);
  1968. ASSERT_TRUE(pool.BuildFile(file_proto) != NULL);
  1969. protobuf_unittest::TestMessageWithCustomOptions::descriptor()
  1970. ->file()->CopyTo(&file_proto);
  1971. ASSERT_TRUE(pool.BuildFile(file_proto) != NULL);
  1972. // The following represents the definition:
  1973. //
  1974. // import "google/protobuf/unittest_custom_options.proto"
  1975. // package protobuf_unittest;
  1976. // message Foo {
  1977. // option (complex_opt1).foo = 1234;
  1978. // option (complex_opt1).foo2 = 1234;
  1979. // option (complex_opt1).foo3 = 1234;
  1980. // }
  1981. ASSERT_TRUE(TextFormat::ParseFromString(
  1982. "name: \"custom_options_import.proto\" "
  1983. "package: \"protobuf_unittest\" "
  1984. "dependency: \"google/protobuf/unittest_custom_options.proto\" "
  1985. "message_type { "
  1986. " name: \"Foo\" "
  1987. " options { "
  1988. " uninterpreted_option { "
  1989. " name { "
  1990. " name_part: \"complex_opt1\" "
  1991. " is_extension: true "
  1992. " } "
  1993. " name { "
  1994. " name_part: \"foo\" "
  1995. " is_extension: false "
  1996. " } "
  1997. " positive_int_value: 1234 "
  1998. " } "
  1999. " uninterpreted_option { "
  2000. " name { "
  2001. " name_part: \"complex_opt1\" "
  2002. " is_extension: true "
  2003. " } "
  2004. " name { "
  2005. " name_part: \"foo2\" "
  2006. " is_extension: false "
  2007. " } "
  2008. " positive_int_value: 1234 "
  2009. " } "
  2010. " uninterpreted_option { "
  2011. " name { "
  2012. " name_part: \"complex_opt1\" "
  2013. " is_extension: true "
  2014. " } "
  2015. " name { "
  2016. " name_part: \"foo3\" "
  2017. " is_extension: false "
  2018. " } "
  2019. " positive_int_value: 1234 "
  2020. " } "
  2021. " } "
  2022. "}",
  2023. &file_proto));
  2024. const FileDescriptor* file = pool.BuildFile(file_proto);
  2025. ASSERT_TRUE(file != NULL);
  2026. ASSERT_EQ(1, file->message_type_count());
  2027. const MessageOptions& options = file->message_type(0)->options();
  2028. EXPECT_EQ(1234, options.GetExtension(protobuf_unittest::complex_opt1).foo());
  2029. }
  2030. // Check that aggregate options were parsed and saved correctly in
  2031. // the appropriate descriptors.
  2032. TEST(CustomOptions, AggregateOptions) {
  2033. const Descriptor* msg = protobuf_unittest::AggregateMessage::descriptor();
  2034. const FileDescriptor* file = msg->file();
  2035. const FieldDescriptor* field = msg->FindFieldByName("fieldname");
  2036. const EnumDescriptor* enumd = file->FindEnumTypeByName("AggregateEnum");
  2037. const EnumValueDescriptor* enumv = enumd->FindValueByName("VALUE");
  2038. const ServiceDescriptor* service = file->FindServiceByName(
  2039. "AggregateService");
  2040. const MethodDescriptor* method = service->FindMethodByName("Method");
  2041. // Tests for the different types of data embedded in fileopt
  2042. const protobuf_unittest::Aggregate& file_options =
  2043. file->options().GetExtension(protobuf_unittest::fileopt);
  2044. EXPECT_EQ(100, file_options.i());
  2045. EXPECT_EQ("FileAnnotation", file_options.s());
  2046. EXPECT_EQ("NestedFileAnnotation", file_options.sub().s());
  2047. EXPECT_EQ("FileExtensionAnnotation",
  2048. file_options.file().GetExtension(protobuf_unittest::fileopt).s());
  2049. EXPECT_EQ("EmbeddedMessageSetElement",
  2050. file_options.mset().GetExtension(
  2051. protobuf_unittest::AggregateMessageSetElement
  2052. ::message_set_extension).s());
  2053. // Simple tests for all the other types of annotations
  2054. EXPECT_EQ("MessageAnnotation",
  2055. msg->options().GetExtension(protobuf_unittest::msgopt).s());
  2056. EXPECT_EQ("FieldAnnotation",
  2057. field->options().GetExtension(protobuf_unittest::fieldopt).s());
  2058. EXPECT_EQ("EnumAnnotation",
  2059. enumd->options().GetExtension(protobuf_unittest::enumopt).s());
  2060. EXPECT_EQ("EnumValueAnnotation",
  2061. enumv->options().GetExtension(protobuf_unittest::enumvalopt).s());
  2062. EXPECT_EQ("ServiceAnnotation",
  2063. service->options().GetExtension(protobuf_unittest::serviceopt).s());
  2064. EXPECT_EQ("MethodAnnotation",
  2065. method->options().GetExtension(protobuf_unittest::methodopt).s());
  2066. }
  2067. // ===================================================================
  2068. // The tests below trigger every unique call to AddError() in descriptor.cc,
  2069. // in the order in which they appear in that file. I'm using TextFormat here
  2070. // to specify the input descriptors because building them using code would
  2071. // be too bulky.
  2072. class MockErrorCollector : public DescriptorPool::ErrorCollector {
  2073. public:
  2074. MockErrorCollector() {}
  2075. ~MockErrorCollector() {}
  2076. string text_;
  2077. // implements ErrorCollector ---------------------------------------
  2078. void AddError(const string& filename,
  2079. const string& element_name, const Message* descriptor,
  2080. ErrorLocation location, const string& message) {
  2081. const char* location_name = NULL;
  2082. switch (location) {
  2083. case NAME : location_name = "NAME" ; break;
  2084. case NUMBER : location_name = "NUMBER" ; break;
  2085. case TYPE : location_name = "TYPE" ; break;
  2086. case EXTENDEE : location_name = "EXTENDEE" ; break;
  2087. case DEFAULT_VALUE: location_name = "DEFAULT_VALUE"; break;
  2088. case OPTION_NAME : location_name = "OPTION_NAME" ; break;
  2089. case OPTION_VALUE : location_name = "OPTION_VALUE" ; break;
  2090. case INPUT_TYPE : location_name = "INPUT_TYPE" ; break;
  2091. case OUTPUT_TYPE : location_name = "OUTPUT_TYPE" ; break;
  2092. case OTHER : location_name = "OTHER" ; break;
  2093. }
  2094. strings::SubstituteAndAppend(
  2095. &text_, "$0: $1: $2: $3\n",
  2096. filename, element_name, location_name, message);
  2097. }
  2098. };
  2099. class ValidationErrorTest : public testing::Test {
  2100. protected:
  2101. // Parse file_text as a FileDescriptorProto in text format and add it
  2102. // to the DescriptorPool. Expect no errors.
  2103. void BuildFile(const string& file_text) {
  2104. FileDescriptorProto file_proto;
  2105. ASSERT_TRUE(TextFormat::ParseFromString(file_text, &file_proto));
  2106. ASSERT_TRUE(pool_.BuildFile(file_proto) != NULL);
  2107. }
  2108. // Parse file_text as a FileDescriptorProto in text format and add it
  2109. // to the DescriptorPool. Expect errors to be produced which match the
  2110. // given error text.
  2111. void BuildFileWithErrors(const string& file_text,
  2112. const string& expected_errors) {
  2113. FileDescriptorProto file_proto;
  2114. ASSERT_TRUE(TextFormat::ParseFromString(file_text, &file_proto));
  2115. MockErrorCollector error_collector;
  2116. EXPECT_TRUE(
  2117. pool_.BuildFileCollectingErrors(file_proto, &error_collector) == NULL);
  2118. EXPECT_EQ(expected_errors, error_collector.text_);
  2119. }
  2120. // Builds some already-parsed file in our test pool.
  2121. void BuildFileInTestPool(const FileDescriptor* file) {
  2122. FileDescriptorProto file_proto;
  2123. file->CopyTo(&file_proto);
  2124. ASSERT_TRUE(pool_.BuildFile(file_proto) != NULL);
  2125. }
  2126. // Build descriptor.proto in our test pool. This allows us to extend it in
  2127. // the test pool, so we can test custom options.
  2128. void BuildDescriptorMessagesInTestPool() {
  2129. BuildFileInTestPool(DescriptorProto::descriptor()->file());
  2130. }
  2131. DescriptorPool pool_;
  2132. };
  2133. TEST_F(ValidationErrorTest, AlreadyDefined) {
  2134. BuildFileWithErrors(
  2135. "name: \"foo.proto\" "
  2136. "message_type { name: \"Foo\" }"
  2137. "message_type { name: \"Foo\" }",
  2138. "foo.proto: Foo: NAME: \"Foo\" is already defined.\n");
  2139. }
  2140. TEST_F(ValidationErrorTest, AlreadyDefinedInPackage) {
  2141. BuildFileWithErrors(
  2142. "name: \"foo.proto\" "
  2143. "package: \"foo.bar\" "
  2144. "message_type { name: \"Foo\" }"
  2145. "message_type { name: \"Foo\" }",
  2146. "foo.proto: foo.bar.Foo: NAME: \"Foo\" is already defined in "
  2147. "\"foo.bar\".\n");
  2148. }
  2149. TEST_F(ValidationErrorTest, AlreadyDefinedInOtherFile) {
  2150. BuildFile(
  2151. "name: \"foo.proto\" "
  2152. "message_type { name: \"Foo\" }");
  2153. BuildFileWithErrors(
  2154. "name: \"bar.proto\" "
  2155. "message_type { name: \"Foo\" }",
  2156. "bar.proto: Foo: NAME: \"Foo\" is already defined in file "
  2157. "\"foo.proto\".\n");
  2158. }
  2159. TEST_F(ValidationErrorTest, PackageAlreadyDefined) {
  2160. BuildFile(
  2161. "name: \"foo.proto\" "
  2162. "message_type { name: \"foo\" }");
  2163. BuildFileWithErrors(
  2164. "name: \"bar.proto\" "
  2165. "package: \"foo.bar\"",
  2166. "bar.proto: foo: NAME: \"foo\" is already defined (as something other "
  2167. "than a package) in file \"foo.proto\".\n");
  2168. }
  2169. TEST_F(ValidationErrorTest, EnumValueAlreadyDefinedInParent) {
  2170. BuildFileWithErrors(
  2171. "name: \"foo.proto\" "
  2172. "enum_type { name: \"Foo\" value { name: \"FOO\" number: 1 } } "
  2173. "enum_type { name: \"Bar\" value { name: \"FOO\" number: 1 } } ",
  2174. "foo.proto: FOO: NAME: \"FOO\" is already defined.\n"
  2175. "foo.proto: FOO: NAME: Note that enum values use C++ scoping rules, "
  2176. "meaning that enum values are siblings of their type, not children of "
  2177. "it. Therefore, \"FOO\" must be unique within the global scope, not "
  2178. "just within \"Bar\".\n");
  2179. }
  2180. TEST_F(ValidationErrorTest, EnumValueAlreadyDefinedInParentNonGlobal) {
  2181. BuildFileWithErrors(
  2182. "name: \"foo.proto\" "
  2183. "package: \"pkg\" "
  2184. "enum_type { name: \"Foo\" value { name: \"FOO\" number: 1 } } "
  2185. "enum_type { name: \"Bar\" value { name: \"FOO\" number: 1 } } ",
  2186. "foo.proto: pkg.FOO: NAME: \"FOO\" is already defined in \"pkg\".\n"
  2187. "foo.proto: pkg.FOO: NAME: Note that enum values use C++ scoping rules, "
  2188. "meaning that enum values are siblings of their type, not children of "
  2189. "it. Therefore, \"FOO\" must be unique within \"pkg\", not just within "
  2190. "\"Bar\".\n");
  2191. }
  2192. TEST_F(ValidationErrorTest, MissingName) {
  2193. BuildFileWithErrors(
  2194. "name: \"foo.proto\" "
  2195. "message_type { }",
  2196. "foo.proto: : NAME: Missing name.\n");
  2197. }
  2198. TEST_F(ValidationErrorTest, InvalidName) {
  2199. BuildFileWithErrors(
  2200. "name: \"foo.proto\" "
  2201. "message_type { name: \"$\" }",
  2202. "foo.proto: $: NAME: \"$\" is not a valid identifier.\n");
  2203. }
  2204. TEST_F(ValidationErrorTest, InvalidPackageName) {
  2205. BuildFileWithErrors(
  2206. "name: \"foo.proto\" "
  2207. "package: \"foo.$\"",
  2208. "foo.proto: foo.$: NAME: \"$\" is not a valid identifier.\n");
  2209. }
  2210. TEST_F(ValidationErrorTest, MissingFileName) {
  2211. BuildFileWithErrors(
  2212. "",
  2213. ": : OTHER: Missing field: FileDescriptorProto.name.\n");
  2214. }
  2215. TEST_F(ValidationErrorTest, DupeDependency) {
  2216. BuildFile("name: \"foo.proto\"");
  2217. BuildFileWithErrors(
  2218. "name: \"bar.proto\" "
  2219. "dependency: \"foo.proto\" "
  2220. "dependency: \"foo.proto\" ",
  2221. "bar.proto: bar.proto: OTHER: Import \"foo.proto\" was listed twice.\n");
  2222. }
  2223. TEST_F(ValidationErrorTest, UnknownDependency) {
  2224. BuildFileWithErrors(
  2225. "name: \"bar.proto\" "
  2226. "dependency: \"foo.proto\" ",
  2227. "bar.proto: bar.proto: OTHER: Import \"foo.proto\" has not been loaded.\n");
  2228. }
  2229. TEST_F(ValidationErrorTest, InvalidPublicDependencyIndex) {
  2230. BuildFile("name: \"foo.proto\"");
  2231. BuildFileWithErrors(
  2232. "name: \"bar.proto\" "
  2233. "dependency: \"foo.proto\" "
  2234. "public_dependency: 1",
  2235. "bar.proto: bar.proto: OTHER: Invalid public dependency index.\n");
  2236. }
  2237. TEST_F(ValidationErrorTest, ForeignUnimportedPackageNoCrash) {
  2238. // Used to crash: If we depend on a non-existent file and then refer to a
  2239. // package defined in a file that we didn't import, and that package is
  2240. // nested within a parent package which this file is also in, and we don't
  2241. // include that parent package in the name (i.e. we do a relative lookup)...
  2242. // Yes, really.
  2243. BuildFile(
  2244. "name: 'foo.proto' "
  2245. "package: 'outer.foo' ");
  2246. BuildFileWithErrors(
  2247. "name: 'bar.proto' "
  2248. "dependency: 'baz.proto' "
  2249. "package: 'outer.bar' "
  2250. "message_type { "
  2251. " name: 'Bar' "
  2252. " field { name:'bar' number:1 label:LABEL_OPTIONAL type_name:'foo.Foo' }"
  2253. "}",
  2254. "bar.proto: bar.proto: OTHER: Import \"baz.proto\" has not been loaded.\n"
  2255. "bar.proto: outer.bar.Bar.bar: TYPE: \"outer.foo\" seems to be defined in "
  2256. "\"foo.proto\", which is not imported by \"bar.proto\". To use it here, "
  2257. "please add the necessary import.\n");
  2258. }
  2259. TEST_F(ValidationErrorTest, DupeFile) {
  2260. BuildFile(
  2261. "name: \"foo.proto\" "
  2262. "message_type { name: \"Foo\" }");
  2263. // Note: We should *not* get redundant errors about "Foo" already being
  2264. // defined.
  2265. BuildFileWithErrors(
  2266. "name: \"foo.proto\" "
  2267. "message_type { name: \"Foo\" } "
  2268. // Add another type so that the files aren't identical (in which case there
  2269. // would be no error).
  2270. "enum_type { name: \"Bar\" }",
  2271. "foo.proto: foo.proto: OTHER: A file with this name is already in the "
  2272. "pool.\n");
  2273. }
  2274. TEST_F(ValidationErrorTest, FieldInExtensionRange) {
  2275. BuildFileWithErrors(
  2276. "name: \"foo.proto\" "
  2277. "message_type {"
  2278. " name: \"Foo\""
  2279. " field { name: \"foo\" number: 9 label:LABEL_OPTIONAL type:TYPE_INT32 }"
  2280. " field { name: \"bar\" number: 10 label:LABEL_OPTIONAL type:TYPE_INT32 }"
  2281. " field { name: \"baz\" number: 19 label:LABEL_OPTIONAL type:TYPE_INT32 }"
  2282. " field { name: \"qux\" number: 20 label:LABEL_OPTIONAL type:TYPE_INT32 }"
  2283. " extension_range { start: 10 end: 20 }"
  2284. "}",
  2285. "foo.proto: Foo.bar: NUMBER: Extension range 10 to 19 includes field "
  2286. "\"bar\" (10).\n"
  2287. "foo.proto: Foo.baz: NUMBER: Extension range 10 to 19 includes field "
  2288. "\"baz\" (19).\n");
  2289. }
  2290. TEST_F(ValidationErrorTest, OverlappingExtensionRanges) {
  2291. BuildFileWithErrors(
  2292. "name: \"foo.proto\" "
  2293. "message_type {"
  2294. " name: \"Foo\""
  2295. " extension_range { start: 10 end: 20 }"
  2296. " extension_range { start: 20 end: 30 }"
  2297. " extension_range { start: 19 end: 21 }"
  2298. "}",
  2299. "foo.proto: Foo: NUMBER: Extension range 19 to 20 overlaps with "
  2300. "already-defined range 10 to 19.\n"
  2301. "foo.proto: Foo: NUMBER: Extension range 19 to 20 overlaps with "
  2302. "already-defined range 20 to 29.\n");
  2303. }
  2304. TEST_F(ValidationErrorTest, InvalidDefaults) {
  2305. BuildFileWithErrors(
  2306. "name: \"foo.proto\" "
  2307. "message_type {"
  2308. " name: \"Foo\""
  2309. // Invalid number.
  2310. " field { name: \"foo\" number: 1 label: LABEL_OPTIONAL type: TYPE_INT32"
  2311. " default_value: \"abc\" }"
  2312. // Empty default value.
  2313. " field { name: \"bar\" number: 2 label: LABEL_OPTIONAL type: TYPE_INT32"
  2314. " default_value: \"\" }"
  2315. // Invalid boolean.
  2316. " field { name: \"baz\" number: 3 label: LABEL_OPTIONAL type: TYPE_BOOL"
  2317. " default_value: \"abc\" }"
  2318. // Messages can't have defaults.
  2319. " field { name: \"qux\" number: 4 label: LABEL_OPTIONAL type: TYPE_MESSAGE"
  2320. " default_value: \"abc\" type_name: \"Foo\" }"
  2321. // Same thing, but we don't know that this field has message type until
  2322. // we look up the type name.
  2323. " field { name: \"quux\" number: 5 label: LABEL_OPTIONAL"
  2324. " default_value: \"abc\" type_name: \"Foo\" }"
  2325. // Repeateds can't have defaults.
  2326. " field { name: \"corge\" number: 6 label: LABEL_REPEATED type: TYPE_INT32"
  2327. " default_value: \"1\" }"
  2328. "}",
  2329. "foo.proto: Foo.foo: DEFAULT_VALUE: Couldn't parse default value.\n"
  2330. "foo.proto: Foo.bar: DEFAULT_VALUE: Couldn't parse default value.\n"
  2331. "foo.proto: Foo.baz: DEFAULT_VALUE: Boolean default must be true or "
  2332. "false.\n"
  2333. "foo.proto: Foo.qux: DEFAULT_VALUE: Messages can't have default values.\n"
  2334. "foo.proto: Foo.corge: DEFAULT_VALUE: Repeated fields can't have default "
  2335. "values.\n"
  2336. // This ends up being reported later because the error is detected at
  2337. // cross-linking time.
  2338. "foo.proto: Foo.quux: DEFAULT_VALUE: Messages can't have default "
  2339. "values.\n");
  2340. }
  2341. TEST_F(ValidationErrorTest, NegativeFieldNumber) {
  2342. BuildFileWithErrors(
  2343. "name: \"foo.proto\" "
  2344. "message_type {"
  2345. " name: \"Foo\""
  2346. " field { name: \"foo\" number: -1 label:LABEL_OPTIONAL type:TYPE_INT32 }"
  2347. "}",
  2348. "foo.proto: Foo.foo: NUMBER: Field numbers must be positive integers.\n");
  2349. }
  2350. TEST_F(ValidationErrorTest, HugeFieldNumber) {
  2351. BuildFileWithErrors(
  2352. "name: \"foo.proto\" "
  2353. "message_type {"
  2354. " name: \"Foo\""
  2355. " field { name: \"foo\" number: 0x70000000 "
  2356. " label:LABEL_OPTIONAL type:TYPE_INT32 }"
  2357. "}",
  2358. "foo.proto: Foo.foo: NUMBER: Field numbers cannot be greater than "
  2359. "536870911.\n");
  2360. }
  2361. TEST_F(ValidationErrorTest, ReservedFieldNumber) {
  2362. BuildFileWithErrors(
  2363. "name: \"foo.proto\" "
  2364. "message_type {"
  2365. " name: \"Foo\""
  2366. " field {name:\"foo\" number: 18999 label:LABEL_OPTIONAL type:TYPE_INT32 }"
  2367. " field {name:\"bar\" number: 19000 label:LABEL_OPTIONAL type:TYPE_INT32 }"
  2368. " field {name:\"baz\" number: 19999 label:LABEL_OPTIONAL type:TYPE_INT32 }"
  2369. " field {name:\"qux\" number: 20000 label:LABEL_OPTIONAL type:TYPE_INT32 }"
  2370. "}",
  2371. "foo.proto: Foo.bar: NUMBER: Field numbers 19000 through 19999 are "
  2372. "reserved for the protocol buffer library implementation.\n"
  2373. "foo.proto: Foo.baz: NUMBER: Field numbers 19000 through 19999 are "
  2374. "reserved for the protocol buffer library implementation.\n");
  2375. }
  2376. TEST_F(ValidationErrorTest, ExtensionMissingExtendee) {
  2377. BuildFileWithErrors(
  2378. "name: \"foo.proto\" "
  2379. "message_type {"
  2380. " name: \"Foo\""
  2381. " extension { name: \"foo\" number: 1 label: LABEL_OPTIONAL"
  2382. " type_name: \"Foo\" }"
  2383. "}",
  2384. "foo.proto: Foo.foo: EXTENDEE: FieldDescriptorProto.extendee not set for "
  2385. "extension field.\n");
  2386. }
  2387. TEST_F(ValidationErrorTest, NonExtensionWithExtendee) {
  2388. BuildFileWithErrors(
  2389. "name: \"foo.proto\" "
  2390. "message_type {"
  2391. " name: \"Bar\""
  2392. " extension_range { start: 1 end: 2 }"
  2393. "}"
  2394. "message_type {"
  2395. " name: \"Foo\""
  2396. " field { name: \"foo\" number: 1 label: LABEL_OPTIONAL"
  2397. " type_name: \"Foo\" extendee: \"Bar\" }"
  2398. "}",
  2399. "foo.proto: Foo.foo: EXTENDEE: FieldDescriptorProto.extendee set for "
  2400. "non-extension field.\n");
  2401. }
  2402. TEST_F(ValidationErrorTest, FieldNumberConflict) {
  2403. BuildFileWithErrors(
  2404. "name: \"foo.proto\" "
  2405. "message_type {"
  2406. " name: \"Foo\""
  2407. " field { name: \"foo\" number: 1 label:LABEL_OPTIONAL type:TYPE_INT32 }"
  2408. " field { name: \"bar\" number: 1 label:LABEL_OPTIONAL type:TYPE_INT32 }"
  2409. "}",
  2410. "foo.proto: Foo.bar: NUMBER: Field number 1 has already been used in "
  2411. "\"Foo\" by field \"foo\".\n");
  2412. }
  2413. TEST_F(ValidationErrorTest, BadMessageSetExtensionType) {
  2414. BuildFileWithErrors(
  2415. "name: \"foo.proto\" "
  2416. "message_type {"
  2417. " name: \"MessageSet\""
  2418. " options { message_set_wire_format: true }"
  2419. " extension_range { start: 4 end: 5 }"
  2420. "}"
  2421. "message_type {"
  2422. " name: \"Foo\""
  2423. " extension { name:\"foo\" number:4 label:LABEL_OPTIONAL type:TYPE_INT32"
  2424. " extendee: \"MessageSet\" }"
  2425. "}",
  2426. "foo.proto: Foo.foo: TYPE: Extensions of MessageSets must be optional "
  2427. "messages.\n");
  2428. }
  2429. TEST_F(ValidationErrorTest, BadMessageSetExtensionLabel) {
  2430. BuildFileWithErrors(
  2431. "name: \"foo.proto\" "
  2432. "message_type {"
  2433. " name: \"MessageSet\""
  2434. " options { message_set_wire_format: true }"
  2435. " extension_range { start: 4 end: 5 }"
  2436. "}"
  2437. "message_type {"
  2438. " name: \"Foo\""
  2439. " extension { name:\"foo\" number:4 label:LABEL_REPEATED type:TYPE_MESSAGE"
  2440. " type_name: \"Foo\" extendee: \"MessageSet\" }"
  2441. "}",
  2442. "foo.proto: Foo.foo: TYPE: Extensions of MessageSets must be optional "
  2443. "messages.\n");
  2444. }
  2445. TEST_F(ValidationErrorTest, FieldInMessageSet) {
  2446. BuildFileWithErrors(
  2447. "name: \"foo.proto\" "
  2448. "message_type {"
  2449. " name: \"Foo\""
  2450. " options { message_set_wire_format: true }"
  2451. " field { name: \"foo\" number: 1 label:LABEL_OPTIONAL type:TYPE_INT32 }"
  2452. "}",
  2453. "foo.proto: Foo.foo: NAME: MessageSets cannot have fields, only "
  2454. "extensions.\n");
  2455. }
  2456. TEST_F(ValidationErrorTest, NegativeExtensionRangeNumber) {
  2457. BuildFileWithErrors(
  2458. "name: \"foo.proto\" "
  2459. "message_type {"
  2460. " name: \"Foo\""
  2461. " extension_range { start: -10 end: -1 }"
  2462. "}",
  2463. "foo.proto: Foo: NUMBER: Extension numbers must be positive integers.\n");
  2464. }
  2465. TEST_F(ValidationErrorTest, HugeExtensionRangeNumber) {
  2466. BuildFileWithErrors(
  2467. "name: \"foo.proto\" "
  2468. "message_type {"
  2469. " name: \"Foo\""
  2470. " extension_range { start: 1 end: 0x70000000 }"
  2471. "}",
  2472. "foo.proto: Foo: NUMBER: Extension numbers cannot be greater than "
  2473. "536870911.\n");
  2474. }
  2475. TEST_F(ValidationErrorTest, ExtensionRangeEndBeforeStart) {
  2476. BuildFileWithErrors(
  2477. "name: \"foo.proto\" "
  2478. "message_type {"
  2479. " name: \"Foo\""
  2480. " extension_range { start: 10 end: 10 }"
  2481. " extension_range { start: 10 end: 5 }"
  2482. "}",
  2483. "foo.proto: Foo: NUMBER: Extension range end number must be greater than "
  2484. "start number.\n"
  2485. "foo.proto: Foo: NUMBER: Extension range end number must be greater than "
  2486. "start number.\n");
  2487. }
  2488. TEST_F(ValidationErrorTest, EmptyEnum) {
  2489. BuildFileWithErrors(
  2490. "name: \"foo.proto\" "
  2491. "enum_type { name: \"Foo\" }"
  2492. // Also use the empty enum in a message to make sure there are no crashes
  2493. // during validation (possible if the code attempts to derive a default
  2494. // value for the field).
  2495. "message_type {"
  2496. " name: \"Bar\""
  2497. " field { name: \"foo\" number: 1 label:LABEL_OPTIONAL type_name:\"Foo\" }"
  2498. " field { name: \"bar\" number: 2 label:LABEL_OPTIONAL type_name:\"Foo\" "
  2499. " default_value: \"NO_SUCH_VALUE\" }"
  2500. "}",
  2501. "foo.proto: Foo: NAME: Enums must contain at least one value.\n"
  2502. "foo.proto: Bar.bar: DEFAULT_VALUE: Enum type \"Foo\" has no value named "
  2503. "\"NO_SUCH_VALUE\".\n");
  2504. }
  2505. TEST_F(ValidationErrorTest, UndefinedExtendee) {
  2506. BuildFileWithErrors(
  2507. "name: \"foo.proto\" "
  2508. "message_type {"
  2509. " name: \"Foo\""
  2510. " extension { name:\"foo\" number:1 label:LABEL_OPTIONAL type:TYPE_INT32"
  2511. " extendee: \"Bar\" }"
  2512. "}",
  2513. "foo.proto: Foo.foo: EXTENDEE: \"Bar\" is not defined.\n");
  2514. }
  2515. TEST_F(ValidationErrorTest, NonMessageExtendee) {
  2516. BuildFileWithErrors(
  2517. "name: \"foo.proto\" "
  2518. "enum_type { name: \"Bar\" value { name:\"DUMMY\" number:0 } }"
  2519. "message_type {"
  2520. " name: \"Foo\""
  2521. " extension { name:\"foo\" number:1 label:LABEL_OPTIONAL type:TYPE_INT32"
  2522. " extendee: \"Bar\" }"
  2523. "}",
  2524. "foo.proto: Foo.foo: EXTENDEE: \"Bar\" is not a message type.\n");
  2525. }
  2526. TEST_F(ValidationErrorTest, NotAnExtensionNumber) {
  2527. BuildFileWithErrors(
  2528. "name: \"foo.proto\" "
  2529. "message_type {"
  2530. " name: \"Bar\""
  2531. "}"
  2532. "message_type {"
  2533. " name: \"Foo\""
  2534. " extension { name:\"foo\" number:1 label:LABEL_OPTIONAL type:TYPE_INT32"
  2535. " extendee: \"Bar\" }"
  2536. "}",
  2537. "foo.proto: Foo.foo: NUMBER: \"Bar\" does not declare 1 as an extension "
  2538. "number.\n");
  2539. }
  2540. TEST_F(ValidationErrorTest, UndefinedFieldType) {
  2541. BuildFileWithErrors(
  2542. "name: \"foo.proto\" "
  2543. "message_type {"
  2544. " name: \"Foo\""
  2545. " field { name:\"foo\" number:1 label:LABEL_OPTIONAL type_name:\"Bar\" }"
  2546. "}",
  2547. "foo.proto: Foo.foo: TYPE: \"Bar\" is not defined.\n");
  2548. }
  2549. TEST_F(ValidationErrorTest, FieldTypeDefinedInUndeclaredDependency) {
  2550. BuildFile(
  2551. "name: \"bar.proto\" "
  2552. "message_type { name: \"Bar\" } ");
  2553. BuildFileWithErrors(
  2554. "name: \"foo.proto\" "
  2555. "message_type {"
  2556. " name: \"Foo\""
  2557. " field { name:\"foo\" number:1 label:LABEL_OPTIONAL type_name:\"Bar\" }"
  2558. "}",
  2559. "foo.proto: Foo.foo: TYPE: \"Bar\" seems to be defined in \"bar.proto\", "
  2560. "which is not imported by \"foo.proto\". To use it here, please add the "
  2561. "necessary import.\n");
  2562. }
  2563. TEST_F(ValidationErrorTest, FieldTypeDefinedInIndirectDependency) {
  2564. // Test for hidden dependencies.
  2565. //
  2566. // // bar.proto
  2567. // message Bar{}
  2568. //
  2569. // // forward.proto
  2570. // import "bar.proto"
  2571. //
  2572. // // foo.proto
  2573. // import "forward.proto"
  2574. // message Foo {
  2575. // optional Bar foo = 1; // Error, needs to import bar.proto explicitly.
  2576. // }
  2577. //
  2578. BuildFile(
  2579. "name: \"bar.proto\" "
  2580. "message_type { name: \"Bar\" }");
  2581. BuildFile(
  2582. "name: \"forward.proto\""
  2583. "dependency: \"bar.proto\"");
  2584. BuildFileWithErrors(
  2585. "name: \"foo.proto\" "
  2586. "dependency: \"forward.proto\" "
  2587. "message_type {"
  2588. " name: \"Foo\""
  2589. " field { name:\"foo\" number:1 label:LABEL_OPTIONAL type_name:\"Bar\" }"
  2590. "}",
  2591. "foo.proto: Foo.foo: TYPE: \"Bar\" seems to be defined in \"bar.proto\", "
  2592. "which is not imported by \"foo.proto\". To use it here, please add the "
  2593. "necessary import.\n");
  2594. }
  2595. TEST_F(ValidationErrorTest, FieldTypeDefinedInPublicDependency) {
  2596. // Test for public dependencies.
  2597. //
  2598. // // bar.proto
  2599. // message Bar{}
  2600. //
  2601. // // forward.proto
  2602. // import public "bar.proto"
  2603. //
  2604. // // foo.proto
  2605. // import "forward.proto"
  2606. // message Foo {
  2607. // optional Bar foo = 1; // Correct. "bar.proto" is public imported into
  2608. // // forward.proto, so when "foo.proto" imports
  2609. // // "forward.proto", it imports "bar.proto" too.
  2610. // }
  2611. //
  2612. BuildFile(
  2613. "name: \"bar.proto\" "
  2614. "message_type { name: \"Bar\" }");
  2615. BuildFile(
  2616. "name: \"forward.proto\""
  2617. "dependency: \"bar.proto\" "
  2618. "public_dependency: 0");
  2619. BuildFile(
  2620. "name: \"foo.proto\" "
  2621. "dependency: \"forward.proto\" "
  2622. "message_type {"
  2623. " name: \"Foo\""
  2624. " field { name:\"foo\" number:1 label:LABEL_OPTIONAL type_name:\"Bar\" }"
  2625. "}");
  2626. }
  2627. TEST_F(ValidationErrorTest, FieldTypeDefinedInTransitivePublicDependency) {
  2628. // Test for public dependencies.
  2629. //
  2630. // // bar.proto
  2631. // message Bar{}
  2632. //
  2633. // // forward.proto
  2634. // import public "bar.proto"
  2635. //
  2636. // // forward2.proto
  2637. // import public "forward.proto"
  2638. //
  2639. // // foo.proto
  2640. // import "forward2.proto"
  2641. // message Foo {
  2642. // optional Bar foo = 1; // Correct, public imports are transitive.
  2643. // }
  2644. //
  2645. BuildFile(
  2646. "name: \"bar.proto\" "
  2647. "message_type { name: \"Bar\" }");
  2648. BuildFile(
  2649. "name: \"forward.proto\""
  2650. "dependency: \"bar.proto\" "
  2651. "public_dependency: 0");
  2652. BuildFile(
  2653. "name: \"forward2.proto\""
  2654. "dependency: \"forward.proto\" "
  2655. "public_dependency: 0");
  2656. BuildFile(
  2657. "name: \"foo.proto\" "
  2658. "dependency: \"forward2.proto\" "
  2659. "message_type {"
  2660. " name: \"Foo\""
  2661. " field { name:\"foo\" number:1 label:LABEL_OPTIONAL type_name:\"Bar\" }"
  2662. "}");
  2663. }
  2664. TEST_F(ValidationErrorTest,
  2665. FieldTypeDefinedInPrivateDependencyOfPublicDependency) {
  2666. // Test for public dependencies.
  2667. //
  2668. // // bar.proto
  2669. // message Bar{}
  2670. //
  2671. // // forward.proto
  2672. // import "bar.proto"
  2673. //
  2674. // // forward2.proto
  2675. // import public "forward.proto"
  2676. //
  2677. // // foo.proto
  2678. // import "forward2.proto"
  2679. // message Foo {
  2680. // optional Bar foo = 1; // Error, the "bar.proto" is not public imported
  2681. // // into "forward.proto", so will not be imported
  2682. // // into either "forward2.proto" or "foo.proto".
  2683. // }
  2684. //
  2685. BuildFile(
  2686. "name: \"bar.proto\" "
  2687. "message_type { name: \"Bar\" }");
  2688. BuildFile(
  2689. "name: \"forward.proto\""
  2690. "dependency: \"bar.proto\"");
  2691. BuildFile(
  2692. "name: \"forward2.proto\""
  2693. "dependency: \"forward.proto\" "
  2694. "public_dependency: 0");
  2695. BuildFileWithErrors(
  2696. "name: \"foo.proto\" "
  2697. "dependency: \"forward2.proto\" "
  2698. "message_type {"
  2699. " name: \"Foo\""
  2700. " field { name:\"foo\" number:1 label:LABEL_OPTIONAL type_name:\"Bar\" }"
  2701. "}",
  2702. "foo.proto: Foo.foo: TYPE: \"Bar\" seems to be defined in \"bar.proto\", "
  2703. "which is not imported by \"foo.proto\". To use it here, please add the "
  2704. "necessary import.\n");
  2705. }
  2706. TEST_F(ValidationErrorTest, SearchMostLocalFirst) {
  2707. // The following should produce an error that Bar.Baz is not defined:
  2708. // message Bar { message Baz {} }
  2709. // message Foo {
  2710. // message Bar {
  2711. // // Placing "message Baz{}" here, or removing Foo.Bar altogether,
  2712. // // would fix the error.
  2713. // }
  2714. // optional Bar.Baz baz = 1;
  2715. // }
  2716. // An one point the lookup code incorrectly did not produce an error in this
  2717. // case, because when looking for Bar.Baz, it would try "Foo.Bar.Baz" first,
  2718. // fail, and ten try "Bar.Baz" and succeed, even though "Bar" should actually
  2719. // refer to the inner Bar, not the outer one.
  2720. BuildFileWithErrors(
  2721. "name: \"foo.proto\" "
  2722. "message_type {"
  2723. " name: \"Bar\""
  2724. " nested_type { name: \"Baz\" }"
  2725. "}"
  2726. "message_type {"
  2727. " name: \"Foo\""
  2728. " nested_type { name: \"Bar\" }"
  2729. " field { name:\"baz\" number:1 label:LABEL_OPTIONAL"
  2730. " type_name:\"Bar.Baz\" }"
  2731. "}",
  2732. "foo.proto: Foo.baz: TYPE: \"Bar.Baz\" is not defined.\n");
  2733. }
  2734. TEST_F(ValidationErrorTest, SearchMostLocalFirst2) {
  2735. // This test would find the most local "Bar" first, and does, but
  2736. // proceeds to find the outer one because the inner one's not an
  2737. // aggregate.
  2738. BuildFile(
  2739. "name: \"foo.proto\" "
  2740. "message_type {"
  2741. " name: \"Bar\""
  2742. " nested_type { name: \"Baz\" }"
  2743. "}"
  2744. "message_type {"
  2745. " name: \"Foo\""
  2746. " field { name: \"Bar\" number:1 type:TYPE_BYTES } "
  2747. " field { name:\"baz\" number:2 label:LABEL_OPTIONAL"
  2748. " type_name:\"Bar.Baz\" }"
  2749. "}");
  2750. }
  2751. TEST_F(ValidationErrorTest, PackageOriginallyDeclaredInTransitiveDependent) {
  2752. // Imagine we have the following:
  2753. //
  2754. // foo.proto:
  2755. // package foo.bar;
  2756. // bar.proto:
  2757. // package foo.bar;
  2758. // import "foo.proto";
  2759. // message Bar {}
  2760. // baz.proto:
  2761. // package foo;
  2762. // import "bar.proto"
  2763. // message Baz { optional bar.Bar qux = 1; }
  2764. //
  2765. // When validating baz.proto, we will look up "bar.Bar". As part of this
  2766. // lookup, we first lookup "bar" then try to find "Bar" within it. "bar"
  2767. // should resolve to "foo.bar". Note, though, that "foo.bar" was originally
  2768. // defined in foo.proto, which is not a direct dependency of baz.proto. The
  2769. // implementation of FindSymbol() normally only returns symbols in direct
  2770. // dependencies, not indirect ones. This test insures that this does not
  2771. // prevent it from finding "foo.bar".
  2772. BuildFile(
  2773. "name: \"foo.proto\" "
  2774. "package: \"foo.bar\" ");
  2775. BuildFile(
  2776. "name: \"bar.proto\" "
  2777. "package: \"foo.bar\" "
  2778. "dependency: \"foo.proto\" "
  2779. "message_type { name: \"Bar\" }");
  2780. BuildFile(
  2781. "name: \"baz.proto\" "
  2782. "package: \"foo\" "
  2783. "dependency: \"bar.proto\" "
  2784. "message_type { "
  2785. " name: \"Baz\" "
  2786. " field { name:\"qux\" number:1 label:LABEL_OPTIONAL "
  2787. " type_name:\"bar.Bar\" }"
  2788. "}");
  2789. }
  2790. TEST_F(ValidationErrorTest, FieldTypeNotAType) {
  2791. BuildFileWithErrors(
  2792. "name: \"foo.proto\" "
  2793. "message_type {"
  2794. " name: \"Foo\""
  2795. " field { name:\"foo\" number:1 label:LABEL_OPTIONAL "
  2796. " type_name:\".Foo.bar\" }"
  2797. " field { name:\"bar\" number:2 label:LABEL_OPTIONAL type:TYPE_INT32 }"
  2798. "}",
  2799. "foo.proto: Foo.foo: TYPE: \".Foo.bar\" is not a type.\n");
  2800. }
  2801. TEST_F(ValidationErrorTest, RelativeFieldTypeNotAType) {
  2802. BuildFileWithErrors(
  2803. "name: \"foo.proto\" "
  2804. "message_type {"
  2805. " nested_type {"
  2806. " name: \"Bar\""
  2807. " field { name:\"Baz\" number:2 label:LABEL_OPTIONAL type:TYPE_INT32 }"
  2808. " }"
  2809. " name: \"Foo\""
  2810. " field { name:\"foo\" number:1 label:LABEL_OPTIONAL "
  2811. " type_name:\"Bar.Baz\" }"
  2812. "}",
  2813. "foo.proto: Foo.foo: TYPE: \"Bar.Baz\" is not a type.\n");
  2814. }
  2815. TEST_F(ValidationErrorTest, FieldTypeMayBeItsName) {
  2816. BuildFile(
  2817. "name: \"foo.proto\" "
  2818. "message_type {"
  2819. " name: \"Bar\""
  2820. "}"
  2821. "message_type {"
  2822. " name: \"Foo\""
  2823. " field { name:\"Bar\" number:1 label:LABEL_OPTIONAL type_name:\"Bar\" }"
  2824. "}");
  2825. }
  2826. TEST_F(ValidationErrorTest, EnumFieldTypeIsMessage) {
  2827. BuildFileWithErrors(
  2828. "name: \"foo.proto\" "
  2829. "message_type { name: \"Bar\" } "
  2830. "message_type {"
  2831. " name: \"Foo\""
  2832. " field { name:\"foo\" number:1 label:LABEL_OPTIONAL type:TYPE_ENUM"
  2833. " type_name:\"Bar\" }"
  2834. "}",
  2835. "foo.proto: Foo.foo: TYPE: \"Bar\" is not an enum type.\n");
  2836. }
  2837. TEST_F(ValidationErrorTest, MessageFieldTypeIsEnum) {
  2838. BuildFileWithErrors(
  2839. "name: \"foo.proto\" "
  2840. "enum_type { name: \"Bar\" value { name:\"DUMMY\" number:0 } } "
  2841. "message_type {"
  2842. " name: \"Foo\""
  2843. " field { name:\"foo\" number:1 label:LABEL_OPTIONAL type:TYPE_MESSAGE"
  2844. " type_name:\"Bar\" }"
  2845. "}",
  2846. "foo.proto: Foo.foo: TYPE: \"Bar\" is not a message type.\n");
  2847. }
  2848. TEST_F(ValidationErrorTest, BadEnumDefaultValue) {
  2849. BuildFileWithErrors(
  2850. "name: \"foo.proto\" "
  2851. "enum_type { name: \"Bar\" value { name:\"DUMMY\" number:0 } } "
  2852. "message_type {"
  2853. " name: \"Foo\""
  2854. " field { name:\"foo\" number:1 label:LABEL_OPTIONAL type_name:\"Bar\""
  2855. " default_value:\"NO_SUCH_VALUE\" }"
  2856. "}",
  2857. "foo.proto: Foo.foo: DEFAULT_VALUE: Enum type \"Bar\" has no value named "
  2858. "\"NO_SUCH_VALUE\".\n");
  2859. }
  2860. TEST_F(ValidationErrorTest, PrimitiveWithTypeName) {
  2861. BuildFileWithErrors(
  2862. "name: \"foo.proto\" "
  2863. "message_type {"
  2864. " name: \"Foo\""
  2865. " field { name:\"foo\" number:1 label:LABEL_OPTIONAL type:TYPE_INT32"
  2866. " type_name:\"Foo\" }"
  2867. "}",
  2868. "foo.proto: Foo.foo: TYPE: Field with primitive type has type_name.\n");
  2869. }
  2870. TEST_F(ValidationErrorTest, NonPrimitiveWithoutTypeName) {
  2871. BuildFileWithErrors(
  2872. "name: \"foo.proto\" "
  2873. "message_type {"
  2874. " name: \"Foo\""
  2875. " field { name:\"foo\" number:1 label:LABEL_OPTIONAL type:TYPE_MESSAGE }"
  2876. "}",
  2877. "foo.proto: Foo.foo: TYPE: Field with message or enum type missing "
  2878. "type_name.\n");
  2879. }
  2880. TEST_F(ValidationErrorTest, InputTypeNotDefined) {
  2881. BuildFileWithErrors(
  2882. "name: \"foo.proto\" "
  2883. "message_type { name: \"Foo\" } "
  2884. "service {"
  2885. " name: \"TestService\""
  2886. " method { name: \"A\" input_type: \"Bar\" output_type: \"Foo\" }"
  2887. "}",
  2888. "foo.proto: TestService.A: INPUT_TYPE: \"Bar\" is not defined.\n"
  2889. );
  2890. }
  2891. TEST_F(ValidationErrorTest, InputTypeNotAMessage) {
  2892. BuildFileWithErrors(
  2893. "name: \"foo.proto\" "
  2894. "message_type { name: \"Foo\" } "
  2895. "enum_type { name: \"Bar\" value { name:\"DUMMY\" number:0 } } "
  2896. "service {"
  2897. " name: \"TestService\""
  2898. " method { name: \"A\" input_type: \"Bar\" output_type: \"Foo\" }"
  2899. "}",
  2900. "foo.proto: TestService.A: INPUT_TYPE: \"Bar\" is not a message type.\n"
  2901. );
  2902. }
  2903. TEST_F(ValidationErrorTest, OutputTypeNotDefined) {
  2904. BuildFileWithErrors(
  2905. "name: \"foo.proto\" "
  2906. "message_type { name: \"Foo\" } "
  2907. "service {"
  2908. " name: \"TestService\""
  2909. " method { name: \"A\" input_type: \"Foo\" output_type: \"Bar\" }"
  2910. "}",
  2911. "foo.proto: TestService.A: OUTPUT_TYPE: \"Bar\" is not defined.\n"
  2912. );
  2913. }
  2914. TEST_F(ValidationErrorTest, OutputTypeNotAMessage) {
  2915. BuildFileWithErrors(
  2916. "name: \"foo.proto\" "
  2917. "message_type { name: \"Foo\" } "
  2918. "enum_type { name: \"Bar\" value { name:\"DUMMY\" number:0 } } "
  2919. "service {"
  2920. " name: \"TestService\""
  2921. " method { name: \"A\" input_type: \"Foo\" output_type: \"Bar\" }"
  2922. "}",
  2923. "foo.proto: TestService.A: OUTPUT_TYPE: \"Bar\" is not a message type.\n"
  2924. );
  2925. }
  2926. TEST_F(ValidationErrorTest, IllegalPackedField) {
  2927. BuildFileWithErrors(
  2928. "name: \"foo.proto\" "
  2929. "message_type {\n"
  2930. " name: \"Foo\""
  2931. " field { name:\"packed_string\" number:1 label:LABEL_REPEATED "
  2932. " type:TYPE_STRING "
  2933. " options { uninterpreted_option {"
  2934. " name { name_part: \"packed\" is_extension: false }"
  2935. " identifier_value: \"true\" }}}\n"
  2936. " field { name:\"packed_message\" number:3 label:LABEL_REPEATED "
  2937. " type_name: \"Foo\""
  2938. " options { uninterpreted_option {"
  2939. " name { name_part: \"packed\" is_extension: false }"
  2940. " identifier_value: \"true\" }}}\n"
  2941. " field { name:\"optional_int32\" number: 4 label: LABEL_OPTIONAL "
  2942. " type:TYPE_INT32 "
  2943. " options { uninterpreted_option {"
  2944. " name { name_part: \"packed\" is_extension: false }"
  2945. " identifier_value: \"true\" }}}\n"
  2946. "}",
  2947. "foo.proto: Foo.packed_string: TYPE: [packed = true] can only be "
  2948. "specified for repeated primitive fields.\n"
  2949. "foo.proto: Foo.packed_message: TYPE: [packed = true] can only be "
  2950. "specified for repeated primitive fields.\n"
  2951. "foo.proto: Foo.optional_int32: TYPE: [packed = true] can only be "
  2952. "specified for repeated primitive fields.\n"
  2953. );
  2954. }
  2955. TEST_F(ValidationErrorTest, OptionWrongType) {
  2956. BuildFileWithErrors(
  2957. "name: \"foo.proto\" "
  2958. "message_type { "
  2959. " name: \"TestMessage\" "
  2960. " field { name:\"foo\" number:1 label:LABEL_OPTIONAL type:TYPE_STRING "
  2961. " options { uninterpreted_option { name { name_part: \"ctype\" "
  2962. " is_extension: false }"
  2963. " positive_int_value: 1 }"
  2964. " }"
  2965. " }"
  2966. "}\n",
  2967. "foo.proto: TestMessage.foo: OPTION_VALUE: Value must be identifier for "
  2968. "enum-valued option \"google.protobuf.FieldOptions.ctype\".\n");
  2969. }
  2970. TEST_F(ValidationErrorTest, OptionExtendsAtomicType) {
  2971. BuildFileWithErrors(
  2972. "name: \"foo.proto\" "
  2973. "message_type { "
  2974. " name: \"TestMessage\" "
  2975. " field { name:\"foo\" number:1 label:LABEL_OPTIONAL type:TYPE_STRING "
  2976. " options { uninterpreted_option { name { name_part: \"ctype\" "
  2977. " is_extension: false }"
  2978. " name { name_part: \"foo\" "
  2979. " is_extension: true }"
  2980. " positive_int_value: 1 }"
  2981. " }"
  2982. " }"
  2983. "}\n",
  2984. "foo.proto: TestMessage.foo: OPTION_NAME: Option \"ctype\" is an "
  2985. "atomic type, not a message.\n");
  2986. }
  2987. TEST_F(ValidationErrorTest, DupOption) {
  2988. BuildFileWithErrors(
  2989. "name: \"foo.proto\" "
  2990. "message_type { "
  2991. " name: \"TestMessage\" "
  2992. " field { name:\"foo\" number:1 label:LABEL_OPTIONAL type:TYPE_UINT32 "
  2993. " options { uninterpreted_option { name { name_part: \"ctype\" "
  2994. " is_extension: false }"
  2995. " identifier_value: \"CORD\" }"
  2996. " uninterpreted_option { name { name_part: \"ctype\" "
  2997. " is_extension: false }"
  2998. " identifier_value: \"CORD\" }"
  2999. " }"
  3000. " }"
  3001. "}\n",
  3002. "foo.proto: TestMessage.foo: OPTION_NAME: Option \"ctype\" was "
  3003. "already set.\n");
  3004. }
  3005. TEST_F(ValidationErrorTest, InvalidOptionName) {
  3006. BuildFileWithErrors(
  3007. "name: \"foo.proto\" "
  3008. "message_type { "
  3009. " name: \"TestMessage\" "
  3010. " field { name:\"foo\" number:1 label:LABEL_OPTIONAL type:TYPE_BOOL "
  3011. " options { uninterpreted_option { "
  3012. " name { name_part: \"uninterpreted_option\" "
  3013. " is_extension: false }"
  3014. " positive_int_value: 1 "
  3015. " }"
  3016. " }"
  3017. " }"
  3018. "}\n",
  3019. "foo.proto: TestMessage.foo: OPTION_NAME: Option must not use "
  3020. "reserved name \"uninterpreted_option\".\n");
  3021. }
  3022. TEST_F(ValidationErrorTest, RepeatedOption) {
  3023. BuildDescriptorMessagesInTestPool();
  3024. BuildFileWithErrors(
  3025. "name: \"foo.proto\" "
  3026. "dependency: \"google/protobuf/descriptor.proto\" "
  3027. "extension { name: \"foo\" number: 7672757 label: LABEL_REPEATED "
  3028. " type: TYPE_FLOAT extendee: \"google.protobuf.FileOptions\" }"
  3029. "options { uninterpreted_option { name { name_part: \"foo\" "
  3030. " is_extension: true } "
  3031. " double_value: 1.2 } }",
  3032. "foo.proto: foo.proto: OPTION_NAME: Option field \"(foo)\" is repeated. "
  3033. "Repeated options are not supported.\n");
  3034. }
  3035. TEST_F(ValidationErrorTest, CustomOptionConflictingFieldNumber) {
  3036. BuildDescriptorMessagesInTestPool();
  3037. BuildFileWithErrors(
  3038. "name: \"foo.proto\" "
  3039. "dependency: \"google/protobuf/descriptor.proto\" "
  3040. "extension { name: \"foo1\" number: 7672757 label: LABEL_OPTIONAL "
  3041. " type: TYPE_INT32 extendee: \"google.protobuf.FieldOptions\" }"
  3042. "extension { name: \"foo2\" number: 7672757 label: LABEL_OPTIONAL "
  3043. " type: TYPE_INT32 extendee: \"google.protobuf.FieldOptions\" }",
  3044. "foo.proto: foo2: NUMBER: Extension number 7672757 has already been used "
  3045. "in \"google.protobuf.FieldOptions\" by extension \"foo1\".\n");
  3046. }
  3047. TEST_F(ValidationErrorTest, Int32OptionValueOutOfPositiveRange) {
  3048. BuildDescriptorMessagesInTestPool();
  3049. BuildFileWithErrors(
  3050. "name: \"foo.proto\" "
  3051. "dependency: \"google/protobuf/descriptor.proto\" "
  3052. "extension { name: \"foo\" number: 7672757 label: LABEL_OPTIONAL "
  3053. " type: TYPE_INT32 extendee: \"google.protobuf.FileOptions\" }"
  3054. "options { uninterpreted_option { name { name_part: \"foo\" "
  3055. " is_extension: true } "
  3056. " positive_int_value: 0x80000000 } "
  3057. "}",
  3058. "foo.proto: foo.proto: OPTION_VALUE: Value out of range "
  3059. "for int32 option \"foo\".\n");
  3060. }
  3061. TEST_F(ValidationErrorTest, Int32OptionValueOutOfNegativeRange) {
  3062. BuildDescriptorMessagesInTestPool();
  3063. BuildFileWithErrors(
  3064. "name: \"foo.proto\" "
  3065. "dependency: \"google/protobuf/descriptor.proto\" "
  3066. "extension { name: \"foo\" number: 7672757 label: LABEL_OPTIONAL "
  3067. " type: TYPE_INT32 extendee: \"google.protobuf.FileOptions\" }"
  3068. "options { uninterpreted_option { name { name_part: \"foo\" "
  3069. " is_extension: true } "
  3070. " negative_int_value: -0x80000001 } "
  3071. "}",
  3072. "foo.proto: foo.proto: OPTION_VALUE: Value out of range "
  3073. "for int32 option \"foo\".\n");
  3074. }
  3075. TEST_F(ValidationErrorTest, Int32OptionValueIsNotPositiveInt) {
  3076. BuildDescriptorMessagesInTestPool();
  3077. BuildFileWithErrors(
  3078. "name: \"foo.proto\" "
  3079. "dependency: \"google/protobuf/descriptor.proto\" "
  3080. "extension { name: \"foo\" number: 7672757 label: LABEL_OPTIONAL "
  3081. " type: TYPE_INT32 extendee: \"google.protobuf.FileOptions\" }"
  3082. "options { uninterpreted_option { name { name_part: \"foo\" "
  3083. " is_extension: true } "
  3084. " string_value: \"5\" } }",
  3085. "foo.proto: foo.proto: OPTION_VALUE: Value must be integer "
  3086. "for int32 option \"foo\".\n");
  3087. }
  3088. TEST_F(ValidationErrorTest, Int64OptionValueOutOfRange) {
  3089. BuildDescriptorMessagesInTestPool();
  3090. BuildFileWithErrors(
  3091. "name: \"foo.proto\" "
  3092. "dependency: \"google/protobuf/descriptor.proto\" "
  3093. "extension { name: \"foo\" number: 7672757 label: LABEL_OPTIONAL "
  3094. " type: TYPE_INT64 extendee: \"google.protobuf.FileOptions\" }"
  3095. "options { uninterpreted_option { name { name_part: \"foo\" "
  3096. " is_extension: true } "
  3097. " positive_int_value: 0x8000000000000000 } "
  3098. "}",
  3099. "foo.proto: foo.proto: OPTION_VALUE: Value out of range "
  3100. "for int64 option \"foo\".\n");
  3101. }
  3102. TEST_F(ValidationErrorTest, Int64OptionValueIsNotPositiveInt) {
  3103. BuildDescriptorMessagesInTestPool();
  3104. BuildFileWithErrors(
  3105. "name: \"foo.proto\" "
  3106. "dependency: \"google/protobuf/descriptor.proto\" "
  3107. "extension { name: \"foo\" number: 7672757 label: LABEL_OPTIONAL "
  3108. " type: TYPE_INT64 extendee: \"google.protobuf.FileOptions\" }"
  3109. "options { uninterpreted_option { name { name_part: \"foo\" "
  3110. " is_extension: true } "
  3111. " identifier_value: \"5\" } }",
  3112. "foo.proto: foo.proto: OPTION_VALUE: Value must be integer "
  3113. "for int64 option \"foo\".\n");
  3114. }
  3115. TEST_F(ValidationErrorTest, UInt32OptionValueOutOfRange) {
  3116. BuildDescriptorMessagesInTestPool();
  3117. BuildFileWithErrors(
  3118. "name: \"foo.proto\" "
  3119. "dependency: \"google/protobuf/descriptor.proto\" "
  3120. "extension { name: \"foo\" number: 7672757 label: LABEL_OPTIONAL "
  3121. " type: TYPE_UINT32 extendee: \"google.protobuf.FileOptions\" }"
  3122. "options { uninterpreted_option { name { name_part: \"foo\" "
  3123. " is_extension: true } "
  3124. " positive_int_value: 0x100000000 } }",
  3125. "foo.proto: foo.proto: OPTION_VALUE: Value out of range "
  3126. "for uint32 option \"foo\".\n");
  3127. }
  3128. TEST_F(ValidationErrorTest, UInt32OptionValueIsNotPositiveInt) {
  3129. BuildDescriptorMessagesInTestPool();
  3130. BuildFileWithErrors(
  3131. "name: \"foo.proto\" "
  3132. "dependency: \"google/protobuf/descriptor.proto\" "
  3133. "extension { name: \"foo\" number: 7672757 label: LABEL_OPTIONAL "
  3134. " type: TYPE_UINT32 extendee: \"google.protobuf.FileOptions\" }"
  3135. "options { uninterpreted_option { name { name_part: \"foo\" "
  3136. " is_extension: true } "
  3137. " double_value: -5.6 } }",
  3138. "foo.proto: foo.proto: OPTION_VALUE: Value must be non-negative integer "
  3139. "for uint32 option \"foo\".\n");
  3140. }
  3141. TEST_F(ValidationErrorTest, UInt64OptionValueIsNotPositiveInt) {
  3142. BuildDescriptorMessagesInTestPool();
  3143. BuildFileWithErrors(
  3144. "name: \"foo.proto\" "
  3145. "dependency: \"google/protobuf/descriptor.proto\" "
  3146. "extension { name: \"foo\" number: 7672757 label: LABEL_OPTIONAL "
  3147. " type: TYPE_UINT64 extendee: \"google.protobuf.FileOptions\" }"
  3148. "options { uninterpreted_option { name { name_part: \"foo\" "
  3149. " is_extension: true } "
  3150. " negative_int_value: -5 } }",
  3151. "foo.proto: foo.proto: OPTION_VALUE: Value must be non-negative integer "
  3152. "for uint64 option \"foo\".\n");
  3153. }
  3154. TEST_F(ValidationErrorTest, FloatOptionValueIsNotNumber) {
  3155. BuildDescriptorMessagesInTestPool();
  3156. BuildFileWithErrors(
  3157. "name: \"foo.proto\" "
  3158. "dependency: \"google/protobuf/descriptor.proto\" "
  3159. "extension { name: \"foo\" number: 7672757 label: LABEL_OPTIONAL "
  3160. " type: TYPE_FLOAT extendee: \"google.protobuf.FileOptions\" }"
  3161. "options { uninterpreted_option { name { name_part: \"foo\" "
  3162. " is_extension: true } "
  3163. " string_value: \"bar\" } }",
  3164. "foo.proto: foo.proto: OPTION_VALUE: Value must be number "
  3165. "for float option \"foo\".\n");
  3166. }
  3167. TEST_F(ValidationErrorTest, DoubleOptionValueIsNotNumber) {
  3168. BuildDescriptorMessagesInTestPool();
  3169. BuildFileWithErrors(
  3170. "name: \"foo.proto\" "
  3171. "dependency: \"google/protobuf/descriptor.proto\" "
  3172. "extension { name: \"foo\" number: 7672757 label: LABEL_OPTIONAL "
  3173. " type: TYPE_DOUBLE extendee: \"google.protobuf.FileOptions\" }"
  3174. "options { uninterpreted_option { name { name_part: \"foo\" "
  3175. " is_extension: true } "
  3176. " string_value: \"bar\" } }",
  3177. "foo.proto: foo.proto: OPTION_VALUE: Value must be number "
  3178. "for double option \"foo\".\n");
  3179. }
  3180. TEST_F(ValidationErrorTest, BoolOptionValueIsNotTrueOrFalse) {
  3181. BuildDescriptorMessagesInTestPool();
  3182. BuildFileWithErrors(
  3183. "name: \"foo.proto\" "
  3184. "dependency: \"google/protobuf/descriptor.proto\" "
  3185. "extension { name: \"foo\" number: 7672757 label: LABEL_OPTIONAL "
  3186. " type: TYPE_BOOL extendee: \"google.protobuf.FileOptions\" }"
  3187. "options { uninterpreted_option { name { name_part: \"foo\" "
  3188. " is_extension: true } "
  3189. " identifier_value: \"bar\" } }",
  3190. "foo.proto: foo.proto: OPTION_VALUE: Value must be \"true\" or \"false\" "
  3191. "for boolean option \"foo\".\n");
  3192. }
  3193. TEST_F(ValidationErrorTest, EnumOptionValueIsNotIdentifier) {
  3194. BuildDescriptorMessagesInTestPool();
  3195. BuildFileWithErrors(
  3196. "name: \"foo.proto\" "
  3197. "dependency: \"google/protobuf/descriptor.proto\" "
  3198. "enum_type { name: \"FooEnum\" value { name: \"BAR\" number: 1 } "
  3199. " value { name: \"BAZ\" number: 2 } }"
  3200. "extension { name: \"foo\" number: 7672757 label: LABEL_OPTIONAL "
  3201. " type: TYPE_ENUM type_name: \"FooEnum\" "
  3202. " extendee: \"google.protobuf.FileOptions\" }"
  3203. "options { uninterpreted_option { name { name_part: \"foo\" "
  3204. " is_extension: true } "
  3205. " string_value: \"QUUX\" } }",
  3206. "foo.proto: foo.proto: OPTION_VALUE: Value must be identifier for "
  3207. "enum-valued option \"foo\".\n");
  3208. }
  3209. TEST_F(ValidationErrorTest, EnumOptionValueIsNotEnumValueName) {
  3210. BuildDescriptorMessagesInTestPool();
  3211. BuildFileWithErrors(
  3212. "name: \"foo.proto\" "
  3213. "dependency: \"google/protobuf/descriptor.proto\" "
  3214. "enum_type { name: \"FooEnum\" value { name: \"BAR\" number: 1 } "
  3215. " value { name: \"BAZ\" number: 2 } }"
  3216. "extension { name: \"foo\" number: 7672757 label: LABEL_OPTIONAL "
  3217. " type: TYPE_ENUM type_name: \"FooEnum\" "
  3218. " extendee: \"google.protobuf.FileOptions\" }"
  3219. "options { uninterpreted_option { name { name_part: \"foo\" "
  3220. " is_extension: true } "
  3221. " identifier_value: \"QUUX\" } }",
  3222. "foo.proto: foo.proto: OPTION_VALUE: Enum type \"FooEnum\" has no value "
  3223. "named \"QUUX\" for option \"foo\".\n");
  3224. }
  3225. TEST_F(ValidationErrorTest, EnumOptionValueIsSiblingEnumValueName) {
  3226. BuildDescriptorMessagesInTestPool();
  3227. BuildFileWithErrors(
  3228. "name: \"foo.proto\" "
  3229. "dependency: \"google/protobuf/descriptor.proto\" "
  3230. "enum_type { name: \"FooEnum1\" value { name: \"BAR\" number: 1 } "
  3231. " value { name: \"BAZ\" number: 2 } }"
  3232. "enum_type { name: \"FooEnum2\" value { name: \"QUX\" number: 1 } "
  3233. " value { name: \"QUUX\" number: 2 } }"
  3234. "extension { name: \"foo\" number: 7672757 label: LABEL_OPTIONAL "
  3235. " type: TYPE_ENUM type_name: \"FooEnum1\" "
  3236. " extendee: \"google.protobuf.FileOptions\" }"
  3237. "options { uninterpreted_option { name { name_part: \"foo\" "
  3238. " is_extension: true } "
  3239. " identifier_value: \"QUUX\" } }",
  3240. "foo.proto: foo.proto: OPTION_VALUE: Enum type \"FooEnum1\" has no value "
  3241. "named \"QUUX\" for option \"foo\". This appears to be a value from a "
  3242. "sibling type.\n");
  3243. }
  3244. TEST_F(ValidationErrorTest, StringOptionValueIsNotString) {
  3245. BuildDescriptorMessagesInTestPool();
  3246. BuildFileWithErrors(
  3247. "name: \"foo.proto\" "
  3248. "dependency: \"google/protobuf/descriptor.proto\" "
  3249. "extension { name: \"foo\" number: 7672757 label: LABEL_OPTIONAL "
  3250. " type: TYPE_STRING extendee: \"google.protobuf.FileOptions\" }"
  3251. "options { uninterpreted_option { name { name_part: \"foo\" "
  3252. " is_extension: true } "
  3253. " identifier_value: \"QUUX\" } }",
  3254. "foo.proto: foo.proto: OPTION_VALUE: Value must be quoted string for "
  3255. "string option \"foo\".\n");
  3256. }
  3257. // Helper function for tests that check for aggregate value parsing
  3258. // errors. The "value" argument is embedded inside the
  3259. // "uninterpreted_option" portion of the result.
  3260. static string EmbedAggregateValue(const char* value) {
  3261. return strings::Substitute(
  3262. "name: \"foo.proto\" "
  3263. "dependency: \"google/protobuf/descriptor.proto\" "
  3264. "message_type { name: \"Foo\" } "
  3265. "extension { name: \"foo\" number: 7672757 label: LABEL_OPTIONAL "
  3266. " type: TYPE_MESSAGE type_name: \"Foo\" "
  3267. " extendee: \"google.protobuf.FileOptions\" }"
  3268. "options { uninterpreted_option { name { name_part: \"foo\" "
  3269. " is_extension: true } "
  3270. " $0 } }",
  3271. value);
  3272. }
  3273. TEST_F(ValidationErrorTest, AggregateValueNotFound) {
  3274. BuildDescriptorMessagesInTestPool();
  3275. BuildFileWithErrors(
  3276. EmbedAggregateValue("string_value: \"\""),
  3277. "foo.proto: foo.proto: OPTION_VALUE: Option \"foo\" is a message. "
  3278. "To set the entire message, use syntax like "
  3279. "\"foo = { <proto text format> }\". To set fields within it, use "
  3280. "syntax like \"foo.foo = value\".\n");
  3281. }
  3282. TEST_F(ValidationErrorTest, AggregateValueParseError) {
  3283. BuildDescriptorMessagesInTestPool();
  3284. BuildFileWithErrors(
  3285. EmbedAggregateValue("aggregate_value: \"1+2\""),
  3286. "foo.proto: foo.proto: OPTION_VALUE: Error while parsing option "
  3287. "value for \"foo\": Expected identifier.\n");
  3288. }
  3289. TEST_F(ValidationErrorTest, AggregateValueUnknownFields) {
  3290. BuildDescriptorMessagesInTestPool();
  3291. BuildFileWithErrors(
  3292. EmbedAggregateValue("aggregate_value: \"x:100\""),
  3293. "foo.proto: foo.proto: OPTION_VALUE: Error while parsing option "
  3294. "value for \"foo\": Message type \"Foo\" has no field named \"x\".\n");
  3295. }
  3296. TEST_F(ValidationErrorTest, NotLiteImportsLite) {
  3297. BuildFile(
  3298. "name: \"bar.proto\" "
  3299. "options { optimize_for: LITE_RUNTIME } ");
  3300. BuildFileWithErrors(
  3301. "name: \"foo.proto\" "
  3302. "dependency: \"bar.proto\" ",
  3303. "foo.proto: foo.proto: OTHER: Files that do not use optimize_for = "
  3304. "LITE_RUNTIME cannot import files which do use this option. This file "
  3305. "is not lite, but it imports \"bar.proto\" which is.\n");
  3306. }
  3307. TEST_F(ValidationErrorTest, LiteExtendsNotLite) {
  3308. BuildFile(
  3309. "name: \"bar.proto\" "
  3310. "message_type: {"
  3311. " name: \"Bar\""
  3312. " extension_range { start: 1 end: 1000 }"
  3313. "}");
  3314. BuildFileWithErrors(
  3315. "name: \"foo.proto\" "
  3316. "dependency: \"bar.proto\" "
  3317. "options { optimize_for: LITE_RUNTIME } "
  3318. "extension { name: \"ext\" number: 123 label: LABEL_OPTIONAL "
  3319. " type: TYPE_INT32 extendee: \"Bar\" }",
  3320. "foo.proto: ext: EXTENDEE: Extensions to non-lite types can only be "
  3321. "declared in non-lite files. Note that you cannot extend a non-lite "
  3322. "type to contain a lite type, but the reverse is allowed.\n");
  3323. }
  3324. TEST_F(ValidationErrorTest, NoLiteServices) {
  3325. BuildFileWithErrors(
  3326. "name: \"foo.proto\" "
  3327. "options {"
  3328. " optimize_for: LITE_RUNTIME"
  3329. " cc_generic_services: true"
  3330. " java_generic_services: true"
  3331. "} "
  3332. "service { name: \"Foo\" }",
  3333. "foo.proto: Foo: NAME: Files with optimize_for = LITE_RUNTIME cannot "
  3334. "define services unless you set both options cc_generic_services and "
  3335. "java_generic_sevices to false.\n");
  3336. BuildFile(
  3337. "name: \"bar.proto\" "
  3338. "options {"
  3339. " optimize_for: LITE_RUNTIME"
  3340. " cc_generic_services: false"
  3341. " java_generic_services: false"
  3342. "} "
  3343. "service { name: \"Bar\" }");
  3344. }
  3345. TEST_F(ValidationErrorTest, RollbackAfterError) {
  3346. // Build a file which contains every kind of construct but references an
  3347. // undefined type. All these constructs will be added to the symbol table
  3348. // before the undefined type error is noticed. The DescriptorPool will then
  3349. // have to roll everything back.
  3350. BuildFileWithErrors(
  3351. "name: \"foo.proto\" "
  3352. "message_type {"
  3353. " name: \"TestMessage\""
  3354. " field { name:\"foo\" label:LABEL_OPTIONAL type:TYPE_INT32 number:1 }"
  3355. "} "
  3356. "enum_type {"
  3357. " name: \"TestEnum\""
  3358. " value { name:\"BAR\" number:1 }"
  3359. "} "
  3360. "service {"
  3361. " name: \"TestService\""
  3362. " method {"
  3363. " name: \"Baz\""
  3364. " input_type: \"NoSuchType\"" // error
  3365. " output_type: \"TestMessage\""
  3366. " }"
  3367. "}",
  3368. "foo.proto: TestService.Baz: INPUT_TYPE: \"NoSuchType\" is not defined.\n"
  3369. );
  3370. // Make sure that if we build the same file again with the error fixed,
  3371. // it works. If the above rollback was incomplete, then some symbols will
  3372. // be left defined, and this second attempt will fail since it tries to
  3373. // re-define the same symbols.
  3374. BuildFile(
  3375. "name: \"foo.proto\" "
  3376. "message_type {"
  3377. " name: \"TestMessage\""
  3378. " field { name:\"foo\" label:LABEL_OPTIONAL type:TYPE_INT32 number:1 }"
  3379. "} "
  3380. "enum_type {"
  3381. " name: \"TestEnum\""
  3382. " value { name:\"BAR\" number:1 }"
  3383. "} "
  3384. "service {"
  3385. " name: \"TestService\""
  3386. " method { name:\"Baz\""
  3387. " input_type:\"TestMessage\""
  3388. " output_type:\"TestMessage\" }"
  3389. "}");
  3390. }
  3391. TEST_F(ValidationErrorTest, ErrorsReportedToLogError) {
  3392. // Test that errors are reported to GOOGLE_LOG(ERROR) if no error collector is
  3393. // provided.
  3394. FileDescriptorProto file_proto;
  3395. ASSERT_TRUE(TextFormat::ParseFromString(
  3396. "name: \"foo.proto\" "
  3397. "message_type { name: \"Foo\" } "
  3398. "message_type { name: \"Foo\" } ",
  3399. &file_proto));
  3400. vector<string> errors;
  3401. {
  3402. ScopedMemoryLog log;
  3403. EXPECT_TRUE(pool_.BuildFile(file_proto) == NULL);
  3404. errors = log.GetMessages(ERROR);
  3405. }
  3406. ASSERT_EQ(2, errors.size());
  3407. EXPECT_EQ("Invalid proto descriptor for file \"foo.proto\":", errors[0]);
  3408. EXPECT_EQ(" Foo: \"Foo\" is already defined.", errors[1]);
  3409. }
  3410. TEST_F(ValidationErrorTest, DisallowEnumAlias) {
  3411. BuildFileWithErrors(
  3412. "name: \"foo.proto\" "
  3413. "enum_type {"
  3414. " name: \"Bar\""
  3415. " value { name:\"ENUM_A\" number:0 }"
  3416. " value { name:\"ENUM_B\" number:0 }"
  3417. " options { allow_alias: false }"
  3418. "}",
  3419. "foo.proto: Bar: NUMBER: "
  3420. "\"ENUM_B\" uses the same enum value as \"ENUM_A\". "
  3421. "If this is intended, set 'option allow_alias = true;' to the enum "
  3422. "definition.\n");
  3423. }
  3424. // ===================================================================
  3425. // DescriptorDatabase
  3426. static void AddToDatabase(SimpleDescriptorDatabase* database,
  3427. const char* file_text) {
  3428. FileDescriptorProto file_proto;
  3429. EXPECT_TRUE(TextFormat::ParseFromString(file_text, &file_proto));
  3430. database->Add(file_proto);
  3431. }
  3432. class DatabaseBackedPoolTest : public testing::Test {
  3433. protected:
  3434. DatabaseBackedPoolTest() {}
  3435. SimpleDescriptorDatabase database_;
  3436. virtual void SetUp() {
  3437. AddToDatabase(&database_,
  3438. "name: 'foo.proto' "
  3439. "message_type { name:'Foo' extension_range { start: 1 end: 100 } } "
  3440. "enum_type { name:'TestEnum' value { name:'DUMMY' number:0 } } "
  3441. "service { name:'TestService' } ");
  3442. AddToDatabase(&database_,
  3443. "name: 'bar.proto' "
  3444. "dependency: 'foo.proto' "
  3445. "message_type { name:'Bar' } "
  3446. "extension { name:'foo_ext' extendee: '.Foo' number:5 "
  3447. " label:LABEL_OPTIONAL type:TYPE_INT32 } ");
  3448. // Baz has an undeclared dependency on Foo.
  3449. AddToDatabase(&database_,
  3450. "name: 'baz.proto' "
  3451. "message_type { "
  3452. " name:'Baz' "
  3453. " field { name:'foo' number:1 label:LABEL_OPTIONAL type_name:'Foo' } "
  3454. "}");
  3455. }
  3456. // We can't inject a file containing errors into a DescriptorPool, so we
  3457. // need an actual mock DescriptorDatabase to test errors.
  3458. class ErrorDescriptorDatabase : public DescriptorDatabase {
  3459. public:
  3460. ErrorDescriptorDatabase() {}
  3461. ~ErrorDescriptorDatabase() {}
  3462. // implements DescriptorDatabase ---------------------------------
  3463. bool FindFileByName(const string& filename,
  3464. FileDescriptorProto* output) {
  3465. // error.proto and error2.proto cyclically import each other.
  3466. if (filename == "error.proto") {
  3467. output->Clear();
  3468. output->set_name("error.proto");
  3469. output->add_dependency("error2.proto");
  3470. return true;
  3471. } else if (filename == "error2.proto") {
  3472. output->Clear();
  3473. output->set_name("error2.proto");
  3474. output->add_dependency("error.proto");
  3475. return true;
  3476. } else {
  3477. return false;
  3478. }
  3479. }
  3480. bool FindFileContainingSymbol(const string& symbol_name,
  3481. FileDescriptorProto* output) {
  3482. return false;
  3483. }
  3484. bool FindFileContainingExtension(const string& containing_type,
  3485. int field_number,
  3486. FileDescriptorProto* output) {
  3487. return false;
  3488. }
  3489. };
  3490. // A DescriptorDatabase that counts how many times each method has been
  3491. // called and forwards to some other DescriptorDatabase.
  3492. class CallCountingDatabase : public DescriptorDatabase {
  3493. public:
  3494. CallCountingDatabase(DescriptorDatabase* wrapped_db)
  3495. : wrapped_db_(wrapped_db) {
  3496. Clear();
  3497. }
  3498. ~CallCountingDatabase() {}
  3499. DescriptorDatabase* wrapped_db_;
  3500. int call_count_;
  3501. void Clear() {
  3502. call_count_ = 0;
  3503. }
  3504. // implements DescriptorDatabase ---------------------------------
  3505. bool FindFileByName(const string& filename,
  3506. FileDescriptorProto* output) {
  3507. ++call_count_;
  3508. return wrapped_db_->FindFileByName(filename, output);
  3509. }
  3510. bool FindFileContainingSymbol(const string& symbol_name,
  3511. FileDescriptorProto* output) {
  3512. ++call_count_;
  3513. return wrapped_db_->FindFileContainingSymbol(symbol_name, output);
  3514. }
  3515. bool FindFileContainingExtension(const string& containing_type,
  3516. int field_number,
  3517. FileDescriptorProto* output) {
  3518. ++call_count_;
  3519. return wrapped_db_->FindFileContainingExtension(
  3520. containing_type, field_number, output);
  3521. }
  3522. };
  3523. // A DescriptorDatabase which falsely always returns foo.proto when searching
  3524. // for any symbol or extension number. This shouldn't cause the
  3525. // DescriptorPool to reload foo.proto if it is already loaded.
  3526. class FalsePositiveDatabase : public DescriptorDatabase {
  3527. public:
  3528. FalsePositiveDatabase(DescriptorDatabase* wrapped_db)
  3529. : wrapped_db_(wrapped_db) {}
  3530. ~FalsePositiveDatabase() {}
  3531. DescriptorDatabase* wrapped_db_;
  3532. // implements DescriptorDatabase ---------------------------------
  3533. bool FindFileByName(const string& filename,
  3534. FileDescriptorProto* output) {
  3535. return wrapped_db_->FindFileByName(filename, output);
  3536. }
  3537. bool FindFileContainingSymbol(const string& symbol_name,
  3538. FileDescriptorProto* output) {
  3539. return FindFileByName("foo.proto", output);
  3540. }
  3541. bool FindFileContainingExtension(const string& containing_type,
  3542. int field_number,
  3543. FileDescriptorProto* output) {
  3544. return FindFileByName("foo.proto", output);
  3545. }
  3546. };
  3547. };
  3548. TEST_F(DatabaseBackedPoolTest, FindFileByName) {
  3549. DescriptorPool pool(&database_);
  3550. const FileDescriptor* foo = pool.FindFileByName("foo.proto");
  3551. ASSERT_TRUE(foo != NULL);
  3552. EXPECT_EQ("foo.proto", foo->name());
  3553. ASSERT_EQ(1, foo->message_type_count());
  3554. EXPECT_EQ("Foo", foo->message_type(0)->name());
  3555. EXPECT_EQ(foo, pool.FindFileByName("foo.proto"));
  3556. EXPECT_TRUE(pool.FindFileByName("no_such_file.proto") == NULL);
  3557. }
  3558. TEST_F(DatabaseBackedPoolTest, FindDependencyBeforeDependent) {
  3559. DescriptorPool pool(&database_);
  3560. const FileDescriptor* foo = pool.FindFileByName("foo.proto");
  3561. ASSERT_TRUE(foo != NULL);
  3562. EXPECT_EQ("foo.proto", foo->name());
  3563. ASSERT_EQ(1, foo->message_type_count());
  3564. EXPECT_EQ("Foo", foo->message_type(0)->name());
  3565. const FileDescriptor* bar = pool.FindFileByName("bar.proto");
  3566. ASSERT_TRUE(bar != NULL);
  3567. EXPECT_EQ("bar.proto", bar->name());
  3568. ASSERT_EQ(1, bar->message_type_count());
  3569. EXPECT_EQ("Bar", bar->message_type(0)->name());
  3570. ASSERT_EQ(1, bar->dependency_count());
  3571. EXPECT_EQ(foo, bar->dependency(0));
  3572. }
  3573. TEST_F(DatabaseBackedPoolTest, FindDependentBeforeDependency) {
  3574. DescriptorPool pool(&database_);
  3575. const FileDescriptor* bar = pool.FindFileByName("bar.proto");
  3576. ASSERT_TRUE(bar != NULL);
  3577. EXPECT_EQ("bar.proto", bar->name());
  3578. ASSERT_EQ(1, bar->message_type_count());
  3579. ASSERT_EQ("Bar", bar->message_type(0)->name());
  3580. const FileDescriptor* foo = pool.FindFileByName("foo.proto");
  3581. ASSERT_TRUE(foo != NULL);
  3582. EXPECT_EQ("foo.proto", foo->name());
  3583. ASSERT_EQ(1, foo->message_type_count());
  3584. ASSERT_EQ("Foo", foo->message_type(0)->name());
  3585. ASSERT_EQ(1, bar->dependency_count());
  3586. EXPECT_EQ(foo, bar->dependency(0));
  3587. }
  3588. TEST_F(DatabaseBackedPoolTest, FindFileContainingSymbol) {
  3589. DescriptorPool pool(&database_);
  3590. const FileDescriptor* file = pool.FindFileContainingSymbol("Foo");
  3591. ASSERT_TRUE(file != NULL);
  3592. EXPECT_EQ("foo.proto", file->name());
  3593. EXPECT_EQ(file, pool.FindFileByName("foo.proto"));
  3594. EXPECT_TRUE(pool.FindFileContainingSymbol("NoSuchSymbol") == NULL);
  3595. }
  3596. TEST_F(DatabaseBackedPoolTest, FindMessageTypeByName) {
  3597. DescriptorPool pool(&database_);
  3598. const Descriptor* type = pool.FindMessageTypeByName("Foo");
  3599. ASSERT_TRUE(type != NULL);
  3600. EXPECT_EQ("Foo", type->name());
  3601. EXPECT_EQ(type->file(), pool.FindFileByName("foo.proto"));
  3602. EXPECT_TRUE(pool.FindMessageTypeByName("NoSuchType") == NULL);
  3603. }
  3604. TEST_F(DatabaseBackedPoolTest, FindExtensionByNumber) {
  3605. DescriptorPool pool(&database_);
  3606. const Descriptor* foo = pool.FindMessageTypeByName("Foo");
  3607. ASSERT_TRUE(foo != NULL);
  3608. const FieldDescriptor* extension = pool.FindExtensionByNumber(foo, 5);
  3609. ASSERT_TRUE(extension != NULL);
  3610. EXPECT_EQ("foo_ext", extension->name());
  3611. EXPECT_EQ(extension->file(), pool.FindFileByName("bar.proto"));
  3612. EXPECT_TRUE(pool.FindExtensionByNumber(foo, 12) == NULL);
  3613. }
  3614. TEST_F(DatabaseBackedPoolTest, FindAllExtensions) {
  3615. DescriptorPool pool(&database_);
  3616. const Descriptor* foo = pool.FindMessageTypeByName("Foo");
  3617. for (int i = 0; i < 2; ++i) {
  3618. // Repeat the lookup twice, to check that we get consistent
  3619. // results despite the fallback database lookup mutating the pool.
  3620. vector<const FieldDescriptor*> extensions;
  3621. pool.FindAllExtensions(foo, &extensions);
  3622. ASSERT_EQ(1, extensions.size());
  3623. EXPECT_EQ(5, extensions[0]->number());
  3624. }
  3625. }
  3626. TEST_F(DatabaseBackedPoolTest, ErrorWithoutErrorCollector) {
  3627. ErrorDescriptorDatabase error_database;
  3628. DescriptorPool pool(&error_database);
  3629. vector<string> errors;
  3630. {
  3631. ScopedMemoryLog log;
  3632. EXPECT_TRUE(pool.FindFileByName("error.proto") == NULL);
  3633. errors = log.GetMessages(ERROR);
  3634. }
  3635. EXPECT_FALSE(errors.empty());
  3636. }
  3637. TEST_F(DatabaseBackedPoolTest, ErrorWithErrorCollector) {
  3638. ErrorDescriptorDatabase error_database;
  3639. MockErrorCollector error_collector;
  3640. DescriptorPool pool(&error_database, &error_collector);
  3641. EXPECT_TRUE(pool.FindFileByName("error.proto") == NULL);
  3642. EXPECT_EQ(
  3643. "error.proto: error.proto: OTHER: File recursively imports itself: "
  3644. "error.proto -> error2.proto -> error.proto\n"
  3645. "error2.proto: error2.proto: OTHER: Import \"error.proto\" was not "
  3646. "found or had errors.\n"
  3647. "error.proto: error.proto: OTHER: Import \"error2.proto\" was not "
  3648. "found or had errors.\n",
  3649. error_collector.text_);
  3650. }
  3651. TEST_F(DatabaseBackedPoolTest, UndeclaredDependencyOnUnbuiltType) {
  3652. // Check that we find and report undeclared dependencies on types that exist
  3653. // in the descriptor database but that have not not been built yet.
  3654. MockErrorCollector error_collector;
  3655. DescriptorPool pool(&database_, &error_collector);
  3656. EXPECT_TRUE(pool.FindMessageTypeByName("Baz") == NULL);
  3657. EXPECT_EQ(
  3658. "baz.proto: Baz.foo: TYPE: \"Foo\" seems to be defined in \"foo.proto\", "
  3659. "which is not imported by \"baz.proto\". To use it here, please add "
  3660. "the necessary import.\n",
  3661. error_collector.text_);
  3662. }
  3663. TEST_F(DatabaseBackedPoolTest, RollbackAfterError) {
  3664. // Make sure that all traces of bad types are removed from the pool. This used
  3665. // to be b/4529436, due to the fact that a symbol resolution failure could
  3666. // potentially cause another file to be recursively built, which would trigger
  3667. // a checkpoint _past_ possibly invalid symbols.
  3668. // Baz is defined in the database, but the file is invalid because it is
  3669. // missing a necessary import.
  3670. DescriptorPool pool(&database_);
  3671. EXPECT_TRUE(pool.FindMessageTypeByName("Baz") == NULL);
  3672. // Make sure that searching again for the file or the type fails.
  3673. EXPECT_TRUE(pool.FindFileByName("baz.proto") == NULL);
  3674. EXPECT_TRUE(pool.FindMessageTypeByName("Baz") == NULL);
  3675. }
  3676. TEST_F(DatabaseBackedPoolTest, UnittestProto) {
  3677. // Try to load all of unittest.proto from a DescriptorDatabase. This should
  3678. // thoroughly test all paths through DescriptorBuilder to insure that there
  3679. // are no deadlocking problems when pool_->mutex_ is non-NULL.
  3680. const FileDescriptor* original_file =
  3681. protobuf_unittest::TestAllTypes::descriptor()->file();
  3682. DescriptorPoolDatabase database(*DescriptorPool::generated_pool());
  3683. DescriptorPool pool(&database);
  3684. const FileDescriptor* file_from_database =
  3685. pool.FindFileByName(original_file->name());
  3686. ASSERT_TRUE(file_from_database != NULL);
  3687. FileDescriptorProto original_file_proto;
  3688. original_file->CopyTo(&original_file_proto);
  3689. FileDescriptorProto file_from_database_proto;
  3690. file_from_database->CopyTo(&file_from_database_proto);
  3691. EXPECT_EQ(original_file_proto.DebugString(),
  3692. file_from_database_proto.DebugString());
  3693. }
  3694. TEST_F(DatabaseBackedPoolTest, DoesntRetryDbUnnecessarily) {
  3695. // Searching for a child of an existing descriptor should never fall back
  3696. // to the DescriptorDatabase even if it isn't found, because we know all
  3697. // children are already loaded.
  3698. CallCountingDatabase call_counter(&database_);
  3699. DescriptorPool pool(&call_counter);
  3700. const FileDescriptor* file = pool.FindFileByName("foo.proto");
  3701. ASSERT_TRUE(file != NULL);
  3702. const Descriptor* foo = pool.FindMessageTypeByName("Foo");
  3703. ASSERT_TRUE(foo != NULL);
  3704. const EnumDescriptor* test_enum = pool.FindEnumTypeByName("TestEnum");
  3705. ASSERT_TRUE(test_enum != NULL);
  3706. const ServiceDescriptor* test_service = pool.FindServiceByName("TestService");
  3707. ASSERT_TRUE(test_service != NULL);
  3708. EXPECT_NE(0, call_counter.call_count_);
  3709. call_counter.Clear();
  3710. EXPECT_TRUE(foo->FindFieldByName("no_such_field") == NULL);
  3711. EXPECT_TRUE(foo->FindExtensionByName("no_such_extension") == NULL);
  3712. EXPECT_TRUE(foo->FindNestedTypeByName("NoSuchMessageType") == NULL);
  3713. EXPECT_TRUE(foo->FindEnumTypeByName("NoSuchEnumType") == NULL);
  3714. EXPECT_TRUE(foo->FindEnumValueByName("NO_SUCH_VALUE") == NULL);
  3715. EXPECT_TRUE(test_enum->FindValueByName("NO_SUCH_VALUE") == NULL);
  3716. EXPECT_TRUE(test_service->FindMethodByName("NoSuchMethod") == NULL);
  3717. EXPECT_TRUE(file->FindMessageTypeByName("NoSuchMessageType") == NULL);
  3718. EXPECT_TRUE(file->FindEnumTypeByName("NoSuchEnumType") == NULL);
  3719. EXPECT_TRUE(file->FindEnumValueByName("NO_SUCH_VALUE") == NULL);
  3720. EXPECT_TRUE(file->FindServiceByName("NO_SUCH_VALUE") == NULL);
  3721. EXPECT_TRUE(file->FindExtensionByName("no_such_extension") == NULL);
  3722. EXPECT_TRUE(pool.FindFileContainingSymbol("Foo.no.such.field") == NULL);
  3723. EXPECT_TRUE(pool.FindFileContainingSymbol("Foo.no_such_field") == NULL);
  3724. EXPECT_TRUE(pool.FindMessageTypeByName("Foo.NoSuchMessageType") == NULL);
  3725. EXPECT_TRUE(pool.FindFieldByName("Foo.no_such_field") == NULL);
  3726. EXPECT_TRUE(pool.FindExtensionByName("Foo.no_such_extension") == NULL);
  3727. EXPECT_TRUE(pool.FindEnumTypeByName("Foo.NoSuchEnumType") == NULL);
  3728. EXPECT_TRUE(pool.FindEnumValueByName("Foo.NO_SUCH_VALUE") == NULL);
  3729. EXPECT_TRUE(pool.FindMethodByName("TestService.NoSuchMethod") == NULL);
  3730. EXPECT_EQ(0, call_counter.call_count_);
  3731. }
  3732. TEST_F(DatabaseBackedPoolTest, DoesntReloadFilesUncesessarily) {
  3733. // If FindFileContainingSymbol() or FindFileContainingExtension() return a
  3734. // file that is already in the DescriptorPool, it should not attempt to
  3735. // reload the file.
  3736. FalsePositiveDatabase false_positive_database(&database_);
  3737. MockErrorCollector error_collector;
  3738. DescriptorPool pool(&false_positive_database, &error_collector);
  3739. // First make sure foo.proto is loaded.
  3740. const Descriptor* foo = pool.FindMessageTypeByName("Foo");
  3741. ASSERT_TRUE(foo != NULL);
  3742. // Try inducing false positives.
  3743. EXPECT_TRUE(pool.FindMessageTypeByName("NoSuchSymbol") == NULL);
  3744. EXPECT_TRUE(pool.FindExtensionByNumber(foo, 22) == NULL);
  3745. // No errors should have been reported. (If foo.proto was incorrectly
  3746. // loaded multiple times, errors would have been reported.)
  3747. EXPECT_EQ("", error_collector.text_);
  3748. }
  3749. TEST_F(DatabaseBackedPoolTest, DoesntReloadKnownBadFiles) {
  3750. ErrorDescriptorDatabase error_database;
  3751. MockErrorCollector error_collector;
  3752. DescriptorPool pool(&error_database, &error_collector);
  3753. EXPECT_TRUE(pool.FindFileByName("error.proto") == NULL);
  3754. error_collector.text_.clear();
  3755. EXPECT_TRUE(pool.FindFileByName("error.proto") == NULL);
  3756. EXPECT_EQ("", error_collector.text_);
  3757. }
  3758. TEST_F(DatabaseBackedPoolTest, DoesntFallbackOnWrongType) {
  3759. // If a lookup finds a symbol of the wrong type (e.g. we pass a type name
  3760. // to FindFieldByName()), we should fail fast, without checking the fallback
  3761. // database.
  3762. CallCountingDatabase call_counter(&database_);
  3763. DescriptorPool pool(&call_counter);
  3764. const FileDescriptor* file = pool.FindFileByName("foo.proto");
  3765. ASSERT_TRUE(file != NULL);
  3766. const Descriptor* foo = pool.FindMessageTypeByName("Foo");
  3767. ASSERT_TRUE(foo != NULL);
  3768. const EnumDescriptor* test_enum = pool.FindEnumTypeByName("TestEnum");
  3769. ASSERT_TRUE(test_enum != NULL);
  3770. EXPECT_NE(0, call_counter.call_count_);
  3771. call_counter.Clear();
  3772. EXPECT_TRUE(pool.FindMessageTypeByName("TestEnum") == NULL);
  3773. EXPECT_TRUE(pool.FindFieldByName("Foo") == NULL);
  3774. EXPECT_TRUE(pool.FindExtensionByName("Foo") == NULL);
  3775. EXPECT_TRUE(pool.FindEnumTypeByName("Foo") == NULL);
  3776. EXPECT_TRUE(pool.FindEnumValueByName("Foo") == NULL);
  3777. EXPECT_TRUE(pool.FindServiceByName("Foo") == NULL);
  3778. EXPECT_TRUE(pool.FindMethodByName("Foo") == NULL);
  3779. EXPECT_EQ(0, call_counter.call_count_);
  3780. }
  3781. // ===================================================================
  3782. class AbortingErrorCollector : public DescriptorPool::ErrorCollector {
  3783. public:
  3784. AbortingErrorCollector() {}
  3785. virtual void AddError(
  3786. const string &filename,
  3787. const string &element_name,
  3788. const Message *message,
  3789. ErrorLocation location,
  3790. const string &error_message) {
  3791. GOOGLE_LOG(FATAL) << "AddError() called unexpectedly: " << filename << ": "
  3792. << error_message;
  3793. }
  3794. private:
  3795. GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(AbortingErrorCollector);
  3796. };
  3797. // A source tree containing only one file.
  3798. class SingletonSourceTree : public compiler::SourceTree {
  3799. public:
  3800. SingletonSourceTree(const string& filename, const string& contents)
  3801. : filename_(filename), contents_(contents) {}
  3802. virtual io::ZeroCopyInputStream* Open(const string& filename) {
  3803. return filename == filename_ ?
  3804. new io::ArrayInputStream(contents_.data(), contents_.size()) : NULL;
  3805. }
  3806. private:
  3807. const string filename_;
  3808. const string contents_;
  3809. GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(SingletonSourceTree);
  3810. };
  3811. const char *const kSourceLocationTestInput =
  3812. "syntax = \"proto2\";\n"
  3813. "message A {\n"
  3814. " optional int32 a = 1;\n"
  3815. " message B {\n"
  3816. " required double b = 1;\n"
  3817. " }\n"
  3818. "}\n"
  3819. "enum Indecision {\n"
  3820. " YES = 1;\n"
  3821. " NO = 2;\n"
  3822. " MAYBE = 3;\n"
  3823. "}\n"
  3824. "service S {\n"
  3825. " rpc Method(A) returns (A.B);\n"
  3826. // Put an empty line here to make the source location range match.
  3827. "\n"
  3828. "}\n";
  3829. class SourceLocationTest : public testing::Test {
  3830. public:
  3831. SourceLocationTest()
  3832. : source_tree_("/test/test.proto", kSourceLocationTestInput),
  3833. db_(&source_tree_),
  3834. pool_(&db_, &collector_) {}
  3835. static string PrintSourceLocation(const SourceLocation &loc) {
  3836. return strings::Substitute("$0:$1-$2:$3",
  3837. 1 + loc.start_line,
  3838. 1 + loc.start_column,
  3839. 1 + loc.end_line,
  3840. 1 + loc.end_column);
  3841. }
  3842. private:
  3843. AbortingErrorCollector collector_;
  3844. SingletonSourceTree source_tree_;
  3845. compiler::SourceTreeDescriptorDatabase db_;
  3846. protected:
  3847. DescriptorPool pool_;
  3848. };
  3849. // TODO(adonovan): implement support for option fields and for
  3850. // subparts of declarations.
  3851. TEST_F(SourceLocationTest, GetSourceLocation) {
  3852. SourceLocation loc;
  3853. const FileDescriptor *file_desc =
  3854. GOOGLE_CHECK_NOTNULL(pool_.FindFileByName("/test/test.proto"));
  3855. const Descriptor *a_desc = file_desc->FindMessageTypeByName("A");
  3856. EXPECT_TRUE(a_desc->GetSourceLocation(&loc));
  3857. EXPECT_EQ("2:1-7:2", PrintSourceLocation(loc));
  3858. const Descriptor *a_b_desc = a_desc->FindNestedTypeByName("B");
  3859. EXPECT_TRUE(a_b_desc->GetSourceLocation(&loc));
  3860. EXPECT_EQ("4:3-6:4", PrintSourceLocation(loc));
  3861. const EnumDescriptor *e_desc = file_desc->FindEnumTypeByName("Indecision");
  3862. EXPECT_TRUE(e_desc->GetSourceLocation(&loc));
  3863. EXPECT_EQ("8:1-12:2", PrintSourceLocation(loc));
  3864. const EnumValueDescriptor *yes_desc = e_desc->FindValueByName("YES");
  3865. EXPECT_TRUE(yes_desc->GetSourceLocation(&loc));
  3866. EXPECT_EQ("9:3-9:13", PrintSourceLocation(loc));
  3867. const ServiceDescriptor *s_desc = file_desc->FindServiceByName("S");
  3868. EXPECT_TRUE(s_desc->GetSourceLocation(&loc));
  3869. EXPECT_EQ("13:1-16:2", PrintSourceLocation(loc));
  3870. const MethodDescriptor *m_desc = s_desc->FindMethodByName("Method");
  3871. EXPECT_TRUE(m_desc->GetSourceLocation(&loc));
  3872. EXPECT_EQ("14:3-14:31", PrintSourceLocation(loc));
  3873. }
  3874. // Missing SourceCodeInfo doesn't cause crash:
  3875. TEST_F(SourceLocationTest, GetSourceLocation_MissingSourceCodeInfo) {
  3876. SourceLocation loc;
  3877. const FileDescriptor *file_desc =
  3878. GOOGLE_CHECK_NOTNULL(pool_.FindFileByName("/test/test.proto"));
  3879. FileDescriptorProto proto;
  3880. file_desc->CopyTo(&proto); // Note, this discards the SourceCodeInfo.
  3881. EXPECT_FALSE(proto.has_source_code_info());
  3882. DescriptorPool bad1_pool(&pool_);
  3883. const FileDescriptor* bad1_file_desc =
  3884. GOOGLE_CHECK_NOTNULL(bad1_pool.BuildFile(proto));
  3885. const Descriptor *bad1_a_desc = bad1_file_desc->FindMessageTypeByName("A");
  3886. EXPECT_FALSE(bad1_a_desc->GetSourceLocation(&loc));
  3887. }
  3888. // Corrupt SourceCodeInfo doesn't cause crash:
  3889. TEST_F(SourceLocationTest, GetSourceLocation_BogusSourceCodeInfo) {
  3890. SourceLocation loc;
  3891. const FileDescriptor *file_desc =
  3892. GOOGLE_CHECK_NOTNULL(pool_.FindFileByName("/test/test.proto"));
  3893. FileDescriptorProto proto;
  3894. file_desc->CopyTo(&proto); // Note, this discards the SourceCodeInfo.
  3895. EXPECT_FALSE(proto.has_source_code_info());
  3896. SourceCodeInfo_Location *loc_msg =
  3897. proto.mutable_source_code_info()->add_location();
  3898. loc_msg->add_path(1);
  3899. loc_msg->add_path(2);
  3900. loc_msg->add_path(3);
  3901. loc_msg->add_span(4);
  3902. loc_msg->add_span(5);
  3903. loc_msg->add_span(6);
  3904. DescriptorPool bad2_pool(&pool_);
  3905. const FileDescriptor* bad2_file_desc =
  3906. GOOGLE_CHECK_NOTNULL(bad2_pool.BuildFile(proto));
  3907. const Descriptor *bad2_a_desc = bad2_file_desc->FindMessageTypeByName("A");
  3908. EXPECT_FALSE(bad2_a_desc->GetSourceLocation(&loc));
  3909. }
  3910. // ===================================================================
  3911. const char* const kCopySourceCodeInfoToTestInput =
  3912. "syntax = \"proto2\";\n"
  3913. "message Foo {}\n";
  3914. // Required since source code information is not preserved by
  3915. // FileDescriptorTest.
  3916. class CopySourceCodeInfoToTest : public testing::Test {
  3917. public:
  3918. CopySourceCodeInfoToTest()
  3919. : source_tree_("/test/test.proto", kCopySourceCodeInfoToTestInput),
  3920. db_(&source_tree_),
  3921. pool_(&db_, &collector_) {}
  3922. private:
  3923. AbortingErrorCollector collector_;
  3924. SingletonSourceTree source_tree_;
  3925. compiler::SourceTreeDescriptorDatabase db_;
  3926. protected:
  3927. DescriptorPool pool_;
  3928. };
  3929. TEST_F(CopySourceCodeInfoToTest, CopyTo_DoesNotCopySourceCodeInfo) {
  3930. const FileDescriptor* file_desc =
  3931. GOOGLE_CHECK_NOTNULL(pool_.FindFileByName("/test/test.proto"));
  3932. FileDescriptorProto file_desc_proto;
  3933. ASSERT_FALSE(file_desc_proto.has_source_code_info());
  3934. file_desc->CopyTo(&file_desc_proto);
  3935. EXPECT_FALSE(file_desc_proto.has_source_code_info());
  3936. }
  3937. TEST_F(CopySourceCodeInfoToTest, CopySourceCodeInfoTo) {
  3938. const FileDescriptor* file_desc =
  3939. GOOGLE_CHECK_NOTNULL(pool_.FindFileByName("/test/test.proto"));
  3940. FileDescriptorProto file_desc_proto;
  3941. ASSERT_FALSE(file_desc_proto.has_source_code_info());
  3942. file_desc->CopySourceCodeInfoTo(&file_desc_proto);
  3943. const SourceCodeInfo& info = file_desc_proto.source_code_info();
  3944. ASSERT_EQ(3, info.location_size());
  3945. // Get the Foo message location
  3946. const SourceCodeInfo_Location& foo_location = info.location(1);
  3947. ASSERT_EQ(2, foo_location.path_size());
  3948. EXPECT_EQ(FileDescriptorProto::kMessageTypeFieldNumber, foo_location.path(0));
  3949. EXPECT_EQ(0, foo_location.path(1)); // Foo is the first message defined
  3950. ASSERT_EQ(3, foo_location.span_size()); // Foo spans one line
  3951. EXPECT_EQ(1, foo_location.span(0)); // Foo is declared on line 1
  3952. EXPECT_EQ(0, foo_location.span(1)); // Foo starts at column 0
  3953. EXPECT_EQ(14, foo_location.span(2)); // Foo ends on column 14
  3954. }
  3955. // ===================================================================
  3956. } // namespace descriptor_unittest
  3957. } // namespace protobuf
  3958. } // namespace google