blob: 8a9632f8bfdb1282c0f5d1986c48b5a22a2262ea [file] [log] [blame]
/*
* 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 "));
}
}