@Test
  public void testEncryptDecryptNettyByteBuf() throws Exception {
    // testEncryptDecryptBytes already tests the correctness of the encrypt decrypt methods with ByteBuffer, in this
    // test case, we can make the assumption that these two functions always provide correct answers.

    String key = TestUtils.getRandomKey(DEFAULT_KEY_SIZE_IN_CHARS);
    Properties props = getKMSProperties(key, DEFAULT_KEY_SIZE_IN_CHARS);
    VerifiableProperties verifiableProperties = new VerifiableProperties((props));
    SecretKeySpec secretKeySpec = new SecretKeySpec(Hex.decode(key), "AES");
    GCMCryptoService cryptoService =
        (GCMCryptoService) (new GCMCryptoServiceFactory(verifiableProperties, REGISTRY).getCryptoService());
    byte[] fixedIv = new byte[12];
    boolean directMemorySupported = PooledByteBufAllocator.DEFAULT.isDirectBufferPooled();
    for (int i = 0; i < 5; i++) {
      int size = TestUtils.RANDOM.nextInt(MAX_DATA_SIZE);
      byte[] randomData = new byte[size];
      TestUtils.RANDOM.nextBytes(randomData);
      ByteBuffer toEncrypt = ByteBuffer.wrap(randomData);
      ByteBuf toEncryptByteBufHeap = PooledByteBufAllocator.DEFAULT.heapBuffer(size);
      ByteBuf toEncryptByteBufDirect = PooledByteBufAllocator.DEFAULT.ioBuffer(size);
      toEncryptByteBufHeap.writeBytes(randomData);
      toEncryptByteBufDirect.writeBytes(randomData);

      ByteBuffer encryptedBytes = cryptoService.encrypt(toEncrypt, secretKeySpec, fixedIv);
      ByteBuf encryptedBytesByteBufHeap = cryptoService.encrypt(toEncryptByteBufHeap, secretKeySpec, fixedIv);
      ByteBuf encryptedBytesByteBufDirect = cryptoService.encrypt(toEncryptByteBufDirect, secretKeySpec, fixedIv);

      // EncryptedByteBuf should be a head buffer always.
      Assert.assertEquals(directMemorySupported, !encryptedBytesByteBufHeap.hasArray());
      Assert.assertEquals(directMemorySupported, !encryptedBytesByteBufDirect.hasArray());
      Assert.assertEquals(encryptedBytes.remaining(), encryptedBytesByteBufHeap.readableBytes());
      Assert.assertEquals(encryptedBytes.remaining(), encryptedBytesByteBufDirect.readableBytes());
      Assert.assertEquals(toEncrypt.remaining(), 0);
      Assert.assertEquals(toEncryptByteBufDirect.readableBytes(), 0);
      Assert.assertEquals(toEncryptByteBufHeap.readableBytes(), 0);

      byte[] arrayFromByteBuf = new byte[encryptedBytesByteBufHeap.readableBytes()];
      encryptedBytesByteBufHeap.getBytes(encryptedBytesByteBufHeap.readerIndex(), arrayFromByteBuf);
      Assert.assertArrayEquals(encryptedBytes.array(), arrayFromByteBuf);
      encryptedBytesByteBufDirect.getBytes(encryptedBytesByteBufDirect.readerIndex(), arrayFromByteBuf);
      Assert.assertArrayEquals(encryptedBytes.array(), arrayFromByteBuf);

      toEncryptByteBufHeap.release();
      toEncryptByteBufDirect.release();
      encryptedBytesByteBufHeap.release();
      encryptedBytesByteBufDirect.release();

      ByteBuf toDecryptByteBufHeap = PooledByteBufAllocator.DEFAULT.heapBuffer(arrayFromByteBuf.length);
      ByteBuf toDecryptByteBufDirect = ByteBufAllocator.DEFAULT.ioBuffer(arrayFromByteBuf.length);
      toDecryptByteBufHeap.writeBytes(arrayFromByteBuf);
      toDecryptByteBufDirect.writeBytes(arrayFromByteBuf);

      ByteBuffer decryptedBytes = cryptoService.decrypt(encryptedBytes, secretKeySpec);
      ByteBuf decryptedBytesByteBufHeap = cryptoService.decrypt(toDecryptByteBufHeap, secretKeySpec);
      ByteBuf decryptedBytesByteBufDirect = cryptoService.decrypt(toDecryptByteBufDirect, secretKeySpec);

      Assert.assertEquals(directMemorySupported, !decryptedBytesByteBufHeap.hasArray());
      Assert.assertEquals(directMemorySupported, !decryptedBytesByteBufDirect.hasArray());
      Assert.assertEquals(decryptedBytes.remaining(), decryptedBytesByteBufHeap.readableBytes());
      Assert.assertEquals(decryptedBytes.remaining(), decryptedBytesByteBufDirect.readableBytes());
      Assert.assertEquals(encryptedBytes.remaining(), 0);
      Assert.assertEquals(toDecryptByteBufDirect.readableBytes(), 0);
      Assert.assertEquals(toDecryptByteBufHeap.readableBytes(), 0);

      arrayFromByteBuf = new byte[decryptedBytesByteBufHeap.readableBytes()];
      decryptedBytesByteBufHeap.getBytes(decryptedBytesByteBufHeap.readerIndex(), arrayFromByteBuf);
      Assert.assertArrayEquals(decryptedBytes.array(), arrayFromByteBuf);
      decryptedBytesByteBufDirect.getBytes(decryptedBytesByteBufDirect.readerIndex(), arrayFromByteBuf);
      Assert.assertArrayEquals(decryptedBytes.array(), arrayFromByteBuf);

      toDecryptByteBufHeap.release();
      toDecryptByteBufDirect.release();
      decryptedBytesByteBufHeap.release();
      decryptedBytesByteBufDirect.release();
    }
  }
Test basic encryption and decryption for random data in {@link ByteBuf}.
@throws Exception Any unexpected error
ambry-router/src/test/java/com/github/ambry/router/GCMCryptoServiceTest.java