package com.github.davidmoten.rx.internal.operators; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicInteger; import org.junit.Test; import com.github.davidmoten.rx.Actions; import com.github.davidmoten.rx.Transformers; import rx.Observable; import rx.Subscription; import rx.exceptions.OnErrorNotImplementedException; import rx.functions.Action0; import rx.functions.Func0; import rx.observers.TestSubscriber; import rx.subjects.PublishSubject; public final class OnSubscribeDoOnEmptyTest { @Test public void testNonEmpty() { Observable<String> source = Observable.just("Chicago", "Houston", "Phoenix"); final AtomicBoolean wasCalled = new AtomicBoolean(false); source.compose(Transformers.doOnEmpty(new Action0() { @Override public void call() { wasCalled.set(true); } })).subscribe(); assertFalse(wasCalled.get()); } @Test public void testEmpty() { Observable<String> source = Observable.empty(); final AtomicBoolean wasCalled = new AtomicBoolean(false); source.compose(Transformers.doOnEmpty(new Action0() { @Override public void call() { wasCalled.set(true); } })).subscribe(); assertTrue(wasCalled.get()); } @Test public void testUnsubscription() { final AtomicBoolean wasCalled = new AtomicBoolean(false); PublishSubject<Integer> source = PublishSubject.create(); Subscription subscription = source.compose(Transformers.doOnEmpty(new Action0() { @Override public void call() { wasCalled.set(true); } })).take(3).subscribe(); assertTrue(source.hasObservers()); source.onNext(0); source.onNext(1); assertTrue(source.hasObservers()); source.onNext(2); assertFalse(source.hasObservers()); subscription.unsubscribe(); assertFalse(wasCalled.get()); } @Test public void testBackPressure() { final AtomicBoolean wasCalled = new AtomicBoolean(false); Observable<Integer> source = Observable.range(0, 1000) .compose(Transformers.<Integer> doOnEmpty(Actions.setToTrue0(wasCalled))); TestSubscriber<Integer> ts = new TestSubscriber<Integer>(0); source.subscribe(ts); ts.requestMore(1); assertTrue(ts.getOnNextEvents().size() == 1); ts.assertNotCompleted(); assertTrue(ts.getOnErrorEvents().size() == 0); assertFalse(wasCalled.get()); } @Test public void subscriberStateTest() { final AtomicInteger counter = new AtomicInteger(0); final AtomicInteger callCount = new AtomicInteger(0); Observable<Integer> o = Observable.defer(new Func0<Observable<Integer>>() { @Override public Observable<Integer> call() { return Observable.range(1, counter.getAndIncrement() % 2); } }).compose(Transformers.<Integer> doOnEmpty(Actions.increment0(callCount))); o.subscribe(); o.subscribe(); o.subscribe(); o.subscribe(); o.subscribe(); assert (callCount.get() == 3); } @Test public void ifSourceEmitsErrorThenDoOnEmptyIsNotRun() { TestSubscriber<Object> ts = TestSubscriber.create(); AtomicBoolean set = new AtomicBoolean(false); Exception ex = new Exception("boo"); Observable.error(ex) // .compose(Transformers.doOnEmpty(Actions.setToTrue0(set))) // .subscribe(ts); assertFalse(set.get()); ts.assertError(ex); ts.assertNoValues(); } @Test(expected=OnErrorNotImplementedException.class) public void ifOnEmptyActionThrowsOnErrorNotImplementedExceptionThenSubscribeThrows() { Observable.empty() // .compose(Transformers.doOnEmpty(Actions.throw0(new OnErrorNotImplementedException(new RuntimeException())))) // .subscribe(); } @Test public void ifOnEmptyActionThrowsNonFatalRuntimeExceptionThenErrorEmitted() { TestSubscriber<Object> ts = TestSubscriber.create(); Observable.empty() // .compose(Transformers.doOnEmpty(Actions.throw0(new NumberFormatException()))) // .subscribe(ts); ts.assertNoValues(); ts.assertTerminalEvent(); ts.assertError(NumberFormatException.class); } @Test public void testUnsubscribeAfterActionButBeforeCompletionMeansStreamDoesNotComplete() { final TestSubscriber<Object> ts = TestSubscriber.create(); Observable.empty() // .compose(Transformers.doOnEmpty(new Action0() { @Override public void call() { ts.unsubscribe(); }})).subscribe(ts); ts.assertNoValues(); ts.assertNotCompleted(); } }