| /* |
| * 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; |
| |
| import java.nio.ByteBuffer; |
| import java.util.concurrent.ThreadLocalRandom; |
| import org.apache.ignite.IgniteCheckedException; |
| import org.apache.ignite.plugin.extensions.communication.MessageReader; |
| import org.apache.ignite.plugin.extensions.communication.MessageWriter; |
| import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest; |
| import org.jetbrains.annotations.Nullable; |
| import org.junit.Assert; |
| import org.junit.Test; |
| |
| /** |
| * Simple test for arbitrary CacheObject reading/writing. |
| */ |
| public class IgniteIncompleteCacheObjectSelfTest extends GridCommonAbstractTest { |
| /** |
| * Test case when requested data cut on cache object header. |
| * |
| * @throws Exception If failed. |
| */ |
| @Test |
| public void testIncompleteObject() throws Exception { |
| final byte[] data = new byte[1024]; |
| |
| ThreadLocalRandom.current().nextBytes(data); |
| |
| final ByteBuffer dataBuf = ByteBuffer.allocate(IncompleteCacheObject.HEAD_LEN + data.length); |
| |
| int off = 0; |
| int len = 3; |
| |
| final TestCacheObject obj = new TestCacheObject((byte)1); |
| |
| // Write part of the cache object and cut on header (3 bytes instead of 5) |
| assert CacheObjectAdapter.putValue(obj.cacheObjectType(), dataBuf, off, len, data, 0); |
| |
| off += len; |
| len = IncompleteCacheObject.HEAD_LEN - len + data.length; |
| |
| // Write rest data. |
| assert CacheObjectAdapter.putValue(obj.cacheObjectType(), dataBuf, off, len, data, 0); |
| |
| assert !dataBuf.hasRemaining() : "Not all data were written."; |
| |
| dataBuf.clear(); |
| |
| // Cut on header for reading. |
| dataBuf.limit(3); |
| |
| final IncompleteCacheObject incompleteObj = new IncompleteCacheObject(dataBuf); |
| |
| incompleteObj.readData(dataBuf); |
| |
| assert !incompleteObj.isReady(); |
| |
| assert !dataBuf.hasRemaining() : "Data were read incorrectly."; |
| |
| // Make rest data available. |
| dataBuf.limit(dataBuf.capacity()); |
| |
| incompleteObj.readData(dataBuf); |
| |
| assert incompleteObj.isReady(); |
| |
| // Check that cache object data assembled correctly. |
| assertEquals(obj.cacheObjectType(), incompleteObj.type()); |
| Assert.assertArrayEquals(data, incompleteObj.data()); |
| } |
| |
| /** |
| * |
| */ |
| private static class TestCacheObject implements CacheObject { |
| /** */ |
| private static final long serialVersionUID = 0L; |
| |
| /** */ |
| private final byte type; |
| |
| /** |
| * @param type Cache object type. |
| */ |
| private TestCacheObject(final byte type) { |
| this.type = type; |
| } |
| |
| /** {@inheritDoc} */ |
| @Nullable @Override public <T> T value(final CacheObjectValueContext ctx, final boolean cpy) { |
| return value(ctx, cpy, null); |
| } |
| |
| /** {@inheritDoc} */ |
| @Nullable @Override public <T> T value(final CacheObjectValueContext ctx, final boolean cpy, ClassLoader ldr) { |
| return null; |
| } |
| |
| /** {@inheritDoc} */ |
| @Override public byte[] valueBytes(final CacheObjectValueContext ctx) throws IgniteCheckedException { |
| return new byte[0]; |
| } |
| |
| /** {@inheritDoc} */ |
| @Override public int valueBytesLength(final CacheObjectContext ctx) throws IgniteCheckedException { |
| return 0; |
| } |
| |
| /** {@inheritDoc} */ |
| @Override public boolean putValue(final ByteBuffer buf) throws IgniteCheckedException { |
| return false; |
| } |
| |
| /** {@inheritDoc} */ |
| @Override public int putValue(long addr) throws IgniteCheckedException { |
| throw new UnsupportedOperationException(); |
| } |
| |
| /** {@inheritDoc} */ |
| @Override public boolean putValue(final ByteBuffer buf, final int off, final int len) |
| throws IgniteCheckedException { |
| return false; |
| } |
| |
| /** {@inheritDoc} */ |
| @Override public byte cacheObjectType() { |
| return type; |
| } |
| |
| /** {@inheritDoc} */ |
| @Override public boolean isPlatformType() { |
| return false; |
| } |
| |
| /** {@inheritDoc} */ |
| @Override public CacheObject prepareForCache(final CacheObjectContext ctx) { |
| return null; |
| } |
| |
| /** {@inheritDoc} */ |
| @Override public void finishUnmarshal(final CacheObjectValueContext ctx, final ClassLoader ldr) |
| throws IgniteCheckedException { |
| // No-op |
| } |
| |
| /** {@inheritDoc} */ |
| @Override public void prepareMarshal(final CacheObjectValueContext ctx) throws IgniteCheckedException { |
| // No-op |
| } |
| |
| /** {@inheritDoc} */ |
| @Override public boolean writeTo(final ByteBuffer buf, final MessageWriter writer) { |
| return false; |
| } |
| |
| /** {@inheritDoc} */ |
| @Override public boolean readFrom(final ByteBuffer buf, final MessageReader reader) { |
| return false; |
| } |
| |
| /** {@inheritDoc} */ |
| @Override public short directType() { |
| return 0; |
| } |
| |
| /** {@inheritDoc} */ |
| @Override public byte fieldsCount() { |
| return 0; |
| } |
| |
| /** {@inheritDoc} */ |
| @Override public void onAckReceived() { |
| // No-op |
| } |
| } |
| } |