public MttTestCallableResult call() throws Exception {
      LOG.info(Thread.currentThread().getId() + " thread starts");
      TestBuddyAllocator.syncThreadStart(cdlIn, cdlOut);
      MttTestCallableResult result = new MttTestCallableResult();
      result.allocSize = allocSize;
      List<MemoryBuffer> allocs = new ArrayList<>(allocCount);
      LlapAllocatorBuffer[] dest = new LlapAllocatorBuffer[1];
      for (int i = 0; i < iterCount; ++i) {
        for (int j = 0; j < allocCount; ++j) {
          try {
            dest[0] = null;
            a.allocateMultiple(dest, allocSize);
            LlapAllocatorBuffer buf = dest[0];
            assertTrue(buf.incRef() > 0);
            allocs.add(buf);
            ++result.successes;
            buf.decRef();
          } catch (AllocatorOutOfMemoryException ex) {
            ++result.ooms;
          } catch (Throwable ex) {
            LOG.error("Failed", ex);
            throw new Exception(ex);
          }
        }
        for (MemoryBuffer buf : allocs) {
          try {
            a.deallocate(buf);
          } catch (Throwable ex) {
            LOG.error("Failed", ex);
            throw new Exception(ex);
          }
        }
        allocs.clear();
      }
      return result;
    }
This relies on allocations basically being sequential, no internal reordering. Rather,
the specific paths it takes do; all the scenarios should work regardless of allocation.
llap-server/src/test/org/apache/hadoop/hive/llap/cache/TestBuddyAllocatorForceEvict.java