诸暨麻将添加redis
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

8046 lines
300 KiB

  1. // Protocol Buffers - Google's data interchange format
  2. // Copyright 2008 Google Inc. All rights reserved.
  3. // https://developers.google.com/protocol-buffers/
  4. //
  5. // Redistribution and use in source and binary forms, with or without
  6. // modification, are permitted provided that the following conditions are
  7. // met:
  8. //
  9. // * Redistributions of source code must retain the above copyright
  10. // notice, this list of conditions and the following disclaimer.
  11. // * Redistributions in binary form must reproduce the above
  12. // copyright notice, this list of conditions and the following disclaimer
  13. // in the documentation and/or other materials provided with the
  14. // distribution.
  15. // * Neither the name of Google Inc. nor the names of its
  16. // contributors may be used to endorse or promote products derived from
  17. // this software without specific prior written permission.
  18. //
  19. // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  20. // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  21. // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  22. // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  23. // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  24. // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  25. // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  26. // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  27. // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  28. // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  29. // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  30. // Author: kenton@google.com (Kenton Varda)
  31. // Based on original Protocol Buffers design by
  32. // Sanjay Ghemawat, Jeff Dean, and others.
  33. //
  34. // This file makes extensive use of RFC 3092. :)
  35. #include <limits>
  36. #include <memory>
  37. #include <vector>
  38. #include <google/protobuf/compiler/importer.h>
  39. #include <google/protobuf/compiler/parser.h>
  40. #include <google/protobuf/unittest.pb.h>
  41. #include <google/protobuf/unittest_custom_options.pb.h>
  42. #include <google/protobuf/stubs/common.h>
  43. #include <google/protobuf/stubs/logging.h>
  44. #include <google/protobuf/stubs/logging.h>
  45. #include <google/protobuf/stubs/stringprintf.h>
  46. #include <google/protobuf/unittest_lazy_dependencies.pb.h>
  47. #include <google/protobuf/unittest_proto3_arena.pb.h>
  48. #include <google/protobuf/io/tokenizer.h>
  49. #include <google/protobuf/io/zero_copy_stream_impl.h>
  50. #include <google/protobuf/descriptor.pb.h>
  51. #include <google/protobuf/descriptor.h>
  52. #include <google/protobuf/descriptor_database.h>
  53. #include <google/protobuf/dynamic_message.h>
  54. #include <google/protobuf/text_format.h>
  55. #include <google/protobuf/stubs/strutil.h>
  56. #include <google/protobuf/testing/googletest.h>
  57. #include <gtest/gtest.h>
  58. #include <google/protobuf/stubs/substitute.h>
  59. #include <google/protobuf/port_def.inc>
  60. namespace google {
  61. namespace protobuf {
  62. // Can't use an anonymous namespace here due to brokenness of Tru64 compiler.
  63. namespace descriptor_unittest {
  64. // Some helpers to make assembling descriptors faster.
  65. DescriptorProto* AddMessage(FileDescriptorProto* file,
  66. const std::string& name) {
  67. DescriptorProto* result = file->add_message_type();
  68. result->set_name(name);
  69. return result;
  70. }
  71. DescriptorProto* AddNestedMessage(DescriptorProto* parent,
  72. const std::string& name) {
  73. DescriptorProto* result = parent->add_nested_type();
  74. result->set_name(name);
  75. return result;
  76. }
  77. EnumDescriptorProto* AddEnum(FileDescriptorProto* file,
  78. const std::string& name) {
  79. EnumDescriptorProto* result = file->add_enum_type();
  80. result->set_name(name);
  81. return result;
  82. }
  83. EnumDescriptorProto* AddNestedEnum(DescriptorProto* parent,
  84. const std::string& name) {
  85. EnumDescriptorProto* result = parent->add_enum_type();
  86. result->set_name(name);
  87. return result;
  88. }
  89. ServiceDescriptorProto* AddService(FileDescriptorProto* file,
  90. const std::string& name) {
  91. ServiceDescriptorProto* result = file->add_service();
  92. result->set_name(name);
  93. return result;
  94. }
  95. FieldDescriptorProto* AddField(DescriptorProto* parent, const std::string& name,
  96. int number, FieldDescriptorProto::Label label,
  97. FieldDescriptorProto::Type type) {
  98. FieldDescriptorProto* result = parent->add_field();
  99. result->set_name(name);
  100. result->set_number(number);
  101. result->set_label(label);
  102. result->set_type(type);
  103. return result;
  104. }
  105. FieldDescriptorProto* AddExtension(FileDescriptorProto* file,
  106. const std::string& extendee,
  107. const std::string& name, int number,
  108. FieldDescriptorProto::Label label,
  109. FieldDescriptorProto::Type type) {
  110. FieldDescriptorProto* result = file->add_extension();
  111. result->set_name(name);
  112. result->set_number(number);
  113. result->set_label(label);
  114. result->set_type(type);
  115. result->set_extendee(extendee);
  116. return result;
  117. }
  118. FieldDescriptorProto* AddNestedExtension(DescriptorProto* parent,
  119. const std::string& extendee,
  120. const std::string& name, int number,
  121. FieldDescriptorProto::Label label,
  122. FieldDescriptorProto::Type type) {
  123. FieldDescriptorProto* result = parent->add_extension();
  124. result->set_name(name);
  125. result->set_number(number);
  126. result->set_label(label);
  127. result->set_type(type);
  128. result->set_extendee(extendee);
  129. return result;
  130. }
  131. DescriptorProto::ExtensionRange* AddExtensionRange(DescriptorProto* parent,
  132. int start, int end) {
  133. DescriptorProto::ExtensionRange* result = parent->add_extension_range();
  134. result->set_start(start);
  135. result->set_end(end);
  136. return result;
  137. }
  138. DescriptorProto::ReservedRange* AddReservedRange(DescriptorProto* parent,
  139. int start, int end) {
  140. DescriptorProto::ReservedRange* result = parent->add_reserved_range();
  141. result->set_start(start);
  142. result->set_end(end);
  143. return result;
  144. }
  145. EnumDescriptorProto::EnumReservedRange* AddReservedRange(
  146. EnumDescriptorProto* parent, int start, int end) {
  147. EnumDescriptorProto::EnumReservedRange* result = parent->add_reserved_range();
  148. result->set_start(start);
  149. result->set_end(end);
  150. return result;
  151. }
  152. EnumValueDescriptorProto* AddEnumValue(EnumDescriptorProto* enum_proto,
  153. const std::string& name, int number) {
  154. EnumValueDescriptorProto* result = enum_proto->add_value();
  155. result->set_name(name);
  156. result->set_number(number);
  157. return result;
  158. }
  159. MethodDescriptorProto* AddMethod(ServiceDescriptorProto* service,
  160. const std::string& name,
  161. const std::string& input_type,
  162. const std::string& output_type) {
  163. MethodDescriptorProto* result = service->add_method();
  164. result->set_name(name);
  165. result->set_input_type(input_type);
  166. result->set_output_type(output_type);
  167. return result;
  168. }
  169. // Empty enums technically aren't allowed. We need to insert a dummy value
  170. // into them.
  171. void AddEmptyEnum(FileDescriptorProto* file, const std::string& name) {
  172. AddEnumValue(AddEnum(file, name), name + "_DUMMY", 1);
  173. }
  174. class MockErrorCollector : public DescriptorPool::ErrorCollector {
  175. public:
  176. MockErrorCollector() {}
  177. ~MockErrorCollector() {}
  178. std::string text_;
  179. std::string warning_text_;
  180. // implements ErrorCollector ---------------------------------------
  181. void AddError(const std::string& filename, const std::string& element_name,
  182. const Message* descriptor, ErrorLocation location,
  183. const std::string& message) {
  184. const char* location_name = nullptr;
  185. switch (location) {
  186. case NAME:
  187. location_name = "NAME";
  188. break;
  189. case NUMBER:
  190. location_name = "NUMBER";
  191. break;
  192. case TYPE:
  193. location_name = "TYPE";
  194. break;
  195. case EXTENDEE:
  196. location_name = "EXTENDEE";
  197. break;
  198. case DEFAULT_VALUE:
  199. location_name = "DEFAULT_VALUE";
  200. break;
  201. case OPTION_NAME:
  202. location_name = "OPTION_NAME";
  203. break;
  204. case OPTION_VALUE:
  205. location_name = "OPTION_VALUE";
  206. break;
  207. case INPUT_TYPE:
  208. location_name = "INPUT_TYPE";
  209. break;
  210. case OUTPUT_TYPE:
  211. location_name = "OUTPUT_TYPE";
  212. break;
  213. case IMPORT:
  214. location_name = "IMPORT";
  215. break;
  216. case OTHER:
  217. location_name = "OTHER";
  218. break;
  219. }
  220. strings::SubstituteAndAppend(&text_, "$0: $1: $2: $3\n", filename,
  221. element_name, location_name, message);
  222. }
  223. // implements ErrorCollector ---------------------------------------
  224. void AddWarning(const std::string& filename, const std::string& element_name,
  225. const Message* descriptor, ErrorLocation location,
  226. const std::string& message) {
  227. const char* location_name = nullptr;
  228. switch (location) {
  229. case NAME:
  230. location_name = "NAME";
  231. break;
  232. case NUMBER:
  233. location_name = "NUMBER";
  234. break;
  235. case TYPE:
  236. location_name = "TYPE";
  237. break;
  238. case EXTENDEE:
  239. location_name = "EXTENDEE";
  240. break;
  241. case DEFAULT_VALUE:
  242. location_name = "DEFAULT_VALUE";
  243. break;
  244. case OPTION_NAME:
  245. location_name = "OPTION_NAME";
  246. break;
  247. case OPTION_VALUE:
  248. location_name = "OPTION_VALUE";
  249. break;
  250. case INPUT_TYPE:
  251. location_name = "INPUT_TYPE";
  252. break;
  253. case OUTPUT_TYPE:
  254. location_name = "OUTPUT_TYPE";
  255. break;
  256. case IMPORT:
  257. location_name = "IMPORT";
  258. break;
  259. case OTHER:
  260. location_name = "OTHER";
  261. break;
  262. }
  263. strings::SubstituteAndAppend(&warning_text_, "$0: $1: $2: $3\n", filename,
  264. element_name, location_name, message);
  265. }
  266. };
  267. // ===================================================================
  268. // Test simple files.
  269. class FileDescriptorTest : public testing::Test {
  270. protected:
  271. virtual void SetUp() {
  272. // Build descriptors for the following definitions:
  273. //
  274. // // in "foo.proto"
  275. // message FooMessage { extensions 1; }
  276. // enum FooEnum {FOO_ENUM_VALUE = 1;}
  277. // service FooService {}
  278. // extend FooMessage { optional int32 foo_extension = 1; }
  279. //
  280. // // in "bar.proto"
  281. // package bar_package;
  282. // message BarMessage { extensions 1; }
  283. // enum BarEnum {BAR_ENUM_VALUE = 1;}
  284. // service BarService {}
  285. // extend BarMessage { optional int32 bar_extension = 1; }
  286. //
  287. // Also, we have an empty file "baz.proto". This file's purpose is to
  288. // make sure that even though it has the same package as foo.proto,
  289. // searching it for members of foo.proto won't work.
  290. FileDescriptorProto foo_file;
  291. foo_file.set_name("foo.proto");
  292. AddExtensionRange(AddMessage(&foo_file, "FooMessage"), 1, 2);
  293. AddEnumValue(AddEnum(&foo_file, "FooEnum"), "FOO_ENUM_VALUE", 1);
  294. AddService(&foo_file, "FooService");
  295. AddExtension(&foo_file, "FooMessage", "foo_extension", 1,
  296. FieldDescriptorProto::LABEL_OPTIONAL,
  297. FieldDescriptorProto::TYPE_INT32);
  298. FileDescriptorProto bar_file;
  299. bar_file.set_name("bar.proto");
  300. bar_file.set_package("bar_package");
  301. bar_file.add_dependency("foo.proto");
  302. AddExtensionRange(AddMessage(&bar_file, "BarMessage"), 1, 2);
  303. AddEnumValue(AddEnum(&bar_file, "BarEnum"), "BAR_ENUM_VALUE", 1);
  304. AddService(&bar_file, "BarService");
  305. AddExtension(&bar_file, "bar_package.BarMessage", "bar_extension", 1,
  306. FieldDescriptorProto::LABEL_OPTIONAL,
  307. FieldDescriptorProto::TYPE_INT32);
  308. FileDescriptorProto baz_file;
  309. baz_file.set_name("baz.proto");
  310. // Build the descriptors and get the pointers.
  311. foo_file_ = pool_.BuildFile(foo_file);
  312. ASSERT_TRUE(foo_file_ != nullptr);
  313. bar_file_ = pool_.BuildFile(bar_file);
  314. ASSERT_TRUE(bar_file_ != nullptr);
  315. baz_file_ = pool_.BuildFile(baz_file);
  316. ASSERT_TRUE(baz_file_ != nullptr);
  317. ASSERT_EQ(1, foo_file_->message_type_count());
  318. foo_message_ = foo_file_->message_type(0);
  319. ASSERT_EQ(1, foo_file_->enum_type_count());
  320. foo_enum_ = foo_file_->enum_type(0);
  321. ASSERT_EQ(1, foo_enum_->value_count());
  322. foo_enum_value_ = foo_enum_->value(0);
  323. ASSERT_EQ(1, foo_file_->service_count());
  324. foo_service_ = foo_file_->service(0);
  325. ASSERT_EQ(1, foo_file_->extension_count());
  326. foo_extension_ = foo_file_->extension(0);
  327. ASSERT_EQ(1, bar_file_->message_type_count());
  328. bar_message_ = bar_file_->message_type(0);
  329. ASSERT_EQ(1, bar_file_->enum_type_count());
  330. bar_enum_ = bar_file_->enum_type(0);
  331. ASSERT_EQ(1, bar_enum_->value_count());
  332. bar_enum_value_ = bar_enum_->value(0);
  333. ASSERT_EQ(1, bar_file_->service_count());
  334. bar_service_ = bar_file_->service(0);
  335. ASSERT_EQ(1, bar_file_->extension_count());
  336. bar_extension_ = bar_file_->extension(0);
  337. }
  338. DescriptorPool pool_;
  339. const FileDescriptor* foo_file_;
  340. const FileDescriptor* bar_file_;
  341. const FileDescriptor* baz_file_;
  342. const Descriptor* foo_message_;
  343. const EnumDescriptor* foo_enum_;
  344. const EnumValueDescriptor* foo_enum_value_;
  345. const ServiceDescriptor* foo_service_;
  346. const FieldDescriptor* foo_extension_;
  347. const Descriptor* bar_message_;
  348. const EnumDescriptor* bar_enum_;
  349. const EnumValueDescriptor* bar_enum_value_;
  350. const ServiceDescriptor* bar_service_;
  351. const FieldDescriptor* bar_extension_;
  352. };
  353. TEST_F(FileDescriptorTest, Name) {
  354. EXPECT_EQ("foo.proto", foo_file_->name());
  355. EXPECT_EQ("bar.proto", bar_file_->name());
  356. EXPECT_EQ("baz.proto", baz_file_->name());
  357. }
  358. TEST_F(FileDescriptorTest, Package) {
  359. EXPECT_EQ("", foo_file_->package());
  360. EXPECT_EQ("bar_package", bar_file_->package());
  361. }
  362. TEST_F(FileDescriptorTest, Dependencies) {
  363. EXPECT_EQ(0, foo_file_->dependency_count());
  364. EXPECT_EQ(1, bar_file_->dependency_count());
  365. EXPECT_EQ(foo_file_, bar_file_->dependency(0));
  366. }
  367. TEST_F(FileDescriptorTest, FindMessageTypeByName) {
  368. EXPECT_EQ(foo_message_, foo_file_->FindMessageTypeByName("FooMessage"));
  369. EXPECT_EQ(bar_message_, bar_file_->FindMessageTypeByName("BarMessage"));
  370. EXPECT_TRUE(foo_file_->FindMessageTypeByName("BarMessage") == nullptr);
  371. EXPECT_TRUE(bar_file_->FindMessageTypeByName("FooMessage") == nullptr);
  372. EXPECT_TRUE(baz_file_->FindMessageTypeByName("FooMessage") == nullptr);
  373. EXPECT_TRUE(foo_file_->FindMessageTypeByName("NoSuchMessage") == nullptr);
  374. EXPECT_TRUE(foo_file_->FindMessageTypeByName("FooEnum") == nullptr);
  375. }
  376. TEST_F(FileDescriptorTest, FindEnumTypeByName) {
  377. EXPECT_EQ(foo_enum_, foo_file_->FindEnumTypeByName("FooEnum"));
  378. EXPECT_EQ(bar_enum_, bar_file_->FindEnumTypeByName("BarEnum"));
  379. EXPECT_TRUE(foo_file_->FindEnumTypeByName("BarEnum") == nullptr);
  380. EXPECT_TRUE(bar_file_->FindEnumTypeByName("FooEnum") == nullptr);
  381. EXPECT_TRUE(baz_file_->FindEnumTypeByName("FooEnum") == nullptr);
  382. EXPECT_TRUE(foo_file_->FindEnumTypeByName("NoSuchEnum") == nullptr);
  383. EXPECT_TRUE(foo_file_->FindEnumTypeByName("FooMessage") == nullptr);
  384. }
  385. TEST_F(FileDescriptorTest, FindEnumValueByName) {
  386. EXPECT_EQ(foo_enum_value_, foo_file_->FindEnumValueByName("FOO_ENUM_VALUE"));
  387. EXPECT_EQ(bar_enum_value_, bar_file_->FindEnumValueByName("BAR_ENUM_VALUE"));
  388. EXPECT_TRUE(foo_file_->FindEnumValueByName("BAR_ENUM_VALUE") == nullptr);
  389. EXPECT_TRUE(bar_file_->FindEnumValueByName("FOO_ENUM_VALUE") == nullptr);
  390. EXPECT_TRUE(baz_file_->FindEnumValueByName("FOO_ENUM_VALUE") == nullptr);
  391. EXPECT_TRUE(foo_file_->FindEnumValueByName("NO_SUCH_VALUE") == nullptr);
  392. EXPECT_TRUE(foo_file_->FindEnumValueByName("FooMessage") == nullptr);
  393. }
  394. TEST_F(FileDescriptorTest, FindServiceByName) {
  395. EXPECT_EQ(foo_service_, foo_file_->FindServiceByName("FooService"));
  396. EXPECT_EQ(bar_service_, bar_file_->FindServiceByName("BarService"));
  397. EXPECT_TRUE(foo_file_->FindServiceByName("BarService") == nullptr);
  398. EXPECT_TRUE(bar_file_->FindServiceByName("FooService") == nullptr);
  399. EXPECT_TRUE(baz_file_->FindServiceByName("FooService") == nullptr);
  400. EXPECT_TRUE(foo_file_->FindServiceByName("NoSuchService") == nullptr);
  401. EXPECT_TRUE(foo_file_->FindServiceByName("FooMessage") == nullptr);
  402. }
  403. TEST_F(FileDescriptorTest, FindExtensionByName) {
  404. EXPECT_EQ(foo_extension_, foo_file_->FindExtensionByName("foo_extension"));
  405. EXPECT_EQ(bar_extension_, bar_file_->FindExtensionByName("bar_extension"));
  406. EXPECT_TRUE(foo_file_->FindExtensionByName("bar_extension") == nullptr);
  407. EXPECT_TRUE(bar_file_->FindExtensionByName("foo_extension") == nullptr);
  408. EXPECT_TRUE(baz_file_->FindExtensionByName("foo_extension") == nullptr);
  409. EXPECT_TRUE(foo_file_->FindExtensionByName("no_such_extension") == nullptr);
  410. EXPECT_TRUE(foo_file_->FindExtensionByName("FooMessage") == nullptr);
  411. }
  412. TEST_F(FileDescriptorTest, FindExtensionByNumber) {
  413. EXPECT_EQ(foo_extension_, pool_.FindExtensionByNumber(foo_message_, 1));
  414. EXPECT_EQ(bar_extension_, pool_.FindExtensionByNumber(bar_message_, 1));
  415. EXPECT_TRUE(pool_.FindExtensionByNumber(foo_message_, 2) == nullptr);
  416. }
  417. TEST_F(FileDescriptorTest, BuildAgain) {
  418. // Test that if te call BuildFile again on the same input we get the same
  419. // FileDescriptor back.
  420. FileDescriptorProto file;
  421. foo_file_->CopyTo(&file);
  422. EXPECT_EQ(foo_file_, pool_.BuildFile(file));
  423. // But if we change the file then it won't work.
  424. file.set_package("some.other.package");
  425. EXPECT_TRUE(pool_.BuildFile(file) == nullptr);
  426. }
  427. TEST_F(FileDescriptorTest, BuildAgainWithSyntax) {
  428. // Test that if te call BuildFile again on the same input we get the same
  429. // FileDescriptor back even if syntax param is specified.
  430. FileDescriptorProto proto_syntax2;
  431. proto_syntax2.set_name("foo_syntax2");
  432. proto_syntax2.set_syntax("proto2");
  433. const FileDescriptor* proto2_descriptor = pool_.BuildFile(proto_syntax2);
  434. EXPECT_TRUE(proto2_descriptor != nullptr);
  435. EXPECT_EQ(proto2_descriptor, pool_.BuildFile(proto_syntax2));
  436. FileDescriptorProto implicit_proto2;
  437. implicit_proto2.set_name("foo_implicit_syntax2");
  438. const FileDescriptor* implicit_proto2_descriptor =
  439. pool_.BuildFile(implicit_proto2);
  440. EXPECT_TRUE(implicit_proto2_descriptor != nullptr);
  441. // We get the same FileDescriptor back if syntax param is explicitly
  442. // specified.
  443. implicit_proto2.set_syntax("proto2");
  444. EXPECT_EQ(implicit_proto2_descriptor, pool_.BuildFile(implicit_proto2));
  445. FileDescriptorProto proto_syntax3;
  446. proto_syntax3.set_name("foo_syntax3");
  447. proto_syntax3.set_syntax("proto3");
  448. const FileDescriptor* proto3_descriptor = pool_.BuildFile(proto_syntax3);
  449. EXPECT_TRUE(proto3_descriptor != nullptr);
  450. EXPECT_EQ(proto3_descriptor, pool_.BuildFile(proto_syntax3));
  451. }
  452. TEST_F(FileDescriptorTest, Syntax) {
  453. FileDescriptorProto proto;
  454. proto.set_name("foo");
  455. // Enable the test when we also populate the syntax for proto2.
  456. #if 0
  457. {
  458. proto.set_syntax("proto2");
  459. DescriptorPool pool;
  460. const FileDescriptor* file = pool.BuildFile(proto);
  461. EXPECT_TRUE(file != nullptr);
  462. EXPECT_EQ(FileDescriptor::SYNTAX_PROTO2, file->syntax());
  463. FileDescriptorProto other;
  464. file->CopyTo(&other);
  465. EXPECT_EQ("proto2", other.syntax());
  466. }
  467. #endif
  468. {
  469. proto.set_syntax("proto3");
  470. DescriptorPool pool;
  471. const FileDescriptor* file = pool.BuildFile(proto);
  472. EXPECT_TRUE(file != nullptr);
  473. EXPECT_EQ(FileDescriptor::SYNTAX_PROTO3, file->syntax());
  474. FileDescriptorProto other;
  475. file->CopyTo(&other);
  476. EXPECT_EQ("proto3", other.syntax());
  477. }
  478. }
  479. void ExtractDebugString(
  480. const FileDescriptor* file, std::set<std::string>* visited,
  481. std::vector<std::pair<std::string, std::string>>* debug_strings) {
  482. if (!visited->insert(file->name()).second) {
  483. return;
  484. }
  485. for (int i = 0; i < file->dependency_count(); ++i) {
  486. ExtractDebugString(file->dependency(i), visited, debug_strings);
  487. }
  488. debug_strings->push_back(std::make_pair(file->name(), file->DebugString()));
  489. }
  490. class SimpleErrorCollector : public io::ErrorCollector {
  491. public:
  492. // implements ErrorCollector ---------------------------------------
  493. void AddError(int line, int column, const std::string& message) {
  494. last_error_ = StringPrintf("%d:%d:", line, column) + message;
  495. }
  496. const std::string& last_error() { return last_error_; }
  497. private:
  498. std::string last_error_;
  499. };
  500. // Test that the result of FileDescriptor::DebugString() can be used to create
  501. // the original descriptors.
  502. TEST_F(FileDescriptorTest, DebugStringRoundTrip) {
  503. std::set<std::string> visited;
  504. std::vector<std::pair<std::string, std::string>> debug_strings;
  505. ExtractDebugString(protobuf_unittest::TestAllTypes::descriptor()->file(),
  506. &visited, &debug_strings);
  507. ExtractDebugString(
  508. protobuf_unittest::TestMessageWithCustomOptions::descriptor()->file(),
  509. &visited, &debug_strings);
  510. ExtractDebugString(proto3_arena_unittest::TestAllTypes::descriptor()->file(),
  511. &visited, &debug_strings);
  512. ASSERT_GE(debug_strings.size(), 3);
  513. DescriptorPool pool;
  514. for (int i = 0; i < debug_strings.size(); ++i) {
  515. const std::string& name = debug_strings[i].first;
  516. const std::string& content = debug_strings[i].second;
  517. io::ArrayInputStream input_stream(content.data(), content.size());
  518. SimpleErrorCollector error_collector;
  519. io::Tokenizer tokenizer(&input_stream, &error_collector);
  520. compiler::Parser parser;
  521. parser.RecordErrorsTo(&error_collector);
  522. FileDescriptorProto proto;
  523. ASSERT_TRUE(parser.Parse(&tokenizer, &proto))
  524. << error_collector.last_error() << "\n"
  525. << content;
  526. ASSERT_EQ("", error_collector.last_error());
  527. proto.set_name(name);
  528. const FileDescriptor* descriptor = pool.BuildFile(proto);
  529. ASSERT_TRUE(descriptor != nullptr) << proto.DebugString();
  530. EXPECT_EQ(content, descriptor->DebugString());
  531. }
  532. }
  533. // ===================================================================
  534. // Test simple flat messages and fields.
  535. class DescriptorTest : public testing::Test {
  536. protected:
  537. virtual void SetUp() {
  538. // Build descriptors for the following definitions:
  539. //
  540. // // in "foo.proto"
  541. // message TestForeign {}
  542. // enum TestEnum {}
  543. //
  544. // message TestMessage {
  545. // required string foo = 1;
  546. // optional TestEnum bar = 6;
  547. // repeated TestForeign baz = 500000000;
  548. // optional group qux = 15 {}
  549. // }
  550. //
  551. // // in "bar.proto"
  552. // package corge.grault;
  553. // message TestMessage2 {
  554. // required string foo = 1;
  555. // required string bar = 2;
  556. // required string quux = 6;
  557. // }
  558. //
  559. // // in "map.proto"
  560. // message TestMessage3 {
  561. // map<int32, int32> map_int32_int32 = 1;
  562. // }
  563. //
  564. // // in "json.proto"
  565. // message TestMessage4 {
  566. // optional int32 field_name1 = 1;
  567. // optional int32 fieldName2 = 2;
  568. // optional int32 FieldName3 = 3;
  569. // optional int32 _field_name4 = 4;
  570. // optional int32 FIELD_NAME5 = 5;
  571. // optional int32 field_name6 = 6 [json_name = "@type"];
  572. // }
  573. //
  574. // We cheat and use TestForeign as the type for qux rather than create
  575. // an actual nested type.
  576. //
  577. // Since all primitive types (including string) use the same building
  578. // code, there's no need to test each one individually.
  579. //
  580. // TestMessage2 is primarily here to test FindFieldByName and friends.
  581. // All messages created from the same DescriptorPool share the same lookup
  582. // table, so we need to insure that they don't interfere.
  583. FileDescriptorProto foo_file;
  584. foo_file.set_name("foo.proto");
  585. AddMessage(&foo_file, "TestForeign");
  586. AddEmptyEnum(&foo_file, "TestEnum");
  587. DescriptorProto* message = AddMessage(&foo_file, "TestMessage");
  588. AddField(message, "foo", 1, FieldDescriptorProto::LABEL_REQUIRED,
  589. FieldDescriptorProto::TYPE_STRING);
  590. AddField(message, "bar", 6, FieldDescriptorProto::LABEL_OPTIONAL,
  591. FieldDescriptorProto::TYPE_ENUM)
  592. ->set_type_name("TestEnum");
  593. AddField(message, "baz", 500000000, FieldDescriptorProto::LABEL_REPEATED,
  594. FieldDescriptorProto::TYPE_MESSAGE)
  595. ->set_type_name("TestForeign");
  596. AddField(message, "qux", 15, FieldDescriptorProto::LABEL_OPTIONAL,
  597. FieldDescriptorProto::TYPE_GROUP)
  598. ->set_type_name("TestForeign");
  599. FileDescriptorProto bar_file;
  600. bar_file.set_name("bar.proto");
  601. bar_file.set_package("corge.grault");
  602. DescriptorProto* message2 = AddMessage(&bar_file, "TestMessage2");
  603. AddField(message2, "foo", 1, FieldDescriptorProto::LABEL_REQUIRED,
  604. FieldDescriptorProto::TYPE_STRING);
  605. AddField(message2, "bar", 2, FieldDescriptorProto::LABEL_REQUIRED,
  606. FieldDescriptorProto::TYPE_STRING);
  607. AddField(message2, "quux", 6, FieldDescriptorProto::LABEL_REQUIRED,
  608. FieldDescriptorProto::TYPE_STRING);
  609. FileDescriptorProto map_file;
  610. map_file.set_name("map.proto");
  611. DescriptorProto* message3 = AddMessage(&map_file, "TestMessage3");
  612. DescriptorProto* entry = AddNestedMessage(message3, "MapInt32Int32Entry");
  613. AddField(entry, "key", 1, FieldDescriptorProto::LABEL_OPTIONAL,
  614. FieldDescriptorProto::TYPE_INT32);
  615. AddField(entry, "value", 2, FieldDescriptorProto::LABEL_OPTIONAL,
  616. FieldDescriptorProto::TYPE_INT32);
  617. entry->mutable_options()->set_map_entry(true);
  618. AddField(message3, "map_int32_int32", 1,
  619. FieldDescriptorProto::LABEL_REPEATED,
  620. FieldDescriptorProto::TYPE_MESSAGE)
  621. ->set_type_name("MapInt32Int32Entry");
  622. FileDescriptorProto json_file;
  623. json_file.set_name("json.proto");
  624. json_file.set_syntax("proto3");
  625. DescriptorProto* message4 = AddMessage(&json_file, "TestMessage4");
  626. AddField(message4, "field_name1", 1, FieldDescriptorProto::LABEL_OPTIONAL,
  627. FieldDescriptorProto::TYPE_INT32);
  628. AddField(message4, "fieldName2", 2, FieldDescriptorProto::LABEL_OPTIONAL,
  629. FieldDescriptorProto::TYPE_INT32);
  630. AddField(message4, "FieldName3", 3, FieldDescriptorProto::LABEL_OPTIONAL,
  631. FieldDescriptorProto::TYPE_INT32);
  632. AddField(message4, "_field_name4", 4, FieldDescriptorProto::LABEL_OPTIONAL,
  633. FieldDescriptorProto::TYPE_INT32);
  634. AddField(message4, "FIELD_NAME5", 5, FieldDescriptorProto::LABEL_OPTIONAL,
  635. FieldDescriptorProto::TYPE_INT32);
  636. AddField(message4, "field_name6", 6, FieldDescriptorProto::LABEL_OPTIONAL,
  637. FieldDescriptorProto::TYPE_INT32)
  638. ->set_json_name("@type");
  639. // Build the descriptors and get the pointers.
  640. foo_file_ = pool_.BuildFile(foo_file);
  641. ASSERT_TRUE(foo_file_ != nullptr);
  642. bar_file_ = pool_.BuildFile(bar_file);
  643. ASSERT_TRUE(bar_file_ != nullptr);
  644. map_file_ = pool_.BuildFile(map_file);
  645. ASSERT_TRUE(map_file_ != nullptr);
  646. json_file_ = pool_.BuildFile(json_file);
  647. ASSERT_TRUE(json_file_ != nullptr);
  648. ASSERT_EQ(1, foo_file_->enum_type_count());
  649. enum_ = foo_file_->enum_type(0);
  650. ASSERT_EQ(2, foo_file_->message_type_count());
  651. foreign_ = foo_file_->message_type(0);
  652. message_ = foo_file_->message_type(1);
  653. ASSERT_EQ(4, message_->field_count());
  654. foo_ = message_->field(0);
  655. bar_ = message_->field(1);
  656. baz_ = message_->field(2);
  657. qux_ = message_->field(3);
  658. ASSERT_EQ(1, bar_file_->message_type_count());
  659. message2_ = bar_file_->message_type(0);
  660. ASSERT_EQ(3, message2_->field_count());
  661. foo2_ = message2_->field(0);
  662. bar2_ = message2_->field(1);
  663. quux2_ = message2_->field(2);
  664. ASSERT_EQ(1, map_file_->message_type_count());
  665. message3_ = map_file_->message_type(0);
  666. ASSERT_EQ(1, message3_->field_count());
  667. map_ = message3_->field(0);
  668. ASSERT_EQ(1, json_file_->message_type_count());
  669. message4_ = json_file_->message_type(0);
  670. }
  671. void CopyWithJsonName(const Descriptor* message, DescriptorProto* proto) {
  672. message->CopyTo(proto);
  673. message->CopyJsonNameTo(proto);
  674. }
  675. DescriptorPool pool_;
  676. const FileDescriptor* foo_file_;
  677. const FileDescriptor* bar_file_;
  678. const FileDescriptor* map_file_;
  679. const FileDescriptor* json_file_;
  680. const Descriptor* message_;
  681. const Descriptor* message2_;
  682. const Descriptor* message3_;
  683. const Descriptor* message4_;
  684. const Descriptor* foreign_;
  685. const EnumDescriptor* enum_;
  686. const FieldDescriptor* foo_;
  687. const FieldDescriptor* bar_;
  688. const FieldDescriptor* baz_;
  689. const FieldDescriptor* qux_;
  690. const FieldDescriptor* foo2_;
  691. const FieldDescriptor* bar2_;
  692. const FieldDescriptor* quux2_;
  693. const FieldDescriptor* map_;
  694. };
  695. TEST_F(DescriptorTest, Name) {
  696. EXPECT_EQ("TestMessage", message_->name());
  697. EXPECT_EQ("TestMessage", message_->full_name());
  698. EXPECT_EQ(foo_file_, message_->file());
  699. EXPECT_EQ("TestMessage2", message2_->name());
  700. EXPECT_EQ("corge.grault.TestMessage2", message2_->full_name());
  701. EXPECT_EQ(bar_file_, message2_->file());
  702. }
  703. TEST_F(DescriptorTest, ContainingType) {
  704. EXPECT_TRUE(message_->containing_type() == nullptr);
  705. EXPECT_TRUE(message2_->containing_type() == nullptr);
  706. }
  707. TEST_F(DescriptorTest, FieldsByIndex) {
  708. ASSERT_EQ(4, message_->field_count());
  709. EXPECT_EQ(foo_, message_->field(0));
  710. EXPECT_EQ(bar_, message_->field(1));
  711. EXPECT_EQ(baz_, message_->field(2));
  712. EXPECT_EQ(qux_, message_->field(3));
  713. }
  714. TEST_F(DescriptorTest, FindFieldByName) {
  715. // All messages in the same DescriptorPool share a single lookup table for
  716. // fields. So, in addition to testing that FindFieldByName finds the fields
  717. // of the message, we need to test that it does *not* find the fields of
  718. // *other* messages.
  719. EXPECT_EQ(foo_, message_->FindFieldByName("foo"));
  720. EXPECT_EQ(bar_, message_->FindFieldByName("bar"));
  721. EXPECT_EQ(baz_, message_->FindFieldByName("baz"));
  722. EXPECT_EQ(qux_, message_->FindFieldByName("qux"));
  723. EXPECT_TRUE(message_->FindFieldByName("no_such_field") == nullptr);
  724. EXPECT_TRUE(message_->FindFieldByName("quux") == nullptr);
  725. EXPECT_EQ(foo2_, message2_->FindFieldByName("foo"));
  726. EXPECT_EQ(bar2_, message2_->FindFieldByName("bar"));
  727. EXPECT_EQ(quux2_, message2_->FindFieldByName("quux"));
  728. EXPECT_TRUE(message2_->FindFieldByName("baz") == nullptr);
  729. EXPECT_TRUE(message2_->FindFieldByName("qux") == nullptr);
  730. }
  731. TEST_F(DescriptorTest, FindFieldByNumber) {
  732. EXPECT_EQ(foo_, message_->FindFieldByNumber(1));
  733. EXPECT_EQ(bar_, message_->FindFieldByNumber(6));
  734. EXPECT_EQ(baz_, message_->FindFieldByNumber(500000000));
  735. EXPECT_EQ(qux_, message_->FindFieldByNumber(15));
  736. EXPECT_TRUE(message_->FindFieldByNumber(837592) == nullptr);
  737. EXPECT_TRUE(message_->FindFieldByNumber(2) == nullptr);
  738. EXPECT_EQ(foo2_, message2_->FindFieldByNumber(1));
  739. EXPECT_EQ(bar2_, message2_->FindFieldByNumber(2));
  740. EXPECT_EQ(quux2_, message2_->FindFieldByNumber(6));
  741. EXPECT_TRUE(message2_->FindFieldByNumber(15) == nullptr);
  742. EXPECT_TRUE(message2_->FindFieldByNumber(500000000) == nullptr);
  743. }
  744. TEST_F(DescriptorTest, FieldName) {
  745. EXPECT_EQ("foo", foo_->name());
  746. EXPECT_EQ("bar", bar_->name());
  747. EXPECT_EQ("baz", baz_->name());
  748. EXPECT_EQ("qux", qux_->name());
  749. }
  750. TEST_F(DescriptorTest, FieldFullName) {
  751. EXPECT_EQ("TestMessage.foo", foo_->full_name());
  752. EXPECT_EQ("TestMessage.bar", bar_->full_name());
  753. EXPECT_EQ("TestMessage.baz", baz_->full_name());
  754. EXPECT_EQ("TestMessage.qux", qux_->full_name());
  755. EXPECT_EQ("corge.grault.TestMessage2.foo", foo2_->full_name());
  756. EXPECT_EQ("corge.grault.TestMessage2.bar", bar2_->full_name());
  757. EXPECT_EQ("corge.grault.TestMessage2.quux", quux2_->full_name());
  758. }
  759. TEST_F(DescriptorTest, PrintableNameIsFullNameForNonExtensionFields) {
  760. EXPECT_EQ("TestMessage.foo", foo_->PrintableNameForExtension());
  761. EXPECT_EQ("TestMessage.bar", bar_->PrintableNameForExtension());
  762. EXPECT_EQ("TestMessage.baz", baz_->PrintableNameForExtension());
  763. EXPECT_EQ("TestMessage.qux", qux_->PrintableNameForExtension());
  764. EXPECT_EQ("corge.grault.TestMessage2.foo",
  765. foo2_->PrintableNameForExtension());
  766. EXPECT_EQ("corge.grault.TestMessage2.bar",
  767. bar2_->PrintableNameForExtension());
  768. EXPECT_EQ("corge.grault.TestMessage2.quux",
  769. quux2_->PrintableNameForExtension());
  770. }
  771. TEST_F(DescriptorTest, PrintableNameIsFullNameForNonMessageSetExtension) {
  772. EXPECT_EQ("protobuf_unittest.Aggregate.nested",
  773. protobuf_unittest::Aggregate::descriptor()
  774. ->FindExtensionByName("nested")
  775. ->PrintableNameForExtension());
  776. }
  777. TEST_F(DescriptorTest, PrintableNameIsExtendingTypeForMessageSetExtension) {
  778. EXPECT_EQ("protobuf_unittest.AggregateMessageSetElement",
  779. protobuf_unittest::AggregateMessageSetElement::descriptor()
  780. ->FindExtensionByName("message_set_extension")
  781. ->PrintableNameForExtension());
  782. }
  783. TEST_F(DescriptorTest, FieldJsonName) {
  784. EXPECT_EQ("fieldName1", message4_->field(0)->json_name());
  785. EXPECT_EQ("fieldName2", message4_->field(1)->json_name());
  786. EXPECT_EQ("FieldName3", message4_->field(2)->json_name());
  787. EXPECT_EQ("FieldName4", message4_->field(3)->json_name());
  788. EXPECT_EQ("FIELDNAME5", message4_->field(4)->json_name());
  789. EXPECT_EQ("@type", message4_->field(5)->json_name());
  790. DescriptorProto proto;
  791. message4_->CopyTo(&proto);
  792. ASSERT_EQ(6, proto.field_size());
  793. EXPECT_FALSE(proto.field(0).has_json_name());
  794. EXPECT_FALSE(proto.field(1).has_json_name());
  795. EXPECT_FALSE(proto.field(2).has_json_name());
  796. EXPECT_FALSE(proto.field(3).has_json_name());
  797. EXPECT_FALSE(proto.field(4).has_json_name());
  798. EXPECT_EQ("@type", proto.field(5).json_name());
  799. proto.Clear();
  800. CopyWithJsonName(message4_, &proto);
  801. ASSERT_EQ(6, proto.field_size());
  802. EXPECT_EQ("fieldName1", proto.field(0).json_name());
  803. EXPECT_EQ("fieldName2", proto.field(1).json_name());
  804. EXPECT_EQ("FieldName3", proto.field(2).json_name());
  805. EXPECT_EQ("FieldName4", proto.field(3).json_name());
  806. EXPECT_EQ("FIELDNAME5", proto.field(4).json_name());
  807. EXPECT_EQ("@type", proto.field(5).json_name());
  808. // Test generated descriptor.
  809. const Descriptor* generated = protobuf_unittest::TestJsonName::descriptor();
  810. ASSERT_EQ(6, generated->field_count());
  811. EXPECT_EQ("fieldName1", generated->field(0)->json_name());
  812. EXPECT_EQ("fieldName2", generated->field(1)->json_name());
  813. EXPECT_EQ("FieldName3", generated->field(2)->json_name());
  814. EXPECT_EQ("FieldName4", generated->field(3)->json_name());
  815. EXPECT_EQ("FIELDNAME5", generated->field(4)->json_name());
  816. EXPECT_EQ("@type", generated->field(5)->json_name());
  817. }
  818. TEST_F(DescriptorTest, FieldFile) {
  819. EXPECT_EQ(foo_file_, foo_->file());
  820. EXPECT_EQ(foo_file_, bar_->file());
  821. EXPECT_EQ(foo_file_, baz_->file());
  822. EXPECT_EQ(foo_file_, qux_->file());
  823. EXPECT_EQ(bar_file_, foo2_->file());
  824. EXPECT_EQ(bar_file_, bar2_->file());
  825. EXPECT_EQ(bar_file_, quux2_->file());
  826. }
  827. TEST_F(DescriptorTest, FieldIndex) {
  828. EXPECT_EQ(0, foo_->index());
  829. EXPECT_EQ(1, bar_->index());
  830. EXPECT_EQ(2, baz_->index());
  831. EXPECT_EQ(3, qux_->index());
  832. }
  833. TEST_F(DescriptorTest, FieldNumber) {
  834. EXPECT_EQ(1, foo_->number());
  835. EXPECT_EQ(6, bar_->number());
  836. EXPECT_EQ(500000000, baz_->number());
  837. EXPECT_EQ(15, qux_->number());
  838. }
  839. TEST_F(DescriptorTest, FieldType) {
  840. EXPECT_EQ(FieldDescriptor::TYPE_STRING, foo_->type());
  841. EXPECT_EQ(FieldDescriptor::TYPE_ENUM, bar_->type());
  842. EXPECT_EQ(FieldDescriptor::TYPE_MESSAGE, baz_->type());
  843. EXPECT_EQ(FieldDescriptor::TYPE_GROUP, qux_->type());
  844. }
  845. TEST_F(DescriptorTest, FieldLabel) {
  846. EXPECT_EQ(FieldDescriptor::LABEL_REQUIRED, foo_->label());
  847. EXPECT_EQ(FieldDescriptor::LABEL_OPTIONAL, bar_->label());
  848. EXPECT_EQ(FieldDescriptor::LABEL_REPEATED, baz_->label());
  849. EXPECT_EQ(FieldDescriptor::LABEL_OPTIONAL, qux_->label());
  850. EXPECT_TRUE(foo_->is_required());
  851. EXPECT_FALSE(foo_->is_optional());
  852. EXPECT_FALSE(foo_->is_repeated());
  853. EXPECT_FALSE(bar_->is_required());
  854. EXPECT_TRUE(bar_->is_optional());
  855. EXPECT_FALSE(bar_->is_repeated());
  856. EXPECT_FALSE(baz_->is_required());
  857. EXPECT_FALSE(baz_->is_optional());
  858. EXPECT_TRUE(baz_->is_repeated());
  859. }
  860. TEST_F(DescriptorTest, IsMap) {
  861. EXPECT_TRUE(map_->is_map());
  862. EXPECT_FALSE(baz_->is_map());
  863. EXPECT_TRUE(map_->message_type()->options().map_entry());
  864. }
  865. TEST_F(DescriptorTest, FieldHasDefault) {
  866. EXPECT_FALSE(foo_->has_default_value());
  867. EXPECT_FALSE(bar_->has_default_value());
  868. EXPECT_FALSE(baz_->has_default_value());
  869. EXPECT_FALSE(qux_->has_default_value());
  870. }
  871. TEST_F(DescriptorTest, FieldContainingType) {
  872. EXPECT_EQ(message_, foo_->containing_type());
  873. EXPECT_EQ(message_, bar_->containing_type());
  874. EXPECT_EQ(message_, baz_->containing_type());
  875. EXPECT_EQ(message_, qux_->containing_type());
  876. EXPECT_EQ(message2_, foo2_->containing_type());
  877. EXPECT_EQ(message2_, bar2_->containing_type());
  878. EXPECT_EQ(message2_, quux2_->containing_type());
  879. }
  880. TEST_F(DescriptorTest, FieldMessageType) {
  881. EXPECT_TRUE(foo_->message_type() == nullptr);
  882. EXPECT_TRUE(bar_->message_type() == nullptr);
  883. EXPECT_EQ(foreign_, baz_->message_type());
  884. EXPECT_EQ(foreign_, qux_->message_type());
  885. }
  886. TEST_F(DescriptorTest, FieldEnumType) {
  887. EXPECT_TRUE(foo_->enum_type() == nullptr);
  888. EXPECT_TRUE(baz_->enum_type() == nullptr);
  889. EXPECT_TRUE(qux_->enum_type() == nullptr);
  890. EXPECT_EQ(enum_, bar_->enum_type());
  891. }
  892. // ===================================================================
  893. // Test simple flat messages and fields.
  894. class OneofDescriptorTest : public testing::Test {
  895. protected:
  896. virtual void SetUp() {
  897. // Build descriptors for the following definitions:
  898. //
  899. // package garply;
  900. // message TestOneof {
  901. // optional int32 a = 1;
  902. // oneof foo {
  903. // string b = 2;
  904. // TestOneof c = 3;
  905. // }
  906. // oneof bar {
  907. // float d = 4;
  908. // }
  909. // }
  910. FileDescriptorProto baz_file;
  911. baz_file.set_name("baz.proto");
  912. baz_file.set_package("garply");
  913. DescriptorProto* oneof_message = AddMessage(&baz_file, "TestOneof");
  914. oneof_message->add_oneof_decl()->set_name("foo");
  915. oneof_message->add_oneof_decl()->set_name("bar");
  916. AddField(oneof_message, "a", 1, FieldDescriptorProto::LABEL_OPTIONAL,
  917. FieldDescriptorProto::TYPE_INT32);
  918. AddField(oneof_message, "b", 2, FieldDescriptorProto::LABEL_OPTIONAL,
  919. FieldDescriptorProto::TYPE_STRING);
  920. oneof_message->mutable_field(1)->set_oneof_index(0);
  921. AddField(oneof_message, "c", 3, FieldDescriptorProto::LABEL_OPTIONAL,
  922. FieldDescriptorProto::TYPE_MESSAGE);
  923. oneof_message->mutable_field(2)->set_oneof_index(0);
  924. oneof_message->mutable_field(2)->set_type_name("TestOneof");
  925. AddField(oneof_message, "d", 4, FieldDescriptorProto::LABEL_OPTIONAL,
  926. FieldDescriptorProto::TYPE_FLOAT);
  927. oneof_message->mutable_field(3)->set_oneof_index(1);
  928. // Build the descriptors and get the pointers.
  929. baz_file_ = pool_.BuildFile(baz_file);
  930. ASSERT_TRUE(baz_file_ != nullptr);
  931. ASSERT_EQ(1, baz_file_->message_type_count());
  932. oneof_message_ = baz_file_->message_type(0);
  933. ASSERT_EQ(2, oneof_message_->oneof_decl_count());
  934. oneof_ = oneof_message_->oneof_decl(0);
  935. oneof2_ = oneof_message_->oneof_decl(1);
  936. ASSERT_EQ(4, oneof_message_->field_count());
  937. a_ = oneof_message_->field(0);
  938. b_ = oneof_message_->field(1);
  939. c_ = oneof_message_->field(2);
  940. d_ = oneof_message_->field(3);
  941. }
  942. DescriptorPool pool_;
  943. const FileDescriptor* baz_file_;
  944. const Descriptor* oneof_message_;
  945. const OneofDescriptor* oneof_;
  946. const OneofDescriptor* oneof2_;
  947. const FieldDescriptor* a_;
  948. const FieldDescriptor* b_;
  949. const FieldDescriptor* c_;
  950. const FieldDescriptor* d_;
  951. };
  952. TEST_F(OneofDescriptorTest, Normal) {
  953. EXPECT_EQ("foo", oneof_->name());
  954. EXPECT_EQ("garply.TestOneof.foo", oneof_->full_name());
  955. EXPECT_EQ(0, oneof_->index());
  956. ASSERT_EQ(2, oneof_->field_count());
  957. EXPECT_EQ(b_, oneof_->field(0));
  958. EXPECT_EQ(c_, oneof_->field(1));
  959. EXPECT_TRUE(a_->containing_oneof() == nullptr);
  960. EXPECT_EQ(oneof_, b_->containing_oneof());
  961. EXPECT_EQ(oneof_, c_->containing_oneof());
  962. }
  963. TEST_F(OneofDescriptorTest, FindByName) {
  964. EXPECT_EQ(oneof_, oneof_message_->FindOneofByName("foo"));
  965. EXPECT_EQ(oneof2_, oneof_message_->FindOneofByName("bar"));
  966. EXPECT_TRUE(oneof_message_->FindOneofByName("no_such_oneof") == nullptr);
  967. }
  968. // ===================================================================
  969. class StylizedFieldNamesTest : public testing::Test {
  970. protected:
  971. void SetUp() {
  972. FileDescriptorProto file;
  973. file.set_name("foo.proto");
  974. AddExtensionRange(AddMessage(&file, "ExtendableMessage"), 1, 1000);
  975. DescriptorProto* message = AddMessage(&file, "TestMessage");
  976. AddField(message, "foo_foo", 1, FieldDescriptorProto::LABEL_OPTIONAL,
  977. FieldDescriptorProto::TYPE_INT32);
  978. AddField(message, "FooBar", 2, FieldDescriptorProto::LABEL_OPTIONAL,
  979. FieldDescriptorProto::TYPE_INT32);
  980. AddField(message, "fooBaz", 3, FieldDescriptorProto::LABEL_OPTIONAL,
  981. FieldDescriptorProto::TYPE_INT32);
  982. AddField(message, "fooFoo", 4, // Camel-case conflict with foo_foo.
  983. FieldDescriptorProto::LABEL_OPTIONAL,
  984. FieldDescriptorProto::TYPE_INT32);
  985. AddField(message, "foobar", 5, // Lower-case conflict with FooBar.
  986. FieldDescriptorProto::LABEL_OPTIONAL,
  987. FieldDescriptorProto::TYPE_INT32);
  988. AddNestedExtension(message, "ExtendableMessage", "bar_foo", 1,
  989. FieldDescriptorProto::LABEL_OPTIONAL,
  990. FieldDescriptorProto::TYPE_INT32);
  991. AddNestedExtension(message, "ExtendableMessage", "BarBar", 2,
  992. FieldDescriptorProto::LABEL_OPTIONAL,
  993. FieldDescriptorProto::TYPE_INT32);
  994. AddNestedExtension(message, "ExtendableMessage", "BarBaz", 3,
  995. FieldDescriptorProto::LABEL_OPTIONAL,
  996. FieldDescriptorProto::TYPE_INT32);
  997. AddNestedExtension(message, "ExtendableMessage", "barFoo", 4, // Conflict
  998. FieldDescriptorProto::LABEL_OPTIONAL,
  999. FieldDescriptorProto::TYPE_INT32);
  1000. AddNestedExtension(message, "ExtendableMessage", "barbar", 5, // Conflict
  1001. FieldDescriptorProto::LABEL_OPTIONAL,
  1002. FieldDescriptorProto::TYPE_INT32);
  1003. AddExtension(&file, "ExtendableMessage", "baz_foo", 11,
  1004. FieldDescriptorProto::LABEL_OPTIONAL,
  1005. FieldDescriptorProto::TYPE_INT32);
  1006. AddExtension(&file, "ExtendableMessage", "BazBar", 12,
  1007. FieldDescriptorProto::LABEL_OPTIONAL,
  1008. FieldDescriptorProto::TYPE_INT32);
  1009. AddExtension(&file, "ExtendableMessage", "BazBaz", 13,
  1010. FieldDescriptorProto::LABEL_OPTIONAL,
  1011. FieldDescriptorProto::TYPE_INT32);
  1012. AddExtension(&file, "ExtendableMessage", "bazFoo", 14, // Conflict
  1013. FieldDescriptorProto::LABEL_OPTIONAL,
  1014. FieldDescriptorProto::TYPE_INT32);
  1015. AddExtension(&file, "ExtendableMessage", "bazbar", 15, // Conflict
  1016. FieldDescriptorProto::LABEL_OPTIONAL,
  1017. FieldDescriptorProto::TYPE_INT32);
  1018. file_ = pool_.BuildFile(file);
  1019. ASSERT_TRUE(file_ != nullptr);
  1020. ASSERT_EQ(2, file_->message_type_count());
  1021. message_ = file_->message_type(1);
  1022. ASSERT_EQ("TestMessage", message_->name());
  1023. ASSERT_EQ(5, message_->field_count());
  1024. ASSERT_EQ(5, message_->extension_count());
  1025. ASSERT_EQ(5, file_->extension_count());
  1026. }
  1027. DescriptorPool pool_;
  1028. const FileDescriptor* file_;
  1029. const Descriptor* message_;
  1030. };
  1031. TEST_F(StylizedFieldNamesTest, LowercaseName) {
  1032. EXPECT_EQ("foo_foo", message_->field(0)->lowercase_name());
  1033. EXPECT_EQ("foobar", message_->field(1)->lowercase_name());
  1034. EXPECT_EQ("foobaz", message_->field(2)->lowercase_name());
  1035. EXPECT_EQ("foofoo", message_->field(3)->lowercase_name());
  1036. EXPECT_EQ("foobar", message_->field(4)->lowercase_name());
  1037. EXPECT_EQ("bar_foo", message_->extension(0)->lowercase_name());
  1038. EXPECT_EQ("barbar", message_->extension(1)->lowercase_name());
  1039. EXPECT_EQ("barbaz", message_->extension(2)->lowercase_name());
  1040. EXPECT_EQ("barfoo", message_->extension(3)->lowercase_name());
  1041. EXPECT_EQ("barbar", message_->extension(4)->lowercase_name());
  1042. EXPECT_EQ("baz_foo", file_->extension(0)->lowercase_name());
  1043. EXPECT_EQ("bazbar", file_->extension(1)->lowercase_name());
  1044. EXPECT_EQ("bazbaz", file_->extension(2)->lowercase_name());
  1045. EXPECT_EQ("bazfoo", file_->extension(3)->lowercase_name());
  1046. EXPECT_EQ("bazbar", file_->extension(4)->lowercase_name());
  1047. }
  1048. TEST_F(StylizedFieldNamesTest, CamelcaseName) {
  1049. EXPECT_EQ("fooFoo", message_->field(0)->camelcase_name());
  1050. EXPECT_EQ("fooBar", message_->field(1)->camelcase_name());
  1051. EXPECT_EQ("fooBaz", message_->field(2)->camelcase_name());
  1052. EXPECT_EQ("fooFoo", message_->field(3)->camelcase_name());
  1053. EXPECT_EQ("foobar", message_->field(4)->camelcase_name());
  1054. EXPECT_EQ("barFoo", message_->extension(0)->camelcase_name());
  1055. EXPECT_EQ("barBar", message_->extension(1)->camelcase_name());
  1056. EXPECT_EQ("barBaz", message_->extension(2)->camelcase_name());
  1057. EXPECT_EQ("barFoo", message_->extension(3)->camelcase_name());
  1058. EXPECT_EQ("barbar", message_->extension(4)->camelcase_name());
  1059. EXPECT_EQ("bazFoo", file_->extension(0)->camelcase_name());
  1060. EXPECT_EQ("bazBar", file_->extension(1)->camelcase_name());
  1061. EXPECT_EQ("bazBaz", file_->extension(2)->camelcase_name());
  1062. EXPECT_EQ("bazFoo", file_->extension(3)->camelcase_name());
  1063. EXPECT_EQ("bazbar", file_->extension(4)->camelcase_name());
  1064. }
  1065. TEST_F(StylizedFieldNamesTest, FindByLowercaseName) {
  1066. EXPECT_EQ(message_->field(0), message_->FindFieldByLowercaseName("foo_foo"));
  1067. EXPECT_EQ(message_->field(1), message_->FindFieldByLowercaseName("foobar"));
  1068. EXPECT_EQ(message_->field(2), message_->FindFieldByLowercaseName("foobaz"));
  1069. EXPECT_TRUE(message_->FindFieldByLowercaseName("FooBar") == nullptr);
  1070. EXPECT_TRUE(message_->FindFieldByLowercaseName("fooBaz") == nullptr);
  1071. EXPECT_TRUE(message_->FindFieldByLowercaseName("bar_foo") == nullptr);
  1072. EXPECT_TRUE(message_->FindFieldByLowercaseName("nosuchfield") == nullptr);
  1073. EXPECT_EQ(message_->extension(0),
  1074. message_->FindExtensionByLowercaseName("bar_foo"));
  1075. EXPECT_EQ(message_->extension(1),
  1076. message_->FindExtensionByLowercaseName("barbar"));
  1077. EXPECT_EQ(message_->extension(2),
  1078. message_->FindExtensionByLowercaseName("barbaz"));
  1079. EXPECT_TRUE(message_->FindExtensionByLowercaseName("BarBar") == nullptr);
  1080. EXPECT_TRUE(message_->FindExtensionByLowercaseName("barBaz") == nullptr);
  1081. EXPECT_TRUE(message_->FindExtensionByLowercaseName("foo_foo") == nullptr);
  1082. EXPECT_TRUE(message_->FindExtensionByLowercaseName("nosuchfield") == nullptr);
  1083. EXPECT_EQ(file_->extension(0),
  1084. file_->FindExtensionByLowercaseName("baz_foo"));
  1085. EXPECT_EQ(file_->extension(1), file_->FindExtensionByLowercaseName("bazbar"));
  1086. EXPECT_EQ(file_->extension(2), file_->FindExtensionByLowercaseName("bazbaz"));
  1087. EXPECT_TRUE(file_->FindExtensionByLowercaseName("BazBar") == nullptr);
  1088. EXPECT_TRUE(file_->FindExtensionByLowercaseName("bazBaz") == nullptr);
  1089. EXPECT_TRUE(file_->FindExtensionByLowercaseName("nosuchfield") == nullptr);
  1090. }
  1091. TEST_F(StylizedFieldNamesTest, FindByCamelcaseName) {
  1092. EXPECT_EQ(message_->field(0), message_->FindFieldByCamelcaseName("fooFoo"));
  1093. EXPECT_EQ(message_->field(1), message_->FindFieldByCamelcaseName("fooBar"));
  1094. EXPECT_EQ(message_->field(2), message_->FindFieldByCamelcaseName("fooBaz"));
  1095. EXPECT_TRUE(message_->FindFieldByCamelcaseName("foo_foo") == nullptr);
  1096. EXPECT_TRUE(message_->FindFieldByCamelcaseName("FooBar") == nullptr);
  1097. EXPECT_TRUE(message_->FindFieldByCamelcaseName("barFoo") == nullptr);
  1098. EXPECT_TRUE(message_->FindFieldByCamelcaseName("nosuchfield") == nullptr);
  1099. EXPECT_EQ(message_->extension(0),
  1100. message_->FindExtensionByCamelcaseName("barFoo"));
  1101. EXPECT_EQ(message_->extension(1),
  1102. message_->FindExtensionByCamelcaseName("barBar"));
  1103. EXPECT_EQ(message_->extension(2),
  1104. message_->FindExtensionByCamelcaseName("barBaz"));
  1105. EXPECT_TRUE(message_->FindExtensionByCamelcaseName("bar_foo") == nullptr);
  1106. EXPECT_TRUE(message_->FindExtensionByCamelcaseName("BarBar") == nullptr);
  1107. EXPECT_TRUE(message_->FindExtensionByCamelcaseName("fooFoo") == nullptr);
  1108. EXPECT_TRUE(message_->FindExtensionByCamelcaseName("nosuchfield") == nullptr);
  1109. EXPECT_EQ(file_->extension(0), file_->FindExtensionByCamelcaseName("bazFoo"));
  1110. EXPECT_EQ(file_->extension(1), file_->FindExtensionByCamelcaseName("bazBar"));
  1111. EXPECT_EQ(file_->extension(2), file_->FindExtensionByCamelcaseName("bazBaz"));
  1112. EXPECT_TRUE(file_->FindExtensionByCamelcaseName("baz_foo") == nullptr);
  1113. EXPECT_TRUE(file_->FindExtensionByCamelcaseName("BazBar") == nullptr);
  1114. EXPECT_TRUE(file_->FindExtensionByCamelcaseName("nosuchfield") == nullptr);
  1115. }
  1116. // ===================================================================
  1117. // Test enum descriptors.
  1118. class EnumDescriptorTest : public testing::Test {
  1119. protected:
  1120. virtual void SetUp() {
  1121. // Build descriptors for the following definitions:
  1122. //
  1123. // // in "foo.proto"
  1124. // enum TestEnum {
  1125. // FOO = 1;
  1126. // BAR = 2;
  1127. // }
  1128. //
  1129. // // in "bar.proto"
  1130. // package corge.grault;
  1131. // enum TestEnum2 {
  1132. // FOO = 1;
  1133. // BAZ = 3;
  1134. // }
  1135. //
  1136. // TestEnum2 is primarily here to test FindValueByName and friends.
  1137. // All enums created from the same DescriptorPool share the same lookup
  1138. // table, so we need to insure that they don't interfere.
  1139. // TestEnum
  1140. FileDescriptorProto foo_file;
  1141. foo_file.set_name("foo.proto");
  1142. EnumDescriptorProto* enum_proto = AddEnum(&foo_file, "TestEnum");
  1143. AddEnumValue(enum_proto, "FOO", 1);
  1144. AddEnumValue(enum_proto, "BAR", 2);
  1145. // TestEnum2
  1146. FileDescriptorProto bar_file;
  1147. bar_file.set_name("bar.proto");
  1148. bar_file.set_package("corge.grault");
  1149. EnumDescriptorProto* enum2_proto = AddEnum(&bar_file, "TestEnum2");
  1150. AddEnumValue(enum2_proto, "FOO", 1);
  1151. AddEnumValue(enum2_proto, "BAZ", 3);
  1152. // Build the descriptors and get the pointers.
  1153. foo_file_ = pool_.BuildFile(foo_file);
  1154. ASSERT_TRUE(foo_file_ != nullptr);
  1155. bar_file_ = pool_.BuildFile(bar_file);
  1156. ASSERT_TRUE(bar_file_ != nullptr);
  1157. ASSERT_EQ(1, foo_file_->enum_type_count());
  1158. enum_ = foo_file_->enum_type(0);
  1159. ASSERT_EQ(2, enum_->value_count());
  1160. foo_ = enum_->value(0);
  1161. bar_ = enum_->value(1);
  1162. ASSERT_EQ(1, bar_file_->enum_type_count());
  1163. enum2_ = bar_file_->enum_type(0);
  1164. ASSERT_EQ(2, enum2_->value_count());
  1165. foo2_ = enum2_->value(0);
  1166. baz2_ = enum2_->value(1);
  1167. }
  1168. DescriptorPool pool_;
  1169. const FileDescriptor* foo_file_;
  1170. const FileDescriptor* bar_file_;
  1171. const EnumDescriptor* enum_;
  1172. const EnumDescriptor* enum2_;
  1173. const EnumValueDescriptor* foo_;
  1174. const EnumValueDescriptor* bar_;
  1175. const EnumValueDescriptor* foo2_;
  1176. const EnumValueDescriptor* baz2_;
  1177. };
  1178. TEST_F(EnumDescriptorTest, Name) {
  1179. EXPECT_EQ("TestEnum", enum_->name());
  1180. EXPECT_EQ("TestEnum", enum_->full_name());
  1181. EXPECT_EQ(foo_file_, enum_->file());
  1182. EXPECT_EQ("TestEnum2", enum2_->name());
  1183. EXPECT_EQ("corge.grault.TestEnum2", enum2_->full_name());
  1184. EXPECT_EQ(bar_file_, enum2_->file());
  1185. }
  1186. TEST_F(EnumDescriptorTest, ContainingType) {
  1187. EXPECT_TRUE(enum_->containing_type() == nullptr);
  1188. EXPECT_TRUE(enum2_->containing_type() == nullptr);
  1189. }
  1190. TEST_F(EnumDescriptorTest, ValuesByIndex) {
  1191. ASSERT_EQ(2, enum_->value_count());
  1192. EXPECT_EQ(foo_, enum_->value(0));
  1193. EXPECT_EQ(bar_, enum_->value(1));
  1194. }
  1195. TEST_F(EnumDescriptorTest, FindValueByName) {
  1196. EXPECT_EQ(foo_, enum_->FindValueByName("FOO"));
  1197. EXPECT_EQ(bar_, enum_->FindValueByName("BAR"));
  1198. EXPECT_EQ(foo2_, enum2_->FindValueByName("FOO"));
  1199. EXPECT_EQ(baz2_, enum2_->FindValueByName("BAZ"));
  1200. EXPECT_TRUE(enum_->FindValueByName("NO_SUCH_VALUE") == nullptr);
  1201. EXPECT_TRUE(enum_->FindValueByName("BAZ") == nullptr);
  1202. EXPECT_TRUE(enum2_->FindValueByName("BAR") == nullptr);
  1203. }
  1204. TEST_F(EnumDescriptorTest, FindValueByNumber) {
  1205. EXPECT_EQ(foo_, enum_->FindValueByNumber(1));
  1206. EXPECT_EQ(bar_, enum_->FindValueByNumber(2));
  1207. EXPECT_EQ(foo2_, enum2_->FindValueByNumber(1));
  1208. EXPECT_EQ(baz2_, enum2_->FindValueByNumber(3));
  1209. EXPECT_TRUE(enum_->FindValueByNumber(416) == nullptr);
  1210. EXPECT_TRUE(enum_->FindValueByNumber(3) == nullptr);
  1211. EXPECT_TRUE(enum2_->FindValueByNumber(2) == nullptr);
  1212. }
  1213. TEST_F(EnumDescriptorTest, ValueName) {
  1214. EXPECT_EQ("FOO", foo_->name());
  1215. EXPECT_EQ("BAR", bar_->name());
  1216. }
  1217. TEST_F(EnumDescriptorTest, ValueFullName) {
  1218. EXPECT_EQ("FOO", foo_->full_name());
  1219. EXPECT_EQ("BAR", bar_->full_name());
  1220. EXPECT_EQ("corge.grault.FOO", foo2_->full_name());
  1221. EXPECT_EQ("corge.grault.BAZ", baz2_->full_name());
  1222. }
  1223. TEST_F(EnumDescriptorTest, ValueIndex) {
  1224. EXPECT_EQ(0, foo_->index());
  1225. EXPECT_EQ(1, bar_->index());
  1226. }
  1227. TEST_F(EnumDescriptorTest, ValueNumber) {
  1228. EXPECT_EQ(1, foo_->number());
  1229. EXPECT_EQ(2, bar_->number());
  1230. }
  1231. TEST_F(EnumDescriptorTest, ValueType) {
  1232. EXPECT_EQ(enum_, foo_->type());
  1233. EXPECT_EQ(enum_, bar_->type());
  1234. EXPECT_EQ(enum2_, foo2_->type());
  1235. EXPECT_EQ(enum2_, baz2_->type());
  1236. }
  1237. // ===================================================================
  1238. // Test service descriptors.
  1239. class ServiceDescriptorTest : public testing::Test {
  1240. protected:
  1241. virtual void SetUp() {
  1242. // Build descriptors for the following messages and service:
  1243. // // in "foo.proto"
  1244. // message FooRequest {}
  1245. // message FooResponse {}
  1246. // message BarRequest {}
  1247. // message BarResponse {}
  1248. // message BazRequest {}
  1249. // message BazResponse {}
  1250. //
  1251. // service TestService {
  1252. // rpc Foo(FooRequest) returns (FooResponse);
  1253. // rpc Bar(BarRequest) returns (BarResponse);
  1254. // }
  1255. //
  1256. // // in "bar.proto"
  1257. // package corge.grault
  1258. // service TestService2 {
  1259. // rpc Foo(FooRequest) returns (FooResponse);
  1260. // rpc Baz(BazRequest) returns (BazResponse);
  1261. // }
  1262. FileDescriptorProto foo_file;
  1263. foo_file.set_name("foo.proto");
  1264. AddMessage(&foo_file, "FooRequest");
  1265. AddMessage(&foo_file, "FooResponse");
  1266. AddMessage(&foo_file, "BarRequest");
  1267. AddMessage(&foo_file, "BarResponse");
  1268. AddMessage(&foo_file, "BazRequest");
  1269. AddMessage(&foo_file, "BazResponse");
  1270. ServiceDescriptorProto* service = AddService(&foo_file, "TestService");
  1271. AddMethod(service, "Foo", "FooRequest", "FooResponse");
  1272. AddMethod(service, "Bar", "BarRequest", "BarResponse");
  1273. FileDescriptorProto bar_file;
  1274. bar_file.set_name("bar.proto");
  1275. bar_file.set_package("corge.grault");
  1276. bar_file.add_dependency("foo.proto");
  1277. ServiceDescriptorProto* service2 = AddService(&bar_file, "TestService2");
  1278. AddMethod(service2, "Foo", "FooRequest", "FooResponse");
  1279. AddMethod(service2, "Baz", "BazRequest", "BazResponse");
  1280. // Build the descriptors and get the pointers.
  1281. foo_file_ = pool_.BuildFile(foo_file);
  1282. ASSERT_TRUE(foo_file_ != nullptr);
  1283. bar_file_ = pool_.BuildFile(bar_file);
  1284. ASSERT_TRUE(bar_file_ != nullptr);
  1285. ASSERT_EQ(6, foo_file_->message_type_count());
  1286. foo_request_ = foo_file_->message_type(0);
  1287. foo_response_ = foo_file_->message_type(1);
  1288. bar_request_ = foo_file_->message_type(2);
  1289. bar_response_ = foo_file_->message_type(3);
  1290. baz_request_ = foo_file_->message_type(4);
  1291. baz_response_ = foo_file_->message_type(5);
  1292. ASSERT_EQ(1, foo_file_->service_count());
  1293. service_ = foo_file_->service(0);
  1294. ASSERT_EQ(2, service_->method_count());
  1295. foo_ = service_->method(0);
  1296. bar_ = service_->method(1);
  1297. ASSERT_EQ(1, bar_file_->service_count());
  1298. service2_ = bar_file_->service(0);
  1299. ASSERT_EQ(2, service2_->method_count());
  1300. foo2_ = service2_->method(0);
  1301. baz2_ = service2_->method(1);
  1302. }
  1303. DescriptorPool pool_;
  1304. const FileDescriptor* foo_file_;
  1305. const FileDescriptor* bar_file_;
  1306. const Descriptor* foo_request_;
  1307. const Descriptor* foo_response_;
  1308. const Descriptor* bar_request_;
  1309. const Descriptor* bar_response_;
  1310. const Descriptor* baz_request_;
  1311. const Descriptor* baz_response_;
  1312. const ServiceDescriptor* service_;
  1313. const ServiceDescriptor* service2_;
  1314. const MethodDescriptor* foo_;
  1315. const MethodDescriptor* bar_;
  1316. const MethodDescriptor* foo2_;
  1317. const MethodDescriptor* baz2_;
  1318. };
  1319. TEST_F(ServiceDescriptorTest, Name) {
  1320. EXPECT_EQ("TestService", service_->name());
  1321. EXPECT_EQ("TestService", service_->full_name());
  1322. EXPECT_EQ(foo_file_, service_->file());
  1323. EXPECT_EQ("TestService2", service2_->name());
  1324. EXPECT_EQ("corge.grault.TestService2", service2_->full_name());
  1325. EXPECT_EQ(bar_file_, service2_->file());
  1326. }
  1327. TEST_F(ServiceDescriptorTest, MethodsByIndex) {
  1328. ASSERT_EQ(2, service_->method_count());
  1329. EXPECT_EQ(foo_, service_->method(0));
  1330. EXPECT_EQ(bar_, service_->method(1));
  1331. }
  1332. TEST_F(ServiceDescriptorTest, FindMethodByName) {
  1333. EXPECT_EQ(foo_, service_->FindMethodByName("Foo"));
  1334. EXPECT_EQ(bar_, service_->FindMethodByName("Bar"));
  1335. EXPECT_EQ(foo2_, service2_->FindMethodByName("Foo"));
  1336. EXPECT_EQ(baz2_, service2_->FindMethodByName("Baz"));
  1337. EXPECT_TRUE(service_->FindMethodByName("NoSuchMethod") == nullptr);
  1338. EXPECT_TRUE(service_->FindMethodByName("Baz") == nullptr);
  1339. EXPECT_TRUE(service2_->FindMethodByName("Bar") == nullptr);
  1340. }
  1341. TEST_F(ServiceDescriptorTest, MethodName) {
  1342. EXPECT_EQ("Foo", foo_->name());
  1343. EXPECT_EQ("Bar", bar_->name());
  1344. }
  1345. TEST_F(ServiceDescriptorTest, MethodFullName) {
  1346. EXPECT_EQ("TestService.Foo", foo_->full_name());
  1347. EXPECT_EQ("TestService.Bar", bar_->full_name());
  1348. EXPECT_EQ("corge.grault.TestService2.Foo", foo2_->full_name());
  1349. EXPECT_EQ("corge.grault.TestService2.Baz", baz2_->full_name());
  1350. }
  1351. TEST_F(ServiceDescriptorTest, MethodIndex) {
  1352. EXPECT_EQ(0, foo_->index());
  1353. EXPECT_EQ(1, bar_->index());
  1354. }
  1355. TEST_F(ServiceDescriptorTest, MethodParent) {
  1356. EXPECT_EQ(service_, foo_->service());
  1357. EXPECT_EQ(service_, bar_->service());
  1358. }
  1359. TEST_F(ServiceDescriptorTest, MethodInputType) {
  1360. EXPECT_EQ(foo_request_, foo_->input_type());
  1361. EXPECT_EQ(bar_request_, bar_->input_type());
  1362. }
  1363. TEST_F(ServiceDescriptorTest, MethodOutputType) {
  1364. EXPECT_EQ(foo_response_, foo_->output_type());
  1365. EXPECT_EQ(bar_response_, bar_->output_type());
  1366. }
  1367. // ===================================================================
  1368. // Test nested types.
  1369. class NestedDescriptorTest : public testing::Test {
  1370. protected:
  1371. virtual void SetUp() {
  1372. // Build descriptors for the following definitions:
  1373. //
  1374. // // in "foo.proto"
  1375. // message TestMessage {
  1376. // message Foo {}
  1377. // message Bar {}
  1378. // enum Baz { A = 1; }
  1379. // enum Qux { B = 1; }
  1380. // }
  1381. //
  1382. // // in "bar.proto"
  1383. // package corge.grault;
  1384. // message TestMessage2 {
  1385. // message Foo {}
  1386. // message Baz {}
  1387. // enum Qux { A = 1; }
  1388. // enum Quux { C = 1; }
  1389. // }
  1390. //
  1391. // TestMessage2 is primarily here to test FindNestedTypeByName and friends.
  1392. // All messages created from the same DescriptorPool share the same lookup
  1393. // table, so we need to insure that they don't interfere.
  1394. //
  1395. // We add enum values to the enums in order to test searching for enum
  1396. // values across a message's scope.
  1397. FileDescriptorProto foo_file;
  1398. foo_file.set_name("foo.proto");
  1399. DescriptorProto* message = AddMessage(&foo_file, "TestMessage");
  1400. AddNestedMessage(message, "Foo");
  1401. AddNestedMessage(message, "Bar");
  1402. EnumDescriptorProto* baz = AddNestedEnum(message, "Baz");
  1403. AddEnumValue(baz, "A", 1);
  1404. EnumDescriptorProto* qux = AddNestedEnum(message, "Qux");
  1405. AddEnumValue(qux, "B", 1);
  1406. FileDescriptorProto bar_file;
  1407. bar_file.set_name("bar.proto");
  1408. bar_file.set_package("corge.grault");
  1409. DescriptorProto* message2 = AddMessage(&bar_file, "TestMessage2");
  1410. AddNestedMessage(message2, "Foo");
  1411. AddNestedMessage(message2, "Baz");
  1412. EnumDescriptorProto* qux2 = AddNestedEnum(message2, "Qux");
  1413. AddEnumValue(qux2, "A", 1);
  1414. EnumDescriptorProto* quux2 = AddNestedEnum(message2, "Quux");
  1415. AddEnumValue(quux2, "C", 1);
  1416. // Build the descriptors and get the pointers.
  1417. foo_file_ = pool_.BuildFile(foo_file);
  1418. ASSERT_TRUE(foo_file_ != nullptr);
  1419. bar_file_ = pool_.BuildFile(bar_file);
  1420. ASSERT_TRUE(bar_file_ != nullptr);
  1421. ASSERT_EQ(1, foo_file_->message_type_count());
  1422. message_ = foo_file_->message_type(0);
  1423. ASSERT_EQ(2, message_->nested_type_count());
  1424. foo_ = message_->nested_type(0);
  1425. bar_ = message_->nested_type(1);
  1426. ASSERT_EQ(2, message_->enum_type_count());
  1427. baz_ = message_->enum_type(0);
  1428. qux_ = message_->enum_type(1);
  1429. ASSERT_EQ(1, baz_->value_count());
  1430. a_ = baz_->value(0);
  1431. ASSERT_EQ(1, qux_->value_count());
  1432. b_ = qux_->value(0);
  1433. ASSERT_EQ(1, bar_file_->message_type_count());
  1434. message2_ = bar_file_->message_type(0);
  1435. ASSERT_EQ(2, message2_->nested_type_count());
  1436. foo2_ = message2_->nested_type(0);
  1437. baz2_ = message2_->nested_type(1);
  1438. ASSERT_EQ(2, message2_->enum_type_count());
  1439. qux2_ = message2_->enum_type(0);
  1440. quux2_ = message2_->enum_type(1);
  1441. ASSERT_EQ(1, qux2_->value_count());
  1442. a2_ = qux2_->value(0);
  1443. ASSERT_EQ(1, quux2_->value_count());
  1444. c2_ = quux2_->value(0);
  1445. }
  1446. DescriptorPool pool_;
  1447. const FileDescriptor* foo_file_;
  1448. const FileDescriptor* bar_file_;
  1449. const Descriptor* message_;
  1450. const Descriptor* message2_;
  1451. const Descriptor* foo_;
  1452. const Descriptor* bar_;
  1453. const EnumDescriptor* baz_;
  1454. const EnumDescriptor* qux_;
  1455. const EnumValueDescriptor* a_;
  1456. const EnumValueDescriptor* b_;
  1457. const Descriptor* foo2_;
  1458. const Descriptor* baz2_;
  1459. const EnumDescriptor* qux2_;
  1460. const EnumDescriptor* quux2_;
  1461. const EnumValueDescriptor* a2_;
  1462. const EnumValueDescriptor* c2_;
  1463. };
  1464. TEST_F(NestedDescriptorTest, MessageName) {
  1465. EXPECT_EQ("Foo", foo_->name());
  1466. EXPECT_EQ("Bar", bar_->name());
  1467. EXPECT_EQ("Foo", foo2_->name());
  1468. EXPECT_EQ("Baz", baz2_->name());
  1469. EXPECT_EQ("TestMessage.Foo", foo_->full_name());
  1470. EXPECT_EQ("TestMessage.Bar", bar_->full_name());
  1471. EXPECT_EQ("corge.grault.TestMessage2.Foo", foo2_->full_name());
  1472. EXPECT_EQ("corge.grault.TestMessage2.Baz", baz2_->full_name());
  1473. }
  1474. TEST_F(NestedDescriptorTest, MessageContainingType) {
  1475. EXPECT_EQ(message_, foo_->containing_type());
  1476. EXPECT_EQ(message_, bar_->containing_type());
  1477. EXPECT_EQ(message2_, foo2_->containing_type());
  1478. EXPECT_EQ(message2_, baz2_->containing_type());
  1479. }
  1480. TEST_F(NestedDescriptorTest, NestedMessagesByIndex) {
  1481. ASSERT_EQ(2, message_->nested_type_count());
  1482. EXPECT_EQ(foo_, message_->nested_type(0));
  1483. EXPECT_EQ(bar_, message_->nested_type(1));
  1484. }
  1485. TEST_F(NestedDescriptorTest, FindFieldByNameDoesntFindNestedTypes) {
  1486. EXPECT_TRUE(message_->FindFieldByName("Foo") == nullptr);
  1487. EXPECT_TRUE(message_->FindFieldByName("Qux") == nullptr);
  1488. EXPECT_TRUE(message_->FindExtensionByName("Foo") == nullptr);
  1489. EXPECT_TRUE(message_->FindExtensionByName("Qux") == nullptr);
  1490. }
  1491. TEST_F(NestedDescriptorTest, FindNestedTypeByName) {
  1492. EXPECT_EQ(foo_, message_->FindNestedTypeByName("Foo"));
  1493. EXPECT_EQ(bar_, message_->FindNestedTypeByName("Bar"));
  1494. EXPECT_EQ(foo2_, message2_->FindNestedTypeByName("Foo"));
  1495. EXPECT_EQ(baz2_, message2_->FindNestedTypeByName("Baz"));
  1496. EXPECT_TRUE(message_->FindNestedTypeByName("NoSuchType") == nullptr);
  1497. EXPECT_TRUE(message_->FindNestedTypeByName("Baz") == nullptr);
  1498. EXPECT_TRUE(message2_->FindNestedTypeByName("Bar") == nullptr);
  1499. EXPECT_TRUE(message_->FindNestedTypeByName("Qux") == nullptr);
  1500. }
  1501. TEST_F(NestedDescriptorTest, EnumName) {
  1502. EXPECT_EQ("Baz", baz_->name());
  1503. EXPECT_EQ("Qux", qux_->name());
  1504. EXPECT_EQ("Qux", qux2_->name());
  1505. EXPECT_EQ("Quux", quux2_->name());
  1506. EXPECT_EQ("TestMessage.Baz", baz_->full_name());
  1507. EXPECT_EQ("TestMessage.Qux", qux_->full_name());
  1508. EXPECT_EQ("corge.grault.TestMessage2.Qux", qux2_->full_name());
  1509. EXPECT_EQ("corge.grault.TestMessage2.Quux", quux2_->full_name());
  1510. }
  1511. TEST_F(NestedDescriptorTest, EnumContainingType) {
  1512. EXPECT_EQ(message_, baz_->containing_type());
  1513. EXPECT_EQ(message_, qux_->containing_type());
  1514. EXPECT_EQ(message2_, qux2_->containing_type());
  1515. EXPECT_EQ(message2_, quux2_->containing_type());
  1516. }
  1517. TEST_F(NestedDescriptorTest, NestedEnumsByIndex) {
  1518. ASSERT_EQ(2, message_->nested_type_count());
  1519. EXPECT_EQ(foo_, message_->nested_type(0));
  1520. EXPECT_EQ(bar_, message_->nested_type(1));
  1521. }
  1522. TEST_F(NestedDescriptorTest, FindEnumTypeByName) {
  1523. EXPECT_EQ(baz_, message_->FindEnumTypeByName("Baz"));
  1524. EXPECT_EQ(qux_, message_->FindEnumTypeByName("Qux"));
  1525. EXPECT_EQ(qux2_, message2_->FindEnumTypeByName("Qux"));
  1526. EXPECT_EQ(quux2_, message2_->FindEnumTypeByName("Quux"));
  1527. EXPECT_TRUE(message_->FindEnumTypeByName("NoSuchType") == nullptr);
  1528. EXPECT_TRUE(message_->FindEnumTypeByName("Quux") == nullptr);
  1529. EXPECT_TRUE(message2_->FindEnumTypeByName("Baz") == nullptr);
  1530. EXPECT_TRUE(message_->FindEnumTypeByName("Foo") == nullptr);
  1531. }
  1532. TEST_F(NestedDescriptorTest, FindEnumValueByName) {
  1533. EXPECT_EQ(a_, message_->FindEnumValueByName("A"));
  1534. EXPECT_EQ(b_, message_->FindEnumValueByName("B"));
  1535. EXPECT_EQ(a2_, message2_->FindEnumValueByName("A"));
  1536. EXPECT_EQ(c2_, message2_->FindEnumValueByName("C"));
  1537. EXPECT_TRUE(message_->FindEnumValueByName("NO_SUCH_VALUE") == nullptr);
  1538. EXPECT_TRUE(message_->FindEnumValueByName("C") == nullptr);
  1539. EXPECT_TRUE(message2_->FindEnumValueByName("B") == nullptr);
  1540. EXPECT_TRUE(message_->FindEnumValueByName("Foo") == nullptr);
  1541. }
  1542. // ===================================================================
  1543. // Test extensions.
  1544. class ExtensionDescriptorTest : public testing::Test {
  1545. protected:
  1546. virtual void SetUp() {
  1547. // Build descriptors for the following definitions:
  1548. //
  1549. // enum Baz {}
  1550. // message Qux {}
  1551. //
  1552. // message Foo {
  1553. // extensions 10 to 19;
  1554. // extensions 30 to 39;
  1555. // }
  1556. // extends Foo with optional int32 foo_int32 = 10;
  1557. // extends Foo with repeated TestEnum foo_enum = 19;
  1558. // message Bar {
  1559. // extends Foo with optional Qux foo_message = 30;
  1560. // // (using Qux as the group type)
  1561. // extends Foo with repeated group foo_group = 39;
  1562. // }
  1563. FileDescriptorProto foo_file;
  1564. foo_file.set_name("foo.proto");
  1565. AddEmptyEnum(&foo_file, "Baz");
  1566. AddMessage(&foo_file, "Qux");
  1567. DescriptorProto* foo = AddMessage(&foo_file, "Foo");
  1568. AddExtensionRange(foo, 10, 20);
  1569. AddExtensionRange(foo, 30, 40);
  1570. AddExtension(&foo_file, "Foo", "foo_int32", 10,
  1571. FieldDescriptorProto::LABEL_OPTIONAL,
  1572. FieldDescriptorProto::TYPE_INT32);
  1573. AddExtension(&foo_file, "Foo", "foo_enum", 19,
  1574. FieldDescriptorProto::LABEL_REPEATED,
  1575. FieldDescriptorProto::TYPE_ENUM)
  1576. ->set_type_name("Baz");
  1577. DescriptorProto* bar = AddMessage(&foo_file, "Bar");
  1578. AddNestedExtension(bar, "Foo", "foo_message", 30,
  1579. FieldDescriptorProto::LABEL_OPTIONAL,
  1580. FieldDescriptorProto::TYPE_MESSAGE)
  1581. ->set_type_name("Qux");
  1582. AddNestedExtension(bar, "Foo", "foo_group", 39,
  1583. FieldDescriptorProto::LABEL_REPEATED,
  1584. FieldDescriptorProto::TYPE_GROUP)
  1585. ->set_type_name("Qux");
  1586. // Build the descriptors and get the pointers.
  1587. foo_file_ = pool_.BuildFile(foo_file);
  1588. ASSERT_TRUE(foo_file_ != nullptr);
  1589. ASSERT_EQ(1, foo_file_->enum_type_count());
  1590. baz_ = foo_file_->enum_type(0);
  1591. ASSERT_EQ(3, foo_file_->message_type_count());
  1592. qux_ = foo_file_->message_type(0);
  1593. foo_ = foo_file_->message_type(1);
  1594. bar_ = foo_file_->message_type(2);
  1595. }
  1596. DescriptorPool pool_;
  1597. const FileDescriptor* foo_file_;
  1598. const Descriptor* foo_;
  1599. const Descriptor* bar_;
  1600. const EnumDescriptor* baz_;
  1601. const Descriptor* qux_;
  1602. };
  1603. TEST_F(ExtensionDescriptorTest, ExtensionRanges) {
  1604. EXPECT_EQ(0, bar_->extension_range_count());
  1605. ASSERT_EQ(2, foo_->extension_range_count());
  1606. EXPECT_EQ(10, foo_->extension_range(0)->start);
  1607. EXPECT_EQ(30, foo_->extension_range(1)->start);
  1608. EXPECT_EQ(20, foo_->extension_range(0)->end);
  1609. EXPECT_EQ(40, foo_->extension_range(1)->end);
  1610. };
  1611. TEST_F(ExtensionDescriptorTest, Extensions) {
  1612. EXPECT_EQ(0, foo_->extension_count());
  1613. ASSERT_EQ(2, foo_file_->extension_count());
  1614. ASSERT_EQ(2, bar_->extension_count());
  1615. EXPECT_TRUE(foo_file_->extension(0)->is_extension());
  1616. EXPECT_TRUE(foo_file_->extension(1)->is_extension());
  1617. EXPECT_TRUE(bar_->extension(0)->is_extension());
  1618. EXPECT_TRUE(bar_->extension(1)->is_extension());
  1619. EXPECT_EQ("foo_int32", foo_file_->extension(0)->name());
  1620. EXPECT_EQ("foo_enum", foo_file_->extension(1)->name());
  1621. EXPECT_EQ("foo_message", bar_->extension(0)->name());
  1622. EXPECT_EQ("foo_group", bar_->extension(1)->name());
  1623. EXPECT_EQ(10, foo_file_->extension(0)->number());
  1624. EXPECT_EQ(19, foo_file_->extension(1)->number());
  1625. EXPECT_EQ(30, bar_->extension(0)->number());
  1626. EXPECT_EQ(39, bar_->extension(1)->number());
  1627. EXPECT_EQ(FieldDescriptor::TYPE_INT32, foo_file_->extension(0)->type());
  1628. EXPECT_EQ(FieldDescriptor::TYPE_ENUM, foo_file_->extension(1)->type());
  1629. EXPECT_EQ(FieldDescriptor::TYPE_MESSAGE, bar_->extension(0)->type());
  1630. EXPECT_EQ(FieldDescriptor::TYPE_GROUP, bar_->extension(1)->type());
  1631. EXPECT_EQ(baz_, foo_file_->extension(1)->enum_type());
  1632. EXPECT_EQ(qux_, bar_->extension(0)->message_type());
  1633. EXPECT_EQ(qux_, bar_->extension(1)->message_type());
  1634. EXPECT_EQ(FieldDescriptor::LABEL_OPTIONAL, foo_file_->extension(0)->label());
  1635. EXPECT_EQ(FieldDescriptor::LABEL_REPEATED, foo_file_->extension(1)->label());
  1636. EXPECT_EQ(FieldDescriptor::LABEL_OPTIONAL, bar_->extension(0)->label());
  1637. EXPECT_EQ(FieldDescriptor::LABEL_REPEATED, bar_->extension(1)->label());
  1638. EXPECT_EQ(foo_, foo_file_->extension(0)->containing_type());
  1639. EXPECT_EQ(foo_, foo_file_->extension(1)->containing_type());
  1640. EXPECT_EQ(foo_, bar_->extension(0)->containing_type());
  1641. EXPECT_EQ(foo_, bar_->extension(1)->containing_type());
  1642. EXPECT_TRUE(foo_file_->extension(0)->extension_scope() == nullptr);
  1643. EXPECT_TRUE(foo_file_->extension(1)->extension_scope() == nullptr);
  1644. EXPECT_EQ(bar_, bar_->extension(0)->extension_scope());
  1645. EXPECT_EQ(bar_, bar_->extension(1)->extension_scope());
  1646. };
  1647. TEST_F(ExtensionDescriptorTest, IsExtensionNumber) {
  1648. EXPECT_FALSE(foo_->IsExtensionNumber(9));
  1649. EXPECT_TRUE(foo_->IsExtensionNumber(10));
  1650. EXPECT_TRUE(foo_->IsExtensionNumber(19));
  1651. EXPECT_FALSE(foo_->IsExtensionNumber(20));
  1652. EXPECT_FALSE(foo_->IsExtensionNumber(29));
  1653. EXPECT_TRUE(foo_->IsExtensionNumber(30));
  1654. EXPECT_TRUE(foo_->IsExtensionNumber(39));
  1655. EXPECT_FALSE(foo_->IsExtensionNumber(40));
  1656. }
  1657. TEST_F(ExtensionDescriptorTest, FindExtensionByName) {
  1658. // Note that FileDescriptor::FindExtensionByName() is tested by
  1659. // FileDescriptorTest.
  1660. ASSERT_EQ(2, bar_->extension_count());
  1661. EXPECT_EQ(bar_->extension(0), bar_->FindExtensionByName("foo_message"));
  1662. EXPECT_EQ(bar_->extension(1), bar_->FindExtensionByName("foo_group"));
  1663. EXPECT_TRUE(bar_->FindExtensionByName("no_such_extension") == nullptr);
  1664. EXPECT_TRUE(foo_->FindExtensionByName("foo_int32") == nullptr);
  1665. EXPECT_TRUE(foo_->FindExtensionByName("foo_message") == nullptr);
  1666. }
  1667. TEST_F(ExtensionDescriptorTest, FindExtensionByPrintableName) {
  1668. EXPECT_TRUE(pool_.FindExtensionByPrintableName(foo_, "no_such_extension") ==
  1669. nullptr);
  1670. EXPECT_TRUE(pool_.FindExtensionByPrintableName(bar_, "no_such_extension") ==
  1671. nullptr);
  1672. ASSERT_FALSE(pool_.FindExtensionByPrintableName(foo_, "Bar.foo_message") ==
  1673. nullptr);
  1674. ASSERT_FALSE(pool_.FindExtensionByPrintableName(foo_, "Bar.foo_group") ==
  1675. nullptr);
  1676. EXPECT_TRUE(pool_.FindExtensionByPrintableName(bar_, "foo_message") ==
  1677. nullptr);
  1678. EXPECT_TRUE(pool_.FindExtensionByPrintableName(bar_, "foo_group") == nullptr);
  1679. EXPECT_EQ(bar_->FindExtensionByName("foo_message"),
  1680. pool_.FindExtensionByPrintableName(foo_, "Bar.foo_message"));
  1681. EXPECT_EQ(bar_->FindExtensionByName("foo_group"),
  1682. pool_.FindExtensionByPrintableName(foo_, "Bar.foo_group"));
  1683. ASSERT_FALSE(pool_.FindExtensionByPrintableName(foo_, "foo_int32") ==
  1684. nullptr);
  1685. ASSERT_FALSE(pool_.FindExtensionByPrintableName(foo_, "foo_enum") == nullptr);
  1686. EXPECT_TRUE(pool_.FindExtensionByPrintableName(bar_, "foo_int32") == nullptr);
  1687. EXPECT_TRUE(pool_.FindExtensionByPrintableName(bar_, "foo_enum") == nullptr);
  1688. EXPECT_EQ(foo_file_->FindExtensionByName("foo_int32"),
  1689. pool_.FindExtensionByPrintableName(foo_, "foo_int32"));
  1690. EXPECT_EQ(foo_file_->FindExtensionByName("foo_enum"),
  1691. pool_.FindExtensionByPrintableName(foo_, "foo_enum"));
  1692. }
  1693. TEST_F(ExtensionDescriptorTest, FindAllExtensions) {
  1694. std::vector<const FieldDescriptor*> extensions;
  1695. pool_.FindAllExtensions(foo_, &extensions);
  1696. ASSERT_EQ(4, extensions.size());
  1697. EXPECT_EQ(10, extensions[0]->number());
  1698. EXPECT_EQ(19, extensions[1]->number());
  1699. EXPECT_EQ(30, extensions[2]->number());
  1700. EXPECT_EQ(39, extensions[3]->number());
  1701. }
  1702. TEST_F(ExtensionDescriptorTest, DuplicateFieldNumber) {
  1703. DescriptorPool pool;
  1704. FileDescriptorProto file_proto;
  1705. // Add "google/protobuf/descriptor.proto".
  1706. FileDescriptorProto::descriptor()->file()->CopyTo(&file_proto);
  1707. ASSERT_TRUE(pool.BuildFile(file_proto) != nullptr);
  1708. // Add "foo.proto":
  1709. // import "google/protobuf/descriptor.proto";
  1710. // extend google.protobuf.FieldOptions {
  1711. // optional int32 option1 = 1000;
  1712. // }
  1713. file_proto.Clear();
  1714. file_proto.set_name("foo.proto");
  1715. file_proto.add_dependency("google/protobuf/descriptor.proto");
  1716. AddExtension(&file_proto, "google.protobuf.FieldOptions", "option1", 1000,
  1717. FieldDescriptorProto::LABEL_OPTIONAL,
  1718. FieldDescriptorProto::TYPE_INT32);
  1719. ASSERT_TRUE(pool.BuildFile(file_proto) != nullptr);
  1720. // Add "bar.proto":
  1721. // import "google/protobuf/descriptor.proto";
  1722. // extend google.protobuf.FieldOptions {
  1723. // optional int32 option2 = 1000;
  1724. // }
  1725. file_proto.Clear();
  1726. file_proto.set_name("bar.proto");
  1727. file_proto.add_dependency("google/protobuf/descriptor.proto");
  1728. AddExtension(&file_proto, "google.protobuf.FieldOptions", "option2", 1000,
  1729. FieldDescriptorProto::LABEL_OPTIONAL,
  1730. FieldDescriptorProto::TYPE_INT32);
  1731. // Currently we only generate a warning for conflicting extension numbers.
  1732. // TODO(xiaofeng): Change it to an error.
  1733. ASSERT_TRUE(pool.BuildFile(file_proto) != nullptr);
  1734. }
  1735. // ===================================================================
  1736. // Test reserved fields.
  1737. class ReservedDescriptorTest : public testing::Test {
  1738. protected:
  1739. virtual void SetUp() {
  1740. // Build descriptors for the following definitions:
  1741. //
  1742. // message Foo {
  1743. // reserved 2, 9 to 11, 15;
  1744. // reserved "foo", "bar";
  1745. // }
  1746. FileDescriptorProto foo_file;
  1747. foo_file.set_name("foo.proto");
  1748. DescriptorProto* foo = AddMessage(&foo_file, "Foo");
  1749. AddReservedRange(foo, 2, 3);
  1750. AddReservedRange(foo, 9, 12);
  1751. AddReservedRange(foo, 15, 16);
  1752. foo->add_reserved_name("foo");
  1753. foo->add_reserved_name("bar");
  1754. // Build the descriptors and get the pointers.
  1755. foo_file_ = pool_.BuildFile(foo_file);
  1756. ASSERT_TRUE(foo_file_ != nullptr);
  1757. ASSERT_EQ(1, foo_file_->message_type_count());
  1758. foo_ = foo_file_->message_type(0);
  1759. }
  1760. DescriptorPool pool_;
  1761. const FileDescriptor* foo_file_;
  1762. const Descriptor* foo_;
  1763. };
  1764. TEST_F(ReservedDescriptorTest, ReservedRanges) {
  1765. ASSERT_EQ(3, foo_->reserved_range_count());
  1766. EXPECT_EQ(2, foo_->reserved_range(0)->start);
  1767. EXPECT_EQ(3, foo_->reserved_range(0)->end);
  1768. EXPECT_EQ(9, foo_->reserved_range(1)->start);
  1769. EXPECT_EQ(12, foo_->reserved_range(1)->end);
  1770. EXPECT_EQ(15, foo_->reserved_range(2)->start);
  1771. EXPECT_EQ(16, foo_->reserved_range(2)->end);
  1772. };
  1773. TEST_F(ReservedDescriptorTest, IsReservedNumber) {
  1774. EXPECT_FALSE(foo_->IsReservedNumber(1));
  1775. EXPECT_TRUE(foo_->IsReservedNumber(2));
  1776. EXPECT_FALSE(foo_->IsReservedNumber(3));
  1777. EXPECT_FALSE(foo_->IsReservedNumber(8));
  1778. EXPECT_TRUE(foo_->IsReservedNumber(9));
  1779. EXPECT_TRUE(foo_->IsReservedNumber(10));
  1780. EXPECT_TRUE(foo_->IsReservedNumber(11));
  1781. EXPECT_FALSE(foo_->IsReservedNumber(12));
  1782. EXPECT_FALSE(foo_->IsReservedNumber(13));
  1783. EXPECT_FALSE(foo_->IsReservedNumber(14));
  1784. EXPECT_TRUE(foo_->IsReservedNumber(15));
  1785. EXPECT_FALSE(foo_->IsReservedNumber(16));
  1786. };
  1787. TEST_F(ReservedDescriptorTest, ReservedNames) {
  1788. ASSERT_EQ(2, foo_->reserved_name_count());
  1789. EXPECT_EQ("foo", foo_->reserved_name(0));
  1790. EXPECT_EQ("bar", foo_->reserved_name(1));
  1791. };
  1792. TEST_F(ReservedDescriptorTest, IsReservedName) {
  1793. EXPECT_TRUE(foo_->IsReservedName("foo"));
  1794. EXPECT_TRUE(foo_->IsReservedName("bar"));
  1795. EXPECT_FALSE(foo_->IsReservedName("baz"));
  1796. };
  1797. // ===================================================================
  1798. // Test reserved enum fields.
  1799. class ReservedEnumDescriptorTest : public testing::Test {
  1800. protected:
  1801. virtual void SetUp() {
  1802. // Build descriptors for the following definitions:
  1803. //
  1804. // enum Foo {
  1805. // BAR = 1;
  1806. // reserved 2, 9 to 11, 15;
  1807. // reserved "foo", "bar";
  1808. // }
  1809. FileDescriptorProto foo_file;
  1810. foo_file.set_name("foo.proto");
  1811. EnumDescriptorProto* foo = AddEnum(&foo_file, "Foo");
  1812. EnumDescriptorProto* edge1 = AddEnum(&foo_file, "Edge1");
  1813. EnumDescriptorProto* edge2 = AddEnum(&foo_file, "Edge2");
  1814. AddEnumValue(foo, "BAR", 4);
  1815. AddReservedRange(foo, -5, -3);
  1816. AddReservedRange(foo, -2, 1);
  1817. AddReservedRange(foo, 2, 3);
  1818. AddReservedRange(foo, 9, 12);
  1819. AddReservedRange(foo, 15, 16);
  1820. foo->add_reserved_name("foo");
  1821. foo->add_reserved_name("bar");
  1822. // Some additional edge cases that cover most or all of the range of enum
  1823. // values
  1824. // Note: We use INT_MAX as the maximum reserved range upper bound,
  1825. // inclusive.
  1826. AddEnumValue(edge1, "EDGE1", 1);
  1827. AddReservedRange(edge1, 10, INT_MAX);
  1828. AddEnumValue(edge2, "EDGE2", 15);
  1829. AddReservedRange(edge2, INT_MIN, 10);
  1830. // Build the descriptors and get the pointers.
  1831. foo_file_ = pool_.BuildFile(foo_file);
  1832. ASSERT_TRUE(foo_file_ != nullptr);
  1833. ASSERT_EQ(3, foo_file_->enum_type_count());
  1834. foo_ = foo_file_->enum_type(0);
  1835. edge1_ = foo_file_->enum_type(1);
  1836. edge2_ = foo_file_->enum_type(2);
  1837. }
  1838. DescriptorPool pool_;
  1839. const FileDescriptor* foo_file_;
  1840. const EnumDescriptor* foo_;
  1841. const EnumDescriptor* edge1_;
  1842. const EnumDescriptor* edge2_;
  1843. };
  1844. TEST_F(ReservedEnumDescriptorTest, ReservedRanges) {
  1845. ASSERT_EQ(5, foo_->reserved_range_count());
  1846. EXPECT_EQ(-5, foo_->reserved_range(0)->start);
  1847. EXPECT_EQ(-3, foo_->reserved_range(0)->end);
  1848. EXPECT_EQ(-2, foo_->reserved_range(1)->start);
  1849. EXPECT_EQ(1, foo_->reserved_range(1)->end);
  1850. EXPECT_EQ(2, foo_->reserved_range(2)->start);
  1851. EXPECT_EQ(3, foo_->reserved_range(2)->end);
  1852. EXPECT_EQ(9, foo_->reserved_range(3)->start);
  1853. EXPECT_EQ(12, foo_->reserved_range(3)->end);
  1854. EXPECT_EQ(15, foo_->reserved_range(4)->start);
  1855. EXPECT_EQ(16, foo_->reserved_range(4)->end);
  1856. ASSERT_EQ(1, edge1_->reserved_range_count());
  1857. EXPECT_EQ(10, edge1_->reserved_range(0)->start);
  1858. EXPECT_EQ(INT_MAX, edge1_->reserved_range(0)->end);
  1859. ASSERT_EQ(1, edge2_->reserved_range_count());
  1860. EXPECT_EQ(INT_MIN, edge2_->reserved_range(0)->start);
  1861. EXPECT_EQ(10, edge2_->reserved_range(0)->end);
  1862. }
  1863. TEST_F(ReservedEnumDescriptorTest, IsReservedNumber) {
  1864. EXPECT_TRUE(foo_->IsReservedNumber(-5));
  1865. EXPECT_TRUE(foo_->IsReservedNumber(-4));
  1866. EXPECT_TRUE(foo_->IsReservedNumber(-3));
  1867. EXPECT_TRUE(foo_->IsReservedNumber(-2));
  1868. EXPECT_TRUE(foo_->IsReservedNumber(-1));
  1869. EXPECT_TRUE(foo_->IsReservedNumber(0));
  1870. EXPECT_TRUE(foo_->IsReservedNumber(1));
  1871. EXPECT_TRUE(foo_->IsReservedNumber(2));
  1872. EXPECT_TRUE(foo_->IsReservedNumber(3));
  1873. EXPECT_FALSE(foo_->IsReservedNumber(8));
  1874. EXPECT_TRUE(foo_->IsReservedNumber(9));
  1875. EXPECT_TRUE(foo_->IsReservedNumber(10));
  1876. EXPECT_TRUE(foo_->IsReservedNumber(11));
  1877. EXPECT_TRUE(foo_->IsReservedNumber(12));
  1878. EXPECT_FALSE(foo_->IsReservedNumber(13));
  1879. EXPECT_FALSE(foo_->IsReservedNumber(13));
  1880. EXPECT_FALSE(foo_->IsReservedNumber(14));
  1881. EXPECT_TRUE(foo_->IsReservedNumber(15));
  1882. EXPECT_TRUE(foo_->IsReservedNumber(16));
  1883. EXPECT_FALSE(foo_->IsReservedNumber(17));
  1884. EXPECT_FALSE(edge1_->IsReservedNumber(9));
  1885. EXPECT_TRUE(edge1_->IsReservedNumber(10));
  1886. EXPECT_TRUE(edge1_->IsReservedNumber(INT_MAX - 1));
  1887. EXPECT_TRUE(edge1_->IsReservedNumber(INT_MAX));
  1888. EXPECT_TRUE(edge2_->IsReservedNumber(INT_MIN));
  1889. EXPECT_TRUE(edge2_->IsReservedNumber(9));
  1890. EXPECT_TRUE(edge2_->IsReservedNumber(10));
  1891. EXPECT_FALSE(edge2_->IsReservedNumber(11));
  1892. }
  1893. TEST_F(ReservedEnumDescriptorTest, ReservedNames) {
  1894. ASSERT_EQ(2, foo_->reserved_name_count());
  1895. EXPECT_EQ("foo", foo_->reserved_name(0));
  1896. EXPECT_EQ("bar", foo_->reserved_name(1));
  1897. }
  1898. TEST_F(ReservedEnumDescriptorTest, IsReservedName) {
  1899. EXPECT_TRUE(foo_->IsReservedName("foo"));
  1900. EXPECT_TRUE(foo_->IsReservedName("bar"));
  1901. EXPECT_FALSE(foo_->IsReservedName("baz"));
  1902. }
  1903. // ===================================================================
  1904. class MiscTest : public testing::Test {
  1905. protected:
  1906. // Function which makes a field descriptor of the given type.
  1907. const FieldDescriptor* GetFieldDescriptorOfType(FieldDescriptor::Type type) {
  1908. FileDescriptorProto file_proto;
  1909. file_proto.set_name("foo.proto");
  1910. AddEmptyEnum(&file_proto, "DummyEnum");
  1911. DescriptorProto* message = AddMessage(&file_proto, "TestMessage");
  1912. FieldDescriptorProto* field = AddField(
  1913. message, "foo", 1, FieldDescriptorProto::LABEL_OPTIONAL,
  1914. static_cast<FieldDescriptorProto::Type>(static_cast<int>(type)));
  1915. if (type == FieldDescriptor::TYPE_MESSAGE ||
  1916. type == FieldDescriptor::TYPE_GROUP) {
  1917. field->set_type_name("TestMessage");
  1918. } else if (type == FieldDescriptor::TYPE_ENUM) {
  1919. field->set_type_name("DummyEnum");
  1920. }
  1921. // Build the descriptors and get the pointers.
  1922. pool_.reset(new DescriptorPool());
  1923. const FileDescriptor* file = pool_->BuildFile(file_proto);
  1924. if (file != nullptr && file->message_type_count() == 1 &&
  1925. file->message_type(0)->field_count() == 1) {
  1926. return file->message_type(0)->field(0);
  1927. } else {
  1928. return nullptr;
  1929. }
  1930. }
  1931. const char* GetTypeNameForFieldType(FieldDescriptor::Type type) {
  1932. const FieldDescriptor* field = GetFieldDescriptorOfType(type);
  1933. return field != nullptr ? field->type_name() : "";
  1934. }
  1935. FieldDescriptor::CppType GetCppTypeForFieldType(FieldDescriptor::Type type) {
  1936. const FieldDescriptor* field = GetFieldDescriptorOfType(type);
  1937. return field != nullptr ? field->cpp_type()
  1938. : static_cast<FieldDescriptor::CppType>(0);
  1939. }
  1940. const char* GetCppTypeNameForFieldType(FieldDescriptor::Type type) {
  1941. const FieldDescriptor* field = GetFieldDescriptorOfType(type);
  1942. return field != nullptr ? field->cpp_type_name() : "";
  1943. }
  1944. const Descriptor* GetMessageDescriptorForFieldType(
  1945. FieldDescriptor::Type type) {
  1946. const FieldDescriptor* field = GetFieldDescriptorOfType(type);
  1947. return field != nullptr ? field->message_type() : nullptr;
  1948. }
  1949. const EnumDescriptor* GetEnumDescriptorForFieldType(
  1950. FieldDescriptor::Type type) {
  1951. const FieldDescriptor* field = GetFieldDescriptorOfType(type);
  1952. return field != nullptr ? field->enum_type() : nullptr;
  1953. }
  1954. std::unique_ptr<DescriptorPool> pool_;
  1955. };
  1956. TEST_F(MiscTest, TypeNames) {
  1957. // Test that correct type names are returned.
  1958. typedef FieldDescriptor FD; // avoid ugly line wrapping
  1959. EXPECT_STREQ("double", GetTypeNameForFieldType(FD::TYPE_DOUBLE));
  1960. EXPECT_STREQ("float", GetTypeNameForFieldType(FD::TYPE_FLOAT));
  1961. EXPECT_STREQ("int64", GetTypeNameForFieldType(FD::TYPE_INT64));
  1962. EXPECT_STREQ("uint64", GetTypeNameForFieldType(FD::TYPE_UINT64));
  1963. EXPECT_STREQ("int32", GetTypeNameForFieldType(FD::TYPE_INT32));
  1964. EXPECT_STREQ("fixed64", GetTypeNameForFieldType(FD::TYPE_FIXED64));
  1965. EXPECT_STREQ("fixed32", GetTypeNameForFieldType(FD::TYPE_FIXED32));
  1966. EXPECT_STREQ("bool", GetTypeNameForFieldType(FD::TYPE_BOOL));
  1967. EXPECT_STREQ("string", GetTypeNameForFieldType(FD::TYPE_STRING));
  1968. EXPECT_STREQ("group", GetTypeNameForFieldType(FD::TYPE_GROUP));
  1969. EXPECT_STREQ("message", GetTypeNameForFieldType(FD::TYPE_MESSAGE));
  1970. EXPECT_STREQ("bytes", GetTypeNameForFieldType(FD::TYPE_BYTES));
  1971. EXPECT_STREQ("uint32", GetTypeNameForFieldType(FD::TYPE_UINT32));
  1972. EXPECT_STREQ("enum", GetTypeNameForFieldType(FD::TYPE_ENUM));
  1973. EXPECT_STREQ("sfixed32", GetTypeNameForFieldType(FD::TYPE_SFIXED32));
  1974. EXPECT_STREQ("sfixed64", GetTypeNameForFieldType(FD::TYPE_SFIXED64));
  1975. EXPECT_STREQ("sint32", GetTypeNameForFieldType(FD::TYPE_SINT32));
  1976. EXPECT_STREQ("sint64", GetTypeNameForFieldType(FD::TYPE_SINT64));
  1977. }
  1978. TEST_F(MiscTest, StaticTypeNames) {
  1979. // Test that correct type names are returned.
  1980. typedef FieldDescriptor FD; // avoid ugly line wrapping
  1981. EXPECT_STREQ("double", FD::TypeName(FD::TYPE_DOUBLE));
  1982. EXPECT_STREQ("float", FD::TypeName(FD::TYPE_FLOAT));
  1983. EXPECT_STREQ("int64", FD::TypeName(FD::TYPE_INT64));
  1984. EXPECT_STREQ("uint64", FD::TypeName(FD::TYPE_UINT64));
  1985. EXPECT_STREQ("int32", FD::TypeName(FD::TYPE_INT32));
  1986. EXPECT_STREQ("fixed64", FD::TypeName(FD::TYPE_FIXED64));
  1987. EXPECT_STREQ("fixed32", FD::TypeName(FD::TYPE_FIXED32));
  1988. EXPECT_STREQ("bool", FD::TypeName(FD::TYPE_BOOL));
  1989. EXPECT_STREQ("string", FD::TypeName(FD::TYPE_STRING));
  1990. EXPECT_STREQ("group", FD::TypeName(FD::TYPE_GROUP));
  1991. EXPECT_STREQ("message", FD::TypeName(FD::TYPE_MESSAGE));
  1992. EXPECT_STREQ("bytes", FD::TypeName(FD::TYPE_BYTES));
  1993. EXPECT_STREQ("uint32", FD::TypeName(FD::TYPE_UINT32));
  1994. EXPECT_STREQ("enum", FD::TypeName(FD::TYPE_ENUM));
  1995. EXPECT_STREQ("sfixed32", FD::TypeName(FD::TYPE_SFIXED32));
  1996. EXPECT_STREQ("sfixed64", FD::TypeName(FD::TYPE_SFIXED64));
  1997. EXPECT_STREQ("sint32", FD::TypeName(FD::TYPE_SINT32));
  1998. EXPECT_STREQ("sint64", FD::TypeName(FD::TYPE_SINT64));
  1999. }
  2000. TEST_F(MiscTest, CppTypes) {
  2001. // Test that CPP types are assigned correctly.
  2002. typedef FieldDescriptor FD; // avoid ugly line wrapping
  2003. EXPECT_EQ(FD::CPPTYPE_DOUBLE, GetCppTypeForFieldType(FD::TYPE_DOUBLE));
  2004. EXPECT_EQ(FD::CPPTYPE_FLOAT, GetCppTypeForFieldType(FD::TYPE_FLOAT));
  2005. EXPECT_EQ(FD::CPPTYPE_INT64, GetCppTypeForFieldType(FD::TYPE_INT64));
  2006. EXPECT_EQ(FD::CPPTYPE_UINT64, GetCppTypeForFieldType(FD::TYPE_UINT64));
  2007. EXPECT_EQ(FD::CPPTYPE_INT32, GetCppTypeForFieldType(FD::TYPE_INT32));
  2008. EXPECT_EQ(FD::CPPTYPE_UINT64, GetCppTypeForFieldType(FD::TYPE_FIXED64));
  2009. EXPECT_EQ(FD::CPPTYPE_UINT32, GetCppTypeForFieldType(FD::TYPE_FIXED32));
  2010. EXPECT_EQ(FD::CPPTYPE_BOOL, GetCppTypeForFieldType(FD::TYPE_BOOL));
  2011. EXPECT_EQ(FD::CPPTYPE_STRING, GetCppTypeForFieldType(FD::TYPE_STRING));
  2012. EXPECT_EQ(FD::CPPTYPE_MESSAGE, GetCppTypeForFieldType(FD::TYPE_GROUP));
  2013. EXPECT_EQ(FD::CPPTYPE_MESSAGE, GetCppTypeForFieldType(FD::TYPE_MESSAGE));
  2014. EXPECT_EQ(FD::CPPTYPE_STRING, GetCppTypeForFieldType(FD::TYPE_BYTES));
  2015. EXPECT_EQ(FD::CPPTYPE_UINT32, GetCppTypeForFieldType(FD::TYPE_UINT32));
  2016. EXPECT_EQ(FD::CPPTYPE_ENUM, GetCppTypeForFieldType(FD::TYPE_ENUM));
  2017. EXPECT_EQ(FD::CPPTYPE_INT32, GetCppTypeForFieldType(FD::TYPE_SFIXED32));
  2018. EXPECT_EQ(FD::CPPTYPE_INT64, GetCppTypeForFieldType(FD::TYPE_SFIXED64));
  2019. EXPECT_EQ(FD::CPPTYPE_INT32, GetCppTypeForFieldType(FD::TYPE_SINT32));
  2020. EXPECT_EQ(FD::CPPTYPE_INT64, GetCppTypeForFieldType(FD::TYPE_SINT64));
  2021. }
  2022. TEST_F(MiscTest, CppTypeNames) {
  2023. // Test that correct CPP type names are returned.
  2024. typedef FieldDescriptor FD; // avoid ugly line wrapping
  2025. EXPECT_STREQ("double", GetCppTypeNameForFieldType(FD::TYPE_DOUBLE));
  2026. EXPECT_STREQ("float", GetCppTypeNameForFieldType(FD::TYPE_FLOAT));
  2027. EXPECT_STREQ("int64", GetCppTypeNameForFieldType(FD::TYPE_INT64));
  2028. EXPECT_STREQ("uint64", GetCppTypeNameForFieldType(FD::TYPE_UINT64));
  2029. EXPECT_STREQ("int32", GetCppTypeNameForFieldType(FD::TYPE_INT32));
  2030. EXPECT_STREQ("uint64", GetCppTypeNameForFieldType(FD::TYPE_FIXED64));
  2031. EXPECT_STREQ("uint32", GetCppTypeNameForFieldType(FD::TYPE_FIXED32));
  2032. EXPECT_STREQ("bool", GetCppTypeNameForFieldType(FD::TYPE_BOOL));
  2033. EXPECT_STREQ("string", GetCppTypeNameForFieldType(FD::TYPE_STRING));
  2034. EXPECT_STREQ("message", GetCppTypeNameForFieldType(FD::TYPE_GROUP));
  2035. EXPECT_STREQ("message", GetCppTypeNameForFieldType(FD::TYPE_MESSAGE));
  2036. EXPECT_STREQ("string", GetCppTypeNameForFieldType(FD::TYPE_BYTES));
  2037. EXPECT_STREQ("uint32", GetCppTypeNameForFieldType(FD::TYPE_UINT32));
  2038. EXPECT_STREQ("enum", GetCppTypeNameForFieldType(FD::TYPE_ENUM));
  2039. EXPECT_STREQ("int32", GetCppTypeNameForFieldType(FD::TYPE_SFIXED32));
  2040. EXPECT_STREQ("int64", GetCppTypeNameForFieldType(FD::TYPE_SFIXED64));
  2041. EXPECT_STREQ("int32", GetCppTypeNameForFieldType(FD::TYPE_SINT32));
  2042. EXPECT_STREQ("int64", GetCppTypeNameForFieldType(FD::TYPE_SINT64));
  2043. }
  2044. TEST_F(MiscTest, StaticCppTypeNames) {
  2045. // Test that correct CPP type names are returned.
  2046. typedef FieldDescriptor FD; // avoid ugly line wrapping
  2047. EXPECT_STREQ("int32", FD::CppTypeName(FD::CPPTYPE_INT32));
  2048. EXPECT_STREQ("int64", FD::CppTypeName(FD::CPPTYPE_INT64));
  2049. EXPECT_STREQ("uint32", FD::CppTypeName(FD::CPPTYPE_UINT32));
  2050. EXPECT_STREQ("uint64", FD::CppTypeName(FD::CPPTYPE_UINT64));
  2051. EXPECT_STREQ("double", FD::CppTypeName(FD::CPPTYPE_DOUBLE));
  2052. EXPECT_STREQ("float", FD::CppTypeName(FD::CPPTYPE_FLOAT));
  2053. EXPECT_STREQ("bool", FD::CppTypeName(FD::CPPTYPE_BOOL));
  2054. EXPECT_STREQ("enum", FD::CppTypeName(FD::CPPTYPE_ENUM));
  2055. EXPECT_STREQ("string", FD::CppTypeName(FD::CPPTYPE_STRING));
  2056. EXPECT_STREQ("message", FD::CppTypeName(FD::CPPTYPE_MESSAGE));
  2057. }
  2058. TEST_F(MiscTest, MessageType) {
  2059. // Test that message_type() is nullptr for non-aggregate fields
  2060. typedef FieldDescriptor FD; // avoid ugly line wrapping
  2061. EXPECT_TRUE(nullptr == GetMessageDescriptorForFieldType(FD::TYPE_DOUBLE));
  2062. EXPECT_TRUE(nullptr == GetMessageDescriptorForFieldType(FD::TYPE_FLOAT));
  2063. EXPECT_TRUE(nullptr == GetMessageDescriptorForFieldType(FD::TYPE_INT64));
  2064. EXPECT_TRUE(nullptr == GetMessageDescriptorForFieldType(FD::TYPE_UINT64));
  2065. EXPECT_TRUE(nullptr == GetMessageDescriptorForFieldType(FD::TYPE_INT32));
  2066. EXPECT_TRUE(nullptr == GetMessageDescriptorForFieldType(FD::TYPE_FIXED64));
  2067. EXPECT_TRUE(nullptr == GetMessageDescriptorForFieldType(FD::TYPE_FIXED32));
  2068. EXPECT_TRUE(nullptr == GetMessageDescriptorForFieldType(FD::TYPE_BOOL));
  2069. EXPECT_TRUE(nullptr == GetMessageDescriptorForFieldType(FD::TYPE_STRING));
  2070. EXPECT_TRUE(nullptr != GetMessageDescriptorForFieldType(FD::TYPE_GROUP));
  2071. EXPECT_TRUE(nullptr != GetMessageDescriptorForFieldType(FD::TYPE_MESSAGE));
  2072. EXPECT_TRUE(nullptr == GetMessageDescriptorForFieldType(FD::TYPE_BYTES));
  2073. EXPECT_TRUE(nullptr == GetMessageDescriptorForFieldType(FD::TYPE_UINT32));
  2074. EXPECT_TRUE(nullptr == GetMessageDescriptorForFieldType(FD::TYPE_ENUM));
  2075. EXPECT_TRUE(nullptr == GetMessageDescriptorForFieldType(FD::TYPE_SFIXED32));
  2076. EXPECT_TRUE(nullptr == GetMessageDescriptorForFieldType(FD::TYPE_SFIXED64));
  2077. EXPECT_TRUE(nullptr == GetMessageDescriptorForFieldType(FD::TYPE_SINT32));
  2078. EXPECT_TRUE(nullptr == GetMessageDescriptorForFieldType(FD::TYPE_SINT64));
  2079. }
  2080. TEST_F(MiscTest, EnumType) {
  2081. // Test that enum_type() is nullptr for non-enum fields
  2082. typedef FieldDescriptor FD; // avoid ugly line wrapping
  2083. EXPECT_TRUE(nullptr == GetEnumDescriptorForFieldType(FD::TYPE_DOUBLE));
  2084. EXPECT_TRUE(nullptr == GetEnumDescriptorForFieldType(FD::TYPE_FLOAT));
  2085. EXPECT_TRUE(nullptr == GetEnumDescriptorForFieldType(FD::TYPE_INT64));
  2086. EXPECT_TRUE(nullptr == GetEnumDescriptorForFieldType(FD::TYPE_UINT64));
  2087. EXPECT_TRUE(nullptr == GetEnumDescriptorForFieldType(FD::TYPE_INT32));
  2088. EXPECT_TRUE(nullptr == GetEnumDescriptorForFieldType(FD::TYPE_FIXED64));
  2089. EXPECT_TRUE(nullptr == GetEnumDescriptorForFieldType(FD::TYPE_FIXED32));
  2090. EXPECT_TRUE(nullptr == GetEnumDescriptorForFieldType(FD::TYPE_BOOL));
  2091. EXPECT_TRUE(nullptr == GetEnumDescriptorForFieldType(FD::TYPE_STRING));
  2092. EXPECT_TRUE(nullptr == GetEnumDescriptorForFieldType(FD::TYPE_GROUP));
  2093. EXPECT_TRUE(nullptr == GetEnumDescriptorForFieldType(FD::TYPE_MESSAGE));
  2094. EXPECT_TRUE(nullptr == GetEnumDescriptorForFieldType(FD::TYPE_BYTES));
  2095. EXPECT_TRUE(nullptr == GetEnumDescriptorForFieldType(FD::TYPE_UINT32));
  2096. EXPECT_TRUE(nullptr != GetEnumDescriptorForFieldType(FD::TYPE_ENUM));
  2097. EXPECT_TRUE(nullptr == GetEnumDescriptorForFieldType(FD::TYPE_SFIXED32));
  2098. EXPECT_TRUE(nullptr == GetEnumDescriptorForFieldType(FD::TYPE_SFIXED64));
  2099. EXPECT_TRUE(nullptr == GetEnumDescriptorForFieldType(FD::TYPE_SINT32));
  2100. EXPECT_TRUE(nullptr == GetEnumDescriptorForFieldType(FD::TYPE_SINT64));
  2101. }
  2102. TEST_F(MiscTest, DefaultValues) {
  2103. // Test that setting default values works.
  2104. FileDescriptorProto file_proto;
  2105. file_proto.set_name("foo.proto");
  2106. EnumDescriptorProto* enum_type_proto = AddEnum(&file_proto, "DummyEnum");
  2107. AddEnumValue(enum_type_proto, "A", 1);
  2108. AddEnumValue(enum_type_proto, "B", 2);
  2109. DescriptorProto* message_proto = AddMessage(&file_proto, "TestMessage");
  2110. typedef FieldDescriptorProto FD; // avoid ugly line wrapping
  2111. const FD::Label label = FD::LABEL_OPTIONAL;
  2112. // Create fields of every CPP type with default values.
  2113. AddField(message_proto, "int32", 1, label, FD::TYPE_INT32)
  2114. ->set_default_value("-1");
  2115. AddField(message_proto, "int64", 2, label, FD::TYPE_INT64)
  2116. ->set_default_value("-1000000000000");
  2117. AddField(message_proto, "uint32", 3, label, FD::TYPE_UINT32)
  2118. ->set_default_value("42");
  2119. AddField(message_proto, "uint64", 4, label, FD::TYPE_UINT64)
  2120. ->set_default_value("2000000000000");
  2121. AddField(message_proto, "float", 5, label, FD::TYPE_FLOAT)
  2122. ->set_default_value("4.5");
  2123. AddField(message_proto, "double", 6, label, FD::TYPE_DOUBLE)
  2124. ->set_default_value("10e100");
  2125. AddField(message_proto, "bool", 7, label, FD::TYPE_BOOL)
  2126. ->set_default_value("true");
  2127. AddField(message_proto, "string", 8, label, FD::TYPE_STRING)
  2128. ->set_default_value("hello");
  2129. AddField(message_proto, "data", 9, label, FD::TYPE_BYTES)
  2130. ->set_default_value("\\001\\002\\003");
  2131. FieldDescriptorProto* enum_field =
  2132. AddField(message_proto, "enum", 10, label, FD::TYPE_ENUM);
  2133. enum_field->set_type_name("DummyEnum");
  2134. enum_field->set_default_value("B");
  2135. // Strings are allowed to have empty defaults. (At one point, due to
  2136. // a bug, empty defaults for strings were rejected. Oops.)
  2137. AddField(message_proto, "empty_string", 11, label, FD::TYPE_STRING)
  2138. ->set_default_value("");
  2139. // Add a second set of fields with implicit defalut values.
  2140. AddField(message_proto, "implicit_int32", 21, label, FD::TYPE_INT32);
  2141. AddField(message_proto, "implicit_int64", 22, label, FD::TYPE_INT64);
  2142. AddField(message_proto, "implicit_uint32", 23, label, FD::TYPE_UINT32);
  2143. AddField(message_proto, "implicit_uint64", 24, label, FD::TYPE_UINT64);
  2144. AddField(message_proto, "implicit_float", 25, label, FD::TYPE_FLOAT);
  2145. AddField(message_proto, "implicit_double", 26, label, FD::TYPE_DOUBLE);
  2146. AddField(message_proto, "implicit_bool", 27, label, FD::TYPE_BOOL);
  2147. AddField(message_proto, "implicit_string", 28, label, FD::TYPE_STRING);
  2148. AddField(message_proto, "implicit_data", 29, label, FD::TYPE_BYTES);
  2149. AddField(message_proto, "implicit_enum", 30, label, FD::TYPE_ENUM)
  2150. ->set_type_name("DummyEnum");
  2151. // Build it.
  2152. DescriptorPool pool;
  2153. const FileDescriptor* file = pool.BuildFile(file_proto);
  2154. ASSERT_TRUE(file != nullptr);
  2155. ASSERT_EQ(1, file->enum_type_count());
  2156. const EnumDescriptor* enum_type = file->enum_type(0);
  2157. ASSERT_EQ(2, enum_type->value_count());
  2158. const EnumValueDescriptor* enum_value_a = enum_type->value(0);
  2159. const EnumValueDescriptor* enum_value_b = enum_type->value(1);
  2160. ASSERT_EQ(1, file->message_type_count());
  2161. const Descriptor* message = file->message_type(0);
  2162. ASSERT_EQ(21, message->field_count());
  2163. // Check the default values.
  2164. ASSERT_TRUE(message->field(0)->has_default_value());
  2165. ASSERT_TRUE(message->field(1)->has_default_value());
  2166. ASSERT_TRUE(message->field(2)->has_default_value());
  2167. ASSERT_TRUE(message->field(3)->has_default_value());
  2168. ASSERT_TRUE(message->field(4)->has_default_value());
  2169. ASSERT_TRUE(message->field(5)->has_default_value());
  2170. ASSERT_TRUE(message->field(6)->has_default_value());
  2171. ASSERT_TRUE(message->field(7)->has_default_value());
  2172. ASSERT_TRUE(message->field(8)->has_default_value());
  2173. ASSERT_TRUE(message->field(9)->has_default_value());
  2174. ASSERT_TRUE(message->field(10)->has_default_value());
  2175. EXPECT_EQ(-1, message->field(0)->default_value_int32());
  2176. EXPECT_EQ(-PROTOBUF_ULONGLONG(1000000000000),
  2177. message->field(1)->default_value_int64());
  2178. EXPECT_EQ(42, message->field(2)->default_value_uint32());
  2179. EXPECT_EQ(PROTOBUF_ULONGLONG(2000000000000),
  2180. message->field(3)->default_value_uint64());
  2181. EXPECT_EQ(4.5, message->field(4)->default_value_float());
  2182. EXPECT_EQ(10e100, message->field(5)->default_value_double());
  2183. EXPECT_TRUE(message->field(6)->default_value_bool());
  2184. EXPECT_EQ("hello", message->field(7)->default_value_string());
  2185. EXPECT_EQ("\001\002\003", message->field(8)->default_value_string());
  2186. EXPECT_EQ(enum_value_b, message->field(9)->default_value_enum());
  2187. EXPECT_EQ("", message->field(10)->default_value_string());
  2188. ASSERT_FALSE(message->field(11)->has_default_value());
  2189. ASSERT_FALSE(message->field(12)->has_default_value());
  2190. ASSERT_FALSE(message->field(13)->has_default_value());
  2191. ASSERT_FALSE(message->field(14)->has_default_value());
  2192. ASSERT_FALSE(message->field(15)->has_default_value());
  2193. ASSERT_FALSE(message->field(16)->has_default_value());
  2194. ASSERT_FALSE(message->field(17)->has_default_value());
  2195. ASSERT_FALSE(message->field(18)->has_default_value());
  2196. ASSERT_FALSE(message->field(19)->has_default_value());
  2197. ASSERT_FALSE(message->field(20)->has_default_value());
  2198. EXPECT_EQ(0, message->field(11)->default_value_int32());
  2199. EXPECT_EQ(0, message->field(12)->default_value_int64());
  2200. EXPECT_EQ(0, message->field(13)->default_value_uint32());
  2201. EXPECT_EQ(0, message->field(14)->default_value_uint64());
  2202. EXPECT_EQ(0.0f, message->field(15)->default_value_float());
  2203. EXPECT_EQ(0.0, message->field(16)->default_value_double());
  2204. EXPECT_FALSE(message->field(17)->default_value_bool());
  2205. EXPECT_EQ("", message->field(18)->default_value_string());
  2206. EXPECT_EQ("", message->field(19)->default_value_string());
  2207. EXPECT_EQ(enum_value_a, message->field(20)->default_value_enum());
  2208. }
  2209. TEST_F(MiscTest, FieldOptions) {
  2210. // Try setting field options.
  2211. FileDescriptorProto file_proto;
  2212. file_proto.set_name("foo.proto");
  2213. DescriptorProto* message_proto = AddMessage(&file_proto, "TestMessage");
  2214. AddField(message_proto, "foo", 1, FieldDescriptorProto::LABEL_OPTIONAL,
  2215. FieldDescriptorProto::TYPE_INT32);
  2216. FieldDescriptorProto* bar_proto =
  2217. AddField(message_proto, "bar", 2, FieldDescriptorProto::LABEL_OPTIONAL,
  2218. FieldDescriptorProto::TYPE_INT32);
  2219. FieldOptions* options = bar_proto->mutable_options();
  2220. options->set_ctype(FieldOptions::CORD);
  2221. // Build the descriptors and get the pointers.
  2222. DescriptorPool pool;
  2223. const FileDescriptor* file = pool.BuildFile(file_proto);
  2224. ASSERT_TRUE(file != nullptr);
  2225. ASSERT_EQ(1, file->message_type_count());
  2226. const Descriptor* message = file->message_type(0);
  2227. ASSERT_EQ(2, message->field_count());
  2228. const FieldDescriptor* foo = message->field(0);
  2229. const FieldDescriptor* bar = message->field(1);
  2230. // "foo" had no options set, so it should return the default options.
  2231. EXPECT_EQ(&FieldOptions::default_instance(), &foo->options());
  2232. // "bar" had options set.
  2233. EXPECT_NE(&FieldOptions::default_instance(), options);
  2234. EXPECT_TRUE(bar->options().has_ctype());
  2235. EXPECT_EQ(FieldOptions::CORD, bar->options().ctype());
  2236. }
  2237. // ===================================================================
  2238. enum DescriptorPoolMode { NO_DATABASE, FALLBACK_DATABASE };
  2239. class AllowUnknownDependenciesTest
  2240. : public testing::TestWithParam<DescriptorPoolMode> {
  2241. protected:
  2242. DescriptorPoolMode mode() { return GetParam(); }
  2243. virtual void SetUp() {
  2244. FileDescriptorProto foo_proto, bar_proto;
  2245. switch (mode()) {
  2246. case NO_DATABASE:
  2247. pool_.reset(new DescriptorPool);
  2248. break;
  2249. case FALLBACK_DATABASE:
  2250. pool_.reset(new DescriptorPool(&db_));
  2251. break;
  2252. }
  2253. pool_->AllowUnknownDependencies();
  2254. ASSERT_TRUE(TextFormat::ParseFromString(
  2255. "name: 'foo.proto'"
  2256. "dependency: 'bar.proto'"
  2257. "dependency: 'baz.proto'"
  2258. "message_type {"
  2259. " name: 'Foo'"
  2260. " field { name:'bar' number:1 label:LABEL_OPTIONAL type_name:'Bar' }"
  2261. " field { name:'baz' number:2 label:LABEL_OPTIONAL type_name:'Baz' }"
  2262. " field { name:'qux' number:3 label:LABEL_OPTIONAL"
  2263. " type_name: '.corge.Qux'"
  2264. " type: TYPE_ENUM"
  2265. " options {"
  2266. " uninterpreted_option {"
  2267. " name {"
  2268. " name_part: 'grault'"
  2269. " is_extension: true"
  2270. " }"
  2271. " positive_int_value: 1234"
  2272. " }"
  2273. " }"
  2274. " }"
  2275. "}",
  2276. &foo_proto));
  2277. ASSERT_TRUE(
  2278. TextFormat::ParseFromString("name: 'bar.proto'"
  2279. "message_type { name: 'Bar' }",
  2280. &bar_proto));
  2281. // Collect pointers to stuff.
  2282. bar_file_ = BuildFile(bar_proto);
  2283. ASSERT_TRUE(bar_file_ != nullptr);
  2284. ASSERT_EQ(1, bar_file_->message_type_count());
  2285. bar_type_ = bar_file_->message_type(0);
  2286. foo_file_ = BuildFile(foo_proto);
  2287. ASSERT_TRUE(foo_file_ != nullptr);
  2288. ASSERT_EQ(1, foo_file_->message_type_count());
  2289. foo_type_ = foo_file_->message_type(0);
  2290. ASSERT_EQ(3, foo_type_->field_count());
  2291. bar_field_ = foo_type_->field(0);
  2292. baz_field_ = foo_type_->field(1);
  2293. qux_field_ = foo_type_->field(2);
  2294. }
  2295. const FileDescriptor* BuildFile(const FileDescriptorProto& proto) {
  2296. switch (mode()) {
  2297. case NO_DATABASE:
  2298. return pool_->BuildFile(proto);
  2299. break;
  2300. case FALLBACK_DATABASE: {
  2301. EXPECT_TRUE(db_.Add(proto));
  2302. return pool_->FindFileByName(proto.name());
  2303. }
  2304. }
  2305. GOOGLE_LOG(FATAL) << "Can't get here.";
  2306. return nullptr;
  2307. }
  2308. const FileDescriptor* bar_file_;
  2309. const Descriptor* bar_type_;
  2310. const FileDescriptor* foo_file_;
  2311. const Descriptor* foo_type_;
  2312. const FieldDescriptor* bar_field_;
  2313. const FieldDescriptor* baz_field_;
  2314. const FieldDescriptor* qux_field_;
  2315. SimpleDescriptorDatabase db_; // used if in FALLBACK_DATABASE mode.
  2316. std::unique_ptr<DescriptorPool> pool_;
  2317. };
  2318. TEST_P(AllowUnknownDependenciesTest, PlaceholderFile) {
  2319. ASSERT_EQ(2, foo_file_->dependency_count());
  2320. EXPECT_EQ(bar_file_, foo_file_->dependency(0));
  2321. EXPECT_FALSE(bar_file_->is_placeholder());
  2322. const FileDescriptor* baz_file = foo_file_->dependency(1);
  2323. EXPECT_EQ("baz.proto", baz_file->name());
  2324. EXPECT_EQ(0, baz_file->message_type_count());
  2325. EXPECT_TRUE(baz_file->is_placeholder());
  2326. // Placeholder files should not be findable.
  2327. EXPECT_EQ(bar_file_, pool_->FindFileByName(bar_file_->name()));
  2328. EXPECT_TRUE(pool_->FindFileByName(baz_file->name()) == nullptr);
  2329. // Copy*To should not crash for placeholder files.
  2330. FileDescriptorProto baz_file_proto;
  2331. baz_file->CopyTo(&baz_file_proto);
  2332. baz_file->CopySourceCodeInfoTo(&baz_file_proto);
  2333. EXPECT_FALSE(baz_file_proto.has_source_code_info());
  2334. }
  2335. TEST_P(AllowUnknownDependenciesTest, PlaceholderTypes) {
  2336. ASSERT_EQ(FieldDescriptor::TYPE_MESSAGE, bar_field_->type());
  2337. EXPECT_EQ(bar_type_, bar_field_->message_type());
  2338. EXPECT_FALSE(bar_type_->is_placeholder());
  2339. ASSERT_EQ(FieldDescriptor::TYPE_MESSAGE, baz_field_->type());
  2340. const Descriptor* baz_type = baz_field_->message_type();
  2341. EXPECT_EQ("Baz", baz_type->name());
  2342. EXPECT_EQ("Baz", baz_type->full_name());
  2343. EXPECT_EQ(0, baz_type->extension_range_count());
  2344. EXPECT_TRUE(baz_type->is_placeholder());
  2345. ASSERT_EQ(FieldDescriptor::TYPE_ENUM, qux_field_->type());
  2346. const EnumDescriptor* qux_type = qux_field_->enum_type();
  2347. EXPECT_EQ("Qux", qux_type->name());
  2348. EXPECT_EQ("corge.Qux", qux_type->full_name());
  2349. EXPECT_TRUE(qux_type->is_placeholder());
  2350. // Placeholder types should not be findable.
  2351. EXPECT_EQ(bar_type_, pool_->FindMessageTypeByName(bar_type_->full_name()));
  2352. EXPECT_TRUE(pool_->FindMessageTypeByName(baz_type->full_name()) == nullptr);
  2353. EXPECT_TRUE(pool_->FindEnumTypeByName(qux_type->full_name()) == nullptr);
  2354. }
  2355. TEST_P(AllowUnknownDependenciesTest, CopyTo) {
  2356. // FieldDescriptor::CopyTo() should write non-fully-qualified type names
  2357. // for placeholder types which were not originally fully-qualified.
  2358. FieldDescriptorProto proto;
  2359. // Bar is not a placeholder, so it is fully-qualified.
  2360. bar_field_->CopyTo(&proto);
  2361. EXPECT_EQ(".Bar", proto.type_name());
  2362. EXPECT_EQ(FieldDescriptorProto::TYPE_MESSAGE, proto.type());
  2363. // Baz is an unqualified placeholder.
  2364. proto.Clear();
  2365. baz_field_->CopyTo(&proto);
  2366. EXPECT_EQ("Baz", proto.type_name());
  2367. EXPECT_FALSE(proto.has_type());
  2368. // Qux is a fully-qualified placeholder.
  2369. proto.Clear();
  2370. qux_field_->CopyTo(&proto);
  2371. EXPECT_EQ(".corge.Qux", proto.type_name());
  2372. EXPECT_EQ(FieldDescriptorProto::TYPE_ENUM, proto.type());
  2373. }
  2374. TEST_P(AllowUnknownDependenciesTest, CustomOptions) {
  2375. // Qux should still have the uninterpreted option attached.
  2376. ASSERT_EQ(1, qux_field_->options().uninterpreted_option_size());
  2377. const UninterpretedOption& option =
  2378. qux_field_->options().uninterpreted_option(0);
  2379. ASSERT_EQ(1, option.name_size());
  2380. EXPECT_EQ("grault", option.name(0).name_part());
  2381. }
  2382. TEST_P(AllowUnknownDependenciesTest, UnknownExtendee) {
  2383. // Test that we can extend an unknown type. This is slightly tricky because
  2384. // it means that the placeholder type must have an extension range.
  2385. FileDescriptorProto extension_proto;
  2386. ASSERT_TRUE(TextFormat::ParseFromString(
  2387. "name: 'extension.proto'"
  2388. "extension { extendee: 'UnknownType' name:'some_extension' number:123"
  2389. " label:LABEL_OPTIONAL type:TYPE_INT32 }",
  2390. &extension_proto));
  2391. const FileDescriptor* file = BuildFile(extension_proto);
  2392. ASSERT_TRUE(file != nullptr);
  2393. ASSERT_EQ(1, file->extension_count());
  2394. const Descriptor* extendee = file->extension(0)->containing_type();
  2395. EXPECT_EQ("UnknownType", extendee->name());
  2396. EXPECT_TRUE(extendee->is_placeholder());
  2397. ASSERT_EQ(1, extendee->extension_range_count());
  2398. EXPECT_EQ(1, extendee->extension_range(0)->start);
  2399. EXPECT_EQ(FieldDescriptor::kMaxNumber + 1, extendee->extension_range(0)->end);
  2400. }
  2401. TEST_P(AllowUnknownDependenciesTest, CustomOption) {
  2402. // Test that we can use a custom option without having parsed
  2403. // descriptor.proto.
  2404. FileDescriptorProto option_proto;
  2405. ASSERT_TRUE(TextFormat::ParseFromString(
  2406. "name: \"unknown_custom_options.proto\" "
  2407. "dependency: \"google/protobuf/descriptor.proto\" "
  2408. "extension { "
  2409. " extendee: \"google.protobuf.FileOptions\" "
  2410. " name: \"some_option\" "
  2411. " number: 123456 "
  2412. " label: LABEL_OPTIONAL "
  2413. " type: TYPE_INT32 "
  2414. "} "
  2415. "options { "
  2416. " uninterpreted_option { "
  2417. " name { "
  2418. " name_part: \"some_option\" "
  2419. " is_extension: true "
  2420. " } "
  2421. " positive_int_value: 1234 "
  2422. " } "
  2423. " uninterpreted_option { "
  2424. " name { "
  2425. " name_part: \"unknown_option\" "
  2426. " is_extension: true "
  2427. " } "
  2428. " positive_int_value: 1234 "
  2429. " } "
  2430. " uninterpreted_option { "
  2431. " name { "
  2432. " name_part: \"optimize_for\" "
  2433. " is_extension: false "
  2434. " } "
  2435. " identifier_value: \"SPEED\" "
  2436. " } "
  2437. "}",
  2438. &option_proto));
  2439. const FileDescriptor* file = BuildFile(option_proto);
  2440. ASSERT_TRUE(file != nullptr);
  2441. // Verify that no extension options were set, but they were left as
  2442. // uninterpreted_options.
  2443. std::vector<const FieldDescriptor*> fields;
  2444. file->options().GetReflection()->ListFields(file->options(), &fields);
  2445. ASSERT_EQ(2, fields.size());
  2446. EXPECT_TRUE(file->options().has_optimize_for());
  2447. EXPECT_EQ(2, file->options().uninterpreted_option_size());
  2448. }
  2449. TEST_P(AllowUnknownDependenciesTest,
  2450. UndeclaredDependencyTriggersBuildOfDependency) {
  2451. // Crazy case: suppose foo.proto refers to a symbol without declaring the
  2452. // dependency that finds it. In the event that the pool is backed by a
  2453. // DescriptorDatabase, the pool will attempt to find the symbol in the
  2454. // database. If successful, it will build the undeclared dependency to verify
  2455. // that the file does indeed contain the symbol. If that file fails to build,
  2456. // then its descriptors must be rolled back. However, we still want foo.proto
  2457. // to build successfully, since we are allowing unknown dependencies.
  2458. FileDescriptorProto undeclared_dep_proto;
  2459. // We make this file fail to build by giving it two fields with tag 1.
  2460. ASSERT_TRUE(TextFormat::ParseFromString(
  2461. "name: \"invalid_file_as_undeclared_dep.proto\" "
  2462. "package: \"undeclared\" "
  2463. "message_type: { "
  2464. " name: \"Quux\" "
  2465. " field { "
  2466. " name:'qux' number:1 label:LABEL_OPTIONAL type: TYPE_INT32 "
  2467. " }"
  2468. " field { "
  2469. " name:'quux' number:1 label:LABEL_OPTIONAL type: TYPE_INT64 "
  2470. " }"
  2471. "}",
  2472. &undeclared_dep_proto));
  2473. // We can't use the BuildFile() helper because we don't actually want to build
  2474. // it into the descriptor pool in the fallback database case: it just needs to
  2475. // be sitting in the database so that it gets built during the building of
  2476. // test.proto below.
  2477. switch (mode()) {
  2478. case NO_DATABASE: {
  2479. ASSERT_TRUE(pool_->BuildFile(undeclared_dep_proto) == nullptr);
  2480. break;
  2481. }
  2482. case FALLBACK_DATABASE: {
  2483. ASSERT_TRUE(db_.Add(undeclared_dep_proto));
  2484. }
  2485. }
  2486. FileDescriptorProto test_proto;
  2487. ASSERT_TRUE(TextFormat::ParseFromString(
  2488. "name: \"test.proto\" "
  2489. "message_type: { "
  2490. " name: \"Corge\" "
  2491. " field { "
  2492. " name:'quux' number:1 label: LABEL_OPTIONAL "
  2493. " type_name:'undeclared.Quux' type: TYPE_MESSAGE "
  2494. " }"
  2495. "}",
  2496. &test_proto));
  2497. const FileDescriptor* file = BuildFile(test_proto);
  2498. ASSERT_TRUE(file != nullptr);
  2499. GOOGLE_LOG(INFO) << file->DebugString();
  2500. EXPECT_EQ(0, file->dependency_count());
  2501. ASSERT_EQ(1, file->message_type_count());
  2502. const Descriptor* corge_desc = file->message_type(0);
  2503. ASSERT_EQ("Corge", corge_desc->name());
  2504. ASSERT_EQ(1, corge_desc->field_count());
  2505. EXPECT_FALSE(corge_desc->is_placeholder());
  2506. const FieldDescriptor* quux_field = corge_desc->field(0);
  2507. ASSERT_EQ(FieldDescriptor::TYPE_MESSAGE, quux_field->type());
  2508. ASSERT_EQ("Quux", quux_field->message_type()->name());
  2509. ASSERT_EQ("undeclared.Quux", quux_field->message_type()->full_name());
  2510. EXPECT_TRUE(quux_field->message_type()->is_placeholder());
  2511. // The place holder type should not be findable.
  2512. ASSERT_TRUE(pool_->FindMessageTypeByName("undeclared.Quux") == nullptr);
  2513. }
  2514. INSTANTIATE_TEST_SUITE_P(DatabaseSource, AllowUnknownDependenciesTest,
  2515. testing::Values(NO_DATABASE, FALLBACK_DATABASE));
  2516. // ===================================================================
  2517. TEST(CustomOptions, OptionLocations) {
  2518. const Descriptor* message =
  2519. protobuf_unittest::TestMessageWithCustomOptions::descriptor();
  2520. const FileDescriptor* file = message->file();
  2521. const FieldDescriptor* field = message->FindFieldByName("field1");
  2522. const OneofDescriptor* oneof = message->FindOneofByName("AnOneof");
  2523. const EnumDescriptor* enm = message->FindEnumTypeByName("AnEnum");
  2524. // TODO(benjy): Support EnumValue options, once the compiler does.
  2525. const ServiceDescriptor* service =
  2526. file->FindServiceByName("TestServiceWithCustomOptions");
  2527. const MethodDescriptor* method = service->FindMethodByName("Foo");
  2528. EXPECT_EQ(PROTOBUF_LONGLONG(9876543210),
  2529. file->options().GetExtension(protobuf_unittest::file_opt1));
  2530. EXPECT_EQ(-56,
  2531. message->options().GetExtension(protobuf_unittest::message_opt1));
  2532. EXPECT_EQ(PROTOBUF_LONGLONG(8765432109),
  2533. field->options().GetExtension(protobuf_unittest::field_opt1));
  2534. EXPECT_EQ(42, // Check that we get the default for an option we don't set.
  2535. field->options().GetExtension(protobuf_unittest::field_opt2));
  2536. EXPECT_EQ(-99, oneof->options().GetExtension(protobuf_unittest::oneof_opt1));
  2537. EXPECT_EQ(-789, enm->options().GetExtension(protobuf_unittest::enum_opt1));
  2538. EXPECT_EQ(123, enm->value(1)->options().GetExtension(
  2539. protobuf_unittest::enum_value_opt1));
  2540. EXPECT_EQ(PROTOBUF_LONGLONG(-9876543210),
  2541. service->options().GetExtension(protobuf_unittest::service_opt1));
  2542. EXPECT_EQ(protobuf_unittest::METHODOPT1_VAL2,
  2543. method->options().GetExtension(protobuf_unittest::method_opt1));
  2544. // See that the regular options went through unscathed.
  2545. EXPECT_TRUE(message->options().has_message_set_wire_format());
  2546. EXPECT_EQ(FieldOptions::CORD, field->options().ctype());
  2547. }
  2548. TEST(CustomOptions, OptionTypes) {
  2549. const MessageOptions* options = nullptr;
  2550. options =
  2551. &protobuf_unittest::CustomOptionMinIntegerValues::descriptor()->options();
  2552. EXPECT_EQ(false, options->GetExtension(protobuf_unittest::bool_opt));
  2553. EXPECT_EQ(kint32min, options->GetExtension(protobuf_unittest::int32_opt));
  2554. EXPECT_EQ(kint64min, options->GetExtension(protobuf_unittest::int64_opt));
  2555. EXPECT_EQ(0, options->GetExtension(protobuf_unittest::uint32_opt));
  2556. EXPECT_EQ(0, options->GetExtension(protobuf_unittest::uint64_opt));
  2557. EXPECT_EQ(kint32min, options->GetExtension(protobuf_unittest::sint32_opt));
  2558. EXPECT_EQ(kint64min, options->GetExtension(protobuf_unittest::sint64_opt));
  2559. EXPECT_EQ(0, options->GetExtension(protobuf_unittest::fixed32_opt));
  2560. EXPECT_EQ(0, options->GetExtension(protobuf_unittest::fixed64_opt));
  2561. EXPECT_EQ(kint32min, options->GetExtension(protobuf_unittest::sfixed32_opt));
  2562. EXPECT_EQ(kint64min, options->GetExtension(protobuf_unittest::sfixed64_opt));
  2563. options =
  2564. &protobuf_unittest::CustomOptionMaxIntegerValues::descriptor()->options();
  2565. EXPECT_EQ(true, options->GetExtension(protobuf_unittest::bool_opt));
  2566. EXPECT_EQ(kint32max, options->GetExtension(protobuf_unittest::int32_opt));
  2567. EXPECT_EQ(kint64max, options->GetExtension(protobuf_unittest::int64_opt));
  2568. EXPECT_EQ(kuint32max, options->GetExtension(protobuf_unittest::uint32_opt));
  2569. EXPECT_EQ(kuint64max, options->GetExtension(protobuf_unittest::uint64_opt));
  2570. EXPECT_EQ(kint32max, options->GetExtension(protobuf_unittest::sint32_opt));
  2571. EXPECT_EQ(kint64max, options->GetExtension(protobuf_unittest::sint64_opt));
  2572. EXPECT_EQ(kuint32max, options->GetExtension(protobuf_unittest::fixed32_opt));
  2573. EXPECT_EQ(kuint64max, options->GetExtension(protobuf_unittest::fixed64_opt));
  2574. EXPECT_EQ(kint32max, options->GetExtension(protobuf_unittest::sfixed32_opt));
  2575. EXPECT_EQ(kint64max, options->GetExtension(protobuf_unittest::sfixed64_opt));
  2576. options = &protobuf_unittest::CustomOptionOtherValues::descriptor()->options();
  2577. EXPECT_EQ(-100, options->GetExtension(protobuf_unittest::int32_opt));
  2578. EXPECT_FLOAT_EQ(12.3456789,
  2579. options->GetExtension(protobuf_unittest::float_opt));
  2580. EXPECT_DOUBLE_EQ(1.234567890123456789,
  2581. options->GetExtension(protobuf_unittest::double_opt));
  2582. EXPECT_EQ("Hello, \"World\"",
  2583. options->GetExtension(protobuf_unittest::string_opt));
  2584. EXPECT_EQ(std::string("Hello\0World", 11),
  2585. options->GetExtension(protobuf_unittest::bytes_opt));
  2586. EXPECT_EQ(protobuf_unittest::DummyMessageContainingEnum::TEST_OPTION_ENUM_TYPE2,
  2587. options->GetExtension(protobuf_unittest::enum_opt));
  2588. options =
  2589. &protobuf_unittest::SettingRealsFromPositiveInts::descriptor()->options();
  2590. EXPECT_FLOAT_EQ(12, options->GetExtension(protobuf_unittest::float_opt));
  2591. EXPECT_DOUBLE_EQ(154, options->GetExtension(protobuf_unittest::double_opt));
  2592. options =
  2593. &protobuf_unittest::SettingRealsFromNegativeInts::descriptor()->options();
  2594. EXPECT_FLOAT_EQ(-12, options->GetExtension(protobuf_unittest::float_opt));
  2595. EXPECT_DOUBLE_EQ(-154, options->GetExtension(protobuf_unittest::double_opt));
  2596. }
  2597. TEST(CustomOptions, ComplexExtensionOptions) {
  2598. const MessageOptions* options =
  2599. &protobuf_unittest::VariousComplexOptions::descriptor()->options();
  2600. EXPECT_EQ(options->GetExtension(protobuf_unittest::complex_opt1).foo(), 42);
  2601. EXPECT_EQ(options->GetExtension(protobuf_unittest::complex_opt1)
  2602. .GetExtension(protobuf_unittest::quux),
  2603. 324);
  2604. EXPECT_EQ(options->GetExtension(protobuf_unittest::complex_opt1)
  2605. .GetExtension(protobuf_unittest::corge)
  2606. .qux(),
  2607. 876);
  2608. EXPECT_EQ(options->GetExtension(protobuf_unittest::complex_opt2).baz(), 987);
  2609. EXPECT_EQ(options->GetExtension(protobuf_unittest::complex_opt2)
  2610. .GetExtension(protobuf_unittest::grault),
  2611. 654);
  2612. EXPECT_EQ(options->GetExtension(protobuf_unittest::complex_opt2).bar().foo(),
  2613. 743);
  2614. EXPECT_EQ(options->GetExtension(protobuf_unittest::complex_opt2)
  2615. .bar()
  2616. .GetExtension(protobuf_unittest::quux),
  2617. 1999);
  2618. EXPECT_EQ(options->GetExtension(protobuf_unittest::complex_opt2)
  2619. .bar()
  2620. .GetExtension(protobuf_unittest::corge)
  2621. .qux(),
  2622. 2008);
  2623. EXPECT_EQ(options->GetExtension(protobuf_unittest::complex_opt2)
  2624. .GetExtension(protobuf_unittest::garply)
  2625. .foo(),
  2626. 741);
  2627. EXPECT_EQ(options->GetExtension(protobuf_unittest::complex_opt2)
  2628. .GetExtension(protobuf_unittest::garply)
  2629. .GetExtension(protobuf_unittest::quux),
  2630. 1998);
  2631. EXPECT_EQ(options->GetExtension(protobuf_unittest::complex_opt2)
  2632. .GetExtension(protobuf_unittest::garply)
  2633. .GetExtension(protobuf_unittest::corge)
  2634. .qux(),
  2635. 2121);
  2636. EXPECT_EQ(options
  2637. ->GetExtension(protobuf_unittest::ComplexOptionType2::
  2638. ComplexOptionType4::complex_opt4)
  2639. .waldo(),
  2640. 1971);
  2641. EXPECT_EQ(options->GetExtension(protobuf_unittest::complex_opt2).fred().waldo(),
  2642. 321);
  2643. EXPECT_EQ(9, options->GetExtension(protobuf_unittest::complex_opt3).qux());
  2644. EXPECT_EQ(22, options->GetExtension(protobuf_unittest::complex_opt3)
  2645. .complexoptiontype5()
  2646. .plugh());
  2647. EXPECT_EQ(24, options->GetExtension(protobuf_unittest::complexopt6).xyzzy());
  2648. }
  2649. TEST(CustomOptions, OptionsFromOtherFile) {
  2650. // Test that to use a custom option, we only need to import the file
  2651. // defining the option; we do not also have to import descriptor.proto.
  2652. DescriptorPool pool;
  2653. FileDescriptorProto file_proto;
  2654. FileDescriptorProto::descriptor()->file()->CopyTo(&file_proto);
  2655. ASSERT_TRUE(pool.BuildFile(file_proto) != nullptr);
  2656. protobuf_unittest::TestMessageWithCustomOptions::descriptor()->file()->CopyTo(
  2657. &file_proto);
  2658. ASSERT_TRUE(pool.BuildFile(file_proto) != nullptr);
  2659. ASSERT_TRUE(TextFormat::ParseFromString(
  2660. "name: \"custom_options_import.proto\" "
  2661. "package: \"protobuf_unittest\" "
  2662. "dependency: \"google/protobuf/unittest_custom_options.proto\" "
  2663. "options { "
  2664. " uninterpreted_option { "
  2665. " name { "
  2666. " name_part: \"file_opt1\" "
  2667. " is_extension: true "
  2668. " } "
  2669. " positive_int_value: 1234 "
  2670. " } "
  2671. // Test a non-extension option too. (At one point this failed due to a
  2672. // bug.)
  2673. " uninterpreted_option { "
  2674. " name { "
  2675. " name_part: \"java_package\" "
  2676. " is_extension: false "
  2677. " } "
  2678. " string_value: \"foo\" "
  2679. " } "
  2680. // Test that enum-typed options still work too. (At one point this also
  2681. // failed due to a bug.)
  2682. " uninterpreted_option { "
  2683. " name { "
  2684. " name_part: \"optimize_for\" "
  2685. " is_extension: false "
  2686. " } "
  2687. " identifier_value: \"SPEED\" "
  2688. " } "
  2689. "}",
  2690. &file_proto));
  2691. const FileDescriptor* file = pool.BuildFile(file_proto);
  2692. ASSERT_TRUE(file != nullptr);
  2693. EXPECT_EQ(1234, file->options().GetExtension(protobuf_unittest::file_opt1));
  2694. EXPECT_TRUE(file->options().has_java_package());
  2695. EXPECT_EQ("foo", file->options().java_package());
  2696. EXPECT_TRUE(file->options().has_optimize_for());
  2697. EXPECT_EQ(FileOptions::SPEED, file->options().optimize_for());
  2698. }
  2699. TEST(CustomOptions, MessageOptionThreeFieldsSet) {
  2700. // This tests a bug which previously existed in custom options parsing. The
  2701. // bug occurred when you defined a custom option with message type and then
  2702. // set three fields of that option on a single definition (see the example
  2703. // below). The bug is a bit hard to explain, so check the change history if
  2704. // you want to know more.
  2705. DescriptorPool pool;
  2706. FileDescriptorProto file_proto;
  2707. FileDescriptorProto::descriptor()->file()->CopyTo(&file_proto);
  2708. ASSERT_TRUE(pool.BuildFile(file_proto) != nullptr);
  2709. protobuf_unittest::TestMessageWithCustomOptions::descriptor()->file()->CopyTo(
  2710. &file_proto);
  2711. ASSERT_TRUE(pool.BuildFile(file_proto) != nullptr);
  2712. // The following represents the definition:
  2713. //
  2714. // import "google/protobuf/unittest_custom_options.proto"
  2715. // package protobuf_unittest;
  2716. // message Foo {
  2717. // option (complex_opt1).foo = 1234;
  2718. // option (complex_opt1).foo2 = 1234;
  2719. // option (complex_opt1).foo3 = 1234;
  2720. // }
  2721. ASSERT_TRUE(TextFormat::ParseFromString(
  2722. "name: \"custom_options_import.proto\" "
  2723. "package: \"protobuf_unittest\" "
  2724. "dependency: \"google/protobuf/unittest_custom_options.proto\" "
  2725. "message_type { "
  2726. " name: \"Foo\" "
  2727. " options { "
  2728. " uninterpreted_option { "
  2729. " name { "
  2730. " name_part: \"complex_opt1\" "
  2731. " is_extension: true "
  2732. " } "
  2733. " name { "
  2734. " name_part: \"foo\" "
  2735. " is_extension: false "
  2736. " } "
  2737. " positive_int_value: 1234 "
  2738. " } "
  2739. " uninterpreted_option { "
  2740. " name { "
  2741. " name_part: \"complex_opt1\" "
  2742. " is_extension: true "
  2743. " } "
  2744. " name { "
  2745. " name_part: \"foo2\" "
  2746. " is_extension: false "
  2747. " } "
  2748. " positive_int_value: 1234 "
  2749. " } "
  2750. " uninterpreted_option { "
  2751. " name { "
  2752. " name_part: \"complex_opt1\" "
  2753. " is_extension: true "
  2754. " } "
  2755. " name { "
  2756. " name_part: \"foo3\" "
  2757. " is_extension: false "
  2758. " } "
  2759. " positive_int_value: 1234 "
  2760. " } "
  2761. " } "
  2762. "}",
  2763. &file_proto));
  2764. const FileDescriptor* file = pool.BuildFile(file_proto);
  2765. ASSERT_TRUE(file != nullptr);
  2766. ASSERT_EQ(1, file->message_type_count());
  2767. const MessageOptions& options = file->message_type(0)->options();
  2768. EXPECT_EQ(1234, options.GetExtension(protobuf_unittest::complex_opt1).foo());
  2769. }
  2770. TEST(CustomOptions, MessageOptionRepeatedLeafFieldSet) {
  2771. // This test verifies that repeated fields in custom options can be
  2772. // given multiple values by repeating the option with a different value.
  2773. // This test checks repeated leaf values. Each repeated custom value
  2774. // appears in a different uninterpreted_option, which will be concatenated
  2775. // when they are merged into the final option value.
  2776. DescriptorPool pool;
  2777. FileDescriptorProto file_proto;
  2778. FileDescriptorProto::descriptor()->file()->CopyTo(&file_proto);
  2779. ASSERT_TRUE(pool.BuildFile(file_proto) != nullptr);
  2780. protobuf_unittest::TestMessageWithCustomOptions::descriptor()->file()->CopyTo(
  2781. &file_proto);
  2782. ASSERT_TRUE(pool.BuildFile(file_proto) != nullptr);
  2783. // The following represents the definition:
  2784. //
  2785. // import "google/protobuf/unittest_custom_options.proto"
  2786. // package protobuf_unittest;
  2787. // message Foo {
  2788. // option (complex_opt1).foo4 = 12;
  2789. // option (complex_opt1).foo4 = 34;
  2790. // option (complex_opt1).foo4 = 56;
  2791. // }
  2792. ASSERT_TRUE(TextFormat::ParseFromString(
  2793. "name: \"custom_options_import.proto\" "
  2794. "package: \"protobuf_unittest\" "
  2795. "dependency: \"google/protobuf/unittest_custom_options.proto\" "
  2796. "message_type { "
  2797. " name: \"Foo\" "
  2798. " options { "
  2799. " uninterpreted_option { "
  2800. " name { "
  2801. " name_part: \"complex_opt1\" "
  2802. " is_extension: true "
  2803. " } "
  2804. " name { "
  2805. " name_part: \"foo4\" "
  2806. " is_extension: false "
  2807. " } "
  2808. " positive_int_value: 12 "
  2809. " } "
  2810. " uninterpreted_option { "
  2811. " name { "
  2812. " name_part: \"complex_opt1\" "
  2813. " is_extension: true "
  2814. " } "
  2815. " name { "
  2816. " name_part: \"foo4\" "
  2817. " is_extension: false "
  2818. " } "
  2819. " positive_int_value: 34 "
  2820. " } "
  2821. " uninterpreted_option { "
  2822. " name { "
  2823. " name_part: \"complex_opt1\" "
  2824. " is_extension: true "
  2825. " } "
  2826. " name { "
  2827. " name_part: \"foo4\" "
  2828. " is_extension: false "
  2829. " } "
  2830. " positive_int_value: 56 "
  2831. " } "
  2832. " } "
  2833. "}",
  2834. &file_proto));
  2835. const FileDescriptor* file = pool.BuildFile(file_proto);
  2836. ASSERT_TRUE(file != nullptr);
  2837. ASSERT_EQ(1, file->message_type_count());
  2838. const MessageOptions& options = file->message_type(0)->options();
  2839. EXPECT_EQ(3, options.GetExtension(protobuf_unittest::complex_opt1).foo4_size());
  2840. EXPECT_EQ(12, options.GetExtension(protobuf_unittest::complex_opt1).foo4(0));
  2841. EXPECT_EQ(34, options.GetExtension(protobuf_unittest::complex_opt1).foo4(1));
  2842. EXPECT_EQ(56, options.GetExtension(protobuf_unittest::complex_opt1).foo4(2));
  2843. }
  2844. TEST(CustomOptions, MessageOptionRepeatedMsgFieldSet) {
  2845. // This test verifies that repeated fields in custom options can be
  2846. // given multiple values by repeating the option with a different value.
  2847. // This test checks repeated message values. Each repeated custom value
  2848. // appears in a different uninterpreted_option, which will be concatenated
  2849. // when they are merged into the final option value.
  2850. DescriptorPool pool;
  2851. FileDescriptorProto file_proto;
  2852. FileDescriptorProto::descriptor()->file()->CopyTo(&file_proto);
  2853. ASSERT_TRUE(pool.BuildFile(file_proto) != nullptr);
  2854. protobuf_unittest::TestMessageWithCustomOptions::descriptor()->file()->CopyTo(
  2855. &file_proto);
  2856. ASSERT_TRUE(pool.BuildFile(file_proto) != nullptr);
  2857. // The following represents the definition:
  2858. //
  2859. // import "google/protobuf/unittest_custom_options.proto"
  2860. // package protobuf_unittest;
  2861. // message Foo {
  2862. // option (complex_opt2).barney = {waldo: 1};
  2863. // option (complex_opt2).barney = {waldo: 10};
  2864. // option (complex_opt2).barney = {waldo: 100};
  2865. // }
  2866. ASSERT_TRUE(TextFormat::ParseFromString(
  2867. "name: \"custom_options_import.proto\" "
  2868. "package: \"protobuf_unittest\" "
  2869. "dependency: \"google/protobuf/unittest_custom_options.proto\" "
  2870. "message_type { "
  2871. " name: \"Foo\" "
  2872. " options { "
  2873. " uninterpreted_option { "
  2874. " name { "
  2875. " name_part: \"complex_opt2\" "
  2876. " is_extension: true "
  2877. " } "
  2878. " name { "
  2879. " name_part: \"barney\" "
  2880. " is_extension: false "
  2881. " } "
  2882. " aggregate_value: \"waldo: 1\" "
  2883. " } "
  2884. " uninterpreted_option { "
  2885. " name { "
  2886. " name_part: \"complex_opt2\" "
  2887. " is_extension: true "
  2888. " } "
  2889. " name { "
  2890. " name_part: \"barney\" "
  2891. " is_extension: false "
  2892. " } "
  2893. " aggregate_value: \"waldo: 10\" "
  2894. " } "
  2895. " uninterpreted_option { "
  2896. " name { "
  2897. " name_part: \"complex_opt2\" "
  2898. " is_extension: true "
  2899. " } "
  2900. " name { "
  2901. " name_part: \"barney\" "
  2902. " is_extension: false "
  2903. " } "
  2904. " aggregate_value: \"waldo: 100\" "
  2905. " } "
  2906. " } "
  2907. "}",
  2908. &file_proto));
  2909. const FileDescriptor* file = pool.BuildFile(file_proto);
  2910. ASSERT_TRUE(file != nullptr);
  2911. ASSERT_EQ(1, file->message_type_count());
  2912. const MessageOptions& options = file->message_type(0)->options();
  2913. EXPECT_EQ(3,
  2914. options.GetExtension(protobuf_unittest::complex_opt2).barney_size());
  2915. EXPECT_EQ(
  2916. 1, options.GetExtension(protobuf_unittest::complex_opt2).barney(0).waldo());
  2917. EXPECT_EQ(
  2918. 10,
  2919. options.GetExtension(protobuf_unittest::complex_opt2).barney(1).waldo());
  2920. EXPECT_EQ(
  2921. 100,
  2922. options.GetExtension(protobuf_unittest::complex_opt2).barney(2).waldo());
  2923. }
  2924. // Check that aggregate options were parsed and saved correctly in
  2925. // the appropriate descriptors.
  2926. TEST(CustomOptions, AggregateOptions) {
  2927. const Descriptor* msg = protobuf_unittest::AggregateMessage::descriptor();
  2928. const FileDescriptor* file = msg->file();
  2929. const FieldDescriptor* field = msg->FindFieldByName("fieldname");
  2930. const EnumDescriptor* enumd = file->FindEnumTypeByName("AggregateEnum");
  2931. const EnumValueDescriptor* enumv = enumd->FindValueByName("VALUE");
  2932. const ServiceDescriptor* service =
  2933. file->FindServiceByName("AggregateService");
  2934. const MethodDescriptor* method = service->FindMethodByName("Method");
  2935. // Tests for the different types of data embedded in fileopt
  2936. const protobuf_unittest::Aggregate& file_options =
  2937. file->options().GetExtension(protobuf_unittest::fileopt);
  2938. EXPECT_EQ(100, file_options.i());
  2939. EXPECT_EQ("FileAnnotation", file_options.s());
  2940. EXPECT_EQ("NestedFileAnnotation", file_options.sub().s());
  2941. EXPECT_EQ("FileExtensionAnnotation",
  2942. file_options.file().GetExtension(protobuf_unittest::fileopt).s());
  2943. EXPECT_EQ("EmbeddedMessageSetElement",
  2944. file_options.mset()
  2945. .GetExtension(protobuf_unittest::AggregateMessageSetElement ::
  2946. message_set_extension)
  2947. .s());
  2948. // Simple tests for all the other types of annotations
  2949. EXPECT_EQ("MessageAnnotation",
  2950. msg->options().GetExtension(protobuf_unittest::msgopt).s());
  2951. EXPECT_EQ("FieldAnnotation",
  2952. field->options().GetExtension(protobuf_unittest::fieldopt).s());
  2953. EXPECT_EQ("EnumAnnotation",
  2954. enumd->options().GetExtension(protobuf_unittest::enumopt).s());
  2955. EXPECT_EQ("EnumValueAnnotation",
  2956. enumv->options().GetExtension(protobuf_unittest::enumvalopt).s());
  2957. EXPECT_EQ("ServiceAnnotation",
  2958. service->options().GetExtension(protobuf_unittest::serviceopt).s());
  2959. EXPECT_EQ("MethodAnnotation",
  2960. method->options().GetExtension(protobuf_unittest::methodopt).s());
  2961. }
  2962. TEST(CustomOptions, UnusedImportWarning) {
  2963. DescriptorPool pool;
  2964. FileDescriptorProto file_proto;
  2965. FileDescriptorProto::descriptor()->file()->CopyTo(&file_proto);
  2966. ASSERT_TRUE(pool.BuildFile(file_proto) != nullptr);
  2967. protobuf_unittest::TestMessageWithCustomOptions::descriptor()->file()->CopyTo(
  2968. &file_proto);
  2969. ASSERT_TRUE(pool.BuildFile(file_proto) != nullptr);
  2970. pool.AddUnusedImportTrackFile("custom_options_import.proto");
  2971. ASSERT_TRUE(TextFormat::ParseFromString(
  2972. "name: \"custom_options_import.proto\" "
  2973. "package: \"protobuf_unittest\" "
  2974. "dependency: \"google/protobuf/unittest_custom_options.proto\" ",
  2975. &file_proto));
  2976. MockErrorCollector error_collector;
  2977. EXPECT_TRUE(pool.BuildFileCollectingErrors(file_proto, &error_collector));
  2978. EXPECT_EQ(
  2979. "custom_options_import.proto: "
  2980. "google/protobuf/unittest_custom_options.proto: IMPORT: Import "
  2981. "google/protobuf/unittest_custom_options.proto is unused.\n",
  2982. error_collector.warning_text_);
  2983. EXPECT_EQ("", error_collector.text_);
  2984. }
  2985. // Verifies that proto files can correctly be parsed, even if the
  2986. // custom options defined in the file are incompatible with those
  2987. // compiled in the binary. See http://b/19276250.
  2988. TEST(CustomOptions, OptionsWithIncompatibleDescriptors) {
  2989. DescriptorPool pool;
  2990. FileDescriptorProto file_proto;
  2991. MessageOptions::descriptor()->file()->CopyTo(&file_proto);
  2992. ASSERT_TRUE(pool.BuildFile(file_proto) != nullptr);
  2993. // Create a new file descriptor proto containing a subset of the
  2994. // messages defined in google/protobuf/unittest_custom_options.proto.
  2995. file_proto.Clear();
  2996. file_proto.set_name("unittest_custom_options.proto");
  2997. file_proto.set_package("protobuf_unittest");
  2998. file_proto.add_dependency("google/protobuf/descriptor.proto");
  2999. // Add the "required_enum_opt" extension.
  3000. FieldDescriptorProto* extension = file_proto.add_extension();
  3001. protobuf_unittest::OldOptionType::descriptor()
  3002. ->file()
  3003. ->FindExtensionByName("required_enum_opt")
  3004. ->CopyTo(extension);
  3005. // Add a test message that uses the "required_enum_opt" option.
  3006. DescriptorProto* test_message_type = file_proto.add_message_type();
  3007. protobuf_unittest::TestMessageWithRequiredEnumOption::descriptor()->CopyTo(
  3008. test_message_type);
  3009. // Instruct the extension to use NewOptionType instead of
  3010. // OldOptionType, and add the descriptor of NewOptionType.
  3011. extension->set_type_name(".protobuf_unittest.NewOptionType");
  3012. DescriptorProto* new_option_type = file_proto.add_message_type();
  3013. protobuf_unittest::NewOptionType::descriptor()->CopyTo(new_option_type);
  3014. // Replace the value of the "required_enum_opt" option used in the
  3015. // test message with an enum value that only exists in NewOptionType.
  3016. ASSERT_TRUE(
  3017. TextFormat::ParseFromString("uninterpreted_option { "
  3018. " name { "
  3019. " name_part: 'required_enum_opt' "
  3020. " is_extension: true "
  3021. " } "
  3022. " aggregate_value: 'value: NEW_VALUE'"
  3023. "}",
  3024. test_message_type->mutable_options()));
  3025. // Adding the file descriptor to the pool should fail.
  3026. EXPECT_TRUE(pool.BuildFile(file_proto) == nullptr);
  3027. }
  3028. // Test that FileDescriptor::DebugString() formats custom options correctly.
  3029. TEST(CustomOptions, DebugString) {
  3030. DescriptorPool pool;
  3031. FileDescriptorProto file_proto;
  3032. MessageOptions::descriptor()->file()->CopyTo(&file_proto);
  3033. ASSERT_TRUE(pool.BuildFile(file_proto) != nullptr);
  3034. // Add "foo.proto":
  3035. // import "google/protobuf/descriptor.proto";
  3036. // package "protobuf_unittest";
  3037. // option (protobuf_unittest.cc_option1) = 1;
  3038. // option (protobuf_unittest.cc_option2) = 2;
  3039. // extend google.protobuf.FieldOptions {
  3040. // optional int32 cc_option1 = 7736974;
  3041. // optional int32 cc_option2 = 7736975;
  3042. // }
  3043. ASSERT_TRUE(TextFormat::ParseFromString(
  3044. "name: \"foo.proto\" "
  3045. "package: \"protobuf_unittest\" "
  3046. "dependency: \"google/protobuf/descriptor.proto\" "
  3047. "options { "
  3048. " uninterpreted_option { "
  3049. " name { "
  3050. " name_part: \"protobuf_unittest.cc_option1\" "
  3051. " is_extension: true "
  3052. " } "
  3053. " positive_int_value: 1 "
  3054. " } "
  3055. " uninterpreted_option { "
  3056. " name { "
  3057. " name_part: \"protobuf_unittest.cc_option2\" "
  3058. " is_extension: true "
  3059. " } "
  3060. " positive_int_value: 2 "
  3061. " } "
  3062. "} "
  3063. "extension { "
  3064. " name: \"cc_option1\" "
  3065. " extendee: \".google.protobuf.FileOptions\" "
  3066. // This field number is intentionally chosen to be the same as
  3067. // (.fileopt1) defined in unittest_custom_options.proto (linked
  3068. // in this test binary). This is to test whether we are messing
  3069. // generated pool with custom descriptor pools when dealing with
  3070. // custom options.
  3071. " number: 7736974 "
  3072. " label: LABEL_OPTIONAL "
  3073. " type: TYPE_INT32 "
  3074. "}"
  3075. "extension { "
  3076. " name: \"cc_option2\" "
  3077. " extendee: \".google.protobuf.FileOptions\" "
  3078. " number: 7736975 "
  3079. " label: LABEL_OPTIONAL "
  3080. " type: TYPE_INT32 "
  3081. "}",
  3082. &file_proto));
  3083. const FileDescriptor* descriptor = pool.BuildFile(file_proto);
  3084. ASSERT_TRUE(descriptor != nullptr);
  3085. EXPECT_EQ(2, descriptor->extension_count());
  3086. ASSERT_EQ(
  3087. "syntax = \"proto2\";\n"
  3088. "\n"
  3089. "import \"google/protobuf/descriptor.proto\";\n"
  3090. "package protobuf_unittest;\n"
  3091. "\n"
  3092. "option (.protobuf_unittest.cc_option1) = 1;\n"
  3093. "option (.protobuf_unittest.cc_option2) = 2;\n"
  3094. "\n"
  3095. "extend .google.protobuf.FileOptions {\n"
  3096. " optional int32 cc_option1 = 7736974;\n"
  3097. " optional int32 cc_option2 = 7736975;\n"
  3098. "}\n"
  3099. "\n",
  3100. descriptor->DebugString());
  3101. }
  3102. // ===================================================================
  3103. class ValidationErrorTest : public testing::Test {
  3104. protected:
  3105. // Parse file_text as a FileDescriptorProto in text format and add it
  3106. // to the DescriptorPool. Expect no errors.
  3107. const FileDescriptor* BuildFile(const std::string& file_text) {
  3108. FileDescriptorProto file_proto;
  3109. EXPECT_TRUE(TextFormat::ParseFromString(file_text, &file_proto));
  3110. return GOOGLE_CHECK_NOTNULL(pool_.BuildFile(file_proto));
  3111. }
  3112. // Parse file_text as a FileDescriptorProto in text format and add it
  3113. // to the DescriptorPool. Expect errors to be produced which match the
  3114. // given error text.
  3115. void BuildFileWithErrors(const std::string& file_text,
  3116. const std::string& expected_errors) {
  3117. FileDescriptorProto file_proto;
  3118. ASSERT_TRUE(TextFormat::ParseFromString(file_text, &file_proto));
  3119. MockErrorCollector error_collector;
  3120. EXPECT_TRUE(pool_.BuildFileCollectingErrors(file_proto, &error_collector) ==
  3121. nullptr);
  3122. EXPECT_EQ(expected_errors, error_collector.text_);
  3123. }
  3124. // Parse file_text as a FileDescriptorProto in text format and add it
  3125. // to the DescriptorPool. Expect errors to be produced which match the
  3126. // given warning text.
  3127. void BuildFileWithWarnings(const std::string& file_text,
  3128. const std::string& expected_warnings) {
  3129. FileDescriptorProto file_proto;
  3130. ASSERT_TRUE(TextFormat::ParseFromString(file_text, &file_proto));
  3131. MockErrorCollector error_collector;
  3132. EXPECT_TRUE(pool_.BuildFileCollectingErrors(file_proto, &error_collector));
  3133. EXPECT_EQ(expected_warnings, error_collector.warning_text_);
  3134. }
  3135. // Builds some already-parsed file in our test pool.
  3136. void BuildFileInTestPool(const FileDescriptor* file) {
  3137. FileDescriptorProto file_proto;
  3138. file->CopyTo(&file_proto);
  3139. ASSERT_TRUE(pool_.BuildFile(file_proto) != nullptr);
  3140. }
  3141. // Build descriptor.proto in our test pool. This allows us to extend it in
  3142. // the test pool, so we can test custom options.
  3143. void BuildDescriptorMessagesInTestPool() {
  3144. BuildFileInTestPool(DescriptorProto::descriptor()->file());
  3145. }
  3146. DescriptorPool pool_;
  3147. };
  3148. TEST_F(ValidationErrorTest, AlreadyDefined) {
  3149. BuildFileWithErrors(
  3150. "name: \"foo.proto\" "
  3151. "message_type { name: \"Foo\" }"
  3152. "message_type { name: \"Foo\" }",
  3153. "foo.proto: Foo: NAME: \"Foo\" is already defined.\n");
  3154. }
  3155. TEST_F(ValidationErrorTest, AlreadyDefinedInPackage) {
  3156. BuildFileWithErrors(
  3157. "name: \"foo.proto\" "
  3158. "package: \"foo.bar\" "
  3159. "message_type { name: \"Foo\" }"
  3160. "message_type { name: \"Foo\" }",
  3161. "foo.proto: foo.bar.Foo: NAME: \"Foo\" is already defined in "
  3162. "\"foo.bar\".\n");
  3163. }
  3164. TEST_F(ValidationErrorTest, AlreadyDefinedInOtherFile) {
  3165. BuildFile(
  3166. "name: \"foo.proto\" "
  3167. "message_type { name: \"Foo\" }");
  3168. BuildFileWithErrors(
  3169. "name: \"bar.proto\" "
  3170. "message_type { name: \"Foo\" }",
  3171. "bar.proto: Foo: NAME: \"Foo\" is already defined in file "
  3172. "\"foo.proto\".\n");
  3173. }
  3174. TEST_F(ValidationErrorTest, PackageAlreadyDefined) {
  3175. BuildFile(
  3176. "name: \"foo.proto\" "
  3177. "message_type { name: \"foo\" }");
  3178. BuildFileWithErrors(
  3179. "name: \"bar.proto\" "
  3180. "package: \"foo.bar\"",
  3181. "bar.proto: foo: NAME: \"foo\" is already defined (as something other "
  3182. "than a package) in file \"foo.proto\".\n");
  3183. }
  3184. TEST_F(ValidationErrorTest, EnumValueAlreadyDefinedInParent) {
  3185. BuildFileWithErrors(
  3186. "name: \"foo.proto\" "
  3187. "enum_type { name: \"Foo\" value { name: \"FOO\" number: 1 } } "
  3188. "enum_type { name: \"Bar\" value { name: \"FOO\" number: 1 } } ",
  3189. "foo.proto: FOO: NAME: \"FOO\" is already defined.\n"
  3190. "foo.proto: FOO: NAME: Note that enum values use C++ scoping rules, "
  3191. "meaning that enum values are siblings of their type, not children of "
  3192. "it. Therefore, \"FOO\" must be unique within the global scope, not "
  3193. "just within \"Bar\".\n");
  3194. }
  3195. TEST_F(ValidationErrorTest, EnumValueAlreadyDefinedInParentNonGlobal) {
  3196. BuildFileWithErrors(
  3197. "name: \"foo.proto\" "
  3198. "package: \"pkg\" "
  3199. "enum_type { name: \"Foo\" value { name: \"FOO\" number: 1 } } "
  3200. "enum_type { name: \"Bar\" value { name: \"FOO\" number: 1 } } ",
  3201. "foo.proto: pkg.FOO: NAME: \"FOO\" is already defined in \"pkg\".\n"
  3202. "foo.proto: pkg.FOO: NAME: Note that enum values use C++ scoping rules, "
  3203. "meaning that enum values are siblings of their type, not children of "
  3204. "it. Therefore, \"FOO\" must be unique within \"pkg\", not just within "
  3205. "\"Bar\".\n");
  3206. }
  3207. TEST_F(ValidationErrorTest, MissingName) {
  3208. BuildFileWithErrors(
  3209. "name: \"foo.proto\" "
  3210. "message_type { }",
  3211. "foo.proto: : NAME: Missing name.\n");
  3212. }
  3213. TEST_F(ValidationErrorTest, InvalidName) {
  3214. BuildFileWithErrors(
  3215. "name: \"foo.proto\" "
  3216. "message_type { name: \"$\" }",
  3217. "foo.proto: $: NAME: \"$\" is not a valid identifier.\n");
  3218. }
  3219. TEST_F(ValidationErrorTest, InvalidPackageName) {
  3220. BuildFileWithErrors(
  3221. "name: \"foo.proto\" "
  3222. "package: \"foo.$\"",
  3223. "foo.proto: foo.$: NAME: \"$\" is not a valid identifier.\n");
  3224. }
  3225. TEST_F(ValidationErrorTest, MissingFileName) {
  3226. BuildFileWithErrors("",
  3227. ": : OTHER: Missing field: FileDescriptorProto.name.\n");
  3228. }
  3229. TEST_F(ValidationErrorTest, DupeDependency) {
  3230. BuildFile("name: \"foo.proto\"");
  3231. BuildFileWithErrors(
  3232. "name: \"bar.proto\" "
  3233. "dependency: \"foo.proto\" "
  3234. "dependency: \"foo.proto\" ",
  3235. "bar.proto: foo.proto: IMPORT: Import \"foo.proto\" was listed twice.\n");
  3236. }
  3237. TEST_F(ValidationErrorTest, UnknownDependency) {
  3238. BuildFileWithErrors(
  3239. "name: \"bar.proto\" "
  3240. "dependency: \"foo.proto\" ",
  3241. "bar.proto: foo.proto: IMPORT: Import \"foo.proto\" has not been "
  3242. "loaded.\n");
  3243. }
  3244. TEST_F(ValidationErrorTest, InvalidPublicDependencyIndex) {
  3245. BuildFile("name: \"foo.proto\"");
  3246. BuildFileWithErrors(
  3247. "name: \"bar.proto\" "
  3248. "dependency: \"foo.proto\" "
  3249. "public_dependency: 1",
  3250. "bar.proto: bar.proto: OTHER: Invalid public dependency index.\n");
  3251. }
  3252. TEST_F(ValidationErrorTest, ForeignUnimportedPackageNoCrash) {
  3253. // Used to crash: If we depend on a non-existent file and then refer to a
  3254. // package defined in a file that we didn't import, and that package is
  3255. // nested within a parent package which this file is also in, and we don't
  3256. // include that parent package in the name (i.e. we do a relative lookup)...
  3257. // Yes, really.
  3258. BuildFile(
  3259. "name: 'foo.proto' "
  3260. "package: 'outer.foo' ");
  3261. BuildFileWithErrors(
  3262. "name: 'bar.proto' "
  3263. "dependency: 'baz.proto' "
  3264. "package: 'outer.bar' "
  3265. "message_type { "
  3266. " name: 'Bar' "
  3267. " field { name:'bar' number:1 label:LABEL_OPTIONAL type_name:'foo.Foo' }"
  3268. "}",
  3269. "bar.proto: baz.proto: IMPORT: Import \"baz.proto\" has not been "
  3270. "loaded.\n"
  3271. "bar.proto: outer.bar.Bar.bar: TYPE: \"outer.foo\" seems to be defined "
  3272. "in "
  3273. "\"foo.proto\", which is not imported by \"bar.proto\". To use it here, "
  3274. "please add the necessary import.\n");
  3275. }
  3276. TEST_F(ValidationErrorTest, DupeFile) {
  3277. BuildFile(
  3278. "name: \"foo.proto\" "
  3279. "message_type { name: \"Foo\" }");
  3280. // Note: We should *not* get redundant errors about "Foo" already being
  3281. // defined.
  3282. BuildFileWithErrors(
  3283. "name: \"foo.proto\" "
  3284. "message_type { name: \"Foo\" } "
  3285. // Add another type so that the files aren't identical (in which case
  3286. // there would be no error).
  3287. "enum_type { name: \"Bar\" }",
  3288. "foo.proto: foo.proto: OTHER: A file with this name is already in the "
  3289. "pool.\n");
  3290. }
  3291. TEST_F(ValidationErrorTest, FieldInExtensionRange) {
  3292. BuildFileWithErrors(
  3293. "name: \"foo.proto\" "
  3294. "message_type {"
  3295. " name: \"Foo\""
  3296. " field { name: \"foo\" number: 9 label:LABEL_OPTIONAL type:TYPE_INT32 "
  3297. "}"
  3298. " field { name: \"bar\" number: 10 label:LABEL_OPTIONAL type:TYPE_INT32 "
  3299. "}"
  3300. " field { name: \"baz\" number: 19 label:LABEL_OPTIONAL type:TYPE_INT32 "
  3301. "}"
  3302. " field { name: \"qux\" number: 20 label:LABEL_OPTIONAL type:TYPE_INT32 "
  3303. "}"
  3304. " extension_range { start: 10 end: 20 }"
  3305. "}",
  3306. "foo.proto: Foo.bar: NUMBER: Extension range 10 to 19 includes field "
  3307. "\"bar\" (10).\n"
  3308. "foo.proto: Foo.baz: NUMBER: Extension range 10 to 19 includes field "
  3309. "\"baz\" (19).\n");
  3310. }
  3311. TEST_F(ValidationErrorTest, OverlappingExtensionRanges) {
  3312. BuildFileWithErrors(
  3313. "name: \"foo.proto\" "
  3314. "message_type {"
  3315. " name: \"Foo\""
  3316. " extension_range { start: 10 end: 20 }"
  3317. " extension_range { start: 20 end: 30 }"
  3318. " extension_range { start: 19 end: 21 }"
  3319. "}",
  3320. "foo.proto: Foo: NUMBER: Extension range 19 to 20 overlaps with "
  3321. "already-defined range 10 to 19.\n"
  3322. "foo.proto: Foo: NUMBER: Extension range 19 to 20 overlaps with "
  3323. "already-defined range 20 to 29.\n");
  3324. }
  3325. TEST_F(ValidationErrorTest, ReservedFieldError) {
  3326. BuildFileWithErrors(
  3327. "name: \"foo.proto\" "
  3328. "message_type {"
  3329. " name: \"Foo\""
  3330. " field { name: \"foo\" number: 15 label:LABEL_OPTIONAL type:TYPE_INT32 "
  3331. "}"
  3332. " reserved_range { start: 10 end: 20 }"
  3333. "}",
  3334. "foo.proto: Foo.foo: NUMBER: Field \"foo\" uses reserved number 15.\n");
  3335. }
  3336. TEST_F(ValidationErrorTest, ReservedExtensionRangeError) {
  3337. BuildFileWithErrors(
  3338. "name: \"foo.proto\" "
  3339. "message_type {"
  3340. " name: \"Foo\""
  3341. " extension_range { start: 10 end: 20 }"
  3342. " reserved_range { start: 5 end: 15 }"
  3343. "}",
  3344. "foo.proto: Foo: NUMBER: Extension range 10 to 19"
  3345. " overlaps with reserved range 5 to 14.\n");
  3346. }
  3347. TEST_F(ValidationErrorTest, ReservedExtensionRangeAdjacent) {
  3348. BuildFile(
  3349. "name: \"foo.proto\" "
  3350. "message_type {"
  3351. " name: \"Foo\""
  3352. " extension_range { start: 10 end: 20 }"
  3353. " reserved_range { start: 5 end: 10 }"
  3354. "}");
  3355. }
  3356. TEST_F(ValidationErrorTest, ReservedRangeOverlap) {
  3357. BuildFileWithErrors(
  3358. "name: \"foo.proto\" "
  3359. "message_type {"
  3360. " name: \"Foo\""
  3361. " reserved_range { start: 10 end: 20 }"
  3362. " reserved_range { start: 5 end: 15 }"
  3363. "}",
  3364. "foo.proto: Foo: NUMBER: Reserved range 5 to 14"
  3365. " overlaps with already-defined range 10 to 19.\n");
  3366. }
  3367. TEST_F(ValidationErrorTest, ReservedNameError) {
  3368. BuildFileWithErrors(
  3369. "name: \"foo.proto\" "
  3370. "message_type {"
  3371. " name: \"Foo\""
  3372. " field { name: \"foo\" number: 15 label:LABEL_OPTIONAL type:TYPE_INT32 "
  3373. "}"
  3374. " field { name: \"bar\" number: 16 label:LABEL_OPTIONAL type:TYPE_INT32 "
  3375. "}"
  3376. " field { name: \"baz\" number: 17 label:LABEL_OPTIONAL type:TYPE_INT32 "
  3377. "}"
  3378. " reserved_name: \"foo\""
  3379. " reserved_name: \"bar\""
  3380. "}",
  3381. "foo.proto: Foo.foo: NAME: Field name \"foo\" is reserved.\n"
  3382. "foo.proto: Foo.bar: NAME: Field name \"bar\" is reserved.\n");
  3383. }
  3384. TEST_F(ValidationErrorTest, ReservedNameRedundant) {
  3385. BuildFileWithErrors(
  3386. "name: \"foo.proto\" "
  3387. "message_type {"
  3388. " name: \"Foo\""
  3389. " reserved_name: \"foo\""
  3390. " reserved_name: \"foo\""
  3391. "}",
  3392. "foo.proto: foo: NAME: Field name \"foo\" is reserved multiple times.\n");
  3393. }
  3394. TEST_F(ValidationErrorTest, ReservedFieldsDebugString) {
  3395. const FileDescriptor* file = BuildFile(
  3396. "name: \"foo.proto\" "
  3397. "message_type {"
  3398. " name: \"Foo\""
  3399. " reserved_name: \"foo\""
  3400. " reserved_name: \"bar\""
  3401. " reserved_range { start: 5 end: 6 }"
  3402. " reserved_range { start: 10 end: 20 }"
  3403. "}");
  3404. ASSERT_EQ(
  3405. "syntax = \"proto2\";\n\n"
  3406. "message Foo {\n"
  3407. " reserved 5, 10 to 19;\n"
  3408. " reserved \"foo\", \"bar\";\n"
  3409. "}\n\n",
  3410. file->DebugString());
  3411. }
  3412. TEST_F(ValidationErrorTest, EnumReservedFieldError) {
  3413. BuildFileWithErrors(
  3414. "name: \"foo.proto\" "
  3415. "enum_type {"
  3416. " name: \"Foo\""
  3417. " value { name:\"BAR\" number:15 }"
  3418. " reserved_range { start: 10 end: 20 }"
  3419. "}",
  3420. "foo.proto: BAR: NUMBER: Enum value \"BAR\" uses reserved number 15.\n");
  3421. }
  3422. TEST_F(ValidationErrorTest, EnumNegativeReservedFieldError) {
  3423. BuildFileWithErrors(
  3424. "name: \"foo.proto\" "
  3425. "enum_type {"
  3426. " name: \"Foo\""
  3427. " value { name:\"BAR\" number:-15 }"
  3428. " reserved_range { start: -20 end: -10 }"
  3429. "}",
  3430. "foo.proto: BAR: NUMBER: Enum value \"BAR\" uses reserved number -15.\n");
  3431. }
  3432. TEST_F(ValidationErrorTest, EnumReservedRangeOverlap) {
  3433. BuildFileWithErrors(
  3434. "name: \"foo.proto\" "
  3435. "enum_type {"
  3436. " name: \"Foo\""
  3437. " value { name:\"BAR\" number:0 }"
  3438. " reserved_range { start: 10 end: 20 }"
  3439. " reserved_range { start: 5 end: 15 }"
  3440. "}",
  3441. "foo.proto: Foo: NUMBER: Reserved range 5 to 15"
  3442. " overlaps with already-defined range 10 to 20.\n");
  3443. }
  3444. TEST_F(ValidationErrorTest, EnumReservedRangeOverlapByOne) {
  3445. BuildFileWithErrors(
  3446. "name: \"foo.proto\" "
  3447. "enum_type {"
  3448. " name: \"Foo\""
  3449. " value { name:\"BAR\" number:0 }"
  3450. " reserved_range { start: 10 end: 20 }"
  3451. " reserved_range { start: 5 end: 10 }"
  3452. "}",
  3453. "foo.proto: Foo: NUMBER: Reserved range 5 to 10"
  3454. " overlaps with already-defined range 10 to 20.\n");
  3455. }
  3456. TEST_F(ValidationErrorTest, EnumNegativeReservedRangeOverlap) {
  3457. BuildFileWithErrors(
  3458. "name: \"foo.proto\" "
  3459. "enum_type {"
  3460. " name: \"Foo\""
  3461. " value { name:\"BAR\" number:0 }"
  3462. " reserved_range { start: -20 end: -10 }"
  3463. " reserved_range { start: -15 end: -5 }"
  3464. "}",
  3465. "foo.proto: Foo: NUMBER: Reserved range -15 to -5"
  3466. " overlaps with already-defined range -20 to -10.\n");
  3467. }
  3468. TEST_F(ValidationErrorTest, EnumMixedReservedRangeOverlap) {
  3469. BuildFileWithErrors(
  3470. "name: \"foo.proto\" "
  3471. "enum_type {"
  3472. " name: \"Foo\""
  3473. " value { name:\"BAR\" number:20 }"
  3474. " reserved_range { start: -20 end: 10 }"
  3475. " reserved_range { start: -15 end: 5 }"
  3476. "}",
  3477. "foo.proto: Foo: NUMBER: Reserved range -15 to 5"
  3478. " overlaps with already-defined range -20 to 10.\n");
  3479. }
  3480. TEST_F(ValidationErrorTest, EnumMixedReservedRangeOverlap2) {
  3481. BuildFileWithErrors(
  3482. "name: \"foo.proto\" "
  3483. "enum_type {"
  3484. " name: \"Foo\""
  3485. " value { name:\"BAR\" number:20 }"
  3486. " reserved_range { start: -20 end: 10 }"
  3487. " reserved_range { start: 10 end: 10 }"
  3488. "}",
  3489. "foo.proto: Foo: NUMBER: Reserved range 10 to 10"
  3490. " overlaps with already-defined range -20 to 10.\n");
  3491. }
  3492. TEST_F(ValidationErrorTest, EnumReservedRangeStartGreaterThanEnd) {
  3493. BuildFileWithErrors(
  3494. "name: \"foo.proto\" "
  3495. "enum_type {"
  3496. " name: \"Foo\""
  3497. " value { name:\"BAR\" number:20 }"
  3498. " reserved_range { start: 11 end: 10 }"
  3499. "}",
  3500. "foo.proto: Foo: NUMBER: Reserved range end number must be greater"
  3501. " than start number.\n");
  3502. }
  3503. TEST_F(ValidationErrorTest, EnumReservedNameError) {
  3504. BuildFileWithErrors(
  3505. "name: \"foo.proto\" "
  3506. "enum_type {"
  3507. " name: \"Foo\""
  3508. " value { name:\"FOO\" number:15 }"
  3509. " value { name:\"BAR\" number:15 }"
  3510. " reserved_name: \"FOO\""
  3511. " reserved_name: \"BAR\""
  3512. "}",
  3513. "foo.proto: FOO: NAME: Enum value \"FOO\" is reserved.\n"
  3514. "foo.proto: BAR: NAME: Enum value \"BAR\" is reserved.\n");
  3515. }
  3516. TEST_F(ValidationErrorTest, EnumReservedNameRedundant) {
  3517. BuildFileWithErrors(
  3518. "name: \"foo.proto\" "
  3519. "enum_type {"
  3520. " name: \"Foo\""
  3521. " value { name:\"FOO\" number:15 }"
  3522. " reserved_name: \"foo\""
  3523. " reserved_name: \"foo\""
  3524. "}",
  3525. "foo.proto: foo: NAME: Enum value \"foo\" is reserved multiple times.\n");
  3526. }
  3527. TEST_F(ValidationErrorTest, EnumReservedFieldsDebugString) {
  3528. const FileDescriptor* file = BuildFile(
  3529. "name: \"foo.proto\" "
  3530. "enum_type {"
  3531. " name: \"Foo\""
  3532. " value { name:\"FOO\" number:3 }"
  3533. " reserved_name: \"foo\""
  3534. " reserved_name: \"bar\""
  3535. " reserved_range { start: -6 end: -6 }"
  3536. " reserved_range { start: -5 end: -4 }"
  3537. " reserved_range { start: -1 end: 1 }"
  3538. " reserved_range { start: 5 end: 5 }"
  3539. " reserved_range { start: 10 end: 19 }"
  3540. "}");
  3541. ASSERT_EQ(
  3542. "syntax = \"proto2\";\n\n"
  3543. "enum Foo {\n"
  3544. " FOO = 3;\n"
  3545. " reserved -6, -5 to -4, -1 to 1, 5, 10 to 19;\n"
  3546. " reserved \"foo\", \"bar\";\n"
  3547. "}\n\n",
  3548. file->DebugString());
  3549. }
  3550. TEST_F(ValidationErrorTest, InvalidDefaults) {
  3551. BuildFileWithErrors(
  3552. "name: \"foo.proto\" "
  3553. "message_type {"
  3554. " name: \"Foo\""
  3555. // Invalid number.
  3556. " field { name: \"foo\" number: 1 label: LABEL_OPTIONAL type: TYPE_INT32"
  3557. " default_value: \"abc\" }"
  3558. // Empty default value.
  3559. " field { name: \"bar\" number: 2 label: LABEL_OPTIONAL type: TYPE_INT32"
  3560. " default_value: \"\" }"
  3561. // Invalid boolean.
  3562. " field { name: \"baz\" number: 3 label: LABEL_OPTIONAL type: TYPE_BOOL"
  3563. " default_value: \"abc\" }"
  3564. // Messages can't have defaults.
  3565. " field { name: \"qux\" number: 4 label: LABEL_OPTIONAL type: "
  3566. "TYPE_MESSAGE"
  3567. " default_value: \"abc\" type_name: \"Foo\" }"
  3568. // Same thing, but we don't know that this field has message type until
  3569. // we look up the type name.
  3570. " field { name: \"quux\" number: 5 label: LABEL_OPTIONAL"
  3571. " default_value: \"abc\" type_name: \"Foo\" }"
  3572. // Repeateds can't have defaults.
  3573. " field { name: \"corge\" number: 6 label: LABEL_REPEATED type: "
  3574. "TYPE_INT32"
  3575. " default_value: \"1\" }"
  3576. "}",
  3577. "foo.proto: Foo.foo: DEFAULT_VALUE: Couldn't parse default value "
  3578. "\"abc\".\n"
  3579. "foo.proto: Foo.bar: DEFAULT_VALUE: Couldn't parse default value \"\".\n"
  3580. "foo.proto: Foo.baz: DEFAULT_VALUE: Boolean default must be true or "
  3581. "false.\n"
  3582. "foo.proto: Foo.qux: DEFAULT_VALUE: Messages can't have default values.\n"
  3583. "foo.proto: Foo.corge: DEFAULT_VALUE: Repeated fields can't have default "
  3584. "values.\n"
  3585. // This ends up being reported later because the error is detected at
  3586. // cross-linking time.
  3587. "foo.proto: Foo.quux: DEFAULT_VALUE: Messages can't have default "
  3588. "values.\n");
  3589. }
  3590. TEST_F(ValidationErrorTest, NegativeFieldNumber) {
  3591. BuildFileWithErrors(
  3592. "name: \"foo.proto\" "
  3593. "message_type {"
  3594. " name: \"Foo\""
  3595. " field { name: \"foo\" number: -1 label:LABEL_OPTIONAL type:TYPE_INT32 "
  3596. "}"
  3597. "}",
  3598. "foo.proto: Foo.foo: NUMBER: Field numbers must be positive integers.\n");
  3599. }
  3600. TEST_F(ValidationErrorTest, HugeFieldNumber) {
  3601. BuildFileWithErrors(
  3602. "name: \"foo.proto\" "
  3603. "message_type {"
  3604. " name: \"Foo\""
  3605. " field { name: \"foo\" number: 0x70000000 "
  3606. " label:LABEL_OPTIONAL type:TYPE_INT32 }"
  3607. "}",
  3608. "foo.proto: Foo.foo: NUMBER: Field numbers cannot be greater than "
  3609. "536870911.\n");
  3610. }
  3611. TEST_F(ValidationErrorTest, ReservedFieldNumber) {
  3612. BuildFileWithErrors(
  3613. "name: \"foo.proto\" "
  3614. "message_type {"
  3615. " name: \"Foo\""
  3616. " field {name:\"foo\" number: 18999 label:LABEL_OPTIONAL "
  3617. "type:TYPE_INT32 }"
  3618. " field {name:\"bar\" number: 19000 label:LABEL_OPTIONAL "
  3619. "type:TYPE_INT32 }"
  3620. " field {name:\"baz\" number: 19999 label:LABEL_OPTIONAL "
  3621. "type:TYPE_INT32 }"
  3622. " field {name:\"qux\" number: 20000 label:LABEL_OPTIONAL "
  3623. "type:TYPE_INT32 }"
  3624. "}",
  3625. "foo.proto: Foo.bar: NUMBER: Field numbers 19000 through 19999 are "
  3626. "reserved for the protocol buffer library implementation.\n"
  3627. "foo.proto: Foo.baz: NUMBER: Field numbers 19000 through 19999 are "
  3628. "reserved for the protocol buffer library implementation.\n");
  3629. }
  3630. TEST_F(ValidationErrorTest, ExtensionMissingExtendee) {
  3631. BuildFileWithErrors(
  3632. "name: \"foo.proto\" "
  3633. "message_type {"
  3634. " name: \"Foo\""
  3635. " extension { name: \"foo\" number: 1 label: LABEL_OPTIONAL"
  3636. " type_name: \"Foo\" }"
  3637. "}",
  3638. "foo.proto: Foo.foo: EXTENDEE: FieldDescriptorProto.extendee not set for "
  3639. "extension field.\n");
  3640. }
  3641. TEST_F(ValidationErrorTest, NonExtensionWithExtendee) {
  3642. BuildFileWithErrors(
  3643. "name: \"foo.proto\" "
  3644. "message_type {"
  3645. " name: \"Bar\""
  3646. " extension_range { start: 1 end: 2 }"
  3647. "}"
  3648. "message_type {"
  3649. " name: \"Foo\""
  3650. " field { name: \"foo\" number: 1 label: LABEL_OPTIONAL"
  3651. " type_name: \"Foo\" extendee: \"Bar\" }"
  3652. "}",
  3653. "foo.proto: Foo.foo: EXTENDEE: FieldDescriptorProto.extendee set for "
  3654. "non-extension field.\n");
  3655. }
  3656. TEST_F(ValidationErrorTest, FieldOneofIndexTooLarge) {
  3657. BuildFileWithErrors(
  3658. "name: \"foo.proto\" "
  3659. "message_type {"
  3660. " name: \"Foo\""
  3661. " field { name:\"foo\" number:1 label:LABEL_OPTIONAL type:TYPE_INT32 "
  3662. " oneof_index: 1 }"
  3663. " field { name:\"dummy\" number:2 label:LABEL_OPTIONAL type:TYPE_INT32 "
  3664. " oneof_index: 0 }"
  3665. " oneof_decl { name:\"bar\" }"
  3666. "}",
  3667. "foo.proto: Foo.foo: TYPE: FieldDescriptorProto.oneof_index 1 is out of "
  3668. "range for type \"Foo\".\n");
  3669. }
  3670. TEST_F(ValidationErrorTest, FieldOneofIndexNegative) {
  3671. BuildFileWithErrors(
  3672. "name: \"foo.proto\" "
  3673. "message_type {"
  3674. " name: \"Foo\""
  3675. " field { name:\"foo\" number:1 label:LABEL_OPTIONAL type:TYPE_INT32 "
  3676. " oneof_index: -1 }"
  3677. " field { name:\"dummy\" number:2 label:LABEL_OPTIONAL type:TYPE_INT32 "
  3678. " oneof_index: 0 }"
  3679. " oneof_decl { name:\"bar\" }"
  3680. "}",
  3681. "foo.proto: Foo.foo: TYPE: FieldDescriptorProto.oneof_index -1 is out "
  3682. "of "
  3683. "range for type \"Foo\".\n");
  3684. }
  3685. TEST_F(ValidationErrorTest, OneofFieldsConsecutiveDefinition) {
  3686. // Fields belonging to the same oneof must be defined consecutively.
  3687. BuildFileWithErrors(
  3688. "name: \"foo.proto\" "
  3689. "message_type {"
  3690. " name: \"Foo\""
  3691. " field { name:\"foo1\" number: 1 label:LABEL_OPTIONAL type:TYPE_INT32 "
  3692. " oneof_index: 0 }"
  3693. " field { name:\"bar\" number: 2 label:LABEL_OPTIONAL type:TYPE_INT32 }"
  3694. " field { name:\"foo2\" number: 3 label:LABEL_OPTIONAL type:TYPE_INT32 "
  3695. " oneof_index: 0 }"
  3696. " oneof_decl { name:\"foos\" }"
  3697. "}",
  3698. "foo.proto: Foo.bar: TYPE: Fields in the same oneof must be defined "
  3699. "consecutively. \"bar\" cannot be defined before the completion of the "
  3700. "\"foos\" oneof definition.\n");
  3701. // Prevent interleaved fields, which belong to different oneofs.
  3702. BuildFileWithErrors(
  3703. "name: \"foo2.proto\" "
  3704. "message_type {"
  3705. " name: \"Foo2\""
  3706. " field { name:\"foo1\" number: 1 label:LABEL_OPTIONAL type:TYPE_INT32 "
  3707. " oneof_index: 0 }"
  3708. " field { name:\"bar1\" number: 2 label:LABEL_OPTIONAL type:TYPE_INT32 "
  3709. " oneof_index: 1 }"
  3710. " field { name:\"foo2\" number: 3 label:LABEL_OPTIONAL type:TYPE_INT32 "
  3711. " oneof_index: 0 }"
  3712. " field { name:\"bar2\" number: 4 label:LABEL_OPTIONAL type:TYPE_INT32 "
  3713. " oneof_index: 1 }"
  3714. " oneof_decl { name:\"foos\" }"
  3715. " oneof_decl { name:\"bars\" }"
  3716. "}",
  3717. "foo2.proto: Foo2.bar1: TYPE: Fields in the same oneof must be defined "
  3718. "consecutively. \"bar1\" cannot be defined before the completion of the "
  3719. "\"foos\" oneof definition.\n"
  3720. "foo2.proto: Foo2.foo2: TYPE: Fields in the same oneof must be defined "
  3721. "consecutively. \"foo2\" cannot be defined before the completion of the "
  3722. "\"bars\" oneof definition.\n");
  3723. // Another case for normal fields and different oneof fields interleave.
  3724. BuildFileWithErrors(
  3725. "name: \"foo3.proto\" "
  3726. "message_type {"
  3727. " name: \"Foo3\""
  3728. " field { name:\"foo1\" number: 1 label:LABEL_OPTIONAL type:TYPE_INT32 "
  3729. " oneof_index: 0 }"
  3730. " field { name:\"bar1\" number: 2 label:LABEL_OPTIONAL type:TYPE_INT32 "
  3731. " oneof_index: 1 }"
  3732. " field { name:\"baz\" number: 3 label:LABEL_OPTIONAL type:TYPE_INT32 }"
  3733. " field { name:\"foo2\" number: 4 label:LABEL_OPTIONAL type:TYPE_INT32 "
  3734. " oneof_index: 0 }"
  3735. " oneof_decl { name:\"foos\" }"
  3736. " oneof_decl { name:\"bars\" }"
  3737. "}",
  3738. "foo3.proto: Foo3.baz: TYPE: Fields in the same oneof must be defined "
  3739. "consecutively. \"baz\" cannot be defined before the completion of the "
  3740. "\"foos\" oneof definition.\n");
  3741. }
  3742. TEST_F(ValidationErrorTest, FieldNumberConflict) {
  3743. BuildFileWithErrors(
  3744. "name: \"foo.proto\" "
  3745. "message_type {"
  3746. " name: \"Foo\""
  3747. " field { name: \"foo\" number: 1 label:LABEL_OPTIONAL type:TYPE_INT32 }"
  3748. " field { name: \"bar\" number: 1 label:LABEL_OPTIONAL type:TYPE_INT32 }"
  3749. "}",
  3750. "foo.proto: Foo.bar: NUMBER: Field number 1 has already been used in "
  3751. "\"Foo\" by field \"foo\".\n");
  3752. }
  3753. TEST_F(ValidationErrorTest, BadMessageSetExtensionType) {
  3754. BuildFileWithErrors(
  3755. "name: \"foo.proto\" "
  3756. "message_type {"
  3757. " name: \"MessageSet\""
  3758. " options { message_set_wire_format: true }"
  3759. " extension_range { start: 4 end: 5 }"
  3760. "}"
  3761. "message_type {"
  3762. " name: \"Foo\""
  3763. " extension { name:\"foo\" number:4 label:LABEL_OPTIONAL type:TYPE_INT32"
  3764. " extendee: \"MessageSet\" }"
  3765. "}",
  3766. "foo.proto: Foo.foo: TYPE: Extensions of MessageSets must be optional "
  3767. "messages.\n");
  3768. }
  3769. TEST_F(ValidationErrorTest, BadMessageSetExtensionLabel) {
  3770. BuildFileWithErrors(
  3771. "name: \"foo.proto\" "
  3772. "message_type {"
  3773. " name: \"MessageSet\""
  3774. " options { message_set_wire_format: true }"
  3775. " extension_range { start: 4 end: 5 }"
  3776. "}"
  3777. "message_type {"
  3778. " name: \"Foo\""
  3779. " extension { name:\"foo\" number:4 label:LABEL_REPEATED "
  3780. "type:TYPE_MESSAGE"
  3781. " type_name: \"Foo\" extendee: \"MessageSet\" }"
  3782. "}",
  3783. "foo.proto: Foo.foo: TYPE: Extensions of MessageSets must be optional "
  3784. "messages.\n");
  3785. }
  3786. TEST_F(ValidationErrorTest, FieldInMessageSet) {
  3787. BuildFileWithErrors(
  3788. "name: \"foo.proto\" "
  3789. "message_type {"
  3790. " name: \"Foo\""
  3791. " options { message_set_wire_format: true }"
  3792. " field { name: \"foo\" number: 1 label:LABEL_OPTIONAL type:TYPE_INT32 }"
  3793. "}",
  3794. "foo.proto: Foo.foo: NAME: MessageSets cannot have fields, only "
  3795. "extensions.\n");
  3796. }
  3797. TEST_F(ValidationErrorTest, NegativeExtensionRangeNumber) {
  3798. BuildFileWithErrors(
  3799. "name: \"foo.proto\" "
  3800. "message_type {"
  3801. " name: \"Foo\""
  3802. " extension_range { start: -10 end: -1 }"
  3803. "}",
  3804. "foo.proto: Foo: NUMBER: Extension numbers must be positive integers.\n");
  3805. }
  3806. TEST_F(ValidationErrorTest, HugeExtensionRangeNumber) {
  3807. BuildFileWithErrors(
  3808. "name: \"foo.proto\" "
  3809. "message_type {"
  3810. " name: \"Foo\""
  3811. " extension_range { start: 1 end: 0x70000000 }"
  3812. "}",
  3813. "foo.proto: Foo: NUMBER: Extension numbers cannot be greater than "
  3814. "536870911.\n");
  3815. }
  3816. TEST_F(ValidationErrorTest, ExtensionRangeEndBeforeStart) {
  3817. BuildFileWithErrors(
  3818. "name: \"foo.proto\" "
  3819. "message_type {"
  3820. " name: \"Foo\""
  3821. " extension_range { start: 10 end: 10 }"
  3822. " extension_range { start: 10 end: 5 }"
  3823. "}",
  3824. "foo.proto: Foo: NUMBER: Extension range end number must be greater than "
  3825. "start number.\n"
  3826. "foo.proto: Foo: NUMBER: Extension range end number must be greater than "
  3827. "start number.\n");
  3828. }
  3829. TEST_F(ValidationErrorTest, EmptyEnum) {
  3830. BuildFileWithErrors(
  3831. "name: \"foo.proto\" "
  3832. "enum_type { name: \"Foo\" }"
  3833. // Also use the empty enum in a message to make sure there are no crashes
  3834. // during validation (possible if the code attempts to derive a default
  3835. // value for the field).
  3836. "message_type {"
  3837. " name: \"Bar\""
  3838. " field { name: \"foo\" number: 1 label:LABEL_OPTIONAL "
  3839. "type_name:\"Foo\" }"
  3840. " field { name: \"bar\" number: 2 label:LABEL_OPTIONAL "
  3841. "type_name:\"Foo\" "
  3842. " default_value: \"NO_SUCH_VALUE\" }"
  3843. "}",
  3844. "foo.proto: Foo: NAME: Enums must contain at least one value.\n"
  3845. "foo.proto: Bar.bar: DEFAULT_VALUE: Enum type \"Foo\" has no value named "
  3846. "\"NO_SUCH_VALUE\".\n");
  3847. }
  3848. TEST_F(ValidationErrorTest, UndefinedExtendee) {
  3849. BuildFileWithErrors(
  3850. "name: \"foo.proto\" "
  3851. "message_type {"
  3852. " name: \"Foo\""
  3853. " extension { name:\"foo\" number:1 label:LABEL_OPTIONAL type:TYPE_INT32"
  3854. " extendee: \"Bar\" }"
  3855. "}",
  3856. "foo.proto: Foo.foo: EXTENDEE: \"Bar\" is not defined.\n");
  3857. }
  3858. TEST_F(ValidationErrorTest, NonMessageExtendee) {
  3859. BuildFileWithErrors(
  3860. "name: \"foo.proto\" "
  3861. "enum_type { name: \"Bar\" value { name:\"DUMMY\" number:0 } }"
  3862. "message_type {"
  3863. " name: \"Foo\""
  3864. " extension { name:\"foo\" number:1 label:LABEL_OPTIONAL type:TYPE_INT32"
  3865. " extendee: \"Bar\" }"
  3866. "}",
  3867. "foo.proto: Foo.foo: EXTENDEE: \"Bar\" is not a message type.\n");
  3868. }
  3869. TEST_F(ValidationErrorTest, NotAnExtensionNumber) {
  3870. BuildFileWithErrors(
  3871. "name: \"foo.proto\" "
  3872. "message_type {"
  3873. " name: \"Bar\""
  3874. "}"
  3875. "message_type {"
  3876. " name: \"Foo\""
  3877. " extension { name:\"foo\" number:1 label:LABEL_OPTIONAL type:TYPE_INT32"
  3878. " extendee: \"Bar\" }"
  3879. "}",
  3880. "foo.proto: Foo.foo: NUMBER: \"Bar\" does not declare 1 as an extension "
  3881. "number.\n");
  3882. }
  3883. TEST_F(ValidationErrorTest, RequiredExtension) {
  3884. BuildFileWithErrors(
  3885. "name: \"foo.proto\" "
  3886. "message_type {"
  3887. " name: \"Bar\""
  3888. " extension_range { start: 1000 end: 10000 }"
  3889. "}"
  3890. "message_type {"
  3891. " name: \"Foo\""
  3892. " extension {"
  3893. " name:\"foo\""
  3894. " number:1000"
  3895. " label:LABEL_REQUIRED"
  3896. " type:TYPE_INT32"
  3897. " extendee: \"Bar\""
  3898. " }"
  3899. "}",
  3900. "foo.proto: Foo.foo: TYPE: The extension Foo.foo cannot be required.\n");
  3901. }
  3902. TEST_F(ValidationErrorTest, UndefinedFieldType) {
  3903. BuildFileWithErrors(
  3904. "name: \"foo.proto\" "
  3905. "message_type {"
  3906. " name: \"Foo\""
  3907. " field { name:\"foo\" number:1 label:LABEL_OPTIONAL type_name:\"Bar\" }"
  3908. "}",
  3909. "foo.proto: Foo.foo: TYPE: \"Bar\" is not defined.\n");
  3910. }
  3911. TEST_F(ValidationErrorTest, UndefinedFieldTypeWithDefault) {
  3912. // See b/12533582. Previously this failed because the default value was not
  3913. // accepted by the parser, which assumed an enum type, leading to an unclear
  3914. // error message. We want this input to yield a validation error instead,
  3915. // since the unknown type is the primary problem.
  3916. BuildFileWithErrors(
  3917. "name: \"foo.proto\" "
  3918. "message_type {"
  3919. " name: \"Foo\""
  3920. " field { name:\"foo\" number:1 label:LABEL_OPTIONAL type_name:\"int\" "
  3921. " default_value:\"1\" }"
  3922. "}",
  3923. "foo.proto: Foo.foo: TYPE: \"int\" is not defined.\n");
  3924. }
  3925. TEST_F(ValidationErrorTest, UndefinedNestedFieldType) {
  3926. BuildFileWithErrors(
  3927. "name: \"foo.proto\" "
  3928. "message_type {"
  3929. " name: \"Foo\""
  3930. " nested_type { name:\"Baz\" }"
  3931. " field { name:\"foo\" number:1"
  3932. " label:LABEL_OPTIONAL"
  3933. " type_name:\"Foo.Baz.Bar\" }"
  3934. "}",
  3935. "foo.proto: Foo.foo: TYPE: \"Foo.Baz.Bar\" is not defined.\n");
  3936. }
  3937. TEST_F(ValidationErrorTest, FieldTypeDefinedInUndeclaredDependency) {
  3938. BuildFile(
  3939. "name: \"bar.proto\" "
  3940. "message_type { name: \"Bar\" } ");
  3941. BuildFileWithErrors(
  3942. "name: \"foo.proto\" "
  3943. "message_type {"
  3944. " name: \"Foo\""
  3945. " field { name:\"foo\" number:1 label:LABEL_OPTIONAL type_name:\"Bar\" }"
  3946. "}",
  3947. "foo.proto: Foo.foo: TYPE: \"Bar\" seems to be defined in \"bar.proto\", "
  3948. "which is not imported by \"foo.proto\". To use it here, please add the "
  3949. "necessary import.\n");
  3950. }
  3951. TEST_F(ValidationErrorTest, FieldTypeDefinedInIndirectDependency) {
  3952. // Test for hidden dependencies.
  3953. //
  3954. // // bar.proto
  3955. // message Bar{}
  3956. //
  3957. // // forward.proto
  3958. // import "bar.proto"
  3959. //
  3960. // // foo.proto
  3961. // import "forward.proto"
  3962. // message Foo {
  3963. // optional Bar foo = 1; // Error, needs to import bar.proto explicitly.
  3964. // }
  3965. //
  3966. BuildFile(
  3967. "name: \"bar.proto\" "
  3968. "message_type { name: \"Bar\" }");
  3969. BuildFile(
  3970. "name: \"forward.proto\""
  3971. "dependency: \"bar.proto\"");
  3972. BuildFileWithErrors(
  3973. "name: \"foo.proto\" "
  3974. "dependency: \"forward.proto\" "
  3975. "message_type {"
  3976. " name: \"Foo\""
  3977. " field { name:\"foo\" number:1 label:LABEL_OPTIONAL type_name:\"Bar\" }"
  3978. "}",
  3979. "foo.proto: Foo.foo: TYPE: \"Bar\" seems to be defined in \"bar.proto\", "
  3980. "which is not imported by \"foo.proto\". To use it here, please add the "
  3981. "necessary import.\n");
  3982. }
  3983. TEST_F(ValidationErrorTest, FieldTypeDefinedInPublicDependency) {
  3984. // Test for public dependencies.
  3985. //
  3986. // // bar.proto
  3987. // message Bar{}
  3988. //
  3989. // // forward.proto
  3990. // import public "bar.proto"
  3991. //
  3992. // // foo.proto
  3993. // import "forward.proto"
  3994. // message Foo {
  3995. // optional Bar foo = 1; // Correct. "bar.proto" is public imported into
  3996. // // forward.proto, so when "foo.proto" imports
  3997. // // "forward.proto", it imports "bar.proto" too.
  3998. // }
  3999. //
  4000. BuildFile(
  4001. "name: \"bar.proto\" "
  4002. "message_type { name: \"Bar\" }");
  4003. BuildFile(
  4004. "name: \"forward.proto\""
  4005. "dependency: \"bar.proto\" "
  4006. "public_dependency: 0");
  4007. BuildFile(
  4008. "name: \"foo.proto\" "
  4009. "dependency: \"forward.proto\" "
  4010. "message_type {"
  4011. " name: \"Foo\""
  4012. " field { name:\"foo\" number:1 label:LABEL_OPTIONAL type_name:\"Bar\" }"
  4013. "}");
  4014. }
  4015. TEST_F(ValidationErrorTest, FieldTypeDefinedInTransitivePublicDependency) {
  4016. // Test for public dependencies.
  4017. //
  4018. // // bar.proto
  4019. // message Bar{}
  4020. //
  4021. // // forward.proto
  4022. // import public "bar.proto"
  4023. //
  4024. // // forward2.proto
  4025. // import public "forward.proto"
  4026. //
  4027. // // foo.proto
  4028. // import "forward2.proto"
  4029. // message Foo {
  4030. // optional Bar foo = 1; // Correct, public imports are transitive.
  4031. // }
  4032. //
  4033. BuildFile(
  4034. "name: \"bar.proto\" "
  4035. "message_type { name: \"Bar\" }");
  4036. BuildFile(
  4037. "name: \"forward.proto\""
  4038. "dependency: \"bar.proto\" "
  4039. "public_dependency: 0");
  4040. BuildFile(
  4041. "name: \"forward2.proto\""
  4042. "dependency: \"forward.proto\" "
  4043. "public_dependency: 0");
  4044. BuildFile(
  4045. "name: \"foo.proto\" "
  4046. "dependency: \"forward2.proto\" "
  4047. "message_type {"
  4048. " name: \"Foo\""
  4049. " field { name:\"foo\" number:1 label:LABEL_OPTIONAL type_name:\"Bar\" }"
  4050. "}");
  4051. }
  4052. TEST_F(ValidationErrorTest,
  4053. FieldTypeDefinedInPrivateDependencyOfPublicDependency) {
  4054. // Test for public dependencies.
  4055. //
  4056. // // bar.proto
  4057. // message Bar{}
  4058. //
  4059. // // forward.proto
  4060. // import "bar.proto"
  4061. //
  4062. // // forward2.proto
  4063. // import public "forward.proto"
  4064. //
  4065. // // foo.proto
  4066. // import "forward2.proto"
  4067. // message Foo {
  4068. // optional Bar foo = 1; // Error, the "bar.proto" is not public imported
  4069. // // into "forward.proto", so will not be imported
  4070. // // into either "forward2.proto" or "foo.proto".
  4071. // }
  4072. //
  4073. BuildFile(
  4074. "name: \"bar.proto\" "
  4075. "message_type { name: \"Bar\" }");
  4076. BuildFile(
  4077. "name: \"forward.proto\""
  4078. "dependency: \"bar.proto\"");
  4079. BuildFile(
  4080. "name: \"forward2.proto\""
  4081. "dependency: \"forward.proto\" "
  4082. "public_dependency: 0");
  4083. BuildFileWithErrors(
  4084. "name: \"foo.proto\" "
  4085. "dependency: \"forward2.proto\" "
  4086. "message_type {"
  4087. " name: \"Foo\""
  4088. " field { name:\"foo\" number:1 label:LABEL_OPTIONAL type_name:\"Bar\" }"
  4089. "}",
  4090. "foo.proto: Foo.foo: TYPE: \"Bar\" seems to be defined in \"bar.proto\", "
  4091. "which is not imported by \"foo.proto\". To use it here, please add the "
  4092. "necessary import.\n");
  4093. }
  4094. TEST_F(ValidationErrorTest, SearchMostLocalFirst) {
  4095. // The following should produce an error that Bar.Baz is resolved but
  4096. // not defined:
  4097. // message Bar { message Baz {} }
  4098. // message Foo {
  4099. // message Bar {
  4100. // // Placing "message Baz{}" here, or removing Foo.Bar altogether,
  4101. // // would fix the error.
  4102. // }
  4103. // optional Bar.Baz baz = 1;
  4104. // }
  4105. // An one point the lookup code incorrectly did not produce an error in this
  4106. // case, because when looking for Bar.Baz, it would try "Foo.Bar.Baz" first,
  4107. // fail, and ten try "Bar.Baz" and succeed, even though "Bar" should actually
  4108. // refer to the inner Bar, not the outer one.
  4109. BuildFileWithErrors(
  4110. "name: \"foo.proto\" "
  4111. "message_type {"
  4112. " name: \"Bar\""
  4113. " nested_type { name: \"Baz\" }"
  4114. "}"
  4115. "message_type {"
  4116. " name: \"Foo\""
  4117. " nested_type { name: \"Bar\" }"
  4118. " field { name:\"baz\" number:1 label:LABEL_OPTIONAL"
  4119. " type_name:\"Bar.Baz\" }"
  4120. "}",
  4121. "foo.proto: Foo.baz: TYPE: \"Bar.Baz\" is resolved to \"Foo.Bar.Baz\","
  4122. " which is not defined. The innermost scope is searched first in name "
  4123. "resolution. Consider using a leading '.'(i.e., \".Bar.Baz\") to start "
  4124. "from the outermost scope.\n");
  4125. }
  4126. TEST_F(ValidationErrorTest, SearchMostLocalFirst2) {
  4127. // This test would find the most local "Bar" first, and does, but
  4128. // proceeds to find the outer one because the inner one's not an
  4129. // aggregate.
  4130. BuildFile(
  4131. "name: \"foo.proto\" "
  4132. "message_type {"
  4133. " name: \"Bar\""
  4134. " nested_type { name: \"Baz\" }"
  4135. "}"
  4136. "message_type {"
  4137. " name: \"Foo\""
  4138. " field { name: \"Bar\" number:1 type:TYPE_BYTES } "
  4139. " field { name:\"baz\" number:2 label:LABEL_OPTIONAL"
  4140. " type_name:\"Bar.Baz\" }"
  4141. "}");
  4142. }
  4143. TEST_F(ValidationErrorTest, PackageOriginallyDeclaredInTransitiveDependent) {
  4144. // Imagine we have the following:
  4145. //
  4146. // foo.proto:
  4147. // package foo.bar;
  4148. // bar.proto:
  4149. // package foo.bar;
  4150. // import "foo.proto";
  4151. // message Bar {}
  4152. // baz.proto:
  4153. // package foo;
  4154. // import "bar.proto"
  4155. // message Baz { optional bar.Bar qux = 1; }
  4156. //
  4157. // When validating baz.proto, we will look up "bar.Bar". As part of this
  4158. // lookup, we first lookup "bar" then try to find "Bar" within it. "bar"
  4159. // should resolve to "foo.bar". Note, though, that "foo.bar" was originally
  4160. // defined in foo.proto, which is not a direct dependency of baz.proto. The
  4161. // implementation of FindSymbol() normally only returns symbols in direct
  4162. // dependencies, not indirect ones. This test insures that this does not
  4163. // prevent it from finding "foo.bar".
  4164. BuildFile(
  4165. "name: \"foo.proto\" "
  4166. "package: \"foo.bar\" ");
  4167. BuildFile(
  4168. "name: \"bar.proto\" "
  4169. "package: \"foo.bar\" "
  4170. "dependency: \"foo.proto\" "
  4171. "message_type { name: \"Bar\" }");
  4172. BuildFile(
  4173. "name: \"baz.proto\" "
  4174. "package: \"foo\" "
  4175. "dependency: \"bar.proto\" "
  4176. "message_type { "
  4177. " name: \"Baz\" "
  4178. " field { name:\"qux\" number:1 label:LABEL_OPTIONAL "
  4179. " type_name:\"bar.Bar\" }"
  4180. "}");
  4181. }
  4182. TEST_F(ValidationErrorTest, FieldTypeNotAType) {
  4183. BuildFileWithErrors(
  4184. "name: \"foo.proto\" "
  4185. "message_type {"
  4186. " name: \"Foo\""
  4187. " field { name:\"foo\" number:1 label:LABEL_OPTIONAL "
  4188. " type_name:\".Foo.bar\" }"
  4189. " field { name:\"bar\" number:2 label:LABEL_OPTIONAL type:TYPE_INT32 }"
  4190. "}",
  4191. "foo.proto: Foo.foo: TYPE: \".Foo.bar\" is not a type.\n");
  4192. }
  4193. TEST_F(ValidationErrorTest, RelativeFieldTypeNotAType) {
  4194. BuildFileWithErrors(
  4195. "name: \"foo.proto\" "
  4196. "message_type {"
  4197. " nested_type {"
  4198. " name: \"Bar\""
  4199. " field { name:\"Baz\" number:2 label:LABEL_OPTIONAL type:TYPE_INT32 }"
  4200. " }"
  4201. " name: \"Foo\""
  4202. " field { name:\"foo\" number:1 label:LABEL_OPTIONAL "
  4203. " type_name:\"Bar.Baz\" }"
  4204. "}",
  4205. "foo.proto: Foo.foo: TYPE: \"Bar.Baz\" is not a type.\n");
  4206. }
  4207. TEST_F(ValidationErrorTest, FieldTypeMayBeItsName) {
  4208. BuildFile(
  4209. "name: \"foo.proto\" "
  4210. "message_type {"
  4211. " name: \"Bar\""
  4212. "}"
  4213. "message_type {"
  4214. " name: \"Foo\""
  4215. " field { name:\"Bar\" number:1 label:LABEL_OPTIONAL type_name:\"Bar\" }"
  4216. "}");
  4217. }
  4218. TEST_F(ValidationErrorTest, EnumFieldTypeIsMessage) {
  4219. BuildFileWithErrors(
  4220. "name: \"foo.proto\" "
  4221. "message_type { name: \"Bar\" } "
  4222. "message_type {"
  4223. " name: \"Foo\""
  4224. " field { name:\"foo\" number:1 label:LABEL_OPTIONAL type:TYPE_ENUM"
  4225. " type_name:\"Bar\" }"
  4226. "}",
  4227. "foo.proto: Foo.foo: TYPE: \"Bar\" is not an enum type.\n");
  4228. }
  4229. TEST_F(ValidationErrorTest, MessageFieldTypeIsEnum) {
  4230. BuildFileWithErrors(
  4231. "name: \"foo.proto\" "
  4232. "enum_type { name: \"Bar\" value { name:\"DUMMY\" number:0 } } "
  4233. "message_type {"
  4234. " name: \"Foo\""
  4235. " field { name:\"foo\" number:1 label:LABEL_OPTIONAL type:TYPE_MESSAGE"
  4236. " type_name:\"Bar\" }"
  4237. "}",
  4238. "foo.proto: Foo.foo: TYPE: \"Bar\" is not a message type.\n");
  4239. }
  4240. TEST_F(ValidationErrorTest, BadEnumDefaultValue) {
  4241. BuildFileWithErrors(
  4242. "name: \"foo.proto\" "
  4243. "enum_type { name: \"Bar\" value { name:\"DUMMY\" number:0 } } "
  4244. "message_type {"
  4245. " name: \"Foo\""
  4246. " field { name:\"foo\" number:1 label:LABEL_OPTIONAL type_name:\"Bar\""
  4247. " default_value:\"NO_SUCH_VALUE\" }"
  4248. "}",
  4249. "foo.proto: Foo.foo: DEFAULT_VALUE: Enum type \"Bar\" has no value named "
  4250. "\"NO_SUCH_VALUE\".\n");
  4251. }
  4252. TEST_F(ValidationErrorTest, EnumDefaultValueIsInteger) {
  4253. BuildFileWithErrors(
  4254. "name: \"foo.proto\" "
  4255. "enum_type { name: \"Bar\" value { name:\"DUMMY\" number:0 } } "
  4256. "message_type {"
  4257. " name: \"Foo\""
  4258. " field { name:\"foo\" number:1 label:LABEL_OPTIONAL type_name:\"Bar\""
  4259. " default_value:\"0\" }"
  4260. "}",
  4261. "foo.proto: Foo.foo: DEFAULT_VALUE: Default value for an enum field must "
  4262. "be an identifier.\n");
  4263. }
  4264. TEST_F(ValidationErrorTest, PrimitiveWithTypeName) {
  4265. BuildFileWithErrors(
  4266. "name: \"foo.proto\" "
  4267. "message_type {"
  4268. " name: \"Foo\""
  4269. " field { name:\"foo\" number:1 label:LABEL_OPTIONAL type:TYPE_INT32"
  4270. " type_name:\"Foo\" }"
  4271. "}",
  4272. "foo.proto: Foo.foo: TYPE: Field with primitive type has type_name.\n");
  4273. }
  4274. TEST_F(ValidationErrorTest, NonPrimitiveWithoutTypeName) {
  4275. BuildFileWithErrors(
  4276. "name: \"foo.proto\" "
  4277. "message_type {"
  4278. " name: \"Foo\""
  4279. " field { name:\"foo\" number:1 label:LABEL_OPTIONAL type:TYPE_MESSAGE }"
  4280. "}",
  4281. "foo.proto: Foo.foo: TYPE: Field with message or enum type missing "
  4282. "type_name.\n");
  4283. }
  4284. TEST_F(ValidationErrorTest, OneofWithNoFields) {
  4285. BuildFileWithErrors(
  4286. "name: \"foo.proto\" "
  4287. "message_type {"
  4288. " name: \"Foo\""
  4289. " oneof_decl { name:\"bar\" }"
  4290. "}",
  4291. "foo.proto: Foo.bar: NAME: Oneof must have at least one field.\n");
  4292. }
  4293. TEST_F(ValidationErrorTest, OneofLabelMismatch) {
  4294. BuildFileWithErrors(
  4295. "name: \"foo.proto\" "
  4296. "message_type {"
  4297. " name: \"Foo\""
  4298. " field { name:\"foo\" number:1 label:LABEL_REPEATED type:TYPE_INT32 "
  4299. " oneof_index:0 }"
  4300. " oneof_decl { name:\"bar\" }"
  4301. "}",
  4302. "foo.proto: Foo.foo: NAME: Fields of oneofs must themselves have label "
  4303. "LABEL_OPTIONAL.\n");
  4304. }
  4305. TEST_F(ValidationErrorTest, InputTypeNotDefined) {
  4306. BuildFileWithErrors(
  4307. "name: \"foo.proto\" "
  4308. "message_type { name: \"Foo\" } "
  4309. "service {"
  4310. " name: \"TestService\""
  4311. " method { name: \"A\" input_type: \"Bar\" output_type: \"Foo\" }"
  4312. "}",
  4313. "foo.proto: TestService.A: INPUT_TYPE: \"Bar\" is not defined.\n"
  4314. );
  4315. }
  4316. TEST_F(ValidationErrorTest, InputTypeNotAMessage) {
  4317. BuildFileWithErrors(
  4318. "name: \"foo.proto\" "
  4319. "message_type { name: \"Foo\" } "
  4320. "enum_type { name: \"Bar\" value { name:\"DUMMY\" number:0 } } "
  4321. "service {"
  4322. " name: \"TestService\""
  4323. " method { name: \"A\" input_type: \"Bar\" output_type: \"Foo\" }"
  4324. "}",
  4325. "foo.proto: TestService.A: INPUT_TYPE: \"Bar\" is not a message type.\n"
  4326. );
  4327. }
  4328. TEST_F(ValidationErrorTest, OutputTypeNotDefined) {
  4329. BuildFileWithErrors(
  4330. "name: \"foo.proto\" "
  4331. "message_type { name: \"Foo\" } "
  4332. "service {"
  4333. " name: \"TestService\""
  4334. " method { name: \"A\" input_type: \"Foo\" output_type: \"Bar\" }"
  4335. "}",
  4336. "foo.proto: TestService.A: OUTPUT_TYPE: \"Bar\" is not defined.\n"
  4337. );
  4338. }
  4339. TEST_F(ValidationErrorTest, OutputTypeNotAMessage) {
  4340. BuildFileWithErrors(
  4341. "name: \"foo.proto\" "
  4342. "message_type { name: \"Foo\" } "
  4343. "enum_type { name: \"Bar\" value { name:\"DUMMY\" number:0 } } "
  4344. "service {"
  4345. " name: \"TestService\""
  4346. " method { name: \"A\" input_type: \"Foo\" output_type: \"Bar\" }"
  4347. "}",
  4348. "foo.proto: TestService.A: OUTPUT_TYPE: \"Bar\" is not a message type.\n"
  4349. );
  4350. }
  4351. TEST_F(ValidationErrorTest, IllegalPackedField) {
  4352. BuildFileWithErrors(
  4353. "name: \"foo.proto\" "
  4354. "message_type {\n"
  4355. " name: \"Foo\""
  4356. " field { name:\"packed_string\" number:1 label:LABEL_REPEATED "
  4357. " type:TYPE_STRING "
  4358. " options { uninterpreted_option {"
  4359. " name { name_part: \"packed\" is_extension: false }"
  4360. " identifier_value: \"true\" }}}\n"
  4361. " field { name:\"packed_message\" number:3 label:LABEL_REPEATED "
  4362. " type_name: \"Foo\""
  4363. " options { uninterpreted_option {"
  4364. " name { name_part: \"packed\" is_extension: false }"
  4365. " identifier_value: \"true\" }}}\n"
  4366. " field { name:\"optional_int32\" number: 4 label: LABEL_OPTIONAL "
  4367. " type:TYPE_INT32 "
  4368. " options { uninterpreted_option {"
  4369. " name { name_part: \"packed\" is_extension: false }"
  4370. " identifier_value: \"true\" }}}\n"
  4371. "}",
  4372. "foo.proto: Foo.packed_string: TYPE: [packed = true] can only be "
  4373. "specified for repeated primitive fields.\n"
  4374. "foo.proto: Foo.packed_message: TYPE: [packed = true] can only be "
  4375. "specified for repeated primitive fields.\n"
  4376. "foo.proto: Foo.optional_int32: TYPE: [packed = true] can only be "
  4377. "specified for repeated primitive fields.\n");
  4378. }
  4379. TEST_F(ValidationErrorTest, OptionWrongType) {
  4380. BuildFileWithErrors(
  4381. "name: \"foo.proto\" "
  4382. "message_type { "
  4383. " name: \"TestMessage\" "
  4384. " field { name:\"foo\" number:1 label:LABEL_OPTIONAL type:TYPE_STRING "
  4385. " options { uninterpreted_option { name { name_part: \"ctype\" "
  4386. " is_extension: false }"
  4387. " positive_int_value: 1 }"
  4388. " }"
  4389. " }"
  4390. "}\n",
  4391. "foo.proto: TestMessage.foo: OPTION_VALUE: Value must be identifier for "
  4392. "enum-valued option \"google.protobuf.FieldOptions.ctype\".\n");
  4393. }
  4394. TEST_F(ValidationErrorTest, OptionExtendsAtomicType) {
  4395. BuildFileWithErrors(
  4396. "name: \"foo.proto\" "
  4397. "message_type { "
  4398. " name: \"TestMessage\" "
  4399. " field { name:\"foo\" number:1 label:LABEL_OPTIONAL type:TYPE_STRING "
  4400. " options { uninterpreted_option { name { name_part: \"ctype\" "
  4401. " is_extension: false }"
  4402. " name { name_part: \"foo\" "
  4403. " is_extension: true }"
  4404. " positive_int_value: 1 }"
  4405. " }"
  4406. " }"
  4407. "}\n",
  4408. "foo.proto: TestMessage.foo: OPTION_NAME: Option \"ctype\" is an "
  4409. "atomic type, not a message.\n");
  4410. }
  4411. TEST_F(ValidationErrorTest, DupOption) {
  4412. BuildFileWithErrors(
  4413. "name: \"foo.proto\" "
  4414. "message_type { "
  4415. " name: \"TestMessage\" "
  4416. " field { name:\"foo\" number:1 label:LABEL_OPTIONAL type:TYPE_UINT32 "
  4417. " options { uninterpreted_option { name { name_part: \"ctype\" "
  4418. " is_extension: false }"
  4419. " identifier_value: \"CORD\" }"
  4420. " uninterpreted_option { name { name_part: \"ctype\" "
  4421. " is_extension: false }"
  4422. " identifier_value: \"CORD\" }"
  4423. " }"
  4424. " }"
  4425. "}\n",
  4426. "foo.proto: TestMessage.foo: OPTION_NAME: Option \"ctype\" was "
  4427. "already set.\n");
  4428. }
  4429. TEST_F(ValidationErrorTest, InvalidOptionName) {
  4430. BuildFileWithErrors(
  4431. "name: \"foo.proto\" "
  4432. "message_type { "
  4433. " name: \"TestMessage\" "
  4434. " field { name:\"foo\" number:1 label:LABEL_OPTIONAL type:TYPE_BOOL "
  4435. " options { uninterpreted_option { "
  4436. " name { name_part: \"uninterpreted_option\" "
  4437. " is_extension: false }"
  4438. " positive_int_value: 1 "
  4439. " }"
  4440. " }"
  4441. " }"
  4442. "}\n",
  4443. "foo.proto: TestMessage.foo: OPTION_NAME: Option must not use "
  4444. "reserved name \"uninterpreted_option\".\n");
  4445. }
  4446. TEST_F(ValidationErrorTest, RepeatedMessageOption) {
  4447. BuildDescriptorMessagesInTestPool();
  4448. BuildFileWithErrors(
  4449. "name: \"foo.proto\" "
  4450. "dependency: \"google/protobuf/descriptor.proto\" "
  4451. "message_type: { name: \"Bar\" field: { "
  4452. " name: \"foo\" number: 1 label: LABEL_OPTIONAL type: TYPE_INT32 } "
  4453. "} "
  4454. "extension { name: \"bar\" number: 7672757 label: LABEL_REPEATED "
  4455. " type: TYPE_MESSAGE type_name: \"Bar\" "
  4456. " extendee: \"google.protobuf.FileOptions\" }"
  4457. "options { uninterpreted_option { name { name_part: \"bar\" "
  4458. " is_extension: true } "
  4459. " name { name_part: \"foo\" "
  4460. " is_extension: false } "
  4461. " positive_int_value: 1 } }",
  4462. "foo.proto: foo.proto: OPTION_NAME: Option field \"(bar)\" is a "
  4463. "repeated message. Repeated message options must be initialized "
  4464. "using an aggregate value.\n");
  4465. }
  4466. TEST_F(ValidationErrorTest, ResolveUndefinedOption) {
  4467. // The following should produce an eror that baz.bar is resolved but not
  4468. // defined.
  4469. // foo.proto:
  4470. // package baz
  4471. // import google/protobuf/descriptor.proto
  4472. // message Bar { optional int32 foo = 1; }
  4473. // extend FileOptions { optional Bar bar = 7672757; }
  4474. //
  4475. // qux.proto:
  4476. // package qux.baz
  4477. // option (baz.bar).foo = 1;
  4478. //
  4479. // Although "baz.bar" is already defined, the lookup code will try
  4480. // "qux.baz.bar", since it's the match from the innermost scope, which will
  4481. // cause a symbol not defined error.
  4482. BuildDescriptorMessagesInTestPool();
  4483. BuildFile(
  4484. "name: \"foo.proto\" "
  4485. "package: \"baz\" "
  4486. "dependency: \"google/protobuf/descriptor.proto\" "
  4487. "message_type: { name: \"Bar\" field: { "
  4488. " name: \"foo\" number: 1 label: LABEL_OPTIONAL type: TYPE_INT32 } "
  4489. "} "
  4490. "extension { name: \"bar\" number: 7672757 label: LABEL_OPTIONAL "
  4491. " type: TYPE_MESSAGE type_name: \"Bar\" "
  4492. " extendee: \"google.protobuf.FileOptions\" }");
  4493. BuildFileWithErrors(
  4494. "name: \"qux.proto\" "
  4495. "package: \"qux.baz\" "
  4496. "options { uninterpreted_option { name { name_part: \"baz.bar\" "
  4497. " is_extension: true } "
  4498. " name { name_part: \"foo\" "
  4499. " is_extension: false } "
  4500. " positive_int_value: 1 } }",
  4501. "qux.proto: qux.proto: OPTION_NAME: Option \"(baz.bar)\" is resolved to "
  4502. "\"(qux.baz.bar)\","
  4503. " which is not defined. The innermost scope is searched first in name "
  4504. "resolution. Consider using a leading '.'(i.e., \"(.baz.bar)\") to start "
  4505. "from the outermost scope.\n");
  4506. }
  4507. TEST_F(ValidationErrorTest, UnknownOption) {
  4508. BuildFileWithErrors(
  4509. "name: \"qux.proto\" "
  4510. "package: \"qux.baz\" "
  4511. "options { uninterpreted_option { name { name_part: \"baaz.bar\" "
  4512. " is_extension: true } "
  4513. " name { name_part: \"foo\" "
  4514. " is_extension: false } "
  4515. " positive_int_value: 1 } }",
  4516. "qux.proto: qux.proto: OPTION_NAME: Option \"(baaz.bar)\" unknown. "
  4517. "Ensure "
  4518. "that your proto definition file imports the proto which defines the "
  4519. "option.\n");
  4520. }
  4521. TEST_F(ValidationErrorTest, CustomOptionConflictingFieldNumber) {
  4522. BuildDescriptorMessagesInTestPool();
  4523. BuildFileWithErrors(
  4524. "name: \"foo.proto\" "
  4525. "dependency: \"google/protobuf/descriptor.proto\" "
  4526. "extension { name: \"foo1\" number: 7672757 label: LABEL_OPTIONAL "
  4527. " type: TYPE_INT32 extendee: \"google.protobuf.FieldOptions\" }"
  4528. "extension { name: \"foo2\" number: 7672757 label: LABEL_OPTIONAL "
  4529. " type: TYPE_INT32 extendee: \"google.protobuf.FieldOptions\" }",
  4530. "foo.proto: foo2: NUMBER: Extension number 7672757 has already been used "
  4531. "in \"google.protobuf.FieldOptions\" by extension \"foo1\".\n");
  4532. }
  4533. TEST_F(ValidationErrorTest, Int32OptionValueOutOfPositiveRange) {
  4534. BuildDescriptorMessagesInTestPool();
  4535. BuildFileWithErrors(
  4536. "name: \"foo.proto\" "
  4537. "dependency: \"google/protobuf/descriptor.proto\" "
  4538. "extension { name: \"foo\" number: 7672757 label: LABEL_OPTIONAL "
  4539. " type: TYPE_INT32 extendee: \"google.protobuf.FileOptions\" }"
  4540. "options { uninterpreted_option { name { name_part: \"foo\" "
  4541. " is_extension: true } "
  4542. " positive_int_value: 0x80000000 } "
  4543. "}",
  4544. "foo.proto: foo.proto: OPTION_VALUE: Value out of range "
  4545. "for int32 option \"foo\".\n");
  4546. }
  4547. TEST_F(ValidationErrorTest, Int32OptionValueOutOfNegativeRange) {
  4548. BuildDescriptorMessagesInTestPool();
  4549. BuildFileWithErrors(
  4550. "name: \"foo.proto\" "
  4551. "dependency: \"google/protobuf/descriptor.proto\" "
  4552. "extension { name: \"foo\" number: 7672757 label: LABEL_OPTIONAL "
  4553. " type: TYPE_INT32 extendee: \"google.protobuf.FileOptions\" }"
  4554. "options { uninterpreted_option { name { name_part: \"foo\" "
  4555. " is_extension: true } "
  4556. " negative_int_value: -0x80000001 } "
  4557. "}",
  4558. "foo.proto: foo.proto: OPTION_VALUE: Value out of range "
  4559. "for int32 option \"foo\".\n");
  4560. }
  4561. TEST_F(ValidationErrorTest, Int32OptionValueIsNotPositiveInt) {
  4562. BuildDescriptorMessagesInTestPool();
  4563. BuildFileWithErrors(
  4564. "name: \"foo.proto\" "
  4565. "dependency: \"google/protobuf/descriptor.proto\" "
  4566. "extension { name: \"foo\" number: 7672757 label: LABEL_OPTIONAL "
  4567. " type: TYPE_INT32 extendee: \"google.protobuf.FileOptions\" }"
  4568. "options { uninterpreted_option { name { name_part: \"foo\" "
  4569. " is_extension: true } "
  4570. " string_value: \"5\" } }",
  4571. "foo.proto: foo.proto: OPTION_VALUE: Value must be integer "
  4572. "for int32 option \"foo\".\n");
  4573. }
  4574. TEST_F(ValidationErrorTest, Int64OptionValueOutOfRange) {
  4575. BuildDescriptorMessagesInTestPool();
  4576. BuildFileWithErrors(
  4577. "name: \"foo.proto\" "
  4578. "dependency: \"google/protobuf/descriptor.proto\" "
  4579. "extension { name: \"foo\" number: 7672757 label: LABEL_OPTIONAL "
  4580. " type: TYPE_INT64 extendee: \"google.protobuf.FileOptions\" }"
  4581. "options { uninterpreted_option { name { name_part: \"foo\" "
  4582. " is_extension: true } "
  4583. " positive_int_value: 0x8000000000000000 "
  4584. "} "
  4585. "}",
  4586. "foo.proto: foo.proto: OPTION_VALUE: Value out of range "
  4587. "for int64 option \"foo\".\n");
  4588. }
  4589. TEST_F(ValidationErrorTest, Int64OptionValueIsNotPositiveInt) {
  4590. BuildDescriptorMessagesInTestPool();
  4591. BuildFileWithErrors(
  4592. "name: \"foo.proto\" "
  4593. "dependency: \"google/protobuf/descriptor.proto\" "
  4594. "extension { name: \"foo\" number: 7672757 label: LABEL_OPTIONAL "
  4595. " type: TYPE_INT64 extendee: \"google.protobuf.FileOptions\" }"
  4596. "options { uninterpreted_option { name { name_part: \"foo\" "
  4597. " is_extension: true } "
  4598. " identifier_value: \"5\" } }",
  4599. "foo.proto: foo.proto: OPTION_VALUE: Value must be integer "
  4600. "for int64 option \"foo\".\n");
  4601. }
  4602. TEST_F(ValidationErrorTest, UInt32OptionValueOutOfRange) {
  4603. BuildDescriptorMessagesInTestPool();
  4604. BuildFileWithErrors(
  4605. "name: \"foo.proto\" "
  4606. "dependency: \"google/protobuf/descriptor.proto\" "
  4607. "extension { name: \"foo\" number: 7672757 label: LABEL_OPTIONAL "
  4608. " type: TYPE_UINT32 extendee: \"google.protobuf.FileOptions\" }"
  4609. "options { uninterpreted_option { name { name_part: \"foo\" "
  4610. " is_extension: true } "
  4611. " positive_int_value: 0x100000000 } }",
  4612. "foo.proto: foo.proto: OPTION_VALUE: Value out of range "
  4613. "for uint32 option \"foo\".\n");
  4614. }
  4615. TEST_F(ValidationErrorTest, UInt32OptionValueIsNotPositiveInt) {
  4616. BuildDescriptorMessagesInTestPool();
  4617. BuildFileWithErrors(
  4618. "name: \"foo.proto\" "
  4619. "dependency: \"google/protobuf/descriptor.proto\" "
  4620. "extension { name: \"foo\" number: 7672757 label: LABEL_OPTIONAL "
  4621. " type: TYPE_UINT32 extendee: \"google.protobuf.FileOptions\" }"
  4622. "options { uninterpreted_option { name { name_part: \"foo\" "
  4623. " is_extension: true } "
  4624. " double_value: -5.6 } }",
  4625. "foo.proto: foo.proto: OPTION_VALUE: Value must be non-negative integer "
  4626. "for uint32 option \"foo\".\n");
  4627. }
  4628. TEST_F(ValidationErrorTest, UInt64OptionValueIsNotPositiveInt) {
  4629. BuildDescriptorMessagesInTestPool();
  4630. BuildFileWithErrors(
  4631. "name: \"foo.proto\" "
  4632. "dependency: \"google/protobuf/descriptor.proto\" "
  4633. "extension { name: \"foo\" number: 7672757 label: LABEL_OPTIONAL "
  4634. " type: TYPE_UINT64 extendee: \"google.protobuf.FileOptions\" }"
  4635. "options { uninterpreted_option { name { name_part: \"foo\" "
  4636. " is_extension: true } "
  4637. " negative_int_value: -5 } }",
  4638. "foo.proto: foo.proto: OPTION_VALUE: Value must be non-negative integer "
  4639. "for uint64 option \"foo\".\n");
  4640. }
  4641. TEST_F(ValidationErrorTest, FloatOptionValueIsNotNumber) {
  4642. BuildDescriptorMessagesInTestPool();
  4643. BuildFileWithErrors(
  4644. "name: \"foo.proto\" "
  4645. "dependency: \"google/protobuf/descriptor.proto\" "
  4646. "extension { name: \"foo\" number: 7672757 label: LABEL_OPTIONAL "
  4647. " type: TYPE_FLOAT extendee: \"google.protobuf.FileOptions\" }"
  4648. "options { uninterpreted_option { name { name_part: \"foo\" "
  4649. " is_extension: true } "
  4650. " string_value: \"bar\" } }",
  4651. "foo.proto: foo.proto: OPTION_VALUE: Value must be number "
  4652. "for float option \"foo\".\n");
  4653. }
  4654. TEST_F(ValidationErrorTest, DoubleOptionValueIsNotNumber) {
  4655. BuildDescriptorMessagesInTestPool();
  4656. BuildFileWithErrors(
  4657. "name: \"foo.proto\" "
  4658. "dependency: \"google/protobuf/descriptor.proto\" "
  4659. "extension { name: \"foo\" number: 7672757 label: LABEL_OPTIONAL "
  4660. " type: TYPE_DOUBLE extendee: \"google.protobuf.FileOptions\" }"
  4661. "options { uninterpreted_option { name { name_part: \"foo\" "
  4662. " is_extension: true } "
  4663. " string_value: \"bar\" } }",
  4664. "foo.proto: foo.proto: OPTION_VALUE: Value must be number "
  4665. "for double option \"foo\".\n");
  4666. }
  4667. TEST_F(ValidationErrorTest, BoolOptionValueIsNotTrueOrFalse) {
  4668. BuildDescriptorMessagesInTestPool();
  4669. BuildFileWithErrors(
  4670. "name: \"foo.proto\" "
  4671. "dependency: \"google/protobuf/descriptor.proto\" "
  4672. "extension { name: \"foo\" number: 7672757 label: LABEL_OPTIONAL "
  4673. " type: TYPE_BOOL extendee: \"google.protobuf.FileOptions\" }"
  4674. "options { uninterpreted_option { name { name_part: \"foo\" "
  4675. " is_extension: true } "
  4676. " identifier_value: \"bar\" } }",
  4677. "foo.proto: foo.proto: OPTION_VALUE: Value must be \"true\" or \"false\" "
  4678. "for boolean option \"foo\".\n");
  4679. }
  4680. TEST_F(ValidationErrorTest, EnumOptionValueIsNotIdentifier) {
  4681. BuildDescriptorMessagesInTestPool();
  4682. BuildFileWithErrors(
  4683. "name: \"foo.proto\" "
  4684. "dependency: \"google/protobuf/descriptor.proto\" "
  4685. "enum_type { name: \"FooEnum\" value { name: \"BAR\" number: 1 } "
  4686. " value { name: \"BAZ\" number: 2 } }"
  4687. "extension { name: \"foo\" number: 7672757 label: LABEL_OPTIONAL "
  4688. " type: TYPE_ENUM type_name: \"FooEnum\" "
  4689. " extendee: \"google.protobuf.FileOptions\" }"
  4690. "options { uninterpreted_option { name { name_part: \"foo\" "
  4691. " is_extension: true } "
  4692. " string_value: \"QUUX\" } }",
  4693. "foo.proto: foo.proto: OPTION_VALUE: Value must be identifier for "
  4694. "enum-valued option \"foo\".\n");
  4695. }
  4696. TEST_F(ValidationErrorTest, EnumOptionValueIsNotEnumValueName) {
  4697. BuildDescriptorMessagesInTestPool();
  4698. BuildFileWithErrors(
  4699. "name: \"foo.proto\" "
  4700. "dependency: \"google/protobuf/descriptor.proto\" "
  4701. "enum_type { name: \"FooEnum\" value { name: \"BAR\" number: 1 } "
  4702. " value { name: \"BAZ\" number: 2 } }"
  4703. "extension { name: \"foo\" number: 7672757 label: LABEL_OPTIONAL "
  4704. " type: TYPE_ENUM type_name: \"FooEnum\" "
  4705. " extendee: \"google.protobuf.FileOptions\" }"
  4706. "options { uninterpreted_option { name { name_part: \"foo\" "
  4707. " is_extension: true } "
  4708. " identifier_value: \"QUUX\" } }",
  4709. "foo.proto: foo.proto: OPTION_VALUE: Enum type \"FooEnum\" has no value "
  4710. "named \"QUUX\" for option \"foo\".\n");
  4711. }
  4712. TEST_F(ValidationErrorTest, EnumOptionValueIsSiblingEnumValueName) {
  4713. BuildDescriptorMessagesInTestPool();
  4714. BuildFileWithErrors(
  4715. "name: \"foo.proto\" "
  4716. "dependency: \"google/protobuf/descriptor.proto\" "
  4717. "enum_type { name: \"FooEnum1\" value { name: \"BAR\" number: 1 } "
  4718. " value { name: \"BAZ\" number: 2 } }"
  4719. "enum_type { name: \"FooEnum2\" value { name: \"QUX\" number: 1 } "
  4720. " value { name: \"QUUX\" number: 2 } }"
  4721. "extension { name: \"foo\" number: 7672757 label: LABEL_OPTIONAL "
  4722. " type: TYPE_ENUM type_name: \"FooEnum1\" "
  4723. " extendee: \"google.protobuf.FileOptions\" }"
  4724. "options { uninterpreted_option { name { name_part: \"foo\" "
  4725. " is_extension: true } "
  4726. " identifier_value: \"QUUX\" } }",
  4727. "foo.proto: foo.proto: OPTION_VALUE: Enum type \"FooEnum1\" has no value "
  4728. "named \"QUUX\" for option \"foo\". This appears to be a value from a "
  4729. "sibling type.\n");
  4730. }
  4731. TEST_F(ValidationErrorTest, StringOptionValueIsNotString) {
  4732. BuildDescriptorMessagesInTestPool();
  4733. BuildFileWithErrors(
  4734. "name: \"foo.proto\" "
  4735. "dependency: \"google/protobuf/descriptor.proto\" "
  4736. "extension { name: \"foo\" number: 7672757 label: LABEL_OPTIONAL "
  4737. " type: TYPE_STRING extendee: \"google.protobuf.FileOptions\" }"
  4738. "options { uninterpreted_option { name { name_part: \"foo\" "
  4739. " is_extension: true } "
  4740. " identifier_value: \"QUUX\" } }",
  4741. "foo.proto: foo.proto: OPTION_VALUE: Value must be quoted string "
  4742. "for "
  4743. "string option \"foo\".\n");
  4744. }
  4745. TEST_F(ValidationErrorTest, JsonNameOptionOnExtensions) {
  4746. BuildFileWithErrors(
  4747. "name: \"foo.proto\" "
  4748. "package: \"foo\" "
  4749. "message_type {"
  4750. " name: \"Foo\""
  4751. " extension_range { start: 10 end: 20 }"
  4752. "}"
  4753. "extension {"
  4754. " name: \"value\""
  4755. " number: 10"
  4756. " label: LABEL_OPTIONAL"
  4757. " type: TYPE_INT32"
  4758. " extendee: \"foo.Foo\""
  4759. " json_name: \"myName\""
  4760. "}",
  4761. "foo.proto: foo.value: OPTION_NAME: option json_name is not allowed on "
  4762. "extension fields.\n");
  4763. }
  4764. TEST_F(ValidationErrorTest, DuplicateExtensionFieldNumber) {
  4765. BuildDescriptorMessagesInTestPool();
  4766. BuildFile(
  4767. "name: \"foo.proto\" "
  4768. "dependency: \"google/protobuf/descriptor.proto\" "
  4769. "extension { name: \"option1\" number: 1000 label: LABEL_OPTIONAL "
  4770. " type: TYPE_INT32 extendee: \"google.protobuf.FileOptions\" }");
  4771. BuildFileWithWarnings(
  4772. "name: \"bar.proto\" "
  4773. "dependency: \"google/protobuf/descriptor.proto\" "
  4774. "extension { name: \"option2\" number: 1000 label: LABEL_OPTIONAL "
  4775. " type: TYPE_INT32 extendee: \"google.protobuf.FileOptions\" }",
  4776. "bar.proto: option2: NUMBER: Extension number 1000 has already been used "
  4777. "in \"google.protobuf.FileOptions\" by extension \"option1\" defined in "
  4778. "foo.proto.\n");
  4779. }
  4780. // Helper function for tests that check for aggregate value parsing
  4781. // errors. The "value" argument is embedded inside the
  4782. // "uninterpreted_option" portion of the result.
  4783. static std::string EmbedAggregateValue(const char* value) {
  4784. return strings::Substitute(
  4785. "name: \"foo.proto\" "
  4786. "dependency: \"google/protobuf/descriptor.proto\" "
  4787. "message_type { name: \"Foo\" } "
  4788. "extension { name: \"foo\" number: 7672757 label: LABEL_OPTIONAL "
  4789. " type: TYPE_MESSAGE type_name: \"Foo\" "
  4790. " extendee: \"google.protobuf.FileOptions\" }"
  4791. "options { uninterpreted_option { name { name_part: \"foo\" "
  4792. " is_extension: true } "
  4793. " $0 } }",
  4794. value);
  4795. }
  4796. TEST_F(ValidationErrorTest, AggregateValueNotFound) {
  4797. BuildDescriptorMessagesInTestPool();
  4798. BuildFileWithErrors(
  4799. EmbedAggregateValue("string_value: \"\""),
  4800. "foo.proto: foo.proto: OPTION_VALUE: Option \"foo\" is a message. "
  4801. "To set the entire message, use syntax like "
  4802. "\"foo = { <proto text format> }\". To set fields within it, use "
  4803. "syntax like \"foo.foo = value\".\n");
  4804. }
  4805. TEST_F(ValidationErrorTest, AggregateValueParseError) {
  4806. BuildDescriptorMessagesInTestPool();
  4807. BuildFileWithErrors(
  4808. EmbedAggregateValue("aggregate_value: \"1+2\""),
  4809. "foo.proto: foo.proto: OPTION_VALUE: Error while parsing option "
  4810. "value for \"foo\": Expected identifier, got: 1\n");
  4811. }
  4812. TEST_F(ValidationErrorTest, AggregateValueUnknownFields) {
  4813. BuildDescriptorMessagesInTestPool();
  4814. BuildFileWithErrors(
  4815. EmbedAggregateValue("aggregate_value: \"x:100\""),
  4816. "foo.proto: foo.proto: OPTION_VALUE: Error while parsing option "
  4817. "value for \"foo\": Message type \"Foo\" has no field named \"x\".\n");
  4818. }
  4819. TEST_F(ValidationErrorTest, NotLiteImportsLite) {
  4820. BuildFile(
  4821. "name: \"bar.proto\" "
  4822. "options { optimize_for: LITE_RUNTIME } ");
  4823. BuildFileWithErrors(
  4824. "name: \"foo.proto\" "
  4825. "dependency: \"bar.proto\" ",
  4826. "foo.proto: bar.proto: IMPORT: Files that do not use optimize_for = "
  4827. "LITE_RUNTIME cannot import files which do use this option. This file "
  4828. "is not lite, but it imports \"bar.proto\" which is.\n");
  4829. }
  4830. TEST_F(ValidationErrorTest, LiteExtendsNotLite) {
  4831. BuildFile(
  4832. "name: \"bar.proto\" "
  4833. "message_type: {"
  4834. " name: \"Bar\""
  4835. " extension_range { start: 1 end: 1000 }"
  4836. "}");
  4837. BuildFileWithErrors(
  4838. "name: \"foo.proto\" "
  4839. "dependency: \"bar.proto\" "
  4840. "options { optimize_for: LITE_RUNTIME } "
  4841. "extension { name: \"ext\" number: 123 label: LABEL_OPTIONAL "
  4842. " type: TYPE_INT32 extendee: \"Bar\" }",
  4843. "foo.proto: ext: EXTENDEE: Extensions to non-lite types can only be "
  4844. "declared in non-lite files. Note that you cannot extend a non-lite "
  4845. "type to contain a lite type, but the reverse is allowed.\n");
  4846. }
  4847. TEST_F(ValidationErrorTest, NoLiteServices) {
  4848. BuildFileWithErrors(
  4849. "name: \"foo.proto\" "
  4850. "options {"
  4851. " optimize_for: LITE_RUNTIME"
  4852. " cc_generic_services: true"
  4853. " java_generic_services: true"
  4854. "} "
  4855. "service { name: \"Foo\" }",
  4856. "foo.proto: Foo: NAME: Files with optimize_for = LITE_RUNTIME cannot "
  4857. "define services unless you set both options cc_generic_services and "
  4858. "java_generic_services to false.\n");
  4859. BuildFile(
  4860. "name: \"bar.proto\" "
  4861. "options {"
  4862. " optimize_for: LITE_RUNTIME"
  4863. " cc_generic_services: false"
  4864. " java_generic_services: false"
  4865. "} "
  4866. "service { name: \"Bar\" }");
  4867. }
  4868. TEST_F(ValidationErrorTest, RollbackAfterError) {
  4869. // Build a file which contains every kind of construct but references an
  4870. // undefined type. All these constructs will be added to the symbol table
  4871. // before the undefined type error is noticed. The DescriptorPool will then
  4872. // have to roll everything back.
  4873. BuildFileWithErrors(
  4874. "name: \"foo.proto\" "
  4875. "message_type {"
  4876. " name: \"TestMessage\""
  4877. " field { name:\"foo\" label:LABEL_OPTIONAL type:TYPE_INT32 number:1 }"
  4878. "} "
  4879. "enum_type {"
  4880. " name: \"TestEnum\""
  4881. " value { name:\"BAR\" number:1 }"
  4882. "} "
  4883. "service {"
  4884. " name: \"TestService\""
  4885. " method {"
  4886. " name: \"Baz\""
  4887. " input_type: \"NoSuchType\"" // error
  4888. " output_type: \"TestMessage\""
  4889. " }"
  4890. "}",
  4891. "foo.proto: TestService.Baz: INPUT_TYPE: \"NoSuchType\" is not defined.\n"
  4892. );
  4893. // Make sure that if we build the same file again with the error fixed,
  4894. // it works. If the above rollback was incomplete, then some symbols will
  4895. // be left defined, and this second attempt will fail since it tries to
  4896. // re-define the same symbols.
  4897. BuildFile(
  4898. "name: \"foo.proto\" "
  4899. "message_type {"
  4900. " name: \"TestMessage\""
  4901. " field { name:\"foo\" label:LABEL_OPTIONAL type:TYPE_INT32 number:1 }"
  4902. "} "
  4903. "enum_type {"
  4904. " name: \"TestEnum\""
  4905. " value { name:\"BAR\" number:1 }"
  4906. "} "
  4907. "service {"
  4908. " name: \"TestService\""
  4909. " method { name:\"Baz\""
  4910. " input_type:\"TestMessage\""
  4911. " output_type:\"TestMessage\" }"
  4912. "}");
  4913. }
  4914. TEST_F(ValidationErrorTest, ErrorsReportedToLogError) {
  4915. // Test that errors are reported to GOOGLE_LOG(ERROR) if no error collector is
  4916. // provided.
  4917. FileDescriptorProto file_proto;
  4918. ASSERT_TRUE(
  4919. TextFormat::ParseFromString("name: \"foo.proto\" "
  4920. "message_type { name: \"Foo\" } "
  4921. "message_type { name: \"Foo\" } ",
  4922. &file_proto));
  4923. std::vector<std::string> errors;
  4924. {
  4925. ScopedMemoryLog log;
  4926. EXPECT_TRUE(pool_.BuildFile(file_proto) == nullptr);
  4927. errors = log.GetMessages(ERROR);
  4928. }
  4929. ASSERT_EQ(2, errors.size());
  4930. EXPECT_EQ("Invalid proto descriptor for file \"foo.proto\":", errors[0]);
  4931. EXPECT_EQ(" Foo: \"Foo\" is already defined.", errors[1]);
  4932. }
  4933. TEST_F(ValidationErrorTest, DisallowEnumAlias) {
  4934. BuildFileWithErrors(
  4935. "name: \"foo.proto\" "
  4936. "enum_type {"
  4937. " name: \"Bar\""
  4938. " value { name:\"ENUM_A\" number:0 }"
  4939. " value { name:\"ENUM_B\" number:0 }"
  4940. "}",
  4941. "foo.proto: Bar: NUMBER: "
  4942. "\"ENUM_B\" uses the same enum value as \"ENUM_A\". "
  4943. "If this is intended, set 'option allow_alias = true;' to the enum "
  4944. "definition.\n");
  4945. }
  4946. TEST_F(ValidationErrorTest, AllowEnumAlias) {
  4947. BuildFile(
  4948. "name: \"foo.proto\" "
  4949. "enum_type {"
  4950. " name: \"Bar\""
  4951. " value { name:\"ENUM_A\" number:0 }"
  4952. " value { name:\"ENUM_B\" number:0 }"
  4953. " options { allow_alias: true }"
  4954. "}");
  4955. }
  4956. TEST_F(ValidationErrorTest, UnusedImportWarning) {
  4957. pool_.AddUnusedImportTrackFile("bar.proto");
  4958. BuildFile(
  4959. "name: \"bar.proto\" "
  4960. "message_type { name: \"Bar\" }");
  4961. pool_.AddUnusedImportTrackFile("base.proto");
  4962. BuildFile(
  4963. "name: \"base.proto\" "
  4964. "message_type { name: \"Base\" }");
  4965. pool_.AddUnusedImportTrackFile("baz.proto");
  4966. BuildFile(
  4967. "name: \"baz.proto\" "
  4968. "message_type { name: \"Baz\" }");
  4969. pool_.AddUnusedImportTrackFile("public.proto");
  4970. BuildFile(
  4971. "name: \"public.proto\" "
  4972. "dependency: \"bar.proto\""
  4973. "public_dependency: 0");
  4974. // // forward.proto
  4975. // import "base.proto" // No warning: Base message is used.
  4976. // import "bar.proto" // Will log a warning.
  4977. // import public "baz.proto" // No warning: Do not track import public.
  4978. // import "public.proto" // No warning: public.proto has import public.
  4979. // message Forward {
  4980. // optional Base base = 1;
  4981. // }
  4982. //
  4983. pool_.AddUnusedImportTrackFile("forward.proto");
  4984. BuildFileWithWarnings(
  4985. "name: \"forward.proto\""
  4986. "dependency: \"base.proto\""
  4987. "dependency: \"bar.proto\""
  4988. "dependency: \"baz.proto\""
  4989. "dependency: \"public.proto\""
  4990. "public_dependency: 2 "
  4991. "message_type {"
  4992. " name: \"Forward\""
  4993. " field { name:\"base\" number:1 label:LABEL_OPTIONAL "
  4994. "type_name:\"Base\" }"
  4995. "}",
  4996. "forward.proto: bar.proto: IMPORT: Import bar.proto is unused.\n");
  4997. }
  4998. namespace {
  4999. void FillValidMapEntry(FileDescriptorProto* file_proto) {
  5000. ASSERT_TRUE(TextFormat::ParseFromString(
  5001. "name: 'foo.proto' "
  5002. "message_type { "
  5003. " name: 'Foo' "
  5004. " field { "
  5005. " name: 'foo_map' number: 1 label:LABEL_REPEATED "
  5006. " type_name: 'FooMapEntry' "
  5007. " } "
  5008. " nested_type { "
  5009. " name: 'FooMapEntry' "
  5010. " options { map_entry: true } "
  5011. " field { "
  5012. " name: 'key' number: 1 type:TYPE_INT32 label:LABEL_OPTIONAL "
  5013. " } "
  5014. " field { "
  5015. " name: 'value' number: 2 type:TYPE_INT32 label:LABEL_OPTIONAL "
  5016. " } "
  5017. " } "
  5018. "} "
  5019. "message_type { "
  5020. " name: 'Bar' "
  5021. " extension_range { start: 1 end: 10 }"
  5022. "} ",
  5023. file_proto));
  5024. }
  5025. static const char* kMapEntryErrorMessage =
  5026. "foo.proto: Foo.foo_map: TYPE: map_entry should not be set explicitly. "
  5027. "Use map<KeyType, ValueType> instead.\n";
  5028. static const char* kMapEntryKeyTypeErrorMessage =
  5029. "foo.proto: Foo.foo_map: TYPE: Key in map fields cannot be float/double, "
  5030. "bytes or message types.\n";
  5031. } // namespace
  5032. TEST_F(ValidationErrorTest, MapEntryBase) {
  5033. FileDescriptorProto file_proto;
  5034. FillValidMapEntry(&file_proto);
  5035. BuildFile(file_proto.DebugString());
  5036. }
  5037. TEST_F(ValidationErrorTest, MapEntryExtensionRange) {
  5038. FileDescriptorProto file_proto;
  5039. FillValidMapEntry(&file_proto);
  5040. TextFormat::MergeFromString(
  5041. "extension_range { "
  5042. " start: 10 end: 20 "
  5043. "} ",
  5044. file_proto.mutable_message_type(0)->mutable_nested_type(0));
  5045. BuildFileWithErrors(file_proto.DebugString(), kMapEntryErrorMessage);
  5046. }
  5047. TEST_F(ValidationErrorTest, MapEntryExtension) {
  5048. FileDescriptorProto file_proto;
  5049. FillValidMapEntry(&file_proto);
  5050. TextFormat::MergeFromString(
  5051. "extension { "
  5052. " name: 'foo_ext' extendee: '.Bar' number: 5"
  5053. "} ",
  5054. file_proto.mutable_message_type(0)->mutable_nested_type(0));
  5055. BuildFileWithErrors(file_proto.DebugString(), kMapEntryErrorMessage);
  5056. }
  5057. TEST_F(ValidationErrorTest, MapEntryNestedType) {
  5058. FileDescriptorProto file_proto;
  5059. FillValidMapEntry(&file_proto);
  5060. TextFormat::MergeFromString(
  5061. "nested_type { "
  5062. " name: 'Bar' "
  5063. "} ",
  5064. file_proto.mutable_message_type(0)->mutable_nested_type(0));
  5065. BuildFileWithErrors(file_proto.DebugString(), kMapEntryErrorMessage);
  5066. }
  5067. TEST_F(ValidationErrorTest, MapEntryEnumTypes) {
  5068. FileDescriptorProto file_proto;
  5069. FillValidMapEntry(&file_proto);
  5070. TextFormat::MergeFromString(
  5071. "enum_type { "
  5072. " name: 'BarEnum' "
  5073. " value { name: 'BAR_BAR' number:0 } "
  5074. "} ",
  5075. file_proto.mutable_message_type(0)->mutable_nested_type(0));
  5076. BuildFileWithErrors(file_proto.DebugString(), kMapEntryErrorMessage);
  5077. }
  5078. TEST_F(ValidationErrorTest, MapEntryExtraField) {
  5079. FileDescriptorProto file_proto;
  5080. FillValidMapEntry(&file_proto);
  5081. TextFormat::MergeFromString(
  5082. "field { "
  5083. " name: 'other_field' "
  5084. " label: LABEL_OPTIONAL "
  5085. " type: TYPE_INT32 "
  5086. " number: 3 "
  5087. "} ",
  5088. file_proto.mutable_message_type(0)->mutable_nested_type(0));
  5089. BuildFileWithErrors(file_proto.DebugString(), kMapEntryErrorMessage);
  5090. }
  5091. TEST_F(ValidationErrorTest, MapEntryMessageName) {
  5092. FileDescriptorProto file_proto;
  5093. FillValidMapEntry(&file_proto);
  5094. file_proto.mutable_message_type(0)->mutable_nested_type(0)->set_name(
  5095. "OtherMapEntry");
  5096. file_proto.mutable_message_type(0)->mutable_field(0)->set_type_name(
  5097. "OtherMapEntry");
  5098. BuildFileWithErrors(file_proto.DebugString(), kMapEntryErrorMessage);
  5099. }
  5100. TEST_F(ValidationErrorTest, MapEntryNoneRepeatedMapEntry) {
  5101. FileDescriptorProto file_proto;
  5102. FillValidMapEntry(&file_proto);
  5103. file_proto.mutable_message_type(0)->mutable_field(0)->set_label(
  5104. FieldDescriptorProto::LABEL_OPTIONAL);
  5105. BuildFileWithErrors(file_proto.DebugString(), kMapEntryErrorMessage);
  5106. }
  5107. TEST_F(ValidationErrorTest, MapEntryDifferentContainingType) {
  5108. FileDescriptorProto file_proto;
  5109. FillValidMapEntry(&file_proto);
  5110. // Move the nested MapEntry message into the top level, which should not pass
  5111. // the validation.
  5112. file_proto.mutable_message_type()->AddAllocated(
  5113. file_proto.mutable_message_type(0)->mutable_nested_type()->ReleaseLast());
  5114. BuildFileWithErrors(file_proto.DebugString(), kMapEntryErrorMessage);
  5115. }
  5116. TEST_F(ValidationErrorTest, MapEntryKeyName) {
  5117. FileDescriptorProto file_proto;
  5118. FillValidMapEntry(&file_proto);
  5119. FieldDescriptorProto* key =
  5120. file_proto.mutable_message_type(0)->mutable_nested_type(0)->mutable_field(
  5121. 0);
  5122. key->set_name("Key");
  5123. BuildFileWithErrors(file_proto.DebugString(), kMapEntryErrorMessage);
  5124. }
  5125. TEST_F(ValidationErrorTest, MapEntryKeyLabel) {
  5126. FileDescriptorProto file_proto;
  5127. FillValidMapEntry(&file_proto);
  5128. FieldDescriptorProto* key =
  5129. file_proto.mutable_message_type(0)->mutable_nested_type(0)->mutable_field(
  5130. 0);
  5131. key->set_label(FieldDescriptorProto::LABEL_REQUIRED);
  5132. BuildFileWithErrors(file_proto.DebugString(), kMapEntryErrorMessage);
  5133. }
  5134. TEST_F(ValidationErrorTest, MapEntryKeyNumber) {
  5135. FileDescriptorProto file_proto;
  5136. FillValidMapEntry(&file_proto);
  5137. FieldDescriptorProto* key =
  5138. file_proto.mutable_message_type(0)->mutable_nested_type(0)->mutable_field(
  5139. 0);
  5140. key->set_number(3);
  5141. BuildFileWithErrors(file_proto.DebugString(), kMapEntryErrorMessage);
  5142. }
  5143. TEST_F(ValidationErrorTest, MapEntryValueName) {
  5144. FileDescriptorProto file_proto;
  5145. FillValidMapEntry(&file_proto);
  5146. FieldDescriptorProto* value =
  5147. file_proto.mutable_message_type(0)->mutable_nested_type(0)->mutable_field(
  5148. 1);
  5149. value->set_name("Value");
  5150. BuildFileWithErrors(file_proto.DebugString(), kMapEntryErrorMessage);
  5151. }
  5152. TEST_F(ValidationErrorTest, MapEntryValueLabel) {
  5153. FileDescriptorProto file_proto;
  5154. FillValidMapEntry(&file_proto);
  5155. FieldDescriptorProto* value =
  5156. file_proto.mutable_message_type(0)->mutable_nested_type(0)->mutable_field(
  5157. 1);
  5158. value->set_label(FieldDescriptorProto::LABEL_REQUIRED);
  5159. BuildFileWithErrors(file_proto.DebugString(), kMapEntryErrorMessage);
  5160. }
  5161. TEST_F(ValidationErrorTest, MapEntryValueNumber) {
  5162. FileDescriptorProto file_proto;
  5163. FillValidMapEntry(&file_proto);
  5164. FieldDescriptorProto* value =
  5165. file_proto.mutable_message_type(0)->mutable_nested_type(0)->mutable_field(
  5166. 1);
  5167. value->set_number(3);
  5168. BuildFileWithErrors(file_proto.DebugString(), kMapEntryErrorMessage);
  5169. }
  5170. TEST_F(ValidationErrorTest, MapEntryKeyTypeFloat) {
  5171. FileDescriptorProto file_proto;
  5172. FillValidMapEntry(&file_proto);
  5173. FieldDescriptorProto* key =
  5174. file_proto.mutable_message_type(0)->mutable_nested_type(0)->mutable_field(
  5175. 0);
  5176. key->set_type(FieldDescriptorProto::TYPE_FLOAT);
  5177. BuildFileWithErrors(file_proto.DebugString(), kMapEntryKeyTypeErrorMessage);
  5178. }
  5179. TEST_F(ValidationErrorTest, MapEntryKeyTypeDouble) {
  5180. FileDescriptorProto file_proto;
  5181. FillValidMapEntry(&file_proto);
  5182. FieldDescriptorProto* key =
  5183. file_proto.mutable_message_type(0)->mutable_nested_type(0)->mutable_field(
  5184. 0);
  5185. key->set_type(FieldDescriptorProto::TYPE_DOUBLE);
  5186. BuildFileWithErrors(file_proto.DebugString(), kMapEntryKeyTypeErrorMessage);
  5187. }
  5188. TEST_F(ValidationErrorTest, MapEntryKeyTypeBytes) {
  5189. FileDescriptorProto file_proto;
  5190. FillValidMapEntry(&file_proto);
  5191. FieldDescriptorProto* key =
  5192. file_proto.mutable_message_type(0)->mutable_nested_type(0)->mutable_field(
  5193. 0);
  5194. key->set_type(FieldDescriptorProto::TYPE_BYTES);
  5195. BuildFileWithErrors(file_proto.DebugString(), kMapEntryKeyTypeErrorMessage);
  5196. }
  5197. TEST_F(ValidationErrorTest, MapEntryKeyTypeEnum) {
  5198. FileDescriptorProto file_proto;
  5199. FillValidMapEntry(&file_proto);
  5200. FieldDescriptorProto* key =
  5201. file_proto.mutable_message_type(0)->mutable_nested_type(0)->mutable_field(
  5202. 0);
  5203. key->clear_type();
  5204. key->set_type_name("BarEnum");
  5205. EnumDescriptorProto* enum_proto = file_proto.add_enum_type();
  5206. enum_proto->set_name("BarEnum");
  5207. EnumValueDescriptorProto* enum_value_proto = enum_proto->add_value();
  5208. enum_value_proto->set_name("BAR_VALUE0");
  5209. enum_value_proto->set_number(0);
  5210. BuildFileWithErrors(file_proto.DebugString(),
  5211. "foo.proto: Foo.foo_map: TYPE: Key in map fields cannot "
  5212. "be enum types.\n");
  5213. // Enum keys are not allowed in proto3 as well.
  5214. // Get rid of extensions for proto3 to make it proto3 compatible.
  5215. file_proto.mutable_message_type()->RemoveLast();
  5216. file_proto.set_syntax("proto3");
  5217. BuildFileWithErrors(file_proto.DebugString(),
  5218. "foo.proto: Foo.foo_map: TYPE: Key in map fields cannot "
  5219. "be enum types.\n");
  5220. }
  5221. TEST_F(ValidationErrorTest, MapEntryKeyTypeMessage) {
  5222. FileDescriptorProto file_proto;
  5223. FillValidMapEntry(&file_proto);
  5224. FieldDescriptorProto* key =
  5225. file_proto.mutable_message_type(0)->mutable_nested_type(0)->mutable_field(
  5226. 0);
  5227. key->clear_type();
  5228. key->set_type_name(".Bar");
  5229. BuildFileWithErrors(file_proto.DebugString(), kMapEntryKeyTypeErrorMessage);
  5230. }
  5231. TEST_F(ValidationErrorTest, MapEntryConflictsWithField) {
  5232. FileDescriptorProto file_proto;
  5233. FillValidMapEntry(&file_proto);
  5234. TextFormat::MergeFromString(
  5235. "field { "
  5236. " name: 'FooMapEntry' "
  5237. " type: TYPE_INT32 "
  5238. " label: LABEL_OPTIONAL "
  5239. " number: 100 "
  5240. "}",
  5241. file_proto.mutable_message_type(0));
  5242. BuildFileWithErrors(
  5243. file_proto.DebugString(),
  5244. "foo.proto: Foo.FooMapEntry: NAME: \"FooMapEntry\" is already defined in "
  5245. "\"Foo\".\n"
  5246. "foo.proto: Foo.foo_map: TYPE: \"FooMapEntry\" is not defined.\n"
  5247. "foo.proto: Foo: NAME: Expanded map entry type FooMapEntry conflicts "
  5248. "with an existing field.\n");
  5249. }
  5250. TEST_F(ValidationErrorTest, MapEntryConflictsWithMessage) {
  5251. FileDescriptorProto file_proto;
  5252. FillValidMapEntry(&file_proto);
  5253. TextFormat::MergeFromString(
  5254. "nested_type { "
  5255. " name: 'FooMapEntry' "
  5256. "}",
  5257. file_proto.mutable_message_type(0));
  5258. BuildFileWithErrors(
  5259. file_proto.DebugString(),
  5260. "foo.proto: Foo.FooMapEntry: NAME: \"FooMapEntry\" is already defined in "
  5261. "\"Foo\".\n"
  5262. "foo.proto: Foo: NAME: Expanded map entry type FooMapEntry conflicts "
  5263. "with an existing nested message type.\n");
  5264. }
  5265. TEST_F(ValidationErrorTest, MapEntryConflictsWithEnum) {
  5266. FileDescriptorProto file_proto;
  5267. FillValidMapEntry(&file_proto);
  5268. TextFormat::MergeFromString(
  5269. "enum_type { "
  5270. " name: 'FooMapEntry' "
  5271. " value { name: 'ENTRY_FOO' number: 0 }"
  5272. "}",
  5273. file_proto.mutable_message_type(0));
  5274. BuildFileWithErrors(
  5275. file_proto.DebugString(),
  5276. "foo.proto: Foo.FooMapEntry: NAME: \"FooMapEntry\" is already defined in "
  5277. "\"Foo\".\n"
  5278. "foo.proto: Foo: NAME: Expanded map entry type FooMapEntry conflicts "
  5279. "with an existing enum type.\n");
  5280. }
  5281. TEST_F(ValidationErrorTest, EnumValuesConflictWithDifferentCasing) {
  5282. BuildFileWithErrors(
  5283. "syntax: 'proto3'"
  5284. "name: 'foo.proto' "
  5285. "enum_type {"
  5286. " name: 'FooEnum' "
  5287. " value { name: 'BAR' number: 0 }"
  5288. " value { name: 'bar' number: 1 }"
  5289. "}",
  5290. "foo.proto: bar: NAME: Enum name bar has the same name as BAR "
  5291. "if you ignore case and strip out the enum name prefix (if any). "
  5292. "This is error-prone and can lead to undefined behavior. "
  5293. "Please avoid doing this. If you are using allow_alias, please assign "
  5294. "the same numeric value to both enums.\n");
  5295. // Not an error because both enums are mapped to the same value.
  5296. BuildFile(
  5297. "syntax: 'proto3'"
  5298. "name: 'foo.proto' "
  5299. "enum_type {"
  5300. " name: 'FooEnum' "
  5301. " options { allow_alias: true }"
  5302. " value { name: 'UNKNOWN' number: 0 }"
  5303. " value { name: 'BAR' number: 1 }"
  5304. " value { name: 'bar' number: 1 }"
  5305. "}");
  5306. }
  5307. TEST_F(ValidationErrorTest, EnumValuesConflictWhenPrefixesStripped) {
  5308. BuildFileWithErrors(
  5309. "syntax: 'proto3'"
  5310. "name: 'foo.proto' "
  5311. "enum_type {"
  5312. " name: 'FooEnum' "
  5313. " value { name: 'FOO_ENUM_BAZ' number: 0 }"
  5314. " value { name: 'BAZ' number: 1 }"
  5315. "}",
  5316. "foo.proto: BAZ: NAME: Enum name BAZ has the same name as FOO_ENUM_BAZ "
  5317. "if you ignore case and strip out the enum name prefix (if any). "
  5318. "This is error-prone and can lead to undefined behavior. "
  5319. "Please avoid doing this. If you are using allow_alias, please assign "
  5320. "the same numeric value to both enums.\n");
  5321. BuildFileWithErrors(
  5322. "syntax: 'proto3'"
  5323. "name: 'foo.proto' "
  5324. "enum_type {"
  5325. " name: 'FooEnum' "
  5326. " value { name: 'FOOENUM_BAZ' number: 0 }"
  5327. " value { name: 'BAZ' number: 1 }"
  5328. "}",
  5329. "foo.proto: BAZ: NAME: Enum name BAZ has the same name as FOOENUM_BAZ "
  5330. "if you ignore case and strip out the enum name prefix (if any). "
  5331. "This is error-prone and can lead to undefined behavior. "
  5332. "Please avoid doing this. If you are using allow_alias, please assign "
  5333. "the same numeric value to both enums.\n");
  5334. BuildFileWithErrors(
  5335. "syntax: 'proto3'"
  5336. "name: 'foo.proto' "
  5337. "enum_type {"
  5338. " name: 'FooEnum' "
  5339. " value { name: 'FOO_ENUM_BAR_BAZ' number: 0 }"
  5340. " value { name: 'BAR__BAZ' number: 1 }"
  5341. "}",
  5342. "foo.proto: BAR__BAZ: NAME: Enum name BAR__BAZ has the same name as "
  5343. "FOO_ENUM_BAR_BAZ if you ignore case and strip out the enum name prefix "
  5344. "(if any). This is error-prone and can lead to undefined behavior. "
  5345. "Please avoid doing this. If you are using allow_alias, please assign "
  5346. "the same numeric value to both enums.\n");
  5347. BuildFileWithErrors(
  5348. "syntax: 'proto3'"
  5349. "name: 'foo.proto' "
  5350. "enum_type {"
  5351. " name: 'FooEnum' "
  5352. " value { name: 'FOO_ENUM__BAR_BAZ' number: 0 }"
  5353. " value { name: 'BAR_BAZ' number: 1 }"
  5354. "}",
  5355. "foo.proto: BAR_BAZ: NAME: Enum name BAR_BAZ has the same name as "
  5356. "FOO_ENUM__BAR_BAZ if you ignore case and strip out the enum name prefix "
  5357. "(if any). This is error-prone and can lead to undefined behavior. "
  5358. "Please avoid doing this. If you are using allow_alias, please assign "
  5359. "the same numeric value to both enums.\n");
  5360. // This isn't an error because the underscore will cause the PascalCase to
  5361. // differ by case (BarBaz vs. Barbaz).
  5362. BuildFile(
  5363. "syntax: 'proto3'"
  5364. "name: 'foo.proto' "
  5365. "enum_type {"
  5366. " name: 'FooEnum' "
  5367. " value { name: 'BAR_BAZ' number: 0 }"
  5368. " value { name: 'BARBAZ' number: 1 }"
  5369. "}");
  5370. }
  5371. TEST_F(ValidationErrorTest, MapEntryConflictsWithOneof) {
  5372. FileDescriptorProto file_proto;
  5373. FillValidMapEntry(&file_proto);
  5374. TextFormat::MergeFromString(
  5375. "oneof_decl { "
  5376. " name: 'FooMapEntry' "
  5377. "}"
  5378. "field { "
  5379. " name: 'int_field' "
  5380. " type: TYPE_INT32 "
  5381. " label: LABEL_OPTIONAL "
  5382. " oneof_index: 0 "
  5383. " number: 100 "
  5384. "} ",
  5385. file_proto.mutable_message_type(0));
  5386. BuildFileWithErrors(
  5387. file_proto.DebugString(),
  5388. "foo.proto: Foo.FooMapEntry: NAME: \"FooMapEntry\" is already defined in "
  5389. "\"Foo\".\n"
  5390. "foo.proto: Foo.foo_map: TYPE: \"FooMapEntry\" is not defined.\n"
  5391. "foo.proto: Foo: NAME: Expanded map entry type FooMapEntry conflicts "
  5392. "with an existing oneof type.\n");
  5393. }
  5394. TEST_F(ValidationErrorTest, MapEntryUsesNoneZeroEnumDefaultValue) {
  5395. BuildFileWithErrors(
  5396. "name: \"foo.proto\" "
  5397. "enum_type {"
  5398. " name: \"Bar\""
  5399. " value { name:\"ENUM_A\" number:1 }"
  5400. " value { name:\"ENUM_B\" number:2 }"
  5401. "}"
  5402. "message_type {"
  5403. " name: 'Foo' "
  5404. " field { "
  5405. " name: 'foo_map' number: 1 label:LABEL_REPEATED "
  5406. " type_name: 'FooMapEntry' "
  5407. " } "
  5408. " nested_type { "
  5409. " name: 'FooMapEntry' "
  5410. " options { map_entry: true } "
  5411. " field { "
  5412. " name: 'key' number: 1 type:TYPE_INT32 label:LABEL_OPTIONAL "
  5413. " } "
  5414. " field { "
  5415. " name: 'value' number: 2 type_name:\"Bar\" label:LABEL_OPTIONAL "
  5416. " } "
  5417. " } "
  5418. "}",
  5419. "foo.proto: Foo.foo_map: "
  5420. "TYPE: Enum value in map must define 0 as the first value.\n");
  5421. }
  5422. TEST_F(ValidationErrorTest, Proto3RequiredFields) {
  5423. BuildFileWithErrors(
  5424. "name: 'foo.proto' "
  5425. "syntax: 'proto3' "
  5426. "message_type { "
  5427. " name: 'Foo' "
  5428. " field { name:'foo' number:1 label:LABEL_REQUIRED type:TYPE_INT32 } "
  5429. "}",
  5430. "foo.proto: Foo.foo: TYPE: Required fields are not allowed in "
  5431. "proto3.\n");
  5432. // applied to nested types as well.
  5433. BuildFileWithErrors(
  5434. "name: 'foo.proto' "
  5435. "syntax: 'proto3' "
  5436. "message_type { "
  5437. " name: 'Foo' "
  5438. " nested_type { "
  5439. " name : 'Bar' "
  5440. " field { name:'bar' number:1 label:LABEL_REQUIRED type:TYPE_INT32 } "
  5441. " } "
  5442. "}",
  5443. "foo.proto: Foo.Bar.bar: TYPE: Required fields are not allowed in "
  5444. "proto3.\n");
  5445. // optional and repeated fields are OK.
  5446. BuildFile(
  5447. "name: 'foo.proto' "
  5448. "syntax: 'proto3' "
  5449. "message_type { "
  5450. " name: 'Foo' "
  5451. " field { name:'foo' number:1 label:LABEL_OPTIONAL type:TYPE_INT32 } "
  5452. " field { name:'bar' number:2 label:LABEL_REPEATED type:TYPE_INT32 } "
  5453. "}");
  5454. }
  5455. TEST_F(ValidationErrorTest, ValidateProto3DefaultValue) {
  5456. BuildFileWithErrors(
  5457. "name: 'foo.proto' "
  5458. "syntax: 'proto3' "
  5459. "message_type { "
  5460. " name: 'Foo' "
  5461. " field { name:'foo' number:1 label:LABEL_OPTIONAL type:TYPE_INT32 "
  5462. " default_value: '1' }"
  5463. "}",
  5464. "foo.proto: Foo.foo: DEFAULT_VALUE: Explicit default values are not "
  5465. "allowed in proto3.\n");
  5466. BuildFileWithErrors(
  5467. "name: 'foo.proto' "
  5468. "syntax: 'proto3' "
  5469. "message_type { "
  5470. " name: 'Foo' "
  5471. " nested_type { "
  5472. " name : 'Bar' "
  5473. " field { name:'bar' number:1 label:LABEL_OPTIONAL type:TYPE_INT32 "
  5474. " default_value: '1' }"
  5475. " } "
  5476. "}",
  5477. "foo.proto: Foo.Bar.bar: DEFAULT_VALUE: Explicit default values are not "
  5478. "allowed in proto3.\n");
  5479. }
  5480. TEST_F(ValidationErrorTest, ValidateProto3ExtensionRange) {
  5481. BuildFileWithErrors(
  5482. "name: 'foo.proto' "
  5483. "syntax: 'proto3' "
  5484. "message_type { "
  5485. " name: 'Foo' "
  5486. " field { name:'foo' number:1 label:LABEL_OPTIONAL type:TYPE_INT32 } "
  5487. " extension_range { start:10 end:100 } "
  5488. "}",
  5489. "foo.proto: Foo: NUMBER: Extension ranges are not allowed in "
  5490. "proto3.\n");
  5491. BuildFileWithErrors(
  5492. "name: 'foo.proto' "
  5493. "syntax: 'proto3' "
  5494. "message_type { "
  5495. " name: 'Foo' "
  5496. " nested_type { "
  5497. " name : 'Bar' "
  5498. " field { name:'bar' number:1 label:LABEL_OPTIONAL type:TYPE_INT32 } "
  5499. " extension_range { start:10 end:100 } "
  5500. " } "
  5501. "}",
  5502. "foo.proto: Foo.Bar: NUMBER: Extension ranges are not allowed in "
  5503. "proto3.\n");
  5504. }
  5505. TEST_F(ValidationErrorTest, ValidateProto3MessageSetWireFormat) {
  5506. BuildFileWithErrors(
  5507. "name: 'foo.proto' "
  5508. "syntax: 'proto3' "
  5509. "message_type { "
  5510. " name: 'Foo' "
  5511. " options { message_set_wire_format: true } "
  5512. "}",
  5513. "foo.proto: Foo: NAME: MessageSet is not supported "
  5514. "in proto3.\n");
  5515. }
  5516. TEST_F(ValidationErrorTest, ValidateProto3Enum) {
  5517. BuildFileWithErrors(
  5518. "name: 'foo.proto' "
  5519. "syntax: 'proto3' "
  5520. "enum_type { "
  5521. " name: 'FooEnum' "
  5522. " value { name: 'FOO_FOO' number:1 } "
  5523. "}",
  5524. "foo.proto: FooEnum: NUMBER: The first enum value must be "
  5525. "zero in proto3.\n");
  5526. BuildFileWithErrors(
  5527. "name: 'foo.proto' "
  5528. "syntax: 'proto3' "
  5529. "message_type { "
  5530. " name: 'Foo' "
  5531. " enum_type { "
  5532. " name: 'FooEnum' "
  5533. " value { name: 'FOO_FOO' number:1 } "
  5534. " } "
  5535. "}",
  5536. "foo.proto: Foo.FooEnum: NUMBER: The first enum value must be "
  5537. "zero in proto3.\n");
  5538. // valid case.
  5539. BuildFile(
  5540. "name: 'foo.proto' "
  5541. "syntax: 'proto3' "
  5542. "enum_type { "
  5543. " name: 'FooEnum' "
  5544. " value { name: 'FOO_FOO' number:0 } "
  5545. "}");
  5546. }
  5547. TEST_F(ValidationErrorTest, ValidateProto3Group) {
  5548. BuildFileWithErrors(
  5549. "name: 'foo.proto' "
  5550. "syntax: 'proto3' "
  5551. "message_type { "
  5552. " name: 'Foo' "
  5553. " nested_type { "
  5554. " name: 'FooGroup' "
  5555. " } "
  5556. " field { name:'foo_group' number: 1 label:LABEL_OPTIONAL "
  5557. " type: TYPE_GROUP type_name:'FooGroup' } "
  5558. "}",
  5559. "foo.proto: Foo.foo_group: TYPE: Groups are not supported in proto3 "
  5560. "syntax.\n");
  5561. }
  5562. TEST_F(ValidationErrorTest, ValidateProto3EnumFromProto2) {
  5563. // Define an enum in a proto2 file.
  5564. BuildFile(
  5565. "name: 'foo.proto' "
  5566. "package: 'foo' "
  5567. "syntax: 'proto2' "
  5568. "enum_type { "
  5569. " name: 'FooEnum' "
  5570. " value { name: 'DEFAULT_OPTION' number:0 } "
  5571. "}");
  5572. // Now try to refer to it. (All tests in the fixture use the same pool, so we
  5573. // can refer to the enum above in this definition.)
  5574. BuildFileWithErrors(
  5575. "name: 'bar.proto' "
  5576. "dependency: 'foo.proto' "
  5577. "syntax: 'proto3' "
  5578. "message_type { "
  5579. " name: 'Foo' "
  5580. " field { name:'bar' number:1 label:LABEL_OPTIONAL type:TYPE_ENUM "
  5581. " type_name: 'foo.FooEnum' }"
  5582. "}",
  5583. "bar.proto: Foo.bar: TYPE: Enum type \"foo.FooEnum\" is not a proto3 "
  5584. "enum, but is used in \"Foo\" which is a proto3 message type.\n");
  5585. }
  5586. TEST_F(ValidationErrorTest, ValidateProto3Extension) {
  5587. // Valid for options.
  5588. DescriptorPool pool;
  5589. FileDescriptorProto file_proto;
  5590. // Add "google/protobuf/descriptor.proto".
  5591. FileDescriptorProto::descriptor()->file()->CopyTo(&file_proto);
  5592. ASSERT_TRUE(pool.BuildFile(file_proto) != nullptr);
  5593. // Add "foo.proto":
  5594. // import "google/protobuf/descriptor.proto";
  5595. // extend google.protobuf.FieldOptions {
  5596. // optional int32 option1 = 1000;
  5597. // }
  5598. file_proto.Clear();
  5599. file_proto.set_name("foo.proto");
  5600. file_proto.set_syntax("proto3");
  5601. file_proto.add_dependency("google/protobuf/descriptor.proto");
  5602. AddExtension(&file_proto, "google.protobuf.FieldOptions", "option1", 1000,
  5603. FieldDescriptorProto::LABEL_OPTIONAL,
  5604. FieldDescriptorProto::TYPE_INT32);
  5605. ASSERT_TRUE(pool.BuildFile(file_proto) != nullptr);
  5606. // Copy and change the package of the descriptor.proto
  5607. BuildFile(
  5608. "name: 'google.protobuf.proto' "
  5609. "syntax: 'proto2' "
  5610. "message_type { "
  5611. " name: 'Container' extension_range { start: 1 end: 1000 } "
  5612. "}");
  5613. BuildFileWithErrors(
  5614. "name: 'bar.proto' "
  5615. "syntax: 'proto3' "
  5616. "dependency: 'google.protobuf.proto' "
  5617. "extension { "
  5618. " name: 'bar' number: 1 label: LABEL_OPTIONAL type: TYPE_INT32 "
  5619. " extendee: 'Container' "
  5620. "}",
  5621. "bar.proto: bar: EXTENDEE: Extensions in proto3 are only allowed for "
  5622. "defining options.\n");
  5623. }
  5624. // Test that field names that may conflict in JSON is not allowed by protoc.
  5625. TEST_F(ValidationErrorTest, ValidateProto3JsonName) {
  5626. // The comparison is case-insensitive.
  5627. BuildFileWithErrors(
  5628. "name: 'foo.proto' "
  5629. "syntax: 'proto3' "
  5630. "message_type {"
  5631. " name: 'Foo'"
  5632. " field { name:'name' number:1 label:LABEL_OPTIONAL type:TYPE_INT32 }"
  5633. " field { name:'Name' number:2 label:LABEL_OPTIONAL type:TYPE_INT32 }"
  5634. "}",
  5635. "foo.proto: Foo: NAME: The JSON camel-case name of field \"Name\" "
  5636. "conflicts with field \"name\". This is not allowed in proto3.\n");
  5637. // Underscores are ignored.
  5638. BuildFileWithErrors(
  5639. "name: 'foo.proto' "
  5640. "syntax: 'proto3' "
  5641. "message_type {"
  5642. " name: 'Foo'"
  5643. " field { name:'ab' number:1 label:LABEL_OPTIONAL type:TYPE_INT32 }"
  5644. " field { name:'_a__b_' number:2 label:LABEL_OPTIONAL type:TYPE_INT32 }"
  5645. "}",
  5646. "foo.proto: Foo: NAME: The JSON camel-case name of field \"_a__b_\" "
  5647. "conflicts with field \"ab\". This is not allowed in proto3.\n");
  5648. }
  5649. // ===================================================================
  5650. // DescriptorDatabase
  5651. static void AddToDatabase(SimpleDescriptorDatabase* database,
  5652. const char* file_text) {
  5653. FileDescriptorProto file_proto;
  5654. EXPECT_TRUE(TextFormat::ParseFromString(file_text, &file_proto));
  5655. database->Add(file_proto);
  5656. }
  5657. class DatabaseBackedPoolTest : public testing::Test {
  5658. protected:
  5659. DatabaseBackedPoolTest() {}
  5660. SimpleDescriptorDatabase database_;
  5661. virtual void SetUp() {
  5662. AddToDatabase(
  5663. &database_,
  5664. "name: 'foo.proto' "
  5665. "message_type { name:'Foo' extension_range { start: 1 end: 100 } } "
  5666. "enum_type { name:'TestEnum' value { name:'DUMMY' number:0 } } "
  5667. "service { name:'TestService' } ");
  5668. AddToDatabase(&database_,
  5669. "name: 'bar.proto' "
  5670. "dependency: 'foo.proto' "
  5671. "message_type { name:'Bar' } "
  5672. "extension { name:'foo_ext' extendee: '.Foo' number:5 "
  5673. " label:LABEL_OPTIONAL type:TYPE_INT32 } ");
  5674. // Baz has an undeclared dependency on Foo.
  5675. AddToDatabase(
  5676. &database_,
  5677. "name: 'baz.proto' "
  5678. "message_type { "
  5679. " name:'Baz' "
  5680. " field { name:'foo' number:1 label:LABEL_OPTIONAL type_name:'Foo' } "
  5681. "}");
  5682. }
  5683. // We can't inject a file containing errors into a DescriptorPool, so we
  5684. // need an actual mock DescriptorDatabase to test errors.
  5685. class ErrorDescriptorDatabase : public DescriptorDatabase {
  5686. public:
  5687. ErrorDescriptorDatabase() {}
  5688. ~ErrorDescriptorDatabase() {}
  5689. // implements DescriptorDatabase ---------------------------------
  5690. bool FindFileByName(const std::string& filename,
  5691. FileDescriptorProto* output) {
  5692. // error.proto and error2.proto cyclically import each other.
  5693. if (filename == "error.proto") {
  5694. output->Clear();
  5695. output->set_name("error.proto");
  5696. output->add_dependency("error2.proto");
  5697. return true;
  5698. } else if (filename == "error2.proto") {
  5699. output->Clear();
  5700. output->set_name("error2.proto");
  5701. output->add_dependency("error.proto");
  5702. return true;
  5703. } else {
  5704. return false;
  5705. }
  5706. }
  5707. bool FindFileContainingSymbol(const std::string& symbol_name,
  5708. FileDescriptorProto* output) {
  5709. return false;
  5710. }
  5711. bool FindFileContainingExtension(const std::string& containing_type,
  5712. int field_number,
  5713. FileDescriptorProto* output) {
  5714. return false;
  5715. }
  5716. };
  5717. // A DescriptorDatabase that counts how many times each method has been
  5718. // called and forwards to some other DescriptorDatabase.
  5719. class CallCountingDatabase : public DescriptorDatabase {
  5720. public:
  5721. CallCountingDatabase(DescriptorDatabase* wrapped_db)
  5722. : wrapped_db_(wrapped_db) {
  5723. Clear();
  5724. }
  5725. ~CallCountingDatabase() {}
  5726. DescriptorDatabase* wrapped_db_;
  5727. int call_count_;
  5728. void Clear() { call_count_ = 0; }
  5729. // implements DescriptorDatabase ---------------------------------
  5730. bool FindFileByName(const std::string& filename,
  5731. FileDescriptorProto* output) {
  5732. ++call_count_;
  5733. return wrapped_db_->FindFileByName(filename, output);
  5734. }
  5735. bool FindFileContainingSymbol(const std::string& symbol_name,
  5736. FileDescriptorProto* output) {
  5737. ++call_count_;
  5738. return wrapped_db_->FindFileContainingSymbol(symbol_name, output);
  5739. }
  5740. bool FindFileContainingExtension(const std::string& containing_type,
  5741. int field_number,
  5742. FileDescriptorProto* output) {
  5743. ++call_count_;
  5744. return wrapped_db_->FindFileContainingExtension(containing_type,
  5745. field_number, output);
  5746. }
  5747. };
  5748. // A DescriptorDatabase which falsely always returns foo.proto when searching
  5749. // for any symbol or extension number. This shouldn't cause the
  5750. // DescriptorPool to reload foo.proto if it is already loaded.
  5751. class FalsePositiveDatabase : public DescriptorDatabase {
  5752. public:
  5753. FalsePositiveDatabase(DescriptorDatabase* wrapped_db)
  5754. : wrapped_db_(wrapped_db) {}
  5755. ~FalsePositiveDatabase() {}
  5756. DescriptorDatabase* wrapped_db_;
  5757. // implements DescriptorDatabase ---------------------------------
  5758. bool FindFileByName(const std::string& filename,
  5759. FileDescriptorProto* output) {
  5760. return wrapped_db_->FindFileByName(filename, output);
  5761. }
  5762. bool FindFileContainingSymbol(const std::string& symbol_name,
  5763. FileDescriptorProto* output) {
  5764. return FindFileByName("foo.proto", output);
  5765. }
  5766. bool FindFileContainingExtension(const std::string& containing_type,
  5767. int field_number,
  5768. FileDescriptorProto* output) {
  5769. return FindFileByName("foo.proto", output);
  5770. }
  5771. };
  5772. };
  5773. TEST_F(DatabaseBackedPoolTest, FindFileByName) {
  5774. DescriptorPool pool(&database_);
  5775. const FileDescriptor* foo = pool.FindFileByName("foo.proto");
  5776. ASSERT_TRUE(foo != nullptr);
  5777. EXPECT_EQ("foo.proto", foo->name());
  5778. ASSERT_EQ(1, foo->message_type_count());
  5779. EXPECT_EQ("Foo", foo->message_type(0)->name());
  5780. EXPECT_EQ(foo, pool.FindFileByName("foo.proto"));
  5781. EXPECT_TRUE(pool.FindFileByName("no_such_file.proto") == nullptr);
  5782. }
  5783. TEST_F(DatabaseBackedPoolTest, FindDependencyBeforeDependent) {
  5784. DescriptorPool pool(&database_);
  5785. const FileDescriptor* foo = pool.FindFileByName("foo.proto");
  5786. ASSERT_TRUE(foo != nullptr);
  5787. EXPECT_EQ("foo.proto", foo->name());
  5788. ASSERT_EQ(1, foo->message_type_count());
  5789. EXPECT_EQ("Foo", foo->message_type(0)->name());
  5790. const FileDescriptor* bar = pool.FindFileByName("bar.proto");
  5791. ASSERT_TRUE(bar != nullptr);
  5792. EXPECT_EQ("bar.proto", bar->name());
  5793. ASSERT_EQ(1, bar->message_type_count());
  5794. EXPECT_EQ("Bar", bar->message_type(0)->name());
  5795. ASSERT_EQ(1, bar->dependency_count());
  5796. EXPECT_EQ(foo, bar->dependency(0));
  5797. }
  5798. TEST_F(DatabaseBackedPoolTest, FindDependentBeforeDependency) {
  5799. DescriptorPool pool(&database_);
  5800. const FileDescriptor* bar = pool.FindFileByName("bar.proto");
  5801. ASSERT_TRUE(bar != nullptr);
  5802. EXPECT_EQ("bar.proto", bar->name());
  5803. ASSERT_EQ(1, bar->message_type_count());
  5804. ASSERT_EQ("Bar", bar->message_type(0)->name());
  5805. const FileDescriptor* foo = pool.FindFileByName("foo.proto");
  5806. ASSERT_TRUE(foo != nullptr);
  5807. EXPECT_EQ("foo.proto", foo->name());
  5808. ASSERT_EQ(1, foo->message_type_count());
  5809. ASSERT_EQ("Foo", foo->message_type(0)->name());
  5810. ASSERT_EQ(1, bar->dependency_count());
  5811. EXPECT_EQ(foo, bar->dependency(0));
  5812. }
  5813. TEST_F(DatabaseBackedPoolTest, FindFileContainingSymbol) {
  5814. DescriptorPool pool(&database_);
  5815. const FileDescriptor* file = pool.FindFileContainingSymbol("Foo");
  5816. ASSERT_TRUE(file != nullptr);
  5817. EXPECT_EQ("foo.proto", file->name());
  5818. EXPECT_EQ(file, pool.FindFileByName("foo.proto"));
  5819. EXPECT_TRUE(pool.FindFileContainingSymbol("NoSuchSymbol") == nullptr);
  5820. }
  5821. TEST_F(DatabaseBackedPoolTest, FindMessageTypeByName) {
  5822. DescriptorPool pool(&database_);
  5823. const Descriptor* type = pool.FindMessageTypeByName("Foo");
  5824. ASSERT_TRUE(type != nullptr);
  5825. EXPECT_EQ("Foo", type->name());
  5826. EXPECT_EQ(type->file(), pool.FindFileByName("foo.proto"));
  5827. EXPECT_TRUE(pool.FindMessageTypeByName("NoSuchType") == nullptr);
  5828. }
  5829. TEST_F(DatabaseBackedPoolTest, FindExtensionByNumber) {
  5830. DescriptorPool pool(&database_);
  5831. const Descriptor* foo = pool.FindMessageTypeByName("Foo");
  5832. ASSERT_TRUE(foo != nullptr);
  5833. const FieldDescriptor* extension = pool.FindExtensionByNumber(foo, 5);
  5834. ASSERT_TRUE(extension != nullptr);
  5835. EXPECT_EQ("foo_ext", extension->name());
  5836. EXPECT_EQ(extension->file(), pool.FindFileByName("bar.proto"));
  5837. EXPECT_TRUE(pool.FindExtensionByNumber(foo, 12) == nullptr);
  5838. }
  5839. TEST_F(DatabaseBackedPoolTest, FindAllExtensions) {
  5840. DescriptorPool pool(&database_);
  5841. const Descriptor* foo = pool.FindMessageTypeByName("Foo");
  5842. for (int i = 0; i < 2; ++i) {
  5843. // Repeat the lookup twice, to check that we get consistent
  5844. // results despite the fallback database lookup mutating the pool.
  5845. std::vector<const FieldDescriptor*> extensions;
  5846. pool.FindAllExtensions(foo, &extensions);
  5847. ASSERT_EQ(1, extensions.size());
  5848. EXPECT_EQ(5, extensions[0]->number());
  5849. }
  5850. }
  5851. TEST_F(DatabaseBackedPoolTest, ErrorWithoutErrorCollector) {
  5852. ErrorDescriptorDatabase error_database;
  5853. DescriptorPool pool(&error_database);
  5854. std::vector<std::string> errors;
  5855. {
  5856. ScopedMemoryLog log;
  5857. EXPECT_TRUE(pool.FindFileByName("error.proto") == nullptr);
  5858. errors = log.GetMessages(ERROR);
  5859. }
  5860. EXPECT_FALSE(errors.empty());
  5861. }
  5862. TEST_F(DatabaseBackedPoolTest, ErrorWithErrorCollector) {
  5863. ErrorDescriptorDatabase error_database;
  5864. MockErrorCollector error_collector;
  5865. DescriptorPool pool(&error_database, &error_collector);
  5866. EXPECT_TRUE(pool.FindFileByName("error.proto") == nullptr);
  5867. EXPECT_EQ(
  5868. "error.proto: error2.proto: IMPORT: File recursively imports itself: "
  5869. "error.proto -> error2.proto -> error.proto\n"
  5870. "error2.proto: error.proto: IMPORT: Import \"error.proto\" was not "
  5871. "found or had errors.\n"
  5872. "error.proto: error2.proto: IMPORT: Import \"error2.proto\" was not "
  5873. "found or had errors.\n",
  5874. error_collector.text_);
  5875. }
  5876. TEST_F(DatabaseBackedPoolTest, UndeclaredDependencyOnUnbuiltType) {
  5877. // Check that we find and report undeclared dependencies on types that exist
  5878. // in the descriptor database but that have not not been built yet.
  5879. MockErrorCollector error_collector;
  5880. DescriptorPool pool(&database_, &error_collector);
  5881. EXPECT_TRUE(pool.FindMessageTypeByName("Baz") == nullptr);
  5882. EXPECT_EQ(
  5883. "baz.proto: Baz.foo: TYPE: \"Foo\" seems to be defined in \"foo.proto\", "
  5884. "which is not imported by \"baz.proto\". To use it here, please add "
  5885. "the necessary import.\n",
  5886. error_collector.text_);
  5887. }
  5888. TEST_F(DatabaseBackedPoolTest, RollbackAfterError) {
  5889. // Make sure that all traces of bad types are removed from the pool. This used
  5890. // to be b/4529436, due to the fact that a symbol resolution failure could
  5891. // potentially cause another file to be recursively built, which would trigger
  5892. // a checkpoint _past_ possibly invalid symbols.
  5893. // Baz is defined in the database, but the file is invalid because it is
  5894. // missing a necessary import.
  5895. DescriptorPool pool(&database_);
  5896. EXPECT_TRUE(pool.FindMessageTypeByName("Baz") == nullptr);
  5897. // Make sure that searching again for the file or the type fails.
  5898. EXPECT_TRUE(pool.FindFileByName("baz.proto") == nullptr);
  5899. EXPECT_TRUE(pool.FindMessageTypeByName("Baz") == nullptr);
  5900. }
  5901. TEST_F(DatabaseBackedPoolTest, UnittestProto) {
  5902. // Try to load all of unittest.proto from a DescriptorDatabase. This should
  5903. // thoroughly test all paths through DescriptorBuilder to insure that there
  5904. // are no deadlocking problems when pool_->mutex_ is non-null.
  5905. const FileDescriptor* original_file =
  5906. protobuf_unittest::TestAllTypes::descriptor()->file();
  5907. DescriptorPoolDatabase database(*DescriptorPool::generated_pool());
  5908. DescriptorPool pool(&database);
  5909. const FileDescriptor* file_from_database =
  5910. pool.FindFileByName(original_file->name());
  5911. ASSERT_TRUE(file_from_database != nullptr);
  5912. FileDescriptorProto original_file_proto;
  5913. original_file->CopyTo(&original_file_proto);
  5914. FileDescriptorProto file_from_database_proto;
  5915. file_from_database->CopyTo(&file_from_database_proto);
  5916. EXPECT_EQ(original_file_proto.DebugString(),
  5917. file_from_database_proto.DebugString());
  5918. // Also verify that CopyTo() did not omit any information.
  5919. EXPECT_EQ(original_file->DebugString(), file_from_database->DebugString());
  5920. }
  5921. TEST_F(DatabaseBackedPoolTest, DoesntRetryDbUnnecessarily) {
  5922. // Searching for a child of an existing descriptor should never fall back
  5923. // to the DescriptorDatabase even if it isn't found, because we know all
  5924. // children are already loaded.
  5925. CallCountingDatabase call_counter(&database_);
  5926. DescriptorPool pool(&call_counter);
  5927. const FileDescriptor* file = pool.FindFileByName("foo.proto");
  5928. ASSERT_TRUE(file != nullptr);
  5929. const Descriptor* foo = pool.FindMessageTypeByName("Foo");
  5930. ASSERT_TRUE(foo != nullptr);
  5931. const EnumDescriptor* test_enum = pool.FindEnumTypeByName("TestEnum");
  5932. ASSERT_TRUE(test_enum != nullptr);
  5933. const ServiceDescriptor* test_service = pool.FindServiceByName("TestService");
  5934. ASSERT_TRUE(test_service != nullptr);
  5935. EXPECT_NE(0, call_counter.call_count_);
  5936. call_counter.Clear();
  5937. EXPECT_TRUE(foo->FindFieldByName("no_such_field") == nullptr);
  5938. EXPECT_TRUE(foo->FindExtensionByName("no_such_extension") == nullptr);
  5939. EXPECT_TRUE(foo->FindNestedTypeByName("NoSuchMessageType") == nullptr);
  5940. EXPECT_TRUE(foo->FindEnumTypeByName("NoSuchEnumType") == nullptr);
  5941. EXPECT_TRUE(foo->FindEnumValueByName("NO_SUCH_VALUE") == nullptr);
  5942. EXPECT_TRUE(test_enum->FindValueByName("NO_SUCH_VALUE") == nullptr);
  5943. EXPECT_TRUE(test_service->FindMethodByName("NoSuchMethod") == nullptr);
  5944. EXPECT_TRUE(file->FindMessageTypeByName("NoSuchMessageType") == nullptr);
  5945. EXPECT_TRUE(file->FindEnumTypeByName("NoSuchEnumType") == nullptr);
  5946. EXPECT_TRUE(file->FindEnumValueByName("NO_SUCH_VALUE") == nullptr);
  5947. EXPECT_TRUE(file->FindServiceByName("NO_SUCH_VALUE") == nullptr);
  5948. EXPECT_TRUE(file->FindExtensionByName("no_such_extension") == nullptr);
  5949. EXPECT_TRUE(pool.FindFileContainingSymbol("Foo.no.such.field") == nullptr);
  5950. EXPECT_TRUE(pool.FindFileContainingSymbol("Foo.no_such_field") == nullptr);
  5951. EXPECT_TRUE(pool.FindMessageTypeByName("Foo.NoSuchMessageType") == nullptr);
  5952. EXPECT_TRUE(pool.FindFieldByName("Foo.no_such_field") == nullptr);
  5953. EXPECT_TRUE(pool.FindExtensionByName("Foo.no_such_extension") == nullptr);
  5954. EXPECT_TRUE(pool.FindEnumTypeByName("Foo.NoSuchEnumType") == nullptr);
  5955. EXPECT_TRUE(pool.FindEnumValueByName("Foo.NO_SUCH_VALUE") == nullptr);
  5956. EXPECT_TRUE(pool.FindMethodByName("TestService.NoSuchMethod") == nullptr);
  5957. EXPECT_EQ(0, call_counter.call_count_);
  5958. }
  5959. TEST_F(DatabaseBackedPoolTest, DoesntReloadFilesUncesessarily) {
  5960. // If FindFileContainingSymbol() or FindFileContainingExtension() return a
  5961. // file that is already in the DescriptorPool, it should not attempt to
  5962. // reload the file.
  5963. FalsePositiveDatabase false_positive_database(&database_);
  5964. MockErrorCollector error_collector;
  5965. DescriptorPool pool(&false_positive_database, &error_collector);
  5966. // First make sure foo.proto is loaded.
  5967. const Descriptor* foo = pool.FindMessageTypeByName("Foo");
  5968. ASSERT_TRUE(foo != nullptr);
  5969. // Try inducing false positives.
  5970. EXPECT_TRUE(pool.FindMessageTypeByName("NoSuchSymbol") == nullptr);
  5971. EXPECT_TRUE(pool.FindExtensionByNumber(foo, 22) == nullptr);
  5972. // No errors should have been reported. (If foo.proto was incorrectly
  5973. // loaded multiple times, errors would have been reported.)
  5974. EXPECT_EQ("", error_collector.text_);
  5975. }
  5976. // DescriptorDatabase that attempts to induce exponentially-bad performance
  5977. // in DescriptorPool. For every positive N, the database contains a file
  5978. // fileN.proto, which defines a message MessageN, which contains fields of
  5979. // type MessageK for all K in [0,N). Message0 is not defined anywhere
  5980. // (file0.proto exists, but is empty), so every other file and message type
  5981. // will fail to build.
  5982. //
  5983. // If the DescriptorPool is not careful to memoize errors, an attempt to
  5984. // build a descriptor for MessageN can require O(2^N) time.
  5985. class ExponentialErrorDatabase : public DescriptorDatabase {
  5986. public:
  5987. ExponentialErrorDatabase() {}
  5988. ~ExponentialErrorDatabase() {}
  5989. // implements DescriptorDatabase ---------------------------------
  5990. bool FindFileByName(const std::string& filename,
  5991. FileDescriptorProto* output) {
  5992. int file_num = -1;
  5993. FullMatch(filename, "file", ".proto", &file_num);
  5994. if (file_num > -1) {
  5995. return PopulateFile(file_num, output);
  5996. } else {
  5997. return false;
  5998. }
  5999. }
  6000. bool FindFileContainingSymbol(const std::string& symbol_name,
  6001. FileDescriptorProto* output) {
  6002. int file_num = -1;
  6003. FullMatch(symbol_name, "Message", "", &file_num);
  6004. if (file_num > 0) {
  6005. return PopulateFile(file_num, output);
  6006. } else {
  6007. return false;
  6008. }
  6009. }
  6010. bool FindFileContainingExtension(const std::string& containing_type,
  6011. int field_number,
  6012. FileDescriptorProto* output) {
  6013. return false;
  6014. }
  6015. private:
  6016. void FullMatch(const std::string& name, const std::string& begin_with,
  6017. const std::string& end_with, int* file_num) {
  6018. int begin_size = begin_with.size();
  6019. int end_size = end_with.size();
  6020. if (name.substr(0, begin_size) != begin_with ||
  6021. name.substr(name.size() - end_size, end_size) != end_with) {
  6022. return;
  6023. }
  6024. safe_strto32(
  6025. name.substr(begin_size, name.size() - end_size - begin_size), file_num);
  6026. }
  6027. bool PopulateFile(int file_num, FileDescriptorProto* output) {
  6028. using strings::Substitute;
  6029. GOOGLE_CHECK_GE(file_num, 0);
  6030. output->Clear();
  6031. output->set_name(Substitute("file$0.proto", file_num));
  6032. // file0.proto doesn't define Message0
  6033. if (file_num > 0) {
  6034. DescriptorProto* message = output->add_message_type();
  6035. message->set_name(Substitute("Message$0", file_num));
  6036. for (int i = 0; i < file_num; ++i) {
  6037. output->add_dependency(Substitute("file$0.proto", i));
  6038. FieldDescriptorProto* field = message->add_field();
  6039. field->set_name(Substitute("field$0", i));
  6040. field->set_number(i);
  6041. field->set_label(FieldDescriptorProto::LABEL_OPTIONAL);
  6042. field->set_type(FieldDescriptorProto::TYPE_MESSAGE);
  6043. field->set_type_name(Substitute("Message$0", i));
  6044. }
  6045. }
  6046. return true;
  6047. }
  6048. };
  6049. TEST_F(DatabaseBackedPoolTest, DoesntReloadKnownBadFiles) {
  6050. ExponentialErrorDatabase error_database;
  6051. DescriptorPool pool(&error_database);
  6052. GOOGLE_LOG(INFO) << "A timeout in this test probably indicates a real bug.";
  6053. EXPECT_TRUE(pool.FindFileByName("file40.proto") == nullptr);
  6054. EXPECT_TRUE(pool.FindMessageTypeByName("Message40") == nullptr);
  6055. }
  6056. TEST_F(DatabaseBackedPoolTest, DoesntFallbackOnWrongType) {
  6057. // If a lookup finds a symbol of the wrong type (e.g. we pass a type name
  6058. // to FindFieldByName()), we should fail fast, without checking the fallback
  6059. // database.
  6060. CallCountingDatabase call_counter(&database_);
  6061. DescriptorPool pool(&call_counter);
  6062. const FileDescriptor* file = pool.FindFileByName("foo.proto");
  6063. ASSERT_TRUE(file != nullptr);
  6064. const Descriptor* foo = pool.FindMessageTypeByName("Foo");
  6065. ASSERT_TRUE(foo != nullptr);
  6066. const EnumDescriptor* test_enum = pool.FindEnumTypeByName("TestEnum");
  6067. ASSERT_TRUE(test_enum != nullptr);
  6068. EXPECT_NE(0, call_counter.call_count_);
  6069. call_counter.Clear();
  6070. EXPECT_TRUE(pool.FindMessageTypeByName("TestEnum") == nullptr);
  6071. EXPECT_TRUE(pool.FindFieldByName("Foo") == nullptr);
  6072. EXPECT_TRUE(pool.FindExtensionByName("Foo") == nullptr);
  6073. EXPECT_TRUE(pool.FindEnumTypeByName("Foo") == nullptr);
  6074. EXPECT_TRUE(pool.FindEnumValueByName("Foo") == nullptr);
  6075. EXPECT_TRUE(pool.FindServiceByName("Foo") == nullptr);
  6076. EXPECT_TRUE(pool.FindMethodByName("Foo") == nullptr);
  6077. EXPECT_EQ(0, call_counter.call_count_);
  6078. }
  6079. // ===================================================================
  6080. class AbortingErrorCollector : public DescriptorPool::ErrorCollector {
  6081. public:
  6082. AbortingErrorCollector() {}
  6083. virtual void AddError(const std::string& filename,
  6084. const std::string& element_name, const Message* message,
  6085. ErrorLocation location,
  6086. const std::string& error_message) {
  6087. GOOGLE_LOG(FATAL) << "AddError() called unexpectedly: " << filename << " ["
  6088. << element_name << "]: " << error_message;
  6089. }
  6090. private:
  6091. GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(AbortingErrorCollector);
  6092. };
  6093. // A source tree containing only one file.
  6094. class SingletonSourceTree : public compiler::SourceTree {
  6095. public:
  6096. SingletonSourceTree(const std::string& filename, const std::string& contents)
  6097. : filename_(filename), contents_(contents) {}
  6098. virtual io::ZeroCopyInputStream* Open(const std::string& filename) {
  6099. return filename == filename_
  6100. ? new io::ArrayInputStream(contents_.data(), contents_.size())
  6101. : nullptr;
  6102. }
  6103. private:
  6104. const std::string filename_;
  6105. const std::string contents_;
  6106. GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(SingletonSourceTree);
  6107. };
  6108. const char* const kSourceLocationTestInput =
  6109. "syntax = \"proto2\";\n"
  6110. "option java_package = \"com.foo.bar\";\n"
  6111. "option (test_file_opt) = \"foobar\";\n"
  6112. "message A {\n"
  6113. " option (test_msg_opt) = \"foobar\";\n"
  6114. " optional int32 a = 1 [deprecated = true];\n"
  6115. " message B {\n"
  6116. " required double b = 1 [(test_field_opt) = \"foobar\"];\n"
  6117. " }\n"
  6118. " oneof c {\n"
  6119. " option (test_oneof_opt) = \"foobar\";\n"
  6120. " string d = 2;\n"
  6121. " string e = 3;\n"
  6122. " string f = 4;\n"
  6123. " }\n"
  6124. "}\n"
  6125. "enum Indecision {\n"
  6126. " option (test_enum_opt) = 21;\n"
  6127. " option (test_enum_opt) = 42;\n"
  6128. " option (test_enum_opt) = 63;\n"
  6129. " YES = 1 [(test_enumval_opt).a = 100];\n"
  6130. " NO = 2 [(test_enumval_opt) = {a:200}];\n"
  6131. " MAYBE = 3;\n"
  6132. "}\n"
  6133. "service S {\n"
  6134. " option (test_svc_opt) = {a:100};\n"
  6135. " option (test_svc_opt) = {a:200};\n"
  6136. " option (test_svc_opt) = {a:300};\n"
  6137. " rpc Method(A) returns (A.B);\n"
  6138. // Put an empty line here to make the source location range match.
  6139. "\n"
  6140. " rpc OtherMethod(A) returns (A) {\n"
  6141. " option deprecated = true;\n"
  6142. " option (test_method_opt) = \"foobar\";\n"
  6143. " }\n"
  6144. "}\n"
  6145. "message MessageWithExtensions {\n"
  6146. " extensions 1000 to 2000, 2001 to max [(test_ext_opt) = \"foobar\"];\n"
  6147. "}\n"
  6148. "extend MessageWithExtensions {\n"
  6149. " repeated int32 int32_extension = 1001 [packed=true];\n"
  6150. "}\n"
  6151. "message C {\n"
  6152. " extend MessageWithExtensions {\n"
  6153. " optional C message_extension = 1002;\n"
  6154. " }\n"
  6155. "}\n"
  6156. "import \"google/protobuf/descriptor.proto\";\n"
  6157. "extend google.protobuf.FileOptions {\n"
  6158. " optional string test_file_opt = 10101;\n"
  6159. "}\n"
  6160. "extend google.protobuf.MessageOptions {\n"
  6161. " optional string test_msg_opt = 10101;\n"
  6162. "}\n"
  6163. "extend google.protobuf.FieldOptions {\n"
  6164. " optional string test_field_opt = 10101;\n"
  6165. "}\n"
  6166. "extend google.protobuf.EnumOptions {\n"
  6167. " repeated int32 test_enum_opt = 10101;\n"
  6168. "}\n"
  6169. "extend google.protobuf.EnumValueOptions {\n"
  6170. " optional A test_enumval_opt = 10101;\n"
  6171. "}\n"
  6172. "extend google.protobuf.ServiceOptions {\n"
  6173. " repeated A test_svc_opt = 10101;\n"
  6174. "}\n"
  6175. "extend google.protobuf.MethodOptions {\n"
  6176. " optional string test_method_opt = 10101;\n"
  6177. "}\n"
  6178. "extend google.protobuf.OneofOptions {\n"
  6179. " optional string test_oneof_opt = 10101;\n"
  6180. "}\n"
  6181. "extend google.protobuf.ExtensionRangeOptions {\n"
  6182. " optional string test_ext_opt = 10101;\n"
  6183. "}\n";
  6184. class SourceLocationTest : public testing::Test {
  6185. public:
  6186. SourceLocationTest()
  6187. : source_tree_("/test/test.proto", kSourceLocationTestInput),
  6188. simple_db_(),
  6189. source_tree_db_(&source_tree_),
  6190. merged_db_(&simple_db_, &source_tree_db_),
  6191. pool_(&merged_db_, &collector_) {
  6192. // we need descriptor.proto to be accessible by the pool
  6193. // since our test file imports it
  6194. FileDescriptorProto::descriptor()->file()->CopyTo(&file_proto_);
  6195. simple_db_.Add(file_proto_);
  6196. }
  6197. static std::string PrintSourceLocation(const SourceLocation& loc) {
  6198. return strings::Substitute("$0:$1-$2:$3", 1 + loc.start_line,
  6199. 1 + loc.start_column, 1 + loc.end_line,
  6200. 1 + loc.end_column);
  6201. }
  6202. private:
  6203. FileDescriptorProto file_proto_;
  6204. AbortingErrorCollector collector_;
  6205. SingletonSourceTree source_tree_;
  6206. SimpleDescriptorDatabase simple_db_; // contains descriptor.proto
  6207. compiler::SourceTreeDescriptorDatabase source_tree_db_; // loads test.proto
  6208. MergedDescriptorDatabase merged_db_; // combines above two dbs
  6209. protected:
  6210. DescriptorPool pool_;
  6211. // tag number of all custom options in above test file
  6212. static const int kCustomOptionFieldNumber = 10101;
  6213. // tag number of field "a" in message type "A" in above test file
  6214. static const int kAFieldNumber = 1;
  6215. };
  6216. // TODO(adonovan): implement support for option fields and for
  6217. // subparts of declarations.
  6218. TEST_F(SourceLocationTest, GetSourceLocation) {
  6219. SourceLocation loc;
  6220. const FileDescriptor* file_desc =
  6221. GOOGLE_CHECK_NOTNULL(pool_.FindFileByName("/test/test.proto"));
  6222. const Descriptor* a_desc = file_desc->FindMessageTypeByName("A");
  6223. EXPECT_TRUE(a_desc->GetSourceLocation(&loc));
  6224. EXPECT_EQ("4:1-16:2", PrintSourceLocation(loc));
  6225. const Descriptor* a_b_desc = a_desc->FindNestedTypeByName("B");
  6226. EXPECT_TRUE(a_b_desc->GetSourceLocation(&loc));
  6227. EXPECT_EQ("7:3-9:4", PrintSourceLocation(loc));
  6228. const EnumDescriptor* e_desc = file_desc->FindEnumTypeByName("Indecision");
  6229. EXPECT_TRUE(e_desc->GetSourceLocation(&loc));
  6230. EXPECT_EQ("17:1-24:2", PrintSourceLocation(loc));
  6231. const EnumValueDescriptor* yes_desc = e_desc->FindValueByName("YES");
  6232. EXPECT_TRUE(yes_desc->GetSourceLocation(&loc));
  6233. EXPECT_EQ("21:3-21:42", PrintSourceLocation(loc));
  6234. const ServiceDescriptor* s_desc = file_desc->FindServiceByName("S");
  6235. EXPECT_TRUE(s_desc->GetSourceLocation(&loc));
  6236. EXPECT_EQ("25:1-35:2", PrintSourceLocation(loc));
  6237. const MethodDescriptor* m_desc = s_desc->FindMethodByName("Method");
  6238. EXPECT_TRUE(m_desc->GetSourceLocation(&loc));
  6239. EXPECT_EQ("29:3-29:31", PrintSourceLocation(loc));
  6240. }
  6241. TEST_F(SourceLocationTest, ExtensionSourceLocation) {
  6242. SourceLocation loc;
  6243. const FileDescriptor* file_desc =
  6244. GOOGLE_CHECK_NOTNULL(pool_.FindFileByName("/test/test.proto"));
  6245. const FieldDescriptor* int32_extension_desc =
  6246. file_desc->FindExtensionByName("int32_extension");
  6247. EXPECT_TRUE(int32_extension_desc->GetSourceLocation(&loc));
  6248. EXPECT_EQ("40:3-40:55", PrintSourceLocation(loc));
  6249. const Descriptor* c_desc = file_desc->FindMessageTypeByName("C");
  6250. EXPECT_TRUE(c_desc->GetSourceLocation(&loc));
  6251. EXPECT_EQ("42:1-46:2", PrintSourceLocation(loc));
  6252. const FieldDescriptor* message_extension_desc =
  6253. c_desc->FindExtensionByName("message_extension");
  6254. EXPECT_TRUE(message_extension_desc->GetSourceLocation(&loc));
  6255. EXPECT_EQ("44:5-44:41", PrintSourceLocation(loc));
  6256. }
  6257. TEST_F(SourceLocationTest, InterpretedOptionSourceLocation) {
  6258. // This one's a doozy. It checks every kind of option, including
  6259. // extension range options.
  6260. // We are verifying that the file's source info contains correct
  6261. // info for interpreted options and that it does *not* contain
  6262. // any info for corresponding uninterpreted option path.
  6263. SourceLocation loc;
  6264. const FileDescriptor* file_desc =
  6265. GOOGLE_CHECK_NOTNULL(pool_.FindFileByName("/test/test.proto"));
  6266. // File options
  6267. {
  6268. int path[] = {FileDescriptorProto::kOptionsFieldNumber,
  6269. FileOptions::kJavaPackageFieldNumber};
  6270. int unint[] = {FileDescriptorProto::kOptionsFieldNumber,
  6271. FileOptions::kUninterpretedOptionFieldNumber, 0};
  6272. std::vector<int> vpath(path, path + 2);
  6273. EXPECT_TRUE(file_desc->GetSourceLocation(vpath, &loc));
  6274. EXPECT_EQ("2:1-2:37", PrintSourceLocation(loc));
  6275. std::vector<int> vunint(unint, unint + 3);
  6276. EXPECT_FALSE(file_desc->GetSourceLocation(vunint, &loc));
  6277. }
  6278. {
  6279. int path[] = {FileDescriptorProto::kOptionsFieldNumber,
  6280. kCustomOptionFieldNumber};
  6281. int unint[] = {FileDescriptorProto::kOptionsFieldNumber,
  6282. FileOptions::kUninterpretedOptionFieldNumber, 1};
  6283. std::vector<int> vpath(path, path + 2);
  6284. EXPECT_TRUE(file_desc->GetSourceLocation(vpath, &loc));
  6285. EXPECT_EQ("3:1-3:35", PrintSourceLocation(loc));
  6286. std::vector<int> vunint(unint, unint + 3);
  6287. EXPECT_FALSE(file_desc->GetSourceLocation(vunint, &loc));
  6288. }
  6289. // Message option
  6290. {
  6291. int path[] = {FileDescriptorProto::kMessageTypeFieldNumber, 0,
  6292. DescriptorProto::kOptionsFieldNumber,
  6293. kCustomOptionFieldNumber};
  6294. int unint[] = {FileDescriptorProto::kMessageTypeFieldNumber, 0,
  6295. DescriptorProto::kOptionsFieldNumber,
  6296. MessageOptions::kUninterpretedOptionFieldNumber, 0};
  6297. std::vector<int> vpath(path, path + 4);
  6298. EXPECT_TRUE(file_desc->GetSourceLocation(vpath, &loc));
  6299. EXPECT_EQ("5:3-5:36", PrintSourceLocation(loc));
  6300. std::vector<int> vunint(unint, unint + 5);
  6301. EXPECT_FALSE(file_desc->GetSourceLocation(vunint, &loc));
  6302. }
  6303. // Field option
  6304. {
  6305. int path[] = {FileDescriptorProto::kMessageTypeFieldNumber,
  6306. 0,
  6307. DescriptorProto::kFieldFieldNumber,
  6308. 0,
  6309. FieldDescriptorProto::kOptionsFieldNumber,
  6310. FieldOptions::kDeprecatedFieldNumber};
  6311. int unint[] = {FileDescriptorProto::kMessageTypeFieldNumber,
  6312. 0,
  6313. DescriptorProto::kFieldFieldNumber,
  6314. 0,
  6315. FieldDescriptorProto::kOptionsFieldNumber,
  6316. FieldOptions::kUninterpretedOptionFieldNumber,
  6317. 0};
  6318. std::vector<int> vpath(path, path + 6);
  6319. EXPECT_TRUE(file_desc->GetSourceLocation(vpath, &loc));
  6320. EXPECT_EQ("6:25-6:42", PrintSourceLocation(loc));
  6321. std::vector<int> vunint(unint, unint + 7);
  6322. EXPECT_FALSE(file_desc->GetSourceLocation(vunint, &loc));
  6323. }
  6324. // Nested message option
  6325. {
  6326. int path[] = {
  6327. FileDescriptorProto::kMessageTypeFieldNumber, 0,
  6328. DescriptorProto::kNestedTypeFieldNumber, 0,
  6329. DescriptorProto::kFieldFieldNumber, 0,
  6330. FieldDescriptorProto::kOptionsFieldNumber, kCustomOptionFieldNumber};
  6331. int unint[] = {FileDescriptorProto::kMessageTypeFieldNumber,
  6332. 0,
  6333. DescriptorProto::kNestedTypeFieldNumber,
  6334. 0,
  6335. DescriptorProto::kFieldFieldNumber,
  6336. 0,
  6337. FieldDescriptorProto::kOptionsFieldNumber,
  6338. FieldOptions::kUninterpretedOptionFieldNumber,
  6339. 0};
  6340. std::vector<int> vpath(path, path + 8);
  6341. EXPECT_TRUE(file_desc->GetSourceLocation(vpath, &loc));
  6342. EXPECT_EQ("8:28-8:55", PrintSourceLocation(loc));
  6343. std::vector<int> vunint(unint, unint + 9);
  6344. EXPECT_FALSE(file_desc->GetSourceLocation(vunint, &loc));
  6345. }
  6346. // One-of option
  6347. {
  6348. int path[] = {
  6349. FileDescriptorProto::kMessageTypeFieldNumber, 0,
  6350. DescriptorProto::kOneofDeclFieldNumber, 0,
  6351. OneofDescriptorProto::kOptionsFieldNumber, kCustomOptionFieldNumber};
  6352. int unint[] = {FileDescriptorProto::kMessageTypeFieldNumber,
  6353. 0,
  6354. DescriptorProto::kOneofDeclFieldNumber,
  6355. 0,
  6356. OneofDescriptorProto::kOptionsFieldNumber,
  6357. OneofOptions::kUninterpretedOptionFieldNumber,
  6358. 0};
  6359. std::vector<int> vpath(path, path + 6);
  6360. EXPECT_TRUE(file_desc->GetSourceLocation(vpath, &loc));
  6361. EXPECT_EQ("11:5-11:40", PrintSourceLocation(loc));
  6362. std::vector<int> vunint(unint, unint + 7);
  6363. EXPECT_FALSE(file_desc->GetSourceLocation(vunint, &loc));
  6364. }
  6365. // Enum option, repeated options
  6366. {
  6367. int path[] = {FileDescriptorProto::kEnumTypeFieldNumber, 0,
  6368. EnumDescriptorProto::kOptionsFieldNumber,
  6369. kCustomOptionFieldNumber, 0};
  6370. int unint[] = {FileDescriptorProto::kEnumTypeFieldNumber, 0,
  6371. EnumDescriptorProto::kOptionsFieldNumber,
  6372. EnumOptions::kUninterpretedOptionFieldNumber, 0};
  6373. std::vector<int> vpath(path, path + 5);
  6374. EXPECT_TRUE(file_desc->GetSourceLocation(vpath, &loc));
  6375. EXPECT_EQ("18:3-18:31", PrintSourceLocation(loc));
  6376. std::vector<int> vunint(unint, unint + 5);
  6377. EXPECT_FALSE(file_desc->GetSourceLocation(vunint, &loc));
  6378. }
  6379. {
  6380. int path[] = {FileDescriptorProto::kEnumTypeFieldNumber, 0,
  6381. EnumDescriptorProto::kOptionsFieldNumber,
  6382. kCustomOptionFieldNumber, 1};
  6383. int unint[] = {FileDescriptorProto::kEnumTypeFieldNumber, 0,
  6384. EnumDescriptorProto::kOptionsFieldNumber,
  6385. EnumOptions::kUninterpretedOptionFieldNumber, 1};
  6386. std::vector<int> vpath(path, path + 5);
  6387. EXPECT_TRUE(file_desc->GetSourceLocation(vpath, &loc));
  6388. EXPECT_EQ("19:3-19:31", PrintSourceLocation(loc));
  6389. std::vector<int> vunint(unint, unint + 5);
  6390. EXPECT_FALSE(file_desc->GetSourceLocation(vunint, &loc));
  6391. }
  6392. {
  6393. int path[] = {FileDescriptorProto::kEnumTypeFieldNumber, 0,
  6394. EnumDescriptorProto::kOptionsFieldNumber,
  6395. kCustomOptionFieldNumber, 2};
  6396. int unint[] = {FileDescriptorProto::kEnumTypeFieldNumber, 0,
  6397. EnumDescriptorProto::kOptionsFieldNumber,
  6398. OneofOptions::kUninterpretedOptionFieldNumber, 2};
  6399. std::vector<int> vpath(path, path + 5);
  6400. EXPECT_TRUE(file_desc->GetSourceLocation(vpath, &loc));
  6401. EXPECT_EQ("20:3-20:31", PrintSourceLocation(loc));
  6402. std::vector<int> vunint(unint, unint + 5);
  6403. EXPECT_FALSE(file_desc->GetSourceLocation(vunint, &loc));
  6404. }
  6405. // Enum value options
  6406. {
  6407. // option w/ message type that directly sets field
  6408. int path[] = {FileDescriptorProto::kEnumTypeFieldNumber,
  6409. 0,
  6410. EnumDescriptorProto::kValueFieldNumber,
  6411. 0,
  6412. EnumValueDescriptorProto::kOptionsFieldNumber,
  6413. kCustomOptionFieldNumber,
  6414. kAFieldNumber};
  6415. int unint[] = {FileDescriptorProto::kEnumTypeFieldNumber,
  6416. 0,
  6417. EnumDescriptorProto::kValueFieldNumber,
  6418. 0,
  6419. EnumValueDescriptorProto::kOptionsFieldNumber,
  6420. EnumValueOptions::kUninterpretedOptionFieldNumber,
  6421. 0};
  6422. std::vector<int> vpath(path, path + 7);
  6423. EXPECT_TRUE(file_desc->GetSourceLocation(vpath, &loc));
  6424. EXPECT_EQ("21:14-21:40", PrintSourceLocation(loc));
  6425. std::vector<int> vunint(unint, unint + 7);
  6426. EXPECT_FALSE(file_desc->GetSourceLocation(vunint, &loc));
  6427. }
  6428. {
  6429. int path[] = {FileDescriptorProto::kEnumTypeFieldNumber,
  6430. 0,
  6431. EnumDescriptorProto::kValueFieldNumber,
  6432. 1,
  6433. EnumValueDescriptorProto::kOptionsFieldNumber,
  6434. kCustomOptionFieldNumber};
  6435. int unint[] = {FileDescriptorProto::kEnumTypeFieldNumber,
  6436. 0,
  6437. EnumDescriptorProto::kValueFieldNumber,
  6438. 1,
  6439. EnumValueDescriptorProto::kOptionsFieldNumber,
  6440. EnumValueOptions::kUninterpretedOptionFieldNumber,
  6441. 0};
  6442. std::vector<int> vpath(path, path + 6);
  6443. EXPECT_TRUE(file_desc->GetSourceLocation(vpath, &loc));
  6444. EXPECT_EQ("22:14-22:42", PrintSourceLocation(loc));
  6445. std::vector<int> vunint(unint, unint + 7);
  6446. EXPECT_FALSE(file_desc->GetSourceLocation(vunint, &loc));
  6447. }
  6448. // Service option, repeated options
  6449. {
  6450. int path[] = {FileDescriptorProto::kServiceFieldNumber, 0,
  6451. ServiceDescriptorProto::kOptionsFieldNumber,
  6452. kCustomOptionFieldNumber, 0};
  6453. int unint[] = {FileDescriptorProto::kServiceFieldNumber, 0,
  6454. ServiceDescriptorProto::kOptionsFieldNumber,
  6455. ServiceOptions::kUninterpretedOptionFieldNumber, 0};
  6456. std::vector<int> vpath(path, path + 5);
  6457. EXPECT_TRUE(file_desc->GetSourceLocation(vpath, &loc));
  6458. EXPECT_EQ("26:3-26:35", PrintSourceLocation(loc));
  6459. std::vector<int> vunint(unint, unint + 5);
  6460. EXPECT_FALSE(file_desc->GetSourceLocation(vunint, &loc));
  6461. }
  6462. {
  6463. int path[] = {FileDescriptorProto::kServiceFieldNumber, 0,
  6464. ServiceDescriptorProto::kOptionsFieldNumber,
  6465. kCustomOptionFieldNumber, 1};
  6466. int unint[] = {FileDescriptorProto::kServiceFieldNumber, 0,
  6467. ServiceDescriptorProto::kOptionsFieldNumber,
  6468. ServiceOptions::kUninterpretedOptionFieldNumber, 1};
  6469. std::vector<int> vpath(path, path + 5);
  6470. EXPECT_TRUE(file_desc->GetSourceLocation(vpath, &loc));
  6471. EXPECT_EQ("27:3-27:35", PrintSourceLocation(loc));
  6472. std::vector<int> vunint(unint, unint + 5);
  6473. EXPECT_FALSE(file_desc->GetSourceLocation(vunint, &loc));
  6474. }
  6475. {
  6476. int path[] = {FileDescriptorProto::kServiceFieldNumber, 0,
  6477. ServiceDescriptorProto::kOptionsFieldNumber,
  6478. kCustomOptionFieldNumber, 2};
  6479. int unint[] = {FileDescriptorProto::kServiceFieldNumber, 0,
  6480. ServiceDescriptorProto::kOptionsFieldNumber,
  6481. ServiceOptions::kUninterpretedOptionFieldNumber, 2};
  6482. std::vector<int> vpath(path, path + 5);
  6483. EXPECT_TRUE(file_desc->GetSourceLocation(vpath, &loc));
  6484. EXPECT_EQ("28:3-28:35", PrintSourceLocation(loc));
  6485. std::vector<int> vunint(unint, unint + 5);
  6486. EXPECT_FALSE(file_desc->GetSourceLocation(vunint, &loc));
  6487. }
  6488. // Method options
  6489. {
  6490. int path[] = {FileDescriptorProto::kServiceFieldNumber,
  6491. 0,
  6492. ServiceDescriptorProto::kMethodFieldNumber,
  6493. 1,
  6494. MethodDescriptorProto::kOptionsFieldNumber,
  6495. MethodOptions::kDeprecatedFieldNumber};
  6496. int unint[] = {FileDescriptorProto::kServiceFieldNumber,
  6497. 0,
  6498. ServiceDescriptorProto::kMethodFieldNumber,
  6499. 1,
  6500. MethodDescriptorProto::kOptionsFieldNumber,
  6501. MethodOptions::kUninterpretedOptionFieldNumber,
  6502. 0};
  6503. std::vector<int> vpath(path, path + 6);
  6504. EXPECT_TRUE(file_desc->GetSourceLocation(vpath, &loc));
  6505. EXPECT_EQ("32:5-32:30", PrintSourceLocation(loc));
  6506. std::vector<int> vunint(unint, unint + 7);
  6507. EXPECT_FALSE(file_desc->GetSourceLocation(vunint, &loc));
  6508. }
  6509. {
  6510. int path[] = {
  6511. FileDescriptorProto::kServiceFieldNumber, 0,
  6512. ServiceDescriptorProto::kMethodFieldNumber, 1,
  6513. MethodDescriptorProto::kOptionsFieldNumber, kCustomOptionFieldNumber};
  6514. int unint[] = {FileDescriptorProto::kServiceFieldNumber,
  6515. 0,
  6516. ServiceDescriptorProto::kMethodFieldNumber,
  6517. 1,
  6518. MethodDescriptorProto::kOptionsFieldNumber,
  6519. MethodOptions::kUninterpretedOptionFieldNumber,
  6520. 1};
  6521. std::vector<int> vpath(path, path + 6);
  6522. EXPECT_TRUE(file_desc->GetSourceLocation(vpath, &loc));
  6523. EXPECT_EQ("33:5-33:41", PrintSourceLocation(loc));
  6524. std::vector<int> vunint(unint, unint + 7);
  6525. EXPECT_FALSE(file_desc->GetSourceLocation(vunint, &loc));
  6526. }
  6527. // Extension range options
  6528. {
  6529. int path[] = {FileDescriptorProto::kMessageTypeFieldNumber, 1,
  6530. DescriptorProto::kExtensionRangeFieldNumber, 0,
  6531. DescriptorProto_ExtensionRange::kOptionsFieldNumber};
  6532. std::vector<int> vpath(path, path + 5);
  6533. EXPECT_TRUE(file_desc->GetSourceLocation(vpath, &loc));
  6534. EXPECT_EQ("37:40-37:67", PrintSourceLocation(loc));
  6535. }
  6536. {
  6537. int path[] = {FileDescriptorProto::kMessageTypeFieldNumber,
  6538. 1,
  6539. DescriptorProto::kExtensionRangeFieldNumber,
  6540. 0,
  6541. DescriptorProto_ExtensionRange::kOptionsFieldNumber,
  6542. kCustomOptionFieldNumber};
  6543. int unint[] = {FileDescriptorProto::kMessageTypeFieldNumber,
  6544. 1,
  6545. DescriptorProto::kExtensionRangeFieldNumber,
  6546. 0,
  6547. DescriptorProto_ExtensionRange::kOptionsFieldNumber,
  6548. ExtensionRangeOptions::kUninterpretedOptionFieldNumber,
  6549. 0};
  6550. std::vector<int> vpath(path, path + 6);
  6551. EXPECT_TRUE(file_desc->GetSourceLocation(vpath, &loc));
  6552. EXPECT_EQ("37:41-37:66", PrintSourceLocation(loc));
  6553. std::vector<int> vunint(unint, unint + 7);
  6554. EXPECT_FALSE(file_desc->GetSourceLocation(vunint, &loc));
  6555. }
  6556. {
  6557. int path[] = {FileDescriptorProto::kMessageTypeFieldNumber,
  6558. 1,
  6559. DescriptorProto::kExtensionRangeFieldNumber,
  6560. 1,
  6561. DescriptorProto_ExtensionRange::kOptionsFieldNumber,
  6562. kCustomOptionFieldNumber};
  6563. int unint[] = {FileDescriptorProto::kMessageTypeFieldNumber,
  6564. 1,
  6565. DescriptorProto::kExtensionRangeFieldNumber,
  6566. 1,
  6567. DescriptorProto_ExtensionRange::kOptionsFieldNumber,
  6568. ExtensionRangeOptions::kUninterpretedOptionFieldNumber,
  6569. 0};
  6570. std::vector<int> vpath(path, path + 6);
  6571. EXPECT_TRUE(file_desc->GetSourceLocation(vpath, &loc));
  6572. EXPECT_EQ("37:41-37:66", PrintSourceLocation(loc));
  6573. std::vector<int> vunint(unint, unint + 7);
  6574. EXPECT_FALSE(file_desc->GetSourceLocation(vunint, &loc));
  6575. }
  6576. // Field option on extension
  6577. {
  6578. int path[] = {FileDescriptorProto::kExtensionFieldNumber, 0,
  6579. FieldDescriptorProto::kOptionsFieldNumber,
  6580. FieldOptions::kPackedFieldNumber};
  6581. int unint[] = {FileDescriptorProto::kExtensionFieldNumber, 0,
  6582. FieldDescriptorProto::kOptionsFieldNumber,
  6583. FieldOptions::kUninterpretedOptionFieldNumber, 0};
  6584. std::vector<int> vpath(path, path + 4);
  6585. EXPECT_TRUE(file_desc->GetSourceLocation(vpath, &loc));
  6586. EXPECT_EQ("40:42-40:53", PrintSourceLocation(loc));
  6587. std::vector<int> vunint(unint, unint + 5);
  6588. EXPECT_FALSE(file_desc->GetSourceLocation(vunint, &loc));
  6589. }
  6590. }
  6591. // Missing SourceCodeInfo doesn't cause crash:
  6592. TEST_F(SourceLocationTest, GetSourceLocation_MissingSourceCodeInfo) {
  6593. SourceLocation loc;
  6594. const FileDescriptor* file_desc =
  6595. GOOGLE_CHECK_NOTNULL(pool_.FindFileByName("/test/test.proto"));
  6596. FileDescriptorProto proto;
  6597. file_desc->CopyTo(&proto); // Note, this discards the SourceCodeInfo.
  6598. EXPECT_FALSE(proto.has_source_code_info());
  6599. DescriptorPool bad1_pool(&pool_);
  6600. const FileDescriptor* bad1_file_desc =
  6601. GOOGLE_CHECK_NOTNULL(bad1_pool.BuildFile(proto));
  6602. const Descriptor* bad1_a_desc = bad1_file_desc->FindMessageTypeByName("A");
  6603. EXPECT_FALSE(bad1_a_desc->GetSourceLocation(&loc));
  6604. }
  6605. // Corrupt SourceCodeInfo doesn't cause crash:
  6606. TEST_F(SourceLocationTest, GetSourceLocation_BogusSourceCodeInfo) {
  6607. SourceLocation loc;
  6608. const FileDescriptor* file_desc =
  6609. GOOGLE_CHECK_NOTNULL(pool_.FindFileByName("/test/test.proto"));
  6610. FileDescriptorProto proto;
  6611. file_desc->CopyTo(&proto); // Note, this discards the SourceCodeInfo.
  6612. EXPECT_FALSE(proto.has_source_code_info());
  6613. SourceCodeInfo_Location* loc_msg =
  6614. proto.mutable_source_code_info()->add_location();
  6615. loc_msg->add_path(1);
  6616. loc_msg->add_path(2);
  6617. loc_msg->add_path(3);
  6618. loc_msg->add_span(4);
  6619. loc_msg->add_span(5);
  6620. loc_msg->add_span(6);
  6621. DescriptorPool bad2_pool(&pool_);
  6622. const FileDescriptor* bad2_file_desc =
  6623. GOOGLE_CHECK_NOTNULL(bad2_pool.BuildFile(proto));
  6624. const Descriptor* bad2_a_desc = bad2_file_desc->FindMessageTypeByName("A");
  6625. EXPECT_FALSE(bad2_a_desc->GetSourceLocation(&loc));
  6626. }
  6627. // ===================================================================
  6628. const char* const kCopySourceCodeInfoToTestInput =
  6629. "syntax = \"proto2\";\n"
  6630. "message Foo {}\n";
  6631. // Required since source code information is not preserved by
  6632. // FileDescriptorTest.
  6633. class CopySourceCodeInfoToTest : public testing::Test {
  6634. public:
  6635. CopySourceCodeInfoToTest()
  6636. : source_tree_("/test/test.proto", kCopySourceCodeInfoToTestInput),
  6637. db_(&source_tree_),
  6638. pool_(&db_, &collector_) {}
  6639. private:
  6640. AbortingErrorCollector collector_;
  6641. SingletonSourceTree source_tree_;
  6642. compiler::SourceTreeDescriptorDatabase db_;
  6643. protected:
  6644. DescriptorPool pool_;
  6645. };
  6646. TEST_F(CopySourceCodeInfoToTest, CopyTo_DoesNotCopySourceCodeInfo) {
  6647. const FileDescriptor* file_desc =
  6648. GOOGLE_CHECK_NOTNULL(pool_.FindFileByName("/test/test.proto"));
  6649. FileDescriptorProto file_desc_proto;
  6650. ASSERT_FALSE(file_desc_proto.has_source_code_info());
  6651. file_desc->CopyTo(&file_desc_proto);
  6652. EXPECT_FALSE(file_desc_proto.has_source_code_info());
  6653. }
  6654. TEST_F(CopySourceCodeInfoToTest, CopySourceCodeInfoTo) {
  6655. const FileDescriptor* file_desc =
  6656. GOOGLE_CHECK_NOTNULL(pool_.FindFileByName("/test/test.proto"));
  6657. FileDescriptorProto file_desc_proto;
  6658. ASSERT_FALSE(file_desc_proto.has_source_code_info());
  6659. file_desc->CopySourceCodeInfoTo(&file_desc_proto);
  6660. const SourceCodeInfo& info = file_desc_proto.source_code_info();
  6661. ASSERT_EQ(4, info.location_size());
  6662. // Get the Foo message location
  6663. const SourceCodeInfo_Location& foo_location = info.location(2);
  6664. ASSERT_EQ(2, foo_location.path_size());
  6665. EXPECT_EQ(FileDescriptorProto::kMessageTypeFieldNumber, foo_location.path(0));
  6666. EXPECT_EQ(0, foo_location.path(1)); // Foo is the first message defined
  6667. ASSERT_EQ(3, foo_location.span_size()); // Foo spans one line
  6668. EXPECT_EQ(1, foo_location.span(0)); // Foo is declared on line 1
  6669. EXPECT_EQ(0, foo_location.span(1)); // Foo starts at column 0
  6670. EXPECT_EQ(14, foo_location.span(2)); // Foo ends on column 14
  6671. }
  6672. // ===================================================================
  6673. class LazilyBuildDependenciesTest : public testing::Test {
  6674. public:
  6675. LazilyBuildDependenciesTest() : pool_(&db_, nullptr) {
  6676. pool_.InternalSetLazilyBuildDependencies();
  6677. }
  6678. void ParseProtoAndAddToDb(const char* proto) {
  6679. FileDescriptorProto tmp;
  6680. ASSERT_TRUE(TextFormat::ParseFromString(proto, &tmp));
  6681. db_.Add(tmp);
  6682. }
  6683. void ParseProtoAndAddToDb(const std::string& proto) {
  6684. FileDescriptorProto tmp;
  6685. ASSERT_TRUE(TextFormat::ParseFromString(proto, &tmp));
  6686. db_.Add(tmp);
  6687. }
  6688. void AddSimpleMessageProtoFileToDb(const char* file_name,
  6689. const char* message_name) {
  6690. ParseProtoAndAddToDb("name: '" + std::string(file_name) +
  6691. ".proto' "
  6692. "package: \"protobuf_unittest\" "
  6693. "message_type { "
  6694. " name:'" +
  6695. std::string(message_name) +
  6696. "' "
  6697. " field { name:'a' number:1 "
  6698. " label:LABEL_OPTIONAL "
  6699. " type_name:'int32' } "
  6700. "}");
  6701. }
  6702. void AddSimpleEnumProtoFileToDb(const char* file_name, const char* enum_name,
  6703. const char* enum_value_name) {
  6704. ParseProtoAndAddToDb("name: '" + std::string(file_name) +
  6705. ".proto' "
  6706. "package: 'protobuf_unittest' "
  6707. "enum_type { "
  6708. " name:'" +
  6709. std::string(enum_name) +
  6710. "' "
  6711. " value { name:'" +
  6712. std::string(enum_value_name) +
  6713. "' number:1 } "
  6714. "}");
  6715. }
  6716. protected:
  6717. SimpleDescriptorDatabase db_;
  6718. DescriptorPool pool_;
  6719. };
  6720. TEST_F(LazilyBuildDependenciesTest, Message) {
  6721. ParseProtoAndAddToDb(
  6722. "name: 'foo.proto' "
  6723. "package: 'protobuf_unittest' "
  6724. "dependency: 'bar.proto' "
  6725. "message_type { "
  6726. " name:'Foo' "
  6727. " field { name:'bar' number:1 label:LABEL_OPTIONAL "
  6728. "type_name:'.protobuf_unittest.Bar' } "
  6729. "}");
  6730. AddSimpleMessageProtoFileToDb("bar", "Bar");
  6731. // Verify neither has been built yet.
  6732. EXPECT_FALSE(pool_.InternalIsFileLoaded("foo.proto"));
  6733. EXPECT_FALSE(pool_.InternalIsFileLoaded("bar.proto"));
  6734. const FileDescriptor* file = pool_.FindFileByName("foo.proto");
  6735. // Verify only foo gets built when asking for foo.proto
  6736. EXPECT_TRUE(file != nullptr);
  6737. EXPECT_TRUE(pool_.InternalIsFileLoaded("foo.proto"));
  6738. EXPECT_FALSE(pool_.InternalIsFileLoaded("bar.proto"));
  6739. // Verify calling FindFieldBy* works when the type of the field was
  6740. // not built at cross link time. Verify this doesn't build the file
  6741. // the field's type is defined in, as well.
  6742. const Descriptor* desc = file->FindMessageTypeByName("Foo");
  6743. const FieldDescriptor* field = desc->FindFieldByName("bar");
  6744. EXPECT_TRUE(field != nullptr);
  6745. EXPECT_EQ(field, desc->FindFieldByNumber(1));
  6746. EXPECT_EQ(field, desc->FindFieldByLowercaseName("bar"));
  6747. EXPECT_EQ(field, desc->FindFieldByCamelcaseName("bar"));
  6748. EXPECT_FALSE(pool_.InternalIsFileLoaded("bar.proto"));
  6749. // Finally, verify that if we call message_type() on the field, we will
  6750. // buid the file where the message is defined, and get a valid descriptor
  6751. EXPECT_TRUE(field->message_type() != nullptr);
  6752. EXPECT_TRUE(pool_.InternalIsFileLoaded("bar.proto"));
  6753. }
  6754. TEST_F(LazilyBuildDependenciesTest, Enum) {
  6755. ParseProtoAndAddToDb(
  6756. "name: 'foo.proto' "
  6757. "package: 'protobuf_unittest' "
  6758. "dependency: 'enum1.proto' "
  6759. "dependency: 'enum2.proto' "
  6760. "message_type { "
  6761. " name:'Lazy' "
  6762. " field { name:'enum1' number:1 label:LABEL_OPTIONAL "
  6763. "type_name:'.protobuf_unittest.Enum1' } "
  6764. " field { name:'enum2' number:1 label:LABEL_OPTIONAL "
  6765. "type_name:'.protobuf_unittest.Enum2' } "
  6766. "}");
  6767. AddSimpleEnumProtoFileToDb("enum1", "Enum1", "ENUM1");
  6768. AddSimpleEnumProtoFileToDb("enum2", "Enum2", "ENUM2");
  6769. const FileDescriptor* file = pool_.FindFileByName("foo.proto");
  6770. // Verify calling enum_type() on a field whose definition is not
  6771. // yet built will build the file and return a descriptor.
  6772. EXPECT_FALSE(pool_.InternalIsFileLoaded("enum1.proto"));
  6773. const Descriptor* desc = file->FindMessageTypeByName("Lazy");
  6774. EXPECT_TRUE(desc != nullptr);
  6775. const FieldDescriptor* field = desc->FindFieldByName("enum1");
  6776. EXPECT_TRUE(field != nullptr);
  6777. EXPECT_TRUE(field->enum_type() != nullptr);
  6778. EXPECT_TRUE(pool_.InternalIsFileLoaded("enum1.proto"));
  6779. // Verify calling default_value_enum() on a field whose definition is not
  6780. // yet built will build the file and return a descriptor to the value.
  6781. EXPECT_FALSE(pool_.InternalIsFileLoaded("enum2.proto"));
  6782. field = desc->FindFieldByName("enum2");
  6783. EXPECT_TRUE(field != nullptr);
  6784. EXPECT_TRUE(field->default_value_enum() != nullptr);
  6785. EXPECT_TRUE(pool_.InternalIsFileLoaded("enum2.proto"));
  6786. }
  6787. TEST_F(LazilyBuildDependenciesTest, Type) {
  6788. ParseProtoAndAddToDb(
  6789. "name: 'foo.proto' "
  6790. "package: 'protobuf_unittest' "
  6791. "dependency: 'message1.proto' "
  6792. "dependency: 'message2.proto' "
  6793. "dependency: 'enum1.proto' "
  6794. "dependency: 'enum2.proto' "
  6795. "message_type { "
  6796. " name:'Lazy' "
  6797. " field { name:'message1' number:1 label:LABEL_OPTIONAL "
  6798. "type_name:'.protobuf_unittest.Message1' } "
  6799. " field { name:'message2' number:1 label:LABEL_OPTIONAL "
  6800. "type_name:'.protobuf_unittest.Message2' } "
  6801. " field { name:'enum1' number:1 label:LABEL_OPTIONAL "
  6802. "type_name:'.protobuf_unittest.Enum1' } "
  6803. " field { name:'enum2' number:1 label:LABEL_OPTIONAL "
  6804. "type_name:'.protobuf_unittest.Enum2' } "
  6805. "}");
  6806. AddSimpleMessageProtoFileToDb("message1", "Message1");
  6807. AddSimpleMessageProtoFileToDb("message2", "Message2");
  6808. AddSimpleEnumProtoFileToDb("enum1", "Enum1", "ENUM1");
  6809. AddSimpleEnumProtoFileToDb("enum2", "Enum2", "ENUM2");
  6810. const FileDescriptor* file = pool_.FindFileByName("foo.proto");
  6811. // Verify calling type() on a field that is a message type will
  6812. // build the type defined in another file.
  6813. EXPECT_FALSE(pool_.InternalIsFileLoaded("message1.proto"));
  6814. const Descriptor* desc = file->FindMessageTypeByName("Lazy");
  6815. EXPECT_TRUE(desc != nullptr);
  6816. const FieldDescriptor* field = desc->FindFieldByName("message1");
  6817. EXPECT_TRUE(field != nullptr);
  6818. EXPECT_EQ(field->type(), FieldDescriptor::TYPE_MESSAGE);
  6819. EXPECT_TRUE(pool_.InternalIsFileLoaded("message1.proto"));
  6820. // Verify calling cpp_type() on a field that is a message type will
  6821. // build the type defined in another file.
  6822. EXPECT_FALSE(pool_.InternalIsFileLoaded("message2.proto"));
  6823. field = desc->FindFieldByName("message2");
  6824. EXPECT_TRUE(field != nullptr);
  6825. EXPECT_EQ(field->cpp_type(), FieldDescriptor::CPPTYPE_MESSAGE);
  6826. EXPECT_TRUE(pool_.InternalIsFileLoaded("message2.proto"));
  6827. // Verify calling type() on a field that is an enum type will
  6828. // build the type defined in another file.
  6829. EXPECT_FALSE(pool_.InternalIsFileLoaded("enum1.proto"));
  6830. field = desc->FindFieldByName("enum1");
  6831. EXPECT_TRUE(field != nullptr);
  6832. EXPECT_EQ(field->type(), FieldDescriptor::TYPE_ENUM);
  6833. EXPECT_TRUE(pool_.InternalIsFileLoaded("enum1.proto"));
  6834. // Verify calling cpp_type() on a field that is an enum type will
  6835. // build the type defined in another file.
  6836. EXPECT_FALSE(pool_.InternalIsFileLoaded("enum2.proto"));
  6837. field = desc->FindFieldByName("enum2");
  6838. EXPECT_TRUE(field != nullptr);
  6839. EXPECT_EQ(field->cpp_type(), FieldDescriptor::CPPTYPE_ENUM);
  6840. EXPECT_TRUE(pool_.InternalIsFileLoaded("enum2.proto"));
  6841. }
  6842. TEST_F(LazilyBuildDependenciesTest, Extension) {
  6843. ParseProtoAndAddToDb(
  6844. "name: 'foo.proto' "
  6845. "package: 'protobuf_unittest' "
  6846. "dependency: 'bar.proto' "
  6847. "dependency: 'baz.proto' "
  6848. "extension { extendee: '.protobuf_unittest.Bar' name:'bar' number:11"
  6849. " label:LABEL_OPTIONAL type_name:'.protobuf_unittest.Baz' }");
  6850. ParseProtoAndAddToDb(
  6851. "name: 'bar.proto' "
  6852. "package: 'protobuf_unittest' "
  6853. "message_type { "
  6854. " name:'Bar' "
  6855. " extension_range { start: 10 end: 20 }"
  6856. "}");
  6857. AddSimpleMessageProtoFileToDb("baz", "Baz");
  6858. // Verify none have been built yet.
  6859. EXPECT_FALSE(pool_.InternalIsFileLoaded("foo.proto"));
  6860. EXPECT_FALSE(pool_.InternalIsFileLoaded("bar.proto"));
  6861. EXPECT_FALSE(pool_.InternalIsFileLoaded("baz.proto"));
  6862. const FileDescriptor* file = pool_.FindFileByName("foo.proto");
  6863. // Verify foo.bar gets loaded, and bar.proto gets loaded
  6864. // to register the extension. baz.proto should not get loaded.
  6865. EXPECT_TRUE(file != nullptr);
  6866. EXPECT_TRUE(pool_.InternalIsFileLoaded("foo.proto"));
  6867. EXPECT_TRUE(pool_.InternalIsFileLoaded("bar.proto"));
  6868. EXPECT_FALSE(pool_.InternalIsFileLoaded("baz.proto"));
  6869. }
  6870. TEST_F(LazilyBuildDependenciesTest, Service) {
  6871. ParseProtoAndAddToDb(
  6872. "name: 'foo.proto' "
  6873. "package: 'protobuf_unittest' "
  6874. "dependency: 'message1.proto' "
  6875. "dependency: 'message2.proto' "
  6876. "dependency: 'message3.proto' "
  6877. "dependency: 'message4.proto' "
  6878. "service {"
  6879. " name: 'LazyService'"
  6880. " method { name: 'A' input_type: '.protobuf_unittest.Message1' "
  6881. " output_type: '.protobuf_unittest.Message2' }"
  6882. "}");
  6883. AddSimpleMessageProtoFileToDb("message1", "Message1");
  6884. AddSimpleMessageProtoFileToDb("message2", "Message2");
  6885. AddSimpleMessageProtoFileToDb("message3", "Message3");
  6886. AddSimpleMessageProtoFileToDb("message4", "Message4");
  6887. const FileDescriptor* file = pool_.FindFileByName("foo.proto");
  6888. // Verify calling FindServiceByName or FindMethodByName doesn't build the
  6889. // files defining the input and output type, and input_type() and
  6890. // output_type() does indeed build the appropriate files.
  6891. const ServiceDescriptor* service = file->FindServiceByName("LazyService");
  6892. EXPECT_TRUE(service != nullptr);
  6893. const MethodDescriptor* method = service->FindMethodByName("A");
  6894. EXPECT_FALSE(pool_.InternalIsFileLoaded("message1.proto"));
  6895. EXPECT_FALSE(pool_.InternalIsFileLoaded("message2.proto"));
  6896. EXPECT_TRUE(method != nullptr);
  6897. EXPECT_TRUE(method->input_type() != nullptr);
  6898. EXPECT_TRUE(pool_.InternalIsFileLoaded("message1.proto"));
  6899. EXPECT_FALSE(pool_.InternalIsFileLoaded("message2.proto"));
  6900. EXPECT_TRUE(method->output_type() != nullptr);
  6901. EXPECT_TRUE(pool_.InternalIsFileLoaded("message2.proto"));
  6902. }
  6903. TEST_F(LazilyBuildDependenciesTest, GeneratedFile) {
  6904. // Most testing is done with custom pools with lazy dependencies forced on,
  6905. // do some sanity checking that lazy imports is on by default for the
  6906. // generated pool, and do custom options testing with generated to
  6907. // be able to use the GetExtension ids for the custom options.
  6908. // Verify none of the files are loaded yet.
  6909. EXPECT_FALSE(DescriptorPool::generated_pool()->InternalIsFileLoaded(
  6910. "google/protobuf/unittest_lazy_dependencies.proto"));
  6911. EXPECT_FALSE(DescriptorPool::generated_pool()->InternalIsFileLoaded(
  6912. "google/protobuf/unittest_lazy_dependencies_custom_option.proto"));
  6913. EXPECT_FALSE(DescriptorPool::generated_pool()->InternalIsFileLoaded(
  6914. "google/protobuf/unittest_lazy_dependencies_enum.proto"));
  6915. // Verify calling autogenerated function to get a descriptor in the base
  6916. // file will build that file but none of it's imports. This verifies that
  6917. // lazily_build_dependencies_ is set on the generated pool, and also that
  6918. // the generated function "descriptor()" doesn't somehow subvert the laziness
  6919. // by manually loading the dependencies or something.
  6920. EXPECT_TRUE(protobuf_unittest::lazy_imports::ImportedMessage::descriptor() !=
  6921. nullptr);
  6922. EXPECT_TRUE(DescriptorPool::generated_pool()->InternalIsFileLoaded(
  6923. "google/protobuf/unittest_lazy_dependencies.proto"));
  6924. EXPECT_FALSE(DescriptorPool::generated_pool()->InternalIsFileLoaded(
  6925. "google/protobuf/unittest_lazy_dependencies_custom_option.proto"));
  6926. EXPECT_FALSE(DescriptorPool::generated_pool()->InternalIsFileLoaded(
  6927. "google/protobuf/unittest_lazy_dependencies_enum.proto"));
  6928. // Verify custom options work when defined in an import that isn't loaded,
  6929. // and that a non-default value of a custom option doesn't load the file
  6930. // where that enum is defined.
  6931. const MessageOptions& options =
  6932. protobuf_unittest::lazy_imports::MessageCustomOption::descriptor()
  6933. ->options();
  6934. protobuf_unittest::lazy_imports::LazyEnum custom_option_value =
  6935. options.GetExtension(protobuf_unittest::lazy_imports::lazy_enum_option);
  6936. EXPECT_FALSE(DescriptorPool::generated_pool()->InternalIsFileLoaded(
  6937. "google/protobuf/unittest_lazy_dependencies_custom_option.proto"));
  6938. EXPECT_FALSE(DescriptorPool::generated_pool()->InternalIsFileLoaded(
  6939. "google/protobuf/unittest_lazy_dependencies_enum.proto"));
  6940. EXPECT_EQ(custom_option_value, protobuf_unittest::lazy_imports::LAZY_ENUM_1);
  6941. const MessageOptions& options2 =
  6942. protobuf_unittest::lazy_imports::MessageCustomOption2::descriptor()
  6943. ->options();
  6944. custom_option_value =
  6945. options2.GetExtension(protobuf_unittest::lazy_imports::lazy_enum_option);
  6946. EXPECT_FALSE(DescriptorPool::generated_pool()->InternalIsFileLoaded(
  6947. "google/protobuf/unittest_lazy_dependencies_custom_option.proto"));
  6948. EXPECT_FALSE(DescriptorPool::generated_pool()->InternalIsFileLoaded(
  6949. "google/protobuf/unittest_lazy_dependencies_enum.proto"));
  6950. EXPECT_EQ(custom_option_value, protobuf_unittest::lazy_imports::LAZY_ENUM_0);
  6951. }
  6952. TEST_F(LazilyBuildDependenciesTest, Dependency) {
  6953. ParseProtoAndAddToDb(
  6954. "name: 'foo.proto' "
  6955. "package: 'protobuf_unittest' "
  6956. "dependency: 'bar.proto' "
  6957. "message_type { "
  6958. " name:'Foo' "
  6959. " field { name:'bar' number:1 label:LABEL_OPTIONAL "
  6960. "type_name:'.protobuf_unittest.Bar' } "
  6961. "}");
  6962. ParseProtoAndAddToDb(
  6963. "name: 'bar.proto' "
  6964. "package: 'protobuf_unittest' "
  6965. "dependency: 'baz.proto' "
  6966. "message_type { "
  6967. " name:'Bar' "
  6968. " field { name:'baz' number:1 label:LABEL_OPTIONAL "
  6969. "type_name:'.protobuf_unittest.Baz' } "
  6970. "}");
  6971. AddSimpleMessageProtoFileToDb("baz", "Baz");
  6972. const FileDescriptor* foo_file = pool_.FindFileByName("foo.proto");
  6973. EXPECT_TRUE(foo_file != nullptr);
  6974. // As expected, requesting foo.proto shouldn't build it's dependencies
  6975. EXPECT_TRUE(pool_.InternalIsFileLoaded("foo.proto"));
  6976. EXPECT_FALSE(pool_.InternalIsFileLoaded("bar.proto"));
  6977. EXPECT_FALSE(pool_.InternalIsFileLoaded("baz.proto"));
  6978. // Verify calling dependency(N) will build the dependency, but
  6979. // not that file's dependencies.
  6980. const FileDescriptor* bar_file = foo_file->dependency(0);
  6981. EXPECT_TRUE(bar_file != nullptr);
  6982. EXPECT_TRUE(pool_.InternalIsFileLoaded("bar.proto"));
  6983. EXPECT_FALSE(pool_.InternalIsFileLoaded("baz.proto"));
  6984. }
  6985. // ===================================================================
  6986. } // namespace descriptor_unittest
  6987. } // namespace protobuf
  6988. } // namespace google