@Test
  public void testMultipleRequestedServedAfterBlocked() throws Exception {
    final int n = 3;
    final int smallSize = 1024;
    final int largeSize = n * smallSize;
    final long capacity = n * smallSize;
    final long maxBlockTimeInMs = 200;
    SimpleByteBufferPool pool = new SimpleByteBufferPool(capacity);
    CountDownLatch largeAllocated = new CountDownLatch(1);
    CountDownLatch largeUsed = new CountDownLatch(1);
    CountDownLatch smallAllocated = new CountDownLatch(n);
    CountDownLatch smallUsed = new CountDownLatch(n);
    BufferConsumer largeConsumer = new BufferConsumer(largeSize, maxBlockTimeInMs, pool, largeAllocated, largeUsed);
    new Thread(largeConsumer).start();
    if (!largeAllocated.await(100, TimeUnit.MILLISECONDS)) {
      fail("SimpleByteBufferPool takes too long time to allocate a buffer to largeConsumer.");
    }
    assertEquals(0, pool.availableMemory());
    BufferConsumer[] smallConsumers = new BufferConsumer[n];
    Thread[] smallConsumerThreads = new Thread[n];
    for (int i = 0; i < n; i++) {
      smallConsumers[i] = new BufferConsumer(smallSize, maxBlockTimeInMs, pool, smallAllocated, smallUsed);
      smallConsumerThreads[i] = new Thread(smallConsumers[i]);
      smallConsumerThreads[i].start();
    }
    largeUsed.countDown();
    if (!smallAllocated.await(100, TimeUnit.MILLISECONDS)) {
      fail("SimpleByteBufferPool takes too long time to allocate a buffer to smallConsumer.");
    }
    assertEquals(0, pool.availableMemory());
    for (int i = 0; i < n; i++) {
      smallUsed.countDown();
    }
    for (int i = 0; i < n; i++) {
      smallConsumerThreads[i].join();
    }
    assertEquals(capacity, pool.availableMemory());
    if (largeConsumer.exception != null) {
      throw largeConsumer.exception;
    }
    for (int i = 0; i < n; i++) {
      if (smallConsumers[i].exception != null) {
        throw smallConsumers[i].exception;
      }
    }
  }
This scenario tests when there is not enough memory, n requests are blocked during getting memory from a
{@link SimpleByteBufferPool}. After a large amount of buffer is deallocated back to the buffer pool, all
the n requests can be served successfully. There should be no exception during the test.
ambry-utils/src/test/java/com/github/ambry/utils/SimpleByteBufferPoolTest.java