Source:
public void testWorkerStalenessCheck() throws NetworkException, InterruptedException { final int numOfThreads = 3; final int key = 0; final int timeoutInMilliseconds = 500; final Runnable[] threads = new Runnable[numOfThreads]; final Map<Runnable, CountDownLatch> threadLatchMap = new HashMap<>(); final class WorkerStalenessCheckThread implements Runnable { @Override public void run() { parameterWorker.pull(key); threadLatchMap.get(this).countDown(); } } workerClock.initialize(); while (workerClock.getWorkerClock() <= workerClock.getGlobalMinimumClock() + STALENESS_BOUND) { for (int i = 0; i < numOfThreads; i++) { threads[i] = new WorkerStalenessCheckThread(); threadLatchMap.put(threads[i], new CountDownLatch(1)); } ThreadUtils.runConcurrently(threads); for (final Runnable thread : threads) { threadLatchMap.get(thread).await(); assertTrue(threadLatchMap.get(thread).getCount() == 0); } threadLatchMap.clear(); workerClock.clock(); } assertTrue(workerClock.getWorkerClock() > workerClock.getGlobalMinimumClock() + STALENESS_BOUND); for (int i = 0; i < numOfThreads; i++) { threads[i] = new WorkerStalenessCheckThread(); threadLatchMap.put(threads[i], new CountDownLatch(1)); } ThreadUtils.runConcurrently(threads); for (final Runnable thread : threads) { threadLatchMap.get(thread).await(10, TimeUnit.SECONDS); assertTrue(threadLatchMap.get(thread).getCount() > 0); } final int oldGlobalMinimumClock = workerClock.getGlobalMinimumClock(); final int deltaClock = 1; final byte[] initClockMsgData = codec.encode(ClockManager.getBroadcastMinClockMessage(oldGlobalMinimumClock + deltaClock)); mockAggregationMaster.send(ClockManager.AGGREGATION_CLIENT_NAME, "worker", initClockMsgData); assertEquals(oldGlobalMinimumClock + deltaClock, workerClock.getGlobalMinimumClock()); assertTrue(workerClock.getWorkerClock() <= workerClock.getGlobalMinimumClock() + STALENESS_BOUND); for (final Runnable thread : threads) { threadLatchMap.get(thread).await(); assertTrue(threadLatchMap.get(thread).getCount() == 0); } }

Target:
public void testWorkerStalenessCheck() throws NetworkException, InterruptedException, BrokenBarrierException { final int numOfThreads = 3; final int key = 0; final long timeoutInMilliSeconds = 10000; final int cyclicBarrierSize = numOfThreads + 1; final CyclicBarrier barrier = new CyclicBarrier(cyclicBarrierSize); final Runnable[] threads = new Runnable[numOfThreads]; final class WorkerStalenessCheckThread implements Runnable { private final CyclicBarrier cyclicBarrier; WorkerStalenessCheckThread(final CyclicBarrier barrier) { this.cyclicBarrier = barrier; } @Override public void run() { parameterWorker.pull(key); try { cyclicBarrier.await(); } catch (InterruptedException | BrokenBarrierException e) { fail("Exception occurred while waiting: " + e.getMessage()); } } } workerClock.initialize(); while (workerClock.getWorkerClock() <= workerClock.getGlobalMinimumClock() + STALENESS_BOUND) { barrier.reset(); for (int i = 0; i < numOfThreads; i++) { threads[i] = new WorkerStalenessCheckThread(barrier); } ThreadUtils.runConcurrently(threads); barrier.await(); workerClock.clock(); } assertTrue(workerClock.getWorkerClock() > workerClock.getGlobalMinimumClock() + STALENESS_BOUND); barrier.reset(); for (int i = 0; i < numOfThreads; i++) { threads[i] = new WorkerStalenessCheckThread(barrier); } ThreadUtils.runConcurrently(threads); Thread.sleep(timeoutInMilliSeconds); assertEquals(barrier.getNumberWaiting(), 0); final int oldGlobalMinimumClock = workerClock.getGlobalMinimumClock(); final int deltaClock = 1; final byte[] initClockMsgData = codec.encode(ClockManager.getBroadcastMinClockMessage(oldGlobalMinimumClock + deltaClock)); mockAggregationMaster.send(ClockManager.AGGREGATION_CLIENT_NAME, WORKER_ID, initClockMsgData); assertEquals(oldGlobalMinimumClock + deltaClock, workerClock.getGlobalMinimumClock()); assertTrue(workerClock.getWorkerClock() <= workerClock.getGlobalMinimumClock() + STALENESS_BOUND); barrier.await(); }