blob: 0f228bda28537dbb082a5de3843eb29c4f74c5c1 [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.
*/
/*
* Note: Lincoln's Gettysburg Address is in the public domain. See LICENSE.
*/
package org.apache.datasketches.memory;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertFalse;
import static org.testng.Assert.assertNotNull;
import static org.testng.Assert.assertNull;
import static org.testng.Assert.assertTrue;
import java.io.File;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.List;
import org.testng.Assert;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
import org.testng.collections.Lists;
public class MemoryTest {
@BeforeClass
public void setReadOnly() {
UtilTest.setGettysburgAddressFileToReadOnly(this);
}
@Test
public void checkDirectRoundTrip() {
int n = 1024; //longs
try (WritableHandle wh = WritableMemory.allocateDirect(n * 8)) {
WritableMemory mem = wh.get();
for (int i = 0; i < n; i++) {
mem.putLong(i * 8, i);
}
for (int i = 0; i < n; i++) {
long v = mem.getLong(i * 8);
assertEquals(v, i);
}
}
}
@Test
public void checkAutoHeapRoundTrip() {
int n = 1024; //longs
WritableMemory wmem = WritableMemory.allocate(n * 8);
for (int i = 0; i < n; i++) {
wmem.putLong(i * 8, i);
}
for (int i = 0; i < n; i++) {
long v = wmem.getLong(i * 8);
assertEquals(v, i);
}
}
@Test
public void checkArrayWrap() {
int n = 1024; //longs
byte[] arr = new byte[n * 8];
WritableMemory wmem = WritableMemory.wrap(arr);
for (int i = 0; i < n; i++) {
wmem.putLong(i * 8, i);
}
for (int i = 0; i < n; i++) {
long v = wmem.getLong(i * 8);
assertEquals(v, i);
}
Memory mem = Memory.wrap(arr, ByteOrder.nativeOrder());
for (int i = 0; i < n; i++) {
long v = mem.getLong(i * 8);
assertEquals(v, i);
}
// check 0 length array wraps
Memory memZeroLengthArrayBoolean = WritableMemory.wrap(new boolean[0]);
Memory memZeroLengthArrayByte = WritableMemory.wrap(new byte[0]);
Memory memZeroLengthArrayChar = WritableMemory.wrap(new char[0]);
Memory memZeroLengthArrayShort = WritableMemory.wrap(new short[0]);
Memory memZeroLengthArrayInt = WritableMemory.wrap(new int[0]);
Memory memZeroLengthArrayLong = WritableMemory.wrap(new long[0]);
Memory memZeroLengthArrayFloat = WritableMemory.wrap(new float[0]);
Memory memZeroLengthArrayDouble = WritableMemory.wrap(new double[0]);
assertEquals(memZeroLengthArrayBoolean.getCapacity(), 0);
assertEquals(memZeroLengthArrayByte.getCapacity(), 0);
assertEquals(memZeroLengthArrayChar.getCapacity(), 0);
assertEquals(memZeroLengthArrayShort.getCapacity(), 0);
assertEquals(memZeroLengthArrayInt.getCapacity(), 0);
assertEquals(memZeroLengthArrayLong.getCapacity(), 0);
assertEquals(memZeroLengthArrayFloat.getCapacity(), 0);
assertEquals(memZeroLengthArrayDouble.getCapacity(), 0);
// check 0 length array wraps
List<Memory> memoryToCheck = Lists.newArrayList();
memoryToCheck.add(WritableMemory.allocate(0));
memoryToCheck.add(WritableMemory.wrap(ByteBuffer.allocate(0)));
memoryToCheck.add(WritableMemory.wrap(new boolean[0]));
memoryToCheck.add(WritableMemory.wrap(new byte[0]));
memoryToCheck.add(WritableMemory.wrap(new char[0]));
memoryToCheck.add(WritableMemory.wrap(new short[0]));
memoryToCheck.add(WritableMemory.wrap(new int[0]));
memoryToCheck.add(WritableMemory.wrap(new long[0]));
memoryToCheck.add(WritableMemory.wrap(new float[0]));
memoryToCheck.add(WritableMemory.wrap(new double[0]));
memoryToCheck.add(Memory.wrap(ByteBuffer.allocate(0)));
memoryToCheck.add(Memory.wrap(new boolean[0]));
memoryToCheck.add(Memory.wrap(new byte[0]));
memoryToCheck.add(Memory.wrap(new char[0]));
memoryToCheck.add(Memory.wrap(new short[0]));
memoryToCheck.add(Memory.wrap(new int[0]));
memoryToCheck.add(Memory.wrap(new long[0]));
memoryToCheck.add(Memory.wrap(new float[0]));
memoryToCheck.add(Memory.wrap(new double[0]));
//Check the Memory lengths
for (Memory memory : memoryToCheck) {
assertEquals(memory.getCapacity(), 0);
}
}
@Test
public void checkByteBufHeap() {
int n = 1024; //longs
byte[] arr = new byte[n * 8];
ByteBuffer bb = ByteBuffer.wrap(arr);
bb.order(ByteOrder.nativeOrder());
WritableMemory wmem = WritableMemory.wrap(bb);
for (int i = 0; i < n; i++) { //write to wmem
wmem.putLong(i * 8, i);
}
for (int i = 0; i < n; i++) { //read from wmem
long v = wmem.getLong(i * 8);
assertEquals(v, i);
}
for (int i = 0; i < n; i++) { //read from BB
long v = bb.getLong(i * 8);
assertEquals(v, i);
}
Memory mem1 = Memory.wrap(arr);
for (int i = 0; i < n; i++) { //read from wrapped arr
long v = mem1.getLong(i * 8);
assertEquals(v, i);
}
//convert to RO
Memory mem = wmem;
for (int i = 0; i < n; i++) {
long v = mem.getLong(i * 8);
assertEquals(v, i);
}
}
@Test
public void checkByteBufDirect() {
int n = 1024; //longs
ByteBuffer bb = ByteBuffer.allocateDirect(n * 8);
bb.order(ByteOrder.nativeOrder());
WritableMemory wmem = WritableMemory.wrap(bb);
for (int i = 0; i < n; i++) { //write to wmem
wmem.putLong(i * 8, i);
}
for (int i = 0; i < n; i++) { //read from wmem
long v = wmem.getLong(i * 8);
assertEquals(v, i);
}
for (int i = 0; i < n; i++) { //read from BB
long v = bb.getLong(i * 8);
assertEquals(v, i);
}
Memory mem1 = Memory.wrap(bb);
for (int i = 0; i < n; i++) { //read from wrapped bb RO
long v = mem1.getLong(i * 8);
assertEquals(v, i);
}
//convert to RO
Memory mem = wmem;
for (int i = 0; i < n; i++) {
long v = mem.getLong(i * 8);
assertEquals(v, i);
}
}
@Test
public void checkByteBufWrongOrder() {
int n = 1024; //longs
ByteBuffer bb = ByteBuffer.allocate(n * 8);
bb.order(ByteOrder.BIG_ENDIAN);
Memory mem = Memory.wrap(bb);
assertFalse(mem.getTypeByteOrder() == BaseState.nativeByteOrder);
assertEquals(mem.getTypeByteOrder(), ByteOrder.BIG_ENDIAN);
}
@Test
public void checkReadOnlyHeapByteBuffer() {
ByteBuffer bb = ByteBuffer.allocate(128);
bb.order(ByteOrder.nativeOrder());
for (int i = 0; i < 128; i++) { bb.put(i, (byte)i); }
bb.position(64);
ByteBuffer slice = bb.slice().asReadOnlyBuffer();
slice.order(ByteOrder.nativeOrder());
Memory mem = Memory.wrap(slice);
for (int i = 0; i < 64; i++) {
assertEquals(mem.getByte(i), 64 + i);
}
mem.toHexString("slice", 0, slice.capacity());
//println(s);
}
@Test
public void checkPutGetArraysHeap() {
int n = 1024; //longs
long[] arr = new long[n];
for (int i = 0; i < n; i++) { arr[i] = i; }
WritableMemory wmem = WritableMemory.allocate(n * 8);
wmem.putLongArray(0, arr, 0, n);
long[] arr2 = new long[n];
wmem.getLongArray(0, arr2, 0, n);
for (int i = 0; i < n; i++) {
assertEquals(arr2[i], i);
}
}
@Test
public void checkRORegions() {
int n = 16;
int n2 = n / 2;
long[] arr = new long[n];
for (int i = 0; i < n; i++) { arr[i] = i; }
Memory mem = Memory.wrap(arr);
Memory reg = mem.region(n2 * 8, n2 * 8); //top half
for (int i = 0; i < n2; i++) {
long v = reg.getLong(i * 8);
long e = i + n2;
assertEquals(v, e);
}
}
@Test
public void checkRORegionsReverseBO() {
int n = 16;
int n2 = n / 2;
long[] arr = new long[n];
for (int i = 0; i < n; i++) { arr[i] = i; }
Memory mem = Memory.wrap(arr);
Memory reg = mem.region(n2 * 8, n2 * 8, BaseState.nonNativeByteOrder); //top half
for (int i = 0; i < n2; i++) {
long v = Long.reverseBytes(reg.getLong(i * 8));
long e = i + n2;
assertEquals(v, e);
}
}
@Test
public void checkWRegions() {
int n = 16;
int n2 = n / 2;
long[] arr = new long[n];
for (int i = 0; i < n; i++) { arr[i] = i; }
WritableMemory wmem = WritableMemory.wrap(arr);
for (int i = 0; i < n; i++) {
assertEquals(wmem.getLong(i * 8), i);
//println("" + wmem.getLong(i * 8));
}
//println("");
WritableMemory reg = wmem.writableRegion(n2 * 8, n2 * 8);
for (int i = 0; i < n2; i++) { reg.putLong(i * 8, i); }
for (int i = 0; i < n; i++) {
assertEquals(wmem.getLong(i * 8), i % 8);
//println("" + wmem.getLong(i * 8));
}
}
@Test
public void checkWRegionsReverseBO() {
int n = 16;
int n2 = n / 2;
long[] arr = new long[n];
for (int i = 0; i < n; i++) { arr[i] = i; }
WritableMemory wmem = WritableMemory.wrap(arr);
for (int i = 0; i < n; i++) {
assertEquals(wmem.getLong(i * 8), i);
//println("" + wmem.getLong(i * 8));
}
//println("");
WritableMemory reg = wmem.writableRegion(n2 * 8, n2 * 8, BaseState.nonNativeByteOrder);
for (int i = 0; i < n2; i++) { reg.putLong(i * 8, i); }
for (int i = 0; i < n; i++) {
long v = wmem.getLong(i * 8);
if (i < n2) {
assertEquals(v, i % 8);
} else {
assertEquals(Long.reverseBytes(v), i % 8);
}
//println("" + wmem.getLong(i * 8));
}
}
@Test(expectedExceptions = AssertionError.class)
public void checkParentUseAfterFree() {
int bytes = 64 * 8;
@SuppressWarnings("resource") //intentionally not using try-with-resouces here
WritableHandle wh = WritableMemory.allocateDirect(bytes);
WritableMemory wmem = wh.get();
wh.close();
//with -ea assert: Memory not valid.
//with -da sometimes segfaults, sometimes passes!
wmem.getLong(0);
}
@Test(expectedExceptions = AssertionError.class)
public void checkRegionUseAfterFree() {
int bytes = 64;
@SuppressWarnings("resource") //intentionally not using try-with-resouces here
WritableHandle wh = WritableMemory.allocateDirect(bytes);
Memory wmem = wh.get();
Memory region = wmem.region(0L, bytes);
wh.close();
//with -ea assert: Memory not valid.
//with -da sometimes segfaults, sometimes passes!
region.getByte(0);
}
@Test
public void checkUnsafeByteBufferView() {
try (WritableDirectHandle wmemDirectHandle = WritableMemory.allocateDirect(2)) {
WritableMemory wmemDirect = wmemDirectHandle.get();
wmemDirect.putByte(0, (byte) 1);
wmemDirect.putByte(1, (byte) 2);
checkUnsafeByteBufferView(wmemDirect);
}
checkUnsafeByteBufferView(Memory.wrap(new byte[] {1, 2}));
try {
@SuppressWarnings("unused")
ByteBuffer unused = Memory.wrap(new int[]{1}).unsafeByteBufferView(0, 1);
Assert.fail();
} catch (UnsupportedOperationException ingore) {
// expected
}
}
private static void checkUnsafeByteBufferView(final Memory mem) {
ByteBuffer emptyByteBuffer = mem.unsafeByteBufferView(0, 0);
Assert.assertEquals(emptyByteBuffer.capacity(), 0);
ByteBuffer bb = mem.unsafeByteBufferView(1, 1);
Assert.assertTrue(bb.isReadOnly());
Assert.assertEquals(bb.capacity(), 1);
Assert.assertEquals(bb.get(), 2);
try {
@SuppressWarnings("unused")
ByteBuffer unused = mem.unsafeByteBufferView(1, 2);
Assert.fail();
} catch (IllegalArgumentException ignore) {
// expected
}
}
@SuppressWarnings("resource")
@Test
public void checkMonitorDirectStats() {
int bytes = 1024;
WritableHandle wh1 = WritableMemory.allocateDirect(bytes);
WritableHandle wh2 = WritableMemory.allocateDirect(bytes);
assertEquals(BaseState.getCurrentDirectMemoryAllocations(), 2L);
assertEquals(BaseState.getCurrentDirectMemoryAllocated(), 2 * bytes);
wh1.close();
assertEquals(BaseState.getCurrentDirectMemoryAllocations(), 1L);
assertEquals(BaseState.getCurrentDirectMemoryAllocated(), bytes);
wh2.close();
wh2.close(); //check that it doesn't go negative.
assertEquals(BaseState.getCurrentDirectMemoryAllocations(), 0L);
assertEquals(BaseState.getCurrentDirectMemoryAllocated(), 0L);
}
@SuppressWarnings("resource")
@Test
public void checkMonitorDirectMapStats() throws Exception {
File file = new File(getClass().getClassLoader().getResource("GettysburgAddress.txt").getFile());
long bytes = file.length();
MapHandle mmh1 = Memory.map(file);
MapHandle mmh2 = Memory.map(file);
assertEquals(BaseState.getCurrentDirectMemoryMapAllocations(), 2L);
assertEquals(BaseState.getCurrentDirectMemoryMapAllocated(), 2 * bytes);
mmh1.close();
assertEquals(BaseState.getCurrentDirectMemoryMapAllocations(), 1L);
assertEquals(BaseState.getCurrentDirectMemoryMapAllocated(), bytes);
mmh2.close();
mmh2.close(); //check that it doesn't go negative.
assertEquals(BaseState.getCurrentDirectMemoryMapAllocations(), 0L);
assertEquals(BaseState.getCurrentDirectMemoryMapAllocated(), 0L);
}
@Test
public void checkNullMemReqSvr() {
WritableMemory wmem = WritableMemory.wrap(new byte[16]);
assertNull(wmem.getMemoryRequestServer());
try (WritableDirectHandle wdh = WritableMemory.allocateDirect(16)) {
WritableMemory wmem2 = wdh.get();
assertNotNull(wmem2.getMemoryRequestServer());
}
println(wmem.toHexString("Test", 0, 16));
}
@Test
public void checkHashCode() {
WritableMemory wmem = WritableMemory.allocate(32 + 7);
int hc = wmem.hashCode();
assertEquals(hc, -1895166923);
}
@Test
public void checkSelfEqualsToAndCompareTo() {
int len = 64;
WritableMemory wmem = WritableMemory.allocate(len);
for (int i = 0; i < len; i++) { wmem.putByte(i, (byte) i); }
assertTrue(wmem.equalTo(0, wmem, 0, len));
assertFalse(wmem.equalTo(0, wmem, len/2, len/2));
assertEquals(wmem.compareTo(0, len, wmem, 0, len), 0);
assertTrue(wmem.compareTo(0, 0, wmem, len/2, len/2) < 0);
}
@Test
public void wrapBigEndianAsLittle() {
ByteBuffer bb = ByteBuffer.allocate(64);
bb.putChar(0, (char)1); //as BE
Memory mem = Memory.wrap(bb, ByteOrder.LITTLE_ENDIAN);
assertEquals(mem.getChar(0), 256);
}
@Test
public void printlnTest() {
println("PRINTING: "+this.getClass().getName());
}
/**
* @param s value to print
*/
static void println(final String s) {
//System.out.println(s);
}
}