objectserializer_test.js 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595
  1. // Copyright 2008 The Closure Library Authors. All Rights Reserved.
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS-IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. goog.provide('goog.proto2.ObjectSerializerTest');
  15. goog.setTestOnly('goog.proto2.ObjectSerializerTest');
  16. goog.require('goog.proto2.ObjectSerializer');
  17. goog.require('goog.proto2.Serializer');
  18. goog.require('goog.testing.PropertyReplacer');
  19. goog.require('goog.testing.jsunit');
  20. goog.require('proto2.TestAllTypes');
  21. var propertyReplacer = new goog.testing.PropertyReplacer();
  22. function tearDown() {
  23. propertyReplacer.reset();
  24. }
  25. function testSerialization() {
  26. var message = new proto2.TestAllTypes();
  27. // Set the fields.
  28. // Singular.
  29. message.setOptionalInt32(101);
  30. message.setOptionalInt64('102');
  31. message.setOptionalUint32(103);
  32. message.setOptionalUint64('104');
  33. message.setOptionalSint32(105);
  34. message.setOptionalSint64('106');
  35. message.setOptionalFixed32(107);
  36. message.setOptionalFixed64('108');
  37. message.setOptionalSfixed32(109);
  38. message.setOptionalSfixed64('110');
  39. message.setOptionalFloat(111.5);
  40. message.setOptionalDouble(112.5);
  41. message.setOptionalBool(true);
  42. message.setOptionalString('test');
  43. message.setOptionalBytes('abcd');
  44. var group = new proto2.TestAllTypes.OptionalGroup();
  45. group.setA(111);
  46. message.setOptionalgroup(group);
  47. var nestedMessage = new proto2.TestAllTypes.NestedMessage();
  48. nestedMessage.setB(112);
  49. message.setOptionalNestedMessage(nestedMessage);
  50. message.setOptionalNestedEnum(proto2.TestAllTypes.NestedEnum.FOO);
  51. // Repeated.
  52. message.addRepeatedInt32(201);
  53. message.addRepeatedInt32(202);
  54. // Serialize to a simplified object.
  55. var simplified = new goog.proto2.ObjectSerializer().serialize(message);
  56. // Assert that everything serialized properly.
  57. assertEquals(101, simplified[1]);
  58. assertEquals('102', simplified[2]);
  59. assertEquals(103, simplified[3]);
  60. assertEquals('104', simplified[4]);
  61. assertEquals(105, simplified[5]);
  62. assertEquals('106', simplified[6]);
  63. assertEquals(107, simplified[7]);
  64. assertEquals('108', simplified[8]);
  65. assertEquals(109, simplified[9]);
  66. assertEquals('110', simplified[10]);
  67. assertEquals(111.5, simplified[11]);
  68. assertEquals(112.5, simplified[12]);
  69. assertEquals(true, simplified[13]);
  70. assertEquals('test', simplified[14]);
  71. assertEquals('abcd', simplified[15]);
  72. assertEquals(111, simplified[16][17]);
  73. assertEquals(112, simplified[18][1]);
  74. assertEquals(proto2.TestAllTypes.NestedEnum.FOO, simplified[21]);
  75. assertEquals(201, simplified[31][0]);
  76. assertEquals(202, simplified[31][1]);
  77. // Serialize to a simplified object (with key as name).
  78. simplified =
  79. new goog.proto2
  80. .ObjectSerializer(goog.proto2.ObjectSerializer.KeyOption.NAME)
  81. .serialize(message);
  82. // Assert that everything serialized properly.
  83. assertEquals(101, simplified['optional_int32']);
  84. assertEquals('102', simplified['optional_int64']);
  85. assertEquals(103, simplified['optional_uint32']);
  86. assertEquals('104', simplified['optional_uint64']);
  87. assertEquals(105, simplified['optional_sint32']);
  88. assertEquals('106', simplified['optional_sint64']);
  89. assertEquals(107, simplified['optional_fixed32']);
  90. assertEquals('108', simplified['optional_fixed64']);
  91. assertEquals(109, simplified['optional_sfixed32']);
  92. assertEquals('110', simplified['optional_sfixed64']);
  93. assertEquals(111.5, simplified['optional_float']);
  94. assertEquals(112.5, simplified['optional_double']);
  95. assertEquals(true, simplified['optional_bool']);
  96. assertEquals('test', simplified['optional_string']);
  97. assertEquals('abcd', simplified['optional_bytes']);
  98. assertEquals(111, simplified['optionalgroup']['a']);
  99. assertEquals(112, simplified['optional_nested_message']['b']);
  100. assertEquals(
  101. proto2.TestAllTypes.NestedEnum.FOO, simplified['optional_nested_enum']);
  102. assertEquals(201, simplified['repeated_int32'][0]);
  103. assertEquals(202, simplified['repeated_int32'][1]);
  104. }
  105. function testSerializationOfUnknown() {
  106. var message = new proto2.TestAllTypes();
  107. // Set the fields.
  108. // Known.
  109. message.setOptionalInt32(101);
  110. message.setOptionalInt64('102');
  111. message.addRepeatedInt32(201);
  112. message.addRepeatedInt32(202);
  113. // Unknown.
  114. message.setUnknown(1000, 301);
  115. message.setUnknown(1001, 302);
  116. // Serialize.
  117. var simplified = new goog.proto2.ObjectSerializer().serialize(message);
  118. assertEquals(101, simplified['1']);
  119. assertEquals('102', simplified['2']);
  120. assertEquals(201, simplified['31'][0]);
  121. assertEquals(202, simplified['31'][1]);
  122. assertEquals(301, simplified['1000']);
  123. assertEquals(302, simplified['1001']);
  124. }
  125. function testDeserializationOfUnknown() {
  126. var simplified = {1: 101, 2: '102', 1000: 103, 1001: 104};
  127. var serializer = new goog.proto2.ObjectSerializer();
  128. var message =
  129. serializer.deserialize(proto2.TestAllTypes.getDescriptor(), simplified);
  130. assertNotNull(message);
  131. assertTrue(message.hasOptionalInt32());
  132. assertTrue(message.hasOptionalInt64());
  133. assertEquals(101, message.getOptionalInt32());
  134. assertEquals('102', message.getOptionalInt64());
  135. var count = 0;
  136. message.forEachUnknown(function(tag, value) {
  137. if (tag == 1000) {
  138. assertEquals(103, value);
  139. }
  140. if (tag == 1001) {
  141. assertEquals(104, value);
  142. }
  143. ++count;
  144. });
  145. assertEquals(2, count);
  146. }
  147. function testDeserializationRepeated() {
  148. var simplified = {
  149. 31: [101, 102],
  150. 41: [201.5, 202.5, 203.5],
  151. 42: [],
  152. 43: [true, false],
  153. 44: ['he', 'llo'],
  154. 46: [{47: [101]}, {47: [102]}],
  155. 48: [{1: 201}, {1: 202}]
  156. };
  157. var serializer = new goog.proto2.ObjectSerializer();
  158. var message =
  159. serializer.deserialize(proto2.TestAllTypes.getDescriptor(), simplified);
  160. assertNotNull(message);
  161. // Ensure the fields are set as expected.
  162. assertTrue(message.hasRepeatedInt32());
  163. assertTrue(message.hasRepeatedFloat());
  164. assertFalse(message.hasRepeatedDouble());
  165. assertTrue(message.hasRepeatedBool());
  166. assertTrue(message.hasRepeatedgroup());
  167. assertTrue(message.hasRepeatedNestedMessage());
  168. // Ensure the counts match.
  169. assertEquals(2, message.repeatedInt32Count());
  170. assertEquals(3, message.repeatedFloatCount());
  171. assertEquals(0, message.repeatedDoubleCount());
  172. assertEquals(2, message.repeatedBoolCount());
  173. assertEquals(2, message.repeatedStringCount());
  174. assertEquals(2, message.repeatedgroupCount());
  175. assertEquals(2, message.repeatedNestedMessageCount());
  176. // Ensure the values match.
  177. assertEquals(101, message.getRepeatedInt32(0));
  178. assertEquals(102, message.getRepeatedInt32(1));
  179. assertEquals(201.5, message.getRepeatedFloat(0));
  180. assertEquals(202.5, message.getRepeatedFloat(1));
  181. assertEquals(203.5, message.getRepeatedFloat(2));
  182. assertEquals(true, message.getRepeatedBool(0));
  183. assertEquals(false, message.getRepeatedBool(1));
  184. assertEquals('he', message.getRepeatedString(0));
  185. assertEquals('llo', message.getRepeatedString(1));
  186. assertEquals(101, message.getRepeatedgroup(0).getA(0));
  187. assertEquals(102, message.getRepeatedgroup(1).getA(0));
  188. assertEquals(201, message.getRepeatedNestedMessage(0).getB());
  189. assertEquals(202, message.getRepeatedNestedMessage(1).getB());
  190. }
  191. function testDeserialization() {
  192. var simplified = {
  193. 1: 101,
  194. 2: '102',
  195. 3: 103,
  196. 4: '104',
  197. 5: 105,
  198. 6: '106',
  199. 7: 107,
  200. 8: '108',
  201. 9: 109,
  202. 10: '110',
  203. 11: 111.5,
  204. 12: 112.5,
  205. 13: true,
  206. 14: 'test',
  207. 15: 'abcd',
  208. 16: {17: 113},
  209. 18: {1: 114},
  210. 21: proto2.TestAllTypes.NestedEnum.FOO
  211. };
  212. var serializer = new goog.proto2.ObjectSerializer();
  213. var message =
  214. serializer.deserialize(proto2.TestAllTypes.getDescriptor(), simplified);
  215. assertNotNull(message);
  216. assertTrue(message.hasOptionalInt32());
  217. assertTrue(message.hasOptionalInt64());
  218. assertTrue(message.hasOptionalUint32());
  219. assertTrue(message.hasOptionalUint64());
  220. assertTrue(message.hasOptionalSint32());
  221. assertTrue(message.hasOptionalSint64());
  222. assertTrue(message.hasOptionalFixed32());
  223. assertTrue(message.hasOptionalFixed64());
  224. assertTrue(message.hasOptionalSfixed32());
  225. assertTrue(message.hasOptionalSfixed64());
  226. assertTrue(message.hasOptionalFloat());
  227. assertTrue(message.hasOptionalDouble());
  228. assertTrue(message.hasOptionalBool());
  229. assertTrue(message.hasOptionalString());
  230. assertTrue(message.hasOptionalBytes());
  231. assertTrue(message.hasOptionalgroup());
  232. assertTrue(message.hasOptionalNestedMessage());
  233. assertTrue(message.hasOptionalNestedEnum());
  234. assertEquals(1, message.optionalInt32Count());
  235. assertEquals(1, message.optionalInt64Count());
  236. assertEquals(1, message.optionalUint32Count());
  237. assertEquals(1, message.optionalUint64Count());
  238. assertEquals(1, message.optionalSint32Count());
  239. assertEquals(1, message.optionalSint64Count());
  240. assertEquals(1, message.optionalFixed32Count());
  241. assertEquals(1, message.optionalFixed64Count());
  242. assertEquals(1, message.optionalSfixed32Count());
  243. assertEquals(1, message.optionalSfixed64Count());
  244. assertEquals(1, message.optionalFloatCount());
  245. assertEquals(1, message.optionalDoubleCount());
  246. assertEquals(1, message.optionalBoolCount());
  247. assertEquals(1, message.optionalStringCount());
  248. assertEquals(1, message.optionalBytesCount());
  249. assertEquals(1, message.optionalgroupCount());
  250. assertEquals(1, message.optionalNestedMessageCount());
  251. assertEquals(1, message.optionalNestedEnumCount());
  252. assertEquals(101, message.getOptionalInt32());
  253. assertEquals('102', message.getOptionalInt64());
  254. assertEquals(103, message.getOptionalUint32());
  255. assertEquals('104', message.getOptionalUint64());
  256. assertEquals(105, message.getOptionalSint32());
  257. assertEquals('106', message.getOptionalSint64());
  258. assertEquals(107, message.getOptionalFixed32());
  259. assertEquals('108', message.getOptionalFixed64());
  260. assertEquals(109, message.getOptionalSfixed32());
  261. assertEquals('110', message.getOptionalSfixed64());
  262. assertEquals(111.5, message.getOptionalFloat());
  263. assertEquals(112.5, message.getOptionalDouble());
  264. assertEquals(true, message.getOptionalBool());
  265. assertEquals('test', message.getOptionalString());
  266. assertEquals('abcd', message.getOptionalBytes());
  267. assertEquals(113, message.getOptionalgroup().getA());
  268. assertEquals(114, message.getOptionalNestedMessage().getB());
  269. assertEquals(
  270. proto2.TestAllTypes.NestedEnum.FOO, message.getOptionalNestedEnum());
  271. }
  272. function testDeserializationUnknownEnumValue() {
  273. var simplified = {21: 1001};
  274. var serializer = new goog.proto2.ObjectSerializer();
  275. var message =
  276. serializer.deserialize(proto2.TestAllTypes.getDescriptor(), simplified);
  277. assertNotNull(message);
  278. assertEquals(1001, message.getOptionalNestedEnum());
  279. }
  280. function testDeserializationSymbolicEnumValue() {
  281. var simplified = {21: 'BAR'};
  282. propertyReplacer.set(goog.proto2.Serializer, 'DECODE_SYMBOLIC_ENUMS', true);
  283. var serializer = new goog.proto2.ObjectSerializer();
  284. var message =
  285. serializer.deserialize(proto2.TestAllTypes.getDescriptor(), simplified);
  286. assertNotNull(message);
  287. assertEquals(
  288. proto2.TestAllTypes.NestedEnum.BAR, message.getOptionalNestedEnum());
  289. }
  290. function testDeserializationSymbolicEnumValueTurnedOff() {
  291. var simplified = {21: 'BAR'};
  292. var serializer = new goog.proto2.ObjectSerializer();
  293. assertThrows(
  294. 'Should have an assertion failure in deserialization', function() {
  295. serializer.deserialize(proto2.TestAllTypes.getDescriptor(), simplified);
  296. });
  297. }
  298. function testDeserializationUnknownSymbolicEnumValue() {
  299. var simplified = {21: 'BARRED'};
  300. var serializer = new goog.proto2.ObjectSerializer();
  301. assertThrows(
  302. 'Should have an assertion failure in deserialization', function() {
  303. serializer.deserialize(proto2.TestAllTypes.getDescriptor(), simplified);
  304. });
  305. }
  306. function testDeserializationEnumValueAsNumericString() {
  307. var simplified = {21: '2'};
  308. var serializer = new goog.proto2.ObjectSerializer();
  309. var message =
  310. serializer.deserialize(proto2.TestAllTypes.getDescriptor(), simplified);
  311. assertNotNull(message);
  312. assertEquals(
  313. proto2.TestAllTypes.NestedEnum.BAR, message.getOptionalNestedEnum());
  314. }
  315. function testDeserializationEnumValueWithNegativeString() {
  316. var simplified = {21: '-2'};
  317. var serializer = new goog.proto2.ObjectSerializer();
  318. assertThrows(
  319. 'Should have an assertion failure in deserialization', function() {
  320. serializer.deserialize(proto2.TestAllTypes.getDescriptor(), simplified);
  321. });
  322. }
  323. function testDeserializationNumbersOrStrings() {
  324. // 64-bit types may have been serialized as numbers or strings.
  325. // Deserialization should be able to handle either.
  326. var simplifiedWithNumbers =
  327. {50: 5000, 51: 5100, 52: [5200, 5201], 53: [5300, 5301]};
  328. var simplifiedWithStrings =
  329. {50: '5000', 51: '5100', 52: ['5200', '5201'], 53: ['5300', '5301']};
  330. var serializer = new goog.proto2.ObjectSerializer();
  331. var message = serializer.deserialize(
  332. proto2.TestAllTypes.getDescriptor(), simplifiedWithNumbers);
  333. assertNotNull(message);
  334. assertEquals(5000, message.getOptionalInt64Number());
  335. assertEquals('5100', message.getOptionalInt64String());
  336. assertEquals(5200, message.getRepeatedInt64Number(0));
  337. assertEquals(5201, message.getRepeatedInt64Number(1));
  338. assertEquals('5300', message.getRepeatedInt64String(0));
  339. assertEquals('5301', message.getRepeatedInt64String(1));
  340. assertArrayEquals([5200, 5201], message.repeatedInt64NumberArray());
  341. assertArrayEquals(['5300', '5301'], message.repeatedInt64StringArray());
  342. message = serializer.deserialize(
  343. proto2.TestAllTypes.getDescriptor(), simplifiedWithStrings);
  344. assertNotNull(message);
  345. assertEquals(5000, message.getOptionalInt64Number());
  346. assertEquals('5100', message.getOptionalInt64String());
  347. assertEquals(5200, message.getRepeatedInt64Number(0));
  348. assertEquals(5201, message.getRepeatedInt64Number(1));
  349. assertEquals('5300', message.getRepeatedInt64String(0));
  350. assertEquals('5301', message.getRepeatedInt64String(1));
  351. assertArrayEquals([5200, 5201], message.repeatedInt64NumberArray());
  352. assertArrayEquals(['5300', '5301'], message.repeatedInt64StringArray());
  353. }
  354. function testSerializationSpecialFloatDoubleValues() {
  355. // NaN, Infinity and -Infinity should get serialized as strings.
  356. var message = new proto2.TestAllTypes();
  357. message.setOptionalFloat(Infinity);
  358. message.setOptionalDouble(-Infinity);
  359. message.addRepeatedFloat(Infinity);
  360. message.addRepeatedFloat(-Infinity);
  361. message.addRepeatedFloat(NaN);
  362. message.addRepeatedDouble(Infinity);
  363. message.addRepeatedDouble(-Infinity);
  364. message.addRepeatedDouble(NaN);
  365. var simplified = new goog.proto2.ObjectSerializer().serialize(message);
  366. // Assert that everything serialized properly.
  367. assertEquals('Infinity', simplified[11]);
  368. assertEquals('-Infinity', simplified[12]);
  369. assertEquals('Infinity', simplified[41][0]);
  370. assertEquals('-Infinity', simplified[41][1]);
  371. assertEquals('NaN', simplified[41][2]);
  372. assertEquals('Infinity', simplified[42][0]);
  373. assertEquals('-Infinity', simplified[42][1]);
  374. assertEquals('NaN', simplified[42][2]);
  375. }
  376. function testDeserializationSpecialFloatDoubleValues() {
  377. // NaN, Infinity and -Infinity values should be de-serialized from their
  378. // string representation.
  379. var simplified = {
  380. 41: ['Infinity', '-Infinity', 'NaN'],
  381. 42: ['Infinity', '-Infinity', 'NaN']
  382. };
  383. var serializer = new goog.proto2.ObjectSerializer();
  384. var message =
  385. serializer.deserialize(proto2.TestAllTypes.getDescriptor(), simplified);
  386. assertNotNull(message);
  387. var floatArray = message.repeatedFloatArray();
  388. assertEquals(Infinity, floatArray[0]);
  389. assertEquals(-Infinity, floatArray[1]);
  390. assertTrue(isNaN(floatArray[2]));
  391. var doubleArray = message.repeatedDoubleArray();
  392. assertEquals(Infinity, doubleArray[0]);
  393. assertEquals(-Infinity, doubleArray[1]);
  394. assertTrue(isNaN(doubleArray[2]));
  395. }
  396. function testDeserializationConversionProhibited() {
  397. // 64-bit types may have been serialized as numbers or strings.
  398. // But 32-bit types must be serialized as numbers.
  399. // Test deserialization fails on 32-bit numbers as strings.
  400. var simplified = {
  401. 1: '1000' // optionalInt32
  402. };
  403. var serializer = new goog.proto2.ObjectSerializer();
  404. assertThrows(
  405. 'Should have an assertion failure in deserialization', function() {
  406. serializer.deserialize(proto2.TestAllTypes.getDescriptor(), simplified);
  407. });
  408. }
  409. function testDefaultValueNumbersOrStrings() {
  410. // 64-bit types may have been serialized as numbers or strings.
  411. // The default values should have the correct type.
  412. var serializer = new goog.proto2.ObjectSerializer();
  413. var message = serializer.deserialize(proto2.TestAllTypes.getDescriptor(), {});
  414. assertNotNull(message);
  415. // Default when using Number is a number, and precision is lost.
  416. var value = message.getOptionalInt64NumberOrDefault();
  417. assertTrue('Expecting a number', typeof value === 'number');
  418. assertEquals(1000000000000000000, value);
  419. assertEquals(1000000000000000001, value);
  420. assertEquals(1000000000000000002, value);
  421. assertEquals('1000000000000000000', String(value)); // Value is rounded!
  422. // When using a String, the value is preserved.
  423. assertEquals(
  424. '1000000000000000001', message.getOptionalInt64StringOrDefault());
  425. }
  426. function testSerializationBooleanAsNumberFalse() {
  427. // Some libraries, such as GWT, can expect boolean field values as 0/1
  428. var message = new proto2.TestAllTypes();
  429. message.setOptionalBool(false);
  430. var serializer = new goog.proto2.ObjectSerializer(
  431. goog.proto2.ObjectSerializer.KeyOption.TAG,
  432. true /* opt_serializeBooleanAsNumber */);
  433. var simplified = serializer.serialize(message);
  434. assertEquals(0, simplified[13]);
  435. }
  436. function testSerializationBooleanAsNumberTrue() {
  437. var message = new proto2.TestAllTypes();
  438. message.setOptionalBool(true);
  439. var serializer = new goog.proto2.ObjectSerializer(
  440. goog.proto2.ObjectSerializer.KeyOption.TAG,
  441. true /* opt_serializeBooleanAsNumber */);
  442. var simplified = serializer.serialize(message);
  443. assertEquals(1, simplified[13]);
  444. }
  445. function testDeserializationBooleanAsNumberFalse() {
  446. // Some libraries, such as GWT, can serialize boolean values as 0/1
  447. var simplified = {13: 0};
  448. var serializer = new goog.proto2.ObjectSerializer();
  449. var message =
  450. serializer.deserialize(proto2.TestAllTypes.getDescriptor(), simplified);
  451. assertNotNull(message);
  452. assertFalse(message.getOptionalBool());
  453. }
  454. function testDeserializationBooleanAsNumberTrue() {
  455. var simplified = {13: 1};
  456. var serializer = new goog.proto2.ObjectSerializer();
  457. var message =
  458. serializer.deserialize(proto2.TestAllTypes.getDescriptor(), simplified);
  459. assertNotNull(message);
  460. assertTrue(message.getOptionalBool());
  461. }