static void testArray(Handles hs) throws Throwable {
    int[] array = new int[10];

    for (int i = 0; i < array.length; i++) {
      // Plain
      {
        hs.get(TestAccessMode.SET).invokeExact(array, i, 0x01234567);
        int x = (int) hs.get(TestAccessMode.GET).invokeExact(array, i);
        assertEquals(x, 0x01234567, "get int value");
      }

      // Volatile
      {
        hs.get(TestAccessMode.SET_VOLATILE).invokeExact(array, i, 0x89ABCDEF);
        int x = (int) hs.get(TestAccessMode.GET_VOLATILE).invokeExact(array, i);
        assertEquals(x, 0x89ABCDEF, "setVolatile int value");
      }

      // Lazy
      {
        hs.get(TestAccessMode.SET_RELEASE).invokeExact(array, i, 0x01234567);
        int x = (int) hs.get(TestAccessMode.GET_ACQUIRE).invokeExact(array, i);
        assertEquals(x, 0x01234567, "setRelease int value");
      }

      // Opaque
      {
        hs.get(TestAccessMode.SET_OPAQUE).invokeExact(array, i, 0x89ABCDEF);
        int x = (int) hs.get(TestAccessMode.GET_OPAQUE).invokeExact(array, i);
        assertEquals(x, 0x89ABCDEF, "setOpaque int value");
      }

      hs.get(TestAccessMode.SET).invokeExact(array, i, 0x01234567);

      // Compare
      {
        boolean r =
            (boolean)
                hs.get(TestAccessMode.COMPARE_AND_SET)
                    .invokeExact(array, i, 0x01234567, 0x89ABCDEF);
        assertEquals(r, true, "success compareAndSet int");
        int x = (int) hs.get(TestAccessMode.GET).invokeExact(array, i);
        assertEquals(x, 0x89ABCDEF, "success compareAndSet int value");
      }

      {
        boolean r =
            (boolean)
                hs.get(TestAccessMode.COMPARE_AND_SET)
                    .invokeExact(array, i, 0x01234567, 0xCAFEBABE);
        assertEquals(r, false, "failing compareAndSet int");
        int x = (int) hs.get(TestAccessMode.GET).invokeExact(array, i);
        assertEquals(x, 0x89ABCDEF, "failing compareAndSet int value");
      }

      {
        int r =
            (int)
                hs.get(TestAccessMode.COMPARE_AND_EXCHANGE)
                    .invokeExact(array, i, 0x89ABCDEF, 0x01234567);
        assertEquals(r, 0x89ABCDEF, "success compareAndExchange int");
        int x = (int) hs.get(TestAccessMode.GET).invokeExact(array, i);
        assertEquals(x, 0x01234567, "success compareAndExchange int value");
      }

      {
        int r =
            (int)
                hs.get(TestAccessMode.COMPARE_AND_EXCHANGE)
                    .invokeExact(array, i, 0x89ABCDEF, 0xCAFEBABE);
        assertEquals(r, 0x01234567, "failing compareAndExchange int");
        int x = (int) hs.get(TestAccessMode.GET).invokeExact(array, i);
        assertEquals(x, 0x01234567, "failing compareAndExchange int value");
      }

      {
        int r =
            (int)
                hs.get(TestAccessMode.COMPARE_AND_EXCHANGE_ACQUIRE)
                    .invokeExact(array, i, 0x01234567, 0x89ABCDEF);
        assertEquals(r, 0x01234567, "success compareAndExchangeAcquire int");
        int x = (int) hs.get(TestAccessMode.GET).invokeExact(array, i);
        assertEquals(x, 0x89ABCDEF, "success compareAndExchangeAcquire int value");
      }

      {
        int r =
            (int)
                hs.get(TestAccessMode.COMPARE_AND_EXCHANGE_ACQUIRE)
                    .invokeExact(array, i, 0x01234567, 0xCAFEBABE);
        assertEquals(r, 0x89ABCDEF, "failing compareAndExchangeAcquire int");
        int x = (int) hs.get(TestAccessMode.GET).invokeExact(array, i);
        assertEquals(x, 0x89ABCDEF, "failing compareAndExchangeAcquire int value");
      }

      {
        int r =
            (int)
                hs.get(TestAccessMode.COMPARE_AND_EXCHANGE_RELEASE)
                    .invokeExact(array, i, 0x89ABCDEF, 0x01234567);
        assertEquals(r, 0x89ABCDEF, "success compareAndExchangeRelease int");
        int x = (int) hs.get(TestAccessMode.GET).invokeExact(array, i);
        assertEquals(x, 0x01234567, "success compareAndExchangeRelease int value");
      }

      {
        int r =
            (int)
                hs.get(TestAccessMode.COMPARE_AND_EXCHANGE_RELEASE)
                    .invokeExact(array, i, 0x89ABCDEF, 0xCAFEBABE);
        assertEquals(r, 0x01234567, "failing compareAndExchangeRelease int");
        int x = (int) hs.get(TestAccessMode.GET).invokeExact(array, i);
        assertEquals(x, 0x01234567, "failing compareAndExchangeRelease int value");
      }

      {
        boolean success = false;
        for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
          success =
              (boolean)
                  hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_PLAIN)
                      .invokeExact(array, i, 0x01234567, 0x89ABCDEF);
        }
        assertEquals(success, true, "weakCompareAndSetPlain int");
        int x = (int) hs.get(TestAccessMode.GET).invokeExact(array, i);
        assertEquals(x, 0x89ABCDEF, "weakCompareAndSetPlain int value");
      }

      {
        boolean success = false;
        for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
          success =
              (boolean)
                  hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_ACQUIRE)
                      .invokeExact(array, i, 0x89ABCDEF, 0x01234567);
        }
        assertEquals(success, true, "weakCompareAndSetAcquire int");
        int x = (int) hs.get(TestAccessMode.GET).invokeExact(array, i);
        assertEquals(x, 0x01234567, "weakCompareAndSetAcquire int");
      }

      {
        boolean success = false;
        for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
          success =
              (boolean)
                  hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_RELEASE)
                      .invokeExact(array, i, 0x01234567, 0x89ABCDEF);
        }
        assertEquals(success, true, "weakCompareAndSetRelease int");
        int x = (int) hs.get(TestAccessMode.GET).invokeExact(array, i);
        assertEquals(x, 0x89ABCDEF, "weakCompareAndSetRelease int");
      }

      {
        boolean success = false;
        for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
          success =
              (boolean)
                  hs.get(TestAccessMode.WEAK_COMPARE_AND_SET)
                      .invokeExact(array, i, 0x89ABCDEF, 0x01234567);
        }
        assertEquals(success, true, "weakCompareAndSet int");
        int x = (int) hs.get(TestAccessMode.GET).invokeExact(array, i);
        assertEquals(x, 0x01234567, "weakCompareAndSet int");
      }

      // Compare set and get
      {
        hs.get(TestAccessMode.SET).invokeExact(array, i, 0x01234567);

        int o = (int) hs.get(TestAccessMode.GET_AND_SET).invokeExact(array, i, 0x89ABCDEF);
        assertEquals(o, 0x01234567, "getAndSet int");
        int x = (int) hs.get(TestAccessMode.GET).invokeExact(array, i);
        assertEquals(x, 0x89ABCDEF, "getAndSet int value");
      }

      {
        hs.get(TestAccessMode.SET).invokeExact(array, i, 0x01234567);

        int o = (int) hs.get(TestAccessMode.GET_AND_SET_ACQUIRE).invokeExact(array, i, 0x89ABCDEF);
        assertEquals(o, 0x01234567, "getAndSetAcquire int");
        int x = (int) hs.get(TestAccessMode.GET).invokeExact(array, i);
        assertEquals(x, 0x89ABCDEF, "getAndSetAcquire int value");
      }

      {
        hs.get(TestAccessMode.SET).invokeExact(array, i, 0x01234567);

        int o = (int) hs.get(TestAccessMode.GET_AND_SET_RELEASE).invokeExact(array, i, 0x89ABCDEF);
        assertEquals(o, 0x01234567, "getAndSetRelease int");
        int x = (int) hs.get(TestAccessMode.GET).invokeExact(array, i);
        assertEquals(x, 0x89ABCDEF, "getAndSetRelease int value");
      }

      // get and add, add and get
      {
        hs.get(TestAccessMode.SET).invokeExact(array, i, 0x01234567);

        int o = (int) hs.get(TestAccessMode.GET_AND_ADD).invokeExact(array, i, 0x89ABCDEF);
        assertEquals(o, 0x01234567, "getAndAdd int");
        int x = (int) hs.get(TestAccessMode.GET).invokeExact(array, i);
        assertEquals(x, (int) (0x01234567 + 0x89ABCDEF), "getAndAdd int value");
      }

      {
        hs.get(TestAccessMode.SET).invokeExact(array, i, 0x01234567);

        int o = (int) hs.get(TestAccessMode.GET_AND_ADD_ACQUIRE).invokeExact(array, i, 0x89ABCDEF);
        assertEquals(o, 0x01234567, "getAndAddAcquire int");
        int x = (int) hs.get(TestAccessMode.GET).invokeExact(array, i);
        assertEquals(x, (int) (0x01234567 + 0x89ABCDEF), "getAndAddAcquire int value");
      }

      {
        hs.get(TestAccessMode.SET).invokeExact(array, i, 0x01234567);

        int o = (int) hs.get(TestAccessMode.GET_AND_ADD_RELEASE).invokeExact(array, i, 0x89ABCDEF);
        assertEquals(o, 0x01234567, "getAndAddRelease int");
        int x = (int) hs.get(TestAccessMode.GET).invokeExact(array, i);
        assertEquals(x, (int) (0x01234567 + 0x89ABCDEF), "getAndAddRelease int value");
      }

      // get and bitwise or
      {
        hs.get(TestAccessMode.SET).invokeExact(array, i, 0x01234567);

        int o = (int) hs.get(TestAccessMode.GET_AND_BITWISE_OR).invokeExact(array, i, 0x89ABCDEF);
        assertEquals(o, 0x01234567, "getAndBitwiseOr int");
        int x = (int) hs.get(TestAccessMode.GET).invokeExact(array, i);
        assertEquals(x, (int) (0x01234567 | 0x89ABCDEF), "getAndBitwiseOr int value");
      }

      {
        hs.get(TestAccessMode.SET).invokeExact(array, i, 0x01234567);

        int o =
            (int)
                hs.get(TestAccessMode.GET_AND_BITWISE_OR_ACQUIRE).invokeExact(array, i, 0x89ABCDEF);
        assertEquals(o, 0x01234567, "getAndBitwiseOrAcquire int");
        int x = (int) hs.get(TestAccessMode.GET).invokeExact(array, i);
        assertEquals(x, (int) (0x01234567 | 0x89ABCDEF), "getAndBitwiseOrAcquire int value");
      }

      {
        hs.get(TestAccessMode.SET).invokeExact(array, i, 0x01234567);

        int o =
            (int)
                hs.get(TestAccessMode.GET_AND_BITWISE_OR_RELEASE).invokeExact(array, i, 0x89ABCDEF);
        assertEquals(o, 0x01234567, "getAndBitwiseOrRelease int");
        int x = (int) hs.get(TestAccessMode.GET).invokeExact(array, i);
        assertEquals(x, (int) (0x01234567 | 0x89ABCDEF), "getAndBitwiseOrRelease int value");
      }

      // get and bitwise and
      {
        hs.get(TestAccessMode.SET).invokeExact(array, i, 0x01234567);

        int o = (int) hs.get(TestAccessMode.GET_AND_BITWISE_AND).invokeExact(array, i, 0x89ABCDEF);
        assertEquals(o, 0x01234567, "getAndBitwiseAnd int");
        int x = (int) hs.get(TestAccessMode.GET).invokeExact(array, i);
        assertEquals(x, (int) (0x01234567 & 0x89ABCDEF), "getAndBitwiseAnd int value");
      }

      {
        hs.get(TestAccessMode.SET).invokeExact(array, i, 0x01234567);

        int o =
            (int)
                hs.get(TestAccessMode.GET_AND_BITWISE_AND_ACQUIRE)
                    .invokeExact(array, i, 0x89ABCDEF);
        assertEquals(o, 0x01234567, "getAndBitwiseAndAcquire int");
        int x = (int) hs.get(TestAccessMode.GET).invokeExact(array, i);
        assertEquals(x, (int) (0x01234567 & 0x89ABCDEF), "getAndBitwiseAndAcquire int value");
      }

      {
        hs.get(TestAccessMode.SET).invokeExact(array, i, 0x01234567);

        int o =
            (int)
                hs.get(TestAccessMode.GET_AND_BITWISE_AND_RELEASE)
                    .invokeExact(array, i, 0x89ABCDEF);
        assertEquals(o, 0x01234567, "getAndBitwiseAndRelease int");
        int x = (int) hs.get(TestAccessMode.GET).invokeExact(array, i);
        assertEquals(x, (int) (0x01234567 & 0x89ABCDEF), "getAndBitwiseAndRelease int value");
      }

      // get and bitwise xor
      {
        hs.get(TestAccessMode.SET).invokeExact(array, i, 0x01234567);

        int o = (int) hs.get(TestAccessMode.GET_AND_BITWISE_XOR).invokeExact(array, i, 0x89ABCDEF);
        assertEquals(o, 0x01234567, "getAndBitwiseXor int");
        int x = (int) hs.get(TestAccessMode.GET).invokeExact(array, i);
        assertEquals(x, (int) (0x01234567 ^ 0x89ABCDEF), "getAndBitwiseXor int value");
      }

      {
        hs.get(TestAccessMode.SET).invokeExact(array, i, 0x01234567);

        int o =
            (int)
                hs.get(TestAccessMode.GET_AND_BITWISE_XOR_ACQUIRE)
                    .invokeExact(array, i, 0x89ABCDEF);
        assertEquals(o, 0x01234567, "getAndBitwiseXorAcquire int");
        int x = (int) hs.get(TestAccessMode.GET).invokeExact(array, i);
        assertEquals(x, (int) (0x01234567 ^ 0x89ABCDEF), "getAndBitwiseXorAcquire int value");
      }

      {
        hs.get(TestAccessMode.SET).invokeExact(array, i, 0x01234567);

        int o =
            (int)
                hs.get(TestAccessMode.GET_AND_BITWISE_XOR_RELEASE)
                    .invokeExact(array, i, 0x89ABCDEF);
        assertEquals(o, 0x01234567, "getAndBitwiseXorRelease int");
        int x = (int) hs.get(TestAccessMode.GET).invokeExact(array, i);
        assertEquals(x, (int) (0x01234567 ^ 0x89ABCDEF), "getAndBitwiseXorRelease int value");
      }
    }
  }
  static void testArrayIndexOutOfBounds(Handles hs) throws Throwable {
    int[] array = new int[10];

    for (int i : new int[] {-1, Integer.MIN_VALUE, 10, 11, Integer.MAX_VALUE}) {
      final int ci = i;

      for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET)) {
        checkIOOBE(
            am,
            () -> {
              int x = (int) hs.get(am).invokeExact(array, ci);
            });
      }

      for (TestAccessMode am : testAccessModesOfType(TestAccessType.SET)) {
        checkIOOBE(
            am,
            () -> {
              hs.get(am).invokeExact(array, ci, 0x01234567);
            });
      }

      for (TestAccessMode am : testAccessModesOfType(TestAccessType.COMPARE_AND_SET)) {
        checkIOOBE(
            am,
            () -> {
              boolean r = (boolean) hs.get(am).invokeExact(array, ci, 0x01234567, 0x89ABCDEF);
            });
      }

      for (TestAccessMode am : testAccessModesOfType(TestAccessType.COMPARE_AND_EXCHANGE)) {
        checkIOOBE(
            am,
            () -> {
              int r = (int) hs.get(am).invokeExact(array, ci, 0x89ABCDEF, 0x01234567);
            });
      }

      for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET_AND_SET)) {
        checkIOOBE(
            am,
            () -> {
              int o = (int) hs.get(am).invokeExact(array, ci, 0x01234567);
            });
      }

      for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET_AND_ADD)) {
        checkIOOBE(
            am,
            () -> {
              int o = (int) hs.get(am).invokeExact(array, ci, 0xCAFEBABE);
            });
      }

      for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET_AND_BITWISE)) {
        checkIOOBE(
            am,
            () -> {
              int o = (int) hs.get(am).invokeExact(array, ci, 0xCAFEBABE);
            });
      }
    }
  }