| /* |
| * 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.geode.internal.offheap; |
| |
| import static org.junit.Assert.assertArrayEquals; |
| import static org.junit.Assert.assertEquals; |
| import static org.junit.Assert.assertNotNull; |
| import static org.mockito.Mockito.atLeastOnce; |
| import static org.mockito.Mockito.mock; |
| import static org.mockito.Mockito.never; |
| import static org.mockito.Mockito.times; |
| import static org.mockito.Mockito.verify; |
| import static org.mockito.Mockito.when; |
| |
| import java.nio.ByteBuffer; |
| |
| import org.junit.Test; |
| |
| import org.apache.geode.compression.Compressor; |
| import org.apache.geode.internal.cache.BytesAndBitsForCompactor; |
| import org.apache.geode.internal.cache.CachePerfStats; |
| import org.apache.geode.internal.cache.EntryEventImpl; |
| import org.apache.geode.internal.cache.RegionEntryContext; |
| import org.apache.geode.internal.serialization.DSCODE; |
| |
| public class TinyStoredObjectJUnitTest 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 TinyStoredObject 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 TinyStoredObject(encodedAddress); |
| } |
| |
| @Override |
| public TinyStoredObject createValueAsSerializedStoredObject(Object value) { |
| byte[] valueInSerializedByteArray = EntryEventImpl.serialize(value); |
| // encode a serialized entry value to address |
| long encodedAddress = |
| OffHeapRegionEntryHelper.encodeDataAsAddress(valueInSerializedByteArray, true, false); |
| return new TinyStoredObject(encodedAddress); |
| } |
| |
| public TinyStoredObject 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 TinyStoredObject(encodedAddress); |
| } |
| |
| public TinyStoredObject 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 TinyStoredObject(encodedAddress); |
| } |
| |
| @Test |
| public void shouldReturnCorrectEncodingAddress() { |
| |
| TinyStoredObject address1 = new TinyStoredObject(10001L); |
| assertNotNull(address1); |
| assertEquals("Encoding address should be:", 10001, address1.getAddress()); |
| |
| TinyStoredObject address2 = new TinyStoredObject(10002L); |
| assertNotNull(address2); |
| assertEquals("Returning always 10001 expected 10002", 10002, address2.getAddress()); |
| } |
| |
| @Test |
| public void twoAddressesShouldBeEqualIfEncodingAddressIsSame() { |
| TinyStoredObject address1 = new TinyStoredObject(10001L); |
| TinyStoredObject address2 = new TinyStoredObject(10001L); |
| |
| assertEquals("Two addresses are equal if encoding address is same", true, |
| address1.equals(address2)); |
| } |
| |
| @Test |
| public void twoAddressesShouldNotBeEqualIfEncodingAddressIsNotSame() { |
| TinyStoredObject address1 = new TinyStoredObject(10001L); |
| TinyStoredObject address2 = new TinyStoredObject(10002L); |
| |
| assertEquals("Two addresses are not equal if encoding address is not same", false, |
| address1.equals(address2)); |
| } |
| |
| @Test |
| public void twoAddressesAreNotEqualIfTheyAreNotTypeDataAsAddress() { |
| TinyStoredObject address1 = new TinyStoredObject(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() { |
| TinyStoredObject address1 = new TinyStoredObject(10001L); |
| assertEquals("", 10001, address1.hashCode()); |
| } |
| |
| @Test |
| public void getSizeInBytesAlwaysReturnsZero() { |
| TinyStoredObject address1 = new TinyStoredObject(10001L); |
| TinyStoredObject address2 = new TinyStoredObject(10002L); |
| |
| assertEquals("getSizeInBytes", 0, address1.getSizeInBytes()); |
| assertEquals("getSizeInBytes", 0, address2.getSizeInBytes()); |
| } |
| |
| @Test |
| public void getValueSizeInBytesAlwaysReturnsZero() { |
| TinyStoredObject address1 = new TinyStoredObject(10001L); |
| TinyStoredObject address2 = new TinyStoredObject(10002L); |
| |
| assertEquals("getSizeInBytes", 0, address1.getValueSizeInBytes()); |
| assertEquals("getSizeInBytes", 0, address2.getValueSizeInBytes()); |
| } |
| |
| @Test |
| public void isCompressedShouldReturnTrueIfCompressed() { |
| Object regionEntryValue = getValue(); |
| |
| TinyStoredObject offheapAddress = createValueAsCompressedStoredObject(regionEntryValue); |
| |
| assertEquals("Should return true as it is compressed", true, offheapAddress.isCompressed()); |
| } |
| |
| @Test |
| public void isCompressedShouldReturnFalseIfNotCompressed() { |
| Object regionEntryValue = getValue(); |
| |
| TinyStoredObject offheapAddress = createValueAsUncompressedStoredObject(regionEntryValue); |
| |
| assertEquals("Should return false as it is compressed", false, offheapAddress.isCompressed()); |
| } |
| |
| @Test |
| public void isSerializedShouldReturnTrueIfSeriazlied() { |
| Object regionEntryValue = getValue(); |
| |
| TinyStoredObject offheapAddress = createValueAsSerializedStoredObject(regionEntryValue); |
| |
| assertEquals("Should return true as it is serialized", true, offheapAddress.isSerialized()); |
| } |
| |
| @Test |
| public void isSerializedShouldReturnFalseIfNotSeriazlied() { |
| Object regionEntryValue = getValue(); |
| |
| TinyStoredObject 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); |
| TinyStoredObject offheapAddress = new TinyStoredObject(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(); |
| |
| TinyStoredObject 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(); |
| |
| TinyStoredObject offheapAddress = |
| createValueAsUnserializedStoredObject(regionEntryValueAsBytes); |
| byte[] actual = offheapAddress.getRawBytes(); |
| |
| assertArrayEquals(regionEntryValueAsBytes, actual); |
| } |
| |
| @Test |
| public void getSerializedValueShouldReturnASerializedByteArray() { |
| Object regionEntryValue = getValue(); |
| |
| TinyStoredObject offheapAddress = createValueAsSerializedStoredObject(regionEntryValue); |
| |
| byte[] actualSerializedValue = offheapAddress.getSerializedValue(); |
| |
| Object actualRegionEntryValue = convertSerializedByteArrayToObject(actualSerializedValue); |
| |
| assertEquals(regionEntryValue, actualRegionEntryValue); |
| } |
| |
| @Test |
| public void getDeserializedObjectShouldReturnADeserializedObject() { |
| Object regionEntryValue = getValue(); |
| |
| TinyStoredObject offheapAddress = createValueAsSerializedStoredObject(regionEntryValue); |
| |
| Integer actualRegionEntryValue = (Integer) offheapAddress.getDeserializedValue(null, null); |
| |
| assertEquals(regionEntryValue, actualRegionEntryValue); |
| } |
| |
| @Test |
| public void getDeserializedObjectShouldReturnAByteArrayAsIsIfNotSerialized() { |
| byte[] regionEntryValueAsBytes = getValueAsByteArray(); |
| |
| TinyStoredObject 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); |
| |
| TinyStoredObject offheapAddress = new TinyStoredObject(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); |
| |
| TinyStoredObject offheapAddress = new TinyStoredObject(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] = DSCODE.ILLEGAL.toByte(); |
| |
| // encode a un serialized entry value to address |
| long encodedAddress = |
| OffHeapRegionEntryHelper.encodeDataAsAddress(serializedValue, true, false); |
| |
| TinyStoredObject offheapAddress = new TinyStoredObject(encodedAddress); |
| |
| String errorMessage = offheapAddress.getStringForm(); |
| |
| assertEquals(true, errorMessage.contains("Could not convert object to string because ")); |
| } |
| } |