/** * 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.internal.operators.flowable; import static org.junit.Assert.*; import java.util.*; import org.junit.Test; import io.reactivex.Flowable; import io.reactivex.exceptions.*; import io.reactivex.functions.Function; import io.reactivex.processors.PublishProcessor; import io.reactivex.subscribers.TestSubscriber; public class FlowableConcatDelayErrorTest { @Test public void mainCompletes() { PublishProcessor<Integer> source = PublishProcessor.create(); TestSubscriber<Integer> ts = TestSubscriber.create(); source.concatMapDelayError(new Function<Integer, Flowable<Integer>>() { @Override public Flowable<Integer> apply(Integer v) { return Flowable.range(v, 2); } }).subscribe(ts); source.onNext(1); source.onNext(2); source.onComplete(); ts.assertValues(1, 2, 2, 3); ts.assertNoErrors(); ts.assertComplete(); } @Test public void mainErrors() { PublishProcessor<Integer> source = PublishProcessor.create(); TestSubscriber<Integer> ts = TestSubscriber.create(); source.concatMapDelayError(new Function<Integer, Flowable<Integer>>() { @Override public Flowable<Integer> apply(Integer v) { return Flowable.range(v, 2); } }).subscribe(ts); source.onNext(1); source.onNext(2); source.onError(new TestException()); ts.assertValues(1, 2, 2, 3); ts.assertError(TestException.class); ts.assertNotComplete(); } @Test public void innerErrors() { final Flowable<Integer> inner = Flowable.range(1, 2) .concatWith(Flowable.<Integer>error(new TestException())); TestSubscriber<Integer> ts = TestSubscriber.create(); Flowable.range(1, 3).concatMapDelayError(new Function<Integer, Flowable<Integer>>() { @Override public Flowable<Integer> apply(Integer v) { return inner; } }).subscribe(ts); ts.assertValues(1, 2, 1, 2, 1, 2); ts.assertError(CompositeException.class); ts.assertNotComplete(); } @Test public void singleInnerErrors() { final Flowable<Integer> inner = Flowable.range(1, 2).concatWith(Flowable.<Integer>error(new TestException())); TestSubscriber<Integer> ts = TestSubscriber.create(); Flowable.just(1) .hide() // prevent scalar optimization .concatMapDelayError(new Function<Integer, Flowable<Integer>>() { @Override public Flowable<Integer> apply(Integer v) { return inner; } }).subscribe(ts); ts.assertValues(1, 2); ts.assertError(TestException.class); ts.assertNotComplete(); } @Test public void innerNull() { TestSubscriber<Integer> ts = TestSubscriber.create(); Flowable.just(1) .hide() // prevent scalar optimization .concatMapDelayError(new Function<Integer, Flowable<Integer>>() { @Override public Flowable<Integer> apply(Integer v) { return null; } }).subscribe(ts); ts.assertNoValues(); ts.assertError(NullPointerException.class); ts.assertNotComplete(); } @Test public void innerThrows() { TestSubscriber<Integer> ts = TestSubscriber.create(); Flowable.just(1) .hide() // prevent scalar optimization .concatMapDelayError(new Function<Integer, Flowable<Integer>>() { @Override public Flowable<Integer> apply(Integer v) { throw new TestException(); } }).subscribe(ts); ts.assertNoValues(); ts.assertError(TestException.class); ts.assertNotComplete(); } @Test public void innerWithEmpty() { TestSubscriber<Integer> ts = TestSubscriber.create(); Flowable.range(1, 3) .concatMapDelayError(new Function<Integer, Flowable<Integer>>() { @Override public Flowable<Integer> apply(Integer v) { return v == 2 ? Flowable.<Integer>empty() : Flowable.range(1, 2); } }).subscribe(ts); ts.assertValues(1, 2, 1, 2); ts.assertNoErrors(); ts.assertComplete(); } @Test public void innerWithScalar() { TestSubscriber<Integer> ts = TestSubscriber.create(); Flowable.range(1, 3) .concatMapDelayError(new Function<Integer, Flowable<Integer>>() { @Override public Flowable<Integer> apply(Integer v) { return v == 2 ? Flowable.just(3) : Flowable.range(1, 2); } }).subscribe(ts); ts.assertValues(1, 2, 3, 1, 2); ts.assertNoErrors(); ts.assertComplete(); } @Test public void backpressure() { TestSubscriber<Integer> ts = TestSubscriber.create(0); Flowable.range(1, 3).concatMapDelayError(new Function<Integer, Flowable<Integer>>() { @Override public Flowable<Integer> apply(Integer v) { return Flowable.range(v, 2); } }).subscribe(ts); ts.assertNoValues(); ts.assertNoErrors(); ts.assertNotComplete(); ts.request(1); ts.assertValues(1); ts.assertNoErrors(); ts.assertNotComplete(); ts.request(3); ts.assertValues(1, 2, 2, 3); ts.assertNoErrors(); ts.assertNotComplete(); ts.request(2); ts.assertValues(1, 2, 2, 3, 3, 4); ts.assertNoErrors(); ts.assertComplete(); } static <T> Flowable<T> withError(Flowable<T> source) { return source.concatWith(Flowable.<T>error(new TestException())); } @Test public void concatDelayErrorFlowable() { TestSubscriber<Integer> ts = TestSubscriber.create(); Flowable.concatDelayError( Flowable.just(Flowable.just(1), Flowable.just(2))) .subscribe(ts); ts.assertValues(1, 2); ts.assertNoErrors(); ts.assertComplete(); } @Test public void concatDelayErrorFlowableError() { TestSubscriber<Integer> ts = TestSubscriber.create(); Flowable.concatDelayError( withError(Flowable.just(withError(Flowable.just(1)), withError(Flowable.just(2))))) .subscribe(ts); ts.assertValues(1, 2); ts.assertError(CompositeException.class); ts.assertNotComplete(); CompositeException ce = (CompositeException)ts.errors().get(0); List<Throwable> cex = ce.getExceptions(); assertEquals(3, cex.size()); assertTrue(cex.get(0).toString(), cex.get(0) instanceof TestException); assertTrue(cex.get(1).toString(), cex.get(1) instanceof TestException); assertTrue(cex.get(2).toString(), cex.get(2) instanceof TestException); } @SuppressWarnings("unchecked") @Test public void concatDelayErrorIterable() { TestSubscriber<Integer> ts = TestSubscriber.create(); Flowable.concatDelayError( Arrays.asList(Flowable.just(1), Flowable.just(2))) .subscribe(ts); ts.assertValues(1, 2); ts.assertNoErrors(); ts.assertComplete(); } @SuppressWarnings("unchecked") @Test public void concatDelayErrorIterableError() { TestSubscriber<Integer> ts = TestSubscriber.create(); Flowable.concatDelayError( Arrays.asList(withError(Flowable.just(1)), withError(Flowable.just(2)))) .subscribe(ts); ts.assertValues(1, 2); ts.assertError(CompositeException.class); ts.assertNotComplete(); assertEquals(2, ((CompositeException)ts.errors().get(0)).getExceptions().size()); } }