// Path: src/main/java/org/lmdbjava/BufferProxy.java
// protected static final int MDB_VAL_STRUCT_SIZE = BYTES * 2;
// 
// Path: src/main/java/org/lmdbjava/ByteBufferProxy.java
// static Field findField(final Class<?> c, final String name) {
//   Class<?> clazz = c;
//   do {
//     try {
//       final Field field = clazz.getDeclaredField(name);
//       field.setAccessible(true);
//       return field;
//     } catch (final NoSuchFieldException e) {
//       clazz = clazz.getSuperclass();
//     }
//   } while (clazz != null);
//   throw new LmdbException(name + " not found");
// }
// 
// Path: src/main/java/org/lmdbjava/ByteBufferProxy.java
// public static final BufferProxy<ByteBuffer> PROXY_OPTIMAL;
// 
// Path: src/main/java/org/lmdbjava/ByteBufferProxy.java
// public static final BufferProxy<ByteBuffer> PROXY_SAFE;
// 
// Path: src/main/java/org/lmdbjava/Env.java
// public static Builder<ByteBuffer> create() {
//   return new Builder<>(PROXY_OPTIMAL);
// }
// 
// Path: src/main/java/org/lmdbjava/Library.java
// static final jnr.ffi.Runtime RUNTIME;
// 
// Path: src/test/java/org/lmdbjava/TestUtils.java
// public static final String DB_1 = "test-db-1";
// 
// Path: src/test/java/org/lmdbjava/TestUtils.java
// static void invokePrivateConstructor(final Class<?> clazz) {
//   try {
//     final Constructor<?> c = clazz.getDeclaredConstructor();
//     c.setAccessible(true);
//     c.newInstance();
//   } catch (final NoSuchMethodException | InstantiationException
//                      | IllegalAccessException | IllegalArgumentException
//                      | InvocationTargetException e) {
//     throw new LmdbException("Private construction failed", e);
//   }
// }
// 
// Path: src/main/java/org/lmdbjava/UnsafeAccess.java
// public static final boolean ALLOW_UNSAFE = !getBoolean(DISABLE_UNSAFE_PROP);
// 
// Path: src/main/java/org/lmdbjava/ByteBufferProxy.java
// public static final class BufferMustBeDirectException extends LmdbException {
// 
//   private static final long serialVersionUID = 1L;
// 
//   /**
//    * Creates a new instance.
//    */
//   public BufferMustBeDirectException() {
//     super("The buffer must be a direct buffer (not heap allocated");
//   }
// }
// 
// Path: src/main/java/org/lmdbjava/Env.java
// public static final class ReadersFullException extends LmdbNativeException {
// 
//   static final int MDB_READERS_FULL = -30_790;
//   private static final long serialVersionUID = 1L;
// 
//   ReadersFullException() {
//     super(MDB_READERS_FULL, "Environment maxreaders reached");
//   }
// }


import static java.lang.Integer.BYTES;
import static java.nio.ByteBuffer.allocate;
import static java.nio.ByteBuffer.allocateDirect;
import static java.nio.ByteOrder.BIG_ENDIAN;
import static java.nio.ByteOrder.LITTLE_ENDIAN;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.CoreMatchers.not;
import static org.hamcrest.CoreMatchers.notNullValue;
import static org.hamcrest.CoreMatchers.startsWith;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.lmdbjava.BufferProxy.MDB_VAL_STRUCT_SIZE;
import static org.lmdbjava.ByteBufferProxy.AbstractByteBufferProxy.findField;
import static org.lmdbjava.ByteBufferProxy.PROXY_OPTIMAL;
import static org.lmdbjava.ByteBufferProxy.PROXY_SAFE;
import static org.lmdbjava.DbiFlags.MDB_CREATE;
import static org.lmdbjava.Env.create;
import static org.lmdbjava.Library.RUNTIME;
import static org.lmdbjava.TestUtils.DB_1;
import static org.lmdbjava.TestUtils.invokePrivateConstructor;
import static org.lmdbjava.UnsafeAccess.ALLOW_UNSAFE;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.Field;
import java.nio.ByteBuffer;
import jnr.ffi.Pointer;
import jnr.ffi.provider.MemoryManager;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
import org.lmdbjava.ByteBufferProxy.BufferMustBeDirectException;
import org.lmdbjava.Env.ReadersFullException;

  @Test
  public void inOutBuffersProxySafe() {
    checkInOut(PROXY_SAFE);
  }

  @Test
  public void optimalAlwaysAvailable() {
    final BufferProxy<ByteBuffer> v = PROXY_OPTIMAL;
    assertThat(v, is(notNullValue()));
  }

  @Test
  public void safeCanBeForced() {
    final BufferProxy<ByteBuffer> v = PROXY_SAFE;
    assertThat(v, is(notNullValue()));
    assertThat(v.getClass().getSimpleName(), startsWith("Reflect"));
  }

  @Test
  public void unsafeIsDefault() {
    assertThat(ALLOW_UNSAFE, is(true));
    final BufferProxy<ByteBuffer> v = PROXY_OPTIMAL;
    assertThat(v, is(notNullValue()));
    assertThat(v, is(not(PROXY_SAFE)));
    assertThat(v.getClass().getSimpleName(), startsWith("Unsafe"));
  }

  private void checkInOut(final BufferProxy<ByteBuffer> v) {
    // allocate a buffer larger than max key size
// Path: src/main/java/org/lmdbjava/BufferProxy.java
// protected static final int MDB_VAL_STRUCT_SIZE = BYTES * 2;
// 
// Path: src/main/java/org/lmdbjava/ByteBufferProxy.java
// static Field findField(final Class<?> c, final String name) {
//   Class<?> clazz = c;
//   do {
//     try {
//       final Field field = clazz.getDeclaredField(name);
//       field.setAccessible(true);
//       return field;
//     } catch (final NoSuchFieldException e) {
//       clazz = clazz.getSuperclass();
//     }
//   } while (clazz != null);
//   throw new LmdbException(name + " not found");
// }
// 
// Path: src/main/java/org/lmdbjava/ByteBufferProxy.java
// public static final BufferProxy<ByteBuffer> PROXY_OPTIMAL;
// 
// Path: src/main/java/org/lmdbjava/ByteBufferProxy.java
// public static final BufferProxy<ByteBuffer> PROXY_SAFE;
// 
// Path: src/main/java/org/lmdbjava/Env.java
// public static Builder<ByteBuffer> create() {
//   return new Builder<>(PROXY_OPTIMAL);
// }
// 
// Path: src/main/java/org/lmdbjava/Library.java
// static final jnr.ffi.Runtime RUNTIME;
// 
// Path: src/test/java/org/lmdbjava/TestUtils.java
// public static final String DB_1 = "test-db-1";
// 
// Path: src/test/java/org/lmdbjava/TestUtils.java
// static void invokePrivateConstructor(final Class<?> clazz) {
//   try {
//     final Constructor<?> c = clazz.getDeclaredConstructor();
//     c.setAccessible(true);
//     c.newInstance();
//   } catch (final NoSuchMethodException | InstantiationException
//                      | IllegalAccessException | IllegalArgumentException
//                      | InvocationTargetException e) {
//     throw new LmdbException("Private construction failed", e);
//   }
// }
// 
// Path: src/main/java/org/lmdbjava/UnsafeAccess.java
// public static final boolean ALLOW_UNSAFE = !getBoolean(DISABLE_UNSAFE_PROP);
// 
// Path: src/main/java/org/lmdbjava/ByteBufferProxy.java
// public static final class BufferMustBeDirectException extends LmdbException {
// 
//   private static final long serialVersionUID = 1L;
// 
//   /**
//    * Creates a new instance.
//    */
//   public BufferMustBeDirectException() {
//     super("The buffer must be a direct buffer (not heap allocated");
//   }
// }
// 
// Path: src/main/java/org/lmdbjava/Env.java
// public static final class ReadersFullException extends LmdbNativeException {
// 
//   static final int MDB_READERS_FULL = -30_790;
//   private static final long serialVersionUID = 1L;
// 
//   ReadersFullException() {
//     super(MDB_READERS_FULL, "Environment maxreaders reached");
//   }
// }


// Path: src/test/java/org/lmdbjava/ByteBufferProxyTest.java
import static java.lang.Integer.BYTES;
import static java.nio.ByteBuffer.allocate;
import static java.nio.ByteBuffer.allocateDirect;
import static java.nio.ByteOrder.BIG_ENDIAN;
import static java.nio.ByteOrder.LITTLE_ENDIAN;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.CoreMatchers.not;
import static org.hamcrest.CoreMatchers.notNullValue;
import static org.hamcrest.CoreMatchers.startsWith;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.lmdbjava.BufferProxy.MDB_VAL_STRUCT_SIZE;
import static org.lmdbjava.ByteBufferProxy.AbstractByteBufferProxy.findField;
import static org.lmdbjava.ByteBufferProxy.PROXY_OPTIMAL;
import static org.lmdbjava.ByteBufferProxy.PROXY_SAFE;
import static org.lmdbjava.DbiFlags.MDB_CREATE;
import static org.lmdbjava.Env.create;
import static org.lmdbjava.Library.RUNTIME;
import static org.lmdbjava.TestUtils.DB_1;
import static org.lmdbjava.TestUtils.invokePrivateConstructor;
import static org.lmdbjava.UnsafeAccess.ALLOW_UNSAFE;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.Field;
import java.nio.ByteBuffer;
import jnr.ffi.Pointer;
import jnr.ffi.provider.MemoryManager;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
import org.lmdbjava.ByteBufferProxy.BufferMustBeDirectException;
import org.lmdbjava.Env.ReadersFullException;


  @Test
  public void inOutBuffersProxySafe() {
    checkInOut(PROXY_SAFE);
  }

  @Test
  public void optimalAlwaysAvailable() {
    final BufferProxy<ByteBuffer> v = PROXY_OPTIMAL;
    assertThat(v, is(notNullValue()));
  }

  @Test
  public void safeCanBeForced() {
    final BufferProxy<ByteBuffer> v = PROXY_SAFE;
    assertThat(v, is(notNullValue()));
    assertThat(v.getClass().getSimpleName(), startsWith("Reflect"));
  }

  @Test
  public void unsafeIsDefault() {
    assertThat(ALLOW_UNSAFE, is(true));
    final BufferProxy<ByteBuffer> v = PROXY_OPTIMAL;
    assertThat(v, is(notNullValue()));
    assertThat(v, is(not(PROXY_SAFE)));
    assertThat(v.getClass().getSimpleName(), startsWith("Unsafe"));
  }

  private void checkInOut(final BufferProxy<ByteBuffer> v) {
    // allocate a buffer larger than max key size
    final ByteBuffer b = allocateDirect(1_000);