@Test public void testSimple() throws InterruptedException, ExecutionException { Callable<String> mainJob = new Callable<String>() { public String call() { log.info("main job - " + Tasks.current()); messages.add("main"); DynamicTasks.queue(sayTask("world")); return "bye"; } }; DynamicSequentialTask<String> t = new DynamicSequentialTask<String>(mainJob); // this should be added before anything added when the task is invoked t.queue(sayTask("hello")); Assert.assertEquals(messages, Lists.newArrayList()); Assert.assertEquals(t.isBegun(), false); Assert.assertEquals(Iterables.size(t.getChildren()), 1); ec.submit(t); Assert.assertEquals(t.isSubmitted(), true); Assert.assertEquals(t.getUnchecked(Duration.ONE_SECOND), "bye"); long elapsed = t.getEndTimeUtc() - t.getSubmitTimeUtc(); Assert.assertTrue( elapsed < 1000, "elapsed time should have been less than 1s but was " + Time.makeTimeString(elapsed, true)); Assert.assertEquals(Iterables.size(t.getChildren()), 2); Assert.assertEquals(messages.size(), 3, "expected 3 entries, but had " + messages); // either main or hello can be first, but world should be last Assert.assertEquals(messages.get(2), "world"); }
@Test public void testInessentialChildrenFailureDoesNotAbortSecondaryOrFailPrimary() { Task<String> t1 = monitorableTask(null, "1", new FailCallable()); TaskTags.markInessential(t1); Task<String> t = Tasks.<String>builder() .dynamic(true) .body(monitorableJob("main")) .add(t1) .add(monitorableTask("2")) .build(); ec.submit(t); releaseAndWaitForMonitorableJob("1"); Assert.assertFalse(t.blockUntilEnded(TINY_TIME)); releaseAndWaitForMonitorableJob("2"); Assert.assertFalse(t.blockUntilEnded(TINY_TIME)); releaseMonitorableJob("main"); Assert.assertTrue(t.blockUntilEnded(TIMEOUT)); Assert.assertEquals(messages, MutableList.of("1", "2", "main")); Assert.assertTrue( stopwatch.elapsed(TimeUnit.MILLISECONDS) < TIMEOUT.toMilliseconds(), "took too long: " + stopwatch); Assert.assertFalse(t.isError()); Assert.assertTrue(t1.isError()); }
@Test public void testCancelled() throws InterruptedException, ExecutionException { Task<List<?>> t = Tasks.sequential(sayTask("1"), sayTask("2a", Duration.THIRTY_SECONDS, "2b"), sayTask("3")); ec.submit(t); synchronized (messages) { while (messages.size() <= 1) messages.wait(); } Assert.assertEquals(messages, Arrays.asList("1", "2a")); Time.sleep(Duration.millis(50)); t.cancel(true); Assert.assertTrue(t.isDone()); // 2 should get cancelled, and invoke the cancellation semaphore // 3 should get cancelled and not run at all Assert.assertEquals(messages, Arrays.asList("1", "2a")); // Need to ensure that 2 has been started; race where we might cancel it before its run method // is even begun. Hence doing "2a; pause; 2b" where nothing is interruptable before pause. Assert.assertTrue(cancellations.tryAcquire(10, TimeUnit.SECONDS)); Iterator<Task<?>> ci = ((HasTaskChildren) t).getChildren().iterator(); Assert.assertEquals(ci.next().get(), "1"); Task<?> task2 = ci.next(); Assert.assertTrue(task2.isBegun()); Assert.assertTrue(task2.isDone()); Assert.assertTrue(task2.isCancelled()); Task<?> task3 = ci.next(); Assert.assertFalse(task3.isBegun()); Assert.assertTrue(task2.isDone()); Assert.assertTrue(task2.isCancelled()); // but we do _not_ get a mutex from task3 as it does not run (is not interrupted) Assert.assertEquals(cancellations.availablePermits(), 0); }
@Test public void testComplex() throws InterruptedException, ExecutionException { Task<List<?>> t = Tasks.sequential( sayTask("1"), sayTask("2"), Tasks.parallel(sayTask("4"), sayTask("3")), sayTask("5")); ec.submit(t); Assert.assertEquals(t.get().size(), 4); Asserts.assertEqualsIgnoringOrder((List<?>) t.get().get(2), ImmutableSet.of("3", "4")); Assert.assertTrue( messages.equals(Arrays.asList("1", "2", "3", "4", "5")) || messages.equals(Arrays.asList("1", "2", "4", "3", "5")), "messages=" + messages); }
@Test public void testTaskBuilderUsingAddAllChildren() { Task<String> t = Tasks.<String>builder() .dynamic(true) .body(monitorableJob("main")) .addAll(ImmutableList.of(monitorableTask("1"), monitorableTask("2"))) .build(); ec.submit(t); releaseAndWaitForMonitorableJob("1"); releaseAndWaitForMonitorableJob("2"); releaseAndWaitForMonitorableJob("main"); Assert.assertEquals(messages, MutableList.of("1", "2", "main")); }
@Test public void testChildrenRunConcurrentlyWithPrimary() { Task<String> t = Tasks.<String>builder() .dynamic(true) .body(monitorableJob("main")) .add(monitorableTask("1")) .add(monitorableTask("2")) .build(); ec.submit(t); releaseAndWaitForMonitorableJob("1"); releaseAndWaitForMonitorableJob("main"); Assert.assertFalse(t.blockUntilEnded(TINY_TIME)); releaseMonitorableJob("2"); Assert.assertTrue(t.blockUntilEnded(TIMEOUT)); Assert.assertEquals(messages, MutableList.of("1", "main", "2")); Assert.assertTrue( stopwatch.elapsed(TimeUnit.MILLISECONDS) < TIMEOUT.toMilliseconds(), "took too long: " + stopwatch); Assert.assertFalse(t.isError()); }