/**
* 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.subscribers;
import static org.junit.Assert.*;
import static org.mockito.Mockito.*;
import java.io.IOException;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import org.junit.*;
import org.junit.rules.ExpectedException;
import org.mockito.InOrder;
import org.reactivestreams.*;
import io.reactivex.*;
import io.reactivex.Scheduler.Worker;
import io.reactivex.exceptions.*;
import io.reactivex.functions.*;
import io.reactivex.internal.functions.Functions;
import io.reactivex.internal.fuseable.QueueSubscription;
import io.reactivex.internal.subscriptions.*;
import io.reactivex.observers.BaseTestConsumer;
import io.reactivex.observers.BaseTestConsumer.TestWaitStrategy;
import io.reactivex.processors.*;
import io.reactivex.schedulers.Schedulers;
public class TestSubscriberTest {
@Rule
public ExpectedException thrown = ExpectedException.none();
@Test
public void testAssert() {
Flowable<Integer> oi = Flowable.fromIterable(Arrays.asList(1, 2));
TestSubscriber<Integer> o = new TestSubscriber<Integer>();
oi.subscribe(o);
o.assertValues(1, 2);
o.assertValueCount(2);
o.assertTerminated();
}
@Test
public void testAssertNotMatchCount() {
Flowable<Integer> oi = Flowable.fromIterable(Arrays.asList(1, 2));
TestSubscriber<Integer> o = new TestSubscriber<Integer>();
oi.subscribe(o);
thrown.expect(AssertionError.class);
// FIXME different message pattern
// thrown.expectMessage("Number of items does not match. Provided: 1 Actual: 2");
o.assertValues(1);
o.assertValueCount(2);
o.assertTerminated();
}
@Test
public void testAssertNotMatchValue() {
Flowable<Integer> oi = Flowable.fromIterable(Arrays.asList(1, 2));
TestSubscriber<Integer> o = new TestSubscriber<Integer>();
oi.subscribe(o);
thrown.expect(AssertionError.class);
// FIXME different message pattern
// thrown.expectMessage("Value at index: 1 expected to be [3] (Integer) but was: [2] (Integer)");
o.assertValues(1, 3);
o.assertValueCount(2);
o.assertTerminated();
}
@Test
public void assertNeverAtNotMatchingValue() {
Flowable<Integer> oi = Flowable.fromIterable(Arrays.asList(1, 2));
TestSubscriber<Integer> o = new TestSubscriber<Integer>();
oi.subscribe(o);
o.assertNever(3);
o.assertValueCount(2);
o.assertTerminated();
}
@Test
public void assertNeverAtMatchingValue() {
Flowable<Integer> oi = Flowable.fromIterable(Arrays.asList(1, 2));
TestSubscriber<Integer> o = new TestSubscriber<Integer>();
oi.subscribe(o);
o.assertValues(1, 2);
thrown.expect(AssertionError.class);
o.assertNever(2);
o.assertValueCount(2);
o.assertTerminated();
}
@Test
public void assertNeverAtMatchingPredicate() {
TestSubscriber<Integer> ts = new TestSubscriber<Integer>();
Flowable.just(1, 2).subscribe(ts);
ts.assertValues(1, 2);
thrown.expect(AssertionError.class);
ts.assertNever(new Predicate<Integer>() {
@Override
public boolean test(final Integer o) throws Exception {
return o == 1;
}
});
}
@Test
public void assertNeverAtNotMatchingPredicate() {
TestSubscriber<Integer> ts = new TestSubscriber<Integer>();
Flowable.just(2, 3).subscribe(ts);
ts.assertNever(new Predicate<Integer>() {
@Override
public boolean test(final Integer o) throws Exception {
return o == 1;
}
});
}
@Test
public void testAssertTerminalEventNotReceived() {
PublishProcessor<Integer> p = PublishProcessor.create();
TestSubscriber<Integer> o = new TestSubscriber<Integer>();
p.subscribe(o);
p.onNext(1);
p.onNext(2);
thrown.expect(AssertionError.class);
// FIXME different message pattern
// thrown.expectMessage("No terminal events received.");
o.assertValues(1, 2);
o.assertValueCount(2);
o.assertTerminated();
}
@Test
public void testWrappingMock() {
Flowable<Integer> oi = Flowable.fromIterable(Arrays.asList(1, 2));
Subscriber<Integer> mockObserver = TestHelper.mockSubscriber();
oi.subscribe(new TestSubscriber<Integer>(mockObserver));
InOrder inOrder = inOrder(mockObserver);
inOrder.verify(mockObserver, times(1)).onNext(1);
inOrder.verify(mockObserver, times(1)).onNext(2);
inOrder.verify(mockObserver, times(1)).onComplete();
inOrder.verifyNoMoreInteractions();
}
@Test
public void testWrappingMockWhenUnsubscribeInvolved() {
Flowable<Integer> oi = Flowable.fromIterable(Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9)).take(2);
Subscriber<Integer> mockObserver = TestHelper.mockSubscriber();
oi.subscribe(new TestSubscriber<Integer>(mockObserver));
InOrder inOrder = inOrder(mockObserver);
inOrder.verify(mockObserver, times(1)).onNext(1);
inOrder.verify(mockObserver, times(1)).onNext(2);
inOrder.verify(mockObserver, times(1)).onComplete();
inOrder.verifyNoMoreInteractions();
}
@Test
public void testAssertError() {
RuntimeException e = new RuntimeException("Oops");
TestSubscriber<Object> subscriber = new TestSubscriber<Object>();
Flowable.error(e).subscribe(subscriber);
subscriber.assertError(e);
}
@Test
public void testAwaitTerminalEventWithDuration() {
TestSubscriber<Object> ts = new TestSubscriber<Object>();
Flowable.just(1).subscribe(ts);
ts.awaitTerminalEvent(1, TimeUnit.SECONDS);
ts.assertTerminated();
}
@Test
public void testAwaitTerminalEventWithDurationAndUnsubscribeOnTimeout() {
TestSubscriber<Object> ts = new TestSubscriber<Object>();
final AtomicBoolean unsub = new AtomicBoolean(false);
Flowable.just(1)
//
.doOnCancel(new Action() {
@Override
public void run() {
unsub.set(true);
}
})
//
.delay(1000, TimeUnit.MILLISECONDS).subscribe(ts);
ts.awaitTerminalEvent(100, TimeUnit.MILLISECONDS);
ts.dispose();
assertTrue(unsub.get());
}
@Test(expected = NullPointerException.class)
public void testNullDelegate1() {
TestSubscriber<Integer> ts = new TestSubscriber<Integer>(null);
ts.onComplete();
}
@Test(expected = NullPointerException.class)
public void testNullDelegate2() {
TestSubscriber<Integer> ts = new TestSubscriber<Integer>(null);
ts.onComplete();
}
@Test(expected = NullPointerException.class)
public void testNullDelegate3() {
TestSubscriber<Integer> ts = new TestSubscriber<Integer>(null, 0L);
ts.onComplete();
}
@Test
public void testDelegate1() {
TestSubscriber<Integer> to = new TestSubscriber<Integer>();
to.onSubscribe(EmptySubscription.INSTANCE);
TestSubscriber<Integer> ts = new TestSubscriber<Integer>(to);
ts.onComplete();
to.assertTerminated();
}
@Test
public void testDelegate2() {
TestSubscriber<Integer> ts1 = new TestSubscriber<Integer>();
TestSubscriber<Integer> ts2 = new TestSubscriber<Integer>(ts1);
ts2.onComplete();
ts1.assertComplete();
}
@Test
public void testDelegate3() {
TestSubscriber<Integer> ts1 = new TestSubscriber<Integer>();
TestSubscriber<Integer> ts2 = new TestSubscriber<Integer>(ts1, 0L);
ts2.onComplete();
ts1.assertComplete();
}
@Test
public void testUnsubscribed() {
TestSubscriber<Integer> ts = new TestSubscriber<Integer>();
assertFalse(ts.isCancelled());
}
@Test
public void testNoErrors() {
TestSubscriber<Integer> ts = new TestSubscriber<Integer>();
ts.onError(new TestException());
try {
ts.assertNoErrors();
} catch (AssertionError ex) {
// expected
return;
}
fail("Error present but no assertion error!");
}
@Test
public void testNotCompleted() {
TestSubscriber<Integer> ts = new TestSubscriber<Integer>();
try {
ts.assertComplete();
} catch (AssertionError ex) {
// expected
return;
}
fail("Not completed and no assertion error!");
}
@Test
public void testMultipleCompletions() {
TestSubscriber<Integer> ts = new TestSubscriber<Integer>();
ts.onComplete();
ts.onComplete();
try {
ts.assertComplete();
} catch (AssertionError ex) {
// expected
return;
}
fail("Multiple completions and no assertion error!");
}
@Test
public void testCompleted() {
TestSubscriber<Integer> ts = new TestSubscriber<Integer>();
ts.onComplete();
try {
ts.assertNotComplete();
} catch (AssertionError ex) {
// expected
return;
}
fail("Completed and no assertion error!");
}
@Test
public void testMultipleCompletions2() {
TestSubscriber<Integer> ts = new TestSubscriber<Integer>();
ts.onComplete();
ts.onComplete();
try {
ts.assertNotComplete();
} catch (AssertionError ex) {
// expected
return;
}
fail("Multiple completions and no assertion error!");
}
@Test
public void testMultipleErrors() {
TestSubscriber<Integer> ts = new TestSubscriber<Integer>();
ts.onSubscribe(EmptySubscription.INSTANCE);
ts.onError(new TestException());
ts.onError(new TestException());
try {
ts.assertNoErrors();
} catch (AssertionError ex) {
Throwable e = ex.getCause();
if (!(e instanceof CompositeException)) {
fail("Multiple Error present but the reported error doesn't have a composite cause!");
}
CompositeException ce = (CompositeException)e;
if (ce.size() != 2) {
ce.printStackTrace();
}
assertEquals(2, ce.size());
// expected
return;
}
fail("Multiple Error present but no assertion error!");
}
@Test
public void testMultipleErrors2() {
TestSubscriber<Integer> ts = new TestSubscriber<Integer>();
ts.onSubscribe(EmptySubscription.INSTANCE);
ts.onError(new TestException());
ts.onError(new TestException());
try {
ts.assertError(TestException.class);
} catch (AssertionError ex) {
Throwable e = ex.getCause();
if (!(e instanceof CompositeException)) {
fail("Multiple Error present but the reported error doesn't have a composite cause!");
}
CompositeException ce = (CompositeException)e;
assertEquals(2, ce.size());
// expected
return;
}
fail("Multiple Error present but no assertion error!");
}
@Test
public void testMultipleErrors3() {
TestSubscriber<Integer> ts = new TestSubscriber<Integer>();
ts.onSubscribe(EmptySubscription.INSTANCE);
ts.onError(new TestException());
ts.onError(new TestException());
try {
ts.assertError(new TestException());
} catch (AssertionError ex) {
Throwable e = ex.getCause();
if (!(e instanceof CompositeException)) {
fail("Multiple Error present but the reported error doesn't have a composite cause!");
}
CompositeException ce = (CompositeException)e;
assertEquals(2, ce.size());
// expected
return;
}
fail("Multiple Error present but no assertion error!");
}
@Test
public void testMultipleErrors4() {
TestSubscriber<Integer> ts = new TestSubscriber<Integer>();
ts.onSubscribe(EmptySubscription.INSTANCE);
ts.onError(new TestException());
ts.onError(new TestException());
try {
ts.assertError(Functions.<Throwable>alwaysTrue());
} catch (AssertionError ex) {
Throwable e = ex.getCause();
if (!(e instanceof CompositeException)) {
fail("Multiple Error present but the reported error doesn't have a composite cause!");
}
CompositeException ce = (CompositeException)e;
assertEquals(2, ce.size());
// expected
return;
}
fail("Multiple Error present but no assertion error!");
}
@Test
public void testDifferentError() {
TestSubscriber<Integer> ts = new TestSubscriber<Integer>();
ts.onError(new TestException());
try {
ts.assertError(new TestException());
} catch (AssertionError ex) {
// expected
return;
}
fail("Different Error present but no assertion error!");
}
@Test
public void testDifferentError2() {
TestSubscriber<Integer> ts = new TestSubscriber<Integer>();
ts.onError(new RuntimeException());
try {
ts.assertError(new TestException());
} catch (AssertionError ex) {
// expected
return;
}
fail("Different Error present but no assertion error!");
}
@Test
public void testDifferentError3() {
TestSubscriber<Integer> ts = new TestSubscriber<Integer>();
ts.onError(new RuntimeException());
try {
ts.assertError(TestException.class);
}
catch (AssertionError ex) {
// expected
return;
}
fail("Different Error present but no assertion error!");
}
@Test
public void testDifferentError4() {
TestSubscriber<Integer> ts = new TestSubscriber<Integer>();
ts.onError(new RuntimeException());
try {
ts.assertError(Functions.<Throwable>alwaysFalse());
} catch (AssertionError ex) {
// expected
return;
}
fail("Different Error present but no assertion error!");
}
@Test
public void testErrorInPredicate() {
TestSubscriber<Integer> ts = new TestSubscriber<Integer>();
ts.onError(new RuntimeException());
try {
ts.assertError(new Predicate<Throwable>() {
@Override
public boolean test(Throwable throwable) throws Exception {
throw new TestException();
}
});
} catch (TestException ex) {
// expected
return;
}
fail("Error in predicate but not thrown!");
}
@Test
public void testNoError() {
TestSubscriber<Integer> ts = new TestSubscriber<Integer>();
try {
ts.assertError(TestException.class);
} catch (AssertionError ex) {
// expected
return;
}
fail("No present but no assertion error!");
}
@Test
public void testNoError2() {
TestSubscriber<Integer> ts = new TestSubscriber<Integer>();
try {
ts.assertError(new TestException());
} catch (AssertionError ex) {
// expected
return;
}
fail("No present but no assertion error!");
}
@Test
public void testNoError3() {
TestSubscriber<Integer> ts = new TestSubscriber<Integer>();
try {
ts.assertError(Functions.<Throwable>alwaysTrue());
} catch (AssertionError ex) {
// expected
return;
}
fail("No present but no assertion error!");
}
@Test
public void testInterruptTerminalEventAwait() {
TestSubscriber<Integer> ts = new TestSubscriber<Integer>();
final Thread t0 = Thread.currentThread();
Worker w = Schedulers.computation().createWorker();
try {
w.schedule(new Runnable() {
@Override
public void run() {
t0.interrupt();
}
}, 200, TimeUnit.MILLISECONDS);
try {
if (ts.awaitTerminalEvent()) {
fail("Did not interrupt wait!");
}
} catch (RuntimeException ex) {
if (!(ex.getCause() instanceof InterruptedException)) {
fail("The cause is not InterruptedException! " + ex.getCause());
}
}
} finally {
w.dispose();
}
}
@Test
public void testInterruptTerminalEventAwaitTimed() {
TestSubscriber<Integer> ts = new TestSubscriber<Integer>();
final Thread t0 = Thread.currentThread();
Worker w = Schedulers.computation().createWorker();
try {
w.schedule(new Runnable() {
@Override
public void run() {
t0.interrupt();
}
}, 200, TimeUnit.MILLISECONDS);
try {
if (ts.awaitTerminalEvent(5, TimeUnit.SECONDS)) {
fail("Did not interrupt wait!");
}
} catch (RuntimeException ex) {
if (!(ex.getCause() instanceof InterruptedException)) {
fail("The cause is not InterruptedException! " + ex.getCause());
}
}
} finally {
Thread.interrupted(); // clear interrupted flag
w.dispose();
}
}
@Test
public void testInterruptTerminalEventAwaitAndUnsubscribe() {
TestSubscriber<Integer> ts = new TestSubscriber<Integer>();
final Thread t0 = Thread.currentThread();
Worker w = Schedulers.computation().createWorker();
try {
w.schedule(new Runnable() {
@Override
public void run() {
t0.interrupt();
}
}, 200, TimeUnit.MILLISECONDS);
ts.awaitTerminalEvent(5, TimeUnit.SECONDS);
ts.dispose();
if (!ts.isCancelled()) {
fail("Did not unsubscribe!");
}
} finally {
w.dispose();
}
}
@Test
public void testNoTerminalEventBut1Completed() {
TestSubscriber<Integer> ts = new TestSubscriber<Integer>();
ts.onComplete();
try {
ts.assertNotTerminated();
fail("Failed to report there were terminal event(s)!");
} catch (AssertionError ex) {
// expected
}
}
@Test
public void testNoTerminalEventBut1Error() {
TestSubscriber<Integer> ts = new TestSubscriber<Integer>();
ts.onError(new TestException());
try {
ts.assertNotTerminated();
fail("Failed to report there were terminal event(s)!");
} catch (AssertionError ex) {
// expected
}
}
@Test
public void testNoTerminalEventBut1Error1Completed() {
TestSubscriber<Integer> ts = new TestSubscriber<Integer>();
ts.onComplete();
ts.onError(new TestException());
try {
ts.assertNotTerminated();
fail("Failed to report there were terminal event(s)!");
} catch (AssertionError ex) {
// expected
}
}
@Test
public void testNoTerminalEventBut2Errors() {
TestSubscriber<Integer> ts = new TestSubscriber<Integer>();
ts.onSubscribe(EmptySubscription.INSTANCE);
ts.onError(new TestException());
ts.onError(new TestException());
try {
ts.assertNotTerminated();
fail("Failed to report there were terminal event(s)!");
} catch (AssertionError ex) {
// expected
Throwable e = ex.getCause();
if (!(e instanceof CompositeException)) {
fail("Multiple Error present but the reported error doesn't have a composite cause!");
}
CompositeException ce = (CompositeException)e;
assertEquals(2, ce.size());
}
}
@Test
public void testNoValues() {
TestSubscriber<Integer> ts = new TestSubscriber<Integer>();
ts.onNext(1);
try {
ts.assertNoValues();
fail("Failed to report there were values!");
} catch (AssertionError ex) {
// expected
}
}
@Test
public void testValueCount() {
TestSubscriber<Integer> ts = new TestSubscriber<Integer>();
ts.onNext(1);
ts.onNext(2);
try {
ts.assertValueCount(3);
fail("Failed to report there were values!");
} catch (AssertionError ex) {
// expected
}
}
@Test(timeout = 1000)
public void testOnCompletedCrashCountsDownLatch() {
TestSubscriber<Integer> to = new TestSubscriber<Integer>() {
@Override
public void onComplete() {
throw new TestException();
}
};
TestSubscriber<Integer> ts = new TestSubscriber<Integer>(to);
try {
ts.onComplete();
} catch (TestException ex) {
// expected
}
ts.awaitTerminalEvent();
}
@Test(timeout = 1000)
public void testOnErrorCrashCountsDownLatch() {
TestSubscriber<Integer> to = new TestSubscriber<Integer>() {
@Override
public void onError(Throwable e) {
throw new TestException();
}
};
TestSubscriber<Integer> ts = new TestSubscriber<Integer>(to);
try {
ts.onError(new RuntimeException());
} catch (TestException ex) {
// expected
}
ts.awaitTerminalEvent();
}
@Test
public void createDelegate() {
TestSubscriber<Integer> ts1 = TestSubscriber.create();
TestSubscriber<Integer> ts = TestSubscriber.create(ts1);
ts.assertNotSubscribed();
assertFalse(ts.hasSubscription());
ts.onSubscribe(new BooleanSubscription());
try {
ts.assertNotSubscribed();
throw new RuntimeException("Should have thrown");
} catch (AssertionError ex) {
// expected
}
assertTrue(ts.hasSubscription());
assertFalse(ts.isDisposed());
ts.onNext(1);
ts.onError(new TestException());
ts.onComplete();
ts1.assertValue(1).assertError(TestException.class).assertComplete();
ts.dispose();
assertTrue(ts.isDisposed());
assertTrue(ts.isTerminated());
assertSame(Thread.currentThread(), ts.lastThread());
try {
ts.assertNoValues();
throw new RuntimeException("Should have thrown");
} catch (AssertionError exc) {
// expected
}
try {
ts.assertValueCount(0);
throw new RuntimeException("Should have thrown");
} catch (AssertionError exc) {
// expected
}
ts.assertValueSequence(Collections.singletonList(1));
try {
ts.assertValueSequence(Collections.singletonList(2));
throw new RuntimeException("Should have thrown");
} catch (AssertionError exc) {
// expected
}
ts.assertValueSet(Collections.singleton(1));
try {
ts.assertValueSet(Collections.singleton(2));
throw new RuntimeException("Should have thrown");
} catch (AssertionError exc) {
// expected
}
}
@Test
public void assertError() {
TestSubscriber<Integer> ts = TestSubscriber.create();
try {
ts.assertError(TestException.class);
throw new RuntimeException("Should have thrown");
} catch (AssertionError ex) {
// expected
}
try {
ts.assertError(new TestException());
throw new RuntimeException("Should have thrown");
} catch (AssertionError ex) {
// expected
}
try {
ts.assertErrorMessage("");
throw new RuntimeException("Should have thrown");
} catch (AssertionError exc) {
// expected
}
try {
ts.assertError(Functions.<Throwable>alwaysTrue());
throw new RuntimeException("Should have thrown");
} catch (AssertionError ex) {
// expected
}
try {
ts.assertSubscribed();
throw new RuntimeException("Should have thrown");
} catch (AssertionError exc) {
// expected
}
try {
ts.assertTerminated();
throw new RuntimeException("Should have thrown");
} catch (AssertionError exc) {
// expected
}
ts.onSubscribe(new BooleanSubscription());
ts.assertSubscribed();
ts.assertNoErrors();
TestException ex = new TestException("Forced failure");
ts.onError(ex);
ts.assertError(ex);
ts.assertError(TestException.class);
ts.assertErrorMessage("Forced failure");
ts.assertError(Functions.<Throwable>alwaysTrue());
ts.assertError(new Predicate<Throwable>() {
@Override
public boolean test(Throwable t) {
return t.getMessage() != null && t.getMessage().contains("Forced");
}
});
try {
ts.assertErrorMessage("");
throw new RuntimeException("Should have thrown");
} catch (AssertionError exc) {
// expected
}
try {
ts.assertError(new RuntimeException());
throw new RuntimeException("Should have thrown");
} catch (AssertionError exc) {
// expected
}
try {
ts.assertError(IOException.class);
throw new RuntimeException("Should have thrown");
} catch (AssertionError exc) {
// expected
}
try {
ts.assertNoErrors();
throw new RuntimeException("Should have thrown");
} catch (AssertionError exc) {
// expected
}
try {
ts.assertError(Functions.<Throwable>alwaysFalse());
throw new RuntimeException("Should have thrown");
} catch (AssertionError exc) {
// expected
}
ts.assertTerminated();
ts.assertValueCount(0);
ts.assertNoValues();
}
@Test
public void emptyObserverEnum() {
assertEquals(1, TestSubscriber.EmptySubscriber.values().length);
assertNotNull(TestSubscriber.EmptySubscriber.valueOf("INSTANCE"));
}
@Test
public void valueAndClass() {
assertEquals("null", TestSubscriber.valueAndClass(null));
assertEquals("1 (class: Integer)", TestSubscriber.valueAndClass(1));
}
@Test
public void assertFailure() {
TestSubscriber<Integer> ts = TestSubscriber.create();
ts.onSubscribe(new BooleanSubscription());
ts.onError(new TestException("Forced failure"));
ts.assertFailure(TestException.class);
ts.assertFailure(Functions.<Throwable>alwaysTrue());
ts.assertFailureAndMessage(TestException.class, "Forced failure");
ts.onNext(1);
ts.assertFailure(TestException.class, 1);
ts.assertFailure(Functions.<Throwable>alwaysTrue(), 1);
ts.assertFailureAndMessage(TestException.class, "Forced failure", 1);
}
@Test
public void assertFuseable() {
TestSubscriber<Integer> ts = TestSubscriber.create();
ts.onSubscribe(new BooleanSubscription());
ts.assertNotFuseable();
try {
ts.assertFuseable();
throw new RuntimeException("Should have thrown");
} catch (AssertionError ex) {
// expected
}
try {
ts.assertFusionMode(QueueSubscription.SYNC);
throw new RuntimeException("Should have thrown");
} catch (AssertionError ex) {
// expected
}
ts = TestSubscriber.create();
ts.setInitialFusionMode(QueueSubscription.ANY);
ts.onSubscribe(new ScalarSubscription<Integer>(ts, 1));
ts.assertFuseable();
ts.assertFusionMode(QueueSubscription.SYNC);
try {
ts.assertFusionMode(QueueSubscription.NONE);
throw new RuntimeException("Should have thrown");
} catch (AssertionError ex) {
// expected
}
try {
ts.assertNotFuseable();
throw new RuntimeException("Should have thrown");
} catch (AssertionError ex) {
// expected
}
}
@Test
public void assertTerminated() {
TestSubscriber<Integer> ts = TestSubscriber.create();
ts.assertNotTerminated();
ts.onError(null);
try {
ts.assertNotTerminated();
throw new RuntimeException("Should have thrown!");
} catch (AssertionError ex) {
// expected
}
}
@Test
public void assertOf() {
TestSubscriber<Integer> ts = TestSubscriber.create();
ts.assertOf(new Consumer<TestSubscriber<Integer>>() {
@Override
public void accept(TestSubscriber<Integer> f) throws Exception {
f.assertNotSubscribed();
}
});
try {
ts.assertOf(new Consumer<TestSubscriber<Integer>>() {
@Override
public void accept(TestSubscriber<Integer> f) throws Exception {
f.assertSubscribed();
}
});
throw new RuntimeException("Should have thrown");
} catch (AssertionError ex) {
// expected
}
try {
ts.assertOf(new Consumer<TestSubscriber<Integer>>() {
@Override
public void accept(TestSubscriber<Integer> f) throws Exception {
throw new IllegalArgumentException();
}
});
throw new RuntimeException("Should have thrown");
} catch (IllegalArgumentException ex) {
// expected
}
}
@Test
public void assertResult() {
TestSubscriber<Integer> ts = TestSubscriber.create();
ts.onSubscribe(new BooleanSubscription());
ts.onComplete();
ts.assertResult();
try {
ts.assertResult(1);
throw new RuntimeException("Should have thrown");
} catch (AssertionError ex) {
// expected
}
ts.onNext(1);
ts.assertResult(1);
try {
ts.assertResult(2);
throw new RuntimeException("Should have thrown");
} catch (AssertionError ex) {
// expected
}
try {
ts.assertResult();
throw new RuntimeException("Should have thrown");
} catch (AssertionError ex) {
// expected
}
}
@Test(timeout = 5000)
public void await() throws Exception {
TestSubscriber<Integer> ts = TestSubscriber.create();
ts.onSubscribe(new BooleanSubscription());
assertFalse(ts.await(100, TimeUnit.MILLISECONDS));
ts.awaitDone(100, TimeUnit.MILLISECONDS);
assertTrue(ts.isDisposed());
assertFalse(ts.awaitTerminalEvent(100, TimeUnit.MILLISECONDS));
assertEquals(0, ts.completions());
assertEquals(0, ts.errorCount());
ts.onComplete();
assertTrue(ts.await(100, TimeUnit.MILLISECONDS));
ts.await();
ts.awaitDone(5, TimeUnit.SECONDS);
assertEquals(1, ts.completions());
assertEquals(0, ts.errorCount());
assertTrue(ts.awaitTerminalEvent());
final TestSubscriber<Integer> ts1 = TestSubscriber.create();
ts1.onSubscribe(new BooleanSubscription());
Schedulers.single().scheduleDirect(new Runnable() {
@Override
public void run() {
ts1.onComplete();
}
}, 200, TimeUnit.MILLISECONDS);
ts1.await();
ts1.assertValueSet(Collections.<Integer>emptySet());
}
@Test
public void errors() {
TestSubscriber<Integer> ts = TestSubscriber.create();
ts.onSubscribe(new BooleanSubscription());
assertEquals(0, ts.errors().size());
ts.onError(new TestException());
assertEquals(1, ts.errors().size());
TestHelper.assertError(ts.errors(), 0, TestException.class);
}
@SuppressWarnings("unchecked")
@Test
public void onNext() {
TestSubscriber<Integer> ts = TestSubscriber.create();
ts.onSubscribe(new BooleanSubscription());
assertEquals(0, ts.valueCount());
assertEquals(Collections.emptyList(), ts.values());
ts.onNext(1);
assertEquals(Collections.singletonList(1), ts.values());
ts.cancel();
assertTrue(ts.isCancelled());
assertTrue(ts.isDisposed());
ts.assertValue(1);
assertEquals(Arrays.asList(Collections.singletonList(1), Collections.emptyList(), Collections.emptyList()), ts.getEvents());
ts.onComplete();
assertEquals(Arrays.asList(Collections.singletonList(1), Collections.emptyList(), Collections.singletonList(Notification.createOnComplete())), ts.getEvents());
}
@Test
public void fusionModeToString() {
assertEquals("NONE", TestSubscriber.fusionModeToString(QueueSubscription.NONE));
assertEquals("SYNC", TestSubscriber.fusionModeToString(QueueSubscription.SYNC));
assertEquals("ASYNC", TestSubscriber.fusionModeToString(QueueSubscription.ASYNC));
assertEquals("Unknown(100)", TestSubscriber.fusionModeToString(100));
}
@Test
public void multipleTerminals() {
TestSubscriber<Integer> ts = TestSubscriber.create();
ts.onSubscribe(new BooleanSubscription());
ts.assertNotComplete();
ts.onComplete();
try {
ts.assertNotComplete();
throw new RuntimeException("Should have thrown");
} catch (Throwable ex) {
// expected
}
ts.assertTerminated();
ts.onComplete();
try {
ts.assertComplete();
throw new RuntimeException("Should have thrown");
} catch (Throwable ex) {
// expected
}
try {
ts.assertTerminated();
throw new RuntimeException("Should have thrown");
} catch (Throwable ex) {
// expected
}
try {
ts.assertNotComplete();
throw new RuntimeException("Should have thrown");
} catch (Throwable ex) {
// expected
}
}
@Test
public void assertValue() {
TestSubscriber<Integer> ts = TestSubscriber.create();
ts.onSubscribe(new BooleanSubscription());
try {
ts.assertValue(1);
throw new RuntimeException("Should have thrown");
} catch (Throwable ex) {
// expected
}
ts.onNext(1);
ts.assertValue(1);
try {
ts.assertValue(2);
throw new RuntimeException("Should have thrown");
} catch (Throwable ex) {
// expected
}
ts.onNext(2);
try {
ts.assertValue(1);
throw new RuntimeException("Should have thrown");
} catch (Throwable ex) {
// expected
}
}
@Test
public void onNextMisbehave() {
TestSubscriber<Integer> ts = TestSubscriber.create();
ts.onNext(1);
ts.assertError(IllegalStateException.class);
ts = TestSubscriber.create();
ts.onSubscribe(new BooleanSubscription());
ts.onNext(null);
ts.assertFailure(NullPointerException.class, (Integer)null);
}
@Test
public void awaitTerminalEventInterrupt() {
final TestSubscriber<Integer> ts = TestSubscriber.create();
ts.onSubscribe(new BooleanSubscription());
Thread.currentThread().interrupt();
ts.awaitTerminalEvent();
assertTrue(Thread.interrupted());
Thread.currentThread().interrupt();
ts.awaitTerminalEvent(5, TimeUnit.SECONDS);
assertTrue(Thread.interrupted());
}
@Test
public void assertTerminated2() {
TestSubscriber<Integer> ts = TestSubscriber.create();
ts.onSubscribe(new BooleanSubscription());
assertFalse(ts.isTerminated());
ts.onError(new TestException());
ts.onError(new IOException());
assertTrue(ts.isTerminated());
try {
ts.assertTerminated();
throw new RuntimeException("Should have thrown");
} catch (AssertionError ex) {
// expected
}
try {
ts.assertError(TestException.class);
throw new RuntimeException("Should have thrown");
} catch (AssertionError ex) {
// expected
}
ts = TestSubscriber.create();
ts.onSubscribe(new BooleanSubscription());
ts.onError(new TestException());
ts.onComplete();
try {
ts.assertTerminated();
throw new RuntimeException("Should have thrown");
} catch (AssertionError ex) {
// expected
}
}
@Test
public void onSubscribe() {
TestSubscriber<Integer> ts = TestSubscriber.create();
ts.onSubscribe(null);
ts.assertError(NullPointerException.class);
ts = TestSubscriber.create();
ts.onSubscribe(new BooleanSubscription());
BooleanSubscription d1 = new BooleanSubscription();
ts.onSubscribe(d1);
assertTrue(d1.isCancelled());
ts.assertError(IllegalStateException.class);
ts = TestSubscriber.create();
ts.dispose();
d1 = new BooleanSubscription();
ts.onSubscribe(d1);
assertTrue(d1.isCancelled());
}
@Test
public void assertValueSequence() {
TestSubscriber<Integer> ts = TestSubscriber.create();
ts.onSubscribe(new BooleanSubscription());
ts.onNext(1);
ts.onNext(2);
try {
ts.assertValueSequence(Collections.<Integer>emptyList());
throw new RuntimeException("Should have thrown");
} catch (AssertionError ex) {
// expected
}
try {
ts.assertValueSequence(Collections.singletonList(1));
throw new RuntimeException("Should have thrown");
} catch (AssertionError ex) {
// expected
}
ts.assertValueSequence(Arrays.asList(1, 2));
try {
ts.assertValueSequence(Arrays.asList(1, 2, 3));
throw new RuntimeException("Should have thrown");
} catch (AssertionError ex) {
// expected
}
}
@Test
public void assertEmpty() {
TestSubscriber<Integer> ts = new TestSubscriber<Integer>();
try {
ts.assertEmpty();
throw new RuntimeException("Should have thrown!");
} catch (AssertionError ex) {
// expected
}
ts.onSubscribe(new BooleanSubscription());
ts.assertEmpty();
ts.onNext(1);
try {
ts.assertEmpty();
throw new RuntimeException("Should have thrown!");
} catch (AssertionError ex) {
// expected
}
}
@Test
public void awaitDoneTimed() {
TestSubscriber<Integer> ts = new TestSubscriber<Integer>();
Thread.currentThread().interrupt();
try {
ts.awaitDone(5, TimeUnit.SECONDS);
} catch (RuntimeException ex) {
assertTrue(ex.toString(), ex.getCause() instanceof InterruptedException);
}
}
@Test
public void assertNotSubscribed() {
TestSubscriber<Integer> ts = new TestSubscriber<Integer>();
ts.assertNotSubscribed();
ts.errors().add(new TestException());
try {
ts.assertNotSubscribed();
throw new RuntimeException("Should have thrown!");
} catch (AssertionError ex) {
// expected
}
}
@Test
public void assertErrorMultiple() {
TestSubscriber<Integer> ts = new TestSubscriber<Integer>();
TestException e = new TestException();
ts.errors().add(e);
ts.errors().add(new TestException());
try {
ts.assertError(TestException.class);
throw new RuntimeException("Should have thrown!");
} catch (AssertionError ex) {
// expected
}
try {
ts.assertError(e);
throw new RuntimeException("Should have thrown!");
} catch (AssertionError ex) {
// expected
}
try {
ts.assertErrorMessage("");
throw new RuntimeException("Should have thrown!");
} catch (AssertionError ex) {
// expected
}
}
@Test
public void assertComplete() {
TestSubscriber<Integer> ts = new TestSubscriber<Integer>();
ts.onSubscribe(new BooleanSubscription());
try {
ts.assertComplete();
throw new RuntimeException("Should have thrown!");
} catch (AssertionError ex) {
// expected
}
ts.onComplete();
ts.assertComplete();
ts.onComplete();
try {
ts.assertComplete();
throw new RuntimeException("Should have thrown!");
} catch (AssertionError ex) {
// expected
}
}
@Test
public void completeWithoutOnSubscribe() {
TestSubscriber<Integer> ts = new TestSubscriber<Integer>();
ts.onComplete();
ts.assertError(IllegalStateException.class);
}
@Test
public void completeDelegateThrows() {
TestSubscriber<Integer> ts = new TestSubscriber<Integer>(new FlowableSubscriber<Integer>() {
@Override
public void onSubscribe(Subscription d) {
}
@Override
public void onNext(Integer value) {
}
@Override
public void onError(Throwable e) {
throw new TestException();
}
@Override
public void onComplete() {
throw new TestException();
}
});
ts.onSubscribe(new BooleanSubscription());
try {
ts.onComplete();
throw new RuntimeException("Should have thrown!");
} catch (TestException ex) {
assertTrue(ts.isTerminated());
}
}
@Test
public void errorDelegateThrows() {
TestSubscriber<Integer> ts = new TestSubscriber<Integer>(new FlowableSubscriber<Integer>() {
@Override
public void onSubscribe(Subscription d) {
}
@Override
public void onNext(Integer value) {
}
@Override
public void onError(Throwable e) {
throw new TestException();
}
@Override
public void onComplete() {
throw new TestException();
}
});
ts.onSubscribe(new BooleanSubscription());
try {
ts.onError(new IOException());
throw new RuntimeException("Should have thrown!");
} catch (TestException ex) {
assertTrue(ts.isTerminated());
}
}
@Test
public void syncQueueThrows() {
TestSubscriber<Object> ts = new TestSubscriber<Object>();
ts.setInitialFusionMode(QueueSubscription.SYNC);
Flowable.range(1, 5)
.map(new Function<Integer, Object>() {
@Override
public Object apply(Integer v) throws Exception { throw new TestException(); }
})
.subscribe(ts);
ts.assertSubscribed()
.assertFuseable()
.assertFusionMode(QueueSubscription.SYNC)
.assertFailure(TestException.class);
}
@Test
public void asyncQueueThrows() {
TestSubscriber<Object> ts = new TestSubscriber<Object>();
ts.setInitialFusionMode(QueueSubscription.ANY);
UnicastProcessor<Integer> up = UnicastProcessor.create();
up
.map(new Function<Integer, Object>() {
@Override
public Object apply(Integer v) throws Exception { throw new TestException(); }
})
.subscribe(ts);
up.onNext(1);
ts.assertSubscribed()
.assertFuseable()
.assertFusionMode(QueueSubscription.ASYNC)
.assertFailure(TestException.class);
}
@Test
public void assertValuePredicateEmpty() {
TestSubscriber<Object> ts = new TestSubscriber<Object>();
Flowable.empty().subscribe(ts);
thrown.expect(AssertionError.class);
thrown.expectMessage("No values");
ts.assertValue(new Predicate<Object>() {
@Override public boolean test(final Object o) throws Exception {
return false;
}
});
}
@Test
public void assertValuePredicateMatch() {
TestSubscriber<Integer> ts = new TestSubscriber<Integer>();
Flowable.just(1).subscribe(ts);
ts.assertValue(new Predicate<Integer>() {
@Override public boolean test(final Integer o) throws Exception {
return o == 1;
}
});
}
@Test
public void assertValuePredicateNoMatch() {
TestSubscriber<Integer> ts = new TestSubscriber<Integer>();
Flowable.just(1).subscribe(ts);
thrown.expect(AssertionError.class);
thrown.expectMessage("Value not present");
ts.assertValue(new Predicate<Integer>() {
@Override public boolean test(final Integer o) throws Exception {
return o != 1;
}
});
}
@Test
public void assertValuePredicateMatchButMore() {
TestSubscriber<Integer> ts = new TestSubscriber<Integer>();
Flowable.just(1, 2).subscribe(ts);
thrown.expect(AssertionError.class);
thrown.expectMessage("Value present but other values as well");
ts.assertValue(new Predicate<Integer>() {
@Override public boolean test(final Integer o) throws Exception {
return o == 1;
}
});
}
@Test
public void assertValueAtPredicateEmpty() {
TestSubscriber<Object> ts = new TestSubscriber<Object>();
Flowable.empty().subscribe(ts);
thrown.expect(AssertionError.class);
thrown.expectMessage("No values");
ts.assertValueAt(0, new Predicate<Object>() {
@Override public boolean test(final Object o) throws Exception {
return false;
}
});
}
@Test
public void assertValueAtPredicateMatch() {
TestSubscriber<Integer> ts = new TestSubscriber<Integer>();
Flowable.just(1, 2).subscribe(ts);
ts.assertValueAt(1, new Predicate<Integer>() {
@Override public boolean test(final Integer o) throws Exception {
return o == 2;
}
});
}
@Test
public void assertValueAtPredicateNoMatch() {
TestSubscriber<Integer> ts = new TestSubscriber<Integer>();
Flowable.just(1, 2, 3).subscribe(ts);
thrown.expect(AssertionError.class);
thrown.expectMessage("Value not present");
ts.assertValueAt(2, new Predicate<Integer>() {
@Override public boolean test(final Integer o) throws Exception {
return o != 3;
}
});
}
@Test
public void assertValueAtInvalidIndex() {
TestSubscriber<Integer> ts = new TestSubscriber<Integer>();
Flowable.just(1, 2).subscribe(ts);
thrown.expect(AssertionError.class);
thrown.expectMessage("Invalid index: 2 (latch = 0, values = 2, errors = 0, completions = 1)");
ts.assertValueAt(2, new Predicate<Integer>() {
@Override public boolean test(final Integer o) throws Exception {
return o == 1;
}
});
}
@Test
public void requestMore() {
Flowable.range(1, 5)
.test(0)
.requestMore(1)
.assertValue(1)
.requestMore(2)
.assertValues(1, 2, 3)
.requestMore(3)
.assertResult(1, 2, 3, 4, 5);
}
@Test
public void withTag() {
try {
for (int i = 1; i < 3; i++) {
Flowable.just(i)
.test()
.withTag("testing with item=" + i)
.assertResult(1)
;
}
fail("Should have thrown!");
} catch (AssertionError ex) {
assertTrue(ex.toString(), ex.toString().contains("testing with item=2"));
}
}
@Test
public void timeoutIndicated() throws InterruptedException {
Thread.interrupted(); // clear flag
TestSubscriber<Object> ts = Flowable.never()
.test();
assertFalse(ts.await(1, TimeUnit.MILLISECONDS));
try {
ts.assertResult(1);
fail("Should have thrown!");
} catch (AssertionError ex) {
assertTrue(ex.toString(), ex.toString().contains("timeout!"));
}
}
@Test
public void timeoutIndicated2() throws InterruptedException {
try {
Flowable.never()
.test()
.awaitDone(1, TimeUnit.MILLISECONDS)
.assertResult(1);
fail("Should have thrown!");
} catch (AssertionError ex) {
assertTrue(ex.toString(), ex.toString().contains("timeout!"));
}
}
@Test
public void timeoutIndicated3() throws InterruptedException {
TestSubscriber<Object> ts = Flowable.never()
.test();
assertFalse(ts.awaitTerminalEvent(1, TimeUnit.MILLISECONDS));
try {
ts.assertResult(1);
fail("Should have thrown!");
} catch (AssertionError ex) {
assertTrue(ex.toString(), ex.toString().contains("timeout!"));
}
}
@Test
public void disposeIndicated() {
TestSubscriber<Object> ts = new TestSubscriber<Object>();
ts.cancel();
try {
ts.assertResult(1);
fail("Should have thrown!");
} catch (Throwable ex) {
assertTrue(ex.toString(), ex.toString().contains("disposed!"));
}
}
@Test
public void checkTestWaitStrategyEnum() {
TestHelper.checkEnum(BaseTestConsumer.TestWaitStrategy.class);
}
@Test
public void awaitCount() {
Flowable.range(1, 10).delay(100, TimeUnit.MILLISECONDS)
.test(5)
.awaitCount(5)
.assertValues(1, 2, 3, 4, 5)
.requestMore(5)
.awaitDone(5, TimeUnit.SECONDS)
.assertResult(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
}
@Test
public void awaitCountLess() {
Flowable.range(1, 4)
.test()
.awaitCount(5)
.assertResult(1, 2, 3, 4);
}
@Test
public void awaitCountLess2() {
Flowable.range(1, 4)
.test()
.awaitCount(5, TestWaitStrategy.YIELD)
.assertResult(1, 2, 3, 4);
}
@Test
public void awaitCountLess3() {
Flowable.range(1, 4).delay(50, TimeUnit.MILLISECONDS)
.test()
.awaitCount(5, TestWaitStrategy.SLEEP_1MS)
.assertResult(1, 2, 3, 4);
}
@Test
public void interruptTestWaitStrategy() {
try {
Thread.currentThread().interrupt();
TestWaitStrategy.SLEEP_1000MS.run();
} catch (RuntimeException ex) {
assertTrue(ex.toString(), ex.getCause() instanceof InterruptedException);
}
}
@Test
public void awaitCountTimeout() {
TestSubscriber<Object> ts = Flowable.never()
.test()
.awaitCount(1, TestWaitStrategy.SLEEP_1MS, 50);
assertTrue(ts.isTimeout());
ts.clearTimeout();
assertFalse(ts.isTimeout());
}
@Test
public void assertTimeout() {
Flowable.never()
.test()
.awaitCount(1, TestWaitStrategy.SLEEP_1MS, 50)
.assertTimeout();
}
@Test
public void assertTimeout2() {
try {
Flowable.empty()
.test()
.awaitCount(1, TestWaitStrategy.SLEEP_1MS, 50)
.assertTimeout();
fail("Should have thrown!");
} catch (AssertionError ex) {
assertTrue(ex.toString(), ex.getMessage().contains("No timeout?!"));
}
}
@Test
public void assertNoTimeout() {
Flowable.just(1)
.test()
.awaitCount(1, TestWaitStrategy.SLEEP_1MS, 50)
.assertNoTimeout();
}
@Test
public void assertNoTimeout2() {
try {
Flowable.never()
.test()
.awaitCount(1, TestWaitStrategy.SLEEP_1MS, 50)
.assertNoTimeout();
fail("Should have thrown!");
} catch (AssertionError ex) {
assertTrue(ex.toString(), ex.getMessage().contains("Timeout?!"));
}
}
@Test
public void assertNeverPredicateThrows() {
try {
Flowable.just(1)
.test()
.assertNever(new Predicate<Integer>() {
@Override
public boolean test(Integer t) throws Exception {
throw new IllegalArgumentException();
}
});
fail("Should have thrown!");
} catch (IllegalArgumentException ex) {
// expected
}
}
@Test
public void assertValueAtPredicateThrows() {
try {
Flowable.just(1)
.test()
.assertValueAt(0, new Predicate<Integer>() {
@Override
public boolean test(Integer t) throws Exception {
throw new IllegalArgumentException();
}
});
fail("Should have thrown!");
} catch (IllegalArgumentException ex) {
// expected
}
}
@Test
public void waitStrategyRuns() {
for (TestWaitStrategy ws : TestWaitStrategy.values()) {
ws.run();
}
}
}