code: /*
   * Licensed to the Apache Software Foundation (ASF) under one
   * or more contributor license agreements.  See the NOTICE file
   * distributed with this work for additional information
   * regarding copyright ownership.  The ASF licenses this file
   * to you under the Apache License, Version 2.0 (the
   * "License"); you may not use this file except in compliance
   * with the License.  You may obtain a copy of the License at
   *
   *   http://www.apache.org/licenses/LICENSE-2.0
   *
   * Unless required by applicable law or agreed to in writing,
   * software distributed under the License is distributed on an
   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
   * KIND, either express or implied.  See the License for the
   * specific language governing permissions and limitations
   * under the License.
   */
  
  package org.apache.datasketches.memory.internal;
  
  import static org.testng.Assert.assertEquals;
  import static org.testng.Assert.fail;
  
  import java.nio.ByteBuffer;
  
  import org.apache.datasketches.memory.Buffer;
  import org.apache.datasketches.memory.BufferPositionInvariantsException;
  import org.apache.datasketches.memory.WritableBuffer;
  import org.apache.datasketches.memory.WritableMemory;
  import org.testng.annotations.Test;
  
  /**
   * @author Lee Rhodes
   */
  public class BufferInvariantsTest {
  
    @Test
    public void testRegion() {
      ByteBuffer byteBuffer = ByteBuffer.allocate(10);
      byteBuffer.limit(7);
      Buffer buff = Buffer.wrap(byteBuffer); //assuming buff has cap of 8
      assertEquals(buff.getCapacity(), 10); //wrong should be 8
      buff.getByte(); //pos moves to 1
      Buffer copyBuff = buff.region(); //pos: 0, start: 0, end: 6: cap: 7
      assertEquals(copyBuff.getEnd(), 6);
      assertEquals(copyBuff.getCapacity(), 6);
      assertEquals(copyBuff.getStart(), 0);
      assertEquals(copyBuff.getPosition(), 0);
  
      buff.setStartPositionEnd(1, 1, 5);
      buff.getByte();
      Buffer copyBuff2 = buff.region();
      assertEquals(copyBuff2.getEnd(), 3);
      assertEquals(copyBuff2.getCapacity(), 3);
      assertEquals(copyBuff2.getStart(), 0);
      assertEquals(copyBuff2.getPosition(), 0);
    }
  
    @Test
    public void testBB() {
      int n = 25;
      ByteBuffer bb = ByteBuffer.allocate(n);
      for (byte i = 0; i < n; i++) { bb.put(i, i); }
      assertEquals(bb.position(), 0);
      assertEquals(bb.limit(), n);
      assertEquals(bb.get(0), 0);
  //    print("Orig : ");
  //    printbb(bb);
  
      bb.limit(20);
      bb.position(5);
      assertEquals(bb.remaining(), 15);
  //    print("Set  : ");
  //    printbb(bb);
  
      ByteBuffer dup = bb.duplicate();
      assertEquals(dup.position(), 5);
      assertEquals(dup.limit(), 20);
      assertEquals(dup.capacity(), 25);
  //    print("Dup  : ");
  //    printbb(dup);
  
      ByteBuffer sl = bb.slice();
      assertEquals(sl.position(), 0);
      assertEquals(sl.limit(), 15);
      assertEquals(sl.capacity(), 15);
  //    print("Slice: ");
  //    printbb(sl);
    }
  
    @Test
    public void testBuf() {
      int n = 25;
      WritableBuffer buf = WritableMemory.allocate(n).asWritableBuffer();
      for (byte i = 0; i < n; i++) { buf.putByte(i); }
      buf.setPosition(0);
      assertEquals(buf.getPosition(), 0);
      assertEquals(buf.getEnd(), 25);
      assertEquals(buf.getCapacity(), 25);
  //    print("Orig  : ");
  //    printbuf(buf);
  
      buf.setStartPositionEnd(0, 5, 20);
      assertEquals(buf.getRemaining(), 15);
      assertEquals(buf.getCapacity(), 25);
      assertEquals(buf.getByte(), 5);
      buf.setPosition(5);
  //    print("Set   : ");
  //    printbuf(buf);
  
      Buffer dup = buf.duplicate();
      assertEquals(dup.getRemaining(), 15);
      assertEquals(dup.getCapacity(), 25);
      assertEquals(dup.getByte(), 5);
      dup.setPosition(5);
  //    print("Dup   : ");
  //    printbuf(dup);
  
  
      Buffer reg = buf.region();
      assertEquals(reg.getPosition(), 0);
      assertEquals(reg.getEnd(), 15);
      assertEquals(reg.getRemaining(), 15);
      assertEquals(reg.getCapacity(), 15);
      assertEquals(reg.getByte(), 5);
      reg.setPosition(0);
  //    print("Region: ");
  //    printbuf(reg);
    }
  
    @Test
    public void testBufWrap() {
      int n = 25;
      ByteBuffer bb = ByteBuffer.allocate(n);
      for (byte i = 0; i < n; i++) { bb.put(i, i); }
  
      bb.position(5);
      bb.limit(20);
  
      Buffer buf = Buffer.wrap(bb);
      assertEquals(buf.getPosition(), 5);
      assertEquals(buf.getEnd(), 20);
      assertEquals(buf.getRemaining(), 15);
      assertEquals(buf.getCapacity(), 25);
      assertEquals(buf.getByte(), 5);
      buf.setPosition(5);
  //    print("Buf.wrap: ");
  //    printbuf(buf);
  
      Buffer reg = buf.region();
      assertEquals(reg.getPosition(), 0);
      assertEquals(reg.getEnd(), 15);
      assertEquals(reg.getRemaining(), 15);
      assertEquals(reg.getCapacity(), 15);
      assertEquals(reg.getByte(), 5);
      reg.setPosition(0);
  //    print("Buf.region: ");
  //    printbuf(reg);
    }
  
    @Test
    public void checkLimitsDirect() throws Exception {
      try (WritableMemory wmem = WritableMemory.allocateDirect(100)) {
        Buffer buf = wmem.asBuffer();
        buf.setStartPositionEnd(40, 45, 50);
        buf.setStartPositionEnd(0, 0, 100);
        try {
          buf.setStartPositionEnd(0, 0, 101);
          fail();
        } catch (BufferPositionInvariantsException e) {
          //ok
        }
      }
    }
  
    @Test
    public void testRegionDirect() {
      ByteBuffer byteBuffer = ByteBuffer.allocate(10);
      byteBuffer.limit(7);
      Buffer buff = Buffer.wrap(byteBuffer); //assuming buff has cap of 8
      assertEquals(buff.getCapacity(), 10); //wrong should be 8
      buff.getByte(); //pos moves to 1
      Buffer copyBuff = buff.region(); //pos: 0, start: 0, end: 6: cap: 7
      assertEquals(copyBuff.getEnd(), 6);
      assertEquals(copyBuff.getCapacity(), 6);
      assertEquals(copyBuff.getStart(), 0);
      assertEquals(copyBuff.getPosition(), 0);
  
      buff.setStartPositionEnd(1, 1, 5);
      buff.getByte();
      Buffer copyBuff2 = buff.region();
      assertEquals(copyBuff2.getEnd(), 3);
      assertEquals(copyBuff2.getCapacity(), 3);
      assertEquals(copyBuff2.getStart(), 0);
      assertEquals(copyBuff2.getPosition(), 0);
    }
  
    @Test
    public void testBBDirect() {
      int n = 25;
      ByteBuffer bb = ByteBuffer.allocateDirect(n);
      for (byte i = 0; i < n; i++) { bb.put(i, i); }
      assertEquals(bb.position(), 0);
      assertEquals(bb.limit(), n);
      assertEquals(bb.get(0), 0);
  //    print("Orig : ");
  //    printbb(bb);
  
      bb.limit(20);
      bb.position(5);
      assertEquals(bb.remaining(), 15);
  //    print("Set  : ");
  //    printbb(bb);
  
      ByteBuffer dup = bb.duplicate();
      assertEquals(dup.position(), 5);
      assertEquals(dup.limit(), 20);
      assertEquals(dup.capacity(), 25);
  //    print("Dup  : ");
  //    printbb(dup);
  
      ByteBuffer sl = bb.slice();
      assertEquals(sl.position(), 0);
      assertEquals(sl.limit(), 15);
      assertEquals(sl.capacity(), 15);
  //    print("Slice: ");
  //    printbb(sl);
    }
  
    @Test
    public void testBufDirect() throws Exception {
      int n = 25;
      try (WritableMemory wmem = WritableMemory.allocateDirect(n)) {
      WritableBuffer buf = wmem.asWritableBuffer();
      for (byte i = 0; i < n; i++) { buf.putByte(i); }
      buf.setPosition(0);
      assertEquals(buf.getPosition(), 0);
      assertEquals(buf.getEnd(), 25);
      assertEquals(buf.getCapacity(), 25);
  //    print("Orig  : ");
  //    printbuf(buf);
  
      buf.setStartPositionEnd(0, 5, 20);
      assertEquals(buf.getRemaining(), 15);
      assertEquals(buf.getCapacity(), 25);
      assertEquals(buf.getByte(), 5);
      buf.setPosition(5);
  //    print("Set   : ");
  //    printbuf(buf);
  
      Buffer dup = buf.duplicate();
      assertEquals(dup.getRemaining(), 15);
      assertEquals(dup.getCapacity(), 25);
      assertEquals(dup.getByte(), 5);
      dup.setPosition(5);
  //    print("Dup   : ");
  //    printbuf(dup);
  
  
      Buffer reg = buf.region();
      assertEquals(reg.getPosition(), 0);
      assertEquals(reg.getEnd(), 15);
      assertEquals(reg.getRemaining(), 15);
      assertEquals(reg.getCapacity(), 15);
      assertEquals(reg.getByte(), 5);
      reg.setPosition(0);
  //    print("Region: ");
  //    printbuf(reg);
      }
    }
  
    @Test
    public void testBufWrapDirect() {
      int n = 25;
      ByteBuffer bb = ByteBuffer.allocateDirect(n);
      for (byte i = 0; i < n; i++) { bb.put(i, i); }
  
      bb.position(5);
      bb.limit(20);
  
      Buffer buf = Buffer.wrap(bb);
      assertEquals(buf.getPosition(), 5);
      assertEquals(buf.getEnd(), 20);
      assertEquals(buf.getRemaining(), 15);
      assertEquals(buf.getCapacity(), 25);
      assertEquals(buf.getByte(), 5);
      buf.setPosition(5);
  //    print("Buf.wrap: ");
  //    printbuf(buf);
  
      Buffer reg = buf.region();
      assertEquals(reg.getPosition(), 0);
      assertEquals(reg.getEnd(), 15);
      assertEquals(reg.getRemaining(), 15);
      assertEquals(reg.getCapacity(), 15);
      assertEquals(reg.getByte(), 5);
      reg.setPosition(0);
  //    print("Buf.region: ");
  //    printbuf(reg);
    }
  
    static void printbb(ByteBuffer bb) {
      println("pos: " + bb.position() + ", lim: " + bb.limit() + ", cap: " + bb.capacity());
      int rem = bb.remaining();
      int pos = bb.position();
      int i;
      for (i = 0; i < (rem - 1); i++) {
        print(bb.get(i + pos) + ", ");
      }
      println(bb.get(i + pos) + "\n");
    }
  
    static void printbuf(Buffer buf) {
      println("pos: " + buf.getPosition() + ", end: " + buf.getEnd() + ", cap: " + buf.getCapacity());
      long rem = buf.getRemaining();
      long pos = buf.getPosition();
      int i;
      for (i = 0; i < (rem - 1); i++) {
        print(buf.getByte(i + pos) + ", ");
      }
      println(buf.getByte(i + pos) + "\n");
    }
  
    /**
     * @param s value to print
     */
    static void println(String s) {
      //System.out.println(s); //disable here
    }
  
    /**
     * @param s value to print
     */
    static void print(String s) {
      //System.out.print(s); //disable here
    }
  }
  