// Copyright 2008 The Closure Library Authors. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS-IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. goog.provide('goog.proto2.PbLiteSerializerTest'); goog.setTestOnly('goog.proto2.PbLiteSerializerTest'); goog.require('goog.proto2.PbLiteSerializer'); goog.require('goog.testing.jsunit'); goog.require('proto2.TestAllTypes'); function testSerializationAndDeserialization() { var message = createPopulatedMessage(); // Serialize. var serializer = new goog.proto2.PbLiteSerializer(); var pblite = serializer.serialize(message); assertTrue(goog.isArray(pblite)); // Assert that everything serialized properly. assertEquals(101, pblite[1]); assertEquals('102', pblite[2]); assertEquals(103, pblite[3]); assertEquals('104', pblite[4]); assertEquals(105, pblite[5]); assertEquals('106', pblite[6]); assertEquals(107, pblite[7]); assertEquals('108', pblite[8]); assertEquals(109, pblite[9]); assertEquals('110', pblite[10]); assertEquals(111.5, pblite[11]); assertEquals(112.5, pblite[12]); assertEquals(1, pblite[13]); // true is serialized as 1 assertEquals('test', pblite[14]); assertEquals('abcd', pblite[15]); assertEquals(111, pblite[16][17]); assertEquals(112, pblite[18][1]); assertTrue(pblite[19] === undefined); assertTrue(pblite[20] === undefined); assertEquals(proto2.TestAllTypes.NestedEnum.FOO, pblite[21]); assertEquals(201, pblite[31][0]); assertEquals(202, pblite[31][1]); assertEquals('foo', pblite[44][0]); assertEquals('bar', pblite[44][1]); var serializer = new goog.proto2.PbLiteSerializer(); // Deserialize. var messageCopy = serializer.deserialize(proto2.TestAllTypes.getDescriptor(), pblite); assertNotEquals(messageCopy, message); assertDeserializationMatches(messageCopy); } function testZeroBasedSerializationAndDeserialization() { var message = createPopulatedMessage(); // Serialize. var serializer = new goog.proto2.PbLiteSerializer(); serializer.setZeroIndexed(true); var pblite = serializer.serialize(message); assertTrue(goog.isArray(pblite)); // Assert that everything serialized properly. assertEquals(101, pblite[0]); assertEquals('102', pblite[1]); assertEquals(103, pblite[2]); assertEquals('104', pblite[3]); assertEquals(105, pblite[4]); assertEquals('106', pblite[5]); assertEquals(107, pblite[6]); assertEquals('108', pblite[7]); assertEquals(109, pblite[8]); assertEquals('110', pblite[9]); assertEquals(111.5, pblite[10]); assertEquals(112.5, pblite[11]); assertEquals(1, pblite[12]); // true is serialized as 1 assertEquals('test', pblite[13]); assertEquals('abcd', pblite[14]); assertEquals(111, pblite[15][16]); assertEquals(112, pblite[17][0]); assertTrue(pblite[18] === undefined); assertTrue(pblite[19] === undefined); assertEquals(proto2.TestAllTypes.NestedEnum.FOO, pblite[20]); assertEquals(201, pblite[30][0]); assertEquals(202, pblite[30][1]); assertEquals('foo', pblite[43][0]); assertEquals('bar', pblite[43][1]); // Deserialize. var messageCopy = serializer.deserialize(proto2.TestAllTypes.getDescriptor(), pblite); assertNotEquals(messageCopy, message); assertEquals(message.getOptionalInt32(), messageCopy.getOptionalInt32()); assertDeserializationMatches(messageCopy); } function createPopulatedMessage() { var message = new proto2.TestAllTypes(); // Set the fields. // Singular. message.setOptionalInt32(101); message.setOptionalInt64('102'); message.setOptionalUint32(103); message.setOptionalUint64('104'); message.setOptionalSint32(105); message.setOptionalSint64('106'); message.setOptionalFixed32(107); message.setOptionalFixed64('108'); message.setOptionalSfixed32(109); message.setOptionalSfixed64('110'); message.setOptionalFloat(111.5); message.setOptionalDouble(112.5); message.setOptionalBool(true); message.setOptionalString('test'); message.setOptionalBytes('abcd'); var group = new proto2.TestAllTypes.OptionalGroup(); group.setA(111); message.setOptionalgroup(group); var nestedMessage = new proto2.TestAllTypes.NestedMessage(); nestedMessage.setB(112); message.setOptionalNestedMessage(nestedMessage); message.setOptionalNestedEnum(proto2.TestAllTypes.NestedEnum.FOO); // Repeated. message.addRepeatedInt32(201); message.addRepeatedInt32(202); // Skip a few repeated fields so we can test how null array values are // handled. message.addRepeatedString('foo'); message.addRepeatedString('bar'); return message; } function testDeserializationFromExternalSource() { // Test deserialization where the JSON array is initialized from something // outside the Closure proto2 library, such as the JsPbLite library, or // manually as in this test. var pblite = [ , // 0 101, // 1 '102', // 2 103, // 3 '104', // 4 105, // 5 '106', // 6 107, // 7 '108', // 8 109, // 9 '110', // 10 111.5, // 11 112.5, // 12 1, // 13 'test', // 14 'abcd', // 15 [ , , , , , , , , , , , , , , , , , 111 ], // 16, note the 17 commas so value is index 17 , // 17 [, 112], // 18 , , // 19-20 proto2.TestAllTypes.NestedEnum.FOO, // 21 , , , , , , , , , // 22-30 [201, 202], // 31 , , , , , , , , , , , , // 32-43 ['foo', 'bar'] // 44 ]; pblite.length = 50; // Deserialize. var serializer = new goog.proto2.PbLiteSerializer(); var messageCopy = serializer.deserialize(proto2.TestAllTypes.getDescriptor(), pblite); assertDeserializationMatches(messageCopy); // http://b/issue?id=2928075 assertFalse(messageCopy.hasRepeatedInt64()); assertEquals(0, messageCopy.repeatedInt64Count()); messageCopy.repeatedInt64Array(); assertFalse(messageCopy.hasRepeatedInt64()); assertEquals(0, messageCopy.repeatedInt64Count()); // Access a nested message to ensure it is deserialized. assertNotNull(messageCopy.getOptionalNestedMessage()); // Verify that the pblite array itself has not been replaced by the // deserialization. assertEquals('array', goog.typeOf(pblite[16])); // Update some fields and verify that the changes work with the lazy // deserializer. messageCopy.setOptionalBool(true); assertTrue(messageCopy.getOptionalBool()); messageCopy.setOptionalBool(false); assertFalse(messageCopy.getOptionalBool()); messageCopy.setOptionalInt32(1234); assertEquals(1234, messageCopy.getOptionalInt32()); } function testModifyLazyDeserializedMessage() { var pblite = [ , // 0 101, // 1 '102', // 2 103, // 3 '104', // 4 105, // 5 '106', // 6 107, // 7 '108', // 8 109, // 9 '110', // 10 111.5, // 11 112.5, // 12 1, // 13 'test', // 14 'abcd', // 15 [ , , , , , , , , , , , , , , , , , 111 ], // 16, note the 17 commas so value is index 17 , // 17 [, 112], // 18 , , // 19-20 proto2.TestAllTypes.NestedEnum.FOO, // 21 , , , , , , , , , // 22-30 [201, 202], // 31 , , , , , , , , , , , , // 32-43 ['foo', 'bar'] // 44 ]; pblite.length = 50; // Deserialize. var serializer = new goog.proto2.PbLiteSerializer(); var message = serializer.deserialize(proto2.TestAllTypes.getDescriptor(), pblite); // Conduct some operations, ensuring that they all work as expected, even with // the lazily deserialized data. assertEquals(101, message.getOptionalInt32()); message.setOptionalInt32(401); assertEquals(401, message.getOptionalInt32()); assertEquals(2, message.repeatedInt32Count()); assertEquals(201, message.getRepeatedInt32(0)); assertEquals(202, message.getRepeatedInt32(1)); message.clearRepeatedInt32(); assertEquals(0, message.repeatedInt32Count()); message.addRepeatedInt32(101); assertEquals(1, message.repeatedInt32Count()); assertEquals(101, message.getRepeatedInt32(0)); message.setUnknown(12345, 601); message.forEachUnknown(function(tag, value) { assertEquals(12345, tag); assertEquals(601, value); }); // Create a copy of the message. var messageCopy = new proto2.TestAllTypes(); messageCopy.copyFrom(message); assertEquals(1, messageCopy.repeatedInt32Count()); assertEquals(101, messageCopy.getRepeatedInt32(0)); } function testModifyLazyDeserializedMessageByAddingMessage() { var pblite = [ , // 0 101, // 1 '102', // 2 103, // 3 '104', // 4 105, // 5 '106', // 6 107, // 7 '108', // 8 109, // 9 '110', // 10 111.5, // 11 112.5, // 12 1, // 13 'test', // 14 'abcd', // 15 [ , , , , , , , , , , , , , , , , , 111 ], // 16, note the 17 commas so value is index 17 , // 17 [, 112], // 18 , , // 19-20 proto2.TestAllTypes.NestedEnum.FOO, // 21 , , , , , , , , , // 22-30 [201, 202], // 31 , , , , , , , , , , , , // 32-43 ['foo', 'bar'] // 44 ]; pblite.length = 50; // Deserialize. var serializer = new goog.proto2.PbLiteSerializer(); var message = serializer.deserialize(proto2.TestAllTypes.getDescriptor(), pblite); // Add a new nested message. var nested1 = new proto2.TestAllTypes.NestedMessage(); nested1.setB(1234); var nested2 = new proto2.TestAllTypes.NestedMessage(); nested2.setB(4567); message.addRepeatedNestedMessage(nested1); // Check the new nested message. assertEquals(1, message.repeatedNestedMessageArray().length); assertTrue(message.repeatedNestedMessageArray()[0].equals(nested1)); // Add another nested message. message.addRepeatedNestedMessage(nested2); // Check both nested messages. assertEquals(2, message.repeatedNestedMessageArray().length); assertTrue(message.repeatedNestedMessageArray()[0].equals(nested1)); assertTrue(message.repeatedNestedMessageArray()[1].equals(nested2)); } function assertDeserializationMatches(messageCopy) { assertNotNull(messageCopy); assertTrue(messageCopy.hasOptionalInt32()); assertTrue(messageCopy.hasOptionalInt64()); assertTrue(messageCopy.hasOptionalUint32()); assertTrue(messageCopy.hasOptionalUint64()); assertTrue(messageCopy.hasOptionalSint32()); assertTrue(messageCopy.hasOptionalSint64()); assertTrue(messageCopy.hasOptionalFixed32()); assertTrue(messageCopy.hasOptionalFixed64()); assertTrue(messageCopy.hasOptionalSfixed32()); assertTrue(messageCopy.hasOptionalSfixed64()); assertTrue(messageCopy.hasOptionalFloat()); assertTrue(messageCopy.hasOptionalDouble()); assertTrue(messageCopy.hasOptionalBool()); assertTrue(messageCopy.hasOptionalString()); assertTrue(messageCopy.hasOptionalBytes()); assertTrue(messageCopy.hasOptionalgroup()); assertTrue(messageCopy.hasOptionalNestedMessage()); assertTrue(messageCopy.hasOptionalNestedEnum()); assertTrue(messageCopy.hasRepeatedInt32()); assertFalse(messageCopy.hasRepeatedInt64()); assertFalse(messageCopy.hasRepeatedUint32()); assertFalse(messageCopy.hasRepeatedUint64()); assertFalse(messageCopy.hasRepeatedSint32()); assertFalse(messageCopy.hasRepeatedSint64()); assertFalse(messageCopy.hasRepeatedFixed32()); assertFalse(messageCopy.hasRepeatedFixed64()); assertFalse(messageCopy.hasRepeatedSfixed32()); assertFalse(messageCopy.hasRepeatedSfixed64()); assertFalse(messageCopy.hasRepeatedFloat()); assertFalse(messageCopy.hasRepeatedDouble()); assertFalse(messageCopy.hasRepeatedBool()); assertTrue(messageCopy.hasRepeatedString()); assertFalse(messageCopy.hasRepeatedBytes()); assertFalse(messageCopy.hasRepeatedgroup()); assertFalse(messageCopy.hasRepeatedNestedMessage()); assertFalse(messageCopy.hasRepeatedNestedEnum()); assertEquals(1, messageCopy.optionalInt32Count()); assertEquals(1, messageCopy.optionalInt64Count()); assertEquals(1, messageCopy.optionalUint32Count()); assertEquals(1, messageCopy.optionalUint64Count()); assertEquals(1, messageCopy.optionalSint32Count()); assertEquals(1, messageCopy.optionalSint64Count()); assertEquals(1, messageCopy.optionalFixed32Count()); assertEquals(1, messageCopy.optionalFixed64Count()); assertEquals(1, messageCopy.optionalSfixed32Count()); assertEquals(1, messageCopy.optionalSfixed64Count()); assertEquals(1, messageCopy.optionalFloatCount()); assertEquals(1, messageCopy.optionalDoubleCount()); assertEquals(1, messageCopy.optionalBoolCount()); assertEquals(1, messageCopy.optionalStringCount()); assertEquals(1, messageCopy.optionalBytesCount()); assertEquals(1, messageCopy.optionalgroupCount()); assertEquals(1, messageCopy.optionalNestedMessageCount()); assertEquals(1, messageCopy.optionalNestedEnumCount()); assertEquals(2, messageCopy.repeatedInt32Count()); assertEquals(0, messageCopy.repeatedInt64Count()); assertEquals(0, messageCopy.repeatedUint32Count()); assertEquals(0, messageCopy.repeatedUint64Count()); assertEquals(0, messageCopy.repeatedSint32Count()); assertEquals(0, messageCopy.repeatedSint64Count()); assertEquals(0, messageCopy.repeatedFixed32Count()); assertEquals(0, messageCopy.repeatedFixed64Count()); assertEquals(0, messageCopy.repeatedSfixed32Count()); assertEquals(0, messageCopy.repeatedSfixed64Count()); assertEquals(0, messageCopy.repeatedFloatCount()); assertEquals(0, messageCopy.repeatedDoubleCount()); assertEquals(0, messageCopy.repeatedBoolCount()); assertEquals(2, messageCopy.repeatedStringCount()); assertEquals(0, messageCopy.repeatedBytesCount()); assertEquals(0, messageCopy.repeatedgroupCount()); assertEquals(0, messageCopy.repeatedNestedMessageCount()); assertEquals(0, messageCopy.repeatedNestedEnumCount()); assertEquals(101, messageCopy.getOptionalInt32()); assertEquals('102', messageCopy.getOptionalInt64()); assertEquals(103, messageCopy.getOptionalUint32()); assertEquals('104', messageCopy.getOptionalUint64()); assertEquals(105, messageCopy.getOptionalSint32()); assertEquals('106', messageCopy.getOptionalSint64()); assertEquals(107, messageCopy.getOptionalFixed32()); assertEquals('108', messageCopy.getOptionalFixed64()); assertEquals(109, messageCopy.getOptionalSfixed32()); assertEquals('110', messageCopy.getOptionalSfixed64()); assertEquals(111.5, messageCopy.getOptionalFloat()); assertEquals(112.5, messageCopy.getOptionalDouble()); assertEquals(true, messageCopy.getOptionalBool()); assertEquals('test', messageCopy.getOptionalString()); assertEquals('abcd', messageCopy.getOptionalBytes()); assertEquals(111, messageCopy.getOptionalgroup().getA()); assertEquals(112, messageCopy.getOptionalNestedMessage().getB()); assertEquals( proto2.TestAllTypes.NestedEnum.FOO, messageCopy.getOptionalNestedEnum()); assertEquals(201, messageCopy.getRepeatedInt32(0)); assertEquals(202, messageCopy.getRepeatedInt32(1)); } function testMergeFromLazyTarget() { var serializer = new goog.proto2.PbLiteSerializer(); var source = new proto2.TestAllTypes(); var nested = new proto2.TestAllTypes.NestedMessage(); nested.setB(66); source.setOptionalNestedMessage(nested); source.setOptionalInt32(32); source.setOptionalString('foo'); source.setOptionalNestedEnum(proto2.TestAllTypes.NestedEnum.FOO); source.addRepeatedInt32(2); var target = new proto2.TestAllTypes(); nested = new proto2.TestAllTypes.NestedMessage(); nested.setC(77); target.setOptionalNestedMessage(nested); target.setOptionalInt64('64'); target.setOptionalString('bar'); target.setOptionalNestedEnum(proto2.TestAllTypes.NestedEnum.BAR); target.addRepeatedInt32(1); var pbliteTarget = serializer.serialize(target); var lazyTarget = serializer.deserialize(proto2.TestAllTypes.getDescriptor(), pbliteTarget); var expected = new proto2.TestAllTypes(); nested = new proto2.TestAllTypes.NestedMessage(); nested.setB(66); nested.setC(77); expected.setOptionalNestedMessage(nested); expected.setOptionalInt32(32); expected.setOptionalInt64('64'); expected.setOptionalString('foo'); expected.setOptionalNestedEnum(proto2.TestAllTypes.NestedEnum.FOO); expected.addRepeatedInt32(1); expected.addRepeatedInt32(2); lazyTarget.mergeFrom(source); assertTrue( 'expected and lazyTarget are equal after mergeFrom', lazyTarget.equals(expected)); }