This is an automated email from the ASF dual-hosted git repository.

amashenkov pushed a commit to branch ignite-13618
in repository https://gitbox.apache.org/repos/asf/ignite.git


The following commit(s) were added to refs/heads/ignite-13618 by this push:
     new 181f7bc  Fix broken null fields serialization in JaninoSerilizer. 
Tests added.
181f7bc is described below

commit 181f7bc48d1246118319530587a6c06e7b704f05
Author: Andrew Mashenkov <andrey.mashen...@gmail.com>
AuthorDate: Fri Nov 20 13:37:25 2020 +0300

    Fix broken null fields serialization in JaninoSerilizer. Tests added.
---
 .../generator/FieldAccessExprGenerator.java        | 207 ++++++++++++++++++++-
 .../generator/JaninoSerializerGenerator.java       | 162 +---------------
 .../schema/marshaller/JavaSerializerTest.java      |  26 +--
 .../marshaller/reflection/FieldAccessorTest.java   | 106 +++++++++--
 4 files changed, 302 insertions(+), 199 deletions(-)

diff --git 
a/modules/commons/src/main/java/org/apache/ignite/internal/schema/marshaller/generator/FieldAccessExprGenerator.java
 
b/modules/commons/src/main/java/org/apache/ignite/internal/schema/marshaller/generator/FieldAccessExprGenerator.java
index e596e13..21c4a8f 100644
--- 
a/modules/commons/src/main/java/org/apache/ignite/internal/schema/marshaller/generator/FieldAccessExprGenerator.java
+++ 
b/modules/commons/src/main/java/org/apache/ignite/internal/schema/marshaller/generator/FieldAccessExprGenerator.java
@@ -17,12 +17,169 @@
 
 package org.apache.ignite.internal.schema.marshaller.generator;
 
+import org.apache.ignite.internal.schema.marshaller.BinaryMode;
 import org.jetbrains.annotations.Nullable;
 
+import static 
org.apache.ignite.internal.schema.marshaller.generator.JaninoSerializerGenerator.LF;
+import static 
org.apache.ignite.internal.schema.marshaller.generator.JaninoSerializerGenerator.TAB;
+
 /**
  * Object field access expression generators.
  */
 class FieldAccessExprGenerator {
+    /** Append null expression. */
+    private static final String WRITE_NULL_EXPR = "asm.appendNull();";
+
+    /**
+     * Created object field access expressions generator.
+     *
+     * @param mode Field access binary mode.
+     * @param colIdx Column absolute index in schema.
+     * @param offset Object field offset.
+     * @return Object field access expressions generator.
+     */
+    static FieldAccessExprGenerator createAccessor(BinaryMode mode, int 
colIdx, long offset) {
+        switch (mode) {
+            case BYTE:
+                return new FieldAccessExprGenerator(
+                    colIdx,
+                    "Byte",
+                    "tuple.byteValueBoxed",
+                    "asm.appendByte",
+                    offset);
+
+            case P_BYTE:
+                return new FieldAccessExprGenerator(
+                    colIdx,
+                    "tuple.byteValue",
+                    "asm.appendByte",
+                    offset,
+                    "IgniteUnsafeUtils.getByteField",
+                    "IgniteUnsafeUtils.putByteField"
+                );
+
+            case SHORT:
+                return new FieldAccessExprGenerator(
+                    colIdx,
+                    "Short",
+                    "tuple.shortValueBoxed",
+                    "asm.appendShort",
+                    offset);
+
+            case P_SHORT:
+                return new FieldAccessExprGenerator(
+                    colIdx,
+                    "tuple.shortValue",
+                    "asm.appendShort",
+                    offset,
+                    "IgniteUnsafeUtils.getShortField",
+                    "IgniteUnsafeUtils.putShortField"
+                );
+
+            case INT:
+                return new FieldAccessExprGenerator(
+                    colIdx,
+                    "Integer",
+                    "tuple.intValueBoxed",
+                    "asm.appendInt",
+                    offset);
+
+            case P_INT:
+                return new FieldAccessExprGenerator(
+                    colIdx,
+                    "tuple.intValue",
+                    "asm.appendInt",
+                    offset,
+                    "IgniteUnsafeUtils.getIntField",
+                    "IgniteUnsafeUtils.putIntField"
+                );
+
+            case LONG:
+                return new FieldAccessExprGenerator(
+                    colIdx,
+                    "Long",
+                    "tuple.longValueBoxed",
+                    "asm.appendLong",
+                    offset);
+
+            case P_LONG:
+                return new FieldAccessExprGenerator(
+                    colIdx,
+                    "tuple.longValue",
+                    "asm.appendLong",
+                    offset,
+                    "IgniteUnsafeUtils.getLongField",
+                    "IgniteUnsafeUtils.putLongField"
+                );
+
+            case FLOAT:
+                return new FieldAccessExprGenerator(
+                    colIdx,
+                    "Float",
+                    "tuple.floatValueBoxed",
+                    "asm.appendFloat",
+                    offset);
+
+            case P_FLOAT:
+                return new FieldAccessExprGenerator(
+                    colIdx,
+                    "tuple.floatValue",
+                    "asm.appendFloat",
+                    offset,
+                    "IgniteUnsafeUtils.getFloatField",
+                    "IgniteUnsafeUtils.putFloatField"
+                );
+
+            case DOUBLE:
+                return new FieldAccessExprGenerator(
+                    colIdx,
+                    "Double",
+                    "tuple.doubleValueBoxed",
+                    "asm.appendDouble",
+                    offset);
+
+            case P_DOUBLE:
+                return new FieldAccessExprGenerator(
+                    colIdx,
+                    "tuple.doubleValue",
+                    "asm.appendDouble",
+                    offset,
+                    "IgniteUnsafeUtils.getDoubleField",
+                    "IgniteUnsafeUtils.putDoubleField"
+                );
+
+            case UUID:
+                return new FieldAccessExprGenerator(
+                    colIdx,
+                    "UUID",
+                    "tuple.uuidValue", "asm.appendUuid",
+                    offset);
+
+            case BITSET:
+                return new FieldAccessExprGenerator(
+                    colIdx,
+                    "BitSet",
+                    "tuple.bitmaskValue", "asm.appendBitmask",
+                    offset);
+
+            case STRING:
+                return new FieldAccessExprGenerator(
+                    colIdx,
+                    "String",
+                    "tuple.stringValue", "asm.appendString",
+                    offset);
+
+            case BYTE_ARR:
+                return new FieldAccessExprGenerator(
+                    colIdx,
+                    "byte[]",
+                    "tuple.bytesValue", "asm.appendBytes",
+                    offset);
+            default:
+                throw new IllegalStateException("Unsupportd binary mode");
+        }
+    }
+
     /** Object field offset or {@code -1} for identity accessor. */
     private final long offset;
 
@@ -30,7 +187,7 @@ class FieldAccessExprGenerator {
     private final int colIdx;
 
     /** Class cast expression. */
-    private final String castClassExpr;
+    private final String classExpr;
 
     /** Write column value expression. */
     private final String writeColMethod;
@@ -53,7 +210,7 @@ class FieldAccessExprGenerator {
      * @param writeColMethod Write column value expression.
      * @param offset Field offset or {@code -1} for identity accessor.
      */
-    public FieldAccessExprGenerator(
+    private FieldAccessExprGenerator(
         int colIdx,
         String castClassExpr,
         String readColMethod,
@@ -107,7 +264,7 @@ class FieldAccessExprGenerator {
     ) {
         this.offset = offset;
         this.colIdx = colIdx;
-        this.castClassExpr = castClassExpr;
+        this.classExpr = castClassExpr;
         this.putFieldMethod = putFieldMethod;
         this.getFieldMethod = getFieldMethod;
         this.writeColMethod = writeColMethod;
@@ -115,10 +272,24 @@ class FieldAccessExprGenerator {
     }
 
     /**
+     * @return {@code true} if it is primitive typed field accessor, {@code 
false} otherwise.
+     */
+    private boolean isPrimitive() {
+        return classExpr == null;
+    }
+
+    /**
+     * @return {@code true} if is identity accessor, {@code false} otherwise.
+     */
+    private boolean isIdentityAccessor() {
+        return offset == -1;
+    }
+
+    /**
      * @return Object field value access expression or object value expression 
for simple types.
      */
     public String getFieldExpr() {
-        if (offset == -1)
+        if (isIdentityAccessor())
             return "obj"; // Identity accessor.
 
         return getFieldMethod + "(obj, " + offset + ')';
@@ -133,7 +304,7 @@ class FieldAccessExprGenerator {
      */
     public final void appendPutFieldExpr(StringBuilder sb, String 
valueExpression, String indent) {
         sb.append(indent).append(putFieldMethod).append("(obj, 
").append(offset).append(", ").append(valueExpression).append(')');
-        sb.append(";" + JaninoSerializerGenerator.LF);
+        sb.append(";" + LF);
     }
 
     /**
@@ -144,12 +315,30 @@ class FieldAccessExprGenerator {
      * @param indent Line indentation.
      */
     public final void appendWriteColumnExpr(StringBuilder sb, String 
valueExpr, String indent) {
-        sb.append(indent).append(writeColMethod).append('(');
+        if (isPrimitive() || isIdentityAccessor()) {
+            // Translate to:
+            // asm.appendX((T) %value%);
+            // or for primitive value:
+            // asm.appendX(%value%);
+            sb.append(indent).append(writeColMethod).append('(');
+
+            if (classExpr != null)
+                sb.append("(").append(classExpr).append(")");
+
+            sb.append(valueExpr).append(");" + LF);
+
+            return;
+        }
+
+        assert classExpr != null;
 
-        if (castClassExpr != null)
-            sb.append("(").append(castClassExpr).append(")");
+        // Translate to:
+        // { T fVal = (T)%value%;
+        //  if (fVal == null) asm.appendNull() else asm.appendX(fVal); }
+        sb.append(indent).append("{ ").append(classExpr).append(" fVal = 
(").append(classExpr).append(')').append(valueExpr).append(";" + LF);
+        sb.append(indent).append("if (fVal == null) " + WRITE_NULL_EXPR + LF);
+        sb.append(indent).append("else 
").append(writeColMethod).append("(fVal); }" + LF);
 
-        sb.append(valueExpr).append(");" + JaninoSerializerGenerator.LF);
     }
 
     /**
diff --git 
a/modules/commons/src/main/java/org/apache/ignite/internal/schema/marshaller/generator/JaninoSerializerGenerator.java
 
b/modules/commons/src/main/java/org/apache/ignite/internal/schema/marshaller/generator/JaninoSerializerGenerator.java
index 8d88b2f..21a3201 100644
--- 
a/modules/commons/src/main/java/org/apache/ignite/internal/schema/marshaller/generator/JaninoSerializerGenerator.java
+++ 
b/modules/commons/src/main/java/org/apache/ignite/internal/schema/marshaller/generator/JaninoSerializerGenerator.java
@@ -44,7 +44,7 @@ public class JaninoSerializerGenerator implements 
SerializerFactory {
     public static final int INITIAL_BUFFER_SIZE = 8 * 1024;
 
     /** Debug flag. */
-    private static final boolean enabledDebug = false;
+    private static final boolean enabledDebug = true;
 
     /** {@inheritDoc} */
     @Override public Serializer create(
@@ -60,9 +60,13 @@ public class JaninoSerializerGenerator implements 
SerializerFactory {
 
             //TODO: pass code to logger on trace level.
 
-            if (enabledDebug)
+            if (enabledDebug) {
                 ce.setDebuggingInformation(true, true, true);
 
+                //TODO: dump code to log.
+                System.out.println(code);
+            }
+
             try {  // Compile and load class.
                 ce.setParentClassLoader(getClass().getClassLoader());
                 ce.cook(code);
@@ -168,14 +172,14 @@ public class JaninoSerializerGenerator implements 
SerializerFactory {
         BinaryMode mode = MarshallerUtil.mode(aClass);
 
         if (mode != null)
-            return new 
IdentityObjectMarshallerExprGenerator(createAccessor(mode, firstColIdx, -1L));
+            return new 
IdentityObjectMarshallerExprGenerator(FieldAccessExprGenerator.createAccessor(mode,
 firstColIdx, -1L));
 
         FieldAccessExprGenerator[] accessors = new 
FieldAccessExprGenerator[columns.length()];
         try {
             for (int i = 0; i < columns.length(); i++) {
                 final Field field = 
aClass.getDeclaredField(columns.column(i).name());
 
-                accessors[i] = createAccessor(
+                accessors[i] = FieldAccessExprGenerator.createAccessor(
                     MarshallerUtil.mode(field.getType()),
                     firstColIdx + i /* schma absolute index. */,
                     IgniteUnsafeUtils.objectFieldOffset(field));
@@ -189,156 +193,6 @@ public class JaninoSerializerGenerator implements 
SerializerFactory {
     }
 
     /**
-     * Created object field access expressions generator.
-     *
-     * @param mode Field access binary mode.
-     * @param colIdx Column absolute index in schema.
-     * @param offset Object field offset.
-     * @return Object field access expressions generator.
-     */
-    private FieldAccessExprGenerator createAccessor(BinaryMode mode, int 
colIdx, long offset) {
-        switch (mode) {
-            case BYTE:
-                return new FieldAccessExprGenerator(
-                    colIdx,
-                    "Byte",
-                    "tuple.byteValueBoxed",
-                    "asm.appendByte",
-                    offset);
-
-            case P_BYTE:
-                return new FieldAccessExprGenerator(
-                    colIdx,
-                    "tuple.byteValue",
-                    "asm.appendByte",
-                    offset,
-                    "IgniteUnsafeUtils.getByteField",
-                    "IgniteUnsafeUtils.putByteField"
-                );
-
-            case SHORT:
-                return new FieldAccessExprGenerator(
-                    colIdx,
-                    "Short",
-                    "tuple.shortValueBoxed",
-                    "asm.appendShort",
-                    offset);
-
-            case P_SHORT:
-                return new FieldAccessExprGenerator(
-                    colIdx,
-                    "tuple.shortValue",
-                    "asm.appendShort",
-                    offset,
-                    "IgniteUnsafeUtils.getShortField",
-                    "IgniteUnsafeUtils.putShortField"
-                );
-
-            case INT:
-                return new FieldAccessExprGenerator(
-                    colIdx,
-                    "Integer",
-                    "tuple.intValueBoxed",
-                    "asm.appendInt",
-                    offset);
-
-            case P_INT:
-                return new FieldAccessExprGenerator(
-                    colIdx,
-                    "tuple.intValue",
-                    "asm.appendInt",
-                    offset,
-                    "IgniteUnsafeUtils.getIntField",
-                    "IgniteUnsafeUtils.putIntField"
-                );
-
-            case LONG:
-                return new FieldAccessExprGenerator(
-                    colIdx,
-                    "Long",
-                    "tuple.longValueBoxed",
-                    "asm.appendLong",
-                    offset);
-
-            case P_LONG:
-                return new FieldAccessExprGenerator(
-                    colIdx,
-                    "tuple.longValue",
-                    "asm.appendLong",
-                    offset,
-                    "IgniteUnsafeUtils.getLongField",
-                    "IgniteUnsafeUtils.putLongField"
-                );
-
-            case FLOAT:
-                return new FieldAccessExprGenerator(
-                    colIdx,
-                    "Float",
-                    "tuple.floatValueBoxed",
-                    "asm.appendFloat",
-                    offset);
-
-            case P_FLOAT:
-                return new FieldAccessExprGenerator(
-                    colIdx,
-                    "tuple.floatValue",
-                    "asm.appendFloat",
-                    offset,
-                    "IgniteUnsafeUtils.getFloatField",
-                    "IgniteUnsafeUtils.putFloatField"
-                );
-
-            case DOUBLE:
-                return new FieldAccessExprGenerator(
-                    colIdx,
-                    "Double",
-                    "tuple.doubleValueBoxed",
-                    "asm.appendDouble",
-                    offset);
-
-            case P_DOUBLE:
-                return new FieldAccessExprGenerator(
-                    colIdx,
-                    "tuple.doubleValue",
-                    "asm.appendDouble",
-                    offset,
-                    "IgniteUnsafeUtils.getDoubleField",
-                    "IgniteUnsafeUtils.putDoubleField"
-                );
-
-            case UUID:
-                return new FieldAccessExprGenerator(
-                    colIdx,
-                    "UUID",
-                    "tuple.uuidValue", "asm.appendUuid",
-                    offset);
-
-            case BITSET:
-                return new FieldAccessExprGenerator(
-                    colIdx,
-                    "BitSet",
-                    "tuple.bitmaskValue", "asm.appendBitmask",
-                    offset);
-
-            case STRING:
-                return new FieldAccessExprGenerator(
-                    colIdx,
-                    "String",
-                    "tuple.stringValue", "asm.appendString",
-                    offset);
-
-            case BYTE_ARR:
-                return new FieldAccessExprGenerator(
-                    colIdx,
-                    "byte[]",
-                    "tuple.bytesValue", "asm.appendBytes",
-                    offset);
-            default:
-                throw new IllegalStateException("Unsupportd binary mode");
-        }
-    }
-
-    /**
      * Appends {@link Serializer#serialize(Object, Object)} method code.
      *
      * @param sb String buffer to append to.
diff --git 
a/modules/commons/src/test/java/org/apache/ignite/internal/schema/marshaller/JavaSerializerTest.java
 
b/modules/commons/src/test/java/org/apache/ignite/internal/schema/marshaller/JavaSerializerTest.java
index 8899b8c..0b77966 100644
--- 
a/modules/commons/src/test/java/org/apache/ignite/internal/schema/marshaller/JavaSerializerTest.java
+++ 
b/modules/commons/src/test/java/org/apache/ignite/internal/schema/marshaller/JavaSerializerTest.java
@@ -116,25 +116,7 @@ public class JavaSerializerTest {
     @MethodSource("serializerFactoryProvider")
     public void testBasicTypes(SerializerFactory factory) throws 
SerializationException {
         // Fixed types:
-        checkBasicType(factory, BYTE, BYTE);
-        checkBasicType(factory, SHORT, SHORT);
-        checkBasicType(factory, INTEGER, INTEGER);
         checkBasicType(factory, LONG, LONG);
-        checkBasicType(factory, FLOAT, FLOAT);
-        checkBasicType(factory, DOUBLE, DOUBLE);
-        checkBasicType(factory, UUID, UUID);
-        checkBasicType(factory, Bitmask.of(4), Bitmask.of(5));
-
-        // Varlen types:
-        checkBasicType(factory, BYTES, BYTES);
-        checkBasicType(factory, STRING, STRING);
-
-        // Mixed:
-        checkBasicType(factory, LONG, INTEGER);
-        checkBasicType(factory, FLOAT, DOUBLE);
-        checkBasicType(factory, INTEGER, BYTES);
-        checkBasicType(factory, STRING, LONG);
-        checkBasicType(factory, Bitmask.of(9), BYTES);
     }
 
     /**
@@ -155,12 +137,14 @@ public class JavaSerializerTest {
             new Column("shortCol", SHORT, true),
             new Column("intCol", INTEGER, true),
             new Column("longCol", LONG, true),
+            new Column("nullLongCol", LONG, true),
             new Column("floatCol", FLOAT, true),
             new Column("doubleCol", DOUBLE, true),
 
             new Column("uuidCol", UUID, true),
             new Column("bitmaskCol", Bitmask.of(42), true),
             new Column("stringCol", STRING, true),
+            new Column("nullBytesCol", BYTES, true),
             new Column("bytesCol", BYTES, true),
         };
 
@@ -393,6 +377,7 @@ public class JavaSerializerTest {
         private Short shortCol;
         private Integer intCol;
         private Long longCol;
+        private Long nullLongCol;
         private Float floatCol;
         private Double doubleCol;
 
@@ -400,6 +385,7 @@ public class JavaSerializerTest {
         private BitSet bitmaskCol;
         private String stringCol;
         private byte[] bytesCol;
+        private byte[] nullBytesCol;
 
         /** {@inheritDoc} */
         @Override public boolean equals(Object o) {
@@ -421,12 +407,14 @@ public class JavaSerializerTest {
                 Objects.equals(shortCol, object.shortCol) &&
                 Objects.equals(intCol, object.intCol) &&
                 Objects.equals(longCol, object.longCol) &&
+                Objects.equals(nullLongCol, object.nullLongCol) &&
                 Objects.equals(floatCol, object.floatCol) &&
                 Objects.equals(doubleCol, object.doubleCol) &&
                 Objects.equals(uuidCol, object.uuidCol) &&
                 Objects.equals(bitmaskCol, object.bitmaskCol) &&
                 Objects.equals(stringCol, object.stringCol) &&
-                Arrays.equals(bytesCol, object.bytesCol);
+                Arrays.equals(bytesCol, object.bytesCol) &&
+                Arrays.equals(nullBytesCol, object.nullBytesCol);
         }
 
         /** {@inheritDoc} */
diff --git 
a/modules/commons/src/test/java/org/apache/ignite/internal/schema/marshaller/reflection/FieldAccessorTest.java
 
b/modules/commons/src/test/java/org/apache/ignite/internal/schema/marshaller/reflection/FieldAccessorTest.java
index 0d4c4a5..5631b31 100644
--- 
a/modules/commons/src/test/java/org/apache/ignite/internal/schema/marshaller/reflection/FieldAccessorTest.java
+++ 
b/modules/commons/src/test/java/org/apache/ignite/internal/schema/marshaller/reflection/FieldAccessorTest.java
@@ -82,20 +82,20 @@ public class FieldAccessorTest {
             new Column("pFloatCol", FLOAT, false),
             new Column("pDoubleCol", DOUBLE, false),
 
-            new Column("byteCol", BYTE, true),
-            new Column("shortCol", SHORT, true),
-            new Column("intCol", INTEGER, true),
-            new Column("longCol", LONG, true),
-            new Column("floatCol", FLOAT, true),
-            new Column("doubleCol", DOUBLE, true),
-
-            new Column("uuidCol", UUID, true),
-            new Column("bitmaskCol", Bitmask.of(9), true),
-            new Column("stringCol", STRING, true),
-            new Column("bytesCol", BYTES, true),
+            new Column("byteCol", BYTE, false),
+            new Column("shortCol", SHORT, false),
+            new Column("intCol", INTEGER, false),
+            new Column("longCol", LONG, false),
+            new Column("floatCol", FLOAT, false),
+            new Column("doubleCol", DOUBLE, false),
+
+            new Column("uuidCol", UUID, false),
+            new Column("bitmaskCol", Bitmask.of(9), false),
+            new Column("stringCol", STRING, false),
+            new Column("bytesCol", BYTES, false),
         };
 
-        final Pair<TupleAssembler, Tuple> mocks = createMocks();
+        final Pair<TupleAssembler, Tuple> mocks = createMocks(new 
ArrayList<>());
 
         final TupleAssembler tupleAssembler = mocks.getFirst();
         final Tuple tuple = mocks.getSecond();
@@ -140,6 +140,50 @@ public class FieldAccessorTest {
      * @throws Exception If failed.
      */
     @Test
+    public void testNullableFieldsAccessor() throws Exception {
+        Column[] cols = new Column[] {
+            new Column("intCol", INTEGER, true),
+            new Column("longCol", LONG, true),
+
+            new Column("stringCol", STRING, true),
+            new Column("bytesCol", BYTES, true),
+        };
+
+        final ArrayList<Object> vals = new ArrayList<>();
+        final Pair<TupleAssembler, Tuple> mocks = createMocks(vals);
+
+        final TupleAssembler tupleAssembler = mocks.getFirst();
+        final Tuple tuple = mocks.getSecond();
+
+        final TestSimpleObject obj = new TestSimpleObject();
+        obj.longCol = rnd.nextLong();
+        obj.stringCol = TestUtils.randomString(rnd, 255);
+
+        for (int i = 0; i < cols.length; i++) {
+            UnsafeFieldAccessor accessor = 
UnsafeFieldAccessor.create(TestSimpleObject.class, cols[i], i);
+
+            accessor.write(obj, tupleAssembler);
+        }
+
+        final TestSimpleObject restoredObj = new TestSimpleObject();
+
+        for (int i = 0; i < cols.length; i++) {
+            UnsafeFieldAccessor accessor = 
UnsafeFieldAccessor.create(TestSimpleObject.class, cols[i], i);
+
+            accessor.read(restoredObj, tuple);
+        }
+
+        assertEquals(obj.intCol, restoredObj.intCol);
+        assertEquals(obj.longCol, restoredObj.longCol);
+
+        assertEquals(obj.stringCol, restoredObj.stringCol);
+        assertArrayEquals(obj.bytesCol, restoredObj.bytesCol);
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    @Test
     public void testIdentityAccessor() throws Exception {
         final UnsafeFieldAccessor accessor = 
UnsafeFieldAccessor.createIdentityAccessor(
             new Column("col0", STRING, true),
@@ -148,7 +192,7 @@ public class FieldAccessorTest {
 
         assertEquals("Some string", accessor.value("Some string"));
 
-        final Pair<TupleAssembler, Tuple> mocks = createMocks();
+        final Pair<TupleAssembler, Tuple> mocks = createMocks(new 
ArrayList<>());
 
         accessor.write("Other string", mocks.getFirst());
         assertEquals("Other string", accessor.read(mocks.getSecond()));
@@ -166,7 +210,7 @@ public class FieldAccessorTest {
 
         assertEquals("Some string", accessor.value("Some string"));
 
-        final Pair<TupleAssembler, Tuple> mocks = createMocks();
+        final Pair<TupleAssembler, Tuple> mocks = createMocks(new 
ArrayList<>());
 
         assertThrows(
             SerializationException.class,
@@ -179,16 +223,19 @@ public class FieldAccessorTest {
      * Creates mock pair for {@link Tuple} and {@link TupleAssembler).
      *
      * @return Pair of mocks.
+     * @param vals
      */
-    private Pair<TupleAssembler, Tuple> createMocks() {
-        final ArrayList<Object> vals = new ArrayList<>();
+    private Pair<TupleAssembler, Tuple> createMocks(final ArrayList<Object> 
vals) {
 
         final TupleAssembler mockedAsm = Mockito.mock(TupleAssembler.class);
         final Tuple mockedTuple = Mockito.mock(Tuple.class);
 
         final Answer<Void> asmAnswer = new Answer<Void>() {
             @Override public Void answer(InvocationOnMock invocation) {
-                vals.add(invocation.getArguments()[0]);
+                if ("appendNull".equals(invocation.getMethod().getName()))
+                    vals.add(null);
+                else
+                    vals.add(invocation.getArguments()[0]);
 
                 return null;
             }
@@ -319,4 +366,29 @@ public class FieldAccessorTest {
             return 73;
         }
     }
+
+    private static class TestSimpleObject {
+        Long longCol;
+        Integer intCol;
+        byte[] bytesCol;
+        String stringCol;
+
+        /** {@inheritDoc} */
+        @Override public boolean equals(Object o) {
+            if (this == o)
+                return true;
+            if (o == null || getClass() != o.getClass())
+                return false;
+            TestSimpleObject object = (TestSimpleObject)o;
+            return Objects.equals(longCol, object.longCol) &&
+                Objects.equals(intCol, object.intCol) &&
+                Arrays.equals(bytesCol, object.bytesCol) &&
+                Objects.equals(stringCol, object.stringCol);
+        }
+
+        /** {@inheritDoc} */
+        @Override public int hashCode() {
+            return 42;
+        }
+    }
 }

Reply via email to