[ https://issues.apache.org/jira/browse/GEODE-651?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=15059178#comment-15059178 ]
ASF GitHub Bot commented on GEODE-651: -------------------------------------- Github user dschneider-pivotal commented on a diff in the pull request: https://github.com/apache/incubator-geode/pull/60#discussion_r47720094 --- Diff: gemfire-core/src/test/java/com/gemstone/gemfire/internal/offheap/GemFireChunkJUnitTest.java --- @@ -0,0 +1,945 @@ +/* + * 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 static org.assertj.core.api.Assertions.assertThat; +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.doNothing; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import java.io.IOException; +import java.nio.ByteBuffer; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.junit.experimental.categories.Category; + +import com.gemstone.gemfire.LogWriter; +import com.gemstone.gemfire.compression.Compressor; +import com.gemstone.gemfire.internal.DSCODE; +import com.gemstone.gemfire.internal.HeapDataOutputStream; +import com.gemstone.gemfire.internal.Version; +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.MemoryBlock.State; +import com.gemstone.gemfire.test.junit.categories.UnitTest; + +@Category(UnitTest.class) +public class GemFireChunkJUnitTest extends AbstractStoredObjectTestBase { + + private MemoryAllocator ma; + + static { + ClassLoader.getSystemClassLoader().setDefaultAssertionStatus(true); + } + + @Before + public void setUp() { + OutOfOffHeapMemoryListener ooohml = mock(OutOfOffHeapMemoryListener.class); + OffHeapMemoryStats stats = mock(OffHeapMemoryStats.class); + LogWriter lw = mock(LogWriter.class); + + ma = SimpleMemoryAllocatorImpl.create(ooohml, stats, lw, 3, OffHeapStorage.MIN_SLAB_SIZE * 3, OffHeapStorage.MIN_SLAB_SIZE); + } + + @After + public void tearDown() { + SimpleMemoryAllocatorImpl.freeOffHeapMemory(); + } + + @Override + public Object getValue() { + return Long.valueOf(Long.MAX_VALUE); + } + + @Override + public byte[] getValueAsByteArray() { + return convertValueToByteArray(getValue()); + } + + private byte[] convertValueToByteArray(Object value) { + return ByteBuffer.allocate(Long.SIZE / Byte.SIZE).putLong((Long) value).array(); + } + + @Override + public Object convertByteArrayToObject(byte[] valueInByteArray) { + return ByteBuffer.wrap(valueInByteArray).getLong(); + } + + @Override + public Object convertSerializedByteArrayToObject(byte[] valueInSerializedByteArray) { + return EntryEventImpl.deserialize(valueInSerializedByteArray); + } + + @Override + public GemFireChunk createValueAsUnserializedStoredObject(Object value) { + byte[] valueInByteArray; + if (value instanceof Long) { + valueInByteArray = convertValueToByteArray(value); + } else { + valueInByteArray = (byte[]) value; + } + + boolean isSerialized = false; + boolean isCompressed = false; + + return createChunk(valueInByteArray, isSerialized, isCompressed); + } + + @Override + public GemFireChunk createValueAsSerializedStoredObject(Object value) { + byte[] valueInSerializedByteArray = EntryEventImpl.serialize(value); + + boolean isSerialized = true; + boolean isCompressed = false; + + return createChunk(valueInSerializedByteArray, isSerialized, isCompressed); + } + + private GemFireChunk createChunk(byte[] v, boolean isSerialized, boolean isCompressed) { + GemFireChunk chunk = (GemFireChunk) ma.allocateAndInitialize(v, isSerialized, isCompressed, GemFireChunk.TYPE); + chunk.setSerializedValue(v); + chunk.setCompressed(isCompressed); + chunk.setSerialized(isSerialized); + + return chunk; + } + + @Test + public void chunkCanBeCreatedFromAnotherChunk() { + GemFireChunk chunk = createValueAsUnserializedStoredObject(getValue()); + + GemFireChunk newChunk = new GemFireChunk(chunk); + + assertNotNull(newChunk); + assertThat(newChunk.getMemoryAddress()).isEqualTo(chunk.getMemoryAddress()); + + chunk.release(); + } + + @Test + public void chunkCanBeCreatedWithOnlyMemoryAddress() { + GemFireChunk chunk = createValueAsUnserializedStoredObject(getValue()); + + GemFireChunk newChunk = new GemFireChunk(chunk.getMemoryAddress()); + + assertNotNull(newChunk); + assertThat(newChunk.getMemoryAddress()).isEqualTo(chunk.getMemoryAddress()); + + chunk.release(); + } + + @Test + public void chunkSliceCanBeCreatedFromAnotherChunk() { + GemFireChunk chunk = createValueAsUnserializedStoredObject(getValue()); + + int position = 1; + int end = 2; + + GemFireChunk newChunk = (GemFireChunk) chunk.slice(position, end); + + assertNotNull(newChunk); + assertThat(newChunk.getClass()).isEqualTo(GemFireChunkSlice.class); + assertThat(newChunk.getMemoryAddress()).isEqualTo(chunk.getMemoryAddress()); + + chunk.release(); + } + + @Test + public void fillSerializedValueShouldFillWrapperWithSerializedValueIfValueIsSerialized() { + GemFireChunk chunk = createValueAsSerializedStoredObject(getValue()); + + // mock the things + BytesAndBitsForCompactor wrapper = mock(BytesAndBitsForCompactor.class); + + byte userBits = 0; + byte serializedUserBits = 1; + chunk.fillSerializedValue(wrapper, userBits); + + verify(wrapper, times(1)).setChunkData(chunk, serializedUserBits); + + chunk.release(); + } + + @Test + public void fillSerializedValueShouldFillWrapperWithDeserializedValueIfValueIsNotSerialized() { + GemFireChunk chunk = createValueAsUnserializedStoredObject(getValue()); + + // mock the things + BytesAndBitsForCompactor wrapper = mock(BytesAndBitsForCompactor.class); + + byte userBits = 1; + chunk.fillSerializedValue(wrapper, userBits); + + verify(wrapper, times(1)).setChunkData(chunk, userBits); + + chunk.release(); + } + + @Test + public void getShortClassNameShouldReturnShortClassName() { + GemFireChunk chunk = createValueAsUnserializedStoredObject(getValue()); + assertThat(chunk.getShortClassName()).isEqualTo("GemFireChunk"); + + chunk.release(); + } + + @Test + public void chunksAreEqualsOnlyByAddress() { + GemFireChunk chunk = createValueAsSerializedStoredObject(getValue()); + + GemFireChunk newChunk = new GemFireChunk(chunk.getMemoryAddress()); + assertThat(chunk.equals(newChunk)).isTrue(); + + GemFireChunk chunkWithSameValue = createValueAsUnserializedStoredObject(getValue()); + assertThat(chunk.equals(chunkWithSameValue)).isFalse(); + + Object someObject = getValue(); + assertThat(chunk.equals(someObject)).isFalse(); + + chunk.release(); + chunkWithSameValue.release(); + } + + @Test + public void chunksShouldBeComparedBySize() { + GemFireChunk chunk1 = createValueAsSerializedStoredObject(getValue()); + + GemFireChunk chunk2 = chunk1; + assertThat(chunk1.compareTo(chunk2)).isEqualTo(0); + + GemFireChunk chunkWithSameValue = createValueAsSerializedStoredObject(getValue()); + assertThat(chunk1.compareTo(chunkWithSameValue)).isEqualTo(Long.signum(chunk1.getMemoryAddress() - chunkWithSameValue.getMemoryAddress())); + + GemFireChunk chunk3 = createValueAsSerializedStoredObject(Long.MAX_VALUE); + GemFireChunk chunk4 = createValueAsSerializedStoredObject(Long.MAX_VALUE); + + int newSizeForChunk3 = 2; + int newSizeForChunk4 = 3; + + assertThat(chunk3.compareTo(chunk4)).isEqualTo(Integer.signum(newSizeForChunk3 - newSizeForChunk4)); + + chunk1.release(); + chunk4.release(); + } + + @Test + public void setSerializedShouldSetTheSerializedBit() { + Object regionEntryValue = getValue(); + byte[] regionEntryValueAsBytes = convertValueToByteArray(regionEntryValue); + + boolean isSerialized = false; + boolean isCompressed = false; + + GemFireChunk chunk = (GemFireChunk) ma.allocateAndInitialize(regionEntryValueAsBytes, isSerialized, isCompressed, GemFireChunk.TYPE); + chunk.setSerializedValue(regionEntryValueAsBytes); + + int headerBeforeSerializedBitSet = UnsafeMemoryChunk.readAbsoluteIntVolatile(chunk.getMemoryAddress() + 4/* REF_COUNT_OFFSET */); + + assertThat(chunk.isSerialized()).isFalse(); + + chunk.setSerialized(true); // set to true + + assertThat(chunk.isSerialized()).isTrue(); + + int headerAfterSerializedBitSet = UnsafeMemoryChunk.readAbsoluteIntVolatile(chunk.getMemoryAddress() + 4/* REF_COUNT_OFFSET */); + + assertThat(headerAfterSerializedBitSet).isEqualTo(headerBeforeSerializedBitSet | 0x80000000/* IS_SERIALIZED_BIT */); + + chunk.release(); + } + + @Test(expected = IllegalStateException.class) + public void setSerialziedShouldThrowExceptionIfChunkIsAlreadyReleased() { + GemFireChunk chunk = createValueAsUnserializedStoredObject(getValue()); + chunk.release(); + chunk.setSerialized(true); + + chunk.release(); + } + + @Test + public void setCompressedShouldSetTheCompressedBit() { + Object regionEntryValue = getValue(); + byte[] regionEntryValueAsBytes = convertValueToByteArray(regionEntryValue); + + boolean isSerialized = false; + boolean isCompressed = false; + + GemFireChunk chunk = (GemFireChunk) ma.allocateAndInitialize(regionEntryValueAsBytes, isSerialized, isCompressed, GemFireChunk.TYPE); + chunk.setSerializedValue(regionEntryValueAsBytes); + + int headerBeforeCompressedBitSet = UnsafeMemoryChunk.readAbsoluteIntVolatile(chunk.getMemoryAddress() + 4/* REF_COUNT_OFFSET */); + + assertThat(chunk.isCompressed()).isFalse(); + + chunk.setCompressed(true); // set to true + + assertThat(chunk.isCompressed()).isTrue(); + + int headerAfterCompressedBitSet = UnsafeMemoryChunk.readAbsoluteIntVolatile(chunk.getMemoryAddress() + 4/* REF_COUNT_OFFSET */); + + assertThat(headerAfterCompressedBitSet).isEqualTo(headerBeforeCompressedBitSet | 0x40000000/* IS_SERIALIZED_BIT */); + + chunk.release(); + } + + @Test(expected = IllegalStateException.class) + public void setCompressedShouldThrowExceptionIfChunkIsAlreadyReleased() { + GemFireChunk chunk = createValueAsUnserializedStoredObject(getValue()); + chunk.release(); + chunk.setCompressed(true); + + chunk.release(); + } + + @Test + public void setDataSizeShouldSetTheDataSizeBits() { + GemFireChunk chunk = createValueAsUnserializedStoredObject(getValue()); + + int beforeSize = chunk.getDataSize(); + + chunk.setDataSize(2); + + int afterSize = chunk.getDataSize(); + + assertThat(afterSize).isEqualTo(2); + assertThat(afterSize).isNotEqualTo(beforeSize); + + chunk.release(); + } + + @Test(expected = IllegalStateException.class) + public void setDataSizeShouldThrowExceptionIfChunkIsAlreadyReleased() { + GemFireChunk chunk = createValueAsUnserializedStoredObject(getValue()); + chunk.release(); + chunk.setDataSize(1); + + chunk.release(); + } + + @Test(expected = IllegalStateException.class) + public void initializeUseCountShouldThrowIllegalStateExceptionIfChunkIsAlreadyRetained() { + GemFireChunk chunk = createValueAsUnserializedStoredObject(getValue()); + chunk.retain(); + chunk.initializeUseCount(); + + chunk.release(); + } + + @Test(expected = IllegalStateException.class) + public void initializeUseCountShouldThrowIllegalStateExceptionIfChunkIsAlreadyReleased() { + GemFireChunk chunk = createValueAsUnserializedStoredObject(getValue()); + chunk.release(); + chunk.initializeUseCount(); + + chunk.release(); + } + + @Test + public void isSerializedPdxInstanceShouldReturnTrueIfItsPDXInstance() { + GemFireChunk chunk = createValueAsSerializedStoredObject(getValue()); + + byte[] serailizedValue = chunk.getSerializedValue(); + serailizedValue[0] = DSCODE.PDX; + chunk.setSerializedValue(serailizedValue); + + assertThat(chunk.isSerializedPdxInstance()).isTrue(); + + serailizedValue = chunk.getSerializedValue(); + serailizedValue[0] = DSCODE.PDX_ENUM; + chunk.setSerializedValue(serailizedValue); + + assertThat(chunk.isSerializedPdxInstance()).isTrue(); + + serailizedValue = chunk.getSerializedValue(); + serailizedValue[0] = DSCODE.PDX_INLINE_ENUM; + chunk.setSerializedValue(serailizedValue); + + assertThat(chunk.isSerializedPdxInstance()).isTrue(); + + chunk.release(); + } + + @Test + public void isSerializedPdxInstanceShouldReturnFalseIfItsNotPDXInstance() { + GemFireChunk chunk = createValueAsSerializedStoredObject(getValue()); + assertThat(chunk.isSerializedPdxInstance()).isFalse(); + + chunk.release(); + } + + @Test + public void checkDataEqualsByChunk() { + GemFireChunk chunk1 = createValueAsSerializedStoredObject(getValue()); + GemFireChunk sameAsChunk1 = chunk1; + + assertThat(chunk1.checkDataEquals(sameAsChunk1)).isTrue(); + + GemFireChunk unserializedChunk = createValueAsUnserializedStoredObject(getValue()); + assertThat(chunk1.checkDataEquals(unserializedChunk)).isFalse(); + + GemFireChunk chunkDifferBySize = createValueAsSerializedStoredObject(getValue()); + chunkDifferBySize.setSize(0); + assertThat(chunk1.checkDataEquals(chunkDifferBySize)).isFalse(); + + GemFireChunk chunkDifferByValue = createValueAsSerializedStoredObject(Long.MAX_VALUE - 1); + assertThat(chunk1.checkDataEquals(chunkDifferByValue)).isFalse(); + + GemFireChunk newChunk1 = createValueAsSerializedStoredObject(getValue()); + assertThat(chunk1.checkDataEquals(newChunk1)).isTrue(); + + chunk1.release(); + unserializedChunk.release(); + chunkDifferBySize.release(); + chunkDifferByValue.release(); + newChunk1.release(); + } + + @Test + public void checkDataEqualsBySerializedValue() { + GemFireChunk chunk = createValueAsSerializedStoredObject(getValue()); + assertThat(chunk.checkDataEquals(new byte[1])).isFalse(); + + GemFireChunk chunkDifferByValue = createValueAsSerializedStoredObject(Long.MAX_VALUE - 1); + assertThat(chunk.checkDataEquals(chunkDifferByValue.getSerializedValue())).isFalse(); + + GemFireChunk newChunk = createValueAsSerializedStoredObject(getValue()); + assertThat(chunk.checkDataEquals(newChunk.getSerializedValue())).isTrue(); + + chunk.release(); + chunkDifferByValue.release(); + newChunk.release(); + } + + @Test + public void getDecompressedBytesShouldReturnDecompressedBytesIfCompressed() { + Object regionEntryValue = getValue(); + byte[] regionEntryValueAsBytes = convertValueToByteArray(regionEntryValue); + + boolean isSerialized = true; + boolean isCompressed = true; + + GemFireChunk chunk = (GemFireChunk) ma.allocateAndInitialize(regionEntryValueAsBytes, isSerialized, isCompressed, GemFireChunk.TYPE); + chunk.setSerializedValue(regionEntryValueAsBytes); --- End diff -- remove the calls to setSerializedValue, setSerialized, and setCompressed since allocateAndInitialize call them > Chunk classes need unit tests > ----------------------------- > > Key: GEODE-651 > URL: https://issues.apache.org/jira/browse/GEODE-651 > Project: Geode > Issue Type: Sub-task > Components: offheap > Reporter: Sai Boorlagadda > Assignee: Sai Boorlagadda > > Chunk and its subclasses (GemFireChunk, ChunkWithHeapForm, and > GemFireChunkSlice) need unit tests. > GemFireChunkFactory needs a unit test. -- This message was sent by Atlassian JIRA (v6.3.4#6332)