GEODE-644: add unit test for DataAsAddress
Project: http://git-wip-us.apache.org/repos/asf/incubator-geode/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-geode/commit/56b37571 Tree: http://git-wip-us.apache.org/repos/asf/incubator-geode/tree/56b37571 Diff: http://git-wip-us.apache.org/repos/asf/incubator-geode/diff/56b37571 Branch: refs/heads/feature/GEODE-291 Commit: 56b3757129fb20ab047d8c164fa965eff50099c4 Parents: 7cbb5db Author: Sai Boorlagadda <[email protected]> Authored: Tue Dec 8 15:08:02 2015 -0800 Committer: Darrel Schneider <[email protected]> Committed: Thu Dec 10 11:11:30 2015 -0800 ---------------------------------------------------------------------- .../gemfire/internal/offheap/DataAsAddress.java | 14 +- .../offheap/OffHeapRegionEntryHelper.java | 51 +-- .../offheap/AbstractStoredObjectTestBase.java | 203 ++++++++++ .../offheap/DataAsAddressJUnitTest.java | 368 +++++++++++++++++++ 4 files changed, 593 insertions(+), 43 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/56b37571/gemfire-core/src/main/java/com/gemstone/gemfire/internal/offheap/DataAsAddress.java ---------------------------------------------------------------------- diff --git a/gemfire-core/src/main/java/com/gemstone/gemfire/internal/offheap/DataAsAddress.java b/gemfire-core/src/main/java/com/gemstone/gemfire/internal/offheap/DataAsAddress.java index 5b14389..dff1d8f 100644 --- a/gemfire-core/src/main/java/com/gemstone/gemfire/internal/offheap/DataAsAddress.java +++ b/gemfire-core/src/main/java/com/gemstone/gemfire/internal/offheap/DataAsAddress.java @@ -59,7 +59,13 @@ public class DataAsAddress extends AbstractStoredObject { } public byte[] getDecompressedBytes(RegionEntryContext r) { - return OffHeapRegionEntryHelper.encodedAddressToBytes(this.address, true, r); + byte[] bytes = OffHeapRegionEntryHelper.decodeAddressToBytes(getEncodedAddress(), true, true); + if (isCompressed()) { + long time = r.getCachePerfStats().startDecompression(); + bytes = r.getCompressor().decompress(bytes); + r.getCachePerfStats().endDecompression(time); + } + return bytes; } /** @@ -67,17 +73,17 @@ public class DataAsAddress extends AbstractStoredObject { * Otherwise return the serialize bytes in us in a byte array. */ public byte[] getRawBytes() { - return OffHeapRegionEntryHelper.encodedAddressToRawBytes(this.address); + return OffHeapRegionEntryHelper.decodeAddressToBytes(getEncodedAddress(), true, false); } @Override public byte[] getSerializedValue() { - return OffHeapRegionEntryHelper.encodedAddressToBytes(this.address); + return OffHeapRegionEntryHelper.decodeAddressToBytes(this.address); } @Override public Object getDeserializedValue(Region r, RegionEntry re) { - return OffHeapRegionEntryHelper.encodedAddressToObject(this.address); + return OffHeapRegionEntryHelper.decodeAddressToObject(this.address); } @Override http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/56b37571/gemfire-core/src/main/java/com/gemstone/gemfire/internal/offheap/OffHeapRegionEntryHelper.java ---------------------------------------------------------------------- diff --git a/gemfire-core/src/main/java/com/gemstone/gemfire/internal/offheap/OffHeapRegionEntryHelper.java b/gemfire-core/src/main/java/com/gemstone/gemfire/internal/offheap/OffHeapRegionEntryHelper.java index d1a81f0..1731b01 100644 --- a/gemfire-core/src/main/java/com/gemstone/gemfire/internal/offheap/OffHeapRegionEntryHelper.java +++ b/gemfire-core/src/main/java/com/gemstone/gemfire/internal/offheap/OffHeapRegionEntryHelper.java @@ -87,10 +87,6 @@ public class OffHeapRegionEntryHelper { if (v == Token.NOT_AVAILABLE) return NOT_AVAILABLE_ADDRESS; throw new IllegalStateException("Can not convert " + v + " to an off heap address."); } - - static Object encodedAddressToObject(long ohAddress) { - return encodedAddressToObject(ohAddress, true, true); - } //TODO:Asif:Check if this is a valid equality conditions public static boolean isAddressInvalidOrRemoved(long address) { @@ -280,23 +276,20 @@ public class OffHeapRegionEntryHelper { } return 0L; } - - public static Object encodedAddressToObject(long addr, boolean decompress, boolean deserialize) { - boolean isSerialized = (addr & SERIALIZED_BIT) != 0; - byte[] bytes = encodedAddressToBytes(addr, decompress, false); - if (isSerialized) { - if (deserialize) { - return EntryEventImpl.deserialize(bytes); + + static Object decodeAddressToObject(long ohAddress) { + byte[] bytes = decodeAddressToBytes(ohAddress, true, false); + + boolean isSerialized = (ohAddress & SERIALIZED_BIT) != 0; + if (isSerialized) { + return EntryEventImpl.deserialize(bytes); } else { - return CachedDeserializableFactory.create(bytes); + return bytes; } - } else { - return bytes; - } } - - static byte[] encodedAddressToBytes(long addr) { - byte[] result = encodedAddressToBytes(addr, true, false); + + static byte[] decodeAddressToBytes(long addr) { + byte[] result = decodeAddressToBytes(addr, true, false); boolean isSerialized = (addr & SERIALIZED_BIT) != 0; if (!isSerialized) { result = EntryEventImpl.serialize(result); @@ -304,15 +297,7 @@ public class OffHeapRegionEntryHelper { return result; } - /** - * If the address contains a byte[] return it. - * Otherwise return the serialize bytes in the address in a byte array. - */ - static byte[] encodedAddressToRawBytes(long addr) { - return encodedAddressToBytes(addr, true, false); - } - - private static byte[] encodedAddressToBytes(long addr, boolean decompress, boolean compressedOk) { + static byte[] decodeAddressToBytes(long addr, boolean decompress, boolean compressedOk) { assert (addr & ENCODED_BIT) != 0; boolean isCompressed = (addr & COMPRESSED_BIT) != 0; int size = (int) ((addr & SIZE_MASK) >> SIZE_SHIFT); @@ -344,18 +329,6 @@ public class OffHeapRegionEntryHelper { } return bytes; } - public static byte[] encodedAddressToBytes(long addr, boolean decompress, RegionEntryContext context) { - byte[] bytes = encodedAddressToBytes(addr, decompress, true); - if (decompress) { - boolean isCompressed = (addr & COMPRESSED_BIT) != 0; - if (isCompressed) { - long time = context.getCachePerfStats().startDecompression(); - bytes = context.getCompressor().decompress(bytes); - context.getCachePerfStats().endDecompression(time); - } - } - return bytes; - } /** * The previous value at the address in 're' will be @Released and then the http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/56b37571/gemfire-core/src/test/java/com/gemstone/gemfire/internal/offheap/AbstractStoredObjectTestBase.java ---------------------------------------------------------------------- diff --git a/gemfire-core/src/test/java/com/gemstone/gemfire/internal/offheap/AbstractStoredObjectTestBase.java b/gemfire-core/src/test/java/com/gemstone/gemfire/internal/offheap/AbstractStoredObjectTestBase.java new file mode 100644 index 0000000..a5fac48 --- /dev/null +++ b/gemfire-core/src/test/java/com/gemstone/gemfire/internal/offheap/AbstractStoredObjectTestBase.java @@ -0,0 +1,203 @@ +/* + * 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 com.gemstone.gemfire.internal.offheap; + +import com.gemstone.gemfire.internal.DataSerializableFixedID; +import com.gemstone.gemfire.internal.offheap.StoredObject; +import org.junit.Test; + +import java.io.DataOutput; +import java.io.IOException; + +import static org.junit.Assert.assertArrayEquals; +import static org.junit.Assert.assertEquals; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; + +public abstract class AbstractStoredObjectTestBase { + + /* Returns Value as an Object Eg: Integer or UserDefinedRegionValue */ + protected abstract Object getValue(); + + /* Returns Value as an ByteArray (not serialized) */ + protected abstract byte[] getValueAsByteArray(); + + protected abstract Object convertByteArrayToObject(byte[] valueInByteArray); + + protected abstract Object convertSerializedByteArrayToObject(byte[] valueInSerializedByteArray); + + protected abstract StoredObject createValueAsUnserializedStoredObject(Object value); + + protected abstract StoredObject createValueAsSerializedStoredObject(Object value); + + @Test + public void getValueAsDeserializedHeapObjectShouldReturnDeserializedValueIfValueIsSerialized() { + Object regionEntryValue = getValue(); + StoredObject storedObject = createValueAsSerializedStoredObject(regionEntryValue); + + Integer actualRegionEntryValue = (Integer) storedObject.getValueAsDeserializedHeapObject(); + assertEquals(regionEntryValue, actualRegionEntryValue); + } + + @Test + public void getValueAsDeserializedHeapObjectShouldReturnValueAsIsIfNotSerialized() { + byte[] regionEntryValue = getValueAsByteArray(); + StoredObject storedObject = createValueAsUnserializedStoredObject(regionEntryValue); + + byte[] deserializedValue = (byte[]) storedObject.getValueAsDeserializedHeapObject(); + assertArrayEquals(regionEntryValue, deserializedValue); + } + + @Test + public void getValueAsHeapByteArrayShouldReturnSerializedByteArrayIfValueIsSerialized() { + Object regionEntryValue = getValue(); + StoredObject storedObject = createValueAsSerializedStoredObject(regionEntryValue); + + byte[] valueInSerializedByteArray = (byte[]) storedObject.getValueAsHeapByteArray(); + Object actualRegionEntryValue = convertSerializedByteArrayToObject(valueInSerializedByteArray); + + assertEquals(regionEntryValue, actualRegionEntryValue); + } + + @Test + public void getValueAsHeapByteArrayShouldReturnDeserializedByteArrayIfValueIsNotSerialized() { + Object regionEntryValue = getValue(); + + StoredObject storedObject = createValueAsUnserializedStoredObject(regionEntryValue); + + byte[] valueInByteArray = (byte[]) storedObject.getValueAsHeapByteArray(); + + Object actualRegionEntryValue = convertByteArrayToObject(valueInByteArray); + + assertEquals(regionEntryValue, actualRegionEntryValue); + } + + @Test + public void getStringFormShouldReturnStringFromDeserializedValue() { + Object regionEntryValue = getValue(); + StoredObject storedObject = createValueAsSerializedStoredObject(regionEntryValue); + + String stringForm = storedObject.getStringForm(); + assertEquals(String.valueOf(regionEntryValue), stringForm); + } + + @Test + public void getValueShouldReturnSerializedValue() { + Object regionEntryValue = getValue(); + StoredObject storedObject = createValueAsSerializedStoredObject(regionEntryValue); + + byte[] valueAsSerializedByteArray = (byte[]) storedObject.getValue(); + + Object actualValue = convertSerializedByteArrayToObject(valueAsSerializedByteArray); + + assertEquals(regionEntryValue, actualValue); + } + + @Test(expected = IllegalStateException.class) + public void getValueShouldThrowExceptionIfValueIsNotSerialized() { + Object regionEntryValue = getValue(); + StoredObject storedObject = createValueAsUnserializedStoredObject(regionEntryValue); + + byte[] deserializedValue = (byte[]) storedObject.getValue(); + } + + @Test + public void getDeserializedWritableCopyShouldReturnDeserializedValue() { + byte[] regionEntryValue = getValueAsByteArray(); + StoredObject storedObject = createValueAsSerializedStoredObject(regionEntryValue); + + assertArrayEquals(regionEntryValue, (byte[]) storedObject.getDeserializedWritableCopy(null, null)); + } + + @Test + public void writeValueAsByteArrayWritesToProvidedDataOutput() throws IOException { + byte[] regionEntryValue = getValueAsByteArray(); + StoredObject storedObject = createValueAsSerializedStoredObject(regionEntryValue); + + DataOutput dataOutput = mock(DataOutput.class); + storedObject.writeValueAsByteArray(dataOutput); + + verify(dataOutput, times(1)).write(storedObject.getSerializedValue(), 0 , storedObject.getSerializedValue().length); + } + + @Test + public void sendToShouldWriteSerializedValueToDataOutput() throws IOException { + Object regionEntryValue = getValue(); + StoredObject storedObject = createValueAsSerializedStoredObject(regionEntryValue); + + DataOutput dataOutput = mock(DataOutput.class); + storedObject.sendTo(dataOutput); + + verify(dataOutput, times(1)).write(storedObject.getSerializedValue()); + } + + @Test + public void sendToShouldWriteDeserializedObjectToDataOutput() throws IOException { + byte[] regionEntryValue = getValueAsByteArray(); + StoredObject storedObject = createValueAsUnserializedStoredObject(regionEntryValue); + + DataOutput dataOutput = mock(DataOutput.class); + storedObject.sendTo(dataOutput); + + verify(dataOutput, times(1)).write(regionEntryValue, 0, regionEntryValue.length); + } + + @Test + public void sendAsByteArrayShouldWriteSerializedValueToDataOutput() throws IOException { + Object regionEntryValue = getValue(); + StoredObject storedObject = createValueAsSerializedStoredObject(regionEntryValue); + + DataOutput dataOutput = mock(DataOutput.class); + storedObject.sendAsByteArray(dataOutput); + + verify(dataOutput, times(1)).write(storedObject.getSerializedValue(), 0, storedObject.getSerializedValue().length); + } + + @Test + public void sendAsByteArrayShouldWriteDeserializedObjectToDataOutput() throws IOException { + byte[] regionEntryValue = getValueAsByteArray(); + StoredObject storedObject = createValueAsUnserializedStoredObject(regionEntryValue); + + DataOutput dataOutput = mock(DataOutput.class); + storedObject.sendAsByteArray(dataOutput); + + verify(dataOutput, times(1)).write(regionEntryValue, 0, regionEntryValue.length); + } + + @Test + public void sendAsCachedDeserializableShouldWriteSerializedValueToDataOutputAndSetsHeader() throws IOException { + Object regionEntryValue = getValue(); + StoredObject storedObject = createValueAsSerializedStoredObject(regionEntryValue); + + DataOutput dataOutput = mock(DataOutput.class); + storedObject.sendAsCachedDeserializable(dataOutput); + + verify(dataOutput, times(1)).writeByte((DataSerializableFixedID.VM_CACHED_DESERIALIZABLE)); + verify(dataOutput, times(1)).write(storedObject.getSerializedValue(), 0, storedObject.getSerializedValue().length); + } + + @Test(expected = IllegalStateException.class) + public void sendAsCachedDeserializableShouldThrowExceptionIfValueIsNotSerialized() throws IOException { + Object regionEntryValue = getValue(); + StoredObject storedObject = createValueAsUnserializedStoredObject(regionEntryValue); + + DataOutput dataOutput = mock(DataOutput.class); + storedObject.sendAsCachedDeserializable(dataOutput); + } +} http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/56b37571/gemfire-core/src/test/java/com/gemstone/gemfire/internal/offheap/DataAsAddressJUnitTest.java ---------------------------------------------------------------------- diff --git a/gemfire-core/src/test/java/com/gemstone/gemfire/internal/offheap/DataAsAddressJUnitTest.java b/gemfire-core/src/test/java/com/gemstone/gemfire/internal/offheap/DataAsAddressJUnitTest.java new file mode 100644 index 0000000..8a251fd --- /dev/null +++ b/gemfire-core/src/test/java/com/gemstone/gemfire/internal/offheap/DataAsAddressJUnitTest.java @@ -0,0 +1,368 @@ +/* + * 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 com.gemstone.gemfire.internal.offheap; + +import com.gemstone.gemfire.compression.Compressor; +import com.gemstone.gemfire.internal.cache.BytesAndBitsForCompactor; +import com.gemstone.gemfire.internal.cache.CachePerfStats; +import com.gemstone.gemfire.internal.cache.EntryEventImpl; +import com.gemstone.gemfire.internal.cache.RegionEntryContext; +import com.gemstone.gemfire.internal.offheap.DataAsAddress; + +import com.gemstone.gemfire.internal.offheap.OffHeapRegionEntryHelper; +import com.gemstone.gemfire.test.junit.categories.UnitTest; +import org.junit.Test; +import org.junit.experimental.categories.Category; +import org.mockito.Mock; + +import java.nio.ByteBuffer; + +import static org.junit.Assert.assertArrayEquals; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.mockito.Mockito.*; + +@Category(UnitTest.class) +public class DataAsAddressJUnitTest extends AbstractStoredObjectTestBase { + + @Override + public Object getValue() { + return Integer.valueOf(123456789); + } + + @Override + public byte[] getValueAsByteArray() { + return convertValueToByteArray(getValue()); + } + + private byte[] convertValueToByteArray(Object value) { + return ByteBuffer.allocate(Integer.SIZE / Byte.SIZE).putInt((Integer) value).array(); + } + + @Override + public Object convertByteArrayToObject(byte[] valueInByteArray) { + return ByteBuffer.wrap(valueInByteArray).getInt(); + } + + @Override + public Object convertSerializedByteArrayToObject(byte[] valueInSerializedByteArray) { + return EntryEventImpl.deserialize(valueInSerializedByteArray); + } + + @Override + public DataAsAddress createValueAsUnserializedStoredObject(Object value) { + byte[] valueInByteArray; + if(value instanceof Integer) { + valueInByteArray = convertValueToByteArray(value); + } else { + valueInByteArray = (byte[]) value; + } + //encode a non-serialized entry value to address + long encodedAddress = OffHeapRegionEntryHelper.encodeDataAsAddress(valueInByteArray, false, false); + return new DataAsAddress(encodedAddress); + } + + @Override + public DataAsAddress createValueAsSerializedStoredObject(Object value) { + byte[] valueInSerializedByteArray = EntryEventImpl.serialize(value); + //encode a serialized entry value to address + long encodedAddress = OffHeapRegionEntryHelper.encodeDataAsAddress(valueInSerializedByteArray, true, false); + return new DataAsAddress(encodedAddress); + } + + public DataAsAddress createValueAsCompressedStoredObject(Object value) { + byte[] valueInSerializedByteArray = EntryEventImpl.serialize(value); + //encode a serialized, compressed entry value to address + long encodedAddress = OffHeapRegionEntryHelper.encodeDataAsAddress(valueInSerializedByteArray, true, true); + return new DataAsAddress(encodedAddress); + } + + public DataAsAddress createValueAsUncompressedStoredObject(Object value) { + byte[] valueInSerializedByteArray = EntryEventImpl.serialize(value); + //encode a serialized, uncompressed entry value to address + long encodedAddress = OffHeapRegionEntryHelper.encodeDataAsAddress(valueInSerializedByteArray, true, false); + return new DataAsAddress(encodedAddress); + } + + @Test + public void shouldReturnCorrectEncodingAddress() { + + DataAsAddress address1 = new DataAsAddress(10001L); + assertNotNull(address1); + assertEquals("Encoding address should be:", 10001, address1.getEncodedAddress()); + + DataAsAddress address2 = new DataAsAddress(10002L); + assertNotNull(address2); + assertEquals("Returning always 10001 expected 10002", 10002, address2.getEncodedAddress()); + } + + @Test + public void twoAddressesShouldBeEqualIfEncodingAddressIsSame() { + DataAsAddress address1 = new DataAsAddress(10001L); + DataAsAddress address2 = new DataAsAddress(10001L); + + assertEquals("Two addresses are equal if encoding address is same", true, address1.equals(address2)); + } + + @Test + public void twoAddressesShouldNotBeEqualIfEncodingAddressIsNotSame() { + DataAsAddress address1 = new DataAsAddress(10001L); + DataAsAddress address2 = new DataAsAddress(10002L); + + assertEquals("Two addresses are not equal if encoding address is not same", false, address1.equals(address2)); + } + + @Test + public void twoAddressesAreNotEqualIfTheyAreNotTypeDataAsAddress() { + DataAsAddress address1 = new DataAsAddress(10001L); + Long address2 = new Long(10002L); + + assertEquals("Two addresses are not equal if encoding address is not same", false, address1.equals(address2)); + } + + @Test + public void addressHashCodeShouldBe() { + DataAsAddress address1 = new DataAsAddress(10001L); + assertEquals("", 10001, address1.hashCode()); + } + + @Test + public void getSizeInBytesAlwaysReturnsZero() { + DataAsAddress address1 = new DataAsAddress(10001L); + DataAsAddress address2 = new DataAsAddress(10002L); + + assertEquals("getSizeInBytes", 0, address1.getSizeInBytes()); + assertEquals("getSizeInBytes", 0, address2.getSizeInBytes()); + } + + @Test + public void getValueSizeInBytesAlwaysReturnsZero() { + DataAsAddress address1 = new DataAsAddress(10001L); + DataAsAddress address2 = new DataAsAddress(10002L); + + assertEquals("getSizeInBytes", 0, address1.getValueSizeInBytes()); + assertEquals("getSizeInBytes", 0, address2.getValueSizeInBytes()); + } + + @Test + public void retainShouldAlwaysBeTrue() { + DataAsAddress address1 = new DataAsAddress(10001L); + DataAsAddress address2 = new DataAsAddress(10002L); + + assertEquals("retain", true, address1.retain()); + assertEquals("retain", true, address2.retain()); + } + + @Test + public void dataAsAddressShouldImplementReleaseToAdhereToStoredObject() { + DataAsAddress address = new DataAsAddress(10001L); + address.release(); + } + + @Test + public void isCompressedShouldReturnTrueIfCompressed() { + Object regionEntryValue = getValue(); + + DataAsAddress offheapAddress = createValueAsCompressedStoredObject(regionEntryValue); + + assertEquals("Should return true as it is compressed", true, offheapAddress.isCompressed()); + } + + @Test + public void isCompressedShouldReturnFalseIfNotCompressed() { + Object regionEntryValue = getValue(); + + DataAsAddress offheapAddress = createValueAsUncompressedStoredObject(regionEntryValue); + + assertEquals("Should return false as it is compressed", false, offheapAddress.isCompressed()); + } + + @Test + public void isSerializedShouldReturnTrueIfSeriazlied() { + Object regionEntryValue = getValue(); + + DataAsAddress offheapAddress = createValueAsSerializedStoredObject(regionEntryValue); + + assertEquals("Should return true as it is serialized", true, offheapAddress.isSerialized()); + } + + @Test + public void isSerializedShouldReturnFalseIfNotSeriazlied() { + Object regionEntryValue = getValue(); + + DataAsAddress offheapAddress = createValueAsUnserializedStoredObject(regionEntryValue); + + assertEquals("Should return false as it is serialized", false, offheapAddress.isSerialized()); + } + + @Test + public void getDecompressedBytesShouldReturnDecompressedBytesIfCompressed() { + Object regionEntryValue = getValue(); + byte[] regionEntryValueAsBytes = convertValueToByteArray(regionEntryValue); + + //encode a non-serialized and compressed entry value to address - last argument is to let that it is compressed + long encodedAddress = OffHeapRegionEntryHelper.encodeDataAsAddress(regionEntryValueAsBytes, false, true); + DataAsAddress offheapAddress = new DataAsAddress(encodedAddress); + + RegionEntryContext regionContext = mock(RegionEntryContext.class); + CachePerfStats cacheStats = mock(CachePerfStats.class); + Compressor compressor = mock(Compressor.class); + + long startTime = 10000L; + + //mock required things + when(regionContext.getCompressor()).thenReturn(compressor); + when(compressor.decompress(regionEntryValueAsBytes)).thenReturn(regionEntryValueAsBytes); + when(regionContext.getCachePerfStats()).thenReturn(cacheStats); + when(cacheStats.startDecompression()).thenReturn(startTime); + + //invoke the thing + byte[] bytes = offheapAddress.getDecompressedBytes(regionContext); + + //verify the thing happened + verify(cacheStats, atLeastOnce()).startDecompression(); + verify(compressor, times(1)).decompress(regionEntryValueAsBytes); + verify(cacheStats, atLeastOnce()).endDecompression(startTime); + + assertArrayEquals(regionEntryValueAsBytes, bytes); + } + + @Test + public void getDecompressedBytesShouldNotTryToDecompressIfNotCompressed() { + Object regionEntryValue = getValue(); + + DataAsAddress offheapAddress = createValueAsUncompressedStoredObject(regionEntryValue); + + //mock the thing + RegionEntryContext regionContext = mock(RegionEntryContext.class); + Compressor compressor = mock(Compressor.class); + when(regionContext.getCompressor()).thenReturn(compressor); + + //invoke the thing + byte[] actualValueInBytes = offheapAddress.getDecompressedBytes(regionContext); + + //createValueAsUncompressedStoredObject does uses a serialized value - so convert it to object + Object actualRegionValue = convertSerializedByteArrayToObject(actualValueInBytes); + + //verify the thing happened + verify(regionContext, never()).getCompressor(); + assertEquals(regionEntryValue, actualRegionValue); + } + + @Test + public void getRawBytesShouldReturnAByteArray() { + byte[] regionEntryValueAsBytes = getValueAsByteArray(); + + DataAsAddress offheapAddress = createValueAsUnserializedStoredObject(regionEntryValueAsBytes); + byte[] actual = offheapAddress.getRawBytes(); + + assertArrayEquals(regionEntryValueAsBytes, actual); + } + + @Test + public void getSerializedValueShouldReturnASerializedByteArray() { + Object regionEntryValue = getValue(); + + DataAsAddress offheapAddress = createValueAsSerializedStoredObject(regionEntryValue); + + byte[] actualSerializedValue = offheapAddress.getSerializedValue(); + + Object actualRegionEntryValue = convertSerializedByteArrayToObject(actualSerializedValue); + + assertEquals(regionEntryValue, actualRegionEntryValue); + } + + @Test + public void getDeserializedObjectShouldReturnADeserializedObject() { + Object regionEntryValue = getValue(); + + DataAsAddress offheapAddress = createValueAsSerializedStoredObject(regionEntryValue); + + Integer actualRegionEntryValue = (Integer) offheapAddress.getDeserializedValue(null, null); + + assertEquals(regionEntryValue, actualRegionEntryValue); + } + + @Test + public void getDeserializedObjectShouldReturnAByteArrayAsIsIfNotSerialized() { + byte[] regionEntryValueAsBytes = getValueAsByteArray(); + + DataAsAddress offheapAddress = createValueAsUnserializedStoredObject(regionEntryValueAsBytes); + + byte[] deserializeValue = (byte[]) offheapAddress.getDeserializedValue(null, null); + + assertArrayEquals(regionEntryValueAsBytes, deserializeValue); + } + + @Test + public void fillSerializedValueShouldFillWrapperWithSerializedValueIfValueIsSerialized() { + Object regionEntryValue = getValue(); + byte[] serializedRegionEntryValue = EntryEventImpl.serialize(regionEntryValue); + + //encode a serialized entry value to address + long encodedAddress = OffHeapRegionEntryHelper.encodeDataAsAddress(serializedRegionEntryValue, true, false); + + DataAsAddress offheapAddress = new DataAsAddress(encodedAddress); + + //mock the things + BytesAndBitsForCompactor wrapper = mock(BytesAndBitsForCompactor.class); + + byte userBits = 1; + offheapAddress.fillSerializedValue(wrapper, userBits); + + verify(wrapper, times(1)).setData(serializedRegionEntryValue, userBits, serializedRegionEntryValue.length, true); + } + + @Test + public void fillSerializedValueShouldFillWrapperWithDeserializedValueIfValueIsNotSerialized() { + Object regionEntryValue = getValue(); + byte[] regionEntryValueAsBytes = convertValueToByteArray(regionEntryValue); + + //encode a un serialized entry value to address + long encodedAddress = OffHeapRegionEntryHelper.encodeDataAsAddress(regionEntryValueAsBytes, false, false); + + DataAsAddress offheapAddress = new DataAsAddress(encodedAddress); + + //mock the things + BytesAndBitsForCompactor wrapper = mock(BytesAndBitsForCompactor.class); + + byte userBits = 1; + offheapAddress.fillSerializedValue(wrapper, userBits); + + verify(wrapper, times(1)).setData(regionEntryValueAsBytes, userBits, regionEntryValueAsBytes.length, true); + } + + @Test + public void getStringFormShouldCatchExceptionAndReturnErrorMessageAsString() { + Object regionEntryValueAsBytes = getValue(); + + byte[] serializedValue = EntryEventImpl.serialize(regionEntryValueAsBytes); + + //store -127 (DSCODE.ILLEGAL) - in order the deserialize to throw exception + serializedValue[0] = -127; + + //encode a un serialized entry value to address + long encodedAddress = OffHeapRegionEntryHelper.encodeDataAsAddress(serializedValue, true, false); + + DataAsAddress offheapAddress = new DataAsAddress(encodedAddress); + + String errorMessage = offheapAddress.getStringForm(); + + assertEquals(true, errorMessage.contains("Could not convert object to string because ")); + } +}
