package jetbrains.jetpad.base;

import jetbrains.jetpad.base.function.Predicate;

public class Asserts {
  public static void assertSuccess(Async<Void> async) {
    assertSuccessValue(null, async);
  }

  public static <T> void assertSuccessValue(T expected, Async<T> async) {
    T value = Asyncs.get(async);
    if (value == null) {
      if (expected != null) {
        throw new AssertionError("Expected: " + expected + ", but got: " + value);
      }
    } else if (!value.equals(expected)) {
      throw new AssertionError("Expected: " + expected + ", but got: " + value);
    }
  }

  public static <T> void assertSuccess(Predicate<T> assertion, Async<T> async) {
    T value = Asyncs.get(async);
    if (!assertion.test(value)) {
      throw new AssertionError("succes value failed assertion: " + value);
    }
  }

  public static void assertFailure(Class<? extends Throwable> expected, Async<?> async) {
    try {
      Asyncs.get(async);
      throw new AssertionError("Async expected to fail: " + async);
    } catch (Throwable t) {
      if (!expected.isAssignableFrom(t.getClass())) {
        throw new AssertionError("Async failed with unexpected exception expected=" + expected + ", exception=" + t);
      }
    }
  }

  private Asserts() { }
}

@@ -25,16 +25,64 @@
 .base;%0A%0A
+import jetbrains.jetpad.base.function.Consumer;%0A
 import j
@@ -153,32 +153,36 @@
 %0A  public static
+ %3CT%3E
  void assertSucc
@@ -195,12 +195,9 @@
 ync%3C
-Void
+T
 %3E as
@@ -224,18 +224,117 @@
 cess
-Value(null
+(new Predicate%3CT%3E() %7B%0A      @Override%0A      public boolean test(T value) %7B%0A        return true;%0A      %7D%0A    %7D
 , as
@@ -428,34 +428,41 @@
   T value = 
-Asyncs.get
+getSucceededValue
 (async);%0A   
@@ -833,26 +833,33 @@
 value = 
-Asyncs.get
+getSucceededValue
 (async);
@@ -1018,196 +1018,398 @@
 ure(
-Class%3C? extends Throwable%3E expected, Async%3C?%3E async) %7B%0A    try %7B%0A      Asyncs.get(async);%0A      throw new AssertionError(%22Async expected to fail: %22 + async);%0A    %7D catch (Throwable t) %7B%0A  
+Async%3C?%3E async) %7B%0A    assertFailure(Throwable.class, async);%0A  %7D%0A%0A  public static void assertFailure(Class%3C? extends Throwable%3E expected, Async%3C?%3E async) %7B%0A    AsyncResult%3C?%3E result = getResult(async);%0A    if (result.state != AsyncState.FAILED) %7B%0A      throw new AssertionError(%22Async expected to succeed: async=%22 + async + %22, state=%22 + result.state);%0A    %7D%0A    Throwable t = result.error;%0A
     
@@ -1452,26 +1452,24 @@
 Class())) %7B%0A
-  
       throw 
@@ -1580,44 +1580,1290 @@
     
+%7D%0A
   %7D%0A
-    %7D%0A  %7D%0A%0A  private Asserts() %7B
+%0A  private static %3CT%3E T getSucceededValue(Async%3CT%3E async) %7B%0A    AsyncResult%3CT%3E result = getResult(async);%0A    if (result.state != AsyncState.SUCCEEDED) %7B%0A      throw new AssertionError(%22Async expected to succeed: async=%22 + async + %22, state=%22 + result.state);%0A    %7D%0A    return result.value;%0A  %7D%0A%0A  private static %3CT%3E AsyncResult%3CT%3E getResult(Async%3CT%3E async) %7B%0A    final Value%3CAsyncResult%3CT%3E%3E resultValue = new Value%3C%3E(new AsyncResult%3CT%3E(AsyncState.UNFINISHED, null, null));%0A    async.onResult(new Consumer%3CT%3E() %7B%0A      @Override%0A      public void accept(T value) %7B%0A        resultValue.set(new AsyncResult%3C%3E(AsyncState.SUCCEEDED, value, null));%0A      %7D%0A    %7D, new Consumer%3CThrowable%3E() %7B%0A      @Override%0A      public void accept(Throwable throwable) %7B%0A        resultValue.set(new AsyncResult%3CT%3E(AsyncState.FAILED, null, throwable));%0A      %7D%0A    %7D);%0A    return resultValue.get();%0A  %7D%0A%0A  private Asserts() %7B %7D%0A%0A  private static class AsyncResult%3CT%3E %7B%0A    private final AsyncState state;%0A    private final T value;%0A    private final Throwable error;%0A%0A    private AsyncResult(AsyncState state, T value, Throwable error) %7B%0A      this.state = state;%0A      this.value = value;%0A      this.error = error;%0A    %7D%0A  %7D%0A%0A  private enum AsyncState %7B%0A    UNFINISHED,%0A    SUCCEEDED,%0A    FAILED%0A 
  %7D%0A%7D

refactor Asserts utility methods not to hang in case of unfinished async