diff options
Diffstat (limited to 'common/tests/unit/src/com/android/net/module/util/StructTest.java')
-rw-r--r-- | common/tests/unit/src/com/android/net/module/util/StructTest.java | 1075 |
1 files changed, 0 insertions, 1075 deletions
diff --git a/common/tests/unit/src/com/android/net/module/util/StructTest.java b/common/tests/unit/src/com/android/net/module/util/StructTest.java deleted file mode 100644 index b4da0439..00000000 --- a/common/tests/unit/src/com/android/net/module/util/StructTest.java +++ /dev/null @@ -1,1075 +0,0 @@ -/* - * Copyright (C) 2020 The Android Open Source Project - * - * 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. - */ - -package com.android.net.module.util; - -import static com.android.testutils.MiscAsserts.assertThrows; - -import static org.junit.Assert.assertArrayEquals; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotEquals; -import static org.junit.Assert.assertTrue; - -import android.annotation.SuppressLint; -import android.net.InetAddresses; -import android.net.IpPrefix; -import android.net.MacAddress; - -import androidx.test.filters.SmallTest; -import androidx.test.runner.AndroidJUnit4; - -import com.android.net.module.util.Struct.Field; -import com.android.net.module.util.Struct.Type; - -import org.junit.Test; -import org.junit.runner.RunWith; - -import java.math.BigInteger; -import java.net.Inet4Address; -import java.net.Inet6Address; -import java.net.InetAddress; -import java.nio.BufferOverflowException; -import java.nio.ByteBuffer; -import java.nio.ByteOrder; -import java.util.Arrays; - -@RunWith(AndroidJUnit4.class) -@SmallTest -public class StructTest { - - // IPv6, 0 bytes of options, ifindex 15715755: 0x00efcdab, type 134 (RA), code 0, padding. - private static final String HDR_EMPTY = "0a00" + "0000" + "abcdef00" + "8600000000000000"; - - // UBE16: 0xfeff, UBE32: 0xfeffffff, UBE64: 0xfeffffffffffffff, UBE63: 0x7effffffffffffff - private static final String NETWORK_ORDER_MSG = "feff" + "feffffff" + "feffffffffffffff" - + "7effffffffffffff"; - - // S8: 0x7f, S16: 0x7fff, S32: 0x7fffffff, S64: 0x7fffffffffffffff - private static final String SIGNED_DATA = "7f" + "ff7f" + "ffffff7f" + "ffffffffffffff7f"; - - // nS8: 0x81, nS16: 0x8001, nS32: 0x80000001, nS64: 800000000000000001 - private static final String SIGNED_NEGATIVE_DATA = "81" + "0180" + "01000080" - + "0100000000000080"; - - // U8: 0xff, U16: 0xffff, U32: 0xffffffff, U64: 0xffffffffffffffff, U63: 0x7fffffffffffffff, - // U63: 0xffffffffffffffff(-1L) - private static final String UNSIGNED_DATA = "ff" + "ffff" + "ffffffff" + "ffffffffffffffff" - + "ffffffffffffff7f" + "ffffffffffffffff"; - - // PREF64 option, 2001:db8:3:4:5:6::/96, lifetime: 10064 - private static final String OPT_PREF64 = "2750" + "20010db80003000400050006"; - private static final byte[] TEST_PREFIX64 = new byte[]{ - (byte) 0x20, (byte) 0x01, (byte) 0x0d, (byte) 0xb8, (byte) 0x00, (byte) 0x03, - (byte) 0x00, (byte) 0x04, (byte) 0x00, (byte) 0x05, (byte) 0x00, (byte) 0x06, - }; - - private static final Inet4Address TEST_IPV4_ADDRESS = - (Inet4Address) InetAddresses.parseNumericAddress("192.168.100.1"); - private static final Inet6Address TEST_IPV6_ADDRESS = - (Inet6Address) InetAddresses.parseNumericAddress("2001:db8:3:4:5:6:7:8"); - - private <T> T doParsingMessageTest(final String hexString, final Class<T> clazz, - final ByteOrder order) { - final ByteBuffer buf = toByteBuffer(hexString); - buf.order(order); - return Struct.parse(clazz, buf); - } - - public static class HeaderMsgWithConstructor extends Struct { - static int sType; - static int sLength; - - @Field(order = 0, type = Type.U8, padding = 1) - public final short mFamily; - @Field(order = 1, type = Type.U16) - public final int mLen; - @Field(order = 2, type = Type.S32) - public final int mIfindex; - @Field(order = 3, type = Type.U8) - public final short mIcmpType; - @Field(order = 4, type = Type.U8, padding = 6) - public final short mIcmpCode; - - HeaderMsgWithConstructor(final short family, final int len, final int ifindex, - final short type, final short code) { - mFamily = family; - mLen = len; - mIfindex = ifindex; - mIcmpType = type; - mIcmpCode = code; - } - } - - private void verifyHeaderParsing(final HeaderMsgWithConstructor msg) { - assertEquals(10, msg.mFamily); - assertEquals(0, msg.mLen); - assertEquals(15715755, msg.mIfindex); - assertEquals(134, msg.mIcmpType); - assertEquals(0, msg.mIcmpCode); - - assertEquals(16, Struct.getSize(HeaderMsgWithConstructor.class)); - assertArrayEquals(toByteBuffer(HDR_EMPTY).array(), - msg.writeToBytes(ByteOrder.LITTLE_ENDIAN)); - } - - @Test - public void testClassWithExplicitConstructor() { - final HeaderMsgWithConstructor msg = doParsingMessageTest(HDR_EMPTY, - HeaderMsgWithConstructor.class, ByteOrder.LITTLE_ENDIAN); - verifyHeaderParsing(msg); - } - - public static class HeaderMsgWithoutConstructor extends Struct { - static int sType; - static int sLength; - - @Field(order = 0, type = Type.U8, padding = 1) - public short mFamily; - @Field(order = 1, type = Type.U16) - public int mLen; - @Field(order = 2, type = Type.S32) - public int mIfindex; - @Field(order = 3, type = Type.U8) - public short mIcmpType; - @Field(order = 4, type = Type.U8, padding = 6) - public short mIcmpCode; - } - - @Test - public void testClassWithDefaultConstructor() { - final HeaderMsgWithoutConstructor msg = doParsingMessageTest(HDR_EMPTY, - HeaderMsgWithoutConstructor.class, ByteOrder.LITTLE_ENDIAN); - assertEquals(10, msg.mFamily); - assertEquals(0, msg.mLen); - assertEquals(15715755, msg.mIfindex); - assertEquals(134, msg.mIcmpType); - assertEquals(0, msg.mIcmpCode); - - assertEquals(16, Struct.getSize(HeaderMsgWithoutConstructor.class)); - assertArrayEquals(toByteBuffer(HDR_EMPTY).array(), - msg.writeToBytes(ByteOrder.LITTLE_ENDIAN)); - } - - public static class HeaderMessage { - @Field(order = 0, type = Type.U8, padding = 1) - short mFamily; - @Field(order = 1, type = Type.U16) - int mLen; - @Field(order = 2, type = Type.S32) - int mIfindex; - @Field(order = 3, type = Type.U8) - short mIcmpType; - @Field(order = 4, type = Type.U8, padding = 6) - short mIcmpCode; - } - - @Test - public void testInvalidClass_NotSubClass() { - final ByteBuffer buf = toByteBuffer(HDR_EMPTY); - assertThrows(IllegalArgumentException.class, () -> Struct.parse(HeaderMessage.class, buf)); - } - - public static class HeaderMessageMissingAnnotation extends Struct { - @Field(order = 0, type = Type.U8, padding = 1) - short mFamily; - @Field(order = 1, type = Type.U16) - int mLen; - int mIfindex; - @Field(order = 2, type = Type.U8) - short mIcmpType; - @Field(order = 3, type = Type.U8, padding = 6) - short mIcmpCode; - } - - @Test - public void testInvalidClass_MissingAnnotationField() { - final ByteBuffer buf = toByteBuffer(HDR_EMPTY); - assertThrows(IllegalArgumentException.class, - () -> Struct.parse(HeaderMessageMissingAnnotation.class, buf)); - } - - public static class NetworkOrderMessage extends Struct { - @Field(order = 0, type = Type.UBE16) - public final int mUBE16; - @Field(order = 1, type = Type.UBE32) - public final long mUBE32; - @Field(order = 2, type = Type.UBE64) - public final BigInteger mUBE64; - @Field(order = 3, type = Type.UBE63) - public final long mUBE63; - - NetworkOrderMessage(final int be16, final long be32, final BigInteger be64, - final long be63) { - mUBE16 = be16; - mUBE32 = be32; - mUBE64 = be64; - mUBE63 = be63; - } - } - - @Test - public void testNetworkOrder() { - final NetworkOrderMessage msg = doParsingMessageTest(NETWORK_ORDER_MSG, - NetworkOrderMessage.class, ByteOrder.LITTLE_ENDIAN); - assertEquals(65279, msg.mUBE16); - assertEquals(4278190079L, msg.mUBE32); - assertEquals(new BigInteger("18374686479671623679"), msg.mUBE64); - assertEquals(9151314442816847871L, msg.mUBE63); - - assertEquals(22, Struct.getSize(NetworkOrderMessage.class)); - assertArrayEquals(toByteBuffer(NETWORK_ORDER_MSG).array(), - msg.writeToBytes(ByteOrder.LITTLE_ENDIAN)); - } - - public static class UnsignedDataMessage extends Struct { - @Field(order = 0, type = Type.U8) - public final short mU8; - @Field(order = 1, type = Type.U16) - public final int mU16; - @Field(order = 2, type = Type.U32) - public final long mU32; - @Field(order = 3, type = Type.U64) - public final BigInteger mU64; - @Field(order = 4, type = Type.U63) - public final long mU63; - @Field(order = 5, type = Type.U63) - public final long mLU64; // represent U64 data with U63 type - - UnsignedDataMessage(final short u8, final int u16, final long u32, final BigInteger u64, - final long u63, final long lu64) { - mU8 = u8; - mU16 = u16; - mU32 = u32; - mU64 = u64; - mU63 = u63; - mLU64 = lu64; - } - } - - @Test - public void testUnsignedData() { - final UnsignedDataMessage msg = doParsingMessageTest(UNSIGNED_DATA, - UnsignedDataMessage.class, ByteOrder.LITTLE_ENDIAN); - assertEquals(255, msg.mU8); - assertEquals(65535, msg.mU16); - assertEquals(4294967295L, msg.mU32); - assertEquals(new BigInteger("18446744073709551615"), msg.mU64); - assertEquals(9223372036854775807L, msg.mU63); - assertEquals(-1L, msg.mLU64); - - assertEquals(31, Struct.getSize(UnsignedDataMessage.class)); - assertArrayEquals(toByteBuffer(UNSIGNED_DATA).array(), - msg.writeToBytes(ByteOrder.LITTLE_ENDIAN)); - } - - public static class U64DataMessage extends Struct { - @Field(order = 0, type = Type.U64) long mU64; - } - - @Test - public void testInvalidType_U64WithLongPrimitive() { - assertThrows(IllegalArgumentException.class, - () -> Struct.parse(U64DataMessage.class, toByteBuffer("ffffffffffffffff"))); - } - - // BigInteger U64: 0x0000000000001234, BigInteger UBE64: 0x0000000000001234, BigInteger U64: 0 - private static final String SMALL_VALUE_BIGINTEGER = "3412000000000000" + "0000000000001234" - + "0000000000000000"; - - public static class SmallValueBigInteger extends Struct { - @Field(order = 0, type = Type.U64) public final BigInteger mSmallValue; - @Field(order = 1, type = Type.UBE64) public final BigInteger mBSmallValue; - @Field(order = 2, type = Type.U64) public final BigInteger mZero; - - SmallValueBigInteger(final BigInteger smallValue, final BigInteger bSmallValue, - final BigInteger zero) { - mSmallValue = smallValue; - mBSmallValue = bSmallValue; - mZero = zero; - } - } - - @Test - public void testBigIntegerSmallValueOrZero() { - final SmallValueBigInteger msg = doParsingMessageTest(SMALL_VALUE_BIGINTEGER, - SmallValueBigInteger.class, ByteOrder.LITTLE_ENDIAN); - assertEquals(new BigInteger("4660"), msg.mSmallValue); - assertEquals(new BigInteger("4660"), msg.mBSmallValue); - assertEquals(new BigInteger("0"), msg.mZero); - - assertEquals(24, Struct.getSize(SmallValueBigInteger.class)); - assertArrayEquals(toByteBuffer(SMALL_VALUE_BIGINTEGER).array(), - msg.writeToBytes(ByteOrder.LITTLE_ENDIAN)); - } - - public static class SignedDataMessage extends Struct { - @Field(order = 0, type = Type.S8) - public final byte mS8; - @Field(order = 1, type = Type.S16) - public final short mS16; - @Field(order = 2, type = Type.S32) - public final int mS32; - @Field(order = 3, type = Type.S64) - public final long mS64; - - SignedDataMessage(final byte s8, final short s16, final int s32, final long s64) { - mS8 = s8; - mS16 = s16; - mS32 = s32; - mS64 = s64; - } - } - - @Test - public void testSignedPositiveData() { - final SignedDataMessage msg = doParsingMessageTest(SIGNED_DATA, SignedDataMessage.class, - ByteOrder.LITTLE_ENDIAN); - assertEquals(127, msg.mS8); - assertEquals(32767, msg.mS16); - assertEquals(2147483647, msg.mS32); - assertEquals(9223372036854775807L, msg.mS64); - - assertEquals(15, Struct.getSize(SignedDataMessage.class)); - assertArrayEquals(toByteBuffer(SIGNED_DATA).array(), - msg.writeToBytes(ByteOrder.LITTLE_ENDIAN)); - } - - @Test - public void testSignedNegativeData() { - final SignedDataMessage msg = doParsingMessageTest(SIGNED_NEGATIVE_DATA, - SignedDataMessage.class, ByteOrder.LITTLE_ENDIAN); - assertEquals(-127, msg.mS8); - assertEquals(-32767, msg.mS16); - assertEquals(-2147483647, msg.mS32); - assertEquals(-9223372036854775807L, msg.mS64); - - assertEquals(15, Struct.getSize(SignedDataMessage.class)); - assertArrayEquals(toByteBuffer(SIGNED_NEGATIVE_DATA).array(), - msg.writeToBytes(ByteOrder.LITTLE_ENDIAN)); - } - - public static class HeaderMessageWithDuplicateOrder extends Struct { - @Field(order = 0, type = Type.U8, padding = 1) - short mFamily; - @Field(order = 1, type = Type.U16) - int mLen; - @Field(order = 2, type = Type.S32) - int mIfindex; - @Field(order = 2, type = Type.U8) - short mIcmpType; - @Field(order = 3, type = Type.U8, padding = 6) - short mIcmpCode; - } - - @Test - public void testInvalidClass_DuplicateFieldOrder() { - final ByteBuffer buf = toByteBuffer(HDR_EMPTY); - assertThrows(IllegalArgumentException.class, - () -> Struct.parse(HeaderMessageWithDuplicateOrder.class, buf)); - } - - public static class HeaderMessageWithNegativeOrder extends Struct { - @Field(order = 0, type = Type.U8, padding = 1) - short mFamily; - @Field(order = 1, type = Type.U16) - int mLen; - @Field(order = 2, type = Type.S32) - int mIfindex; - @Field(order = 3, type = Type.U8) - short mIcmpType; - @Field(order = -4, type = Type.U8, padding = 6) - short mIcmpCode; - } - - @Test - public void testInvalidClass_NegativeFieldOrder() { - final ByteBuffer buf = toByteBuffer(HDR_EMPTY); - assertThrows(IllegalArgumentException.class, - () -> Struct.parse(HeaderMessageWithNegativeOrder.class, buf)); - } - - public static class HeaderMessageOutOfIndexBounds extends Struct { - @Field(order = 0, type = Type.U8, padding = 1) - short mFamily; - @Field(order = 1, type = Type.U16) - int mLen; - @Field(order = 2, type = Type.S32) - int mIfindex; - @Field(order = 3, type = Type.U8) - short mIcmpType; - @Field(order = 5, type = Type.U8, padding = 6) - short mIcmpCode; - } - - @Test - public void testInvalidClass_OutOfIndexBounds() { - final ByteBuffer buf = toByteBuffer(HDR_EMPTY); - assertThrows(IllegalArgumentException.class, - () -> Struct.parse(HeaderMessageOutOfIndexBounds.class, buf)); - } - - public static class HeaderMessageMismatchedPrimitiveType extends Struct { - @Field(order = 0, type = Type.U8, padding = 1) - short mFamily; - @Field(order = 1, type = Type.U16) - short mLen; // should be integer - @Field(order = 2, type = Type.S32) - int mIfindex; - @Field(order = 3, type = Type.U8) - short mIcmpType; - @Field(order = 4, type = Type.U8, padding = 6) - short mIcmpCode; - } - - @Test - public void testInvalidClass_MismatchedPrimitiveDataType() { - final ByteBuffer buf = toByteBuffer(HDR_EMPTY); - assertThrows(IllegalArgumentException.class, - () -> Struct.parse(HeaderMessageMismatchedPrimitiveType.class, buf)); - } - - public static class PrefixMessage extends Struct { - @Field(order = 0, type = Type.UBE16) - public final int mLifetime; - @Field(order = 1, type = Type.ByteArray, arraysize = 12) - public final byte[] mPrefix; - - PrefixMessage(final int lifetime, final byte[] prefix) { - mLifetime = lifetime; - mPrefix = prefix; - } - } - - @SuppressLint("NewApi") - private void verifyPrefixByteArrayParsing(final PrefixMessage msg) throws Exception { - // The original PREF64 option message has just 12 bytes for prefix byte array - // (Highest 96 bits of the Prefix), copyOf pads the 128-bits IPv6 address with - // prefix and 4-bytes zeros. - final InetAddress addr = InetAddress.getByAddress(Arrays.copyOf(msg.mPrefix, 16)); - final IpPrefix prefix = new IpPrefix(addr, 96); - assertEquals(10064, msg.mLifetime); - assertTrue(prefix.equals(new IpPrefix("2001:db8:3:4:5:6::/96"))); - - assertEquals(14, Struct.getSize(PrefixMessage.class)); - assertArrayEquals(toByteBuffer(OPT_PREF64).array(), - msg.writeToBytes(ByteOrder.LITTLE_ENDIAN)); - } - - public static class PrefixMessageWithZeroLengthArray extends Struct { - @Field(order = 0, type = Type.UBE16) - final int mLifetime; - @Field(order = 1, type = Type.ByteArray, arraysize = 0) - final byte[] mPrefix; - - PrefixMessageWithZeroLengthArray(final int lifetime, final byte[] prefix) { - mLifetime = lifetime; - mPrefix = prefix; - } - } - - @Test - public void testInvalidClass_ZeroLengthByteArray() { - final ByteBuffer buf = toByteBuffer(OPT_PREF64); - assertThrows(IllegalArgumentException.class, - () -> Struct.parse(PrefixMessageWithZeroLengthArray.class, buf)); - } - - @Test - public void testPrefixArrayField() throws Exception { - final PrefixMessage msg = doParsingMessageTest(OPT_PREF64, PrefixMessage.class, - ByteOrder.LITTLE_ENDIAN); - verifyPrefixByteArrayParsing(msg); - } - - public static class HeaderMessageWithMutableField extends Struct { - @Field(order = 0, type = Type.U8, padding = 1) - final short mFamily; - @Field(order = 1, type = Type.U16) - final int mLen; - @Field(order = 2, type = Type.S32) - int mIfindex; - @Field(order = 3, type = Type.U8) - short mIcmpType; - @Field(order = 4, type = Type.U8, padding = 6) - final short mIcmpCode; - - HeaderMessageWithMutableField(final short family, final int len, final short code) { - mFamily = family; - mLen = len; - mIcmpCode = code; - } - } - - @Test - public void testMixMutableAndImmutableFields() { - final ByteBuffer buf = toByteBuffer(HDR_EMPTY); - assertThrows(IllegalArgumentException.class, - () -> Struct.parse(HeaderMessageWithMutableField.class, buf)); - } - - public static class HeaderMsgWithStaticConstant extends Struct { - private static final String TAG = "HeaderMessage"; - private static final int FIELD_COUNT = 5; - - @Field(order = 0, type = Type.U8, padding = 1) - public final short mFamily; - @Field(order = 1, type = Type.U16) - public final int mLen; - @Field(order = 2, type = Type.S32) - public final int mIfindex; - @Field(order = 3, type = Type.U8) - public final short mIcmpType; - @Field(order = 4, type = Type.U8, padding = 6) - public final short mIcmpCode; - - HeaderMsgWithStaticConstant(final short family, final int len, final int ifindex, - final short type, final short code) { - mFamily = family; - mLen = len; - mIfindex = ifindex; - mIcmpType = type; - mIcmpCode = code; - } - } - - @Test - public void testStaticConstantField() { - final HeaderMsgWithStaticConstant msg = doParsingMessageTest(HDR_EMPTY, - HeaderMsgWithStaticConstant.class, ByteOrder.LITTLE_ENDIAN); - assertEquals(10, msg.mFamily); - assertEquals(0, msg.mLen); - assertEquals(15715755, msg.mIfindex); - assertEquals(134, msg.mIcmpType); - assertEquals(0, msg.mIcmpCode); - - assertEquals(16, Struct.getSize(HeaderMsgWithStaticConstant.class)); - assertArrayEquals(toByteBuffer(HDR_EMPTY).array(), - msg.writeToBytes(ByteOrder.LITTLE_ENDIAN)); - } - - public static class MismatchedConstructor extends Struct { - @Field(order = 0, type = Type.U16) final int mInt1; - @Field(order = 1, type = Type.U16) final int mInt2; - MismatchedConstructor(String int1, String int2) { - mInt1 = Integer.valueOf(int1); - mInt2 = Integer.valueOf(int2); - } - } - - @Test - public void testMisMatchedConstructor() { - final ByteBuffer buf = toByteBuffer("1234" + "5678"); - assertThrows(IllegalArgumentException.class, - () -> Struct.parse(MismatchedConstructor.class, buf)); - } - - public static class ClassWithTwoConstructors extends Struct { - @Field(order = 0, type = Type.U16) public final int mInt1; - @Field(order = 1, type = Type.U16) public final int mInt2; - ClassWithTwoConstructors(String int1, String int2) { - mInt1 = Integer.valueOf(int1); - mInt2 = Integer.valueOf(int2); - } - ClassWithTwoConstructors(int int1, int int2) { - mInt1 = int1; - mInt2 = int2; - } - } - - @Test - public void testClassWithTwoConstructors() { - final ClassWithTwoConstructors msg = doParsingMessageTest("1234" + "5678", - ClassWithTwoConstructors.class, ByteOrder.LITTLE_ENDIAN); - assertEquals(13330 /* 0x3412 */, msg.mInt1); - assertEquals(30806 /* 0x7856 */, msg.mInt2); - - assertEquals(4, Struct.getSize(ClassWithTwoConstructors.class)); - assertArrayEquals(toByteBuffer("1234" + "5678").array(), - msg.writeToBytes(ByteOrder.LITTLE_ENDIAN)); - } - - @Test - public void testInvalidOutputByteBuffer_ZeroCapacity() { - final ByteBuffer output = ByteBuffer.allocate(0); - output.order(ByteOrder.LITTLE_ENDIAN); - final HeaderMsgWithConstructor msg = doParsingMessageTest(HDR_EMPTY, - HeaderMsgWithConstructor.class, ByteOrder.LITTLE_ENDIAN); - assertThrows(BufferOverflowException.class, () -> msg.writeToByteBuffer(output)); - } - - @Test - public void testConsecutiveWrites() { - final HeaderMsgWithConstructor msg1 = doParsingMessageTest(HDR_EMPTY, - HeaderMsgWithConstructor.class, ByteOrder.LITTLE_ENDIAN); - final PrefixMessage msg2 = doParsingMessageTest(OPT_PREF64, PrefixMessage.class, - ByteOrder.LITTLE_ENDIAN); - - int size = Struct.getSize(HeaderMsgWithConstructor.class) - + Struct.getSize(PrefixMessage.class); - final ByteBuffer output = ByteBuffer.allocate(size); - output.order(ByteOrder.LITTLE_ENDIAN); - - msg1.writeToByteBuffer(output); - msg2.writeToByteBuffer(output); - output.flip(); - - final ByteBuffer concat = ByteBuffer.allocate(size).put(toByteBuffer(HDR_EMPTY)) - .put(toByteBuffer(OPT_PREF64)); - assertArrayEquals(output.array(), concat.array()); - } - - @Test - public void testClassesParsedFromCache() throws Exception { - for (int i = 0; i < 100; i++) { - final HeaderMsgWithConstructor msg1 = doParsingMessageTest(HDR_EMPTY, - HeaderMsgWithConstructor.class, ByteOrder.LITTLE_ENDIAN); - verifyHeaderParsing(msg1); - - final PrefixMessage msg2 = doParsingMessageTest(OPT_PREF64, PrefixMessage.class, - ByteOrder.LITTLE_ENDIAN); - verifyPrefixByteArrayParsing(msg2); - } - } - - public static class BigEndianDataMessage extends Struct { - @Field(order = 0, type = Type.S32) public int mInt1; - @Field(order = 1, type = Type.S32) public int mInt2; - @Field(order = 2, type = Type.UBE16) public int mInt3; - @Field(order = 3, type = Type.U16) public int mInt4; - @Field(order = 4, type = Type.U64) public BigInteger mBigInteger1; - @Field(order = 5, type = Type.UBE64) public BigInteger mBigInteger2; - @Field(order = 6, type = Type.S64) public long mLong; - } - - private static final String BIG_ENDIAN_DATA = "00000001" + "fffffffe" + "fffe" + "fffe" - + "ff00004500002301" + "ff00004500002301" + "ff00004500002301"; - - @Test - public void testBigEndianByteBuffer() { - final BigEndianDataMessage msg = doParsingMessageTest(BIG_ENDIAN_DATA, - BigEndianDataMessage.class, ByteOrder.BIG_ENDIAN); - - assertEquals(1, msg.mInt1); - assertEquals(-2, msg.mInt2); - assertEquals(65534, msg.mInt3); - assertEquals(65534, msg.mInt4); - assertEquals(new BigInteger("18374686776024376065"), msg.mBigInteger1); - assertEquals(new BigInteger("18374686776024376065"), msg.mBigInteger2); - assertEquals(0xff00004500002301L, msg.mLong); - - assertEquals(36, Struct.getSize(BigEndianDataMessage.class)); - assertArrayEquals(toByteBuffer(BIG_ENDIAN_DATA).array(), - msg.writeToBytes(ByteOrder.BIG_ENDIAN)); - } - - private ByteBuffer toByteBuffer(final String hexString) { - return ByteBuffer.wrap(HexDump.hexStringToByteArray(hexString)); - } - - public static class MacAddressMessage extends Struct { - public @Field(order = 0, type = Type.EUI48) final MacAddress mMac1; - public @Field(order = 1, type = Type.EUI48) final MacAddress mMac2; - - MacAddressMessage(final MacAddress mac1, final MacAddress mac2) { - this.mMac1 = mac1; - this.mMac2 = mac2; - } - } - - @Test - public void testMacAddressType() { - final MacAddressMessage msg = doParsingMessageTest("001122334455" + "ffffffffffff", - MacAddressMessage.class, ByteOrder.BIG_ENDIAN); - - assertEquals(MacAddress.fromString("00:11:22:33:44:55"), msg.mMac1); - assertEquals(MacAddress.fromString("ff:ff:ff:ff:ff:ff"), msg.mMac2); - - assertEquals(12, Struct.getSize(MacAddressMessage.class)); - assertArrayEquals(toByteBuffer("001122334455" + "ffffffffffff").array(), - msg.writeToBytes(ByteOrder.BIG_ENDIAN)); - } - - public static class BadMacAddressType extends Struct { - @Field(order = 0, type = Type.EUI48) byte[] mMac; - } - - @Test - public void testIncorrectType_EUI48WithByteArray() { - assertThrows(IllegalArgumentException.class, - () -> Struct.parse(BadMacAddressType.class, toByteBuffer("ffffffffffff"))); - } - - @Test - public void testStructToByteArrayRoundTrip() { - final SignedDataMessage littleEndianMsg = doParsingMessageTest(SIGNED_DATA, - SignedDataMessage.class, ByteOrder.LITTLE_ENDIAN); - assertArrayEquals(toByteBuffer(SIGNED_DATA).array(), - littleEndianMsg.writeToBytes(ByteOrder.LITTLE_ENDIAN)); - - final SignedDataMessage bigEndianMsg = doParsingMessageTest(SIGNED_DATA, - SignedDataMessage.class, ByteOrder.BIG_ENDIAN); - assertArrayEquals(toByteBuffer(SIGNED_DATA).array(), - bigEndianMsg.writeToBytes(ByteOrder.BIG_ENDIAN)); - - final SignedDataMessage nativeOrderMsg = ByteOrder.nativeOrder().equals( - ByteOrder.LITTLE_ENDIAN) ? littleEndianMsg : bigEndianMsg; - assertArrayEquals(toByteBuffer(SIGNED_DATA).array(), - nativeOrderMsg.writeToBytes()); - } - - @Test - public void testStructToByteArray() { - final SignedDataMessage msg = new SignedDataMessage((byte) -5, (short) 42, (int) 0xff000004, - (long) 0xff000004ff000005L); - final String leHexString = "fb" + "2a00" + "040000ff" + "050000ff040000ff"; - final String beHexString = "fb" + "002a" + "ff000004" + "ff000004ff000005"; - final String hexString = ByteOrder.nativeOrder().equals(ByteOrder.LITTLE_ENDIAN) - ? leHexString : beHexString; - assertArrayEquals(toByteBuffer(hexString).array(), msg.writeToBytes()); - } - - public static class IpAddressMessage extends Struct { - @Field(order = 0, type = Type.Ipv4Address) public final Inet4Address ipv4Address; - @Field(order = 1, type = Type.Ipv6Address) public final Inet6Address ipv6Address; - - IpAddressMessage(final Inet4Address ipv4Address, final Inet6Address ipv6Address) { - this.ipv4Address = ipv4Address; - this.ipv6Address = ipv6Address; - } - } - - @Test - public void testIpAddressType() { - final IpAddressMessage msg = doParsingMessageTest("c0a86401" - + "20010db8000300040005000600070008", IpAddressMessage.class, ByteOrder.BIG_ENDIAN); - - assertEquals(TEST_IPV4_ADDRESS, msg.ipv4Address); - assertEquals(TEST_IPV6_ADDRESS, msg.ipv6Address); - - assertEquals(20, Struct.getSize(IpAddressMessage.class)); - assertArrayEquals(toByteBuffer("c0a86401" + "20010db8000300040005000600070008").array(), - msg.writeToBytes(ByteOrder.BIG_ENDIAN)); - } - - public static class WrongIpAddressType extends Struct { - @Field(order = 0, type = Type.Ipv4Address) public byte[] ipv4Address; - @Field(order = 1, type = Type.Ipv6Address) public byte[] ipv6Address; - } - - @Test - public void testIncorrectType_IpAddressWithByteArray() { - assertThrows(IllegalArgumentException.class, - () -> Struct.parse(WrongIpAddressType.class, - toByteBuffer("c0a86401" + "20010db8000300040005000600070008"))); - } - - public static class FullTypeMessage extends Struct { - @Field(order = 0, type = Type.U8) public final short u8; - @Field(order = 1, type = Type.U16) public final int u16; - @Field(order = 2, type = Type.U32) public final long u32; - @Field(order = 3, type = Type.U63) public final long u63; - @Field(order = 4, type = Type.U64) public final BigInteger u64; - @Field(order = 5, type = Type.S8) public final byte s8; - @Field(order = 6, type = Type.S16) public final short s16; - @Field(order = 7, type = Type.S32) public final int s32; - @Field(order = 8, type = Type.S64) public final long s64; - @Field(order = 9, type = Type.UBE16) public final int ube16; - @Field(order = 10, type = Type.UBE32) public final long ube32; - @Field(order = 11, type = Type.UBE63) public final long ube63; - @Field(order = 12, type = Type.UBE64) public final BigInteger ube64; - @Field(order = 13, type = Type.ByteArray, arraysize = 12) public final byte[] bytes; - @Field(order = 14, type = Type.EUI48) public final MacAddress eui48; - @Field(order = 15, type = Type.Ipv4Address) public final Inet4Address ipv4Address; - @Field(order = 16, type = Type.Ipv6Address) public final Inet6Address ipv6Address; - - FullTypeMessage(final short u8, final int u16, final long u32, final long u63, - final BigInteger u64, final byte s8, final short s16, final int s32, final long s64, - final int ube16, final long ube32, final long ube63, final BigInteger ube64, - final byte[] bytes, final MacAddress eui48, final Inet4Address ipv4Address, - final Inet6Address ipv6Address) { - this.u8 = u8; - this.u16 = u16; - this.u32 = u32; - this.u63 = u63; - this.u64 = u64; - this.s8 = s8; - this.s16 = s16; - this.s32 = s32; - this.s64 = s64; - this.ube16 = ube16; - this.ube32 = ube32; - this.ube63 = ube63; - this.ube64 = ube64; - this.bytes = bytes; - this.eui48 = eui48; - this.ipv4Address = ipv4Address; - this.ipv6Address = ipv6Address; - } - } - - private static final String FULL_TYPE_DATA = "ff" + "ffff" + "ffffffff" + "7fffffffffffffff" - + "ffffffffffffffff" + "7f" + "7fff" + "7fffffff" + "7fffffffffffffff" + "7fff" - + "7fffffff" + "7fffffffffffffff" + "ffffffffffffffff" + "20010db80003000400050006" - + "001122334455" + "c0a86401" + "20010db8000300040005000600070008"; - private static final String FULL_TYPE_DATA_DIFF_MAC = "ff" + "ffff" + "ffffffff" - + "7fffffffffffffff" + "ffffffffffffffff" + "7f" + "7fff" + "7fffffff" - + "7fffffffffffffff" + "7fff" + "7fffffff" + "7fffffffffffffff" + "ffffffffffffffff" - + "20010db80003000400050006" + "112233445566" - + "c0a86401" + "20010db8000300040005000600070008"; - private static final String FULL_TYPE_DATA_DIFF_LONG = "ff" + "ffff" + "ffffffff" - + "7ffffffffffffffe" + "ffffffffffffffff" + "7f" + "7fff" + "7fffffff" - + "7fffffffffffffff" + "7fff" + "7fffffff" + "7fffffffffffffff" + "ffffffffffffffff" - + "20010db80003000400050006" + "001122334455" - + "c0a86401" + "20010db8000300040005000600070008"; - private static final String FULL_TYPE_DATA_DIFF_INTEGER = "ff" + "ffff" + "ffffffff" - + "7fffffffffffffff" + "ffffffffffffffff" + "7f" + "7fff" + "7fffffff" - + "7fffffffffffffff" + "7fff" + "ffffff7f" + "7fffffffffffffff" + "ffffffffffffffff" - + "20010db80003000400050006" + "001122334455" - + "c0a86401" + "20010db8000300040005000600070008"; - private static final String FULL_TYPE_DATA_DIFF_IPV4 = "ff" + "ffff" + "ffffffff" - + "7fffffffffffffff" + "ffffffffffffffff" + "7f" + "7fff" + "7fffffff" - + "7fffffffffffffff" + "7fff" + "ffffff7f" + "7fffffffffffffff" + "ffffffffffffffff" - + "20010db80003000400050006" + "001122334455" - + "c0a81010" + "20010db8000300040005000600070008"; - private static final String FULL_TYPE_DATA_DIFF_IPV6 = "ff" + "ffff" + "ffffffff" - + "7fffffffffffffff" + "ffffffffffffffff" + "7f" + "7fff" + "7fffffff" - + "7fffffffffffffff" + "7fff" + "ffffff7f" + "7fffffffffffffff" + "ffffffffffffffff" - + "20010db80003000400050006" + "001122334455" - + "c0a86401" + "20010db800030004000500060007000a"; - @Test - public void testStructClass_equals() { - final FullTypeMessage msg = doParsingMessageTest(FULL_TYPE_DATA, FullTypeMessage.class, - ByteOrder.BIG_ENDIAN); - - assertEquals(255, msg.u8); - assertEquals(65535, msg.u16); - assertEquals(4294967295L, msg.u32); - assertEquals(9223372036854775807L, msg.u63); - assertEquals(new BigInteger("18446744073709551615"), msg.u64); - assertEquals(127, msg.s8); - assertEquals(32767, msg.s16); - assertEquals(2147483647, msg.s32); - assertEquals(9223372036854775807L, msg.s64); - assertEquals(32767, msg.ube16); - assertEquals(2147483647, msg.ube32); - assertEquals(9223372036854775807L, msg.ube63); - assertEquals(new BigInteger("18446744073709551615"), msg.ube64); - assertArrayEquals(TEST_PREFIX64, msg.bytes); - assertEquals(MacAddress.fromString("00:11:22:33:44:55"), msg.eui48); - assertEquals(TEST_IPV4_ADDRESS, msg.ipv4Address); - assertEquals(TEST_IPV6_ADDRESS, msg.ipv6Address); - - assertEquals(98, msg.getSize(FullTypeMessage.class)); - assertArrayEquals(toByteBuffer(FULL_TYPE_DATA).array(), - msg.writeToBytes(ByteOrder.BIG_ENDIAN)); - - final FullTypeMessage msg1 = new FullTypeMessage((short) 0xff, (int) 0xffff, - (long) 0xffffffffL, (long) 0x7fffffffffffffffL, - new BigInteger("18446744073709551615"), (byte) 0x7f, (short) 0x7fff, - (int) 0x7fffffff, (long) 0x7fffffffffffffffL, (int) 0x7fff, (long) 0x7fffffffL, - (long) 0x7fffffffffffffffL, new BigInteger("18446744073709551615"), TEST_PREFIX64, - MacAddress.fromString("00:11:22:33:44:55"), TEST_IPV4_ADDRESS, TEST_IPV6_ADDRESS); - assertTrue(msg.equals(msg1)); - } - - public static class FullTypeMessageWithDupType extends Struct { - @Field(order = 0, type = Type.U8) public final short u8; - @Field(order = 1, type = Type.U16) public final int u16; - @Field(order = 2, type = Type.U32) public final long u32; - @Field(order = 3, type = Type.S64) public final long u63; // old: U63, new: S64 - @Field(order = 4, type = Type.UBE64) public final BigInteger u64; // old: U64, new: UBE64 - @Field(order = 5, type = Type.S8) public final byte s8; - @Field(order = 6, type = Type.S16) public final short s16; - @Field(order = 7, type = Type.S32) public final int s32; - @Field(order = 8, type = Type.S64) public final long s64; - @Field(order = 9, type = Type.U16) public final int ube16; // old:UBE16, new: U16 - @Field(order = 10, type = Type.UBE32) public final long ube32; - @Field(order = 11, type = Type.UBE63) public final long ube63; - @Field(order = 12, type = Type.UBE64) public final BigInteger ube64; - @Field(order = 13, type = Type.ByteArray, arraysize = 12) public final byte[] bytes; - @Field(order = 14, type = Type.EUI48) public final MacAddress eui48; - @Field(order = 15, type = Type.Ipv4Address) public final Inet4Address ipv4Address; - @Field(order = 16, type = Type.Ipv6Address) public final Inet6Address ipv6Address; - - FullTypeMessageWithDupType(final short u8, final int u16, final long u32, final long u63, - final BigInteger u64, final byte s8, final short s16, final int s32, final long s64, - final int ube16, final long ube32, final long ube63, final BigInteger ube64, - final byte[] bytes, final MacAddress eui48, final Inet4Address ipv4Address, - final Inet6Address ipv6Address) { - this.u8 = u8; - this.u16 = u16; - this.u32 = u32; - this.u63 = u63; - this.u64 = u64; - this.s8 = s8; - this.s16 = s16; - this.s32 = s32; - this.s64 = s64; - this.ube16 = ube16; - this.ube32 = ube32; - this.ube63 = ube63; - this.ube64 = ube64; - this.bytes = bytes; - this.eui48 = eui48; - this.ipv4Address = ipv4Address; - this.ipv6Address = ipv6Address; - } - } - - @Test - public void testStructClass_notEqualWithDifferentClass() { - final FullTypeMessage msg = doParsingMessageTest(FULL_TYPE_DATA, FullTypeMessage.class, - ByteOrder.BIG_ENDIAN); - final FullTypeMessageWithDupType msg1 = doParsingMessageTest(FULL_TYPE_DATA, - FullTypeMessageWithDupType.class, ByteOrder.BIG_ENDIAN); - - assertFalse(msg.equals(msg1)); - } - - @Test - public void testStructClass_notEqualWithDifferentValue() { - final FullTypeMessage msg = doParsingMessageTest(FULL_TYPE_DATA, FullTypeMessage.class, - ByteOrder.BIG_ENDIAN); - - // With different MAC address. - final FullTypeMessage msg1 = doParsingMessageTest(FULL_TYPE_DATA_DIFF_MAC, - FullTypeMessage.class, ByteOrder.BIG_ENDIAN); - assertNotEquals(msg.eui48, msg1.eui48); - assertFalse(msg.equals(msg1)); - - // With different byte array. - final FullTypeMessage msg2 = doParsingMessageTest(FULL_TYPE_DATA, FullTypeMessage.class, - ByteOrder.BIG_ENDIAN); - msg2.bytes[5] = (byte) 42; // change one byte in the array. - assertFalse(msg.equals(msg2)); - - // With different Long primitive. - final FullTypeMessage msg3 = doParsingMessageTest(FULL_TYPE_DATA_DIFF_LONG, - FullTypeMessage.class, ByteOrder.BIG_ENDIAN); - assertNotEquals(msg.u63, msg3.u63); - assertFalse(msg.equals(msg3)); - - // With different Integer primitive. - final FullTypeMessage msg4 = doParsingMessageTest(FULL_TYPE_DATA_DIFF_INTEGER, - FullTypeMessage.class, ByteOrder.BIG_ENDIAN); - assertNotEquals(msg.ube32, msg4.ube32); - assertFalse(msg.equals(msg4)); - - // With different IPv4 address. - final FullTypeMessage msg5 = doParsingMessageTest(FULL_TYPE_DATA_DIFF_IPV4, - FullTypeMessage.class, ByteOrder.BIG_ENDIAN); - assertNotEquals(msg.ipv4Address, msg5.ipv4Address); - assertFalse(msg.equals(msg5)); - - // With different IPv6 address. - final FullTypeMessage msg6 = doParsingMessageTest(FULL_TYPE_DATA_DIFF_IPV6, - FullTypeMessage.class, ByteOrder.BIG_ENDIAN); - assertNotEquals(msg.ipv6Address, msg6.ipv6Address); - assertFalse(msg.equals(msg6)); - } - - @Test - public void testStructClass_toString() { - final String expected = "u8: 255, u16: 65535, u32: 4294967295," - + " u63: 9223372036854775807, u64: 18446744073709551615, s8: 127, s16: 32767," - + " s32: 2147483647, s64: 9223372036854775807, ube16: 32767, ube32: 2147483647," - + " ube63: 9223372036854775807, ube64: 18446744073709551615," - + " bytes: 0x20010DB80003000400050006," - + " eui48: 00:11:22:33:44:55," - + " ipv4Address: 192.168.100.1," - + " ipv6Address: 2001:db8:3:4:5:6:7:8"; - - final FullTypeMessage msg = doParsingMessageTest(FULL_TYPE_DATA, FullTypeMessage.class, - ByteOrder.BIG_ENDIAN); - assertEquals(expected, msg.toString()); - } - - @Test - public void testStructClass_toStringWithNullMember() { - final String expected = "u8: 255, u16: 65535, u32: 4294967295," - + " u63: 9223372036854775807, u64: null, s8: 127, s16: 32767," - + " s32: 2147483647, s64: 9223372036854775807, ube16: 32767, ube32: 2147483647," - + " ube63: 9223372036854775807, ube64: 18446744073709551615," - + " bytes: null, eui48: null, ipv4Address: 192.168.100.1," - + " ipv6Address: null"; - - final FullTypeMessage msg = new FullTypeMessage((short) 0xff, (int) 0xffff, - (long) 0xffffffffL, (long) 0x7fffffffffffffffL, - null /* u64 */, (byte) 0x7f, (short) 0x7fff, - (int) 0x7fffffff, (long) 0x7fffffffffffffffL, (int) 0x7fff, (long) 0x7fffffffL, - (long) 0x7fffffffffffffffL, new BigInteger("18446744073709551615"), - null /* bytes */, null /* eui48 */, TEST_IPV4_ADDRESS, null /* ipv6Address */); - assertEquals(expected, msg.toString()); - } - - @Test - public void testStructClass_hashcode() { - final FullTypeMessage msg = doParsingMessageTest(FULL_TYPE_DATA, FullTypeMessage.class, - ByteOrder.BIG_ENDIAN); - final FullTypeMessage msg1 = doParsingMessageTest(FULL_TYPE_DATA, FullTypeMessage.class, - ByteOrder.BIG_ENDIAN); - - assertNotEquals(0, msg.hashCode()); - assertNotEquals(0, msg1.hashCode()); - assertTrue(msg.equals(msg1)); - assertEquals(msg.hashCode(), msg1.hashCode()); - } - - public static class InvalidByteArray extends Struct { - @Field(order = 0, type = Type.ByteArray, arraysize = 12) public byte[] bytes; - } - - @Test - public void testStructClass_WrongByteArraySize() { - final InvalidByteArray msg = doParsingMessageTest("20010db80003000400050006", - InvalidByteArray.class, ByteOrder.BIG_ENDIAN); - - // Actual byte array size doesn't match the size declared in the annotation. - msg.bytes = new byte[16]; - assertThrows(IllegalStateException.class, () -> msg.writeToBytes()); - - final ByteBuffer output = ByteBuffer.allocate(Struct.getSize(InvalidByteArray.class)); - output.order(ByteOrder.LITTLE_ENDIAN); - assertThrows(IllegalStateException.class, () -> msg.writeToByteBuffer(output)); - } - - @Test - public void testStructClass_NullByteArray() { - final InvalidByteArray msg = doParsingMessageTest("20010db80003000400050006", - InvalidByteArray.class, ByteOrder.BIG_ENDIAN); - - msg.bytes = null; - assertThrows(NullPointerException.class, () -> msg.writeToBytes()); - - final ByteBuffer output = ByteBuffer.allocate(Struct.getSize(InvalidByteArray.class)); - output.order(ByteOrder.LITTLE_ENDIAN); - assertThrows(NullPointerException.class, () -> msg.writeToByteBuffer(output)); - } - - @Test - public void testStructClass_ParsingByteArrayAfterInitialization() { - InvalidByteArray msg = new InvalidByteArray(); - msg.bytes = new byte[]{(byte) 0x00, (byte) 0x01, (byte) 0x02, (byte) 0x03}; - - // Although bytes member has been initialized with the length different with - // annotation size, parsing from ByteBuffer will get bytes member have the - // reference to byte array with correct size. - msg = doParsingMessageTest("20010db80003000400050006", InvalidByteArray.class, - ByteOrder.BIG_ENDIAN); - assertArrayEquals(TEST_PREFIX64, msg.bytes); - } -} |