|
|
|
@ -33,6 +33,8 @@ package com.google.protobuf; |
|
|
|
|
import com.google.protobuf.nano.CodedInputByteBufferNano; |
|
|
|
|
import com.google.protobuf.nano.EnumClassNanoMultiple; |
|
|
|
|
import com.google.protobuf.nano.EnumClassNanos; |
|
|
|
|
import com.google.protobuf.nano.EnumValidity; |
|
|
|
|
import com.google.protobuf.nano.EnumValidityAccessors; |
|
|
|
|
import com.google.protobuf.nano.Extensions; |
|
|
|
|
import com.google.protobuf.nano.Extensions.AnotherMessage; |
|
|
|
|
import com.google.protobuf.nano.Extensions.MessageWithGroup; |
|
|
|
@ -2092,6 +2094,126 @@ public class NanoTest extends TestCase { |
|
|
|
|
assertEquals(nestedMsg2.bb, newMsg.repeatedNestedMessage[2].bb); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* Tests that invalid enum values from the wire are not accepted. |
|
|
|
|
*/ |
|
|
|
|
public void testNanoEnumValidity() throws Exception { |
|
|
|
|
final int invalid = 120; |
|
|
|
|
final int alsoInvalid = 121; |
|
|
|
|
|
|
|
|
|
EnumValidity.M m = new EnumValidity.M(); |
|
|
|
|
// Sanity check & baseline of the assertions for the first case below.
|
|
|
|
|
assertEquals(EnumValidity.E.default_, m.optionalE); |
|
|
|
|
assertEquals(EnumValidity.E.BAZ, m.defaultE); |
|
|
|
|
|
|
|
|
|
m.optionalE = invalid; |
|
|
|
|
m.defaultE = invalid; |
|
|
|
|
// E contains all valid values
|
|
|
|
|
m.repeatedE = new int[] {EnumValidity.E.FOO, EnumValidity.E.BAR}; |
|
|
|
|
m.packedE = new int[] {EnumValidity.E.FOO, EnumValidity.E.BAZ}; |
|
|
|
|
// E2 contains some invalid values
|
|
|
|
|
m.repeatedE2 = new int[] {invalid, EnumValidity.E.BAR, alsoInvalid}; |
|
|
|
|
m.packedE2 = new int[] {EnumValidity.E.FOO, invalid, alsoInvalid}; |
|
|
|
|
// E3 contains all invalid values
|
|
|
|
|
m.repeatedE3 = new int[] {invalid, invalid}; |
|
|
|
|
m.packedE3 = new int[] {alsoInvalid, alsoInvalid}; |
|
|
|
|
byte[] serialized = MessageNano.toByteArray(m); |
|
|
|
|
// Sanity check that we do have all data in the byte array.
|
|
|
|
|
assertEquals(31, serialized.length); |
|
|
|
|
|
|
|
|
|
// Test 1: tests that invalid values aren't included in the deserialized message.
|
|
|
|
|
EnumValidity.M deserialized = MessageNano.mergeFrom(new EnumValidity.M(), serialized); |
|
|
|
|
assertEquals(EnumValidity.E.default_, deserialized.optionalE); |
|
|
|
|
assertEquals(EnumValidity.E.BAZ, deserialized.defaultE); |
|
|
|
|
assertTrue(Arrays.equals( |
|
|
|
|
new int[] {EnumValidity.E.FOO, EnumValidity.E.BAR}, deserialized.repeatedE)); |
|
|
|
|
assertTrue(Arrays.equals( |
|
|
|
|
new int[] {EnumValidity.E.FOO, EnumValidity.E.BAZ}, deserialized.packedE)); |
|
|
|
|
assertTrue(Arrays.equals( |
|
|
|
|
new int[] {EnumValidity.E.BAR}, deserialized.repeatedE2)); |
|
|
|
|
assertTrue(Arrays.equals( |
|
|
|
|
new int[] {EnumValidity.E.FOO}, deserialized.packedE2)); |
|
|
|
|
assertEquals(0, deserialized.repeatedE3.length); |
|
|
|
|
assertEquals(0, deserialized.packedE3.length); |
|
|
|
|
|
|
|
|
|
// Test 2: tests that invalid values do not override previous values in the field, including
|
|
|
|
|
// arrays, including pre-existing invalid values.
|
|
|
|
|
deserialized.optionalE = EnumValidity.E.BAR; |
|
|
|
|
deserialized.defaultE = alsoInvalid; |
|
|
|
|
deserialized.repeatedE = new int[] {EnumValidity.E.BAZ}; |
|
|
|
|
deserialized.packedE = new int[] {EnumValidity.E.BAZ, alsoInvalid}; |
|
|
|
|
deserialized.repeatedE2 = new int[] {invalid, alsoInvalid}; |
|
|
|
|
deserialized.packedE2 = null; |
|
|
|
|
deserialized.repeatedE3 = null; |
|
|
|
|
deserialized.packedE3 = new int[0]; |
|
|
|
|
MessageNano.mergeFrom(deserialized, serialized); |
|
|
|
|
assertEquals(EnumValidity.E.BAR, deserialized.optionalE); |
|
|
|
|
assertEquals(alsoInvalid, deserialized.defaultE); |
|
|
|
|
assertTrue(Arrays.equals( |
|
|
|
|
new int[] {EnumValidity.E.BAZ, /* + */ EnumValidity.E.FOO, EnumValidity.E.BAR}, |
|
|
|
|
deserialized.repeatedE)); |
|
|
|
|
assertTrue(Arrays.equals( |
|
|
|
|
new int[] {EnumValidity.E.BAZ, alsoInvalid, /* + */ EnumValidity.E.FOO, EnumValidity.E.BAZ}, |
|
|
|
|
deserialized.packedE)); |
|
|
|
|
assertTrue(Arrays.equals( |
|
|
|
|
new int[] {invalid, alsoInvalid, /* + */ EnumValidity.E.BAR}, |
|
|
|
|
deserialized.repeatedE2)); |
|
|
|
|
assertTrue(Arrays.equals( |
|
|
|
|
new int[] {/* <null> + */ EnumValidity.E.FOO}, |
|
|
|
|
deserialized.packedE2)); |
|
|
|
|
assertNull(deserialized.repeatedE3); // null + all invalid == null
|
|
|
|
|
assertEquals(0, deserialized.packedE3.length); // empty + all invalid == empty
|
|
|
|
|
|
|
|
|
|
// Test 3: reading by alternative forms
|
|
|
|
|
EnumValidity.Alt alt = MessageNano.mergeFrom(new EnumValidity.Alt(), serialized); |
|
|
|
|
assertEquals(EnumValidity.E.BAR, // last valid value in m.repeatedE2
|
|
|
|
|
alt.repeatedE2AsOptional); |
|
|
|
|
assertTrue(Arrays.equals(new int[] {EnumValidity.E.FOO}, alt.packedE2AsNonPacked)); |
|
|
|
|
assertEquals(0, alt.nonPackedE3AsPacked.length); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* Tests the same as {@link #testNanoEnumValidity()} with accessor style. Repeated fields are |
|
|
|
|
* not re-tested here because they are not affected by the accessor style. |
|
|
|
|
*/ |
|
|
|
|
public void testNanoEnumValidityAccessors() throws Exception { |
|
|
|
|
final int invalid = 120; |
|
|
|
|
final int alsoInvalid = 121; |
|
|
|
|
|
|
|
|
|
EnumValidityAccessors.M m = new EnumValidityAccessors.M(); |
|
|
|
|
// Sanity check & baseline of the assertions for the first case below.
|
|
|
|
|
assertEquals(EnumValidityAccessors.default_, m.getOptionalE()); |
|
|
|
|
assertEquals(EnumValidityAccessors.BAZ, m.getDefaultE()); |
|
|
|
|
|
|
|
|
|
m.setOptionalE(invalid); |
|
|
|
|
m.setDefaultE(invalid); |
|
|
|
|
// Set repeatedE2 for Alt.repeatedE2AsOptional
|
|
|
|
|
m.repeatedE2 = new int[] {invalid, EnumValidityAccessors.BAR, alsoInvalid}; |
|
|
|
|
byte[] serialized = MessageNano.toByteArray(m); |
|
|
|
|
// Sanity check that we do have all data in the byte array.
|
|
|
|
|
assertEquals(10, serialized.length); |
|
|
|
|
|
|
|
|
|
// Test 1: tests that invalid values aren't included in the deserialized message.
|
|
|
|
|
EnumValidityAccessors.M deserialized = |
|
|
|
|
MessageNano.mergeFrom(new EnumValidityAccessors.M(), serialized); |
|
|
|
|
assertEquals(EnumValidityAccessors.default_, deserialized.getOptionalE()); |
|
|
|
|
assertEquals(EnumValidityAccessors.BAZ, deserialized.getDefaultE()); |
|
|
|
|
|
|
|
|
|
// Test 2: tests that invalid values do not override previous values in the field, including
|
|
|
|
|
// pre-existing invalid values.
|
|
|
|
|
deserialized.setOptionalE(EnumValidityAccessors.BAR); |
|
|
|
|
deserialized.setDefaultE(alsoInvalid); |
|
|
|
|
MessageNano.mergeFrom(deserialized, serialized); |
|
|
|
|
assertEquals(EnumValidityAccessors.BAR, deserialized.getOptionalE()); |
|
|
|
|
assertEquals(alsoInvalid, deserialized.getDefaultE()); |
|
|
|
|
|
|
|
|
|
// Test 3: reading by alternative forms
|
|
|
|
|
EnumValidityAccessors.Alt alt = |
|
|
|
|
MessageNano.mergeFrom(new EnumValidityAccessors.Alt(), serialized); |
|
|
|
|
assertEquals(EnumValidityAccessors.BAR, // last valid value in m.repeatedE2
|
|
|
|
|
alt.getRepeatedE2AsOptional()); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* Tests that code generation correctly wraps a single message into its outer |
|
|
|
|
* class. The class {@code SingleMessageNano} is imported from the outer |
|
|
|
@ -3248,12 +3370,16 @@ public class NanoTest extends TestCase { |
|
|
|
|
// Check that repeated fields with packable types can accept both packed and unpacked
|
|
|
|
|
// serialized forms.
|
|
|
|
|
NanoRepeatedPackables.NonPacked nonPacked = new NanoRepeatedPackables.NonPacked(); |
|
|
|
|
nonPacked.int32S = new int[] {1, 2, 3}; |
|
|
|
|
nonPacked.int64S = new long[] {4, 5, 6}; |
|
|
|
|
nonPacked.uint32S = new int[] {7, 8, 9}; |
|
|
|
|
nonPacked.uint64S = new long[] {10, 11, 12}; |
|
|
|
|
nonPacked.sint32S = new int[] {13, 14, 15}; |
|
|
|
|
nonPacked.sint64S = new long[] {16, 17, 18}; |
|
|
|
|
// Exaggerates the first values of varint-typed arrays. This is to test that the parsing code
|
|
|
|
|
// of packed fields handles non-packed data correctly. If the code incorrectly thinks it is
|
|
|
|
|
// reading from a packed tag, it will read the first value as the byte length of the field,
|
|
|
|
|
// and the large number will cause the input to go out of bounds, thus capturing the error.
|
|
|
|
|
nonPacked.int32S = new int[] {1000, 2, 3}; |
|
|
|
|
nonPacked.int64S = new long[] {4000, 5, 6}; |
|
|
|
|
nonPacked.uint32S = new int[] {7000, 8, 9}; |
|
|
|
|
nonPacked.uint64S = new long[] {10000, 11, 12}; |
|
|
|
|
nonPacked.sint32S = new int[] {13000, 14, 15}; |
|
|
|
|
nonPacked.sint64S = new long[] {16000, 17, 18}; |
|
|
|
|
nonPacked.fixed32S = new int[] {19, 20, 21}; |
|
|
|
|
nonPacked.fixed64S = new long[] {22, 23, 24}; |
|
|
|
|
nonPacked.sfixed32S = new int[] {25, 26, 27}; |
|
|
|
@ -3290,8 +3416,8 @@ public class NanoTest extends TestCase { |
|
|
|
|
nonPacked = MessageNano.mergeFrom(new NanoRepeatedPackables.NonPacked(), mixedSerialized); |
|
|
|
|
packed = MessageNano.mergeFrom(new NanoRepeatedPackables.Packed(), mixedSerialized); |
|
|
|
|
assertRepeatedPackablesEqual(nonPacked, packed); |
|
|
|
|
assertTrue(Arrays.equals(new int[] {1, 2, 3, 1, 2, 3}, nonPacked.int32S)); |
|
|
|
|
assertTrue(Arrays.equals(new int[] {13, 14, 15, 13, 14, 15}, nonPacked.sint32S)); |
|
|
|
|
assertTrue(Arrays.equals(new int[] {1000, 2, 3, 1000, 2, 3}, nonPacked.int32S)); |
|
|
|
|
assertTrue(Arrays.equals(new int[] {13000, 14, 15, 13000, 14, 15}, nonPacked.sint32S)); |
|
|
|
|
assertTrue(Arrays.equals(new int[] {25, 26, 27, 25, 26, 27}, nonPacked.sfixed32S)); |
|
|
|
|
assertTrue(Arrays.equals(new boolean[] {false, true, false, true}, nonPacked.bools)); |
|
|
|
|
} |
|
|
|
|