You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ignite.apache.org by av...@apache.org on 2016/09/19 15:40:58 UTC

[02/10] ignite git commit: IGNITE-3635 - Fixed StackOverflowError thrown from BinaryObject.toString()

IGNITE-3635 - Fixed StackOverflowError thrown from BinaryObject.toString()


Project: http://git-wip-us.apache.org/repos/asf/ignite/repo
Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/c0b2b479
Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/c0b2b479
Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/c0b2b479

Branch: refs/heads/master
Commit: c0b2b4797be4f250f6f1304ff27d45c72154608a
Parents: 98914fe
Author: Valentin Kulichenko <va...@gmail.com>
Authored: Fri Sep 16 14:59:35 2016 -0700
Committer: Valentin Kulichenko <va...@gmail.com>
Committed: Fri Sep 16 14:59:35 2016 -0700

----------------------------------------------------------------------
 .../internal/binary/BinaryObjectExImpl.java     | 161 +++++++++++++------
 .../binary/BinaryObjectToStringSelfTest.java    |  75 +++++++++
 .../IgniteBinaryObjectsTestSuite.java           |   2 +
 3 files changed, 190 insertions(+), 48 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/c0b2b479/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryObjectExImpl.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryObjectExImpl.java b/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryObjectExImpl.java
index b4e909e..e6df407 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryObjectExImpl.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryObjectExImpl.java
@@ -20,14 +20,16 @@ package org.apache.ignite.internal.binary;
 import java.math.BigDecimal;
 import java.util.Arrays;
 import java.util.IdentityHashMap;
+import java.util.Iterator;
+import java.util.Map;
 import org.apache.ignite.IgniteException;
+import org.apache.ignite.binary.BinaryObject;
 import org.apache.ignite.binary.BinaryObjectBuilder;
+import org.apache.ignite.binary.BinaryObjectException;
+import org.apache.ignite.binary.BinaryType;
 import org.apache.ignite.internal.binary.builder.BinaryObjectBuilderImpl;
 import org.apache.ignite.internal.util.offheap.unsafe.GridUnsafeMemory;
 import org.apache.ignite.internal.util.typedef.internal.SB;
-import org.apache.ignite.binary.BinaryObjectException;
-import org.apache.ignite.binary.BinaryType;
-import org.apache.ignite.binary.BinaryObject;
 import org.jetbrains.annotations.Nullable;
 
 /**
@@ -164,6 +166,20 @@ public abstract class BinaryObjectExImpl implements BinaryObjectEx {
         }
     }
 
+    /** {@inheritDoc} */
+    @Override public String toString() {
+        try {
+            BinaryReaderHandles ctx = new BinaryReaderHandles();
+
+            ctx.put(start(), this);
+
+            return toString(ctx, new IdentityHashMap<BinaryObject, Integer>());
+        }
+        catch (BinaryObjectException e) {
+            throw new IgniteException("Failed to create string representation of binary object.", e);
+        }
+    }
+
     /**
      * @param ctx Reader context.
      * @param handles Handles for already traversed objects.
@@ -197,43 +213,7 @@ public abstract class BinaryObjectExImpl implements BinaryObjectEx {
 
                 buf.a(", ").a(name).a('=');
 
-                if (val instanceof byte[])
-                    buf.a(Arrays.toString((byte[]) val));
-                else if (val instanceof short[])
-                    buf.a(Arrays.toString((short[])val));
-                else if (val instanceof int[])
-                    buf.a(Arrays.toString((int[])val));
-                else if (val instanceof long[])
-                    buf.a(Arrays.toString((long[])val));
-                else if (val instanceof float[])
-                    buf.a(Arrays.toString((float[])val));
-                else if (val instanceof double[])
-                    buf.a(Arrays.toString((double[])val));
-                else if (val instanceof char[])
-                    buf.a(Arrays.toString((char[])val));
-                else if (val instanceof boolean[])
-                    buf.a(Arrays.toString((boolean[]) val));
-                else if (val instanceof BigDecimal[])
-                    buf.a(Arrays.toString((BigDecimal[])val));
-                else {
-                    if (val instanceof BinaryObjectExImpl) {
-                        BinaryObjectExImpl po = (BinaryObjectExImpl)val;
-
-                        Integer idHash0 = handles.get(val);
-
-                        if (idHash0 != null) {  // Circular reference.
-                            BinaryType meta0 = po.rawType();
-
-                            assert meta0 != null;
-
-                            buf.a(meta0.typeName()).a(" [hash=").a(idHash0).a(", ...]");
-                        }
-                        else
-                            buf.a(po.toString(ctx, handles));
-                    }
-                    else
-                        buf.a(val);
-                }
+                appendValue(val, buf, ctx, handles);
             }
 
             buf.a(']');
@@ -242,17 +222,102 @@ public abstract class BinaryObjectExImpl implements BinaryObjectEx {
         return buf.toString();
     }
 
-    /** {@inheritDoc} */
-    @Override public String toString() {
-        try {
-            BinaryReaderHandles ctx = new BinaryReaderHandles();
+    /**
+     * @param val Value to append.
+     * @param buf Buffer to append to.
+     * @param ctx Reader context.
+     * @param handles Handles for already traversed objects.
+     */
+    private void appendValue(Object val, SB buf, BinaryReaderHandles ctx,
+        IdentityHashMap<BinaryObject, Integer> handles) {
+        if (val instanceof byte[])
+            buf.a(Arrays.toString((byte[]) val));
+        else if (val instanceof short[])
+            buf.a(Arrays.toString((short[])val));
+        else if (val instanceof int[])
+            buf.a(Arrays.toString((int[])val));
+        else if (val instanceof long[])
+            buf.a(Arrays.toString((long[])val));
+        else if (val instanceof float[])
+            buf.a(Arrays.toString((float[])val));
+        else if (val instanceof double[])
+            buf.a(Arrays.toString((double[])val));
+        else if (val instanceof char[])
+            buf.a(Arrays.toString((char[])val));
+        else if (val instanceof boolean[])
+            buf.a(Arrays.toString((boolean[]) val));
+        else if (val instanceof BigDecimal[])
+            buf.a(Arrays.toString((BigDecimal[])val));
+        else if (val instanceof BinaryObjectExImpl) {
+            BinaryObjectExImpl po = (BinaryObjectExImpl)val;
+
+            Integer idHash0 = handles.get(val);
+
+            if (idHash0 != null) {  // Circular reference.
+                BinaryType meta0 = po.rawType();
+
+                assert meta0 != null;
+
+                buf.a(meta0.typeName()).a(" [hash=").a(idHash0).a(", ...]");
+            }
+            else
+                buf.a(po.toString(ctx, handles));
+        }
+        else if (val instanceof Object[]) {
+            Object[] arr = (Object[])val;
 
-            ctx.put(start(), this);
+            buf.a('[');
 
-            return toString(ctx, new IdentityHashMap<BinaryObject, Integer>());
+            for (int i = 0; i < arr.length; i++) {
+                Object o = arr[i];
+
+                appendValue(o, buf, ctx, handles);
+
+                if (i < arr.length - 1)
+                    buf.a(", ");
+            }
         }
-        catch (BinaryObjectException e) {
-            throw new IgniteException("Failed to create string representation of binary object.", e);
+        else if (val instanceof Iterable) {
+            Iterable<Object> col = (Iterable<Object>)val;
+
+            buf.a(col.getClass().getSimpleName()).a(" {");
+
+            Iterator it = col.iterator();
+
+            while (it.hasNext()) {
+                Object o = it.next();
+
+                appendValue(o, buf, ctx, handles);
+
+                if (it.hasNext())
+                    buf.a(", ");
+            }
+
+            buf.a('}');
+        }
+        else if (val instanceof Map) {
+            Map<Object, Object> map = (Map<Object, Object>)val;
+
+            buf.a(map.getClass().getSimpleName()).a(" {");
+
+            Iterator<Map.Entry<Object, Object>> it = map.entrySet().iterator();
+
+            while (it.hasNext()) {
+                Map.Entry<Object, Object> e = it.next();
+
+                appendValue(e.getKey(), buf, ctx, handles);
+
+                buf.a('=');
+
+                appendValue(e.getValue(), buf, ctx, handles);
+
+                if (it.hasNext())
+                    buf.a(", ");
+            }
+
+            buf.a('}');
         }
+        else
+            buf.a(val);
     }
 }

http://git-wip-us.apache.org/repos/asf/ignite/blob/c0b2b479/modules/core/src/test/java/org/apache/ignite/internal/binary/BinaryObjectToStringSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/binary/BinaryObjectToStringSelfTest.java b/modules/core/src/test/java/org/apache/ignite/internal/binary/BinaryObjectToStringSelfTest.java
new file mode 100644
index 0000000..cc6cf8b
--- /dev/null
+++ b/modules/core/src/test/java/org/apache/ignite/internal/binary/BinaryObjectToStringSelfTest.java
@@ -0,0 +1,75 @@
+package org.apache.ignite.internal.binary;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
+import org.apache.ignite.binary.BinaryObject;
+import org.apache.ignite.configuration.IgniteConfiguration;
+import org.apache.ignite.spi.discovery.tcp.TcpDiscoverySpi;
+import org.apache.ignite.spi.discovery.tcp.ipfinder.TcpDiscoveryIpFinder;
+import org.apache.ignite.spi.discovery.tcp.ipfinder.vm.TcpDiscoveryVmIpFinder;
+import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest;
+
+/**
+ * Tests for {@code BinaryObject.toString()}.
+ */
+public class BinaryObjectToStringSelfTest extends GridCommonAbstractTest {
+    /** */
+    private static final TcpDiscoveryIpFinder IP_FINDER = new TcpDiscoveryVmIpFinder(true);
+
+    /** {@inheritDoc} */
+    @Override protected IgniteConfiguration getConfiguration(String gridName) throws Exception {
+        IgniteConfiguration cfg = super.getConfiguration(gridName);
+
+        cfg.setMarshaller(new BinaryMarshaller());
+        cfg.setDiscoverySpi(new TcpDiscoverySpi().setIpFinder(IP_FINDER));
+
+        return cfg;
+    }
+
+    /** {@inheritDoc} */
+    @Override protected void beforeTest() throws Exception {
+        startGrid();
+    }
+
+    /** {@inheritDoc} */
+    @Override protected void afterTest() throws Exception {
+        stopAllGrids();
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    @SuppressWarnings("unchecked")
+    public void testToString() throws Exception {
+        MyObject obj = new MyObject();
+
+        obj.arr = new Object[] {111, "aaa", obj};
+        obj.col = Arrays.asList(222, "bbb", obj);
+
+        obj.map = new HashMap();
+
+        obj.map.put(10, 333);
+        obj.map.put(20, "ccc");
+        obj.map.put(30, obj);
+
+        BinaryObject bo = grid().binary().toBinary(obj);
+
+        // Check that toString() doesn't fail with StackOverflowError or other exceptions.
+        bo.toString();
+    }
+
+    /**
+     */
+    private static class MyObject {
+        /** Object array. */
+        private Object[] arr;
+
+        /** Collection. */
+        private Collection col;
+
+        /** Map. */
+        private Map map;
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/c0b2b479/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteBinaryObjectsTestSuite.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteBinaryObjectsTestSuite.java b/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteBinaryObjectsTestSuite.java
index dc0540d..c1d9974 100644
--- a/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteBinaryObjectsTestSuite.java
+++ b/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteBinaryObjectsTestSuite.java
@@ -30,6 +30,7 @@ import org.apache.ignite.internal.binary.BinaryMarshallerSelfTest;
 import org.apache.ignite.internal.binary.BinaryObjectBuilderAdditionalSelfTest;
 import org.apache.ignite.internal.binary.BinaryObjectBuilderDefaultMappersSelfTest;
 import org.apache.ignite.internal.binary.BinaryObjectBuilderSimpleNameLowerCaseMappersSelfTest;
+import org.apache.ignite.internal.binary.BinaryObjectToStringSelfTest;
 import org.apache.ignite.internal.binary.BinarySimpleNameTestPropertySelfTest;
 import org.apache.ignite.internal.binary.BinaryTreeSelfTest;
 import org.apache.ignite.internal.binary.GridBinaryAffinityKeySelfTest;
@@ -102,6 +103,7 @@ public class IgniteBinaryObjectsTestSuite extends TestSuite {
         suite.addTestSuite(GridSimpleLowerCaseBinaryMappersBinaryMetaDataSelfTest.class);
         suite.addTestSuite(GridBinaryAffinityKeySelfTest.class);
         suite.addTestSuite(GridBinaryWildcardsSelfTest.class);
+        suite.addTestSuite(BinaryObjectToStringSelfTest.class);
 
         // Tests for objects with non-compact footers.
         suite.addTestSuite(BinaryMarshallerNonCompactSelfTest.class);