message_test.js 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493
  1. // Copyright 2010 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.MessageTest');
  15. goog.setTestOnly('goog.proto2.MessageTest');
  16. goog.require('goog.testing.TestCase');
  17. goog.require('goog.testing.jsunit');
  18. goog.require('proto2.TestAllTypes');
  19. goog.require('proto2.TestAllTypes.NestedEnum');
  20. goog.require('proto2.TestAllTypes.NestedMessage');
  21. goog.require('proto2.TestAllTypes.OptionalGroup');
  22. goog.require('proto2.TestAllTypes.RepeatedGroup');
  23. function setUp() {
  24. // TODO(b/25875505): Fix unreported assertions (go/failonunreportedasserts).
  25. goog.testing.TestCase.getActiveTestCase().failOnUnreportedAsserts = false;
  26. }
  27. function testEqualsWithEmptyMessages() {
  28. var message1 = new proto2.TestAllTypes();
  29. assertTrue('same message object', message1.equals(message1));
  30. assertFalse('comparison with null', message1.equals(null));
  31. assertFalse('comparison with undefined', message1.equals(undefined));
  32. var message2 = new proto2.TestAllTypes();
  33. assertTrue('two empty message objects', message1.equals(message2));
  34. var message3 = new proto2.TestAllTypes.NestedMessage();
  35. assertFalse('different message types', message3.equals(message1));
  36. }
  37. function testEqualsWithSingleInt32Field() {
  38. var message1 = new proto2.TestAllTypes();
  39. var message2 = new proto2.TestAllTypes();
  40. message1.setOptionalInt32(1);
  41. assertFalse('message1 has an extra int32 field', message1.equals(message2));
  42. message2.setOptionalInt32(1);
  43. assertTrue('same int32 field in both messages', message1.equals(message2));
  44. message2.setOptionalInt32(2);
  45. assertFalse('different int32 field', message1.equals(message2));
  46. message1.clearOptionalInt32();
  47. assertFalse('message2 has an extra int32 field', message1.equals(message2));
  48. }
  49. function testEqualsWithRepeatedInt32Fields() {
  50. var message1 = new proto2.TestAllTypes();
  51. var message2 = new proto2.TestAllTypes();
  52. message1.addRepeatedInt32(0);
  53. message2.addRepeatedInt32(0);
  54. assertTrue('equal repeated int32 field', message1.equals(message2));
  55. message1.addRepeatedInt32(1);
  56. assertFalse('message1 has more items', message1.equals(message2));
  57. message2.addRepeatedInt32(1);
  58. message2.addRepeatedInt32(1);
  59. assertFalse('message2 has more items', message1.equals(message2));
  60. message1.addRepeatedInt32(2);
  61. assertFalse('different int32 items', message1.equals(message2));
  62. }
  63. function testEqualsWithDefaultValue() {
  64. var message1 = new proto2.TestAllTypes();
  65. var message2 = new proto2.TestAllTypes();
  66. message1.setOptionalInt64('1');
  67. assertEquals(
  68. 'message1.getOptionalInt64OrDefault should return 1', '1',
  69. message1.getOptionalInt64OrDefault());
  70. assertEquals(
  71. 'message2.getOptionalInt64OrDefault should return 1 too', '1',
  72. message2.getOptionalInt64OrDefault());
  73. assertTrue(
  74. 'message1.hasOptionalInt64() should be true',
  75. message1.hasOptionalInt64());
  76. assertFalse(
  77. 'message2.hasOptionalInt64() should be false',
  78. message2.hasOptionalInt64());
  79. assertFalse('as a result they are not equal', message1.equals(message2));
  80. }
  81. function testEqualsWithOptionalGroup() {
  82. var message1 = new proto2.TestAllTypes();
  83. var message2 = new proto2.TestAllTypes();
  84. var group1 = new proto2.TestAllTypes.OptionalGroup();
  85. var group2 = new proto2.TestAllTypes.OptionalGroup();
  86. message1.setOptionalgroup(group1);
  87. assertFalse(
  88. 'only message1 has OptionalGroup field', message1.equals(message2));
  89. message2.setOptionalgroup(group2);
  90. assertTrue(
  91. 'both messages have OptionalGroup field', message1.equals(message2));
  92. group1.setA(0);
  93. group2.setA(1);
  94. assertFalse(
  95. 'different value in the optional group', message1.equals(message2));
  96. message1.clearOptionalgroup();
  97. assertFalse(
  98. 'only message2 has OptionalGroup field', message1.equals(message2));
  99. }
  100. function testEqualsWithRepeatedGroup() {
  101. var message1 = new proto2.TestAllTypes();
  102. var message2 = new proto2.TestAllTypes();
  103. var group1 = new proto2.TestAllTypes.RepeatedGroup();
  104. var group2 = new proto2.TestAllTypes.RepeatedGroup();
  105. message1.addRepeatedgroup(group1);
  106. assertFalse('message1 has more RepeatedGroups', message1.equals(message2));
  107. message2.addRepeatedgroup(group2);
  108. assertTrue('both messages have one RepeatedGroup', message1.equals(message2));
  109. group1.addA(1);
  110. assertFalse(
  111. 'message1 has more int32s in RepeatedGroup', message1.equals(message2));
  112. group2.addA(1);
  113. assertTrue(
  114. 'both messages have one int32 in RepeatedGroup',
  115. message1.equals(message2));
  116. group1.addA(1);
  117. group2.addA(2);
  118. assertFalse(
  119. 'the messages have different int32s in RepeatedGroup',
  120. message1.equals(message2));
  121. }
  122. function testEqualsWithNestedMessage() {
  123. var message1 = new proto2.TestAllTypes();
  124. var message2 = new proto2.TestAllTypes();
  125. var nested1 = new proto2.TestAllTypes.NestedMessage();
  126. var nested2 = new proto2.TestAllTypes.NestedMessage();
  127. message1.setOptionalNestedMessage(nested1);
  128. assertFalse('only message1 has nested message', message1.equals(message2));
  129. message2.setOptionalNestedMessage(nested2);
  130. assertTrue('both messages have nested message', message1.equals(message2));
  131. nested1.setB(1);
  132. assertFalse(
  133. 'different int32 in the nested messages', message1.equals(message2));
  134. message1.clearOptionalNestedMessage();
  135. assertFalse('only message2 has nested message', message1.equals(message2));
  136. }
  137. function testEqualsWithNestedEnum() {
  138. var message1 = new proto2.TestAllTypes();
  139. var message2 = new proto2.TestAllTypes();
  140. message1.setOptionalNestedEnum(proto2.TestAllTypes.NestedEnum.FOO);
  141. assertFalse('only message1 has nested enum', message1.equals(message2));
  142. message2.setOptionalNestedEnum(proto2.TestAllTypes.NestedEnum.FOO);
  143. assertTrue('both messages have nested enum', message1.equals(message2));
  144. message2.setOptionalNestedEnum(proto2.TestAllTypes.NestedEnum.BAR);
  145. assertFalse('different enum value', message1.equals(message2));
  146. message1.clearOptionalNestedEnum();
  147. assertFalse('only message2 has nested enum', message1.equals(message2));
  148. }
  149. function testEqualsWithUnknownFields() {
  150. var message1 = new proto2.TestAllTypes();
  151. var message2 = new proto2.TestAllTypes();
  152. message1.setUnknown(999, 'foo');
  153. message1.setUnknown(999, 'bar');
  154. assertTrue('unknown fields are ignored', message1.equals(message2));
  155. }
  156. function testCloneEmptyMessage() {
  157. var message = new proto2.TestAllTypes();
  158. var clone = message.clone();
  159. assertObjectEquals('cloned empty message', message, clone);
  160. }
  161. function testCloneMessageWithSeveralFields() {
  162. var message = new proto2.TestAllTypes();
  163. message.setOptionalInt32(1);
  164. message.addRepeatedInt32(2);
  165. var optionalGroup = new proto2.TestAllTypes.OptionalGroup();
  166. optionalGroup.setA(3);
  167. message.setOptionalgroup(optionalGroup);
  168. var repeatedGroup = new proto2.TestAllTypes.RepeatedGroup();
  169. repeatedGroup.addA(4);
  170. message.addRepeatedgroup(repeatedGroup);
  171. var nestedMessage = new proto2.TestAllTypes.NestedMessage();
  172. nestedMessage.setB(5);
  173. message.setOptionalNestedMessage(nestedMessage);
  174. message.setOptionalNestedEnum(proto2.TestAllTypes.NestedEnum.FOO);
  175. message.setUnknown(999, 'foo');
  176. var clone = message.clone();
  177. assertNotEquals(
  178. 'different OptionalGroup instance', message.getOptionalgroup(),
  179. clone.getOptionalgroup());
  180. assertNotEquals(
  181. 'different RepeatedGroup array instance', message.repeatedgroupArray(),
  182. clone.repeatedgroupArray());
  183. assertNotEquals(
  184. 'different RepeatedGroup array item instance',
  185. message.getRepeatedgroup(0), clone.getRepeatedgroup(0));
  186. assertNotEquals(
  187. 'different NestedMessage instance', message.getOptionalNestedMessage(),
  188. clone.getOptionalNestedMessage());
  189. }
  190. function testCloneWithUnknownFields() {
  191. var message = new proto2.TestAllTypes();
  192. message.setUnknown(999, 'foo');
  193. var clone = message.clone();
  194. assertTrue('clone.equals(message) returns true', clone.equals(message));
  195. clone.forEachUnknown(function(tag, value) {
  196. fail('the unknown fields should not have been cloned');
  197. });
  198. clone.setUnknown(999, 'foo');
  199. assertObjectEquals(
  200. 'the original and the cloned message are equal except ' +
  201. 'for the unknown fields',
  202. message, clone);
  203. }
  204. function testCopyFromSameMessage() {
  205. var source = new proto2.TestAllTypes();
  206. source.setOptionalInt32(32);
  207. source.copyFrom(source);
  208. assertEquals(32, source.getOptionalInt32());
  209. }
  210. function testCopyFromFlatMessage() {
  211. // Recursive copying is implicitly tested in the testClone... methods.
  212. var source = new proto2.TestAllTypes();
  213. source.setOptionalInt32(32);
  214. source.setOptionalInt64('64');
  215. source.addRepeatedInt32(32);
  216. var target = new proto2.TestAllTypes();
  217. target.setOptionalInt32(33);
  218. target.setOptionalUint32(33);
  219. target.addRepeatedInt32(33);
  220. target.copyFrom(source);
  221. assertObjectEquals(
  222. 'source and target are equal after copyFrom', source, target);
  223. target.copyFrom(source);
  224. assertObjectEquals('second copyFrom call has no effect', source, target);
  225. source.setUnknown(999, 'foo');
  226. target.setUnknown(999, 'bar');
  227. target.copyFrom(source);
  228. assertThrows(
  229. 'unknown fields are not copied',
  230. goog.partial(assertObjectEquals, source, target));
  231. }
  232. function testMergeFromEmptyMessage() {
  233. var source = new proto2.TestAllTypes();
  234. source.setOptionalInt32(32);
  235. source.setOptionalInt64('64');
  236. var nested = new proto2.TestAllTypes.NestedMessage();
  237. nested.setB(66);
  238. source.setOptionalNestedMessage(nested);
  239. var target = new proto2.TestAllTypes();
  240. target.mergeFrom(source);
  241. assertObjectEquals(
  242. 'source and target are equal after mergeFrom', source, target);
  243. }
  244. function testMergeFromFlatMessage() {
  245. var source = new proto2.TestAllTypes();
  246. source.setOptionalInt32(32);
  247. source.setOptionalString('foo');
  248. source.setOptionalNestedEnum(proto2.TestAllTypes.NestedEnum.FOO);
  249. var target = new proto2.TestAllTypes();
  250. target.setOptionalInt64('64');
  251. target.setOptionalString('bar');
  252. target.setOptionalNestedEnum(proto2.TestAllTypes.NestedEnum.BAR);
  253. var expected = new proto2.TestAllTypes();
  254. expected.setOptionalInt32(32);
  255. expected.setOptionalInt64('64');
  256. expected.setOptionalString('foo');
  257. expected.setOptionalNestedEnum(proto2.TestAllTypes.NestedEnum.FOO);
  258. target.mergeFrom(source);
  259. assertObjectEquals(
  260. 'expected and target are equal after mergeFrom', expected, target);
  261. }
  262. function testMergeFromNestedMessage() {
  263. var source = new proto2.TestAllTypes();
  264. var nested = new proto2.TestAllTypes.NestedMessage();
  265. nested.setB(66);
  266. source.setOptionalNestedMessage(nested);
  267. var target = new proto2.TestAllTypes();
  268. nested = new proto2.TestAllTypes.NestedMessage();
  269. nested.setC(77);
  270. target.setOptionalNestedMessage(nested);
  271. var expected = new proto2.TestAllTypes();
  272. nested = new proto2.TestAllTypes.NestedMessage();
  273. nested.setB(66);
  274. nested.setC(77);
  275. expected.setOptionalNestedMessage(nested);
  276. target.mergeFrom(source);
  277. assertObjectEquals(
  278. 'expected and target are equal after mergeFrom', expected, target);
  279. }
  280. function testMergeFromRepeatedMessage() {
  281. var source = new proto2.TestAllTypes();
  282. source.addRepeatedInt32(2);
  283. source.addRepeatedInt32(3);
  284. var target = new proto2.TestAllTypes();
  285. target.addRepeatedInt32(1);
  286. target.mergeFrom(source);
  287. assertArrayEquals(
  288. 'repeated_int32 array has elements from both messages', [1, 2, 3],
  289. target.repeatedInt32Array());
  290. }
  291. function testInitDefaultsWithEmptyMessage() {
  292. var message = new proto2.TestAllTypes();
  293. message.initDefaults(false);
  294. assertFalse('int32 field is not set', message.hasOptionalInt32());
  295. assertFalse('int64 [default=1] field is not set', message.hasOptionalInt64());
  296. assertTrue('optional group field is set', message.hasOptionalgroup());
  297. assertFalse(
  298. 'int32 inside the group is not set', message.getOptionalgroup().hasA());
  299. assertObjectEquals(
  300. 'value of the optional group', new proto2.TestAllTypes.OptionalGroup(),
  301. message.getOptionalgroup());
  302. assertTrue('nested message is set', message.hasOptionalNestedMessage());
  303. assertObjectEquals(
  304. 'value of the nested message', new proto2.TestAllTypes.NestedMessage(),
  305. message.getOptionalNestedMessage());
  306. assertFalse('nested enum is not set', message.hasOptionalNestedEnum());
  307. assertFalse('repeated int32 is not set', message.hasRepeatedInt32());
  308. assertFalse(
  309. 'repeated nested message is not set', message.hasRepeatedNestedMessage());
  310. message = new proto2.TestAllTypes();
  311. message.initDefaults(true);
  312. assertTrue('int32 field is set', message.hasOptionalInt32());
  313. assertEquals('value of the int32 field', 0, message.getOptionalInt32());
  314. assertTrue('int64 [default=1] field is set', message.hasOptionalInt64());
  315. assertEquals('value of the int64 field', '1', message.getOptionalInt64());
  316. assertTrue(
  317. 'int32 inside nested message is set',
  318. message.getOptionalNestedMessage().hasB());
  319. assertEquals(
  320. 'value of the int32 field inside the nested message', 0,
  321. message.getOptionalNestedMessage().getB());
  322. }
  323. function testInitDefaultsWithNonEmptyMessage() {
  324. var message = new proto2.TestAllTypes();
  325. message.setOptionalInt32(32);
  326. message.setOptionalInt64('64');
  327. message.setOptionalgroup(new proto2.TestAllTypes.OptionalGroup());
  328. var nested1 = new proto2.TestAllTypes.NestedMessage();
  329. nested1.setB(66);
  330. message.setOptionalNestedMessage(nested1);
  331. var nested2 = new proto2.TestAllTypes.NestedMessage();
  332. message.addRepeatedNestedMessage(nested2);
  333. var nested3 = new proto2.TestAllTypes.NestedMessage();
  334. nested3.setB(66);
  335. message.addRepeatedNestedMessage(nested3);
  336. message.initDefaults(true);
  337. assertEquals('int32 field is unchanged', 32, message.getOptionalInt32());
  338. assertEquals(
  339. 'int64 [default=1] field is unchanged', '64', message.getOptionalInt64());
  340. assertTrue('bool field is initialized', message.hasOptionalBool());
  341. assertFalse('value of the bool field', message.getOptionalBool());
  342. assertTrue(
  343. 'int32 inside the optional group is initialized',
  344. message.getOptionalgroup().hasA());
  345. assertEquals(
  346. 'value of the int32 inside the optional group', 0,
  347. message.getOptionalgroup().getA());
  348. assertEquals(
  349. 'int32 inside nested message is unchanged', 66,
  350. message.getOptionalNestedMessage().getB());
  351. assertTrue(
  352. 'int32 at index 0 of the repeated nested message is initialized',
  353. message.getRepeatedNestedMessage(0).hasB());
  354. assertEquals(
  355. 'value of int32 at index 0 of the repeated nested message', 0,
  356. message.getRepeatedNestedMessage(0).getB());
  357. assertEquals(
  358. 'int32 at index 1 of the repeated nested message is unchanged', 66,
  359. message.getRepeatedNestedMessage(1).getB());
  360. }
  361. function testInitDefaultsTwice() {
  362. var message = new proto2.TestAllTypes();
  363. message.initDefaults(false);
  364. var clone = message.clone();
  365. clone.initDefaults(false);
  366. assertObjectEquals(
  367. 'second call of initDefaults(false) has no effect', message, clone);
  368. message = new proto2.TestAllTypes();
  369. message.initDefaults(true);
  370. clone = message.clone();
  371. clone.initDefaults(true);
  372. assertObjectEquals(
  373. 'second call of initDefaults(true) has no effect', message, clone);
  374. }
  375. function testInitDefaultsThenClone() {
  376. var message = new proto2.TestAllTypes();
  377. message.initDefaults(true);
  378. assertObjectEquals('message is cloned properly', message, message.clone());
  379. }
  380. function testClassGetDescriptorEqualToInstanceGetDescriptor() {
  381. var classDescriptor = proto2.TestAllTypes.getDescriptor();
  382. var instanceDescriptor = new proto2.TestAllTypes().getDescriptor();
  383. assertEquals(classDescriptor, instanceDescriptor);
  384. }
  385. function testGetAfterSetWithLazyDeserializer() {
  386. // Test makes sure that the lazy deserializer for a field is not
  387. // erroneously called when get$Value is called after set$Value.
  388. var message = new proto2.TestAllTypes();
  389. var fakeDeserializer = {}; // stub with no methods defined; fails hard
  390. message.initializeForLazyDeserializer(fakeDeserializer, {} /* data */);
  391. message.setOptionalBool(true);
  392. assertEquals(true, message.getOptionalBool());
  393. }
  394. function testHasOnLazyDeserializer() {
  395. // Test that null values for fields are treated as absent by the lazy
  396. // deserializer.
  397. var message = new proto2.TestAllTypes();
  398. var fakeDeserializer = {}; // stub with no methods defined; fails hard
  399. message.initializeForLazyDeserializer(
  400. fakeDeserializer, {13: false} /* data */);
  401. assertEquals(true, message.hasOptionalBool());
  402. }
  403. function testHasOnLazyDeserializerWithNulls() {
  404. // Test that null values for fields are treated as absent by the lazy
  405. // deserializer.
  406. var message = new proto2.TestAllTypes();
  407. var fakeDeserializer = {}; // stub with no methods defined; fails hard
  408. message.initializeForLazyDeserializer(
  409. fakeDeserializer, {13: null} /* data */);
  410. assertEquals(false, message.hasOptionalBool());
  411. }