protostream_objectsource_test.cc 33 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087
  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