/** * 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 org.junit.*; import org.reactivestreams.*; import io.reactivex.*; import io.reactivex.exceptions.*; import io.reactivex.functions.Cancellable; import io.reactivex.processors.PublishProcessor; import io.reactivex.subscribers.*; public class FlowableFromSourceTest { PublishAsyncEmitter source; PublishAsyncEmitterNoCancel sourceNoCancel; TestSubscriber<Integer> ts; @Before public void before() { source = new PublishAsyncEmitter(); sourceNoCancel = new PublishAsyncEmitterNoCancel(); ts = new TestSubscriber<Integer>(0L); } @Test public void normalBuffered() { Flowable.create(source, BackpressureStrategy.BUFFER).subscribe(ts); source.onNext(1); source.onNext(2); source.onComplete(); ts.request(1); ts.assertValue(1); Assert.assertEquals(0, source.requested()); ts.request(1); ts.assertValues(1, 2); ts.assertNoErrors(); ts.assertComplete(); } @Test public void normalDrop() { Flowable.create(source, BackpressureStrategy.DROP).subscribe(ts); source.onNext(1); ts.request(1); ts.assertNoValues(); source.onNext(2); source.onComplete(); ts.assertValues(2); ts.assertNoErrors(); ts.assertComplete(); } @Test public void normalLatest() { Flowable.create(source, BackpressureStrategy.LATEST).subscribe(ts); source.onNext(1); source.onNext(2); source.onComplete(); ts.assertNoValues(); ts.request(1); ts.assertValues(2); ts.assertNoErrors(); ts.assertComplete(); } @Test public void normalMissing() { Flowable.create(source, BackpressureStrategy.MISSING).subscribe(ts); source.onNext(1); source.onNext(2); source.onComplete(); ts.assertValues(1, 2); ts.assertNoErrors(); ts.assertComplete(); } @Test public void normalMissingRequested() { Flowable.create(source, BackpressureStrategy.MISSING).subscribe(ts); ts.request(2); source.onNext(1); source.onNext(2); source.onComplete(); ts.assertValues(1, 2); ts.assertNoErrors(); ts.assertComplete(); } @Test public void normalError() { Flowable.create(source, BackpressureStrategy.ERROR).subscribe(ts); source.onNext(1); source.onNext(2); source.onComplete(); ts.assertNoValues(); ts.assertError(MissingBackpressureException.class); ts.assertNotComplete(); Assert.assertEquals("create: could not emit value due to lack of requests", ts.errors().get(0).getMessage()); } @Test public void errorBuffered() { Flowable.create(source, BackpressureStrategy.BUFFER).subscribe(ts); source.onNext(1); source.onNext(2); source.onError(new TestException()); ts.request(1); ts.assertValue(1); ts.request(1); ts.assertValues(1, 2); ts.assertError(TestException.class); ts.assertNotComplete(); } @Test public void errorLatest() { Flowable.create(source, BackpressureStrategy.LATEST).subscribe(ts); source.onNext(1); source.onNext(2); source.onError(new TestException()); ts.assertNoValues(); ts.request(1); ts.assertValues(2); ts.assertError(TestException.class); ts.assertNotComplete(); } @Test public void errorMissing() { Flowable.create(source, BackpressureStrategy.MISSING).subscribe(ts); source.onNext(1); source.onNext(2); source.onError(new TestException()); ts.request(1); ts.assertValues(1, 2); ts.assertError(TestException.class); ts.assertNotComplete(); } @Test public void unsubscribedBuffer() { Flowable.create(source, BackpressureStrategy.BUFFER).subscribe(ts); ts.cancel(); source.onNext(1); source.onNext(2); source.onError(new TestException()); ts.request(1); ts.assertNoValues(); ts.assertNoErrors(); ts.assertNotComplete(); } @Test public void unsubscribedLatest() { Flowable.create(source, BackpressureStrategy.LATEST).subscribe(ts); ts.cancel(); source.onNext(1); source.onNext(2); source.onError(new TestException()); ts.request(1); ts.assertNoValues(); ts.assertNoErrors(); ts.assertNotComplete(); } @Test public void unsubscribedError() { Flowable.create(source, BackpressureStrategy.ERROR).subscribe(ts); ts.cancel(); source.onNext(1); source.onNext(2); source.onError(new TestException()); ts.request(1); ts.assertNoValues(); ts.assertNoErrors(); ts.assertNotComplete(); } @Test public void unsubscribedDrop() { Flowable.create(source, BackpressureStrategy.DROP).subscribe(ts); ts.cancel(); source.onNext(1); source.onNext(2); source.onError(new TestException()); ts.request(1); ts.assertNoValues(); ts.assertNoErrors(); ts.assertNotComplete(); } @Test public void unsubscribedMissing() { Flowable.create(source, BackpressureStrategy.MISSING).subscribe(ts); ts.cancel(); source.onNext(1); source.onNext(2); source.onError(new TestException()); ts.request(1); ts.assertNoValues(); ts.assertNoErrors(); ts.assertNotComplete(); } @Test public void unsubscribedNoCancelBuffer() { Flowable.create(sourceNoCancel, BackpressureStrategy.BUFFER).subscribe(ts); ts.cancel(); sourceNoCancel.onNext(1); sourceNoCancel.onNext(2); sourceNoCancel.onError(new TestException()); ts.request(1); ts.assertNoValues(); ts.assertNoErrors(); ts.assertNotComplete(); } @Test public void unsubscribedNoCancelLatest() { Flowable.create(sourceNoCancel, BackpressureStrategy.LATEST).subscribe(ts); ts.cancel(); sourceNoCancel.onNext(1); sourceNoCancel.onNext(2); sourceNoCancel.onError(new TestException()); ts.request(1); ts.assertNoValues(); ts.assertNoErrors(); ts.assertNotComplete(); } @Test public void unsubscribedNoCancelError() { Flowable.create(sourceNoCancel, BackpressureStrategy.ERROR).subscribe(ts); ts.cancel(); sourceNoCancel.onNext(1); sourceNoCancel.onNext(2); sourceNoCancel.onError(new TestException()); ts.request(1); ts.assertNoValues(); ts.assertNoErrors(); ts.assertNotComplete(); } @Test public void unsubscribedNoCancelDrop() { Flowable.create(sourceNoCancel, BackpressureStrategy.DROP).subscribe(ts); ts.cancel(); sourceNoCancel.onNext(1); sourceNoCancel.onNext(2); sourceNoCancel.onError(new TestException()); ts.request(1); ts.assertNoValues(); ts.assertNoErrors(); ts.assertNotComplete(); } @Test public void unsubscribedNoCancelMissing() { Flowable.create(sourceNoCancel, BackpressureStrategy.MISSING).subscribe(ts); ts.cancel(); sourceNoCancel.onNext(1); sourceNoCancel.onNext(2); sourceNoCancel.onError(new TestException()); ts.request(1); ts.assertNoValues(); ts.assertNoErrors(); ts.assertNotComplete(); } @Test public void deferredRequest() { Flowable.create(source, BackpressureStrategy.BUFFER).subscribe(ts); source.onNext(1); source.onNext(2); source.onComplete(); ts.request(2); ts.assertValues(1, 2); ts.assertNoErrors(); ts.assertComplete(); } @Test public void take() { Flowable.create(source, BackpressureStrategy.BUFFER).take(2).subscribe(ts); source.onNext(1); source.onNext(2); source.onComplete(); ts.request(2); ts.assertValues(1, 2); ts.assertNoErrors(); ts.assertComplete(); } @Test public void takeOne() { Flowable.create(source, BackpressureStrategy.BUFFER).take(1).subscribe(ts); ts.request(2); source.onNext(1); source.onNext(2); source.onComplete(); ts.assertValues(1); ts.assertNoErrors(); ts.assertComplete(); } @Test public void requestExact() { Flowable.create(source, BackpressureStrategy.BUFFER).subscribe(ts); ts.request(2); source.onNext(1); source.onNext(2); source.onComplete(); ts.assertValues(1, 2); ts.assertNoErrors(); ts.assertComplete(); } @Test public void takeNoCancel() { Flowable.create(sourceNoCancel, BackpressureStrategy.BUFFER).take(2).subscribe(ts); sourceNoCancel.onNext(1); sourceNoCancel.onNext(2); sourceNoCancel.onComplete(); ts.request(2); ts.assertValues(1, 2); ts.assertNoErrors(); ts.assertComplete(); } @Test public void takeOneNoCancel() { Flowable.create(sourceNoCancel, BackpressureStrategy.BUFFER).take(1).subscribe(ts); ts.request(2); sourceNoCancel.onNext(1); sourceNoCancel.onNext(2); sourceNoCancel.onComplete(); ts.assertValues(1); ts.assertNoErrors(); ts.assertComplete(); } @Test public void unsubscribeNoCancel() { Flowable.create(sourceNoCancel, BackpressureStrategy.BUFFER).subscribe(ts); ts.request(2); sourceNoCancel.onNext(1); ts.cancel(); sourceNoCancel.onNext(2); ts.assertValues(1); ts.assertNoErrors(); ts.assertNotComplete(); } @Test public void unsubscribeInline() { TestSubscriber<Integer> ts1 = new TestSubscriber<Integer>() { @Override public void onNext(Integer t) { super.onNext(t); cancel(); } }; Flowable.create(sourceNoCancel, BackpressureStrategy.BUFFER).subscribe(ts1); sourceNoCancel.onNext(1); ts1.assertValues(1); ts1.assertNoErrors(); ts1.assertNotComplete(); } @Test public void completeInline() { Flowable.create(sourceNoCancel, BackpressureStrategy.BUFFER).subscribe(ts); sourceNoCancel.onNext(1); sourceNoCancel.onComplete(); ts.request(2); ts.assertValues(1); ts.assertNoErrors(); ts.assertComplete(); } @Test public void errorInline() { Flowable.create(sourceNoCancel, BackpressureStrategy.BUFFER).subscribe(ts); sourceNoCancel.onNext(1); sourceNoCancel.onError(new TestException()); ts.request(2); ts.assertValues(1); ts.assertError(TestException.class); ts.assertNotComplete(); } @Test public void requestInline() { TestSubscriber<Integer> ts1 = new TestSubscriber<Integer>(1L) { @Override public void onNext(Integer t) { super.onNext(t); request(1); } }; Flowable.create(sourceNoCancel, BackpressureStrategy.BUFFER).subscribe(ts1); sourceNoCancel.onNext(1); sourceNoCancel.onNext(2); ts1.assertValues(1, 2); ts1.assertNoErrors(); ts1.assertNotComplete(); } @Test public void unsubscribeInlineLatest() { TestSubscriber<Integer> ts1 = new TestSubscriber<Integer>() { @Override public void onNext(Integer t) { super.onNext(t); cancel(); } }; Flowable.create(sourceNoCancel, BackpressureStrategy.LATEST).subscribe(ts1); sourceNoCancel.onNext(1); ts1.assertValues(1); ts1.assertNoErrors(); ts1.assertNotComplete(); } @Test public void unsubscribeInlineExactLatest() { TestSubscriber<Integer> ts1 = new TestSubscriber<Integer>(1L) { @Override public void onNext(Integer t) { super.onNext(t); cancel(); } }; Flowable.create(sourceNoCancel, BackpressureStrategy.LATEST).subscribe(ts1); sourceNoCancel.onNext(1); ts1.assertValues(1); ts1.assertNoErrors(); ts1.assertNotComplete(); } @Test public void completeInlineLatest() { Flowable.create(sourceNoCancel, BackpressureStrategy.LATEST).subscribe(ts); sourceNoCancel.onNext(1); sourceNoCancel.onComplete(); ts.request(2); ts.assertValues(1); ts.assertNoErrors(); ts.assertComplete(); } @Test public void completeInlineExactLatest() { Flowable.create(sourceNoCancel, BackpressureStrategy.LATEST).subscribe(ts); sourceNoCancel.onNext(1); sourceNoCancel.onComplete(); ts.request(1); ts.assertValues(1); ts.assertNoErrors(); ts.assertComplete(); } @Test public void errorInlineLatest() { Flowable.create(sourceNoCancel, BackpressureStrategy.LATEST).subscribe(ts); sourceNoCancel.onNext(1); sourceNoCancel.onError(new TestException()); ts.request(2); ts.assertValues(1); ts.assertError(TestException.class); ts.assertNotComplete(); } @Test public void requestInlineLatest() { TestSubscriber<Integer> ts1 = new TestSubscriber<Integer>(1L) { @Override public void onNext(Integer t) { super.onNext(t); request(1); } }; Flowable.create(sourceNoCancel, BackpressureStrategy.LATEST).subscribe(ts1); sourceNoCancel.onNext(1); sourceNoCancel.onNext(2); ts1.assertValues(1, 2); ts1.assertNoErrors(); ts1.assertNotComplete(); } static final class PublishAsyncEmitter implements FlowableOnSubscribe<Integer>, FlowableSubscriber<Integer> { final PublishProcessor<Integer> subject; FlowableEmitter<Integer> current; PublishAsyncEmitter() { this.subject = PublishProcessor.create(); } long requested() { return current.requested(); } @Override public void subscribe(final FlowableEmitter<Integer> t) { this.current = t; final ResourceSubscriber<Integer> as = new ResourceSubscriber<Integer>() { @Override public void onComplete() { t.onComplete(); } @Override public void onError(Throwable e) { t.onError(e); } @Override public void onNext(Integer v) { t.onNext(v); } }; subject.subscribe(as); t.setCancellable(new Cancellable() { @Override public void cancel() throws Exception { as.dispose(); } });; } @Override public void onSubscribe(Subscription s) { s.request(Long.MAX_VALUE); } @Override public void onNext(Integer t) { subject.onNext(t); } @Override public void onError(Throwable e) { subject.onError(e); } @Override public void onComplete() { subject.onComplete(); } } static final class PublishAsyncEmitterNoCancel implements FlowableOnSubscribe<Integer>, FlowableSubscriber<Integer> { final PublishProcessor<Integer> subject; PublishAsyncEmitterNoCancel() { this.subject = PublishProcessor.create(); } @Override public void subscribe(final FlowableEmitter<Integer> t) { subject.subscribe(new FlowableSubscriber<Integer>() { @Override public void onSubscribe(Subscription s) { s.request(Long.MAX_VALUE); } @Override public void onComplete() { t.onComplete(); } @Override public void onError(Throwable e) { t.onError(e); } @Override public void onNext(Integer v) { t.onNext(v); } }); } @Override public void onSubscribe(Subscription s) { s.request(Long.MAX_VALUE); } @Override public void onNext(Integer t) { subject.onNext(t); } @Override public void onError(Throwable e) { subject.onError(e); } @Override public void onComplete() { subject.onComplete(); } } }