http://git-wip-us.apache.org/repos/asf/ignite/blob/1dbf20e0/modules/core/src/test/java/org/apache/ignite/internal/binary/BinaryMarshallerSelfTest.java ---------------------------------------------------------------------- diff --git a/modules/core/src/test/java/org/apache/ignite/internal/binary/BinaryMarshallerSelfTest.java b/modules/core/src/test/java/org/apache/ignite/internal/binary/BinaryMarshallerSelfTest.java new file mode 100644 index 0000000..d4f3acf --- /dev/null +++ b/modules/core/src/test/java/org/apache/ignite/internal/binary/BinaryMarshallerSelfTest.java @@ -0,0 +1,4209 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 org.apache.ignite.internal.binary; + +import java.io.Externalizable; +import java.io.IOException; +import java.io.ObjectInput; +import java.io.ObjectOutput; +import java.io.Serializable; +import java.lang.reflect.Field; +import java.lang.reflect.InvocationHandler; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.lang.reflect.Proxy; +import java.math.BigDecimal; +import java.math.BigInteger; +import java.net.InetSocketAddress; +import java.sql.Timestamp; +import java.util.AbstractQueue; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.Date; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.Queue; +import java.util.TreeMap; +import java.util.TreeSet; +import java.util.UUID; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentSkipListSet; +import junit.framework.Assert; +import org.apache.ignite.IgniteCheckedException; +import org.apache.ignite.binary.BinaryCollectionFactory; +import org.apache.ignite.binary.BinaryIdMapper; +import org.apache.ignite.binary.BinaryMapFactory; +import org.apache.ignite.binary.BinaryObject; +import org.apache.ignite.binary.BinaryObjectBuilder; +import org.apache.ignite.binary.BinaryObjectException; +import org.apache.ignite.binary.BinaryRawReader; +import org.apache.ignite.binary.BinaryRawWriter; +import org.apache.ignite.binary.BinaryReader; +import org.apache.ignite.binary.BinarySerializer; +import org.apache.ignite.binary.BinaryTypeConfiguration; +import org.apache.ignite.binary.BinaryWriter; +import org.apache.ignite.binary.Binarylizable; +import org.apache.ignite.configuration.BinaryConfiguration; +import org.apache.ignite.configuration.IgniteConfiguration; +import org.apache.ignite.internal.binary.builder.BinaryObjectBuilderImpl; +import org.apache.ignite.internal.processors.cache.CacheObjectContext; +import org.apache.ignite.internal.util.GridUnsafe; +import org.apache.ignite.internal.util.IgniteUtils; +import org.apache.ignite.internal.util.lang.GridMapEntry; +import org.apache.ignite.internal.util.typedef.F; +import org.apache.ignite.internal.util.typedef.internal.S; +import org.apache.ignite.internal.util.typedef.internal.U; +import org.apache.ignite.marshaller.MarshallerContextTestImpl; +import org.apache.ignite.testframework.GridTestUtils; +import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.jsr166.ConcurrentHashMap8; +import sun.misc.Unsafe; + +import static org.apache.ignite.internal.binary.streams.PortableMemoryAllocator.INSTANCE; +import static org.junit.Assert.assertArrayEquals; +import static org.junit.Assert.assertNotEquals; + +/** + * Portable marshaller tests. + */ +@SuppressWarnings({"OverlyStrongTypeCast", "ArrayHashCode", "ConstantConditions"}) +public class BinaryMarshallerSelfTest extends GridCommonAbstractTest { + /** */ + private static final Unsafe UNSAFE = GridUnsafe.unsafe(); + + /** */ + protected static final long BYTE_ARR_OFF = UNSAFE.arrayBaseOffset(byte[].class); + + /** + * @throws Exception If failed. + */ + public void testNull() throws Exception { + assertNull(marshalUnmarshal(null)); + } + + /** + * @throws Exception If failed. + */ + public void testByte() throws Exception { + assertEquals((byte) 100, marshalUnmarshal((byte)100).byteValue()); + } + + /** + * @throws Exception If failed. + */ + public void testShort() throws Exception { + assertEquals((short)100, marshalUnmarshal((short)100).shortValue()); + } + + /** + * @throws Exception If failed. + */ + public void testInt() throws Exception { + assertEquals(100, marshalUnmarshal(100).intValue()); + } + + /** + * @throws Exception If failed. + */ + public void testLong() throws Exception { + assertEquals(100L, marshalUnmarshal(100L).longValue()); + } + + /** + * @throws Exception If failed. + */ + public void testFloat() throws Exception { + assertEquals(100.001f, marshalUnmarshal(100.001f), 0); + } + + /** + * @throws Exception If failed. + */ + public void testDouble() throws Exception { + assertEquals(100.001d, marshalUnmarshal(100.001d), 0); + } + + /** + * @throws Exception If failed. + */ + public void testChar() throws Exception { + assertEquals((char)100, marshalUnmarshal((char)100).charValue()); + } + + /** + * @throws Exception If failed. + */ + public void testBoolean() throws Exception { + assertEquals(true, marshalUnmarshal(true).booleanValue()); + } + + /** + * @throws Exception If failed. + */ + public void testDecimal() throws Exception { + BigDecimal val; + + assertEquals((val = BigDecimal.ZERO), marshalUnmarshal(val)); + assertEquals((val = BigDecimal.valueOf(Long.MAX_VALUE, 0)), marshalUnmarshal(val)); + assertEquals((val = BigDecimal.valueOf(Long.MIN_VALUE, 0)), marshalUnmarshal(val)); + assertEquals((val = BigDecimal.valueOf(Long.MAX_VALUE, 8)), marshalUnmarshal(val)); + assertEquals((val = BigDecimal.valueOf(Long.MIN_VALUE, 8)), marshalUnmarshal(val)); + + assertEquals((val = new BigDecimal(new BigInteger("-79228162514264337593543950336"))), marshalUnmarshal(val)); + } + + /** + * @throws Exception If failed. + */ + public void testString() throws Exception { + assertEquals("str", marshalUnmarshal("str")); + } + + /** + * @throws Exception If failed. + */ + public void testUuid() throws Exception { + UUID uuid = UUID.randomUUID(); + + assertEquals(uuid, marshalUnmarshal(uuid)); + } + + /** + * @throws Exception If failed. + */ + public void testDate() throws Exception { + Date date = new Date(); + + Date val = marshalUnmarshal(date); + + assertEquals(date, val); + assertEquals(Date.class, val.getClass()); + } + + /** + * @throws Exception If failed. + */ + public void testTimestamp() throws Exception { + Timestamp ts = new Timestamp(System.currentTimeMillis()); + + ts.setNanos(999999999); + + assertEquals(ts, marshalUnmarshal(ts)); + } + + /** + * @throws Exception If failed. + */ + public void testByteArray() throws Exception { + byte[] arr = new byte[] {10, 20, 30}; + + assertArrayEquals(arr, marshalUnmarshal(arr)); + } + + /** + * @throws Exception If failed. + */ + public void testShortArray() throws Exception { + short[] arr = new short[] {10, 20, 30}; + + assertArrayEquals(arr, marshalUnmarshal(arr)); + } + + /** + * @throws Exception If failed. + */ + public void testIntArray() throws Exception { + int[] arr = new int[] {10, 20, 30}; + + assertArrayEquals(arr, marshalUnmarshal(arr)); + } + + /** + * @throws Exception If failed. + */ + public void testLongArray() throws Exception { + long[] arr = new long[] {10, 20, 30}; + + assertArrayEquals(arr, marshalUnmarshal(arr)); + } + + /** + * @throws Exception If failed. + */ + public void testFloatArray() throws Exception { + float[] arr = new float[] {10.1f, 20.1f, 30.1f}; + + assertArrayEquals(arr, marshalUnmarshal(arr), 0); + } + + /** + * @throws Exception If failed. + */ + public void testDoubleArray() throws Exception { + double[] arr = new double[] {10.1d, 20.1d, 30.1d}; + + assertArrayEquals(arr, marshalUnmarshal(arr), 0); + } + + /** + * @throws Exception If failed. + */ + public void testCharArray() throws Exception { + char[] arr = new char[] {10, 20, 30}; + + assertArrayEquals(arr, marshalUnmarshal(arr)); + } + + /** + * @throws Exception If failed. + */ + public void testBooleanArray() throws Exception { + boolean[] arr = new boolean[] {true, false, true}; + + assertBooleanArrayEquals(arr, marshalUnmarshal(arr)); + } + + /** + * @throws Exception If failed. + */ + public void testDecimalArray() throws Exception { + BigDecimal[] arr = new BigDecimal[] {BigDecimal.ZERO, BigDecimal.ONE, BigDecimal.TEN} ; + + assertArrayEquals(arr, marshalUnmarshal(arr)); + } + + /** + * @throws Exception If failed. + */ + public void testStringArray() throws Exception { + String[] arr = new String[] {"str1", "str2", "str3"}; + + assertArrayEquals(arr, marshalUnmarshal(arr)); + } + + /** + * @throws Exception If failed. + */ + public void testUuidArray() throws Exception { + UUID[] arr = new UUID[] {UUID.randomUUID(), UUID.randomUUID(), UUID.randomUUID()}; + + assertArrayEquals(arr, marshalUnmarshal(arr)); + } + + /** + * @throws Exception If failed. + */ + public void testDateArray() throws Exception { + Date[] arr = new Date[] {new Date(11111), new Date(22222), new Date(33333)}; + + assertArrayEquals(arr, marshalUnmarshal(arr)); + } + + /** + * @throws Exception If failed. + */ + public void testObjectArray() throws Exception { + Object[] arr = new Object[] {1, 2, 3}; + + assertArrayEquals(arr, marshalUnmarshal(arr)); + } + + /** + * @throws Exception If failed. + */ + public void testException() throws Exception { + Exception ex = new RuntimeException(); + + // Checks that Optimize marshaller will be used, because Throwable has writeObject method. + // Exception's stacktrace equals to zero-length array by default and generates at Throwable's writeObject method. + assertNotEquals(0, marshalUnmarshal(ex).getStackTrace().length); + } + + /** + * @throws Exception If failed. + */ + public void testCollection() throws Exception { + testCollection(new ArrayList<Integer>(3)); + testCollection(new LinkedHashSet<Integer>()); + testCollection(new HashSet<Integer>()); + testCollection(new TreeSet<Integer>()); + testCollection(new ConcurrentSkipListSet<Integer>()); + } + + /** + * @throws Exception If failed. + */ + private void testCollection(Collection<Integer> col) throws Exception { + col.add(1); + col.add(2); + col.add(3); + + assertEquals(col, marshalUnmarshal(col)); + } + + /** + * @throws Exception If failed. + */ + public void testMap() throws Exception { + testMap(new HashMap<Integer, String>()); + testMap(new LinkedHashMap<Integer, String>()); + testMap(new TreeMap<Integer, String>()); + testMap(new ConcurrentHashMap8<Integer, String>()); + testMap(new ConcurrentHashMap<Integer, String>()); + } + + /** + * @throws Exception If failed. + */ + private void testMap(Map<Integer, String> map) throws Exception { + map.put(1, "str1"); + map.put(2, "str2"); + map.put(3, "str3"); + + assertEquals(map, marshalUnmarshal(map)); + } + + /** + * Test serialization of custom collections. + * + * @throws Exception If failed. + */ + @SuppressWarnings("unchecked") + public void testCustomCollections() throws Exception { + CustomCollections cc = new CustomCollections(); + + cc.list.add(1); + cc.customList.add(2); + + CustomCollections copiedCc = marshalUnmarshal(cc); + + assert copiedCc.customList.getClass().equals(CustomArrayList.class); + + assertEquals(cc.list.size(), copiedCc.list.size()); + assertEquals(cc.customList.size(), copiedCc.customList.size()); + + assertEquals(cc.list.get(0), copiedCc.list.get(0)); + assertEquals(cc.customList.get(0), copiedCc.customList.get(0)); + } + + /** + * Test custom collections with factories. + * + * @throws Exception If failed. + */ + @SuppressWarnings("unchecked") + public void testCustomCollectionsWithFactory() throws Exception { + CustomCollectionsWithFactory cc = new CustomCollectionsWithFactory(); + + cc.list.add(new DummyHolder(1)); + cc.map.put(new DummyHolder(2), new DummyHolder(3)); + + CustomCollectionsWithFactory copiedCc = marshalUnmarshal(cc); + + assertEquals(cc.list.size(), copiedCc.list.size()); + assertEquals(cc.map.size(), copiedCc.map.size()); + + assertEquals(cc.list.get(0), copiedCc.list.get(0)); + assertEquals(cc.map.get(new DummyHolder(2)), copiedCc.map.get(new DummyHolder(2))); + } + + /** + * @throws Exception If failed. + */ + public void testExternalizableHashCode() throws Exception { + SimpleExternalizable sim1 = new SimpleExternalizable("Simple"); + SimpleExternalizable sim2 = new SimpleExternalizable("Simple"); + + BinaryMarshaller marsh = binaryMarshaller(); + + BinaryObjectImpl sim1Binary = marshal(sim1, marsh); + BinaryObjectImpl sim2Binary = marshal(sim2, marsh); + + assertEquals(sim1.hashCode(), sim2.hashCode()); + assertEquals(sim1.hashCode(), sim1Binary.hashCode()); + assertEquals(sim2.hashCode(), sim2Binary.hashCode()); + } + + /** + * @throws Exception If failed. + */ + public void testExternalizableInEnclosing() throws Exception { + SimpleEnclosingObject obj = new SimpleEnclosingObject(); + obj.simpl = new SimpleExternalizable("field"); + + SimpleEnclosingObject other = marshalUnmarshal(obj); + + assertEquals(((SimpleExternalizable)obj.simpl).field, ((SimpleExternalizable)other.simpl).field); + } + + /** + * @throws Exception If failed. + */ + public void testMapEntry() throws Exception { + Map.Entry<Integer, String> e = new GridMapEntry<>(1, "str1"); + + assertEquals(e, marshalUnmarshal(e)); + + Map<Integer, String> map = new HashMap<>(1); + + map.put(2, "str2"); + + e = F.firstEntry(map); + + Map.Entry<Integer, String> e0 = marshalUnmarshal(e); + + assertEquals(2, e0.getKey().intValue()); + assertEquals("str2", e0.getValue()); + } + + /** + * @throws Exception If failed. + */ + public void testBinaryObject() throws Exception { + BinaryMarshaller marsh = binaryMarshaller(Arrays.asList(new BinaryTypeConfiguration(SimpleObject.class.getName()))); + + SimpleObject obj = simpleObject(); + + BinaryObject po = marshal(obj, marsh); + + BinaryObject po0 = marshalUnmarshal(po, marsh); + + assertTrue(po.hasField("b")); + assertTrue(po.hasField("s")); + assertTrue(po.hasField("i")); + assertTrue(po.hasField("l")); + assertTrue(po.hasField("f")); + assertTrue(po.hasField("d")); + assertTrue(po.hasField("c")); + assertTrue(po.hasField("bool")); + + assertFalse(po.hasField("no_such_field")); + + assertEquals(obj, po.deserialize()); + assertEquals(obj, po0.deserialize()); + } + + /** + * @throws Exception If failed. + */ + public void testEnum() throws Exception { + BinaryMarshaller marsh = binaryMarshaller(Arrays.asList(new BinaryTypeConfiguration(TestEnum.class.getName()))); + + assertEquals(TestEnum.B, marshalUnmarshal(TestEnum.B, marsh)); + } + + /** + * @throws Exception If failed. + */ + public void testDateAndTimestampInSingleObject() throws Exception { + BinaryTypeConfiguration cfg1 = new BinaryTypeConfiguration(DateClass1.class.getName()); + + BinaryMarshaller marsh = binaryMarshaller(Arrays.asList(cfg1)); + + Date date = new Date(); + Timestamp ts = new Timestamp(System.currentTimeMillis()); + + DateClass1 obj1 = new DateClass1(); + obj1.date = date; + obj1.ts = ts; + + BinaryObject po1 = marshal(obj1, marsh); + + assertEquals(date, po1.field("date")); + assertEquals(Date.class, po1.field("date").getClass()); + assertEquals(ts, po1.field("ts")); + assertEquals(Timestamp.class, po1.field("ts").getClass()); + + obj1 = po1.deserialize(); + assertEquals(date, obj1.date); + assertEquals(ts, obj1.ts); + } + + /** + * @throws Exception If failed. + */ + public void testSimpleObject() throws Exception { + BinaryMarshaller marsh = binaryMarshaller(Arrays.asList( + new BinaryTypeConfiguration(SimpleObject.class.getName()) + )); + + SimpleObject obj = simpleObject(); + + BinaryObject po = marshal(obj, marsh); + + assertEquals(obj.hashCode(), po.hashCode()); + + assertEquals(obj, po.deserialize()); + + assertEquals(obj.b, (byte)po.field("b")); + assertEquals(obj.s, (short)po.field("s")); + assertEquals(obj.i, (int)po.field("i")); + assertEquals(obj.l, (long)po.field("l")); + assertEquals(obj.f, (float)po.field("f"), 0); + assertEquals(obj.d, (double)po.field("d"), 0); + assertEquals(obj.c, (char)po.field("c")); + assertEquals(obj.bool, (boolean)po.field("bool")); + assertEquals(obj.str, po.field("str")); + assertEquals(obj.uuid, po.field("uuid")); + assertEquals(obj.date, po.field("date")); + assertEquals(Date.class, obj.date.getClass()); + assertEquals(obj.ts, po.field("ts")); + assertArrayEquals(obj.bArr, (byte[])po.field("bArr")); + assertArrayEquals(obj.sArr, (short[])po.field("sArr")); + assertArrayEquals(obj.iArr, (int[])po.field("iArr")); + assertArrayEquals(obj.lArr, (long[])po.field("lArr")); + assertArrayEquals(obj.fArr, (float[])po.field("fArr"), 0); + assertArrayEquals(obj.dArr, (double[])po.field("dArr"), 0); + assertArrayEquals(obj.cArr, (char[])po.field("cArr")); + assertBooleanArrayEquals(obj.boolArr, (boolean[])po.field("boolArr")); + assertArrayEquals(obj.strArr, (String[])po.field("strArr")); + assertArrayEquals(obj.uuidArr, (UUID[])po.field("uuidArr")); + assertArrayEquals(obj.dateArr, (Date[])po.field("dateArr")); + assertArrayEquals(obj.objArr, (Object[])po.field("objArr")); + assertEquals(obj.col, po.field("col")); + assertEquals(obj.map, po.field("map")); + assertEquals(new Integer(obj.enumVal.ordinal()), new Integer(((BinaryObject)po.field("enumVal")).enumOrdinal())); + assertArrayEquals(ordinals(obj.enumArr), ordinals((BinaryObject[])po.field("enumArr"))); + assertNull(po.field("unknown")); + + BinaryObject innerPo = po.field("inner"); + + assertEquals(obj.inner, innerPo.deserialize()); + + assertEquals(obj.inner.b, (byte)innerPo.field("b")); + assertEquals(obj.inner.s, (short)innerPo.field("s")); + assertEquals(obj.inner.i, (int)innerPo.field("i")); + assertEquals(obj.inner.l, (long)innerPo.field("l")); + assertEquals(obj.inner.f, (float)innerPo.field("f"), 0); + assertEquals(obj.inner.d, (double)innerPo.field("d"), 0); + assertEquals(obj.inner.c, (char)innerPo.field("c")); + assertEquals(obj.inner.bool, (boolean)innerPo.field("bool")); + assertEquals(obj.inner.str, innerPo.field("str")); + assertEquals(obj.inner.uuid, innerPo.field("uuid")); + assertEquals(obj.inner.date, innerPo.field("date")); + assertEquals(Date.class, obj.inner.date.getClass()); + assertEquals(obj.inner.ts, innerPo.field("ts")); + assertArrayEquals(obj.inner.bArr, (byte[])innerPo.field("bArr")); + assertArrayEquals(obj.inner.sArr, (short[])innerPo.field("sArr")); + assertArrayEquals(obj.inner.iArr, (int[])innerPo.field("iArr")); + assertArrayEquals(obj.inner.lArr, (long[])innerPo.field("lArr")); + assertArrayEquals(obj.inner.fArr, (float[])innerPo.field("fArr"), 0); + assertArrayEquals(obj.inner.dArr, (double[])innerPo.field("dArr"), 0); + assertArrayEquals(obj.inner.cArr, (char[])innerPo.field("cArr")); + assertBooleanArrayEquals(obj.inner.boolArr, (boolean[])innerPo.field("boolArr")); + assertArrayEquals(obj.inner.strArr, (String[])innerPo.field("strArr")); + assertArrayEquals(obj.inner.uuidArr, (UUID[])innerPo.field("uuidArr")); + assertArrayEquals(obj.inner.dateArr, (Date[])innerPo.field("dateArr")); + assertArrayEquals(obj.inner.objArr, (Object[])innerPo.field("objArr")); + assertEquals(obj.inner.col, innerPo.field("col")); + assertEquals(obj.inner.map, innerPo.field("map")); + assertEquals(new Integer(obj.inner.enumVal.ordinal()), + new Integer(((BinaryObject)innerPo.field("enumVal")).enumOrdinal())); + assertArrayEquals(ordinals(obj.inner.enumArr), ordinals((BinaryObject[])innerPo.field("enumArr"))); + assertNull(innerPo.field("inner")); + assertNull(innerPo.field("unknown")); + } + + /** + * @throws Exception If failed. + */ + public void testPortable() throws Exception { + BinaryMarshaller marsh = binaryMarshaller(Arrays.asList( + new BinaryTypeConfiguration(SimpleObject.class.getName()), + new BinaryTypeConfiguration(TestBinary.class.getName()) + )); + + TestBinary obj = binaryObject(); + + BinaryObject po = marshal(obj, marsh); + + assertEquals(obj.hashCode(), po.hashCode()); + + assertEquals(obj, po.deserialize()); + + assertEquals(obj.b, (byte)po.field("_b")); + assertEquals(obj.s, (short)po.field("_s")); + assertEquals(obj.i, (int)po.field("_i")); + assertEquals(obj.l, (long)po.field("_l")); + assertEquals(obj.f, (float)po.field("_f"), 0); + assertEquals(obj.d, (double)po.field("_d"), 0); + assertEquals(obj.c, (char)po.field("_c")); + assertEquals(obj.bool, (boolean)po.field("_bool")); + assertEquals(obj.str, po.field("_str")); + assertEquals(obj.uuid, po.field("_uuid")); + assertEquals(obj.date, po.field("_date")); + assertEquals(obj.ts, po.field("_ts")); + assertArrayEquals(obj.bArr, (byte[])po.field("_bArr")); + assertArrayEquals(obj.sArr, (short[])po.field("_sArr")); + assertArrayEquals(obj.iArr, (int[])po.field("_iArr")); + assertArrayEquals(obj.lArr, (long[])po.field("_lArr")); + assertArrayEquals(obj.fArr, (float[])po.field("_fArr"), 0); + assertArrayEquals(obj.dArr, (double[])po.field("_dArr"), 0); + assertArrayEquals(obj.cArr, (char[])po.field("_cArr")); + assertBooleanArrayEquals(obj.boolArr, (boolean[])po.field("_boolArr")); + assertArrayEquals(obj.strArr, (String[])po.field("_strArr")); + assertArrayEquals(obj.uuidArr, (UUID[])po.field("_uuidArr")); + assertArrayEquals(obj.dateArr, (Date[])po.field("_dateArr")); + assertArrayEquals(obj.objArr, (Object[])po.field("_objArr")); + assertEquals(obj.col, po.field("_col")); + assertEquals(obj.map, po.field("_map")); + assertEquals(new Integer(obj.enumVal.ordinal()), new Integer(((BinaryObject)po.field("_enumVal")).enumOrdinal())); + assertArrayEquals(ordinals(obj.enumArr), ordinals((BinaryObject[])po.field("_enumArr"))); + assertNull(po.field("unknown")); + + BinaryObject simplePo = po.field("_simple"); + + assertEquals(obj.simple, simplePo.deserialize()); + + assertEquals(obj.simple.b, (byte)simplePo.field("b")); + assertEquals(obj.simple.s, (short)simplePo.field("s")); + assertEquals(obj.simple.i, (int)simplePo.field("i")); + assertEquals(obj.simple.l, (long)simplePo.field("l")); + assertEquals(obj.simple.f, (float)simplePo.field("f"), 0); + assertEquals(obj.simple.d, (double)simplePo.field("d"), 0); + assertEquals(obj.simple.c, (char)simplePo.field("c")); + assertEquals(obj.simple.bool, (boolean)simplePo.field("bool")); + assertEquals(obj.simple.str, simplePo.field("str")); + assertEquals(obj.simple.uuid, simplePo.field("uuid")); + assertEquals(obj.simple.date, simplePo.field("date")); + assertEquals(Date.class, obj.simple.date.getClass()); + assertEquals(obj.simple.ts, simplePo.field("ts")); + assertArrayEquals(obj.simple.bArr, (byte[])simplePo.field("bArr")); + assertArrayEquals(obj.simple.sArr, (short[])simplePo.field("sArr")); + assertArrayEquals(obj.simple.iArr, (int[])simplePo.field("iArr")); + assertArrayEquals(obj.simple.lArr, (long[])simplePo.field("lArr")); + assertArrayEquals(obj.simple.fArr, (float[])simplePo.field("fArr"), 0); + assertArrayEquals(obj.simple.dArr, (double[])simplePo.field("dArr"), 0); + assertArrayEquals(obj.simple.cArr, (char[])simplePo.field("cArr")); + assertBooleanArrayEquals(obj.simple.boolArr, (boolean[])simplePo.field("boolArr")); + assertArrayEquals(obj.simple.strArr, (String[])simplePo.field("strArr")); + assertArrayEquals(obj.simple.uuidArr, (UUID[])simplePo.field("uuidArr")); + assertArrayEquals(obj.simple.dateArr, (Date[])simplePo.field("dateArr")); + assertArrayEquals(obj.simple.objArr, (Object[])simplePo.field("objArr")); + assertEquals(obj.simple.col, simplePo.field("col")); + assertEquals(obj.simple.map, simplePo.field("map")); + assertEquals(new Integer(obj.simple.enumVal.ordinal()), + new Integer(((BinaryObject)simplePo.field("enumVal")).enumOrdinal())); + assertArrayEquals(ordinals(obj.simple.enumArr), ordinals((BinaryObject[])simplePo.field("enumArr"))); + assertNull(simplePo.field("simple")); + assertNull(simplePo.field("portable")); + assertNull(simplePo.field("unknown")); + + BinaryObject portablePo = po.field("_portable"); + + assertEquals(obj.portable, portablePo.deserialize()); + + assertEquals(obj.portable.b, (byte)portablePo.field("_b")); + assertEquals(obj.portable.s, (short)portablePo.field("_s")); + assertEquals(obj.portable.i, (int)portablePo.field("_i")); + assertEquals(obj.portable.l, (long)portablePo.field("_l")); + assertEquals(obj.portable.f, (float)portablePo.field("_f"), 0); + assertEquals(obj.portable.d, (double)portablePo.field("_d"), 0); + assertEquals(obj.portable.c, (char)portablePo.field("_c")); + assertEquals(obj.portable.bool, (boolean)portablePo.field("_bool")); + assertEquals(obj.portable.str, portablePo.field("_str")); + assertEquals(obj.portable.uuid, portablePo.field("_uuid")); + assertEquals(obj.portable.date, portablePo.field("_date")); + assertEquals(obj.portable.ts, portablePo.field("_ts")); + assertArrayEquals(obj.portable.bArr, (byte[])portablePo.field("_bArr")); + assertArrayEquals(obj.portable.sArr, (short[])portablePo.field("_sArr")); + assertArrayEquals(obj.portable.iArr, (int[])portablePo.field("_iArr")); + assertArrayEquals(obj.portable.lArr, (long[])portablePo.field("_lArr")); + assertArrayEquals(obj.portable.fArr, (float[])portablePo.field("_fArr"), 0); + assertArrayEquals(obj.portable.dArr, (double[])portablePo.field("_dArr"), 0); + assertArrayEquals(obj.portable.cArr, (char[])portablePo.field("_cArr")); + assertBooleanArrayEquals(obj.portable.boolArr, (boolean[])portablePo.field("_boolArr")); + assertArrayEquals(obj.portable.strArr, (String[])portablePo.field("_strArr")); + assertArrayEquals(obj.portable.uuidArr, (UUID[])portablePo.field("_uuidArr")); + assertArrayEquals(obj.portable.dateArr, (Date[])portablePo.field("_dateArr")); + assertArrayEquals(obj.portable.objArr, (Object[])portablePo.field("_objArr")); + assertEquals(obj.portable.col, portablePo.field("_col")); + assertEquals(obj.portable.map, portablePo.field("_map")); + assertEquals(new Integer(obj.portable.enumVal.ordinal()), + new Integer(((BinaryObject)portablePo.field("_enumVal")).enumOrdinal())); + assertArrayEquals(ordinals(obj.portable.enumArr), ordinals((BinaryObject[])portablePo.field("_enumArr"))); + assertNull(portablePo.field("_simple")); + assertNull(portablePo.field("_portable")); + assertNull(portablePo.field("unknown")); + } + + /** + * @throws Exception If failed. + */ + public void testObjectFieldOfExternalizableCollection() throws Exception { + EnclosingObj obj = new EnclosingObj(); + + obj.queue = new TestQueue("test"); + + assertEquals(obj, marshalUnmarshal(obj)); + } + + /** + * + */ + private static class EnclosingObj implements Serializable { + /** Queue. */ + Queue<Integer> queue = new TestQueue("test"); + + /** {@inheritDoc} */ + @Override public boolean equals(Object o) { + if (this == o) + return true; + + if (o == null || getClass() != o.getClass()) + return false; + + EnclosingObj obj = (EnclosingObj)o; + + return Objects.equals(queue, obj.queue); + } + + /** {@inheritDoc} */ + @Override public int hashCode() { + return Objects.hash(queue); + } + } + + /** + * + */ + private static class TestQueue extends AbstractQueue<Integer> implements Externalizable { + /** Name. */ + private String name; + + /** + * @param name Name. + */ + public TestQueue(String name) { + this.name = name; + } + + /** {@inheritDoc} */ + @NotNull @Override public Iterator<Integer> iterator() { + return Collections.emptyIterator(); + } + + /** {@inheritDoc} */ + @Override public int size() { + return 0; + } + + /** {@inheritDoc} */ + @Override public void writeExternal(ObjectOutput out) throws IOException { + out.writeObject(name); + } + + /** {@inheritDoc} */ + @Override public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { + name = (String)in.readObject(); + } + + /** {@inheritDoc} */ + @Override public boolean offer(Integer integer) { + throw new UnsupportedOperationException(); + } + + /** {@inheritDoc} */ + @Override public Integer poll() { + throw new UnsupportedOperationException(); + } + + /** {@inheritDoc} */ + @Override public Integer peek() { + throw new UnsupportedOperationException(); + } + + /** {@inheritDoc} */ + @Override public boolean equals(Object o) { + if (this == o) + return true; + + if (o == null || getClass() != o.getClass()) + return false; + + TestQueue integers = (TestQueue)o; + + return Objects.equals(name, integers.name); + } + + /** {@inheritDoc} */ + @Override public int hashCode() { + return Objects.hash(name); + } + } + + /** + * @param obj Simple object. + * @param po Portable object. + */ + private void checkSimpleObjectData(SimpleObject obj, BinaryObject po) { + assertEquals(obj.b, (byte)po.field("b")); + assertEquals(obj.s, (short)po.field("s")); + assertEquals(obj.i, (int)po.field("i")); + assertEquals(obj.l, (long)po.field("l")); + assertEquals(obj.f, (float)po.field("f"), 0); + assertEquals(obj.d, (double)po.field("d"), 0); + assertEquals(obj.c, (char)po.field("c")); + assertEquals(obj.bool, (boolean)po.field("bool")); + assertEquals(obj.str, po.field("str")); + assertEquals(obj.uuid, po.field("uuid")); + assertEquals(obj.date, po.field("date")); + assertEquals(Date.class, obj.date.getClass()); + assertEquals(obj.ts, po.field("ts")); + assertArrayEquals(obj.bArr, (byte[])po.field("bArr")); + assertArrayEquals(obj.sArr, (short[])po.field("sArr")); + assertArrayEquals(obj.iArr, (int[])po.field("iArr")); + assertArrayEquals(obj.lArr, (long[])po.field("lArr")); + assertArrayEquals(obj.fArr, (float[])po.field("fArr"), 0); + assertArrayEquals(obj.dArr, (double[])po.field("dArr"), 0); + assertArrayEquals(obj.cArr, (char[])po.field("cArr")); + assertBooleanArrayEquals(obj.boolArr, (boolean[])po.field("boolArr")); + assertArrayEquals(obj.strArr, (String[])po.field("strArr")); + assertArrayEquals(obj.uuidArr, (UUID[])po.field("uuidArr")); + assertArrayEquals(obj.dateArr, (Date[])po.field("dateArr")); + assertArrayEquals(obj.objArr, (Object[])po.field("objArr")); + assertEquals(obj.col, po.field("col")); + assertEquals(obj.map, po.field("map")); + assertEquals(new Integer(obj.enumVal.ordinal()), new Integer(((BinaryObject)po.field("enumVal")).enumOrdinal())); + assertArrayEquals(ordinals(obj.enumArr), ordinals((BinaryObject[])po.field("enumArr"))); + assertNull(po.field("unknown")); + + assertEquals(obj, po.deserialize()); + } + + /** + * @throws Exception If failed. + */ + public void testClassWithoutPublicConstructor() throws Exception { + BinaryMarshaller marsh = binaryMarshaller(Arrays.asList( + new BinaryTypeConfiguration(NoPublicConstructor.class.getName()), + new BinaryTypeConfiguration(NoPublicDefaultConstructor.class.getName()), + new BinaryTypeConfiguration(ProtectedConstructor.class.getName())) + ); + + NoPublicConstructor npc = new NoPublicConstructor(); + BinaryObject npc2 = marshal(npc, marsh); + + assertEquals("test", npc2.<NoPublicConstructor>deserialize().val); + + NoPublicDefaultConstructor npdc = new NoPublicDefaultConstructor(239); + BinaryObject npdc2 = marshal(npdc, marsh); + + assertEquals(239, npdc2.<NoPublicDefaultConstructor>deserialize().val); + + ProtectedConstructor pc = new ProtectedConstructor(); + BinaryObject pc2 = marshal(pc, marsh); + + assertEquals(ProtectedConstructor.class, pc2.<ProtectedConstructor>deserialize().getClass()); + } + + /** + * @throws Exception If failed. + */ + public void testCustomSerializer() throws Exception { + BinaryTypeConfiguration type = + new BinaryTypeConfiguration(CustomSerializedObject1.class.getName()); + + type.setSerializer(new CustomSerializer1()); + + BinaryMarshaller marsh = binaryMarshaller(Arrays.asList(type)); + + CustomSerializedObject1 obj1 = new CustomSerializedObject1(10); + + BinaryObject po1 = marshal(obj1, marsh); + + assertEquals(20, po1.<CustomSerializedObject1>deserialize().val); + } + + /** + * @throws Exception If failed. + */ + public void testCustomSerializerWithGlobal() throws Exception { + BinaryTypeConfiguration type1 = + new BinaryTypeConfiguration(CustomSerializedObject1.class.getName()); + BinaryTypeConfiguration type2 = + new BinaryTypeConfiguration(CustomSerializedObject2.class.getName()); + + type2.setSerializer(new CustomSerializer2()); + + BinaryMarshaller marsh = binaryMarshaller(new CustomSerializer1(), Arrays.asList(type1, type2)); + + CustomSerializedObject1 obj1 = new CustomSerializedObject1(10); + + BinaryObject po1 = marshal(obj1, marsh); + + assertEquals(20, po1.<CustomSerializedObject1>deserialize().val); + + CustomSerializedObject2 obj2 = new CustomSerializedObject2(10); + + BinaryObject po2 = marshal(obj2, marsh); + + assertEquals(30, po2.<CustomSerializedObject2>deserialize().val); + } + + /** + * @throws Exception If failed. + */ + public void testCustomIdMapper() throws Exception { + BinaryTypeConfiguration type = + new BinaryTypeConfiguration(CustomMappedObject1.class.getName()); + + type.setIdMapper(new BinaryIdMapper() { + @Override public int typeId(String clsName) { + return 11111; + } + + @Override public int fieldId(int typeId, String fieldName) { + assert typeId == 11111; + + if ("val1".equals(fieldName)) + return 22222; + else if ("val2".equals(fieldName)) + return 33333; + + assert false : "Unknown field: " + fieldName; + + return 0; + } + }); + + BinaryMarshaller marsh = binaryMarshaller(Arrays.asList(type)); + + CustomMappedObject1 obj1 = new CustomMappedObject1(10, "str"); + + BinaryObjectExImpl po1 = marshal(obj1, marsh); + + assertEquals(11111, po1.type().typeId()); + assertEquals((Integer)10, po1.field(22222)); + assertEquals("str", po1.field(33333)); + + assertEquals(10, po1.<CustomMappedObject1>deserialize().val1); + assertEquals("str", po1.<CustomMappedObject1>deserialize().val2); + } + + /** + * @throws Exception If failed. + */ + public void testCustomIdMapperWithGlobal() throws Exception { + BinaryTypeConfiguration type1 = + new BinaryTypeConfiguration(CustomMappedObject1.class.getName()); + BinaryTypeConfiguration type2 = + new BinaryTypeConfiguration(CustomMappedObject2.class.getName()); + + type2.setIdMapper(new BinaryIdMapper() { + @Override public int typeId(String clsName) { + return 44444; + } + + @Override public int fieldId(int typeId, String fieldName) { + assert typeId == 44444; + + if ("val1".equals(fieldName)) return 55555; + else if ("val2".equals(fieldName)) return 66666; + + assert false : "Unknown field: " + fieldName; + + return 0; + } + }); + + BinaryMarshaller marsh = binaryMarshaller(new BinaryIdMapper() { + @Override public int typeId(String clsName) { + return 11111; + } + + @Override public int fieldId(int typeId, String fieldName) { + assert typeId == 11111; + + if ("val1".equals(fieldName)) + return 22222; + else if ("val2".equals(fieldName)) + return 33333; + + assert false : "Unknown field: " + fieldName; + + return 0; + } + }, Arrays.asList(type1, type2)); + + CustomMappedObject1 obj1 = new CustomMappedObject1(10, "str1"); + + BinaryObjectExImpl po1 = marshal(obj1, marsh); + + assertEquals(11111, po1.type().typeId()); + assertEquals((Integer)10, po1.field(22222)); + assertEquals("str1", po1.field(33333)); + + assertEquals(10, po1.<CustomMappedObject1>deserialize().val1); + assertEquals("str1", po1.<CustomMappedObject1>deserialize().val2); + + CustomMappedObject2 obj2 = new CustomMappedObject2(20, "str2"); + + BinaryObjectExImpl po2 = marshal(obj2, marsh); + + assertEquals(44444, po2.type().typeId()); + assertEquals((Integer)20, po2.field(55555)); + assertEquals("str2", po2.field(66666)); + + assertEquals(20, po2.<CustomMappedObject2>deserialize().val1); + assertEquals("str2", po2.<CustomMappedObject2>deserialize().val2); + } + + /** + * @throws Exception If failed. + */ + public void testDynamicObject() throws Exception { + BinaryMarshaller marsh = binaryMarshaller(Arrays.asList( + new BinaryTypeConfiguration(DynamicObject.class.getName()) + )); + + BinaryObject po1 = marshal(new DynamicObject(0, 10, 20, 30), marsh); + + assertEquals(new Integer(10), po1.field("val1")); + assertEquals(null, po1.field("val2")); + assertEquals(null, po1.field("val3")); + + DynamicObject do1 = po1.deserialize(); + + assertEquals(10, do1.val1); + assertEquals(0, do1.val2); + assertEquals(0, do1.val3); + + BinaryObject po2 = marshal(new DynamicObject(1, 10, 20, 30), marsh); + + assertEquals(new Integer(10), po2.field("val1")); + assertEquals(new Integer(20), po2.field("val2")); + assertEquals(null, po2.field("val3")); + + DynamicObject do2 = po2.deserialize(); + + assertEquals(10, do2.val1); + assertEquals(20, do2.val2); + assertEquals(0, do2.val3); + + BinaryObject po3 = marshal(new DynamicObject(2, 10, 20, 30), marsh); + + assertEquals(new Integer(10), po3.field("val1")); + assertEquals(new Integer(20), po3.field("val2")); + assertEquals(new Integer(30), po3.field("val3")); + + DynamicObject do3 = po3.deserialize(); + + assertEquals(10, do3.val1); + assertEquals(20, do3.val2); + assertEquals(30, do3.val3); + } + + /** + * @throws Exception If failed. + */ + public void testCycleLink() throws Exception { + BinaryMarshaller marsh = binaryMarshaller(Arrays.asList( + new BinaryTypeConfiguration(CycleLinkObject.class.getName()) + )); + + CycleLinkObject obj = new CycleLinkObject(); + + obj.self = obj; + + BinaryObject po = marshal(obj, marsh); + + CycleLinkObject obj0 = po.deserialize(); + + assert obj0.self == obj0; + } + + /** + * @throws Exception If failed. + */ + public void testDetached() throws Exception { + BinaryMarshaller marsh = binaryMarshaller(Arrays.asList( + new BinaryTypeConfiguration(DetachedTestObject.class.getName()), + new BinaryTypeConfiguration(DetachedInnerTestObject.class.getName()) + )); + + UUID id = UUID.randomUUID(); + + DetachedTestObject obj = marshal(new DetachedTestObject( + new DetachedInnerTestObject(null, id)), marsh).deserialize(); + + assertEquals(id, obj.inner1.id); + assertEquals(id, obj.inner4.id); + + assert obj.inner1 == obj.inner4; + + BinaryObjectImpl innerPo = (BinaryObjectImpl)obj.inner2; + + assert innerPo.detached(); + + DetachedInnerTestObject inner = innerPo.deserialize(); + + assertEquals(id, inner.id); + + BinaryObjectImpl detachedPo = (BinaryObjectImpl)innerPo.detach(); + + assert detachedPo.detached(); + + inner = detachedPo.deserialize(); + + assertEquals(id, inner.id); + + innerPo = (BinaryObjectImpl)obj.inner3; + + assert innerPo.detached(); + + inner = innerPo.deserialize(); + + assertEquals(id, inner.id); + assertNotNull(inner.inner); + + detachedPo = (BinaryObjectImpl)innerPo.detach(); + + assert detachedPo.detached(); + + inner = innerPo.deserialize(); + + assertEquals(id, inner.id); + assertNotNull(inner.inner); + } + + /** + * @throws Exception If failed. + */ + public void testCollectionFields() throws Exception { + BinaryMarshaller marsh = binaryMarshaller(Arrays.asList( + new BinaryTypeConfiguration(CollectionFieldsObject.class.getName()), + new BinaryTypeConfiguration(Key.class.getName()), + new BinaryTypeConfiguration(Value.class.getName()) + )); + + Object[] arr = new Object[] {new Value(1), new Value(2), new Value(3)}; + Collection<Value> col = new ArrayList<>(Arrays.asList(new Value(4), new Value(5), new Value(6))); + Map<Key, Value> map = new HashMap<>(F.asMap(new Key(10), new Value(10), new Key(20), new Value(20), new Key(30), new Value(30))); + + CollectionFieldsObject obj = new CollectionFieldsObject(arr, col, map); + + BinaryObject po = marshal(obj, marsh); + + Object[] arr0 = po.field("arr"); + + assertEquals(3, arr0.length); + + int i = 1; + + for (Object valPo : arr0) + assertEquals(i++, ((BinaryObject)valPo).<Value>deserialize().val); + + Collection<BinaryObject> col0 = po.field("col"); + + i = 4; + + for (BinaryObject valPo : col0) + assertEquals(i++, valPo.<Value>deserialize().val); + + Map<BinaryObject, BinaryObject> map0 = po.field("map"); + + for (Map.Entry<BinaryObject, BinaryObject> e : map0.entrySet()) + assertEquals(e.getKey().<Key>deserialize().key, e.getValue().<Value>deserialize().val); + } + + /** + * @throws Exception If failed. + */ + public void _testDefaultMapping() throws Exception { + BinaryTypeConfiguration customMappingType = + new BinaryTypeConfiguration(TestBinary.class.getName()); + + customMappingType.setIdMapper(new BinaryIdMapper() { + @Override public int typeId(String clsName) { + String typeName; + + try { + Method mtd = PortableContext.class.getDeclaredMethod("typeName", String.class); + + mtd.setAccessible(true); + + typeName = (String)mtd.invoke(null, clsName); + } + catch (NoSuchMethodException | InvocationTargetException | IllegalAccessException e) { + throw new RuntimeException(e); + } + + return typeName.toLowerCase().hashCode(); + } + + @Override public int fieldId(int typeId, String fieldName) { + return fieldName.toLowerCase().hashCode(); + } + }); + + BinaryMarshaller marsh1 = binaryMarshaller(Arrays.asList( + new BinaryTypeConfiguration(SimpleObject.class.getName()), + customMappingType + )); + + TestBinary obj = binaryObject(); + + BinaryObjectImpl po = marshal(obj, marsh1); + + BinaryMarshaller marsh2 = binaryMarshaller(Arrays.asList( + new BinaryTypeConfiguration(SimpleObject.class.getName()), + new BinaryTypeConfiguration(TestBinary.class.getName()) + )); + + po = marshal(obj, marsh2); + + assertEquals(obj, po.deserialize()); + } + + /** + * @throws Exception If failed. + */ + public void testTypeNames() throws Exception { + BinaryTypeConfiguration customType1 = new BinaryTypeConfiguration(Value.class.getName()); + + customType1.setIdMapper(new BinaryIdMapper() { + @Override public int typeId(String clsName) { + return 300; + } + + @Override public int fieldId(int typeId, String fieldName) { + return 0; + } + }); + + BinaryTypeConfiguration customType2 = new BinaryTypeConfiguration("org.gridgain.NonExistentClass1"); + + customType2.setIdMapper(new BinaryIdMapper() { + @Override public int typeId(String clsName) { + return 400; + } + + @Override public int fieldId(int typeId, String fieldName) { + return 0; + } + }); + + BinaryTypeConfiguration customType3 = new BinaryTypeConfiguration("NonExistentClass2"); + + customType3.setIdMapper(new BinaryIdMapper() { + @Override public int typeId(String clsName) { + return 500; + } + + @Override public int fieldId(int typeId, String fieldName) { + return 0; + } + }); + + BinaryTypeConfiguration customType4 = new BinaryTypeConfiguration("NonExistentClass5"); + + customType4.setIdMapper(new BinaryIdMapper() { + @Override public int typeId(String clsName) { + return 0; + } + + @Override public int fieldId(int typeId, String fieldName) { + return 0; + } + }); + + BinaryMarshaller marsh = binaryMarshaller(Arrays.asList( + new BinaryTypeConfiguration(Key.class.getName()), + new BinaryTypeConfiguration("org.gridgain.NonExistentClass3"), + new BinaryTypeConfiguration("NonExistentClass4"), + customType1, + customType2, + customType3, + customType4 + )); + + PortableContext ctx = portableContext(marsh); + + assertEquals("notconfiguredclass".hashCode(), ctx.typeId("NotConfiguredClass")); + assertEquals("key".hashCode(), ctx.typeId("Key")); + assertEquals("nonexistentclass3".hashCode(), ctx.typeId("NonExistentClass3")); + assertEquals("nonexistentclass4".hashCode(), ctx.typeId("NonExistentClass4")); + assertEquals(300, ctx.typeId(getClass().getSimpleName() + "$Value")); + assertEquals(400, ctx.typeId("NonExistentClass1")); + assertEquals(500, ctx.typeId("NonExistentClass2")); + assertEquals("nonexistentclass5".hashCode(), ctx.typeId("NonExistentClass5")); + } + + /** + * @throws Exception If failed. + */ + public void testFieldIdMapping() throws Exception { + BinaryTypeConfiguration customType1 = new BinaryTypeConfiguration(Value.class.getName()); + + customType1.setIdMapper(new BinaryIdMapper() { + @Override public int typeId(String clsName) { + return 300; + } + + @Override public int fieldId(int typeId, String fieldName) { + switch (fieldName) { + case "val1": + return 301; + + case "val2": + return 302; + + default: + return 0; + } + } + }); + + BinaryTypeConfiguration customType2 = new BinaryTypeConfiguration("NonExistentClass1"); + + customType2.setIdMapper(new BinaryIdMapper() { + @Override public int typeId(String clsName) { + return 400; + } + + @Override public int fieldId(int typeId, String fieldName) { + switch (fieldName) { + case "val1": + return 401; + + case "val2": + return 402; + + default: + return 0; + } + } + }); + + BinaryMarshaller marsh = binaryMarshaller(Arrays.asList(new BinaryTypeConfiguration(Key.class.getName()), + new BinaryTypeConfiguration("NonExistentClass2"), + customType1, + customType2)); + + PortableContext ctx = portableContext(marsh); + + assertEquals("val".hashCode(), ctx.fieldId("key".hashCode(), "val")); + assertEquals("val".hashCode(), ctx.fieldId("nonexistentclass2".hashCode(), "val")); + assertEquals("val".hashCode(), ctx.fieldId("notconfiguredclass".hashCode(), "val")); + assertEquals(301, ctx.fieldId(300, "val1")); + assertEquals(302, ctx.fieldId(300, "val2")); + assertEquals("val3".hashCode(), ctx.fieldId(300, "val3")); + assertEquals(401, ctx.fieldId(400, "val1")); + assertEquals(402, ctx.fieldId(400, "val2")); + assertEquals("val3".hashCode(), ctx.fieldId(400, "val3")); + } + + /** + * @throws Exception If failed. + */ + public void testDuplicateTypeId() throws Exception { + BinaryTypeConfiguration customType1 = new BinaryTypeConfiguration("org.gridgain.Class1"); + + customType1.setIdMapper(new BinaryIdMapper() { + @Override public int typeId(String clsName) { + return 100; + } + + @Override public int fieldId(int typeId, String fieldName) { + return 0; + } + }); + + BinaryTypeConfiguration customType2 = new BinaryTypeConfiguration("org.gridgain.Class2"); + + customType2.setIdMapper(new BinaryIdMapper() { + @Override public int typeId(String clsName) { + return 100; + } + + @Override public int fieldId(int typeId, String fieldName) { + return 0; + } + }); + + try { + binaryMarshaller(Arrays.asList(customType1, customType2)); + } + catch (IgniteCheckedException e) { + assertEquals("Duplicate type ID [clsName=org.gridgain.Class2, id=100]", + e.getCause().getCause().getMessage()); + + return; + } + + assert false; + } + + /** + * @throws Exception If failed. + */ + public void testPortableCopy() throws Exception { + BinaryMarshaller marsh = binaryMarshaller(Arrays.asList( + new BinaryTypeConfiguration(SimpleObject.class.getName()) + )); + + SimpleObject obj = simpleObject(); + + final BinaryObject po = marshal(obj, marsh); + + assertEquals(obj, po.deserialize()); + + BinaryObject copy = copy(po, null); + + assertEquals(obj, copy.deserialize()); + + copy = copy(po, new HashMap<String, Object>()); + + assertEquals(obj, copy.deserialize()); + + Map<String, Object> map = new HashMap<>(1, 1.0f); + + map.put("i", 3); + + copy = copy(po, map); + + assertEquals((byte)2, copy.<Byte>field("b").byteValue()); + assertEquals((short)2, copy.<Short>field("s").shortValue()); + assertEquals(3, copy.<Integer>field("i").intValue()); + assertEquals(2L, copy.<Long>field("l").longValue()); + assertEquals(2.2f, copy.<Float>field("f").floatValue(), 0); + assertEquals(2.2d, copy.<Double>field("d").doubleValue(), 0); + assertEquals((char)2, copy.<Character>field("c").charValue()); + assertEquals(false, copy.<Boolean>field("bool").booleanValue()); + + SimpleObject obj0 = copy.deserialize(); + + assertEquals((byte)2, obj0.b); + assertEquals((short)2, obj0.s); + assertEquals(3, obj0.i); + assertEquals(2L, obj0.l); + assertEquals(2.2f, obj0.f, 0); + assertEquals(2.2d, obj0.d, 0); + assertEquals((char)2, obj0.c); + assertEquals(false, obj0.bool); + + map = new HashMap<>(3, 1.0f); + + map.put("b", (byte)3); + map.put("l", 3L); + map.put("bool", true); + + copy = copy(po, map); + + assertEquals((byte)3, copy.<Byte>field("b").byteValue()); + assertEquals((short)2, copy.<Short>field("s").shortValue()); + assertEquals(2, copy.<Integer>field("i").intValue()); + assertEquals(3L, copy.<Long>field("l").longValue()); + assertEquals(2.2f, copy.<Float>field("f").floatValue(), 0); + assertEquals(2.2d, copy.<Double>field("d").doubleValue(), 0); + assertEquals((char)2, copy.<Character>field("c").charValue()); + assertEquals(true, copy.<Boolean>field("bool").booleanValue()); + + obj0 = copy.deserialize(); + + assertEquals((byte)3, obj0.b); + assertEquals((short)2, obj0.s); + assertEquals(2, obj0.i); + assertEquals(3L, obj0.l); + assertEquals(2.2f, obj0.f, 0); + assertEquals(2.2d, obj0.d, 0); + assertEquals((char)2, obj0.c); + assertEquals(true, obj0.bool); + + map = new HashMap<>(8, 1.0f); + + map.put("b", (byte)3); + map.put("s", (short)3); + map.put("i", 3); + map.put("l", 3L); + map.put("f", 3.3f); + map.put("d", 3.3d); + map.put("c", (char)3); + map.put("bool", true); + + copy = copy(po, map); + + assertEquals((byte)3, copy.<Byte>field("b").byteValue()); + assertEquals((short)3, copy.<Short>field("s").shortValue()); + assertEquals(3, copy.<Integer>field("i").intValue()); + assertEquals(3L, copy.<Long>field("l").longValue()); + assertEquals(3.3f, copy.<Float>field("f").floatValue(), 0); + assertEquals(3.3d, copy.<Double>field("d").doubleValue(), 0); + assertEquals((char)3, copy.<Character>field("c").charValue()); + assertEquals(true, copy.<Boolean>field("bool").booleanValue()); + + obj0 = copy.deserialize(); + + assertEquals((byte)3, obj0.b); + assertEquals((short)3, obj0.s); + assertEquals(3, obj0.i); + assertEquals(3L, obj0.l); + assertEquals(3.3f, obj0.f, 0); + assertEquals(3.3d, obj0.d, 0); + assertEquals((char)3, obj0.c); + assertEquals(true, obj0.bool); + +// GridTestUtils.assertThrows( +// log, +// new Callable<Object>() { +// @Override public Object call() throws Exception { +// po.copy(F.<String, Object>asMap("i", false)); +// +// return null; +// } +// }, +// PortableException.class, +// "Invalid value type for field: i" +// ); + } + + /** + * @throws Exception If failed. + */ + public void testPortableCopyString() throws Exception { + BinaryMarshaller marsh = binaryMarshaller(Arrays.asList( + new BinaryTypeConfiguration(SimpleObject.class.getName()) + )); + + SimpleObject obj = simpleObject(); + + BinaryObject po = marshal(obj, marsh); + + BinaryObject copy = copy(po, F.<String, Object>asMap("str", "str3")); + + assertEquals("str3", copy.<String>field("str")); + + SimpleObject obj0 = copy.deserialize(); + + assertEquals("str3", obj0.str); + } + + /** + * @throws Exception If failed. + */ + public void testPortableCopyUuid() throws Exception { + BinaryMarshaller marsh = binaryMarshaller(Arrays.asList( + new BinaryTypeConfiguration(SimpleObject.class.getName()) + )); + + SimpleObject obj = simpleObject(); + + BinaryObject po = marshal(obj, marsh); + + UUID uuid = UUID.randomUUID(); + + BinaryObject copy = copy(po, F.<String, Object>asMap("uuid", uuid)); + + assertEquals(uuid, copy.<UUID>field("uuid")); + + SimpleObject obj0 = copy.deserialize(); + + assertEquals(uuid, obj0.uuid); + } + + /** + * @throws Exception If failed. + */ + public void testPortableCopyByteArray() throws Exception { + BinaryMarshaller marsh = binaryMarshaller(Arrays.asList( + new BinaryTypeConfiguration(SimpleObject.class.getName()) + )); + + SimpleObject obj = simpleObject(); + + BinaryObject po = marshal(obj, marsh); + + BinaryObject copy = copy(po, F.<String, Object>asMap("bArr", new byte[]{1, 2, 3})); + + assertArrayEquals(new byte[]{1, 2, 3}, copy.<byte[]>field("bArr")); + + SimpleObject obj0 = copy.deserialize(); + + assertArrayEquals(new byte[]{1, 2, 3}, obj0.bArr); + } + + /** + * @param po Portable object. + * @param fields Fields. + * @return Copy. + */ + private BinaryObject copy(BinaryObject po, Map<String, Object> fields) { + BinaryObjectBuilder builder = BinaryObjectBuilderImpl.wrap(po); + + if (fields != null) { + for (Map.Entry<String, Object> e : fields.entrySet()) + builder.setField(e.getKey(), e.getValue()); + } + + return builder.build(); + } + + /** + * @throws Exception If failed. + */ + public void testPortableCopyShortArray() throws Exception { + BinaryMarshaller marsh = binaryMarshaller(Arrays.asList( + new BinaryTypeConfiguration(SimpleObject.class.getName()) + )); + + SimpleObject obj = simpleObject(); + + BinaryObject po = marshal(obj, marsh); + + BinaryObject copy = copy(po, F.<String, Object>asMap("sArr", new short[]{1, 2, 3})); + + assertArrayEquals(new short[] {1, 2, 3}, copy.<short[]>field("sArr")); + + SimpleObject obj0 = copy.deserialize(); + + assertArrayEquals(new short[] {1, 2, 3}, obj0.sArr); + } + + /** + * @throws Exception If failed. + */ + public void testPortableCopyIntArray() throws Exception { + BinaryMarshaller marsh = binaryMarshaller(Arrays.asList( + new BinaryTypeConfiguration(SimpleObject.class.getName()) + )); + + SimpleObject obj = simpleObject(); + + BinaryObject po = marshal(obj, marsh); + + BinaryObject copy = copy(po, F.<String, Object>asMap("iArr", new int[]{1, 2, 3})); + + assertArrayEquals(new int[] {1, 2, 3}, copy.<int[]>field("iArr")); + + SimpleObject obj0 = copy.deserialize(); + + assertArrayEquals(new int[] {1, 2, 3}, obj0.iArr); + } + + /** + * @throws Exception If failed. + */ + public void testPortableCopyLongArray() throws Exception { + BinaryMarshaller marsh = binaryMarshaller(Arrays.asList( + new BinaryTypeConfiguration(SimpleObject.class.getName()) + )); + + SimpleObject obj = simpleObject(); + + BinaryObject po = marshal(obj, marsh); + + BinaryObject copy = copy(po, F.<String, Object>asMap("lArr", new long[]{1, 2, 3})); + + assertArrayEquals(new long[] {1, 2, 3}, copy.<long[]>field("lArr")); + + SimpleObject obj0 = copy.deserialize(); + + assertArrayEquals(new long[] {1, 2, 3}, obj0.lArr); + } + + /** + * @throws Exception If failed. + */ + public void testPortableCopyFloatArray() throws Exception { + BinaryMarshaller marsh = binaryMarshaller(Arrays.asList( + new BinaryTypeConfiguration(SimpleObject.class.getName()) + )); + + SimpleObject obj = simpleObject(); + + BinaryObject po = marshal(obj, marsh); + + BinaryObject copy = copy(po, F.<String, Object>asMap("fArr", new float[]{1, 2, 3})); + + assertArrayEquals(new float[] {1, 2, 3}, copy.<float[]>field("fArr"), 0); + + SimpleObject obj0 = copy.deserialize(); + + assertArrayEquals(new float[] {1, 2, 3}, obj0.fArr, 0); + } + + /** + * @throws Exception If failed. + */ + public void testPortableCopyDoubleArray() throws Exception { + BinaryMarshaller marsh = binaryMarshaller(Arrays.asList( + new BinaryTypeConfiguration(SimpleObject.class.getName()) + )); + + SimpleObject obj = simpleObject(); + + BinaryObject po = marshal(obj, marsh); + + BinaryObject copy = copy(po, F.<String, Object>asMap("dArr", new double[]{1, 2, 3})); + + assertArrayEquals(new double[] {1, 2, 3}, copy.<double[]>field("dArr"), 0); + + SimpleObject obj0 = copy.deserialize(); + + assertArrayEquals(new double[] {1, 2, 3}, obj0.dArr, 0); + } + + /** + * @throws Exception If failed. + */ + public void testPortableCopyCharArray() throws Exception { + BinaryMarshaller marsh = binaryMarshaller(Arrays.asList( + new BinaryTypeConfiguration(SimpleObject.class.getName()) + )); + + SimpleObject obj = simpleObject(); + + BinaryObject po = marshal(obj, marsh); + + BinaryObject copy = copy(po, F.<String, Object>asMap("cArr", new char[]{1, 2, 3})); + + assertArrayEquals(new char[]{1, 2, 3}, copy.<char[]>field("cArr")); + + SimpleObject obj0 = copy.deserialize(); + + assertArrayEquals(new char[]{1, 2, 3}, obj0.cArr); + } + + /** + * @throws Exception If failed. + */ + public void testPortableCopyStringArray() throws Exception { + BinaryMarshaller marsh = binaryMarshaller(Arrays.asList( + new BinaryTypeConfiguration(SimpleObject.class.getName()) + )); + + SimpleObject obj = simpleObject(); + + BinaryObject po = marshal(obj, marsh); + + BinaryObject copy = copy(po, F.<String, Object>asMap("strArr", new String[]{"str1", "str2"})); + + assertArrayEquals(new String[]{"str1", "str2"}, copy.<String[]>field("strArr")); + + SimpleObject obj0 = copy.deserialize(); + + assertArrayEquals(new String[]{"str1", "str2"}, obj0.strArr); + } + + /** + * @throws Exception If failed. + */ + public void testPortableCopyObject() throws Exception { + BinaryMarshaller marsh = binaryMarshaller(Arrays.asList( + new BinaryTypeConfiguration(SimpleObject.class.getName()) + )); + + SimpleObject obj = simpleObject(); + + BinaryObject po = marshal(obj, marsh); + + SimpleObject newObj = new SimpleObject(); + + newObj.i = 12345; + newObj.fArr = new float[] {5, 8, 0}; + newObj.str = "newStr"; + + BinaryObject copy = copy(po, F.<String, Object>asMap("inner", newObj)); + + assertEquals(newObj, copy.<BinaryObject>field("inner").deserialize()); + + SimpleObject obj0 = copy.deserialize(); + + assertEquals(newObj, obj0.inner); + } + + /** + * @throws Exception If failed. + */ + public void testPortableCopyNonPrimitives() throws Exception { + BinaryMarshaller marsh = binaryMarshaller(Arrays.asList( + new BinaryTypeConfiguration(SimpleObject.class.getName()) + )); + + SimpleObject obj = simpleObject(); + + BinaryObject po = marshal(obj, marsh); + + Map<String, Object> map = new HashMap<>(3, 1.0f); + + SimpleObject newObj = new SimpleObject(); + + newObj.i = 12345; + newObj.fArr = new float[] {5, 8, 0}; + newObj.str = "newStr"; + + map.put("str", "str555"); + map.put("inner", newObj); + map.put("bArr", new byte[]{6, 7, 9}); + + BinaryObject copy = copy(po, map); + + assertEquals("str555", copy.<String>field("str")); + assertEquals(newObj, copy.<BinaryObject>field("inner").deserialize()); + assertArrayEquals(new byte[]{6, 7, 9}, copy.<byte[]>field("bArr")); + + SimpleObject obj0 = copy.deserialize(); + + assertEquals("str555", obj0.str); + assertEquals(newObj, obj0.inner); + assertArrayEquals(new byte[]{6, 7, 9}, obj0.bArr); + } + + /** + * @throws Exception If failed. + */ + public void testPortableCopyMixed() throws Exception { + BinaryMarshaller marsh = binaryMarshaller(Arrays.asList(new BinaryTypeConfiguration(SimpleObject.class.getName()))); + + SimpleObject obj = simpleObject(); + + BinaryObject po = marshal(obj, marsh); + + Map<String, Object> map = new HashMap<>(3, 1.0f); + + SimpleObject newObj = new SimpleObject(); + + newObj.i = 12345; + newObj.fArr = new float[] {5, 8, 0}; + newObj.str = "newStr"; + + map.put("i", 1234); + map.put("str", "str555"); + map.put("inner", newObj); + map.put("s", (short)2323); + map.put("bArr", new byte[]{6, 7, 9}); + map.put("b", (byte) 111); + + BinaryObject copy = copy(po, map); + + assertEquals(1234, copy.<Integer>field("i").intValue()); + assertEquals("str555", copy.<String>field("str")); + assertEquals(newObj, copy.<BinaryObject>field("inner").deserialize()); + assertEquals((short)2323, copy.<Short>field("s").shortValue()); + assertArrayEquals(new byte[] {6, 7, 9}, copy.<byte[]>field("bArr")); + assertEquals((byte)111, copy.<Byte>field("b").byteValue()); + + SimpleObject obj0 = copy.deserialize(); + + assertEquals(1234, obj0.i); + assertEquals("str555", obj0.str); + assertEquals(newObj, obj0.inner); + assertEquals((short)2323, obj0.s); + assertArrayEquals(new byte[]{6, 7, 9}, obj0.bArr); + assertEquals((byte) 111, obj0.b); + } + + /** + * @throws Exception If failed. + */ + public void testKeepDeserialized() throws Exception { + BinaryMarshaller marsh = binaryMarshaller(Arrays.asList(new BinaryTypeConfiguration(SimpleObject.class.getName()))); + + BinaryObjectImpl po = marshal(simpleObject(), marsh); + + CacheObjectContext coCtx = new CacheObjectContext(newContext(), null, false, true, false); + + assert po.value(coCtx, false) == po.value(coCtx, false); + + po = marshal(simpleObject(), marsh); + + assert po.deserialize() != po.deserialize(); + } + + /** + * @throws Exception If failed. + */ + public void testOffheapPortable() throws Exception { + BinaryMarshaller marsh = binaryMarshaller(Arrays.asList(new BinaryTypeConfiguration(SimpleObject.class.getName()))); + + PortableContext ctx = portableContext(marsh); + + SimpleObject simpleObj = simpleObject(); + + BinaryObjectImpl obj = marshal(simpleObj, marsh); + + long ptr = 0; + + long ptr1 = 0; + + long ptr2 = 0; + + try { + ptr = copyOffheap(obj); + + BinaryObjectOffheapImpl offheapObj = new BinaryObjectOffheapImpl(ctx, + ptr, + 0, + obj.array().length); + + assertTrue(offheapObj.equals(offheapObj)); + assertFalse(offheapObj.equals(null)); + assertFalse(offheapObj.equals("str")); + assertTrue(offheapObj.equals(obj)); + assertTrue(obj.equals(offheapObj)); + + ptr1 = copyOffheap(obj); + + BinaryObjectOffheapImpl offheapObj1 = new BinaryObjectOffheapImpl(ctx, + ptr1, + 0, + obj.array().length); + + assertTrue(offheapObj.equals(offheapObj1)); + assertTrue(offheapObj1.equals(offheapObj)); + + assertEquals(obj.type().typeId(), offheapObj.type().typeId()); + assertEquals(obj.hashCode(), offheapObj.hashCode()); + + checkSimpleObjectData(simpleObj, offheapObj); + + BinaryObjectOffheapImpl innerOffheapObj = offheapObj.field("inner"); + + assertNotNull(innerOffheapObj); + + checkSimpleObjectData(simpleObj.inner, innerOffheapObj); + + obj = (BinaryObjectImpl)offheapObj.heapCopy(); + + assertEquals(obj.type().typeId(), offheapObj.type().typeId()); + assertEquals(obj.hashCode(), offheapObj.hashCode()); + + checkSimpleObjectData(simpleObj, obj); + + BinaryObjectImpl innerObj = obj.field("inner"); + + assertNotNull(innerObj); + + checkSimpleObjectData(simpleObj.inner, innerObj); + + simpleObj.d = 0; + + obj = marshal(simpleObj, marsh); + + assertFalse(offheapObj.equals(obj)); + assertFalse(obj.equals(offheapObj)); + + ptr2 = copyOffheap(obj); + + BinaryObjectOffheapImpl offheapObj2 = new BinaryObjectOffheapImpl(ctx, + ptr2, + 0, + obj.array().length); + + assertFalse(offheapObj.equals(offheapObj2)); + assertFalse(offheapObj2.equals(offheapObj)); + } + finally { + UNSAFE.freeMemory(ptr); + + if (ptr1 > 0) + UNSAFE.freeMemory(ptr1); + + if (ptr2 > 0) + UNSAFE.freeMemory(ptr2); + } + } + + /** + * + */ + public void testReadResolve() throws Exception { + BinaryMarshaller marsh = binaryMarshaller(Arrays.asList( + new BinaryTypeConfiguration(MySingleton.class.getName()), + new BinaryTypeConfiguration(SingletonMarker.class.getName()))); + + BinaryObjectImpl portableObj = marshal(MySingleton.INSTANCE, marsh); + + assertTrue(portableObj.array().length <= 1024); // Check that big string was not serialized. + + MySingleton singleton = portableObj.deserialize(); + + assertSame(MySingleton.INSTANCE, singleton); + } + + /** + * + */ + public void testReadResolveOnPortableAware() throws Exception { + BinaryMarshaller marsh = binaryMarshaller(Collections.singletonList( + new BinaryTypeConfiguration(MyTestClass.class.getName()))); + + BinaryObjectImpl portableObj = marshal(new MyTestClass(), marsh); + + MyTestClass obj = portableObj.deserialize(); + + assertEquals("readResolve", obj.s); + } + + /** + * @throws Exception If ecxeption thrown. + */ + public void testDeclareReadResolveInParent() throws Exception { + BinaryMarshaller marsh = binaryMarshaller(Arrays.asList(new BinaryTypeConfiguration(ChildPortable.class.getName()))); + + BinaryObjectImpl portableObj = marshal(new ChildPortable(), marsh); + + ChildPortable singleton = portableObj.deserialize(); + + assertNotNull(singleton.s); + } + + /** + * + */ + public void testDecimalFields() throws Exception { + Collection<BinaryTypeConfiguration> clsNames = new ArrayList<>(); + + clsNames.add(new BinaryTypeConfiguration(DecimalReflective.class.getName())); + clsNames.add(new BinaryTypeConfiguration(DecimalMarshalAware.class.getName())); + + BinaryMarshaller marsh = binaryMarshaller(clsNames); + + // 1. Test reflective stuff. + DecimalReflective obj1 = new DecimalReflective(); + + obj1.val = BigDecimal.ZERO; + obj1.valArr = new BigDecimal[] { BigDecimal.ONE, BigDecimal.TEN }; + + BinaryObjectImpl portObj = marshal(obj1, marsh); + + assertEquals(obj1.val, portObj.field("val")); + assertArrayEquals(obj1.valArr, portObj.<BigDecimal[]>field("valArr")); + + assertEquals(obj1.val, portObj.<DecimalReflective>deserialize().val); + assertArrayEquals(obj1.valArr, portObj.<DecimalReflective>deserialize().valArr); + + // 2. Test marshal aware stuff. + DecimalMarshalAware obj2 = new DecimalMarshalAware(); + + obj2.val = BigDecimal.ZERO; + obj2.valArr = new BigDecimal[] { BigDecimal.ONE, BigDecimal.TEN.negate() }; + obj2.rawVal = BigDecimal.TEN; + obj2.rawValArr = new BigDecimal[] { BigDecimal.ZERO, BigDecimal.ONE }; + + portObj = marshal(obj2, marsh); + + assertEquals(obj2.val, portObj.field("val")); + assertArrayEquals(obj2.valArr, portObj.<BigDecimal[]>field("valArr")); + + assertEquals(obj2.val, portObj.<DecimalMarshalAware>deserialize().val); + assertArrayEquals(obj2.valArr, portObj.<DecimalMarshalAware>deserialize().valArr); + assertEquals(obj2.rawVal, portObj.<DecimalMarshalAware>deserialize().rawVal); + assertArrayEquals(obj2.rawValArr, portObj.<DecimalMarshalAware>deserialize().rawValArr); + } + + /** + * @throws IgniteCheckedException If failed. + */ + public void testFinalField() throws IgniteCheckedException { + BinaryMarshaller marsh = binaryMarshaller(); + + SimpleObjectWithFinal obj = new SimpleObjectWithFinal(); + + SimpleObjectWithFinal po0 = marshalUnmarshal(obj, marsh); + + assertEquals(obj.time, po0.time); + } + + /** + * @throws IgniteCheckedException If failed. + */ + public void testThreadLocalArrayReleased() throws Exception { + // Checking the writer directly. + assertEquals(false, INSTANCE.isAcquired()); + + BinaryMarshaller marsh = binaryMarshaller(); + + try (BinaryWriterExImpl writer = new BinaryWriterExImpl(portableContext(marsh))) { + assertEquals(true, INSTANCE.isAcquired()); + + writer.writeString("Thread local test"); + + writer.array(); + + assertEquals(true, INSTANCE.isAcquired()); + } + + // Checking the portable marshaller. + assertEquals(false, INSTANCE.isAcquired()); + + marsh = binaryMarshaller(); + + marsh.marshal(new SimpleObject()); + + assertEquals(false, INSTANCE.isAcquired()); + + marsh = binaryMarshaller(); + + // Checking the builder. + BinaryObjectBuilder builder = new BinaryObjectBuilderImpl(portableContext(marsh), + "org.gridgain.foo.bar.TestClass"); + + builder.setField("a", "1"); + + BinaryObject portableObj = builder.build(); + + assertEquals(false, INSTANCE.isAcquired()); + } + + /** + * @throws Exception If failed. + */ + public void testDuplicateName() throws Exception { + BinaryMarshaller marsh = binaryMarshaller(); + + Test1.Job job1 = new Test1().new Job(); + Test2.Job job2 = new Test2().new Job(); + + marsh.marshal(job1); + + try { + marsh.marshal(job2); + } + catch (BinaryObjectException e) { + assertEquals(true, e.getMessage().contains("Failed to register class")); + + return; + } + + assert false; + } + + /** + * @throws Exception If failed. + */ + public void testClass() throws Exception { + BinaryMarshaller marsh = binaryMarshaller(); + + Class cls = BinaryMarshallerSelfTest.class; + + Class unmarshalledCls = marshalUnmarshal(cls, marsh); + + Assert.assertEquals(cls, unmarshalledCls); + } + + /** + * @throws Exception If failed. + */ + public void testClassFieldsMarshalling() throws Exception { + BinaryMarshaller marsh = binaryMarshaller(); + + ObjectWithClassFields obj = new ObjectWithClassFields(); + obj.cls1 = BinaryMarshallerSelfTest.class; + + byte[] marshal = marsh.marshal(obj); + + ObjectWithClassFields obj2 = marsh.unmarshal(marshal, null); + + assertEquals(obj.cls1, obj2.cls1); + assertNull(obj2.cls2); + + BinaryObject portObj = marshal(obj, marsh); + + Class cls1 = portObj.field("cls1"); + + assertEquals(obj.cls1, cls1); + } + + /** + * @throws Exception If failed. + */ + public void testMarshallingThroughJdk() throws Exception { + BinaryMarshaller marsh = binaryMarshaller(); + + InetSocketAddress addr = new InetSocketAddress("192.168.0.2", 4545); + + byte[] arr = marsh.marshal(addr); + + InetSocketAddress addr2 = marsh.unmarshal(arr, null); + + assertEquals(addr.getHostString(), addr2.getHostString()); + assertEquals(addr.getPort(), addr2.getPort()); + + TestAddress testAddr = new TestAddress(); + testAddr.addr = addr; + testAddr.str1 = "Hello World"; + + SimpleObject simpleObj = new SimpleObject(); + simpleObj.c = 'g'; + simpleObj.date = new Date(); + + testAddr.obj = simpleObj; + + arr = marsh.marshal(testAddr); + + TestAddress testAddr2 = marsh.unmarshal(arr, null); + + assertEquals(testAddr.addr.getHostString(), testAddr2.addr.getHostString()); + assertEquals(testAddr.addr.getPort(), testAddr2.addr.getPort()); + assertEquals(testAddr.str1, testAddr2.str1); + assertEquals(testAddr.obj.c, testAddr2.obj.c); + assertEquals(testAddr.obj.date, testAddr2.obj.date); + } + + /** + * @throws Exception If failed. + */ + public void testPredefinedTypeIds() throws Exception { + BinaryMarshaller marsh = binaryMarshaller(); + + PortableContext pCtx = portableContext(marsh); + + Field field = pCtx.getClass().getDeclaredField("predefinedTypeNames"); + + field.setAccessible(true); + + Map<String, Integer> map = (Map<String, Integer>)field.get(pCtx); + + assertTrue(map.size() > 0); + + for (Map.Entry<String, Integer> entry : map.entrySet()) { + int id = entry.getValue(); + + if (id == GridPortableMarshaller.UNREGISTERED_TYPE_ID) + continue; + + PortableClassDescriptor desc = pCtx.descriptorForTypeId(false, entry.getValue(), null, false); + + assertEquals(desc.typeId(), pCtx.typeId(desc.describedClass().getName())); + assertEquals(desc.typeId(), pCtx.typeId(pCtx.typeName(desc.describedClass().getName()))); + } + } + + /** + * @throws Exception If failed. + */ + public void testCyclicReferencesMarshalling() throws Exception { + BinaryMarshaller marsh = binaryMarshaller(); + + SimpleObject obj = simpleObject(); + + obj.bArr = obj.inner.bArr; + obj.cArr = obj.inner.cArr; + obj.boolArr = obj.inner.boolArr; + obj.sArr = obj.inner.sArr; + obj.strArr = obj.inner.strArr; + obj.iArr = obj.inner.iArr; + obj.lArr = obj.inner.lArr; + obj.fArr = obj.inner.fArr; + obj.dArr = obj.inner.dArr; + obj.dateArr = obj.inner.dateArr; + obj.uuidArr = obj.inner.uuidArr; + obj.objArr = obj.inner.objArr; + obj.bdArr = obj.inner.bdArr; + obj.map = obj.inner.map; + obj.col = obj.inner.col; + obj.mEntry = obj.inner.mEntry; + + SimpleObject res = (SimpleObject)marshalUnmarshal(obj, marsh); + + assertEquals(obj, res); + + assertTrue(res.objArr == res.inner.objArr); + assertTrue(res.map == res.inner.map); + assertTrue(res.col == res.inner.col); + assertTrue(res.mEntry == res.inner.mEntry); + } + + /** + * @throws Exception If failed. + */ + public void testProxy() throws Exception { + BinaryMarshaller marsh = binaryMarshaller(); + + SomeItf inItf = (SomeItf)Proxy.newProxyInstance( + BinaryMarshallerSelfTest.class.getClassLoader(), new Class[] {SomeItf.class}, + new InvocationHandler() { + private NonSerializable obj = new NonSerializable(null); + + @Override public Object invoke(Object proxy, Method mtd, Object[] args) throws Throwable { + if ("hashCode".equals(mtd.getName())) + return obj.hashCode(); + + obj.checkAfterUnmarshalled(); + + return 17; + } + } + ); + + SomeItf outItf = marsh.unmarshal(marsh.marshal(inItf), null); + + assertEquals(outItf.checkAfterUnmarshalled(), 17); + } + + /** + * + */ + private static interface SomeItf { + /** + * @return Check result. + */ + int checkAfterUnmarshalled(); + } + + /** + * Some non-serializable class. + */ + @SuppressWarnings( {"PublicField","TransientFieldInNonSerializableClass","FieldMayBeStatic"}) + private static class NonSerializableA { + /** */ + private final long longVal = 0x33445566778899AAL; + + /** */ + protected Short shortVal = (short)0xAABB; + + /** */ + public String[] strArr = {"AA","BB"}; + + /** */ + public boolean flag1 = true; + + /** */ + public boolean flag2; + + /** */ + public Boolean flag3; + + /** */ + public Boolean flag4 = true; + + /** */ + public Boolean flag5 = false; + + /** */ + private transient int intVal = 0xAABBCCDD; + + /** + * @param strArr Array. + * @param shortVal Short value. + */ + @SuppressWarnings( {"UnusedDeclaration"}) + private NonSerializableA(@Nullable String[] strArr, @Nullable Short shortVal) { + // No-op. + } + + /** + * Checks correctness of the state after unmarshalling. + */ + void checkAfterUnmarshalled() { + assertEquals(longVal, 0x33445566778899AAL); + + assertEquals(shortVal.shortValue(), (short)0xAABB); + + assertTrue(Arrays.equals(strArr, new String[] {"AA","BB"})); + + assertEquals(0, intVal); + + assertTrue(flag1); + assertFalse(flag2); + assertNull(flag3); + assertTrue(flag4); + assertFalse(flag5); + } + } + + /** + * Some non-serializable class. + */ + @SuppressWarnings( {"PublicField","TransientFieldInNonSerializableClass","PackageVisibleInnerClass"}) + static class NonSerializableB extends NonSerializableA { + /** */ + public Short shortValue = 0x1122; + + /** */ + public long longValue = 0x8877665544332211L; + + /** */ + private transient NonSerializableA[] aArr = { + new NonSerializableA(null, null), + new NonSerializableA(null, null), + new NonSerializableA(null, null) + }; + + /** */ + protected Double doubleVal = 123.456; + + /** + * Just to eliminate the default constructor. + */ + private NonSerializableB() { + super(null, null); + } + + /** + * Checks correctness of the state after unmarshalling. + */ + @Override void checkAfterUnmarshalled() { + super.checkAfterUnmarshalled(); + + assertEquals(shortValue.shortValue(), 0x1122); + + assertEquals(longValue, 0x8877665544332211L); + + assertNull(aArr); + + assertEquals(doubleVal, 123.456); + } + } + + /** + * Some non-serializable class. + */ + @SuppressWarnings( {"TransientFieldInNonSerializableClass","PublicField"}) + private static class NonSerializable extends NonSerializableB { + /** */ + private int idVal = -17; + + /** */ + private final NonSerializableA aVal = new NonSerializableB(); + + /** */ + private transient NonSerializableB bVal = new NonSerializableB(); + + /** */ + private NonSerializableA[] bArr = new NonSerializableA[] { + new NonSerializableB(), + new NonSerializableA(null, null) + }; + + /** */ + public float floatVal = 567.89F; + + /** + * Just to eliminate the default constructor. + * + * @param aVal Unused. + */ + @SuppressWarnings( {"UnusedDeclaration"}) + private NonSerializable(NonSerializableA aVal) { + } + + /** + * Checks correctness of the state after unmarshalling. + */ + @Override void checkAfterUnmarshalled() { + super.checkAfterUnmarshalled(); + + assertEquals(idVal, -17); + + aVal.checkAfterUnmarshalled(); + + assertNull(bVal); + + for (NonSerializableA a : bArr) { + a.checkAfterUnmarshalled(); + } + + assertEquals(floatVal, 567.89F); + } + } + + /** + * Object with class fields. + */ + private static class ObjectWithClassFields { + /** */ + private Class<?> cls1; + + /** */ + private Class<?> cls2; + } + + /** + * + */ + private static class TestAddress { + /** */ + private SimpleObject obj; + + /** */ + private InetSocketAddress addr; + + /** */ + private String str1; + } + + /** + * + */ + private static class Test1 { + /** + * + */ + private class Job { + + } + } + + /** + * + */ + private static class Test2 { + /** + * + */ + private class Job { + + } + } + + /** + * @param obj Object. + * @return Offheap address. + */ + private long copyOffheap(BinaryObjectImpl obj) { + byte[] arr = obj.array(); + + long ptr = UNSAFE.allocateMemory(arr.length); + + UNSAFE.copyMemory(arr, BYTE_ARR_OFF, null, ptr, arr.length); + + return ptr; + } + + /** + * @param enumArr Enum array. + * @return Ordinals. + */ + private <T extends Enum<?>> Integer[] ordinals(T[] enumArr) { + Integer[] ords = new Integer[enumArr.length]; + + for (int i = 0; i < enumArr.length; i++) + ords[i] = enumArr[i].ordinal(); + + return ords; + } + + /** + * @param enumArr Enum array. + * @return Ordinals. + */ + private <T extends Enum<?>> Integer[] ordinals(BinaryObject[]
<TRUNCATED>
