Added: 
dev/datasketches/memory/2.2.0-RC1/apache-datasketches-memory-2.2.0-src/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/BufferTest.java
==============================================================================
--- 
dev/datasketches/memory/2.2.0-RC1/apache-datasketches-memory-2.2.0-src/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/BufferTest.java
 (added)
+++ 
dev/datasketches/memory/2.2.0-RC1/apache-datasketches-memory-2.2.0-src/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/BufferTest.java
 Tue May 21 21:11:49 2024
@@ -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);
+  }
+
+}

Propchange: 
dev/datasketches/memory/2.2.0-RC1/apache-datasketches-memory-2.2.0-src/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/BufferTest.java
------------------------------------------------------------------------------
    svn:executable = *

Added: 
dev/datasketches/memory/2.2.0-RC1/apache-datasketches-memory-2.2.0-src/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/CommonBufferTest.java
==============================================================================
--- 
dev/datasketches/memory/2.2.0-RC1/apache-datasketches-memory-2.2.0-src/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/CommonBufferTest.java
 (added)
+++ 
dev/datasketches/memory/2.2.0-RC1/apache-datasketches-memory-2.2.0-src/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/CommonBufferTest.java
 Tue May 21 21:11:49 2024
@@ -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
+  }
+
+}

Propchange: 
dev/datasketches/memory/2.2.0-RC1/apache-datasketches-memory-2.2.0-src/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/CommonBufferTest.java
------------------------------------------------------------------------------
    svn:executable = *

Added: 
dev/datasketches/memory/2.2.0-RC1/apache-datasketches-memory-2.2.0-src/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/CommonMemoryTest.java
==============================================================================
--- 
dev/datasketches/memory/2.2.0-RC1/apache-datasketches-memory-2.2.0-src/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/CommonMemoryTest.java
 (added)
+++ 
dev/datasketches/memory/2.2.0-RC1/apache-datasketches-memory-2.2.0-src/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/CommonMemoryTest.java
 Tue May 21 21:11:49 2024
@@ -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
+  }
+}

Propchange: 
dev/datasketches/memory/2.2.0-RC1/apache-datasketches-memory-2.2.0-src/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/CommonMemoryTest.java
------------------------------------------------------------------------------
    svn:executable = *

Added: 
dev/datasketches/memory/2.2.0-RC1/apache-datasketches-memory-2.2.0-src/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/CopyMemoryOverlapTest.java
==============================================================================
--- 
dev/datasketches/memory/2.2.0-RC1/apache-datasketches-memory-2.2.0-src/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/CopyMemoryOverlapTest.java
 (added)
+++ 
dev/datasketches/memory/2.2.0-RC1/apache-datasketches-memory-2.2.0-src/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/CopyMemoryOverlapTest.java
 Tue May 21 21:11:49 2024
@@ -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
+  }
+}

Propchange: 
dev/datasketches/memory/2.2.0-RC1/apache-datasketches-memory-2.2.0-src/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/CopyMemoryOverlapTest.java
------------------------------------------------------------------------------
    svn:executable = *

Added: 
dev/datasketches/memory/2.2.0-RC1/apache-datasketches-memory-2.2.0-src/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/CopyMemoryTest.java
==============================================================================
--- 
dev/datasketches/memory/2.2.0-RC1/apache-datasketches-memory-2.2.0-src/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/CopyMemoryTest.java
 (added)
+++ 
dev/datasketches/memory/2.2.0-RC1/apache-datasketches-memory-2.2.0-src/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/CopyMemoryTest.java
 Tue May 21 21:11:49 2024
@@ -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
+  }
+}

Propchange: 
dev/datasketches/memory/2.2.0-RC1/apache-datasketches-memory-2.2.0-src/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/CopyMemoryTest.java
------------------------------------------------------------------------------
    svn:executable = *

Added: 
dev/datasketches/memory/2.2.0-RC1/apache-datasketches-memory-2.2.0-src/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/DruidIssue11544Test.java
==============================================================================
--- 
dev/datasketches/memory/2.2.0-RC1/apache-datasketches-memory-2.2.0-src/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/DruidIssue11544Test.java
 (added)
+++ 
dev/datasketches/memory/2.2.0-RC1/apache-datasketches-memory-2.2.0-src/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/DruidIssue11544Test.java
 Tue May 21 21:11:49 2024
@@ -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());
+  }
+
+}

Propchange: 
dev/datasketches/memory/2.2.0-RC1/apache-datasketches-memory-2.2.0-src/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/DruidIssue11544Test.java
------------------------------------------------------------------------------
    svn:executable = *

Added: 
dev/datasketches/memory/2.2.0-RC1/apache-datasketches-memory-2.2.0-src/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/ExampleMemoryRequestServerTest.java
==============================================================================
--- 
dev/datasketches/memory/2.2.0-RC1/apache-datasketches-memory-2.2.0-src/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/ExampleMemoryRequestServerTest.java
 (added)
+++ 
dev/datasketches/memory/2.2.0-RC1/apache-datasketches-memory-2.2.0-src/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/ExampleMemoryRequestServerTest.java
 Tue May 21 21:11:49 2024
@@ -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
+  }
+}

Propchange: 
dev/datasketches/memory/2.2.0-RC1/apache-datasketches-memory-2.2.0-src/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/ExampleMemoryRequestServerTest.java
------------------------------------------------------------------------------
    svn:executable = *

Added: 
dev/datasketches/memory/2.2.0-RC1/apache-datasketches-memory-2.2.0-src/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/IgnoredArrayOverflowTest.java
==============================================================================
--- 
dev/datasketches/memory/2.2.0-RC1/apache-datasketches-memory-2.2.0-src/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/IgnoredArrayOverflowTest.java
 (added)
+++ 
dev/datasketches/memory/2.2.0-RC1/apache-datasketches-memory-2.2.0-src/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/IgnoredArrayOverflowTest.java
 Tue May 21 21:11:49 2024
@@ -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);
+  }
+}

Propchange: 
dev/datasketches/memory/2.2.0-RC1/apache-datasketches-memory-2.2.0-src/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/IgnoredArrayOverflowTest.java
------------------------------------------------------------------------------
    svn:executable = *

Added: 
dev/datasketches/memory/2.2.0-RC1/apache-datasketches-memory-2.2.0-src/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/IsValidUtf8TestUtil.java
==============================================================================
--- 
dev/datasketches/memory/2.2.0-RC1/apache-datasketches-memory-2.2.0-src/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/IsValidUtf8TestUtil.java
 (added)
+++ 
dev/datasketches/memory/2.2.0-RC1/apache-datasketches-memory-2.2.0-src/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/IsValidUtf8TestUtil.java
 Tue May 21 21:11:49 2024
@@ -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;
+
+}

Propchange: 
dev/datasketches/memory/2.2.0-RC1/apache-datasketches-memory-2.2.0-src/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/IsValidUtf8TestUtil.java
------------------------------------------------------------------------------
    svn:executable = *



---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to