You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@datasketches.apache.org by le...@apache.org on 2022/06/20 00:01:17 UTC
[datasketches-memory] 02/02: Moved tests from module -java8-tests to module -java8
This is an automated email from the ASF dual-hosted git repository.
leerho pushed a commit to branch move-java8test-to-java8
in repository https://gitbox.apache.org/repos/asf/datasketches-memory.git
commit cc0040e61208b801232bf722ad970413c9efdfc4
Author: Lee Rhodes <le...@users.noreply.github.com>
AuthorDate: Sun Jun 19 16:52:25 2022 -0700
Moved tests from module -java8-tests to module -java8
---
.../WritableDirectCopyTest.java | 253 +++++
.../WritableMemoryTest.java | 199 ++++
.../XxHash64LoopingTest.java | 1082 ++++++++++++++++++++
datasketches-memory-java8-tests/XxHash64Test.java | 183 ++++
.../ZeroCapacityTest.java | 68 ++
.../memory/test/AllocateDirectMapMemoryTest.java | 170 +++
.../memory/internal/AllocateDirectMemoryTest.java | 7 +-
.../AllocateDirectWritableMapMemoryTest.java | 253 +++++
.../memory/internal/BaseBufferTest.java | 89 ++
.../memory/internal/BaseStateTest.java | 142 +++
.../datasketches/memory/internal/Buffer2Test.java | 462 +++++++++
.../memory/internal/BufferBoundaryCheckTest.java | 237 +++++
.../memory/internal/BufferInvariantsTest.java | 341 ++++++
.../memory/internal/BufferReadWriteSafetyTest.java | 175 ++++
.../datasketches/memory/internal/BufferTest.java | 326 ++++++
.../memory/internal/CommonBufferTest.java | 448 ++++++++
.../memory/internal/CommonMemoryTest.java | 416 ++++++++
.../memory/internal/CopyMemoryOverlapTest.java | 183 ++++
.../memory/internal/CopyMemoryTest.java | 184 ++++
.../memory/internal/DruidIssue11544Test.java | 110 ++
.../internal/ExampleMemoryRequestServerTest.java | 177 ++++
.../memory/internal/IgnoredArrayOverflowTest.java | 104 ++
.../memory/internal/IsValidUtf8TestUtil.java | 64 ++
.../datasketches/memory/internal/LeafImplTest.java | 276 +++++
.../memory/internal/MemoryBoundaryCheckTest.java | 205 ++++
.../memory/internal/MemoryCleanerTest.java | 62 ++
.../memory/internal/MemoryCloseExceptionTest.java | 39 +
.../memory/internal/MemoryReadWriteSafetyTest.java | 227 ++++
.../datasketches/memory/internal/MemoryTest.java | 479 +++++++++
.../memory/internal/MemoryWriteToTest.java | 96 ++
.../memory/internal/MurmurHash3v2Test.java | 401 ++++++++
.../internal/NativeWritableBufferImplTest.java | 600 +++++++++++
.../internal/NativeWritableMemoryImplTest.java | 723 +++++++++++++
.../datasketches/memory/internal/NioBitsTest.java | 78 ++
.../internal/NonNativeWritableBufferImplTest.java | 260 +++++
.../internal/NonNativeWritableMemoryImplTest.java | 219 ++++
.../memory/internal/SpecificLeafTest.java | 194 ++++
.../memory/internal/UnsafeUtilTest.java | 151 +++
.../datasketches/memory/internal/Utf8Test.java | 516 ++++++++++
.../datasketches/memory/internal/UtilTest.java | 2 -
.../memory/internal/VirtualMachineMemoryTest.java | 39 +
.../memory/internal/WritableDirectCopyTest.java | 253 +++++
.../memory/internal/WritableMemoryTest.java | 198 ++++
.../memory/internal/XxHash64LoopingTest.java | 1082 ++++++++++++++++++++
.../datasketches/memory/internal/XxHash64Test.java | 183 ++++
.../memory/internal/ZeroCapacityTest.java | 68 ++
46 files changed, 12018 insertions(+), 6 deletions(-)
diff --git a/datasketches-memory-java8-tests/WritableDirectCopyTest.java b/datasketches-memory-java8-tests/WritableDirectCopyTest.java
new file mode 100644
index 0000000..f52aa34
--- /dev/null
+++ b/datasketches-memory-java8-tests/WritableDirectCopyTest.java
@@ -0,0 +1,253 @@
+/*
+ * 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.datasketches.memory.internal;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.fail;
+
+import org.apache.datasketches.memory.WritableHandle;
+import org.apache.datasketches.memory.Memory;
+import org.apache.datasketches.memory.WritableMemory;
+import org.testng.annotations.Test;
+
+/**
+ * @author Lee Rhodes
+ */
+public class WritableDirectCopyTest {
+
+//Copy Within tests
+
+ @Test
+ public void checkCopyWithinNativeSmall() throws Exception {
+ int memCapacity = 64;
+ int half = memCapacity / 2;
+ try (WritableHandle wrh = WritableMemory.allocateDirect(memCapacity)) {
+ WritableMemory mem = wrh.getWritable();
+ mem.clear();
+
+ for (int i = 0; i < half; i++) { //fill first half
+ mem.putByte(i, (byte) i);
+ }
+
+ mem.copyTo(0, mem, half, half);
+
+ for (int i = 0; i < half; i++) {
+ assertEquals(mem.getByte(i + half), (byte) i);
+ }
+ }
+ }
+
+ @Test
+ public void checkCopyWithinNativeLarge() throws Exception {
+ int memCapacity = (2 << 20) + 64;
+ int memCapLongs = memCapacity / 8;
+ int halfBytes = memCapacity / 2;
+ int halfLongs = memCapLongs / 2;
+ try (WritableHandle wrh = WritableMemory.allocateDirect(memCapacity)) {
+ WritableMemory mem = wrh.getWritable();
+ mem.clear();
+
+ for (int i = 0; i < halfLongs; i++) {
+ mem.putLong(i * 8, i);
+ }
+
+ mem.copyTo(0, mem, halfBytes, halfBytes);
+
+ for (int i = 0; i < halfLongs; i++) {
+ assertEquals(mem.getLong((i + halfLongs) * 8), i);
+ }
+ }
+ }
+
+ @Test
+ public void checkCopyWithinNativeOverlap() throws Exception {
+ int memCapacity = 64;
+ try (WritableHandle wrh = WritableMemory.allocateDirect(memCapacity)) {
+ WritableMemory mem = wrh.getWritable();
+ mem.clear();
+ //println(mem.toHexString("Clear 64", 0, memCapacity));
+
+ for (int i = 0; i < (memCapacity / 2); i++) {
+ mem.putByte(i, (byte) i);
+ }
+ //println(mem.toHexString("Set 1st 32 to ints ", 0, memCapacity));
+ mem.copyTo(0, mem, memCapacity / 4, memCapacity / 2); //overlap is OK
+ }
+ }
+
+ @Test
+ public void checkCopyWithinNativeSrcBound() throws Exception {
+ int memCapacity = 64;
+ try (WritableHandle wrh = WritableMemory.allocateDirect(memCapacity)) {
+ WritableMemory mem = wrh.getWritable();
+ mem.copyTo(32, mem, 32, 33); //hit source bound check
+ fail("Did Not Catch Assertion Error: source bound");
+ } catch (IllegalArgumentException e) {
+ //pass
+ }
+ }
+
+ @Test
+ public void checkCopyWithinNativeDstBound() throws Exception {
+ int memCapacity = 64;
+ try (WritableHandle wrh = WritableMemory.allocateDirect(memCapacity)) {
+ WritableMemory mem = wrh.getWritable();
+ mem.copyTo(0, mem, 32, 33); //hit dst bound check
+ fail("Did Not Catch Assertion Error: dst bound");
+ } catch (IllegalArgumentException e) {
+ //pass
+ }
+ }
+
+ @Test
+ public void checkCopyCrossNativeSmall() throws Exception {
+ int memCapacity = 64;
+
+ try (WritableHandle wrh1 = WritableMemory.allocateDirect(memCapacity);
+ WritableHandle wrh2 = WritableMemory.allocateDirect(memCapacity)) {
+ WritableMemory mem1 = wrh1.getWritable();
+ WritableMemory mem2 = wrh2.getWritable();
+
+ for (int i = 0; i < memCapacity; i++) {
+ mem1.putByte(i, (byte) i);
+ }
+ mem2.clear();
+ mem1.copyTo(0, mem2, 0, memCapacity);
+
+ for (int i = 0; i < memCapacity; i++) {
+ assertEquals(mem2.getByte(i), (byte) i);
+ }
+ wrh1.close();
+ wrh2.close();
+ }
+ }
+
+ @Test
+ public void checkCopyCrossNativeLarge() throws Exception {
+ int memCapacity = (2 << 20) + 64;
+ int memCapLongs = memCapacity / 8;
+
+ try (WritableHandle wrh1 = WritableMemory.allocateDirect(memCapacity);
+ WritableHandle wrh2 = WritableMemory.allocateDirect(memCapacity)) {
+ WritableMemory mem1 = wrh1.getWritable();
+ WritableMemory mem2 = wrh2.getWritable();
+
+ for (int i = 0; i < memCapLongs; i++) {
+ mem1.putLong(i * 8, i);
+ }
+ mem2.clear();
+
+ mem1.copyTo(0, mem2, 0, memCapacity);
+
+ for (int i = 0; i < memCapLongs; i++) {
+ assertEquals(mem2.getLong(i * 8), i);
+ }
+ }
+ }
+
+ @Test
+ public void checkCopyCrossNativeAndByteArray() throws Exception {
+ int memCapacity = 64;
+ try (WritableHandle wrh1 = WritableMemory.allocateDirect(memCapacity)) {
+ WritableMemory mem1 = wrh1.getWritable();
+
+ for (int i = 0; i < mem1.getCapacity(); i++) {
+ mem1.putByte(i, (byte) i);
+ }
+
+ WritableMemory mem2 = WritableMemory.allocate(memCapacity);
+ mem1.copyTo(8, mem2, 16, 16);
+
+ for (int i = 0; i < 16; i++) {
+ assertEquals(mem1.getByte(8 + i), mem2.getByte(16 + i));
+ }
+ //println(mem2.toHexString("Mem2", 0, (int)mem2.getCapacity()));
+ }
+ }
+
+ @Test
+ public void checkCopyCrossRegionsSameNative() throws Exception {
+ int memCapacity = 128;
+
+ try (WritableHandle wrh1 = WritableMemory.allocateDirect(memCapacity)) {
+ WritableMemory mem1 = wrh1.getWritable();
+
+ for (int i = 0; i < mem1.getCapacity(); i++) {
+ mem1.putByte(i, (byte) i);
+ }
+ //println(mem1.toHexString("Mem1", 0, (int)mem1.getCapacity()));
+
+ Memory reg1 = mem1.region(8, 16);
+ //println(reg1.toHexString("Reg1", 0, (int)reg1.getCapacity()));
+
+ WritableMemory reg2 = mem1.writableRegion(24, 16);
+ //println(reg2.toHexString("Reg2", 0, (int)reg2.getCapacity()));
+ reg1.copyTo(0, reg2, 0, 16);
+
+ for (int i = 0; i < 16; i++) {
+ assertEquals(reg1.getByte(i), reg2.getByte(i));
+ assertEquals(mem1.getByte(8 + i), mem1.getByte(24 + i));
+ }
+ //println(mem1.toHexString("Mem1", 0, (int)mem1.getCapacity()));
+ }
+ }
+
+ @Test
+ public void checkCopyCrossNativeArrayAndHierarchicalRegions() throws Exception {
+ int memCapacity = 64;
+ try (WritableHandle wrh1 = WritableMemory.allocateDirect(memCapacity)) {
+ WritableMemory mem1 = wrh1.getWritable();
+
+ for (int i = 0; i < mem1.getCapacity(); i++) { //fill with numbers
+ mem1.putByte(i, (byte) i);
+ }
+ //println(mem1.toHexString("Mem1", 0, (int)mem1.getCapacity()));
+
+ WritableMemory mem2 = WritableMemory.allocate(memCapacity);
+
+ Memory reg1 = mem1.region(8, 32);
+ Memory reg1B = reg1.region(8, 16);
+ //println(reg1.toHexString("Reg1", 0, (int)reg1.getCapacity()));
+ //println(reg1B.toHexString("Reg1B", 0, (int)reg1B.getCapacity()));
+
+ WritableMemory reg2 = mem2.writableRegion(32, 16);
+ reg1B.copyTo(0, reg2, 0, 16);
+ //println(reg2.toHexString("Reg2", 0, (int)reg2.getCapacity()));
+
+ //println(mem2.toHexString("Mem2", 0, (int)mem2.getCapacity()));
+ for (int i = 32, j = 16; i < 40; i++, j++) {
+ assertEquals(mem2.getByte(i), j);
+ }
+ }
+ }
+
+ @Test
+ public void printlnTest() {
+ println("PRINTING: " + this.getClass().getName());
+ }
+
+ /**
+ * @param s value to print
+ */
+ static void println(String s) {
+ //System.out.println(s); //disable here
+ }
+
+}
diff --git a/datasketches-memory-java8-tests/WritableMemoryTest.java b/datasketches-memory-java8-tests/WritableMemoryTest.java
new file mode 100644
index 0000000..0c4cbab
--- /dev/null
+++ b/datasketches-memory-java8-tests/WritableMemoryTest.java
@@ -0,0 +1,199 @@
+/*
+ * 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.datasketches.memory.internal;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertFalse;
+import static org.testng.Assert.assertTrue;
+
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.util.concurrent.ThreadLocalRandom;
+
+import org.apache.datasketches.memory.Memory;
+import org.apache.datasketches.memory.WritableBuffer;
+import org.apache.datasketches.memory.WritableMemory;
+import org.apache.datasketches.memory.internal.Util;
+import org.testng.annotations.Test;
+
+public class WritableMemoryTest {
+
+ @Test
+ public void wrapBigEndian() {
+ ByteBuffer bb = ByteBuffer.allocate(64); //big endian
+ WritableMemory wmem = WritableMemory.writableWrap(bb);
+ assertEquals(wmem.getTypeByteOrder(), ByteOrder.BIG_ENDIAN);
+ wmem = WritableMemory.writableWrap(bb, ByteOrder.nativeOrder());
+ assertEquals(wmem.getTypeByteOrder(), ByteOrder.LITTLE_ENDIAN);
+ }
+
+ @Test
+ public void wrapBigEndianAsLittle() {
+ ByteBuffer bb = ByteBuffer.allocate(64);
+ bb.putChar(0, (char)1); //as NNO
+ WritableMemory wmem = WritableMemory.writableWrap(bb, ByteOrder.LITTLE_ENDIAN, null);
+ assertEquals(wmem.getChar(0), 256);
+ }
+
+ @Test
+ public void allocateWithByteOrder() {
+ WritableMemory wmem = WritableMemory.allocate(64, ByteOrder.BIG_ENDIAN);
+ assertEquals(wmem.getTypeByteOrder(), ByteOrder.BIG_ENDIAN);
+ wmem = WritableMemory.allocate(64, ByteOrder.LITTLE_ENDIAN);
+ assertEquals(wmem.getTypeByteOrder(), ByteOrder.LITTLE_ENDIAN);
+ wmem = WritableMemory.writableWrap(new byte[64], 32, 32, ByteOrder.BIG_ENDIAN);
+ assertEquals(wmem.getTypeByteOrder(), ByteOrder.BIG_ENDIAN);
+ }
+
+ @Test
+ public void checkGetArray() {
+ byte[] byteArr = new byte[64];
+ WritableMemory wmem = WritableMemory.writableWrap(byteArr);
+ assertTrue(wmem.getArray() == byteArr);
+ WritableBuffer wbuf = wmem.asWritableBuffer();
+ assertTrue(wbuf.getArray() == byteArr);
+ }
+
+ @Test(expectedExceptions = IllegalArgumentException.class)
+ public void checkSelfArrayCopy() {
+ byte[] srcAndDst = new byte[128];
+ WritableMemory wmem = WritableMemory.writableWrap(srcAndDst);
+ wmem.getByteArray(0, srcAndDst, 64, 64); //non-overlapping
+ }
+
+ @Test
+ public void checkEquals() {
+ int len = 7;
+ WritableMemory wmem1 = WritableMemory.allocate(len);
+ //@SuppressWarnings({"EqualsWithItself", "SelfEquals"}) //unsupported
+ //SelfEquals for Plexus, EqualsWithItself for IntelliJ
+ //boolean eq1 = wmem1.equals(wmem1); //strict profile complains
+ //assertTrue(eq1);
+
+ WritableMemory wmem2 = WritableMemory.allocate(len + 1);
+ assertFalse(wmem1.equals(wmem2));
+
+ WritableMemory reg1 = wmem1.writableRegion(0, wmem1.getCapacity());
+ assertTrue(wmem1.equals(reg1));
+
+ wmem2 = WritableMemory.allocate(len);
+ for (int i = 0; i < len; i++) {
+ wmem1.putByte(i, (byte) i);
+ wmem2.putByte(i, (byte) i);
+ }
+ assertTrue(wmem1.equals(wmem2));
+ assertTrue(wmem1.equalTo(0, wmem1, 0, len));
+
+ reg1 = wmem1.writableRegion(0, wmem1.getCapacity());
+ assertTrue(wmem1.equalTo(0, reg1, 0, len));
+
+ len = 24;
+ wmem1 = WritableMemory.allocate(len);
+ wmem2 = WritableMemory.allocate(len);
+ for (int i = 0; i < len; i++) {
+ wmem1.putByte(i, (byte) i);
+ wmem2.putByte(i, (byte) i);
+ }
+ assertTrue(wmem1.equalTo(0, wmem2, 0, len - 1));
+ assertTrue(wmem1.equalTo(0, wmem2, 0, len));
+ wmem2.putByte(0, (byte) 10);
+ assertFalse(wmem1.equalTo(0, wmem2, 0, len));
+ wmem2.putByte(0, (byte) 0);
+ wmem2.putByte(len - 2, (byte) 0);
+ assertFalse(wmem1.equalTo(0, wmem2, 0, len - 1));
+ }
+
+ @Test
+ public void checkEquals2() {
+ int len = 23;
+ WritableMemory wmem1 = WritableMemory.allocate(len);
+ assertFalse(wmem1.equals(null));
+ //@SuppressWarnings({"EqualsWithItself", "SelfEquals"}) //unsupported
+ //SelfEquals for Plexus, EqualsWithItself for IntelliJ
+ //boolean eq1 = wmem1.equals(wmem1); //strict profile complains
+ //assertTrue(eq1);
+
+ WritableMemory wmem2 = WritableMemory.allocate(len + 1);
+ assertFalse(wmem1.equals(wmem2));
+
+ for (int i = 0; i < len; i++) {
+ wmem1.putByte(i, (byte) i);
+ wmem2.putByte(i, (byte) i);
+ }
+ assertTrue(wmem1.equalTo(0, wmem2, 0, len));
+ assertTrue(wmem1.equalTo(1, wmem2, 1, len - 1));
+ }
+
+ @Test
+ public void checkLargeEquals() {
+ // Size bigger than UNSAFE_COPY_MEMORY_THRESHOLD; size with "reminder" = 7, to test several
+ // traits of the implementation
+ final int thresh = Util.UNSAFE_COPY_THRESHOLD_BYTES;
+ byte[] bytes1 = new byte[(thresh * 2) + 7];
+ ThreadLocalRandom.current().nextBytes(bytes1);
+ byte[] bytes2 = bytes1.clone();
+ Memory mem1 = Memory.wrap(bytes1);
+ Memory mem2 = Memory.wrap(bytes2);
+ assertTrue(mem1.equals(mem2));
+
+ bytes2[thresh + 10] = (byte) (bytes1[thresh + 10] + 1);
+ assertFalse(mem1.equals(mem2));
+
+ bytes2[thresh + 10] = bytes1[thresh + 10];
+ bytes2[(thresh * 2) + 3] = (byte) (bytes1[(thresh * 2) + 3] + 1);
+ assertFalse(mem1.equals(mem2));
+ }
+
+ @Test
+ public void checkWrapWithBO() {
+ WritableMemory wmem = WritableMemory.writableWrap(new byte[0], ByteOrder.BIG_ENDIAN);
+ boolean nativeBO = wmem.getTypeByteOrder() == ByteOrder.nativeOrder();
+ assertFalse(nativeBO);
+ println("" + nativeBO);
+ wmem = WritableMemory.writableWrap(new byte[8], ByteOrder.BIG_ENDIAN);
+ nativeBO = wmem.getTypeByteOrder() == ByteOrder.nativeOrder();
+ assertFalse(nativeBO);
+ println("" + nativeBO);
+ }
+
+ @Test
+ @SuppressWarnings("unused")
+ public void checkOwnerClientCase() {
+ WritableMemory owner = WritableMemory.allocate(64);
+ Memory client1 = owner; //Client1 cannot write (no API)
+ owner.putInt(0, 1); //But owner can write
+ ((WritableMemory)client1).putInt(0, 2); //Client1 can write, but with explicit effort.
+ Memory client2 = owner.region(0, owner.getCapacity()); //client2 cannot write (no API)
+ owner.putInt(0, 3); //But Owner should be able to write
+ }
+
+ @Test
+ public void printlnTest() {
+ println("PRINTING: "+this.getClass().getName());
+ }
+
+ /**
+ * @param s value to print
+ */
+ static void println(final String s) {
+ //System.out.println(s);
+ }
+
+}
diff --git a/datasketches-memory-java8-tests/XxHash64LoopingTest.java b/datasketches-memory-java8-tests/XxHash64LoopingTest.java
new file mode 100644
index 0000000..6fc4f81
--- /dev/null
+++ b/datasketches-memory-java8-tests/XxHash64LoopingTest.java
@@ -0,0 +1,1082 @@
+/*
+ * 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.datasketches.memory.internal;
+
+import static org.testng.Assert.assertEquals;
+
+import org.apache.datasketches.memory.WritableMemory;
+import org.testng.annotations.Test;
+
+/**
+ * @author Lee Rhodes
+ */
+public class XxHash64LoopingTest {
+
+ /*
+ * This test is adapted from
+ * <a href="https://github.com/OpenHFT/Zero-Allocation-Hashing/blob/master/src/test/java/net/openhft/hashing/XxHashTest.java">
+ * OpenHFT/Zero-Allocation-Hashing</a> to test hash compatibility with that implementation.
+ * See LICENSE.
+ */
+ @Test
+ public void testWithSeed() {
+ long seed = 42L;
+ for (int i = 0; i < 1025; i++) {
+ byte[] byteArr = new byte[i];
+ for (int j = 0; j < byteArr.length; j++) { byteArr[j] = (byte) j; }
+ WritableMemory wmem = WritableMemory.writableWrap(byteArr);
+ long hash = wmem.xxHash64(0, byteArr.length, seed);
+ assertEquals(hash, HASHES_OF_LOOPING_BYTES_WITH_SEED_42[i]);
+ }
+ }
+
+ /*This data is from
+ * <a href="https://github.com/OpenHFT/Zero-Allocation-Hashing/blob/master/src/test/java/net/openhft/hashing/XxHashTest.java">
+ * OpenHFT/Zero-Allocation-Hashing</a> to test hash compatibility with that implementation.
+ * See LICENSE.
+ */
+ private static final long[] HASHES_OF_LOOPING_BYTES_WITH_SEED_42 = {
+ -7444071767201028348L,
+ -8959994473701255385L,
+ 7116559933691734543L,
+ 6019482000716350659L,
+ -6625277557348586272L,
+ -5507563483608914162L,
+ 1540412690865189709L,
+ 4522324563441226749L,
+ -7143238906056518746L,
+ -7989831429045113014L,
+ -7103973673268129917L,
+ -2319060423616348937L,
+ -7576144055863289344L,
+ -8903544572546912743L,
+ 6376815151655939880L,
+ 5913754614426879871L,
+ 6466567997237536608L,
+ -869838547529805462L,
+ -2416009472486582019L,
+ -3059673981515537339L,
+ 4211239092494362041L,
+ 1414635639471257331L,
+ 166863084165354636L,
+ -3761330575439628223L,
+ 3524931906845391329L,
+ 6070229753198168844L,
+ -3740381894759773016L,
+ -1268276809699008557L,
+ 1518581707938531581L,
+ 7988048690914090770L,
+ -4510281763783422346L,
+ -8988936099728967847L,
+ -8644129751861931918L,
+ 2046936095001747419L,
+ 339737284852751748L,
+ -8493525091666023417L,
+ -3962890767051635164L,
+ -5799948707353228709L,
+ -6503577434416464161L,
+ 7718729912902936653L,
+ 191197390694726650L,
+ -2677870679247057207L,
+ 20411540801847004L,
+ 2738354376741059902L,
+ -3754251900675510347L,
+ -3208495075154651980L,
+ 5505877218642938179L,
+ 6710910171520780908L,
+ -9060809096139575515L,
+ 6936438027860748388L,
+ -6675099569841255629L,
+ -5358120966884144380L,
+ -4970515091611332076L,
+ -1810965683604454696L,
+ -516197887510505242L,
+ 1240864593087756274L,
+ 6033499571835033332L,
+ 7223146028771530185L,
+ 909128106589125206L,
+ 1567720774747329341L,
+ -1867353301780159863L,
+ 4655107429511759333L,
+ 5356891185236995950L,
+ 182631115370802890L,
+ -3582744155969569138L,
+ 595148673029792797L,
+ 495183136068540256L,
+ 5536689004903505647L,
+ -8472683670935785889L,
+ -4335021702965928166L,
+ 7306662983232020244L,
+ 4285260837125010956L,
+ 8288813008819191181L,
+ -3442351913745287612L,
+ 4883297703151707194L,
+ 9135546183059994964L,
+ 123663780425483012L,
+ 509606241253238381L,
+ 5940344208569311369L,
+ -2650142344608291176L,
+ 3232776678942440459L,
+ -922581627593772181L,
+ 7617977317085633049L,
+ 7154902266379028518L,
+ -5806388675416795571L,
+ 4368003766009575737L,
+ -2922716024457242064L,
+ 4771160713173250118L,
+ 3275897444752647349L,
+ -297220751499763878L,
+ 5095659287766176401L,
+ 1181843887132908826L,
+ 9058283605301070357L,
+ 3984713963471276643L,
+ 6050484112980480005L,
+ 1551535065359244224L,
+ 565337293533335618L,
+ 7412521035272884309L,
+ -4735469481351389369L,
+ 6998597101178745656L,
+ -9107075101236275961L,
+ 5879828914430779796L,
+ 6034964979406620806L,
+ 5666406915264701514L,
+ -4666218379625258428L,
+ 2749972203764815656L,
+ -782986256139071446L,
+ 6830581400521008570L,
+ 2588852022632995043L,
+ -5484725487363818922L,
+ -3319556935687817112L,
+ 6481961252981840893L,
+ 2204492445852963006L,
+ -5301091763401031066L,
+ -2615065677047206256L,
+ -6769817545131782460L,
+ -8421640685322953142L,
+ -3669062629317949176L,
+ -9167016978640750490L,
+ 2783671191687959562L,
+ -7599469568522039782L,
+ -7589134103255480011L,
+ -5932706841188717592L,
+ -8689756354284562694L,
+ -3934347391198581249L,
+ -1344748563236040701L,
+ 2172701592984478834L,
+ -5322052340624064417L,
+ -8493945390573620511L,
+ 3349021988137788403L,
+ -1806262525300459538L,
+ -8091524448239736618L,
+ 4022306289903960690L,
+ -8346915997379834224L,
+ -2106001381993805461L,
+ -5784123934724688161L,
+ 6775158099649720388L,
+ -3869682756870293568L,
+ 4356490186652082006L,
+ 8469371446702290916L,
+ -2972961082318458602L,
+ -7188106622222784561L,
+ -4961006366631572412L,
+ 3199991182014172900L,
+ 2917435868590434179L,
+ 8385845305547872127L,
+ 7706824402560674655L,
+ -1587379863634865277L,
+ -4212156212298809650L,
+ -1305209322000720233L,
+ -7866728337506665880L,
+ 8195089740529247049L,
+ -4876930125798534239L,
+ 798222697981617129L,
+ -2441020897729372845L,
+ -3926158482651178666L,
+ -1254795122048514130L,
+ 5192463866522217407L,
+ -5426289318796042964L,
+ -3267454004443530826L,
+ 471043133625225785L,
+ -660956397365869974L,
+ -6149209189144999161L,
+ -2630977660039166559L,
+ 8512219789663151219L,
+ -3309844068134074620L,
+ -6211275327487847132L,
+ -2130171729366885995L,
+ 6569302074205462321L,
+ 4855778342281619706L,
+ 3867211421508653033L,
+ -3002480002418725542L,
+ -8297543107467502696L,
+ 8049642289208775831L,
+ -5439825716055425635L,
+ 7251760070798756432L,
+ -4774526021749797528L,
+ -3892389575184442548L,
+ 5162451061244344424L,
+ 6000530226398686578L,
+ -5713092252241819676L,
+ 8740913206879606081L,
+ -8693282419677309723L,
+ 1576205127972543824L,
+ 5760354502610401246L,
+ 3173225529903529385L,
+ 1785166236732849743L,
+ -1024443476832068882L,
+ -7389053248306187459L,
+ 1171021620017782166L,
+ 1471572212217428724L,
+ 7720766400407679932L,
+ -8844781213239282804L,
+ -7030159830170200877L,
+ 2195066352895261150L,
+ 1343620937208608634L,
+ 9178233160016731645L,
+ -757883447602665223L,
+ 3303032934975960867L,
+ -3685775162104101116L,
+ -4454903657585596656L,
+ -5721532367620482629L,
+ 8453227136542829644L,
+ 5397498317904798888L,
+ 7820279586106842836L,
+ -2369852356421022546L,
+ 3910437403657116169L,
+ 6072677490463894877L,
+ -2651044781586183960L,
+ 5173762670440434510L,
+ -2970017317595590978L,
+ -1024698859439768763L,
+ -3098335260967738522L,
+ -1983156467650050768L,
+ -8132353894276010246L,
+ -1088647368768943835L,
+ -3942884234250555927L,
+ 7169967005748210436L,
+ 2870913702735953746L,
+ -2207022373847083021L,
+ 1104181306093040609L,
+ 5026420573696578749L,
+ -5874879996794598513L,
+ -4777071762424874671L,
+ -7506667858329720470L,
+ -2926679936584725232L,
+ -5530649174168373609L,
+ 5282408526788020384L,
+ 3589529249264153135L,
+ -6220724706210580398L,
+ -7141769650716479812L,
+ 5142537361821482047L,
+ -7029808662366864423L,
+ -6593520217660744466L,
+ 1454581737122410695L,
+ -139542971769349865L,
+ 1727752089112067235L,
+ -775001449688420017L,
+ -5011311035350652032L,
+ -8671171179275033159L,
+ -2850915129917664667L,
+ -5258897903906998781L,
+ -6954153088230718761L,
+ -4070351752166223959L,
+ -6902592976462171099L,
+ -7850366369290661391L,
+ -4562443925864904705L,
+ 3186922928616271015L,
+ 2208521081203400591L,
+ -2727824999830592777L,
+ -3817861137262331295L,
+ 2236720618756809066L,
+ -4888946967413746075L,
+ -446884183491477687L,
+ -43021963625359034L,
+ -5857689226703189898L,
+ -2156533592262354883L,
+ -2027655907961967077L,
+ 7151844076490292500L,
+ -5029149124756905464L,
+ 526404452686156976L,
+ 8741076980297445408L,
+ 7962851518384256467L,
+ -105985852299572102L,
+ -2614605270539434398L,
+ -8265006689379110448L,
+ 8158561071761524496L,
+ -6923530157382047308L,
+ 5551949335037580397L,
+ 565709346370307061L,
+ -4780869469938333359L,
+ 6931895917517004830L,
+ 565234767538051407L,
+ -8663136372880869656L,
+ 1427340323685448983L,
+ 6492705666640232290L,
+ 1481585578088475369L,
+ -1712711110946325531L,
+ 3281685342714380741L,
+ 6441384790483098576L,
+ -1073539554682358394L,
+ 5704050067194788964L,
+ -5495724689443043319L,
+ -5425043165837577535L,
+ 8349736730194941321L,
+ -4123620508872850061L,
+ 4687874980541143573L,
+ -468891940172550975L,
+ -3212254545038049829L,
+ -6830802881920725628L,
+ 9033050533972480988L,
+ 4204031879107709260L,
+ -677513987701096310L,
+ -3286978557209370155L,
+ 1644111582609113135L,
+ 2040089403280131741L,
+ 3323690950628902653L,
+ -7686964480987925756L,
+ -4664519769497402737L,
+ 3358384147145476542L,
+ -4699919744264452277L,
+ -4795197464927839170L,
+ 5051607253379734527L,
+ -8987703459734976898L,
+ 8993686795574431834L,
+ -2688919474688811047L,
+ 375938183536293311L,
+ 1049459889197081920L,
+ -1213022037395838295L,
+ 4932989235110984138L,
+ -6647247877090282452L,
+ -7698817539128166242L,
+ -3264029336002462659L,
+ 6487828018122309795L,
+ -2660821091484592878L,
+ 7104391069028909121L,
+ -1765840012354703384L,
+ 85428166783788931L,
+ -6732726318028261938L,
+ 7566202549055682933L,
+ 229664898114413280L,
+ -1474237851782211353L,
+ -1571058880058007603L,
+ -7926453582850712144L,
+ 2487148368914275243L,
+ 8740031015380673473L,
+ 1908345726881363169L,
+ -2510061320536523178L,
+ 7854780026906019630L,
+ -6023415596650016493L,
+ -6264841978089051107L,
+ 4024998278016087488L,
+ -4266288992025826072L,
+ -3222176619422665563L,
+ -1999258726038299316L,
+ 1715270077442385636L,
+ 6764658837948099754L,
+ -8646962299105812577L,
+ -51484064212171546L,
+ -1482515279051057493L,
+ -8663965522608868414L,
+ -256555202123523670L,
+ 1973279596140303801L,
+ -7280796173024508575L,
+ -5691760367231354704L,
+ -5915786562256300861L,
+ -3697715074906156565L,
+ 3710290115318541949L,
+ 6796151623958134374L,
+ -935299482515386356L,
+ -7078378973978660385L,
+ 5379481350768846927L,
+ -9011221735308556302L,
+ 5936568631579608418L,
+ -6060732654964511813L,
+ -4243141607840017809L,
+ 3198488845875349355L,
+ -7809288876010447646L,
+ 4371587872421472389L,
+ -1304197371105522943L,
+ 7389861473143460103L,
+ -1892352887992004024L,
+ 2214828764044713398L,
+ 6347546952883613388L,
+ 1275694314105480954L,
+ -5262663163358903733L,
+ 1524757505892047607L,
+ 1474285098416162746L,
+ -7976447341881911786L,
+ 4014100291977623265L,
+ 8994982266451461043L,
+ -7737118961020539453L,
+ -2303955536994331092L,
+ 1383016539349937136L,
+ 1771516393548245271L,
+ -5441914919967503849L,
+ 5449813464890411403L,
+ -3321280356474552496L,
+ 4084073849712624363L,
+ 4290039323210935932L,
+ 2449523715173349652L,
+ 7494827882138362156L,
+ 9035007221503623051L,
+ 5722056230130603177L,
+ -5443061851556843748L,
+ -7554957764207092109L,
+ 447883090204372074L,
+ 533916651576859197L,
+ -3104765246501904165L,
+ -4002281505194601516L,
+ -8402008431255610992L,
+ -408273018037005304L,
+ 214196458752109430L,
+ 6458513309998070914L,
+ 2665048360156607904L,
+ 96698248584467992L,
+ -3238403026096269033L,
+ 6759639479763272920L,
+ -4231971627796170796L,
+ -2149574977639731179L,
+ -1437035755788460036L,
+ -6000005629185669767L,
+ 145244292800946348L,
+ -3056352941404947199L,
+ 3748284277779018970L,
+ 7328354565489106580L,
+ -2176895260373660284L,
+ 3077983936372755601L,
+ 1215485830019410079L,
+ 683050801367331140L,
+ -3173237622987755212L,
+ -1951990779107873701L,
+ -4714366021269652421L,
+ 4934690664256059008L,
+ 1674823104333774474L,
+ -3974408282362828040L,
+ 2001478896492417760L,
+ -4115105568354384199L,
+ -2039694725495941666L,
+ -587763432329933431L,
+ -391276713546911316L,
+ -5543400904809469053L,
+ 1882564440421402418L,
+ -4991793588968693036L,
+ 3454088185914578321L,
+ 2290855447126188424L,
+ 3027910585026909453L,
+ 2136873580213167431L,
+ -6243562989966916730L,
+ 5887939953208193029L,
+ -3491821629467655741L,
+ -3138303216306660662L,
+ 8572629205737718669L,
+ 4154439973110146459L,
+ 5542921963475106759L,
+ -2025215496720103521L,
+ -4047933760493641640L,
+ -169455456138383823L,
+ -1164572689128024473L,
+ -8551078127234162906L,
+ -7247713218016599028L,
+ 8725299775220778242L,
+ 6263466461599623132L,
+ 7931568057263751768L,
+ 7365493014712655238L,
+ -7343740914722477108L,
+ 8294118602089088477L,
+ 7677867223984211483L,
+ -7052188421655969232L,
+ -3739992520633991431L,
+ 772835781531324307L,
+ 881441588914692737L,
+ 6321450879891466401L,
+ 5682516032668315027L,
+ 8493068269270840662L,
+ -3895212467022280567L,
+ -3241911302335746277L,
+ -7199586338775635848L,
+ -4606922569968527974L,
+ -806850906331637768L,
+ 2433670352784844513L,
+ -5787982146811444512L,
+ 7852193425348711165L,
+ 8669396209073850051L,
+ -6898875695148963118L,
+ 6523939610287206782L,
+ -8084962379210153174L,
+ 8159432443823995836L,
+ -2631068535470883494L,
+ -338649779993793113L,
+ 6514650029997052016L,
+ 3926259678521802094L,
+ 5443275905907218528L,
+ 7312187582713433551L,
+ -2993773587362997676L,
+ -1068335949405953411L,
+ 4499730398606216151L,
+ 8538015793827433712L,
+ -4057209365270423575L,
+ -1504284818438273559L,
+ -6460688570035010846L,
+ 1765077117408991117L,
+ 8278320303525164177L,
+ 8510128922449361533L,
+ 1305722765578569816L,
+ 7250861238779078656L,
+ -576624504295396147L,
+ -4363714566147521011L,
+ -5932111494795524073L,
+ 1837387625936544674L,
+ -4186755953373944712L,
+ -7657073597826358867L,
+ 140408487263951108L,
+ 5578463635002659628L,
+ 3400326044813475885L,
+ -6092804808386714986L,
+ -2410324417287268694L,
+ 3222007930183458970L,
+ 4932471983280850419L,
+ 3554114546976144528L,
+ -7216067928362857082L,
+ -6115289896923351748L,
+ -6769646077108881947L,
+ 4263895947722578066L,
+ 2939136721007694271L,
+ 1426030606447416658L,
+ -1316192446807442076L,
+ 5366182640480055129L,
+ 6527003877470258527L,
+ 5849680119000207603L,
+ 5263993237214222328L,
+ -6936533648789185663L,
+ -9063642143790846605L,
+ 3795892210758087672L,
+ 4987213125282940176L,
+ 2505500970421590750L,
+ -1014022559552365387L,
+ -3574736245968367770L,
+ 1180676507127340259L,
+ -2261908445207512503L,
+ -8416682633172243509L,
+ 1114990703652673283L,
+ 7753746660364401380L,
+ 1874908722469707905L,
+ 2033421444403047677L,
+ 21412168602505589L,
+ 385957952615286205L,
+ 2053171460074727107L,
+ 1915131899400103774L,
+ 6680879515029368390L,
+ 568807208929724162L,
+ -6211541450459087674L,
+ -5026690733412145448L,
+ 1384781941404886235L,
+ -98027820852587266L,
+ 1806580495924249669L,
+ 6322077317403503963L,
+ 9078162931419569939L,
+ -2809061215428363978L,
+ 7697867577577415733L,
+ -5270063855897737274L,
+ 5649864555290587388L,
+ -6970990547695444247L,
+ 579684606137331754L,
+ 3871931565451195154L,
+ 2030008578322050218L,
+ -5012357307111799829L,
+ -2271365921756144065L,
+ 4551962665158074190L,
+ -3385474923040271312L,
+ -7647625164191633577L,
+ 6634635380316963029L,
+ -5201190933687061585L,
+ 8864818738548593973L,
+ 2855828214210882907L,
+ 9154512990734024165L,
+ -6945306719789457786L,
+ 1200243352799481087L,
+ 875998327415853787L,
+ 1275313054449881011L,
+ -6105772045375948736L,
+ -2926927684328291437L,
+ 9200050852144954779L,
+ 5188726645765880663L,
+ 5197037323312705176L,
+ 3434926231010121611L,
+ -5054013669361906544L,
+ 2582959199749224670L,
+ -6053757512723474059L,
+ -5016308176846054473L,
+ -2509827316698626133L,
+ 7700343644503853204L,
+ -1997627249894596731L,
+ 3993168688325352290L,
+ -8181743677541277704L,
+ 3719056119682565597L,
+ -7264411659282947790L,
+ 7177028972346484464L,
+ -5460831176884283278L,
+ 1799904662416293978L,
+ -6549616005092764514L,
+ 5472403994001122052L,
+ 8683463751708388502L,
+ -7873363037838316398L,
+ 689134758256487260L,
+ -1287443614028696450L,
+ 4452712919702709507L,
+ 762909374167538893L,
+ 6594302592326281411L,
+ 1183786629674781984L,
+ 5021847859620133476L,
+ -2490098069181538915L,
+ 5105145136026716679L,
+ 4437836948098585718L,
+ 1987270426215858862L,
+ 6170312798826946249L,
+ 634297557126003407L,
+ -1672811625495999581L,
+ 6282971595586218191L,
+ 4549149305727581687L,
+ -5652165370435317782L,
+ 1064501550023753890L,
+ -5334885527127139723L,
+ -6904378001629481237L,
+ -1807576691784201230L,
+ -205688432992053911L,
+ 7621619053293393289L,
+ 6258649161313982470L,
+ -1111634238359342096L,
+ -8044260779481691987L,
+ 400270655839010807L,
+ -7806833581382890725L,
+ -2970563349459508036L,
+ -7392591524816802798L,
+ 2918924613160219805L,
+ -6444161627929149002L,
+ 6096497501321778876L,
+ -1477975665655830038L,
+ 1690651307597306138L,
+ -2364076888826085362L,
+ -6521987420014905821L,
+ -4419193480146960582L,
+ 3538587780233092477L,
+ 8374665961716940404L,
+ 7492412312405424500L,
+ 6311662249091276767L,
+ -1240235198282023566L,
+ 5478559631401166447L,
+ 3476714419313462133L,
+ 377427285984503784L,
+ 2570472638778991109L,
+ -2741381313777447835L,
+ -7123472905503039596L,
+ 2493658686946955193L,
+ 1024677789035847585L,
+ -2916713904339582981L,
+ -4532003852004642304L,
+ -2202143560366234111L,
+ 5832267856442755135L,
+ -261740607772957384L,
+ 239435959690278014L,
+ 5755548341947719409L,
+ 6138795458221887696L,
+ -7709506987360146385L,
+ -6657487758065140444L,
+ -7006376793203657499L,
+ 6544409861846502033L,
+ 3171929352014159247L,
+ 1051041925048792869L,
+ 2617300158375649749L,
+ 952652799620095175L,
+ -576661730162168147L,
+ -1634191369221345988L,
+ 4833656816115993519L,
+ 647566759700005786L,
+ 2473810683785291822L,
+ 3005977181064745326L,
+ -3321881966853149523L,
+ 7595337666427588699L,
+ 6004093624251057224L,
+ -563917505657690279L,
+ 6117428527147449302L,
+ -6287297509522976113L,
+ -4527219334756214406L,
+ 742626429298092489L,
+ 3057351806086972041L,
+ 645967551210272605L,
+ -4428701157828864227L,
+ 3236379103879435414L,
+ -8477089892132066300L,
+ -6127365537275859058L,
+ -4052490484706946358L,
+ -8004854976625046469L,
+ -3679456917426613424L,
+ -8212793762082595299L,
+ -818288739465424130L,
+ 1358812099481667095L,
+ 7835987612195254310L,
+ -3663247409614323059L,
+ -2931105150130396604L,
+ 7296136776835614792L,
+ -2014557408985889628L,
+ 7267662411237959788L,
+ 3699280615819277743L,
+ -212010675469091396L,
+ -6518374332458360120L,
+ 145026010541628849L,
+ 1879297324213501001L,
+ -7146296067751816833L,
+ -5002958800391379931L,
+ 6060682439924517608L,
+ -432234782921170964L,
+ -6669688947353256956L,
+ 7728943532792041267L,
+ 830911367341171721L,
+ 3396934884314289432L,
+ -779464156662780749L,
+ 2330041851883352285L,
+ -4783350380736276693L,
+ -5758476056890049254L,
+ -7551552301614791791L,
+ 1253334187723911710L,
+ -2685018208308798978L,
+ 5379636036360946454L,
+ 6154668487114681217L,
+ -8641287462255458898L,
+ 4676087643800649558L,
+ -2405142641398691475L,
+ 1088685126864246881L,
+ 6431149082338374041L,
+ -607357695335069155L,
+ -720970692129524140L,
+ 2648766932394044468L,
+ 8408344790179354573L,
+ -6193808387735667350L,
+ 7722524628524697419L,
+ -6975433852560238120L,
+ -2925851029234475295L,
+ -4274458387165211028L,
+ -8355836377702147319L,
+ 5278146397877332061L,
+ 8502098812383680707L,
+ 2292836642336580326L,
+ -6127608082651070062L,
+ 2222301962240611208L,
+ -1930887695854799378L,
+ 7640503480494894592L,
+ 1162652186586436094L,
+ -1918002592943761683L,
+ 7648998601717261840L,
+ -8472603250832757057L,
+ -988877663117552456L,
+ 2368458128168026494L,
+ -6480813811998475245L,
+ -5896967824416018967L,
+ -2593783161701820446L,
+ 6950098417530252598L,
+ 6362589545555771236L,
+ 7981389665448567125L,
+ 3954017080198558850L,
+ 1626078615050230622L,
+ 6650159066527969109L,
+ 697345338922935394L,
+ -1226816215461768626L,
+ 8740408765973837440L,
+ -4194155864629568323L,
+ 7016680023232424746L,
+ 6043281358142429469L,
+ -4201005667174376809L,
+ 1216727117859013155L,
+ 6367202436544203935L,
+ 35414869396444636L,
+ 3715622794033998412L,
+ 488654435687670554L,
+ -2503747297224687460L,
+ 3147101919441470388L,
+ -8248611218693190922L,
+ 970697264481229955L,
+ 3411465763826851418L,
+ 9117405004661599969L,
+ -5204346498331519734L,
+ -19637460819385174L,
+ -5039124225167977219L,
+ 2990108874601696668L,
+ -2623857460235459202L,
+ 4256291692861397446L,
+ 6724147860870760443L,
+ 3558616688507246537L,
+ 6487680097936412800L,
+ -6470792832935928161L,
+ 4314814550912237614L,
+ -1292878983006062345L,
+ 6791915152630414174L,
+ 5971652079925815310L,
+ 2557529546662864312L,
+ 466175054322801580L,
+ -585216717310746872L,
+ -2486640422147349036L,
+ 7212029603994220134L,
+ 3958995069888972500L,
+ 4950471855791412790L,
+ -3721948842035712763L,
+ -6184503487488243051L,
+ 4079570444585775332L,
+ -3952156172546996872L,
+ 4543894231118208322L,
+ -1739995588466209963L,
+ 9155948355455935530L,
+ 5821980345462207860L,
+ -2431287667309520417L,
+ -3890108130519441316L,
+ -558124689277030490L,
+ 6079823537335801717L,
+ 5409742395192364262L,
+ -2329885777717160453L,
+ -7332804342513677651L,
+ 1466490574975950555L,
+ -420549419907427929L,
+ -5249909814389692516L,
+ -5145692168206210661L,
+ 5934113980649113921L,
+ 3241618428555359661L,
+ -6622110266160980250L,
+ 5048250878669516223L,
+ 5747219637359976174L,
+ 2975906212588223728L,
+ 5730216838646273215L,
+ -176713127129024690L,
+ 6734624279336671146L,
+ 5127866734316017180L,
+ 7111761230887705595L,
+ 3457811808274317235L,
+ 3362961434604932375L,
+ -1877869936854991246L,
+ 7171428594877765665L,
+ -8252167178400462374L,
+ -6306888185035821047L,
+ -6684702191247683887L,
+ -7754928454824190529L,
+ -1902605599135704386L,
+ -4037319846689421239L,
+ 8493746058123583457L,
+ -8156648963857047193L,
+ 2051510355149839497L,
+ -1256416624177218909L,
+ -3344927996254072010L,
+ -1838853051925943568L,
+ 316927471680974556L,
+ -1502257066700798003L,
+ -5836095610125837606L,
+ -1594125583615895424L,
+ 1442211486559637962L,
+ -144295071206619569L,
+ 5159850900959273410L,
+ 4589139881166423678L,
+ -7038726987463097509L,
+ 2886082400772974595L,
+ 2780759114707171916L,
+ 5694649587906297495L,
+ 1260349041268169667L,
+ 4921517488271434890L,
+ 644696475796073018L,
+ 6262811963753436289L,
+ -6128198676595868773L,
+ -3625352083004760261L,
+ -8751453332943236675L,
+ 8749249479868749221L,
+ -2450808199545048250L,
+ -6517435817046180917L,
+ -3433321727429234998L,
+ -2591586258908763451L,
+ 3847750870868804507L,
+ 6603614438546398643L,
+ -7598682191291031287L,
+ 8710261565627204971L,
+ 4753389483755344355L,
+ -4645333069458786881L,
+ -6742695046613492214L,
+ 643070478568866643L,
+ -7543096104151965610L,
+ 7171495384655926161L,
+ 595063872610714431L,
+ 3292310150781130424L,
+ 4326847806055440904L,
+ -4580020566072794152L,
+ 3142286571820373678L,
+ 5530356537440155930L,
+ 546372639737516181L,
+ 7401214477400367500L,
+ 7406531960402873109L,
+ 3287639667219172570L,
+ 4977301681213633671L,
+ 5253257820925174498L,
+ 2906216636104297878L,
+ 6142955758238347523L,
+ -3498651268741727235L,
+ -5875053958265588593L,
+ 3896719087169993883L,
+ -910904726885775073L,
+ 380107493197368177L,
+ -4993591912695447004L,
+ 2970487257212582761L,
+ 2551762717569548774L,
+ 953061649962736812L,
+ 8949739538606589463L,
+ -2962839167079475801L,
+ -1375673191272573835L,
+ 3761793818361866390L,
+ -389577789190726878L,
+ 5661262051502180269L,
+ -6558556411143987683L,
+ -702798336372315031L,
+ -336662820551371779L,
+ 998576401126580155L,
+ -5945021269112582755L,
+ 6108533925730179871L,
+ 2207095297001999618L,
+ -9042779159998880435L,
+ -6177868444342118372L,
+ 6775965402605895077L,
+ -3788428885163306576L,
+ 7790055010527190387L,
+ 3581587652196995358L,
+ -6176354155561607694L,
+ -5859381340906321207L,
+ 395898765763528395L,
+ 8132967590863909348L,
+ -3329092504090544483L,
+ -6785855381158040247L,
+ 1497218517051796750L,
+ -5352392845588925911L,
+ -6271364901230559194L,
+ 2314830370653350118L,
+ -7617588269001325450L,
+ 1423166885758213795L,
+ 8538612578307869519L,
+ -61918791718295474L,
+ -8177103503192338593L,
+ -4740086042584326695L,
+ 3677931948215558698L,
+ 6558856291580149558L,
+ 2674975452453336335L,
+ 5133796555646930522L,
+ 5139252693299337100L,
+ 7949476871295347205L,
+ 4407815324662880678L,
+ -3758305875280581215L,
+ 6066309507576587415L,
+ -7368508486398350973L,
+ -3181640264332856492L,
+ 6905100869343314145L,
+ 3677177673848733417L,
+ 8862933624870506941L,
+ -8575223195813810568L,
+ 9178470351355678144L,
+ 4677809017145408358L,
+ -1194833416287894989L,
+ 3436364743255571183L,
+ -5204770725795363579L,
+ 560599448536335263L,
+ -3192077522964776200L,
+ -751575299648803575L,
+ 6334581746534596579L,
+ -8358187891202563300L,
+ -1462480609823525055L,
+ 5605961062646987941L,
+ 4968399805931440889L,
+ 7968693270782626653L,
+ -5868205923557518188L,
+ 1830234928743560617L,
+ -8435261076693154407L,
+ 2138416970728681332L,
+ 8088740745199685138L,
+ 806532400344230520L,
+ 1800590379902909333L,
+ -8909128842071238901L,
+ -7357495566969170860L,
+ 3679766664126940553L,
+ 2060050474865839094L,
+ 2363972840121763414L,
+ 525695004292982714L,
+ -1224842191746529593L,
+ 7011317848855545003L,
+ -6337167558180299938L,
+ -5184688833363785939L,
+ -8426673387248359061L,
+ -5035438815930785229L,
+ 3521810320608058994L,
+ 4803742557254962242L,
+ 6623527039545786598L,
+ -1221475882122634738L,
+ -3344794405518401087L,
+ 6510298498414053658L,
+ 2844753907937720338L,
+ 90502309714994895L,
+ -750403235344282494L,
+ -4825474181021465833L,
+ -3405519947983849510L,
+ 3503875590944089793L,
+ 7286294700691822468L,
+ 7828126881500292486L,
+ 8437899353709338096L,
+ 136052254470293480L,
+ 1113259077339995086L,
+ -8244887265606191121L,
+ 8089569503800461649L,
+ -1429698194850157567L,
+ 1575595674002364989L,
+ 3576095286627428675L,
+ -7653655285807569222L,
+ -6053506977362539111L,
+ -3923855345805787169L,
+ -8001149080454232377L,
+ -4382867706931832271L,
+ 4212860258835896297L,
+ 4207674254247034014L,
+ 5519424058779519159L,
+ -754483042161434654L,
+ 1434113479814210082L,
+ -6416645032698336896L,
+ 5624329676066514819L,
+ -8229557208322175959L,
+ 3922640911653270376L,
+ 7826932478782081910L,
+ -4862787164488635842L,
+ 1449234668827944573L,
+ -1781657689570106327L,
+ 5442827552725289699L,
+ 3589862161007644641L,
+ 4787115581650652778L,
+ -3512152721942525726L,
+ -6750103117958685206L,
+ 5012970446659949261L,
+ 6797752795961689017L,
+ 5086454597639943700L,
+ -7616068364979994076L,
+ 1492846825433110217L,
+ 2967476304433704510L,
+ -8413824338284112078L,
+ -1319049442043273974L,
+ -1756090916806844109L,
+ -9061091728950139525L,
+ -6864767830358160810L,
+ 4879532090226251157L,
+ 5528644708740739488L
+ };
+}
diff --git a/datasketches-memory-java8-tests/XxHash64Test.java b/datasketches-memory-java8-tests/XxHash64Test.java
new file mode 100644
index 0000000..9656420
--- /dev/null
+++ b/datasketches-memory-java8-tests/XxHash64Test.java
@@ -0,0 +1,183 @@
+/*
+ * 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.datasketches.memory.internal;
+
+import static org.apache.datasketches.memory.XxHash.*;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertTrue;
+
+import java.util.Random;
+import java.util.concurrent.ThreadLocalRandom;
+
+import org.apache.datasketches.memory.BaseState;
+import org.apache.datasketches.memory.Memory;
+import org.apache.datasketches.memory.WritableMemory;
+import org.testng.annotations.Test;
+
+import net.openhft.hashing.LongHashFunction;
+
+/**
+ * @author Lee Rhodes
+ */
+public class XxHash64Test {
+
+ @Test
+ public void offsetChecks() {
+ long seed = 12345;
+ int blocks = 6;
+ int cap = blocks * 16;
+
+ long hash;
+
+ WritableMemory wmem = WritableMemory.allocate(cap);
+ for (int i = 0; i < cap; i++) { wmem.putByte(i, (byte)(-128 + i)); }
+
+ for (int offset = 0; offset < 16; offset++) {
+ int arrLen = cap - offset;
+ hash = wmem.xxHash64(offset, arrLen, seed);
+ assertTrue(hash != 0);
+ }
+ }
+
+ @Test
+ public void byteArrChecks() {
+ long seed = 0;
+ int offset = 0;
+ int bytes = 16;
+
+ for (int j = 1; j < bytes; j++) {
+ byte[] in = new byte[bytes];
+
+ WritableMemory wmem = WritableMemory.writableWrap(in);
+ for (int i = 0; i < j; i++) { wmem.putByte(i, (byte) (-128 + i)); }
+
+ long hash =wmem.xxHash64(offset, bytes, seed);
+ assertTrue(hash != 0);
+ }
+ }
+
+ /*
+ * This test is adapted from
+ * <a href="https://github.com/OpenHFT/Zero-Allocation-Hashing/blob/master/
+ * src/test/java/net/openhft/hashing/XxHashCollisionTest.java">
+ * OpenHFT/Zero-Allocation-Hashing</a> to test hash compatibility with that implementation.
+ * It is licensed under Apache License, version 2.0. See LICENSE.
+ */
+ @Test
+ public void collisionTest() {
+ WritableMemory wmem = WritableMemory.allocate(128);
+ wmem.putLong(0, 1);
+ wmem.putLong(16, 42);
+ wmem.putLong(32, 2);
+ long h1 = wmem.xxHash64(0, wmem.getCapacity(), 0);
+
+ wmem.putLong(0, 1L + 0xBA79078168D4BAFL);
+ wmem.putLong(32, 2L + 0x9C90005B80000000L);
+ long h2 = wmem.xxHash64(0, wmem.getCapacity(), 0);
+ assertEquals(h1, h2);
+
+ wmem.putLong(0, 1L + (0xBA79078168D4BAFL * 2));
+ wmem.putLong(32, 2L + (0x392000b700000000L)); //= (0x9C90005B80000000L * 2) fix overflow false pos
+
+ long h3 = wmem.xxHash64(0, wmem.getCapacity(), 0);
+ assertEquals(h2, h3);
+ }
+
+ /**
+ * This simple test compares the output of {@link BaseState#xxHash64(long, long, long)} with the
+ * output of {@link net.openhft.hashing.LongHashFunction}, that itself is tested against the
+ * reference implementation in C. This increase confidence that the xxHash function implemented
+ * in this package is in fact the same xxHash function implemented in C.
+ *
+ * @author Roman Leventov
+ * @author Lee Rhodes
+ */
+ @Test
+ public void testXxHash() {
+ Random random = ThreadLocalRandom.current();
+ for (int len = 0; len < 100; len++) {
+ byte[] bytes = new byte[len];
+ for (int i = 0; i < 10; i++) {
+ long zahXxHash = LongHashFunction.xx().hashBytes(bytes);
+ long memoryXxHash = Memory.wrap(bytes).xxHash64(0, len, 0);
+ assertEquals(memoryXxHash, zahXxHash);
+ random.nextBytes(bytes);
+ }
+ }
+ }
+
+ private static final byte[] barr = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};
+
+ @Test
+ public void testArrHashes() {
+ WritableMemory wmem = WritableMemory.writableWrap(barr);
+ long hash0 = wmem.xxHash64(8, 8, 0);
+ long hash1 = hashByteArr(barr, 8, 8, 0);
+ assertEquals(hash1, hash0);
+
+ char[] carr = new char[8];
+ wmem.getCharArray(0, carr, 0, 8);
+ hash1 = hashCharArr(carr, 4, 4, 0);
+ assertEquals(hash1, hash0);
+
+ short[] sarr = new short[8];
+ wmem.getShortArray(0, sarr, 0, 8);
+ hash1 = hashShortArr(sarr, 4, 4, 0);
+ assertEquals(hash1, hash0);
+
+ int[] iarr = new int[4];
+ wmem.getIntArray(0, iarr, 0, 4);
+ hash1 = hashIntArr(iarr, 2, 2, 0);
+ assertEquals(hash1, hash0);
+
+ float[] farr = new float[4];
+ wmem.getFloatArray(0, farr, 0, 4);
+ hash1 = hashFloatArr(farr, 2, 2, 0);
+ assertEquals(hash1, hash0);
+
+ long[] larr = new long[2];
+ wmem.getLongArray(0, larr, 0, 2);
+ hash1 = hashLongArr(larr, 1, 1, 0);
+ long in = wmem.getLong(8);
+ long hash2 = hashLong(in, 00); //tests the single long hash
+ assertEquals(hash1, hash0);
+ assertEquals(hash2, hash0);
+
+ double[] darr = new double[2];
+ wmem.getDoubleArray(0, darr, 0, 2);
+ hash1 = hashDoubleArr(darr, 1, 1, 0);
+ assertEquals(hash1, hash0);
+
+ boolean[] blarr = new boolean[16];
+ wmem.getBooleanArray(0, blarr, 0, 16); //any byte != 0 is true
+ hash1 = hashBooleanArr(blarr, 8, 8, 0);
+ assertEquals(hash1, hash0);
+ }
+
+ @Test
+ public void testString() {
+ String s = "Now is the time for all good men to come to the aid of their country.";
+ char[] arr = s.toCharArray();
+ long hash0 = hashString(s, 0, s.length(), 0);
+ long hash1 = hashCharArr(arr, 0, arr.length, 0);
+ assertEquals(hash1, hash0);
+ }
+
+}
diff --git a/datasketches-memory-java8-tests/ZeroCapacityTest.java b/datasketches-memory-java8-tests/ZeroCapacityTest.java
new file mode 100644
index 0000000..5979e37
--- /dev/null
+++ b/datasketches-memory-java8-tests/ZeroCapacityTest.java
@@ -0,0 +1,68 @@
+/*
+ * 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.datasketches.memory.internal;
+
+import static org.testng.Assert.assertEquals;
+
+import java.nio.ByteBuffer;
+
+import org.apache.datasketches.memory.Memory;
+import org.apache.datasketches.memory.WritableHandle;
+import org.apache.datasketches.memory.WritableMemory;
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+/**
+ * @author Lee Rhodes
+ */
+public class ZeroCapacityTest {
+
+ @Test
+ public void checkZeroCapacity() throws Exception {
+ WritableMemory wmem = WritableMemory.allocate(0);
+ assertEquals(wmem.getCapacity(), 0);
+
+ Memory.wrap(new byte[0]);
+ Memory.wrap(ByteBuffer.allocate(0));
+ Memory mem3 = Memory.wrap(ByteBuffer.allocateDirect(0));
+ mem3.region(0, 0);
+ WritableHandle wh = null;
+ try {
+ wh = WritableMemory.allocateDirect(0);
+ Assert.fail();
+ } catch (IllegalArgumentException ignore) {
+ if (wh != null) { wh.close(); }
+ // expected
+ }
+ }
+
+ @Test
+ public void printlnTest() {
+ //println("PRINTING: "+this.getClass().getName());
+ }
+
+ /**
+ * @param s value to print
+ */
+ static void println(String s) {
+ //System.out.println(s); //disable here
+ }
+
+}
diff --git a/datasketches-memory-java8-tests/src/test/java/org/apache/datasketches/memory/test/AllocateDirectMapMemoryTest.java b/datasketches-memory-java8-tests/src/test/java/org/apache/datasketches/memory/test/AllocateDirectMapMemoryTest.java
new file mode 100644
index 0000000..e33d8ad
--- /dev/null
+++ b/datasketches-memory-java8-tests/src/test/java/org/apache/datasketches/memory/test/AllocateDirectMapMemoryTest.java
@@ -0,0 +1,170 @@
+/*
+ * 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.test;
+
+import static org.apache.datasketches.memory.internal.Util.*;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertFalse;
+import static org.testng.Assert.assertTrue;
+import static org.testng.Assert.fail;
+
+import java.io.File;
+import java.nio.ByteOrder;
+
+import org.apache.datasketches.memory.MapHandle;
+import org.apache.datasketches.memory.Memory;
+import org.testng.annotations.AfterClass;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+public class AllocateDirectMapMemoryTest {
+ private static final String LS = System.getProperty("line.separator");
+ MapHandle hand = null;
+
+ @BeforeClass
+ public void setReadOnly() {
+ UtilTest.setGettysburgAddressFileToReadOnly();
+ }
+
+ @Test
+ public void simpleMap() throws Exception {
+ File file = getResourceFile("GettysburgAddress.txt");
+ assertTrue(ReflectUtil.isFileReadOnly(file));
+ try (MapHandle rh = Memory.map(file)) {
+ rh.close();
+ }
+ }
+
+ @Test
+ public void testIllegalArguments() throws Exception {
+ File file = getResourceFile("GettysburgAddress.txt");
+ try (MapHandle rh = Memory.map(file, -1, Integer.MAX_VALUE, ByteOrder.nativeOrder())) {
+ fail("Failed: testIllegalArgumentException: Position was negative.");
+ } catch (IllegalArgumentException e) {
+ //ok
+ }
+
+ try (MapHandle rh = Memory.map(file, 0, -1, ByteOrder.nativeOrder())) {
+ fail("Failed: testIllegalArgumentException: Size was negative.");
+ } catch (IllegalArgumentException e) {
+ //ok
+ }
+ }
+
+ @Test
+ public void testMapAndMultipleClose() throws Exception {
+ File file = getResourceFile("GettysburgAddress.txt");
+ long memCapacity = file.length();
+ try (MapHandle rh = Memory.map(file, 0, memCapacity, ByteOrder.nativeOrder())) {
+ Memory map = rh.get();
+ assertEquals(memCapacity, map.getCapacity());
+ rh.close();
+ rh.close();
+ map.getCapacity(); //throws assertion error
+ } catch (AssertionError e) {
+ //OK
+ }
+ }
+
+ @Test
+ public void testReadFailAfterClose() throws Exception {
+ File file = getResourceFile("GettysburgAddress.txt");
+ long memCapacity = file.length();
+ try (MapHandle rh = Memory.map(file, 0, memCapacity, ByteOrder.nativeOrder())) {
+ Memory mmf = rh.get();
+ rh.close();
+ mmf.getByte(0);
+ } catch (AssertionError e) {
+ //OK
+ }
+ }
+
+ @Test
+ public void testLoad() throws Exception {
+ File file = getResourceFile("GettysburgAddress.txt");
+ long memCapacity = file.length();
+ try (MapHandle rh = Memory.map(file, 0, memCapacity, ByteOrder.nativeOrder())) {
+ rh.load();
+ assertTrue(rh.isLoaded());
+ rh.close();
+ }
+ }
+
+ @Test
+ public void testHandlerHandoffWithTWR() throws Exception {
+ File file = getResourceFile("GettysburgAddress.txt");
+ long memCapacity = file.length();
+ Memory mem;
+ try (MapHandle rh = Memory.map(file, 0, memCapacity, ByteOrder.nativeOrder())) {
+ rh.load();
+ assertTrue(rh.isLoaded());
+ hand = rh;
+ mem = rh.get();
+ } //TWR closes
+ assertFalse(mem.isValid());
+ //println(""+mem.isValid());
+ }
+
+ @Test
+ public void testHandoffWithoutClose() throws Exception {
+ File file = getResourceFile("GettysburgAddress.txt");
+ long memCapacity = file.length();
+ MapHandle rh = Memory.map(file, 0, memCapacity, ByteOrder.nativeOrder());
+ rh.load();
+ assertTrue(rh.isLoaded());
+ hand = rh;
+ //The receiver of the handler must close the resource, in this case it is the class.
+ }
+
+ @AfterClass
+ public void afterAllTests() throws Exception {
+ if (hand != null) {
+ Memory mem = hand.get();
+ if ((mem != null) && mem.isValid()) {
+ hand.close();
+ assertFalse(mem.isValid());
+ }
+ }
+ }
+
+ @Test
+ public void printlnTest() {
+ println("PRINTING: "+this.getClass().getName());
+ }
+
+ static void println(final Object o) {
+ if (o == null) { print(LS); }
+ else { print(o.toString() + LS); }
+ }
+
+ /**
+ * @param o value to print
+ */
+ static void print(final Object o) {
+ if (o != null) {
+ //System.out.print(o.toString()); //disable here
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/AllocateDirectMemoryTest.java b/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/AllocateDirectMemoryTest.java
index f14e3ec..7ebe3e5 100644
--- a/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/AllocateDirectMemoryTest.java
+++ b/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/AllocateDirectMemoryTest.java
@@ -23,12 +23,11 @@ import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertFalse;
import static org.testng.Assert.fail;
-import static org.apache.datasketches.memory.BaseState.*;
+import org.apache.datasketches.memory.BaseState;
import org.apache.datasketches.memory.DefaultMemoryRequestServer;
import org.apache.datasketches.memory.MemoryRequestServer;
import org.apache.datasketches.memory.WritableHandle;
import org.apache.datasketches.memory.WritableMemory;
-import org.apache.datasketches.memory.internal.Util;
import org.testng.annotations.AfterClass;
import org.testng.annotations.Test;
@@ -45,12 +44,12 @@ public class AllocateDirectMemoryTest {
assertEquals(wMem.getLong(i << 3), i);
}
//inside the TWR block the memory should be valid
- BaseState.checkValid(wMem);
+ ((BaseStateImpl)wMem).checkValid();
//OK
}
//The TWR block has exited, so the memory should be invalid
try {
- ReflectUtil.checkValid(wMem);
+ ((BaseStateImpl)wMem).checkValid();
fail();
} catch (final RuntimeException e) {
//OK
diff --git a/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/AllocateDirectWritableMapMemoryTest.java b/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/AllocateDirectWritableMapMemoryTest.java
new file mode 100644
index 0000000..9cecaaa
--- /dev/null
+++ b/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/AllocateDirectWritableMapMemoryTest.java
@@ -0,0 +1,253 @@
+/*
+ * 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.internal;
+
+import static java.nio.charset.StandardCharsets.UTF_8;
+import static org.apache.datasketches.memory.internal.Util.getResourceFile;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertTrue;
+import static org.testng.Assert.fail;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.io.UnsupportedEncodingException;
+import java.nio.ByteOrder;
+
+import org.apache.datasketches.memory.BaseState;
+import org.apache.datasketches.memory.MapHandle;
+import org.apache.datasketches.memory.Memory;
+import org.apache.datasketches.memory.ReadOnlyException;
+import org.apache.datasketches.memory.WritableHandle;
+import org.apache.datasketches.memory.WritableMapHandle;
+import org.apache.datasketches.memory.WritableMemory;
+import org.testng.annotations.AfterClass;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+public class AllocateDirectWritableMapMemoryTest {
+ private static final String LS = System.getProperty("line.separator");
+
+ @BeforeClass
+ public void setReadOnly() {
+ UtilTest.setGettysburgAddressFileToReadOnly();
+ }
+
+ @Test
+ public void simpleMap() throws Exception {
+ File file = getResourceFile("GettysburgAddress.txt");
+ try (MapHandle h = Memory.map(file); WritableMapHandle wh = (WritableMapHandle) h) {
+ Memory mem = h.get();
+ byte[] bytes = new byte[(int)mem.getCapacity()];
+ mem.getByteArray(0, bytes, 0, bytes.length);
+ String text = new String(bytes, UTF_8);
+ println(text);
+ try {
+ wh.force();
+ fail();
+ } catch (ReadOnlyException e) {
+ //OK
+ }
+ }
+ }
+
+ @Test
+ public void copyOffHeapToMemoryMappedFile() throws Exception {
+ long bytes = 1L << 10; //small for unit tests. Make it larger than 2GB if you like.
+ long longs = bytes >>> 3;
+
+ File file = new File("TestFile.bin");
+ if (file.exists()) {
+ try {
+ java.nio.file.Files.delete(file.toPath());
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+ assertTrue(file.createNewFile());
+ assertTrue (file.setWritable(true, false)); //writable=true, ownerOnly=false
+ assertTrue (file.isFile());
+ file.deleteOnExit(); //comment out if you want to examine the file.
+
+ try (
+ WritableMapHandle dstHandle
+ = WritableMemory.writableMap(file, 0, bytes, ByteOrder.nativeOrder());
+ WritableHandle srcHandle = WritableMemory.allocateDirect(bytes)) {
+
+ WritableMemory dstMem = dstHandle.getWritable();
+ WritableMemory srcMem = srcHandle.getWritable();
+
+ for (long i = 0; i < longs; i++) {
+ srcMem.putLong(i << 3, i); //load source with consecutive longs
+ }
+
+ srcMem.copyTo(0, dstMem, 0, srcMem.getCapacity()); //off-heap to off-heap copy
+
+ dstHandle.force(); //push any remaining to the file
+
+ //check end value
+ assertEquals(dstMem.getLong(longs - 1L << 3), longs - 1L);
+ }
+ }
+
+ @Test
+ public void checkNonNativeFile() throws Exception {
+ File file = new File("TestFile2.bin");
+ if (file.exists()) {
+ try {
+ java.nio.file.Files.delete(file.toPath());
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+ assertTrue(file.createNewFile());
+ assertTrue(file.setWritable(true, false)); //writable=true, ownerOnly=false
+ assertTrue(file.isFile());
+ file.deleteOnExit(); //comment out if you want to examine the file.
+
+ final long bytes = 8;
+ try (WritableMapHandle h = WritableMemory.writableMap(file, 0L, bytes, Util.NON_NATIVE_BYTE_ORDER)) {
+ WritableMemory wmem = h.getWritable();
+ wmem.putChar(0, (char) 1);
+ assertEquals(wmem.getByte(1), (byte) 1);
+ }
+ }
+
+ @Test(expectedExceptions = RuntimeException.class)
+ public void testMapException() throws IOException {
+ File dummy = createFile("dummy.txt", ""); //zero length
+ //throws java.lang.reflect.InvocationTargetException
+ Memory.map(dummy, 0, dummy.length(), ByteOrder.nativeOrder());
+ }
+
+ @Test(expectedExceptions = ReadOnlyException.class)
+ public void simpleMap2() throws Exception {
+ File file = getResourceFile("GettysburgAddress.txt");
+ assertTrue(file.canRead() && !file.canWrite());
+ try (WritableMapHandle rh =
+ WritableMemory.writableMap(file)) { //throws
+ //
+ }
+ }
+
+ @Test(expectedExceptions = ReadOnlyException.class)
+ public void checkOverLength() throws Exception {
+ File file = getResourceFile("GettysburgAddress.txt");
+ try (WritableMapHandle rh =
+ WritableMemory.writableMap(file, 0, 1 << 20, ByteOrder.nativeOrder())) {
+ //
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ @Test
+ public void testForce() throws Exception {
+ String origStr = "Corectng spellng mistks";
+ File origFile = createFile("force_original.txt", origStr); //23
+ assertTrue(origFile.setWritable(true, false));
+ long origBytes = origFile.length();
+ String correctStr = "Correcting spelling mistakes"; //28
+ byte[] correctByteArr = correctStr.getBytes(UTF_8);
+ long corrBytes = correctByteArr.length;
+
+ try (MapHandle rh = Memory.map(origFile, 0, origBytes, ByteOrder.nativeOrder())) {
+ Memory map = rh.get();
+ rh.load();
+ assertTrue(rh.isLoaded());
+ //confirm orig string
+ byte[] buf = new byte[(int)origBytes];
+ map.getByteArray(0, buf, 0, (int)origBytes);
+ String bufStr = new String(buf, UTF_8);
+ assertEquals(bufStr, origStr);
+ }
+
+ try (WritableMapHandle wrh = WritableMemory.writableMap(origFile, 0, corrBytes,
+ ByteOrder.nativeOrder())) {
+ WritableMemory wMap = wrh.getWritable();
+ wrh.load();
+ assertTrue(wrh.isLoaded());
+ // over write content
+ wMap.putByteArray(0, correctByteArr, 0, (int)corrBytes);
+ wrh.force();
+ //confirm correct string
+ byte[] buf = new byte[(int)corrBytes];
+ wMap.getByteArray(0, buf, 0, (int)corrBytes);
+ String bufStr = new String(buf, UTF_8);
+ assertEquals(bufStr, correctStr);
+ }
+ }
+
+ private static File createFile(String fileName, String text) throws FileNotFoundException {
+ File file = new File(fileName);
+ file.deleteOnExit();
+ PrintWriter writer;
+ try {
+ writer = new PrintWriter(file, UTF_8.name());
+ writer.print(text);
+ writer.close();
+ } catch (UnsupportedEncodingException e) {
+ e.printStackTrace();
+ }
+ return file;
+ }
+
+ @Test
+ public void checkExplicitClose() throws Exception {
+ File file = getResourceFile("GettysburgAddress.txt");
+ try (MapHandle wmh = Memory.map(file)) {
+ wmh.close(); //explicit close.
+ } //end of scope call to Cleaner/Deallocator also will be redundant
+ }
+
+ @AfterClass
+ public void checkDirectCounter() {
+ long count = BaseState.getCurrentDirectMemoryMapAllocations();
+ if (count != 0) {
+ println(""+count);
+ fail();
+ }
+ }
+
+ @Test
+ public void printlnTest() {
+ println("PRINTING: "+this.getClass().getName());
+ }
+
+ static void println(final Object o) {
+ if (o == null) { print(LS); }
+ else { print(o.toString() + LS); }
+ }
+
+ /**
+ * @param o value to print
+ */
+ static void print(final Object o) {
+ if (o != null) {
+ //System.out.print(o.toString()); //disable here
+ }
+ }
+
+}
diff --git a/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/BaseBufferTest.java b/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/BaseBufferTest.java
new file mode 100644
index 0000000..4e8bfff
--- /dev/null
+++ b/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/BaseBufferTest.java
@@ -0,0 +1,89 @@
+/*
+ * 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.datasketches.memory.internal;
+
+import static org.testng.Assert.fail;
+
+import org.apache.datasketches.memory.Buffer;
+import org.apache.datasketches.memory.Memory;
+import org.apache.datasketches.memory.WritableHandle;
+import org.apache.datasketches.memory.WritableMemory;
+import org.testng.annotations.Test;
+
+/**
+ * @author Lee Rhodes
+ */
+public class BaseBufferTest {
+
+ @Test
+ public void checkLimits() {
+ Buffer buf = Memory.wrap(new byte[100]).asBuffer();
+ buf.setStartPositionEnd(40, 45, 50);
+ buf.setStartPositionEnd(0, 0, 100);
+ try {
+ buf.setStartPositionEnd(0, 0, 101);
+ fail();
+ } catch (AssertionError e) {
+ //ok
+ }
+ }
+
+ @Test
+ public void checkLimitsAndCheck() {
+ Buffer buf = Memory.wrap(new byte[100]).asBuffer();
+ buf.setAndCheckStartPositionEnd(40, 45, 50);
+ buf.setAndCheckStartPositionEnd(0, 0, 100);
+ try {
+ buf.setAndCheckStartPositionEnd(0, 0, 101);
+ fail();
+ } catch (IllegalArgumentException e) {
+ //ok
+ }
+ buf.setAndCheckPosition(100);
+ try {
+ buf.setAndCheckPosition(101);
+ fail();
+ } catch (IllegalArgumentException e) {
+ //ok
+ }
+ buf.setPosition(99);
+ buf.incrementAndCheckPosition(1L);
+ try {
+ buf.incrementAndCheckPosition(1L);
+ fail();
+ } catch (IllegalArgumentException e) {
+ //ok
+ }
+ }
+
+ @Test
+ public void checkCheckValid() throws Exception {
+ WritableMemory wmem;
+ Buffer buf;
+ try (WritableHandle hand = WritableMemory.allocateDirect(100)) {
+ wmem = hand.getWritable();
+ buf = wmem.asBuffer();
+ }
+ try {
+ @SuppressWarnings("unused")
+ Memory mem = buf.asMemory();
+ } catch (AssertionError ae) { }
+ }
+}
diff --git a/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/BaseStateTest.java b/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/BaseStateTest.java
new file mode 100644
index 0000000..430dfa1
--- /dev/null
+++ b/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/BaseStateTest.java
@@ -0,0 +1,142 @@
+/*
+ * 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.datasketches.memory.internal;
+
+import static org.apache.datasketches.memory.internal.UnsafeUtil.ARRAY_DOUBLE_INDEX_SCALE;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertFalse;
+import static org.testng.Assert.assertTrue;
+import static org.testng.Assert.fail;
+
+import java.nio.ByteOrder;
+
+import org.apache.datasketches.memory.Buffer;
+import org.apache.datasketches.memory.Memory;
+import org.apache.datasketches.memory.WritableBuffer;
+import org.apache.datasketches.memory.WritableMemory;
+import org.testng.annotations.Test;
+
+public class BaseStateTest {
+
+ @Test
+ public void checkPrimOffset() {
+ int off = (int)Prim.BYTE.off();
+ assertTrue(off > 0);
+ }
+
+ @Test
+ public void checkIsSameResource() {
+ WritableMemory wmem = WritableMemory.allocate(16);
+ Memory mem = wmem;
+ assertFalse(wmem.isSameResource(null));
+ assertTrue(wmem.isSameResource(mem));
+
+ WritableBuffer wbuf = wmem.asWritableBuffer();
+ Buffer buf = wbuf;
+ assertFalse(wbuf.isSameResource(null));
+ assertTrue(wbuf.isSameResource(buf));
+ }
+
+ @Test
+ public void checkNotEqualTo() {
+ byte[] arr = new byte[8];
+ Memory mem = Memory.wrap(arr);
+ assertFalse(mem.equalTo(0, arr, 0, 8));
+ }
+
+ //StepBoolean checks
+ @Test
+ public void checkStepBoolean() {
+ checkStepBoolean(true);
+ checkStepBoolean(false);
+ }
+
+ private static void checkStepBoolean(boolean initialState) {
+ StepBoolean step = new StepBoolean(initialState);
+ assertTrue(step.get() == initialState); //confirm initialState
+ step.change();
+ assertTrue(step.hasChanged()); //1st change was successful
+ assertTrue(step.get() != initialState); //confirm it is different from initialState
+ step.change();
+ assertTrue(step.get() != initialState); //Still different from initialState
+ assertTrue(step.hasChanged()); //confirm it was changed from initialState value
+ }
+
+ @Test
+ public void checkPrim() {
+ assertEquals(Prim.DOUBLE.scale(), ARRAY_DOUBLE_INDEX_SCALE);
+ }
+
+ @Test
+ public void checkGetNativeBaseOffset_Heap() throws Exception {
+ WritableMemory wmem = WritableMemory.allocate(8); //heap
+ final long offset = ((BaseStateImpl)wmem).getNativeBaseOffset();
+ assertEquals(offset, 0L);
+ }
+
+ @Test
+ public void checkIsByteOrderCompatible() {
+ WritableMemory wmem = WritableMemory.allocate(8);
+ assertTrue(wmem.isByteOrderCompatible(ByteOrder.nativeOrder()));
+ }
+
+ @Test(expectedExceptions = IllegalArgumentException.class)
+ public void checkByteOrderNull() {
+ Util.isNativeByteOrder(null);
+ fail();
+ }
+
+ @Test
+ public void checkIsNativeByteOrder() {
+ assertTrue(BaseStateImpl.isNativeByteOrder(ByteOrder.nativeOrder()));
+ try {
+ BaseStateImpl.isNativeByteOrder(null);
+ fail();
+ } catch (final IllegalArgumentException e) {}
+ }
+
+ @Test
+ public void checkXxHash64() {
+ WritableMemory mem = WritableMemory.allocate(8);
+ long out = mem.xxHash64(mem.getLong(0), 1L);
+ assertTrue(out != 0);
+ }
+
+ @Test
+ public void checkTypeDecode() {
+ for (int i = 0; i < 128; i++) {
+ BaseStateImpl.typeDecode(i);
+ }
+ }
+
+ /********************/
+ @Test
+ public void printlnTest() {
+ println("PRINTING: "+this.getClass().getName());
+ }
+
+ /**
+ * @param s value to print
+ */
+ static void println(String s) {
+ //System.out.println(s); //disable here
+ }
+
+}
diff --git a/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/Buffer2Test.java b/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/Buffer2Test.java
new file mode 100644
index 0000000..e625cb4
--- /dev/null
+++ b/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/Buffer2Test.java
@@ -0,0 +1,462 @@
+/*
+ * 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.datasketches.memory.internal;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertFalse;
+import static org.testng.Assert.assertNotNull;
+import static org.testng.Assert.assertTrue;
+
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+
+import org.apache.datasketches.memory.Buffer;
+import org.apache.datasketches.memory.DefaultMemoryRequestServer;
+import org.apache.datasketches.memory.Memory;
+import org.apache.datasketches.memory.ReadOnlyException;
+import org.apache.datasketches.memory.WritableBuffer;
+import org.apache.datasketches.memory.WritableMemory;
+import org.testng.annotations.Test;
+
+public class Buffer2Test {
+
+ @Test
+ public void testWrapByteBuf() {
+ ByteBuffer bb = ByteBuffer.allocate(64).order(ByteOrder.nativeOrder());
+
+ Byte b = 0;
+ while (bb.hasRemaining()) {
+ bb.put(b);
+ b++;
+ }
+ bb.position(0);
+
+ Buffer buffer = Buffer.wrap(bb.asReadOnlyBuffer().order(ByteOrder.nativeOrder()));
+ while (buffer.hasRemaining()) {
+ assertEquals(bb.get(), buffer.getByte());
+ }
+
+ assertEquals(true, buffer.hasArray());
+ assertEquals(true, buffer.hasByteBuffer());
+ }
+
+ @Test
+ public void testWrapDirectBB() {
+ ByteBuffer bb = ByteBuffer.allocateDirect(64).order(ByteOrder.nativeOrder());
+
+ Byte b = 0;
+ while (bb.hasRemaining()) {
+ bb.put(b);
+ b++;
+ }
+ bb.position(0);
+
+ Buffer buffer = Buffer.wrap(bb);
+ while (buffer.hasRemaining()) {
+ assertEquals(bb.get(), buffer.getByte());
+ }
+
+ assertEquals(false, buffer.hasArray());
+ assertEquals(true, buffer.hasByteBuffer());
+ }
+
+ @Test
+ public void testWrapByteArray() {
+ byte[] byteArray = new byte[64];
+
+ for (byte i = 0; i < 64; i++) {
+ byteArray[i] = i;
+ }
+
+ Buffer buffer = Memory.wrap(byteArray).asBuffer();
+ int i = 0;
+ while (buffer.hasRemaining()) {
+ assertEquals(byteArray[i++], buffer.getByte());
+ }
+
+ buffer.setPosition(0);
+ byte[] copyByteArray = new byte[64];
+ buffer.getByteArray(copyByteArray, 0, 64);
+ assertEquals(byteArray, copyByteArray);
+
+ assertEquals(true, buffer.hasArray());
+ assertEquals(false, buffer.hasByteBuffer());
+ }
+
+ @Test
+ public void testWrapCharArray() {
+ char[] charArray = new char[64];
+
+ for (char i = 0; i < 64; i++) {
+ charArray[i] = i;
+ }
+
+ Buffer buffer = Memory.wrap(charArray).asBuffer();
+ int i = 0;
+ while (buffer.hasRemaining()) {
+ assertEquals(charArray[i++], buffer.getChar());
+ }
+
+ buffer.setPosition(0);
+ char[] copyCharArray = new char[64];
+ buffer.getCharArray(copyCharArray, 0, 64);
+ assertEquals(charArray, copyCharArray);
+ }
+
+ @Test
+ public void testWrapShortArray() {
+ short[] shortArray = new short[64];
+
+ for (short i = 0; i < 64; i++) {
+ shortArray[i] = i;
+ }
+
+ Buffer buffer = Memory.wrap(shortArray).asBuffer();
+ int i = 0;
+ while (buffer.hasRemaining()) {
+ assertEquals(shortArray[i++], buffer.getShort());
+ }
+
+ buffer.setPosition(0);
+ short[] copyShortArray = new short[64];
+ buffer.getShortArray(copyShortArray, 0, 64);
+ assertEquals(shortArray, copyShortArray);
+ }
+
+ @Test
+ public void testWrapIntArray() {
+ int[] intArray = new int[64];
+
+ for (int i = 0; i < 64; i++) {
+ intArray[i] = i;
+ }
+
+ Buffer buffer = Memory.wrap(intArray).asBuffer();
+ int i = 0;
+ while (buffer.hasRemaining()) {
+ assertEquals(intArray[i++], buffer.getInt());
+ }
+
+ buffer.setPosition(0);
+ int[] copyIntArray = new int[64];
+ buffer.getIntArray(copyIntArray, 0, 64);
+ assertEquals(intArray, copyIntArray);
+ }
+
+ @Test
+ public void testWrapLongArray() {
+ long[] longArray = new long[64];
+
+ for (int i = 0; i < 64; i++) {
+ longArray[i] = i;
+ }
+
+ Buffer buffer = Memory.wrap(longArray).asBuffer();
+ int i = 0;
+ while (buffer.hasRemaining()) {
+ assertEquals(longArray[i++], buffer.getLong());
+ }
+
+ buffer.setPosition(0);
+ long[] copyLongArray = new long[64];
+ buffer.getLongArray(copyLongArray, 0, 64);
+ assertEquals(longArray, copyLongArray);
+ }
+
+ @Test
+ public void testWrapFloatArray() {
+ float[] floatArray = new float[64];
+
+ for (int i = 0; i < 64; i++) {
+ floatArray[i] = i;
+ }
+
+ Buffer buffer = Memory.wrap(floatArray).asBuffer();
+ int i = 0;
+ while (buffer.hasRemaining()) {
+ assertEquals(floatArray[i++], buffer.getFloat());
+ }
+
+ buffer.setPosition(0);
+ float[] copyFloatArray = new float[64];
+ buffer.getFloatArray(copyFloatArray, 0, 64);
+ assertEquals(floatArray, copyFloatArray);
+ }
+
+ @Test
+ public void testWrapDoubleArray() {
+ double[] doubleArray = new double[64];
+
+ for (int i = 0; i < 64; i++) {
+ doubleArray[i] = i;
+ }
+
+ Buffer buffer = Memory.wrap(doubleArray).asBuffer();
+ int i = 0;
+ while (buffer.hasRemaining()) {
+ assertEquals(doubleArray[i++], buffer.getDouble());
+ }
+
+ buffer.setPosition(0);
+ double[] copyDoubleArray = new double[64];
+ buffer.getDoubleArray(copyDoubleArray, 0, 64);
+ assertEquals(doubleArray, copyDoubleArray);
+ }
+
+ @Test
+ public void testWrapBooleanArray() {
+ boolean[] booleanArray = new boolean[64];
+
+ for (int i = 0; i < 64; i++) {
+ if ((i % 3) == 0) {
+ booleanArray[i] = true;
+ }
+ }
+
+ Buffer buffer = Memory.wrap(booleanArray).asBuffer();
+ int i = 0;
+ while (buffer.hasRemaining()) {
+ assertEquals(booleanArray[i++], buffer.getBoolean());
+ }
+
+ buffer.setPosition(0);
+ boolean[] copyBooleanArray = new boolean[64];
+ buffer.getBooleanArray(copyBooleanArray, 0, 64);
+ for (int j = 0; j < copyBooleanArray.length; j++) {
+ assertEquals(booleanArray[j], copyBooleanArray[j]);
+ }
+ }
+
+ @Test
+ public void testByteBufferPositionPreservation() {
+ ByteBuffer bb = ByteBuffer.allocate(64).order(ByteOrder.nativeOrder());
+
+ Byte b = 0;
+ while (bb.hasRemaining()) {
+ bb.put(b);
+ b++;
+ }
+ bb.position(10);
+
+ Buffer buffer = Buffer.wrap(bb);
+ while (buffer.hasRemaining()) {
+ assertEquals(bb.get(), buffer.getByte());
+ }
+ }
+
+ @Test
+ public void testGetAndHasRemaining() {
+ ByteBuffer bb = ByteBuffer.allocate(64).order(ByteOrder.nativeOrder());
+
+ Byte b = 0;
+ while (bb.hasRemaining()) {
+ bb.put(b);
+ b++;
+ }
+ bb.position(10);
+
+ Buffer buffer = Buffer.wrap(bb);
+ assertEquals(bb.hasRemaining(), buffer.hasRemaining());
+ assertEquals(bb.remaining(), buffer.getRemaining());
+ }
+
+ @Test
+ public void testGetSetIncResetPosition() {
+ ByteBuffer bb = ByteBuffer.allocate(64).order(ByteOrder.nativeOrder());
+
+ Byte b = 0;
+ while (bb.hasRemaining()) {
+ bb.put(b);
+ b++;
+ }
+ bb.position(10);
+
+ Buffer buffer = Buffer.wrap(bb);
+ assertEquals(bb.position(), buffer.getPosition());
+ assertEquals(30, buffer.setPosition(30).getPosition());
+ assertEquals(40, buffer.incrementPosition(10).getPosition());
+ assertEquals(0, buffer.resetPosition().getPosition());
+ }
+
+ @Test
+ public void testByteBufferSlice() {
+ ByteBuffer bb = ByteBuffer.allocate(64).order(ByteOrder.nativeOrder());
+
+ Byte b = 0;
+ while (bb.hasRemaining()) {
+ bb.put(b);
+ b++;
+ }
+ bb.position(10);
+
+ Buffer buffer = Buffer.wrap(bb.slice().order(ByteOrder.nativeOrder()));
+ while (buffer.hasRemaining()) {
+ assertEquals(bb.get(), buffer.getByte());
+ }
+
+ assertEquals(bb.position(), buffer.getPosition() + 10);
+ assertEquals(30, buffer.setPosition(30).getPosition());
+ assertEquals(40, buffer.incrementPosition(10).getPosition());
+ assertEquals(0, buffer.resetPosition().getPosition());
+ }
+
+ @Test
+ public void testDuplicateAndRegion() {
+ ByteBuffer bb = ByteBuffer.allocate(64).order(ByteOrder.nativeOrder());
+
+ Byte b = 0;
+ while (bb.hasRemaining()) {
+ bb.put(b);
+ b++;
+ }
+ bb.position(10);
+
+ Buffer buffer = Buffer.wrap(bb.slice().order(ByteOrder.nativeOrder())); //slice = 54
+ buffer.setPosition(30);//remaining = 24
+ Buffer dupBuffer = buffer.duplicate(); //all 54
+ Buffer regionBuffer = buffer.region(); //24
+
+ assertEquals(dupBuffer.getStart(), buffer.getStart());
+ assertEquals(regionBuffer.getStart(), buffer.getStart());
+ assertEquals(dupBuffer.getEnd(), buffer.getEnd());
+ assertEquals(regionBuffer.getEnd(), buffer.getRemaining());
+ assertEquals(dupBuffer.getPosition(), buffer.getPosition());
+ assertEquals(regionBuffer.getPosition(), 0);
+ assertEquals(dupBuffer.getCapacity(), buffer.getCapacity());
+ assertEquals(regionBuffer.getCapacity(), buffer.getCapacity() - 30);
+ }
+
+ @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);
+ Buffer buf = mem.asBuffer();
+ Buffer reg = buf.region(n2 * 8, n2 * 8, buf.getTypeByteOrder()); //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 testAsMemory() {
+ ByteBuffer bb = ByteBuffer.allocate(64).order(ByteOrder.nativeOrder());
+
+ Byte b = 0;
+ while (bb.hasRemaining()) {
+ bb.put(b);
+ b++;
+ }
+ bb.position(10);
+
+ Buffer buffer = Buffer.wrap(bb);
+ Memory memory = buffer.asMemory();
+
+ assertEquals(buffer.getCapacity(), memory.getCapacity());
+
+ while(buffer.hasRemaining()){
+ assertEquals(memory.getByte(buffer.getPosition()), buffer.getByte());
+ }
+ }
+
+ @Test(expectedExceptions = AssertionError.class)
+ public void testROByteBuffer() {
+ byte[] arr = new byte[64];
+ ByteBuffer roBB = ByteBuffer.wrap(arr).asReadOnlyBuffer();
+ Buffer buf = Buffer.wrap(roBB);
+ WritableBuffer wbuf = (WritableBuffer) buf;
+ wbuf.putByte(0, (byte) 1);
+ }
+
+ @Test(expectedExceptions = ReadOnlyException.class)
+ public void testROByteBuffer2() {
+ byte[] arr = new byte[64];
+ ByteBuffer roBB = ByteBuffer.wrap(arr).asReadOnlyBuffer();
+ Buffer buf = Buffer.wrap(roBB);
+ WritableBuffer wbuf = (WritableBuffer) buf;
+ wbuf.putByteArray(arr, 0, 64);
+ }
+
+ @Test(expectedExceptions = ReadOnlyException.class)
+ public void testIllegalFill() {
+ byte[] arr = new byte[64];
+ ByteBuffer roBB = ByteBuffer.wrap(arr).asReadOnlyBuffer();
+ Buffer buf = Buffer.wrap(roBB);
+ WritableBuffer wbuf = (WritableBuffer) buf;
+ wbuf.fill((byte)0);
+ }
+
+ @Test
+ public void checkWritableWrap() {
+ ByteBuffer bb = ByteBuffer.allocate(16);
+ WritableBuffer buf = WritableBuffer.writableWrap(bb, ByteOrder.nativeOrder(), null);
+ assertNotNull(buf);
+ buf = WritableBuffer.writableWrap(bb, ByteOrder.nativeOrder(), new DefaultMemoryRequestServer());
+ assertNotNull(buf);
+ }
+
+ @Test
+ public void testWritableDuplicate() {
+ WritableMemory wmem = WritableMemory.writableWrap(new byte[1]);
+ WritableBuffer wbuf = wmem.asWritableBuffer();
+ WritableBuffer wbuf2 = wbuf.writableDuplicate();
+ assertEquals(wbuf2.getCapacity(), 1);
+ Buffer buf = wmem.asBuffer();
+ assertEquals(buf.getCapacity(), 1);
+ }
+
+ @Test
+ public void checkIndependence() {
+ int cap = 64;
+ WritableMemory wmem = WritableMemory.allocate(cap);
+ WritableBuffer wbuf1 = wmem.asWritableBuffer();
+ WritableBuffer wbuf2 = wmem.asWritableBuffer();
+ assertFalse(wbuf1 == wbuf2);
+ assertTrue(wbuf1.isSameResource(wbuf2));
+
+ WritableMemory reg1 = wmem.writableRegion(0, cap);
+ WritableMemory reg2 = wmem.writableRegion(0, cap);
+ assertFalse(reg1 == reg2);
+ assertTrue(reg1.isSameResource(reg2));
+
+
+ WritableBuffer wbuf3 = wbuf1.writableRegion();
+ WritableBuffer wbuf4 = wbuf1.writableRegion();
+ assertFalse(wbuf3 == wbuf4);
+ assertTrue(wbuf3.isSameResource(wbuf4));
+ }
+
+ @Test
+ public void printlnTest() {
+ println("PRINTING: "+this.getClass().getName());
+ }
+
+ /**
+ * @param s value to print
+ */
+ static void println(String s) {
+ //System.out.println(s); //disable here
+ }
+
+}
diff --git a/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/BufferBoundaryCheckTest.java b/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/BufferBoundaryCheckTest.java
new file mode 100644
index 0000000..535b0ca
--- /dev/null
+++ b/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/BufferBoundaryCheckTest.java
@@ -0,0 +1,237 @@
+/*
+ * 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.datasketches.memory.internal;
+
+import org.apache.datasketches.memory.WritableMemory;
+import org.testng.annotations.Test;
+
+public class BufferBoundaryCheckTest {
+
+ private final WritableMemory writableMemory = WritableMemory.allocate(8);
+
+ @Test
+ public void testGetBoolean() {
+ writableMemory.getBoolean(7);
+ try {
+ writableMemory.getBoolean(8);
+ throw new RuntimeException("Expected AssertionError");
+ } catch (final AssertionError expected) {
+ // ignore
+ }
+ }
+
+ @Test
+ public void testPutBoolean() {
+ writableMemory.putBoolean(7, true);
+ try {
+ writableMemory.putBoolean(8, true);
+ throw new RuntimeException("Expected AssertionError");
+ } catch (final AssertionError expected) {
+ // ignore
+ }
+ }
+
+ @Test
+ public void testGetByte() {
+ writableMemory.getByte(7);
+ try {
+ writableMemory.getByte(8);
+ throw new RuntimeException("Expected AssertionError");
+ } catch (final AssertionError expected) {
+ // ignore
+ }
+ }
+
+ @Test
+ public void testPutByte() {
+ writableMemory.putByte(7, (byte) 1);
+ try {
+ writableMemory.putByte(8, (byte) 1);
+ throw new RuntimeException("Expected AssertionError");
+ } catch (final AssertionError expected) {
+ // ignore
+ }
+ }
+
+ @Test
+ public void testGetChar() {
+ writableMemory.getChar(6);
+ try {
+ writableMemory.getChar(7);
+ throw new RuntimeException("Expected AssertionError");
+ } catch (final AssertionError expected) {
+ // ignore
+ }
+ }
+
+ @Test
+ public void testPutChar() {
+ writableMemory.putChar(6, 'a');
+ try {
+ writableMemory.putChar(7, 'a');
+ throw new RuntimeException("Expected AssertionError");
+ } catch (final AssertionError expected) {
+ // ignore
+ }
+ }
+
+ @Test
+ public void testGetShort() {
+ writableMemory.getShort(6);
+ try {
+ writableMemory.getShort(7);
+ throw new RuntimeException("Expected AssertionError");
+ } catch (final AssertionError expected) {
+ // ignore
+ }
+ }
+
+ @Test
+ public void testPutShort() {
+ writableMemory.putShort(6, (short) 1);
+ try {
+ writableMemory.putShort(7, (short) 1);
+ throw new RuntimeException("Expected AssertionError");
+ } catch (final AssertionError expected) {
+ // ignore
+ }
+ }
+
+ @Test
+ public void testGetInt() {
+ writableMemory.getInt(4);
+ try {
+ writableMemory.getInt(5);
+ throw new RuntimeException("Expected AssertionError");
+ } catch (final AssertionError expected) {
+ // ignore
+ }
+ }
+
+ @Test
+ public void testPutInt() {
+ writableMemory.putInt(4, 1);
+ try {
+ writableMemory.putInt(5, 1);
+ throw new RuntimeException("Expected AssertionError");
+ } catch (final AssertionError expected) {
+ // ignore
+ }
+ }
+
+ @Test
+ public void testGetFloat() {
+ writableMemory.getFloat(4);
+ try {
+ writableMemory.getFloat(5);
+ throw new RuntimeException("Expected AssertionError");
+ } catch (final AssertionError expected) {
+ // ignore
+ }
+ }
+
+ @Test
+ public void testPutFloat() {
+ writableMemory.putFloat(4, 1f);
+ try {
+ writableMemory.putFloat(5, 1f);
+ throw new RuntimeException("Expected AssertionError");
+ } catch (final AssertionError expected) {
+ // ignore
+ }
+ }
+
+ @Test
+ public void testGetLong() {
+ writableMemory.getLong(0);
+ try {
+ writableMemory.getLong(1);
+ throw new RuntimeException("Expected AssertionError");
+ } catch (final AssertionError expected) {
+ // ignore
+ }
+ }
+
+ @Test
+ public void testPutLong() {
+ writableMemory.putLong(0, 1L);
+ try {
+ writableMemory.putLong(1, 1L);
+ throw new RuntimeException("Expected AssertionError");
+ } catch (final AssertionError expected) {
+ // ignore
+ }
+ }
+
+ @Test
+ public void testGetDouble() {
+ writableMemory.getDouble(0);
+ try {
+ writableMemory.getDouble(1);
+ throw new RuntimeException("Expected AssertionError");
+ } catch (final AssertionError expected) {
+ // ignore
+ }
+ }
+
+ @Test
+ public void testPutDouble() {
+ writableMemory.putDouble(0, 1d);
+ try {
+ writableMemory.putDouble(1, 1d);
+ throw new RuntimeException("Expected AssertionError");
+ } catch (final AssertionError expected) {
+ // ignore
+ }
+ }
+
+ @Test
+ public void testGetAndAddLong() {
+ writableMemory.getAndAddLong(0, 1L);
+ try {
+ writableMemory.getAndAddLong(1, 1L);
+ throw new RuntimeException("Expected AssertionError");
+ } catch (final AssertionError expected) {
+ // ignore
+ }
+ }
+
+ @Test
+ public void testGetAndSetLong() {
+ writableMemory.getAndSetLong(0, 1L);
+ try {
+ writableMemory.getAndSetLong(1, 1L);
+ throw new RuntimeException("Expected AssertionError");
+ } catch (final AssertionError expected) {
+ // ignore
+ }
+ }
+
+ @Test
+ public void testCompareAndSwapLong() {
+ writableMemory.compareAndSwapLong(0, 0L, 1L);
+ try {
+ writableMemory.compareAndSwapLong(1, 0L, 1L);
+ throw new RuntimeException("Expected AssertionError");
+ } catch (final AssertionError expected) {
+ // ignore
+ }
+ }
+}
diff --git a/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/BufferInvariantsTest.java b/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/BufferInvariantsTest.java
new file mode 100644
index 0000000..735c6b0
--- /dev/null
+++ b/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/BufferInvariantsTest.java
@@ -0,0 +1,341 @@
+/*
+ * 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.datasketches.memory.internal;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.fail;
+
+import java.nio.ByteBuffer;
+
+import org.apache.datasketches.memory.Buffer;
+import org.apache.datasketches.memory.WritableBuffer;
+import org.apache.datasketches.memory.WritableHandle;
+import org.apache.datasketches.memory.WritableMemory;
+import org.testng.annotations.Test;
+
+/**
+ * @author Lee Rhodes
+ */
+public class BufferInvariantsTest {
+
+ @Test
+ public void testRegion() {
+ ByteBuffer byteBuffer = ByteBuffer.allocate(10);
+ byteBuffer.limit(7);
+ Buffer buff = Buffer.wrap(byteBuffer); //assuming buff has cap of 8
+ assertEquals(buff.getCapacity(), 10); //wrong should be 8
+ buff.getByte(); //pos moves to 1
+ Buffer copyBuff = buff.region(); //pos: 0, start: 0, end: 6: cap: 7
+ assertEquals(copyBuff.getEnd(), 6);
+ assertEquals(copyBuff.getCapacity(), 6);
+ assertEquals(copyBuff.getStart(), 0);
+ assertEquals(copyBuff.getPosition(), 0);
+
+ buff.setStartPositionEnd(1, 1, 5);
+ buff.getByte();
+ Buffer copyBuff2 = buff.region();
+ assertEquals(copyBuff2.getEnd(), 3);
+ assertEquals(copyBuff2.getCapacity(), 3);
+ assertEquals(copyBuff2.getStart(), 0);
+ assertEquals(copyBuff2.getPosition(), 0);
+ }
+
+ @Test
+ public void testBB() {
+ int n = 25;
+ ByteBuffer bb = ByteBuffer.allocate(n);
+ for (byte i = 0; i < n; i++) { bb.put(i, i); }
+ assertEquals(bb.position(), 0);
+ assertEquals(bb.limit(), n);
+ assertEquals(bb.get(0), 0);
+// print("Orig : ");
+// printbb(bb);
+
+ bb.limit(20);
+ bb.position(5);
+ assertEquals(bb.remaining(), 15);
+// print("Set : ");
+// printbb(bb);
+
+ ByteBuffer dup = bb.duplicate();
+ assertEquals(dup.position(), 5);
+ assertEquals(dup.limit(), 20);
+ assertEquals(dup.capacity(), 25);
+// print("Dup : ");
+// printbb(dup);
+
+ ByteBuffer sl = bb.slice();
+ assertEquals(sl.position(), 0);
+ assertEquals(sl.limit(), 15);
+ assertEquals(sl.capacity(), 15);
+// print("Slice: ");
+// printbb(sl);
+ }
+
+ @Test
+ public void testBuf() {
+ int n = 25;
+ WritableBuffer buf = WritableMemory.allocate(n).asWritableBuffer();
+ for (byte i = 0; i < n; i++) { buf.putByte(i); }
+ buf.setPosition(0);
+ assertEquals(buf.getPosition(), 0);
+ assertEquals(buf.getEnd(), 25);
+ assertEquals(buf.getCapacity(), 25);
+// print("Orig : ");
+// printbuf(buf);
+
+ buf.setStartPositionEnd(0, 5, 20);
+ assertEquals(buf.getRemaining(), 15);
+ assertEquals(buf.getCapacity(), 25);
+ assertEquals(buf.getByte(), 5);
+ buf.setPosition(5);
+// print("Set : ");
+// printbuf(buf);
+
+ Buffer dup = buf.duplicate();
+ assertEquals(dup.getRemaining(), 15);
+ assertEquals(dup.getCapacity(), 25);
+ assertEquals(dup.getByte(), 5);
+ dup.setPosition(5);
+// print("Dup : ");
+// printbuf(dup);
+
+
+ Buffer reg = buf.region();
+ assertEquals(reg.getPosition(), 0);
+ assertEquals(reg.getEnd(), 15);
+ assertEquals(reg.getRemaining(), 15);
+ assertEquals(reg.getCapacity(), 15);
+ assertEquals(reg.getByte(), 5);
+ reg.setPosition(0);
+// print("Region: ");
+// printbuf(reg);
+ }
+
+ @Test
+ public void testBufWrap() {
+ int n = 25;
+ ByteBuffer bb = ByteBuffer.allocate(n);
+ for (byte i = 0; i < n; i++) { bb.put(i, i); }
+
+ bb.position(5);
+ bb.limit(20);
+
+ Buffer buf = Buffer.wrap(bb);
+ assertEquals(buf.getPosition(), 5);
+ assertEquals(buf.getEnd(), 20);
+ assertEquals(buf.getRemaining(), 15);
+ assertEquals(buf.getCapacity(), 25);
+ assertEquals(buf.getByte(), 5);
+ buf.setPosition(5);
+// print("Buf.wrap: ");
+// printbuf(buf);
+
+ Buffer reg = buf.region();
+ assertEquals(reg.getPosition(), 0);
+ assertEquals(reg.getEnd(), 15);
+ assertEquals(reg.getRemaining(), 15);
+ assertEquals(reg.getCapacity(), 15);
+ assertEquals(reg.getByte(), 5);
+ reg.setPosition(0);
+// print("Buf.region: ");
+// printbuf(reg);
+ }
+
+ @Test
+ public void checkLimitsDirect() throws Exception {
+ try (WritableHandle hand = WritableMemory.allocateDirect(100)) {
+ WritableMemory wmem = hand.getWritable();
+ Buffer buf = wmem.asBuffer();
+ buf.setStartPositionEnd(40, 45, 50);
+ buf.setStartPositionEnd(0, 0, 100);
+ try {
+ buf.setStartPositionEnd(0, 0, 101);
+ fail();
+ } catch (AssertionError e) {
+ //ok
+ }
+ }
+ }
+
+ @Test
+ public void testRegionDirect() {
+ ByteBuffer byteBuffer = ByteBuffer.allocate(10);
+ byteBuffer.limit(7);
+ Buffer buff = Buffer.wrap(byteBuffer); //assuming buff has cap of 8
+ assertEquals(buff.getCapacity(), 10); //wrong should be 8
+ buff.getByte(); //pos moves to 1
+ Buffer copyBuff = buff.region(); //pos: 0, start: 0, end: 6: cap: 7
+ assertEquals(copyBuff.getEnd(), 6);
+ assertEquals(copyBuff.getCapacity(), 6);
+ assertEquals(copyBuff.getStart(), 0);
+ assertEquals(copyBuff.getPosition(), 0);
+
+ buff.setStartPositionEnd(1, 1, 5);
+ buff.getByte();
+ Buffer copyBuff2 = buff.region();
+ assertEquals(copyBuff2.getEnd(), 3);
+ assertEquals(copyBuff2.getCapacity(), 3);
+ assertEquals(copyBuff2.getStart(), 0);
+ assertEquals(copyBuff2.getPosition(), 0);
+ }
+
+ @Test
+ public void testBBDirect() {
+ int n = 25;
+ ByteBuffer bb = ByteBuffer.allocateDirect(n);
+ for (byte i = 0; i < n; i++) { bb.put(i, i); }
+ assertEquals(bb.position(), 0);
+ assertEquals(bb.limit(), n);
+ assertEquals(bb.get(0), 0);
+// print("Orig : ");
+// printbb(bb);
+
+ bb.limit(20);
+ bb.position(5);
+ assertEquals(bb.remaining(), 15);
+// print("Set : ");
+// printbb(bb);
+
+ ByteBuffer dup = bb.duplicate();
+ assertEquals(dup.position(), 5);
+ assertEquals(dup.limit(), 20);
+ assertEquals(dup.capacity(), 25);
+// print("Dup : ");
+// printbb(dup);
+
+ ByteBuffer sl = bb.slice();
+ assertEquals(sl.position(), 0);
+ assertEquals(sl.limit(), 15);
+ assertEquals(sl.capacity(), 15);
+// print("Slice: ");
+// printbb(sl);
+ }
+
+ @Test
+ public void testBufDirect() throws Exception {
+ int n = 25;
+ try (WritableHandle whand = WritableMemory.allocateDirect(n)) {
+ WritableMemory wmem = whand.getWritable();
+ WritableBuffer buf = wmem.asWritableBuffer();
+ for (byte i = 0; i < n; i++) { buf.putByte(i); }
+ buf.setPosition(0);
+ assertEquals(buf.getPosition(), 0);
+ assertEquals(buf.getEnd(), 25);
+ assertEquals(buf.getCapacity(), 25);
+// print("Orig : ");
+// printbuf(buf);
+
+ buf.setStartPositionEnd(0, 5, 20);
+ assertEquals(buf.getRemaining(), 15);
+ assertEquals(buf.getCapacity(), 25);
+ assertEquals(buf.getByte(), 5);
+ buf.setPosition(5);
+// print("Set : ");
+// printbuf(buf);
+
+ Buffer dup = buf.duplicate();
+ assertEquals(dup.getRemaining(), 15);
+ assertEquals(dup.getCapacity(), 25);
+ assertEquals(dup.getByte(), 5);
+ dup.setPosition(5);
+// print("Dup : ");
+// printbuf(dup);
+
+
+ Buffer reg = buf.region();
+ assertEquals(reg.getPosition(), 0);
+ assertEquals(reg.getEnd(), 15);
+ assertEquals(reg.getRemaining(), 15);
+ assertEquals(reg.getCapacity(), 15);
+ assertEquals(reg.getByte(), 5);
+ reg.setPosition(0);
+// print("Region: ");
+// printbuf(reg);
+ }
+ }
+
+ @Test
+ public void testBufWrapDirect() {
+ int n = 25;
+ ByteBuffer bb = ByteBuffer.allocateDirect(n);
+ for (byte i = 0; i < n; i++) { bb.put(i, i); }
+
+ bb.position(5);
+ bb.limit(20);
+
+ Buffer buf = Buffer.wrap(bb);
+ assertEquals(buf.getPosition(), 5);
+ assertEquals(buf.getEnd(), 20);
+ assertEquals(buf.getRemaining(), 15);
+ assertEquals(buf.getCapacity(), 25);
+ assertEquals(buf.getByte(), 5);
+ buf.setPosition(5);
+// print("Buf.wrap: ");
+// printbuf(buf);
+
+ Buffer reg = buf.region();
+ assertEquals(reg.getPosition(), 0);
+ assertEquals(reg.getEnd(), 15);
+ assertEquals(reg.getRemaining(), 15);
+ assertEquals(reg.getCapacity(), 15);
+ assertEquals(reg.getByte(), 5);
+ reg.setPosition(0);
+// print("Buf.region: ");
+// printbuf(reg);
+ }
+
+
+ static void printbb(ByteBuffer bb) {
+ println("pos: " + bb.position() + ", lim: " + bb.limit() + ", cap: " + bb.capacity());
+ int rem = bb.remaining();
+ int pos = bb.position();
+ int i;
+ for (i = 0; i < (rem-1); i++) {
+ print(bb.get(i+ pos) + ", ");
+ }
+ println(bb.get(i + pos) + "\n");
+ }
+
+ static void printbuf(Buffer buf) {
+ println("pos: " + buf.getPosition() + ", end: " + buf.getEnd() + ", cap: " + buf.getCapacity());
+ long rem = buf.getRemaining();
+ long pos = buf.getPosition();
+ int i;
+ for (i = 0; i < (rem-1); i++) {
+ print(buf.getByte(i+ pos) + ", ");
+ }
+ println(buf.getByte(i + pos) + "\n");
+ }
+
+ /**
+ * @param s value to print
+ */
+ static void println(String s) {
+ //System.out.println(s); //disable here
+ }
+
+ /**
+ * @param s value to print
+ */
+ static void print(String s) {
+ //System.out.print(s); //disable here
+ }
+}
diff --git a/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/BufferReadWriteSafetyTest.java b/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/BufferReadWriteSafetyTest.java
new file mode 100644
index 0000000..6f9f62a
--- /dev/null
+++ b/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/BufferReadWriteSafetyTest.java
@@ -0,0 +1,175 @@
+/*
+ * 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.datasketches.memory.internal;
+
+import java.nio.ByteBuffer;
+
+import org.apache.datasketches.memory.Buffer;
+import org.apache.datasketches.memory.ReadOnlyException;
+import org.apache.datasketches.memory.WritableBuffer;
+import org.apache.datasketches.memory.WritableMemory;
+import org.testng.annotations.Test;
+
+public class BufferReadWriteSafetyTest {
+
+ // Test various operations with read-only Buffer
+
+ private final WritableBuffer buf = (WritableBuffer) Buffer.wrap(ByteBuffer.allocate(8));
+
+ @Test(expectedExceptions = AssertionError.class)
+ public void testPutByte() {
+ buf.putByte(0, (byte) 1);
+ }
+
+ @Test(expectedExceptions = AssertionError.class)
+ public void testPutBytePositional() {
+ buf.putByte((byte) 1);
+ }
+
+ @Test(expectedExceptions = AssertionError.class)
+ public void testPutBoolean() {
+ buf.putBoolean(0, true);
+ }
+
+ @Test(expectedExceptions = AssertionError.class)
+ public void testPutBooleanPositional() {
+ buf.putBoolean(true);
+ }
+
+ @Test(expectedExceptions = AssertionError.class)
+ public void testPutShort() {
+ buf.putShort(0, (short) 1);
+ }
+
+ @Test(expectedExceptions = AssertionError.class)
+ public void testPutShortPositional() {
+ buf.putShort((short) 1);
+ }
+
+ @Test(expectedExceptions = AssertionError.class)
+ public void testPutChar() {
+ buf.putChar(0, (char) 1);
+ }
+
+ @Test(expectedExceptions = AssertionError.class)
+ public void testPutCharPositional() {
+ buf.putChar((char) 1);
+ }
+
+ @Test(expectedExceptions = AssertionError.class)
+ public void testPutInt() {
+ buf.putInt(0, 1);
+ }
+
+ @Test(expectedExceptions = AssertionError.class)
+ public void testPutIntPositional() {
+ buf.putInt(1);
+ }
+
+ @Test(expectedExceptions = AssertionError.class)
+ public void testPutLong() {
+ buf.putLong(0, 1);
+ }
+
+ @Test(expectedExceptions = AssertionError.class)
+ public void testPutLongPositional() {
+ buf.putLong(1);
+ }
+
+ @Test(expectedExceptions = AssertionError.class)
+ public void testPutFloat() {
+ buf.putFloat(0, 1);
+ }
+
+ @Test(expectedExceptions = AssertionError.class)
+ public void testPutFloatPositional() {
+ buf.putFloat(1);
+ }
+
+ @Test(expectedExceptions = AssertionError.class)
+ public void testPutDouble() {
+ buf.putDouble(0, 1);
+ }
+
+ @Test(expectedExceptions = AssertionError.class)
+ public void testPutDoublePositional() {
+ buf.putDouble(1);
+ }
+
+ @Test(expectedExceptions = ReadOnlyException.class)
+ public void testPutByteArray() {
+ buf.putByteArray(new byte[] {1}, 0, 1);
+ }
+
+ @Test(expectedExceptions = ReadOnlyException.class)
+ public void testPutBooleanArray() {
+ buf.putBooleanArray(new boolean[] {true}, 0, 1);
+ }
+
+ @Test(expectedExceptions = ReadOnlyException.class)
+ public void testPutShortArray() {
+ buf.putShortArray(new short[] {1}, 0, 1);
+ }
+
+ @Test(expectedExceptions = ReadOnlyException.class)
+ public void testPutCharArray() {
+ buf.putCharArray(new char[] {1}, 0, 1);
+ }
+
+ @Test(expectedExceptions = ReadOnlyException.class)
+ public void testPutIntArray() {
+ buf.putIntArray(new int[] {1}, 0, 1);
+ }
+
+ @Test(expectedExceptions = ReadOnlyException.class)
+ public void testPutLongArray() {
+ buf.putLongArray(new long[] {1}, 0, 1);
+ }
+
+ @Test(expectedExceptions = ReadOnlyException.class)
+ public void testPutFloatArray() {
+ buf.putFloatArray(new float[] {1}, 0, 1);
+ }
+
+ @Test(expectedExceptions = ReadOnlyException.class)
+ public void testDoubleByteArray() {
+ buf.putDoubleArray(new double[] {1}, 0, 1);
+ }
+
+ // Now, test that various ways to obtain a read-only buffer produce a read-only buffer indeed
+
+ @Test(expectedExceptions = AssertionError.class)
+ public void testWritableMemoryAsBuffer() {
+ WritableBuffer buf1 = (WritableBuffer) WritableMemory.allocate(8).asBuffer();
+ buf1.putInt(1);
+ }
+
+ @Test(expectedExceptions = AssertionError.class)
+ public void testWritableBufferRegion() {
+ WritableBuffer buf1 = (WritableBuffer) WritableMemory.allocate(8).asWritableBuffer().region();
+ buf1.putInt(1);
+ }
+
+ @Test(expectedExceptions = AssertionError.class)
+ public void testWritableBufferDuplicate() {
+ WritableBuffer buf1 = (WritableBuffer) WritableMemory.allocate(8).asWritableBuffer().duplicate();
+ buf1.putInt(1);
+ }
+}
diff --git a/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/BufferTest.java b/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/BufferTest.java
new file mode 100644
index 0000000..64b3c77
--- /dev/null
+++ b/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/BufferTest.java
@@ -0,0 +1,326 @@
+/*
+ * 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.datasketches.memory.internal;
+
+import static org.testng.Assert.assertEquals;
+
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.util.List;
+
+import org.apache.datasketches.memory.WritableHandle;
+import org.apache.datasketches.memory.Buffer;
+import org.apache.datasketches.memory.Memory;
+import org.apache.datasketches.memory.WritableBuffer;
+import org.apache.datasketches.memory.WritableMemory;
+import org.testng.annotations.Test;
+import org.testng.collections.Lists;
+
+public class BufferTest {
+
+ @Test
+ public void checkDirectRoundTrip() throws Exception {
+ int n = 1024; //longs
+ try (WritableHandle wh = WritableMemory.allocateDirect(n * 8)) {
+ WritableMemory wmem = wh.getWritable();
+ WritableBuffer wbuf = wmem.asWritableBuffer();
+ for (int i = 0; i < n; i++) {
+ wbuf.putLong(i);
+ }
+ wbuf.resetPosition();
+ for (int i = 0; i < n; i++) {
+ long v = wbuf.getLong();
+ assertEquals(v, i);
+ }
+ }
+ }
+
+ @Test
+ public void checkAutoHeapRoundTrip() {
+ int n = 1024; //longs
+ WritableBuffer wbuf = WritableMemory.allocate(n * 8).asWritableBuffer();
+ for (int i = 0; i < n; i++) {
+ wbuf.putLong(i);
+ }
+ wbuf.resetPosition();
+ for (int i = 0; i < n; i++) {
+ long v = wbuf.getLong();
+ assertEquals(v, i);
+ }
+ }
+
+ @Test
+ public void checkArrayWrap() {
+ int n = 1024; //longs
+ byte[] arr = new byte[n * 8];
+ WritableBuffer wbuf = WritableMemory.writableWrap(arr).asWritableBuffer();
+ for (int i = 0; i < n; i++) {
+ wbuf.putLong(i);
+ }
+ wbuf.resetPosition();
+ for (int i = 0; i < n; i++) {
+ long v = wbuf.getLong();
+ assertEquals(v, i);
+ }
+ Buffer buf = Memory.wrap(arr).asBuffer();
+ buf.resetPosition();
+ for (int i = 0; i < n; i++) {
+ long v = buf.getLong();
+ assertEquals(v, i);
+ }
+ // Check Zero length array wraps
+ Memory mem = Memory.wrap(new byte[0]);
+ Buffer buffZeroLengthArrayWrap = mem.asBuffer();
+ assertEquals(buffZeroLengthArrayWrap.getCapacity(), 0);
+ // check 0 length array wraps
+ List<Buffer> buffersToCheck = Lists.newArrayList();
+ buffersToCheck.add(WritableMemory.allocate(0).asBuffer());
+ buffersToCheck.add(WritableBuffer.writableWrap(ByteBuffer.allocate(0)));
+ buffersToCheck.add(Buffer.wrap(ByteBuffer.allocate(0)));
+ buffersToCheck.add(Memory.wrap(new boolean[0]).asBuffer());
+ buffersToCheck.add(Memory.wrap(new byte[0]).asBuffer());
+ buffersToCheck.add(Memory.wrap(new char[0]).asBuffer());
+ buffersToCheck.add(Memory.wrap(new short[0]).asBuffer());
+ buffersToCheck.add(Memory.wrap(new int[0]).asBuffer());
+ buffersToCheck.add(Memory.wrap(new long[0]).asBuffer());
+ buffersToCheck.add(Memory.wrap(new float[0]).asBuffer());
+ buffersToCheck.add(Memory.wrap(new double[0]).asBuffer());
+ //Check the buffer lengths
+ for (Buffer buffer : buffersToCheck) {
+ assertEquals(buffer.getCapacity(), 0);
+ }
+ }
+
+ @Test
+ public void simpleBBTest() {
+ int n = 1024; //longs
+ byte[] arr = new byte[n * 8];
+ ByteBuffer bb = ByteBuffer.wrap(arr);
+ bb.order(ByteOrder.nativeOrder());
+
+ WritableBuffer wbuf = WritableBuffer.writableWrap(bb);
+ for (int i = 0; i < n; i++) { //write to wbuf
+ wbuf.putLong(i);
+ }
+ wbuf.resetPosition();
+ for (int i = 0; i < n; i++) { //read from wbuf
+ long v = wbuf.getLong();
+ assertEquals(v, i);
+ }
+ for (int i = 0; i < n; i++) { //read from BB
+ long v = bb.getLong();
+ assertEquals(v, i);
+ }
+ }
+
+ @Test
+ public void checkByteBufHeap() {
+ int n = 1024; //longs
+ byte[] arr = new byte[n * 8];
+ ByteBuffer bb = ByteBuffer.wrap(arr);
+ bb.order(ByteOrder.nativeOrder());
+
+ WritableBuffer wbuf = WritableBuffer.writableWrap(bb);
+ for (int i = 0; i < n; i++) { //write to wbuf
+ wbuf.putLong(i);
+ }
+ wbuf.resetPosition();
+ for (int i = 0; i < n; i++) { //read from wbuf
+ long v = wbuf.getLong();
+ assertEquals(v, i);
+ }
+ for (int i = 0; i < n; i++) { //read from BB
+ long v = bb.getLong(i * 8);
+ assertEquals(v, i);
+ }
+ Buffer buf1 = Memory.wrap(arr).asBuffer();
+ for (int i = 0; i < n; i++) { //read from wrapped arr
+ long v = buf1.getLong();
+ assertEquals(v, i);
+ }
+ //convert to wbuf to RO
+ Buffer buf = wbuf;
+ buf.resetPosition();
+ for (int i = 0; i < n; i++) {
+ long v = buf.getLong();
+ assertEquals(v, i);
+ }
+ }
+
+ @Test
+ public void checkByteBufDirect() {
+ int n = 1024; //longs
+ ByteBuffer bb = ByteBuffer.allocateDirect(n * 8);
+ bb.order(ByteOrder.nativeOrder());
+
+ WritableBuffer wbuf = WritableBuffer.writableWrap(bb);
+ for (int i = 0; i < n; i++) { //write to wmem
+ wbuf.putLong(i);
+ }
+ wbuf.resetPosition();
+ for (int i = 0; i < n; i++) { //read from wmem
+ long v = wbuf.getLong();
+ assertEquals(v, i);
+ }
+ for (int i = 0; i < n; i++) { //read from BB
+ long v = bb.getLong(i * 8);
+ assertEquals(v, i);
+ }
+ Buffer buf1 = Buffer.wrap(bb);
+ for (int i = 0; i < n; i++) { //read from wrapped bb RO
+ long v = buf1.getLong();
+ assertEquals(v, i);
+ }
+ //convert to RO
+ Buffer buf = wbuf;
+ buf.resetPosition();
+ for (int i = 0; i < n; i++) {
+ long v = buf.getLong();
+ assertEquals(v, i);
+ }
+ }
+
+ @Test
+ public void checkByteBufBigEndianOrder() {
+ int n = 1024; //longs
+ ByteBuffer bb = ByteBuffer.allocate(n * 8);
+ bb.order(ByteOrder.BIG_ENDIAN);
+ Buffer buf = Buffer.wrap(bb);
+ assertEquals(buf.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());
+
+ Buffer buf = Buffer.wrap(slice);
+ for (int i = 0; i < 64; i++) {
+ assertEquals(buf.getByte(), 64 + i);
+ }
+ buf.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; }
+
+ WritableBuffer wbuf = WritableMemory.allocate(n * 8).asWritableBuffer();
+ wbuf.putLongArray(arr, 0, n);
+ long[] arr2 = new long[n];
+ wbuf.resetPosition();
+ wbuf.getLongArray(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; }
+
+ Buffer buf = Memory.wrap(arr).asBuffer();
+ buf.setPosition(n2 * 8);
+ Buffer reg = buf.region();
+ for (int i = 0; i < n2; i++) {
+ long v = reg.getLong();
+ assertEquals(v, i + n2);
+ //println("" + v);
+ }
+ }
+
+ @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; }
+ WritableBuffer wbuf = WritableMemory.writableWrap(arr).asWritableBuffer();
+ for (int i = 0; i < n; i++) {
+ assertEquals(wbuf.getLong(), i); //write all
+ //println("" + wmem.getLong(i * 8));
+ }
+ //println("");
+ wbuf.setPosition(n2 * 8);
+ WritableBuffer reg = wbuf.writableRegion();
+ for (int i = 0; i < n2; i++) { reg.putLong(i); } //rewrite top half
+ wbuf.resetPosition();
+ for (int i = 0; i < n; i++) {
+ assertEquals(wbuf.getLong(), i % 8);
+ //println("" + wmem.getLong(i * 8));
+ }
+ }
+
+ @Test(expectedExceptions = AssertionError.class)
+ public void checkParentUseAfterFree() throws Exception {
+ int bytes = 64 * 8;
+ WritableHandle wh = WritableMemory.allocateDirect(bytes);
+ WritableMemory wmem = wh.getWritable();
+ WritableBuffer wbuf = wmem.asWritableBuffer();
+ wh.close();
+ //with -ea assert: Memory not valid.
+ //with -da sometimes segfaults, sometimes passes!
+ wbuf.getLong();
+ }
+
+ @Test(expectedExceptions = AssertionError.class)
+ public void checkRegionUseAfterFree() throws Exception {
+ int bytes = 64;
+ WritableHandle wh = WritableMemory.allocateDirect(bytes);
+ Memory wmem = wh.get();
+
+ Buffer reg = wmem.asBuffer().region();
+ wh.close();
+ //with -ea assert: Memory not valid.
+ //with -da sometimes segfaults, sometimes passes!
+ reg.getByte();
+ }
+
+ @Test(expectedExceptions = AssertionError.class)
+ public void checkBaseBufferInvariants() {
+ WritableBuffer wbuf = WritableMemory.allocate(64).asWritableBuffer();
+ wbuf.setStartPositionEnd(1, 0, 2); //out of order
+ }
+
+
+ @Test
+ public void printlnTest() {
+ println("PRINTING: "+this.getClass().getName());
+ }
+
+ /**
+ * @param s String to print
+ */
+ static void println(final String s) {
+ //System.out.println(s);
+ }
+
+}
diff --git a/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/CommonBufferTest.java b/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/CommonBufferTest.java
new file mode 100644
index 0000000..e5033a2
--- /dev/null
+++ b/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/CommonBufferTest.java
@@ -0,0 +1,448 @@
+/*
+ * 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.datasketches.memory.internal;
+
+import static org.testng.Assert.assertEquals;
+
+import org.apache.datasketches.memory.WritableHandle;
+import org.apache.datasketches.memory.WritableBuffer;
+import org.apache.datasketches.memory.WritableMemory;
+import org.testng.annotations.Test;
+
+public class CommonBufferTest {
+
+ @Test
+ public void checkSetGet() throws Exception {
+ int memCapacity = 60; //must be at least 60
+ try (WritableHandle wrh = WritableMemory.allocateDirect(memCapacity)) {
+ WritableMemory mem = wrh.getWritable();
+ WritableBuffer buf = mem.asWritableBuffer();
+ assertEquals(buf.getCapacity(), memCapacity);
+ setGetTests(buf);
+ setGetTests2(buf);
+ }
+ }
+
+ public static void setGetTests(WritableBuffer buf) {
+ buf.putBoolean(true);
+ buf.putBoolean(false);
+ buf.putByte((byte) -1);
+ buf.putByte((byte) 0);
+ buf.putChar('A');
+ buf.putChar('Z');
+ buf.putShort(Short.MAX_VALUE);
+ buf.putShort(Short.MIN_VALUE);
+ buf.putInt(Integer.MAX_VALUE);
+ buf.putInt(Integer.MIN_VALUE);
+ buf.putFloat(Float.MAX_VALUE);
+ buf.putFloat(Float.MIN_VALUE);
+ buf.putLong(Long.MAX_VALUE);
+ buf.putLong(Long.MIN_VALUE);
+ buf.putDouble(Double.MAX_VALUE);
+ buf.putDouble(Double.MIN_VALUE);
+
+ buf.resetPosition();
+
+ assertEquals(buf.getBoolean(buf.getPosition()), true);
+ assertEquals(buf.getBoolean(), true);
+ assertEquals(buf.getBoolean(buf.getPosition()), false);
+ assertEquals(buf.getBoolean(), false);
+ assertEquals(buf.getByte(buf.getPosition()), (byte) -1);
+ assertEquals(buf.getByte(), (byte) -1);
+ assertEquals(buf.getByte(buf.getPosition()), (byte)0);
+ assertEquals(buf.getByte(), (byte)0);
+ assertEquals(buf.getChar(buf.getPosition()), 'A');
+ assertEquals(buf.getChar(), 'A');
+ assertEquals(buf.getChar(buf.getPosition()), 'Z');
+ assertEquals(buf.getChar(), 'Z');
+ assertEquals(buf.getShort(buf.getPosition()), Short.MAX_VALUE);
+ assertEquals(buf.getShort(), Short.MAX_VALUE);
+ assertEquals(buf.getShort(buf.getPosition()), Short.MIN_VALUE);
+ assertEquals(buf.getShort(), Short.MIN_VALUE);
+ assertEquals(buf.getInt(buf.getPosition()), Integer.MAX_VALUE);
+ assertEquals(buf.getInt(), Integer.MAX_VALUE);
+ assertEquals(buf.getInt(buf.getPosition()), Integer.MIN_VALUE);
+ assertEquals(buf.getInt(), Integer.MIN_VALUE);
+ assertEquals(buf.getFloat(buf.getPosition()), Float.MAX_VALUE);
+ assertEquals(buf.getFloat(), Float.MAX_VALUE);
+ assertEquals(buf.getFloat(buf.getPosition()), Float.MIN_VALUE);
+ assertEquals(buf.getFloat(), Float.MIN_VALUE);
+ assertEquals(buf.getLong(buf.getPosition()), Long.MAX_VALUE);
+ assertEquals(buf.getLong(), Long.MAX_VALUE);
+ assertEquals(buf.getLong(buf.getPosition()), Long.MIN_VALUE);
+ assertEquals(buf.getLong(), Long.MIN_VALUE);
+ assertEquals(buf.getDouble(buf.getPosition()), Double.MAX_VALUE);
+ assertEquals(buf.getDouble(), Double.MAX_VALUE);
+ assertEquals(buf.getDouble(buf.getPosition()), Double.MIN_VALUE);
+ assertEquals(buf.getDouble(), Double.MIN_VALUE);
+ }
+
+ public static void setGetTests2(WritableBuffer buf) {
+ buf.putBoolean(0, true);
+ buf.putBoolean(1, false);
+ buf.putByte(2, (byte) -1);
+ buf.putByte(3, (byte) 0);
+ buf.putChar(4,'A');
+ buf.putChar(6,'Z');
+ buf.putShort(8, Short.MAX_VALUE);
+ buf.putShort(10, Short.MIN_VALUE);
+ buf.putInt(12, Integer.MAX_VALUE);
+ buf.putInt(16, Integer.MIN_VALUE);
+ buf.putFloat(20, Float.MAX_VALUE);
+ buf.putFloat(24, Float.MIN_VALUE);
+ buf.putLong(28, Long.MAX_VALUE);
+ buf.putLong(36, Long.MIN_VALUE);
+ buf.putDouble(44, Double.MAX_VALUE);
+ buf.putDouble(52, Double.MIN_VALUE);
+
+ assertEquals(buf.getBoolean(0), true);
+ assertEquals(buf.getBoolean(1), false);
+ assertEquals(buf.getByte(2), (byte) -1);
+ assertEquals(buf.getByte(3), (byte)0);
+ assertEquals(buf.getChar(4), 'A');
+ assertEquals(buf.getChar(6), 'Z');
+ assertEquals(buf.getShort(8), Short.MAX_VALUE);
+ assertEquals(buf.getShort(10), Short.MIN_VALUE);
+ assertEquals(buf.getInt(12), Integer.MAX_VALUE);
+ assertEquals(buf.getInt(16), Integer.MIN_VALUE);
+ assertEquals(buf.getFloat(20), Float.MAX_VALUE);
+ assertEquals(buf.getFloat(24), Float.MIN_VALUE);
+ assertEquals(buf.getLong(28), Long.MAX_VALUE);
+ assertEquals(buf.getLong(36), Long.MIN_VALUE);
+ assertEquals(buf.getDouble(44), Double.MAX_VALUE);
+ assertEquals(buf.getDouble(52), Double.MIN_VALUE);
+ }
+
+ @Test
+ public void checkSetGetArrays() throws Exception {
+ int memCapacity = 32;
+ try (WritableHandle wrh = WritableMemory.allocateDirect(memCapacity)) {
+ WritableMemory mem = wrh.getWritable();
+ WritableBuffer buf = mem.asWritableBuffer();
+ assertEquals(buf.getCapacity(), memCapacity);
+ setGetArraysTests(buf);
+ }
+ }
+
+ public static void setGetArraysTests(WritableBuffer buf) {
+ int words = 4;
+
+ boolean[] srcArray1 = {true, false, true, false};
+ boolean[] dstArray1 = new boolean[words];
+ buf.resetPosition();
+ buf.fill((byte)127);
+ buf.resetPosition();
+ buf.putBooleanArray(srcArray1, 0, words);
+ buf.resetPosition();
+ buf.getBooleanArray(dstArray1, 0, words);
+ for (int i=0; i<words; i++) {
+ assertEquals(dstArray1[i], srcArray1[i]);
+ }
+
+ byte[] srcArray2 = { 1, -2, 3, -4 };
+ byte[] dstArray2 = new byte[4];
+ buf.resetPosition();
+ buf.putByteArray(srcArray2, 0, words);
+ buf.resetPosition();
+ buf.getByteArray(dstArray2, 0, words);
+ for (int i=0; i<words; i++) {
+ assertEquals(dstArray2[i], srcArray2[i]);
+ }
+
+ char[] srcArray3 = { 'A', 'B', 'C', 'D' };
+ char[] dstArray3 = new char[words];
+ buf.resetPosition();
+ buf.putCharArray(srcArray3, 0, words);
+ buf.resetPosition();
+ buf.getCharArray(dstArray3, 0, words);
+ for (int i=0; i<words; i++) {
+ assertEquals(dstArray3[i], srcArray3[i]);
+ }
+
+ double[] srcArray4 = { 1.0, -2.0, 3.0, -4.0 };
+ double[] dstArray4 = new double[words];
+ buf.resetPosition();
+ buf.putDoubleArray(srcArray4, 0, words);
+ buf.resetPosition();
+ buf.getDoubleArray(dstArray4, 0, words);
+ for (int i=0; i<words; i++) {
+ assertEquals(dstArray4[i], srcArray4[i], 0.0);
+ }
+
+ float[] srcArray5 = { (float)1.0, (float)-2.0, (float)3.0, (float)-4.0 };
+ float[] dstArray5 = new float[words];
+ buf.resetPosition();
+ buf.putFloatArray(srcArray5, 0, words);
+ buf.resetPosition();
+ buf.getFloatArray(dstArray5, 0, words);
+ for (int i=0; i<words; i++) {
+ assertEquals(dstArray5[i], srcArray5[i], 0.0);
+ }
+
+ int[] srcArray6 = { 1, -2, 3, -4 };
+ int[] dstArray6 = new int[words];
+ buf.resetPosition();
+ buf.putIntArray(srcArray6, 0, words);
+ buf.resetPosition();
+ buf.getIntArray(dstArray6, 0, words);
+ for (int i=0; i<words; i++) {
+ assertEquals(dstArray6[i], srcArray6[i]);
+ }
+
+ long[] srcArray7 = { 1, -2, 3, -4 };
+ long[] dstArray7 = new long[words];
+ buf.resetPosition();
+ buf.putLongArray(srcArray7, 0, words);
+ buf.resetPosition();
+ buf.getLongArray(dstArray7, 0, words);
+ for (int i=0; i<words; i++) {
+ assertEquals(dstArray7[i], srcArray7[i]);
+ }
+
+ short[] srcArray8 = { 1, -2, 3, -4 };
+ short[] dstArray8 = new short[words];
+ buf.resetPosition();
+ buf.putShortArray(srcArray8, 0, words);
+ buf.resetPosition();
+ buf.getShortArray(dstArray8, 0, words);
+ for (int i=0; i<words; i++) {
+ assertEquals(dstArray8[i], srcArray8[i]);
+ }
+ }
+
+ @Test
+ public void checkSetGetPartialArraysWithOffset() throws Exception {
+ int memCapacity = 32;
+ try (WritableHandle wrh = WritableMemory.allocateDirect(memCapacity)) {
+ WritableMemory mem = wrh.getWritable();
+ WritableBuffer buf = mem.asWritableBuffer();
+ assertEquals(buf.getCapacity(), memCapacity);
+ setGetPartialArraysWithOffsetTests(buf);
+ }
+ }
+
+ public static void setGetPartialArraysWithOffsetTests(WritableBuffer buf) {
+ int items= 4;
+ boolean[] srcArray1 = {true, false, true, false};
+ boolean[] dstArray1 = new boolean[items];
+ buf.resetPosition();
+ buf.putBooleanArray(srcArray1, 2, items/2);
+ buf.resetPosition();
+ buf.getBooleanArray(dstArray1, 2, items/2);
+ for (int i=2; i<items; i++) {
+ assertEquals(dstArray1[i], srcArray1[i]);
+ }
+
+ byte[] srcArray2 = { 1, -2, 3, -4 };
+ byte[] dstArray2 = new byte[items];
+ buf.resetPosition();
+ buf.putByteArray(srcArray2, 2, items/2);
+ buf.resetPosition();
+ buf.getByteArray(dstArray2, 2, items/2);
+ for (int i=2; i<items; i++) {
+ assertEquals(dstArray2[i], srcArray2[i]);
+ }
+
+ char[] srcArray3 = { 'A', 'B', 'C', 'D' };
+ char[] dstArray3 = new char[items];
+ buf.resetPosition();
+ buf.putCharArray(srcArray3, 2, items/2);
+ buf.resetPosition();
+ buf.getCharArray(dstArray3, 2, items/2);
+ for (int i=2; i<items; i++) {
+ assertEquals(dstArray3[i], srcArray3[i]);
+ }
+
+ double[] srcArray4 = { 1.0, -2.0, 3.0, -4.0 };
+ double[] dstArray4 = new double[items];
+ buf.resetPosition();
+ buf.putDoubleArray(srcArray4, 2, items/2);
+ buf.resetPosition();
+ buf.getDoubleArray(dstArray4, 2, items/2);
+ for (int i=2; i<items; i++) {
+ assertEquals(dstArray4[i], srcArray4[i], 0.0);
+ }
+
+ float[] srcArray5 = { (float)1.0, (float)-2.0, (float)3.0, (float)-4.0 };
+ float[] dstArray5 = new float[items];
+ buf.resetPosition();
+ buf.putFloatArray(srcArray5, 2, items/2);
+ buf.resetPosition();
+ buf.getFloatArray(dstArray5, 2, items/2);
+ for (int i=2; i<items; i++) {
+ assertEquals(dstArray5[i], srcArray5[i], 0.0);
+ }
+
+ int[] srcArray6 = { 1, -2, 3, -4 };
+ int[] dstArray6 = new int[items];
+ buf.resetPosition();
+ buf.putIntArray(srcArray6, 2, items/2);
+ buf.resetPosition();
+ buf.getIntArray(dstArray6, 2, items/2);
+ for (int i=2; i<items; i++) {
+ assertEquals(dstArray6[i], srcArray6[i]);
+ }
+
+ long[] srcArray7 = { 1, -2, 3, -4 };
+ long[] dstArray7 = new long[items];
+ buf.resetPosition();
+ buf.putLongArray(srcArray7, 2, items/2);
+ buf.resetPosition();
+ buf.getLongArray(dstArray7, 2, items/2);
+ for (int i=2; i<items; i++) {
+ assertEquals(dstArray7[i], srcArray7[i]);
+ }
+
+ short[] srcArray8 = { 1, -2, 3, -4 };
+ short[] dstArray8 = new short[items];
+ buf.resetPosition();
+ buf.putShortArray(srcArray8, 2, items/2);
+ buf.resetPosition();
+ buf.getShortArray(dstArray8, 2, items/2);
+ for (int i=2; i<items; i++) {
+ assertEquals(dstArray8[i], srcArray8[i]);
+ }
+ }
+
+ @Test
+ public void checkSetClearMemoryRegions() throws Exception {
+ int memCapacity = 64; //must be 64
+ try (WritableHandle wrh1 = WritableMemory.allocateDirect(memCapacity)) {
+ WritableMemory mem = wrh1.getWritable();
+ WritableBuffer buf = mem.asWritableBuffer();
+ assertEquals(buf.getCapacity(), memCapacity);
+
+ setClearMemoryRegionsTests(buf); //requires println enabled to visually check
+ buf.resetPosition();
+ for (int i = 0; i < memCapacity; i++) {
+ assertEquals(mem.getByte(i), 0);
+ }
+ }
+ }
+
+ //enable println statements to visually check
+ public static void setClearMemoryRegionsTests(WritableBuffer buf) {
+ int accessCapacity = (int)buf.getCapacity();
+
+ //define regions
+ int reg1Start = 0;
+ int reg1Len = 28;
+ int reg2Start = 28;
+ int reg2Len = 32;
+
+ //set region 1
+ byte b1 = 5;
+ buf.setStartPositionEnd(reg1Start, reg1Start, reg1Len);
+ buf.fill(b1);
+ buf.resetPosition();
+ for (int i=reg1Start; i<(reg1Len+reg1Start); i++) {
+ assertEquals(buf.getByte(), b1);
+ }
+ //println(buf.toHexString("Region1 to 5", reg1Start, reg1Len));
+
+ //set region 2
+ byte b2 = 7;
+ buf.setStartPositionEnd(reg2Start, reg2Start, reg2Start + reg2Len);
+ buf.fill(b2);
+ //println(mem.toHexString("Fill", 0, (int)mem.getCapacity()));
+ buf.resetPosition();
+ for (int i=reg2Start; i<(reg2Start+reg2Len); i++) {
+ assertEquals(buf.getByte(), b2);
+ }
+ //println(buf.toHexString("Region2 to 7", reg2Start, reg2Len));
+
+ //clear region 1
+ byte zeroByte = 0;
+ buf.setStartPositionEnd(reg1Start, reg1Start, reg2Len);
+ buf.resetPosition();
+ buf.clear();
+ buf.resetPosition();
+ for (int i=reg1Start; i<(reg1Start+reg1Len); i++) {
+ assertEquals(buf.getByte(), zeroByte);
+ }
+ //println(buf.toHexString("Region1 cleared", reg1Start, reg1Len));
+
+ //clear region 2
+ buf.setStartPositionEnd(reg2Start, reg2Start, reg2Start + reg2Len);
+ buf.resetPosition();
+ buf.clear();
+ buf.resetPosition();
+ for (int i=reg2Start; i<(reg2Len+reg2Start); i++) {
+ assertEquals(buf.getByte(), zeroByte);
+ }
+ //println(buf.toHexString("Region2 cleared", reg2Start, reg2Len));
+
+ //set all to ones
+ buf.setStartPositionEnd(reg1Start, reg1Start, accessCapacity);
+ byte b4 = 127;
+ buf.resetPosition();
+ buf.fill(b4);
+ buf.resetPosition();
+ for (int i=0; i<accessCapacity; i++) {
+ assertEquals(buf.getByte(), b4);
+ }
+ //println(buf.toHexString("Region1 + Region2 all ones", 0, accessCapacity));
+
+ //clear all
+ buf.resetPosition();
+ buf.clear();
+ buf.resetPosition();
+ for (int i=0; i<accessCapacity; i++) {
+ assertEquals(buf.getByte(), zeroByte);
+ }
+ //println(buf.toHexString("Region1 + Region2 cleared", 0, accessCapacity));
+ }
+
+ @Test
+ public void checkToHexStringAllMem() throws Exception {
+ int memCapacity = 48; //must be 48
+ try (WritableHandle wrh1 = WritableMemory.allocateDirect(memCapacity)) {
+ WritableMemory mem = wrh1.getWritable();
+ WritableBuffer buf = mem.asWritableBuffer();
+ assertEquals(buf.getCapacity(), memCapacity);
+ toHexStringAllMemTests(buf); //requires println enabled to visually check
+ }
+ }
+
+ //enable println to visually check
+ public static void toHexStringAllMemTests(WritableBuffer buf) {
+ int memCapacity = (int)buf.getCapacity();
+
+ for (int i=0; i<memCapacity; i++) {
+ buf.putByte((byte)i);
+ }
+
+ //println(buf.toHexString("Check toHexString(0, 48) to integers", 0, memCapacity));
+ //println(buf.toHexString("Check toHexString(8, 40)", 8, 40));
+ }
+
+ @Test
+ public void printlnTest() {
+ println("PRINTING: "+this.getClass().getName());
+ }
+
+ /**
+ * @param s value to print
+ */
+ static void println(String s) {
+ //System.out.println(s); //disable here
+ }
+
+}
diff --git a/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/CommonMemoryTest.java b/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/CommonMemoryTest.java
new file mode 100644
index 0000000..322352f
--- /dev/null
+++ b/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/CommonMemoryTest.java
@@ -0,0 +1,416 @@
+/*
+ * 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.datasketches.memory.internal;
+
+import static org.apache.datasketches.memory.internal.Util.isAllBitsClear;
+import static org.apache.datasketches.memory.internal.Util.isAllBitsSet;
+import static org.apache.datasketches.memory.internal.Util.isAnyBitsClear;
+import static org.apache.datasketches.memory.internal.Util.isAnyBitsSet;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertFalse;
+import static org.testng.Assert.assertTrue;
+
+import org.apache.datasketches.memory.WritableHandle;
+import org.apache.datasketches.memory.WritableMemory;
+import org.testng.annotations.Test;
+
+public class CommonMemoryTest {
+
+ @Test
+ public void checkSetGet() throws Exception {
+ int memCapacity = 16; //must be at least 8
+ try (WritableHandle wrh = WritableMemory.allocateDirect(memCapacity)) {
+ WritableMemory mem = wrh.getWritable();
+ assertEquals(mem.getCapacity(), memCapacity);
+ setGetTests(mem);
+ }
+ }
+
+ public static void setGetTests(WritableMemory mem) {
+ mem.putBoolean(0, true);
+ assertEquals(mem.getBoolean(0), true);
+ mem.putBoolean(0, false);
+ assertEquals(mem.getBoolean(0), false);
+
+ mem.putByte(0, (byte) -1);
+ assertEquals(mem.getByte(0), (byte) -1);
+ mem.putByte(0, (byte) 0);
+ assertEquals(mem.getByte(0), (byte) 0);
+
+ mem.putChar(0, 'A');
+ assertEquals(mem.getChar(0), 'A');
+ mem.putChar(0, 'Z');
+ assertEquals(mem.getChar(0), 'Z');
+
+ mem.putShort(0, Short.MAX_VALUE);
+ assertEquals(mem.getShort(0), Short.MAX_VALUE);
+ mem.putShort(0, Short.MIN_VALUE);
+ assertEquals(mem.getShort(0), Short.MIN_VALUE);
+
+ mem.putInt(0, Integer.MAX_VALUE);
+ assertEquals(mem.getInt(0), Integer.MAX_VALUE);
+ mem.putInt(0, Integer.MIN_VALUE);
+ assertEquals(mem.getInt(0), Integer.MIN_VALUE);
+
+ mem.putFloat(0, Float.MAX_VALUE);
+ assertEquals(mem.getFloat(0), Float.MAX_VALUE);
+ mem.putFloat(0, Float.MIN_VALUE);
+ assertEquals(mem.getFloat(0), Float.MIN_VALUE);
+
+ mem.putLong(0, Long.MAX_VALUE);
+ assertEquals(mem.getLong(0), Long.MAX_VALUE);
+ mem.putLong(0, Long.MIN_VALUE);
+ assertEquals(mem.getLong(0), Long.MIN_VALUE);
+
+ mem.putDouble(0, Double.MAX_VALUE);
+ assertEquals(mem.getDouble(0), Double.MAX_VALUE);
+ mem.putDouble(0, Double.MIN_VALUE);
+ assertEquals(mem.getDouble(0), Double.MIN_VALUE);
+ }
+
+ @Test
+ public void checkSetGetArrays() throws Exception {
+ int memCapacity = 32;
+ try (WritableHandle wrh = WritableMemory.allocateDirect(memCapacity)) {
+ WritableMemory mem = wrh.getWritable();
+ assertEquals(memCapacity, mem.getCapacity());
+ setGetArraysTests(mem);
+ }
+ }
+
+ public static void setGetArraysTests(WritableMemory mem) {
+ int accessCapacity = (int)mem.getCapacity();
+
+ int words = 4;
+ boolean[] srcArray1 = {true, false, true, false};
+ boolean[] dstArray1 = new boolean[words];
+ mem.fill(0, accessCapacity, (byte)127);
+ mem.putBooleanArray(0, srcArray1, 0, words);
+ mem.getBooleanArray(0, dstArray1, 0, words);
+ for (int i = 0; i < words; i++) {
+ assertEquals(dstArray1[i], srcArray1[i]);
+ }
+
+ byte[] srcArray2 = { 1, -2, 3, -4 };
+ byte[] dstArray2 = new byte[4];
+ mem.putByteArray(0, srcArray2, 0, words);
+ mem.getByteArray(0, dstArray2, 0, words);
+ for (int i = 0; i < words; i++) {
+ assertEquals(dstArray2[i], srcArray2[i]);
+ }
+
+ char[] srcArray3 = { 'A', 'B', 'C', 'D' };
+ char[] dstArray3 = new char[words];
+ mem.putCharArray(0, srcArray3, 0, words);
+ mem.getCharArray(0, dstArray3, 0, words);
+ for (int i = 0; i < words; i++) {
+ assertEquals(dstArray3[i], srcArray3[i]);
+ }
+
+ double[] srcArray4 = { 1.0, -2.0, 3.0, -4.0 };
+ double[] dstArray4 = new double[words];
+ mem.putDoubleArray(0, srcArray4, 0, words);
+ mem.getDoubleArray(0, dstArray4, 0, words);
+ for (int i = 0; i < words; i++) {
+ assertEquals(dstArray4[i], srcArray4[i], 0.0);
+ }
+
+ float[] srcArray5 = { (float)1.0, (float)-2.0, (float)3.0, (float)-4.0 };
+ float[] dstArray5 = new float[words];
+ mem.putFloatArray(0, srcArray5, 0, words);
+ mem.getFloatArray(0, dstArray5, 0, words);
+ for (int i = 0; i < words; i++) {
+ assertEquals(dstArray5[i], srcArray5[i], 0.0);
+ }
+
+ int[] srcArray6 = { 1, -2, 3, -4 };
+ int[] dstArray6 = new int[words];
+ mem.putIntArray(0, srcArray6, 0, words);
+ mem.getIntArray(0, dstArray6, 0, words);
+ for (int i = 0; i < words; i++) {
+ assertEquals(dstArray6[i], srcArray6[i]);
+ }
+
+ long[] srcArray7 = { 1, -2, 3, -4 };
+ long[] dstArray7 = new long[words];
+ mem.putLongArray(0, srcArray7, 0, words);
+ mem.getLongArray(0, dstArray7, 0, words);
+ for (int i = 0; i < words; i++) {
+ assertEquals(dstArray7[i], srcArray7[i]);
+ }
+
+ short[] srcArray8 = { 1, -2, 3, -4 };
+ short[] dstArray8 = new short[words];
+ mem.putShortArray(0, srcArray8, 0, words);
+ mem.getShortArray(0, dstArray8, 0, words);
+ for (int i = 0; i < words; i++) {
+ assertEquals(dstArray8[i], srcArray8[i]);
+ }
+ }
+
+ @Test
+ public void checkSetGetPartialArraysWithOffset() throws Exception {
+ int memCapacity = 32;
+ try (WritableHandle wrh = WritableMemory.allocateDirect(memCapacity)) {
+ WritableMemory mem = wrh.getWritable();
+ assertEquals(memCapacity, mem.getCapacity());
+ setGetPartialArraysWithOffsetTests(mem);
+ }
+ }
+
+ public static void setGetPartialArraysWithOffsetTests(WritableMemory mem) {
+ int items= 4;
+ boolean[] srcArray1 = {true, false, true, false};
+ boolean[] dstArray1 = new boolean[items];
+ mem.putBooleanArray(0, srcArray1, 2, items/2);
+ mem.getBooleanArray(0, dstArray1, 2, items/2);
+ for (int i = 2; i < items; i++) {
+ assertEquals(dstArray1[i], srcArray1[i]);
+ }
+
+ byte[] srcArray2 = { 1, -2, 3, -4 };
+ byte[] dstArray2 = new byte[items];
+ mem.putByteArray(0, srcArray2, 2, items/2);
+ mem.getByteArray(0, dstArray2, 2, items/2);
+ for (int i = 2; i < items; i++) {
+ assertEquals(dstArray2[i], srcArray2[i]);
+ }
+
+ char[] srcArray3 = { 'A', 'B', 'C', 'D' };
+ char[] dstArray3 = new char[items];
+ mem.putCharArray(0, srcArray3, 2, items/2);
+ mem.getCharArray(0, dstArray3, 2, items/2);
+ for (int i = 2; i < items; i++) {
+ assertEquals(dstArray3[i], srcArray3[i]);
+ }
+
+ double[] srcArray4 = { 1.0, -2.0, 3.0, -4.0 };
+ double[] dstArray4 = new double[items];
+ mem.putDoubleArray(0, srcArray4, 2, items/2);
+ mem.getDoubleArray(0, dstArray4, 2, items/2);
+ for (int i = 2; i < items; i++) {
+ assertEquals(dstArray4[i], srcArray4[i], 0.0);
+ }
+
+ float[] srcArray5 = { (float)1.0, (float)-2.0, (float)3.0, (float)-4.0 };
+ float[] dstArray5 = new float[items];
+ mem.putFloatArray(0, srcArray5, 2, items/2);
+ mem.getFloatArray(0, dstArray5, 2, items/2);
+ for (int i = 2; i < items; i++) {
+ assertEquals(dstArray5[i], srcArray5[i], 0.0);
+ }
+
+ int[] srcArray6 = { 1, -2, 3, -4 };
+ int[] dstArray6 = new int[items];
+ mem.putIntArray(0, srcArray6, 2, items/2);
+ mem.getIntArray(0, dstArray6, 2, items/2);
+ for (int i = 2; i < items; i++) {
+ assertEquals(dstArray6[i], srcArray6[i]);
+ }
+
+ long[] srcArray7 = { 1, -2, 3, -4 };
+ long[] dstArray7 = new long[items];
+ mem.putLongArray(0, srcArray7, 2, items/2);
+ mem.getLongArray(0, dstArray7, 2, items/2);
+ for (int i = 2; i < items; i++) {
+ assertEquals(dstArray7[i], srcArray7[i]);
+ }
+
+ short[] srcArray8 = { 1, -2, 3, -4 };
+ short[] dstArray8 = new short[items];
+ mem.putShortArray(0, srcArray8, 2, items/2);
+ mem.getShortArray(0, dstArray8, 2, items/2);
+ for (int i = 2; i < items; i++) {
+ assertEquals(dstArray8[i], srcArray8[i]);
+ }
+ }
+
+ @Test
+ public void checkSetClearIsBits() throws Exception {
+ int memCapacity = 8;
+ try (WritableHandle wrh = WritableMemory.allocateDirect(memCapacity)) {
+ WritableMemory mem = wrh.getWritable();
+ assertEquals(memCapacity, mem.getCapacity());
+ mem.clear();
+ setClearIsBitsTests(mem);
+ }
+ }
+
+ public static void setClearIsBitsTests(WritableMemory mem) {
+ //single bits
+ for (int i = 0; i < 8; i++) {
+ long bitMask = (1 << i);
+ long v = mem.getByte(0) & 0XFFL;
+ assertTrue(isAnyBitsClear(v, bitMask));
+ mem.setBits(0, (byte) bitMask);
+ v = mem.getByte(0) & 0XFFL;
+ assertTrue(isAnyBitsSet(v, bitMask));
+ mem.clearBits(0, (byte) bitMask);
+ v = mem.getByte(0) & 0XFFL;
+ assertTrue(isAnyBitsClear(v, bitMask));
+ }
+
+ //multiple bits
+ for (int i = 0; i < 7; i++) {
+ long bitMask1 = (1 << i);
+ long bitMask2 = (3 << i);
+ long v = mem.getByte(0) & 0XFFL;
+ assertTrue(isAnyBitsClear(v, bitMask1));
+ assertTrue(isAnyBitsClear(v, bitMask2));
+ mem.setBits(0, (byte) bitMask1); //set one bit
+ v = mem.getByte(0) & 0XFFL;
+ assertTrue(isAnyBitsSet(v, bitMask2));
+ assertTrue(isAnyBitsClear(v, bitMask2));
+ assertFalse(isAllBitsSet(v, bitMask2));
+ assertFalse(isAllBitsClear(v, bitMask2));
+ }
+ }
+
+ @Test
+ public void checkAtomicMethods() throws Exception {
+ int memCapacity = 8;
+ try (WritableHandle wrh = WritableMemory.allocateDirect(memCapacity)) {
+ WritableMemory mem = wrh.getWritable();
+ assertEquals(mem.getCapacity(), memCapacity);
+ atomicMethodTests(mem);
+ }
+ }
+
+ public static void atomicMethodTests(WritableMemory mem) {
+ mem.putLong(0, 500);
+ mem.getAndAddLong(0, 1);
+ assertEquals(mem.getLong(0), 501);
+
+ mem.putInt(0, 500);
+ boolean b = mem.compareAndSwapLong(0, 500, 501);
+ assertTrue(b);
+ assertEquals(mem.getLong(0), 501);
+
+ mem.putLong(0, 500);
+ long oldLong = mem.getAndSetLong(0, 501);
+ long newLong = mem.getLong(0);
+ assertEquals(oldLong, 500);
+ assertEquals(newLong, 501);
+ }
+
+ @Test
+ public void checkSetClearMemoryRegions() throws Exception {
+ int memCapacity = 64; //must be 64
+ try (WritableHandle wrh1 = WritableMemory.allocateDirect(memCapacity)) {
+ WritableMemory mem = wrh1.getWritable();
+
+ setClearMemoryRegionsTests(mem); //requires println enabled to visually check
+ for (int i = 0; i < memCapacity; i++) {
+ assertEquals(mem.getByte(i), 0);
+ }
+ }
+ }
+
+ //enable println stmts to visually check
+ public static void setClearMemoryRegionsTests(WritableMemory mem) {
+ int accessCapacity = (int)mem.getCapacity();
+
+ //define regions
+ int reg1Start = 0;
+ int reg1Len = 28;
+ int reg2Start = 28;
+ int reg2Len = 32;
+
+ //set region 1
+ byte b1 = 5;
+ mem.fill(reg1Start, reg1Len, b1);
+ for (int i = reg1Start; i < (reg1Len+reg1Start); i++) {
+ assertEquals(mem.getByte(i), b1);
+ }
+ //println(mem.toHexString("Region1 to 5", reg1Start, reg1Len));
+
+ //set region 2
+ byte b2 = 7;
+ mem.fill(reg2Start, reg2Len, b2);
+ //println(mem.toHexString("Fill", 0, (int)mem.getCapacity()));
+ for (int i = reg2Start; i < (reg2Len+reg2Start); i++) {
+ assertEquals(mem.getByte(i), b2);
+ }
+ //println(mem.toHexString("Region2 to 7", reg2Start, reg2Len));
+
+ //clear region 1
+ byte zeroByte = 0;
+ mem.clear(reg1Start, reg1Len);
+ for (int i = reg1Start; i < (reg1Len+reg1Start); i++) {
+ assertEquals(mem.getByte(i), zeroByte);
+ }
+ //println(mem.toHexString("Region1 cleared", reg1Start, reg1Len));
+
+ //clear region 2
+ mem.clear(reg2Start, reg2Len);
+ for (int i = reg2Start; i < (reg2Len+reg2Start); i++) {
+ assertEquals(mem.getByte(i), zeroByte);
+ }
+ //println(mem.toHexString("Region2 cleared", reg2Start, reg2Len));
+
+ //set all to ones
+ byte b4 = 127;
+ mem.fill(b4);
+ for (int i=0; i<accessCapacity; i++) {
+ assertEquals(mem.getByte(i), b4);
+ }
+ //println(mem.toHexString("Region1 + Region2 all ones", 0, accessCapacity));
+
+ //clear all
+ mem.clear();
+ for (int i = 0; i < accessCapacity; i++) {
+ assertEquals(mem.getByte(i), zeroByte);
+ }
+ //println(mem.toHexString("Region1 + Region2 cleared", 0, accessCapacity));
+ }
+
+ @Test
+ public void checkToHexStringAllMem() throws Exception {
+ int memCapacity = 48; //must be 48
+ try (WritableHandle wrh1 = WritableMemory.allocateDirect(memCapacity)) {
+ WritableMemory mem = wrh1.getWritable();
+ toHexStringAllMemTests(mem); //requires println enabled to visually check
+ }
+ }
+
+ //enable println to visually check
+ public static void toHexStringAllMemTests(WritableMemory mem) {
+ int memCapacity = (int)mem.getCapacity();
+
+ for (int i = 0; i < memCapacity; i++) {
+ mem.putByte(i, (byte)i);
+ }
+
+ //println(mem.toHexString("Check toHexString(0, 48) to integers", 0, memCapacity));
+ //println(mem.toHexString("Check toHexString(8, 40)", 8, 40));
+ }
+
+ @Test
+ public void printlnTest() {
+ println("PRINTING: "+this.getClass().getName());
+ }
+
+ /**
+ * @param s value to print
+ */
+ static void println(String s) {
+ //System.out.println(s); //disable here
+ }
+}
diff --git a/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/CopyMemoryOverlapTest.java b/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/CopyMemoryOverlapTest.java
new file mode 100644
index 0000000..962b12f
--- /dev/null
+++ b/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/CopyMemoryOverlapTest.java
@@ -0,0 +1,183 @@
+/*
+ * 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.datasketches.memory.internal;
+
+import static org.testng.Assert.assertEquals;
+
+import org.apache.datasketches.memory.WritableHandle;
+import org.apache.datasketches.memory.Memory;
+import org.apache.datasketches.memory.WritableMemory;
+import org.testng.annotations.Test;
+
+/**
+ * @author Lee Rhodes
+ */
+public class CopyMemoryOverlapTest {
+
+ @Test
+ public void checkOverlapUsingMemory() throws Exception {
+ long copyLongs = 1 << 20;
+ double overlap = 0.5;
+ long start_mS = System.currentTimeMillis();
+
+ copyUsingDirectMemory(copyLongs, overlap, true);
+ long end1_mS = System.currentTimeMillis();
+
+ copyUsingDirectMemory(copyLongs, overlap, false);
+ long end2_mS = System.currentTimeMillis();
+
+ println("CopyUp Time Sec: " + ((end1_mS - start_mS)/1000.0));
+ println("CopyDn Time Sec: " + ((end2_mS - end1_mS)/1000.0));
+ }
+
+ @Test
+ public void checkOverlapUsingRegions() throws Exception {
+ long copyLongs = 1 << 20;
+ double overlap = 0.5;
+ long start_mS = System.currentTimeMillis();
+
+ copyUsingDirectRegions(copyLongs, overlap, true);
+ long end1_mS = System.currentTimeMillis();
+
+ copyUsingDirectRegions(copyLongs, overlap, false);
+ long end2_mS = System.currentTimeMillis();
+
+ println("CopyUp Time Sec: " + ((end1_mS - start_mS)/1000.0));
+ println("CopyDn Time Sec: " + ((end2_mS - end1_mS)/1000.0));
+ }
+
+ private static final void copyUsingDirectMemory(long copyLongs, double overlap, boolean copyUp) throws Exception {
+ println("Copy Using Direct Memory");
+ long overlapLongs = (long) (overlap * copyLongs);
+ long backingLongs = (2 * copyLongs) - overlapLongs;
+
+ long fromOffsetLongs;
+ long toOffsetLongs;
+ //long deltaLongs;
+
+ if (copyUp) {
+ fromOffsetLongs = 0;
+ toOffsetLongs = copyLongs - overlapLongs;
+ //deltaLongs = toOffsetLongs - fromOffsetLongs;
+ } else {
+ fromOffsetLongs = copyLongs - overlapLongs;
+ toOffsetLongs = 0;
+ //deltaLongs = toOffsetLongs - fromOffsetLongs;
+ }
+
+ long backingBytes = backingLongs << 3;
+ long copyBytes = copyLongs << 3;
+ long fromOffsetBytes = fromOffsetLongs << 3;
+ long toOffsetBytes = toOffsetLongs << 3;
+ //long deltaBytes = deltaLongs << 3;
+ println("Copy longs : " + copyLongs + "\t bytes: " + copyBytes);
+ println("Overlap : " + (overlap * 100.0) + "%");
+ println("CopyUp : " + copyUp);
+ println("Backing longs: " + backingLongs + "\t bytes: " + backingBytes);
+
+ try (WritableHandle backHandle = WritableMemory.allocateDirect(backingBytes)) {
+ WritableMemory backingMem = backHandle.getWritable();
+ fill(backingMem); //fill mem with 0 thru copyLongs -1
+ //listMem(backingMem, "Original");
+ backingMem.copyTo(fromOffsetBytes, backingMem, toOffsetBytes, copyBytes);
+ //listMem(backingMem, "After");
+ checkMemLongs(backingMem, fromOffsetLongs, toOffsetLongs, copyLongs);
+ }
+ println("");
+ }
+
+ private static final void copyUsingDirectRegions(long copyLongs, double overlap, boolean copyUp) throws Exception {
+ println("Copy Using Direct Memory");
+ long overlapLongs = (long) (overlap * copyLongs);
+ long backingLongs = (2 * copyLongs) - overlapLongs;
+
+ long fromOffsetLongs;
+ long toOffsetLongs;
+ //long deltaLongs;
+
+ if (copyUp) {
+ fromOffsetLongs = 0;
+ toOffsetLongs = copyLongs - overlapLongs;
+ //deltaLongs = toOffsetLongs - fromOffsetLongs;
+ } else {
+ fromOffsetLongs = copyLongs - overlapLongs;
+ toOffsetLongs = 0;
+ //deltaLongs = toOffsetLongs - fromOffsetLongs;
+ }
+
+ long backingBytes = backingLongs << 3;
+ long copyBytes = copyLongs << 3;
+ long fromOffsetBytes = fromOffsetLongs << 3;
+ long toOffsetBytes = toOffsetLongs << 3;
+ //long deltaBytes = deltaLongs << 3;
+ println("Copy longs : " + copyLongs + "\t bytes: " + copyBytes);
+ println("Overlap : " + (overlap * 100.0) + "%");
+ println("CopyUp : " + copyUp);
+ println("Backing longs: " + backingLongs + "\t bytes: " + backingBytes);
+
+ try (WritableHandle backHandle = WritableMemory.allocateDirect(backingBytes)) {
+ WritableMemory backingMem = backHandle.getWritable();
+ fill(backingMem); //fill mem with 0 thru copyLongs -1
+ //listMem(backingMem, "Original");
+ WritableMemory reg1 = backingMem.writableRegion(fromOffsetBytes, copyBytes);
+ WritableMemory reg2 = backingMem.writableRegion(toOffsetBytes, copyBytes);
+
+ reg1.copyTo(0, reg2, 0, copyBytes);
+ //listMem(backingMem, "After");
+ checkMemLongs(reg2, fromOffsetLongs, 0, copyLongs);
+ }
+ println("");
+ }
+
+ private static final void fill(WritableMemory wmem) {
+ long longs = wmem.getCapacity() >>> 3;
+ for (long i = 0; i < longs; i++) { wmem.putLong(i << 3, i); } //fill with 0 .. (longs - 1)
+ //checkMemLongs(wmem, 0L, 0L, longs);
+ }
+
+ private static final void checkMemLongs(Memory mem, long fromOffsetLongs, long toOffsetLongs, long copyLongs) {
+ for (long i = 0; i < copyLongs; i++) {
+ long memVal = mem.getLong((toOffsetLongs + i) << 3);
+ assertEquals(memVal, fromOffsetLongs + i);
+ }
+ }
+
+ @SuppressWarnings("unused")
+ private static final void listMem(Memory mem, String comment) {
+ println(comment);
+ println("Idx\tValue");
+ long longs = mem.getCapacity() >>> 3;
+ for (long i = 0; i < longs; i++) {
+ println(i + "\t" + mem.getLong(i << 3));
+ }
+ }
+
+ @Test
+ public void printlnTest() {
+ println("PRINTING: "+this.getClass().getName());
+ }
+
+ /**
+ * @param s value to print
+ */
+ static void println(String s) {
+ //System.out.println(s); //disable here
+ }
+}
diff --git a/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/CopyMemoryTest.java b/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/CopyMemoryTest.java
new file mode 100644
index 0000000..fe37aad
--- /dev/null
+++ b/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/CopyMemoryTest.java
@@ -0,0 +1,184 @@
+/*
+ * 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.datasketches.memory.internal;
+
+import static org.apache.datasketches.memory.internal.Util.UNSAFE_COPY_THRESHOLD_BYTES;
+import static org.testng.Assert.assertEquals;
+
+import java.util.concurrent.ThreadLocalRandom;
+
+import org.apache.datasketches.memory.WritableHandle;
+import org.apache.datasketches.memory.Memory;
+import org.apache.datasketches.memory.WritableMemory;
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+public class CopyMemoryTest {
+
+ @Test
+ public void heapWSource() {
+ int k1 = 1 << 20; //longs
+ int k2 = 2 * k1;
+ WritableMemory srcMem = genMem(k1, false); //!empty
+ //println(srcMem.toHexString("src: ", 0, k1 << 3));
+ WritableMemory dstMem = genMem(k2, true);
+ srcMem.copyTo(0, dstMem, k1 << 3, k1 << 3);
+ //println(dstMem.toHexString("dst: ", 0, k2 << 3));
+ check(dstMem, k1, k1, 1);
+ }
+
+ @Test
+ public void heapROSource() {
+ int k1 = 1 << 20; //longs
+ int k2 = 2 * k1;
+ Memory srcMem = genMem(k1, false); //!empty
+ WritableMemory dstMem = genMem(k2, true);
+ srcMem.copyTo(0, dstMem, k1 << 3, k1 << 3);
+ check(dstMem, k1, k1, 1);
+ }
+
+ @Test
+ public void directWSource() throws Exception {
+ int k1 = 1 << 20; //longs
+ int k2 = 2 * k1;
+ try (WritableHandle wrh = genWRH(k1, false)) {
+ WritableMemory srcMem = wrh.getWritable();
+ WritableMemory dstMem = genMem(k2, true);
+ srcMem.copyTo(0, dstMem, k1 << 3, k1 << 3);
+ check(dstMem, k1, k1, 1);
+ }
+ }
+
+ @Test
+ public void directROSource() throws Exception {
+ int k1 = 1 << 20; //longs
+ int k2 = 2 * k1;
+ try (WritableHandle wrh = genWRH(k1, false)) {
+ Memory srcMem = wrh.get();
+ WritableMemory dstMem = genMem(k2, true);
+ srcMem.copyTo(0, dstMem, k1 << 3, k1 << 3);
+ check(dstMem, k1, k1, 1);
+ }
+ }
+
+ @Test
+ public void heapWSrcRegion() {
+ int k1 = 1 << 20; //longs
+ //gen baseMem of k1 longs w data
+ WritableMemory baseMem = genMem(k1, false); //!empty
+ //gen src region of k1/2 longs, off= k1/2
+ WritableMemory srcReg = baseMem.writableRegion((k1/2) << 3, (k1/2) << 3);
+ WritableMemory dstMem = genMem(2 * k1, true); //empty
+ srcReg.copyTo(0, dstMem, k1 << 3, (k1/2) << 3);
+ //println(dstMem.toHexString("dstMem: ", k1 << 3, (k1/2) << 3));
+ check(dstMem, k1, k1/2, (k1/2) + 1);
+ }
+
+ @Test
+ public void heapROSrcRegion() {
+ int k1 = 1 << 20; //longs
+ //gen baseMem of k1 longs w data
+ WritableMemory baseMem = genMem(k1, false); //!empty
+ //gen src region of k1/2 longs, off= k1/2
+ Memory srcReg = baseMem.region((k1/2) << 3, (k1/2) << 3);
+ WritableMemory dstMem = genMem(2 * k1, true); //empty
+ srcReg.copyTo(0, dstMem, k1 << 3, (k1/2) << 3);
+ check(dstMem, k1, k1/2, (k1/2) + 1);
+ }
+
+ @Test
+ public void directROSrcRegion() throws Exception {
+ int k1 = 1 << 20; //longs
+ //gen baseMem of k1 longs w data, direct
+ try (WritableHandle wrh = genWRH(k1, false)) {
+ Memory baseMem = wrh.get();
+ //gen src region of k1/2 longs, off= k1/2
+ Memory srcReg = baseMem.region((k1/2) << 3, (k1/2) << 3);
+ WritableMemory dstMem = genMem(2 * k1, true); //empty
+ srcReg.copyTo(0, dstMem, k1 << 3, (k1/2) << 3);
+ check(dstMem, k1, k1/2, (k1/2) + 1);
+ }
+ }
+
+ @Test
+ public void testOverlappingCopyLeftToRight() {
+ byte[] bytes = new byte[((UNSAFE_COPY_THRESHOLD_BYTES * 5) / 2) + 1];
+ ThreadLocalRandom.current().nextBytes(bytes);
+ byte[] referenceBytes = bytes.clone();
+ Memory referenceMem = Memory.wrap(referenceBytes);
+ WritableMemory mem = WritableMemory.writableWrap(bytes);
+ long copyLen = UNSAFE_COPY_THRESHOLD_BYTES * 2;
+ mem.copyTo(0, mem, UNSAFE_COPY_THRESHOLD_BYTES / 2, copyLen);
+ Assert.assertEquals(0, mem.compareTo(UNSAFE_COPY_THRESHOLD_BYTES / 2, copyLen, referenceMem, 0,
+ copyLen));
+ }
+
+ @Test
+ public void testOverlappingCopyRightToLeft() {
+ byte[] bytes = new byte[((UNSAFE_COPY_THRESHOLD_BYTES * 5) / 2) + 1];
+ ThreadLocalRandom.current().nextBytes(bytes);
+ byte[] referenceBytes = bytes.clone();
+ Memory referenceMem = Memory.wrap(referenceBytes);
+ WritableMemory mem = WritableMemory.writableWrap(bytes);
+ long copyLen = UNSAFE_COPY_THRESHOLD_BYTES * 2;
+ mem.copyTo(UNSAFE_COPY_THRESHOLD_BYTES / 2, mem, 0, copyLen);
+ Assert.assertEquals(0, mem.compareTo(0, copyLen, referenceMem, UNSAFE_COPY_THRESHOLD_BYTES / 2,
+ copyLen));
+ }
+
+ private static void check(Memory mem, int offsetLongs, int lengthLongs, int startValue) {
+ int offBytes = offsetLongs << 3;
+ for (long i = 0; i < lengthLongs; i++) {
+ assertEquals(mem.getLong(offBytes + (i << 3)), i + startValue);
+ }
+ }
+
+ private static WritableHandle genWRH(int longs, boolean empty) {
+ WritableHandle wrh = WritableMemory.allocateDirect(longs << 3);
+ WritableMemory mem = wrh.getWritable();
+ if (empty) {
+ mem.clear();
+ } else {
+ for (int i = 0; i < longs; i++) { mem.putLong(i << 3, i + 1); }
+ }
+ return wrh;
+ }
+
+
+ private static WritableMemory genMem(int longs, boolean empty) {
+ WritableMemory mem = WritableMemory.allocate(longs << 3);
+ if (!empty) {
+ for (int i = 0; i < longs; i++) { mem.putLong(i << 3, i + 1); }
+ }
+ return mem;
+ }
+
+ @Test
+ public void printlnTest() {
+ println("PRINTING: "+this.getClass().getName());
+ }
+
+ /**
+ * @param s value to print
+ */
+ static void println(String s) {
+ //System.out.println(s); //disable here
+ }
+}
diff --git a/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/DruidIssue11544Test.java b/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/DruidIssue11544Test.java
new file mode 100644
index 0000000..581bdda
--- /dev/null
+++ b/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/DruidIssue11544Test.java
@@ -0,0 +1,110 @@
+/*
+ * 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.datasketches.memory.internal;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertFalse;
+import static org.testng.Assert.assertNotNull;
+import static org.testng.Assert.assertTrue;
+
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+
+import org.apache.datasketches.memory.DefaultMemoryRequestServer;
+import org.apache.datasketches.memory.MemoryRequestServer;
+import org.apache.datasketches.memory.WritableMemory;
+import org.testng.annotations.Test;
+
+/**
+ * The original design provided the MemoryRequestServer callback only for Memory segments allocated via
+ * <i>WritableMemory.allocateDirect(...)</i> calls. Memory segments allocated via
+ * <i>WritableMemory.wrap(ByteBuffer)</i> did not have this capability. This was a major oversight since
+ * all off-heap memory in Druid is allocated using ByteBuffers! It is unusual that no one has
+ * uncovered this until August 2021. Nonetheless, the fix involves instrumenting all the paths involved
+ * in providing this callback mechanism for wrapped ByteBuffers.
+ *
+ * This issues was first identified in Druid Issue #11544 and then posted as DataSketches-java Issue #358.
+ * But the actual source of the problem was in Memory.
+ *
+ * This test mimics the Druid issue but at a much smaller scale.
+ *
+ * @author Lee Rhodes
+ *
+ */
+public class DruidIssue11544Test {
+
+ @Test
+ public void withByteBuffer() {
+ int initialLongs = 1000;
+ int size1 = initialLongs * 8;
+
+ //Start with a ByteBuffer
+ ByteBuffer bb = ByteBuffer.allocateDirect(size1);
+ bb.order(ByteOrder.nativeOrder());
+
+ //Wrap bb into WritableMemory
+ WritableMemory mem1 = WritableMemory.writableWrap(bb);
+ assertTrue(mem1.isDirect()); //confirm mem1 is off-heap
+
+ //Acquire the DefaultMemoryRequestServer
+ //NOTE: it is a policy decision to allow the DefaultMemoryServer to be set as a default.
+ // It might be set to null. So we need to check what the current policy is.
+ MemoryRequestServer svr = mem1.getMemoryRequestServer();
+ if (svr == null) {
+ svr = new DefaultMemoryRequestServer();
+ }
+ assertNotNull(svr);
+
+ //Request Bigger Memory
+ int size2 = size1 * 2;
+ WritableMemory mem2 = svr.request(mem1, size2);
+
+ //Confirm that mem2 is on the heap (the default) and 2X size1
+ assertFalse(mem2.isDirect());
+ assertEquals(mem2.getCapacity(), size2);
+
+ //Move data to new memory
+ mem1.copyTo(0, mem2, 0, size1);
+
+ //Prepare to request deallocation
+ //In the DefaultMemoryRequestServer, this is a no-op, so nothing is actually deallocated.
+ svr.requestClose(mem1, mem2);
+ assertTrue(mem1.isValid());
+ assertTrue(mem2.isValid());
+
+ //Now we are on the heap and need to grow again:
+ int size3 = size2 * 2;
+ WritableMemory mem3 = svr.request(mem2, size3);
+
+ //Confirm that mem3 is still on the heap and 2X of size2
+ assertFalse(mem3.isDirect());
+ assertEquals(mem3.getCapacity(), size3);
+
+ //Move data to new memory
+ mem2.copyTo(0, mem3, 0, size2);
+
+ //Prepare to request deallocation
+
+ svr.requestClose(mem2, mem3); //No-op
+ assertTrue(mem2.isValid());
+ assertTrue(mem3.isValid());
+ }
+
+}
diff --git a/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/ExampleMemoryRequestServerTest.java b/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/ExampleMemoryRequestServerTest.java
new file mode 100644
index 0000000..b970e4b
--- /dev/null
+++ b/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/ExampleMemoryRequestServerTest.java
@@ -0,0 +1,177 @@
+/*
+ * 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.datasketches.memory.internal;
+
+import static org.testng.Assert.assertFalse;
+
+import java.nio.ByteOrder;
+import java.util.IdentityHashMap;
+
+import org.apache.datasketches.memory.MemoryRequestServer;
+import org.apache.datasketches.memory.WritableHandle;
+import org.apache.datasketches.memory.WritableMemory;
+import org.testng.annotations.Test;
+
+/**
+ * Examples of how to use the MemoryRequestServer with a memory hungry client.
+ * @author Lee Rhodes
+ */
+public class ExampleMemoryRequestServerTest {
+
+ /**
+ * This version is without a TWR block.all of the memory allocations are done through the MemoryRequestServer
+ * and each is closed by the MemoryClient when it is done with each.
+ * @throws Exception
+ */
+ @Test
+ public void checkExampleMemoryRequestServer1() throws Exception {
+ int bytes = 8;
+ ExampleMemoryRequestServer svr = new ExampleMemoryRequestServer();
+ try (WritableHandle wh = WritableMemory.allocateDirect(8)) {
+ WritableMemory memStart = wh.getWritable();
+ WritableMemory wMem = svr.request(memStart, bytes);
+ MemoryClient client = new MemoryClient(wMem);
+ client.process();
+ svr.cleanup();
+ }
+ }
+
+ /**
+ * In this version the first memory allocation is done up front in a TWR block.
+ * And then the MemoryClient allocates new memories as needed, which are then closed
+ * by the MemoryClient when it is done with the new memory allocations.
+ * The initial allocation stays open until the end where it is closed at the end of the
+ * TWR scope.
+ * @throws Exception
+ */
+ @Test
+ public void checkExampleMemoryRequestServer2() throws Exception {
+ int bytes = 8;
+ ExampleMemoryRequestServer svr = new ExampleMemoryRequestServer();
+ try (WritableHandle handle = WritableMemory.allocateDirect(bytes, ByteOrder.nativeOrder(), svr)) {
+ WritableMemory memStart = handle.getWritable();
+ MemoryClient client = new MemoryClient(memStart);
+ client.process();
+ svr.cleanup(); //just to be sure all are closed.
+ }
+ }
+
+ @Test(expectedExceptions = IllegalArgumentException.class)
+ public void checkZeroCapacity() throws Exception {
+ ExampleMemoryRequestServer svr = new ExampleMemoryRequestServer();
+ try (WritableHandle wh = WritableMemory.allocateDirect(0, ByteOrder.nativeOrder(), svr)) {
+
+ }
+ }
+
+ /**
+ * This little client is never happy with how much memory it has been allocated and keeps
+ * requesting for more. When it does ask for more, it must copy its old data into the new
+ * memory, release the prior memory, and then continue working from there.
+ *
+ * <p>In reality, these memory requests should be quite rare.</p>
+ */
+ static class MemoryClient {
+ WritableMemory smallMem;
+ MemoryRequestServer svr;
+
+ MemoryClient(WritableMemory memStart) {
+ smallMem = memStart;
+ svr = memStart.getMemoryRequestServer();
+ }
+
+ void process() {
+ long cap1 = smallMem.getCapacity();
+ smallMem.fill((byte) 1); //fill it, but not big enough
+ println(smallMem.toHexString("Small", 0, (int)cap1));
+
+ WritableMemory bigMem = svr.request(smallMem, 2 * cap1); //get bigger mem
+ long cap2 = bigMem.getCapacity();
+ smallMem.copyTo(0, bigMem, 0, cap1); //copy data from small to big
+ svr.requestClose(smallMem, bigMem); //done with smallMem, release it
+
+ bigMem.fill(cap1, cap1, (byte) 2); //fill the rest of bigMem, still not big enough
+ println(bigMem.toHexString("Big", 0, (int)cap2));
+
+ WritableMemory giantMem = svr.request(bigMem, 2 * cap2); //get giant mem
+ long cap3 = giantMem.getCapacity();
+ bigMem.copyTo(0, giantMem, 0, cap2); //copy data from small to big
+ svr.requestClose(bigMem, giantMem); //done with bigMem, release it
+
+ giantMem.fill(cap2, cap2, (byte) 3); //fill the rest of giantMem
+ println(giantMem.toHexString("Giant", 0, (int)cap3));
+ svr.requestClose(giantMem, null); //done with giantMem, release it
+ }
+ }
+
+ /**
+ * This example MemoryRequestServer is simplistic but demonstrates one of many ways to
+ * possibly manage the continuous requests for larger memory and to track the associations between
+ * handles and their associated memory.
+ */
+ public static class ExampleMemoryRequestServer implements MemoryRequestServer {
+ IdentityHashMap<WritableMemory, WritableHandle> map = new IdentityHashMap<>();
+
+ @Override
+ public WritableMemory request(WritableMemory currentWMem, long capacityBytes) {
+ ByteOrder order = currentWMem.getTypeByteOrder();
+ WritableHandle handle = WritableMemory.allocateDirect(capacityBytes, order, this);
+ WritableMemory wmem = handle.getWritable();
+ map.put(wmem, handle); //We track the newly allocated memory and its handle.
+ return wmem;
+ }
+
+ @Override
+ //here we actually release it, in reality it might be a lot more complex.
+ public void requestClose(WritableMemory memToRelease, WritableMemory newMemory) {
+ WritableHandle handle = map.get(memToRelease);
+ if (handle != null && handle.getWritable() == memToRelease) {
+ try {
+ handle.close();
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+ }
+
+ public void cleanup() {
+ map.forEach((k,v) -> {
+ assertFalse(k.isValid()); //all entries in the map should be invalid
+ try {
+ v.close();
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ });
+ }
+ }
+
+ @Test
+ public void printlnTest() {
+ println("PRINTING: "+this.getClass().getName());
+ }
+
+ /**
+ * @param s value to print
+ */
+ static void println(String s) {
+ //System.out.println(s); //disable here
+ }
+}
diff --git a/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/IgnoredArrayOverflowTest.java b/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/IgnoredArrayOverflowTest.java
new file mode 100644
index 0000000..d9e0773
--- /dev/null
+++ b/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/IgnoredArrayOverflowTest.java
@@ -0,0 +1,104 @@
+/*
+ * 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.datasketches.memory.internal;
+
+import org.apache.datasketches.memory.WritableHandle;
+import org.apache.datasketches.memory.WritableMemory;
+import org.testng.annotations.AfterClass;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+public class IgnoredArrayOverflowTest {
+
+ private WritableHandle h;
+ private WritableMemory memory;
+ private static final long MAX_SIZE = (1L << 10); // use 1L << 31 to test int overrange
+
+ @BeforeClass
+ public void allocate() {
+ h = WritableMemory.allocateDirect(MAX_SIZE);
+ memory = h.getWritable();
+ }
+
+ @AfterClass
+ public void close() throws Exception {
+ h.close();
+ }
+
+ @Test
+ public void testCharArray() {
+ int size = (int) (memory.getCapacity() / 2);
+ char[] array = new char[size];
+ memory.getCharArray(0, array, 0, size);
+ memory.asBuffer().getCharArray(array, 0, size);
+ memory.putCharArray(0, array, 0, size);
+ memory.asWritableBuffer().putCharArray(array, 0, size);
+ }
+
+ @Test
+ public void testShortArray() {
+ int size = (int) (memory.getCapacity() / 2);
+ short[] array = new short[size];
+ memory.getShortArray(0, array, 0, size);
+ memory.asBuffer().getShortArray(array, 0, size);
+ memory.putShortArray(0, array, 0, size);
+ memory.asWritableBuffer().putShortArray(array, 0, size);
+ }
+
+ @Test
+ public void testIntArray() {
+ int size = (int) (memory.getCapacity() / 4);
+ int[] array = new int[size];
+ memory.getIntArray(0, array, 0, size);
+ memory.asBuffer().getIntArray(array, 0, size);
+ memory.putIntArray(0, array, 0, size);
+ memory.asWritableBuffer().putIntArray(array, 0, size);
+ }
+
+ @Test
+ public void testFloatArray() {
+ int size = (int) (memory.getCapacity() / 4);
+ float[] array = new float[size];
+ memory.getFloatArray(0, array, 0, size);
+ memory.asBuffer().getFloatArray(array, 0, size);
+ memory.putFloatArray(0, array, 0, size);
+ memory.asWritableBuffer().putFloatArray(array, 0, size);
+ }
+
+ @Test
+ public void testLongArray() {
+ int size = (int) (memory.getCapacity() / 8);
+ long[] array = new long[size];
+ memory.getLongArray(0, array, 0, size);
+ memory.asBuffer().getLongArray(array, 0, size);
+ memory.putLongArray(0, array, 0, size);
+ memory.asWritableBuffer().putLongArray(array, 0, size);
+ }
+
+ @Test
+ public void testDoubleArray() {
+ int size = (int) (memory.getCapacity() / 8);
+ double[] array = new double[size];
+ memory.getDoubleArray(0, array, 0, size);
+ memory.asBuffer().getDoubleArray(array, 0, size);
+ memory.putDoubleArray(0, array, 0, size);
+ memory.asWritableBuffer().putDoubleArray(array, 0, size);
+ }
+}
diff --git a/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/IsValidUtf8TestUtil.java b/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/IsValidUtf8TestUtil.java
new file mode 100644
index 0000000..cf01920
--- /dev/null
+++ b/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/IsValidUtf8TestUtil.java
@@ -0,0 +1,64 @@
+/*
+ * 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.datasketches.memory.internal;
+
+/**
+ * Stripped down version of
+ * https://github.com/protocolbuffers/protobuf/blob/master/java/core/src/test/java/com/google/protobuf/IsValidUtf8TestUtil.java
+ *
+ * <p>Copyright 2008 Google Inc. All rights reserved.
+ * https://developers.google.com/protocol-buffers/
+ * See LICENSE.
+ */
+public class IsValidUtf8TestUtil {
+
+ // 128 - [chars 0x0000 to 0x007f]
+ static final long ONE_BYTE_ROUNDTRIPPABLE_CHARACTERS = (0x007f - 0x0000) + 1;
+
+ // 128
+ static final long EXPECTED_ONE_BYTE_ROUNDTRIPPABLE_COUNT = ONE_BYTE_ROUNDTRIPPABLE_CHARACTERS;
+
+ // 1920 [chars 0x0080 to 0x07FF]
+ static final long TWO_BYTE_ROUNDTRIPPABLE_CHARACTERS = (0x07FF - 0x0080) + 1;
+
+ // 18,304
+ static final long EXPECTED_TWO_BYTE_ROUNDTRIPPABLE_COUNT =
+ // Both bytes are one byte characters
+ (long) Math.pow(EXPECTED_ONE_BYTE_ROUNDTRIPPABLE_COUNT, 2)
+ // The possible number of two byte characters
+ + TWO_BYTE_ROUNDTRIPPABLE_CHARACTERS;
+
+ // 2048
+ static final long THREE_BYTE_SURROGATES = 2 * 1024;
+
+ // 61,440 [chars 0x0800 to 0xFFFF, minus surrogates]
+ static final long THREE_BYTE_ROUNDTRIPPABLE_CHARACTERS =
+ ((0xFFFF - 0x0800) + 1) - THREE_BYTE_SURROGATES;
+
+ // 2,650,112
+ static final long EXPECTED_THREE_BYTE_ROUNDTRIPPABLE_COUNT =
+ // All one byte characters
+ (long) Math.pow(EXPECTED_ONE_BYTE_ROUNDTRIPPABLE_COUNT, 3)
+ // One two byte character and a one byte character
+ + (2 * TWO_BYTE_ROUNDTRIPPABLE_CHARACTERS * ONE_BYTE_ROUNDTRIPPABLE_CHARACTERS)
+ // Three byte characters
+ + THREE_BYTE_ROUNDTRIPPABLE_CHARACTERS;
+
+}
diff --git a/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/LeafImplTest.java b/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/LeafImplTest.java
new file mode 100644
index 0000000..f1ef17e
--- /dev/null
+++ b/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/LeafImplTest.java
@@ -0,0 +1,276 @@
+/*
+ * 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.datasketches.memory.internal;
+
+import static org.apache.datasketches.memory.internal.Util.NON_NATIVE_BYTE_ORDER;
+import static org.apache.datasketches.memory.internal.Util.otherByteOrder;
+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.io.IOException;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+
+import org.apache.datasketches.memory.MemoryRequestServer;
+import org.apache.datasketches.memory.WritableBuffer;
+import org.apache.datasketches.memory.WritableHandle;
+import org.apache.datasketches.memory.WritableMapHandle;
+import org.apache.datasketches.memory.WritableMemory;
+import org.testng.annotations.Test;
+
+/**
+ * @author Lee Rhodes
+ */
+public class LeafImplTest {
+ private static final ByteOrder NBO = ByteOrder.nativeOrder();
+ private static final ByteOrder NNBO = NON_NATIVE_BYTE_ORDER;
+ private static final MemoryRequestServer dummyMemReqSvr = new DummyMemoryRequestServer();
+
+ static class DummyMemoryRequestServer implements MemoryRequestServer {
+ @Override
+ public WritableMemory request(WritableMemory currentWMem, long capacityBytes) { return null; }
+ @Override
+ public void requestClose(WritableMemory memToClose, WritableMemory newMemory) { }
+ }
+
+ @Test
+ public void checkDirectLeafs() throws Exception {
+ long off = 0;
+ long cap = 128;
+ // Off Heap, Native order, No ByteBuffer, has MemReqSvr
+ try (WritableHandle wdh = WritableMemory.allocateDirect(cap, NBO, dummyMemReqSvr)) {
+ WritableMemory memNO = wdh.getWritable();
+ memNO.putShort(0, (short) 1);
+ assertNull(((BaseStateImpl)memNO).getUnsafeObject());
+ assertTrue(memNO.isDirect());
+ checkCombinations(memNO, off, cap, memNO.isDirect(), NBO, false, true);
+ }
+ // Off Heap, Non Native order, No ByteBuffer, has MemReqSvr
+ try (WritableHandle wdh = WritableMemory.allocateDirect(cap, NNBO, dummyMemReqSvr)) {
+ WritableMemory memNNO = wdh.getWritable();
+ memNNO.putShort(0, (short) 1);
+ assertNull(((BaseStateImpl)memNNO).getUnsafeObject());
+ assertTrue(memNNO.isDirect());
+ checkCombinations(memNNO, off, cap, memNNO.isDirect(), NNBO, false, true);
+ }
+ }
+
+ @Test
+ public void checkByteBufferLeafs() {
+ long off = 0;
+ long cap = 128;
+ //BB on heap, native order, has ByteBuffer, has MemReqSvr
+ ByteBuffer bb = ByteBuffer.allocate((int)cap);
+ bb.order(NBO);
+ bb.putShort(0, (short) 1);
+ WritableMemory mem = WritableMemory.writableWrap(bb, NBO, dummyMemReqSvr);
+ assertEquals(bb.isDirect(), mem.isDirect());
+ assertNotNull(((BaseStateImpl)mem).getUnsafeObject());
+ checkCombinations(mem, off, cap, mem.isDirect(), mem.getTypeByteOrder(), true, true);
+
+ //BB off heap, native order, has ByteBuffer, has MemReqSvr
+ ByteBuffer dbb = ByteBuffer.allocateDirect((int)cap);
+ dbb.order(NBO);
+ dbb.putShort(0, (short) 1);
+ mem = WritableMemory.writableWrap(dbb, NBO, dummyMemReqSvr);
+ assertEquals(dbb.isDirect(), mem.isDirect());
+ assertNull(((BaseStateImpl)mem).getUnsafeObject());
+ checkCombinations(mem, off, cap, mem.isDirect(), mem.getTypeByteOrder(), true, true);
+
+ //BB on heap, non native order, has ByteBuffer, has MemReqSvr
+ bb = ByteBuffer.allocate((int)cap);
+ bb.order(NNBO);
+ bb.putShort(0, (short) 1);
+ mem = WritableMemory.writableWrap(bb, NNBO, dummyMemReqSvr);
+ assertEquals(bb.isDirect(), mem.isDirect());
+ assertNotNull(((BaseStateImpl)mem).getUnsafeObject());
+ checkCombinations(mem, off, cap, mem.isDirect(), mem.getTypeByteOrder(), true, true);
+
+ //BB off heap, non native order, has ByteBuffer, has MemReqSvr
+ dbb = ByteBuffer.allocateDirect((int)cap);
+ dbb.order(NNBO);
+ dbb.putShort(0, (short) 1);
+ mem = WritableMemory.writableWrap(dbb, NNBO, dummyMemReqSvr);
+ assertEquals(dbb.isDirect(), mem.isDirect());
+ assertNull(((BaseStateImpl)mem).getUnsafeObject());
+ checkCombinations(mem, off, cap, mem.isDirect(), mem.getTypeByteOrder(), true, true);
+ }
+
+ @Test
+ public void checkMapLeafs() throws Exception {
+ long off = 0;
+ long cap = 128;
+ File file = new File("TestFile2.bin");
+ if (file.exists()) {
+ try {
+ java.nio.file.Files.delete(file.toPath());
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+ assertTrue(file.createNewFile());
+ assertTrue(file.setWritable(true, false)); //writable=true, ownerOnly=false
+ assertTrue(file.isFile());
+ file.deleteOnExit(); //comment out if you want to examine the file.
+ // Off Heap, Native order, No ByteBuffer, No MemReqSvr
+ try (WritableMapHandle wmh = WritableMemory.writableMap(file, off, cap, NBO)) {
+ WritableMemory memNO = wmh.getWritable();
+ memNO.putShort(0, (short) 1);
+ assertNull(((BaseStateImpl)memNO).getUnsafeObject());
+ assertTrue(memNO.isDirect());
+ checkCombinations(memNO, off, cap, memNO.isDirect(), NBO, false, false);
+ }
+ // Off heap, Non Native order, No ByteBuffer, no MemReqSvr
+ try (WritableMapHandle wmh = WritableMemory.writableMap(file, off, cap, NNBO)) {
+ WritableMemory memNNO = wmh.getWritable();
+ memNNO.putShort(0, (short) 1);
+ assertNull(((BaseStateImpl)memNNO).getUnsafeObject());
+ assertTrue(memNNO.isDirect());
+ checkCombinations(memNNO, off, cap, memNNO.isDirect(), NNBO, false, false);
+ }
+ }
+
+ @Test
+ public void checkHeapLeafs() {
+ long off = 0;
+ long cap = 128;
+ // On Heap, Native order, No ByteBuffer, No MemReqSvr
+ WritableMemory memNO = WritableMemory.allocate((int)cap); //assumes NBO
+ memNO.putShort(0, (short) 1);
+ assertNotNull(((BaseStateImpl)memNO).getUnsafeObject());
+ assertFalse(memNO.isDirect());
+ checkCombinations(memNO, off, cap, memNO.isDirect(), NBO, false, false);
+ // On Heap, Non-native order, No ByteBuffer, No MemReqSvr
+ WritableMemory memNNO = WritableMemory.allocate((int)cap, NNBO);
+ memNNO.putShort(0, (short) 1);
+ assertNotNull(((BaseStateImpl)memNNO).getUnsafeObject());
+ assertFalse(memNNO.isDirect());
+ checkCombinations(memNNO, off, cap, memNNO.isDirect(), NNBO, false, false);
+ }
+
+ private static void checkCombinations(WritableMemory mem, long off, long cap,
+ boolean direct, ByteOrder bo, boolean hasByteBuffer, boolean hasMemReqSvr) {
+ ByteOrder oo = otherByteOrder(bo);
+
+ assertEquals(mem.writableRegion(off, cap, bo).getShort(0), 1);
+ assertEquals(mem.writableRegion(off, cap, oo).getShort(0), 256);
+
+ assertEquals(mem.asWritableBuffer(bo).getShort(0), 1);
+ assertEquals(mem.asWritableBuffer(oo).getShort(0), 256);
+
+ ByteBuffer bb = mem.getByteBuffer();
+ assertTrue( hasByteBuffer ? bb != null : bb == null);
+
+ assertTrue(mem.getTypeByteOrder() == bo);
+
+ if (hasMemReqSvr) { assertTrue(mem.getMemoryRequestServer() instanceof DummyMemoryRequestServer); }
+
+ Object obj = ((BaseStateImpl)mem).getUnsafeObject();
+ if (direct) {
+ assertTrue(mem.isDirect());
+ assertNull(obj);
+ } else {
+ assertFalse(mem.isDirect());
+ assertNotNull(obj);
+ }
+
+ assertTrue(mem.isValid() == true);
+
+ WritableBuffer buf = mem.asWritableBuffer();
+
+ assertEquals(buf.writableRegion(off, cap, bo).getShort(0), 1);
+ assertEquals(buf.writableRegion(off, cap, oo).getShort(0), 256);
+ assertEquals(buf.writableDuplicate(bo).getShort(0), 1);
+ assertEquals(buf.writableDuplicate(oo).getShort(0), 256);
+
+ bb = buf.getByteBuffer();
+ assertTrue(hasByteBuffer ? bb != null : bb == null);
+
+ assertTrue(buf.getTypeByteOrder() == bo);
+
+ if (hasMemReqSvr) { assertTrue(buf.getMemoryRequestServer() instanceof DummyMemoryRequestServer); }
+
+ obj = ((BaseStateImpl)buf).getUnsafeObject();
+ if (direct) {
+ assertTrue(buf.isDirect());
+ assertNull(obj);
+ } else {
+ assertFalse(buf.isDirect());
+ assertNotNull(obj);
+ }
+
+ assertTrue(buf.isValid() == true);
+
+ WritableMemory nnMem = mem.writableRegion(off, cap, oo);
+
+ assertEquals(nnMem.writableRegion(off, cap, bo).getShort(0), 1);
+ assertEquals(nnMem.writableRegion(off, cap, oo).getShort(0), 256);
+ assertEquals(nnMem.asWritableBuffer(bo).getShort(0), 1);
+ assertEquals(nnMem.asWritableBuffer(oo).getShort(0), 256);
+
+ bb = nnMem.getByteBuffer();
+ assertTrue( hasByteBuffer ? bb != null : bb == null);
+
+ assertTrue(nnMem.getTypeByteOrder() == oo);
+
+ if (hasMemReqSvr) { assertTrue(nnMem.getMemoryRequestServer() instanceof DummyMemoryRequestServer); }
+
+ obj = ((BaseStateImpl)nnMem).getUnsafeObject();
+ if (direct) {
+ assertTrue(nnMem.isDirect());
+ assertNull(obj);
+ } else {
+ assertFalse(nnMem.isDirect());
+ assertNotNull(obj);
+ }
+
+ assertTrue(nnMem.isValid() == true);
+
+ WritableBuffer nnBuf = mem.asWritableBuffer(oo);
+
+ assertEquals(nnBuf.writableRegion(off, cap, bo).getShort(0), 1);
+ assertEquals(nnBuf.writableRegion(off, cap, oo).getShort(0), 256);
+ assertEquals(nnBuf.writableDuplicate(bo).getShort(0), 1);
+ assertEquals(nnBuf.writableDuplicate(oo).getShort(0), 256);
+
+ bb = nnBuf.getByteBuffer();
+ assertTrue( hasByteBuffer ? bb != null : bb == null);
+
+ assertTrue(nnBuf.getTypeByteOrder() == oo);
+
+ if (hasMemReqSvr) { assertTrue(nnBuf.getMemoryRequestServer() instanceof DummyMemoryRequestServer); }
+
+ obj = ((BaseStateImpl)nnBuf).getUnsafeObject();
+ if (direct) {
+ assertTrue(nnBuf.isDirect());
+ assertNull(obj);
+ } else {
+ assertFalse(nnBuf.isDirect());
+ assertNotNull(obj);
+ }
+
+ assertTrue(nnBuf.isValid() == true);
+ }
+
+}
diff --git a/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/MemoryBoundaryCheckTest.java b/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/MemoryBoundaryCheckTest.java
new file mode 100644
index 0000000..1362f44
--- /dev/null
+++ b/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/MemoryBoundaryCheckTest.java
@@ -0,0 +1,205 @@
+/*
+ * 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.datasketches.memory.internal;
+
+import org.apache.datasketches.memory.WritableBuffer;
+import org.apache.datasketches.memory.WritableMemory;
+import org.testng.annotations.Test;
+
+public class MemoryBoundaryCheckTest {
+
+ private final WritableBuffer writableBuffer = WritableMemory.allocate(8).asWritableBuffer();
+
+ @Test
+ public void testGetBoolean() {
+ writableBuffer.getBoolean(7);
+ try {
+ writableBuffer.getBoolean(8);
+ throw new RuntimeException("Expected AssertionError");
+ } catch (final AssertionError expected) {
+ // ignore
+ }
+ }
+
+ @Test
+ public void testPutBoolean() {
+ writableBuffer.putBoolean(7, true);
+ try {
+ writableBuffer.putBoolean(8, true);
+ throw new RuntimeException("Expected AssertionError");
+ } catch (final AssertionError expected) {
+ // ignore
+ }
+ }
+
+ @Test
+ public void testGetByte() {
+ writableBuffer.getByte(7);
+ try {
+ writableBuffer.getByte(8);
+ throw new RuntimeException("Expected AssertionError");
+ } catch (final AssertionError expected) {
+ // ignore
+ }
+ }
+
+ @Test
+ public void testPutByte() {
+ writableBuffer.putByte(7, (byte) 1);
+ try {
+ writableBuffer.putByte(8, (byte) 1);
+ throw new RuntimeException("Expected AssertionError");
+ } catch (final AssertionError expected) {
+ // ignore
+ }
+ }
+
+ @Test
+ public void testGetChar() {
+ writableBuffer.getChar(6);
+ try {
+ writableBuffer.getChar(7);
+ throw new RuntimeException("Expected AssertionError");
+ } catch (final AssertionError expected) {
+ // ignore
+ }
+ }
+
+ @Test
+ public void testPutChar() {
+ writableBuffer.putChar(6, 'a');
+ try {
+ writableBuffer.putChar(7, 'a');
+ throw new RuntimeException("Expected AssertionError");
+ } catch (final AssertionError expected) {
+ // ignore
+ }
+ }
+
+ @Test
+ public void testGetShort() {
+ writableBuffer.getShort(6);
+ try {
+ writableBuffer.getShort(7);
+ throw new RuntimeException("Expected AssertionError");
+ } catch (final AssertionError expected) {
+ // ignore
+ }
+ }
+
+ @Test
+ public void testPutShort() {
+ writableBuffer.putShort(6, (short) 1);
+ try {
+ writableBuffer.putShort(7, (short) 1);
+ throw new RuntimeException("Expected AssertionError");
+ } catch (final AssertionError expected) {
+ // ignore
+ }
+ }
+
+ @Test
+ public void testGetInt() {
+ writableBuffer.getInt(4);
+ try {
+ writableBuffer.getInt(5);
+ throw new RuntimeException("Expected AssertionError");
+ } catch (final AssertionError expected) {
+ // ignore
+ }
+ }
+
+ @Test
+ public void testPutInt() {
+ writableBuffer.putInt(4, 1);
+ try {
+ writableBuffer.putInt(5, 1);
+ throw new RuntimeException("Expected AssertionError");
+ } catch (final AssertionError expected) {
+ // ignore
+ }
+ }
+
+ @Test
+ public void testGetFloat() {
+ writableBuffer.getFloat(4);
+ try {
+ writableBuffer.getFloat(5);
+ throw new RuntimeException("Expected AssertionError");
+ } catch (final AssertionError expected) {
+ // ignore
+ }
+ }
+
+ @Test
+ public void testPutFloat() {
+ writableBuffer.putFloat(4, 1f);
+ try {
+ writableBuffer.putFloat(5, 1f);
+ throw new RuntimeException("Expected AssertionError");
+ } catch (final AssertionError expected) {
+ // ignore
+ }
+ }
+
+ @Test
+ public void testGetLong() {
+ writableBuffer.getLong(0);
+ try {
+ writableBuffer.getLong(1);
+ throw new RuntimeException("Expected AssertionError");
+ } catch (final AssertionError expected) {
+ // ignore
+ }
+ }
+
+ @Test
+ public void testPutLong() {
+ writableBuffer.putLong(0, 1L);
+ try {
+ writableBuffer.putLong(1, 1L);
+ throw new RuntimeException("Expected AssertionError");
+ } catch (final AssertionError expected) {
+ // ignore
+ }
+ }
+
+ @Test
+ public void testGetDouble() {
+ writableBuffer.getDouble(0);
+ try {
+ writableBuffer.getDouble(1);
+ throw new RuntimeException("Expected AssertionError");
+ } catch (final AssertionError expected) {
+ // ignore
+ }
+ }
+
+ @Test
+ public void testPutDouble() {
+ writableBuffer.putDouble(0, 1d);
+ try {
+ writableBuffer.putDouble(1, 1d);
+ throw new RuntimeException("Expected AssertionError");
+ } catch (final AssertionError expected) {
+ // ignore
+ }
+ }
+}
diff --git a/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/MemoryCleanerTest.java b/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/MemoryCleanerTest.java
new file mode 100644
index 0000000..d7b40ea
--- /dev/null
+++ b/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/MemoryCleanerTest.java
@@ -0,0 +1,62 @@
+/*
+ * 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.datasketches.memory.internal;
+
+import static org.testng.Assert.assertFalse;
+import static org.testng.Assert.assertTrue;
+
+import java.util.concurrent.atomic.AtomicBoolean;
+
+import org.testng.annotations.Test;
+
+public class MemoryCleanerTest {
+
+ @Test
+ public void cleanerDeallocates() {
+ SimpleDeallocator deallocator = new SimpleDeallocator();
+ MemoryCleaner cleaner = new MemoryCleaner(this, deallocator);
+ cleaner.clean();
+ assertTrue(SimpleDeallocator.getHasRun());
+ }
+
+ @Test
+ public void noDeallocation() {
+ SimpleDeallocator deallocator = new SimpleDeallocator();
+ new MemoryCleaner(this, deallocator);
+ assertFalse(SimpleDeallocator.getHasRun());
+ }
+
+ static final class SimpleDeallocator implements Runnable {
+ static final AtomicBoolean hasRun = new AtomicBoolean();
+
+ SimpleDeallocator() {
+ hasRun.set(false);
+ }
+
+ @Override
+ public void run() {
+ hasRun.compareAndSet(false, true);
+ }
+
+ public static Boolean getHasRun() {
+ return hasRun.get();
+ }
+ }
+}
diff --git a/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/MemoryCloseExceptionTest.java b/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/MemoryCloseExceptionTest.java
new file mode 100644
index 0000000..249d432
--- /dev/null
+++ b/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/MemoryCloseExceptionTest.java
@@ -0,0 +1,39 @@
+/*
+ * 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.datasketches.memory.internal;
+
+import org.apache.datasketches.memory.MemoryCloseException;
+import org.testng.annotations.Test;
+
+public class MemoryCloseExceptionTest {
+
+ @Test
+ public void checkNoArgs() {
+ try {
+ throw new MemoryCloseException();
+ } catch (final MemoryCloseException e) {}
+
+ try {
+ throw new MemoryCloseException("Test Exception");
+ } catch (final MemoryCloseException e) {}
+ }
+}
+
+
diff --git a/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/MemoryReadWriteSafetyTest.java b/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/MemoryReadWriteSafetyTest.java
new file mode 100644
index 0000000..553c432
--- /dev/null
+++ b/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/MemoryReadWriteSafetyTest.java
@@ -0,0 +1,227 @@
+/*
+ * 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.datasketches.memory.internal;
+
+import java.io.File;
+import java.io.RandomAccessFile;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+
+import org.apache.datasketches.memory.MapHandle;
+import org.apache.datasketches.memory.Memory;
+import org.apache.datasketches.memory.ReadOnlyException;
+import org.apache.datasketches.memory.WritableMemory;
+import org.testng.annotations.Test;
+
+public class MemoryReadWriteSafetyTest {
+
+ // Test various operations with read-only Memory
+
+ final WritableMemory mem = (WritableMemory) Memory.wrap(new byte[8]);
+
+ @Test(expectedExceptions = AssertionError.class)
+ public void testPutByte() {
+ mem.putByte(0, (byte) 1);
+ }
+
+ @Test(expectedExceptions = AssertionError.class)
+ public void testPutBoolean() {
+ mem.putBoolean(0, true);
+ }
+
+ @Test(expectedExceptions = AssertionError.class)
+ public void testPutShort() {
+ mem.putShort(0, (short) 1);
+ }
+
+ @Test(expectedExceptions = AssertionError.class)
+ public void testPutChar() {
+ mem.putChar(0, (char) 1);
+ }
+
+ @Test(expectedExceptions = AssertionError.class)
+ public void testPutInt() {
+ mem.putInt(0, 1);
+ }
+
+ @Test(expectedExceptions = AssertionError.class)
+ public void testPutLong() {
+ mem.putLong(0, 1);
+ }
+
+ @Test(expectedExceptions = AssertionError.class)
+ public void testPutFloat() {
+ mem.putFloat(0, 1);
+ }
+
+ @Test(expectedExceptions = AssertionError.class)
+ public void testPutDouble() {
+ mem.putDouble(0, 1);
+ }
+
+ @Test(expectedExceptions = ReadOnlyException.class)
+ public void testPutByteArray() {
+ mem.putByteArray(0, new byte[] {1}, 0, 1);
+ }
+
+ @Test(expectedExceptions = ReadOnlyException.class)
+ public void testPutBooleanArray() {
+ mem.putBooleanArray(0, new boolean[] {true}, 0, 1);
+ }
+
+ @Test(expectedExceptions = ReadOnlyException.class)
+ public void testPutShortArray() {
+ mem.putShortArray(0, new short[] {1}, 0, 1);
+ }
+
+ @Test(expectedExceptions = ReadOnlyException.class)
+ public void testPutCharArray() {
+ mem.putCharArray(0, new char[] {1}, 0, 1);
+ }
+
+ @Test(expectedExceptions = ReadOnlyException.class)
+ public void testPutIntArray() {
+ mem.putIntArray(0, new int[] {1}, 0, 1);
+ }
+
+ @Test(expectedExceptions = ReadOnlyException.class)
+ public void testPutLongArray() {
+ mem.putLongArray(0, new long[] {1}, 0, 1);
+ }
+
+ @Test(expectedExceptions = ReadOnlyException.class)
+ public void testPutFloatArray() {
+ mem.putFloatArray(0, new float[] {1}, 0, 1);
+ }
+
+ @Test(expectedExceptions = ReadOnlyException.class)
+ public void testDoubleByteArray() {
+ mem.putDoubleArray(0, new double[] {1}, 0, 1);
+ }
+
+ // Now, test that various ways to obtain a read-only memory produce a read-only memory indeed
+
+ @Test(expectedExceptions = AssertionError.class)
+ public void testWritableMemoryRegion() {
+ WritableMemory mem1 = (WritableMemory) WritableMemory.allocate(8).region(0, 8);
+ mem1.putInt(0, 1);
+ }
+
+ @Test(expectedExceptions = AssertionError.class)
+ public void testByteArrayWrap() {
+ WritableMemory mem1 = (WritableMemory) Memory.wrap(new byte[8]);
+ mem1.putInt(0, 1);
+ }
+
+ @Test(expectedExceptions = AssertionError.class)
+ public void testByteArrayWrapWithBO() {
+ WritableMemory mem1 = (WritableMemory) Memory.wrap(new byte[8], ByteOrder.nativeOrder());
+ mem1.putInt(0, 1);
+ }
+
+ @Test(expectedExceptions = AssertionError.class)
+ public void testByteArrayWrapWithOffsetsAndBO() {
+ WritableMemory mem1 = (WritableMemory) Memory.wrap(new byte[8], 0, 4, ByteOrder.nativeOrder());
+ mem1.putInt(0, 1);
+ }
+
+ @Test(expectedExceptions = AssertionError.class)
+ public void testBooleanArrayWrap() {
+ WritableMemory mem1 = (WritableMemory) Memory.wrap(new boolean[8]);
+ mem1.putInt(0, 1);
+ }
+
+ @Test(expectedExceptions = AssertionError.class)
+ public void testShortArrayWrap() {
+ WritableMemory mem1 = (WritableMemory) Memory.wrap(new short[8]);
+ mem1.putInt(0, 1);
+ }
+
+ @Test(expectedExceptions = AssertionError.class)
+ public void testCharArrayWrap() {
+ WritableMemory mem1 = (WritableMemory) Memory.wrap(new char[8]);
+ mem1.putInt(0, 1);
+ }
+
+ @Test(expectedExceptions = AssertionError.class)
+ public void testIntArrayWrap() {
+ WritableMemory mem1 = (WritableMemory) Memory.wrap(new int[8]);
+ mem1.putInt(0, 1);
+ }
+
+ @Test(expectedExceptions = AssertionError.class)
+ public void testLongArrayWrap() {
+ WritableMemory mem1 = (WritableMemory) Memory.wrap(new long[8]);
+ mem1.putInt(0, 1);
+ }
+
+ @Test(expectedExceptions = AssertionError.class)
+ public void testFloatArrayWrap() {
+ WritableMemory mem1 = (WritableMemory) Memory.wrap(new float[8]);
+ mem1.putInt(0, 1);
+ }
+
+ @Test(expectedExceptions = AssertionError.class)
+ public void testDoubleArrayWrap() {
+ WritableMemory mem1 = (WritableMemory) Memory.wrap(new double[8]);
+ mem1.putInt(0, 1);
+ }
+
+ @Test(expectedExceptions = AssertionError.class)
+ public void testByteBufferWrap() {
+ WritableMemory mem1 = (WritableMemory) Memory.wrap(ByteBuffer.allocate(8));
+ mem1.putInt(0, 1);
+ }
+
+ //@SuppressWarnings("resource")
+ @Test(expectedExceptions = AssertionError.class)
+ public void testMapFile() throws Exception {
+ File tempFile = File.createTempFile("test", null);
+ tempFile.deleteOnExit();
+ try (RandomAccessFile raf = new RandomAccessFile(tempFile, "rw")) {
+ raf.setLength(8);
+ //System.out.println(UtilTest.getFileAttributes(tempFile));
+ try (MapHandle h = Memory.map(tempFile)) {
+ ((WritableMemory) h.get()).putInt(0, 1);
+ }
+ }
+ }
+
+ @SuppressWarnings("resource")
+ @Test(expectedExceptions = AssertionError.class)
+ public void testMapFileWithOffsetsAndBO() throws Exception {
+ File tempFile = File.createTempFile("test", "test");
+ tempFile.deleteOnExit();
+ new RandomAccessFile(tempFile, "rw").setLength(8);
+ try (MapHandle h = Memory.map(tempFile, 0, 4, ByteOrder.nativeOrder())) {
+ ((WritableMemory) h.get()).putInt(0, 1);
+ }
+ }
+
+ @SuppressWarnings("resource")
+ @Test(expectedExceptions = IllegalArgumentException.class)
+ public void testMapFileBeyondTheFileSize() throws Exception {
+ File tempFile = File.createTempFile("test", "test");
+ tempFile.deleteOnExit();
+ new RandomAccessFile(tempFile, "rw").setLength(8);
+ try (MapHandle unused = Memory.map(tempFile, 0, 16, ByteOrder.nativeOrder())) {
+ }
+ }
+}
diff --git a/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/MemoryTest.java b/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/MemoryTest.java
new file mode 100644
index 0000000..045c59f
--- /dev/null
+++ b/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/MemoryTest.java
@@ -0,0 +1,479 @@
+/*
+ * 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.internal;
+
+import static org.apache.datasketches.memory.internal.Util.getResourceFile;
+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.apache.datasketches.memory.BaseState;
+import org.apache.datasketches.memory.MapHandle;
+import org.apache.datasketches.memory.Memory;
+import org.apache.datasketches.memory.WritableBuffer;
+import org.apache.datasketches.memory.WritableHandle;
+import org.apache.datasketches.memory.WritableMemory;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+import org.testng.collections.Lists;
+
+public class MemoryTest {
+ private static final String LS = System.getProperty("line.separator");
+
+ @BeforeClass
+ public void setReadOnly() {
+ UtilTest.setGettysburgAddressFileToReadOnly();
+ }
+
+ @Test
+ public void checkDirectRoundTrip() throws Exception {
+ int n = 1024; //longs
+ try (WritableHandle wh = WritableMemory.allocateDirect(n * 8)) {
+ WritableMemory mem = wh.getWritable();
+ 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.writableWrap(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.writableWrap(new boolean[0]);
+ Memory memZeroLengthArrayByte = WritableMemory.writableWrap(new byte[0]);
+ Memory memZeroLengthArrayChar = WritableMemory.writableWrap(new char[0]);
+ Memory memZeroLengthArrayShort = WritableMemory.writableWrap(new short[0]);
+ Memory memZeroLengthArrayInt = WritableMemory.writableWrap(new int[0]);
+ Memory memZeroLengthArrayLong = WritableMemory.writableWrap(new long[0]);
+ Memory memZeroLengthArrayFloat = WritableMemory.writableWrap(new float[0]);
+ Memory memZeroLengthArrayDouble = WritableMemory.writableWrap(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.writableWrap(ByteBuffer.allocate(0)));
+ memoryToCheck.add(WritableMemory.writableWrap(new boolean[0]));
+ memoryToCheck.add(WritableMemory.writableWrap(new byte[0]));
+ memoryToCheck.add(WritableMemory.writableWrap(new char[0]));
+ memoryToCheck.add(WritableMemory.writableWrap(new short[0]));
+ memoryToCheck.add(WritableMemory.writableWrap(new int[0]));
+ memoryToCheck.add(WritableMemory.writableWrap(new long[0]));
+ memoryToCheck.add(WritableMemory.writableWrap(new float[0]));
+ memoryToCheck.add(WritableMemory.writableWrap(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.writableWrap(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.writableWrap(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() == ByteOrder.nativeOrder());
+ 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, Util.NON_NATIVE_BYTE_ORDER); //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.writableWrap(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.writableWrap(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, Util.NON_NATIVE_BYTE_ORDER);
+ 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() throws Exception {
+ int bytes = 64 * 8;
+ WritableHandle wh = WritableMemory.allocateDirect(bytes);
+ WritableMemory wmem = wh.getWritable();
+ wh.close();
+ //with -ea assert: Memory not valid.
+ //with -da sometimes segfaults, sometimes passes!
+ wmem.getLong(0);
+ }
+
+ @Test(expectedExceptions = AssertionError.class)
+ public void checkRegionUseAfterFree() throws Exception {
+ int bytes = 64;
+ 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 checkMonitorDirectStats() throws Exception {
+ int bytes = 1024;
+ long curAllocations = BaseState.getCurrentDirectMemoryAllocations();
+ long curAllocated = BaseState.getCurrentDirectMemoryAllocated();
+ if (curAllocations != 0) { System.err.println(curAllocations + " should be zero!"); }
+ WritableHandle wh1 = WritableMemory.allocateDirect(bytes);
+ WritableHandle wh2 = WritableMemory.allocateDirect(bytes);
+ assertEquals(BaseState.getCurrentDirectMemoryAllocations(), 2L + curAllocations);
+ assertEquals(BaseState.getCurrentDirectMemoryAllocated(), 2 * bytes + curAllocated);
+
+ wh1.close();
+ assertEquals(BaseState.getCurrentDirectMemoryAllocations(), 1L + curAllocations);
+ assertEquals(BaseState.getCurrentDirectMemoryAllocated(), bytes + curAllocated);
+
+ wh2.close();
+ wh2.close(); //check that it doesn't go negative.
+ //even though the handles are closed, these methods are static access
+ assertEquals(BaseState.getCurrentDirectMemoryAllocations(), 0L + curAllocations);
+ assertEquals(BaseState.getCurrentDirectMemoryAllocated(), 0L + curAllocated);
+ }
+
+ @Test
+ public void checkMonitorDirectMapStats() throws Exception {
+ File file = getResourceFile("GettysburgAddress.txt");
+ 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.
+ //even though the handles are closed, these methods are static access
+ assertEquals(BaseState.getCurrentDirectMemoryMapAllocations(), 0L);
+ assertEquals(BaseState.getCurrentDirectMemoryMapAllocated(), 0L);
+ }
+
+ @Test
+ public void checkMemReqSvr() throws Exception {
+ WritableMemory wmem;
+ WritableBuffer wbuf;
+ if (BaseState.defaultMemReqSvr == null) { //This is a policy choice
+ //ON HEAP
+ wmem = WritableMemory.writableWrap(new byte[16]);
+ assertNull(wmem.getMemoryRequestServer());
+ wbuf = wmem.asWritableBuffer();
+ assertNull(wbuf.getMemoryRequestServer());
+ //OFF HEAP
+ try (WritableHandle wdh = WritableMemory.allocateDirect(16)) { //OFF HEAP
+ wmem = wdh.getWritable();
+ assertNull(wmem.getMemoryRequestServer());
+ wbuf = wmem.asWritableBuffer();
+ assertNull(wbuf.getMemoryRequestServer());
+ }
+ //ByteBuffer
+ ByteBuffer bb = ByteBuffer.allocate(16);
+ wmem = WritableMemory.writableWrap(bb);
+ assertNull(wmem.getMemoryRequestServer());
+ wbuf = wmem.asWritableBuffer();
+ assertNull(wbuf.getMemoryRequestServer());
+ } else {
+ //ON HEAP
+ wmem = WritableMemory.writableWrap(new byte[16]);
+ assertNotNull(wmem.getMemoryRequestServer());
+ wbuf = wmem.asWritableBuffer();
+ assertNotNull(wbuf.getMemoryRequestServer());
+ //OFF HEAP
+ try (WritableHandle wdh = WritableMemory.allocateDirect(16)) {
+ WritableMemory wmem2 = wdh.getWritable();
+ assertNotNull(wmem2.getMemoryRequestServer());
+ wbuf = wmem.asWritableBuffer();
+ assertNotNull(wbuf.getMemoryRequestServer());
+ }
+ //ByteBuffer
+ ByteBuffer bb = ByteBuffer.allocate(16);
+ wmem = WritableMemory.writableWrap(bb);
+ assertNotNull(wmem.getMemoryRequestServer());
+ wbuf = wmem.asWritableBuffer();
+ assertNotNull(wbuf.getMemoryRequestServer());
+ }
+ }
+
+ @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 NNO
+ Memory mem = Memory.wrap(bb, ByteOrder.LITTLE_ENDIAN);
+ assertEquals(mem.getChar(0), 256);
+ }
+
+ @Test
+ public void printlnTest() {
+ println("PRINTING: "+this.getClass().getName());
+ }
+
+ static void println(final Object o) {
+ if (o == null) { print(LS); }
+ else { print(o.toString() + LS); }
+ }
+
+ /**
+ * @param o value to print
+ */
+ static void print(final Object o) {
+ if (o != null) {
+ //System.out.print(o.toString()); //disable here
+ }
+ }
+
+}
diff --git a/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/MemoryWriteToTest.java b/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/MemoryWriteToTest.java
new file mode 100644
index 0000000..78e51ab
--- /dev/null
+++ b/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/MemoryWriteToTest.java
@@ -0,0 +1,96 @@
+/*
+ * 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.datasketches.memory.internal;
+
+import static org.apache.datasketches.memory.internal.Util.UNSAFE_COPY_THRESHOLD_BYTES;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.nio.channels.Channels;
+import java.nio.channels.WritableByteChannel;
+import java.util.concurrent.ThreadLocalRandom;
+
+import org.apache.datasketches.memory.WritableHandle;
+import org.apache.datasketches.memory.Memory;
+import org.apache.datasketches.memory.WritableMemory;
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+public class MemoryWriteToTest {
+
+ @Test
+ public void testOnHeap() throws IOException {
+ testWriteTo(createRandomBytesMemory(0));
+ testWriteTo(createRandomBytesMemory(7));
+ testWriteTo(createRandomBytesMemory(1023));
+ testWriteTo(createRandomBytesMemory(10_000));
+ testWriteTo(createRandomBytesMemory(UNSAFE_COPY_THRESHOLD_BYTES * 5));
+ testWriteTo(createRandomBytesMemory((UNSAFE_COPY_THRESHOLD_BYTES * 5) + 10));
+ }
+
+ @Test
+ public void testOnHeapInts() throws IOException {
+ testWriteTo(createRandomIntsMemory(0));
+ testWriteTo(createRandomIntsMemory(7));
+ testWriteTo(createRandomIntsMemory(1023));
+ testWriteTo(createRandomIntsMemory(10_000));
+ testWriteTo(createRandomIntsMemory(UNSAFE_COPY_THRESHOLD_BYTES * 5));
+ testWriteTo(createRandomIntsMemory((UNSAFE_COPY_THRESHOLD_BYTES * 5) + 10));
+ }
+
+ @Test
+ public void testOffHeap() throws Exception {
+ try (WritableHandle handle =
+ WritableMemory.allocateDirect((UNSAFE_COPY_THRESHOLD_BYTES * 5) + 10)) {
+ WritableMemory mem = handle.getWritable();
+ testWriteTo(mem.region(0, 0));
+ testOffHeap(mem, 7);
+ testOffHeap(mem, 1023);
+ testOffHeap(mem, 10_000);
+ testOffHeap(mem, UNSAFE_COPY_THRESHOLD_BYTES * 5);
+ testOffHeap(mem, (UNSAFE_COPY_THRESHOLD_BYTES * 5) + 10);
+ }
+ }
+
+ private static void testOffHeap(WritableMemory mem, int size) throws IOException {
+ createRandomBytesMemory(size).copyTo(0, mem, 0, size);
+ testWriteTo(mem.region(0, size));
+ }
+
+ private static Memory createRandomBytesMemory(int size) {
+ byte[] bytes = new byte[size];
+ ThreadLocalRandom.current().nextBytes(bytes);
+ return Memory.wrap(bytes);
+ }
+
+ private static Memory createRandomIntsMemory(int size) {
+ int[] ints = ThreadLocalRandom.current().ints(size).toArray();
+ return Memory.wrap(ints);
+ }
+
+ private static void testWriteTo(Memory mem) throws IOException {
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ try (WritableByteChannel out = Channels.newChannel(baos)) {
+ mem.writeTo(0, mem.getCapacity(), out);
+ }
+ byte[] result = baos.toByteArray();
+ Assert.assertTrue(mem.equals(Memory.wrap(result)));
+ }
+}
diff --git a/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/MurmurHash3v2Test.java b/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/MurmurHash3v2Test.java
new file mode 100644
index 0000000..6949008
--- /dev/null
+++ b/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/MurmurHash3v2Test.java
@@ -0,0 +1,401 @@
+/*
+ * 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.datasketches.memory.internal;
+
+import static java.nio.charset.StandardCharsets.UTF_8;
+import static org.apache.datasketches.memory.MurmurHash3v2.hash;
+import static org.testng.Assert.fail;
+
+import org.apache.datasketches.memory.Memory;
+import org.apache.datasketches.memory.MurmurHash3v2;
+import org.apache.datasketches.memory.WritableHandle;
+import org.apache.datasketches.memory.WritableMemory;
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+/**
+ * Tests the MurmurHash3 against specific, known hash results given known
+ * inputs obtained from the public domain C++ version 150.
+ *
+ * @author Lee Rhodes
+ */
+public class MurmurHash3v2Test {
+
+ @Test
+ public void checkByteArrRemainderGT8() { //byte[], remainder > 8
+ String keyStr = "The quick brown fox jumps over the lazy dog";
+ byte[] key = keyStr.getBytes(UTF_8);
+ long[] result = hash(key, 0);
+ //Should be:
+ long h1 = 0xe34bbc7bbc071b6cL;
+ long h2 = 0x7a433ca9c49a9347L;
+ Assert.assertEquals(result[0], h1);
+ Assert.assertEquals(result[1], h2);
+ }
+
+ @Test
+ public void checkByteArrChange1bit() { //byte[], change one bit
+ String keyStr = "The quick brown fox jumps over the lazy eog";
+ byte[] key = keyStr.getBytes(UTF_8);
+ long[] result = hash(key, 0);
+ //Should be:
+ long h1 = 0x362108102c62d1c9L;
+ long h2 = 0x3285cd100292b305L;
+ Assert.assertEquals(result[0], h1);
+ Assert.assertEquals(result[1], h2);
+ }
+
+ @Test
+ public void checkByteArrRemainderLt8() { //byte[], test a remainder < 8
+ String keyStr = "The quick brown fox jumps over the lazy dogdogdog";
+ byte[] key = keyStr.getBytes(UTF_8);
+ long[] result = hash(key, 0);
+ //Should be;
+ long h1 = 0x9c8205300e612fc4L;
+ long h2 = 0xcbc0af6136aa3df9L;
+ Assert.assertEquals(result[0], h1);
+ Assert.assertEquals(result[1], h2);
+ }
+
+ @Test
+ public void checkByteArrReaminderEQ8() { //byte[], test a remainder = 8
+ String keyStr = "The quick brown fox jumps over the lazy1";
+ byte[] key = keyStr.getBytes(UTF_8);
+ long[] result = hash(key, 0);
+ //Should be:
+ long h1 = 0xe3301a827e5cdfe3L;
+ long h2 = 0xbdbf05f8da0f0392L;
+ Assert.assertEquals(result[0], h1);
+ Assert.assertEquals(result[1], h2);
+
+ }
+
+ /**
+ * This test should have the exact same output as Test4
+ */
+ @Test
+ public void checkLongArrRemainderEQ8() { //long[], test a remainder = 8
+ String keyStr = "The quick brown fox jumps over the lazy1";
+ long[] key = stringToLongs(keyStr);
+ long[] result = hash(key, 0);
+ //Should be:
+ long h1 = 0xe3301a827e5cdfe3L;
+ long h2 = 0xbdbf05f8da0f0392L;
+ Assert.assertEquals(result[0], h1);
+ Assert.assertEquals(result[1], h2);
+
+ }
+
+ /**
+ * This test should have the exact same output as Test4
+ */
+ @Test
+ public void checkIntArrRemainderEQ8() { //int[], test a remainder = 8
+ String keyStr = "The quick brown fox jumps over the lazy1"; //40B
+ int[] key = stringToInts(keyStr);
+ long[] result = hash(key, 0);
+ //Should be:
+ long h1 = 0xe3301a827e5cdfe3L;
+ long h2 = 0xbdbf05f8da0f0392L;
+ Assert.assertEquals(result[0], h1);
+ Assert.assertEquals(result[1], h2);
+ }
+
+ @Test
+ public void checkIntArrRemainderEQ0() { //int[], test a remainder = 0
+ String keyStr = "The quick brown fox jumps over t"; //32B
+ int[] key = stringToInts(keyStr);
+ long[] result = hash(key, 0);
+ //Should be:
+ long h1 = 0xdf6af91bb29bdacfL;
+ long h2 = 0x91a341c58df1f3a6L;
+ Assert.assertEquals(result[0], h1);
+ Assert.assertEquals(result[1], h2);
+ }
+
+
+ /**
+ * Tests an odd remainder of int[].
+ */
+ @Test
+ public void checkIntArrOddRemainder() { //int[], odd remainder
+ String keyStr = "The quick brown fox jumps over the lazy dog"; //43B
+ int[] key = stringToInts(keyStr);
+ long[] result = hash(key, 0);
+ //Should be:
+ long h1 = 0x1eb232b0087543f5L;
+ long h2 = 0xfc4c1383c3ace40fL;
+ Assert.assertEquals(result[0], h1);
+ Assert.assertEquals(result[1], h2);
+ }
+
+
+ /**
+ * Tests an odd remainder of int[].
+ */
+ @Test
+ public void checkCharArrOddRemainder() { //char[], odd remainder
+ String keyStr = "The quick brown fox jumps over the lazy dog.."; //45B
+ char[] key = keyStr.toCharArray();
+ long[] result = hash(key, 0);
+ //Should be:
+ long h1 = 0xca77b498ea9ed953L;
+ long h2 = 0x8b8f8ec3a8f4657eL;
+ Assert.assertEquals(result[0], h1);
+ Assert.assertEquals(result[1], h2);
+ }
+
+ /**
+ * Tests an odd remainder of int[].
+ */
+ @Test
+ public void checkCharArrRemainderEQ0() { //char[], remainder of 0
+ String keyStr = "The quick brown fox jumps over the lazy "; //40B
+ char[] key = keyStr.toCharArray();
+ long[] result = hash(key, 0);
+ //Should be:
+ long h1 = 0x51b15e9d0887f9f1L;
+ long h2 = 0x8106d226786511ebL;
+ Assert.assertEquals(result[0], h1);
+ Assert.assertEquals(result[1], h2);
+ }
+
+ @Test
+ public void checkByteArrAllOnesZeros() { //byte[], test a ones byte and a zeros byte
+ byte[] key = {
+ 0x54, 0x68, 0x65, 0x20, 0x71, 0x75, 0x69, 0x63, 0x6b, 0x20, 0x62, 0x72, 0x6f, 0x77, 0x6e,
+ 0x20, 0x66, 0x6f, 0x78, 0x20, 0x6a, 0x75, 0x6d, 0x70, 0x73, 0x20, 0x6f, 0x76, 0x65,
+ 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6c, 0x61, 0x7a, 0x79, 0x20, 0x64, 0x6f, 0x67,
+ (byte) 0xff, 0x64, 0x6f, 0x67, 0x00
+ };
+ long[] result = MurmurHash3v2.hash(key, 0);
+
+ //Should be:
+ long h1 = 0xe88abda785929c9eL;
+ long h2 = 0x96b98587cacc83d6L;
+ Assert.assertEquals(result[0], h1);
+ Assert.assertEquals(result[1], h2);
+ }
+
+ /**
+ * This test demonstrates that the hash of byte[], char[], int[], or long[] will produce the
+ * same hash result if, and only if, all the arrays have the same exact length in bytes, and if
+ * the contents of the values in the arrays have the same byte endianness and overall order.
+ */
+ @Test
+ public void checkCrossTypeHashConsistency() {
+ long[] out;
+ println("Bytes");
+ byte[] bArr = {1,2,3,4,5,6,7,8, 9,10,11,12,13,14,15,16, 17,18,19,20,21,22,23,24};
+ long[] out1 = hash(bArr, 0L);
+ println(longToHexBytes(out1[0]));
+ println(longToHexBytes(out1[1]));
+
+ println("Chars");
+ char[] cArr = {0X0201, 0X0403, 0X0605, 0X0807, 0X0a09, 0X0c0b, 0X0e0d, 0X100f,
+ 0X1211, 0X1413, 0X1615, 0X1817};
+ out = hash(cArr, 0L);
+ Assert.assertEquals(out, out1);
+ println(longToHexBytes(out[0]));
+ println(longToHexBytes(out[1]));
+
+ println("Ints");
+ int[] iArr = {0X04030201, 0X08070605, 0X0c0b0a09, 0X100f0e0d, 0X14131211, 0X18171615};
+ out = hash(iArr, 0L);
+ Assert.assertEquals(out, out1);
+ println(longToHexBytes(out[0]));
+ println(longToHexBytes(out[1]));
+
+ println("Longs");
+ long[] lArr = {0X0807060504030201L, 0X100f0e0d0c0b0a09L, 0X1817161514131211L};
+ out = hash(lArr, 0L);
+ Assert.assertEquals(out, out1);
+ println(longToHexBytes(out[0]));
+ println(longToHexBytes(out[1]));
+ }
+
+ @Test
+ public void checkEmptyOrNullExceptions() {
+ try {
+ long[] arr = null; hash(arr, 1L); fail();
+ } catch (final IllegalArgumentException e) { }
+ try {
+ int[] arr = null; hash(arr, 1L); fail();
+ } catch (final IllegalArgumentException e) { }
+ try {
+ char[] arr = null; hash(arr, 1L); fail();
+ } catch (final IllegalArgumentException e) { }
+ try {
+ byte[] arr = null; hash(arr, 1L); fail();
+ } catch (final IllegalArgumentException e) { }
+ try {
+ long[] out = new long[2];
+ String in = null; hash(in, 1L, out); fail();
+ } catch (final IllegalArgumentException e) { }
+ try {
+ long[] out = new long[2];
+ Memory mem = Memory.wrap(new byte[0]);
+ out = hash(mem, 0L, 4L, 1L, out);
+ } catch (final IllegalArgumentException e) { }
+ try (WritableHandle wh = WritableMemory.allocateDirect(8)) {
+ long[] out = new long[2];
+ Memory mem = wh.get();
+ out = hash(mem, 0L, 4L, 1L, out);
+ } catch (Exception ee) {}
+ }
+
+ @Test
+ public void checkHashTails() {
+ long[] out = new long[2];
+ WritableMemory mem = WritableMemory.allocate(32);
+ mem.fill((byte)85);
+
+ for (int i = 16; i <= 32; i++) {
+ out = hash(mem, 0, i, 1L, out);
+ }
+ }
+
+ @Test
+ public void checkSinglePrimitives() {
+ long[] out = new long[2];
+ out = hash(1L, 1L, out);
+ out = hash(0.0, 1L, out);
+ out = hash("123", 1L, out);
+ }
+
+ //Helper methods
+
+ private static long[] stringToLongs(String in) {
+ byte[] bArr = in.getBytes(UTF_8);
+ int inLen = bArr.length;
+ int outLen = (inLen / 8) + (((inLen % 8) != 0) ? 1 : 0);
+ long[] out = new long[outLen];
+
+ for (int i = 0; i < (outLen - 1); i++ ) {
+ for (int j = 0; j < 8; j++ ) {
+ out[i] |= ((bArr[(i * 8) + j] & 0xFFL) << (j * 8));
+ }
+ }
+ int inTail = 8 * (outLen - 1);
+ int rem = inLen - inTail;
+ for (int j = 0; j < rem; j++ ) {
+ out[outLen - 1] |= ((bArr[inTail + j] & 0xFFL) << (j * 8));
+ }
+ return out;
+ }
+
+ private static int[] stringToInts(String in) {
+ byte[] bArr = in.getBytes(UTF_8);
+ int inLen = bArr.length;
+ int outLen = (inLen / 4) + (((inLen % 4) != 0) ? 1 : 0);
+ int[] out = new int[outLen];
+
+ for (int i = 0; i < (outLen - 1); i++ ) {
+ for (int j = 0; j < 4; j++ ) {
+ out[i] |= ((bArr[(i * 4) + j] & 0xFFL) << (j * 8));
+ }
+ }
+ int inTail = 4 * (outLen - 1);
+ int rem = inLen - inTail;
+ for (int j = 0; j < rem; j++ ) {
+ out[outLen - 1] |= ((bArr[inTail + j] & 0xFFL) << (j * 8));
+ }
+ return out;
+ }
+
+ /**
+ * Returns a string of spaced hex bytes in Big-Endian order.
+ * @param v the given long
+ * @return string of spaced hex bytes in Big-Endian order.
+ */
+ private static String longToHexBytes(final long v) {
+ final long mask = 0XFFL;
+ final StringBuilder sb = new StringBuilder();
+ for (int i = 8; i-- > 0; ) {
+ final String s = Long.toHexString((v >>> (i * 8)) & mask);
+ sb.append(zeroPad(s, 2)).append(" ");
+ }
+ return sb.toString();
+ }
+
+ /**
+ * Prepend the given string with zeros. If the given string is equal or greater than the given
+ * field length, it will be returned without modification.
+ * @param s the given string
+ * @param fieldLength desired total field length including the given string
+ * @return the given string prepended with zeros.
+ */
+ private static final String zeroPad(final String s, final int fieldLength) {
+ return characterPad(s, fieldLength, '0', false);
+ }
+
+ /**
+ * Prepend or postpend the given string with the given character to fill the given field length.
+ * If the given string is equal or greater than the given field length, it will be returned
+ * without modification.
+ * @param s the given string
+ * @param fieldLength the desired field length
+ * @param padChar the desired pad character
+ * @param postpend if true append the padCharacters to the end of the string.
+ * @return prepended or postpended given string with the given character to fill the given field
+ * length.
+ */
+ private static final String characterPad(final String s, final int fieldLength, final char padChar,
+ final boolean postpend) {
+ final char[] chArr = s.toCharArray();
+ final int sLen = chArr.length;
+ if (sLen < fieldLength) {
+ final char[] out = new char[fieldLength];
+ final int blanks = fieldLength - sLen;
+
+ if (postpend) {
+ for (int i = 0; i < sLen; i++) {
+ out[i] = chArr[i];
+ }
+ for (int i = sLen; i < fieldLength; i++) {
+ out[i] = padChar;
+ }
+ } else { //prepend
+ for (int i = 0; i < blanks; i++) {
+ out[i] = padChar;
+ }
+ for (int i = blanks; i < fieldLength; i++) {
+ out[i] = chArr[i - blanks];
+ }
+ }
+
+ return String.valueOf(out);
+ }
+ return s;
+ }
+
+ @Test
+ public void printlnTest() {
+ println("PRINTING: "+this.getClass().getName());
+ }
+
+ /**
+ * @param s value to print
+ */
+ static void println(String s) {
+ //System.out.println(s); //disable here
+ }
+
+}
diff --git a/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/NativeWritableBufferImplTest.java b/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/NativeWritableBufferImplTest.java
new file mode 100644
index 0000000..0461104
--- /dev/null
+++ b/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/NativeWritableBufferImplTest.java
@@ -0,0 +1,600 @@
+/*
+ * 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.datasketches.memory.internal;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertFalse;
+import static org.testng.Assert.assertNotNull;
+import static org.testng.Assert.assertTrue;
+
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+
+import org.apache.datasketches.memory.Buffer;
+import org.apache.datasketches.memory.Memory;
+import org.apache.datasketches.memory.ReadOnlyException;
+import org.apache.datasketches.memory.WritableBuffer;
+import org.apache.datasketches.memory.WritableHandle;
+import org.apache.datasketches.memory.WritableMemory;
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+public class NativeWritableBufferImplTest {
+
+ //Simple Native direct
+
+ @Test
+ public void checkNativeCapacityAndClose() throws Exception {
+ int memCapacity = 64;
+ WritableHandle wmh = WritableMemory.allocateDirect(memCapacity);
+ WritableMemory wmem = wmh.getWritable();
+ WritableBuffer wbuf = wmem.asWritableBuffer();
+ assertEquals(wbuf.getCapacity(), memCapacity);
+
+ wmh.close(); //intentional
+ assertFalse(wbuf.isValid());
+
+ wmh.close(); //intentional, nothing to free
+ }
+
+ //Simple Heap arrays
+
+ @Test
+ public void checkBooleanArray() {
+ boolean[] srcArray = { true, false, true, false, false, true, true, false };
+ boolean[] dstArray = new boolean[8];
+
+ Buffer buf = Memory.wrap(srcArray).asBuffer();
+ buf.getBooleanArray(dstArray, 0, 8);
+ for (int i=0; i<8; i++) {
+ assertEquals(dstArray[i], srcArray[i]);
+ }
+
+ WritableBuffer wbuf = WritableMemory.writableWrap(srcArray).asWritableBuffer();
+ wbuf.getBooleanArray(dstArray, 0, 8);
+ for (int i=0; i<8; i++) {
+ assertEquals(dstArray[i], srcArray[i]);
+ }
+ assertTrue(buf.hasArray());
+ }
+
+ @Test
+ public void checkByteArray() {
+ byte[] srcArray = { 1, -2, 3, -4, 5, -6, 7, -8 };
+ byte[] dstArray = new byte[8];
+
+ Buffer buf = Memory.wrap(srcArray).asBuffer();
+ buf.getByteArray(dstArray, 0, 8);
+ for (int i=0; i<8; i++) {
+ assertEquals(dstArray[i], srcArray[i]);
+ }
+
+ WritableBuffer wbuf = WritableMemory.writableWrap(srcArray).asWritableBuffer();
+ wbuf.getByteArray(dstArray, 0, 8);
+ for (int i=0; i<8; i++) {
+ assertEquals(dstArray[i], srcArray[i]);
+ }
+ }
+
+ @Test
+ public void checkCharArray() {
+ char[] srcArray = { 1, 2, 3, 4, 5, 6, 7, 8 };
+ char[] dstArray = new char[8];
+
+ Buffer buf = Memory.wrap(srcArray).asBuffer();
+ buf.getCharArray(dstArray, 0, 8);
+ for (int i=0; i<8; i++) {
+ assertEquals(dstArray[i], srcArray[i]);
+ }
+
+ WritableBuffer wbuf = WritableMemory.writableWrap(srcArray).asWritableBuffer();
+ wbuf.getCharArray(dstArray, 0, 8);
+ for (int i=0; i<8; i++) {
+ assertEquals(dstArray[i], srcArray[i]);
+ }
+ }
+
+ @Test
+ public void checkShortArray() {
+ short[] srcArray = { 1, -2, 3, -4, 5, -6, 7, -8 };
+ short[] dstArray = new short[8];
+
+ Buffer buf = Memory.wrap(srcArray).asBuffer();
+ buf.getShortArray(dstArray, 0, 8);
+ for (int i=0; i<8; i++) {
+ assertEquals(dstArray[i], srcArray[i]);
+ }
+
+ WritableBuffer wbuf = WritableMemory.writableWrap(srcArray).asWritableBuffer();
+ wbuf.getShortArray(dstArray, 0, 8);
+ for (int i=0; i<8; i++) {
+ assertEquals(dstArray[i], srcArray[i]);
+ }
+ }
+
+ @Test
+ public void checkIntArray() {
+ int[] srcArray = { 1, -2, 3, -4, 5, -6, 7, -8 };
+ int[] dstArray = new int[8];
+
+ Buffer buf = Memory.wrap(srcArray).asBuffer();
+ buf.getIntArray(dstArray, 0, 8);
+ for (int i=0; i<8; i++) {
+ assertEquals(dstArray[i], srcArray[i]);
+ }
+
+ WritableBuffer wbuf = WritableMemory.writableWrap(srcArray).asWritableBuffer();
+ wbuf.getIntArray(dstArray, 0, 8);
+ for (int i=0; i<8; i++) {
+ assertEquals(dstArray[i], srcArray[i]);
+ }
+ }
+
+ @Test
+ public void checkLongArray() {
+ long[] srcArray = { 1, -2, 3, -4, 5, -6, 7, -8 };
+ long[] dstArray = new long[8];
+
+ Buffer buf = Memory.wrap(srcArray).asBuffer();
+ buf.getLongArray(dstArray, 0, 8);
+ for (int i=0; i<8; i++) {
+ assertEquals(dstArray[i], srcArray[i]);
+ }
+
+ WritableBuffer wbuf = WritableMemory.writableWrap(srcArray).asWritableBuffer();
+ wbuf.getLongArray(dstArray, 0, 8);
+ for (int i=0; i<8; i++) {
+ assertEquals(dstArray[i], srcArray[i]);
+ }
+ }
+
+ @Test
+ public void checkFloatArray() {
+ float[] srcArray = { 1, -2, 3, -4, 5, -6, 7, -8 };
+ float[] dstArray = new float[8];
+
+ Buffer buf = Memory.wrap(srcArray).asBuffer();
+ buf.getFloatArray(dstArray, 0, 8);
+ for (int i=0; i<8; i++) {
+ assertEquals(dstArray[i], srcArray[i]);
+ }
+
+ WritableBuffer wbuf = WritableMemory.writableWrap(srcArray).asWritableBuffer();
+ wbuf.getFloatArray(dstArray, 0, 8);
+ for (int i=0; i<8; i++) {
+ assertEquals(dstArray[i], srcArray[i]);
+ }
+ }
+
+ @Test
+ public void checkDoubleArray() {
+ double[] srcArray = { 1, -2, 3, -4, 5, -6, 7, -8 };
+ double[] dstArray = new double[8];
+
+ Buffer buf = Memory.wrap(srcArray).asBuffer();
+ buf.getDoubleArray(dstArray, 0, 8);
+ for (int i=0; i<8; i++) {
+ assertEquals(dstArray[i], srcArray[i]);
+ }
+
+ WritableBuffer wbuf = WritableMemory.writableWrap(srcArray).asWritableBuffer();
+ wbuf.getDoubleArray(dstArray, 0, 8);
+ for (int i=0; i<8; i++) {
+ assertEquals(dstArray[i], srcArray[i]);
+ }
+ }
+
+ @Test
+ public void checkNativeBaseBound() throws Exception {
+ int memCapacity = 64;
+ try (WritableHandle wrh = WritableMemory.allocateDirect(memCapacity)) {
+ WritableMemory wmem = wrh.getWritable();
+ WritableBuffer wbuf = wmem.asWritableBuffer();
+ wbuf.toHexString("Force Assertion Error", memCapacity, 8);
+ } catch (IllegalArgumentException e) {
+ //ok
+ }
+ }
+
+ @Test
+ public void checkNativeSrcArrayBound() throws Exception {
+ long memCapacity = 64;
+ try (WritableHandle wrh = WritableMemory.allocateDirect(memCapacity)) {
+ WritableMemory wmem = wrh.getWritable();
+ WritableBuffer wbuf = wmem.asWritableBuffer();
+ byte[] srcArray = { 1, -2, 3, -4 };
+ wbuf.putByteArray(srcArray, 0, 5); //wrong!
+ } catch (IllegalArgumentException e) {
+ //pass
+ }
+ }
+
+
+ @Test(expectedExceptions = IllegalArgumentException.class)
+ public void checkRegionBounds() throws Exception {
+ int memCapacity = 64;
+ try (WritableHandle wrh = WritableMemory.allocateDirect(memCapacity)) {
+ WritableMemory wmem = wrh.getWritable();
+ WritableBuffer wbuf = wmem.asWritableBuffer();
+ wbuf.writableRegion(1, 64, wbuf.getTypeByteOrder()); //wrong!
+ }
+ }
+
+ @Test
+ public void checkByteBufferWrap() {
+ int memCapacity = 64;
+ ByteBuffer byteBuf = ByteBuffer.allocate(memCapacity);
+ byteBuf.order(ByteOrder.nativeOrder());
+
+ for (int i=0; i<memCapacity; i++) {
+ byteBuf.put(i, (byte) i);
+ }
+
+ WritableBuffer wbuf = WritableBuffer.writableWrap(byteBuf);
+
+ for (int i=0; i<memCapacity; i++) {
+ assertEquals(wbuf.getByte(), byteBuf.get(i));
+ }
+
+ assertTrue(wbuf.hasByteBuffer());
+ ByteBuffer byteBuf2 = wbuf.getByteBuffer();
+ assertEquals(byteBuf2, byteBuf);
+ //println( mem.toHexString("HeapBB", 0, memCapacity));
+ }
+
+ @Test
+ public void checkWrapWithBBReadonly1() {
+ int memCapacity = 64;
+ ByteBuffer byteBuf = ByteBuffer.allocate(memCapacity);
+ byteBuf.order(ByteOrder.nativeOrder());
+
+ for (int i = 0; i < memCapacity; i++) {
+ byteBuf.put(i, (byte) i);
+ }
+
+ Buffer buf = WritableBuffer.writableWrap(byteBuf);
+
+ for (int i = 0; i < memCapacity; i++) {
+ assertEquals(buf.getByte(), byteBuf.get(i));
+ }
+
+ //println(mem.toHexString("HeapBB", 0, memCapacity));
+ }
+
+ @Test(expectedExceptions = ReadOnlyException.class)
+ public void checkWrapWithBBReadonly2() {
+ int memCapacity = 64;
+ ByteBuffer byteBuf = ByteBuffer.allocate(memCapacity);
+ byteBuf.order(ByteOrder.nativeOrder());
+ ByteBuffer byteBufRO = byteBuf.asReadOnlyBuffer();
+ byteBufRO.order(ByteOrder.nativeOrder());
+ assertTrue(true);
+ WritableBuffer wbuf = WritableBuffer.writableWrap(byteBufRO);
+ assertTrue(wbuf.isReadOnly());
+ }
+
+ @Test
+ public void checkWrapWithDirectBBReadonly() {
+ int memCapacity = 64;
+ ByteBuffer byteBuf = ByteBuffer.allocateDirect(memCapacity);
+ byteBuf.order(ByteOrder.nativeOrder());
+
+ for (int i = 0; i < memCapacity; i++) {
+ byteBuf.put(i, (byte) i);
+ }
+ ByteBuffer byteBufRO = byteBuf.asReadOnlyBuffer();
+ byteBufRO.order(ByteOrder.nativeOrder());
+
+ Buffer buf = Buffer.wrap(byteBufRO);
+
+ for (int i = 0; i < memCapacity; i++) {
+ assertEquals(buf.getByte(), byteBuf.get(i));
+ }
+
+ //println(mem.toHexString("HeapBB", 0, memCapacity));
+ }
+
+ @Test(expectedExceptions = ReadOnlyException.class)
+ public void checkWrapWithDirectBBReadonlyPut() {
+ int memCapacity = 64;
+ ByteBuffer byteBuf = ByteBuffer.allocateDirect(memCapacity);
+ ByteBuffer byteBufRO = byteBuf.asReadOnlyBuffer();
+ byteBufRO.order(ByteOrder.nativeOrder());
+
+ WritableBuffer.writableWrap(byteBufRO);
+ }
+
+ @Test
+ public void checkByteBufferWrapDirectAccess() {
+ int memCapacity = 64;
+ ByteBuffer byteBuf = ByteBuffer.allocateDirect(memCapacity);
+ byteBuf.order(ByteOrder.nativeOrder());
+
+ for (int i=0; i<memCapacity; i++) {
+ byteBuf.put(i, (byte) i);
+ }
+
+ Buffer buf = Buffer.wrap(byteBuf);
+
+ for (int i=0; i<memCapacity; i++) {
+ assertEquals(buf.getByte(), byteBuf.get(i));
+ }
+
+ //println( mem.toHexString("HeapBB", 0, memCapacity));
+ }
+
+ @Test
+ public void checkIsDirect() throws Exception {
+ int memCapacity = 64;
+ WritableBuffer mem = WritableMemory.allocate(memCapacity).asWritableBuffer();
+ assertFalse(mem.isDirect());
+ try (WritableHandle wrh = WritableMemory.allocateDirect(memCapacity)) {
+ WritableMemory mem2 = wrh.getWritable();
+ WritableBuffer wbuf = mem2.asWritableBuffer();
+ assertTrue(wbuf.isDirect());
+ wrh.close(); //immediate close
+ }
+ }
+
+ @Test
+ public void checkIsReadOnly() {
+ long[] srcArray = { 1, -2, 3, -4, 5, -6, 7, -8 };
+
+ WritableBuffer wbuf = WritableMemory.writableWrap(srcArray).asWritableBuffer();
+ assertFalse(wbuf.isReadOnly());
+
+ Buffer buf = wbuf;
+ assertFalse(buf.isReadOnly());
+
+ for (int i = 0; i < srcArray.length; i++) {
+ assertEquals(buf.getLong(), srcArray[i]);
+ }
+ }
+
+ @Test
+ public void checkGoodBounds() {
+ UnsafeUtil.checkBounds(50, 50, 100);
+ }
+
+ @Test
+ public void checkCompareToHeap() {
+ byte[] arr1 = new byte[] {0, 1, 2, 3};
+ byte[] arr2 = new byte[] {0, 1, 2, 4};
+ byte[] arr3 = new byte[] {0, 1, 2, 3, 4};
+
+ Buffer buf1 = Memory.wrap(arr1).asBuffer();
+ Buffer buf2 = Memory.wrap(arr2).asBuffer();
+ Buffer buf3 = Memory.wrap(arr3).asBuffer();
+
+ int comp = buf1.compareTo(0, 3, buf2, 0, 3);
+ assertEquals(comp, 0);
+ comp = buf1.compareTo(0, 4, buf2, 0, 4);
+ assertEquals(comp, -1);
+ comp = buf2.compareTo(0, 4, buf1, 0, 4);
+ assertEquals(comp, 1);
+ //different lengths
+ comp = buf1.compareTo(0, 4, buf3, 0, 5);
+ assertEquals(comp, -1);
+ comp = buf3.compareTo(0, 5, buf1, 0, 4);
+ assertEquals(comp, 1);
+ }
+
+ @Test
+ public void checkCompareToDirect() throws Exception {
+ byte[] arr1 = new byte[] {0, 1, 2, 3};
+ byte[] arr2 = new byte[] {0, 1, 2, 4};
+ byte[] arr3 = new byte[] {0, 1, 2, 3, 4};
+
+ try (WritableHandle h1 = WritableMemory.allocateDirect(4);
+ WritableHandle h2 = WritableMemory.allocateDirect(4);
+ WritableHandle h3 = WritableMemory.allocateDirect(5))
+ {
+ WritableMemory mem1 = h1.getWritable();
+ mem1.putByteArray(0, arr1, 0, 4);
+
+ WritableMemory mem2 = h2.getWritable();
+ mem2.putByteArray(0, arr2, 0, 4);
+
+ WritableMemory mem3 = h3.getWritable();
+ mem3.putByteArray(0, arr3, 0, 5);
+
+ Buffer buf1 = mem1.asBuffer();
+ Buffer buf2 = mem2.asBuffer();
+ Buffer buf3 = mem3.asBuffer();
+
+ int comp = buf1.compareTo(0, 3, buf2, 0, 3);
+ assertEquals(comp, 0);
+ comp = buf1.compareTo(0, 4, buf2, 0, 4);
+ assertEquals(comp, -1);
+ comp = buf2.compareTo(0, 4, buf1, 0, 4);
+ assertEquals(comp, 1);
+ //different lengths
+ comp = buf1.compareTo(0, 4, buf3, 0, 5);
+ assertEquals(comp, -1);
+ comp = buf3.compareTo(0, 5, buf1, 0, 4);
+ assertEquals(comp, 1);
+ }
+ }
+
+ @Test
+ public void checkAsBuffer() {
+ WritableMemory wmem = WritableMemory.allocate(64);
+ WritableBuffer wbuf = wmem.asWritableBuffer();
+ wbuf.setPosition(32);
+ for (int i = 32; i < 64; i++) { wbuf.putByte((byte)i); }
+ //println(wbuf.toHexString("Buf", 0, (int)wbuf.getCapacity()));
+
+ Buffer buf = wmem.asBuffer();
+ buf.setPosition(32);
+ for (int i = 32; i < 64; i++) {
+ assertEquals(buf.getByte(), i);
+ }
+ }
+
+ @Test
+ public void checkDuplicate() {
+ WritableMemory wmem = WritableMemory.allocate(64);
+ for (int i = 0; i < 64; i++) { wmem.putByte(i, (byte)i); }
+
+ WritableBuffer wbuf = wmem.asWritableBuffer().writableDuplicate();
+ wbuf.checkValidAndBounds(0, 64);
+ for (int i = 0; i < 64; i++) {
+ assertEquals(wbuf.getByte(), i);
+ }
+ Buffer buf = wmem.asBuffer().duplicate();
+ for (int i = 0; i < 64; i++) {
+ assertEquals(buf.getByte(), i);
+ }
+
+ WritableMemory wmem2 = wbuf.asWritableMemory();
+ for (int i = 0; i < 64; i++) {
+ assertEquals(wmem2.getByte(i), i);
+ }
+ WritableMemory wmem3 = wbuf.asWritableMemory();
+ wmem3.checkValidAndBounds(0, 64);
+ }
+
+ @Test
+ public void checkCumAndRegionOffset() {
+ WritableMemory wmem = WritableMemory.allocate(64);
+ WritableMemory reg = wmem.writableRegion(32, 32);
+ WritableBuffer buf = reg.asWritableBuffer();
+ assertEquals(buf.getRegionOffset(), 32);
+ assertEquals(buf.getRegionOffset(0), 32);
+ assertEquals(buf.getCumulativeOffset(), 32 + 16);
+ assertEquals(buf.getCumulativeOffset(0), 32 + 16);
+ }
+
+ @Test
+ public void checkIsSameResource() {
+ byte[] byteArr = new byte[64];
+ WritableBuffer wbuf1 = WritableMemory.writableWrap(byteArr).asWritableBuffer();
+ WritableBuffer wbuf2 = WritableMemory.writableWrap(byteArr).asWritableBuffer();
+ assertTrue(wbuf1.isSameResource(wbuf2));
+ }
+
+ @Test
+ public void checkDegenerateRegionReturn() {
+ Memory mem = Memory.wrap(new byte[0]);
+ Buffer buf = mem.asBuffer();
+ Buffer reg = buf.region();
+ assertEquals(reg.getCapacity(), 0);
+ }
+
+ @Test
+ public void checkAsWritableMemoryRO() {
+ ByteBuffer bb = ByteBuffer.allocate(64);
+ WritableBuffer wbuf = WritableBuffer.writableWrap(bb);
+ WritableMemory wmem = wbuf.asWritableMemory(); //OK
+ assertNotNull(wmem);
+
+ try {
+ Buffer buf = Buffer.wrap(bb.asReadOnlyBuffer());
+ wbuf = (WritableBuffer) buf;
+ wmem = wbuf.asWritableMemory();
+ Assert.fail();
+ } catch (ReadOnlyException expected) {
+ // expected
+ }
+ }
+
+ @Test
+ public void checkWritableDuplicateRO() {
+ ByteBuffer bb = ByteBuffer.allocate(64);
+ WritableBuffer wbuf = WritableBuffer.writableWrap(bb);
+ @SuppressWarnings("unused")
+ WritableBuffer wdup = wbuf.writableDuplicate();
+
+ try {
+ Buffer buf = Buffer.wrap(bb);
+ wbuf = (WritableBuffer) buf;
+ @SuppressWarnings("unused")
+ WritableBuffer wdup2 = wbuf.writableDuplicate();
+ Assert.fail();
+ } catch (ReadOnlyException expected) {
+ // ignore
+ }
+ }
+
+ @Test
+ public void checkWritableRegionRO() {
+ ByteBuffer bb = ByteBuffer.allocate(64);
+ WritableBuffer wbuf = WritableBuffer.writableWrap(bb);
+ @SuppressWarnings("unused")
+ WritableBuffer wreg = wbuf.writableRegion();
+
+ try {
+ Buffer buf = Buffer.wrap(bb);
+ wbuf = (WritableBuffer) buf;
+ @SuppressWarnings("unused")
+ WritableBuffer wreg2 = wbuf.writableRegion();
+ Assert.fail();
+ } catch (ReadOnlyException expected) {
+ // ignore
+ }
+ }
+
+ @Test
+ public void checkWritableRegionWithParamsRO() {
+ ByteBuffer bb = ByteBuffer.allocate(64);
+ WritableBuffer wbuf = WritableBuffer.writableWrap(bb);
+ @SuppressWarnings("unused")
+ WritableBuffer wreg = wbuf.writableRegion(0, 1, wbuf.getTypeByteOrder());
+
+ try {
+ Buffer buf = Buffer.wrap(bb);
+ wbuf = (WritableBuffer) buf;
+ @SuppressWarnings("unused")
+ WritableBuffer wreg2 = wbuf.writableRegion(0, 1, wbuf.getTypeByteOrder());
+ Assert.fail();
+ } catch (ReadOnlyException expected) {
+ // ignore
+ }
+ }
+
+ @Test
+ public void checkZeroBuffer() {
+ WritableMemory wmem = WritableMemory.allocate(8);
+ WritableBuffer wbuf = wmem.asWritableBuffer();
+ WritableBuffer reg = wbuf.writableRegion(0, 0, wbuf.getTypeByteOrder());
+ assertEquals(reg.getCapacity(), 0);
+ }
+
+ @Test
+ public void checkDuplicateNonNative() {
+ WritableMemory wmem = WritableMemory.allocate(64);
+ wmem.putShort(0, (short) 1);
+ Buffer buf = wmem.asWritableBuffer().duplicate(Util.NON_NATIVE_BYTE_ORDER);
+ assertEquals(buf.getShort(0), 256);
+ }
+
+ @Test
+ public void printlnTest() {
+ println("PRINTING: "+this.getClass().getName());
+ }
+
+ /**
+ * @param s value to print
+ */
+ static void println(String s) {
+ //System.out.println(s); //disable here
+ }
+
+}
diff --git a/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/NativeWritableMemoryImplTest.java b/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/NativeWritableMemoryImplTest.java
new file mode 100644
index 0000000..8d52250
--- /dev/null
+++ b/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/NativeWritableMemoryImplTest.java
@@ -0,0 +1,723 @@
+/*
+ * 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.datasketches.memory.internal;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertFalse;
+import static org.testng.Assert.assertTrue;
+import static org.testng.Assert.fail;
+
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+
+import org.apache.datasketches.memory.WritableHandle;
+import org.apache.datasketches.memory.Buffer;
+import org.apache.datasketches.memory.Memory;
+import org.apache.datasketches.memory.ReadOnlyException;
+import org.apache.datasketches.memory.WritableBuffer;
+import org.apache.datasketches.memory.WritableMemory;
+import org.testng.annotations.Test;
+
+public class NativeWritableMemoryImplTest {
+
+ //Simple Native direct
+
+ @Test
+ public void checkNativeCapacityAndClose() throws Exception {
+ int memCapacity = 64;
+ WritableHandle wmh = WritableMemory.allocateDirect(memCapacity);
+ WritableMemory mem = wmh.getWritable();
+ assertEquals(memCapacity, mem.getCapacity());
+
+ wmh.close(); //intentional
+ assertFalse(mem.isValid());
+
+ wmh.close(); //intentional, nothing to free
+ }
+
+ //Simple Native arrays
+
+ @Test
+ public void checkBooleanArray() {
+ boolean[] srcArray = { true, false, true, false, false, true, true, false };
+ boolean[] dstArray = new boolean[8];
+
+ Memory mem = Memory.wrap(srcArray);
+ mem.getBooleanArray(0, dstArray, 0, 8);
+ for (int i=0; i<8; i++) {
+ assertEquals(dstArray[i], srcArray[i]);
+ }
+
+ WritableMemory wmem = WritableMemory.writableWrap(srcArray);
+ wmem.getBooleanArray(0, dstArray, 0, 8);
+ for (int i=0; i<8; i++) {
+ assertEquals(dstArray[i], srcArray[i]);
+ }
+ assertTrue(mem.hasArray());
+ }
+
+ @Test
+ public void checkByteArray() {
+ byte[] srcArray = { 1, -2, 3, -4, 5, -6, 7, -8 };
+ byte[] dstArray = new byte[8];
+
+ Memory mem = Memory.wrap(srcArray);
+ mem.getByteArray(0, dstArray, 0, 8);
+ for (int i=0; i<8; i++) {
+ assertEquals(dstArray[i], srcArray[i]);
+ }
+
+ WritableMemory wmem = WritableMemory.writableWrap(srcArray);
+ wmem.getByteArray(0, dstArray, 0, 8);
+ for (int i=0; i<8; i++) {
+ assertEquals(dstArray[i], srcArray[i]);
+ }
+ }
+
+ @Test
+ public void checkCharArray() {
+ char[] srcArray = { 1, 2, 3, 4, 5, 6, 7, 8 };
+ char[] dstArray = new char[8];
+
+ Memory mem = Memory.wrap(srcArray);
+ mem.getCharArray(0, dstArray, 0, 8);
+ for (int i=0; i<8; i++) {
+ assertEquals(dstArray[i], srcArray[i]);
+ }
+
+ WritableMemory wmem = WritableMemory.writableWrap(srcArray);
+ wmem.getCharArray(0, dstArray, 0, 8);
+ for (int i=0; i<8; i++) {
+ assertEquals(dstArray[i], srcArray[i]);
+ }
+ }
+
+ @Test
+ public void checkShortArray() {
+ short[] srcArray = { 1, -2, 3, -4, 5, -6, 7, -8 };
+ short[] dstArray = new short[8];
+
+ Memory mem = Memory.wrap(srcArray);
+ mem.getShortArray(0, dstArray, 0, 8);
+ for (int i=0; i<8; i++) {
+ assertEquals(dstArray[i], srcArray[i]);
+ }
+
+ WritableMemory wmem = WritableMemory.writableWrap(srcArray);
+ wmem.getShortArray(0, dstArray, 0, 8);
+ for (int i=0; i<8; i++) {
+ assertEquals(dstArray[i], srcArray[i]);
+ }
+ }
+
+ @Test
+ public void checkIntArray() {
+ int[] srcArray = { 1, -2, 3, -4, 5, -6, 7, -8 };
+ int[] dstArray = new int[8];
+
+ Memory mem = Memory.wrap(srcArray);
+ mem.getIntArray(0, dstArray, 0, 8);
+ for (int i=0; i<8; i++) {
+ assertEquals(dstArray[i], srcArray[i]);
+ }
+
+ WritableMemory wmem = WritableMemory.writableWrap(srcArray);
+ wmem.getIntArray(0, dstArray, 0, 8);
+ for (int i=0; i<8; i++) {
+ assertEquals(dstArray[i], srcArray[i]);
+ }
+ }
+
+ @Test
+ public void checkLongArray() {
+ long[] srcArray = { 1, -2, 3, -4, 5, -6, 7, -8 };
+ long[] dstArray = new long[8];
+
+ Memory mem = Memory.wrap(srcArray);
+ mem.getLongArray(0, dstArray, 0, 8);
+ for (int i=0; i<8; i++) {
+ assertEquals(dstArray[i], srcArray[i]);
+ }
+
+ WritableMemory wmem = WritableMemory.writableWrap(srcArray);
+ wmem.getLongArray(0, dstArray, 0, 8);
+ for (int i=0; i<8; i++) {
+ assertEquals(dstArray[i], srcArray[i]);
+ }
+ }
+
+ @Test
+ public void checkFloatArray() {
+ float[] srcArray = { 1, -2, 3, -4, 5, -6, 7, -8 };
+ float[] dstArray = new float[8];
+
+ Memory mem = Memory.wrap(srcArray);
+ mem.getFloatArray(0, dstArray, 0, 8);
+ for (int i=0; i<8; i++) {
+ assertEquals(dstArray[i], srcArray[i]);
+ }
+
+ WritableMemory wmem = WritableMemory.writableWrap(srcArray);
+ wmem.getFloatArray(0, dstArray, 0, 8);
+ for (int i=0; i<8; i++) {
+ assertEquals(dstArray[i], srcArray[i]);
+ }
+ }
+
+ @Test
+ public void checkDoubleArray() {
+ double[] srcArray = { 1, -2, 3, -4, 5, -6, 7, -8 };
+ double[] dstArray = new double[8];
+
+ Memory mem = Memory.wrap(srcArray);
+ mem.getDoubleArray(0, dstArray, 0, 8);
+ for (int i=0; i<8; i++) {
+ assertEquals(dstArray[i], srcArray[i]);
+ }
+
+ WritableMemory wmem = WritableMemory.writableWrap(srcArray);
+ wmem.getDoubleArray(0, dstArray, 0, 8);
+ for (int i=0; i<8; i++) {
+ assertEquals(dstArray[i], srcArray[i]);
+ }
+ }
+
+ @Test
+ public void checkNativeBaseBound() throws Exception {
+ int memCapacity = 64;
+ try (WritableHandle wrh = WritableMemory.allocateDirect(memCapacity)) {
+ WritableMemory mem = wrh.getWritable();
+ mem.toHexString("Force Assertion Error", memCapacity, 8);
+ } catch (IllegalArgumentException e) {
+ //ok
+ }
+ }
+
+ @Test
+ public void checkNativeSrcArrayBound() throws Exception {
+ long memCapacity = 64;
+ try (WritableHandle wrh = WritableMemory.allocateDirect(memCapacity)) {
+ WritableMemory mem = wrh.getWritable();
+ byte[] srcArray = { 1, -2, 3, -4 };
+ mem.putByteArray(0L, srcArray, 0, 5);
+ } catch (IllegalArgumentException e) {
+ //pass
+ }
+ }
+
+ //Copy Within tests
+
+ @Test(expectedExceptions = IllegalArgumentException.class)
+ public void checkDegenerateCopyTo() {
+ WritableMemory wmem = WritableMemory.allocate(64);
+ wmem.copyTo(0, wmem, 0, 64);
+ }
+
+ @Test
+ public void checkCopyWithinNativeSmall() throws Exception {
+ int memCapacity = 64;
+ int half = memCapacity/2;
+ try (WritableHandle wrh = WritableMemory.allocateDirect(memCapacity)) {
+ WritableMemory mem = wrh.getWritable();
+ mem.clear();
+
+ for (int i=0; i<half; i++) { //fill first half
+ mem.putByte(i, (byte) i);
+ }
+
+ mem.copyTo(0, mem, half, half);
+
+ for (int i=0; i<half; i++) {
+ assertEquals(mem.getByte(i+half), (byte) i);
+ }
+ }
+ }
+
+ @Test
+ public void checkCopyWithinNativeLarge() throws Exception {
+ int memCapacity = (2 << 20) + 64;
+ int memCapLongs = memCapacity / 8;
+ int halfBytes = memCapacity / 2;
+ int halfLongs = memCapLongs / 2;
+ try (WritableHandle wrh = WritableMemory.allocateDirect(memCapacity)) {
+ WritableMemory mem = wrh.getWritable();
+ mem.clear();
+
+ for (int i=0; i < halfLongs; i++) {
+ mem.putLong(i*8, i);
+ }
+
+ mem.copyTo(0, mem, halfBytes, halfBytes);
+
+ for (int i=0; i < halfLongs; i++) {
+ assertEquals(mem.getLong((i + halfLongs)*8), i);
+ }
+ }
+ }
+
+ @Test
+ public void checkCopyWithinNativeSrcBound() throws Exception {
+ int memCapacity = 64;
+ try (WritableHandle wrh = WritableMemory.allocateDirect(memCapacity)) {
+ WritableMemory mem = wrh.getWritable();
+ mem.copyTo(32, mem, 32, 33); //hit source bound check
+ fail("Did Not Catch Assertion Error: source bound");
+ }
+ catch (IllegalArgumentException e) {
+ //pass
+ }
+ }
+
+ @Test
+ public void checkCopyWithinNativeDstBound() throws Exception {
+ int memCapacity = 64;
+ try (WritableHandle wrh = WritableMemory.allocateDirect(memCapacity)) {
+ WritableMemory mem = wrh.getWritable();
+ mem.copyTo(0, mem, 32, 33); //hit dst bound check
+ fail("Did Not Catch Assertion Error: dst bound");
+ }
+ catch (IllegalArgumentException e) {
+ //pass
+ }
+ }
+
+ @Test
+ public void checkCopyCrossNativeSmall() throws Exception {
+ int memCapacity = 64;
+
+ try (WritableHandle wrh1 = WritableMemory.allocateDirect(memCapacity);
+ WritableHandle wrh2 = WritableMemory.allocateDirect(memCapacity))
+ {
+ WritableMemory mem1 = wrh1.getWritable();
+ WritableMemory mem2 = wrh2.getWritable();
+
+ for (int i=0; i < memCapacity; i++) {
+ mem1.putByte(i, (byte) i);
+ }
+ mem2.clear();
+ mem1.copyTo(0, mem2, 0, memCapacity);
+
+ for (int i=0; i<memCapacity; i++) {
+ assertEquals(mem2.getByte(i), (byte) i);
+ }
+ wrh1.close();
+ wrh2.close();
+ }
+ }
+
+ @Test
+ public void checkCopyCrossNativeLarge() throws Exception {
+ int memCapacity = (2<<20) + 64;
+ int memCapLongs = memCapacity / 8;
+
+ try (WritableHandle wrh1 = WritableMemory.allocateDirect(memCapacity);
+ WritableHandle wrh2 = WritableMemory.allocateDirect(memCapacity))
+ {
+ WritableMemory mem1 = wrh1.getWritable();
+ WritableMemory mem2 = wrh2.getWritable();
+
+ for (int i=0; i < memCapLongs; i++) {
+ mem1.putLong(i*8, i);
+ }
+ mem2.clear();
+
+ mem1.copyTo(0, mem2, 0, memCapacity);
+
+ for (int i=0; i<memCapLongs; i++) {
+ assertEquals(mem2.getLong(i*8), i);
+ }
+ }
+ }
+
+ @Test
+ public void checkCopyCrossNativeAndByteArray() throws Exception {
+ int memCapacity = 64;
+ try (WritableHandle wrh1 = WritableMemory.allocateDirect(memCapacity)) {
+ WritableMemory mem1 = wrh1.getWritable();
+
+ for (int i= 0; i < mem1.getCapacity(); i++) {
+ mem1.putByte(i, (byte) i);
+ }
+
+ WritableMemory mem2 = WritableMemory.allocate(memCapacity);
+ mem1.copyTo(8, mem2, 16, 16);
+
+ for (int i=0; i<16; i++) {
+ assertEquals(mem1.getByte(8+i), mem2.getByte(16+i));
+ }
+ //println(mem2.toHexString("Mem2", 0, (int)mem2.getCapacity()));
+ }
+ }
+
+ @Test
+ public void checkCopyCrossRegionsSameNative() throws Exception {
+ int memCapacity = 128;
+
+ try (WritableHandle wrh1 = WritableMemory.allocateDirect(memCapacity)) {
+ WritableMemory mem1 = wrh1.getWritable();
+
+ for (int i= 0; i < mem1.getCapacity(); i++) {
+ mem1.putByte(i, (byte) i);
+ }
+ //println(mem1.toHexString("Mem1", 0, (int)mem1.getCapacity()));
+
+ Memory reg1 = mem1.region(8, 16);
+ //println(reg1.toHexString("Reg1", 0, (int)reg1.getCapacity()));
+
+ WritableMemory reg2 = mem1.writableRegion(24, 16);
+ //println(reg2.toHexString("Reg2", 0, (int)reg2.getCapacity()));
+ reg1.copyTo(0, reg2, 0, 16);
+
+ for (int i=0; i<16; i++) {
+ assertEquals(reg1.getByte(i), reg2.getByte(i));
+ assertEquals(mem1.getByte(8+i), mem1.getByte(24+i));
+ }
+ //println(mem1.toHexString("Mem1", 0, (int)mem1.getCapacity()));
+ }
+ }
+
+ @Test
+ public void checkCopyCrossNativeArrayAndHierarchicalRegions() throws Exception {
+ int memCapacity = 64;
+ try (WritableHandle wrh1 = WritableMemory.allocateDirect(memCapacity)) {
+ WritableMemory mem1 = wrh1.getWritable();
+
+ for (int i= 0; i < mem1.getCapacity(); i++) { //fill with numbers
+ mem1.putByte(i, (byte) i);
+ }
+ //println(mem1.toHexString("Mem1", 0, (int)mem1.getCapacity()));
+
+ WritableMemory mem2 = WritableMemory.allocate(memCapacity);
+
+ Memory reg1 = mem1.region(8, 32);
+ Memory reg1B = reg1.region(8, 16);
+ //println(reg1.toHexString("Reg1", 0, (int)reg1.getCapacity()));
+ //println(reg1B.toHexString("Reg1B", 0, (int)reg1B.getCapacity()));
+
+ WritableMemory reg2 = mem2.writableRegion(32, 16);
+ reg1B.copyTo(0, reg2, 0, 16);
+ //println(reg2.toHexString("Reg2", 0, (int)reg2.getCapacity()));
+
+ //println(mem2.toHexString("Mem2", 0, (int)mem2.getCapacity()));
+ for (int i = 32, j = 16; i < 40; i++, j++) {
+ assertEquals(mem2.getByte(i), j);
+ }
+ }
+
+ }
+
+ @Test(expectedExceptions = IllegalArgumentException.class)
+ public void checkRegionBounds() throws Exception {
+ int memCapacity = 64;
+ try (WritableHandle wrh = WritableMemory.allocateDirect(memCapacity)) {
+ WritableMemory mem = wrh.getWritable();
+ mem.writableRegion(1, 64);
+ }
+ }
+
+ @Test
+ public void checkByteBufferWrap() {
+ int memCapacity = 64;
+ ByteBuffer byteBuf = ByteBuffer.allocate(memCapacity);
+ byteBuf.order(ByteOrder.nativeOrder());
+
+ for (int i=0; i<memCapacity; i++) {
+ byteBuf.put(i, (byte) i);
+ }
+
+ WritableMemory wmem = WritableMemory.writableWrap(byteBuf);
+
+ for (int i=0; i<memCapacity; i++) {
+ assertEquals(wmem.getByte(i), byteBuf.get(i));
+ }
+
+ assertTrue(wmem.hasByteBuffer());
+ ByteBuffer byteBuf2 = wmem.getByteBuffer();
+ assertEquals(byteBuf2, byteBuf);
+ //println( mem.toHexString("HeapBB", 0, memCapacity));
+ }
+
+ @Test
+ public void checkWrapWithBBReadonly1() {
+ int memCapacity = 64;
+ ByteBuffer byteBuf = ByteBuffer.allocate(memCapacity);
+ byteBuf.order(ByteOrder.nativeOrder());
+
+ for (int i = 0; i < memCapacity; i++) {
+ byteBuf.put(i, (byte) i);
+ }
+
+ Memory mem = WritableMemory.writableWrap(byteBuf);
+
+ for (int i = 0; i < memCapacity; i++) {
+ assertEquals(mem.getByte(i), byteBuf.get(i));
+ }
+
+ //println(mem.toHexString("HeapBB", 0, memCapacity));
+ }
+
+ @Test(expectedExceptions = ReadOnlyException.class)
+ public void checkWrapWithBBReadonly2() {
+ int memCapacity = 64;
+ ByteBuffer byteBuf = ByteBuffer.allocate(memCapacity);
+ byteBuf.order(ByteOrder.nativeOrder());
+ ByteBuffer byteBufRO = byteBuf.asReadOnlyBuffer();
+
+ WritableMemory.writableWrap(byteBufRO);
+ }
+
+ @Test
+ public void checkWrapWithDirectBBReadonly() {
+ int memCapacity = 64;
+ ByteBuffer byteBuf = ByteBuffer.allocateDirect(memCapacity);
+ byteBuf.order(ByteOrder.nativeOrder());
+
+ for (int i = 0; i < memCapacity; i++) {
+ byteBuf.put(i, (byte) i);
+ }
+ ByteBuffer byteBufRO = byteBuf.asReadOnlyBuffer();
+ byteBufRO.order(ByteOrder.nativeOrder());
+
+ Memory mem = Memory.wrap(byteBufRO);
+
+ for (int i = 0; i < memCapacity; i++) {
+ assertEquals(mem.getByte(i), byteBuf.get(i));
+ }
+
+ //println(mem.toHexString("HeapBB", 0, memCapacity));
+ }
+
+ @Test(expectedExceptions = ReadOnlyException.class)
+ public void checkWrapWithDirectBBReadonlyPut() {
+ int memCapacity = 64;
+ ByteBuffer byteBuf = ByteBuffer.allocateDirect(memCapacity);
+ ByteBuffer byteBufRO = byteBuf.asReadOnlyBuffer();
+ byteBufRO.order(ByteOrder.nativeOrder());
+
+ WritableMemory.writableWrap(byteBufRO);
+ }
+
+ @Test
+ public void checkByteBufferWrapDirectAccess() {
+ int memCapacity = 64;
+ ByteBuffer byteBuf = ByteBuffer.allocateDirect(memCapacity);
+ byteBuf.order(ByteOrder.nativeOrder());
+
+ for (int i=0; i<memCapacity; i++) {
+ byteBuf.put(i, (byte) i);
+ }
+
+ Memory mem = Memory.wrap(byteBuf);
+
+ for (int i=0; i<memCapacity; i++) {
+ assertEquals(mem.getByte(i), byteBuf.get(i));
+ }
+
+ //println( mem.toHexString("HeapBB", 0, memCapacity));
+ }
+
+ @Test
+ public void checkIsDirect() throws Exception {
+ int memCapacity = 64;
+ WritableMemory mem = WritableMemory.allocate(memCapacity);
+ assertFalse(mem.isDirect());
+ try (WritableHandle wrh = WritableMemory.allocateDirect(memCapacity)) {
+ mem = wrh.getWritable();
+ assertTrue(mem.isDirect());
+ wrh.close();
+ }
+ }
+
+ @Test
+ public void checkIsReadOnly() {
+ long[] srcArray = { 1, -2, 3, -4, 5, -6, 7, -8 };
+
+ WritableMemory wmem = WritableMemory.writableWrap(srcArray);
+ assertFalse(wmem.isReadOnly());
+
+ Memory memRO = wmem;
+ assertFalse(memRO.isReadOnly());
+
+ for (int i = 0; i < wmem.getCapacity(); i++) {
+ assertEquals(wmem.getByte(i), memRO.getByte(i));
+ }
+ }
+
+ @Test
+ public void checkGoodBounds() {
+ UnsafeUtil.checkBounds(50, 50, 100);
+ }
+
+ @Test
+ public void checkCompareToHeap() {
+ byte[] arr1 = new byte[] {0, 1, 2, 3};
+ byte[] arr2 = new byte[] {0, 1, 2, 4};
+ byte[] arr3 = new byte[] {0, 1, 2, 3, 4};
+
+ Memory mem1 = Memory.wrap(arr1);
+ Memory mem2 = Memory.wrap(arr2);
+ Memory mem3 = Memory.wrap(arr3);
+ Memory mem4 = Memory.wrap(arr3); //same resource
+
+ int comp = mem1.compareTo(0, 3, mem2, 0, 3);
+ assertEquals(comp, 0);
+ comp = mem1.compareTo(0, 4, mem2, 0, 4);
+ assertEquals(comp, -1);
+ comp = mem2.compareTo(0, 4, mem1, 0, 4);
+ assertEquals(comp, 1);
+ //different lengths
+ comp = mem1.compareTo(0, 4, mem3, 0, 5);
+ assertEquals(comp, -1);
+ comp = mem3.compareTo(0, 5, mem1, 0, 4);
+ assertEquals(comp, 1);
+ comp = mem3.compareTo(0, 5, mem4, 0, 5);
+ assertEquals(comp, 0);
+ comp = mem3.compareTo(0, 4, mem4, 1, 4);
+ assertEquals(comp, -1);
+ mem3.checkValidAndBounds(0, 5);
+ }
+
+ @Test
+ public void checkCompareToDirect() throws Exception {
+ byte[] arr1 = new byte[] {0, 1, 2, 3};
+ byte[] arr2 = new byte[] {0, 1, 2, 4};
+ byte[] arr3 = new byte[] {0, 1, 2, 3, 4};
+
+ try (WritableHandle h1 = WritableMemory.allocateDirect(4);
+ WritableHandle h2 = WritableMemory.allocateDirect(4);
+ WritableHandle h3 = WritableMemory.allocateDirect(5))
+ {
+ WritableMemory mem1 = h1.getWritable();
+ mem1.putByteArray(0, arr1, 0, 4);
+
+ WritableMemory mem2 = h2.getWritable();
+ mem2.putByteArray(0, arr2, 0, 4);
+
+ WritableMemory mem3 = h3.getWritable();
+ mem3.putByteArray(0, arr3, 0, 5);
+
+ int comp = mem1.compareTo(0, 3, mem2, 0, 3);
+ assertEquals(comp, 0);
+ comp = mem1.compareTo(0, 4, mem2, 0, 4);
+ assertEquals(comp, -1);
+ comp = mem2.compareTo(0, 4, mem1, 0, 4);
+ assertEquals(comp, 1);
+ //different lengths
+ comp = mem1.compareTo(0, 4, mem3, 0, 5);
+ assertEquals(comp, -1);
+ comp = mem3.compareTo(0, 5, mem1, 0, 4);
+ assertEquals(comp, 1);
+ }
+ }
+
+ @Test
+ public void testCompareToSameStart() {
+ Memory mem = WritableMemory.allocate(3);
+ assertEquals(-1, mem.compareTo(0, 1, mem, 0, 2));
+ assertEquals(0, mem.compareTo(1, 1, mem, 1, 1));
+ assertEquals(1, mem.compareTo(1, 2, mem, 1, 1));
+ }
+
+ @Test
+ public void checkAsBuffer() {
+ WritableMemory wmem = WritableMemory.allocate(64);
+ WritableBuffer wbuf = wmem.asWritableBuffer();
+ wbuf.setPosition(32);
+ for (int i = 32; i < 64; i++) { wbuf.putByte((byte)i); }
+ //println(wbuf.toHexString("Buf", 0, (int)wbuf.getCapacity()));
+
+ Buffer buf = wmem.asBuffer();
+ buf.setPosition(32);
+ for (int i = 32; i < 64; i++) {
+ assertEquals(buf.getByte(), i);
+ }
+ }
+
+ @Test
+ public void checkCumAndRegionOffset() {
+ WritableMemory wmem = WritableMemory.allocate(64);
+ WritableMemory reg = wmem.writableRegion(32, 32);
+ assertEquals(reg.getRegionOffset(), 32);
+ assertEquals(reg.getRegionOffset(0), 32);
+ assertEquals(reg.getCumulativeOffset(), 32 + 16);
+ assertEquals(reg.getCumulativeOffset(0), 32 + 16);
+ }
+
+ @Test
+ public void checkIsSameResource() {
+ byte[] byteArr = new byte[64];
+ WritableMemory wmem1 = WritableMemory.writableWrap(byteArr);
+ WritableMemory wmem2 = WritableMemory.writableWrap(byteArr);
+ assertTrue(wmem1.isSameResource(wmem2));
+ }
+
+ @Test
+ public void checkAsWritableBufferWithBB() {
+ ByteBuffer byteBuf = ByteBuffer.allocate(64);
+ byteBuf.position(16);
+ byteBuf.limit(48);
+ WritableMemory wmem = WritableMemory.writableWrap(byteBuf);
+ WritableBuffer wbuf = wmem.asWritableBuffer();
+ assertEquals(wbuf.getCapacity(), 64);
+ assertEquals(wbuf.getPosition(), 0);
+ assertEquals(wbuf.getEnd(), 64);
+ }
+
+ @Test(expectedExceptions = ReadOnlyException.class)
+ public void checkAsWritableRegionRO() {
+ ByteBuffer byteBuf = ByteBuffer.allocate(64);
+ WritableMemory wmem = (WritableMemory) Memory.wrap(byteBuf);
+ wmem.writableRegion(0, 1);
+ }
+
+ @Test(expectedExceptions = ReadOnlyException.class)
+ public void checkAsWritableBufferRO() {
+ ByteBuffer byteBuf = ByteBuffer.allocate(64);
+ WritableMemory wmem = (WritableMemory) Memory.wrap(byteBuf);
+ wmem.asWritableBuffer();
+ }
+
+ @Test void checkZeroMemory() {
+ WritableMemory wmem = WritableMemory.allocate(8);
+ WritableMemory reg = wmem.writableRegion(0, 0);
+ assertEquals(reg.getCapacity(), 0);
+ }
+
+ @Test
+ public void checkAsBufferNonNative() {
+ WritableMemory wmem = WritableMemory.allocate(64);
+ wmem.putShort(0, (short) 1);
+ Buffer buf = wmem.asBuffer(Util.NON_NATIVE_BYTE_ORDER);
+ assertEquals(buf.getShort(0), 256);
+ }
+
+ @Test
+ public void printlnTest() {
+ println("PRINTING: "+this.getClass().getName());
+ }
+
+ /**
+ * @param s value to print
+ */
+ static void println(String s) {
+ //System.out.println(s); //disable here
+ }
+
+}
diff --git a/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/NioBitsTest.java b/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/NioBitsTest.java
new file mode 100644
index 0000000..8ed5916
--- /dev/null
+++ b/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/NioBitsTest.java
@@ -0,0 +1,78 @@
+/*
+ * 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.datasketches.memory.internal;
+
+import static org.testng.Assert.assertEquals;
+
+import org.testng.annotations.Test;
+
+/**
+ * @author Lee Rhodes
+ */
+public class NioBitsTest {
+
+ @Test
+ public void checkVMParams() {
+ println("Max MemoryImpl: " + NioBits.getMaxDirectByteBufferMemory());
+ println("Page Aligned: " + NioBits.isPageAligned());
+ println("Page Size: " + NioBits.pageSize());
+ }
+
+ @Test
+ public void checkGetAtomicFields() {
+ //testing this beyond 2GB may not work on JVMs < 8GB.
+ //This should be checked manually
+ // long cap = 1024L + Integer.MAX_VALUE;
+ long cap = 1L << 10;
+ printStats();
+ NioBits.reserveMemory(cap, cap);
+ printStats();
+ NioBits. unreserveMemory(cap, cap);
+ printStats();
+ }
+
+ @Test
+ public void checkPageCount() {
+ assertEquals(NioBits.pageCount(0), 0);
+ assertEquals(NioBits.pageCount(1), 1);
+ }
+
+ private static void printStats() {
+ long count = NioBits.getDirectAllocationsCount();
+ long resMem = NioBits.getReservedMemory();
+ long totCap = NioBits.getTotalCapacity();
+ long maxDBBmem = NioBits.getMaxDirectByteBufferMemory();
+ String s = String.format("%,10d\t%,15d\t%,15d\t%,15d", count, resMem, totCap, maxDBBmem);
+ println(s);
+ }
+
+ @Test
+ public void printlnTest() {
+ println("PRINTING: " + this.getClass().getName());
+ }
+
+ /**
+ * @param s value to print
+ */
+ static void println(final String s) {
+ //System.out.println(s); //disable here
+ }
+
+}
diff --git a/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/NonNativeWritableBufferImplTest.java b/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/NonNativeWritableBufferImplTest.java
new file mode 100644
index 0000000..57d481a
--- /dev/null
+++ b/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/NonNativeWritableBufferImplTest.java
@@ -0,0 +1,260 @@
+/*
+ * 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.datasketches.memory.internal;
+
+import static org.testng.Assert.assertEquals;
+
+import java.nio.ByteOrder;
+
+import org.apache.datasketches.memory.Buffer;
+import org.apache.datasketches.memory.WritableBuffer;
+import org.apache.datasketches.memory.WritableMemory;
+import org.testng.annotations.Test;
+
+/**
+ * @author Lee Rhodes
+ */
+public class NonNativeWritableBufferImplTest {
+
+//Check primitives
+ @Test
+ public void checkCharacters() {
+ int n = 8;
+ int m = Character.BYTES;
+ byte[] arr1 = new byte[n * m]; //non-native
+ //put & get
+ WritableMemory wmem = WritableMemory.writableWrap(arr1, ByteOrder.BIG_ENDIAN);
+ WritableBuffer wbuf = wmem.asWritableBuffer();
+ char ch = 'a';
+ for (int i = 0; i < n; i++) { wbuf.putChar(i * m, ch++); }
+ ch = 'a';
+ for (int i = 0; i < n; i++) {
+ assertEquals(wbuf.getChar(i * m), ch++);
+ }
+ ch = 'a';
+ wbuf.setPosition(0);
+ for (int i = 0; i < n; i++) { wbuf.putChar(ch++); }
+ ch = 'a';
+ wbuf.setPosition(0);
+ for (int i = 0; i < n; i++) {
+ assertEquals(wbuf.getChar(), ch++);
+ }
+ //getArr & putArr
+ char[] cArr = new char[n]; //native
+ wbuf.setPosition(0);
+ wbuf.getCharArray(cArr, 0, n); //wmem is non-native
+ byte[] arr2 = new byte[n * m];
+ WritableMemory wmem2 = WritableMemory.writableWrap(arr2, ByteOrder.BIG_ENDIAN);
+ WritableBuffer wbuf2 = wmem2.asWritableBuffer();
+ wbuf2.putCharArray(cArr, 0, n);
+ assertEquals(arr2, arr1);
+ }
+
+ @Test
+ public void checkDoubles() {
+ int n = 8;
+ int m = Double.BYTES;
+ byte[] arr1 = new byte[n * m]; //non-native
+ //put & get
+ WritableMemory wmem = WritableMemory.writableWrap(arr1, ByteOrder.BIG_ENDIAN);
+ WritableBuffer wbuf = wmem.asWritableBuffer();
+ double dbl = 1.0;
+ for (int i = 0; i < n; i++) { wbuf.putDouble(i * m, dbl++); }
+ dbl = 1.0;
+ for (int i = 0; i < n; i++) {
+ assertEquals(wbuf.getDouble(i * m), dbl++);
+ }
+ dbl = 1.0;
+ wbuf.setPosition(0);
+ for (int i = 0; i < n; i++) { wbuf.putDouble(dbl++); }
+ dbl = 1.0;
+ wbuf.setPosition(0);
+ for (int i = 0; i < n; i++) {
+ assertEquals(wbuf.getDouble(), dbl++);
+ }
+ //getArr & putArr
+ double[] dblArr = new double[n]; //native
+ wbuf.setPosition(0);
+ wbuf.getDoubleArray(dblArr, 0, n); //wmem is non-native
+ byte[] arr2 = new byte[n * m];
+ WritableMemory wmem2 = WritableMemory.writableWrap(arr2, ByteOrder.BIG_ENDIAN);
+ WritableBuffer wbuf2 = wmem2.asWritableBuffer();
+ wbuf2.putDoubleArray(dblArr, 0, n);
+ assertEquals(arr2, arr1);
+ }
+
+ @Test
+ public void checkFloats() {
+ int n = 8;
+ int m = Float.BYTES;
+ byte[] arr1 = new byte[n * m]; //non-native
+ //put & get
+ WritableMemory wmem = WritableMemory.writableWrap(arr1, ByteOrder.BIG_ENDIAN);
+ WritableBuffer wbuf = wmem.asWritableBuffer();
+ float flt = 1.0F;
+ for (int i = 0; i < n; i++) { wbuf.putFloat(i * m, flt++); }
+ flt = 1.0F;
+ for (int i = 0; i < n; i++) {
+ assertEquals(wbuf.getFloat(i * m), flt++);
+ }
+ flt = 1.0F;
+ wbuf.setPosition(0);
+ for (int i = 0; i < n; i++) { wbuf.putFloat(flt++); }
+ flt = 1.0F;
+ wbuf.setPosition(0);
+ for (int i = 0; i < n; i++) {
+ assertEquals(wbuf.getFloat(), flt++);
+ }
+ //getArr & putArr
+ float[] fltArr = new float[n]; //native
+ wbuf.setPosition(0);
+ wbuf.getFloatArray(fltArr, 0, n); //wmem is non-native
+ byte[] arr2 = new byte[n * m];
+ WritableMemory wmem2 = WritableMemory.writableWrap(arr2, ByteOrder.BIG_ENDIAN);
+ WritableBuffer wbuf2 = wmem2.asWritableBuffer();
+ wbuf2.putFloatArray(fltArr, 0, n);
+ assertEquals(arr2, arr1);
+ }
+
+ @Test
+ public void checkInts() {
+ int n = 8;
+ int m = Integer.BYTES;
+ byte[] arr1 = new byte[n * m]; //non-native
+ //put & get
+ WritableMemory wmem = WritableMemory.writableWrap(arr1, ByteOrder.BIG_ENDIAN);
+ WritableBuffer wbuf = wmem.asWritableBuffer();
+ int intg = 1;
+ for (int i = 0; i < n; i++) { wbuf.putInt(i * m, intg++); }
+ intg = 1;
+ for (int i = 0; i < n; i++) {
+ assertEquals(wbuf.getInt(i * m), intg++);
+ }
+ intg = 1;
+ wbuf.setPosition(0);
+ for (int i = 0; i < n; i++) { wbuf.putInt(intg++); }
+ intg = 1;
+ wbuf.setPosition(0);
+ for (int i = 0; i < n; i++) {
+ assertEquals(wbuf.getInt(), intg++);
+ }
+ //getArr & putArr
+ int[] intArr = new int[n]; //native
+ wbuf.setPosition(0);
+ wbuf.getIntArray(intArr, 0, n); //wmem is non-native
+ byte[] arr2 = new byte[n * m];
+ WritableMemory wmem2 = WritableMemory.writableWrap(arr2, ByteOrder.BIG_ENDIAN);
+ WritableBuffer wbuf2 = wmem2.asWritableBuffer();
+ wbuf2.putIntArray(intArr, 0, n);
+ assertEquals(arr2, arr1);
+ }
+
+ @Test
+ public void checkLongs() {
+ int n = 8;
+ int m = Long.BYTES;
+ byte[] arr1 = new byte[n * m]; //non-native
+ //put & get
+ WritableMemory wmem = WritableMemory.writableWrap(arr1, ByteOrder.BIG_ENDIAN);
+ WritableBuffer wbuf = wmem.asWritableBuffer();
+ long lng = 1;
+ for (int i = 0; i < n; i++) { wbuf.putLong(i * m, lng++); }
+ lng = 1;
+ for (int i = 0; i < n; i++) {
+ assertEquals(wbuf.getLong(i * m), lng++);
+ }
+ lng = 1;
+ wbuf.setPosition(0);
+ for (int i = 0; i < n; i++) { wbuf.putLong(lng++); }
+ lng = 1;
+ wbuf.setPosition(0);
+ for (int i = 0; i < n; i++) {
+ assertEquals(wbuf.getLong(), lng++);
+ }
+ //getArr & putArr
+ long[] longArr = new long[n]; //native
+ wbuf.setPosition(0);
+ wbuf.getLongArray(longArr, 0, n); //wmem is non-native
+ byte[] arr2 = new byte[n * m];
+ WritableMemory wmem2 = WritableMemory.writableWrap(arr2, ByteOrder.BIG_ENDIAN);
+ WritableBuffer wbuf2 = wmem2.asWritableBuffer();
+ wbuf2.putLongArray(longArr, 0, n);
+ assertEquals(arr2, arr1);
+ }
+
+ @Test
+ public void checkShorts() {
+ int n = 8;
+ int m = Short.BYTES;
+ byte[] arr1 = new byte[n * m]; //non-native
+ //put & get
+ WritableMemory wmem = WritableMemory.writableWrap(arr1, ByteOrder.BIG_ENDIAN);
+ WritableBuffer wbuf = wmem.asWritableBuffer();
+ short sht = 1;
+ for (int i = 0; i < n; i++) { wbuf.putShort(i * m, sht++); }
+ sht = 1;
+ for (int i = 0; i < n; i++) {
+ assertEquals(wbuf.getShort(i * m), sht++);
+ }
+ sht = 1;
+ wbuf.setPosition(0);
+ for (int i = 0; i < n; i++) { wbuf.putShort(sht++); }
+ sht = 1;
+ wbuf.setPosition(0);
+ for (int i = 0; i < n; i++) {
+ assertEquals(wbuf.getShort(), sht++);
+ }
+ //getArr & putArr
+ short[] shortArr = new short[n]; //native
+ wbuf.setPosition(0);
+ wbuf.getShortArray(shortArr, 0, n); //wmem is non-native
+ byte[] arr2 = new byte[n * m];
+ WritableMemory wmem2 = WritableMemory.writableWrap(arr2, ByteOrder.BIG_ENDIAN);
+ WritableBuffer wbuf2 = wmem2.asWritableBuffer();
+ wbuf2.putShortArray(shortArr, 0, n);
+ assertEquals(arr2, arr1);
+ }
+
+ //check Duplicate, Region
+ @Test
+ public void checkDuplicate() {
+ byte[] bArr = new byte[8];
+ WritableMemory wmem = WritableMemory.writableWrap(bArr, ByteOrder.BIG_ENDIAN);
+ WritableBuffer wbuf = wmem.asWritableBuffer();
+ WritableBuffer wdup = wbuf.writableDuplicate();
+ assertEquals(wdup.getTypeByteOrder(), ByteOrder.BIG_ENDIAN);
+
+ WritableBuffer wreg = wbuf.writableRegion();
+ assertEquals(wreg.getTypeByteOrder(), ByteOrder.BIG_ENDIAN);
+ }
+
+ @Test
+ public void checkDuplicateZeros() {
+ byte[] bArr = new byte[0];
+ WritableMemory wmem = WritableMemory.writableWrap(bArr, ByteOrder.BIG_ENDIAN);
+ Buffer buf = wmem.asBuffer();
+ Buffer dup = buf.duplicate();
+ assertEquals(dup.getTypeByteOrder(), ByteOrder.LITTLE_ENDIAN);
+
+ Buffer reg = buf.region();
+ assertEquals(reg.getTypeByteOrder(), ByteOrder.LITTLE_ENDIAN);
+ }
+
+}
diff --git a/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/NonNativeWritableMemoryImplTest.java b/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/NonNativeWritableMemoryImplTest.java
new file mode 100644
index 0000000..c6bd5d0
--- /dev/null
+++ b/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/NonNativeWritableMemoryImplTest.java
@@ -0,0 +1,219 @@
+/*
+ * 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.datasketches.memory.internal;
+
+import static org.testng.Assert.assertEquals;
+
+import java.nio.ByteOrder;
+
+import org.apache.datasketches.memory.Memory;
+import org.apache.datasketches.memory.WritableMemory;
+import org.testng.annotations.Test;
+
+/**
+ * @author Lee Rhodes
+ */
+public class NonNativeWritableMemoryImplTest {
+ private byte[] bArr = new byte[8];
+ private final WritableMemory wmem = WritableMemory.writableWrap(bArr, ByteOrder.BIG_ENDIAN);
+
+//Check primitives
+ @Test
+ public void checkCharacters() {
+ int m = Character.BYTES;
+ int n = ((1 << 20) / m) + m;
+ byte[] arr1 = new byte[n * m]; //non-native
+ //put & get
+ WritableMemory wmem1 = WritableMemory.writableWrap(arr1, ByteOrder.BIG_ENDIAN);
+ for (int i = 0; i < n; i++) { wmem1.putChar(i * m, (char) i++); }
+ for (int i = 0; i < n; i++) {
+ assertEquals(wmem1.getChar(i * m), (char) i++);
+ }
+ //getArr & putArr
+ char[] cArr = new char[n]; //native
+ wmem1.getCharArray(0, cArr, 0, n); //wmem is non-native
+ byte[] arr2 = new byte[n * m];
+ WritableMemory wmem2 = WritableMemory.writableWrap(arr2, ByteOrder.BIG_ENDIAN);
+ wmem2.putCharArray(0, cArr, 0, n);
+ assertEquals(arr2, arr1);
+ }
+
+ @Test
+ public void checkDoubles() {
+ int m = Double.BYTES;
+ int n = ((1 << 20) / m) + m;
+ byte[] arr1 = new byte[n * m]; //non-native
+ //put & get
+ WritableMemory wmem1 = WritableMemory.writableWrap(arr1, ByteOrder.BIG_ENDIAN);
+ double dbl = 1.0;
+ for (int i = 0; i < n; i++) { wmem1.putDouble(i * m, dbl++); }
+ dbl = 1.0;
+ for (int i = 0; i < n; i++) {
+ assertEquals(wmem1.getDouble(i * m), dbl++);
+ }
+ //getArr & putArr
+ double[] dblArr = new double[n]; //native
+ wmem1.getDoubleArray(0, dblArr, 0, n); //wmem is non-native
+ byte[] arr2 = new byte[n * m];
+ WritableMemory wmem2 = WritableMemory.writableWrap(arr2, ByteOrder.BIG_ENDIAN);
+ wmem2.putDoubleArray(0, dblArr, 0, n);
+ assertEquals(arr2, arr1);
+ }
+
+ @Test
+ public void checkFloats() {
+ int m = Float.BYTES;
+ int n = ((1 << 20) / m) + m;
+ byte[] arr1 = new byte[n * m]; //non-native
+ //put & get
+ WritableMemory wmem1 = WritableMemory.writableWrap(arr1, ByteOrder.BIG_ENDIAN);
+ float flt = 1.0F;
+ for (int i = 0; i < n; i++) { wmem1.putFloat(i * m, flt++); }
+ flt = 1.0F;
+ for (int i = 0; i < n; i++) {
+ assertEquals(wmem1.getFloat(i * m), flt++);
+ }
+ //getArr & putArr
+ float[] fltArr = new float[n]; //native
+ wmem1.getFloatArray(0, fltArr, 0, n); //wmem is non-native
+ byte[] arr2 = new byte[n * m];
+ WritableMemory wmem2 = WritableMemory.writableWrap(arr2, ByteOrder.BIG_ENDIAN);
+ wmem2.putFloatArray(0, fltArr, 0, n);
+ assertEquals(arr2, arr1);
+ }
+
+ @Test
+ public void checkInts() {
+ int m = Integer.BYTES;
+ int n = ((1 << 20) / m) + m;
+ byte[] arr1 = new byte[n * m]; //non-native
+ //put & get
+ WritableMemory wmem1 = WritableMemory.writableWrap(arr1, ByteOrder.BIG_ENDIAN);
+ int intg = 1;
+ for (int i = 0; i < n; i++) { wmem1.putInt(i * m, intg++); }
+ intg = 1;
+ for (int i = 0; i < n; i++) {
+ assertEquals(wmem1.getInt(i * m), intg++);
+ }
+ //getArr & putArr
+ int[] intArr = new int[n]; //native
+ wmem1.getIntArray(0, intArr, 0, n); //wmem is non-native
+ byte[] arr2 = new byte[n * m];
+ WritableMemory wmem2 = WritableMemory.writableWrap(arr2, ByteOrder.BIG_ENDIAN);
+ wmem2.putIntArray(0, intArr, 0, n);
+ assertEquals(arr2, arr1);
+ }
+
+ @Test
+ public void checkLongs() {
+ int m = Long.BYTES;
+ int n = ((1 << 20) / m) + m;
+ byte[] arr1 = new byte[n * m]; //non-native
+ //put & get
+ WritableMemory wmem1 = WritableMemory.writableWrap(arr1, ByteOrder.BIG_ENDIAN);
+ long lng = 1;
+ for (int i = 0; i < n; i++) { wmem1.putLong(i * m, lng++); }
+ lng = 1;
+ for (int i = 0; i < n; i++) {
+ assertEquals(wmem1.getLong(i * m), lng++);
+ }
+ //getArr & putArr
+ long[] longArr = new long[n]; //native
+ wmem1.getLongArray(0, longArr, 0, n); //wmem is non-native
+ byte[] arr2 = new byte[n * m];
+ WritableMemory wmem2 = WritableMemory.writableWrap(arr2, ByteOrder.BIG_ENDIAN);
+ wmem2.putLongArray(0, longArr, 0, n);
+ assertEquals(arr2, arr1);
+ }
+
+ @Test
+ public void checkShorts() {
+ int m = Short.BYTES;
+ int n = ((1 << 20) / m) + m;
+ byte[] arr1 = new byte[n * m]; //non-native
+ //put & get
+ WritableMemory wmem1 = WritableMemory.writableWrap(arr1, ByteOrder.BIG_ENDIAN);
+ short sht = 1;
+ for (int i = 0; i < n; i++) { wmem1.putShort(i * m, sht++); }
+ sht = 1;
+ for (int i = 0; i < n; i++) {
+ assertEquals(wmem1.getShort(i * m), sht++);
+ }
+ //getArr & putArr
+ short[] shortArr = new short[n]; //native
+ wmem1.getShortArray(0, shortArr, 0, n); //wmem is non-native
+ byte[] arr2 = new byte[n * m];
+ WritableMemory wmem2 = WritableMemory.writableWrap(arr2, ByteOrder.BIG_ENDIAN);
+ wmem2.putShortArray(0, shortArr, 0, n);
+ assertEquals(arr2, arr1);
+ }
+
+ //check Atomic Write Methods
+
+
+ @Test
+ public void testGetAndAddLong() {
+ wmem.getAndAddLong(0, 1L);
+ try {
+ wmem.getAndAddLong(1, 1L);
+ throw new RuntimeException("Expected AssertionError");
+ } catch (final AssertionError expected) {
+ // ignore
+ }
+ }
+
+ @Test
+ public void testGetAndSetLong() {
+ wmem.getAndSetLong(0, 1L);
+ try {
+ wmem.getAndSetLong(1, 1L);
+ throw new RuntimeException("Expected AssertionError");
+ } catch (final AssertionError expected) {
+ // ignore
+ }
+ }
+
+ @Test
+ public void testCompareAndSwapLong() {
+ wmem.compareAndSwapLong(0, 0L, 1L);
+ try {
+ wmem.compareAndSwapLong(1, 0L, 1L);
+ throw new RuntimeException("Expected AssertionError");
+ } catch (final AssertionError expected) {
+ // ignore
+ }
+ }
+
+ //check Region
+ @Test
+ public void checkRegion() {
+ WritableMemory wreg = wmem.writableRegion(0, wmem.getCapacity());
+ assertEquals(wreg.getTypeByteOrder(), ByteOrder.BIG_ENDIAN);
+ }
+
+ @Test
+ public void checkRegionZeros() {
+ byte[] bArr1 = new byte[0];
+ WritableMemory wmem1 = WritableMemory.writableWrap(bArr1, ByteOrder.BIG_ENDIAN);
+ Memory reg = wmem1.region(0, wmem1.getCapacity());
+ assertEquals(reg.getTypeByteOrder(), ByteOrder.LITTLE_ENDIAN);
+ }
+
+}
diff --git a/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/SpecificLeafTest.java b/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/SpecificLeafTest.java
new file mode 100644
index 0000000..87f7e35
--- /dev/null
+++ b/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/SpecificLeafTest.java
@@ -0,0 +1,194 @@
+/*
+ * 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.datasketches.memory.internal;
+
+import static org.testng.Assert.assertFalse;
+import static org.testng.Assert.assertTrue;
+
+import java.io.File;
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+
+import org.apache.datasketches.memory.Buffer;
+import org.apache.datasketches.memory.Memory;
+import org.apache.datasketches.memory.WritableHandle;
+import org.apache.datasketches.memory.WritableMapHandle;
+import org.apache.datasketches.memory.WritableMemory;
+import org.testng.annotations.Test;
+
+/**
+ * @author Lee Rhodes
+ */
+public class SpecificLeafTest {
+
+ @Test
+ public void checkByteBufferLeafs() {
+ int bytes = 128;
+ ByteBuffer bb = ByteBuffer.allocate(bytes);
+ bb.order(ByteOrder.nativeOrder());
+
+ Memory mem = Memory.wrap(bb).region(0, bytes, ByteOrder.nativeOrder());
+ assertTrue(((BaseStateImpl)mem).isBBType());
+ assertTrue(mem.isReadOnly());
+ checkCrossLeafTypeIds(mem);
+ Buffer buf = mem.asBuffer().region(0, bytes, ByteOrder.nativeOrder());
+
+ bb.order(Util.NON_NATIVE_BYTE_ORDER);
+ Memory mem2 = Memory.wrap(bb).region(0, bytes, Util.NON_NATIVE_BYTE_ORDER);
+ Buffer buf2 = mem2.asBuffer().region(0, bytes, Util.NON_NATIVE_BYTE_ORDER);
+ Buffer buf3 = buf2.duplicate();
+
+ assertTrue(((BaseStateImpl)mem).isRegionType());
+ assertTrue(((BaseStateImpl)mem2).isRegionType());
+ assertTrue(((BaseStateImpl)buf).isRegionType());
+ assertTrue(((BaseStateImpl)buf2).isRegionType());
+ assertTrue(((BaseStateImpl)buf3).isDuplicateType());
+ }
+
+ @Test
+ public void checkDirectLeafs() throws Exception {
+ int bytes = 128;
+ try (WritableHandle h = WritableMemory.allocateDirect(bytes)) {
+ WritableMemory wmem = h.getWritable(); //native mem
+ assertTrue(((BaseStateImpl)wmem).isDirectType());
+ assertFalse(wmem.isReadOnly());
+ checkCrossLeafTypeIds(wmem);
+ WritableMemory nnwmem = wmem.writableRegion(0, bytes, Util.NON_NATIVE_BYTE_ORDER);
+
+ Memory mem = wmem.region(0, bytes, ByteOrder.nativeOrder());
+ Buffer buf = mem.asBuffer().region(0, bytes, ByteOrder.nativeOrder());
+
+
+ Memory mem2 = nnwmem.region(0, bytes, Util.NON_NATIVE_BYTE_ORDER);
+ Buffer buf2 = mem2.asBuffer().region(0, bytes, Util.NON_NATIVE_BYTE_ORDER);
+ Buffer buf3 = buf2.duplicate();
+
+ assertTrue(((BaseStateImpl)mem).isRegionType());
+ assertTrue(((BaseStateImpl)mem2).isRegionType());
+ assertTrue(((BaseStateImpl)buf).isRegionType());
+ assertTrue(((BaseStateImpl)buf2).isRegionType());
+ assertTrue(((BaseStateImpl)buf3).isDuplicateType());
+ }
+ }
+
+ @Test
+ public void checkMapLeafs() throws Exception {
+ File file = new File("TestFile2.bin");
+ if (file.exists()) {
+ try {
+ java.nio.file.Files.delete(file.toPath());
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+ assertTrue(file.createNewFile());
+ assertTrue(file.setWritable(true, false)); //writable=true, ownerOnly=false
+ assertTrue(file.isFile());
+ file.deleteOnExit(); //comment out if you want to examine the file.
+
+ final long bytes = 128;
+
+ try (WritableMapHandle h = WritableMemory.writableMap(file, 0L, bytes, ByteOrder.nativeOrder())) {
+ WritableMemory mem = h.getWritable(); //native mem
+ assertTrue(((BaseStateImpl)mem).isMapType());
+ assertFalse(mem.isReadOnly());
+ checkCrossLeafTypeIds(mem);
+ Memory nnreg = mem.region(0, bytes, Util.NON_NATIVE_BYTE_ORDER);
+
+ Memory reg = mem.region(0, bytes, ByteOrder.nativeOrder());
+ Buffer buf = reg.asBuffer().region(0, bytes, ByteOrder.nativeOrder());
+ Buffer buf4 = buf.duplicate();
+
+ Memory reg2 = nnreg.region(0, bytes, Util.NON_NATIVE_BYTE_ORDER);
+ Buffer buf2 = reg2.asBuffer().region(0, bytes, Util.NON_NATIVE_BYTE_ORDER);
+ Buffer buf3 = buf2.duplicate();
+
+ assertTrue(((BaseStateImpl)reg).isRegionType());
+ assertTrue(((BaseStateImpl)reg2).isRegionType());
+ assertTrue(((BaseStateImpl)buf).isRegionType());
+ assertTrue(((BaseStateImpl)buf2).isRegionType());
+ assertTrue(((BaseStateImpl)buf3).isDuplicateType());
+ assertTrue(((BaseStateImpl)buf4).isDuplicateType());
+ }
+ }
+
+ @Test
+ public void checkHeapLeafs() {
+ int bytes = 128;
+ Memory mem = Memory.wrap(new byte[bytes]);
+ assertTrue(((BaseStateImpl)mem).isHeapType());
+ assertTrue(((BaseStateImpl)mem).isReadOnlyType());
+ checkCrossLeafTypeIds(mem);
+ Memory nnreg = mem.region(0, bytes, Util.NON_NATIVE_BYTE_ORDER);
+
+ Memory reg = mem.region(0, bytes, ByteOrder.nativeOrder());
+ Buffer buf = reg.asBuffer().region(0, bytes, ByteOrder.nativeOrder());
+ Buffer buf4 = buf.duplicate();
+
+ Memory reg2 = nnreg.region(0, bytes, Util.NON_NATIVE_BYTE_ORDER);
+ Buffer buf2 = reg2.asBuffer().region(0, bytes, Util.NON_NATIVE_BYTE_ORDER);
+ Buffer buf3 = buf2.duplicate();
+
+ assertFalse(((BaseStateImpl)mem).isRegionType());
+ assertTrue(((BaseStateImpl)reg2).isRegionType());
+ assertTrue(((BaseStateImpl)buf).isRegionType());
+ assertTrue(((BaseStateImpl)buf2).isRegionType());
+ assertTrue(((BaseStateImpl)buf3).isDuplicateType());
+ assertTrue(((BaseStateImpl)buf4).isDuplicateType());
+ }
+
+ private static void checkCrossLeafTypeIds(Memory mem) {
+ Memory reg1 = mem.region(0, mem.getCapacity());
+ assertTrue(((BaseStateImpl)reg1).isRegionType());
+
+ Buffer buf1 = reg1.asBuffer();
+ assertTrue(((BaseStateImpl)buf1).isRegionType());
+ assertTrue(((BaseStateImpl)buf1).isBufferType());
+ assertTrue(buf1.isReadOnly());
+
+ Buffer buf2 = buf1.duplicate();
+ assertTrue(((BaseStateImpl)buf2).isRegionType());
+ assertTrue(((BaseStateImpl)buf2).isBufferType());
+ assertTrue(((BaseStateImpl)buf2).isDuplicateType());
+ assertTrue(buf2.isReadOnly());
+
+ Memory mem2 = buf1.asMemory(); //
+ assertTrue(((BaseStateImpl)mem2).isRegionType());
+ assertFalse(((BaseStateImpl)mem2).isBufferType());
+ assertFalse(((BaseStateImpl)mem2).isDuplicateType());
+ assertTrue(mem2.isReadOnly());
+
+ Buffer buf3 = buf1.duplicate(Util.NON_NATIVE_BYTE_ORDER);
+ assertTrue(((BaseStateImpl)buf3).isRegionType());
+ assertTrue(((BaseStateImpl)buf3).isBufferType());
+ assertTrue(((BaseStateImpl)buf3).isDuplicateType());
+ assertTrue(((BaseStateImpl)buf3).isNonNativeType());
+ assertTrue(buf3.isReadOnly());
+
+ Memory mem3 = buf3.asMemory();
+ assertTrue(((BaseStateImpl)mem3).isRegionType());
+ assertFalse(((BaseStateImpl)mem3).isBufferType());
+ assertTrue(((BaseStateImpl)mem3).isDuplicateType());
+ assertTrue(((BaseStateImpl)mem3).isNonNativeType());
+ assertTrue(mem3.isReadOnly());
+ }
+
+}
diff --git a/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/UnsafeUtilTest.java b/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/UnsafeUtilTest.java
new file mode 100644
index 0000000..baaf90a
--- /dev/null
+++ b/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/UnsafeUtilTest.java
@@ -0,0 +1,151 @@
+/*
+ * 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.datasketches.memory.internal;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertTrue;
+import static org.testng.Assert.fail;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.testng.annotations.Test;
+
+
+/**
+ * @author Lee Rhodes
+ */
+public class UnsafeUtilTest {
+ long testField = 1; //Do not remove & cannot be static. Used in reflection check.
+
+
+ @Test
+ public void checkJdkString() {
+ String jdkVer;
+ int[] p = new int[2];
+ String[] good1_Strings = {"1.8.0_121", "8", "9", "10", "11", "12", "13"};
+ int len = good1_Strings.length;
+ for (int i = 0; i < len; i++) {
+ jdkVer = good1_Strings[i];
+ p = UnsafeUtil.parseJavaVersion(jdkVer);
+ UnsafeUtil.checkJavaVersion(jdkVer, p[0], p[1]);
+ int jdkMajor = (p[0] == 1) ? p[1] : p[0]; //model the actual JDK_MAJOR
+ if (p[0] == 1) { assertTrue(jdkMajor == p[1]); }
+ if (p[0] > 1 ) { assertTrue(jdkMajor == p[0]); }
+ }
+ try {
+ jdkVer = "14.0.4"; //ver 14 string
+ p = UnsafeUtil.parseJavaVersion(jdkVer);
+ UnsafeUtil.checkJavaVersion(jdkVer, p[0], p[1]);
+ fail();
+ } catch (IllegalArgumentException e) {
+ println("" + e);
+ }
+
+ try {
+ jdkVer = "1.7.0_80"; //1.7 string
+ p = UnsafeUtil.parseJavaVersion(jdkVer);
+ UnsafeUtil.checkJavaVersion(jdkVer, p[0], p[1]);
+ fail();
+ } catch (IllegalArgumentException e) {
+ println("" + e);
+ }
+ try {
+ jdkVer = "1.6.0_65"; //valid string but < 1.7
+ p = UnsafeUtil.parseJavaVersion(jdkVer);
+ UnsafeUtil.checkJavaVersion(jdkVer, p[0], p[1]); //throws
+ fail();
+ } catch (IllegalArgumentException e) {
+ println("" + e);
+ }
+ try {
+ jdkVer = "b"; //invalid string
+ p = UnsafeUtil.parseJavaVersion(jdkVer);
+ UnsafeUtil.checkJavaVersion(jdkVer, p[0], p[1]); //throws
+ fail();
+ } catch (IllegalArgumentException e) {
+ println("" + e);
+ }
+ try {
+ jdkVer = ""; //invalid string
+ p = UnsafeUtil.parseJavaVersion(jdkVer);
+ UnsafeUtil.checkJavaVersion(jdkVer, p[0], p[1]); //throws
+ fail();
+ } catch (IllegalArgumentException e) {
+ println("" + e);
+ }
+ }
+
+ @Test
+ public void checkFieldOffset() {
+ assertEquals(testField, 1);
+ long offset = UnsafeUtil.getFieldOffset(this.getClass(), "testField");
+ assertEquals(offset, 16);
+ try {
+ offset = UnsafeUtil.getFieldOffset(this.getClass(), "testField2");
+ fail();
+ } catch (IllegalStateException e) {
+ //OK
+ }
+ }
+
+ @Test(expectedExceptions = IllegalArgumentException.class)
+ public void checkInts() {
+ Ints.checkedCast(1L << 32);
+ }
+
+ @SuppressWarnings("restriction")
+ @Test
+ public void checkArrayBaseOffset()
+ {
+ final List<Class<?>> classes = new ArrayList<>();
+ classes.add(byte[].class);
+ classes.add(int[].class);
+ classes.add(long[].class);
+ classes.add(float[].class);
+ classes.add(double[].class);
+ classes.add(boolean[].class);
+ classes.add(short[].class);
+ classes.add(char[].class);
+ classes.add(Object[].class);
+ classes.add(byte[][].class); // An array type that is not cached
+
+ for (Class<?> clazz : classes) {
+ assertEquals(
+ UnsafeUtil.getArrayBaseOffset(clazz),
+ UnsafeUtil.unsafe.arrayBaseOffset(clazz),
+ clazz.getTypeName()
+ );
+ }
+ }
+
+ @Test
+ public void printlnTest() {
+ println("PRINTING: "+this.getClass().getName());
+ }
+
+ /**
+ * @param s String to print
+ */
+ static void println(final String s) {
+ //System.out.println(s);
+ }
+
+}
diff --git a/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/Utf8Test.java b/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/Utf8Test.java
new file mode 100644
index 0000000..762efe3
--- /dev/null
+++ b/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/Utf8Test.java
@@ -0,0 +1,516 @@
+/*
+ * 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
... 2380 lines suppressed ...
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@datasketches.apache.org
For additional commands, e-mail: commits-help@datasketches.apache.org