Source:
public void testAcquireReleaseOutbound() throws Throwable { test((inbound, outbound, endpoint) -> { double maxSendQueueCapacity = outbound.settings().applicationSendQueueCapacityInBytes + Double.min(outbound.settings().applicationSendQueueReserveEndpointCapacityInBytes, outbound.settings().applicationSendQueueReserveGlobalCapacityInBytes.limit()); int concurrency = 100; int attempts = 10000; int acquireCount = concurrency * attempts; long acquireStep = Math.round(maxSendQueueCapacity * 1.2 / acquireCount / 2); long maxFailures = (long) Math.ceil((acquireCount * acquireStep * 2 - maxSendQueueCapacity) / acquireStep); AtomicLong acquisitionFailures = new AtomicLong(); Runnable acquirer = () -> { for (int j = 0; j < attempts; j++) { if (!outbound.unsafeAcquireCapacity(acquireStep)) acquisitionFailures.incrementAndGet(); } }; Runnable releaser = () -> { for (int j = 0; j < attempts; j++) outbound.unsafeReleaseCapacity(acquireStep); }; List<Runnable> invokeOrder = new ArrayList<>(); for (int i = 0 ; i < concurrency ; ++i) invokeOrder.add(acquirer); for (int i = 0 ; i < concurrency ; ++i) invokeOrder.add(releaser); randomize(invokeOrder); try { Assert.assertTrue(outbound.unsafeAcquireCapacity(acquireCount, acquireCount * acquireStep)); ExecutorService executor = Executors.newFixedThreadPool(concurrency); invokeOrder.forEach(executor::submit); executor.shutdown(); executor.awaitTermination(10, TimeUnit.SECONDS); Assert.assertEquals(acquireCount * acquireStep - (acquisitionFailures.get() * acquireStep), outbound.pendingBytes()); Assert.assertEquals(acquireCount - acquisitionFailures.get(), outbound.pendingCount()); Assert.assertTrue(acquisitionFailures.get() <= maxFailures); } finally { outbound.unsafeReleaseCapacity(outbound.pendingCount(), outbound.pendingBytes()); } }); }

Target:
public void testAcquireReleaseOutbound() throws Throwable { test((inbound, outbound, endpoint) -> { double maxSendQueueCapacity = outbound.settings().applicationSendQueueCapacityInBytes + Double.min(outbound.settings().applicationSendQueueReserveEndpointCapacityInBytes, outbound.settings().applicationSendQueueReserveGlobalCapacityInBytes.limit()); int concurrency = 100; int attempts = 10000; int acquireCount = concurrency * attempts; long acquireStep = Math.round(maxSendQueueCapacity * 1.2 / acquireCount / 2); long maxFailures = (long) Math.ceil((acquireCount * acquireStep * 2 - maxSendQueueCapacity) / acquireStep); AtomicLong acquisitionFailures = new AtomicLong(); Runnable acquirer = () -> { for (int j = 0; j < attempts; j++) { if (!outbound.unsafeAcquireCapacity(acquireStep)) acquisitionFailures.incrementAndGet(); } }; Runnable releaser = () -> { for (int j = 0; j < attempts; j++) outbound.unsafeReleaseCapacity(acquireStep); }; List<Runnable> submitOrder = new ArrayList<>(concurrency * 2); for (int i = 0 ; i < concurrency ; ++i) submitOrder.add(acquirer); for (int i = 0 ; i < concurrency ; ++i) submitOrder.add(releaser); randomize(submitOrder); try { Assert.assertTrue("Unable to reserve enough capacity", outbound.unsafeAcquireCapacity(acquireCount, acquireCount * acquireStep)); ExecutorService executor = Executors.newFixedThreadPool(concurrency); submitOrder.forEach(executor::submit); executor.shutdown(); executor.awaitTermination(10, TimeUnit.SECONDS); Assert.assertEquals(acquireCount * acquireStep - (acquisitionFailures.get() * acquireStep), outbound.pendingBytes()); Assert.assertEquals(acquireCount - acquisitionFailures.get(), outbound.pendingCount()); Assert.assertTrue(String.format("acquisitionFailures should be capped by maxFailure. acquisitionFailures: %d, acquisitionFailures: %d", maxFailures, acquisitionFailures.get()), acquisitionFailures.get() <= maxFailures); } finally { outbound.unsafeReleaseCapacity(outbound.pendingCount(), outbound.pendingBytes()); } }); }