@Test
 public void runTestWithAsyncCompletionCompletedInTest() throws Exception {
   AtomicBoolean ok = new AtomicBoolean();
   TestSuite suite =
       TestSuite.create("my_suite")
           .test(
               "my_test",
               context -> {
                 Async async = context.async();
                 async.complete();
                 try {
                   async.complete();
                 } catch (IllegalStateException ignore) {
                 }
                 ok.set(true);
               });
   TestReporter reporter = new TestReporter();
   run(suite, reporter);
   reporter.await();
   assertTrue(ok.get());
   assertTrue(reporter.completed());
   assertEquals(0, reporter.exceptions.size());
   assertEquals(1, reporter.results.size());
   TestResult result = reporter.results.get(0);
   assertEquals("my_test", result.name());
   assertTrue(result.succeeded());
   assertFalse(result.failed());
   assertNull(result.failure());
 }
 @Test
 public void testAssertAsyncFailureHandlerSucceededAsync() throws Exception {
   BlockingQueue<Handler<AsyncResult<String>>> handlerQueue = new ArrayBlockingQueue<>(1);
   BlockingQueue<Async> resultQueue = new ArrayBlockingQueue<>(1);
   TestSuite suite =
       TestSuite.create("my_suite")
           .test(
               "my_test",
               context -> {
                 handlerQueue.add(
                     context.<String>asyncAssertFailure(
                         r -> {
                           resultQueue.add(context.async());
                         }));
               });
   TestReporter reporter = new TestReporter();
   run(suite, reporter);
   Handler<AsyncResult<String>> handler = handlerQueue.poll(2, TimeUnit.SECONDS);
   handler.handle(Future.failedFuture(new Throwable()));
   Async result = resultQueue.poll(2, TimeUnit.SECONDS);
   assertFalse(reporter.completed());
   result.complete();
   reporter.await();
   assertEquals(0, reporter.exceptions.size());
   assertEquals(1, reporter.results.size());
   assertEquals("my_test", reporter.results.get(0).name());
   assertFalse(reporter.results.get(0).failed());
 }
 @Test
 public void runTestWithAsyncCompletionAfterFailureInTest() throws Exception {
   AtomicBoolean completed = new AtomicBoolean();
   TestSuite suite =
       TestSuite.create("my_suite")
           .test(
               "my_test",
               context -> {
                 Async async = context.async();
                 try {
                   context.fail("msg");
                 } catch (AssertionError ignore) {
                 }
                 async.complete();
                 completed.set(true);
               });
   TestReporter reporter = new TestReporter();
   run(suite, reporter);
   reporter.await();
   assertTrue(completed.get());
   assertTrue(reporter.completed());
   assertEquals(0, reporter.exceptions.size());
   assertEquals(1, reporter.results.size());
   TestResult result = reporter.results.get(0);
   assertEquals("my_test", result.name());
   assertTrue(result.failed());
 }
 @Test
 public void runTestWithFailBeforeAsync() throws Exception {
   AtomicReference<AssertionError> failure = new AtomicReference<>();
   BlockingQueue<Async> queue = new ArrayBlockingQueue<>(1);
   TestSuite suite =
       TestSuite.create("my_suite")
           .test(
               "my_test",
               context -> {
                 try {
                   context.fail();
                 } catch (AssertionError e) {
                   failure.set(e);
                 }
                 queue.add(context.async());
               });
   TestReporter reporter = new TestReporter();
   run(suite, reporter);
   reporter.await();
   Async async = queue.poll(2, TimeUnit.SECONDS);
   async.complete();
   assertTrue(reporter.completed());
   assertEquals(0, reporter.exceptions.size());
   assertEquals(1, reporter.results.size());
   TestResult result = reporter.results.get(0);
   assertEquals("my_test", result.name());
   assertFalse(result.succeeded());
   assertTrue(result.failed());
   assertNotNull(result.failure());
   assertSame(failure.get(), result.failure().cause());
 }
 @Test
 public void runTestWithFailAfterAsync() throws Exception {
   RuntimeException failure = new RuntimeException();
   BlockingQueue<Async> queue = new ArrayBlockingQueue<>(1);
   TestSuite suite =
       TestSuite.create("my_suite")
           .test(
               "my_test",
               context -> {
                 queue.add(context.async());
                 throw failure;
               });
   TestReporter reporter = new TestReporter();
   run(suite, reporter);
   reporter.await();
   Async async = queue.poll(2, TimeUnit.SECONDS);
   async.complete();
   assertTrue(reporter.completed());
   assertEquals(0, reporter.exceptions.size());
   assertEquals(1, reporter.results.size());
   TestResult result = reporter.results.get(0);
   assertEquals("my_test", result.name());
   assertFalse(result.succeeded());
   assertTrue(result.failed());
   assertNotNull(result.failure());
   assertSame(failure, result.failure().cause());
 }
 @Test
 public void testTimeout() throws Exception {
   BlockingQueue<Async> queue = new ArrayBlockingQueue<>(2);
   TestSuite suite =
       TestSuite.create("my_suite")
           .test("my_test0", context -> queue.add(context.async()))
           .test("my_test1", context -> queue.add(context.async()));
   TestReporter reporter = new TestReporter();
   run(suite, reporter, 300); // 300 ms
   reporter.await(); // Wait until timeout and suite completes
   assertEquals(2, reporter.results.size());
   for (int i = 0; i < 2; i++) {
     Async async = queue.poll(2, TimeUnit.SECONDS);
     assertEquals("my_test" + i, reporter.results.get(i).name());
     assertTrue(reporter.results.get(i).failed());
     assertNotNull(reporter.results.get(i).failure());
     assertTrue(reporter.results.get(i).failure().cause() instanceof TimeoutException);
     async.complete();
   }
 }