You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@datasketches.apache.org by dc...@apache.org on 2021/08/19 22:18:24 UTC

svn commit: r49567 [5/14] - in /dev/datasketches/memory/2.0.0-RC1: ./ apache-datasketches-memory-2.0.0-src/ apache-datasketches-memory-2.0.0-src/datasketches-memory-java11/ apache-datasketches-memory-2.0.0-src/datasketches-memory-java11/src/ apache-dat...

Added: dev/datasketches/memory/2.0.0-RC1/apache-datasketches-memory-2.0.0-src/datasketches-memory-java8-tests/src/test/java/org/apache/datasketches/memory/test/NonNativeWritableBufferImplTest.java
==============================================================================
--- dev/datasketches/memory/2.0.0-RC1/apache-datasketches-memory-2.0.0-src/datasketches-memory-java8-tests/src/test/java/org/apache/datasketches/memory/test/NonNativeWritableBufferImplTest.java (added)
+++ dev/datasketches/memory/2.0.0-RC1/apache-datasketches-memory-2.0.0-src/datasketches-memory-java8-tests/src/test/java/org/apache/datasketches/memory/test/NonNativeWritableBufferImplTest.java Thu Aug 19 22:18:24 2021
@@ -0,0 +1,261 @@
+/*
+ * 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.test;
+
+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
+ */
+@SuppressWarnings("javadoc")
+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);
+  }
+
+}

Added: dev/datasketches/memory/2.0.0-RC1/apache-datasketches-memory-2.0.0-src/datasketches-memory-java8-tests/src/test/java/org/apache/datasketches/memory/test/NonNativeWritableMemoryImplTest.java
==============================================================================
--- dev/datasketches/memory/2.0.0-RC1/apache-datasketches-memory-2.0.0-src/datasketches-memory-java8-tests/src/test/java/org/apache/datasketches/memory/test/NonNativeWritableMemoryImplTest.java (added)
+++ dev/datasketches/memory/2.0.0-RC1/apache-datasketches-memory-2.0.0-src/datasketches-memory-java8-tests/src/test/java/org/apache/datasketches/memory/test/NonNativeWritableMemoryImplTest.java Thu Aug 19 22:18:24 2021
@@ -0,0 +1,220 @@
+/*
+ * 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.test;
+
+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
+ */
+@SuppressWarnings("javadoc")
+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);
+  }
+
+}

Added: dev/datasketches/memory/2.0.0-RC1/apache-datasketches-memory-2.0.0-src/datasketches-memory-java8-tests/src/test/java/org/apache/datasketches/memory/test/ReflectUtil.java
==============================================================================
--- dev/datasketches/memory/2.0.0-RC1/apache-datasketches-memory-2.0.0-src/datasketches-memory-java8-tests/src/test/java/org/apache/datasketches/memory/test/ReflectUtil.java (added)
+++ dev/datasketches/memory/2.0.0-RC1/apache-datasketches-memory-2.0.0-src/datasketches-memory-java8-tests/src/test/java/org/apache/datasketches/memory/test/ReflectUtil.java Thu Aug 19 22:18:24 2021
@@ -0,0 +1,400 @@
+/*
+ * 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.test;
+
+import java.io.File;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.nio.ByteOrder;
+
+import org.apache.datasketches.memory.MemoryRequestServer;
+
+@SuppressWarnings("javadoc")
+public final class ReflectUtil {
+
+  private ReflectUtil() {}
+
+  static final Class<?> BASE_STATE;
+  static final Class<?> BASE_WRITABLE_MEMORY_IMPL;
+  static final Class<?> ALLOCATE_DIRECT_MAP;
+  static final Class<?> NIO_BITS;
+
+  static final Method CHECK_VALID; //BaseStateImpl
+  static final Method GET_DIRECT_ALLOCATIONS_COUNT; //NioBits
+  static final Method GET_MAX_DIRECT_BYTE_BUFFER_MEMORY; //NioBits
+  static final Method GET_NATIVE_BASE_OFFSET; //BaseStateImpl
+  static final Method GET_RESERVED_MEMORY; //NioBits
+  static final Method GET_TOTAL_CAPACITY; //NioBits
+  static final Method GET_UNSAFE_OBJECT; //BaseStateImpl
+  static final Method IS_BB_TYPE; //BaseStateImpl
+  static final Method IS_BUFFER_TYPE; //BaseStateImpl
+  static final Method IS_DIRECT_TYPE; //BaseStateImpl
+  static final Method IS_DUPLICATE_TYPE; //BaseStateImpl
+  static final Method IS_FILE_READ_ONLY; //AllocateDirectMap
+  static final Method IS_HEAP_TYPE; //BaseStateImpl
+  static final Method IS_MAP_TYPE; //BaseStateImpl
+  static final Method IS_NON_NATIVE_TYPE; //BaseStateImpl
+  static final Method IS_PAGE_ALIGHED; //NioBits
+  static final Method IS_READ_ONLY_TYPE; //BaseStateImpl
+  static final Method IS_REGION_TYPE; //BaseStateImpl
+  static final Method PAGE_COUNT; //NioBits
+  static final Method PAGE_SIZE; //NioBits
+  static final Method RESERVE_MEMORY; //NioBits
+  static final Method UNRESERVE_MEMORY; //NioBits
+  static final Method WRAP_DIRECT; //BaseWritableMemoryImpl
+
+  static {
+    BASE_STATE =
+        getClass("org.apache.datasketches.memory.internal.BaseStateImpl");
+    BASE_WRITABLE_MEMORY_IMPL =
+        getClass("org.apache.datasketches.memory.internal.BaseWritableMemoryImpl");
+    ALLOCATE_DIRECT_MAP =
+        getClass("org.apache.datasketches.memory.internal.AllocateDirectMap");
+    NIO_BITS =
+        getClass("org.apache.datasketches.memory.internal.NioBits");
+
+    CHECK_VALID =
+        getMethod(BASE_STATE, "checkValid", (Class<?>[])null); //not static
+    GET_DIRECT_ALLOCATIONS_COUNT =
+        getMethod(NIO_BITS, "getDirectAllocationsCount", (Class<?>[])null); //static
+    GET_MAX_DIRECT_BYTE_BUFFER_MEMORY =
+        getMethod(NIO_BITS, "getMaxDirectByteBufferMemory", (Class<?>[])null); //static
+    GET_NATIVE_BASE_OFFSET =
+        getMethod(BASE_STATE, "getNativeBaseOffset", (Class<?>[])null);
+    GET_RESERVED_MEMORY =
+        getMethod(NIO_BITS, "getReservedMemory", (Class<?>[])null); //static
+    GET_TOTAL_CAPACITY =
+        getMethod(NIO_BITS, "getTotalCapacity", (Class<?>[])null); //static
+    GET_UNSAFE_OBJECT =
+        getMethod(BASE_STATE, "getUnsafeObject", (Class<?>[])null); //not static
+    IS_BB_TYPE =
+        getMethod(BASE_STATE, "isBBType", (Class<?>[])null); //not static
+    IS_BUFFER_TYPE =
+        getMethod(BASE_STATE, "isBufferType", (Class<?>[])null); //not static
+    IS_DIRECT_TYPE =
+        getMethod(BASE_STATE, "isDirectType", (Class<?>[])null); //not static
+    IS_DUPLICATE_TYPE =
+        getMethod(BASE_STATE, "isDuplicateType", (Class<?>[])null); //not static
+    IS_FILE_READ_ONLY =
+        getMethod(ALLOCATE_DIRECT_MAP, "isFileReadOnly", File.class);
+    IS_HEAP_TYPE =
+        getMethod(BASE_STATE, "isHeapType", (Class<?>[])null); //not static
+    IS_MAP_TYPE =
+        getMethod(BASE_STATE, "isMapType", (Class<?>[])null); //not static
+    IS_NON_NATIVE_TYPE =
+        getMethod(BASE_STATE, "isNonNativeType", (Class<?>[])null); //not static
+    IS_PAGE_ALIGHED =
+        getMethod(NIO_BITS, "isPageAligned", (Class<?>[])null); //static
+    IS_READ_ONLY_TYPE =
+        getMethod(BASE_STATE, "isReadOnlyType", (Class<?>[])null); //not static
+    IS_REGION_TYPE =
+        getMethod(BASE_STATE, "isRegionType", (Class<?>[])null); //not static
+    PAGE_COUNT =
+        getMethod(NIO_BITS, "pageCount", long.class); //static
+    PAGE_SIZE =
+        getMethod(NIO_BITS, "pageSize", (Class<?>[])null); //static
+    RESERVE_MEMORY =
+        getMethod(NIO_BITS, "reserveMemory", long.class, long.class); //static
+    UNRESERVE_MEMORY =
+        getMethod(NIO_BITS, "unreserveMemory", long.class, long.class); //static
+    WRAP_DIRECT =
+        getMethod(BASE_WRITABLE_MEMORY_IMPL,
+            "wrapDirect", long.class, ByteOrder.class, MemoryRequestServer.class);  //static method
+  }
+
+  /**
+   * Gets a Class reference to the given class loaded by the SystemClassLoader.
+   * This will work for private, package-private and abstract classes.
+   * @param fullyQualifiedBinaryName the binary name is the name of the class file on disk. This does not instantiate
+   * a concrete class, but allows access to constructors, static fields and static methods.
+   * @return the Class object of the given class.
+   */
+  public static Class<?> getClass(final String fullyQualifiedBinaryName) {
+    try {
+      final ClassLoader scl = ClassLoader.getSystemClassLoader();
+      return scl.loadClass(fullyQualifiedBinaryName);
+    } catch (final ClassNotFoundException e) {
+      throw new RuntimeException(e);
+    }
+  }
+
+  /**
+   * Gets a declared constructor given the owner class and parameter types
+   * @param ownerClass the Class<?> object of the class loaded by the SystemClassLoader.
+   * @param parameterTypes parameter types for the constructor
+   * @return the constructor
+   */
+  public static Constructor<?> getConstructor(final Class<?> ownerClass, final Class<?>... parameterTypes ) {
+    try {
+      final Constructor<?> ctor = ownerClass.getDeclaredConstructor(parameterTypes);
+      ctor.setAccessible(true);
+      return ctor;
+    } catch (final NoSuchMethodException | SecurityException e) {
+      throw new RuntimeException(e);
+    }
+  }
+
+  /**
+   * Gets a class instance from its constructor and initializing arguments.
+   * @param constructor the given Constructor
+   * @param initargs the initializing arguments
+   * @return the instantiated class.
+   */
+  public static Object getInstance(final Constructor<?> constructor, final Object... initargs) {
+    try {
+      constructor.setAccessible(true);
+      return constructor.newInstance(initargs);
+    } catch (final InstantiationException | IllegalAccessException | IllegalArgumentException
+          | InvocationTargetException | SecurityException e) {
+      throw new RuntimeException(e);
+    }
+  }
+
+  /**
+   * Gets a declared field of the given the loaded owner class and field name. The accessible flag will be set true.
+   * @param ownerClass the Class<?> object of the class loaded by the SystemClassLoader.
+   * @param fieldName the desired field name
+   * @return the desired field.
+   */
+  public static Field getField(final Class<?> ownerClass, final String fieldName) {
+    try {
+      final Field field = ownerClass.getDeclaredField(fieldName);
+      field.setAccessible(true);
+      return field;
+    } catch (final NoSuchFieldException | SecurityException e) {
+      throw new RuntimeException(e);
+    }
+  }
+
+  /**
+   * Gets a field value given the loaded owner class and the Field. The accessible flag will be set true.
+   * @param ownerClass the loaded class owning the field
+   * @param field The Field object
+   * @return the returned value as an object.
+   */
+  public static Object getFieldValue(final Class<?> ownerClass, final Field field) {
+    try {
+      field.setAccessible(true);
+      return field.get(ownerClass);
+    } catch (final IllegalAccessException | SecurityException | IllegalArgumentException e) {
+      throw new RuntimeException(e);
+    }
+  }
+
+  /**
+   * Gets a declared method of the given the loaded owning class, method name and parameter types.
+   * The accessible flag will be set true.
+   * @param ownerClass the given
+   * @param methodName the given method name
+   * @param parameterTypes the list of parameter types
+   * @return the desired method.
+   */
+  public static Method getMethod(
+      final Class<?> ownerClass, final String methodName, final Class<?>... parameterTypes ) {
+    try {
+      final Method method = (parameterTypes == null)
+          ? ownerClass.getDeclaredMethod(methodName)
+          : ownerClass.getDeclaredMethod(methodName, parameterTypes);
+      method.setAccessible(true);
+      return method;
+    } catch (final NoSuchMethodException | SecurityException e) {
+      throw new RuntimeException(e);
+    }
+  }
+
+  static void checkValid(final Object target) {
+    try {
+      CHECK_VALID.invoke(target);
+    } catch (final IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
+      throw new RuntimeException(e);
+    }
+  }
+
+  static long getDirectAllocationsCount() {
+    try {
+      return (long) GET_DIRECT_ALLOCATIONS_COUNT.invoke(null);
+    } catch (final IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
+      throw new RuntimeException(e);
+    }
+  }
+
+  static long getMaxDirectByteBufferMemory() {
+    try {
+      return (long) GET_MAX_DIRECT_BYTE_BUFFER_MEMORY.invoke(null);
+    } catch (final IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
+      throw new RuntimeException(e);
+    }
+  }
+
+  static long getNativeBaseOffset(final Object target) {
+    try {
+      return (long) GET_NATIVE_BASE_OFFSET.invoke(target);
+    } catch (final IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
+      throw new RuntimeException(e);
+    }
+  }
+
+  static long getReservedMemory() {
+    try {
+      return (long) GET_RESERVED_MEMORY.invoke(null);
+    } catch (final IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
+      throw new RuntimeException(e);
+    }
+  }
+
+  static long getTotalCapacity() {
+    try {
+      return (long) GET_TOTAL_CAPACITY.invoke(null);
+    } catch (final IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
+      throw new RuntimeException(e);
+    }
+  }
+
+  static Object getUnsafeObject(final Object target) {
+    try {
+      return GET_UNSAFE_OBJECT.invoke(target);
+    } catch (final IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
+      throw new RuntimeException(e);
+    }
+  }
+
+  static boolean isBBType(final Object target) {
+    try {
+      return (boolean) IS_BB_TYPE.invoke(target);
+    } catch (final IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
+      throw new RuntimeException(e);
+    }
+  }
+
+  static boolean isBufferType(final Object target) {
+    try {
+      return (boolean) IS_BUFFER_TYPE.invoke(target);
+    } catch (final IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
+      throw new RuntimeException(e);
+    }
+  }
+
+  static boolean isDirectType(final Object target) {
+    try {
+      return (boolean) IS_DIRECT_TYPE.invoke(target);
+    } catch (final IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
+      throw new RuntimeException(e);
+    }
+  }
+
+  static boolean isDuplicateType(final Object target) {
+    try {
+      return (boolean) IS_DUPLICATE_TYPE.invoke(target);
+    } catch (final IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
+      throw new RuntimeException(e);
+    }
+  }
+
+  static boolean isFileReadOnly(final File file) {
+    try {
+      return (boolean) IS_FILE_READ_ONLY.invoke(null, file);
+    } catch (final IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
+      throw new RuntimeException(e);
+    }
+  }
+
+  static boolean isHeapType(final Object target) {
+    try {
+      return (boolean) IS_HEAP_TYPE.invoke(target);
+    } catch (final IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
+      throw new RuntimeException(e);
+    }
+  }
+
+  static boolean isMapType(final Object target) {
+    try {
+      return (boolean) IS_MAP_TYPE.invoke(target);
+    } catch (final IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
+      throw new RuntimeException(e);
+    }
+  }
+
+  static boolean isNonNativeType(final Object target) {
+    try {
+      return (boolean) IS_NON_NATIVE_TYPE.invoke(target);
+    } catch (final IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
+      throw new RuntimeException(e);
+    }
+  }
+
+  static boolean isPageAligned() {
+    try {
+      return (boolean) IS_PAGE_ALIGHED.invoke(null);
+    } catch (final IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
+      throw new RuntimeException(e);
+    }
+  }
+
+  static boolean isReadOnlyType(final Object target) {
+    try {
+      return (boolean) IS_READ_ONLY_TYPE.invoke(target);
+    } catch (final IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
+      throw new RuntimeException(e);
+    }
+  }
+
+  static boolean isRegionType(final Object target) {
+    try {
+      return (boolean) IS_REGION_TYPE.invoke(target);
+    } catch (final IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
+      throw new RuntimeException(e);
+    }
+  }
+
+  static int pageCount(final long bytes) {
+    try {
+      return (int) PAGE_COUNT.invoke(null, bytes);
+    } catch (final IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
+      throw new RuntimeException(e);
+    }
+  }
+
+  static int pageSize() {
+    try {
+      return (int) PAGE_SIZE.invoke(null);
+    } catch (final IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
+      throw new RuntimeException(e);
+    }
+  }
+
+  static void reserveMemory(final long allocationSize, final long capacity) {
+    try {
+     RESERVE_MEMORY.invoke(null, allocationSize, capacity);
+    } catch (final IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
+      throw new RuntimeException(e);
+    }
+  }
+
+  static void unreserveMemory(final long allocationSize, final long capacity) {
+    try {
+      UNRESERVE_MEMORY.invoke(null, allocationSize, capacity);
+    } catch (final IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
+      throw new RuntimeException(e);
+    }
+  }
+
+}

Added: dev/datasketches/memory/2.0.0-RC1/apache-datasketches-memory-2.0.0-src/datasketches-memory-java8-tests/src/test/java/org/apache/datasketches/memory/test/SpecificLeafTest.java
==============================================================================
--- dev/datasketches/memory/2.0.0-RC1/apache-datasketches-memory-2.0.0-src/datasketches-memory-java8-tests/src/test/java/org/apache/datasketches/memory/test/SpecificLeafTest.java (added)
+++ dev/datasketches/memory/2.0.0-RC1/apache-datasketches-memory-2.0.0-src/datasketches-memory-java8-tests/src/test/java/org/apache/datasketches/memory/test/SpecificLeafTest.java Thu Aug 19 22:18:24 2021
@@ -0,0 +1,196 @@
+/*
+ * 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.test;
+
+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.apache.datasketches.memory.internal.Util;
+import org.testng.annotations.Test;
+
+/**
+ * @author Lee Rhodes
+ */
+@SuppressWarnings("javadoc")
+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(ReflectUtil.isBBType(mem));
+    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(ReflectUtil.isRegionType(mem));
+    assertTrue(ReflectUtil.isRegionType(mem2));
+    assertTrue(ReflectUtil.isRegionType(buf));
+    assertTrue(ReflectUtil.isRegionType(buf2));
+    assertTrue(ReflectUtil.isDuplicateType(buf3));
+  }
+
+  @Test
+  public void checkDirectLeafs() throws Exception {
+    int bytes = 128;
+    try (WritableHandle h = WritableMemory.allocateDirect(bytes)) {
+      WritableMemory wmem = h.getWritable(); //native mem
+      assertTrue(ReflectUtil.isDirectType(wmem));
+      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(ReflectUtil.isRegionType(mem));
+      assertTrue(ReflectUtil.isRegionType(mem2));
+      assertTrue(ReflectUtil.isRegionType(buf));
+      assertTrue(ReflectUtil.isRegionType(buf2));
+      assertTrue(ReflectUtil.isDuplicateType(buf3));
+    }
+  }
+
+  @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(ReflectUtil.isMapType(mem));
+      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(ReflectUtil.isRegionType(reg));
+      assertTrue(ReflectUtil.isRegionType(reg2));
+      assertTrue(ReflectUtil.isRegionType(buf));
+      assertTrue(ReflectUtil.isRegionType(buf2));
+      assertTrue(ReflectUtil.isDuplicateType(buf3));
+      assertTrue(ReflectUtil.isDuplicateType(buf4));
+    }
+  }
+
+  @Test
+  public void checkHeapLeafs() {
+    int bytes = 128;
+    Memory mem = Memory.wrap(new byte[bytes]);
+    assertTrue(ReflectUtil.isHeapType(mem));
+    assertTrue(ReflectUtil.isReadOnlyType(mem));
+    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(ReflectUtil.isRegionType(mem));
+    assertTrue(ReflectUtil.isRegionType(reg2));
+    assertTrue(ReflectUtil.isRegionType(buf));
+    assertTrue(ReflectUtil.isRegionType(buf2));
+    assertTrue(ReflectUtil.isDuplicateType(buf3));
+    assertTrue(ReflectUtil.isDuplicateType(buf4));
+  }
+
+  private static void checkCrossLeafTypeIds(Memory mem) {
+    Memory reg1 = mem.region(0, mem.getCapacity());
+    assertTrue(ReflectUtil.isRegionType(reg1));
+
+    Buffer buf1 = reg1.asBuffer();
+    assertTrue(ReflectUtil.isRegionType(buf1));
+    assertTrue(ReflectUtil.isBufferType(buf1));
+    assertTrue(buf1.isReadOnly());
+
+    Buffer buf2 = buf1.duplicate();
+    assertTrue(ReflectUtil.isRegionType(buf2));
+    assertTrue(ReflectUtil.isBufferType(buf2));
+    assertTrue(ReflectUtil.isDuplicateType(buf2));
+    assertTrue(buf2.isReadOnly());
+
+    Memory mem2 = buf1.asMemory(); //
+    assertTrue(ReflectUtil.isRegionType(mem2));
+    assertFalse(ReflectUtil.isBufferType(mem2));
+    assertFalse(ReflectUtil.isDuplicateType(mem2));
+    assertTrue(mem2.isReadOnly());
+
+    Buffer buf3 = buf1.duplicate(Util.NON_NATIVE_BYTE_ORDER);
+    assertTrue(ReflectUtil.isRegionType(buf3));
+    assertTrue(ReflectUtil.isBufferType(buf3));
+    assertTrue(ReflectUtil.isDuplicateType(buf3));
+    assertTrue(ReflectUtil.isNonNativeType(buf3));
+    assertTrue(buf3.isReadOnly());
+
+    Memory mem3 = buf3.asMemory();
+    assertTrue(ReflectUtil.isRegionType(mem3));
+    assertFalse(ReflectUtil.isBufferType(mem3));
+    assertTrue(ReflectUtil.isDuplicateType(mem3));
+    assertTrue(ReflectUtil.isNonNativeType(mem3));
+    assertTrue(mem3.isReadOnly());
+  }
+
+}

Added: dev/datasketches/memory/2.0.0-RC1/apache-datasketches-memory-2.0.0-src/datasketches-memory-java8-tests/src/test/java/org/apache/datasketches/memory/test/UnsafeUtilTest.java
==============================================================================
--- dev/datasketches/memory/2.0.0-RC1/apache-datasketches-memory-2.0.0-src/datasketches-memory-java8-tests/src/test/java/org/apache/datasketches/memory/test/UnsafeUtilTest.java (added)
+++ dev/datasketches/memory/2.0.0-RC1/apache-datasketches-memory-2.0.0-src/datasketches-memory-java8-tests/src/test/java/org/apache/datasketches/memory/test/UnsafeUtilTest.java Thu Aug 19 22:18:24 2021
@@ -0,0 +1,154 @@
+/*
+ * 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.test;
+
+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.apache.datasketches.memory.internal.Ints;
+import org.apache.datasketches.memory.internal.UnsafeUtil;
+import org.testng.annotations.Test;
+
+
+/**
+ * @author Lee Rhodes
+ */
+@SuppressWarnings("javadoc")
+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);
+  }
+
+}

Added: dev/datasketches/memory/2.0.0-RC1/apache-datasketches-memory-2.0.0-src/datasketches-memory-java8-tests/src/test/java/org/apache/datasketches/memory/test/Utf8Test.java
==============================================================================
--- dev/datasketches/memory/2.0.0-RC1/apache-datasketches-memory-2.0.0-src/datasketches-memory-java8-tests/src/test/java/org/apache/datasketches/memory/test/Utf8Test.java (added)
+++ dev/datasketches/memory/2.0.0-RC1/apache-datasketches-memory-2.0.0-src/datasketches-memory-java8-tests/src/test/java/org/apache/datasketches/memory/test/Utf8Test.java Thu Aug 19 22:18:24 2021
@@ -0,0 +1,517 @@
+/*
+ * 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.test;
+
+import static java.nio.charset.StandardCharsets.UTF_8;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.fail;
+
+import java.io.IOException;
+import java.nio.CharBuffer;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.datasketches.memory.Memory;
+import org.apache.datasketches.memory.Utf8CodingException;
+import org.apache.datasketches.memory.WritableMemory;
+import org.apache.datasketches.memory.internal.Util.RandomCodePoints;
+import org.testng.annotations.Test;
+
+import com.google.protobuf.ByteString;
+
+/**
+ * Adapted version of
+ * https://github.com/protocolbuffers/protobuf/blob/master/java/core/src/test/java/com/google/protobuf/DecodeUtf8Test.java
+ *
+ * Copyright 2008 Google Inc.  All rights reserved.
+ * https://developers.google.com/protocol-buffers/
+ * See LICENSE.
+ */
+@SuppressWarnings("javadoc")
+public class Utf8Test {
+
+  @Test
+  public void testRoundTripAllValidCodePoints() throws IOException { //the non-surrogate code pts
+    for (int cp = Character.MIN_CODE_POINT; cp < Character.MAX_CODE_POINT; cp++) {
+      if (!isSurrogateCodePoint(cp)) {
+        String refStr = new String(Character.toChars(cp));
+        assertRoundTrips(refStr);
+      }
+    }
+  }
+
+  @Test
+  public void testPutInvalidChars() { //The surrogates must be a pair, thus invalid alone
+    WritableMemory mem = WritableMemory.allocate(10);
+    WritableMemory emptyMem = WritableMemory.allocate(0);
+    for (int c = Character.MIN_SURROGATE; c <= Character.MAX_SURROGATE; c++) {
+      assertSurrogate(mem, (char) c);
+      assertSurrogate(emptyMem, (char) c);
+    }
+  }
+
+  private static void assertSurrogate(WritableMemory mem, char c) {
+    try {
+      mem.putCharsToUtf8(0, new String(new char[] {c}));
+      fail();
+    } catch (Utf8CodingException e) {
+      // Expected.
+    }
+  }
+
+  @Test
+  public void testPutInvaidSurrogatePairs() {
+    WritableMemory mem = WritableMemory.allocate(4);
+    StringBuilder sb = new StringBuilder();
+    sb.append(Character.MIN_HIGH_SURROGATE);
+    sb.append(Character.MAX_HIGH_SURROGATE);
+    try {
+      mem.putCharsToUtf8(0, sb);
+    } catch (Utf8CodingException e) {
+      //Expected;
+    }
+  }
+
+  @Test
+  public void testPutHighBMP() {
+    WritableMemory mem = WritableMemory.allocate(2);
+    StringBuilder sb = new StringBuilder();
+    sb.append("\uE000");
+    try {
+      mem.putCharsToUtf8(0, sb);
+    } catch (Utf8CodingException e) {
+      //Expected;
+    }
+  }
+
+  @Test
+  public void testPutExtendedAscii() {
+    WritableMemory mem = WritableMemory.allocate(1);
+    StringBuilder sb = new StringBuilder();
+    sb.append("\u07FF");
+    try {
+      mem.putCharsToUtf8(0, sb);
+    } catch (Utf8CodingException e) {
+      //Expected;
+    }
+  }
+
+  @Test
+  public void testPutOneAsciiToEmpty() {
+    WritableMemory mem = WritableMemory.allocate(0);
+    StringBuilder sb = new StringBuilder();
+    sb.append("a");
+    try {
+      mem.putCharsToUtf8(0, sb);
+    } catch (Utf8CodingException e) {
+      //Expected;
+    }
+  }
+
+  @Test
+  public void testPutValidSurrogatePair() {
+    WritableMemory mem = WritableMemory.allocate(4);
+    StringBuilder sb = new StringBuilder();
+    sb.append(Character.MIN_HIGH_SURROGATE);
+    sb.append(Character.MIN_LOW_SURROGATE);
+    mem.putCharsToUtf8(0, sb);
+  }
+
+  // Test all 1, 2, 3 invalid byte combinations. Valid ones would have been covered above.
+
+  @Test
+  public void testOneByte() {
+    int valid = 0;
+    for (int i = Byte.MIN_VALUE; i <= Byte.MAX_VALUE; i++) {
+      ByteString bs = ByteString.copyFrom(new byte[] {(byte) i });
+      if (!bs.isValidUtf8()) { //from -128 to -1
+        assertInvalid(bs.toByteArray());
+      } else {
+        valid++; //from 0 to 127
+      }
+    }
+    assertEquals(IsValidUtf8TestUtil.EXPECTED_ONE_BYTE_ROUNDTRIPPABLE_COUNT, valid);
+  }
+
+  @Test
+  public void testTwoBytes() {
+    int valid = 0;
+    for (int i = Byte.MIN_VALUE; i <= Byte.MAX_VALUE; i++) {
+      for (int j = Byte.MIN_VALUE; j <= Byte.MAX_VALUE; j++) {
+        ByteString bs = ByteString.copyFrom(new byte[]{(byte) i, (byte) j});
+        if (!bs.isValidUtf8()) {
+          assertInvalid(bs.toByteArray());
+        } else {
+          valid++;
+        }
+      }
+    }
+    assertEquals(IsValidUtf8TestUtil.EXPECTED_TWO_BYTE_ROUNDTRIPPABLE_COUNT, valid);
+  }
+
+  //@Test
+  //This test is very long, and doesn't cover the 4-byte combinations.
+  // This is replaced by the test following which does cover some 4-byte combinations.
+  public void testThreeBytes() {
+    // Travis' OOM killer doesn't like this test
+    if (System.getenv("TRAVIS") == null) {
+      int count = 0;
+      int valid = 0;
+      for (int i = Byte.MIN_VALUE; i <= Byte.MAX_VALUE; i++) {
+        for (int j = Byte.MIN_VALUE; j <= Byte.MAX_VALUE; j++) {
+          for (int k = Byte.MIN_VALUE; k <= Byte.MAX_VALUE; k++) {
+            byte[] bytes = new byte[]{(byte) i, (byte) j, (byte) k};
+            ByteString bs = ByteString.copyFrom(bytes);
+            if (!bs.isValidUtf8()) {
+              assertInvalid(bytes);
+            } else {
+              valid++;
+            }
+            count++;
+            if ((count % 1000000L) == 0) {
+              println("Processed " + (count / 1000000L) + " million characters");
+            }
+          }
+        }
+      }
+      assertEquals(IsValidUtf8TestUtil.EXPECTED_THREE_BYTE_ROUNDTRIPPABLE_COUNT, valid);
+    }
+  }
+
+  /* These code points can be used by the following test to customize different regions of the
+   * Code Point space. This randomized test can replace the exhaustive
+   * combinatorially explosive previous test, which doesn't cover the 4 byte combinations.
+   */
+  static final int min1ByteCP   = 0; //ASCII
+  static final int min2ByteCP   = 0X000080;
+  static final int min3ByteCP   = 0X000800;
+  static final int min4ByteCP   = Character.MIN_SUPPLEMENTARY_CODE_POINT; //0X010000;
+  static final int minPlane2CP  = 0X020000;
+  static final int maxCodePoint = Character.MAX_CODE_POINT;               //0X10FFFF
+  static final int minSurr      = Character.MIN_SURROGATE;                //0X00D800;
+  static final int maxSurr      = Character.MAX_SURROGATE;                //0X00E000;
+
+  @Test
+  //randomly selects CP from a range that include 1, 2, 3 and 4 byte encodings.
+  // with 50% coming from plane 0 and 50% coming from plane 1.
+  public void checkRandomValidCodePoints() {
+    RandomCodePoints rcp = new RandomCodePoints(true);
+    int numCP = 1000;
+    int[] cpArr = new int[numCP];
+    rcp.fillCodePointArray(cpArr, 0, minPlane2CP);
+    String rcpStr = new String(cpArr, 0, numCP);
+    //println(rcpStr);
+    WritableMemory wmem = WritableMemory.allocate(4 * numCP);
+    int utf8Bytes = (int) wmem.putCharsToUtf8(0, rcpStr);
+
+    StringBuilder sb = new StringBuilder();
+    try {
+      wmem.getCharsFromUtf8(0L, utf8Bytes, (Appendable) sb);
+    } catch (IOException | Utf8CodingException e) {
+      throw new RuntimeException(e);
+    }
+    checkStrings(sb.toString(), rcpStr);
+
+    CharBuffer cb = CharBuffer.allocate(rcpStr.length());
+    try {
+      wmem.getCharsFromUtf8(0L, utf8Bytes, cb);
+    } catch (IOException | Utf8CodingException e) {
+      throw new RuntimeException(e);
+    }
+    String cbStr = sb.toString();
+    assertEquals(cbStr.length(), rcpStr.length());
+    checkStrings(cbStr, rcpStr);
+  }
+
+  @Test
+  public void checkRandomValidCodePoints2() {
+    //checks the non-deterministic constructor
+    @SuppressWarnings("unused")
+    RandomCodePoints rcp = new RandomCodePoints(false);
+  }
+
+
+  /**
+   * Tests that round tripping of a sample of four byte permutations work.
+   */
+  @Test
+  public void testInvalid_4BytesSamples() {
+    // Bad trailing bytes
+    assertInvalid(0xF0, 0xA4, 0xAD, 0x7F);
+    assertInvalid(0xF0, 0xA4, 0xAD, 0xC0);
+
+    // Special cases for byte2
+    assertInvalid(0xF0, 0x8F, 0xAD, 0xA2);
+    assertInvalid(0xF4, 0x90, 0xAD, 0xA2);
+  }
+
+  @Test
+  public void testRealStrings() throws IOException {
+    // English
+    assertRoundTrips("The quick brown fox jumps over the lazy dog");
+    // German
+    assertRoundTrips("Quizdeltagerne spiste jordb\u00e6r med fl\u00f8de, mens cirkusklovnen");
+    // Japanese
+    assertRoundTrips(
+        "\u3044\u308d\u306f\u306b\u307b\u3078\u3068\u3061\u308a\u306c\u308b\u3092");
+    // Hebrew
+    assertRoundTrips(
+        "\u05d3\u05d2 \u05e1\u05e7\u05e8\u05df \u05e9\u05d8 \u05d1\u05d9\u05dd "
+        + "\u05de\u05d0\u05d5\u05db\u05d6\u05d1 \u05d5\u05dc\u05e4\u05ea\u05e2"
+        + " \u05de\u05e6\u05d0 \u05dc\u05d5 \u05d7\u05d1\u05e8\u05d4 "
+        + "\u05d0\u05d9\u05da \u05d4\u05e7\u05dc\u05d9\u05d8\u05d4");
+    // Thai
+    assertRoundTrips(
+        " \u0e08\u0e07\u0e1d\u0e48\u0e32\u0e1f\u0e31\u0e19\u0e1e\u0e31\u0e12"
+        + "\u0e19\u0e32\u0e27\u0e34\u0e0a\u0e32\u0e01\u0e32\u0e23");
+    // Chinese
+    assertRoundTrips(
+        "\u8fd4\u56de\u94fe\u4e2d\u7684\u4e0b\u4e00\u4e2a\u4ee3\u7406\u9879\u9009\u62e9\u5668");
+    // Chinese with 4-byte chars
+    assertRoundTrips("\uD841\uDF0E\uD841\uDF31\uD841\uDF79\uD843\uDC53\uD843\uDC78"
+                     + "\uD843\uDC96\uD843\uDCCF\uD843\uDCD5\uD843\uDD15\uD843\uDD7C\uD843\uDD7F"
+                     + "\uD843\uDE0E\uD843\uDE0F\uD843\uDE77\uD843\uDE9D\uD843\uDEA2");
+    // Mixed
+    assertRoundTrips(
+        "The quick brown \u3044\u308d\u306f\u306b\u307b\u3078\u8fd4\u56de\u94fe"
+        + "\u4e2d\u7684\u4e0b\u4e00");
+  }
+
+  @Test
+  public void checkNonEmptyDestinationForDecode() {
+    StringBuilder sb = new StringBuilder();
+    sb.append("abc"); //current contents of destination
+    int startChars = sb.toString().toCharArray().length;
+    String refStr = "Quizdeltagerne spiste jordb\u00e6r med fl\u00f8de, mens cirkusklovnen";
+    byte[] refByteArr = refStr.getBytes(UTF_8);
+    int addBytes = refByteArr.length;
+    WritableMemory refMem = WritableMemory.writableWrap(refByteArr);
+    int decodedChars = refMem.getCharsFromUtf8(0, addBytes, sb);
+    String finalStr = sb.toString();
+    int finalChars = finalStr.toCharArray().length;
+    assertEquals(decodedChars + startChars, finalChars);
+    println("Decoded chars: " + decodedChars);
+    println("Final chars: " + finalChars);
+    println(sb.toString());
+  }
+
+  @Test
+  public void checkNonEmptyDestinationForEncode() {
+    String refStr = "Quizdeltagerne spiste jordb\u00e6r med fl\u00f8de, mens cirkusklovnen";
+    byte[] refByteArr = refStr.getBytes(UTF_8);
+    int refBytes = refByteArr.length;
+    int offset = 100;
+    WritableMemory tgtMem = WritableMemory.allocate(refBytes + offset);
+    long bytesEncoded = tgtMem.putCharsToUtf8(offset, refStr);
+    assertEquals(bytesEncoded, refBytes);
+  }
+
+  @Test
+  public void testOverlong() {
+    assertInvalid(0xc0, 0xaf);
+    assertInvalid(0xe0, 0x80, 0xaf);
+    assertInvalid(0xf0, 0x80, 0x80, 0xaf);
+
+    // Max overlong
+    assertInvalid(0xc1, 0xbf);
+    assertInvalid(0xe0, 0x9f, 0xbf);
+    assertInvalid(0xf0 ,0x8f, 0xbf, 0xbf);
+
+    // null overlong
+    assertInvalid(0xc0, 0x80);
+    assertInvalid(0xe0, 0x80, 0x80);
+    assertInvalid(0xf0, 0x80, 0x80, 0x80);
+  }
+
+  @Test
+  public void testIllegalCodepoints() {
+    // Single surrogate
+    assertInvalid(0xed, 0xa0, 0x80);
+    assertInvalid(0xed, 0xad, 0xbf);
+    assertInvalid(0xed, 0xae, 0x80);
+    assertInvalid(0xed, 0xaf, 0xbf);
+    assertInvalid(0xed, 0xb0, 0x80);
+    assertInvalid(0xed, 0xbe, 0x80);
+    assertInvalid(0xed, 0xbf, 0xbf);
+
+    // Paired surrogates
+    assertInvalid(0xed, 0xa0, 0x80, 0xed, 0xb0, 0x80);
+    assertInvalid(0xed, 0xa0, 0x80, 0xed, 0xbf, 0xbf);
+    assertInvalid(0xed, 0xad, 0xbf, 0xed, 0xb0, 0x80);
+    assertInvalid(0xed, 0xad, 0xbf, 0xed, 0xbf, 0xbf);
+    assertInvalid(0xed, 0xae, 0x80, 0xed, 0xb0, 0x80);
+    assertInvalid(0xed, 0xae, 0x80, 0xed, 0xbf, 0xbf);
+    assertInvalid(0xed, 0xaf, 0xbf, 0xed, 0xb0, 0x80);
+    assertInvalid(0xed, 0xaf, 0xbf, 0xed, 0xbf, 0xbf);
+  }
+
+  @Test
+  public void testBufferSlice() throws IOException {
+    String str = "The quick brown fox jumps over the lazy dog";
+    assertRoundTrips(str, 4, 10, 4);
+    assertRoundTrips(str, 0, str.length(), 0);
+  }
+
+  @Test
+  public void testInvalidBufferSlice() { //these are pure Memory bounds violations
+    byte[] bytes  = "The quick brown fox jumps over the lazy dog".getBytes(UTF_8);
+    assertInvalidSlice(bytes, bytes.length - 3, 4);
+    assertInvalidSlice(bytes, bytes.length, 1);
+    assertInvalidSlice(bytes, bytes.length + 1, 0);
+    assertInvalidSlice(bytes, 0, bytes.length + 1);
+  }
+
+  private static void assertInvalid(int... bytesAsInt) { //invalid byte sequences
+    byte[] bytes = new byte[bytesAsInt.length];
+    for (int i = 0; i < bytesAsInt.length; i++) {
+      bytes[i] = (byte) bytesAsInt[i];
+    }
+    assertInvalid(bytes);
+  }
+
+  private static void assertInvalid(byte[] bytes) {
+    int bytesLen = bytes.length;
+    try {
+      Memory.wrap(bytes).getCharsFromUtf8(0, bytesLen, new StringBuilder());
+      fail();
+    } catch (Utf8CodingException e) {
+      // Expected.
+    }
+    try {
+      CharBuffer cb = CharBuffer.allocate(bytesLen);
+      Memory.wrap(bytes).getCharsFromUtf8(0, bytesLen, cb);
+      fail();
+    } catch (Utf8CodingException | IOException e) {
+      // Expected.
+    }
+  }
+
+  private static void assertInvalidSlice(byte[] bytes, int index, int size) {
+    try {
+      Memory mem = Memory.wrap(bytes);
+      mem.getCharsFromUtf8(index, size, new StringBuilder());
+      fail();
+    } catch (IllegalArgumentException e) { //Pure bounds violation
+      // Expected.
+    }
+  }
+
+  /**
+   * Performs round-trip test using the given reference string
+   * @param refStr the reference string
+   * @throws IOException
+   */
+  private static void assertRoundTrips(String refStr) throws IOException {
+    assertRoundTrips(refStr, refStr.toCharArray().length, 0, -1);
+  }
+
+  /**
+   * Performs round-trip test using the given reference string
+   * @param refStr the reference string
+   * @param refSubCharLen the number of characters expected to be decoded
+   * @param offsetBytes starting utf8 byte offset
+   * @param utf8LengthBytes length of utf8 bytes
+   * @throws IOException
+   */
+  private static void assertRoundTrips(String refStr, int refSubCharLen, int offsetBytes,
+      int utf8LengthBytes) throws IOException {
+    byte[] refByteArr = refStr.getBytes(UTF_8);
+    if (utf8LengthBytes == -1) {
+      utf8LengthBytes = refByteArr.length;
+    }
+    Memory refMem = Memory.wrap(refByteArr);
+
+    byte[] refByteArr2 = new byte[refByteArr.length + 1];
+    System.arraycopy(refByteArr, 0, refByteArr2, 1, refByteArr.length);
+    Memory refReg = Memory.wrap(refByteArr2).region(1, refByteArr.length);
+
+    WritableMemory dstMem = WritableMemory.allocate(refByteArr.length);
+    WritableMemory dstMem2 =
+            WritableMemory.allocate(refByteArr.length + 1).writableRegion(1, refByteArr.length);
+
+    // Test with Memory objects, where base offset != 0
+    assertRoundTrips(refStr, refSubCharLen, offsetBytes, utf8LengthBytes, refByteArr, refMem, dstMem);
+    assertRoundTrips(refStr, refSubCharLen, offsetBytes, utf8LengthBytes, refByteArr, refMem, dstMem2);
+    assertRoundTrips(refStr, refSubCharLen, offsetBytes, utf8LengthBytes, refByteArr, refReg, dstMem);
+    assertRoundTrips(refStr, refSubCharLen, offsetBytes, utf8LengthBytes, refByteArr, refReg, dstMem2);
+  }
+
+  private static void assertRoundTrips(String refStr, int refSubCharLen, int offsetBytes,
+      int utf8LengthBytes, byte[] refByteArr, Memory refMem, WritableMemory dstMem)
+          throws IOException {
+    StringBuilder sb = new StringBuilder();
+
+    int charPos = refMem.getCharsFromUtf8(offsetBytes, utf8LengthBytes, sb);
+    checkStrings(sb.toString(), new String(refByteArr, offsetBytes, utf8LengthBytes, UTF_8));
+    assertEquals(charPos, refSubCharLen);
+
+    CharBuffer cb = CharBuffer.allocate(refByteArr.length + 1);
+    cb.position(1);
+    // Make CharBuffer 1-based, to check correct offset handling
+    cb = cb.slice();
+    refMem.getCharsFromUtf8(offsetBytes, utf8LengthBytes, cb);
+    cb.flip();
+    checkStrings(cb.toString(), new String(refByteArr, offsetBytes, utf8LengthBytes, UTF_8));
+
+    long encodedUtf8Bytes = dstMem.putCharsToUtf8(0, refStr); //encodes entire refStr
+    assertEquals(encodedUtf8Bytes, refByteArr.length); //compares bytes length
+    //compare the actual bytes encoded
+    assertEquals(0, dstMem.compareTo(0, refByteArr.length, refMem, 0, refByteArr.length));
+
+    // Test write overflow
+    WritableMemory writeMem2 = WritableMemory.allocate(refByteArr.length - 1);
+    try {
+      writeMem2.putCharsToUtf8(0, refStr);
+      fail();
+    } catch (Utf8CodingException e) {
+      // Expected.
+    }
+  }
+
+  private static boolean isSurrogateCodePoint(final int cp) {
+    return (cp >= Character.MIN_SURROGATE) && (cp <= Character.MAX_SURROGATE);
+  }
+
+  private static void checkStrings(String actual, String expected) {
+    if (!expected.equals(actual)) {
+      fail("Failure: Expected (" + codepoints(expected) + ") Actual (" + codepoints(actual) + ")");
+    }
+  }
+
+  private static List<String> codepoints(String str) {
+    List<String> codepoints = new ArrayList<>();
+    for (int i = 0; i < str.length(); i++) {
+      codepoints.add(Long.toHexString(str.charAt(i)));
+    }
+    return codepoints;
+  }
+
+  @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
+  }
+}

Added: dev/datasketches/memory/2.0.0-RC1/apache-datasketches-memory-2.0.0-src/datasketches-memory-java8-tests/src/test/java/org/apache/datasketches/memory/test/UtilTest.java
==============================================================================
--- dev/datasketches/memory/2.0.0-RC1/apache-datasketches-memory-2.0.0-src/datasketches-memory-java8-tests/src/test/java/org/apache/datasketches/memory/test/UtilTest.java (added)
+++ dev/datasketches/memory/2.0.0-RC1/apache-datasketches-memory-2.0.0-src/datasketches-memory-java8-tests/src/test/java/org/apache/datasketches/memory/test/UtilTest.java Thu Aug 19 22:18:24 2021
@@ -0,0 +1,207 @@
+/*
+ * 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.characterPad;
+import static org.apache.datasketches.memory.internal.Util.getResourceBytes;
+import static org.apache.datasketches.memory.internal.Util.getResourceFile;
+import static org.apache.datasketches.memory.internal.Util.negativeCheck;
+import static org.apache.datasketches.memory.internal.Util.nullCheck;
+import static org.apache.datasketches.memory.internal.Util.zeroCheck;
+import static org.apache.datasketches.memory.internal.Util.zeroPad;
+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.IOException;
+import java.nio.file.Files;
+import java.nio.file.LinkOption;
+import java.nio.file.attribute.PosixFileAttributeView;
+import java.nio.file.attribute.PosixFileAttributes;
+import java.nio.file.attribute.PosixFilePermissions;
+
+import org.apache.datasketches.memory.internal.UnsafeUtil;
+import org.apache.datasketches.memory.internal.Util;
+import org.apache.datasketches.memory.WritableMemory;
+import org.testng.annotations.Test;
+
+@SuppressWarnings("javadoc")
+public class UtilTest {
+  private static final String LS = System.getProperty("line.separator");
+
+  //Binary Search
+  @Test
+  public void checkBinarySearch() {
+    int k = 1024; //longs
+    WritableMemory wMem = WritableMemory.allocate(k << 3); //1024 longs
+    for (int i = 0; i < k; i++) { wMem.putLong(i << 3, i); }
+    long idx = Util.binarySearchLongs(wMem, 0, k - 1, k / 2);
+    long val = wMem.getLong(idx << 3);
+    assertEquals(idx, k/2);
+    assertEquals(val, k/2);
+
+    idx = Util.binarySearchLongs(wMem, 0, k - 1, k);
+    assertEquals(idx, -1024);
+  }
+
+  @Test(expectedExceptions = IllegalArgumentException.class)
+  public void checkBoundsTest() {
+    UnsafeUtil.checkBounds(999, 2, 1000);
+  }
+
+  @Test
+  public void checkPadding() {
+    String s = "123";
+    String t = zeroPad(s, 4);
+    assertTrue(t.startsWith("0"));
+
+    t = characterPad(s, 4, '0', true);
+    assertTrue(t.endsWith("0"));
+
+    t = characterPad(s, 3, '0', false);
+    assertEquals(s, t);
+  }
+
+  @Test
+  public void checkNullZeroNegativeChecks() {
+    Object obj = null;
+    try {
+      nullCheck(obj, "Test Object");
+      fail();
+    } catch (IllegalArgumentException e) {
+      //OK
+    }
+    try {
+      zeroCheck(0, "Test Long");
+      fail();
+    } catch (IllegalArgumentException e) {
+      //OK
+    }
+    try {
+      negativeCheck(-1L, "Test Long");
+      fail();
+    } catch (IllegalArgumentException e) {
+      //OK
+    }
+  }
+
+  @Test
+  public void checkCodePointArr() {
+    final Util.RandomCodePoints rvcp = new Util.RandomCodePoints(true);
+    final int n = 1000;
+    final int[] cpArr = new int[n];
+    rvcp.fillCodePointArray(cpArr);
+    for (int i = 0; i < n; i++) {
+      int cp = cpArr[i];
+      if ((cp >= Character.MIN_SURROGATE) && (cp <= Character.MAX_SURROGATE)) {
+        fail();
+      }
+    }
+  }
+
+  @Test
+  public void checkCodePoint() {
+    final Util.RandomCodePoints rvcp = new Util.RandomCodePoints(true);
+    final int n = 1000;
+    for (int i = 0; i < n; i++) {
+      int cp = rvcp.getCodePoint();
+      if ((cp >= Character.MIN_SURROGATE) && (cp <= Character.MAX_SURROGATE)) {
+        fail();
+      }
+    }
+  }
+
+  static final String getFileAttributes(File file) {
+    try {
+    PosixFileAttributes attrs = Files.getFileAttributeView(
+        file.toPath(), PosixFileAttributeView.class, new LinkOption[0]).readAttributes();
+    String s = String.format("%s: %s %s %s%n",
+        file.getPath(),
+        attrs.owner().getName(),
+        attrs.group().getName(),
+        PosixFilePermissions.toString(attrs.permissions()));
+    return s;
+    } catch (IOException e) {
+      throw new RuntimeException(e);
+    }
+  }
+
+  static final void setGettysburgAddressFileToReadOnly() {
+    File file = getResourceFile("GettysburgAddress.txt");
+    try {
+    Files.setPosixFilePermissions(file.toPath(), PosixFilePermissions.fromString("r--r--r--"));
+    } catch (IOException e) {
+      throw new RuntimeException(e);
+    }
+  }
+
+  //Resources
+
+  @Test
+  public void resourceFileExits() {
+    final String shortFileName = "GettysburgAddress.txt";
+    final File file = getResourceFile(shortFileName);
+    assertTrue(file.exists());
+  }
+
+  @Test(expectedExceptions = IllegalArgumentException.class)
+  public void resourceFileNotFound() {
+    final String shortFileName = "GettysburgAddress.txt";
+    getResourceFile(shortFileName + "123");
+  }
+
+  @Test
+  public void resourceBytesCorrect() {
+    final String shortFileName = "GettysburgAddress.txt";
+    final byte[] bytes = getResourceBytes(shortFileName);
+    assertTrue(bytes.length == 1541);
+  }
+
+  @Test(expectedExceptions = IllegalArgumentException.class)
+  public void resourceBytesFileNotFound() {
+    final String shortFileName = "GettysburgAddress.txt";
+    getResourceBytes(shortFileName + "123");
+  }
+
+  @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
+    }
+  }
+
+}

Added: dev/datasketches/memory/2.0.0-RC1/apache-datasketches-memory-2.0.0-src/datasketches-memory-java8-tests/src/test/java/org/apache/datasketches/memory/test/VirtualMachineMemoryTest.java
==============================================================================
--- dev/datasketches/memory/2.0.0-RC1/apache-datasketches-memory-2.0.0-src/datasketches-memory-java8-tests/src/test/java/org/apache/datasketches/memory/test/VirtualMachineMemoryTest.java (added)
+++ dev/datasketches/memory/2.0.0-RC1/apache-datasketches-memory-2.0.0-src/datasketches-memory-java8-tests/src/test/java/org/apache/datasketches/memory/test/VirtualMachineMemoryTest.java Thu Aug 19 22:18:24 2021
@@ -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.test;
+
+import org.apache.datasketches.memory.internal.VirtualMachineMemory;
+import org.testng.annotations.Test;
+
+@SuppressWarnings({"javadoc","unused"})
+public class VirtualMachineMemoryTest {
+
+    @Test
+    public void maxDirectBufferMemory() {
+       assert(VirtualMachineMemory.getMaxDBBMemory() >= 0);
+    }
+
+    @Test
+    public void inertPageAlignment() {
+      boolean result = VirtualMachineMemory.getIsPageAligned();
+      //System.out.println("VM page alignment:" + result);
+      assert(true); //no exception was thrown
+    }
+}

Added: dev/datasketches/memory/2.0.0-RC1/apache-datasketches-memory-2.0.0-src/datasketches-memory-java8-tests/src/test/java/org/apache/datasketches/memory/test/WritableDirectCopyTest.java
==============================================================================
--- dev/datasketches/memory/2.0.0-RC1/apache-datasketches-memory-2.0.0-src/datasketches-memory-java8-tests/src/test/java/org/apache/datasketches/memory/test/WritableDirectCopyTest.java (added)
+++ dev/datasketches/memory/2.0.0-RC1/apache-datasketches-memory-2.0.0-src/datasketches-memory-java8-tests/src/test/java/org/apache/datasketches/memory/test/WritableDirectCopyTest.java Thu Aug 19 22:18:24 2021
@@ -0,0 +1,254 @@
+/*
+ * 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.test;
+
+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
+ */
+@SuppressWarnings("javadoc")
+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
+  }
+
+}



---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@datasketches.apache.org
For additional commands, e-mail: commits-help@datasketches.apache.org