protostream_objectsource_test.cc 33 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088
  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. #include <google/protobuf/util/internal/protostream_objectsource.h>
  31. #include <memory>
  32. #include <sstream>
  33. #include <google/protobuf/stubs/casts.h>
  34. #include <google/protobuf/any.pb.h>
  35. #include <google/protobuf/io/coded_stream.h>
  36. #include <google/protobuf/io/zero_copy_stream_impl_lite.h>
  37. #include <google/protobuf/descriptor.h>
  38. #include <google/protobuf/util/internal/expecting_objectwriter.h>
  39. #include <google/protobuf/util/internal/testdata/anys.pb.h>
  40. #include <google/protobuf/util/internal/testdata/books.pb.h>
  41. #include <google/protobuf/util/internal/testdata/field_mask.pb.h>
  42. #include <google/protobuf/util/internal/testdata/maps.pb.h>
  43. #include <google/protobuf/util/internal/testdata/proto3.pb.h>
  44. #include <google/protobuf/util/internal/testdata/struct.pb.h>
  45. #include <google/protobuf/util/internal/testdata/timestamp_duration.pb.h>
  46. #include <google/protobuf/util/internal/type_info_test_helper.h>
  47. #include <google/protobuf/util/internal/constants.h>
  48. #include <google/protobuf/stubs/strutil.h>
  49. #include <gtest/gtest.h>
  50. namespace google {
  51. namespace protobuf {
  52. namespace util {
  53. namespace converter {
  54. using google::protobuf::Descriptor;
  55. using google::protobuf::DescriptorPool;
  56. using google::protobuf::FileDescriptorProto;
  57. using google::protobuf::Message;
  58. using google::protobuf::io::ArrayInputStream;
  59. using google::protobuf::io::CodedInputStream;
  60. using util::Status;
  61. using google::protobuf::testing::AnyM;
  62. using google::protobuf::testing::AnyOut;
  63. using google::protobuf::testing::Author;
  64. using google::protobuf::testing::BadAuthor;
  65. using google::protobuf::testing::BadNestedBook;
  66. using google::protobuf::testing::Book;
  67. using google::protobuf::testing::Book_Label;
  68. using google::protobuf::testing::Cyclic;
  69. using google::protobuf::testing::FieldMaskTest;
  70. using google::protobuf::testing::MapOut;
  71. using google::protobuf::testing::MapOutWireFormat;
  72. using google::protobuf::testing::NestedBook;
  73. using google::protobuf::testing::NestedFieldMask;
  74. using google::protobuf::testing::PackedPrimitive;
  75. using google::protobuf::testing::Primitive;
  76. using google::protobuf::testing::Proto3Message;
  77. using google::protobuf::testing::StructType;
  78. using google::protobuf::testing::TimestampDuration;
  79. using ::testing::_;
  80. namespace {
  81. string GetTypeUrl(const Descriptor* descriptor) {
  82. return string(kTypeServiceBaseUrl) + "/" + descriptor->full_name();
  83. }
  84. } // namespace
  85. class ProtostreamObjectSourceTest
  86. : public ::testing::TestWithParam<testing::TypeInfoSource> {
  87. protected:
  88. ProtostreamObjectSourceTest()
  89. : helper_(GetParam()),
  90. mock_(),
  91. ow_(&mock_),
  92. use_lower_camel_for_enums_(false),
  93. use_ints_for_enums_(false),
  94. add_trailing_zeros_(false),
  95. render_unknown_enum_values_(true) {
  96. helper_.ResetTypeInfo(Book::descriptor(), Proto3Message::descriptor());
  97. }
  98. virtual ~ProtostreamObjectSourceTest() {}
  99. void DoTest(const Message& msg, const Descriptor* descriptor) {
  100. Status status = ExecuteTest(msg, descriptor);
  101. EXPECT_EQ(util::Status(), status);
  102. }
  103. Status ExecuteTest(const Message& msg, const Descriptor* descriptor) {
  104. std::ostringstream oss;
  105. msg.SerializePartialToOstream(&oss);
  106. string proto = oss.str();
  107. ArrayInputStream arr_stream(proto.data(), proto.size());
  108. CodedInputStream in_stream(&arr_stream);
  109. std::unique_ptr<ProtoStreamObjectSource> os(
  110. helper_.NewProtoSource(&in_stream, GetTypeUrl(descriptor)));
  111. if (use_lower_camel_for_enums_) os->set_use_lower_camel_for_enums(true);
  112. if (use_ints_for_enums_) os->set_use_ints_for_enums(true);
  113. os->set_max_recursion_depth(64);
  114. return os->WriteTo(&mock_);
  115. }
  116. void PrepareExpectingObjectWriterForRepeatedPrimitive() {
  117. ow_.StartObject("")
  118. ->StartList("repFix32")
  119. ->RenderUint32("", bit_cast<uint32>(3201))
  120. ->RenderUint32("", bit_cast<uint32>(0))
  121. ->RenderUint32("", bit_cast<uint32>(3202))
  122. ->EndList()
  123. ->StartList("repU32")
  124. ->RenderUint32("", bit_cast<uint32>(3203))
  125. ->RenderUint32("", bit_cast<uint32>(0))
  126. ->EndList()
  127. ->StartList("repI32")
  128. ->RenderInt32("", 0)
  129. ->RenderInt32("", 3204)
  130. ->RenderInt32("", 3205)
  131. ->EndList()
  132. ->StartList("repSf32")
  133. ->RenderInt32("", 3206)
  134. ->RenderInt32("", 0)
  135. ->EndList()
  136. ->StartList("repS32")
  137. ->RenderInt32("", 0)
  138. ->RenderInt32("", 3207)
  139. ->RenderInt32("", 3208)
  140. ->EndList()
  141. ->StartList("repFix64")
  142. ->RenderUint64("", bit_cast<uint64>(6401LL))
  143. ->RenderUint64("", bit_cast<uint64>(0LL))
  144. ->EndList()
  145. ->StartList("repU64")
  146. ->RenderUint64("", bit_cast<uint64>(0LL))
  147. ->RenderUint64("", bit_cast<uint64>(6402LL))
  148. ->RenderUint64("", bit_cast<uint64>(6403LL))
  149. ->EndList()
  150. ->StartList("repI64")
  151. ->RenderInt64("", 6404L)
  152. ->RenderInt64("", 0L)
  153. ->EndList()
  154. ->StartList("repSf64")
  155. ->RenderInt64("", 0L)
  156. ->RenderInt64("", 6405L)
  157. ->RenderInt64("", 6406L)
  158. ->EndList()
  159. ->StartList("repS64")
  160. ->RenderInt64("", 6407L)
  161. ->RenderInt64("", 0L)
  162. ->EndList()
  163. ->StartList("repFloat")
  164. ->RenderFloat("", 0.0f)
  165. ->RenderFloat("", 32.1f)
  166. ->RenderFloat("", 32.2f)
  167. ->EndList()
  168. ->StartList("repDouble")
  169. ->RenderDouble("", 64.1L)
  170. ->RenderDouble("", 0.0L)
  171. ->EndList()
  172. ->StartList("repBool")
  173. ->RenderBool("", true)
  174. ->RenderBool("", false)
  175. ->EndList()
  176. ->EndObject();
  177. }
  178. Primitive PrepareRepeatedPrimitive() {
  179. Primitive primitive;
  180. primitive.add_rep_fix32(3201);
  181. primitive.add_rep_fix32(0);
  182. primitive.add_rep_fix32(3202);
  183. primitive.add_rep_u32(3203);
  184. primitive.add_rep_u32(0);
  185. primitive.add_rep_i32(0);
  186. primitive.add_rep_i32(3204);
  187. primitive.add_rep_i32(3205);
  188. primitive.add_rep_sf32(3206);
  189. primitive.add_rep_sf32(0);
  190. primitive.add_rep_s32(0);
  191. primitive.add_rep_s32(3207);
  192. primitive.add_rep_s32(3208);
  193. primitive.add_rep_fix64(6401L);
  194. primitive.add_rep_fix64(0L);
  195. primitive.add_rep_u64(0L);
  196. primitive.add_rep_u64(6402L);
  197. primitive.add_rep_u64(6403L);
  198. primitive.add_rep_i64(6404L);
  199. primitive.add_rep_i64(0L);
  200. primitive.add_rep_sf64(0L);
  201. primitive.add_rep_sf64(6405L);
  202. primitive.add_rep_sf64(6406L);
  203. primitive.add_rep_s64(6407L);
  204. primitive.add_rep_s64(0L);
  205. primitive.add_rep_float(0.0f);
  206. primitive.add_rep_float(32.1f);
  207. primitive.add_rep_float(32.2f);
  208. primitive.add_rep_double(64.1L);
  209. primitive.add_rep_double(0.0);
  210. primitive.add_rep_bool(true);
  211. primitive.add_rep_bool(false);
  212. PrepareExpectingObjectWriterForRepeatedPrimitive();
  213. return primitive;
  214. }
  215. PackedPrimitive PreparePackedPrimitive() {
  216. PackedPrimitive primitive;
  217. primitive.add_rep_fix32(3201);
  218. primitive.add_rep_fix32(0);
  219. primitive.add_rep_fix32(3202);
  220. primitive.add_rep_u32(3203);
  221. primitive.add_rep_u32(0);
  222. primitive.add_rep_i32(0);
  223. primitive.add_rep_i32(3204);
  224. primitive.add_rep_i32(3205);
  225. primitive.add_rep_sf32(3206);
  226. primitive.add_rep_sf32(0);
  227. primitive.add_rep_s32(0);
  228. primitive.add_rep_s32(3207);
  229. primitive.add_rep_s32(3208);
  230. primitive.add_rep_fix64(6401L);
  231. primitive.add_rep_fix64(0L);
  232. primitive.add_rep_u64(0L);
  233. primitive.add_rep_u64(6402L);
  234. primitive.add_rep_u64(6403L);
  235. primitive.add_rep_i64(6404L);
  236. primitive.add_rep_i64(0L);
  237. primitive.add_rep_sf64(0L);
  238. primitive.add_rep_sf64(6405L);
  239. primitive.add_rep_sf64(6406L);
  240. primitive.add_rep_s64(6407L);
  241. primitive.add_rep_s64(0L);
  242. primitive.add_rep_float(0.0f);
  243. primitive.add_rep_float(32.1f);
  244. primitive.add_rep_float(32.2f);
  245. primitive.add_rep_double(64.1L);
  246. primitive.add_rep_double(0.0);
  247. primitive.add_rep_bool(true);
  248. primitive.add_rep_bool(false);
  249. PrepareExpectingObjectWriterForRepeatedPrimitive();
  250. return primitive;
  251. }
  252. void UseLowerCamelForEnums() { use_lower_camel_for_enums_ = true; }
  253. void UseIntsForEnums() { use_ints_for_enums_ = true; }
  254. void AddTrailingZeros() { add_trailing_zeros_ = true; }
  255. void SetRenderUnknownEnumValues(bool value) {
  256. render_unknown_enum_values_ = value;
  257. }
  258. testing::TypeInfoTestHelper helper_;
  259. ::testing::NiceMock<MockObjectWriter> mock_;
  260. ExpectingObjectWriter ow_;
  261. bool use_lower_camel_for_enums_;
  262. bool use_ints_for_enums_;
  263. bool add_trailing_zeros_;
  264. bool render_unknown_enum_values_;
  265. };
  266. INSTANTIATE_TEST_CASE_P(DifferentTypeInfoSourceTest,
  267. ProtostreamObjectSourceTest,
  268. ::testing::Values(
  269. testing::USE_TYPE_RESOLVER));
  270. TEST_P(ProtostreamObjectSourceTest, EmptyMessage) {
  271. Book empty;
  272. ow_.StartObject("")->EndObject();
  273. DoTest(empty, Book::descriptor());
  274. }
  275. TEST_P(ProtostreamObjectSourceTest, Primitives) {
  276. Primitive primitive;
  277. primitive.set_fix32(3201);
  278. primitive.set_u32(3202);
  279. primitive.set_i32(3203);
  280. primitive.set_sf32(3204);
  281. primitive.set_s32(3205);
  282. primitive.set_fix64(6401L);
  283. primitive.set_u64(6402L);
  284. primitive.set_i64(6403L);
  285. primitive.set_sf64(6404L);
  286. primitive.set_s64(6405L);
  287. primitive.set_str("String Value");
  288. primitive.set_bytes("Some Bytes");
  289. primitive.set_float_(32.1f);
  290. primitive.set_double_(64.1L);
  291. primitive.set_bool_(true);
  292. ow_.StartObject("")
  293. ->RenderUint32("fix32", bit_cast<uint32>(3201))
  294. ->RenderUint32("u32", bit_cast<uint32>(3202))
  295. ->RenderInt32("i32", 3203)
  296. ->RenderInt32("sf32", 3204)
  297. ->RenderInt32("s32", 3205)
  298. ->RenderUint64("fix64", bit_cast<uint64>(6401LL))
  299. ->RenderUint64("u64", bit_cast<uint64>(6402LL))
  300. ->RenderInt64("i64", 6403L)
  301. ->RenderInt64("sf64", 6404L)
  302. ->RenderInt64("s64", 6405L)
  303. ->RenderString("str", "String Value")
  304. ->RenderBytes("bytes", "Some Bytes")
  305. ->RenderFloat("float", 32.1f)
  306. ->RenderDouble("double", 64.1L)
  307. ->RenderBool("bool", true)
  308. ->EndObject();
  309. DoTest(primitive, Primitive::descriptor());
  310. }
  311. TEST_P(ProtostreamObjectSourceTest, RepeatingPrimitives) {
  312. Primitive primitive = PrepareRepeatedPrimitive();
  313. primitive.add_rep_str("String One");
  314. primitive.add_rep_str("String Two");
  315. primitive.add_rep_bytes("Some Bytes");
  316. ow_.StartList("repStr")
  317. ->RenderString("", "String One")
  318. ->RenderString("", "String Two")
  319. ->EndList()
  320. ->StartList("repBytes")
  321. ->RenderBytes("", "Some Bytes")
  322. ->EndList();
  323. DoTest(primitive, Primitive::descriptor());
  324. }
  325. TEST_P(ProtostreamObjectSourceTest, CustomJsonName) {
  326. Author author;
  327. author.set_id(12345);
  328. ow_.StartObject("")->RenderUint64("@id", 12345)->EndObject();
  329. DoTest(author, Author::descriptor());
  330. }
  331. TEST_P(ProtostreamObjectSourceTest, NestedMessage) {
  332. Author* author = new Author();
  333. author->set_name("Tolstoy");
  334. Book book;
  335. book.set_title("My Book");
  336. book.set_allocated_author(author);
  337. ow_.StartObject("")
  338. ->RenderString("title", "My Book")
  339. ->StartObject("author")
  340. ->RenderString("name", "Tolstoy")
  341. ->EndObject()
  342. ->EndObject();
  343. DoTest(book, Book::descriptor());
  344. }
  345. TEST_P(ProtostreamObjectSourceTest, RepeatingField) {
  346. Author author;
  347. author.set_alive(false);
  348. author.set_name("john");
  349. author.add_pseudonym("phil");
  350. author.add_pseudonym("bob");
  351. ow_.StartObject("")
  352. ->RenderBool("alive", false)
  353. ->RenderString("name", "john")
  354. ->StartList("pseudonym")
  355. ->RenderString("", "phil")
  356. ->RenderString("", "bob")
  357. ->EndList()
  358. ->EndObject();
  359. DoTest(author, Author::descriptor());
  360. }
  361. TEST_P(ProtostreamObjectSourceTest, PackedRepeatingFields) {
  362. DoTest(PreparePackedPrimitive(), PackedPrimitive::descriptor());
  363. }
  364. TEST_P(ProtostreamObjectSourceTest, NonPackedPackableFieldsActuallyPacked) {
  365. // Protostream is packed, but parse with non-packed Primitive.
  366. DoTest(PreparePackedPrimitive(), Primitive::descriptor());
  367. }
  368. TEST_P(ProtostreamObjectSourceTest, PackedPackableFieldNotActuallyPacked) {
  369. // Protostream is not packed, but parse with PackedPrimitive.
  370. DoTest(PrepareRepeatedPrimitive(), PackedPrimitive::descriptor());
  371. }
  372. TEST_P(ProtostreamObjectSourceTest, BadAuthor) {
  373. Author author;
  374. author.set_alive(false);
  375. author.set_name("john");
  376. author.set_id(1234L);
  377. author.add_pseudonym("phil");
  378. author.add_pseudonym("bob");
  379. ow_.StartObject("")
  380. ->StartList("alive")
  381. ->RenderBool("", false)
  382. ->EndList()
  383. ->StartList("name")
  384. ->RenderUint64("", static_cast<uint64>('j'))
  385. ->RenderUint64("", static_cast<uint64>('o'))
  386. ->RenderUint64("", static_cast<uint64>('h'))
  387. ->RenderUint64("", static_cast<uint64>('n'))
  388. ->EndList()
  389. ->RenderString("pseudonym", "phil")
  390. ->RenderString("pseudonym", "bob")
  391. ->EndObject();
  392. // Protostream created with Author, but parsed with BadAuthor.
  393. DoTest(author, BadAuthor::descriptor());
  394. }
  395. TEST_P(ProtostreamObjectSourceTest, NestedBookToBadNestedBook) {
  396. Book* book = new Book();
  397. book->set_length(250);
  398. book->set_published(2014L);
  399. NestedBook nested;
  400. nested.set_allocated_book(book);
  401. ow_.StartObject("")
  402. ->StartList("book")
  403. ->RenderUint32("", 24) // tag for field length (3 << 3)
  404. ->RenderUint32("", 250)
  405. ->RenderUint32("", 32) // tag for field published (4 << 3)
  406. ->RenderUint32("", 2014)
  407. ->EndList()
  408. ->EndObject();
  409. // Protostream created with NestedBook, but parsed with BadNestedBook.
  410. DoTest(nested, BadNestedBook::descriptor());
  411. }
  412. TEST_P(ProtostreamObjectSourceTest, BadNestedBookToNestedBook) {
  413. BadNestedBook nested;
  414. nested.add_book(1);
  415. nested.add_book(2);
  416. nested.add_book(3);
  417. nested.add_book(4);
  418. nested.add_book(5);
  419. nested.add_book(6);
  420. nested.add_book(7);
  421. ow_.StartObject("")->StartObject("book")->EndObject()->EndObject();
  422. // Protostream created with BadNestedBook, but parsed with NestedBook.
  423. DoTest(nested, NestedBook::descriptor());
  424. }
  425. TEST_P(ProtostreamObjectSourceTest,
  426. LongRepeatedListDoesNotBreakIntoMultipleJsonLists) {
  427. Book book;
  428. int repeat = 10000;
  429. for (int i = 0; i < repeat; ++i) {
  430. Book_Label* label = book.add_labels();
  431. label->set_key(StrCat("i", i));
  432. label->set_value(StrCat("v", i));
  433. }
  434. // Make sure StartList and EndList are called exactly once (see b/18227499 for
  435. // problems when this doesn't happen)
  436. EXPECT_CALL(mock_, StartList(_)).Times(1);
  437. EXPECT_CALL(mock_, EndList()).Times(1);
  438. DoTest(book, Book::descriptor());
  439. }
  440. TEST_P(ProtostreamObjectSourceTest, LowerCamelEnumOutputMacroCase) {
  441. Book book;
  442. book.set_type(Book::ACTION_AND_ADVENTURE);
  443. UseLowerCamelForEnums();
  444. ow_.StartObject("")->RenderString("type", "actionAndAdventure")->EndObject();
  445. DoTest(book, Book::descriptor());
  446. }
  447. TEST_P(ProtostreamObjectSourceTest, LowerCamelEnumOutputSnakeCase) {
  448. Book book;
  449. book.set_type(Book::arts_and_photography);
  450. UseLowerCamelForEnums();
  451. ow_.StartObject("")->RenderString("type", "artsAndPhotography")->EndObject();
  452. DoTest(book, Book::descriptor());
  453. }
  454. TEST_P(ProtostreamObjectSourceTest, LowerCamelEnumOutputWithNumber) {
  455. Book book;
  456. book.set_type(Book::I18N_Tech);
  457. UseLowerCamelForEnums();
  458. ow_.StartObject("")->RenderString("type", "i18nTech")->EndObject();
  459. DoTest(book, Book::descriptor());
  460. }
  461. TEST_P(ProtostreamObjectSourceTest, EnumCaseIsUnchangedByDefault) {
  462. Book book;
  463. book.set_type(Book::ACTION_AND_ADVENTURE);
  464. ow_.StartObject("")
  465. ->RenderString("type", "ACTION_AND_ADVENTURE")
  466. ->EndObject();
  467. DoTest(book, Book::descriptor());
  468. }
  469. TEST_P(ProtostreamObjectSourceTest, UseIntsForEnumsTest) {
  470. Book book;
  471. book.set_type(Book::ACTION_AND_ADVENTURE);
  472. UseIntsForEnums();
  473. ow_.StartObject("")->RenderInt32("type", 3)->EndObject();
  474. DoTest(book, Book::descriptor());
  475. }
  476. TEST_P(ProtostreamObjectSourceTest,
  477. UnknownEnumAreDroppedWhenRenderUnknownEnumValuesIsUnset) {
  478. Proto3Message message;
  479. message.set_enum_value(static_cast<Proto3Message::NestedEnum>(1234));
  480. SetRenderUnknownEnumValues(false);
  481. // Unknown enum values are not output.
  482. ow_.StartObject("")->EndObject();
  483. DoTest(message, Proto3Message::descriptor());
  484. }
  485. TEST_P(ProtostreamObjectSourceTest,
  486. UnknownEnumAreOutputWhenRenderUnknownEnumValuesIsSet) {
  487. Proto3Message message;
  488. message.set_enum_value(static_cast<Proto3Message::NestedEnum>(1234));
  489. SetRenderUnknownEnumValues(true);
  490. // Unknown enum values are output.
  491. ow_.StartObject("")->RenderInt32("enumValue", 1234)->EndObject();
  492. DoTest(message, Proto3Message::descriptor());
  493. }
  494. TEST_P(ProtostreamObjectSourceTest, CyclicMessageDepthTest) {
  495. Cyclic cyclic;
  496. cyclic.set_m_int(123);
  497. Book* book = cyclic.mutable_m_book();
  498. book->set_title("book title");
  499. Cyclic* current = cyclic.mutable_m_cyclic();
  500. Author* current_author = cyclic.add_m_author();
  501. for (int i = 0; i < 63; ++i) {
  502. Author* next = current_author->add_friend_();
  503. next->set_id(i);
  504. next->set_name(StrCat("author_name_", i));
  505. next->set_alive(true);
  506. current_author = next;
  507. }
  508. // Recursive message with depth (65) > max (max is 64).
  509. for (int i = 0; i < 64; ++i) {
  510. Cyclic* next = current->mutable_m_cyclic();
  511. next->set_m_str(StrCat("count_", i));
  512. current = next;
  513. }
  514. Status status = ExecuteTest(cyclic, Cyclic::descriptor());
  515. EXPECT_EQ(util::error::INVALID_ARGUMENT, status.error_code());
  516. }
  517. class ProtostreamObjectSourceMapsTest : public ProtostreamObjectSourceTest {
  518. protected:
  519. ProtostreamObjectSourceMapsTest() {
  520. helper_.ResetTypeInfo(MapOut::descriptor());
  521. }
  522. };
  523. INSTANTIATE_TEST_CASE_P(DifferentTypeInfoSourceTest,
  524. ProtostreamObjectSourceMapsTest,
  525. ::testing::Values(
  526. testing::USE_TYPE_RESOLVER));
  527. // Tests JSON map.
  528. //
  529. // This is the example expected output.
  530. // {
  531. // "map1": {
  532. // "key1": {
  533. // "foo": "foovalue"
  534. // },
  535. // "key2": {
  536. // "foo": "barvalue"
  537. // }
  538. // },
  539. // "map2": {
  540. // "nestedself": {
  541. // "map1": {
  542. // "nested_key1": {
  543. // "foo": "nested_foo"
  544. // }
  545. // },
  546. // "bar": "nested_bar_string"
  547. // }
  548. // },
  549. // "map3": {
  550. // "111": "one one one"
  551. // },
  552. // "bar": "top bar"
  553. // }
  554. TEST_P(ProtostreamObjectSourceMapsTest, MapsTest) {
  555. MapOut out;
  556. (*out.mutable_map1())["key1"].set_foo("foovalue");
  557. (*out.mutable_map1())["key2"].set_foo("barvalue");
  558. MapOut* nested_value = &(*out.mutable_map2())["nestedself"];
  559. (*nested_value->mutable_map1())["nested_key1"].set_foo("nested_foo");
  560. nested_value->set_bar("nested_bar_string");
  561. (*out.mutable_map3())[111] = "one one one";
  562. out.set_bar("top bar");
  563. ow_.StartObject("")
  564. ->StartObject("map1")
  565. ->StartObject("key1")
  566. ->RenderString("foo", "foovalue")
  567. ->EndObject()
  568. ->StartObject("key2")
  569. ->RenderString("foo", "barvalue")
  570. ->EndObject()
  571. ->StartObject("map2")
  572. ->StartObject("nestedself")
  573. ->StartObject("map1")
  574. ->StartObject("nested_key1")
  575. ->RenderString("foo", "nested_foo")
  576. ->EndObject()
  577. ->EndObject()
  578. ->RenderString("bar", "nested_bar_string")
  579. ->EndObject()
  580. ->EndObject()
  581. ->StartObject("map3")
  582. ->RenderString("111", "one one one")
  583. ->EndObject()
  584. ->EndObject()
  585. ->RenderString("bar", "top bar")
  586. ->EndObject();
  587. DoTest(out, MapOut::descriptor());
  588. }
  589. TEST_P(ProtostreamObjectSourceMapsTest, MissingKeysTest) {
  590. // MapOutWireFormat has the same wire representation with MapOut but uses
  591. // repeated message fields to represent map fields so we can intentionally
  592. // leave out the key field or the value field of a map entry.
  593. MapOutWireFormat out;
  594. // Create some map entries without keys. They will be rendered with the
  595. // default values ("" for strings, "0" for integers, etc.).
  596. // {
  597. // "map1": {
  598. // "": {
  599. // "foo": "foovalue"
  600. // }
  601. // },
  602. // "map2": {
  603. // "": {
  604. // "map1": {
  605. // "nested_key1": {
  606. // "foo": "nested_foo"
  607. // }
  608. // }
  609. // }
  610. // },
  611. // "map3": {
  612. // "0": "one one one"
  613. // },
  614. // "map4": {
  615. // "false": "bool"
  616. // }
  617. // }
  618. out.add_map1()->mutable_value()->set_foo("foovalue");
  619. MapOut* nested = out.add_map2()->mutable_value();
  620. (*nested->mutable_map1())["nested_key1"].set_foo("nested_foo");
  621. out.add_map3()->set_value("one one one");
  622. out.add_map4()->set_value("bool");
  623. ow_.StartObject("")
  624. ->StartObject("map1")
  625. ->StartObject("")
  626. ->RenderString("foo", "foovalue")
  627. ->EndObject()
  628. ->EndObject()
  629. ->StartObject("map2")
  630. ->StartObject("")
  631. ->StartObject("map1")
  632. ->StartObject("nested_key1")
  633. ->RenderString("foo", "nested_foo")
  634. ->EndObject()
  635. ->EndObject()
  636. ->EndObject()
  637. ->EndObject()
  638. ->StartObject("map3")
  639. ->RenderString("0", "one one one")
  640. ->EndObject()
  641. ->StartObject("map4")
  642. ->RenderString("false", "bool")
  643. ->EndObject()
  644. ->EndObject();
  645. DoTest(out, MapOut::descriptor());
  646. }
  647. class ProtostreamObjectSourceAnysTest : public ProtostreamObjectSourceTest {
  648. protected:
  649. ProtostreamObjectSourceAnysTest() {
  650. helper_.ResetTypeInfo(AnyOut::descriptor(),
  651. google::protobuf::Any::descriptor());
  652. }
  653. };
  654. INSTANTIATE_TEST_CASE_P(DifferentTypeInfoSourceTest,
  655. ProtostreamObjectSourceAnysTest,
  656. ::testing::Values(
  657. testing::USE_TYPE_RESOLVER));
  658. // Tests JSON any support.
  659. //
  660. // This is the example expected output.
  661. // {
  662. // "any": {
  663. // "@type": "type.googleapis.com/google.protobuf.testing.AnyM"
  664. // "foo": "foovalue"
  665. // }
  666. // }
  667. TEST_P(ProtostreamObjectSourceAnysTest, BasicAny) {
  668. AnyOut out;
  669. ::google::protobuf::Any* any = out.mutable_any();
  670. AnyM m;
  671. m.set_foo("foovalue");
  672. any->PackFrom(m);
  673. ow_.StartObject("")
  674. ->StartObject("any")
  675. ->RenderString("@type",
  676. "type.googleapis.com/google.protobuf.testing.AnyM")
  677. ->RenderString("foo", "foovalue")
  678. ->EndObject()
  679. ->EndObject();
  680. DoTest(out, AnyOut::descriptor());
  681. }
  682. TEST_P(ProtostreamObjectSourceAnysTest, RecursiveAny) {
  683. AnyOut out;
  684. ::google::protobuf::Any* any = out.mutable_any();
  685. any->set_type_url("type.googleapis.com/google.protobuf.Any");
  686. ::google::protobuf::Any nested_any;
  687. nested_any.set_type_url("type.googleapis.com/google.protobuf.testing.AnyM");
  688. AnyM m;
  689. m.set_foo("foovalue");
  690. nested_any.set_value(m.SerializeAsString());
  691. any->set_value(nested_any.SerializeAsString());
  692. ow_.StartObject("")
  693. ->StartObject("any")
  694. ->RenderString("@type", "type.googleapis.com/google.protobuf.Any")
  695. ->StartObject("value")
  696. ->RenderString("@type",
  697. "type.googleapis.com/google.protobuf.testing.AnyM")
  698. ->RenderString("foo", "foovalue")
  699. ->EndObject()
  700. ->EndObject()
  701. ->EndObject();
  702. DoTest(out, AnyOut::descriptor());
  703. }
  704. TEST_P(ProtostreamObjectSourceAnysTest, DoubleRecursiveAny) {
  705. AnyOut out;
  706. ::google::protobuf::Any* any = out.mutable_any();
  707. any->set_type_url("type.googleapis.com/google.protobuf.Any");
  708. ::google::protobuf::Any nested_any;
  709. nested_any.set_type_url("type.googleapis.com/google.protobuf.Any");
  710. ::google::protobuf::Any second_nested_any;
  711. second_nested_any.set_type_url(
  712. "type.googleapis.com/google.protobuf.testing.AnyM");
  713. AnyM m;
  714. m.set_foo("foovalue");
  715. second_nested_any.set_value(m.SerializeAsString());
  716. nested_any.set_value(second_nested_any.SerializeAsString());
  717. any->set_value(nested_any.SerializeAsString());
  718. ow_.StartObject("")
  719. ->StartObject("any")
  720. ->RenderString("@type", "type.googleapis.com/google.protobuf.Any")
  721. ->StartObject("value")
  722. ->RenderString("@type", "type.googleapis.com/google.protobuf.Any")
  723. ->StartObject("value")
  724. ->RenderString("@type",
  725. "type.googleapis.com/google.protobuf.testing.AnyM")
  726. ->RenderString("foo", "foovalue")
  727. ->EndObject()
  728. ->EndObject()
  729. ->EndObject()
  730. ->EndObject();
  731. DoTest(out, AnyOut::descriptor());
  732. }
  733. TEST_P(ProtostreamObjectSourceAnysTest, EmptyAnyOutputsEmptyObject) {
  734. AnyOut out;
  735. out.mutable_any();
  736. ow_.StartObject("")->StartObject("any")->EndObject()->EndObject();
  737. DoTest(out, AnyOut::descriptor());
  738. }
  739. TEST_P(ProtostreamObjectSourceAnysTest, EmptyWithTypeAndNoValueOutputsType) {
  740. AnyOut out;
  741. out.mutable_any()->set_type_url("foo.googleapis.com/my.Type");
  742. ow_.StartObject("")
  743. ->StartObject("any")
  744. ->RenderString("@type", "foo.googleapis.com/my.Type")
  745. ->EndObject()
  746. ->EndObject();
  747. DoTest(out, AnyOut::descriptor());
  748. }
  749. TEST_P(ProtostreamObjectSourceAnysTest, MissingTypeUrlError) {
  750. AnyOut out;
  751. ::google::protobuf::Any* any = out.mutable_any();
  752. AnyM m;
  753. m.set_foo("foovalue");
  754. any->set_value(m.SerializeAsString());
  755. // We start the "AnyOut" part and then fail when we hit the Any object.
  756. ow_.StartObject("");
  757. Status status = ExecuteTest(out, AnyOut::descriptor());
  758. EXPECT_EQ(util::error::INTERNAL, status.error_code());
  759. }
  760. TEST_P(ProtostreamObjectSourceAnysTest, UnknownTypeServiceError) {
  761. AnyOut out;
  762. ::google::protobuf::Any* any = out.mutable_any();
  763. any->set_type_url("foo.googleapis.com/my.own.Type");
  764. AnyM m;
  765. m.set_foo("foovalue");
  766. any->set_value(m.SerializeAsString());
  767. // We start the "AnyOut" part and then fail when we hit the Any object.
  768. ow_.StartObject("");
  769. Status status = ExecuteTest(out, AnyOut::descriptor());
  770. EXPECT_EQ(util::error::INTERNAL, status.error_code());
  771. }
  772. TEST_P(ProtostreamObjectSourceAnysTest, UnknownTypeError) {
  773. AnyOut out;
  774. ::google::protobuf::Any* any = out.mutable_any();
  775. any->set_type_url("type.googleapis.com/unknown.Type");
  776. AnyM m;
  777. m.set_foo("foovalue");
  778. any->set_value(m.SerializeAsString());
  779. // We start the "AnyOut" part and then fail when we hit the Any object.
  780. ow_.StartObject("");
  781. Status status = ExecuteTest(out, AnyOut::descriptor());
  782. EXPECT_EQ(util::error::INTERNAL, status.error_code());
  783. }
  784. class ProtostreamObjectSourceStructTest : public ProtostreamObjectSourceTest {
  785. protected:
  786. ProtostreamObjectSourceStructTest() {
  787. helper_.ResetTypeInfo(StructType::descriptor(),
  788. google::protobuf::Struct::descriptor());
  789. }
  790. };
  791. INSTANTIATE_TEST_CASE_P(DifferentTypeInfoSourceTest,
  792. ProtostreamObjectSourceStructTest,
  793. ::testing::Values(
  794. testing::USE_TYPE_RESOLVER));
  795. // Tests struct
  796. //
  797. // "object": {
  798. // "k1": 123,
  799. // "k2": true
  800. // }
  801. TEST_P(ProtostreamObjectSourceStructTest, StructRenderSuccess) {
  802. StructType out;
  803. google::protobuf::Struct* s = out.mutable_object();
  804. s->mutable_fields()->operator[]("k1").set_number_value(123);
  805. s->mutable_fields()->operator[]("k2").set_bool_value(true);
  806. ow_.StartObject("")
  807. ->StartObject("object")
  808. ->RenderDouble("k1", 123)
  809. ->RenderBool("k2", true)
  810. ->EndObject()
  811. ->EndObject();
  812. DoTest(out, StructType::descriptor());
  813. }
  814. TEST_P(ProtostreamObjectSourceStructTest, MissingValueSkipsField) {
  815. StructType out;
  816. google::protobuf::Struct* s = out.mutable_object();
  817. s->mutable_fields()->operator[]("k1");
  818. ow_.StartObject("")->StartObject("object")->EndObject()->EndObject();
  819. DoTest(out, StructType::descriptor());
  820. }
  821. class ProtostreamObjectSourceFieldMaskTest
  822. : public ProtostreamObjectSourceTest {
  823. protected:
  824. ProtostreamObjectSourceFieldMaskTest() {
  825. helper_.ResetTypeInfo(FieldMaskTest::descriptor(),
  826. google::protobuf::FieldMask::descriptor());
  827. }
  828. };
  829. INSTANTIATE_TEST_CASE_P(DifferentTypeInfoSourceTest,
  830. ProtostreamObjectSourceFieldMaskTest,
  831. ::testing::Values(
  832. testing::USE_TYPE_RESOLVER));
  833. TEST_P(ProtostreamObjectSourceFieldMaskTest, FieldMaskRenderSuccess) {
  834. FieldMaskTest out;
  835. out.set_id("1");
  836. out.mutable_single_mask()->add_paths("path1");
  837. out.mutable_single_mask()->add_paths("snake_case_path2");
  838. ::google::protobuf::FieldMask* mask = out.add_repeated_mask();
  839. mask->add_paths("path3");
  840. mask = out.add_repeated_mask();
  841. mask->add_paths("snake_case_path4");
  842. mask->add_paths("path5");
  843. NestedFieldMask* nested = out.add_nested_mask();
  844. nested->set_data("data");
  845. nested->mutable_single_mask()->add_paths("nested.path1");
  846. nested->mutable_single_mask()->add_paths("nested_field.snake_case_path2");
  847. mask = nested->add_repeated_mask();
  848. mask->add_paths("nested_field.path3");
  849. mask->add_paths("nested.snake_case_path4");
  850. mask = nested->add_repeated_mask();
  851. mask->add_paths("nested.path5");
  852. mask = nested->add_repeated_mask();
  853. mask->add_paths(
  854. "snake_case.map_field[\"map_key_should_be_ignored\"].nested_snake_case."
  855. "map_field[\"map_key_sho\\\"uld_be_ignored\"]");
  856. ow_.StartObject("")
  857. ->RenderString("id", "1")
  858. ->RenderString("singleMask", "path1,snakeCasePath2")
  859. ->StartList("repeatedMask")
  860. ->RenderString("", "path3")
  861. ->RenderString("", "snakeCasePath4,path5")
  862. ->EndList()
  863. ->StartList("nestedMask")
  864. ->StartObject("")
  865. ->RenderString("data", "data")
  866. ->RenderString("singleMask", "nested.path1,nestedField.snakeCasePath2")
  867. ->StartList("repeatedMask")
  868. ->RenderString("", "nestedField.path3,nested.snakeCasePath4")
  869. ->RenderString("", "nested.path5")
  870. ->RenderString("",
  871. "snakeCase.mapField[\"map_key_should_be_ignored\"]."
  872. "nestedSnakeCase.mapField[\"map_key_sho\\\"uld_be_"
  873. "ignored\"]")
  874. ->EndList()
  875. ->EndObject()
  876. ->EndList()
  877. ->EndObject();
  878. DoTest(out, FieldMaskTest::descriptor());
  879. }
  880. class ProtostreamObjectSourceTimestampTest
  881. : public ProtostreamObjectSourceTest {
  882. protected:
  883. ProtostreamObjectSourceTimestampTest() {
  884. helper_.ResetTypeInfo(TimestampDuration::descriptor());
  885. }
  886. };
  887. INSTANTIATE_TEST_CASE_P(DifferentTypeInfoSourceTest,
  888. ProtostreamObjectSourceTimestampTest,
  889. ::testing::Values(
  890. testing::USE_TYPE_RESOLVER));
  891. TEST_P(ProtostreamObjectSourceTimestampTest, InvalidTimestampBelowMinTest) {
  892. TimestampDuration out;
  893. google::protobuf::Timestamp* ts = out.mutable_ts();
  894. // Min allowed seconds - 1
  895. ts->set_seconds(kTimestampMinSeconds - 1);
  896. ow_.StartObject("");
  897. Status status = ExecuteTest(out, TimestampDuration::descriptor());
  898. EXPECT_EQ(util::error::INTERNAL, status.error_code());
  899. }
  900. TEST_P(ProtostreamObjectSourceTimestampTest, InvalidTimestampAboveMaxTest) {
  901. TimestampDuration out;
  902. google::protobuf::Timestamp* ts = out.mutable_ts();
  903. // Max allowed seconds + 1
  904. ts->set_seconds(kTimestampMaxSeconds + 1);
  905. ow_.StartObject("");
  906. Status status = ExecuteTest(out, TimestampDuration::descriptor());
  907. EXPECT_EQ(util::error::INTERNAL, status.error_code());
  908. }
  909. TEST_P(ProtostreamObjectSourceTimestampTest, InvalidDurationBelowMinTest) {
  910. TimestampDuration out;
  911. google::protobuf::Duration* dur = out.mutable_dur();
  912. // Min allowed seconds - 1
  913. dur->set_seconds(kDurationMinSeconds - 1);
  914. ow_.StartObject("");
  915. Status status = ExecuteTest(out, TimestampDuration::descriptor());
  916. EXPECT_EQ(util::error::INTERNAL, status.error_code());
  917. }
  918. TEST_P(ProtostreamObjectSourceTimestampTest, InvalidDurationAboveMaxTest) {
  919. TimestampDuration out;
  920. google::protobuf::Duration* dur = out.mutable_dur();
  921. // Min allowed seconds + 1
  922. dur->set_seconds(kDurationMaxSeconds + 1);
  923. ow_.StartObject("");
  924. Status status = ExecuteTest(out, TimestampDuration::descriptor());
  925. EXPECT_EQ(util::error::INTERNAL, status.error_code());
  926. }
  927. TEST_P(ProtostreamObjectSourceTimestampTest, TimestampDurationDefaultValue) {
  928. TimestampDuration out;
  929. out.mutable_ts()->set_seconds(0);
  930. out.mutable_dur()->set_seconds(0);
  931. ow_.StartObject("")
  932. ->RenderString("ts", "1970-01-01T00:00:00Z")
  933. ->RenderString("dur", "0s")
  934. ->EndObject();
  935. DoTest(out, TimestampDuration::descriptor());
  936. }
  937. } // namespace converter
  938. } // namespace util
  939. } // namespace protobuf
  940. } // namespace google