@Test
  public void testReconnect() throws Exception {
    CompletableFuture<Boolean> firstStartFuture = new CompletableFuture<>();
    CompletableFuture<Boolean> secondStartFuture = new CompletableFuture<>();
    doAnswer(
            invocation -> {
              if (!firstStartFuture.isDone()) {
                firstStartFuture.complete(true);
                throw new IOException("test exception");
              }

              secondStartFuture.complete(true);
              botShutdownLatch.await();
              return null;
            })
        .when(pircBotX)
        .startBot();

    instance.connect();
    firstStartFuture.get(TIMEOUT, TIMEOUT_UNIT);

    secondStartFuture.get(TIMEOUT, TIMEOUT_UNIT);

    verify(pircBotX, times(2)).startBot();
  }
Beispiel #2
0
 static void checkCompletedNormally(CompletableFuture<?> cf, Object[] values) {
   try {
     equalAnyOf(cf.join(), values);
   } catch (Throwable x) {
     unexpected(x);
   }
   try {
     equalAnyOf(cf.getNow(null), values);
   } catch (Throwable x) {
     unexpected(x);
   }
   try {
     equalAnyOf(cf.get(), values);
   } catch (Throwable x) {
     unexpected(x);
   }
   try {
     equalAnyOf(cf.get(0L, SECONDS), values);
   } catch (Throwable x) {
     unexpected(x);
   }
   check(cf.isDone(), "Expected isDone to be true, got:" + cf);
   check(!cf.isCancelled(), "Expected isCancelled to be false");
   check(!cf.cancel(true), "Expected cancel to return false");
   check(cf.toString().contains("[Completed normally]"));
   check(cf.complete(null) == false, "Expected complete() to fail");
   check(
       cf.completeExceptionally(new Throwable()) == false,
       "Expected completeExceptionally() to fail");
 }
  /**
   * Connects to an RS world.
   *
   * @param world the world, as a string. For RS3, use a numeric string. For oldschool, use
   *     "oldschool[world]".
   * @return A future for the connection task.
   */
  public CompletableFuture<Void> connect(String world) {
    if (connectionTask != null && !connectionTask.isDone()) {
      connectionTask.cancel(true);
    }

    disconnect();

    String host;
    int port;
    if (world.startsWith("oldschool")) {
      host = world + HOST_SUFFIX;
      port = OLDSCHOOL_PORT;
    } else {
      host = "world" + world + HOST_SUFFIX;
      port = RS3_PORT;
    }

    connectionTask = new CompletableFuture<>();
    CompletableFuture.runAsync(
        () -> {
          try {
            synchronized (this) {
              socket = new Socket(host, port);
            }
            connectionTask.complete(null);
          } catch (IOException e) {
            connectionTask.completeExceptionally(e);
          }
        });
    return connectionTask;
  }
Beispiel #4
0
  @Test
  public void shouldConvertFailureToFailedCompletableFuture() {

    final CompletableFuture<Object> future = failure().toCompletableFuture();
    assertThat(future.isDone());
    assertThat(future.isCompletedExceptionally());
    assertThatThrownBy(future::get)
        .isExactlyInstanceOf(ExecutionException.class)
        .hasCauseExactlyInstanceOf(RuntimeException.class);
  }
Beispiel #5
0
 @SuppressWarnings("unchecked")
 static <T> void checkCompletedExceptionally(CompletableFuture<T> cf, boolean cancelled)
     throws Exception {
   try {
     cf.join();
     fail("Excepted exception to be thrown");
   } catch (CompletionException x) {
     if (cancelled) fail();
     else pass();
   } catch (CancellationException x) {
     if (cancelled) pass();
     else fail();
   }
   try {
     cf.getNow(null);
     fail("Excepted exception to be thrown");
   } catch (CompletionException x) {
     if (cancelled) fail();
     else pass();
   } catch (CancellationException x) {
     if (cancelled) pass();
     else fail();
   }
   try {
     cf.get();
     fail("Excepted exception to be thrown");
   } catch (CancellationException x) {
     if (cancelled) pass();
     else fail();
   } catch (ExecutionException x) {
     if (cancelled) check(x.getCause() instanceof CancellationException);
     else pass();
   }
   try {
     cf.get(0L, SECONDS);
     fail("Excepted exception to be thrown");
   } catch (CancellationException x) {
     if (cancelled) pass();
     else fail();
   } catch (ExecutionException x) {
     if (cancelled) check(x.getCause() instanceof CancellationException);
     else pass();
   }
   check(cf.isDone(), "Expected isDone to be true, got:" + cf);
   check(
       cf.isCancelled() == cancelled,
       "Expected isCancelled: " + cancelled + ", got:" + cf.isCancelled());
   check(
       cf.cancel(true) == cancelled, "Expected cancel: " + cancelled + ", got:" + cf.cancel(true));
   check(cf.toString().contains("[Completed exceptionally]")); // ## TODO: 'E'xceptionally
   check(cf.complete((T) new Object()) == false, "Expected complete() to fail");
   check(
       cf.completeExceptionally(new Throwable()) == false,
       "Expected completeExceptionally() to fail, already completed");
 }
 private CompletableFuture<HRegionLocation> withTimeout(
     CompletableFuture<HRegionLocation> future, long timeoutNs, Supplier<String> timeoutMsg) {
   if (future.isDone() || timeoutNs <= 0) {
     return future;
   }
   Timeout timeoutTask =
       retryTimer.newTimeout(
           t -> {
             if (future.isDone()) {
               return;
             }
             future.completeExceptionally(new TimeoutIOException(timeoutMsg.get()));
           },
           timeoutNs,
           TimeUnit.NANOSECONDS);
   return future.whenComplete(
       (loc, error) -> {
         if (error != null && error.getClass() != TimeoutIOException.class) {
           // cancel timeout task if we are not completed by it.
           timeoutTask.cancel();
         }
       });
 }
  /** Returns the server-side annotations that should be added to a Zipkin span. */
  protected List<KeyValueAnnotation> annotations(ServiceRequestContext ctx, RequestLog req, O res) {

    final List<KeyValueAnnotation> annotations = new ArrayList<>(5);

    final StringBuilder uriBuilder = new StringBuilder();
    uriBuilder.append(req.scheme().uriText());
    uriBuilder.append("://");
    uriBuilder.append(req.host());
    uriBuilder.append(ctx.path());
    if (req.method() != null) {
      uriBuilder.append('#');
      uriBuilder.append(req.method());
    }
    annotations.add(KeyValueAnnotation.create("server.uri", uriBuilder.toString()));

    if (ctx.remoteAddress() != null) {
      annotations.add(KeyValueAnnotation.create("server.remote", ctx.remoteAddress().toString()));
    }

    if (ctx.localAddress() != null) {
      annotations.add(KeyValueAnnotation.create("server.local", ctx.localAddress().toString()));
    }

    final CompletableFuture<?> f = res.closeFuture();
    if (f.isDone()) {
      // Need to use a callback because CompletableFuture does not have a getter for the cause of
      // failure.
      // The callback will be invoked immediately because the future is done already.
      f.handle(
              voidFunction(
                  (result, cause) -> {
                    final String resultText = cause == null ? "success" : "failure";
                    annotations.add(KeyValueAnnotation.create("server.result", resultText));

                    if (cause != null) {
                      annotations.add(KeyValueAnnotation.create("server.cause", cause.toString()));
                    }
                  }))
          .exceptionally(CompletionActions::log);
    }

    return annotations;
  }
Beispiel #8
0
  @Test
  public void testAllPrimitivesAndStack() throws IllegalAccessException, InstantiationException {
    PrimitiveUser4 a = new PrimitiveUser4();

    CompletableFuture<String> blocker = new CompletableFuture<>();

    Random r = new Random();
    int i1 = r.nextInt();
    short s1 = (short) r.nextInt();
    byte b1 = (byte) r.nextInt();
    double d1 = r.nextDouble();
    char c1 = (char) r.nextInt();
    boolean z1 = r.nextBoolean();
    long g1 = r.nextLong();
    Object o1 = new Object();
    float f1 = r.nextFloat();

    final CompletableFuture<Object> res = a.melange(i1, s1, b1, d1, c1, z1, g1, o1, f1, blocker, 0);
    assertFalse(res.isDone());
    blocker.complete("x");
    assertEquals(":", res.join());
    a.assertFields(i1, s1, b1, d1, c1, z1, g1, o1, f1);
  }
 /** Determines if all items have been returned to the client. */
 public boolean allItemsAvailable() {
   return readCompleted.isDone();
 }
Beispiel #10
0
  private static void test(ExecutorService executor) throws Throwable {

    Thread.currentThread().setName("mainThread");

    // ----------------------------------------------------------------
    // supplyAsync tests
    // ----------------------------------------------------------------
    try {
      CompletableFuture<String> cf = supplyAsync(() -> "a test string");
      checkCompletedNormally(cf, cf.join());
      cf = supplyAsync(() -> "a test string", commonPool());
      checkCompletedNormally(cf, cf.join());
      cf = supplyAsync(() -> "a test string", executor);
      checkCompletedNormally(cf, cf.join());
      cf =
          supplyAsync(
              () -> {
                throw new RuntimeException();
              });
      checkCompletedExceptionally(cf);
      cf =
          supplyAsync(
              () -> {
                throw new RuntimeException();
              },
              commonPool());
      checkCompletedExceptionally(cf);
      cf =
          supplyAsync(
              () -> {
                throw new RuntimeException();
              },
              executor);
      checkCompletedExceptionally(cf);
    } catch (Throwable t) {
      unexpected(t);
    }

    // ----------------------------------------------------------------
    // runAsync tests
    // ----------------------------------------------------------------
    try {
      CompletableFuture<Void> cf = runAsync(() -> {});
      checkCompletedNormally(cf, cf.join());
      cf = runAsync(() -> {}, commonPool());
      checkCompletedNormally(cf, cf.join());
      cf = runAsync(() -> {}, executor);
      checkCompletedNormally(cf, cf.join());
      cf =
          runAsync(
              () -> {
                throw new RuntimeException();
              });
      checkCompletedExceptionally(cf);
      cf =
          runAsync(
              () -> {
                throw new RuntimeException();
              },
              commonPool());
      checkCompletedExceptionally(cf);
      cf =
          runAsync(
              () -> {
                throw new RuntimeException();
              },
              executor);
      checkCompletedExceptionally(cf);
    } catch (Throwable t) {
      unexpected(t);
    }

    // ----------------------------------------------------------------
    // explicit completion
    // ----------------------------------------------------------------
    try {
      final Phaser phaser = new Phaser(1);
      final int phase = phaser.getPhase();
      CompletableFuture<Integer> cf;
      cf =
          supplyAsync(
              () -> {
                phaser.awaitAdvance(phase);
                return 1;
              });
      cf.complete(2);
      phaser.arrive();
      checkCompletedNormally(cf, 2);

      cf =
          supplyAsync(
              () -> {
                phaser.awaitAdvance(phase + 1);
                return 1;
              });
      cf.completeExceptionally(new Throwable());
      phaser.arrive();
      checkCompletedExceptionally(cf);

      cf =
          supplyAsync(
              () -> {
                phaser.awaitAdvance(phase + 2);
                return 1;
              });
      cf.cancel(true);
      phaser.arrive();
      checkCompletedExceptionally(cf, true);

      cf =
          supplyAsync(
              () -> {
                phaser.awaitAdvance(phase + 3);
                return 1;
              });
      check(cf.getNow(2) == 2);
      phaser.arrive();
      checkCompletedNormally(cf, 1);
      check(cf.getNow(2) == 1);
    } catch (Throwable t) {
      unexpected(t);
    }

    // ----------------------------------------------------------------
    // thenApplyXXX tests
    // ----------------------------------------------------------------
    try {
      CompletableFuture<Integer> cf2;
      CompletableFuture<String> cf1 = supplyAsync(() -> "a test string");
      cf2 =
          cf1.thenApply(
              (x) -> {
                if (x.equals("a test string")) return 1;
                else return 0;
              });
      checkCompletedNormally(cf1, "a test string");
      checkCompletedNormally(cf2, 1);

      cf1 = supplyAsync(() -> "a test string");
      cf2 =
          cf1.thenApplyAsync(
              (x) -> {
                if (x.equals("a test string")) return 1;
                else return 0;
              });
      checkCompletedNormally(cf1, "a test string");
      checkCompletedNormally(cf2, 1);

      cf1 = supplyAsync(() -> "a test string");
      cf2 =
          cf1.thenApplyAsync(
              (x) -> {
                if (x.equals("a test string")) return 1;
                else return 0;
              },
              executor);
      checkCompletedNormally(cf1, "a test string");
      checkCompletedNormally(cf2, 1);

      cf1 =
          supplyAsync(
              () -> {
                throw new RuntimeException();
              });
      cf2 =
          cf1.thenApply(
              (x) -> {
                return 0;
              });
      checkCompletedExceptionally(cf1);
      checkCompletedExceptionally(cf2);

      cf1 =
          supplyAsync(
              () -> {
                throw new RuntimeException();
              });
      cf2 =
          cf1.thenApplyAsync(
              (x) -> {
                return 0;
              });
      checkCompletedExceptionally(cf1);
      checkCompletedExceptionally(cf2);

      cf1 =
          supplyAsync(
              () -> {
                throw new RuntimeException();
              });
      cf2 =
          cf1.thenApplyAsync(
              (x) -> {
                return 0;
              },
              executor);
      checkCompletedExceptionally(cf1);
      checkCompletedExceptionally(cf2);
    } catch (Throwable t) {
      unexpected(t);
    }

    // ----------------------------------------------------------------
    // thenAcceptXXX tests
    // ----------------------------------------------------------------
    try {
      CompletableFuture<Void> cf2;
      int before = atomicInt.get();
      CompletableFuture<String> cf1 = supplyAsync(() -> "a test string");
      cf2 =
          cf1.thenAccept(
              (x) -> {
                if (x.equals("a test string")) {
                  atomicInt.incrementAndGet();
                  return;
                }
                throw new RuntimeException();
              });
      checkCompletedNormally(cf1, "a test string");
      checkCompletedNormally(cf2, null);
      check(atomicInt.get() == (before + 1));

      before = atomicInt.get();
      cf1 = supplyAsync(() -> "a test string");
      cf2 =
          cf1.thenAcceptAsync(
              (x) -> {
                if (x.equals("a test string")) {
                  atomicInt.incrementAndGet();
                  return;
                }
                throw new RuntimeException();
              });
      checkCompletedNormally(cf1, "a test string");
      checkCompletedNormally(cf2, null);
      check(atomicInt.get() == (before + 1));

      before = atomicInt.get();
      cf1 = supplyAsync(() -> "a test string");
      cf2 =
          cf1.thenAcceptAsync(
              (x) -> {
                if (x.equals("a test string")) {
                  atomicInt.incrementAndGet();
                  return;
                }
                throw new RuntimeException();
              },
              executor);
      checkCompletedNormally(cf1, "a test string");
      checkCompletedNormally(cf2, null);
      check(atomicInt.get() == (before + 1));

      before = atomicInt.get();
      cf1 =
          supplyAsync(
              () -> {
                throw new RuntimeException();
              });
      cf2 =
          cf1.thenAccept(
              (x) -> {
                atomicInt.incrementAndGet();
              });
      checkCompletedExceptionally(cf1);
      checkCompletedExceptionally(cf2);
      check(atomicInt.get() == before);

      cf1 =
          supplyAsync(
              () -> {
                throw new RuntimeException();
              });
      cf2 =
          cf1.thenAcceptAsync(
              (x) -> {
                atomicInt.incrementAndGet();
              });
      checkCompletedExceptionally(cf1);
      checkCompletedExceptionally(cf2);
      check(atomicInt.get() == before);

      cf1 =
          supplyAsync(
              () -> {
                throw new RuntimeException();
              });
      cf2 =
          cf1.thenAcceptAsync(
              (x) -> {
                atomicInt.incrementAndGet();
              },
              executor);
      checkCompletedExceptionally(cf1);
      checkCompletedExceptionally(cf2);
      check(atomicInt.get() == before);
    } catch (Throwable t) {
      unexpected(t);
    }

    // ----------------------------------------------------------------
    // thenRunXXX tests
    // ----------------------------------------------------------------
    try {
      CompletableFuture<Void> cf2;
      int before = atomicInt.get();
      CompletableFuture<String> cf1 = supplyAsync(() -> "a test string");
      cf2 =
          cf1.thenRun(
              () -> {
                atomicInt.incrementAndGet();
              });
      checkCompletedNormally(cf1, "a test string");
      checkCompletedNormally(cf2, null);
      check(atomicInt.get() == (before + 1));

      before = atomicInt.get();
      cf1 = supplyAsync(() -> "a test string");
      cf2 =
          cf1.thenRunAsync(
              () -> {
                atomicInt.incrementAndGet();
              });
      checkCompletedNormally(cf1, "a test string");
      checkCompletedNormally(cf2, null);
      check(atomicInt.get() == (before + 1));

      before = atomicInt.get();
      cf1 = supplyAsync(() -> "a test string");
      cf2 =
          cf1.thenRunAsync(
              () -> {
                atomicInt.incrementAndGet();
              },
              executor);
      checkCompletedNormally(cf1, "a test string");
      checkCompletedNormally(cf2, null);
      check(atomicInt.get() == (before + 1));

      before = atomicInt.get();
      cf1 =
          supplyAsync(
              () -> {
                throw new RuntimeException();
              });
      cf2 =
          cf1.thenRun(
              () -> {
                atomicInt.incrementAndGet();
              });
      checkCompletedExceptionally(cf1);
      checkCompletedExceptionally(cf2);
      check(atomicInt.get() == before);

      cf1 =
          supplyAsync(
              () -> {
                throw new RuntimeException();
              });
      cf2 =
          cf1.thenRunAsync(
              () -> {
                atomicInt.incrementAndGet();
              });
      checkCompletedExceptionally(cf1);
      checkCompletedExceptionally(cf2);
      check(atomicInt.get() == before);

      cf1 =
          supplyAsync(
              () -> {
                throw new RuntimeException();
              });
      cf2 =
          cf1.thenRunAsync(
              () -> {
                atomicInt.incrementAndGet();
              },
              executor);
      checkCompletedExceptionally(cf1);
      checkCompletedExceptionally(cf2);
      check(atomicInt.get() == before);
    } catch (Throwable t) {
      unexpected(t);
    }

    // ----------------------------------------------------------------
    // thenCombineXXX tests
    // ----------------------------------------------------------------
    try {
      CompletableFuture<Integer> cf3;
      CompletableFuture<Integer> cf1 = supplyAsync(() -> 1);
      CompletableFuture<Integer> cf2 = supplyAsync(() -> 1);
      cf3 =
          cf1.thenCombine(
              cf2,
              (x, y) -> {
                return x + y;
              });
      checkCompletedNormally(cf1, 1);
      checkCompletedNormally(cf2, 1);
      checkCompletedNormally(cf3, 2);

      cf1 = supplyAsync(() -> 1);
      cf2 = supplyAsync(() -> 1);
      cf3 =
          cf1.thenCombineAsync(
              cf2,
              (x, y) -> {
                return x + y;
              });
      checkCompletedNormally(cf1, 1);
      checkCompletedNormally(cf2, 1);
      checkCompletedNormally(cf3, 2);

      cf1 = supplyAsync(() -> 1);
      cf2 = supplyAsync(() -> 1);
      cf3 =
          cf1.thenCombineAsync(
              cf2,
              (x, y) -> {
                return x + y;
              },
              executor);
      checkCompletedNormally(cf1, 1);
      checkCompletedNormally(cf2, 1);
      checkCompletedNormally(cf3, 2);

      cf1 =
          supplyAsync(
              () -> {
                throw new RuntimeException();
              });
      cf2 = supplyAsync(() -> 1);
      cf3 =
          cf1.thenCombine(
              cf2,
              (x, y) -> {
                return 0;
              });
      checkCompletedExceptionally(cf1);
      checkCompletedNormally(cf2, 1);
      checkCompletedExceptionally(cf3);

      cf1 = supplyAsync(() -> 1);
      cf2 =
          supplyAsync(
              () -> {
                throw new RuntimeException();
              });
      cf3 =
          cf1.thenCombineAsync(
              cf2,
              (x, y) -> {
                return 0;
              });
      checkCompletedNormally(cf1, 1);
      checkCompletedExceptionally(cf2);
      checkCompletedExceptionally(cf3);

      cf1 =
          supplyAsync(
              () -> {
                throw new RuntimeException();
              });
      cf2 =
          supplyAsync(
              () -> {
                throw new RuntimeException();
              });
      cf3 =
          cf1.thenCombineAsync(
              cf2,
              (x, y) -> {
                return 0;
              },
              executor);
      checkCompletedExceptionally(cf1);
      checkCompletedExceptionally(cf2);
      checkCompletedExceptionally(cf3);
    } catch (Throwable t) {
      unexpected(t);
    }

    // ----------------------------------------------------------------
    // thenAcceptBothXXX tests
    // ----------------------------------------------------------------
    try {
      CompletableFuture<Void> cf3;
      int before = atomicInt.get();
      CompletableFuture<Integer> cf1 = supplyAsync(() -> 1);
      CompletableFuture<Integer> cf2 = supplyAsync(() -> 1);
      cf3 =
          cf1.thenAcceptBoth(
              cf2,
              (x, y) -> {
                check(x + y == 2);
                atomicInt.incrementAndGet();
              });
      checkCompletedNormally(cf1, 1);
      checkCompletedNormally(cf2, 1);
      checkCompletedNormally(cf3, null);
      check(atomicInt.get() == (before + 1));

      before = atomicInt.get();
      cf1 = supplyAsync(() -> 1);
      cf2 = supplyAsync(() -> 1);
      cf3 =
          cf1.thenAcceptBothAsync(
              cf2,
              (x, y) -> {
                check(x + y == 2);
                atomicInt.incrementAndGet();
              });
      checkCompletedNormally(cf1, 1);
      checkCompletedNormally(cf2, 1);
      checkCompletedNormally(cf3, null);
      check(atomicInt.get() == (before + 1));

      before = atomicInt.get();
      cf1 = supplyAsync(() -> 1);
      cf2 = supplyAsync(() -> 1);
      cf3 =
          cf1.thenAcceptBothAsync(
              cf2,
              (x, y) -> {
                check(x + y == 2);
                atomicInt.incrementAndGet();
              },
              executor);
      checkCompletedNormally(cf1, 1);
      checkCompletedNormally(cf2, 1);
      checkCompletedNormally(cf3, null);
      check(atomicInt.get() == (before + 1));

      before = atomicInt.get();
      cf1 =
          supplyAsync(
              () -> {
                throw new RuntimeException();
              });
      cf2 = supplyAsync(() -> 1);
      cf3 =
          cf1.thenAcceptBoth(
              cf2,
              (x, y) -> {
                atomicInt.incrementAndGet();
              });
      checkCompletedExceptionally(cf1);
      checkCompletedNormally(cf2, 1);
      checkCompletedExceptionally(cf3);
      check(atomicInt.get() == before);

      cf1 = supplyAsync(() -> 1);
      cf2 =
          supplyAsync(
              () -> {
                throw new RuntimeException();
              });
      cf3 =
          cf1.thenAcceptBothAsync(
              cf2,
              (x, y) -> {
                atomicInt.incrementAndGet();
              });
      checkCompletedNormally(cf1, 1);
      checkCompletedExceptionally(cf2);
      checkCompletedExceptionally(cf3);
      check(atomicInt.get() == before);

      cf1 =
          supplyAsync(
              () -> {
                throw new RuntimeException();
              });
      cf2 =
          supplyAsync(
              () -> {
                throw new RuntimeException();
              });
      cf3 =
          cf1.thenAcceptBothAsync(
              cf2,
              (x, y) -> {
                atomicInt.incrementAndGet();
              },
              executor);
      checkCompletedExceptionally(cf1);
      checkCompletedExceptionally(cf2);
      checkCompletedExceptionally(cf3);
      check(atomicInt.get() == before);
    } catch (Throwable t) {
      unexpected(t);
    }

    // ----------------------------------------------------------------
    // runAfterBothXXX tests
    // ----------------------------------------------------------------
    try {
      CompletableFuture<Void> cf3;
      int before = atomicInt.get();
      CompletableFuture<Integer> cf1 = supplyAsync(() -> 1);
      CompletableFuture<Integer> cf2 = supplyAsync(() -> 1);
      cf3 =
          cf1.runAfterBoth(
              cf2,
              () -> {
                check(cf1.isDone());
                check(cf2.isDone());
                atomicInt.incrementAndGet();
              });
      checkCompletedNormally(cf1, 1);
      checkCompletedNormally(cf2, 1);
      checkCompletedNormally(cf3, null);
      check(atomicInt.get() == (before + 1));

      before = atomicInt.get();
      CompletableFuture<Integer> cfa = supplyAsync(() -> 1);
      CompletableFuture<Integer> cfb = supplyAsync(() -> 1);
      cf3 =
          cfa.runAfterBothAsync(
              cfb,
              () -> {
                check(cfa.isDone());
                check(cfb.isDone());
                atomicInt.incrementAndGet();
              });
      checkCompletedNormally(cfa, 1);
      checkCompletedNormally(cfb, 1);
      checkCompletedNormally(cf3, null);
      check(atomicInt.get() == (before + 1));

      before = atomicInt.get();
      CompletableFuture<Integer> cfx = supplyAsync(() -> 1);
      CompletableFuture<Integer> cfy = supplyAsync(() -> 1);
      cf3 =
          cfy.runAfterBothAsync(
              cfx,
              () -> {
                check(cfx.isDone());
                check(cfy.isDone());
                atomicInt.incrementAndGet();
              },
              executor);
      checkCompletedNormally(cfx, 1);
      checkCompletedNormally(cfy, 1);
      checkCompletedNormally(cf3, null);
      check(atomicInt.get() == (before + 1));

      before = atomicInt.get();
      CompletableFuture<Integer> cf4 =
          supplyAsync(
              () -> {
                throw new RuntimeException();
              });
      CompletableFuture<Integer> cf5 = supplyAsync(() -> 1);
      cf3 =
          cf5.runAfterBothAsync(
              cf4,
              () -> {
                atomicInt.incrementAndGet();
              },
              executor);
      checkCompletedExceptionally(cf4);
      checkCompletedNormally(cf5, 1);
      checkCompletedExceptionally(cf3);
      check(atomicInt.get() == before);

      before = atomicInt.get();
      cf4 = supplyAsync(() -> 1);
      cf5 =
          supplyAsync(
              () -> {
                throw new RuntimeException();
              });
      cf3 =
          cf5.runAfterBothAsync(
              cf4,
              () -> {
                atomicInt.incrementAndGet();
              });
      checkCompletedNormally(cf4, 1);
      checkCompletedExceptionally(cf5);
      checkCompletedExceptionally(cf3);
      check(atomicInt.get() == before);

      before = atomicInt.get();
      cf4 =
          supplyAsync(
              () -> {
                throw new RuntimeException();
              });
      cf5 =
          supplyAsync(
              () -> {
                throw new RuntimeException();
              });
      cf3 =
          cf5.runAfterBoth(
              cf4,
              () -> {
                atomicInt.incrementAndGet();
              });
      checkCompletedExceptionally(cf4);
      checkCompletedExceptionally(cf5);
      checkCompletedExceptionally(cf3);
      check(atomicInt.get() == before);
    } catch (Throwable t) {
      unexpected(t);
    }

    // ----------------------------------------------------------------
    // applyToEitherXXX tests
    // ----------------------------------------------------------------
    try {
      CompletableFuture<Integer> cf3;
      CompletableFuture<Integer> cf1 = supplyAsync(() -> 1);
      CompletableFuture<Integer> cf2 = supplyAsync(() -> 2);
      cf3 =
          cf1.applyToEither(
              cf2,
              (x) -> {
                check(x == 1 || x == 2);
                return x;
              });
      checkCompletedNormally(cf3, new Object[] {1, 2});
      check(cf1.isDone() || cf2.isDone());

      cf1 = supplyAsync(() -> 1);
      cf2 = supplyAsync(() -> 2);
      cf3 =
          cf1.applyToEitherAsync(
              cf2,
              (x) -> {
                check(x == 1 || x == 2);
                return x;
              });
      checkCompletedNormally(cf3, new Object[] {1, 2});
      check(cf1.isDone() || cf2.isDone());

      cf1 = supplyAsync(() -> 1);
      cf2 = supplyAsync(() -> 2);
      cf3 =
          cf1.applyToEitherAsync(
              cf2,
              (x) -> {
                check(x == 1 || x == 2);
                return x;
              },
              executor);
      checkCompletedNormally(cf3, new Object[] {1, 2});
      check(cf1.isDone() || cf2.isDone());

      cf1 =
          supplyAsync(
              () -> {
                throw new RuntimeException();
              });
      cf2 = supplyAsync(() -> 2);
      cf3 =
          cf1.applyToEither(
              cf2,
              (x) -> {
                check(x == 2);
                return x;
              });
      try {
        check(cf3.join() == 2);
      } catch (CompletionException x) {
        pass();
      }
      check(cf3.isDone());
      check(cf1.isDone() || cf2.isDone());

      cf1 = supplyAsync(() -> 1);
      cf2 =
          supplyAsync(
              () -> {
                throw new RuntimeException();
              });
      cf3 =
          cf1.applyToEitherAsync(
              cf2,
              (x) -> {
                check(x == 1);
                return x;
              });
      try {
        check(cf3.join() == 1);
      } catch (CompletionException x) {
        pass();
      }
      check(cf3.isDone());
      check(cf1.isDone() || cf2.isDone());

      cf1 =
          supplyAsync(
              () -> {
                throw new RuntimeException();
              });
      cf2 =
          supplyAsync(
              () -> {
                throw new RuntimeException();
              });
      cf3 =
          cf1.applyToEitherAsync(
              cf2,
              (x) -> {
                fail();
                return x;
              });
      checkCompletedExceptionally(cf3);
      check(cf1.isDone() || cf2.isDone());

      final Phaser cf3Done = new Phaser(2);
      cf1 =
          supplyAsync(
              () -> {
                cf3Done.arriveAndAwaitAdvance();
                return 1;
              });
      cf2 = supplyAsync(() -> 2);
      cf3 =
          cf1.applyToEither(
              cf2,
              (x) -> {
                check(x == 2);
                return x;
              });
      checkCompletedNormally(cf3, 2);
      checkCompletedNormally(cf2, 2);
      check(!cf1.isDone());
      cf3Done.arrive();
      checkCompletedNormally(cf1, 1);
      checkCompletedNormally(cf3, 2);

      cf1 = supplyAsync(() -> 1);
      cf2 =
          supplyAsync(
              () -> {
                cf3Done.arriveAndAwaitAdvance();
                return 2;
              });
      cf3 =
          cf1.applyToEitherAsync(
              cf2,
              (x) -> {
                check(x == 1);
                return x;
              });
      checkCompletedNormally(cf3, 1);
      checkCompletedNormally(cf1, 1);
      check(!cf2.isDone());
      cf3Done.arrive();
      checkCompletedNormally(cf2, 2);
      checkCompletedNormally(cf3, 1);
    } catch (Throwable t) {
      unexpected(t);
    }

    // ----------------------------------------------------------------
    // acceptEitherXXX tests
    // ----------------------------------------------------------------
    try {
      CompletableFuture<Void> cf3;
      int before = atomicInt.get();
      CompletableFuture<Integer> cf1 = supplyAsync(() -> 1);
      CompletableFuture<Integer> cf2 = supplyAsync(() -> 2);
      cf3 =
          cf1.acceptEither(
              cf2,
              (x) -> {
                check(x == 1 || x == 2);
                atomicInt.incrementAndGet();
              });
      checkCompletedNormally(cf3, null);
      check(cf1.isDone() || cf2.isDone());
      check(atomicInt.get() == (before + 1));

      before = atomicInt.get();
      cf1 = supplyAsync(() -> 1);
      cf2 = supplyAsync(() -> 2);
      cf3 =
          cf1.acceptEitherAsync(
              cf2,
              (x) -> {
                check(x == 1 || x == 2);
                atomicInt.incrementAndGet();
              });
      checkCompletedNormally(cf3, null);
      check(cf1.isDone() || cf2.isDone());
      check(atomicInt.get() == (before + 1));

      before = atomicInt.get();
      cf1 = supplyAsync(() -> 1);
      cf2 = supplyAsync(() -> 2);
      cf3 =
          cf2.acceptEitherAsync(
              cf1,
              (x) -> {
                check(x == 1 || x == 2);
                atomicInt.incrementAndGet();
              },
              executor);
      checkCompletedNormally(cf3, null);
      check(cf1.isDone() || cf2.isDone());
      check(atomicInt.get() == (before + 1));

      cf1 =
          supplyAsync(
              () -> {
                throw new RuntimeException();
              });
      cf2 = supplyAsync(() -> 2);
      cf3 =
          cf2.acceptEitherAsync(
              cf1,
              (x) -> {
                check(x == 2);
              },
              executor);
      try {
        check(cf3.join() == null);
      } catch (CompletionException x) {
        pass();
      }
      check(cf3.isDone());
      check(cf1.isDone() || cf2.isDone());

      cf1 = supplyAsync(() -> 1);
      cf2 =
          supplyAsync(
              () -> {
                throw new RuntimeException();
              });
      cf3 =
          cf2.acceptEitherAsync(
              cf1,
              (x) -> {
                check(x == 1);
              });
      try {
        check(cf3.join() == null);
      } catch (CompletionException x) {
        pass();
      }
      check(cf3.isDone());
      check(cf1.isDone() || cf2.isDone());

      cf1 =
          supplyAsync(
              () -> {
                throw new RuntimeException();
              });
      cf2 =
          supplyAsync(
              () -> {
                throw new RuntimeException();
              });
      cf3 =
          cf2.acceptEitherAsync(
              cf1,
              (x) -> {
                fail();
              });
      checkCompletedExceptionally(cf3);
      check(cf1.isDone() || cf2.isDone());

      final Phaser cf3Done = new Phaser(2);
      cf1 =
          supplyAsync(
              () -> {
                cf3Done.arriveAndAwaitAdvance();
                return 1;
              });
      cf2 = supplyAsync(() -> 2);
      cf3 =
          cf1.acceptEither(
              cf2,
              (x) -> {
                check(x == 2);
              });
      checkCompletedNormally(cf3, null);
      checkCompletedNormally(cf2, 2);
      check(!cf1.isDone());
      cf3Done.arrive();
      checkCompletedNormally(cf1, 1);
      checkCompletedNormally(cf3, null);

      cf1 = supplyAsync(() -> 1);
      cf2 =
          supplyAsync(
              () -> {
                cf3Done.arriveAndAwaitAdvance();
                return 2;
              });
      cf3 =
          cf1.acceptEitherAsync(
              cf2,
              (x) -> {
                check(x == 1);
              });
      checkCompletedNormally(cf3, null);
      checkCompletedNormally(cf1, 1);
      check(!cf2.isDone());
      cf3Done.arrive();
      checkCompletedNormally(cf2, 2);
      checkCompletedNormally(cf3, null);
    } catch (Throwable t) {
      unexpected(t);
    }

    // ----------------------------------------------------------------
    // runAfterEitherXXX tests
    // ----------------------------------------------------------------
    try {
      CompletableFuture<Void> cf3;
      int before = atomicInt.get();
      CompletableFuture<Void> cf1 = runAsync(() -> {});
      CompletableFuture<Void> cf2 = runAsync(() -> {});
      cf3 =
          cf1.runAfterEither(
              cf2,
              () -> {
                atomicInt.incrementAndGet();
              });
      checkCompletedNormally(cf3, null);
      check(cf1.isDone() || cf2.isDone());
      check(atomicInt.get() == (before + 1));

      before = atomicInt.get();
      cf1 = runAsync(() -> {});
      cf2 = runAsync(() -> {});
      cf3 =
          cf1.runAfterEitherAsync(
              cf2,
              () -> {
                atomicInt.incrementAndGet();
              });
      checkCompletedNormally(cf3, null);
      check(cf1.isDone() || cf2.isDone());
      check(atomicInt.get() == (before + 1));

      before = atomicInt.get();
      cf1 = runAsync(() -> {});
      cf2 = runAsync(() -> {});
      cf3 =
          cf2.runAfterEitherAsync(
              cf1,
              () -> {
                atomicInt.incrementAndGet();
              },
              executor);
      checkCompletedNormally(cf3, null);
      check(cf1.isDone() || cf2.isDone());
      check(atomicInt.get() == (before + 1));

      before = atomicInt.get();
      cf1 =
          runAsync(
              () -> {
                throw new RuntimeException();
              });
      cf2 = runAsync(() -> {});
      cf3 =
          cf2.runAfterEither(
              cf1,
              () -> {
                atomicInt.incrementAndGet();
              });
      try {
        check(cf3.join() == null);
        check(atomicInt.get() == (before + 1));
      } catch (CompletionException x) {
        pass();
      }
      check(cf3.isDone());
      check(cf1.isDone() || cf2.isDone());

      before = atomicInt.get();
      cf1 = runAsync(() -> {});
      cf2 =
          runAsync(
              () -> {
                throw new RuntimeException();
              });
      cf3 =
          cf1.runAfterEitherAsync(
              cf2,
              () -> {
                atomicInt.incrementAndGet();
              });
      try {
        check(cf3.join() == null);
        check(atomicInt.get() == (before + 1));
      } catch (CompletionException x) {
        pass();
      }
      check(cf3.isDone());
      check(cf1.isDone() || cf2.isDone());

      before = atomicInt.get();
      cf1 =
          runAsync(
              () -> {
                throw new RuntimeException();
              });
      cf2 =
          runAsync(
              () -> {
                throw new RuntimeException();
              });
      cf3 =
          cf2.runAfterEitherAsync(
              cf1,
              () -> {
                atomicInt.incrementAndGet();
              },
              executor);
      checkCompletedExceptionally(cf3);
      check(cf1.isDone() || cf2.isDone());
      check(atomicInt.get() == before);

      final Phaser cf3Done = new Phaser(2);
      before = atomicInt.get();
      cf1 =
          runAsync(
              () -> {
                cf3Done.arriveAndAwaitAdvance();
              });
      cf2 = runAsync(() -> {});
      cf3 =
          cf1.runAfterEither(
              cf2,
              () -> {
                atomicInt.incrementAndGet();
              });
      checkCompletedNormally(cf3, null);
      checkCompletedNormally(cf2, null);
      check(!cf1.isDone());
      check(atomicInt.get() == (before + 1));
      cf3Done.arrive();
      checkCompletedNormally(cf1, null);
      checkCompletedNormally(cf3, null);

      before = atomicInt.get();
      cf1 = runAsync(() -> {});
      cf2 =
          runAsync(
              () -> {
                cf3Done.arriveAndAwaitAdvance();
              });
      cf3 =
          cf1.runAfterEitherAsync(
              cf2,
              () -> {
                atomicInt.incrementAndGet();
              });
      checkCompletedNormally(cf3, null);
      checkCompletedNormally(cf1, null);
      check(!cf2.isDone());
      check(atomicInt.get() == (before + 1));
      cf3Done.arrive();
      checkCompletedNormally(cf2, null);
      checkCompletedNormally(cf3, null);
    } catch (Throwable t) {
      unexpected(t);
    }

    // ----------------------------------------------------------------
    // thenComposeXXX tests
    // ----------------------------------------------------------------
    try {
      CompletableFuture<Integer> cf2;
      CompletableFuture<Integer> cf1 = supplyAsync(() -> 1);
      cf2 =
          cf1.thenCompose(
              (x) -> {
                check(x == 1);
                return CompletableFuture.completedFuture(2);
              });
      checkCompletedNormally(cf1, 1);
      checkCompletedNormally(cf2, 2);

      cf1 = supplyAsync(() -> 1);
      cf2 =
          cf1.thenComposeAsync(
              (x) -> {
                check(x == 1);
                return CompletableFuture.completedFuture(2);
              });
      checkCompletedNormally(cf1, 1);
      checkCompletedNormally(cf2, 2);

      cf1 = supplyAsync(() -> 1);
      cf2 =
          cf1.thenComposeAsync(
              (x) -> {
                check(x == 1);
                return CompletableFuture.completedFuture(2);
              },
              executor);
      checkCompletedNormally(cf1, 1);
      checkCompletedNormally(cf2, 2);

      int before = atomicInt.get();
      cf1 =
          supplyAsync(
              () -> {
                throw new RuntimeException();
              });
      cf2 =
          cf1.thenCompose(
              (x) -> {
                atomicInt.incrementAndGet();
                return CompletableFuture.completedFuture(2);
              });
      checkCompletedExceptionally(cf1);
      checkCompletedExceptionally(cf2);
      check(atomicInt.get() == before);

      cf1 =
          supplyAsync(
              () -> {
                throw new RuntimeException();
              });
      cf2 =
          cf1.thenComposeAsync(
              (x) -> {
                atomicInt.incrementAndGet();
                return CompletableFuture.completedFuture(2);
              });
      checkCompletedExceptionally(cf1);
      checkCompletedExceptionally(cf2);
      check(atomicInt.get() == before);

      cf1 = supplyAsync(() -> 1);
      cf2 =
          cf1.thenComposeAsync(
              (x) -> {
                throw new RuntimeException();
              },
              executor);
      checkCompletedNormally(cf1, 1);
      checkCompletedExceptionally(cf2);
    } catch (Throwable t) {
      unexpected(t);
    }

    // ----------------------------------------------------------------
    // anyOf tests
    // ----------------------------------------------------------------
    try {
      CompletableFuture<Object> cf3;
      for (int k = 0; k < 10; k++) {
        CompletableFuture<Integer> cf1 = supplyAsync(() -> 1);
        CompletableFuture<Integer> cf2 = supplyAsync(() -> 2);
        cf3 = CompletableFuture.anyOf(cf1, cf2);
        checkCompletedNormally(cf3, new Object[] {1, 2});
        check(cf1.isDone() || cf2.isDone());
      }
    } catch (Throwable t) {
      unexpected(t);
    }

    // ----------------------------------------------------------------
    // allOf tests
    // ----------------------------------------------------------------
    try {
      CompletableFuture<?> cf3;
      for (int k = 0; k < 10; k++) {
        CompletableFuture<Integer>[] cfs =
            (CompletableFuture<Integer>[]) Array.newInstance(CompletableFuture.class, 10);
        for (int j = 0; j < 10; j++) {
          final int v = j;
          cfs[j] = supplyAsync(() -> v);
        }
        cf3 = CompletableFuture.allOf(cfs);
        for (int j = 0; j < 10; j++) checkCompletedNormally(cfs[j], j);
        checkCompletedNormally(cf3, null);
      }
    } catch (Throwable t) {
      unexpected(t);
    }

    // ----------------------------------------------------------------
    // exceptionally tests
    // ----------------------------------------------------------------
    try {
      CompletableFuture<Integer> cf2;
      CompletableFuture<Integer> cf1 = supplyAsync(() -> 1);
      cf2 =
          cf1.exceptionally(
              (t) -> {
                fail("function should never be called");
                return 2;
              });
      checkCompletedNormally(cf1, 1);
      checkCompletedNormally(cf2, 1);

      final RuntimeException t = new RuntimeException();
      cf1 =
          supplyAsync(
              () -> {
                throw t;
              });
      cf2 =
          cf1.exceptionally(
              (x) -> {
                check(x.getCause() == t);
                return 2;
              });
      checkCompletedExceptionally(cf1);
      checkCompletedNormally(cf2, 2);
    } catch (Throwable t) {
      unexpected(t);
    }

    // ----------------------------------------------------------------
    // handle tests
    // ----------------------------------------------------------------
    try {
      CompletableFuture<Integer> cf2;
      CompletableFuture<Integer> cf1 = supplyAsync(() -> 1);
      cf2 = cf1.handle((x, t) -> x + 1);
      checkCompletedNormally(cf1, 1);
      checkCompletedNormally(cf2, 2);

      final RuntimeException ex = new RuntimeException();
      cf1 =
          supplyAsync(
              () -> {
                throw ex;
              });
      cf2 =
          cf1.handle(
              (x, t) -> {
                check(t.getCause() == ex);
                return 2;
              });
      checkCompletedExceptionally(cf1);
      checkCompletedNormally(cf2, 2);
    } catch (Throwable t) {
      unexpected(t);
    }
  }
Beispiel #11
0
 @Test
 public void shouldConvertSuccessToCompletableFuture() {
   CompletableFuture<String> future = success().toCompletableFuture();
   assertThat(future.isDone());
   assertThat(Try.of(future::get).get()).isEqualTo(success().get());
 }