package jetbrains.jetpad.base;

import org.junit.Test;

import java.util.ConcurrentModificationException;

public class SimpleAsyncRegistrationsTest {
  private SimpleAsync<Void> async = new SimpleAsync<>();

  @Test
  public void removeSuccessRegistration() {
    Registration reg = async.onSuccess(throwingHandler());
    reg.remove();
    async.success(null);
  }

  @Test
  public void removeFailureRegistration() {
    Registration reg = async.onFailure(throwingFailureHandler());
    reg.remove();
    async.failure(null);
  }

  @Test
  public void removeCompositeRegistration1() {
    Registration reg = async.onResult(throwingHandler(), throwingFailureHandler());
    reg.remove();
    async.success(null);
  }

  @Test
  public void removeCompositeRegistration2() {
    Registration reg = async.onResult(throwingHandler(), throwingFailureHandler());
    reg.remove();
    async.failure(null);
  }

  @Test(expected = ConcurrentModificationException.class)
  public void removeRegistrationInSuccessHandler() {
    final Value<Registration> regValue = new Value<>();
    Registration reg = async.onSuccess(new Handler<Void>() {
      @Override
      public void handle(Void item) {
        regValue.get().remove();
      }
    });
    regValue.set(reg);
    async.success(null);
  }

  @Test(expected = ConcurrentModificationException.class)
  public void removeRegistrationInFailureHandler() {
    final Value<Registration> regValue = new Value<>();
    Registration reg = async.onFailure(new Handler<Throwable>() {
      @Override
      public void handle(Throwable item) {
        regValue.get().remove();
      }
    });
    regValue.set(reg);
    async.failure(null);
  }

  @Test
  public void addSuccessHandlerAfterFailure() {
    async.failure(new Throwable());
    Registration reg = async.onSuccess(new Handler<Void>() {
      @Override
      public void handle(Void item) {
      }
    });
    reg.remove();
  }

  @Test
  public void addFailureHandlerAfterSuccess() {
    async.success(null);
    Registration reg = async.onFailure(new Handler<Throwable>() {
      @Override
      public void handle(Throwable item) {
      }
    });
    reg.remove();
  }

  private Handler<Throwable> throwingFailureHandler() {
    return throwingHandler();
  }

  private <ItemT> Handler<ItemT> throwingHandler() {
    return new Handler<ItemT>() {
      @Override
      public void handle(ItemT item) {
        throw new RuntimeException();
      }
    };
  }
}

@@ -2162,32 +2162,1024 @@
 .remove();%0A  %7D%0A%0A
+  @Test%0A  public void removeSuccessRegistrationAfterSuccess() %7B%0A    Registration reg = async.onSuccess(new Handler%3CVoid%3E() %7B%0A      @Override%0A      public void handle(Void item) %7B%0A      %7D%0A    %7D);%0A    async.success(null);%0A    reg.remove();%0A  %7D%0A%0A  @Test%0A  public void removeSuccessRegistrationAfterFailure() %7B%0A    Registration reg = async.onSuccess(new Handler%3CVoid%3E() %7B%0A      @Override%0A      public void handle(Void item) %7B%0A      %7D%0A    %7D);%0A    async.failure(null);%0A    reg.remove();%0A  %7D%0A%0A  @Test%0A  public void removeFailureRegistrationAfterSuccess() %7B%0A    Registration reg = async.onFailure(new Handler%3CThrowable%3E() %7B%0A      @Override%0A      public void handle(Throwable item) %7B%0A      %7D%0A    %7D);%0A    async.success(null);%0A    reg.remove();%0A  %7D%0A%0A  @Test%0A  public void removeFailureRegistrationAfterFailure() %7B%0A    Registration reg = async.onFailure(new Handler%3CThrowable%3E() %7B%0A      @Override%0A      public void handle(Throwable item) %7B%0A      %7D%0A    %7D);%0A    async.failure(null);%0A    reg.remove();%0A  %7D%0A%0A
   private Handle

add tests on registration removal after SimpleAsync handled