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.assertTrue;
  
  import java.lang.reflect.*;
  import java.util.*;
  import java.util.concurrent.*;
  
  import org.junit.*;
  
  import io.reactivex.common.*;
  import io.reactivex.common.exceptions.*;
  import io.reactivex.common.functions.*;
  import io.reactivex.common.internal.functions.Functions;
  
  public class SingleNullTests {
  
      Single<Integer> just1 = Single.just(1);
  
      Single<Integer> error = Single.error(new TestException());
  
      @Test(expected = NullPointerException.class)
      public void ambIterableNull() {
          Single.amb((Iterable<Single<Integer>>)null);
      }
  
      @Test
      public void ambIterableIteratorNull() {
          Single.amb(new Iterable<Single<Object>>() {
              @Override
              public Iterator<Single<Object>> iterator() {
                  return null;
              }
          }).test().assertError(NullPointerException.class);
      }
  
      @SuppressWarnings("unchecked")
      @Test
      public void ambIterableOneIsNull() {
          Single.amb(Arrays.asList(null, just1))
                  .test()
                  .assertError(NullPointerException.class);
      }
  
      @Test(expected = NullPointerException.class)
      public void ambArrayNull() {
          Single.ambArray((Single<Integer>[])null);
      }
  
      @SuppressWarnings("unchecked")
      @Test
      public void ambArrayOneIsNull() {
          Single.ambArray(null, just1)
              .test()
              .assertError(NullPointerException.class);
      }
  
      @Test(expected = NullPointerException.class)
      public void concatIterableNull() {
          Single.concat((Iterable<Single<Integer>>)null);
      }
  
      @Test(expected = NullPointerException.class)
      public void concatIterableIteratorNull() {
          Single.concat(new Iterable<Single<Object>>() {
              @Override
              public Iterator<Single<Object>> iterator() {
                  return null;
              }
          }).blockingSubscribe();
      }
  
      @SuppressWarnings("unchecked")
      @Test(expected = NullPointerException.class)
      public void concatIterableOneIsNull() {
          Single.concat(Arrays.asList(just1, null)).blockingSubscribe();
      }
  
      @Test(expected = NullPointerException.class)
      public void concatObservableNull() {
          Single.concat((Observable<Single<Integer>>)null);
      }
  
      @Test
      public void concatNull() throws Exception {
          int maxArgs = 4;
  
          @SuppressWarnings("rawtypes")
          Class<Single> clazz = Single.class;
          for (int argCount = 2; argCount <= maxArgs; argCount++) {
              for (int argNull = 1; argNull <= argCount; argNull++) {
                  Class<?>[] params = new Class[argCount];
                  Arrays.fill(params, SingleSource.class);
  
                  Object[] values = new Object[argCount];
                  Arrays.fill(values, just1);
                  values[argNull - 1] = null;
  
                  Method m = clazz.getMethod("concat", params);
  
                  try {
                      m.invoke(null, values);
                      Assert.fail("No exception for argCount " + argCount + " / argNull " + argNull);
                  } catch (InvocationTargetException ex) {
                      if (!(ex.getCause() instanceof NullPointerException)) {
                          Assert.fail("Unexpected exception for argCount " + argCount + " / argNull " + argNull + ": " + ex);
                      }
                  }
              }
          }
      }
  
      @Test(expected = NullPointerException.class)
      public void createNull() {
          Single.unsafeCreate(null);
      }
  
      @Test(expected = NullPointerException.class)
      public void deferNull() {
          Single.defer(null);
      }
  
      @Test(expected = NullPointerException.class)
      public void deferReturnsNull() {
          Single.defer(Functions.<Single<Object>>nullSupplier()).blockingGet();
      }
  
      @Test(expected = NullPointerException.class)
      public void errorSupplierNull() {
          Single.error((Callable<Throwable>)null);
      }
  
      @Test(expected = NullPointerException.class)
      public void errorSupplierReturnsNull() {
          Single.error(Functions.<Throwable>nullSupplier()).blockingGet();
      }
  
      @Test(expected = NullPointerException.class)
      public void errorNull() {
          Single.error((Throwable)null);
      }
  
      @Test(expected = NullPointerException.class)
      public void fromCallableNull() {
          Single.fromCallable(null);
      }
  
      @Test(expected = NullPointerException.class)
      public void fromCallableReturnsNull() {
          Single.fromCallable(new Callable<Object>() {
              @Override
              public Object call() throws Exception {
                  return null;
              }
          }).blockingGet();
      }
  
      @Test(expected = NullPointerException.class)
      public void fromFutureNull() {
          Single.fromFuture((Future<Integer>)null);
      }
  
      @Test(expected = NullPointerException.class)
      public void fromFutureReturnsNull() {
          FutureTask<Object> f = new FutureTask<Object>(Functions.EMPTY_RUNNABLE, null);
          f.run();
          Single.fromFuture(f).blockingGet();
      }
  
      @Test(expected = NullPointerException.class)
      public void fromFutureTimedFutureNull() {
          Single.fromFuture(null, 1, TimeUnit.SECONDS);
      }
  
      @Test(expected = NullPointerException.class)
      public void fromFutureTimedUnitNull() {
          Single.fromFuture(new FutureTask<Object>(new Callable<Object>() {
              @Override
              public Object call() throws Exception {
                  return null;
              }
          }), 1, null);
      }
  
      @Test(expected = NullPointerException.class)
      public void fromFutureTimedSchedulerNull() {
          Single.fromFuture(new FutureTask<Object>(new Callable<Object>() {
              @Override
              public Object call() throws Exception {
                  return null;
              }
          }), 1, TimeUnit.SECONDS, null);
      }
  
      @Test(expected = NullPointerException.class)
      public void fromFutureTimedReturnsNull() {
          FutureTask<Object> f = new FutureTask<Object>(Functions.EMPTY_RUNNABLE, null);
          f.run();
          Single.fromFuture(f, 1, TimeUnit.SECONDS).blockingGet();
      }
  
      @Test(expected = NullPointerException.class)
      public void fromFutureSchedulerNull() {
          Single.fromFuture(new FutureTask<Object>(new Callable<Object>() {
              @Override
              public Object call() throws Exception {
                  return null;
              }
          }), null);
      }
  
      @Test(expected = NullPointerException.class)
      public void justNull() {
          Single.just(null);
      }
  
      @Test(expected = NullPointerException.class)
      public void mergeIterableNull() {
          Single.merge((Iterable<Single<Integer>>)null);
      }
  
      @Test(expected = NullPointerException.class)
      public void mergeIterableIteratorNull() {
          Single.merge(new Iterable<Single<Object>>() {
              @Override
              public Iterator<Single<Object>> iterator() {
                  return null;
              }
          }).blockingSubscribe();
      }
  
      @SuppressWarnings("unchecked")
      @Test(expected = NullPointerException.class)
      public void mergeIterableOneIsNull() {
          Single.merge(Arrays.asList(null, just1)).blockingSubscribe();
      }
  
      @Test(expected = NullPointerException.class)
      public void mergeSingleNull() {
          Single.merge((Single<Single<Integer>>)null);
      }
  
      @Test
      public void mergeNull() throws Exception {
          int maxArgs = 4;
  
          @SuppressWarnings("rawtypes")
          Class<Single> clazz = Single.class;
          for (int argCount = 2; argCount <= maxArgs; argCount++) {
              for (int argNull = 1; argNull <= argCount; argNull++) {
                  Class<?>[] params = new Class[argCount];
                  Arrays.fill(params, SingleSource.class);
  
                  Object[] values = new Object[argCount];
                  Arrays.fill(values, just1);
                  values[argNull - 1] = null;
  
                  Method m = clazz.getMethod("merge", params);
  
                  try {
                      m.invoke(null, values);
                      Assert.fail("No exception for argCount " + argCount + " / argNull " + argNull);
                  } catch (InvocationTargetException ex) {
                      if (!(ex.getCause() instanceof NullPointerException)) {
                          Assert.fail("Unexpected exception for argCount " + argCount + " / argNull " + argNull + ": " + ex);
                      }
                  }
              }
          }
      }
  
      @Test(expected = NullPointerException.class)
      public void timerUnitNull() {
          Single.timer(1, null);
      }
  
      @Test(expected = NullPointerException.class)
      public void timerSchedulerNull() {
          Single.timer(1, TimeUnit.SECONDS, null);
      }
  
      @Test(expected = NullPointerException.class)
      public void equalsFirstNull() {
          Single.equals(null, just1);
      }
  
      @Test(expected = NullPointerException.class)
      public void equalsSecondNull() {
          Single.equals(just1, null);
      }
  
      @Test(expected = NullPointerException.class)
      public void usingResourceSupplierNull() {
          Single.using(null, new Function<Object, Single<Integer>>() {
              @Override
              public Single<Integer> apply(Object d) {
                  return just1;
              }
          }, Functions.emptyConsumer());
      }
  
      @Test(expected = NullPointerException.class)
      public void usingSingleSupplierNull() {
          Single.using(new Callable<Object>() {
              @Override
              public Object call() {
                  return 1;
              }
          }, null, Functions.emptyConsumer());
      }
  
      @Test(expected = NullPointerException.class)
      public void usingSingleSupplierReturnsNull() {
          Single.using(new Callable<Object>() {
              @Override
              public Object call() {
                  return 1;
              }
          }, new Function<Object, Single<Object>>() {
              @Override
              public Single<Object> apply(Object d) {
                  return null;
              }
          }, Functions.emptyConsumer()).blockingGet();
      }
  
      @Test(expected = NullPointerException.class)
      public void usingDisposeNull() {
          Single.using(new Callable<Object>() {
              @Override
              public Object call() {
                  return 1;
              }
          }, new Function<Object, Single<Integer>>() {
              @Override
              public Single<Integer> apply(Object d) {
                  return just1;
              }
          }, null);
      }
  
      @Test(expected = NullPointerException.class)
      public void zipIterableNull() {
          Single.zip((Iterable<Single<Integer>>)null, new Function<Object[], Object>() {
              @Override
              public Object apply(Object[] v) {
                  return 1;
              }
          });
      }
  
      @Test(expected = NullPointerException.class)
      public void zipIterableIteratorNull() {
          Single.zip(new Iterable<Single<Object>>() {
              @Override
              public Iterator<Single<Object>> iterator() {
                  return null;
              }
          }, new Function<Object[], Object>() {
              @Override
              public Object apply(Object[] v) {
                  return 1;
              }
          }).blockingGet();
      }
  
      @SuppressWarnings("unchecked")
      @Test(expected = NullPointerException.class)
      public void zipIterableOneIsNull() {
          Single.zip(Arrays.asList(null, just1), new Function<Object[], Object>() {
              @Override
              public Object apply(Object[] v) {
                  return 1;
              }
          }).blockingGet();
      }
  
      @SuppressWarnings("unchecked")
      @Test(expected = NullPointerException.class)
      public void zipIterableOneFunctionNull() {
          Single.zip(Arrays.asList(just1, just1), null).blockingGet();
      }
  
      @SuppressWarnings("unchecked")
      @Test(expected = NullPointerException.class)
      public void zipIterableOneFunctionReturnsNull() {
          Single.zip(Arrays.asList(just1, just1), new Function<Object[], Object>() {
              @Override
              public Object apply(Object[] v) {
                  return null;
              }
          }).blockingGet();
      }
  
      @SuppressWarnings("unchecked")
      @Test
      public void zipNull() throws Exception {
          @SuppressWarnings("rawtypes")
          Class<Single> clazz = Single.class;
          for (int argCount = 3; argCount < 10; argCount++) {
              for (int argNull = 1; argNull <= argCount; argNull++) {
                  Class<?>[] params = new Class[argCount + 1];
                  Arrays.fill(params, SingleSource.class);
                  Class<?> fniClass = Class.forName("io.reactivex.common.functions.Function" + argCount);
                  params[argCount] = fniClass;
  
                  Object[] values = new Object[argCount + 1];
                  Arrays.fill(values, just1);
                  values[argNull - 1] = null;
                  values[argCount] = Proxy.newProxyInstance(getClass().getClassLoader(), new Class[] { fniClass }, new InvocationHandler() {
                      @Override
                      public Object invoke(Object o, Method m, Object[] a) throws Throwable {
                          return 1;
                      }
                  });
  
                  Method m = clazz.getMethod("zip", params);
  
                  try {
                      m.invoke(null, values);
                      Assert.fail("No exception for argCount " + argCount + " / argNull " + argNull);
                  } catch (InvocationTargetException ex) {
                      if (!(ex.getCause() instanceof NullPointerException)) {
                          Assert.fail("Unexpected exception for argCount " + argCount + " / argNull " + argNull + ": " + ex);
                      }
                  }
  
                  values[argCount] = Proxy.newProxyInstance(getClass().getClassLoader(), new Class[] { fniClass }, new InvocationHandler() {
                      @Override
                      public Object invoke(Object o, Method m1, Object[] a) throws Throwable {
                          return null;
                      }
                  });
                  try {
                      ((Single<Object>)m.invoke(null, values)).blockingGet();
                      Assert.fail("No exception for argCount " + argCount + " / argNull " + argNull);
                  } catch (InvocationTargetException ex) {
                      if (!(ex.getCause() instanceof NullPointerException)) {
                          Assert.fail("Unexpected exception for argCount " + argCount + " / argNull " + argNull + ": " + ex);
                      }
                  }
  
              }
  
              Class<?>[] params = new Class[argCount + 1];
              Arrays.fill(params, SingleSource.class);
              Class<?> fniClass = Class.forName("io.reactivex.common.functions.Function" + argCount);
              params[argCount] = fniClass;
  
              Object[] values = new Object[argCount + 1];
              Arrays.fill(values, just1);
              values[argCount] = null;
  
              Method m = clazz.getMethod("zip", params);
  
              try {
                  m.invoke(null, values);
                  Assert.fail("No exception for argCount " + argCount + " / zipper function ");
              } catch (InvocationTargetException ex) {
                  if (!(ex.getCause() instanceof NullPointerException)) {
                      Assert.fail("Unexpected exception for argCount " + argCount + " / zipper function: " + ex);
                  }
              }
          }
      }
  
      @Test(expected = NullPointerException.class)
      public void zip2FirstNull() {
          Single.zip(null, just1, new BiFunction<Object, Integer, Object>() {
              @Override
              public Object apply(Object a, Integer b) {
                  return 1;
              }
          });
      }
  
      @Test(expected = NullPointerException.class)
      public void zip2SecondNull() {
          Single.zip(just1, null, new BiFunction<Integer, Object, Object>() {
              @Override
              public Object apply(Integer a, Object b) {
                  return 1;
              }
          });
      }
  
      @Test(expected = NullPointerException.class)
      public void zip2ZipperNull() {
          Single.zip(just1, just1, null);
      }
  
      @Test(expected = NullPointerException.class)
      public void zip2ZipperReturnsdNull() {
          Single.zip(just1, null, new BiFunction<Integer, Object, Object>() {
              @Override
              public Object apply(Integer a, Object b) {
                  return null;
              }
          }).blockingGet();
      }
  
      @Test(expected = NullPointerException.class)
      public void zipArrayNull() {
          Single.zipArray(new Function<Object[], Object>() {
              @Override
              public Object apply(Object[] v) {
                  return 1;
              }
          }, (Single<Integer>[])null);
      }
  
      @SuppressWarnings("unchecked")
      @Test(expected = NullPointerException.class)
      public void zipIterableTwoIsNull() {
          Single.zip(Arrays.asList(just1, null), new Function<Object[], Object>() {
              @Override
              public Object apply(Object[] v) {
                  return 1;
              }
          })
          .blockingGet();
      }
  
      @SuppressWarnings("unchecked")
      @Test(expected = NullPointerException.class)
      public void zipArrayOneIsNull() {
          Single.zipArray(new Function<Object[], Object>() {
              @Override
              public Object apply(Object[] v) {
                  return 1;
              }
          }, just1, null)
          .blockingGet();
      }
  
      @SuppressWarnings("unchecked")
      @Test(expected = NullPointerException.class)
      public void zipArrayFunctionNull() {
          Single.zipArray(null, just1, just1);
      }
  
      @SuppressWarnings("unchecked")
      @Test(expected = NullPointerException.class)
      public void zipArrayFunctionReturnsNull() {
          Single.zipArray(new Function<Object[], Object>() {
              @Override
              public Object apply(Object[] v) {
                  return null;
              }
          }, just1, just1).blockingGet();
      }
  
      //**************************************************
      // Instance methods
      //**************************************************
  
      @Test(expected = NullPointerException.class)
      public void ambWithNull() {
          just1.ambWith(null);
      }
  
      @Test(expected = NullPointerException.class)
      public void composeNull() {
          just1.compose(null);
      }
  
      @Test(expected = NullPointerException.class)
      public void castNull() {
          just1.cast(null);
      }
  
      @Test(expected = NullPointerException.class)
      public void concatWith() {
          just1.concatWith(null);
      }
  
      @Test(expected = NullPointerException.class)
      public void delayUnitNull() {
          just1.delay(1, null);
      }
  
      @Test(expected = NullPointerException.class)
      public void delaySchedulerNull() {
          just1.delay(1, TimeUnit.SECONDS, null);
      }
  
      @Test(expected = NullPointerException.class)
      public void doOnSubscribeNull() {
          just1.doOnSubscribe(null);
      }
  
      @Test(expected = NullPointerException.class)
      public void doOnSuccess() {
          just1.doOnSuccess(null);
      }
  
      @Test(expected = NullPointerException.class)
      public void doOnError() {
          error.doOnError(null);
      }
  
      @Test(expected = NullPointerException.class)
      public void doOnDisposeNull() {
          just1.doOnDispose(null);
      }
  
      @Test(expected = NullPointerException.class)
      public void flatMapNull() {
          just1.flatMap(null);
      }
  
      @Test(expected = NullPointerException.class)
      public void flatMapFunctionReturnsNull() {
          just1.flatMap(new Function<Integer, Single<Object>>() {
              @Override
              public Single<Object> apply(Integer v) {
                  return null;
              }
          }).blockingGet();
      }
  
      @Test(expected = NullPointerException.class)
      public void liftNull() {
          just1.lift(null);
      }
  
      @Test(expected = NullPointerException.class)
      public void liftFunctionReturnsNull() {
          just1.lift(new SingleOperator<Object, Integer>() {
              @Override
              public SingleObserver<? super Integer> apply(SingleObserver<? super Object> s) {
                  return null;
              }
          }).blockingGet();
      }
  
      @Test(expected = NullPointerException.class)
      public void containsNull() {
          just1.contains(null);
      }
  
      @Test(expected = NullPointerException.class)
      public void containsComparerNull() {
          just1.contains(1, null);
      }
  
      @Test(expected = NullPointerException.class)
      public void mergeWithNull() {
          just1.mergeWith(null);
      }
  
      @Test(expected = NullPointerException.class)
      public void observeOnNull() {
          just1.observeOn(null);
      }
  
      @Test(expected = NullPointerException.class)
      public void onErrorReturnSupplierNull() {
          just1.onErrorReturn((Function<Throwable, Integer>)null);
      }
  
      @Test(expected = NullPointerException.class)
      public void onErrorReturnsSupplierReturnsNull() {
          error.onErrorReturn(new Function<Throwable, Integer>() {
              @Override
              public Integer apply(Throwable t) throws Exception {
                  return null;
              }
          }).blockingGet();
      }
  
      @Test(expected = NullPointerException.class)
      public void onErrorReturnValueNull() {
          error.onErrorReturnItem(null);
      }
  
      @Test(expected = NullPointerException.class)
      public void onErrorResumeNextSingleNull() {
          error.onErrorResumeNext((Single<Integer>)null);
      }
  
      @Test(expected = NullPointerException.class)
      public void onErrorResumeNextFunctionNull() {
          error.onErrorResumeNext((Function<Throwable, Single<Integer>>)null);
      }
  
      @Test
      public void onErrorResumeNextFunctionReturnsNull() {
          try {
              error.onErrorResumeNext(new Function<Throwable, Single<Integer>>() {
                  @Override
                  public Single<Integer> apply(Throwable e) {
                      return null;
                  }
              }).blockingGet();
          } catch (CompositeException ex) {
              assertTrue(ex.toString(), ex.getExceptions().get(1) instanceof NullPointerException);
          }
      }
  
      @Test(expected = NullPointerException.class)
      public void repeatWhenNull() {
          error.repeatWhen(null);
      }
  
      @Test(expected = NullPointerException.class)
      public void repeatWhenFunctionReturnsNull() {
          error.repeatWhen(new Function<Observable<Object>, Observable<Object>>() {
              @Override
              public Observable<Object> apply(Observable<Object> v) {
                  return null;
              }
          }).blockingSubscribe();
      }
  
      @Test(expected = NullPointerException.class)
      public void repeatUntilNull() {
          error.repeatUntil(null);
      }
  
      @Test(expected = NullPointerException.class)
      public void retryBiPreducateNull() {
          error.retry((BiPredicate<Integer, Throwable>)null);
      }
  
      @Test(expected = NullPointerException.class)
      public void retryPredicateNull() {
          error.retry((Predicate<Throwable>)null);
      }
  
      @Test(expected = NullPointerException.class)
      public void retryWhenNull() {
          error.retryWhen(null);
      }
  
      @Test(expected = NullPointerException.class)
      public void retryWhenFunctionReturnsNull() {
          error.retryWhen(new Function<Observable<? extends Throwable>, Observable<Object>>() {
              @Override
              public Observable<Object> apply(Observable<? extends Throwable> e) {
                  return null;
              }
          }).blockingGet();
      }
  
      @Test(expected = NullPointerException.class)
      public void subscribeBiConsumerNull() {
          just1.subscribe((BiConsumer<Integer, Throwable>)null);
      }
  
      @Test(expected = NullPointerException.class)
      public void subscribeConsumerNull() {
          just1.subscribe((Consumer<Integer>)null);
      }
  
      @Test(expected = NullPointerException.class)
      public void subscribeSingeSubscriberNull() {
          just1.subscribe((SingleObserver<Integer>)null);
      }
  
      @Test(expected = NullPointerException.class)
      public void subscribeOnSuccessNull() {
          just1.subscribe(null, new Consumer<Throwable>() {
              @Override
              public void accept(Throwable e) { }
          });
      }
  
      @Test(expected = NullPointerException.class)
      public void subscribeOnErrorNull() {
          just1.subscribe(new Consumer<Integer>() {
              @Override
              public void accept(Integer v) { }
          }, null);
      }
  
      @Test(expected = NullPointerException.class)
      public void subscribeOnNull() {
          just1.subscribeOn(null);
      }
  
      @Test(expected = NullPointerException.class)
      public void timeoutUnitNull() {
          just1.timeout(1, null);
      }
  
      @Test(expected = NullPointerException.class)
      public void timeoutSchedulerNull() {
          just1.timeout(1, TimeUnit.SECONDS, (Scheduler)null);
      }
  
      @Test(expected = NullPointerException.class)
      public void timeoutOtherNull() {
          just1.timeout(1, TimeUnit.SECONDS, Schedulers.single(), null);
      }
  
      @Test(expected = NullPointerException.class)
      public void timeoutOther2Null() {
          just1.timeout(1, TimeUnit.SECONDS, (Single<Integer>)null);
      }
  
      @Test(expected = NullPointerException.class)
      public void toNull() {
          just1.to(null);
      }
  
      @Test(expected = NullPointerException.class)
      public void zipWithNull() {
          just1.zipWith(null, new BiFunction<Integer, Object, Object>() {
              @Override
              public Object apply(Integer a, Object b) {
                  return 1;
              }
          });
      }
  
      @Test(expected = NullPointerException.class)
      public void zipWithFunctionNull() {
          just1.zipWith(just1, null);
      }
  
      @Test(expected = NullPointerException.class)
      public void zipWithFunctionReturnsNull() {
          just1.zipWith(just1, new BiFunction<Integer, Integer, Object>() {
              @Override
              public Object apply(Integer a, Integer b) {
                  return null;
              }
          }).blockingGet();
      }
  }
  