| // 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.ObjectSerializerTest'); |
| goog.setTestOnly('goog.proto2.ObjectSerializerTest'); |
| |
| goog.require('goog.proto2.ObjectSerializer'); |
| goog.require('goog.proto2.Serializer'); |
| goog.require('goog.testing.PropertyReplacer'); |
| goog.require('goog.testing.jsunit'); |
| goog.require('proto2.TestAllTypes'); |
| |
| var propertyReplacer = new goog.testing.PropertyReplacer(); |
| |
| function tearDown() { |
| propertyReplacer.reset(); |
| } |
| |
| function testSerialization() { |
| 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); |
| |
| // Serialize to a simplified object. |
| var simplified = new goog.proto2.ObjectSerializer().serialize(message); |
| |
| // Assert that everything serialized properly. |
| assertEquals(101, simplified[1]); |
| assertEquals('102', simplified[2]); |
| assertEquals(103, simplified[3]); |
| assertEquals('104', simplified[4]); |
| assertEquals(105, simplified[5]); |
| assertEquals('106', simplified[6]); |
| assertEquals(107, simplified[7]); |
| assertEquals('108', simplified[8]); |
| assertEquals(109, simplified[9]); |
| assertEquals('110', simplified[10]); |
| assertEquals(111.5, simplified[11]); |
| assertEquals(112.5, simplified[12]); |
| assertEquals(true, simplified[13]); |
| assertEquals('test', simplified[14]); |
| assertEquals('abcd', simplified[15]); |
| |
| assertEquals(111, simplified[16][17]); |
| assertEquals(112, simplified[18][1]); |
| assertEquals(proto2.TestAllTypes.NestedEnum.FOO, simplified[21]); |
| |
| assertEquals(201, simplified[31][0]); |
| assertEquals(202, simplified[31][1]); |
| |
| // Serialize to a simplified object (with key as name). |
| simplified = new goog.proto2.ObjectSerializer( |
| goog.proto2.ObjectSerializer.KeyOption.NAME).serialize(message); |
| |
| // Assert that everything serialized properly. |
| assertEquals(101, simplified['optional_int32']); |
| assertEquals('102', simplified['optional_int64']); |
| assertEquals(103, simplified['optional_uint32']); |
| assertEquals('104', simplified['optional_uint64']); |
| assertEquals(105, simplified['optional_sint32']); |
| assertEquals('106', simplified['optional_sint64']); |
| assertEquals(107, simplified['optional_fixed32']); |
| assertEquals('108', simplified['optional_fixed64']); |
| assertEquals(109, simplified['optional_sfixed32']); |
| assertEquals('110', simplified['optional_sfixed64']); |
| assertEquals(111.5, simplified['optional_float']); |
| assertEquals(112.5, simplified['optional_double']); |
| assertEquals(true, simplified['optional_bool']); |
| assertEquals('test', simplified['optional_string']); |
| assertEquals('abcd', simplified['optional_bytes']); |
| |
| assertEquals(111, simplified['optionalgroup']['a']); |
| assertEquals(112, simplified['optional_nested_message']['b']); |
| |
| assertEquals(proto2.TestAllTypes.NestedEnum.FOO, |
| simplified['optional_nested_enum']); |
| |
| assertEquals(201, simplified['repeated_int32'][0]); |
| assertEquals(202, simplified['repeated_int32'][1]); |
| } |
| |
| |
| function testSerializationOfUnknown() { |
| var message = new proto2.TestAllTypes(); |
| |
| // Set the fields. |
| // Known. |
| message.setOptionalInt32(101); |
| message.setOptionalInt64('102'); |
| message.addRepeatedInt32(201); |
| message.addRepeatedInt32(202); |
| |
| // Unknown. |
| message.setUnknown(1000, 301); |
| message.setUnknown(1001, 302); |
| |
| // Serialize. |
| var simplified = new goog.proto2.ObjectSerializer().serialize(message); |
| |
| assertEquals(101, simplified['1']); |
| assertEquals('102', simplified['2']); |
| |
| assertEquals(201, simplified['31'][0]); |
| assertEquals(202, simplified['31'][1]); |
| |
| assertEquals(301, simplified['1000']); |
| assertEquals(302, simplified['1001']); |
| } |
| |
| function testDeserializationOfUnknown() { |
| var simplified = { |
| 1: 101, |
| 2: '102', |
| 1000: 103, |
| 1001: 104 |
| }; |
| |
| var serializer = new goog.proto2.ObjectSerializer(); |
| |
| var message = serializer.deserialize( |
| proto2.TestAllTypes.getDescriptor(), simplified); |
| |
| assertNotNull(message); |
| assertTrue(message.hasOptionalInt32()); |
| assertTrue(message.hasOptionalInt64()); |
| |
| assertEquals(101, message.getOptionalInt32()); |
| assertEquals('102', message.getOptionalInt64()); |
| |
| var count = 0; |
| |
| message.forEachUnknown(function(tag, value) { |
| if (tag == 1000) { |
| assertEquals(103, value); |
| } |
| |
| if (tag == 1001) { |
| assertEquals(104, value); |
| } |
| |
| ++count; |
| }); |
| |
| assertEquals(2, count); |
| } |
| |
| function testDeserializationRepeated() { |
| var simplified = { |
| 31: [101, 102], |
| 41: [201.5, 202.5, 203.5], |
| 42: [], |
| 43: [true, false], |
| 44: ['he', 'llo'], |
| 46: [{ 47: [101] } , { 47: [102] }], |
| 48: [{ 1: 201 }, { 1: 202 }] |
| }; |
| |
| var serializer = new goog.proto2.ObjectSerializer(); |
| |
| var message = serializer.deserialize( |
| proto2.TestAllTypes.getDescriptor(), simplified); |
| |
| assertNotNull(message); |
| |
| // Ensure the fields are set as expected. |
| assertTrue(message.hasRepeatedInt32()); |
| assertTrue(message.hasRepeatedFloat()); |
| |
| assertFalse(message.hasRepeatedDouble()); |
| |
| assertTrue(message.hasRepeatedBool()); |
| assertTrue(message.hasRepeatedgroup()); |
| assertTrue(message.hasRepeatedNestedMessage()); |
| |
| // Ensure the counts match. |
| assertEquals(2, message.repeatedInt32Count()); |
| assertEquals(3, message.repeatedFloatCount()); |
| |
| assertEquals(0, message.repeatedDoubleCount()); |
| |
| assertEquals(2, message.repeatedBoolCount()); |
| assertEquals(2, message.repeatedStringCount()); |
| assertEquals(2, message.repeatedgroupCount()); |
| assertEquals(2, message.repeatedNestedMessageCount()); |
| |
| // Ensure the values match. |
| assertEquals(101, message.getRepeatedInt32(0)); |
| assertEquals(102, message.getRepeatedInt32(1)); |
| |
| assertEquals(201.5, message.getRepeatedFloat(0)); |
| assertEquals(202.5, message.getRepeatedFloat(1)); |
| assertEquals(203.5, message.getRepeatedFloat(2)); |
| |
| assertEquals(true, message.getRepeatedBool(0)); |
| assertEquals(false, message.getRepeatedBool(1)); |
| |
| assertEquals('he', message.getRepeatedString(0)); |
| assertEquals('llo', message.getRepeatedString(1)); |
| |
| assertEquals(101, message.getRepeatedgroup(0).getA(0)); |
| assertEquals(102, message.getRepeatedgroup(1).getA(0)); |
| |
| assertEquals(201, message.getRepeatedNestedMessage(0).getB()); |
| assertEquals(202, message.getRepeatedNestedMessage(1).getB()); |
| } |
| |
| function testDeserialization() { |
| var simplified = { |
| 1: 101, |
| 2: '102', |
| 3: 103, |
| 4: '104', |
| 5: 105, |
| 6: '106', |
| 7: 107, |
| 8: '108', |
| 9: 109, |
| 10: '110', |
| 11: 111.5, |
| 12: 112.5, |
| 13: true, |
| 14: 'test', |
| 15: 'abcd', |
| 16: { 17 : 113 }, |
| 18: { 1 : 114 }, |
| 21: proto2.TestAllTypes.NestedEnum.FOO |
| }; |
| |
| var serializer = new goog.proto2.ObjectSerializer(); |
| |
| var message = serializer.deserialize( |
| proto2.TestAllTypes.getDescriptor(), simplified); |
| |
| assertNotNull(message); |
| |
| assertTrue(message.hasOptionalInt32()); |
| assertTrue(message.hasOptionalInt64()); |
| assertTrue(message.hasOptionalUint32()); |
| assertTrue(message.hasOptionalUint64()); |
| assertTrue(message.hasOptionalSint32()); |
| assertTrue(message.hasOptionalSint64()); |
| assertTrue(message.hasOptionalFixed32()); |
| assertTrue(message.hasOptionalFixed64()); |
| assertTrue(message.hasOptionalSfixed32()); |
| assertTrue(message.hasOptionalSfixed64()); |
| assertTrue(message.hasOptionalFloat()); |
| assertTrue(message.hasOptionalDouble()); |
| assertTrue(message.hasOptionalBool()); |
| assertTrue(message.hasOptionalString()); |
| assertTrue(message.hasOptionalBytes()); |
| assertTrue(message.hasOptionalgroup()); |
| assertTrue(message.hasOptionalNestedMessage()); |
| assertTrue(message.hasOptionalNestedEnum()); |
| |
| assertEquals(1, message.optionalInt32Count()); |
| assertEquals(1, message.optionalInt64Count()); |
| assertEquals(1, message.optionalUint32Count()); |
| assertEquals(1, message.optionalUint64Count()); |
| assertEquals(1, message.optionalSint32Count()); |
| assertEquals(1, message.optionalSint64Count()); |
| assertEquals(1, message.optionalFixed32Count()); |
| assertEquals(1, message.optionalFixed64Count()); |
| assertEquals(1, message.optionalSfixed32Count()); |
| assertEquals(1, message.optionalSfixed64Count()); |
| assertEquals(1, message.optionalFloatCount()); |
| assertEquals(1, message.optionalDoubleCount()); |
| assertEquals(1, message.optionalBoolCount()); |
| assertEquals(1, message.optionalStringCount()); |
| assertEquals(1, message.optionalBytesCount()); |
| assertEquals(1, message.optionalgroupCount()); |
| assertEquals(1, message.optionalNestedMessageCount()); |
| assertEquals(1, message.optionalNestedEnumCount()); |
| |
| assertEquals(101, message.getOptionalInt32()); |
| assertEquals('102', message.getOptionalInt64()); |
| assertEquals(103, message.getOptionalUint32()); |
| assertEquals('104', message.getOptionalUint64()); |
| assertEquals(105, message.getOptionalSint32()); |
| assertEquals('106', message.getOptionalSint64()); |
| assertEquals(107, message.getOptionalFixed32()); |
| assertEquals('108', message.getOptionalFixed64()); |
| assertEquals(109, message.getOptionalSfixed32()); |
| assertEquals('110', message.getOptionalSfixed64()); |
| assertEquals(111.5, message.getOptionalFloat()); |
| assertEquals(112.5, message.getOptionalDouble()); |
| assertEquals(true, message.getOptionalBool()); |
| assertEquals('test', message.getOptionalString()); |
| assertEquals('abcd', message.getOptionalBytes()); |
| assertEquals(113, message.getOptionalgroup().getA()); |
| assertEquals(114, message.getOptionalNestedMessage().getB()); |
| |
| assertEquals(proto2.TestAllTypes.NestedEnum.FOO, |
| message.getOptionalNestedEnum()); |
| } |
| |
| function testDeserializationUnknownEnumValue() { |
| var simplified = { |
| 21: 1001 |
| }; |
| |
| var serializer = new goog.proto2.ObjectSerializer(); |
| |
| var message = serializer.deserialize( |
| proto2.TestAllTypes.getDescriptor(), simplified); |
| |
| assertNotNull(message); |
| |
| assertEquals(1001, message.getOptionalNestedEnum()); |
| } |
| |
| function testDeserializationSymbolicEnumValue() { |
| var simplified = { |
| 21: 'BAR' |
| }; |
| |
| propertyReplacer.set(goog.proto2.Serializer, 'DECODE_SYMBOLIC_ENUMS', true); |
| |
| var serializer = new goog.proto2.ObjectSerializer(); |
| |
| var message = serializer.deserialize( |
| proto2.TestAllTypes.getDescriptor(), simplified); |
| |
| assertNotNull(message); |
| |
| assertEquals(proto2.TestAllTypes.NestedEnum.BAR, |
| message.getOptionalNestedEnum()); |
| } |
| |
| function testDeserializationSymbolicEnumValueTurnedOff() { |
| var simplified = { |
| 21: 'BAR' |
| }; |
| |
| var serializer = new goog.proto2.ObjectSerializer(); |
| |
| assertThrows('Should have an assertion failure in deserialization', |
| function() { |
| serializer.deserialize(proto2.TestAllTypes.getDescriptor(), simplified); |
| }); |
| } |
| |
| function testDeserializationUnknownSymbolicEnumValue() { |
| var simplified = { |
| 21: 'BARRED' |
| }; |
| |
| var serializer = new goog.proto2.ObjectSerializer(); |
| |
| assertThrows('Should have an assertion failure in deserialization', |
| function() { |
| serializer.deserialize(proto2.TestAllTypes.getDescriptor(), simplified); |
| }); |
| } |
| |
| function testDeserializationNumbersOrStrings() { |
| // 64-bit types may have been serialized as numbers or strings. |
| // Deserialization should be able to handle either. |
| |
| var simplifiedWithNumbers = { |
| 50: 5000, |
| 51: 5100, |
| 52: [5200, 5201], |
| 53: [5300, 5301] |
| }; |
| |
| var simplifiedWithStrings = { |
| 50: '5000', |
| 51: '5100', |
| 52: ['5200', '5201'], |
| 53: ['5300', '5301'] |
| }; |
| |
| var serializer = new goog.proto2.ObjectSerializer(); |
| |
| var message = serializer.deserialize( |
| proto2.TestAllTypes.getDescriptor(), simplifiedWithNumbers); |
| |
| assertNotNull(message); |
| |
| assertEquals(5000, message.getOptionalInt64Number()); |
| assertEquals('5100', message.getOptionalInt64String()); |
| assertEquals(5200, message.getRepeatedInt64Number(0)); |
| assertEquals(5201, message.getRepeatedInt64Number(1)); |
| assertEquals('5300', message.getRepeatedInt64String(0)); |
| assertEquals('5301', message.getRepeatedInt64String(1)); |
| |
| assertArrayEquals([5200, 5201], message.repeatedInt64NumberArray()); |
| assertArrayEquals(['5300', '5301'], message.repeatedInt64StringArray()); |
| |
| message = serializer.deserialize( |
| proto2.TestAllTypes.getDescriptor(), simplifiedWithStrings); |
| |
| assertNotNull(message); |
| |
| assertEquals(5000, message.getOptionalInt64Number()); |
| assertEquals('5100', message.getOptionalInt64String()); |
| assertEquals(5200, message.getRepeatedInt64Number(0)); |
| assertEquals(5201, message.getRepeatedInt64Number(1)); |
| assertEquals('5300', message.getRepeatedInt64String(0)); |
| assertEquals('5301', message.getRepeatedInt64String(1)); |
| |
| assertArrayEquals([5200, 5201], message.repeatedInt64NumberArray()); |
| assertArrayEquals(['5300', '5301'], message.repeatedInt64StringArray()); |
| } |
| |
| function testSerializationSpecialFloatDoubleValues() { |
| // NaN, Infinity and -Infinity should get serialized as strings. |
| var message = new proto2.TestAllTypes(); |
| message.setOptionalFloat(Infinity); |
| message.setOptionalDouble(-Infinity); |
| message.addRepeatedFloat(Infinity); |
| message.addRepeatedFloat(-Infinity); |
| message.addRepeatedFloat(NaN); |
| message.addRepeatedDouble(Infinity); |
| message.addRepeatedDouble(-Infinity); |
| message.addRepeatedDouble(NaN); |
| var simplified = new goog.proto2.ObjectSerializer().serialize(message); |
| |
| // Assert that everything serialized properly. |
| assertEquals('Infinity', simplified[11]); |
| assertEquals('-Infinity', simplified[12]); |
| assertEquals('Infinity', simplified[41][0]); |
| assertEquals('-Infinity', simplified[41][1]); |
| assertEquals('NaN', simplified[41][2]); |
| assertEquals('Infinity', simplified[42][0]); |
| assertEquals('-Infinity', simplified[42][1]); |
| assertEquals('NaN', simplified[42][2]); |
| } |
| |
| function testDeserializationSpecialFloatDoubleValues() { |
| // NaN, Infinity and -Infinity values should be de-serialized from their |
| // string representation. |
| var simplified = { |
| 41: ['Infinity', '-Infinity', 'NaN'], |
| 42: ['Infinity', '-Infinity', 'NaN'] |
| }; |
| |
| var serializer = new goog.proto2.ObjectSerializer(); |
| |
| var message = serializer.deserialize( |
| proto2.TestAllTypes.getDescriptor(), simplified); |
| |
| assertNotNull(message); |
| |
| var floatArray = message.repeatedFloatArray(); |
| assertEquals(Infinity, floatArray[0]); |
| assertEquals(-Infinity, floatArray[1]); |
| assertTrue(isNaN(floatArray[2])); |
| |
| var doubleArray = message.repeatedDoubleArray(); |
| assertEquals(Infinity, doubleArray[0]); |
| assertEquals(-Infinity, doubleArray[1]); |
| assertTrue(isNaN(doubleArray[2])); |
| } |
| |
| function testDeserializationConversionProhibited() { |
| // 64-bit types may have been serialized as numbers or strings. |
| // But 32-bit types must be serialized as numbers. |
| // Test deserialization fails on 32-bit numbers as strings. |
| |
| var simplified = { |
| 1: '1000' // optionalInt32 |
| }; |
| var serializer = new goog.proto2.ObjectSerializer(); |
| |
| assertThrows('Should have an assertion failure in deserialization', |
| function() { |
| serializer.deserialize(proto2.TestAllTypes.getDescriptor(), simplified); |
| }); |
| } |
| |
| function testDefaultValueNumbersOrStrings() { |
| // 64-bit types may have been serialized as numbers or strings. |
| // The default values should have the correct type. |
| |
| var serializer = new goog.proto2.ObjectSerializer(); |
| var message = serializer.deserialize(proto2.TestAllTypes.getDescriptor(), {}); |
| |
| assertNotNull(message); |
| |
| // Default when using Number is a number, and precision is lost. |
| var value = message.getOptionalInt64NumberOrDefault(); |
| assertTrue('Expecting a number', typeof value === 'number'); |
| assertEquals(1000000000000000000, value); |
| assertEquals(1000000000000000001, value); |
| assertEquals(1000000000000000002, value); |
| assertEquals('1000000000000000000', String(value)); // Value is rounded! |
| |
| // When using a String, the value is preserved. |
| assertEquals('1000000000000000001', |
| message.getOptionalInt64StringOrDefault()); |
| } |
| |
| function testBooleanAsNumberFalse() { |
| // Some libraries, such as GWT, can serialize boolean values as 0/1 |
| |
| var simplified = { |
| 13: 0 |
| }; |
| |
| var serializer = new goog.proto2.ObjectSerializer(); |
| |
| var message = serializer.deserialize( |
| proto2.TestAllTypes.getDescriptor(), simplified); |
| |
| assertNotNull(message); |
| |
| assertFalse(message.getOptionalBool()); |
| } |
| |
| function testBooleanAsNumberTrue() { |
| var simplified = { |
| 13: 1 |
| }; |
| |
| var serializer = new goog.proto2.ObjectSerializer(); |
| |
| var message = serializer.deserialize( |
| proto2.TestAllTypes.getDescriptor(), simplified); |
| |
| assertNotNull(message); |
| |
| assertTrue(message.getOptionalBool()); |
| } |