diff options
Diffstat (limited to 'java/core/src/test/java/com/google/protobuf/MapTest.java')
-rw-r--r-- | java/core/src/test/java/com/google/protobuf/MapTest.java | 416 |
1 files changed, 318 insertions, 98 deletions
diff --git a/java/core/src/test/java/com/google/protobuf/MapTest.java b/java/core/src/test/java/com/google/protobuf/MapTest.java index caef246b..58efce92 100644 --- a/java/core/src/test/java/com/google/protobuf/MapTest.java +++ b/java/core/src/test/java/com/google/protobuf/MapTest.java @@ -30,18 +30,18 @@ package com.google.protobuf; - +import static org.junit.Assert.assertArrayEquals; import com.google.protobuf.Descriptors.Descriptor; import com.google.protobuf.Descriptors.EnumDescriptor; import com.google.protobuf.Descriptors.EnumValueDescriptor; import com.google.protobuf.Descriptors.FieldDescriptor; import map_test.MapTestProto.BizarroTestMap; +import map_test.MapTestProto.ReservedAsMapField; +import map_test.MapTestProto.ReservedAsMapFieldWithEnumValue; import map_test.MapTestProto.TestMap; import map_test.MapTestProto.TestMap.MessageValue; import map_test.MapTestProto.TestMapOrBuilder; import map_test.MapTestProto.TestOnChangeEventPropagation; -import junit.framework.TestCase; - import java.io.ByteArrayOutputStream; import java.io.IOException; import java.util.ArrayList; @@ -49,6 +49,7 @@ import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; +import junit.framework.TestCase; /** * Unit tests for map fields. @@ -59,26 +60,26 @@ public class MapTest extends TestCase { builder.getMutableInt32ToInt32Field().put(1, 11); builder.getMutableInt32ToInt32Field().put(2, 22); builder.getMutableInt32ToInt32Field().put(3, 33); - + // builder.getMutableInt32ToStringField().put(1, "11"); builder.getMutableInt32ToStringField().put(2, "22"); builder.getMutableInt32ToStringField().put(3, "33"); - + // builder.getMutableInt32ToBytesField().put(1, TestUtil.toBytes("11")); builder.getMutableInt32ToBytesField().put(2, TestUtil.toBytes("22")); builder.getMutableInt32ToBytesField().put(3, TestUtil.toBytes("33")); - + // builder.getMutableInt32ToEnumField().put(1, TestMap.EnumValue.FOO); builder.getMutableInt32ToEnumField().put(2, TestMap.EnumValue.BAR); builder.getMutableInt32ToEnumField().put(3, TestMap.EnumValue.BAZ); - + // builder.getMutableInt32ToMessageField().put( 1, MessageValue.newBuilder().setValue(11).build()); builder.getMutableInt32ToMessageField().put( 2, MessageValue.newBuilder().setValue(22).build()); builder.getMutableInt32ToMessageField().put( 3, MessageValue.newBuilder().setValue(33).build()); - + // builder.getMutableStringToInt32Field().put("1", 11); builder.getMutableStringToInt32Field().put("2", 22); builder.getMutableStringToInt32Field().put("3", 33); @@ -121,6 +122,7 @@ public class MapTest extends TestCase { setMapValuesUsingAccessors(usingAccessorsBuilder); TestMap usingAccessors = usingAccessorsBuilder.build(); assertMapValuesSet(usingAccessors); + assertEquals(usingAccessors, usingMutableMap); } @@ -170,25 +172,25 @@ public class MapTest extends TestCase { builder.getMutableInt32ToInt32Field().put(1, 111); builder.getMutableInt32ToInt32Field().remove(2); builder.getMutableInt32ToInt32Field().put(4, 44); - + // builder.getMutableInt32ToStringField().put(1, "111"); builder.getMutableInt32ToStringField().remove(2); builder.getMutableInt32ToStringField().put(4, "44"); - + // builder.getMutableInt32ToBytesField().put(1, TestUtil.toBytes("111")); builder.getMutableInt32ToBytesField().remove(2); builder.getMutableInt32ToBytesField().put(4, TestUtil.toBytes("44")); - + // builder.getMutableInt32ToEnumField().put(1, TestMap.EnumValue.BAR); builder.getMutableInt32ToEnumField().remove(2); builder.getMutableInt32ToEnumField().put(4, TestMap.EnumValue.QUX); - + // builder.getMutableInt32ToMessageField().put( 1, MessageValue.newBuilder().setValue(111).build()); builder.getMutableInt32ToMessageField().remove(2); builder.getMutableInt32ToMessageField().put( 4, MessageValue.newBuilder().setValue(44).build()); - + // builder.getMutableStringToInt32Field().put("1", 111); builder.getMutableStringToInt32Field().remove("2"); builder.getMutableStringToInt32Field().put("4", 44); @@ -231,8 +233,9 @@ public class MapTest extends TestCase { setMapValuesUsingAccessors(usingAccessorsBuilder); TestMap usingAccessors = usingAccessorsBuilder.build(); assertMapValuesSet(usingAccessors); - assertEquals(usingAccessors, usingMutableMap); + assertEquals(usingAccessors, usingMutableMap); + // usingMutableMapBuilder = usingMutableMap.toBuilder(); updateMapValuesUsingMutableMap(usingMutableMapBuilder); usingMutableMap = usingMutableMapBuilder.build(); @@ -336,7 +339,7 @@ public class MapTest extends TestCase { assertEquals(newMap(1, 2), builder.getInt32ToInt32Field()); builder.getMutableInt32ToInt32Field().put(2, 3); assertEquals(newMap(1, 2, 2, 3), builder.getInt32ToInt32Field()); - + // Map<Integer, TestMap.EnumValue> enumMap = builder.getMutableInt32ToEnumField(); enumMap.put(1, TestMap.EnumValue.BAR); assertEquals(newMap(1, TestMap.EnumValue.BAR), builder.build().getInt32ToEnumField()); @@ -351,7 +354,7 @@ public class MapTest extends TestCase { assertEquals( newMap(1, TestMap.EnumValue.BAR, 2, TestMap.EnumValue.FOO), builder.getInt32ToEnumField()); - + // Map<Integer, String> stringMap = builder.getMutableInt32ToStringField(); stringMap.put(1, "1"); assertEquals(newMap(1, "1"), builder.build().getInt32ToStringField()); @@ -362,11 +365,11 @@ public class MapTest extends TestCase { // expected } assertEquals(newMap(1, "1"), builder.getInt32ToStringField()); - builder.getMutableInt32ToStringField().put(2, "2"); + builder.putInt32ToStringField(2, "2"); assertEquals( newMap(1, "1", 2, "2"), builder.getInt32ToStringField()); - + // Map<Integer, TestMap.MessageValue> messageMap = builder.getMutableInt32ToMessageField(); messageMap.put(1, TestMap.MessageValue.getDefaultInstance()); assertEquals(newMap(1, TestMap.MessageValue.getDefaultInstance()), @@ -379,13 +382,13 @@ public class MapTest extends TestCase { } assertEquals(newMap(1, TestMap.MessageValue.getDefaultInstance()), builder.getInt32ToMessageField()); - builder.getMutableInt32ToMessageField().put(2, TestMap.MessageValue.getDefaultInstance()); + builder.putInt32ToMessageField(2, TestMap.MessageValue.getDefaultInstance()); assertEquals( newMap(1, TestMap.MessageValue.getDefaultInstance(), 2, TestMap.MessageValue.getDefaultInstance()), builder.getInt32ToMessageField()); } - + // public void testMutableMapLifecycle_collections() { TestMap.Builder builder = TestMap.newBuilder(); Map<Integer, Integer> intMap = builder.getMutableInt32ToInt32Field(); @@ -432,18 +435,19 @@ public class MapTest extends TestCase { assertEquals(newMap(1, 2), builder.build().getInt32ToInt32Field()); } + public void testGettersAndSetters() throws Exception { TestMap.Builder builder = TestMap.newBuilder(); TestMap message = builder.build(); assertMapValuesCleared(message); builder = message.toBuilder(); - setMapValuesUsingMutableMap(builder); + setMapValuesUsingAccessors(builder); message = builder.build(); assertMapValuesSet(message); builder = message.toBuilder(); - updateMapValuesUsingMutableMap(builder); + updateMapValuesUsingAccessors(builder); message = builder.build(); assertMapValuesUpdated(message); @@ -456,7 +460,7 @@ public class MapTest extends TestCase { public void testPutAll() throws Exception { TestMap.Builder sourceBuilder = TestMap.newBuilder(); - setMapValuesUsingMutableMap(sourceBuilder); + setMapValuesUsingAccessors(sourceBuilder); TestMap source = sourceBuilder.build(); assertMapValuesSet(source); @@ -466,15 +470,16 @@ public class MapTest extends TestCase { } public void testPutAllForUnknownEnumValues() throws Exception { - TestMap.Builder sourceBuilder = TestMap.newBuilder(); - sourceBuilder.getMutableInt32ToEnumFieldValue().put(0, 0); - sourceBuilder.getMutableInt32ToEnumFieldValue().put(1, 1); - sourceBuilder.getMutableInt32ToEnumFieldValue().put(2, 1000); // unknown value. - TestMap source = sourceBuilder.build(); + TestMap source = TestMap.newBuilder() + .putAllInt32ToEnumFieldValue(newMap( + 0, 0, + 1, 1, + 2, 1000)) // unknown value. + .build(); - TestMap.Builder destinationBuilder = TestMap.newBuilder(); - destinationBuilder.putAllInt32ToEnumFieldValue(source.getInt32ToEnumFieldValue()); - TestMap destination = destinationBuilder.build(); + TestMap destination = TestMap.newBuilder() + .putAllInt32ToEnumFieldValue(source.getInt32ToEnumFieldValue()) + .build(); assertEquals(0, destination.getInt32ToEnumFieldValue().get(0).intValue()); assertEquals(1, destination.getInt32ToEnumFieldValue().get(1).intValue()); @@ -485,19 +490,13 @@ public class MapTest extends TestCase { public void testPutForUnknownEnumValues() throws Exception { TestMap.Builder builder = TestMap.newBuilder() .putInt32ToEnumFieldValue(0, 0) - .putInt32ToEnumFieldValue(1, 1); - - try { - builder.putInt32ToEnumFieldValue(2, 1000); // unknown value. - fail(); - } catch (IllegalArgumentException e) { - // expected - } - + .putInt32ToEnumFieldValue(1, 1) + .putInt32ToEnumFieldValue(2, 1000); // unknown value. TestMap message = builder.build(); assertEquals(0, message.getInt32ToEnumFieldValueOrThrow(0)); assertEquals(1, message.getInt32ToEnumFieldValueOrThrow(1)); - assertEquals(2, message.getInt32ToEnumFieldCount()); + assertEquals(1000, message.getInt32ToEnumFieldValueOrThrow(2)); + assertEquals(3, message.getInt32ToEnumFieldCount()); } public void testPutChecksNullKeysAndValues() throws Exception { @@ -541,14 +540,14 @@ public class MapTest extends TestCase { public void testSerializeAndParse() throws Exception { TestMap.Builder builder = TestMap.newBuilder(); - setMapValuesUsingMutableMap(builder); + setMapValuesUsingAccessors(builder); TestMap message = builder.build(); assertEquals(message.getSerializedSize(), message.toByteString().size()); message = TestMap.parser().parseFrom(message.toByteString()); assertMapValuesSet(message); builder = message.toBuilder(); - updateMapValuesUsingMutableMap(builder); + updateMapValuesUsingAccessors(builder); message = builder.build(); assertEquals(message.getSerializedSize(), message.toByteString().size()); message = TestMap.parser().parseFrom(message.toByteString()); @@ -577,12 +576,12 @@ public class MapTest extends TestCase { TestMap map = tryParseTestMap(BizarroTestMap.newBuilder() .putInt32ToInt32Field(5, bytes) .build()); - assertEquals(map.getInt32ToInt32FieldOrDefault(5, -1), 0); + assertEquals(0, map.getInt32ToInt32FieldOrDefault(5, -1)); map = tryParseTestMap(BizarroTestMap.newBuilder() .putInt32ToStringField(stringKey, 5) .build()); - assertEquals(map.getInt32ToStringFieldOrDefault(0, null), ""); + assertEquals("", map.getInt32ToStringFieldOrDefault(0, null)); map = tryParseTestMap(BizarroTestMap.newBuilder() .putInt32ToBytesField(stringKey, 5) @@ -592,7 +591,7 @@ public class MapTest extends TestCase { map = tryParseTestMap(BizarroTestMap.newBuilder() .putInt32ToEnumField(stringKey, bytes) .build()); - assertEquals(map.getInt32ToEnumFieldOrDefault(0, null), TestMap.EnumValue.FOO); + assertEquals(TestMap.EnumValue.FOO, map.getInt32ToEnumFieldOrDefault(0, null)); try { tryParseTestMap(BizarroTestMap.newBuilder() @@ -608,12 +607,12 @@ public class MapTest extends TestCase { map = tryParseTestMap(BizarroTestMap.newBuilder() .putStringToInt32Field(stringKey, bytes) .build()); - assertEquals(map.getStringToInt32FieldOrDefault(stringKey, -1), 0); + assertEquals(0, map.getStringToInt32FieldOrDefault(stringKey, -1)); } public void testMergeFrom() throws Exception { TestMap.Builder builder = TestMap.newBuilder(); - setMapValuesUsingMutableMap(builder); + setMapValuesUsingAccessors(builder); TestMap message = builder.build(); TestMap.Builder other = TestMap.newBuilder(); @@ -627,23 +626,23 @@ public class MapTest extends TestCase { // We can't control the order of elements in a HashMap. The best we can do // here is to add elements in different order. - TestMap.Builder b1 = TestMap.newBuilder(); - b1.getMutableInt32ToInt32Field().put(1, 2); - b1.getMutableInt32ToInt32Field().put(3, 4); - b1.getMutableInt32ToInt32Field().put(5, 6); + TestMap.Builder b1 = TestMap.newBuilder() + .putInt32ToInt32Field(1, 2) + .putInt32ToInt32Field(3, 4) + .putInt32ToInt32Field(5, 6); TestMap m1 = b1.build(); - TestMap.Builder b2 = TestMap.newBuilder(); - b2.getMutableInt32ToInt32Field().put(5, 6); - b2.getMutableInt32ToInt32Field().put(1, 2); - b2.getMutableInt32ToInt32Field().put(3, 4); + TestMap.Builder b2 = TestMap.newBuilder() + .putInt32ToInt32Field(5, 6) + .putInt32ToInt32Field(1, 2) + .putInt32ToInt32Field(3, 4); TestMap m2 = b2.build(); assertEquals(m1, m2); assertEquals(m1.hashCode(), m2.hashCode()); // Make sure we did compare map fields. - b2.getMutableInt32ToInt32Field().put(1, 0); + b2.putInt32ToInt32Field(1, 0); m2 = b2.build(); assertFalse(m1.equals(m2)); // Don't check m1.hashCode() != m2.hashCode() because it's not guaranteed @@ -651,7 +650,7 @@ public class MapTest extends TestCase { // Regression test for b/18549190: if a map is a subset of the other map, // equals() should return false. - b2.getMutableInt32ToInt32Field().remove(1); + b2.removeInt32ToInt32Field(1); m2 = b2.build(); assertFalse(m1.equals(m2)); assertFalse(m2.equals(m1)); @@ -660,20 +659,19 @@ public class MapTest extends TestCase { public void testNestedBuilderOnChangeEventPropagation() { TestOnChangeEventPropagation.Builder parent = TestOnChangeEventPropagation.newBuilder(); - parent.getOptionalMessageBuilder().getMutableInt32ToInt32Field().put(1, 2); + parent.getOptionalMessageBuilder().putInt32ToInt32Field(1, 2); TestOnChangeEventPropagation message = parent.build(); assertEquals(2, message.getOptionalMessage().getInt32ToInt32Field().get(1).intValue()); // Make a change using nested builder. - parent.getOptionalMessageBuilder().getMutableInt32ToInt32Field().put(1, 3); + parent.getOptionalMessageBuilder().putInt32ToInt32Field(1, 3); // Should be able to observe the change. message = parent.build(); assertEquals(3, message.getOptionalMessage().getInt32ToInt32Field().get(1).intValue()); // Make another change using mergeFrom() - TestMap.Builder other = TestMap.newBuilder(); - other.getMutableInt32ToInt32Field().put(1, 4); + TestMap.Builder other = TestMap.newBuilder().putInt32ToInt32Field(1, 4); parent.getOptionalMessageBuilder().mergeFrom(other.build()); // Should be able to observe the change. @@ -696,8 +694,7 @@ public class MapTest extends TestCase { TestMap.Builder testMapBuilder = parentBuilder.getOptionalMessageBuilder(); // Create a map entry message. - TestMap.Builder entryBuilder = TestMap.newBuilder(); - entryBuilder.getMutableInt32ToInt32Field().put(1, 1); + TestMap.Builder entryBuilder = TestMap.newBuilder().putInt32ToInt32Field(1, 1); // Put the entry into the nested builder. testMapBuilder.addRepeatedField( @@ -708,7 +705,7 @@ public class MapTest extends TestCase { assertEquals(1, message.getOptionalMessage().getInt32ToInt32Field().size()); // Change the entry value. - entryBuilder.getMutableInt32ToInt32Field().put(1, 4); + entryBuilder.putInt32ToInt32Field(1, 4); testMapBuilder = parentBuilder.getOptionalMessageBuilder(); testMapBuilder.setRepeatedField( intMapField, 0, entryBuilder.getRepeatedField(intMapField, 0)); @@ -795,13 +792,11 @@ public class MapTest extends TestCase { public void testReflectionApi() throws Exception { // In reflection API, map fields are just repeated message fields. - TestMap.Builder builder = TestMap.newBuilder(); - builder.getMutableInt32ToInt32Field().put(1, 2); - builder.getMutableInt32ToInt32Field().put(3, 4); - builder.getMutableInt32ToMessageField().put( - 11, MessageValue.newBuilder().setValue(22).build()); - builder.getMutableInt32ToMessageField().put( - 33, MessageValue.newBuilder().setValue(44).build()); + TestMap.Builder builder = TestMap.newBuilder() + .putInt32ToInt32Field(1, 2) + .putInt32ToInt32Field(3, 4) + .putInt32ToMessageField(11, MessageValue.newBuilder().setValue(22).build()) + .putInt32ToMessageField(33, MessageValue.newBuilder().setValue(44).build()); TestMap message = builder.build(); // Test getField(), getRepeatedFieldCount(), getRepeatedField(). @@ -869,9 +864,10 @@ public class MapTest extends TestCase { assertEquals(55, message.getInt32ToInt32Field().get(55).intValue()); } + // See additional coverage in TextFormatTest.java. public void testTextFormat() throws Exception { TestMap.Builder builder = TestMap.newBuilder(); - setMapValuesUsingMutableMap(builder); + setMapValuesUsingAccessors(builder); TestMap message = builder.build(); String textData = TextFormat.printToString(message); @@ -885,7 +881,7 @@ public class MapTest extends TestCase { public void testDynamicMessage() throws Exception { TestMap.Builder builder = TestMap.newBuilder(); - setMapValuesUsingMutableMap(builder); + setMapValuesUsingAccessors(builder); TestMap message = builder.build(); Message dynamicDefaultInstance = @@ -897,6 +893,24 @@ public class MapTest extends TestCase { assertEquals(message.hashCode(), dynamicMessage.hashCode()); } + // Check that DynamicMessage handles map field serialization the same way as generated code + // regarding unset key and value field in a map entry. + public void testDynamicMessageUnsetKeyAndValue() throws Exception { + FieldDescriptor field = f("int32_to_int32_field"); + + Message dynamicDefaultInstance = + DynamicMessage.getDefaultInstance(TestMap.getDescriptor()); + Message.Builder builder = dynamicDefaultInstance.newBuilderForType(); + // Add an entry without key and value. + builder.addRepeatedField(field, builder.newBuilderForField(field).build()); + Message message = builder.build(); + ByteString bytes = message.toByteString(); + // Parse it back to the same generated type. + Message generatedMessage = TestMap.parseFrom(bytes); + // Assert the serialized bytes are equivalent. + assertEquals(generatedMessage.toByteString(), bytes); + } + public void testReflectionEqualsAndHashCode() throws Exception { // Test that generated equals() and hashCode() will disregard the order // of map entries when comparing/hashing map fields. @@ -930,10 +944,11 @@ public class MapTest extends TestCase { } public void testUnknownEnumValues() throws Exception { - TestMap.Builder builder = TestMap.newBuilder(); - builder.getMutableInt32ToEnumFieldValue().put(0, 0); - builder.getMutableInt32ToEnumFieldValue().put(1, 1); - builder.getMutableInt32ToEnumFieldValue().put(2, 1000); // unknown value. + TestMap.Builder builder = TestMap.newBuilder() + .putAllInt32ToEnumFieldValue(newMap( + 0, 0, + 1, 1, + 2, 1000)); // unknown value. TestMap message = builder.build(); assertEquals(TestMap.EnumValue.FOO, @@ -956,7 +971,7 @@ public class MapTest extends TestCase { assertEquals(1000, builder.getInt32ToEnumFieldValue().get(2).intValue()); // hashCode()/equals() should take unknown enum values into account. - builder.getMutableInt32ToEnumFieldValue().put(2, 1001); + builder.putAllInt32ToEnumFieldValue(newMap(2, 1001)); TestMap message2 = builder.build(); assertFalse(message.hashCode() == message2.hashCode()); assertFalse(message.equals(message2)); @@ -970,15 +985,13 @@ public class MapTest extends TestCase { EnumDescriptor enumDescriptor = TestMap.EnumValue.getDescriptor(); FieldDescriptor field = descriptor.findFieldByName("int32_to_enum_field"); - Map<Integer, Integer> data = new HashMap<Integer, Integer>(); - data.put(0, 0); - data.put(1, 1); - data.put(2, 1000); // unknown value. + Map<Integer, Integer> data = newMap( + 0, 0, + 1, 1, + 2, 1000); // unknown value - TestMap.Builder builder = TestMap.newBuilder(); - for (Map.Entry<Integer, Integer> entry : data.entrySet()) { - builder.getMutableInt32ToEnumFieldValue().put(entry.getKey(), entry.getValue()); - } + TestMap.Builder builder = TestMap.newBuilder() + .putAllInt32ToEnumFieldValue(data); // Try to read unknown enum values using reflection API. for (int i = 0; i < builder.getRepeatedFieldCount(field); i++) { @@ -1002,7 +1015,7 @@ public class MapTest extends TestCase { public void testIterationOrder() throws Exception { TestMap.Builder builder = TestMap.newBuilder(); - setMapValuesUsingMutableMap(builder); + setMapValuesUsingAccessors(builder); TestMap message = builder.build(); assertEquals(Arrays.asList("1", "2", "3"), @@ -1011,7 +1024,7 @@ public class MapTest extends TestCase { public void testGetMap() { TestMap.Builder builder = TestMap.newBuilder(); - setMapValuesUsingMutableMap(builder); + setMapValuesUsingAccessors(builder); TestMap message = builder.build(); assertEquals( message.getStringToInt32Field(), @@ -1032,7 +1045,7 @@ public class MapTest extends TestCase { public void testContains() { TestMap.Builder builder = TestMap.newBuilder(); - setMapValuesUsingMutableMap(builder); + setMapValuesUsingAccessors(builder); assertMapContainsSetValues(builder); assertMapContainsSetValues(builder.build()); } @@ -1073,7 +1086,7 @@ public class MapTest extends TestCase { TestMap.Builder builder = TestMap.newBuilder(); assertMapCounts(0, builder); - setMapValuesUsingMutableMap(builder); + setMapValuesUsingAccessors(builder); assertMapCounts(3, builder); TestMap message = builder.build(); @@ -1250,12 +1263,9 @@ public class MapTest extends TestCase { builder.putInt32ToEnumFieldValue(1, TestMap.EnumValue.BAR.getNumber()); assertEquals( TestMap.EnumValue.BAR.getNumber(), builder.getInt32ToEnumFieldValueOrThrow(1)); - try { - builder.putInt32ToEnumFieldValue(1, -1); - fail(); - } catch (IllegalArgumentException e) { - // expected - } + builder.putInt32ToEnumFieldValue(1, -1); + assertEquals(-1, builder.getInt32ToEnumFieldValueOrThrow(1)); + assertEquals(TestMap.EnumValue.UNRECOGNIZED, builder.getInt32ToEnumFieldOrThrow(1)); builder.putStringToInt32Field("a", 1); assertEquals(1, builder.getStringToInt32FieldOrThrow("a")); @@ -1268,7 +1278,7 @@ public class MapTest extends TestCase { public void testRemove() { TestMap.Builder builder = TestMap.newBuilder(); - setMapValuesUsingMutableMap(builder); + setMapValuesUsingAccessors(builder); assertEquals(11, builder.getInt32ToInt32FieldOrThrow(1)); for (int times = 0; times < 2; times++) { builder.removeInt32ToInt32Field(1); @@ -1307,6 +1317,171 @@ public class MapTest extends TestCase { } } + public void testReservedWordsFieldNames() { + ReservedAsMapField.newBuilder().build(); + ReservedAsMapFieldWithEnumValue.newBuilder().build(); + } + + public void testDeterministicSerialziation() throws Exception { + TestMap.Builder builder = TestMap.newBuilder(); + // int32->int32 + builder.putInt32ToInt32Field(5, 1); + builder.putInt32ToInt32Field(1, 1); + builder.putInt32ToInt32Field(4, 1); + builder.putInt32ToInt32Field(-2, 1); + builder.putInt32ToInt32Field(0, 1); + + // uint32->int32 + builder.putUint32ToInt32Field(5, 1); + builder.putUint32ToInt32Field(1, 1); + builder.putUint32ToInt32Field(4, 1); + builder.putUint32ToInt32Field(-2, 1); + builder.putUint32ToInt32Field(0, 1); + + // int64->int32 + builder.putInt64ToInt32Field(5L, 1); + builder.putInt64ToInt32Field(1L, 1); + builder.putInt64ToInt32Field(4L, 1); + builder.putInt64ToInt32Field(-2L, 1); + builder.putInt64ToInt32Field(0L, 1); + + // string->int32 + builder.putStringToInt32Field("baz", 1); + builder.putStringToInt32Field("foo", 1); + builder.putStringToInt32Field("bar", 1); + builder.putStringToInt32Field("", 1); + builder.putStringToInt32Field("hello", 1); + builder.putStringToInt32Field("world", 1); + + TestMap message = builder.build(); + byte[] serialized = new byte[message.getSerializedSize()]; + CodedOutputStream output = CodedOutputStream.newInstance(serialized); + output.useDeterministicSerialization(); + message.writeTo(output); + output.flush(); + + CodedInputStream input = CodedInputStream.newInstance(serialized); + List<Integer> int32Keys = new ArrayList<Integer>(); + List<Integer> uint32Keys = new ArrayList<Integer>(); + List<Long> int64Keys = new ArrayList<Long>(); + List<String> stringKeys = new ArrayList<String>(); + int tag; + while (true) { + tag = input.readTag(); + if (tag == 0) { + break; + } + int length = input.readRawVarint32(); + int oldLimit = input.pushLimit(length); + switch (WireFormat.getTagFieldNumber(tag)) { + case TestMap.STRING_TO_INT32_FIELD_FIELD_NUMBER: + stringKeys.add(readMapStringKey(input)); + break; + case TestMap.INT32_TO_INT32_FIELD_FIELD_NUMBER: + int32Keys.add(readMapIntegerKey(input)); + break; + case TestMap.UINT32_TO_INT32_FIELD_FIELD_NUMBER: + uint32Keys.add(readMapIntegerKey(input)); + break; + case TestMap.INT64_TO_INT32_FIELD_FIELD_NUMBER: + int64Keys.add(readMapLongKey(input)); + break; + default: + fail("Unexpected fields."); + } + input.popLimit(oldLimit); + } + assertEquals( + Arrays.asList(-2, 0, 1, 4, 5), + int32Keys); + assertEquals( + Arrays.asList(-2, 0, 1, 4, 5), + uint32Keys); + assertEquals( + Arrays.asList(-2L, 0L, 1L, 4L, 5L), + int64Keys); + assertEquals( + Arrays.asList("", "bar", "baz", "foo", "hello", "world"), + stringKeys); + } + + public void testInitFromPartialDynamicMessage() { + FieldDescriptor fieldDescriptor = + TestMap.getDescriptor().findFieldByNumber(TestMap.INT32_TO_MESSAGE_FIELD_FIELD_NUMBER); + Descriptor mapEntryType = fieldDescriptor.getMessageType(); + FieldDescriptor keyField = mapEntryType.findFieldByNumber(1); + FieldDescriptor valueField = mapEntryType.findFieldByNumber(2); + DynamicMessage dynamicMessage = + DynamicMessage.newBuilder(TestMap.getDescriptor()) + .addRepeatedField( + fieldDescriptor, + DynamicMessage.newBuilder(mapEntryType) + .setField(keyField, 10) + .setField(valueField, TestMap.MessageValue.newBuilder().setValue(10).build()) + .build()) + .build(); + TestMap message = TestMap.newBuilder().mergeFrom(dynamicMessage).build(); + assertEquals( + TestMap.MessageValue.newBuilder().setValue(10).build(), + message.getInt32ToMessageFieldMap().get(10)); + } + + public void testInitFromFullyDynamicMessage() { + FieldDescriptor fieldDescriptor = + TestMap.getDescriptor().findFieldByNumber(TestMap.INT32_TO_MESSAGE_FIELD_FIELD_NUMBER); + Descriptor mapEntryType = fieldDescriptor.getMessageType(); + FieldDescriptor keyField = mapEntryType.findFieldByNumber(1); + FieldDescriptor valueField = mapEntryType.findFieldByNumber(2); + DynamicMessage dynamicMessage = + DynamicMessage.newBuilder(TestMap.getDescriptor()) + .addRepeatedField( + fieldDescriptor, + DynamicMessage.newBuilder(mapEntryType) + .setField(keyField, 10) + .setField( + valueField, + DynamicMessage.newBuilder(TestMap.MessageValue.getDescriptor()) + .setField( + TestMap.MessageValue.getDescriptor().findFieldByName("value"), 10) + .build()) + .build()) + .build(); + TestMap message = TestMap.newBuilder().mergeFrom(dynamicMessage).build(); + assertEquals( + TestMap.MessageValue.newBuilder().setValue(10).build(), + message.getInt32ToMessageFieldMap().get(10)); + } + + private int readMapIntegerKey(CodedInputStream input) throws IOException { + int tag = input.readTag(); + assertEquals(WireFormat.makeTag(1, WireFormat.WIRETYPE_VARINT), tag); + int ret = input.readInt32(); + // skip the value field. + input.skipField(input.readTag()); + assertTrue(input.isAtEnd()); + return ret; + } + + private long readMapLongKey(CodedInputStream input) throws IOException { + int tag = input.readTag(); + assertEquals(WireFormat.makeTag(1, WireFormat.WIRETYPE_VARINT), tag); + long ret = input.readInt64(); + // skip the value field. + input.skipField(input.readTag()); + assertTrue(input.isAtEnd()); + return ret; + } + + private String readMapStringKey(CodedInputStream input) throws IOException { + int tag = input.readTag(); + assertEquals(WireFormat.makeTag(1, WireFormat.WIRETYPE_LENGTH_DELIMITED), tag); + String ret = input.readString(); + // skip the value field. + input.skipField(input.readTag()); + assertTrue(input.isAtEnd()); + return ret; + } + private static <K, V> Map<K, V> newMap(K key1, V value1) { Map<K, V> map = new HashMap<K, V>(); map.put(key1, value1); @@ -1319,4 +1494,49 @@ public class MapTest extends TestCase { map.put(key2, value2); return map; } + + private static <K, V> Map<K, V> newMap(K key1, V value1, K key2, V value2, K key3, V value3) { + Map<K, V> map = new HashMap<K, V>(); + map.put(key1, value1); + map.put(key2, value2); + map.put(key3, value3); + return map; + } + + public void testMap_withNulls() { + TestMap.Builder builder = TestMap.newBuilder(); + + try { + builder.putStringToInt32Field(null, 3); + fail(); + } catch (NullPointerException expected) { + } + + try { + builder.putAllStringToInt32Field(newMap(null, 3, "hi", 4)); + fail(); + } catch (NullPointerException expected) { + } + + try { + builder.putInt32ToMessageField(3, null); + fail(); + } catch (NullPointerException expected) { + } + + try { + builder.putAllInt32ToMessageField( + MapTest.<Integer, MessageValue>newMap(4, null, 5, null)); + fail(); + } catch (NullPointerException expected) { + } + + try { + builder.putAllInt32ToMessageField(null); + fail(); + } catch (NullPointerException expected) { + } + + assertArrayEquals(new byte[0], builder.build().toByteArray()); + } } |