/** * Allows using and disposing a resource while running a SingleSource instance generated from * that resource (similar to a try-with-resources). * <dl> * <dt><b>Scheduler:</b></dt> * <dd>{@code using} does not operate by default on a particular {@link Scheduler}.</dd> * </dl> * @param <T> the value type of the SingleSource generated * @param <U> the resource type * @param resourceSupplier the Callable called for each SingleObserver to generate a resource Object * @param singleFunction the function called with the returned resource * Object from {@code resourceSupplier} and should return a SingleSource instance * to be run by the operator * @param disposer the consumer of the generated resource that is called exactly once for * that particular resource when the generated SingleSource terminates * (successfully or with an error) or gets cancelled. * @return the new Single instance * @since 2.0 */ @CheckReturnValue @SchedulerSupport(SchedulerSupport.NONE) public static <T, U> Single<T> using(Callable<U> resourceSupplier, Function<? super U, ? extends SingleSource<? extends T>> singleFunction, Consumer<? super U> disposer) { return using(resourceSupplier, singleFunction, disposer, true); }
/** * Allows using and disposing a resource while running a SingleSource instance generated from * that resource (similar to a try-with-resources). * <dl> * <dt><b>Scheduler:</b></dt> * <dd>{@code using} does not operate by default on a particular {@link Scheduler}.</dd> * </dl> * @param <T> the value type of the SingleSource generated * @param <U> the resource type * @param resourceSupplier the Callable called for each SingleObserver to generate a resource Object * @param singleFunction the function called with the returned resource * Object from {@code resourceSupplier} and should return a SingleSource instance * to be run by the operator * @param disposer the consumer of the generated resource that is called exactly once for * that particular resource when the generated SingleSource terminates * (successfully or with an error) or gets cancelled. * @return the new Single instance * @since 2.0 */ @CheckReturnValue @SchedulerSupport(SchedulerSupport.NONE) public static <T, U> Single<T> using(Callable<U> resourceSupplier, Function<? super U, ? extends SingleSource<? extends T>> singleFunction, Consumer<? super U> disposer) { return using(resourceSupplier, singleFunction, disposer, true); }
@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 usingSingleSupplierNull() { Single.using(new Callable<Object>() { @Override public Object call() { return 1; } }, null, Functions.emptyConsumer()); }
@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 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 public void disposerThrowsEager() { Single.using(Functions.justCallable(Disposables.empty()), mapper, disposerThrows) .test() .assertFailure(TestException.class); }
@Test public void dispose() { Disposable d = Disposables.empty(); Single.using(Functions.justCallable(d), mapper, disposer, false) .test(true); assertTrue(d.isDisposed()); }
@Test public void resourceSupplierThrows() { Single.using(new Callable<Integer>() { @Override public Integer call() throws Exception { throw new TestException(); } }, Functions.justFunction(Single.just(1)), Functions.emptyConsumer()) .test() .assertFailure(TestException.class); }
@Test public void eagerMapperThrowsDisposerThrows() { TestObserver<Integer> ts = Single.using(Functions.justCallable(Disposables.empty()), mapperThrows, disposerThrows) .test() .assertFailure(CompositeException.class); List<Throwable> ce = TestCommonHelper.compositeList(ts.errors().get(0)); TestCommonHelper.assertError(ce, 0, TestException.class, "Mapper"); TestCommonHelper.assertError(ce, 1, TestException.class, "Disposer"); }
@Test public void resourceDisposedIfMapperCrashesNonEager() { Disposable d = Disposables.empty(); Single.using(Functions.justCallable(d), mapperThrows, disposer, false) .test() .assertFailure(TestException.class); assertTrue(d.isDisposed()); }
@Test public void normalEager() { Single.using(Functions.justCallable(1), Functions.justFunction(Single.just(1)), Functions.emptyConsumer()) .test() .assertResult(1); }
@Test public void errorAndDisposerThrowsEager() { TestObserver<Integer> ts = Single.using(Functions.justCallable(Disposables.empty()), new Function<Disposable, SingleSource<Integer>>() { @Override public SingleSource<Integer> apply(Disposable v) throws Exception { return Single.<Integer>error(new TestException("Mapper-run")); } }, disposerThrows) .test() .assertFailure(CompositeException.class); List<Throwable> ce = TestCommonHelper.compositeList(ts.errors().get(0)); TestCommonHelper.assertError(ce, 0, TestException.class, "Mapper-run"); TestCommonHelper.assertError(ce, 1, TestException.class, "Disposer"); }
@Test public void normalNonEager() { Single.using(Functions.justCallable(1), Functions.justFunction(Single.just(1)), Functions.emptyConsumer(), false) .test() .assertResult(1); }
@Test public void resourceDisposedIfMapperCrashes() { Disposable d = Disposables.empty(); Single.using(Functions.justCallable(d), mapperThrows, disposer) .test() .assertFailure(TestException.class); assertTrue(d.isDisposed()); }
@Test public void errorNonEager() { Single.using(Functions.justCallable(1), Functions.justFunction(Single.error(new TestException())), Functions.emptyConsumer(), false) .test() .assertFailure(TestException.class); }
@Test public void errorEager() { Single.using(Functions.justCallable(1), Functions.justFunction(Single.error(new TestException())), Functions.emptyConsumer()) .test() .assertFailure(TestException.class); }
@Test public void disposerThrowsNonEager() { List<Throwable> errors = TestCommonHelper.trackPluginErrors(); try { Single.using(Functions.justCallable(Disposables.empty()), mapper, disposerThrows, false) .test() .assertResult(1); TestCommonHelper.assertUndeliverable(errors, 0, TestException.class, "Disposer"); } finally { RxJavaCommonPlugins.reset(); } }
@Test public void noneagerMapperThrowsDisposerThrows() { List<Throwable> errors = TestCommonHelper.trackPluginErrors(); try { Single.using(Functions.justCallable(Disposables.empty()), mapperThrows, disposerThrows, false) .test() .assertFailureAndMessage(TestException.class, "Mapper"); TestCommonHelper.assertUndeliverable(errors, 0, TestException.class, "Disposer"); } finally { RxJavaCommonPlugins.reset(); } }
@Test public void errorAndDisposerThrowsNonEager() { List<Throwable> errors = TestCommonHelper.trackPluginErrors(); try { Single.using(Functions.justCallable(Disposables.empty()), new Function<Disposable, SingleSource<Integer>>() { @Override public SingleSource<Integer> apply(Disposable v) throws Exception { return Single.<Integer>error(new TestException("Mapper-run")); } }, disposerThrows, false) .test() .assertFailure(TestException.class); TestCommonHelper.assertUndeliverable(errors, 0, TestException.class, "Disposer"); } finally { RxJavaCommonPlugins.reset(); } }