| /* |
| * 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 org.apache.ignite.binary.BinaryField; |
| import org.apache.ignite.binary.BinaryObject; |
| import org.apache.ignite.binary.BinaryTypeConfiguration; |
| import org.apache.ignite.configuration.BinaryConfiguration; |
| import org.apache.ignite.configuration.IgniteConfiguration; |
| import org.apache.ignite.internal.util.IgniteUtils; |
| import org.apache.ignite.internal.util.typedef.internal.U; |
| import org.apache.ignite.logger.NullLogger; |
| import org.apache.ignite.marshaller.MarshallerContextTestImpl; |
| import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest; |
| |
| import java.math.BigDecimal; |
| import java.sql.Timestamp; |
| import java.util.Arrays; |
| import java.util.Date; |
| import java.util.UUID; |
| import org.junit.Test; |
| |
| /** |
| * Contains tests for binary object fields. |
| */ |
| public abstract class BinaryFieldsAbstractSelfTest extends GridCommonAbstractTest { |
| /** Marshaller. */ |
| protected BinaryMarshaller dfltMarsh; |
| |
| /** |
| * Create marshaller. |
| * |
| * @return Binary marshaller. |
| * @throws Exception If failed. |
| */ |
| protected BinaryMarshaller createMarshaller() throws Exception { |
| BinaryContext ctx = new BinaryContext(BinaryCachingMetadataHandler.create(), new IgniteConfiguration(), |
| new NullLogger()); |
| |
| BinaryMarshaller marsh = new BinaryMarshaller(); |
| |
| BinaryConfiguration bCfg = new BinaryConfiguration(); |
| |
| bCfg.setCompactFooter(compactFooter()); |
| |
| bCfg.setTypeConfigurations(Arrays.asList( |
| new BinaryTypeConfiguration(TestObject.class.getName()), |
| new BinaryTypeConfiguration(TestOuterObject.class.getName()), |
| new BinaryTypeConfiguration(TestInnerObject.class.getName()) |
| )); |
| |
| IgniteConfiguration iCfg = new IgniteConfiguration(); |
| |
| iCfg.setBinaryConfiguration(bCfg); |
| |
| marsh.setContext(new MarshallerContextTestImpl(null)); |
| |
| IgniteUtils.invoke(BinaryMarshaller.class, marsh, "setBinaryContext", ctx, iCfg); |
| |
| return marsh; |
| } |
| |
| /** |
| * @return Whether to use compact footer. |
| */ |
| protected boolean compactFooter() { |
| return true; |
| } |
| |
| /** |
| * Get binary context for the current marshaller. |
| * |
| * @param marsh Marshaller. |
| * @return Binary context. |
| */ |
| protected static BinaryContext binaryContext(BinaryMarshaller marsh) { |
| GridBinaryMarshaller impl = U.field(marsh, "impl"); |
| |
| return impl.context(); |
| } |
| |
| /** {@inheritDoc} */ |
| @Override protected void beforeTest() throws Exception { |
| super.beforeTest(); |
| |
| dfltMarsh = createMarshaller(); |
| } |
| |
| /** |
| * Test byte field. |
| * |
| * @throws Exception If failed. |
| */ |
| @Test |
| public void testByte() throws Exception { |
| check("fByte"); |
| } |
| |
| /** |
| * Test byte array field. |
| * |
| * @throws Exception If failed. |
| */ |
| @Test |
| public void testByteArray() throws Exception { |
| check("fByteArr"); |
| } |
| |
| /** |
| * Test boolean field. |
| * |
| * @throws Exception If failed. |
| */ |
| @Test |
| public void testBoolean() throws Exception { |
| check("fBool"); |
| } |
| |
| /** |
| * Test boolean array field. |
| * |
| * @throws Exception If failed. |
| */ |
| @Test |
| public void testBooleanArray() throws Exception { |
| check("fBoolArr"); |
| } |
| |
| /** |
| * Test short field. |
| * |
| * @throws Exception If failed. |
| */ |
| @Test |
| public void testShort() throws Exception { |
| check("fShort"); |
| } |
| |
| /** |
| * Test short array field. |
| * |
| * @throws Exception If failed. |
| */ |
| @Test |
| public void testShortArray() throws Exception { |
| check("fShortArr"); |
| } |
| |
| /** |
| * Test char field. |
| * |
| * @throws Exception If failed. |
| */ |
| @Test |
| public void testChar() throws Exception { |
| check("fChar"); |
| } |
| |
| /** |
| * Test char array field. |
| * |
| * @throws Exception If failed. |
| */ |
| @Test |
| public void testCharArray() throws Exception { |
| check("fCharArr"); |
| } |
| |
| /** |
| * Test int field. |
| * |
| * @throws Exception If failed. |
| */ |
| @Test |
| public void testInt() throws Exception { |
| check("fInt"); |
| } |
| |
| /** |
| * Test int array field. |
| * |
| * @throws Exception If failed. |
| */ |
| @Test |
| public void testIntArray() throws Exception { |
| check("fIntArr"); |
| } |
| |
| /** |
| * Test long field. |
| * |
| * @throws Exception If failed. |
| */ |
| @Test |
| public void testLong() throws Exception { |
| check("fLong"); |
| } |
| |
| /** |
| * Test long array field. |
| * |
| * @throws Exception If failed. |
| */ |
| @Test |
| public void testLongArray() throws Exception { |
| check("fLongArr"); |
| } |
| |
| /** |
| * Test float field. |
| * |
| * @throws Exception If failed. |
| */ |
| @Test |
| public void testFloat() throws Exception { |
| check("fFloat"); |
| } |
| |
| /** |
| * Test float array field. |
| * |
| * @throws Exception If failed. |
| */ |
| @Test |
| public void testFloatArray() throws Exception { |
| check("fFloatArr"); |
| } |
| |
| /** |
| * Test double field. |
| * |
| * @throws Exception If failed. |
| */ |
| @Test |
| public void testDouble() throws Exception { |
| check("fDouble"); |
| } |
| |
| /** |
| * Test double array field. |
| * |
| * @throws Exception If failed. |
| */ |
| @Test |
| public void testDoubleArray() throws Exception { |
| check("fDoubleArr"); |
| } |
| |
| /** |
| * Test string field. |
| * |
| * @throws Exception If failed. |
| */ |
| @Test |
| public void testString() throws Exception { |
| check("fString"); |
| } |
| |
| /** |
| * Test string array field. |
| * |
| * @throws Exception If failed. |
| */ |
| @Test |
| public void testStringArray() throws Exception { |
| check("fStringArr"); |
| } |
| |
| /** |
| * Test date field. |
| * |
| * @throws Exception If failed. |
| */ |
| @Test |
| public void testDate() throws Exception { |
| check("fDate"); |
| } |
| |
| /** |
| * Test date array field. |
| * |
| * @throws Exception If failed. |
| */ |
| @Test |
| public void testDateArray() throws Exception { |
| check("fDateArr"); |
| } |
| |
| /** |
| * Test timestamp field. |
| * |
| * @throws Exception If failed. |
| */ |
| @Test |
| public void testTimestamp() throws Exception { |
| check("fTimestamp"); |
| } |
| |
| /** |
| * Test timestamp array field. |
| * |
| * @throws Exception If failed. |
| */ |
| @Test |
| public void testTimestampArray() throws Exception { |
| check("fTimestampArr"); |
| } |
| |
| /** |
| * Test UUID field. |
| * |
| * @throws Exception If failed. |
| */ |
| @Test |
| public void testUuid() throws Exception { |
| check("fUuid"); |
| } |
| |
| /** |
| * Test UUID array field. |
| * |
| * @throws Exception If failed. |
| */ |
| @Test |
| public void testUuidArray() throws Exception { |
| check("fUuidArr"); |
| } |
| |
| /** |
| * Test decimal field. |
| * |
| * @throws Exception If failed. |
| */ |
| @Test |
| public void testDecimal() throws Exception { |
| check("fDecimal"); |
| } |
| |
| /** |
| * Test decimal array field. |
| * |
| * @throws Exception If failed. |
| */ |
| @Test |
| public void testDecimalArray() throws Exception { |
| check("fDecimalArr"); |
| } |
| |
| /** |
| * Test object field. |
| * |
| * @throws Exception If failed. |
| */ |
| @Test |
| public void testObject() throws Exception { |
| check("fObj"); |
| } |
| |
| /** |
| * Test object array field. |
| * |
| * @throws Exception If failed. |
| */ |
| @Test |
| public void testObjectArray() throws Exception { |
| check("fObjArr"); |
| } |
| |
| /** |
| * Test null field. |
| * |
| * @throws Exception If failed. |
| */ |
| @Test |
| public void testNull() throws Exception { |
| check("fNull"); |
| } |
| |
| /** |
| * Test missing field. |
| * |
| * @throws Exception If failed. |
| */ |
| @Test |
| public void testMissing() throws Exception { |
| String fieldName = "fMissing"; |
| |
| checkNormal(dfltMarsh, fieldName, false); |
| checkNested(dfltMarsh, fieldName, false); |
| } |
| |
| /** |
| * Check field resolution in both normal and nested modes. |
| * |
| * @param fieldName Field name. |
| * @throws Exception If failed. |
| */ |
| public void check(String fieldName) throws Exception { |
| checkNormal(dfltMarsh, fieldName, true); |
| checkNested(dfltMarsh, fieldName, true); |
| } |
| |
| /** |
| * Check field. |
| * |
| * @param marsh Marshaller. |
| * @param fieldName Field name. |
| * @param exists Whether field should exist. |
| * @throws Exception If failed. |
| */ |
| private void checkNormal(BinaryMarshaller marsh, String fieldName, boolean exists) throws Exception { |
| TestContext testCtx = context(marsh, fieldName); |
| |
| check0(fieldName, testCtx, exists); |
| } |
| |
| /** |
| * Check nested field. |
| * |
| * @param marsh Marshaller. |
| * @param fieldName Field name. |
| * @param exists Whether field should exist. |
| * @throws Exception If failed. |
| */ |
| private void checkNested(BinaryMarshaller marsh, String fieldName, boolean exists) throws Exception { |
| TestContext testCtx = nestedContext(marsh, fieldName); |
| |
| check0(fieldName, testCtx, exists); |
| } |
| |
| /** |
| * Internal check routine. |
| * |
| * @param fieldName Field name. |
| * @param ctx Context. |
| * @param exists Whether field should exist. |
| * @throws Exception If failed. |
| */ |
| private void check0(String fieldName, TestContext ctx, boolean exists) throws Exception { |
| Object val = ctx.field.value(ctx.portObj); |
| |
| if (exists) { |
| assertTrue(ctx.field.exists(ctx.portObj)); |
| |
| Object expVal = U.field(ctx.obj, fieldName); |
| |
| if (val instanceof BinaryObject) |
| val = ((BinaryObject) val).deserialize(); |
| |
| if (val != null && val.getClass().isArray()) { |
| assertNotNull(expVal); |
| |
| if (val instanceof byte[]) |
| assertTrue(Arrays.equals((byte[]) expVal, (byte[]) val)); |
| else if (val instanceof boolean[]) |
| assertTrue(Arrays.equals((boolean[]) expVal, (boolean[]) val)); |
| else if (val instanceof short[]) |
| assertTrue(Arrays.equals((short[]) expVal, (short[]) val)); |
| else if (val instanceof char[]) |
| assertTrue(Arrays.equals((char[]) expVal, (char[]) val)); |
| else if (val instanceof int[]) |
| assertTrue(Arrays.equals((int[]) expVal, (int[]) val)); |
| else if (val instanceof long[]) |
| assertTrue(Arrays.equals((long[]) expVal, (long[]) val)); |
| else if (val instanceof float[]) |
| assertTrue(Arrays.equals((float[]) expVal, (float[]) val)); |
| else if (val instanceof double[]) |
| assertTrue(Arrays.equals((double[]) expVal, (double[]) val)); |
| else { |
| Object[] expVal0 = (Object[])expVal; |
| Object[] val0 = (Object[])val; |
| |
| assertEquals(expVal0.length, val0.length); |
| |
| for (int i = 0; i < expVal0.length; i++) { |
| Object expItem = expVal0[i]; |
| Object item = val0[i]; |
| |
| if (item instanceof BinaryObject) |
| item = ((BinaryObject)item).deserialize(); |
| |
| assertEquals(expItem, item); |
| } |
| } |
| } |
| else |
| assertEquals(expVal, val); |
| } |
| else { |
| assertFalse(ctx.field.exists(ctx.portObj)); |
| |
| assert val == null; |
| } |
| } |
| |
| /** |
| * Get test context. |
| * |
| * @param marsh Binary marshaller. |
| * @param fieldName Field name. |
| * @return Test context. |
| * @throws Exception If failed. |
| */ |
| private TestContext context(BinaryMarshaller marsh, String fieldName) throws Exception { |
| TestObject obj = createObject(); |
| |
| BinaryObjectExImpl portObj = toBinary(marsh, obj); |
| |
| BinaryField field = portObj.type().field(fieldName); |
| |
| return new TestContext(obj, portObj, field); |
| } |
| |
| /** |
| * Get test context with nested test object. |
| * |
| * @param marsh Binary marshaller. |
| * @param fieldName Field name. |
| * @return Test context. |
| * @throws Exception If failed. |
| */ |
| private TestContext nestedContext(BinaryMarshaller marsh, String fieldName) |
| throws Exception { |
| TestObject obj = createObject(); |
| TestOuterObject outObj = new TestOuterObject(obj); |
| |
| BinaryObjectExImpl portOutObj = toBinary(marsh, outObj); |
| BinaryObjectExImpl portObj = portOutObj.field("fInner"); |
| |
| assert portObj != null; |
| |
| BinaryField field = portObj.type().field(fieldName); |
| |
| return new TestContext(obj, portObj, field); |
| } |
| |
| /** |
| * Create test object. |
| * |
| * @return Test object. |
| */ |
| private TestObject createObject() { |
| return new TestObject(0); |
| } |
| |
| /** |
| * Convert object to binary object. |
| * |
| * @param marsh Marshaller. |
| * @param obj Object. |
| * @return Binary object. |
| * @throws Exception If failed. |
| */ |
| protected abstract BinaryObjectExImpl toBinary(BinaryMarshaller marsh, Object obj) throws Exception; |
| |
| /** |
| * Outer test object. |
| */ |
| public static class TestOuterObject { |
| /** Inner object. */ |
| public TestObject fInner; |
| |
| /** |
| * Default constructor. |
| */ |
| public TestOuterObject() { |
| // No-op. |
| } |
| |
| /** |
| * Constructor. |
| * |
| * @param fInner Inner object. |
| */ |
| public TestOuterObject(TestObject fInner) { |
| this.fInner = fInner; |
| } |
| } |
| |
| /** |
| * Test object class, c |
| */ |
| public static class TestObject { |
| /** Primitive fields. */ |
| public byte fByte; |
| |
| public boolean fBool; |
| |
| public short fShort; |
| |
| public char fChar; |
| |
| public int fInt; |
| |
| public long fLong; |
| |
| public float fFloat; |
| |
| public double fDouble; |
| |
| public byte[] fByteArr; |
| |
| public boolean[] fBoolArr; |
| |
| public short[] fShortArr; |
| |
| public char[] fCharArr; |
| |
| public int[] fIntArr; |
| |
| public long[] fLongArr; |
| |
| public float[] fFloatArr; |
| |
| public double[] fDoubleArr; |
| |
| /** Special fields. */ |
| public String fString; |
| |
| public Date fDate; |
| |
| public Timestamp fTimestamp; |
| |
| public UUID fUuid; |
| |
| public BigDecimal fDecimal; |
| |
| public String[] fStringArr; |
| |
| public Date[] fDateArr; |
| |
| public Timestamp[] fTimestampArr; |
| |
| public UUID[] fUuidArr; |
| |
| public BigDecimal[] fDecimalArr; |
| |
| /** Nested object. */ |
| public TestInnerObject fObj; |
| |
| public TestInnerObject[] fObjArr; |
| |
| /** Field which is always set to null. */ |
| public Object fNull; |
| |
| /** |
| * Default constructor. |
| */ |
| public TestObject() { |
| // No-op. |
| } |
| |
| /** |
| * Non-default constructor. |
| * |
| * @param ignore Ignored. |
| */ |
| public TestObject(int ignore) { |
| fByte = 1; |
| fBool = true; |
| fShort = 2; |
| fChar = 3; |
| fInt = 4; |
| fLong = 5; |
| fFloat = 6.6f; |
| fDouble = 7.7; |
| |
| fByteArr = new byte[] { 1, 2 }; |
| fBoolArr = new boolean[] { true, false }; |
| fShortArr = new short[] { 2, 3 }; |
| fCharArr = new char[] { 3, 4 }; |
| fIntArr = new int[] { 4, 5 }; |
| fLongArr = new long[] { 5, 6 }; |
| fFloatArr = new float[] { 6.6f, 7.7f }; |
| fDoubleArr = new double[] { 7.7, 8.8 }; |
| |
| fString = "8"; |
| fDate = new Date(); |
| fTimestamp = new Timestamp(new Date().getTime() + 1); |
| fUuid = UUID.randomUUID(); |
| fDecimal = new BigDecimal(9); |
| |
| fStringArr = new String[] { "8", "9" }; |
| fDateArr = new Date[] { new Date(), new Date(new Date().getTime() + 1) }; |
| fTimestampArr = |
| new Timestamp[] { new Timestamp(new Date().getTime() + 1), new Timestamp(new Date().getTime() + 2) }; |
| fUuidArr = new UUID[] { UUID.randomUUID(), UUID.randomUUID() }; |
| fDecimalArr = new BigDecimal[] { new BigDecimal(9), new BigDecimal(10) }; |
| |
| fObj = new TestInnerObject(10); |
| fObjArr = new TestInnerObject[] { new TestInnerObject(10), new TestInnerObject(11) }; |
| } |
| } |
| |
| /** |
| * Inner test object. |
| */ |
| public static class TestInnerObject { |
| /** Value. */ |
| private int val; |
| |
| /** |
| * Default constructor. |
| */ |
| public TestInnerObject() { |
| // No-op. |
| } |
| |
| /** |
| * Constructor. |
| * |
| * @param val Value. |
| */ |
| public TestInnerObject(int val) { |
| this.val = val; |
| } |
| |
| /** {@inheritDoc} */ |
| @Override public int hashCode() { |
| return val; |
| } |
| |
| /** {@inheritDoc} */ |
| @Override public boolean equals(Object other) { |
| return other != null && other instanceof TestInnerObject && val == ((TestInnerObject)(other)).val; |
| } |
| } |
| |
| /** |
| * Test context. |
| */ |
| public static class TestContext { |
| /** Object. */ |
| public final TestObject obj; |
| |
| /** Binary object. */ |
| public final BinaryObjectExImpl portObj; |
| |
| /** Field. */ |
| public final BinaryField field; |
| |
| /** |
| * Constructor. |
| * |
| * @param obj Object. |
| * @param portObj Binary object. |
| * @param field Field. |
| */ |
| public TestContext(TestObject obj, BinaryObjectExImpl portObj, BinaryField field) { |
| this.obj = obj; |
| this.portObj = portObj; |
| this.field = field; |
| } |
| } |
| } |