content: /**
   * Copyright (c) 2016-present, RxJava Contributors.
   *
   * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in
   * compliance with the License. You may obtain a copy of the License at
   *
   * http://www.apache.org/licenses/LICENSE-2.0
   *
   * Unless required by applicable law or agreed to in writing, software distributed under the License is
   * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See
   * the License for the specific language governing permissions and limitations under the License.
   */
  
  package io.reactivex.observable;
  
  import static org.junit.Assert.*;
  
  import java.io.IOException;
  import java.lang.management.*;
  import java.util.*;
  import java.util.concurrent.*;
  import java.util.concurrent.atomic.AtomicInteger;
  
  import org.junit.Test;
  
  import io.reactivex.common.*;
  import io.reactivex.common.exceptions.*;
  import io.reactivex.common.functions.*;
  import io.reactivex.common.internal.functions.Functions;
  import io.reactivex.observable.extensions.QueueDisposable;
  import io.reactivex.observable.internal.operators.*;
  import io.reactivex.observable.observers.*;
  import io.reactivex.observable.subjects.*;
  
  public class MaybeTest {
  
      @Test
      public void fromObservableEmpty() {
  
          Observable.empty()
          .singleElement()
          .test()
          .assertResult();
      }
  
      @Test
      public void fromObservableJust() {
  
          Observable.just(1)
          .singleElement()
          .test()
          .assertResult(1);
      }
  
      @Test
      public void fromObservableError() {
  
          Observable.error(new TestException())
          .singleElement()
          .test()
          .assertFailure(TestException.class);
      }
  
      @Test
      public void fromObservableValueAndError() {
          Observable.just(1).concatWith(Observable.<Integer>error(new TestException()))
          .singleElement()
          .test()
          .assertFailure(TestException.class);
      }
  
      @Test
      public void fromObservableMany() {
  
          Observable.range(1, 2)
          .singleElement()
          .test()
          .assertFailure(IllegalArgumentException.class);
      }
  
      @Test
      public void fromObservableDisposeComposesThrough() {
          PublishSubject<Integer> pp = PublishSubject.create();
  
          TestObserver<Integer> ts = pp.singleElement().test(false);
  
          assertTrue(pp.hasObservers());
  
          ts.cancel();
  
          assertFalse(pp.hasObservers());
      }
  
      @Test
      public void fromObservableDisposeComposesThroughImmediatelyCancelled() {
          PublishSubject<Integer> pp = PublishSubject.create();
  
          pp.singleElement().test(true);
  
          assertFalse(pp.hasObservers());
      }
  
      @Test
      public void just() {
          Maybe.just(1)
          .test()
          .assertResult(1);
      }
  
      @Test(expected = NullPointerException.class)
      public void justNull() {
          Maybe.just(null);
      }
  
      @Test
      public void empty() {
          Maybe.empty()
          .test()
          .assertResult();
      }
  
      @Test
      public void never() {
          Maybe.never()
          .test()
          .assertSubscribed()
          .assertNoValues()
          .assertNoErrors()
          .assertNotComplete();
      }
  
      @Test(expected = NullPointerException.class)
      public void errorNull() {
          Maybe.error((Throwable)null);
      }
  
      @Test(expected = NullPointerException.class)
      public void errorCallableNull() {
          Maybe.error((Callable<Throwable>)null);
      }
  
      @Test
      public void error() {
          Maybe.error(new TestException())
          .test()
          .assertFailure(TestException.class);
      }
  
      @Test
      public void errorCallable() {
          Maybe.error(Functions.justCallable(new TestException()))
          .test()
          .assertFailure(TestException.class);
      }
  
      @Test
      public void errorCallableReturnsNull() {
          Maybe.error(Functions.justCallable((Throwable)null))
          .test()
          .assertFailure(NullPointerException.class);
      }
  
      @Test
      public void wrapCustom() {
          Maybe.wrap(new MaybeSource<Integer>() {
              @Override
              public void subscribe(MaybeObserver<? super Integer> observer) {
                  observer.onSubscribe(Disposables.empty());
                  observer.onSuccess(1);
              }
          })
          .test()
          .assertResult(1);
      }
  
      @Test
      public void wrapMaybe() {
          assertSame(Maybe.empty(), Maybe.wrap(Maybe.empty()));
      }
  
      @Test(expected = NullPointerException.class)
      public void wrapNull() {
          Maybe.wrap(null);
      }
  
      @Test
      public void emptySingleton() {
          assertSame(Maybe.empty(), Maybe.empty());
      }
  
      @Test
      public void neverSingleton() {
          assertSame(Maybe.never(), Maybe.never());
      }
  
      @Test(expected = NullPointerException.class)
      public void liftNull() {
          Maybe.just(1).lift(null);
      }
  
      @Test
      public void liftJust() {
          Maybe.just(1).lift(new MaybeOperator<Integer, Integer>() {
              @Override
              public MaybeObserver<? super Integer> apply(MaybeObserver<? super Integer> t) throws Exception {
                  return t;
              }
          })
          .test()
          .assertResult(1);
      }
  
      @Test
      public void liftThrows() {
          Maybe.just(1).lift(new MaybeOperator<Integer, Integer>() {
              @Override
              public MaybeObserver<? super Integer> apply(MaybeObserver<? super Integer> t) throws Exception {
                  throw new TestException();
              }
          })
          .test()
          .assertFailure(TestException.class);
      }
  
      @Test(expected = NullPointerException.class)
      public void deferNull() {
          Maybe.defer(null);
      }
  
      @Test
      public void deferThrows() {
          Maybe.defer(new Callable<Maybe<Integer>>() {
              @Override
              public Maybe<Integer> call() throws Exception {
                  throw new TestException();
              }
          })
          .test()
          .assertFailure(TestException.class);
      }
  
      @Test
      public void deferReturnsNull() {
          Maybe.defer(new Callable<Maybe<Integer>>() {
              @Override
              public Maybe<Integer> call() throws Exception {
                  return null;
              }
          })
          .test()
          .assertFailure(NullPointerException.class);
      }
  
      @Test
      public void defer() {
          Maybe<Integer> source = Maybe.defer(new Callable<Maybe<Integer>>() {
              int count;
              @Override
              public Maybe<Integer> call() throws Exception {
                  return Maybe.just(count++);
              }
          });
  
          for (int i = 0; i < 128; i++) {
              source.test().assertResult(i);
          }
      }
  
      @Test
      public void obervableMaybeobervable() {
          Observable.just(1).singleElement().toObservable().test().assertResult(1);
      }
  
      @Test
      public void singleMaybeSingle() {
          Single.just(1).toMaybe().toSingle().test().assertResult(1);
      }
  
      @Test
      public void completableMaybeCompletable() {
          Completable.complete().toMaybe().ignoreElement().test().assertResult();
      }
  
  
      @Test
      public void unsafeCreate() {
          Maybe.unsafeCreate(new MaybeSource<Integer>() {
              @Override
              public void subscribe(MaybeObserver<? super Integer> observer) {
                  observer.onSubscribe(Disposables.empty());
                  observer.onSuccess(1);
              }
          })
          .test()
          .assertResult(1);
      }
  
      @Test(expected = NullPointerException.class)
      public void unsafeCreateNull() {
          Maybe.unsafeCreate(null);
      }
  
      @Test
      public void to() {
          Maybe.just(1).to(new Function<Maybe<Integer>, Observable<Integer>>() {
              @Override
              public Observable<Integer> apply(Maybe<Integer> v) throws Exception {
                  return v.toObservable();
              }
          })
          .test()
          .assertResult(1);
      }
  
      @Test(expected = NullPointerException.class)
      public void toNull() {
          Maybe.just(1).to(null);
      }
  
      @Test
      public void compose() {
          Maybe.just(1).compose(new MaybeTransformer<Integer, Integer>() {
              @Override
              public MaybeSource<Integer> apply(Maybe<Integer> m) {
                  return m.map(new Function<Integer, Integer>() {
                      @Override
                      public Integer apply(Integer w) throws Exception {
                          return w + 1;
                      }
                  });
              }
          })
          .test()
          .assertResult(2);
      }
  
      @Test(expected = NullPointerException.class)
      public void composeNull() {
          Maybe.just(1).compose(null);
      }
  
      @Test(expected = NullPointerException.class)
      public void mapNull() {
          Maybe.just(1).map(null);
      }
  
      @Test
      public void mapReturnNull() {
          Maybe.just(1).map(new Function<Integer, Object>() {
              @Override
              public Object apply(Integer v) throws Exception {
                  return null;
              }
          }).test().assertFailure(NullPointerException.class);
      }
  
      @Test
      public void mapThrows() {
          Maybe.just(1).map(new Function<Integer, Object>() {
              @Override
              public Object apply(Integer v) throws Exception {
                  throw new IOException();
              }
          }).test().assertFailure(IOException.class);
      }
  
      @Test
      public void map() {
          Maybe.just(1).map(new Function<Integer, String>() {
              @Override
              public String apply(Integer v) throws Exception {
                  return v.toString();
              }
          }).test().assertResult("1");
      }
  
      @Test(expected = NullPointerException.class)
      public void filterNull() {
          Maybe.just(1).filter(null);
      }
  
      @Test
      public void filterThrows() {
          Maybe.just(1).filter(new Predicate<Integer>() {
              @Override
              public boolean test(Integer v) throws Exception {
                  throw new IOException();
              }
          }).test().assertFailure(IOException.class);
      }
  
      @Test
      public void filterTrue() {
          Maybe.just(1).filter(new Predicate<Integer>() {
              @Override
              public boolean test(Integer v) throws Exception {
                  return v == 1;
              }
          }).test().assertResult(1);
      }
  
      @Test
      public void filterFalse() {
          Maybe.just(2).filter(new Predicate<Integer>() {
              @Override
              public boolean test(Integer v) throws Exception {
                  return v == 1;
              }
          }).test().assertResult();
      }
  
      @Test
      public void filterEmpty() {
          Maybe.<Integer>empty().filter(new Predicate<Integer>() {
              @Override
              public boolean test(Integer v) throws Exception {
                  return v == 1;
              }
          }).test().assertResult();
      }
  
      @Test(expected = NullPointerException.class)
      public void singleFilterNull() {
          Single.just(1).filter(null);
      }
  
      @Test
      public void singleFilterThrows() {
          Single.just(1).filter(new Predicate<Integer>() {
              @Override
              public boolean test(Integer v) throws Exception {
                  throw new IOException();
              }
          }).test().assertFailure(IOException.class);
      }
  
      @Test
      public void singleFilterTrue() {
          Single.just(1).filter(new Predicate<Integer>() {
              @Override
              public boolean test(Integer v) throws Exception {
                  return v == 1;
              }
          }).test().assertResult(1);
      }
  
      @Test
      public void singleFilterFalse() {
          Single.just(2).filter(new Predicate<Integer>() {
              @Override
              public boolean test(Integer v) throws Exception {
                  return v == 1;
              }
          }).test().assertResult();
      }
  
      @Test
      public void cast() {
          TestObserver<Number> ts = Maybe.just(1).cast(Number.class).test();
          // don'n inline this due to the generic type
          ts.assertResult((Number)1);
      }
  
      @Test(expected = NullPointerException.class)
      public void observeOnNull() {
          Maybe.just(1).observeOn(null);
      }
  
      @Test(expected = NullPointerException.class)
      public void subscribeOnNull() {
          Maybe.just(1).observeOn(null);
      }
  
      @Test
      public void observeOnSuccess() {
          String main = Thread.currentThread().getName();
          Maybe.just(1)
          .observeOn(Schedulers.single())
          .map(new Function<Integer, String>() {
              @Override
              public String apply(Integer v) throws Exception {
                  return v + ": " + Thread.currentThread().getName();
              }
          })
          .test()
          .awaitDone(5, TimeUnit.SECONDS)
          .assertOf(TestHelper.observerSingleNot("1: " + main))
          ;
      }
  
      @Test
      public void observeOnError() {
          Maybe.error(new TestException())
          .observeOn(Schedulers.single())
          .test()
          .awaitDone(5, TimeUnit.SECONDS)
          .assertFailure(TestException.class)
          ;
      }
  
      @Test
      public void observeOnComplete() {
          Maybe.empty()
          .observeOn(Schedulers.single())
          .test()
          .awaitDone(5, TimeUnit.SECONDS)
          .assertResult()
          ;
      }
  
      @Test
      public void observeOnDispose2() {
          TestHelper.checkDisposed(Maybe.empty().observeOn(Schedulers.single()));
      }
  
      @Test
      public void observeOnDoubleSubscribe() {
          TestHelper.checkDoubleOnSubscribeMaybe(new Function<Maybe<Object>, MaybeSource<Object>>() {
              @Override
              public MaybeSource<Object> apply(Maybe<Object> m) throws Exception {
                  return m.observeOn(Schedulers.single());
              }
          });
      }
  
      @Test
      public void subscribeOnSuccess() {
          String main = Thread.currentThread().getName();
          Maybe.fromCallable(new Callable<String>() {
              @Override
              public String call() throws Exception {
                  return Thread.currentThread().getName();
              }
          })
          .subscribeOn(Schedulers.single())
          .test()
          .awaitDone(5, TimeUnit.SECONDS)
          .assertOf(TestHelper.observerSingleNot(main))
          ;
      }
  
      @Test
      public void observeOnErrorThread() {
          String main = Thread.currentThread().getName();
  
          final String[] name = { null };
  
          Maybe.error(new TestException()).observeOn(Schedulers.single())
          .doOnError(new Consumer<Throwable>() {
              @Override
              public void accept(Throwable e) throws Exception {
                  name[0] = Thread.currentThread().getName();
              }
          })
          .test()
          .awaitDone(5, TimeUnit.SECONDS)
          .assertFailure(TestException.class)
          ;
  
          assertNotEquals(main, name[0]);
      }
  
  
      @Test
      public void observeOnCompleteThread() {
          String main = Thread.currentThread().getName();
  
          final String[] name = { null };
  
          Maybe.empty().observeOn(Schedulers.single())
          .doOnComplete(new Action() {
              @Override
              public void run() throws Exception {
                  name[0] = Thread.currentThread().getName();
              }
          })
          .test()
          .awaitDone(5, TimeUnit.SECONDS)
          .assertResult()
          ;
  
          assertNotEquals(main, name[0]);
      }
  
      @Test
      public void subscribeOnError() {
          Maybe.error(new TestException())
          .subscribeOn(Schedulers.single())
          .test()
          .awaitDone(5, TimeUnit.SECONDS)
          .assertFailure(TestException.class)
          ;
      }
  
      @Test
      public void subscribeOnComplete() {
          Maybe.empty()
          .subscribeOn(Schedulers.single())
          .test()
          .awaitDone(5, TimeUnit.SECONDS)
          .assertResult()
          ;
      }
  
  
      @Test
      public void fromAction() {
          final int[] call = { 0 };
  
          Maybe.fromAction(new Action() {
              @Override
              public void run() throws Exception {
                  call[0]++;
              }
          })
          .test()
          .assertResult();
  
          assertEquals(1, call[0]);
      }
  
      @Test
      public void fromActionThrows() {
          Maybe.fromAction(new Action() {
              @Override
              public void run() throws Exception {
                  throw new TestException();
              }
          })
          .test()
          .assertFailure(TestException.class);
      }
  
      @Test
      public void fromRunnable() {
          final int[] call = { 0 };
  
          Maybe.fromRunnable(new Runnable() {
              @Override
              public void run() {
                  call[0]++;
              }
          })
          .test()
          .assertResult();
  
          assertEquals(1, call[0]);
      }
  
      @Test
      public void fromRunnableThrows() {
          Maybe.fromRunnable(new Runnable() {
              @Override
              public void run() {
                  throw new TestException();
              }
          })
          .test()
          .assertFailure(TestException.class);
      }
  
      @Test
      public void fromCallableThrows() {
          Maybe.fromCallable(new Callable<Object>() {
              @Override
              public Object call() throws Exception {
                  throw new TestException();
              }
          })
          .test()
          .assertFailure(TestException.class);
      }
  
      @Test
      public void doOnSuccess() {
          final Integer[] value = { null };
  
          Maybe.just(1).doOnSuccess(new Consumer<Integer>() {
              @Override
              public void accept(Integer v) throws Exception {
                  value[0] = v;
              }
          })
          .test()
          .assertResult(1);
  
          assertEquals(1, value[0].intValue());
      }
  
      @Test
      public void doOnSuccessEmpty() {
          final Integer[] value = { null };
  
          Maybe.<Integer>empty().doOnSuccess(new Consumer<Integer>() {
              @Override
              public void accept(Integer v) throws Exception {
                  value[0] = v;
              }
          })
          .test()
          .assertResult();
  
          assertNull(value[0]);
      }
  
      @Test
      public void doOnSuccessThrows() {
          Maybe.just(1).doOnSuccess(new Consumer<Integer>() {
              @Override
              public void accept(Integer v) throws Exception {
                  throw new TestException();
              }
          })
          .test()
          .assertFailure(TestException.class);
      }
  
  
      @Test
      public void doOnSubscribe() {
          final Disposable[] value = { null };
  
          Maybe.just(1).doOnSubscribe(new Consumer<Disposable>() {
              @Override
              public void accept(Disposable v) throws Exception {
                  value[0] = v;
              }
          })
          .test()
          .assertResult(1);
  
          assertNotNull(value[0]);
      }
  
      @Test
      public void doOnSubscribeThrows() {
          Maybe.just(1).doOnSubscribe(new Consumer<Disposable>() {
              @Override
              public void accept(Disposable v) throws Exception {
                  throw new TestException();
              }
          })
          .test()
          .assertFailure(TestException.class);
      }
  
  
      @Test
      public void doOnCompleteThrows() {
          Maybe.empty().doOnComplete(new Action() {
              @Override
              public void run() throws Exception {
                  throw new TestException();
              }
          })
          .test()
          .assertFailure(TestException.class);
      }
  
      @Test
      public void doOnDispose() {
          final int[] call = { 0 };
  
          Maybe.just(1).doOnDispose(new Action() {
              @Override
              public void run() throws Exception {
                  call[0]++;
              }
          })
          .test(true)
          .assertSubscribed()
          .assertNoValues()
          .assertNoErrors()
          .assertNotComplete();
  
          assertEquals(1, call[0]);
      }
  
  
      @Test
      public void doOnDisposeThrows() {
          List<Throwable> list = TestCommonHelper.trackPluginErrors();
  
          try {
              MaybeSubject<Integer> pp = MaybeSubject.create();
  
              TestObserver<Integer> ts = pp.doOnDispose(new Action() {
                  @Override
                  public void run() throws Exception {
                      throw new TestException();
                  }
              })
              .test();
  
              assertTrue(pp.hasObservers());
  
              ts.cancel();
  
              assertFalse(pp.hasObservers());
  
              ts.assertSubscribed()
              .assertNoValues()
              .assertNoErrors()
              .assertNotComplete();
  
              TestCommonHelper.assertUndeliverable(list, 0, TestException.class);
          } finally {
              RxJavaCommonPlugins.reset();
          }
      }
  
      @Test
      public void observeOnDispose() throws Exception {
          final TestObserver<Integer> ts = new TestObserver<Integer>();
  
          final CountDownLatch cdl = new CountDownLatch(1);
  
          Maybe.just(1)
          .observeOn(Schedulers.single())
          .doOnSuccess(new Consumer<Integer>() {
              @Override
              public void accept(Integer v) throws Exception {
                  if (!cdl.await(5, TimeUnit.SECONDS)) {
                      throw new TimeoutException();
                  }
              }
          })
          .subscribe(ts);
  
          Thread.sleep(250);
  
          ts.cancel();
  
          ts.awaitDone(5, TimeUnit.SECONDS)
          .assertFailure(InterruptedException.class);
      }
  
      @Test
      public void doAfterTerminateSuccess() {
          final int[] call = { 0 };
  
          Maybe.just(1)
          .doOnSuccess(new Consumer<Integer>() {
              @Override
              public void accept(Integer v) throws Exception {
                  call[0]++;
              }
          })
          .doAfterTerminate(new Action() {
              @Override
              public void run() throws Exception {
                  if (call[0] == 1) {
                      call[0] = -1;
                  }
              }
          })
          .test()
          .assertResult(1);
  
          assertEquals(-1, call[0]);
      }
  
      @Test
      public void doAfterTerminateError() {
          final int[] call = { 0 };
  
          Maybe.error(new TestException())
          .doOnError(new Consumer<Object>() {
              @Override
              public void accept(Object v) throws Exception {
                  call[0]++;
              }
          })
          .doAfterTerminate(new Action() {
              @Override
              public void run() throws Exception {
                  if (call[0] == 1) {
                      call[0] = -1;
                  }
              }
          })
          .test()
          .assertFailure(TestException.class);
  
          assertEquals(-1, call[0]);
      }
  
  
      @Test
      public void doAfterTerminateComplete() {
          final int[] call = { 0 };
  
          Maybe.empty()
          .doOnComplete(new Action() {
              @Override
              public void run() throws Exception {
                  call[0]++;
              }
          })
          .doAfterTerminate(new Action() {
              @Override
              public void run() throws Exception {
                  if (call[0] == 1) {
                      call[0] = -1;
                  }
              }
          })
          .test()
          .assertResult();
  
          assertEquals(-1, call[0]);
      }
  
      @Test
      public void sourceThrowsNPE() {
          try {
              Maybe.unsafeCreate(new MaybeSource<Object>() {
                  @Override
                  public void subscribe(MaybeObserver<? super Object> s) {
                      throw new NullPointerException("Forced failure");
                  }
              }).test();
  
              fail("Should have thrown!");
          } catch (NullPointerException ex) {
              assertEquals("Forced failure", ex.getMessage());
          }
      }
  
  
      @Test
      public void sourceThrowsIAE() {
          try {
              Maybe.unsafeCreate(new MaybeSource<Object>() {
                  @Override
                  public void subscribe(MaybeObserver<? super Object> s) {
                      throw new IllegalArgumentException("Forced failure");
                  }
              }).test();
  
              fail("Should have thrown!");
          } catch (NullPointerException ex) {
              assertTrue(ex.toString(), ex.getCause() instanceof IllegalArgumentException);
              assertEquals("Forced failure", ex.getCause().getMessage());
          }
      }
  
      @Test
      public void flatMap() {
          Maybe.just(1).flatMap(new Function<Integer, MaybeSource<Integer>>() {
              @Override
              public MaybeSource<Integer> apply(Integer v) throws Exception {
                  return Maybe.just(v * 10);
              }
          })
          .test()
          .assertResult(10);
      }
  
      @Test
      public void concatMap() {
          Maybe.just(1).concatMap(new Function<Integer, MaybeSource<Integer>>() {
              @Override
              public MaybeSource<Integer> apply(Integer v) throws Exception {
                  return Maybe.just(v * 10);
              }
          })
          .test()
          .assertResult(10);
      }
  
      @Test
      public void flatMapEmpty() {
          Maybe.just(1).flatMap(new Function<Integer, MaybeSource<Integer>>() {
              @Override
              public MaybeSource<Integer> apply(Integer v) throws Exception {
                  return Maybe.empty();
              }
          })
          .test()
          .assertResult();
      }
  
      @Test
      public void flatMapError() {
          Maybe.just(1).flatMap(new Function<Integer, MaybeSource<Integer>>() {
              @Override
              public MaybeSource<Integer> apply(Integer v) throws Exception {
                  return Maybe.error(new TestException());
              }
          })
          .test()
          .assertFailure(TestException.class);
      }
  
      @Test
      public void flatMapNotifySuccess() {
          Maybe.just(1)
          .flatMap(new Function<Integer, MaybeSource<Integer>>() {
              @Override
              public MaybeSource<Integer> apply(Integer v) throws Exception {
                  return Maybe.just(v * 10);
              }
          },
          new Function<Throwable, MaybeSource<Integer>>() {
              @Override
              public MaybeSource<Integer> apply(Throwable v) throws Exception {
                  return Maybe.just(100);
              }
          },
  
          new Callable<MaybeSource<Integer>>() {
              @Override
              public MaybeSource<Integer> call() throws Exception {
                  return Maybe.just(200);
              }
          })
          .test()
          .assertResult(10);
      }
  
      @Test
      public void flatMapNotifyError() {
          Maybe.<Integer>error(new TestException())
          .flatMap(new Function<Integer, MaybeSource<Integer>>() {
              @Override
              public MaybeSource<Integer> apply(Integer v) throws Exception {
                  return Maybe.just(v * 10);
              }
          },
          new Function<Throwable, MaybeSource<Integer>>() {
              @Override
              public MaybeSource<Integer> apply(Throwable v) throws Exception {
                  return Maybe.just(100);
              }
          },
  
          new Callable<MaybeSource<Integer>>() {
              @Override
              public MaybeSource<Integer> call() throws Exception {
                  return Maybe.just(200);
              }
          })
          .test()
          .assertResult(100);
      }
  
      @Test
      public void flatMapNotifyComplete() {
          Maybe.<Integer>empty()
          .flatMap(new Function<Integer, MaybeSource<Integer>>() {
              @Override
              public MaybeSource<Integer> apply(Integer v) throws Exception {
                  return Maybe.just(v * 10);
              }
          },
          new Function<Throwable, MaybeSource<Integer>>() {
              @Override
              public MaybeSource<Integer> apply(Throwable v) throws Exception {
                  return Maybe.just(100);
              }
          },
  
          new Callable<MaybeSource<Integer>>() {
              @Override
              public MaybeSource<Integer> call() throws Exception {
                  return Maybe.just(200);
              }
          })
          .test()
          .assertResult(200);
      }
  
      @Test
      public void ignoreElementSuccess() {
          Maybe.just(1)
          .ignoreElement()
          .test()
          .assertResult();
      }
  
      @Test
      public void ignoreElementError() {
          Maybe.error(new TestException())
          .ignoreElement()
          .test()
          .assertFailure(TestException.class);
      }
  
      @Test
      public void ignoreElementComplete() {
          Maybe.empty()
          .ignoreElement()
          .test()
          .assertResult();
      }
      @Test
      public void ignoreElementSuccessMaybe() {
          Maybe.just(1)
          .ignoreElement()
          .toMaybe()
          .test()
          .assertResult();
      }
  
      @Test
      public void ignoreElementErrorMaybe() {
          Maybe.error(new TestException())
          .ignoreElement()
          .toMaybe()
          .test()
          .assertFailure(TestException.class);
      }
  
      @Test
      public void ignoreElementCompleteMaybe() {
          Maybe.empty()
          .ignoreElement()
          .toMaybe()
          .test()
          .assertResult();
      }
  
      @Test
      public void singleToMaybe() {
          Single.just(1)
          .toMaybe()
          .test()
          .assertResult(1);
      }
  
      @Test
      public void singleToMaybeError() {
          Single.error(new TestException())
          .toMaybe()
          .test()
          .assertFailure(TestException.class);
      }
  
      @Test
      public void completableToMaybe() {
          Completable.complete()
          .toMaybe()
          .test()
          .assertResult();
      }
  
      @Test
      public void completableToMaybeError() {
          Completable.error(new TestException())
          .toMaybe()
          .test()
          .assertFailure(TestException.class);
      }
  
      @Test
      public void emptyToSingle() {
          Maybe.empty()
          .toSingle()
          .test()
          .assertFailure(NoSuchElementException.class);
      }
  
      @Test
      public void errorToSingle() {
          Maybe.error(new TestException())
          .toSingle()
          .test()
          .assertFailure(TestException.class);
      }
  
      @Test
      public void emptyToCompletable() {
          Maybe.empty()
          .ignoreElement()
          .test()
          .assertResult();
      }
  
      @Test
      public void errorToCompletable() {
          Maybe.error(new TestException())
          .ignoreElement()
          .test()
          .assertFailure(TestException.class);
      }
  
      @Test
      public void concat2() {
          Maybe.concat(Maybe.just(1), Maybe.just(2))
          .test()
          .assertResult(1, 2);
      }
  
      @Test
      public void concat2Empty() {
          Maybe.concat(Maybe.empty(), Maybe.empty())
          .test()
          .assertResult();
      }
  
      @Test
      public void concat2Backpressured() {
          TestObserver<Integer> ts = Maybe.concat(Maybe.just(1), Maybe.just(2))
          .test();
  
          ts.assertResult(1, 2);
      }
  
      @Test
      public void concat2BackpressuredNonEager() {
          MaybeSubject<Integer> pp1 = MaybeSubject.create();
          MaybeSubject<Integer> pp2 = MaybeSubject.create();
  
          TestObserver<Integer> ts = Maybe.concat(pp1, pp2)
          .test();
  
          assertTrue(pp1.hasObservers());
          assertFalse(pp2.hasObservers());
  
  
          assertTrue(pp1.hasObservers());
          assertFalse(pp2.hasObservers());
  
          pp1.onSuccess(1);
  
          ts.assertValue(1);
  
          assertFalse(pp1.hasObservers());
          assertTrue(pp2.hasObservers());
  
          pp2.onSuccess(2);
          pp2.onComplete();
  
          ts.assertResult(1, 2);
  
          assertFalse(pp1.hasObservers());
          assertFalse(pp2.hasObservers());
      }
  
      @Test
      public void concat3() {
          Maybe.concat(Maybe.just(1), Maybe.just(2), Maybe.just(3))
          .test()
          .assertResult(1, 2, 3);
      }
  
      @Test
      public void concat3Empty() {
          Maybe.concat(Maybe.empty(), Maybe.empty(), Maybe.empty())
          .test()
          .assertResult();
      }
  
      @Test
      public void concat3Mixed1() {
          Maybe.concat(Maybe.just(1), Maybe.empty(), Maybe.just(3))
          .test()
          .assertResult(1, 3);
      }
  
      @Test
      public void concat3Mixed2() {
          Maybe.concat(Maybe.just(1), Maybe.just(2), Maybe.empty())
          .test()
          .assertResult(1, 2);
      }
  
      @Test
      public void concat3Backpressured() {
          TestObserver<Integer> ts = Maybe.concat(Maybe.just(1), Maybe.just(2), Maybe.just(3))
          .test();
  
          ts.assertResult(1, 2, 3);
      }
  
      @SuppressWarnings("unchecked")
      @Test
      public void concatArrayZero() {
          assertSame(Observable.empty(), Maybe.concatArray());
      }
  
      @SuppressWarnings("unchecked")
      @Test
      public void concatArrayOne() {
          Maybe.concatArray(Maybe.just(1)).test().assertResult(1);
      }
  
      @Test
      public void concat4() {
          Maybe.concat(Maybe.just(1), Maybe.just(2), Maybe.just(3), Maybe.just(4))
          .test()
          .assertResult(1, 2, 3, 4);
      }
  
      @SuppressWarnings("unchecked")
      @Test
      public void concatIterable() {
          Maybe.concat(Arrays.asList(Maybe.just(1), Maybe.just(2)))
          .test()
          .assertResult(1, 2);
      }
  
      @SuppressWarnings("unchecked")
      @Test
      public void concatIterableEmpty() {
          Maybe.concat(Arrays.asList(Maybe.empty(), Maybe.empty()))
          .test()
          .assertResult();
      }
  
      @SuppressWarnings("unchecked")
      @Test
      public void concatIterableBackpressured() {
          TestObserver<Integer> ts = Maybe.concat(Arrays.asList(Maybe.just(1), Maybe.just(2)))
          .test();
  
          ts.assertResult(1, 2);
      }
  
      @SuppressWarnings("unchecked")
      @Test
      public void concatIterableBackpressuredNonEager() {
          MaybeSubject<Integer> pp1 = MaybeSubject.create();
          MaybeSubject<Integer> pp2 = MaybeSubject.create();
  
          TestObserver<Integer> ts = Maybe.concat(Arrays.asList(pp1, pp2))
          .test();
  
          assertTrue(pp1.hasObservers());
          assertFalse(pp2.hasObservers());
  
          ts.assertEmpty();
  
          assertTrue(pp1.hasObservers());
          assertFalse(pp2.hasObservers());
  
          pp1.onSuccess(1);
  
          ts.assertValue(1);
  
          assertFalse(pp1.hasObservers());
          assertTrue(pp2.hasObservers());
  
          pp2.onSuccess(2);
  
          ts.assertResult(1, 2);
  
          assertFalse(pp1.hasObservers());
          assertFalse(pp2.hasObservers());
      }
  
      @Test
      public void concatIterableZero() {
          Maybe.concat(Collections.<Maybe<Integer>>emptyList()).test().assertResult();
      }
  
      @Test
      public void concatIterableOne() {
          Maybe.concat(Collections.<Maybe<Integer>>singleton(Maybe.just(1))).test().assertResult(1);
      }
  
      @Test
      public void concatObservable() {
          Maybe.concat(Observable.just(Maybe.just(1), Maybe.just(2))).test().assertResult(1, 2);
      }
  
      @Test
      public void concatObservablePrefetch() {
          Maybe.concat(Observable.just(Maybe.just(1), Maybe.just(2)), 1).test().assertResult(1, 2);
      }
  
      @Test(expected = NullPointerException.class)
      public void nullArgument() {
          Maybe.create(null);
      }
  
      @Test
      public void basic() {
          final Disposable d = Disposables.empty();
  
          Maybe.<Integer>create(new MaybeOnSubscribe<Integer>() {
              @Override
              public void subscribe(MaybeEmitter<Integer> e) throws Exception {
                  e.setDisposable(d);
  
                  e.onSuccess(1);
                  e.onError(new TestException());
                  e.onSuccess(2);
                  e.onError(new TestException());
                  e.onComplete();
              }
          })
          .test()
          .assertResult(1);
  
          assertTrue(d.isDisposed());
      }
  
      @Test
      public void basicWithError() {
          final Disposable d = Disposables.empty();
  
          Maybe.<Integer>create(new MaybeOnSubscribe<Integer>() {
              @Override
              public void subscribe(MaybeEmitter<Integer> e) throws Exception {
                  e.setDisposable(d);
  
                  e.onError(new TestException());
                  e.onSuccess(2);
                  e.onError(new TestException());
                  e.onComplete();
              }
          })
          .test()
          .assertFailure(TestException.class);
  
          assertTrue(d.isDisposed());
      }
  
      @Test
      public void basicWithComplete() {
          final Disposable d = Disposables.empty();
  
          Maybe.<Integer>create(new MaybeOnSubscribe<Integer>() {
              @Override
              public void subscribe(MaybeEmitter<Integer> e) throws Exception {
                  e.setDisposable(d);
  
                  e.onComplete();
                  e.onSuccess(1);
                  e.onError(new TestException());
                  e.onComplete();
                  e.onSuccess(2);
                  e.onError(new TestException());
              }
          })
          .test()
          .assertResult();
  
          assertTrue(d.isDisposed());
      }
  
      @Test(expected = IllegalArgumentException.class)
      public void unsafeCreateWithMaybe() {
          Maybe.unsafeCreate(Maybe.just(1));
      }
  
      @Test
      public void maybeToObservableEnum() {
          TestCommonHelper.checkEnum(MaybeToObservable.MaybeToObservableConverter.class);
      }
  
      @SuppressWarnings("unchecked")
      @Test
      public void ambArrayOneIsNull() {
          Maybe.ambArray(null, Maybe.just(1))
                  .test()
                  .assertError(NullPointerException.class);
      }
  
      @SuppressWarnings("unchecked")
      @Test
      public void ambArrayEmpty() {
          assertSame(Maybe.empty(), Maybe.ambArray());
      }
  
      @SuppressWarnings("unchecked")
      @Test
      public void ambArrayOne() {
          assertSame(Maybe.never(), Maybe.ambArray(Maybe.never()));
      }
  
      @Test
      public void ambWithOrder() {
          Maybe<Integer> error = Maybe.error(new RuntimeException());
          Maybe.just(1).ambWith(error).test().assertValue(1);
      }
  
      @SuppressWarnings("unchecked")
      @Test
      public void ambIterableOrder() {
          Maybe<Integer> error = Maybe.error(new RuntimeException());
          Maybe.amb(Arrays.asList(Maybe.just(1), error)).test().assertValue(1);
      }
  
      @SuppressWarnings("unchecked")
      @Test
      public void ambArrayOrder() {
          Maybe<Integer> error = Maybe.error(new RuntimeException());
          Maybe.ambArray(Maybe.just(1), error).test().assertValue(1);
      }
  
      @SuppressWarnings("unchecked")
      @Test
      public void ambArray1SignalsSuccess() {
          MaybeSubject<Integer> pp1 = MaybeSubject.create();
          MaybeSubject<Integer> pp2 = MaybeSubject.create();
  
          TestObserver<Integer> ts = Maybe.ambArray(pp1, pp2)
          .test();
  
          ts.assertEmpty();
  
          assertTrue(pp1.hasObservers());
          assertTrue(pp2.hasObservers());
  
          pp1.onSuccess(1);
  
          assertFalse(pp1.hasObservers());
          assertFalse(pp2.hasObservers());
  
          ts.assertResult(1);
      }
  
      @SuppressWarnings("unchecked")
      @Test
      public void ambArray2SignalsSuccess() {
          MaybeSubject<Integer> pp1 = MaybeSubject.create();
          MaybeSubject<Integer> pp2 = MaybeSubject.create();
  
          TestObserver<Integer> ts = Maybe.ambArray(pp1, pp2)
          .test();
  
          ts.assertEmpty();
  
          assertTrue(pp1.hasObservers());
          assertTrue(pp2.hasObservers());
  
          pp2.onSuccess(2);
  
          assertFalse(pp1.hasObservers());
          assertFalse(pp2.hasObservers());
  
          ts.assertResult(2);
      }
  
      @SuppressWarnings("unchecked")
      @Test
      public void ambArray1SignalsError() {
          MaybeSubject<Integer> pp1 = MaybeSubject.create();
          MaybeSubject<Integer> pp2 = MaybeSubject.create();
  
          TestObserver<Integer> ts = Maybe.ambArray(pp1, pp2)
          .test();
  
          ts.assertEmpty();
  
          assertTrue(pp1.hasObservers());
          assertTrue(pp2.hasObservers());
  
          pp1.onError(new TestException());
  
          assertFalse(pp1.hasObservers());
          assertFalse(pp2.hasObservers());
  
          ts.assertFailure(TestException.class);
      }
  
      @SuppressWarnings("unchecked")
      @Test
      public void ambArray2SignalsError() {
          MaybeSubject<Integer> pp1 = MaybeSubject.create();
          MaybeSubject<Integer> pp2 = MaybeSubject.create();
  
          TestObserver<Integer> ts = Maybe.ambArray(pp1, pp2)
          .test();
  
          ts.assertEmpty();
  
          assertTrue(pp1.hasObservers());
          assertTrue(pp2.hasObservers());
  
          pp2.onError(new TestException());
  
          assertFalse(pp1.hasObservers());
          assertFalse(pp2.hasObservers());
  
          ts.assertFailure(TestException.class);
      }
  
      @SuppressWarnings("unchecked")
      @Test
      public void ambArray1SignalsComplete() {
          MaybeSubject<Integer> pp1 = MaybeSubject.create();
          MaybeSubject<Integer> pp2 = MaybeSubject.create();
  
          TestObserver<Integer> ts = Maybe.ambArray(pp1, pp2)
          .test();
  
          ts.assertEmpty();
  
          assertTrue(pp1.hasObservers());
          assertTrue(pp2.hasObservers());
  
          pp1.onComplete();
  
          assertFalse(pp1.hasObservers());
          assertFalse(pp2.hasObservers());
  
          ts.assertResult();
      }
  
      @SuppressWarnings("unchecked")
      @Test
      public void ambArray2SignalsComplete() {
          MaybeSubject<Integer> pp1 = MaybeSubject.create();
          MaybeSubject<Integer> pp2 = MaybeSubject.create();
  
          TestObserver<Integer> ts = Maybe.ambArray(pp1, pp2)
          .test();
  
          ts.assertEmpty();
  
          assertTrue(pp1.hasObservers());
          assertTrue(pp2.hasObservers());
  
          pp2.onComplete();
  
          assertFalse(pp1.hasObservers());
          assertFalse(pp2.hasObservers());
  
          ts.assertResult();
      }
  
      @SuppressWarnings("unchecked")
      @Test
      public void ambIterable1SignalsSuccess() {
          MaybeSubject<Integer> pp1 = MaybeSubject.create();
          MaybeSubject<Integer> pp2 = MaybeSubject.create();
  
          TestObserver<Integer> ts = Maybe.amb(Arrays.asList(pp1, pp2))
          .test();
  
          ts.assertEmpty();
  
          assertTrue(pp1.hasObservers());
          assertTrue(pp2.hasObservers());
  
          pp1.onSuccess(1);
  
          assertFalse(pp1.hasObservers());
          assertFalse(pp2.hasObservers());
  
          ts.assertResult(1);
      }
  
      @SuppressWarnings("unchecked")
      @Test
      public void ambIterable2SignalsSuccess() {
          MaybeSubject<Integer> pp1 = MaybeSubject.create();
          MaybeSubject<Integer> pp2 = MaybeSubject.create();
  
          TestObserver<Integer> ts = Maybe.amb(Arrays.asList(pp1, pp2))
          .test();
  
          ts.assertEmpty();
  
          assertTrue(pp1.hasObservers());
          assertTrue(pp2.hasObservers());
  
          pp2.onSuccess(2);
  
          assertFalse(pp1.hasObservers());
          assertFalse(pp2.hasObservers());
  
          ts.assertResult(2);
      }
  
      @SuppressWarnings("unchecked")
      @Test
      public void ambIterable2SignalsSuccessWithOverlap() {
          MaybeSubject<Integer> pp1 = MaybeSubject.create();
          MaybeSubject<Integer> pp2 = MaybeSubject.create();
  
          TestObserver<Integer> ts = Maybe.amb(Arrays.asList(pp1, pp2))
                  .test();
  
          ts.assertEmpty();
  
          assertTrue(pp1.hasObservers());
          assertTrue(pp2.hasObservers());
  
          pp2.onSuccess(2);
          pp1.onSuccess(1);
  
          assertFalse(pp1.hasObservers());
          assertFalse(pp2.hasObservers());
  
          ts.assertResult(2);
      }
  
      @SuppressWarnings("unchecked")
      @Test
      public void ambIterable1SignalsError() {
          MaybeSubject<Integer> pp1 = MaybeSubject.create();
          MaybeSubject<Integer> pp2 = MaybeSubject.create();
  
          TestObserver<Integer> ts = Maybe.amb(Arrays.asList(pp1, pp2))
          .test();
  
          ts.assertEmpty();
  
          assertTrue(pp1.hasObservers());
          assertTrue(pp2.hasObservers());
  
          pp1.onError(new TestException());
  
          assertFalse(pp1.hasObservers());
          assertFalse(pp2.hasObservers());
  
          ts.assertFailure(TestException.class);
      }
  
      @SuppressWarnings("unchecked")
      @Test
      public void ambIterable2SignalsError() {
          MaybeSubject<Integer> pp1 = MaybeSubject.create();
          MaybeSubject<Integer> pp2 = MaybeSubject.create();
  
          TestObserver<Integer> ts = Maybe.amb(Arrays.asList(pp1, pp2))
          .test();
  
          ts.assertEmpty();
  
          assertTrue(pp1.hasObservers());
          assertTrue(pp2.hasObservers());
  
          pp2.onError(new TestException());
  
          assertFalse(pp1.hasObservers());
          assertFalse(pp2.hasObservers());
  
          ts.assertFailure(TestException.class);
      }
  
      @SuppressWarnings("unchecked")
      @Test
      public void ambIterable2SignalsErrorWithOverlap() {
          MaybeSubject<Integer> pp1 = MaybeSubject.create();
          MaybeSubject<Integer> pp2 = MaybeSubject.create();
  
          TestObserver<Integer> ts = Maybe.amb(Arrays.asList(pp1, pp2))
                  .test();
  
          ts.assertEmpty();
  
          assertTrue(pp1.hasObservers());
          assertTrue(pp2.hasObservers());
  
          pp2.onError(new TestException("2"));
          pp1.onError(new TestException("1"));
  
          assertFalse(pp1.hasObservers());
          assertFalse(pp2.hasObservers());
  
          ts.assertFailureAndMessage(TestException.class, "2");
      }
  
      @SuppressWarnings("unchecked")
      @Test
      public void ambIterable1SignalsComplete() {
          MaybeSubject<Integer> pp1 = MaybeSubject.create();
          MaybeSubject<Integer> pp2 = MaybeSubject.create();
  
          TestObserver<Integer> ts = Maybe.amb(Arrays.asList(pp1, pp2))
          .test();
  
          ts.assertEmpty();
  
          assertTrue(pp1.hasObservers());
          assertTrue(pp2.hasObservers());
  
          pp1.onComplete();
  
          assertFalse(pp1.hasObservers());
          assertFalse(pp2.hasObservers());
  
          ts.assertResult();
      }
  
      @SuppressWarnings("unchecked")
      @Test
      public void ambIterable2SignalsComplete() {
          MaybeSubject<Integer> pp1 = MaybeSubject.create();
          MaybeSubject<Integer> pp2 = MaybeSubject.create();
  
          TestObserver<Integer> ts = Maybe.amb(Arrays.asList(pp1, pp2))
          .test();
  
          ts.assertEmpty();
  
          assertTrue(pp1.hasObservers());
          assertTrue(pp2.hasObservers());
  
          pp2.onComplete();
  
          assertFalse(pp1.hasObservers());
          assertFalse(pp2.hasObservers());
  
          ts.assertResult();
      }
  
      @Test(expected = NullPointerException.class)
      public void ambIterableNull() {
          Maybe.amb((Iterable<Maybe<Integer>>)null);
      }
  
      @Test
      public void ambIterableIteratorNull() {
          Maybe.amb(new Iterable<Maybe<Object>>() {
              @Override
              public Iterator<Maybe<Object>> iterator() {
                  return null;
              }
          }).test().assertError(NullPointerException.class);
      }
  
      @SuppressWarnings("unchecked")
      @Test
      public void ambIterableOneIsNull() {
          Maybe.amb(Arrays.asList(null, Maybe.just(1)))
                  .test()
                  .assertError(NullPointerException.class);
      }
  
      @Test
      public void ambIterableEmpty() {
          Maybe.amb(Collections.<Maybe<Integer>>emptyList()).test().assertResult();
      }
  
      @Test
      public void ambIterableOne() {
          Maybe.amb(Collections.singleton(Maybe.just(1))).test().assertResult(1);
      }
  
      @SuppressWarnings("unchecked")
      @Test
      public void mergeArray() {
          Maybe.mergeArray(Maybe.just(1), Maybe.just(2), Maybe.just(3))
          .test()
          .assertResult(1, 2, 3);
      }
  
      @Test
      public void merge2() {
          Maybe.merge(Maybe.just(1), Maybe.just(2))
          .test()
          .assertResult(1, 2);
      }
  
      @Test
      public void merge3() {
          Maybe.merge(Maybe.just(1), Maybe.just(2), Maybe.just(3))
          .test()
          .assertResult(1, 2, 3);
      }
  
      @Test
      public void merge4() {
          Maybe.merge(Maybe.just(1), Maybe.just(2), Maybe.just(3), Maybe.just(4))
          .test()
          .assertResult(1, 2, 3, 4);
      }
  
      @Test
      public void merge4Take2() {
          Maybe.merge(Maybe.just(1), Maybe.just(2), Maybe.just(3), Maybe.just(4))
          .take(2)
          .test()
          .assertResult(1, 2);
      }
  
      @SuppressWarnings("unchecked")
      @Test
      public void mergeArrayBackpressured() {
          TestObserver<Integer> ts = Maybe.mergeArray(Maybe.just(1), Maybe.just(2), Maybe.just(3))
          .test();
  
          ts.assertResult(1, 2, 3);
      }
  
      @SuppressWarnings("unchecked")
      @Test
      public void mergeArrayBackpressuredMixed1() {
          TestObserver<Integer> ts = Maybe.mergeArray(Maybe.just(1), Maybe.<Integer>empty(), Maybe.just(3))
          .test();
  
          ts.assertResult(1, 3);
      }
  
      @SuppressWarnings("unchecked")
      @Test
      public void mergeArrayBackpressuredMixed2() {
          TestObserver<Integer> ts = Maybe.mergeArray(Maybe.just(1), Maybe.just(2), Maybe.<Integer>empty())
          .test();
  
          ts.assertResult(1, 2);
      }
  
      @SuppressWarnings("unchecked")
      @Test
      public void mergeArrayBackpressuredMixed3() {
          TestObserver<Integer> ts = Maybe.mergeArray(Maybe.<Integer>empty(), Maybe.just(2), Maybe.just(3))
          .test();
  
          ts.assertResult(2, 3);
      }
  
      @SuppressWarnings("unchecked")
      @Test
      public void mergeArrayFused() {
          TestObserver<Integer> ts = ObserverFusion.newTest(QueueDisposable.ANY);
  
          Maybe.mergeArray(Maybe.just(1), Maybe.just(2), Maybe.just(3)).subscribe(ts);
  
          ts.assertSubscribed()
          .assertOf(ObserverFusion.<Integer>assertFuseable())
          .assertOf(ObserverFusion.<Integer>assertFusionMode(QueueDisposable.ASYNC))
          .assertResult(1, 2, 3);
      }
  
      @SuppressWarnings("unchecked")
      @Test
      public void mergeArrayFusedRace() {
          for (int i = 0; i < 500; i++) {
              final MaybeSubject<Integer> pp1 = MaybeSubject.create();
              final MaybeSubject<Integer> pp2 = MaybeSubject.create();
  
              TestObserver<Integer> ts = ObserverFusion.newTest(QueueDisposable.ANY);
  
              Maybe.mergeArray(pp1, pp2).subscribe(ts);
  
              ts.assertSubscribed()
              .assertOf(ObserverFusion.<Integer>assertFuseable())
              .assertOf(ObserverFusion.<Integer>assertFusionMode(QueueDisposable.ASYNC))
              ;
  
              TestCommonHelper.race(new Runnable() {
                  @Override
                  public void run() {
                      pp1.onSuccess(1);
                  }
              }, new Runnable() {
                  @Override
                  public void run() {
                      pp2.onSuccess(1);
                      pp2.onComplete();
                  }
              }, Schedulers.single());
  
              ts
              .awaitDone(5, TimeUnit.SECONDS)
              .assertResult(1, 1);
          }
      }
  
      @SuppressWarnings("unchecked")
      @Test
      public void mergeArrayZero() {
          assertSame(Observable.empty(), Maybe.mergeArray());
      }
  
      @SuppressWarnings("unchecked")
      @Test
      public void mergeArrayOne() {
          Maybe.mergeArray(Maybe.just(1)).test().assertResult(1);
      }
  
      @Test
      public void mergeObservable() {
          Maybe.merge(Observable.just(Maybe.just(1), Maybe.just(2), Maybe.just(3)))
          .test()
          .assertResult(1, 2, 3);
      }
  
      @Test
      public void mergeObservableMaxConcurrent() {
          final MaybeSubject<Integer> pp1 = MaybeSubject.create();
          final MaybeSubject<Integer> pp2 = MaybeSubject.create();
  
          TestObserver<Integer> ts = Maybe.merge(Observable.just(pp1, pp2), 1).test();
  
          assertTrue(pp1.hasObservers());
          assertFalse(pp2.hasObservers());
  
          pp1.onSuccess(1);
  
          assertFalse(pp1.hasObservers());
          assertTrue(pp2.hasObservers());
  
          ts.assertValue(1);
      }
  
      @Test
      public void mergeMaybe() {
          Maybe.merge(Maybe.just(Maybe.just(1)))
          .test()
          .assertResult(1);
      }
  
      @SuppressWarnings("unchecked")
      @Test
      public void mergeIterable() {
          Maybe.merge(Arrays.asList(Maybe.just(1), Maybe.just(2), Maybe.just(3)))
          .test()
          .assertResult(1, 2, 3);
      }
  
      @Test
      public void mergeALot() {
          @SuppressWarnings("unchecked")
          Maybe<Integer>[] sources = new Maybe[Observable.bufferSize() * 2];
          Arrays.fill(sources, Maybe.just(1));
  
          Maybe.mergeArray(sources)
          .test()
          .assertSubscribed()
          .assertValueCount(sources.length)
          .assertNoErrors()
          .assertComplete();
      }
  
      @Test
      public void mergeALotLastEmpty() {
          @SuppressWarnings("unchecked")
          Maybe<Integer>[] sources = new Maybe[Observable.bufferSize() * 2];
          Arrays.fill(sources, Maybe.just(1));
          sources[sources.length - 1] = Maybe.empty();
  
          Maybe.mergeArray(sources)
          .test()
          .assertSubscribed()
          .assertValueCount(sources.length - 1)
          .assertNoErrors()
          .assertComplete();
      }
  
      @Test
      public void mergeALotFused() {
          @SuppressWarnings("unchecked")
          Maybe<Integer>[] sources = new Maybe[Observable.bufferSize() * 2];
          Arrays.fill(sources, Maybe.just(1));
  
          TestObserver<Integer> ts = ObserverFusion.newTest(QueueDisposable.ANY);
  
          Maybe.mergeArray(sources).subscribe(ts);
  
          ts
          .assertSubscribed()
          .assertOf(ObserverFusion.<Integer>assertFuseable())
          .assertOf(ObserverFusion.<Integer>assertFusionMode(QueueDisposable.ASYNC))
          .assertValueCount(sources.length)
          .assertNoErrors()
          .assertComplete();
      }
  
      @Test
      public void mergeErrorSuccess() {
          Maybe.merge(Maybe.error(new TestException()), Maybe.just(1))
          .test()
          .assertFailure(TestException.class);
      }
  
      @Test
      public void mergeSuccessError() {
          Maybe.merge(Maybe.just(1), Maybe.error(new TestException()))
          .test()
          .assertFailure(TestException.class, 1);
      }
  
      @Test
      public void subscribeZero() {
          assertTrue(Maybe.just(1)
          .subscribe().isDisposed());
      }
  
      @Test
      public void subscribeZeroError() {
          List<Throwable> errors = TestCommonHelper.trackPluginErrors();
  
          try {
              assertTrue(Maybe.error(new TestException())
              .subscribe().isDisposed());
  
              TestCommonHelper.assertError(errors, 0, OnErrorNotImplementedException.class);
              Throwable c = errors.get(0).getCause();
              assertTrue("" + c, c instanceof TestException);
          } finally {
              RxJavaCommonPlugins.reset();
          }
      }
  
      @Test
      public void subscribeToOnSuccess() {
          final List<Integer> values = new ArrayList<Integer>();
  
          Consumer<Integer> onSuccess = new Consumer<Integer>() {
              @Override
              public void accept(Integer e) throws Exception {
                  values.add(e);
              }
          };
  
          Maybe<Integer> source = Maybe.just(1);
  
          source.subscribe(onSuccess);
          source.subscribe(onSuccess, Functions.emptyConsumer());
          source.subscribe(onSuccess, Functions.emptyConsumer(), Functions.EMPTY_ACTION);
  
          assertEquals(Arrays.asList(1, 1, 1), values);
      }
  
      @Test
      public void subscribeToOnError() {
          final List<Throwable> values = new ArrayList<Throwable>();
  
          Consumer<Throwable> onError = new Consumer<Throwable>() {
              @Override
              public void accept(Throwable e) throws Exception {
                  values.add(e);
              }
          };
  
          TestException ex = new TestException();
  
          Maybe<Integer> source = Maybe.error(ex);
  
          source.subscribe(Functions.emptyConsumer(), onError);
          source.subscribe(Functions.emptyConsumer(), onError, Functions.EMPTY_ACTION);
  
          assertEquals(Arrays.asList(ex, ex), values);
      }
  
      @Test
      public void subscribeToOnComplete() {
          final List<Integer> values = new ArrayList<Integer>();
  
          Action onComplete = new Action() {
              @Override
              public void run() throws Exception {
                  values.add(100);
              }
          };
  
          Maybe<Integer> source = Maybe.empty();
  
          source.subscribe(Functions.emptyConsumer(), Functions.emptyConsumer(), onComplete);
  
          assertEquals(Arrays.asList(100), values);
      }
  
      @Test
      public void subscribeWith() {
          MaybeObserver<Integer> mo = new MaybeObserver<Integer>() {
  
              @Override
              public void onSubscribe(Disposable d) {
  
              }
  
              @Override
              public void onSuccess(Integer value) {
  
              }
  
              @Override
              public void onError(Throwable e) {
  
              }
  
              @Override
              public void onComplete() {
  
              }
  
          };
  
          assertSame(mo, Maybe.just(1).subscribeWith(mo));
      }
  
      @Test
      public void doOnEventSuccess() {
          final List<Object> list = new ArrayList<Object>();
  
          assertTrue(Maybe.just(1)
          .doOnEvent(new BiConsumer<Integer, Throwable>() {
              @Override
              public void accept(Integer v, Throwable e) throws Exception {
                  list.add(v);
                  list.add(e);
              }
          })
          .subscribe().isDisposed());
  
          assertEquals(Arrays.asList(1, null), list);
      }
  
      @Test
      public void doOnEventError() {
          final List<Object> list = new ArrayList<Object>();
  
          TestException ex = new TestException();
  
          assertTrue(Maybe.<Integer>error(ex)
          .doOnEvent(new BiConsumer<Integer, Throwable>() {
              @Override
              public void accept(Integer v, Throwable e) throws Exception {
                  list.add(v);
                  list.add(e);
              }
          })
          .subscribe().isDisposed());
  
          assertEquals(Arrays.asList(null, ex), list);
      }
  
      @Test
      public void doOnEventComplete() {
          final List<Object> list = new ArrayList<Object>();
  
          assertTrue(Maybe.<Integer>empty()
          .doOnEvent(new BiConsumer<Integer, Throwable>() {
              @Override
              public void accept(Integer v, Throwable e) throws Exception {
                  list.add(v);
                  list.add(e);
              }
          })
          .subscribe().isDisposed());
  
          assertEquals(Arrays.asList(null, null), list);
      }
  
      @Test(expected = NullPointerException.class)
      public void doOnEventNull() {
          Maybe.just(1).doOnEvent(null);
      }
  
      @Test
      public void doOnEventSuccessThrows() {
          Maybe.just(1)
          .doOnEvent(new BiConsumer<Integer, Throwable>() {
              @Override
              public void accept(Integer v, Throwable e) throws Exception {
                  throw new TestException();
              }
          })
          .test()
          .assertFailure(TestException.class);
      }
  
      @Test
      public void doOnEventErrorThrows() {
          TestObserver<Integer> ts = Maybe.<Integer>error(new TestException("Outer"))
          .doOnEvent(new BiConsumer<Integer, Throwable>() {
              @Override
              public void accept(Integer v, Throwable e) throws Exception {
                  throw new TestException("Inner");
              }
          })
          .test()
          .assertFailure(CompositeException.class);
  
          List<Throwable> list = TestCommonHelper.compositeList(ts.errors().get(0));
          TestCommonHelper.assertError(list, 0, TestException.class, "Outer");
          TestCommonHelper.assertError(list, 1, TestException.class, "Inner");
          assertEquals(2, list.size());
      }
  
  
      @Test
      public void doOnEventCompleteThrows() {
          Maybe.<Integer>empty()
          .doOnEvent(new BiConsumer<Integer, Throwable>() {
              @Override
              public void accept(Integer v, Throwable e) throws Exception {
                  throw new TestException();
              }
          })
          .test()
          .assertFailure(TestException.class);
      }
  
      @SuppressWarnings("unchecked")
      @Test
      public void concatArrayDelayError() {
          Maybe.concatArrayDelayError(Maybe.empty(), Maybe.just(1), Maybe.error(new TestException()))
          .test()
          .assertFailure(TestException.class, 1);
  
          Maybe.concatArrayDelayError(Maybe.error(new TestException()), Maybe.empty(), Maybe.just(1))
          .test()
          .assertFailure(TestException.class, 1);
  
          assertSame(Observable.empty(), Maybe.concatArrayDelayError());
  
          assertFalse(Maybe.concatArrayDelayError(Maybe.never()) instanceof MaybeConcatArrayDelayError);
      }
  
      @SuppressWarnings("unchecked")
      @Test
      public void concatIterableDelayError() {
          Maybe.concatDelayError(Arrays.asList(Maybe.empty(), Maybe.just(1), Maybe.error(new TestException())))
          .test()
          .assertFailure(TestException.class, 1);
  
          Maybe.concatDelayError(Arrays.asList(Maybe.error(new TestException()), Maybe.empty(), Maybe.just(1)))
          .test()
          .assertFailure(TestException.class, 1);
      }
  
      @Test
      public void concatObservableDelayError() {
          Maybe.concatDelayError(Observable.just(Maybe.empty(), Maybe.just(1), Maybe.error(new TestException())))
          .test()
          .assertFailure(TestException.class, 1);
  
          Maybe.concatDelayError(Observable.just(Maybe.error(new TestException()), Maybe.empty(), Maybe.just(1)))
          .test()
          .assertFailure(TestException.class, 1);
      }
  
      @SuppressWarnings("unchecked")
      @Test
      public void concatEagerArray() {
          MaybeSubject<Integer> pp1 = MaybeSubject.create();
          MaybeSubject<Integer> pp2 = MaybeSubject.create();
  
          TestObserver<Integer> ts = Maybe.concatArrayEager(pp1, pp2).test();
  
          assertTrue(pp1.hasObservers());
          assertTrue(pp2.hasObservers());
  
          pp2.onSuccess(2);
  
          ts.assertEmpty();
  
          pp1.onSuccess(1);
          pp1.onComplete();
  
          ts.assertResult(1, 2);
  
      }
  
      @SuppressWarnings("unchecked")
      @Test
      public void concatEagerIterable() {
          MaybeSubject<Integer> pp1 = MaybeSubject.create();
          MaybeSubject<Integer> pp2 = MaybeSubject.create();
  
          TestObserver<Integer> ts = Maybe.concatEager(Arrays.asList(pp1, pp2)).test();
  
          assertTrue(pp1.hasObservers());
          assertTrue(pp2.hasObservers());
  
          pp2.onSuccess(2);
  
          ts.assertEmpty();
  
          pp1.onSuccess(1);
  
          ts.assertResult(1, 2);
  
      }
  
      @Test
      public void concatEagerObservable() {
          MaybeSubject<Integer> pp1 = MaybeSubject.create();
          MaybeSubject<Integer> pp2 = MaybeSubject.create();
  
          TestObserver<Integer> ts = Maybe.concatEager(Observable.just(pp1, pp2)).test();
  
          assertTrue(pp1.hasObservers());
          assertTrue(pp2.hasObservers());
  
          pp2.onSuccess(2);
  
          ts.assertEmpty();
  
          pp1.onSuccess(1);
  
          ts.assertResult(1, 2);
  
      }
  
      static Future<Integer> emptyFuture() {
          final ScheduledExecutorService exec = Executors.newSingleThreadScheduledExecutor();
  
          return exec.schedule(new Callable<Integer>() {
  
              @Override
              public Integer call() throws Exception {
                  exec.shutdown();
                  return null;
              }
          }, 200, TimeUnit.MILLISECONDS);
      }
  
      @Test
      public void fromFuture() {
          Maybe.fromFuture(Observable.just(1).delay(200, TimeUnit.MILLISECONDS).toFuture())
          .test()
          .awaitDone(5, TimeUnit.SECONDS)
          .assertResult(1)
          ;
  
          Maybe.fromFuture(emptyFuture())
          .test()
          .awaitDone(5, TimeUnit.SECONDS)
          .assertResult()
          ;
  
          Maybe.fromFuture(Observable.error(new TestException()).delay(200, TimeUnit.MILLISECONDS, true).toFuture())
          .test()
          .awaitDone(5, TimeUnit.SECONDS)
          .assertFailure(TestException.class)
          ;
  
          Maybe.fromFuture(Observable.empty().delay(10, TimeUnit.SECONDS).toFuture(), 100, TimeUnit.MILLISECONDS)
          .test()
          .awaitDone(5, TimeUnit.SECONDS)
          .assertFailure(TimeoutException.class)
          ;
      }
  
      @SuppressWarnings("unchecked")
      @Test
      public void mergeArrayDelayError() {
          Maybe.mergeArrayDelayError(Maybe.empty(), Maybe.just(1), Maybe.error(new TestException()))
          .test()
          .assertFailure(TestException.class, 1);
  
          Maybe.mergeArrayDelayError(Maybe.error(new TestException()), Maybe.empty(), Maybe.just(1))
          .test()
          .assertFailure(TestException.class, 1);
  
          assertSame(Observable.empty(), Maybe.mergeArrayDelayError());
      }
  
      @SuppressWarnings("unchecked")
      @Test
      public void mergeIterableDelayError() {
          Maybe.mergeDelayError(Arrays.asList(Maybe.empty(), Maybe.just(1), Maybe.error(new TestException())))
          .test()
          .assertFailure(TestException.class, 1);
  
          Maybe.mergeDelayError(Arrays.asList(Maybe.error(new TestException()), Maybe.empty(), Maybe.just(1)))
          .test()
          .assertFailure(TestException.class, 1);
      }
  
      @Test
      public void mergeObservableDelayError() {
          Maybe.mergeDelayError(Observable.just(Maybe.empty(), Maybe.just(1), Maybe.error(new TestException())))
          .test()
          .assertFailure(TestException.class, 1);
  
          Maybe.mergeDelayError(Observable.just(Maybe.error(new TestException()), Maybe.empty(), Maybe.just(1)))
          .test()
          .assertFailure(TestException.class, 1);
      }
  
      @Test
      public void mergeDelayError2() {
          Maybe.mergeDelayError(Maybe.just(1), Maybe.error(new TestException()))
          .test()
          .assertFailure(TestException.class, 1);
  
          Maybe.mergeDelayError(Maybe.error(new TestException()), Maybe.just(1))
          .test()
          .assertFailure(TestException.class, 1);
      }
  
      @Test
      public void mergeDelayError3() {
          Maybe.mergeDelayError(Maybe.just(1), Maybe.error(new TestException()), Maybe.just(2))
          .test()
          .assertFailure(TestException.class, 1, 2);
  
          Maybe.mergeDelayError(Maybe.error(new TestException()), Maybe.just(1), Maybe.just(2))
          .test()
          .assertFailure(TestException.class, 1, 2);
  
          Maybe.mergeDelayError(Maybe.just(1), Maybe.just(2), Maybe.error(new TestException()))
          .test()
          .assertFailure(TestException.class, 1, 2);
      }
  
      @Test
      public void mergeDelayError4() {
          Maybe.mergeDelayError(Maybe.just(1), Maybe.error(new TestException()), Maybe.just(2), Maybe.just(3))
          .test()
          .assertFailure(TestException.class, 1, 2, 3);
  
          Maybe.mergeDelayError(Maybe.error(new TestException()), Maybe.just(1), Maybe.just(2), Maybe.just(3))
          .test()
          .assertFailure(TestException.class, 1, 2, 3);
  
          Maybe.mergeDelayError(Maybe.just(1), Maybe.just(2), Maybe.just(3), Maybe.error(new TestException()))
          .test()
          .assertFailure(TestException.class, 1, 2, 3);
      }
  
      @Test
      public void sequenceEqual() {
          Maybe.sequenceEqual(Maybe.just(1), Maybe.just(new Integer(1))).test().assertResult(true);
  
          Maybe.sequenceEqual(Maybe.just(1), Maybe.just(2)).test().assertResult(false);
  
          Maybe.sequenceEqual(Maybe.just(1), Maybe.empty()).test().assertResult(false);
  
          Maybe.sequenceEqual(Maybe.empty(), Maybe.just(2)).test().assertResult(false);
  
          Maybe.sequenceEqual(Maybe.empty(), Maybe.empty()).test().assertResult(true);
  
          Maybe.sequenceEqual(Maybe.just(1), Maybe.error(new TestException())).test().assertFailure(TestException.class);
  
          Maybe.sequenceEqual(Maybe.error(new TestException()), Maybe.just(1)).test().assertFailure(TestException.class);
  
          List<Throwable> errors = TestCommonHelper.trackPluginErrors();
  
          try {
              Maybe.sequenceEqual(Maybe.error(new TestException("One")), Maybe.error(new TestException("Two"))).test().assertFailureAndMessage(TestException.class, "One");
  
              TestCommonHelper.assertUndeliverable(errors, 0, TestException.class, "Two");
          } finally {
              RxJavaCommonPlugins.reset();
          }
  
          Maybe.sequenceEqual(Maybe.just(1), Maybe.error(new TestException()), new BiPredicate<Object, Object>() {
              @Override
              public boolean test(Object t1, Object t2) throws Exception {
                  throw new TestException();
              }
          })
          .test().assertFailure(TestException.class);
      }
  
      @Test
      public void timer() {
          Maybe.timer(100, TimeUnit.MILLISECONDS)
          .test()
          .awaitDone(5, TimeUnit.SECONDS)
          .assertResult(0L);
      }
  
      @Test
      public void blockingGet() {
          assertEquals(1, Maybe.just(1).blockingGet().intValue());
  
          assertEquals(100, Maybe.empty().blockingGet(100));
  
          try {
              Maybe.error(new TestException()).blockingGet();
              fail("Should have thrown!");
          } catch (TestException ex) {
              // expected
          }
  
          try {
              Maybe.error(new TestException()).blockingGet(100);
              fail("Should have thrown!");
          } catch (TestException ex) {
              // expected
          }
      }
  
      @Test
      public void toSingleDefault() {
          Maybe.just(1).toSingle(100)
          .test().assertResult(1);
  
          Maybe.empty().toSingle(100)
          .test().assertResult(100);
      }
  
      @Test
      public void flatMapContinuation() {
          Maybe.just(1).flatMapCompletable(new Function<Integer, Completable>() {
              @Override
              public Completable apply(Integer v) throws Exception {
                  return Completable.complete();
              }
          })
          .test().assertResult();
  
          Maybe.just(1).flatMapCompletable(new Function<Integer, Completable>() {
              @Override
              public Completable apply(Integer v) throws Exception {
                  return Completable.error(new TestException());
              }
          })
          .test().assertFailure(TestException.class);
  
          Maybe.just(1).flatMapObservable(new Function<Integer, Observable<Integer>>() {
              @Override
              public Observable<Integer> apply(Integer v) throws Exception {
                  return Observable.range(1, 5);
              }
          })
          .test().assertResult(1, 2, 3, 4, 5);
  
          Maybe.just(1).flatMapObservable(new Function<Integer, Observable<Integer>>() {
              @Override
              public Observable<Integer> apply(Integer v) throws Exception {
                  return Observable.error(new TestException());
              }
          })
          .test().assertFailure(TestException.class);
  
          Maybe.just(1).flatMapObservable(new Function<Integer, Observable<Integer>>() {
              @Override
              public Observable<Integer> apply(Integer v) throws Exception {
                  return Observable.range(1, 5);
              }
          })
          .test().assertResult(1, 2, 3, 4, 5);
  
          Maybe.just(1).flatMapObservable(new Function<Integer, Observable<Integer>>() {
              @Override
              public Observable<Integer> apply(Integer v) throws Exception {
                  return Observable.error(new TestException());
              }
          })
          .test().assertFailure(TestException.class);
      }
  
      @Test
      public void using() {
          final AtomicInteger disposeCount = new AtomicInteger();
  
          Maybe.using(Functions.justCallable(1), new Function<Integer, MaybeSource<Integer>>() {
              @Override
              public MaybeSource<Integer> apply(Integer v) throws Exception {
                  return Maybe.just(v);
              }
          }, new Consumer<Integer>() {
              @Override
              public void accept(Integer d) throws Exception {
                  disposeCount.set(d);
              }
          })
          .map(new Function<Integer, Object>() {
              @Override
              public String apply(Integer v) throws Exception {
                  return "" + disposeCount.get() + v * 10;
              }
          })
          .test()
          .assertResult("110");
      }
  
      @Test
      public void usingNonEager() {
          final AtomicInteger disposeCount = new AtomicInteger();
  
          Maybe.using(Functions.justCallable(1), new Function<Integer, MaybeSource<Integer>>() {
              @Override
              public MaybeSource<Integer> apply(Integer v) throws Exception {
                  return Maybe.just(v);
              }
          }, new Consumer<Integer>() {
              @Override
              public void accept(Integer d) throws Exception {
                  disposeCount.set(d);
              }
          }, false)
          .map(new Function<Integer, Object>() {
              @Override
              public String apply(Integer v) throws Exception {
                  return "" + disposeCount.get() + v * 10;
              }
          })
          .test()
          .assertResult("010");
  
          assertEquals(1, disposeCount.get());
      }
  
      Function<Object[], String> arrayToString = new Function<Object[], String>() {
          @Override
          public String apply(Object[] a) throws Exception {
              return Arrays.toString(a);
          }
      };
  
      @SuppressWarnings("unchecked")
      @Test
      public void zipArray() {
          Maybe.zipArray(arrayToString, Maybe.just(1), Maybe.just(2))
          .test()
          .assertResult("[1, 2]");
  
          Maybe.zipArray(arrayToString, Maybe.just(1), Maybe.empty())
          .test()
          .assertResult();
  
          Maybe.zipArray(arrayToString, Maybe.just(1), Maybe.error(new TestException()))
          .test()
          .assertFailure(TestException.class);
  
          assertSame(Maybe.empty(), Maybe.zipArray(ArgsToString.INSTANCE));
  
          Maybe.zipArray(arrayToString, Maybe.just(1))
          .test()
          .assertResult("[1]");
      }
  
      /**
       * Implements all Function types which return a String concatenating their inputs.
       */
      @SuppressWarnings("rawtypes")
      public enum ArgsToString implements Function, BiFunction, Function3, Function4, Function5, Function6, Function7, Function8, Function9 {
          INSTANCE;
  
          @Override
          public Object apply(Object t1, Object t2, Object t3, Object t4, Object t5, Object t6, Object t7, Object t8,
                  Object t9) throws Exception {
              return "" + t1 + t2 + t3 + t4 + t5 + t6 + t7 + t8 + t9;
          }
  
          @Override
          public Object apply(Object t1, Object t2, Object t3, Object t4, Object t5, Object t6, Object t7, Object t8)
                  throws Exception {
              return "" + t1 + t2 + t3 + t4 + t5 + t6 + t7 + t8;
          }
  
          @Override
          public Object apply(Object t1, Object t2, Object t3, Object t4, Object t5, Object t6, Object t7)
                  throws Exception {
              return "" + t1 + t2 + t3 + t4 + t5 + t6 + t7;
          }
  
          @Override
          public Object apply(Object t1, Object t2, Object t3, Object t4, Object t5, Object t6) throws Exception {
              return "" + t1 + t2 + t3 + t4 + t5 + t6;
          }
  
          @Override
          public Object apply(Object t1, Object t2, Object t3, Object t4, Object t5) throws Exception {
              return "" + t1 + t2 + t3 + t4 + t5;
          }
  
          @Override
          public Object apply(Object t1, Object t2, Object t3, Object t4) throws Exception {
              return "" + t1 + t2 + t3 + t4;
          }
  
          @Override
          public Object apply(Object t1, Object t2, Object t3) throws Exception {
              return "" + t1 + t2 + t3;
          }
  
          @Override
          public Object apply(Object t1, Object t2) throws Exception {
              return "" + t1 + t2;
          }
  
          @Override
          public Object apply(Object t1) throws Exception {
              return "" + t1;
          }
      }
  
  
      @SuppressWarnings("unchecked")
      @Test
      public void zipIterable() {
          Maybe.zip(
          Arrays.asList(Maybe.just(1), Maybe.just(2)),
          arrayToString)
          .test()
          .assertResult("[1, 2]");
  
          Maybe.zip(Collections.<Maybe<Integer>>emptyList(), arrayToString)
          .test()
          .assertResult();
  
          Maybe.zip(Collections.singletonList(Maybe.just(1)), arrayToString)
          .test()
          .assertResult("[1]");
      }
  
      @SuppressWarnings("unchecked")
      @Test
      public void zip2() {
          Maybe.zip(Maybe.just(1), Maybe.just(2), ArgsToString.INSTANCE)
          .test()
          .assertResult("12");
      }
  
      @SuppressWarnings("unchecked")
      @Test
      public void zipWith() {
          Maybe.just(1).zipWith(Maybe.just(2), ArgsToString.INSTANCE)
          .test()
          .assertResult("12");
      }
  
      @SuppressWarnings("unchecked")
      @Test
      public void zip3() {
          Maybe.zip(Maybe.just(1), Maybe.just(2), Maybe.just(3),
              ArgsToString.INSTANCE)
          .test()
          .assertResult("123");
      }
  
      @SuppressWarnings("unchecked")
      @Test
      public void zip4() {
          Maybe.zip(Maybe.just(1), Maybe.just(2), Maybe.just(3), Maybe.just(4),
              ArgsToString.INSTANCE)
          .test()
          .assertResult("1234");
      }
  
      @SuppressWarnings("unchecked")
      @Test
      public void zip5() {
          Maybe.zip(Maybe.just(1), Maybe.just(2), Maybe.just(3), Maybe.just(4),
                  Maybe.just(5),
              ArgsToString.INSTANCE)
          .test()
          .assertResult("12345");
      }
  
      @SuppressWarnings("unchecked")
      @Test
      public void zip6() {
          Maybe.zip(Maybe.just(1), Maybe.just(2), Maybe.just(3), Maybe.just(4),
                  Maybe.just(5), Maybe.just(6),
              ArgsToString.INSTANCE)
          .test()
          .assertResult("123456");
      }
  
      @SuppressWarnings("unchecked")
      @Test
      public void zip7() {
          Maybe.zip(Maybe.just(1), Maybe.just(2), Maybe.just(3), Maybe.just(4),
                  Maybe.just(5), Maybe.just(6), Maybe.just(7),
              ArgsToString.INSTANCE)
          .test()
          .assertResult("1234567");
      }
  
      @SuppressWarnings("unchecked")
      @Test
      public void zip8() {
          Maybe.zip(Maybe.just(1), Maybe.just(2), Maybe.just(3), Maybe.just(4),
                  Maybe.just(5), Maybe.just(6), Maybe.just(7), Maybe.just(8),
              ArgsToString.INSTANCE)
          .test()
          .assertResult("12345678");
      }
  
      @SuppressWarnings("unchecked")
      @Test
      public void zip9() {
          Maybe.zip(Maybe.just(1), Maybe.just(2), Maybe.just(3), Maybe.just(4),
                  Maybe.just(5), Maybe.just(6), Maybe.just(7), Maybe.just(8), Maybe.just(9),
              ArgsToString.INSTANCE)
          .test()
          .assertResult("123456789");
      }
  
  
      @Test
      public void ambWith1SignalsSuccess() {
          MaybeSubject<Integer> pp1 = MaybeSubject.create();
          MaybeSubject<Integer> pp2 = MaybeSubject.create();
  
          TestObserver<Integer> ts = pp1.ambWith(pp2)
          .test();
  
          ts.assertEmpty();
  
          assertTrue(pp1.hasObservers());
          assertTrue(pp2.hasObservers());
  
          pp1.onSuccess(1);
  
          assertFalse(pp1.hasObservers());
          assertFalse(pp2.hasObservers());
  
          ts.assertResult(1);
      }
  
      @Test
      public void ambWith2SignalsSuccess() {
          MaybeSubject<Integer> pp1 = MaybeSubject.create();
          MaybeSubject<Integer> pp2 = MaybeSubject.create();
  
          TestObserver<Integer> ts = pp1.ambWith(pp2)
          .test();
  
          ts.assertEmpty();
  
          assertTrue(pp1.hasObservers());
          assertTrue(pp2.hasObservers());
  
          pp2.onSuccess(2);
  
          assertFalse(pp1.hasObservers());
          assertFalse(pp2.hasObservers());
  
          ts.assertResult(2);
      }
  
      @Test
      public void zipIterableObject() {
          @SuppressWarnings("unchecked")
          final List<Maybe<Integer>> maybes = Arrays.asList(Maybe.just(1), Maybe.just(4));
          Maybe.zip(maybes, new Function<Object[], Object>() {
              @Override
              public Object apply(final Object[] o) throws Exception {
                  int sum = 0;
                  for (Object i : o) {
                      sum += (Integer) i;
                  }
                  return sum;
              }
          }).test().assertResult(5);
      }
  
      static long usedMemoryNow() {
          MemoryMXBean memoryMXBean = ManagementFactory.getMemoryMXBean();
  
          MemoryUsage heapMemoryUsage = memoryMXBean.getHeapMemoryUsage();
  
          return heapMemoryUsage.getUsed();
      }
  
      @Test
      public void onTerminateDetach() throws Exception {
          System.gc();
  
          Thread.sleep(150);
  
          long before = usedMemoryNow();
  
          Maybe<Object> source = Observable.just((Object)new Object[10000000]).singleElement();
  
          long middle = usedMemoryNow();
  
          MaybeObserver<Object> observer = new MaybeObserver<Object>() {
              @SuppressWarnings("unused")
              Disposable u;
  
              @Override
              public void onSubscribe(Disposable d) {
                  this.u = d;
              }
  
              @Override
              public void onSuccess(Object value) {
  
              }
  
              @Override
              public void onError(Throwable e) {
  
              }
  
              @Override
              public void onComplete() {
  
              }
  
          };
          source.onTerminateDetach().subscribe(observer);
  
          source = null;
  
          System.gc();
  
          Thread.sleep(250);
  
          long after = usedMemoryNow();
  
          String log = String.format("%.2f MB -> %.2f MB -> %.2f MB%n",
                  before / 1024.0 / 1024.0,
                  middle / 1024.0 / 1024.0,
                  after / 1024.0 / 1024.0);
  
          System.out.printf(log);
  
          if (before * 1.3 < after) {
              fail("There seems to be a memory leak: " + log);
          }
  
          assertNotNull(observer); // hold onto the reference to prevent premature GC
      }
  
      @Test
      public void repeat() {
          Maybe.just(1).repeat().take(5).test().assertResult(1, 1, 1, 1, 1);
  
          Maybe.just(1).repeat(5).test().assertResult(1, 1, 1, 1, 1);
  
          Maybe.just(1).repeatUntil(new BooleanSupplier() {
              @Override
              public boolean getAsBoolean() throws Exception {
                  return false;
              }
          }).take(5).test().assertResult(1, 1, 1, 1, 1);
  
          Maybe.just(1).repeatWhen(new Function<Observable<Object>, Observable<Object>>() {
              @Override
              public Observable<Object> apply(Observable<Object> v) throws Exception {
                  return v;
              }
          }).take(5).test().assertResult(1, 1, 1, 1, 1);
      }
  
      @Test
      public void retry() {
          Maybe.just(1).retry().test().assertResult(1);
  
          Maybe.just(1).retry(5).test().assertResult(1);
  
          Maybe.just(1).retry(Functions.alwaysTrue()).test().assertResult(1);
  
          Maybe.just(1).retry(5, Functions.alwaysTrue()).test().assertResult(1);
  
          Maybe.just(1).retry(new BiPredicate<Integer, Throwable>() {
              @Override
              public boolean test(Integer a, Throwable e) throws Exception {
                  return true;
              }
          }).test().assertResult(1);
  
          Maybe.just(1).retryUntil(new BooleanSupplier() {
              @Override
              public boolean getAsBoolean() throws Exception {
                  return false;
              }
          }).test().assertResult(1);
  
          Maybe.just(1).retryWhen(new Function<Observable<? extends Throwable>, Observable<Object>>() {
              @SuppressWarnings({ "rawtypes", "unchecked" })
              @Override
              public Observable<Object> apply(Observable<? extends Throwable> v) throws Exception {
                  return (Observable)v;
              }
          }).test().assertResult(1);
      }
  
      @Test
      public void onErrorResumeNextEmpty() {
          Maybe.empty()
              .onErrorResumeNext(Maybe.just(1))
              .test()
              .assertNoValues()
              .assertNoErrors()
              .assertComplete();
      }
  
      @Test
      public void onErrorResumeNextValue() {
          Maybe.just(1)
              .onErrorResumeNext(Maybe.<Integer>empty())
              .test()
              .assertNoErrors()
              .assertValue(1);
      }
  
      @Test
      public void onErrorResumeNextError() {
          Maybe.error(new RuntimeException("some error"))
              .onErrorResumeNext(Maybe.empty())
              .test()
              .assertNoValues()
              .assertNoErrors()
              .assertComplete();
      }
  
      @Test
      public void valueConcatWithValue() {
          Maybe.just(1)
              .concatWith(Maybe.just(2))
              .test()
              .assertNoErrors()
              .assertComplete()
              .assertValues(1, 2);
      }
  
      @Test
      public void errorConcatWithValue() {
          Maybe.<Integer>error(new RuntimeException("error"))
              .concatWith(Maybe.just(2))
              .test()
              .assertError(RuntimeException.class)
              .assertErrorMessage("error")
              .assertNoValues();
      }
  
      @Test
      public void valueConcatWithError() {
          Maybe.just(1)
              .concatWith(Maybe.<Integer>error(new RuntimeException("error")))
              .test()
              .assertValue(1)
              .assertError(RuntimeException.class)
              .assertErrorMessage("error");
      }
  
      @Test
      public void emptyConcatWithValue() {
          Maybe.<Integer>empty()
              .concatWith(Maybe.just(2))
              .test()
              .assertNoErrors()
              .assertComplete()
              .assertValues(2);
      }
  
      @Test
      public void emptyConcatWithError() {
          Maybe.<Integer>empty()
              .concatWith(Maybe.<Integer>error(new RuntimeException("error")))
              .test()
              .assertNoValues()
              .assertError(RuntimeException.class)
              .assertErrorMessage("error");
      }
  }
  