package org.webpieces.util.locking; import java.util.List; import java.util.concurrent.CompletableFuture; import java.util.concurrent.Executor; import java.util.concurrent.Executors; import org.junit.Assert; import org.junit.Test; import org.webpieces.util.threading.NamedThreadFactory; import com.webpieces.util.locking.PermitQueue; public class TestPermitQueue { private Executor executor = Executors.newFixedThreadPool(5, new NamedThreadFactory("deansThr")); private PermitQueue<Long> queue1 = new PermitQueue<>(1); private MockService svc = new MockService(); @Test public void testPermits1() throws InterruptedException { CompletableFuture<Long> future1 = new CompletableFuture<Long>(); svc.addToReturn(future1); CompletableFuture<Long> future2 = new CompletableFuture<Long>(); svc.addToReturn(future2); queue1.runRequest(() -> svc.runFunction(1)); queue1.runRequest(() -> svc.runFunction(2)); List<Integer> results = svc.getAndClear(); Assert.assertEquals(1,results.size()); Assert.assertEquals(1, results.get(0).intValue()); future1.complete(3L); queue1.releasePermit(); List<Integer> results2 = svc.getAndClear(); Assert.assertEquals(1,results2.size()); Assert.assertEquals(2, results2.get(0).intValue()); } @Test public void testReducePermits() throws InterruptedException { PermitQueue<Long> queue = new PermitQueue<>(2); CompletableFuture<Long> future1 = new CompletableFuture<Long>(); svc.addToReturn(future1); svc.addToReturn(future1); svc.addToReturn(future1); svc.addToReturn(future1); queue.runRequest(() -> svc.runFunction(1)); queue.runRequest(() -> svc.runFunction(2)); queue.runRequest(() -> svc.runFunction(3)); queue.runRequest(() -> svc.runFunction(4)); List<Integer> results = svc.getAndClear(); Assert.assertEquals(2,results.size()); Assert.assertEquals(1, results.get(0).intValue()); Assert.assertEquals(2, results.get(1).intValue()); queue.modifyPermitPoolSize(-1); //release two queue.releasePermit(); queue.releasePermit(); //only one will run List<Integer> results2 = svc.getAndClear(); Assert.assertEquals(1,results2.size()); Assert.assertEquals(3, results2.get(0).intValue()); queue.releasePermit(); List<Integer> results3 = svc.getAndClear(); Assert.assertEquals(1,results3.size()); Assert.assertEquals(4, results3.get(0).intValue()); } @Test public void testAddPermits() throws InterruptedException { PermitQueue<Long> queue = new PermitQueue<>(1); CompletableFuture<Long> future1 = new CompletableFuture<Long>(); svc.addToReturn(future1); svc.addToReturn(future1); svc.addToReturn(future1); svc.addToReturn(future1); queue.runRequest(() -> svc.runFunction(1)); queue.runRequest(() -> svc.runFunction(2)); queue.runRequest(() -> svc.runFunction(3)); queue.runRequest(() -> svc.runFunction(4)); List<Integer> results = svc.getAndClear(); Assert.assertEquals(1,results.size()); Assert.assertEquals(1, results.get(0).intValue()); queue.modifyPermitPoolSize(2); List<Integer> results2 = svc.getAndClear(); Assert.assertEquals(2,results2.size()); Assert.assertEquals(2, results2.get(0).intValue()); Assert.assertEquals(3, results2.get(1).intValue()); queue.releasePermit(); List<Integer> results3 = svc.getAndClear(); Assert.assertEquals(1,results3.size()); Assert.assertEquals(4, results3.get(0).intValue()); } @Test public void testPermits() throws InterruptedException { executor.execute(new MyRunnable(0)); executor.execute(new MyRunnable(1)); executor.execute(new MyRunnable(2)); } private CompletableFuture<Long> someFunction(int i) { System.out.println("function"+i); try { Thread.sleep(1000); } catch (InterruptedException e) { throw new RuntimeException(e); } CompletableFuture<Long> future = new CompletableFuture<Long>(); executor.execute(() -> { try { Thread.sleep(1000); } catch (InterruptedException e) { throw new RuntimeException(e); } System.out.println("complete"+i); future.complete(100L+i); }); return future; } private class MyRunnable implements Runnable { private int id; public MyRunnable(int i) { this.id = i; } @Override public void run() { queue1.runRequest(() -> someFunction(id)).thenApply( longId -> { System.out.println("id="+longId); return longId; }); } } }