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

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


The following commit(s) were added to refs/heads/ignite-2.16 by this push:
     new 78c5f7dc505 IGNITE-20816 in-memory server node is crashed by 
TcpIgniteClient.putAllConflict() if cache objects transformation applied 
(#11037)
78c5f7dc505 is described below

commit 78c5f7dc50537ffa143c85dc700542887a673807
Author: Anton Vinogradov <a...@apache.org>
AuthorDate: Thu Nov 16 16:02:15 2023 +0300

    IGNITE-20816 in-memory server node is crashed by 
TcpIgniteClient.putAllConflict() if cache objects transformation applied 
(#11037)
    
    (cherry picked from commit 2d3b96d83c9763d14a07c84bdddb590191647fd4)
---
 .../apache/ignite/internal/binary/BinaryUtils.java |   2 +
 .../cacheobject/PlatformCacheObjectImpl.java       |  71 ++++++
 .../platform/client/ClientMessageParser.java       |   4 +-
 .../cache/ClientCachePutAllConflictRequest.java    |   4 +-
 .../cache/ClientCacheRemoveAllConflictRequest.java |   2 +-
 .../streamer/ClientDataStreamerAddDataRequest.java |   4 +-
 .../client/streamer/ClientDataStreamerReader.java  |   9 +-
 .../streamer/ClientDataStreamerStartRequest.java   |   4 +-
 .../processors/platform/utils/PlatformUtils.java   |   8 +-
 .../CacheObjectTransformationCacheApiTest.java     | 282 +++++++++++++++++++++
 .../ignite/testsuites/IgniteCacheTestSuite13.java  |   3 +
 11 files changed, 373 insertions(+), 20 deletions(-)

diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryUtils.java 
b/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryUtils.java
index 60a00441737..f513d3ddd2f 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryUtils.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryUtils.java
@@ -70,6 +70,7 @@ import 
org.apache.ignite.internal.binary.streams.BinaryInputStream;
 import org.apache.ignite.internal.processors.cache.CacheObjectByteArrayImpl;
 import org.apache.ignite.internal.processors.cache.CacheObjectImpl;
 import org.apache.ignite.internal.processors.cache.KeyCacheObjectImpl;
+import 
org.apache.ignite.internal.processors.cacheobject.PlatformCacheObjectImpl;
 import 
org.apache.ignite.internal.processors.cacheobject.UserCacheObjectByteArrayImpl;
 import org.apache.ignite.internal.processors.cacheobject.UserCacheObjectImpl;
 import 
org.apache.ignite.internal.processors.cacheobject.UserKeyCacheObjectImpl;
@@ -749,6 +750,7 @@ public class BinaryUtils {
             cls == BinaryEnumObjectImpl.class ||
             cls == UserKeyCacheObjectImpl.class ||
             cls == UserCacheObjectImpl.class ||
+            cls == PlatformCacheObjectImpl.class ||
             cls == UserCacheObjectByteArrayImpl.class;
     }
 
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/cacheobject/PlatformCacheObjectImpl.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/cacheobject/PlatformCacheObjectImpl.java
new file mode 100644
index 00000000000..d89ea657bad
--- /dev/null
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/cacheobject/PlatformCacheObjectImpl.java
@@ -0,0 +1,71 @@
+/*
+ * 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.processors.cacheobject;
+
+import org.apache.ignite.internal.GridDirectTransient;
+import org.apache.ignite.internal.processors.cache.CacheObject;
+import org.apache.ignite.internal.processors.cache.CacheObjectContext;
+import org.apache.ignite.internal.processors.cache.CacheObjectImpl;
+import org.apache.ignite.internal.processors.cache.CacheObjectTransformerUtils;
+import org.apache.ignite.internal.processors.cache.CacheObjectValueContext;
+
+/**
+ * Wraps value provided by platform, must be transformed before stored in 
cache.
+ */
+public class PlatformCacheObjectImpl extends CacheObjectImpl {
+    /** */
+    private static final long serialVersionUID = 0L;
+
+    /** */
+    @GridDirectTransient
+    private byte[] arr;
+
+    /**
+     *
+     */
+    public PlatformCacheObjectImpl() {
+        //No-op.
+    }
+
+    /**
+     * @param val Value.
+     * @param arr Value bytes.
+     */
+    public PlatformCacheObjectImpl(Object val, byte[] arr) {
+        super(val, null);
+
+        this.arr = arr;
+    }
+
+    /**
+     * @return Value bytes.
+     */
+    private byte[] valueBytesFromArray(CacheObjectValueContext ctx) {
+        assert arr != null;
+
+        return CacheObjectTransformerUtils.transformIfNecessary(arr, 0, 
arr.length, ctx);
+    }
+
+    /** {@inheritDoc} */
+    @Override public CacheObject prepareForCache(CacheObjectContext ctx) {
+        if (valBytes == null)
+            valBytes = valueBytesFromArray(ctx);
+
+        return this;
+    }
+}
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/ClientMessageParser.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/ClientMessageParser.java
index ab3fe4c1608..6a7562f1a1c 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/ClientMessageParser.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/ClientMessageParser.java
@@ -631,10 +631,10 @@ public class ClientMessageParser implements 
ClientListenerMessageParser {
                 return new ClientServiceGetDescriptorRequest(reader);
 
             case OP_DATA_STREAMER_START:
-                return new ClientDataStreamerStartRequest(reader, ctx);
+                return new ClientDataStreamerStartRequest(reader);
 
             case OP_DATA_STREAMER_ADD_DATA:
-                return new ClientDataStreamerAddDataRequest(reader, ctx);
+                return new ClientDataStreamerAddDataRequest(reader);
 
             case OP_ATOMIC_LONG_CREATE:
                 return new ClientAtomicLongCreateRequest(reader);
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCachePutAllConflictRequest.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCachePutAllConflictRequest.java
index 4701f654e66..ac3182b751b 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCachePutAllConflictRequest.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCachePutAllConflictRequest.java
@@ -60,8 +60,8 @@ public class ClientCachePutAllConflictRequest extends 
ClientCacheDataRequest imp
         map = new LinkedHashMap<>(cnt);
 
         for (int i = 0; i < cnt; i++) {
-            KeyCacheObject key = readCacheObject(reader, true, ctx);
-            CacheObject val = readCacheObject(reader, false, ctx);
+            KeyCacheObject key = readCacheObject(reader, true);
+            CacheObject val = readCacheObject(reader, false);
             GridCacheVersion ver = 
(GridCacheVersion)reader.readObjectDetached();
             long expireTime = reader.readLong();
 
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheRemoveAllConflictRequest.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheRemoveAllConflictRequest.java
index 168585bb099..c6e1a35f1d2 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheRemoveAllConflictRequest.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheRemoveAllConflictRequest.java
@@ -51,7 +51,7 @@ public class ClientCacheRemoveAllConflictRequest extends 
ClientCacheDataRequest
         map = new LinkedHashMap<>(cnt);
 
         for (int i = 0; i < cnt; i++) {
-            KeyCacheObject key = readCacheObject(reader, true, null);
+            KeyCacheObject key = readCacheObject(reader, true);
             GridCacheVersion ver = 
(GridCacheVersion)reader.readObjectDetached();
 
             map.put(key, ver);
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/streamer/ClientDataStreamerAddDataRequest.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/streamer/ClientDataStreamerAddDataRequest.java
index 9eaaec9e2e9..094e7ea02e0 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/streamer/ClientDataStreamerAddDataRequest.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/streamer/ClientDataStreamerAddDataRequest.java
@@ -47,12 +47,12 @@ public class ClientDataStreamerAddDataRequest extends 
ClientDataStreamerRequest
      *
      * @param reader Data reader.
      */
-    public ClientDataStreamerAddDataRequest(BinaryReaderExImpl reader, 
ClientConnectionContext ctx) {
+    public ClientDataStreamerAddDataRequest(BinaryReaderExImpl reader) {
         super(reader);
 
         streamerId = reader.readLong();
         flags = reader.readByte();
-        entries = ClientDataStreamerReader.read(reader, ctx);
+        entries = ClientDataStreamerReader.read(reader);
     }
 
     /**
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/streamer/ClientDataStreamerReader.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/streamer/ClientDataStreamerReader.java
index da1ea65bef8..278910459d1 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/streamer/ClientDataStreamerReader.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/streamer/ClientDataStreamerReader.java
@@ -21,7 +21,6 @@ import java.util.ArrayList;
 import java.util.Collection;
 import org.apache.ignite.internal.binary.BinaryReaderExImpl;
 import org.apache.ignite.internal.processors.datastreamer.DataStreamerEntry;
-import 
org.apache.ignite.internal.processors.platform.client.ClientConnectionContext;
 
 import static 
org.apache.ignite.internal.processors.platform.utils.PlatformUtils.readCacheObject;
 
@@ -35,7 +34,7 @@ class ClientDataStreamerReader {
      * @param reader Data reader.
      * @return Streamer entry.
      */
-    public static Collection<DataStreamerEntry> read(BinaryReaderExImpl 
reader, ClientConnectionContext ctx) {
+    public static Collection<DataStreamerEntry> read(BinaryReaderExImpl 
reader) {
         int entriesCnt = reader.readInt();
 
         if (entriesCnt == 0)
@@ -43,10 +42,8 @@ class ClientDataStreamerReader {
 
         Collection<DataStreamerEntry> entries = new ArrayList<>(entriesCnt);
 
-        for (int i = 0; i < entriesCnt; i++) {
-            entries.add(new DataStreamerEntry(readCacheObject(reader, true, 
ctx),
-                    readCacheObject(reader, false, ctx)));
-        }
+        for (int i = 0; i < entriesCnt; i++)
+            entries.add(new DataStreamerEntry(readCacheObject(reader, true), 
readCacheObject(reader, false)));
 
         return entries;
     }
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/streamer/ClientDataStreamerStartRequest.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/streamer/ClientDataStreamerStartRequest.java
index 7c96f423e69..6ea88a4c49b 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/streamer/ClientDataStreamerStartRequest.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/streamer/ClientDataStreamerStartRequest.java
@@ -72,7 +72,7 @@ public class ClientDataStreamerStartRequest extends 
ClientDataStreamerRequest {
      *
      * @param reader Data reader.
      */
-    public ClientDataStreamerStartRequest(BinaryReaderExImpl reader, 
ClientConnectionContext ctx) {
+    public ClientDataStreamerStartRequest(BinaryReaderExImpl reader) {
         super(reader);
 
         cacheId = reader.readInt();
@@ -81,7 +81,7 @@ public class ClientDataStreamerStartRequest extends 
ClientDataStreamerRequest {
         perThreadBufferSize = reader.readInt();
         receiverObj = reader.readObjectDetached();
         receiverPlatform = receiverObj == null ? 0 : reader.readByte();
-        entries = ClientDataStreamerReader.read(reader, ctx);
+        entries = ClientDataStreamerReader.read(reader);
     }
 
     /** {@inheritDoc} */
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/utils/PlatformUtils.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/utils/PlatformUtils.java
index 94b99943d89..0690e145aab 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/utils/PlatformUtils.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/utils/PlatformUtils.java
@@ -61,14 +61,13 @@ import org.apache.ignite.internal.binary.BinaryUtils;
 import org.apache.ignite.internal.binary.GridBinaryMarshaller;
 import org.apache.ignite.internal.binary.streams.BinaryInputStream;
 import org.apache.ignite.internal.processors.cache.CacheObject;
-import org.apache.ignite.internal.processors.cache.CacheObjectImpl;
 import org.apache.ignite.internal.processors.cache.KeyCacheObjectImpl;
 import 
org.apache.ignite.internal.processors.cache.binary.CacheObjectBinaryProcessorImpl;
+import 
org.apache.ignite.internal.processors.cacheobject.PlatformCacheObjectImpl;
 import org.apache.ignite.internal.processors.platform.PlatformContext;
 import 
org.apache.ignite.internal.processors.platform.PlatformExtendedException;
 import org.apache.ignite.internal.processors.platform.PlatformNativeException;
 import org.apache.ignite.internal.processors.platform.PlatformProcessor;
-import 
org.apache.ignite.internal.processors.platform.client.ClientConnectionContext;
 import 
org.apache.ignite.internal.processors.platform.dotnet.PlatformDotNetServiceImpl;
 import 
org.apache.ignite.internal.processors.platform.memory.PlatformInputStream;
 import org.apache.ignite.internal.processors.platform.memory.PlatformMemory;
@@ -1374,9 +1373,8 @@ public class PlatformUtils {
      *
      * @param reader Reader.
      * @param isKey {@code True} if object is a key.
-     * @param ctx Client connection context.
      */
-    public static <T extends CacheObject> T readCacheObject(BinaryReaderExImpl 
reader, boolean isKey, ClientConnectionContext ctx) {
+    public static <T extends CacheObject> T readCacheObject(BinaryReaderExImpl 
reader, boolean isKey) {
         BinaryInputStream in = reader.in();
 
         int pos0 = in.position();
@@ -1397,7 +1395,7 @@ public class PlatformUtils {
 
         return isKey ?
             (T)new KeyCacheObjectImpl(obj, objBytes, -1) :
-            (T)new CacheObjectImpl(obj, ctx.kernalContext().transformer() == 
null ? objBytes : null);
+            (T)new PlatformCacheObjectImpl(obj, objBytes);
     }
 
     /**
diff --git 
a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/transform/CacheObjectTransformationCacheApiTest.java
 
b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/transform/CacheObjectTransformationCacheApiTest.java
new file mode 100644
index 00000000000..4912ed91d97
--- /dev/null
+++ 
b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/transform/CacheObjectTransformationCacheApiTest.java
@@ -0,0 +1,282 @@
+/*
+ * 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.processors.cache.transform;
+
+import java.nio.ByteBuffer;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.function.Function;
+import org.apache.ignite.Ignite;
+import org.apache.ignite.IgniteCache;
+import org.apache.ignite.cache.CacheAtomicityMode;
+import org.apache.ignite.client.ClientCache;
+import org.apache.ignite.client.IgniteClient;
+import org.apache.ignite.cluster.ClusterState;
+import org.apache.ignite.configuration.CacheConfiguration;
+import org.apache.ignite.configuration.ClientConfiguration;
+import org.apache.ignite.configuration.DataRegionConfiguration;
+import org.apache.ignite.configuration.IgniteConfiguration;
+import org.apache.ignite.internal.client.thin.TcpClientCache;
+import org.apache.ignite.internal.processors.cache.version.GridCacheVersion;
+import org.apache.ignite.internal.util.typedef.G;
+import org.apache.ignite.internal.util.typedef.T3;
+import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+import static 
org.apache.ignite.internal.binary.GridBinaryMarshaller.TRANSFORMED;
+
+/**
+ * Checks transformation works via public and private cache API.
+ */
+@RunWith(Parameterized.class)
+public class CacheObjectTransformationCacheApiTest extends 
GridCommonAbstractTest {
+    /** Region name. */
+    private static final String REGION_NAME = "region";
+
+    /** Cache name. */
+    protected static final String CACHE_NAME = "data";
+
+    /** Nodes count. */
+    protected static final int NODES = 3;
+
+    /** Atomicity mode. */
+    @Parameterized.Parameter()
+    public CacheAtomicityMode mode;
+
+    /** Persistence enabled flag. */
+    @Parameterized.Parameter(1)
+    public boolean persistence;
+
+    /** Generator. */
+    @Parameterized.Parameter(2)
+    public Gen gen;
+
+    /** @return Test parameters. */
+    @Parameterized.Parameters(name = "mode={0}, persistence={1}, gen={2}")
+    public static Collection<?> parameters() {
+        List<Object[]> res = new ArrayList<>();
+
+        for (CacheAtomicityMode mode : CacheAtomicityMode.values())
+            for (boolean persistence : new boolean[] {true, false})
+                for (Gen gen : Gen.values())
+                    res.add(new Object[] {mode, persistence, gen});
+
+        return res;
+    }
+
+    /** {@inheritDoc} */
+    @Override protected void beforeTest() throws Exception {
+        super.beforeTest();
+
+        cleanPersistenceDir();
+
+        Ignite ignite = startGrids(NODES);
+
+        if (persistence)
+            ignite.cluster().state(ClusterState.ACTIVE);
+
+        awaitPartitionMapExchange();
+    }
+
+    /** {@inheritDoc} */
+    @Override protected void afterTest() throws Exception {
+        super.afterTest();
+
+        stopAllGrids();
+
+        cleanPersistenceDir();
+    }
+
+    /** {@inheritDoc} */
+    @Override protected IgniteConfiguration getConfiguration(String 
igniteInstanceName) throws Exception {
+        IgniteConfiguration cfg = super.getConfiguration(igniteInstanceName);
+
+        DataRegionConfiguration drCgf = new DataRegionConfiguration()
+            .setName(REGION_NAME)
+            .setMaxSize(1000L * 1024 * 1024)
+            .setInitialSize(1000L * 1024 * 1024);
+
+        if (persistence)
+            drCgf.setPersistenceEnabled(true);
+
+        cfg.setPluginProviders(
+            new TestCacheObjectTransformerPluginProvider(new 
CacheObjectDuplicatorTransformer()));
+
+        CacheConfiguration<?, ?> cCfg = new 
CacheConfiguration<>(CACHE_NAME).setAtomicityMode(mode);
+
+        cfg.setCacheConfiguration(cCfg);
+
+        return cfg;
+    }
+
+    /** */
+    @Test
+    public void testCachePut() {
+        Ignite ignite = grid(0);
+
+        IgniteCache<Object, Object> cache = 
ignite.getOrCreateCache(CACHE_NAME);
+
+        for (int i = 0; i < 100; i++) {
+            Object val = gen.apply(i);
+
+            cache.put(i, val);
+            cache.put(i, val); // Override check.
+
+            assertEqualsArraysAware(cache.get(i), val);
+        }
+    }
+
+    /** */
+    @Test
+    public void testClientCachePut() {
+        Ignite ignite = grid(0);
+
+        String host = ignite.configuration().getLocalHost();
+        int port = 
ignite.configuration().getClientConnectorConfiguration().getPort();
+
+        try (IgniteClient client = G.startClient(new 
ClientConfiguration().setAddresses(host + ":" + port))) {
+            ClientCache<Object, Object> cache = client.cache(CACHE_NAME);
+
+            for (int i = 0; i < 100; i++) {
+                Object val = gen.apply(i);
+
+                if (i % 2 == 0) {
+                    cache.put(i, val);
+                    cache.put(i, val); // Override check.
+                }
+                else {
+                    Map<Object, T3<Object, GridCacheVersion, Long>> data = new 
HashMap<>();
+
+                    GridCacheVersion otherVer = new GridCacheVersion(1, 1, 1, 
0);
+
+                    data.put(i, new T3<>(val, otherVer, 0L));
+
+                    ((TcpClientCache)cache).putAllConflict(data);
+                    ((TcpClientCache)cache).putAllConflict(data); // Override 
check.
+                }
+
+                assertEqualsArraysAware(cache.get(i), val);
+            }
+        }
+    }
+
+    /**
+     * Transforms each object with a shift.
+     */
+    private static final class CacheObjectDuplicatorTransformer extends 
TestCacheObjectTransformerProcessorAdapter {
+        /** {@inheritDoc} */
+        @Override public ByteBuffer transform(ByteBuffer original) {
+            ByteBuffer transformed = ByteBuffer.wrap(new 
byte[original.remaining() * 2 + 1]);
+
+            transformed.put(TRANSFORMED);
+
+            while (original.hasRemaining()) {
+                byte b = original.get();
+
+                transformed.put(b);
+                transformed.put(b);
+            }
+
+            transformed.flip();
+
+            return transformed;
+        }
+
+        /** {@inheritDoc} */
+        @Override public ByteBuffer restore(ByteBuffer transformed) {
+            ByteBuffer restored = ByteBuffer.wrap(new 
byte[transformed.remaining() / 2]);
+
+            while (transformed.hasRemaining()) {
+                byte b1 = transformed.get();
+                byte b2 = transformed.get();
+
+                assertEquals(b1, b2);
+
+                restored.put(b1);
+            }
+
+            restored.flip();
+
+            return restored;
+        }
+    }
+
+    /** */
+    private static final class TestData {
+        /** */
+        int i;
+
+        /** */
+        public TestData(int i) {
+            this.i = i;
+        }
+
+        /** {@inheritDoc} */
+        @Override public boolean equals(Object o) {
+            if (this == o)
+                return true;
+            if (o == null || getClass() != o.getClass())
+                return false;
+
+            TestData data = (TestData)o;
+
+            return i == data.i;
+        }
+
+        /** {@inheritDoc} */
+        @Override public int hashCode() {
+            return i;
+        }
+    }
+
+    /** */
+    private enum Gen {
+        /** */
+        INT((i) -> i),
+
+        /** */
+        ARR((i) -> new int[] {i}),
+
+        /** */
+        STR(String::valueOf),
+
+        /** */
+        OBJ(TestData::new),
+
+        /** */
+        ARR_OBJ((i) -> new TestData[] {new TestData(i)});
+
+        /** */
+        private final Function<Integer, Object> gen;
+
+        /** */
+        Gen(Function<Integer, Object> gen) {
+            this.gen = gen;
+        }
+
+        /** */
+        private Object apply(Integer i) {
+            return gen.apply(i);
+        }
+    }
+}
diff --git 
a/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteCacheTestSuite13.java
 
b/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteCacheTestSuite13.java
index dd1729f44b2..0759c5f8f01 100644
--- 
a/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteCacheTestSuite13.java
+++ 
b/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteCacheTestSuite13.java
@@ -42,6 +42,7 @@ import 
org.apache.ignite.internal.processors.cache.distributed.FailBackupOnAtomi
 import 
org.apache.ignite.internal.processors.cache.distributed.rebalancing.RebalanceStatisticsTest;
 import 
org.apache.ignite.internal.processors.cache.transactions.TxAsyncOpsSemaphorePermitsExceededTest;
 import 
org.apache.ignite.internal.processors.cache.transactions.TxRecoveryOnCoordniatorFailTest;
+import 
org.apache.ignite.internal.processors.cache.transform.CacheObjectTransformationCacheApiTest;
 import 
org.apache.ignite.internal.processors.cache.transform.CacheObjectTransformationEvolutionTest;
 import 
org.apache.ignite.internal.processors.cache.transform.CacheObjectTransformationTest;
 import 
org.apache.ignite.internal.processors.cluster.ClusterNameBeforeActivation;
@@ -106,6 +107,8 @@ public class IgniteCacheTestSuite13 {
 
         GridTestUtils.addTestIfNeeded(suite, 
CacheObjectTransformationTest.class, ignoredTests);
         GridTestUtils.addTestIfNeeded(suite, 
CacheObjectTransformationEvolutionTest.class, ignoredTests);
+        GridTestUtils.addTestIfNeeded(suite, 
CacheObjectTransformationCacheApiTest.class, ignoredTests);
+
         GridTestUtils.addTestIfNeeded(suite, 
ContinuousQueryBuffersCleanupTest.class, ignoredTests);
 
         return suite;

Reply via email to