From 1c66113ece291932235ef2ec2b0c4a3ae1dd58bc Mon Sep 17 00:00:00 2001 From: Pedro Viegas Date: Mon, 4 Nov 2013 10:43:51 +0530 Subject: [PATCH 1/6] creating test classes on test source folder --- ...estSchedulers.java => SchedulersTest.java} | 65 +++++++++---------- .../CurrentThreadSchedulerTest.java | 7 ++ .../concurrency/ImmediateSchedulerTest.java | 7 ++ .../observables/BlockingObservableTest.java | 7 ++ .../java/rx/operators/OperationAllTest.java | 7 ++ .../java/rx/operators/OperationAnyTest.java | 7 ++ .../rx/operators/OperationAverageTest.java | 7 ++ .../rx/operators/OperationBufferTest.java | 7 ++ .../java/rx/operators/OperationCacheTest.java | 7 ++ .../java/rx/operators/OperationCastTest.java | 7 ++ .../operators/OperationCombineLatestTest.java | 7 ++ .../rx/operators/OperationConcatTest.java | 7 ++ .../rx/operators/OperationDebounceTest.java | 7 ++ .../OperationDefaultIfEmptyTest.java | 7 ++ .../java/rx/operators/OperationDeferTest.java | 7 ++ .../operators/OperationDematerializeTest.java | 7 ++ .../rx/operators/OperationDistinctTest.java | 7 ++ .../OperationDistinctUntilChangedTest.java | 7 ++ .../rx/operators/OperationElementAtTest.java | 7 ++ .../rx/operators/OperationFilterTest.java | 7 ++ .../rx/operators/OperationFinallyTest.java | 7 ++ .../OperationFirstOrDefaultTest.java | 7 ++ .../rx/operators/OperationGroupByTest.java | 7 ++ .../rx/operators/OperationIntervalTest.java | 7 ++ .../java/rx/operators/OperationMapTest.java | 7 ++ .../operators/OperationMaterializeTest.java | 7 ++ .../OperationMergeDelayErrorTest.java | 7 ++ .../java/rx/operators/OperationMergeTest.java | 7 ++ .../rx/operators/OperationMostRecentTest.java | 7 ++ .../rx/operators/OperationMulticastTest.java | 7 ++ .../java/rx/operators/OperationNextTest.java | 7 ++ .../rx/operators/OperationObserveOnTest.java | 7 ++ ...ationOnErrorResumeNextViaFunctionTest.java | 7 ++ ...ionOnErrorResumeNextViaObservableTest.java | 7 ++ .../operators/OperationOnErrorReturnTest.java | 7 ++ ...nExceptionResumeNextViaObservableTest.java | 7 ++ .../rx/operators/OperationParallelTest.java | 7 ++ .../java/rx/operators/OperationRetryTest.java | 7 ++ .../rx/operators/OperationSampleTest.java | 7 ++ .../java/rx/operators/OperationScanTest.java | 7 ++ .../rx/operators/OperationSkipLastTest.java | 7 ++ .../java/rx/operators/OperationSkipTest.java | 7 ++ .../rx/operators/OperationSkipWhileTest.java | 7 ++ .../operators/OperationSubscribeOnTest.java | 7 ++ .../java/rx/operators/OperationSumTest.java | 7 ++ .../rx/operators/OperationSwitchTest.java | 7 ++ .../operators/OperationSynchronizeTest.java | 7 ++ .../rx/operators/OperationTakeLastTest.java | 7 ++ .../java/rx/operators/OperationTakeTest.java | 7 ++ .../rx/operators/OperationTakeUntilTest.java | 7 ++ .../operators/OperationThrottleFirstTest.java | 7 ++ .../OperationToObservableFutureTest.java | 7 ++ .../OperationToObservableIterableTest.java | 7 ++ .../OperationToObservableListTest.java | 7 ++ .../OperationToObservableSortedListTest.java | 7 ++ .../rx/operators/OperationWindowTest.java | 7 ++ .../java/rx/operators/OperationZipTest.java | 7 ++ .../java/rx/operators/OperatorTesterTest.java | 7 ++ .../SafeObservableSubscriptionTest.java | 7 ++ .../operators/SynchronizedObserverTest.java | 7 ++ .../test/java/rx/operators/TakeWhileTest.java | 7 ++ .../operators/TimeIntervalObserverTest.java | 7 ++ .../java/rx/plugins/RxJavaPluginsTest.java | 7 ++ .../java/rx/subjects/AsyncSubjectTest.java | 7 ++ .../java/rx/subjects/BehaviorSubjectTest.java | 7 ++ .../java/rx/subjects/PublishSubjectTest.java | 7 ++ .../java/rx/subjects/ReplaySubjectTest.java | 7 ++ .../CompositeSubscriptionTest.java | 7 ++ .../rx/subscriptions/SubscriptionsTest.java | 7 ++ .../src/test/java/rx/util/RangeTest.java | 7 ++ 70 files changed, 514 insertions(+), 34 deletions(-) rename rxjava-core/src/test/java/rx/{concurrency/TestSchedulers.java => SchedulersTest.java} (95%) create mode 100644 rxjava-core/src/test/java/rx/concurrency/CurrentThreadSchedulerTest.java create mode 100644 rxjava-core/src/test/java/rx/concurrency/ImmediateSchedulerTest.java create mode 100644 rxjava-core/src/test/java/rx/observables/BlockingObservableTest.java create mode 100644 rxjava-core/src/test/java/rx/operators/OperationAllTest.java create mode 100644 rxjava-core/src/test/java/rx/operators/OperationAnyTest.java create mode 100644 rxjava-core/src/test/java/rx/operators/OperationAverageTest.java create mode 100644 rxjava-core/src/test/java/rx/operators/OperationBufferTest.java create mode 100644 rxjava-core/src/test/java/rx/operators/OperationCacheTest.java create mode 100644 rxjava-core/src/test/java/rx/operators/OperationCastTest.java create mode 100644 rxjava-core/src/test/java/rx/operators/OperationCombineLatestTest.java create mode 100644 rxjava-core/src/test/java/rx/operators/OperationConcatTest.java create mode 100644 rxjava-core/src/test/java/rx/operators/OperationDebounceTest.java create mode 100644 rxjava-core/src/test/java/rx/operators/OperationDefaultIfEmptyTest.java create mode 100644 rxjava-core/src/test/java/rx/operators/OperationDeferTest.java create mode 100644 rxjava-core/src/test/java/rx/operators/OperationDematerializeTest.java create mode 100644 rxjava-core/src/test/java/rx/operators/OperationDistinctTest.java create mode 100644 rxjava-core/src/test/java/rx/operators/OperationDistinctUntilChangedTest.java create mode 100644 rxjava-core/src/test/java/rx/operators/OperationElementAtTest.java create mode 100644 rxjava-core/src/test/java/rx/operators/OperationFilterTest.java create mode 100644 rxjava-core/src/test/java/rx/operators/OperationFinallyTest.java create mode 100644 rxjava-core/src/test/java/rx/operators/OperationFirstOrDefaultTest.java create mode 100644 rxjava-core/src/test/java/rx/operators/OperationGroupByTest.java create mode 100644 rxjava-core/src/test/java/rx/operators/OperationIntervalTest.java create mode 100644 rxjava-core/src/test/java/rx/operators/OperationMapTest.java create mode 100644 rxjava-core/src/test/java/rx/operators/OperationMaterializeTest.java create mode 100644 rxjava-core/src/test/java/rx/operators/OperationMergeDelayErrorTest.java create mode 100644 rxjava-core/src/test/java/rx/operators/OperationMergeTest.java create mode 100644 rxjava-core/src/test/java/rx/operators/OperationMostRecentTest.java create mode 100644 rxjava-core/src/test/java/rx/operators/OperationMulticastTest.java create mode 100644 rxjava-core/src/test/java/rx/operators/OperationNextTest.java create mode 100644 rxjava-core/src/test/java/rx/operators/OperationObserveOnTest.java create mode 100644 rxjava-core/src/test/java/rx/operators/OperationOnErrorResumeNextViaFunctionTest.java create mode 100644 rxjava-core/src/test/java/rx/operators/OperationOnErrorResumeNextViaObservableTest.java create mode 100644 rxjava-core/src/test/java/rx/operators/OperationOnErrorReturnTest.java create mode 100644 rxjava-core/src/test/java/rx/operators/OperationOnExceptionResumeNextViaObservableTest.java create mode 100644 rxjava-core/src/test/java/rx/operators/OperationParallelTest.java create mode 100644 rxjava-core/src/test/java/rx/operators/OperationRetryTest.java create mode 100644 rxjava-core/src/test/java/rx/operators/OperationSampleTest.java create mode 100644 rxjava-core/src/test/java/rx/operators/OperationScanTest.java create mode 100644 rxjava-core/src/test/java/rx/operators/OperationSkipLastTest.java create mode 100644 rxjava-core/src/test/java/rx/operators/OperationSkipTest.java create mode 100644 rxjava-core/src/test/java/rx/operators/OperationSkipWhileTest.java create mode 100644 rxjava-core/src/test/java/rx/operators/OperationSubscribeOnTest.java create mode 100644 rxjava-core/src/test/java/rx/operators/OperationSumTest.java create mode 100644 rxjava-core/src/test/java/rx/operators/OperationSwitchTest.java create mode 100644 rxjava-core/src/test/java/rx/operators/OperationSynchronizeTest.java create mode 100644 rxjava-core/src/test/java/rx/operators/OperationTakeLastTest.java create mode 100644 rxjava-core/src/test/java/rx/operators/OperationTakeTest.java create mode 100644 rxjava-core/src/test/java/rx/operators/OperationTakeUntilTest.java create mode 100644 rxjava-core/src/test/java/rx/operators/OperationThrottleFirstTest.java create mode 100644 rxjava-core/src/test/java/rx/operators/OperationToObservableFutureTest.java create mode 100644 rxjava-core/src/test/java/rx/operators/OperationToObservableIterableTest.java create mode 100644 rxjava-core/src/test/java/rx/operators/OperationToObservableListTest.java create mode 100644 rxjava-core/src/test/java/rx/operators/OperationToObservableSortedListTest.java create mode 100644 rxjava-core/src/test/java/rx/operators/OperationWindowTest.java create mode 100644 rxjava-core/src/test/java/rx/operators/OperationZipTest.java create mode 100644 rxjava-core/src/test/java/rx/operators/OperatorTesterTest.java create mode 100644 rxjava-core/src/test/java/rx/operators/SafeObservableSubscriptionTest.java create mode 100644 rxjava-core/src/test/java/rx/operators/SynchronizedObserverTest.java create mode 100644 rxjava-core/src/test/java/rx/operators/TakeWhileTest.java create mode 100644 rxjava-core/src/test/java/rx/operators/TimeIntervalObserverTest.java create mode 100644 rxjava-core/src/test/java/rx/plugins/RxJavaPluginsTest.java create mode 100644 rxjava-core/src/test/java/rx/subjects/AsyncSubjectTest.java create mode 100644 rxjava-core/src/test/java/rx/subjects/BehaviorSubjectTest.java create mode 100644 rxjava-core/src/test/java/rx/subjects/PublishSubjectTest.java create mode 100644 rxjava-core/src/test/java/rx/subjects/ReplaySubjectTest.java create mode 100644 rxjava-core/src/test/java/rx/subscriptions/CompositeSubscriptionTest.java create mode 100644 rxjava-core/src/test/java/rx/subscriptions/SubscriptionsTest.java create mode 100644 rxjava-core/src/test/java/rx/util/RangeTest.java diff --git a/rxjava-core/src/test/java/rx/concurrency/TestSchedulers.java b/rxjava-core/src/test/java/rx/SchedulersTest.java similarity index 95% rename from rxjava-core/src/test/java/rx/concurrency/TestSchedulers.java rename to rxjava-core/src/test/java/rx/SchedulersTest.java index e1df828237..d2ac58e61f 100644 --- a/rxjava-core/src/test/java/rx/concurrency/TestSchedulers.java +++ b/rxjava-core/src/test/java/rx/SchedulersTest.java @@ -1,36 +1,24 @@ /** * Copyright 2013 Netflix, Inc. - * + * * 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 rx.concurrency; - -import static org.junit.Assert.*; - -import java.util.Date; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicBoolean; -import java.util.concurrent.atomic.AtomicInteger; -import java.util.concurrent.atomic.AtomicReference; +package rx; import org.junit.Test; - -import rx.Observable; import rx.Observable.OnSubscribeFunc; -import rx.Observer; -import rx.Scheduler; -import rx.Subscription; +import rx.concurrency.Schedulers; +import rx.concurrency.TestScheduler; import rx.subscriptions.BooleanSubscription; import rx.subscriptions.Subscriptions; import rx.util.functions.Action0; @@ -38,7 +26,16 @@ import rx.util.functions.Func1; import rx.util.functions.Func2; -public class TestSchedulers { +import java.util.Date; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.atomic.AtomicReference; + +import static org.junit.Assert.*; + +public class SchedulersTest { @Test public void testComputationThreadPool1() { @@ -447,18 +444,18 @@ public void testSubscribeOnNestedConcurrency() throws InterruptedException { Observable o = Observable.from("one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten") .mapMany(new Func1>() { - @Override - public Observable call(final String v) { - return Observable.create(new OnSubscribeFunc() { - - @Override - public Subscription onSubscribe(final Observer observer) { - observer.onNext("value_after_map-" + v); - observer.onCompleted(); - return Subscriptions.empty(); - } - }).subscribeOn(Schedulers.newThread()); // subscribe on a new thread - } + @Override + public Observable call(final String v) { + return Observable.create(new OnSubscribeFunc() { + + @Override + public Subscription onSubscribe(final Observer observer) { + observer.onNext("value_after_map-" + v); + observer.onCompleted(); + return Subscriptions.empty(); + } + }).subscribeOn(Schedulers.newThread()); // subscribe on a new thread + } }); ConcurrentObserverValidator observer = new ConcurrentObserverValidator(); @@ -474,7 +471,7 @@ public Subscription onSubscribe(final Observer observer) { fail("Error: " + observer.error.get().getMessage()); } } - + @Test public void testRecursion() { TestScheduler s = new TestScheduler(); @@ -494,11 +491,11 @@ public void call(Action0 self) { subscription.unsubscribe(); assertEquals(0, counter.get()); } - + /** * Used to determine if onNext is being invoked concurrently. - * + * * @param */ private static class ConcurrentObserverValidator implements Observer { diff --git a/rxjava-core/src/test/java/rx/concurrency/CurrentThreadSchedulerTest.java b/rxjava-core/src/test/java/rx/concurrency/CurrentThreadSchedulerTest.java new file mode 100644 index 0000000000..b9a9b1a1c2 --- /dev/null +++ b/rxjava-core/src/test/java/rx/concurrency/CurrentThreadSchedulerTest.java @@ -0,0 +1,7 @@ +package rx.concurrency; + +import org.junit.Ignore; + +@Ignore("WIP") +public class CurrentThreadSchedulerTest { +} diff --git a/rxjava-core/src/test/java/rx/concurrency/ImmediateSchedulerTest.java b/rxjava-core/src/test/java/rx/concurrency/ImmediateSchedulerTest.java new file mode 100644 index 0000000000..036103e540 --- /dev/null +++ b/rxjava-core/src/test/java/rx/concurrency/ImmediateSchedulerTest.java @@ -0,0 +1,7 @@ +package rx.concurrency; + +import org.junit.Ignore; + +@Ignore("WIP") +public class ImmediateSchedulerTest { +} diff --git a/rxjava-core/src/test/java/rx/observables/BlockingObservableTest.java b/rxjava-core/src/test/java/rx/observables/BlockingObservableTest.java new file mode 100644 index 0000000000..aa38f711ad --- /dev/null +++ b/rxjava-core/src/test/java/rx/observables/BlockingObservableTest.java @@ -0,0 +1,7 @@ +package rx.observables; + +import org.junit.Ignore; + +@Ignore("WIP") +public class BlockingObservableTest { +} diff --git a/rxjava-core/src/test/java/rx/operators/OperationAllTest.java b/rxjava-core/src/test/java/rx/operators/OperationAllTest.java new file mode 100644 index 0000000000..ffb0b56798 --- /dev/null +++ b/rxjava-core/src/test/java/rx/operators/OperationAllTest.java @@ -0,0 +1,7 @@ +package rx.operators; + +import org.junit.Ignore; + +@Ignore("WIP") +public class OperationAllTest { +} diff --git a/rxjava-core/src/test/java/rx/operators/OperationAnyTest.java b/rxjava-core/src/test/java/rx/operators/OperationAnyTest.java new file mode 100644 index 0000000000..98d6e72fa5 --- /dev/null +++ b/rxjava-core/src/test/java/rx/operators/OperationAnyTest.java @@ -0,0 +1,7 @@ +package rx.operators; + +import org.junit.Ignore; + +@Ignore("WIP") +public class OperationAnyTest { +} diff --git a/rxjava-core/src/test/java/rx/operators/OperationAverageTest.java b/rxjava-core/src/test/java/rx/operators/OperationAverageTest.java new file mode 100644 index 0000000000..6fa01dfc92 --- /dev/null +++ b/rxjava-core/src/test/java/rx/operators/OperationAverageTest.java @@ -0,0 +1,7 @@ +package rx.operators; + +import org.junit.Ignore; + +@Ignore("WIP") +public class OperationAverageTest { +} diff --git a/rxjava-core/src/test/java/rx/operators/OperationBufferTest.java b/rxjava-core/src/test/java/rx/operators/OperationBufferTest.java new file mode 100644 index 0000000000..d096cd666a --- /dev/null +++ b/rxjava-core/src/test/java/rx/operators/OperationBufferTest.java @@ -0,0 +1,7 @@ +package rx.operators; + +import org.junit.Ignore; + +@Ignore("WIP") +public class OperationBufferTest { +} diff --git a/rxjava-core/src/test/java/rx/operators/OperationCacheTest.java b/rxjava-core/src/test/java/rx/operators/OperationCacheTest.java new file mode 100644 index 0000000000..4a754528e5 --- /dev/null +++ b/rxjava-core/src/test/java/rx/operators/OperationCacheTest.java @@ -0,0 +1,7 @@ +package rx.operators; + +import org.junit.Ignore; + +@Ignore("WIP") +public class OperationCacheTest { +} diff --git a/rxjava-core/src/test/java/rx/operators/OperationCastTest.java b/rxjava-core/src/test/java/rx/operators/OperationCastTest.java new file mode 100644 index 0000000000..36bab268ff --- /dev/null +++ b/rxjava-core/src/test/java/rx/operators/OperationCastTest.java @@ -0,0 +1,7 @@ +package rx.operators; + +import org.junit.Ignore; + +@Ignore("WIP") +public class OperationCastTest { +} diff --git a/rxjava-core/src/test/java/rx/operators/OperationCombineLatestTest.java b/rxjava-core/src/test/java/rx/operators/OperationCombineLatestTest.java new file mode 100644 index 0000000000..b154ce1223 --- /dev/null +++ b/rxjava-core/src/test/java/rx/operators/OperationCombineLatestTest.java @@ -0,0 +1,7 @@ +package rx.operators; + +import org.junit.Ignore; + +@Ignore("WIP") +public class OperationCombineLatestTest { +} diff --git a/rxjava-core/src/test/java/rx/operators/OperationConcatTest.java b/rxjava-core/src/test/java/rx/operators/OperationConcatTest.java new file mode 100644 index 0000000000..1380ffcaef --- /dev/null +++ b/rxjava-core/src/test/java/rx/operators/OperationConcatTest.java @@ -0,0 +1,7 @@ +package rx.operators; + +import org.junit.Ignore; + +@Ignore("WIP") +public class OperationConcatTest { +} diff --git a/rxjava-core/src/test/java/rx/operators/OperationDebounceTest.java b/rxjava-core/src/test/java/rx/operators/OperationDebounceTest.java new file mode 100644 index 0000000000..a1f6d4c237 --- /dev/null +++ b/rxjava-core/src/test/java/rx/operators/OperationDebounceTest.java @@ -0,0 +1,7 @@ +package rx.operators; + +import org.junit.Ignore; + +@Ignore("WIP") +public class OperationDebounceTest { +} diff --git a/rxjava-core/src/test/java/rx/operators/OperationDefaultIfEmptyTest.java b/rxjava-core/src/test/java/rx/operators/OperationDefaultIfEmptyTest.java new file mode 100644 index 0000000000..241c8790c3 --- /dev/null +++ b/rxjava-core/src/test/java/rx/operators/OperationDefaultIfEmptyTest.java @@ -0,0 +1,7 @@ +package rx.operators; + +import org.junit.Ignore; + +@Ignore("WIP") +public class OperationDefaultIfEmptyTest { +} diff --git a/rxjava-core/src/test/java/rx/operators/OperationDeferTest.java b/rxjava-core/src/test/java/rx/operators/OperationDeferTest.java new file mode 100644 index 0000000000..344cbee450 --- /dev/null +++ b/rxjava-core/src/test/java/rx/operators/OperationDeferTest.java @@ -0,0 +1,7 @@ +package rx.operators; + +import org.junit.Ignore; + +@Ignore("WIP") +public class OperationDeferTest { +} diff --git a/rxjava-core/src/test/java/rx/operators/OperationDematerializeTest.java b/rxjava-core/src/test/java/rx/operators/OperationDematerializeTest.java new file mode 100644 index 0000000000..f0433032fb --- /dev/null +++ b/rxjava-core/src/test/java/rx/operators/OperationDematerializeTest.java @@ -0,0 +1,7 @@ +package rx.operators; + +import org.junit.Ignore; + +@Ignore("WIP") +public class OperationDematerializeTest { +} diff --git a/rxjava-core/src/test/java/rx/operators/OperationDistinctTest.java b/rxjava-core/src/test/java/rx/operators/OperationDistinctTest.java new file mode 100644 index 0000000000..1704b644fc --- /dev/null +++ b/rxjava-core/src/test/java/rx/operators/OperationDistinctTest.java @@ -0,0 +1,7 @@ +package rx.operators; + +import org.junit.Ignore; + +@Ignore("WIP") +public class OperationDistinctTest { +} diff --git a/rxjava-core/src/test/java/rx/operators/OperationDistinctUntilChangedTest.java b/rxjava-core/src/test/java/rx/operators/OperationDistinctUntilChangedTest.java new file mode 100644 index 0000000000..cdb4eb7203 --- /dev/null +++ b/rxjava-core/src/test/java/rx/operators/OperationDistinctUntilChangedTest.java @@ -0,0 +1,7 @@ +package rx.operators; + +import org.junit.Ignore; + +@Ignore("WIP") +public class OperationDistinctUntilChangedTest { +} diff --git a/rxjava-core/src/test/java/rx/operators/OperationElementAtTest.java b/rxjava-core/src/test/java/rx/operators/OperationElementAtTest.java new file mode 100644 index 0000000000..b17efa3cd3 --- /dev/null +++ b/rxjava-core/src/test/java/rx/operators/OperationElementAtTest.java @@ -0,0 +1,7 @@ +package rx.operators; + +import org.junit.Ignore; + +@Ignore("WIP") +public class OperationElementAtTest { +} diff --git a/rxjava-core/src/test/java/rx/operators/OperationFilterTest.java b/rxjava-core/src/test/java/rx/operators/OperationFilterTest.java new file mode 100644 index 0000000000..19e15ea81a --- /dev/null +++ b/rxjava-core/src/test/java/rx/operators/OperationFilterTest.java @@ -0,0 +1,7 @@ +package rx.operators; + +import org.junit.Ignore; + +@Ignore("WIP") +public class OperationFilterTest { +} diff --git a/rxjava-core/src/test/java/rx/operators/OperationFinallyTest.java b/rxjava-core/src/test/java/rx/operators/OperationFinallyTest.java new file mode 100644 index 0000000000..0e46ce1cb2 --- /dev/null +++ b/rxjava-core/src/test/java/rx/operators/OperationFinallyTest.java @@ -0,0 +1,7 @@ +package rx.operators; + +import org.junit.Ignore; + +@Ignore("WIP") +public class OperationFinallyTest { +} diff --git a/rxjava-core/src/test/java/rx/operators/OperationFirstOrDefaultTest.java b/rxjava-core/src/test/java/rx/operators/OperationFirstOrDefaultTest.java new file mode 100644 index 0000000000..39a60a03c5 --- /dev/null +++ b/rxjava-core/src/test/java/rx/operators/OperationFirstOrDefaultTest.java @@ -0,0 +1,7 @@ +package rx.operators; + +import org.junit.Ignore; + +@Ignore("WIP") +public class OperationFirstOrDefaultTest { +} diff --git a/rxjava-core/src/test/java/rx/operators/OperationGroupByTest.java b/rxjava-core/src/test/java/rx/operators/OperationGroupByTest.java new file mode 100644 index 0000000000..222085a96f --- /dev/null +++ b/rxjava-core/src/test/java/rx/operators/OperationGroupByTest.java @@ -0,0 +1,7 @@ +package rx.operators; + +import org.junit.Ignore; + +@Ignore("WIP") +public class OperationGroupByTest { +} diff --git a/rxjava-core/src/test/java/rx/operators/OperationIntervalTest.java b/rxjava-core/src/test/java/rx/operators/OperationIntervalTest.java new file mode 100644 index 0000000000..60b2ad7789 --- /dev/null +++ b/rxjava-core/src/test/java/rx/operators/OperationIntervalTest.java @@ -0,0 +1,7 @@ +package rx.operators; + +import org.junit.Ignore; + +@Ignore("WIP") +public class OperationIntervalTest { +} diff --git a/rxjava-core/src/test/java/rx/operators/OperationMapTest.java b/rxjava-core/src/test/java/rx/operators/OperationMapTest.java new file mode 100644 index 0000000000..3c3ee5813c --- /dev/null +++ b/rxjava-core/src/test/java/rx/operators/OperationMapTest.java @@ -0,0 +1,7 @@ +package rx.operators; + +import org.junit.Ignore; + +@Ignore("WIP") +public class OperationMapTest { +} diff --git a/rxjava-core/src/test/java/rx/operators/OperationMaterializeTest.java b/rxjava-core/src/test/java/rx/operators/OperationMaterializeTest.java new file mode 100644 index 0000000000..24f67b432c --- /dev/null +++ b/rxjava-core/src/test/java/rx/operators/OperationMaterializeTest.java @@ -0,0 +1,7 @@ +package rx.operators; + +import org.junit.Ignore; + +@Ignore("WIP") +public class OperationMaterializeTest { +} diff --git a/rxjava-core/src/test/java/rx/operators/OperationMergeDelayErrorTest.java b/rxjava-core/src/test/java/rx/operators/OperationMergeDelayErrorTest.java new file mode 100644 index 0000000000..1e3c763573 --- /dev/null +++ b/rxjava-core/src/test/java/rx/operators/OperationMergeDelayErrorTest.java @@ -0,0 +1,7 @@ +package rx.operators; + +import org.junit.Ignore; + +@Ignore("WIP") +public class OperationMergeDelayErrorTest { +} diff --git a/rxjava-core/src/test/java/rx/operators/OperationMergeTest.java b/rxjava-core/src/test/java/rx/operators/OperationMergeTest.java new file mode 100644 index 0000000000..ef50b179e6 --- /dev/null +++ b/rxjava-core/src/test/java/rx/operators/OperationMergeTest.java @@ -0,0 +1,7 @@ +package rx.operators; + +import org.junit.Ignore; + +@Ignore("WIP") +public class OperationMergeTest { +} diff --git a/rxjava-core/src/test/java/rx/operators/OperationMostRecentTest.java b/rxjava-core/src/test/java/rx/operators/OperationMostRecentTest.java new file mode 100644 index 0000000000..1f5806b310 --- /dev/null +++ b/rxjava-core/src/test/java/rx/operators/OperationMostRecentTest.java @@ -0,0 +1,7 @@ +package rx.operators; + +import org.junit.Ignore; + +@Ignore("WIP") +public class OperationMostRecentTest { +} diff --git a/rxjava-core/src/test/java/rx/operators/OperationMulticastTest.java b/rxjava-core/src/test/java/rx/operators/OperationMulticastTest.java new file mode 100644 index 0000000000..dd2ba06360 --- /dev/null +++ b/rxjava-core/src/test/java/rx/operators/OperationMulticastTest.java @@ -0,0 +1,7 @@ +package rx.operators; + +import org.junit.Ignore; + +@Ignore("WIP") +public class OperationMulticastTest { +} diff --git a/rxjava-core/src/test/java/rx/operators/OperationNextTest.java b/rxjava-core/src/test/java/rx/operators/OperationNextTest.java new file mode 100644 index 0000000000..bad26bbcb1 --- /dev/null +++ b/rxjava-core/src/test/java/rx/operators/OperationNextTest.java @@ -0,0 +1,7 @@ +package rx.operators; + +import org.junit.Ignore; + +@Ignore("WIP") +public class OperationNextTest { +} diff --git a/rxjava-core/src/test/java/rx/operators/OperationObserveOnTest.java b/rxjava-core/src/test/java/rx/operators/OperationObserveOnTest.java new file mode 100644 index 0000000000..9f439949a8 --- /dev/null +++ b/rxjava-core/src/test/java/rx/operators/OperationObserveOnTest.java @@ -0,0 +1,7 @@ +package rx.operators; + +import org.junit.Ignore; + +@Ignore("WIP") +public class OperationObserveOnTest { +} diff --git a/rxjava-core/src/test/java/rx/operators/OperationOnErrorResumeNextViaFunctionTest.java b/rxjava-core/src/test/java/rx/operators/OperationOnErrorResumeNextViaFunctionTest.java new file mode 100644 index 0000000000..8a98b35dd2 --- /dev/null +++ b/rxjava-core/src/test/java/rx/operators/OperationOnErrorResumeNextViaFunctionTest.java @@ -0,0 +1,7 @@ +package rx.operators; + +import org.junit.Ignore; + +@Ignore("WIP") +public class OperationOnErrorResumeNextViaFunctionTest { +} diff --git a/rxjava-core/src/test/java/rx/operators/OperationOnErrorResumeNextViaObservableTest.java b/rxjava-core/src/test/java/rx/operators/OperationOnErrorResumeNextViaObservableTest.java new file mode 100644 index 0000000000..b0ec9f3211 --- /dev/null +++ b/rxjava-core/src/test/java/rx/operators/OperationOnErrorResumeNextViaObservableTest.java @@ -0,0 +1,7 @@ +package rx.operators; + +import org.junit.Ignore; + +@Ignore("WIP") +public class OperationOnErrorResumeNextViaObservableTest { +} diff --git a/rxjava-core/src/test/java/rx/operators/OperationOnErrorReturnTest.java b/rxjava-core/src/test/java/rx/operators/OperationOnErrorReturnTest.java new file mode 100644 index 0000000000..0fe50a7f04 --- /dev/null +++ b/rxjava-core/src/test/java/rx/operators/OperationOnErrorReturnTest.java @@ -0,0 +1,7 @@ +package rx.operators; + +import org.junit.Ignore; + +@Ignore("WIP") +public class OperationOnErrorReturnTest { +} diff --git a/rxjava-core/src/test/java/rx/operators/OperationOnExceptionResumeNextViaObservableTest.java b/rxjava-core/src/test/java/rx/operators/OperationOnExceptionResumeNextViaObservableTest.java new file mode 100644 index 0000000000..4e8a7c1586 --- /dev/null +++ b/rxjava-core/src/test/java/rx/operators/OperationOnExceptionResumeNextViaObservableTest.java @@ -0,0 +1,7 @@ +package rx.operators; + +import org.junit.Ignore; + +@Ignore("WIP") +public class OperationOnExceptionResumeNextViaObservableTest { +} diff --git a/rxjava-core/src/test/java/rx/operators/OperationParallelTest.java b/rxjava-core/src/test/java/rx/operators/OperationParallelTest.java new file mode 100644 index 0000000000..fee3816e98 --- /dev/null +++ b/rxjava-core/src/test/java/rx/operators/OperationParallelTest.java @@ -0,0 +1,7 @@ +package rx.operators; + +import org.junit.Ignore; + +@Ignore("WIP") +public class OperationParallelTest { +} diff --git a/rxjava-core/src/test/java/rx/operators/OperationRetryTest.java b/rxjava-core/src/test/java/rx/operators/OperationRetryTest.java new file mode 100644 index 0000000000..768d1f5f9c --- /dev/null +++ b/rxjava-core/src/test/java/rx/operators/OperationRetryTest.java @@ -0,0 +1,7 @@ +package rx.operators; + +import org.junit.Ignore; + +@Ignore("WIP") +public class OperationRetryTest { +} diff --git a/rxjava-core/src/test/java/rx/operators/OperationSampleTest.java b/rxjava-core/src/test/java/rx/operators/OperationSampleTest.java new file mode 100644 index 0000000000..a718adbc0a --- /dev/null +++ b/rxjava-core/src/test/java/rx/operators/OperationSampleTest.java @@ -0,0 +1,7 @@ +package rx.operators; + +import org.junit.Ignore; + +@Ignore("WIP") +public class OperationSampleTest { +} diff --git a/rxjava-core/src/test/java/rx/operators/OperationScanTest.java b/rxjava-core/src/test/java/rx/operators/OperationScanTest.java new file mode 100644 index 0000000000..aa3d7d6f9e --- /dev/null +++ b/rxjava-core/src/test/java/rx/operators/OperationScanTest.java @@ -0,0 +1,7 @@ +package rx.operators; + +import org.junit.Ignore; + +@Ignore("WIP") +public class OperationScanTest { +} diff --git a/rxjava-core/src/test/java/rx/operators/OperationSkipLastTest.java b/rxjava-core/src/test/java/rx/operators/OperationSkipLastTest.java new file mode 100644 index 0000000000..9604c718c7 --- /dev/null +++ b/rxjava-core/src/test/java/rx/operators/OperationSkipLastTest.java @@ -0,0 +1,7 @@ +package rx.operators; + +import org.junit.Ignore; + +@Ignore("WIP") +public class OperationSkipLastTest { +} diff --git a/rxjava-core/src/test/java/rx/operators/OperationSkipTest.java b/rxjava-core/src/test/java/rx/operators/OperationSkipTest.java new file mode 100644 index 0000000000..1d74ed6302 --- /dev/null +++ b/rxjava-core/src/test/java/rx/operators/OperationSkipTest.java @@ -0,0 +1,7 @@ +package rx.operators; + +import org.junit.Ignore; + +@Ignore("WIP") +public class OperationSkipTest { +} diff --git a/rxjava-core/src/test/java/rx/operators/OperationSkipWhileTest.java b/rxjava-core/src/test/java/rx/operators/OperationSkipWhileTest.java new file mode 100644 index 0000000000..d9347d907e --- /dev/null +++ b/rxjava-core/src/test/java/rx/operators/OperationSkipWhileTest.java @@ -0,0 +1,7 @@ +package rx.operators; + +import org.junit.Ignore; + +@Ignore("WIP") +public class OperationSkipWhileTest { +} diff --git a/rxjava-core/src/test/java/rx/operators/OperationSubscribeOnTest.java b/rxjava-core/src/test/java/rx/operators/OperationSubscribeOnTest.java new file mode 100644 index 0000000000..495cbc6713 --- /dev/null +++ b/rxjava-core/src/test/java/rx/operators/OperationSubscribeOnTest.java @@ -0,0 +1,7 @@ +package rx.operators; + +import org.junit.Ignore; + +@Ignore("WIP") +public class OperationSubscribeOnTest { +} diff --git a/rxjava-core/src/test/java/rx/operators/OperationSumTest.java b/rxjava-core/src/test/java/rx/operators/OperationSumTest.java new file mode 100644 index 0000000000..c89121e207 --- /dev/null +++ b/rxjava-core/src/test/java/rx/operators/OperationSumTest.java @@ -0,0 +1,7 @@ +package rx.operators; + +import org.junit.Ignore; + +@Ignore("WIP") +public class OperationSumTest { +} diff --git a/rxjava-core/src/test/java/rx/operators/OperationSwitchTest.java b/rxjava-core/src/test/java/rx/operators/OperationSwitchTest.java new file mode 100644 index 0000000000..d91bb804bf --- /dev/null +++ b/rxjava-core/src/test/java/rx/operators/OperationSwitchTest.java @@ -0,0 +1,7 @@ +package rx.operators; + +import org.junit.Ignore; + +@Ignore("WIP") +public class OperationSwitchTest { +} diff --git a/rxjava-core/src/test/java/rx/operators/OperationSynchronizeTest.java b/rxjava-core/src/test/java/rx/operators/OperationSynchronizeTest.java new file mode 100644 index 0000000000..2dce4a7d32 --- /dev/null +++ b/rxjava-core/src/test/java/rx/operators/OperationSynchronizeTest.java @@ -0,0 +1,7 @@ +package rx.operators; + +import org.junit.Ignore; + +@Ignore("WIP") +public class OperationSynchronizeTest { +} diff --git a/rxjava-core/src/test/java/rx/operators/OperationTakeLastTest.java b/rxjava-core/src/test/java/rx/operators/OperationTakeLastTest.java new file mode 100644 index 0000000000..234e70d543 --- /dev/null +++ b/rxjava-core/src/test/java/rx/operators/OperationTakeLastTest.java @@ -0,0 +1,7 @@ +package rx.operators; + +import org.junit.Ignore; + +@Ignore("WIP") +public class OperationTakeLastTest { +} diff --git a/rxjava-core/src/test/java/rx/operators/OperationTakeTest.java b/rxjava-core/src/test/java/rx/operators/OperationTakeTest.java new file mode 100644 index 0000000000..eaa1bdf1d4 --- /dev/null +++ b/rxjava-core/src/test/java/rx/operators/OperationTakeTest.java @@ -0,0 +1,7 @@ +package rx.operators; + +import org.junit.Ignore; + +@Ignore("WIP") +public class OperationTakeTest { +} diff --git a/rxjava-core/src/test/java/rx/operators/OperationTakeUntilTest.java b/rxjava-core/src/test/java/rx/operators/OperationTakeUntilTest.java new file mode 100644 index 0000000000..22cd5eb078 --- /dev/null +++ b/rxjava-core/src/test/java/rx/operators/OperationTakeUntilTest.java @@ -0,0 +1,7 @@ +package rx.operators; + +import org.junit.Ignore; + +@Ignore("WIP") +public class OperationTakeUntilTest { +} diff --git a/rxjava-core/src/test/java/rx/operators/OperationThrottleFirstTest.java b/rxjava-core/src/test/java/rx/operators/OperationThrottleFirstTest.java new file mode 100644 index 0000000000..66301abfca --- /dev/null +++ b/rxjava-core/src/test/java/rx/operators/OperationThrottleFirstTest.java @@ -0,0 +1,7 @@ +package rx.operators; + +import org.junit.Ignore; + +@Ignore("WIP") +public class OperationThrottleFirstTest { +} diff --git a/rxjava-core/src/test/java/rx/operators/OperationToObservableFutureTest.java b/rxjava-core/src/test/java/rx/operators/OperationToObservableFutureTest.java new file mode 100644 index 0000000000..3f58b63911 --- /dev/null +++ b/rxjava-core/src/test/java/rx/operators/OperationToObservableFutureTest.java @@ -0,0 +1,7 @@ +package rx.operators; + +import org.junit.Ignore; + +@Ignore("WIP") +public class OperationToObservableFutureTest { +} diff --git a/rxjava-core/src/test/java/rx/operators/OperationToObservableIterableTest.java b/rxjava-core/src/test/java/rx/operators/OperationToObservableIterableTest.java new file mode 100644 index 0000000000..1805e1cbcd --- /dev/null +++ b/rxjava-core/src/test/java/rx/operators/OperationToObservableIterableTest.java @@ -0,0 +1,7 @@ +package rx.operators; + +import org.junit.Ignore; + +@Ignore("WIP") +public class OperationToObservableIterableTest { +} diff --git a/rxjava-core/src/test/java/rx/operators/OperationToObservableListTest.java b/rxjava-core/src/test/java/rx/operators/OperationToObservableListTest.java new file mode 100644 index 0000000000..49c7409e86 --- /dev/null +++ b/rxjava-core/src/test/java/rx/operators/OperationToObservableListTest.java @@ -0,0 +1,7 @@ +package rx.operators; + +import org.junit.Ignore; + +@Ignore("WIP") +public class OperationToObservableListTest { +} diff --git a/rxjava-core/src/test/java/rx/operators/OperationToObservableSortedListTest.java b/rxjava-core/src/test/java/rx/operators/OperationToObservableSortedListTest.java new file mode 100644 index 0000000000..62efef680d --- /dev/null +++ b/rxjava-core/src/test/java/rx/operators/OperationToObservableSortedListTest.java @@ -0,0 +1,7 @@ +package rx.operators; + +import org.junit.Ignore; + +@Ignore("WIP") +public class OperationToObservableSortedListTest { +} diff --git a/rxjava-core/src/test/java/rx/operators/OperationWindowTest.java b/rxjava-core/src/test/java/rx/operators/OperationWindowTest.java new file mode 100644 index 0000000000..0e602254f5 --- /dev/null +++ b/rxjava-core/src/test/java/rx/operators/OperationWindowTest.java @@ -0,0 +1,7 @@ +package rx.operators; + +import org.junit.Ignore; + +@Ignore("WIP") +public class OperationWindowTest { +} diff --git a/rxjava-core/src/test/java/rx/operators/OperationZipTest.java b/rxjava-core/src/test/java/rx/operators/OperationZipTest.java new file mode 100644 index 0000000000..3e027193ab --- /dev/null +++ b/rxjava-core/src/test/java/rx/operators/OperationZipTest.java @@ -0,0 +1,7 @@ +package rx.operators; + +import org.junit.Ignore; + +@Ignore("WIP") +public class OperationZipTest { +} diff --git a/rxjava-core/src/test/java/rx/operators/OperatorTesterTest.java b/rxjava-core/src/test/java/rx/operators/OperatorTesterTest.java new file mode 100644 index 0000000000..f5a4161708 --- /dev/null +++ b/rxjava-core/src/test/java/rx/operators/OperatorTesterTest.java @@ -0,0 +1,7 @@ +package rx.operators; + +import org.junit.Ignore; + +@Ignore("WIP") +public class OperatorTesterTest { +} diff --git a/rxjava-core/src/test/java/rx/operators/SafeObservableSubscriptionTest.java b/rxjava-core/src/test/java/rx/operators/SafeObservableSubscriptionTest.java new file mode 100644 index 0000000000..c5b7e6d590 --- /dev/null +++ b/rxjava-core/src/test/java/rx/operators/SafeObservableSubscriptionTest.java @@ -0,0 +1,7 @@ +package rx.operators; + +import org.junit.Ignore; + +@Ignore("WIP") +public class SafeObservableSubscriptionTest { +} diff --git a/rxjava-core/src/test/java/rx/operators/SynchronizedObserverTest.java b/rxjava-core/src/test/java/rx/operators/SynchronizedObserverTest.java new file mode 100644 index 0000000000..5b4b301590 --- /dev/null +++ b/rxjava-core/src/test/java/rx/operators/SynchronizedObserverTest.java @@ -0,0 +1,7 @@ +package rx.operators; + +import org.junit.Ignore; + +@Ignore("WIP") +public class SynchronizedObserverTest { +} diff --git a/rxjava-core/src/test/java/rx/operators/TakeWhileTest.java b/rxjava-core/src/test/java/rx/operators/TakeWhileTest.java new file mode 100644 index 0000000000..c81169eac2 --- /dev/null +++ b/rxjava-core/src/test/java/rx/operators/TakeWhileTest.java @@ -0,0 +1,7 @@ +package rx.operators; + +import org.junit.Ignore; + +@Ignore("WIP") +public class TakeWhileTest { +} diff --git a/rxjava-core/src/test/java/rx/operators/TimeIntervalObserverTest.java b/rxjava-core/src/test/java/rx/operators/TimeIntervalObserverTest.java new file mode 100644 index 0000000000..6f073696f0 --- /dev/null +++ b/rxjava-core/src/test/java/rx/operators/TimeIntervalObserverTest.java @@ -0,0 +1,7 @@ +package rx.operators; + +import org.junit.Ignore; + +@Ignore("WIP") +public class TimeIntervalObserverTest { +} diff --git a/rxjava-core/src/test/java/rx/plugins/RxJavaPluginsTest.java b/rxjava-core/src/test/java/rx/plugins/RxJavaPluginsTest.java new file mode 100644 index 0000000000..1def236246 --- /dev/null +++ b/rxjava-core/src/test/java/rx/plugins/RxJavaPluginsTest.java @@ -0,0 +1,7 @@ +package rx.plugins; + +import org.junit.Ignore; + +@Ignore("WIP") +public class RxJavaPluginsTest { +} diff --git a/rxjava-core/src/test/java/rx/subjects/AsyncSubjectTest.java b/rxjava-core/src/test/java/rx/subjects/AsyncSubjectTest.java new file mode 100644 index 0000000000..bfe0aa0bb0 --- /dev/null +++ b/rxjava-core/src/test/java/rx/subjects/AsyncSubjectTest.java @@ -0,0 +1,7 @@ +package rx.subjects; + +import org.junit.Ignore; + +@Ignore("WIP") +public class AsyncSubjectTest { +} diff --git a/rxjava-core/src/test/java/rx/subjects/BehaviorSubjectTest.java b/rxjava-core/src/test/java/rx/subjects/BehaviorSubjectTest.java new file mode 100644 index 0000000000..ffee087158 --- /dev/null +++ b/rxjava-core/src/test/java/rx/subjects/BehaviorSubjectTest.java @@ -0,0 +1,7 @@ +package rx.subjects; + +import org.junit.Ignore; + +@Ignore("WIP") +public class BehaviorSubjectTest { +} diff --git a/rxjava-core/src/test/java/rx/subjects/PublishSubjectTest.java b/rxjava-core/src/test/java/rx/subjects/PublishSubjectTest.java new file mode 100644 index 0000000000..25cebbf510 --- /dev/null +++ b/rxjava-core/src/test/java/rx/subjects/PublishSubjectTest.java @@ -0,0 +1,7 @@ +package rx.subjects; + +import org.junit.Ignore; + +@Ignore("WIP") +public class PublishSubjectTest { +} diff --git a/rxjava-core/src/test/java/rx/subjects/ReplaySubjectTest.java b/rxjava-core/src/test/java/rx/subjects/ReplaySubjectTest.java new file mode 100644 index 0000000000..1e722e5e5e --- /dev/null +++ b/rxjava-core/src/test/java/rx/subjects/ReplaySubjectTest.java @@ -0,0 +1,7 @@ +package rx.subjects; + +import org.junit.Ignore; + +@Ignore("WIP") +public class ReplaySubjectTest { +} diff --git a/rxjava-core/src/test/java/rx/subscriptions/CompositeSubscriptionTest.java b/rxjava-core/src/test/java/rx/subscriptions/CompositeSubscriptionTest.java new file mode 100644 index 0000000000..43830564ce --- /dev/null +++ b/rxjava-core/src/test/java/rx/subscriptions/CompositeSubscriptionTest.java @@ -0,0 +1,7 @@ +package rx.subscriptions; + +import org.junit.Ignore; + +@Ignore("WIP") +public class CompositeSubscriptionTest { +} diff --git a/rxjava-core/src/test/java/rx/subscriptions/SubscriptionsTest.java b/rxjava-core/src/test/java/rx/subscriptions/SubscriptionsTest.java new file mode 100644 index 0000000000..17bb5b4619 --- /dev/null +++ b/rxjava-core/src/test/java/rx/subscriptions/SubscriptionsTest.java @@ -0,0 +1,7 @@ +package rx.subscriptions; + +import org.junit.Ignore; + +@Ignore("WIP") +public class SubscriptionsTest { +} diff --git a/rxjava-core/src/test/java/rx/util/RangeTest.java b/rxjava-core/src/test/java/rx/util/RangeTest.java new file mode 100644 index 0000000000..640678b5c3 --- /dev/null +++ b/rxjava-core/src/test/java/rx/util/RangeTest.java @@ -0,0 +1,7 @@ +package rx.util; + +import org.junit.Ignore; + +@Ignore("WIP") +public class RangeTest { +} From cc7958d90f40090cd2f57038f7de95a3d4be69c5 Mon Sep 17 00:00:00 2001 From: Pedro Viegas Date: Mon, 4 Nov 2013 12:10:47 +0530 Subject: [PATCH 2/6] moving tests to test source folder #439 --- rxjava-core/src/main/java/rx/Scheduler.java | 59 +- .../concurrency/CurrentThreadScheduler.java | 136 +-- .../rx/concurrency/ImmediateScheduler.java | 103 +-- .../rx/observables/BlockingObservable.java | 258 +----- .../main/java/rx/operators/OperationAll.java | 83 +- .../main/java/rx/operators/OperationAny.java | 183 +--- .../java/rx/operators/OperationAverage.java | 100 --- .../java/rx/operators/OperationBuffer.java | 344 +------ .../java/rx/operators/OperationCache.java | 70 +- .../main/java/rx/operators/OperationCast.java | 41 - .../rx/operators/OperationCombineLatest.java | 631 +------------ .../java/rx/operators/OperationConcat.java | 547 +---------- .../java/rx/operators/OperationDebounce.java | 146 +-- .../rx/operators/OperationDefaultIfEmpty.java | 44 - .../java/rx/operators/OperationDefer.java | 43 - .../rx/operators/OperationDematerialize.java | 53 -- .../java/rx/operators/OperationDistinct.java | 182 +--- .../OperationDistinctUntilChanged.java | 181 +--- .../java/rx/operators/OperationElementAt.java | 114 +-- .../java/rx/operators/OperationFilter.java | 30 - .../java/rx/operators/OperationFinally.java | 32 - .../rx/operators/OperationFirstOrDefault.java | 79 +- .../java/rx/operators/OperationGroupBy.java | 331 +------ .../java/rx/operators/OperationInterval.java | 174 +--- .../main/java/rx/operators/OperationMap.java | 273 ------ .../rx/operators/OperationMaterialize.java | 144 --- .../java/rx/operators/OperationMerge.java | 456 +--------- .../operators/OperationMergeDelayError.java | 500 +---------- .../rx/operators/OperationMostRecent.java | 61 +- .../java/rx/operators/OperationMulticast.java | 93 -- .../main/java/rx/operators/OperationNext.java | 298 +----- .../java/rx/operators/OperationObserveOn.java | 68 -- ...OperationOnErrorResumeNextViaFunction.java | 165 +--- ...erationOnErrorResumeNextViaObservable.java | 127 +-- .../rx/operators/OperationOnErrorReturn.java | 128 +-- ...ionOnExceptionResumeNextViaObservable.java | 224 +---- .../java/rx/operators/OperationParallel.java | 44 +- .../java/rx/operators/OperationRetry.java | 110 +-- .../java/rx/operators/OperationSample.java | 92 +- .../main/java/rx/operators/OperationScan.java | 95 -- .../main/java/rx/operators/OperationSkip.java | 44 +- .../java/rx/operators/OperationSkipLast.java | 106 +-- .../java/rx/operators/OperationSkipWhile.java | 101 +-- .../rx/operators/OperationSubscribeOn.java | 32 - .../main/java/rx/operators/OperationSum.java | 104 --- .../java/rx/operators/OperationSwitch.java | 368 -------- .../rx/operators/OperationSynchronize.java | 199 ---- .../main/java/rx/operators/OperationTake.java | 225 +---- .../java/rx/operators/OperationTakeLast.java | 107 +-- .../java/rx/operators/OperationTakeUntil.java | 160 ---- .../java/rx/operators/OperationTakeWhile.java | 216 +---- .../rx/operators/OperationThrottleFirst.java | 116 +-- .../rx/operators/OperationTimeInterval.java | 57 -- .../OperationToObservableFuture.java | 49 +- .../OperationToObservableIterable.java | 26 - .../operators/OperationToObservableList.java | 55 +- .../OperationToObservableSortedList.java | 54 +- .../java/rx/operators/OperationWindow.java | 308 +------ .../main/java/rx/operators/OperationZip.java | 596 +----------- .../java/rx/operators/OperatorTester.java | 97 -- .../operators/SafeObservableSubscription.java | 17 +- .../rx/operators/SynchronizedObserver.java | 756 ---------------- .../main/java/rx/plugins/RxJavaPlugins.java | 79 +- .../main/java/rx/subjects/AsyncSubject.java | 145 +-- .../java/rx/subjects/BehaviorSubject.java | 146 +-- .../main/java/rx/subjects/PublishSubject.java | 377 +------- .../main/java/rx/subjects/ReplaySubject.java | 184 +--- .../subscriptions/CompositeSubscription.java | 70 +- .../java/rx/subscriptions/Subscriptions.java | 21 +- rxjava-core/src/main/java/rx/util/Range.java | 49 - .../src/test/java/rx/SchedulersTest.java | 850 +++++++++--------- .../CurrentThreadSchedulerTest.java | 126 ++- .../concurrency/ImmediateSchedulerTest.java | 56 +- .../observables/BlockingObservableTest.java | 245 ++++- .../java/rx/operators/OperationAllTest.java | 81 +- .../java/rx/operators/OperationAnyTest.java | 179 +++- .../rx/operators/OperationAverageTest.java | 108 ++- .../rx/operators/OperationBufferTest.java | 347 ++++++- .../java/rx/operators/OperationCacheTest.java | 69 +- .../java/rx/operators/OperationCastTest.java | 37 +- .../operators/OperationCombineLatestTest.java | 616 ++++++++++++- .../rx/operators/OperationConcatTest.java | 541 ++++++++++- .../rx/operators/OperationDebounceTest.java | 143 ++- .../OperationDefaultIfEmptyTest.java | 41 +- .../java/rx/operators/OperationDeferTest.java | 44 +- .../operators/OperationDematerializeTest.java | 55 +- .../rx/operators/OperationDistinctTest.java | 179 +++- .../OperationDistinctUntilChangedTest.java | 182 +++- .../rx/operators/OperationElementAtTest.java | 110 ++- .../rx/operators/OperationFilterTest.java | 32 +- .../rx/operators/OperationFinallyTest.java | 35 +- .../OperationFirstOrDefaultTest.java | 75 +- .../rx/operators/OperationGroupByTest.java | 328 ++++++- .../rx/operators/OperationIntervalTest.java | 173 +++- .../java/rx/operators/OperationMapTest.java | 273 +++++- .../operators/OperationMaterializeTest.java | 147 ++- .../OperationMergeDelayErrorTest.java | 497 +++++++++- .../java/rx/operators/OperationMergeTest.java | 455 +++++++++- .../rx/operators/OperationMostRecentTest.java | 56 +- .../rx/operators/OperationMulticastTest.java | 94 +- .../java/rx/operators/OperationNextTest.java | 278 +++++- .../rx/operators/OperationObserveOnTest.java | 65 +- ...ationOnErrorResumeNextViaFunctionTest.java | 165 +++- ...ionOnErrorResumeNextViaObservableTest.java | 124 ++- .../operators/OperationOnErrorReturnTest.java | 127 ++- ...nExceptionResumeNextViaObservableTest.java | 221 ++++- .../rx/operators/OperationParallelTest.java | 42 +- .../java/rx/operators/OperationRetryTest.java | 111 ++- .../rx/operators/OperationSampleTest.java | 88 +- .../java/rx/operators/OperationScanTest.java | 99 +- .../rx/operators/OperationSkipLastTest.java | 95 +- .../java/rx/operators/OperationSkipTest.java | 39 +- .../rx/operators/OperationSkipWhileTest.java | 101 ++- .../operators/OperationSubscribeOnTest.java | 37 +- .../java/rx/operators/OperationSumTest.java | 110 ++- .../rx/operators/OperationSwitchTest.java | 365 +++++++- .../operators/OperationSynchronizeTest.java | 200 ++++- .../rx/operators/OperationTakeLastTest.java | 94 +- .../java/rx/operators/OperationTakeTest.java | 210 ++++- .../rx/operators/OperationTakeUntilTest.java | 161 +++- .../rx/operators/OperationTakeWhileTest.java | 204 +++++ .../operators/OperationThrottleFirstTest.java | 111 ++- .../operators/OperationTimeIntervalTest.java | 60 ++ .../OperationToObservableFutureTest.java | 44 +- .../OperationToObservableIterableTest.java | 27 +- .../OperationToObservableListTest.java | 50 +- .../OperationToObservableSortedListTest.java | 47 +- .../rx/operators/OperationWindowTest.java | 312 ++++++- .../java/rx/operators/OperationZipTest.java | 579 +++++++++++- .../SafeObservableSubscriptionTest.java | 16 +- .../operators/SynchronizedObserverTest.java | 748 ++++++++++++++- .../java/rx/plugins/RxJavaPluginsTest.java | 74 +- .../java/rx/subjects/AsyncSubjectTest.java | 132 ++- .../java/rx/subjects/BehaviorSubjectTest.java | 132 ++- .../java/rx/subjects/PublishSubjectTest.java | 361 +++++++- .../java/rx/subjects/ReplaySubjectTest.java | 166 +++- .../CompositeSubscriptionTest.java | 67 +- .../rx/subscriptions/SubscriptionsTest.java | 17 +- .../src/test/java/rx/test/OperatorTester.java | 94 ++ .../src/test/java/rx/util/RangeTest.java | 47 +- 140 files changed, 11833 insertions(+), 12067 deletions(-) delete mode 100644 rxjava-core/src/main/java/rx/operators/OperatorTester.java create mode 100644 rxjava-core/src/test/java/rx/operators/OperationTakeWhileTest.java create mode 100644 rxjava-core/src/test/java/rx/operators/OperationTimeIntervalTest.java create mode 100644 rxjava-core/src/test/java/rx/test/OperatorTester.java diff --git a/rxjava-core/src/main/java/rx/Scheduler.java b/rxjava-core/src/main/java/rx/Scheduler.java index cb3430c1f3..3da38f41f2 100644 --- a/rxjava-core/src/main/java/rx/Scheduler.java +++ b/rxjava-core/src/main/java/rx/Scheduler.java @@ -15,26 +15,17 @@ */ package rx; -import static org.mockito.Matchers.*; -import static org.mockito.Mockito.*; - -import java.util.Date; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicBoolean; - -import org.junit.Test; -import org.mockito.InOrder; -import org.mockito.Mockito; - -import rx.concurrency.TestScheduler; import rx.subscriptions.CompositeSubscription; import rx.subscriptions.MultipleAssignmentSubscription; import rx.subscriptions.Subscriptions; import rx.util.functions.Action0; import rx.util.functions.Action1; -import rx.util.functions.Func1; import rx.util.functions.Func2; +import java.util.Date; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicBoolean; + /** * Represents an object that schedules units of work. *

@@ -264,46 +255,4 @@ public long now() { public int degreeOfParallelism() { return Runtime.getRuntime().availableProcessors(); } - - public static class UnitTest { - @SuppressWarnings("unchecked") - // mocking is unchecked, unfortunately - @Test - public void testPeriodicScheduling() { - final Func1 calledOp = mock(Func1.class); - - final TestScheduler scheduler = new TestScheduler(); - Subscription subscription = scheduler.schedulePeriodically(new Action0() { - @Override - public void call() { - System.out.println(scheduler.now()); - calledOp.call(scheduler.now()); - } - }, 1, 2, TimeUnit.SECONDS); - - verify(calledOp, never()).call(anyLong()); - - InOrder inOrder = Mockito.inOrder(calledOp); - - scheduler.advanceTimeBy(999L, TimeUnit.MILLISECONDS); - inOrder.verify(calledOp, never()).call(anyLong()); - - scheduler.advanceTimeBy(1L, TimeUnit.MILLISECONDS); - inOrder.verify(calledOp, times(1)).call(1000L); - - scheduler.advanceTimeBy(1999L, TimeUnit.MILLISECONDS); - inOrder.verify(calledOp, never()).call(3000L); - - scheduler.advanceTimeBy(1L, TimeUnit.MILLISECONDS); - inOrder.verify(calledOp, times(1)).call(3000L); - - scheduler.advanceTimeBy(5L, TimeUnit.SECONDS); - inOrder.verify(calledOp, times(1)).call(5000L); - inOrder.verify(calledOp, times(1)).call(7000L); - - subscription.unsubscribe(); - scheduler.advanceTimeBy(11L, TimeUnit.SECONDS); - inOrder.verify(calledOp, never()).call(anyLong()); - } - } } diff --git a/rxjava-core/src/main/java/rx/concurrency/CurrentThreadScheduler.java b/rxjava-core/src/main/java/rx/concurrency/CurrentThreadScheduler.java index 455b49d04c..a096ef06e2 100644 --- a/rxjava-core/src/main/java/rx/concurrency/CurrentThreadScheduler.java +++ b/rxjava-core/src/main/java/rx/concurrency/CurrentThreadScheduler.java @@ -15,20 +15,14 @@ */ package rx.concurrency; -import static org.mockito.Mockito.*; +import rx.Scheduler; +import rx.Subscription; +import rx.util.functions.Func2; import java.util.PriorityQueue; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; -import org.junit.Test; -import org.mockito.InOrder; - -import rx.Scheduler; -import rx.Subscription; -import rx.util.functions.Action0; -import rx.util.functions.Func2; - /** * Schedules work on the current thread but does not execute immediately. Work is put in a queue and executed after the current unit of work is completed. */ @@ -41,7 +35,7 @@ public static CurrentThreadScheduler getInstance() { private static final ThreadLocal> QUEUE = new ThreadLocal>(); - private CurrentThreadScheduler() { + CurrentThreadScheduler() { } private final AtomicInteger counter = new AtomicInteger(0); @@ -102,126 +96,4 @@ public int compareTo(TimedAction that) { return result; } } - - public static class UnitTest { - - @Test - public void testNestedActions() { - final CurrentThreadScheduler scheduler = new CurrentThreadScheduler(); - - final Action0 firstStepStart = mock(Action0.class); - final Action0 firstStepEnd = mock(Action0.class); - - final Action0 secondStepStart = mock(Action0.class); - final Action0 secondStepEnd = mock(Action0.class); - - final Action0 thirdStepStart = mock(Action0.class); - final Action0 thirdStepEnd = mock(Action0.class); - - final Action0 firstAction = new Action0() { - @Override - public void call() { - firstStepStart.call(); - firstStepEnd.call(); - } - }; - final Action0 secondAction = new Action0() { - @Override - public void call() { - secondStepStart.call(); - scheduler.schedule(firstAction); - secondStepEnd.call(); - - } - }; - final Action0 thirdAction = new Action0() { - @Override - public void call() { - thirdStepStart.call(); - scheduler.schedule(secondAction); - thirdStepEnd.call(); - } - }; - - InOrder inOrder = inOrder(firstStepStart, firstStepEnd, secondStepStart, secondStepEnd, thirdStepStart, thirdStepEnd); - - scheduler.schedule(thirdAction); - - inOrder.verify(thirdStepStart, times(1)).call(); - inOrder.verify(thirdStepEnd, times(1)).call(); - inOrder.verify(secondStepStart, times(1)).call(); - inOrder.verify(secondStepEnd, times(1)).call(); - inOrder.verify(firstStepStart, times(1)).call(); - inOrder.verify(firstStepEnd, times(1)).call(); - } - - @Test - public void testSequenceOfActions() { - final CurrentThreadScheduler scheduler = new CurrentThreadScheduler(); - - final Action0 first = mock(Action0.class); - final Action0 second = mock(Action0.class); - - scheduler.schedule(first); - scheduler.schedule(second); - - verify(first, times(1)).call(); - verify(second, times(1)).call(); - - } - - @Test - public void testSequenceOfDelayedActions() { - final CurrentThreadScheduler scheduler = new CurrentThreadScheduler(); - - final Action0 first = mock(Action0.class); - final Action0 second = mock(Action0.class); - - scheduler.schedule(new Action0() { - @Override - public void call() { - scheduler.schedule(first, 30, TimeUnit.MILLISECONDS); - scheduler.schedule(second, 10, TimeUnit.MILLISECONDS); - } - }); - - InOrder inOrder = inOrder(first, second); - - inOrder.verify(second, times(1)).call(); - inOrder.verify(first, times(1)).call(); - - - } - - @Test - public void testMixOfDelayedAndNonDelayedActions() { - final CurrentThreadScheduler scheduler = new CurrentThreadScheduler(); - - final Action0 first = mock(Action0.class); - final Action0 second = mock(Action0.class); - final Action0 third = mock(Action0.class); - final Action0 fourth = mock(Action0.class); - - scheduler.schedule(new Action0() { - @Override - public void call() { - scheduler.schedule(first); - scheduler.schedule(second, 300, TimeUnit.MILLISECONDS); - scheduler.schedule(third, 100, TimeUnit.MILLISECONDS); - scheduler.schedule(fourth); - } - }); - - InOrder inOrder = inOrder(first, second, third, fourth); - - inOrder.verify(first, times(1)).call(); - inOrder.verify(fourth, times(1)).call(); - inOrder.verify(third, times(1)).call(); - inOrder.verify(second, times(1)).call(); - - - } - - } - } diff --git a/rxjava-core/src/main/java/rx/concurrency/ImmediateScheduler.java b/rxjava-core/src/main/java/rx/concurrency/ImmediateScheduler.java index f3f4353bb7..d1d00355f4 100644 --- a/rxjava-core/src/main/java/rx/concurrency/ImmediateScheduler.java +++ b/rxjava-core/src/main/java/rx/concurrency/ImmediateScheduler.java @@ -1,12 +1,12 @@ /** * Copyright 2013 Netflix, Inc. - * + * * 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. @@ -15,96 +15,35 @@ */ package rx.concurrency; -import static org.mockito.Mockito.*; - -import java.util.concurrent.TimeUnit; - -import org.junit.Test; -import org.mockito.InOrder; - import rx.Scheduler; import rx.Subscription; -import rx.util.functions.Action0; import rx.util.functions.Func2; +import java.util.concurrent.TimeUnit; + /** * Executes work immediately on the current thread. */ public final class ImmediateScheduler extends Scheduler { - private static final ImmediateScheduler INSTANCE = new ImmediateScheduler(); - - public static ImmediateScheduler getInstance() { - return INSTANCE; - } - - private ImmediateScheduler() { - } - - @Override - public Subscription schedule(T state, Func2 action) { - return action.call(this, state); - } - - @Override - public Subscription schedule(T state, Func2 action, long dueTime, TimeUnit unit) { - // since we are executing immediately on this thread we must cause this thread to sleep - long execTime = now() + unit.toMillis(dueTime); - - return schedule(state, new SleepingAction(action, this, execTime)); - } - - public static class UnitTest { - - @Test - public void testNestedActions() { - final ImmediateScheduler scheduler = new ImmediateScheduler(); - - final Action0 firstStepStart = mock(Action0.class); - final Action0 firstStepEnd = mock(Action0.class); - - final Action0 secondStepStart = mock(Action0.class); - final Action0 secondStepEnd = mock(Action0.class); - - final Action0 thirdStepStart = mock(Action0.class); - final Action0 thirdStepEnd = mock(Action0.class); - - final Action0 firstAction = new Action0() { - @Override - public void call() { - firstStepStart.call(); - firstStepEnd.call(); - } - }; - final Action0 secondAction = new Action0() { - @Override - public void call() { - secondStepStart.call(); - scheduler.schedule(firstAction); - secondStepEnd.call(); - - } - }; - final Action0 thirdAction = new Action0() { - @Override - public void call() { - thirdStepStart.call(); - scheduler.schedule(secondAction); - thirdStepEnd.call(); - } - }; + private static final ImmediateScheduler INSTANCE = new ImmediateScheduler(); - InOrder inOrder = inOrder(firstStepStart, firstStepEnd, secondStepStart, secondStepEnd, thirdStepStart, thirdStepEnd); + public static ImmediateScheduler getInstance() { + return INSTANCE; + } - scheduler.schedule(thirdAction); + ImmediateScheduler() { + } - inOrder.verify(thirdStepStart, times(1)).call(); - inOrder.verify(secondStepStart, times(1)).call(); - inOrder.verify(firstStepStart, times(1)).call(); - inOrder.verify(firstStepEnd, times(1)).call(); - inOrder.verify(secondStepEnd, times(1)).call(); - inOrder.verify(thirdStepEnd, times(1)).call(); - } + @Override + public Subscription schedule(T state, Func2 action) { + return action.call(this, state); + } - } + @Override + public Subscription schedule(T state, Func2 action, long dueTime, TimeUnit unit) { + // since we are executing immediately on this thread we must cause this thread to sleep + long execTime = now() + unit.toMillis(dueTime); + return schedule(state, new SleepingAction(action, this, execTime)); + } } diff --git a/rxjava-core/src/main/java/rx/observables/BlockingObservable.java b/rxjava-core/src/main/java/rx/observables/BlockingObservable.java index 32e2db7400..b59f34d78c 100644 --- a/rxjava-core/src/main/java/rx/observables/BlockingObservable.java +++ b/rxjava-core/src/main/java/rx/observables/BlockingObservable.java @@ -15,33 +15,18 @@ */ package rx.observables; -import static org.junit.Assert.*; - -import java.util.Iterator; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.Future; -import java.util.concurrent.atomic.AtomicReference; - -import org.junit.Before; -import org.junit.Test; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; - import rx.Observable; -import rx.Observable.OnSubscribeFunc; import rx.Observer; import rx.Subscription; -import rx.operators.OperationMostRecent; -import rx.operators.OperationNext; -import rx.operators.OperationToFuture; -import rx.operators.OperationToIterator; -import rx.operators.SafeObservableSubscription; -import rx.operators.SafeObserver; -import rx.subscriptions.BooleanSubscription; -import rx.subscriptions.Subscriptions; +import rx.operators.*; import rx.util.functions.Action1; import rx.util.functions.Func1; +import java.util.Iterator; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.Future; +import java.util.concurrent.atomic.AtomicReference; + /** * An extension of {@link Observable} that provides blocking operators. *

@@ -367,235 +352,4 @@ public Iterator iterator() { } }; } - - public static class UnitTest { - - @Mock - Observer w; - - @Before - public void before() { - MockitoAnnotations.initMocks(this); - } - - @Test - public void testLast() { - BlockingObservable obs = BlockingObservable.from(Observable.from("one", "two", "three")); - - assertEquals("three", obs.last()); - } - - @Test - public void testLastEmptyObservable() { - BlockingObservable obs = BlockingObservable.from(Observable.empty()); - - assertNull(obs.last()); - } - - @Test - public void testLastOrDefault() { - BlockingObservable observable = BlockingObservable.from(Observable.from(1, 0, -1)); - int last = observable.lastOrDefault(-100, new Func1() { - @Override - public Boolean call(Integer args) { - return args >= 0; - } - }); - assertEquals(0, last); - } - - @Test - public void testLastOrDefault1() { - BlockingObservable observable = BlockingObservable.from(Observable.from("one", "two", "three")); - assertEquals("three", observable.lastOrDefault("default")); - } - - @Test - public void testLastOrDefault2() { - BlockingObservable observable = BlockingObservable.from(Observable.empty()); - assertEquals("default", observable.lastOrDefault("default")); - } - - @Test - public void testLastOrDefaultWithPredicate() { - BlockingObservable observable = BlockingObservable.from(Observable.from(1, 0, -1)); - int last = observable.lastOrDefault(0, new Func1() { - @Override - public Boolean call(Integer args) { - return args < 0; - } - }); - - assertEquals(-1, last); - } - - @Test - public void testLastOrDefaultWrongPredicate() { - BlockingObservable observable = BlockingObservable.from(Observable.from(-1, -2, -3)); - int last = observable.lastOrDefault(0, new Func1() { - @Override - public Boolean call(Integer args) { - return args >= 0; - } - }); - assertEquals(0, last); - } - - @Test - public void testLastWithPredicate() { - BlockingObservable obs = BlockingObservable.from(Observable.from("one", "two", "three")); - - assertEquals("two", obs.last(new Func1() { - @Override - public Boolean call(String s) { - return s.length() == 3; - } - })); - } - - public void testSingle() { - BlockingObservable observable = BlockingObservable.from(Observable.from("one")); - assertEquals("one", observable.single()); - } - - @Test - public void testSingleDefault() { - BlockingObservable observable = BlockingObservable.from(Observable.empty()); - assertEquals("default", observable.singleOrDefault("default")); - } - - @Test(expected = IllegalStateException.class) - public void testSingleDefaultPredicateMatchesMoreThanOne() { - BlockingObservable.from(Observable.from("one", "two")).singleOrDefault("default", new Func1() { - @Override - public Boolean call(String args) { - return args.length() == 3; - } - }); - } - - @Test - public void testSingleDefaultPredicateMatchesNothing() { - BlockingObservable observable = BlockingObservable.from(Observable.from("one", "two")); - String result = observable.singleOrDefault("default", new Func1() { - @Override - public Boolean call(String args) { - return args.length() == 4; - } - }); - assertEquals("default", result); - } - - @Test(expected = IllegalStateException.class) - public void testSingleDefaultWithMoreThanOne() { - BlockingObservable observable = BlockingObservable.from(Observable.from("one", "two", "three")); - observable.singleOrDefault("default"); - } - - @Test - public void testSingleWithPredicateDefault() { - BlockingObservable observable = BlockingObservable.from(Observable.from("one", "two", "four")); - assertEquals("four", observable.single(new Func1() { - @Override - public Boolean call(String s) { - return s.length() == 4; - } - })); - } - - @Test(expected = IllegalStateException.class) - public void testSingleWrong() { - BlockingObservable observable = BlockingObservable.from(Observable.from(1, 2)); - observable.single(); - } - - @Test(expected = IllegalStateException.class) - public void testSingleWrongPredicate() { - BlockingObservable observable = BlockingObservable.from(Observable.from(-1)); - observable.single(new Func1() { - @Override - public Boolean call(Integer args) { - return args > 0; - } - }); - } - - @Test - public void testToIterable() { - BlockingObservable obs = BlockingObservable.from(Observable.from("one", "two", "three")); - - Iterator it = obs.toIterable().iterator(); - - assertEquals(true, it.hasNext()); - assertEquals("one", it.next()); - - assertEquals(true, it.hasNext()); - assertEquals("two", it.next()); - - assertEquals(true, it.hasNext()); - assertEquals("three", it.next()); - - assertEquals(false, it.hasNext()); - - } - - @Test(expected = TestException.class) - public void testToIterableWithException() { - BlockingObservable obs = BlockingObservable.from(Observable.create(new OnSubscribeFunc() { - - @Override - public Subscription onSubscribe(Observer observer) { - observer.onNext("one"); - observer.onError(new TestException()); - return Subscriptions.empty(); - } - })); - - Iterator it = obs.toIterable().iterator(); - - assertEquals(true, it.hasNext()); - assertEquals("one", it.next()); - - assertEquals(true, it.hasNext()); - it.next(); - - } - - @Test - public void testForEachWithError() { - try { - BlockingObservable.from(Observable.create(new OnSubscribeFunc() { - - @Override - public Subscription onSubscribe(final Observer observer) { - final BooleanSubscription subscription = new BooleanSubscription(); - new Thread(new Runnable() { - - @Override - public void run() { - observer.onNext("one"); - observer.onNext("two"); - observer.onNext("three"); - observer.onCompleted(); - } - }).start(); - return subscription; - } - })).forEach(new Action1() { - - @Override - public void call(String t1) { - throw new RuntimeException("fail"); - } - }); - fail("we expect an exception to be thrown"); - } catch (Throwable e) { - // do nothing as we expect this - } - } - - private static class TestException extends RuntimeException { - private static final long serialVersionUID = 1L; - } - } } diff --git a/rxjava-core/src/main/java/rx/operators/OperationAll.java b/rxjava-core/src/main/java/rx/operators/OperationAll.java index e0a18154c0..908fd1f54e 100644 --- a/rxjava-core/src/main/java/rx/operators/OperationAll.java +++ b/rxjava-core/src/main/java/rx/operators/OperationAll.java @@ -15,18 +15,14 @@ */ package rx.operators; -import static org.mockito.Mockito.*; - -import java.util.concurrent.atomic.AtomicBoolean; - -import org.junit.Test; - import rx.Observable; import rx.Observable.OnSubscribeFunc; import rx.Observer; import rx.Subscription; import rx.util.functions.Func1; +import java.util.concurrent.atomic.AtomicBoolean; + /** * Returns an Observable that emits a Boolean that indicates whether all items emitted by an * Observable satisfy a condition. @@ -94,79 +90,4 @@ public void onNext(T args) { } } - - public static class UnitTest { - - @Test - @SuppressWarnings("unchecked") - public void testAll() { - Observable obs = Observable.from("one", "two", "six"); - - Observer observer = mock(Observer.class); - Observable.create(all(obs, new Func1() { - @Override - public Boolean call(String s) { - return s.length() == 3; - } - })).subscribe(observer); - - verify(observer).onNext(true); - verify(observer).onCompleted(); - verifyNoMoreInteractions(observer); - } - - @Test - @SuppressWarnings("unchecked") - public void testNotAll() { - Observable obs = Observable.from("one", "two", "three", "six"); - - Observer observer = mock(Observer.class); - Observable.create(all(obs, new Func1() { - @Override - public Boolean call(String s) { - return s.length() == 3; - } - })).subscribe(observer); - - verify(observer).onNext(false); - verify(observer).onCompleted(); - verifyNoMoreInteractions(observer); - } - - @Test - @SuppressWarnings("unchecked") - public void testEmpty() { - Observable obs = Observable.empty(); - - Observer observer = mock(Observer.class); - Observable.create(all(obs, new Func1() { - @Override - public Boolean call(String s) { - return s.length() == 3; - } - })).subscribe(observer); - - verify(observer).onNext(true); - verify(observer).onCompleted(); - verifyNoMoreInteractions(observer); - } - - @Test - @SuppressWarnings("unchecked") - public void testError() { - Throwable error = new Throwable(); - Observable obs = Observable.error(error); - - Observer observer = mock(Observer.class); - Observable.create(all(obs, new Func1() { - @Override - public Boolean call(String s) { - return s.length() == 3; - } - })).subscribe(observer); - - verify(observer).onError(error); - verifyNoMoreInteractions(observer); - } - } } diff --git a/rxjava-core/src/main/java/rx/operators/OperationAny.java b/rxjava-core/src/main/java/rx/operators/OperationAny.java index a5f12c224f..5830fbb1f2 100644 --- a/rxjava-core/src/main/java/rx/operators/OperationAny.java +++ b/rxjava-core/src/main/java/rx/operators/OperationAny.java @@ -15,19 +15,16 @@ */ package rx.operators; -import static org.mockito.Mockito.*; -import static rx.util.functions.Functions.*; - -import java.util.concurrent.atomic.AtomicBoolean; - -import org.junit.Test; - import rx.Observable; import rx.Observable.OnSubscribeFunc; import rx.Observer; import rx.Subscription; import rx.util.functions.Func1; +import java.util.concurrent.atomic.AtomicBoolean; + +import static rx.util.functions.Functions.alwaysTrue; + /** * Returns an {@link Observable} that emits true if any element of * an observable sequence satisfies a condition, otherwise false. @@ -126,176 +123,4 @@ public void onCompleted() { } } - - public static class UnitTest { - - @Test - public void testAnyWithTwoItems() { - Observable w = Observable.from(1, 2); - Observable observable = Observable.create(any(w)); - - @SuppressWarnings("unchecked") - Observer aObserver = mock(Observer.class); - observable.subscribe(aObserver); - verify(aObserver, never()).onNext(false); - verify(aObserver, times(1)).onNext(true); - verify(aObserver, never()).onError(org.mockito.Matchers.any(Throwable.class)); - verify(aObserver, times(1)).onCompleted(); - } - - @Test - public void testIsEmptyWithTwoItems() { - Observable w = Observable.from(1, 2); - Observable observable = Observable.create(isEmpty(w)); - - @SuppressWarnings("unchecked") - Observer aObserver = mock(Observer.class); - observable.subscribe(aObserver); - verify(aObserver, never()).onNext(true); - verify(aObserver, times(1)).onNext(false); - verify(aObserver, never()).onError(org.mockito.Matchers.any(Throwable.class)); - verify(aObserver, times(1)).onCompleted(); - } - - @Test - public void testAnyWithOneItem() { - Observable w = Observable.from(1); - Observable observable = Observable.create(any(w)); - - @SuppressWarnings("unchecked") - Observer aObserver = mock(Observer.class); - observable.subscribe(aObserver); - verify(aObserver, never()).onNext(false); - verify(aObserver, times(1)).onNext(true); - verify(aObserver, never()).onError(org.mockito.Matchers.any(Throwable.class)); - verify(aObserver, times(1)).onCompleted(); - } - - @Test - public void testIsEmptyWithOneItem() { - Observable w = Observable.from(1); - Observable observable = Observable.create(isEmpty(w)); - - @SuppressWarnings("unchecked") - Observer aObserver = mock(Observer.class); - observable.subscribe(aObserver); - verify(aObserver, never()).onNext(true); - verify(aObserver, times(1)).onNext(false); - verify(aObserver, never()).onError(org.mockito.Matchers.any(Throwable.class)); - verify(aObserver, times(1)).onCompleted(); - } - - @Test - public void testAnyWithEmpty() { - Observable w = Observable.empty(); - Observable observable = Observable.create(any(w)); - - @SuppressWarnings("unchecked") - Observer aObserver = mock(Observer.class); - observable.subscribe(aObserver); - verify(aObserver, times(1)).onNext(false); - verify(aObserver, never()).onNext(true); - verify(aObserver, never()).onError(org.mockito.Matchers.any(Throwable.class)); - verify(aObserver, times(1)).onCompleted(); - } - - @Test - public void testIsEmptyWithEmpty() { - Observable w = Observable.empty(); - Observable observable = Observable.create(isEmpty(w)); - - @SuppressWarnings("unchecked") - Observer aObserver = mock(Observer.class); - observable.subscribe(aObserver); - verify(aObserver, times(1)).onNext(true); - verify(aObserver, never()).onNext(false); - verify(aObserver, never()).onError(org.mockito.Matchers.any(Throwable.class)); - verify(aObserver, times(1)).onCompleted(); - } - - @Test - public void testAnyWithPredicate1() { - Observable w = Observable.from(1, 2, 3); - Observable observable = Observable.create(any(w, - new Func1() { - - @Override - public Boolean call(Integer t1) { - return t1 < 2; - } - })); - - @SuppressWarnings("unchecked") - Observer aObserver = mock(Observer.class); - observable.subscribe(aObserver); - verify(aObserver, never()).onNext(false); - verify(aObserver, times(1)).onNext(true); - verify(aObserver, never()).onError(org.mockito.Matchers.any(Throwable.class)); - verify(aObserver, times(1)).onCompleted(); - } - - @Test - public void testExists1() { - Observable w = Observable.from(1, 2, 3); - Observable observable = Observable.create(exists(w, - new Func1() { - - @Override - public Boolean call(Integer t1) { - return t1 < 2; - } - })); - - @SuppressWarnings("unchecked") - Observer aObserver = mock(Observer.class); - observable.subscribe(aObserver); - verify(aObserver, never()).onNext(false); - verify(aObserver, times(1)).onNext(true); - verify(aObserver, never()).onError(org.mockito.Matchers.any(Throwable.class)); - verify(aObserver, times(1)).onCompleted(); - } - - @Test - public void testAnyWithPredicate2() { - Observable w = Observable.from(1, 2, 3); - Observable observable = Observable.create(any(w, - new Func1() { - - @Override - public Boolean call(Integer t1) { - return t1 < 1; - } - })); - - @SuppressWarnings("unchecked") - Observer aObserver = mock(Observer.class); - observable.subscribe(aObserver); - verify(aObserver, times(1)).onNext(false); - verify(aObserver, never()).onNext(true); - verify(aObserver, never()).onError(org.mockito.Matchers.any(Throwable.class)); - verify(aObserver, times(1)).onCompleted(); - } - - @Test - public void testAnyWithEmptyAndPredicate() { - // If the source is empty, always output false. - Observable w = Observable.empty(); - Observable observable = Observable.create(any(w, - new Func1() { - - @Override - public Boolean call(Integer t1) { - return true; - } - })); - - @SuppressWarnings("unchecked") - Observer aObserver = mock(Observer.class); - observable.subscribe(aObserver); - verify(aObserver, times(1)).onNext(false); - verify(aObserver, never()).onNext(true); - verify(aObserver, never()).onError(org.mockito.Matchers.any(Throwable.class)); - verify(aObserver, times(1)).onCompleted(); - } - } } diff --git a/rxjava-core/src/main/java/rx/operators/OperationAverage.java b/rxjava-core/src/main/java/rx/operators/OperationAverage.java index 054a117053..c130396f2a 100644 --- a/rxjava-core/src/main/java/rx/operators/OperationAverage.java +++ b/rxjava-core/src/main/java/rx/operators/OperationAverage.java @@ -15,12 +15,7 @@ */ package rx.operators; -import static org.mockito.Mockito.*; - -import org.junit.Test; - import rx.Observable; -import rx.Observer; import rx.util.functions.Func1; import rx.util.functions.Func2; @@ -100,99 +95,4 @@ public Double call(Tuple2 result) { } }); } - - public static class UnitTest { - @SuppressWarnings("unchecked") - Observer w = mock(Observer.class); - @SuppressWarnings("unchecked") - Observer wl = mock(Observer.class); - @SuppressWarnings("unchecked") - Observer wf = mock(Observer.class); - @SuppressWarnings("unchecked") - Observer wd = mock(Observer.class); - - @Test - public void testAverageOfAFewInts() throws Throwable { - Observable src = Observable.from(1, 2, 3, 4, 6); - average(src).subscribe(w); - - verify(w, times(1)).onNext(anyInt()); - verify(w).onNext(3); - verify(w, never()).onError(any(Throwable.class)); - verify(w, times(1)).onCompleted(); - } - - @Test - public void testEmptyAverage() throws Throwable { - Observable src = Observable.empty(); - average(src).subscribe(w); - - verify(w, never()).onNext(anyInt()); - verify(w, times(1)).onError(any(ArithmeticException.class)); - verify(w, never()).onCompleted(); - } - - @Test - public void testAverageOfAFewLongs() throws Throwable { - Observable src = Observable.from(1L, 2L, 3L, 4L, 6L); - averageLongs(src).subscribe(wl); - - verify(wl, times(1)).onNext(anyLong()); - verify(wl).onNext(3L); - verify(wl, never()).onError(any(Throwable.class)); - verify(wl, times(1)).onCompleted(); - } - - @Test - public void testEmptyAverageLongs() throws Throwable { - Observable src = Observable.empty(); - averageLongs(src).subscribe(wl); - - verify(wl, never()).onNext(anyLong()); - verify(wl, times(1)).onError(any(ArithmeticException.class)); - verify(wl, never()).onCompleted(); - } - - @Test - public void testAverageOfAFewFloats() throws Throwable { - Observable src = Observable.from(1.0f, 2.0f); - averageFloats(src).subscribe(wf); - - verify(wf, times(1)).onNext(anyFloat()); - verify(wf).onNext(1.5f); - verify(wf, never()).onError(any(Throwable.class)); - verify(wf, times(1)).onCompleted(); - } - - @Test - public void testEmptyAverageFloats() throws Throwable { - Observable src = Observable.empty(); - averageFloats(src).subscribe(wf); - - verify(wf, never()).onNext(anyFloat()); - verify(wf, times(1)).onError(any(ArithmeticException.class)); - verify(wf, never()).onCompleted(); - } - - @Test - public void testAverageOfAFewDoubles() throws Throwable { - Observable src = Observable.from(1.0d, 2.0d); - averageDoubles(src).subscribe(wd); - - verify(wd, times(1)).onNext(anyDouble()); - verify(wd).onNext(1.5d); - verify(wd, never()).onError(any(Throwable.class)); - verify(wd, times(1)).onCompleted(); - } - - @Test - public void testEmptyAverageDoubles() throws Throwable { - Observable src = Observable.empty(); - averageDoubles(src).subscribe(wd); - - verify(wd, never()).onNext(anyDouble()); - verify(wd, times(1)).onError(any(ArithmeticException.class)); - verify(wd, never()).onCompleted(); - } - } } diff --git a/rxjava-core/src/main/java/rx/operators/OperationBuffer.java b/rxjava-core/src/main/java/rx/operators/OperationBuffer.java index 898260d0ef..03d2dc02b8 100644 --- a/rxjava-core/src/main/java/rx/operators/OperationBuffer.java +++ b/rxjava-core/src/main/java/rx/operators/OperationBuffer.java @@ -15,35 +15,20 @@ */ package rx.operators; -import static org.junit.Assert.assertFalse; - -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.TimeUnit; - -import org.junit.Before; -import org.junit.Test; -import org.mockito.InOrder; -import org.mockito.Mockito; - import rx.Observable; import rx.Observable.OnSubscribeFunc; import rx.Observer; import rx.Scheduler; import rx.Subscription; import rx.concurrency.Schedulers; -import rx.concurrency.TestScheduler; -import rx.subscriptions.Subscriptions; import rx.util.Closing; -import rx.util.Closings; import rx.util.Opening; -import rx.util.Openings; -import rx.util.functions.Action0; -import rx.util.functions.Action1; import rx.util.functions.Func0; import rx.util.functions.Func1; +import java.util.List; +import java.util.concurrent.TimeUnit; + public final class OperationBuffer extends ChunkedOperation { private static Func0> bufferMaker() { @@ -372,327 +357,4 @@ public List getContents() { return contents; } } - - public static class UnitTest { - - private Observer> observer; - private TestScheduler scheduler; - - @Before - @SuppressWarnings("unchecked") - public void before() { - observer = Mockito.mock(Observer.class); - scheduler = new TestScheduler(); - } - - @Test - public void testComplete() { - Observable source = Observable.create(new OnSubscribeFunc() { - @Override - public Subscription onSubscribe(Observer observer) { - observer.onCompleted(); - return Subscriptions.empty(); - } - }); - - Observable> buffered = Observable.create(buffer(source, 3, 3)); - buffered.subscribe(observer); - - Mockito.verify(observer, Mockito.never()).onNext(Mockito.anyListOf(String.class)); - Mockito.verify(observer, Mockito.never()).onError(Mockito.any(Throwable.class)); - Mockito.verify(observer, Mockito.times(1)).onCompleted(); - } - - @Test - public void testSkipAndCountOverlappingBuffers() { - Observable source = Observable.create(new OnSubscribeFunc() { - @Override - public Subscription onSubscribe(Observer observer) { - observer.onNext("one"); - observer.onNext("two"); - observer.onNext("three"); - observer.onNext("four"); - observer.onNext("five"); - return Subscriptions.empty(); - } - }); - - Observable> buffered = Observable.create(buffer(source, 3, 1)); - buffered.subscribe(observer); - - InOrder inOrder = Mockito.inOrder(observer); - inOrder.verify(observer, Mockito.times(1)).onNext(list("one", "two", "three")); - inOrder.verify(observer, Mockito.times(1)).onNext(list("two", "three", "four")); - inOrder.verify(observer, Mockito.times(1)).onNext(list("three", "four", "five")); - inOrder.verify(observer, Mockito.never()).onNext(Mockito.anyListOf(String.class)); - inOrder.verify(observer, Mockito.never()).onError(Mockito.any(Throwable.class)); - inOrder.verify(observer, Mockito.never()).onCompleted(); - } - - @Test - public void testSkipAndCountGaplessBuffers() { - Observable source = Observable.create(new OnSubscribeFunc() { - @Override - public Subscription onSubscribe(Observer observer) { - observer.onNext("one"); - observer.onNext("two"); - observer.onNext("three"); - observer.onNext("four"); - observer.onNext("five"); - observer.onCompleted(); - return Subscriptions.empty(); - } - }); - - Observable> buffered = Observable.create(buffer(source, 3, 3)); - buffered.subscribe(observer); - - InOrder inOrder = Mockito.inOrder(observer); - inOrder.verify(observer, Mockito.times(1)).onNext(list("one", "two", "three")); - inOrder.verify(observer, Mockito.times(1)).onNext(list("four", "five")); - inOrder.verify(observer, Mockito.never()).onNext(Mockito.anyListOf(String.class)); - inOrder.verify(observer, Mockito.never()).onError(Mockito.any(Throwable.class)); - inOrder.verify(observer, Mockito.times(1)).onCompleted(); - } - - @Test - public void testSkipAndCountBuffersWithGaps() { - Observable source = Observable.create(new OnSubscribeFunc() { - @Override - public Subscription onSubscribe(Observer observer) { - observer.onNext("one"); - observer.onNext("two"); - observer.onNext("three"); - observer.onNext("four"); - observer.onNext("five"); - observer.onCompleted(); - return Subscriptions.empty(); - } - }); - - Observable> buffered = Observable.create(buffer(source, 2, 3)); - buffered.subscribe(observer); - - InOrder inOrder = Mockito.inOrder(observer); - inOrder.verify(observer, Mockito.times(1)).onNext(list("one", "two")); - inOrder.verify(observer, Mockito.times(1)).onNext(list("four", "five")); - inOrder.verify(observer, Mockito.never()).onNext(Mockito.anyListOf(String.class)); - inOrder.verify(observer, Mockito.never()).onError(Mockito.any(Throwable.class)); - inOrder.verify(observer, Mockito.times(1)).onCompleted(); - } - - @Test - public void testTimedAndCount() { - Observable source = Observable.create(new OnSubscribeFunc() { - @Override - public Subscription onSubscribe(Observer observer) { - push(observer, "one", 10); - push(observer, "two", 90); - push(observer, "three", 110); - push(observer, "four", 190); - push(observer, "five", 210); - complete(observer, 250); - return Subscriptions.empty(); - } - }); - - Observable> buffered = Observable.create(buffer(source, 100, TimeUnit.MILLISECONDS, 2, scheduler)); - buffered.subscribe(observer); - - InOrder inOrder = Mockito.inOrder(observer); - scheduler.advanceTimeTo(100, TimeUnit.MILLISECONDS); - inOrder.verify(observer, Mockito.times(1)).onNext(list("one", "two")); - - scheduler.advanceTimeTo(200, TimeUnit.MILLISECONDS); - inOrder.verify(observer, Mockito.times(1)).onNext(list("three", "four")); - - scheduler.advanceTimeTo(300, TimeUnit.MILLISECONDS); - inOrder.verify(observer, Mockito.times(1)).onNext(list("five")); - inOrder.verify(observer, Mockito.never()).onNext(Mockito.anyListOf(String.class)); - inOrder.verify(observer, Mockito.never()).onError(Mockito.any(Throwable.class)); - inOrder.verify(observer, Mockito.times(1)).onCompleted(); - } - - @Test - public void testTimed() { - Observable source = Observable.create(new OnSubscribeFunc() { - @Override - public Subscription onSubscribe(Observer observer) { - push(observer, "one", 98); - push(observer, "two", 99); - push(observer, "three", 100); - push(observer, "four", 101); - push(observer, "five", 102); - complete(observer, 150); - return Subscriptions.empty(); - } - }); - - Observable> buffered = Observable.create(buffer(source, 100, TimeUnit.MILLISECONDS, scheduler)); - buffered.subscribe(observer); - - InOrder inOrder = Mockito.inOrder(observer); - scheduler.advanceTimeTo(101, TimeUnit.MILLISECONDS); - inOrder.verify(observer, Mockito.times(1)).onNext(list("one", "two", "three")); - - scheduler.advanceTimeTo(201, TimeUnit.MILLISECONDS); - inOrder.verify(observer, Mockito.times(1)).onNext(list("four", "five")); - inOrder.verify(observer, Mockito.never()).onNext(Mockito.anyListOf(String.class)); - inOrder.verify(observer, Mockito.never()).onError(Mockito.any(Throwable.class)); - inOrder.verify(observer, Mockito.times(1)).onCompleted(); - } - - @Test - public void testObservableBasedOpenerAndCloser() { - Observable source = Observable.create(new OnSubscribeFunc() { - @Override - public Subscription onSubscribe(Observer observer) { - push(observer, "one", 10); - push(observer, "two", 60); - push(observer, "three", 110); - push(observer, "four", 160); - push(observer, "five", 210); - complete(observer, 500); - return Subscriptions.empty(); - } - }); - - Observable openings = Observable.create(new OnSubscribeFunc() { - @Override - public Subscription onSubscribe(Observer observer) { - push(observer, Openings.create(), 50); - push(observer, Openings.create(), 200); - complete(observer, 250); - return Subscriptions.empty(); - } - }); - - Func1> closer = new Func1>() { - @Override - public Observable call(Opening opening) { - return Observable.create(new OnSubscribeFunc() { - @Override - public Subscription onSubscribe(Observer observer) { - push(observer, Closings.create(), 100); - complete(observer, 101); - return Subscriptions.empty(); - } - }); - } - }; - - Observable> buffered = Observable.create(buffer(source, openings, closer)); - buffered.subscribe(observer); - - InOrder inOrder = Mockito.inOrder(observer); - scheduler.advanceTimeTo(500, TimeUnit.MILLISECONDS); - inOrder.verify(observer, Mockito.times(1)).onNext(list("two", "three")); - inOrder.verify(observer, Mockito.times(1)).onNext(list("five")); - inOrder.verify(observer, Mockito.never()).onNext(Mockito.anyListOf(String.class)); - inOrder.verify(observer, Mockito.never()).onError(Mockito.any(Throwable.class)); - inOrder.verify(observer, Mockito.times(1)).onCompleted(); - } - - @Test - public void testObservableBasedCloser() { - Observable source = Observable.create(new OnSubscribeFunc() { - @Override - public Subscription onSubscribe(Observer observer) { - push(observer, "one", 10); - push(observer, "two", 60); - push(observer, "three", 110); - push(observer, "four", 160); - push(observer, "five", 210); - complete(observer, 250); - return Subscriptions.empty(); - } - }); - - Func0> closer = new Func0>() { - @Override - public Observable call() { - return Observable.create(new OnSubscribeFunc() { - @Override - public Subscription onSubscribe(Observer observer) { - push(observer, Closings.create(), 100); - complete(observer, 101); - return Subscriptions.empty(); - } - }); - } - }; - - Observable> buffered = Observable.create(buffer(source, closer)); - buffered.subscribe(observer); - - InOrder inOrder = Mockito.inOrder(observer); - scheduler.advanceTimeTo(500, TimeUnit.MILLISECONDS); - inOrder.verify(observer, Mockito.times(1)).onNext(list("one", "two")); - inOrder.verify(observer, Mockito.times(1)).onNext(list("three", "four")); - inOrder.verify(observer, Mockito.times(1)).onNext(list("five")); - inOrder.verify(observer, Mockito.never()).onNext(Mockito.anyListOf(String.class)); - inOrder.verify(observer, Mockito.never()).onError(Mockito.any(Throwable.class)); - inOrder.verify(observer, Mockito.times(1)).onCompleted(); - } - - @Test - public void testLongTimeAction() throws InterruptedException { - final CountDownLatch latch = new CountDownLatch(1); - LongTimeAction action = new LongTimeAction(latch); - Observable.from(1).buffer(10, TimeUnit.MILLISECONDS, 10) - .subscribe(action); - latch.await(); - assertFalse(action.fail); - } - - private static class LongTimeAction implements Action1> { - - CountDownLatch latch; - boolean fail = false; - - public LongTimeAction(CountDownLatch latch) { - this.latch = latch; - } - - @Override - public void call(List t1) { - try { - if (fail) { - return; - } - Thread.sleep(200); - } catch (InterruptedException e) { - fail = true; - } finally { - latch.countDown(); - } - } - } - - private List list(String... args) { - List list = new ArrayList(); - for (String arg : args) { - list.add(arg); - } - return list; - } - - private void push(final Observer observer, final T value, int delay) { - scheduler.schedule(new Action0() { - @Override - public void call() { - observer.onNext(value); - } - }, delay, TimeUnit.MILLISECONDS); - } - - private void complete(final Observer observer, int delay) { - scheduler.schedule(new Action0() { - @Override - public void call() { - observer.onCompleted(); - } - }, delay, TimeUnit.MILLISECONDS); - } - } } diff --git a/rxjava-core/src/main/java/rx/operators/OperationCache.java b/rxjava-core/src/main/java/rx/operators/OperationCache.java index e5f8ce69e3..44749bbd15 100644 --- a/rxjava-core/src/main/java/rx/operators/OperationCache.java +++ b/rxjava-core/src/main/java/rx/operators/OperationCache.java @@ -15,22 +15,13 @@ */ package rx.operators; -import static org.junit.Assert.*; - -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicBoolean; -import java.util.concurrent.atomic.AtomicInteger; - -import org.junit.Test; - import rx.Observable; import rx.Observable.OnSubscribeFunc; import rx.Observer; import rx.Subscription; import rx.subjects.ReplaySubject; -import rx.subscriptions.BooleanSubscription; -import rx.util.functions.Action1; + +import java.util.concurrent.atomic.AtomicBoolean; /** * This method has similar behavior to {@link Observable#replay()} except that this auto-subscribes @@ -70,61 +61,4 @@ public Subscription onSubscribe(Observer observer) { }; } - - public static class UnitTest { - - @Test - public void testCache() throws InterruptedException { - final AtomicInteger counter = new AtomicInteger(); - Observable o = Observable.create(cache(Observable.create(new OnSubscribeFunc() { - - @Override - public Subscription onSubscribe(final Observer observer) { - final BooleanSubscription subscription = new BooleanSubscription(); - new Thread(new Runnable() { - - @Override - public void run() { - counter.incrementAndGet(); - System.out.println("published observable being executed"); - observer.onNext("one"); - observer.onCompleted(); - } - }).start(); - return subscription; - } - }))); - - // we then expect the following 2 subscriptions to get that same value - final CountDownLatch latch = new CountDownLatch(2); - - // subscribe once - o.subscribe(new Action1() { - - @Override - public void call(String v) { - assertEquals("one", v); - System.out.println("v: " + v); - latch.countDown(); - } - }); - - // subscribe again - o.subscribe(new Action1() { - - @Override - public void call(String v) { - assertEquals("one", v); - System.out.println("v: " + v); - latch.countDown(); - } - }); - - if (!latch.await(1000, TimeUnit.MILLISECONDS)) { - fail("subscriptions did not receive values"); - } - assertEquals(1, counter.get()); - } - } - } diff --git a/rxjava-core/src/main/java/rx/operators/OperationCast.java b/rxjava-core/src/main/java/rx/operators/OperationCast.java index a4887c3afe..0643624a02 100644 --- a/rxjava-core/src/main/java/rx/operators/OperationCast.java +++ b/rxjava-core/src/main/java/rx/operators/OperationCast.java @@ -1,15 +1,7 @@ package rx.operators; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.never; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; - -import org.junit.Test; - import rx.Observable; import rx.Observable.OnSubscribeFunc; -import rx.Observer; import rx.util.functions.Func1; /** @@ -25,37 +17,4 @@ public R call(T t) { } }); } - - public static class UnitTest { - - @Test - public void testCast() { - Observable source = Observable.from(1, 2); - Observable observable = Observable.create(cast(source, - Integer.class)); - - @SuppressWarnings("unchecked") - Observer aObserver = mock(Observer.class); - observable.subscribe(aObserver); - verify(aObserver, times(1)).onNext(1); - verify(aObserver, times(1)).onNext(1); - verify(aObserver, never()).onError( - org.mockito.Matchers.any(Throwable.class)); - verify(aObserver, times(1)).onCompleted(); - } - - @Test - public void testCastWithWrongType() { - Observable source = Observable.from(1, 2); - Observable observable = Observable.create(cast(source, - Boolean.class)); - - @SuppressWarnings("unchecked") - Observer aObserver = mock(Observer.class); - observable.subscribe(aObserver); - verify(aObserver, times(1)).onError( - org.mockito.Matchers.any(ClassCastException.class)); - } - } - } diff --git a/rxjava-core/src/main/java/rx/operators/OperationCombineLatest.java b/rxjava-core/src/main/java/rx/operators/OperationCombineLatest.java index 020254d8a0..b87aaea0ba 100644 --- a/rxjava-core/src/main/java/rx/operators/OperationCombineLatest.java +++ b/rxjava-core/src/main/java/rx/operators/OperationCombineLatest.java @@ -15,10 +15,12 @@ */ package rx.operators; -import static org.mockito.Matchers.*; -import static org.mockito.Mockito.*; +import rx.Observable; +import rx.Observable.OnSubscribeFunc; +import rx.Observer; +import rx.Subscription; +import rx.util.functions.*; -import java.util.Arrays; import java.util.LinkedList; import java.util.List; import java.util.Map; @@ -26,26 +28,6 @@ import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicInteger; -import org.junit.Test; -import org.mockito.InOrder; -import org.mockito.Matchers; - -import rx.Observable; -import rx.Observable.OnSubscribeFunc; -import rx.Observer; -import rx.Subscription; -import rx.subscriptions.Subscriptions; -import rx.util.functions.Func2; -import rx.util.functions.Func3; -import rx.util.functions.Func4; -import rx.util.functions.Func5; -import rx.util.functions.Func6; -import rx.util.functions.Func7; -import rx.util.functions.Func8; -import rx.util.functions.Func9; -import rx.util.functions.FuncN; -import rx.util.functions.Functions; - /** * Returns an Observable that combines the emissions of multiple source observables. Once each * source Observable has emitted at least one item, combineLatest emits an item whenever any of @@ -179,7 +161,7 @@ public static OnSubscribeFunc combine return a; } - private static class CombineObserver implements Observer { + static class CombineObserver implements Observer { final Observable w; final Aggregator a; private Subscription subscription; @@ -217,7 +199,7 @@ public void onNext(T args) { * whenever we have received an event from one of the observables, as soon as each Observable has received * at least one event. */ - private static class Aggregator implements OnSubscribeFunc { + static class Aggregator implements OnSubscribeFunc { private volatile Observer observer; @@ -351,603 +333,4 @@ private void stop() { } } } - - public static class UnitTest { - - @Test - public void testCombineLatestWithFunctionThatThrowsAnException() { - @SuppressWarnings("unchecked") // mock calls don't do generics - Observer w = mock(Observer.class); - - TestObservable w1 = new TestObservable(); - TestObservable w2 = new TestObservable(); - - Observable combined = Observable.create(combineLatest(Observable.create(w1), Observable.create(w2), new Func2() { - @Override - public String call(String v1, String v2) { - throw new RuntimeException("I don't work."); - } - })); - combined.subscribe(w); - - w1.observer.onNext("first value of w1"); - w2.observer.onNext("first value of w2"); - - verify(w, never()).onNext(anyString()); - verify(w, never()).onCompleted(); - verify(w, times(1)).onError(Matchers.any()); - } - - @Test - public void testCombineLatestDifferentLengthObservableSequences1() { - @SuppressWarnings("unchecked") // mock calls don't do generics - Observer w = mock(Observer.class); - - TestObservable w1 = new TestObservable(); - TestObservable w2 = new TestObservable(); - TestObservable w3 = new TestObservable(); - - Observable combineLatestW = Observable.create(combineLatest(Observable.create(w1), Observable.create(w2), Observable.create(w3), getConcat3StringsCombineLatestFunction())); - combineLatestW.subscribe(w); - - /* simulate sending data */ - // once for w1 - w1.observer.onNext("1a"); - w2.observer.onNext("2a"); - w3.observer.onNext("3a"); - w1.observer.onCompleted(); - // twice for w2 - w2.observer.onNext("2b"); - w2.observer.onCompleted(); - // 4 times for w3 - w3.observer.onNext("3b"); - w3.observer.onNext("3c"); - w3.observer.onNext("3d"); - w3.observer.onCompleted(); - - /* we should have been called 4 times on the Observer */ - InOrder inOrder = inOrder(w); - inOrder.verify(w).onNext("1a2a3a"); - inOrder.verify(w).onNext("1a2b3a"); - inOrder.verify(w).onNext("1a2b3b"); - inOrder.verify(w).onNext("1a2b3c"); - inOrder.verify(w).onNext("1a2b3d"); - inOrder.verify(w, never()).onNext(anyString()); - inOrder.verify(w, times(1)).onCompleted(); - } - - @Test - public void testCombineLatestDifferentLengthObservableSequences2() { - @SuppressWarnings("unchecked") - Observer w = mock(Observer.class); - - TestObservable w1 = new TestObservable(); - TestObservable w2 = new TestObservable(); - TestObservable w3 = new TestObservable(); - - Observable combineLatestW = Observable.create(combineLatest(Observable.create(w1), Observable.create(w2), Observable.create(w3), getConcat3StringsCombineLatestFunction())); - combineLatestW.subscribe(w); - - /* simulate sending data */ - // 4 times for w1 - w1.observer.onNext("1a"); - w1.observer.onNext("1b"); - w1.observer.onNext("1c"); - w1.observer.onNext("1d"); - w1.observer.onCompleted(); - // twice for w2 - w2.observer.onNext("2a"); - w2.observer.onNext("2b"); - w2.observer.onCompleted(); - // 1 times for w3 - w3.observer.onNext("3a"); - w3.observer.onCompleted(); - - /* we should have been called 1 time only on the Observer since we only combine the "latest" we don't go back and loop through others once completed */ - InOrder inOrder = inOrder(w); - inOrder.verify(w, times(1)).onNext("1d2b3a"); - inOrder.verify(w, never()).onNext(anyString()); - - inOrder.verify(w, times(1)).onCompleted(); - - } - - @Test - public void testCombineLatestWithInterleavingSequences() { - @SuppressWarnings("unchecked") - Observer w = mock(Observer.class); - - TestObservable w1 = new TestObservable(); - TestObservable w2 = new TestObservable(); - TestObservable w3 = new TestObservable(); - - Observable combineLatestW = Observable.create(combineLatest(Observable.create(w1), Observable.create(w2), Observable.create(w3), getConcat3StringsCombineLatestFunction())); - combineLatestW.subscribe(w); - - /* simulate sending data */ - w1.observer.onNext("1a"); - w2.observer.onNext("2a"); - w2.observer.onNext("2b"); - w3.observer.onNext("3a"); - - w1.observer.onNext("1b"); - w2.observer.onNext("2c"); - w2.observer.onNext("2d"); - w3.observer.onNext("3b"); - - w1.observer.onCompleted(); - w2.observer.onCompleted(); - w3.observer.onCompleted(); - - /* we should have been called 5 times on the Observer */ - InOrder inOrder = inOrder(w); - inOrder.verify(w).onNext("1a2b3a"); - inOrder.verify(w).onNext("1b2b3a"); - inOrder.verify(w).onNext("1b2c3a"); - inOrder.verify(w).onNext("1b2d3a"); - inOrder.verify(w).onNext("1b2d3b"); - - inOrder.verify(w, never()).onNext(anyString()); - inOrder.verify(w, times(1)).onCompleted(); - } - - /** - * Testing internal private logic due to the complexity so I want to use TDD to test as a I build it rather than relying purely on the overall functionality expected by the public methods. - */ - @SuppressWarnings("unchecked") - /* mock calls don't do generics */ - @Test - public void testAggregatorSimple() { - FuncN combineLatestFunction = getConcatCombineLatestFunction(); - /* create the aggregator which will execute the combineLatest function when all Observables provide values */ - Aggregator a = new Aggregator(combineLatestFunction); - - /* define a Observer to receive aggregated events */ - Observer aObserver = mock(Observer.class); - Observable.create(a).subscribe(aObserver); - - /* mock the Observable Observers that are 'pushing' data for us */ - CombineObserver r1 = mock(CombineObserver.class); - CombineObserver r2 = mock(CombineObserver.class); - - /* pretend we're starting up */ - a.addObserver(r1); - a.addObserver(r2); - - /* simulate the Observables pushing data into the aggregator */ - a.next(r1, "hello"); - a.next(r2, "world"); - - InOrder inOrder = inOrder(aObserver); - - verify(aObserver, never()).onError(any(Throwable.class)); - verify(aObserver, never()).onCompleted(); - inOrder.verify(aObserver, times(1)).onNext("helloworld"); - - a.next(r1, "hello "); - a.next(r2, "again"); - - verify(aObserver, never()).onError(any(Throwable.class)); - verify(aObserver, never()).onCompleted(); - inOrder.verify(aObserver, times(1)).onNext("hello again"); - - a.complete(r1); - a.complete(r2); - - inOrder.verify(aObserver, never()).onNext(anyString()); - verify(aObserver, times(1)).onCompleted(); - } - - @SuppressWarnings("unchecked") - /* mock calls don't do generics */ - @Test - public void testAggregatorDifferentSizedResultsWithOnComplete() { - FuncN combineLatestFunction = getConcatCombineLatestFunction(); - /* create the aggregator which will execute the combineLatest function when all Observables provide values */ - Aggregator a = new Aggregator(combineLatestFunction); - - /* define a Observer to receive aggregated events */ - Observer aObserver = mock(Observer.class); - Observable.create(a).subscribe(aObserver); - - /* mock the Observable Observers that are 'pushing' data for us */ - CombineObserver r1 = mock(CombineObserver.class); - CombineObserver r2 = mock(CombineObserver.class); - - /* pretend we're starting up */ - a.addObserver(r1); - a.addObserver(r2); - - /* simulate the Observables pushing data into the aggregator */ - a.next(r1, "hello"); - a.next(r2, "world"); - a.complete(r2); - - verify(aObserver, never()).onError(any(Throwable.class)); - verify(aObserver, never()).onCompleted(); - verify(aObserver, times(1)).onNext("helloworld"); - - a.next(r1, "hi"); - a.complete(r1); - - verify(aObserver, never()).onError(any(Throwable.class)); - verify(aObserver, times(1)).onCompleted(); - verify(aObserver, times(1)).onNext("hiworld"); - } - - @SuppressWarnings("unchecked") - /* mock calls don't do generics */ - @Test - public void testAggregateMultipleTypes() { - FuncN combineLatestFunction = getConcatCombineLatestFunction(); - /* create the aggregator which will execute the combineLatest function when all Observables provide values */ - Aggregator a = new Aggregator(combineLatestFunction); - - /* define a Observer to receive aggregated events */ - Observer aObserver = mock(Observer.class); - Observable.create(a).subscribe(aObserver); - - /* mock the Observable Observers that are 'pushing' data for us */ - CombineObserver r1 = mock(CombineObserver.class); - CombineObserver r2 = mock(CombineObserver.class); - - /* pretend we're starting up */ - a.addObserver(r1); - a.addObserver(r2); - - /* simulate the Observables pushing data into the aggregator */ - a.next(r1, "hello"); - a.next(r2, "world"); - a.complete(r2); - - verify(aObserver, never()).onError(any(Throwable.class)); - verify(aObserver, never()).onCompleted(); - verify(aObserver, times(1)).onNext("helloworld"); - - a.next(r1, "hi"); - a.complete(r1); - - verify(aObserver, never()).onError(any(Throwable.class)); - verify(aObserver, times(1)).onCompleted(); - verify(aObserver, times(1)).onNext("hiworld"); - } - - @SuppressWarnings("unchecked") - /* mock calls don't do generics */ - @Test - public void testAggregate3Types() { - FuncN combineLatestFunction = getConcatCombineLatestFunction(); - /* create the aggregator which will execute the combineLatest function when all Observables provide values */ - Aggregator a = new Aggregator(combineLatestFunction); - - /* define a Observer to receive aggregated events */ - Observer aObserver = mock(Observer.class); - Observable.create(a).subscribe(aObserver); - - /* mock the Observable Observers that are 'pushing' data for us */ - CombineObserver r1 = mock(CombineObserver.class); - CombineObserver r2 = mock(CombineObserver.class); - CombineObserver r3 = mock(CombineObserver.class); - - /* pretend we're starting up */ - a.addObserver(r1); - a.addObserver(r2); - a.addObserver(r3); - - /* simulate the Observables pushing data into the aggregator */ - a.next(r1, "hello"); - a.next(r2, 2); - a.next(r3, new int[] { 5, 6, 7 }); - - verify(aObserver, never()).onError(any(Throwable.class)); - verify(aObserver, never()).onCompleted(); - verify(aObserver, times(1)).onNext("hello2[5, 6, 7]"); - } - - @SuppressWarnings("unchecked") - /* mock calls don't do generics */ - @Test - public void testAggregatorsWithDifferentSizesAndTiming() { - FuncN combineLatestFunction = getConcatCombineLatestFunction(); - /* create the aggregator which will execute the combineLatest function when all Observables provide values */ - Aggregator a = new Aggregator(combineLatestFunction); - - /* define a Observer to receive aggregated events */ - Observer aObserver = mock(Observer.class); - Observable.create(a).subscribe(aObserver); - - /* mock the Observable Observers that are 'pushing' data for us */ - CombineObserver r1 = mock(CombineObserver.class); - CombineObserver r2 = mock(CombineObserver.class); - - /* pretend we're starting up */ - a.addObserver(r1); - a.addObserver(r2); - - /* simulate the Observables pushing data into the aggregator */ - a.next(r1, "one"); - a.next(r1, "two"); - a.next(r1, "three"); - a.next(r2, "A"); - - verify(aObserver, never()).onError(any(Throwable.class)); - verify(aObserver, never()).onCompleted(); - verify(aObserver, times(1)).onNext("threeA"); - - a.next(r1, "four"); - a.complete(r1); - a.next(r2, "B"); - verify(aObserver, times(1)).onNext("fourB"); - a.next(r2, "C"); - verify(aObserver, times(1)).onNext("fourC"); - a.next(r2, "D"); - verify(aObserver, times(1)).onNext("fourD"); - a.next(r2, "E"); - verify(aObserver, times(1)).onNext("fourE"); - a.complete(r2); - - verify(aObserver, never()).onError(any(Throwable.class)); - verify(aObserver, times(1)).onCompleted(); - } - - @SuppressWarnings("unchecked") - /* mock calls don't do generics */ - @Test - public void testAggregatorError() { - FuncN combineLatestFunction = getConcatCombineLatestFunction(); - /* create the aggregator which will execute the combineLatest function when all Observables provide values */ - Aggregator a = new Aggregator(combineLatestFunction); - - /* define a Observer to receive aggregated events */ - Observer aObserver = mock(Observer.class); - Observable.create(a).subscribe(aObserver); - - /* mock the Observable Observers that are 'pushing' data for us */ - CombineObserver r1 = mock(CombineObserver.class); - CombineObserver r2 = mock(CombineObserver.class); - - /* pretend we're starting up */ - a.addObserver(r1); - a.addObserver(r2); - - /* simulate the Observables pushing data into the aggregator */ - a.next(r1, "hello"); - a.next(r2, "world"); - - verify(aObserver, never()).onError(any(Throwable.class)); - verify(aObserver, never()).onCompleted(); - verify(aObserver, times(1)).onNext("helloworld"); - - a.error(new RuntimeException("")); - a.next(r1, "hello"); - a.next(r2, "again"); - - verify(aObserver, times(1)).onError(any(Throwable.class)); - verify(aObserver, never()).onCompleted(); - // we don't want to be called again after an error - verify(aObserver, times(0)).onNext("helloagain"); - } - - @SuppressWarnings("unchecked") - /* mock calls don't do generics */ - @Test - public void testAggregatorUnsubscribe() { - FuncN combineLatestFunction = getConcatCombineLatestFunction(); - /* create the aggregator which will execute the combineLatest function when all Observables provide values */ - Aggregator a = new Aggregator(combineLatestFunction); - - /* define a Observer to receive aggregated events */ - Observer aObserver = mock(Observer.class); - Subscription subscription = Observable.create(a).subscribe(aObserver); - - /* mock the Observable Observers that are 'pushing' data for us */ - CombineObserver r1 = mock(CombineObserver.class); - CombineObserver r2 = mock(CombineObserver.class); - - /* pretend we're starting up */ - a.addObserver(r1); - a.addObserver(r2); - - /* simulate the Observables pushing data into the aggregator */ - a.next(r1, "hello"); - a.next(r2, "world"); - - verify(aObserver, never()).onError(any(Throwable.class)); - verify(aObserver, never()).onCompleted(); - verify(aObserver, times(1)).onNext("helloworld"); - - subscription.unsubscribe(); - a.next(r1, "hello"); - a.next(r2, "again"); - - verify(aObserver, times(0)).onError(any(Throwable.class)); - verify(aObserver, never()).onCompleted(); - // we don't want to be called again after an error - verify(aObserver, times(0)).onNext("helloagain"); - } - - @SuppressWarnings("unchecked") - /* mock calls don't do generics */ - @Test - public void testAggregatorEarlyCompletion() { - FuncN combineLatestFunction = getConcatCombineLatestFunction(); - /* create the aggregator which will execute the combineLatest function when all Observables provide values */ - Aggregator a = new Aggregator(combineLatestFunction); - - /* define a Observer to receive aggregated events */ - Observer aObserver = mock(Observer.class); - Observable.create(a).subscribe(aObserver); - - /* mock the Observable Observers that are 'pushing' data for us */ - CombineObserver r1 = mock(CombineObserver.class); - CombineObserver r2 = mock(CombineObserver.class); - - /* pretend we're starting up */ - a.addObserver(r1); - a.addObserver(r2); - - /* simulate the Observables pushing data into the aggregator */ - a.next(r1, "one"); - a.next(r1, "two"); - a.complete(r1); - a.next(r2, "A"); - - InOrder inOrder = inOrder(aObserver); - - inOrder.verify(aObserver, never()).onError(any(Throwable.class)); - inOrder.verify(aObserver, never()).onCompleted(); - inOrder.verify(aObserver, times(1)).onNext("twoA"); - - a.complete(r2); - - inOrder.verify(aObserver, never()).onError(any(Throwable.class)); - inOrder.verify(aObserver, times(1)).onCompleted(); - // we shouldn't get this since completed is called before any other onNext calls could trigger this - inOrder.verify(aObserver, never()).onNext(anyString()); - } - - @SuppressWarnings("unchecked") - /* mock calls don't do generics */ - @Test - public void testCombineLatest2Types() { - Func2 combineLatestFunction = getConcatStringIntegerCombineLatestFunction(); - - /* define a Observer to receive aggregated events */ - Observer aObserver = mock(Observer.class); - - Observable w = Observable.create(combineLatest(Observable.from("one", "two"), Observable.from(2, 3, 4), combineLatestFunction)); - w.subscribe(aObserver); - - verify(aObserver, never()).onError(any(Throwable.class)); - verify(aObserver, times(1)).onCompleted(); - verify(aObserver, times(1)).onNext("two2"); - verify(aObserver, times(1)).onNext("two3"); - verify(aObserver, times(1)).onNext("two4"); - } - - @SuppressWarnings("unchecked") - /* mock calls don't do generics */ - @Test - public void testCombineLatest3TypesA() { - Func3 combineLatestFunction = getConcatStringIntegerIntArrayCombineLatestFunction(); - - /* define a Observer to receive aggregated events */ - Observer aObserver = mock(Observer.class); - - Observable w = Observable.create(combineLatest(Observable.from("one", "two"), Observable.from(2), Observable.from(new int[] { 4, 5, 6 }), combineLatestFunction)); - w.subscribe(aObserver); - - verify(aObserver, never()).onError(any(Throwable.class)); - verify(aObserver, times(1)).onCompleted(); - verify(aObserver, times(1)).onNext("two2[4, 5, 6]"); - } - - @SuppressWarnings("unchecked") - /* mock calls don't do generics */ - @Test - public void testCombineLatest3TypesB() { - Func3 combineLatestFunction = getConcatStringIntegerIntArrayCombineLatestFunction(); - - /* define a Observer to receive aggregated events */ - Observer aObserver = mock(Observer.class); - - Observable w = Observable.create(combineLatest(Observable.from("one"), Observable.from(2), Observable.from(new int[] { 4, 5, 6 }, new int[] { 7, 8 }), combineLatestFunction)); - w.subscribe(aObserver); - - verify(aObserver, never()).onError(any(Throwable.class)); - verify(aObserver, times(1)).onCompleted(); - verify(aObserver, times(1)).onNext("one2[4, 5, 6]"); - verify(aObserver, times(1)).onNext("one2[7, 8]"); - } - - private Func3 getConcat3StringsCombineLatestFunction() { - Func3 combineLatestFunction = new Func3() { - - @Override - public String call(String a1, String a2, String a3) { - if (a1 == null) { - a1 = ""; - } - if (a2 == null) { - a2 = ""; - } - if (a3 == null) { - a3 = ""; - } - return a1 + a2 + a3; - } - - }; - return combineLatestFunction; - } - - private FuncN getConcatCombineLatestFunction() { - FuncN combineLatestFunction = new FuncN() { - - @Override - public String call(Object... args) { - String returnValue = ""; - for (Object o : args) { - if (o != null) { - returnValue += getStringValue(o); - } - } - System.out.println("returning: " + returnValue); - return returnValue; - } - - }; - return combineLatestFunction; - } - - private Func2 getConcatStringIntegerCombineLatestFunction() { - Func2 combineLatestFunction = new Func2() { - - @Override - public String call(String s, Integer i) { - return getStringValue(s) + getStringValue(i); - } - - }; - return combineLatestFunction; - } - - private Func3 getConcatStringIntegerIntArrayCombineLatestFunction() { - Func3 combineLatestFunction = new Func3() { - - @Override - public String call(String s, Integer i, int[] iArray) { - return getStringValue(s) + getStringValue(i) + getStringValue(iArray); - } - - }; - return combineLatestFunction; - } - - private static String getStringValue(Object o) { - if (o == null) { - return ""; - } else { - if (o instanceof int[]) { - return Arrays.toString((int[]) o); - } else { - return String.valueOf(o); - } - } - } - - private static class TestObservable implements OnSubscribeFunc { - - Observer observer; - - @Override - public Subscription onSubscribe(Observer observer) { - // just store the variable where it can be accessed so we can manually trigger it - this.observer = observer; - return Subscriptions.empty(); - } - - } - } - } diff --git a/rxjava-core/src/main/java/rx/operators/OperationConcat.java b/rxjava-core/src/main/java/rx/operators/OperationConcat.java index 734751e9d0..4488ddf177 100644 --- a/rxjava-core/src/main/java/rx/operators/OperationConcat.java +++ b/rxjava-core/src/main/java/rx/operators/OperationConcat.java @@ -15,28 +15,14 @@ */ package rx.operators; -import static org.junit.Assert.*; -import static org.mockito.Matchers.*; -import static org.mockito.Mockito.*; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.Queue; -import java.util.concurrent.ConcurrentLinkedQueue; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicBoolean; -import java.util.concurrent.atomic.AtomicReference; - -import org.junit.Test; -import org.mockito.InOrder; - import rx.Observable; import rx.Observable.OnSubscribeFunc; import rx.Observer; import rx.Subscription; -import rx.subscriptions.BooleanSubscription; + +import java.util.Queue; +import java.util.concurrent.ConcurrentLinkedQueue; +import java.util.concurrent.atomic.AtomicBoolean; /** * Returns an Observable that emits the items emitted by two or more Observables, one after the @@ -166,529 +152,4 @@ public void unsubscribe() { }; } } - - public static class UnitTest { - - @Test - public void testConcat() { - @SuppressWarnings("unchecked") - Observer observer = mock(Observer.class); - - final String[] o = { "1", "3", "5", "7" }; - final String[] e = { "2", "4", "6" }; - - final Observable odds = Observable.from(o); - final Observable even = Observable.from(e); - - @SuppressWarnings("unchecked") - Observable concat = Observable.create(concat(odds, even)); - concat.subscribe(observer); - - verify(observer, times(7)).onNext(anyString()); - } - - @Test - public void testConcatWithList() { - @SuppressWarnings("unchecked") - Observer observer = mock(Observer.class); - - final String[] o = { "1", "3", "5", "7" }; - final String[] e = { "2", "4", "6" }; - - final Observable odds = Observable.from(o); - final Observable even = Observable.from(e); - final List> list = new ArrayList>(); - list.add(odds); - list.add(even); - Observable concat = Observable.create(concat(list)); - concat.subscribe(observer); - - verify(observer, times(7)).onNext(anyString()); - } - - @Test - public void testConcatObservableOfObservables() { - @SuppressWarnings("unchecked") - Observer observer = mock(Observer.class); - - final String[] o = { "1", "3", "5", "7" }; - final String[] e = { "2", "4", "6" }; - - final Observable odds = Observable.from(o); - final Observable even = Observable.from(e); - - Observable> observableOfObservables = Observable.create(new OnSubscribeFunc>() { - - @Override - public Subscription onSubscribe(Observer> observer) { - // simulate what would happen in an observable - observer.onNext(odds); - observer.onNext(even); - observer.onCompleted(); - - return new Subscription() { - - @Override - public void unsubscribe() { - // unregister ... will never be called here since we are executing synchronously - } - - }; - } - - }); - Observable concat = Observable.create(concat(observableOfObservables)); - - concat.subscribe(observer); - - verify(observer, times(7)).onNext(anyString()); - } - - /** - * Simple concat of 2 asynchronous observables ensuring it emits in correct order. - */ - @SuppressWarnings("unchecked") - @Test - public void testSimpleAsyncConcat() { - Observer observer = mock(Observer.class); - - TestObservable o1 = new TestObservable("one", "two", "three"); - TestObservable o2 = new TestObservable("four", "five", "six"); - - Observable.concat(Observable.create(o1), Observable.create(o2)).subscribe(observer); - - try { - // wait for async observables to complete - o1.t.join(); - o2.t.join(); - } catch (Throwable e) { - throw new RuntimeException("failed waiting on threads"); - } - - InOrder inOrder = inOrder(observer); - inOrder.verify(observer, times(1)).onNext("one"); - inOrder.verify(observer, times(1)).onNext("two"); - inOrder.verify(observer, times(1)).onNext("three"); - inOrder.verify(observer, times(1)).onNext("four"); - inOrder.verify(observer, times(1)).onNext("five"); - inOrder.verify(observer, times(1)).onNext("six"); - } - - /** - * Test an async Observable that emits more async Observables - */ - @SuppressWarnings("unchecked") - @Test - public void testNestedAsyncConcat() throws Throwable { - Observer observer = mock(Observer.class); - - final TestObservable o1 = new TestObservable("one", "two", "three"); - final TestObservable o2 = new TestObservable("four", "five", "six"); - final TestObservable o3 = new TestObservable("seven", "eight", "nine"); - final CountDownLatch allowThird = new CountDownLatch(1); - - final AtomicReference parent = new AtomicReference(); - Observable> observableOfObservables = Observable.create(new OnSubscribeFunc>() { - - @Override - public Subscription onSubscribe(final Observer> observer) { - final BooleanSubscription s = new BooleanSubscription(); - parent.set(new Thread(new Runnable() { - - @Override - public void run() { - try { - // emit first - if (!s.isUnsubscribed()) { - System.out.println("Emit o1"); - observer.onNext(Observable.create(o1)); - } - // emit second - if (!s.isUnsubscribed()) { - System.out.println("Emit o2"); - observer.onNext(Observable.create(o2)); - } - - // wait until sometime later and emit third - try { - allowThird.await(); - } catch (InterruptedException e) { - observer.onError(e); - } - if (!s.isUnsubscribed()) { - System.out.println("Emit o3"); - observer.onNext(Observable.create(o3)); - } - - } catch (Throwable e) { - observer.onError(e); - } finally { - System.out.println("Done parent Observable"); - observer.onCompleted(); - } - } - })); - parent.get().start(); - return s; - } - }); - - Observable.create(concat(observableOfObservables)).subscribe(observer); - - // wait for parent to start - while (parent.get() == null) { - Thread.sleep(1); - } - - try { - // wait for first 2 async observables to complete - while (o1.t == null) { - Thread.sleep(1); - } - System.out.println("Thread1 started ... waiting for it to complete ..."); - o1.t.join(); - while (o2.t == null) { - Thread.sleep(1); - } - System.out.println("Thread2 started ... waiting for it to complete ..."); - o2.t.join(); - } catch (Throwable e) { - throw new RuntimeException("failed waiting on threads", e); - } - - InOrder inOrder = inOrder(observer); - inOrder.verify(observer, times(1)).onNext("one"); - inOrder.verify(observer, times(1)).onNext("two"); - inOrder.verify(observer, times(1)).onNext("three"); - inOrder.verify(observer, times(1)).onNext("four"); - inOrder.verify(observer, times(1)).onNext("five"); - inOrder.verify(observer, times(1)).onNext("six"); - // we shouldn't have the following 3 yet - inOrder.verify(observer, never()).onNext("seven"); - inOrder.verify(observer, never()).onNext("eight"); - inOrder.verify(observer, never()).onNext("nine"); - // we should not be completed yet - verify(observer, never()).onCompleted(); - verify(observer, never()).onError(any(Throwable.class)); - - // now allow the third - allowThird.countDown(); - - try { - while (o3.t == null) { - Thread.sleep(1); - } - // wait for 3rd to complete - o3.t.join(); - } catch (Throwable e) { - throw new RuntimeException("failed waiting on threads", e); - } - - inOrder.verify(observer, times(1)).onNext("seven"); - inOrder.verify(observer, times(1)).onNext("eight"); - inOrder.verify(observer, times(1)).onNext("nine"); - - inOrder.verify(observer, times(1)).onCompleted(); - verify(observer, never()).onError(any(Throwable.class)); - } - - @SuppressWarnings("unchecked") - @Test - public void testBlockedObservableOfObservables() { - Observer observer = mock(Observer.class); - - final String[] o = { "1", "3", "5", "7" }; - final String[] e = { "2", "4", "6" }; - final Observable odds = Observable.from(o); - final Observable even = Observable.from(e); - final CountDownLatch callOnce = new CountDownLatch(1); - final CountDownLatch okToContinue = new CountDownLatch(1); - TestObservable> observableOfObservables = new TestObservable>(callOnce, okToContinue, odds, even); - OnSubscribeFunc concatF = concat(Observable.create(observableOfObservables)); - Observable concat = Observable.create(concatF); - concat.subscribe(observer); - try { - //Block main thread to allow observables to serve up o1. - callOnce.await(); - } catch (Throwable ex) { - ex.printStackTrace(); - fail(ex.getMessage()); - } - // The concated observable should have served up all of the odds. - verify(observer, times(1)).onNext("1"); - verify(observer, times(1)).onNext("3"); - verify(observer, times(1)).onNext("5"); - verify(observer, times(1)).onNext("7"); - - try { - // unblock observables so it can serve up o2 and complete - okToContinue.countDown(); - observableOfObservables.t.join(); - } catch (Throwable ex) { - ex.printStackTrace(); - fail(ex.getMessage()); - } - // The concatenated observable should now have served up all the evens. - verify(observer, times(1)).onNext("2"); - verify(observer, times(1)).onNext("4"); - verify(observer, times(1)).onNext("6"); - } - - @Test - public void testConcatConcurrentWithInfinity() { - final TestObservable w1 = new TestObservable("one", "two", "three"); - //This observable will send "hello" MAX_VALUE time. - final TestObservable w2 = new TestObservable("hello", Integer.MAX_VALUE); - - @SuppressWarnings("unchecked") - Observer aObserver = mock(Observer.class); - @SuppressWarnings("unchecked") - TestObservable> observableOfObservables = new TestObservable>(Observable.create(w1), Observable.create(w2)); - OnSubscribeFunc concatF = concat(Observable.create(observableOfObservables)); - - Observable concat = Observable.create(concatF); - - concat.take(50).subscribe(aObserver); - - //Wait for the thread to start up. - try { - Thread.sleep(25); - w1.t.join(); - w2.t.join(); - } catch (InterruptedException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - - InOrder inOrder = inOrder(aObserver); - inOrder.verify(aObserver, times(1)).onNext("one"); - inOrder.verify(aObserver, times(1)).onNext("two"); - inOrder.verify(aObserver, times(1)).onNext("three"); - inOrder.verify(aObserver, times(47)).onNext("hello"); - verify(aObserver, times(1)).onCompleted(); - verify(aObserver, never()).onError(any(Throwable.class)); - } - - @Test - public void testConcatNonBlockingObservables() { - - final CountDownLatch okToContinueW1 = new CountDownLatch(1); - final CountDownLatch okToContinueW2 = new CountDownLatch(1); - - final TestObservable w1 = new TestObservable(null, okToContinueW1, "one", "two", "three"); - final TestObservable w2 = new TestObservable(null, okToContinueW2, "four", "five", "six"); - - @SuppressWarnings("unchecked") - Observer aObserver = mock(Observer.class); - Observable> observableOfObservables = Observable.create(new OnSubscribeFunc>() { - - @Override - public Subscription onSubscribe(Observer> observer) { - // simulate what would happen in an observable - observer.onNext(Observable.create(w1)); - observer.onNext(Observable.create(w2)); - observer.onCompleted(); - - return new Subscription() { - - @Override - public void unsubscribe() { - } - - }; - } - - }); - Observable concat = Observable.create(concat(observableOfObservables)); - concat.subscribe(aObserver); - - verify(aObserver, times(0)).onCompleted(); - - try { - // release both threads - okToContinueW1.countDown(); - okToContinueW2.countDown(); - // wait for both to finish - w1.t.join(); - w2.t.join(); - } catch (InterruptedException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - - InOrder inOrder = inOrder(aObserver); - inOrder.verify(aObserver, times(1)).onNext("one"); - inOrder.verify(aObserver, times(1)).onNext("two"); - inOrder.verify(aObserver, times(1)).onNext("three"); - inOrder.verify(aObserver, times(1)).onNext("four"); - inOrder.verify(aObserver, times(1)).onNext("five"); - inOrder.verify(aObserver, times(1)).onNext("six"); - verify(aObserver, times(1)).onCompleted(); - - } - - /** - * Test unsubscribing the concatenated Observable in a single thread. - */ - @Test - public void testConcatUnsubscribe() { - final CountDownLatch callOnce = new CountDownLatch(1); - final CountDownLatch okToContinue = new CountDownLatch(1); - final TestObservable w1 = new TestObservable("one", "two", "three"); - final TestObservable w2 = new TestObservable(callOnce, okToContinue, "four", "five", "six"); - - @SuppressWarnings("unchecked") - final Observer aObserver = mock(Observer.class); - @SuppressWarnings("unchecked") - final Observable concat = Observable.create(concat(Observable.create(w1), Observable.create(w2))); - final SafeObservableSubscription s1 = new SafeObservableSubscription(); - - try { - // Subscribe - s1.wrap(concat.subscribe(aObserver)); - //Block main thread to allow observable "w1" to complete and observable "w2" to call onNext once. - callOnce.await(); - // Unsubcribe - s1.unsubscribe(); - //Unblock the observable to continue. - okToContinue.countDown(); - w1.t.join(); - w2.t.join(); - } catch (Throwable e) { - e.printStackTrace(); - fail(e.getMessage()); - } - - InOrder inOrder = inOrder(aObserver); - inOrder.verify(aObserver, times(1)).onNext("one"); - inOrder.verify(aObserver, times(1)).onNext("two"); - inOrder.verify(aObserver, times(1)).onNext("three"); - inOrder.verify(aObserver, times(1)).onNext("four"); - inOrder.verify(aObserver, never()).onNext("five"); - inOrder.verify(aObserver, never()).onNext("six"); - inOrder.verify(aObserver, never()).onCompleted(); - - } - - /** - * All observables will be running in different threads so subscribe() is unblocked. CountDownLatch is only used in order to call unsubscribe() in a predictable manner. - */ - @Test - public void testConcatUnsubscribeConcurrent() { - final CountDownLatch callOnce = new CountDownLatch(1); - final CountDownLatch okToContinue = new CountDownLatch(1); - final TestObservable w1 = new TestObservable("one", "two", "three"); - final TestObservable w2 = new TestObservable(callOnce, okToContinue, "four", "five", "six"); - - @SuppressWarnings("unchecked") - Observer aObserver = mock(Observer.class); - @SuppressWarnings("unchecked") - TestObservable> observableOfObservables = new TestObservable>(Observable.create(w1), Observable.create(w2)); - OnSubscribeFunc concatF = concat(Observable.create(observableOfObservables)); - - Observable concat = Observable.create(concatF); - - Subscription s1 = concat.subscribe(aObserver); - - try { - //Block main thread to allow observable "w1" to complete and observable "w2" to call onNext exactly once. - callOnce.await(); - //"four" from w2 has been processed by onNext() - s1.unsubscribe(); - //"five" and "six" will NOT be processed by onNext() - //Unblock the observable to continue. - okToContinue.countDown(); - w1.t.join(); - w2.t.join(); - } catch (Throwable e) { - e.printStackTrace(); - fail(e.getMessage()); - } - - InOrder inOrder = inOrder(aObserver); - inOrder.verify(aObserver, times(1)).onNext("one"); - inOrder.verify(aObserver, times(1)).onNext("two"); - inOrder.verify(aObserver, times(1)).onNext("three"); - inOrder.verify(aObserver, times(1)).onNext("four"); - inOrder.verify(aObserver, never()).onNext("five"); - inOrder.verify(aObserver, never()).onNext("six"); - verify(aObserver, never()).onCompleted(); - verify(aObserver, never()).onError(any(Throwable.class)); - } - - private static class TestObservable implements OnSubscribeFunc { - - private final Subscription s = new Subscription() { - - @Override - public void unsubscribe() { - subscribed = false; - } - - }; - private final List values; - private Thread t = null; - private int count = 0; - private boolean subscribed = true; - private final CountDownLatch once; - private final CountDownLatch okToContinue; - private final T seed; - private final int size; - - public TestObservable(T... values) { - this(null, null, values); - } - - public TestObservable(CountDownLatch once, CountDownLatch okToContinue, T... values) { - this.values = Arrays.asList(values); - this.size = this.values.size(); - this.once = once; - this.okToContinue = okToContinue; - this.seed = null; - } - - public TestObservable(T seed, int size) { - values = null; - once = null; - okToContinue = null; - this.seed = seed; - this.size = size; - } - - @Override - public Subscription onSubscribe(final Observer observer) { - t = new Thread(new Runnable() { - - @Override - public void run() { - try { - while (count < size && subscribed) { - if (null != values) - observer.onNext(values.get(count)); - else - observer.onNext(seed); - count++; - //Unblock the main thread to call unsubscribe. - if (null != once) - once.countDown(); - //Block until the main thread has called unsubscribe. - if (null != okToContinue) - okToContinue.await(5, TimeUnit.SECONDS); - } - if (subscribed) - observer.onCompleted(); - } catch (InterruptedException e) { - e.printStackTrace(); - fail(e.getMessage()); - } - } - - }); - t.start(); - return s; - } - - } - - } } diff --git a/rxjava-core/src/main/java/rx/operators/OperationDebounce.java b/rxjava-core/src/main/java/rx/operators/OperationDebounce.java index d225477069..ebbcbc8ad1 100644 --- a/rxjava-core/src/main/java/rx/operators/OperationDebounce.java +++ b/rxjava-core/src/main/java/rx/operators/OperationDebounce.java @@ -15,27 +15,18 @@ */ package rx.operators; -import static org.mockito.Matchers.*; -import static org.mockito.Mockito.*; - -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicReference; - -import org.junit.Before; -import org.junit.Test; -import org.mockito.InOrder; - import rx.Observable; import rx.Observable.OnSubscribeFunc; import rx.Observer; import rx.Scheduler; import rx.Subscription; import rx.concurrency.Schedulers; -import rx.concurrency.TestScheduler; -import rx.subscriptions.Subscriptions; import rx.util.functions.Action0; import rx.util.functions.Func1; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicReference; + /** * This operation is used to filter out bursts of events. This is done by ignoring the events from an observable which are too * quickly followed up with other values. Values which are not followed up by other values within the specified timeout are published @@ -160,135 +151,4 @@ public void call() { } } } - - public static class UnitTest { - - private TestScheduler scheduler; - private Observer observer; - - @Before - @SuppressWarnings("unchecked") - public void before() { - scheduler = new TestScheduler(); - observer = mock(Observer.class); - } - - @Test - public void testDebounceWithCompleted() { - Observable source = Observable.create(new OnSubscribeFunc() { - @Override - public Subscription onSubscribe(Observer observer) { - publishNext(observer, 100, "one"); // Should be skipped since "two" will arrive before the timeout expires. - publishNext(observer, 400, "two"); // Should be published since "three" will arrive after the timeout expires. - publishNext(observer, 900, "three"); // Should be skipped since onCompleted will arrive before the timeout expires. - publishCompleted(observer, 1000); // Should be published as soon as the timeout expires. - - return Subscriptions.empty(); - } - }); - - Observable sampled = Observable.create(OperationDebounce.debounce(source, 400, TimeUnit.MILLISECONDS, scheduler)); - sampled.subscribe(observer); - - scheduler.advanceTimeTo(0, TimeUnit.MILLISECONDS); - InOrder inOrder = inOrder(observer); - // must go to 800 since it must be 400 after when two is sent, which is at 400 - scheduler.advanceTimeTo(800, TimeUnit.MILLISECONDS); - inOrder.verify(observer, times(1)).onNext("two"); - scheduler.advanceTimeTo(1000, TimeUnit.MILLISECONDS); - inOrder.verify(observer, times(1)).onCompleted(); - inOrder.verifyNoMoreInteractions(); - } - - @Test - public void testDebounceNeverEmits() { - Observable source = Observable.create(new OnSubscribeFunc() { - @Override - public Subscription onSubscribe(Observer observer) { - // all should be skipped since they are happening faster than the 200ms timeout - publishNext(observer, 100, "a"); // Should be skipped - publishNext(observer, 200, "b"); // Should be skipped - publishNext(observer, 300, "c"); // Should be skipped - publishNext(observer, 400, "d"); // Should be skipped - publishNext(observer, 500, "e"); // Should be skipped - publishNext(observer, 600, "f"); // Should be skipped - publishNext(observer, 700, "g"); // Should be skipped - publishNext(observer, 800, "h"); // Should be skipped - publishCompleted(observer, 900); // Should be published as soon as the timeout expires. - - return Subscriptions.empty(); - } - }); - - Observable sampled = Observable.create(OperationDebounce.debounce(source, 200, TimeUnit.MILLISECONDS, scheduler)); - sampled.subscribe(observer); - - scheduler.advanceTimeTo(0, TimeUnit.MILLISECONDS); - InOrder inOrder = inOrder(observer); - inOrder.verify(observer, times(0)).onNext(anyString()); - scheduler.advanceTimeTo(1000, TimeUnit.MILLISECONDS); - inOrder.verify(observer, times(1)).onCompleted(); - inOrder.verifyNoMoreInteractions(); - } - - @Test - public void testDebounceWithError() { - Observable source = Observable.create(new OnSubscribeFunc() { - @Override - public Subscription onSubscribe(Observer observer) { - Exception error = new TestException(); - publishNext(observer, 100, "one"); // Should be published since "two" will arrive after the timeout expires. - publishNext(observer, 600, "two"); // Should be skipped since onError will arrive before the timeout expires. - publishError(observer, 700, error); // Should be published as soon as the timeout expires. - - return Subscriptions.empty(); - } - }); - - Observable sampled = Observable.create(OperationDebounce.debounce(source, 400, TimeUnit.MILLISECONDS, scheduler)); - sampled.subscribe(observer); - - scheduler.advanceTimeTo(0, TimeUnit.MILLISECONDS); - InOrder inOrder = inOrder(observer); - // 100 + 400 means it triggers at 500 - scheduler.advanceTimeTo(500, TimeUnit.MILLISECONDS); - inOrder.verify(observer).onNext("one"); - scheduler.advanceTimeTo(701, TimeUnit.MILLISECONDS); - inOrder.verify(observer).onError(any(TestException.class)); - inOrder.verifyNoMoreInteractions(); - } - - private void publishCompleted(final Observer observer, long delay) { - scheduler.schedule(new Action0() { - @Override - public void call() { - observer.onCompleted(); - } - }, delay, TimeUnit.MILLISECONDS); - } - - private void publishError(final Observer observer, long delay, final Exception error) { - scheduler.schedule(new Action0() { - @Override - public void call() { - observer.onError(error); - } - }, delay, TimeUnit.MILLISECONDS); - } - - private void publishNext(final Observer observer, final long delay, final T value) { - scheduler.schedule(new Action0() { - @Override - public void call() { - observer.onNext(value); - } - }, delay, TimeUnit.MILLISECONDS); - } - - @SuppressWarnings("serial") - private class TestException extends Exception { - } - - } - } diff --git a/rxjava-core/src/main/java/rx/operators/OperationDefaultIfEmpty.java b/rxjava-core/src/main/java/rx/operators/OperationDefaultIfEmpty.java index 195422dadc..cfe7f27a2f 100644 --- a/rxjava-core/src/main/java/rx/operators/OperationDefaultIfEmpty.java +++ b/rxjava-core/src/main/java/rx/operators/OperationDefaultIfEmpty.java @@ -1,12 +1,5 @@ package rx.operators; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.never; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; - -import org.junit.Test; - import rx.Observable; import rx.Observable.OnSubscribeFunc; import rx.Observer; @@ -82,41 +75,4 @@ public void onCompleted() { })); } } - - public static class UnitTest { - - @Test - public void testDefaultIfEmpty() { - Observable source = Observable.from(1, 2, 3); - Observable observable = Observable.create(defaultIfEmpty( - source, 10)); - - @SuppressWarnings("unchecked") - Observer aObserver = mock(Observer.class); - observable.subscribe(aObserver); - verify(aObserver, never()).onNext(10); - verify(aObserver, times(1)).onNext(1); - verify(aObserver, times(1)).onNext(2); - verify(aObserver, times(1)).onNext(3); - verify(aObserver, never()).onError( - org.mockito.Matchers.any(Throwable.class)); - verify(aObserver, times(1)).onCompleted(); - } - - @Test - public void testDefaultIfEmptyWithEmpty() { - Observable source = Observable.empty(); - Observable observable = Observable.create(defaultIfEmpty( - source, 10)); - - @SuppressWarnings("unchecked") - Observer aObserver = mock(Observer.class); - observable.subscribe(aObserver); - verify(aObserver, times(1)).onNext(10); - verify(aObserver, never()).onError( - org.mockito.Matchers.any(Throwable.class)); - verify(aObserver, times(1)).onCompleted(); - } - - } } diff --git a/rxjava-core/src/main/java/rx/operators/OperationDefer.java b/rxjava-core/src/main/java/rx/operators/OperationDefer.java index 4be1ff01df..0d326b364e 100644 --- a/rxjava-core/src/main/java/rx/operators/OperationDefer.java +++ b/rxjava-core/src/main/java/rx/operators/OperationDefer.java @@ -15,10 +15,6 @@ */ package rx.operators; -import static org.mockito.Mockito.*; - -import org.junit.Test; - import rx.Observable; import rx.Observable.OnSubscribeFunc; import rx.Observer; @@ -48,43 +44,4 @@ public Subscription onSubscribe(Observer observer) { }; } - - public static class UnitTest { - @Test - @SuppressWarnings("unchecked") - public void testDefer() throws Throwable { - - Func0> factory = mock(Func0.class); - - Observable firstObservable = Observable.from("one", "two"); - Observable secondObservable = Observable.from("three", "four"); - when(factory.call()).thenReturn(firstObservable, secondObservable); - - Observable deferred = Observable.defer(factory); - - verifyZeroInteractions(factory); - - Observer firstObserver = mock(Observer.class); - deferred.subscribe(firstObserver); - - verify(factory, times(1)).call(); - verify(firstObserver, times(1)).onNext("one"); - verify(firstObserver, times(1)).onNext("two"); - verify(firstObserver, times(0)).onNext("three"); - verify(firstObserver, times(0)).onNext("four"); - verify(firstObserver, times(1)).onCompleted(); - - Observer secondObserver = mock(Observer.class); - deferred.subscribe(secondObserver); - - verify(factory, times(2)).call(); - verify(secondObserver, times(0)).onNext("one"); - verify(secondObserver, times(0)).onNext("two"); - verify(secondObserver, times(1)).onNext("three"); - verify(secondObserver, times(1)).onNext("four"); - verify(secondObserver, times(1)).onCompleted(); - - } - } - } diff --git a/rxjava-core/src/main/java/rx/operators/OperationDematerialize.java b/rxjava-core/src/main/java/rx/operators/OperationDematerialize.java index 529c507b14..8e958cbc14 100644 --- a/rxjava-core/src/main/java/rx/operators/OperationDematerialize.java +++ b/rxjava-core/src/main/java/rx/operators/OperationDematerialize.java @@ -15,11 +15,6 @@ */ package rx.operators; -import static org.mockito.Matchers.*; -import static org.mockito.Mockito.*; - -import org.junit.Test; - import rx.Notification; import rx.Observable; import rx.Observable.OnSubscribeFunc; @@ -85,52 +80,4 @@ public void onNext(Notification value) { }); } } - - public static class UnitTest { - - @Test - @SuppressWarnings("unchecked") - public void testDematerialize1() { - Observable> notifications = Observable.from(1, 2).materialize(); - Observable dematerialize = notifications.dematerialize(); - - Observer aObserver = mock(Observer.class); - dematerialize.subscribe(aObserver); - - verify(aObserver, times(1)).onNext(1); - verify(aObserver, times(1)).onNext(2); - verify(aObserver, times(1)).onCompleted(); - verify(aObserver, never()).onError(any(Throwable.class)); - } - - @Test - @SuppressWarnings("unchecked") - public void testDematerialize2() { - Throwable exception = new Throwable("test"); - Observable observable = Observable.error(exception); - Observable dematerialize = Observable.create(dematerialize(observable.materialize())); - - Observer aObserver = mock(Observer.class); - dematerialize.subscribe(aObserver); - - verify(aObserver, times(1)).onError(exception); - verify(aObserver, times(0)).onCompleted(); - verify(aObserver, times(0)).onNext(any(Integer.class)); - } - - @Test - @SuppressWarnings("unchecked") - public void testDematerialize3() { - Exception exception = new Exception("test"); - Observable observable = Observable.error(exception); - Observable dematerialize = Observable.create(dematerialize(observable.materialize())); - - Observer aObserver = mock(Observer.class); - dematerialize.subscribe(aObserver); - - verify(aObserver, times(1)).onError(exception); - verify(aObserver, times(0)).onCompleted(); - verify(aObserver, times(0)).onNext(any(Integer.class)); - } - } } diff --git a/rxjava-core/src/main/java/rx/operators/OperationDistinct.java b/rxjava-core/src/main/java/rx/operators/OperationDistinct.java index b56f0cd22f..9c0bccce2c 100644 --- a/rxjava-core/src/main/java/rx/operators/OperationDistinct.java +++ b/rxjava-core/src/main/java/rx/operators/OperationDistinct.java @@ -15,24 +15,6 @@ */ package rx.operators; -import static org.mockito.Matchers.*; -import static org.mockito.Mockito.*; -import static org.mockito.MockitoAnnotations.initMocks; -import static rx.Observable.create; -import static rx.Observable.empty; -import static rx.Observable.from; - -import java.util.ArrayList; -import java.util.Comparator; -import java.util.HashSet; -import java.util.List; -import java.util.Set; - -import org.junit.Before; -import org.junit.Test; -import org.mockito.InOrder; -import org.mockito.Mock; - import rx.Observable; import rx.Observable.OnSubscribeFunc; import rx.Observer; @@ -42,6 +24,8 @@ import rx.util.functions.Func1; import rx.util.functions.Functions; +import java.util.*; + /** * Returns an Observable that emits all distinct items emitted by the source. * @@ -192,166 +176,4 @@ public void call() { }); } } - - public static class UnitTest { - @Mock - Observer w; - @Mock - Observer w2; - - // nulls lead to exceptions - final Func1 TO_UPPER_WITH_EXCEPTION = new Func1() { - @Override - public String call(String s) { - if (s.equals("x")) { - return "XX"; - } - return s.toUpperCase(); - } - }; - - final Comparator COMPARE_LENGTH = new Comparator() { - @Override - public int compare(String s1, String s2) { - return s1.length() - s2.length(); - } - }; - - @Before - public void before() { - initMocks(this); - } - - @Test - public void testDistinctOfNone() { - Observable src = empty(); - create(distinct(src)).subscribe(w); - - verify(w, never()).onNext(anyString()); - verify(w, never()).onError(any(Throwable.class)); - verify(w, times(1)).onCompleted(); - } - - @Test - public void testDistinctOfNoneWithKeySelector() { - Observable src = empty(); - create(distinct(src, TO_UPPER_WITH_EXCEPTION)).subscribe(w); - - verify(w, never()).onNext(anyString()); - verify(w, never()).onError(any(Throwable.class)); - verify(w, times(1)).onCompleted(); - } - - @Test - public void testDistinctOfNormalSource() { - Observable src = from("a", "b", "c", "c", "c", "b", "b", "a", "e"); - create(distinct(src)).subscribe(w); - - InOrder inOrder = inOrder(w); - inOrder.verify(w, times(1)).onNext("a"); - inOrder.verify(w, times(1)).onNext("b"); - inOrder.verify(w, times(1)).onNext("c"); - inOrder.verify(w, times(1)).onNext("e"); - inOrder.verify(w, times(1)).onCompleted(); - inOrder.verify(w, never()).onNext(anyString()); - verify(w, never()).onError(any(Throwable.class)); - } - - @Test - public void testDistinctOfNormalSourceWithKeySelector() { - Observable src = from("a", "B", "c", "C", "c", "B", "b", "a", "E"); - create(distinct(src, TO_UPPER_WITH_EXCEPTION)).subscribe(w); - - InOrder inOrder = inOrder(w); - inOrder.verify(w, times(1)).onNext("a"); - inOrder.verify(w, times(1)).onNext("B"); - inOrder.verify(w, times(1)).onNext("c"); - inOrder.verify(w, times(1)).onNext("E"); - inOrder.verify(w, times(1)).onCompleted(); - inOrder.verify(w, never()).onNext(anyString()); - verify(w, never()).onError(any(Throwable.class)); - } - - @Test - public void testDistinctOfNormalSourceWithComparator() { - Observable src = from("1", "12", "123", "aaa", "321", "12", "21", "1", "12345"); - create(distinct(src, COMPARE_LENGTH)).subscribe(w); - - InOrder inOrder = inOrder(w); - inOrder.verify(w, times(1)).onNext("1"); - inOrder.verify(w, times(1)).onNext("12"); - inOrder.verify(w, times(1)).onNext("123"); - inOrder.verify(w, times(1)).onNext("12345"); - inOrder.verify(w, times(1)).onCompleted(); - inOrder.verify(w, never()).onNext(anyString()); - verify(w, never()).onError(any(Throwable.class)); - } - - @Test - public void testDistinctOfNormalSourceWithKeySelectorAndComparator() { - Observable src = from("a", "x", "ab", "abc", "cba", "de", "x", "a", "abcd"); - create(distinct(src, TO_UPPER_WITH_EXCEPTION, COMPARE_LENGTH)).subscribe(w); - - InOrder inOrder = inOrder(w); - inOrder.verify(w, times(1)).onNext("a"); - inOrder.verify(w, times(1)).onNext("x"); - inOrder.verify(w, times(1)).onNext("abc"); - inOrder.verify(w, times(1)).onNext("abcd"); - inOrder.verify(w, times(1)).onCompleted(); - inOrder.verify(w, never()).onNext(anyString()); - verify(w, never()).onError(any(Throwable.class)); - } - - @Test - public void testDistinctOfNormalSourceWithKeySelectorAndComparatorAndTwoSubscriptions() { - Observable src = from("a", "x", "ab", "abc", "cba", "de", "x", "a", "abcd"); - create(distinct(src, TO_UPPER_WITH_EXCEPTION, COMPARE_LENGTH)).subscribe(w); - - InOrder inOrder = inOrder(w); - inOrder.verify(w, times(1)).onNext("a"); - inOrder.verify(w, times(1)).onNext("x"); - create(distinct(src, TO_UPPER_WITH_EXCEPTION, COMPARE_LENGTH)).subscribe(w2); - inOrder.verify(w, times(1)).onNext("abc"); - inOrder.verify(w, times(1)).onNext("abcd"); - inOrder.verify(w, times(1)).onCompleted(); - inOrder.verify(w, never()).onNext(anyString()); - verify(w, never()).onError(any(Throwable.class)); - - InOrder inOrder2 = inOrder(w2); - inOrder2.verify(w2, times(1)).onNext("a"); - inOrder2.verify(w2, times(1)).onNext("x"); - inOrder2.verify(w2, times(1)).onNext("abc"); - inOrder2.verify(w2, times(1)).onNext("abcd"); - inOrder2.verify(w2, times(1)).onCompleted(); - inOrder2.verify(w2, never()).onNext(anyString()); - verify(w2, never()).onError(any(Throwable.class)); - } - - @Test - public void testDistinctOfSourceWithNulls() { - Observable src = from(null, "a", "a", null, null, "b", null); - create(distinct(src)).subscribe(w); - - InOrder inOrder = inOrder(w); - inOrder.verify(w, times(1)).onNext(null); - inOrder.verify(w, times(1)).onNext("a"); - inOrder.verify(w, times(1)).onNext("b"); - inOrder.verify(w, times(1)).onCompleted(); - inOrder.verify(w, never()).onNext(anyString()); - verify(w, never()).onError(any(Throwable.class)); - } - - @Test - public void testDistinctOfSourceWithExceptionsFromKeySelector() { - Observable src = from("a", "b", null, "c"); - create(distinct(src, TO_UPPER_WITH_EXCEPTION)).subscribe(w); - - InOrder inOrder = inOrder(w); - inOrder.verify(w, times(1)).onNext("a"); - inOrder.verify(w, times(1)).onNext("b"); - inOrder.verify(w, times(1)).onError(any(NullPointerException.class)); - inOrder.verify(w, never()).onNext(anyString()); - inOrder.verify(w, never()).onCompleted(); - } - } } diff --git a/rxjava-core/src/main/java/rx/operators/OperationDistinctUntilChanged.java b/rxjava-core/src/main/java/rx/operators/OperationDistinctUntilChanged.java index c43edc0202..d1ea86b653 100644 --- a/rxjava-core/src/main/java/rx/operators/OperationDistinctUntilChanged.java +++ b/rxjava-core/src/main/java/rx/operators/OperationDistinctUntilChanged.java @@ -15,20 +15,6 @@ */ package rx.operators; -import static org.mockito.Matchers.*; -import static org.mockito.Mockito.*; -import static org.mockito.MockitoAnnotations.initMocks; -import static rx.Observable.create; -import static rx.Observable.empty; -import static rx.Observable.from; - -import java.util.Comparator; - -import org.junit.Before; -import org.junit.Test; -import org.mockito.InOrder; -import org.mockito.Mock; - import rx.Observable; import rx.Observable.OnSubscribeFunc; import rx.Observer; @@ -38,6 +24,8 @@ import rx.util.functions.Func1; import rx.util.functions.Functions; +import java.util.Comparator; + /** * Returns an Observable that emits all sequentially distinct items emitted by the source. */ @@ -152,169 +140,4 @@ public void call() { }); } } - - public static class UnitTest { - @Mock - Observer w; - @Mock - Observer w2; - - // nulls lead to exceptions - final Func1 TO_UPPER_WITH_EXCEPTION = new Func1() { - @Override - public String call(String s) { - if (s.equals("x")) { - return "xx"; - } - return s.toUpperCase(); - } - }; - - final Comparator COMPARE_LENGTH = new Comparator() { - @Override - public int compare(String s1, String s2) { - return s1.length() - s2.length(); - } - }; - - @Before - public void before() { - initMocks(this); - } - - @Test - public void testDistinctUntilChangedOfNone() { - Observable src = empty(); - create(distinctUntilChanged(src)).subscribe(w); - - verify(w, never()).onNext(anyString()); - verify(w, never()).onError(any(Throwable.class)); - verify(w, times(1)).onCompleted(); - } - - @Test - public void testDistinctUntilChangedOfNoneWithKeySelector() { - Observable src = empty(); - create(distinctUntilChanged(src, TO_UPPER_WITH_EXCEPTION)).subscribe(w); - - verify(w, never()).onNext(anyString()); - verify(w, never()).onError(any(Throwable.class)); - verify(w, times(1)).onCompleted(); - } - - @Test - public void testDistinctUntilChangedOfNormalSource() { - Observable src = from("a", "b", "c", "c", "c", "b", "b", "a", "e"); - create(distinctUntilChanged(src)).subscribe(w); - - InOrder inOrder = inOrder(w); - inOrder.verify(w, times(1)).onNext("a"); - inOrder.verify(w, times(1)).onNext("b"); - inOrder.verify(w, times(1)).onNext("c"); - inOrder.verify(w, times(1)).onNext("b"); - inOrder.verify(w, times(1)).onNext("a"); - inOrder.verify(w, times(1)).onNext("e"); - inOrder.verify(w, times(1)).onCompleted(); - inOrder.verify(w, never()).onNext(anyString()); - verify(w, never()).onError(any(Throwable.class)); - } - - @Test - public void testDistinctUntilChangedOfNormalSourceWithKeySelector() { - Observable src = from("a", "b", "c", "C", "c", "B", "b", "a", "e"); - create(distinctUntilChanged(src, TO_UPPER_WITH_EXCEPTION)).subscribe(w); - - InOrder inOrder = inOrder(w); - inOrder.verify(w, times(1)).onNext("a"); - inOrder.verify(w, times(1)).onNext("b"); - inOrder.verify(w, times(1)).onNext("c"); - inOrder.verify(w, times(1)).onNext("B"); - inOrder.verify(w, times(1)).onNext("a"); - inOrder.verify(w, times(1)).onNext("e"); - inOrder.verify(w, times(1)).onCompleted(); - inOrder.verify(w, never()).onNext(anyString()); - verify(w, never()).onError(any(Throwable.class)); - } - - @Test - public void testDistinctUntilChangedOfSourceWithNulls() { - Observable src = from(null, "a", "a", null, null, "b", null, null); - create(distinctUntilChanged(src)).subscribe(w); - - InOrder inOrder = inOrder(w); - inOrder.verify(w, times(1)).onNext(null); - inOrder.verify(w, times(1)).onNext("a"); - inOrder.verify(w, times(1)).onNext(null); - inOrder.verify(w, times(1)).onNext("b"); - inOrder.verify(w, times(1)).onNext(null); - inOrder.verify(w, times(1)).onCompleted(); - inOrder.verify(w, never()).onNext(anyString()); - verify(w, never()).onError(any(Throwable.class)); - } - - @Test - public void testDistinctUntilChangedOfSourceWithExceptionsFromKeySelector() { - Observable src = from("a", "b", null, "c"); - create(distinctUntilChanged(src, TO_UPPER_WITH_EXCEPTION)).subscribe(w); - - InOrder inOrder = inOrder(w); - inOrder.verify(w, times(1)).onNext("a"); - inOrder.verify(w, times(1)).onNext("b"); - verify(w, times(1)).onError(any(NullPointerException.class)); - inOrder.verify(w, never()).onNext(anyString()); - inOrder.verify(w, never()).onCompleted(); - } - - @Test - public void testDistinctUntilChangedWithComparator() { - Observable src = from("a", "b", "c", "aa", "bb", "c", "ddd"); - create(distinctUntilChanged(src, COMPARE_LENGTH)).subscribe(w); - InOrder inOrder = inOrder(w); - inOrder.verify(w, times(1)).onNext("a"); - inOrder.verify(w, times(1)).onNext("aa"); - inOrder.verify(w, times(1)).onNext("c"); - inOrder.verify(w, times(1)).onNext("ddd"); - inOrder.verify(w, times(1)).onCompleted(); - inOrder.verify(w, never()).onNext(anyString()); - verify(w, never()).onError(any(Throwable.class)); - } - - @Test - public void testDistinctUntilChangedWithComparatorAndKeySelector() { - Observable src = from("a", "b", "x", "aa", "bb", "c", "ddd"); - create(distinctUntilChanged(src, TO_UPPER_WITH_EXCEPTION, COMPARE_LENGTH)).subscribe(w); - InOrder inOrder = inOrder(w); - inOrder.verify(w, times(1)).onNext("a"); - inOrder.verify(w, times(1)).onNext("x"); - inOrder.verify(w, times(1)).onNext("c"); - inOrder.verify(w, times(1)).onNext("ddd"); - inOrder.verify(w, times(1)).onCompleted(); - inOrder.verify(w, never()).onNext(anyString()); - verify(w, never()).onError(any(Throwable.class)); - } - - @Test - public void testDistinctUntilChangedWithComparatorAndKeySelectorandTwoSubscriptions() { - Observable src = from("a", "b", "x", "aa", "bb", "c", "ddd"); - create(distinctUntilChanged(src, TO_UPPER_WITH_EXCEPTION, COMPARE_LENGTH)).subscribe(w); - InOrder inOrder = inOrder(w); - inOrder.verify(w, times(1)).onNext("a"); - inOrder.verify(w, times(1)).onNext("x"); - create(distinctUntilChanged(src, TO_UPPER_WITH_EXCEPTION, COMPARE_LENGTH)).subscribe(w2); - inOrder.verify(w, times(1)).onNext("c"); - inOrder.verify(w, times(1)).onNext("ddd"); - inOrder.verify(w, times(1)).onCompleted(); - inOrder.verify(w, never()).onNext(anyString()); - verify(w, never()).onError(any(Throwable.class)); - - InOrder inOrder2 = inOrder(w2); - inOrder2.verify(w2, times(1)).onNext("a"); - inOrder2.verify(w2, times(1)).onNext("x"); - inOrder2.verify(w2, times(1)).onNext("c"); - inOrder2.verify(w2, times(1)).onNext("ddd"); - inOrder2.verify(w2, times(1)).onCompleted(); - inOrder2.verify(w2, never()).onNext(anyString()); - verify(w2, never()).onError(any(Throwable.class)); - } - } } diff --git a/rxjava-core/src/main/java/rx/operators/OperationElementAt.java b/rxjava-core/src/main/java/rx/operators/OperationElementAt.java index 0d91709be1..c1310bc013 100644 --- a/rxjava-core/src/main/java/rx/operators/OperationElementAt.java +++ b/rxjava-core/src/main/java/rx/operators/OperationElementAt.java @@ -15,25 +15,13 @@ */ package rx.operators; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.any; -import static org.mockito.Mockito.never; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; - -import java.util.Iterator; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.atomic.AtomicInteger; - -import org.junit.Test; - import rx.Observable; import rx.Observable.OnSubscribeFunc; import rx.Observer; import rx.Subscription; +import java.util.concurrent.atomic.AtomicInteger; + /** * Returns the element at a specified index in a sequence. */ @@ -146,102 +134,4 @@ public void onCompleted() { })); } } - - public static class UnitTest { - - @Test - public void testElementAt() { - Observable w = Observable.from(1, 2); - Observable observable = Observable.create(elementAt(w, 1)); - - @SuppressWarnings("unchecked") - Observer aObserver = mock(Observer.class); - observable.subscribe(aObserver); - verify(aObserver, never()).onNext(1); - verify(aObserver, times(1)).onNext(2); - verify(aObserver, never()).onError( - any(Throwable.class)); - verify(aObserver, times(1)).onCompleted(); - } - - @Test - public void testElementAtWithMinusIndex() { - Observable w = Observable.from(1, 2); - Observable observable = Observable - .create(elementAt(w, -1)); - - try { - Iterator iter = OperationToIterator - .toIterator(observable); - assertTrue(iter.hasNext()); - iter.next(); - fail("expect an IndexOutOfBoundsException when index is out of bounds"); - } catch (IndexOutOfBoundsException e) { - } - } - - @Test - public void testElementAtWithIndexOutOfBounds() - throws InterruptedException, ExecutionException { - Observable w = Observable.from(1, 2); - Observable observable = Observable.create(elementAt(w, 2)); - try { - Iterator iter = OperationToIterator - .toIterator(observable); - assertTrue(iter.hasNext()); - iter.next(); - fail("expect an IndexOutOfBoundsException when index is out of bounds"); - } catch (IndexOutOfBoundsException e) { - } - } - - @Test - public void testElementAtOrDefault() throws InterruptedException, - ExecutionException { - Observable w = Observable.from(1, 2); - Observable observable = Observable - .create(elementAtOrDefault(w, 1, 0)); - - @SuppressWarnings("unchecked") - Observer aObserver = mock(Observer.class); - observable.subscribe(aObserver); - verify(aObserver, never()).onNext(1); - verify(aObserver, times(1)).onNext(2); - verify(aObserver, never()).onError(any(Throwable.class)); - verify(aObserver, times(1)).onCompleted(); - } - - @Test - public void testElementAtOrDefaultWithIndexOutOfBounds() - throws InterruptedException, ExecutionException { - Observable w = Observable.from(1, 2); - Observable observable = Observable - .create(elementAtOrDefault(w, 2, 0)); - - @SuppressWarnings("unchecked") - Observer aObserver = mock(Observer.class); - observable.subscribe(aObserver); - verify(aObserver, never()).onNext(1); - verify(aObserver, never()).onNext(2); - verify(aObserver, times(1)).onNext(0); - verify(aObserver, never()).onError(any(Throwable.class)); - verify(aObserver, times(1)).onCompleted(); - } - - @Test - public void testElementAtOrDefaultWithMinusIndex() { - Observable w = Observable.from(1, 2); - Observable observable = Observable - .create(elementAtOrDefault(w, -1, 0)); - - try { - Iterator iter = OperationToIterator - .toIterator(observable); - assertTrue(iter.hasNext()); - iter.next(); - fail("expect an IndexOutOfBoundsException when index is out of bounds"); - } catch (IndexOutOfBoundsException e) { - } - } - } } diff --git a/rxjava-core/src/main/java/rx/operators/OperationFilter.java b/rxjava-core/src/main/java/rx/operators/OperationFilter.java index 5026f11d0c..560600dc9c 100644 --- a/rxjava-core/src/main/java/rx/operators/OperationFilter.java +++ b/rxjava-core/src/main/java/rx/operators/OperationFilter.java @@ -15,12 +15,6 @@ */ package rx.operators; -import static org.mockito.Matchers.*; -import static org.mockito.Mockito.*; - -import org.junit.Test; -import org.mockito.Mockito; - import rx.Observable; import rx.Observable.OnSubscribeFunc; import rx.Observer; @@ -74,28 +68,4 @@ public void onCompleted() { } } - - public static class UnitTest { - - @Test - public void testFilter() { - Observable w = Observable.from("one", "two", "three"); - Observable observable = Observable.create(filter(w, new Func1() { - - @Override - public Boolean call(String t1) { - return t1.equals("two"); - } - })); - - @SuppressWarnings("unchecked") - Observer aObserver = mock(Observer.class); - observable.subscribe(aObserver); - verify(aObserver, Mockito.never()).onNext("one"); - verify(aObserver, times(1)).onNext("two"); - verify(aObserver, Mockito.never()).onNext("three"); - verify(aObserver, Mockito.never()).onError(any(Throwable.class)); - verify(aObserver, times(1)).onCompleted(); - } - } } diff --git a/rxjava-core/src/main/java/rx/operators/OperationFinally.java b/rxjava-core/src/main/java/rx/operators/OperationFinally.java index ad711b08ca..6e4d58768a 100644 --- a/rxjava-core/src/main/java/rx/operators/OperationFinally.java +++ b/rxjava-core/src/main/java/rx/operators/OperationFinally.java @@ -15,11 +15,6 @@ */ package rx.operators; -import static org.mockito.Mockito.*; - -import org.junit.Before; -import org.junit.Test; - import rx.Observable; import rx.Observable.OnSubscribeFunc; import rx.Observer; @@ -105,31 +100,4 @@ public void onNext(T args) { } } } - - public static class UnitTest { - private Action0 aAction0; - private Observer aObserver; - - @SuppressWarnings("unchecked") // mocking has to be unchecked, unfortunately - @Before - public void before() { - aAction0 = mock(Action0.class); - aObserver = mock(Observer.class); - } - - private void checkActionCalled(Observable input) { - Observable.create(finallyDo(input, aAction0)).subscribe(aObserver); - verify(aAction0, times(1)).call(); - } - - @Test - public void testFinallyCalledOnComplete() { - checkActionCalled(Observable.from(new String[] {"1", "2", "3"})); - } - - @Test - public void testFinallyCalledOnError() { - checkActionCalled(Observable.error(new RuntimeException("expected"))); - } - } } diff --git a/rxjava-core/src/main/java/rx/operators/OperationFirstOrDefault.java b/rxjava-core/src/main/java/rx/operators/OperationFirstOrDefault.java index 73283a8a3b..66dcb6e90d 100644 --- a/rxjava-core/src/main/java/rx/operators/OperationFirstOrDefault.java +++ b/rxjava-core/src/main/java/rx/operators/OperationFirstOrDefault.java @@ -15,20 +15,6 @@ */ package rx.operators; -import static org.mockito.Matchers.*; -import static org.mockito.Mockito.*; -import static org.mockito.MockitoAnnotations.initMocks; -import static rx.Observable.create; -import static rx.Observable.empty; -import static rx.Observable.from; -import static rx.util.functions.Functions.alwaysTrue; - -import java.util.concurrent.atomic.AtomicBoolean; - -import org.junit.Before; -import org.junit.Test; -import org.mockito.Mock; - import rx.Observable; import rx.Observable.OnSubscribeFunc; import rx.Observer; @@ -37,6 +23,10 @@ import rx.util.functions.Action0; import rx.util.functions.Func1; +import java.util.concurrent.atomic.AtomicBoolean; + +import static rx.util.functions.Functions.alwaysTrue; + /** * Returns an Observable that emits the first item emitted by the source * Observable, or a default value if the source emits nothing. @@ -126,65 +116,4 @@ public void call() { }); } } - - public static class UnitTest { - @Mock - Observer w; - - private static final Func1 IS_D = new Func1() { - @Override - public Boolean call(String value) { - return "d".equals(value); - } - }; - - @Before - public void before() { - initMocks(this); - } - - @Test - public void testFirstOrElseOfNone() { - Observable src = empty(); - create(firstOrDefault(src, "default")).subscribe(w); - - verify(w, times(1)).onNext(anyString()); - verify(w, times(1)).onNext("default"); - verify(w, never()).onError(any(Throwable.class)); - verify(w, times(1)).onCompleted(); - } - - @Test - public void testFirstOrElseOfSome() { - Observable src = from("a", "b", "c"); - create(firstOrDefault(src, "default")).subscribe(w); - - verify(w, times(1)).onNext(anyString()); - verify(w, times(1)).onNext("a"); - verify(w, never()).onError(any(Throwable.class)); - verify(w, times(1)).onCompleted(); - } - - @Test - public void testFirstOrElseWithPredicateOfNoneMatchingThePredicate() { - Observable src = from("a", "b", "c"); - create(firstOrDefault(src, IS_D, "default")).subscribe(w); - - verify(w, times(1)).onNext(anyString()); - verify(w, times(1)).onNext("default"); - verify(w, never()).onError(any(Throwable.class)); - verify(w, times(1)).onCompleted(); - } - - @Test - public void testFirstOrElseWithPredicateOfSome() { - Observable src = from("a", "b", "c", "d", "e", "f"); - create(firstOrDefault(src, IS_D, "default")).subscribe(w); - - verify(w, times(1)).onNext(anyString()); - verify(w, times(1)).onNext("d"); - verify(w, never()).onError(any(Throwable.class)); - verify(w, times(1)).onCompleted(); - } - } } diff --git a/rxjava-core/src/main/java/rx/operators/OperationGroupBy.java b/rxjava-core/src/main/java/rx/operators/OperationGroupBy.java index 96a6861406..e4311c5421 100644 --- a/rxjava-core/src/main/java/rx/operators/OperationGroupBy.java +++ b/rxjava-core/src/main/java/rx/operators/OperationGroupBy.java @@ -15,32 +15,19 @@ */ package rx.operators; -import static org.junit.Assert.*; - -import java.util.Arrays; -import java.util.Collection; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentLinkedQueue; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicBoolean; -import java.util.concurrent.atomic.AtomicInteger; -import java.util.concurrent.atomic.AtomicReference; - -import org.junit.Test; - import rx.Observable; import rx.Observable.OnSubscribeFunc; import rx.Observer; import rx.Subscription; import rx.observables.GroupedObservable; -import rx.subscriptions.BooleanSubscription; -import rx.subscriptions.Subscriptions; -import rx.util.functions.Action1; import rx.util.functions.Func1; import rx.util.functions.Functions; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.atomic.AtomicReference; + /** * Groups the items emitted by an Observable according to a specified criterion, and emits these * grouped items as Observables, one Observable per group. @@ -251,312 +238,4 @@ private KeyValue(K key, V value) { this.value = value; } } - - public static class UnitTest { - final Func1 length = new Func1() { - @Override - public Integer call(String s) { - return s.length(); - } - }; - - @Test - public void testGroupBy() { - Observable source = Observable.from("one", "two", "three", "four", "five", "six"); - Observable> grouped = Observable.create(groupBy(source, length)); - - Map> map = toMap(grouped); - - assertEquals(3, map.size()); - assertArrayEquals(Arrays.asList("one", "two", "six").toArray(), map.get(3).toArray()); - assertArrayEquals(Arrays.asList("four", "five").toArray(), map.get(4).toArray()); - assertArrayEquals(Arrays.asList("three").toArray(), map.get(5).toArray()); - } - - @Test - public void testEmpty() { - Observable source = Observable.empty(); - Observable> grouped = Observable.create(groupBy(source, length)); - - Map> map = toMap(grouped); - - assertTrue(map.isEmpty()); - } - - @Test - public void testError() { - Observable sourceStrings = Observable.from("one", "two", "three", "four", "five", "six"); - Observable errorSource = Observable.error(new RuntimeException("forced failure")); - Observable source = Observable.concat(sourceStrings, errorSource); - - Observable> grouped = Observable.create(groupBy(source, length)); - - final AtomicInteger groupCounter = new AtomicInteger(); - final AtomicInteger eventCounter = new AtomicInteger(); - final AtomicReference error = new AtomicReference(); - - grouped.mapMany(new Func1, Observable>() { - - @Override - public Observable call(final GroupedObservable o) { - groupCounter.incrementAndGet(); - return o.map(new Func1() { - - @Override - public String call(String v) { - return "Event => key: " + o.getKey() + " value: " + v; - } - }); - } - }).subscribe(new Observer() { - - @Override - public void onCompleted() { - - } - - @Override - public void onError(Throwable e) { - e.printStackTrace(); - error.set(e); - } - - @Override - public void onNext(String v) { - eventCounter.incrementAndGet(); - System.out.println(v); - - } - }); - - assertEquals(3, groupCounter.get()); - assertEquals(6, eventCounter.get()); - assertNotNull(error.get()); - } - - private static Map> toMap(Observable> observable) { - - final ConcurrentHashMap> result = new ConcurrentHashMap>(); - - observable.toBlockingObservable().forEach(new Action1>() { - - @Override - public void call(final GroupedObservable o) { - result.put(o.getKey(), new ConcurrentLinkedQueue()); - o.subscribe(new Action1() { - - @Override - public void call(V v) { - result.get(o.getKey()).add(v); - } - - }); - } - }); - - return result; - } - - /** - * Assert that only a single subscription to a stream occurs and that all events are received. - * - * @throws Throwable - */ - @Test - public void testGroupedEventStream() throws Throwable { - - final AtomicInteger eventCounter = new AtomicInteger(); - final AtomicInteger subscribeCounter = new AtomicInteger(); - final AtomicInteger groupCounter = new AtomicInteger(); - final CountDownLatch latch = new CountDownLatch(1); - final int count = 100; - final int groupCount = 2; - - Observable es = Observable.create(new OnSubscribeFunc() { - - @Override - public Subscription onSubscribe(final Observer observer) { - System.out.println("*** Subscribing to EventStream ***"); - subscribeCounter.incrementAndGet(); - new Thread(new Runnable() { - - @Override - public void run() { - for (int i = 0; i < count; i++) { - Event e = new Event(); - e.source = i % groupCount; - e.message = "Event-" + i; - observer.onNext(e); - } - observer.onCompleted(); - } - - }).start(); - return Subscriptions.empty(); - } - - }); - - es.groupBy(new Func1() { - - @Override - public Integer call(Event e) { - return e.source; - } - }).mapMany(new Func1, Observable>() { - - @Override - public Observable call(GroupedObservable eventGroupedObservable) { - System.out.println("GroupedObservable Key: " + eventGroupedObservable.getKey()); - groupCounter.incrementAndGet(); - - return eventGroupedObservable.map(new Func1() { - - @Override - public String call(Event event) { - return "Source: " + event.source + " Message: " + event.message; - } - }); - - } - }).subscribe(new Observer() { - - @Override - public void onCompleted() { - latch.countDown(); - } - - @Override - public void onError(Throwable e) { - e.printStackTrace(); - latch.countDown(); - } - - @Override - public void onNext(String outputMessage) { - System.out.println(outputMessage); - eventCounter.incrementAndGet(); - } - }); - - latch.await(5000, TimeUnit.MILLISECONDS); - assertEquals(1, subscribeCounter.get()); - assertEquals(groupCount, groupCounter.get()); - assertEquals(count, eventCounter.get()); - - } - - /* - * We will only take 1 group with 20 events from it and then unsubscribe. - */ - @Test - public void testUnsubscribe() throws InterruptedException { - - final AtomicInteger eventCounter = new AtomicInteger(); - final AtomicInteger subscribeCounter = new AtomicInteger(); - final AtomicInteger groupCounter = new AtomicInteger(); - final AtomicInteger sentEventCounter = new AtomicInteger(); - final CountDownLatch latch = new CountDownLatch(1); - final int count = 100; - final int groupCount = 2; - - Observable es = Observable.create(new OnSubscribeFunc() { - - @Override - public Subscription onSubscribe(final Observer observer) { - final BooleanSubscription s = new BooleanSubscription(); - System.out.println("testUnsubscribe => *** Subscribing to EventStream ***"); - subscribeCounter.incrementAndGet(); - new Thread(new Runnable() { - - @Override - public void run() { - for (int i = 0; i < count; i++) { - if (s.isUnsubscribed()) { - break; - } - Event e = new Event(); - e.source = i % groupCount; - e.message = "Event-" + i; - observer.onNext(e); - sentEventCounter.incrementAndGet(); - } - observer.onCompleted(); - } - - }).start(); - return s; - } - - }); - - es.groupBy(new Func1() { - - @Override - public Integer call(Event e) { - return e.source; - } - }) - .take(1) // we want only the first group - .mapMany(new Func1, Observable>() { - - @Override - public Observable call(GroupedObservable eventGroupedObservable) { - System.out.println("testUnsubscribe => GroupedObservable Key: " + eventGroupedObservable.getKey()); - groupCounter.incrementAndGet(); - - return eventGroupedObservable - .take(20) // limit to only 20 events on this group - .map(new Func1() { - - @Override - public String call(Event event) { - return "testUnsubscribe => Source: " + event.source + " Message: " + event.message; - } - }); - - } - }).subscribe(new Observer() { - - @Override - public void onCompleted() { - latch.countDown(); - } - - @Override - public void onError(Throwable e) { - e.printStackTrace(); - latch.countDown(); - } - - @Override - public void onNext(String outputMessage) { - System.out.println(outputMessage); - eventCounter.incrementAndGet(); - } - }); - - latch.await(5000, TimeUnit.MILLISECONDS); - assertEquals(1, subscribeCounter.get()); - assertEquals(1, groupCounter.get()); - assertEquals(20, eventCounter.get()); - // sentEvents will go until 'eventCounter' hits 20 and then unsubscribes - // which means it will also send (but ignore) the 19/20 events for the other group - // It will not however send all 100 events. - assertEquals(39, sentEventCounter.get(), 10); - // gave it a delta of 10 to account for the threading/unsubscription race condition which can vary depending on a machines performance, thread-scheduler, etc - } - - private static class Event { - int source; - String message; - - @Override - public String toString() { - return "Event => source: " + source + " message: " + message; - } - } - - } - } diff --git a/rxjava-core/src/main/java/rx/operators/OperationInterval.java b/rxjava-core/src/main/java/rx/operators/OperationInterval.java index 0711bff4a2..0c767eada7 100644 --- a/rxjava-core/src/main/java/rx/operators/OperationInterval.java +++ b/rxjava-core/src/main/java/rx/operators/OperationInterval.java @@ -15,27 +15,16 @@ */ package rx.operators; -import static org.mockito.Matchers.*; -import static org.mockito.Mockito.*; - -import java.util.concurrent.Executors; -import java.util.concurrent.TimeUnit; - -import org.junit.Before; -import org.junit.Test; -import org.mockito.InOrder; - -import rx.Observable; import rx.Observable.OnSubscribeFunc; import rx.Observer; import rx.Scheduler; import rx.Subscription; import rx.concurrency.Schedulers; -import rx.concurrency.TestScheduler; -import rx.observables.ConnectableObservable; import rx.subscriptions.Subscriptions; import rx.util.functions.Action0; +import java.util.concurrent.TimeUnit; + /** * Returns an observable sequence that produces a value after each period. * The value starts at 0 and counts up each period. @@ -94,163 +83,4 @@ public void call() { }); } } - - public static class UnitTest { - private TestScheduler scheduler; - private Observer observer; - private Observer observer2; - - @Before - @SuppressWarnings("unchecked") // due to mocking - public void before() { - scheduler = new TestScheduler(); - observer = mock(Observer.class); - observer2 = mock(Observer.class); - } - - @Test - public void testInterval() { - Observable w = Observable.create(OperationInterval.interval(1, TimeUnit.SECONDS, scheduler)); - Subscription sub = w.subscribe(observer); - - verify(observer, never()).onNext(0L); - verify(observer, never()).onCompleted(); - verify(observer, never()).onError(any(Throwable.class)); - - scheduler.advanceTimeTo(2, TimeUnit.SECONDS); - - InOrder inOrder = inOrder(observer); - inOrder.verify(observer, times(1)).onNext(0L); - inOrder.verify(observer, times(1)).onNext(1L); - inOrder.verify(observer, never()).onNext(2L); - verify(observer, never()).onCompleted(); - verify(observer, never()).onError(any(Throwable.class)); - - sub.unsubscribe(); - scheduler.advanceTimeTo(4, TimeUnit.SECONDS); - verify(observer, never()).onNext(2L); - verify(observer, times(1)).onCompleted(); - verify(observer, never()).onError(any(Throwable.class)); - } - - @Test - public void testWithMultipleSubscribersStartingAtSameTime() { - Observable w = Observable.create(OperationInterval.interval(1, TimeUnit.SECONDS, scheduler)); - Subscription sub1 = w.subscribe(observer); - Subscription sub2 = w.subscribe(observer2); - - verify(observer, never()).onNext(anyLong()); - verify(observer2, never()).onNext(anyLong()); - - scheduler.advanceTimeTo(2, TimeUnit.SECONDS); - - InOrder inOrder1 = inOrder(observer); - InOrder inOrder2 = inOrder(observer2); - - inOrder1.verify(observer, times(1)).onNext(0L); - inOrder1.verify(observer, times(1)).onNext(1L); - inOrder1.verify(observer, never()).onNext(2L); - verify(observer, never()).onCompleted(); - verify(observer, never()).onError(any(Throwable.class)); - - inOrder2.verify(observer2, times(1)).onNext(0L); - inOrder2.verify(observer2, times(1)).onNext(1L); - inOrder2.verify(observer2, never()).onNext(2L); - verify(observer2, never()).onCompleted(); - verify(observer2, never()).onError(any(Throwable.class)); - - sub1.unsubscribe(); - sub2.unsubscribe(); - scheduler.advanceTimeTo(4, TimeUnit.SECONDS); - - verify(observer, never()).onNext(2L); - verify(observer, times(1)).onCompleted(); - verify(observer, never()).onError(any(Throwable.class)); - - verify(observer2, never()).onNext(2L); - verify(observer2, times(1)).onCompleted(); - verify(observer2, never()).onError(any(Throwable.class)); - } - - @Test - public void testWithMultipleStaggeredSubscribers() { - Observable w = Observable.create(OperationInterval.interval(1, TimeUnit.SECONDS, scheduler)); - Subscription sub1 = w.subscribe(observer); - - verify(observer, never()).onNext(anyLong()); - - scheduler.advanceTimeTo(2, TimeUnit.SECONDS); - Subscription sub2 = w.subscribe(observer2); - - InOrder inOrder1 = inOrder(observer); - inOrder1.verify(observer, times(1)).onNext(0L); - inOrder1.verify(observer, times(1)).onNext(1L); - inOrder1.verify(observer, never()).onNext(2L); - - verify(observer, never()).onCompleted(); - verify(observer, never()).onError(any(Throwable.class)); - verify(observer2, never()).onNext(anyLong()); - - scheduler.advanceTimeTo(4, TimeUnit.SECONDS); - - inOrder1.verify(observer, times(1)).onNext(2L); - inOrder1.verify(observer, times(1)).onNext(3L); - - InOrder inOrder2 = inOrder(observer2); - inOrder2.verify(observer2, times(1)).onNext(0L); - inOrder2.verify(observer2, times(1)).onNext(1L); - - sub1.unsubscribe(); - sub2.unsubscribe(); - - inOrder1.verify(observer, never()).onNext(anyLong()); - inOrder1.verify(observer, times(1)).onCompleted(); - verify(observer, never()).onError(any(Throwable.class)); - - inOrder2.verify(observer2, never()).onNext(anyLong()); - inOrder2.verify(observer2, times(1)).onCompleted(); - verify(observer2, never()).onError(any(Throwable.class)); - } - - @Test - public void testWithMultipleStaggeredSubscribersAndPublish() { - ConnectableObservable w = Observable.create(OperationInterval.interval(1, TimeUnit.SECONDS, scheduler)).publish(); - Subscription sub1 = w.subscribe(observer); - w.connect(); - - verify(observer, never()).onNext(anyLong()); - - scheduler.advanceTimeTo(2, TimeUnit.SECONDS); - Subscription sub2 = w.subscribe(observer2); - - InOrder inOrder1 = inOrder(observer); - inOrder1.verify(observer, times(1)).onNext(0L); - inOrder1.verify(observer, times(1)).onNext(1L); - inOrder1.verify(observer, never()).onNext(2L); - - verify(observer, never()).onCompleted(); - verify(observer, never()).onError(any(Throwable.class)); - verify(observer2, never()).onNext(anyLong()); - - scheduler.advanceTimeTo(4, TimeUnit.SECONDS); - - inOrder1.verify(observer, times(1)).onNext(2L); - inOrder1.verify(observer, times(1)).onNext(3L); - - InOrder inOrder2 = inOrder(observer2); - inOrder2.verify(observer2, times(1)).onNext(2L); - inOrder2.verify(observer2, times(1)).onNext(3L); - - sub1.unsubscribe(); - sub2.unsubscribe(); - - inOrder1.verify(observer, never()).onNext(anyLong()); - inOrder1.verify(observer, never()).onCompleted(); - verify(observer, never()).onError(any(Throwable.class)); - - inOrder2.verify(observer2, never()).onNext(anyLong()); - inOrder2.verify(observer2, never()).onCompleted(); - verify(observer2, never()).onError(any(Throwable.class)); - } - } } diff --git a/rxjava-core/src/main/java/rx/operators/OperationMap.java b/rxjava-core/src/main/java/rx/operators/OperationMap.java index 940147b0b8..f2543326f2 100644 --- a/rxjava-core/src/main/java/rx/operators/OperationMap.java +++ b/rxjava-core/src/main/java/rx/operators/OperationMap.java @@ -15,29 +15,10 @@ */ package rx.operators; -import static org.junit.Assert.assertEquals; -import static org.mockito.Matchers.any; -import static org.mockito.Mockito.inOrder; -import static org.mockito.Mockito.never; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; - -import java.util.HashMap; -import java.util.Map; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.atomic.AtomicInteger; - -import org.junit.Before; -import org.junit.Test; -import org.mockito.InOrder; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; - import rx.Observable; import rx.Observable.OnSubscribeFunc; import rx.Observer; import rx.Subscription; -import rx.concurrency.Schedulers; import rx.util.functions.Func1; import rx.util.functions.Func2; @@ -156,258 +137,4 @@ public void onCompleted() { }))); } } - - public static class UnitTest { - @Mock - Observer stringObserver; - @Mock - Observer stringObserver2; - - final static Func2 APPEND_INDEX = new Func2() { - @Override - public String call(String value, Integer index) { - return value + index; - } - }; - - @Before - public void before() { - MockitoAnnotations.initMocks(this); - } - - @Test - public void testMap() { - Map m1 = getMap("One"); - Map m2 = getMap("Two"); - Observable> observable = Observable.from(m1, m2); - - Observable m = Observable.create(map(observable, new Func1, String>() { - - @Override - public String call(Map map) { - return map.get("firstName"); - } - - })); - m.subscribe(stringObserver); - - verify(stringObserver, never()).onError(any(Throwable.class)); - verify(stringObserver, times(1)).onNext("OneFirst"); - verify(stringObserver, times(1)).onNext("TwoFirst"); - verify(stringObserver, times(1)).onCompleted(); - } - - @Test - public void testMapWithIndex() { - Observable w = Observable.from("a", "b", "c"); - Observable m = Observable.create(mapWithIndex(w, APPEND_INDEX)); - m.subscribe(stringObserver); - InOrder inOrder = inOrder(stringObserver); - inOrder.verify(stringObserver, times(1)).onNext("a0"); - inOrder.verify(stringObserver, times(1)).onNext("b1"); - inOrder.verify(stringObserver, times(1)).onNext("c2"); - inOrder.verify(stringObserver, times(1)).onCompleted(); - verify(stringObserver, never()).onError(any(Throwable.class)); - } - - @Test - public void testMapWithIndexAndMultipleSubscribers() { - Observable w = Observable.from("a", "b", "c"); - Observable m = Observable.create(mapWithIndex(w, APPEND_INDEX)); - m.subscribe(stringObserver); - m.subscribe(stringObserver2); - InOrder inOrder = inOrder(stringObserver); - inOrder.verify(stringObserver, times(1)).onNext("a0"); - inOrder.verify(stringObserver, times(1)).onNext("b1"); - inOrder.verify(stringObserver, times(1)).onNext("c2"); - inOrder.verify(stringObserver, times(1)).onCompleted(); - verify(stringObserver, never()).onError(any(Throwable.class)); - - InOrder inOrder2 = inOrder(stringObserver2); - inOrder2.verify(stringObserver2, times(1)).onNext("a0"); - inOrder2.verify(stringObserver2, times(1)).onNext("b1"); - inOrder2.verify(stringObserver2, times(1)).onNext("c2"); - inOrder2.verify(stringObserver2, times(1)).onCompleted(); - verify(stringObserver2, never()).onError(any(Throwable.class)); - } - - @Test - public void testMapMany() { - /* simulate a top-level async call which returns IDs */ - Observable ids = Observable.from(1, 2); - - /* now simulate the behavior to take those IDs and perform nested async calls based on them */ - Observable m = Observable.create(mapMany(ids, new Func1>() { - - @Override - public Observable call(Integer id) { - /* simulate making a nested async call which creates another Observable */ - Observable> subObservable = null; - if (id == 1) { - Map m1 = getMap("One"); - Map m2 = getMap("Two"); - subObservable = Observable.from(m1, m2); - } else { - Map m3 = getMap("Three"); - Map m4 = getMap("Four"); - subObservable = Observable.from(m3, m4); - } - - /* simulate kicking off the async call and performing a select on it to transform the data */ - return Observable.create(map(subObservable, new Func1, String>() { - @Override - public String call(Map map) { - return map.get("firstName"); - } - })); - } - - })); - m.subscribe(stringObserver); - - verify(stringObserver, never()).onError(any(Throwable.class)); - verify(stringObserver, times(1)).onNext("OneFirst"); - verify(stringObserver, times(1)).onNext("TwoFirst"); - verify(stringObserver, times(1)).onNext("ThreeFirst"); - verify(stringObserver, times(1)).onNext("FourFirst"); - verify(stringObserver, times(1)).onCompleted(); - } - - @Test - public void testMapMany2() { - Map m1 = getMap("One"); - Map m2 = getMap("Two"); - Observable> observable1 = Observable.from(m1, m2); - - Map m3 = getMap("Three"); - Map m4 = getMap("Four"); - Observable> observable2 = Observable.from(m3, m4); - - Observable>> observable = Observable.from(observable1, observable2); - - Observable m = Observable.create(mapMany(observable, new Func1>, Observable>() { - - @Override - public Observable call(Observable> o) { - return Observable.create(map(o, new Func1, String>() { - - @Override - public String call(Map map) { - return map.get("firstName"); - } - })); - } - - })); - m.subscribe(stringObserver); - - verify(stringObserver, never()).onError(any(Throwable.class)); - verify(stringObserver, times(1)).onNext("OneFirst"); - verify(stringObserver, times(1)).onNext("TwoFirst"); - verify(stringObserver, times(1)).onNext("ThreeFirst"); - verify(stringObserver, times(1)).onNext("FourFirst"); - verify(stringObserver, times(1)).onCompleted(); - - } - - @Test - public void testMapWithError() { - Observable w = Observable.from("one", "fail", "two", "three", "fail"); - Observable m = Observable.create(map(w, new Func1() { - @Override - public String call(String s) { - if ("fail".equals(s)) { - throw new RuntimeException("Forced Failure"); - } - return s; - } - })); - - m.subscribe(stringObserver); - verify(stringObserver, times(1)).onNext("one"); - verify(stringObserver, never()).onNext("two"); - verify(stringObserver, never()).onNext("three"); - verify(stringObserver, never()).onCompleted(); - verify(stringObserver, times(1)).onError(any(Throwable.class)); - } - - @Test - public void testMapWithSynchronousObservableContainingError() { - Observable w = Observable.from("one", "fail", "two", "three", "fail"); - final AtomicInteger c1 = new AtomicInteger(); - final AtomicInteger c2 = new AtomicInteger(); - Observable m = Observable.create(map(w, new Func1() { - @Override - public String call(String s) { - if ("fail".equals(s)) - throw new RuntimeException("Forced Failure"); - System.out.println("BadMapper:" + s); - c1.incrementAndGet(); - return s; - } - })).map(new Func1() { - @Override - public String call(String s) { - System.out.println("SecondMapper:" + s); - c2.incrementAndGet(); - return s; - } - }); - - m.subscribe(stringObserver); - - verify(stringObserver, times(1)).onNext("one"); - verify(stringObserver, never()).onNext("two"); - verify(stringObserver, never()).onNext("three"); - verify(stringObserver, never()).onCompleted(); - verify(stringObserver, times(1)).onError(any(Throwable.class)); - - // we should have only returned 1 value: "one" - assertEquals(1, c1.get()); - assertEquals(1, c2.get()); - } - - @Test(expected = IllegalArgumentException.class) - public void testMapWithIssue417() { - Observable.from(1).observeOn(Schedulers.threadPoolForComputation()) - .map(new Func1() { - public Integer call(Integer arg0) { - throw new IllegalArgumentException("any error"); - } - }).toBlockingObservable().single(); - } - - @Test - public void testMapWithErrorInFuncAndThreadPoolScheduler() throws InterruptedException { - // The error will throw in one of threads in the thread pool. - // If map does not handle it, the error will disappear. - // so map needs to handle the error by itself. - final CountDownLatch latch = new CountDownLatch(1); - Observable m = Observable.from("one") - .observeOn(Schedulers.threadPoolForComputation()) - .map(new Func1() { - public String call(String arg0) { - try { - throw new IllegalArgumentException("any error"); - } finally { - latch.countDown(); - } - } - }); - - m.subscribe(stringObserver); - latch.await(); - InOrder inorder = inOrder(stringObserver); - inorder.verify(stringObserver, times(1)).onError(any(IllegalArgumentException.class)); - inorder.verifyNoMoreInteractions(); - } - - private static Map getMap(String prefix) { - Map m = new HashMap(); - m.put("firstName", prefix + "First"); - m.put("lastName", prefix + "Last"); - return m; - } - - } } diff --git a/rxjava-core/src/main/java/rx/operators/OperationMaterialize.java b/rxjava-core/src/main/java/rx/operators/OperationMaterialize.java index 7d906720fa..f1998ffe64 100644 --- a/rxjava-core/src/main/java/rx/operators/OperationMaterialize.java +++ b/rxjava-core/src/main/java/rx/operators/OperationMaterialize.java @@ -15,14 +15,6 @@ */ package rx.operators; -import static org.junit.Assert.*; - -import java.util.List; -import java.util.Vector; -import java.util.concurrent.ExecutionException; - -import org.junit.Test; - import rx.Notification; import rx.Observable; import rx.Observable.OnSubscribeFunc; @@ -85,140 +77,4 @@ public void onNext(T value) { } } - - public static class UnitTest { - @Test - public void testMaterialize1() { - // null will cause onError to be triggered before "three" can be returned - final TestAsyncErrorObservable o1 = new TestAsyncErrorObservable("one", "two", null, "three"); - - TestObserver Observer = new TestObserver(); - Observable> m = Observable.create(materialize(Observable.create(o1))); - m.subscribe(Observer); - - try { - o1.t.join(); - } catch (InterruptedException e) { - throw new RuntimeException(e); - } - - assertFalse(Observer.onError); - assertTrue(Observer.onCompleted); - assertEquals(3, Observer.notifications.size()); - assertEquals("one", Observer.notifications.get(0).getValue()); - assertTrue(Observer.notifications.get(0).isOnNext()); - assertEquals("two", Observer.notifications.get(1).getValue()); - assertTrue(Observer.notifications.get(1).isOnNext()); - assertEquals(NullPointerException.class, Observer.notifications.get(2).getThrowable().getClass()); - assertTrue(Observer.notifications.get(2).isOnError()); - } - - @Test - public void testMaterialize2() { - final TestAsyncErrorObservable o1 = new TestAsyncErrorObservable("one", "two", "three"); - - TestObserver Observer = new TestObserver(); - Observable> m = Observable.create(materialize(Observable.create(o1))); - m.subscribe(Observer); - - try { - o1.t.join(); - } catch (InterruptedException e) { - throw new RuntimeException(e); - } - - assertFalse(Observer.onError); - assertTrue(Observer.onCompleted); - assertEquals(4, Observer.notifications.size()); - assertEquals("one", Observer.notifications.get(0).getValue()); - assertTrue(Observer.notifications.get(0).isOnNext()); - assertEquals("two", Observer.notifications.get(1).getValue()); - assertTrue(Observer.notifications.get(1).isOnNext()); - assertEquals("three", Observer.notifications.get(2).getValue()); - assertTrue(Observer.notifications.get(2).isOnNext()); - assertTrue(Observer.notifications.get(3).isOnCompleted()); - } - - @Test - public void testMultipleSubscribes() throws InterruptedException, ExecutionException { - final TestAsyncErrorObservable o = new TestAsyncErrorObservable("one", "two", null, "three"); - - Observable> m = Observable.create(materialize(Observable.create(o))); - - assertEquals(3, m.toList().toBlockingObservable().toFuture().get().size()); - assertEquals(3, m.toList().toBlockingObservable().toFuture().get().size()); - } - - } - - private static class TestObserver implements Observer> { - - boolean onCompleted = false; - boolean onError = false; - List> notifications = new Vector>(); - - @Override - public void onCompleted() { - this.onCompleted = true; - } - - @Override - public void onError(Throwable e) { - this.onError = true; - } - - @Override - public void onNext(Notification value) { - this.notifications.add(value); - } - - } - - private static class TestAsyncErrorObservable implements OnSubscribeFunc { - - String[] valuesToReturn; - - TestAsyncErrorObservable(String... values) { - valuesToReturn = values; - } - - volatile Thread t; - - @Override - public Subscription onSubscribe(final Observer observer) { - t = new Thread(new Runnable() { - - @Override - public void run() { - for (String s : valuesToReturn) { - if (s == null) { - System.out.println("throwing exception"); - try { - Thread.sleep(100); - } catch (Throwable e) { - - } - observer.onError(new NullPointerException()); - return; - } else { - observer.onNext(s); - } - } - System.out.println("subscription complete"); - observer.onCompleted(); - } - - }); - t.start(); - - return new Subscription() { - - @Override - public void unsubscribe() { - - } - - }; - } - } } diff --git a/rxjava-core/src/main/java/rx/operators/OperationMerge.java b/rxjava-core/src/main/java/rx/operators/OperationMerge.java index ab226c1eee..4f98439292 100644 --- a/rxjava-core/src/main/java/rx/operators/OperationMerge.java +++ b/rxjava-core/src/main/java/rx/operators/OperationMerge.java @@ -15,32 +15,15 @@ */ package rx.operators; -import static org.junit.Assert.*; -import static org.mockito.Matchers.*; -import static org.mockito.Mockito.*; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicBoolean; -import java.util.concurrent.atomic.AtomicInteger; - -import org.junit.Before; -import org.junit.Test; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; - import rx.Observable; import rx.Observable.OnSubscribeFunc; import rx.Observer; import rx.Subscription; import rx.subscriptions.CompositeSubscription; -import rx.subscriptions.Subscriptions; -import rx.util.functions.Action0; -import rx.util.functions.Action1; + +import java.util.Arrays; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.atomic.AtomicBoolean; /** * Flattens a list of Observables into one Observable sequence, without any transformation. @@ -287,435 +270,4 @@ public void onNext(T args) { } } - - public static class UnitTest { - @Mock - Observer stringObserver; - - @Before - public void before() { - MockitoAnnotations.initMocks(this); - } - - @Test - public void testMergeObservableOfObservables() { - final Observable o1 = Observable.create(new TestSynchronousObservable()); - final Observable o2 = Observable.create(new TestSynchronousObservable()); - - Observable> observableOfObservables = Observable.create(new OnSubscribeFunc>() { - - @Override - public Subscription onSubscribe(Observer> observer) { - // simulate what would happen in an observable - observer.onNext(o1); - observer.onNext(o2); - observer.onCompleted(); - - return new Subscription() { - - @Override - public void unsubscribe() { - // unregister ... will never be called here since we are executing synchronously - } - - }; - } - - }); - Observable m = Observable.create(merge(observableOfObservables)); - m.subscribe(stringObserver); - - verify(stringObserver, never()).onError(any(Throwable.class)); - verify(stringObserver, times(1)).onCompleted(); - verify(stringObserver, times(2)).onNext("hello"); - } - - @Test - public void testMergeArray() { - final Observable o1 = Observable.create(new TestSynchronousObservable()); - final Observable o2 = Observable.create(new TestSynchronousObservable()); - - @SuppressWarnings("unchecked") - Observable m = Observable.create(merge(o1, o2)); - m.subscribe(stringObserver); - - verify(stringObserver, never()).onError(any(Throwable.class)); - verify(stringObserver, times(2)).onNext("hello"); - verify(stringObserver, times(1)).onCompleted(); - } - - @Test - public void testMergeList() { - final Observable o1 = Observable.create(new TestSynchronousObservable()); - final Observable o2 = Observable.create(new TestSynchronousObservable()); - List> listOfObservables = new ArrayList>(); - listOfObservables.add(o1); - listOfObservables.add(o2); - - Observable m = Observable.create(merge(listOfObservables)); - m.subscribe(stringObserver); - - verify(stringObserver, never()).onError(any(Throwable.class)); - verify(stringObserver, times(1)).onCompleted(); - verify(stringObserver, times(2)).onNext("hello"); - } - - @Test - public void testUnSubscribe() { - TestObservable tA = new TestObservable(); - TestObservable tB = new TestObservable(); - - @SuppressWarnings("unchecked") - Observable m = Observable.create(merge(Observable.create(tA), Observable.create(tB))); - Subscription s = m.subscribe(stringObserver); - - tA.sendOnNext("Aone"); - tB.sendOnNext("Bone"); - s.unsubscribe(); - tA.sendOnNext("Atwo"); - tB.sendOnNext("Btwo"); - tA.sendOnCompleted(); - tB.sendOnCompleted(); - - verify(stringObserver, never()).onError(any(Throwable.class)); - verify(stringObserver, times(1)).onNext("Aone"); - verify(stringObserver, times(1)).onNext("Bone"); - assertTrue(tA.unsubscribed); - assertTrue(tB.unsubscribed); - verify(stringObserver, never()).onNext("Atwo"); - verify(stringObserver, never()).onNext("Btwo"); - verify(stringObserver, never()).onCompleted(); - } - - @Test - public void testUnSubscribeObservableOfObservables() throws InterruptedException { - - final AtomicBoolean unsubscribed = new AtomicBoolean(); - final CountDownLatch latch = new CountDownLatch(1); - - Observable> source = Observable.create(new OnSubscribeFunc>() { - - @Override - public Subscription onSubscribe(final Observer> observer) { - // verbose on purpose so I can track the inside of it - final Subscription s = Subscriptions.create(new Action0() { - - @Override - public void call() { - System.out.println("*** unsubscribed"); - unsubscribed.set(true); - } - - }); - - new Thread(new Runnable() { - - @Override - public void run() { - - while (!unsubscribed.get()) { - observer.onNext(Observable.from(1L, 2L)); - } - System.out.println("Done looping after unsubscribe: " + unsubscribed.get()); - observer.onCompleted(); - - // mark that the thread is finished - latch.countDown(); - } - }).start(); - - return s; - }; - - }); - - final AtomicInteger count = new AtomicInteger(); - Observable.create(merge(source)).take(6).toBlockingObservable().forEach(new Action1() { - - @Override - public void call(Long v) { - System.out.println("Value: " + v); - int c = count.incrementAndGet(); - if (c > 6) { - fail("Should be only 6"); - } - - } - }); - - latch.await(1000, TimeUnit.MILLISECONDS); - - System.out.println("unsubscribed: " + unsubscribed.get()); - - assertTrue(unsubscribed.get()); - - } - - @Test - public void testMergeArrayWithThreading() { - final TestASynchronousObservable o1 = new TestASynchronousObservable(); - final TestASynchronousObservable o2 = new TestASynchronousObservable(); - - @SuppressWarnings("unchecked") - Observable m = Observable.create(merge(Observable.create(o1), Observable.create(o2))); - m.subscribe(stringObserver); - - try { - o1.t.join(); - o2.t.join(); - } catch (InterruptedException e) { - throw new RuntimeException(e); - } - - verify(stringObserver, never()).onError(any(Throwable.class)); - verify(stringObserver, times(2)).onNext("hello"); - verify(stringObserver, times(1)).onCompleted(); - } - - @Test - public void testSynchronizationOfMultipleSequences() throws Throwable { - final TestASynchronousObservable o1 = new TestASynchronousObservable(); - final TestASynchronousObservable o2 = new TestASynchronousObservable(); - - // use this latch to cause onNext to wait until we're ready to let it go - final CountDownLatch endLatch = new CountDownLatch(1); - - final AtomicInteger concurrentCounter = new AtomicInteger(); - final AtomicInteger totalCounter = new AtomicInteger(); - - @SuppressWarnings("unchecked") - Observable m = Observable.create(merge(Observable.create(o1), Observable.create(o2))); - m.subscribe(new Observer() { - - @Override - public void onCompleted() { - - } - - @Override - public void onError(Throwable e) { - throw new RuntimeException("failed", e); - } - - @Override - public void onNext(String v) { - totalCounter.incrementAndGet(); - concurrentCounter.incrementAndGet(); - try { - // wait here until we're done asserting - endLatch.await(); - } catch (InterruptedException e) { - e.printStackTrace(); - throw new RuntimeException("failed", e); - } finally { - concurrentCounter.decrementAndGet(); - } - } - - }); - - // wait for both observables to send (one should be blocked) - o1.onNextBeingSent.await(); - o2.onNextBeingSent.await(); - - // I can't think of a way to know for sure that both threads have or are trying to send onNext - // since I can't use a CountDownLatch for "after" onNext since I want to catch during it - // but I can't know for sure onNext is invoked - // so I'm unfortunately reverting to using a Thread.sleep to allow the process scheduler time - // to make sure after o1.onNextBeingSent and o2.onNextBeingSent are hit that the following - // onNext is invoked. - - Thread.sleep(300); - - try { // in try/finally so threads are released via latch countDown even if assertion fails - assertEquals(1, concurrentCounter.get()); - } finally { - // release so it can finish - endLatch.countDown(); - } - - try { - o1.t.join(); - o2.t.join(); - } catch (InterruptedException e) { - throw new RuntimeException(e); - } - - assertEquals(2, totalCounter.get()); - assertEquals(0, concurrentCounter.get()); - } - - /** - * unit test from OperationMergeDelayError backported here to show how these use cases work with normal merge - */ - @Test - public void testError1() { - // we are using synchronous execution to test this exactly rather than non-deterministic concurrent behavior - final Observable o1 = Observable.create(new TestErrorObservable("four", null, "six")); // we expect to lose "six" - final Observable o2 = Observable.create(new TestErrorObservable("one", "two", "three")); // we expect to lose all of these since o1 is done first and fails - - @SuppressWarnings("unchecked") - Observable m = Observable.create(merge(o1, o2)); - m.subscribe(stringObserver); - - verify(stringObserver, times(1)).onError(any(NullPointerException.class)); - verify(stringObserver, never()).onCompleted(); - verify(stringObserver, times(0)).onNext("one"); - verify(stringObserver, times(0)).onNext("two"); - verify(stringObserver, times(0)).onNext("three"); - verify(stringObserver, times(1)).onNext("four"); - verify(stringObserver, times(0)).onNext("five"); - verify(stringObserver, times(0)).onNext("six"); - } - - /** - * unit test from OperationMergeDelayError backported here to show how these use cases work with normal merge - */ - @Test - public void testError2() { - // we are using synchronous execution to test this exactly rather than non-deterministic concurrent behavior - final Observable o1 = Observable.create(new TestErrorObservable("one", "two", "three")); - final Observable o2 = Observable.create(new TestErrorObservable("four", null, "six")); // we expect to lose "six" - final Observable o3 = Observable.create(new TestErrorObservable("seven", "eight", null));// we expect to lose all of these since o2 is done first and fails - final Observable o4 = Observable.create(new TestErrorObservable("nine"));// we expect to lose all of these since o2 is done first and fails - - @SuppressWarnings("unchecked") - Observable m = Observable.create(merge(o1, o2, o3, o4)); - m.subscribe(stringObserver); - - verify(stringObserver, times(1)).onError(any(NullPointerException.class)); - verify(stringObserver, never()).onCompleted(); - verify(stringObserver, times(1)).onNext("one"); - verify(stringObserver, times(1)).onNext("two"); - verify(stringObserver, times(1)).onNext("three"); - verify(stringObserver, times(1)).onNext("four"); - verify(stringObserver, times(0)).onNext("five"); - verify(stringObserver, times(0)).onNext("six"); - verify(stringObserver, times(0)).onNext("seven"); - verify(stringObserver, times(0)).onNext("eight"); - verify(stringObserver, times(0)).onNext("nine"); - } - - private static class TestSynchronousObservable implements OnSubscribeFunc { - - @Override - public Subscription onSubscribe(Observer observer) { - - observer.onNext("hello"); - observer.onCompleted(); - - return new Subscription() { - - @Override - public void unsubscribe() { - // unregister ... will never be called here since we are executing synchronously - } - - }; - } - } - - private static class TestASynchronousObservable implements OnSubscribeFunc { - Thread t; - final CountDownLatch onNextBeingSent = new CountDownLatch(1); - - @Override - public Subscription onSubscribe(final Observer observer) { - t = new Thread(new Runnable() { - - @Override - public void run() { - onNextBeingSent.countDown(); - observer.onNext("hello"); - // I can't use a countDownLatch to prove we are actually sending 'onNext' - // since it will block if synchronized and I'll deadlock - observer.onCompleted(); - } - - }); - t.start(); - - return new Subscription() { - - @Override - public void unsubscribe() { - - } - - }; - } - } - - /** - * A Observable that doesn't do the right thing on UnSubscribe/Error/etc in that it will keep sending events down the pipe regardless of what happens. - */ - private static class TestObservable implements OnSubscribeFunc { - - Observer observer = null; - volatile boolean unsubscribed = false; - Subscription s = new Subscription() { - - @Override - public void unsubscribe() { - unsubscribed = true; - - } - - }; - - /* used to simulate subscription */ - public void sendOnCompleted() { - observer.onCompleted(); - } - - /* used to simulate subscription */ - public void sendOnNext(String value) { - observer.onNext(value); - } - - /* used to simulate subscription */ - @SuppressWarnings("unused") - public void sendOnError(Throwable e) { - observer.onError(e); - } - - @Override - public Subscription onSubscribe(final Observer observer) { - this.observer = observer; - return s; - } - } - - private static class TestErrorObservable implements OnSubscribeFunc { - - String[] valuesToReturn; - - TestErrorObservable(String... values) { - valuesToReturn = values; - } - - @Override - public Subscription onSubscribe(Observer observer) { - - for (String s : valuesToReturn) { - if (s == null) { - System.out.println("throwing exception"); - observer.onError(new NullPointerException()); - } else { - observer.onNext(s); - } - } - observer.onCompleted(); - - return new Subscription() { - - @Override - public void unsubscribe() { - // unregister ... will never be called here since we are executing synchronously - } - - }; - } - } - } } diff --git a/rxjava-core/src/main/java/rx/operators/OperationMergeDelayError.java b/rxjava-core/src/main/java/rx/operators/OperationMergeDelayError.java index abb450dd4d..5f1af2ff80 100644 --- a/rxjava-core/src/main/java/rx/operators/OperationMergeDelayError.java +++ b/rxjava-core/src/main/java/rx/operators/OperationMergeDelayError.java @@ -15,27 +15,17 @@ */ package rx.operators; -import static org.junit.Assert.*; -import static org.mockito.Matchers.*; -import static org.mockito.Mockito.*; - -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentLinkedQueue; -import java.util.concurrent.atomic.AtomicBoolean; - -import org.junit.Before; -import org.junit.Test; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; - import rx.Observable; import rx.Observable.OnSubscribeFunc; import rx.Observer; import rx.Subscription; import rx.util.CompositeException; +import java.util.List; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentLinkedQueue; +import java.util.concurrent.atomic.AtomicBoolean; + /** * This behaves like {@link OperationMerge} except that if any of the merged Observables notify of * an error via onError, mergeDelayError will refrain from propagating that error @@ -342,484 +332,4 @@ public void onNext(T args) { } } - - public static class UnitTest { - @Mock - Observer stringObserver; - - @Before - public void before() { - MockitoAnnotations.initMocks(this); - } - - @Test - public void testErrorDelayed1() { - final Observable o1 = Observable.create(new TestErrorObservable("four", null, "six")); // we expect to lose "six" from the source (and it should never be sent by the source since onError was called - final Observable o2 = Observable.create(new TestErrorObservable("one", "two", "three")); - - @SuppressWarnings("unchecked") - Observable m = Observable.create(mergeDelayError(o1, o2)); - m.subscribe(stringObserver); - - verify(stringObserver, times(1)).onError(any(NullPointerException.class)); - verify(stringObserver, never()).onCompleted(); - verify(stringObserver, times(1)).onNext("one"); - verify(stringObserver, times(1)).onNext("two"); - verify(stringObserver, times(1)).onNext("three"); - verify(stringObserver, times(1)).onNext("four"); - verify(stringObserver, times(0)).onNext("five"); - verify(stringObserver, times(0)).onNext("six"); - } - - @Test - public void testErrorDelayed2() { - final Observable o1 = Observable.create(new TestErrorObservable("one", "two", "three")); - final Observable o2 = Observable.create(new TestErrorObservable("four", null, "six")); // we expect to lose "six" from the source (and it should never be sent by the source since onError was called - final Observable o3 = Observable.create(new TestErrorObservable("seven", "eight", null)); - final Observable o4 = Observable.create(new TestErrorObservable("nine")); - - @SuppressWarnings("unchecked") - Observable m = Observable.create(mergeDelayError(o1, o2, o3, o4)); - m.subscribe(stringObserver); - - verify(stringObserver, times(1)).onError(any(NullPointerException.class)); - verify(stringObserver, never()).onCompleted(); - verify(stringObserver, times(1)).onNext("one"); - verify(stringObserver, times(1)).onNext("two"); - verify(stringObserver, times(1)).onNext("three"); - verify(stringObserver, times(1)).onNext("four"); - verify(stringObserver, times(0)).onNext("five"); - verify(stringObserver, times(0)).onNext("six"); - verify(stringObserver, times(1)).onNext("seven"); - verify(stringObserver, times(1)).onNext("eight"); - verify(stringObserver, times(1)).onNext("nine"); - } - - @Test - public void testErrorDelayed3() { - final Observable o1 = Observable.create(new TestErrorObservable("one", "two", "three")); - final Observable o2 = Observable.create(new TestErrorObservable("four", "five", "six")); - final Observable o3 = Observable.create(new TestErrorObservable("seven", "eight", null)); - final Observable o4 = Observable.create(new TestErrorObservable("nine")); - - @SuppressWarnings("unchecked") - Observable m = Observable.create(mergeDelayError(o1, o2, o3, o4)); - m.subscribe(stringObserver); - - verify(stringObserver, times(1)).onError(any(NullPointerException.class)); - verify(stringObserver, never()).onCompleted(); - verify(stringObserver, times(1)).onNext("one"); - verify(stringObserver, times(1)).onNext("two"); - verify(stringObserver, times(1)).onNext("three"); - verify(stringObserver, times(1)).onNext("four"); - verify(stringObserver, times(1)).onNext("five"); - verify(stringObserver, times(1)).onNext("six"); - verify(stringObserver, times(1)).onNext("seven"); - verify(stringObserver, times(1)).onNext("eight"); - verify(stringObserver, times(1)).onNext("nine"); - } - - @Test - public void testErrorDelayed4() { - final Observable o1 = Observable.create(new TestErrorObservable("one", "two", "three")); - final Observable o2 = Observable.create(new TestErrorObservable("four", "five", "six")); - final Observable o3 = Observable.create(new TestErrorObservable("seven", "eight")); - final Observable o4 = Observable.create(new TestErrorObservable("nine", null)); - - @SuppressWarnings("unchecked") - Observable m = Observable.create(mergeDelayError(o1, o2, o3, o4)); - m.subscribe(stringObserver); - - verify(stringObserver, times(1)).onError(any(NullPointerException.class)); - verify(stringObserver, never()).onCompleted(); - verify(stringObserver, times(1)).onNext("one"); - verify(stringObserver, times(1)).onNext("two"); - verify(stringObserver, times(1)).onNext("three"); - verify(stringObserver, times(1)).onNext("four"); - verify(stringObserver, times(1)).onNext("five"); - verify(stringObserver, times(1)).onNext("six"); - verify(stringObserver, times(1)).onNext("seven"); - verify(stringObserver, times(1)).onNext("eight"); - verify(stringObserver, times(1)).onNext("nine"); - } - - @Test - public void testErrorDelayed4WithThreading() { - final TestAsyncErrorObservable o1 = new TestAsyncErrorObservable("one", "two", "three"); - final TestAsyncErrorObservable o2 = new TestAsyncErrorObservable("four", "five", "six"); - final TestAsyncErrorObservable o3 = new TestAsyncErrorObservable("seven", "eight"); - // throw the error at the very end so no onComplete will be called after it - final TestAsyncErrorObservable o4 = new TestAsyncErrorObservable("nine", null); - - @SuppressWarnings("unchecked") - Observable m = Observable.create(mergeDelayError(Observable.create(o1), Observable.create(o2), Observable.create(o3), Observable.create(o4))); - m.subscribe(stringObserver); - - try { - o1.t.join(); - o2.t.join(); - o3.t.join(); - o4.t.join(); - } catch (InterruptedException e) { - throw new RuntimeException(e); - } - - verify(stringObserver, times(1)).onError(any(NullPointerException.class)); - verify(stringObserver, never()).onCompleted(); - verify(stringObserver, times(1)).onNext("one"); - verify(stringObserver, times(1)).onNext("two"); - verify(stringObserver, times(1)).onNext("three"); - verify(stringObserver, times(1)).onNext("four"); - verify(stringObserver, times(1)).onNext("five"); - verify(stringObserver, times(1)).onNext("six"); - verify(stringObserver, times(1)).onNext("seven"); - verify(stringObserver, times(1)).onNext("eight"); - verify(stringObserver, times(1)).onNext("nine"); - } - - @Test - public void testCompositeErrorDelayed1() { - final Observable o1 = Observable.create(new TestErrorObservable("four", null, "six")); // we expect to lose "six" from the source (and it should never be sent by the source since onError was called - final Observable o2 = Observable.create(new TestErrorObservable("one", "two", null)); - - @SuppressWarnings("unchecked") - Observable m = Observable.create(mergeDelayError(o1, o2)); - m.subscribe(stringObserver); - - verify(stringObserver, times(1)).onError(any(CompositeException.class)); - verify(stringObserver, never()).onCompleted(); - verify(stringObserver, times(1)).onNext("one"); - verify(stringObserver, times(1)).onNext("two"); - verify(stringObserver, times(0)).onNext("three"); - verify(stringObserver, times(1)).onNext("four"); - verify(stringObserver, times(0)).onNext("five"); - verify(stringObserver, times(0)).onNext("six"); - } - - @Test - public void testCompositeErrorDelayed2() { - final Observable o1 = Observable.create(new TestErrorObservable("four", null, "six")); // we expect to lose "six" from the source (and it should never be sent by the source since onError was called - final Observable o2 = Observable.create(new TestErrorObservable("one", "two", null)); - - @SuppressWarnings("unchecked") - Observable m = Observable.create(mergeDelayError(o1, o2)); - CaptureObserver w = new CaptureObserver(); - m.subscribe(w); - - assertNotNull(w.e); - if (w.e instanceof CompositeException) { - assertEquals(2, ((CompositeException) w.e).getExceptions().size()); - w.e.printStackTrace(); - } else { - fail("Expecting CompositeException"); - } - - } - - /** - * The unit tests below are from OperationMerge and should ensure the normal merge functionality is correct. - */ - - @Test - public void testMergeObservableOfObservables() { - final Observable o1 = Observable.create(new TestSynchronousObservable()); - final Observable o2 = Observable.create(new TestSynchronousObservable()); - - Observable> observableOfObservables = Observable.create(new OnSubscribeFunc>() { - - @Override - public Subscription onSubscribe(Observer> observer) { - // simulate what would happen in an observable - observer.onNext(o1); - observer.onNext(o2); - observer.onCompleted(); - - return new Subscription() { - - @Override - public void unsubscribe() { - // unregister ... will never be called here since we are executing synchronously - } - - }; - } - - }); - Observable m = Observable.create(mergeDelayError(observableOfObservables)); - m.subscribe(stringObserver); - - verify(stringObserver, never()).onError(any(Throwable.class)); - verify(stringObserver, times(1)).onCompleted(); - verify(stringObserver, times(2)).onNext("hello"); - } - - @Test - public void testMergeArray() { - final Observable o1 = Observable.create(new TestSynchronousObservable()); - final Observable o2 = Observable.create(new TestSynchronousObservable()); - - @SuppressWarnings("unchecked") - Observable m = Observable.create(mergeDelayError(o1, o2)); - m.subscribe(stringObserver); - - verify(stringObserver, never()).onError(any(Throwable.class)); - verify(stringObserver, times(2)).onNext("hello"); - verify(stringObserver, times(1)).onCompleted(); - } - - @Test - public void testMergeList() { - final Observable o1 = Observable.create(new TestSynchronousObservable()); - final Observable o2 = Observable.create(new TestSynchronousObservable()); - List> listOfObservables = new ArrayList>(); - listOfObservables.add(o1); - listOfObservables.add(o2); - - Observable m = Observable.create(mergeDelayError(listOfObservables)); - m.subscribe(stringObserver); - - verify(stringObserver, never()).onError(any(Throwable.class)); - verify(stringObserver, times(1)).onCompleted(); - verify(stringObserver, times(2)).onNext("hello"); - } - - @Test - public void testUnSubscribe() { - TestObservable tA = new TestObservable(); - TestObservable tB = new TestObservable(); - - @SuppressWarnings("unchecked") - Observable m = Observable.create(mergeDelayError(Observable.create(tA), Observable.create(tB))); - Subscription s = m.subscribe(stringObserver); - - tA.sendOnNext("Aone"); - tB.sendOnNext("Bone"); - s.unsubscribe(); - tA.sendOnNext("Atwo"); - tB.sendOnNext("Btwo"); - tA.sendOnCompleted(); - tB.sendOnCompleted(); - - verify(stringObserver, never()).onError(any(Throwable.class)); - verify(stringObserver, times(1)).onNext("Aone"); - verify(stringObserver, times(1)).onNext("Bone"); - assertTrue(tA.unsubscribed); - assertTrue(tB.unsubscribed); - verify(stringObserver, never()).onNext("Atwo"); - verify(stringObserver, never()).onNext("Btwo"); - verify(stringObserver, never()).onCompleted(); - } - - @Test - public void testMergeArrayWithThreading() { - final TestASynchronousObservable o1 = new TestASynchronousObservable(); - final TestASynchronousObservable o2 = new TestASynchronousObservable(); - - @SuppressWarnings("unchecked") - Observable m = Observable.create(mergeDelayError(Observable.create(o1), Observable.create(o2))); - m.subscribe(stringObserver); - - try { - o1.t.join(); - o2.t.join(); - } catch (InterruptedException e) { - throw new RuntimeException(e); - } - - verify(stringObserver, never()).onError(any(Throwable.class)); - verify(stringObserver, times(2)).onNext("hello"); - verify(stringObserver, times(1)).onCompleted(); - } - - private static class TestSynchronousObservable implements OnSubscribeFunc { - - @Override - public Subscription onSubscribe(Observer observer) { - - observer.onNext("hello"); - observer.onCompleted(); - - return new Subscription() { - - @Override - public void unsubscribe() { - // unregister ... will never be called here since we are executing synchronously - } - - }; - } - } - - private static class TestASynchronousObservable implements OnSubscribeFunc { - Thread t; - - @Override - public Subscription onSubscribe(final Observer observer) { - t = new Thread(new Runnable() { - - @Override - public void run() { - observer.onNext("hello"); - observer.onCompleted(); - } - - }); - t.start(); - - return new Subscription() { - - @Override - public void unsubscribe() { - - } - - }; - } - } - - /** - * A Observable that doesn't do the right thing on UnSubscribe/Error/etc in that it will keep sending events down the pipe regardless of what happens. - */ - private static class TestObservable implements OnSubscribeFunc { - - Observer observer = null; - volatile boolean unsubscribed = false; - Subscription s = new Subscription() { - - @Override - public void unsubscribe() { - unsubscribed = true; - - } - - }; - - /* used to simulate subscription */ - public void sendOnCompleted() { - observer.onCompleted(); - } - - /* used to simulate subscription */ - public void sendOnNext(String value) { - observer.onNext(value); - } - - /* used to simulate subscription */ - @SuppressWarnings("unused") - public void sendOnError(Throwable e) { - observer.onError(e); - } - - @Override - public Subscription onSubscribe(final Observer observer) { - this.observer = observer; - return s; - } - } - - private static class TestErrorObservable implements OnSubscribeFunc { - - String[] valuesToReturn; - - TestErrorObservable(String... values) { - valuesToReturn = values; - } - - @Override - public Subscription onSubscribe(Observer observer) { - boolean errorThrown = false; - for (String s : valuesToReturn) { - if (s == null) { - System.out.println("throwing exception"); - observer.onError(new NullPointerException()); - errorThrown = true; - // purposefully not returning here so it will continue calling onNext - // so that we also test that we handle bad sequences like this - } else { - observer.onNext(s); - } - } - if (!errorThrown) { - observer.onCompleted(); - } - - return new Subscription() { - - @Override - public void unsubscribe() { - // unregister ... will never be called here since we are executing synchronously - } - - }; - } - } - - private static class TestAsyncErrorObservable implements OnSubscribeFunc { - - String[] valuesToReturn; - - TestAsyncErrorObservable(String... values) { - valuesToReturn = values; - } - - Thread t; - - @Override - public Subscription onSubscribe(final Observer observer) { - t = new Thread(new Runnable() { - - @Override - public void run() { - for (String s : valuesToReturn) { - if (s == null) { - System.out.println("throwing exception"); - try { - Thread.sleep(100); - } catch (Throwable e) { - - } - observer.onError(new NullPointerException()); - return; - } else { - observer.onNext(s); - } - } - System.out.println("subscription complete"); - observer.onCompleted(); - } - - }); - t.start(); - - return new Subscription() { - - @Override - public void unsubscribe() { - - } - - }; - } - } - - private static class CaptureObserver implements Observer { - volatile Throwable e; - - @Override - public void onCompleted() { - - } - - @Override - public void onError(Throwable e) { - this.e = e; - } - - @Override - public void onNext(String args) { - - } - - } - } } diff --git a/rxjava-core/src/main/java/rx/operators/OperationMostRecent.java b/rxjava-core/src/main/java/rx/operators/OperationMostRecent.java index b2eabb2893..003b54aaad 100644 --- a/rxjava-core/src/main/java/rx/operators/OperationMostRecent.java +++ b/rxjava-core/src/main/java/rx/operators/OperationMostRecent.java @@ -15,20 +15,14 @@ */ package rx.operators; -import static org.junit.Assert.*; +import rx.Observable; +import rx.Observer; +import rx.util.Exceptions; import java.util.Iterator; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicReference; -import org.junit.Test; - -import rx.Observable; -import rx.Observer; -import rx.subjects.PublishSubject; -import rx.subjects.Subject; -import rx.util.Exceptions; - /** * Returns an Iterable that always returns the item most recently emitted by an Observable, or a * seed value if no item has yet been emitted. @@ -117,53 +111,4 @@ private T getRecentValue() { } } - - public static class UnitTest { - @Test - public void testMostRecent() { - Subject observable = PublishSubject.create(); - - Iterator it = mostRecent(observable, "default").iterator(); - - assertTrue(it.hasNext()); - assertEquals("default", it.next()); - assertEquals("default", it.next()); - - observable.onNext("one"); - assertTrue(it.hasNext()); - assertEquals("one", it.next()); - assertEquals("one", it.next()); - - observable.onNext("two"); - assertTrue(it.hasNext()); - assertEquals("two", it.next()); - assertEquals("two", it.next()); - - observable.onCompleted(); - assertFalse(it.hasNext()); - - } - - @Test(expected = TestException.class) - public void testMostRecentWithException() { - Subject observable = PublishSubject.create(); - - Iterator it = mostRecent(observable, "default").iterator(); - - assertTrue(it.hasNext()); - assertEquals("default", it.next()); - assertEquals("default", it.next()); - - observable.onError(new TestException()); - assertTrue(it.hasNext()); - - it.next(); - } - - private static class TestException extends RuntimeException { - private static final long serialVersionUID = 1L; - } - - } - } diff --git a/rxjava-core/src/main/java/rx/operators/OperationMulticast.java b/rxjava-core/src/main/java/rx/operators/OperationMulticast.java index e24c24a91a..b93f9917f1 100644 --- a/rxjava-core/src/main/java/rx/operators/OperationMulticast.java +++ b/rxjava-core/src/main/java/rx/operators/OperationMulticast.java @@ -15,15 +15,10 @@ */ package rx.operators; -import static org.mockito.Mockito.*; - -import org.junit.Test; - import rx.Observable; import rx.Observer; import rx.Subscription; import rx.observables.ConnectableObservable; -import rx.subjects.PublishSubject; import rx.subjects.Subject; public class OperationMulticast { @@ -88,92 +83,4 @@ public void unsubscribe() { } - - public static class UnitTest { - - @Test - public void testMulticast() { - Subject source = PublishSubject.create(); - - ConnectableObservable multicasted = OperationMulticast.multicast(source, - PublishSubject.create()); - - @SuppressWarnings("unchecked") - Observer observer = mock(Observer.class); - multicasted.subscribe(observer); - - source.onNext("one"); - source.onNext("two"); - - multicasted.connect(); - - source.onNext("three"); - source.onNext("four"); - source.onCompleted(); - - verify(observer, never()).onNext("one"); - verify(observer, never()).onNext("two"); - verify(observer, times(1)).onNext("three"); - verify(observer, times(1)).onNext("four"); - verify(observer, times(1)).onCompleted(); - - } - - @Test - public void testMulticastConnectTwice() { - Subject source = PublishSubject.create(); - - ConnectableObservable multicasted = OperationMulticast.multicast(source, - PublishSubject.create()); - - @SuppressWarnings("unchecked") - Observer observer = mock(Observer.class); - multicasted.subscribe(observer); - - source.onNext("one"); - - multicasted.connect(); - multicasted.connect(); - - source.onNext("two"); - source.onCompleted(); - - verify(observer, never()).onNext("one"); - verify(observer, times(1)).onNext("two"); - verify(observer, times(1)).onCompleted(); - - } - - @Test - public void testMulticastDisconnect() { - Subject source = PublishSubject.create(); - - ConnectableObservable multicasted = OperationMulticast.multicast(source, - PublishSubject.create()); - - @SuppressWarnings("unchecked") - Observer observer = mock(Observer.class); - multicasted.subscribe(observer); - - source.onNext("one"); - - Subscription connection = multicasted.connect(); - source.onNext("two"); - - connection.unsubscribe(); - source.onNext("three"); - - multicasted.connect(); - source.onNext("four"); - source.onCompleted(); - - verify(observer, never()).onNext("one"); - verify(observer, times(1)).onNext("two"); - verify(observer, never()).onNext("three"); - verify(observer, times(1)).onNext("four"); - verify(observer, times(1)).onCompleted(); - - } - - } } diff --git a/rxjava-core/src/main/java/rx/operators/OperationNext.java b/rxjava-core/src/main/java/rx/operators/OperationNext.java index 43100e1096..a4812881e3 100644 --- a/rxjava-core/src/main/java/rx/operators/OperationNext.java +++ b/rxjava-core/src/main/java/rx/operators/OperationNext.java @@ -15,32 +15,16 @@ */ package rx.operators; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; +import rx.Notification; +import rx.Observable; +import rx.Observer; +import rx.util.Exceptions; import java.util.Iterator; import java.util.NoSuchElementException; import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.BlockingQueue; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicBoolean; -import java.util.concurrent.atomic.AtomicInteger; - -import org.junit.Test; - -import rx.Notification; -import rx.Observable; -import rx.Observable.OnSubscribeFunc; -import rx.Observer; -import rx.Subscription; -import rx.concurrency.Schedulers; -import rx.subjects.PublishSubject; -import rx.subjects.Subject; -import rx.subscriptions.Subscriptions; -import rx.util.Exceptions; /** * Returns an Iterable that blocks until the Observable emits another item, then returns that item. @@ -180,278 +164,4 @@ public Notification takeNext() throws InterruptedException { } } - - public static class UnitTest { - - private void fireOnNextInNewThread(final Subject o, final String value) { - new Thread() { - @Override - public void run() { - try { - Thread.sleep(500); - } catch (InterruptedException e) { - // ignore - } - o.onNext(value); - } - }.start(); - } - - private void fireOnErrorInNewThread(final Subject o) { - new Thread() { - @Override - public void run() { - try { - Thread.sleep(500); - } catch (InterruptedException e) { - // ignore - } - o.onError(new TestException()); - } - }.start(); - } - - - @Test - public void testNext() { - Subject obs = PublishSubject.create(); - Iterator it = next(obs).iterator(); - fireOnNextInNewThread(obs, "one"); - assertTrue(it.hasNext()); - assertEquals("one", it.next()); - - fireOnNextInNewThread(obs, "two"); - assertTrue(it.hasNext()); - assertEquals("two", it.next()); - - obs.onCompleted(); - assertFalse(it.hasNext()); - try { - it.next(); - fail("At the end of an iterator should throw a NoSuchElementException"); - } - catch(NoSuchElementException e){ - } - - // If the observable is completed, hasNext always returns false and next always throw a NoSuchElementException. - assertFalse(it.hasNext()); - try { - it.next(); - fail("At the end of an iterator should throw a NoSuchElementException"); - } - catch(NoSuchElementException e){ - } - } - - @Test - public void testNextWithError() { - Subject obs = PublishSubject.create(); - Iterator it = next(obs).iterator(); - fireOnNextInNewThread(obs, "one"); - assertTrue(it.hasNext()); - assertEquals("one", it.next()); - - fireOnErrorInNewThread(obs); - try { - it.hasNext(); - fail("Expected an TestException"); - } - catch(TestException e) { - } - - assertErrorAfterObservableFail(it); - } - - @Test - public void testNextWithEmpty() { - Observable obs = Observable.empty().observeOn(Schedulers.newThread()); - Iterator it = next(obs).iterator(); - - assertFalse(it.hasNext()); - try { - it.next(); - fail("At the end of an iterator should throw a NoSuchElementException"); - } - catch(NoSuchElementException e){ - } - - // If the observable is completed, hasNext always returns false and next always throw a NoSuchElementException. - assertFalse(it.hasNext()); - try { - it.next(); - fail("At the end of an iterator should throw a NoSuchElementException"); - } - catch(NoSuchElementException e){ - } - } - - @Test - public void testOnError() throws Throwable { - Subject obs = PublishSubject.create(); - Iterator it = next(obs).iterator(); - - obs.onError(new TestException()); - try { - it.hasNext(); - fail("Expected an TestException"); - } - catch(TestException e) { - // successful - } - - assertErrorAfterObservableFail(it); - } - - @Test - public void testOnErrorInNewThread() { - Subject obs = PublishSubject.create(); - Iterator it = next(obs).iterator(); - - fireOnErrorInNewThread(obs); - - try { - it.hasNext(); - fail("Expected an TestException"); - } - catch(TestException e) { - // successful - } - - assertErrorAfterObservableFail(it); - } - - private void assertErrorAfterObservableFail(Iterator it) { - // After the observable fails, hasNext and next always throw the exception. - try { - it.hasNext(); - fail("hasNext should throw a TestException"); - } - catch(TestException e){ - } - try { - it.next(); - fail("next should throw a TestException"); - } - catch(TestException e){ - } - } - - @Test - public void testNextWithOnlyUsingNextMethod() { - Subject obs = PublishSubject.create(); - Iterator it = next(obs).iterator(); - fireOnNextInNewThread(obs, "one"); - assertEquals("one", it.next()); - - fireOnNextInNewThread(obs, "two"); - assertEquals("two", it.next()); - - obs.onCompleted(); - try { - it.next(); - fail("At the end of an iterator should throw a NoSuchElementException"); - } - catch(NoSuchElementException e){ - } - } - - @Test - public void testNextWithCallingHasNextMultipleTimes() { - Subject obs = PublishSubject.create(); - Iterator it = next(obs).iterator(); - fireOnNextInNewThread(obs, "one"); - assertTrue(it.hasNext()); - assertTrue(it.hasNext()); - assertTrue(it.hasNext()); - assertTrue(it.hasNext()); - assertEquals("one", it.next()); - - obs.onCompleted(); - try { - it.next(); - fail("At the end of an iterator should throw a NoSuchElementException"); - } - catch(NoSuchElementException e){ - } - } - - @SuppressWarnings("serial") - private static class TestException extends RuntimeException { - - } - - /** - * Confirm that no buffering or blocking of the Observable onNext calls occurs and it just grabs the next emitted value. - * - * This results in output such as => a: 1 b: 2 c: 89 - * - * @throws Throwable - */ - @Test - public void testNoBufferingOrBlockingOfSequence() throws Throwable { - final CountDownLatch finished = new CountDownLatch(1); - final int COUNT = 30; - final CountDownLatch timeHasPassed = new CountDownLatch(COUNT); - final AtomicBoolean running = new AtomicBoolean(true); - final AtomicInteger count = new AtomicInteger(0); - final Observable obs = Observable.create(new OnSubscribeFunc() { - - @Override - public Subscription onSubscribe(final Observer o) { - new Thread(new Runnable() { - - @Override - public void run() { - try { - while (running.get()) { - o.onNext(count.incrementAndGet()); - timeHasPassed.countDown(); - } - o.onCompleted(); - } catch (Throwable e) { - o.onError(e); - } finally { - finished.countDown(); - } - } - }).start(); - return Subscriptions.empty(); - } - - }); - - Iterator it = next(obs).iterator(); - - assertTrue(it.hasNext()); - int a = it.next(); - assertTrue(it.hasNext()); - int b = it.next(); - // we should have a different value - assertTrue("a and b should be different", a != b); - - // wait for some time (if times out we are blocked somewhere so fail ... set very high for very slow, constrained machines) - timeHasPassed.await(8000, TimeUnit.MILLISECONDS); - - assertTrue(it.hasNext()); - int c = it.next(); - - assertTrue("c should not just be the next in sequence", c != (b + 1)); - assertTrue("expected that c [" + c + "] is higher than or equal to " + COUNT, c >= COUNT); - - assertTrue(it.hasNext()); - int d = it.next(); - assertTrue(d > c); - - // shut down the thread - running.set(false); - - finished.await(); - - assertFalse(it.hasNext()); - - System.out.println("a: " + a + " b: " + b + " c: " + c); - } - - } - } diff --git a/rxjava-core/src/main/java/rx/operators/OperationObserveOn.java b/rxjava-core/src/main/java/rx/operators/OperationObserveOn.java index aef1cb9548..e1272b8152 100644 --- a/rxjava-core/src/main/java/rx/operators/OperationObserveOn.java +++ b/rxjava-core/src/main/java/rx/operators/OperationObserveOn.java @@ -15,27 +15,13 @@ */ package rx.operators; -import static org.junit.Assert.*; -import static org.mockito.Mockito.*; - -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicReference; - -import org.junit.Test; -import org.mockito.InOrder; -import org.mockito.invocation.InvocationOnMock; -import org.mockito.stubbing.Answer; - import rx.Observable; import rx.Observable.OnSubscribeFunc; import rx.Observer; import rx.Scheduler; import rx.Subscription; import rx.concurrency.ImmediateScheduler; -import rx.concurrency.Schedulers; import rx.subscriptions.CompositeSubscription; -import rx.util.functions.Func2; /** * Asynchronously notify Observers on the specified Scheduler. @@ -69,58 +55,4 @@ public Subscription onSubscribe(final Observer observer) { } } } - - public static class UnitTest { - - /** - * This is testing a no-op path since it uses Schedulers.immediate() which will not do scheduling. - */ - @Test - @SuppressWarnings("unchecked") - public void testObserveOn() { - Observer observer = mock(Observer.class); - Observable.create(observeOn(Observable.from(1, 2, 3), Schedulers.immediate())).subscribe(observer); - - verify(observer, times(1)).onNext(1); - verify(observer, times(1)).onNext(2); - verify(observer, times(1)).onNext(3); - verify(observer, times(1)).onCompleted(); - } - - @Test - @SuppressWarnings("unchecked") - public void testOrdering() throws InterruptedException { - Observable obs = Observable.from("one", null, "two", "three", "four"); - - Observer observer = mock(Observer.class); - - InOrder inOrder = inOrder(observer); - - final CountDownLatch completedLatch = new CountDownLatch(1); - doAnswer(new Answer() { - - @Override - public Void answer(InvocationOnMock invocation) throws Throwable { - completedLatch.countDown(); - return null; - } - }).when(observer).onCompleted(); - - obs.observeOn(Schedulers.threadPoolForComputation()).subscribe(observer); - - if (!completedLatch.await(1000, TimeUnit.MILLISECONDS)) { - fail("timed out waiting"); - } - - inOrder.verify(observer, times(1)).onNext("one"); - inOrder.verify(observer, times(1)).onNext(null); - inOrder.verify(observer, times(1)).onNext("two"); - inOrder.verify(observer, times(1)).onNext("three"); - inOrder.verify(observer, times(1)).onNext("four"); - inOrder.verify(observer, times(1)).onCompleted(); - inOrder.verifyNoMoreInteractions(); - } - - } - } diff --git a/rxjava-core/src/main/java/rx/operators/OperationOnErrorResumeNextViaFunction.java b/rxjava-core/src/main/java/rx/operators/OperationOnErrorResumeNextViaFunction.java index 28bf8be311..3f63463cf9 100644 --- a/rxjava-core/src/main/java/rx/operators/OperationOnErrorResumeNextViaFunction.java +++ b/rxjava-core/src/main/java/rx/operators/OperationOnErrorResumeNextViaFunction.java @@ -15,24 +15,16 @@ */ package rx.operators; -import static org.junit.Assert.*; -import static org.mockito.Matchers.*; -import static org.mockito.Mockito.*; - -import java.util.Arrays; -import java.util.concurrent.atomic.AtomicReference; - -import org.junit.Test; -import org.mockito.Mockito; - import rx.Observable; import rx.Observable.OnSubscribeFunc; import rx.Observer; import rx.Subscription; -import rx.subscriptions.Subscriptions; import rx.util.CompositeException; import rx.util.functions.Func1; +import java.util.Arrays; +import java.util.concurrent.atomic.AtomicReference; + /** * Instruct an Observable to pass control to another Observable (the return value of a function) * rather than invoking onError if it encounters an error. @@ -122,155 +114,4 @@ public void unsubscribe() { }; } } - - public static class UnitTest { - - @Test - public void testResumeNextWithSynchronousExecution() { - final AtomicReference receivedException = new AtomicReference(); - Observable w = Observable.create(new OnSubscribeFunc() { - - @Override - public Subscription onSubscribe(Observer observer) { - observer.onNext("one"); - observer.onError(new Throwable("injected failure")); - return Subscriptions.empty(); - } - }); - - Func1> resume = new Func1>() { - - @Override - public Observable call(Throwable t1) { - receivedException.set(t1); - return Observable.from("twoResume", "threeResume"); - } - - }; - Observable observable = Observable.create(onErrorResumeNextViaFunction(w, resume)); - - @SuppressWarnings("unchecked") - Observer aObserver = mock(Observer.class); - observable.subscribe(aObserver); - - verify(aObserver, Mockito.never()).onError(any(Throwable.class)); - verify(aObserver, times(1)).onCompleted(); - verify(aObserver, times(1)).onNext("one"); - verify(aObserver, Mockito.never()).onNext("two"); - verify(aObserver, Mockito.never()).onNext("three"); - verify(aObserver, times(1)).onNext("twoResume"); - verify(aObserver, times(1)).onNext("threeResume"); - assertNotNull(receivedException.get()); - } - - @Test - public void testResumeNextWithAsyncExecution() { - final AtomicReference receivedException = new AtomicReference(); - Subscription s = mock(Subscription.class); - TestObservable w = new TestObservable(s, "one"); - Func1> resume = new Func1>() { - - @Override - public Observable call(Throwable t1) { - receivedException.set(t1); - return Observable.from("twoResume", "threeResume"); - } - - }; - Observable observable = Observable.create(onErrorResumeNextViaFunction(Observable.create(w), resume)); - - @SuppressWarnings("unchecked") - Observer aObserver = mock(Observer.class); - observable.subscribe(aObserver); - - try { - w.t.join(); - } catch (InterruptedException e) { - fail(e.getMessage()); - } - - verify(aObserver, Mockito.never()).onError(any(Throwable.class)); - verify(aObserver, times(1)).onCompleted(); - verify(aObserver, times(1)).onNext("one"); - verify(aObserver, Mockito.never()).onNext("two"); - verify(aObserver, Mockito.never()).onNext("three"); - verify(aObserver, times(1)).onNext("twoResume"); - verify(aObserver, times(1)).onNext("threeResume"); - assertNotNull(receivedException.get()); - } - - /** - * Test that when a function throws an exception this is propagated through onError - */ - @Test - public void testFunctionThrowsError() { - Subscription s = mock(Subscription.class); - TestObservable w = new TestObservable(s, "one"); - Func1> resume = new Func1>() { - - @Override - public Observable call(Throwable t1) { - throw new RuntimeException("exception from function"); - } - - }; - Observable observable = Observable.create(onErrorResumeNextViaFunction(Observable.create(w), resume)); - - @SuppressWarnings("unchecked") - Observer aObserver = mock(Observer.class); - observable.subscribe(aObserver); - - try { - w.t.join(); - } catch (InterruptedException e) { - fail(e.getMessage()); - } - - // we should get the "one" value before the error - verify(aObserver, times(1)).onNext("one"); - - // we should have received an onError call on the Observer since the resume function threw an exception - verify(aObserver, times(1)).onError(any(Throwable.class)); - verify(aObserver, times(0)).onCompleted(); - } - - private static class TestObservable implements OnSubscribeFunc { - - final Subscription s; - final String[] values; - Thread t = null; - - public TestObservable(Subscription s, String... values) { - this.s = s; - this.values = values; - } - - @Override - public Subscription onSubscribe(final Observer observer) { - System.out.println("TestObservable subscribed to ..."); - t = new Thread(new Runnable() { - - @Override - public void run() { - try { - System.out.println("running TestObservable thread"); - for (String s : values) { - System.out.println("TestObservable onNext: " + s); - observer.onNext(s); - } - throw new RuntimeException("Forced Failure"); - } catch (Throwable e) { - observer.onError(e); - } - } - - }); - System.out.println("starting TestObservable thread"); - t.start(); - System.out.println("done starting TestObservable thread"); - return s; - } - - } - } } diff --git a/rxjava-core/src/main/java/rx/operators/OperationOnErrorResumeNextViaObservable.java b/rxjava-core/src/main/java/rx/operators/OperationOnErrorResumeNextViaObservable.java index 3b49ce5f9c..8e09ce027a 100644 --- a/rxjava-core/src/main/java/rx/operators/OperationOnErrorResumeNextViaObservable.java +++ b/rxjava-core/src/main/java/rx/operators/OperationOnErrorResumeNextViaObservable.java @@ -15,20 +15,12 @@ */ package rx.operators; -import static org.junit.Assert.*; -import static org.mockito.Matchers.*; -import static org.mockito.Mockito.*; - -import java.util.concurrent.atomic.AtomicReference; - -import org.junit.Test; -import org.mockito.Mockito; - import rx.Observable; import rx.Observable.OnSubscribeFunc; import rx.Observer; import rx.Subscription; -import rx.util.functions.Func1; + +import java.util.concurrent.atomic.AtomicReference; /** * Instruct an Observable to pass control to another Observable rather than invoking @@ -116,119 +108,4 @@ public void unsubscribe() { }; } } - - public static class UnitTest { - - @Test - public void testResumeNext() { - Subscription s = mock(Subscription.class); - // Trigger failure on second element - TestObservable f = new TestObservable(s, "one", "fail", "two", "three"); - Observable w = Observable.create(f); - Observable resume = Observable.from("twoResume", "threeResume"); - Observable observable = Observable.create(onErrorResumeNextViaObservable(w, resume)); - - @SuppressWarnings("unchecked") - Observer aObserver = mock(Observer.class); - observable.subscribe(aObserver); - - try { - f.t.join(); - } catch (InterruptedException e) { - fail(e.getMessage()); - } - - verify(aObserver, Mockito.never()).onError(any(Throwable.class)); - verify(aObserver, times(1)).onCompleted(); - verify(aObserver, times(1)).onNext("one"); - verify(aObserver, Mockito.never()).onNext("two"); - verify(aObserver, Mockito.never()).onNext("three"); - verify(aObserver, times(1)).onNext("twoResume"); - verify(aObserver, times(1)).onNext("threeResume"); - } - - @Test - public void testMapResumeAsyncNext() { - Subscription sr = mock(Subscription.class); - // Trigger multiple failures - Observable w = Observable.from("one", "fail", "two", "three", "fail"); - // Resume Observable is async - TestObservable f = new TestObservable(sr, "twoResume", "threeResume"); - Observable resume = Observable.create(f); - - // Introduce map function that fails intermittently (Map does not prevent this when the observer is a - // rx.operator incl onErrorResumeNextViaObservable) - w = w.map(new Func1() { - public String call(String s) { - if ("fail".equals(s)) - throw new RuntimeException("Forced Failure"); - System.out.println("BadMapper:" + s); - return s; - } - }); - - Observable observable = Observable.create(onErrorResumeNextViaObservable(w, resume)); - - @SuppressWarnings("unchecked") - Observer aObserver = mock(Observer.class); - observable.subscribe(aObserver); - - try { - f.t.join(); - } catch (InterruptedException e) { - fail(e.getMessage()); - } - - verify(aObserver, Mockito.never()).onError(any(Throwable.class)); - verify(aObserver, times(1)).onCompleted(); - verify(aObserver, times(1)).onNext("one"); - verify(aObserver, Mockito.never()).onNext("two"); - verify(aObserver, Mockito.never()).onNext("three"); - verify(aObserver, times(1)).onNext("twoResume"); - verify(aObserver, times(1)).onNext("threeResume"); - } - - private static class TestObservable implements OnSubscribeFunc { - - final Subscription s; - final String[] values; - Thread t = null; - - public TestObservable(Subscription s, String... values) { - this.s = s; - this.values = values; - } - - @Override - public Subscription onSubscribe(final Observer observer) { - System.out.println("TestObservable subscribed to ..."); - t = new Thread(new Runnable() { - - @Override - public void run() { - try { - System.out.println("running TestObservable thread"); - for (String s : values) { - if ("fail".equals(s)) - throw new RuntimeException("Forced Failure"); - System.out.println("TestObservable onNext: " + s); - observer.onNext(s); - } - System.out.println("TestObservable onCompleted"); - observer.onCompleted(); - } catch (Throwable e) { - System.out.println("TestObservable onError: " + e); - observer.onError(e); - } - } - - }); - System.out.println("starting TestObservable thread"); - t.start(); - System.out.println("done starting TestObservable thread"); - return s; - } - - } - } } diff --git a/rxjava-core/src/main/java/rx/operators/OperationOnErrorReturn.java b/rxjava-core/src/main/java/rx/operators/OperationOnErrorReturn.java index 02a268c04a..fd04d078b1 100644 --- a/rxjava-core/src/main/java/rx/operators/OperationOnErrorReturn.java +++ b/rxjava-core/src/main/java/rx/operators/OperationOnErrorReturn.java @@ -15,16 +15,6 @@ */ package rx.operators; -import static org.junit.Assert.*; -import static org.mockito.Matchers.*; -import static org.mockito.Mockito.*; - -import java.util.Arrays; -import java.util.concurrent.atomic.AtomicReference; - -import org.junit.Test; -import org.mockito.Mockito; - import rx.Observable; import rx.Observable.OnSubscribeFunc; import rx.Observer; @@ -32,6 +22,9 @@ import rx.util.CompositeException; import rx.util.functions.Func1; +import java.util.Arrays; +import java.util.concurrent.atomic.AtomicReference; + /** * Instruct an Observable to emit a particular item to its Observer's onNext method * rather than invoking onError if it encounters an error. @@ -125,119 +118,4 @@ public void unsubscribe() { }; } } - - public static class UnitTest { - - @Test - public void testResumeNext() { - Subscription s = mock(Subscription.class); - TestObservable f = new TestObservable(s, "one"); - Observable w = Observable.create(f); - final AtomicReference capturedException = new AtomicReference(); - - Observable observable = Observable.create(onErrorReturn(w, new Func1() { - - @Override - public String call(Throwable e) { - capturedException.set(e); - return "failure"; - } - - })); - - @SuppressWarnings("unchecked") - Observer aObserver = mock(Observer.class); - observable.subscribe(aObserver); - - try { - f.t.join(); - } catch (InterruptedException e) { - fail(e.getMessage()); - } - - verify(aObserver, Mockito.never()).onError(any(Throwable.class)); - verify(aObserver, times(1)).onCompleted(); - verify(aObserver, times(1)).onNext("one"); - verify(aObserver, times(1)).onNext("failure"); - assertNotNull(capturedException.get()); - } - - /** - * Test that when a function throws an exception this is propagated through onError - */ - @Test - public void testFunctionThrowsError() { - Subscription s = mock(Subscription.class); - TestObservable f = new TestObservable(s, "one"); - Observable w = Observable.create(f); - final AtomicReference capturedException = new AtomicReference(); - - Observable observable = Observable.create(onErrorReturn(w, new Func1() { - - @Override - public String call(Throwable e) { - capturedException.set(e); - throw new RuntimeException("exception from function"); - } - - })); - - @SuppressWarnings("unchecked") - Observer aObserver = mock(Observer.class); - observable.subscribe(aObserver); - - try { - f.t.join(); - } catch (InterruptedException e) { - fail(e.getMessage()); - } - - // we should get the "one" value before the error - verify(aObserver, times(1)).onNext("one"); - - // we should have received an onError call on the Observer since the resume function threw an exception - verify(aObserver, times(1)).onError(any(Throwable.class)); - verify(aObserver, times(0)).onCompleted(); - assertNotNull(capturedException.get()); - } - - private static class TestObservable implements OnSubscribeFunc { - - final Subscription s; - final String[] values; - Thread t = null; - - public TestObservable(Subscription s, String... values) { - this.s = s; - this.values = values; - } - - @Override - public Subscription onSubscribe(final Observer observer) { - System.out.println("TestObservable subscribed to ..."); - t = new Thread(new Runnable() { - - @Override - public void run() { - try { - System.out.println("running TestObservable thread"); - for (String s : values) { - System.out.println("TestObservable onNext: " + s); - observer.onNext(s); - } - throw new RuntimeException("Forced Failure"); - } catch (Throwable e) { - observer.onError(e); - } - } - - }); - System.out.println("starting TestObservable thread"); - t.start(); - System.out.println("done starting TestObservable thread"); - return s; - } - - } - } } diff --git a/rxjava-core/src/main/java/rx/operators/OperationOnExceptionResumeNextViaObservable.java b/rxjava-core/src/main/java/rx/operators/OperationOnExceptionResumeNextViaObservable.java index 9642ed9269..20e8fce867 100644 --- a/rxjava-core/src/main/java/rx/operators/OperationOnExceptionResumeNextViaObservable.java +++ b/rxjava-core/src/main/java/rx/operators/OperationOnExceptionResumeNextViaObservable.java @@ -15,20 +15,12 @@ */ package rx.operators; -import static org.junit.Assert.*; -import static org.mockito.Matchers.*; -import static org.mockito.Mockito.*; - -import java.util.concurrent.atomic.AtomicReference; - -import org.junit.Test; -import org.mockito.Mockito; - import rx.Observable; import rx.Observable.OnSubscribeFunc; import rx.Observer; import rx.Subscription; -import rx.util.functions.Func1; + +import java.util.concurrent.atomic.AtomicReference; /** * Instruct an Observable to pass control to another Observable rather than invoking @@ -123,216 +115,4 @@ public void unsubscribe() { }; } } - - public static class UnitTest { - - @Test - public void testResumeNextWithException() { - Subscription s = mock(Subscription.class); - // Trigger failure on second element - TestObservable f = new TestObservable(s, "one", "EXCEPTION", "two", "three"); - Observable w = Observable.create(f); - Observable resume = Observable.from("twoResume", "threeResume"); - Observable observable = Observable.create(onExceptionResumeNextViaObservable(w, resume)); - - @SuppressWarnings("unchecked") - Observer aObserver = mock(Observer.class); - observable.subscribe(aObserver); - - try { - f.t.join(); - } catch (InterruptedException e) { - fail(e.getMessage()); - } - - verify(aObserver, times(1)).onNext("one"); - verify(aObserver, Mockito.never()).onNext("two"); - verify(aObserver, Mockito.never()).onNext("three"); - verify(aObserver, times(1)).onNext("twoResume"); - verify(aObserver, times(1)).onNext("threeResume"); - verify(aObserver, Mockito.never()).onError(any(Throwable.class)); - verify(aObserver, times(1)).onCompleted(); - verifyNoMoreInteractions(aObserver); - } - - @Test - public void testResumeNextWithRuntimeException() { - Subscription s = mock(Subscription.class); - // Trigger failure on second element - TestObservable f = new TestObservable(s, "one", "RUNTIMEEXCEPTION", "two", "three"); - Observable w = Observable.create(f); - Observable resume = Observable.from("twoResume", "threeResume"); - Observable observable = Observable.create(onExceptionResumeNextViaObservable(w, resume)); - - @SuppressWarnings("unchecked") - Observer aObserver = mock(Observer.class); - observable.subscribe(aObserver); - - try { - f.t.join(); - } catch (InterruptedException e) { - fail(e.getMessage()); - } - - verify(aObserver, times(1)).onNext("one"); - verify(aObserver, Mockito.never()).onNext("two"); - verify(aObserver, Mockito.never()).onNext("three"); - verify(aObserver, times(1)).onNext("twoResume"); - verify(aObserver, times(1)).onNext("threeResume"); - verify(aObserver, Mockito.never()).onError(any(Throwable.class)); - verify(aObserver, times(1)).onCompleted(); - verifyNoMoreInteractions(aObserver); - } - - @Test - public void testThrowablePassesThru() { - Subscription s = mock(Subscription.class); - // Trigger failure on second element - TestObservable f = new TestObservable(s, "one", "THROWABLE", "two", "three"); - Observable w = Observable.create(f); - Observable resume = Observable.from("twoResume", "threeResume"); - Observable observable = Observable.create(onExceptionResumeNextViaObservable(w, resume)); - - @SuppressWarnings("unchecked") - Observer aObserver = mock(Observer.class); - observable.subscribe(aObserver); - - try { - f.t.join(); - } catch (InterruptedException e) { - fail(e.getMessage()); - } - - verify(aObserver, times(1)).onNext("one"); - verify(aObserver, never()).onNext("two"); - verify(aObserver, never()).onNext("three"); - verify(aObserver, never()).onNext("twoResume"); - verify(aObserver, never()).onNext("threeResume"); - verify(aObserver, times(1)).onError(any(Throwable.class)); - verify(aObserver, never()).onCompleted(); - verifyNoMoreInteractions(aObserver); - } - - @Test - public void testErrorPassesThru() { - Subscription s = mock(Subscription.class); - // Trigger failure on second element - TestObservable f = new TestObservable(s, "one", "ERROR", "two", "three"); - Observable w = Observable.create(f); - Observable resume = Observable.from("twoResume", "threeResume"); - Observable observable = Observable.create(onExceptionResumeNextViaObservable(w, resume)); - - @SuppressWarnings("unchecked") - Observer aObserver = mock(Observer.class); - observable.subscribe(aObserver); - - try { - f.t.join(); - } catch (InterruptedException e) { - fail(e.getMessage()); - } - - verify(aObserver, times(1)).onNext("one"); - verify(aObserver, never()).onNext("two"); - verify(aObserver, never()).onNext("three"); - verify(aObserver, never()).onNext("twoResume"); - verify(aObserver, never()).onNext("threeResume"); - verify(aObserver, times(1)).onError(any(Throwable.class)); - verify(aObserver, never()).onCompleted(); - verifyNoMoreInteractions(aObserver); - } - - @Test - public void testMapResumeAsyncNext() { - Subscription sr = mock(Subscription.class); - // Trigger multiple failures - Observable w = Observable.from("one", "fail", "two", "three", "fail"); - // Resume Observable is async - TestObservable f = new TestObservable(sr, "twoResume", "threeResume"); - Observable resume = Observable.create(f); - - // Introduce map function that fails intermittently (Map does not prevent this when the observer is a - // rx.operator incl onErrorResumeNextViaObservable) - w = w.map(new Func1() { - public String call(String s) { - if ("fail".equals(s)) - throw new RuntimeException("Forced Failure"); - System.out.println("BadMapper:" + s); - return s; - } - }); - - Observable observable = Observable.create(onExceptionResumeNextViaObservable(w, resume)); - - @SuppressWarnings("unchecked") - Observer aObserver = mock(Observer.class); - observable.subscribe(aObserver); - - try { - // if the thread gets started (which it shouldn't if it's working correctly) - if (f.t != null) { - f.t.join(); - } - } catch (InterruptedException e) { - fail(e.getMessage()); - } - - verify(aObserver, times(1)).onNext("one"); - verify(aObserver, never()).onNext("two"); - verify(aObserver, never()).onNext("three"); - verify(aObserver, times(1)).onNext("twoResume"); - verify(aObserver, times(1)).onNext("threeResume"); - verify(aObserver, Mockito.never()).onError(any(Throwable.class)); - verify(aObserver, times(1)).onCompleted(); - } - - private static class TestObservable implements OnSubscribeFunc { - - final Subscription s; - final String[] values; - Thread t = null; - - public TestObservable(Subscription s, String... values) { - this.s = s; - this.values = values; - } - - @Override - public Subscription onSubscribe(final Observer observer) { - System.out.println("TestObservable subscribed to ..."); - t = new Thread(new Runnable() { - - @Override - public void run() { - try { - System.out.println("running TestObservable thread"); - for (String s : values) { - if ("EXCEPTION".equals(s)) - throw new Exception("Forced Exception"); - else if ("RUNTIMEEXCEPTION".equals(s)) - throw new RuntimeException("Forced RuntimeException"); - else if ("ERROR".equals(s)) - throw new Error("Forced Error"); - else if ("THROWABLE".equals(s)) - throw new Throwable("Forced Throwable"); - System.out.println("TestObservable onNext: " + s); - observer.onNext(s); - } - System.out.println("TestObservable onCompleted"); - observer.onCompleted(); - } catch (Throwable e) { - System.out.println("TestObservable onError: " + e); - observer.onError(e); - } - } - - }); - System.out.println("starting TestObservable thread"); - t.start(); - System.out.println("done starting TestObservable thread"); - return s; - } - - } - } } diff --git a/rxjava-core/src/main/java/rx/operators/OperationParallel.java b/rxjava-core/src/main/java/rx/operators/OperationParallel.java index 125fd2d291..25a955e616 100644 --- a/rxjava-core/src/main/java/rx/operators/OperationParallel.java +++ b/rxjava-core/src/main/java/rx/operators/OperationParallel.java @@ -15,20 +15,15 @@ */ package rx.operators; -import static org.junit.Assert.*; - -import java.util.concurrent.atomic.AtomicInteger; - -import org.junit.Test; - import rx.Observable; import rx.Scheduler; import rx.concurrency.Schedulers; import rx.observables.GroupedObservable; -import rx.util.functions.Action1; import rx.util.functions.Func0; import rx.util.functions.Func1; +import java.util.concurrent.atomic.AtomicInteger; + /** * Identifies unit of work that can be executed in parallel on a given Scheduler. */ @@ -61,39 +56,4 @@ public Observable call(GroupedObservable group) { } }); } - - public static class UnitTest { - - @Test - public void testParallel() { - int NUM = 1000; - final AtomicInteger count = new AtomicInteger(); - Observable.range(1, NUM).parallel( - new Func1, Observable>() { - - @Override - public Observable call(Observable o) { - return o.map(new Func1() { - - @Override - public Integer[] call(Integer t) { - return new Integer[] { t, t * 99 }; - } - - }); - } - }).toBlockingObservable().forEach(new Action1() { - - @Override - public void call(Integer[] v) { - count.incrementAndGet(); - System.out.println("V: " + v[0] + " R: " + v[1] + " Thread: " + Thread.currentThread()); - } - - }); - - // just making sure we finish and get the number we expect - assertEquals(NUM, count.get()); - } - } } diff --git a/rxjava-core/src/main/java/rx/operators/OperationRetry.java b/rxjava-core/src/main/java/rx/operators/OperationRetry.java index 0f664ee3ec..864caf3c4e 100644 --- a/rxjava-core/src/main/java/rx/operators/OperationRetry.java +++ b/rxjava-core/src/main/java/rx/operators/OperationRetry.java @@ -15,13 +15,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import static org.mockito.Matchers.*; -import static org.mockito.Mockito.*; - -import java.util.concurrent.atomic.AtomicInteger; - -import org.junit.Test; -import org.mockito.InOrder; import rx.Observable; import rx.Observable.OnSubscribeFunc; @@ -31,9 +24,10 @@ import rx.concurrency.Schedulers; import rx.subscriptions.CompositeSubscription; import rx.subscriptions.MultipleAssignmentSubscription; -import rx.subscriptions.Subscriptions; import rx.util.functions.Func2; +import java.util.concurrent.atomic.AtomicInteger; + public class OperationRetry { private static final int INFINITE_RETRY = -1; @@ -103,104 +97,4 @@ public void onNext(T v) { } } - - public static class UnitTest { - - @Test - public void testOriginFails() { - @SuppressWarnings("unchecked") - Observer observer = mock(Observer.class); - Observable origin = Observable.create(new FuncWithErrors(2)); - origin.subscribe(observer); - - InOrder inOrder = inOrder(observer); - inOrder.verify(observer, times(1)).onNext("beginningEveryTime"); - inOrder.verify(observer, times(1)).onError(any(RuntimeException.class)); - inOrder.verify(observer, never()).onNext("onSuccessOnly"); - inOrder.verify(observer, never()).onCompleted(); - } - - @Test - public void testRetryFail() { - int NUM_RETRIES = 1; - int NUM_FAILURES = 2; - @SuppressWarnings("unchecked") - Observer observer = mock(Observer.class); - Observable origin = Observable.create(new FuncWithErrors(NUM_FAILURES)); - Observable.create(retry(origin, NUM_RETRIES)).subscribe(observer); - - InOrder inOrder = inOrder(observer); - // should show 2 attempts (first time fail, second time (1st retry) fail) - inOrder.verify(observer, times(1 + NUM_RETRIES)).onNext("beginningEveryTime"); - // should only retry once, fail again and emit onError - inOrder.verify(observer, times(1)).onError(any(RuntimeException.class)); - // no success - inOrder.verify(observer, never()).onNext("onSuccessOnly"); - inOrder.verify(observer, never()).onCompleted(); - inOrder.verifyNoMoreInteractions(); - } - - @Test - public void testRetrySuccess() { - int NUM_RETRIES = 3; - int NUM_FAILURES = 2; - @SuppressWarnings("unchecked") - Observer observer = mock(Observer.class); - Observable origin = Observable.create(new FuncWithErrors(NUM_FAILURES)); - Observable.create(retry(origin, NUM_RETRIES)).subscribe(observer); - - InOrder inOrder = inOrder(observer); - // should show 3 attempts - inOrder.verify(observer, times(1 + NUM_FAILURES)).onNext("beginningEveryTime"); - // should have no errors - inOrder.verify(observer, never()).onError(any(Throwable.class)); - // should have a single success - inOrder.verify(observer, times(1)).onNext("onSuccessOnly"); - // should have a single successful onCompleted - inOrder.verify(observer, times(1)).onCompleted(); - inOrder.verifyNoMoreInteractions(); - } - - @Test - public void testInfiniteRetry() { - int NUM_FAILURES = 20; - @SuppressWarnings("unchecked") - Observer observer = mock(Observer.class); - Observable origin = Observable.create(new FuncWithErrors(NUM_FAILURES)); - Observable.create(retry(origin)).subscribe(observer); - - InOrder inOrder = inOrder(observer); - // should show 3 attempts - inOrder.verify(observer, times(1 + NUM_FAILURES)).onNext("beginningEveryTime"); - // should have no errors - inOrder.verify(observer, never()).onError(any(Throwable.class)); - // should have a single success - inOrder.verify(observer, times(1)).onNext("onSuccessOnly"); - // should have a single successful onCompleted - inOrder.verify(observer, times(1)).onCompleted(); - inOrder.verifyNoMoreInteractions(); - } - - public static class FuncWithErrors implements OnSubscribeFunc { - - private final int numFailures; - private final AtomicInteger count = new AtomicInteger(0); - - FuncWithErrors(int count) { - this.numFailures = count; - } - - @Override - public Subscription onSubscribe(Observer o) { - o.onNext("beginningEveryTime"); - if (count.incrementAndGet() <= numFailures) { - o.onError(new RuntimeException("forced failure: " + count.get())); - } else { - o.onNext("onSuccessOnly"); - o.onCompleted(); - } - return Subscriptions.empty(); - } - } - } } diff --git a/rxjava-core/src/main/java/rx/operators/OperationSample.java b/rxjava-core/src/main/java/rx/operators/OperationSample.java index 3be189f32b..32c58b1f04 100644 --- a/rxjava-core/src/main/java/rx/operators/OperationSample.java +++ b/rxjava-core/src/main/java/rx/operators/OperationSample.java @@ -15,28 +15,19 @@ */ package rx.operators; -import static org.mockito.Matchers.*; -import static org.mockito.Mockito.*; - -import java.util.concurrent.Executors; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicBoolean; -import java.util.concurrent.atomic.AtomicReference; - -import org.junit.Before; -import org.junit.Test; -import org.mockito.InOrder; - import rx.Observable; import rx.Observable.OnSubscribeFunc; import rx.Observer; import rx.Scheduler; import rx.Subscription; import rx.concurrency.Schedulers; -import rx.concurrency.TestScheduler; import rx.subscriptions.Subscriptions; import rx.util.functions.Action0; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicReference; + /** * Returns an Observable that emits the results of sampling the items emitted by the source * Observable at a specified time interval. @@ -122,79 +113,4 @@ public void call() { }); } } - - public static class UnitTest { - private TestScheduler scheduler; - private Observer observer; - - @Before - @SuppressWarnings("unchecked") // due to mocking - public void before() { - scheduler = new TestScheduler(); - observer = mock(Observer.class); - } - - @Test - public void testSample() { - Observable source = Observable.create(new OnSubscribeFunc() { - @Override - public Subscription onSubscribe(final Observer observer1) { - scheduler.schedule(new Action0() { - @Override - public void call() { - observer1.onNext(1L); - } - }, 1, TimeUnit.SECONDS); - scheduler.schedule(new Action0() { - @Override - public void call() { - observer1.onNext(2L); - } - }, 2, TimeUnit.SECONDS); - scheduler.schedule(new Action0() { - @Override - public void call() { - observer1.onCompleted(); - } - }, 3, TimeUnit.SECONDS); - - return Subscriptions.empty(); - } - }); - - Observable sampled = Observable.create(OperationSample.sample(source, 400L, TimeUnit.MILLISECONDS, scheduler)); - sampled.subscribe(observer); - - InOrder inOrder = inOrder(observer); - - scheduler.advanceTimeTo(800L, TimeUnit.MILLISECONDS); - verify(observer, never()).onNext(any(Long.class)); - verify(observer, never()).onCompleted(); - verify(observer, never()).onError(any(Throwable.class)); - - scheduler.advanceTimeTo(1200L, TimeUnit.MILLISECONDS); - inOrder.verify(observer, times(1)).onNext(1L); - verify(observer, never()).onNext(2L); - verify(observer, never()).onCompleted(); - verify(observer, never()).onError(any(Throwable.class)); - - scheduler.advanceTimeTo(1600L, TimeUnit.MILLISECONDS); - inOrder.verify(observer, times(1)).onNext(1L); - verify(observer, never()).onNext(2L); - verify(observer, never()).onCompleted(); - verify(observer, never()).onError(any(Throwable.class)); - - scheduler.advanceTimeTo(2000L, TimeUnit.MILLISECONDS); - inOrder.verify(observer, never()).onNext(1L); - inOrder.verify(observer, times(1)).onNext(2L); - verify(observer, never()).onCompleted(); - verify(observer, never()).onError(any(Throwable.class)); - - scheduler.advanceTimeTo(3000L, TimeUnit.MILLISECONDS); - inOrder.verify(observer, never()).onNext(1L); - inOrder.verify(observer, times(2)).onNext(2L); - verify(observer, times(1)).onCompleted(); - verify(observer, never()).onError(any(Throwable.class)); - } - } } diff --git a/rxjava-core/src/main/java/rx/operators/OperationScan.java b/rxjava-core/src/main/java/rx/operators/OperationScan.java index 513646b8ef..4d0cfc95d0 100644 --- a/rxjava-core/src/main/java/rx/operators/OperationScan.java +++ b/rxjava-core/src/main/java/rx/operators/OperationScan.java @@ -15,13 +15,6 @@ */ package rx.operators; -import static org.mockito.Matchers.*; -import static org.mockito.Mockito.*; - -import org.junit.Before; -import org.junit.Test; -import org.mockito.MockitoAnnotations; - import rx.Observable; import rx.Observable.OnSubscribeFunc; import rx.Observer; @@ -171,92 +164,4 @@ public void onCompleted() { observer.onCompleted(); } } - - public static class UnitTest { - - @Before - public void before() { - MockitoAnnotations.initMocks(this); - } - - @Test - public void testScanIntegersWithInitialValue() { - @SuppressWarnings("unchecked") - Observer observer = mock(Observer.class); - - Observable observable = Observable.from(1, 2, 3); - - Observable m = Observable.create(scan(observable, "", new Func2() { - - @Override - public String call(String s, Integer n) { - return s + n.toString(); - } - - })); - m.subscribe(observer); - - verify(observer, never()).onError(any(Throwable.class)); - verify(observer, times(1)).onNext(""); - verify(observer, times(1)).onNext("1"); - verify(observer, times(1)).onNext("12"); - verify(observer, times(1)).onNext("123"); - verify(observer, times(4)).onNext(anyString()); - verify(observer, times(1)).onCompleted(); - verify(observer, never()).onError(any(Throwable.class)); - } - - @Test - public void testScanIntegersWithoutInitialValue() { - @SuppressWarnings("unchecked") - Observer Observer = mock(Observer.class); - - Observable observable = Observable.from(1, 2, 3); - - Observable m = Observable.create(scan(observable, new Func2() { - - @Override - public Integer call(Integer t1, Integer t2) { - return t1 + t2; - } - - })); - m.subscribe(Observer); - - verify(Observer, never()).onError(any(Throwable.class)); - verify(Observer, never()).onNext(0); - verify(Observer, times(1)).onNext(1); - verify(Observer, times(1)).onNext(3); - verify(Observer, times(1)).onNext(6); - verify(Observer, times(3)).onNext(anyInt()); - verify(Observer, times(1)).onCompleted(); - verify(Observer, never()).onError(any(Throwable.class)); - } - - @Test - public void testScanIntegersWithoutInitialValueAndOnlyOneValue() { - @SuppressWarnings("unchecked") - Observer Observer = mock(Observer.class); - - Observable observable = Observable.from(1); - - Observable m = Observable.create(scan(observable, new Func2() { - - @Override - public Integer call(Integer t1, Integer t2) { - return t1 + t2; - } - - })); - m.subscribe(Observer); - - verify(Observer, never()).onError(any(Throwable.class)); - verify(Observer, never()).onNext(0); - verify(Observer, times(1)).onNext(1); - verify(Observer, times(1)).onNext(anyInt()); - verify(Observer, times(1)).onCompleted(); - verify(Observer, never()).onError(any(Throwable.class)); - } - } - } diff --git a/rxjava-core/src/main/java/rx/operators/OperationSkip.java b/rxjava-core/src/main/java/rx/operators/OperationSkip.java index 11fb10f1b5..63b873d826 100644 --- a/rxjava-core/src/main/java/rx/operators/OperationSkip.java +++ b/rxjava-core/src/main/java/rx/operators/OperationSkip.java @@ -15,18 +15,13 @@ */ package rx.operators; -import static org.mockito.Matchers.*; -import static org.mockito.Mockito.*; - -import java.util.concurrent.atomic.AtomicInteger; - -import org.junit.Test; - import rx.Observable; import rx.Observable.OnSubscribeFunc; import rx.Observer; import rx.Subscription; +import java.util.concurrent.atomic.AtomicInteger; + /** * Returns an Observable that skips the first num items emitted by the source * Observable. @@ -112,39 +107,4 @@ public void onNext(T args) { } } - - public static class UnitTest { - - @Test - public void testSkip1() { - Observable w = Observable.from("one", "two", "three"); - Observable skip = Observable.create(skip(w, 2)); - - @SuppressWarnings("unchecked") - Observer aObserver = mock(Observer.class); - skip.subscribe(aObserver); - verify(aObserver, never()).onNext("one"); - verify(aObserver, never()).onNext("two"); - verify(aObserver, times(1)).onNext("three"); - verify(aObserver, never()).onError(any(Throwable.class)); - verify(aObserver, times(1)).onCompleted(); - } - - @Test - public void testSkip2() { - Observable w = Observable.from("one", "two", "three"); - Observable skip = Observable.create(skip(w, 1)); - - @SuppressWarnings("unchecked") - Observer aObserver = mock(Observer.class); - skip.subscribe(aObserver); - verify(aObserver, never()).onNext("one"); - verify(aObserver, times(1)).onNext("two"); - verify(aObserver, times(1)).onNext("three"); - verify(aObserver, never()).onError(any(Throwable.class)); - verify(aObserver, times(1)).onCompleted(); - } - - } - } diff --git a/rxjava-core/src/main/java/rx/operators/OperationSkipLast.java b/rxjava-core/src/main/java/rx/operators/OperationSkipLast.java index 10da0c06b4..9bd8253392 100644 --- a/rxjava-core/src/main/java/rx/operators/OperationSkipLast.java +++ b/rxjava-core/src/main/java/rx/operators/OperationSkipLast.java @@ -15,25 +15,15 @@ */ package rx.operators; -import static org.mockito.Matchers.any; -import static org.mockito.Mockito.inOrder; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.never; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; - -import java.util.Deque; -import java.util.LinkedList; -import java.util.concurrent.locks.ReentrantLock; - -import org.junit.Test; -import org.mockito.InOrder; - import rx.Observable; import rx.Observable.OnSubscribeFunc; import rx.Observer; import rx.Subscription; +import java.util.Deque; +import java.util.LinkedList; +import java.util.concurrent.locks.ReentrantLock; + /** * Bypasses a specified number of elements at the end of an observable sequence. */ @@ -133,92 +123,4 @@ public void onNext(T value) { })); } } - - public static class UnitTest { - - @Test - public void testSkipLastEmpty() { - Observable w = Observable.empty(); - Observable observable = Observable.create(skipLast(w, 2)); - - @SuppressWarnings("unchecked") - Observer aObserver = mock(Observer.class); - observable.subscribe(aObserver); - verify(aObserver, never()).onNext(any(String.class)); - verify(aObserver, never()).onError(any(Throwable.class)); - verify(aObserver, times(1)).onCompleted(); - } - - @Test - public void testSkipLast1() { - Observable w = Observable.from("one", "two", "three"); - Observable observable = Observable.create(skipLast(w, 2)); - - @SuppressWarnings("unchecked") - Observer aObserver = mock(Observer.class); - InOrder inOrder = inOrder(aObserver); - observable.subscribe(aObserver); - inOrder.verify(aObserver, never()).onNext("two"); - inOrder.verify(aObserver, never()).onNext("three"); - verify(aObserver, times(1)).onNext("one"); - verify(aObserver, never()).onError(any(Throwable.class)); - verify(aObserver, times(1)).onCompleted(); - } - - @Test - public void testSkipLast2() { - Observable w = Observable.from("one", "two"); - Observable observable = Observable.create(skipLast(w, 2)); - - @SuppressWarnings("unchecked") - Observer aObserver = mock(Observer.class); - observable.subscribe(aObserver); - verify(aObserver, never()).onNext(any(String.class)); - verify(aObserver, never()).onError(any(Throwable.class)); - verify(aObserver, times(1)).onCompleted(); - } - - @Test - public void testSkipLastWithZeroCount() { - Observable w = Observable.from("one", "two"); - Observable observable = Observable.create(skipLast(w, 0)); - - @SuppressWarnings("unchecked") - Observer aObserver = mock(Observer.class); - observable.subscribe(aObserver); - verify(aObserver, times(1)).onNext("one"); - verify(aObserver, times(1)).onNext("two"); - verify(aObserver, never()).onError(any(Throwable.class)); - verify(aObserver, times(1)).onCompleted(); - } - - @Test - public void testSkipLastWithNull() { - Observable w = Observable.from("one", null, "two"); - Observable observable = Observable.create(skipLast(w, 1)); - - @SuppressWarnings("unchecked") - Observer aObserver = mock(Observer.class); - observable.subscribe(aObserver); - verify(aObserver, times(1)).onNext("one"); - verify(aObserver, times(1)).onNext(null); - verify(aObserver, never()).onNext("two"); - verify(aObserver, never()).onError(any(Throwable.class)); - verify(aObserver, times(1)).onCompleted(); - } - - @Test - public void testSkipLastWithNegativeCount() { - Observable w = Observable.from("one"); - Observable observable = Observable.create(skipLast(w, -1)); - - @SuppressWarnings("unchecked") - Observer aObserver = mock(Observer.class); - observable.subscribe(aObserver); - verify(aObserver, never()).onNext(any(String.class)); - verify(aObserver, times(1)).onError( - any(IndexOutOfBoundsException.class)); - verify(aObserver, never()).onCompleted(); - } - } } diff --git a/rxjava-core/src/main/java/rx/operators/OperationSkipWhile.java b/rxjava-core/src/main/java/rx/operators/OperationSkipWhile.java index 8277f80fc2..bf1528d8a2 100644 --- a/rxjava-core/src/main/java/rx/operators/OperationSkipWhile.java +++ b/rxjava-core/src/main/java/rx/operators/OperationSkipWhile.java @@ -15,16 +15,6 @@ */ package rx.operators; -import static org.mockito.Matchers.*; -import static org.mockito.Mockito.*; -import static rx.Observable.create; - -import java.util.concurrent.atomic.AtomicBoolean; -import java.util.concurrent.atomic.AtomicInteger; - -import org.junit.Test; -import org.mockito.InOrder; - import rx.Observable; import rx.Observable.OnSubscribeFunc; import rx.Observer; @@ -32,6 +22,9 @@ import rx.util.functions.Func1; import rx.util.functions.Func2; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicInteger; + /** * Skips any emitted source items as long as the specified condition holds true. Emits all further source items * as soon as the condition becomes false. @@ -102,92 +95,4 @@ public void onNext(T next) { } } - - public static class UnitTest { - @SuppressWarnings("unchecked") - Observer w = mock(Observer.class); - - private static final Func1 LESS_THAN_FIVE = new Func1() { - @Override - public Boolean call(Integer v) { - if (v == 42) throw new RuntimeException("that's not the answer to everything!"); - return v < 5; - } - }; - - private static final Func2 INDEX_LESS_THAN_THREE = new Func2() { - @Override - public Boolean call(Integer value, Integer index) { - return index < 3; - } - }; - - @Test - public void testSkipWithIndex() { - Observable src = Observable.from(1, 2, 3, 4, 5); - create(skipWhileWithIndex(src, INDEX_LESS_THAN_THREE)).subscribe(w); - - InOrder inOrder = inOrder(w); - inOrder.verify(w, times(1)).onNext(4); - inOrder.verify(w, times(1)).onNext(5); - inOrder.verify(w, times(1)).onCompleted(); - inOrder.verify(w, never()).onError(any(Throwable.class)); - } - - @Test - public void testSkipEmpty() { - Observable src = Observable.empty(); - create(skipWhile(src, LESS_THAN_FIVE)).subscribe(w); - verify(w, never()).onNext(anyInt()); - verify(w, never()).onError(any(Throwable.class)); - verify(w, times(1)).onCompleted(); - } - - @Test - public void testSkipEverything() { - Observable src = Observable.from(1, 2, 3, 4, 3, 2, 1); - create(skipWhile(src, LESS_THAN_FIVE)).subscribe(w); - verify(w, never()).onNext(anyInt()); - verify(w, never()).onError(any(Throwable.class)); - verify(w, times(1)).onCompleted(); - } - - @Test - public void testSkipNothing() { - Observable src = Observable.from(5, 3, 1); - create(skipWhile(src, LESS_THAN_FIVE)).subscribe(w); - - InOrder inOrder = inOrder(w); - inOrder.verify(w, times(1)).onNext(5); - inOrder.verify(w, times(1)).onNext(3); - inOrder.verify(w, times(1)).onNext(1); - inOrder.verify(w, times(1)).onCompleted(); - inOrder.verify(w, never()).onError(any(Throwable.class)); - } - - @Test - public void testSkipSome() { - Observable src = Observable.from(1, 2, 3, 4, 5, 3, 1, 5); - create(skipWhile(src, LESS_THAN_FIVE)).subscribe(w); - - InOrder inOrder = inOrder(w); - inOrder.verify(w, times(1)).onNext(5); - inOrder.verify(w, times(1)).onNext(3); - inOrder.verify(w, times(1)).onNext(1); - inOrder.verify(w, times(1)).onNext(5); - inOrder.verify(w, times(1)).onCompleted(); - inOrder.verify(w, never()).onError(any(Throwable.class)); - } - - @Test - public void testSkipError() { - Observable src = Observable.from(1, 2, 42, 5, 3, 1); - create(skipWhile(src, LESS_THAN_FIVE)).subscribe(w); - - InOrder inOrder = inOrder(w); - inOrder.verify(w, never()).onNext(anyInt()); - inOrder.verify(w, never()).onCompleted(); - inOrder.verify(w, times(1)).onError(any(RuntimeException.class)); - } - } } diff --git a/rxjava-core/src/main/java/rx/operators/OperationSubscribeOn.java b/rxjava-core/src/main/java/rx/operators/OperationSubscribeOn.java index 6f75a32b57..f1cac4fe9d 100644 --- a/rxjava-core/src/main/java/rx/operators/OperationSubscribeOn.java +++ b/rxjava-core/src/main/java/rx/operators/OperationSubscribeOn.java @@ -15,17 +15,11 @@ */ package rx.operators; -import static org.mockito.Matchers.*; -import static org.mockito.Mockito.*; - -import org.junit.Test; - import rx.Observable; import rx.Observable.OnSubscribeFunc; import rx.Observer; import rx.Scheduler; import rx.Subscription; -import rx.concurrency.Schedulers; import rx.util.functions.Action0; import rx.util.functions.Func2; @@ -79,30 +73,4 @@ public void call() { }); } } - - public static class UnitTest { - - @Test - @SuppressWarnings("unchecked") - public void testSubscribeOn() { - Observable w = Observable.from(1, 2, 3); - - Scheduler scheduler = spy(OperatorTester.UnitTest.forwardingScheduler(Schedulers.immediate())); - - Observer observer = mock(Observer.class); - Subscription subscription = Observable.create(subscribeOn(w, scheduler)).subscribe(observer); - - verify(scheduler, times(1)).schedule(isNull(), any(Func2.class)); - subscription.unsubscribe(); - verify(scheduler, times(1)).schedule(any(Action0.class)); - verifyNoMoreInteractions(scheduler); - - verify(observer, times(1)).onNext(1); - verify(observer, times(1)).onNext(2); - verify(observer, times(1)).onNext(3); - verify(observer, times(1)).onCompleted(); - } - - } - } diff --git a/rxjava-core/src/main/java/rx/operators/OperationSum.java b/rxjava-core/src/main/java/rx/operators/OperationSum.java index 5892a00520..cc34f79520 100644 --- a/rxjava-core/src/main/java/rx/operators/OperationSum.java +++ b/rxjava-core/src/main/java/rx/operators/OperationSum.java @@ -15,12 +15,7 @@ */ package rx.operators; -import static org.mockito.Mockito.*; - -import org.junit.Test; - import rx.Observable; -import rx.Observer; import rx.util.functions.Func2; /** @@ -63,103 +58,4 @@ public Double call(Double accu, Double next) { } }); } - - public static class UnitTest { - @SuppressWarnings("unchecked") - Observer w = mock(Observer.class); - @SuppressWarnings("unchecked") - Observer wl = mock(Observer.class); - @SuppressWarnings("unchecked") - Observer wf = mock(Observer.class); - @SuppressWarnings("unchecked") - Observer wd = mock(Observer.class); - - @Test - public void testSumOfAFewInts() throws Throwable { - Observable src = Observable.from(1, 2, 3, 4, 5); - sum(src).subscribe(w); - - verify(w, times(1)).onNext(anyInt()); - verify(w).onNext(15); - verify(w, never()).onError(any(Throwable.class)); - verify(w, times(1)).onCompleted(); - } - - @Test - public void testEmptySum() throws Throwable { - Observable src = Observable.empty(); - sum(src).subscribe(w); - - verify(w, times(1)).onNext(anyInt()); - verify(w).onNext(0); - verify(w, never()).onError(any(Throwable.class)); - verify(w, times(1)).onCompleted(); - } - - @Test - public void testSumOfAFewLongs() throws Throwable { - Observable src = Observable.from(1L, 2L, 3L, 4L, 5L); - sumLongs(src).subscribe(wl); - - verify(wl, times(1)).onNext(anyLong()); - verify(wl).onNext(15L); - verify(wl, never()).onError(any(Throwable.class)); - verify(wl, times(1)).onCompleted(); - } - - @Test - public void testEmptySumLongs() throws Throwable { - Observable src = Observable.empty(); - sumLongs(src).subscribe(wl); - - verify(wl, times(1)).onNext(anyLong()); - verify(wl).onNext(0L); - verify(wl, never()).onError(any(Throwable.class)); - verify(wl, times(1)).onCompleted(); - } - - @Test - public void testSumOfAFewFloats() throws Throwable { - Observable src = Observable.from(1.0f); - sumFloats(src).subscribe(wf); - - verify(wf, times(1)).onNext(anyFloat()); - verify(wf).onNext(1.0f); - verify(wf, never()).onError(any(Throwable.class)); - verify(wf, times(1)).onCompleted(); - } - - @Test - public void testEmptySumFloats() throws Throwable { - Observable src = Observable.empty(); - sumFloats(src).subscribe(wf); - - verify(wf, times(1)).onNext(anyFloat()); - verify(wf).onNext(0.0f); - verify(wf, never()).onError(any(Throwable.class)); - verify(wf, times(1)).onCompleted(); - } - - @Test - public void testSumOfAFewDoubles() throws Throwable { - Observable src = Observable.from(0.0d, 1.0d, 0.5d); - sumDoubles(src).subscribe(wd); - - verify(wd, times(1)).onNext(anyDouble()); - verify(wd).onNext(1.5d); - verify(wd, never()).onError(any(Throwable.class)); - verify(wd, times(1)).onCompleted(); - } - - @Test - public void testEmptySumDoubles() throws Throwable { - Observable src = Observable.empty(); - sumDoubles(src).subscribe(wd); - - verify(wd, times(1)).onNext(anyDouble()); - verify(wd).onNext(0.0d); - verify(wd, never()).onError(any(Throwable.class)); - verify(wd, times(1)).onCompleted(); - } - } } diff --git a/rxjava-core/src/main/java/rx/operators/OperationSwitch.java b/rxjava-core/src/main/java/rx/operators/OperationSwitch.java index c40864de84..25d94a714a 100644 --- a/rxjava-core/src/main/java/rx/operators/OperationSwitch.java +++ b/rxjava-core/src/main/java/rx/operators/OperationSwitch.java @@ -15,29 +15,12 @@ */ package rx.operators; -import static org.mockito.Matchers.any; -import static org.mockito.Matchers.anyString; -import static org.mockito.Mockito.inOrder; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.never; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; - -import java.util.concurrent.TimeUnit; - -import org.junit.Before; -import org.junit.Test; -import org.mockito.InOrder; - import rx.Observable; import rx.Observable.OnSubscribeFunc; import rx.Observer; import rx.Subscription; -import rx.concurrency.TestScheduler; import rx.subscriptions.CompositeSubscription; import rx.subscriptions.MultipleAssignmentSubscription; -import rx.subscriptions.Subscriptions; -import rx.util.functions.Action0; import rx.util.functions.Func1; /** @@ -182,355 +165,4 @@ public void onCompleted() { } } - - public static class UnitTest { - - private TestScheduler scheduler; - private Observer observer; - - @Before - @SuppressWarnings("unchecked") - public void before() { - scheduler = new TestScheduler(); - observer = mock(Observer.class); - } - - @Test - public void testSwitchWhenOuterCompleteBeforeInner() { - Observable> source = Observable.create(new OnSubscribeFunc>() { - @Override - public Subscription onSubscribe(Observer> observer) { - publishNext(observer, 50, Observable.create(new OnSubscribeFunc() { - @Override - public Subscription onSubscribe(Observer observer) { - publishNext(observer, 70, "one"); - publishNext(observer, 100, "two"); - publishCompleted(observer, 200); - return Subscriptions.empty(); - } - })); - publishCompleted(observer, 60); - - return Subscriptions.empty(); - } - }); - - Observable sampled = Observable.create(OperationSwitch.switchDo(source)); - sampled.subscribe(observer); - - InOrder inOrder = inOrder(observer); - - scheduler.advanceTimeTo(350, TimeUnit.MILLISECONDS); - inOrder.verify(observer, times(2)).onNext(anyString()); - inOrder.verify(observer, times(1)).onCompleted(); - } - - @Test - public void testSwitchWhenInnerCompleteBeforeOuter() { - Observable> source = Observable.create(new OnSubscribeFunc>() { - @Override - public Subscription onSubscribe(Observer> observer) { - publishNext(observer, 10, Observable.create(new OnSubscribeFunc() { - @Override - public Subscription onSubscribe(Observer observer) { - publishNext(observer, 0, "one"); - publishNext(observer, 10, "two"); - publishCompleted(observer, 20); - return Subscriptions.empty(); - } - })); - - publishNext(observer, 100, Observable.create(new OnSubscribeFunc() { - @Override - public Subscription onSubscribe(Observer observer) { - publishNext(observer, 0, "three"); - publishNext(observer, 10, "four"); - publishCompleted(observer, 20); - return Subscriptions.empty(); - } - })); - publishCompleted(observer, 200); - - return Subscriptions.empty(); - } - }); - - Observable sampled = Observable.create(OperationSwitch.switchDo(source)); - sampled.subscribe(observer); - - InOrder inOrder = inOrder(observer); - - scheduler.advanceTimeTo(150, TimeUnit.MILLISECONDS); - inOrder.verify(observer, never()).onCompleted(); - inOrder.verify(observer, times(1)).onNext("one"); - inOrder.verify(observer, times(1)).onNext("two"); - inOrder.verify(observer, times(1)).onNext("three"); - inOrder.verify(observer, times(1)).onNext("four"); - - scheduler.advanceTimeTo(250, TimeUnit.MILLISECONDS); - inOrder.verify(observer, never()).onNext(anyString()); - inOrder.verify(observer, times(1)).onCompleted(); - } - - @Test - public void testSwitchWithComplete() { - Observable> source = Observable.create(new OnSubscribeFunc>() { - @Override - public Subscription onSubscribe(Observer> observer) { - publishNext(observer, 50, Observable.create(new OnSubscribeFunc() { - @Override - public Subscription onSubscribe(Observer observer) { - publishNext(observer, 60, "one"); - publishNext(observer, 100, "two"); - return Subscriptions.empty(); - } - })); - - publishNext(observer, 200, Observable.create(new OnSubscribeFunc() { - @Override - public Subscription onSubscribe(Observer observer) { - publishNext(observer, 0, "three"); - publishNext(observer, 100, "four"); - return Subscriptions.empty(); - } - })); - - publishCompleted(observer, 250); - - return Subscriptions.empty(); - } - }); - - Observable sampled = Observable.create(OperationSwitch.switchDo(source)); - sampled.subscribe(observer); - - InOrder inOrder = inOrder(observer); - - scheduler.advanceTimeTo(90, TimeUnit.MILLISECONDS); - inOrder.verify(observer, never()).onNext(anyString()); - verify(observer, never()).onCompleted(); - verify(observer, never()).onError(any(Throwable.class)); - - scheduler.advanceTimeTo(125, TimeUnit.MILLISECONDS); - inOrder.verify(observer, times(1)).onNext("one"); - verify(observer, never()).onCompleted(); - verify(observer, never()).onError(any(Throwable.class)); - - scheduler.advanceTimeTo(175, TimeUnit.MILLISECONDS); - inOrder.verify(observer, times(1)).onNext("two"); - verify(observer, never()).onCompleted(); - verify(observer, never()).onError(any(Throwable.class)); - - scheduler.advanceTimeTo(225, TimeUnit.MILLISECONDS); - inOrder.verify(observer, times(1)).onNext("three"); - verify(observer, never()).onCompleted(); - verify(observer, never()).onError(any(Throwable.class)); - - scheduler.advanceTimeTo(350, TimeUnit.MILLISECONDS); - inOrder.verify(observer, times(1)).onNext("four"); - verify(observer, never()).onCompleted(); - verify(observer, never()).onError(any(Throwable.class)); - } - - @Test - public void testSwitchWithError() { - Observable> source = Observable.create(new OnSubscribeFunc>() { - @Override - public Subscription onSubscribe(Observer> observer) { - publishNext(observer, 50, Observable.create(new OnSubscribeFunc() { - @Override - public Subscription onSubscribe(Observer observer) { - publishNext(observer, 50, "one"); - publishNext(observer, 100, "two"); - return Subscriptions.empty(); - } - })); - - publishNext(observer, 200, Observable.create(new OnSubscribeFunc() { - @Override - public Subscription onSubscribe(Observer observer) { - publishNext(observer, 0, "three"); - publishNext(observer, 100, "four"); - return Subscriptions.empty(); - } - })); - - publishError(observer, 250, new TestException()); - - return Subscriptions.empty(); - } - }); - - Observable sampled = Observable.create(OperationSwitch.switchDo(source)); - sampled.subscribe(observer); - - InOrder inOrder = inOrder(observer); - - scheduler.advanceTimeTo(90, TimeUnit.MILLISECONDS); - inOrder.verify(observer, never()).onNext(anyString()); - verify(observer, never()).onCompleted(); - verify(observer, never()).onError(any(Throwable.class)); - - scheduler.advanceTimeTo(125, TimeUnit.MILLISECONDS); - inOrder.verify(observer, times(1)).onNext("one"); - verify(observer, never()).onCompleted(); - verify(observer, never()).onError(any(Throwable.class)); - - scheduler.advanceTimeTo(175, TimeUnit.MILLISECONDS); - inOrder.verify(observer, times(1)).onNext("two"); - verify(observer, never()).onCompleted(); - verify(observer, never()).onError(any(Throwable.class)); - - scheduler.advanceTimeTo(225, TimeUnit.MILLISECONDS); - inOrder.verify(observer, times(1)).onNext("three"); - verify(observer, never()).onCompleted(); - verify(observer, never()).onError(any(Throwable.class)); - - scheduler.advanceTimeTo(350, TimeUnit.MILLISECONDS); - inOrder.verify(observer, never()).onNext(anyString()); - verify(observer, never()).onCompleted(); - verify(observer, times(1)).onError(any(TestException.class)); - } - - @Test - public void testSwitchWithSubsequenceComplete() { - Observable> source = Observable.create(new OnSubscribeFunc>() { - @Override - public Subscription onSubscribe(Observer> observer) { - publishNext(observer, 50, Observable.create(new OnSubscribeFunc() { - @Override - public Subscription onSubscribe(Observer observer) { - publishNext(observer, 50, "one"); - publishNext(observer, 100, "two"); - return Subscriptions.empty(); - } - })); - - publishNext(observer, 130, Observable.create(new OnSubscribeFunc() { - @Override - public Subscription onSubscribe(Observer observer) { - publishCompleted(observer, 0); - return Subscriptions.empty(); - } - })); - - publishNext(observer, 150, Observable.create(new OnSubscribeFunc() { - @Override - public Subscription onSubscribe(Observer observer) { - publishNext(observer, 50, "three"); - return Subscriptions.empty(); - } - })); - - return Subscriptions.empty(); - } - }); - - Observable sampled = Observable.create(OperationSwitch.switchDo(source)); - sampled.subscribe(observer); - - InOrder inOrder = inOrder(observer); - - scheduler.advanceTimeTo(90, TimeUnit.MILLISECONDS); - inOrder.verify(observer, never()).onNext(anyString()); - verify(observer, never()).onCompleted(); - verify(observer, never()).onError(any(Throwable.class)); - - scheduler.advanceTimeTo(125, TimeUnit.MILLISECONDS); - inOrder.verify(observer, times(1)).onNext("one"); - verify(observer, never()).onCompleted(); - verify(observer, never()).onError(any(Throwable.class)); - - scheduler.advanceTimeTo(250, TimeUnit.MILLISECONDS); - inOrder.verify(observer, times(1)).onNext("three"); - verify(observer, never()).onCompleted(); - verify(observer, never()).onError(any(Throwable.class)); - } - - @Test - public void testSwitchWithSubsequenceError() { - Observable> source = Observable.create(new OnSubscribeFunc>() { - @Override - public Subscription onSubscribe(Observer> observer) { - publishNext(observer, 50, Observable.create(new OnSubscribeFunc() { - @Override - public Subscription onSubscribe(Observer observer) { - publishNext(observer, 50, "one"); - publishNext(observer, 100, "two"); - return Subscriptions.empty(); - } - })); - - publishNext(observer, 130, Observable.create(new OnSubscribeFunc() { - @Override - public Subscription onSubscribe(Observer observer) { - publishError(observer, 0, new TestException()); - return Subscriptions.empty(); - } - })); - - publishNext(observer, 150, Observable.create(new OnSubscribeFunc() { - @Override - public Subscription onSubscribe(Observer observer) { - publishNext(observer, 50, "three"); - return Subscriptions.empty(); - } - })); - - return Subscriptions.empty(); - } - }); - - Observable sampled = Observable.create(OperationSwitch.switchDo(source)); - sampled.subscribe(observer); - - InOrder inOrder = inOrder(observer); - - scheduler.advanceTimeTo(90, TimeUnit.MILLISECONDS); - inOrder.verify(observer, never()).onNext(anyString()); - verify(observer, never()).onCompleted(); - verify(observer, never()).onError(any(Throwable.class)); - - scheduler.advanceTimeTo(125, TimeUnit.MILLISECONDS); - inOrder.verify(observer, times(1)).onNext("one"); - verify(observer, never()).onCompleted(); - verify(observer, never()).onError(any(Throwable.class)); - - scheduler.advanceTimeTo(250, TimeUnit.MILLISECONDS); - inOrder.verify(observer, never()).onNext("three"); - verify(observer, never()).onCompleted(); - verify(observer, times(1)).onError(any(TestException.class)); - } - - private void publishCompleted(final Observer observer, long delay) { - scheduler.schedule(new Action0() { - @Override - public void call() { - observer.onCompleted(); - } - }, delay, TimeUnit.MILLISECONDS); - } - - private void publishError(final Observer observer, long delay, final Throwable error) { - scheduler.schedule(new Action0() { - @Override - public void call() { - observer.onError(error); - } - }, delay, TimeUnit.MILLISECONDS); - } - - private void publishNext(final Observer observer, long delay, final T value) { - scheduler.schedule(new Action0() { - @Override - public void call() { - observer.onNext(value); - } - }, delay, TimeUnit.MILLISECONDS); - } - - @SuppressWarnings("serial") - private class TestException extends Throwable { - } - } } diff --git a/rxjava-core/src/main/java/rx/operators/OperationSynchronize.java b/rxjava-core/src/main/java/rx/operators/OperationSynchronize.java index b7cd689102..4ec205f156 100644 --- a/rxjava-core/src/main/java/rx/operators/OperationSynchronize.java +++ b/rxjava-core/src/main/java/rx/operators/OperationSynchronize.java @@ -15,12 +15,6 @@ */ package rx.operators; -import static org.mockito.Matchers.*; -import static org.mockito.Mockito.*; - -import org.junit.Test; -import org.mockito.Mockito; - import rx.Observable; import rx.Observable.OnSubscribeFunc; import rx.Observer; @@ -102,197 +96,4 @@ public Subscription onSubscribe(Observer observer) { } } - - public static class UnitTest { - - /** - * Ensure onCompleted can not be called after an Unsubscribe - */ - @Test - public void testOnCompletedAfterUnSubscribe() { - TestObservable t = new TestObservable(null); - Observable st = Observable.create(synchronize(Observable.create(t))); - - @SuppressWarnings("unchecked") - Observer w = mock(Observer.class); - Subscription ws = st.subscribe(w); - - t.sendOnNext("one"); - ws.unsubscribe(); - t.sendOnCompleted(); - - verify(w, times(1)).onNext("one"); - verify(w, Mockito.never()).onCompleted(); - } - - /** - * Ensure onNext can not be called after an Unsubscribe - */ - @Test - public void testOnNextAfterUnSubscribe() { - TestObservable t = new TestObservable(null); - Observable st = Observable.create(synchronize(Observable.create(t))); - - @SuppressWarnings("unchecked") - Observer w = mock(Observer.class); - Subscription ws = st.subscribe(w); - - t.sendOnNext("one"); - ws.unsubscribe(); - t.sendOnNext("two"); - - verify(w, times(1)).onNext("one"); - verify(w, Mockito.never()).onNext("two"); - } - - /** - * Ensure onError can not be called after an Unsubscribe - */ - @Test - public void testOnErrorAfterUnSubscribe() { - TestObservable t = new TestObservable(null); - Observable st = Observable.create(synchronize(Observable.create(t))); - - @SuppressWarnings("unchecked") - Observer w = mock(Observer.class); - Subscription ws = st.subscribe(w); - - t.sendOnNext("one"); - ws.unsubscribe(); - t.sendOnError(new RuntimeException("bad")); - - verify(w, times(1)).onNext("one"); - verify(w, Mockito.never()).onError(any(Throwable.class)); - } - - /** - * Ensure onNext can not be called after onError - */ - @Test - public void testOnNextAfterOnError() { - TestObservable t = new TestObservable(null); - Observable st = Observable.create(synchronize(Observable.create(t))); - - @SuppressWarnings("unchecked") - Observer w = mock(Observer.class); - @SuppressWarnings("unused") - Subscription ws = st.subscribe(w); - - t.sendOnNext("one"); - t.sendOnError(new RuntimeException("bad")); - t.sendOnNext("two"); - - verify(w, times(1)).onNext("one"); - verify(w, times(1)).onError(any(Throwable.class)); - verify(w, Mockito.never()).onNext("two"); - } - - /** - * Ensure onCompleted can not be called after onError - */ - @Test - public void testOnCompletedAfterOnError() { - TestObservable t = new TestObservable(null); - Observable st = Observable.create(synchronize(Observable.create(t))); - - @SuppressWarnings("unchecked") - Observer w = mock(Observer.class); - @SuppressWarnings("unused") - Subscription ws = st.subscribe(w); - - t.sendOnNext("one"); - t.sendOnError(new RuntimeException("bad")); - t.sendOnCompleted(); - - verify(w, times(1)).onNext("one"); - verify(w, times(1)).onError(any(Throwable.class)); - verify(w, Mockito.never()).onCompleted(); - } - - /** - * Ensure onNext can not be called after onCompleted - */ - @Test - public void testOnNextAfterOnCompleted() { - TestObservable t = new TestObservable(null); - Observable st = Observable.create(synchronize(Observable.create(t))); - - @SuppressWarnings("unchecked") - Observer w = mock(Observer.class); - @SuppressWarnings("unused") - Subscription ws = st.subscribe(w); - - t.sendOnNext("one"); - t.sendOnCompleted(); - t.sendOnNext("two"); - - verify(w, times(1)).onNext("one"); - verify(w, Mockito.never()).onNext("two"); - verify(w, times(1)).onCompleted(); - verify(w, Mockito.never()).onError(any(Throwable.class)); - } - - /** - * Ensure onError can not be called after onCompleted - */ - @Test - public void testOnErrorAfterOnCompleted() { - TestObservable t = new TestObservable(null); - Observable st = Observable.create(synchronize(Observable.create(t))); - - @SuppressWarnings("unchecked") - Observer w = mock(Observer.class); - @SuppressWarnings("unused") - Subscription ws = st.subscribe(w); - - t.sendOnNext("one"); - t.sendOnCompleted(); - t.sendOnError(new RuntimeException("bad")); - - verify(w, times(1)).onNext("one"); - verify(w, times(1)).onCompleted(); - verify(w, Mockito.never()).onError(any(Throwable.class)); - } - - /** - * A Observable that doesn't do the right thing on UnSubscribe/Error/etc in that it will keep sending events down the pipe regardless of what happens. - */ - private static class TestObservable implements OnSubscribeFunc { - - Observer observer = null; - - public TestObservable(Subscription s) { - } - - /* used to simulate subscription */ - public void sendOnCompleted() { - observer.onCompleted(); - } - - /* used to simulate subscription */ - public void sendOnNext(String value) { - observer.onNext(value); - } - - /* used to simulate subscription */ - public void sendOnError(Throwable e) { - observer.onError(e); - } - - @Override - public Subscription onSubscribe(final Observer observer) { - this.observer = observer; - return new Subscription() { - - @Override - public void unsubscribe() { - // going to do nothing to pretend I'm a bad Observable that keeps allowing events to be sent - } - - }; - } - - } - } - } diff --git a/rxjava-core/src/main/java/rx/operators/OperationTake.java b/rxjava-core/src/main/java/rx/operators/OperationTake.java index 061e930ff0..6448a628db 100644 --- a/rxjava-core/src/main/java/rx/operators/OperationTake.java +++ b/rxjava-core/src/main/java/rx/operators/OperationTake.java @@ -15,30 +15,13 @@ */ package rx.operators; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; -import static org.mockito.Matchers.any; -import static org.mockito.Matchers.anyInt; -import static org.mockito.Matchers.anyString; -import static org.mockito.Mockito.inOrder; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.never; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.verifyNoMoreInteractions; - -import java.util.concurrent.atomic.AtomicBoolean; -import java.util.concurrent.atomic.AtomicInteger; - -import org.junit.Test; -import org.mockito.InOrder; - import rx.Observable; import rx.Observable.OnSubscribeFunc; import rx.Observer; import rx.Subscription; import rx.subscriptions.Subscriptions; -import rx.util.functions.Func1; + +import java.util.concurrent.atomic.AtomicInteger; /** * Returns an Observable that emits the first num items emitted by the source @@ -178,208 +161,4 @@ public void onNext(T args) { } } - - public static class UnitTest { - - @Test - public void testTake1() { - Observable w = Observable.from("one", "two", "three"); - Observable take = Observable.create(take(w, 2)); - - @SuppressWarnings("unchecked") - Observer aObserver = mock(Observer.class); - take.subscribe(aObserver); - verify(aObserver, times(1)).onNext("one"); - verify(aObserver, times(1)).onNext("two"); - verify(aObserver, never()).onNext("three"); - verify(aObserver, never()).onError(any(Throwable.class)); - verify(aObserver, times(1)).onCompleted(); - } - - @Test - public void testTake2() { - Observable w = Observable.from("one", "two", "three"); - Observable take = Observable.create(take(w, 1)); - - @SuppressWarnings("unchecked") - Observer aObserver = mock(Observer.class); - take.subscribe(aObserver); - verify(aObserver, times(1)).onNext("one"); - verify(aObserver, never()).onNext("two"); - verify(aObserver, never()).onNext("three"); - verify(aObserver, never()).onError(any(Throwable.class)); - verify(aObserver, times(1)).onCompleted(); - } - - @Test(expected = IllegalArgumentException.class) - public void testTakeWithError() { - Observable.from(1, 2, 3).take(1).map(new Func1() { - public Integer call(Integer t1) { - throw new IllegalArgumentException("some error"); - } - }).toBlockingObservable().single(); - } - - @Test - public void testTakeWithErrorHappeningInOnNext() { - Observable w = Observable.from(1, 2, 3).take(2).map(new Func1() { - public Integer call(Integer t1) { - throw new IllegalArgumentException("some error"); - } - }); - - @SuppressWarnings("unchecked") - Observer observer = mock(Observer.class); - w.subscribe(observer); - InOrder inOrder = inOrder(observer); - inOrder.verify(observer, times(1)).onError(any(IllegalArgumentException.class)); - inOrder.verifyNoMoreInteractions(); - } - - @Test - public void testTakeWithErrorHappeningInTheLastOnNext() { - Observable w = Observable.from(1, 2, 3).take(1).map(new Func1() { - public Integer call(Integer t1) { - throw new IllegalArgumentException("some error"); - } - }); - - @SuppressWarnings("unchecked") - Observer observer = mock(Observer.class); - w.subscribe(observer); - InOrder inOrder = inOrder(observer); - inOrder.verify(observer, times(1)).onError(any(IllegalArgumentException.class)); - inOrder.verifyNoMoreInteractions(); - } - - @Test - public void testTakeDoesntLeakErrors() { - Observable source = Observable.create(new OnSubscribeFunc() - { - @Override - public Subscription onSubscribe(Observer observer) - { - observer.onNext("one"); - observer.onError(new Throwable("test failed")); - return Subscriptions.empty(); - } - }); - - @SuppressWarnings("unchecked") - Observer aObserver = mock(Observer.class); - - Observable.create(take(source, 1)).subscribe(aObserver); - - verify(aObserver, times(1)).onNext("one"); - // even though onError is called we take(1) so shouldn't see it - verify(aObserver, never()).onError(any(Throwable.class)); - verify(aObserver, times(1)).onCompleted(); - verifyNoMoreInteractions(aObserver); - } - - @Test - public void testTakeZeroDoesntLeakError() { - final AtomicBoolean subscribed = new AtomicBoolean(false); - final AtomicBoolean unSubscribed = new AtomicBoolean(false); - Observable source = Observable.create(new OnSubscribeFunc() - { - @Override - public Subscription onSubscribe(Observer observer) - { - subscribed.set(true); - observer.onError(new Throwable("test failed")); - return new Subscription() - { - @Override - public void unsubscribe() - { - unSubscribed.set(true); - } - }; - } - }); - - @SuppressWarnings("unchecked") - Observer aObserver = mock(Observer.class); - - Observable.create(take(source, 0)).subscribe(aObserver); - assertTrue("source subscribed", subscribed.get()); - assertTrue("source unsubscribed", unSubscribed.get()); - - verify(aObserver, never()).onNext(anyString()); - // even though onError is called we take(0) so shouldn't see it - verify(aObserver, never()).onError(any(Throwable.class)); - verify(aObserver, times(1)).onCompleted(); - verifyNoMoreInteractions(aObserver); - } - - @Test - public void testUnsubscribeAfterTake() { - final Subscription s = mock(Subscription.class); - TestObservableFunc f = new TestObservableFunc(s, "one", "two", "three"); - Observable w = Observable.create(f); - - @SuppressWarnings("unchecked") - Observer aObserver = mock(Observer.class); - Observable take = Observable.create(take(w, 1)); - take.subscribe(aObserver); - - // wait for the Observable to complete - try { - f.t.join(); - } catch (Throwable e) { - e.printStackTrace(); - fail(e.getMessage()); - } - - System.out.println("TestObservable thread finished"); - verify(aObserver, times(1)).onNext("one"); - verify(aObserver, never()).onNext("two"); - verify(aObserver, never()).onNext("three"); - verify(aObserver, times(1)).onCompleted(); - verify(s, times(1)).unsubscribe(); - verifyNoMoreInteractions(aObserver); - } - - private static class TestObservableFunc implements OnSubscribeFunc { - - final Subscription s; - final String[] values; - Thread t = null; - - public TestObservableFunc(Subscription s, String... values) { - this.s = s; - this.values = values; - } - - @Override - public Subscription onSubscribe(final Observer observer) { - System.out.println("TestObservable subscribed to ..."); - t = new Thread(new Runnable() { - - @Override - public void run() { - try { - System.out.println("running TestObservable thread"); - for (String s : values) { - System.out.println("TestObservable onNext: " + s); - observer.onNext(s); - } - observer.onCompleted(); - } catch (Throwable e) { - throw new RuntimeException(e); - } - } - - }); - System.out.println("starting TestObservable thread"); - t.start(); - System.out.println("done starting TestObservable thread"); - return s; - } - - } - - } - } diff --git a/rxjava-core/src/main/java/rx/operators/OperationTakeLast.java b/rxjava-core/src/main/java/rx/operators/OperationTakeLast.java index e83f5dc432..d608552315 100644 --- a/rxjava-core/src/main/java/rx/operators/OperationTakeLast.java +++ b/rxjava-core/src/main/java/rx/operators/OperationTakeLast.java @@ -15,25 +15,15 @@ */ package rx.operators; -import static org.mockito.Matchers.any; -import static org.mockito.Mockito.inOrder; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.never; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; - -import java.util.Deque; -import java.util.LinkedList; -import java.util.concurrent.locks.ReentrantLock; - -import org.junit.Test; -import org.mockito.InOrder; - import rx.Observable; import rx.Observable.OnSubscribeFunc; import rx.Observer; import rx.Subscription; +import java.util.Deque; +import java.util.LinkedList; +import java.util.concurrent.locks.ReentrantLock; + /** * Returns an Observable that emits the last count items emitted by the source * Observable. @@ -129,93 +119,4 @@ public void onNext(T value) { } } - - public static class UnitTest { - - @Test - public void testTakeLastEmpty() { - Observable w = Observable.empty(); - Observable take = Observable.create(takeLast(w, 2)); - - @SuppressWarnings("unchecked") - Observer aObserver = mock(Observer.class); - take.subscribe(aObserver); - verify(aObserver, never()).onNext(any(String.class)); - verify(aObserver, never()).onError(any(Throwable.class)); - verify(aObserver, times(1)).onCompleted(); - } - - @Test - public void testTakeLast1() { - Observable w = Observable.from("one", "two", "three"); - Observable take = Observable.create(takeLast(w, 2)); - - @SuppressWarnings("unchecked") - Observer aObserver = mock(Observer.class); - InOrder inOrder = inOrder(aObserver); - take.subscribe(aObserver); - inOrder.verify(aObserver, times(1)).onNext("two"); - inOrder.verify(aObserver, times(1)).onNext("three"); - verify(aObserver, never()).onNext("one"); - verify(aObserver, never()).onError(any(Throwable.class)); - verify(aObserver, times(1)).onCompleted(); - } - - @Test - public void testTakeLast2() { - Observable w = Observable.from("one"); - Observable take = Observable.create(takeLast(w, 10)); - - @SuppressWarnings("unchecked") - Observer aObserver = mock(Observer.class); - take.subscribe(aObserver); - verify(aObserver, times(1)).onNext("one"); - verify(aObserver, never()).onError(any(Throwable.class)); - verify(aObserver, times(1)).onCompleted(); - } - - @Test - public void testTakeLastWithZeroCount() { - Observable w = Observable.from("one"); - Observable take = Observable.create(takeLast(w, 0)); - - @SuppressWarnings("unchecked") - Observer aObserver = mock(Observer.class); - take.subscribe(aObserver); - verify(aObserver, never()).onNext("one"); - verify(aObserver, never()).onError(any(Throwable.class)); - verify(aObserver, times(1)).onCompleted(); - } - - @Test - public void testTakeLastWithNull() { - Observable w = Observable.from("one", null, "three"); - Observable take = Observable.create(takeLast(w, 2)); - - @SuppressWarnings("unchecked") - Observer aObserver = mock(Observer.class); - take.subscribe(aObserver); - verify(aObserver, never()).onNext("one"); - verify(aObserver, times(1)).onNext(null); - verify(aObserver, times(1)).onNext("three"); - verify(aObserver, never()).onError(any(Throwable.class)); - verify(aObserver, times(1)).onCompleted(); - } - - @Test - public void testTakeLastWithNegativeCount() { - Observable w = Observable.from("one"); - Observable take = Observable.create(takeLast(w, -1)); - - @SuppressWarnings("unchecked") - Observer aObserver = mock(Observer.class); - take.subscribe(aObserver); - verify(aObserver, never()).onNext("one"); - verify(aObserver, times(1)).onError( - any(IndexOutOfBoundsException.class)); - verify(aObserver, never()).onCompleted(); - } - - } - } diff --git a/rxjava-core/src/main/java/rx/operators/OperationTakeUntil.java b/rxjava-core/src/main/java/rx/operators/OperationTakeUntil.java index 841190f023..4f344d72a1 100644 --- a/rxjava-core/src/main/java/rx/operators/OperationTakeUntil.java +++ b/rxjava-core/src/main/java/rx/operators/OperationTakeUntil.java @@ -15,10 +15,6 @@ */ package rx.operators; -import static org.mockito.Mockito.*; - -import org.junit.Test; - import rx.Observable; import rx.Observable.OnSubscribeFunc; import rx.Observer; @@ -139,160 +135,4 @@ public void onNext(E args) { }); } } - - public static class UnitTest { - - @Test - @SuppressWarnings("unchecked") - public void testTakeUntil() { - Subscription sSource = mock(Subscription.class); - Subscription sOther = mock(Subscription.class); - TestObservable source = new TestObservable(sSource); - TestObservable other = new TestObservable(sOther); - - Observer result = mock(Observer.class); - Observable stringObservable = takeUntil(Observable.create(source), Observable.create(other)); - stringObservable.subscribe(result); - source.sendOnNext("one"); - source.sendOnNext("two"); - other.sendOnNext("three"); - source.sendOnNext("four"); - source.sendOnCompleted(); - other.sendOnCompleted(); - - verify(result, times(1)).onNext("one"); - verify(result, times(1)).onNext("two"); - verify(result, times(0)).onNext("three"); - verify(result, times(0)).onNext("four"); - verify(sSource, times(1)).unsubscribe(); - verify(sOther, times(1)).unsubscribe(); - - } - - @Test - @SuppressWarnings("unchecked") - public void testTakeUntilSourceCompleted() { - Subscription sSource = mock(Subscription.class); - Subscription sOther = mock(Subscription.class); - TestObservable source = new TestObservable(sSource); - TestObservable other = new TestObservable(sOther); - - Observer result = mock(Observer.class); - Observable stringObservable = takeUntil(Observable.create(source), Observable.create(other)); - stringObservable.subscribe(result); - source.sendOnNext("one"); - source.sendOnNext("two"); - source.sendOnCompleted(); - - verify(result, times(1)).onNext("one"); - verify(result, times(1)).onNext("two"); - verify(sSource, times(1)).unsubscribe(); - verify(sOther, times(1)).unsubscribe(); - - } - - @Test - @SuppressWarnings("unchecked") - public void testTakeUntilSourceError() { - Subscription sSource = mock(Subscription.class); - Subscription sOther = mock(Subscription.class); - TestObservable source = new TestObservable(sSource); - TestObservable other = new TestObservable(sOther); - Throwable error = new Throwable(); - - Observer result = mock(Observer.class); - Observable stringObservable = takeUntil(Observable.create(source), Observable.create(other)); - stringObservable.subscribe(result); - source.sendOnNext("one"); - source.sendOnNext("two"); - source.sendOnError(error); - - verify(result, times(1)).onNext("one"); - verify(result, times(1)).onNext("two"); - verify(result, times(1)).onError(error); - verify(sSource, times(1)).unsubscribe(); - verify(sOther, times(1)).unsubscribe(); - - } - - @Test - @SuppressWarnings("unchecked") - public void testTakeUntilOtherError() { - Subscription sSource = mock(Subscription.class); - Subscription sOther = mock(Subscription.class); - TestObservable source = new TestObservable(sSource); - TestObservable other = new TestObservable(sOther); - Throwable error = new Throwable(); - - Observer result = mock(Observer.class); - Observable stringObservable = takeUntil(Observable.create(source), Observable.create(other)); - stringObservable.subscribe(result); - source.sendOnNext("one"); - source.sendOnNext("two"); - other.sendOnError(error); - - verify(result, times(1)).onNext("one"); - verify(result, times(1)).onNext("two"); - verify(result, times(1)).onError(error); - verify(result, times(0)).onCompleted(); - verify(sSource, times(1)).unsubscribe(); - verify(sOther, times(1)).unsubscribe(); - - } - - @Test - @SuppressWarnings("unchecked") - public void testTakeUntilOtherCompleted() { - Subscription sSource = mock(Subscription.class); - Subscription sOther = mock(Subscription.class); - TestObservable source = new TestObservable(sSource); - TestObservable other = new TestObservable(sOther); - - Observer result = mock(Observer.class); - Observable stringObservable = takeUntil(Observable.create(source), Observable.create(other)); - stringObservable.subscribe(result); - source.sendOnNext("one"); - source.sendOnNext("two"); - other.sendOnCompleted(); - - verify(result, times(1)).onNext("one"); - verify(result, times(1)).onNext("two"); - verify(result, times(0)).onCompleted(); - verify(sSource, times(0)).unsubscribe(); - verify(sOther, times(0)).unsubscribe(); - - } - - private static class TestObservable implements OnSubscribeFunc { - - Observer observer = null; - Subscription s; - - public TestObservable(Subscription s) { - this.s = s; - } - - /* used to simulate subscription */ - public void sendOnCompleted() { - observer.onCompleted(); - } - - /* used to simulate subscription */ - public void sendOnNext(String value) { - observer.onNext(value); - } - - /* used to simulate subscription */ - public void sendOnError(Throwable e) { - observer.onError(e); - } - - @Override - public Subscription onSubscribe(final Observer observer) { - this.observer = observer; - return s; - } - } - - } } diff --git a/rxjava-core/src/main/java/rx/operators/OperationTakeWhile.java b/rxjava-core/src/main/java/rx/operators/OperationTakeWhile.java index 5b833b22a1..b56029bcae 100644 --- a/rxjava-core/src/main/java/rx/operators/OperationTakeWhile.java +++ b/rxjava-core/src/main/java/rx/operators/OperationTakeWhile.java @@ -15,24 +15,15 @@ */ package rx.operators; -import static org.junit.Assert.*; -import static org.mockito.Matchers.*; -import static org.mockito.Mockito.*; - -import java.util.concurrent.atomic.AtomicInteger; - -import org.junit.Test; - import rx.Observable; import rx.Observable.OnSubscribeFunc; import rx.Observer; import rx.Subscription; -import rx.subjects.PublishSubject; -import rx.subjects.Subject; -import rx.subscriptions.Subscriptions; import rx.util.functions.Func1; import rx.util.functions.Func2; +import java.util.concurrent.atomic.AtomicInteger; + /** * Returns an Observable that emits items emitted by the source Observable as long as a specified * condition is true. @@ -151,207 +142,4 @@ public void onNext(T args) { } } - - public static class UnitTest { - - @Test - public void testTakeWhile1() { - Observable w = Observable.from(1, 2, 3); - Observable take = Observable.create(takeWhile(w, new Func1() - { - @Override - public Boolean call(Integer input) - { - return input < 3; - } - })); - - @SuppressWarnings("unchecked") - Observer aObserver = mock(Observer.class); - take.subscribe(aObserver); - verify(aObserver, times(1)).onNext(1); - verify(aObserver, times(1)).onNext(2); - verify(aObserver, never()).onNext(3); - verify(aObserver, never()).onError(any(Throwable.class)); - verify(aObserver, times(1)).onCompleted(); - } - - @Test - public void testTakeWhileOnSubject1() { - Subject s = PublishSubject.create(); - Observable take = Observable.create(takeWhile(s, new Func1() - { - @Override - public Boolean call(Integer input) - { - return input < 3; - } - })); - - @SuppressWarnings("unchecked") - Observer aObserver = mock(Observer.class); - take.subscribe(aObserver); - - s.onNext(1); - s.onNext(2); - s.onNext(3); - s.onNext(4); - s.onNext(5); - s.onCompleted(); - - verify(aObserver, times(1)).onNext(1); - verify(aObserver, times(1)).onNext(2); - verify(aObserver, never()).onNext(3); - verify(aObserver, never()).onNext(4); - verify(aObserver, never()).onNext(5); - verify(aObserver, never()).onError(any(Throwable.class)); - verify(aObserver, times(1)).onCompleted(); - } - - @Test - public void testTakeWhile2() { - Observable w = Observable.from("one", "two", "three"); - Observable take = Observable.create(takeWhileWithIndex(w, new Func2() - { - @Override - public Boolean call(String input, Integer index) - { - return index < 2; - } - })); - - @SuppressWarnings("unchecked") - Observer aObserver = mock(Observer.class); - take.subscribe(aObserver); - verify(aObserver, times(1)).onNext("one"); - verify(aObserver, times(1)).onNext("two"); - verify(aObserver, never()).onNext("three"); - verify(aObserver, never()).onError(any(Throwable.class)); - verify(aObserver, times(1)).onCompleted(); - } - - @Test - public void testTakeWhileDoesntLeakErrors() { - Observable source = Observable.create(new OnSubscribeFunc() - { - @Override - public Subscription onSubscribe(Observer observer) - { - observer.onNext("one"); - observer.onError(new Throwable("test failed")); - return Subscriptions.empty(); - } - }); - - Observable.create(takeWhile(source, new Func1() - { - @Override - public Boolean call(String s) - { - return false; - } - })).toBlockingObservable().last(); - } - - @Test - public void testTakeWhileProtectsPredicateCall() { - TestObservable source = new TestObservable(mock(Subscription.class), "one"); - final RuntimeException testException = new RuntimeException("test exception"); - - @SuppressWarnings("unchecked") - Observer aObserver = mock(Observer.class); - Observable take = Observable.create(takeWhile(Observable.create(source), new Func1() - { - @Override - public Boolean call(String s) - { - throw testException; - } - })); - take.subscribe(aObserver); - - // wait for the Observable to complete - try { - source.t.join(); - } catch (Throwable e) { - e.printStackTrace(); - fail(e.getMessage()); - } - - verify(aObserver, never()).onNext(any(String.class)); - verify(aObserver, times(1)).onError(testException); - } - - @Test - public void testUnsubscribeAfterTake() { - Subscription s = mock(Subscription.class); - TestObservable w = new TestObservable(s, "one", "two", "three"); - - @SuppressWarnings("unchecked") - Observer aObserver = mock(Observer.class); - Observable take = Observable.create(takeWhileWithIndex(Observable.create(w), new Func2() - { - @Override - public Boolean call(String s, Integer index) - { - return index < 1; - } - })); - take.subscribe(aObserver); - - // wait for the Observable to complete - try { - w.t.join(); - } catch (Throwable e) { - e.printStackTrace(); - fail(e.getMessage()); - } - - System.out.println("TestObservable thread finished"); - verify(aObserver, times(1)).onNext("one"); - verify(aObserver, never()).onNext("two"); - verify(aObserver, never()).onNext("three"); - verify(s, times(1)).unsubscribe(); - } - - private static class TestObservable implements OnSubscribeFunc { - - final Subscription s; - final String[] values; - Thread t = null; - - public TestObservable(Subscription s, String... values) { - this.s = s; - this.values = values; - } - - @Override - public Subscription onSubscribe(final Observer observer) { - System.out.println("TestObservable subscribed to ..."); - t = new Thread(new Runnable() { - - @Override - public void run() { - try { - System.out.println("running TestObservable thread"); - for (String s : values) { - System.out.println("TestObservable onNext: " + s); - observer.onNext(s); - } - observer.onCompleted(); - } catch (Throwable e) { - throw new RuntimeException(e); - } - } - - }); - System.out.println("starting TestObservable thread"); - t.start(); - System.out.println("done starting TestObservable thread"); - return s; - } - - } - } - } diff --git a/rxjava-core/src/main/java/rx/operators/OperationThrottleFirst.java b/rxjava-core/src/main/java/rx/operators/OperationThrottleFirst.java index 4c3a1ea8d4..ebc6bf55d9 100644 --- a/rxjava-core/src/main/java/rx/operators/OperationThrottleFirst.java +++ b/rxjava-core/src/main/java/rx/operators/OperationThrottleFirst.java @@ -15,27 +15,17 @@ */ package rx.operators; -import static org.mockito.Matchers.*; -import static org.mockito.Mockito.*; - -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicLong; - -import org.junit.Before; -import org.junit.Test; -import org.mockito.InOrder; - import rx.Observable; import rx.Observable.OnSubscribeFunc; import rx.Observer; import rx.Scheduler; import rx.Subscription; import rx.concurrency.Schedulers; -import rx.concurrency.TestScheduler; -import rx.subscriptions.Subscriptions; -import rx.util.functions.Action0; import rx.util.functions.Func1; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicLong; + /** * Throttle by windowing a stream and returning the first value in each window. */ @@ -94,104 +84,4 @@ public Boolean call(T value) { } }; } - - public static class UnitTest { - - private TestScheduler scheduler; - private Observer observer; - - @Before - @SuppressWarnings("unchecked") - public void before() { - scheduler = new TestScheduler(); - observer = mock(Observer.class); - } - - @Test - public void testThrottlingWithCompleted() { - Observable source = Observable.create(new OnSubscribeFunc() { - @Override - public Subscription onSubscribe(Observer observer) { - publishNext(observer, 100, "one"); // publish as it's first - publishNext(observer, 300, "two"); // skip as it's last within the first 400 - publishNext(observer, 900, "three"); // publish - publishNext(observer, 905, "four"); // skip - publishCompleted(observer, 1000); // Should be published as soon as the timeout expires. - - return Subscriptions.empty(); - } - }); - - Observable sampled = Observable.create(OperationThrottleFirst.throttleFirst(source, 400, TimeUnit.MILLISECONDS, scheduler)); - sampled.subscribe(observer); - - InOrder inOrder = inOrder(observer); - - scheduler.advanceTimeTo(1000, TimeUnit.MILLISECONDS); - inOrder.verify(observer, times(1)).onNext("one"); - inOrder.verify(observer, times(0)).onNext("two"); - inOrder.verify(observer, times(1)).onNext("three"); - inOrder.verify(observer, times(0)).onNext("four"); - inOrder.verify(observer, times(1)).onCompleted(); - inOrder.verifyNoMoreInteractions(); - } - - @Test - public void testThrottlingWithError() { - Observable source = Observable.create(new OnSubscribeFunc() { - @Override - public Subscription onSubscribe(Observer observer) { - Exception error = new TestException(); - publishNext(observer, 100, "one"); // Should be published since it is first - publishNext(observer, 200, "two"); // Should be skipped since onError will arrive before the timeout expires - publishError(observer, 300, error); // Should be published as soon as the timeout expires. - - return Subscriptions.empty(); - } - }); - - Observable sampled = Observable.create(OperationThrottleFirst.throttleFirst(source, 400, TimeUnit.MILLISECONDS, scheduler)); - sampled.subscribe(observer); - - InOrder inOrder = inOrder(observer); - - scheduler.advanceTimeTo(400, TimeUnit.MILLISECONDS); - inOrder.verify(observer).onNext("one"); - inOrder.verify(observer).onError(any(TestException.class)); - inOrder.verifyNoMoreInteractions(); - } - - private void publishCompleted(final Observer observer, long delay) { - scheduler.schedule(new Action0() { - @Override - public void call() { - observer.onCompleted(); - } - }, delay, TimeUnit.MILLISECONDS); - } - - private void publishError(final Observer observer, long delay, final Exception error) { - scheduler.schedule(new Action0() { - @Override - public void call() { - observer.onError(error); - } - }, delay, TimeUnit.MILLISECONDS); - } - - private void publishNext(final Observer observer, long delay, final T value) { - scheduler.schedule(new Action0() { - @Override - public void call() { - observer.onNext(value); - } - }, delay, TimeUnit.MILLISECONDS); - } - - @SuppressWarnings("serial") - private class TestException extends Exception { - } - - } - } diff --git a/rxjava-core/src/main/java/rx/operators/OperationTimeInterval.java b/rxjava-core/src/main/java/rx/operators/OperationTimeInterval.java index 7b70818bc1..874cb9dd39 100644 --- a/rxjava-core/src/main/java/rx/operators/OperationTimeInterval.java +++ b/rxjava-core/src/main/java/rx/operators/OperationTimeInterval.java @@ -15,25 +15,12 @@ */ package rx.operators; -import static org.mockito.Mockito.inOrder; -import static org.mockito.Mockito.times; - -import java.util.concurrent.TimeUnit; - -import org.junit.Before; -import org.junit.Test; -import org.mockito.InOrder; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; - import rx.Observable; import rx.Observable.OnSubscribeFunc; import rx.Observer; import rx.Scheduler; import rx.Subscription; import rx.concurrency.Schedulers; -import rx.concurrency.TestScheduler; -import rx.subjects.PublishSubject; import rx.util.TimeInterval; /** @@ -93,48 +80,4 @@ public void onError(Throwable e) { observer.onCompleted(); } } - - public static class UnitTest { - - private static final TimeUnit TIME_UNIT = TimeUnit.MILLISECONDS; - - @Mock - private Observer> observer; - - private TestScheduler testScheduler; - private PublishSubject subject; - private Observable> observable; - - @Before - public void setUp() { - MockitoAnnotations.initMocks(this); - testScheduler = new TestScheduler(); - subject = PublishSubject.create(); - observable = subject.timeInterval(testScheduler); - } - - @Test - public void testTimeInterval() { - InOrder inOrder = inOrder(observer); - observable.subscribe(observer); - - testScheduler.advanceTimeBy(1000, TIME_UNIT); - subject.onNext(1); - testScheduler.advanceTimeBy(2000, TIME_UNIT); - subject.onNext(2); - testScheduler.advanceTimeBy(3000, TIME_UNIT); - subject.onNext(3); - subject.onCompleted(); - - inOrder.verify(observer, times(1)).onNext( - new TimeInterval(1000, 1)); - inOrder.verify(observer, times(1)).onNext( - new TimeInterval(2000, 2)); - inOrder.verify(observer, times(1)).onNext( - new TimeInterval(3000, 3)); - inOrder.verify(observer, times(1)).onCompleted(); - inOrder.verifyNoMoreInteractions(); - } - } - } diff --git a/rxjava-core/src/main/java/rx/operators/OperationToObservableFuture.java b/rxjava-core/src/main/java/rx/operators/OperationToObservableFuture.java index 958aa9ad3f..af2f0b1a3f 100644 --- a/rxjava-core/src/main/java/rx/operators/OperationToObservableFuture.java +++ b/rxjava-core/src/main/java/rx/operators/OperationToObservableFuture.java @@ -15,18 +15,14 @@ */ package rx.operators; -import static org.mockito.Mockito.*; - -import java.util.concurrent.Future; -import java.util.concurrent.TimeUnit; - -import org.junit.Test; - import rx.Observable.OnSubscribeFunc; import rx.Observer; import rx.Subscription; import rx.subscriptions.Subscriptions; +import java.util.concurrent.Future; +import java.util.concurrent.TimeUnit; + /** * Converts a Future into an Observable. *

@@ -39,7 +35,7 @@ * Observable.subscribe(Observer) does nothing. */ public class OperationToObservableFuture { - private static class ToObservableFuture implements OnSubscribeFunc { + static class ToObservableFuture implements OnSubscribeFunc { private final Future that; private final Long time; private final TimeUnit unit; @@ -82,41 +78,4 @@ public static OnSubscribeFunc toObservableFuture(final Future OnSubscribeFunc toObservableFuture(final Future that, long time, TimeUnit unit) { return new ToObservableFuture(that, time, unit); } - - @SuppressWarnings("unchecked") - public static class UnitTest { - @Test - public void testSuccess() throws Exception { - Future future = mock(Future.class); - Object value = new Object(); - when(future.get()).thenReturn(value); - ToObservableFuture ob = new ToObservableFuture(future); - Observer o = mock(Observer.class); - - Subscription sub = ob.onSubscribe(o); - sub.unsubscribe(); - - verify(o, times(1)).onNext(value); - verify(o, times(1)).onCompleted(); - verify(o, never()).onError(null); - verify(future, never()).cancel(true); - } - - @Test - public void testFailure() throws Exception { - Future future = mock(Future.class); - RuntimeException e = new RuntimeException(); - when(future.get()).thenThrow(e); - ToObservableFuture ob = new ToObservableFuture(future); - Observer o = mock(Observer.class); - - Subscription sub = ob.onSubscribe(o); - sub.unsubscribe(); - - verify(o, never()).onNext(null); - verify(o, never()).onCompleted(); - verify(o, times(1)).onError(e); - verify(future, never()).cancel(true); - } - } } diff --git a/rxjava-core/src/main/java/rx/operators/OperationToObservableIterable.java b/rxjava-core/src/main/java/rx/operators/OperationToObservableIterable.java index bebc31550a..a8a970bdd8 100644 --- a/rxjava-core/src/main/java/rx/operators/OperationToObservableIterable.java +++ b/rxjava-core/src/main/java/rx/operators/OperationToObservableIterable.java @@ -15,15 +15,6 @@ */ package rx.operators; -import static org.mockito.Matchers.*; -import static org.mockito.Mockito.*; - -import java.util.Arrays; - -import org.junit.Test; -import org.mockito.Mockito; - -import rx.Observable; import rx.Observable.OnSubscribeFunc; import rx.Observer; import rx.Subscription; @@ -59,21 +50,4 @@ public Subscription onSubscribe(Observer observer) { return Subscriptions.empty(); } } - - public static class UnitTest { - - @Test - public void testIterable() { - Observable observable = Observable.create(toObservableIterable(Arrays. asList("one", "two", "three"))); - - @SuppressWarnings("unchecked") - Observer aObserver = mock(Observer.class); - observable.subscribe(aObserver); - verify(aObserver, times(1)).onNext("one"); - verify(aObserver, times(1)).onNext("two"); - verify(aObserver, times(1)).onNext("three"); - verify(aObserver, Mockito.never()).onError(any(Throwable.class)); - verify(aObserver, times(1)).onCompleted(); - } - } } diff --git a/rxjava-core/src/main/java/rx/operators/OperationToObservableList.java b/rxjava-core/src/main/java/rx/operators/OperationToObservableList.java index f6bc080211..c798cf8cc1 100644 --- a/rxjava-core/src/main/java/rx/operators/OperationToObservableList.java +++ b/rxjava-core/src/main/java/rx/operators/OperationToObservableList.java @@ -15,22 +15,15 @@ */ package rx.operators; -import static org.mockito.Matchers.*; -import static org.mockito.Mockito.*; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.concurrent.ConcurrentLinkedQueue; - -import org.junit.Test; -import org.mockito.Mockito; - import rx.Observable; import rx.Observable.OnSubscribeFunc; import rx.Observer; import rx.Subscription; +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.ConcurrentLinkedQueue; + /** * Returns an Observable that emits a single item, a list composed of all the items emitted by the * source Observable. @@ -93,44 +86,4 @@ public void onCompleted() { }); } } - - public static class UnitTest { - - @Test - public void testList() { - Observable w = Observable.from("one", "two", "three"); - Observable> observable = Observable.create(toObservableList(w)); - - @SuppressWarnings("unchecked") - Observer> aObserver = mock(Observer.class); - observable.subscribe(aObserver); - verify(aObserver, times(1)).onNext(Arrays.asList("one", "two", "three")); - verify(aObserver, Mockito.never()).onError(any(Throwable.class)); - verify(aObserver, times(1)).onCompleted(); - } - - @Test - public void testListMultipleObservers() { - Observable w = Observable.from("one", "two", "three"); - Observable> observable = Observable.create(toObservableList(w)); - - @SuppressWarnings("unchecked") - Observer> o1 = mock(Observer.class); - observable.subscribe(o1); - - @SuppressWarnings("unchecked") - Observer> o2 = mock(Observer.class); - observable.subscribe(o2); - - List expected = Arrays.asList("one", "two", "three"); - - verify(o1, times(1)).onNext(expected); - verify(o1, Mockito.never()).onError(any(Throwable.class)); - verify(o1, times(1)).onCompleted(); - - verify(o2, times(1)).onNext(expected); - verify(o2, Mockito.never()).onError(any(Throwable.class)); - verify(o2, times(1)).onCompleted(); - } - } } diff --git a/rxjava-core/src/main/java/rx/operators/OperationToObservableSortedList.java b/rxjava-core/src/main/java/rx/operators/OperationToObservableSortedList.java index 655f833a5d..cf3ffac636 100644 --- a/rxjava-core/src/main/java/rx/operators/OperationToObservableSortedList.java +++ b/rxjava-core/src/main/java/rx/operators/OperationToObservableSortedList.java @@ -15,25 +15,18 @@ */ package rx.operators; -import static org.mockito.Matchers.*; -import static org.mockito.Mockito.*; +import rx.Observable; +import rx.Observable.OnSubscribeFunc; +import rx.Observer; +import rx.Subscription; +import rx.util.functions.Func2; import java.util.ArrayList; -import java.util.Arrays; import java.util.Collections; import java.util.Comparator; import java.util.List; import java.util.concurrent.ConcurrentLinkedQueue; -import org.junit.Test; -import org.mockito.Mockito; - -import rx.Observable; -import rx.Observable.OnSubscribeFunc; -import rx.Observer; -import rx.Subscription; -import rx.util.functions.Func2; - /** * Return an Observable that emits the items emitted by the source Observable, in a sorted order * (each item emitted by the Observable must implement Comparable with respect to all other items @@ -142,41 +135,4 @@ public Integer call(Object t1, Object t2) { } } - - public static class UnitTest { - - @Test - public void testSortedList() { - Observable w = Observable.from(1, 3, 2, 5, 4); - Observable> observable = Observable.create(toSortedList(w)); - - @SuppressWarnings("unchecked") - Observer> aObserver = mock(Observer.class); - observable.subscribe(aObserver); - verify(aObserver, times(1)).onNext(Arrays.asList(1, 2, 3, 4, 5)); - verify(aObserver, Mockito.never()).onError(any(Throwable.class)); - verify(aObserver, times(1)).onCompleted(); - } - - @Test - public void testSortedListWithCustomFunction() { - Observable w = Observable.from(1, 3, 2, 5, 4); - Observable> observable = Observable.create(toSortedList(w, new Func2() { - - @Override - public Integer call(Integer t1, Integer t2) { - return t2 - t1; - } - - })); - - @SuppressWarnings("unchecked") - Observer> aObserver = mock(Observer.class); - observable.subscribe(aObserver); - verify(aObserver, times(1)).onNext(Arrays.asList(5, 4, 3, 2, 1)); - verify(aObserver, Mockito.never()).onError(any(Throwable.class)); - verify(aObserver, times(1)).onCompleted(); - } - - } } diff --git a/rxjava-core/src/main/java/rx/operators/OperationWindow.java b/rxjava-core/src/main/java/rx/operators/OperationWindow.java index 5cffda9661..61d1839f32 100644 --- a/rxjava-core/src/main/java/rx/operators/OperationWindow.java +++ b/rxjava-core/src/main/java/rx/operators/OperationWindow.java @@ -15,32 +15,19 @@ */ package rx.operators; -import static org.junit.Assert.*; - -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.TimeUnit; - -import org.junit.Before; -import org.junit.Test; - import rx.Observable; import rx.Observable.OnSubscribeFunc; import rx.Observer; import rx.Scheduler; import rx.Subscription; import rx.concurrency.Schedulers; -import rx.concurrency.TestScheduler; -import rx.subscriptions.Subscriptions; import rx.util.Closing; -import rx.util.Closings; import rx.util.Opening; -import rx.util.Openings; -import rx.util.functions.Action0; -import rx.util.functions.Action1; import rx.util.functions.Func0; import rx.util.functions.Func1; +import java.util.concurrent.TimeUnit; + public final class OperationWindow extends ChunkedOperation { public static Func0> windowMaker() { @@ -369,295 +356,4 @@ public Observable getContents() { return Observable.from(contents); } } - - public static class UnitTest { - - private TestScheduler scheduler; - - @Before - public void before() { - scheduler = new TestScheduler(); - } - - private static List> toLists(Observable> observable) { - final List list = new ArrayList(); - final List> lists = new ArrayList>(); - - observable.subscribe(new Action1>() { - @Override - public void call(Observable tObservable) { - tObservable.subscribe(new Action1() { - @Override - public void call(T t) { - list.add(t); - } - }); - lists.add(new ArrayList(list)); - list.clear(); - } - }); - return lists; - } - - @Test - public void testNonOverlappingWindows() { - Observable subject = Observable.from("one", "two", "three", "four", "five"); - Observable> windowed = Observable.create(window(subject, 3)); - - List> windows = toLists(windowed); - - assertEquals(2, windows.size()); - assertEquals(list("one", "two", "three"), windows.get(0)); - assertEquals(list("four", "five"), windows.get(1)); - } - - @Test - public void testSkipAndCountGaplessEindows() { - Observable subject = Observable.from("one", "two", "three", "four", "five"); - Observable> windowed = Observable.create(window(subject, 3, 3)); - - List> windows = toLists(windowed); - - assertEquals(2, windows.size()); - assertEquals(list("one", "two", "three"), windows.get(0)); - assertEquals(list("four", "five"), windows.get(1)); - } - - @Test - public void testOverlappingWindows() { - Observable subject = Observable.from("zero", "one", "two", "three", "four", "five"); - Observable> windowed = Observable.create(window(subject, 3, 1)); - - List> windows = toLists(windowed); - - assertEquals(6, windows.size()); - assertEquals(list("zero", "one", "two"), windows.get(0)); - assertEquals(list("one", "two", "three"), windows.get(1)); - assertEquals(list("two", "three", "four"), windows.get(2)); - assertEquals(list("three", "four", "five"), windows.get(3)); - assertEquals(list("four", "five"), windows.get(4)); - assertEquals(list("five"), windows.get(5)); - } - - @Test - public void testSkipAndCountWindowsWithGaps() { - Observable subject = Observable.from("one", "two", "three", "four", "five"); - Observable> windowed = Observable.create(window(subject, 2, 3)); - - List> windows = toLists(windowed); - - assertEquals(2, windows.size()); - assertEquals(list("one", "two"), windows.get(0)); - assertEquals(list("four", "five"), windows.get(1)); - } - - @Test - public void testTimedAndCount() { - final List list = new ArrayList(); - final List> lists = new ArrayList>(); - - Observable source = Observable.create(new OnSubscribeFunc() { - @Override - public Subscription onSubscribe(Observer observer) { - push(observer, "one", 10); - push(observer, "two", 90); - push(observer, "three", 110); - push(observer, "four", 190); - push(observer, "five", 210); - complete(observer, 250); - return Subscriptions.empty(); - } - }); - - Observable> windowed = Observable.create(window(source, 100, TimeUnit.MILLISECONDS, 2, scheduler)); - windowed.subscribe(observeWindow(list, lists)); - - scheduler.advanceTimeTo(100, TimeUnit.MILLISECONDS); - assertEquals(1, lists.size()); - assertEquals(lists.get(0), list("one", "two")); - - scheduler.advanceTimeTo(200, TimeUnit.MILLISECONDS); - assertEquals(2, lists.size()); - assertEquals(lists.get(1), list("three", "four")); - - scheduler.advanceTimeTo(300, TimeUnit.MILLISECONDS); - assertEquals(3, lists.size()); - assertEquals(lists.get(2), list("five")); - } - - @Test - public void testTimed() { - final List list = new ArrayList(); - final List> lists = new ArrayList>(); - - Observable source = Observable.create(new OnSubscribeFunc() { - @Override - public Subscription onSubscribe(Observer observer) { - push(observer, "one", 98); - push(observer, "two", 99); - push(observer, "three", 100); - push(observer, "four", 101); - push(observer, "five", 102); - complete(observer, 150); - return Subscriptions.empty(); - } - }); - - Observable> windowed = Observable.create(window(source, 100, TimeUnit.MILLISECONDS, scheduler)); - windowed.subscribe(observeWindow(list, lists)); - - scheduler.advanceTimeTo(101, TimeUnit.MILLISECONDS); - assertEquals(1, lists.size()); - assertEquals(lists.get(0), list("one", "two", "three")); - - scheduler.advanceTimeTo(201, TimeUnit.MILLISECONDS); - assertEquals(2, lists.size()); - assertEquals(lists.get(1), list("four", "five")); - } - - @Test - public void testObservableBasedOpenerAndCloser() { - final List list = new ArrayList(); - final List> lists = new ArrayList>(); - - Observable source = Observable.create(new OnSubscribeFunc() { - @Override - public Subscription onSubscribe(Observer observer) { - push(observer, "one", 10); - push(observer, "two", 60); - push(observer, "three", 110); - push(observer, "four", 160); - push(observer, "five", 210); - complete(observer, 500); - return Subscriptions.empty(); - } - }); - - Observable openings = Observable.create(new OnSubscribeFunc() { - @Override - public Subscription onSubscribe(Observer observer) { - push(observer, Openings.create(), 50); - push(observer, Openings.create(), 200); - complete(observer, 250); - return Subscriptions.empty(); - } - }); - - Func1> closer = new Func1>() { - @Override - public Observable call(Opening opening) { - return Observable.create(new OnSubscribeFunc() { - @Override - public Subscription onSubscribe(Observer observer) { - push(observer, Closings.create(), 100); - complete(observer, 101); - return Subscriptions.empty(); - } - }); - } - }; - - Observable> windowed = Observable.create(window(source, openings, closer)); - windowed.subscribe(observeWindow(list, lists)); - - scheduler.advanceTimeTo(500, TimeUnit.MILLISECONDS); - assertEquals(2, lists.size()); - assertEquals(lists.get(0), list("two", "three")); - assertEquals(lists.get(1), list("five")); - } - - @Test - public void testObservableBasedCloser() { - final List list = new ArrayList(); - final List> lists = new ArrayList>(); - - Observable source = Observable.create(new OnSubscribeFunc() { - @Override - public Subscription onSubscribe(Observer observer) { - push(observer, "one", 10); - push(observer, "two", 60); - push(observer, "three", 110); - push(observer, "four", 160); - push(observer, "five", 210); - complete(observer, 250); - return Subscriptions.empty(); - } - }); - - Func0> closer = new Func0>() { - @Override - public Observable call() { - return Observable.create(new OnSubscribeFunc() { - @Override - public Subscription onSubscribe(Observer observer) { - push(observer, Closings.create(), 100); - complete(observer, 101); - return Subscriptions.empty(); - } - }); - } - }; - - Observable> windowed = Observable.create(window(source, closer)); - windowed.subscribe(observeWindow(list, lists)); - - scheduler.advanceTimeTo(500, TimeUnit.MILLISECONDS); - assertEquals(3, lists.size()); - assertEquals(lists.get(0), list("one", "two")); - assertEquals(lists.get(1), list("three", "four")); - assertEquals(lists.get(2), list("five")); - } - - private List list(String... args) { - List list = new ArrayList(); - for (String arg : args) { - list.add(arg); - } - return list; - } - - private void push(final Observer observer, final T value, int delay) { - scheduler.schedule(new Action0() { - @Override - public void call() { - observer.onNext(value); - } - }, delay, TimeUnit.MILLISECONDS); - } - - private void complete(final Observer observer, int delay) { - scheduler.schedule(new Action0() { - @Override - public void call() { - observer.onCompleted(); - } - }, delay, TimeUnit.MILLISECONDS); - } - - private Action1> observeWindow(final List list, final List> lists) { - return new Action1>() { - @Override - public void call(Observable stringObservable) { - stringObservable.subscribe(new Observer() { - @Override - public void onCompleted() { - lists.add(new ArrayList(list)); - list.clear(); - } - - @Override - public void onError(Throwable e) { - fail(e.getMessage()); - } - - @Override - public void onNext(String args) { - list.add(args); - } - }); - } - }; - } - - } } diff --git a/rxjava-core/src/main/java/rx/operators/OperationZip.java b/rxjava-core/src/main/java/rx/operators/OperationZip.java index 517a1faecc..eb07f87738 100644 --- a/rxjava-core/src/main/java/rx/operators/OperationZip.java +++ b/rxjava-core/src/main/java/rx/operators/OperationZip.java @@ -15,33 +15,15 @@ */ package rx.operators; -import static org.mockito.Matchers.*; -import static org.mockito.Mockito.*; - -import java.util.Arrays; -import java.util.Collection; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentLinkedQueue; -import java.util.concurrent.atomic.AtomicBoolean; - -import org.junit.Test; -import org.mockito.InOrder; - import rx.Observable; import rx.Observable.OnSubscribeFunc; import rx.Observer; import rx.Subscription; -import rx.subscriptions.Subscriptions; -import rx.util.functions.Func2; -import rx.util.functions.Func3; -import rx.util.functions.Func4; -import rx.util.functions.Func5; -import rx.util.functions.Func6; -import rx.util.functions.Func7; -import rx.util.functions.Func8; -import rx.util.functions.Func9; -import rx.util.functions.FuncN; -import rx.util.functions.Functions; +import rx.util.functions.*; + +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentLinkedQueue; +import java.util.concurrent.atomic.AtomicBoolean; /** * Returns an Observable that emits the results of a function applied to sets of items emitted, in @@ -159,7 +141,7 @@ public static OnSubscribeFunc zip(Iterable> ws, F /* * ThreadSafe */ - private static class ZipObserver implements Observer { + static class ZipObserver implements Observer { final Observable w; final Aggregator a; private final SafeObservableSubscription subscription = new SafeObservableSubscription(); @@ -204,7 +186,7 @@ public void onNext(T args) { * * @param */ - private static class Aggregator implements OnSubscribeFunc { + static class Aggregator implements OnSubscribeFunc { private volatile SynchronizedObserver observer; private final FuncN zipFunction; @@ -228,7 +210,7 @@ public Aggregator(FuncN zipFunction) { * * @param w */ - private void addObserver(ZipObserver w) { + void addObserver(ZipObserver w) { // initialize this ZipObserver observers.add(w); receivedValuesPerObserver.put(w, new ConcurrentLinkedQueue()); @@ -361,566 +343,4 @@ private void stop() { } } - - public static class UnitTest { - - @SuppressWarnings("unchecked") - @Test - public void testCollectionSizeDifferentThanFunction() { - FuncN zipr = Functions.fromFunc(getConcatStringIntegerIntArrayZipr()); - //Func3 - - /* define a Observer to receive aggregated events */ - Observer aObserver = mock(Observer.class); - - @SuppressWarnings("rawtypes") - Collection ws = java.util.Collections.singleton(Observable.from("one", "two")); - Observable w = Observable.create(zip(ws, zipr)); - w.subscribe(aObserver); - - verify(aObserver, times(1)).onError(any(Throwable.class)); - verify(aObserver, never()).onCompleted(); - verify(aObserver, never()).onNext(any(String.class)); - } - - @SuppressWarnings("unchecked") - /* mock calls don't do generics */ - @Test - public void testZippingDifferentLengthObservableSequences1() { - Observer w = mock(Observer.class); - - TestObservable w1 = new TestObservable(); - TestObservable w2 = new TestObservable(); - TestObservable w3 = new TestObservable(); - - Observable zipW = Observable.create(zip(Observable.create(w1), Observable.create(w2), Observable.create(w3), getConcat3StringsZipr())); - zipW.subscribe(w); - - /* simulate sending data */ - // once for w1 - w1.observer.onNext("1a"); - w1.observer.onCompleted(); - // twice for w2 - w2.observer.onNext("2a"); - w2.observer.onNext("2b"); - w2.observer.onCompleted(); - // 4 times for w3 - w3.observer.onNext("3a"); - w3.observer.onNext("3b"); - w3.observer.onNext("3c"); - w3.observer.onNext("3d"); - w3.observer.onCompleted(); - - /* we should have been called 1 time on the Observer */ - InOrder inOrder = inOrder(w); - inOrder.verify(w).onNext("1a2a3a"); - - inOrder.verify(w, times(1)).onCompleted(); - } - - @Test - public void testZippingDifferentLengthObservableSequences2() { - @SuppressWarnings("unchecked") - Observer w = mock(Observer.class); - - TestObservable w1 = new TestObservable(); - TestObservable w2 = new TestObservable(); - TestObservable w3 = new TestObservable(); - - Observable zipW = Observable.create(zip(Observable.create(w1), Observable.create(w2), Observable.create(w3), getConcat3StringsZipr())); - zipW.subscribe(w); - - /* simulate sending data */ - // 4 times for w1 - w1.observer.onNext("1a"); - w1.observer.onNext("1b"); - w1.observer.onNext("1c"); - w1.observer.onNext("1d"); - w1.observer.onCompleted(); - // twice for w2 - w2.observer.onNext("2a"); - w2.observer.onNext("2b"); - w2.observer.onCompleted(); - // 1 times for w3 - w3.observer.onNext("3a"); - w3.observer.onCompleted(); - - /* we should have been called 1 time on the Observer */ - InOrder inOrder = inOrder(w); - inOrder.verify(w).onNext("1a2a3a"); - - inOrder.verify(w, times(1)).onCompleted(); - - } - - /** - * Testing internal private logic due to the complexity so I want to use TDD to test as a I build it rather than relying purely on the overall functionality expected by the public methods. - */ - @SuppressWarnings("unchecked") - /* mock calls don't do generics */ - @Test - public void testAggregatorSimple() { - FuncN zipr = getConcatZipr(); - /* create the aggregator which will execute the zip function when all Observables provide values */ - Aggregator a = new Aggregator(zipr); - - /* define a Observer to receive aggregated events */ - Observer aObserver = mock(Observer.class); - a.onSubscribe(aObserver); - - /* mock the Observable Observers that are 'pushing' data for us */ - ZipObserver r1 = mock(ZipObserver.class); - ZipObserver r2 = mock(ZipObserver.class); - - /* pretend we're starting up */ - a.addObserver(r1); - a.addObserver(r2); - - /* simulate the Observables pushing data into the aggregator */ - a.next(r1, "hello"); - a.next(r2, "world"); - - InOrder inOrder = inOrder(aObserver); - - verify(aObserver, never()).onError(any(Throwable.class)); - verify(aObserver, never()).onCompleted(); - inOrder.verify(aObserver, times(1)).onNext("helloworld"); - - a.next(r1, "hello "); - a.next(r2, "again"); - - verify(aObserver, never()).onError(any(Throwable.class)); - verify(aObserver, never()).onCompleted(); - inOrder.verify(aObserver, times(1)).onNext("hello again"); - - a.complete(r1); - a.complete(r2); - - inOrder.verify(aObserver, never()).onNext(anyString()); - verify(aObserver, times(1)).onCompleted(); - } - - @SuppressWarnings("unchecked") - /* mock calls don't do generics */ - @Test - public void testAggregatorDifferentSizedResultsWithOnComplete() { - FuncN zipr = getConcatZipr(); - /* create the aggregator which will execute the zip function when all Observables provide values */ - Aggregator a = new Aggregator(zipr); - - /* define a Observer to receive aggregated events */ - Observer aObserver = mock(Observer.class); - a.onSubscribe(aObserver); - - /* mock the Observable Observers that are 'pushing' data for us */ - ZipObserver r1 = mock(ZipObserver.class); - ZipObserver r2 = mock(ZipObserver.class); - - /* pretend we're starting up */ - a.addObserver(r1); - a.addObserver(r2); - - /* simulate the Observables pushing data into the aggregator */ - a.next(r1, "hello"); - a.next(r2, "world"); - a.complete(r2); - - InOrder inOrder = inOrder(aObserver); - - inOrder.verify(aObserver, never()).onError(any(Throwable.class)); - inOrder.verify(aObserver, never()).onCompleted(); - inOrder.verify(aObserver, times(1)).onNext("helloworld"); - - a.next(r1, "hi"); - a.complete(r1); - - inOrder.verify(aObserver, never()).onError(any(Throwable.class)); - inOrder.verify(aObserver, times(1)).onCompleted(); - inOrder.verify(aObserver, never()).onNext(anyString()); - } - - @SuppressWarnings("unchecked") - /* mock calls don't do generics */ - @Test - public void testAggregateMultipleTypes() { - FuncN zipr = getConcatZipr(); - /* create the aggregator which will execute the zip function when all Observables provide values */ - Aggregator a = new Aggregator(zipr); - - /* define a Observer to receive aggregated events */ - Observer aObserver = mock(Observer.class); - a.onSubscribe(aObserver); - - /* mock the Observable Observers that are 'pushing' data for us */ - ZipObserver r1 = mock(ZipObserver.class); - ZipObserver r2 = mock(ZipObserver.class); - - /* pretend we're starting up */ - a.addObserver(r1); - a.addObserver(r2); - - /* simulate the Observables pushing data into the aggregator */ - a.next(r1, "hello"); - a.next(r2, "world"); - a.complete(r2); - - InOrder inOrder = inOrder(aObserver); - - inOrder.verify(aObserver, never()).onError(any(Throwable.class)); - inOrder.verify(aObserver, never()).onCompleted(); - inOrder.verify(aObserver, times(1)).onNext("helloworld"); - - a.next(r1, "hi"); - a.complete(r1); - - inOrder.verify(aObserver, never()).onError(any(Throwable.class)); - inOrder.verify(aObserver, times(1)).onCompleted(); - inOrder.verify(aObserver, never()).onNext(anyString()); - } - - @SuppressWarnings("unchecked") - /* mock calls don't do generics */ - @Test - public void testAggregate3Types() { - FuncN zipr = getConcatZipr(); - /* create the aggregator which will execute the zip function when all Observables provide values */ - Aggregator a = new Aggregator(zipr); - - /* define a Observer to receive aggregated events */ - Observer aObserver = mock(Observer.class); - a.onSubscribe(aObserver); - - /* mock the Observable Observers that are 'pushing' data for us */ - ZipObserver r1 = mock(ZipObserver.class); - ZipObserver r2 = mock(ZipObserver.class); - ZipObserver r3 = mock(ZipObserver.class); - - /* pretend we're starting up */ - a.addObserver(r1); - a.addObserver(r2); - a.addObserver(r3); - - /* simulate the Observables pushing data into the aggregator */ - a.next(r1, "hello"); - a.next(r2, 2); - a.next(r3, new int[] { 5, 6, 7 }); - - verify(aObserver, never()).onError(any(Throwable.class)); - verify(aObserver, never()).onCompleted(); - verify(aObserver, times(1)).onNext("hello2[5, 6, 7]"); - } - - @SuppressWarnings("unchecked") - /* mock calls don't do generics */ - @Test - public void testAggregatorsWithDifferentSizesAndTiming() { - FuncN zipr = getConcatZipr(); - /* create the aggregator which will execute the zip function when all Observables provide values */ - Aggregator a = new Aggregator(zipr); - - /* define a Observer to receive aggregated events */ - Observer aObserver = mock(Observer.class); - a.onSubscribe(aObserver); - - /* mock the Observable Observers that are 'pushing' data for us */ - ZipObserver r1 = mock(ZipObserver.class); - ZipObserver r2 = mock(ZipObserver.class); - - /* pretend we're starting up */ - a.addObserver(r1); - a.addObserver(r2); - - /* simulate the Observables pushing data into the aggregator */ - a.next(r1, "one"); - a.next(r1, "two"); - a.next(r1, "three"); - a.next(r2, "A"); - - verify(aObserver, never()).onError(any(Throwable.class)); - verify(aObserver, never()).onCompleted(); - verify(aObserver, times(1)).onNext("oneA"); - - a.next(r1, "four"); - a.complete(r1); - a.next(r2, "B"); - verify(aObserver, times(1)).onNext("twoB"); - a.next(r2, "C"); - verify(aObserver, times(1)).onNext("threeC"); - a.next(r2, "D"); - verify(aObserver, times(1)).onNext("fourD"); - a.next(r2, "E"); - verify(aObserver, never()).onNext("E"); - a.complete(r2); - - verify(aObserver, never()).onError(any(Throwable.class)); - verify(aObserver, times(1)).onCompleted(); - } - - @SuppressWarnings("unchecked") - /* mock calls don't do generics */ - @Test - public void testAggregatorError() { - FuncN zipr = getConcatZipr(); - /* create the aggregator which will execute the zip function when all Observables provide values */ - Aggregator a = new Aggregator(zipr); - - /* define a Observer to receive aggregated events */ - Observer aObserver = mock(Observer.class); - a.onSubscribe(aObserver); - - /* mock the Observable Observers that are 'pushing' data for us */ - ZipObserver r1 = mock(ZipObserver.class); - ZipObserver r2 = mock(ZipObserver.class); - - /* pretend we're starting up */ - a.addObserver(r1); - a.addObserver(r2); - - /* simulate the Observables pushing data into the aggregator */ - a.next(r1, "hello"); - a.next(r2, "world"); - - verify(aObserver, never()).onError(any(Throwable.class)); - verify(aObserver, never()).onCompleted(); - verify(aObserver, times(1)).onNext("helloworld"); - - a.error(r1, new RuntimeException("")); - a.next(r1, "hello"); - a.next(r2, "again"); - - verify(aObserver, times(1)).onError(any(Throwable.class)); - verify(aObserver, never()).onCompleted(); - // we don't want to be called again after an error - verify(aObserver, times(0)).onNext("helloagain"); - } - - @SuppressWarnings("unchecked") - /* mock calls don't do generics */ - @Test - public void testAggregatorUnsubscribe() { - FuncN zipr = getConcatZipr(); - /* create the aggregator which will execute the zip function when all Observables provide values */ - Aggregator a = new Aggregator(zipr); - - /* define a Observer to receive aggregated events */ - Observer aObserver = mock(Observer.class); - Subscription subscription = a.onSubscribe(aObserver); - - /* mock the Observable Observers that are 'pushing' data for us */ - ZipObserver r1 = mock(ZipObserver.class); - ZipObserver r2 = mock(ZipObserver.class); - - /* pretend we're starting up */ - a.addObserver(r1); - a.addObserver(r2); - - /* simulate the Observables pushing data into the aggregator */ - a.next(r1, "hello"); - a.next(r2, "world"); - - verify(aObserver, never()).onError(any(Throwable.class)); - verify(aObserver, never()).onCompleted(); - verify(aObserver, times(1)).onNext("helloworld"); - - subscription.unsubscribe(); - a.next(r1, "hello"); - a.next(r2, "again"); - - verify(aObserver, times(0)).onError(any(Throwable.class)); - verify(aObserver, never()).onCompleted(); - // we don't want to be called again after an error - verify(aObserver, times(0)).onNext("helloagain"); - } - - @SuppressWarnings("unchecked") - /* mock calls don't do generics */ - @Test - public void testAggregatorEarlyCompletion() { - FuncN zipr = getConcatZipr(); - /* create the aggregator which will execute the zip function when all Observables provide values */ - Aggregator a = new Aggregator(zipr); - - /* define a Observer to receive aggregated events */ - Observer aObserver = mock(Observer.class); - a.onSubscribe(aObserver); - - /* mock the Observable Observers that are 'pushing' data for us */ - ZipObserver r1 = mock(ZipObserver.class); - ZipObserver r2 = mock(ZipObserver.class); - - /* pretend we're starting up */ - a.addObserver(r1); - a.addObserver(r2); - - /* simulate the Observables pushing data into the aggregator */ - a.next(r1, "one"); - a.next(r1, "two"); - a.complete(r1); - a.next(r2, "A"); - - InOrder inOrder = inOrder(aObserver); - - inOrder.verify(aObserver, never()).onError(any(Throwable.class)); - inOrder.verify(aObserver, never()).onCompleted(); - inOrder.verify(aObserver, times(1)).onNext("oneA"); - - a.complete(r2); - - inOrder.verify(aObserver, never()).onError(any(Throwable.class)); - inOrder.verify(aObserver, times(1)).onCompleted(); - inOrder.verify(aObserver, never()).onNext(anyString()); - } - - @SuppressWarnings("unchecked") - /* mock calls don't do generics */ - @Test - public void testZip2Types() { - Func2 zipr = getConcatStringIntegerZipr(); - - /* define a Observer to receive aggregated events */ - Observer aObserver = mock(Observer.class); - - Observable w = Observable.create(zip(Observable.from("one", "two"), Observable.from(2, 3, 4), zipr)); - w.subscribe(aObserver); - - verify(aObserver, never()).onError(any(Throwable.class)); - verify(aObserver, times(1)).onCompleted(); - verify(aObserver, times(1)).onNext("one2"); - verify(aObserver, times(1)).onNext("two3"); - verify(aObserver, never()).onNext("4"); - } - - @SuppressWarnings("unchecked") - /* mock calls don't do generics */ - @Test - public void testZip3Types() { - Func3 zipr = getConcatStringIntegerIntArrayZipr(); - - /* define a Observer to receive aggregated events */ - Observer aObserver = mock(Observer.class); - - Observable w = Observable.create(zip(Observable.from("one", "two"), Observable.from(2), Observable.from(new int[] { 4, 5, 6 }), zipr)); - w.subscribe(aObserver); - - verify(aObserver, never()).onError(any(Throwable.class)); - verify(aObserver, times(1)).onCompleted(); - verify(aObserver, times(1)).onNext("one2[4, 5, 6]"); - verify(aObserver, never()).onNext("two"); - } - - @Test - public void testOnNextExceptionInvokesOnError() { - Func2 zipr = getDivideZipr(); - - @SuppressWarnings("unchecked") - Observer aObserver = mock(Observer.class); - - Observable w = Observable.create(zip(Observable.from(10, 20, 30), Observable.from(0, 1, 2), zipr)); - w.subscribe(aObserver); - - verify(aObserver, times(1)).onError(any(Throwable.class)); - } - - private Func2 getDivideZipr() { - Func2 zipr = new Func2() { - - @Override - public Integer call(Integer i1, Integer i2) { - return i1 / i2; - } - - }; - return zipr; - } - - private Func3 getConcat3StringsZipr() { - Func3 zipr = new Func3() { - - @Override - public String call(String a1, String a2, String a3) { - if (a1 == null) { - a1 = ""; - } - if (a2 == null) { - a2 = ""; - } - if (a3 == null) { - a3 = ""; - } - return a1 + a2 + a3; - } - - }; - return zipr; - } - - private FuncN getConcatZipr() { - FuncN zipr = new FuncN() { - - @Override - public String call(Object... args) { - String returnValue = ""; - for (Object o : args) { - if (o != null) { - returnValue += getStringValue(o); - } - } - System.out.println("returning: " + returnValue); - return returnValue; - } - - }; - return zipr; - } - - private Func2 getConcatStringIntegerZipr() { - Func2 zipr = new Func2() { - - @Override - public String call(String s, Integer i) { - return getStringValue(s) + getStringValue(i); - } - - }; - return zipr; - } - - private Func3 getConcatStringIntegerIntArrayZipr() { - Func3 zipr = new Func3() { - - @Override - public String call(String s, Integer i, int[] iArray) { - return getStringValue(s) + getStringValue(i) + getStringValue(iArray); - } - - }; - return zipr; - } - - private static String getStringValue(Object o) { - if (o == null) { - return ""; - } else { - if (o instanceof int[]) { - return Arrays.toString((int[]) o); - } else { - return String.valueOf(o); - } - } - } - - private static class TestObservable implements OnSubscribeFunc { - - Observer observer; - - @Override - public Subscription onSubscribe(Observer Observer) { - // just store the variable where it can be accessed so we can manually trigger it - this.observer = Observer; - return Subscriptions.empty(); - } - - } - } - } diff --git a/rxjava-core/src/main/java/rx/operators/OperatorTester.java b/rxjava-core/src/main/java/rx/operators/OperatorTester.java deleted file mode 100644 index 62b41a0567..0000000000 --- a/rxjava-core/src/main/java/rx/operators/OperatorTester.java +++ /dev/null @@ -1,97 +0,0 @@ -/** - * Copyright 2013 Netflix, Inc. - * - * 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 rx.operators; - -import java.util.concurrent.TimeUnit; - -import rx.Scheduler; -import rx.Subscription; -import rx.util.functions.Action0; -import rx.util.functions.Func2; - -/** - * Common utility functions for testing operator implementations. - */ -/* package */class OperatorTester { - /* - * This is purposefully package-only so it does not leak into the public API outside of this package. - * - * This package is implementation details and not part of the Javadocs and thus can change without breaking backwards compatibility. - * - * benjchristensen => I'm procrastinating the decision of where and how these types of classes (see rx.subjects.UnsubscribeTester) should exist. - * If they are only for internal implementations then I don't want them as part of the API. - * If they are truly useful for everyone to use then an "rx.testing" package may make sense. - */ - - private OperatorTester() { - } - - public static class UnitTest { - - /** - * Used for mocking of Schedulers since many Scheduler implementations are static/final. - * - * @param underlying - * @return - */ - public static Scheduler forwardingScheduler(Scheduler underlying) { - return new ForwardingScheduler(underlying); - } - - public static class ForwardingScheduler extends Scheduler { - private final Scheduler underlying; - - public ForwardingScheduler(Scheduler underlying) { - this.underlying = underlying; - } - - @Override - public Subscription schedule(Action0 action) { - return underlying.schedule(action); - } - - @Override - public Subscription schedule(T state, Func2 action) { - return underlying.schedule(state, action); - } - - @Override - public Subscription schedule(Action0 action, long dueTime, TimeUnit unit) { - return underlying.schedule(action, dueTime, unit); - } - - @Override - public Subscription schedule(T state, Func2 action, long dueTime, TimeUnit unit) { - return underlying.schedule(state, action, dueTime, unit); - } - - @Override - public Subscription schedulePeriodically(Action0 action, long initialDelay, long period, TimeUnit unit) { - return underlying.schedulePeriodically(action, initialDelay, period, unit); - } - - @Override - public Subscription schedulePeriodically(T state, Func2 action, long initialDelay, long period, TimeUnit unit) { - return underlying.schedulePeriodically(state, action, initialDelay, period, unit); - } - - @Override - public long now() { - return underlying.now(); - } - } - } -} \ No newline at end of file diff --git a/rxjava-core/src/main/java/rx/operators/SafeObservableSubscription.java b/rxjava-core/src/main/java/rx/operators/SafeObservableSubscription.java index a94f658708..69e22def56 100644 --- a/rxjava-core/src/main/java/rx/operators/SafeObservableSubscription.java +++ b/rxjava-core/src/main/java/rx/operators/SafeObservableSubscription.java @@ -15,14 +15,10 @@ */ package rx.operators; -import static org.mockito.Mockito.*; +import rx.Subscription; import java.util.concurrent.atomic.AtomicReference; -import org.junit.Test; - -import rx.Subscription; - /** * Thread-safe wrapper around Observable Subscription that ensures unsubscribe can be called only once. *

@@ -82,15 +78,4 @@ public void unsubscribe() { public boolean isUnsubscribed() { return actualSubscription.get() == UNSUBSCRIBED; } - - public static class UnitTest { - @Test - public void testWrapAfterUnsubscribe() { - SafeObservableSubscription atomicObservableSubscription = new SafeObservableSubscription(); - atomicObservableSubscription.unsubscribe(); - Subscription innerSubscription = mock(Subscription.class); - atomicObservableSubscription.wrap(innerSubscription); - verify(innerSubscription, times(1)).unsubscribe(); - } - } } diff --git a/rxjava-core/src/main/java/rx/operators/SynchronizedObserver.java b/rxjava-core/src/main/java/rx/operators/SynchronizedObserver.java index 9a6b14d09f..c8b4fac812 100644 --- a/rxjava-core/src/main/java/rx/operators/SynchronizedObserver.java +++ b/rxjava-core/src/main/java/rx/operators/SynchronizedObserver.java @@ -15,27 +15,7 @@ */ package rx.operators; -import static org.junit.Assert.*; -import static org.mockito.Matchers.*; -import static org.mockito.Mockito.*; - -import java.util.Random; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.Future; -import java.util.concurrent.LinkedBlockingQueue; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicInteger; - -import org.junit.Before; -import org.junit.Test; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; - -import rx.Observable; -import rx.Observable.OnSubscribeFunc; import rx.Observer; -import rx.Subscription; /** * A thread-safe Observer for transitioning states in operators. @@ -138,740 +118,4 @@ public void onCompleted() { finished = true; } } - - public static class UnitTest { - @Mock - Observer aObserver; - - @Before - public void before() { - MockitoAnnotations.initMocks(this); - } - - @Test - public void testSingleThreadedBasic() { - Subscription s = mock(Subscription.class); - TestSingleThreadedObservable onSubscribe = new TestSingleThreadedObservable(s, "one", "two", "three"); - Observable w = Observable.create(onSubscribe); - - SafeObservableSubscription as = new SafeObservableSubscription(s); - SynchronizedObserver aw = new SynchronizedObserver(aObserver, as); - - w.subscribe(aw); - onSubscribe.waitToFinish(); - - verify(aObserver, times(1)).onNext("one"); - verify(aObserver, times(1)).onNext("two"); - verify(aObserver, times(1)).onNext("three"); - verify(aObserver, never()).onError(any(Throwable.class)); - verify(aObserver, times(1)).onCompleted(); - // non-deterministic because unsubscribe happens after 'waitToFinish' releases - // so commenting out for now as this is not a critical thing to test here - // verify(s, times(1)).unsubscribe(); - } - - @Test - public void testMultiThreadedBasic() { - Subscription s = mock(Subscription.class); - TestMultiThreadedObservable onSubscribe = new TestMultiThreadedObservable(s, "one", "two", "three"); - Observable w = Observable.create(onSubscribe); - - SafeObservableSubscription as = new SafeObservableSubscription(s); - BusyObserver busyObserver = new BusyObserver(); - SynchronizedObserver aw = new SynchronizedObserver(busyObserver, as); - - w.subscribe(aw); - onSubscribe.waitToFinish(); - - assertEquals(3, busyObserver.onNextCount.get()); - assertFalse(busyObserver.onError); - assertTrue(busyObserver.onCompleted); - // non-deterministic because unsubscribe happens after 'waitToFinish' releases - // so commenting out for now as this is not a critical thing to test here - // verify(s, times(1)).unsubscribe(); - - // we can have concurrency ... - assertTrue(onSubscribe.maxConcurrentThreads.get() > 1); - // ... but the onNext execution should be single threaded - assertEquals(1, busyObserver.maxConcurrentThreads.get()); - } - - @Test - public void testMultiThreadedBasicWithLock() { - Subscription s = mock(Subscription.class); - TestMultiThreadedObservable onSubscribe = new TestMultiThreadedObservable(s, "one", "two", "three"); - Observable w = Observable.create(onSubscribe); - - SafeObservableSubscription as = new SafeObservableSubscription(s); - BusyObserver busyObserver = new BusyObserver(); - - Object lock = new Object(); - ExternalBusyThread externalBusyThread = new ExternalBusyThread(busyObserver, lock, 10, 100); - - SynchronizedObserver aw = new SynchronizedObserver(busyObserver, as, lock); - - externalBusyThread.start(); - - w.subscribe(aw); - onSubscribe.waitToFinish(); - - try { - externalBusyThread.join(10000); - assertFalse(externalBusyThread.isAlive()); - assertFalse(externalBusyThread.fail); - } catch (InterruptedException e) { - // ignore - } - - assertEquals(3, busyObserver.onNextCount.get()); - assertFalse(busyObserver.onError); - assertTrue(busyObserver.onCompleted); - // non-deterministic because unsubscribe happens after 'waitToFinish' releases - // so commenting out for now as this is not a critical thing to test here - // verify(s, times(1)).unsubscribe(); - - // we can have concurrency ... - assertTrue(onSubscribe.maxConcurrentThreads.get() > 1); - // ... but the onNext execution should be single threaded - assertEquals(1, busyObserver.maxConcurrentThreads.get()); - } - - @Test - public void testMultiThreadedWithNPE() { - Subscription s = mock(Subscription.class); - TestMultiThreadedObservable onSubscribe = new TestMultiThreadedObservable(s, "one", "two", "three", null); - Observable w = Observable.create(onSubscribe); - - SafeObservableSubscription as = new SafeObservableSubscription(s); - BusyObserver busyObserver = new BusyObserver(); - SynchronizedObserver aw = new SynchronizedObserver(busyObserver, as); - - w.subscribe(aw); - onSubscribe.waitToFinish(); - - System.out.println("maxConcurrentThreads: " + onSubscribe.maxConcurrentThreads.get()); - - // we can't know how many onNext calls will occur since they each run on a separate thread - // that depends on thread scheduling so 0, 1, 2 and 3 are all valid options - // assertEquals(3, busyObserver.onNextCount.get()); - assertTrue(busyObserver.onNextCount.get() < 4); - assertTrue(busyObserver.onError); - // no onCompleted because onError was invoked - assertFalse(busyObserver.onCompleted); - // non-deterministic because unsubscribe happens after 'waitToFinish' releases - // so commenting out for now as this is not a critical thing to test here - //verify(s, times(1)).unsubscribe(); - - // we can have concurrency ... - assertTrue(onSubscribe.maxConcurrentThreads.get() > 1); - // ... but the onNext execution should be single threaded - assertEquals(1, busyObserver.maxConcurrentThreads.get()); - } - - @Test - public void testMultiThreadedWithNPEAndLock() { - Subscription s = mock(Subscription.class); - TestMultiThreadedObservable onSubscribe = new TestMultiThreadedObservable(s, "one", "two", "three", null); - Observable w = Observable.create(onSubscribe); - - SafeObservableSubscription as = new SafeObservableSubscription(s); - BusyObserver busyObserver = new BusyObserver(); - - Object lock = new Object(); - ExternalBusyThread externalBusyThread = new ExternalBusyThread(busyObserver, lock, 10, 100); - - SynchronizedObserver aw = new SynchronizedObserver(busyObserver, as, lock); - - externalBusyThread.start(); - - w.subscribe(aw); - onSubscribe.waitToFinish(); - - try { - externalBusyThread.join(10000); - assertFalse(externalBusyThread.isAlive()); - assertFalse(externalBusyThread.fail); - } catch (InterruptedException e) { - // ignore - } - - System.out.println("maxConcurrentThreads: " + onSubscribe.maxConcurrentThreads.get()); - - // we can't know how many onNext calls will occur since they each run on a separate thread - // that depends on thread scheduling so 0, 1, 2 and 3 are all valid options - // assertEquals(3, busyObserver.onNextCount.get()); - assertTrue(busyObserver.onNextCount.get() < 4); - assertTrue(busyObserver.onError); - // no onCompleted because onError was invoked - assertFalse(busyObserver.onCompleted); - // non-deterministic because unsubscribe happens after 'waitToFinish' releases - // so commenting out for now as this is not a critical thing to test here - //verify(s, times(1)).unsubscribe(); - - // we can have concurrency ... - assertTrue(onSubscribe.maxConcurrentThreads.get() > 1); - // ... but the onNext execution should be single threaded - assertEquals(1, busyObserver.maxConcurrentThreads.get()); - } - - @Test - public void testMultiThreadedWithNPEinMiddle() { - Subscription s = mock(Subscription.class); - TestMultiThreadedObservable onSubscribe = new TestMultiThreadedObservable(s, "one", "two", "three", null, "four", "five", "six", "seven", "eight", "nine"); - Observable w = Observable.create(onSubscribe); - - SafeObservableSubscription as = new SafeObservableSubscription(s); - BusyObserver busyObserver = new BusyObserver(); - SynchronizedObserver aw = new SynchronizedObserver(busyObserver, as); - - w.subscribe(aw); - onSubscribe.waitToFinish(); - - System.out.println("maxConcurrentThreads: " + onSubscribe.maxConcurrentThreads.get()); - // this should not be the full number of items since the error should stop it before it completes all 9 - System.out.println("onNext count: " + busyObserver.onNextCount.get()); - assertTrue(busyObserver.onNextCount.get() < 9); - assertTrue(busyObserver.onError); - // no onCompleted because onError was invoked - assertFalse(busyObserver.onCompleted); - // non-deterministic because unsubscribe happens after 'waitToFinish' releases - // so commenting out for now as this is not a critical thing to test here - // verify(s, times(1)).unsubscribe(); - - // we can have concurrency ... - assertTrue(onSubscribe.maxConcurrentThreads.get() > 1); - // ... but the onNext execution should be single threaded - assertEquals(1, busyObserver.maxConcurrentThreads.get()); - } - - @Test - public void testMultiThreadedWithNPEinMiddleAndLock() { - Subscription s = mock(Subscription.class); - TestMultiThreadedObservable onSubscribe = new TestMultiThreadedObservable(s, "one", "two", "three", null, "four", "five", "six", "seven", "eight", "nine"); - Observable w = Observable.create(onSubscribe); - - SafeObservableSubscription as = new SafeObservableSubscription(s); - BusyObserver busyObserver = new BusyObserver(); - - Object lock = new Object(); - ExternalBusyThread externalBusyThread = new ExternalBusyThread(busyObserver, lock, 10, 100); - - SynchronizedObserver aw = new SynchronizedObserver(busyObserver, as, lock); - - externalBusyThread.start(); - - w.subscribe(aw); - onSubscribe.waitToFinish(); - - try { - externalBusyThread.join(10000); - assertFalse(externalBusyThread.isAlive()); - assertFalse(externalBusyThread.fail); - } catch (InterruptedException e) { - // ignore - } - - System.out.println("maxConcurrentThreads: " + onSubscribe.maxConcurrentThreads.get()); - // this should not be the full number of items since the error should stop it before it completes all 9 - System.out.println("onNext count: " + busyObserver.onNextCount.get()); - assertTrue(busyObserver.onNextCount.get() < 9); - assertTrue(busyObserver.onError); - // no onCompleted because onError was invoked - assertFalse(busyObserver.onCompleted); - // non-deterministic because unsubscribe happens after 'waitToFinish' releases - // so commenting out for now as this is not a critical thing to test here - // verify(s, times(1)).unsubscribe(); - - // we can have concurrency ... - assertTrue(onSubscribe.maxConcurrentThreads.get() > 1); - // ... but the onNext execution should be single threaded - assertEquals(1, busyObserver.maxConcurrentThreads.get()); - } - - /** - * A non-realistic use case that tries to expose thread-safety issues by throwing lots of out-of-order - * events on many threads. - * - * @param w - * @param tw - */ - @Test - public void runConcurrencyTest() { - ExecutorService tp = Executors.newFixedThreadPool(20); - try { - TestConcurrencyObserver tw = new TestConcurrencyObserver(); - SafeObservableSubscription s = new SafeObservableSubscription(); - SynchronizedObserver w = new SynchronizedObserver(tw, s); - - Future f1 = tp.submit(new OnNextThread(w, 12000)); - Future f2 = tp.submit(new OnNextThread(w, 5000)); - Future f3 = tp.submit(new OnNextThread(w, 75000)); - Future f4 = tp.submit(new OnNextThread(w, 13500)); - Future f5 = tp.submit(new OnNextThread(w, 22000)); - Future f6 = tp.submit(new OnNextThread(w, 15000)); - Future f7 = tp.submit(new OnNextThread(w, 7500)); - Future f8 = tp.submit(new OnNextThread(w, 23500)); - - Future f10 = tp.submit(new CompletionThread(w, TestConcurrencyObserverEvent.onCompleted, f1, f2, f3, f4)); - try { - Thread.sleep(1); - } catch (InterruptedException e) { - // ignore - } - Future f11 = tp.submit(new CompletionThread(w, TestConcurrencyObserverEvent.onCompleted, f4, f6, f7)); - Future f12 = tp.submit(new CompletionThread(w, TestConcurrencyObserverEvent.onCompleted, f4, f6, f7)); - Future f13 = tp.submit(new CompletionThread(w, TestConcurrencyObserverEvent.onCompleted, f4, f6, f7)); - Future f14 = tp.submit(new CompletionThread(w, TestConcurrencyObserverEvent.onCompleted, f4, f6, f7)); - // // the next 4 onError events should wait on same as f10 - Future f15 = tp.submit(new CompletionThread(w, TestConcurrencyObserverEvent.onError, f1, f2, f3, f4)); - Future f16 = tp.submit(new CompletionThread(w, TestConcurrencyObserverEvent.onError, f1, f2, f3, f4)); - Future f17 = tp.submit(new CompletionThread(w, TestConcurrencyObserverEvent.onError, f1, f2, f3, f4)); - Future f18 = tp.submit(new CompletionThread(w, TestConcurrencyObserverEvent.onError, f1, f2, f3, f4)); - - waitOnThreads(f1, f2, f3, f4, f5, f6, f7, f8, f10, f11, f12, f13, f14, f15, f16, f17, f18); - @SuppressWarnings("unused") - int numNextEvents = tw.assertEvents(null); // no check of type since we don't want to test barging results here, just interleaving behavior - // System.out.println("Number of events executed: " + numNextEvents); - } catch (Throwable e) { - fail("Concurrency test failed: " + e.getMessage()); - e.printStackTrace(); - } finally { - tp.shutdown(); - try { - tp.awaitTermination(5000, TimeUnit.MILLISECONDS); - } catch (InterruptedException e) { - e.printStackTrace(); - } - } - } - - private static void waitOnThreads(Future... futures) { - for (Future f : futures) { - try { - f.get(10, TimeUnit.SECONDS); - } catch (Throwable e) { - System.err.println("Failed while waiting on future."); - e.printStackTrace(); - } - } - } - - /** - * A thread that will pass data to onNext - */ - public static class OnNextThread implements Runnable { - - private final Observer Observer; - private final int numStringsToSend; - - OnNextThread(Observer Observer, int numStringsToSend) { - this.Observer = Observer; - this.numStringsToSend = numStringsToSend; - } - - @Override - public void run() { - for (int i = 0; i < numStringsToSend; i++) { - Observer.onNext("aString"); - } - } - } - - /** - * A thread that will call onError or onNext - */ - public static class CompletionThread implements Runnable { - - private final Observer Observer; - private final TestConcurrencyObserverEvent event; - private final Future[] waitOnThese; - - CompletionThread(Observer Observer, TestConcurrencyObserverEvent event, Future... waitOnThese) { - this.Observer = Observer; - this.event = event; - this.waitOnThese = waitOnThese; - } - - @Override - public void run() { - /* if we have 'waitOnThese' futures, we'll wait on them before proceeding */ - if (waitOnThese != null) { - for (Future f : waitOnThese) { - try { - f.get(); - } catch (Throwable e) { - System.err.println("Error while waiting on future in CompletionThread"); - } - } - } - - /* send the event */ - if (event == TestConcurrencyObserverEvent.onError) { - Observer.onError(new RuntimeException("mocked exception")); - } else if (event == TestConcurrencyObserverEvent.onCompleted) { - Observer.onCompleted(); - - } else { - throw new IllegalArgumentException("Expecting either onError or onCompleted"); - } - } - } - - private static enum TestConcurrencyObserverEvent { - onCompleted, onError, onNext - } - - private static class TestConcurrencyObserver implements Observer { - - /** used to store the order and number of events received */ - private final LinkedBlockingQueue events = new LinkedBlockingQueue(); - private final int waitTime; - - @SuppressWarnings("unused") - public TestConcurrencyObserver(int waitTimeInNext) { - this.waitTime = waitTimeInNext; - } - - public TestConcurrencyObserver() { - this.waitTime = 0; - } - - @Override - public void onCompleted() { - events.add(TestConcurrencyObserverEvent.onCompleted); - } - - @Override - public void onError(Throwable e) { - events.add(TestConcurrencyObserverEvent.onError); - } - - @Override - public void onNext(String args) { - events.add(TestConcurrencyObserverEvent.onNext); - // do some artificial work to make the thread scheduling/timing vary - int s = 0; - for (int i = 0; i < 20; i++) { - s += s * i; - } - - if (waitTime > 0) { - try { - Thread.sleep(waitTime); - } catch (InterruptedException e) { - // ignore - } - } - } - - /** - * Assert the order of events is correct and return the number of onNext executions. - * - * @param expectedEndingEvent - * @return int count of onNext calls - * @throws IllegalStateException - * If order of events was invalid. - */ - public int assertEvents(TestConcurrencyObserverEvent expectedEndingEvent) throws IllegalStateException { - int nextCount = 0; - boolean finished = false; - for (TestConcurrencyObserverEvent e : events) { - if (e == TestConcurrencyObserverEvent.onNext) { - if (finished) { - // already finished, we shouldn't get this again - throw new IllegalStateException("Received onNext but we're already finished."); - } - nextCount++; - } else if (e == TestConcurrencyObserverEvent.onError) { - if (finished) { - // already finished, we shouldn't get this again - throw new IllegalStateException("Received onError but we're already finished."); - } - if (expectedEndingEvent != null && TestConcurrencyObserverEvent.onError != expectedEndingEvent) { - throw new IllegalStateException("Received onError ending event but expected " + expectedEndingEvent); - } - finished = true; - } else if (e == TestConcurrencyObserverEvent.onCompleted) { - if (finished) { - // already finished, we shouldn't get this again - throw new IllegalStateException("Received onCompleted but we're already finished."); - } - if (expectedEndingEvent != null && TestConcurrencyObserverEvent.onCompleted != expectedEndingEvent) { - throw new IllegalStateException("Received onCompleted ending event but expected " + expectedEndingEvent); - } - finished = true; - } - } - - return nextCount; - } - - } - - /** - * This spawns a single thread for the subscribe execution - * - */ - private static class TestSingleThreadedObservable implements OnSubscribeFunc { - - final Subscription s; - final String[] values; - private Thread t = null; - - public TestSingleThreadedObservable(final Subscription s, final String... values) { - this.s = s; - this.values = values; - - } - - public Subscription onSubscribe(final Observer observer) { - System.out.println("TestSingleThreadedObservable subscribed to ..."); - t = new Thread(new Runnable() { - - @Override - public void run() { - try { - System.out.println("running TestSingleThreadedObservable thread"); - for (String s : values) { - System.out.println("TestSingleThreadedObservable onNext: " + s); - observer.onNext(s); - } - observer.onCompleted(); - } catch (Throwable e) { - throw new RuntimeException(e); - } - } - - }); - System.out.println("starting TestSingleThreadedObservable thread"); - t.start(); - System.out.println("done starting TestSingleThreadedObservable thread"); - return s; - } - - public void waitToFinish() { - try { - t.join(); - } catch (InterruptedException e) { - throw new RuntimeException(e); - } - } - - } - - /** - * This spawns a thread for the subscription, then a separate thread for each onNext call. - * - */ - private static class TestMultiThreadedObservable implements OnSubscribeFunc { - - final Subscription s; - final String[] values; - Thread t = null; - AtomicInteger threadsRunning = new AtomicInteger(); - AtomicInteger maxConcurrentThreads = new AtomicInteger(); - ExecutorService threadPool; - - public TestMultiThreadedObservable(Subscription s, String... values) { - this.s = s; - this.values = values; - this.threadPool = Executors.newCachedThreadPool(); - } - - @Override - public Subscription onSubscribe(final Observer observer) { - System.out.println("TestMultiThreadedObservable subscribed to ..."); - t = new Thread(new Runnable() { - - @Override - public void run() { - try { - System.out.println("running TestMultiThreadedObservable thread"); - for (final String s : values) { - threadPool.execute(new Runnable() { - - @Override - public void run() { - threadsRunning.incrementAndGet(); - try { - // perform onNext call - System.out.println("TestMultiThreadedObservable onNext: " + s); - if (s == null) { - // force an error - throw new NullPointerException(); - } - observer.onNext(s); - // capture 'maxThreads' - int concurrentThreads = threadsRunning.get(); - int maxThreads = maxConcurrentThreads.get(); - if (concurrentThreads > maxThreads) { - maxConcurrentThreads.compareAndSet(maxThreads, concurrentThreads); - } - } catch (Throwable e) { - observer.onError(e); - } finally { - threadsRunning.decrementAndGet(); - } - } - }); - } - // we are done spawning threads - threadPool.shutdown(); - } catch (Throwable e) { - throw new RuntimeException(e); - } - - // wait until all threads are done, then mark it as COMPLETED - try { - // wait for all the threads to finish - threadPool.awaitTermination(2, TimeUnit.SECONDS); - } catch (InterruptedException e) { - throw new RuntimeException(e); - } - observer.onCompleted(); - } - }); - System.out.println("starting TestMultiThreadedObservable thread"); - t.start(); - System.out.println("done starting TestMultiThreadedObservable thread"); - return s; - } - - public void waitToFinish() { - try { - t.join(); - } catch (InterruptedException e) { - throw new RuntimeException(e); - } - } - } - - private static class BusyObserver implements Observer { - volatile boolean onCompleted = false; - volatile boolean onError = false; - AtomicInteger onNextCount = new AtomicInteger(); - AtomicInteger threadsRunning = new AtomicInteger(); - AtomicInteger maxConcurrentThreads = new AtomicInteger(); - - @Override - public void onCompleted() { - threadsRunning.incrementAndGet(); - - System.out.println(">>> BusyObserver received onCompleted"); - onCompleted = true; - - int concurrentThreads = threadsRunning.get(); - int maxThreads = maxConcurrentThreads.get(); - if (concurrentThreads > maxThreads) { - maxConcurrentThreads.compareAndSet(maxThreads, concurrentThreads); - } - threadsRunning.decrementAndGet(); - } - - @Override - public void onError(Throwable e) { - threadsRunning.incrementAndGet(); - - System.out.println(">>> BusyObserver received onError: " + e.getMessage()); - onError = true; - - int concurrentThreads = threadsRunning.get(); - int maxThreads = maxConcurrentThreads.get(); - if (concurrentThreads > maxThreads) { - maxConcurrentThreads.compareAndSet(maxThreads, concurrentThreads); - } - threadsRunning.decrementAndGet(); - } - - @Override - public void onNext(String args) { - threadsRunning.incrementAndGet(); - try { - onNextCount.incrementAndGet(); - System.out.println(">>> BusyObserver received onNext: " + args); - try { - // simulate doing something computational - Thread.sleep(200); - } catch (InterruptedException e) { - e.printStackTrace(); - } - } finally { - // capture 'maxThreads' - int concurrentThreads = threadsRunning.get(); - int maxThreads = maxConcurrentThreads.get(); - if (concurrentThreads > maxThreads) { - maxConcurrentThreads.compareAndSet(maxThreads, concurrentThreads); - } - threadsRunning.decrementAndGet(); - } - } - - } - - private static class ExternalBusyThread extends Thread { - - private BusyObserver observer; - private Object lock; - private int lockTimes; - private int waitTime; - public volatile boolean fail; - - public ExternalBusyThread(BusyObserver observer, Object lock, int lockTimes, int waitTime) { - this.observer = observer; - this.lock = lock; - this.lockTimes = lockTimes; - this.waitTime = waitTime; - this.fail = false; - } - - @Override - public void run() { - Random r = new Random(); - for (int i = 0; i < lockTimes; i++) { - synchronized (lock) { - int oldOnNextCount = observer.onNextCount.get(); - boolean oldOnCompleted = observer.onCompleted; - boolean oldOnError = observer.onError; - try { - Thread.sleep(r.nextInt(waitTime)); - } catch (InterruptedException e) { - // ignore - } - // Since we own the lock, onNextCount, onCompleted and - // onError must not be changed. - int newOnNextCount = observer.onNextCount.get(); - boolean newOnCompleted = observer.onCompleted; - boolean newOnError = observer.onError; - if (oldOnNextCount != newOnNextCount) { - System.out.println(">>> ExternalBusyThread received different onNextCount: " - + oldOnNextCount - + " -> " - + newOnNextCount); - fail = true; - break; - } - if (oldOnCompleted != newOnCompleted) { - System.out.println(">>> ExternalBusyThread received different onCompleted: " - + oldOnCompleted - + " -> " - + newOnCompleted); - fail = true; - break; - } - if (oldOnError != newOnError) { - System.out.println(">>> ExternalBusyThread received different onError: " - + oldOnError - + " -> " - + newOnError); - fail = true; - break; - } - } - } - } - - } - - } - } \ No newline at end of file diff --git a/rxjava-core/src/main/java/rx/plugins/RxJavaPlugins.java b/rxjava-core/src/main/java/rx/plugins/RxJavaPlugins.java index e27c343815..1e049732ff 100644 --- a/rxjava-core/src/main/java/rx/plugins/RxJavaPlugins.java +++ b/rxjava-core/src/main/java/rx/plugins/RxJavaPlugins.java @@ -15,12 +15,8 @@ */ package rx.plugins; -import static org.junit.Assert.*; - import java.util.concurrent.atomic.AtomicReference; -import org.junit.Test; - /** * Registry for plugin implementations that allows global override and handles the retrieval of correct implementation based on order of precedence: *

    @@ -36,7 +32,7 @@ public class RxJavaPlugins { private final AtomicReference errorHandler = new AtomicReference(); private final AtomicReference observableExecutionHook = new AtomicReference(); - private RxJavaPlugins() { + RxJavaPlugins() { } @@ -148,77 +144,4 @@ private static Object getPluginImplementationViaProperty(Class pluginClass) { return null; } } - - public static class UnitTest { - - @Test - public void testErrorHandlerDefaultImpl() { - RxJavaErrorHandler impl = new RxJavaPlugins().getErrorHandler(); - assertTrue(impl instanceof RxJavaErrorHandlerDefault); - } - - @Test - public void testErrorHandlerViaRegisterMethod() { - RxJavaPlugins p = new RxJavaPlugins(); - p.registerErrorHandler(new RxJavaErrorHandlerTestImpl()); - RxJavaErrorHandler impl = p.getErrorHandler(); - assertTrue(impl instanceof RxJavaErrorHandlerTestImpl); - } - - @Test - public void testErrorHandlerViaProperty() { - try { - RxJavaPlugins p = new RxJavaPlugins(); - String fullClass = getFullClassNameForTestClass(RxJavaErrorHandlerTestImpl.class); - System.setProperty("rxjava.plugin.RxJavaErrorHandler.implementation", fullClass); - RxJavaErrorHandler impl = p.getErrorHandler(); - assertTrue(impl instanceof RxJavaErrorHandlerTestImpl); - } finally { - System.clearProperty("rxjava.plugin.RxJavaErrorHandler.implementation"); - } - } - - // inside UnitTest so it is stripped from Javadocs - public static class RxJavaErrorHandlerTestImpl extends RxJavaErrorHandler { - // just use defaults - } - - @Test - public void testObservableExecutionHookDefaultImpl() { - RxJavaPlugins p = new RxJavaPlugins(); - RxJavaObservableExecutionHook impl = p.getObservableExecutionHook(); - assertTrue(impl instanceof RxJavaObservableExecutionHookDefault); - } - - @Test - public void testObservableExecutionHookViaRegisterMethod() { - RxJavaPlugins p = new RxJavaPlugins(); - p.registerObservableExecutionHook(new RxJavaObservableExecutionHookTestImpl()); - RxJavaObservableExecutionHook impl = p.getObservableExecutionHook(); - assertTrue(impl instanceof RxJavaObservableExecutionHookTestImpl); - } - - @Test - public void testObservableExecutionHookViaProperty() { - try { - RxJavaPlugins p = new RxJavaPlugins(); - String fullClass = getFullClassNameForTestClass(RxJavaObservableExecutionHookTestImpl.class); - System.setProperty("rxjava.plugin.RxJavaObservableExecutionHook.implementation", fullClass); - RxJavaObservableExecutionHook impl = p.getObservableExecutionHook(); - assertTrue(impl instanceof RxJavaObservableExecutionHookTestImpl); - } finally { - System.clearProperty("rxjava.plugin.RxJavaObservableExecutionHook.implementation"); - } - } - - // inside UnitTest so it is stripped from Javadocs - public static class RxJavaObservableExecutionHookTestImpl extends RxJavaObservableExecutionHook { - // just use defaults - } - - private static String getFullClassNameForTestClass(Class cls) { - return RxJavaPlugins.class.getPackage().getName() + "." + RxJavaPlugins.class.getSimpleName() + "$UnitTest$" + cls.getSimpleName(); - } - } - } diff --git a/rxjava-core/src/main/java/rx/subjects/AsyncSubject.java b/rxjava-core/src/main/java/rx/subjects/AsyncSubject.java index f50ff21322..7e4357c696 100644 --- a/rxjava-core/src/main/java/rx/subjects/AsyncSubject.java +++ b/rxjava-core/src/main/java/rx/subjects/AsyncSubject.java @@ -15,20 +15,12 @@ */ package rx.subjects; -import static org.mockito.Matchers.*; -import static org.mockito.Mockito.*; - -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.atomic.AtomicReference; - -import org.junit.Test; -import org.mockito.Mockito; - import rx.Observer; import rx.Subscription; import rx.operators.SafeObservableSubscription; -import rx.util.functions.Action1; -import rx.util.functions.Func0; + +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.atomic.AtomicReference; /** * Subject that publishes only the last event to each {@link Observer} that has subscribed when the @@ -123,135 +115,4 @@ public void onError(Throwable e) { public void onNext(T args) { currentValue.set(args); } - - public static class UnitTest { - - private final Throwable testException = new Throwable(); - - @Test - public void testNeverCompleted() { - AsyncSubject subject = AsyncSubject.create(); - - @SuppressWarnings("unchecked") - Observer aObserver = mock(Observer.class); - subject.subscribe(aObserver); - - subject.onNext("one"); - subject.onNext("two"); - subject.onNext("three"); - - assertNeverCompletedObserver(aObserver); - } - - private void assertNeverCompletedObserver(Observer aObserver) - { - verify(aObserver, Mockito.never()).onNext(anyString()); - verify(aObserver, Mockito.never()).onError(testException); - verify(aObserver, Mockito.never()).onCompleted(); - } - - @Test - public void testCompleted() { - AsyncSubject subject = AsyncSubject.create(); - - @SuppressWarnings("unchecked") - Observer aObserver = mock(Observer.class); - subject.subscribe(aObserver); - - subject.onNext("one"); - subject.onNext("two"); - subject.onNext("three"); - subject.onCompleted(); - - assertCompletedObserver(aObserver); - } - - private void assertCompletedObserver(Observer aObserver) - { - verify(aObserver, times(1)).onNext("three"); - verify(aObserver, Mockito.never()).onError(any(Throwable.class)); - verify(aObserver, times(1)).onCompleted(); - } - - @Test - public void testError() { - AsyncSubject subject = AsyncSubject.create(); - - @SuppressWarnings("unchecked") - Observer aObserver = mock(Observer.class); - subject.subscribe(aObserver); - - subject.onNext("one"); - subject.onNext("two"); - subject.onNext("three"); - subject.onError(testException); - subject.onNext("four"); - subject.onError(new Throwable()); - subject.onCompleted(); - - assertErrorObserver(aObserver); - } - - private void assertErrorObserver(Observer aObserver) - { - verify(aObserver, Mockito.never()).onNext(anyString()); - verify(aObserver, times(1)).onError(testException); - verify(aObserver, Mockito.never()).onCompleted(); - } - - @Test - public void testUnsubscribeBeforeCompleted() { - AsyncSubject subject = AsyncSubject.create(); - - @SuppressWarnings("unchecked") - Observer aObserver = mock(Observer.class); - Subscription subscription = subject.subscribe(aObserver); - - subject.onNext("one"); - subject.onNext("two"); - - subscription.unsubscribe(); - assertNoOnNextEventsReceived(aObserver); - - subject.onNext("three"); - subject.onCompleted(); - - assertNoOnNextEventsReceived(aObserver); - } - - private void assertNoOnNextEventsReceived(Observer aObserver) - { - verify(aObserver, Mockito.never()).onNext(anyString()); - verify(aObserver, Mockito.never()).onError(any(Throwable.class)); - verify(aObserver, Mockito.never()).onCompleted(); - } - - @Test - public void testUnsubscribe() - { - UnsubscribeTester.test(new Func0>() - { - @Override - public AsyncSubject call() - { - return AsyncSubject.create(); - } - }, new Action1>() - { - @Override - public void call(AsyncSubject DefaultSubject) - { - DefaultSubject.onCompleted(); - } - }, new Action1>() - { - @Override - public void call(AsyncSubject DefaultSubject) - { - DefaultSubject.onError(new Throwable()); - } - }, - null); - } - } } diff --git a/rxjava-core/src/main/java/rx/subjects/BehaviorSubject.java b/rxjava-core/src/main/java/rx/subjects/BehaviorSubject.java index 1efe3571bd..5ea3c52146 100644 --- a/rxjava-core/src/main/java/rx/subjects/BehaviorSubject.java +++ b/rxjava-core/src/main/java/rx/subjects/BehaviorSubject.java @@ -15,19 +15,12 @@ */ package rx.subjects; -import static org.mockito.Mockito.*; - -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.atomic.AtomicReference; - -import org.junit.Test; -import org.mockito.Mockito; - import rx.Observer; import rx.Subscription; import rx.operators.SafeObservableSubscription; -import rx.util.functions.Action1; -import rx.util.functions.Func0; + +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.atomic.AtomicReference; /** * Subject that publishes the most recent and all subsequent events to each subscribed {@link Observer}. @@ -127,137 +120,4 @@ public void onNext(T args) { observer.onNext(args); } } - - public static class UnitTest { - - private final Throwable testException = new Throwable(); - - @Test - public void testThatObserverReceivesDefaultValueIfNothingWasPublished() { - BehaviorSubject subject = BehaviorSubject.createWithDefaultValue("default"); - - @SuppressWarnings("unchecked") - Observer aObserver = mock(Observer.class); - subject.subscribe(aObserver); - - subject.onNext("one"); - subject.onNext("two"); - subject.onNext("three"); - - assertReceivedAllEvents(aObserver); - } - - private void assertReceivedAllEvents(Observer aObserver) { - verify(aObserver, times(1)).onNext("default"); - verify(aObserver, times(1)).onNext("one"); - verify(aObserver, times(1)).onNext("two"); - verify(aObserver, times(1)).onNext("three"); - verify(aObserver, Mockito.never()).onError(testException); - verify(aObserver, Mockito.never()).onCompleted(); - } - - @Test - public void testThatObserverDoesNotReceiveDefaultValueIfSomethingWasPublished() { - BehaviorSubject subject = BehaviorSubject.createWithDefaultValue("default"); - - subject.onNext("one"); - - @SuppressWarnings("unchecked") - Observer aObserver = mock(Observer.class); - subject.subscribe(aObserver); - - subject.onNext("two"); - subject.onNext("three"); - - assertDidNotReceiveTheDefaultValue(aObserver); - } - - private void assertDidNotReceiveTheDefaultValue(Observer aObserver) { - verify(aObserver, Mockito.never()).onNext("default"); - verify(aObserver, times(1)).onNext("one"); - verify(aObserver, times(1)).onNext("two"); - verify(aObserver, times(1)).onNext("three"); - verify(aObserver, Mockito.never()).onError(testException); - verify(aObserver, Mockito.never()).onCompleted(); - } - - @Test - public void testCompleted() { - BehaviorSubject subject = BehaviorSubject.createWithDefaultValue("default"); - - @SuppressWarnings("unchecked") - Observer aObserver = mock(Observer.class); - subject.subscribe(aObserver); - - subject.onNext("one"); - subject.onCompleted(); - - assertCompletedObserver(aObserver); - } - - private void assertCompletedObserver(Observer aObserver) - { - verify(aObserver, times(1)).onNext("default"); - verify(aObserver, times(1)).onNext("one"); - verify(aObserver, Mockito.never()).onError(any(Throwable.class)); - verify(aObserver, times(1)).onCompleted(); - } - - @Test - public void testCompletedAfterError() { - BehaviorSubject subject = BehaviorSubject.createWithDefaultValue("default"); - - @SuppressWarnings("unchecked") - Observer aObserver = mock(Observer.class); - subject.subscribe(aObserver); - - subject.onNext("one"); - subject.onError(testException); - subject.onNext("two"); - subject.onCompleted(); - - assertErrorObserver(aObserver); - } - - private void assertErrorObserver(Observer aObserver) - { - verify(aObserver, times(1)).onNext("default"); - verify(aObserver, times(1)).onNext("one"); - verify(aObserver, times(1)).onError(testException); - } - - @Test - public void testUnsubscribe() - { - UnsubscribeTester.test(new Func0>() - { - @Override - public BehaviorSubject call() - { - return BehaviorSubject.createWithDefaultValue("default"); - } - }, new Action1>() - { - @Override - public void call(BehaviorSubject DefaultSubject) - { - DefaultSubject.onCompleted(); - } - }, new Action1>() - { - @Override - public void call(BehaviorSubject DefaultSubject) - { - DefaultSubject.onError(new Throwable()); - } - }, new Action1>() - { - @Override - public void call(BehaviorSubject DefaultSubject) - { - DefaultSubject.onNext("one"); - } - }); - } - } } diff --git a/rxjava-core/src/main/java/rx/subjects/PublishSubject.java b/rxjava-core/src/main/java/rx/subjects/PublishSubject.java index 5588dd485b..ca248ea231 100644 --- a/rxjava-core/src/main/java/rx/subjects/PublishSubject.java +++ b/rxjava-core/src/main/java/rx/subjects/PublishSubject.java @@ -15,32 +15,13 @@ */ package rx.subjects; -import static org.junit.Assert.*; -import static org.mockito.Mockito.*; +import rx.Observer; +import rx.Subscription; +import rx.operators.SafeObservableSubscription; import java.util.ArrayList; import java.util.Collection; -import java.util.List; import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.atomic.AtomicBoolean; -import java.util.concurrent.atomic.AtomicInteger; -import java.util.concurrent.atomic.AtomicReference; - -import junit.framework.Assert; - -import org.junit.Test; -import org.mockito.InOrder; -import org.mockito.Mockito; - -import rx.Notification; -import rx.Observable; -import rx.Observer; -import rx.Subscription; -import rx.operators.SafeObservableSubscription; -import rx.subscriptions.Subscriptions; -import rx.util.functions.Action1; -import rx.util.functions.Func0; -import rx.util.functions.Func1; /** * Subject that, once and {@link Observer} has subscribed, publishes all subsequent events to the subscriber. @@ -136,356 +117,4 @@ public void onNext(T args) { private Collection> snapshotOfValues() { return new ArrayList>(observers.values()); } - - public static class UnitTest { - @Test - public void test() { - PublishSubject subject = PublishSubject.create(); - final AtomicReference>> actualRef = new AtomicReference>>(); - - Observable>> wNotificationsList = subject.materialize().toList(); - wNotificationsList.subscribe(new Action1>>() { - @Override - public void call(List> actual) { - actualRef.set(actual); - } - }); - - Subscription sub = Observable.create(new OnSubscribeFunc() { - @Override - public Subscription onSubscribe(final Observer observer) { - final AtomicBoolean stop = new AtomicBoolean(false); - new Thread() { - @Override - public void run() { - int i = 1; - while (!stop.get()) { - observer.onNext(i++); - } - observer.onCompleted(); - } - }.start(); - return new Subscription() { - @Override - public void unsubscribe() { - stop.set(true); - } - }; - } - }).subscribe(subject); - // the subject has received an onComplete from the first subscribe because - // it is synchronous and the next subscribe won't do anything. - Observable.from(-1, -2, -3).subscribe(subject); - - List> expected = new ArrayList>(); - expected.add(new Notification(-1)); - expected.add(new Notification(-2)); - expected.add(new Notification(-3)); - expected.add(new Notification()); - Assert.assertTrue(actualRef.get().containsAll(expected)); - - sub.unsubscribe(); - } - - private final Throwable testException = new Throwable(); - - @Test - public void testCompleted() { - PublishSubject subject = PublishSubject.create(); - - @SuppressWarnings("unchecked") - Observer aObserver = mock(Observer.class); - subject.subscribe(aObserver); - - subject.onNext("one"); - subject.onNext("two"); - subject.onNext("three"); - subject.onCompleted(); - - @SuppressWarnings("unchecked") - Observer anotherObserver = mock(Observer.class); - subject.subscribe(anotherObserver); - - subject.onNext("four"); - subject.onCompleted(); - subject.onError(new Throwable()); - - assertCompletedObserver(aObserver); - // todo bug? assertNeverObserver(anotherObserver); - } - - private void assertCompletedObserver(Observer aObserver) - { - verify(aObserver, times(1)).onNext("one"); - verify(aObserver, times(1)).onNext("two"); - verify(aObserver, times(1)).onNext("three"); - verify(aObserver, Mockito.never()).onError(any(Throwable.class)); - verify(aObserver, times(1)).onCompleted(); - } - - @Test - public void testError() { - PublishSubject subject = PublishSubject.create(); - - @SuppressWarnings("unchecked") - Observer aObserver = mock(Observer.class); - subject.subscribe(aObserver); - - subject.onNext("one"); - subject.onNext("two"); - subject.onNext("three"); - subject.onError(testException); - - @SuppressWarnings("unchecked") - Observer anotherObserver = mock(Observer.class); - subject.subscribe(anotherObserver); - - subject.onNext("four"); - subject.onError(new Throwable()); - subject.onCompleted(); - - assertErrorObserver(aObserver); - // todo bug? assertNeverObserver(anotherObserver); - } - - private void assertErrorObserver(Observer aObserver) - { - verify(aObserver, times(1)).onNext("one"); - verify(aObserver, times(1)).onNext("two"); - verify(aObserver, times(1)).onNext("three"); - verify(aObserver, times(1)).onError(testException); - verify(aObserver, Mockito.never()).onCompleted(); - } - - @Test - public void testSubscribeMidSequence() { - PublishSubject subject = PublishSubject.create(); - - @SuppressWarnings("unchecked") - Observer aObserver = mock(Observer.class); - subject.subscribe(aObserver); - - subject.onNext("one"); - subject.onNext("two"); - - assertObservedUntilTwo(aObserver); - - @SuppressWarnings("unchecked") - Observer anotherObserver = mock(Observer.class); - subject.subscribe(anotherObserver); - - subject.onNext("three"); - subject.onCompleted(); - - assertCompletedObserver(aObserver); - assertCompletedStartingWithThreeObserver(anotherObserver); - } - - private void assertCompletedStartingWithThreeObserver(Observer aObserver) - { - verify(aObserver, Mockito.never()).onNext("one"); - verify(aObserver, Mockito.never()).onNext("two"); - verify(aObserver, times(1)).onNext("three"); - verify(aObserver, Mockito.never()).onError(any(Throwable.class)); - verify(aObserver, times(1)).onCompleted(); - } - - @Test - public void testUnsubscribeFirstObserver() { - PublishSubject subject = PublishSubject.create(); - - @SuppressWarnings("unchecked") - Observer aObserver = mock(Observer.class); - Subscription subscription = subject.subscribe(aObserver); - - subject.onNext("one"); - subject.onNext("two"); - - subscription.unsubscribe(); - assertObservedUntilTwo(aObserver); - - @SuppressWarnings("unchecked") - Observer anotherObserver = mock(Observer.class); - subject.subscribe(anotherObserver); - - subject.onNext("three"); - subject.onCompleted(); - - assertObservedUntilTwo(aObserver); - assertCompletedStartingWithThreeObserver(anotherObserver); - } - - private void assertObservedUntilTwo(Observer aObserver) - { - verify(aObserver, times(1)).onNext("one"); - verify(aObserver, times(1)).onNext("two"); - verify(aObserver, Mockito.never()).onNext("three"); - verify(aObserver, Mockito.never()).onError(any(Throwable.class)); - verify(aObserver, Mockito.never()).onCompleted(); - } - - @Test - public void testUnsubscribe() - { - UnsubscribeTester.test(new Func0>() - { - @Override - public PublishSubject call() - { - return PublishSubject.create(); - } - }, new Action1>() - { - @Override - public void call(PublishSubject DefaultSubject) - { - DefaultSubject.onCompleted(); - } - }, new Action1>() - { - @Override - public void call(PublishSubject DefaultSubject) - { - DefaultSubject.onError(new Throwable()); - } - }, new Action1>() - { - @Override - public void call(PublishSubject DefaultSubject) - { - DefaultSubject.onNext("one"); - } - }); - } - - @Test - public void testNestedSubscribe() { - final PublishSubject s = PublishSubject.create(); - - final AtomicInteger countParent = new AtomicInteger(); - final AtomicInteger countChildren = new AtomicInteger(); - final AtomicInteger countTotal = new AtomicInteger(); - - final ArrayList list = new ArrayList(); - - s.mapMany(new Func1>() { - - @Override - public Observable call(final Integer v) { - countParent.incrementAndGet(); - - // then subscribe to subject again (it will not receive the previous value) - return s.map(new Func1() { - - @Override - public String call(Integer v2) { - countChildren.incrementAndGet(); - return "Parent: " + v + " Child: " + v2; - } - - }); - } - - }).subscribe(new Action1() { - - @Override - public void call(String v) { - countTotal.incrementAndGet(); - list.add(v); - } - - }); - - for (int i = 0; i < 10; i++) { - s.onNext(i); - } - s.onCompleted(); - - // System.out.println("countParent: " + countParent.get()); - // System.out.println("countChildren: " + countChildren.get()); - // System.out.println("countTotal: " + countTotal.get()); - - // 9+8+7+6+5+4+3+2+1+0 == 45 - assertEquals(45, list.size()); - } - - /** - * Should be able to unsubscribe all Observers, have it stop emitting, then subscribe new ones and it start emitting again. - */ - @Test - public void testReSubscribe() { - final PublishSubject ps = PublishSubject.create(); - - Observer o1 = mock(Observer.class); - Subscription s1 = ps.subscribe(o1); - - // emit - ps.onNext(1); - - // validate we got it - InOrder inOrder1 = inOrder(o1); - inOrder1.verify(o1, times(1)).onNext(1); - inOrder1.verifyNoMoreInteractions(); - - // unsubscribe - s1.unsubscribe(); - - // emit again but nothing will be there to receive it - ps.onNext(2); - - Observer o2 = mock(Observer.class); - Subscription s2 = ps.subscribe(o2); - - // emit - ps.onNext(3); - - // validate we got it - InOrder inOrder2 = inOrder(o2); - inOrder2.verify(o2, times(1)).onNext(3); - inOrder2.verifyNoMoreInteractions(); - - s2.unsubscribe(); - } - - /** - * Even if subject received an onError/onCompleted, new subscriptions should be able to restart it. - */ - @Test - public void testReSubscribeAfterTerminalState() { - final PublishSubject ps = PublishSubject.create(); - - Observer o1 = mock(Observer.class); - Subscription s1 = ps.subscribe(o1); - - // emit - ps.onNext(1); - - // validate we got it - InOrder inOrder1 = inOrder(o1); - inOrder1.verify(o1, times(1)).onNext(1); - inOrder1.verifyNoMoreInteractions(); - - // unsubscribe - s1.unsubscribe(); - - ps.onCompleted(); - - // emit again but nothing will be there to receive it - ps.onNext(2); - - Observer o2 = mock(Observer.class); - Subscription s2 = ps.subscribe(o2); - - // emit - ps.onNext(3); - - // validate we got it - InOrder inOrder2 = inOrder(o2); - inOrder2.verify(o2, times(1)).onNext(3); - inOrder2.verifyNoMoreInteractions(); - - s2.unsubscribe(); - } - - } } diff --git a/rxjava-core/src/main/java/rx/subjects/ReplaySubject.java b/rxjava-core/src/main/java/rx/subjects/ReplaySubject.java index 3c106e30bc..e103e5fe3b 100644 --- a/rxjava-core/src/main/java/rx/subjects/ReplaySubject.java +++ b/rxjava-core/src/main/java/rx/subjects/ReplaySubject.java @@ -15,25 +15,13 @@ */ package rx.subjects; -import static org.mockito.Mockito.*; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import org.junit.Test; -import org.mockito.InOrder; -import org.mockito.Mockito; - import rx.Observer; import rx.Subscription; import rx.subscriptions.Subscriptions; -import rx.util.functions.Action1; -import rx.util.functions.Func0; import rx.util.functions.Func1; +import java.util.*; + /** * Subject that retains all events and will replay them to an {@link Observer} that subscribes. *

    @@ -178,172 +166,4 @@ public void onNext(T args) } } } - - public static class UnitTest { - - private final Throwable testException = new Throwable(); - - @SuppressWarnings("unchecked") - @Test - public void testCompleted() { - ReplaySubject subject = ReplaySubject.create(); - - Observer o1 = mock(Observer.class); - subject.subscribe(o1); - - subject.onNext("one"); - subject.onNext("two"); - subject.onNext("three"); - subject.onCompleted(); - - subject.onNext("four"); - subject.onCompleted(); - subject.onError(new Throwable()); - - assertCompletedObserver(o1); - - // assert that subscribing a 2nd time gets the same data - Observer o2 = mock(Observer.class); - subject.subscribe(o2); - assertCompletedObserver(o2); - } - - private void assertCompletedObserver(Observer aObserver) - { - InOrder inOrder = inOrder(aObserver); - - inOrder.verify(aObserver, times(1)).onNext("one"); - inOrder.verify(aObserver, times(1)).onNext("two"); - inOrder.verify(aObserver, times(1)).onNext("three"); - inOrder.verify(aObserver, Mockito.never()).onError(any(Throwable.class)); - inOrder.verify(aObserver, times(1)).onCompleted(); - inOrder.verifyNoMoreInteractions(); - } - - @SuppressWarnings("unchecked") - @Test - public void testError() { - ReplaySubject subject = ReplaySubject.create(); - - Observer aObserver = mock(Observer.class); - subject.subscribe(aObserver); - - subject.onNext("one"); - subject.onNext("two"); - subject.onNext("three"); - subject.onError(testException); - - subject.onNext("four"); - subject.onError(new Throwable()); - subject.onCompleted(); - - assertErrorObserver(aObserver); - - aObserver = mock(Observer.class); - subject.subscribe(aObserver); - assertErrorObserver(aObserver); - } - - private void assertErrorObserver(Observer aObserver) - { - verify(aObserver, times(1)).onNext("one"); - verify(aObserver, times(1)).onNext("two"); - verify(aObserver, times(1)).onNext("three"); - verify(aObserver, times(1)).onError(testException); - verify(aObserver, Mockito.never()).onCompleted(); - } - - @SuppressWarnings("unchecked") - @Test - public void testSubscribeMidSequence() { - ReplaySubject subject = ReplaySubject.create(); - - Observer aObserver = mock(Observer.class); - subject.subscribe(aObserver); - - subject.onNext("one"); - subject.onNext("two"); - - assertObservedUntilTwo(aObserver); - - Observer anotherObserver = mock(Observer.class); - subject.subscribe(anotherObserver); - assertObservedUntilTwo(anotherObserver); - - subject.onNext("three"); - subject.onCompleted(); - - assertCompletedObserver(aObserver); - assertCompletedObserver(anotherObserver); - } - - @SuppressWarnings("unchecked") - @Test - public void testUnsubscribeFirstObserver() { - ReplaySubject subject = ReplaySubject.create(); - - Observer aObserver = mock(Observer.class); - Subscription subscription = subject.subscribe(aObserver); - - subject.onNext("one"); - subject.onNext("two"); - - subscription.unsubscribe(); - assertObservedUntilTwo(aObserver); - - Observer anotherObserver = mock(Observer.class); - subject.subscribe(anotherObserver); - assertObservedUntilTwo(anotherObserver); - - subject.onNext("three"); - subject.onCompleted(); - - assertObservedUntilTwo(aObserver); - assertCompletedObserver(anotherObserver); - } - - private void assertObservedUntilTwo(Observer aObserver) - { - verify(aObserver, times(1)).onNext("one"); - verify(aObserver, times(1)).onNext("two"); - verify(aObserver, Mockito.never()).onNext("three"); - verify(aObserver, Mockito.never()).onError(any(Throwable.class)); - verify(aObserver, Mockito.never()).onCompleted(); - } - - @Test - public void testUnsubscribe() - { - UnsubscribeTester.test(new Func0>() - { - @Override - public ReplaySubject call() - { - return ReplaySubject.create(); - } - }, new Action1>() - { - @Override - public void call(ReplaySubject repeatSubject) - { - repeatSubject.onCompleted(); - } - }, new Action1>() - { - @Override - public void call(ReplaySubject repeatSubject) - { - repeatSubject.onError(new Throwable()); - } - }, new Action1>() - { - @Override - public void call(ReplaySubject repeatSubject) - { - repeatSubject.onNext("one"); - } - } - ); - } - } } diff --git a/rxjava-core/src/main/java/rx/subscriptions/CompositeSubscription.java b/rxjava-core/src/main/java/rx/subscriptions/CompositeSubscription.java index 6ca5c8a699..480da47178 100644 --- a/rxjava-core/src/main/java/rx/subscriptions/CompositeSubscription.java +++ b/rxjava-core/src/main/java/rx/subscriptions/CompositeSubscription.java @@ -15,19 +15,14 @@ */ package rx.subscriptions; -import static org.junit.Assert.*; +import rx.Subscription; +import rx.util.CompositeException; import java.util.ArrayList; import java.util.Collection; import java.util.List; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.atomic.AtomicBoolean; -import java.util.concurrent.atomic.AtomicInteger; - -import org.junit.Test; - -import rx.Subscription; -import rx.util.CompositeException; /** * Subscription that represents a group of Subscriptions that are unsubscribed together. @@ -91,65 +86,4 @@ public synchronized void unsubscribe() { } } } - - public static class UnitTest { - - @Test - public void testSuccess() { - final AtomicInteger counter = new AtomicInteger(); - CompositeSubscription s = new CompositeSubscription(); - s.add(new Subscription() { - - @Override - public void unsubscribe() { - counter.incrementAndGet(); - } - }); - - s.add(new Subscription() { - - @Override - public void unsubscribe() { - counter.incrementAndGet(); - } - }); - - s.unsubscribe(); - - assertEquals(2, counter.get()); - } - - @Test - public void testException() { - final AtomicInteger counter = new AtomicInteger(); - CompositeSubscription s = new CompositeSubscription(); - s.add(new Subscription() { - - @Override - public void unsubscribe() { - throw new RuntimeException("failed on first one"); - } - }); - - s.add(new Subscription() { - - @Override - public void unsubscribe() { - counter.incrementAndGet(); - } - }); - - try { - s.unsubscribe(); - fail("Expecting an exception"); - } catch (CompositeException e) { - // we expect this - assertEquals(1, e.getExceptions().size()); - } - - // we should still have unsubscribed to the second one - assertEquals(1, counter.get()); - } - } - } diff --git a/rxjava-core/src/main/java/rx/subscriptions/Subscriptions.java b/rxjava-core/src/main/java/rx/subscriptions/Subscriptions.java index 5febe4f46a..bb85ed7a15 100644 --- a/rxjava-core/src/main/java/rx/subscriptions/Subscriptions.java +++ b/rxjava-core/src/main/java/rx/subscriptions/Subscriptions.java @@ -15,18 +15,12 @@ */ package rx.subscriptions; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; - -import java.util.concurrent.Future; - -import org.junit.Test; - import rx.Subscription; import rx.operators.SafeObservableSubscription; import rx.util.functions.Action0; +import java.util.concurrent.Future; + /** * Helper methods and utilities for creating and working with {@link Subscription} objects */ @@ -129,15 +123,4 @@ public static CompositeSubscription create(Subscription... subscriptions) { public void unsubscribe() { } }; - - public static class UnitTest { - @Test - public void testUnsubscribeOnlyOnce() { - Action0 unsubscribe = mock(Action0.class); - Subscription subscription = create(unsubscribe); - subscription.unsubscribe(); - subscription.unsubscribe(); - verify(unsubscribe, times(1)).call(); - } - } } diff --git a/rxjava-core/src/main/java/rx/util/Range.java b/rxjava-core/src/main/java/rx/util/Range.java index c263c53471..5f7418b218 100644 --- a/rxjava-core/src/main/java/rx/util/Range.java +++ b/rxjava-core/src/main/java/rx/util/Range.java @@ -15,16 +15,9 @@ */ package rx.util; -import static org.junit.Assert.*; - -import java.util.ArrayList; -import java.util.Arrays; import java.util.Iterator; -import java.util.List; import java.util.NoSuchElementException; -import org.junit.Test; - public final class Range implements Iterable { private final int start; private final int end; @@ -79,46 +72,4 @@ public void remove() { public String toString() { return "Range (" + start + ", " + end + "), step " + step; } - - public static class UnitTest { - - @Test - public void testSimpleRange() { - assertEquals(Arrays.asList(1, 2, 3, 4), toList(Range.create(1, 5))); - } - - @Test - public void testRangeWithStep() { - assertEquals(Arrays.asList(1, 3, 5, 7, 9), toList(Range.createWithStep(1, 10, 2))); - } - - @Test - public void testRangeWithCount() { - assertEquals(Arrays.asList(1, 2, 3, 4, 5), toList(Range.createWithCount(1, 5))); - } - - @Test - public void testRangeWithCount2() { - assertEquals(Arrays.asList(2, 3, 4, 5), toList(Range.createWithCount(2, 4))); - } - - @Test - public void testRangeWithCount3() { - assertEquals(Arrays.asList(0, 1, 2, 3), toList(Range.createWithCount(0, 4))); - } - - @Test - public void testRangeWithCount4() { - assertEquals(Arrays.asList(10, 11, 12, 13, 14), toList(Range.createWithCount(10, 5))); - } - - private static List toList(Iterable iterable) { - List result = new ArrayList(); - for (T element : iterable) { - result.add(element); - } - return result; - } - - } } \ No newline at end of file diff --git a/rxjava-core/src/test/java/rx/SchedulersTest.java b/rxjava-core/src/test/java/rx/SchedulersTest.java index d2ac58e61f..4150686d74 100644 --- a/rxjava-core/src/test/java/rx/SchedulersTest.java +++ b/rxjava-core/src/test/java/rx/SchedulersTest.java @@ -16,6 +16,8 @@ package rx; import org.junit.Test; +import org.mockito.InOrder; +import org.mockito.Mockito; import rx.Observable.OnSubscribeFunc; import rx.concurrency.Schedulers; import rx.concurrency.TestScheduler; @@ -34,505 +36,547 @@ import java.util.concurrent.atomic.AtomicReference; import static org.junit.Assert.*; +import static org.mockito.Matchers.anyLong; +import static org.mockito.Mockito.*; public class SchedulersTest { - @Test - public void testComputationThreadPool1() { + @SuppressWarnings("unchecked") + // mocking is unchecked, unfortunately + @Test + public void testPeriodicScheduling() { + final Func1 calledOp = mock(Func1.class); - Observable o1 = Observable. from(1, 2, 3, 4, 5); - Observable o2 = Observable. from(6, 7, 8, 9, 10); - Observable o = Observable. merge(o1, o2).map(new Func1() { + final TestScheduler scheduler = new TestScheduler(); + Subscription subscription = scheduler.schedulePeriodically(new Action0() { + @Override + public void call() { + System.out.println(scheduler.now()); + calledOp.call(scheduler.now()); + } + }, 1, 2, TimeUnit.SECONDS); + + verify(calledOp, never()).call(anyLong()); - @Override - public String call(Integer t) { - assertTrue(Thread.currentThread().getName().startsWith("RxComputationThreadPool")); - return "Value_" + t + "_Thread_" + Thread.currentThread().getName(); - } - }); - - o.subscribeOn(Schedulers.threadPoolForComputation()).toBlockingObservable().forEach(new Action1() { + InOrder inOrder = Mockito.inOrder(calledOp); + + scheduler.advanceTimeBy(999L, TimeUnit.MILLISECONDS); + inOrder.verify(calledOp, never()).call(anyLong()); - @Override - public void call(String t) { - System.out.println("t: " + t); - } - }); - } + scheduler.advanceTimeBy(1L, TimeUnit.MILLISECONDS); + inOrder.verify(calledOp, times(1)).call(1000L); + + scheduler.advanceTimeBy(1999L, TimeUnit.MILLISECONDS); + inOrder.verify(calledOp, never()).call(3000L); + + scheduler.advanceTimeBy(1L, TimeUnit.MILLISECONDS); + inOrder.verify(calledOp, times(1)).call(3000L); + + scheduler.advanceTimeBy(5L, TimeUnit.SECONDS); + inOrder.verify(calledOp, times(1)).call(5000L); + inOrder.verify(calledOp, times(1)).call(7000L); + + subscription.unsubscribe(); + scheduler.advanceTimeBy(11L, TimeUnit.SECONDS); + inOrder.verify(calledOp, never()).call(anyLong()); + } + + @Test + public void testComputationThreadPool1() { + + Observable o1 = Observable.from(1, 2, 3, 4, 5); + Observable o2 = Observable.from(6, 7, 8, 9, 10); + Observable o = Observable.merge(o1, o2).map(new Func1() { + + @Override + public String call(Integer t) { + assertTrue(Thread.currentThread().getName().startsWith("RxComputationThreadPool")); + return "Value_" + t + "_Thread_" + Thread.currentThread().getName(); + } + }); - @Test - public void testIOThreadPool1() { + o.subscribeOn(Schedulers.threadPoolForComputation()).toBlockingObservable().forEach(new Action1() { + + @Override + public void call(String t) { + System.out.println("t: " + t); + } + }); + } + + @Test + public void testIOThreadPool1() { - Observable o1 = Observable. from(1, 2, 3, 4, 5); - Observable o2 = Observable. from(6, 7, 8, 9, 10); - Observable o = Observable. merge(o1, o2).map(new Func1() { + Observable o1 = Observable.from(1, 2, 3, 4, 5); + Observable o2 = Observable.from(6, 7, 8, 9, 10); + Observable o = Observable.merge(o1, o2).map(new Func1() { - @Override - public String call(Integer t) { - assertTrue(Thread.currentThread().getName().startsWith("RxIOThreadPool")); - return "Value_" + t + "_Thread_" + Thread.currentThread().getName(); - } - }); + @Override + public String call(Integer t) { + assertTrue(Thread.currentThread().getName().startsWith("RxIOThreadPool")); + return "Value_" + t + "_Thread_" + Thread.currentThread().getName(); + } + }); + + o.subscribeOn(Schedulers.threadPoolForIO()).toBlockingObservable().forEach(new Action1() { + + @Override + public void call(String t) { + System.out.println("t: " + t); + } + }); + } + + @Test + public void testMergeWithoutScheduler1() { + + final String currentThreadName = Thread.currentThread().getName(); + + Observable o1 = Observable.from(1, 2, 3, 4, 5); + Observable o2 = Observable.from(6, 7, 8, 9, 10); + Observable o = Observable.merge(o1, o2).map(new Func1() { + + @Override + public String call(Integer t) { + assertTrue(Thread.currentThread().getName().equals(currentThreadName)); + return "Value_" + t + "_Thread_" + Thread.currentThread().getName(); + } + }); + + o.toBlockingObservable().forEach(new Action1() { + + @Override + public void call(String t) { + System.out.println("t: " + t); + } + }); + } - o.subscribeOn(Schedulers.threadPoolForIO()).toBlockingObservable().forEach(new Action1() { + @Test + public void testMergeWithImmediateScheduler1() { - @Override - public void call(String t) { - System.out.println("t: " + t); - } - }); - } + final String currentThreadName = Thread.currentThread().getName(); - @Test - public void testMergeWithoutScheduler1() { + Observable o1 = Observable.from(1, 2, 3, 4, 5); + Observable o2 = Observable.from(6, 7, 8, 9, 10); + Observable o = Observable.merge(o1, o2).subscribeOn(Schedulers.immediate()).map(new Func1() { - final String currentThreadName = Thread.currentThread().getName(); + @Override + public String call(Integer t) { + assertTrue(Thread.currentThread().getName().equals(currentThreadName)); + return "Value_" + t + "_Thread_" + Thread.currentThread().getName(); + } + }); + + o.toBlockingObservable().forEach(new Action1() { + + @Override + public void call(String t) { + System.out.println("t: " + t); + } + }); + } + + @Test + public void testMergeWithCurrentThreadScheduler1() { + + final String currentThreadName = Thread.currentThread().getName(); + + Observable o1 = Observable.from(1, 2, 3, 4, 5); + Observable o2 = Observable.from(6, 7, 8, 9, 10); + Observable o = Observable.merge(o1, o2).subscribeOn(Schedulers.currentThread()).map(new Func1() { + + @Override + public String call(Integer t) { + assertTrue(Thread.currentThread().getName().equals(currentThreadName)); + return "Value_" + t + "_Thread_" + Thread.currentThread().getName(); + } + }); - Observable o1 = Observable. from(1, 2, 3, 4, 5); - Observable o2 = Observable. from(6, 7, 8, 9, 10); - Observable o = Observable. merge(o1, o2).map(new Func1() { + o.toBlockingObservable().forEach(new Action1() { - @Override - public String call(Integer t) { - assertTrue(Thread.currentThread().getName().equals(currentThreadName)); - return "Value_" + t + "_Thread_" + Thread.currentThread().getName(); - } - }); + @Override + public void call(String t) { + System.out.println("t: " + t); + } + }); + } - o.toBlockingObservable().forEach(new Action1() { + @Test + public void testMergeWithScheduler1() { - @Override - public void call(String t) { - System.out.println("t: " + t); - } - }); - } + final String currentThreadName = Thread.currentThread().getName(); - @Test - public void testMergeWithImmediateScheduler1() { + Observable o1 = Observable.from(1, 2, 3, 4, 5); + Observable o2 = Observable.from(6, 7, 8, 9, 10); + Observable o = Observable.merge(o1, o2).subscribeOn(Schedulers.threadPoolForComputation()).map(new Func1() { - final String currentThreadName = Thread.currentThread().getName(); + @Override + public String call(Integer t) { + assertFalse(Thread.currentThread().getName().equals(currentThreadName)); + assertTrue(Thread.currentThread().getName().startsWith("RxComputationThreadPool")); + return "Value_" + t + "_Thread_" + Thread.currentThread().getName(); + } + }); - Observable o1 = Observable. from(1, 2, 3, 4, 5); - Observable o2 = Observable. from(6, 7, 8, 9, 10); - Observable o = Observable. merge(o1, o2).subscribeOn(Schedulers.immediate()).map(new Func1() { + o.toBlockingObservable().forEach(new Action1() { - @Override - public String call(Integer t) { - assertTrue(Thread.currentThread().getName().equals(currentThreadName)); - return "Value_" + t + "_Thread_" + Thread.currentThread().getName(); - } - }); + @Override + public void call(String t) { + System.out.println("t: " + t); + } + }); + } - o.toBlockingObservable().forEach(new Action1() { + @Test + public void testSubscribeWithScheduler1() throws InterruptedException { - @Override - public void call(String t) { - System.out.println("t: " + t); - } - }); - } + final AtomicInteger count = new AtomicInteger(); - @Test - public void testMergeWithCurrentThreadScheduler1() { + Observable o1 = Observable.from(1, 2, 3, 4, 5); - final String currentThreadName = Thread.currentThread().getName(); + o1.subscribe(new Action1() { - Observable o1 = Observable. from(1, 2, 3, 4, 5); - Observable o2 = Observable. from(6, 7, 8, 9, 10); - Observable o = Observable. merge(o1, o2).subscribeOn(Schedulers.currentThread()).map(new Func1() { + @Override + public void call(Integer t) { + System.out.println("Thread: " + Thread.currentThread().getName()); + System.out.println("t: " + t); + count.incrementAndGet(); + } + }); - @Override - public String call(Integer t) { - assertTrue(Thread.currentThread().getName().equals(currentThreadName)); - return "Value_" + t + "_Thread_" + Thread.currentThread().getName(); - } - }); + // the above should be blocking so we should see a count of 5 + assertEquals(5, count.get()); - o.toBlockingObservable().forEach(new Action1() { + count.set(0); - @Override - public void call(String t) { - System.out.println("t: " + t); - } - }); - } + // now we'll subscribe with a scheduler and it should be async - @Test - public void testMergeWithScheduler1() { + final String currentThreadName = Thread.currentThread().getName(); - final String currentThreadName = Thread.currentThread().getName(); + // latches for deterministically controlling the test below across threads + final CountDownLatch latch = new CountDownLatch(5); + final CountDownLatch first = new CountDownLatch(1); - Observable o1 = Observable. from(1, 2, 3, 4, 5); - Observable o2 = Observable. from(6, 7, 8, 9, 10); - Observable o = Observable. merge(o1, o2).subscribeOn(Schedulers.threadPoolForComputation()).map(new Func1() { + o1.subscribe(new Action1() { - @Override - public String call(Integer t) { - assertFalse(Thread.currentThread().getName().equals(currentThreadName)); - assertTrue(Thread.currentThread().getName().startsWith("RxComputationThreadPool")); - return "Value_" + t + "_Thread_" + Thread.currentThread().getName(); + @Override + public void call(Integer t) { + try { + // we block the first one so we can assert this executes asynchronously with a count + first.await(1000, TimeUnit.SECONDS); + } catch (InterruptedException e) { + throw new RuntimeException("The latch should have released if we are async.", e); + } + assertFalse(Thread.currentThread().getName().equals(currentThreadName)); + assertTrue(Thread.currentThread().getName().startsWith("RxComputationThreadPool")); + System.out.println("Thread: " + Thread.currentThread().getName()); + System.out.println("t: " + t); + count.incrementAndGet(); + latch.countDown(); + } + }, Schedulers.threadPoolForComputation()); + + // assert we are async + assertEquals(0, count.get()); + // release the latch so it can go forward + first.countDown(); + + // wait for all 5 responses + latch.await(); + assertEquals(5, count.get()); + } + + @Test + public void testRecursiveScheduler1() { + Observable obs = Observable.create(new OnSubscribeFunc() { + @Override + public Subscription onSubscribe(final Observer observer) { + return Schedulers.currentThread().schedule(0, new Func2() { + @Override + public Subscription call(Scheduler scheduler, Integer i) { + if (i > 42) { + observer.onCompleted(); + return Subscriptions.empty(); } - }); - o.toBlockingObservable().forEach(new Action1() { + observer.onNext(i); - @Override - public void call(String t) { - System.out.println("t: " + t); - } + return scheduler.schedule(i + 1, this); + } }); - } - - @Test - public void testSubscribeWithScheduler1() throws InterruptedException { - - final AtomicInteger count = new AtomicInteger(); + } + }); + + final AtomicInteger lastValue = new AtomicInteger(); + obs.toBlockingObservable().forEach(new Action1() { + + @Override + public void call(Integer v) { + System.out.println("Value: " + v); + lastValue.set(v); + } + }); + + assertEquals(42, lastValue.get()); + } + + @Test + public void testRecursiveScheduler2() throws InterruptedException { + // use latches instead of Thread.sleep + final CountDownLatch latch = new CountDownLatch(10); + final CountDownLatch completionLatch = new CountDownLatch(1); + + Observable obs = Observable.create(new OnSubscribeFunc() { + @Override + public Subscription onSubscribe(final Observer observer) { + + return Schedulers.threadPoolForComputation().schedule(new BooleanSubscription(), new Func2() { + @Override + public Subscription call(Scheduler scheduler, BooleanSubscription cancel) { + if (cancel.isUnsubscribed()) { + observer.onCompleted(); + completionLatch.countDown(); + return Subscriptions.empty(); + } - Observable o1 = Observable. from(1, 2, 3, 4, 5); + observer.onNext(42); + latch.countDown(); - o1.subscribe(new Action1() { + // this will recursively schedule this task for execution again + scheduler.schedule(cancel, this); - @Override - public void call(Integer t) { - System.out.println("Thread: " + Thread.currentThread().getName()); - System.out.println("t: " + t); - count.incrementAndGet(); - } + return cancel; + } }); + } + }); + + final AtomicInteger count = new AtomicInteger(); + final AtomicBoolean completed = new AtomicBoolean(false); + Subscription subscribe = obs.subscribe(new Observer() { + @Override + public void onCompleted() { + System.out.println("Completed"); + completed.set(true); + } + + @Override + public void onError(Throwable e) { + System.out.println("Error"); + } + + @Override + public void onNext(Integer args) { + count.incrementAndGet(); + System.out.println(args); + } + }); + + if (!latch.await(5000, TimeUnit.MILLISECONDS)) { + fail("Timed out waiting on onNext latch"); + } - // the above should be blocking so we should see a count of 5 - assertEquals(5, count.get()); + // now unsubscribe and ensure it stops the recursive loop + subscribe.unsubscribe(); + System.out.println("unsubscribe"); - count.set(0); + if (!completionLatch.await(5000, TimeUnit.MILLISECONDS)) { + fail("Timed out waiting on completion latch"); + } - // now we'll subscribe with a scheduler and it should be async + // the count can be 10 or higher due to thread scheduling of the unsubscribe vs the scheduler looping to emit the count + assertTrue(count.get() >= 10); + assertTrue(completed.get()); + } - final String currentThreadName = Thread.currentThread().getName(); + @Test + public void testSchedulingWithDueTime() throws InterruptedException { - // latches for deterministically controlling the test below across threads - final CountDownLatch latch = new CountDownLatch(5); - final CountDownLatch first = new CountDownLatch(1); + final CountDownLatch latch = new CountDownLatch(5); + final AtomicInteger counter = new AtomicInteger(); - o1.subscribe(new Action1() { + long start = System.currentTimeMillis(); - @Override - public void call(Integer t) { - try { - // we block the first one so we can assert this executes asynchronously with a count - first.await(1000, TimeUnit.SECONDS); - } catch (InterruptedException e) { - throw new RuntimeException("The latch should have released if we are async.", e); - } - assertFalse(Thread.currentThread().getName().equals(currentThreadName)); - assertTrue(Thread.currentThread().getName().startsWith("RxComputationThreadPool")); - System.out.println("Thread: " + Thread.currentThread().getName()); - System.out.println("t: " + t); - count.incrementAndGet(); - latch.countDown(); - } - }, Schedulers.threadPoolForComputation()); + Schedulers.threadPoolForComputation().schedule(null, new Func2() { - // assert we are async - assertEquals(0, count.get()); - // release the latch so it can go forward - first.countDown(); + @Override + public Subscription call(Scheduler scheduler, String state) { + System.out.println("doing work"); + counter.incrementAndGet(); + latch.countDown(); + if (latch.getCount() == 0) { + return Subscriptions.empty(); + } else { + return scheduler.schedule(state, this, new Date(System.currentTimeMillis() + 50)); + } + } + }, new Date(System.currentTimeMillis() + 100)); - // wait for all 5 responses - latch.await(); - assertEquals(5, count.get()); + if (!latch.await(3000, TimeUnit.MILLISECONDS)) { + fail("didn't execute ... timed out"); } - @Test - public void testRecursiveScheduler1() { - Observable obs = Observable.create(new OnSubscribeFunc() { - @Override - public Subscription onSubscribe(final Observer observer) { - return Schedulers.currentThread().schedule(0, new Func2() { - @Override - public Subscription call(Scheduler scheduler, Integer i) { - if (i > 42) { - observer.onCompleted(); - return Subscriptions.empty(); - } - - observer.onNext(i); - - return scheduler.schedule(i + 1, this); - } - }); - } - }); - - final AtomicInteger lastValue = new AtomicInteger(); - obs.toBlockingObservable().forEach(new Action1() { + long end = System.currentTimeMillis(); - @Override - public void call(Integer v) { - System.out.println("Value: " + v); - lastValue.set(v); - } - }); - - assertEquals(42, lastValue.get()); + assertEquals(5, counter.get()); + if ((end - start) < 250) { + fail("it should have taken over 250ms since each step was scheduled 50ms in the future"); } + } - @Test - public void testRecursiveScheduler2() throws InterruptedException { - // use latches instead of Thread.sleep - final CountDownLatch latch = new CountDownLatch(10); - final CountDownLatch completionLatch = new CountDownLatch(1); + @Test + public void testConcurrentOnNextFailsValidation() throws InterruptedException { - Observable obs = Observable.create(new OnSubscribeFunc() { - @Override - public Subscription onSubscribe(final Observer observer) { - - return Schedulers.threadPoolForComputation().schedule(new BooleanSubscription(), new Func2() { - @Override - public Subscription call(Scheduler scheduler, BooleanSubscription cancel) { - if (cancel.isUnsubscribed()) { - observer.onCompleted(); - completionLatch.countDown(); - return Subscriptions.empty(); - } - - observer.onNext(42); - latch.countDown(); - - // this will recursively schedule this task for execution again - scheduler.schedule(cancel, this); - - return cancel; - } - }); - } - }); + final int count = 10; + final CountDownLatch latch = new CountDownLatch(count); + Observable o = Observable.create(new OnSubscribeFunc() { - final AtomicInteger count = new AtomicInteger(); - final AtomicBoolean completed = new AtomicBoolean(false); - Subscription subscribe = obs.subscribe(new Observer() { - @Override - public void onCompleted() { - System.out.println("Completed"); - completed.set(true); - } + @Override + public Subscription onSubscribe(final Observer observer) { + for (int i = 0; i < count; i++) { + final int v = i; + new Thread(new Runnable() { @Override - public void onError(Throwable e) { - System.out.println("Error"); - } + public void run() { + observer.onNext("v: " + v); - @Override - public void onNext(Integer args) { - count.incrementAndGet(); - System.out.println(args); + latch.countDown(); } - }); - - if (!latch.await(5000, TimeUnit.MILLISECONDS)) { - fail("Timed out waiting on onNext latch"); + }).start(); } + return Subscriptions.empty(); + } + }); - // now unsubscribe and ensure it stops the recursive loop - subscribe.unsubscribe(); - System.out.println("unsubscribe"); - - if (!completionLatch.await(5000, TimeUnit.MILLISECONDS)) { - fail("Timed out waiting on completion latch"); - } + ConcurrentObserverValidator observer = new ConcurrentObserverValidator(); + // this should call onNext concurrently + o.subscribe(observer); - // the count can be 10 or higher due to thread scheduling of the unsubscribe vs the scheduler looping to emit the count - assertTrue(count.get() >= 10); - assertTrue(completed.get()); + if (!observer.completed.await(3000, TimeUnit.MILLISECONDS)) { + fail("timed out"); } - @Test - public void testSchedulingWithDueTime() throws InterruptedException { + if (observer.error.get() == null) { + fail("We expected error messages due to concurrency"); + } + } - final CountDownLatch latch = new CountDownLatch(5); - final AtomicInteger counter = new AtomicInteger(); + @Test + public void testObserveOn() throws InterruptedException { - long start = System.currentTimeMillis(); + Observable o = Observable.from("one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten"); - Schedulers.threadPoolForComputation().schedule(null, new Func2() { + ConcurrentObserverValidator observer = new ConcurrentObserverValidator(); - @Override - public Subscription call(Scheduler scheduler, String state) { - System.out.println("doing work"); - counter.incrementAndGet(); - latch.countDown(); - if (latch.getCount() == 0) { - return Subscriptions.empty(); - } else { - return scheduler.schedule(state, this, new Date(System.currentTimeMillis() + 50)); - } - } - }, new Date(System.currentTimeMillis() + 100)); + o.observeOn(Schedulers.threadPoolForComputation()).subscribe(observer); - if (!latch.await(3000, TimeUnit.MILLISECONDS)) { - fail("didn't execute ... timed out"); - } - - long end = System.currentTimeMillis(); + if (!observer.completed.await(3000, TimeUnit.MILLISECONDS)) { + fail("timed out"); + } - assertEquals(5, counter.get()); - if ((end - start) < 250) { - fail("it should have taken over 250ms since each step was scheduled 50ms in the future"); - } + if (observer.error.get() != null) { + observer.error.get().printStackTrace(); + fail("Error: " + observer.error.get().getMessage()); } + } - @Test - public void testConcurrentOnNextFailsValidation() throws InterruptedException { + @Test + public void testSubscribeOnNestedConcurrency() throws InterruptedException { - final int count = 10; - final CountDownLatch latch = new CountDownLatch(count); - Observable o = Observable.create(new OnSubscribeFunc() { + Observable o = Observable.from("one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten") + .mapMany(new Func1>() { - @Override - public Subscription onSubscribe(final Observer observer) { - for (int i = 0; i < count; i++) { - final int v = i; - new Thread(new Runnable() { - - @Override - public void run() { - observer.onNext("v: " + v); - - latch.countDown(); - } - }).start(); - } + @Override + public Observable call(final String v) { + return Observable.create(new OnSubscribeFunc() { + + @Override + public Subscription onSubscribe(final Observer observer) { + observer.onNext("value_after_map-" + v); + observer.onCompleted(); return Subscriptions.empty(); - } + } + }).subscribeOn(Schedulers.newThread()); // subscribe on a new thread + } }); - ConcurrentObserverValidator observer = new ConcurrentObserverValidator(); - // this should call onNext concurrently - o.subscribe(observer); + ConcurrentObserverValidator observer = new ConcurrentObserverValidator(); - if (!observer.completed.await(3000, TimeUnit.MILLISECONDS)) { - fail("timed out"); - } + o.subscribe(observer); - if (observer.error.get() == null) { - fail("We expected error messages due to concurrency"); - } + if (!observer.completed.await(3000, TimeUnit.MILLISECONDS)) { + fail("timed out"); } - @Test - public void testObserveOn() throws InterruptedException { - - Observable o = Observable.from("one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten"); - - ConcurrentObserverValidator observer = new ConcurrentObserverValidator(); - - o.observeOn(Schedulers.threadPoolForComputation()).subscribe(observer); - - if (!observer.completed.await(3000, TimeUnit.MILLISECONDS)) { - fail("timed out"); - } - - if (observer.error.get() != null) { - observer.error.get().printStackTrace(); - fail("Error: " + observer.error.get().getMessage()); - } + if (observer.error.get() != null) { + observer.error.get().printStackTrace(); + fail("Error: " + observer.error.get().getMessage()); } + } - @Test - public void testSubscribeOnNestedConcurrency() throws InterruptedException { - - Observable o = Observable.from("one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten") - .mapMany(new Func1>() { + @Test + public void testRecursion() { + TestScheduler s = new TestScheduler(); - @Override - public Observable call(final String v) { - return Observable.create(new OnSubscribeFunc() { + final AtomicInteger counter = new AtomicInteger(0); - @Override - public Subscription onSubscribe(final Observer observer) { - observer.onNext("value_after_map-" + v); - observer.onCompleted(); - return Subscriptions.empty(); - } - }).subscribeOn(Schedulers.newThread()); // subscribe on a new thread - } - }); + Subscription subscription = s.schedule(new Action1() { - ConcurrentObserverValidator observer = new ConcurrentObserverValidator(); + @Override + public void call(Action0 self) { + counter.incrementAndGet(); + System.out.println("counter: " + counter.get()); + self.call(); + } - o.subscribe(observer); + }); + subscription.unsubscribe(); + assertEquals(0, counter.get()); + } - if (!observer.completed.await(3000, TimeUnit.MILLISECONDS)) { - fail("timed out"); - } - - if (observer.error.get() != null) { - observer.error.get().printStackTrace(); - fail("Error: " + observer.error.get().getMessage()); - } - } - @Test - public void testRecursion() { - TestScheduler s = new TestScheduler(); + /** + * Used to determine if onNext is being invoked concurrently. + * + * @param + */ + private static class ConcurrentObserverValidator implements Observer { - final AtomicInteger counter = new AtomicInteger(0); + final AtomicInteger concurrentCounter = new AtomicInteger(); + final AtomicReference error = new AtomicReference(); + final CountDownLatch completed = new CountDownLatch(1); - Subscription subscription = s.schedule(new Action1() { - - @Override - public void call(Action0 self) { - counter.incrementAndGet(); - System.out.println("counter: " + counter.get()); - self.call(); - } - - }); - subscription.unsubscribe(); - assertEquals(0, counter.get()); + @Override + public void onCompleted() { + completed.countDown(); } + @Override + public void onError(Throwable e) { + completed.countDown(); + error.set(e); + } - /** - * Used to determine if onNext is being invoked concurrently. - * - * @param - */ - private static class ConcurrentObserverValidator implements Observer { - - final AtomicInteger concurrentCounter = new AtomicInteger(); - final AtomicReference error = new AtomicReference(); - final CountDownLatch completed = new CountDownLatch(1); - - @Override - public void onCompleted() { - completed.countDown(); - } - - @Override - public void onError(Throwable e) { - completed.countDown(); - error.set(e); - } - - @Override - public void onNext(T args) { - int count = concurrentCounter.incrementAndGet(); - System.out.println("ConcurrentObserverValidator.onNext: " + args); - if (count > 1) { - onError(new RuntimeException("we should not have concurrent execution of onNext")); - } - try { - try { - // take some time so other onNext calls could pile up (I haven't yet thought of a way to do this without sleeping) - Thread.sleep(50); - } catch (InterruptedException e) { - // ignore - } - } finally { - concurrentCounter.decrementAndGet(); - } + @Override + public void onNext(T args) { + int count = concurrentCounter.incrementAndGet(); + System.out.println("ConcurrentObserverValidator.onNext: " + args); + if (count > 1) { + onError(new RuntimeException("we should not have concurrent execution of onNext")); + } + try { + try { + // take some time so other onNext calls could pile up (I haven't yet thought of a way to do this without sleeping) + Thread.sleep(50); + } catch (InterruptedException e) { + // ignore } - + } finally { + concurrentCounter.decrementAndGet(); + } } + + } } diff --git a/rxjava-core/src/test/java/rx/concurrency/CurrentThreadSchedulerTest.java b/rxjava-core/src/test/java/rx/concurrency/CurrentThreadSchedulerTest.java index b9a9b1a1c2..de34142a93 100644 --- a/rxjava-core/src/test/java/rx/concurrency/CurrentThreadSchedulerTest.java +++ b/rxjava-core/src/test/java/rx/concurrency/CurrentThreadSchedulerTest.java @@ -1,7 +1,129 @@ package rx.concurrency; -import org.junit.Ignore; +import org.junit.Test; +import org.mockito.InOrder; +import rx.util.functions.Action0; + +import java.util.concurrent.TimeUnit; + +import static org.mockito.Mockito.*; -@Ignore("WIP") public class CurrentThreadSchedulerTest { + + @Test + public void testNestedActions() { + final CurrentThreadScheduler scheduler = new CurrentThreadScheduler(); + + final Action0 firstStepStart = mock(Action0.class); + final Action0 firstStepEnd = mock(Action0.class); + + final Action0 secondStepStart = mock(Action0.class); + final Action0 secondStepEnd = mock(Action0.class); + + final Action0 thirdStepStart = mock(Action0.class); + final Action0 thirdStepEnd = mock(Action0.class); + + final Action0 firstAction = new Action0() { + @Override + public void call() { + firstStepStart.call(); + firstStepEnd.call(); + } + }; + final Action0 secondAction = new Action0() { + @Override + public void call() { + secondStepStart.call(); + scheduler.schedule(firstAction); + secondStepEnd.call(); + + } + }; + final Action0 thirdAction = new Action0() { + @Override + public void call() { + thirdStepStart.call(); + scheduler.schedule(secondAction); + thirdStepEnd.call(); + } + }; + + InOrder inOrder = inOrder(firstStepStart, firstStepEnd, secondStepStart, secondStepEnd, thirdStepStart, thirdStepEnd); + + scheduler.schedule(thirdAction); + + inOrder.verify(thirdStepStart, times(1)).call(); + inOrder.verify(thirdStepEnd, times(1)).call(); + inOrder.verify(secondStepStart, times(1)).call(); + inOrder.verify(secondStepEnd, times(1)).call(); + inOrder.verify(firstStepStart, times(1)).call(); + inOrder.verify(firstStepEnd, times(1)).call(); + } + + @Test + public void testSequenceOfActions() { + final CurrentThreadScheduler scheduler = new CurrentThreadScheduler(); + + final Action0 first = mock(Action0.class); + final Action0 second = mock(Action0.class); + + scheduler.schedule(first); + scheduler.schedule(second); + + verify(first, times(1)).call(); + verify(second, times(1)).call(); + + } + + @Test + public void testSequenceOfDelayedActions() { + final CurrentThreadScheduler scheduler = new CurrentThreadScheduler(); + + final Action0 first = mock(Action0.class); + final Action0 second = mock(Action0.class); + + scheduler.schedule(new Action0() { + @Override + public void call() { + scheduler.schedule(first, 30, TimeUnit.MILLISECONDS); + scheduler.schedule(second, 10, TimeUnit.MILLISECONDS); + } + }); + + InOrder inOrder = inOrder(first, second); + + inOrder.verify(second, times(1)).call(); + inOrder.verify(first, times(1)).call(); + + + } + + @Test + public void testMixOfDelayedAndNonDelayedActions() { + final CurrentThreadScheduler scheduler = new CurrentThreadScheduler(); + + final Action0 first = mock(Action0.class); + final Action0 second = mock(Action0.class); + final Action0 third = mock(Action0.class); + final Action0 fourth = mock(Action0.class); + + scheduler.schedule(new Action0() { + @Override + public void call() { + scheduler.schedule(first); + scheduler.schedule(second, 300, TimeUnit.MILLISECONDS); + scheduler.schedule(third, 100, TimeUnit.MILLISECONDS); + scheduler.schedule(fourth); + } + }); + + InOrder inOrder = inOrder(first, second, third, fourth); + + inOrder.verify(first, times(1)).call(); + inOrder.verify(fourth, times(1)).call(); + inOrder.verify(third, times(1)).call(); + inOrder.verify(second, times(1)).call(); + + + } } diff --git a/rxjava-core/src/test/java/rx/concurrency/ImmediateSchedulerTest.java b/rxjava-core/src/test/java/rx/concurrency/ImmediateSchedulerTest.java index 036103e540..df08b8aa31 100644 --- a/rxjava-core/src/test/java/rx/concurrency/ImmediateSchedulerTest.java +++ b/rxjava-core/src/test/java/rx/concurrency/ImmediateSchedulerTest.java @@ -1,7 +1,59 @@ package rx.concurrency; -import org.junit.Ignore; +import org.junit.Test; +import org.mockito.InOrder; +import rx.util.functions.Action0; + +import static org.mockito.Mockito.*; -@Ignore("WIP") public class ImmediateSchedulerTest { + @Test + public void testNestedActions() { + final ImmediateScheduler scheduler = new ImmediateScheduler(); + + final Action0 firstStepStart = mock(Action0.class); + final Action0 firstStepEnd = mock(Action0.class); + + final Action0 secondStepStart = mock(Action0.class); + final Action0 secondStepEnd = mock(Action0.class); + + final Action0 thirdStepStart = mock(Action0.class); + final Action0 thirdStepEnd = mock(Action0.class); + + final Action0 firstAction = new Action0() { + @Override + public void call() { + firstStepStart.call(); + firstStepEnd.call(); + } + }; + final Action0 secondAction = new Action0() { + @Override + public void call() { + secondStepStart.call(); + scheduler.schedule(firstAction); + secondStepEnd.call(); + + } + }; + final Action0 thirdAction = new Action0() { + @Override + public void call() { + thirdStepStart.call(); + scheduler.schedule(secondAction); + thirdStepEnd.call(); + } + }; + + InOrder inOrder = inOrder(firstStepStart, firstStepEnd, secondStepStart, secondStepEnd, thirdStepStart, thirdStepEnd); + + scheduler.schedule(thirdAction); + + inOrder.verify(thirdStepStart, times(1)).call(); + inOrder.verify(secondStepStart, times(1)).call(); + inOrder.verify(firstStepStart, times(1)).call(); + inOrder.verify(firstStepEnd, times(1)).call(); + inOrder.verify(secondStepEnd, times(1)).call(); + inOrder.verify(thirdStepEnd, times(1)).call(); + } } diff --git a/rxjava-core/src/test/java/rx/observables/BlockingObservableTest.java b/rxjava-core/src/test/java/rx/observables/BlockingObservableTest.java index aa38f711ad..0c6f885de9 100644 --- a/rxjava-core/src/test/java/rx/observables/BlockingObservableTest.java +++ b/rxjava-core/src/test/java/rx/observables/BlockingObservableTest.java @@ -1,7 +1,248 @@ package rx.observables; -import org.junit.Ignore; +import org.junit.Before; +import org.junit.Test; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import rx.Observable; +import rx.Observer; +import rx.Subscription; +import rx.subscriptions.BooleanSubscription; +import rx.subscriptions.Subscriptions; +import rx.util.functions.Action1; +import rx.util.functions.Func1; + +import java.util.Iterator; + +import static org.junit.Assert.*; -@Ignore("WIP") public class BlockingObservableTest { + + @Mock + Observer w; + + @Before + public void before() { + MockitoAnnotations.initMocks(this); + } + + @Test + public void testLast() { + BlockingObservable obs = BlockingObservable.from(Observable.from("one", "two", "three")); + + assertEquals("three", obs.last()); + } + + @Test + public void testLastEmptyObservable() { + BlockingObservable obs = BlockingObservable.from(Observable.empty()); + + assertNull(obs.last()); + } + + @Test + public void testLastOrDefault() { + BlockingObservable observable = BlockingObservable.from(Observable.from(1, 0, -1)); + int last = observable.lastOrDefault(-100, new Func1() { + @Override + public Boolean call(Integer args) { + return args >= 0; + } + }); + assertEquals(0, last); + } + + @Test + public void testLastOrDefault1() { + BlockingObservable observable = BlockingObservable.from(Observable.from("one", "two", "three")); + assertEquals("three", observable.lastOrDefault("default")); + } + + @Test + public void testLastOrDefault2() { + BlockingObservable observable = BlockingObservable.from(Observable.empty()); + assertEquals("default", observable.lastOrDefault("default")); + } + + @Test + public void testLastOrDefaultWithPredicate() { + BlockingObservable observable = BlockingObservable.from(Observable.from(1, 0, -1)); + int last = observable.lastOrDefault(0, new Func1() { + @Override + public Boolean call(Integer args) { + return args < 0; + } + }); + + assertEquals(-1, last); + } + + @Test + public void testLastOrDefaultWrongPredicate() { + BlockingObservable observable = BlockingObservable.from(Observable.from(-1, -2, -3)); + int last = observable.lastOrDefault(0, new Func1() { + @Override + public Boolean call(Integer args) { + return args >= 0; + } + }); + assertEquals(0, last); + } + + @Test + public void testLastWithPredicate() { + BlockingObservable obs = BlockingObservable.from(Observable.from("one", "two", "three")); + + assertEquals("two", obs.last(new Func1() { + @Override + public Boolean call(String s) { + return s.length() == 3; + } + })); + } + + public void testSingle() { + BlockingObservable observable = BlockingObservable.from(Observable.from("one")); + assertEquals("one", observable.single()); + } + + @Test + public void testSingleDefault() { + BlockingObservable observable = BlockingObservable.from(Observable.empty()); + assertEquals("default", observable.singleOrDefault("default")); + } + + @Test(expected = IllegalStateException.class) + public void testSingleDefaultPredicateMatchesMoreThanOne() { + BlockingObservable.from(Observable.from("one", "two")).singleOrDefault("default", new Func1() { + @Override + public Boolean call(String args) { + return args.length() == 3; + } + }); + } + + @Test + public void testSingleDefaultPredicateMatchesNothing() { + BlockingObservable observable = BlockingObservable.from(Observable.from("one", "two")); + String result = observable.singleOrDefault("default", new Func1() { + @Override + public Boolean call(String args) { + return args.length() == 4; + } + }); + assertEquals("default", result); + } + + @Test(expected = IllegalStateException.class) + public void testSingleDefaultWithMoreThanOne() { + BlockingObservable observable = BlockingObservable.from(Observable.from("one", "two", "three")); + observable.singleOrDefault("default"); + } + + @Test + public void testSingleWithPredicateDefault() { + BlockingObservable observable = BlockingObservable.from(Observable.from("one", "two", "four")); + assertEquals("four", observable.single(new Func1() { + @Override + public Boolean call(String s) { + return s.length() == 4; + } + })); + } + + @Test(expected = IllegalStateException.class) + public void testSingleWrong() { + BlockingObservable observable = BlockingObservable.from(Observable.from(1, 2)); + observable.single(); + } + + @Test(expected = IllegalStateException.class) + public void testSingleWrongPredicate() { + BlockingObservable observable = BlockingObservable.from(Observable.from(-1)); + observable.single(new Func1() { + @Override + public Boolean call(Integer args) { + return args > 0; + } + }); + } + + @Test + public void testToIterable() { + BlockingObservable obs = BlockingObservable.from(Observable.from("one", "two", "three")); + + Iterator it = obs.toIterable().iterator(); + + assertEquals(true, it.hasNext()); + assertEquals("one", it.next()); + + assertEquals(true, it.hasNext()); + assertEquals("two", it.next()); + + assertEquals(true, it.hasNext()); + assertEquals("three", it.next()); + + assertEquals(false, it.hasNext()); + + } + + @Test(expected = TestException.class) + public void testToIterableWithException() { + BlockingObservable obs = BlockingObservable.from(Observable.create(new Observable.OnSubscribeFunc() { + + @Override + public Subscription onSubscribe(Observer observer) { + observer.onNext("one"); + observer.onError(new TestException()); + return Subscriptions.empty(); + } + })); + + Iterator it = obs.toIterable().iterator(); + + assertEquals(true, it.hasNext()); + assertEquals("one", it.next()); + + assertEquals(true, it.hasNext()); + it.next(); + + } + + @Test + public void testForEachWithError() { + try { + BlockingObservable.from(Observable.create(new Observable.OnSubscribeFunc() { + + @Override + public Subscription onSubscribe(final Observer observer) { + final BooleanSubscription subscription = new BooleanSubscription(); + new Thread(new Runnable() { + + @Override + public void run() { + observer.onNext("one"); + observer.onNext("two"); + observer.onNext("three"); + observer.onCompleted(); + } + }).start(); + return subscription; + } + })).forEach(new Action1() { + + @Override + public void call(String t1) { + throw new RuntimeException("fail"); + } + }); + fail("we expect an exception to be thrown"); + } catch (Throwable e) { + // do nothing as we expect this + } + } + + private static class TestException extends RuntimeException { + private static final long serialVersionUID = 1L; + } } diff --git a/rxjava-core/src/test/java/rx/operators/OperationAllTest.java b/rxjava-core/src/test/java/rx/operators/OperationAllTest.java index ffb0b56798..23bde39e59 100644 --- a/rxjava-core/src/test/java/rx/operators/OperationAllTest.java +++ b/rxjava-core/src/test/java/rx/operators/OperationAllTest.java @@ -1,7 +1,84 @@ package rx.operators; -import org.junit.Ignore; +import org.junit.Test; +import rx.Observable; +import rx.Observer; +import rx.util.functions.Func1; + +import static org.mockito.Mockito.*; +import static rx.operators.OperationAll.all; -@Ignore("WIP") public class OperationAllTest { + + @Test + @SuppressWarnings("unchecked") + public void testAll() { + Observable obs = Observable.from("one", "two", "six"); + + Observer observer = mock(Observer.class); + Observable.create(all(obs, new Func1() { + @Override + public Boolean call(String s) { + return s.length() == 3; + } + })).subscribe(observer); + + verify(observer).onNext(true); + verify(observer).onCompleted(); + verifyNoMoreInteractions(observer); + } + + @Test + @SuppressWarnings("unchecked") + public void testNotAll() { + Observable obs = Observable.from("one", "two", "three", "six"); + + Observer observer = mock(Observer.class); + Observable.create(all(obs, new Func1() { + @Override + public Boolean call(String s) { + return s.length() == 3; + } + })).subscribe(observer); + + verify(observer).onNext(false); + verify(observer).onCompleted(); + verifyNoMoreInteractions(observer); + } + + @Test + @SuppressWarnings("unchecked") + public void testEmpty() { + Observable obs = Observable.empty(); + + Observer observer = mock(Observer.class); + Observable.create(all(obs, new Func1() { + @Override + public Boolean call(String s) { + return s.length() == 3; + } + })).subscribe(observer); + + verify(observer).onNext(true); + verify(observer).onCompleted(); + verifyNoMoreInteractions(observer); + } + + @Test + @SuppressWarnings("unchecked") + public void testError() { + Throwable error = new Throwable(); + Observable obs = Observable.error(error); + + Observer observer = mock(Observer.class); + Observable.create(all(obs, new Func1() { + @Override + public Boolean call(String s) { + return s.length() == 3; + } + })).subscribe(observer); + + verify(observer).onError(error); + verifyNoMoreInteractions(observer); + } } diff --git a/rxjava-core/src/test/java/rx/operators/OperationAnyTest.java b/rxjava-core/src/test/java/rx/operators/OperationAnyTest.java index 98d6e72fa5..801a35d0c3 100644 --- a/rxjava-core/src/test/java/rx/operators/OperationAnyTest.java +++ b/rxjava-core/src/test/java/rx/operators/OperationAnyTest.java @@ -1,7 +1,182 @@ package rx.operators; -import org.junit.Ignore; +import org.junit.Test; +import rx.Observable; +import rx.Observer; +import rx.util.functions.Func1; + +import static org.mockito.Mockito.*; +import static rx.operators.OperationAny.any; +import static rx.operators.OperationAny.*; -@Ignore("WIP") public class OperationAnyTest { + + @Test + public void testAnyWithTwoItems() { + Observable w = Observable.from(1, 2); + Observable observable = Observable.create(any(w)); + + @SuppressWarnings("unchecked") + Observer aObserver = mock(Observer.class); + observable.subscribe(aObserver); + verify(aObserver, never()).onNext(false); + verify(aObserver, times(1)).onNext(true); + verify(aObserver, never()).onError(org.mockito.Matchers.any(Throwable.class)); + verify(aObserver, times(1)).onCompleted(); + } + + @Test + public void testIsEmptyWithTwoItems() { + Observable w = Observable.from(1, 2); + Observable observable = Observable.create(isEmpty(w)); + + @SuppressWarnings("unchecked") + Observer aObserver = mock(Observer.class); + observable.subscribe(aObserver); + verify(aObserver, never()).onNext(true); + verify(aObserver, times(1)).onNext(false); + verify(aObserver, never()).onError(org.mockito.Matchers.any(Throwable.class)); + verify(aObserver, times(1)).onCompleted(); + } + + @Test + public void testAnyWithOneItem() { + Observable w = Observable.from(1); + Observable observable = Observable.create(any(w)); + + @SuppressWarnings("unchecked") + Observer aObserver = mock(Observer.class); + observable.subscribe(aObserver); + verify(aObserver, never()).onNext(false); + verify(aObserver, times(1)).onNext(true); + verify(aObserver, never()).onError(org.mockito.Matchers.any(Throwable.class)); + verify(aObserver, times(1)).onCompleted(); + } + + @Test + public void testIsEmptyWithOneItem() { + Observable w = Observable.from(1); + Observable observable = Observable.create(isEmpty(w)); + + @SuppressWarnings("unchecked") + Observer aObserver = mock(Observer.class); + observable.subscribe(aObserver); + verify(aObserver, never()).onNext(true); + verify(aObserver, times(1)).onNext(false); + verify(aObserver, never()).onError(org.mockito.Matchers.any(Throwable.class)); + verify(aObserver, times(1)).onCompleted(); + } + + @Test + public void testAnyWithEmpty() { + Observable w = Observable.empty(); + Observable observable = Observable.create(any(w)); + + @SuppressWarnings("unchecked") + Observer aObserver = mock(Observer.class); + observable.subscribe(aObserver); + verify(aObserver, times(1)).onNext(false); + verify(aObserver, never()).onNext(true); + verify(aObserver, never()).onError(org.mockito.Matchers.any(Throwable.class)); + verify(aObserver, times(1)).onCompleted(); + } + + @Test + public void testIsEmptyWithEmpty() { + Observable w = Observable.empty(); + Observable observable = Observable.create(isEmpty(w)); + + @SuppressWarnings("unchecked") + Observer aObserver = mock(Observer.class); + observable.subscribe(aObserver); + verify(aObserver, times(1)).onNext(true); + verify(aObserver, never()).onNext(false); + verify(aObserver, never()).onError(org.mockito.Matchers.any(Throwable.class)); + verify(aObserver, times(1)).onCompleted(); + } + + @Test + public void testAnyWithPredicate1() { + Observable w = Observable.from(1, 2, 3); + Observable observable = Observable.create(any(w, + new Func1() { + + @Override + public Boolean call(Integer t1) { + return t1 < 2; + } + })); + + @SuppressWarnings("unchecked") + Observer aObserver = mock(Observer.class); + observable.subscribe(aObserver); + verify(aObserver, never()).onNext(false); + verify(aObserver, times(1)).onNext(true); + verify(aObserver, never()).onError(org.mockito.Matchers.any(Throwable.class)); + verify(aObserver, times(1)).onCompleted(); + } + + @Test + public void testExists1() { + Observable w = Observable.from(1, 2, 3); + Observable observable = Observable.create(exists(w, + new Func1() { + + @Override + public Boolean call(Integer t1) { + return t1 < 2; + } + })); + + @SuppressWarnings("unchecked") + Observer aObserver = mock(Observer.class); + observable.subscribe(aObserver); + verify(aObserver, never()).onNext(false); + verify(aObserver, times(1)).onNext(true); + verify(aObserver, never()).onError(org.mockito.Matchers.any(Throwable.class)); + verify(aObserver, times(1)).onCompleted(); + } + + @Test + public void testAnyWithPredicate2() { + Observable w = Observable.from(1, 2, 3); + Observable observable = Observable.create(any(w, + new Func1() { + + @Override + public Boolean call(Integer t1) { + return t1 < 1; + } + })); + + @SuppressWarnings("unchecked") + Observer aObserver = mock(Observer.class); + observable.subscribe(aObserver); + verify(aObserver, times(1)).onNext(false); + verify(aObserver, never()).onNext(true); + verify(aObserver, never()).onError(org.mockito.Matchers.any(Throwable.class)); + verify(aObserver, times(1)).onCompleted(); + } + + @Test + public void testAnyWithEmptyAndPredicate() { + // If the source is empty, always output false. + Observable w = Observable.empty(); + Observable observable = Observable.create(any(w, + new Func1() { + + @Override + public Boolean call(Integer t1) { + return true; + } + })); + + @SuppressWarnings("unchecked") + Observer aObserver = mock(Observer.class); + observable.subscribe(aObserver); + verify(aObserver, times(1)).onNext(false); + verify(aObserver, never()).onNext(true); + verify(aObserver, never()).onError(org.mockito.Matchers.any(Throwable.class)); + verify(aObserver, times(1)).onCompleted(); + } } diff --git a/rxjava-core/src/test/java/rx/operators/OperationAverageTest.java b/rxjava-core/src/test/java/rx/operators/OperationAverageTest.java index 6fa01dfc92..45e23bf2b9 100644 --- a/rxjava-core/src/test/java/rx/operators/OperationAverageTest.java +++ b/rxjava-core/src/test/java/rx/operators/OperationAverageTest.java @@ -1,7 +1,111 @@ package rx.operators; -import org.junit.Ignore; +import org.junit.Test; +import rx.Observable; +import rx.Observer; + +import static org.mockito.Matchers.any; +import static org.mockito.Matchers.anyDouble; +import static org.mockito.Matchers.anyFloat; +import static org.mockito.Matchers.anyInt; +import static org.mockito.Matchers.anyLong; +import static org.mockito.Mockito.*; +import static rx.operators.OperationAverage.*; + -@Ignore("WIP") public class OperationAverageTest { + + @SuppressWarnings("unchecked") + Observer w = mock(Observer.class); + @SuppressWarnings("unchecked") + Observer wl = mock(Observer.class); + @SuppressWarnings("unchecked") + Observer wf = mock(Observer.class); + @SuppressWarnings("unchecked") + Observer wd = mock(Observer.class); + + @Test + public void testAverageOfAFewInts() throws Throwable { + Observable src = Observable.from(1, 2, 3, 4, 6); + average(src).subscribe(w); + + verify(w, times(1)).onNext(anyInt()); + verify(w).onNext(3); + verify(w, never()).onError(any(Throwable.class)); + verify(w, times(1)).onCompleted(); + } + + @Test + public void testEmptyAverage() throws Throwable { + Observable src = Observable.empty(); + average(src).subscribe(w); + + verify(w, never()).onNext(anyInt()); + verify(w, times(1)).onError(any(ArithmeticException.class)); + verify(w, never()).onCompleted(); + } + + @Test + public void testAverageOfAFewLongs() throws Throwable { + Observable src = Observable.from(1L, 2L, 3L, 4L, 6L); + averageLongs(src).subscribe(wl); + + verify(wl, times(1)).onNext(anyLong()); + verify(wl).onNext(3L); + verify(wl, never()).onError(any(Throwable.class)); + verify(wl, times(1)).onCompleted(); + } + + @Test + public void testEmptyAverageLongs() throws Throwable { + Observable src = Observable.empty(); + averageLongs(src).subscribe(wl); + + verify(wl, never()).onNext(anyLong()); + verify(wl, times(1)).onError(any(ArithmeticException.class)); + verify(wl, never()).onCompleted(); + } + + @Test + public void testAverageOfAFewFloats() throws Throwable { + Observable src = Observable.from(1.0f, 2.0f); + averageFloats(src).subscribe(wf); + + verify(wf, times(1)).onNext(anyFloat()); + verify(wf).onNext(1.5f); + verify(wf, never()).onError(any(Throwable.class)); + verify(wf, times(1)).onCompleted(); + } + + + @Test + public void testEmptyAverageFloats() throws Throwable { + Observable src = Observable.empty(); + averageFloats(src).subscribe(wf); + + verify(wf, never()).onNext(anyFloat()); + verify(wf, times(1)).onError(any(ArithmeticException.class)); + verify(wf, never()).onCompleted(); + } + + @Test + public void testAverageOfAFewDoubles() throws Throwable { + Observable src = Observable.from(1.0d, 2.0d); + averageDoubles(src).subscribe(wd); + + verify(wd, times(1)).onNext(anyDouble()); + verify(wd).onNext(1.5d); + verify(wd, never()).onError(any(Throwable.class)); + verify(wd, times(1)).onCompleted(); + } + + @Test + public void testEmptyAverageDoubles() throws Throwable { + Observable src = Observable.empty(); + averageDoubles(src).subscribe(wd); + + verify(wd, never()).onNext(anyDouble()); + verify(wd, times(1)).onError(any(ArithmeticException.class)); + verify(wd, never()).onCompleted(); + } } diff --git a/rxjava-core/src/test/java/rx/operators/OperationBufferTest.java b/rxjava-core/src/test/java/rx/operators/OperationBufferTest.java index d096cd666a..fdc44e4014 100644 --- a/rxjava-core/src/test/java/rx/operators/OperationBufferTest.java +++ b/rxjava-core/src/test/java/rx/operators/OperationBufferTest.java @@ -1,7 +1,350 @@ package rx.operators; -import org.junit.Ignore; +import org.junit.Before; +import org.junit.Test; +import org.mockito.InOrder; +import org.mockito.Mockito; +import rx.Observable; +import rx.Observer; +import rx.Subscription; +import rx.concurrency.TestScheduler; +import rx.subscriptions.Subscriptions; +import rx.util.Closing; +import rx.util.Closings; +import rx.util.Opening; +import rx.util.Openings; +import rx.util.functions.Action0; +import rx.util.functions.Action1; +import rx.util.functions.Func0; +import rx.util.functions.Func1; + +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; + +import static org.junit.Assert.assertFalse; +import static rx.operators.OperationBuffer.buffer; -@Ignore("WIP") public class OperationBufferTest { + + private Observer> observer; + private TestScheduler scheduler; + + @Before + @SuppressWarnings("unchecked") + public void before() { + observer = Mockito.mock(Observer.class); + scheduler = new TestScheduler(); + } + + @Test + public void testComplete() { + Observable source = Observable.create(new Observable.OnSubscribeFunc() { + @Override + public Subscription onSubscribe(Observer observer) { + observer.onCompleted(); + return Subscriptions.empty(); + } + }); + + Observable> buffered = Observable.create(buffer(source, 3, 3)); + buffered.subscribe(observer); + + Mockito.verify(observer, Mockito.never()).onNext(Mockito.anyListOf(String.class)); + Mockito.verify(observer, Mockito.never()).onError(Mockito.any(Throwable.class)); + Mockito.verify(observer, Mockito.times(1)).onCompleted(); + } + + @Test + public void testSkipAndCountOverlappingBuffers() { + Observable source = Observable.create(new Observable.OnSubscribeFunc() { + @Override + public Subscription onSubscribe(Observer observer) { + observer.onNext("one"); + observer.onNext("two"); + observer.onNext("three"); + observer.onNext("four"); + observer.onNext("five"); + return Subscriptions.empty(); + } + }); + + Observable> buffered = Observable.create(buffer(source, 3, 1)); + buffered.subscribe(observer); + + InOrder inOrder = Mockito.inOrder(observer); + inOrder.verify(observer, Mockito.times(1)).onNext(list("one", "two", "three")); + inOrder.verify(observer, Mockito.times(1)).onNext(list("two", "three", "four")); + inOrder.verify(observer, Mockito.times(1)).onNext(list("three", "four", "five")); + inOrder.verify(observer, Mockito.never()).onNext(Mockito.anyListOf(String.class)); + inOrder.verify(observer, Mockito.never()).onError(Mockito.any(Throwable.class)); + inOrder.verify(observer, Mockito.never()).onCompleted(); + } + + @Test + public void testSkipAndCountGaplessBuffers() { + Observable source = Observable.create(new Observable.OnSubscribeFunc() { + @Override + public Subscription onSubscribe(Observer observer) { + observer.onNext("one"); + observer.onNext("two"); + observer.onNext("three"); + observer.onNext("four"); + observer.onNext("five"); + observer.onCompleted(); + return Subscriptions.empty(); + } + }); + + Observable> buffered = Observable.create(buffer(source, 3, 3)); + buffered.subscribe(observer); + + InOrder inOrder = Mockito.inOrder(observer); + inOrder.verify(observer, Mockito.times(1)).onNext(list("one", "two", "three")); + inOrder.verify(observer, Mockito.times(1)).onNext(list("four", "five")); + inOrder.verify(observer, Mockito.never()).onNext(Mockito.anyListOf(String.class)); + inOrder.verify(observer, Mockito.never()).onError(Mockito.any(Throwable.class)); + inOrder.verify(observer, Mockito.times(1)).onCompleted(); + } + + @Test + public void testSkipAndCountBuffersWithGaps() { + Observable source = Observable.create(new Observable.OnSubscribeFunc() { + @Override + public Subscription onSubscribe(Observer observer) { + observer.onNext("one"); + observer.onNext("two"); + observer.onNext("three"); + observer.onNext("four"); + observer.onNext("five"); + observer.onCompleted(); + return Subscriptions.empty(); + } + }); + + Observable> buffered = Observable.create(buffer(source, 2, 3)); + buffered.subscribe(observer); + + InOrder inOrder = Mockito.inOrder(observer); + inOrder.verify(observer, Mockito.times(1)).onNext(list("one", "two")); + inOrder.verify(observer, Mockito.times(1)).onNext(list("four", "five")); + inOrder.verify(observer, Mockito.never()).onNext(Mockito.anyListOf(String.class)); + inOrder.verify(observer, Mockito.never()).onError(Mockito.any(Throwable.class)); + inOrder.verify(observer, Mockito.times(1)).onCompleted(); + } + + @Test + public void testTimedAndCount() { + Observable source = Observable.create(new Observable.OnSubscribeFunc() { + @Override + public Subscription onSubscribe(Observer observer) { + push(observer, "one", 10); + push(observer, "two", 90); + push(observer, "three", 110); + push(observer, "four", 190); + push(observer, "five", 210); + complete(observer, 250); + return Subscriptions.empty(); + } + }); + + Observable> buffered = Observable.create(buffer(source, 100, TimeUnit.MILLISECONDS, 2, scheduler)); + buffered.subscribe(observer); + + InOrder inOrder = Mockito.inOrder(observer); + scheduler.advanceTimeTo(100, TimeUnit.MILLISECONDS); + inOrder.verify(observer, Mockito.times(1)).onNext(list("one", "two")); + + scheduler.advanceTimeTo(200, TimeUnit.MILLISECONDS); + inOrder.verify(observer, Mockito.times(1)).onNext(list("three", "four")); + + scheduler.advanceTimeTo(300, TimeUnit.MILLISECONDS); + inOrder.verify(observer, Mockito.times(1)).onNext(list("five")); + inOrder.verify(observer, Mockito.never()).onNext(Mockito.anyListOf(String.class)); + inOrder.verify(observer, Mockito.never()).onError(Mockito.any(Throwable.class)); + inOrder.verify(observer, Mockito.times(1)).onCompleted(); + } + + @Test + public void testTimed() { + Observable source = Observable.create(new Observable.OnSubscribeFunc() { + @Override + public Subscription onSubscribe(Observer observer) { + push(observer, "one", 98); + push(observer, "two", 99); + push(observer, "three", 100); + push(observer, "four", 101); + push(observer, "five", 102); + complete(observer, 150); + return Subscriptions.empty(); + } + }); + + Observable> buffered = Observable.create(buffer(source, 100, TimeUnit.MILLISECONDS, scheduler)); + buffered.subscribe(observer); + + InOrder inOrder = Mockito.inOrder(observer); + scheduler.advanceTimeTo(101, TimeUnit.MILLISECONDS); + inOrder.verify(observer, Mockito.times(1)).onNext(list("one", "two", "three")); + + scheduler.advanceTimeTo(201, TimeUnit.MILLISECONDS); + inOrder.verify(observer, Mockito.times(1)).onNext(list("four", "five")); + inOrder.verify(observer, Mockito.never()).onNext(Mockito.anyListOf(String.class)); + inOrder.verify(observer, Mockito.never()).onError(Mockito.any(Throwable.class)); + inOrder.verify(observer, Mockito.times(1)).onCompleted(); + } + + @Test + public void testObservableBasedOpenerAndCloser() { + Observable source = Observable.create(new Observable.OnSubscribeFunc() { + @Override + public Subscription onSubscribe(Observer observer) { + push(observer, "one", 10); + push(observer, "two", 60); + push(observer, "three", 110); + push(observer, "four", 160); + push(observer, "five", 210); + complete(observer, 500); + return Subscriptions.empty(); + } + }); + + Observable openings = Observable.create(new Observable.OnSubscribeFunc() { + @Override + public Subscription onSubscribe(Observer observer) { + push(observer, Openings.create(), 50); + push(observer, Openings.create(), 200); + complete(observer, 250); + return Subscriptions.empty(); + } + }); + + Func1> closer = new Func1>() { + @Override + public Observable call(Opening opening) { + return Observable.create(new Observable.OnSubscribeFunc() { + @Override + public Subscription onSubscribe(Observer observer) { + push(observer, Closings.create(), 100); + complete(observer, 101); + return Subscriptions.empty(); + } + }); + } + }; + + Observable> buffered = Observable.create(buffer(source, openings, closer)); + buffered.subscribe(observer); + + InOrder inOrder = Mockito.inOrder(observer); + scheduler.advanceTimeTo(500, TimeUnit.MILLISECONDS); + inOrder.verify(observer, Mockito.times(1)).onNext(list("two", "three")); + inOrder.verify(observer, Mockito.times(1)).onNext(list("five")); + inOrder.verify(observer, Mockito.never()).onNext(Mockito.anyListOf(String.class)); + inOrder.verify(observer, Mockito.never()).onError(Mockito.any(Throwable.class)); + inOrder.verify(observer, Mockito.times(1)).onCompleted(); + } + + @Test + public void testObservableBasedCloser() { + Observable source = Observable.create(new Observable.OnSubscribeFunc() { + @Override + public Subscription onSubscribe(Observer observer) { + push(observer, "one", 10); + push(observer, "two", 60); + push(observer, "three", 110); + push(observer, "four", 160); + push(observer, "five", 210); + complete(observer, 250); + return Subscriptions.empty(); + } + }); + + Func0> closer = new Func0>() { + @Override + public Observable call() { + return Observable.create(new Observable.OnSubscribeFunc() { + @Override + public Subscription onSubscribe(Observer observer) { + push(observer, Closings.create(), 100); + complete(observer, 101); + return Subscriptions.empty(); + } + }); + } + }; + + Observable> buffered = Observable.create(buffer(source, closer)); + buffered.subscribe(observer); + + InOrder inOrder = Mockito.inOrder(observer); + scheduler.advanceTimeTo(500, TimeUnit.MILLISECONDS); + inOrder.verify(observer, Mockito.times(1)).onNext(list("one", "two")); + inOrder.verify(observer, Mockito.times(1)).onNext(list("three", "four")); + inOrder.verify(observer, Mockito.times(1)).onNext(list("five")); + inOrder.verify(observer, Mockito.never()).onNext(Mockito.anyListOf(String.class)); + inOrder.verify(observer, Mockito.never()).onError(Mockito.any(Throwable.class)); + inOrder.verify(observer, Mockito.times(1)).onCompleted(); + } + + @Test + public void testLongTimeAction() throws InterruptedException { + final CountDownLatch latch = new CountDownLatch(1); + LongTimeAction action = new LongTimeAction(latch); + Observable.from(1).buffer(10, TimeUnit.MILLISECONDS, 10) + .subscribe(action); + latch.await(); + assertFalse(action.fail); + } + + private static class LongTimeAction implements Action1> { + + CountDownLatch latch; + boolean fail = false; + + public LongTimeAction(CountDownLatch latch) { + this.latch = latch; + } + + @Override + public void call(List t1) { + try { + if (fail) { + return; + } + Thread.sleep(200); + } catch (InterruptedException e) { + fail = true; + } finally { + latch.countDown(); + } + } + } + + private List list(String... args) { + List list = new ArrayList(); + for (String arg : args) { + list.add(arg); + } + return list; + } + + private void push(final Observer observer, final T value, int delay) { + scheduler.schedule(new Action0() { + @Override + public void call() { + observer.onNext(value); + } + }, delay, TimeUnit.MILLISECONDS); + } + + private void complete(final Observer observer, int delay) { + scheduler.schedule(new Action0() { + @Override + public void call() { + observer.onCompleted(); + } + }, delay, TimeUnit.MILLISECONDS); + } } diff --git a/rxjava-core/src/test/java/rx/operators/OperationCacheTest.java b/rxjava-core/src/test/java/rx/operators/OperationCacheTest.java index 4a754528e5..9f9ab051a1 100644 --- a/rxjava-core/src/test/java/rx/operators/OperationCacheTest.java +++ b/rxjava-core/src/test/java/rx/operators/OperationCacheTest.java @@ -1,7 +1,72 @@ package rx.operators; -import org.junit.Ignore; +import org.junit.Test; +import rx.Observable; +import rx.Observer; +import rx.Subscription; +import rx.subscriptions.BooleanSubscription; +import rx.util.functions.Action1; + +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicInteger; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.fail; +import static rx.operators.OperationCache.cache; -@Ignore("WIP") public class OperationCacheTest { + + @Test + public void testCache() throws InterruptedException { + final AtomicInteger counter = new AtomicInteger(); + Observable o = Observable.create(cache(Observable.create(new Observable.OnSubscribeFunc() { + + @Override + public Subscription onSubscribe(final Observer observer) { + final BooleanSubscription subscription = new BooleanSubscription(); + new Thread(new Runnable() { + + @Override + public void run() { + counter.incrementAndGet(); + System.out.println("published observable being executed"); + observer.onNext("one"); + observer.onCompleted(); + } + }).start(); + return subscription; + } + }))); + + // we then expect the following 2 subscriptions to get that same value + final CountDownLatch latch = new CountDownLatch(2); + + // subscribe once + o.subscribe(new Action1() { + + @Override + public void call(String v) { + assertEquals("one", v); + System.out.println("v: " + v); + latch.countDown(); + } + }); + + // subscribe again + o.subscribe(new Action1() { + + @Override + public void call(String v) { + assertEquals("one", v); + System.out.println("v: " + v); + latch.countDown(); + } + }); + + if (!latch.await(1000, TimeUnit.MILLISECONDS)) { + fail("subscriptions did not receive values"); + } + assertEquals(1, counter.get()); + } } diff --git a/rxjava-core/src/test/java/rx/operators/OperationCastTest.java b/rxjava-core/src/test/java/rx/operators/OperationCastTest.java index 36bab268ff..1a87c915fc 100644 --- a/rxjava-core/src/test/java/rx/operators/OperationCastTest.java +++ b/rxjava-core/src/test/java/rx/operators/OperationCastTest.java @@ -1,7 +1,40 @@ package rx.operators; -import org.junit.Ignore; +import org.junit.Test; +import rx.Observable; +import rx.Observer; + +import static org.mockito.Mockito.*; +import static rx.operators.OperationCast.cast; -@Ignore("WIP") public class OperationCastTest { + + @Test + public void testCast() { + Observable source = Observable.from(1, 2); + Observable observable = Observable.create(cast(source, + Integer.class)); + + @SuppressWarnings("unchecked") + Observer aObserver = mock(Observer.class); + observable.subscribe(aObserver); + verify(aObserver, times(1)).onNext(1); + verify(aObserver, times(1)).onNext(1); + verify(aObserver, never()).onError( + org.mockito.Matchers.any(Throwable.class)); + verify(aObserver, times(1)).onCompleted(); + } + + @Test + public void testCastWithWrongType() { + Observable source = Observable.from(1, 2); + Observable observable = Observable.create(cast(source, + Boolean.class)); + + @SuppressWarnings("unchecked") + Observer aObserver = mock(Observer.class); + observable.subscribe(aObserver); + verify(aObserver, times(1)).onError( + org.mockito.Matchers.any(ClassCastException.class)); + } } diff --git a/rxjava-core/src/test/java/rx/operators/OperationCombineLatestTest.java b/rxjava-core/src/test/java/rx/operators/OperationCombineLatestTest.java index b154ce1223..b7ea62a8fd 100644 --- a/rxjava-core/src/test/java/rx/operators/OperationCombineLatestTest.java +++ b/rxjava-core/src/test/java/rx/operators/OperationCombineLatestTest.java @@ -1,7 +1,619 @@ package rx.operators; -import org.junit.Ignore; +import org.junit.Test; +import org.mockito.InOrder; +import org.mockito.Matchers; +import rx.Observable; +import rx.Observer; +import rx.Subscription; +import rx.subscriptions.Subscriptions; +import rx.util.functions.Func2; +import rx.util.functions.Func3; +import rx.util.functions.FuncN; + +import java.util.Arrays; + +import static org.mockito.Matchers.any; +import static org.mockito.Matchers.anyString; +import static org.mockito.Mockito.*; +import static rx.operators.OperationCombineLatest.Aggregator; +import static rx.operators.OperationCombineLatest.CombineObserver; +import static rx.operators.OperationCombineLatest.combineLatest; -@Ignore("WIP") public class OperationCombineLatestTest { + + @Test + public void testCombineLatestWithFunctionThatThrowsAnException() { + @SuppressWarnings("unchecked") // mock calls don't do generics + Observer w = mock(Observer.class); + + TestObservable w1 = new TestObservable(); + TestObservable w2 = new TestObservable(); + + Observable combined = Observable.create(combineLatest(Observable.create(w1), Observable.create(w2), new Func2() { + @Override + public String call(String v1, String v2) { + throw new RuntimeException("I don't work."); + } + })); + combined.subscribe(w); + + w1.observer.onNext("first value of w1"); + w2.observer.onNext("first value of w2"); + + verify(w, never()).onNext(anyString()); + verify(w, never()).onCompleted(); + verify(w, times(1)).onError(Matchers.any()); + } + + @Test + public void testCombineLatestDifferentLengthObservableSequences1() { + @SuppressWarnings("unchecked") // mock calls don't do generics + Observer w = mock(Observer.class); + + TestObservable w1 = new TestObservable(); + TestObservable w2 = new TestObservable(); + TestObservable w3 = new TestObservable(); + + Observable combineLatestW = Observable.create(combineLatest(Observable.create(w1), Observable.create(w2), Observable.create(w3), getConcat3StringsCombineLatestFunction())); + combineLatestW.subscribe(w); + + /* simulate sending data */ + // once for w1 + w1.observer.onNext("1a"); + w2.observer.onNext("2a"); + w3.observer.onNext("3a"); + w1.observer.onCompleted(); + // twice for w2 + w2.observer.onNext("2b"); + w2.observer.onCompleted(); + // 4 times for w3 + w3.observer.onNext("3b"); + w3.observer.onNext("3c"); + w3.observer.onNext("3d"); + w3.observer.onCompleted(); + + /* we should have been called 4 times on the Observer */ + InOrder inOrder = inOrder(w); + inOrder.verify(w).onNext("1a2a3a"); + inOrder.verify(w).onNext("1a2b3a"); + inOrder.verify(w).onNext("1a2b3b"); + inOrder.verify(w).onNext("1a2b3c"); + inOrder.verify(w).onNext("1a2b3d"); + inOrder.verify(w, never()).onNext(anyString()); + inOrder.verify(w, times(1)).onCompleted(); + } + + @Test + public void testCombineLatestDifferentLengthObservableSequences2() { + @SuppressWarnings("unchecked") + Observer w = mock(Observer.class); + + TestObservable w1 = new TestObservable(); + TestObservable w2 = new TestObservable(); + TestObservable w3 = new TestObservable(); + + Observable combineLatestW = Observable.create(combineLatest(Observable.create(w1), Observable.create(w2), Observable.create(w3), getConcat3StringsCombineLatestFunction())); + combineLatestW.subscribe(w); + + /* simulate sending data */ + // 4 times for w1 + w1.observer.onNext("1a"); + w1.observer.onNext("1b"); + w1.observer.onNext("1c"); + w1.observer.onNext("1d"); + w1.observer.onCompleted(); + // twice for w2 + w2.observer.onNext("2a"); + w2.observer.onNext("2b"); + w2.observer.onCompleted(); + // 1 times for w3 + w3.observer.onNext("3a"); + w3.observer.onCompleted(); + + /* we should have been called 1 time only on the Observer since we only combine the "latest" we don't go back and loop through others once completed */ + InOrder inOrder = inOrder(w); + inOrder.verify(w, times(1)).onNext("1d2b3a"); + inOrder.verify(w, never()).onNext(anyString()); + + inOrder.verify(w, times(1)).onCompleted(); + + } + + @Test + public void testCombineLatestWithInterleavingSequences() { + @SuppressWarnings("unchecked") + Observer w = mock(Observer.class); + + TestObservable w1 = new TestObservable(); + TestObservable w2 = new TestObservable(); + TestObservable w3 = new TestObservable(); + + Observable combineLatestW = Observable.create(combineLatest(Observable.create(w1), Observable.create(w2), Observable.create(w3), getConcat3StringsCombineLatestFunction())); + combineLatestW.subscribe(w); + + /* simulate sending data */ + w1.observer.onNext("1a"); + w2.observer.onNext("2a"); + w2.observer.onNext("2b"); + w3.observer.onNext("3a"); + + w1.observer.onNext("1b"); + w2.observer.onNext("2c"); + w2.observer.onNext("2d"); + w3.observer.onNext("3b"); + + w1.observer.onCompleted(); + w2.observer.onCompleted(); + w3.observer.onCompleted(); + + /* we should have been called 5 times on the Observer */ + InOrder inOrder = inOrder(w); + inOrder.verify(w).onNext("1a2b3a"); + inOrder.verify(w).onNext("1b2b3a"); + inOrder.verify(w).onNext("1b2c3a"); + inOrder.verify(w).onNext("1b2d3a"); + inOrder.verify(w).onNext("1b2d3b"); + + inOrder.verify(w, never()).onNext(anyString()); + inOrder.verify(w, times(1)).onCompleted(); + } + + /** + * Testing internal private logic due to the complexity so I want to use TDD to test as a I build it rather than relying purely on the overall functionality expected by the public methods. + */ + @SuppressWarnings("unchecked") + /* mock calls don't do generics */ + @Test + public void testAggregatorSimple() { + FuncN combineLatestFunction = getConcatCombineLatestFunction(); + /* create the aggregator which will execute the combineLatest function when all Observables provide values */ + Aggregator a = new Aggregator(combineLatestFunction); + + /* define a Observer to receive aggregated events */ + Observer aObserver = mock(Observer.class); + Observable.create(a).subscribe(aObserver); + + /* mock the Observable Observers that are 'pushing' data for us */ + CombineObserver r1 = mock(CombineObserver.class); + CombineObserver r2 = mock(CombineObserver.class); + + /* pretend we're starting up */ + a.addObserver(r1); + a.addObserver(r2); + + /* simulate the Observables pushing data into the aggregator */ + a.next(r1, "hello"); + a.next(r2, "world"); + + InOrder inOrder = inOrder(aObserver); + + verify(aObserver, never()).onError(any(Throwable.class)); + verify(aObserver, never()).onCompleted(); + inOrder.verify(aObserver, times(1)).onNext("helloworld"); + + a.next(r1, "hello "); + a.next(r2, "again"); + + verify(aObserver, never()).onError(any(Throwable.class)); + verify(aObserver, never()).onCompleted(); + inOrder.verify(aObserver, times(1)).onNext("hello again"); + + a.complete(r1); + a.complete(r2); + + inOrder.verify(aObserver, never()).onNext(anyString()); + verify(aObserver, times(1)).onCompleted(); + } + + @SuppressWarnings("unchecked") + /* mock calls don't do generics */ + @Test + public void testAggregatorDifferentSizedResultsWithOnComplete() { + FuncN combineLatestFunction = getConcatCombineLatestFunction(); + /* create the aggregator which will execute the combineLatest function when all Observables provide values */ + Aggregator a = new Aggregator(combineLatestFunction); + + /* define a Observer to receive aggregated events */ + Observer aObserver = mock(Observer.class); + Observable.create(a).subscribe(aObserver); + + /* mock the Observable Observers that are 'pushing' data for us */ + CombineObserver r1 = mock(CombineObserver.class); + CombineObserver r2 = mock(CombineObserver.class); + + /* pretend we're starting up */ + a.addObserver(r1); + a.addObserver(r2); + + /* simulate the Observables pushing data into the aggregator */ + a.next(r1, "hello"); + a.next(r2, "world"); + a.complete(r2); + + verify(aObserver, never()).onError(any(Throwable.class)); + verify(aObserver, never()).onCompleted(); + verify(aObserver, times(1)).onNext("helloworld"); + + a.next(r1, "hi"); + a.complete(r1); + + verify(aObserver, never()).onError(any(Throwable.class)); + verify(aObserver, times(1)).onCompleted(); + verify(aObserver, times(1)).onNext("hiworld"); + } + + @SuppressWarnings("unchecked") + /* mock calls don't do generics */ + @Test + public void testAggregateMultipleTypes() { + FuncN combineLatestFunction = getConcatCombineLatestFunction(); + /* create the aggregator which will execute the combineLatest function when all Observables provide values */ + Aggregator a = new Aggregator(combineLatestFunction); + + /* define a Observer to receive aggregated events */ + Observer aObserver = mock(Observer.class); + Observable.create(a).subscribe(aObserver); + + /* mock the Observable Observers that are 'pushing' data for us */ + CombineObserver r1 = mock(CombineObserver.class); + CombineObserver r2 = mock(CombineObserver.class); + + /* pretend we're starting up */ + a.addObserver(r1); + a.addObserver(r2); + + /* simulate the Observables pushing data into the aggregator */ + a.next(r1, "hello"); + a.next(r2, "world"); + a.complete(r2); + + verify(aObserver, never()).onError(any(Throwable.class)); + verify(aObserver, never()).onCompleted(); + verify(aObserver, times(1)).onNext("helloworld"); + + a.next(r1, "hi"); + a.complete(r1); + + verify(aObserver, never()).onError(any(Throwable.class)); + verify(aObserver, times(1)).onCompleted(); + verify(aObserver, times(1)).onNext("hiworld"); + } + + @SuppressWarnings("unchecked") + /* mock calls don't do generics */ + @Test + public void testAggregate3Types() { + FuncN combineLatestFunction = getConcatCombineLatestFunction(); + /* create the aggregator which will execute the combineLatest function when all Observables provide values */ + Aggregator a = new Aggregator(combineLatestFunction); + + /* define a Observer to receive aggregated events */ + Observer aObserver = mock(Observer.class); + Observable.create(a).subscribe(aObserver); + + /* mock the Observable Observers that are 'pushing' data for us */ + CombineObserver r1 = mock(CombineObserver.class); + CombineObserver r2 = mock(CombineObserver.class); + CombineObserver r3 = mock(CombineObserver.class); + + /* pretend we're starting up */ + a.addObserver(r1); + a.addObserver(r2); + a.addObserver(r3); + + /* simulate the Observables pushing data into the aggregator */ + a.next(r1, "hello"); + a.next(r2, 2); + a.next(r3, new int[]{5, 6, 7}); + + verify(aObserver, never()).onError(any(Throwable.class)); + verify(aObserver, never()).onCompleted(); + verify(aObserver, times(1)).onNext("hello2[5, 6, 7]"); + } + + @SuppressWarnings("unchecked") + /* mock calls don't do generics */ + @Test + public void testAggregatorsWithDifferentSizesAndTiming() { + FuncN combineLatestFunction = getConcatCombineLatestFunction(); + /* create the aggregator which will execute the combineLatest function when all Observables provide values */ + Aggregator a = new Aggregator(combineLatestFunction); + + /* define a Observer to receive aggregated events */ + Observer aObserver = mock(Observer.class); + Observable.create(a).subscribe(aObserver); + + /* mock the Observable Observers that are 'pushing' data for us */ + CombineObserver r1 = mock(CombineObserver.class); + CombineObserver r2 = mock(CombineObserver.class); + + /* pretend we're starting up */ + a.addObserver(r1); + a.addObserver(r2); + + /* simulate the Observables pushing data into the aggregator */ + a.next(r1, "one"); + a.next(r1, "two"); + a.next(r1, "three"); + a.next(r2, "A"); + + verify(aObserver, never()).onError(any(Throwable.class)); + verify(aObserver, never()).onCompleted(); + verify(aObserver, times(1)).onNext("threeA"); + + a.next(r1, "four"); + a.complete(r1); + a.next(r2, "B"); + verify(aObserver, times(1)).onNext("fourB"); + a.next(r2, "C"); + verify(aObserver, times(1)).onNext("fourC"); + a.next(r2, "D"); + verify(aObserver, times(1)).onNext("fourD"); + a.next(r2, "E"); + verify(aObserver, times(1)).onNext("fourE"); + a.complete(r2); + + verify(aObserver, never()).onError(any(Throwable.class)); + verify(aObserver, times(1)).onCompleted(); + } + + @SuppressWarnings("unchecked") + /* mock calls don't do generics */ + @Test + public void testAggregatorError() { + FuncN combineLatestFunction = getConcatCombineLatestFunction(); + /* create the aggregator which will execute the combineLatest function when all Observables provide values */ + Aggregator a = new Aggregator(combineLatestFunction); + + /* define a Observer to receive aggregated events */ + Observer aObserver = mock(Observer.class); + Observable.create(a).subscribe(aObserver); + + /* mock the Observable Observers that are 'pushing' data for us */ + CombineObserver r1 = mock(CombineObserver.class); + CombineObserver r2 = mock(CombineObserver.class); + + /* pretend we're starting up */ + a.addObserver(r1); + a.addObserver(r2); + + /* simulate the Observables pushing data into the aggregator */ + a.next(r1, "hello"); + a.next(r2, "world"); + + verify(aObserver, never()).onError(any(Throwable.class)); + verify(aObserver, never()).onCompleted(); + verify(aObserver, times(1)).onNext("helloworld"); + + a.error(new RuntimeException("")); + a.next(r1, "hello"); + a.next(r2, "again"); + + verify(aObserver, times(1)).onError(any(Throwable.class)); + verify(aObserver, never()).onCompleted(); + // we don't want to be called again after an error + verify(aObserver, times(0)).onNext("helloagain"); + } + + @SuppressWarnings("unchecked") + /* mock calls don't do generics */ + @Test + public void testAggregatorUnsubscribe() { + FuncN combineLatestFunction = getConcatCombineLatestFunction(); + /* create the aggregator which will execute the combineLatest function when all Observables provide values */ + Aggregator a = new Aggregator(combineLatestFunction); + + /* define a Observer to receive aggregated events */ + Observer aObserver = mock(Observer.class); + Subscription subscription = Observable.create(a).subscribe(aObserver); + + /* mock the Observable Observers that are 'pushing' data for us */ + CombineObserver r1 = mock(CombineObserver.class); + CombineObserver r2 = mock(CombineObserver.class); + + /* pretend we're starting up */ + a.addObserver(r1); + a.addObserver(r2); + + /* simulate the Observables pushing data into the aggregator */ + a.next(r1, "hello"); + a.next(r2, "world"); + + verify(aObserver, never()).onError(any(Throwable.class)); + verify(aObserver, never()).onCompleted(); + verify(aObserver, times(1)).onNext("helloworld"); + + subscription.unsubscribe(); + a.next(r1, "hello"); + a.next(r2, "again"); + + verify(aObserver, times(0)).onError(any(Throwable.class)); + verify(aObserver, never()).onCompleted(); + // we don't want to be called again after an error + verify(aObserver, times(0)).onNext("helloagain"); + } + + @SuppressWarnings("unchecked") + /* mock calls don't do generics */ + @Test + public void testAggregatorEarlyCompletion() { + FuncN combineLatestFunction = getConcatCombineLatestFunction(); + /* create the aggregator which will execute the combineLatest function when all Observables provide values */ + Aggregator a = new Aggregator(combineLatestFunction); + + /* define a Observer to receive aggregated events */ + Observer aObserver = mock(Observer.class); + Observable.create(a).subscribe(aObserver); + + /* mock the Observable Observers that are 'pushing' data for us */ + CombineObserver r1 = mock(CombineObserver.class); + CombineObserver r2 = mock(CombineObserver.class); + + /* pretend we're starting up */ + a.addObserver(r1); + a.addObserver(r2); + + /* simulate the Observables pushing data into the aggregator */ + a.next(r1, "one"); + a.next(r1, "two"); + a.complete(r1); + a.next(r2, "A"); + + InOrder inOrder = inOrder(aObserver); + + inOrder.verify(aObserver, never()).onError(any(Throwable.class)); + inOrder.verify(aObserver, never()).onCompleted(); + inOrder.verify(aObserver, times(1)).onNext("twoA"); + + a.complete(r2); + + inOrder.verify(aObserver, never()).onError(any(Throwable.class)); + inOrder.verify(aObserver, times(1)).onCompleted(); + // we shouldn't get this since completed is called before any other onNext calls could trigger this + inOrder.verify(aObserver, never()).onNext(anyString()); + } + + @SuppressWarnings("unchecked") + /* mock calls don't do generics */ + @Test + public void testCombineLatest2Types() { + Func2 combineLatestFunction = getConcatStringIntegerCombineLatestFunction(); + + /* define a Observer to receive aggregated events */ + Observer aObserver = mock(Observer.class); + + Observable w = Observable.create(combineLatest(Observable.from("one", "two"), Observable.from(2, 3, 4), combineLatestFunction)); + w.subscribe(aObserver); + + verify(aObserver, never()).onError(any(Throwable.class)); + verify(aObserver, times(1)).onCompleted(); + verify(aObserver, times(1)).onNext("two2"); + verify(aObserver, times(1)).onNext("two3"); + verify(aObserver, times(1)).onNext("two4"); + } + + @SuppressWarnings("unchecked") + /* mock calls don't do generics */ + @Test + public void testCombineLatest3TypesA() { + Func3 combineLatestFunction = getConcatStringIntegerIntArrayCombineLatestFunction(); + + /* define a Observer to receive aggregated events */ + Observer aObserver = mock(Observer.class); + + Observable w = Observable.create(combineLatest(Observable.from("one", "two"), Observable.from(2), Observable.from(new int[]{4, 5, 6}), combineLatestFunction)); + w.subscribe(aObserver); + + verify(aObserver, never()).onError(any(Throwable.class)); + verify(aObserver, times(1)).onCompleted(); + verify(aObserver, times(1)).onNext("two2[4, 5, 6]"); + } + + @SuppressWarnings("unchecked") + /* mock calls don't do generics */ + @Test + public void testCombineLatest3TypesB() { + Func3 combineLatestFunction = getConcatStringIntegerIntArrayCombineLatestFunction(); + + /* define a Observer to receive aggregated events */ + Observer aObserver = mock(Observer.class); + + Observable w = Observable.create(combineLatest(Observable.from("one"), Observable.from(2), Observable.from(new int[]{4, 5, 6}, new int[]{7, 8}), combineLatestFunction)); + w.subscribe(aObserver); + + verify(aObserver, never()).onError(any(Throwable.class)); + verify(aObserver, times(1)).onCompleted(); + verify(aObserver, times(1)).onNext("one2[4, 5, 6]"); + verify(aObserver, times(1)).onNext("one2[7, 8]"); + } + + private Func3 getConcat3StringsCombineLatestFunction() { + Func3 combineLatestFunction = new Func3() { + + @Override + public String call(String a1, String a2, String a3) { + if (a1 == null) { + a1 = ""; + } + if (a2 == null) { + a2 = ""; + } + if (a3 == null) { + a3 = ""; + } + return a1 + a2 + a3; + } + + }; + return combineLatestFunction; + } + + private FuncN getConcatCombineLatestFunction() { + FuncN combineLatestFunction = new FuncN() { + + @Override + public String call(Object... args) { + String returnValue = ""; + for (Object o : args) { + if (o != null) { + returnValue += getStringValue(o); + } + } + System.out.println("returning: " + returnValue); + return returnValue; + } + + }; + return combineLatestFunction; + } + + private Func2 getConcatStringIntegerCombineLatestFunction() { + Func2 combineLatestFunction = new Func2() { + + @Override + public String call(String s, Integer i) { + return getStringValue(s) + getStringValue(i); + } + + }; + return combineLatestFunction; + } + + private Func3 getConcatStringIntegerIntArrayCombineLatestFunction() { + Func3 combineLatestFunction = new Func3() { + + @Override + public String call(String s, Integer i, int[] iArray) { + return getStringValue(s) + getStringValue(i) + getStringValue(iArray); + } + + }; + return combineLatestFunction; + } + + private static String getStringValue(Object o) { + if (o == null) { + return ""; + } else { + if (o instanceof int[]) { + return Arrays.toString((int[]) o); + } else { + return String.valueOf(o); + } + } + } + + private static class TestObservable implements Observable.OnSubscribeFunc { + + Observer observer; + + @Override + public Subscription onSubscribe(Observer observer) { + // just store the variable where it can be accessed so we can manually trigger it + this.observer = observer; + return Subscriptions.empty(); + } + + } } diff --git a/rxjava-core/src/test/java/rx/operators/OperationConcatTest.java b/rxjava-core/src/test/java/rx/operators/OperationConcatTest.java index 1380ffcaef..35fc22bcc2 100644 --- a/rxjava-core/src/test/java/rx/operators/OperationConcatTest.java +++ b/rxjava-core/src/test/java/rx/operators/OperationConcatTest.java @@ -1,7 +1,544 @@ package rx.operators; -import org.junit.Ignore; +import org.junit.Test; +import org.mockito.InOrder; +import rx.Observable; +import rx.Observer; +import rx.Subscription; +import rx.subscriptions.BooleanSubscription; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicReference; + +import static org.junit.Assert.fail; +import static org.mockito.Matchers.any; +import static org.mockito.Matchers.anyString; +import static org.mockito.Mockito.*; +import static rx.operators.OperationConcat.concat; -@Ignore("WIP") public class OperationConcatTest { + + @Test + public void testConcat() { + @SuppressWarnings("unchecked") + Observer observer = mock(Observer.class); + + final String[] o = {"1", "3", "5", "7"}; + final String[] e = {"2", "4", "6"}; + + final Observable odds = Observable.from(o); + final Observable even = Observable.from(e); + + @SuppressWarnings("unchecked") + Observable concat = Observable.create(concat(odds, even)); + concat.subscribe(observer); + + verify(observer, times(7)).onNext(anyString()); + } + + @Test + public void testConcatWithList() { + @SuppressWarnings("unchecked") + Observer observer = mock(Observer.class); + + final String[] o = {"1", "3", "5", "7"}; + final String[] e = {"2", "4", "6"}; + + final Observable odds = Observable.from(o); + final Observable even = Observable.from(e); + final List> list = new ArrayList>(); + list.add(odds); + list.add(even); + Observable concat = Observable.create(concat(list)); + concat.subscribe(observer); + + verify(observer, times(7)).onNext(anyString()); + } + + @Test + public void testConcatObservableOfObservables() { + @SuppressWarnings("unchecked") + Observer observer = mock(Observer.class); + + final String[] o = {"1", "3", "5", "7"}; + final String[] e = {"2", "4", "6"}; + + final Observable odds = Observable.from(o); + final Observable even = Observable.from(e); + + Observable> observableOfObservables = Observable.create(new Observable.OnSubscribeFunc>() { + + @Override + public Subscription onSubscribe(Observer> observer) { + // simulate what would happen in an observable + observer.onNext(odds); + observer.onNext(even); + observer.onCompleted(); + + return new Subscription() { + + @Override + public void unsubscribe() { + // unregister ... will never be called here since we are executing synchronously + } + + }; + } + + }); + Observable concat = Observable.create(concat(observableOfObservables)); + + concat.subscribe(observer); + + verify(observer, times(7)).onNext(anyString()); + } + + /** + * Simple concat of 2 asynchronous observables ensuring it emits in correct order. + */ + @SuppressWarnings("unchecked") + @Test + public void testSimpleAsyncConcat() { + Observer observer = mock(Observer.class); + + TestObservable o1 = new TestObservable("one", "two", "three"); + TestObservable o2 = new TestObservable("four", "five", "six"); + + Observable.concat(Observable.create(o1), Observable.create(o2)).subscribe(observer); + + try { + // wait for async observables to complete + o1.t.join(); + o2.t.join(); + } catch (Throwable e) { + throw new RuntimeException("failed waiting on threads"); + } + + InOrder inOrder = inOrder(observer); + inOrder.verify(observer, times(1)).onNext("one"); + inOrder.verify(observer, times(1)).onNext("two"); + inOrder.verify(observer, times(1)).onNext("three"); + inOrder.verify(observer, times(1)).onNext("four"); + inOrder.verify(observer, times(1)).onNext("five"); + inOrder.verify(observer, times(1)).onNext("six"); + } + + /** + * Test an async Observable that emits more async Observables + */ + @SuppressWarnings("unchecked") + @Test + public void testNestedAsyncConcat() throws Throwable { + Observer observer = mock(Observer.class); + + final TestObservable o1 = new TestObservable("one", "two", "three"); + final TestObservable o2 = new TestObservable("four", "five", "six"); + final TestObservable o3 = new TestObservable("seven", "eight", "nine"); + final CountDownLatch allowThird = new CountDownLatch(1); + + final AtomicReference parent = new AtomicReference(); + Observable> observableOfObservables = Observable.create(new Observable.OnSubscribeFunc>() { + + @Override + public Subscription onSubscribe(final Observer> observer) { + final BooleanSubscription s = new BooleanSubscription(); + parent.set(new Thread(new Runnable() { + + @Override + public void run() { + try { + // emit first + if (!s.isUnsubscribed()) { + System.out.println("Emit o1"); + observer.onNext(Observable.create(o1)); + } + // emit second + if (!s.isUnsubscribed()) { + System.out.println("Emit o2"); + observer.onNext(Observable.create(o2)); + } + + // wait until sometime later and emit third + try { + allowThird.await(); + } catch (InterruptedException e) { + observer.onError(e); + } + if (!s.isUnsubscribed()) { + System.out.println("Emit o3"); + observer.onNext(Observable.create(o3)); + } + + } catch (Throwable e) { + observer.onError(e); + } finally { + System.out.println("Done parent Observable"); + observer.onCompleted(); + } + } + })); + parent.get().start(); + return s; + } + }); + + Observable.create(concat(observableOfObservables)).subscribe(observer); + + // wait for parent to start + while (parent.get() == null) { + Thread.sleep(1); + } + + try { + // wait for first 2 async observables to complete + while (o1.t == null) { + Thread.sleep(1); + } + System.out.println("Thread1 started ... waiting for it to complete ..."); + o1.t.join(); + while (o2.t == null) { + Thread.sleep(1); + } + System.out.println("Thread2 started ... waiting for it to complete ..."); + o2.t.join(); + } catch (Throwable e) { + throw new RuntimeException("failed waiting on threads", e); + } + + InOrder inOrder = inOrder(observer); + inOrder.verify(observer, times(1)).onNext("one"); + inOrder.verify(observer, times(1)).onNext("two"); + inOrder.verify(observer, times(1)).onNext("three"); + inOrder.verify(observer, times(1)).onNext("four"); + inOrder.verify(observer, times(1)).onNext("five"); + inOrder.verify(observer, times(1)).onNext("six"); + // we shouldn't have the following 3 yet + inOrder.verify(observer, never()).onNext("seven"); + inOrder.verify(observer, never()).onNext("eight"); + inOrder.verify(observer, never()).onNext("nine"); + // we should not be completed yet + verify(observer, never()).onCompleted(); + verify(observer, never()).onError(any(Throwable.class)); + + // now allow the third + allowThird.countDown(); + + try { + while (o3.t == null) { + Thread.sleep(1); + } + // wait for 3rd to complete + o3.t.join(); + } catch (Throwable e) { + throw new RuntimeException("failed waiting on threads", e); + } + + inOrder.verify(observer, times(1)).onNext("seven"); + inOrder.verify(observer, times(1)).onNext("eight"); + inOrder.verify(observer, times(1)).onNext("nine"); + + inOrder.verify(observer, times(1)).onCompleted(); + verify(observer, never()).onError(any(Throwable.class)); + } + + @SuppressWarnings("unchecked") + @Test + public void testBlockedObservableOfObservables() { + Observer observer = mock(Observer.class); + + final String[] o = {"1", "3", "5", "7"}; + final String[] e = {"2", "4", "6"}; + final Observable odds = Observable.from(o); + final Observable even = Observable.from(e); + final CountDownLatch callOnce = new CountDownLatch(1); + final CountDownLatch okToContinue = new CountDownLatch(1); + TestObservable> observableOfObservables = new TestObservable>(callOnce, okToContinue, odds, even); + Observable.OnSubscribeFunc concatF = concat(Observable.create(observableOfObservables)); + Observable concat = Observable.create(concatF); + concat.subscribe(observer); + try { + //Block main thread to allow observables to serve up o1. + callOnce.await(); + } catch (Throwable ex) { + ex.printStackTrace(); + fail(ex.getMessage()); + } + // The concated observable should have served up all of the odds. + verify(observer, times(1)).onNext("1"); + verify(observer, times(1)).onNext("3"); + verify(observer, times(1)).onNext("5"); + verify(observer, times(1)).onNext("7"); + + try { + // unblock observables so it can serve up o2 and complete + okToContinue.countDown(); + observableOfObservables.t.join(); + } catch (Throwable ex) { + ex.printStackTrace(); + fail(ex.getMessage()); + } + // The concatenated observable should now have served up all the evens. + verify(observer, times(1)).onNext("2"); + verify(observer, times(1)).onNext("4"); + verify(observer, times(1)).onNext("6"); + } + + @Test + public void testConcatConcurrentWithInfinity() { + final TestObservable w1 = new TestObservable("one", "two", "three"); + //This observable will send "hello" MAX_VALUE time. + final TestObservable w2 = new TestObservable("hello", Integer.MAX_VALUE); + + @SuppressWarnings("unchecked") + Observer aObserver = mock(Observer.class); + @SuppressWarnings("unchecked") + TestObservable> observableOfObservables = new TestObservable>(Observable.create(w1), Observable.create(w2)); + Observable.OnSubscribeFunc concatF = concat(Observable.create(observableOfObservables)); + + Observable concat = Observable.create(concatF); + + concat.take(50).subscribe(aObserver); + + //Wait for the thread to start up. + try { + Thread.sleep(25); + w1.t.join(); + w2.t.join(); + } catch (InterruptedException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + + InOrder inOrder = inOrder(aObserver); + inOrder.verify(aObserver, times(1)).onNext("one"); + inOrder.verify(aObserver, times(1)).onNext("two"); + inOrder.verify(aObserver, times(1)).onNext("three"); + inOrder.verify(aObserver, times(47)).onNext("hello"); + verify(aObserver, times(1)).onCompleted(); + verify(aObserver, never()).onError(any(Throwable.class)); + } + + @Test + public void testConcatNonBlockingObservables() { + + final CountDownLatch okToContinueW1 = new CountDownLatch(1); + final CountDownLatch okToContinueW2 = new CountDownLatch(1); + + final TestObservable w1 = new TestObservable(null, okToContinueW1, "one", "two", "three"); + final TestObservable w2 = new TestObservable(null, okToContinueW2, "four", "five", "six"); + + @SuppressWarnings("unchecked") + Observer aObserver = mock(Observer.class); + Observable> observableOfObservables = Observable.create(new Observable.OnSubscribeFunc>() { + + @Override + public Subscription onSubscribe(Observer> observer) { + // simulate what would happen in an observable + observer.onNext(Observable.create(w1)); + observer.onNext(Observable.create(w2)); + observer.onCompleted(); + + return new Subscription() { + + @Override + public void unsubscribe() { + } + + }; + } + + }); + Observable concat = Observable.create(concat(observableOfObservables)); + concat.subscribe(aObserver); + + verify(aObserver, times(0)).onCompleted(); + + try { + // release both threads + okToContinueW1.countDown(); + okToContinueW2.countDown(); + // wait for both to finish + w1.t.join(); + w2.t.join(); + } catch (InterruptedException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + + InOrder inOrder = inOrder(aObserver); + inOrder.verify(aObserver, times(1)).onNext("one"); + inOrder.verify(aObserver, times(1)).onNext("two"); + inOrder.verify(aObserver, times(1)).onNext("three"); + inOrder.verify(aObserver, times(1)).onNext("four"); + inOrder.verify(aObserver, times(1)).onNext("five"); + inOrder.verify(aObserver, times(1)).onNext("six"); + verify(aObserver, times(1)).onCompleted(); + + } + + /** + * Test unsubscribing the concatenated Observable in a single thread. + */ + @Test + public void testConcatUnsubscribe() { + final CountDownLatch callOnce = new CountDownLatch(1); + final CountDownLatch okToContinue = new CountDownLatch(1); + final TestObservable w1 = new TestObservable("one", "two", "three"); + final TestObservable w2 = new TestObservable(callOnce, okToContinue, "four", "five", "six"); + + @SuppressWarnings("unchecked") + final Observer aObserver = mock(Observer.class); + @SuppressWarnings("unchecked") + final Observable concat = Observable.create(concat(Observable.create(w1), Observable.create(w2))); + final SafeObservableSubscription s1 = new SafeObservableSubscription(); + + try { + // Subscribe + s1.wrap(concat.subscribe(aObserver)); + //Block main thread to allow observable "w1" to complete and observable "w2" to call onNext once. + callOnce.await(); + // Unsubcribe + s1.unsubscribe(); + //Unblock the observable to continue. + okToContinue.countDown(); + w1.t.join(); + w2.t.join(); + } catch (Throwable e) { + e.printStackTrace(); + fail(e.getMessage()); + } + + InOrder inOrder = inOrder(aObserver); + inOrder.verify(aObserver, times(1)).onNext("one"); + inOrder.verify(aObserver, times(1)).onNext("two"); + inOrder.verify(aObserver, times(1)).onNext("three"); + inOrder.verify(aObserver, times(1)).onNext("four"); + inOrder.verify(aObserver, never()).onNext("five"); + inOrder.verify(aObserver, never()).onNext("six"); + inOrder.verify(aObserver, never()).onCompleted(); + + } + + /** + * All observables will be running in different threads so subscribe() is unblocked. CountDownLatch is only used in order to call unsubscribe() in a predictable manner. + */ + @Test + public void testConcatUnsubscribeConcurrent() { + final CountDownLatch callOnce = new CountDownLatch(1); + final CountDownLatch okToContinue = new CountDownLatch(1); + final TestObservable w1 = new TestObservable("one", "two", "three"); + final TestObservable w2 = new TestObservable(callOnce, okToContinue, "four", "five", "six"); + + @SuppressWarnings("unchecked") + Observer aObserver = mock(Observer.class); + @SuppressWarnings("unchecked") + TestObservable> observableOfObservables = new TestObservable>(Observable.create(w1), Observable.create(w2)); + Observable.OnSubscribeFunc concatF = concat(Observable.create(observableOfObservables)); + + Observable concat = Observable.create(concatF); + + Subscription s1 = concat.subscribe(aObserver); + + try { + //Block main thread to allow observable "w1" to complete and observable "w2" to call onNext exactly once. + callOnce.await(); + //"four" from w2 has been processed by onNext() + s1.unsubscribe(); + //"five" and "six" will NOT be processed by onNext() + //Unblock the observable to continue. + okToContinue.countDown(); + w1.t.join(); + w2.t.join(); + } catch (Throwable e) { + e.printStackTrace(); + fail(e.getMessage()); + } + + InOrder inOrder = inOrder(aObserver); + inOrder.verify(aObserver, times(1)).onNext("one"); + inOrder.verify(aObserver, times(1)).onNext("two"); + inOrder.verify(aObserver, times(1)).onNext("three"); + inOrder.verify(aObserver, times(1)).onNext("four"); + inOrder.verify(aObserver, never()).onNext("five"); + inOrder.verify(aObserver, never()).onNext("six"); + verify(aObserver, never()).onCompleted(); + verify(aObserver, never()).onError(any(Throwable.class)); + } + + private static class TestObservable implements Observable.OnSubscribeFunc { + + private final Subscription s = new Subscription() { + + @Override + public void unsubscribe() { + subscribed = false; + } + + }; + private final List values; + private Thread t = null; + private int count = 0; + private boolean subscribed = true; + private final CountDownLatch once; + private final CountDownLatch okToContinue; + private final T seed; + private final int size; + + public TestObservable(T... values) { + this(null, null, values); + } + + public TestObservable(CountDownLatch once, CountDownLatch okToContinue, T... values) { + this.values = Arrays.asList(values); + this.size = this.values.size(); + this.once = once; + this.okToContinue = okToContinue; + this.seed = null; + } + + public TestObservable(T seed, int size) { + values = null; + once = null; + okToContinue = null; + this.seed = seed; + this.size = size; + } + + @Override + public Subscription onSubscribe(final Observer observer) { + t = new Thread(new Runnable() { + + @Override + public void run() { + try { + while (count < size && subscribed) { + if (null != values) + observer.onNext(values.get(count)); + else + observer.onNext(seed); + count++; + //Unblock the main thread to call unsubscribe. + if (null != once) + once.countDown(); + //Block until the main thread has called unsubscribe. + if (null != okToContinue) + okToContinue.await(5, TimeUnit.SECONDS); + } + if (subscribed) + observer.onCompleted(); + } catch (InterruptedException e) { + e.printStackTrace(); + fail(e.getMessage()); + } + } + + }); + t.start(); + return s; + } + } } diff --git a/rxjava-core/src/test/java/rx/operators/OperationDebounceTest.java b/rxjava-core/src/test/java/rx/operators/OperationDebounceTest.java index a1f6d4c237..2e907d8f6b 100644 --- a/rxjava-core/src/test/java/rx/operators/OperationDebounceTest.java +++ b/rxjava-core/src/test/java/rx/operators/OperationDebounceTest.java @@ -1,7 +1,146 @@ package rx.operators; -import org.junit.Ignore; +import org.junit.Before; +import org.junit.Test; +import org.mockito.InOrder; +import rx.Observable; +import rx.Observer; +import rx.Subscription; +import rx.concurrency.TestScheduler; +import rx.subscriptions.Subscriptions; +import rx.util.functions.Action0; + +import java.util.concurrent.TimeUnit; + +import static org.mockito.Matchers.any; +import static org.mockito.Matchers.anyString; +import static org.mockito.Mockito.*; -@Ignore("WIP") public class OperationDebounceTest { + + private TestScheduler scheduler; + private Observer observer; + + @Before + @SuppressWarnings("unchecked") + public void before() { + scheduler = new TestScheduler(); + observer = mock(Observer.class); + } + + @Test + public void testDebounceWithCompleted() { + Observable source = Observable.create(new Observable.OnSubscribeFunc() { + @Override + public Subscription onSubscribe(Observer observer) { + publishNext(observer, 100, "one"); // Should be skipped since "two" will arrive before the timeout expires. + publishNext(observer, 400, "two"); // Should be published since "three" will arrive after the timeout expires. + publishNext(observer, 900, "three"); // Should be skipped since onCompleted will arrive before the timeout expires. + publishCompleted(observer, 1000); // Should be published as soon as the timeout expires. + + return Subscriptions.empty(); + } + }); + + Observable sampled = Observable.create(OperationDebounce.debounce(source, 400, TimeUnit.MILLISECONDS, scheduler)); + sampled.subscribe(observer); + + scheduler.advanceTimeTo(0, TimeUnit.MILLISECONDS); + InOrder inOrder = inOrder(observer); + // must go to 800 since it must be 400 after when two is sent, which is at 400 + scheduler.advanceTimeTo(800, TimeUnit.MILLISECONDS); + inOrder.verify(observer, times(1)).onNext("two"); + scheduler.advanceTimeTo(1000, TimeUnit.MILLISECONDS); + inOrder.verify(observer, times(1)).onCompleted(); + inOrder.verifyNoMoreInteractions(); + } + + @Test + public void testDebounceNeverEmits() { + Observable source = Observable.create(new Observable.OnSubscribeFunc() { + @Override + public Subscription onSubscribe(Observer observer) { + // all should be skipped since they are happening faster than the 200ms timeout + publishNext(observer, 100, "a"); // Should be skipped + publishNext(observer, 200, "b"); // Should be skipped + publishNext(observer, 300, "c"); // Should be skipped + publishNext(observer, 400, "d"); // Should be skipped + publishNext(observer, 500, "e"); // Should be skipped + publishNext(observer, 600, "f"); // Should be skipped + publishNext(observer, 700, "g"); // Should be skipped + publishNext(observer, 800, "h"); // Should be skipped + publishCompleted(observer, 900); // Should be published as soon as the timeout expires. + + return Subscriptions.empty(); + } + }); + + Observable sampled = Observable.create(OperationDebounce.debounce(source, 200, TimeUnit.MILLISECONDS, scheduler)); + sampled.subscribe(observer); + + scheduler.advanceTimeTo(0, TimeUnit.MILLISECONDS); + InOrder inOrder = inOrder(observer); + inOrder.verify(observer, times(0)).onNext(anyString()); + scheduler.advanceTimeTo(1000, TimeUnit.MILLISECONDS); + inOrder.verify(observer, times(1)).onCompleted(); + inOrder.verifyNoMoreInteractions(); + } + + @Test + public void testDebounceWithError() { + Observable source = Observable.create(new Observable.OnSubscribeFunc() { + @Override + public Subscription onSubscribe(Observer observer) { + Exception error = new TestException(); + publishNext(observer, 100, "one"); // Should be published since "two" will arrive after the timeout expires. + publishNext(observer, 600, "two"); // Should be skipped since onError will arrive before the timeout expires. + publishError(observer, 700, error); // Should be published as soon as the timeout expires. + + return Subscriptions.empty(); + } + }); + + Observable sampled = Observable.create(OperationDebounce.debounce(source, 400, TimeUnit.MILLISECONDS, scheduler)); + sampled.subscribe(observer); + + scheduler.advanceTimeTo(0, TimeUnit.MILLISECONDS); + InOrder inOrder = inOrder(observer); + // 100 + 400 means it triggers at 500 + scheduler.advanceTimeTo(500, TimeUnit.MILLISECONDS); + inOrder.verify(observer).onNext("one"); + scheduler.advanceTimeTo(701, TimeUnit.MILLISECONDS); + inOrder.verify(observer).onError(any(TestException.class)); + inOrder.verifyNoMoreInteractions(); + } + + private void publishCompleted(final Observer observer, long delay) { + scheduler.schedule(new Action0() { + @Override + public void call() { + observer.onCompleted(); + } + }, delay, TimeUnit.MILLISECONDS); + } + + private void publishError(final Observer observer, long delay, final Exception error) { + scheduler.schedule(new Action0() { + @Override + public void call() { + observer.onError(error); + } + }, delay, TimeUnit.MILLISECONDS); + } + + private void publishNext(final Observer observer, final long delay, final T value) { + scheduler.schedule(new Action0() { + @Override + public void call() { + observer.onNext(value); + } + }, delay, TimeUnit.MILLISECONDS); + } + + @SuppressWarnings("serial") + private class TestException extends Exception { + } } diff --git a/rxjava-core/src/test/java/rx/operators/OperationDefaultIfEmptyTest.java b/rxjava-core/src/test/java/rx/operators/OperationDefaultIfEmptyTest.java index 241c8790c3..fb2166dfc1 100644 --- a/rxjava-core/src/test/java/rx/operators/OperationDefaultIfEmptyTest.java +++ b/rxjava-core/src/test/java/rx/operators/OperationDefaultIfEmptyTest.java @@ -1,7 +1,44 @@ package rx.operators; -import org.junit.Ignore; +import org.junit.Test; +import rx.Observable; +import rx.Observer; + +import static org.mockito.Mockito.*; +import static rx.operators.OperationDefaultIfEmpty.defaultIfEmpty; -@Ignore("WIP") public class OperationDefaultIfEmptyTest { + + @Test + public void testDefaultIfEmpty() { + Observable source = Observable.from(1, 2, 3); + Observable observable = Observable.create(defaultIfEmpty( + source, 10)); + + @SuppressWarnings("unchecked") + Observer aObserver = mock(Observer.class); + observable.subscribe(aObserver); + verify(aObserver, never()).onNext(10); + verify(aObserver, times(1)).onNext(1); + verify(aObserver, times(1)).onNext(2); + verify(aObserver, times(1)).onNext(3); + verify(aObserver, never()).onError( + org.mockito.Matchers.any(Throwable.class)); + verify(aObserver, times(1)).onCompleted(); + } + + @Test + public void testDefaultIfEmptyWithEmpty() { + Observable source = Observable.empty(); + Observable observable = Observable.create(defaultIfEmpty( + source, 10)); + + @SuppressWarnings("unchecked") + Observer aObserver = mock(Observer.class); + observable.subscribe(aObserver); + verify(aObserver, times(1)).onNext(10); + verify(aObserver, never()).onError( + org.mockito.Matchers.any(Throwable.class)); + verify(aObserver, times(1)).onCompleted(); + } } diff --git a/rxjava-core/src/test/java/rx/operators/OperationDeferTest.java b/rxjava-core/src/test/java/rx/operators/OperationDeferTest.java index 344cbee450..8e02b17647 100644 --- a/rxjava-core/src/test/java/rx/operators/OperationDeferTest.java +++ b/rxjava-core/src/test/java/rx/operators/OperationDeferTest.java @@ -1,7 +1,47 @@ package rx.operators; -import org.junit.Ignore; +import org.junit.Test; +import rx.Observable; +import rx.Observer; +import rx.util.functions.Func0; + +import static org.mockito.Mockito.*; -@Ignore("WIP") public class OperationDeferTest { + + @Test + @SuppressWarnings("unchecked") + public void testDefer() throws Throwable { + + Func0> factory = mock(Func0.class); + + Observable firstObservable = Observable.from("one", "two"); + Observable secondObservable = Observable.from("three", "four"); + when(factory.call()).thenReturn(firstObservable, secondObservable); + + Observable deferred = Observable.defer(factory); + + verifyZeroInteractions(factory); + + Observer firstObserver = mock(Observer.class); + deferred.subscribe(firstObserver); + + verify(factory, times(1)).call(); + verify(firstObserver, times(1)).onNext("one"); + verify(firstObserver, times(1)).onNext("two"); + verify(firstObserver, times(0)).onNext("three"); + verify(firstObserver, times(0)).onNext("four"); + verify(firstObserver, times(1)).onCompleted(); + + Observer secondObserver = mock(Observer.class); + deferred.subscribe(secondObserver); + + verify(factory, times(2)).call(); + verify(secondObserver, times(0)).onNext("one"); + verify(secondObserver, times(0)).onNext("two"); + verify(secondObserver, times(1)).onNext("three"); + verify(secondObserver, times(1)).onNext("four"); + verify(secondObserver, times(1)).onCompleted(); + + } } diff --git a/rxjava-core/src/test/java/rx/operators/OperationDematerializeTest.java b/rxjava-core/src/test/java/rx/operators/OperationDematerializeTest.java index f0433032fb..fcc1898d4a 100644 --- a/rxjava-core/src/test/java/rx/operators/OperationDematerializeTest.java +++ b/rxjava-core/src/test/java/rx/operators/OperationDematerializeTest.java @@ -1,7 +1,58 @@ package rx.operators; -import org.junit.Ignore; +import org.junit.Test; +import rx.Notification; +import rx.Observable; +import rx.Observer; + +import static org.mockito.Matchers.any; +import static org.mockito.Mockito.*; +import static rx.operators.OperationDematerialize.dematerialize; -@Ignore("WIP") public class OperationDematerializeTest { + + @Test + @SuppressWarnings("unchecked") + public void testDematerialize1() { + Observable> notifications = Observable.from(1, 2).materialize(); + Observable dematerialize = notifications.dematerialize(); + + Observer aObserver = mock(Observer.class); + dematerialize.subscribe(aObserver); + + verify(aObserver, times(1)).onNext(1); + verify(aObserver, times(1)).onNext(2); + verify(aObserver, times(1)).onCompleted(); + verify(aObserver, never()).onError(any(Throwable.class)); + } + + @Test + @SuppressWarnings("unchecked") + public void testDematerialize2() { + Throwable exception = new Throwable("test"); + Observable observable = Observable.error(exception); + Observable dematerialize = Observable.create(dematerialize(observable.materialize())); + + Observer aObserver = mock(Observer.class); + dematerialize.subscribe(aObserver); + + verify(aObserver, times(1)).onError(exception); + verify(aObserver, times(0)).onCompleted(); + verify(aObserver, times(0)).onNext(any(Integer.class)); + } + + @Test + @SuppressWarnings("unchecked") + public void testDematerialize3() { + Exception exception = new Exception("test"); + Observable observable = Observable.error(exception); + Observable dematerialize = Observable.create(dematerialize(observable.materialize())); + + Observer aObserver = mock(Observer.class); + dematerialize.subscribe(aObserver); + + verify(aObserver, times(1)).onError(exception); + verify(aObserver, times(0)).onCompleted(); + verify(aObserver, times(0)).onNext(any(Integer.class)); + } } diff --git a/rxjava-core/src/test/java/rx/operators/OperationDistinctTest.java b/rxjava-core/src/test/java/rx/operators/OperationDistinctTest.java index 1704b644fc..740ba9429a 100644 --- a/rxjava-core/src/test/java/rx/operators/OperationDistinctTest.java +++ b/rxjava-core/src/test/java/rx/operators/OperationDistinctTest.java @@ -1,7 +1,182 @@ package rx.operators; -import org.junit.Ignore; +import org.junit.Before; +import org.junit.Test; +import org.mockito.InOrder; +import org.mockito.Mock; +import rx.Observable; +import rx.Observer; +import rx.util.functions.Func1; + +import java.util.Comparator; + +import static org.mockito.Matchers.any; +import static org.mockito.Matchers.anyString; +import static org.mockito.Mockito.*; +import static org.mockito.Mockito.never; +import static org.mockito.MockitoAnnotations.initMocks; +import static rx.Observable.*; +import static rx.operators.OperationDistinct.distinct; -@Ignore("WIP") public class OperationDistinctTest { + + @Mock + Observer w; + @Mock + Observer w2; + + // nulls lead to exceptions + final Func1 TO_UPPER_WITH_EXCEPTION = new Func1() { + @Override + public String call(String s) { + if (s.equals("x")) { + return "XX"; + } + return s.toUpperCase(); + } + }; + + final Comparator COMPARE_LENGTH = new Comparator() { + @Override + public int compare(String s1, String s2) { + return s1.length() - s2.length(); + } + }; + + @Before + public void before() { + initMocks(this); + } + + @Test + public void testDistinctOfNone() { + Observable src = empty(); + create(distinct(src)).subscribe(w); + + verify(w, never()).onNext(anyString()); + verify(w, never()).onError(any(Throwable.class)); + verify(w, times(1)).onCompleted(); + } + + @Test + public void testDistinctOfNoneWithKeySelector() { + Observable src = empty(); + create(distinct(src, TO_UPPER_WITH_EXCEPTION)).subscribe(w); + + verify(w, never()).onNext(anyString()); + verify(w, never()).onError(any(Throwable.class)); + verify(w, times(1)).onCompleted(); + } + + @Test + public void testDistinctOfNormalSource() { + Observable src = from("a", "b", "c", "c", "c", "b", "b", "a", "e"); + create(distinct(src)).subscribe(w); + + InOrder inOrder = inOrder(w); + inOrder.verify(w, times(1)).onNext("a"); + inOrder.verify(w, times(1)).onNext("b"); + inOrder.verify(w, times(1)).onNext("c"); + inOrder.verify(w, times(1)).onNext("e"); + inOrder.verify(w, times(1)).onCompleted(); + inOrder.verify(w, never()).onNext(anyString()); + verify(w, never()).onError(any(Throwable.class)); + } + + @Test + public void testDistinctOfNormalSourceWithKeySelector() { + Observable src = from("a", "B", "c", "C", "c", "B", "b", "a", "E"); + create(distinct(src, TO_UPPER_WITH_EXCEPTION)).subscribe(w); + + InOrder inOrder = inOrder(w); + inOrder.verify(w, times(1)).onNext("a"); + inOrder.verify(w, times(1)).onNext("B"); + inOrder.verify(w, times(1)).onNext("c"); + inOrder.verify(w, times(1)).onNext("E"); + inOrder.verify(w, times(1)).onCompleted(); + inOrder.verify(w, never()).onNext(anyString()); + verify(w, never()).onError(any(Throwable.class)); + } + + @Test + public void testDistinctOfNormalSourceWithComparator() { + Observable src = from("1", "12", "123", "aaa", "321", "12", "21", "1", "12345"); + create(distinct(src, COMPARE_LENGTH)).subscribe(w); + + InOrder inOrder = inOrder(w); + inOrder.verify(w, times(1)).onNext("1"); + inOrder.verify(w, times(1)).onNext("12"); + inOrder.verify(w, times(1)).onNext("123"); + inOrder.verify(w, times(1)).onNext("12345"); + inOrder.verify(w, times(1)).onCompleted(); + inOrder.verify(w, never()).onNext(anyString()); + verify(w, never()).onError(any(Throwable.class)); + } + + @Test + public void testDistinctOfNormalSourceWithKeySelectorAndComparator() { + Observable src = from("a", "x", "ab", "abc", "cba", "de", "x", "a", "abcd"); + create(distinct(src, TO_UPPER_WITH_EXCEPTION, COMPARE_LENGTH)).subscribe(w); + + InOrder inOrder = inOrder(w); + inOrder.verify(w, times(1)).onNext("a"); + inOrder.verify(w, times(1)).onNext("x"); + inOrder.verify(w, times(1)).onNext("abc"); + inOrder.verify(w, times(1)).onNext("abcd"); + inOrder.verify(w, times(1)).onCompleted(); + inOrder.verify(w, never()).onNext(anyString()); + verify(w, never()).onError(any(Throwable.class)); + } + + @Test + public void testDistinctOfNormalSourceWithKeySelectorAndComparatorAndTwoSubscriptions() { + Observable src = from("a", "x", "ab", "abc", "cba", "de", "x", "a", "abcd"); + create(distinct(src, TO_UPPER_WITH_EXCEPTION, COMPARE_LENGTH)).subscribe(w); + + InOrder inOrder = inOrder(w); + inOrder.verify(w, times(1)).onNext("a"); + inOrder.verify(w, times(1)).onNext("x"); + create(distinct(src, TO_UPPER_WITH_EXCEPTION, COMPARE_LENGTH)).subscribe(w2); + inOrder.verify(w, times(1)).onNext("abc"); + inOrder.verify(w, times(1)).onNext("abcd"); + inOrder.verify(w, times(1)).onCompleted(); + inOrder.verify(w, never()).onNext(anyString()); + verify(w, never()).onError(any(Throwable.class)); + + InOrder inOrder2 = inOrder(w2); + inOrder2.verify(w2, times(1)).onNext("a"); + inOrder2.verify(w2, times(1)).onNext("x"); + inOrder2.verify(w2, times(1)).onNext("abc"); + inOrder2.verify(w2, times(1)).onNext("abcd"); + inOrder2.verify(w2, times(1)).onCompleted(); + inOrder2.verify(w2, never()).onNext(anyString()); + verify(w2, never()).onError(any(Throwable.class)); + } + + @Test + public void testDistinctOfSourceWithNulls() { + Observable src = from(null, "a", "a", null, null, "b", null); + create(distinct(src)).subscribe(w); + + InOrder inOrder = inOrder(w); + inOrder.verify(w, times(1)).onNext(null); + inOrder.verify(w, times(1)).onNext("a"); + inOrder.verify(w, times(1)).onNext("b"); + inOrder.verify(w, times(1)).onCompleted(); + inOrder.verify(w, never()).onNext(anyString()); + verify(w, never()).onError(any(Throwable.class)); + } + + @Test + public void testDistinctOfSourceWithExceptionsFromKeySelector() { + Observable src = from("a", "b", null, "c"); + create(distinct(src, TO_UPPER_WITH_EXCEPTION)).subscribe(w); + + InOrder inOrder = inOrder(w); + inOrder.verify(w, times(1)).onNext("a"); + inOrder.verify(w, times(1)).onNext("b"); + inOrder.verify(w, times(1)).onError(any(NullPointerException.class)); + inOrder.verify(w, never()).onNext(anyString()); + inOrder.verify(w, never()).onCompleted(); + } } diff --git a/rxjava-core/src/test/java/rx/operators/OperationDistinctUntilChangedTest.java b/rxjava-core/src/test/java/rx/operators/OperationDistinctUntilChangedTest.java index cdb4eb7203..e39a123f3d 100644 --- a/rxjava-core/src/test/java/rx/operators/OperationDistinctUntilChangedTest.java +++ b/rxjava-core/src/test/java/rx/operators/OperationDistinctUntilChangedTest.java @@ -1,7 +1,185 @@ package rx.operators; -import org.junit.Ignore; +import org.junit.Before; +import org.junit.Test; +import org.mockito.InOrder; +import org.mockito.Mock; +import rx.Observable; +import rx.Observer; +import rx.util.functions.Func1; + +import java.util.Comparator; + +import static org.mockito.Matchers.any; +import static org.mockito.Matchers.anyString; +import static org.mockito.Mockito.*; +import static org.mockito.Mockito.never; +import static org.mockito.MockitoAnnotations.initMocks; +import static rx.Observable.*; +import static rx.operators.OperationDistinctUntilChanged.distinctUntilChanged; -@Ignore("WIP") public class OperationDistinctUntilChangedTest { + + @Mock + Observer w; + @Mock + Observer w2; + + // nulls lead to exceptions + final Func1 TO_UPPER_WITH_EXCEPTION = new Func1() { + @Override + public String call(String s) { + if (s.equals("x")) { + return "xx"; + } + return s.toUpperCase(); + } + }; + + final Comparator COMPARE_LENGTH = new Comparator() { + @Override + public int compare(String s1, String s2) { + return s1.length() - s2.length(); + } + }; + + @Before + public void before() { + initMocks(this); + } + + @Test + public void testDistinctUntilChangedOfNone() { + Observable src = empty(); + create(distinctUntilChanged(src)).subscribe(w); + + verify(w, never()).onNext(anyString()); + verify(w, never()).onError(any(Throwable.class)); + verify(w, times(1)).onCompleted(); + } + + @Test + public void testDistinctUntilChangedOfNoneWithKeySelector() { + Observable src = empty(); + create(distinctUntilChanged(src, TO_UPPER_WITH_EXCEPTION)).subscribe(w); + + verify(w, never()).onNext(anyString()); + verify(w, never()).onError(any(Throwable.class)); + verify(w, times(1)).onCompleted(); + } + + @Test + public void testDistinctUntilChangedOfNormalSource() { + Observable src = from("a", "b", "c", "c", "c", "b", "b", "a", "e"); + create(distinctUntilChanged(src)).subscribe(w); + + InOrder inOrder = inOrder(w); + inOrder.verify(w, times(1)).onNext("a"); + inOrder.verify(w, times(1)).onNext("b"); + inOrder.verify(w, times(1)).onNext("c"); + inOrder.verify(w, times(1)).onNext("b"); + inOrder.verify(w, times(1)).onNext("a"); + inOrder.verify(w, times(1)).onNext("e"); + inOrder.verify(w, times(1)).onCompleted(); + inOrder.verify(w, never()).onNext(anyString()); + verify(w, never()).onError(any(Throwable.class)); + } + + @Test + public void testDistinctUntilChangedOfNormalSourceWithKeySelector() { + Observable src = from("a", "b", "c", "C", "c", "B", "b", "a", "e"); + create(distinctUntilChanged(src, TO_UPPER_WITH_EXCEPTION)).subscribe(w); + + InOrder inOrder = inOrder(w); + inOrder.verify(w, times(1)).onNext("a"); + inOrder.verify(w, times(1)).onNext("b"); + inOrder.verify(w, times(1)).onNext("c"); + inOrder.verify(w, times(1)).onNext("B"); + inOrder.verify(w, times(1)).onNext("a"); + inOrder.verify(w, times(1)).onNext("e"); + inOrder.verify(w, times(1)).onCompleted(); + inOrder.verify(w, never()).onNext(anyString()); + verify(w, never()).onError(any(Throwable.class)); + } + + @Test + public void testDistinctUntilChangedOfSourceWithNulls() { + Observable src = from(null, "a", "a", null, null, "b", null, null); + create(distinctUntilChanged(src)).subscribe(w); + + InOrder inOrder = inOrder(w); + inOrder.verify(w, times(1)).onNext(null); + inOrder.verify(w, times(1)).onNext("a"); + inOrder.verify(w, times(1)).onNext(null); + inOrder.verify(w, times(1)).onNext("b"); + inOrder.verify(w, times(1)).onNext(null); + inOrder.verify(w, times(1)).onCompleted(); + inOrder.verify(w, never()).onNext(anyString()); + verify(w, never()).onError(any(Throwable.class)); + } + + @Test + public void testDistinctUntilChangedOfSourceWithExceptionsFromKeySelector() { + Observable src = from("a", "b", null, "c"); + create(distinctUntilChanged(src, TO_UPPER_WITH_EXCEPTION)).subscribe(w); + + InOrder inOrder = inOrder(w); + inOrder.verify(w, times(1)).onNext("a"); + inOrder.verify(w, times(1)).onNext("b"); + verify(w, times(1)).onError(any(NullPointerException.class)); + inOrder.verify(w, never()).onNext(anyString()); + inOrder.verify(w, never()).onCompleted(); + } + + @Test + public void testDistinctUntilChangedWithComparator() { + Observable src = from("a", "b", "c", "aa", "bb", "c", "ddd"); + create(distinctUntilChanged(src, COMPARE_LENGTH)).subscribe(w); + InOrder inOrder = inOrder(w); + inOrder.verify(w, times(1)).onNext("a"); + inOrder.verify(w, times(1)).onNext("aa"); + inOrder.verify(w, times(1)).onNext("c"); + inOrder.verify(w, times(1)).onNext("ddd"); + inOrder.verify(w, times(1)).onCompleted(); + inOrder.verify(w, never()).onNext(anyString()); + verify(w, never()).onError(any(Throwable.class)); + } + + @Test + public void testDistinctUntilChangedWithComparatorAndKeySelector() { + Observable src = from("a", "b", "x", "aa", "bb", "c", "ddd"); + create(distinctUntilChanged(src, TO_UPPER_WITH_EXCEPTION, COMPARE_LENGTH)).subscribe(w); + InOrder inOrder = inOrder(w); + inOrder.verify(w, times(1)).onNext("a"); + inOrder.verify(w, times(1)).onNext("x"); + inOrder.verify(w, times(1)).onNext("c"); + inOrder.verify(w, times(1)).onNext("ddd"); + inOrder.verify(w, times(1)).onCompleted(); + inOrder.verify(w, never()).onNext(anyString()); + verify(w, never()).onError(any(Throwable.class)); + } + + @Test + public void testDistinctUntilChangedWithComparatorAndKeySelectorandTwoSubscriptions() { + Observable src = from("a", "b", "x", "aa", "bb", "c", "ddd"); + create(distinctUntilChanged(src, TO_UPPER_WITH_EXCEPTION, COMPARE_LENGTH)).subscribe(w); + InOrder inOrder = inOrder(w); + inOrder.verify(w, times(1)).onNext("a"); + inOrder.verify(w, times(1)).onNext("x"); + create(distinctUntilChanged(src, TO_UPPER_WITH_EXCEPTION, COMPARE_LENGTH)).subscribe(w2); + inOrder.verify(w, times(1)).onNext("c"); + inOrder.verify(w, times(1)).onNext("ddd"); + inOrder.verify(w, times(1)).onCompleted(); + inOrder.verify(w, never()).onNext(anyString()); + verify(w, never()).onError(any(Throwable.class)); + + InOrder inOrder2 = inOrder(w2); + inOrder2.verify(w2, times(1)).onNext("a"); + inOrder2.verify(w2, times(1)).onNext("x"); + inOrder2.verify(w2, times(1)).onNext("c"); + inOrder2.verify(w2, times(1)).onNext("ddd"); + inOrder2.verify(w2, times(1)).onCompleted(); + inOrder2.verify(w2, never()).onNext(anyString()); + verify(w2, never()).onError(any(Throwable.class)); + } } diff --git a/rxjava-core/src/test/java/rx/operators/OperationElementAtTest.java b/rxjava-core/src/test/java/rx/operators/OperationElementAtTest.java index b17efa3cd3..4f1326df06 100644 --- a/rxjava-core/src/test/java/rx/operators/OperationElementAtTest.java +++ b/rxjava-core/src/test/java/rx/operators/OperationElementAtTest.java @@ -1,7 +1,113 @@ package rx.operators; -import org.junit.Ignore; +import org.junit.Test; +import rx.Observable; +import rx.Observer; + +import java.util.Iterator; +import java.util.concurrent.ExecutionException; + +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; +import static org.mockito.Matchers.any; +import static org.mockito.Mockito.*; +import static rx.operators.OperationElementAt.elementAt; +import static rx.operators.OperationElementAt.elementAtOrDefault; -@Ignore("WIP") public class OperationElementAtTest { + + @Test + public void testElementAt() { + Observable w = Observable.from(1, 2); + Observable observable = Observable.create(elementAt(w, 1)); + + @SuppressWarnings("unchecked") + Observer aObserver = mock(Observer.class); + observable.subscribe(aObserver); + verify(aObserver, never()).onNext(1); + verify(aObserver, times(1)).onNext(2); + verify(aObserver, never()).onError( + any(Throwable.class)); + verify(aObserver, times(1)).onCompleted(); + } + + @Test + public void testElementAtWithMinusIndex() { + Observable w = Observable.from(1, 2); + Observable observable = Observable + .create(elementAt(w, -1)); + + try { + Iterator iter = OperationToIterator + .toIterator(observable); + assertTrue(iter.hasNext()); + iter.next(); + fail("expect an IndexOutOfBoundsException when index is out of bounds"); + } catch (IndexOutOfBoundsException e) { + } + } + + @Test + public void testElementAtWithIndexOutOfBounds() + throws InterruptedException, ExecutionException { + Observable w = Observable.from(1, 2); + Observable observable = Observable.create(elementAt(w, 2)); + try { + Iterator iter = OperationToIterator + .toIterator(observable); + assertTrue(iter.hasNext()); + iter.next(); + fail("expect an IndexOutOfBoundsException when index is out of bounds"); + } catch (IndexOutOfBoundsException e) { + } + } + + @Test + public void testElementAtOrDefault() throws InterruptedException, + ExecutionException { + Observable w = Observable.from(1, 2); + Observable observable = Observable + .create(elementAtOrDefault(w, 1, 0)); + + @SuppressWarnings("unchecked") + Observer aObserver = mock(Observer.class); + observable.subscribe(aObserver); + verify(aObserver, never()).onNext(1); + verify(aObserver, times(1)).onNext(2); + verify(aObserver, never()).onError(any(Throwable.class)); + verify(aObserver, times(1)).onCompleted(); + } + + @Test + public void testElementAtOrDefaultWithIndexOutOfBounds() + throws InterruptedException, ExecutionException { + Observable w = Observable.from(1, 2); + Observable observable = Observable + .create(elementAtOrDefault(w, 2, 0)); + + @SuppressWarnings("unchecked") + Observer aObserver = mock(Observer.class); + observable.subscribe(aObserver); + verify(aObserver, never()).onNext(1); + verify(aObserver, never()).onNext(2); + verify(aObserver, times(1)).onNext(0); + verify(aObserver, never()).onError(any(Throwable.class)); + verify(aObserver, times(1)).onCompleted(); + } + + @Test + public void testElementAtOrDefaultWithMinusIndex() { + Observable w = Observable.from(1, 2); + Observable observable = Observable + .create(elementAtOrDefault(w, -1, 0)); + + try { + Iterator iter = OperationToIterator + .toIterator(observable); + assertTrue(iter.hasNext()); + iter.next(); + fail("expect an IndexOutOfBoundsException when index is out of bounds"); + } catch (IndexOutOfBoundsException e) { + } + } } diff --git a/rxjava-core/src/test/java/rx/operators/OperationFilterTest.java b/rxjava-core/src/test/java/rx/operators/OperationFilterTest.java index 19e15ea81a..a6da7261e1 100644 --- a/rxjava-core/src/test/java/rx/operators/OperationFilterTest.java +++ b/rxjava-core/src/test/java/rx/operators/OperationFilterTest.java @@ -1,7 +1,35 @@ package rx.operators; -import org.junit.Ignore; +import org.junit.Test; +import org.mockito.Mockito; +import rx.Observable; +import rx.Observer; +import rx.util.functions.Func1; + +import static org.mockito.Matchers.any; +import static org.mockito.Mockito.*; +import static rx.operators.OperationFilter.filter; -@Ignore("WIP") public class OperationFilterTest { + + @Test + public void testFilter() { + Observable w = Observable.from("one", "two", "three"); + Observable observable = Observable.create(filter(w, new Func1() { + + @Override + public Boolean call(String t1) { + return t1.equals("two"); + } + })); + + @SuppressWarnings("unchecked") + Observer aObserver = mock(Observer.class); + observable.subscribe(aObserver); + verify(aObserver, Mockito.never()).onNext("one"); + verify(aObserver, times(1)).onNext("two"); + verify(aObserver, Mockito.never()).onNext("three"); + verify(aObserver, Mockito.never()).onError(any(Throwable.class)); + verify(aObserver, times(1)).onCompleted(); + } } diff --git a/rxjava-core/src/test/java/rx/operators/OperationFinallyTest.java b/rxjava-core/src/test/java/rx/operators/OperationFinallyTest.java index 0e46ce1cb2..b856c86fa6 100644 --- a/rxjava-core/src/test/java/rx/operators/OperationFinallyTest.java +++ b/rxjava-core/src/test/java/rx/operators/OperationFinallyTest.java @@ -1,7 +1,38 @@ package rx.operators; -import org.junit.Ignore; +import org.junit.Before; +import org.junit.Test; +import rx.Observable; +import rx.Observer; +import rx.util.functions.Action0; + +import static org.mockito.Mockito.*; +import static rx.operators.OperationFinally.finallyDo; -@Ignore("WIP") public class OperationFinallyTest { + + private Action0 aAction0; + private Observer aObserver; + + @SuppressWarnings("unchecked") // mocking has to be unchecked, unfortunately + @Before + public void before() { + aAction0 = mock(Action0.class); + aObserver = mock(Observer.class); + } + + private void checkActionCalled(Observable input) { + Observable.create(finallyDo(input, aAction0)).subscribe(aObserver); + verify(aAction0, times(1)).call(); + } + + @Test + public void testFinallyCalledOnComplete() { + checkActionCalled(Observable.from(new String[]{"1", "2", "3"})); + } + + @Test + public void testFinallyCalledOnError() { + checkActionCalled(Observable.error(new RuntimeException("expected"))); + } } diff --git a/rxjava-core/src/test/java/rx/operators/OperationFirstOrDefaultTest.java b/rxjava-core/src/test/java/rx/operators/OperationFirstOrDefaultTest.java index 39a60a03c5..344ab98578 100644 --- a/rxjava-core/src/test/java/rx/operators/OperationFirstOrDefaultTest.java +++ b/rxjava-core/src/test/java/rx/operators/OperationFirstOrDefaultTest.java @@ -1,7 +1,78 @@ package rx.operators; -import org.junit.Ignore; +import org.junit.Before; +import org.junit.Test; +import org.mockito.Mock; +import rx.Observable; +import rx.Observer; +import rx.util.functions.Func1; + +import static org.mockito.Matchers.any; +import static org.mockito.Matchers.anyString; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.*; +import static org.mockito.MockitoAnnotations.initMocks; +import static rx.Observable.*; +import static rx.operators.OperationFirstOrDefault.firstOrDefault; -@Ignore("WIP") public class OperationFirstOrDefaultTest { + + @Mock + Observer w; + + private static final Func1 IS_D = new Func1() { + @Override + public Boolean call(String value) { + return "d".equals(value); + } + }; + + @Before + public void before() { + initMocks(this); + } + + @Test + public void testFirstOrElseOfNone() { + Observable src = empty(); + create(firstOrDefault(src, "default")).subscribe(w); + + verify(w, times(1)).onNext(anyString()); + verify(w, times(1)).onNext("default"); + verify(w, never()).onError(any(Throwable.class)); + verify(w, times(1)).onCompleted(); + } + + @Test + public void testFirstOrElseOfSome() { + Observable src = from("a", "b", "c"); + create(firstOrDefault(src, "default")).subscribe(w); + + verify(w, times(1)).onNext(anyString()); + verify(w, times(1)).onNext("a"); + verify(w, never()).onError(any(Throwable.class)); + verify(w, times(1)).onCompleted(); + } + + @Test + public void testFirstOrElseWithPredicateOfNoneMatchingThePredicate() { + Observable src = from("a", "b", "c"); + create(firstOrDefault(src, IS_D, "default")).subscribe(w); + + verify(w, times(1)).onNext(anyString()); + verify(w, times(1)).onNext("default"); + verify(w, never()).onError(any(Throwable.class)); + verify(w, times(1)).onCompleted(); + } + + @Test + public void testFirstOrElseWithPredicateOfSome() { + Observable src = from("a", "b", "c", "d", "e", "f"); + create(firstOrDefault(src, IS_D, "default")).subscribe(w); + + verify(w, times(1)).onNext(anyString()); + verify(w, times(1)).onNext("d"); + verify(w, never()).onError(any(Throwable.class)); + verify(w, times(1)).onCompleted(); + } } diff --git a/rxjava-core/src/test/java/rx/operators/OperationGroupByTest.java b/rxjava-core/src/test/java/rx/operators/OperationGroupByTest.java index 222085a96f..e62be97d11 100644 --- a/rxjava-core/src/test/java/rx/operators/OperationGroupByTest.java +++ b/rxjava-core/src/test/java/rx/operators/OperationGroupByTest.java @@ -1,7 +1,331 @@ package rx.operators; -import org.junit.Ignore; +import org.junit.Test; +import rx.Observable; +import rx.Observer; +import rx.Subscription; +import rx.observables.GroupedObservable; +import rx.subscriptions.BooleanSubscription; +import rx.subscriptions.Subscriptions; +import rx.util.functions.Action1; +import rx.util.functions.Func1; + +import java.util.Arrays; +import java.util.Collection; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentLinkedQueue; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.atomic.AtomicReference; + +import static org.junit.Assert.*; +import static rx.operators.OperationGroupBy.groupBy; -@Ignore("WIP") public class OperationGroupByTest { + + final Func1 length = new Func1() { + @Override + public Integer call(String s) { + return s.length(); + } + }; + + @Test + public void testGroupBy() { + Observable source = Observable.from("one", "two", "three", "four", "five", "six"); + Observable> grouped = Observable.create(groupBy(source, length)); + + Map> map = toMap(grouped); + + assertEquals(3, map.size()); + assertArrayEquals(Arrays.asList("one", "two", "six").toArray(), map.get(3).toArray()); + assertArrayEquals(Arrays.asList("four", "five").toArray(), map.get(4).toArray()); + assertArrayEquals(Arrays.asList("three").toArray(), map.get(5).toArray()); + } + + @Test + public void testEmpty() { + Observable source = Observable.empty(); + Observable> grouped = Observable.create(groupBy(source, length)); + + Map> map = toMap(grouped); + + assertTrue(map.isEmpty()); + } + + @Test + public void testError() { + Observable sourceStrings = Observable.from("one", "two", "three", "four", "five", "six"); + Observable errorSource = Observable.error(new RuntimeException("forced failure")); + Observable source = Observable.concat(sourceStrings, errorSource); + + Observable> grouped = Observable.create(groupBy(source, length)); + + final AtomicInteger groupCounter = new AtomicInteger(); + final AtomicInteger eventCounter = new AtomicInteger(); + final AtomicReference error = new AtomicReference(); + + grouped.mapMany(new Func1, Observable>() { + + @Override + public Observable call(final GroupedObservable o) { + groupCounter.incrementAndGet(); + return o.map(new Func1() { + + @Override + public String call(String v) { + return "Event => key: " + o.getKey() + " value: " + v; + } + }); + } + }).subscribe(new Observer() { + + @Override + public void onCompleted() { + + } + + @Override + public void onError(Throwable e) { + e.printStackTrace(); + error.set(e); + } + + @Override + public void onNext(String v) { + eventCounter.incrementAndGet(); + System.out.println(v); + + } + }); + + assertEquals(3, groupCounter.get()); + assertEquals(6, eventCounter.get()); + assertNotNull(error.get()); + } + + private static Map> toMap(Observable> observable) { + + final ConcurrentHashMap> result = new ConcurrentHashMap>(); + + observable.toBlockingObservable().forEach(new Action1>() { + + @Override + public void call(final GroupedObservable o) { + result.put(o.getKey(), new ConcurrentLinkedQueue()); + o.subscribe(new Action1() { + + @Override + public void call(V v) { + result.get(o.getKey()).add(v); + } + + }); + } + }); + + return result; + } + + /** + * Assert that only a single subscription to a stream occurs and that all events are received. + * + * @throws Throwable + */ + @Test + public void testGroupedEventStream() throws Throwable { + + final AtomicInteger eventCounter = new AtomicInteger(); + final AtomicInteger subscribeCounter = new AtomicInteger(); + final AtomicInteger groupCounter = new AtomicInteger(); + final CountDownLatch latch = new CountDownLatch(1); + final int count = 100; + final int groupCount = 2; + + Observable es = Observable.create(new Observable.OnSubscribeFunc() { + + @Override + public Subscription onSubscribe(final Observer observer) { + System.out.println("*** Subscribing to EventStream ***"); + subscribeCounter.incrementAndGet(); + new Thread(new Runnable() { + + @Override + public void run() { + for (int i = 0; i < count; i++) { + Event e = new Event(); + e.source = i % groupCount; + e.message = "Event-" + i; + observer.onNext(e); + } + observer.onCompleted(); + } + + }).start(); + return Subscriptions.empty(); + } + + }); + + es.groupBy(new Func1() { + + @Override + public Integer call(Event e) { + return e.source; + } + }).mapMany(new Func1, Observable>() { + + @Override + public Observable call(GroupedObservable eventGroupedObservable) { + System.out.println("GroupedObservable Key: " + eventGroupedObservable.getKey()); + groupCounter.incrementAndGet(); + + return eventGroupedObservable.map(new Func1() { + + @Override + public String call(Event event) { + return "Source: " + event.source + " Message: " + event.message; + } + }); + + } + }).subscribe(new Observer() { + + @Override + public void onCompleted() { + latch.countDown(); + } + + @Override + public void onError(Throwable e) { + e.printStackTrace(); + latch.countDown(); + } + + @Override + public void onNext(String outputMessage) { + System.out.println(outputMessage); + eventCounter.incrementAndGet(); + } + }); + + latch.await(5000, TimeUnit.MILLISECONDS); + assertEquals(1, subscribeCounter.get()); + assertEquals(groupCount, groupCounter.get()); + assertEquals(count, eventCounter.get()); + + } + + /* + * We will only take 1 group with 20 events from it and then unsubscribe. + */ + @Test + public void testUnsubscribe() throws InterruptedException { + + final AtomicInteger eventCounter = new AtomicInteger(); + final AtomicInteger subscribeCounter = new AtomicInteger(); + final AtomicInteger groupCounter = new AtomicInteger(); + final AtomicInteger sentEventCounter = new AtomicInteger(); + final CountDownLatch latch = new CountDownLatch(1); + final int count = 100; + final int groupCount = 2; + + Observable es = Observable.create(new Observable.OnSubscribeFunc() { + + @Override + public Subscription onSubscribe(final Observer observer) { + final BooleanSubscription s = new BooleanSubscription(); + System.out.println("testUnsubscribe => *** Subscribing to EventStream ***"); + subscribeCounter.incrementAndGet(); + new Thread(new Runnable() { + + @Override + public void run() { + for (int i = 0; i < count; i++) { + if (s.isUnsubscribed()) { + break; + } + Event e = new Event(); + e.source = i % groupCount; + e.message = "Event-" + i; + observer.onNext(e); + sentEventCounter.incrementAndGet(); + } + observer.onCompleted(); + } + + }).start(); + return s; + } + + }); + + es.groupBy(new Func1() { + + @Override + public Integer call(Event e) { + return e.source; + } + }) + .take(1) // we want only the first group + .mapMany(new Func1, Observable>() { + + @Override + public Observable call(GroupedObservable eventGroupedObservable) { + System.out.println("testUnsubscribe => GroupedObservable Key: " + eventGroupedObservable.getKey()); + groupCounter.incrementAndGet(); + + return eventGroupedObservable + .take(20) // limit to only 20 events on this group + .map(new Func1() { + + @Override + public String call(Event event) { + return "testUnsubscribe => Source: " + event.source + " Message: " + event.message; + } + }); + + } + }).subscribe(new Observer() { + + @Override + public void onCompleted() { + latch.countDown(); + } + + @Override + public void onError(Throwable e) { + e.printStackTrace(); + latch.countDown(); + } + + @Override + public void onNext(String outputMessage) { + System.out.println(outputMessage); + eventCounter.incrementAndGet(); + } + }); + + latch.await(5000, TimeUnit.MILLISECONDS); + assertEquals(1, subscribeCounter.get()); + assertEquals(1, groupCounter.get()); + assertEquals(20, eventCounter.get()); + // sentEvents will go until 'eventCounter' hits 20 and then unsubscribes + // which means it will also send (but ignore) the 19/20 events for the other group + // It will not however send all 100 events. + assertEquals(39, sentEventCounter.get(), 10); + // gave it a delta of 10 to account for the threading/unsubscription race condition which can vary depending on a machines performance, thread-scheduler, etc + } + + private static class Event { + int source; + String message; + + @Override + public String toString() { + return "Event => source: " + source + " message: " + message; + } + } } diff --git a/rxjava-core/src/test/java/rx/operators/OperationIntervalTest.java b/rxjava-core/src/test/java/rx/operators/OperationIntervalTest.java index 60b2ad7789..0ffd27c85b 100644 --- a/rxjava-core/src/test/java/rx/operators/OperationIntervalTest.java +++ b/rxjava-core/src/test/java/rx/operators/OperationIntervalTest.java @@ -1,7 +1,176 @@ package rx.operators; -import org.junit.Ignore; +import org.junit.Before; +import org.junit.Test; +import org.mockito.InOrder; +import rx.Observable; +import rx.Observer; +import rx.Subscription; +import rx.concurrency.TestScheduler; +import rx.observables.ConnectableObservable; + +import java.util.concurrent.TimeUnit; + +import static org.mockito.Matchers.any; +import static org.mockito.Matchers.anyLong; +import static org.mockito.Mockito.*; -@Ignore("WIP") public class OperationIntervalTest { + + private TestScheduler scheduler; + private Observer observer; + private Observer observer2; + + @Before + @SuppressWarnings("unchecked") // due to mocking + public void before() { + scheduler = new TestScheduler(); + observer = mock(Observer.class); + observer2 = mock(Observer.class); + } + + @Test + public void testInterval() { + Observable w = Observable.create(OperationInterval.interval(1, TimeUnit.SECONDS, scheduler)); + Subscription sub = w.subscribe(observer); + + verify(observer, never()).onNext(0L); + verify(observer, never()).onCompleted(); + verify(observer, never()).onError(any(Throwable.class)); + + scheduler.advanceTimeTo(2, TimeUnit.SECONDS); + + InOrder inOrder = inOrder(observer); + inOrder.verify(observer, times(1)).onNext(0L); + inOrder.verify(observer, times(1)).onNext(1L); + inOrder.verify(observer, never()).onNext(2L); + verify(observer, never()).onCompleted(); + verify(observer, never()).onError(any(Throwable.class)); + + sub.unsubscribe(); + scheduler.advanceTimeTo(4, TimeUnit.SECONDS); + verify(observer, never()).onNext(2L); + verify(observer, times(1)).onCompleted(); + verify(observer, never()).onError(any(Throwable.class)); + } + + @Test + public void testWithMultipleSubscribersStartingAtSameTime() { + Observable w = Observable.create(OperationInterval.interval(1, TimeUnit.SECONDS, scheduler)); + Subscription sub1 = w.subscribe(observer); + Subscription sub2 = w.subscribe(observer2); + + verify(observer, never()).onNext(anyLong()); + verify(observer2, never()).onNext(anyLong()); + + scheduler.advanceTimeTo(2, TimeUnit.SECONDS); + + InOrder inOrder1 = inOrder(observer); + InOrder inOrder2 = inOrder(observer2); + + inOrder1.verify(observer, times(1)).onNext(0L); + inOrder1.verify(observer, times(1)).onNext(1L); + inOrder1.verify(observer, never()).onNext(2L); + verify(observer, never()).onCompleted(); + verify(observer, never()).onError(any(Throwable.class)); + + inOrder2.verify(observer2, times(1)).onNext(0L); + inOrder2.verify(observer2, times(1)).onNext(1L); + inOrder2.verify(observer2, never()).onNext(2L); + verify(observer2, never()).onCompleted(); + verify(observer2, never()).onError(any(Throwable.class)); + + sub1.unsubscribe(); + sub2.unsubscribe(); + scheduler.advanceTimeTo(4, TimeUnit.SECONDS); + + verify(observer, never()).onNext(2L); + verify(observer, times(1)).onCompleted(); + verify(observer, never()).onError(any(Throwable.class)); + + verify(observer2, never()).onNext(2L); + verify(observer2, times(1)).onCompleted(); + verify(observer2, never()).onError(any(Throwable.class)); + } + + @Test + public void testWithMultipleStaggeredSubscribers() { + Observable w = Observable.create(OperationInterval.interval(1, TimeUnit.SECONDS, scheduler)); + Subscription sub1 = w.subscribe(observer); + + verify(observer, never()).onNext(anyLong()); + + scheduler.advanceTimeTo(2, TimeUnit.SECONDS); + Subscription sub2 = w.subscribe(observer2); + + InOrder inOrder1 = inOrder(observer); + inOrder1.verify(observer, times(1)).onNext(0L); + inOrder1.verify(observer, times(1)).onNext(1L); + inOrder1.verify(observer, never()).onNext(2L); + + verify(observer, never()).onCompleted(); + verify(observer, never()).onError(any(Throwable.class)); + verify(observer2, never()).onNext(anyLong()); + + scheduler.advanceTimeTo(4, TimeUnit.SECONDS); + + inOrder1.verify(observer, times(1)).onNext(2L); + inOrder1.verify(observer, times(1)).onNext(3L); + + InOrder inOrder2 = inOrder(observer2); + inOrder2.verify(observer2, times(1)).onNext(0L); + inOrder2.verify(observer2, times(1)).onNext(1L); + + sub1.unsubscribe(); + sub2.unsubscribe(); + + inOrder1.verify(observer, never()).onNext(anyLong()); + inOrder1.verify(observer, times(1)).onCompleted(); + verify(observer, never()).onError(any(Throwable.class)); + + inOrder2.verify(observer2, never()).onNext(anyLong()); + inOrder2.verify(observer2, times(1)).onCompleted(); + verify(observer2, never()).onError(any(Throwable.class)); + } + + @Test + public void testWithMultipleStaggeredSubscribersAndPublish() { + ConnectableObservable w = Observable.create(OperationInterval.interval(1, TimeUnit.SECONDS, scheduler)).publish(); + Subscription sub1 = w.subscribe(observer); + w.connect(); + + verify(observer, never()).onNext(anyLong()); + + scheduler.advanceTimeTo(2, TimeUnit.SECONDS); + Subscription sub2 = w.subscribe(observer2); + + InOrder inOrder1 = inOrder(observer); + inOrder1.verify(observer, times(1)).onNext(0L); + inOrder1.verify(observer, times(1)).onNext(1L); + inOrder1.verify(observer, never()).onNext(2L); + + verify(observer, never()).onCompleted(); + verify(observer, never()).onError(any(Throwable.class)); + verify(observer2, never()).onNext(anyLong()); + + scheduler.advanceTimeTo(4, TimeUnit.SECONDS); + + inOrder1.verify(observer, times(1)).onNext(2L); + inOrder1.verify(observer, times(1)).onNext(3L); + + InOrder inOrder2 = inOrder(observer2); + inOrder2.verify(observer2, times(1)).onNext(2L); + inOrder2.verify(observer2, times(1)).onNext(3L); + + sub1.unsubscribe(); + sub2.unsubscribe(); + + inOrder1.verify(observer, never()).onNext(anyLong()); + inOrder1.verify(observer, never()).onCompleted(); + verify(observer, never()).onError(any(Throwable.class)); + + inOrder2.verify(observer2, never()).onNext(anyLong()); + inOrder2.verify(observer2, never()).onCompleted(); + verify(observer2, never()).onError(any(Throwable.class)); + } } diff --git a/rxjava-core/src/test/java/rx/operators/OperationMapTest.java b/rxjava-core/src/test/java/rx/operators/OperationMapTest.java index 3c3ee5813c..cfd081112e 100644 --- a/rxjava-core/src/test/java/rx/operators/OperationMapTest.java +++ b/rxjava-core/src/test/java/rx/operators/OperationMapTest.java @@ -1,7 +1,276 @@ package rx.operators; -import org.junit.Ignore; +import org.junit.Before; +import org.junit.Test; +import org.mockito.InOrder; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import rx.Observable; +import rx.Observer; +import rx.concurrency.Schedulers; +import rx.util.functions.Func1; +import rx.util.functions.Func2; + +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.atomic.AtomicInteger; + +import static org.junit.Assert.assertEquals; +import static org.mockito.Matchers.any; +import static org.mockito.Mockito.*; +import static rx.operators.OperationMap.*; -@Ignore("WIP") public class OperationMapTest { + + @Mock + Observer stringObserver; + @Mock + Observer stringObserver2; + + final static Func2 APPEND_INDEX = new Func2() { + @Override + public String call(String value, Integer index) { + return value + index; + } + }; + + @Before + public void before() { + MockitoAnnotations.initMocks(this); + } + + @Test + public void testMap() { + Map m1 = getMap("One"); + Map m2 = getMap("Two"); + Observable> observable = Observable.from(m1, m2); + + Observable m = Observable.create(map(observable, new Func1, String>() { + + @Override + public String call(Map map) { + return map.get("firstName"); + } + + })); + m.subscribe(stringObserver); + + verify(stringObserver, never()).onError(any(Throwable.class)); + verify(stringObserver, times(1)).onNext("OneFirst"); + verify(stringObserver, times(1)).onNext("TwoFirst"); + verify(stringObserver, times(1)).onCompleted(); + } + + @Test + public void testMapWithIndex() { + Observable w = Observable.from("a", "b", "c"); + Observable m = Observable.create(mapWithIndex(w, APPEND_INDEX)); + m.subscribe(stringObserver); + InOrder inOrder = inOrder(stringObserver); + inOrder.verify(stringObserver, times(1)).onNext("a0"); + inOrder.verify(stringObserver, times(1)).onNext("b1"); + inOrder.verify(stringObserver, times(1)).onNext("c2"); + inOrder.verify(stringObserver, times(1)).onCompleted(); + verify(stringObserver, never()).onError(any(Throwable.class)); + } + + @Test + public void testMapWithIndexAndMultipleSubscribers() { + Observable w = Observable.from("a", "b", "c"); + Observable m = Observable.create(mapWithIndex(w, APPEND_INDEX)); + m.subscribe(stringObserver); + m.subscribe(stringObserver2); + InOrder inOrder = inOrder(stringObserver); + inOrder.verify(stringObserver, times(1)).onNext("a0"); + inOrder.verify(stringObserver, times(1)).onNext("b1"); + inOrder.verify(stringObserver, times(1)).onNext("c2"); + inOrder.verify(stringObserver, times(1)).onCompleted(); + verify(stringObserver, never()).onError(any(Throwable.class)); + + InOrder inOrder2 = inOrder(stringObserver2); + inOrder2.verify(stringObserver2, times(1)).onNext("a0"); + inOrder2.verify(stringObserver2, times(1)).onNext("b1"); + inOrder2.verify(stringObserver2, times(1)).onNext("c2"); + inOrder2.verify(stringObserver2, times(1)).onCompleted(); + verify(stringObserver2, never()).onError(any(Throwable.class)); + } + + @Test + public void testMapMany() { + /* simulate a top-level async call which returns IDs */ + Observable ids = Observable.from(1, 2); + + /* now simulate the behavior to take those IDs and perform nested async calls based on them */ + Observable m = Observable.create(mapMany(ids, new Func1>() { + + @Override + public Observable call(Integer id) { + /* simulate making a nested async call which creates another Observable */ + Observable> subObservable = null; + if (id == 1) { + Map m1 = getMap("One"); + Map m2 = getMap("Two"); + subObservable = Observable.from(m1, m2); + } else { + Map m3 = getMap("Three"); + Map m4 = getMap("Four"); + subObservable = Observable.from(m3, m4); + } + + /* simulate kicking off the async call and performing a select on it to transform the data */ + return Observable.create(map(subObservable, new Func1, String>() { + @Override + public String call(Map map) { + return map.get("firstName"); + } + })); + } + + })); + m.subscribe(stringObserver); + + verify(stringObserver, never()).onError(any(Throwable.class)); + verify(stringObserver, times(1)).onNext("OneFirst"); + verify(stringObserver, times(1)).onNext("TwoFirst"); + verify(stringObserver, times(1)).onNext("ThreeFirst"); + verify(stringObserver, times(1)).onNext("FourFirst"); + verify(stringObserver, times(1)).onCompleted(); + } + + @Test + public void testMapMany2() { + Map m1 = getMap("One"); + Map m2 = getMap("Two"); + Observable> observable1 = Observable.from(m1, m2); + + Map m3 = getMap("Three"); + Map m4 = getMap("Four"); + Observable> observable2 = Observable.from(m3, m4); + + Observable>> observable = Observable.from(observable1, observable2); + + Observable m = Observable.create(mapMany(observable, new Func1>, Observable>() { + + @Override + public Observable call(Observable> o) { + return Observable.create(map(o, new Func1, String>() { + + @Override + public String call(Map map) { + return map.get("firstName"); + } + })); + } + + })); + m.subscribe(stringObserver); + + verify(stringObserver, never()).onError(any(Throwable.class)); + verify(stringObserver, times(1)).onNext("OneFirst"); + verify(stringObserver, times(1)).onNext("TwoFirst"); + verify(stringObserver, times(1)).onNext("ThreeFirst"); + verify(stringObserver, times(1)).onNext("FourFirst"); + verify(stringObserver, times(1)).onCompleted(); + + } + + @Test + public void testMapWithError() { + Observable w = Observable.from("one", "fail", "two", "three", "fail"); + Observable m = Observable.create(map(w, new Func1() { + @Override + public String call(String s) { + if ("fail".equals(s)) { + throw new RuntimeException("Forced Failure"); + } + return s; + } + })); + + m.subscribe(stringObserver); + verify(stringObserver, times(1)).onNext("one"); + verify(stringObserver, never()).onNext("two"); + verify(stringObserver, never()).onNext("three"); + verify(stringObserver, never()).onCompleted(); + verify(stringObserver, times(1)).onError(any(Throwable.class)); + } + + @Test + public void testMapWithSynchronousObservableContainingError() { + Observable w = Observable.from("one", "fail", "two", "three", "fail"); + final AtomicInteger c1 = new AtomicInteger(); + final AtomicInteger c2 = new AtomicInteger(); + Observable m = Observable.create(map(w, new Func1() { + @Override + public String call(String s) { + if ("fail".equals(s)) + throw new RuntimeException("Forced Failure"); + System.out.println("BadMapper:" + s); + c1.incrementAndGet(); + return s; + } + })).map(new Func1() { + @Override + public String call(String s) { + System.out.println("SecondMapper:" + s); + c2.incrementAndGet(); + return s; + } + }); + + m.subscribe(stringObserver); + + verify(stringObserver, times(1)).onNext("one"); + verify(stringObserver, never()).onNext("two"); + verify(stringObserver, never()).onNext("three"); + verify(stringObserver, never()).onCompleted(); + verify(stringObserver, times(1)).onError(any(Throwable.class)); + + // we should have only returned 1 value: "one" + assertEquals(1, c1.get()); + assertEquals(1, c2.get()); + } + + @Test(expected = IllegalArgumentException.class) + public void testMapWithIssue417() { + Observable.from(1).observeOn(Schedulers.threadPoolForComputation()) + .map(new Func1() { + public Integer call(Integer arg0) { + throw new IllegalArgumentException("any error"); + } + }).toBlockingObservable().single(); + } + + @Test + public void testMapWithErrorInFuncAndThreadPoolScheduler() throws InterruptedException { + // The error will throw in one of threads in the thread pool. + // If map does not handle it, the error will disappear. + // so map needs to handle the error by itself. + final CountDownLatch latch = new CountDownLatch(1); + Observable m = Observable.from("one") + .observeOn(Schedulers.threadPoolForComputation()) + .map(new Func1() { + public String call(String arg0) { + try { + throw new IllegalArgumentException("any error"); + } finally { + latch.countDown(); + } + } + }); + + m.subscribe(stringObserver); + latch.await(); + InOrder inorder = inOrder(stringObserver); + inorder.verify(stringObserver, times(1)).onError(any(IllegalArgumentException.class)); + inorder.verifyNoMoreInteractions(); + } + + private static Map getMap(String prefix) { + Map m = new HashMap(); + m.put("firstName", prefix + "First"); + m.put("lastName", prefix + "Last"); + return m; + } } diff --git a/rxjava-core/src/test/java/rx/operators/OperationMaterializeTest.java b/rxjava-core/src/test/java/rx/operators/OperationMaterializeTest.java index 24f67b432c..f7f4142672 100644 --- a/rxjava-core/src/test/java/rx/operators/OperationMaterializeTest.java +++ b/rxjava-core/src/test/java/rx/operators/OperationMaterializeTest.java @@ -1,7 +1,150 @@ package rx.operators; -import org.junit.Ignore; +import org.junit.Test; +import rx.Notification; +import rx.Observable; +import rx.Observer; +import rx.Subscription; + +import java.util.List; +import java.util.Vector; +import java.util.concurrent.ExecutionException; + +import static org.junit.Assert.*; +import static rx.operators.OperationMaterialize.materialize; -@Ignore("WIP") public class OperationMaterializeTest { + + @Test + public void testMaterialize1() { + // null will cause onError to be triggered before "three" can be returned + final TestAsyncErrorObservable o1 = new TestAsyncErrorObservable("one", "two", null, "three"); + + TestObserver Observer = new TestObserver(); + Observable> m = Observable.create(materialize(Observable.create(o1))); + m.subscribe(Observer); + + try { + o1.t.join(); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + + assertFalse(Observer.onError); + assertTrue(Observer.onCompleted); + assertEquals(3, Observer.notifications.size()); + assertEquals("one", Observer.notifications.get(0).getValue()); + assertTrue(Observer.notifications.get(0).isOnNext()); + assertEquals("two", Observer.notifications.get(1).getValue()); + assertTrue(Observer.notifications.get(1).isOnNext()); + assertEquals(NullPointerException.class, Observer.notifications.get(2).getThrowable().getClass()); + assertTrue(Observer.notifications.get(2).isOnError()); + } + + @Test + public void testMaterialize2() { + final TestAsyncErrorObservable o1 = new TestAsyncErrorObservable("one", "two", "three"); + + TestObserver Observer = new TestObserver(); + Observable> m = Observable.create(materialize(Observable.create(o1))); + m.subscribe(Observer); + + try { + o1.t.join(); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + + assertFalse(Observer.onError); + assertTrue(Observer.onCompleted); + assertEquals(4, Observer.notifications.size()); + assertEquals("one", Observer.notifications.get(0).getValue()); + assertTrue(Observer.notifications.get(0).isOnNext()); + assertEquals("two", Observer.notifications.get(1).getValue()); + assertTrue(Observer.notifications.get(1).isOnNext()); + assertEquals("three", Observer.notifications.get(2).getValue()); + assertTrue(Observer.notifications.get(2).isOnNext()); + assertTrue(Observer.notifications.get(3).isOnCompleted()); + } + + @Test + public void testMultipleSubscribes() throws InterruptedException, ExecutionException { + final TestAsyncErrorObservable o = new TestAsyncErrorObservable("one", "two", null, "three"); + + Observable> m = Observable.create(materialize(Observable.create(o))); + + assertEquals(3, m.toList().toBlockingObservable().toFuture().get().size()); + assertEquals(3, m.toList().toBlockingObservable().toFuture().get().size()); + } + + private static class TestObserver implements Observer> { + + boolean onCompleted = false; + boolean onError = false; + List> notifications = new Vector>(); + + @Override + public void onCompleted() { + this.onCompleted = true; + } + + @Override + public void onError(Throwable e) { + this.onError = true; + } + + @Override + public void onNext(Notification value) { + this.notifications.add(value); + } + + } + + private static class TestAsyncErrorObservable implements Observable.OnSubscribeFunc { + + String[] valuesToReturn; + + TestAsyncErrorObservable(String... values) { + valuesToReturn = values; + } + + volatile Thread t; + + @Override + public Subscription onSubscribe(final Observer observer) { + t = new Thread(new Runnable() { + + @Override + public void run() { + for (String s : valuesToReturn) { + if (s == null) { + System.out.println("throwing exception"); + try { + Thread.sleep(100); + } catch (Throwable e) { + + } + observer.onError(new NullPointerException()); + return; + } else { + observer.onNext(s); + } + } + System.out.println("subscription complete"); + observer.onCompleted(); + } + + }); + t.start(); + + return new Subscription() { + + @Override + public void unsubscribe() { + + } + + }; + } + } } diff --git a/rxjava-core/src/test/java/rx/operators/OperationMergeDelayErrorTest.java b/rxjava-core/src/test/java/rx/operators/OperationMergeDelayErrorTest.java index 1e3c763573..03dbcd7044 100644 --- a/rxjava-core/src/test/java/rx/operators/OperationMergeDelayErrorTest.java +++ b/rxjava-core/src/test/java/rx/operators/OperationMergeDelayErrorTest.java @@ -1,7 +1,500 @@ package rx.operators; -import org.junit.Ignore; +import org.junit.Before; +import org.junit.Test; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import rx.Observable; +import rx.Observer; +import rx.Subscription; +import rx.util.CompositeException; + +import java.util.ArrayList; +import java.util.List; + +import static org.junit.Assert.*; +import static org.mockito.Matchers.any; +import static org.mockito.Mockito.*; +import static rx.operators.OperationMergeDelayError.mergeDelayError; -@Ignore("WIP") public class OperationMergeDelayErrorTest { + + + @Mock + Observer stringObserver; + + @Before + public void before() { + MockitoAnnotations.initMocks(this); + } + + @Test + public void testErrorDelayed1() { + final Observable o1 = Observable.create(new TestErrorObservable("four", null, "six")); // we expect to lose "six" from the source (and it should never be sent by the source since onError was called + final Observable o2 = Observable.create(new TestErrorObservable("one", "two", "three")); + + @SuppressWarnings("unchecked") + Observable m = Observable.create(mergeDelayError(o1, o2)); + m.subscribe(stringObserver); + + verify(stringObserver, times(1)).onError(any(NullPointerException.class)); + verify(stringObserver, never()).onCompleted(); + verify(stringObserver, times(1)).onNext("one"); + verify(stringObserver, times(1)).onNext("two"); + verify(stringObserver, times(1)).onNext("three"); + verify(stringObserver, times(1)).onNext("four"); + verify(stringObserver, times(0)).onNext("five"); + verify(stringObserver, times(0)).onNext("six"); + } + + @Test + public void testErrorDelayed2() { + final Observable o1 = Observable.create(new TestErrorObservable("one", "two", "three")); + final Observable o2 = Observable.create(new TestErrorObservable("four", null, "six")); // we expect to lose "six" from the source (and it should never be sent by the source since onError was called + final Observable o3 = Observable.create(new TestErrorObservable("seven", "eight", null)); + final Observable o4 = Observable.create(new TestErrorObservable("nine")); + + @SuppressWarnings("unchecked") + Observable m = Observable.create(mergeDelayError(o1, o2, o3, o4)); + m.subscribe(stringObserver); + + verify(stringObserver, times(1)).onError(any(NullPointerException.class)); + verify(stringObserver, never()).onCompleted(); + verify(stringObserver, times(1)).onNext("one"); + verify(stringObserver, times(1)).onNext("two"); + verify(stringObserver, times(1)).onNext("three"); + verify(stringObserver, times(1)).onNext("four"); + verify(stringObserver, times(0)).onNext("five"); + verify(stringObserver, times(0)).onNext("six"); + verify(stringObserver, times(1)).onNext("seven"); + verify(stringObserver, times(1)).onNext("eight"); + verify(stringObserver, times(1)).onNext("nine"); + } + + @Test + public void testErrorDelayed3() { + final Observable o1 = Observable.create(new TestErrorObservable("one", "two", "three")); + final Observable o2 = Observable.create(new TestErrorObservable("four", "five", "six")); + final Observable o3 = Observable.create(new TestErrorObservable("seven", "eight", null)); + final Observable o4 = Observable.create(new TestErrorObservable("nine")); + + @SuppressWarnings("unchecked") + Observable m = Observable.create(mergeDelayError(o1, o2, o3, o4)); + m.subscribe(stringObserver); + + verify(stringObserver, times(1)).onError(any(NullPointerException.class)); + verify(stringObserver, never()).onCompleted(); + verify(stringObserver, times(1)).onNext("one"); + verify(stringObserver, times(1)).onNext("two"); + verify(stringObserver, times(1)).onNext("three"); + verify(stringObserver, times(1)).onNext("four"); + verify(stringObserver, times(1)).onNext("five"); + verify(stringObserver, times(1)).onNext("six"); + verify(stringObserver, times(1)).onNext("seven"); + verify(stringObserver, times(1)).onNext("eight"); + verify(stringObserver, times(1)).onNext("nine"); + } + + @Test + public void testErrorDelayed4() { + final Observable o1 = Observable.create(new TestErrorObservable("one", "two", "three")); + final Observable o2 = Observable.create(new TestErrorObservable("four", "five", "six")); + final Observable o3 = Observable.create(new TestErrorObservable("seven", "eight")); + final Observable o4 = Observable.create(new TestErrorObservable("nine", null)); + + @SuppressWarnings("unchecked") + Observable m = Observable.create(mergeDelayError(o1, o2, o3, o4)); + m.subscribe(stringObserver); + + verify(stringObserver, times(1)).onError(any(NullPointerException.class)); + verify(stringObserver, never()).onCompleted(); + verify(stringObserver, times(1)).onNext("one"); + verify(stringObserver, times(1)).onNext("two"); + verify(stringObserver, times(1)).onNext("three"); + verify(stringObserver, times(1)).onNext("four"); + verify(stringObserver, times(1)).onNext("five"); + verify(stringObserver, times(1)).onNext("six"); + verify(stringObserver, times(1)).onNext("seven"); + verify(stringObserver, times(1)).onNext("eight"); + verify(stringObserver, times(1)).onNext("nine"); + } + + @Test + public void testErrorDelayed4WithThreading() { + final TestAsyncErrorObservable o1 = new TestAsyncErrorObservable("one", "two", "three"); + final TestAsyncErrorObservable o2 = new TestAsyncErrorObservable("four", "five", "six"); + final TestAsyncErrorObservable o3 = new TestAsyncErrorObservable("seven", "eight"); + // throw the error at the very end so no onComplete will be called after it + final TestAsyncErrorObservable o4 = new TestAsyncErrorObservable("nine", null); + + @SuppressWarnings("unchecked") + Observable m = Observable.create(mergeDelayError(Observable.create(o1), Observable.create(o2), Observable.create(o3), Observable.create(o4))); + m.subscribe(stringObserver); + + try { + o1.t.join(); + o2.t.join(); + o3.t.join(); + o4.t.join(); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + + verify(stringObserver, times(1)).onError(any(NullPointerException.class)); + verify(stringObserver, never()).onCompleted(); + verify(stringObserver, times(1)).onNext("one"); + verify(stringObserver, times(1)).onNext("two"); + verify(stringObserver, times(1)).onNext("three"); + verify(stringObserver, times(1)).onNext("four"); + verify(stringObserver, times(1)).onNext("five"); + verify(stringObserver, times(1)).onNext("six"); + verify(stringObserver, times(1)).onNext("seven"); + verify(stringObserver, times(1)).onNext("eight"); + verify(stringObserver, times(1)).onNext("nine"); + } + + @Test + public void testCompositeErrorDelayed1() { + final Observable o1 = Observable.create(new TestErrorObservable("four", null, "six")); // we expect to lose "six" from the source (and it should never be sent by the source since onError was called + final Observable o2 = Observable.create(new TestErrorObservable("one", "two", null)); + + @SuppressWarnings("unchecked") + Observable m = Observable.create(mergeDelayError(o1, o2)); + m.subscribe(stringObserver); + + verify(stringObserver, times(1)).onError(any(CompositeException.class)); + verify(stringObserver, never()).onCompleted(); + verify(stringObserver, times(1)).onNext("one"); + verify(stringObserver, times(1)).onNext("two"); + verify(stringObserver, times(0)).onNext("three"); + verify(stringObserver, times(1)).onNext("four"); + verify(stringObserver, times(0)).onNext("five"); + verify(stringObserver, times(0)).onNext("six"); + } + + @Test + public void testCompositeErrorDelayed2() { + final Observable o1 = Observable.create(new TestErrorObservable("four", null, "six")); // we expect to lose "six" from the source (and it should never be sent by the source since onError was called + final Observable o2 = Observable.create(new TestErrorObservable("one", "two", null)); + + @SuppressWarnings("unchecked") + Observable m = Observable.create(mergeDelayError(o1, o2)); + CaptureObserver w = new CaptureObserver(); + m.subscribe(w); + + assertNotNull(w.e); + if (w.e instanceof CompositeException) { + assertEquals(2, ((CompositeException) w.e).getExceptions().size()); + w.e.printStackTrace(); + } else { + fail("Expecting CompositeException"); + } + + } + + /** + * The unit tests below are from OperationMerge and should ensure the normal merge functionality is correct. + */ + + @Test + public void testMergeObservableOfObservables() { + final Observable o1 = Observable.create(new TestSynchronousObservable()); + final Observable o2 = Observable.create(new TestSynchronousObservable()); + + Observable> observableOfObservables = Observable.create(new Observable.OnSubscribeFunc>() { + + @Override + public Subscription onSubscribe(Observer> observer) { + // simulate what would happen in an observable + observer.onNext(o1); + observer.onNext(o2); + observer.onCompleted(); + + return new Subscription() { + + @Override + public void unsubscribe() { + // unregister ... will never be called here since we are executing synchronously + } + + }; + } + + }); + Observable m = Observable.create(mergeDelayError(observableOfObservables)); + m.subscribe(stringObserver); + + verify(stringObserver, never()).onError(any(Throwable.class)); + verify(stringObserver, times(1)).onCompleted(); + verify(stringObserver, times(2)).onNext("hello"); + } + + @Test + public void testMergeArray() { + final Observable o1 = Observable.create(new TestSynchronousObservable()); + final Observable o2 = Observable.create(new TestSynchronousObservable()); + + @SuppressWarnings("unchecked") + Observable m = Observable.create(mergeDelayError(o1, o2)); + m.subscribe(stringObserver); + + verify(stringObserver, never()).onError(any(Throwable.class)); + verify(stringObserver, times(2)).onNext("hello"); + verify(stringObserver, times(1)).onCompleted(); + } + + @Test + public void testMergeList() { + final Observable o1 = Observable.create(new TestSynchronousObservable()); + final Observable o2 = Observable.create(new TestSynchronousObservable()); + List> listOfObservables = new ArrayList>(); + listOfObservables.add(o1); + listOfObservables.add(o2); + + Observable m = Observable.create(mergeDelayError(listOfObservables)); + m.subscribe(stringObserver); + + verify(stringObserver, never()).onError(any(Throwable.class)); + verify(stringObserver, times(1)).onCompleted(); + verify(stringObserver, times(2)).onNext("hello"); + } + + @Test + public void testUnSubscribe() { + TestObservable tA = new TestObservable(); + TestObservable tB = new TestObservable(); + + @SuppressWarnings("unchecked") + Observable m = Observable.create(mergeDelayError(Observable.create(tA), Observable.create(tB))); + Subscription s = m.subscribe(stringObserver); + + tA.sendOnNext("Aone"); + tB.sendOnNext("Bone"); + s.unsubscribe(); + tA.sendOnNext("Atwo"); + tB.sendOnNext("Btwo"); + tA.sendOnCompleted(); + tB.sendOnCompleted(); + + verify(stringObserver, never()).onError(any(Throwable.class)); + verify(stringObserver, times(1)).onNext("Aone"); + verify(stringObserver, times(1)).onNext("Bone"); + assertTrue(tA.unsubscribed); + assertTrue(tB.unsubscribed); + verify(stringObserver, never()).onNext("Atwo"); + verify(stringObserver, never()).onNext("Btwo"); + verify(stringObserver, never()).onCompleted(); + } + + @Test + public void testMergeArrayWithThreading() { + final TestASynchronousObservable o1 = new TestASynchronousObservable(); + final TestASynchronousObservable o2 = new TestASynchronousObservable(); + + @SuppressWarnings("unchecked") + Observable m = Observable.create(mergeDelayError(Observable.create(o1), Observable.create(o2))); + m.subscribe(stringObserver); + + try { + o1.t.join(); + o2.t.join(); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + + verify(stringObserver, never()).onError(any(Throwable.class)); + verify(stringObserver, times(2)).onNext("hello"); + verify(stringObserver, times(1)).onCompleted(); + } + + private static class TestSynchronousObservable implements Observable.OnSubscribeFunc { + + @Override + public Subscription onSubscribe(Observer observer) { + + observer.onNext("hello"); + observer.onCompleted(); + + return new Subscription() { + + @Override + public void unsubscribe() { + // unregister ... will never be called here since we are executing synchronously + } + + }; + } + } + + private static class TestASynchronousObservable implements Observable.OnSubscribeFunc { + Thread t; + + @Override + public Subscription onSubscribe(final Observer observer) { + t = new Thread(new Runnable() { + + @Override + public void run() { + observer.onNext("hello"); + observer.onCompleted(); + } + + }); + t.start(); + + return new Subscription() { + + @Override + public void unsubscribe() { + + } + + }; + } + } + + /** + * A Observable that doesn't do the right thing on UnSubscribe/Error/etc in that it will keep sending events down the pipe regardless of what happens. + */ + private static class TestObservable implements Observable.OnSubscribeFunc { + + Observer observer = null; + volatile boolean unsubscribed = false; + Subscription s = new Subscription() { + + @Override + public void unsubscribe() { + unsubscribed = true; + + } + + }; + + /* used to simulate subscription */ + public void sendOnCompleted() { + observer.onCompleted(); + } + + /* used to simulate subscription */ + public void sendOnNext(String value) { + observer.onNext(value); + } + + /* used to simulate subscription */ + @SuppressWarnings("unused") + public void sendOnError(Throwable e) { + observer.onError(e); + } + + @Override + public Subscription onSubscribe(final Observer observer) { + this.observer = observer; + return s; + } + } + + private static class TestErrorObservable implements Observable.OnSubscribeFunc { + + String[] valuesToReturn; + + TestErrorObservable(String... values) { + valuesToReturn = values; + } + + @Override + public Subscription onSubscribe(Observer observer) { + boolean errorThrown = false; + for (String s : valuesToReturn) { + if (s == null) { + System.out.println("throwing exception"); + observer.onError(new NullPointerException()); + errorThrown = true; + // purposefully not returning here so it will continue calling onNext + // so that we also test that we handle bad sequences like this + } else { + observer.onNext(s); + } + } + if (!errorThrown) { + observer.onCompleted(); + } + + return new Subscription() { + + @Override + public void unsubscribe() { + // unregister ... will never be called here since we are executing synchronously + } + + }; + } + } + + private static class TestAsyncErrorObservable implements Observable.OnSubscribeFunc { + + String[] valuesToReturn; + + TestAsyncErrorObservable(String... values) { + valuesToReturn = values; + } + + Thread t; + + @Override + public Subscription onSubscribe(final Observer observer) { + t = new Thread(new Runnable() { + + @Override + public void run() { + for (String s : valuesToReturn) { + if (s == null) { + System.out.println("throwing exception"); + try { + Thread.sleep(100); + } catch (Throwable e) { + + } + observer.onError(new NullPointerException()); + return; + } else { + observer.onNext(s); + } + } + System.out.println("subscription complete"); + observer.onCompleted(); + } + + }); + t.start(); + + return new Subscription() { + + @Override + public void unsubscribe() { + + } + + }; + } + } + + private static class CaptureObserver implements Observer { + volatile Throwable e; + + @Override + public void onCompleted() { + + } + + @Override + public void onError(Throwable e) { + this.e = e; + } + + @Override + public void onNext(String args) { + + } + + } } diff --git a/rxjava-core/src/test/java/rx/operators/OperationMergeTest.java b/rxjava-core/src/test/java/rx/operators/OperationMergeTest.java index ef50b179e6..b3bdf1423c 100644 --- a/rxjava-core/src/test/java/rx/operators/OperationMergeTest.java +++ b/rxjava-core/src/test/java/rx/operators/OperationMergeTest.java @@ -1,7 +1,458 @@ package rx.operators; -import org.junit.Ignore; +import org.junit.Before; +import org.junit.Test; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import rx.Observable; +import rx.Observer; +import rx.Subscription; +import rx.subscriptions.Subscriptions; +import rx.util.functions.Action0; +import rx.util.functions.Action1; + +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicInteger; + +import static org.junit.Assert.*; +import static org.mockito.Matchers.any; +import static org.mockito.Mockito.*; +import static rx.operators.OperationMerge.merge; -@Ignore("WIP") public class OperationMergeTest { + + @Mock + Observer stringObserver; + + @Before + public void before() { + MockitoAnnotations.initMocks(this); + } + + @Test + public void testMergeObservableOfObservables() { + final Observable o1 = Observable.create(new TestSynchronousObservable()); + final Observable o2 = Observable.create(new TestSynchronousObservable()); + + Observable> observableOfObservables = Observable.create(new Observable.OnSubscribeFunc>() { + + @Override + public Subscription onSubscribe(Observer> observer) { + // simulate what would happen in an observable + observer.onNext(o1); + observer.onNext(o2); + observer.onCompleted(); + + return new Subscription() { + + @Override + public void unsubscribe() { + // unregister ... will never be called here since we are executing synchronously + } + + }; + } + + }); + Observable m = Observable.create(merge(observableOfObservables)); + m.subscribe(stringObserver); + + verify(stringObserver, never()).onError(any(Throwable.class)); + verify(stringObserver, times(1)).onCompleted(); + verify(stringObserver, times(2)).onNext("hello"); + } + + @Test + public void testMergeArray() { + final Observable o1 = Observable.create(new TestSynchronousObservable()); + final Observable o2 = Observable.create(new TestSynchronousObservable()); + + @SuppressWarnings("unchecked") + Observable m = Observable.create(merge(o1, o2)); + m.subscribe(stringObserver); + + verify(stringObserver, never()).onError(any(Throwable.class)); + verify(stringObserver, times(2)).onNext("hello"); + verify(stringObserver, times(1)).onCompleted(); + } + + @Test + public void testMergeList() { + final Observable o1 = Observable.create(new TestSynchronousObservable()); + final Observable o2 = Observable.create(new TestSynchronousObservable()); + List> listOfObservables = new ArrayList>(); + listOfObservables.add(o1); + listOfObservables.add(o2); + + Observable m = Observable.create(merge(listOfObservables)); + m.subscribe(stringObserver); + + verify(stringObserver, never()).onError(any(Throwable.class)); + verify(stringObserver, times(1)).onCompleted(); + verify(stringObserver, times(2)).onNext("hello"); + } + + @Test + public void testUnSubscribe() { + TestObservable tA = new TestObservable(); + TestObservable tB = new TestObservable(); + + @SuppressWarnings("unchecked") + Observable m = Observable.create(merge(Observable.create(tA), Observable.create(tB))); + Subscription s = m.subscribe(stringObserver); + + tA.sendOnNext("Aone"); + tB.sendOnNext("Bone"); + s.unsubscribe(); + tA.sendOnNext("Atwo"); + tB.sendOnNext("Btwo"); + tA.sendOnCompleted(); + tB.sendOnCompleted(); + + verify(stringObserver, never()).onError(any(Throwable.class)); + verify(stringObserver, times(1)).onNext("Aone"); + verify(stringObserver, times(1)).onNext("Bone"); + assertTrue(tA.unsubscribed); + assertTrue(tB.unsubscribed); + verify(stringObserver, never()).onNext("Atwo"); + verify(stringObserver, never()).onNext("Btwo"); + verify(stringObserver, never()).onCompleted(); + } + + @Test + public void testUnSubscribeObservableOfObservables() throws InterruptedException { + + final AtomicBoolean unsubscribed = new AtomicBoolean(); + final CountDownLatch latch = new CountDownLatch(1); + + Observable> source = Observable.create(new Observable.OnSubscribeFunc>() { + + @Override + public Subscription onSubscribe(final Observer> observer) { + // verbose on purpose so I can track the inside of it + final Subscription s = Subscriptions.create(new Action0() { + + @Override + public void call() { + System.out.println("*** unsubscribed"); + unsubscribed.set(true); + } + + }); + + new Thread(new Runnable() { + + @Override + public void run() { + + while (!unsubscribed.get()) { + observer.onNext(Observable.from(1L, 2L)); + } + System.out.println("Done looping after unsubscribe: " + unsubscribed.get()); + observer.onCompleted(); + + // mark that the thread is finished + latch.countDown(); + } + }).start(); + + return s; + } + + ; + + }); + + final AtomicInteger count = new AtomicInteger(); + Observable.create(merge(source)).take(6).toBlockingObservable().forEach(new Action1() { + + @Override + public void call(Long v) { + System.out.println("Value: " + v); + int c = count.incrementAndGet(); + if (c > 6) { + fail("Should be only 6"); + } + + } + }); + + latch.await(1000, TimeUnit.MILLISECONDS); + + System.out.println("unsubscribed: " + unsubscribed.get()); + + assertTrue(unsubscribed.get()); + + } + + @Test + public void testMergeArrayWithThreading() { + final TestASynchronousObservable o1 = new TestASynchronousObservable(); + final TestASynchronousObservable o2 = new TestASynchronousObservable(); + + @SuppressWarnings("unchecked") + Observable m = Observable.create(merge(Observable.create(o1), Observable.create(o2))); + m.subscribe(stringObserver); + + try { + o1.t.join(); + o2.t.join(); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + + verify(stringObserver, never()).onError(any(Throwable.class)); + verify(stringObserver, times(2)).onNext("hello"); + verify(stringObserver, times(1)).onCompleted(); + } + + @Test + public void testSynchronizationOfMultipleSequences() throws Throwable { + final TestASynchronousObservable o1 = new TestASynchronousObservable(); + final TestASynchronousObservable o2 = new TestASynchronousObservable(); + + // use this latch to cause onNext to wait until we're ready to let it go + final CountDownLatch endLatch = new CountDownLatch(1); + + final AtomicInteger concurrentCounter = new AtomicInteger(); + final AtomicInteger totalCounter = new AtomicInteger(); + + @SuppressWarnings("unchecked") + Observable m = Observable.create(merge(Observable.create(o1), Observable.create(o2))); + m.subscribe(new Observer() { + + @Override + public void onCompleted() { + + } + + @Override + public void onError(Throwable e) { + throw new RuntimeException("failed", e); + } + + @Override + public void onNext(String v) { + totalCounter.incrementAndGet(); + concurrentCounter.incrementAndGet(); + try { + // wait here until we're done asserting + endLatch.await(); + } catch (InterruptedException e) { + e.printStackTrace(); + throw new RuntimeException("failed", e); + } finally { + concurrentCounter.decrementAndGet(); + } + } + + }); + + // wait for both observables to send (one should be blocked) + o1.onNextBeingSent.await(); + o2.onNextBeingSent.await(); + + // I can't think of a way to know for sure that both threads have or are trying to send onNext + // since I can't use a CountDownLatch for "after" onNext since I want to catch during it + // but I can't know for sure onNext is invoked + // so I'm unfortunately reverting to using a Thread.sleep to allow the process scheduler time + // to make sure after o1.onNextBeingSent and o2.onNextBeingSent are hit that the following + // onNext is invoked. + + Thread.sleep(300); + + try { // in try/finally so threads are released via latch countDown even if assertion fails + assertEquals(1, concurrentCounter.get()); + } finally { + // release so it can finish + endLatch.countDown(); + } + + try { + o1.t.join(); + o2.t.join(); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + + assertEquals(2, totalCounter.get()); + assertEquals(0, concurrentCounter.get()); + } + + /** + * unit test from OperationMergeDelayError backported here to show how these use cases work with normal merge + */ + @Test + public void testError1() { + // we are using synchronous execution to test this exactly rather than non-deterministic concurrent behavior + final Observable o1 = Observable.create(new TestErrorObservable("four", null, "six")); // we expect to lose "six" + final Observable o2 = Observable.create(new TestErrorObservable("one", "two", "three")); // we expect to lose all of these since o1 is done first and fails + + @SuppressWarnings("unchecked") + Observable m = Observable.create(merge(o1, o2)); + m.subscribe(stringObserver); + + verify(stringObserver, times(1)).onError(any(NullPointerException.class)); + verify(stringObserver, never()).onCompleted(); + verify(stringObserver, times(0)).onNext("one"); + verify(stringObserver, times(0)).onNext("two"); + verify(stringObserver, times(0)).onNext("three"); + verify(stringObserver, times(1)).onNext("four"); + verify(stringObserver, times(0)).onNext("five"); + verify(stringObserver, times(0)).onNext("six"); + } + + /** + * unit test from OperationMergeDelayError backported here to show how these use cases work with normal merge + */ + @Test + public void testError2() { + // we are using synchronous execution to test this exactly rather than non-deterministic concurrent behavior + final Observable o1 = Observable.create(new TestErrorObservable("one", "two", "three")); + final Observable o2 = Observable.create(new TestErrorObservable("four", null, "six")); // we expect to lose "six" + final Observable o3 = Observable.create(new TestErrorObservable("seven", "eight", null));// we expect to lose all of these since o2 is done first and fails + final Observable o4 = Observable.create(new TestErrorObservable("nine"));// we expect to lose all of these since o2 is done first and fails + + @SuppressWarnings("unchecked") + Observable m = Observable.create(merge(o1, o2, o3, o4)); + m.subscribe(stringObserver); + + verify(stringObserver, times(1)).onError(any(NullPointerException.class)); + verify(stringObserver, never()).onCompleted(); + verify(stringObserver, times(1)).onNext("one"); + verify(stringObserver, times(1)).onNext("two"); + verify(stringObserver, times(1)).onNext("three"); + verify(stringObserver, times(1)).onNext("four"); + verify(stringObserver, times(0)).onNext("five"); + verify(stringObserver, times(0)).onNext("six"); + verify(stringObserver, times(0)).onNext("seven"); + verify(stringObserver, times(0)).onNext("eight"); + verify(stringObserver, times(0)).onNext("nine"); + } + + private static class TestSynchronousObservable implements Observable.OnSubscribeFunc { + + @Override + public Subscription onSubscribe(Observer observer) { + + observer.onNext("hello"); + observer.onCompleted(); + + return new Subscription() { + + @Override + public void unsubscribe() { + // unregister ... will never be called here since we are executing synchronously + } + + }; + } + } + + private static class TestASynchronousObservable implements Observable.OnSubscribeFunc { + Thread t; + final CountDownLatch onNextBeingSent = new CountDownLatch(1); + + @Override + public Subscription onSubscribe(final Observer observer) { + t = new Thread(new Runnable() { + + @Override + public void run() { + onNextBeingSent.countDown(); + observer.onNext("hello"); + // I can't use a countDownLatch to prove we are actually sending 'onNext' + // since it will block if synchronized and I'll deadlock + observer.onCompleted(); + } + + }); + t.start(); + + return new Subscription() { + + @Override + public void unsubscribe() { + + } + + }; + } + } + + /** + * A Observable that doesn't do the right thing on UnSubscribe/Error/etc in that it will keep sending events down the pipe regardless of what happens. + */ + private static class TestObservable implements Observable.OnSubscribeFunc { + + Observer observer = null; + volatile boolean unsubscribed = false; + Subscription s = new Subscription() { + + @Override + public void unsubscribe() { + unsubscribed = true; + + } + + }; + + /* used to simulate subscription */ + public void sendOnCompleted() { + observer.onCompleted(); + } + + /* used to simulate subscription */ + public void sendOnNext(String value) { + observer.onNext(value); + } + + /* used to simulate subscription */ + @SuppressWarnings("unused") + public void sendOnError(Throwable e) { + observer.onError(e); + } + + @Override + public Subscription onSubscribe(final Observer observer) { + this.observer = observer; + return s; + } + } + + private static class TestErrorObservable implements Observable.OnSubscribeFunc { + + String[] valuesToReturn; + + TestErrorObservable(String... values) { + valuesToReturn = values; + } + + @Override + public Subscription onSubscribe(Observer observer) { + + for (String s : valuesToReturn) { + if (s == null) { + System.out.println("throwing exception"); + observer.onError(new NullPointerException()); + } else { + observer.onNext(s); + } + } + observer.onCompleted(); + + return new Subscription() { + + @Override + public void unsubscribe() { + // unregister ... will never be called here since we are executing synchronously + } + + }; + } + } } diff --git a/rxjava-core/src/test/java/rx/operators/OperationMostRecentTest.java b/rxjava-core/src/test/java/rx/operators/OperationMostRecentTest.java index 1f5806b310..35c6c9fadf 100644 --- a/rxjava-core/src/test/java/rx/operators/OperationMostRecentTest.java +++ b/rxjava-core/src/test/java/rx/operators/OperationMostRecentTest.java @@ -1,7 +1,59 @@ package rx.operators; -import org.junit.Ignore; +import org.junit.Test; +import rx.subjects.PublishSubject; +import rx.subjects.Subject; + +import java.util.Iterator; + +import static org.junit.Assert.*; +import static rx.operators.OperationMostRecent.mostRecent; -@Ignore("WIP") public class OperationMostRecentTest { + + + @Test + public void testMostRecent() { + Subject observable = PublishSubject.create(); + + Iterator it = mostRecent(observable, "default").iterator(); + + assertTrue(it.hasNext()); + assertEquals("default", it.next()); + assertEquals("default", it.next()); + + observable.onNext("one"); + assertTrue(it.hasNext()); + assertEquals("one", it.next()); + assertEquals("one", it.next()); + + observable.onNext("two"); + assertTrue(it.hasNext()); + assertEquals("two", it.next()); + assertEquals("two", it.next()); + + observable.onCompleted(); + assertFalse(it.hasNext()); + + } + + @Test(expected = TestException.class) + public void testMostRecentWithException() { + Subject observable = PublishSubject.create(); + + Iterator it = mostRecent(observable, "default").iterator(); + + assertTrue(it.hasNext()); + assertEquals("default", it.next()); + assertEquals("default", it.next()); + + observable.onError(new TestException()); + assertTrue(it.hasNext()); + + it.next(); + } + + private static class TestException extends RuntimeException { + private static final long serialVersionUID = 1L; + } } diff --git a/rxjava-core/src/test/java/rx/operators/OperationMulticastTest.java b/rxjava-core/src/test/java/rx/operators/OperationMulticastTest.java index dd2ba06360..e33ee00de3 100644 --- a/rxjava-core/src/test/java/rx/operators/OperationMulticastTest.java +++ b/rxjava-core/src/test/java/rx/operators/OperationMulticastTest.java @@ -1,7 +1,97 @@ package rx.operators; -import org.junit.Ignore; +import org.junit.Test; +import rx.Observer; +import rx.Subscription; +import rx.observables.ConnectableObservable; +import rx.subjects.PublishSubject; +import rx.subjects.Subject; + +import static org.mockito.Mockito.*; -@Ignore("WIP") public class OperationMulticastTest { + + @Test + public void testMulticast() { + Subject source = PublishSubject.create(); + + ConnectableObservable multicasted = OperationMulticast.multicast(source, + PublishSubject.create()); + + @SuppressWarnings("unchecked") + Observer observer = mock(Observer.class); + multicasted.subscribe(observer); + + source.onNext("one"); + source.onNext("two"); + + multicasted.connect(); + + source.onNext("three"); + source.onNext("four"); + source.onCompleted(); + + verify(observer, never()).onNext("one"); + verify(observer, never()).onNext("two"); + verify(observer, times(1)).onNext("three"); + verify(observer, times(1)).onNext("four"); + verify(observer, times(1)).onCompleted(); + + } + + @Test + public void testMulticastConnectTwice() { + Subject source = PublishSubject.create(); + + ConnectableObservable multicasted = OperationMulticast.multicast(source, + PublishSubject.create()); + + @SuppressWarnings("unchecked") + Observer observer = mock(Observer.class); + multicasted.subscribe(observer); + + source.onNext("one"); + + multicasted.connect(); + multicasted.connect(); + + source.onNext("two"); + source.onCompleted(); + + verify(observer, never()).onNext("one"); + verify(observer, times(1)).onNext("two"); + verify(observer, times(1)).onCompleted(); + + } + + @Test + public void testMulticastDisconnect() { + Subject source = PublishSubject.create(); + + ConnectableObservable multicasted = OperationMulticast.multicast(source, + PublishSubject.create()); + + @SuppressWarnings("unchecked") + Observer observer = mock(Observer.class); + multicasted.subscribe(observer); + + source.onNext("one"); + + Subscription connection = multicasted.connect(); + source.onNext("two"); + + connection.unsubscribe(); + source.onNext("three"); + + multicasted.connect(); + source.onNext("four"); + source.onCompleted(); + + verify(observer, never()).onNext("one"); + verify(observer, times(1)).onNext("two"); + verify(observer, never()).onNext("three"); + verify(observer, times(1)).onNext("four"); + verify(observer, times(1)).onCompleted(); + + } } diff --git a/rxjava-core/src/test/java/rx/operators/OperationNextTest.java b/rxjava-core/src/test/java/rx/operators/OperationNextTest.java index bad26bbcb1..c696a64c27 100644 --- a/rxjava-core/src/test/java/rx/operators/OperationNextTest.java +++ b/rxjava-core/src/test/java/rx/operators/OperationNextTest.java @@ -1,7 +1,281 @@ package rx.operators; -import org.junit.Ignore; +import org.junit.Test; +import rx.Observable; +import rx.Observer; +import rx.Subscription; +import rx.concurrency.Schedulers; +import rx.subjects.PublishSubject; +import rx.subjects.Subject; +import rx.subscriptions.Subscriptions; + +import java.util.Iterator; +import java.util.NoSuchElementException; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicInteger; + +import static org.junit.Assert.*; +import static rx.operators.OperationNext.next; -@Ignore("WIP") public class OperationNextTest { + + private void fireOnNextInNewThread(final Subject o, final String value) { + new Thread() { + @Override + public void run() { + try { + Thread.sleep(500); + } catch (InterruptedException e) { + // ignore + } + o.onNext(value); + } + }.start(); + } + + private void fireOnErrorInNewThread(final Subject o) { + new Thread() { + @Override + public void run() { + try { + Thread.sleep(500); + } catch (InterruptedException e) { + // ignore + } + o.onError(new TestException()); + } + }.start(); + } + + + @Test + public void testNext() { + Subject obs = PublishSubject.create(); + Iterator it = next(obs).iterator(); + fireOnNextInNewThread(obs, "one"); + assertTrue(it.hasNext()); + assertEquals("one", it.next()); + + fireOnNextInNewThread(obs, "two"); + assertTrue(it.hasNext()); + assertEquals("two", it.next()); + + obs.onCompleted(); + assertFalse(it.hasNext()); + try { + it.next(); + fail("At the end of an iterator should throw a NoSuchElementException"); + } catch (NoSuchElementException e) { + } + + // If the observable is completed, hasNext always returns false and next always throw a NoSuchElementException. + assertFalse(it.hasNext()); + try { + it.next(); + fail("At the end of an iterator should throw a NoSuchElementException"); + } catch (NoSuchElementException e) { + } + } + + @Test + public void testNextWithError() { + Subject obs = PublishSubject.create(); + Iterator it = next(obs).iterator(); + fireOnNextInNewThread(obs, "one"); + assertTrue(it.hasNext()); + assertEquals("one", it.next()); + + fireOnErrorInNewThread(obs); + try { + it.hasNext(); + fail("Expected an TestException"); + } catch (TestException e) { + } + + assertErrorAfterObservableFail(it); + } + + @Test + public void testNextWithEmpty() { + Observable obs = Observable.empty().observeOn(Schedulers.newThread()); + Iterator it = next(obs).iterator(); + + assertFalse(it.hasNext()); + try { + it.next(); + fail("At the end of an iterator should throw a NoSuchElementException"); + } catch (NoSuchElementException e) { + } + + // If the observable is completed, hasNext always returns false and next always throw a NoSuchElementException. + assertFalse(it.hasNext()); + try { + it.next(); + fail("At the end of an iterator should throw a NoSuchElementException"); + } catch (NoSuchElementException e) { + } + } + + @Test + public void testOnError() throws Throwable { + Subject obs = PublishSubject.create(); + Iterator it = next(obs).iterator(); + + obs.onError(new TestException()); + try { + it.hasNext(); + fail("Expected an TestException"); + } catch (TestException e) { + // successful + } + + assertErrorAfterObservableFail(it); + } + + @Test + public void testOnErrorInNewThread() { + Subject obs = PublishSubject.create(); + Iterator it = next(obs).iterator(); + + fireOnErrorInNewThread(obs); + + try { + it.hasNext(); + fail("Expected an TestException"); + } catch (TestException e) { + // successful + } + + assertErrorAfterObservableFail(it); + } + + private void assertErrorAfterObservableFail(Iterator it) { + // After the observable fails, hasNext and next always throw the exception. + try { + it.hasNext(); + fail("hasNext should throw a TestException"); + } catch (TestException e) { + } + try { + it.next(); + fail("next should throw a TestException"); + } catch (TestException e) { + } + } + + @Test + public void testNextWithOnlyUsingNextMethod() { + Subject obs = PublishSubject.create(); + Iterator it = next(obs).iterator(); + fireOnNextInNewThread(obs, "one"); + assertEquals("one", it.next()); + + fireOnNextInNewThread(obs, "two"); + assertEquals("two", it.next()); + + obs.onCompleted(); + try { + it.next(); + fail("At the end of an iterator should throw a NoSuchElementException"); + } catch (NoSuchElementException e) { + } + } + + @Test + public void testNextWithCallingHasNextMultipleTimes() { + Subject obs = PublishSubject.create(); + Iterator it = next(obs).iterator(); + fireOnNextInNewThread(obs, "one"); + assertTrue(it.hasNext()); + assertTrue(it.hasNext()); + assertTrue(it.hasNext()); + assertTrue(it.hasNext()); + assertEquals("one", it.next()); + + obs.onCompleted(); + try { + it.next(); + fail("At the end of an iterator should throw a NoSuchElementException"); + } catch (NoSuchElementException e) { + } + } + + @SuppressWarnings("serial") + private static class TestException extends RuntimeException { + + } + + /** + * Confirm that no buffering or blocking of the Observable onNext calls occurs and it just grabs the next emitted value. + *

    + * This results in output such as => a: 1 b: 2 c: 89 + * + * @throws Throwable + */ + @Test + public void testNoBufferingOrBlockingOfSequence() throws Throwable { + final CountDownLatch finished = new CountDownLatch(1); + final int COUNT = 30; + final CountDownLatch timeHasPassed = new CountDownLatch(COUNT); + final AtomicBoolean running = new AtomicBoolean(true); + final AtomicInteger count = new AtomicInteger(0); + final Observable obs = Observable.create(new Observable.OnSubscribeFunc() { + + @Override + public Subscription onSubscribe(final Observer o) { + new Thread(new Runnable() { + + @Override + public void run() { + try { + while (running.get()) { + o.onNext(count.incrementAndGet()); + timeHasPassed.countDown(); + } + o.onCompleted(); + } catch (Throwable e) { + o.onError(e); + } finally { + finished.countDown(); + } + } + }).start(); + return Subscriptions.empty(); + } + + }); + + Iterator it = next(obs).iterator(); + + assertTrue(it.hasNext()); + int a = it.next(); + assertTrue(it.hasNext()); + int b = it.next(); + // we should have a different value + assertTrue("a and b should be different", a != b); + + // wait for some time (if times out we are blocked somewhere so fail ... set very high for very slow, constrained machines) + timeHasPassed.await(8000, TimeUnit.MILLISECONDS); + + assertTrue(it.hasNext()); + int c = it.next(); + + assertTrue("c should not just be the next in sequence", c != (b + 1)); + assertTrue("expected that c [" + c + "] is higher than or equal to " + COUNT, c >= COUNT); + + assertTrue(it.hasNext()); + int d = it.next(); + assertTrue(d > c); + + // shut down the thread + running.set(false); + + finished.await(); + + assertFalse(it.hasNext()); + + System.out.println("a: " + a + " b: " + b + " c: " + c); + } } diff --git a/rxjava-core/src/test/java/rx/operators/OperationObserveOnTest.java b/rxjava-core/src/test/java/rx/operators/OperationObserveOnTest.java index 9f439949a8..17b5292130 100644 --- a/rxjava-core/src/test/java/rx/operators/OperationObserveOnTest.java +++ b/rxjava-core/src/test/java/rx/operators/OperationObserveOnTest.java @@ -1,7 +1,68 @@ package rx.operators; -import org.junit.Ignore; +import org.junit.Test; +import org.mockito.InOrder; +import org.mockito.invocation.InvocationOnMock; +import org.mockito.stubbing.Answer; +import rx.Observable; +import rx.Observer; +import rx.concurrency.Schedulers; + +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; + +import static org.junit.Assert.fail; +import static org.mockito.Mockito.*; +import static rx.operators.OperationObserveOn.observeOn; -@Ignore("WIP") public class OperationObserveOnTest { + + /** + * This is testing a no-op path since it uses Schedulers.immediate() which will not do scheduling. + */ + @Test + @SuppressWarnings("unchecked") + public void testObserveOn() { + Observer observer = mock(Observer.class); + Observable.create(observeOn(Observable.from(1, 2, 3), Schedulers.immediate())).subscribe(observer); + + verify(observer, times(1)).onNext(1); + verify(observer, times(1)).onNext(2); + verify(observer, times(1)).onNext(3); + verify(observer, times(1)).onCompleted(); + } + + @Test + @SuppressWarnings("unchecked") + public void testOrdering() throws InterruptedException { + Observable obs = Observable.from("one", null, "two", "three", "four"); + + Observer observer = mock(Observer.class); + + InOrder inOrder = inOrder(observer); + + final CountDownLatch completedLatch = new CountDownLatch(1); + doAnswer(new Answer() { + + @Override + public Void answer(InvocationOnMock invocation) throws Throwable { + completedLatch.countDown(); + return null; + } + }).when(observer).onCompleted(); + + obs.observeOn(Schedulers.threadPoolForComputation()).subscribe(observer); + + if (!completedLatch.await(1000, TimeUnit.MILLISECONDS)) { + fail("timed out waiting"); + } + + inOrder.verify(observer, times(1)).onNext("one"); + inOrder.verify(observer, times(1)).onNext(null); + inOrder.verify(observer, times(1)).onNext("two"); + inOrder.verify(observer, times(1)).onNext("three"); + inOrder.verify(observer, times(1)).onNext("four"); + inOrder.verify(observer, times(1)).onCompleted(); + inOrder.verifyNoMoreInteractions(); + } } diff --git a/rxjava-core/src/test/java/rx/operators/OperationOnErrorResumeNextViaFunctionTest.java b/rxjava-core/src/test/java/rx/operators/OperationOnErrorResumeNextViaFunctionTest.java index 8a98b35dd2..3de89d6a49 100644 --- a/rxjava-core/src/test/java/rx/operators/OperationOnErrorResumeNextViaFunctionTest.java +++ b/rxjava-core/src/test/java/rx/operators/OperationOnErrorResumeNextViaFunctionTest.java @@ -1,7 +1,168 @@ package rx.operators; -import org.junit.Ignore; +import org.junit.Test; +import org.mockito.Mockito; +import rx.Observable; +import rx.Observer; +import rx.Subscription; +import rx.subscriptions.Subscriptions; +import rx.util.functions.Func1; + +import java.util.concurrent.atomic.AtomicReference; + +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.fail; +import static org.mockito.Matchers.any; +import static org.mockito.Mockito.*; +import static rx.operators.OperationOnErrorResumeNextViaFunction.onErrorResumeNextViaFunction; -@Ignore("WIP") public class OperationOnErrorResumeNextViaFunctionTest { + + @Test + public void testResumeNextWithSynchronousExecution() { + final AtomicReference receivedException = new AtomicReference(); + Observable w = Observable.create(new Observable.OnSubscribeFunc() { + + @Override + public Subscription onSubscribe(Observer observer) { + observer.onNext("one"); + observer.onError(new Throwable("injected failure")); + return Subscriptions.empty(); + } + }); + + Func1> resume = new Func1>() { + + @Override + public Observable call(Throwable t1) { + receivedException.set(t1); + return Observable.from("twoResume", "threeResume"); + } + + }; + Observable observable = Observable.create(onErrorResumeNextViaFunction(w, resume)); + + @SuppressWarnings("unchecked") + Observer aObserver = mock(Observer.class); + observable.subscribe(aObserver); + + verify(aObserver, Mockito.never()).onError(any(Throwable.class)); + verify(aObserver, times(1)).onCompleted(); + verify(aObserver, times(1)).onNext("one"); + verify(aObserver, Mockito.never()).onNext("two"); + verify(aObserver, Mockito.never()).onNext("three"); + verify(aObserver, times(1)).onNext("twoResume"); + verify(aObserver, times(1)).onNext("threeResume"); + assertNotNull(receivedException.get()); + } + + @Test + public void testResumeNextWithAsyncExecution() { + final AtomicReference receivedException = new AtomicReference(); + Subscription s = mock(Subscription.class); + TestObservable w = new TestObservable(s, "one"); + Func1> resume = new Func1>() { + + @Override + public Observable call(Throwable t1) { + receivedException.set(t1); + return Observable.from("twoResume", "threeResume"); + } + + }; + Observable observable = Observable.create(onErrorResumeNextViaFunction(Observable.create(w), resume)); + + @SuppressWarnings("unchecked") + Observer aObserver = mock(Observer.class); + observable.subscribe(aObserver); + + try { + w.t.join(); + } catch (InterruptedException e) { + fail(e.getMessage()); + } + + verify(aObserver, Mockito.never()).onError(any(Throwable.class)); + verify(aObserver, times(1)).onCompleted(); + verify(aObserver, times(1)).onNext("one"); + verify(aObserver, Mockito.never()).onNext("two"); + verify(aObserver, Mockito.never()).onNext("three"); + verify(aObserver, times(1)).onNext("twoResume"); + verify(aObserver, times(1)).onNext("threeResume"); + assertNotNull(receivedException.get()); + } + + /** + * Test that when a function throws an exception this is propagated through onError + */ + @Test + public void testFunctionThrowsError() { + Subscription s = mock(Subscription.class); + TestObservable w = new TestObservable(s, "one"); + Func1> resume = new Func1>() { + + @Override + public Observable call(Throwable t1) { + throw new RuntimeException("exception from function"); + } + + }; + Observable observable = Observable.create(onErrorResumeNextViaFunction(Observable.create(w), resume)); + + @SuppressWarnings("unchecked") + Observer aObserver = mock(Observer.class); + observable.subscribe(aObserver); + + try { + w.t.join(); + } catch (InterruptedException e) { + fail(e.getMessage()); + } + + // we should get the "one" value before the error + verify(aObserver, times(1)).onNext("one"); + + // we should have received an onError call on the Observer since the resume function threw an exception + verify(aObserver, times(1)).onError(any(Throwable.class)); + verify(aObserver, times(0)).onCompleted(); + } + + private static class TestObservable implements Observable.OnSubscribeFunc { + + final Subscription s; + final String[] values; + Thread t = null; + + public TestObservable(Subscription s, String... values) { + this.s = s; + this.values = values; + } + + @Override + public Subscription onSubscribe(final Observer observer) { + System.out.println("TestObservable subscribed to ..."); + t = new Thread(new Runnable() { + + @Override + public void run() { + try { + System.out.println("running TestObservable thread"); + for (String s : values) { + System.out.println("TestObservable onNext: " + s); + observer.onNext(s); + } + throw new RuntimeException("Forced Failure"); + } catch (Throwable e) { + observer.onError(e); + } + } + + }); + System.out.println("starting TestObservable thread"); + t.start(); + System.out.println("done starting TestObservable thread"); + return s; + } + + } } diff --git a/rxjava-core/src/test/java/rx/operators/OperationOnErrorResumeNextViaObservableTest.java b/rxjava-core/src/test/java/rx/operators/OperationOnErrorResumeNextViaObservableTest.java index b0ec9f3211..69b62ec495 100644 --- a/rxjava-core/src/test/java/rx/operators/OperationOnErrorResumeNextViaObservableTest.java +++ b/rxjava-core/src/test/java/rx/operators/OperationOnErrorResumeNextViaObservableTest.java @@ -1,7 +1,127 @@ package rx.operators; -import org.junit.Ignore; +import org.junit.Test; +import org.mockito.Mockito; +import rx.Observable; +import rx.Observer; +import rx.Subscription; +import rx.util.functions.Func1; + +import static org.junit.Assert.fail; +import static org.mockito.Matchers.any; +import static org.mockito.Mockito.*; +import static rx.operators.OperationOnErrorResumeNextViaObservable.onErrorResumeNextViaObservable; -@Ignore("WIP") public class OperationOnErrorResumeNextViaObservableTest { + + @Test + public void testResumeNext() { + Subscription s = mock(Subscription.class); + // Trigger failure on second element + TestObservable f = new TestObservable(s, "one", "fail", "two", "three"); + Observable w = Observable.create(f); + Observable resume = Observable.from("twoResume", "threeResume"); + Observable observable = Observable.create(onErrorResumeNextViaObservable(w, resume)); + + @SuppressWarnings("unchecked") + Observer aObserver = mock(Observer.class); + observable.subscribe(aObserver); + + try { + f.t.join(); + } catch (InterruptedException e) { + fail(e.getMessage()); + } + + verify(aObserver, Mockito.never()).onError(any(Throwable.class)); + verify(aObserver, times(1)).onCompleted(); + verify(aObserver, times(1)).onNext("one"); + verify(aObserver, Mockito.never()).onNext("two"); + verify(aObserver, Mockito.never()).onNext("three"); + verify(aObserver, times(1)).onNext("twoResume"); + verify(aObserver, times(1)).onNext("threeResume"); + } + + @Test + public void testMapResumeAsyncNext() { + Subscription sr = mock(Subscription.class); + // Trigger multiple failures + Observable w = Observable.from("one", "fail", "two", "three", "fail"); + // Resume Observable is async + TestObservable f = new TestObservable(sr, "twoResume", "threeResume"); + Observable resume = Observable.create(f); + + // Introduce map function that fails intermittently (Map does not prevent this when the observer is a + // rx.operator incl onErrorResumeNextViaObservable) + w = w.map(new Func1() { + public String call(String s) { + if ("fail".equals(s)) + throw new RuntimeException("Forced Failure"); + System.out.println("BadMapper:" + s); + return s; + } + }); + + Observable observable = Observable.create(onErrorResumeNextViaObservable(w, resume)); + + @SuppressWarnings("unchecked") + Observer aObserver = mock(Observer.class); + observable.subscribe(aObserver); + + try { + f.t.join(); + } catch (InterruptedException e) { + fail(e.getMessage()); + } + + verify(aObserver, Mockito.never()).onError(any(Throwable.class)); + verify(aObserver, times(1)).onCompleted(); + verify(aObserver, times(1)).onNext("one"); + verify(aObserver, Mockito.never()).onNext("two"); + verify(aObserver, Mockito.never()).onNext("three"); + verify(aObserver, times(1)).onNext("twoResume"); + verify(aObserver, times(1)).onNext("threeResume"); + } + + private static class TestObservable implements Observable.OnSubscribeFunc { + + final Subscription s; + final String[] values; + Thread t = null; + + public TestObservable(Subscription s, String... values) { + this.s = s; + this.values = values; + } + + @Override + public Subscription onSubscribe(final Observer observer) { + System.out.println("TestObservable subscribed to ..."); + t = new Thread(new Runnable() { + + @Override + public void run() { + try { + System.out.println("running TestObservable thread"); + for (String s : values) { + if ("fail".equals(s)) + throw new RuntimeException("Forced Failure"); + System.out.println("TestObservable onNext: " + s); + observer.onNext(s); + } + System.out.println("TestObservable onCompleted"); + observer.onCompleted(); + } catch (Throwable e) { + System.out.println("TestObservable onError: " + e); + observer.onError(e); + } + } + + }); + System.out.println("starting TestObservable thread"); + t.start(); + System.out.println("done starting TestObservable thread"); + return s; + } + } } diff --git a/rxjava-core/src/test/java/rx/operators/OperationOnErrorReturnTest.java b/rxjava-core/src/test/java/rx/operators/OperationOnErrorReturnTest.java index 0fe50a7f04..b19e60598f 100644 --- a/rxjava-core/src/test/java/rx/operators/OperationOnErrorReturnTest.java +++ b/rxjava-core/src/test/java/rx/operators/OperationOnErrorReturnTest.java @@ -1,7 +1,130 @@ package rx.operators; -import org.junit.Ignore; +import org.junit.Test; +import org.mockito.Mockito; +import rx.Observable; +import rx.Observer; +import rx.Subscription; +import rx.util.functions.Func1; + +import java.util.concurrent.atomic.AtomicReference; + +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.fail; +import static org.mockito.Matchers.any; +import static org.mockito.Mockito.*; +import static rx.operators.OperationOnErrorReturn.onErrorReturn; -@Ignore("WIP") public class OperationOnErrorReturnTest { + + @Test + public void testResumeNext() { + Subscription s = mock(Subscription.class); + TestObservable f = new TestObservable(s, "one"); + Observable w = Observable.create(f); + final AtomicReference capturedException = new AtomicReference(); + + Observable observable = Observable.create(onErrorReturn(w, new Func1() { + + @Override + public String call(Throwable e) { + capturedException.set(e); + return "failure"; + } + + })); + + @SuppressWarnings("unchecked") + Observer aObserver = mock(Observer.class); + observable.subscribe(aObserver); + + try { + f.t.join(); + } catch (InterruptedException e) { + fail(e.getMessage()); + } + + verify(aObserver, Mockito.never()).onError(any(Throwable.class)); + verify(aObserver, times(1)).onCompleted(); + verify(aObserver, times(1)).onNext("one"); + verify(aObserver, times(1)).onNext("failure"); + assertNotNull(capturedException.get()); + } + + /** + * Test that when a function throws an exception this is propagated through onError + */ + @Test + public void testFunctionThrowsError() { + Subscription s = mock(Subscription.class); + TestObservable f = new TestObservable(s, "one"); + Observable w = Observable.create(f); + final AtomicReference capturedException = new AtomicReference(); + + Observable observable = Observable.create(onErrorReturn(w, new Func1() { + + @Override + public String call(Throwable e) { + capturedException.set(e); + throw new RuntimeException("exception from function"); + } + + })); + + @SuppressWarnings("unchecked") + Observer aObserver = mock(Observer.class); + observable.subscribe(aObserver); + + try { + f.t.join(); + } catch (InterruptedException e) { + fail(e.getMessage()); + } + + // we should get the "one" value before the error + verify(aObserver, times(1)).onNext("one"); + + // we should have received an onError call on the Observer since the resume function threw an exception + verify(aObserver, times(1)).onError(any(Throwable.class)); + verify(aObserver, times(0)).onCompleted(); + assertNotNull(capturedException.get()); + } + + private static class TestObservable implements Observable.OnSubscribeFunc { + + final Subscription s; + final String[] values; + Thread t = null; + + public TestObservable(Subscription s, String... values) { + this.s = s; + this.values = values; + } + + @Override + public Subscription onSubscribe(final Observer observer) { + System.out.println("TestObservable subscribed to ..."); + t = new Thread(new Runnable() { + + @Override + public void run() { + try { + System.out.println("running TestObservable thread"); + for (String s : values) { + System.out.println("TestObservable onNext: " + s); + observer.onNext(s); + } + throw new RuntimeException("Forced Failure"); + } catch (Throwable e) { + observer.onError(e); + } + } + + }); + System.out.println("starting TestObservable thread"); + t.start(); + System.out.println("done starting TestObservable thread"); + return s; + } + } } diff --git a/rxjava-core/src/test/java/rx/operators/OperationOnExceptionResumeNextViaObservableTest.java b/rxjava-core/src/test/java/rx/operators/OperationOnExceptionResumeNextViaObservableTest.java index 4e8a7c1586..ee85ed7517 100644 --- a/rxjava-core/src/test/java/rx/operators/OperationOnExceptionResumeNextViaObservableTest.java +++ b/rxjava-core/src/test/java/rx/operators/OperationOnExceptionResumeNextViaObservableTest.java @@ -1,7 +1,224 @@ package rx.operators; -import org.junit.Ignore; +import org.junit.Test; +import org.mockito.Mockito; +import rx.Observable; +import rx.Observer; +import rx.Subscription; +import rx.util.functions.Func1; + +import static org.junit.Assert.fail; +import static org.mockito.Matchers.any; +import static org.mockito.Mockito.*; +import static rx.operators.OperationOnExceptionResumeNextViaObservable.onExceptionResumeNextViaObservable; -@Ignore("WIP") public class OperationOnExceptionResumeNextViaObservableTest { + + @Test + public void testResumeNextWithException() { + Subscription s = mock(Subscription.class); + // Trigger failure on second element + TestObservable f = new TestObservable(s, "one", "EXCEPTION", "two", "three"); + Observable w = Observable.create(f); + Observable resume = Observable.from("twoResume", "threeResume"); + Observable observable = Observable.create(onExceptionResumeNextViaObservable(w, resume)); + + @SuppressWarnings("unchecked") + Observer aObserver = mock(Observer.class); + observable.subscribe(aObserver); + + try { + f.t.join(); + } catch (InterruptedException e) { + fail(e.getMessage()); + } + + verify(aObserver, times(1)).onNext("one"); + verify(aObserver, Mockito.never()).onNext("two"); + verify(aObserver, Mockito.never()).onNext("three"); + verify(aObserver, times(1)).onNext("twoResume"); + verify(aObserver, times(1)).onNext("threeResume"); + verify(aObserver, Mockito.never()).onError(any(Throwable.class)); + verify(aObserver, times(1)).onCompleted(); + verifyNoMoreInteractions(aObserver); + } + + @Test + public void testResumeNextWithRuntimeException() { + Subscription s = mock(Subscription.class); + // Trigger failure on second element + TestObservable f = new TestObservable(s, "one", "RUNTIMEEXCEPTION", "two", "three"); + Observable w = Observable.create(f); + Observable resume = Observable.from("twoResume", "threeResume"); + Observable observable = Observable.create(onExceptionResumeNextViaObservable(w, resume)); + + @SuppressWarnings("unchecked") + Observer aObserver = mock(Observer.class); + observable.subscribe(aObserver); + + try { + f.t.join(); + } catch (InterruptedException e) { + fail(e.getMessage()); + } + + verify(aObserver, times(1)).onNext("one"); + verify(aObserver, Mockito.never()).onNext("two"); + verify(aObserver, Mockito.never()).onNext("three"); + verify(aObserver, times(1)).onNext("twoResume"); + verify(aObserver, times(1)).onNext("threeResume"); + verify(aObserver, Mockito.never()).onError(any(Throwable.class)); + verify(aObserver, times(1)).onCompleted(); + verifyNoMoreInteractions(aObserver); + } + + @Test + public void testThrowablePassesThru() { + Subscription s = mock(Subscription.class); + // Trigger failure on second element + TestObservable f = new TestObservable(s, "one", "THROWABLE", "two", "three"); + Observable w = Observable.create(f); + Observable resume = Observable.from("twoResume", "threeResume"); + Observable observable = Observable.create(onExceptionResumeNextViaObservable(w, resume)); + + @SuppressWarnings("unchecked") + Observer aObserver = mock(Observer.class); + observable.subscribe(aObserver); + + try { + f.t.join(); + } catch (InterruptedException e) { + fail(e.getMessage()); + } + + verify(aObserver, times(1)).onNext("one"); + verify(aObserver, never()).onNext("two"); + verify(aObserver, never()).onNext("three"); + verify(aObserver, never()).onNext("twoResume"); + verify(aObserver, never()).onNext("threeResume"); + verify(aObserver, times(1)).onError(any(Throwable.class)); + verify(aObserver, never()).onCompleted(); + verifyNoMoreInteractions(aObserver); + } + + @Test + public void testErrorPassesThru() { + Subscription s = mock(Subscription.class); + // Trigger failure on second element + TestObservable f = new TestObservable(s, "one", "ERROR", "two", "three"); + Observable w = Observable.create(f); + Observable resume = Observable.from("twoResume", "threeResume"); + Observable observable = Observable.create(onExceptionResumeNextViaObservable(w, resume)); + + @SuppressWarnings("unchecked") + Observer aObserver = mock(Observer.class); + observable.subscribe(aObserver); + + try { + f.t.join(); + } catch (InterruptedException e) { + fail(e.getMessage()); + } + + verify(aObserver, times(1)).onNext("one"); + verify(aObserver, never()).onNext("two"); + verify(aObserver, never()).onNext("three"); + verify(aObserver, never()).onNext("twoResume"); + verify(aObserver, never()).onNext("threeResume"); + verify(aObserver, times(1)).onError(any(Throwable.class)); + verify(aObserver, never()).onCompleted(); + verifyNoMoreInteractions(aObserver); + } + + @Test + public void testMapResumeAsyncNext() { + Subscription sr = mock(Subscription.class); + // Trigger multiple failures + Observable w = Observable.from("one", "fail", "two", "three", "fail"); + // Resume Observable is async + TestObservable f = new TestObservable(sr, "twoResume", "threeResume"); + Observable resume = Observable.create(f); + + // Introduce map function that fails intermittently (Map does not prevent this when the observer is a + // rx.operator incl onErrorResumeNextViaObservable) + w = w.map(new Func1() { + public String call(String s) { + if ("fail".equals(s)) + throw new RuntimeException("Forced Failure"); + System.out.println("BadMapper:" + s); + return s; + } + }); + + Observable observable = Observable.create(onExceptionResumeNextViaObservable(w, resume)); + + @SuppressWarnings("unchecked") + Observer aObserver = mock(Observer.class); + observable.subscribe(aObserver); + + try { + // if the thread gets started (which it shouldn't if it's working correctly) + if (f.t != null) { + f.t.join(); + } + } catch (InterruptedException e) { + fail(e.getMessage()); + } + + verify(aObserver, times(1)).onNext("one"); + verify(aObserver, never()).onNext("two"); + verify(aObserver, never()).onNext("three"); + verify(aObserver, times(1)).onNext("twoResume"); + verify(aObserver, times(1)).onNext("threeResume"); + verify(aObserver, Mockito.never()).onError(any(Throwable.class)); + verify(aObserver, times(1)).onCompleted(); + } + + private static class TestObservable implements Observable.OnSubscribeFunc { + + final Subscription s; + final String[] values; + Thread t = null; + + public TestObservable(Subscription s, String... values) { + this.s = s; + this.values = values; + } + + @Override + public Subscription onSubscribe(final Observer observer) { + System.out.println("TestObservable subscribed to ..."); + t = new Thread(new Runnable() { + + @Override + public void run() { + try { + System.out.println("running TestObservable thread"); + for (String s : values) { + if ("EXCEPTION".equals(s)) + throw new Exception("Forced Exception"); + else if ("RUNTIMEEXCEPTION".equals(s)) + throw new RuntimeException("Forced RuntimeException"); + else if ("ERROR".equals(s)) + throw new Error("Forced Error"); + else if ("THROWABLE".equals(s)) + throw new Throwable("Forced Throwable"); + System.out.println("TestObservable onNext: " + s); + observer.onNext(s); + } + System.out.println("TestObservable onCompleted"); + observer.onCompleted(); + } catch (Throwable e) { + System.out.println("TestObservable onError: " + e); + observer.onError(e); + } + } + + }); + System.out.println("starting TestObservable thread"); + t.start(); + System.out.println("done starting TestObservable thread"); + return s; + } + } } diff --git a/rxjava-core/src/test/java/rx/operators/OperationParallelTest.java b/rxjava-core/src/test/java/rx/operators/OperationParallelTest.java index fee3816e98..fd79f9e9fb 100644 --- a/rxjava-core/src/test/java/rx/operators/OperationParallelTest.java +++ b/rxjava-core/src/test/java/rx/operators/OperationParallelTest.java @@ -1,7 +1,45 @@ package rx.operators; -import org.junit.Ignore; +import org.junit.Test; +import rx.Observable; +import rx.util.functions.Action1; +import rx.util.functions.Func1; + +import java.util.concurrent.atomic.AtomicInteger; + +import static org.junit.Assert.assertEquals; -@Ignore("WIP") public class OperationParallelTest { + + @Test + public void testParallel() { + int NUM = 1000; + final AtomicInteger count = new AtomicInteger(); + Observable.range(1, NUM).parallel( + new Func1, Observable>() { + + @Override + public Observable call(Observable o) { + return o.map(new Func1() { + + @Override + public Integer[] call(Integer t) { + return new Integer[]{t, t * 99}; + } + + }); + } + }).toBlockingObservable().forEach(new Action1() { + + @Override + public void call(Integer[] v) { + count.incrementAndGet(); + System.out.println("V: " + v[0] + " R: " + v[1] + " Thread: " + Thread.currentThread()); + } + + }); + + // just making sure we finish and get the number we expect + assertEquals(NUM, count.get()); + } } diff --git a/rxjava-core/src/test/java/rx/operators/OperationRetryTest.java b/rxjava-core/src/test/java/rx/operators/OperationRetryTest.java index 768d1f5f9c..5132b84219 100644 --- a/rxjava-core/src/test/java/rx/operators/OperationRetryTest.java +++ b/rxjava-core/src/test/java/rx/operators/OperationRetryTest.java @@ -1,7 +1,114 @@ package rx.operators; -import org.junit.Ignore; +import org.junit.Test; +import org.mockito.InOrder; +import rx.Observable; +import rx.Observer; +import rx.Subscription; +import rx.subscriptions.Subscriptions; + +import java.util.concurrent.atomic.AtomicInteger; + +import static org.mockito.Matchers.any; +import static org.mockito.Mockito.*; +import static rx.operators.OperationRetry.retry; -@Ignore("WIP") public class OperationRetryTest { + + @Test + public void testOriginFails() { + @SuppressWarnings("unchecked") + Observer observer = mock(Observer.class); + Observable origin = Observable.create(new FuncWithErrors(2)); + origin.subscribe(observer); + + InOrder inOrder = inOrder(observer); + inOrder.verify(observer, times(1)).onNext("beginningEveryTime"); + inOrder.verify(observer, times(1)).onError(any(RuntimeException.class)); + inOrder.verify(observer, never()).onNext("onSuccessOnly"); + inOrder.verify(observer, never()).onCompleted(); + } + + @Test + public void testRetryFail() { + int NUM_RETRIES = 1; + int NUM_FAILURES = 2; + @SuppressWarnings("unchecked") + Observer observer = mock(Observer.class); + Observable origin = Observable.create(new FuncWithErrors(NUM_FAILURES)); + Observable.create(retry(origin, NUM_RETRIES)).subscribe(observer); + + InOrder inOrder = inOrder(observer); + // should show 2 attempts (first time fail, second time (1st retry) fail) + inOrder.verify(observer, times(1 + NUM_RETRIES)).onNext("beginningEveryTime"); + // should only retry once, fail again and emit onError + inOrder.verify(observer, times(1)).onError(any(RuntimeException.class)); + // no success + inOrder.verify(observer, never()).onNext("onSuccessOnly"); + inOrder.verify(observer, never()).onCompleted(); + inOrder.verifyNoMoreInteractions(); + } + + @Test + public void testRetrySuccess() { + int NUM_RETRIES = 3; + int NUM_FAILURES = 2; + @SuppressWarnings("unchecked") + Observer observer = mock(Observer.class); + Observable origin = Observable.create(new FuncWithErrors(NUM_FAILURES)); + Observable.create(retry(origin, NUM_RETRIES)).subscribe(observer); + + InOrder inOrder = inOrder(observer); + // should show 3 attempts + inOrder.verify(observer, times(1 + NUM_FAILURES)).onNext("beginningEveryTime"); + // should have no errors + inOrder.verify(observer, never()).onError(any(Throwable.class)); + // should have a single success + inOrder.verify(observer, times(1)).onNext("onSuccessOnly"); + // should have a single successful onCompleted + inOrder.verify(observer, times(1)).onCompleted(); + inOrder.verifyNoMoreInteractions(); + } + + @Test + public void testInfiniteRetry() { + int NUM_FAILURES = 20; + @SuppressWarnings("unchecked") + Observer observer = mock(Observer.class); + Observable origin = Observable.create(new FuncWithErrors(NUM_FAILURES)); + Observable.create(retry(origin)).subscribe(observer); + + InOrder inOrder = inOrder(observer); + // should show 3 attempts + inOrder.verify(observer, times(1 + NUM_FAILURES)).onNext("beginningEveryTime"); + // should have no errors + inOrder.verify(observer, never()).onError(any(Throwable.class)); + // should have a single success + inOrder.verify(observer, times(1)).onNext("onSuccessOnly"); + // should have a single successful onCompleted + inOrder.verify(observer, times(1)).onCompleted(); + inOrder.verifyNoMoreInteractions(); + } + + public static class FuncWithErrors implements Observable.OnSubscribeFunc { + + private final int numFailures; + private final AtomicInteger count = new AtomicInteger(0); + + FuncWithErrors(int count) { + this.numFailures = count; + } + + @Override + public Subscription onSubscribe(Observer o) { + o.onNext("beginningEveryTime"); + if (count.incrementAndGet() <= numFailures) { + o.onError(new RuntimeException("forced failure: " + count.get())); + } else { + o.onNext("onSuccessOnly"); + o.onCompleted(); + } + return Subscriptions.empty(); + } + } } diff --git a/rxjava-core/src/test/java/rx/operators/OperationSampleTest.java b/rxjava-core/src/test/java/rx/operators/OperationSampleTest.java index a718adbc0a..789fa9cf2f 100644 --- a/rxjava-core/src/test/java/rx/operators/OperationSampleTest.java +++ b/rxjava-core/src/test/java/rx/operators/OperationSampleTest.java @@ -1,7 +1,91 @@ package rx.operators; -import org.junit.Ignore; +import org.junit.Before; +import org.junit.Test; +import org.mockito.InOrder; +import rx.Observable; +import rx.Observer; +import rx.Subscription; +import rx.concurrency.TestScheduler; +import rx.subscriptions.Subscriptions; +import rx.util.functions.Action0; + +import java.util.concurrent.TimeUnit; + +import static org.mockito.Matchers.any; +import static org.mockito.Mockito.*; -@Ignore("WIP") public class OperationSampleTest { + private TestScheduler scheduler; + private Observer observer; + + @Before + @SuppressWarnings("unchecked") // due to mocking + public void before() { + scheduler = new TestScheduler(); + observer = mock(Observer.class); + } + + @Test + public void testSample() { + Observable source = Observable.create(new Observable.OnSubscribeFunc() { + @Override + public Subscription onSubscribe(final Observer observer1) { + scheduler.schedule(new Action0() { + @Override + public void call() { + observer1.onNext(1L); + } + }, 1, TimeUnit.SECONDS); + scheduler.schedule(new Action0() { + @Override + public void call() { + observer1.onNext(2L); + } + }, 2, TimeUnit.SECONDS); + scheduler.schedule(new Action0() { + @Override + public void call() { + observer1.onCompleted(); + } + }, 3, TimeUnit.SECONDS); + + return Subscriptions.empty(); + } + }); + + Observable sampled = Observable.create(OperationSample.sample(source, 400L, TimeUnit.MILLISECONDS, scheduler)); + sampled.subscribe(observer); + + InOrder inOrder = inOrder(observer); + + scheduler.advanceTimeTo(800L, TimeUnit.MILLISECONDS); + verify(observer, never()).onNext(any(Long.class)); + verify(observer, never()).onCompleted(); + verify(observer, never()).onError(any(Throwable.class)); + + scheduler.advanceTimeTo(1200L, TimeUnit.MILLISECONDS); + inOrder.verify(observer, times(1)).onNext(1L); + verify(observer, never()).onNext(2L); + verify(observer, never()).onCompleted(); + verify(observer, never()).onError(any(Throwable.class)); + + scheduler.advanceTimeTo(1600L, TimeUnit.MILLISECONDS); + inOrder.verify(observer, times(1)).onNext(1L); + verify(observer, never()).onNext(2L); + verify(observer, never()).onCompleted(); + verify(observer, never()).onError(any(Throwable.class)); + + scheduler.advanceTimeTo(2000L, TimeUnit.MILLISECONDS); + inOrder.verify(observer, never()).onNext(1L); + inOrder.verify(observer, times(1)).onNext(2L); + verify(observer, never()).onCompleted(); + verify(observer, never()).onError(any(Throwable.class)); + + scheduler.advanceTimeTo(3000L, TimeUnit.MILLISECONDS); + inOrder.verify(observer, never()).onNext(1L); + inOrder.verify(observer, times(2)).onNext(2L); + verify(observer, times(1)).onCompleted(); + verify(observer, never()).onError(any(Throwable.class)); + } } diff --git a/rxjava-core/src/test/java/rx/operators/OperationScanTest.java b/rxjava-core/src/test/java/rx/operators/OperationScanTest.java index aa3d7d6f9e..691df4b0f1 100644 --- a/rxjava-core/src/test/java/rx/operators/OperationScanTest.java +++ b/rxjava-core/src/test/java/rx/operators/OperationScanTest.java @@ -1,7 +1,102 @@ package rx.operators; -import org.junit.Ignore; +import org.junit.Before; +import org.junit.Test; +import org.mockito.MockitoAnnotations; +import rx.Observable; +import rx.Observer; +import rx.util.functions.Func2; + +import static org.mockito.Matchers.any; +import static org.mockito.Matchers.anyInt; +import static org.mockito.Matchers.anyString; +import static org.mockito.Mockito.*; +import static rx.operators.OperationScan.scan; -@Ignore("WIP") public class OperationScanTest { + + + @Before + public void before() { + MockitoAnnotations.initMocks(this); + } + + @Test + public void testScanIntegersWithInitialValue() { + @SuppressWarnings("unchecked") + Observer observer = mock(Observer.class); + + Observable observable = Observable.from(1, 2, 3); + + Observable m = Observable.create(scan(observable, "", new Func2() { + + @Override + public String call(String s, Integer n) { + return s + n.toString(); + } + + })); + m.subscribe(observer); + + verify(observer, never()).onError(any(Throwable.class)); + verify(observer, times(1)).onNext(""); + verify(observer, times(1)).onNext("1"); + verify(observer, times(1)).onNext("12"); + verify(observer, times(1)).onNext("123"); + verify(observer, times(4)).onNext(anyString()); + verify(observer, times(1)).onCompleted(); + verify(observer, never()).onError(any(Throwable.class)); + } + + @Test + public void testScanIntegersWithoutInitialValue() { + @SuppressWarnings("unchecked") + Observer Observer = mock(Observer.class); + + Observable observable = Observable.from(1, 2, 3); + + Observable m = Observable.create(scan(observable, new Func2() { + + @Override + public Integer call(Integer t1, Integer t2) { + return t1 + t2; + } + + })); + m.subscribe(Observer); + + verify(Observer, never()).onError(any(Throwable.class)); + verify(Observer, never()).onNext(0); + verify(Observer, times(1)).onNext(1); + verify(Observer, times(1)).onNext(3); + verify(Observer, times(1)).onNext(6); + verify(Observer, times(3)).onNext(anyInt()); + verify(Observer, times(1)).onCompleted(); + verify(Observer, never()).onError(any(Throwable.class)); + } + + @Test + public void testScanIntegersWithoutInitialValueAndOnlyOneValue() { + @SuppressWarnings("unchecked") + Observer Observer = mock(Observer.class); + + Observable observable = Observable.from(1); + + Observable m = Observable.create(scan(observable, new Func2() { + + @Override + public Integer call(Integer t1, Integer t2) { + return t1 + t2; + } + + })); + m.subscribe(Observer); + + verify(Observer, never()).onError(any(Throwable.class)); + verify(Observer, never()).onNext(0); + verify(Observer, times(1)).onNext(1); + verify(Observer, times(1)).onNext(anyInt()); + verify(Observer, times(1)).onCompleted(); + verify(Observer, never()).onError(any(Throwable.class)); + } } diff --git a/rxjava-core/src/test/java/rx/operators/OperationSkipLastTest.java b/rxjava-core/src/test/java/rx/operators/OperationSkipLastTest.java index 9604c718c7..8b1dd163fb 100644 --- a/rxjava-core/src/test/java/rx/operators/OperationSkipLastTest.java +++ b/rxjava-core/src/test/java/rx/operators/OperationSkipLastTest.java @@ -1,7 +1,98 @@ package rx.operators; -import org.junit.Ignore; +import org.junit.Test; +import org.mockito.InOrder; +import rx.Observable; +import rx.Observer; + +import static org.mockito.Matchers.any; +import static org.mockito.Mockito.*; +import static rx.operators.OperationSkipLast.skipLast; -@Ignore("WIP") public class OperationSkipLastTest { + + @Test + public void testSkipLastEmpty() { + Observable w = Observable.empty(); + Observable observable = Observable.create(skipLast(w, 2)); + + @SuppressWarnings("unchecked") + Observer aObserver = mock(Observer.class); + observable.subscribe(aObserver); + verify(aObserver, never()).onNext(any(String.class)); + verify(aObserver, never()).onError(any(Throwable.class)); + verify(aObserver, times(1)).onCompleted(); + } + + @Test + public void testSkipLast1() { + Observable w = Observable.from("one", "two", "three"); + Observable observable = Observable.create(skipLast(w, 2)); + + @SuppressWarnings("unchecked") + Observer aObserver = mock(Observer.class); + InOrder inOrder = inOrder(aObserver); + observable.subscribe(aObserver); + inOrder.verify(aObserver, never()).onNext("two"); + inOrder.verify(aObserver, never()).onNext("three"); + verify(aObserver, times(1)).onNext("one"); + verify(aObserver, never()).onError(any(Throwable.class)); + verify(aObserver, times(1)).onCompleted(); + } + + @Test + public void testSkipLast2() { + Observable w = Observable.from("one", "two"); + Observable observable = Observable.create(skipLast(w, 2)); + + @SuppressWarnings("unchecked") + Observer aObserver = mock(Observer.class); + observable.subscribe(aObserver); + verify(aObserver, never()).onNext(any(String.class)); + verify(aObserver, never()).onError(any(Throwable.class)); + verify(aObserver, times(1)).onCompleted(); + } + + @Test + public void testSkipLastWithZeroCount() { + Observable w = Observable.from("one", "two"); + Observable observable = Observable.create(skipLast(w, 0)); + + @SuppressWarnings("unchecked") + Observer aObserver = mock(Observer.class); + observable.subscribe(aObserver); + verify(aObserver, times(1)).onNext("one"); + verify(aObserver, times(1)).onNext("two"); + verify(aObserver, never()).onError(any(Throwable.class)); + verify(aObserver, times(1)).onCompleted(); + } + + @Test + public void testSkipLastWithNull() { + Observable w = Observable.from("one", null, "two"); + Observable observable = Observable.create(skipLast(w, 1)); + + @SuppressWarnings("unchecked") + Observer aObserver = mock(Observer.class); + observable.subscribe(aObserver); + verify(aObserver, times(1)).onNext("one"); + verify(aObserver, times(1)).onNext(null); + verify(aObserver, never()).onNext("two"); + verify(aObserver, never()).onError(any(Throwable.class)); + verify(aObserver, times(1)).onCompleted(); + } + + @Test + public void testSkipLastWithNegativeCount() { + Observable w = Observable.from("one"); + Observable observable = Observable.create(skipLast(w, -1)); + + @SuppressWarnings("unchecked") + Observer aObserver = mock(Observer.class); + observable.subscribe(aObserver); + verify(aObserver, never()).onNext(any(String.class)); + verify(aObserver, times(1)).onError( + any(IndexOutOfBoundsException.class)); + verify(aObserver, never()).onCompleted(); + } } diff --git a/rxjava-core/src/test/java/rx/operators/OperationSkipTest.java b/rxjava-core/src/test/java/rx/operators/OperationSkipTest.java index 1d74ed6302..acc351de34 100644 --- a/rxjava-core/src/test/java/rx/operators/OperationSkipTest.java +++ b/rxjava-core/src/test/java/rx/operators/OperationSkipTest.java @@ -1,7 +1,42 @@ package rx.operators; -import org.junit.Ignore; +import org.junit.Test; +import rx.Observable; +import rx.Observer; + +import static org.mockito.Matchers.any; +import static org.mockito.Mockito.*; +import static rx.operators.OperationSkip.skip; -@Ignore("WIP") public class OperationSkipTest { + + @Test + public void testSkip1() { + Observable w = Observable.from("one", "two", "three"); + Observable skip = Observable.create(skip(w, 2)); + + @SuppressWarnings("unchecked") + Observer aObserver = mock(Observer.class); + skip.subscribe(aObserver); + verify(aObserver, never()).onNext("one"); + verify(aObserver, never()).onNext("two"); + verify(aObserver, times(1)).onNext("three"); + verify(aObserver, never()).onError(any(Throwable.class)); + verify(aObserver, times(1)).onCompleted(); + } + + @Test + public void testSkip2() { + Observable w = Observable.from("one", "two", "three"); + Observable skip = Observable.create(skip(w, 1)); + + @SuppressWarnings("unchecked") + Observer aObserver = mock(Observer.class); + skip.subscribe(aObserver); + verify(aObserver, never()).onNext("one"); + verify(aObserver, times(1)).onNext("two"); + verify(aObserver, times(1)).onNext("three"); + verify(aObserver, never()).onError(any(Throwable.class)); + verify(aObserver, times(1)).onCompleted(); + } } diff --git a/rxjava-core/src/test/java/rx/operators/OperationSkipWhileTest.java b/rxjava-core/src/test/java/rx/operators/OperationSkipWhileTest.java index d9347d907e..f0d8391928 100644 --- a/rxjava-core/src/test/java/rx/operators/OperationSkipWhileTest.java +++ b/rxjava-core/src/test/java/rx/operators/OperationSkipWhileTest.java @@ -1,7 +1,104 @@ package rx.operators; -import org.junit.Ignore; +import org.junit.Test; +import org.mockito.InOrder; +import rx.Observable; +import rx.Observer; +import rx.util.functions.Func1; +import rx.util.functions.Func2; + +import static org.mockito.Matchers.any; +import static org.mockito.Matchers.anyInt; +import static org.mockito.Mockito.*; +import static rx.Observable.create; +import static rx.operators.OperationSkipWhile.skipWhile; +import static rx.operators.OperationSkipWhile.skipWhileWithIndex; -@Ignore("WIP") public class OperationSkipWhileTest { + + @SuppressWarnings("unchecked") + Observer w = mock(Observer.class); + + private static final Func1 LESS_THAN_FIVE = new Func1() { + @Override + public Boolean call(Integer v) { + if (v == 42) throw new RuntimeException("that's not the answer to everything!"); + return v < 5; + } + }; + + private static final Func2 INDEX_LESS_THAN_THREE = new Func2() { + @Override + public Boolean call(Integer value, Integer index) { + return index < 3; + } + }; + + @Test + public void testSkipWithIndex() { + Observable src = Observable.from(1, 2, 3, 4, 5); + create(skipWhileWithIndex(src, INDEX_LESS_THAN_THREE)).subscribe(w); + + InOrder inOrder = inOrder(w); + inOrder.verify(w, times(1)).onNext(4); + inOrder.verify(w, times(1)).onNext(5); + inOrder.verify(w, times(1)).onCompleted(); + inOrder.verify(w, never()).onError(any(Throwable.class)); + } + + @Test + public void testSkipEmpty() { + Observable src = Observable.empty(); + create(skipWhile(src, LESS_THAN_FIVE)).subscribe(w); + verify(w, never()).onNext(anyInt()); + verify(w, never()).onError(any(Throwable.class)); + verify(w, times(1)).onCompleted(); + } + + @Test + public void testSkipEverything() { + Observable src = Observable.from(1, 2, 3, 4, 3, 2, 1); + create(skipWhile(src, LESS_THAN_FIVE)).subscribe(w); + verify(w, never()).onNext(anyInt()); + verify(w, never()).onError(any(Throwable.class)); + verify(w, times(1)).onCompleted(); + } + + @Test + public void testSkipNothing() { + Observable src = Observable.from(5, 3, 1); + create(skipWhile(src, LESS_THAN_FIVE)).subscribe(w); + + InOrder inOrder = inOrder(w); + inOrder.verify(w, times(1)).onNext(5); + inOrder.verify(w, times(1)).onNext(3); + inOrder.verify(w, times(1)).onNext(1); + inOrder.verify(w, times(1)).onCompleted(); + inOrder.verify(w, never()).onError(any(Throwable.class)); + } + + @Test + public void testSkipSome() { + Observable src = Observable.from(1, 2, 3, 4, 5, 3, 1, 5); + create(skipWhile(src, LESS_THAN_FIVE)).subscribe(w); + + InOrder inOrder = inOrder(w); + inOrder.verify(w, times(1)).onNext(5); + inOrder.verify(w, times(1)).onNext(3); + inOrder.verify(w, times(1)).onNext(1); + inOrder.verify(w, times(1)).onNext(5); + inOrder.verify(w, times(1)).onCompleted(); + inOrder.verify(w, never()).onError(any(Throwable.class)); + } + + @Test + public void testSkipError() { + Observable src = Observable.from(1, 2, 42, 5, 3, 1); + create(skipWhile(src, LESS_THAN_FIVE)).subscribe(w); + + InOrder inOrder = inOrder(w); + inOrder.verify(w, never()).onNext(anyInt()); + inOrder.verify(w, never()).onCompleted(); + inOrder.verify(w, times(1)).onError(any(RuntimeException.class)); + } } diff --git a/rxjava-core/src/test/java/rx/operators/OperationSubscribeOnTest.java b/rxjava-core/src/test/java/rx/operators/OperationSubscribeOnTest.java index 495cbc6713..0c260cf8e8 100644 --- a/rxjava-core/src/test/java/rx/operators/OperationSubscribeOnTest.java +++ b/rxjava-core/src/test/java/rx/operators/OperationSubscribeOnTest.java @@ -1,7 +1,40 @@ package rx.operators; -import org.junit.Ignore; +import org.junit.Test; +import rx.Observable; +import rx.Observer; +import rx.Scheduler; +import rx.Subscription; +import rx.concurrency.Schedulers; +import rx.test.OperatorTester; +import rx.util.functions.Action0; +import rx.util.functions.Func2; + +import static org.mockito.Matchers.any; +import static org.mockito.Matchers.isNull; +import static org.mockito.Mockito.*; +import static rx.operators.OperationSubscribeOn.subscribeOn; -@Ignore("WIP") public class OperationSubscribeOnTest { + + @Test + @SuppressWarnings("unchecked") + public void testSubscribeOn() { + Observable w = Observable.from(1, 2, 3); + + Scheduler scheduler = spy(OperatorTester.forwardingScheduler(Schedulers.immediate())); + + Observer observer = mock(Observer.class); + Subscription subscription = Observable.create(subscribeOn(w, scheduler)).subscribe(observer); + + verify(scheduler, times(1)).schedule(isNull(), any(Func2.class)); + subscription.unsubscribe(); + verify(scheduler, times(1)).schedule(any(Action0.class)); + verifyNoMoreInteractions(scheduler); + + verify(observer, times(1)).onNext(1); + verify(observer, times(1)).onNext(2); + verify(observer, times(1)).onNext(3); + verify(observer, times(1)).onCompleted(); + } } diff --git a/rxjava-core/src/test/java/rx/operators/OperationSumTest.java b/rxjava-core/src/test/java/rx/operators/OperationSumTest.java index c89121e207..9e826d8343 100644 --- a/rxjava-core/src/test/java/rx/operators/OperationSumTest.java +++ b/rxjava-core/src/test/java/rx/operators/OperationSumTest.java @@ -1,7 +1,113 @@ package rx.operators; -import org.junit.Ignore; +import org.junit.Test; +import rx.Observable; +import rx.Observer; + +import static org.mockito.Matchers.any; +import static org.mockito.Matchers.anyDouble; +import static org.mockito.Matchers.anyFloat; +import static org.mockito.Matchers.anyInt; +import static org.mockito.Matchers.anyLong; +import static org.mockito.Mockito.*; +import static rx.operators.OperationSum.*; -@Ignore("WIP") public class OperationSumTest { + + @SuppressWarnings("unchecked") + Observer w = mock(Observer.class); + @SuppressWarnings("unchecked") + Observer wl = mock(Observer.class); + @SuppressWarnings("unchecked") + Observer wf = mock(Observer.class); + @SuppressWarnings("unchecked") + Observer wd = mock(Observer.class); + + @Test + public void testSumOfAFewInts() throws Throwable { + Observable src = Observable.from(1, 2, 3, 4, 5); + sum(src).subscribe(w); + + verify(w, times(1)).onNext(anyInt()); + verify(w).onNext(15); + verify(w, never()).onError(any(Throwable.class)); + verify(w, times(1)).onCompleted(); + } + + @Test + public void testEmptySum() throws Throwable { + Observable src = Observable.empty(); + sum(src).subscribe(w); + + verify(w, times(1)).onNext(anyInt()); + verify(w).onNext(0); + verify(w, never()).onError(any(Throwable.class)); + verify(w, times(1)).onCompleted(); + } + + @Test + public void testSumOfAFewLongs() throws Throwable { + Observable src = Observable.from(1L, 2L, 3L, 4L, 5L); + sumLongs(src).subscribe(wl); + + verify(wl, times(1)).onNext(anyLong()); + verify(wl).onNext(15L); + verify(wl, never()).onError(any(Throwable.class)); + verify(wl, times(1)).onCompleted(); + } + + @Test + public void testEmptySumLongs() throws Throwable { + Observable src = Observable.empty(); + sumLongs(src).subscribe(wl); + + verify(wl, times(1)).onNext(anyLong()); + verify(wl).onNext(0L); + verify(wl, never()).onError(any(Throwable.class)); + verify(wl, times(1)).onCompleted(); + } + + @Test + public void testSumOfAFewFloats() throws Throwable { + Observable src = Observable.from(1.0f); + sumFloats(src).subscribe(wf); + + verify(wf, times(1)).onNext(anyFloat()); + verify(wf).onNext(1.0f); + verify(wf, never()).onError(any(Throwable.class)); + verify(wf, times(1)).onCompleted(); + } + + @Test + public void testEmptySumFloats() throws Throwable { + Observable src = Observable.empty(); + sumFloats(src).subscribe(wf); + + verify(wf, times(1)).onNext(anyFloat()); + verify(wf).onNext(0.0f); + verify(wf, never()).onError(any(Throwable.class)); + verify(wf, times(1)).onCompleted(); + } + + @Test + public void testSumOfAFewDoubles() throws Throwable { + Observable src = Observable.from(0.0d, 1.0d, 0.5d); + sumDoubles(src).subscribe(wd); + + verify(wd, times(1)).onNext(anyDouble()); + verify(wd).onNext(1.5d); + verify(wd, never()).onError(any(Throwable.class)); + verify(wd, times(1)).onCompleted(); + } + + @Test + public void testEmptySumDoubles() throws Throwable { + Observable src = Observable.empty(); + sumDoubles(src).subscribe(wd); + + verify(wd, times(1)).onNext(anyDouble()); + verify(wd).onNext(0.0d); + verify(wd, never()).onError(any(Throwable.class)); + verify(wd, times(1)).onCompleted(); + } } diff --git a/rxjava-core/src/test/java/rx/operators/OperationSwitchTest.java b/rxjava-core/src/test/java/rx/operators/OperationSwitchTest.java index d91bb804bf..7c8c9ea21a 100644 --- a/rxjava-core/src/test/java/rx/operators/OperationSwitchTest.java +++ b/rxjava-core/src/test/java/rx/operators/OperationSwitchTest.java @@ -1,7 +1,368 @@ package rx.operators; -import org.junit.Ignore; +import org.junit.Before; +import org.junit.Test; +import org.mockito.InOrder; +import rx.Observable; +import rx.Observer; +import rx.Subscription; +import rx.concurrency.TestScheduler; +import rx.subscriptions.Subscriptions; +import rx.util.functions.Action0; + +import java.util.concurrent.TimeUnit; + +import static org.mockito.Matchers.any; +import static org.mockito.Matchers.anyString; +import static org.mockito.Mockito.*; -@Ignore("WIP") public class OperationSwitchTest { + + private TestScheduler scheduler; + private Observer observer; + + @Before + @SuppressWarnings("unchecked") + public void before() { + scheduler = new TestScheduler(); + observer = mock(Observer.class); + } + + @Test + public void testSwitchWhenOuterCompleteBeforeInner() { + Observable> source = Observable.create(new Observable.OnSubscribeFunc>() { + @Override + public Subscription onSubscribe(Observer> observer) { + publishNext(observer, 50, Observable.create(new Observable.OnSubscribeFunc() { + @Override + public Subscription onSubscribe(Observer observer) { + publishNext(observer, 70, "one"); + publishNext(observer, 100, "two"); + publishCompleted(observer, 200); + return Subscriptions.empty(); + } + })); + publishCompleted(observer, 60); + + return Subscriptions.empty(); + } + }); + + Observable sampled = Observable.create(OperationSwitch.switchDo(source)); + sampled.subscribe(observer); + + InOrder inOrder = inOrder(observer); + + scheduler.advanceTimeTo(350, TimeUnit.MILLISECONDS); + inOrder.verify(observer, times(2)).onNext(anyString()); + inOrder.verify(observer, times(1)).onCompleted(); + } + + @Test + public void testSwitchWhenInnerCompleteBeforeOuter() { + Observable> source = Observable.create(new Observable.OnSubscribeFunc>() { + @Override + public Subscription onSubscribe(Observer> observer) { + publishNext(observer, 10, Observable.create(new Observable.OnSubscribeFunc() { + @Override + public Subscription onSubscribe(Observer observer) { + publishNext(observer, 0, "one"); + publishNext(observer, 10, "two"); + publishCompleted(observer, 20); + return Subscriptions.empty(); + } + })); + + publishNext(observer, 100, Observable.create(new Observable.OnSubscribeFunc() { + @Override + public Subscription onSubscribe(Observer observer) { + publishNext(observer, 0, "three"); + publishNext(observer, 10, "four"); + publishCompleted(observer, 20); + return Subscriptions.empty(); + } + })); + publishCompleted(observer, 200); + + return Subscriptions.empty(); + } + }); + + Observable sampled = Observable.create(OperationSwitch.switchDo(source)); + sampled.subscribe(observer); + + InOrder inOrder = inOrder(observer); + + scheduler.advanceTimeTo(150, TimeUnit.MILLISECONDS); + inOrder.verify(observer, never()).onCompleted(); + inOrder.verify(observer, times(1)).onNext("one"); + inOrder.verify(observer, times(1)).onNext("two"); + inOrder.verify(observer, times(1)).onNext("three"); + inOrder.verify(observer, times(1)).onNext("four"); + + scheduler.advanceTimeTo(250, TimeUnit.MILLISECONDS); + inOrder.verify(observer, never()).onNext(anyString()); + inOrder.verify(observer, times(1)).onCompleted(); + } + + @Test + public void testSwitchWithComplete() { + Observable> source = Observable.create(new Observable.OnSubscribeFunc>() { + @Override + public Subscription onSubscribe(Observer> observer) { + publishNext(observer, 50, Observable.create(new Observable.OnSubscribeFunc() { + @Override + public Subscription onSubscribe(Observer observer) { + publishNext(observer, 60, "one"); + publishNext(observer, 100, "two"); + return Subscriptions.empty(); + } + })); + + publishNext(observer, 200, Observable.create(new Observable.OnSubscribeFunc() { + @Override + public Subscription onSubscribe(Observer observer) { + publishNext(observer, 0, "three"); + publishNext(observer, 100, "four"); + return Subscriptions.empty(); + } + })); + + publishCompleted(observer, 250); + + return Subscriptions.empty(); + } + }); + + Observable sampled = Observable.create(OperationSwitch.switchDo(source)); + sampled.subscribe(observer); + + InOrder inOrder = inOrder(observer); + + scheduler.advanceTimeTo(90, TimeUnit.MILLISECONDS); + inOrder.verify(observer, never()).onNext(anyString()); + verify(observer, never()).onCompleted(); + verify(observer, never()).onError(any(Throwable.class)); + + scheduler.advanceTimeTo(125, TimeUnit.MILLISECONDS); + inOrder.verify(observer, times(1)).onNext("one"); + verify(observer, never()).onCompleted(); + verify(observer, never()).onError(any(Throwable.class)); + + scheduler.advanceTimeTo(175, TimeUnit.MILLISECONDS); + inOrder.verify(observer, times(1)).onNext("two"); + verify(observer, never()).onCompleted(); + verify(observer, never()).onError(any(Throwable.class)); + + scheduler.advanceTimeTo(225, TimeUnit.MILLISECONDS); + inOrder.verify(observer, times(1)).onNext("three"); + verify(observer, never()).onCompleted(); + verify(observer, never()).onError(any(Throwable.class)); + + scheduler.advanceTimeTo(350, TimeUnit.MILLISECONDS); + inOrder.verify(observer, times(1)).onNext("four"); + verify(observer, never()).onCompleted(); + verify(observer, never()).onError(any(Throwable.class)); + } + + @Test + public void testSwitchWithError() { + Observable> source = Observable.create(new Observable.OnSubscribeFunc>() { + @Override + public Subscription onSubscribe(Observer> observer) { + publishNext(observer, 50, Observable.create(new Observable.OnSubscribeFunc() { + @Override + public Subscription onSubscribe(Observer observer) { + publishNext(observer, 50, "one"); + publishNext(observer, 100, "two"); + return Subscriptions.empty(); + } + })); + + publishNext(observer, 200, Observable.create(new Observable.OnSubscribeFunc() { + @Override + public Subscription onSubscribe(Observer observer) { + publishNext(observer, 0, "three"); + publishNext(observer, 100, "four"); + return Subscriptions.empty(); + } + })); + + publishError(observer, 250, new TestException()); + + return Subscriptions.empty(); + } + }); + + Observable sampled = Observable.create(OperationSwitch.switchDo(source)); + sampled.subscribe(observer); + + InOrder inOrder = inOrder(observer); + + scheduler.advanceTimeTo(90, TimeUnit.MILLISECONDS); + inOrder.verify(observer, never()).onNext(anyString()); + verify(observer, never()).onCompleted(); + verify(observer, never()).onError(any(Throwable.class)); + + scheduler.advanceTimeTo(125, TimeUnit.MILLISECONDS); + inOrder.verify(observer, times(1)).onNext("one"); + verify(observer, never()).onCompleted(); + verify(observer, never()).onError(any(Throwable.class)); + + scheduler.advanceTimeTo(175, TimeUnit.MILLISECONDS); + inOrder.verify(observer, times(1)).onNext("two"); + verify(observer, never()).onCompleted(); + verify(observer, never()).onError(any(Throwable.class)); + + scheduler.advanceTimeTo(225, TimeUnit.MILLISECONDS); + inOrder.verify(observer, times(1)).onNext("three"); + verify(observer, never()).onCompleted(); + verify(observer, never()).onError(any(Throwable.class)); + + scheduler.advanceTimeTo(350, TimeUnit.MILLISECONDS); + inOrder.verify(observer, never()).onNext(anyString()); + verify(observer, never()).onCompleted(); + verify(observer, times(1)).onError(any(TestException.class)); + } + + @Test + public void testSwitchWithSubsequenceComplete() { + Observable> source = Observable.create(new Observable.OnSubscribeFunc>() { + @Override + public Subscription onSubscribe(Observer> observer) { + publishNext(observer, 50, Observable.create(new Observable.OnSubscribeFunc() { + @Override + public Subscription onSubscribe(Observer observer) { + publishNext(observer, 50, "one"); + publishNext(observer, 100, "two"); + return Subscriptions.empty(); + } + })); + + publishNext(observer, 130, Observable.create(new Observable.OnSubscribeFunc() { + @Override + public Subscription onSubscribe(Observer observer) { + publishCompleted(observer, 0); + return Subscriptions.empty(); + } + })); + + publishNext(observer, 150, Observable.create(new Observable.OnSubscribeFunc() { + @Override + public Subscription onSubscribe(Observer observer) { + publishNext(observer, 50, "three"); + return Subscriptions.empty(); + } + })); + + return Subscriptions.empty(); + } + }); + + Observable sampled = Observable.create(OperationSwitch.switchDo(source)); + sampled.subscribe(observer); + + InOrder inOrder = inOrder(observer); + + scheduler.advanceTimeTo(90, TimeUnit.MILLISECONDS); + inOrder.verify(observer, never()).onNext(anyString()); + verify(observer, never()).onCompleted(); + verify(observer, never()).onError(any(Throwable.class)); + + scheduler.advanceTimeTo(125, TimeUnit.MILLISECONDS); + inOrder.verify(observer, times(1)).onNext("one"); + verify(observer, never()).onCompleted(); + verify(observer, never()).onError(any(Throwable.class)); + + scheduler.advanceTimeTo(250, TimeUnit.MILLISECONDS); + inOrder.verify(observer, times(1)).onNext("three"); + verify(observer, never()).onCompleted(); + verify(observer, never()).onError(any(Throwable.class)); + } + + @Test + public void testSwitchWithSubsequenceError() { + Observable> source = Observable.create(new Observable.OnSubscribeFunc>() { + @Override + public Subscription onSubscribe(Observer> observer) { + publishNext(observer, 50, Observable.create(new Observable.OnSubscribeFunc() { + @Override + public Subscription onSubscribe(Observer observer) { + publishNext(observer, 50, "one"); + publishNext(observer, 100, "two"); + return Subscriptions.empty(); + } + })); + + publishNext(observer, 130, Observable.create(new Observable.OnSubscribeFunc() { + @Override + public Subscription onSubscribe(Observer observer) { + publishError(observer, 0, new TestException()); + return Subscriptions.empty(); + } + })); + + publishNext(observer, 150, Observable.create(new Observable.OnSubscribeFunc() { + @Override + public Subscription onSubscribe(Observer observer) { + publishNext(observer, 50, "three"); + return Subscriptions.empty(); + } + })); + + return Subscriptions.empty(); + } + }); + + Observable sampled = Observable.create(OperationSwitch.switchDo(source)); + sampled.subscribe(observer); + + InOrder inOrder = inOrder(observer); + + scheduler.advanceTimeTo(90, TimeUnit.MILLISECONDS); + inOrder.verify(observer, never()).onNext(anyString()); + verify(observer, never()).onCompleted(); + verify(observer, never()).onError(any(Throwable.class)); + + scheduler.advanceTimeTo(125, TimeUnit.MILLISECONDS); + inOrder.verify(observer, times(1)).onNext("one"); + verify(observer, never()).onCompleted(); + verify(observer, never()).onError(any(Throwable.class)); + + scheduler.advanceTimeTo(250, TimeUnit.MILLISECONDS); + inOrder.verify(observer, never()).onNext("three"); + verify(observer, never()).onCompleted(); + verify(observer, times(1)).onError(any(TestException.class)); + } + + private void publishCompleted(final Observer observer, long delay) { + scheduler.schedule(new Action0() { + @Override + public void call() { + observer.onCompleted(); + } + }, delay, TimeUnit.MILLISECONDS); + } + + private void publishError(final Observer observer, long delay, final Throwable error) { + scheduler.schedule(new Action0() { + @Override + public void call() { + observer.onError(error); + } + }, delay, TimeUnit.MILLISECONDS); + } + + private void publishNext(final Observer observer, long delay, final T value) { + scheduler.schedule(new Action0() { + @Override + public void call() { + observer.onNext(value); + } + }, delay, TimeUnit.MILLISECONDS); + } + + @SuppressWarnings("serial") + private class TestException extends Throwable { + } } diff --git a/rxjava-core/src/test/java/rx/operators/OperationSynchronizeTest.java b/rxjava-core/src/test/java/rx/operators/OperationSynchronizeTest.java index 2dce4a7d32..28d7676c66 100644 --- a/rxjava-core/src/test/java/rx/operators/OperationSynchronizeTest.java +++ b/rxjava-core/src/test/java/rx/operators/OperationSynchronizeTest.java @@ -1,7 +1,203 @@ package rx.operators; -import org.junit.Ignore; +import org.junit.Test; +import org.mockito.Mockito; +import rx.Observable; +import rx.Observer; +import rx.Subscription; + +import static org.mockito.Matchers.any; +import static org.mockito.Mockito.*; +import static rx.operators.OperationSynchronize.synchronize; -@Ignore("WIP") public class OperationSynchronizeTest { + + /** + * Ensure onCompleted can not be called after an Unsubscribe + */ + @Test + public void testOnCompletedAfterUnSubscribe() { + TestObservable t = new TestObservable(null); + Observable st = Observable.create(synchronize(Observable.create(t))); + + @SuppressWarnings("unchecked") + Observer w = mock(Observer.class); + Subscription ws = st.subscribe(w); + + t.sendOnNext("one"); + ws.unsubscribe(); + t.sendOnCompleted(); + + verify(w, times(1)).onNext("one"); + verify(w, Mockito.never()).onCompleted(); + } + + /** + * Ensure onNext can not be called after an Unsubscribe + */ + @Test + public void testOnNextAfterUnSubscribe() { + TestObservable t = new TestObservable(null); + Observable st = Observable.create(synchronize(Observable.create(t))); + + @SuppressWarnings("unchecked") + Observer w = mock(Observer.class); + Subscription ws = st.subscribe(w); + + t.sendOnNext("one"); + ws.unsubscribe(); + t.sendOnNext("two"); + + verify(w, times(1)).onNext("one"); + verify(w, Mockito.never()).onNext("two"); + } + + /** + * Ensure onError can not be called after an Unsubscribe + */ + @Test + public void testOnErrorAfterUnSubscribe() { + TestObservable t = new TestObservable(null); + Observable st = Observable.create(synchronize(Observable.create(t))); + + @SuppressWarnings("unchecked") + Observer w = mock(Observer.class); + Subscription ws = st.subscribe(w); + + t.sendOnNext("one"); + ws.unsubscribe(); + t.sendOnError(new RuntimeException("bad")); + + verify(w, times(1)).onNext("one"); + verify(w, Mockito.never()).onError(any(Throwable.class)); + } + + /** + * Ensure onNext can not be called after onError + */ + @Test + public void testOnNextAfterOnError() { + TestObservable t = new TestObservable(null); + Observable st = Observable.create(synchronize(Observable.create(t))); + + @SuppressWarnings("unchecked") + Observer w = mock(Observer.class); + @SuppressWarnings("unused") + Subscription ws = st.subscribe(w); + + t.sendOnNext("one"); + t.sendOnError(new RuntimeException("bad")); + t.sendOnNext("two"); + + verify(w, times(1)).onNext("one"); + verify(w, times(1)).onError(any(Throwable.class)); + verify(w, Mockito.never()).onNext("two"); + } + + /** + * Ensure onCompleted can not be called after onError + */ + @Test + public void testOnCompletedAfterOnError() { + TestObservable t = new TestObservable(null); + Observable st = Observable.create(synchronize(Observable.create(t))); + + @SuppressWarnings("unchecked") + Observer w = mock(Observer.class); + @SuppressWarnings("unused") + Subscription ws = st.subscribe(w); + + t.sendOnNext("one"); + t.sendOnError(new RuntimeException("bad")); + t.sendOnCompleted(); + + verify(w, times(1)).onNext("one"); + verify(w, times(1)).onError(any(Throwable.class)); + verify(w, Mockito.never()).onCompleted(); + } + + /** + * Ensure onNext can not be called after onCompleted + */ + @Test + public void testOnNextAfterOnCompleted() { + TestObservable t = new TestObservable(null); + Observable st = Observable.create(synchronize(Observable.create(t))); + + @SuppressWarnings("unchecked") + Observer w = mock(Observer.class); + @SuppressWarnings("unused") + Subscription ws = st.subscribe(w); + + t.sendOnNext("one"); + t.sendOnCompleted(); + t.sendOnNext("two"); + + verify(w, times(1)).onNext("one"); + verify(w, Mockito.never()).onNext("two"); + verify(w, times(1)).onCompleted(); + verify(w, Mockito.never()).onError(any(Throwable.class)); + } + + /** + * Ensure onError can not be called after onCompleted + */ + @Test + public void testOnErrorAfterOnCompleted() { + TestObservable t = new TestObservable(null); + Observable st = Observable.create(synchronize(Observable.create(t))); + + @SuppressWarnings("unchecked") + Observer w = mock(Observer.class); + @SuppressWarnings("unused") + Subscription ws = st.subscribe(w); + + t.sendOnNext("one"); + t.sendOnCompleted(); + t.sendOnError(new RuntimeException("bad")); + + verify(w, times(1)).onNext("one"); + verify(w, times(1)).onCompleted(); + verify(w, Mockito.never()).onError(any(Throwable.class)); + } + + /** + * A Observable that doesn't do the right thing on UnSubscribe/Error/etc in that it will keep sending events down the pipe regardless of what happens. + */ + private static class TestObservable implements Observable.OnSubscribeFunc { + + Observer observer = null; + + public TestObservable(Subscription s) { + } + + /* used to simulate subscription */ + public void sendOnCompleted() { + observer.onCompleted(); + } + + /* used to simulate subscription */ + public void sendOnNext(String value) { + observer.onNext(value); + } + + /* used to simulate subscription */ + public void sendOnError(Throwable e) { + observer.onError(e); + } + + @Override + public Subscription onSubscribe(final Observer observer) { + this.observer = observer; + return new Subscription() { + + @Override + public void unsubscribe() { + // going to do nothing to pretend I'm a bad Observable that keeps allowing events to be sent + } + + }; + } + + } } diff --git a/rxjava-core/src/test/java/rx/operators/OperationTakeLastTest.java b/rxjava-core/src/test/java/rx/operators/OperationTakeLastTest.java index 234e70d543..89fc932b51 100644 --- a/rxjava-core/src/test/java/rx/operators/OperationTakeLastTest.java +++ b/rxjava-core/src/test/java/rx/operators/OperationTakeLastTest.java @@ -1,7 +1,97 @@ package rx.operators; -import org.junit.Ignore; +import org.junit.Test; +import org.mockito.InOrder; +import rx.Observable; +import rx.Observer; + +import static org.mockito.Matchers.any; +import static org.mockito.Mockito.*; +import static rx.operators.OperationTakeLast.takeLast; -@Ignore("WIP") public class OperationTakeLastTest { + + @Test + public void testTakeLastEmpty() { + Observable w = Observable.empty(); + Observable take = Observable.create(takeLast(w, 2)); + + @SuppressWarnings("unchecked") + Observer aObserver = mock(Observer.class); + take.subscribe(aObserver); + verify(aObserver, never()).onNext(any(String.class)); + verify(aObserver, never()).onError(any(Throwable.class)); + verify(aObserver, times(1)).onCompleted(); + } + + @Test + public void testTakeLast1() { + Observable w = Observable.from("one", "two", "three"); + Observable take = Observable.create(takeLast(w, 2)); + + @SuppressWarnings("unchecked") + Observer aObserver = mock(Observer.class); + InOrder inOrder = inOrder(aObserver); + take.subscribe(aObserver); + inOrder.verify(aObserver, times(1)).onNext("two"); + inOrder.verify(aObserver, times(1)).onNext("three"); + verify(aObserver, never()).onNext("one"); + verify(aObserver, never()).onError(any(Throwable.class)); + verify(aObserver, times(1)).onCompleted(); + } + + @Test + public void testTakeLast2() { + Observable w = Observable.from("one"); + Observable take = Observable.create(takeLast(w, 10)); + + @SuppressWarnings("unchecked") + Observer aObserver = mock(Observer.class); + take.subscribe(aObserver); + verify(aObserver, times(1)).onNext("one"); + verify(aObserver, never()).onError(any(Throwable.class)); + verify(aObserver, times(1)).onCompleted(); + } + + @Test + public void testTakeLastWithZeroCount() { + Observable w = Observable.from("one"); + Observable take = Observable.create(takeLast(w, 0)); + + @SuppressWarnings("unchecked") + Observer aObserver = mock(Observer.class); + take.subscribe(aObserver); + verify(aObserver, never()).onNext("one"); + verify(aObserver, never()).onError(any(Throwable.class)); + verify(aObserver, times(1)).onCompleted(); + } + + @Test + public void testTakeLastWithNull() { + Observable w = Observable.from("one", null, "three"); + Observable take = Observable.create(takeLast(w, 2)); + + @SuppressWarnings("unchecked") + Observer aObserver = mock(Observer.class); + take.subscribe(aObserver); + verify(aObserver, never()).onNext("one"); + verify(aObserver, times(1)).onNext(null); + verify(aObserver, times(1)).onNext("three"); + verify(aObserver, never()).onError(any(Throwable.class)); + verify(aObserver, times(1)).onCompleted(); + } + + @Test + public void testTakeLastWithNegativeCount() { + Observable w = Observable.from("one"); + Observable take = Observable.create(takeLast(w, -1)); + + @SuppressWarnings("unchecked") + Observer aObserver = mock(Observer.class); + take.subscribe(aObserver); + verify(aObserver, never()).onNext("one"); + verify(aObserver, times(1)).onError( + any(IndexOutOfBoundsException.class)); + verify(aObserver, never()).onCompleted(); + } } diff --git a/rxjava-core/src/test/java/rx/operators/OperationTakeTest.java b/rxjava-core/src/test/java/rx/operators/OperationTakeTest.java index eaa1bdf1d4..b02c4925cd 100644 --- a/rxjava-core/src/test/java/rx/operators/OperationTakeTest.java +++ b/rxjava-core/src/test/java/rx/operators/OperationTakeTest.java @@ -1,7 +1,213 @@ package rx.operators; -import org.junit.Ignore; +import org.junit.Test; +import org.mockito.InOrder; +import rx.Observable; +import rx.Observer; +import rx.Subscription; +import rx.subscriptions.Subscriptions; +import rx.util.functions.Func1; + +import java.util.concurrent.atomic.AtomicBoolean; + +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; +import static org.mockito.Matchers.any; +import static org.mockito.Matchers.anyString; +import static org.mockito.Mockito.*; +import static rx.operators.OperationTake.take; -@Ignore("WIP") public class OperationTakeTest { + + @Test + public void testTake1() { + Observable w = Observable.from("one", "two", "three"); + Observable take = Observable.create(take(w, 2)); + + @SuppressWarnings("unchecked") + Observer aObserver = mock(Observer.class); + take.subscribe(aObserver); + verify(aObserver, times(1)).onNext("one"); + verify(aObserver, times(1)).onNext("two"); + verify(aObserver, never()).onNext("three"); + verify(aObserver, never()).onError(any(Throwable.class)); + verify(aObserver, times(1)).onCompleted(); + } + + @Test + public void testTake2() { + Observable w = Observable.from("one", "two", "three"); + Observable take = Observable.create(take(w, 1)); + + @SuppressWarnings("unchecked") + Observer aObserver = mock(Observer.class); + take.subscribe(aObserver); + verify(aObserver, times(1)).onNext("one"); + verify(aObserver, never()).onNext("two"); + verify(aObserver, never()).onNext("three"); + verify(aObserver, never()).onError(any(Throwable.class)); + verify(aObserver, times(1)).onCompleted(); + } + + @Test(expected = IllegalArgumentException.class) + public void testTakeWithError() { + Observable.from(1, 2, 3).take(1).map(new Func1() { + public Integer call(Integer t1) { + throw new IllegalArgumentException("some error"); + } + }).toBlockingObservable().single(); + } + + @Test + public void testTakeWithErrorHappeningInOnNext() { + Observable w = Observable.from(1, 2, 3).take(2).map(new Func1() { + public Integer call(Integer t1) { + throw new IllegalArgumentException("some error"); + } + }); + + @SuppressWarnings("unchecked") + Observer observer = mock(Observer.class); + w.subscribe(observer); + InOrder inOrder = inOrder(observer); + inOrder.verify(observer, times(1)).onError(any(IllegalArgumentException.class)); + inOrder.verifyNoMoreInteractions(); + } + + @Test + public void testTakeWithErrorHappeningInTheLastOnNext() { + Observable w = Observable.from(1, 2, 3).take(1).map(new Func1() { + public Integer call(Integer t1) { + throw new IllegalArgumentException("some error"); + } + }); + + @SuppressWarnings("unchecked") + Observer observer = mock(Observer.class); + w.subscribe(observer); + InOrder inOrder = inOrder(observer); + inOrder.verify(observer, times(1)).onError(any(IllegalArgumentException.class)); + inOrder.verifyNoMoreInteractions(); + } + + @Test + public void testTakeDoesntLeakErrors() { + Observable source = Observable.create(new Observable.OnSubscribeFunc() { + @Override + public Subscription onSubscribe(Observer observer) { + observer.onNext("one"); + observer.onError(new Throwable("test failed")); + return Subscriptions.empty(); + } + }); + + @SuppressWarnings("unchecked") + Observer aObserver = mock(Observer.class); + + Observable.create(take(source, 1)).subscribe(aObserver); + + verify(aObserver, times(1)).onNext("one"); + // even though onError is called we take(1) so shouldn't see it + verify(aObserver, never()).onError(any(Throwable.class)); + verify(aObserver, times(1)).onCompleted(); + verifyNoMoreInteractions(aObserver); + } + + @Test + public void testTakeZeroDoesntLeakError() { + final AtomicBoolean subscribed = new AtomicBoolean(false); + final AtomicBoolean unSubscribed = new AtomicBoolean(false); + Observable source = Observable.create(new Observable.OnSubscribeFunc() { + @Override + public Subscription onSubscribe(Observer observer) { + subscribed.set(true); + observer.onError(new Throwable("test failed")); + return new Subscription() { + @Override + public void unsubscribe() { + unSubscribed.set(true); + } + }; + } + }); + + @SuppressWarnings("unchecked") + Observer aObserver = mock(Observer.class); + + Observable.create(take(source, 0)).subscribe(aObserver); + assertTrue("source subscribed", subscribed.get()); + assertTrue("source unsubscribed", unSubscribed.get()); + + verify(aObserver, never()).onNext(anyString()); + // even though onError is called we take(0) so shouldn't see it + verify(aObserver, never()).onError(any(Throwable.class)); + verify(aObserver, times(1)).onCompleted(); + verifyNoMoreInteractions(aObserver); + } + + @Test + public void testUnsubscribeAfterTake() { + final Subscription s = mock(Subscription.class); + TestObservableFunc f = new TestObservableFunc(s, "one", "two", "three"); + Observable w = Observable.create(f); + + @SuppressWarnings("unchecked") + Observer aObserver = mock(Observer.class); + Observable take = Observable.create(take(w, 1)); + take.subscribe(aObserver); + + // wait for the Observable to complete + try { + f.t.join(); + } catch (Throwable e) { + e.printStackTrace(); + fail(e.getMessage()); + } + + System.out.println("TestObservable thread finished"); + verify(aObserver, times(1)).onNext("one"); + verify(aObserver, never()).onNext("two"); + verify(aObserver, never()).onNext("three"); + verify(aObserver, times(1)).onCompleted(); + verify(s, times(1)).unsubscribe(); + verifyNoMoreInteractions(aObserver); + } + + private static class TestObservableFunc implements Observable.OnSubscribeFunc { + + final Subscription s; + final String[] values; + Thread t = null; + + public TestObservableFunc(Subscription s, String... values) { + this.s = s; + this.values = values; + } + + @Override + public Subscription onSubscribe(final Observer observer) { + System.out.println("TestObservable subscribed to ..."); + t = new Thread(new Runnable() { + + @Override + public void run() { + try { + System.out.println("running TestObservable thread"); + for (String s : values) { + System.out.println("TestObservable onNext: " + s); + observer.onNext(s); + } + observer.onCompleted(); + } catch (Throwable e) { + throw new RuntimeException(e); + } + } + + }); + System.out.println("starting TestObservable thread"); + t.start(); + System.out.println("done starting TestObservable thread"); + return s; + } + } } diff --git a/rxjava-core/src/test/java/rx/operators/OperationTakeUntilTest.java b/rxjava-core/src/test/java/rx/operators/OperationTakeUntilTest.java index 22cd5eb078..0e46af91e8 100644 --- a/rxjava-core/src/test/java/rx/operators/OperationTakeUntilTest.java +++ b/rxjava-core/src/test/java/rx/operators/OperationTakeUntilTest.java @@ -1,7 +1,164 @@ package rx.operators; -import org.junit.Ignore; +import org.junit.Test; +import rx.Observable; +import rx.Observer; +import rx.Subscription; + +import static org.mockito.Mockito.*; +import static rx.operators.OperationTakeUntil.takeUntil; -@Ignore("WIP") public class OperationTakeUntilTest { + + @Test + @SuppressWarnings("unchecked") + public void testTakeUntil() { + Subscription sSource = mock(Subscription.class); + Subscription sOther = mock(Subscription.class); + TestObservable source = new TestObservable(sSource); + TestObservable other = new TestObservable(sOther); + + Observer result = mock(Observer.class); + Observable stringObservable = takeUntil(Observable.create(source), Observable.create(other)); + stringObservable.subscribe(result); + source.sendOnNext("one"); + source.sendOnNext("two"); + other.sendOnNext("three"); + source.sendOnNext("four"); + source.sendOnCompleted(); + other.sendOnCompleted(); + + verify(result, times(1)).onNext("one"); + verify(result, times(1)).onNext("two"); + verify(result, times(0)).onNext("three"); + verify(result, times(0)).onNext("four"); + verify(sSource, times(1)).unsubscribe(); + verify(sOther, times(1)).unsubscribe(); + + } + + @Test + @SuppressWarnings("unchecked") + public void testTakeUntilSourceCompleted() { + Subscription sSource = mock(Subscription.class); + Subscription sOther = mock(Subscription.class); + TestObservable source = new TestObservable(sSource); + TestObservable other = new TestObservable(sOther); + + Observer result = mock(Observer.class); + Observable stringObservable = takeUntil(Observable.create(source), Observable.create(other)); + stringObservable.subscribe(result); + source.sendOnNext("one"); + source.sendOnNext("two"); + source.sendOnCompleted(); + + verify(result, times(1)).onNext("one"); + verify(result, times(1)).onNext("two"); + verify(sSource, times(1)).unsubscribe(); + verify(sOther, times(1)).unsubscribe(); + + } + + @Test + @SuppressWarnings("unchecked") + public void testTakeUntilSourceError() { + Subscription sSource = mock(Subscription.class); + Subscription sOther = mock(Subscription.class); + TestObservable source = new TestObservable(sSource); + TestObservable other = new TestObservable(sOther); + Throwable error = new Throwable(); + + Observer result = mock(Observer.class); + Observable stringObservable = takeUntil(Observable.create(source), Observable.create(other)); + stringObservable.subscribe(result); + source.sendOnNext("one"); + source.sendOnNext("two"); + source.sendOnError(error); + + verify(result, times(1)).onNext("one"); + verify(result, times(1)).onNext("two"); + verify(result, times(1)).onError(error); + verify(sSource, times(1)).unsubscribe(); + verify(sOther, times(1)).unsubscribe(); + + } + + @Test + @SuppressWarnings("unchecked") + public void testTakeUntilOtherError() { + Subscription sSource = mock(Subscription.class); + Subscription sOther = mock(Subscription.class); + TestObservable source = new TestObservable(sSource); + TestObservable other = new TestObservable(sOther); + Throwable error = new Throwable(); + + Observer result = mock(Observer.class); + Observable stringObservable = takeUntil(Observable.create(source), Observable.create(other)); + stringObservable.subscribe(result); + source.sendOnNext("one"); + source.sendOnNext("two"); + other.sendOnError(error); + + verify(result, times(1)).onNext("one"); + verify(result, times(1)).onNext("two"); + verify(result, times(1)).onError(error); + verify(result, times(0)).onCompleted(); + verify(sSource, times(1)).unsubscribe(); + verify(sOther, times(1)).unsubscribe(); + + } + + @Test + @SuppressWarnings("unchecked") + public void testTakeUntilOtherCompleted() { + Subscription sSource = mock(Subscription.class); + Subscription sOther = mock(Subscription.class); + TestObservable source = new TestObservable(sSource); + TestObservable other = new TestObservable(sOther); + + Observer result = mock(Observer.class); + Observable stringObservable = takeUntil(Observable.create(source), Observable.create(other)); + stringObservable.subscribe(result); + source.sendOnNext("one"); + source.sendOnNext("two"); + other.sendOnCompleted(); + + verify(result, times(1)).onNext("one"); + verify(result, times(1)).onNext("two"); + verify(result, times(0)).onCompleted(); + verify(sSource, times(0)).unsubscribe(); + verify(sOther, times(0)).unsubscribe(); + + } + + private static class TestObservable implements Observable.OnSubscribeFunc { + + Observer observer = null; + Subscription s; + + public TestObservable(Subscription s) { + this.s = s; + } + + /* used to simulate subscription */ + public void sendOnCompleted() { + observer.onCompleted(); + } + + /* used to simulate subscription */ + public void sendOnNext(String value) { + observer.onNext(value); + } + + /* used to simulate subscription */ + public void sendOnError(Throwable e) { + observer.onError(e); + } + + @Override + public Subscription onSubscribe(final Observer observer) { + this.observer = observer; + return s; + } + } } diff --git a/rxjava-core/src/test/java/rx/operators/OperationTakeWhileTest.java b/rxjava-core/src/test/java/rx/operators/OperationTakeWhileTest.java new file mode 100644 index 0000000000..8109c818e0 --- /dev/null +++ b/rxjava-core/src/test/java/rx/operators/OperationTakeWhileTest.java @@ -0,0 +1,204 @@ +package rx.operators; + +import org.junit.Test; +import rx.Observable; +import rx.Observer; +import rx.Subscription; +import rx.subjects.PublishSubject; +import rx.subjects.Subject; +import rx.subscriptions.Subscriptions; +import rx.util.functions.Func1; +import rx.util.functions.Func2; + +import static org.junit.Assert.fail; +import static org.mockito.Matchers.any; +import static org.mockito.Mockito.*; +import static rx.operators.OperationTakeWhile.takeWhile; +import static rx.operators.OperationTakeWhile.takeWhileWithIndex; + +public class OperationTakeWhileTest { + + @Test + public void testTakeWhile1() { + Observable w = Observable.from(1, 2, 3); + Observable take = Observable.create(takeWhile(w, new Func1() { + @Override + public Boolean call(Integer input) { + return input < 3; + } + })); + + @SuppressWarnings("unchecked") + Observer aObserver = mock(Observer.class); + take.subscribe(aObserver); + verify(aObserver, times(1)).onNext(1); + verify(aObserver, times(1)).onNext(2); + verify(aObserver, never()).onNext(3); + verify(aObserver, never()).onError(any(Throwable.class)); + verify(aObserver, times(1)).onCompleted(); + } + + @Test + public void testTakeWhileOnSubject1() { + Subject s = PublishSubject.create(); + Observable take = Observable.create(takeWhile(s, new Func1() { + @Override + public Boolean call(Integer input) { + return input < 3; + } + })); + + @SuppressWarnings("unchecked") + Observer aObserver = mock(Observer.class); + take.subscribe(aObserver); + + s.onNext(1); + s.onNext(2); + s.onNext(3); + s.onNext(4); + s.onNext(5); + s.onCompleted(); + + verify(aObserver, times(1)).onNext(1); + verify(aObserver, times(1)).onNext(2); + verify(aObserver, never()).onNext(3); + verify(aObserver, never()).onNext(4); + verify(aObserver, never()).onNext(5); + verify(aObserver, never()).onError(any(Throwable.class)); + verify(aObserver, times(1)).onCompleted(); + } + + @Test + public void testTakeWhile2() { + Observable w = Observable.from("one", "two", "three"); + Observable take = Observable.create(takeWhileWithIndex(w, new Func2() { + @Override + public Boolean call(String input, Integer index) { + return index < 2; + } + })); + + @SuppressWarnings("unchecked") + Observer aObserver = mock(Observer.class); + take.subscribe(aObserver); + verify(aObserver, times(1)).onNext("one"); + verify(aObserver, times(1)).onNext("two"); + verify(aObserver, never()).onNext("three"); + verify(aObserver, never()).onError(any(Throwable.class)); + verify(aObserver, times(1)).onCompleted(); + } + + @Test + public void testTakeWhileDoesntLeakErrors() { + Observable source = Observable.create(new Observable.OnSubscribeFunc() { + @Override + public Subscription onSubscribe(Observer observer) { + observer.onNext("one"); + observer.onError(new Throwable("test failed")); + return Subscriptions.empty(); + } + }); + + Observable.create(takeWhile(source, new Func1() { + @Override + public Boolean call(String s) { + return false; + } + })).toBlockingObservable().last(); + } + + @Test + public void testTakeWhileProtectsPredicateCall() { + TestObservable source = new TestObservable(mock(Subscription.class), "one"); + final RuntimeException testException = new RuntimeException("test exception"); + + @SuppressWarnings("unchecked") + Observer aObserver = mock(Observer.class); + Observable take = Observable.create(takeWhile(Observable.create(source), new Func1() { + @Override + public Boolean call(String s) { + throw testException; + } + })); + take.subscribe(aObserver); + + // wait for the Observable to complete + try { + source.t.join(); + } catch (Throwable e) { + e.printStackTrace(); + fail(e.getMessage()); + } + + verify(aObserver, never()).onNext(any(String.class)); + verify(aObserver, times(1)).onError(testException); + } + + @Test + public void testUnsubscribeAfterTake() { + Subscription s = mock(Subscription.class); + TestObservable w = new TestObservable(s, "one", "two", "three"); + + @SuppressWarnings("unchecked") + Observer aObserver = mock(Observer.class); + Observable take = Observable.create(takeWhileWithIndex(Observable.create(w), new Func2() { + @Override + public Boolean call(String s, Integer index) { + return index < 1; + } + })); + take.subscribe(aObserver); + + // wait for the Observable to complete + try { + w.t.join(); + } catch (Throwable e) { + e.printStackTrace(); + fail(e.getMessage()); + } + + System.out.println("TestObservable thread finished"); + verify(aObserver, times(1)).onNext("one"); + verify(aObserver, never()).onNext("two"); + verify(aObserver, never()).onNext("three"); + verify(s, times(1)).unsubscribe(); + } + + private static class TestObservable implements Observable.OnSubscribeFunc { + + final Subscription s; + final String[] values; + Thread t = null; + + public TestObservable(Subscription s, String... values) { + this.s = s; + this.values = values; + } + + @Override + public Subscription onSubscribe(final Observer observer) { + System.out.println("TestObservable subscribed to ..."); + t = new Thread(new Runnable() { + + @Override + public void run() { + try { + System.out.println("running TestObservable thread"); + for (String s : values) { + System.out.println("TestObservable onNext: " + s); + observer.onNext(s); + } + observer.onCompleted(); + } catch (Throwable e) { + throw new RuntimeException(e); + } + } + + }); + System.out.println("starting TestObservable thread"); + t.start(); + System.out.println("done starting TestObservable thread"); + return s; + } + } +} diff --git a/rxjava-core/src/test/java/rx/operators/OperationThrottleFirstTest.java b/rxjava-core/src/test/java/rx/operators/OperationThrottleFirstTest.java index 66301abfca..76cac5dfe9 100644 --- a/rxjava-core/src/test/java/rx/operators/OperationThrottleFirstTest.java +++ b/rxjava-core/src/test/java/rx/operators/OperationThrottleFirstTest.java @@ -1,7 +1,114 @@ package rx.operators; -import org.junit.Ignore; +import org.junit.Before; +import org.junit.Test; +import org.mockito.InOrder; +import rx.Observable; +import rx.Observer; +import rx.Subscription; +import rx.concurrency.TestScheduler; +import rx.subscriptions.Subscriptions; +import rx.util.functions.Action0; + +import java.util.concurrent.TimeUnit; + +import static org.mockito.Matchers.any; +import static org.mockito.Mockito.*; -@Ignore("WIP") public class OperationThrottleFirstTest { + + private TestScheduler scheduler; + private Observer observer; + + @Before + @SuppressWarnings("unchecked") + public void before() { + scheduler = new TestScheduler(); + observer = mock(Observer.class); + } + + @Test + public void testThrottlingWithCompleted() { + Observable source = Observable.create(new Observable.OnSubscribeFunc() { + @Override + public Subscription onSubscribe(Observer observer) { + publishNext(observer, 100, "one"); // publish as it's first + publishNext(observer, 300, "two"); // skip as it's last within the first 400 + publishNext(observer, 900, "three"); // publish + publishNext(observer, 905, "four"); // skip + publishCompleted(observer, 1000); // Should be published as soon as the timeout expires. + + return Subscriptions.empty(); + } + }); + + Observable sampled = Observable.create(OperationThrottleFirst.throttleFirst(source, 400, TimeUnit.MILLISECONDS, scheduler)); + sampled.subscribe(observer); + + InOrder inOrder = inOrder(observer); + + scheduler.advanceTimeTo(1000, TimeUnit.MILLISECONDS); + inOrder.verify(observer, times(1)).onNext("one"); + inOrder.verify(observer, times(0)).onNext("two"); + inOrder.verify(observer, times(1)).onNext("three"); + inOrder.verify(observer, times(0)).onNext("four"); + inOrder.verify(observer, times(1)).onCompleted(); + inOrder.verifyNoMoreInteractions(); + } + + @Test + public void testThrottlingWithError() { + Observable source = Observable.create(new Observable.OnSubscribeFunc() { + @Override + public Subscription onSubscribe(Observer observer) { + Exception error = new TestException(); + publishNext(observer, 100, "one"); // Should be published since it is first + publishNext(observer, 200, "two"); // Should be skipped since onError will arrive before the timeout expires + publishError(observer, 300, error); // Should be published as soon as the timeout expires. + + return Subscriptions.empty(); + } + }); + + Observable sampled = Observable.create(OperationThrottleFirst.throttleFirst(source, 400, TimeUnit.MILLISECONDS, scheduler)); + sampled.subscribe(observer); + + InOrder inOrder = inOrder(observer); + + scheduler.advanceTimeTo(400, TimeUnit.MILLISECONDS); + inOrder.verify(observer).onNext("one"); + inOrder.verify(observer).onError(any(TestException.class)); + inOrder.verifyNoMoreInteractions(); + } + + private void publishCompleted(final Observer observer, long delay) { + scheduler.schedule(new Action0() { + @Override + public void call() { + observer.onCompleted(); + } + }, delay, TimeUnit.MILLISECONDS); + } + + private void publishError(final Observer observer, long delay, final Exception error) { + scheduler.schedule(new Action0() { + @Override + public void call() { + observer.onError(error); + } + }, delay, TimeUnit.MILLISECONDS); + } + + private void publishNext(final Observer observer, long delay, final T value) { + scheduler.schedule(new Action0() { + @Override + public void call() { + observer.onNext(value); + } + }, delay, TimeUnit.MILLISECONDS); + } + + @SuppressWarnings("serial") + private class TestException extends Exception { + } } diff --git a/rxjava-core/src/test/java/rx/operators/OperationTimeIntervalTest.java b/rxjava-core/src/test/java/rx/operators/OperationTimeIntervalTest.java new file mode 100644 index 0000000000..6ce6504b05 --- /dev/null +++ b/rxjava-core/src/test/java/rx/operators/OperationTimeIntervalTest.java @@ -0,0 +1,60 @@ +package rx.operators; + +import org.junit.Before; +import org.junit.Test; +import org.mockito.InOrder; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import rx.Observable; +import rx.Observer; +import rx.concurrency.TestScheduler; +import rx.subjects.PublishSubject; +import rx.util.TimeInterval; + +import java.util.concurrent.TimeUnit; + +import static org.mockito.Mockito.inOrder; +import static org.mockito.Mockito.times; + +public class OperationTimeIntervalTest { + + private static final TimeUnit TIME_UNIT = TimeUnit.MILLISECONDS; + + @Mock + private Observer> observer; + + private TestScheduler testScheduler; + private PublishSubject subject; + private Observable> observable; + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + testScheduler = new TestScheduler(); + subject = PublishSubject.create(); + observable = subject.timeInterval(testScheduler); + } + + @Test + public void testTimeInterval() { + InOrder inOrder = inOrder(observer); + observable.subscribe(observer); + + testScheduler.advanceTimeBy(1000, TIME_UNIT); + subject.onNext(1); + testScheduler.advanceTimeBy(2000, TIME_UNIT); + subject.onNext(2); + testScheduler.advanceTimeBy(3000, TIME_UNIT); + subject.onNext(3); + subject.onCompleted(); + + inOrder.verify(observer, times(1)).onNext( + new TimeInterval(1000, 1)); + inOrder.verify(observer, times(1)).onNext( + new TimeInterval(2000, 2)); + inOrder.verify(observer, times(1)).onNext( + new TimeInterval(3000, 3)); + inOrder.verify(observer, times(1)).onCompleted(); + inOrder.verifyNoMoreInteractions(); + } +} diff --git a/rxjava-core/src/test/java/rx/operators/OperationToObservableFutureTest.java b/rxjava-core/src/test/java/rx/operators/OperationToObservableFutureTest.java index 3f58b63911..f3891128e1 100644 --- a/rxjava-core/src/test/java/rx/operators/OperationToObservableFutureTest.java +++ b/rxjava-core/src/test/java/rx/operators/OperationToObservableFutureTest.java @@ -1,7 +1,47 @@ package rx.operators; -import org.junit.Ignore; +import org.junit.Test; +import rx.Observer; +import rx.Subscription; + +import java.util.concurrent.Future; + +import static org.mockito.Mockito.*; +import static rx.operators.OperationToObservableFuture.ToObservableFuture; -@Ignore("WIP") public class OperationToObservableFutureTest { + + @Test + public void testSuccess() throws Exception { + Future future = mock(Future.class); + Object value = new Object(); + when(future.get()).thenReturn(value); + ToObservableFuture ob = new ToObservableFuture(future); + Observer o = mock(Observer.class); + + Subscription sub = ob.onSubscribe(o); + sub.unsubscribe(); + + verify(o, times(1)).onNext(value); + verify(o, times(1)).onCompleted(); + verify(o, never()).onError(null); + verify(future, never()).cancel(true); + } + + @Test + public void testFailure() throws Exception { + Future future = mock(Future.class); + RuntimeException e = new RuntimeException(); + when(future.get()).thenThrow(e); + ToObservableFuture ob = new ToObservableFuture(future); + Observer o = mock(Observer.class); + + Subscription sub = ob.onSubscribe(o); + sub.unsubscribe(); + + verify(o, never()).onNext(null); + verify(o, never()).onCompleted(); + verify(o, times(1)).onError(e); + verify(future, never()).cancel(true); + } } diff --git a/rxjava-core/src/test/java/rx/operators/OperationToObservableIterableTest.java b/rxjava-core/src/test/java/rx/operators/OperationToObservableIterableTest.java index 1805e1cbcd..a24cb92694 100644 --- a/rxjava-core/src/test/java/rx/operators/OperationToObservableIterableTest.java +++ b/rxjava-core/src/test/java/rx/operators/OperationToObservableIterableTest.java @@ -1,7 +1,32 @@ package rx.operators; import org.junit.Ignore; +import org.junit.Test; +import org.mockito.Mockito; +import rx.Observable; +import rx.Observer; + +import java.util.Arrays; + +import static org.mockito.Matchers.any; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static rx.operators.OperationToObservableIterable.toObservableIterable; -@Ignore("WIP") public class OperationToObservableIterableTest { + + @Test + public void testIterable() { + Observable observable = Observable.create(toObservableIterable(Arrays. asList("one", "two", "three"))); + + @SuppressWarnings("unchecked") + Observer aObserver = mock(Observer.class); + observable.subscribe(aObserver); + verify(aObserver, times(1)).onNext("one"); + verify(aObserver, times(1)).onNext("two"); + verify(aObserver, times(1)).onNext("three"); + verify(aObserver, Mockito.never()).onError(any(Throwable.class)); + verify(aObserver, times(1)).onCompleted(); + } } diff --git a/rxjava-core/src/test/java/rx/operators/OperationToObservableListTest.java b/rxjava-core/src/test/java/rx/operators/OperationToObservableListTest.java index 49c7409e86..12e47aa080 100644 --- a/rxjava-core/src/test/java/rx/operators/OperationToObservableListTest.java +++ b/rxjava-core/src/test/java/rx/operators/OperationToObservableListTest.java @@ -1,7 +1,53 @@ package rx.operators; -import org.junit.Ignore; +import org.junit.Test; +import org.mockito.Mockito; +import rx.Observable; +import rx.Observer; + +import java.util.Arrays; +import java.util.List; + +import static org.mockito.Matchers.any; +import static org.mockito.Mockito.*; +import static rx.operators.OperationToObservableList.toObservableList; -@Ignore("WIP") public class OperationToObservableListTest { + + @Test + public void testList() { + Observable w = Observable.from("one", "two", "three"); + Observable> observable = Observable.create(toObservableList(w)); + + @SuppressWarnings("unchecked") + Observer> aObserver = mock(Observer.class); + observable.subscribe(aObserver); + verify(aObserver, times(1)).onNext(Arrays.asList("one", "two", "three")); + verify(aObserver, Mockito.never()).onError(any(Throwable.class)); + verify(aObserver, times(1)).onCompleted(); + } + + @Test + public void testListMultipleObservers() { + Observable w = Observable.from("one", "two", "three"); + Observable> observable = Observable.create(toObservableList(w)); + + @SuppressWarnings("unchecked") + Observer> o1 = mock(Observer.class); + observable.subscribe(o1); + + @SuppressWarnings("unchecked") + Observer> o2 = mock(Observer.class); + observable.subscribe(o2); + + List expected = Arrays.asList("one", "two", "three"); + + verify(o1, times(1)).onNext(expected); + verify(o1, Mockito.never()).onError(any(Throwable.class)); + verify(o1, times(1)).onCompleted(); + + verify(o2, times(1)).onNext(expected); + verify(o2, Mockito.never()).onError(any(Throwable.class)); + verify(o2, times(1)).onCompleted(); + } } diff --git a/rxjava-core/src/test/java/rx/operators/OperationToObservableSortedListTest.java b/rxjava-core/src/test/java/rx/operators/OperationToObservableSortedListTest.java index 62efef680d..11b6c9ff6a 100644 --- a/rxjava-core/src/test/java/rx/operators/OperationToObservableSortedListTest.java +++ b/rxjava-core/src/test/java/rx/operators/OperationToObservableSortedListTest.java @@ -1,7 +1,50 @@ package rx.operators; -import org.junit.Ignore; +import org.junit.Test; +import org.mockito.Mockito; +import rx.Observable; +import rx.Observer; +import rx.util.functions.Func2; + +import java.util.Arrays; +import java.util.List; + +import static org.mockito.Matchers.any; +import static org.mockito.Mockito.*; +import static rx.operators.OperationToObservableSortedList.toSortedList; -@Ignore("WIP") public class OperationToObservableSortedListTest { + + @Test + public void testSortedList() { + Observable w = Observable.from(1, 3, 2, 5, 4); + Observable> observable = Observable.create(toSortedList(w)); + + @SuppressWarnings("unchecked") + Observer> aObserver = mock(Observer.class); + observable.subscribe(aObserver); + verify(aObserver, times(1)).onNext(Arrays.asList(1, 2, 3, 4, 5)); + verify(aObserver, Mockito.never()).onError(any(Throwable.class)); + verify(aObserver, times(1)).onCompleted(); + } + + @Test + public void testSortedListWithCustomFunction() { + Observable w = Observable.from(1, 3, 2, 5, 4); + Observable> observable = Observable.create(toSortedList(w, new Func2() { + + @Override + public Integer call(Integer t1, Integer t2) { + return t2 - t1; + } + + })); + + @SuppressWarnings("unchecked") + Observer> aObserver = mock(Observer.class); + observable.subscribe(aObserver); + verify(aObserver, times(1)).onNext(Arrays.asList(5, 4, 3, 2, 1)); + verify(aObserver, Mockito.never()).onError(any(Throwable.class)); + verify(aObserver, times(1)).onCompleted(); + } } diff --git a/rxjava-core/src/test/java/rx/operators/OperationWindowTest.java b/rxjava-core/src/test/java/rx/operators/OperationWindowTest.java index 0e602254f5..8a552f534f 100644 --- a/rxjava-core/src/test/java/rx/operators/OperationWindowTest.java +++ b/rxjava-core/src/test/java/rx/operators/OperationWindowTest.java @@ -1,7 +1,315 @@ package rx.operators; -import org.junit.Ignore; +import org.junit.Before; +import org.junit.Test; +import rx.Observable; +import rx.Observer; +import rx.Subscription; +import rx.concurrency.TestScheduler; +import rx.subscriptions.Subscriptions; +import rx.util.Closing; +import rx.util.Closings; +import rx.util.Opening; +import rx.util.Openings; +import rx.util.functions.Action0; +import rx.util.functions.Action1; +import rx.util.functions.Func0; +import rx.util.functions.Func1; + +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.TimeUnit; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.fail; +import static rx.operators.OperationWindow.window; -@Ignore("WIP") public class OperationWindowTest { + + private TestScheduler scheduler; + + @Before + public void before() { + scheduler = new TestScheduler(); + } + + private static List> toLists(Observable> observable) { + final List list = new ArrayList(); + final List> lists = new ArrayList>(); + + observable.subscribe(new Action1>() { + @Override + public void call(Observable tObservable) { + tObservable.subscribe(new Action1() { + @Override + public void call(T t) { + list.add(t); + } + }); + lists.add(new ArrayList(list)); + list.clear(); + } + }); + return lists; + } + + @Test + public void testNonOverlappingWindows() { + Observable subject = Observable.from("one", "two", "three", "four", "five"); + Observable> windowed = Observable.create(window(subject, 3)); + + List> windows = toLists(windowed); + + assertEquals(2, windows.size()); + assertEquals(list("one", "two", "three"), windows.get(0)); + assertEquals(list("four", "five"), windows.get(1)); + } + + @Test + public void testSkipAndCountGaplessEindows() { + Observable subject = Observable.from("one", "two", "three", "four", "five"); + Observable> windowed = Observable.create(window(subject, 3, 3)); + + List> windows = toLists(windowed); + + assertEquals(2, windows.size()); + assertEquals(list("one", "two", "three"), windows.get(0)); + assertEquals(list("four", "five"), windows.get(1)); + } + + @Test + public void testOverlappingWindows() { + Observable subject = Observable.from("zero", "one", "two", "three", "four", "five"); + Observable> windowed = Observable.create(window(subject, 3, 1)); + + List> windows = toLists(windowed); + + assertEquals(6, windows.size()); + assertEquals(list("zero", "one", "two"), windows.get(0)); + assertEquals(list("one", "two", "three"), windows.get(1)); + assertEquals(list("two", "three", "four"), windows.get(2)); + assertEquals(list("three", "four", "five"), windows.get(3)); + assertEquals(list("four", "five"), windows.get(4)); + assertEquals(list("five"), windows.get(5)); + } + + @Test + public void testSkipAndCountWindowsWithGaps() { + Observable subject = Observable.from("one", "two", "three", "four", "five"); + Observable> windowed = Observable.create(window(subject, 2, 3)); + + List> windows = toLists(windowed); + + assertEquals(2, windows.size()); + assertEquals(list("one", "two"), windows.get(0)); + assertEquals(list("four", "five"), windows.get(1)); + } + + @Test + public void testTimedAndCount() { + final List list = new ArrayList(); + final List> lists = new ArrayList>(); + + Observable source = Observable.create(new Observable.OnSubscribeFunc() { + @Override + public Subscription onSubscribe(Observer observer) { + push(observer, "one", 10); + push(observer, "two", 90); + push(observer, "three", 110); + push(observer, "four", 190); + push(observer, "five", 210); + complete(observer, 250); + return Subscriptions.empty(); + } + }); + + Observable> windowed = Observable.create(window(source, 100, TimeUnit.MILLISECONDS, 2, scheduler)); + windowed.subscribe(observeWindow(list, lists)); + + scheduler.advanceTimeTo(100, TimeUnit.MILLISECONDS); + assertEquals(1, lists.size()); + assertEquals(lists.get(0), list("one", "two")); + + scheduler.advanceTimeTo(200, TimeUnit.MILLISECONDS); + assertEquals(2, lists.size()); + assertEquals(lists.get(1), list("three", "four")); + + scheduler.advanceTimeTo(300, TimeUnit.MILLISECONDS); + assertEquals(3, lists.size()); + assertEquals(lists.get(2), list("five")); + } + + @Test + public void testTimed() { + final List list = new ArrayList(); + final List> lists = new ArrayList>(); + + Observable source = Observable.create(new Observable.OnSubscribeFunc() { + @Override + public Subscription onSubscribe(Observer observer) { + push(observer, "one", 98); + push(observer, "two", 99); + push(observer, "three", 100); + push(observer, "four", 101); + push(observer, "five", 102); + complete(observer, 150); + return Subscriptions.empty(); + } + }); + + Observable> windowed = Observable.create(window(source, 100, TimeUnit.MILLISECONDS, scheduler)); + windowed.subscribe(observeWindow(list, lists)); + + scheduler.advanceTimeTo(101, TimeUnit.MILLISECONDS); + assertEquals(1, lists.size()); + assertEquals(lists.get(0), list("one", "two", "three")); + + scheduler.advanceTimeTo(201, TimeUnit.MILLISECONDS); + assertEquals(2, lists.size()); + assertEquals(lists.get(1), list("four", "five")); + } + + @Test + public void testObservableBasedOpenerAndCloser() { + final List list = new ArrayList(); + final List> lists = new ArrayList>(); + + Observable source = Observable.create(new Observable.OnSubscribeFunc() { + @Override + public Subscription onSubscribe(Observer observer) { + push(observer, "one", 10); + push(observer, "two", 60); + push(observer, "three", 110); + push(observer, "four", 160); + push(observer, "five", 210); + complete(observer, 500); + return Subscriptions.empty(); + } + }); + + Observable openings = Observable.create(new Observable.OnSubscribeFunc() { + @Override + public Subscription onSubscribe(Observer observer) { + push(observer, Openings.create(), 50); + push(observer, Openings.create(), 200); + complete(observer, 250); + return Subscriptions.empty(); + } + }); + + Func1> closer = new Func1>() { + @Override + public Observable call(Opening opening) { + return Observable.create(new Observable.OnSubscribeFunc() { + @Override + public Subscription onSubscribe(Observer observer) { + push(observer, Closings.create(), 100); + complete(observer, 101); + return Subscriptions.empty(); + } + }); + } + }; + + Observable> windowed = Observable.create(window(source, openings, closer)); + windowed.subscribe(observeWindow(list, lists)); + + scheduler.advanceTimeTo(500, TimeUnit.MILLISECONDS); + assertEquals(2, lists.size()); + assertEquals(lists.get(0), list("two", "three")); + assertEquals(lists.get(1), list("five")); + } + + @Test + public void testObservableBasedCloser() { + final List list = new ArrayList(); + final List> lists = new ArrayList>(); + + Observable source = Observable.create(new Observable.OnSubscribeFunc() { + @Override + public Subscription onSubscribe(Observer observer) { + push(observer, "one", 10); + push(observer, "two", 60); + push(observer, "three", 110); + push(observer, "four", 160); + push(observer, "five", 210); + complete(observer, 250); + return Subscriptions.empty(); + } + }); + + Func0> closer = new Func0>() { + @Override + public Observable call() { + return Observable.create(new Observable.OnSubscribeFunc() { + @Override + public Subscription onSubscribe(Observer observer) { + push(observer, Closings.create(), 100); + complete(observer, 101); + return Subscriptions.empty(); + } + }); + } + }; + + Observable> windowed = Observable.create(window(source, closer)); + windowed.subscribe(observeWindow(list, lists)); + + scheduler.advanceTimeTo(500, TimeUnit.MILLISECONDS); + assertEquals(3, lists.size()); + assertEquals(lists.get(0), list("one", "two")); + assertEquals(lists.get(1), list("three", "four")); + assertEquals(lists.get(2), list("five")); + } + + private List list(String... args) { + List list = new ArrayList(); + for (String arg : args) { + list.add(arg); + } + return list; + } + + private void push(final Observer observer, final T value, int delay) { + scheduler.schedule(new Action0() { + @Override + public void call() { + observer.onNext(value); + } + }, delay, TimeUnit.MILLISECONDS); + } + + private void complete(final Observer observer, int delay) { + scheduler.schedule(new Action0() { + @Override + public void call() { + observer.onCompleted(); + } + }, delay, TimeUnit.MILLISECONDS); + } + + private Action1> observeWindow(final List list, final List> lists) { + return new Action1>() { + @Override + public void call(Observable stringObservable) { + stringObservable.subscribe(new Observer() { + @Override + public void onCompleted() { + lists.add(new ArrayList(list)); + list.clear(); + } + + @Override + public void onError(Throwable e) { + fail(e.getMessage()); + } + + @Override + public void onNext(String args) { + list.add(args); + } + }); + } + }; + } } diff --git a/rxjava-core/src/test/java/rx/operators/OperationZipTest.java b/rxjava-core/src/test/java/rx/operators/OperationZipTest.java index 3e027193ab..2a73ac3eab 100644 --- a/rxjava-core/src/test/java/rx/operators/OperationZipTest.java +++ b/rxjava-core/src/test/java/rx/operators/OperationZipTest.java @@ -1,7 +1,584 @@ package rx.operators; import org.junit.Ignore; +import org.junit.Test; +import org.mockito.InOrder; +import rx.Observable; +import rx.Observer; +import rx.Subscription; +import rx.subscriptions.Subscriptions; +import rx.util.functions.Func2; +import rx.util.functions.Func3; +import rx.util.functions.FuncN; +import rx.util.functions.Functions; + +import java.util.Arrays; +import java.util.Collection; + +import static org.mockito.Matchers.any; +import static org.mockito.Matchers.anyString; +import static org.mockito.Mockito.*; +import static rx.operators.OperationZip.Aggregator; +import static rx.operators.OperationZip.ZipObserver; +import static rx.operators.OperationZip.zip; -@Ignore("WIP") public class OperationZipTest { + + @SuppressWarnings("unchecked") + @Test + public void testCollectionSizeDifferentThanFunction() { + FuncN zipr = Functions.fromFunc(getConcatStringIntegerIntArrayZipr()); + //Func3 + + /* define a Observer to receive aggregated events */ + Observer aObserver = mock(Observer.class); + + @SuppressWarnings("rawtypes") + Collection ws = java.util.Collections.singleton(Observable.from("one", "two")); + Observable w = Observable.create(zip(ws, zipr)); + w.subscribe(aObserver); + + verify(aObserver, times(1)).onError(any(Throwable.class)); + verify(aObserver, never()).onCompleted(); + verify(aObserver, never()).onNext(any(String.class)); + } + + @SuppressWarnings("unchecked") + /* mock calls don't do generics */ + @Test + public void testZippingDifferentLengthObservableSequences1() { + Observer w = mock(Observer.class); + + TestObservable w1 = new TestObservable(); + TestObservable w2 = new TestObservable(); + TestObservable w3 = new TestObservable(); + + Observable zipW = Observable.create(zip(Observable.create(w1), Observable.create(w2), Observable.create(w3), getConcat3StringsZipr())); + zipW.subscribe(w); + + /* simulate sending data */ + // once for w1 + w1.observer.onNext("1a"); + w1.observer.onCompleted(); + // twice for w2 + w2.observer.onNext("2a"); + w2.observer.onNext("2b"); + w2.observer.onCompleted(); + // 4 times for w3 + w3.observer.onNext("3a"); + w3.observer.onNext("3b"); + w3.observer.onNext("3c"); + w3.observer.onNext("3d"); + w3.observer.onCompleted(); + + /* we should have been called 1 time on the Observer */ + InOrder inOrder = inOrder(w); + inOrder.verify(w).onNext("1a2a3a"); + + inOrder.verify(w, times(1)).onCompleted(); + } + + @Test + public void testZippingDifferentLengthObservableSequences2() { + @SuppressWarnings("unchecked") + Observer w = mock(Observer.class); + + TestObservable w1 = new TestObservable(); + TestObservable w2 = new TestObservable(); + TestObservable w3 = new TestObservable(); + + Observable zipW = Observable.create(zip(Observable.create(w1), Observable.create(w2), Observable.create(w3), getConcat3StringsZipr())); + zipW.subscribe(w); + + /* simulate sending data */ + // 4 times for w1 + w1.observer.onNext("1a"); + w1.observer.onNext("1b"); + w1.observer.onNext("1c"); + w1.observer.onNext("1d"); + w1.observer.onCompleted(); + // twice for w2 + w2.observer.onNext("2a"); + w2.observer.onNext("2b"); + w2.observer.onCompleted(); + // 1 times for w3 + w3.observer.onNext("3a"); + w3.observer.onCompleted(); + + /* we should have been called 1 time on the Observer */ + InOrder inOrder = inOrder(w); + inOrder.verify(w).onNext("1a2a3a"); + + inOrder.verify(w, times(1)).onCompleted(); + + } + + /** + * Testing internal private logic due to the complexity so I want to use TDD to test as a I build it rather than relying purely on the overall functionality expected by the public methods. + */ + @SuppressWarnings("unchecked") + /* mock calls don't do generics */ + @Test + public void testAggregatorSimple() { + FuncN zipr = getConcatZipr(); + /* create the aggregator which will execute the zip function when all Observables provide values */ + Aggregator a = new Aggregator(zipr); + + /* define a Observer to receive aggregated events */ + Observer aObserver = mock(Observer.class); + a.onSubscribe(aObserver); + + /* mock the Observable Observers that are 'pushing' data for us */ + ZipObserver r1 = mock(ZipObserver.class); + ZipObserver r2 = mock(ZipObserver.class); + + /* pretend we're starting up */ + a.addObserver(r1); + a.addObserver(r2); + + /* simulate the Observables pushing data into the aggregator */ + a.next(r1, "hello"); + a.next(r2, "world"); + + InOrder inOrder = inOrder(aObserver); + + verify(aObserver, never()).onError(any(Throwable.class)); + verify(aObserver, never()).onCompleted(); + inOrder.verify(aObserver, times(1)).onNext("helloworld"); + + a.next(r1, "hello "); + a.next(r2, "again"); + + verify(aObserver, never()).onError(any(Throwable.class)); + verify(aObserver, never()).onCompleted(); + inOrder.verify(aObserver, times(1)).onNext("hello again"); + + a.complete(r1); + a.complete(r2); + + inOrder.verify(aObserver, never()).onNext(anyString()); + verify(aObserver, times(1)).onCompleted(); + } + + @SuppressWarnings("unchecked") + /* mock calls don't do generics */ + @Test + public void testAggregatorDifferentSizedResultsWithOnComplete() { + FuncN zipr = getConcatZipr(); + /* create the aggregator which will execute the zip function when all Observables provide values */ + Aggregator a = new Aggregator(zipr); + + /* define a Observer to receive aggregated events */ + Observer aObserver = mock(Observer.class); + a.onSubscribe(aObserver); + + /* mock the Observable Observers that are 'pushing' data for us */ + ZipObserver r1 = mock(ZipObserver.class); + ZipObserver r2 = mock(ZipObserver.class); + + /* pretend we're starting up */ + a.addObserver(r1); + a.addObserver(r2); + + /* simulate the Observables pushing data into the aggregator */ + a.next(r1, "hello"); + a.next(r2, "world"); + a.complete(r2); + + InOrder inOrder = inOrder(aObserver); + + inOrder.verify(aObserver, never()).onError(any(Throwable.class)); + inOrder.verify(aObserver, never()).onCompleted(); + inOrder.verify(aObserver, times(1)).onNext("helloworld"); + + a.next(r1, "hi"); + a.complete(r1); + + inOrder.verify(aObserver, never()).onError(any(Throwable.class)); + inOrder.verify(aObserver, times(1)).onCompleted(); + inOrder.verify(aObserver, never()).onNext(anyString()); + } + + @SuppressWarnings("unchecked") + /* mock calls don't do generics */ + @Test + public void testAggregateMultipleTypes() { + FuncN zipr = getConcatZipr(); + /* create the aggregator which will execute the zip function when all Observables provide values */ + Aggregator a = new Aggregator(zipr); + + /* define a Observer to receive aggregated events */ + Observer aObserver = mock(Observer.class); + a.onSubscribe(aObserver); + + /* mock the Observable Observers that are 'pushing' data for us */ + ZipObserver r1 = mock(ZipObserver.class); + ZipObserver r2 = mock(ZipObserver.class); + + /* pretend we're starting up */ + a.addObserver(r1); + a.addObserver(r2); + + /* simulate the Observables pushing data into the aggregator */ + a.next(r1, "hello"); + a.next(r2, "world"); + a.complete(r2); + + InOrder inOrder = inOrder(aObserver); + + inOrder.verify(aObserver, never()).onError(any(Throwable.class)); + inOrder.verify(aObserver, never()).onCompleted(); + inOrder.verify(aObserver, times(1)).onNext("helloworld"); + + a.next(r1, "hi"); + a.complete(r1); + + inOrder.verify(aObserver, never()).onError(any(Throwable.class)); + inOrder.verify(aObserver, times(1)).onCompleted(); + inOrder.verify(aObserver, never()).onNext(anyString()); + } + + @SuppressWarnings("unchecked") + /* mock calls don't do generics */ + @Test + public void testAggregate3Types() { + FuncN zipr = getConcatZipr(); + /* create the aggregator which will execute the zip function when all Observables provide values */ + Aggregator a = new Aggregator(zipr); + + /* define a Observer to receive aggregated events */ + Observer aObserver = mock(Observer.class); + a.onSubscribe(aObserver); + + /* mock the Observable Observers that are 'pushing' data for us */ + ZipObserver r1 = mock(ZipObserver.class); + ZipObserver r2 = mock(ZipObserver.class); + ZipObserver r3 = mock(ZipObserver.class); + + /* pretend we're starting up */ + a.addObserver(r1); + a.addObserver(r2); + a.addObserver(r3); + + /* simulate the Observables pushing data into the aggregator */ + a.next(r1, "hello"); + a.next(r2, 2); + a.next(r3, new int[] { 5, 6, 7 }); + + verify(aObserver, never()).onError(any(Throwable.class)); + verify(aObserver, never()).onCompleted(); + verify(aObserver, times(1)).onNext("hello2[5, 6, 7]"); + } + + @SuppressWarnings("unchecked") + /* mock calls don't do generics */ + @Test + public void testAggregatorsWithDifferentSizesAndTiming() { + FuncN zipr = getConcatZipr(); + /* create the aggregator which will execute the zip function when all Observables provide values */ + Aggregator a = new Aggregator(zipr); + + /* define a Observer to receive aggregated events */ + Observer aObserver = mock(Observer.class); + a.onSubscribe(aObserver); + + /* mock the Observable Observers that are 'pushing' data for us */ + ZipObserver r1 = mock(ZipObserver.class); + ZipObserver r2 = mock(ZipObserver.class); + + /* pretend we're starting up */ + a.addObserver(r1); + a.addObserver(r2); + + /* simulate the Observables pushing data into the aggregator */ + a.next(r1, "one"); + a.next(r1, "two"); + a.next(r1, "three"); + a.next(r2, "A"); + + verify(aObserver, never()).onError(any(Throwable.class)); + verify(aObserver, never()).onCompleted(); + verify(aObserver, times(1)).onNext("oneA"); + + a.next(r1, "four"); + a.complete(r1); + a.next(r2, "B"); + verify(aObserver, times(1)).onNext("twoB"); + a.next(r2, "C"); + verify(aObserver, times(1)).onNext("threeC"); + a.next(r2, "D"); + verify(aObserver, times(1)).onNext("fourD"); + a.next(r2, "E"); + verify(aObserver, never()).onNext("E"); + a.complete(r2); + + verify(aObserver, never()).onError(any(Throwable.class)); + verify(aObserver, times(1)).onCompleted(); + } + + @SuppressWarnings("unchecked") + /* mock calls don't do generics */ + @Test + public void testAggregatorError() { + FuncN zipr = getConcatZipr(); + /* create the aggregator which will execute the zip function when all Observables provide values */ + Aggregator a = new Aggregator(zipr); + + /* define a Observer to receive aggregated events */ + Observer aObserver = mock(Observer.class); + a.onSubscribe(aObserver); + + /* mock the Observable Observers that are 'pushing' data for us */ + ZipObserver r1 = mock(ZipObserver.class); + ZipObserver r2 = mock(ZipObserver.class); + + /* pretend we're starting up */ + a.addObserver(r1); + a.addObserver(r2); + + /* simulate the Observables pushing data into the aggregator */ + a.next(r1, "hello"); + a.next(r2, "world"); + + verify(aObserver, never()).onError(any(Throwable.class)); + verify(aObserver, never()).onCompleted(); + verify(aObserver, times(1)).onNext("helloworld"); + + a.error(r1, new RuntimeException("")); + a.next(r1, "hello"); + a.next(r2, "again"); + + verify(aObserver, times(1)).onError(any(Throwable.class)); + verify(aObserver, never()).onCompleted(); + // we don't want to be called again after an error + verify(aObserver, times(0)).onNext("helloagain"); + } + + @SuppressWarnings("unchecked") + /* mock calls don't do generics */ + @Test + public void testAggregatorUnsubscribe() { + FuncN zipr = getConcatZipr(); + /* create the aggregator which will execute the zip function when all Observables provide values */ + Aggregator a = new Aggregator(zipr); + + /* define a Observer to receive aggregated events */ + Observer aObserver = mock(Observer.class); + Subscription subscription = a.onSubscribe(aObserver); + + /* mock the Observable Observers that are 'pushing' data for us */ + ZipObserver r1 = mock(ZipObserver.class); + ZipObserver r2 = mock(ZipObserver.class); + + /* pretend we're starting up */ + a.addObserver(r1); + a.addObserver(r2); + + /* simulate the Observables pushing data into the aggregator */ + a.next(r1, "hello"); + a.next(r2, "world"); + + verify(aObserver, never()).onError(any(Throwable.class)); + verify(aObserver, never()).onCompleted(); + verify(aObserver, times(1)).onNext("helloworld"); + + subscription.unsubscribe(); + a.next(r1, "hello"); + a.next(r2, "again"); + + verify(aObserver, times(0)).onError(any(Throwable.class)); + verify(aObserver, never()).onCompleted(); + // we don't want to be called again after an error + verify(aObserver, times(0)).onNext("helloagain"); + } + + @SuppressWarnings("unchecked") + /* mock calls don't do generics */ + @Test + public void testAggregatorEarlyCompletion() { + FuncN zipr = getConcatZipr(); + /* create the aggregator which will execute the zip function when all Observables provide values */ + Aggregator a = new Aggregator(zipr); + + /* define a Observer to receive aggregated events */ + Observer aObserver = mock(Observer.class); + a.onSubscribe(aObserver); + + /* mock the Observable Observers that are 'pushing' data for us */ + ZipObserver r1 = mock(ZipObserver.class); + ZipObserver r2 = mock(ZipObserver.class); + + /* pretend we're starting up */ + a.addObserver(r1); + a.addObserver(r2); + + /* simulate the Observables pushing data into the aggregator */ + a.next(r1, "one"); + a.next(r1, "two"); + a.complete(r1); + a.next(r2, "A"); + + InOrder inOrder = inOrder(aObserver); + + inOrder.verify(aObserver, never()).onError(any(Throwable.class)); + inOrder.verify(aObserver, never()).onCompleted(); + inOrder.verify(aObserver, times(1)).onNext("oneA"); + + a.complete(r2); + + inOrder.verify(aObserver, never()).onError(any(Throwable.class)); + inOrder.verify(aObserver, times(1)).onCompleted(); + inOrder.verify(aObserver, never()).onNext(anyString()); + } + + @SuppressWarnings("unchecked") + /* mock calls don't do generics */ + @Test + public void testZip2Types() { + Func2 zipr = getConcatStringIntegerZipr(); + + /* define a Observer to receive aggregated events */ + Observer aObserver = mock(Observer.class); + + Observable w = Observable.create(zip(Observable.from("one", "two"), Observable.from(2, 3, 4), zipr)); + w.subscribe(aObserver); + + verify(aObserver, never()).onError(any(Throwable.class)); + verify(aObserver, times(1)).onCompleted(); + verify(aObserver, times(1)).onNext("one2"); + verify(aObserver, times(1)).onNext("two3"); + verify(aObserver, never()).onNext("4"); + } + + @SuppressWarnings("unchecked") + /* mock calls don't do generics */ + @Test + public void testZip3Types() { + Func3 zipr = getConcatStringIntegerIntArrayZipr(); + + /* define a Observer to receive aggregated events */ + Observer aObserver = mock(Observer.class); + + Observable w = Observable.create(zip(Observable.from("one", "two"), Observable.from(2), Observable.from(new int[] { 4, 5, 6 }), zipr)); + w.subscribe(aObserver); + + verify(aObserver, never()).onError(any(Throwable.class)); + verify(aObserver, times(1)).onCompleted(); + verify(aObserver, times(1)).onNext("one2[4, 5, 6]"); + verify(aObserver, never()).onNext("two"); + } + + @Test + public void testOnNextExceptionInvokesOnError() { + Func2 zipr = getDivideZipr(); + + @SuppressWarnings("unchecked") + Observer aObserver = mock(Observer.class); + + Observable w = Observable.create(zip(Observable.from(10, 20, 30), Observable.from(0, 1, 2), zipr)); + w.subscribe(aObserver); + + verify(aObserver, times(1)).onError(any(Throwable.class)); + } + + private Func2 getDivideZipr() { + Func2 zipr = new Func2() { + + @Override + public Integer call(Integer i1, Integer i2) { + return i1 / i2; + } + + }; + return zipr; + } + + private Func3 getConcat3StringsZipr() { + Func3 zipr = new Func3() { + + @Override + public String call(String a1, String a2, String a3) { + if (a1 == null) { + a1 = ""; + } + if (a2 == null) { + a2 = ""; + } + if (a3 == null) { + a3 = ""; + } + return a1 + a2 + a3; + } + + }; + return zipr; + } + + private FuncN getConcatZipr() { + FuncN zipr = new FuncN() { + + @Override + public String call(Object... args) { + String returnValue = ""; + for (Object o : args) { + if (o != null) { + returnValue += getStringValue(o); + } + } + System.out.println("returning: " + returnValue); + return returnValue; + } + + }; + return zipr; + } + + private Func2 getConcatStringIntegerZipr() { + Func2 zipr = new Func2() { + + @Override + public String call(String s, Integer i) { + return getStringValue(s) + getStringValue(i); + } + + }; + return zipr; + } + + private Func3 getConcatStringIntegerIntArrayZipr() { + Func3 zipr = new Func3() { + + @Override + public String call(String s, Integer i, int[] iArray) { + return getStringValue(s) + getStringValue(i) + getStringValue(iArray); + } + + }; + return zipr; + } + + private static String getStringValue(Object o) { + if (o == null) { + return ""; + } else { + if (o instanceof int[]) { + return Arrays.toString((int[]) o); + } else { + return String.valueOf(o); + } + } + } + + private static class TestObservable implements Observable.OnSubscribeFunc { + + Observer observer; + + @Override + public Subscription onSubscribe(Observer Observer) { + // just store the variable where it can be accessed so we can manually trigger it + this.observer = Observer; + return Subscriptions.empty(); + } + + } } diff --git a/rxjava-core/src/test/java/rx/operators/SafeObservableSubscriptionTest.java b/rxjava-core/src/test/java/rx/operators/SafeObservableSubscriptionTest.java index c5b7e6d590..a4bf9e8e8c 100644 --- a/rxjava-core/src/test/java/rx/operators/SafeObservableSubscriptionTest.java +++ b/rxjava-core/src/test/java/rx/operators/SafeObservableSubscriptionTest.java @@ -1,7 +1,21 @@ package rx.operators; import org.junit.Ignore; +import org.junit.Test; +import rx.Subscription; + +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; -@Ignore("WIP") public class SafeObservableSubscriptionTest { + + @Test + public void testWrapAfterUnsubscribe() { + SafeObservableSubscription atomicObservableSubscription = new SafeObservableSubscription(); + atomicObservableSubscription.unsubscribe(); + Subscription innerSubscription = mock(Subscription.class); + atomicObservableSubscription.wrap(innerSubscription); + verify(innerSubscription, times(1)).unsubscribe(); + } } diff --git a/rxjava-core/src/test/java/rx/operators/SynchronizedObserverTest.java b/rxjava-core/src/test/java/rx/operators/SynchronizedObserverTest.java index 5b4b301590..b9e4b2e278 100644 --- a/rxjava-core/src/test/java/rx/operators/SynchronizedObserverTest.java +++ b/rxjava-core/src/test/java/rx/operators/SynchronizedObserverTest.java @@ -1,7 +1,751 @@ package rx.operators; -import org.junit.Ignore; +import org.junit.Before; +import org.junit.Test; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import rx.Observable; +import rx.Observer; +import rx.Subscription; + +import java.util.Random; +import java.util.concurrent.*; +import java.util.concurrent.atomic.AtomicInteger; + +import static org.junit.Assert.*; +import static org.mockito.Matchers.any; +import static org.mockito.Mockito.*; -@Ignore("WIP") public class SynchronizedObserverTest { + + @Mock + Observer aObserver; + + @Before + public void before() { + MockitoAnnotations.initMocks(this); + } + + @Test + public void testSingleThreadedBasic() { + Subscription s = mock(Subscription.class); + TestSingleThreadedObservable onSubscribe = new TestSingleThreadedObservable(s, "one", "two", "three"); + Observable w = Observable.create(onSubscribe); + + SafeObservableSubscription as = new SafeObservableSubscription(s); + SynchronizedObserver aw = new SynchronizedObserver(aObserver, as); + + w.subscribe(aw); + onSubscribe.waitToFinish(); + + verify(aObserver, times(1)).onNext("one"); + verify(aObserver, times(1)).onNext("two"); + verify(aObserver, times(1)).onNext("three"); + verify(aObserver, never()).onError(any(Throwable.class)); + verify(aObserver, times(1)).onCompleted(); + // non-deterministic because unsubscribe happens after 'waitToFinish' releases + // so commenting out for now as this is not a critical thing to test here + // verify(s, times(1)).unsubscribe(); + } + + @Test + public void testMultiThreadedBasic() { + Subscription s = mock(Subscription.class); + TestMultiThreadedObservable onSubscribe = new TestMultiThreadedObservable(s, "one", "two", "three"); + Observable w = Observable.create(onSubscribe); + + SafeObservableSubscription as = new SafeObservableSubscription(s); + BusyObserver busyObserver = new BusyObserver(); + SynchronizedObserver aw = new SynchronizedObserver(busyObserver, as); + + w.subscribe(aw); + onSubscribe.waitToFinish(); + + assertEquals(3, busyObserver.onNextCount.get()); + assertFalse(busyObserver.onError); + assertTrue(busyObserver.onCompleted); + // non-deterministic because unsubscribe happens after 'waitToFinish' releases + // so commenting out for now as this is not a critical thing to test here + // verify(s, times(1)).unsubscribe(); + + // we can have concurrency ... + assertTrue(onSubscribe.maxConcurrentThreads.get() > 1); + // ... but the onNext execution should be single threaded + assertEquals(1, busyObserver.maxConcurrentThreads.get()); + } + + @Test + public void testMultiThreadedBasicWithLock() { + Subscription s = mock(Subscription.class); + TestMultiThreadedObservable onSubscribe = new TestMultiThreadedObservable(s, "one", "two", "three"); + Observable w = Observable.create(onSubscribe); + + SafeObservableSubscription as = new SafeObservableSubscription(s); + BusyObserver busyObserver = new BusyObserver(); + + Object lock = new Object(); + ExternalBusyThread externalBusyThread = new ExternalBusyThread(busyObserver, lock, 10, 100); + + SynchronizedObserver aw = new SynchronizedObserver(busyObserver, as, lock); + + externalBusyThread.start(); + + w.subscribe(aw); + onSubscribe.waitToFinish(); + + try { + externalBusyThread.join(10000); + assertFalse(externalBusyThread.isAlive()); + assertFalse(externalBusyThread.fail); + } catch (InterruptedException e) { + // ignore + } + + assertEquals(3, busyObserver.onNextCount.get()); + assertFalse(busyObserver.onError); + assertTrue(busyObserver.onCompleted); + // non-deterministic because unsubscribe happens after 'waitToFinish' releases + // so commenting out for now as this is not a critical thing to test here + // verify(s, times(1)).unsubscribe(); + + // we can have concurrency ... + assertTrue(onSubscribe.maxConcurrentThreads.get() > 1); + // ... but the onNext execution should be single threaded + assertEquals(1, busyObserver.maxConcurrentThreads.get()); + } + + @Test + public void testMultiThreadedWithNPE() { + Subscription s = mock(Subscription.class); + TestMultiThreadedObservable onSubscribe = new TestMultiThreadedObservable(s, "one", "two", "three", null); + Observable w = Observable.create(onSubscribe); + + SafeObservableSubscription as = new SafeObservableSubscription(s); + BusyObserver busyObserver = new BusyObserver(); + SynchronizedObserver aw = new SynchronizedObserver(busyObserver, as); + + w.subscribe(aw); + onSubscribe.waitToFinish(); + + System.out.println("maxConcurrentThreads: " + onSubscribe.maxConcurrentThreads.get()); + + // we can't know how many onNext calls will occur since they each run on a separate thread + // that depends on thread scheduling so 0, 1, 2 and 3 are all valid options + // assertEquals(3, busyObserver.onNextCount.get()); + assertTrue(busyObserver.onNextCount.get() < 4); + assertTrue(busyObserver.onError); + // no onCompleted because onError was invoked + assertFalse(busyObserver.onCompleted); + // non-deterministic because unsubscribe happens after 'waitToFinish' releases + // so commenting out for now as this is not a critical thing to test here + //verify(s, times(1)).unsubscribe(); + + // we can have concurrency ... + assertTrue(onSubscribe.maxConcurrentThreads.get() > 1); + // ... but the onNext execution should be single threaded + assertEquals(1, busyObserver.maxConcurrentThreads.get()); + } + + @Test + public void testMultiThreadedWithNPEAndLock() { + Subscription s = mock(Subscription.class); + TestMultiThreadedObservable onSubscribe = new TestMultiThreadedObservable(s, "one", "two", "three", null); + Observable w = Observable.create(onSubscribe); + + SafeObservableSubscription as = new SafeObservableSubscription(s); + BusyObserver busyObserver = new BusyObserver(); + + Object lock = new Object(); + ExternalBusyThread externalBusyThread = new ExternalBusyThread(busyObserver, lock, 10, 100); + + SynchronizedObserver aw = new SynchronizedObserver(busyObserver, as, lock); + + externalBusyThread.start(); + + w.subscribe(aw); + onSubscribe.waitToFinish(); + + try { + externalBusyThread.join(10000); + assertFalse(externalBusyThread.isAlive()); + assertFalse(externalBusyThread.fail); + } catch (InterruptedException e) { + // ignore + } + + System.out.println("maxConcurrentThreads: " + onSubscribe.maxConcurrentThreads.get()); + + // we can't know how many onNext calls will occur since they each run on a separate thread + // that depends on thread scheduling so 0, 1, 2 and 3 are all valid options + // assertEquals(3, busyObserver.onNextCount.get()); + assertTrue(busyObserver.onNextCount.get() < 4); + assertTrue(busyObserver.onError); + // no onCompleted because onError was invoked + assertFalse(busyObserver.onCompleted); + // non-deterministic because unsubscribe happens after 'waitToFinish' releases + // so commenting out for now as this is not a critical thing to test here + //verify(s, times(1)).unsubscribe(); + + // we can have concurrency ... + assertTrue(onSubscribe.maxConcurrentThreads.get() > 1); + // ... but the onNext execution should be single threaded + assertEquals(1, busyObserver.maxConcurrentThreads.get()); + } + + @Test + public void testMultiThreadedWithNPEinMiddle() { + Subscription s = mock(Subscription.class); + TestMultiThreadedObservable onSubscribe = new TestMultiThreadedObservable(s, "one", "two", "three", null, "four", "five", "six", "seven", "eight", "nine"); + Observable w = Observable.create(onSubscribe); + + SafeObservableSubscription as = new SafeObservableSubscription(s); + BusyObserver busyObserver = new BusyObserver(); + SynchronizedObserver aw = new SynchronizedObserver(busyObserver, as); + + w.subscribe(aw); + onSubscribe.waitToFinish(); + + System.out.println("maxConcurrentThreads: " + onSubscribe.maxConcurrentThreads.get()); + // this should not be the full number of items since the error should stop it before it completes all 9 + System.out.println("onNext count: " + busyObserver.onNextCount.get()); + assertTrue(busyObserver.onNextCount.get() < 9); + assertTrue(busyObserver.onError); + // no onCompleted because onError was invoked + assertFalse(busyObserver.onCompleted); + // non-deterministic because unsubscribe happens after 'waitToFinish' releases + // so commenting out for now as this is not a critical thing to test here + // verify(s, times(1)).unsubscribe(); + + // we can have concurrency ... + assertTrue(onSubscribe.maxConcurrentThreads.get() > 1); + // ... but the onNext execution should be single threaded + assertEquals(1, busyObserver.maxConcurrentThreads.get()); + } + + @Test + public void testMultiThreadedWithNPEinMiddleAndLock() { + Subscription s = mock(Subscription.class); + TestMultiThreadedObservable onSubscribe = new TestMultiThreadedObservable(s, "one", "two", "three", null, "four", "five", "six", "seven", "eight", "nine"); + Observable w = Observable.create(onSubscribe); + + SafeObservableSubscription as = new SafeObservableSubscription(s); + BusyObserver busyObserver = new BusyObserver(); + + Object lock = new Object(); + ExternalBusyThread externalBusyThread = new ExternalBusyThread(busyObserver, lock, 10, 100); + + SynchronizedObserver aw = new SynchronizedObserver(busyObserver, as, lock); + + externalBusyThread.start(); + + w.subscribe(aw); + onSubscribe.waitToFinish(); + + try { + externalBusyThread.join(10000); + assertFalse(externalBusyThread.isAlive()); + assertFalse(externalBusyThread.fail); + } catch (InterruptedException e) { + // ignore + } + + System.out.println("maxConcurrentThreads: " + onSubscribe.maxConcurrentThreads.get()); + // this should not be the full number of items since the error should stop it before it completes all 9 + System.out.println("onNext count: " + busyObserver.onNextCount.get()); + assertTrue(busyObserver.onNextCount.get() < 9); + assertTrue(busyObserver.onError); + // no onCompleted because onError was invoked + assertFalse(busyObserver.onCompleted); + // non-deterministic because unsubscribe happens after 'waitToFinish' releases + // so commenting out for now as this is not a critical thing to test here + // verify(s, times(1)).unsubscribe(); + + // we can have concurrency ... + assertTrue(onSubscribe.maxConcurrentThreads.get() > 1); + // ... but the onNext execution should be single threaded + assertEquals(1, busyObserver.maxConcurrentThreads.get()); + } + + /** + * A non-realistic use case that tries to expose thread-safety issues by throwing lots of out-of-order + * events on many threads. + * + * @param w + * @param tw + */ + @Test + public void runConcurrencyTest() { + ExecutorService tp = Executors.newFixedThreadPool(20); + try { + TestConcurrencyObserver tw = new TestConcurrencyObserver(); + SafeObservableSubscription s = new SafeObservableSubscription(); + SynchronizedObserver w = new SynchronizedObserver(tw, s); + + Future f1 = tp.submit(new OnNextThread(w, 12000)); + Future f2 = tp.submit(new OnNextThread(w, 5000)); + Future f3 = tp.submit(new OnNextThread(w, 75000)); + Future f4 = tp.submit(new OnNextThread(w, 13500)); + Future f5 = tp.submit(new OnNextThread(w, 22000)); + Future f6 = tp.submit(new OnNextThread(w, 15000)); + Future f7 = tp.submit(new OnNextThread(w, 7500)); + Future f8 = tp.submit(new OnNextThread(w, 23500)); + + Future f10 = tp.submit(new CompletionThread(w, TestConcurrencyObserverEvent.onCompleted, f1, f2, f3, f4)); + try { + Thread.sleep(1); + } catch (InterruptedException e) { + // ignore + } + Future f11 = tp.submit(new CompletionThread(w, TestConcurrencyObserverEvent.onCompleted, f4, f6, f7)); + Future f12 = tp.submit(new CompletionThread(w, TestConcurrencyObserverEvent.onCompleted, f4, f6, f7)); + Future f13 = tp.submit(new CompletionThread(w, TestConcurrencyObserverEvent.onCompleted, f4, f6, f7)); + Future f14 = tp.submit(new CompletionThread(w, TestConcurrencyObserverEvent.onCompleted, f4, f6, f7)); + // // the next 4 onError events should wait on same as f10 + Future f15 = tp.submit(new CompletionThread(w, TestConcurrencyObserverEvent.onError, f1, f2, f3, f4)); + Future f16 = tp.submit(new CompletionThread(w, TestConcurrencyObserverEvent.onError, f1, f2, f3, f4)); + Future f17 = tp.submit(new CompletionThread(w, TestConcurrencyObserverEvent.onError, f1, f2, f3, f4)); + Future f18 = tp.submit(new CompletionThread(w, TestConcurrencyObserverEvent.onError, f1, f2, f3, f4)); + + waitOnThreads(f1, f2, f3, f4, f5, f6, f7, f8, f10, f11, f12, f13, f14, f15, f16, f17, f18); + @SuppressWarnings("unused") + int numNextEvents = tw.assertEvents(null); // no check of type since we don't want to test barging results here, just interleaving behavior + // System.out.println("Number of events executed: " + numNextEvents); + } catch (Throwable e) { + fail("Concurrency test failed: " + e.getMessage()); + e.printStackTrace(); + } finally { + tp.shutdown(); + try { + tp.awaitTermination(5000, TimeUnit.MILLISECONDS); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + } + + private static void waitOnThreads(Future... futures) { + for (Future f : futures) { + try { + f.get(10, TimeUnit.SECONDS); + } catch (Throwable e) { + System.err.println("Failed while waiting on future."); + e.printStackTrace(); + } + } + } + + /** + * A thread that will pass data to onNext + */ + public static class OnNextThread implements Runnable { + + private final Observer Observer; + private final int numStringsToSend; + + OnNextThread(Observer Observer, int numStringsToSend) { + this.Observer = Observer; + this.numStringsToSend = numStringsToSend; + } + + @Override + public void run() { + for (int i = 0; i < numStringsToSend; i++) { + Observer.onNext("aString"); + } + } + } + + /** + * A thread that will call onError or onNext + */ + public static class CompletionThread implements Runnable { + + private final Observer Observer; + private final TestConcurrencyObserverEvent event; + private final Future[] waitOnThese; + + CompletionThread(Observer Observer, TestConcurrencyObserverEvent event, Future... waitOnThese) { + this.Observer = Observer; + this.event = event; + this.waitOnThese = waitOnThese; + } + + @Override + public void run() { + /* if we have 'waitOnThese' futures, we'll wait on them before proceeding */ + if (waitOnThese != null) { + for (Future f : waitOnThese) { + try { + f.get(); + } catch (Throwable e) { + System.err.println("Error while waiting on future in CompletionThread"); + } + } + } + + /* send the event */ + if (event == TestConcurrencyObserverEvent.onError) { + Observer.onError(new RuntimeException("mocked exception")); + } else if (event == TestConcurrencyObserverEvent.onCompleted) { + Observer.onCompleted(); + + } else { + throw new IllegalArgumentException("Expecting either onError or onCompleted"); + } + } + } + + private static enum TestConcurrencyObserverEvent { + onCompleted, onError, onNext + } + + private static class TestConcurrencyObserver implements Observer { + + /** + * used to store the order and number of events received + */ + private final LinkedBlockingQueue events = new LinkedBlockingQueue(); + private final int waitTime; + + @SuppressWarnings("unused") + public TestConcurrencyObserver(int waitTimeInNext) { + this.waitTime = waitTimeInNext; + } + + public TestConcurrencyObserver() { + this.waitTime = 0; + } + + @Override + public void onCompleted() { + events.add(TestConcurrencyObserverEvent.onCompleted); + } + + @Override + public void onError(Throwable e) { + events.add(TestConcurrencyObserverEvent.onError); + } + + @Override + public void onNext(String args) { + events.add(TestConcurrencyObserverEvent.onNext); + // do some artificial work to make the thread scheduling/timing vary + int s = 0; + for (int i = 0; i < 20; i++) { + s += s * i; + } + + if (waitTime > 0) { + try { + Thread.sleep(waitTime); + } catch (InterruptedException e) { + // ignore + } + } + } + + /** + * Assert the order of events is correct and return the number of onNext executions. + * + * @param expectedEndingEvent + * @return int count of onNext calls + * @throws IllegalStateException If order of events was invalid. + */ + public int assertEvents(TestConcurrencyObserverEvent expectedEndingEvent) throws IllegalStateException { + int nextCount = 0; + boolean finished = false; + for (TestConcurrencyObserverEvent e : events) { + if (e == TestConcurrencyObserverEvent.onNext) { + if (finished) { + // already finished, we shouldn't get this again + throw new IllegalStateException("Received onNext but we're already finished."); + } + nextCount++; + } else if (e == TestConcurrencyObserverEvent.onError) { + if (finished) { + // already finished, we shouldn't get this again + throw new IllegalStateException("Received onError but we're already finished."); + } + if (expectedEndingEvent != null && TestConcurrencyObserverEvent.onError != expectedEndingEvent) { + throw new IllegalStateException("Received onError ending event but expected " + expectedEndingEvent); + } + finished = true; + } else if (e == TestConcurrencyObserverEvent.onCompleted) { + if (finished) { + // already finished, we shouldn't get this again + throw new IllegalStateException("Received onCompleted but we're already finished."); + } + if (expectedEndingEvent != null && TestConcurrencyObserverEvent.onCompleted != expectedEndingEvent) { + throw new IllegalStateException("Received onCompleted ending event but expected " + expectedEndingEvent); + } + finished = true; + } + } + + return nextCount; + } + + } + + /** + * This spawns a single thread for the subscribe execution + */ + private static class TestSingleThreadedObservable implements Observable.OnSubscribeFunc { + + final Subscription s; + final String[] values; + private Thread t = null; + + public TestSingleThreadedObservable(final Subscription s, final String... values) { + this.s = s; + this.values = values; + + } + + public Subscription onSubscribe(final Observer observer) { + System.out.println("TestSingleThreadedObservable subscribed to ..."); + t = new Thread(new Runnable() { + + @Override + public void run() { + try { + System.out.println("running TestSingleThreadedObservable thread"); + for (String s : values) { + System.out.println("TestSingleThreadedObservable onNext: " + s); + observer.onNext(s); + } + observer.onCompleted(); + } catch (Throwable e) { + throw new RuntimeException(e); + } + } + + }); + System.out.println("starting TestSingleThreadedObservable thread"); + t.start(); + System.out.println("done starting TestSingleThreadedObservable thread"); + return s; + } + + public void waitToFinish() { + try { + t.join(); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + } + + } + + /** + * This spawns a thread for the subscription, then a separate thread for each onNext call. + */ + private static class TestMultiThreadedObservable implements Observable.OnSubscribeFunc { + + final Subscription s; + final String[] values; + Thread t = null; + AtomicInteger threadsRunning = new AtomicInteger(); + AtomicInteger maxConcurrentThreads = new AtomicInteger(); + ExecutorService threadPool; + + public TestMultiThreadedObservable(Subscription s, String... values) { + this.s = s; + this.values = values; + this.threadPool = Executors.newCachedThreadPool(); + } + + @Override + public Subscription onSubscribe(final Observer observer) { + System.out.println("TestMultiThreadedObservable subscribed to ..."); + t = new Thread(new Runnable() { + + @Override + public void run() { + try { + System.out.println("running TestMultiThreadedObservable thread"); + for (final String s : values) { + threadPool.execute(new Runnable() { + + @Override + public void run() { + threadsRunning.incrementAndGet(); + try { + // perform onNext call + System.out.println("TestMultiThreadedObservable onNext: " + s); + if (s == null) { + // force an error + throw new NullPointerException(); + } + observer.onNext(s); + // capture 'maxThreads' + int concurrentThreads = threadsRunning.get(); + int maxThreads = maxConcurrentThreads.get(); + if (concurrentThreads > maxThreads) { + maxConcurrentThreads.compareAndSet(maxThreads, concurrentThreads); + } + } catch (Throwable e) { + observer.onError(e); + } finally { + threadsRunning.decrementAndGet(); + } + } + }); + } + // we are done spawning threads + threadPool.shutdown(); + } catch (Throwable e) { + throw new RuntimeException(e); + } + + // wait until all threads are done, then mark it as COMPLETED + try { + // wait for all the threads to finish + threadPool.awaitTermination(2, TimeUnit.SECONDS); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + observer.onCompleted(); + } + }); + System.out.println("starting TestMultiThreadedObservable thread"); + t.start(); + System.out.println("done starting TestMultiThreadedObservable thread"); + return s; + } + + public void waitToFinish() { + try { + t.join(); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + } + } + + private static class BusyObserver implements Observer { + volatile boolean onCompleted = false; + volatile boolean onError = false; + AtomicInteger onNextCount = new AtomicInteger(); + AtomicInteger threadsRunning = new AtomicInteger(); + AtomicInteger maxConcurrentThreads = new AtomicInteger(); + + @Override + public void onCompleted() { + threadsRunning.incrementAndGet(); + + System.out.println(">>> BusyObserver received onCompleted"); + onCompleted = true; + + int concurrentThreads = threadsRunning.get(); + int maxThreads = maxConcurrentThreads.get(); + if (concurrentThreads > maxThreads) { + maxConcurrentThreads.compareAndSet(maxThreads, concurrentThreads); + } + threadsRunning.decrementAndGet(); + } + + @Override + public void onError(Throwable e) { + threadsRunning.incrementAndGet(); + + System.out.println(">>> BusyObserver received onError: " + e.getMessage()); + onError = true; + + int concurrentThreads = threadsRunning.get(); + int maxThreads = maxConcurrentThreads.get(); + if (concurrentThreads > maxThreads) { + maxConcurrentThreads.compareAndSet(maxThreads, concurrentThreads); + } + threadsRunning.decrementAndGet(); + } + + @Override + public void onNext(String args) { + threadsRunning.incrementAndGet(); + try { + onNextCount.incrementAndGet(); + System.out.println(">>> BusyObserver received onNext: " + args); + try { + // simulate doing something computational + Thread.sleep(200); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } finally { + // capture 'maxThreads' + int concurrentThreads = threadsRunning.get(); + int maxThreads = maxConcurrentThreads.get(); + if (concurrentThreads > maxThreads) { + maxConcurrentThreads.compareAndSet(maxThreads, concurrentThreads); + } + threadsRunning.decrementAndGet(); + } + } + + } + + private static class ExternalBusyThread extends Thread { + + private BusyObserver observer; + private Object lock; + private int lockTimes; + private int waitTime; + public volatile boolean fail; + + public ExternalBusyThread(BusyObserver observer, Object lock, int lockTimes, int waitTime) { + this.observer = observer; + this.lock = lock; + this.lockTimes = lockTimes; + this.waitTime = waitTime; + this.fail = false; + } + + @Override + public void run() { + Random r = new Random(); + for (int i = 0; i < lockTimes; i++) { + synchronized (lock) { + int oldOnNextCount = observer.onNextCount.get(); + boolean oldOnCompleted = observer.onCompleted; + boolean oldOnError = observer.onError; + try { + Thread.sleep(r.nextInt(waitTime)); + } catch (InterruptedException e) { + // ignore + } + // Since we own the lock, onNextCount, onCompleted and + // onError must not be changed. + int newOnNextCount = observer.onNextCount.get(); + boolean newOnCompleted = observer.onCompleted; + boolean newOnError = observer.onError; + if (oldOnNextCount != newOnNextCount) { + System.out.println(">>> ExternalBusyThread received different onNextCount: " + + oldOnNextCount + + " -> " + + newOnNextCount); + fail = true; + break; + } + if (oldOnCompleted != newOnCompleted) { + System.out.println(">>> ExternalBusyThread received different onCompleted: " + + oldOnCompleted + + " -> " + + newOnCompleted); + fail = true; + break; + } + if (oldOnError != newOnError) { + System.out.println(">>> ExternalBusyThread received different onError: " + + oldOnError + + " -> " + + newOnError); + fail = true; + break; + } + } + } + } + + } } diff --git a/rxjava-core/src/test/java/rx/plugins/RxJavaPluginsTest.java b/rxjava-core/src/test/java/rx/plugins/RxJavaPluginsTest.java index 1def236246..3ea17bf152 100644 --- a/rxjava-core/src/test/java/rx/plugins/RxJavaPluginsTest.java +++ b/rxjava-core/src/test/java/rx/plugins/RxJavaPluginsTest.java @@ -1,7 +1,77 @@ package rx.plugins; -import org.junit.Ignore; +import org.junit.Test; + +import static org.junit.Assert.assertTrue; -@Ignore("WIP") public class RxJavaPluginsTest { + + @Test + public void testErrorHandlerDefaultImpl() { + RxJavaErrorHandler impl = new RxJavaPlugins().getErrorHandler(); + assertTrue(impl instanceof RxJavaErrorHandlerDefault); + } + + @Test + public void testErrorHandlerViaRegisterMethod() { + RxJavaPlugins p = new RxJavaPlugins(); + p.registerErrorHandler(new RxJavaErrorHandlerTestImpl()); + RxJavaErrorHandler impl = p.getErrorHandler(); + assertTrue(impl instanceof RxJavaErrorHandlerTestImpl); + } + + @Test + public void testErrorHandlerViaProperty() { + try { + RxJavaPlugins p = new RxJavaPlugins(); + String fullClass = getFullClassNameForTestClass(RxJavaErrorHandlerTestImpl.class); + System.setProperty("rxjava.plugin.RxJavaErrorHandler.implementation", fullClass); + RxJavaErrorHandler impl = p.getErrorHandler(); + assertTrue(impl instanceof RxJavaErrorHandlerTestImpl); + } finally { + System.clearProperty("rxjava.plugin.RxJavaErrorHandler.implementation"); + } + } + + // inside test so it is stripped from Javadocs + public static class RxJavaErrorHandlerTestImpl extends RxJavaErrorHandler { + // just use defaults + } + + @Test + public void testObservableExecutionHookDefaultImpl() { + RxJavaPlugins p = new RxJavaPlugins(); + RxJavaObservableExecutionHook impl = p.getObservableExecutionHook(); + assertTrue(impl instanceof RxJavaObservableExecutionHookDefault); + } + + @Test + public void testObservableExecutionHookViaRegisterMethod() { + RxJavaPlugins p = new RxJavaPlugins(); + p.registerObservableExecutionHook(new RxJavaObservableExecutionHookTestImpl()); + RxJavaObservableExecutionHook impl = p.getObservableExecutionHook(); + assertTrue(impl instanceof RxJavaObservableExecutionHookTestImpl); + } + + @Test + public void testObservableExecutionHookViaProperty() { + try { + RxJavaPlugins p = new RxJavaPlugins(); + String fullClass = getFullClassNameForTestClass(RxJavaObservableExecutionHookTestImpl.class); + System.setProperty("rxjava.plugin.RxJavaObservableExecutionHook.implementation", fullClass); + RxJavaObservableExecutionHook impl = p.getObservableExecutionHook(); + assertTrue(impl instanceof RxJavaObservableExecutionHookTestImpl); + } finally { + System.clearProperty("rxjava.plugin.RxJavaObservableExecutionHook.implementation"); + } + } + + // inside test so it is stripped from Javadocs + public static class RxJavaObservableExecutionHookTestImpl extends RxJavaObservableExecutionHook { + // just use defaults + } + + private static String getFullClassNameForTestClass(Class cls) { + return RxJavaPlugins.class.getPackage().getName() + "." + RxJavaPluginsTest.class.getSimpleName() + "$" + cls.getSimpleName(); + } } diff --git a/rxjava-core/src/test/java/rx/subjects/AsyncSubjectTest.java b/rxjava-core/src/test/java/rx/subjects/AsyncSubjectTest.java index bfe0aa0bb0..fb5220640b 100644 --- a/rxjava-core/src/test/java/rx/subjects/AsyncSubjectTest.java +++ b/rxjava-core/src/test/java/rx/subjects/AsyncSubjectTest.java @@ -1,7 +1,135 @@ package rx.subjects; -import org.junit.Ignore; +import org.junit.Test; +import org.mockito.Mockito; +import rx.Observer; +import rx.Subscription; +import rx.util.functions.Action1; +import rx.util.functions.Func0; + +import static org.mockito.Matchers.any; +import static org.mockito.Matchers.anyString; +import static org.mockito.Mockito.*; -@Ignore("WIP") public class AsyncSubjectTest { + + + private final Throwable testException = new Throwable(); + + @Test + public void testNeverCompleted() { + AsyncSubject subject = AsyncSubject.create(); + + @SuppressWarnings("unchecked") + Observer aObserver = mock(Observer.class); + subject.subscribe(aObserver); + + subject.onNext("one"); + subject.onNext("two"); + subject.onNext("three"); + + assertNeverCompletedObserver(aObserver); + } + + private void assertNeverCompletedObserver(Observer aObserver) { + verify(aObserver, Mockito.never()).onNext(anyString()); + verify(aObserver, Mockito.never()).onError(testException); + verify(aObserver, Mockito.never()).onCompleted(); + } + + @Test + public void testCompleted() { + AsyncSubject subject = AsyncSubject.create(); + + @SuppressWarnings("unchecked") + Observer aObserver = mock(Observer.class); + subject.subscribe(aObserver); + + subject.onNext("one"); + subject.onNext("two"); + subject.onNext("three"); + subject.onCompleted(); + + assertCompletedObserver(aObserver); + } + + private void assertCompletedObserver(Observer aObserver) { + verify(aObserver, times(1)).onNext("three"); + verify(aObserver, Mockito.never()).onError(any(Throwable.class)); + verify(aObserver, times(1)).onCompleted(); + } + + @Test + public void testError() { + AsyncSubject subject = AsyncSubject.create(); + + @SuppressWarnings("unchecked") + Observer aObserver = mock(Observer.class); + subject.subscribe(aObserver); + + subject.onNext("one"); + subject.onNext("two"); + subject.onNext("three"); + subject.onError(testException); + subject.onNext("four"); + subject.onError(new Throwable()); + subject.onCompleted(); + + assertErrorObserver(aObserver); + } + + private void assertErrorObserver(Observer aObserver) { + verify(aObserver, Mockito.never()).onNext(anyString()); + verify(aObserver, times(1)).onError(testException); + verify(aObserver, Mockito.never()).onCompleted(); + } + + @Test + public void testUnsubscribeBeforeCompleted() { + AsyncSubject subject = AsyncSubject.create(); + + @SuppressWarnings("unchecked") + Observer aObserver = mock(Observer.class); + Subscription subscription = subject.subscribe(aObserver); + + subject.onNext("one"); + subject.onNext("two"); + + subscription.unsubscribe(); + assertNoOnNextEventsReceived(aObserver); + + subject.onNext("three"); + subject.onCompleted(); + + assertNoOnNextEventsReceived(aObserver); + } + + private void assertNoOnNextEventsReceived(Observer aObserver) { + verify(aObserver, Mockito.never()).onNext(anyString()); + verify(aObserver, Mockito.never()).onError(any(Throwable.class)); + verify(aObserver, Mockito.never()).onCompleted(); + } + + @Test + public void testUnsubscribe() { + UnsubscribeTester.test( + new Func0>() { + @Override + public AsyncSubject call() { + return AsyncSubject.create(); + } + }, new Action1>() { + @Override + public void call(AsyncSubject DefaultSubject) { + DefaultSubject.onCompleted(); + } + }, new Action1>() { + @Override + public void call(AsyncSubject DefaultSubject) { + DefaultSubject.onError(new Throwable()); + } + }, + null + ); + } } diff --git a/rxjava-core/src/test/java/rx/subjects/BehaviorSubjectTest.java b/rxjava-core/src/test/java/rx/subjects/BehaviorSubjectTest.java index ffee087158..eae3ffbc06 100644 --- a/rxjava-core/src/test/java/rx/subjects/BehaviorSubjectTest.java +++ b/rxjava-core/src/test/java/rx/subjects/BehaviorSubjectTest.java @@ -1,7 +1,135 @@ package rx.subjects; -import org.junit.Ignore; +import org.junit.Test; +import org.mockito.Mockito; +import rx.Observer; +import rx.util.functions.Action1; +import rx.util.functions.Func0; + +import static org.mockito.Matchers.any; +import static org.mockito.Mockito.*; -@Ignore("WIP") public class BehaviorSubjectTest { + + + private final Throwable testException = new Throwable(); + + @Test + public void testThatObserverReceivesDefaultValueIfNothingWasPublished() { + BehaviorSubject subject = BehaviorSubject.createWithDefaultValue("default"); + + @SuppressWarnings("unchecked") + Observer aObserver = mock(Observer.class); + subject.subscribe(aObserver); + + subject.onNext("one"); + subject.onNext("two"); + subject.onNext("three"); + + assertReceivedAllEvents(aObserver); + } + + private void assertReceivedAllEvents(Observer aObserver) { + verify(aObserver, times(1)).onNext("default"); + verify(aObserver, times(1)).onNext("one"); + verify(aObserver, times(1)).onNext("two"); + verify(aObserver, times(1)).onNext("three"); + verify(aObserver, Mockito.never()).onError(testException); + verify(aObserver, Mockito.never()).onCompleted(); + } + + @Test + public void testThatObserverDoesNotReceiveDefaultValueIfSomethingWasPublished() { + BehaviorSubject subject = BehaviorSubject.createWithDefaultValue("default"); + + subject.onNext("one"); + + @SuppressWarnings("unchecked") + Observer aObserver = mock(Observer.class); + subject.subscribe(aObserver); + + subject.onNext("two"); + subject.onNext("three"); + + assertDidNotReceiveTheDefaultValue(aObserver); + } + + private void assertDidNotReceiveTheDefaultValue(Observer aObserver) { + verify(aObserver, Mockito.never()).onNext("default"); + verify(aObserver, times(1)).onNext("one"); + verify(aObserver, times(1)).onNext("two"); + verify(aObserver, times(1)).onNext("three"); + verify(aObserver, Mockito.never()).onError(testException); + verify(aObserver, Mockito.never()).onCompleted(); + } + + @Test + public void testCompleted() { + BehaviorSubject subject = BehaviorSubject.createWithDefaultValue("default"); + + @SuppressWarnings("unchecked") + Observer aObserver = mock(Observer.class); + subject.subscribe(aObserver); + + subject.onNext("one"); + subject.onCompleted(); + + assertCompletedObserver(aObserver); + } + + private void assertCompletedObserver(Observer aObserver) { + verify(aObserver, times(1)).onNext("default"); + verify(aObserver, times(1)).onNext("one"); + verify(aObserver, Mockito.never()).onError(any(Throwable.class)); + verify(aObserver, times(1)).onCompleted(); + } + + @Test + public void testCompletedAfterError() { + BehaviorSubject subject = BehaviorSubject.createWithDefaultValue("default"); + + @SuppressWarnings("unchecked") + Observer aObserver = mock(Observer.class); + subject.subscribe(aObserver); + + subject.onNext("one"); + subject.onError(testException); + subject.onNext("two"); + subject.onCompleted(); + + assertErrorObserver(aObserver); + } + + private void assertErrorObserver(Observer aObserver) { + verify(aObserver, times(1)).onNext("default"); + verify(aObserver, times(1)).onNext("one"); + verify(aObserver, times(1)).onError(testException); + } + + @Test + public void testUnsubscribe() { + UnsubscribeTester.test( + new Func0>() { + @Override + public BehaviorSubject call() { + return BehaviorSubject.createWithDefaultValue("default"); + } + }, new Action1>() { + @Override + public void call(BehaviorSubject DefaultSubject) { + DefaultSubject.onCompleted(); + } + }, new Action1>() { + @Override + public void call(BehaviorSubject DefaultSubject) { + DefaultSubject.onError(new Throwable()); + } + }, new Action1>() { + @Override + public void call(BehaviorSubject DefaultSubject) { + DefaultSubject.onNext("one"); + } + } + ); + } } diff --git a/rxjava-core/src/test/java/rx/subjects/PublishSubjectTest.java b/rxjava-core/src/test/java/rx/subjects/PublishSubjectTest.java index 25cebbf510..da6abf7c44 100644 --- a/rxjava-core/src/test/java/rx/subjects/PublishSubjectTest.java +++ b/rxjava-core/src/test/java/rx/subjects/PublishSubjectTest.java @@ -1,7 +1,364 @@ package rx.subjects; -import org.junit.Ignore; +import junit.framework.Assert; +import org.junit.Test; +import org.mockito.InOrder; +import org.mockito.Mockito; +import rx.Notification; +import rx.Observable; +import rx.Observer; +import rx.Subscription; +import rx.util.functions.Action1; +import rx.util.functions.Func0; +import rx.util.functions.Func1; + +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.atomic.AtomicReference; + +import static org.junit.Assert.assertEquals; +import static org.mockito.Matchers.any; +import static org.mockito.Mockito.*; -@Ignore("WIP") public class PublishSubjectTest { + + @Test + public void test() { + PublishSubject subject = PublishSubject.create(); + final AtomicReference>> actualRef = new AtomicReference>>(); + + Observable>> wNotificationsList = subject.materialize().toList(); + wNotificationsList.subscribe(new Action1>>() { + @Override + public void call(List> actual) { + actualRef.set(actual); + } + }); + + Subscription sub = Observable.create(new Observable.OnSubscribeFunc() { + @Override + public Subscription onSubscribe(final Observer observer) { + final AtomicBoolean stop = new AtomicBoolean(false); + new Thread() { + @Override + public void run() { + int i = 1; + while (!stop.get()) { + observer.onNext(i++); + } + observer.onCompleted(); + } + }.start(); + return new Subscription() { + @Override + public void unsubscribe() { + stop.set(true); + } + }; + } + }).subscribe(subject); + // the subject has received an onComplete from the first subscribe because + // it is synchronous and the next subscribe won't do anything. + Observable.from(-1, -2, -3).subscribe(subject); + + List> expected = new ArrayList>(); + expected.add(new Notification(-1)); + expected.add(new Notification(-2)); + expected.add(new Notification(-3)); + expected.add(new Notification()); + Assert.assertTrue(actualRef.get().containsAll(expected)); + + sub.unsubscribe(); + } + + private final Throwable testException = new Throwable(); + + @Test + public void testCompleted() { + PublishSubject subject = PublishSubject.create(); + + @SuppressWarnings("unchecked") + Observer aObserver = mock(Observer.class); + subject.subscribe(aObserver); + + subject.onNext("one"); + subject.onNext("two"); + subject.onNext("three"); + subject.onCompleted(); + + @SuppressWarnings("unchecked") + Observer anotherObserver = mock(Observer.class); + subject.subscribe(anotherObserver); + + subject.onNext("four"); + subject.onCompleted(); + subject.onError(new Throwable()); + + assertCompletedObserver(aObserver); + // todo bug? assertNeverObserver(anotherObserver); + } + + private void assertCompletedObserver(Observer aObserver) { + verify(aObserver, times(1)).onNext("one"); + verify(aObserver, times(1)).onNext("two"); + verify(aObserver, times(1)).onNext("three"); + verify(aObserver, Mockito.never()).onError(any(Throwable.class)); + verify(aObserver, times(1)).onCompleted(); + } + + @Test + public void testError() { + PublishSubject subject = PublishSubject.create(); + + @SuppressWarnings("unchecked") + Observer aObserver = mock(Observer.class); + subject.subscribe(aObserver); + + subject.onNext("one"); + subject.onNext("two"); + subject.onNext("three"); + subject.onError(testException); + + @SuppressWarnings("unchecked") + Observer anotherObserver = mock(Observer.class); + subject.subscribe(anotherObserver); + + subject.onNext("four"); + subject.onError(new Throwable()); + subject.onCompleted(); + + assertErrorObserver(aObserver); + // todo bug? assertNeverObserver(anotherObserver); + } + + private void assertErrorObserver(Observer aObserver) { + verify(aObserver, times(1)).onNext("one"); + verify(aObserver, times(1)).onNext("two"); + verify(aObserver, times(1)).onNext("three"); + verify(aObserver, times(1)).onError(testException); + verify(aObserver, Mockito.never()).onCompleted(); + } + + @Test + public void testSubscribeMidSequence() { + PublishSubject subject = PublishSubject.create(); + + @SuppressWarnings("unchecked") + Observer aObserver = mock(Observer.class); + subject.subscribe(aObserver); + + subject.onNext("one"); + subject.onNext("two"); + + assertObservedUntilTwo(aObserver); + + @SuppressWarnings("unchecked") + Observer anotherObserver = mock(Observer.class); + subject.subscribe(anotherObserver); + + subject.onNext("three"); + subject.onCompleted(); + + assertCompletedObserver(aObserver); + assertCompletedStartingWithThreeObserver(anotherObserver); + } + + private void assertCompletedStartingWithThreeObserver(Observer aObserver) { + verify(aObserver, Mockito.never()).onNext("one"); + verify(aObserver, Mockito.never()).onNext("two"); + verify(aObserver, times(1)).onNext("three"); + verify(aObserver, Mockito.never()).onError(any(Throwable.class)); + verify(aObserver, times(1)).onCompleted(); + } + + @Test + public void testUnsubscribeFirstObserver() { + PublishSubject subject = PublishSubject.create(); + + @SuppressWarnings("unchecked") + Observer aObserver = mock(Observer.class); + Subscription subscription = subject.subscribe(aObserver); + + subject.onNext("one"); + subject.onNext("two"); + + subscription.unsubscribe(); + assertObservedUntilTwo(aObserver); + + @SuppressWarnings("unchecked") + Observer anotherObserver = mock(Observer.class); + subject.subscribe(anotherObserver); + + subject.onNext("three"); + subject.onCompleted(); + + assertObservedUntilTwo(aObserver); + assertCompletedStartingWithThreeObserver(anotherObserver); + } + + private void assertObservedUntilTwo(Observer aObserver) { + verify(aObserver, times(1)).onNext("one"); + verify(aObserver, times(1)).onNext("two"); + verify(aObserver, Mockito.never()).onNext("three"); + verify(aObserver, Mockito.never()).onError(any(Throwable.class)); + verify(aObserver, Mockito.never()).onCompleted(); + } + + @Test + public void testUnsubscribe() { + UnsubscribeTester.test( + new Func0>() { + @Override + public PublishSubject call() { + return PublishSubject.create(); + } + }, new Action1>() { + @Override + public void call(PublishSubject DefaultSubject) { + DefaultSubject.onCompleted(); + } + }, new Action1>() { + @Override + public void call(PublishSubject DefaultSubject) { + DefaultSubject.onError(new Throwable()); + } + }, new Action1>() { + @Override + public void call(PublishSubject DefaultSubject) { + DefaultSubject.onNext("one"); + } + } + ); + } + + @Test + public void testNestedSubscribe() { + final PublishSubject s = PublishSubject.create(); + + final AtomicInteger countParent = new AtomicInteger(); + final AtomicInteger countChildren = new AtomicInteger(); + final AtomicInteger countTotal = new AtomicInteger(); + + final ArrayList list = new ArrayList(); + + s.mapMany(new Func1>() { + + @Override + public Observable call(final Integer v) { + countParent.incrementAndGet(); + + // then subscribe to subject again (it will not receive the previous value) + return s.map(new Func1() { + + @Override + public String call(Integer v2) { + countChildren.incrementAndGet(); + return "Parent: " + v + " Child: " + v2; + } + + }); + } + + }).subscribe(new Action1() { + + @Override + public void call(String v) { + countTotal.incrementAndGet(); + list.add(v); + } + + }); + + for (int i = 0; i < 10; i++) { + s.onNext(i); + } + s.onCompleted(); + + // System.out.println("countParent: " + countParent.get()); + // System.out.println("countChildren: " + countChildren.get()); + // System.out.println("countTotal: " + countTotal.get()); + + // 9+8+7+6+5+4+3+2+1+0 == 45 + assertEquals(45, list.size()); + } + + /** + * Should be able to unsubscribe all Observers, have it stop emitting, then subscribe new ones and it start emitting again. + */ + @Test + public void testReSubscribe() { + final PublishSubject ps = PublishSubject.create(); + + Observer o1 = mock(Observer.class); + Subscription s1 = ps.subscribe(o1); + + // emit + ps.onNext(1); + + // validate we got it + InOrder inOrder1 = inOrder(o1); + inOrder1.verify(o1, times(1)).onNext(1); + inOrder1.verifyNoMoreInteractions(); + + // unsubscribe + s1.unsubscribe(); + + // emit again but nothing will be there to receive it + ps.onNext(2); + + Observer o2 = mock(Observer.class); + Subscription s2 = ps.subscribe(o2); + + // emit + ps.onNext(3); + + // validate we got it + InOrder inOrder2 = inOrder(o2); + inOrder2.verify(o2, times(1)).onNext(3); + inOrder2.verifyNoMoreInteractions(); + + s2.unsubscribe(); + } + + /** + * Even if subject received an onError/onCompleted, new subscriptions should be able to restart it. + */ + @Test + public void testReSubscribeAfterTerminalState() { + final PublishSubject ps = PublishSubject.create(); + + Observer o1 = mock(Observer.class); + Subscription s1 = ps.subscribe(o1); + + // emit + ps.onNext(1); + + // validate we got it + InOrder inOrder1 = inOrder(o1); + inOrder1.verify(o1, times(1)).onNext(1); + inOrder1.verifyNoMoreInteractions(); + + // unsubscribe + s1.unsubscribe(); + + ps.onCompleted(); + + // emit again but nothing will be there to receive it + ps.onNext(2); + + Observer o2 = mock(Observer.class); + Subscription s2 = ps.subscribe(o2); + + // emit + ps.onNext(3); + + // validate we got it + InOrder inOrder2 = inOrder(o2); + inOrder2.verify(o2, times(1)).onNext(3); + inOrder2.verifyNoMoreInteractions(); + + s2.unsubscribe(); + } } diff --git a/rxjava-core/src/test/java/rx/subjects/ReplaySubjectTest.java b/rxjava-core/src/test/java/rx/subjects/ReplaySubjectTest.java index 1e722e5e5e..dc0298a7e3 100644 --- a/rxjava-core/src/test/java/rx/subjects/ReplaySubjectTest.java +++ b/rxjava-core/src/test/java/rx/subjects/ReplaySubjectTest.java @@ -1,7 +1,169 @@ package rx.subjects; -import org.junit.Ignore; +import org.junit.Test; +import org.mockito.InOrder; +import org.mockito.Mockito; +import rx.Observer; +import rx.Subscription; +import rx.util.functions.Action1; +import rx.util.functions.Func0; + +import static org.mockito.Matchers.any; +import static org.mockito.Mockito.*; -@Ignore("WIP") public class ReplaySubjectTest { + + private final Throwable testException = new Throwable(); + + @SuppressWarnings("unchecked") + @Test + public void testCompleted() { + ReplaySubject subject = ReplaySubject.create(); + + Observer o1 = mock(Observer.class); + subject.subscribe(o1); + + subject.onNext("one"); + subject.onNext("two"); + subject.onNext("three"); + subject.onCompleted(); + + subject.onNext("four"); + subject.onCompleted(); + subject.onError(new Throwable()); + + assertCompletedObserver(o1); + + // assert that subscribing a 2nd time gets the same data + Observer o2 = mock(Observer.class); + subject.subscribe(o2); + assertCompletedObserver(o2); + } + + private void assertCompletedObserver(Observer aObserver) { + InOrder inOrder = inOrder(aObserver); + + inOrder.verify(aObserver, times(1)).onNext("one"); + inOrder.verify(aObserver, times(1)).onNext("two"); + inOrder.verify(aObserver, times(1)).onNext("three"); + inOrder.verify(aObserver, Mockito.never()).onError(any(Throwable.class)); + inOrder.verify(aObserver, times(1)).onCompleted(); + inOrder.verifyNoMoreInteractions(); + } + + @SuppressWarnings("unchecked") + @Test + public void testError() { + ReplaySubject subject = ReplaySubject.create(); + + Observer aObserver = mock(Observer.class); + subject.subscribe(aObserver); + + subject.onNext("one"); + subject.onNext("two"); + subject.onNext("three"); + subject.onError(testException); + + subject.onNext("four"); + subject.onError(new Throwable()); + subject.onCompleted(); + + assertErrorObserver(aObserver); + + aObserver = mock(Observer.class); + subject.subscribe(aObserver); + assertErrorObserver(aObserver); + } + + private void assertErrorObserver(Observer aObserver) { + verify(aObserver, times(1)).onNext("one"); + verify(aObserver, times(1)).onNext("two"); + verify(aObserver, times(1)).onNext("three"); + verify(aObserver, times(1)).onError(testException); + verify(aObserver, Mockito.never()).onCompleted(); + } + + @SuppressWarnings("unchecked") + @Test + public void testSubscribeMidSequence() { + ReplaySubject subject = ReplaySubject.create(); + + Observer aObserver = mock(Observer.class); + subject.subscribe(aObserver); + + subject.onNext("one"); + subject.onNext("two"); + + assertObservedUntilTwo(aObserver); + + Observer anotherObserver = mock(Observer.class); + subject.subscribe(anotherObserver); + assertObservedUntilTwo(anotherObserver); + + subject.onNext("three"); + subject.onCompleted(); + + assertCompletedObserver(aObserver); + assertCompletedObserver(anotherObserver); + } + + @SuppressWarnings("unchecked") + @Test + public void testUnsubscribeFirstObserver() { + ReplaySubject subject = ReplaySubject.create(); + + Observer aObserver = mock(Observer.class); + Subscription subscription = subject.subscribe(aObserver); + + subject.onNext("one"); + subject.onNext("two"); + + subscription.unsubscribe(); + assertObservedUntilTwo(aObserver); + + Observer anotherObserver = mock(Observer.class); + subject.subscribe(anotherObserver); + assertObservedUntilTwo(anotherObserver); + + subject.onNext("three"); + subject.onCompleted(); + + assertObservedUntilTwo(aObserver); + assertCompletedObserver(anotherObserver); + } + + private void assertObservedUntilTwo(Observer aObserver) { + verify(aObserver, times(1)).onNext("one"); + verify(aObserver, times(1)).onNext("two"); + verify(aObserver, Mockito.never()).onNext("three"); + verify(aObserver, Mockito.never()).onError(any(Throwable.class)); + verify(aObserver, Mockito.never()).onCompleted(); + } + + @Test + public void testUnsubscribe() { + UnsubscribeTester.test( + new Func0>() { + @Override + public ReplaySubject call() { + return ReplaySubject.create(); + } + }, new Action1>() { + @Override + public void call(ReplaySubject repeatSubject) { + repeatSubject.onCompleted(); + } + }, new Action1>() { + @Override + public void call(ReplaySubject repeatSubject) { + repeatSubject.onError(new Throwable()); + } + }, new Action1>() { + @Override + public void call(ReplaySubject repeatSubject) { + repeatSubject.onNext("one"); + } + } + ); + } } diff --git a/rxjava-core/src/test/java/rx/subscriptions/CompositeSubscriptionTest.java b/rxjava-core/src/test/java/rx/subscriptions/CompositeSubscriptionTest.java index 43830564ce..3bb8b718a0 100644 --- a/rxjava-core/src/test/java/rx/subscriptions/CompositeSubscriptionTest.java +++ b/rxjava-core/src/test/java/rx/subscriptions/CompositeSubscriptionTest.java @@ -1,7 +1,70 @@ package rx.subscriptions; -import org.junit.Ignore; +import org.junit.Test; +import rx.Subscription; +import rx.util.CompositeException; + +import java.util.concurrent.atomic.AtomicInteger; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.fail; -@Ignore("WIP") public class CompositeSubscriptionTest { + + @Test + public void testSuccess() { + final AtomicInteger counter = new AtomicInteger(); + CompositeSubscription s = new CompositeSubscription(); + s.add(new Subscription() { + + @Override + public void unsubscribe() { + counter.incrementAndGet(); + } + }); + + s.add(new Subscription() { + + @Override + public void unsubscribe() { + counter.incrementAndGet(); + } + }); + + s.unsubscribe(); + + assertEquals(2, counter.get()); + } + + @Test + public void testException() { + final AtomicInteger counter = new AtomicInteger(); + CompositeSubscription s = new CompositeSubscription(); + s.add(new Subscription() { + + @Override + public void unsubscribe() { + throw new RuntimeException("failed on first one"); + } + }); + + s.add(new Subscription() { + + @Override + public void unsubscribe() { + counter.incrementAndGet(); + } + }); + + try { + s.unsubscribe(); + fail("Expecting an exception"); + } catch (CompositeException e) { + // we expect this + assertEquals(1, e.getExceptions().size()); + } + + // we should still have unsubscribed to the second one + assertEquals(1, counter.get()); + } } diff --git a/rxjava-core/src/test/java/rx/subscriptions/SubscriptionsTest.java b/rxjava-core/src/test/java/rx/subscriptions/SubscriptionsTest.java index 17bb5b4619..5ac0242a95 100644 --- a/rxjava-core/src/test/java/rx/subscriptions/SubscriptionsTest.java +++ b/rxjava-core/src/test/java/rx/subscriptions/SubscriptionsTest.java @@ -1,7 +1,20 @@ package rx.subscriptions; -import org.junit.Ignore; +import org.junit.Test; +import rx.Subscription; +import rx.util.functions.Action0; + +import static org.mockito.Mockito.*; +import static rx.subscriptions.Subscriptions.create; -@Ignore("WIP") public class SubscriptionsTest { + + @Test + public void testUnsubscribeOnlyOnce() { + Action0 unsubscribe = mock(Action0.class); + Subscription subscription = create(unsubscribe); + subscription.unsubscribe(); + subscription.unsubscribe(); + verify(unsubscribe, times(1)).call(); + } } diff --git a/rxjava-core/src/test/java/rx/test/OperatorTester.java b/rxjava-core/src/test/java/rx/test/OperatorTester.java new file mode 100644 index 0000000000..ab64251583 --- /dev/null +++ b/rxjava-core/src/test/java/rx/test/OperatorTester.java @@ -0,0 +1,94 @@ +/** + * Copyright 2013 Netflix, Inc. + * + * 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 rx.test; + +import rx.Scheduler; +import rx.Subscription; +import rx.util.functions.Action0; +import rx.util.functions.Func2; + +import java.util.concurrent.TimeUnit; + +/** + * Common utility functions for testing operator implementations. + */ +public class OperatorTester { + /* + * This is purposefully package-only so it does not leak into the public API outside of this package. + * + * This package is implementation details and not part of the Javadocs and thus can change without breaking backwards compatibility. + * + * benjchristensen => I'm procrastinating the decision of where and how these types of classes (see rx.subjects.UnsubscribeTester) should exist. + * If they are only for internal implementations then I don't want them as part of the API. + * If they are truly useful for everyone to use then an "rx.testing" package may make sense. + */ + + private OperatorTester() { + } + + /** + * Used for mocking of Schedulers since many Scheduler implementations are static/final. + * + * @param underlying + * @return + */ + public static Scheduler forwardingScheduler(Scheduler underlying) { + return new ForwardingScheduler(underlying); + } + + public static class ForwardingScheduler extends Scheduler { + private final Scheduler underlying; + + public ForwardingScheduler(Scheduler underlying) { + this.underlying = underlying; + } + + @Override + public Subscription schedule(Action0 action) { + return underlying.schedule(action); + } + + @Override + public Subscription schedule(T state, Func2 action) { + return underlying.schedule(state, action); + } + + @Override + public Subscription schedule(Action0 action, long dueTime, TimeUnit unit) { + return underlying.schedule(action, dueTime, unit); + } + + @Override + public Subscription schedule(T state, Func2 action, long dueTime, TimeUnit unit) { + return underlying.schedule(state, action, dueTime, unit); + } + + @Override + public Subscription schedulePeriodically(Action0 action, long initialDelay, long period, TimeUnit unit) { + return underlying.schedulePeriodically(action, initialDelay, period, unit); + } + + @Override + public Subscription schedulePeriodically(T state, Func2 action, long initialDelay, long period, TimeUnit unit) { + return underlying.schedulePeriodically(state, action, initialDelay, period, unit); + } + + @Override + public long now() { + return underlying.now(); + } + } +} \ No newline at end of file diff --git a/rxjava-core/src/test/java/rx/util/RangeTest.java b/rxjava-core/src/test/java/rx/util/RangeTest.java index 640678b5c3..03ec6eef19 100644 --- a/rxjava-core/src/test/java/rx/util/RangeTest.java +++ b/rxjava-core/src/test/java/rx/util/RangeTest.java @@ -1,7 +1,50 @@ package rx.util; -import org.junit.Ignore; +import org.junit.Test; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import static org.junit.Assert.assertEquals; -@Ignore("WIP") public class RangeTest { + + @Test + public void testSimpleRange() { + assertEquals(Arrays.asList(1, 2, 3, 4), toList(Range.create(1, 5))); + } + + @Test + public void testRangeWithStep() { + assertEquals(Arrays.asList(1, 3, 5, 7, 9), toList(Range.createWithStep(1, 10, 2))); + } + + @Test + public void testRangeWithCount() { + assertEquals(Arrays.asList(1, 2, 3, 4, 5), toList(Range.createWithCount(1, 5))); + } + + @Test + public void testRangeWithCount2() { + assertEquals(Arrays.asList(2, 3, 4, 5), toList(Range.createWithCount(2, 4))); + } + + @Test + public void testRangeWithCount3() { + assertEquals(Arrays.asList(0, 1, 2, 3), toList(Range.createWithCount(0, 4))); + } + + @Test + public void testRangeWithCount4() { + assertEquals(Arrays.asList(10, 11, 12, 13, 14), toList(Range.createWithCount(10, 5))); + } + + private static List toList(Iterable iterable) { + List result = new ArrayList(); + for (T element : iterable) { + result.add(element); + } + return result; + } } From 97ab170928f91847de51d8094a0bcf363de82b22 Mon Sep 17 00:00:00 2001 From: Ben Christensen Date: Mon, 4 Nov 2013 19:52:04 -0800 Subject: [PATCH 3/6] Fix ambiguous imports Mockito.* and Observable.* both have a never() method in them. --- .../rx/operators/OperationDistinctTest.java | 56 +++++++++---------- .../OperationDistinctUntilChangedTest.java | 56 +++++++++---------- .../OperationFirstOrDefaultTest.java | 30 +++++----- .../rx/operators/OperationSkipWhileTest.java | 24 ++++---- 4 files changed, 79 insertions(+), 87 deletions(-) diff --git a/rxjava-core/src/test/java/rx/operators/OperationDistinctTest.java b/rxjava-core/src/test/java/rx/operators/OperationDistinctTest.java index 740ba9429a..f1c91c0fed 100644 --- a/rxjava-core/src/test/java/rx/operators/OperationDistinctTest.java +++ b/rxjava-core/src/test/java/rx/operators/OperationDistinctTest.java @@ -1,23 +1,21 @@ package rx.operators; +import static org.mockito.Matchers.*; +import static org.mockito.Mockito.*; +import static org.mockito.MockitoAnnotations.*; +import static rx.operators.OperationDistinct.*; + +import java.util.Comparator; + import org.junit.Before; import org.junit.Test; import org.mockito.InOrder; import org.mockito.Mock; + import rx.Observable; import rx.Observer; import rx.util.functions.Func1; -import java.util.Comparator; - -import static org.mockito.Matchers.any; -import static org.mockito.Matchers.anyString; -import static org.mockito.Mockito.*; -import static org.mockito.Mockito.never; -import static org.mockito.MockitoAnnotations.initMocks; -import static rx.Observable.*; -import static rx.operators.OperationDistinct.distinct; - public class OperationDistinctTest { @Mock @@ -50,8 +48,8 @@ public void before() { @Test public void testDistinctOfNone() { - Observable src = empty(); - create(distinct(src)).subscribe(w); + Observable src = Observable.empty(); + Observable.create(distinct(src)).subscribe(w); verify(w, never()).onNext(anyString()); verify(w, never()).onError(any(Throwable.class)); @@ -60,8 +58,8 @@ public void testDistinctOfNone() { @Test public void testDistinctOfNoneWithKeySelector() { - Observable src = empty(); - create(distinct(src, TO_UPPER_WITH_EXCEPTION)).subscribe(w); + Observable src = Observable.empty(); + Observable.create(distinct(src, TO_UPPER_WITH_EXCEPTION)).subscribe(w); verify(w, never()).onNext(anyString()); verify(w, never()).onError(any(Throwable.class)); @@ -70,8 +68,8 @@ public void testDistinctOfNoneWithKeySelector() { @Test public void testDistinctOfNormalSource() { - Observable src = from("a", "b", "c", "c", "c", "b", "b", "a", "e"); - create(distinct(src)).subscribe(w); + Observable src = Observable.from("a", "b", "c", "c", "c", "b", "b", "a", "e"); + Observable.create(distinct(src)).subscribe(w); InOrder inOrder = inOrder(w); inOrder.verify(w, times(1)).onNext("a"); @@ -85,8 +83,8 @@ public void testDistinctOfNormalSource() { @Test public void testDistinctOfNormalSourceWithKeySelector() { - Observable src = from("a", "B", "c", "C", "c", "B", "b", "a", "E"); - create(distinct(src, TO_UPPER_WITH_EXCEPTION)).subscribe(w); + Observable src = Observable.from("a", "B", "c", "C", "c", "B", "b", "a", "E"); + Observable.create(distinct(src, TO_UPPER_WITH_EXCEPTION)).subscribe(w); InOrder inOrder = inOrder(w); inOrder.verify(w, times(1)).onNext("a"); @@ -100,8 +98,8 @@ public void testDistinctOfNormalSourceWithKeySelector() { @Test public void testDistinctOfNormalSourceWithComparator() { - Observable src = from("1", "12", "123", "aaa", "321", "12", "21", "1", "12345"); - create(distinct(src, COMPARE_LENGTH)).subscribe(w); + Observable src = Observable.from("1", "12", "123", "aaa", "321", "12", "21", "1", "12345"); + Observable.create(distinct(src, COMPARE_LENGTH)).subscribe(w); InOrder inOrder = inOrder(w); inOrder.verify(w, times(1)).onNext("1"); @@ -115,8 +113,8 @@ public void testDistinctOfNormalSourceWithComparator() { @Test public void testDistinctOfNormalSourceWithKeySelectorAndComparator() { - Observable src = from("a", "x", "ab", "abc", "cba", "de", "x", "a", "abcd"); - create(distinct(src, TO_UPPER_WITH_EXCEPTION, COMPARE_LENGTH)).subscribe(w); + Observable src = Observable.from("a", "x", "ab", "abc", "cba", "de", "x", "a", "abcd"); + Observable.create(distinct(src, TO_UPPER_WITH_EXCEPTION, COMPARE_LENGTH)).subscribe(w); InOrder inOrder = inOrder(w); inOrder.verify(w, times(1)).onNext("a"); @@ -130,13 +128,13 @@ public void testDistinctOfNormalSourceWithKeySelectorAndComparator() { @Test public void testDistinctOfNormalSourceWithKeySelectorAndComparatorAndTwoSubscriptions() { - Observable src = from("a", "x", "ab", "abc", "cba", "de", "x", "a", "abcd"); - create(distinct(src, TO_UPPER_WITH_EXCEPTION, COMPARE_LENGTH)).subscribe(w); + Observable src = Observable.from("a", "x", "ab", "abc", "cba", "de", "x", "a", "abcd"); + Observable.create(distinct(src, TO_UPPER_WITH_EXCEPTION, COMPARE_LENGTH)).subscribe(w); InOrder inOrder = inOrder(w); inOrder.verify(w, times(1)).onNext("a"); inOrder.verify(w, times(1)).onNext("x"); - create(distinct(src, TO_UPPER_WITH_EXCEPTION, COMPARE_LENGTH)).subscribe(w2); + Observable.create(distinct(src, TO_UPPER_WITH_EXCEPTION, COMPARE_LENGTH)).subscribe(w2); inOrder.verify(w, times(1)).onNext("abc"); inOrder.verify(w, times(1)).onNext("abcd"); inOrder.verify(w, times(1)).onCompleted(); @@ -155,8 +153,8 @@ public void testDistinctOfNormalSourceWithKeySelectorAndComparatorAndTwoSubscrip @Test public void testDistinctOfSourceWithNulls() { - Observable src = from(null, "a", "a", null, null, "b", null); - create(distinct(src)).subscribe(w); + Observable src = Observable.from(null, "a", "a", null, null, "b", null); + Observable.create(distinct(src)).subscribe(w); InOrder inOrder = inOrder(w); inOrder.verify(w, times(1)).onNext(null); @@ -169,8 +167,8 @@ public void testDistinctOfSourceWithNulls() { @Test public void testDistinctOfSourceWithExceptionsFromKeySelector() { - Observable src = from("a", "b", null, "c"); - create(distinct(src, TO_UPPER_WITH_EXCEPTION)).subscribe(w); + Observable src = Observable.from("a", "b", null, "c"); + Observable.create(distinct(src, TO_UPPER_WITH_EXCEPTION)).subscribe(w); InOrder inOrder = inOrder(w); inOrder.verify(w, times(1)).onNext("a"); diff --git a/rxjava-core/src/test/java/rx/operators/OperationDistinctUntilChangedTest.java b/rxjava-core/src/test/java/rx/operators/OperationDistinctUntilChangedTest.java index e39a123f3d..2ea0167529 100644 --- a/rxjava-core/src/test/java/rx/operators/OperationDistinctUntilChangedTest.java +++ b/rxjava-core/src/test/java/rx/operators/OperationDistinctUntilChangedTest.java @@ -1,23 +1,21 @@ package rx.operators; +import static org.mockito.Matchers.*; +import static org.mockito.Mockito.*; +import static org.mockito.MockitoAnnotations.*; +import static rx.operators.OperationDistinctUntilChanged.*; + +import java.util.Comparator; + import org.junit.Before; import org.junit.Test; import org.mockito.InOrder; import org.mockito.Mock; + import rx.Observable; import rx.Observer; import rx.util.functions.Func1; -import java.util.Comparator; - -import static org.mockito.Matchers.any; -import static org.mockito.Matchers.anyString; -import static org.mockito.Mockito.*; -import static org.mockito.Mockito.never; -import static org.mockito.MockitoAnnotations.initMocks; -import static rx.Observable.*; -import static rx.operators.OperationDistinctUntilChanged.distinctUntilChanged; - public class OperationDistinctUntilChangedTest { @Mock @@ -50,8 +48,8 @@ public void before() { @Test public void testDistinctUntilChangedOfNone() { - Observable src = empty(); - create(distinctUntilChanged(src)).subscribe(w); + Observable src = Observable.empty(); + Observable.create(distinctUntilChanged(src)).subscribe(w); verify(w, never()).onNext(anyString()); verify(w, never()).onError(any(Throwable.class)); @@ -60,8 +58,8 @@ public void testDistinctUntilChangedOfNone() { @Test public void testDistinctUntilChangedOfNoneWithKeySelector() { - Observable src = empty(); - create(distinctUntilChanged(src, TO_UPPER_WITH_EXCEPTION)).subscribe(w); + Observable src = Observable.empty(); + Observable.create(distinctUntilChanged(src, TO_UPPER_WITH_EXCEPTION)).subscribe(w); verify(w, never()).onNext(anyString()); verify(w, never()).onError(any(Throwable.class)); @@ -70,8 +68,8 @@ public void testDistinctUntilChangedOfNoneWithKeySelector() { @Test public void testDistinctUntilChangedOfNormalSource() { - Observable src = from("a", "b", "c", "c", "c", "b", "b", "a", "e"); - create(distinctUntilChanged(src)).subscribe(w); + Observable src = Observable.from("a", "b", "c", "c", "c", "b", "b", "a", "e"); + Observable.create(distinctUntilChanged(src)).subscribe(w); InOrder inOrder = inOrder(w); inOrder.verify(w, times(1)).onNext("a"); @@ -87,8 +85,8 @@ public void testDistinctUntilChangedOfNormalSource() { @Test public void testDistinctUntilChangedOfNormalSourceWithKeySelector() { - Observable src = from("a", "b", "c", "C", "c", "B", "b", "a", "e"); - create(distinctUntilChanged(src, TO_UPPER_WITH_EXCEPTION)).subscribe(w); + Observable src = Observable.from("a", "b", "c", "C", "c", "B", "b", "a", "e"); + Observable.create(distinctUntilChanged(src, TO_UPPER_WITH_EXCEPTION)).subscribe(w); InOrder inOrder = inOrder(w); inOrder.verify(w, times(1)).onNext("a"); @@ -104,8 +102,8 @@ public void testDistinctUntilChangedOfNormalSourceWithKeySelector() { @Test public void testDistinctUntilChangedOfSourceWithNulls() { - Observable src = from(null, "a", "a", null, null, "b", null, null); - create(distinctUntilChanged(src)).subscribe(w); + Observable src = Observable.from(null, "a", "a", null, null, "b", null, null); + Observable.create(distinctUntilChanged(src)).subscribe(w); InOrder inOrder = inOrder(w); inOrder.verify(w, times(1)).onNext(null); @@ -120,8 +118,8 @@ public void testDistinctUntilChangedOfSourceWithNulls() { @Test public void testDistinctUntilChangedOfSourceWithExceptionsFromKeySelector() { - Observable src = from("a", "b", null, "c"); - create(distinctUntilChanged(src, TO_UPPER_WITH_EXCEPTION)).subscribe(w); + Observable src = Observable.from("a", "b", null, "c"); + Observable.create(distinctUntilChanged(src, TO_UPPER_WITH_EXCEPTION)).subscribe(w); InOrder inOrder = inOrder(w); inOrder.verify(w, times(1)).onNext("a"); @@ -133,8 +131,8 @@ public void testDistinctUntilChangedOfSourceWithExceptionsFromKeySelector() { @Test public void testDistinctUntilChangedWithComparator() { - Observable src = from("a", "b", "c", "aa", "bb", "c", "ddd"); - create(distinctUntilChanged(src, COMPARE_LENGTH)).subscribe(w); + Observable src = Observable.from("a", "b", "c", "aa", "bb", "c", "ddd"); + Observable.create(distinctUntilChanged(src, COMPARE_LENGTH)).subscribe(w); InOrder inOrder = inOrder(w); inOrder.verify(w, times(1)).onNext("a"); inOrder.verify(w, times(1)).onNext("aa"); @@ -147,8 +145,8 @@ public void testDistinctUntilChangedWithComparator() { @Test public void testDistinctUntilChangedWithComparatorAndKeySelector() { - Observable src = from("a", "b", "x", "aa", "bb", "c", "ddd"); - create(distinctUntilChanged(src, TO_UPPER_WITH_EXCEPTION, COMPARE_LENGTH)).subscribe(w); + Observable src = Observable.from("a", "b", "x", "aa", "bb", "c", "ddd"); + Observable.create(distinctUntilChanged(src, TO_UPPER_WITH_EXCEPTION, COMPARE_LENGTH)).subscribe(w); InOrder inOrder = inOrder(w); inOrder.verify(w, times(1)).onNext("a"); inOrder.verify(w, times(1)).onNext("x"); @@ -161,12 +159,12 @@ public void testDistinctUntilChangedWithComparatorAndKeySelector() { @Test public void testDistinctUntilChangedWithComparatorAndKeySelectorandTwoSubscriptions() { - Observable src = from("a", "b", "x", "aa", "bb", "c", "ddd"); - create(distinctUntilChanged(src, TO_UPPER_WITH_EXCEPTION, COMPARE_LENGTH)).subscribe(w); + Observable src = Observable.from("a", "b", "x", "aa", "bb", "c", "ddd"); + Observable.create(distinctUntilChanged(src, TO_UPPER_WITH_EXCEPTION, COMPARE_LENGTH)).subscribe(w); InOrder inOrder = inOrder(w); inOrder.verify(w, times(1)).onNext("a"); inOrder.verify(w, times(1)).onNext("x"); - create(distinctUntilChanged(src, TO_UPPER_WITH_EXCEPTION, COMPARE_LENGTH)).subscribe(w2); + Observable.create(distinctUntilChanged(src, TO_UPPER_WITH_EXCEPTION, COMPARE_LENGTH)).subscribe(w2); inOrder.verify(w, times(1)).onNext("c"); inOrder.verify(w, times(1)).onNext("ddd"); inOrder.verify(w, times(1)).onCompleted(); diff --git a/rxjava-core/src/test/java/rx/operators/OperationFirstOrDefaultTest.java b/rxjava-core/src/test/java/rx/operators/OperationFirstOrDefaultTest.java index 344ab98578..f645fd785e 100644 --- a/rxjava-core/src/test/java/rx/operators/OperationFirstOrDefaultTest.java +++ b/rxjava-core/src/test/java/rx/operators/OperationFirstOrDefaultTest.java @@ -1,20 +1,18 @@ package rx.operators; +import static org.mockito.Matchers.*; +import static org.mockito.Mockito.*; +import static org.mockito.MockitoAnnotations.*; +import static rx.operators.OperationFirstOrDefault.*; + import org.junit.Before; import org.junit.Test; import org.mockito.Mock; + import rx.Observable; import rx.Observer; import rx.util.functions.Func1; -import static org.mockito.Matchers.any; -import static org.mockito.Matchers.anyString; -import static org.mockito.Mockito.never; -import static org.mockito.Mockito.*; -import static org.mockito.MockitoAnnotations.initMocks; -import static rx.Observable.*; -import static rx.operators.OperationFirstOrDefault.firstOrDefault; - public class OperationFirstOrDefaultTest { @Mock @@ -34,8 +32,8 @@ public void before() { @Test public void testFirstOrElseOfNone() { - Observable src = empty(); - create(firstOrDefault(src, "default")).subscribe(w); + Observable src = Observable.empty(); + Observable.create(firstOrDefault(src, "default")).subscribe(w); verify(w, times(1)).onNext(anyString()); verify(w, times(1)).onNext("default"); @@ -45,8 +43,8 @@ public void testFirstOrElseOfNone() { @Test public void testFirstOrElseOfSome() { - Observable src = from("a", "b", "c"); - create(firstOrDefault(src, "default")).subscribe(w); + Observable src = Observable.from("a", "b", "c"); + Observable.create(firstOrDefault(src, "default")).subscribe(w); verify(w, times(1)).onNext(anyString()); verify(w, times(1)).onNext("a"); @@ -56,8 +54,8 @@ public void testFirstOrElseOfSome() { @Test public void testFirstOrElseWithPredicateOfNoneMatchingThePredicate() { - Observable src = from("a", "b", "c"); - create(firstOrDefault(src, IS_D, "default")).subscribe(w); + Observable src = Observable.from("a", "b", "c"); + Observable.create(firstOrDefault(src, IS_D, "default")).subscribe(w); verify(w, times(1)).onNext(anyString()); verify(w, times(1)).onNext("default"); @@ -67,8 +65,8 @@ public void testFirstOrElseWithPredicateOfNoneMatchingThePredicate() { @Test public void testFirstOrElseWithPredicateOfSome() { - Observable src = from("a", "b", "c", "d", "e", "f"); - create(firstOrDefault(src, IS_D, "default")).subscribe(w); + Observable src = Observable.from("a", "b", "c", "d", "e", "f"); + Observable.create(firstOrDefault(src, IS_D, "default")).subscribe(w); verify(w, times(1)).onNext(anyString()); verify(w, times(1)).onNext("d"); diff --git a/rxjava-core/src/test/java/rx/operators/OperationSkipWhileTest.java b/rxjava-core/src/test/java/rx/operators/OperationSkipWhileTest.java index f0d8391928..0c97f00c9b 100644 --- a/rxjava-core/src/test/java/rx/operators/OperationSkipWhileTest.java +++ b/rxjava-core/src/test/java/rx/operators/OperationSkipWhileTest.java @@ -1,19 +1,17 @@ package rx.operators; +import static org.mockito.Matchers.*; +import static org.mockito.Mockito.*; +import static rx.operators.OperationSkipWhile.*; + import org.junit.Test; import org.mockito.InOrder; + import rx.Observable; import rx.Observer; import rx.util.functions.Func1; import rx.util.functions.Func2; -import static org.mockito.Matchers.any; -import static org.mockito.Matchers.anyInt; -import static org.mockito.Mockito.*; -import static rx.Observable.create; -import static rx.operators.OperationSkipWhile.skipWhile; -import static rx.operators.OperationSkipWhile.skipWhileWithIndex; - public class OperationSkipWhileTest { @SuppressWarnings("unchecked") @@ -37,7 +35,7 @@ public Boolean call(Integer value, Integer index) { @Test public void testSkipWithIndex() { Observable src = Observable.from(1, 2, 3, 4, 5); - create(skipWhileWithIndex(src, INDEX_LESS_THAN_THREE)).subscribe(w); + Observable.create(skipWhileWithIndex(src, INDEX_LESS_THAN_THREE)).subscribe(w); InOrder inOrder = inOrder(w); inOrder.verify(w, times(1)).onNext(4); @@ -49,7 +47,7 @@ public void testSkipWithIndex() { @Test public void testSkipEmpty() { Observable src = Observable.empty(); - create(skipWhile(src, LESS_THAN_FIVE)).subscribe(w); + Observable.create(skipWhile(src, LESS_THAN_FIVE)).subscribe(w); verify(w, never()).onNext(anyInt()); verify(w, never()).onError(any(Throwable.class)); verify(w, times(1)).onCompleted(); @@ -58,7 +56,7 @@ public void testSkipEmpty() { @Test public void testSkipEverything() { Observable src = Observable.from(1, 2, 3, 4, 3, 2, 1); - create(skipWhile(src, LESS_THAN_FIVE)).subscribe(w); + Observable.create(skipWhile(src, LESS_THAN_FIVE)).subscribe(w); verify(w, never()).onNext(anyInt()); verify(w, never()).onError(any(Throwable.class)); verify(w, times(1)).onCompleted(); @@ -67,7 +65,7 @@ public void testSkipEverything() { @Test public void testSkipNothing() { Observable src = Observable.from(5, 3, 1); - create(skipWhile(src, LESS_THAN_FIVE)).subscribe(w); + Observable.create(skipWhile(src, LESS_THAN_FIVE)).subscribe(w); InOrder inOrder = inOrder(w); inOrder.verify(w, times(1)).onNext(5); @@ -80,7 +78,7 @@ public void testSkipNothing() { @Test public void testSkipSome() { Observable src = Observable.from(1, 2, 3, 4, 5, 3, 1, 5); - create(skipWhile(src, LESS_THAN_FIVE)).subscribe(w); + Observable.create(skipWhile(src, LESS_THAN_FIVE)).subscribe(w); InOrder inOrder = inOrder(w); inOrder.verify(w, times(1)).onNext(5); @@ -94,7 +92,7 @@ public void testSkipSome() { @Test public void testSkipError() { Observable src = Observable.from(1, 2, 42, 5, 3, 1); - create(skipWhile(src, LESS_THAN_FIVE)).subscribe(w); + Observable.create(skipWhile(src, LESS_THAN_FIVE)).subscribe(w); InOrder inOrder = inOrder(w); inOrder.verify(w, never()).onNext(anyInt()); From 6ec81dfcb52e1444960e7f349100f56389bdeb4a Mon Sep 17 00:00:00 2001 From: Ben Christensen Date: Mon, 4 Nov 2013 20:01:01 -0800 Subject: [PATCH 4/6] Organize, Format, Comments and Cleanup Also included comment => /* package accessible for unit tests */ for private classes made package public to enable unit testing. --- rxjava-core/src/main/java/rx/Observable.java | 204 +-- rxjava-core/src/main/java/rx/Observer.java | 16 +- rxjava-core/src/main/java/rx/Scheduler.java | 8 +- .../concurrency/CurrentThreadScheduler.java | 16 +- .../rx/concurrency/ExecutorScheduler.java | 8 +- .../rx/concurrency/ImmediateScheduler.java | 42 +- .../java/rx/concurrency/SleepingAction.java | 12 +- .../rx/observables/BlockingObservable.java | 17 +- .../rx/observables/ConnectableObservable.java | 12 +- .../rx/observables/GroupedObservable.java | 22 +- .../java/rx/operators/ChunkedOperation.java | 2 +- .../main/java/rx/operators/OperationAll.java | 6 +- .../main/java/rx/operators/OperationAny.java | 12 +- .../java/rx/operators/OperationAverage.java | 5 +- .../java/rx/operators/OperationBuffer.java | 18 +- .../java/rx/operators/OperationCache.java | 4 +- .../rx/operators/OperationCombineLatest.java | 83 +- .../java/rx/operators/OperationConcat.java | 8 +- .../java/rx/operators/OperationDebounce.java | 6 +- .../rx/operators/OperationDefaultIfEmpty.java | 2 +- .../java/rx/operators/OperationDistinct.java | 46 +- .../OperationDistinctUntilChanged.java | 26 +- .../java/rx/operators/OperationElementAt.java | 4 +- .../java/rx/operators/OperationFinally.java | 16 +- .../rx/operators/OperationFirstOrDefault.java | 16 +- .../java/rx/operators/OperationGroupBy.java | 20 +- .../java/rx/operators/OperationInterval.java | 8 +- .../main/java/rx/operators/OperationMap.java | 12 +- .../java/rx/operators/OperationMerge.java | 8 +- .../operators/OperationMergeDelayError.java | 10 +- .../rx/operators/OperationMostRecent.java | 8 +- .../java/rx/operators/OperationMulticast.java | 8 +- .../main/java/rx/operators/OperationNext.java | 26 +- ...OperationOnErrorResumeNextViaFunction.java | 6 +- ...erationOnErrorResumeNextViaObservable.java | 8 +- .../rx/operators/OperationOnErrorReturn.java | 6 +- ...ionOnExceptionResumeNextViaObservable.java | 4 +- .../java/rx/operators/OperationParallel.java | 4 +- .../java/rx/operators/OperationRefCount.java | 6 +- .../java/rx/operators/OperationRetry.java | 4 +- .../java/rx/operators/OperationSample.java | 32 +- .../main/java/rx/operators/OperationScan.java | 21 +- .../main/java/rx/operators/OperationSkip.java | 4 +- .../java/rx/operators/OperationSkipLast.java | 12 +- .../java/rx/operators/OperationSkipWhile.java | 12 +- .../rx/operators/OperationSubscribeOn.java | 6 +- .../main/java/rx/operators/OperationSum.java | 1 + .../java/rx/operators/OperationSwitch.java | 21 +- .../rx/operators/OperationSynchronize.java | 6 +- .../main/java/rx/operators/OperationTake.java | 4 +- .../java/rx/operators/OperationTakeLast.java | 8 +- .../java/rx/operators/OperationTakeWhile.java | 4 +- .../rx/operators/OperationThrottleFirst.java | 6 +- .../rx/operators/OperationTimeInterval.java | 6 +- .../java/rx/operators/OperationTimeout.java | 16 +- .../rx/operators/OperationToIterator.java | 1 + .../OperationToObservableFuture.java | 8 +- .../operators/OperationToObservableList.java | 9 +- .../OperationToObservableSortedList.java | 12 +- .../java/rx/operators/OperationWindow.java | 18 +- .../main/java/rx/operators/OperationZip.java | 23 +- .../operators/SafeObservableSubscription.java | 7 +- .../java/rx/operators/ScheduledObserver.java | 3 +- .../rx/operators/SynchronizedObserver.java | 2 +- .../src/main/java/rx/package-info.java | 16 +- .../main/java/rx/plugins/RxJavaPlugins.java | 2 +- .../main/java/rx/subjects/AsyncSubject.java | 19 +- .../java/rx/subjects/BehaviorSubject.java | 24 +- .../main/java/rx/subjects/PublishSubject.java | 8 +- .../main/java/rx/subjects/ReplaySubject.java | 18 +- .../java/rx/subjects/UnsubscribeTester.java | 6 +- .../subscriptions/CompositeSubscription.java | 6 +- .../rx/subscriptions/SerialSubscription.java | 8 +- .../java/rx/subscriptions/Subscriptions.java | 6 +- .../src/main/java/rx/util/Closings.java | 3 +- .../src/main/java/rx/util/Openings.java | 3 +- .../src/main/java/rx/util/TimeInterval.java | 10 +- .../src/main/java/rx/util/Timestamped.java | 10 +- .../java/rx/util/functions/Functions.java | 5 +- .../src/main/java/rx/util/functions/Not.java | 12 +- rxjava-core/src/test/java/README.md | 6 - rxjava-core/src/test/java/rx/ConcatTests.java | 8 +- .../src/test/java/rx/IntervalDemo.java | 60 +- rxjava-core/src/test/java/rx/MergeTests.java | 9 +- .../src/test/java/rx/ObservableTests.java | 9 +- .../src/test/java/rx/RefCountTests.java | 18 +- .../src/test/java/rx/SchedulersTest.java | 910 ++++++------ .../src/test/java/rx/StartWithTests.java | 2 +- .../src/test/java/rx/TimeoutTests.java | 21 +- .../CurrentThreadSchedulerTest.java | 229 ++- .../concurrency/ImmediateSchedulerTest.java | 103 +- .../observables/BlockingObservableTest.java | 447 +++--- .../java/rx/operators/OperationAllTest.java | 149 +- .../java/rx/operators/OperationAnyTest.java | 344 ++--- .../rx/operators/OperationAverageTest.java | 199 ++- .../rx/operators/OperationBufferTest.java | 637 ++++---- .../java/rx/operators/OperationCacheTest.java | 102 +- .../java/rx/operators/OperationCastTest.java | 63 +- .../operators/OperationCombineLatestTest.java | 1174 +++++++-------- .../rx/operators/OperationConcatTest.java | 940 ++++++------ .../rx/operators/OperationDebounceTest.java | 262 ++-- .../OperationDefaultIfEmptyTest.java | 71 +- .../java/rx/operators/OperationDeferTest.java | 57 +- .../operators/OperationDematerializeTest.java | 97 +- .../rx/operators/OperationDistinctTest.java | 312 ++-- .../OperationDistinctUntilChangedTest.java | 318 ++-- .../rx/operators/OperationElementAtTest.java | 199 ++- .../rx/operators/OperationFilterTest.java | 45 +- .../rx/operators/OperationFinallyTest.java | 56 +- .../OperationFirstOrDefaultTest.java | 96 +- .../rx/operators/OperationGroupByTest.java | 547 +++---- .../rx/operators/OperationIntervalTest.java | 301 ++-- .../java/rx/operators/OperationMapTest.java | 487 +++--- .../operators/OperationMaterializeTest.java | 231 +-- .../OperationMergeDelayErrorTest.java | 826 +++++------ .../java/rx/operators/OperationMergeTest.java | 723 ++++----- .../rx/operators/OperationMostRecentTest.java | 76 +- .../rx/operators/OperationMulticastTest.java | 123 +- .../java/rx/operators/OperationNextTest.java | 462 +++--- .../rx/operators/OperationObserveOnTest.java | 93 +- ...ationOnErrorResumeNextViaFunctionTest.java | 278 ++-- ...ionOnErrorResumeNextViaObservableTest.java | 207 +-- .../operators/OperationOnErrorReturnTest.java | 200 +-- ...nExceptionResumeNextViaObservableTest.java | 389 ++--- .../rx/operators/OperationParallelTest.java | 71 +- .../java/rx/operators/OperationRetryTest.java | 197 +-- .../rx/operators/OperationSampleTest.java | 136 +- .../java/rx/operators/OperationScanTest.java | 178 ++- .../rx/operators/OperationSkipLastTest.java | 177 +-- .../java/rx/operators/OperationSkipTest.java | 67 +- .../rx/operators/OperationSkipWhileTest.java | 165 ++- .../operators/OperationSubscribeOnTest.java | 42 +- .../java/rx/operators/OperationSumTest.java | 205 ++- .../rx/operators/OperationSwitchTest.java | 706 ++++----- .../operators/OperationSynchronizeTest.java | 359 ++--- .../rx/operators/OperationTakeLastTest.java | 175 +-- .../java/rx/operators/OperationTakeTest.java | 375 +++-- .../rx/operators/OperationTakeUntilTest.java | 291 ++-- .../rx/operators/OperationTakeWhileTest.java | 352 ++--- .../operators/OperationThrottleFirstTest.java | 199 +-- .../operators/OperationTimeIntervalTest.java | 88 +- .../OperationToObservableFutureTest.java | 77 +- .../OperationToObservableIterableTest.java | 40 +- .../OperationToObservableListTest.java | 87 +- .../OperationToObservableSortedListTest.java | 79 +- .../rx/operators/OperationWindowTest.java | 576 ++++---- .../java/rx/operators/OperationZipTest.java | 1101 +++++++------- .../SafeObservableSubscriptionTest.java | 24 +- .../operators/SynchronizedObserverTest.java | 1314 +++++++++-------- .../java/rx/plugins/RxJavaPluginsTest.java | 120 +- .../java/rx/subjects/AsyncSubjectTest.java | 245 ++- .../java/rx/subjects/BehaviorSubjectTest.java | 248 ++-- .../java/rx/subjects/PublishSubjectTest.java | 620 ++++---- .../java/rx/subjects/ReplaySubjectTest.java | 297 ++-- .../CompositeSubscriptionTest.java | 116 +- .../SerialSubscriptionTests.java | 11 +- .../rx/subscriptions/SubscriptionsTest.java | 23 +- .../src/test/java/rx/test/OperatorTester.java | 98 +- .../src/test/java/rx/util/RangeTest.java | 76 +- 159 files changed, 11019 insertions(+), 10949 deletions(-) delete mode 100644 rxjava-core/src/test/java/README.md diff --git a/rxjava-core/src/main/java/rx/Observable.java b/rxjava-core/src/main/java/rx/Observable.java index 8cf4c951ed..8ba20d1ca2 100644 --- a/rxjava-core/src/main/java/rx/Observable.java +++ b/rxjava-core/src/main/java/rx/Observable.java @@ -19,7 +19,6 @@ import java.util.ArrayList; import java.util.Arrays; -import java.util.Comparator; import java.util.List; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.Future; @@ -287,7 +286,7 @@ private Subscription protectivelyWrapAndSubscribe(Observer o) { /** * An {@link Observer} must call an Observable's {@code subscribe} method in order to * receive items and notifications from the Observable. - * + * * @param onNext */ public Subscription subscribe(final Action1 onNext) { @@ -324,7 +323,7 @@ public void onNext(T args) { /** * An {@link Observer} must call an Observable's {@code subscribe} method in order to * receive items and notifications from the Observable. - * + * * @param onNext * @param scheduler */ @@ -369,7 +368,7 @@ public void onNext(T args) { /** * An {@link Observer} must call an Observable's {@code subscribe} method in order to * receive items and notifications from the Observable. - * + * * @param onNext * @param onError * @param scheduler @@ -381,7 +380,7 @@ public Subscription subscribe(final Action1 onNext, final Action1 Observable empty() { * its {@link Observer#onCompleted onCompleted} method with the specified scheduler. *

    * + * * @param scheduler * the scheduler to call the {@link Observer#onCompleted onCompleted} method. * @param @@ -571,7 +571,7 @@ public static Observable empty() { * @see MSDN: Observable.Empty Method (IScheduler) */ public static Observable empty(Scheduler scheduler) { - return Observable.empty().subscribeOn(scheduler); + return Observable. empty().subscribeOn(scheduler); } /** @@ -594,7 +594,7 @@ public static Observable error(Throwable exception) { * Returns an Observable that invokes an {@link Observer}'s {@link Observer#onError onError} method with the specified scheduler. *

    * - * + * * @param exception * the particular error to report * @param scheduler @@ -626,7 +626,7 @@ public static Observable error(Throwable exception, Scheduler scheduler) public static Observable from(Iterable iterable) { return create(OperationToObservableIterable.toObservableIterable(iterable)); } - + /** * Converts an Array into an Observable. *

    @@ -906,7 +906,7 @@ public static Observable from(T t1, T t2, T t3, T t4, T t5, T t6, T t7, T public static Observable from(T t1, T t2, T t3, T t4, T t5, T t6, T t7, T t8, T t9) { return from(Arrays.asList(t1, t2, t3, t4, t5, t6, t7, t8, t9)); } - + /** * Converts a series of items into an Observable. *

    @@ -1018,7 +1018,7 @@ public static Observable just(T value) { * Returns an Observable that emits a single item and then completes on a specified scheduler. *

    * This is a scheduler version of {@link Observable#just(Object)}. - * + * * @param value * the item to pass to the {@link Observer}'s {@link Observer#onNext onNext} method * @param scheduler @@ -1049,7 +1049,7 @@ public static Observable just(T value, Scheduler scheduler) { public static Observable merge(Observable> source) { return create(OperationMerge.merge(source)); } - + /** * Flattens a series of Observables into one Observable, without any transformation. *

    @@ -1095,7 +1095,7 @@ public static Observable merge(Observable t1, Observable Observable merge(Observable t1, Observable t2, Observable t3) { return create(OperationMerge.merge(t1, t2, t3)); } - + /** * Flattens a series of Observables into one Observable, without any transformation. *

    @@ -1121,7 +1121,7 @@ public static Observable merge(Observable t1, Observable Observable merge(Observable t1, Observable t2, Observable t3, Observable t4) { return create(OperationMerge.merge(t1, t2, t3, t4)); } - + /** * Flattens a series of Observables into one Observable, without any transformation. *

    @@ -1149,7 +1149,7 @@ public static Observable merge(Observable t1, Observable Observable merge(Observable t1, Observable t2, Observable t3, Observable t4, Observable t5) { return create(OperationMerge.merge(t1, t2, t3, t4, t5)); } - + /** * Flattens a series of Observables into one Observable, without any transformation. *

    @@ -1179,7 +1179,7 @@ public static Observable merge(Observable t1, Observable Observable merge(Observable t1, Observable t2, Observable t3, Observable t4, Observable t5, Observable t6) { return create(OperationMerge.merge(t1, t2, t3, t4, t5, t6)); } - + /** * Flattens a series of Observables into one Observable, without any transformation. *

    @@ -1211,7 +1211,7 @@ public static Observable merge(Observable t1, Observable Observable merge(Observable t1, Observable t2, Observable t3, Observable t4, Observable t5, Observable t6, Observable t7) { return create(OperationMerge.merge(t1, t2, t3, t4, t5, t6, t7)); } - + /** * Flattens a series of Observables into one Observable, without any transformation. *

    @@ -1245,7 +1245,7 @@ public static Observable merge(Observable t1, Observable Observable merge(Observable t1, Observable t2, Observable t3, Observable t4, Observable t5, Observable t6, Observable t7, Observable t8) { return create(OperationMerge.merge(t1, t2, t3, t4, t5, t6, t7, t8)); } - + /** * Flattens a series of Observables into one Observable, without any transformation. *

    @@ -1297,7 +1297,7 @@ public static Observable merge(Observable t1, Observable Observable concat(Observable> observables) { return create(OperationConcat.concat(observables)); } - + /** * Returns an Observable that emits the items emitted by two or more Observables, one after the * other. @@ -1567,7 +1567,7 @@ public static Observable mergeDelayError(Observable Observable mergeDelayError(Observable t1, Observable t2) { return create(OperationMergeDelayError.mergeDelayError(t1, t2)); } - + /** * This behaves like {@link #merge(Observable, Observable, Observable)} except that if any of the merged Observables * notify of an error via {@link Observer#onError onError}, {@code mergeDelayError} will @@ -1597,7 +1597,7 @@ public static Observable mergeDelayError(Observable t1, Obse public static Observable mergeDelayError(Observable t1, Observable t2, Observable t3) { return create(OperationMergeDelayError.mergeDelayError(t1, t2, t3)); } - + /** * This behaves like {@link #merge(Observable, Observable, Observable, Observable)} except that if any of the merged Observables * notify of an error via {@link Observer#onError onError}, {@code mergeDelayError} will @@ -1629,7 +1629,7 @@ public static Observable mergeDelayError(Observable t1, Obse public static Observable mergeDelayError(Observable t1, Observable t2, Observable t3, Observable t4) { return create(OperationMergeDelayError.mergeDelayError(t1, t2, t3, t4)); } - + /** * This behaves like {@link #merge(Observable, Observable, Observable, Observable, Observable)} except that if any of the merged Observables * notify of an error via {@link Observer#onError onError}, {@code mergeDelayError} will @@ -1663,7 +1663,7 @@ public static Observable mergeDelayError(Observable t1, Obse public static Observable mergeDelayError(Observable t1, Observable t2, Observable t3, Observable t4, Observable t5) { return create(OperationMergeDelayError.mergeDelayError(t1, t2, t3, t4, t5)); } - + /** * This behaves like {@link #merge(Observable, Observable, Observable, Observable, Observable, Observable)} except that if any of the merged Observables * notify of an error via {@link Observer#onError onError}, {@code mergeDelayError} will @@ -1699,7 +1699,7 @@ public static Observable mergeDelayError(Observable t1, Obse public static Observable mergeDelayError(Observable t1, Observable t2, Observable t3, Observable t4, Observable t5, Observable t6) { return create(OperationMergeDelayError.mergeDelayError(t1, t2, t3, t4, t5, t6)); } - + /** * This behaves like {@link #merge(Observable, Observable, Observable, Observable, Observable, Observable, Observable)} except that if any of the merged Observables * notify of an error via {@link Observer#onError onError}, {@code mergeDelayError} will @@ -1737,7 +1737,7 @@ public static Observable mergeDelayError(Observable t1, Obse public static Observable mergeDelayError(Observable t1, Observable t2, Observable t3, Observable t4, Observable t5, Observable t6, Observable t7) { return create(OperationMergeDelayError.mergeDelayError(t1, t2, t3, t4, t5, t6, t7)); } - + /** * This behaves like {@link #merge(Observable, Observable, Observable, Observable, Observable, Observable, Observable, Observable)} except that if any of the merged Observables * notify of an error via {@link Observer#onError onError}, {@code mergeDelayError} will @@ -1777,7 +1777,7 @@ public static Observable mergeDelayError(Observable t1, Obse public static Observable mergeDelayError(Observable t1, Observable t2, Observable t3, Observable t4, Observable t5, Observable t6, Observable t7, Observable t8) { return create(OperationMergeDelayError.mergeDelayError(t1, t2, t3, t4, t5, t6, t7, t8)); } - + /** * This behaves like {@link #merge(Observable, Observable, Observable, Observable, Observable, Observable, Observable, Observable, Observable)} except that if any of the merged Observables * notify of an error via {@link Observer#onError onError}, {@code mergeDelayError} will @@ -1866,7 +1866,6 @@ public static Observable switchDo(Observable Observable switchOnNext(Observable> sequenceOfSequences) { return create(OperationSwitch.switchDo(sequenceOfSequences)); } - /** * Accepts an Observable and wraps it in another Observable that ensures that the resulting @@ -1894,7 +1893,7 @@ public Observable synchronize() { * A well-behaved Observable does not interleave its invocations of the {@link Observer#onNext onNext}, {@link Observer#onCompleted onCompleted}, and {@link Observer#onError onError} methods of * its {@link Observer}s; it invokes {@code onCompleted} or {@code onError} only once; and it never invokes {@code onNext} after invoking either {@code onCompleted} or {@code onError}. * {@code synchronize} enforces this, and the Observable it returns invokes {@code onNext} and {@code onCompleted} or {@code onError} synchronously. - * + * * @param lock * The lock object to synchronize each observer call on * @return an Observable that is a chronologically well-behaved version of the source @@ -1905,18 +1904,18 @@ public Observable synchronize(Object lock) { } /** - * @deprecated Replaced with instance method. + * @deprecated Replaced with instance method. */ @Deprecated public static Observable synchronize(Observable source) { return create(OperationSynchronize.synchronize(source)); } - + /** * Emits an item each time interval (containing a sequential number). *

    * - * + * * @param interval * Interval size in time units (see below). * @param unit @@ -1927,12 +1926,12 @@ public static Observable synchronize(Observable source) { public static Observable interval(long interval, TimeUnit unit) { return create(OperationInterval.interval(interval, unit)); } - + /** * Emits an item each time interval (containing a sequential number). *

    * - * + * * @param interval * Interval size in time units (see below). * @param unit @@ -1945,7 +1944,7 @@ public static Observable interval(long interval, TimeUnit unit) { public static Observable interval(long interval, TimeUnit unit, Scheduler scheduler) { return create(OperationInterval.interval(interval, unit, scheduler)); } - + /** * Debounces by dropping all values that are followed by newer values before the timeout value expires. The timer resets on each `onNext` call. *

    @@ -3035,8 +3034,7 @@ public Observable> window(long timespan, long timeshift, TimeUnit /** * Returns an Observable that emits the results of a function of your choosing applied to * combinations of N items emitted, in sequence, by N other Observables as provided by an Iterable. - *

    - * {@code zip} applies this function in strict sequence, so the first item emitted by the + *

    {@code zip} applies this function in strict sequence, so the first item emitted by the * new Observable will be the result of the function applied to the first item emitted by * all of the Observalbes; the second item emitted by the new Observable will be the result of * the function applied to the second item emitted by each of those Observables; and so forth. @@ -3139,7 +3137,7 @@ public Observable distinctUntilChanged(Func1 keyS public Observable distinct() { return create(OperationDistinct.distinct(this)); } - + /** * Returns an Observable that forwards all items emitted from the source Observable that are distinct according * to a key selector function. @@ -3155,7 +3153,7 @@ public Observable distinct() { public Observable distinct(Func1 keySelector) { return create(OperationDistinct.distinct(this, keySelector)); } - + /** * Returns the element at a specified index in a sequence. * @@ -3193,9 +3191,9 @@ public Observable elementAt(int index) { public Observable elementAtOrDefault(int index, T defaultValue) { return create(OperationElementAt.elementAtOrDefault(this, index, defaultValue)); } - + /** - * Returns an {@link Observable} that emits true if any element of the source {@link Observable} satisfies + * Returns an {@link Observable} that emits true if any element of the source {@link Observable} satisfies * the given condition, otherwise false. Note: always emit false if the source {@link Observable} is empty. *

    * In Rx.Net this is the any operator but renamed in RxJava to better match Java naming idioms. @@ -3209,10 +3207,10 @@ public Observable elementAtOrDefault(int index, T defaultValue) { public Observable exists(Func1 predicate) { return create(OperationAny.exists(this, predicate)); } - + /** * Determines whether an observable sequence contains a specified element. - * + * * @param element * The element to search in the sequence. * @return an Observable that emits if the element is in the source sequence. @@ -3531,8 +3529,8 @@ public Observable reduce(Func2 accumulator) { * Returns an Observable that counts the total number of elements in the source Observable. *

    * - * - * @return an Observable emitting the number of counted elements of the source Observable + * + * @return an Observable emitting the number of counted elements of the source Observable * as its single item. * @see MSDN: Observable.Count */ @@ -3544,22 +3542,22 @@ public Integer call(Integer t1, T t2) { } }); } - + /** * Returns an Observable that sums up the elements in the source Observable. *

    * - * + * * @param source - * Source observable to compute the sum of. - * @return an Observable emitting the sum of all the elements of the source Observable + * Source observable to compute the sum of. + * @return an Observable emitting the sum of all the elements of the source Observable * as its single item. * @see MSDN: Observable.Sum */ public static Observable sum(Observable source) { return OperationSum.sum(source); } - + /** * @see #sum(Observable) * @see MSDN: Observable.Sum @@ -3567,7 +3565,7 @@ public static Observable sum(Observable source) { public static Observable sumLongs(Observable source) { return OperationSum.sumLongs(source); } - + /** * @see #sum(Observable) * @see MSDN: Observable.Sum @@ -3575,7 +3573,7 @@ public static Observable sumLongs(Observable source) { public static Observable sumFloats(Observable source) { return OperationSum.sumFloats(source); } - + /** * @see #sum(Observable) * @see MSDN: Observable.Sum @@ -3583,23 +3581,23 @@ public static Observable sumFloats(Observable source) { public static Observable sumDoubles(Observable source) { return OperationSum.sumDoubles(source); } - + /** * Returns an Observable that computes the average of all elements in the source Observable. * For an empty source, it causes an ArithmeticException. *

    * - * + * * @param source - * Source observable to compute the average of. - * @return an Observable emitting the averageof all the elements of the source Observable + * Source observable to compute the average of. + * @return an Observable emitting the averageof all the elements of the source Observable * as its single item. * @see MSDN: Observable.Average */ public static Observable average(Observable source) { return OperationAverage.average(source); } - + /** * @see #average(Observable) * @see MSDN: Observable.Average @@ -3636,7 +3634,7 @@ public static Observable averageDoubles(Observable source) { public ConnectableObservable replay() { return OperationMulticast.multicast(this, ReplaySubject. create()); } - + /** * Retry subscription to origin Observable upto given retry count. *

    @@ -3668,6 +3666,7 @@ public Observable retry(int retryCount) { *

    * For example, if an Observable fails on first time but emits [1, 2] then succeeds the second time and * emits [1, 2, 3, 4, 5] then the complete output would be [1, 2, 1, 2, 3, 4, 5, onCompleted]. + * * @return Observable with retry logic. */ public Observable retry() { @@ -3714,11 +3713,11 @@ public Observable parallel(Func1, Observable> f) { * a {@link Scheduler} to perform the work on. * @return an Observable with the output of the {@link Func1} executed on a {@link Scheduler} */ - + public Observable parallel(final Func1, Observable> f, final Scheduler s) { return OperationParallel.parallel(this, f, s); } - + /** * Returns a {@link ConnectableObservable}, which waits until its {@link ConnectableObservable#connect connect} method is called before it begins emitting * items to those {@link Observer}s that have subscribed to it. @@ -3734,6 +3733,7 @@ public ConnectableObservable publish() { /** * Returns a {@link ConnectableObservable} that shares a single subscription that contains the last notification only. + * * @return a {@link ConnectableObservable} */ public ConnectableObservable publishLast() { @@ -3973,19 +3973,19 @@ public Observable firstOrDefault(Func1 predicate, T defau /** * Returns the elements of the specified sequence or the specified default * value in a singleton sequence if the sequence is empty. - * + * * @param defaultValue * The value to return if the sequence is empty. * @return An observable sequence that contains the specified default value * if the source is empty; otherwise, the elements of the source * itself. - * + * * @see MSDN: Observable.DefaultIfEmpty */ public Observable defaultIfEmpty(T defaultValue) { return create(OperationDefaultIfEmpty.defaultIfEmpty(this, defaultValue)); } - + /** * Returns an Observable that emits only the first num items emitted by the source * Observable. @@ -4051,7 +4051,7 @@ public Observable takeWhileWithIndex(final Func2 takeFirst() { return first(); } - + /** * Returns an Observable that emits only the very first item emitted by the source Observable * that satisfies a given condition. @@ -4068,7 +4068,7 @@ public Observable takeFirst() { public Observable takeFirst(Func1 predicate) { return first(predicate); } - + /** * Returns an Observable that emits only the last count items emitted by the source * Observable. @@ -4108,13 +4108,13 @@ public Observable takeUntil(Observable other) { * condition holds true. Emits all further source items as soon as the condition becomes false. *

    * - * + * * @param predicate * A function to test each item emitted from the source Observable for a condition. * It receives the emitted item as first parameter and the index of the emitted item as * second parameter. * @return an Observable that emits all items from the source Observable as soon as the condition - * becomes false. + * becomes false. * @see MSDN: Observable.SkipWhile */ public Observable skipWhileWithIndex(Func2 predicate) { @@ -4126,11 +4126,11 @@ public Observable skipWhileWithIndex(Func2 predi * condition holds true. Emits all further source items as soon as the condition becomes false. *

    * - * + * * @param predicate * A function to test each item emitted from the source Observable for a condition. * @return an Observable that emits all items from the source Observable as soon as the condition - * becomes false. + * becomes false. * @see MSDN: Observable.SkipWhile */ public Observable skipWhile(Func1 predicate) { @@ -4145,16 +4145,16 @@ public Observable skipWhile(Func1 predicate) { * count elements. As more elements are received, elements are taken from * the front of the queue and produced on the result sequence. This causes * elements to be delayed. - * + * * @param count * number of elements to bypass at the end of the source * sequence. * @return An observable sequence containing the source sequence elements * except for the bypassed ones at the end. - * + * * @throws IndexOutOfBoundsException * count is less than zero. - * + * * @see MSDN: Observable.SkipLast */ public Observable skipLast(int count) { @@ -4225,7 +4225,7 @@ public Observable> toSortedList(Func2 sor public Observable startWith(Iterable values) { return concat(Observable. from(values), this); } - + /** * Emit a specified set of items before beginning to emit items from the source Observable. *

    @@ -4238,7 +4238,7 @@ public Observable startWith(Iterable values) { public Observable startWith(T t1) { return concat(Observable. from(t1), this); } - + /** * Emit a specified set of items before beginning to emit items from the source Observable. *

    @@ -4253,7 +4253,7 @@ public Observable startWith(T t1) { public Observable startWith(T t1, T t2) { return concat(Observable. from(t1, t2), this); } - + /** * Emit a specified set of items before beginning to emit items from the source Observable. *

    @@ -4270,7 +4270,7 @@ public Observable startWith(T t1, T t2) { public Observable startWith(T t1, T t2, T t3) { return concat(Observable. from(t1, t2, t3), this); } - + /** * Emit a specified set of items before beginning to emit items from the source Observable. *

    @@ -4289,7 +4289,7 @@ public Observable startWith(T t1, T t2, T t3) { public Observable startWith(T t1, T t2, T t3, T t4) { return concat(Observable. from(t1, t2, t3, t4), this); } - + /** * Emit a specified set of items before beginning to emit items from the source Observable. *

    @@ -4310,7 +4310,7 @@ public Observable startWith(T t1, T t2, T t3, T t4) { public Observable startWith(T t1, T t2, T t3, T t4, T t5) { return concat(Observable. from(t1, t2, t3, t4, t5), this); } - + /** * Emit a specified set of items before beginning to emit items from the source Observable. *

    @@ -4333,7 +4333,7 @@ public Observable startWith(T t1, T t2, T t3, T t4, T t5) { public Observable startWith(T t1, T t2, T t3, T t4, T t5, T t6) { return concat(Observable. from(t1, t2, t3, t4, t5, t6), this); } - + /** * Emit a specified set of items before beginning to emit items from the source Observable. *

    @@ -4358,7 +4358,7 @@ public Observable startWith(T t1, T t2, T t3, T t4, T t5, T t6) { public Observable startWith(T t1, T t2, T t3, T t4, T t5, T t6, T t7) { return concat(Observable. from(t1, t2, t3, t4, t5, t6, t7), this); } - + /** * Emit a specified set of items before beginning to emit items from the source Observable. *

    @@ -4385,7 +4385,7 @@ public Observable startWith(T t1, T t2, T t3, T t4, T t5, T t6, T t7) { public Observable startWith(T t1, T t2, T t3, T t4, T t5, T t6, T t7, T t8) { return concat(Observable. from(t1, t2, t3, t4, t5, t6, t7, t8), this); } - + /** * Emit a specified set of items before beginning to emit items from the source Observable. *

    @@ -4454,7 +4454,7 @@ public Observable> groupBy(final Func1 Observable> groupBy(final Func1 keySelector) { return create(OperationGroupBy.groupBy(this, keySelector)); } - + /** * Returns an {@link Observable} that emits true if the source {@link Observable} is empty, otherwise false. *

    @@ -4466,7 +4466,7 @@ public Observable> groupBy(final Func1 isEmpty() { return create(OperationAny.isEmpty(this)); } - + /** * Converts an Observable into a {@link BlockingObservable} (an Observable with blocking * operators). @@ -4479,16 +4479,14 @@ public BlockingObservable toBlockingObservable() { /** * Converts the elements of an observable sequence to the specified type. - * + * * @param klass * The target class type which the elements will be converted to. - * + * * @return An observable sequence that contains each element of the source * sequence converted to the specified type. - * - * @see MSDN: - * Observable.Cast + * + * @see MSDN: Observable.Cast */ public Observable cast(final Class klass) { return create(OperationCast.cast(this, klass)); @@ -4497,14 +4495,14 @@ public Observable cast(final Class klass) { /** * Filters the elements of an observable sequence based on the specified * type. - * + * * @param klass * The class type to filter the elements in the source sequence * on. - * + * * @return An observable sequence that contains elements from the input * sequence of type klass. - * + * * @see MSDN: Observable.OfType */ public Observable ofType(final Class klass) { @@ -4517,9 +4515,9 @@ public Boolean call(T t) { /** * Ignores all values in an observable sequence and only calls onCompleted or onError method. - * + * * @return An empty observable sequence that only call onCompleted, or onError method. - * + * * @see MSDN: Observable.IgnoreElements */ public Observable ignoreElements() { @@ -4528,12 +4526,13 @@ public Observable ignoreElements() { /** * Returns either the observable sequence or an TimeoutException if timeout elapses. + * * @param timeout - * The timeout duration + * The timeout duration * @param timeUnit - * The time unit of the timeout + * The time unit of the timeout * @param scheduler - * The scheduler to run the timeout timers on. + * The scheduler to run the timeout timers on. * @return The source sequence with a TimeoutException in case of a timeout. */ public Observable timeout(long timeout, TimeUnit timeUnit, Scheduler scheduler) { @@ -4542,10 +4541,11 @@ public Observable timeout(long timeout, TimeUnit timeUnit, Scheduler schedule /** * Returns either the observable sequence or an TimeoutException if timeout elapses. + * * @param timeout - * The timeout duration + * The timeout duration * @param timeUnit - * The time unit of the timeout + * The time unit of the timeout * @return The source sequence with a TimeoutException in case of a timeout. */ public Observable timeout(long timeout, TimeUnit timeUnit) { @@ -4554,7 +4554,7 @@ public Observable timeout(long timeout, TimeUnit timeUnit) { /** * Records the time interval between consecutive elements in an observable sequence. - * + * * @return An observable sequence with time interval information on elements. * @see MSDN: Observable.TimeInterval */ @@ -4565,10 +4565,10 @@ public Observable> timeInterval() { /** * Records the time interval between consecutive elements in an observable * sequence, using the specified scheduler to compute time intervals. - * + * * @param scheduler * Scheduler used to compute time intervals. - * + * * @return An observable sequence with time interval information on elements. * @see MSDN: Observable.TimeInterval */ @@ -4582,7 +4582,7 @@ public Observable> timeInterval(Scheduler scheduler) { * For why this is being used see https://github.com/Netflix/RxJava/issues/216 for discussion on "Guideline 6.4: Protect calls to user code from within an operator" * * NOTE: If strong reasons for not depending on package names comes up then the implementation of this method can change to looking for a marker interface. - * + * * @param o * @return {@code true} if the given function is an internal implementation, and {@code false} otherwise. */ diff --git a/rxjava-core/src/main/java/rx/Observer.java b/rxjava-core/src/main/java/rx/Observer.java index c18b3d4fde..3d35066ba4 100644 --- a/rxjava-core/src/main/java/rx/Observer.java +++ b/rxjava-core/src/main/java/rx/Observer.java @@ -1,12 +1,12 @@ /** * Copyright 2013 Netflix, Inc. - * + * * 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. @@ -18,12 +18,12 @@ /** * Provides a mechanism for receiving push-based notifications. *

    - * After an Observer calls an {@link Observable}'s Observable.subscribe method, the {@link Observable} - * calls the Observer's onNext method to provide notifications. A well-behaved {@link Observable} will + * After an Observer calls an {@link Observable}'s Observable.subscribe method, the {@link Observable} calls the Observer's onNext method to provide notifications. A + * well-behaved {@link Observable} will * call an Observer's onCompleted closure exactly once or the Observer's onError closure exactly once. *

    * For more information see the RxJava Wiki - * + * * @param */ public interface Observer { @@ -39,7 +39,7 @@ public interface Observer { * Notifies the Observer that the {@link Observable} has experienced an error condition. *

    * If the {@link Observable} calls this closure, it will not thereafter call onNext or onCompleted. - * + * * @param e */ public void onError(Throwable e); @@ -50,7 +50,7 @@ public interface Observer { * The {@link Observable} calls this closure 1 or more times, unless it calls onError in which case this closure may never be called. *

    * The {@link Observable} will not call this closure again after it calls either onCompleted or onError. - * + * * @param args */ public void onNext(T args); diff --git a/rxjava-core/src/main/java/rx/Scheduler.java b/rxjava-core/src/main/java/rx/Scheduler.java index 3da38f41f2..b01872f226 100644 --- a/rxjava-core/src/main/java/rx/Scheduler.java +++ b/rxjava-core/src/main/java/rx/Scheduler.java @@ -15,6 +15,10 @@ */ package rx; +import java.util.Date; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicBoolean; + import rx.subscriptions.CompositeSubscription; import rx.subscriptions.MultipleAssignmentSubscription; import rx.subscriptions.Subscriptions; @@ -22,10 +26,6 @@ import rx.util.functions.Action1; import rx.util.functions.Func2; -import java.util.Date; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicBoolean; - /** * Represents an object that schedules units of work. *

    diff --git a/rxjava-core/src/main/java/rx/concurrency/CurrentThreadScheduler.java b/rxjava-core/src/main/java/rx/concurrency/CurrentThreadScheduler.java index a096ef06e2..9bf1f6ad91 100644 --- a/rxjava-core/src/main/java/rx/concurrency/CurrentThreadScheduler.java +++ b/rxjava-core/src/main/java/rx/concurrency/CurrentThreadScheduler.java @@ -1,12 +1,12 @@ /** * Copyright 2013 Netflix, Inc. - * + * * 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. @@ -15,14 +15,14 @@ */ package rx.concurrency; -import rx.Scheduler; -import rx.Subscription; -import rx.util.functions.Func2; - import java.util.PriorityQueue; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; +import rx.Scheduler; +import rx.Subscription; +import rx.util.functions.Func2; + /** * Schedules work on the current thread but does not execute immediately. Work is put in a queue and executed after the current unit of work is completed. */ @@ -35,7 +35,7 @@ public static CurrentThreadScheduler getInstance() { private static final ThreadLocal> QUEUE = new ThreadLocal>(); - CurrentThreadScheduler() { + /* package accessible for unit tests */CurrentThreadScheduler() { } private final AtomicInteger counter = new AtomicInteger(0); diff --git a/rxjava-core/src/main/java/rx/concurrency/ExecutorScheduler.java b/rxjava-core/src/main/java/rx/concurrency/ExecutorScheduler.java index a1fd36179e..cee84eae44 100644 --- a/rxjava-core/src/main/java/rx/concurrency/ExecutorScheduler.java +++ b/rxjava-core/src/main/java/rx/concurrency/ExecutorScheduler.java @@ -48,7 +48,7 @@ public ExecutorScheduler(ScheduledExecutorService executor) { public Subscription schedulePeriodically(final T state, final Func2 action, long initialDelay, long period, TimeUnit unit) { if (executor instanceof ScheduledExecutorService) { final CompositeSubscription subscriptions = new CompositeSubscription(); - + ScheduledFuture f = ((ScheduledExecutorService) executor).scheduleAtFixedRate(new Runnable() { @Override public void run() { @@ -56,15 +56,15 @@ public void run() { subscriptions.add(s); } }, initialDelay, period, unit); - + subscriptions.add(Subscriptions.create(f)); return subscriptions; - + } else { return super.schedulePeriodically(state, action, initialDelay, period, unit); } } - + @Override public Subscription schedule(final T state, final Func2 action, long delayTime, TimeUnit unit) { final DiscardableAction discardableAction = new DiscardableAction(state, action); diff --git a/rxjava-core/src/main/java/rx/concurrency/ImmediateScheduler.java b/rxjava-core/src/main/java/rx/concurrency/ImmediateScheduler.java index d1d00355f4..c5a4cef9d4 100644 --- a/rxjava-core/src/main/java/rx/concurrency/ImmediateScheduler.java +++ b/rxjava-core/src/main/java/rx/concurrency/ImmediateScheduler.java @@ -1,12 +1,12 @@ /** * Copyright 2013 Netflix, Inc. - * + * * 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. @@ -15,35 +15,35 @@ */ package rx.concurrency; +import java.util.concurrent.TimeUnit; + import rx.Scheduler; import rx.Subscription; import rx.util.functions.Func2; -import java.util.concurrent.TimeUnit; - /** * Executes work immediately on the current thread. */ public final class ImmediateScheduler extends Scheduler { - private static final ImmediateScheduler INSTANCE = new ImmediateScheduler(); + private static final ImmediateScheduler INSTANCE = new ImmediateScheduler(); - public static ImmediateScheduler getInstance() { - return INSTANCE; - } + public static ImmediateScheduler getInstance() { + return INSTANCE; + } - ImmediateScheduler() { - } + /* package accessible for unit tests */ImmediateScheduler() { + } - @Override - public Subscription schedule(T state, Func2 action) { - return action.call(this, state); - } + @Override + public Subscription schedule(T state, Func2 action) { + return action.call(this, state); + } - @Override - public Subscription schedule(T state, Func2 action, long dueTime, TimeUnit unit) { - // since we are executing immediately on this thread we must cause this thread to sleep - long execTime = now() + unit.toMillis(dueTime); + @Override + public Subscription schedule(T state, Func2 action, long dueTime, TimeUnit unit) { + // since we are executing immediately on this thread we must cause this thread to sleep + long execTime = now() + unit.toMillis(dueTime); - return schedule(state, new SleepingAction(action, this, execTime)); - } + return schedule(state, new SleepingAction(action, this, execTime)); + } } diff --git a/rxjava-core/src/main/java/rx/concurrency/SleepingAction.java b/rxjava-core/src/main/java/rx/concurrency/SleepingAction.java index eea75639b8..925403e846 100644 --- a/rxjava-core/src/main/java/rx/concurrency/SleepingAction.java +++ b/rxjava-core/src/main/java/rx/concurrency/SleepingAction.java @@ -1,12 +1,12 @@ /** * Copyright 2013 Netflix, Inc. - * + * * 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. @@ -30,16 +30,14 @@ public SleepingAction(Func2 scheduler.now()) { long delay = execTime - scheduler.now(); - if (delay> 0) { + if (delay > 0) { try { Thread.sleep(delay); - } - catch (InterruptedException e) { + } catch (InterruptedException e) { Thread.currentThread().interrupt(); throw new RuntimeException(e); } diff --git a/rxjava-core/src/main/java/rx/observables/BlockingObservable.java b/rxjava-core/src/main/java/rx/observables/BlockingObservable.java index b59f34d78c..36f372685e 100644 --- a/rxjava-core/src/main/java/rx/observables/BlockingObservable.java +++ b/rxjava-core/src/main/java/rx/observables/BlockingObservable.java @@ -15,18 +15,23 @@ */ package rx.observables; +import java.util.Iterator; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.Future; +import java.util.concurrent.atomic.AtomicReference; + import rx.Observable; import rx.Observer; import rx.Subscription; -import rx.operators.*; +import rx.operators.OperationMostRecent; +import rx.operators.OperationNext; +import rx.operators.OperationToFuture; +import rx.operators.OperationToIterator; +import rx.operators.SafeObservableSubscription; +import rx.operators.SafeObserver; import rx.util.functions.Action1; import rx.util.functions.Func1; -import java.util.Iterator; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.Future; -import java.util.concurrent.atomic.AtomicReference; - /** * An extension of {@link Observable} that provides blocking operators. *

    diff --git a/rxjava-core/src/main/java/rx/observables/ConnectableObservable.java b/rxjava-core/src/main/java/rx/observables/ConnectableObservable.java index 1595c31195..1826905eaf 100644 --- a/rxjava-core/src/main/java/rx/observables/ConnectableObservable.java +++ b/rxjava-core/src/main/java/rx/observables/ConnectableObservable.java @@ -1,12 +1,12 @@ /** * Copyright 2013 Netflix, Inc. - * + * * 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. @@ -19,7 +19,6 @@ import rx.Observer; import rx.Subscription; import rx.operators.OperationRefCount; -import rx.util.functions.Func1; /** * A ConnectableObservable resembles an ordinary {@link Observable}, except that it does not begin @@ -32,7 +31,7 @@ * For more information see * Connectable * Observable Operators at the RxJava Wiki - * + * * @param */ @@ -44,13 +43,14 @@ protected ConnectableObservable(OnSubscribeFunc onSubscribe) { /** * Call a ConnectableObservable's connect() method to instruct it to begin emitting the - * items from its underlying {@link Observable} to its {@link Observer}s. + * items from its underlying {@link Observable} to its {@link Observer}s. */ public abstract Subscription connect(); /** * Returns an observable sequence that stays connected to the source as long * as there is at least one subscription to the observable sequence. + * * @return a {@link Observable} */ public Observable refCount() { diff --git a/rxjava-core/src/main/java/rx/observables/GroupedObservable.java b/rxjava-core/src/main/java/rx/observables/GroupedObservable.java index 940d68e85b..f40e8c40af 100644 --- a/rxjava-core/src/main/java/rx/observables/GroupedObservable.java +++ b/rxjava-core/src/main/java/rx/observables/GroupedObservable.java @@ -1,12 +1,12 @@ /** * Copyright 2013 Netflix, Inc. - * + * * 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. @@ -19,13 +19,14 @@ import rx.util.functions.Func1; /** - * An {@link Observable} that has been grouped by a key whose value can be obtained using - * {@link #getKey()}

    - * + * An {@link Observable} that has been grouped by a key whose value can be obtained using {@link #getKey()}

    + * * @see Observable#groupBy(Func1) - * - * @param the type of the key - * @param the type of the elements in the group + * + * @param + * the type of the key + * @param + * the type of the elements in the group */ public class GroupedObservable extends Observable { private final K key; @@ -37,11 +38,10 @@ public GroupedObservable(K key, OnSubscribeFunc onSubscribe) { /** * Returns the key the elements in this observable were grouped by. - * + * * @return the key the elements in this observable were grouped by */ public K getKey() { return key; } } - diff --git a/rxjava-core/src/main/java/rx/operators/ChunkedOperation.java b/rxjava-core/src/main/java/rx/operators/ChunkedOperation.java index d68501d122..cabc1309e6 100644 --- a/rxjava-core/src/main/java/rx/operators/ChunkedOperation.java +++ b/rxjava-core/src/main/java/rx/operators/ChunkedOperation.java @@ -61,7 +61,7 @@ protected interface ChunkCreator { * * @param * The type of objects which this {@link Chunk} can hold. - * @param + * @param * The type of object being tracked by the {@link Chunk} */ protected abstract static class Chunk { diff --git a/rxjava-core/src/main/java/rx/operators/OperationAll.java b/rxjava-core/src/main/java/rx/operators/OperationAll.java index 908fd1f54e..f3e0f0ebcd 100644 --- a/rxjava-core/src/main/java/rx/operators/OperationAll.java +++ b/rxjava-core/src/main/java/rx/operators/OperationAll.java @@ -15,14 +15,14 @@ */ package rx.operators; +import java.util.concurrent.atomic.AtomicBoolean; + import rx.Observable; import rx.Observable.OnSubscribeFunc; import rx.Observer; import rx.Subscription; import rx.util.functions.Func1; -import java.util.concurrent.atomic.AtomicBoolean; - /** * Returns an Observable that emits a Boolean that indicates whether all items emitted by an * Observable satisfy a condition. @@ -41,13 +41,11 @@ private static class AllObservable implements OnSubscribeFunc { private final SafeObservableSubscription subscription = new SafeObservableSubscription(); - private AllObservable(Observable sequence, Func1 predicate) { this.sequence = sequence; this.predicate = predicate; } - @Override public Subscription onSubscribe(final Observer observer) { return subscription.wrap(sequence.subscribe(new AllObserver(observer))); diff --git a/rxjava-core/src/main/java/rx/operators/OperationAny.java b/rxjava-core/src/main/java/rx/operators/OperationAny.java index 5830fbb1f2..a06058bece 100644 --- a/rxjava-core/src/main/java/rx/operators/OperationAny.java +++ b/rxjava-core/src/main/java/rx/operators/OperationAny.java @@ -15,16 +15,16 @@ */ package rx.operators; +import static rx.util.functions.Functions.*; + +import java.util.concurrent.atomic.AtomicBoolean; + import rx.Observable; import rx.Observable.OnSubscribeFunc; import rx.Observer; import rx.Subscription; import rx.util.functions.Func1; -import java.util.concurrent.atomic.AtomicBoolean; - -import static rx.util.functions.Functions.alwaysTrue; - /** * Returns an {@link Observable} that emits true if any element of * an observable sequence satisfies a condition, otherwise false. @@ -41,7 +41,7 @@ public final class OperationAny { public static OnSubscribeFunc any(Observable source) { return new Any(source, alwaysTrue(), false); } - + public static OnSubscribeFunc isEmpty(Observable source) { return new Any(source, alwaysTrue(), true); } @@ -61,7 +61,7 @@ public static OnSubscribeFunc isEmpty(Observable sourc public static OnSubscribeFunc any(Observable source, Func1 predicate) { return new Any(source, predicate, false); } - + public static OnSubscribeFunc exists(Observable source, Func1 predicate) { return any(source, predicate); } diff --git a/rxjava-core/src/main/java/rx/operators/OperationAverage.java b/rxjava-core/src/main/java/rx/operators/OperationAverage.java index c130396f2a..3fbbd1f05e 100644 --- a/rxjava-core/src/main/java/rx/operators/OperationAverage.java +++ b/rxjava-core/src/main/java/rx/operators/OperationAverage.java @@ -21,19 +21,20 @@ /** * A few operators for implementing the averaging operation. + * * @see MSDN: Observable.Average */ public final class OperationAverage { private static final class Tuple2 { private final T current; private final Integer count; - + private Tuple2(T v1, Integer v2) { current = v1; count = v2; } } - + public static Observable average(Observable source) { return source.reduce(new Tuple2(0, 0), new Func2, Integer, Tuple2>() { @Override diff --git a/rxjava-core/src/main/java/rx/operators/OperationBuffer.java b/rxjava-core/src/main/java/rx/operators/OperationBuffer.java index 03d2dc02b8..c9aba14411 100644 --- a/rxjava-core/src/main/java/rx/operators/OperationBuffer.java +++ b/rxjava-core/src/main/java/rx/operators/OperationBuffer.java @@ -15,6 +15,9 @@ */ package rx.operators; +import java.util.List; +import java.util.concurrent.TimeUnit; + import rx.Observable; import rx.Observable.OnSubscribeFunc; import rx.Observer; @@ -26,9 +29,6 @@ import rx.util.functions.Func0; import rx.util.functions.Func1; -import java.util.List; -import java.util.concurrent.TimeUnit; - public final class OperationBuffer extends ChunkedOperation { private static Func0> bufferMaker() { @@ -65,7 +65,7 @@ public static OnSubscribeFunc> buffer(final Observable source, fi @Override public Subscription onSubscribe(Observer> observer) { - NonOverlappingChunks> buffers = new NonOverlappingChunks>(observer, OperationBuffer.bufferMaker()); + NonOverlappingChunks> buffers = new NonOverlappingChunks>(observer, OperationBuffer. bufferMaker()); ChunkCreator creator = new ObservableBasedSingleChunkCreator>(buffers, bufferClosingSelector); return source.subscribe(new ChunkObserver>(buffers, observer, creator)); } @@ -101,7 +101,7 @@ public static OnSubscribeFunc> buffer(final Observable source, fi return new OnSubscribeFunc>() { @Override public Subscription onSubscribe(final Observer> observer) { - OverlappingChunks> buffers = new OverlappingChunks>(observer, OperationBuffer.bufferMaker()); + OverlappingChunks> buffers = new OverlappingChunks>(observer, OperationBuffer. bufferMaker()); ChunkCreator creator = new ObservableBasedMultiChunkCreator>(buffers, bufferOpenings, bufferClosingSelector); return source.subscribe(new ChunkObserver>(buffers, observer, creator)); } @@ -156,7 +156,7 @@ public static OnSubscribeFunc> buffer(final Observable source, fi return new OnSubscribeFunc>() { @Override public Subscription onSubscribe(final Observer> observer) { - Chunks> chunks = new SizeBasedChunks>(observer, OperationBuffer.bufferMaker(), count); + Chunks> chunks = new SizeBasedChunks>(observer, OperationBuffer. bufferMaker(), count); ChunkCreator creator = new SkippingChunkCreator>(chunks, skip); return source.subscribe(new ChunkObserver>(chunks, observer, creator)); } @@ -211,7 +211,7 @@ public static OnSubscribeFunc> buffer(final Observable source, fi return new OnSubscribeFunc>() { @Override public Subscription onSubscribe(final Observer> observer) { - NonOverlappingChunks> buffers = new NonOverlappingChunks>(observer, OperationBuffer.bufferMaker()); + NonOverlappingChunks> buffers = new NonOverlappingChunks>(observer, OperationBuffer. bufferMaker()); ChunkCreator creator = new TimeBasedChunkCreator>(buffers, timespan, unit, scheduler); return source.subscribe(new ChunkObserver>(buffers, observer, creator)); } @@ -272,7 +272,7 @@ public static OnSubscribeFunc> buffer(final Observable source, fi return new OnSubscribeFunc>() { @Override public Subscription onSubscribe(final Observer> observer) { - Chunks> chunks = new TimeAndSizeBasedChunks>(observer, OperationBuffer.bufferMaker(), count, timespan, unit, scheduler); + Chunks> chunks = new TimeAndSizeBasedChunks>(observer, OperationBuffer. bufferMaker(), count, timespan, unit, scheduler); ChunkCreator creator = new SingleChunkCreator>(chunks); return source.subscribe(new ChunkObserver>(chunks, observer, creator)); } @@ -333,7 +333,7 @@ public static OnSubscribeFunc> buffer(final Observable source, fi return new OnSubscribeFunc>() { @Override public Subscription onSubscribe(final Observer> observer) { - OverlappingChunks> buffers = new TimeBasedChunks>(observer, OperationBuffer.bufferMaker(), timespan, unit, scheduler); + OverlappingChunks> buffers = new TimeBasedChunks>(observer, OperationBuffer. bufferMaker(), timespan, unit, scheduler); ChunkCreator creator = new TimeBasedChunkCreator>(buffers, timeshift, unit, scheduler); return source.subscribe(new ChunkObserver>(buffers, observer, creator)); } diff --git a/rxjava-core/src/main/java/rx/operators/OperationCache.java b/rxjava-core/src/main/java/rx/operators/OperationCache.java index 44749bbd15..71c681a179 100644 --- a/rxjava-core/src/main/java/rx/operators/OperationCache.java +++ b/rxjava-core/src/main/java/rx/operators/OperationCache.java @@ -15,14 +15,14 @@ */ package rx.operators; +import java.util.concurrent.atomic.AtomicBoolean; + import rx.Observable; import rx.Observable.OnSubscribeFunc; import rx.Observer; import rx.Subscription; import rx.subjects.ReplaySubject; -import java.util.concurrent.atomic.AtomicBoolean; - /** * This method has similar behavior to {@link Observable#replay()} except that this auto-subscribes * to the source Observable rather than returning a connectable Observable. diff --git a/rxjava-core/src/main/java/rx/operators/OperationCombineLatest.java b/rxjava-core/src/main/java/rx/operators/OperationCombineLatest.java index b87aaea0ba..8a581667ae 100644 --- a/rxjava-core/src/main/java/rx/operators/OperationCombineLatest.java +++ b/rxjava-core/src/main/java/rx/operators/OperationCombineLatest.java @@ -15,12 +15,6 @@ */ package rx.operators; -import rx.Observable; -import rx.Observable.OnSubscribeFunc; -import rx.Observer; -import rx.Subscription; -import rx.util.functions.*; - import java.util.LinkedList; import java.util.List; import java.util.Map; @@ -28,6 +22,21 @@ import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicInteger; +import rx.Observable; +import rx.Observable.OnSubscribeFunc; +import rx.Observer; +import rx.Subscription; +import rx.util.functions.Func2; +import rx.util.functions.Func3; +import rx.util.functions.Func4; +import rx.util.functions.Func5; +import rx.util.functions.Func6; +import rx.util.functions.Func7; +import rx.util.functions.Func8; +import rx.util.functions.Func9; +import rx.util.functions.FuncN; +import rx.util.functions.Functions; + /** * Returns an Observable that combines the emissions of multiple source observables. Once each * source Observable has emitted at least one item, combineLatest emits an item whenever any of @@ -41,12 +50,13 @@ public class OperationCombineLatest { /** * Combines the two given observables, emitting an event containing an aggregation of the latest values of each of the source observables * each time an event is received from one of the source observables, where the aggregation is defined by the given function. - * @param w0 - * The first source observable. - * @param w1 - * The second source observable. - * @param combineLatestFunction - * The aggregation function used to combine the source observable values. + * + * @param w0 + * The first source observable. + * @param w1 + * The second source observable. + * @param combineLatestFunction + * The aggregation function used to combine the source observable values. * @return A function from an observer to a subscription. This can be used to create an observable from. */ public static OnSubscribeFunc combineLatest(Observable w0, Observable w1, Func2 combineLatestFunction) { @@ -59,7 +69,7 @@ public static OnSubscribeFunc combineLatest(Observable OnSubscribeFunc combineLatest(Observable w0, Observable w1, Observable w2, + public static OnSubscribeFunc combineLatest(Observable w0, Observable w1, Observable w2, Func3 combineLatestFunction) { Aggregator a = new Aggregator(Functions.fromFunc(combineLatestFunction)); a.addObserver(new CombineObserver(a, w0)); @@ -71,7 +81,7 @@ public static OnSubscribeFunc combineLatest(Observable OnSubscribeFunc combineLatest(Observable w0, Observable w1, Observable w2, Observable w3, + public static OnSubscribeFunc combineLatest(Observable w0, Observable w1, Observable w2, Observable w3, Func4 combineLatestFunction) { Aggregator a = new Aggregator(Functions.fromFunc(combineLatestFunction)); a.addObserver(new CombineObserver(a, w0)); @@ -84,7 +94,7 @@ public static OnSubscribeFunc combineLatest(Observable OnSubscribeFunc combineLatest(Observable w0, Observable w1, Observable w2, Observable w3, Observable w4, + public static OnSubscribeFunc combineLatest(Observable w0, Observable w1, Observable w2, Observable w3, Observable w4, Func5 combineLatestFunction) { Aggregator a = new Aggregator(Functions.fromFunc(combineLatestFunction)); a.addObserver(new CombineObserver(a, w0)); @@ -98,7 +108,7 @@ public static OnSubscribeFunc combineLatest(Observabl /** * @see #combineLatest(Observable w0, Observable w1, Func2 combineLatestFunction) */ - public static OnSubscribeFunc combineLatest(Observable w0, Observable w1, Observable w2, Observable w3, Observable w4, Observable w5, + public static OnSubscribeFunc combineLatest(Observable w0, Observable w1, Observable w2, Observable w3, Observable w4, Observable w5, Func6 combineLatestFunction) { Aggregator a = new Aggregator(Functions.fromFunc(combineLatestFunction)); a.addObserver(new CombineObserver(a, w0)); @@ -113,7 +123,7 @@ public static OnSubscribeFunc combineLatest(Obser /** * @see #combineLatest(Observable w0, Observable w1, Func2 combineLatestFunction) */ - public static OnSubscribeFunc combineLatest(Observable w0, Observable w1, Observable w2, Observable w3, Observable w4, Observable w5, Observable w6, + public static OnSubscribeFunc combineLatest(Observable w0, Observable w1, Observable w2, Observable w3, Observable w4, Observable w5, Observable w6, Func7 combineLatestFunction) { Aggregator a = new Aggregator(Functions.fromFunc(combineLatestFunction)); a.addObserver(new CombineObserver(a, w0)); @@ -129,7 +139,7 @@ public static OnSubscribeFunc combineLatest(O /** * @see #combineLatest(Observable w0, Observable w1, Func2 combineLatestFunction) */ - public static OnSubscribeFunc combineLatest(Observable w0, Observable w1, Observable w2, Observable w3, Observable w4, Observable w5, Observable w6, Observable w7, + public static OnSubscribeFunc combineLatest(Observable w0, Observable w1, Observable w2, Observable w3, Observable w4, Observable w5, Observable w6, Observable w7, Func8 combineLatestFunction) { Aggregator a = new Aggregator(Functions.fromFunc(combineLatestFunction)); a.addObserver(new CombineObserver(a, w0)); @@ -146,7 +156,8 @@ public static OnSubscribeFunc combineLate /** * @see #combineLatest(Observable w0, Observable w1, Func2 combineLatestFunction) */ - public static OnSubscribeFunc combineLatest(Observable w0, Observable w1, Observable w2, Observable w3, Observable w4, Observable w5, Observable w6, Observable w7, Observable w8, + public static OnSubscribeFunc combineLatest(Observable w0, Observable w1, Observable w2, Observable w3, Observable w4, Observable w5, Observable w6, Observable w7, + Observable w8, Func9 combineLatestFunction) { Aggregator a = new Aggregator(Functions.fromFunc(combineLatestFunction)); a.addObserver(new CombineObserver(a, w0)); @@ -161,7 +172,7 @@ public static OnSubscribeFunc combine return a; } - static class CombineObserver implements Observer { + /* package accessible for unit tests */static class CombineObserver implements Observer { final Observable w; final Aggregator a; private Subscription subscription; @@ -195,25 +206,25 @@ public void onNext(T args) { } /** - * Receive notifications from each of the observables we are reducing and execute the combineLatestFunction - * whenever we have received an event from one of the observables, as soon as each Observable has received + * Receive notifications from each of the observables we are reducing and execute the combineLatestFunction + * whenever we have received an event from one of the observables, as soon as each Observable has received * at least one event. */ - static class Aggregator implements OnSubscribeFunc { + /* package accessible for unit tests */static class Aggregator implements OnSubscribeFunc { private volatile Observer observer; private final FuncN combineLatestFunction; private final AtomicBoolean running = new AtomicBoolean(true); - + // Stores how many observers have already completed private final AtomicInteger numCompleted = new AtomicInteger(0); - + /** * The latest value from each observer. */ private final Map, Object> latestValue = new ConcurrentHashMap, Object>(); - + /** * Ordered list of observers to combine. * No synchronization is necessary as these can not be added or changed asynchronously. @@ -227,7 +238,8 @@ public Aggregator(FuncN combineLatestFunction) { /** * Receive notification of a Observer starting (meaning we should require it for aggregation) * - * @param w The observer to add. + * @param w + * The observer to add. */ void addObserver(CombineObserver w) { observers.add(w); @@ -236,7 +248,8 @@ void addObserver(CombineObserver w) { /** * Receive notification of a Observer completing its iterations. * - * @param w The observer that has completed. + * @param w + * The observer that has completed. */ void complete(CombineObserver w) { int completed = numCompleted.incrementAndGet(); @@ -280,22 +293,22 @@ void next(CombineObserver w, T arg) { // remember this as the latest value for this observer latestValue.put(w, arg); - + if (latestValue.size() < observers.size()) { - // we don't have a value yet for each observer to combine, so we don't have a combined value yet either - return; + // we don't have a value yet for each observer to combine, so we don't have a combined value yet either + return; } - + Object[] argsToCombineLatest = new Object[observers.size()]; int i = 0; for (CombineObserver _w : observers) { argsToCombineLatest[i++] = latestValue.get(_w); } - + try { R combinedValue = combineLatestFunction.call(argsToCombineLatest); observer.onNext(combinedValue); - } catch(Throwable ex) { + } catch (Throwable ex) { observer.onError(ex); } } @@ -305,7 +318,7 @@ public Subscription onSubscribe(Observer observer) { if (this.observer != null) { throw new IllegalStateException("Only one Observer can subscribe to this Observable."); } - + SafeObservableSubscription subscription = new SafeObservableSubscription(new Subscription() { @Override public void unsubscribe() { diff --git a/rxjava-core/src/main/java/rx/operators/OperationConcat.java b/rxjava-core/src/main/java/rx/operators/OperationConcat.java index 4488ddf177..9838a8073b 100644 --- a/rxjava-core/src/main/java/rx/operators/OperationConcat.java +++ b/rxjava-core/src/main/java/rx/operators/OperationConcat.java @@ -15,15 +15,15 @@ */ package rx.operators; +import java.util.Queue; +import java.util.concurrent.ConcurrentLinkedQueue; +import java.util.concurrent.atomic.AtomicBoolean; + import rx.Observable; import rx.Observable.OnSubscribeFunc; import rx.Observer; import rx.Subscription; -import java.util.Queue; -import java.util.concurrent.ConcurrentLinkedQueue; -import java.util.concurrent.atomic.AtomicBoolean; - /** * Returns an Observable that emits the items emitted by two or more Observables, one after the * other. diff --git a/rxjava-core/src/main/java/rx/operators/OperationDebounce.java b/rxjava-core/src/main/java/rx/operators/OperationDebounce.java index ebbcbc8ad1..3dbdd81f20 100644 --- a/rxjava-core/src/main/java/rx/operators/OperationDebounce.java +++ b/rxjava-core/src/main/java/rx/operators/OperationDebounce.java @@ -15,6 +15,9 @@ */ package rx.operators; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicReference; + import rx.Observable; import rx.Observable.OnSubscribeFunc; import rx.Observer; @@ -24,9 +27,6 @@ import rx.util.functions.Action0; import rx.util.functions.Func1; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicReference; - /** * This operation is used to filter out bursts of events. This is done by ignoring the events from an observable which are too * quickly followed up with other values. Values which are not followed up by other values within the specified timeout are published diff --git a/rxjava-core/src/main/java/rx/operators/OperationDefaultIfEmpty.java b/rxjava-core/src/main/java/rx/operators/OperationDefaultIfEmpty.java index cfe7f27a2f..7c08aca675 100644 --- a/rxjava-core/src/main/java/rx/operators/OperationDefaultIfEmpty.java +++ b/rxjava-core/src/main/java/rx/operators/OperationDefaultIfEmpty.java @@ -14,7 +14,7 @@ public class OperationDefaultIfEmpty { /** * Returns the elements of the specified sequence or the specified default * value in a singleton sequence if the sequence is empty. - * + * * @param source * The sequence to return the specified value for if it is empty. * @param defaultValue diff --git a/rxjava-core/src/main/java/rx/operators/OperationDistinct.java b/rxjava-core/src/main/java/rx/operators/OperationDistinct.java index 9c0bccce2c..d2db484254 100644 --- a/rxjava-core/src/main/java/rx/operators/OperationDistinct.java +++ b/rxjava-core/src/main/java/rx/operators/OperationDistinct.java @@ -15,6 +15,12 @@ */ package rx.operators; +import java.util.ArrayList; +import java.util.Comparator; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + import rx.Observable; import rx.Observable.OnSubscribeFunc; import rx.Observer; @@ -24,18 +30,17 @@ import rx.util.functions.Func1; import rx.util.functions.Functions; -import java.util.*; - /** * Returns an Observable that emits all distinct items emitted by the source. * - * Be careful with this operation when using infinite or very large observables + * Be careful with this operation when using infinite or very large observables * as it has to store all distinct values it has received. */ public final class OperationDistinct { /** * Returns an Observable that emits all distinct items emitted by the source + * * @param source * The source Observable to emit the distinct items for. * @return A subscription function for creating the target Observable. @@ -43,9 +48,10 @@ public final class OperationDistinct { public static OnSubscribeFunc distinct(Observable source, Func1 keySelector) { return new Distinct(source, keySelector); } - + /** * Returns an Observable that emits all distinct items emitted by the source + * * @param source * The source Observable to emit the distinct items for. * @param equalityComparator @@ -53,11 +59,12 @@ public static OnSubscribeFunc distinct(Observable source, * @return A subscription function for creating the target Observable. */ public static OnSubscribeFunc distinct(Observable source, Comparator equalityComparator) { - return new DistinctWithComparator(source, Functions.identity(), equalityComparator); + return new DistinctWithComparator(source, Functions. identity(), equalityComparator); } - + /** * Returns an Observable that emits all distinct items emitted by the source + * * @param source * The source Observable to emit the distinct items for. * @param equalityComparator @@ -67,21 +74,22 @@ public static OnSubscribeFunc distinct(Observable source, Co public static OnSubscribeFunc distinct(Observable source, Func1 keySelector, Comparator equalityComparator) { return new DistinctWithComparator(source, keySelector, equalityComparator); } - + /** * Returns an Observable that emits all distinct items emitted by the source + * * @param source * The source Observable to emit the distinct items for. * @return A subscription function for creating the target Observable. */ public static OnSubscribeFunc distinct(Observable source) { - return new Distinct(source, Functions.identity()); + return new Distinct(source, Functions. identity()); } - + private static class Distinct implements OnSubscribeFunc { private final Observable source; private final Func1 keySelector; - + private Distinct(Observable source, Func1 keySelector) { this.source = source; this.keySelector = keySelector; @@ -91,7 +99,7 @@ private Distinct(Observable source, Func1 k public Subscription onSubscribe(final Observer observer) { final Subscription sourceSub = source.subscribe(new Observer() { private final Set emittedKeys = new HashSet(); - + @Override public void onCompleted() { observer.onCompleted(); @@ -111,7 +119,7 @@ public void onNext(T next) { } } }); - + return Subscriptions.create(new Action0() { @Override public void call() { @@ -120,12 +128,12 @@ public void call() { }); } } - + private static class DistinctWithComparator implements OnSubscribeFunc { private final Observable source; private final Func1 keySelector; private final Comparator equalityComparator; - + private DistinctWithComparator(Observable source, Func1 keySelector, Comparator equalityComparator) { this.source = source; this.keySelector = keySelector; @@ -135,10 +143,10 @@ private DistinctWithComparator(Observable source, Func1 observer) { final Subscription sourceSub = source.subscribe(new Observer() { - + // due to the totally arbitrary equality comparator, we can't use anything more efficient than lists here private final List emittedKeys = new ArrayList(); - + @Override public void onCompleted() { observer.onCompleted(); @@ -157,9 +165,9 @@ public void onNext(T next) { observer.onNext(next); } } - + private boolean alreadyEmitted(U newKey) { - for (U key: emittedKeys) { + for (U key : emittedKeys) { if (equalityComparator.compare(key, newKey) == 0) { return true; } @@ -167,7 +175,7 @@ private boolean alreadyEmitted(U newKey) { return false; } }); - + return Subscriptions.create(new Action0() { @Override public void call() { diff --git a/rxjava-core/src/main/java/rx/operators/OperationDistinctUntilChanged.java b/rxjava-core/src/main/java/rx/operators/OperationDistinctUntilChanged.java index d1ea86b653..eb1d6ed083 100644 --- a/rxjava-core/src/main/java/rx/operators/OperationDistinctUntilChanged.java +++ b/rxjava-core/src/main/java/rx/operators/OperationDistinctUntilChanged.java @@ -15,6 +15,8 @@ */ package rx.operators; +import java.util.Comparator; + import rx.Observable; import rx.Observable.OnSubscribeFunc; import rx.Observer; @@ -24,8 +26,6 @@ import rx.util.functions.Func1; import rx.util.functions.Functions; -import java.util.Comparator; - /** * Returns an Observable that emits all sequentially distinct items emitted by the source. */ @@ -33,6 +33,7 @@ public final class OperationDistinctUntilChanged { /** * Returns an Observable that emits all sequentially distinct items emitted by the source. + * * @param source * The source Observable to emit the sequentially distinct items for. * @param equalityComparator @@ -40,11 +41,12 @@ public final class OperationDistinctUntilChanged { * @return A subscription function for creating the target Observable. */ public static OnSubscribeFunc distinctUntilChanged(Observable source, Comparator equalityComparator) { - return new DistinctUntilChanged(source, Functions.identity(), equalityComparator); + return new DistinctUntilChanged(source, Functions. identity(), equalityComparator); } - + /** * Returns an Observable that emits all sequentially distinct items emitted by the source. + * * @param source * The source Observable to emit the sequentially distinct items for. * @param keySelector @@ -56,9 +58,10 @@ public static OnSubscribeFunc distinctUntilChanged(Observable OnSubscribeFunc distinctUntilChanged(Observable source, Func1 keySelector, Comparator equalityComparator) { return new DistinctUntilChanged(source, keySelector, equalityComparator); } - + /** * Returns an Observable that emits all sequentially distinct items emitted by the source. + * * @param source * The source Observable to emit the sequentially distinct items for. * @param keySelector @@ -68,15 +71,16 @@ public static OnSubscribeFunc distinctUntilChanged(Observable OnSubscribeFunc distinctUntilChanged(Observable source, Func1 keySelector) { return new DistinctUntilChanged(source, keySelector, new DefaultEqualityComparator()); } - + /** * Returns an Observable that emits all sequentially distinct items emitted by the source. + * * @param source * The source Observable to emit the sequentially distinct items for. * @return A subscription function for creating the target Observable. */ public static OnSubscribeFunc distinctUntilChanged(Observable source) { - return new DistinctUntilChanged(source, Functions.identity(), new DefaultEqualityComparator()); + return new DistinctUntilChanged(source, Functions. identity(), new DefaultEqualityComparator()); } // does not define a useful ordering; it's only used for equality tests here @@ -90,12 +94,12 @@ public int compare(T t1, T t2) { } } } - + private static class DistinctUntilChanged implements OnSubscribeFunc { private final Observable source; private final Func1 keySelector; private final Comparator equalityComparator; - + private DistinctUntilChanged(Observable source, Func1 keySelector, Comparator equalityComparator) { this.source = source; this.keySelector = keySelector; @@ -107,7 +111,7 @@ public Subscription onSubscribe(final Observer observer) { final Subscription sourceSub = source.subscribe(new Observer() { private U lastEmittedKey; private boolean hasEmitted; - + @Override public void onCompleted() { observer.onCompleted(); @@ -131,7 +135,7 @@ public void onNext(T next) { } } }); - + return Subscriptions.create(new Action0() { @Override public void call() { diff --git a/rxjava-core/src/main/java/rx/operators/OperationElementAt.java b/rxjava-core/src/main/java/rx/operators/OperationElementAt.java index c1310bc013..3001043c80 100644 --- a/rxjava-core/src/main/java/rx/operators/OperationElementAt.java +++ b/rxjava-core/src/main/java/rx/operators/OperationElementAt.java @@ -15,13 +15,13 @@ */ package rx.operators; +import java.util.concurrent.atomic.AtomicInteger; + import rx.Observable; import rx.Observable.OnSubscribeFunc; import rx.Observer; import rx.Subscription; -import java.util.concurrent.atomic.AtomicInteger; - /** * Returns the element at a specified index in a sequence. */ diff --git a/rxjava-core/src/main/java/rx/operators/OperationFinally.java b/rxjava-core/src/main/java/rx/operators/OperationFinally.java index 6e4d58768a..f8237cbb20 100644 --- a/rxjava-core/src/main/java/rx/operators/OperationFinally.java +++ b/rxjava-core/src/main/java/rx/operators/OperationFinally.java @@ -1,12 +1,12 @@ /** * Copyright 2013 Netflix, Inc. - * + * * 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. @@ -33,14 +33,16 @@ public final class OperationFinally { /** * Call a given action when a sequence completes (with or without an - * exception). The returned observable is exactly as threadsafe as the + * exception). The returned observable is exactly as threadsafe as the * source observable. *

    * Note that "finally" is a Java reserved word and cannot be an identifier, * so we use "finallyDo". - * - * @param sequence An observable sequence of elements - * @param action An action to be taken when the sequence is complete or throws an exception + * + * @param sequence + * An observable sequence of elements + * @param action + * An action to be taken when the sequence is complete or throws an exception * @return An observable sequence with the same elements as the input. * After the last element is consumed (and {@link Observer#onCompleted} has been called), * or after an exception is thrown (and {@link Observer#onError} has been called), diff --git a/rxjava-core/src/main/java/rx/operators/OperationFirstOrDefault.java b/rxjava-core/src/main/java/rx/operators/OperationFirstOrDefault.java index 66dcb6e90d..1a37d68d73 100644 --- a/rxjava-core/src/main/java/rx/operators/OperationFirstOrDefault.java +++ b/rxjava-core/src/main/java/rx/operators/OperationFirstOrDefault.java @@ -15,6 +15,10 @@ */ package rx.operators; +import static rx.util.functions.Functions.*; + +import java.util.concurrent.atomic.AtomicBoolean; + import rx.Observable; import rx.Observable.OnSubscribeFunc; import rx.Observer; @@ -23,10 +27,6 @@ import rx.util.functions.Action0; import rx.util.functions.Func1; -import java.util.concurrent.atomic.AtomicBoolean; - -import static rx.util.functions.Functions.alwaysTrue; - /** * Returns an Observable that emits the first item emitted by the source * Observable, or a default value if the source emits nothing. @@ -35,7 +35,7 @@ public final class OperationFirstOrDefault { /** * Returns an Observable that emits the first item emitted by the source - * Observable that satisfies the given condition, + * Observable that satisfies the given condition, * or a default value if the source emits no items that satisfy the given condition. * * @param source @@ -49,7 +49,7 @@ public final class OperationFirstOrDefault { public static OnSubscribeFunc firstOrDefault(Observable source, Func1 predicate, T defaultValue) { return new FirstOrElse(source, predicate, defaultValue); } - + /** * Returns an Observable that emits the first item emitted by the source * Observable, or a default value if the source emits nothing. @@ -79,7 +79,7 @@ private FirstOrElse(Observable source, Func1 pr public Subscription onSubscribe(final Observer observer) { final Subscription sourceSub = source.subscribe(new Observer() { private final AtomicBoolean hasEmitted = new AtomicBoolean(false); - + @Override public void onCompleted() { if (!hasEmitted.get()) { @@ -107,7 +107,7 @@ public void onNext(T next) { } } }); - + return Subscriptions.create(new Action0() { @Override public void call() { diff --git a/rxjava-core/src/main/java/rx/operators/OperationGroupBy.java b/rxjava-core/src/main/java/rx/operators/OperationGroupBy.java index e4311c5421..a30b97523f 100644 --- a/rxjava-core/src/main/java/rx/operators/OperationGroupBy.java +++ b/rxjava-core/src/main/java/rx/operators/OperationGroupBy.java @@ -15,6 +15,11 @@ */ package rx.operators; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.atomic.AtomicReference; + import rx.Observable; import rx.Observable.OnSubscribeFunc; import rx.Observer; @@ -23,11 +28,6 @@ import rx.util.functions.Func1; import rx.util.functions.Functions; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.atomic.AtomicBoolean; -import java.util.concurrent.atomic.AtomicInteger; -import java.util.concurrent.atomic.AtomicReference; - /** * Groups the items emitted by an Observable according to a specified criterion, and emits these * grouped items as Observables, one Observable per group. @@ -161,7 +161,7 @@ private void unsubscribeKey(K key) { private static class GroupedSubject extends GroupedObservable implements Observer { static GroupedSubject create(final K key, final GroupBy parent) { - final AtomicReference> subscribedObserver = new AtomicReference>(OperationGroupBy.emptyObserver()); + final AtomicReference> subscribedObserver = new AtomicReference>(OperationGroupBy. emptyObserver()); return new GroupedSubject(key, new OnSubscribeFunc() { private final SafeObservableSubscription subscription = new SafeObservableSubscription(); @@ -177,7 +177,7 @@ public Subscription onSubscribe(Observer observer) { @Override public void unsubscribe() { // we remove the Observer so we stop emitting further events (they will be ignored if parent continues to send) - subscribedObserver.set(OperationGroupBy.emptyObserver()); + subscribedObserver.set(OperationGroupBy. emptyObserver()); // now we need to notify the parent that we're unsubscribed parent.unsubscribeKey(key); } @@ -210,18 +210,18 @@ public void onNext(T v) { } - private static Observer emptyObserver() { + private static Observer emptyObserver() { return new Observer() { @Override public void onCompleted() { // do nothing } - + @Override public void onError(Throwable e) { // do nothing } - + @Override public void onNext(T t) { // do nothing diff --git a/rxjava-core/src/main/java/rx/operators/OperationInterval.java b/rxjava-core/src/main/java/rx/operators/OperationInterval.java index 0c767eada7..7e1be94991 100644 --- a/rxjava-core/src/main/java/rx/operators/OperationInterval.java +++ b/rxjava-core/src/main/java/rx/operators/OperationInterval.java @@ -15,6 +15,8 @@ */ package rx.operators; +import java.util.concurrent.TimeUnit; + import rx.Observable.OnSubscribeFunc; import rx.Observer; import rx.Scheduler; @@ -23,8 +25,6 @@ import rx.subscriptions.Subscriptions; import rx.util.functions.Action0; -import java.util.concurrent.TimeUnit; - /** * Returns an observable sequence that produces a value after each period. * The value starts at 0 and counts up each period. @@ -55,7 +55,7 @@ private static class Interval implements OnSubscribeFunc { private final long period; private final TimeUnit unit; private final Scheduler scheduler; - + private long currentValue; private Interval(long period, TimeUnit unit, Scheduler scheduler) { @@ -73,7 +73,7 @@ public void call() { currentValue++; } }, period, period, unit); - + return Subscriptions.create(new Action0() { @Override public void call() { diff --git a/rxjava-core/src/main/java/rx/operators/OperationMap.java b/rxjava-core/src/main/java/rx/operators/OperationMap.java index f2543326f2..d78b5dc6ef 100644 --- a/rxjava-core/src/main/java/rx/operators/OperationMap.java +++ b/rxjava-core/src/main/java/rx/operators/OperationMap.java @@ -46,11 +46,11 @@ public final class OperationMap { */ public static OnSubscribeFunc map(final Observable sequence, final Func1 func) { return mapWithIndex(sequence, new Func2() { - @Override - public R call(T value, @SuppressWarnings("unused") Integer unused) { - return func.call(value); - } - }); + @Override + public R call(T value, @SuppressWarnings("unused") Integer unused) { + return func.call(value); + } + }); } /** @@ -60,7 +60,7 @@ public R call(T value, @SuppressWarnings("unused") Integer unused) { * @param sequence * the input sequence. * @param func - * a function to apply to each item in the sequence. The function gets the index of the emitted item + * a function to apply to each item in the sequence. The function gets the index of the emitted item * as additional parameter. * @param * the type of the input sequence. diff --git a/rxjava-core/src/main/java/rx/operators/OperationMerge.java b/rxjava-core/src/main/java/rx/operators/OperationMerge.java index 4f98439292..12619e9176 100644 --- a/rxjava-core/src/main/java/rx/operators/OperationMerge.java +++ b/rxjava-core/src/main/java/rx/operators/OperationMerge.java @@ -15,16 +15,16 @@ */ package rx.operators; +import java.util.Arrays; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.atomic.AtomicBoolean; + import rx.Observable; import rx.Observable.OnSubscribeFunc; import rx.Observer; import rx.Subscription; import rx.subscriptions.CompositeSubscription; -import java.util.Arrays; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.atomic.AtomicBoolean; - /** * Flattens a list of Observables into one Observable sequence, without any transformation. *

    diff --git a/rxjava-core/src/main/java/rx/operators/OperationMergeDelayError.java b/rxjava-core/src/main/java/rx/operators/OperationMergeDelayError.java index 5f1af2ff80..dbca17522d 100644 --- a/rxjava-core/src/main/java/rx/operators/OperationMergeDelayError.java +++ b/rxjava-core/src/main/java/rx/operators/OperationMergeDelayError.java @@ -15,17 +15,17 @@ */ package rx.operators; +import java.util.List; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentLinkedQueue; +import java.util.concurrent.atomic.AtomicBoolean; + import rx.Observable; import rx.Observable.OnSubscribeFunc; import rx.Observer; import rx.Subscription; import rx.util.CompositeException; -import java.util.List; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentLinkedQueue; -import java.util.concurrent.atomic.AtomicBoolean; - /** * This behaves like {@link OperationMerge} except that if any of the merged Observables notify of * an error via onError, mergeDelayError will refrain from propagating that error diff --git a/rxjava-core/src/main/java/rx/operators/OperationMostRecent.java b/rxjava-core/src/main/java/rx/operators/OperationMostRecent.java index 003b54aaad..15406aeece 100644 --- a/rxjava-core/src/main/java/rx/operators/OperationMostRecent.java +++ b/rxjava-core/src/main/java/rx/operators/OperationMostRecent.java @@ -15,14 +15,14 @@ */ package rx.operators; -import rx.Observable; -import rx.Observer; -import rx.util.Exceptions; - import java.util.Iterator; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicReference; +import rx.Observable; +import rx.Observer; +import rx.util.Exceptions; + /** * Returns an Iterable that always returns the item most recently emitted by an Observable, or a * seed value if no item has yet been emitted. diff --git a/rxjava-core/src/main/java/rx/operators/OperationMulticast.java b/rxjava-core/src/main/java/rx/operators/OperationMulticast.java index b93f9917f1..b634b2dbac 100644 --- a/rxjava-core/src/main/java/rx/operators/OperationMulticast.java +++ b/rxjava-core/src/main/java/rx/operators/OperationMulticast.java @@ -1,12 +1,12 @@ /** * Copyright 2013 Netflix, Inc. - * + * * 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. @@ -67,7 +67,6 @@ public void onNext(T args) { } } - return new Subscription() { @Override public void unsubscribe() { @@ -81,6 +80,5 @@ public void unsubscribe() { }; } - } } diff --git a/rxjava-core/src/main/java/rx/operators/OperationNext.java b/rxjava-core/src/main/java/rx/operators/OperationNext.java index a4812881e3..4f5e9dfd31 100644 --- a/rxjava-core/src/main/java/rx/operators/OperationNext.java +++ b/rxjava-core/src/main/java/rx/operators/OperationNext.java @@ -15,17 +15,17 @@ */ package rx.operators; -import rx.Notification; -import rx.Observable; -import rx.Observer; -import rx.util.Exceptions; - import java.util.Iterator; import java.util.NoSuchElementException; import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.BlockingQueue; import java.util.concurrent.atomic.AtomicBoolean; +import rx.Notification; +import rx.Observable; +import rx.Observer; +import rx.util.Exceptions; + /** * Returns an Iterable that blocks until the Observable emits another item, then returns that item. *

    @@ -63,17 +63,17 @@ private NextIterator(NextObserver observer) { @Override public boolean hasNext() { - if(error != null) { + if (error != null) { // If any error has already been thrown, throw it again. throw Exceptions.propagate(error); } // Since an iterator should not be used in different thread, // so we do not need any synchronization. - if(hasNext == false) { + if (hasNext == false) { // the iterator has reached the end. return false; } - if(isNextConsumed == false) { + if (isNextConsumed == false) { // next has not been used yet. return true; } @@ -83,7 +83,7 @@ public boolean hasNext() { private boolean moveToNext() { try { Notification nextNotification = observer.takeNext(); - if(nextNotification.isOnNext()) { + if (nextNotification.isOnNext()) { isNextConsumed = false; next = nextNotification.getValue(); return true; @@ -91,10 +91,10 @@ private boolean moveToNext() { // If an observable is completed or fails, // hasNext() always return false. hasNext = false; - if(nextNotification.isOnCompleted()) { + if (nextNotification.isOnCompleted()) { return false; } - if(nextNotification.isOnError()) { + if (nextNotification.isOnError()) { error = nextNotification.getThrowable(); throw Exceptions.propagate(error); } @@ -108,11 +108,11 @@ private boolean moveToNext() { @Override public T next() { - if(error != null) { + if (error != null) { // If any error has already been thrown, throw it again. throw Exceptions.propagate(error); } - if(hasNext()) { + if (hasNext()) { isNextConsumed = true; return next; } diff --git a/rxjava-core/src/main/java/rx/operators/OperationOnErrorResumeNextViaFunction.java b/rxjava-core/src/main/java/rx/operators/OperationOnErrorResumeNextViaFunction.java index 3f63463cf9..0122a8c5e1 100644 --- a/rxjava-core/src/main/java/rx/operators/OperationOnErrorResumeNextViaFunction.java +++ b/rxjava-core/src/main/java/rx/operators/OperationOnErrorResumeNextViaFunction.java @@ -15,6 +15,9 @@ */ package rx.operators; +import java.util.Arrays; +import java.util.concurrent.atomic.AtomicReference; + import rx.Observable; import rx.Observable.OnSubscribeFunc; import rx.Observer; @@ -22,9 +25,6 @@ import rx.util.CompositeException; import rx.util.functions.Func1; -import java.util.Arrays; -import java.util.concurrent.atomic.AtomicReference; - /** * Instruct an Observable to pass control to another Observable (the return value of a function) * rather than invoking onError if it encounters an error. diff --git a/rxjava-core/src/main/java/rx/operators/OperationOnErrorResumeNextViaObservable.java b/rxjava-core/src/main/java/rx/operators/OperationOnErrorResumeNextViaObservable.java index 8e09ce027a..6c14d3618a 100644 --- a/rxjava-core/src/main/java/rx/operators/OperationOnErrorResumeNextViaObservable.java +++ b/rxjava-core/src/main/java/rx/operators/OperationOnErrorResumeNextViaObservable.java @@ -15,13 +15,13 @@ */ package rx.operators; +import java.util.concurrent.atomic.AtomicReference; + import rx.Observable; import rx.Observable.OnSubscribeFunc; import rx.Observer; import rx.Subscription; -import java.util.concurrent.atomic.AtomicReference; - /** * Instruct an Observable to pass control to another Observable rather than invoking * onError if it encounters an error. @@ -67,7 +67,7 @@ public Subscription onSubscribe(final Observer observer) { subscription.wrap(originalSequence.subscribe(new Observer() { public void onNext(T value) { // forward the successful calls unless resumed - if (subscriptionRef.get()==subscription) + if (subscriptionRef.get() == subscription) observer.onNext(value); } @@ -92,7 +92,7 @@ public void onError(Throwable ex) { public void onCompleted() { // forward the successful calls unless resumed - if (subscriptionRef.get()==subscription) + if (subscriptionRef.get() == subscription) observer.onCompleted(); } })); diff --git a/rxjava-core/src/main/java/rx/operators/OperationOnErrorReturn.java b/rxjava-core/src/main/java/rx/operators/OperationOnErrorReturn.java index fd04d078b1..d5d6a9fbc7 100644 --- a/rxjava-core/src/main/java/rx/operators/OperationOnErrorReturn.java +++ b/rxjava-core/src/main/java/rx/operators/OperationOnErrorReturn.java @@ -15,6 +15,9 @@ */ package rx.operators; +import java.util.Arrays; +import java.util.concurrent.atomic.AtomicReference; + import rx.Observable; import rx.Observable.OnSubscribeFunc; import rx.Observer; @@ -22,9 +25,6 @@ import rx.util.CompositeException; import rx.util.functions.Func1; -import java.util.Arrays; -import java.util.concurrent.atomic.AtomicReference; - /** * Instruct an Observable to emit a particular item to its Observer's onNext method * rather than invoking onError if it encounters an error. diff --git a/rxjava-core/src/main/java/rx/operators/OperationOnExceptionResumeNextViaObservable.java b/rxjava-core/src/main/java/rx/operators/OperationOnExceptionResumeNextViaObservable.java index 20e8fce867..864ba0730e 100644 --- a/rxjava-core/src/main/java/rx/operators/OperationOnExceptionResumeNextViaObservable.java +++ b/rxjava-core/src/main/java/rx/operators/OperationOnExceptionResumeNextViaObservable.java @@ -15,13 +15,13 @@ */ package rx.operators; +import java.util.concurrent.atomic.AtomicReference; + import rx.Observable; import rx.Observable.OnSubscribeFunc; import rx.Observer; import rx.Subscription; -import java.util.concurrent.atomic.AtomicReference; - /** * Instruct an Observable to pass control to another Observable rather than invoking * onError if it encounters an error of type {@link java.lang.Exception}. diff --git a/rxjava-core/src/main/java/rx/operators/OperationParallel.java b/rxjava-core/src/main/java/rx/operators/OperationParallel.java index 25a955e616..5a584ce370 100644 --- a/rxjava-core/src/main/java/rx/operators/OperationParallel.java +++ b/rxjava-core/src/main/java/rx/operators/OperationParallel.java @@ -15,6 +15,8 @@ */ package rx.operators; +import java.util.concurrent.atomic.AtomicInteger; + import rx.Observable; import rx.Scheduler; import rx.concurrency.Schedulers; @@ -22,8 +24,6 @@ import rx.util.functions.Func0; import rx.util.functions.Func1; -import java.util.concurrent.atomic.AtomicInteger; - /** * Identifies unit of work that can be executed in parallel on a given Scheduler. */ diff --git a/rxjava-core/src/main/java/rx/operators/OperationRefCount.java b/rxjava-core/src/main/java/rx/operators/OperationRefCount.java index 4617f3ac40..d19b700afd 100644 --- a/rxjava-core/src/main/java/rx/operators/OperationRefCount.java +++ b/rxjava-core/src/main/java/rx/operators/OperationRefCount.java @@ -1,12 +1,12 @@ /** * Copyright 2013 Netflix, Inc. - * + * * 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. diff --git a/rxjava-core/src/main/java/rx/operators/OperationRetry.java b/rxjava-core/src/main/java/rx/operators/OperationRetry.java index 864caf3c4e..430ef53ce4 100644 --- a/rxjava-core/src/main/java/rx/operators/OperationRetry.java +++ b/rxjava-core/src/main/java/rx/operators/OperationRetry.java @@ -16,6 +16,8 @@ * limitations under the License. */ +import java.util.concurrent.atomic.AtomicInteger; + import rx.Observable; import rx.Observable.OnSubscribeFunc; import rx.Observer; @@ -26,8 +28,6 @@ import rx.subscriptions.MultipleAssignmentSubscription; import rx.util.functions.Func2; -import java.util.concurrent.atomic.AtomicInteger; - public class OperationRetry { private static final int INFINITE_RETRY = -1; diff --git a/rxjava-core/src/main/java/rx/operators/OperationSample.java b/rxjava-core/src/main/java/rx/operators/OperationSample.java index 32c58b1f04..89da00e5fb 100644 --- a/rxjava-core/src/main/java/rx/operators/OperationSample.java +++ b/rxjava-core/src/main/java/rx/operators/OperationSample.java @@ -15,6 +15,10 @@ */ package rx.operators; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicReference; + import rx.Observable; import rx.Observable.OnSubscribeFunc; import rx.Observer; @@ -24,10 +28,6 @@ import rx.subscriptions.Subscriptions; import rx.util.functions.Action0; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicBoolean; -import java.util.concurrent.atomic.AtomicReference; - /** * Returns an Observable that emits the results of sampling the items emitted by the source * Observable at a specified time interval. @@ -49,16 +49,16 @@ public static OnSubscribeFunc sample(final Observable source public static OnSubscribeFunc sample(final Observable source, long period, TimeUnit unit, Scheduler scheduler) { return new Sample(source, period, unit, scheduler); } - + private static class Sample implements OnSubscribeFunc { private final Observable source; private final long period; private final TimeUnit unit; private final Scheduler scheduler; - + private final AtomicBoolean hasValue = new AtomicBoolean(); private final AtomicReference latestValue = new AtomicReference(); - + private Sample(Observable source, long interval, TimeUnit unit, Scheduler scheduler) { this.source = source; this.period = interval; @@ -71,11 +71,13 @@ public Subscription onSubscribe(final Observer observer) { Observable clock = Observable.create(OperationInterval.interval(period, unit, scheduler)); final Subscription clockSubscription = clock.subscribe(new Observer() { @Override - public void onCompleted() { /* the clock never completes */ } - + public void onCompleted() { /* the clock never completes */ + } + @Override - public void onError(Throwable e) { /* the clock has no errors */ } - + public void onError(Throwable e) { /* the clock has no errors */ + } + @Override public void onNext(Long tick) { if (hasValue.get()) { @@ -83,27 +85,27 @@ public void onNext(Long tick) { } } }); - + final Subscription sourceSubscription = source.subscribe(new Observer() { @Override public void onCompleted() { clockSubscription.unsubscribe(); observer.onCompleted(); } - + @Override public void onError(Throwable e) { clockSubscription.unsubscribe(); observer.onError(e); } - + @Override public void onNext(T value) { latestValue.set(value); hasValue.set(true); } }); - + return Subscriptions.create(new Action0() { @Override public void call() { diff --git a/rxjava-core/src/main/java/rx/operators/OperationScan.java b/rxjava-core/src/main/java/rx/operators/OperationScan.java index 4d0cfc95d0..a5eedfee46 100644 --- a/rxjava-core/src/main/java/rx/operators/OperationScan.java +++ b/rxjava-core/src/main/java/rx/operators/OperationScan.java @@ -46,7 +46,8 @@ public final class OperationScan { * An accumulator function to be invoked on each element from the sequence. * * @return An observable sequence whose elements are the result of accumulating the output from the list of Observables. - * @see Observable.Scan(TSource, TAccumulate) Method (IObservable(TSource), TAccumulate, Func(TAccumulate, TSource, TAccumulate)) + * @see Observable.Scan(TSource, TAccumulate) Method (IObservable(TSource), TAccumulate, Func(TAccumulate, TSource, + * TAccumulate)) */ public static OnSubscribeFunc scan(Observable sequence, R initialValue, Func2 accumulator) { return new Accumulator(sequence, initialValue, accumulator); @@ -70,18 +71,18 @@ public static OnSubscribeFunc scan(Observable sequence, Func private static class AccuWithoutInitialValue implements OnSubscribeFunc { private final Observable sequence; private final Func2 accumulatorFunction; - + private AccumulatingObserver accumulatingObserver; - + private AccuWithoutInitialValue(Observable sequence, Func2 accumulator) { this.sequence = sequence; this.accumulatorFunction = accumulator; } - + @Override public Subscription onSubscribe(final Observer observer) { return sequence.subscribe(new Observer() { - + // has to be synchronized so that the initial value is always sent only once. @Override public synchronized void onNext(T value) { @@ -92,7 +93,7 @@ public synchronized void onNext(T value) { accumulatingObserver.onNext(value); } } - + @Override public void onError(Throwable e) { observer.onError(e); @@ -105,7 +106,7 @@ public void onCompleted() { }); } } - + private static class Accumulator implements OnSubscribeFunc { private final Observable sequence; private final R initialValue; @@ -133,7 +134,7 @@ private static class AccumulatingObserver implements Observer { private AccumulatingObserver(Observer observer, R initialValue, Func2 accumulator) { this.observer = observer; this.accumulatorFunction = accumulator; - + this.acc = initialValue; } @@ -153,12 +154,12 @@ public synchronized void onNext(T value) { observer.onError(ex); } } - + @Override public void onError(Throwable e) { observer.onError(e); } - + @Override public void onCompleted() { observer.onCompleted(); diff --git a/rxjava-core/src/main/java/rx/operators/OperationSkip.java b/rxjava-core/src/main/java/rx/operators/OperationSkip.java index 63b873d826..4dc3359815 100644 --- a/rxjava-core/src/main/java/rx/operators/OperationSkip.java +++ b/rxjava-core/src/main/java/rx/operators/OperationSkip.java @@ -15,13 +15,13 @@ */ package rx.operators; +import java.util.concurrent.atomic.AtomicInteger; + import rx.Observable; import rx.Observable.OnSubscribeFunc; import rx.Observer; import rx.Subscription; -import java.util.concurrent.atomic.AtomicInteger; - /** * Returns an Observable that skips the first num items emitted by the source * Observable. diff --git a/rxjava-core/src/main/java/rx/operators/OperationSkipLast.java b/rxjava-core/src/main/java/rx/operators/OperationSkipLast.java index 9bd8253392..f3cb462e55 100644 --- a/rxjava-core/src/main/java/rx/operators/OperationSkipLast.java +++ b/rxjava-core/src/main/java/rx/operators/OperationSkipLast.java @@ -15,15 +15,15 @@ */ package rx.operators; +import java.util.Deque; +import java.util.LinkedList; +import java.util.concurrent.locks.ReentrantLock; + import rx.Observable; import rx.Observable.OnSubscribeFunc; import rx.Observer; import rx.Subscription; -import java.util.Deque; -import java.util.LinkedList; -import java.util.concurrent.locks.ReentrantLock; - /** * Bypasses a specified number of elements at the end of an observable sequence. */ @@ -37,7 +37,7 @@ public class OperationSkipLast { * count elements. As more elements are received, elements are taken from * the front of the queue and produced on the result sequence. This causes * elements to be delayed. - * + * * @param source * the source sequence. * @param count @@ -45,7 +45,7 @@ public class OperationSkipLast { * sequence. * @return An observable sequence containing the source sequence elements * except for the bypassed ones at the end. - * + * * @throws IndexOutOfBoundsException * count is less than zero. */ diff --git a/rxjava-core/src/main/java/rx/operators/OperationSkipWhile.java b/rxjava-core/src/main/java/rx/operators/OperationSkipWhile.java index bf1528d8a2..6bc747e9bf 100644 --- a/rxjava-core/src/main/java/rx/operators/OperationSkipWhile.java +++ b/rxjava-core/src/main/java/rx/operators/OperationSkipWhile.java @@ -15,6 +15,9 @@ */ package rx.operators; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicInteger; + import rx.Observable; import rx.Observable.OnSubscribeFunc; import rx.Observer; @@ -22,9 +25,6 @@ import rx.util.functions.Func1; import rx.util.functions.Func2; -import java.util.concurrent.atomic.AtomicBoolean; -import java.util.concurrent.atomic.AtomicInteger; - /** * Skips any emitted source items as long as the specified condition holds true. Emits all further source items * as soon as the condition becomes false. @@ -33,7 +33,7 @@ public final class OperationSkipWhile { public static OnSubscribeFunc skipWhileWithIndex(Observable source, Func2 predicate) { return new SkipWhile(source, predicate); } - + public static OnSubscribeFunc skipWhile(Observable source, final Func1 predicate) { return new SkipWhile(source, new Func2() { @Override @@ -48,7 +48,7 @@ private static class SkipWhile implements OnSubscribeFunc { private final Func2 predicate; private final AtomicBoolean skipping = new AtomicBoolean(true); private final AtomicInteger index = new AtomicInteger(0); - + SkipWhile(Observable source, Func2 pred) { this.source = source; this.predicate = pred; @@ -86,7 +86,7 @@ public void onNext(T next) { observer.onNext(next); } else { } - } catch(Throwable t) { + } catch (Throwable t) { observer.onError(t); } } diff --git a/rxjava-core/src/main/java/rx/operators/OperationSubscribeOn.java b/rxjava-core/src/main/java/rx/operators/OperationSubscribeOn.java index f1cac4fe9d..fe7aa00216 100644 --- a/rxjava-core/src/main/java/rx/operators/OperationSubscribeOn.java +++ b/rxjava-core/src/main/java/rx/operators/OperationSubscribeOn.java @@ -1,12 +1,12 @@ /** * Copyright 2013 Netflix, Inc. - * + * * 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. diff --git a/rxjava-core/src/main/java/rx/operators/OperationSum.java b/rxjava-core/src/main/java/rx/operators/OperationSum.java index cc34f79520..fef81a2625 100644 --- a/rxjava-core/src/main/java/rx/operators/OperationSum.java +++ b/rxjava-core/src/main/java/rx/operators/OperationSum.java @@ -20,6 +20,7 @@ /** * A few operators for implementing the sum operation. + * * @see MSDN: Observable.Sum */ public final class OperationSum { diff --git a/rxjava-core/src/main/java/rx/operators/OperationSwitch.java b/rxjava-core/src/main/java/rx/operators/OperationSwitch.java index 25d94a714a..9094a2affd 100644 --- a/rxjava-core/src/main/java/rx/operators/OperationSwitch.java +++ b/rxjava-core/src/main/java/rx/operators/OperationSwitch.java @@ -33,14 +33,11 @@ public final class OperationSwitch { /** - * This function transforms an {@link Observable} sequence of - * {@link Observable} sequences into a single {@link Observable} sequence - * which produces values from the most recently published {@link Observable} - * . + * This function transforms an {@link Observable} sequence of {@link Observable} sequences into a single {@link Observable} sequence + * which produces values from the most recently published {@link Observable} . * * @param sequences - * The {@link Observable} sequence consisting of - * {@link Observable} sequences. + * The {@link Observable} sequence consisting of {@link Observable} sequences. * @return A {@link Func1} which does this transformation. */ public static OnSubscribeFunc switchDo(final Observable> sequences) { @@ -76,13 +73,13 @@ public Subscription onSubscribe(Observer observer) { private static class SwitchObserver implements Observer> { - private final Object gate; - private final Observer observer; - private final SafeObservableSubscription parent; + private final Object gate; + private final Observer observer; + private final SafeObservableSubscription parent; private final MultipleAssignmentSubscription child; - private long latest; - private boolean stopped; - private boolean hasLatest; + private long latest; + private boolean stopped; + private boolean hasLatest; public SwitchObserver(Observer observer, SafeObservableSubscription parent, MultipleAssignmentSubscription child) { diff --git a/rxjava-core/src/main/java/rx/operators/OperationSynchronize.java b/rxjava-core/src/main/java/rx/operators/OperationSynchronize.java index 4ec205f156..5ba8c0a98e 100644 --- a/rxjava-core/src/main/java/rx/operators/OperationSynchronize.java +++ b/rxjava-core/src/main/java/rx/operators/OperationSynchronize.java @@ -58,11 +58,11 @@ public static OnSubscribeFunc synchronize(Observable observa /** * Accepts an observable and wraps it in another observable which ensures that the resulting observable is well-behaved. * This is accomplished by acquiring a mutual-exclusion lock for the object provided as the lock parameter. - * + * * A well-behaved observable ensures onNext, onCompleted, or onError calls to its subscribers are * not interleaved, onCompleted and onError are only called once respectively, and no * onNext calls follow onCompleted and onError calls. - * + * * @param observable * @param lock * The lock object to synchronize each observer call on @@ -86,7 +86,7 @@ public Synchronize(Observable innerObservable, Object lock) { public Subscription onSubscribe(Observer observer) { SafeObservableSubscription subscription = new SafeObservableSubscription(); - if(lock == null) { + if (lock == null) { atomicObserver = new SynchronizedObserver(observer, subscription); } else { diff --git a/rxjava-core/src/main/java/rx/operators/OperationTake.java b/rxjava-core/src/main/java/rx/operators/OperationTake.java index 6448a628db..877ba4d5f3 100644 --- a/rxjava-core/src/main/java/rx/operators/OperationTake.java +++ b/rxjava-core/src/main/java/rx/operators/OperationTake.java @@ -15,14 +15,14 @@ */ package rx.operators; +import java.util.concurrent.atomic.AtomicInteger; + import rx.Observable; import rx.Observable.OnSubscribeFunc; import rx.Observer; import rx.Subscription; import rx.subscriptions.Subscriptions; -import java.util.concurrent.atomic.AtomicInteger; - /** * Returns an Observable that emits the first num items emitted by the source * Observable. diff --git a/rxjava-core/src/main/java/rx/operators/OperationTakeLast.java b/rxjava-core/src/main/java/rx/operators/OperationTakeLast.java index d608552315..d324f7ce42 100644 --- a/rxjava-core/src/main/java/rx/operators/OperationTakeLast.java +++ b/rxjava-core/src/main/java/rx/operators/OperationTakeLast.java @@ -15,15 +15,15 @@ */ package rx.operators; +import java.util.Deque; +import java.util.LinkedList; +import java.util.concurrent.locks.ReentrantLock; + import rx.Observable; import rx.Observable.OnSubscribeFunc; import rx.Observer; import rx.Subscription; -import java.util.Deque; -import java.util.LinkedList; -import java.util.concurrent.locks.ReentrantLock; - /** * Returns an Observable that emits the last count items emitted by the source * Observable. diff --git a/rxjava-core/src/main/java/rx/operators/OperationTakeWhile.java b/rxjava-core/src/main/java/rx/operators/OperationTakeWhile.java index b56029bcae..479badf6a6 100644 --- a/rxjava-core/src/main/java/rx/operators/OperationTakeWhile.java +++ b/rxjava-core/src/main/java/rx/operators/OperationTakeWhile.java @@ -15,6 +15,8 @@ */ package rx.operators; +import java.util.concurrent.atomic.AtomicInteger; + import rx.Observable; import rx.Observable.OnSubscribeFunc; import rx.Observer; @@ -22,8 +24,6 @@ import rx.util.functions.Func1; import rx.util.functions.Func2; -import java.util.concurrent.atomic.AtomicInteger; - /** * Returns an Observable that emits items emitted by the source Observable as long as a specified * condition is true. diff --git a/rxjava-core/src/main/java/rx/operators/OperationThrottleFirst.java b/rxjava-core/src/main/java/rx/operators/OperationThrottleFirst.java index ebc6bf55d9..e21617a82c 100644 --- a/rxjava-core/src/main/java/rx/operators/OperationThrottleFirst.java +++ b/rxjava-core/src/main/java/rx/operators/OperationThrottleFirst.java @@ -15,6 +15,9 @@ */ package rx.operators; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicLong; + import rx.Observable; import rx.Observable.OnSubscribeFunc; import rx.Observer; @@ -23,9 +26,6 @@ import rx.concurrency.Schedulers; import rx.util.functions.Func1; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicLong; - /** * Throttle by windowing a stream and returning the first value in each window. */ diff --git a/rxjava-core/src/main/java/rx/operators/OperationTimeInterval.java b/rxjava-core/src/main/java/rx/operators/OperationTimeInterval.java index 874cb9dd39..2cd1860711 100644 --- a/rxjava-core/src/main/java/rx/operators/OperationTimeInterval.java +++ b/rxjava-core/src/main/java/rx/operators/OperationTimeInterval.java @@ -1,12 +1,12 @@ /** * Copyright 2013 Netflix, Inc. - * + * * 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. diff --git a/rxjava-core/src/main/java/rx/operators/OperationTimeout.java b/rxjava-core/src/main/java/rx/operators/OperationTimeout.java index 03f5e515ac..3df6cd2929 100644 --- a/rxjava-core/src/main/java/rx/operators/OperationTimeout.java +++ b/rxjava-core/src/main/java/rx/operators/OperationTimeout.java @@ -1,12 +1,12 @@ /** * Copyright 2013 Netflix, Inc. - * + * * 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. @@ -15,6 +15,11 @@ */ package rx.operators; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicLong; + import rx.Observable; import rx.Observer; import rx.Scheduler; @@ -24,11 +29,6 @@ import rx.util.functions.Action0; import rx.util.functions.Func0; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.TimeoutException; -import java.util.concurrent.atomic.AtomicBoolean; -import java.util.concurrent.atomic.AtomicLong; - public final class OperationTimeout { public static Observable.OnSubscribeFunc timeout(Observable source, long timeout, TimeUnit timeUnit, Scheduler scheduler) { return new Timeout(source, timeout, timeUnit, scheduler); diff --git a/rxjava-core/src/main/java/rx/operators/OperationToIterator.java b/rxjava-core/src/main/java/rx/operators/OperationToIterator.java index e7dcc308eb..59debafcb9 100644 --- a/rxjava-core/src/main/java/rx/operators/OperationToIterator.java +++ b/rxjava-core/src/main/java/rx/operators/OperationToIterator.java @@ -36,6 +36,7 @@ *

    * *

    + * * @see Issue #50 */ public class OperationToIterator { diff --git a/rxjava-core/src/main/java/rx/operators/OperationToObservableFuture.java b/rxjava-core/src/main/java/rx/operators/OperationToObservableFuture.java index af2f0b1a3f..875a0dc0d8 100644 --- a/rxjava-core/src/main/java/rx/operators/OperationToObservableFuture.java +++ b/rxjava-core/src/main/java/rx/operators/OperationToObservableFuture.java @@ -15,14 +15,14 @@ */ package rx.operators; +import java.util.concurrent.Future; +import java.util.concurrent.TimeUnit; + import rx.Observable.OnSubscribeFunc; import rx.Observer; import rx.Subscription; import rx.subscriptions.Subscriptions; -import java.util.concurrent.Future; -import java.util.concurrent.TimeUnit; - /** * Converts a Future into an Observable. *

    @@ -35,7 +35,7 @@ * Observable.subscribe(Observer) does nothing. */ public class OperationToObservableFuture { - static class ToObservableFuture implements OnSubscribeFunc { + /* package accessible for unit tests */static class ToObservableFuture implements OnSubscribeFunc { private final Future that; private final Long time; private final TimeUnit unit; diff --git a/rxjava-core/src/main/java/rx/operators/OperationToObservableList.java b/rxjava-core/src/main/java/rx/operators/OperationToObservableList.java index c798cf8cc1..b87a49fdd1 100644 --- a/rxjava-core/src/main/java/rx/operators/OperationToObservableList.java +++ b/rxjava-core/src/main/java/rx/operators/OperationToObservableList.java @@ -15,15 +15,15 @@ */ package rx.operators; +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.ConcurrentLinkedQueue; + import rx.Observable; import rx.Observable.OnSubscribeFunc; import rx.Observer; import rx.Subscription; -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.ConcurrentLinkedQueue; - /** * Returns an Observable that emits a single item, a list composed of all the items emitted by the * source Observable. @@ -56,6 +56,7 @@ public Subscription onSubscribe(final Observer> observer) { return that.subscribe(new Observer() { final ConcurrentLinkedQueue list = new ConcurrentLinkedQueue(); + public void onNext(T value) { // onNext can be concurrently executed so list must be thread-safe list.add(value); diff --git a/rxjava-core/src/main/java/rx/operators/OperationToObservableSortedList.java b/rxjava-core/src/main/java/rx/operators/OperationToObservableSortedList.java index cf3ffac636..cfc7ba35fa 100644 --- a/rxjava-core/src/main/java/rx/operators/OperationToObservableSortedList.java +++ b/rxjava-core/src/main/java/rx/operators/OperationToObservableSortedList.java @@ -15,18 +15,18 @@ */ package rx.operators; -import rx.Observable; -import rx.Observable.OnSubscribeFunc; -import rx.Observer; -import rx.Subscription; -import rx.util.functions.Func2; - import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.List; import java.util.concurrent.ConcurrentLinkedQueue; +import rx.Observable; +import rx.Observable.OnSubscribeFunc; +import rx.Observer; +import rx.Subscription; +import rx.util.functions.Func2; + /** * Return an Observable that emits the items emitted by the source Observable, in a sorted order * (each item emitted by the Observable must implement Comparable with respect to all other items diff --git a/rxjava-core/src/main/java/rx/operators/OperationWindow.java b/rxjava-core/src/main/java/rx/operators/OperationWindow.java index 61d1839f32..d7ff20e061 100644 --- a/rxjava-core/src/main/java/rx/operators/OperationWindow.java +++ b/rxjava-core/src/main/java/rx/operators/OperationWindow.java @@ -15,6 +15,8 @@ */ package rx.operators; +import java.util.concurrent.TimeUnit; + import rx.Observable; import rx.Observable.OnSubscribeFunc; import rx.Observer; @@ -26,8 +28,6 @@ import rx.util.functions.Func0; import rx.util.functions.Func1; -import java.util.concurrent.TimeUnit; - public final class OperationWindow extends ChunkedOperation { public static Func0> windowMaker() { @@ -37,7 +37,7 @@ public Window call() { return new Window(); } }; - } + } /** *

    This method creates a {@link rx.util.functions.Func1} object which represents the window operation. This operation takes @@ -63,7 +63,7 @@ public static OnSubscribeFunc> window(final Observable>() { @Override public Subscription onSubscribe(final Observer> observer) { - NonOverlappingChunks> windows = new NonOverlappingChunks>(observer, OperationWindow.windowMaker()); + NonOverlappingChunks> windows = new NonOverlappingChunks>(observer, OperationWindow. windowMaker()); ChunkCreator creator = new ObservableBasedSingleChunkCreator>(windows, windowClosingSelector); return source.subscribe(new ChunkObserver>(windows, observer, creator)); } @@ -100,7 +100,7 @@ public static OnSubscribeFunc> window(final Observable>() { @Override public Subscription onSubscribe(final Observer> observer) { - OverlappingChunks> windows = new OverlappingChunks>(observer, OperationWindow.windowMaker()); + OverlappingChunks> windows = new OverlappingChunks>(observer, OperationWindow. windowMaker()); ChunkCreator creator = new ObservableBasedMultiChunkCreator>(windows, windowOpenings, windowClosingSelector); return source.subscribe(new ChunkObserver>(windows, observer, creator)); } @@ -155,7 +155,7 @@ public static OnSubscribeFunc> window(final Observable>() { @Override public Subscription onSubscribe(final Observer> observer) { - Chunks> chunks = new SizeBasedChunks>(observer, OperationWindow.windowMaker(), count); + Chunks> chunks = new SizeBasedChunks>(observer, OperationWindow. windowMaker(), count); ChunkCreator creator = new SkippingChunkCreator>(chunks, skip); return source.subscribe(new ChunkObserver>(chunks, observer, creator)); } @@ -210,7 +210,7 @@ public static OnSubscribeFunc> window(final Observable>() { @Override public Subscription onSubscribe(final Observer> observer) { - NonOverlappingChunks> windows = new NonOverlappingChunks>(observer, OperationWindow.windowMaker()); + NonOverlappingChunks> windows = new NonOverlappingChunks>(observer, OperationWindow. windowMaker()); ChunkCreator creator = new TimeBasedChunkCreator>(windows, timespan, unit, scheduler); return source.subscribe(new ChunkObserver>(windows, observer, creator)); } @@ -271,7 +271,7 @@ public static OnSubscribeFunc> window(final Observable>() { @Override public Subscription onSubscribe(final Observer> observer) { - Chunks> chunks = new TimeAndSizeBasedChunks>(observer, OperationWindow.windowMaker(), count, timespan, unit, scheduler); + Chunks> chunks = new TimeAndSizeBasedChunks>(observer, OperationWindow. windowMaker(), count, timespan, unit, scheduler); ChunkCreator creator = new SingleChunkCreator>(chunks); return source.subscribe(new ChunkObserver>(chunks, observer, creator)); } @@ -332,7 +332,7 @@ public static OnSubscribeFunc> window(final Observable>() { @Override public Subscription onSubscribe(final Observer> observer) { - OverlappingChunks> windows = new TimeBasedChunks>(observer, OperationWindow.windowMaker(), timespan, unit, scheduler); + OverlappingChunks> windows = new TimeBasedChunks>(observer, OperationWindow. windowMaker(), timespan, unit, scheduler); ChunkCreator creator = new TimeBasedChunkCreator>(windows, timeshift, unit, scheduler); return source.subscribe(new ChunkObserver>(windows, observer, creator)); } diff --git a/rxjava-core/src/main/java/rx/operators/OperationZip.java b/rxjava-core/src/main/java/rx/operators/OperationZip.java index eb07f87738..1837f6e58b 100644 --- a/rxjava-core/src/main/java/rx/operators/OperationZip.java +++ b/rxjava-core/src/main/java/rx/operators/OperationZip.java @@ -15,15 +15,24 @@ */ package rx.operators; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentLinkedQueue; +import java.util.concurrent.atomic.AtomicBoolean; + import rx.Observable; import rx.Observable.OnSubscribeFunc; import rx.Observer; import rx.Subscription; -import rx.util.functions.*; - -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentLinkedQueue; -import java.util.concurrent.atomic.AtomicBoolean; +import rx.util.functions.Func2; +import rx.util.functions.Func3; +import rx.util.functions.Func4; +import rx.util.functions.Func5; +import rx.util.functions.Func6; +import rx.util.functions.Func7; +import rx.util.functions.Func8; +import rx.util.functions.Func9; +import rx.util.functions.FuncN; +import rx.util.functions.Functions; /** * Returns an Observable that emits the results of a function applied to sets of items emitted, in @@ -141,7 +150,7 @@ public static OnSubscribeFunc zip(Iterable> ws, F /* * ThreadSafe */ - static class ZipObserver implements Observer { + /* package accessible for unit tests */static class ZipObserver implements Observer { final Observable w; final Aggregator a; private final SafeObservableSubscription subscription = new SafeObservableSubscription(); @@ -186,7 +195,7 @@ public void onNext(T args) { * * @param */ - static class Aggregator implements OnSubscribeFunc { + /* package accessible for unit tests */static class Aggregator implements OnSubscribeFunc { private volatile SynchronizedObserver observer; private final FuncN zipFunction; diff --git a/rxjava-core/src/main/java/rx/operators/SafeObservableSubscription.java b/rxjava-core/src/main/java/rx/operators/SafeObservableSubscription.java index 69e22def56..ef33ebd3d3 100644 --- a/rxjava-core/src/main/java/rx/operators/SafeObservableSubscription.java +++ b/rxjava-core/src/main/java/rx/operators/SafeObservableSubscription.java @@ -15,10 +15,10 @@ */ package rx.operators; -import rx.Subscription; - import java.util.concurrent.atomic.AtomicReference; +import rx.Subscription; + /** * Thread-safe wrapper around Observable Subscription that ensures unsubscribe can be called only once. *

    @@ -50,7 +50,8 @@ public SafeObservableSubscription(Subscription actualSubscription) { /** * Wraps the actual subscription once it exists (if it wasn't available when constructed) * - * @param actualSubscription the wrapped subscription + * @param actualSubscription + * the wrapped subscription * @throws IllegalStateException * if trying to set more than once (or use this method after setting via constructor) */ diff --git a/rxjava-core/src/main/java/rx/operators/ScheduledObserver.java b/rxjava-core/src/main/java/rx/operators/ScheduledObserver.java index 20416f2235..0bfef9c2c9 100644 --- a/rxjava-core/src/main/java/rx/operators/ScheduledObserver.java +++ b/rxjava-core/src/main/java/rx/operators/ScheduledObserver.java @@ -36,8 +36,7 @@ private final AtomicBoolean started = new AtomicBoolean(); private final ConcurrentLinkedQueue> queue = new ConcurrentLinkedQueue>(); - - + public ScheduledObserver(CompositeSubscription s, Observer underlying, Scheduler scheduler) { this.parentSubscription = s; this.underlying = underlying; diff --git a/rxjava-core/src/main/java/rx/operators/SynchronizedObserver.java b/rxjava-core/src/main/java/rx/operators/SynchronizedObserver.java index c8b4fac812..2daef3e280 100644 --- a/rxjava-core/src/main/java/rx/operators/SynchronizedObserver.java +++ b/rxjava-core/src/main/java/rx/operators/SynchronizedObserver.java @@ -62,7 +62,7 @@ public SynchronizedObserver(Observer Observer, SafeObservableSubscrip this.subscription = subscription; this.lock = lock; } - + /** * Used when synchronizing an Observer without access to the subscription. * diff --git a/rxjava-core/src/main/java/rx/package-info.java b/rxjava-core/src/main/java/rx/package-info.java index 8af9fb51c8..fdd5084e60 100644 --- a/rxjava-core/src/main/java/rx/package-info.java +++ b/rxjava-core/src/main/java/rx/package-info.java @@ -1,12 +1,12 @@ /** * Copyright 2013 Netflix, Inc. - * + * * 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. @@ -15,7 +15,7 @@ */ /** *

    Rx Observables

    - * + * *

    A library that enables subscribing to and composing asynchronous events and * callbacks.

    *

    The Observable/Observer interfaces and associated operators (in @@ -25,8 +25,8 @@ * More information can be found at http://msdn.microsoft.com/en-us/data/gg577609. *

    - * - * + * + * *

    Compared with the Microsoft implementation: *

      *
    • Observable == IObservable
    • @@ -36,9 +36,9 @@ *
    *

    *

    Services which intend on exposing data asynchronously and wish - * to allow reactive processing and composition can implement the - * {@link rx.Observable} interface which then allows Observers to subscribe to them + * to allow reactive processing and composition can implement the {@link rx.Observable} interface which then allows Observers to subscribe to them * and receive events.

    *

    Usage examples can be found on the {@link rx.Observable} and {@link rx.Observer} classes.

    */ package rx; + diff --git a/rxjava-core/src/main/java/rx/plugins/RxJavaPlugins.java b/rxjava-core/src/main/java/rx/plugins/RxJavaPlugins.java index 1e049732ff..2eb806dd6b 100644 --- a/rxjava-core/src/main/java/rx/plugins/RxJavaPlugins.java +++ b/rxjava-core/src/main/java/rx/plugins/RxJavaPlugins.java @@ -32,7 +32,7 @@ public class RxJavaPlugins { private final AtomicReference errorHandler = new AtomicReference(); private final AtomicReference observableExecutionHook = new AtomicReference(); - RxJavaPlugins() { + /* package accessible for unit tests */RxJavaPlugins() { } diff --git a/rxjava-core/src/main/java/rx/subjects/AsyncSubject.java b/rxjava-core/src/main/java/rx/subjects/AsyncSubject.java index 7e4357c696..fc20aaf274 100644 --- a/rxjava-core/src/main/java/rx/subjects/AsyncSubject.java +++ b/rxjava-core/src/main/java/rx/subjects/AsyncSubject.java @@ -1,12 +1,12 @@ /** * Copyright 2013 Netflix, Inc. - * + * * 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. @@ -15,13 +15,13 @@ */ package rx.subjects; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.atomic.AtomicReference; + import rx.Observer; import rx.Subscription; import rx.operators.SafeObservableSubscription; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.atomic.AtomicReference; - /** * Subject that publishes only the last event to each {@link Observer} that has subscribed when the * sequence completes. @@ -32,7 +32,7 @@ *

    *

     {@code
     
    -  // observer will receive no onNext events because the subject.onCompleted() isn't called.
    + * / observer will receive no onNext events because the subject.onCompleted() isn't called.
       AsyncSubject subject = AsyncSubject.create();
       subject.subscribe(observer);
       subject.onNext("one");
    @@ -48,15 +48,14 @@
       subject.onCompleted();
     
       } 
    - *
    + * 
      * @param 
      */
     public class AsyncSubject extends Subject {
     
    -
         /**
          * Create a new AsyncSubject
    -     *
    +     * 
          * @return a new AsyncSubject
          */
         public static  AsyncSubject create() {
    diff --git a/rxjava-core/src/main/java/rx/subjects/BehaviorSubject.java b/rxjava-core/src/main/java/rx/subjects/BehaviorSubject.java
    index 5ea3c52146..55c91ed122 100644
    --- a/rxjava-core/src/main/java/rx/subjects/BehaviorSubject.java
    +++ b/rxjava-core/src/main/java/rx/subjects/BehaviorSubject.java
    @@ -1,12 +1,12 @@
     /**
      * Copyright 2013 Netflix, Inc.
    - *
    + * 
      * 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.
    @@ -15,13 +15,13 @@
      */
     package rx.subjects;
     
    +import java.util.concurrent.ConcurrentHashMap;
    +import java.util.concurrent.atomic.AtomicReference;
    +
     import rx.Observer;
     import rx.Subscription;
     import rx.operators.SafeObservableSubscription;
     
    -import java.util.concurrent.ConcurrentHashMap;
    -import java.util.concurrent.atomic.AtomicReference;
    -
     /**
      * Subject that publishes the most recent and all subsequent events to each subscribed {@link Observer}.
      * 

    @@ -31,7 +31,7 @@ *

    *

     {@code
     
    -  // observer will receive all events.
    + * / observer will receive all events.
       BehaviorSubject subject = BehaviorSubject.createWithDefaultValue("default");
       subject.subscribe(observer);
       subject.onNext("one");
    @@ -47,18 +47,16 @@
       subject.onNext("three");
     
       } 
    - *
    + * 
      * @param 
      */
     public class BehaviorSubject extends Subject {
     
         /**
    -     * Creates a {@link BehaviorSubject} which publishes the last and all subsequent events to each
    -     * {@link Observer} that subscribes to it.
    -     *
    +     * Creates a {@link BehaviorSubject} which publishes the last and all subsequent events to each {@link Observer} that subscribes to it.
    +     * 
          * @param defaultValue
    -     *            The value which will be published to any {@link Observer} as long as the
    -     *            {@link BehaviorSubject} has not yet received any events.
    +     *            The value which will be published to any {@link Observer} as long as the {@link BehaviorSubject} has not yet received any events.
          * @return the constructed {@link BehaviorSubject}.
          */
         public static  BehaviorSubject createWithDefaultValue(T defaultValue) {
    diff --git a/rxjava-core/src/main/java/rx/subjects/PublishSubject.java b/rxjava-core/src/main/java/rx/subjects/PublishSubject.java
    index ca248ea231..fd32bd6e42 100644
    --- a/rxjava-core/src/main/java/rx/subjects/PublishSubject.java
    +++ b/rxjava-core/src/main/java/rx/subjects/PublishSubject.java
    @@ -15,14 +15,14 @@
      */
     package rx.subjects;
     
    -import rx.Observer;
    -import rx.Subscription;
    -import rx.operators.SafeObservableSubscription;
    -
     import java.util.ArrayList;
     import java.util.Collection;
     import java.util.concurrent.ConcurrentHashMap;
     
    +import rx.Observer;
    +import rx.Subscription;
    +import rx.operators.SafeObservableSubscription;
    +
     /**
      * Subject that, once and {@link Observer} has subscribed, publishes all subsequent events to the subscriber.
      * 

    diff --git a/rxjava-core/src/main/java/rx/subjects/ReplaySubject.java b/rxjava-core/src/main/java/rx/subjects/ReplaySubject.java index e103e5fe3b..13d0cc3b57 100644 --- a/rxjava-core/src/main/java/rx/subjects/ReplaySubject.java +++ b/rxjava-core/src/main/java/rx/subjects/ReplaySubject.java @@ -1,12 +1,12 @@ /** * Copyright 2013 Netflix, Inc. - * + * * 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. @@ -15,13 +15,17 @@ */ package rx.subjects; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + import rx.Observer; import rx.Subscription; import rx.subscriptions.Subscriptions; import rx.util.functions.Func1; -import java.util.*; - /** * Subject that retains all events and will replay them to an {@link Observer} that subscribes. *

    @@ -31,7 +35,7 @@ *

    *

     {@code
     
    -  ReplaySubject subject = ReplaySubject.create();
    + * eplaySubject subject = ReplaySubject.create();
       subject.onNext("one");
       subject.onNext("two");
       subject.onNext("three");
    @@ -42,7 +46,7 @@
       subject.subscribe(observer2);
     
       } 
    - *
    + * 
      * @param 
      */
     public final class ReplaySubject extends Subject
    diff --git a/rxjava-core/src/main/java/rx/subjects/UnsubscribeTester.java b/rxjava-core/src/main/java/rx/subjects/UnsubscribeTester.java
    index 6ff50d39ee..0aaf498bc7 100644
    --- a/rxjava-core/src/main/java/rx/subjects/UnsubscribeTester.java
    +++ b/rxjava-core/src/main/java/rx/subjects/UnsubscribeTester.java
    @@ -1,12 +1,12 @@
     /**
      * Copyright 2013 Netflix, Inc.
    - *
    + * 
      * 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.
    diff --git a/rxjava-core/src/main/java/rx/subscriptions/CompositeSubscription.java b/rxjava-core/src/main/java/rx/subscriptions/CompositeSubscription.java
    index 480da47178..326de38471 100644
    --- a/rxjava-core/src/main/java/rx/subscriptions/CompositeSubscription.java
    +++ b/rxjava-core/src/main/java/rx/subscriptions/CompositeSubscription.java
    @@ -15,15 +15,15 @@
      */
     package rx.subscriptions;
     
    -import rx.Subscription;
    -import rx.util.CompositeException;
    -
     import java.util.ArrayList;
     import java.util.Collection;
     import java.util.List;
     import java.util.concurrent.ConcurrentHashMap;
     import java.util.concurrent.atomic.AtomicBoolean;
     
    +import rx.Subscription;
    +import rx.util.CompositeException;
    +
     /**
      * Subscription that represents a group of Subscriptions that are unsubscribed together.
      * 
    diff --git a/rxjava-core/src/main/java/rx/subscriptions/SerialSubscription.java b/rxjava-core/src/main/java/rx/subscriptions/SerialSubscription.java
    index c1235afda6..ebe084f11c 100644
    --- a/rxjava-core/src/main/java/rx/subscriptions/SerialSubscription.java
    +++ b/rxjava-core/src/main/java/rx/subscriptions/SerialSubscription.java
    @@ -1,12 +1,12 @@
     /**
      * Copyright 2013 Netflix, Inc.
    - *
    + * 
      * 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.
    @@ -20,7 +20,7 @@
     /**
      * Represents a subscription whose underlying subscription can be swapped for another subscription
      * which causes the previous underlying subscription to be unsubscribed.
    - *
    + * 
      * @see Rx.Net equivalent SerialDisposable
      */
     public class SerialSubscription implements Subscription {
    diff --git a/rxjava-core/src/main/java/rx/subscriptions/Subscriptions.java b/rxjava-core/src/main/java/rx/subscriptions/Subscriptions.java
    index bb85ed7a15..61fd6b3f6c 100644
    --- a/rxjava-core/src/main/java/rx/subscriptions/Subscriptions.java
    +++ b/rxjava-core/src/main/java/rx/subscriptions/Subscriptions.java
    @@ -15,12 +15,12 @@
      */
     package rx.subscriptions;
     
    +import java.util.concurrent.Future;
    +
     import rx.Subscription;
     import rx.operators.SafeObservableSubscription;
     import rx.util.functions.Action0;
     
    -import java.util.concurrent.Future;
    -
     /**
      * Helper methods and utilities for creating and working with {@link Subscription} objects
      */
    @@ -102,7 +102,7 @@ public void unsubscribe() {
         public static CompositeSubscription from(Subscription... subscriptions) {
             return new CompositeSubscription(subscriptions);
         }
    -    
    +
         /**
          * A {@link Subscription} that groups multiple Subscriptions together and unsubscribes from all of them together.
          * 
    diff --git a/rxjava-core/src/main/java/rx/util/Closings.java b/rxjava-core/src/main/java/rx/util/Closings.java
    index cc6c589283..0de43b97e9 100644
    --- a/rxjava-core/src/main/java/rx/util/Closings.java
    +++ b/rxjava-core/src/main/java/rx/util/Closings.java
    @@ -18,7 +18,8 @@
     public class Closings {
     
         public static Closing create() {
    -        return new Closing() {};
    +        return new Closing() {
    +        };
         }
     
         private Closings() {
    diff --git a/rxjava-core/src/main/java/rx/util/Openings.java b/rxjava-core/src/main/java/rx/util/Openings.java
    index 3f962ec163..30e11f72ca 100644
    --- a/rxjava-core/src/main/java/rx/util/Openings.java
    +++ b/rxjava-core/src/main/java/rx/util/Openings.java
    @@ -18,7 +18,8 @@
     public class Openings {
     
         public static Opening create() {
    -        return new Opening() {};
    +        return new Opening() {
    +        };
         }
     
         private Openings() {
    diff --git a/rxjava-core/src/main/java/rx/util/TimeInterval.java b/rxjava-core/src/main/java/rx/util/TimeInterval.java
    index 7bf1383688..d585baf1ce 100644
    --- a/rxjava-core/src/main/java/rx/util/TimeInterval.java
    +++ b/rxjava-core/src/main/java/rx/util/TimeInterval.java
    @@ -1,12 +1,12 @@
     /**
      * Copyright 2013 Netflix, Inc.
    - *
    + * 
      * 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.
    @@ -26,7 +26,7 @@ public TimeInterval(long intervalInMilliseconds, T value) {
     
         /**
          * Returns the interval in milliseconds.
    -     *
    +     * 
          * @return interval in milliseconds
          */
         public long getIntervalInMilliseconds() {
    @@ -35,7 +35,7 @@ public long getIntervalInMilliseconds() {
     
         /**
          * Returns the value.
    -     *
    +     * 
          * @return the value
          */
         public T getValue() {
    diff --git a/rxjava-core/src/main/java/rx/util/Timestamped.java b/rxjava-core/src/main/java/rx/util/Timestamped.java
    index 729d27ea99..d47bd2b57f 100644
    --- a/rxjava-core/src/main/java/rx/util/Timestamped.java
    +++ b/rxjava-core/src/main/java/rx/util/Timestamped.java
    @@ -1,12 +1,12 @@
     /**
      * Copyright 2013 Netflix, Inc.
    - *
    + * 
      * 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.
    @@ -29,7 +29,7 @@ public Timestamped(long timestampMillis, T value) {
     
         /**
          * Returns time timestamp, in milliseconds.
    -     *
    +     * 
          * @return timestamp in milliseconds
          */
         public long getTimestampMillis() {
    @@ -38,7 +38,7 @@ public long getTimestampMillis() {
     
         /**
          * Returns the value.
    -     *
    +     * 
          * @return the value
          */
         public T getValue() {
    diff --git a/rxjava-core/src/main/java/rx/util/functions/Functions.java b/rxjava-core/src/main/java/rx/util/functions/Functions.java
    index 356ce41173..91449d95bd 100644
    --- a/rxjava-core/src/main/java/rx/util/functions/Functions.java
    +++ b/rxjava-core/src/main/java/rx/util/functions/Functions.java
    @@ -317,7 +317,8 @@ public Void call(Object... args) {
          * Constructs a predicate that returns true for each input that the source
          * predicate returns false for and vice versa.
          * 
    -     * @param predicate The source predicate to negate.
    +     * @param predicate
    +     *            The source predicate to negate.
          */
         public static  Func1 not(Func1 predicate) {
             return new Not(predicate);
    @@ -348,7 +349,7 @@ public Boolean call(Object o) {
                 return true;
             }
         }
    -    
    +
         private enum AlwaysFalse implements Func1 {
             INSTANCE;
     
    diff --git a/rxjava-core/src/main/java/rx/util/functions/Not.java b/rxjava-core/src/main/java/rx/util/functions/Not.java
    index d3928f7888..b63e1dcea4 100644
    --- a/rxjava-core/src/main/java/rx/util/functions/Not.java
    +++ b/rxjava-core/src/main/java/rx/util/functions/Not.java
    @@ -16,23 +16,25 @@
     package rx.util.functions;
     
     /**
    - * Implements the negation of a predicate. 
    + * Implements the negation of a predicate.
      * 
    - * @param  The type of the single input parameter.
    + * @param 
    + *            The type of the single input parameter.
      */
     public class Not implements Func1 {
         private final Func1 predicate;
    - 
    +
         /**
          * Constructs a predicate that returns true for each input that the source
          * predicate returns false for and vice versa.
          * 
    -     * @param predicate The source predicate to negate.
    +     * @param predicate
    +     *            The source predicate to negate.
          */
         public Not(Func1 predicate) {
             this.predicate = predicate;
         }
    -    
    +
         @Override
         public Boolean call(T param) {
             return !predicate.call(param);
    diff --git a/rxjava-core/src/test/java/README.md b/rxjava-core/src/test/java/README.md
    deleted file mode 100644
    index c6a9aea6af..0000000000
    --- a/rxjava-core/src/test/java/README.md
    +++ /dev/null
    @@ -1,6 +0,0 @@
    -Not all unit tests are here, many are also embedded as inner classes of the main code (such as here: [rxjava-core/src/main/java/rx/operators](https://github.com/Netflix/RxJava/tree/master/rxjava-core/src/main/java/rx/operators)).
    -
    -* For an explanation of this design choice see 
    -Ben J. Christensen's [JUnit Tests as Inner Classes](http://benjchristensen.com/2011/10/23/junit-tests-as-inner-classes/).
    -
    -Also, each of the language adaptors has a /src/test/ folder which further testing (see Groovy for an example: [language-adaptors/rxjava-groovy/src/test](https://github.com/Netflix/RxJava/tree/master/language-adaptors/rxjava-groovy/src/test)).
    diff --git a/rxjava-core/src/test/java/rx/ConcatTests.java b/rxjava-core/src/test/java/rx/ConcatTests.java
    index 29a51d8dfe..a83e9f5a9b 100644
    --- a/rxjava-core/src/test/java/rx/ConcatTests.java
    +++ b/rxjava-core/src/test/java/rx/ConcatTests.java
    @@ -60,7 +60,7 @@ public void testConcatWithIterableOfObservable() {
             assertEquals("three", values.get(2));
             assertEquals("four", values.get(3));
         }
    -    
    +
         @Test
         public void testConcatCovariance() {
             Observable o1 = Observable. from(new HorrorMovie(), new Movie());
    @@ -80,14 +80,14 @@ public void testConcatCovariance2() {
     
             List values = Observable.concat(os).toList().toBlockingObservable().single();
         }
    -    
    +
         @Test
         public void testConcatCovariance3() {
             Observable o1 = Observable.from(new HorrorMovie(), new Movie());
             Observable o2 = Observable.from(new Media(), new HorrorMovie());
     
             List values = Observable.concat(o1, o2).toList().toBlockingObservable().single();
    -        
    +
             assertTrue(values.get(0) instanceof HorrorMovie);
             assertTrue(values.get(1) instanceof Movie);
             assertTrue(values.get(2) instanceof Media);
    @@ -112,7 +112,7 @@ public Subscription onSubscribe(Observer o) {
             Observable o2 = Observable.from(new Media(), new HorrorMovie());
     
             List values = Observable.concat(o1, o2).toList().toBlockingObservable().single();
    -        
    +
             assertTrue(values.get(0) instanceof HorrorMovie);
             assertTrue(values.get(1) instanceof Movie);
             assertTrue(values.get(2) instanceof Media);
    diff --git a/rxjava-core/src/test/java/rx/IntervalDemo.java b/rxjava-core/src/test/java/rx/IntervalDemo.java
    index ef2af97549..2d16901674 100644
    --- a/rxjava-core/src/test/java/rx/IntervalDemo.java
    +++ b/rxjava-core/src/test/java/rx/IntervalDemo.java
    @@ -10,33 +10,37 @@
     import rx.util.functions.Action0;
     import rx.util.functions.Action1;
     
    -@Ignore // since this doesn't do any automatic testing
    +@Ignore
    +// since this doesn't do any automatic testing
     public class IntervalDemo {
    -	
    -	@Test public void demoInterval() throws Exception {
    -		testLongObservable(Observable.interval(500, TimeUnit.MILLISECONDS).take(4), "demoInterval");
    -	}	
    -	
    -	public void testLongObservable(Observable o, final String testname) throws Exception {
    -		final List l = new ArrayList();
    -		Action1 onNext = new Action1() {
    -			public void call(Long i) { 
    -				l.add(i);
    -				System.out.println(testname + " got " + i);
    -			}
    -		};
    -		Action1 onError = new Action1() {
    -			public void call(Throwable t) { t.printStackTrace(); }
    -		};
    -		Action0 onComplete = new Action0() {
    -			public void call() {
    -				System.out.println(testname + " complete"); 
    -			}
    -		};
    -		o.subscribe(onNext, onError, onComplete);
    -		
    -		// need to wait, otherwise JUnit kills the thread of interval()
    -		Thread.sleep(2500);
    -	}
    -	
    +
    +    @Test
    +    public void demoInterval() throws Exception {
    +        testLongObservable(Observable.interval(500, TimeUnit.MILLISECONDS).take(4), "demoInterval");
    +    }
    +
    +    public void testLongObservable(Observable o, final String testname) throws Exception {
    +        final List l = new ArrayList();
    +        Action1 onNext = new Action1() {
    +            public void call(Long i) {
    +                l.add(i);
    +                System.out.println(testname + " got " + i);
    +            }
    +        };
    +        Action1 onError = new Action1() {
    +            public void call(Throwable t) {
    +                t.printStackTrace();
    +            }
    +        };
    +        Action0 onComplete = new Action0() {
    +            public void call() {
    +                System.out.println(testname + " complete");
    +            }
    +        };
    +        o.subscribe(onNext, onError, onComplete);
    +
    +        // need to wait, otherwise JUnit kills the thread of interval()
    +        Thread.sleep(2500);
    +    }
    +
     }
    diff --git a/rxjava-core/src/test/java/rx/MergeTests.java b/rxjava-core/src/test/java/rx/MergeTests.java
    index 11f30c7908..83a71044ef 100644
    --- a/rxjava-core/src/test/java/rx/MergeTests.java
    +++ b/rxjava-core/src/test/java/rx/MergeTests.java
    @@ -43,14 +43,14 @@ public void testMergeCovariance2() {
     
             List values = Observable.merge(os).toList().toBlockingObservable().single();
         }
    -    
    +
         @Test
         public void testMergeCovariance3() {
             Observable o1 = Observable.from(new HorrorMovie(), new Movie());
             Observable o2 = Observable.from(new Media(), new HorrorMovie());
     
             List values = Observable.merge(o1, o2).toList().toBlockingObservable().single();
    -        
    +
             assertTrue(values.get(0) instanceof HorrorMovie);
             assertTrue(values.get(1) instanceof Movie);
             assertTrue(values.get(2) instanceof Media);
    @@ -75,12 +75,11 @@ public Subscription onSubscribe(Observer o) {
             Observable o2 = Observable.from(new Media(), new HorrorMovie());
     
             List values = Observable.merge(o1, o2).toList().toBlockingObservable().single();
    -        
    +
             assertTrue(values.get(0) instanceof HorrorMovie);
             assertTrue(values.get(1) instanceof Movie);
             assertTrue(values.get(2) instanceof Media);
             assertTrue(values.get(3) instanceof HorrorMovie);
         }
    -    
    -    
    +
     }
    diff --git a/rxjava-core/src/test/java/rx/ObservableTests.java b/rxjava-core/src/test/java/rx/ObservableTests.java
    index de0c7d6e81..496f520a11 100644
    --- a/rxjava-core/src/test/java/rx/ObservableTests.java
    +++ b/rxjava-core/src/test/java/rx/ObservableTests.java
    @@ -522,7 +522,8 @@ public void call(String value) {
             // subscribe twice
             connectable.subscribe(new Action1() {
                 @Override
    -            public void call(String _) {}
    +            public void call(String _) {
    +            }
             });
     
             Subscription subscription = connectable.connect();
    @@ -745,7 +746,7 @@ public void onNext(String v) {
                 fail("It should be a NumberFormatException");
             }
         }
    -    
    +
         @Test
         public void testOfType() {
             Observable observable = Observable.from(1, "abc", false, 2L).ofType(String.class);
    @@ -770,7 +771,7 @@ public void testOfTypeWithPolymorphism() {
             l2.add(2);
     
             @SuppressWarnings("rawtypes")
    -        Observable observable = Observable.from(l1, l2, "123").ofType(List.class);
    +        Observable observable = Observable. from(l1, l2, "123").ofType(List.class);
     
             @SuppressWarnings("unchecked")
             Observer aObserver = mock(Observer.class);
    @@ -827,7 +828,7 @@ public void testContainsWithNull() {
     
         @Test
         public void testContainsWithEmptyObservable() {
    -        Observable observable = Observable.empty().contains("a");
    +        Observable observable = Observable. empty().contains("a");
     
             @SuppressWarnings("unchecked")
             Observer aObserver = mock(Observer.class);
    diff --git a/rxjava-core/src/test/java/rx/RefCountTests.java b/rxjava-core/src/test/java/rx/RefCountTests.java
    index ff99e60e1c..94b4ed50d4 100644
    --- a/rxjava-core/src/test/java/rx/RefCountTests.java
    +++ b/rxjava-core/src/test/java/rx/RefCountTests.java
    @@ -1,5 +1,13 @@
     package rx;
     
    +import static org.junit.Assert.*;
    +import static org.mockito.Mockito.*;
    +
    +import java.util.ArrayList;
    +import java.util.List;
    +import java.util.concurrent.TimeUnit;
    +import java.util.concurrent.atomic.AtomicInteger;
    +
     import org.junit.Before;
     import org.junit.Test;
     import org.mockito.MockitoAnnotations;
    @@ -9,14 +17,6 @@
     import rx.util.functions.Action0;
     import rx.util.functions.Action1;
     
    -import java.util.ArrayList;
    -import java.util.List;
    -import java.util.concurrent.TimeUnit;
    -import java.util.concurrent.atomic.AtomicInteger;
    -
    -import static org.junit.Assert.assertEquals;
    -import static org.mockito.Mockito.mock;
    -
     public class RefCountTests {
     
         @Before
    @@ -51,7 +51,7 @@ public void call() {
             second.unsubscribe();
             assertEquals(1, unsubscriptionCount.get());
         }
    -    
    +
         @Test
         public void testRefCount() {
             TestScheduler s = new TestScheduler();
    diff --git a/rxjava-core/src/test/java/rx/SchedulersTest.java b/rxjava-core/src/test/java/rx/SchedulersTest.java
    index 4150686d74..c9d97054d0 100644
    --- a/rxjava-core/src/test/java/rx/SchedulersTest.java
    +++ b/rxjava-core/src/test/java/rx/SchedulersTest.java
    @@ -1,12 +1,12 @@
     /**
      * Copyright 2013 Netflix, Inc.
    - *
    + * 
      * 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.
    @@ -15,9 +15,21 @@
      */
     package rx;
     
    +import static org.junit.Assert.*;
    +import static org.mockito.Matchers.*;
    +import static org.mockito.Mockito.*;
    +
    +import java.util.Date;
    +import java.util.concurrent.CountDownLatch;
    +import java.util.concurrent.TimeUnit;
    +import java.util.concurrent.atomic.AtomicBoolean;
    +import java.util.concurrent.atomic.AtomicInteger;
    +import java.util.concurrent.atomic.AtomicReference;
    +
     import org.junit.Test;
     import org.mockito.InOrder;
     import org.mockito.Mockito;
    +
     import rx.Observable.OnSubscribeFunc;
     import rx.concurrency.Schedulers;
     import rx.concurrency.TestScheduler;
    @@ -28,555 +40,543 @@
     import rx.util.functions.Func1;
     import rx.util.functions.Func2;
     
    -import java.util.Date;
    -import java.util.concurrent.CountDownLatch;
    -import java.util.concurrent.TimeUnit;
    -import java.util.concurrent.atomic.AtomicBoolean;
    -import java.util.concurrent.atomic.AtomicInteger;
    -import java.util.concurrent.atomic.AtomicReference;
    -
    -import static org.junit.Assert.*;
    -import static org.mockito.Matchers.anyLong;
    -import static org.mockito.Mockito.*;
    -
     public class SchedulersTest {
     
    -  @SuppressWarnings("unchecked")
    -  // mocking is unchecked, unfortunately
    -  @Test
    -  public void testPeriodicScheduling() {
    -    final Func1 calledOp = mock(Func1.class);
    +    @SuppressWarnings("unchecked")
    +    // mocking is unchecked, unfortunately
    +    @Test
    +    public void testPeriodicScheduling() {
    +        final Func1 calledOp = mock(Func1.class);
     
    -    final TestScheduler scheduler = new TestScheduler();
    -    Subscription subscription = scheduler.schedulePeriodically(new Action0() {
    -      @Override
    -      public void call() {
    -        System.out.println(scheduler.now());
    -        calledOp.call(scheduler.now());
    -      }
    -    }, 1, 2, TimeUnit.SECONDS);
    -
    -    verify(calledOp, never()).call(anyLong());
    +        final TestScheduler scheduler = new TestScheduler();
    +        Subscription subscription = scheduler.schedulePeriodically(new Action0() {
    +            @Override
    +            public void call() {
    +                System.out.println(scheduler.now());
    +                calledOp.call(scheduler.now());
    +            }
    +        }, 1, 2, TimeUnit.SECONDS);
     
    -    InOrder inOrder = Mockito.inOrder(calledOp);
    -
    -    scheduler.advanceTimeBy(999L, TimeUnit.MILLISECONDS);
    -    inOrder.verify(calledOp, never()).call(anyLong());
    +        verify(calledOp, never()).call(anyLong());
     
    -    scheduler.advanceTimeBy(1L, TimeUnit.MILLISECONDS);
    -    inOrder.verify(calledOp, times(1)).call(1000L);
    -
    -    scheduler.advanceTimeBy(1999L, TimeUnit.MILLISECONDS);
    -    inOrder.verify(calledOp, never()).call(3000L);
    -
    -    scheduler.advanceTimeBy(1L, TimeUnit.MILLISECONDS);
    -    inOrder.verify(calledOp, times(1)).call(3000L);
    -
    -    scheduler.advanceTimeBy(5L, TimeUnit.SECONDS);
    -    inOrder.verify(calledOp, times(1)).call(5000L);
    -    inOrder.verify(calledOp, times(1)).call(7000L);
    -
    -    subscription.unsubscribe();
    -    scheduler.advanceTimeBy(11L, TimeUnit.SECONDS);
    -    inOrder.verify(calledOp, never()).call(anyLong());
    -  }
    -
    -  @Test
    -  public void testComputationThreadPool1() {
    -
    -    Observable o1 = Observable.from(1, 2, 3, 4, 5);
    -    Observable o2 = Observable.from(6, 7, 8, 9, 10);
    -    Observable o = Observable.merge(o1, o2).map(new Func1() {
    -
    -      @Override
    -      public String call(Integer t) {
    -        assertTrue(Thread.currentThread().getName().startsWith("RxComputationThreadPool"));
    -        return "Value_" + t + "_Thread_" + Thread.currentThread().getName();
    -      }
    -    });
    +        InOrder inOrder = Mockito.inOrder(calledOp);
     
    -    o.subscribeOn(Schedulers.threadPoolForComputation()).toBlockingObservable().forEach(new Action1() {
    -
    -      @Override
    -      public void call(String t) {
    -        System.out.println("t: " + t);
    -      }
    -    });
    -  }
    -
    -  @Test
    -  public void testIOThreadPool1() {
    +        scheduler.advanceTimeBy(999L, TimeUnit.MILLISECONDS);
    +        inOrder.verify(calledOp, never()).call(anyLong());
     
    -    Observable o1 = Observable.from(1, 2, 3, 4, 5);
    -    Observable o2 = Observable.from(6, 7, 8, 9, 10);
    -    Observable o = Observable.merge(o1, o2).map(new Func1() {
    +        scheduler.advanceTimeBy(1L, TimeUnit.MILLISECONDS);
    +        inOrder.verify(calledOp, times(1)).call(1000L);
     
    -      @Override
    -      public String call(Integer t) {
    -        assertTrue(Thread.currentThread().getName().startsWith("RxIOThreadPool"));
    -        return "Value_" + t + "_Thread_" + Thread.currentThread().getName();
    -      }
    -    });
    -
    -    o.subscribeOn(Schedulers.threadPoolForIO()).toBlockingObservable().forEach(new Action1() {
    -
    -      @Override
    -      public void call(String t) {
    -        System.out.println("t: " + t);
    -      }
    -    });
    -  }
    -
    -  @Test
    -  public void testMergeWithoutScheduler1() {
    -
    -    final String currentThreadName = Thread.currentThread().getName();
    -
    -    Observable o1 = Observable.from(1, 2, 3, 4, 5);
    -    Observable o2 = Observable.from(6, 7, 8, 9, 10);
    -    Observable o = Observable.merge(o1, o2).map(new Func1() {
    -
    -      @Override
    -      public String call(Integer t) {
    -        assertTrue(Thread.currentThread().getName().equals(currentThreadName));
    -        return "Value_" + t + "_Thread_" + Thread.currentThread().getName();
    -      }
    -    });
    -
    -    o.toBlockingObservable().forEach(new Action1() {
    -
    -      @Override
    -      public void call(String t) {
    -        System.out.println("t: " + t);
    -      }
    -    });
    -  }
    +        scheduler.advanceTimeBy(1999L, TimeUnit.MILLISECONDS);
    +        inOrder.verify(calledOp, never()).call(3000L);
     
    -  @Test
    -  public void testMergeWithImmediateScheduler1() {
    +        scheduler.advanceTimeBy(1L, TimeUnit.MILLISECONDS);
    +        inOrder.verify(calledOp, times(1)).call(3000L);
     
    -    final String currentThreadName = Thread.currentThread().getName();
    +        scheduler.advanceTimeBy(5L, TimeUnit.SECONDS);
    +        inOrder.verify(calledOp, times(1)).call(5000L);
    +        inOrder.verify(calledOp, times(1)).call(7000L);
     
    -    Observable o1 = Observable.from(1, 2, 3, 4, 5);
    -    Observable o2 = Observable.from(6, 7, 8, 9, 10);
    -    Observable o = Observable.merge(o1, o2).subscribeOn(Schedulers.immediate()).map(new Func1() {
    +        subscription.unsubscribe();
    +        scheduler.advanceTimeBy(11L, TimeUnit.SECONDS);
    +        inOrder.verify(calledOp, never()).call(anyLong());
    +    }
     
    -      @Override
    -      public String call(Integer t) {
    -        assertTrue(Thread.currentThread().getName().equals(currentThreadName));
    -        return "Value_" + t + "_Thread_" + Thread.currentThread().getName();
    -      }
    -    });
    -
    -    o.toBlockingObservable().forEach(new Action1() {
    -
    -      @Override
    -      public void call(String t) {
    -        System.out.println("t: " + t);
    -      }
    -    });
    -  }
    -
    -  @Test
    -  public void testMergeWithCurrentThreadScheduler1() {
    -
    -    final String currentThreadName = Thread.currentThread().getName();
    -
    -    Observable o1 = Observable.from(1, 2, 3, 4, 5);
    -    Observable o2 = Observable.from(6, 7, 8, 9, 10);
    -    Observable o = Observable.merge(o1, o2).subscribeOn(Schedulers.currentThread()).map(new Func1() {
    -
    -      @Override
    -      public String call(Integer t) {
    -        assertTrue(Thread.currentThread().getName().equals(currentThreadName));
    -        return "Value_" + t + "_Thread_" + Thread.currentThread().getName();
    -      }
    -    });
    +    @Test
    +    public void testComputationThreadPool1() {
     
    -    o.toBlockingObservable().forEach(new Action1() {
    +        Observable o1 = Observable. from(1, 2, 3, 4, 5);
    +        Observable o2 = Observable. from(6, 7, 8, 9, 10);
    +        Observable o = Observable. merge(o1, o2).map(new Func1() {
     
    -      @Override
    -      public void call(String t) {
    -        System.out.println("t: " + t);
    -      }
    -    });
    -  }
    +            @Override
    +            public String call(Integer t) {
    +                assertTrue(Thread.currentThread().getName().startsWith("RxComputationThreadPool"));
    +                return "Value_" + t + "_Thread_" + Thread.currentThread().getName();
    +            }
    +        });
     
    -  @Test
    -  public void testMergeWithScheduler1() {
    +        o.subscribeOn(Schedulers.threadPoolForComputation()).toBlockingObservable().forEach(new Action1() {
     
    -    final String currentThreadName = Thread.currentThread().getName();
    +            @Override
    +            public void call(String t) {
    +                System.out.println("t: " + t);
    +            }
    +        });
    +    }
     
    -    Observable o1 = Observable.from(1, 2, 3, 4, 5);
    -    Observable o2 = Observable.from(6, 7, 8, 9, 10);
    -    Observable o = Observable.merge(o1, o2).subscribeOn(Schedulers.threadPoolForComputation()).map(new Func1() {
    +    @Test
    +    public void testIOThreadPool1() {
     
    -      @Override
    -      public String call(Integer t) {
    -        assertFalse(Thread.currentThread().getName().equals(currentThreadName));
    -        assertTrue(Thread.currentThread().getName().startsWith("RxComputationThreadPool"));
    -        return "Value_" + t + "_Thread_" + Thread.currentThread().getName();
    -      }
    -    });
    +        Observable o1 = Observable. from(1, 2, 3, 4, 5);
    +        Observable o2 = Observable. from(6, 7, 8, 9, 10);
    +        Observable o = Observable. merge(o1, o2).map(new Func1() {
    +
    +            @Override
    +            public String call(Integer t) {
    +                assertTrue(Thread.currentThread().getName().startsWith("RxIOThreadPool"));
    +                return "Value_" + t + "_Thread_" + Thread.currentThread().getName();
    +            }
    +        });
     
    -    o.toBlockingObservable().forEach(new Action1() {
    +        o.subscribeOn(Schedulers.threadPoolForIO()).toBlockingObservable().forEach(new Action1() {
     
    -      @Override
    -      public void call(String t) {
    -        System.out.println("t: " + t);
    -      }
    -    });
    -  }
    +            @Override
    +            public void call(String t) {
    +                System.out.println("t: " + t);
    +            }
    +        });
    +    }
     
    -  @Test
    -  public void testSubscribeWithScheduler1() throws InterruptedException {
    +    @Test
    +    public void testMergeWithoutScheduler1() {
     
    -    final AtomicInteger count = new AtomicInteger();
    +        final String currentThreadName = Thread.currentThread().getName();
     
    -    Observable o1 = Observable.from(1, 2, 3, 4, 5);
    +        Observable o1 = Observable. from(1, 2, 3, 4, 5);
    +        Observable o2 = Observable. from(6, 7, 8, 9, 10);
    +        Observable o = Observable. merge(o1, o2).map(new Func1() {
     
    -    o1.subscribe(new Action1() {
    +            @Override
    +            public String call(Integer t) {
    +                assertTrue(Thread.currentThread().getName().equals(currentThreadName));
    +                return "Value_" + t + "_Thread_" + Thread.currentThread().getName();
    +            }
    +        });
     
    -      @Override
    -      public void call(Integer t) {
    -        System.out.println("Thread: " + Thread.currentThread().getName());
    -        System.out.println("t: " + t);
    -        count.incrementAndGet();
    -      }
    -    });
    +        o.toBlockingObservable().forEach(new Action1() {
     
    -    // the above should be blocking so we should see a count of 5
    -    assertEquals(5, count.get());
    +            @Override
    +            public void call(String t) {
    +                System.out.println("t: " + t);
    +            }
    +        });
    +    }
     
    -    count.set(0);
    +    @Test
    +    public void testMergeWithImmediateScheduler1() {
     
    -    // now we'll subscribe with a scheduler and it should be async
    +        final String currentThreadName = Thread.currentThread().getName();
     
    -    final String currentThreadName = Thread.currentThread().getName();
    +        Observable o1 = Observable. from(1, 2, 3, 4, 5);
    +        Observable o2 = Observable. from(6, 7, 8, 9, 10);
    +        Observable o = Observable. merge(o1, o2).subscribeOn(Schedulers.immediate()).map(new Func1() {
     
    -    // latches for deterministically controlling the test below across threads
    -    final CountDownLatch latch = new CountDownLatch(5);
    -    final CountDownLatch first = new CountDownLatch(1);
    +            @Override
    +            public String call(Integer t) {
    +                assertTrue(Thread.currentThread().getName().equals(currentThreadName));
    +                return "Value_" + t + "_Thread_" + Thread.currentThread().getName();
    +            }
    +        });
     
    -    o1.subscribe(new Action1() {
    +        o.toBlockingObservable().forEach(new Action1() {
     
    -      @Override
    -      public void call(Integer t) {
    -        try {
    -          // we block the first one so we can assert this executes asynchronously with a count
    -          first.await(1000, TimeUnit.SECONDS);
    -        } catch (InterruptedException e) {
    -          throw new RuntimeException("The latch should have released if we are async.", e);
    -        }
    -        assertFalse(Thread.currentThread().getName().equals(currentThreadName));
    -        assertTrue(Thread.currentThread().getName().startsWith("RxComputationThreadPool"));
    -        System.out.println("Thread: " + Thread.currentThread().getName());
    -        System.out.println("t: " + t);
    -        count.incrementAndGet();
    -        latch.countDown();
    -      }
    -    }, Schedulers.threadPoolForComputation());
    -
    -    // assert we are async
    -    assertEquals(0, count.get());
    -    // release the latch so it can go forward
    -    first.countDown();
    -
    -    // wait for all 5 responses
    -    latch.await();
    -    assertEquals(5, count.get());
    -  }
    -
    -  @Test
    -  public void testRecursiveScheduler1() {
    -    Observable obs = Observable.create(new OnSubscribeFunc() {
    -      @Override
    -      public Subscription onSubscribe(final Observer observer) {
    -        return Schedulers.currentThread().schedule(0, new Func2() {
    -          @Override
    -          public Subscription call(Scheduler scheduler, Integer i) {
    -            if (i > 42) {
    -              observer.onCompleted();
    -              return Subscriptions.empty();
    +            @Override
    +            public void call(String t) {
    +                System.out.println("t: " + t);
                 }
    +        });
    +    }
     
    -            observer.onNext(i);
    +    @Test
    +    public void testMergeWithCurrentThreadScheduler1() {
     
    -            return scheduler.schedule(i + 1, this);
    -          }
    +        final String currentThreadName = Thread.currentThread().getName();
    +
    +        Observable o1 = Observable. from(1, 2, 3, 4, 5);
    +        Observable o2 = Observable. from(6, 7, 8, 9, 10);
    +        Observable o = Observable. merge(o1, o2).subscribeOn(Schedulers.currentThread()).map(new Func1() {
    +
    +            @Override
    +            public String call(Integer t) {
    +                assertTrue(Thread.currentThread().getName().equals(currentThreadName));
    +                return "Value_" + t + "_Thread_" + Thread.currentThread().getName();
    +            }
             });
    -      }
    -    });
    -
    -    final AtomicInteger lastValue = new AtomicInteger();
    -    obs.toBlockingObservable().forEach(new Action1() {
    -
    -      @Override
    -      public void call(Integer v) {
    -        System.out.println("Value: " + v);
    -        lastValue.set(v);
    -      }
    -    });
    -
    -    assertEquals(42, lastValue.get());
    -  }
    -
    -  @Test
    -  public void testRecursiveScheduler2() throws InterruptedException {
    -    // use latches instead of Thread.sleep
    -    final CountDownLatch latch = new CountDownLatch(10);
    -    final CountDownLatch completionLatch = new CountDownLatch(1);
    -
    -    Observable obs = Observable.create(new OnSubscribeFunc() {
    -      @Override
    -      public Subscription onSubscribe(final Observer observer) {
    -
    -        return Schedulers.threadPoolForComputation().schedule(new BooleanSubscription(), new Func2() {
    -          @Override
    -          public Subscription call(Scheduler scheduler, BooleanSubscription cancel) {
    -            if (cancel.isUnsubscribed()) {
    -              observer.onCompleted();
    -              completionLatch.countDown();
    -              return Subscriptions.empty();
    +
    +        o.toBlockingObservable().forEach(new Action1() {
    +
    +            @Override
    +            public void call(String t) {
    +                System.out.println("t: " + t);
                 }
    +        });
    +    }
     
    -            observer.onNext(42);
    -            latch.countDown();
    +    @Test
    +    public void testMergeWithScheduler1() {
     
    -            // this will recursively schedule this task for execution again
    -            scheduler.schedule(cancel, this);
    +        final String currentThreadName = Thread.currentThread().getName();
     
    -            return cancel;
    -          }
    +        Observable o1 = Observable. from(1, 2, 3, 4, 5);
    +        Observable o2 = Observable. from(6, 7, 8, 9, 10);
    +        Observable o = Observable. merge(o1, o2).subscribeOn(Schedulers.threadPoolForComputation()).map(new Func1() {
    +
    +            @Override
    +            public String call(Integer t) {
    +                assertFalse(Thread.currentThread().getName().equals(currentThreadName));
    +                assertTrue(Thread.currentThread().getName().startsWith("RxComputationThreadPool"));
    +                return "Value_" + t + "_Thread_" + Thread.currentThread().getName();
    +            }
             });
    -      }
    -    });
    -
    -    final AtomicInteger count = new AtomicInteger();
    -    final AtomicBoolean completed = new AtomicBoolean(false);
    -    Subscription subscribe = obs.subscribe(new Observer() {
    -      @Override
    -      public void onCompleted() {
    -        System.out.println("Completed");
    -        completed.set(true);
    -      }
    -
    -      @Override
    -      public void onError(Throwable e) {
    -        System.out.println("Error");
    -      }
    -
    -      @Override
    -      public void onNext(Integer args) {
    -        count.incrementAndGet();
    -        System.out.println(args);
    -      }
    -    });
    -
    -    if (!latch.await(5000, TimeUnit.MILLISECONDS)) {
    -      fail("Timed out waiting on onNext latch");
    -    }
     
    -    // now unsubscribe and ensure it stops the recursive loop
    -    subscribe.unsubscribe();
    -    System.out.println("unsubscribe");
    +        o.toBlockingObservable().forEach(new Action1() {
     
    -    if (!completionLatch.await(5000, TimeUnit.MILLISECONDS)) {
    -      fail("Timed out waiting on completion latch");
    +            @Override
    +            public void call(String t) {
    +                System.out.println("t: " + t);
    +            }
    +        });
         }
     
    -    // the count can be 10 or higher due to thread scheduling of the unsubscribe vs the scheduler looping to emit the count
    -    assertTrue(count.get() >= 10);
    -    assertTrue(completed.get());
    -  }
    +    @Test
    +    public void testSubscribeWithScheduler1() throws InterruptedException {
    +
    +        final AtomicInteger count = new AtomicInteger();
     
    -  @Test
    -  public void testSchedulingWithDueTime() throws InterruptedException {
    +        Observable o1 = Observable. from(1, 2, 3, 4, 5);
     
    -    final CountDownLatch latch = new CountDownLatch(5);
    -    final AtomicInteger counter = new AtomicInteger();
    +        o1.subscribe(new Action1() {
     
    -    long start = System.currentTimeMillis();
    +            @Override
    +            public void call(Integer t) {
    +                System.out.println("Thread: " + Thread.currentThread().getName());
    +                System.out.println("t: " + t);
    +                count.incrementAndGet();
    +            }
    +        });
     
    -    Schedulers.threadPoolForComputation().schedule(null, new Func2() {
    +        // the above should be blocking so we should see a count of 5
    +        assertEquals(5, count.get());
     
    -      @Override
    -      public Subscription call(Scheduler scheduler, String state) {
    -        System.out.println("doing work");
    -        counter.incrementAndGet();
    -        latch.countDown();
    -        if (latch.getCount() == 0) {
    -          return Subscriptions.empty();
    -        } else {
    -          return scheduler.schedule(state, this, new Date(System.currentTimeMillis() + 50));
    -        }
    -      }
    -    }, new Date(System.currentTimeMillis() + 100));
    +        count.set(0);
    +
    +        // now we'll subscribe with a scheduler and it should be async
    +
    +        final String currentThreadName = Thread.currentThread().getName();
    +
    +        // latches for deterministically controlling the test below across threads
    +        final CountDownLatch latch = new CountDownLatch(5);
    +        final CountDownLatch first = new CountDownLatch(1);
    +
    +        o1.subscribe(new Action1() {
    +
    +            @Override
    +            public void call(Integer t) {
    +                try {
    +                    // we block the first one so we can assert this executes asynchronously with a count
    +                    first.await(1000, TimeUnit.SECONDS);
    +                } catch (InterruptedException e) {
    +                    throw new RuntimeException("The latch should have released if we are async.", e);
    +                }
    +                assertFalse(Thread.currentThread().getName().equals(currentThreadName));
    +                assertTrue(Thread.currentThread().getName().startsWith("RxComputationThreadPool"));
    +                System.out.println("Thread: " + Thread.currentThread().getName());
    +                System.out.println("t: " + t);
    +                count.incrementAndGet();
    +                latch.countDown();
    +            }
    +        }, Schedulers.threadPoolForComputation());
    +
    +        // assert we are async
    +        assertEquals(0, count.get());
    +        // release the latch so it can go forward
    +        first.countDown();
     
    -    if (!latch.await(3000, TimeUnit.MILLISECONDS)) {
    -      fail("didn't execute ... timed out");
    +        // wait for all 5 responses
    +        latch.await();
    +        assertEquals(5, count.get());
         }
     
    -    long end = System.currentTimeMillis();
    +    @Test
    +    public void testRecursiveScheduler1() {
    +        Observable obs = Observable.create(new OnSubscribeFunc() {
    +            @Override
    +            public Subscription onSubscribe(final Observer observer) {
    +                return Schedulers.currentThread().schedule(0, new Func2() {
    +                    @Override
    +                    public Subscription call(Scheduler scheduler, Integer i) {
    +                        if (i > 42) {
    +                            observer.onCompleted();
    +                            return Subscriptions.empty();
    +                        }
    +
    +                        observer.onNext(i);
    +
    +                        return scheduler.schedule(i + 1, this);
    +                    }
    +                });
    +            }
    +        });
    +
    +        final AtomicInteger lastValue = new AtomicInteger();
    +        obs.toBlockingObservable().forEach(new Action1() {
     
    -    assertEquals(5, counter.get());
    -    if ((end - start) < 250) {
    -      fail("it should have taken over 250ms since each step was scheduled 50ms in the future");
    +            @Override
    +            public void call(Integer v) {
    +                System.out.println("Value: " + v);
    +                lastValue.set(v);
    +            }
    +        });
    +
    +        assertEquals(42, lastValue.get());
         }
    -  }
     
    -  @Test
    -  public void testConcurrentOnNextFailsValidation() throws InterruptedException {
    +    @Test
    +    public void testRecursiveScheduler2() throws InterruptedException {
    +        // use latches instead of Thread.sleep
    +        final CountDownLatch latch = new CountDownLatch(10);
    +        final CountDownLatch completionLatch = new CountDownLatch(1);
     
    -    final int count = 10;
    -    final CountDownLatch latch = new CountDownLatch(count);
    -    Observable o = Observable.create(new OnSubscribeFunc() {
    +        Observable obs = Observable.create(new OnSubscribeFunc() {
    +            @Override
    +            public Subscription onSubscribe(final Observer observer) {
    +
    +                return Schedulers.threadPoolForComputation().schedule(new BooleanSubscription(), new Func2() {
    +                    @Override
    +                    public Subscription call(Scheduler scheduler, BooleanSubscription cancel) {
    +                        if (cancel.isUnsubscribed()) {
    +                            observer.onCompleted();
    +                            completionLatch.countDown();
    +                            return Subscriptions.empty();
    +                        }
    +
    +                        observer.onNext(42);
    +                        latch.countDown();
    +
    +                        // this will recursively schedule this task for execution again
    +                        scheduler.schedule(cancel, this);
    +
    +                        return cancel;
    +                    }
    +                });
    +            }
    +        });
     
    -      @Override
    -      public Subscription onSubscribe(final Observer observer) {
    -        for (int i = 0; i < count; i++) {
    -          final int v = i;
    -          new Thread(new Runnable() {
    +        final AtomicInteger count = new AtomicInteger();
    +        final AtomicBoolean completed = new AtomicBoolean(false);
    +        Subscription subscribe = obs.subscribe(new Observer() {
    +            @Override
    +            public void onCompleted() {
    +                System.out.println("Completed");
    +                completed.set(true);
    +            }
     
                 @Override
    -            public void run() {
    -              observer.onNext("v: " + v);
    +            public void onError(Throwable e) {
    +                System.out.println("Error");
    +            }
     
    -              latch.countDown();
    +            @Override
    +            public void onNext(Integer args) {
    +                count.incrementAndGet();
    +                System.out.println(args);
                 }
    -          }).start();
    +        });
    +
    +        if (!latch.await(5000, TimeUnit.MILLISECONDS)) {
    +            fail("Timed out waiting on onNext latch");
             }
    -        return Subscriptions.empty();
    -      }
    -    });
     
    -    ConcurrentObserverValidator observer = new ConcurrentObserverValidator();
    -    // this should call onNext concurrently
    -    o.subscribe(observer);
    +        // now unsubscribe and ensure it stops the recursive loop
    +        subscribe.unsubscribe();
    +        System.out.println("unsubscribe");
     
    -    if (!observer.completed.await(3000, TimeUnit.MILLISECONDS)) {
    -      fail("timed out");
    -    }
    +        if (!completionLatch.await(5000, TimeUnit.MILLISECONDS)) {
    +            fail("Timed out waiting on completion latch");
    +        }
     
    -    if (observer.error.get() == null) {
    -      fail("We expected error messages due to concurrency");
    +        // the count can be 10 or higher due to thread scheduling of the unsubscribe vs the scheduler looping to emit the count
    +        assertTrue(count.get() >= 10);
    +        assertTrue(completed.get());
         }
    -  }
     
    -  @Test
    -  public void testObserveOn() throws InterruptedException {
    +    @Test
    +    public void testSchedulingWithDueTime() throws InterruptedException {
     
    -    Observable o = Observable.from("one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten");
    +        final CountDownLatch latch = new CountDownLatch(5);
    +        final AtomicInteger counter = new AtomicInteger();
     
    -    ConcurrentObserverValidator observer = new ConcurrentObserverValidator();
    +        long start = System.currentTimeMillis();
     
    -    o.observeOn(Schedulers.threadPoolForComputation()).subscribe(observer);
    +        Schedulers.threadPoolForComputation().schedule(null, new Func2() {
     
    -    if (!observer.completed.await(3000, TimeUnit.MILLISECONDS)) {
    -      fail("timed out");
    -    }
    +            @Override
    +            public Subscription call(Scheduler scheduler, String state) {
    +                System.out.println("doing work");
    +                counter.incrementAndGet();
    +                latch.countDown();
    +                if (latch.getCount() == 0) {
    +                    return Subscriptions.empty();
    +                } else {
    +                    return scheduler.schedule(state, this, new Date(System.currentTimeMillis() + 50));
    +                }
    +            }
    +        }, new Date(System.currentTimeMillis() + 100));
     
    -    if (observer.error.get() != null) {
    -      observer.error.get().printStackTrace();
    -      fail("Error: " + observer.error.get().getMessage());
    -    }
    -  }
    +        if (!latch.await(3000, TimeUnit.MILLISECONDS)) {
    +            fail("didn't execute ... timed out");
    +        }
     
    -  @Test
    -  public void testSubscribeOnNestedConcurrency() throws InterruptedException {
    +        long end = System.currentTimeMillis();
     
    -    Observable o = Observable.from("one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten")
    -        .mapMany(new Func1>() {
    +        assertEquals(5, counter.get());
    +        if ((end - start) < 250) {
    +            fail("it should have taken over 250ms since each step was scheduled 50ms in the future");
    +        }
    +    }
     
    -          @Override
    -          public Observable call(final String v) {
    -            return Observable.create(new OnSubscribeFunc() {
    +    @Test
    +    public void testConcurrentOnNextFailsValidation() throws InterruptedException {
     
    -              @Override
    -              public Subscription onSubscribe(final Observer observer) {
    -                observer.onNext("value_after_map-" + v);
    -                observer.onCompleted();
    +        final int count = 10;
    +        final CountDownLatch latch = new CountDownLatch(count);
    +        Observable o = Observable.create(new OnSubscribeFunc() {
    +
    +            @Override
    +            public Subscription onSubscribe(final Observer observer) {
    +                for (int i = 0; i < count; i++) {
    +                    final int v = i;
    +                    new Thread(new Runnable() {
    +
    +                        @Override
    +                        public void run() {
    +                            observer.onNext("v: " + v);
    +
    +                            latch.countDown();
    +                        }
    +                    }).start();
    +                }
                     return Subscriptions.empty();
    -              }
    -            }).subscribeOn(Schedulers.newThread()); // subscribe on a new thread
    -          }
    +            }
             });
     
    -    ConcurrentObserverValidator observer = new ConcurrentObserverValidator();
    +        ConcurrentObserverValidator observer = new ConcurrentObserverValidator();
    +        // this should call onNext concurrently
    +        o.subscribe(observer);
     
    -    o.subscribe(observer);
    +        if (!observer.completed.await(3000, TimeUnit.MILLISECONDS)) {
    +            fail("timed out");
    +        }
     
    -    if (!observer.completed.await(3000, TimeUnit.MILLISECONDS)) {
    -      fail("timed out");
    +        if (observer.error.get() == null) {
    +            fail("We expected error messages due to concurrency");
    +        }
         }
     
    -    if (observer.error.get() != null) {
    -      observer.error.get().printStackTrace();
    -      fail("Error: " + observer.error.get().getMessage());
    -    }
    -  }
    +    @Test
    +    public void testObserveOn() throws InterruptedException {
     
    -  @Test
    -  public void testRecursion() {
    -    TestScheduler s = new TestScheduler();
    +        Observable o = Observable.from("one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten");
     
    -    final AtomicInteger counter = new AtomicInteger(0);
    +        ConcurrentObserverValidator observer = new ConcurrentObserverValidator();
     
    -    Subscription subscription = s.schedule(new Action1() {
    +        o.observeOn(Schedulers.threadPoolForComputation()).subscribe(observer);
     
    -      @Override
    -      public void call(Action0 self) {
    -        counter.incrementAndGet();
    -        System.out.println("counter: " + counter.get());
    -        self.call();
    -      }
    +        if (!observer.completed.await(3000, TimeUnit.MILLISECONDS)) {
    +            fail("timed out");
    +        }
    +
    +        if (observer.error.get() != null) {
    +            observer.error.get().printStackTrace();
    +            fail("Error: " + observer.error.get().getMessage());
    +        }
    +    }
    +
    +    @Test
    +    public void testSubscribeOnNestedConcurrency() throws InterruptedException {
     
    -    });
    -    subscription.unsubscribe();
    -    assertEquals(0, counter.get());
    -  }
    +        Observable o = Observable.from("one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten")
    +                .mapMany(new Func1>() {
     
    +                    @Override
    +                    public Observable call(final String v) {
    +                        return Observable.create(new OnSubscribeFunc() {
     
    -  /**
    -   * Used to determine if onNext is being invoked concurrently.
    -   *
    -   * @param 
    -   */
    -  private static class ConcurrentObserverValidator implements Observer {
    +                            @Override
    +                            public Subscription onSubscribe(final Observer observer) {
    +                                observer.onNext("value_after_map-" + v);
    +                                observer.onCompleted();
    +                                return Subscriptions.empty();
    +                            }
    +                        }).subscribeOn(Schedulers.newThread()); // subscribe on a new thread
    +                    }
    +                });
     
    -    final AtomicInteger concurrentCounter = new AtomicInteger();
    -    final AtomicReference error = new AtomicReference();
    -    final CountDownLatch completed = new CountDownLatch(1);
    +        ConcurrentObserverValidator observer = new ConcurrentObserverValidator();
     
    -    @Override
    -    public void onCompleted() {
    -      completed.countDown();
    +        o.subscribe(observer);
    +
    +        if (!observer.completed.await(3000, TimeUnit.MILLISECONDS)) {
    +            fail("timed out");
    +        }
    +
    +        if (observer.error.get() != null) {
    +            observer.error.get().printStackTrace();
    +            fail("Error: " + observer.error.get().getMessage());
    +        }
         }
     
    -    @Override
    -    public void onError(Throwable e) {
    -      completed.countDown();
    -      error.set(e);
    +    @Test
    +    public void testRecursion() {
    +        TestScheduler s = new TestScheduler();
    +
    +        final AtomicInteger counter = new AtomicInteger(0);
    +
    +        Subscription subscription = s.schedule(new Action1() {
    +
    +            @Override
    +            public void call(Action0 self) {
    +                counter.incrementAndGet();
    +                System.out.println("counter: " + counter.get());
    +                self.call();
    +            }
    +
    +        });
    +        subscription.unsubscribe();
    +        assertEquals(0, counter.get());
         }
     
    -    @Override
    -    public void onNext(T args) {
    -      int count = concurrentCounter.incrementAndGet();
    -      System.out.println("ConcurrentObserverValidator.onNext: " + args);
    -      if (count > 1) {
    -        onError(new RuntimeException("we should not have concurrent execution of onNext"));
    -      }
    -      try {
    -        try {
    -          // take some time so other onNext calls could pile up (I haven't yet thought of a way to do this without sleeping)
    -          Thread.sleep(50);
    -        } catch (InterruptedException e) {
    -          // ignore
    +    /**
    +     * Used to determine if onNext is being invoked concurrently.
    +     * 
    +     * @param 
    +     */
    +    private static class ConcurrentObserverValidator implements Observer {
    +
    +        final AtomicInteger concurrentCounter = new AtomicInteger();
    +        final AtomicReference error = new AtomicReference();
    +        final CountDownLatch completed = new CountDownLatch(1);
    +
    +        @Override
    +        public void onCompleted() {
    +            completed.countDown();
    +        }
    +
    +        @Override
    +        public void onError(Throwable e) {
    +            completed.countDown();
    +            error.set(e);
    +        }
    +
    +        @Override
    +        public void onNext(T args) {
    +            int count = concurrentCounter.incrementAndGet();
    +            System.out.println("ConcurrentObserverValidator.onNext: " + args);
    +            if (count > 1) {
    +                onError(new RuntimeException("we should not have concurrent execution of onNext"));
    +            }
    +            try {
    +                try {
    +                    // take some time so other onNext calls could pile up (I haven't yet thought of a way to do this without sleeping)
    +                    Thread.sleep(50);
    +                } catch (InterruptedException e) {
    +                    // ignore
    +                }
    +            } finally {
    +                concurrentCounter.decrementAndGet();
    +            }
             }
    -      } finally {
    -        concurrentCounter.decrementAndGet();
    -      }
    -    }
     
    -  }
    +    }
     }
    diff --git a/rxjava-core/src/test/java/rx/StartWithTests.java b/rxjava-core/src/test/java/rx/StartWithTests.java
    index de7b03e6ef..2204b6f081 100644
    --- a/rxjava-core/src/test/java/rx/StartWithTests.java
    +++ b/rxjava-core/src/test/java/rx/StartWithTests.java
    @@ -16,7 +16,7 @@ public void startWith1() {
             assertEquals("zero", values.get(0));
             assertEquals("two", values.get(2));
         }
    -    
    +
         @Test
         public void startWithIterable() {
             List li = new ArrayList();
    diff --git a/rxjava-core/src/test/java/rx/TimeoutTests.java b/rxjava-core/src/test/java/rx/TimeoutTests.java
    index 532ae42eba..26da4a3713 100644
    --- a/rxjava-core/src/test/java/rx/TimeoutTests.java
    +++ b/rxjava-core/src/test/java/rx/TimeoutTests.java
    @@ -1,12 +1,12 @@
     /**
      * Copyright 2013 Netflix, Inc.
    - *
    + * 
      * 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.
    @@ -15,20 +15,19 @@
      */
     package rx;
     
    +import static org.mockito.Matchers.*;
    +import static org.mockito.Mockito.*;
    +
    +import java.util.concurrent.TimeUnit;
    +import java.util.concurrent.TimeoutException;
    +
     import org.junit.Before;
     import org.junit.Test;
     import org.mockito.MockitoAnnotations;
    +
     import rx.concurrency.TestScheduler;
     import rx.subjects.PublishSubject;
     
    -import java.util.concurrent.TimeUnit;
    -import java.util.concurrent.TimeoutException;
    -
    -import static org.mockito.Matchers.any;
    -import static org.mockito.Mockito.mock;
    -import static org.mockito.Mockito.never;
    -import static org.mockito.Mockito.verify;
    -
     public class TimeoutTests {
         private PublishSubject underlyingSubject;
         private TestScheduler testScheduler;
    diff --git a/rxjava-core/src/test/java/rx/concurrency/CurrentThreadSchedulerTest.java b/rxjava-core/src/test/java/rx/concurrency/CurrentThreadSchedulerTest.java
    index de34142a93..e9a1a1061a 100644
    --- a/rxjava-core/src/test/java/rx/concurrency/CurrentThreadSchedulerTest.java
    +++ b/rxjava-core/src/test/java/rx/concurrency/CurrentThreadSchedulerTest.java
    @@ -1,129 +1,128 @@
     package rx.concurrency;
     
    -import org.junit.Test;
    -import org.mockito.InOrder;
    -import rx.util.functions.Action0;
    +import static org.mockito.Mockito.*;
     
     import java.util.concurrent.TimeUnit;
     
    -import static org.mockito.Mockito.*;
    +import org.junit.Test;
    +import org.mockito.InOrder;
    +
    +import rx.util.functions.Action0;
     
     public class CurrentThreadSchedulerTest {
     
    -  @Test
    -  public void testNestedActions() {
    -    final CurrentThreadScheduler scheduler = new CurrentThreadScheduler();
    -
    -    final Action0 firstStepStart = mock(Action0.class);
    -    final Action0 firstStepEnd = mock(Action0.class);
    -
    -    final Action0 secondStepStart = mock(Action0.class);
    -    final Action0 secondStepEnd = mock(Action0.class);
    -
    -    final Action0 thirdStepStart = mock(Action0.class);
    -    final Action0 thirdStepEnd = mock(Action0.class);
    -
    -    final Action0 firstAction = new Action0() {
    -      @Override
    -      public void call() {
    -        firstStepStart.call();
    -        firstStepEnd.call();
    -      }
    -    };
    -    final Action0 secondAction = new Action0() {
    -      @Override
    -      public void call() {
    -        secondStepStart.call();
    -        scheduler.schedule(firstAction);
    -        secondStepEnd.call();
    -
    -      }
    -    };
    -    final Action0 thirdAction = new Action0() {
    -      @Override
    -      public void call() {
    -        thirdStepStart.call();
    -        scheduler.schedule(secondAction);
    -        thirdStepEnd.call();
    -      }
    -    };
    -
    -    InOrder inOrder = inOrder(firstStepStart, firstStepEnd, secondStepStart, secondStepEnd, thirdStepStart, thirdStepEnd);
    -
    -    scheduler.schedule(thirdAction);
    -
    -    inOrder.verify(thirdStepStart, times(1)).call();
    -    inOrder.verify(thirdStepEnd, times(1)).call();
    -    inOrder.verify(secondStepStart, times(1)).call();
    -    inOrder.verify(secondStepEnd, times(1)).call();
    -    inOrder.verify(firstStepStart, times(1)).call();
    -    inOrder.verify(firstStepEnd, times(1)).call();
    -  }
    -
    -  @Test
    -  public void testSequenceOfActions() {
    -    final CurrentThreadScheduler scheduler = new CurrentThreadScheduler();
    -
    -    final Action0 first = mock(Action0.class);
    -    final Action0 second = mock(Action0.class);
    -
    -    scheduler.schedule(first);
    -    scheduler.schedule(second);
    -
    -    verify(first, times(1)).call();
    -    verify(second, times(1)).call();
    -
    -  }
    -
    -  @Test
    -  public void testSequenceOfDelayedActions() {
    -    final CurrentThreadScheduler scheduler = new CurrentThreadScheduler();
    -
    -    final Action0 first = mock(Action0.class);
    -    final Action0 second = mock(Action0.class);
    -
    -    scheduler.schedule(new Action0() {
    -      @Override
    -      public void call() {
    -        scheduler.schedule(first, 30, TimeUnit.MILLISECONDS);
    -        scheduler.schedule(second, 10, TimeUnit.MILLISECONDS);
    -      }
    -    });
    -
    -    InOrder inOrder = inOrder(first, second);
    -
    -    inOrder.verify(second, times(1)).call();
    -    inOrder.verify(first, times(1)).call();
    -
    -
    -  }
    -
    -  @Test
    -  public void testMixOfDelayedAndNonDelayedActions() {
    -    final CurrentThreadScheduler scheduler = new CurrentThreadScheduler();
    -
    -    final Action0 first = mock(Action0.class);
    -    final Action0 second = mock(Action0.class);
    -    final Action0 third = mock(Action0.class);
    -    final Action0 fourth = mock(Action0.class);
    -
    -    scheduler.schedule(new Action0() {
    -      @Override
    -      public void call() {
    +    @Test
    +    public void testNestedActions() {
    +        final CurrentThreadScheduler scheduler = new CurrentThreadScheduler();
    +
    +        final Action0 firstStepStart = mock(Action0.class);
    +        final Action0 firstStepEnd = mock(Action0.class);
    +
    +        final Action0 secondStepStart = mock(Action0.class);
    +        final Action0 secondStepEnd = mock(Action0.class);
    +
    +        final Action0 thirdStepStart = mock(Action0.class);
    +        final Action0 thirdStepEnd = mock(Action0.class);
    +
    +        final Action0 firstAction = new Action0() {
    +            @Override
    +            public void call() {
    +                firstStepStart.call();
    +                firstStepEnd.call();
    +            }
    +        };
    +        final Action0 secondAction = new Action0() {
    +            @Override
    +            public void call() {
    +                secondStepStart.call();
    +                scheduler.schedule(firstAction);
    +                secondStepEnd.call();
    +
    +            }
    +        };
    +        final Action0 thirdAction = new Action0() {
    +            @Override
    +            public void call() {
    +                thirdStepStart.call();
    +                scheduler.schedule(secondAction);
    +                thirdStepEnd.call();
    +            }
    +        };
    +
    +        InOrder inOrder = inOrder(firstStepStart, firstStepEnd, secondStepStart, secondStepEnd, thirdStepStart, thirdStepEnd);
    +
    +        scheduler.schedule(thirdAction);
    +
    +        inOrder.verify(thirdStepStart, times(1)).call();
    +        inOrder.verify(thirdStepEnd, times(1)).call();
    +        inOrder.verify(secondStepStart, times(1)).call();
    +        inOrder.verify(secondStepEnd, times(1)).call();
    +        inOrder.verify(firstStepStart, times(1)).call();
    +        inOrder.verify(firstStepEnd, times(1)).call();
    +    }
    +
    +    @Test
    +    public void testSequenceOfActions() {
    +        final CurrentThreadScheduler scheduler = new CurrentThreadScheduler();
    +
    +        final Action0 first = mock(Action0.class);
    +        final Action0 second = mock(Action0.class);
    +
             scheduler.schedule(first);
    -        scheduler.schedule(second, 300, TimeUnit.MILLISECONDS);
    -        scheduler.schedule(third, 100, TimeUnit.MILLISECONDS);
    -        scheduler.schedule(fourth);
    -      }
    -    });
    +        scheduler.schedule(second);
    +
    +        verify(first, times(1)).call();
    +        verify(second, times(1)).call();
    +
    +    }
    +
    +    @Test
    +    public void testSequenceOfDelayedActions() {
    +        final CurrentThreadScheduler scheduler = new CurrentThreadScheduler();
    +
    +        final Action0 first = mock(Action0.class);
    +        final Action0 second = mock(Action0.class);
    +
    +        scheduler.schedule(new Action0() {
    +            @Override
    +            public void call() {
    +                scheduler.schedule(first, 30, TimeUnit.MILLISECONDS);
    +                scheduler.schedule(second, 10, TimeUnit.MILLISECONDS);
    +            }
    +        });
    +
    +        InOrder inOrder = inOrder(first, second);
    +
    +        inOrder.verify(second, times(1)).call();
    +        inOrder.verify(first, times(1)).call();
    +
    +    }
    +
    +    @Test
    +    public void testMixOfDelayedAndNonDelayedActions() {
    +        final CurrentThreadScheduler scheduler = new CurrentThreadScheduler();
    +
    +        final Action0 first = mock(Action0.class);
    +        final Action0 second = mock(Action0.class);
    +        final Action0 third = mock(Action0.class);
    +        final Action0 fourth = mock(Action0.class);
     
    -    InOrder inOrder = inOrder(first, second, third, fourth);
    +        scheduler.schedule(new Action0() {
    +            @Override
    +            public void call() {
    +                scheduler.schedule(first);
    +                scheduler.schedule(second, 300, TimeUnit.MILLISECONDS);
    +                scheduler.schedule(third, 100, TimeUnit.MILLISECONDS);
    +                scheduler.schedule(fourth);
    +            }
    +        });
     
    -    inOrder.verify(first, times(1)).call();
    -    inOrder.verify(fourth, times(1)).call();
    -    inOrder.verify(third, times(1)).call();
    -    inOrder.verify(second, times(1)).call();
    +        InOrder inOrder = inOrder(first, second, third, fourth);
     
    +        inOrder.verify(first, times(1)).call();
    +        inOrder.verify(fourth, times(1)).call();
    +        inOrder.verify(third, times(1)).call();
    +        inOrder.verify(second, times(1)).call();
     
    -  }
    +    }
     }
    diff --git a/rxjava-core/src/test/java/rx/concurrency/ImmediateSchedulerTest.java b/rxjava-core/src/test/java/rx/concurrency/ImmediateSchedulerTest.java
    index df08b8aa31..fc2da52963 100644
    --- a/rxjava-core/src/test/java/rx/concurrency/ImmediateSchedulerTest.java
    +++ b/rxjava-core/src/test/java/rx/concurrency/ImmediateSchedulerTest.java
    @@ -1,59 +1,60 @@
     package rx.concurrency;
     
    +import static org.mockito.Mockito.*;
    +
     import org.junit.Test;
     import org.mockito.InOrder;
    -import rx.util.functions.Action0;
     
    -import static org.mockito.Mockito.*;
    +import rx.util.functions.Action0;
     
     public class ImmediateSchedulerTest {
    -  @Test
    -  public void testNestedActions() {
    -    final ImmediateScheduler scheduler = new ImmediateScheduler();
    -
    -    final Action0 firstStepStart = mock(Action0.class);
    -    final Action0 firstStepEnd = mock(Action0.class);
    -
    -    final Action0 secondStepStart = mock(Action0.class);
    -    final Action0 secondStepEnd = mock(Action0.class);
    -
    -    final Action0 thirdStepStart = mock(Action0.class);
    -    final Action0 thirdStepEnd = mock(Action0.class);
    -
    -    final Action0 firstAction = new Action0() {
    -      @Override
    -      public void call() {
    -        firstStepStart.call();
    -        firstStepEnd.call();
    -      }
    -    };
    -    final Action0 secondAction = new Action0() {
    -      @Override
    -      public void call() {
    -        secondStepStart.call();
    -        scheduler.schedule(firstAction);
    -        secondStepEnd.call();
    -
    -      }
    -    };
    -    final Action0 thirdAction = new Action0() {
    -      @Override
    -      public void call() {
    -        thirdStepStart.call();
    -        scheduler.schedule(secondAction);
    -        thirdStepEnd.call();
    -      }
    -    };
    -
    -    InOrder inOrder = inOrder(firstStepStart, firstStepEnd, secondStepStart, secondStepEnd, thirdStepStart, thirdStepEnd);
    -
    -    scheduler.schedule(thirdAction);
    -
    -    inOrder.verify(thirdStepStart, times(1)).call();
    -    inOrder.verify(secondStepStart, times(1)).call();
    -    inOrder.verify(firstStepStart, times(1)).call();
    -    inOrder.verify(firstStepEnd, times(1)).call();
    -    inOrder.verify(secondStepEnd, times(1)).call();
    -    inOrder.verify(thirdStepEnd, times(1)).call();
    -  }
    +    @Test
    +    public void testNestedActions() {
    +        final ImmediateScheduler scheduler = new ImmediateScheduler();
    +
    +        final Action0 firstStepStart = mock(Action0.class);
    +        final Action0 firstStepEnd = mock(Action0.class);
    +
    +        final Action0 secondStepStart = mock(Action0.class);
    +        final Action0 secondStepEnd = mock(Action0.class);
    +
    +        final Action0 thirdStepStart = mock(Action0.class);
    +        final Action0 thirdStepEnd = mock(Action0.class);
    +
    +        final Action0 firstAction = new Action0() {
    +            @Override
    +            public void call() {
    +                firstStepStart.call();
    +                firstStepEnd.call();
    +            }
    +        };
    +        final Action0 secondAction = new Action0() {
    +            @Override
    +            public void call() {
    +                secondStepStart.call();
    +                scheduler.schedule(firstAction);
    +                secondStepEnd.call();
    +
    +            }
    +        };
    +        final Action0 thirdAction = new Action0() {
    +            @Override
    +            public void call() {
    +                thirdStepStart.call();
    +                scheduler.schedule(secondAction);
    +                thirdStepEnd.call();
    +            }
    +        };
    +
    +        InOrder inOrder = inOrder(firstStepStart, firstStepEnd, secondStepStart, secondStepEnd, thirdStepStart, thirdStepEnd);
    +
    +        scheduler.schedule(thirdAction);
    +
    +        inOrder.verify(thirdStepStart, times(1)).call();
    +        inOrder.verify(secondStepStart, times(1)).call();
    +        inOrder.verify(firstStepStart, times(1)).call();
    +        inOrder.verify(firstStepEnd, times(1)).call();
    +        inOrder.verify(secondStepEnd, times(1)).call();
    +        inOrder.verify(thirdStepEnd, times(1)).call();
    +    }
     }
    diff --git a/rxjava-core/src/test/java/rx/observables/BlockingObservableTest.java b/rxjava-core/src/test/java/rx/observables/BlockingObservableTest.java
    index 0c6f885de9..e97765c6ab 100644
    --- a/rxjava-core/src/test/java/rx/observables/BlockingObservableTest.java
    +++ b/rxjava-core/src/test/java/rx/observables/BlockingObservableTest.java
    @@ -1,9 +1,14 @@
     package rx.observables;
     
    +import static org.junit.Assert.*;
    +
    +import java.util.Iterator;
    +
     import org.junit.Before;
     import org.junit.Test;
     import org.mockito.Mock;
     import org.mockito.MockitoAnnotations;
    +
     import rx.Observable;
     import rx.Observer;
     import rx.Subscription;
    @@ -12,237 +17,233 @@
     import rx.util.functions.Action1;
     import rx.util.functions.Func1;
     
    -import java.util.Iterator;
    +public class BlockingObservableTest {
     
    -import static org.junit.Assert.*;
    +    @Mock
    +    Observer w;
     
    -public class BlockingObservableTest {
    +    @Before
    +    public void before() {
    +        MockitoAnnotations.initMocks(this);
    +    }
     
    -  @Mock
    -  Observer w;
    -
    -  @Before
    -  public void before() {
    -    MockitoAnnotations.initMocks(this);
    -  }
    -
    -  @Test
    -  public void testLast() {
    -    BlockingObservable obs = BlockingObservable.from(Observable.from("one", "two", "three"));
    -
    -    assertEquals("three", obs.last());
    -  }
    -
    -  @Test
    -  public void testLastEmptyObservable() {
    -    BlockingObservable obs = BlockingObservable.from(Observable.empty());
    -
    -    assertNull(obs.last());
    -  }
    -
    -  @Test
    -  public void testLastOrDefault() {
    -    BlockingObservable observable = BlockingObservable.from(Observable.from(1, 0, -1));
    -    int last = observable.lastOrDefault(-100, new Func1() {
    -      @Override
    -      public Boolean call(Integer args) {
    -        return args >= 0;
    -      }
    -    });
    -    assertEquals(0, last);
    -  }
    -
    -  @Test
    -  public void testLastOrDefault1() {
    -    BlockingObservable observable = BlockingObservable.from(Observable.from("one", "two", "three"));
    -    assertEquals("three", observable.lastOrDefault("default"));
    -  }
    -
    -  @Test
    -  public void testLastOrDefault2() {
    -    BlockingObservable observable = BlockingObservable.from(Observable.empty());
    -    assertEquals("default", observable.lastOrDefault("default"));
    -  }
    -
    -  @Test
    -  public void testLastOrDefaultWithPredicate() {
    -    BlockingObservable observable = BlockingObservable.from(Observable.from(1, 0, -1));
    -    int last = observable.lastOrDefault(0, new Func1() {
    -      @Override
    -      public Boolean call(Integer args) {
    -        return args < 0;
    -      }
    -    });
    -
    -    assertEquals(-1, last);
    -  }
    -
    -  @Test
    -  public void testLastOrDefaultWrongPredicate() {
    -    BlockingObservable observable = BlockingObservable.from(Observable.from(-1, -2, -3));
    -    int last = observable.lastOrDefault(0, new Func1() {
    -      @Override
    -      public Boolean call(Integer args) {
    -        return args >= 0;
    -      }
    -    });
    -    assertEquals(0, last);
    -  }
    -
    -  @Test
    -  public void testLastWithPredicate() {
    -    BlockingObservable obs = BlockingObservable.from(Observable.from("one", "two", "three"));
    -
    -    assertEquals("two", obs.last(new Func1() {
    -      @Override
    -      public Boolean call(String s) {
    -        return s.length() == 3;
    -      }
    -    }));
    -  }
    -
    -  public void testSingle() {
    -    BlockingObservable observable = BlockingObservable.from(Observable.from("one"));
    -    assertEquals("one", observable.single());
    -  }
    -
    -  @Test
    -  public void testSingleDefault() {
    -    BlockingObservable observable = BlockingObservable.from(Observable.empty());
    -    assertEquals("default", observable.singleOrDefault("default"));
    -  }
    -
    -  @Test(expected = IllegalStateException.class)
    -  public void testSingleDefaultPredicateMatchesMoreThanOne() {
    -    BlockingObservable.from(Observable.from("one", "two")).singleOrDefault("default", new Func1() {
    -      @Override
    -      public Boolean call(String args) {
    -        return args.length() == 3;
    -      }
    -    });
    -  }
    -
    -  @Test
    -  public void testSingleDefaultPredicateMatchesNothing() {
    -    BlockingObservable observable = BlockingObservable.from(Observable.from("one", "two"));
    -    String result = observable.singleOrDefault("default", new Func1() {
    -      @Override
    -      public Boolean call(String args) {
    -        return args.length() == 4;
    -      }
    -    });
    -    assertEquals("default", result);
    -  }
    -
    -  @Test(expected = IllegalStateException.class)
    -  public void testSingleDefaultWithMoreThanOne() {
    -    BlockingObservable observable = BlockingObservable.from(Observable.from("one", "two", "three"));
    -    observable.singleOrDefault("default");
    -  }
    -
    -  @Test
    -  public void testSingleWithPredicateDefault() {
    -    BlockingObservable observable = BlockingObservable.from(Observable.from("one", "two", "four"));
    -    assertEquals("four", observable.single(new Func1() {
    -      @Override
    -      public Boolean call(String s) {
    -        return s.length() == 4;
    -      }
    -    }));
    -  }
    -
    -  @Test(expected = IllegalStateException.class)
    -  public void testSingleWrong() {
    -    BlockingObservable observable = BlockingObservable.from(Observable.from(1, 2));
    -    observable.single();
    -  }
    -
    -  @Test(expected = IllegalStateException.class)
    -  public void testSingleWrongPredicate() {
    -    BlockingObservable observable = BlockingObservable.from(Observable.from(-1));
    -    observable.single(new Func1() {
    -      @Override
    -      public Boolean call(Integer args) {
    -        return args > 0;
    -      }
    -    });
    -  }
    -
    -  @Test
    -  public void testToIterable() {
    -    BlockingObservable obs = BlockingObservable.from(Observable.from("one", "two", "three"));
    -
    -    Iterator it = obs.toIterable().iterator();
    -
    -    assertEquals(true, it.hasNext());
    -    assertEquals("one", it.next());
    -
    -    assertEquals(true, it.hasNext());
    -    assertEquals("two", it.next());
    -
    -    assertEquals(true, it.hasNext());
    -    assertEquals("three", it.next());
    -
    -    assertEquals(false, it.hasNext());
    -
    -  }
    -
    -  @Test(expected = TestException.class)
    -  public void testToIterableWithException() {
    -    BlockingObservable obs = BlockingObservable.from(Observable.create(new Observable.OnSubscribeFunc() {
    -
    -      @Override
    -      public Subscription onSubscribe(Observer observer) {
    -        observer.onNext("one");
    -        observer.onError(new TestException());
    -        return Subscriptions.empty();
    -      }
    -    }));
    -
    -    Iterator it = obs.toIterable().iterator();
    -
    -    assertEquals(true, it.hasNext());
    -    assertEquals("one", it.next());
    -
    -    assertEquals(true, it.hasNext());
    -    it.next();
    -
    -  }
    -
    -  @Test
    -  public void testForEachWithError() {
    -    try {
    -      BlockingObservable.from(Observable.create(new Observable.OnSubscribeFunc() {
    -
    -        @Override
    -        public Subscription onSubscribe(final Observer observer) {
    -          final BooleanSubscription subscription = new BooleanSubscription();
    -          new Thread(new Runnable() {
    +    @Test
    +    public void testLast() {
    +        BlockingObservable obs = BlockingObservable.from(Observable.from("one", "two", "three"));
     
    +        assertEquals("three", obs.last());
    +    }
    +
    +    @Test
    +    public void testLastEmptyObservable() {
    +        BlockingObservable obs = BlockingObservable.from(Observable.empty());
    +
    +        assertNull(obs.last());
    +    }
    +
    +    @Test
    +    public void testLastOrDefault() {
    +        BlockingObservable observable = BlockingObservable.from(Observable.from(1, 0, -1));
    +        int last = observable.lastOrDefault(-100, new Func1() {
                 @Override
    -            public void run() {
    -              observer.onNext("one");
    -              observer.onNext("two");
    -              observer.onNext("three");
    -              observer.onCompleted();
    +            public Boolean call(Integer args) {
    +                return args >= 0;
                 }
    -          }).start();
    -          return subscription;
    -        }
    -      })).forEach(new Action1() {
    +        });
    +        assertEquals(0, last);
    +    }
    +
    +    @Test
    +    public void testLastOrDefault1() {
    +        BlockingObservable observable = BlockingObservable.from(Observable.from("one", "two", "three"));
    +        assertEquals("three", observable.lastOrDefault("default"));
    +    }
    +
    +    @Test
    +    public void testLastOrDefault2() {
    +        BlockingObservable observable = BlockingObservable.from(Observable.empty());
    +        assertEquals("default", observable.lastOrDefault("default"));
    +    }
    +
    +    @Test
    +    public void testLastOrDefaultWithPredicate() {
    +        BlockingObservable observable = BlockingObservable.from(Observable.from(1, 0, -1));
    +        int last = observable.lastOrDefault(0, new Func1() {
    +            @Override
    +            public Boolean call(Integer args) {
    +                return args < 0;
    +            }
    +        });
    +
    +        assertEquals(-1, last);
    +    }
    +
    +    @Test
    +    public void testLastOrDefaultWrongPredicate() {
    +        BlockingObservable observable = BlockingObservable.from(Observable.from(-1, -2, -3));
    +        int last = observable.lastOrDefault(0, new Func1() {
    +            @Override
    +            public Boolean call(Integer args) {
    +                return args >= 0;
    +            }
    +        });
    +        assertEquals(0, last);
    +    }
    +
    +    @Test
    +    public void testLastWithPredicate() {
    +        BlockingObservable obs = BlockingObservable.from(Observable.from("one", "two", "three"));
    +
    +        assertEquals("two", obs.last(new Func1() {
    +            @Override
    +            public Boolean call(String s) {
    +                return s.length() == 3;
    +            }
    +        }));
    +    }
    +
    +    public void testSingle() {
    +        BlockingObservable observable = BlockingObservable.from(Observable.from("one"));
    +        assertEquals("one", observable.single());
    +    }
    +
    +    @Test
    +    public void testSingleDefault() {
    +        BlockingObservable observable = BlockingObservable.from(Observable.empty());
    +        assertEquals("default", observable.singleOrDefault("default"));
    +    }
     
    -        @Override
    -        public void call(String t1) {
    -          throw new RuntimeException("fail");
    +    @Test(expected = IllegalStateException.class)
    +    public void testSingleDefaultPredicateMatchesMoreThanOne() {
    +        BlockingObservable.from(Observable.from("one", "two")).singleOrDefault("default", new Func1() {
    +            @Override
    +            public Boolean call(String args) {
    +                return args.length() == 3;
    +            }
    +        });
    +    }
    +
    +    @Test
    +    public void testSingleDefaultPredicateMatchesNothing() {
    +        BlockingObservable observable = BlockingObservable.from(Observable.from("one", "two"));
    +        String result = observable.singleOrDefault("default", new Func1() {
    +            @Override
    +            public Boolean call(String args) {
    +                return args.length() == 4;
    +            }
    +        });
    +        assertEquals("default", result);
    +    }
    +
    +    @Test(expected = IllegalStateException.class)
    +    public void testSingleDefaultWithMoreThanOne() {
    +        BlockingObservable observable = BlockingObservable.from(Observable.from("one", "two", "three"));
    +        observable.singleOrDefault("default");
    +    }
    +
    +    @Test
    +    public void testSingleWithPredicateDefault() {
    +        BlockingObservable observable = BlockingObservable.from(Observable.from("one", "two", "four"));
    +        assertEquals("four", observable.single(new Func1() {
    +            @Override
    +            public Boolean call(String s) {
    +                return s.length() == 4;
    +            }
    +        }));
    +    }
    +
    +    @Test(expected = IllegalStateException.class)
    +    public void testSingleWrong() {
    +        BlockingObservable observable = BlockingObservable.from(Observable.from(1, 2));
    +        observable.single();
    +    }
    +
    +    @Test(expected = IllegalStateException.class)
    +    public void testSingleWrongPredicate() {
    +        BlockingObservable observable = BlockingObservable.from(Observable.from(-1));
    +        observable.single(new Func1() {
    +            @Override
    +            public Boolean call(Integer args) {
    +                return args > 0;
    +            }
    +        });
    +    }
    +
    +    @Test
    +    public void testToIterable() {
    +        BlockingObservable obs = BlockingObservable.from(Observable.from("one", "two", "three"));
    +
    +        Iterator it = obs.toIterable().iterator();
    +
    +        assertEquals(true, it.hasNext());
    +        assertEquals("one", it.next());
    +
    +        assertEquals(true, it.hasNext());
    +        assertEquals("two", it.next());
    +
    +        assertEquals(true, it.hasNext());
    +        assertEquals("three", it.next());
    +
    +        assertEquals(false, it.hasNext());
    +
    +    }
    +
    +    @Test(expected = TestException.class)
    +    public void testToIterableWithException() {
    +        BlockingObservable obs = BlockingObservable.from(Observable.create(new Observable.OnSubscribeFunc() {
    +
    +            @Override
    +            public Subscription onSubscribe(Observer observer) {
    +                observer.onNext("one");
    +                observer.onError(new TestException());
    +                return Subscriptions.empty();
    +            }
    +        }));
    +
    +        Iterator it = obs.toIterable().iterator();
    +
    +        assertEquals(true, it.hasNext());
    +        assertEquals("one", it.next());
    +
    +        assertEquals(true, it.hasNext());
    +        it.next();
    +
    +    }
    +
    +    @Test
    +    public void testForEachWithError() {
    +        try {
    +            BlockingObservable.from(Observable.create(new Observable.OnSubscribeFunc() {
    +
    +                @Override
    +                public Subscription onSubscribe(final Observer observer) {
    +                    final BooleanSubscription subscription = new BooleanSubscription();
    +                    new Thread(new Runnable() {
    +
    +                        @Override
    +                        public void run() {
    +                            observer.onNext("one");
    +                            observer.onNext("two");
    +                            observer.onNext("three");
    +                            observer.onCompleted();
    +                        }
    +                    }).start();
    +                    return subscription;
    +                }
    +            })).forEach(new Action1() {
    +
    +                @Override
    +                public void call(String t1) {
    +                    throw new RuntimeException("fail");
    +                }
    +            });
    +            fail("we expect an exception to be thrown");
    +        } catch (Throwable e) {
    +            // do nothing as we expect this
             }
    -      });
    -      fail("we expect an exception to be thrown");
    -    } catch (Throwable e) {
    -      // do nothing as we expect this
         }
    -  }
     
    -  private static class TestException extends RuntimeException {
    -    private static final long serialVersionUID = 1L;
    -  }
    +    private static class TestException extends RuntimeException {
    +        private static final long serialVersionUID = 1L;
    +    }
     }
    diff --git a/rxjava-core/src/test/java/rx/operators/OperationAllTest.java b/rxjava-core/src/test/java/rx/operators/OperationAllTest.java
    index 23bde39e59..8418e821d6 100644
    --- a/rxjava-core/src/test/java/rx/operators/OperationAllTest.java
    +++ b/rxjava-core/src/test/java/rx/operators/OperationAllTest.java
    @@ -1,84 +1,85 @@
     package rx.operators;
     
    +import static org.mockito.Mockito.*;
    +import static rx.operators.OperationAll.*;
    +
     import org.junit.Test;
    +
     import rx.Observable;
     import rx.Observer;
     import rx.util.functions.Func1;
     
    -import static org.mockito.Mockito.*;
    -import static rx.operators.OperationAll.all;
    -
     public class OperationAllTest {
     
    -  @Test
    -  @SuppressWarnings("unchecked")
    -  public void testAll() {
    -    Observable obs = Observable.from("one", "two", "six");
    -
    -    Observer observer = mock(Observer.class);
    -    Observable.create(all(obs, new Func1() {
    -      @Override
    -      public Boolean call(String s) {
    -        return s.length() == 3;
    -      }
    -    })).subscribe(observer);
    -
    -    verify(observer).onNext(true);
    -    verify(observer).onCompleted();
    -    verifyNoMoreInteractions(observer);
    -  }
    -
    -  @Test
    -  @SuppressWarnings("unchecked")
    -  public void testNotAll() {
    -    Observable obs = Observable.from("one", "two", "three", "six");
    -
    -    Observer observer = mock(Observer.class);
    -    Observable.create(all(obs, new Func1() {
    -      @Override
    -      public Boolean call(String s) {
    -        return s.length() == 3;
    -      }
    -    })).subscribe(observer);
    -
    -    verify(observer).onNext(false);
    -    verify(observer).onCompleted();
    -    verifyNoMoreInteractions(observer);
    -  }
    -
    -  @Test
    -  @SuppressWarnings("unchecked")
    -  public void testEmpty() {
    -    Observable obs = Observable.empty();
    -
    -    Observer observer = mock(Observer.class);
    -    Observable.create(all(obs, new Func1() {
    -      @Override
    -      public Boolean call(String s) {
    -        return s.length() == 3;
    -      }
    -    })).subscribe(observer);
    -
    -    verify(observer).onNext(true);
    -    verify(observer).onCompleted();
    -    verifyNoMoreInteractions(observer);
    -  }
    -
    -  @Test
    -  @SuppressWarnings("unchecked")
    -  public void testError() {
    -    Throwable error = new Throwable();
    -    Observable obs = Observable.error(error);
    -
    -    Observer observer = mock(Observer.class);
    -    Observable.create(all(obs, new Func1() {
    -      @Override
    -      public Boolean call(String s) {
    -        return s.length() == 3;
    -      }
    -    })).subscribe(observer);
    -
    -    verify(observer).onError(error);
    -    verifyNoMoreInteractions(observer);
    -  }
    +    @Test
    +    @SuppressWarnings("unchecked")
    +    public void testAll() {
    +        Observable obs = Observable.from("one", "two", "six");
    +
    +        Observer observer = mock(Observer.class);
    +        Observable.create(all(obs, new Func1() {
    +            @Override
    +            public Boolean call(String s) {
    +                return s.length() == 3;
    +            }
    +        })).subscribe(observer);
    +
    +        verify(observer).onNext(true);
    +        verify(observer).onCompleted();
    +        verifyNoMoreInteractions(observer);
    +    }
    +
    +    @Test
    +    @SuppressWarnings("unchecked")
    +    public void testNotAll() {
    +        Observable obs = Observable.from("one", "two", "three", "six");
    +
    +        Observer observer = mock(Observer.class);
    +        Observable.create(all(obs, new Func1() {
    +            @Override
    +            public Boolean call(String s) {
    +                return s.length() == 3;
    +            }
    +        })).subscribe(observer);
    +
    +        verify(observer).onNext(false);
    +        verify(observer).onCompleted();
    +        verifyNoMoreInteractions(observer);
    +    }
    +
    +    @Test
    +    @SuppressWarnings("unchecked")
    +    public void testEmpty() {
    +        Observable obs = Observable.empty();
    +
    +        Observer observer = mock(Observer.class);
    +        Observable.create(all(obs, new Func1() {
    +            @Override
    +            public Boolean call(String s) {
    +                return s.length() == 3;
    +            }
    +        })).subscribe(observer);
    +
    +        verify(observer).onNext(true);
    +        verify(observer).onCompleted();
    +        verifyNoMoreInteractions(observer);
    +    }
    +
    +    @Test
    +    @SuppressWarnings("unchecked")
    +    public void testError() {
    +        Throwable error = new Throwable();
    +        Observable obs = Observable.error(error);
    +
    +        Observer observer = mock(Observer.class);
    +        Observable.create(all(obs, new Func1() {
    +            @Override
    +            public Boolean call(String s) {
    +                return s.length() == 3;
    +            }
    +        })).subscribe(observer);
    +
    +        verify(observer).onError(error);
    +        verifyNoMoreInteractions(observer);
    +    }
     }
    diff --git a/rxjava-core/src/test/java/rx/operators/OperationAnyTest.java b/rxjava-core/src/test/java/rx/operators/OperationAnyTest.java
    index 801a35d0c3..f9e64791d8 100644
    --- a/rxjava-core/src/test/java/rx/operators/OperationAnyTest.java
    +++ b/rxjava-core/src/test/java/rx/operators/OperationAnyTest.java
    @@ -1,182 +1,182 @@
     package rx.operators;
     
    +import static org.mockito.Mockito.*;
    +import static rx.operators.OperationAny.*;
    +
     import org.junit.Test;
    +
     import rx.Observable;
     import rx.Observer;
     import rx.util.functions.Func1;
     
    -import static org.mockito.Mockito.*;
    -import static rx.operators.OperationAny.any;
    -import static rx.operators.OperationAny.*;
    -
     public class OperationAnyTest {
     
    -  @Test
    -  public void testAnyWithTwoItems() {
    -    Observable w = Observable.from(1, 2);
    -    Observable observable = Observable.create(any(w));
    -
    -    @SuppressWarnings("unchecked")
    -    Observer aObserver = mock(Observer.class);
    -    observable.subscribe(aObserver);
    -    verify(aObserver, never()).onNext(false);
    -    verify(aObserver, times(1)).onNext(true);
    -    verify(aObserver, never()).onError(org.mockito.Matchers.any(Throwable.class));
    -    verify(aObserver, times(1)).onCompleted();
    -  }
    -
    -  @Test
    -  public void testIsEmptyWithTwoItems() {
    -    Observable w = Observable.from(1, 2);
    -    Observable observable = Observable.create(isEmpty(w));
    -
    -    @SuppressWarnings("unchecked")
    -    Observer aObserver = mock(Observer.class);
    -    observable.subscribe(aObserver);
    -    verify(aObserver, never()).onNext(true);
    -    verify(aObserver, times(1)).onNext(false);
    -    verify(aObserver, never()).onError(org.mockito.Matchers.any(Throwable.class));
    -    verify(aObserver, times(1)).onCompleted();
    -  }
    -
    -  @Test
    -  public void testAnyWithOneItem() {
    -    Observable w = Observable.from(1);
    -    Observable observable = Observable.create(any(w));
    -
    -    @SuppressWarnings("unchecked")
    -    Observer aObserver = mock(Observer.class);
    -    observable.subscribe(aObserver);
    -    verify(aObserver, never()).onNext(false);
    -    verify(aObserver, times(1)).onNext(true);
    -    verify(aObserver, never()).onError(org.mockito.Matchers.any(Throwable.class));
    -    verify(aObserver, times(1)).onCompleted();
    -  }
    -
    -  @Test
    -  public void testIsEmptyWithOneItem() {
    -    Observable w = Observable.from(1);
    -    Observable observable = Observable.create(isEmpty(w));
    -
    -    @SuppressWarnings("unchecked")
    -    Observer aObserver = mock(Observer.class);
    -    observable.subscribe(aObserver);
    -    verify(aObserver, never()).onNext(true);
    -    verify(aObserver, times(1)).onNext(false);
    -    verify(aObserver, never()).onError(org.mockito.Matchers.any(Throwable.class));
    -    verify(aObserver, times(1)).onCompleted();
    -  }
    -
    -  @Test
    -  public void testAnyWithEmpty() {
    -    Observable w = Observable.empty();
    -    Observable observable = Observable.create(any(w));
    -
    -    @SuppressWarnings("unchecked")
    -    Observer aObserver = mock(Observer.class);
    -    observable.subscribe(aObserver);
    -    verify(aObserver, times(1)).onNext(false);
    -    verify(aObserver, never()).onNext(true);
    -    verify(aObserver, never()).onError(org.mockito.Matchers.any(Throwable.class));
    -    verify(aObserver, times(1)).onCompleted();
    -  }
    -
    -  @Test
    -  public void testIsEmptyWithEmpty() {
    -    Observable w = Observable.empty();
    -    Observable observable = Observable.create(isEmpty(w));
    -
    -    @SuppressWarnings("unchecked")
    -    Observer aObserver = mock(Observer.class);
    -    observable.subscribe(aObserver);
    -    verify(aObserver, times(1)).onNext(true);
    -    verify(aObserver, never()).onNext(false);
    -    verify(aObserver, never()).onError(org.mockito.Matchers.any(Throwable.class));
    -    verify(aObserver, times(1)).onCompleted();
    -  }
    -
    -  @Test
    -  public void testAnyWithPredicate1() {
    -    Observable w = Observable.from(1, 2, 3);
    -    Observable observable = Observable.create(any(w,
    -        new Func1() {
    -
    -          @Override
    -          public Boolean call(Integer t1) {
    -            return t1 < 2;
    -          }
    -        }));
    -
    -    @SuppressWarnings("unchecked")
    -    Observer aObserver = mock(Observer.class);
    -    observable.subscribe(aObserver);
    -    verify(aObserver, never()).onNext(false);
    -    verify(aObserver, times(1)).onNext(true);
    -    verify(aObserver, never()).onError(org.mockito.Matchers.any(Throwable.class));
    -    verify(aObserver, times(1)).onCompleted();
    -  }
    -
    -  @Test
    -  public void testExists1() {
    -    Observable w = Observable.from(1, 2, 3);
    -    Observable observable = Observable.create(exists(w,
    -        new Func1() {
    -
    -          @Override
    -          public Boolean call(Integer t1) {
    -            return t1 < 2;
    -          }
    -        }));
    -
    -    @SuppressWarnings("unchecked")
    -    Observer aObserver = mock(Observer.class);
    -    observable.subscribe(aObserver);
    -    verify(aObserver, never()).onNext(false);
    -    verify(aObserver, times(1)).onNext(true);
    -    verify(aObserver, never()).onError(org.mockito.Matchers.any(Throwable.class));
    -    verify(aObserver, times(1)).onCompleted();
    -  }
    -
    -  @Test
    -  public void testAnyWithPredicate2() {
    -    Observable w = Observable.from(1, 2, 3);
    -    Observable observable = Observable.create(any(w,
    -        new Func1() {
    -
    -          @Override
    -          public Boolean call(Integer t1) {
    -            return t1 < 1;
    -          }
    -        }));
    -
    -    @SuppressWarnings("unchecked")
    -    Observer aObserver = mock(Observer.class);
    -    observable.subscribe(aObserver);
    -    verify(aObserver, times(1)).onNext(false);
    -    verify(aObserver, never()).onNext(true);
    -    verify(aObserver, never()).onError(org.mockito.Matchers.any(Throwable.class));
    -    verify(aObserver, times(1)).onCompleted();
    -  }
    -
    -  @Test
    -  public void testAnyWithEmptyAndPredicate() {
    -    // If the source is empty, always output false.
    -    Observable w = Observable.empty();
    -    Observable observable = Observable.create(any(w,
    -        new Func1() {
    -
    -          @Override
    -          public Boolean call(Integer t1) {
    -            return true;
    -          }
    -        }));
    -
    -    @SuppressWarnings("unchecked")
    -    Observer aObserver = mock(Observer.class);
    -    observable.subscribe(aObserver);
    -    verify(aObserver, times(1)).onNext(false);
    -    verify(aObserver, never()).onNext(true);
    -    verify(aObserver, never()).onError(org.mockito.Matchers.any(Throwable.class));
    -    verify(aObserver, times(1)).onCompleted();
    -  }
    +    @Test
    +    public void testAnyWithTwoItems() {
    +        Observable w = Observable.from(1, 2);
    +        Observable observable = Observable.create(any(w));
    +
    +        @SuppressWarnings("unchecked")
    +        Observer aObserver = mock(Observer.class);
    +        observable.subscribe(aObserver);
    +        verify(aObserver, never()).onNext(false);
    +        verify(aObserver, times(1)).onNext(true);
    +        verify(aObserver, never()).onError(org.mockito.Matchers.any(Throwable.class));
    +        verify(aObserver, times(1)).onCompleted();
    +    }
    +
    +    @Test
    +    public void testIsEmptyWithTwoItems() {
    +        Observable w = Observable.from(1, 2);
    +        Observable observable = Observable.create(isEmpty(w));
    +
    +        @SuppressWarnings("unchecked")
    +        Observer aObserver = mock(Observer.class);
    +        observable.subscribe(aObserver);
    +        verify(aObserver, never()).onNext(true);
    +        verify(aObserver, times(1)).onNext(false);
    +        verify(aObserver, never()).onError(org.mockito.Matchers.any(Throwable.class));
    +        verify(aObserver, times(1)).onCompleted();
    +    }
    +
    +    @Test
    +    public void testAnyWithOneItem() {
    +        Observable w = Observable.from(1);
    +        Observable observable = Observable.create(any(w));
    +
    +        @SuppressWarnings("unchecked")
    +        Observer aObserver = mock(Observer.class);
    +        observable.subscribe(aObserver);
    +        verify(aObserver, never()).onNext(false);
    +        verify(aObserver, times(1)).onNext(true);
    +        verify(aObserver, never()).onError(org.mockito.Matchers.any(Throwable.class));
    +        verify(aObserver, times(1)).onCompleted();
    +    }
    +
    +    @Test
    +    public void testIsEmptyWithOneItem() {
    +        Observable w = Observable.from(1);
    +        Observable observable = Observable.create(isEmpty(w));
    +
    +        @SuppressWarnings("unchecked")
    +        Observer aObserver = mock(Observer.class);
    +        observable.subscribe(aObserver);
    +        verify(aObserver, never()).onNext(true);
    +        verify(aObserver, times(1)).onNext(false);
    +        verify(aObserver, never()).onError(org.mockito.Matchers.any(Throwable.class));
    +        verify(aObserver, times(1)).onCompleted();
    +    }
    +
    +    @Test
    +    public void testAnyWithEmpty() {
    +        Observable w = Observable.empty();
    +        Observable observable = Observable.create(any(w));
    +
    +        @SuppressWarnings("unchecked")
    +        Observer aObserver = mock(Observer.class);
    +        observable.subscribe(aObserver);
    +        verify(aObserver, times(1)).onNext(false);
    +        verify(aObserver, never()).onNext(true);
    +        verify(aObserver, never()).onError(org.mockito.Matchers.any(Throwable.class));
    +        verify(aObserver, times(1)).onCompleted();
    +    }
    +
    +    @Test
    +    public void testIsEmptyWithEmpty() {
    +        Observable w = Observable.empty();
    +        Observable observable = Observable.create(isEmpty(w));
    +
    +        @SuppressWarnings("unchecked")
    +        Observer aObserver = mock(Observer.class);
    +        observable.subscribe(aObserver);
    +        verify(aObserver, times(1)).onNext(true);
    +        verify(aObserver, never()).onNext(false);
    +        verify(aObserver, never()).onError(org.mockito.Matchers.any(Throwable.class));
    +        verify(aObserver, times(1)).onCompleted();
    +    }
    +
    +    @Test
    +    public void testAnyWithPredicate1() {
    +        Observable w = Observable.from(1, 2, 3);
    +        Observable observable = Observable.create(any(w,
    +                new Func1() {
    +
    +                    @Override
    +                    public Boolean call(Integer t1) {
    +                        return t1 < 2;
    +                    }
    +                }));
    +
    +        @SuppressWarnings("unchecked")
    +        Observer aObserver = mock(Observer.class);
    +        observable.subscribe(aObserver);
    +        verify(aObserver, never()).onNext(false);
    +        verify(aObserver, times(1)).onNext(true);
    +        verify(aObserver, never()).onError(org.mockito.Matchers.any(Throwable.class));
    +        verify(aObserver, times(1)).onCompleted();
    +    }
    +
    +    @Test
    +    public void testExists1() {
    +        Observable w = Observable.from(1, 2, 3);
    +        Observable observable = Observable.create(exists(w,
    +                new Func1() {
    +
    +                    @Override
    +                    public Boolean call(Integer t1) {
    +                        return t1 < 2;
    +                    }
    +                }));
    +
    +        @SuppressWarnings("unchecked")
    +        Observer aObserver = mock(Observer.class);
    +        observable.subscribe(aObserver);
    +        verify(aObserver, never()).onNext(false);
    +        verify(aObserver, times(1)).onNext(true);
    +        verify(aObserver, never()).onError(org.mockito.Matchers.any(Throwable.class));
    +        verify(aObserver, times(1)).onCompleted();
    +    }
    +
    +    @Test
    +    public void testAnyWithPredicate2() {
    +        Observable w = Observable.from(1, 2, 3);
    +        Observable observable = Observable.create(any(w,
    +                new Func1() {
    +
    +                    @Override
    +                    public Boolean call(Integer t1) {
    +                        return t1 < 1;
    +                    }
    +                }));
    +
    +        @SuppressWarnings("unchecked")
    +        Observer aObserver = mock(Observer.class);
    +        observable.subscribe(aObserver);
    +        verify(aObserver, times(1)).onNext(false);
    +        verify(aObserver, never()).onNext(true);
    +        verify(aObserver, never()).onError(org.mockito.Matchers.any(Throwable.class));
    +        verify(aObserver, times(1)).onCompleted();
    +    }
    +
    +    @Test
    +    public void testAnyWithEmptyAndPredicate() {
    +        // If the source is empty, always output false.
    +        Observable w = Observable.empty();
    +        Observable observable = Observable.create(any(w,
    +                new Func1() {
    +
    +                    @Override
    +                    public Boolean call(Integer t1) {
    +                        return true;
    +                    }
    +                }));
    +
    +        @SuppressWarnings("unchecked")
    +        Observer aObserver = mock(Observer.class);
    +        observable.subscribe(aObserver);
    +        verify(aObserver, times(1)).onNext(false);
    +        verify(aObserver, never()).onNext(true);
    +        verify(aObserver, never()).onError(org.mockito.Matchers.any(Throwable.class));
    +        verify(aObserver, times(1)).onCompleted();
    +    }
     }
    diff --git a/rxjava-core/src/test/java/rx/operators/OperationAverageTest.java b/rxjava-core/src/test/java/rx/operators/OperationAverageTest.java
    index 45e23bf2b9..5985959669 100644
    --- a/rxjava-core/src/test/java/rx/operators/OperationAverageTest.java
    +++ b/rxjava-core/src/test/java/rx/operators/OperationAverageTest.java
    @@ -1,111 +1,106 @@
     package rx.operators;
     
    -import org.junit.Test;
    -import rx.Observable;
    -import rx.Observer;
    -
    -import static org.mockito.Matchers.any;
    -import static org.mockito.Matchers.anyDouble;
    -import static org.mockito.Matchers.anyFloat;
    -import static org.mockito.Matchers.anyInt;
    -import static org.mockito.Matchers.anyLong;
    +import static org.mockito.Matchers.*;
     import static org.mockito.Mockito.*;
     import static rx.operators.OperationAverage.*;
     
    +import org.junit.Test;
    +
    +import rx.Observable;
    +import rx.Observer;
     
     public class OperationAverageTest {
     
    -  @SuppressWarnings("unchecked")
    -  Observer w = mock(Observer.class);
    -  @SuppressWarnings("unchecked")
    -  Observer wl = mock(Observer.class);
    -  @SuppressWarnings("unchecked")
    -  Observer wf = mock(Observer.class);
    -  @SuppressWarnings("unchecked")
    -  Observer wd = mock(Observer.class);
    -
    -  @Test
    -  public void testAverageOfAFewInts() throws Throwable {
    -    Observable src = Observable.from(1, 2, 3, 4, 6);
    -    average(src).subscribe(w);
    -
    -    verify(w, times(1)).onNext(anyInt());
    -    verify(w).onNext(3);
    -    verify(w, never()).onError(any(Throwable.class));
    -    verify(w, times(1)).onCompleted();
    -  }
    -
    -  @Test
    -  public void testEmptyAverage() throws Throwable {
    -    Observable src = Observable.empty();
    -    average(src).subscribe(w);
    -
    -    verify(w, never()).onNext(anyInt());
    -    verify(w, times(1)).onError(any(ArithmeticException.class));
    -    verify(w, never()).onCompleted();
    -  }
    -
    -  @Test
    -  public void testAverageOfAFewLongs() throws Throwable {
    -    Observable src = Observable.from(1L, 2L, 3L, 4L, 6L);
    -    averageLongs(src).subscribe(wl);
    -
    -    verify(wl, times(1)).onNext(anyLong());
    -    verify(wl).onNext(3L);
    -    verify(wl, never()).onError(any(Throwable.class));
    -    verify(wl, times(1)).onCompleted();
    -  }
    -
    -  @Test
    -  public void testEmptyAverageLongs() throws Throwable {
    -    Observable src = Observable.empty();
    -    averageLongs(src).subscribe(wl);
    -
    -    verify(wl, never()).onNext(anyLong());
    -    verify(wl, times(1)).onError(any(ArithmeticException.class));
    -    verify(wl, never()).onCompleted();
    -  }
    -
    -  @Test
    -  public void testAverageOfAFewFloats() throws Throwable {
    -    Observable src = Observable.from(1.0f, 2.0f);
    -    averageFloats(src).subscribe(wf);
    -
    -    verify(wf, times(1)).onNext(anyFloat());
    -    verify(wf).onNext(1.5f);
    -    verify(wf, never()).onError(any(Throwable.class));
    -    verify(wf, times(1)).onCompleted();
    -  }
    -
    -
    -  @Test
    -  public void testEmptyAverageFloats() throws Throwable {
    -    Observable src = Observable.empty();
    -    averageFloats(src).subscribe(wf);
    -
    -    verify(wf, never()).onNext(anyFloat());
    -    verify(wf, times(1)).onError(any(ArithmeticException.class));
    -    verify(wf, never()).onCompleted();
    -  }
    -
    -  @Test
    -  public void testAverageOfAFewDoubles() throws Throwable {
    -    Observable src = Observable.from(1.0d, 2.0d);
    -    averageDoubles(src).subscribe(wd);
    -
    -    verify(wd, times(1)).onNext(anyDouble());
    -    verify(wd).onNext(1.5d);
    -    verify(wd, never()).onError(any(Throwable.class));
    -    verify(wd, times(1)).onCompleted();
    -  }
    -
    -  @Test
    -  public void testEmptyAverageDoubles() throws Throwable {
    -    Observable src = Observable.empty();
    -    averageDoubles(src).subscribe(wd);
    -
    -    verify(wd, never()).onNext(anyDouble());
    -    verify(wd, times(1)).onError(any(ArithmeticException.class));
    -    verify(wd, never()).onCompleted();
    -  }
    +    @SuppressWarnings("unchecked")
    +    Observer w = mock(Observer.class);
    +    @SuppressWarnings("unchecked")
    +    Observer wl = mock(Observer.class);
    +    @SuppressWarnings("unchecked")
    +    Observer wf = mock(Observer.class);
    +    @SuppressWarnings("unchecked")
    +    Observer wd = mock(Observer.class);
    +
    +    @Test
    +    public void testAverageOfAFewInts() throws Throwable {
    +        Observable src = Observable.from(1, 2, 3, 4, 6);
    +        average(src).subscribe(w);
    +
    +        verify(w, times(1)).onNext(anyInt());
    +        verify(w).onNext(3);
    +        verify(w, never()).onError(any(Throwable.class));
    +        verify(w, times(1)).onCompleted();
    +    }
    +
    +    @Test
    +    public void testEmptyAverage() throws Throwable {
    +        Observable src = Observable.empty();
    +        average(src).subscribe(w);
    +
    +        verify(w, never()).onNext(anyInt());
    +        verify(w, times(1)).onError(any(ArithmeticException.class));
    +        verify(w, never()).onCompleted();
    +    }
    +
    +    @Test
    +    public void testAverageOfAFewLongs() throws Throwable {
    +        Observable src = Observable.from(1L, 2L, 3L, 4L, 6L);
    +        averageLongs(src).subscribe(wl);
    +
    +        verify(wl, times(1)).onNext(anyLong());
    +        verify(wl).onNext(3L);
    +        verify(wl, never()).onError(any(Throwable.class));
    +        verify(wl, times(1)).onCompleted();
    +    }
    +
    +    @Test
    +    public void testEmptyAverageLongs() throws Throwable {
    +        Observable src = Observable.empty();
    +        averageLongs(src).subscribe(wl);
    +
    +        verify(wl, never()).onNext(anyLong());
    +        verify(wl, times(1)).onError(any(ArithmeticException.class));
    +        verify(wl, never()).onCompleted();
    +    }
    +
    +    @Test
    +    public void testAverageOfAFewFloats() throws Throwable {
    +        Observable src = Observable.from(1.0f, 2.0f);
    +        averageFloats(src).subscribe(wf);
    +
    +        verify(wf, times(1)).onNext(anyFloat());
    +        verify(wf).onNext(1.5f);
    +        verify(wf, never()).onError(any(Throwable.class));
    +        verify(wf, times(1)).onCompleted();
    +    }
    +
    +    @Test
    +    public void testEmptyAverageFloats() throws Throwable {
    +        Observable src = Observable.empty();
    +        averageFloats(src).subscribe(wf);
    +
    +        verify(wf, never()).onNext(anyFloat());
    +        verify(wf, times(1)).onError(any(ArithmeticException.class));
    +        verify(wf, never()).onCompleted();
    +    }
    +
    +    @Test
    +    public void testAverageOfAFewDoubles() throws Throwable {
    +        Observable src = Observable.from(1.0d, 2.0d);
    +        averageDoubles(src).subscribe(wd);
    +
    +        verify(wd, times(1)).onNext(anyDouble());
    +        verify(wd).onNext(1.5d);
    +        verify(wd, never()).onError(any(Throwable.class));
    +        verify(wd, times(1)).onCompleted();
    +    }
    +
    +    @Test
    +    public void testEmptyAverageDoubles() throws Throwable {
    +        Observable src = Observable.empty();
    +        averageDoubles(src).subscribe(wd);
    +
    +        verify(wd, never()).onNext(anyDouble());
    +        verify(wd, times(1)).onError(any(ArithmeticException.class));
    +        verify(wd, never()).onCompleted();
    +    }
     }
    diff --git a/rxjava-core/src/test/java/rx/operators/OperationBufferTest.java b/rxjava-core/src/test/java/rx/operators/OperationBufferTest.java
    index fdc44e4014..c9f0e8b8e7 100644
    --- a/rxjava-core/src/test/java/rx/operators/OperationBufferTest.java
    +++ b/rxjava-core/src/test/java/rx/operators/OperationBufferTest.java
    @@ -1,9 +1,18 @@
     package rx.operators;
     
    +import static org.junit.Assert.*;
    +import static rx.operators.OperationBuffer.*;
    +
    +import java.util.ArrayList;
    +import java.util.List;
    +import java.util.concurrent.CountDownLatch;
    +import java.util.concurrent.TimeUnit;
    +
     import org.junit.Before;
     import org.junit.Test;
     import org.mockito.InOrder;
     import org.mockito.Mockito;
    +
     import rx.Observable;
     import rx.Observer;
     import rx.Subscription;
    @@ -18,333 +27,325 @@
     import rx.util.functions.Func0;
     import rx.util.functions.Func1;
     
    -import java.util.ArrayList;
    -import java.util.List;
    -import java.util.concurrent.CountDownLatch;
    -import java.util.concurrent.TimeUnit;
    +public class OperationBufferTest {
     
    -import static org.junit.Assert.assertFalse;
    -import static rx.operators.OperationBuffer.buffer;
    +    private Observer> observer;
    +    private TestScheduler scheduler;
     
    -public class OperationBufferTest {
    +    @Before
    +    @SuppressWarnings("unchecked")
    +    public void before() {
    +        observer = Mockito.mock(Observer.class);
    +        scheduler = new TestScheduler();
    +    }
    +
    +    @Test
    +    public void testComplete() {
    +        Observable source = Observable.create(new Observable.OnSubscribeFunc() {
    +            @Override
    +            public Subscription onSubscribe(Observer observer) {
    +                observer.onCompleted();
    +                return Subscriptions.empty();
    +            }
    +        });
    +
    +        Observable> buffered = Observable.create(buffer(source, 3, 3));
    +        buffered.subscribe(observer);
    +
    +        Mockito.verify(observer, Mockito.never()).onNext(Mockito.anyListOf(String.class));
    +        Mockito.verify(observer, Mockito.never()).onError(Mockito.any(Throwable.class));
    +        Mockito.verify(observer, Mockito.times(1)).onCompleted();
    +    }
    +
    +    @Test
    +    public void testSkipAndCountOverlappingBuffers() {
    +        Observable source = Observable.create(new Observable.OnSubscribeFunc() {
    +            @Override
    +            public Subscription onSubscribe(Observer observer) {
    +                observer.onNext("one");
    +                observer.onNext("two");
    +                observer.onNext("three");
    +                observer.onNext("four");
    +                observer.onNext("five");
    +                return Subscriptions.empty();
    +            }
    +        });
    +
    +        Observable> buffered = Observable.create(buffer(source, 3, 1));
    +        buffered.subscribe(observer);
    +
    +        InOrder inOrder = Mockito.inOrder(observer);
    +        inOrder.verify(observer, Mockito.times(1)).onNext(list("one", "two", "three"));
    +        inOrder.verify(observer, Mockito.times(1)).onNext(list("two", "three", "four"));
    +        inOrder.verify(observer, Mockito.times(1)).onNext(list("three", "four", "five"));
    +        inOrder.verify(observer, Mockito.never()).onNext(Mockito.anyListOf(String.class));
    +        inOrder.verify(observer, Mockito.never()).onError(Mockito.any(Throwable.class));
    +        inOrder.verify(observer, Mockito.never()).onCompleted();
    +    }
    +
    +    @Test
    +    public void testSkipAndCountGaplessBuffers() {
    +        Observable source = Observable.create(new Observable.OnSubscribeFunc() {
    +            @Override
    +            public Subscription onSubscribe(Observer observer) {
    +                observer.onNext("one");
    +                observer.onNext("two");
    +                observer.onNext("three");
    +                observer.onNext("four");
    +                observer.onNext("five");
    +                observer.onCompleted();
    +                return Subscriptions.empty();
    +            }
    +        });
    +
    +        Observable> buffered = Observable.create(buffer(source, 3, 3));
    +        buffered.subscribe(observer);
    +
    +        InOrder inOrder = Mockito.inOrder(observer);
    +        inOrder.verify(observer, Mockito.times(1)).onNext(list("one", "two", "three"));
    +        inOrder.verify(observer, Mockito.times(1)).onNext(list("four", "five"));
    +        inOrder.verify(observer, Mockito.never()).onNext(Mockito.anyListOf(String.class));
    +        inOrder.verify(observer, Mockito.never()).onError(Mockito.any(Throwable.class));
    +        inOrder.verify(observer, Mockito.times(1)).onCompleted();
    +    }
    +
    +    @Test
    +    public void testSkipAndCountBuffersWithGaps() {
    +        Observable source = Observable.create(new Observable.OnSubscribeFunc() {
    +            @Override
    +            public Subscription onSubscribe(Observer observer) {
    +                observer.onNext("one");
    +                observer.onNext("two");
    +                observer.onNext("three");
    +                observer.onNext("four");
    +                observer.onNext("five");
    +                observer.onCompleted();
    +                return Subscriptions.empty();
    +            }
    +        });
    +
    +        Observable> buffered = Observable.create(buffer(source, 2, 3));
    +        buffered.subscribe(observer);
     
    -  private Observer> observer;
    -  private TestScheduler scheduler;
    -
    -  @Before
    -  @SuppressWarnings("unchecked")
    -  public void before() {
    -    observer = Mockito.mock(Observer.class);
    -    scheduler = new TestScheduler();
    -  }
    -
    -  @Test
    -  public void testComplete() {
    -    Observable source = Observable.create(new Observable.OnSubscribeFunc() {
    -      @Override
    -      public Subscription onSubscribe(Observer observer) {
    -        observer.onCompleted();
    -        return Subscriptions.empty();
    -      }
    -    });
    -
    -    Observable> buffered = Observable.create(buffer(source, 3, 3));
    -    buffered.subscribe(observer);
    -
    -    Mockito.verify(observer, Mockito.never()).onNext(Mockito.anyListOf(String.class));
    -    Mockito.verify(observer, Mockito.never()).onError(Mockito.any(Throwable.class));
    -    Mockito.verify(observer, Mockito.times(1)).onCompleted();
    -  }
    -
    -  @Test
    -  public void testSkipAndCountOverlappingBuffers() {
    -    Observable source = Observable.create(new Observable.OnSubscribeFunc() {
    -      @Override
    -      public Subscription onSubscribe(Observer observer) {
    -        observer.onNext("one");
    -        observer.onNext("two");
    -        observer.onNext("three");
    -        observer.onNext("four");
    -        observer.onNext("five");
    -        return Subscriptions.empty();
    -      }
    -    });
    -
    -    Observable> buffered = Observable.create(buffer(source, 3, 1));
    -    buffered.subscribe(observer);
    -
    -    InOrder inOrder = Mockito.inOrder(observer);
    -    inOrder.verify(observer, Mockito.times(1)).onNext(list("one", "two", "three"));
    -    inOrder.verify(observer, Mockito.times(1)).onNext(list("two", "three", "four"));
    -    inOrder.verify(observer, Mockito.times(1)).onNext(list("three", "four", "five"));
    -    inOrder.verify(observer, Mockito.never()).onNext(Mockito.anyListOf(String.class));
    -    inOrder.verify(observer, Mockito.never()).onError(Mockito.any(Throwable.class));
    -    inOrder.verify(observer, Mockito.never()).onCompleted();
    -  }
    -
    -  @Test
    -  public void testSkipAndCountGaplessBuffers() {
    -    Observable source = Observable.create(new Observable.OnSubscribeFunc() {
    -      @Override
    -      public Subscription onSubscribe(Observer observer) {
    -        observer.onNext("one");
    -        observer.onNext("two");
    -        observer.onNext("three");
    -        observer.onNext("four");
    -        observer.onNext("five");
    -        observer.onCompleted();
    -        return Subscriptions.empty();
    -      }
    -    });
    -
    -    Observable> buffered = Observable.create(buffer(source, 3, 3));
    -    buffered.subscribe(observer);
    -
    -    InOrder inOrder = Mockito.inOrder(observer);
    -    inOrder.verify(observer, Mockito.times(1)).onNext(list("one", "two", "three"));
    -    inOrder.verify(observer, Mockito.times(1)).onNext(list("four", "five"));
    -    inOrder.verify(observer, Mockito.never()).onNext(Mockito.anyListOf(String.class));
    -    inOrder.verify(observer, Mockito.never()).onError(Mockito.any(Throwable.class));
    -    inOrder.verify(observer, Mockito.times(1)).onCompleted();
    -  }
    -
    -  @Test
    -  public void testSkipAndCountBuffersWithGaps() {
    -    Observable source = Observable.create(new Observable.OnSubscribeFunc() {
    -      @Override
    -      public Subscription onSubscribe(Observer observer) {
    -        observer.onNext("one");
    -        observer.onNext("two");
    -        observer.onNext("three");
    -        observer.onNext("four");
    -        observer.onNext("five");
    -        observer.onCompleted();
    -        return Subscriptions.empty();
    -      }
    -    });
    -
    -    Observable> buffered = Observable.create(buffer(source, 2, 3));
    -    buffered.subscribe(observer);
    -
    -    InOrder inOrder = Mockito.inOrder(observer);
    -    inOrder.verify(observer, Mockito.times(1)).onNext(list("one", "two"));
    -    inOrder.verify(observer, Mockito.times(1)).onNext(list("four", "five"));
    -    inOrder.verify(observer, Mockito.never()).onNext(Mockito.anyListOf(String.class));
    -    inOrder.verify(observer, Mockito.never()).onError(Mockito.any(Throwable.class));
    -    inOrder.verify(observer, Mockito.times(1)).onCompleted();
    -  }
    -
    -  @Test
    -  public void testTimedAndCount() {
    -    Observable source = Observable.create(new Observable.OnSubscribeFunc() {
    -      @Override
    -      public Subscription onSubscribe(Observer observer) {
    -        push(observer, "one", 10);
    -        push(observer, "two", 90);
    -        push(observer, "three", 110);
    -        push(observer, "four", 190);
    -        push(observer, "five", 210);
    -        complete(observer, 250);
    -        return Subscriptions.empty();
    -      }
    -    });
    -
    -    Observable> buffered = Observable.create(buffer(source, 100, TimeUnit.MILLISECONDS, 2, scheduler));
    -    buffered.subscribe(observer);
    -
    -    InOrder inOrder = Mockito.inOrder(observer);
    -    scheduler.advanceTimeTo(100, TimeUnit.MILLISECONDS);
    -    inOrder.verify(observer, Mockito.times(1)).onNext(list("one", "two"));
    -
    -    scheduler.advanceTimeTo(200, TimeUnit.MILLISECONDS);
    -    inOrder.verify(observer, Mockito.times(1)).onNext(list("three", "four"));
    -
    -    scheduler.advanceTimeTo(300, TimeUnit.MILLISECONDS);
    -    inOrder.verify(observer, Mockito.times(1)).onNext(list("five"));
    -    inOrder.verify(observer, Mockito.never()).onNext(Mockito.anyListOf(String.class));
    -    inOrder.verify(observer, Mockito.never()).onError(Mockito.any(Throwable.class));
    -    inOrder.verify(observer, Mockito.times(1)).onCompleted();
    -  }
    -
    -  @Test
    -  public void testTimed() {
    -    Observable source = Observable.create(new Observable.OnSubscribeFunc() {
    -      @Override
    -      public Subscription onSubscribe(Observer observer) {
    -        push(observer, "one", 98);
    -        push(observer, "two", 99);
    -        push(observer, "three", 100);
    -        push(observer, "four", 101);
    -        push(observer, "five", 102);
    -        complete(observer, 150);
    -        return Subscriptions.empty();
    -      }
    -    });
    -
    -    Observable> buffered = Observable.create(buffer(source, 100, TimeUnit.MILLISECONDS, scheduler));
    -    buffered.subscribe(observer);
    -
    -    InOrder inOrder = Mockito.inOrder(observer);
    -    scheduler.advanceTimeTo(101, TimeUnit.MILLISECONDS);
    -    inOrder.verify(observer, Mockito.times(1)).onNext(list("one", "two", "three"));
    -
    -    scheduler.advanceTimeTo(201, TimeUnit.MILLISECONDS);
    -    inOrder.verify(observer, Mockito.times(1)).onNext(list("four", "five"));
    -    inOrder.verify(observer, Mockito.never()).onNext(Mockito.anyListOf(String.class));
    -    inOrder.verify(observer, Mockito.never()).onError(Mockito.any(Throwable.class));
    -    inOrder.verify(observer, Mockito.times(1)).onCompleted();
    -  }
    -
    -  @Test
    -  public void testObservableBasedOpenerAndCloser() {
    -    Observable source = Observable.create(new Observable.OnSubscribeFunc() {
    -      @Override
    -      public Subscription onSubscribe(Observer observer) {
    -        push(observer, "one", 10);
    -        push(observer, "two", 60);
    -        push(observer, "three", 110);
    -        push(observer, "four", 160);
    -        push(observer, "five", 210);
    -        complete(observer, 500);
    -        return Subscriptions.empty();
    -      }
    -    });
    -
    -    Observable openings = Observable.create(new Observable.OnSubscribeFunc() {
    -      @Override
    -      public Subscription onSubscribe(Observer observer) {
    -        push(observer, Openings.create(), 50);
    -        push(observer, Openings.create(), 200);
    -        complete(observer, 250);
    -        return Subscriptions.empty();
    -      }
    -    });
    -
    -    Func1> closer = new Func1>() {
    -      @Override
    -      public Observable call(Opening opening) {
    -        return Observable.create(new Observable.OnSubscribeFunc() {
    -          @Override
    -          public Subscription onSubscribe(Observer observer) {
    -            push(observer, Closings.create(), 100);
    -            complete(observer, 101);
    -            return Subscriptions.empty();
    -          }
    +        InOrder inOrder = Mockito.inOrder(observer);
    +        inOrder.verify(observer, Mockito.times(1)).onNext(list("one", "two"));
    +        inOrder.verify(observer, Mockito.times(1)).onNext(list("four", "five"));
    +        inOrder.verify(observer, Mockito.never()).onNext(Mockito.anyListOf(String.class));
    +        inOrder.verify(observer, Mockito.never()).onError(Mockito.any(Throwable.class));
    +        inOrder.verify(observer, Mockito.times(1)).onCompleted();
    +    }
    +
    +    @Test
    +    public void testTimedAndCount() {
    +        Observable source = Observable.create(new Observable.OnSubscribeFunc() {
    +            @Override
    +            public Subscription onSubscribe(Observer observer) {
    +                push(observer, "one", 10);
    +                push(observer, "two", 90);
    +                push(observer, "three", 110);
    +                push(observer, "four", 190);
    +                push(observer, "five", 210);
    +                complete(observer, 250);
    +                return Subscriptions.empty();
    +            }
    +        });
    +
    +        Observable> buffered = Observable.create(buffer(source, 100, TimeUnit.MILLISECONDS, 2, scheduler));
    +        buffered.subscribe(observer);
    +
    +        InOrder inOrder = Mockito.inOrder(observer);
    +        scheduler.advanceTimeTo(100, TimeUnit.MILLISECONDS);
    +        inOrder.verify(observer, Mockito.times(1)).onNext(list("one", "two"));
    +
    +        scheduler.advanceTimeTo(200, TimeUnit.MILLISECONDS);
    +        inOrder.verify(observer, Mockito.times(1)).onNext(list("three", "four"));
    +
    +        scheduler.advanceTimeTo(300, TimeUnit.MILLISECONDS);
    +        inOrder.verify(observer, Mockito.times(1)).onNext(list("five"));
    +        inOrder.verify(observer, Mockito.never()).onNext(Mockito.anyListOf(String.class));
    +        inOrder.verify(observer, Mockito.never()).onError(Mockito.any(Throwable.class));
    +        inOrder.verify(observer, Mockito.times(1)).onCompleted();
    +    }
    +
    +    @Test
    +    public void testTimed() {
    +        Observable source = Observable.create(new Observable.OnSubscribeFunc() {
    +            @Override
    +            public Subscription onSubscribe(Observer observer) {
    +                push(observer, "one", 98);
    +                push(observer, "two", 99);
    +                push(observer, "three", 100);
    +                push(observer, "four", 101);
    +                push(observer, "five", 102);
    +                complete(observer, 150);
    +                return Subscriptions.empty();
    +            }
    +        });
    +
    +        Observable> buffered = Observable.create(buffer(source, 100, TimeUnit.MILLISECONDS, scheduler));
    +        buffered.subscribe(observer);
    +
    +        InOrder inOrder = Mockito.inOrder(observer);
    +        scheduler.advanceTimeTo(101, TimeUnit.MILLISECONDS);
    +        inOrder.verify(observer, Mockito.times(1)).onNext(list("one", "two", "three"));
    +
    +        scheduler.advanceTimeTo(201, TimeUnit.MILLISECONDS);
    +        inOrder.verify(observer, Mockito.times(1)).onNext(list("four", "five"));
    +        inOrder.verify(observer, Mockito.never()).onNext(Mockito.anyListOf(String.class));
    +        inOrder.verify(observer, Mockito.never()).onError(Mockito.any(Throwable.class));
    +        inOrder.verify(observer, Mockito.times(1)).onCompleted();
    +    }
    +
    +    @Test
    +    public void testObservableBasedOpenerAndCloser() {
    +        Observable source = Observable.create(new Observable.OnSubscribeFunc() {
    +            @Override
    +            public Subscription onSubscribe(Observer observer) {
    +                push(observer, "one", 10);
    +                push(observer, "two", 60);
    +                push(observer, "three", 110);
    +                push(observer, "four", 160);
    +                push(observer, "five", 210);
    +                complete(observer, 500);
    +                return Subscriptions.empty();
    +            }
    +        });
    +
    +        Observable openings = Observable.create(new Observable.OnSubscribeFunc() {
    +            @Override
    +            public Subscription onSubscribe(Observer observer) {
    +                push(observer, Openings.create(), 50);
    +                push(observer, Openings.create(), 200);
    +                complete(observer, 250);
    +                return Subscriptions.empty();
    +            }
             });
    -      }
    -    };
    -
    -    Observable> buffered = Observable.create(buffer(source, openings, closer));
    -    buffered.subscribe(observer);
    -
    -    InOrder inOrder = Mockito.inOrder(observer);
    -    scheduler.advanceTimeTo(500, TimeUnit.MILLISECONDS);
    -    inOrder.verify(observer, Mockito.times(1)).onNext(list("two", "three"));
    -    inOrder.verify(observer, Mockito.times(1)).onNext(list("five"));
    -    inOrder.verify(observer, Mockito.never()).onNext(Mockito.anyListOf(String.class));
    -    inOrder.verify(observer, Mockito.never()).onError(Mockito.any(Throwable.class));
    -    inOrder.verify(observer, Mockito.times(1)).onCompleted();
    -  }
    -
    -  @Test
    -  public void testObservableBasedCloser() {
    -    Observable source = Observable.create(new Observable.OnSubscribeFunc() {
    -      @Override
    -      public Subscription onSubscribe(Observer observer) {
    -        push(observer, "one", 10);
    -        push(observer, "two", 60);
    -        push(observer, "three", 110);
    -        push(observer, "four", 160);
    -        push(observer, "five", 210);
    -        complete(observer, 250);
    -        return Subscriptions.empty();
    -      }
    -    });
    -
    -    Func0> closer = new Func0>() {
    -      @Override
    -      public Observable call() {
    -        return Observable.create(new Observable.OnSubscribeFunc() {
    -          @Override
    -          public Subscription onSubscribe(Observer observer) {
    -            push(observer, Closings.create(), 100);
    -            complete(observer, 101);
    -            return Subscriptions.empty();
    -          }
    +
    +        Func1> closer = new Func1>() {
    +            @Override
    +            public Observable call(Opening opening) {
    +                return Observable.create(new Observable.OnSubscribeFunc() {
    +                    @Override
    +                    public Subscription onSubscribe(Observer observer) {
    +                        push(observer, Closings.create(), 100);
    +                        complete(observer, 101);
    +                        return Subscriptions.empty();
    +                    }
    +                });
    +            }
    +        };
    +
    +        Observable> buffered = Observable.create(buffer(source, openings, closer));
    +        buffered.subscribe(observer);
    +
    +        InOrder inOrder = Mockito.inOrder(observer);
    +        scheduler.advanceTimeTo(500, TimeUnit.MILLISECONDS);
    +        inOrder.verify(observer, Mockito.times(1)).onNext(list("two", "three"));
    +        inOrder.verify(observer, Mockito.times(1)).onNext(list("five"));
    +        inOrder.verify(observer, Mockito.never()).onNext(Mockito.anyListOf(String.class));
    +        inOrder.verify(observer, Mockito.never()).onError(Mockito.any(Throwable.class));
    +        inOrder.verify(observer, Mockito.times(1)).onCompleted();
    +    }
    +
    +    @Test
    +    public void testObservableBasedCloser() {
    +        Observable source = Observable.create(new Observable.OnSubscribeFunc() {
    +            @Override
    +            public Subscription onSubscribe(Observer observer) {
    +                push(observer, "one", 10);
    +                push(observer, "two", 60);
    +                push(observer, "three", 110);
    +                push(observer, "four", 160);
    +                push(observer, "five", 210);
    +                complete(observer, 250);
    +                return Subscriptions.empty();
    +            }
             });
    -      }
    -    };
    -
    -    Observable> buffered = Observable.create(buffer(source, closer));
    -    buffered.subscribe(observer);
    -
    -    InOrder inOrder = Mockito.inOrder(observer);
    -    scheduler.advanceTimeTo(500, TimeUnit.MILLISECONDS);
    -    inOrder.verify(observer, Mockito.times(1)).onNext(list("one", "two"));
    -    inOrder.verify(observer, Mockito.times(1)).onNext(list("three", "four"));
    -    inOrder.verify(observer, Mockito.times(1)).onNext(list("five"));
    -    inOrder.verify(observer, Mockito.never()).onNext(Mockito.anyListOf(String.class));
    -    inOrder.verify(observer, Mockito.never()).onError(Mockito.any(Throwable.class));
    -    inOrder.verify(observer, Mockito.times(1)).onCompleted();
    -  }
    -
    -  @Test
    -  public void testLongTimeAction() throws InterruptedException {
    -    final CountDownLatch latch = new CountDownLatch(1);
    -    LongTimeAction action = new LongTimeAction(latch);
    -    Observable.from(1).buffer(10, TimeUnit.MILLISECONDS, 10)
    -        .subscribe(action);
    -    latch.await();
    -    assertFalse(action.fail);
    -  }
    -
    -  private static class LongTimeAction implements Action1> {
    -
    -    CountDownLatch latch;
    -    boolean fail = false;
    -
    -    public LongTimeAction(CountDownLatch latch) {
    -      this.latch = latch;
    +
    +        Func0> closer = new Func0>() {
    +            @Override
    +            public Observable call() {
    +                return Observable.create(new Observable.OnSubscribeFunc() {
    +                    @Override
    +                    public Subscription onSubscribe(Observer observer) {
    +                        push(observer, Closings.create(), 100);
    +                        complete(observer, 101);
    +                        return Subscriptions.empty();
    +                    }
    +                });
    +            }
    +        };
    +
    +        Observable> buffered = Observable.create(buffer(source, closer));
    +        buffered.subscribe(observer);
    +
    +        InOrder inOrder = Mockito.inOrder(observer);
    +        scheduler.advanceTimeTo(500, TimeUnit.MILLISECONDS);
    +        inOrder.verify(observer, Mockito.times(1)).onNext(list("one", "two"));
    +        inOrder.verify(observer, Mockito.times(1)).onNext(list("three", "four"));
    +        inOrder.verify(observer, Mockito.times(1)).onNext(list("five"));
    +        inOrder.verify(observer, Mockito.never()).onNext(Mockito.anyListOf(String.class));
    +        inOrder.verify(observer, Mockito.never()).onError(Mockito.any(Throwable.class));
    +        inOrder.verify(observer, Mockito.times(1)).onCompleted();
    +    }
    +
    +    @Test
    +    public void testLongTimeAction() throws InterruptedException {
    +        final CountDownLatch latch = new CountDownLatch(1);
    +        LongTimeAction action = new LongTimeAction(latch);
    +        Observable.from(1).buffer(10, TimeUnit.MILLISECONDS, 10)
    +                .subscribe(action);
    +        latch.await();
    +        assertFalse(action.fail);
    +    }
    +
    +    private static class LongTimeAction implements Action1> {
    +
    +        CountDownLatch latch;
    +        boolean fail = false;
    +
    +        public LongTimeAction(CountDownLatch latch) {
    +            this.latch = latch;
    +        }
    +
    +        @Override
    +        public void call(List t1) {
    +            try {
    +                if (fail) {
    +                    return;
    +                }
    +                Thread.sleep(200);
    +            } catch (InterruptedException e) {
    +                fail = true;
    +            } finally {
    +                latch.countDown();
    +            }
    +        }
         }
     
    -    @Override
    -    public void call(List t1) {
    -      try {
    -        if (fail) {
    -          return;
    +    private List list(String... args) {
    +        List list = new ArrayList();
    +        for (String arg : args) {
    +            list.add(arg);
             }
    -        Thread.sleep(200);
    -      } catch (InterruptedException e) {
    -        fail = true;
    -      } finally {
    -        latch.countDown();
    -      }
    +        return list;
    +    }
    +
    +    private  void push(final Observer observer, final T value, int delay) {
    +        scheduler.schedule(new Action0() {
    +            @Override
    +            public void call() {
    +                observer.onNext(value);
    +            }
    +        }, delay, TimeUnit.MILLISECONDS);
         }
    -  }
     
    -  private List list(String... args) {
    -    List list = new ArrayList();
    -    for (String arg : args) {
    -      list.add(arg);
    +    private void complete(final Observer observer, int delay) {
    +        scheduler.schedule(new Action0() {
    +            @Override
    +            public void call() {
    +                observer.onCompleted();
    +            }
    +        }, delay, TimeUnit.MILLISECONDS);
         }
    -    return list;
    -  }
    -
    -  private  void push(final Observer observer, final T value, int delay) {
    -    scheduler.schedule(new Action0() {
    -      @Override
    -      public void call() {
    -        observer.onNext(value);
    -      }
    -    }, delay, TimeUnit.MILLISECONDS);
    -  }
    -
    -  private void complete(final Observer observer, int delay) {
    -    scheduler.schedule(new Action0() {
    -      @Override
    -      public void call() {
    -        observer.onCompleted();
    -      }
    -    }, delay, TimeUnit.MILLISECONDS);
    -  }
     }
    diff --git a/rxjava-core/src/test/java/rx/operators/OperationCacheTest.java b/rxjava-core/src/test/java/rx/operators/OperationCacheTest.java
    index 9f9ab051a1..60f4b5f4fc 100644
    --- a/rxjava-core/src/test/java/rx/operators/OperationCacheTest.java
    +++ b/rxjava-core/src/test/java/rx/operators/OperationCacheTest.java
    @@ -1,72 +1,72 @@
     package rx.operators;
     
    +import static org.junit.Assert.*;
    +import static rx.operators.OperationCache.*;
    +
    +import java.util.concurrent.CountDownLatch;
    +import java.util.concurrent.TimeUnit;
    +import java.util.concurrent.atomic.AtomicInteger;
    +
     import org.junit.Test;
    +
     import rx.Observable;
     import rx.Observer;
     import rx.Subscription;
     import rx.subscriptions.BooleanSubscription;
     import rx.util.functions.Action1;
     
    -import java.util.concurrent.CountDownLatch;
    -import java.util.concurrent.TimeUnit;
    -import java.util.concurrent.atomic.AtomicInteger;
    -
    -import static org.junit.Assert.assertEquals;
    -import static org.junit.Assert.fail;
    -import static rx.operators.OperationCache.cache;
    -
     public class OperationCacheTest {
     
    -  @Test
    -  public void testCache() throws InterruptedException {
    -    final AtomicInteger counter = new AtomicInteger();
    -    Observable o = Observable.create(cache(Observable.create(new Observable.OnSubscribeFunc() {
    +    @Test
    +    public void testCache() throws InterruptedException {
    +        final AtomicInteger counter = new AtomicInteger();
    +        Observable o = Observable.create(cache(Observable.create(new Observable.OnSubscribeFunc() {
     
    -      @Override
    -      public Subscription onSubscribe(final Observer observer) {
    -        final BooleanSubscription subscription = new BooleanSubscription();
    -        new Thread(new Runnable() {
    +            @Override
    +            public Subscription onSubscribe(final Observer observer) {
    +                final BooleanSubscription subscription = new BooleanSubscription();
    +                new Thread(new Runnable() {
     
    -          @Override
    -          public void run() {
    -            counter.incrementAndGet();
    -            System.out.println("published observable being executed");
    -            observer.onNext("one");
    -            observer.onCompleted();
    -          }
    -        }).start();
    -        return subscription;
    -      }
    -    })));
    +                    @Override
    +                    public void run() {
    +                        counter.incrementAndGet();
    +                        System.out.println("published observable being executed");
    +                        observer.onNext("one");
    +                        observer.onCompleted();
    +                    }
    +                }).start();
    +                return subscription;
    +            }
    +        })));
     
    -    // we then expect the following 2 subscriptions to get that same value
    -    final CountDownLatch latch = new CountDownLatch(2);
    +        // we then expect the following 2 subscriptions to get that same value
    +        final CountDownLatch latch = new CountDownLatch(2);
     
    -    // subscribe once
    -    o.subscribe(new Action1() {
    +        // subscribe once
    +        o.subscribe(new Action1() {
     
    -      @Override
    -      public void call(String v) {
    -        assertEquals("one", v);
    -        System.out.println("v: " + v);
    -        latch.countDown();
    -      }
    -    });
    +            @Override
    +            public void call(String v) {
    +                assertEquals("one", v);
    +                System.out.println("v: " + v);
    +                latch.countDown();
    +            }
    +        });
     
    -    // subscribe again
    -    o.subscribe(new Action1() {
    +        // subscribe again
    +        o.subscribe(new Action1() {
     
    -      @Override
    -      public void call(String v) {
    -        assertEquals("one", v);
    -        System.out.println("v: " + v);
    -        latch.countDown();
    -      }
    -    });
    +            @Override
    +            public void call(String v) {
    +                assertEquals("one", v);
    +                System.out.println("v: " + v);
    +                latch.countDown();
    +            }
    +        });
     
    -    if (!latch.await(1000, TimeUnit.MILLISECONDS)) {
    -      fail("subscriptions did not receive values");
    +        if (!latch.await(1000, TimeUnit.MILLISECONDS)) {
    +            fail("subscriptions did not receive values");
    +        }
    +        assertEquals(1, counter.get());
         }
    -    assertEquals(1, counter.get());
    -  }
     }
    diff --git a/rxjava-core/src/test/java/rx/operators/OperationCastTest.java b/rxjava-core/src/test/java/rx/operators/OperationCastTest.java
    index 1a87c915fc..f5c0b6b515 100644
    --- a/rxjava-core/src/test/java/rx/operators/OperationCastTest.java
    +++ b/rxjava-core/src/test/java/rx/operators/OperationCastTest.java
    @@ -1,40 +1,41 @@
     package rx.operators;
     
    +import static org.mockito.Mockito.*;
    +import static rx.operators.OperationCast.*;
    +
     import org.junit.Test;
    +
     import rx.Observable;
     import rx.Observer;
     
    -import static org.mockito.Mockito.*;
    -import static rx.operators.OperationCast.cast;
    -
     public class OperationCastTest {
     
    -  @Test
    -  public void testCast() {
    -    Observable source = Observable.from(1, 2);
    -    Observable observable = Observable.create(cast(source,
    -        Integer.class));
    -
    -    @SuppressWarnings("unchecked")
    -    Observer aObserver = mock(Observer.class);
    -    observable.subscribe(aObserver);
    -    verify(aObserver, times(1)).onNext(1);
    -    verify(aObserver, times(1)).onNext(1);
    -    verify(aObserver, never()).onError(
    -        org.mockito.Matchers.any(Throwable.class));
    -    verify(aObserver, times(1)).onCompleted();
    -  }
    -
    -  @Test
    -  public void testCastWithWrongType() {
    -    Observable source = Observable.from(1, 2);
    -    Observable observable = Observable.create(cast(source,
    -        Boolean.class));
    -
    -    @SuppressWarnings("unchecked")
    -    Observer aObserver = mock(Observer.class);
    -    observable.subscribe(aObserver);
    -    verify(aObserver, times(1)).onError(
    -        org.mockito.Matchers.any(ClassCastException.class));
    -  }
    +    @Test
    +    public void testCast() {
    +        Observable source = Observable.from(1, 2);
    +        Observable observable = Observable.create(cast(source,
    +                Integer.class));
    +
    +        @SuppressWarnings("unchecked")
    +        Observer aObserver = mock(Observer.class);
    +        observable.subscribe(aObserver);
    +        verify(aObserver, times(1)).onNext(1);
    +        verify(aObserver, times(1)).onNext(1);
    +        verify(aObserver, never()).onError(
    +                org.mockito.Matchers.any(Throwable.class));
    +        verify(aObserver, times(1)).onCompleted();
    +    }
    +
    +    @Test
    +    public void testCastWithWrongType() {
    +        Observable source = Observable.from(1, 2);
    +        Observable observable = Observable.create(cast(source,
    +                Boolean.class));
    +
    +        @SuppressWarnings("unchecked")
    +        Observer aObserver = mock(Observer.class);
    +        observable.subscribe(aObserver);
    +        verify(aObserver, times(1)).onError(
    +                org.mockito.Matchers.any(ClassCastException.class));
    +    }
     }
    diff --git a/rxjava-core/src/test/java/rx/operators/OperationCombineLatestTest.java b/rxjava-core/src/test/java/rx/operators/OperationCombineLatestTest.java
    index b7ea62a8fd..b5bb863b2e 100644
    --- a/rxjava-core/src/test/java/rx/operators/OperationCombineLatestTest.java
    +++ b/rxjava-core/src/test/java/rx/operators/OperationCombineLatestTest.java
    @@ -1,619 +1,621 @@
     package rx.operators;
     
    +import static org.mockito.Matchers.*;
    +import static org.mockito.Mockito.*;
    +import static rx.operators.OperationCombineLatest.*;
    +
    +import java.util.Arrays;
    +
     import org.junit.Test;
     import org.mockito.InOrder;
     import org.mockito.Matchers;
    +
     import rx.Observable;
     import rx.Observer;
     import rx.Subscription;
    +import rx.operators.OperationCombineLatest.Aggregator;
    +import rx.operators.OperationCombineLatest.CombineObserver;
     import rx.subscriptions.Subscriptions;
     import rx.util.functions.Func2;
     import rx.util.functions.Func3;
     import rx.util.functions.FuncN;
     
    -import java.util.Arrays;
    +public class OperationCombineLatestTest {
     
    -import static org.mockito.Matchers.any;
    -import static org.mockito.Matchers.anyString;
    -import static org.mockito.Mockito.*;
    -import static rx.operators.OperationCombineLatest.Aggregator;
    -import static rx.operators.OperationCombineLatest.CombineObserver;
    -import static rx.operators.OperationCombineLatest.combineLatest;
    +    @Test
    +    public void testCombineLatestWithFunctionThatThrowsAnException() {
    +        @SuppressWarnings("unchecked")
    +        // mock calls don't do generics
    +        Observer w = mock(Observer.class);
     
    -public class OperationCombineLatestTest {
    +        TestObservable w1 = new TestObservable();
    +        TestObservable w2 = new TestObservable();
    +
    +        Observable combined = Observable.create(combineLatest(Observable.create(w1), Observable.create(w2), new Func2() {
    +            @Override
    +            public String call(String v1, String v2) {
    +                throw new RuntimeException("I don't work.");
    +            }
    +        }));
    +        combined.subscribe(w);
     
    -  @Test
    -  public void testCombineLatestWithFunctionThatThrowsAnException() {
    -    @SuppressWarnings("unchecked") // mock calls don't do generics
    +        w1.observer.onNext("first value of w1");
    +        w2.observer.onNext("first value of w2");
    +
    +        verify(w, never()).onNext(anyString());
    +        verify(w, never()).onCompleted();
    +        verify(w, times(1)).onError(Matchers. any());
    +    }
    +
    +    @Test
    +    public void testCombineLatestDifferentLengthObservableSequences1() {
    +        @SuppressWarnings("unchecked")
    +        // mock calls don't do generics
             Observer w = mock(Observer.class);
     
    -    TestObservable w1 = new TestObservable();
    -    TestObservable w2 = new TestObservable();
    +        TestObservable w1 = new TestObservable();
    +        TestObservable w2 = new TestObservable();
    +        TestObservable w3 = new TestObservable();
    +
    +        Observable combineLatestW = Observable.create(combineLatest(Observable.create(w1), Observable.create(w2), Observable.create(w3), getConcat3StringsCombineLatestFunction()));
    +        combineLatestW.subscribe(w);
    +
    +        /* simulate sending data */
    +        // once for w1
    +        w1.observer.onNext("1a");
    +        w2.observer.onNext("2a");
    +        w3.observer.onNext("3a");
    +        w1.observer.onCompleted();
    +        // twice for w2
    +        w2.observer.onNext("2b");
    +        w2.observer.onCompleted();
    +        // 4 times for w3
    +        w3.observer.onNext("3b");
    +        w3.observer.onNext("3c");
    +        w3.observer.onNext("3d");
    +        w3.observer.onCompleted();
    +
    +        /* we should have been called 4 times on the Observer */
    +        InOrder inOrder = inOrder(w);
    +        inOrder.verify(w).onNext("1a2a3a");
    +        inOrder.verify(w).onNext("1a2b3a");
    +        inOrder.verify(w).onNext("1a2b3b");
    +        inOrder.verify(w).onNext("1a2b3c");
    +        inOrder.verify(w).onNext("1a2b3d");
    +        inOrder.verify(w, never()).onNext(anyString());
    +        inOrder.verify(w, times(1)).onCompleted();
    +    }
     
    -    Observable combined = Observable.create(combineLatest(Observable.create(w1), Observable.create(w2), new Func2() {
    -      @Override
    -      public String call(String v1, String v2) {
    -        throw new RuntimeException("I don't work.");
    -      }
    -    }));
    -    combined.subscribe(w);
    +    @Test
    +    public void testCombineLatestDifferentLengthObservableSequences2() {
    +        @SuppressWarnings("unchecked")
    +        Observer w = mock(Observer.class);
     
    -    w1.observer.onNext("first value of w1");
    -    w2.observer.onNext("first value of w2");
    +        TestObservable w1 = new TestObservable();
    +        TestObservable w2 = new TestObservable();
    +        TestObservable w3 = new TestObservable();
    +
    +        Observable combineLatestW = Observable.create(combineLatest(Observable.create(w1), Observable.create(w2), Observable.create(w3), getConcat3StringsCombineLatestFunction()));
    +        combineLatestW.subscribe(w);
    +
    +        /* simulate sending data */
    +        // 4 times for w1
    +        w1.observer.onNext("1a");
    +        w1.observer.onNext("1b");
    +        w1.observer.onNext("1c");
    +        w1.observer.onNext("1d");
    +        w1.observer.onCompleted();
    +        // twice for w2
    +        w2.observer.onNext("2a");
    +        w2.observer.onNext("2b");
    +        w2.observer.onCompleted();
    +        // 1 times for w3
    +        w3.observer.onNext("3a");
    +        w3.observer.onCompleted();
    +
    +        /* we should have been called 1 time only on the Observer since we only combine the "latest" we don't go back and loop through others once completed */
    +        InOrder inOrder = inOrder(w);
    +        inOrder.verify(w, times(1)).onNext("1d2b3a");
    +        inOrder.verify(w, never()).onNext(anyString());
    +
    +        inOrder.verify(w, times(1)).onCompleted();
     
    -    verify(w, never()).onNext(anyString());
    -    verify(w, never()).onCompleted();
    -    verify(w, times(1)).onError(Matchers.any());
    -  }
    +    }
     
    -  @Test
    -  public void testCombineLatestDifferentLengthObservableSequences1() {
    -    @SuppressWarnings("unchecked") // mock calls don't do generics
    +    @Test
    +    public void testCombineLatestWithInterleavingSequences() {
    +        @SuppressWarnings("unchecked")
             Observer w = mock(Observer.class);
     
    -    TestObservable w1 = new TestObservable();
    -    TestObservable w2 = new TestObservable();
    -    TestObservable w3 = new TestObservable();
    -
    -    Observable combineLatestW = Observable.create(combineLatest(Observable.create(w1), Observable.create(w2), Observable.create(w3), getConcat3StringsCombineLatestFunction()));
    -    combineLatestW.subscribe(w);
    -
    -            /* simulate sending data */
    -    // once for w1
    -    w1.observer.onNext("1a");
    -    w2.observer.onNext("2a");
    -    w3.observer.onNext("3a");
    -    w1.observer.onCompleted();
    -    // twice for w2
    -    w2.observer.onNext("2b");
    -    w2.observer.onCompleted();
    -    // 4 times for w3
    -    w3.observer.onNext("3b");
    -    w3.observer.onNext("3c");
    -    w3.observer.onNext("3d");
    -    w3.observer.onCompleted();
    -
    -            /* we should have been called 4 times on the Observer */
    -    InOrder inOrder = inOrder(w);
    -    inOrder.verify(w).onNext("1a2a3a");
    -    inOrder.verify(w).onNext("1a2b3a");
    -    inOrder.verify(w).onNext("1a2b3b");
    -    inOrder.verify(w).onNext("1a2b3c");
    -    inOrder.verify(w).onNext("1a2b3d");
    -    inOrder.verify(w, never()).onNext(anyString());
    -    inOrder.verify(w, times(1)).onCompleted();
    -  }
    -
    -  @Test
    -  public void testCombineLatestDifferentLengthObservableSequences2() {
    +        TestObservable w1 = new TestObservable();
    +        TestObservable w2 = new TestObservable();
    +        TestObservable w3 = new TestObservable();
    +
    +        Observable combineLatestW = Observable.create(combineLatest(Observable.create(w1), Observable.create(w2), Observable.create(w3), getConcat3StringsCombineLatestFunction()));
    +        combineLatestW.subscribe(w);
    +
    +        /* simulate sending data */
    +        w1.observer.onNext("1a");
    +        w2.observer.onNext("2a");
    +        w2.observer.onNext("2b");
    +        w3.observer.onNext("3a");
    +
    +        w1.observer.onNext("1b");
    +        w2.observer.onNext("2c");
    +        w2.observer.onNext("2d");
    +        w3.observer.onNext("3b");
    +
    +        w1.observer.onCompleted();
    +        w2.observer.onCompleted();
    +        w3.observer.onCompleted();
    +
    +        /* we should have been called 5 times on the Observer */
    +        InOrder inOrder = inOrder(w);
    +        inOrder.verify(w).onNext("1a2b3a");
    +        inOrder.verify(w).onNext("1b2b3a");
    +        inOrder.verify(w).onNext("1b2c3a");
    +        inOrder.verify(w).onNext("1b2d3a");
    +        inOrder.verify(w).onNext("1b2d3b");
    +
    +        inOrder.verify(w, never()).onNext(anyString());
    +        inOrder.verify(w, times(1)).onCompleted();
    +    }
    +
    +    /**
    +     * Testing internal private logic due to the complexity so I want to use TDD to test as a I build it rather than relying purely on the overall functionality expected by the public methods.
    +     */
    +    @SuppressWarnings("unchecked")
    +    /* mock calls don't do generics */
    +    @Test
    +    public void testAggregatorSimple() {
    +        FuncN combineLatestFunction = getConcatCombineLatestFunction();
    +        /* create the aggregator which will execute the combineLatest function when all Observables provide values */
    +        Aggregator a = new Aggregator(combineLatestFunction);
    +
    +        /* define a Observer to receive aggregated events */
    +        Observer aObserver = mock(Observer.class);
    +        Observable.create(a).subscribe(aObserver);
    +
    +        /* mock the Observable Observers that are 'pushing' data for us */
    +        CombineObserver r1 = mock(CombineObserver.class);
    +        CombineObserver r2 = mock(CombineObserver.class);
    +
    +        /* pretend we're starting up */
    +        a.addObserver(r1);
    +        a.addObserver(r2);
    +
    +        /* simulate the Observables pushing data into the aggregator */
    +        a.next(r1, "hello");
    +        a.next(r2, "world");
    +
    +        InOrder inOrder = inOrder(aObserver);
    +
    +        verify(aObserver, never()).onError(any(Throwable.class));
    +        verify(aObserver, never()).onCompleted();
    +        inOrder.verify(aObserver, times(1)).onNext("helloworld");
    +
    +        a.next(r1, "hello ");
    +        a.next(r2, "again");
    +
    +        verify(aObserver, never()).onError(any(Throwable.class));
    +        verify(aObserver, never()).onCompleted();
    +        inOrder.verify(aObserver, times(1)).onNext("hello again");
    +
    +        a.complete(r1);
    +        a.complete(r2);
    +
    +        inOrder.verify(aObserver, never()).onNext(anyString());
    +        verify(aObserver, times(1)).onCompleted();
    +    }
    +
         @SuppressWarnings("unchecked")
    -    Observer w = mock(Observer.class);
    -
    -    TestObservable w1 = new TestObservable();
    -    TestObservable w2 = new TestObservable();
    -    TestObservable w3 = new TestObservable();
    -
    -    Observable combineLatestW = Observable.create(combineLatest(Observable.create(w1), Observable.create(w2), Observable.create(w3), getConcat3StringsCombineLatestFunction()));
    -    combineLatestW.subscribe(w);
    -
    -            /* simulate sending data */
    -    // 4 times for w1
    -    w1.observer.onNext("1a");
    -    w1.observer.onNext("1b");
    -    w1.observer.onNext("1c");
    -    w1.observer.onNext("1d");
    -    w1.observer.onCompleted();
    -    // twice for w2
    -    w2.observer.onNext("2a");
    -    w2.observer.onNext("2b");
    -    w2.observer.onCompleted();
    -    // 1 times for w3
    -    w3.observer.onNext("3a");
    -    w3.observer.onCompleted();
    -
    -            /* we should have been called 1 time only on the Observer since we only combine the "latest" we don't go back and loop through others once completed */
    -    InOrder inOrder = inOrder(w);
    -    inOrder.verify(w, times(1)).onNext("1d2b3a");
    -    inOrder.verify(w, never()).onNext(anyString());
    -
    -    inOrder.verify(w, times(1)).onCompleted();
    -
    -  }
    -
    -  @Test
    -  public void testCombineLatestWithInterleavingSequences() {
    +    /* mock calls don't do generics */
    +    @Test
    +    public void testAggregatorDifferentSizedResultsWithOnComplete() {
    +        FuncN combineLatestFunction = getConcatCombineLatestFunction();
    +        /* create the aggregator which will execute the combineLatest function when all Observables provide values */
    +        Aggregator a = new Aggregator(combineLatestFunction);
    +
    +        /* define a Observer to receive aggregated events */
    +        Observer aObserver = mock(Observer.class);
    +        Observable.create(a).subscribe(aObserver);
    +
    +        /* mock the Observable Observers that are 'pushing' data for us */
    +        CombineObserver r1 = mock(CombineObserver.class);
    +        CombineObserver r2 = mock(CombineObserver.class);
    +
    +        /* pretend we're starting up */
    +        a.addObserver(r1);
    +        a.addObserver(r2);
    +
    +        /* simulate the Observables pushing data into the aggregator */
    +        a.next(r1, "hello");
    +        a.next(r2, "world");
    +        a.complete(r2);
    +
    +        verify(aObserver, never()).onError(any(Throwable.class));
    +        verify(aObserver, never()).onCompleted();
    +        verify(aObserver, times(1)).onNext("helloworld");
    +
    +        a.next(r1, "hi");
    +        a.complete(r1);
    +
    +        verify(aObserver, never()).onError(any(Throwable.class));
    +        verify(aObserver, times(1)).onCompleted();
    +        verify(aObserver, times(1)).onNext("hiworld");
    +    }
    +
         @SuppressWarnings("unchecked")
    -    Observer w = mock(Observer.class);
    -
    -    TestObservable w1 = new TestObservable();
    -    TestObservable w2 = new TestObservable();
    -    TestObservable w3 = new TestObservable();
    -
    -    Observable combineLatestW = Observable.create(combineLatest(Observable.create(w1), Observable.create(w2), Observable.create(w3), getConcat3StringsCombineLatestFunction()));
    -    combineLatestW.subscribe(w);
    -
    -            /* simulate sending data */
    -    w1.observer.onNext("1a");
    -    w2.observer.onNext("2a");
    -    w2.observer.onNext("2b");
    -    w3.observer.onNext("3a");
    -
    -    w1.observer.onNext("1b");
    -    w2.observer.onNext("2c");
    -    w2.observer.onNext("2d");
    -    w3.observer.onNext("3b");
    -
    -    w1.observer.onCompleted();
    -    w2.observer.onCompleted();
    -    w3.observer.onCompleted();
    -
    -            /* we should have been called 5 times on the Observer */
    -    InOrder inOrder = inOrder(w);
    -    inOrder.verify(w).onNext("1a2b3a");
    -    inOrder.verify(w).onNext("1b2b3a");
    -    inOrder.verify(w).onNext("1b2c3a");
    -    inOrder.verify(w).onNext("1b2d3a");
    -    inOrder.verify(w).onNext("1b2d3b");
    -
    -    inOrder.verify(w, never()).onNext(anyString());
    -    inOrder.verify(w, times(1)).onCompleted();
    -  }
    -
    -  /**
    -   * Testing internal private logic due to the complexity so I want to use TDD to test as a I build it rather than relying purely on the overall functionality expected by the public methods.
    -   */
    -  @SuppressWarnings("unchecked")
    -        /* mock calls don't do generics */
    -  @Test
    -  public void testAggregatorSimple() {
    -    FuncN combineLatestFunction = getConcatCombineLatestFunction();
    -            /* create the aggregator which will execute the combineLatest function when all Observables provide values */
    -    Aggregator a = new Aggregator(combineLatestFunction);
    -
    -            /* define a Observer to receive aggregated events */
    -    Observer aObserver = mock(Observer.class);
    -    Observable.create(a).subscribe(aObserver);
    -
    -            /* mock the Observable Observers that are 'pushing' data for us */
    -    CombineObserver r1 = mock(CombineObserver.class);
    -    CombineObserver r2 = mock(CombineObserver.class);
    -
    -            /* pretend we're starting up */
    -    a.addObserver(r1);
    -    a.addObserver(r2);
    -
    -            /* simulate the Observables pushing data into the aggregator */
    -    a.next(r1, "hello");
    -    a.next(r2, "world");
    -
    -    InOrder inOrder = inOrder(aObserver);
    -
    -    verify(aObserver, never()).onError(any(Throwable.class));
    -    verify(aObserver, never()).onCompleted();
    -    inOrder.verify(aObserver, times(1)).onNext("helloworld");
    -
    -    a.next(r1, "hello ");
    -    a.next(r2, "again");
    -
    -    verify(aObserver, never()).onError(any(Throwable.class));
    -    verify(aObserver, never()).onCompleted();
    -    inOrder.verify(aObserver, times(1)).onNext("hello again");
    -
    -    a.complete(r1);
    -    a.complete(r2);
    -
    -    inOrder.verify(aObserver, never()).onNext(anyString());
    -    verify(aObserver, times(1)).onCompleted();
    -  }
    -
    -  @SuppressWarnings("unchecked")
    -        /* mock calls don't do generics */
    -  @Test
    -  public void testAggregatorDifferentSizedResultsWithOnComplete() {
    -    FuncN combineLatestFunction = getConcatCombineLatestFunction();
    -            /* create the aggregator which will execute the combineLatest function when all Observables provide values */
    -    Aggregator a = new Aggregator(combineLatestFunction);
    -
    -            /* define a Observer to receive aggregated events */
    -    Observer aObserver = mock(Observer.class);
    -    Observable.create(a).subscribe(aObserver);
    -
    -            /* mock the Observable Observers that are 'pushing' data for us */
    -    CombineObserver r1 = mock(CombineObserver.class);
    -    CombineObserver r2 = mock(CombineObserver.class);
    -
    -            /* pretend we're starting up */
    -    a.addObserver(r1);
    -    a.addObserver(r2);
    -
    -            /* simulate the Observables pushing data into the aggregator */
    -    a.next(r1, "hello");
    -    a.next(r2, "world");
    -    a.complete(r2);
    -
    -    verify(aObserver, never()).onError(any(Throwable.class));
    -    verify(aObserver, never()).onCompleted();
    -    verify(aObserver, times(1)).onNext("helloworld");
    -
    -    a.next(r1, "hi");
    -    a.complete(r1);
    -
    -    verify(aObserver, never()).onError(any(Throwable.class));
    -    verify(aObserver, times(1)).onCompleted();
    -    verify(aObserver, times(1)).onNext("hiworld");
    -  }
    -
    -  @SuppressWarnings("unchecked")
    -        /* mock calls don't do generics */
    -  @Test
    -  public void testAggregateMultipleTypes() {
    -    FuncN combineLatestFunction = getConcatCombineLatestFunction();
    -            /* create the aggregator which will execute the combineLatest function when all Observables provide values */
    -    Aggregator a = new Aggregator(combineLatestFunction);
    -
    -            /* define a Observer to receive aggregated events */
    -    Observer aObserver = mock(Observer.class);
    -    Observable.create(a).subscribe(aObserver);
    -
    -            /* mock the Observable Observers that are 'pushing' data for us */
    -    CombineObserver r1 = mock(CombineObserver.class);
    -    CombineObserver r2 = mock(CombineObserver.class);
    -
    -            /* pretend we're starting up */
    -    a.addObserver(r1);
    -    a.addObserver(r2);
    -
    -            /* simulate the Observables pushing data into the aggregator */
    -    a.next(r1, "hello");
    -    a.next(r2, "world");
    -    a.complete(r2);
    -
    -    verify(aObserver, never()).onError(any(Throwable.class));
    -    verify(aObserver, never()).onCompleted();
    -    verify(aObserver, times(1)).onNext("helloworld");
    -
    -    a.next(r1, "hi");
    -    a.complete(r1);
    -
    -    verify(aObserver, never()).onError(any(Throwable.class));
    -    verify(aObserver, times(1)).onCompleted();
    -    verify(aObserver, times(1)).onNext("hiworld");
    -  }
    -
    -  @SuppressWarnings("unchecked")
    -        /* mock calls don't do generics */
    -  @Test
    -  public void testAggregate3Types() {
    -    FuncN combineLatestFunction = getConcatCombineLatestFunction();
    -            /* create the aggregator which will execute the combineLatest function when all Observables provide values */
    -    Aggregator a = new Aggregator(combineLatestFunction);
    -
    -            /* define a Observer to receive aggregated events */
    -    Observer aObserver = mock(Observer.class);
    -    Observable.create(a).subscribe(aObserver);
    -
    -            /* mock the Observable Observers that are 'pushing' data for us */
    -    CombineObserver r1 = mock(CombineObserver.class);
    -    CombineObserver r2 = mock(CombineObserver.class);
    -    CombineObserver r3 = mock(CombineObserver.class);
    -
    -            /* pretend we're starting up */
    -    a.addObserver(r1);
    -    a.addObserver(r2);
    -    a.addObserver(r3);
    -
    -            /* simulate the Observables pushing data into the aggregator */
    -    a.next(r1, "hello");
    -    a.next(r2, 2);
    -    a.next(r3, new int[]{5, 6, 7});
    -
    -    verify(aObserver, never()).onError(any(Throwable.class));
    -    verify(aObserver, never()).onCompleted();
    -    verify(aObserver, times(1)).onNext("hello2[5, 6, 7]");
    -  }
    -
    -  @SuppressWarnings("unchecked")
    -        /* mock calls don't do generics */
    -  @Test
    -  public void testAggregatorsWithDifferentSizesAndTiming() {
    -    FuncN combineLatestFunction = getConcatCombineLatestFunction();
    -            /* create the aggregator which will execute the combineLatest function when all Observables provide values */
    -    Aggregator a = new Aggregator(combineLatestFunction);
    -
    -            /* define a Observer to receive aggregated events */
    -    Observer aObserver = mock(Observer.class);
    -    Observable.create(a).subscribe(aObserver);
    -
    -            /* mock the Observable Observers that are 'pushing' data for us */
    -    CombineObserver r1 = mock(CombineObserver.class);
    -    CombineObserver r2 = mock(CombineObserver.class);
    -
    -            /* pretend we're starting up */
    -    a.addObserver(r1);
    -    a.addObserver(r2);
    -
    -            /* simulate the Observables pushing data into the aggregator */
    -    a.next(r1, "one");
    -    a.next(r1, "two");
    -    a.next(r1, "three");
    -    a.next(r2, "A");
    -
    -    verify(aObserver, never()).onError(any(Throwable.class));
    -    verify(aObserver, never()).onCompleted();
    -    verify(aObserver, times(1)).onNext("threeA");
    -
    -    a.next(r1, "four");
    -    a.complete(r1);
    -    a.next(r2, "B");
    -    verify(aObserver, times(1)).onNext("fourB");
    -    a.next(r2, "C");
    -    verify(aObserver, times(1)).onNext("fourC");
    -    a.next(r2, "D");
    -    verify(aObserver, times(1)).onNext("fourD");
    -    a.next(r2, "E");
    -    verify(aObserver, times(1)).onNext("fourE");
    -    a.complete(r2);
    -
    -    verify(aObserver, never()).onError(any(Throwable.class));
    -    verify(aObserver, times(1)).onCompleted();
    -  }
    -
    -  @SuppressWarnings("unchecked")
    -        /* mock calls don't do generics */
    -  @Test
    -  public void testAggregatorError() {
    -    FuncN combineLatestFunction = getConcatCombineLatestFunction();
    -            /* create the aggregator which will execute the combineLatest function when all Observables provide values */
    -    Aggregator a = new Aggregator(combineLatestFunction);
    -
    -            /* define a Observer to receive aggregated events */
    -    Observer aObserver = mock(Observer.class);
    -    Observable.create(a).subscribe(aObserver);
    -
    -            /* mock the Observable Observers that are 'pushing' data for us */
    -    CombineObserver r1 = mock(CombineObserver.class);
    -    CombineObserver r2 = mock(CombineObserver.class);
    -
    -            /* pretend we're starting up */
    -    a.addObserver(r1);
    -    a.addObserver(r2);
    -
    -            /* simulate the Observables pushing data into the aggregator */
    -    a.next(r1, "hello");
    -    a.next(r2, "world");
    -
    -    verify(aObserver, never()).onError(any(Throwable.class));
    -    verify(aObserver, never()).onCompleted();
    -    verify(aObserver, times(1)).onNext("helloworld");
    -
    -    a.error(new RuntimeException(""));
    -    a.next(r1, "hello");
    -    a.next(r2, "again");
    -
    -    verify(aObserver, times(1)).onError(any(Throwable.class));
    -    verify(aObserver, never()).onCompleted();
    -    // we don't want to be called again after an error
    -    verify(aObserver, times(0)).onNext("helloagain");
    -  }
    -
    -  @SuppressWarnings("unchecked")
    -        /* mock calls don't do generics */
    -  @Test
    -  public void testAggregatorUnsubscribe() {
    -    FuncN combineLatestFunction = getConcatCombineLatestFunction();
    -            /* create the aggregator which will execute the combineLatest function when all Observables provide values */
    -    Aggregator a = new Aggregator(combineLatestFunction);
    -
    -            /* define a Observer to receive aggregated events */
    -    Observer aObserver = mock(Observer.class);
    -    Subscription subscription = Observable.create(a).subscribe(aObserver);
    -
    -            /* mock the Observable Observers that are 'pushing' data for us */
    -    CombineObserver r1 = mock(CombineObserver.class);
    -    CombineObserver r2 = mock(CombineObserver.class);
    -
    -            /* pretend we're starting up */
    -    a.addObserver(r1);
    -    a.addObserver(r2);
    -
    -            /* simulate the Observables pushing data into the aggregator */
    -    a.next(r1, "hello");
    -    a.next(r2, "world");
    -
    -    verify(aObserver, never()).onError(any(Throwable.class));
    -    verify(aObserver, never()).onCompleted();
    -    verify(aObserver, times(1)).onNext("helloworld");
    -
    -    subscription.unsubscribe();
    -    a.next(r1, "hello");
    -    a.next(r2, "again");
    -
    -    verify(aObserver, times(0)).onError(any(Throwable.class));
    -    verify(aObserver, never()).onCompleted();
    -    // we don't want to be called again after an error
    -    verify(aObserver, times(0)).onNext("helloagain");
    -  }
    -
    -  @SuppressWarnings("unchecked")
    -        /* mock calls don't do generics */
    -  @Test
    -  public void testAggregatorEarlyCompletion() {
    -    FuncN combineLatestFunction = getConcatCombineLatestFunction();
    -            /* create the aggregator which will execute the combineLatest function when all Observables provide values */
    -    Aggregator a = new Aggregator(combineLatestFunction);
    -
    -            /* define a Observer to receive aggregated events */
    -    Observer aObserver = mock(Observer.class);
    -    Observable.create(a).subscribe(aObserver);
    -
    -            /* mock the Observable Observers that are 'pushing' data for us */
    -    CombineObserver r1 = mock(CombineObserver.class);
    -    CombineObserver r2 = mock(CombineObserver.class);
    -
    -            /* pretend we're starting up */
    -    a.addObserver(r1);
    -    a.addObserver(r2);
    -
    -            /* simulate the Observables pushing data into the aggregator */
    -    a.next(r1, "one");
    -    a.next(r1, "two");
    -    a.complete(r1);
    -    a.next(r2, "A");
    -
    -    InOrder inOrder = inOrder(aObserver);
    -
    -    inOrder.verify(aObserver, never()).onError(any(Throwable.class));
    -    inOrder.verify(aObserver, never()).onCompleted();
    -    inOrder.verify(aObserver, times(1)).onNext("twoA");
    -
    -    a.complete(r2);
    -
    -    inOrder.verify(aObserver, never()).onError(any(Throwable.class));
    -    inOrder.verify(aObserver, times(1)).onCompleted();
    -    // we shouldn't get this since completed is called before any other onNext calls could trigger this
    -    inOrder.verify(aObserver, never()).onNext(anyString());
    -  }
    -
    -  @SuppressWarnings("unchecked")
    -        /* mock calls don't do generics */
    -  @Test
    -  public void testCombineLatest2Types() {
    -    Func2 combineLatestFunction = getConcatStringIntegerCombineLatestFunction();
    -
    -            /* define a Observer to receive aggregated events */
    -    Observer aObserver = mock(Observer.class);
    -
    -    Observable w = Observable.create(combineLatest(Observable.from("one", "two"), Observable.from(2, 3, 4), combineLatestFunction));
    -    w.subscribe(aObserver);
    -
    -    verify(aObserver, never()).onError(any(Throwable.class));
    -    verify(aObserver, times(1)).onCompleted();
    -    verify(aObserver, times(1)).onNext("two2");
    -    verify(aObserver, times(1)).onNext("two3");
    -    verify(aObserver, times(1)).onNext("two4");
    -  }
    -
    -  @SuppressWarnings("unchecked")
    -        /* mock calls don't do generics */
    -  @Test
    -  public void testCombineLatest3TypesA() {
    -    Func3 combineLatestFunction = getConcatStringIntegerIntArrayCombineLatestFunction();
    -
    -            /* define a Observer to receive aggregated events */
    -    Observer aObserver = mock(Observer.class);
    -
    -    Observable w = Observable.create(combineLatest(Observable.from("one", "two"), Observable.from(2), Observable.from(new int[]{4, 5, 6}), combineLatestFunction));
    -    w.subscribe(aObserver);
    -
    -    verify(aObserver, never()).onError(any(Throwable.class));
    -    verify(aObserver, times(1)).onCompleted();
    -    verify(aObserver, times(1)).onNext("two2[4, 5, 6]");
    -  }
    -
    -  @SuppressWarnings("unchecked")
    -        /* mock calls don't do generics */
    -  @Test
    -  public void testCombineLatest3TypesB() {
    -    Func3 combineLatestFunction = getConcatStringIntegerIntArrayCombineLatestFunction();
    -
    -            /* define a Observer to receive aggregated events */
    -    Observer aObserver = mock(Observer.class);
    -
    -    Observable w = Observable.create(combineLatest(Observable.from("one"), Observable.from(2), Observable.from(new int[]{4, 5, 6}, new int[]{7, 8}), combineLatestFunction));
    -    w.subscribe(aObserver);
    -
    -    verify(aObserver, never()).onError(any(Throwable.class));
    -    verify(aObserver, times(1)).onCompleted();
    -    verify(aObserver, times(1)).onNext("one2[4, 5, 6]");
    -    verify(aObserver, times(1)).onNext("one2[7, 8]");
    -  }
    -
    -  private Func3 getConcat3StringsCombineLatestFunction() {
    -    Func3 combineLatestFunction = new Func3() {
    -
    -      @Override
    -      public String call(String a1, String a2, String a3) {
    -        if (a1 == null) {
    -          a1 = "";
    -        }
    -        if (a2 == null) {
    -          a2 = "";
    -        }
    -        if (a3 == null) {
    -          a3 = "";
    -        }
    -        return a1 + a2 + a3;
    -      }
    -
    -    };
    -    return combineLatestFunction;
    -  }
    -
    -  private FuncN getConcatCombineLatestFunction() {
    -    FuncN combineLatestFunction = new FuncN() {
    -
    -      @Override
    -      public String call(Object... args) {
    -        String returnValue = "";
    -        for (Object o : args) {
    -          if (o != null) {
    -            returnValue += getStringValue(o);
    -          }
    -        }
    -        System.out.println("returning: " + returnValue);
    -        return returnValue;
    -      }
    -
    -    };
    -    return combineLatestFunction;
    -  }
    -
    -  private Func2 getConcatStringIntegerCombineLatestFunction() {
    -    Func2 combineLatestFunction = new Func2() {
    -
    -      @Override
    -      public String call(String s, Integer i) {
    -        return getStringValue(s) + getStringValue(i);
    -      }
    -
    -    };
    -    return combineLatestFunction;
    -  }
    -
    -  private Func3 getConcatStringIntegerIntArrayCombineLatestFunction() {
    -    Func3 combineLatestFunction = new Func3() {
    -
    -      @Override
    -      public String call(String s, Integer i, int[] iArray) {
    -        return getStringValue(s) + getStringValue(i) + getStringValue(iArray);
    -      }
    -
    -    };
    -    return combineLatestFunction;
    -  }
    -
    -  private static String getStringValue(Object o) {
    -    if (o == null) {
    -      return "";
    -    } else {
    -      if (o instanceof int[]) {
    -        return Arrays.toString((int[]) o);
    -      } else {
    -        return String.valueOf(o);
    -      }
    +    /* mock calls don't do generics */
    +    @Test
    +    public void testAggregateMultipleTypes() {
    +        FuncN combineLatestFunction = getConcatCombineLatestFunction();
    +        /* create the aggregator which will execute the combineLatest function when all Observables provide values */
    +        Aggregator a = new Aggregator(combineLatestFunction);
    +
    +        /* define a Observer to receive aggregated events */
    +        Observer aObserver = mock(Observer.class);
    +        Observable.create(a).subscribe(aObserver);
    +
    +        /* mock the Observable Observers that are 'pushing' data for us */
    +        CombineObserver r1 = mock(CombineObserver.class);
    +        CombineObserver r2 = mock(CombineObserver.class);
    +
    +        /* pretend we're starting up */
    +        a.addObserver(r1);
    +        a.addObserver(r2);
    +
    +        /* simulate the Observables pushing data into the aggregator */
    +        a.next(r1, "hello");
    +        a.next(r2, "world");
    +        a.complete(r2);
    +
    +        verify(aObserver, never()).onError(any(Throwable.class));
    +        verify(aObserver, never()).onCompleted();
    +        verify(aObserver, times(1)).onNext("helloworld");
    +
    +        a.next(r1, "hi");
    +        a.complete(r1);
    +
    +        verify(aObserver, never()).onError(any(Throwable.class));
    +        verify(aObserver, times(1)).onCompleted();
    +        verify(aObserver, times(1)).onNext("hiworld");
    +    }
    +
    +    @SuppressWarnings("unchecked")
    +    /* mock calls don't do generics */
    +    @Test
    +    public void testAggregate3Types() {
    +        FuncN combineLatestFunction = getConcatCombineLatestFunction();
    +        /* create the aggregator which will execute the combineLatest function when all Observables provide values */
    +        Aggregator a = new Aggregator(combineLatestFunction);
    +
    +        /* define a Observer to receive aggregated events */
    +        Observer aObserver = mock(Observer.class);
    +        Observable.create(a).subscribe(aObserver);
    +
    +        /* mock the Observable Observers that are 'pushing' data for us */
    +        CombineObserver r1 = mock(CombineObserver.class);
    +        CombineObserver r2 = mock(CombineObserver.class);
    +        CombineObserver r3 = mock(CombineObserver.class);
    +
    +        /* pretend we're starting up */
    +        a.addObserver(r1);
    +        a.addObserver(r2);
    +        a.addObserver(r3);
    +
    +        /* simulate the Observables pushing data into the aggregator */
    +        a.next(r1, "hello");
    +        a.next(r2, 2);
    +        a.next(r3, new int[] { 5, 6, 7 });
    +
    +        verify(aObserver, never()).onError(any(Throwable.class));
    +        verify(aObserver, never()).onCompleted();
    +        verify(aObserver, times(1)).onNext("hello2[5, 6, 7]");
    +    }
    +
    +    @SuppressWarnings("unchecked")
    +    /* mock calls don't do generics */
    +    @Test
    +    public void testAggregatorsWithDifferentSizesAndTiming() {
    +        FuncN combineLatestFunction = getConcatCombineLatestFunction();
    +        /* create the aggregator which will execute the combineLatest function when all Observables provide values */
    +        Aggregator a = new Aggregator(combineLatestFunction);
    +
    +        /* define a Observer to receive aggregated events */
    +        Observer aObserver = mock(Observer.class);
    +        Observable.create(a).subscribe(aObserver);
    +
    +        /* mock the Observable Observers that are 'pushing' data for us */
    +        CombineObserver r1 = mock(CombineObserver.class);
    +        CombineObserver r2 = mock(CombineObserver.class);
    +
    +        /* pretend we're starting up */
    +        a.addObserver(r1);
    +        a.addObserver(r2);
    +
    +        /* simulate the Observables pushing data into the aggregator */
    +        a.next(r1, "one");
    +        a.next(r1, "two");
    +        a.next(r1, "three");
    +        a.next(r2, "A");
    +
    +        verify(aObserver, never()).onError(any(Throwable.class));
    +        verify(aObserver, never()).onCompleted();
    +        verify(aObserver, times(1)).onNext("threeA");
    +
    +        a.next(r1, "four");
    +        a.complete(r1);
    +        a.next(r2, "B");
    +        verify(aObserver, times(1)).onNext("fourB");
    +        a.next(r2, "C");
    +        verify(aObserver, times(1)).onNext("fourC");
    +        a.next(r2, "D");
    +        verify(aObserver, times(1)).onNext("fourD");
    +        a.next(r2, "E");
    +        verify(aObserver, times(1)).onNext("fourE");
    +        a.complete(r2);
    +
    +        verify(aObserver, never()).onError(any(Throwable.class));
    +        verify(aObserver, times(1)).onCompleted();
    +    }
    +
    +    @SuppressWarnings("unchecked")
    +    /* mock calls don't do generics */
    +    @Test
    +    public void testAggregatorError() {
    +        FuncN combineLatestFunction = getConcatCombineLatestFunction();
    +        /* create the aggregator which will execute the combineLatest function when all Observables provide values */
    +        Aggregator a = new Aggregator(combineLatestFunction);
    +
    +        /* define a Observer to receive aggregated events */
    +        Observer aObserver = mock(Observer.class);
    +        Observable.create(a).subscribe(aObserver);
    +
    +        /* mock the Observable Observers that are 'pushing' data for us */
    +        CombineObserver r1 = mock(CombineObserver.class);
    +        CombineObserver r2 = mock(CombineObserver.class);
    +
    +        /* pretend we're starting up */
    +        a.addObserver(r1);
    +        a.addObserver(r2);
    +
    +        /* simulate the Observables pushing data into the aggregator */
    +        a.next(r1, "hello");
    +        a.next(r2, "world");
    +
    +        verify(aObserver, never()).onError(any(Throwable.class));
    +        verify(aObserver, never()).onCompleted();
    +        verify(aObserver, times(1)).onNext("helloworld");
    +
    +        a.error(new RuntimeException(""));
    +        a.next(r1, "hello");
    +        a.next(r2, "again");
    +
    +        verify(aObserver, times(1)).onError(any(Throwable.class));
    +        verify(aObserver, never()).onCompleted();
    +        // we don't want to be called again after an error
    +        verify(aObserver, times(0)).onNext("helloagain");
    +    }
    +
    +    @SuppressWarnings("unchecked")
    +    /* mock calls don't do generics */
    +    @Test
    +    public void testAggregatorUnsubscribe() {
    +        FuncN combineLatestFunction = getConcatCombineLatestFunction();
    +        /* create the aggregator which will execute the combineLatest function when all Observables provide values */
    +        Aggregator a = new Aggregator(combineLatestFunction);
    +
    +        /* define a Observer to receive aggregated events */
    +        Observer aObserver = mock(Observer.class);
    +        Subscription subscription = Observable.create(a).subscribe(aObserver);
    +
    +        /* mock the Observable Observers that are 'pushing' data for us */
    +        CombineObserver r1 = mock(CombineObserver.class);
    +        CombineObserver r2 = mock(CombineObserver.class);
    +
    +        /* pretend we're starting up */
    +        a.addObserver(r1);
    +        a.addObserver(r2);
    +
    +        /* simulate the Observables pushing data into the aggregator */
    +        a.next(r1, "hello");
    +        a.next(r2, "world");
    +
    +        verify(aObserver, never()).onError(any(Throwable.class));
    +        verify(aObserver, never()).onCompleted();
    +        verify(aObserver, times(1)).onNext("helloworld");
    +
    +        subscription.unsubscribe();
    +        a.next(r1, "hello");
    +        a.next(r2, "again");
    +
    +        verify(aObserver, times(0)).onError(any(Throwable.class));
    +        verify(aObserver, never()).onCompleted();
    +        // we don't want to be called again after an error
    +        verify(aObserver, times(0)).onNext("helloagain");
    +    }
    +
    +    @SuppressWarnings("unchecked")
    +    /* mock calls don't do generics */
    +    @Test
    +    public void testAggregatorEarlyCompletion() {
    +        FuncN combineLatestFunction = getConcatCombineLatestFunction();
    +        /* create the aggregator which will execute the combineLatest function when all Observables provide values */
    +        Aggregator a = new Aggregator(combineLatestFunction);
    +
    +        /* define a Observer to receive aggregated events */
    +        Observer aObserver = mock(Observer.class);
    +        Observable.create(a).subscribe(aObserver);
    +
    +        /* mock the Observable Observers that are 'pushing' data for us */
    +        CombineObserver r1 = mock(CombineObserver.class);
    +        CombineObserver r2 = mock(CombineObserver.class);
    +
    +        /* pretend we're starting up */
    +        a.addObserver(r1);
    +        a.addObserver(r2);
    +
    +        /* simulate the Observables pushing data into the aggregator */
    +        a.next(r1, "one");
    +        a.next(r1, "two");
    +        a.complete(r1);
    +        a.next(r2, "A");
    +
    +        InOrder inOrder = inOrder(aObserver);
    +
    +        inOrder.verify(aObserver, never()).onError(any(Throwable.class));
    +        inOrder.verify(aObserver, never()).onCompleted();
    +        inOrder.verify(aObserver, times(1)).onNext("twoA");
    +
    +        a.complete(r2);
    +
    +        inOrder.verify(aObserver, never()).onError(any(Throwable.class));
    +        inOrder.verify(aObserver, times(1)).onCompleted();
    +        // we shouldn't get this since completed is called before any other onNext calls could trigger this
    +        inOrder.verify(aObserver, never()).onNext(anyString());
    +    }
    +
    +    @SuppressWarnings("unchecked")
    +    /* mock calls don't do generics */
    +    @Test
    +    public void testCombineLatest2Types() {
    +        Func2 combineLatestFunction = getConcatStringIntegerCombineLatestFunction();
    +
    +        /* define a Observer to receive aggregated events */
    +        Observer aObserver = mock(Observer.class);
    +
    +        Observable w = Observable.create(combineLatest(Observable.from("one", "two"), Observable.from(2, 3, 4), combineLatestFunction));
    +        w.subscribe(aObserver);
    +
    +        verify(aObserver, never()).onError(any(Throwable.class));
    +        verify(aObserver, times(1)).onCompleted();
    +        verify(aObserver, times(1)).onNext("two2");
    +        verify(aObserver, times(1)).onNext("two3");
    +        verify(aObserver, times(1)).onNext("two4");
    +    }
    +
    +    @SuppressWarnings("unchecked")
    +    /* mock calls don't do generics */
    +    @Test
    +    public void testCombineLatest3TypesA() {
    +        Func3 combineLatestFunction = getConcatStringIntegerIntArrayCombineLatestFunction();
    +
    +        /* define a Observer to receive aggregated events */
    +        Observer aObserver = mock(Observer.class);
    +
    +        Observable w = Observable.create(combineLatest(Observable.from("one", "two"), Observable.from(2), Observable.from(new int[] { 4, 5, 6 }), combineLatestFunction));
    +        w.subscribe(aObserver);
    +
    +        verify(aObserver, never()).onError(any(Throwable.class));
    +        verify(aObserver, times(1)).onCompleted();
    +        verify(aObserver, times(1)).onNext("two2[4, 5, 6]");
    +    }
    +
    +    @SuppressWarnings("unchecked")
    +    /* mock calls don't do generics */
    +    @Test
    +    public void testCombineLatest3TypesB() {
    +        Func3 combineLatestFunction = getConcatStringIntegerIntArrayCombineLatestFunction();
    +
    +        /* define a Observer to receive aggregated events */
    +        Observer aObserver = mock(Observer.class);
    +
    +        Observable w = Observable.create(combineLatest(Observable.from("one"), Observable.from(2), Observable.from(new int[] { 4, 5, 6 }, new int[] { 7, 8 }), combineLatestFunction));
    +        w.subscribe(aObserver);
    +
    +        verify(aObserver, never()).onError(any(Throwable.class));
    +        verify(aObserver, times(1)).onCompleted();
    +        verify(aObserver, times(1)).onNext("one2[4, 5, 6]");
    +        verify(aObserver, times(1)).onNext("one2[7, 8]");
         }
    -  }
     
    -  private static class TestObservable implements Observable.OnSubscribeFunc {
    +    private Func3 getConcat3StringsCombineLatestFunction() {
    +        Func3 combineLatestFunction = new Func3() {
    +
    +            @Override
    +            public String call(String a1, String a2, String a3) {
    +                if (a1 == null) {
    +                    a1 = "";
    +                }
    +                if (a2 == null) {
    +                    a2 = "";
    +                }
    +                if (a3 == null) {
    +                    a3 = "";
    +                }
    +                return a1 + a2 + a3;
    +            }
    +
    +        };
    +        return combineLatestFunction;
    +    }
     
    -    Observer observer;
    +    private FuncN getConcatCombineLatestFunction() {
    +        FuncN combineLatestFunction = new FuncN() {
    +
    +            @Override
    +            public String call(Object... args) {
    +                String returnValue = "";
    +                for (Object o : args) {
    +                    if (o != null) {
    +                        returnValue += getStringValue(o);
    +                    }
    +                }
    +                System.out.println("returning: " + returnValue);
    +                return returnValue;
    +            }
    +
    +        };
    +        return combineLatestFunction;
    +    }
    +
    +    private Func2 getConcatStringIntegerCombineLatestFunction() {
    +        Func2 combineLatestFunction = new Func2() {
    +
    +            @Override
    +            public String call(String s, Integer i) {
    +                return getStringValue(s) + getStringValue(i);
    +            }
     
    -    @Override
    -    public Subscription onSubscribe(Observer observer) {
    -      // just store the variable where it can be accessed so we can manually trigger it
    -      this.observer = observer;
    -      return Subscriptions.empty();
    +        };
    +        return combineLatestFunction;
         }
     
    -  }
    +    private Func3 getConcatStringIntegerIntArrayCombineLatestFunction() {
    +        Func3 combineLatestFunction = new Func3() {
    +
    +            @Override
    +            public String call(String s, Integer i, int[] iArray) {
    +                return getStringValue(s) + getStringValue(i) + getStringValue(iArray);
    +            }
    +
    +        };
    +        return combineLatestFunction;
    +    }
    +
    +    private static String getStringValue(Object o) {
    +        if (o == null) {
    +            return "";
    +        } else {
    +            if (o instanceof int[]) {
    +                return Arrays.toString((int[]) o);
    +            } else {
    +                return String.valueOf(o);
    +            }
    +        }
    +    }
    +
    +    private static class TestObservable implements Observable.OnSubscribeFunc {
    +
    +        Observer observer;
    +
    +        @Override
    +        public Subscription onSubscribe(Observer observer) {
    +            // just store the variable where it can be accessed so we can manually trigger it
    +            this.observer = observer;
    +            return Subscriptions.empty();
    +        }
    +
    +    }
     }
    diff --git a/rxjava-core/src/test/java/rx/operators/OperationConcatTest.java b/rxjava-core/src/test/java/rx/operators/OperationConcatTest.java
    index 35fc22bcc2..d6fc1e2d56 100644
    --- a/rxjava-core/src/test/java/rx/operators/OperationConcatTest.java
    +++ b/rxjava-core/src/test/java/rx/operators/OperationConcatTest.java
    @@ -1,11 +1,9 @@
     package rx.operators;
     
    -import org.junit.Test;
    -import org.mockito.InOrder;
    -import rx.Observable;
    -import rx.Observer;
    -import rx.Subscription;
    -import rx.subscriptions.BooleanSubscription;
    +import static org.junit.Assert.*;
    +import static org.mockito.Matchers.*;
    +import static org.mockito.Mockito.*;
    +import static rx.operators.OperationConcat.*;
     
     import java.util.ArrayList;
     import java.util.Arrays;
    @@ -14,531 +12,533 @@
     import java.util.concurrent.TimeUnit;
     import java.util.concurrent.atomic.AtomicReference;
     
    -import static org.junit.Assert.fail;
    -import static org.mockito.Matchers.any;
    -import static org.mockito.Matchers.anyString;
    -import static org.mockito.Mockito.*;
    -import static rx.operators.OperationConcat.concat;
    +import org.junit.Test;
    +import org.mockito.InOrder;
    +
    +import rx.Observable;
    +import rx.Observer;
    +import rx.Subscription;
    +import rx.subscriptions.BooleanSubscription;
     
     public class OperationConcatTest {
     
    -  @Test
    -  public void testConcat() {
    -    @SuppressWarnings("unchecked")
    -    Observer observer = mock(Observer.class);
    +    @Test
    +    public void testConcat() {
    +        @SuppressWarnings("unchecked")
    +        Observer observer = mock(Observer.class);
     
    -    final String[] o = {"1", "3", "5", "7"};
    -    final String[] e = {"2", "4", "6"};
    +        final String[] o = { "1", "3", "5", "7" };
    +        final String[] e = { "2", "4", "6" };
     
    -    final Observable odds = Observable.from(o);
    -    final Observable even = Observable.from(e);
    +        final Observable odds = Observable.from(o);
    +        final Observable even = Observable.from(e);
     
    -    @SuppressWarnings("unchecked")
    -    Observable concat = Observable.create(concat(odds, even));
    -    concat.subscribe(observer);
    +        @SuppressWarnings("unchecked")
    +        Observable concat = Observable.create(concat(odds, even));
    +        concat.subscribe(observer);
     
    -    verify(observer, times(7)).onNext(anyString());
    -  }
    +        verify(observer, times(7)).onNext(anyString());
    +    }
     
    -  @Test
    -  public void testConcatWithList() {
    -    @SuppressWarnings("unchecked")
    -    Observer observer = mock(Observer.class);
    +    @Test
    +    public void testConcatWithList() {
    +        @SuppressWarnings("unchecked")
    +        Observer observer = mock(Observer.class);
     
    -    final String[] o = {"1", "3", "5", "7"};
    -    final String[] e = {"2", "4", "6"};
    +        final String[] o = { "1", "3", "5", "7" };
    +        final String[] e = { "2", "4", "6" };
     
    -    final Observable odds = Observable.from(o);
    -    final Observable even = Observable.from(e);
    -    final List> list = new ArrayList>();
    -    list.add(odds);
    -    list.add(even);
    -    Observable concat = Observable.create(concat(list));
    -    concat.subscribe(observer);
    +        final Observable odds = Observable.from(o);
    +        final Observable even = Observable.from(e);
    +        final List> list = new ArrayList>();
    +        list.add(odds);
    +        list.add(even);
    +        Observable concat = Observable.create(concat(list));
    +        concat.subscribe(observer);
     
    -    verify(observer, times(7)).onNext(anyString());
    -  }
    +        verify(observer, times(7)).onNext(anyString());
    +    }
     
    -  @Test
    -  public void testConcatObservableOfObservables() {
    -    @SuppressWarnings("unchecked")
    -    Observer observer = mock(Observer.class);
    +    @Test
    +    public void testConcatObservableOfObservables() {
    +        @SuppressWarnings("unchecked")
    +        Observer observer = mock(Observer.class);
     
    -    final String[] o = {"1", "3", "5", "7"};
    -    final String[] e = {"2", "4", "6"};
    +        final String[] o = { "1", "3", "5", "7" };
    +        final String[] e = { "2", "4", "6" };
     
    -    final Observable odds = Observable.from(o);
    -    final Observable even = Observable.from(e);
    +        final Observable odds = Observable.from(o);
    +        final Observable even = Observable.from(e);
     
    -    Observable> observableOfObservables = Observable.create(new Observable.OnSubscribeFunc>() {
    +        Observable> observableOfObservables = Observable.create(new Observable.OnSubscribeFunc>() {
     
    -      @Override
    -      public Subscription onSubscribe(Observer> observer) {
    -        // simulate what would happen in an observable
    -        observer.onNext(odds);
    -        observer.onNext(even);
    -        observer.onCompleted();
    +            @Override
    +            public Subscription onSubscribe(Observer> observer) {
    +                // simulate what would happen in an observable
    +                observer.onNext(odds);
    +                observer.onNext(even);
    +                observer.onCompleted();
     
    -        return new Subscription() {
    +                return new Subscription() {
     
    -          @Override
    -          public void unsubscribe() {
    -            // unregister ... will never be called here since we are executing synchronously
    -          }
    +                    @Override
    +                    public void unsubscribe() {
    +                        // unregister ... will never be called here since we are executing synchronously
    +                    }
     
    -        };
    -      }
    +                };
    +            }
     
    -    });
    -    Observable concat = Observable.create(concat(observableOfObservables));
    +        });
    +        Observable concat = Observable.create(concat(observableOfObservables));
     
    -    concat.subscribe(observer);
    +        concat.subscribe(observer);
    +
    +        verify(observer, times(7)).onNext(anyString());
    +    }
     
    -    verify(observer, times(7)).onNext(anyString());
    -  }
    +    /**
    +     * Simple concat of 2 asynchronous observables ensuring it emits in correct order.
    +     */
    +    @SuppressWarnings("unchecked")
    +    @Test
    +    public void testSimpleAsyncConcat() {
    +        Observer observer = mock(Observer.class);
     
    -  /**
    -   * Simple concat of 2 asynchronous observables ensuring it emits in correct order.
    -   */
    -  @SuppressWarnings("unchecked")
    -  @Test
    -  public void testSimpleAsyncConcat() {
    -    Observer observer = mock(Observer.class);
    +        TestObservable o1 = new TestObservable("one", "two", "three");
    +        TestObservable o2 = new TestObservable("four", "five", "six");
     
    -    TestObservable o1 = new TestObservable("one", "two", "three");
    -    TestObservable o2 = new TestObservable("four", "five", "six");
    +        Observable.concat(Observable.create(o1), Observable.create(o2)).subscribe(observer);
     
    -    Observable.concat(Observable.create(o1), Observable.create(o2)).subscribe(observer);
    +        try {
    +            // wait for async observables to complete
    +            o1.t.join();
    +            o2.t.join();
    +        } catch (Throwable e) {
    +            throw new RuntimeException("failed waiting on threads");
    +        }
     
    -    try {
    -      // wait for async observables to complete
    -      o1.t.join();
    -      o2.t.join();
    -    } catch (Throwable e) {
    -      throw new RuntimeException("failed waiting on threads");
    +        InOrder inOrder = inOrder(observer);
    +        inOrder.verify(observer, times(1)).onNext("one");
    +        inOrder.verify(observer, times(1)).onNext("two");
    +        inOrder.verify(observer, times(1)).onNext("three");
    +        inOrder.verify(observer, times(1)).onNext("four");
    +        inOrder.verify(observer, times(1)).onNext("five");
    +        inOrder.verify(observer, times(1)).onNext("six");
         }
     
    -    InOrder inOrder = inOrder(observer);
    -    inOrder.verify(observer, times(1)).onNext("one");
    -    inOrder.verify(observer, times(1)).onNext("two");
    -    inOrder.verify(observer, times(1)).onNext("three");
    -    inOrder.verify(observer, times(1)).onNext("four");
    -    inOrder.verify(observer, times(1)).onNext("five");
    -    inOrder.verify(observer, times(1)).onNext("six");
    -  }
    -
    -  /**
    -   * Test an async Observable that emits more async Observables
    -   */
    -  @SuppressWarnings("unchecked")
    -  @Test
    -  public void testNestedAsyncConcat() throws Throwable {
    -    Observer observer = mock(Observer.class);
    -
    -    final TestObservable o1 = new TestObservable("one", "two", "three");
    -    final TestObservable o2 = new TestObservable("four", "five", "six");
    -    final TestObservable o3 = new TestObservable("seven", "eight", "nine");
    -    final CountDownLatch allowThird = new CountDownLatch(1);
    -
    -    final AtomicReference parent = new AtomicReference();
    -    Observable> observableOfObservables = Observable.create(new Observable.OnSubscribeFunc>() {
    -
    -      @Override
    -      public Subscription onSubscribe(final Observer> observer) {
    -        final BooleanSubscription s = new BooleanSubscription();
    -        parent.set(new Thread(new Runnable() {
    -
    -          @Override
    -          public void run() {
    -            try {
    -              // emit first
    -              if (!s.isUnsubscribed()) {
    -                System.out.println("Emit o1");
    -                observer.onNext(Observable.create(o1));
    -              }
    -              // emit second
    -              if (!s.isUnsubscribed()) {
    -                System.out.println("Emit o2");
    -                observer.onNext(Observable.create(o2));
    -              }
    -
    -              // wait until sometime later and emit third
    -              try {
    -                allowThird.await();
    -              } catch (InterruptedException e) {
    -                observer.onError(e);
    -              }
    -              if (!s.isUnsubscribed()) {
    -                System.out.println("Emit o3");
    -                observer.onNext(Observable.create(o3));
    -              }
    -
    -            } catch (Throwable e) {
    -              observer.onError(e);
    -            } finally {
    -              System.out.println("Done parent Observable");
    -              observer.onCompleted();
    +    /**
    +     * Test an async Observable that emits more async Observables
    +     */
    +    @SuppressWarnings("unchecked")
    +    @Test
    +    public void testNestedAsyncConcat() throws Throwable {
    +        Observer observer = mock(Observer.class);
    +
    +        final TestObservable o1 = new TestObservable("one", "two", "three");
    +        final TestObservable o2 = new TestObservable("four", "five", "six");
    +        final TestObservable o3 = new TestObservable("seven", "eight", "nine");
    +        final CountDownLatch allowThird = new CountDownLatch(1);
    +
    +        final AtomicReference parent = new AtomicReference();
    +        Observable> observableOfObservables = Observable.create(new Observable.OnSubscribeFunc>() {
    +
    +            @Override
    +            public Subscription onSubscribe(final Observer> observer) {
    +                final BooleanSubscription s = new BooleanSubscription();
    +                parent.set(new Thread(new Runnable() {
    +
    +                    @Override
    +                    public void run() {
    +                        try {
    +                            // emit first
    +                            if (!s.isUnsubscribed()) {
    +                                System.out.println("Emit o1");
    +                                observer.onNext(Observable.create(o1));
    +                            }
    +                            // emit second
    +                            if (!s.isUnsubscribed()) {
    +                                System.out.println("Emit o2");
    +                                observer.onNext(Observable.create(o2));
    +                            }
    +
    +                            // wait until sometime later and emit third
    +                            try {
    +                                allowThird.await();
    +                            } catch (InterruptedException e) {
    +                                observer.onError(e);
    +                            }
    +                            if (!s.isUnsubscribed()) {
    +                                System.out.println("Emit o3");
    +                                observer.onNext(Observable.create(o3));
    +                            }
    +
    +                        } catch (Throwable e) {
    +                            observer.onError(e);
    +                        } finally {
    +                            System.out.println("Done parent Observable");
    +                            observer.onCompleted();
    +                        }
    +                    }
    +                }));
    +                parent.get().start();
    +                return s;
                 }
    -          }
    -        }));
    -        parent.get().start();
    -        return s;
    -      }
    -    });
    -
    -    Observable.create(concat(observableOfObservables)).subscribe(observer);
    -
    -    // wait for parent to start
    -    while (parent.get() == null) {
    -      Thread.sleep(1);
    -    }
    +        });
     
    -    try {
    -      // wait for first 2 async observables to complete
    -      while (o1.t == null) {
    -        Thread.sleep(1);
    -      }
    -      System.out.println("Thread1 started ... waiting for it to complete ...");
    -      o1.t.join();
    -      while (o2.t == null) {
    -        Thread.sleep(1);
    -      }
    -      System.out.println("Thread2 started ... waiting for it to complete ...");
    -      o2.t.join();
    -    } catch (Throwable e) {
    -      throw new RuntimeException("failed waiting on threads", e);
    -    }
    +        Observable.create(concat(observableOfObservables)).subscribe(observer);
     
    -    InOrder inOrder = inOrder(observer);
    -    inOrder.verify(observer, times(1)).onNext("one");
    -    inOrder.verify(observer, times(1)).onNext("two");
    -    inOrder.verify(observer, times(1)).onNext("three");
    -    inOrder.verify(observer, times(1)).onNext("four");
    -    inOrder.verify(observer, times(1)).onNext("five");
    -    inOrder.verify(observer, times(1)).onNext("six");
    -    // we shouldn't have the following 3 yet
    -    inOrder.verify(observer, never()).onNext("seven");
    -    inOrder.verify(observer, never()).onNext("eight");
    -    inOrder.verify(observer, never()).onNext("nine");
    -    // we should not be completed yet
    -    verify(observer, never()).onCompleted();
    -    verify(observer, never()).onError(any(Throwable.class));
    -
    -    // now allow the third
    -    allowThird.countDown();
    -
    -    try {
    -      while (o3.t == null) {
    -        Thread.sleep(1);
    -      }
    -      // wait for 3rd to complete
    -      o3.t.join();
    -    } catch (Throwable e) {
    -      throw new RuntimeException("failed waiting on threads", e);
    -    }
    +        // wait for parent to start
    +        while (parent.get() == null) {
    +            Thread.sleep(1);
    +        }
     
    -    inOrder.verify(observer, times(1)).onNext("seven");
    -    inOrder.verify(observer, times(1)).onNext("eight");
    -    inOrder.verify(observer, times(1)).onNext("nine");
    -
    -    inOrder.verify(observer, times(1)).onCompleted();
    -    verify(observer, never()).onError(any(Throwable.class));
    -  }
    -
    -  @SuppressWarnings("unchecked")
    -  @Test
    -  public void testBlockedObservableOfObservables() {
    -    Observer observer = mock(Observer.class);
    -
    -    final String[] o = {"1", "3", "5", "7"};
    -    final String[] e = {"2", "4", "6"};
    -    final Observable odds = Observable.from(o);
    -    final Observable even = Observable.from(e);
    -    final CountDownLatch callOnce = new CountDownLatch(1);
    -    final CountDownLatch okToContinue = new CountDownLatch(1);
    -    TestObservable> observableOfObservables = new TestObservable>(callOnce, okToContinue, odds, even);
    -    Observable.OnSubscribeFunc concatF = concat(Observable.create(observableOfObservables));
    -    Observable concat = Observable.create(concatF);
    -    concat.subscribe(observer);
    -    try {
    -      //Block main thread to allow observables to serve up o1.
    -      callOnce.await();
    -    } catch (Throwable ex) {
    -      ex.printStackTrace();
    -      fail(ex.getMessage());
    -    }
    -    // The concated observable should have served up all of the odds.
    -    verify(observer, times(1)).onNext("1");
    -    verify(observer, times(1)).onNext("3");
    -    verify(observer, times(1)).onNext("5");
    -    verify(observer, times(1)).onNext("7");
    -
    -    try {
    -      // unblock observables so it can serve up o2 and complete
    -      okToContinue.countDown();
    -      observableOfObservables.t.join();
    -    } catch (Throwable ex) {
    -      ex.printStackTrace();
    -      fail(ex.getMessage());
    +        try {
    +            // wait for first 2 async observables to complete
    +            while (o1.t == null) {
    +                Thread.sleep(1);
    +            }
    +            System.out.println("Thread1 started ... waiting for it to complete ...");
    +            o1.t.join();
    +            while (o2.t == null) {
    +                Thread.sleep(1);
    +            }
    +            System.out.println("Thread2 started ... waiting for it to complete ...");
    +            o2.t.join();
    +        } catch (Throwable e) {
    +            throw new RuntimeException("failed waiting on threads", e);
    +        }
    +
    +        InOrder inOrder = inOrder(observer);
    +        inOrder.verify(observer, times(1)).onNext("one");
    +        inOrder.verify(observer, times(1)).onNext("two");
    +        inOrder.verify(observer, times(1)).onNext("three");
    +        inOrder.verify(observer, times(1)).onNext("four");
    +        inOrder.verify(observer, times(1)).onNext("five");
    +        inOrder.verify(observer, times(1)).onNext("six");
    +        // we shouldn't have the following 3 yet
    +        inOrder.verify(observer, never()).onNext("seven");
    +        inOrder.verify(observer, never()).onNext("eight");
    +        inOrder.verify(observer, never()).onNext("nine");
    +        // we should not be completed yet
    +        verify(observer, never()).onCompleted();
    +        verify(observer, never()).onError(any(Throwable.class));
    +
    +        // now allow the third
    +        allowThird.countDown();
    +
    +        try {
    +            while (o3.t == null) {
    +                Thread.sleep(1);
    +            }
    +            // wait for 3rd to complete
    +            o3.t.join();
    +        } catch (Throwable e) {
    +            throw new RuntimeException("failed waiting on threads", e);
    +        }
    +
    +        inOrder.verify(observer, times(1)).onNext("seven");
    +        inOrder.verify(observer, times(1)).onNext("eight");
    +        inOrder.verify(observer, times(1)).onNext("nine");
    +
    +        inOrder.verify(observer, times(1)).onCompleted();
    +        verify(observer, never()).onError(any(Throwable.class));
         }
    -    // The concatenated observable should now have served up all the evens.
    -    verify(observer, times(1)).onNext("2");
    -    verify(observer, times(1)).onNext("4");
    -    verify(observer, times(1)).onNext("6");
    -  }
    -
    -  @Test
    -  public void testConcatConcurrentWithInfinity() {
    -    final TestObservable w1 = new TestObservable("one", "two", "three");
    -    //This observable will send "hello" MAX_VALUE time.
    -    final TestObservable w2 = new TestObservable("hello", Integer.MAX_VALUE);
     
         @SuppressWarnings("unchecked")
    -    Observer aObserver = mock(Observer.class);
    -    @SuppressWarnings("unchecked")
    -    TestObservable> observableOfObservables = new TestObservable>(Observable.create(w1), Observable.create(w2));
    -    Observable.OnSubscribeFunc concatF = concat(Observable.create(observableOfObservables));
    -
    -    Observable concat = Observable.create(concatF);
    +    @Test
    +    public void testBlockedObservableOfObservables() {
    +        Observer observer = mock(Observer.class);
    +
    +        final String[] o = { "1", "3", "5", "7" };
    +        final String[] e = { "2", "4", "6" };
    +        final Observable odds = Observable.from(o);
    +        final Observable even = Observable.from(e);
    +        final CountDownLatch callOnce = new CountDownLatch(1);
    +        final CountDownLatch okToContinue = new CountDownLatch(1);
    +        TestObservable> observableOfObservables = new TestObservable>(callOnce, okToContinue, odds, even);
    +        Observable.OnSubscribeFunc concatF = concat(Observable.create(observableOfObservables));
    +        Observable concat = Observable.create(concatF);
    +        concat.subscribe(observer);
    +        try {
    +            //Block main thread to allow observables to serve up o1.
    +            callOnce.await();
    +        } catch (Throwable ex) {
    +            ex.printStackTrace();
    +            fail(ex.getMessage());
    +        }
    +        // The concated observable should have served up all of the odds.
    +        verify(observer, times(1)).onNext("1");
    +        verify(observer, times(1)).onNext("3");
    +        verify(observer, times(1)).onNext("5");
    +        verify(observer, times(1)).onNext("7");
    +
    +        try {
    +            // unblock observables so it can serve up o2 and complete
    +            okToContinue.countDown();
    +            observableOfObservables.t.join();
    +        } catch (Throwable ex) {
    +            ex.printStackTrace();
    +            fail(ex.getMessage());
    +        }
    +        // The concatenated observable should now have served up all the evens.
    +        verify(observer, times(1)).onNext("2");
    +        verify(observer, times(1)).onNext("4");
    +        verify(observer, times(1)).onNext("6");
    +    }
     
    -    concat.take(50).subscribe(aObserver);
    +    @Test
    +    public void testConcatConcurrentWithInfinity() {
    +        final TestObservable w1 = new TestObservable("one", "two", "three");
    +        //This observable will send "hello" MAX_VALUE time.
    +        final TestObservable w2 = new TestObservable("hello", Integer.MAX_VALUE);
    +
    +        @SuppressWarnings("unchecked")
    +        Observer aObserver = mock(Observer.class);
    +        @SuppressWarnings("unchecked")
    +        TestObservable> observableOfObservables = new TestObservable>(Observable.create(w1), Observable.create(w2));
    +        Observable.OnSubscribeFunc concatF = concat(Observable.create(observableOfObservables));
    +
    +        Observable concat = Observable.create(concatF);
    +
    +        concat.take(50).subscribe(aObserver);
    +
    +        //Wait for the thread to start up.
    +        try {
    +            Thread.sleep(25);
    +            w1.t.join();
    +            w2.t.join();
    +        } catch (InterruptedException e) {
    +            // TODO Auto-generated catch block
    +            e.printStackTrace();
    +        }
     
    -    //Wait for the thread to start up.
    -    try {
    -      Thread.sleep(25);
    -      w1.t.join();
    -      w2.t.join();
    -    } catch (InterruptedException e) {
    -      // TODO Auto-generated catch block
    -      e.printStackTrace();
    +        InOrder inOrder = inOrder(aObserver);
    +        inOrder.verify(aObserver, times(1)).onNext("one");
    +        inOrder.verify(aObserver, times(1)).onNext("two");
    +        inOrder.verify(aObserver, times(1)).onNext("three");
    +        inOrder.verify(aObserver, times(47)).onNext("hello");
    +        verify(aObserver, times(1)).onCompleted();
    +        verify(aObserver, never()).onError(any(Throwable.class));
         }
     
    -    InOrder inOrder = inOrder(aObserver);
    -    inOrder.verify(aObserver, times(1)).onNext("one");
    -    inOrder.verify(aObserver, times(1)).onNext("two");
    -    inOrder.verify(aObserver, times(1)).onNext("three");
    -    inOrder.verify(aObserver, times(47)).onNext("hello");
    -    verify(aObserver, times(1)).onCompleted();
    -    verify(aObserver, never()).onError(any(Throwable.class));
    -  }
    +    @Test
    +    public void testConcatNonBlockingObservables() {
     
    -  @Test
    -  public void testConcatNonBlockingObservables() {
    +        final CountDownLatch okToContinueW1 = new CountDownLatch(1);
    +        final CountDownLatch okToContinueW2 = new CountDownLatch(1);
     
    -    final CountDownLatch okToContinueW1 = new CountDownLatch(1);
    -    final CountDownLatch okToContinueW2 = new CountDownLatch(1);
    +        final TestObservable w1 = new TestObservable(null, okToContinueW1, "one", "two", "three");
    +        final TestObservable w2 = new TestObservable(null, okToContinueW2, "four", "five", "six");
     
    -    final TestObservable w1 = new TestObservable(null, okToContinueW1, "one", "two", "three");
    -    final TestObservable w2 = new TestObservable(null, okToContinueW2, "four", "five", "six");
    +        @SuppressWarnings("unchecked")
    +        Observer aObserver = mock(Observer.class);
    +        Observable> observableOfObservables = Observable.create(new Observable.OnSubscribeFunc>() {
     
    -    @SuppressWarnings("unchecked")
    -    Observer aObserver = mock(Observer.class);
    -    Observable> observableOfObservables = Observable.create(new Observable.OnSubscribeFunc>() {
    +            @Override
    +            public Subscription onSubscribe(Observer> observer) {
    +                // simulate what would happen in an observable
    +                observer.onNext(Observable.create(w1));
    +                observer.onNext(Observable.create(w2));
    +                observer.onCompleted();
     
    -      @Override
    -      public Subscription onSubscribe(Observer> observer) {
    -        // simulate what would happen in an observable
    -        observer.onNext(Observable.create(w1));
    -        observer.onNext(Observable.create(w2));
    -        observer.onCompleted();
    +                return new Subscription() {
     
    -        return new Subscription() {
    +                    @Override
    +                    public void unsubscribe() {
    +                    }
     
    -          @Override
    -          public void unsubscribe() {
    -          }
    +                };
    +            }
     
    -        };
    -      }
    -
    -    });
    -    Observable concat = Observable.create(concat(observableOfObservables));
    -    concat.subscribe(aObserver);
    -
    -    verify(aObserver, times(0)).onCompleted();
    -
    -    try {
    -      // release both threads
    -      okToContinueW1.countDown();
    -      okToContinueW2.countDown();
    -      // wait for both to finish
    -      w1.t.join();
    -      w2.t.join();
    -    } catch (InterruptedException e) {
    -      // TODO Auto-generated catch block
    -      e.printStackTrace();
    -    }
    +        });
    +        Observable concat = Observable.create(concat(observableOfObservables));
    +        concat.subscribe(aObserver);
    +
    +        verify(aObserver, times(0)).onCompleted();
    +
    +        try {
    +            // release both threads
    +            okToContinueW1.countDown();
    +            okToContinueW2.countDown();
    +            // wait for both to finish
    +            w1.t.join();
    +            w2.t.join();
    +        } catch (InterruptedException e) {
    +            // TODO Auto-generated catch block
    +            e.printStackTrace();
    +        }
     
    -    InOrder inOrder = inOrder(aObserver);
    -    inOrder.verify(aObserver, times(1)).onNext("one");
    -    inOrder.verify(aObserver, times(1)).onNext("two");
    -    inOrder.verify(aObserver, times(1)).onNext("three");
    -    inOrder.verify(aObserver, times(1)).onNext("four");
    -    inOrder.verify(aObserver, times(1)).onNext("five");
    -    inOrder.verify(aObserver, times(1)).onNext("six");
    -    verify(aObserver, times(1)).onCompleted();
    -
    -  }
    -
    -  /**
    -   * Test unsubscribing the concatenated Observable in a single thread.
    -   */
    -  @Test
    -  public void testConcatUnsubscribe() {
    -    final CountDownLatch callOnce = new CountDownLatch(1);
    -    final CountDownLatch okToContinue = new CountDownLatch(1);
    -    final TestObservable w1 = new TestObservable("one", "two", "three");
    -    final TestObservable w2 = new TestObservable(callOnce, okToContinue, "four", "five", "six");
    +        InOrder inOrder = inOrder(aObserver);
    +        inOrder.verify(aObserver, times(1)).onNext("one");
    +        inOrder.verify(aObserver, times(1)).onNext("two");
    +        inOrder.verify(aObserver, times(1)).onNext("three");
    +        inOrder.verify(aObserver, times(1)).onNext("four");
    +        inOrder.verify(aObserver, times(1)).onNext("five");
    +        inOrder.verify(aObserver, times(1)).onNext("six");
    +        verify(aObserver, times(1)).onCompleted();
     
    -    @SuppressWarnings("unchecked")
    -    final Observer aObserver = mock(Observer.class);
    -    @SuppressWarnings("unchecked")
    -    final Observable concat = Observable.create(concat(Observable.create(w1), Observable.create(w2)));
    -    final SafeObservableSubscription s1 = new SafeObservableSubscription();
    -
    -    try {
    -      // Subscribe
    -      s1.wrap(concat.subscribe(aObserver));
    -      //Block main thread to allow observable "w1" to complete and observable "w2" to call onNext once.
    -      callOnce.await();
    -      // Unsubcribe
    -      s1.unsubscribe();
    -      //Unblock the observable to continue.
    -      okToContinue.countDown();
    -      w1.t.join();
    -      w2.t.join();
    -    } catch (Throwable e) {
    -      e.printStackTrace();
    -      fail(e.getMessage());
         }
     
    -    InOrder inOrder = inOrder(aObserver);
    -    inOrder.verify(aObserver, times(1)).onNext("one");
    -    inOrder.verify(aObserver, times(1)).onNext("two");
    -    inOrder.verify(aObserver, times(1)).onNext("three");
    -    inOrder.verify(aObserver, times(1)).onNext("four");
    -    inOrder.verify(aObserver, never()).onNext("five");
    -    inOrder.verify(aObserver, never()).onNext("six");
    -    inOrder.verify(aObserver, never()).onCompleted();
    -
    -  }
    -
    -  /**
    -   * All observables will be running in different threads so subscribe() is unblocked. CountDownLatch is only used in order to call unsubscribe() in a predictable manner.
    -   */
    -  @Test
    -  public void testConcatUnsubscribeConcurrent() {
    -    final CountDownLatch callOnce = new CountDownLatch(1);
    -    final CountDownLatch okToContinue = new CountDownLatch(1);
    -    final TestObservable w1 = new TestObservable("one", "two", "three");
    -    final TestObservable w2 = new TestObservable(callOnce, okToContinue, "four", "five", "six");
    +    /**
    +     * Test unsubscribing the concatenated Observable in a single thread.
    +     */
    +    @Test
    +    public void testConcatUnsubscribe() {
    +        final CountDownLatch callOnce = new CountDownLatch(1);
    +        final CountDownLatch okToContinue = new CountDownLatch(1);
    +        final TestObservable w1 = new TestObservable("one", "two", "three");
    +        final TestObservable w2 = new TestObservable(callOnce, okToContinue, "four", "five", "six");
    +
    +        @SuppressWarnings("unchecked")
    +        final Observer aObserver = mock(Observer.class);
    +        @SuppressWarnings("unchecked")
    +        final Observable concat = Observable.create(concat(Observable.create(w1), Observable.create(w2)));
    +        final SafeObservableSubscription s1 = new SafeObservableSubscription();
    +
    +        try {
    +            // Subscribe
    +            s1.wrap(concat.subscribe(aObserver));
    +            //Block main thread to allow observable "w1" to complete and observable "w2" to call onNext once.
    +            callOnce.await();
    +            // Unsubcribe
    +            s1.unsubscribe();
    +            //Unblock the observable to continue.
    +            okToContinue.countDown();
    +            w1.t.join();
    +            w2.t.join();
    +        } catch (Throwable e) {
    +            e.printStackTrace();
    +            fail(e.getMessage());
    +        }
     
    -    @SuppressWarnings("unchecked")
    -    Observer aObserver = mock(Observer.class);
    -    @SuppressWarnings("unchecked")
    -    TestObservable> observableOfObservables = new TestObservable>(Observable.create(w1), Observable.create(w2));
    -    Observable.OnSubscribeFunc concatF = concat(Observable.create(observableOfObservables));
    -
    -    Observable concat = Observable.create(concatF);
    -
    -    Subscription s1 = concat.subscribe(aObserver);
    -
    -    try {
    -      //Block main thread to allow observable "w1" to complete and observable "w2" to call onNext exactly once.
    -      callOnce.await();
    -      //"four" from w2 has been processed by onNext()
    -      s1.unsubscribe();
    -      //"five" and "six" will NOT be processed by onNext()
    -      //Unblock the observable to continue.
    -      okToContinue.countDown();
    -      w1.t.join();
    -      w2.t.join();
    -    } catch (Throwable e) {
    -      e.printStackTrace();
    -      fail(e.getMessage());
    -    }
    +        InOrder inOrder = inOrder(aObserver);
    +        inOrder.verify(aObserver, times(1)).onNext("one");
    +        inOrder.verify(aObserver, times(1)).onNext("two");
    +        inOrder.verify(aObserver, times(1)).onNext("three");
    +        inOrder.verify(aObserver, times(1)).onNext("four");
    +        inOrder.verify(aObserver, never()).onNext("five");
    +        inOrder.verify(aObserver, never()).onNext("six");
    +        inOrder.verify(aObserver, never()).onCompleted();
     
    -    InOrder inOrder = inOrder(aObserver);
    -    inOrder.verify(aObserver, times(1)).onNext("one");
    -    inOrder.verify(aObserver, times(1)).onNext("two");
    -    inOrder.verify(aObserver, times(1)).onNext("three");
    -    inOrder.verify(aObserver, times(1)).onNext("four");
    -    inOrder.verify(aObserver, never()).onNext("five");
    -    inOrder.verify(aObserver, never()).onNext("six");
    -    verify(aObserver, never()).onCompleted();
    -    verify(aObserver, never()).onError(any(Throwable.class));
    -  }
    -
    -  private static class TestObservable implements Observable.OnSubscribeFunc {
    -
    -    private final Subscription s = new Subscription() {
    -
    -      @Override
    -      public void unsubscribe() {
    -        subscribed = false;
    -      }
    -
    -    };
    -    private final List values;
    -    private Thread t = null;
    -    private int count = 0;
    -    private boolean subscribed = true;
    -    private final CountDownLatch once;
    -    private final CountDownLatch okToContinue;
    -    private final T seed;
    -    private final int size;
    -
    -    public TestObservable(T... values) {
    -      this(null, null, values);
         }
     
    -    public TestObservable(CountDownLatch once, CountDownLatch okToContinue, T... values) {
    -      this.values = Arrays.asList(values);
    -      this.size = this.values.size();
    -      this.once = once;
    -      this.okToContinue = okToContinue;
    -      this.seed = null;
    -    }
    +    /**
    +     * All observables will be running in different threads so subscribe() is unblocked. CountDownLatch is only used in order to call unsubscribe() in a predictable manner.
    +     */
    +    @Test
    +    public void testConcatUnsubscribeConcurrent() {
    +        final CountDownLatch callOnce = new CountDownLatch(1);
    +        final CountDownLatch okToContinue = new CountDownLatch(1);
    +        final TestObservable w1 = new TestObservable("one", "two", "three");
    +        final TestObservable w2 = new TestObservable(callOnce, okToContinue, "four", "five", "six");
    +
    +        @SuppressWarnings("unchecked")
    +        Observer aObserver = mock(Observer.class);
    +        @SuppressWarnings("unchecked")
    +        TestObservable> observableOfObservables = new TestObservable>(Observable.create(w1), Observable.create(w2));
    +        Observable.OnSubscribeFunc concatF = concat(Observable.create(observableOfObservables));
    +
    +        Observable concat = Observable.create(concatF);
    +
    +        Subscription s1 = concat.subscribe(aObserver);
    +
    +        try {
    +            //Block main thread to allow observable "w1" to complete and observable "w2" to call onNext exactly once.
    +            callOnce.await();
    +            //"four" from w2 has been processed by onNext()
    +            s1.unsubscribe();
    +            //"five" and "six" will NOT be processed by onNext()
    +            //Unblock the observable to continue.
    +            okToContinue.countDown();
    +            w1.t.join();
    +            w2.t.join();
    +        } catch (Throwable e) {
    +            e.printStackTrace();
    +            fail(e.getMessage());
    +        }
     
    -    public TestObservable(T seed, int size) {
    -      values = null;
    -      once = null;
    -      okToContinue = null;
    -      this.seed = seed;
    -      this.size = size;
    +        InOrder inOrder = inOrder(aObserver);
    +        inOrder.verify(aObserver, times(1)).onNext("one");
    +        inOrder.verify(aObserver, times(1)).onNext("two");
    +        inOrder.verify(aObserver, times(1)).onNext("three");
    +        inOrder.verify(aObserver, times(1)).onNext("four");
    +        inOrder.verify(aObserver, never()).onNext("five");
    +        inOrder.verify(aObserver, never()).onNext("six");
    +        verify(aObserver, never()).onCompleted();
    +        verify(aObserver, never()).onError(any(Throwable.class));
         }
     
    -    @Override
    -    public Subscription onSubscribe(final Observer observer) {
    -      t = new Thread(new Runnable() {
    +    private static class TestObservable implements Observable.OnSubscribeFunc {
     
    -        @Override
    -        public void run() {
    -          try {
    -            while (count < size && subscribed) {
    -              if (null != values)
    -                observer.onNext(values.get(count));
    -              else
    -                observer.onNext(seed);
    -              count++;
    -              //Unblock the main thread to call unsubscribe.
    -              if (null != once)
    -                once.countDown();
    -              //Block until the main thread has called unsubscribe.
    -              if (null != okToContinue)
    -                okToContinue.await(5, TimeUnit.SECONDS);
    +        private final Subscription s = new Subscription() {
    +
    +            @Override
    +            public void unsubscribe() {
    +                subscribed = false;
                 }
    -            if (subscribed)
    -              observer.onCompleted();
    -          } catch (InterruptedException e) {
    -            e.printStackTrace();
    -            fail(e.getMessage());
    -          }
    +
    +        };
    +        private final List values;
    +        private Thread t = null;
    +        private int count = 0;
    +        private boolean subscribed = true;
    +        private final CountDownLatch once;
    +        private final CountDownLatch okToContinue;
    +        private final T seed;
    +        private final int size;
    +
    +        public TestObservable(T... values) {
    +            this(null, null, values);
    +        }
    +
    +        public TestObservable(CountDownLatch once, CountDownLatch okToContinue, T... values) {
    +            this.values = Arrays.asList(values);
    +            this.size = this.values.size();
    +            this.once = once;
    +            this.okToContinue = okToContinue;
    +            this.seed = null;
             }
     
    -      });
    -      t.start();
    -      return s;
    +        public TestObservable(T seed, int size) {
    +            values = null;
    +            once = null;
    +            okToContinue = null;
    +            this.seed = seed;
    +            this.size = size;
    +        }
    +
    +        @Override
    +        public Subscription onSubscribe(final Observer observer) {
    +            t = new Thread(new Runnable() {
    +
    +                @Override
    +                public void run() {
    +                    try {
    +                        while (count < size && subscribed) {
    +                            if (null != values)
    +                                observer.onNext(values.get(count));
    +                            else
    +                                observer.onNext(seed);
    +                            count++;
    +                            //Unblock the main thread to call unsubscribe.
    +                            if (null != once)
    +                                once.countDown();
    +                            //Block until the main thread has called unsubscribe.
    +                            if (null != okToContinue)
    +                                okToContinue.await(5, TimeUnit.SECONDS);
    +                        }
    +                        if (subscribed)
    +                            observer.onCompleted();
    +                    } catch (InterruptedException e) {
    +                        e.printStackTrace();
    +                        fail(e.getMessage());
    +                    }
    +                }
    +
    +            });
    +            t.start();
    +            return s;
    +        }
         }
    -  }
     }
    diff --git a/rxjava-core/src/test/java/rx/operators/OperationDebounceTest.java b/rxjava-core/src/test/java/rx/operators/OperationDebounceTest.java
    index 2e907d8f6b..667c607301 100644
    --- a/rxjava-core/src/test/java/rx/operators/OperationDebounceTest.java
    +++ b/rxjava-core/src/test/java/rx/operators/OperationDebounceTest.java
    @@ -1,8 +1,14 @@
     package rx.operators;
     
    +import static org.mockito.Matchers.*;
    +import static org.mockito.Mockito.*;
    +
    +import java.util.concurrent.TimeUnit;
    +
     import org.junit.Before;
     import org.junit.Test;
     import org.mockito.InOrder;
    +
     import rx.Observable;
     import rx.Observer;
     import rx.Subscription;
    @@ -10,137 +16,131 @@
     import rx.subscriptions.Subscriptions;
     import rx.util.functions.Action0;
     
    -import java.util.concurrent.TimeUnit;
    -
    -import static org.mockito.Matchers.any;
    -import static org.mockito.Matchers.anyString;
    -import static org.mockito.Mockito.*;
    -
     public class OperationDebounceTest {
     
    -  private TestScheduler scheduler;
    -  private Observer observer;
    -
    -  @Before
    -  @SuppressWarnings("unchecked")
    -  public void before() {
    -    scheduler = new TestScheduler();
    -    observer = mock(Observer.class);
    -  }
    -
    -  @Test
    -  public void testDebounceWithCompleted() {
    -    Observable source = Observable.create(new Observable.OnSubscribeFunc() {
    -      @Override
    -      public Subscription onSubscribe(Observer observer) {
    -        publishNext(observer, 100, "one");    // Should be skipped since "two" will arrive before the timeout expires.
    -        publishNext(observer, 400, "two");    // Should be published since "three" will arrive after the timeout expires.
    -        publishNext(observer, 900, "three");   // Should be skipped since onCompleted will arrive before the timeout expires.
    -        publishCompleted(observer, 1000);     // Should be published as soon as the timeout expires.
    -
    -        return Subscriptions.empty();
    -      }
    -    });
    -
    -    Observable sampled = Observable.create(OperationDebounce.debounce(source, 400, TimeUnit.MILLISECONDS, scheduler));
    -    sampled.subscribe(observer);
    -
    -    scheduler.advanceTimeTo(0, TimeUnit.MILLISECONDS);
    -    InOrder inOrder = inOrder(observer);
    -    // must go to 800 since it must be 400 after when two is sent, which is at 400
    -    scheduler.advanceTimeTo(800, TimeUnit.MILLISECONDS);
    -    inOrder.verify(observer, times(1)).onNext("two");
    -    scheduler.advanceTimeTo(1000, TimeUnit.MILLISECONDS);
    -    inOrder.verify(observer, times(1)).onCompleted();
    -    inOrder.verifyNoMoreInteractions();
    -  }
    -
    -  @Test
    -  public void testDebounceNeverEmits() {
    -    Observable source = Observable.create(new Observable.OnSubscribeFunc() {
    -      @Override
    -      public Subscription onSubscribe(Observer observer) {
    -        // all should be skipped since they are happening faster than the 200ms timeout
    -        publishNext(observer, 100, "a");    // Should be skipped
    -        publishNext(observer, 200, "b");    // Should be skipped
    -        publishNext(observer, 300, "c");    // Should be skipped
    -        publishNext(observer, 400, "d");    // Should be skipped
    -        publishNext(observer, 500, "e");    // Should be skipped
    -        publishNext(observer, 600, "f");    // Should be skipped
    -        publishNext(observer, 700, "g");    // Should be skipped
    -        publishNext(observer, 800, "h");    // Should be skipped
    -        publishCompleted(observer, 900);     // Should be published as soon as the timeout expires.
    -
    -        return Subscriptions.empty();
    -      }
    -    });
    -
    -    Observable sampled = Observable.create(OperationDebounce.debounce(source, 200, TimeUnit.MILLISECONDS, scheduler));
    -    sampled.subscribe(observer);
    -
    -    scheduler.advanceTimeTo(0, TimeUnit.MILLISECONDS);
    -    InOrder inOrder = inOrder(observer);
    -    inOrder.verify(observer, times(0)).onNext(anyString());
    -    scheduler.advanceTimeTo(1000, TimeUnit.MILLISECONDS);
    -    inOrder.verify(observer, times(1)).onCompleted();
    -    inOrder.verifyNoMoreInteractions();
    -  }
    -
    -  @Test
    -  public void testDebounceWithError() {
    -    Observable source = Observable.create(new Observable.OnSubscribeFunc() {
    -      @Override
    -      public Subscription onSubscribe(Observer observer) {
    -        Exception error = new TestException();
    -        publishNext(observer, 100, "one");    // Should be published since "two" will arrive after the timeout expires.
    -        publishNext(observer, 600, "two");    // Should be skipped since onError will arrive before the timeout expires.
    -        publishError(observer, 700, error);   // Should be published as soon as the timeout expires.
    -
    -        return Subscriptions.empty();
    -      }
    -    });
    -
    -    Observable sampled = Observable.create(OperationDebounce.debounce(source, 400, TimeUnit.MILLISECONDS, scheduler));
    -    sampled.subscribe(observer);
    -
    -    scheduler.advanceTimeTo(0, TimeUnit.MILLISECONDS);
    -    InOrder inOrder = inOrder(observer);
    -    // 100 + 400 means it triggers at 500
    -    scheduler.advanceTimeTo(500, TimeUnit.MILLISECONDS);
    -    inOrder.verify(observer).onNext("one");
    -    scheduler.advanceTimeTo(701, TimeUnit.MILLISECONDS);
    -    inOrder.verify(observer).onError(any(TestException.class));
    -    inOrder.verifyNoMoreInteractions();
    -  }
    -
    -  private  void publishCompleted(final Observer observer, long delay) {
    -    scheduler.schedule(new Action0() {
    -      @Override
    -      public void call() {
    -        observer.onCompleted();
    -      }
    -    }, delay, TimeUnit.MILLISECONDS);
    -  }
    -
    -  private  void publishError(final Observer observer, long delay, final Exception error) {
    -    scheduler.schedule(new Action0() {
    -      @Override
    -      public void call() {
    -        observer.onError(error);
    -      }
    -    }, delay, TimeUnit.MILLISECONDS);
    -  }
    -
    -  private  void publishNext(final Observer observer, final long delay, final T value) {
    -    scheduler.schedule(new Action0() {
    -      @Override
    -      public void call() {
    -        observer.onNext(value);
    -      }
    -    }, delay, TimeUnit.MILLISECONDS);
    -  }
    -
    -  @SuppressWarnings("serial")
    -  private class TestException extends Exception {
    -  }
    +    private TestScheduler scheduler;
    +    private Observer observer;
    +
    +    @Before
    +    @SuppressWarnings("unchecked")
    +    public void before() {
    +        scheduler = new TestScheduler();
    +        observer = mock(Observer.class);
    +    }
    +
    +    @Test
    +    public void testDebounceWithCompleted() {
    +        Observable source = Observable.create(new Observable.OnSubscribeFunc() {
    +            @Override
    +            public Subscription onSubscribe(Observer observer) {
    +                publishNext(observer, 100, "one");    // Should be skipped since "two" will arrive before the timeout expires.
    +                publishNext(observer, 400, "two");    // Should be published since "three" will arrive after the timeout expires.
    +                publishNext(observer, 900, "three");   // Should be skipped since onCompleted will arrive before the timeout expires.
    +                publishCompleted(observer, 1000);     // Should be published as soon as the timeout expires.
    +
    +                return Subscriptions.empty();
    +            }
    +        });
    +
    +        Observable sampled = Observable.create(OperationDebounce.debounce(source, 400, TimeUnit.MILLISECONDS, scheduler));
    +        sampled.subscribe(observer);
    +
    +        scheduler.advanceTimeTo(0, TimeUnit.MILLISECONDS);
    +        InOrder inOrder = inOrder(observer);
    +        // must go to 800 since it must be 400 after when two is sent, which is at 400
    +        scheduler.advanceTimeTo(800, TimeUnit.MILLISECONDS);
    +        inOrder.verify(observer, times(1)).onNext("two");
    +        scheduler.advanceTimeTo(1000, TimeUnit.MILLISECONDS);
    +        inOrder.verify(observer, times(1)).onCompleted();
    +        inOrder.verifyNoMoreInteractions();
    +    }
    +
    +    @Test
    +    public void testDebounceNeverEmits() {
    +        Observable source = Observable.create(new Observable.OnSubscribeFunc() {
    +            @Override
    +            public Subscription onSubscribe(Observer observer) {
    +                // all should be skipped since they are happening faster than the 200ms timeout
    +                publishNext(observer, 100, "a");    // Should be skipped
    +                publishNext(observer, 200, "b");    // Should be skipped
    +                publishNext(observer, 300, "c");    // Should be skipped
    +                publishNext(observer, 400, "d");    // Should be skipped
    +                publishNext(observer, 500, "e");    // Should be skipped
    +                publishNext(observer, 600, "f");    // Should be skipped
    +                publishNext(observer, 700, "g");    // Should be skipped
    +                publishNext(observer, 800, "h");    // Should be skipped
    +                publishCompleted(observer, 900);     // Should be published as soon as the timeout expires.
    +
    +                return Subscriptions.empty();
    +            }
    +        });
    +
    +        Observable sampled = Observable.create(OperationDebounce.debounce(source, 200, TimeUnit.MILLISECONDS, scheduler));
    +        sampled.subscribe(observer);
    +
    +        scheduler.advanceTimeTo(0, TimeUnit.MILLISECONDS);
    +        InOrder inOrder = inOrder(observer);
    +        inOrder.verify(observer, times(0)).onNext(anyString());
    +        scheduler.advanceTimeTo(1000, TimeUnit.MILLISECONDS);
    +        inOrder.verify(observer, times(1)).onCompleted();
    +        inOrder.verifyNoMoreInteractions();
    +    }
    +
    +    @Test
    +    public void testDebounceWithError() {
    +        Observable source = Observable.create(new Observable.OnSubscribeFunc() {
    +            @Override
    +            public Subscription onSubscribe(Observer observer) {
    +                Exception error = new TestException();
    +                publishNext(observer, 100, "one");    // Should be published since "two" will arrive after the timeout expires.
    +                publishNext(observer, 600, "two");    // Should be skipped since onError will arrive before the timeout expires.
    +                publishError(observer, 700, error);   // Should be published as soon as the timeout expires.
    +
    +                return Subscriptions.empty();
    +            }
    +        });
    +
    +        Observable sampled = Observable.create(OperationDebounce.debounce(source, 400, TimeUnit.MILLISECONDS, scheduler));
    +        sampled.subscribe(observer);
    +
    +        scheduler.advanceTimeTo(0, TimeUnit.MILLISECONDS);
    +        InOrder inOrder = inOrder(observer);
    +        // 100 + 400 means it triggers at 500
    +        scheduler.advanceTimeTo(500, TimeUnit.MILLISECONDS);
    +        inOrder.verify(observer).onNext("one");
    +        scheduler.advanceTimeTo(701, TimeUnit.MILLISECONDS);
    +        inOrder.verify(observer).onError(any(TestException.class));
    +        inOrder.verifyNoMoreInteractions();
    +    }
    +
    +    private  void publishCompleted(final Observer observer, long delay) {
    +        scheduler.schedule(new Action0() {
    +            @Override
    +            public void call() {
    +                observer.onCompleted();
    +            }
    +        }, delay, TimeUnit.MILLISECONDS);
    +    }
    +
    +    private  void publishError(final Observer observer, long delay, final Exception error) {
    +        scheduler.schedule(new Action0() {
    +            @Override
    +            public void call() {
    +                observer.onError(error);
    +            }
    +        }, delay, TimeUnit.MILLISECONDS);
    +    }
    +
    +    private  void publishNext(final Observer observer, final long delay, final T value) {
    +        scheduler.schedule(new Action0() {
    +            @Override
    +            public void call() {
    +                observer.onNext(value);
    +            }
    +        }, delay, TimeUnit.MILLISECONDS);
    +    }
    +
    +    @SuppressWarnings("serial")
    +    private class TestException extends Exception {
    +    }
     }
    diff --git a/rxjava-core/src/test/java/rx/operators/OperationDefaultIfEmptyTest.java b/rxjava-core/src/test/java/rx/operators/OperationDefaultIfEmptyTest.java
    index fb2166dfc1..fa4910707c 100644
    --- a/rxjava-core/src/test/java/rx/operators/OperationDefaultIfEmptyTest.java
    +++ b/rxjava-core/src/test/java/rx/operators/OperationDefaultIfEmptyTest.java
    @@ -1,44 +1,45 @@
     package rx.operators;
     
    +import static org.mockito.Mockito.*;
    +import static rx.operators.OperationDefaultIfEmpty.*;
    +
     import org.junit.Test;
    +
     import rx.Observable;
     import rx.Observer;
     
    -import static org.mockito.Mockito.*;
    -import static rx.operators.OperationDefaultIfEmpty.defaultIfEmpty;
    -
     public class OperationDefaultIfEmptyTest {
     
    -  @Test
    -  public void testDefaultIfEmpty() {
    -    Observable source = Observable.from(1, 2, 3);
    -    Observable observable = Observable.create(defaultIfEmpty(
    -        source, 10));
    -
    -    @SuppressWarnings("unchecked")
    -    Observer aObserver = mock(Observer.class);
    -    observable.subscribe(aObserver);
    -    verify(aObserver, never()).onNext(10);
    -    verify(aObserver, times(1)).onNext(1);
    -    verify(aObserver, times(1)).onNext(2);
    -    verify(aObserver, times(1)).onNext(3);
    -    verify(aObserver, never()).onError(
    -        org.mockito.Matchers.any(Throwable.class));
    -    verify(aObserver, times(1)).onCompleted();
    -  }
    -
    -  @Test
    -  public void testDefaultIfEmptyWithEmpty() {
    -    Observable source = Observable.empty();
    -    Observable observable = Observable.create(defaultIfEmpty(
    -        source, 10));
    -
    -    @SuppressWarnings("unchecked")
    -    Observer aObserver = mock(Observer.class);
    -    observable.subscribe(aObserver);
    -    verify(aObserver, times(1)).onNext(10);
    -    verify(aObserver, never()).onError(
    -        org.mockito.Matchers.any(Throwable.class));
    -    verify(aObserver, times(1)).onCompleted();
    -  }
    +    @Test
    +    public void testDefaultIfEmpty() {
    +        Observable source = Observable.from(1, 2, 3);
    +        Observable observable = Observable.create(defaultIfEmpty(
    +                source, 10));
    +
    +        @SuppressWarnings("unchecked")
    +        Observer aObserver = mock(Observer.class);
    +        observable.subscribe(aObserver);
    +        verify(aObserver, never()).onNext(10);
    +        verify(aObserver, times(1)).onNext(1);
    +        verify(aObserver, times(1)).onNext(2);
    +        verify(aObserver, times(1)).onNext(3);
    +        verify(aObserver, never()).onError(
    +                org.mockito.Matchers.any(Throwable.class));
    +        verify(aObserver, times(1)).onCompleted();
    +    }
    +
    +    @Test
    +    public void testDefaultIfEmptyWithEmpty() {
    +        Observable source = Observable.empty();
    +        Observable observable = Observable.create(defaultIfEmpty(
    +                source, 10));
    +
    +        @SuppressWarnings("unchecked")
    +        Observer aObserver = mock(Observer.class);
    +        observable.subscribe(aObserver);
    +        verify(aObserver, times(1)).onNext(10);
    +        verify(aObserver, never()).onError(
    +                org.mockito.Matchers.any(Throwable.class));
    +        verify(aObserver, times(1)).onCompleted();
    +    }
     }
    diff --git a/rxjava-core/src/test/java/rx/operators/OperationDeferTest.java b/rxjava-core/src/test/java/rx/operators/OperationDeferTest.java
    index 8e02b17647..6ad98c9a8d 100644
    --- a/rxjava-core/src/test/java/rx/operators/OperationDeferTest.java
    +++ b/rxjava-core/src/test/java/rx/operators/OperationDeferTest.java
    @@ -1,47 +1,48 @@
     package rx.operators;
     
    +import static org.mockito.Mockito.*;
    +
     import org.junit.Test;
    +
     import rx.Observable;
     import rx.Observer;
     import rx.util.functions.Func0;
     
    -import static org.mockito.Mockito.*;
    -
     public class OperationDeferTest {
     
    -  @Test
    -  @SuppressWarnings("unchecked")
    -  public void testDefer() throws Throwable {
    +    @Test
    +    @SuppressWarnings("unchecked")
    +    public void testDefer() throws Throwable {
     
    -    Func0> factory = mock(Func0.class);
    +        Func0> factory = mock(Func0.class);
     
    -    Observable firstObservable = Observable.from("one", "two");
    -    Observable secondObservable = Observable.from("three", "four");
    -    when(factory.call()).thenReturn(firstObservable, secondObservable);
    +        Observable firstObservable = Observable.from("one", "two");
    +        Observable secondObservable = Observable.from("three", "four");
    +        when(factory.call()).thenReturn(firstObservable, secondObservable);
     
    -    Observable deferred = Observable.defer(factory);
    +        Observable deferred = Observable.defer(factory);
     
    -    verifyZeroInteractions(factory);
    +        verifyZeroInteractions(factory);
     
    -    Observer firstObserver = mock(Observer.class);
    -    deferred.subscribe(firstObserver);
    +        Observer firstObserver = mock(Observer.class);
    +        deferred.subscribe(firstObserver);
     
    -    verify(factory, times(1)).call();
    -    verify(firstObserver, times(1)).onNext("one");
    -    verify(firstObserver, times(1)).onNext("two");
    -    verify(firstObserver, times(0)).onNext("three");
    -    verify(firstObserver, times(0)).onNext("four");
    -    verify(firstObserver, times(1)).onCompleted();
    +        verify(factory, times(1)).call();
    +        verify(firstObserver, times(1)).onNext("one");
    +        verify(firstObserver, times(1)).onNext("two");
    +        verify(firstObserver, times(0)).onNext("three");
    +        verify(firstObserver, times(0)).onNext("four");
    +        verify(firstObserver, times(1)).onCompleted();
     
    -    Observer secondObserver = mock(Observer.class);
    -    deferred.subscribe(secondObserver);
    +        Observer secondObserver = mock(Observer.class);
    +        deferred.subscribe(secondObserver);
     
    -    verify(factory, times(2)).call();
    -    verify(secondObserver, times(0)).onNext("one");
    -    verify(secondObserver, times(0)).onNext("two");
    -    verify(secondObserver, times(1)).onNext("three");
    -    verify(secondObserver, times(1)).onNext("four");
    -    verify(secondObserver, times(1)).onCompleted();
    +        verify(factory, times(2)).call();
    +        verify(secondObserver, times(0)).onNext("one");
    +        verify(secondObserver, times(0)).onNext("two");
    +        verify(secondObserver, times(1)).onNext("three");
    +        verify(secondObserver, times(1)).onNext("four");
    +        verify(secondObserver, times(1)).onCompleted();
     
    -  }
    +    }
     }
    diff --git a/rxjava-core/src/test/java/rx/operators/OperationDematerializeTest.java b/rxjava-core/src/test/java/rx/operators/OperationDematerializeTest.java
    index fcc1898d4a..3ca31f160c 100644
    --- a/rxjava-core/src/test/java/rx/operators/OperationDematerializeTest.java
    +++ b/rxjava-core/src/test/java/rx/operators/OperationDematerializeTest.java
    @@ -1,58 +1,59 @@
     package rx.operators;
     
    +import static org.mockito.Matchers.*;
    +import static org.mockito.Mockito.*;
    +import static rx.operators.OperationDematerialize.*;
    +
     import org.junit.Test;
    +
     import rx.Notification;
     import rx.Observable;
     import rx.Observer;
     
    -import static org.mockito.Matchers.any;
    -import static org.mockito.Mockito.*;
    -import static rx.operators.OperationDematerialize.dematerialize;
    -
     public class OperationDematerializeTest {
     
    -  @Test
    -  @SuppressWarnings("unchecked")
    -  public void testDematerialize1() {
    -    Observable> notifications = Observable.from(1, 2).materialize();
    -    Observable dematerialize = notifications.dematerialize();
    -
    -    Observer aObserver = mock(Observer.class);
    -    dematerialize.subscribe(aObserver);
    -
    -    verify(aObserver, times(1)).onNext(1);
    -    verify(aObserver, times(1)).onNext(2);
    -    verify(aObserver, times(1)).onCompleted();
    -    verify(aObserver, never()).onError(any(Throwable.class));
    -  }
    -
    -  @Test
    -  @SuppressWarnings("unchecked")
    -  public void testDematerialize2() {
    -    Throwable exception = new Throwable("test");
    -    Observable observable = Observable.error(exception);
    -    Observable dematerialize = Observable.create(dematerialize(observable.materialize()));
    -
    -    Observer aObserver = mock(Observer.class);
    -    dematerialize.subscribe(aObserver);
    -
    -    verify(aObserver, times(1)).onError(exception);
    -    verify(aObserver, times(0)).onCompleted();
    -    verify(aObserver, times(0)).onNext(any(Integer.class));
    -  }
    -
    -  @Test
    -  @SuppressWarnings("unchecked")
    -  public void testDematerialize3() {
    -    Exception exception = new Exception("test");
    -    Observable observable = Observable.error(exception);
    -    Observable dematerialize = Observable.create(dematerialize(observable.materialize()));
    -
    -    Observer aObserver = mock(Observer.class);
    -    dematerialize.subscribe(aObserver);
    -
    -    verify(aObserver, times(1)).onError(exception);
    -    verify(aObserver, times(0)).onCompleted();
    -    verify(aObserver, times(0)).onNext(any(Integer.class));
    -  }
    +    @Test
    +    @SuppressWarnings("unchecked")
    +    public void testDematerialize1() {
    +        Observable> notifications = Observable.from(1, 2).materialize();
    +        Observable dematerialize = notifications.dematerialize();
    +
    +        Observer aObserver = mock(Observer.class);
    +        dematerialize.subscribe(aObserver);
    +
    +        verify(aObserver, times(1)).onNext(1);
    +        verify(aObserver, times(1)).onNext(2);
    +        verify(aObserver, times(1)).onCompleted();
    +        verify(aObserver, never()).onError(any(Throwable.class));
    +    }
    +
    +    @Test
    +    @SuppressWarnings("unchecked")
    +    public void testDematerialize2() {
    +        Throwable exception = new Throwable("test");
    +        Observable observable = Observable.error(exception);
    +        Observable dematerialize = Observable.create(dematerialize(observable.materialize()));
    +
    +        Observer aObserver = mock(Observer.class);
    +        dematerialize.subscribe(aObserver);
    +
    +        verify(aObserver, times(1)).onError(exception);
    +        verify(aObserver, times(0)).onCompleted();
    +        verify(aObserver, times(0)).onNext(any(Integer.class));
    +    }
    +
    +    @Test
    +    @SuppressWarnings("unchecked")
    +    public void testDematerialize3() {
    +        Exception exception = new Exception("test");
    +        Observable observable = Observable.error(exception);
    +        Observable dematerialize = Observable.create(dematerialize(observable.materialize()));
    +
    +        Observer aObserver = mock(Observer.class);
    +        dematerialize.subscribe(aObserver);
    +
    +        verify(aObserver, times(1)).onError(exception);
    +        verify(aObserver, times(0)).onCompleted();
    +        verify(aObserver, times(0)).onNext(any(Integer.class));
    +    }
     }
    diff --git a/rxjava-core/src/test/java/rx/operators/OperationDistinctTest.java b/rxjava-core/src/test/java/rx/operators/OperationDistinctTest.java
    index f1c91c0fed..9d0e1569b5 100644
    --- a/rxjava-core/src/test/java/rx/operators/OperationDistinctTest.java
    +++ b/rxjava-core/src/test/java/rx/operators/OperationDistinctTest.java
    @@ -18,163 +18,163 @@
     
     public class OperationDistinctTest {
     
    -  @Mock
    -  Observer w;
    -  @Mock
    -  Observer w2;
    -
    -  // nulls lead to exceptions
    -  final Func1 TO_UPPER_WITH_EXCEPTION = new Func1() {
    -    @Override
    -    public String call(String s) {
    -      if (s.equals("x")) {
    -        return "XX";
    -      }
    -      return s.toUpperCase();
    +    @Mock
    +    Observer w;
    +    @Mock
    +    Observer w2;
    +
    +    // nulls lead to exceptions
    +    final Func1 TO_UPPER_WITH_EXCEPTION = new Func1() {
    +        @Override
    +        public String call(String s) {
    +            if (s.equals("x")) {
    +                return "XX";
    +            }
    +            return s.toUpperCase();
    +        }
    +    };
    +
    +    final Comparator COMPARE_LENGTH = new Comparator() {
    +        @Override
    +        public int compare(String s1, String s2) {
    +            return s1.length() - s2.length();
    +        }
    +    };
    +
    +    @Before
    +    public void before() {
    +        initMocks(this);
         }
    -  };
     
    -  final Comparator COMPARE_LENGTH = new Comparator() {
    -    @Override
    -    public int compare(String s1, String s2) {
    -      return s1.length() - s2.length();
    +    @Test
    +    public void testDistinctOfNone() {
    +        Observable src = Observable.empty();
    +        Observable.create(distinct(src)).subscribe(w);
    +
    +        verify(w, never()).onNext(anyString());
    +        verify(w, never()).onError(any(Throwable.class));
    +        verify(w, times(1)).onCompleted();
    +    }
    +
    +    @Test
    +    public void testDistinctOfNoneWithKeySelector() {
    +        Observable src = Observable.empty();
    +        Observable.create(distinct(src, TO_UPPER_WITH_EXCEPTION)).subscribe(w);
    +
    +        verify(w, never()).onNext(anyString());
    +        verify(w, never()).onError(any(Throwable.class));
    +        verify(w, times(1)).onCompleted();
    +    }
    +
    +    @Test
    +    public void testDistinctOfNormalSource() {
    +        Observable src = Observable.from("a", "b", "c", "c", "c", "b", "b", "a", "e");
    +        Observable.create(distinct(src)).subscribe(w);
    +
    +        InOrder inOrder = inOrder(w);
    +        inOrder.verify(w, times(1)).onNext("a");
    +        inOrder.verify(w, times(1)).onNext("b");
    +        inOrder.verify(w, times(1)).onNext("c");
    +        inOrder.verify(w, times(1)).onNext("e");
    +        inOrder.verify(w, times(1)).onCompleted();
    +        inOrder.verify(w, never()).onNext(anyString());
    +        verify(w, never()).onError(any(Throwable.class));
    +    }
    +
    +    @Test
    +    public void testDistinctOfNormalSourceWithKeySelector() {
    +        Observable src = Observable.from("a", "B", "c", "C", "c", "B", "b", "a", "E");
    +        Observable.create(distinct(src, TO_UPPER_WITH_EXCEPTION)).subscribe(w);
    +
    +        InOrder inOrder = inOrder(w);
    +        inOrder.verify(w, times(1)).onNext("a");
    +        inOrder.verify(w, times(1)).onNext("B");
    +        inOrder.verify(w, times(1)).onNext("c");
    +        inOrder.verify(w, times(1)).onNext("E");
    +        inOrder.verify(w, times(1)).onCompleted();
    +        inOrder.verify(w, never()).onNext(anyString());
    +        verify(w, never()).onError(any(Throwable.class));
    +    }
    +
    +    @Test
    +    public void testDistinctOfNormalSourceWithComparator() {
    +        Observable src = Observable.from("1", "12", "123", "aaa", "321", "12", "21", "1", "12345");
    +        Observable.create(distinct(src, COMPARE_LENGTH)).subscribe(w);
    +
    +        InOrder inOrder = inOrder(w);
    +        inOrder.verify(w, times(1)).onNext("1");
    +        inOrder.verify(w, times(1)).onNext("12");
    +        inOrder.verify(w, times(1)).onNext("123");
    +        inOrder.verify(w, times(1)).onNext("12345");
    +        inOrder.verify(w, times(1)).onCompleted();
    +        inOrder.verify(w, never()).onNext(anyString());
    +        verify(w, never()).onError(any(Throwable.class));
    +    }
    +
    +    @Test
    +    public void testDistinctOfNormalSourceWithKeySelectorAndComparator() {
    +        Observable src = Observable.from("a", "x", "ab", "abc", "cba", "de", "x", "a", "abcd");
    +        Observable.create(distinct(src, TO_UPPER_WITH_EXCEPTION, COMPARE_LENGTH)).subscribe(w);
    +
    +        InOrder inOrder = inOrder(w);
    +        inOrder.verify(w, times(1)).onNext("a");
    +        inOrder.verify(w, times(1)).onNext("x");
    +        inOrder.verify(w, times(1)).onNext("abc");
    +        inOrder.verify(w, times(1)).onNext("abcd");
    +        inOrder.verify(w, times(1)).onCompleted();
    +        inOrder.verify(w, never()).onNext(anyString());
    +        verify(w, never()).onError(any(Throwable.class));
    +    }
    +
    +    @Test
    +    public void testDistinctOfNormalSourceWithKeySelectorAndComparatorAndTwoSubscriptions() {
    +        Observable src = Observable.from("a", "x", "ab", "abc", "cba", "de", "x", "a", "abcd");
    +        Observable.create(distinct(src, TO_UPPER_WITH_EXCEPTION, COMPARE_LENGTH)).subscribe(w);
    +
    +        InOrder inOrder = inOrder(w);
    +        inOrder.verify(w, times(1)).onNext("a");
    +        inOrder.verify(w, times(1)).onNext("x");
    +        Observable.create(distinct(src, TO_UPPER_WITH_EXCEPTION, COMPARE_LENGTH)).subscribe(w2);
    +        inOrder.verify(w, times(1)).onNext("abc");
    +        inOrder.verify(w, times(1)).onNext("abcd");
    +        inOrder.verify(w, times(1)).onCompleted();
    +        inOrder.verify(w, never()).onNext(anyString());
    +        verify(w, never()).onError(any(Throwable.class));
    +
    +        InOrder inOrder2 = inOrder(w2);
    +        inOrder2.verify(w2, times(1)).onNext("a");
    +        inOrder2.verify(w2, times(1)).onNext("x");
    +        inOrder2.verify(w2, times(1)).onNext("abc");
    +        inOrder2.verify(w2, times(1)).onNext("abcd");
    +        inOrder2.verify(w2, times(1)).onCompleted();
    +        inOrder2.verify(w2, never()).onNext(anyString());
    +        verify(w2, never()).onError(any(Throwable.class));
    +    }
    +
    +    @Test
    +    public void testDistinctOfSourceWithNulls() {
    +        Observable src = Observable.from(null, "a", "a", null, null, "b", null);
    +        Observable.create(distinct(src)).subscribe(w);
    +
    +        InOrder inOrder = inOrder(w);
    +        inOrder.verify(w, times(1)).onNext(null);
    +        inOrder.verify(w, times(1)).onNext("a");
    +        inOrder.verify(w, times(1)).onNext("b");
    +        inOrder.verify(w, times(1)).onCompleted();
    +        inOrder.verify(w, never()).onNext(anyString());
    +        verify(w, never()).onError(any(Throwable.class));
    +    }
    +
    +    @Test
    +    public void testDistinctOfSourceWithExceptionsFromKeySelector() {
    +        Observable src = Observable.from("a", "b", null, "c");
    +        Observable.create(distinct(src, TO_UPPER_WITH_EXCEPTION)).subscribe(w);
    +
    +        InOrder inOrder = inOrder(w);
    +        inOrder.verify(w, times(1)).onNext("a");
    +        inOrder.verify(w, times(1)).onNext("b");
    +        inOrder.verify(w, times(1)).onError(any(NullPointerException.class));
    +        inOrder.verify(w, never()).onNext(anyString());
    +        inOrder.verify(w, never()).onCompleted();
         }
    -  };
    -
    -  @Before
    -  public void before() {
    -    initMocks(this);
    -  }
    -
    -  @Test
    -  public void testDistinctOfNone() {
    -    Observable src = Observable.empty();
    -    Observable.create(distinct(src)).subscribe(w);
    -
    -    verify(w, never()).onNext(anyString());
    -    verify(w, never()).onError(any(Throwable.class));
    -    verify(w, times(1)).onCompleted();
    -  }
    -
    -  @Test
    -  public void testDistinctOfNoneWithKeySelector() {
    -    Observable src = Observable.empty();
    -    Observable.create(distinct(src, TO_UPPER_WITH_EXCEPTION)).subscribe(w);
    -
    -    verify(w, never()).onNext(anyString());
    -    verify(w, never()).onError(any(Throwable.class));
    -    verify(w, times(1)).onCompleted();
    -  }
    -
    -  @Test
    -  public void testDistinctOfNormalSource() {
    -    Observable src = Observable.from("a", "b", "c", "c", "c", "b", "b", "a", "e");
    -    Observable.create(distinct(src)).subscribe(w);
    -
    -    InOrder inOrder = inOrder(w);
    -    inOrder.verify(w, times(1)).onNext("a");
    -    inOrder.verify(w, times(1)).onNext("b");
    -    inOrder.verify(w, times(1)).onNext("c");
    -    inOrder.verify(w, times(1)).onNext("e");
    -    inOrder.verify(w, times(1)).onCompleted();
    -    inOrder.verify(w, never()).onNext(anyString());
    -    verify(w, never()).onError(any(Throwable.class));
    -  }
    -
    -  @Test
    -  public void testDistinctOfNormalSourceWithKeySelector() {
    -    Observable src = Observable.from("a", "B", "c", "C", "c", "B", "b", "a", "E");
    -    Observable.create(distinct(src, TO_UPPER_WITH_EXCEPTION)).subscribe(w);
    -
    -    InOrder inOrder = inOrder(w);
    -    inOrder.verify(w, times(1)).onNext("a");
    -    inOrder.verify(w, times(1)).onNext("B");
    -    inOrder.verify(w, times(1)).onNext("c");
    -    inOrder.verify(w, times(1)).onNext("E");
    -    inOrder.verify(w, times(1)).onCompleted();
    -    inOrder.verify(w, never()).onNext(anyString());
    -    verify(w, never()).onError(any(Throwable.class));
    -  }
    -
    -  @Test
    -  public void testDistinctOfNormalSourceWithComparator() {
    -    Observable src = Observable.from("1", "12", "123", "aaa", "321", "12", "21", "1", "12345");
    -    Observable.create(distinct(src, COMPARE_LENGTH)).subscribe(w);
    -
    -    InOrder inOrder = inOrder(w);
    -    inOrder.verify(w, times(1)).onNext("1");
    -    inOrder.verify(w, times(1)).onNext("12");
    -    inOrder.verify(w, times(1)).onNext("123");
    -    inOrder.verify(w, times(1)).onNext("12345");
    -    inOrder.verify(w, times(1)).onCompleted();
    -    inOrder.verify(w, never()).onNext(anyString());
    -    verify(w, never()).onError(any(Throwable.class));
    -  }
    -
    -  @Test
    -  public void testDistinctOfNormalSourceWithKeySelectorAndComparator() {
    -    Observable src = Observable.from("a", "x", "ab", "abc", "cba", "de", "x", "a", "abcd");
    -    Observable.create(distinct(src, TO_UPPER_WITH_EXCEPTION, COMPARE_LENGTH)).subscribe(w);
    -
    -    InOrder inOrder = inOrder(w);
    -    inOrder.verify(w, times(1)).onNext("a");
    -    inOrder.verify(w, times(1)).onNext("x");
    -    inOrder.verify(w, times(1)).onNext("abc");
    -    inOrder.verify(w, times(1)).onNext("abcd");
    -    inOrder.verify(w, times(1)).onCompleted();
    -    inOrder.verify(w, never()).onNext(anyString());
    -    verify(w, never()).onError(any(Throwable.class));
    -  }
    -
    -  @Test
    -  public void testDistinctOfNormalSourceWithKeySelectorAndComparatorAndTwoSubscriptions() {
    -    Observable src = Observable.from("a", "x", "ab", "abc", "cba", "de", "x", "a", "abcd");
    -    Observable.create(distinct(src, TO_UPPER_WITH_EXCEPTION, COMPARE_LENGTH)).subscribe(w);
    -
    -    InOrder inOrder = inOrder(w);
    -    inOrder.verify(w, times(1)).onNext("a");
    -    inOrder.verify(w, times(1)).onNext("x");
    -    Observable.create(distinct(src, TO_UPPER_WITH_EXCEPTION, COMPARE_LENGTH)).subscribe(w2);
    -    inOrder.verify(w, times(1)).onNext("abc");
    -    inOrder.verify(w, times(1)).onNext("abcd");
    -    inOrder.verify(w, times(1)).onCompleted();
    -    inOrder.verify(w, never()).onNext(anyString());
    -    verify(w, never()).onError(any(Throwable.class));
    -
    -    InOrder inOrder2 = inOrder(w2);
    -    inOrder2.verify(w2, times(1)).onNext("a");
    -    inOrder2.verify(w2, times(1)).onNext("x");
    -    inOrder2.verify(w2, times(1)).onNext("abc");
    -    inOrder2.verify(w2, times(1)).onNext("abcd");
    -    inOrder2.verify(w2, times(1)).onCompleted();
    -    inOrder2.verify(w2, never()).onNext(anyString());
    -    verify(w2, never()).onError(any(Throwable.class));
    -  }
    -
    -  @Test
    -  public void testDistinctOfSourceWithNulls() {
    -    Observable src = Observable.from(null, "a", "a", null, null, "b", null);
    -    Observable.create(distinct(src)).subscribe(w);
    -
    -    InOrder inOrder = inOrder(w);
    -    inOrder.verify(w, times(1)).onNext(null);
    -    inOrder.verify(w, times(1)).onNext("a");
    -    inOrder.verify(w, times(1)).onNext("b");
    -    inOrder.verify(w, times(1)).onCompleted();
    -    inOrder.verify(w, never()).onNext(anyString());
    -    verify(w, never()).onError(any(Throwable.class));
    -  }
    -
    -  @Test
    -  public void testDistinctOfSourceWithExceptionsFromKeySelector() {
    -    Observable src = Observable.from("a", "b", null, "c");
    -    Observable.create(distinct(src, TO_UPPER_WITH_EXCEPTION)).subscribe(w);
    -
    -    InOrder inOrder = inOrder(w);
    -    inOrder.verify(w, times(1)).onNext("a");
    -    inOrder.verify(w, times(1)).onNext("b");
    -    inOrder.verify(w, times(1)).onError(any(NullPointerException.class));
    -    inOrder.verify(w, never()).onNext(anyString());
    -    inOrder.verify(w, never()).onCompleted();
    -  }
     }
    diff --git a/rxjava-core/src/test/java/rx/operators/OperationDistinctUntilChangedTest.java b/rxjava-core/src/test/java/rx/operators/OperationDistinctUntilChangedTest.java
    index 2ea0167529..bd31b91ebc 100644
    --- a/rxjava-core/src/test/java/rx/operators/OperationDistinctUntilChangedTest.java
    +++ b/rxjava-core/src/test/java/rx/operators/OperationDistinctUntilChangedTest.java
    @@ -18,166 +18,166 @@
     
     public class OperationDistinctUntilChangedTest {
     
    -  @Mock
    -  Observer w;
    -  @Mock
    -  Observer w2;
    -
    -  // nulls lead to exceptions
    -  final Func1 TO_UPPER_WITH_EXCEPTION = new Func1() {
    -    @Override
    -    public String call(String s) {
    -      if (s.equals("x")) {
    -        return "xx";
    -      }
    -      return s.toUpperCase();
    +    @Mock
    +    Observer w;
    +    @Mock
    +    Observer w2;
    +
    +    // nulls lead to exceptions
    +    final Func1 TO_UPPER_WITH_EXCEPTION = new Func1() {
    +        @Override
    +        public String call(String s) {
    +            if (s.equals("x")) {
    +                return "xx";
    +            }
    +            return s.toUpperCase();
    +        }
    +    };
    +
    +    final Comparator COMPARE_LENGTH = new Comparator() {
    +        @Override
    +        public int compare(String s1, String s2) {
    +            return s1.length() - s2.length();
    +        }
    +    };
    +
    +    @Before
    +    public void before() {
    +        initMocks(this);
         }
    -  };
     
    -  final Comparator COMPARE_LENGTH = new Comparator() {
    -    @Override
    -    public int compare(String s1, String s2) {
    -      return s1.length() - s2.length();
    +    @Test
    +    public void testDistinctUntilChangedOfNone() {
    +        Observable src = Observable.empty();
    +        Observable.create(distinctUntilChanged(src)).subscribe(w);
    +
    +        verify(w, never()).onNext(anyString());
    +        verify(w, never()).onError(any(Throwable.class));
    +        verify(w, times(1)).onCompleted();
    +    }
    +
    +    @Test
    +    public void testDistinctUntilChangedOfNoneWithKeySelector() {
    +        Observable src = Observable.empty();
    +        Observable.create(distinctUntilChanged(src, TO_UPPER_WITH_EXCEPTION)).subscribe(w);
    +
    +        verify(w, never()).onNext(anyString());
    +        verify(w, never()).onError(any(Throwable.class));
    +        verify(w, times(1)).onCompleted();
    +    }
    +
    +    @Test
    +    public void testDistinctUntilChangedOfNormalSource() {
    +        Observable src = Observable.from("a", "b", "c", "c", "c", "b", "b", "a", "e");
    +        Observable.create(distinctUntilChanged(src)).subscribe(w);
    +
    +        InOrder inOrder = inOrder(w);
    +        inOrder.verify(w, times(1)).onNext("a");
    +        inOrder.verify(w, times(1)).onNext("b");
    +        inOrder.verify(w, times(1)).onNext("c");
    +        inOrder.verify(w, times(1)).onNext("b");
    +        inOrder.verify(w, times(1)).onNext("a");
    +        inOrder.verify(w, times(1)).onNext("e");
    +        inOrder.verify(w, times(1)).onCompleted();
    +        inOrder.verify(w, never()).onNext(anyString());
    +        verify(w, never()).onError(any(Throwable.class));
    +    }
    +
    +    @Test
    +    public void testDistinctUntilChangedOfNormalSourceWithKeySelector() {
    +        Observable src = Observable.from("a", "b", "c", "C", "c", "B", "b", "a", "e");
    +        Observable.create(distinctUntilChanged(src, TO_UPPER_WITH_EXCEPTION)).subscribe(w);
    +
    +        InOrder inOrder = inOrder(w);
    +        inOrder.verify(w, times(1)).onNext("a");
    +        inOrder.verify(w, times(1)).onNext("b");
    +        inOrder.verify(w, times(1)).onNext("c");
    +        inOrder.verify(w, times(1)).onNext("B");
    +        inOrder.verify(w, times(1)).onNext("a");
    +        inOrder.verify(w, times(1)).onNext("e");
    +        inOrder.verify(w, times(1)).onCompleted();
    +        inOrder.verify(w, never()).onNext(anyString());
    +        verify(w, never()).onError(any(Throwable.class));
    +    }
    +
    +    @Test
    +    public void testDistinctUntilChangedOfSourceWithNulls() {
    +        Observable src = Observable.from(null, "a", "a", null, null, "b", null, null);
    +        Observable.create(distinctUntilChanged(src)).subscribe(w);
    +
    +        InOrder inOrder = inOrder(w);
    +        inOrder.verify(w, times(1)).onNext(null);
    +        inOrder.verify(w, times(1)).onNext("a");
    +        inOrder.verify(w, times(1)).onNext(null);
    +        inOrder.verify(w, times(1)).onNext("b");
    +        inOrder.verify(w, times(1)).onNext(null);
    +        inOrder.verify(w, times(1)).onCompleted();
    +        inOrder.verify(w, never()).onNext(anyString());
    +        verify(w, never()).onError(any(Throwable.class));
    +    }
    +
    +    @Test
    +    public void testDistinctUntilChangedOfSourceWithExceptionsFromKeySelector() {
    +        Observable src = Observable.from("a", "b", null, "c");
    +        Observable.create(distinctUntilChanged(src, TO_UPPER_WITH_EXCEPTION)).subscribe(w);
    +
    +        InOrder inOrder = inOrder(w);
    +        inOrder.verify(w, times(1)).onNext("a");
    +        inOrder.verify(w, times(1)).onNext("b");
    +        verify(w, times(1)).onError(any(NullPointerException.class));
    +        inOrder.verify(w, never()).onNext(anyString());
    +        inOrder.verify(w, never()).onCompleted();
    +    }
    +
    +    @Test
    +    public void testDistinctUntilChangedWithComparator() {
    +        Observable src = Observable.from("a", "b", "c", "aa", "bb", "c", "ddd");
    +        Observable.create(distinctUntilChanged(src, COMPARE_LENGTH)).subscribe(w);
    +        InOrder inOrder = inOrder(w);
    +        inOrder.verify(w, times(1)).onNext("a");
    +        inOrder.verify(w, times(1)).onNext("aa");
    +        inOrder.verify(w, times(1)).onNext("c");
    +        inOrder.verify(w, times(1)).onNext("ddd");
    +        inOrder.verify(w, times(1)).onCompleted();
    +        inOrder.verify(w, never()).onNext(anyString());
    +        verify(w, never()).onError(any(Throwable.class));
    +    }
    +
    +    @Test
    +    public void testDistinctUntilChangedWithComparatorAndKeySelector() {
    +        Observable src = Observable.from("a", "b", "x", "aa", "bb", "c", "ddd");
    +        Observable.create(distinctUntilChanged(src, TO_UPPER_WITH_EXCEPTION, COMPARE_LENGTH)).subscribe(w);
    +        InOrder inOrder = inOrder(w);
    +        inOrder.verify(w, times(1)).onNext("a");
    +        inOrder.verify(w, times(1)).onNext("x");
    +        inOrder.verify(w, times(1)).onNext("c");
    +        inOrder.verify(w, times(1)).onNext("ddd");
    +        inOrder.verify(w, times(1)).onCompleted();
    +        inOrder.verify(w, never()).onNext(anyString());
    +        verify(w, never()).onError(any(Throwable.class));
    +    }
    +
    +    @Test
    +    public void testDistinctUntilChangedWithComparatorAndKeySelectorandTwoSubscriptions() {
    +        Observable src = Observable.from("a", "b", "x", "aa", "bb", "c", "ddd");
    +        Observable.create(distinctUntilChanged(src, TO_UPPER_WITH_EXCEPTION, COMPARE_LENGTH)).subscribe(w);
    +        InOrder inOrder = inOrder(w);
    +        inOrder.verify(w, times(1)).onNext("a");
    +        inOrder.verify(w, times(1)).onNext("x");
    +        Observable.create(distinctUntilChanged(src, TO_UPPER_WITH_EXCEPTION, COMPARE_LENGTH)).subscribe(w2);
    +        inOrder.verify(w, times(1)).onNext("c");
    +        inOrder.verify(w, times(1)).onNext("ddd");
    +        inOrder.verify(w, times(1)).onCompleted();
    +        inOrder.verify(w, never()).onNext(anyString());
    +        verify(w, never()).onError(any(Throwable.class));
    +
    +        InOrder inOrder2 = inOrder(w2);
    +        inOrder2.verify(w2, times(1)).onNext("a");
    +        inOrder2.verify(w2, times(1)).onNext("x");
    +        inOrder2.verify(w2, times(1)).onNext("c");
    +        inOrder2.verify(w2, times(1)).onNext("ddd");
    +        inOrder2.verify(w2, times(1)).onCompleted();
    +        inOrder2.verify(w2, never()).onNext(anyString());
    +        verify(w2, never()).onError(any(Throwable.class));
         }
    -  };
    -
    -  @Before
    -  public void before() {
    -    initMocks(this);
    -  }
    -
    -  @Test
    -  public void testDistinctUntilChangedOfNone() {
    -    Observable src = Observable.empty();
    -    Observable.create(distinctUntilChanged(src)).subscribe(w);
    -
    -    verify(w, never()).onNext(anyString());
    -    verify(w, never()).onError(any(Throwable.class));
    -    verify(w, times(1)).onCompleted();
    -  }
    -
    -  @Test
    -  public void testDistinctUntilChangedOfNoneWithKeySelector() {
    -    Observable src = Observable.empty();
    -    Observable.create(distinctUntilChanged(src, TO_UPPER_WITH_EXCEPTION)).subscribe(w);
    -
    -    verify(w, never()).onNext(anyString());
    -    verify(w, never()).onError(any(Throwable.class));
    -    verify(w, times(1)).onCompleted();
    -  }
    -
    -  @Test
    -  public void testDistinctUntilChangedOfNormalSource() {
    -    Observable src = Observable.from("a", "b", "c", "c", "c", "b", "b", "a", "e");
    -    Observable.create(distinctUntilChanged(src)).subscribe(w);
    -
    -    InOrder inOrder = inOrder(w);
    -    inOrder.verify(w, times(1)).onNext("a");
    -    inOrder.verify(w, times(1)).onNext("b");
    -    inOrder.verify(w, times(1)).onNext("c");
    -    inOrder.verify(w, times(1)).onNext("b");
    -    inOrder.verify(w, times(1)).onNext("a");
    -    inOrder.verify(w, times(1)).onNext("e");
    -    inOrder.verify(w, times(1)).onCompleted();
    -    inOrder.verify(w, never()).onNext(anyString());
    -    verify(w, never()).onError(any(Throwable.class));
    -  }
    -
    -  @Test
    -  public void testDistinctUntilChangedOfNormalSourceWithKeySelector() {
    -    Observable src = Observable.from("a", "b", "c", "C", "c", "B", "b", "a", "e");
    -    Observable.create(distinctUntilChanged(src, TO_UPPER_WITH_EXCEPTION)).subscribe(w);
    -
    -    InOrder inOrder = inOrder(w);
    -    inOrder.verify(w, times(1)).onNext("a");
    -    inOrder.verify(w, times(1)).onNext("b");
    -    inOrder.verify(w, times(1)).onNext("c");
    -    inOrder.verify(w, times(1)).onNext("B");
    -    inOrder.verify(w, times(1)).onNext("a");
    -    inOrder.verify(w, times(1)).onNext("e");
    -    inOrder.verify(w, times(1)).onCompleted();
    -    inOrder.verify(w, never()).onNext(anyString());
    -    verify(w, never()).onError(any(Throwable.class));
    -  }
    -
    -  @Test
    -  public void testDistinctUntilChangedOfSourceWithNulls() {
    -    Observable src = Observable.from(null, "a", "a", null, null, "b", null, null);
    -    Observable.create(distinctUntilChanged(src)).subscribe(w);
    -
    -    InOrder inOrder = inOrder(w);
    -    inOrder.verify(w, times(1)).onNext(null);
    -    inOrder.verify(w, times(1)).onNext("a");
    -    inOrder.verify(w, times(1)).onNext(null);
    -    inOrder.verify(w, times(1)).onNext("b");
    -    inOrder.verify(w, times(1)).onNext(null);
    -    inOrder.verify(w, times(1)).onCompleted();
    -    inOrder.verify(w, never()).onNext(anyString());
    -    verify(w, never()).onError(any(Throwable.class));
    -  }
    -
    -  @Test
    -  public void testDistinctUntilChangedOfSourceWithExceptionsFromKeySelector() {
    -    Observable src = Observable.from("a", "b", null, "c");
    -    Observable.create(distinctUntilChanged(src, TO_UPPER_WITH_EXCEPTION)).subscribe(w);
    -
    -    InOrder inOrder = inOrder(w);
    -    inOrder.verify(w, times(1)).onNext("a");
    -    inOrder.verify(w, times(1)).onNext("b");
    -    verify(w, times(1)).onError(any(NullPointerException.class));
    -    inOrder.verify(w, never()).onNext(anyString());
    -    inOrder.verify(w, never()).onCompleted();
    -  }
    -
    -  @Test
    -  public void testDistinctUntilChangedWithComparator() {
    -    Observable src = Observable.from("a", "b", "c", "aa", "bb", "c", "ddd");
    -    Observable.create(distinctUntilChanged(src, COMPARE_LENGTH)).subscribe(w);
    -    InOrder inOrder = inOrder(w);
    -    inOrder.verify(w, times(1)).onNext("a");
    -    inOrder.verify(w, times(1)).onNext("aa");
    -    inOrder.verify(w, times(1)).onNext("c");
    -    inOrder.verify(w, times(1)).onNext("ddd");
    -    inOrder.verify(w, times(1)).onCompleted();
    -    inOrder.verify(w, never()).onNext(anyString());
    -    verify(w, never()).onError(any(Throwable.class));
    -  }
    -
    -  @Test
    -  public void testDistinctUntilChangedWithComparatorAndKeySelector() {
    -    Observable src = Observable.from("a", "b", "x", "aa", "bb", "c", "ddd");
    -    Observable.create(distinctUntilChanged(src, TO_UPPER_WITH_EXCEPTION, COMPARE_LENGTH)).subscribe(w);
    -    InOrder inOrder = inOrder(w);
    -    inOrder.verify(w, times(1)).onNext("a");
    -    inOrder.verify(w, times(1)).onNext("x");
    -    inOrder.verify(w, times(1)).onNext("c");
    -    inOrder.verify(w, times(1)).onNext("ddd");
    -    inOrder.verify(w, times(1)).onCompleted();
    -    inOrder.verify(w, never()).onNext(anyString());
    -    verify(w, never()).onError(any(Throwable.class));
    -  }
    -
    -  @Test
    -  public void testDistinctUntilChangedWithComparatorAndKeySelectorandTwoSubscriptions() {
    -    Observable src = Observable.from("a", "b", "x", "aa", "bb", "c", "ddd");
    -    Observable.create(distinctUntilChanged(src, TO_UPPER_WITH_EXCEPTION, COMPARE_LENGTH)).subscribe(w);
    -    InOrder inOrder = inOrder(w);
    -    inOrder.verify(w, times(1)).onNext("a");
    -    inOrder.verify(w, times(1)).onNext("x");
    -    Observable.create(distinctUntilChanged(src, TO_UPPER_WITH_EXCEPTION, COMPARE_LENGTH)).subscribe(w2);
    -    inOrder.verify(w, times(1)).onNext("c");
    -    inOrder.verify(w, times(1)).onNext("ddd");
    -    inOrder.verify(w, times(1)).onCompleted();
    -    inOrder.verify(w, never()).onNext(anyString());
    -    verify(w, never()).onError(any(Throwable.class));
    -
    -    InOrder inOrder2 = inOrder(w2);
    -    inOrder2.verify(w2, times(1)).onNext("a");
    -    inOrder2.verify(w2, times(1)).onNext("x");
    -    inOrder2.verify(w2, times(1)).onNext("c");
    -    inOrder2.verify(w2, times(1)).onNext("ddd");
    -    inOrder2.verify(w2, times(1)).onCompleted();
    -    inOrder2.verify(w2, never()).onNext(anyString());
    -    verify(w2, never()).onError(any(Throwable.class));
    -  }
     }
    diff --git a/rxjava-core/src/test/java/rx/operators/OperationElementAtTest.java b/rxjava-core/src/test/java/rx/operators/OperationElementAtTest.java
    index 4f1326df06..8642e78300 100644
    --- a/rxjava-core/src/test/java/rx/operators/OperationElementAtTest.java
    +++ b/rxjava-core/src/test/java/rx/operators/OperationElementAtTest.java
    @@ -1,113 +1,112 @@
     package rx.operators;
     
    -import org.junit.Test;
    -import rx.Observable;
    -import rx.Observer;
    +import static org.junit.Assert.*;
    +import static org.mockito.Matchers.*;
    +import static org.mockito.Mockito.*;
    +import static rx.operators.OperationElementAt.*;
     
     import java.util.Iterator;
     import java.util.concurrent.ExecutionException;
     
    -import static org.junit.Assert.assertTrue;
    -import static org.junit.Assert.fail;
    -import static org.mockito.Matchers.any;
    -import static org.mockito.Mockito.*;
    -import static rx.operators.OperationElementAt.elementAt;
    -import static rx.operators.OperationElementAt.elementAtOrDefault;
    +import org.junit.Test;
    +
    +import rx.Observable;
    +import rx.Observer;
     
     public class OperationElementAtTest {
     
    -  @Test
    -  public void testElementAt() {
    -    Observable w = Observable.from(1, 2);
    -    Observable observable = Observable.create(elementAt(w, 1));
    -
    -    @SuppressWarnings("unchecked")
    -    Observer aObserver = mock(Observer.class);
    -    observable.subscribe(aObserver);
    -    verify(aObserver, never()).onNext(1);
    -    verify(aObserver, times(1)).onNext(2);
    -    verify(aObserver, never()).onError(
    -        any(Throwable.class));
    -    verify(aObserver, times(1)).onCompleted();
    -  }
    -
    -  @Test
    -  public void testElementAtWithMinusIndex() {
    -    Observable w = Observable.from(1, 2);
    -    Observable observable = Observable
    -        .create(elementAt(w, -1));
    -
    -    try {
    -      Iterator iter = OperationToIterator
    -          .toIterator(observable);
    -      assertTrue(iter.hasNext());
    -      iter.next();
    -      fail("expect an IndexOutOfBoundsException when index is out of bounds");
    -    } catch (IndexOutOfBoundsException e) {
    +    @Test
    +    public void testElementAt() {
    +        Observable w = Observable.from(1, 2);
    +        Observable observable = Observable.create(elementAt(w, 1));
    +
    +        @SuppressWarnings("unchecked")
    +        Observer aObserver = mock(Observer.class);
    +        observable.subscribe(aObserver);
    +        verify(aObserver, never()).onNext(1);
    +        verify(aObserver, times(1)).onNext(2);
    +        verify(aObserver, never()).onError(
    +                any(Throwable.class));
    +        verify(aObserver, times(1)).onCompleted();
    +    }
    +
    +    @Test
    +    public void testElementAtWithMinusIndex() {
    +        Observable w = Observable.from(1, 2);
    +        Observable observable = Observable
    +                .create(elementAt(w, -1));
    +
    +        try {
    +            Iterator iter = OperationToIterator
    +                    .toIterator(observable);
    +            assertTrue(iter.hasNext());
    +            iter.next();
    +            fail("expect an IndexOutOfBoundsException when index is out of bounds");
    +        } catch (IndexOutOfBoundsException e) {
    +        }
    +    }
    +
    +    @Test
    +    public void testElementAtWithIndexOutOfBounds()
    +            throws InterruptedException, ExecutionException {
    +        Observable w = Observable.from(1, 2);
    +        Observable observable = Observable.create(elementAt(w, 2));
    +        try {
    +            Iterator iter = OperationToIterator
    +                    .toIterator(observable);
    +            assertTrue(iter.hasNext());
    +            iter.next();
    +            fail("expect an IndexOutOfBoundsException when index is out of bounds");
    +        } catch (IndexOutOfBoundsException e) {
    +        }
         }
    -  }
    -
    -  @Test
    -  public void testElementAtWithIndexOutOfBounds()
    -      throws InterruptedException, ExecutionException {
    -    Observable w = Observable.from(1, 2);
    -    Observable observable = Observable.create(elementAt(w, 2));
    -    try {
    -      Iterator iter = OperationToIterator
    -          .toIterator(observable);
    -      assertTrue(iter.hasNext());
    -      iter.next();
    -      fail("expect an IndexOutOfBoundsException when index is out of bounds");
    -    } catch (IndexOutOfBoundsException e) {
    +
    +    @Test
    +    public void testElementAtOrDefault() throws InterruptedException,
    +            ExecutionException {
    +        Observable w = Observable.from(1, 2);
    +        Observable observable = Observable
    +                .create(elementAtOrDefault(w, 1, 0));
    +
    +        @SuppressWarnings("unchecked")
    +        Observer aObserver = mock(Observer.class);
    +        observable.subscribe(aObserver);
    +        verify(aObserver, never()).onNext(1);
    +        verify(aObserver, times(1)).onNext(2);
    +        verify(aObserver, never()).onError(any(Throwable.class));
    +        verify(aObserver, times(1)).onCompleted();
         }
    -  }
    -
    -  @Test
    -  public void testElementAtOrDefault() throws InterruptedException,
    -      ExecutionException {
    -    Observable w = Observable.from(1, 2);
    -    Observable observable = Observable
    -        .create(elementAtOrDefault(w, 1, 0));
    -
    -    @SuppressWarnings("unchecked")
    -    Observer aObserver = mock(Observer.class);
    -    observable.subscribe(aObserver);
    -    verify(aObserver, never()).onNext(1);
    -    verify(aObserver, times(1)).onNext(2);
    -    verify(aObserver, never()).onError(any(Throwable.class));
    -    verify(aObserver, times(1)).onCompleted();
    -  }
    -
    -  @Test
    -  public void testElementAtOrDefaultWithIndexOutOfBounds()
    -      throws InterruptedException, ExecutionException {
    -    Observable w = Observable.from(1, 2);
    -    Observable observable = Observable
    -        .create(elementAtOrDefault(w, 2, 0));
    -
    -    @SuppressWarnings("unchecked")
    -    Observer aObserver = mock(Observer.class);
    -    observable.subscribe(aObserver);
    -    verify(aObserver, never()).onNext(1);
    -    verify(aObserver, never()).onNext(2);
    -    verify(aObserver, times(1)).onNext(0);
    -    verify(aObserver, never()).onError(any(Throwable.class));
    -    verify(aObserver, times(1)).onCompleted();
    -  }
    -
    -  @Test
    -  public void testElementAtOrDefaultWithMinusIndex() {
    -    Observable w = Observable.from(1, 2);
    -    Observable observable = Observable
    -        .create(elementAtOrDefault(w, -1, 0));
    -
    -    try {
    -      Iterator iter = OperationToIterator
    -          .toIterator(observable);
    -      assertTrue(iter.hasNext());
    -      iter.next();
    -      fail("expect an IndexOutOfBoundsException when index is out of bounds");
    -    } catch (IndexOutOfBoundsException e) {
    +
    +    @Test
    +    public void testElementAtOrDefaultWithIndexOutOfBounds()
    +            throws InterruptedException, ExecutionException {
    +        Observable w = Observable.from(1, 2);
    +        Observable observable = Observable
    +                .create(elementAtOrDefault(w, 2, 0));
    +
    +        @SuppressWarnings("unchecked")
    +        Observer aObserver = mock(Observer.class);
    +        observable.subscribe(aObserver);
    +        verify(aObserver, never()).onNext(1);
    +        verify(aObserver, never()).onNext(2);
    +        verify(aObserver, times(1)).onNext(0);
    +        verify(aObserver, never()).onError(any(Throwable.class));
    +        verify(aObserver, times(1)).onCompleted();
    +    }
    +
    +    @Test
    +    public void testElementAtOrDefaultWithMinusIndex() {
    +        Observable w = Observable.from(1, 2);
    +        Observable observable = Observable
    +                .create(elementAtOrDefault(w, -1, 0));
    +
    +        try {
    +            Iterator iter = OperationToIterator
    +                    .toIterator(observable);
    +            assertTrue(iter.hasNext());
    +            iter.next();
    +            fail("expect an IndexOutOfBoundsException when index is out of bounds");
    +        } catch (IndexOutOfBoundsException e) {
    +        }
         }
    -  }
     }
    diff --git a/rxjava-core/src/test/java/rx/operators/OperationFilterTest.java b/rxjava-core/src/test/java/rx/operators/OperationFilterTest.java
    index a6da7261e1..88fb4deacb 100644
    --- a/rxjava-core/src/test/java/rx/operators/OperationFilterTest.java
    +++ b/rxjava-core/src/test/java/rx/operators/OperationFilterTest.java
    @@ -1,35 +1,36 @@
     package rx.operators;
     
    +import static org.mockito.Matchers.*;
    +import static org.mockito.Mockito.*;
    +import static rx.operators.OperationFilter.*;
    +
     import org.junit.Test;
     import org.mockito.Mockito;
    +
     import rx.Observable;
     import rx.Observer;
     import rx.util.functions.Func1;
     
    -import static org.mockito.Matchers.any;
    -import static org.mockito.Mockito.*;
    -import static rx.operators.OperationFilter.filter;
    -
     public class OperationFilterTest {
     
    -  @Test
    -  public void testFilter() {
    -    Observable w = Observable.from("one", "two", "three");
    -    Observable observable = Observable.create(filter(w, new Func1() {
    +    @Test
    +    public void testFilter() {
    +        Observable w = Observable.from("one", "two", "three");
    +        Observable observable = Observable.create(filter(w, new Func1() {
     
    -      @Override
    -      public Boolean call(String t1) {
    -        return t1.equals("two");
    -      }
    -    }));
    +            @Override
    +            public Boolean call(String t1) {
    +                return t1.equals("two");
    +            }
    +        }));
     
    -    @SuppressWarnings("unchecked")
    -    Observer aObserver = mock(Observer.class);
    -    observable.subscribe(aObserver);
    -    verify(aObserver, Mockito.never()).onNext("one");
    -    verify(aObserver, times(1)).onNext("two");
    -    verify(aObserver, Mockito.never()).onNext("three");
    -    verify(aObserver, Mockito.never()).onError(any(Throwable.class));
    -    verify(aObserver, times(1)).onCompleted();
    -  }
    +        @SuppressWarnings("unchecked")
    +        Observer aObserver = mock(Observer.class);
    +        observable.subscribe(aObserver);
    +        verify(aObserver, Mockito.never()).onNext("one");
    +        verify(aObserver, times(1)).onNext("two");
    +        verify(aObserver, Mockito.never()).onNext("three");
    +        verify(aObserver, Mockito.never()).onError(any(Throwable.class));
    +        verify(aObserver, times(1)).onCompleted();
    +    }
     }
    diff --git a/rxjava-core/src/test/java/rx/operators/OperationFinallyTest.java b/rxjava-core/src/test/java/rx/operators/OperationFinallyTest.java
    index b856c86fa6..c0fd0d9ef2 100644
    --- a/rxjava-core/src/test/java/rx/operators/OperationFinallyTest.java
    +++ b/rxjava-core/src/test/java/rx/operators/OperationFinallyTest.java
    @@ -1,38 +1,40 @@
     package rx.operators;
     
    +import static org.mockito.Mockito.*;
    +import static rx.operators.OperationFinally.*;
    +
     import org.junit.Before;
     import org.junit.Test;
    +
     import rx.Observable;
     import rx.Observer;
     import rx.util.functions.Action0;
     
    -import static org.mockito.Mockito.*;
    -import static rx.operators.OperationFinally.finallyDo;
    -
     public class OperationFinallyTest {
     
    -  private Action0 aAction0;
    -  private Observer aObserver;
    -
    -  @SuppressWarnings("unchecked") // mocking has to be unchecked, unfortunately
    -  @Before
    -  public void before() {
    -    aAction0 = mock(Action0.class);
    -    aObserver = mock(Observer.class);
    -  }
    -
    -  private void checkActionCalled(Observable input) {
    -    Observable.create(finallyDo(input, aAction0)).subscribe(aObserver);
    -    verify(aAction0, times(1)).call();
    -  }
    -
    -  @Test
    -  public void testFinallyCalledOnComplete() {
    -    checkActionCalled(Observable.from(new String[]{"1", "2", "3"}));
    -  }
    -
    -  @Test
    -  public void testFinallyCalledOnError() {
    -    checkActionCalled(Observable.error(new RuntimeException("expected")));
    -  }
    +    private Action0 aAction0;
    +    private Observer aObserver;
    +
    +    @SuppressWarnings("unchecked")
    +    // mocking has to be unchecked, unfortunately
    +    @Before
    +    public void before() {
    +        aAction0 = mock(Action0.class);
    +        aObserver = mock(Observer.class);
    +    }
    +
    +    private void checkActionCalled(Observable input) {
    +        Observable.create(finallyDo(input, aAction0)).subscribe(aObserver);
    +        verify(aAction0, times(1)).call();
    +    }
    +
    +    @Test
    +    public void testFinallyCalledOnComplete() {
    +        checkActionCalled(Observable.from(new String[] { "1", "2", "3" }));
    +    }
    +
    +    @Test
    +    public void testFinallyCalledOnError() {
    +        checkActionCalled(Observable. error(new RuntimeException("expected")));
    +    }
     }
    diff --git a/rxjava-core/src/test/java/rx/operators/OperationFirstOrDefaultTest.java b/rxjava-core/src/test/java/rx/operators/OperationFirstOrDefaultTest.java
    index f645fd785e..b17ba4740e 100644
    --- a/rxjava-core/src/test/java/rx/operators/OperationFirstOrDefaultTest.java
    +++ b/rxjava-core/src/test/java/rx/operators/OperationFirstOrDefaultTest.java
    @@ -15,62 +15,62 @@
     
     public class OperationFirstOrDefaultTest {
     
    -  @Mock
    -  Observer w;
    +    @Mock
    +    Observer w;
     
    -  private static final Func1 IS_D = new Func1() {
    -    @Override
    -    public Boolean call(String value) {
    -      return "d".equals(value);
    -    }
    -  };
    +    private static final Func1 IS_D = new Func1() {
    +        @Override
    +        public Boolean call(String value) {
    +            return "d".equals(value);
    +        }
    +    };
     
    -  @Before
    -  public void before() {
    -    initMocks(this);
    -  }
    +    @Before
    +    public void before() {
    +        initMocks(this);
    +    }
     
    -  @Test
    -  public void testFirstOrElseOfNone() {
    -    Observable src = Observable.empty();
    -    Observable.create(firstOrDefault(src, "default")).subscribe(w);
    +    @Test
    +    public void testFirstOrElseOfNone() {
    +        Observable src = Observable.empty();
    +        Observable.create(firstOrDefault(src, "default")).subscribe(w);
     
    -    verify(w, times(1)).onNext(anyString());
    -    verify(w, times(1)).onNext("default");
    -    verify(w, never()).onError(any(Throwable.class));
    -    verify(w, times(1)).onCompleted();
    -  }
    +        verify(w, times(1)).onNext(anyString());
    +        verify(w, times(1)).onNext("default");
    +        verify(w, never()).onError(any(Throwable.class));
    +        verify(w, times(1)).onCompleted();
    +    }
     
    -  @Test
    -  public void testFirstOrElseOfSome() {
    -    Observable src = Observable.from("a", "b", "c");
    -    Observable.create(firstOrDefault(src, "default")).subscribe(w);
    +    @Test
    +    public void testFirstOrElseOfSome() {
    +        Observable src = Observable.from("a", "b", "c");
    +        Observable.create(firstOrDefault(src, "default")).subscribe(w);
     
    -    verify(w, times(1)).onNext(anyString());
    -    verify(w, times(1)).onNext("a");
    -    verify(w, never()).onError(any(Throwable.class));
    -    verify(w, times(1)).onCompleted();
    -  }
    +        verify(w, times(1)).onNext(anyString());
    +        verify(w, times(1)).onNext("a");
    +        verify(w, never()).onError(any(Throwable.class));
    +        verify(w, times(1)).onCompleted();
    +    }
     
    -  @Test
    -  public void testFirstOrElseWithPredicateOfNoneMatchingThePredicate() {
    -    Observable src = Observable.from("a", "b", "c");
    -    Observable.create(firstOrDefault(src, IS_D, "default")).subscribe(w);
    +    @Test
    +    public void testFirstOrElseWithPredicateOfNoneMatchingThePredicate() {
    +        Observable src = Observable.from("a", "b", "c");
    +        Observable.create(firstOrDefault(src, IS_D, "default")).subscribe(w);
     
    -    verify(w, times(1)).onNext(anyString());
    -    verify(w, times(1)).onNext("default");
    -    verify(w, never()).onError(any(Throwable.class));
    -    verify(w, times(1)).onCompleted();
    -  }
    +        verify(w, times(1)).onNext(anyString());
    +        verify(w, times(1)).onNext("default");
    +        verify(w, never()).onError(any(Throwable.class));
    +        verify(w, times(1)).onCompleted();
    +    }
     
    -  @Test
    -  public void testFirstOrElseWithPredicateOfSome() {
    -    Observable src = Observable.from("a", "b", "c", "d", "e", "f");
    -    Observable.create(firstOrDefault(src, IS_D, "default")).subscribe(w);
    +    @Test
    +    public void testFirstOrElseWithPredicateOfSome() {
    +        Observable src = Observable.from("a", "b", "c", "d", "e", "f");
    +        Observable.create(firstOrDefault(src, IS_D, "default")).subscribe(w);
     
    -    verify(w, times(1)).onNext(anyString());
    -    verify(w, times(1)).onNext("d");
    -    verify(w, never()).onError(any(Throwable.class));
    -    verify(w, times(1)).onCompleted();
    -  }
    +        verify(w, times(1)).onNext(anyString());
    +        verify(w, times(1)).onNext("d");
    +        verify(w, never()).onError(any(Throwable.class));
    +        verify(w, times(1)).onCompleted();
    +    }
     }
    diff --git a/rxjava-core/src/test/java/rx/operators/OperationGroupByTest.java b/rxjava-core/src/test/java/rx/operators/OperationGroupByTest.java
    index e62be97d11..86d5af6e46 100644
    --- a/rxjava-core/src/test/java/rx/operators/OperationGroupByTest.java
    +++ b/rxjava-core/src/test/java/rx/operators/OperationGroupByTest.java
    @@ -1,14 +1,7 @@
     package rx.operators;
     
    -import org.junit.Test;
    -import rx.Observable;
    -import rx.Observer;
    -import rx.Subscription;
    -import rx.observables.GroupedObservable;
    -import rx.subscriptions.BooleanSubscription;
    -import rx.subscriptions.Subscriptions;
    -import rx.util.functions.Action1;
    -import rx.util.functions.Func1;
    +import static org.junit.Assert.*;
    +import static rx.operators.OperationGroupBy.*;
     
     import java.util.Arrays;
     import java.util.Collection;
    @@ -20,312 +13,320 @@
     import java.util.concurrent.atomic.AtomicInteger;
     import java.util.concurrent.atomic.AtomicReference;
     
    -import static org.junit.Assert.*;
    -import static rx.operators.OperationGroupBy.groupBy;
    +import org.junit.Test;
    +
    +import rx.Observable;
    +import rx.Observer;
    +import rx.Subscription;
    +import rx.observables.GroupedObservable;
    +import rx.subscriptions.BooleanSubscription;
    +import rx.subscriptions.Subscriptions;
    +import rx.util.functions.Action1;
    +import rx.util.functions.Func1;
     
     public class OperationGroupByTest {
     
    -  final Func1 length = new Func1() {
    -    @Override
    -    public Integer call(String s) {
    -      return s.length();
    +    final Func1 length = new Func1() {
    +        @Override
    +        public Integer call(String s) {
    +            return s.length();
    +        }
    +    };
    +
    +    @Test
    +    public void testGroupBy() {
    +        Observable source = Observable.from("one", "two", "three", "four", "five", "six");
    +        Observable> grouped = Observable.create(groupBy(source, length));
    +
    +        Map> map = toMap(grouped);
    +
    +        assertEquals(3, map.size());
    +        assertArrayEquals(Arrays.asList("one", "two", "six").toArray(), map.get(3).toArray());
    +        assertArrayEquals(Arrays.asList("four", "five").toArray(), map.get(4).toArray());
    +        assertArrayEquals(Arrays.asList("three").toArray(), map.get(5).toArray());
         }
    -  };
     
    -  @Test
    -  public void testGroupBy() {
    -    Observable source = Observable.from("one", "two", "three", "four", "five", "six");
    -    Observable> grouped = Observable.create(groupBy(source, length));
    +    @Test
    +    public void testEmpty() {
    +        Observable source = Observable.empty();
    +        Observable> grouped = Observable.create(groupBy(source, length));
     
    -    Map> map = toMap(grouped);
    +        Map> map = toMap(grouped);
    +
    +        assertTrue(map.isEmpty());
    +    }
     
    -    assertEquals(3, map.size());
    -    assertArrayEquals(Arrays.asList("one", "two", "six").toArray(), map.get(3).toArray());
    -    assertArrayEquals(Arrays.asList("four", "five").toArray(), map.get(4).toArray());
    -    assertArrayEquals(Arrays.asList("three").toArray(), map.get(5).toArray());
    -  }
    +    @Test
    +    public void testError() {
    +        Observable sourceStrings = Observable.from("one", "two", "three", "four", "five", "six");
    +        Observable errorSource = Observable.error(new RuntimeException("forced failure"));
    +        Observable source = Observable.concat(sourceStrings, errorSource);
     
    -  @Test
    -  public void testEmpty() {
    -    Observable source = Observable.empty();
    -    Observable> grouped = Observable.create(groupBy(source, length));
    +        Observable> grouped = Observable.create(groupBy(source, length));
     
    -    Map> map = toMap(grouped);
    +        final AtomicInteger groupCounter = new AtomicInteger();
    +        final AtomicInteger eventCounter = new AtomicInteger();
    +        final AtomicReference error = new AtomicReference();
     
    -    assertTrue(map.isEmpty());
    -  }
    +        grouped.mapMany(new Func1, Observable>() {
     
    -  @Test
    -  public void testError() {
    -    Observable sourceStrings = Observable.from("one", "two", "three", "four", "five", "six");
    -    Observable errorSource = Observable.error(new RuntimeException("forced failure"));
    -    Observable source = Observable.concat(sourceStrings, errorSource);
    +            @Override
    +            public Observable call(final GroupedObservable o) {
    +                groupCounter.incrementAndGet();
    +                return o.map(new Func1() {
    +
    +                    @Override
    +                    public String call(String v) {
    +                        return "Event => key: " + o.getKey() + " value: " + v;
    +                    }
    +                });
    +            }
    +        }).subscribe(new Observer() {
     
    -    Observable> grouped = Observable.create(groupBy(source, length));
    +            @Override
    +            public void onCompleted() {
     
    -    final AtomicInteger groupCounter = new AtomicInteger();
    -    final AtomicInteger eventCounter = new AtomicInteger();
    -    final AtomicReference error = new AtomicReference();
    +            }
     
    -    grouped.mapMany(new Func1, Observable>() {
    +            @Override
    +            public void onError(Throwable e) {
    +                e.printStackTrace();
    +                error.set(e);
    +            }
     
    -      @Override
    -      public Observable call(final GroupedObservable o) {
    -        groupCounter.incrementAndGet();
    -        return o.map(new Func1() {
    +            @Override
    +            public void onNext(String v) {
    +                eventCounter.incrementAndGet();
    +                System.out.println(v);
     
    -          @Override
    -          public String call(String v) {
    -            return "Event => key: " + o.getKey() + " value: " + v;
    -          }
    +            }
             });
    -      }
    -    }).subscribe(new Observer() {
     
    -      @Override
    -      public void onCompleted() {
    +        assertEquals(3, groupCounter.get());
    +        assertEquals(6, eventCounter.get());
    +        assertNotNull(error.get());
    +    }
     
    -      }
    +    private static  Map> toMap(Observable> observable) {
     
    -      @Override
    -      public void onError(Throwable e) {
    -        e.printStackTrace();
    -        error.set(e);
    -      }
    +        final ConcurrentHashMap> result = new ConcurrentHashMap>();
     
    -      @Override
    -      public void onNext(String v) {
    -        eventCounter.incrementAndGet();
    -        System.out.println(v);
    +        observable.toBlockingObservable().forEach(new Action1>() {
     
    -      }
    -    });
    +            @Override
    +            public void call(final GroupedObservable o) {
    +                result.put(o.getKey(), new ConcurrentLinkedQueue());
    +                o.subscribe(new Action1() {
     
    -    assertEquals(3, groupCounter.get());
    -    assertEquals(6, eventCounter.get());
    -    assertNotNull(error.get());
    -  }
    +                    @Override
    +                    public void call(V v) {
    +                        result.get(o.getKey()).add(v);
    +                    }
     
    -  private static  Map> toMap(Observable> observable) {
    +                });
    +            }
    +        });
     
    -    final ConcurrentHashMap> result = new ConcurrentHashMap>();
    +        return result;
    +    }
     
    -    observable.toBlockingObservable().forEach(new Action1>() {
    +    /**
    +     * Assert that only a single subscription to a stream occurs and that all events are received.
    +     * 
    +     * @throws Throwable
    +     */
    +    @Test
    +    public void testGroupedEventStream() throws Throwable {
    +
    +        final AtomicInteger eventCounter = new AtomicInteger();
    +        final AtomicInteger subscribeCounter = new AtomicInteger();
    +        final AtomicInteger groupCounter = new AtomicInteger();
    +        final CountDownLatch latch = new CountDownLatch(1);
    +        final int count = 100;
    +        final int groupCount = 2;
    +
    +        Observable es = Observable.create(new Observable.OnSubscribeFunc() {
    +
    +            @Override
    +            public Subscription onSubscribe(final Observer observer) {
    +                System.out.println("*** Subscribing to EventStream ***");
    +                subscribeCounter.incrementAndGet();
    +                new Thread(new Runnable() {
    +
    +                    @Override
    +                    public void run() {
    +                        for (int i = 0; i < count; i++) {
    +                            Event e = new Event();
    +                            e.source = i % groupCount;
    +                            e.message = "Event-" + i;
    +                            observer.onNext(e);
    +                        }
    +                        observer.onCompleted();
    +                    }
    +
    +                }).start();
    +                return Subscriptions.empty();
    +            }
     
    -      @Override
    -      public void call(final GroupedObservable o) {
    -        result.put(o.getKey(), new ConcurrentLinkedQueue());
    -        o.subscribe(new Action1() {
    +        });
     
    -          @Override
    -          public void call(V v) {
    -            result.get(o.getKey()).add(v);
    -          }
    +        es.groupBy(new Func1() {
     
    -        });
    -      }
    -    });
    -
    -    return result;
    -  }
    -
    -  /**
    -   * Assert that only a single subscription to a stream occurs and that all events are received.
    -   *
    -   * @throws Throwable
    -   */
    -  @Test
    -  public void testGroupedEventStream() throws Throwable {
    -
    -    final AtomicInteger eventCounter = new AtomicInteger();
    -    final AtomicInteger subscribeCounter = new AtomicInteger();
    -    final AtomicInteger groupCounter = new AtomicInteger();
    -    final CountDownLatch latch = new CountDownLatch(1);
    -    final int count = 100;
    -    final int groupCount = 2;
    -
    -    Observable es = Observable.create(new Observable.OnSubscribeFunc() {
    -
    -      @Override
    -      public Subscription onSubscribe(final Observer observer) {
    -        System.out.println("*** Subscribing to EventStream ***");
    -        subscribeCounter.incrementAndGet();
    -        new Thread(new Runnable() {
    -
    -          @Override
    -          public void run() {
    -            for (int i = 0; i < count; i++) {
    -              Event e = new Event();
    -              e.source = i % groupCount;
    -              e.message = "Event-" + i;
    -              observer.onNext(e);
    +            @Override
    +            public Integer call(Event e) {
    +                return e.source;
                 }
    -            observer.onCompleted();
    -          }
    +        }).mapMany(new Func1, Observable>() {
     
    -        }).start();
    -        return Subscriptions.empty();
    -      }
    +            @Override
    +            public Observable call(GroupedObservable eventGroupedObservable) {
    +                System.out.println("GroupedObservable Key: " + eventGroupedObservable.getKey());
    +                groupCounter.incrementAndGet();
     
    -    });
    +                return eventGroupedObservable.map(new Func1() {
     
    -    es.groupBy(new Func1() {
    +                    @Override
    +                    public String call(Event event) {
    +                        return "Source: " + event.source + "  Message: " + event.message;
    +                    }
    +                });
     
    -      @Override
    -      public Integer call(Event e) {
    -        return e.source;
    -      }
    -    }).mapMany(new Func1, Observable>() {
    +            }
    +        }).subscribe(new Observer() {
     
    -      @Override
    -      public Observable call(GroupedObservable eventGroupedObservable) {
    -        System.out.println("GroupedObservable Key: " + eventGroupedObservable.getKey());
    -        groupCounter.incrementAndGet();
    +            @Override
    +            public void onCompleted() {
    +                latch.countDown();
    +            }
    +
    +            @Override
    +            public void onError(Throwable e) {
    +                e.printStackTrace();
    +                latch.countDown();
    +            }
    +
    +            @Override
    +            public void onNext(String outputMessage) {
    +                System.out.println(outputMessage);
    +                eventCounter.incrementAndGet();
    +            }
    +        });
    +
    +        latch.await(5000, TimeUnit.MILLISECONDS);
    +        assertEquals(1, subscribeCounter.get());
    +        assertEquals(groupCount, groupCounter.get());
    +        assertEquals(count, eventCounter.get());
     
    -        return eventGroupedObservable.map(new Func1() {
    +    }
    +
    +    /*
    +     * We will only take 1 group with 20 events from it and then unsubscribe.
    +     */
    +    @Test
    +    public void testUnsubscribe() throws InterruptedException {
    +
    +        final AtomicInteger eventCounter = new AtomicInteger();
    +        final AtomicInteger subscribeCounter = new AtomicInteger();
    +        final AtomicInteger groupCounter = new AtomicInteger();
    +        final AtomicInteger sentEventCounter = new AtomicInteger();
    +        final CountDownLatch latch = new CountDownLatch(1);
    +        final int count = 100;
    +        final int groupCount = 2;
    +
    +        Observable es = Observable.create(new Observable.OnSubscribeFunc() {
    +
    +            @Override
    +            public Subscription onSubscribe(final Observer observer) {
    +                final BooleanSubscription s = new BooleanSubscription();
    +                System.out.println("testUnsubscribe => *** Subscribing to EventStream ***");
    +                subscribeCounter.incrementAndGet();
    +                new Thread(new Runnable() {
    +
    +                    @Override
    +                    public void run() {
    +                        for (int i = 0; i < count; i++) {
    +                            if (s.isUnsubscribed()) {
    +                                break;
    +                            }
    +                            Event e = new Event();
    +                            e.source = i % groupCount;
    +                            e.message = "Event-" + i;
    +                            observer.onNext(e);
    +                            sentEventCounter.incrementAndGet();
    +                        }
    +                        observer.onCompleted();
    +                    }
    +
    +                }).start();
    +                return s;
    +            }
     
    -          @Override
    -          public String call(Event event) {
    -            return "Source: " + event.source + "  Message: " + event.message;
    -          }
             });
     
    -      }
    -    }).subscribe(new Observer() {
    -
    -      @Override
    -      public void onCompleted() {
    -        latch.countDown();
    -      }
    -
    -      @Override
    -      public void onError(Throwable e) {
    -        e.printStackTrace();
    -        latch.countDown();
    -      }
    -
    -      @Override
    -      public void onNext(String outputMessage) {
    -        System.out.println(outputMessage);
    -        eventCounter.incrementAndGet();
    -      }
    -    });
    -
    -    latch.await(5000, TimeUnit.MILLISECONDS);
    -    assertEquals(1, subscribeCounter.get());
    -    assertEquals(groupCount, groupCounter.get());
    -    assertEquals(count, eventCounter.get());
    -
    -  }
    -
    -  /*
    -   * We will only take 1 group with 20 events from it and then unsubscribe.
    -   */
    -  @Test
    -  public void testUnsubscribe() throws InterruptedException {
    -
    -    final AtomicInteger eventCounter = new AtomicInteger();
    -    final AtomicInteger subscribeCounter = new AtomicInteger();
    -    final AtomicInteger groupCounter = new AtomicInteger();
    -    final AtomicInteger sentEventCounter = new AtomicInteger();
    -    final CountDownLatch latch = new CountDownLatch(1);
    -    final int count = 100;
    -    final int groupCount = 2;
    -
    -    Observable es = Observable.create(new Observable.OnSubscribeFunc() {
    -
    -      @Override
    -      public Subscription onSubscribe(final Observer observer) {
    -        final BooleanSubscription s = new BooleanSubscription();
    -        System.out.println("testUnsubscribe => *** Subscribing to EventStream ***");
    -        subscribeCounter.incrementAndGet();
    -        new Thread(new Runnable() {
    -
    -          @Override
    -          public void run() {
    -            for (int i = 0; i < count; i++) {
    -              if (s.isUnsubscribed()) {
    -                break;
    -              }
    -              Event e = new Event();
    -              e.source = i % groupCount;
    -              e.message = "Event-" + i;
    -              observer.onNext(e);
    -              sentEventCounter.incrementAndGet();
    +        es.groupBy(new Func1() {
    +
    +            @Override
    +            public Integer call(Event e) {
    +                return e.source;
                 }
    -            observer.onCompleted();
    -          }
    -
    -        }).start();
    -        return s;
    -      }
    -
    -    });
    -
    -    es.groupBy(new Func1() {
    -
    -      @Override
    -      public Integer call(Event e) {
    -        return e.source;
    -      }
    -    })
    -        .take(1) // we want only the first group
    -        .mapMany(new Func1, Observable>() {
    -
    -          @Override
    -          public Observable call(GroupedObservable eventGroupedObservable) {
    -            System.out.println("testUnsubscribe => GroupedObservable Key: " + eventGroupedObservable.getKey());
    -            groupCounter.incrementAndGet();
    -
    -            return eventGroupedObservable
    -                .take(20) // limit to only 20 events on this group
    -                .map(new Func1() {
    -
    -                  @Override
    -                  public String call(Event event) {
    -                    return "testUnsubscribe => Source: " + event.source + "  Message: " + event.message;
    -                  }
    +        })
    +                .take(1) // we want only the first group
    +                .mapMany(new Func1, Observable>() {
    +
    +                    @Override
    +                    public Observable call(GroupedObservable eventGroupedObservable) {
    +                        System.out.println("testUnsubscribe => GroupedObservable Key: " + eventGroupedObservable.getKey());
    +                        groupCounter.incrementAndGet();
    +
    +                        return eventGroupedObservable
    +                                .take(20) // limit to only 20 events on this group
    +                                .map(new Func1() {
    +
    +                                    @Override
    +                                    public String call(Event event) {
    +                                        return "testUnsubscribe => Source: " + event.source + "  Message: " + event.message;
    +                                    }
    +                                });
    +
    +                    }
    +                }).subscribe(new Observer() {
    +
    +                    @Override
    +                    public void onCompleted() {
    +                        latch.countDown();
    +                    }
    +
    +                    @Override
    +                    public void onError(Throwable e) {
    +                        e.printStackTrace();
    +                        latch.countDown();
    +                    }
    +
    +                    @Override
    +                    public void onNext(String outputMessage) {
    +                        System.out.println(outputMessage);
    +                        eventCounter.incrementAndGet();
    +                    }
                     });
     
    -          }
    -        }).subscribe(new Observer() {
    +        latch.await(5000, TimeUnit.MILLISECONDS);
    +        assertEquals(1, subscribeCounter.get());
    +        assertEquals(1, groupCounter.get());
    +        assertEquals(20, eventCounter.get());
    +        // sentEvents will go until 'eventCounter' hits 20 and then unsubscribes
    +        // which means it will also send (but ignore) the 19/20 events for the other group
    +        // It will not however send all 100 events.
    +        assertEquals(39, sentEventCounter.get(), 10);
    +        // gave it a delta of 10 to account for the threading/unsubscription race condition which can vary depending on a machines performance, thread-scheduler, etc
    +    }
    +
    +    private static class Event {
    +        int source;
    +        String message;
     
    -      @Override
    -      public void onCompleted() {
    -        latch.countDown();
    -      }
    -
    -      @Override
    -      public void onError(Throwable e) {
    -        e.printStackTrace();
    -        latch.countDown();
    -      }
    -
    -      @Override
    -      public void onNext(String outputMessage) {
    -        System.out.println(outputMessage);
    -        eventCounter.incrementAndGet();
    -      }
    -    });
    -
    -    latch.await(5000, TimeUnit.MILLISECONDS);
    -    assertEquals(1, subscribeCounter.get());
    -    assertEquals(1, groupCounter.get());
    -    assertEquals(20, eventCounter.get());
    -    // sentEvents will go until 'eventCounter' hits 20 and then unsubscribes
    -    // which means it will also send (but ignore) the 19/20 events for the other group
    -    // It will not however send all 100 events.
    -    assertEquals(39, sentEventCounter.get(), 10);
    -    // gave it a delta of 10 to account for the threading/unsubscription race condition which can vary depending on a machines performance, thread-scheduler, etc
    -  }
    -
    -  private static class Event {
    -    int source;
    -    String message;
    -
    -    @Override
    -    public String toString() {
    -      return "Event => source: " + source + " message: " + message;
    +        @Override
    +        public String toString() {
    +            return "Event => source: " + source + " message: " + message;
    +        }
         }
    -  }
     }
    diff --git a/rxjava-core/src/test/java/rx/operators/OperationIntervalTest.java b/rxjava-core/src/test/java/rx/operators/OperationIntervalTest.java
    index 0ffd27c85b..86764bd6ae 100644
    --- a/rxjava-core/src/test/java/rx/operators/OperationIntervalTest.java
    +++ b/rxjava-core/src/test/java/rx/operators/OperationIntervalTest.java
    @@ -1,176 +1,177 @@
     package rx.operators;
     
    +import static org.mockito.Matchers.*;
    +import static org.mockito.Mockito.*;
    +
    +import java.util.concurrent.TimeUnit;
    +
     import org.junit.Before;
     import org.junit.Test;
     import org.mockito.InOrder;
    +
     import rx.Observable;
     import rx.Observer;
     import rx.Subscription;
     import rx.concurrency.TestScheduler;
     import rx.observables.ConnectableObservable;
     
    -import java.util.concurrent.TimeUnit;
    -
    -import static org.mockito.Matchers.any;
    -import static org.mockito.Matchers.anyLong;
    -import static org.mockito.Mockito.*;
    -
     public class OperationIntervalTest {
     
    -  private TestScheduler scheduler;
    -  private Observer observer;
    -  private Observer observer2;
    -
    -  @Before
    -  @SuppressWarnings("unchecked") // due to mocking
    -  public void before() {
    -    scheduler = new TestScheduler();
    -    observer = mock(Observer.class);
    -    observer2 = mock(Observer.class);
    -  }
    -
    -  @Test
    -  public void testInterval() {
    -    Observable w = Observable.create(OperationInterval.interval(1, TimeUnit.SECONDS, scheduler));
    -    Subscription sub = w.subscribe(observer);
    -
    -    verify(observer, never()).onNext(0L);
    -    verify(observer, never()).onCompleted();
    -    verify(observer, never()).onError(any(Throwable.class));
    -
    -    scheduler.advanceTimeTo(2, TimeUnit.SECONDS);
    -
    -    InOrder inOrder = inOrder(observer);
    -    inOrder.verify(observer, times(1)).onNext(0L);
    -    inOrder.verify(observer, times(1)).onNext(1L);
    -    inOrder.verify(observer, never()).onNext(2L);
    -    verify(observer, never()).onCompleted();
    -    verify(observer, never()).onError(any(Throwable.class));
    -
    -    sub.unsubscribe();
    -    scheduler.advanceTimeTo(4, TimeUnit.SECONDS);
    -    verify(observer, never()).onNext(2L);
    -    verify(observer, times(1)).onCompleted();
    -    verify(observer, never()).onError(any(Throwable.class));
    -  }
    -
    -  @Test
    -  public void testWithMultipleSubscribersStartingAtSameTime() {
    -    Observable w = Observable.create(OperationInterval.interval(1, TimeUnit.SECONDS, scheduler));
    -    Subscription sub1 = w.subscribe(observer);
    -    Subscription sub2 = w.subscribe(observer2);
    -
    -    verify(observer, never()).onNext(anyLong());
    -    verify(observer2, never()).onNext(anyLong());
    -
    -    scheduler.advanceTimeTo(2, TimeUnit.SECONDS);
    +    private TestScheduler scheduler;
    +    private Observer observer;
    +    private Observer observer2;
    +
    +    @Before
    +    @SuppressWarnings("unchecked")
    +    // due to mocking
    +    public void before() {
    +        scheduler = new TestScheduler();
    +        observer = mock(Observer.class);
    +        observer2 = mock(Observer.class);
    +    }
    +
    +    @Test
    +    public void testInterval() {
    +        Observable w = Observable.create(OperationInterval.interval(1, TimeUnit.SECONDS, scheduler));
    +        Subscription sub = w.subscribe(observer);
    +
    +        verify(observer, never()).onNext(0L);
    +        verify(observer, never()).onCompleted();
    +        verify(observer, never()).onError(any(Throwable.class));
    +
    +        scheduler.advanceTimeTo(2, TimeUnit.SECONDS);
    +
    +        InOrder inOrder = inOrder(observer);
    +        inOrder.verify(observer, times(1)).onNext(0L);
    +        inOrder.verify(observer, times(1)).onNext(1L);
    +        inOrder.verify(observer, never()).onNext(2L);
    +        verify(observer, never()).onCompleted();
    +        verify(observer, never()).onError(any(Throwable.class));
    +
    +        sub.unsubscribe();
    +        scheduler.advanceTimeTo(4, TimeUnit.SECONDS);
    +        verify(observer, never()).onNext(2L);
    +        verify(observer, times(1)).onCompleted();
    +        verify(observer, never()).onError(any(Throwable.class));
    +    }
    +
    +    @Test
    +    public void testWithMultipleSubscribersStartingAtSameTime() {
    +        Observable w = Observable.create(OperationInterval.interval(1, TimeUnit.SECONDS, scheduler));
    +        Subscription sub1 = w.subscribe(observer);
    +        Subscription sub2 = w.subscribe(observer2);
    +
    +        verify(observer, never()).onNext(anyLong());
    +        verify(observer2, never()).onNext(anyLong());
    +
    +        scheduler.advanceTimeTo(2, TimeUnit.SECONDS);
     
    -    InOrder inOrder1 = inOrder(observer);
    -    InOrder inOrder2 = inOrder(observer2);
    -
    -    inOrder1.verify(observer, times(1)).onNext(0L);
    -    inOrder1.verify(observer, times(1)).onNext(1L);
    -    inOrder1.verify(observer, never()).onNext(2L);
    -    verify(observer, never()).onCompleted();
    -    verify(observer, never()).onError(any(Throwable.class));
    -
    -    inOrder2.verify(observer2, times(1)).onNext(0L);
    -    inOrder2.verify(observer2, times(1)).onNext(1L);
    -    inOrder2.verify(observer2, never()).onNext(2L);
    -    verify(observer2, never()).onCompleted();
    -    verify(observer2, never()).onError(any(Throwable.class));
    -
    -    sub1.unsubscribe();
    -    sub2.unsubscribe();
    -    scheduler.advanceTimeTo(4, TimeUnit.SECONDS);
    -
    -    verify(observer, never()).onNext(2L);
    -    verify(observer, times(1)).onCompleted();
    -    verify(observer, never()).onError(any(Throwable.class));
    -
    -    verify(observer2, never()).onNext(2L);
    -    verify(observer2, times(1)).onCompleted();
    -    verify(observer2, never()).onError(any(Throwable.class));
    -  }
    -
    -  @Test
    -  public void testWithMultipleStaggeredSubscribers() {
    -    Observable w = Observable.create(OperationInterval.interval(1, TimeUnit.SECONDS, scheduler));
    -    Subscription sub1 = w.subscribe(observer);
    -
    -    verify(observer, never()).onNext(anyLong());
    -
    -    scheduler.advanceTimeTo(2, TimeUnit.SECONDS);
    -    Subscription sub2 = w.subscribe(observer2);
    -
    -    InOrder inOrder1 = inOrder(observer);
    -    inOrder1.verify(observer, times(1)).onNext(0L);
    -    inOrder1.verify(observer, times(1)).onNext(1L);
    -    inOrder1.verify(observer, never()).onNext(2L);
    -
    -    verify(observer, never()).onCompleted();
    -    verify(observer, never()).onError(any(Throwable.class));
    -    verify(observer2, never()).onNext(anyLong());
    -
    -    scheduler.advanceTimeTo(4, TimeUnit.SECONDS);
    -
    -    inOrder1.verify(observer, times(1)).onNext(2L);
    -    inOrder1.verify(observer, times(1)).onNext(3L);
    -
    -    InOrder inOrder2 = inOrder(observer2);
    -    inOrder2.verify(observer2, times(1)).onNext(0L);
    -    inOrder2.verify(observer2, times(1)).onNext(1L);
    -
    -    sub1.unsubscribe();
    -    sub2.unsubscribe();
    -
    -    inOrder1.verify(observer, never()).onNext(anyLong());
    -    inOrder1.verify(observer, times(1)).onCompleted();
    -    verify(observer, never()).onError(any(Throwable.class));
    +        InOrder inOrder1 = inOrder(observer);
    +        InOrder inOrder2 = inOrder(observer2);
    +
    +        inOrder1.verify(observer, times(1)).onNext(0L);
    +        inOrder1.verify(observer, times(1)).onNext(1L);
    +        inOrder1.verify(observer, never()).onNext(2L);
    +        verify(observer, never()).onCompleted();
    +        verify(observer, never()).onError(any(Throwable.class));
    +
    +        inOrder2.verify(observer2, times(1)).onNext(0L);
    +        inOrder2.verify(observer2, times(1)).onNext(1L);
    +        inOrder2.verify(observer2, never()).onNext(2L);
    +        verify(observer2, never()).onCompleted();
    +        verify(observer2, never()).onError(any(Throwable.class));
    +
    +        sub1.unsubscribe();
    +        sub2.unsubscribe();
    +        scheduler.advanceTimeTo(4, TimeUnit.SECONDS);
    +
    +        verify(observer, never()).onNext(2L);
    +        verify(observer, times(1)).onCompleted();
    +        verify(observer, never()).onError(any(Throwable.class));
    +
    +        verify(observer2, never()).onNext(2L);
    +        verify(observer2, times(1)).onCompleted();
    +        verify(observer2, never()).onError(any(Throwable.class));
    +    }
    +
    +    @Test
    +    public void testWithMultipleStaggeredSubscribers() {
    +        Observable w = Observable.create(OperationInterval.interval(1, TimeUnit.SECONDS, scheduler));
    +        Subscription sub1 = w.subscribe(observer);
    +
    +        verify(observer, never()).onNext(anyLong());
    +
    +        scheduler.advanceTimeTo(2, TimeUnit.SECONDS);
    +        Subscription sub2 = w.subscribe(observer2);
    +
    +        InOrder inOrder1 = inOrder(observer);
    +        inOrder1.verify(observer, times(1)).onNext(0L);
    +        inOrder1.verify(observer, times(1)).onNext(1L);
    +        inOrder1.verify(observer, never()).onNext(2L);
    +
    +        verify(observer, never()).onCompleted();
    +        verify(observer, never()).onError(any(Throwable.class));
    +        verify(observer2, never()).onNext(anyLong());
    +
    +        scheduler.advanceTimeTo(4, TimeUnit.SECONDS);
    +
    +        inOrder1.verify(observer, times(1)).onNext(2L);
    +        inOrder1.verify(observer, times(1)).onNext(3L);
    +
    +        InOrder inOrder2 = inOrder(observer2);
    +        inOrder2.verify(observer2, times(1)).onNext(0L);
    +        inOrder2.verify(observer2, times(1)).onNext(1L);
    +
    +        sub1.unsubscribe();
    +        sub2.unsubscribe();
    +
    +        inOrder1.verify(observer, never()).onNext(anyLong());
    +        inOrder1.verify(observer, times(1)).onCompleted();
    +        verify(observer, never()).onError(any(Throwable.class));
     
    -    inOrder2.verify(observer2, never()).onNext(anyLong());
    -    inOrder2.verify(observer2, times(1)).onCompleted();
    -    verify(observer2, never()).onError(any(Throwable.class));
    -  }
    +        inOrder2.verify(observer2, never()).onNext(anyLong());
    +        inOrder2.verify(observer2, times(1)).onCompleted();
    +        verify(observer2, never()).onError(any(Throwable.class));
    +    }
     
    -  @Test
    -  public void testWithMultipleStaggeredSubscribersAndPublish() {
    -    ConnectableObservable w = Observable.create(OperationInterval.interval(1, TimeUnit.SECONDS, scheduler)).publish();
    -    Subscription sub1 = w.subscribe(observer);
    -    w.connect();
    +    @Test
    +    public void testWithMultipleStaggeredSubscribersAndPublish() {
    +        ConnectableObservable w = Observable.create(OperationInterval.interval(1, TimeUnit.SECONDS, scheduler)).publish();
    +        Subscription sub1 = w.subscribe(observer);
    +        w.connect();
     
    -    verify(observer, never()).onNext(anyLong());
    -
    -    scheduler.advanceTimeTo(2, TimeUnit.SECONDS);
    -    Subscription sub2 = w.subscribe(observer2);
    +        verify(observer, never()).onNext(anyLong());
    +
    +        scheduler.advanceTimeTo(2, TimeUnit.SECONDS);
    +        Subscription sub2 = w.subscribe(observer2);
     
    -    InOrder inOrder1 = inOrder(observer);
    -    inOrder1.verify(observer, times(1)).onNext(0L);
    -    inOrder1.verify(observer, times(1)).onNext(1L);
    -    inOrder1.verify(observer, never()).onNext(2L);
    +        InOrder inOrder1 = inOrder(observer);
    +        inOrder1.verify(observer, times(1)).onNext(0L);
    +        inOrder1.verify(observer, times(1)).onNext(1L);
    +        inOrder1.verify(observer, never()).onNext(2L);
     
    -    verify(observer, never()).onCompleted();
    -    verify(observer, never()).onError(any(Throwable.class));
    -    verify(observer2, never()).onNext(anyLong());
    +        verify(observer, never()).onCompleted();
    +        verify(observer, never()).onError(any(Throwable.class));
    +        verify(observer2, never()).onNext(anyLong());
     
    -    scheduler.advanceTimeTo(4, TimeUnit.SECONDS);
    +        scheduler.advanceTimeTo(4, TimeUnit.SECONDS);
     
    -    inOrder1.verify(observer, times(1)).onNext(2L);
    -    inOrder1.verify(observer, times(1)).onNext(3L);
    +        inOrder1.verify(observer, times(1)).onNext(2L);
    +        inOrder1.verify(observer, times(1)).onNext(3L);
     
    -    InOrder inOrder2 = inOrder(observer2);
    -    inOrder2.verify(observer2, times(1)).onNext(2L);
    -    inOrder2.verify(observer2, times(1)).onNext(3L);
    +        InOrder inOrder2 = inOrder(observer2);
    +        inOrder2.verify(observer2, times(1)).onNext(2L);
    +        inOrder2.verify(observer2, times(1)).onNext(3L);
     
    -    sub1.unsubscribe();
    -    sub2.unsubscribe();
    +        sub1.unsubscribe();
    +        sub2.unsubscribe();
     
    -    inOrder1.verify(observer, never()).onNext(anyLong());
    -    inOrder1.verify(observer, never()).onCompleted();
    -    verify(observer, never()).onError(any(Throwable.class));
    +        inOrder1.verify(observer, never()).onNext(anyLong());
    +        inOrder1.verify(observer, never()).onCompleted();
    +        verify(observer, never()).onError(any(Throwable.class));
     
    -    inOrder2.verify(observer2, never()).onNext(anyLong());
    -    inOrder2.verify(observer2, never()).onCompleted();
    -    verify(observer2, never()).onError(any(Throwable.class));
    -  }
    +        inOrder2.verify(observer2, never()).onNext(anyLong());
    +        inOrder2.verify(observer2, never()).onCompleted();
    +        verify(observer2, never()).onError(any(Throwable.class));
    +    }
     }
    diff --git a/rxjava-core/src/test/java/rx/operators/OperationMapTest.java b/rxjava-core/src/test/java/rx/operators/OperationMapTest.java
    index cfd081112e..279a40eb7f 100644
    --- a/rxjava-core/src/test/java/rx/operators/OperationMapTest.java
    +++ b/rxjava-core/src/test/java/rx/operators/OperationMapTest.java
    @@ -1,276 +1,277 @@
     package rx.operators;
     
    +import static org.junit.Assert.*;
    +import static org.mockito.Matchers.*;
    +import static org.mockito.Mockito.*;
    +import static rx.operators.OperationMap.*;
    +
    +import java.util.HashMap;
    +import java.util.Map;
    +import java.util.concurrent.CountDownLatch;
    +import java.util.concurrent.atomic.AtomicInteger;
    +
     import org.junit.Before;
     import org.junit.Test;
     import org.mockito.InOrder;
     import org.mockito.Mock;
     import org.mockito.MockitoAnnotations;
    +
     import rx.Observable;
     import rx.Observer;
     import rx.concurrency.Schedulers;
     import rx.util.functions.Func1;
     import rx.util.functions.Func2;
     
    -import java.util.HashMap;
    -import java.util.Map;
    -import java.util.concurrent.CountDownLatch;
    -import java.util.concurrent.atomic.AtomicInteger;
    +public class OperationMapTest {
     
    -import static org.junit.Assert.assertEquals;
    -import static org.mockito.Matchers.any;
    -import static org.mockito.Mockito.*;
    -import static rx.operators.OperationMap.*;
    +    @Mock
    +    Observer stringObserver;
    +    @Mock
    +    Observer stringObserver2;
     
    -public class OperationMapTest {
    +    final static Func2 APPEND_INDEX = new Func2() {
    +        @Override
    +        public String call(String value, Integer index) {
    +            return value + index;
    +        }
    +    };
    +
    +    @Before
    +    public void before() {
    +        MockitoAnnotations.initMocks(this);
    +    }
    +
    +    @Test
    +    public void testMap() {
    +        Map m1 = getMap("One");
    +        Map m2 = getMap("Two");
    +        Observable> observable = Observable.from(m1, m2);
     
    -  @Mock
    -  Observer stringObserver;
    -  @Mock
    -  Observer stringObserver2;
    +        Observable m = Observable.create(map(observable, new Func1, String>() {
     
    -  final static Func2 APPEND_INDEX = new Func2() {
    -    @Override
    -    public String call(String value, Integer index) {
    -      return value + index;
    +            @Override
    +            public String call(Map map) {
    +                return map.get("firstName");
    +            }
    +
    +        }));
    +        m.subscribe(stringObserver);
    +
    +        verify(stringObserver, never()).onError(any(Throwable.class));
    +        verify(stringObserver, times(1)).onNext("OneFirst");
    +        verify(stringObserver, times(1)).onNext("TwoFirst");
    +        verify(stringObserver, times(1)).onCompleted();
         }
    -  };
    -
    -  @Before
    -  public void before() {
    -    MockitoAnnotations.initMocks(this);
    -  }
    -
    -  @Test
    -  public void testMap() {
    -    Map m1 = getMap("One");
    -    Map m2 = getMap("Two");
    -    Observable> observable = Observable.from(m1, m2);
    -
    -    Observable m = Observable.create(map(observable, new Func1, String>() {
    -
    -      @Override
    -      public String call(Map map) {
    -        return map.get("firstName");
    -      }
    -
    -    }));
    -    m.subscribe(stringObserver);
    -
    -    verify(stringObserver, never()).onError(any(Throwable.class));
    -    verify(stringObserver, times(1)).onNext("OneFirst");
    -    verify(stringObserver, times(1)).onNext("TwoFirst");
    -    verify(stringObserver, times(1)).onCompleted();
    -  }
    -
    -  @Test
    -  public void testMapWithIndex() {
    -    Observable w = Observable.from("a", "b", "c");
    -    Observable m = Observable.create(mapWithIndex(w, APPEND_INDEX));
    -    m.subscribe(stringObserver);
    -    InOrder inOrder = inOrder(stringObserver);
    -    inOrder.verify(stringObserver, times(1)).onNext("a0");
    -    inOrder.verify(stringObserver, times(1)).onNext("b1");
    -    inOrder.verify(stringObserver, times(1)).onNext("c2");
    -    inOrder.verify(stringObserver, times(1)).onCompleted();
    -    verify(stringObserver, never()).onError(any(Throwable.class));
    -  }
    -
    -  @Test
    -  public void testMapWithIndexAndMultipleSubscribers() {
    -    Observable w = Observable.from("a", "b", "c");
    -    Observable m = Observable.create(mapWithIndex(w, APPEND_INDEX));
    -    m.subscribe(stringObserver);
    -    m.subscribe(stringObserver2);
    -    InOrder inOrder = inOrder(stringObserver);
    -    inOrder.verify(stringObserver, times(1)).onNext("a0");
    -    inOrder.verify(stringObserver, times(1)).onNext("b1");
    -    inOrder.verify(stringObserver, times(1)).onNext("c2");
    -    inOrder.verify(stringObserver, times(1)).onCompleted();
    -    verify(stringObserver, never()).onError(any(Throwable.class));
    -
    -    InOrder inOrder2 = inOrder(stringObserver2);
    -    inOrder2.verify(stringObserver2, times(1)).onNext("a0");
    -    inOrder2.verify(stringObserver2, times(1)).onNext("b1");
    -    inOrder2.verify(stringObserver2, times(1)).onNext("c2");
    -    inOrder2.verify(stringObserver2, times(1)).onCompleted();
    -    verify(stringObserver2, never()).onError(any(Throwable.class));
    -  }
    -
    -  @Test
    -  public void testMapMany() {
    -            /* simulate a top-level async call which returns IDs */
    -    Observable ids = Observable.from(1, 2);
    -
    -            /* now simulate the behavior to take those IDs and perform nested async calls based on them */
    -    Observable m = Observable.create(mapMany(ids, new Func1>() {
    -
    -      @Override
    -      public Observable call(Integer id) {
    -                    /* simulate making a nested async call which creates another Observable */
    -        Observable> subObservable = null;
    -        if (id == 1) {
    -          Map m1 = getMap("One");
    -          Map m2 = getMap("Two");
    -          subObservable = Observable.from(m1, m2);
    -        } else {
    -          Map m3 = getMap("Three");
    -          Map m4 = getMap("Four");
    -          subObservable = Observable.from(m3, m4);
    -        }
     
    -                    /* simulate kicking off the async call and performing a select on it to transform the data */
    -        return Observable.create(map(subObservable, new Func1, String>() {
    -          @Override
    -          public String call(Map map) {
    -            return map.get("firstName");
    -          }
    +    @Test
    +    public void testMapWithIndex() {
    +        Observable w = Observable.from("a", "b", "c");
    +        Observable m = Observable.create(mapWithIndex(w, APPEND_INDEX));
    +        m.subscribe(stringObserver);
    +        InOrder inOrder = inOrder(stringObserver);
    +        inOrder.verify(stringObserver, times(1)).onNext("a0");
    +        inOrder.verify(stringObserver, times(1)).onNext("b1");
    +        inOrder.verify(stringObserver, times(1)).onNext("c2");
    +        inOrder.verify(stringObserver, times(1)).onCompleted();
    +        verify(stringObserver, never()).onError(any(Throwable.class));
    +    }
    +
    +    @Test
    +    public void testMapWithIndexAndMultipleSubscribers() {
    +        Observable w = Observable.from("a", "b", "c");
    +        Observable m = Observable.create(mapWithIndex(w, APPEND_INDEX));
    +        m.subscribe(stringObserver);
    +        m.subscribe(stringObserver2);
    +        InOrder inOrder = inOrder(stringObserver);
    +        inOrder.verify(stringObserver, times(1)).onNext("a0");
    +        inOrder.verify(stringObserver, times(1)).onNext("b1");
    +        inOrder.verify(stringObserver, times(1)).onNext("c2");
    +        inOrder.verify(stringObserver, times(1)).onCompleted();
    +        verify(stringObserver, never()).onError(any(Throwable.class));
    +
    +        InOrder inOrder2 = inOrder(stringObserver2);
    +        inOrder2.verify(stringObserver2, times(1)).onNext("a0");
    +        inOrder2.verify(stringObserver2, times(1)).onNext("b1");
    +        inOrder2.verify(stringObserver2, times(1)).onNext("c2");
    +        inOrder2.verify(stringObserver2, times(1)).onCompleted();
    +        verify(stringObserver2, never()).onError(any(Throwable.class));
    +    }
    +
    +    @Test
    +    public void testMapMany() {
    +        /* simulate a top-level async call which returns IDs */
    +        Observable ids = Observable.from(1, 2);
    +
    +        /* now simulate the behavior to take those IDs and perform nested async calls based on them */
    +        Observable m = Observable.create(mapMany(ids, new Func1>() {
    +
    +            @Override
    +            public Observable call(Integer id) {
    +                /* simulate making a nested async call which creates another Observable */
    +                Observable> subObservable = null;
    +                if (id == 1) {
    +                    Map m1 = getMap("One");
    +                    Map m2 = getMap("Two");
    +                    subObservable = Observable.from(m1, m2);
    +                } else {
    +                    Map m3 = getMap("Three");
    +                    Map m4 = getMap("Four");
    +                    subObservable = Observable.from(m3, m4);
    +                }
    +
    +                /* simulate kicking off the async call and performing a select on it to transform the data */
    +                return Observable.create(map(subObservable, new Func1, String>() {
    +                    @Override
    +                    public String call(Map map) {
    +                        return map.get("firstName");
    +                    }
    +                }));
    +            }
    +
             }));
    -      }
    +        m.subscribe(stringObserver);
    +
    +        verify(stringObserver, never()).onError(any(Throwable.class));
    +        verify(stringObserver, times(1)).onNext("OneFirst");
    +        verify(stringObserver, times(1)).onNext("TwoFirst");
    +        verify(stringObserver, times(1)).onNext("ThreeFirst");
    +        verify(stringObserver, times(1)).onNext("FourFirst");
    +        verify(stringObserver, times(1)).onCompleted();
    +    }
     
    -    }));
    -    m.subscribe(stringObserver);
    +    @Test
    +    public void testMapMany2() {
    +        Map m1 = getMap("One");
    +        Map m2 = getMap("Two");
    +        Observable> observable1 = Observable.from(m1, m2);
     
    -    verify(stringObserver, never()).onError(any(Throwable.class));
    -    verify(stringObserver, times(1)).onNext("OneFirst");
    -    verify(stringObserver, times(1)).onNext("TwoFirst");
    -    verify(stringObserver, times(1)).onNext("ThreeFirst");
    -    verify(stringObserver, times(1)).onNext("FourFirst");
    -    verify(stringObserver, times(1)).onCompleted();
    -  }
    +        Map m3 = getMap("Three");
    +        Map m4 = getMap("Four");
    +        Observable> observable2 = Observable.from(m3, m4);
     
    -  @Test
    -  public void testMapMany2() {
    -    Map m1 = getMap("One");
    -    Map m2 = getMap("Two");
    -    Observable> observable1 = Observable.from(m1, m2);
    +        Observable>> observable = Observable.from(observable1, observable2);
     
    -    Map m3 = getMap("Three");
    -    Map m4 = getMap("Four");
    -    Observable> observable2 = Observable.from(m3, m4);
    +        Observable m = Observable.create(mapMany(observable, new Func1>, Observable>() {
     
    -    Observable>> observable = Observable.from(observable1, observable2);
    +            @Override
    +            public Observable call(Observable> o) {
    +                return Observable.create(map(o, new Func1, String>() {
     
    -    Observable m = Observable.create(mapMany(observable, new Func1>, Observable>() {
    +                    @Override
    +                    public String call(Map map) {
    +                        return map.get("firstName");
    +                    }
    +                }));
    +            }
     
    -      @Override
    -      public Observable call(Observable> o) {
    -        return Observable.create(map(o, new Func1, String>() {
    +        }));
    +        m.subscribe(stringObserver);
    +
    +        verify(stringObserver, never()).onError(any(Throwable.class));
    +        verify(stringObserver, times(1)).onNext("OneFirst");
    +        verify(stringObserver, times(1)).onNext("TwoFirst");
    +        verify(stringObserver, times(1)).onNext("ThreeFirst");
    +        verify(stringObserver, times(1)).onNext("FourFirst");
    +        verify(stringObserver, times(1)).onCompleted();
    +
    +    }
     
    -          @Override
    -          public String call(Map map) {
    -            return map.get("firstName");
    -          }
    +    @Test
    +    public void testMapWithError() {
    +        Observable w = Observable.from("one", "fail", "two", "three", "fail");
    +        Observable m = Observable.create(map(w, new Func1() {
    +            @Override
    +            public String call(String s) {
    +                if ("fail".equals(s)) {
    +                    throw new RuntimeException("Forced Failure");
    +                }
    +                return s;
    +            }
             }));
    -      }
    -
    -    }));
    -    m.subscribe(stringObserver);
    -
    -    verify(stringObserver, never()).onError(any(Throwable.class));
    -    verify(stringObserver, times(1)).onNext("OneFirst");
    -    verify(stringObserver, times(1)).onNext("TwoFirst");
    -    verify(stringObserver, times(1)).onNext("ThreeFirst");
    -    verify(stringObserver, times(1)).onNext("FourFirst");
    -    verify(stringObserver, times(1)).onCompleted();
    -
    -  }
    -
    -  @Test
    -  public void testMapWithError() {
    -    Observable w = Observable.from("one", "fail", "two", "three", "fail");
    -    Observable m = Observable.create(map(w, new Func1() {
    -      @Override
    -      public String call(String s) {
    -        if ("fail".equals(s)) {
    -          throw new RuntimeException("Forced Failure");
    -        }
    -        return s;
    -      }
    -    }));
    -
    -    m.subscribe(stringObserver);
    -    verify(stringObserver, times(1)).onNext("one");
    -    verify(stringObserver, never()).onNext("two");
    -    verify(stringObserver, never()).onNext("three");
    -    verify(stringObserver, never()).onCompleted();
    -    verify(stringObserver, times(1)).onError(any(Throwable.class));
    -  }
    -
    -  @Test
    -  public void testMapWithSynchronousObservableContainingError() {
    -    Observable w = Observable.from("one", "fail", "two", "three", "fail");
    -    final AtomicInteger c1 = new AtomicInteger();
    -    final AtomicInteger c2 = new AtomicInteger();
    -    Observable m = Observable.create(map(w, new Func1() {
    -      @Override
    -      public String call(String s) {
    -        if ("fail".equals(s))
    -          throw new RuntimeException("Forced Failure");
    -        System.out.println("BadMapper:" + s);
    -        c1.incrementAndGet();
    -        return s;
    -      }
    -    })).map(new Func1() {
    -      @Override
    -      public String call(String s) {
    -        System.out.println("SecondMapper:" + s);
    -        c2.incrementAndGet();
    -        return s;
    -      }
    -    });
    -
    -    m.subscribe(stringObserver);
    -
    -    verify(stringObserver, times(1)).onNext("one");
    -    verify(stringObserver, never()).onNext("two");
    -    verify(stringObserver, never()).onNext("three");
    -    verify(stringObserver, never()).onCompleted();
    -    verify(stringObserver, times(1)).onError(any(Throwable.class));
    -
    -    // we should have only returned 1 value: "one"
    -    assertEquals(1, c1.get());
    -    assertEquals(1, c2.get());
    -  }
    -
    -  @Test(expected = IllegalArgumentException.class)
    -  public void testMapWithIssue417() {
    -    Observable.from(1).observeOn(Schedulers.threadPoolForComputation())
    -        .map(new Func1() {
    -          public Integer call(Integer arg0) {
    -            throw new IllegalArgumentException("any error");
    -          }
    -        }).toBlockingObservable().single();
    -  }
    -
    -  @Test
    -  public void testMapWithErrorInFuncAndThreadPoolScheduler() throws InterruptedException {
    -    // The error will throw in one of threads in the thread pool.
    -    // If map does not handle it, the error will disappear.
    -    // so map needs to handle the error by itself.
    -    final CountDownLatch latch = new CountDownLatch(1);
    -    Observable m = Observable.from("one")
    -        .observeOn(Schedulers.threadPoolForComputation())
    -        .map(new Func1() {
    -          public String call(String arg0) {
    -            try {
    -              throw new IllegalArgumentException("any error");
    -            } finally {
    -              latch.countDown();
    +
    +        m.subscribe(stringObserver);
    +        verify(stringObserver, times(1)).onNext("one");
    +        verify(stringObserver, never()).onNext("two");
    +        verify(stringObserver, never()).onNext("three");
    +        verify(stringObserver, never()).onCompleted();
    +        verify(stringObserver, times(1)).onError(any(Throwable.class));
    +    }
    +
    +    @Test
    +    public void testMapWithSynchronousObservableContainingError() {
    +        Observable w = Observable.from("one", "fail", "two", "three", "fail");
    +        final AtomicInteger c1 = new AtomicInteger();
    +        final AtomicInteger c2 = new AtomicInteger();
    +        Observable m = Observable.create(map(w, new Func1() {
    +            @Override
    +            public String call(String s) {
    +                if ("fail".equals(s))
    +                    throw new RuntimeException("Forced Failure");
    +                System.out.println("BadMapper:" + s);
    +                c1.incrementAndGet();
    +                return s;
    +            }
    +        })).map(new Func1() {
    +            @Override
    +            public String call(String s) {
    +                System.out.println("SecondMapper:" + s);
    +                c2.incrementAndGet();
    +                return s;
                 }
    -          }
             });
     
    -    m.subscribe(stringObserver);
    -    latch.await();
    -    InOrder inorder = inOrder(stringObserver);
    -    inorder.verify(stringObserver, times(1)).onError(any(IllegalArgumentException.class));
    -    inorder.verifyNoMoreInteractions();
    -  }
    -
    -  private static Map getMap(String prefix) {
    -    Map m = new HashMap();
    -    m.put("firstName", prefix + "First");
    -    m.put("lastName", prefix + "Last");
    -    return m;
    -  }
    +        m.subscribe(stringObserver);
    +
    +        verify(stringObserver, times(1)).onNext("one");
    +        verify(stringObserver, never()).onNext("two");
    +        verify(stringObserver, never()).onNext("three");
    +        verify(stringObserver, never()).onCompleted();
    +        verify(stringObserver, times(1)).onError(any(Throwable.class));
    +
    +        // we should have only returned 1 value: "one"
    +        assertEquals(1, c1.get());
    +        assertEquals(1, c2.get());
    +    }
    +
    +    @Test(expected = IllegalArgumentException.class)
    +    public void testMapWithIssue417() {
    +        Observable.from(1).observeOn(Schedulers.threadPoolForComputation())
    +                .map(new Func1() {
    +                    public Integer call(Integer arg0) {
    +                        throw new IllegalArgumentException("any error");
    +                    }
    +                }).toBlockingObservable().single();
    +    }
    +
    +    @Test
    +    public void testMapWithErrorInFuncAndThreadPoolScheduler() throws InterruptedException {
    +        // The error will throw in one of threads in the thread pool.
    +        // If map does not handle it, the error will disappear.
    +        // so map needs to handle the error by itself.
    +        final CountDownLatch latch = new CountDownLatch(1);
    +        Observable m = Observable.from("one")
    +                .observeOn(Schedulers.threadPoolForComputation())
    +                .map(new Func1() {
    +                    public String call(String arg0) {
    +                        try {
    +                            throw new IllegalArgumentException("any error");
    +                        } finally {
    +                            latch.countDown();
    +                        }
    +                    }
    +                });
    +
    +        m.subscribe(stringObserver);
    +        latch.await();
    +        InOrder inorder = inOrder(stringObserver);
    +        inorder.verify(stringObserver, times(1)).onError(any(IllegalArgumentException.class));
    +        inorder.verifyNoMoreInteractions();
    +    }
    +
    +    private static Map getMap(String prefix) {
    +        Map m = new HashMap();
    +        m.put("firstName", prefix + "First");
    +        m.put("lastName", prefix + "Last");
    +        return m;
    +    }
     }
    diff --git a/rxjava-core/src/test/java/rx/operators/OperationMaterializeTest.java b/rxjava-core/src/test/java/rx/operators/OperationMaterializeTest.java
    index f7f4142672..0795ec03ed 100644
    --- a/rxjava-core/src/test/java/rx/operators/OperationMaterializeTest.java
    +++ b/rxjava-core/src/test/java/rx/operators/OperationMaterializeTest.java
    @@ -1,150 +1,151 @@
     package rx.operators;
     
    -import org.junit.Test;
    -import rx.Notification;
    -import rx.Observable;
    -import rx.Observer;
    -import rx.Subscription;
    +import static org.junit.Assert.*;
    +import static rx.operators.OperationMaterialize.*;
     
     import java.util.List;
     import java.util.Vector;
     import java.util.concurrent.ExecutionException;
     
    -import static org.junit.Assert.*;
    -import static rx.operators.OperationMaterialize.materialize;
    +import org.junit.Test;
    +
    +import rx.Notification;
    +import rx.Observable;
    +import rx.Observer;
    +import rx.Subscription;
     
     public class OperationMaterializeTest {
     
    -  @Test
    -  public void testMaterialize1() {
    -    // null will cause onError to be triggered before "three" can be returned
    -    final TestAsyncErrorObservable o1 = new TestAsyncErrorObservable("one", "two", null, "three");
    +    @Test
    +    public void testMaterialize1() {
    +        // null will cause onError to be triggered before "three" can be returned
    +        final TestAsyncErrorObservable o1 = new TestAsyncErrorObservable("one", "two", null, "three");
     
    -    TestObserver Observer = new TestObserver();
    -    Observable> m = Observable.create(materialize(Observable.create(o1)));
    -    m.subscribe(Observer);
    +        TestObserver Observer = new TestObserver();
    +        Observable> m = Observable.create(materialize(Observable.create(o1)));
    +        m.subscribe(Observer);
     
    -    try {
    -      o1.t.join();
    -    } catch (InterruptedException e) {
    -      throw new RuntimeException(e);
    -    }
    +        try {
    +            o1.t.join();
    +        } catch (InterruptedException e) {
    +            throw new RuntimeException(e);
    +        }
     
    -    assertFalse(Observer.onError);
    -    assertTrue(Observer.onCompleted);
    -    assertEquals(3, Observer.notifications.size());
    -    assertEquals("one", Observer.notifications.get(0).getValue());
    -    assertTrue(Observer.notifications.get(0).isOnNext());
    -    assertEquals("two", Observer.notifications.get(1).getValue());
    -    assertTrue(Observer.notifications.get(1).isOnNext());
    -    assertEquals(NullPointerException.class, Observer.notifications.get(2).getThrowable().getClass());
    -    assertTrue(Observer.notifications.get(2).isOnError());
    -  }
    -
    -  @Test
    -  public void testMaterialize2() {
    -    final TestAsyncErrorObservable o1 = new TestAsyncErrorObservable("one", "two", "three");
    -
    -    TestObserver Observer = new TestObserver();
    -    Observable> m = Observable.create(materialize(Observable.create(o1)));
    -    m.subscribe(Observer);
    -
    -    try {
    -      o1.t.join();
    -    } catch (InterruptedException e) {
    -      throw new RuntimeException(e);
    +        assertFalse(Observer.onError);
    +        assertTrue(Observer.onCompleted);
    +        assertEquals(3, Observer.notifications.size());
    +        assertEquals("one", Observer.notifications.get(0).getValue());
    +        assertTrue(Observer.notifications.get(0).isOnNext());
    +        assertEquals("two", Observer.notifications.get(1).getValue());
    +        assertTrue(Observer.notifications.get(1).isOnNext());
    +        assertEquals(NullPointerException.class, Observer.notifications.get(2).getThrowable().getClass());
    +        assertTrue(Observer.notifications.get(2).isOnError());
         }
     
    -    assertFalse(Observer.onError);
    -    assertTrue(Observer.onCompleted);
    -    assertEquals(4, Observer.notifications.size());
    -    assertEquals("one", Observer.notifications.get(0).getValue());
    -    assertTrue(Observer.notifications.get(0).isOnNext());
    -    assertEquals("two", Observer.notifications.get(1).getValue());
    -    assertTrue(Observer.notifications.get(1).isOnNext());
    -    assertEquals("three", Observer.notifications.get(2).getValue());
    -    assertTrue(Observer.notifications.get(2).isOnNext());
    -    assertTrue(Observer.notifications.get(3).isOnCompleted());
    -  }
    -
    -  @Test
    -  public void testMultipleSubscribes() throws InterruptedException, ExecutionException {
    -    final TestAsyncErrorObservable o = new TestAsyncErrorObservable("one", "two", null, "three");
    -
    -    Observable> m = Observable.create(materialize(Observable.create(o)));
    -
    -    assertEquals(3, m.toList().toBlockingObservable().toFuture().get().size());
    -    assertEquals(3, m.toList().toBlockingObservable().toFuture().get().size());
    -  }
    -
    -  private static class TestObserver implements Observer> {
    -
    -    boolean onCompleted = false;
    -    boolean onError = false;
    -    List> notifications = new Vector>();
    -
    -    @Override
    -    public void onCompleted() {
    -      this.onCompleted = true;
    -    }
    +    @Test
    +    public void testMaterialize2() {
    +        final TestAsyncErrorObservable o1 = new TestAsyncErrorObservable("one", "two", "three");
     
    -    @Override
    -    public void onError(Throwable e) {
    -      this.onError = true;
    -    }
    +        TestObserver Observer = new TestObserver();
    +        Observable> m = Observable.create(materialize(Observable.create(o1)));
    +        m.subscribe(Observer);
     
    -    @Override
    -    public void onNext(Notification value) {
    -      this.notifications.add(value);
    -    }
    +        try {
    +            o1.t.join();
    +        } catch (InterruptedException e) {
    +            throw new RuntimeException(e);
    +        }
     
    -  }
    +        assertFalse(Observer.onError);
    +        assertTrue(Observer.onCompleted);
    +        assertEquals(4, Observer.notifications.size());
    +        assertEquals("one", Observer.notifications.get(0).getValue());
    +        assertTrue(Observer.notifications.get(0).isOnNext());
    +        assertEquals("two", Observer.notifications.get(1).getValue());
    +        assertTrue(Observer.notifications.get(1).isOnNext());
    +        assertEquals("three", Observer.notifications.get(2).getValue());
    +        assertTrue(Observer.notifications.get(2).isOnNext());
    +        assertTrue(Observer.notifications.get(3).isOnCompleted());
    +    }
     
    -  private static class TestAsyncErrorObservable implements Observable.OnSubscribeFunc {
    +    @Test
    +    public void testMultipleSubscribes() throws InterruptedException, ExecutionException {
    +        final TestAsyncErrorObservable o = new TestAsyncErrorObservable("one", "two", null, "three");
     
    -    String[] valuesToReturn;
    +        Observable> m = Observable.create(materialize(Observable.create(o)));
     
    -    TestAsyncErrorObservable(String... values) {
    -      valuesToReturn = values;
    +        assertEquals(3, m.toList().toBlockingObservable().toFuture().get().size());
    +        assertEquals(3, m.toList().toBlockingObservable().toFuture().get().size());
         }
     
    -    volatile Thread t;
    +    private static class TestObserver implements Observer> {
     
    -    @Override
    -    public Subscription onSubscribe(final Observer observer) {
    -      t = new Thread(new Runnable() {
    +        boolean onCompleted = false;
    +        boolean onError = false;
    +        List> notifications = new Vector>();
     
             @Override
    -        public void run() {
    -          for (String s : valuesToReturn) {
    -            if (s == null) {
    -              System.out.println("throwing exception");
    -              try {
    -                Thread.sleep(100);
    -              } catch (Throwable e) {
    -
    -              }
    -              observer.onError(new NullPointerException());
    -              return;
    -            } else {
    -              observer.onNext(s);
    -            }
    -          }
    -          System.out.println("subscription complete");
    -          observer.onCompleted();
    +        public void onCompleted() {
    +            this.onCompleted = true;
             }
     
    -      });
    -      t.start();
    -
    -      return new Subscription() {
    +        @Override
    +        public void onError(Throwable e) {
    +            this.onError = true;
    +        }
     
             @Override
    -        public void unsubscribe() {
    +        public void onNext(Notification value) {
    +            this.notifications.add(value);
    +        }
     
    +    }
    +
    +    private static class TestAsyncErrorObservable implements Observable.OnSubscribeFunc {
    +
    +        String[] valuesToReturn;
    +
    +        TestAsyncErrorObservable(String... values) {
    +            valuesToReturn = values;
             }
     
    -      };
    +        volatile Thread t;
    +
    +        @Override
    +        public Subscription onSubscribe(final Observer observer) {
    +            t = new Thread(new Runnable() {
    +
    +                @Override
    +                public void run() {
    +                    for (String s : valuesToReturn) {
    +                        if (s == null) {
    +                            System.out.println("throwing exception");
    +                            try {
    +                                Thread.sleep(100);
    +                            } catch (Throwable e) {
    +
    +                            }
    +                            observer.onError(new NullPointerException());
    +                            return;
    +                        } else {
    +                            observer.onNext(s);
    +                        }
    +                    }
    +                    System.out.println("subscription complete");
    +                    observer.onCompleted();
    +                }
    +
    +            });
    +            t.start();
    +
    +            return new Subscription() {
    +
    +                @Override
    +                public void unsubscribe() {
    +
    +                }
    +
    +            };
    +        }
         }
    -  }
     }
    diff --git a/rxjava-core/src/test/java/rx/operators/OperationMergeDelayErrorTest.java b/rxjava-core/src/test/java/rx/operators/OperationMergeDelayErrorTest.java
    index 03dbcd7044..50ebda0bb3 100644
    --- a/rxjava-core/src/test/java/rx/operators/OperationMergeDelayErrorTest.java
    +++ b/rxjava-core/src/test/java/rx/operators/OperationMergeDelayErrorTest.java
    @@ -1,500 +1,500 @@
     package rx.operators;
     
    +import static org.junit.Assert.*;
    +import static org.mockito.Matchers.*;
    +import static org.mockito.Mockito.*;
    +import static rx.operators.OperationMergeDelayError.*;
    +
    +import java.util.ArrayList;
    +import java.util.List;
    +
     import org.junit.Before;
     import org.junit.Test;
     import org.mockito.Mock;
     import org.mockito.MockitoAnnotations;
    +
     import rx.Observable;
     import rx.Observer;
     import rx.Subscription;
     import rx.util.CompositeException;
     
    -import java.util.ArrayList;
    -import java.util.List;
    +public class OperationMergeDelayErrorTest {
     
    -import static org.junit.Assert.*;
    -import static org.mockito.Matchers.any;
    -import static org.mockito.Mockito.*;
    -import static rx.operators.OperationMergeDelayError.mergeDelayError;
    +    @Mock
    +    Observer stringObserver;
     
    -public class OperationMergeDelayErrorTest {
    +    @Before
    +    public void before() {
    +        MockitoAnnotations.initMocks(this);
    +    }
     
    +    @Test
    +    public void testErrorDelayed1() {
    +        final Observable o1 = Observable.create(new TestErrorObservable("four", null, "six")); // we expect to lose "six" from the source (and it should never be sent by the source since onError was called
    +        final Observable o2 = Observable.create(new TestErrorObservable("one", "two", "three"));
    +
    +        @SuppressWarnings("unchecked")
    +        Observable m = Observable.create(mergeDelayError(o1, o2));
    +        m.subscribe(stringObserver);
    +
    +        verify(stringObserver, times(1)).onError(any(NullPointerException.class));
    +        verify(stringObserver, never()).onCompleted();
    +        verify(stringObserver, times(1)).onNext("one");
    +        verify(stringObserver, times(1)).onNext("two");
    +        verify(stringObserver, times(1)).onNext("three");
    +        verify(stringObserver, times(1)).onNext("four");
    +        verify(stringObserver, times(0)).onNext("five");
    +        verify(stringObserver, times(0)).onNext("six");
    +    }
     
    -  @Mock
    -  Observer stringObserver;
    -
    -  @Before
    -  public void before() {
    -    MockitoAnnotations.initMocks(this);
    -  }
    -
    -  @Test
    -  public void testErrorDelayed1() {
    -    final Observable o1 = Observable.create(new TestErrorObservable("four", null, "six")); // we expect to lose "six" from the source (and it should never be sent by the source since onError was called
    -    final Observable o2 = Observable.create(new TestErrorObservable("one", "two", "three"));
    -
    -    @SuppressWarnings("unchecked")
    -    Observable m = Observable.create(mergeDelayError(o1, o2));
    -    m.subscribe(stringObserver);
    -
    -    verify(stringObserver, times(1)).onError(any(NullPointerException.class));
    -    verify(stringObserver, never()).onCompleted();
    -    verify(stringObserver, times(1)).onNext("one");
    -    verify(stringObserver, times(1)).onNext("two");
    -    verify(stringObserver, times(1)).onNext("three");
    -    verify(stringObserver, times(1)).onNext("four");
    -    verify(stringObserver, times(0)).onNext("five");
    -    verify(stringObserver, times(0)).onNext("six");
    -  }
    -
    -  @Test
    -  public void testErrorDelayed2() {
    -    final Observable o1 = Observable.create(new TestErrorObservable("one", "two", "three"));
    -    final Observable o2 = Observable.create(new TestErrorObservable("four", null, "six")); // we expect to lose "six" from the source (and it should never be sent by the source since onError was called
    -    final Observable o3 = Observable.create(new TestErrorObservable("seven", "eight", null));
    -    final Observable o4 = Observable.create(new TestErrorObservable("nine"));
    -
    -    @SuppressWarnings("unchecked")
    -    Observable m = Observable.create(mergeDelayError(o1, o2, o3, o4));
    -    m.subscribe(stringObserver);
    -
    -    verify(stringObserver, times(1)).onError(any(NullPointerException.class));
    -    verify(stringObserver, never()).onCompleted();
    -    verify(stringObserver, times(1)).onNext("one");
    -    verify(stringObserver, times(1)).onNext("two");
    -    verify(stringObserver, times(1)).onNext("three");
    -    verify(stringObserver, times(1)).onNext("four");
    -    verify(stringObserver, times(0)).onNext("five");
    -    verify(stringObserver, times(0)).onNext("six");
    -    verify(stringObserver, times(1)).onNext("seven");
    -    verify(stringObserver, times(1)).onNext("eight");
    -    verify(stringObserver, times(1)).onNext("nine");
    -  }
    -
    -  @Test
    -  public void testErrorDelayed3() {
    -    final Observable o1 = Observable.create(new TestErrorObservable("one", "two", "three"));
    -    final Observable o2 = Observable.create(new TestErrorObservable("four", "five", "six"));
    -    final Observable o3 = Observable.create(new TestErrorObservable("seven", "eight", null));
    -    final Observable o4 = Observable.create(new TestErrorObservable("nine"));
    -
    -    @SuppressWarnings("unchecked")
    -    Observable m = Observable.create(mergeDelayError(o1, o2, o3, o4));
    -    m.subscribe(stringObserver);
    -
    -    verify(stringObserver, times(1)).onError(any(NullPointerException.class));
    -    verify(stringObserver, never()).onCompleted();
    -    verify(stringObserver, times(1)).onNext("one");
    -    verify(stringObserver, times(1)).onNext("two");
    -    verify(stringObserver, times(1)).onNext("three");
    -    verify(stringObserver, times(1)).onNext("four");
    -    verify(stringObserver, times(1)).onNext("five");
    -    verify(stringObserver, times(1)).onNext("six");
    -    verify(stringObserver, times(1)).onNext("seven");
    -    verify(stringObserver, times(1)).onNext("eight");
    -    verify(stringObserver, times(1)).onNext("nine");
    -  }
    -
    -  @Test
    -  public void testErrorDelayed4() {
    -    final Observable o1 = Observable.create(new TestErrorObservable("one", "two", "three"));
    -    final Observable o2 = Observable.create(new TestErrorObservable("four", "five", "six"));
    -    final Observable o3 = Observable.create(new TestErrorObservable("seven", "eight"));
    -    final Observable o4 = Observable.create(new TestErrorObservable("nine", null));
    -
    -    @SuppressWarnings("unchecked")
    -    Observable m = Observable.create(mergeDelayError(o1, o2, o3, o4));
    -    m.subscribe(stringObserver);
    -
    -    verify(stringObserver, times(1)).onError(any(NullPointerException.class));
    -    verify(stringObserver, never()).onCompleted();
    -    verify(stringObserver, times(1)).onNext("one");
    -    verify(stringObserver, times(1)).onNext("two");
    -    verify(stringObserver, times(1)).onNext("three");
    -    verify(stringObserver, times(1)).onNext("four");
    -    verify(stringObserver, times(1)).onNext("five");
    -    verify(stringObserver, times(1)).onNext("six");
    -    verify(stringObserver, times(1)).onNext("seven");
    -    verify(stringObserver, times(1)).onNext("eight");
    -    verify(stringObserver, times(1)).onNext("nine");
    -  }
    -
    -  @Test
    -  public void testErrorDelayed4WithThreading() {
    -    final TestAsyncErrorObservable o1 = new TestAsyncErrorObservable("one", "two", "three");
    -    final TestAsyncErrorObservable o2 = new TestAsyncErrorObservable("four", "five", "six");
    -    final TestAsyncErrorObservable o3 = new TestAsyncErrorObservable("seven", "eight");
    -    // throw the error at the very end so no onComplete will be called after it
    -    final TestAsyncErrorObservable o4 = new TestAsyncErrorObservable("nine", null);
    -
    -    @SuppressWarnings("unchecked")
    -    Observable m = Observable.create(mergeDelayError(Observable.create(o1), Observable.create(o2), Observable.create(o3), Observable.create(o4)));
    -    m.subscribe(stringObserver);
    -
    -    try {
    -      o1.t.join();
    -      o2.t.join();
    -      o3.t.join();
    -      o4.t.join();
    -    } catch (InterruptedException e) {
    -      throw new RuntimeException(e);
    +    @Test
    +    public void testErrorDelayed2() {
    +        final Observable o1 = Observable.create(new TestErrorObservable("one", "two", "three"));
    +        final Observable o2 = Observable.create(new TestErrorObservable("four", null, "six")); // we expect to lose "six" from the source (and it should never be sent by the source since onError was called
    +        final Observable o3 = Observable.create(new TestErrorObservable("seven", "eight", null));
    +        final Observable o4 = Observable.create(new TestErrorObservable("nine"));
    +
    +        @SuppressWarnings("unchecked")
    +        Observable m = Observable.create(mergeDelayError(o1, o2, o3, o4));
    +        m.subscribe(stringObserver);
    +
    +        verify(stringObserver, times(1)).onError(any(NullPointerException.class));
    +        verify(stringObserver, never()).onCompleted();
    +        verify(stringObserver, times(1)).onNext("one");
    +        verify(stringObserver, times(1)).onNext("two");
    +        verify(stringObserver, times(1)).onNext("three");
    +        verify(stringObserver, times(1)).onNext("four");
    +        verify(stringObserver, times(0)).onNext("five");
    +        verify(stringObserver, times(0)).onNext("six");
    +        verify(stringObserver, times(1)).onNext("seven");
    +        verify(stringObserver, times(1)).onNext("eight");
    +        verify(stringObserver, times(1)).onNext("nine");
         }
     
    -    verify(stringObserver, times(1)).onError(any(NullPointerException.class));
    -    verify(stringObserver, never()).onCompleted();
    -    verify(stringObserver, times(1)).onNext("one");
    -    verify(stringObserver, times(1)).onNext("two");
    -    verify(stringObserver, times(1)).onNext("three");
    -    verify(stringObserver, times(1)).onNext("four");
    -    verify(stringObserver, times(1)).onNext("five");
    -    verify(stringObserver, times(1)).onNext("six");
    -    verify(stringObserver, times(1)).onNext("seven");
    -    verify(stringObserver, times(1)).onNext("eight");
    -    verify(stringObserver, times(1)).onNext("nine");
    -  }
    -
    -  @Test
    -  public void testCompositeErrorDelayed1() {
    -    final Observable o1 = Observable.create(new TestErrorObservable("four", null, "six")); // we expect to lose "six" from the source (and it should never be sent by the source since onError was called
    -    final Observable o2 = Observable.create(new TestErrorObservable("one", "two", null));
    -
    -    @SuppressWarnings("unchecked")
    -    Observable m = Observable.create(mergeDelayError(o1, o2));
    -    m.subscribe(stringObserver);
    -
    -    verify(stringObserver, times(1)).onError(any(CompositeException.class));
    -    verify(stringObserver, never()).onCompleted();
    -    verify(stringObserver, times(1)).onNext("one");
    -    verify(stringObserver, times(1)).onNext("two");
    -    verify(stringObserver, times(0)).onNext("three");
    -    verify(stringObserver, times(1)).onNext("four");
    -    verify(stringObserver, times(0)).onNext("five");
    -    verify(stringObserver, times(0)).onNext("six");
    -  }
    -
    -  @Test
    -  public void testCompositeErrorDelayed2() {
    -    final Observable o1 = Observable.create(new TestErrorObservable("four", null, "six")); // we expect to lose "six" from the source (and it should never be sent by the source since onError was called
    -    final Observable o2 = Observable.create(new TestErrorObservable("one", "two", null));
    -
    -    @SuppressWarnings("unchecked")
    -    Observable m = Observable.create(mergeDelayError(o1, o2));
    -    CaptureObserver w = new CaptureObserver();
    -    m.subscribe(w);
    -
    -    assertNotNull(w.e);
    -    if (w.e instanceof CompositeException) {
    -      assertEquals(2, ((CompositeException) w.e).getExceptions().size());
    -      w.e.printStackTrace();
    -    } else {
    -      fail("Expecting CompositeException");
    +    @Test
    +    public void testErrorDelayed3() {
    +        final Observable o1 = Observable.create(new TestErrorObservable("one", "two", "three"));
    +        final Observable o2 = Observable.create(new TestErrorObservable("four", "five", "six"));
    +        final Observable o3 = Observable.create(new TestErrorObservable("seven", "eight", null));
    +        final Observable o4 = Observable.create(new TestErrorObservable("nine"));
    +
    +        @SuppressWarnings("unchecked")
    +        Observable m = Observable.create(mergeDelayError(o1, o2, o3, o4));
    +        m.subscribe(stringObserver);
    +
    +        verify(stringObserver, times(1)).onError(any(NullPointerException.class));
    +        verify(stringObserver, never()).onCompleted();
    +        verify(stringObserver, times(1)).onNext("one");
    +        verify(stringObserver, times(1)).onNext("two");
    +        verify(stringObserver, times(1)).onNext("three");
    +        verify(stringObserver, times(1)).onNext("four");
    +        verify(stringObserver, times(1)).onNext("five");
    +        verify(stringObserver, times(1)).onNext("six");
    +        verify(stringObserver, times(1)).onNext("seven");
    +        verify(stringObserver, times(1)).onNext("eight");
    +        verify(stringObserver, times(1)).onNext("nine");
         }
     
    -  }
    +    @Test
    +    public void testErrorDelayed4() {
    +        final Observable o1 = Observable.create(new TestErrorObservable("one", "two", "three"));
    +        final Observable o2 = Observable.create(new TestErrorObservable("four", "five", "six"));
    +        final Observable o3 = Observable.create(new TestErrorObservable("seven", "eight"));
    +        final Observable o4 = Observable.create(new TestErrorObservable("nine", null));
    +
    +        @SuppressWarnings("unchecked")
    +        Observable m = Observable.create(mergeDelayError(o1, o2, o3, o4));
    +        m.subscribe(stringObserver);
    +
    +        verify(stringObserver, times(1)).onError(any(NullPointerException.class));
    +        verify(stringObserver, never()).onCompleted();
    +        verify(stringObserver, times(1)).onNext("one");
    +        verify(stringObserver, times(1)).onNext("two");
    +        verify(stringObserver, times(1)).onNext("three");
    +        verify(stringObserver, times(1)).onNext("four");
    +        verify(stringObserver, times(1)).onNext("five");
    +        verify(stringObserver, times(1)).onNext("six");
    +        verify(stringObserver, times(1)).onNext("seven");
    +        verify(stringObserver, times(1)).onNext("eight");
    +        verify(stringObserver, times(1)).onNext("nine");
    +    }
     
    -  /**
    -   * The unit tests below are from OperationMerge and should ensure the normal merge functionality is correct.
    -   */
    +    @Test
    +    public void testErrorDelayed4WithThreading() {
    +        final TestAsyncErrorObservable o1 = new TestAsyncErrorObservable("one", "two", "three");
    +        final TestAsyncErrorObservable o2 = new TestAsyncErrorObservable("four", "five", "six");
    +        final TestAsyncErrorObservable o3 = new TestAsyncErrorObservable("seven", "eight");
    +        // throw the error at the very end so no onComplete will be called after it
    +        final TestAsyncErrorObservable o4 = new TestAsyncErrorObservable("nine", null);
    +
    +        @SuppressWarnings("unchecked")
    +        Observable m = Observable.create(mergeDelayError(Observable.create(o1), Observable.create(o2), Observable.create(o3), Observable.create(o4)));
    +        m.subscribe(stringObserver);
    +
    +        try {
    +            o1.t.join();
    +            o2.t.join();
    +            o3.t.join();
    +            o4.t.join();
    +        } catch (InterruptedException e) {
    +            throw new RuntimeException(e);
    +        }
     
    -  @Test
    -  public void testMergeObservableOfObservables() {
    -    final Observable o1 = Observable.create(new TestSynchronousObservable());
    -    final Observable o2 = Observable.create(new TestSynchronousObservable());
    +        verify(stringObserver, times(1)).onError(any(NullPointerException.class));
    +        verify(stringObserver, never()).onCompleted();
    +        verify(stringObserver, times(1)).onNext("one");
    +        verify(stringObserver, times(1)).onNext("two");
    +        verify(stringObserver, times(1)).onNext("three");
    +        verify(stringObserver, times(1)).onNext("four");
    +        verify(stringObserver, times(1)).onNext("five");
    +        verify(stringObserver, times(1)).onNext("six");
    +        verify(stringObserver, times(1)).onNext("seven");
    +        verify(stringObserver, times(1)).onNext("eight");
    +        verify(stringObserver, times(1)).onNext("nine");
    +    }
     
    -    Observable> observableOfObservables = Observable.create(new Observable.OnSubscribeFunc>() {
    +    @Test
    +    public void testCompositeErrorDelayed1() {
    +        final Observable o1 = Observable.create(new TestErrorObservable("four", null, "six")); // we expect to lose "six" from the source (and it should never be sent by the source since onError was called
    +        final Observable o2 = Observable.create(new TestErrorObservable("one", "two", null));
    +
    +        @SuppressWarnings("unchecked")
    +        Observable m = Observable.create(mergeDelayError(o1, o2));
    +        m.subscribe(stringObserver);
    +
    +        verify(stringObserver, times(1)).onError(any(CompositeException.class));
    +        verify(stringObserver, never()).onCompleted();
    +        verify(stringObserver, times(1)).onNext("one");
    +        verify(stringObserver, times(1)).onNext("two");
    +        verify(stringObserver, times(0)).onNext("three");
    +        verify(stringObserver, times(1)).onNext("four");
    +        verify(stringObserver, times(0)).onNext("five");
    +        verify(stringObserver, times(0)).onNext("six");
    +    }
     
    -      @Override
    -      public Subscription onSubscribe(Observer> observer) {
    -        // simulate what would happen in an observable
    -        observer.onNext(o1);
    -        observer.onNext(o2);
    -        observer.onCompleted();
    +    @Test
    +    public void testCompositeErrorDelayed2() {
    +        final Observable o1 = Observable.create(new TestErrorObservable("four", null, "six")); // we expect to lose "six" from the source (and it should never be sent by the source since onError was called
    +        final Observable o2 = Observable.create(new TestErrorObservable("one", "two", null));
     
    -        return new Subscription() {
    +        @SuppressWarnings("unchecked")
    +        Observable m = Observable.create(mergeDelayError(o1, o2));
    +        CaptureObserver w = new CaptureObserver();
    +        m.subscribe(w);
     
    -          @Override
    -          public void unsubscribe() {
    -            // unregister ... will never be called here since we are executing synchronously
    -          }
    +        assertNotNull(w.e);
    +        if (w.e instanceof CompositeException) {
    +            assertEquals(2, ((CompositeException) w.e).getExceptions().size());
    +            w.e.printStackTrace();
    +        } else {
    +            fail("Expecting CompositeException");
    +        }
     
    -        };
    -      }
    -
    -    });
    -    Observable m = Observable.create(mergeDelayError(observableOfObservables));
    -    m.subscribe(stringObserver);
    -
    -    verify(stringObserver, never()).onError(any(Throwable.class));
    -    verify(stringObserver, times(1)).onCompleted();
    -    verify(stringObserver, times(2)).onNext("hello");
    -  }
    -
    -  @Test
    -  public void testMergeArray() {
    -    final Observable o1 = Observable.create(new TestSynchronousObservable());
    -    final Observable o2 = Observable.create(new TestSynchronousObservable());
    -
    -    @SuppressWarnings("unchecked")
    -    Observable m = Observable.create(mergeDelayError(o1, o2));
    -    m.subscribe(stringObserver);
    -
    -    verify(stringObserver, never()).onError(any(Throwable.class));
    -    verify(stringObserver, times(2)).onNext("hello");
    -    verify(stringObserver, times(1)).onCompleted();
    -  }
    -
    -  @Test
    -  public void testMergeList() {
    -    final Observable o1 = Observable.create(new TestSynchronousObservable());
    -    final Observable o2 = Observable.create(new TestSynchronousObservable());
    -    List> listOfObservables = new ArrayList>();
    -    listOfObservables.add(o1);
    -    listOfObservables.add(o2);
    -
    -    Observable m = Observable.create(mergeDelayError(listOfObservables));
    -    m.subscribe(stringObserver);
    -
    -    verify(stringObserver, never()).onError(any(Throwable.class));
    -    verify(stringObserver, times(1)).onCompleted();
    -    verify(stringObserver, times(2)).onNext("hello");
    -  }
    -
    -  @Test
    -  public void testUnSubscribe() {
    -    TestObservable tA = new TestObservable();
    -    TestObservable tB = new TestObservable();
    -
    -    @SuppressWarnings("unchecked")
    -    Observable m = Observable.create(mergeDelayError(Observable.create(tA), Observable.create(tB)));
    -    Subscription s = m.subscribe(stringObserver);
    -
    -    tA.sendOnNext("Aone");
    -    tB.sendOnNext("Bone");
    -    s.unsubscribe();
    -    tA.sendOnNext("Atwo");
    -    tB.sendOnNext("Btwo");
    -    tA.sendOnCompleted();
    -    tB.sendOnCompleted();
    -
    -    verify(stringObserver, never()).onError(any(Throwable.class));
    -    verify(stringObserver, times(1)).onNext("Aone");
    -    verify(stringObserver, times(1)).onNext("Bone");
    -    assertTrue(tA.unsubscribed);
    -    assertTrue(tB.unsubscribed);
    -    verify(stringObserver, never()).onNext("Atwo");
    -    verify(stringObserver, never()).onNext("Btwo");
    -    verify(stringObserver, never()).onCompleted();
    -  }
    -
    -  @Test
    -  public void testMergeArrayWithThreading() {
    -    final TestASynchronousObservable o1 = new TestASynchronousObservable();
    -    final TestASynchronousObservable o2 = new TestASynchronousObservable();
    -
    -    @SuppressWarnings("unchecked")
    -    Observable m = Observable.create(mergeDelayError(Observable.create(o1), Observable.create(o2)));
    -    m.subscribe(stringObserver);
    -
    -    try {
    -      o1.t.join();
    -      o2.t.join();
    -    } catch (InterruptedException e) {
    -      throw new RuntimeException(e);
         }
     
    -    verify(stringObserver, never()).onError(any(Throwable.class));
    -    verify(stringObserver, times(2)).onNext("hello");
    -    verify(stringObserver, times(1)).onCompleted();
    -  }
    +    /**
    +     * The unit tests below are from OperationMerge and should ensure the normal merge functionality is correct.
    +     */
     
    -  private static class TestSynchronousObservable implements Observable.OnSubscribeFunc {
    +    @Test
    +    public void testMergeObservableOfObservables() {
    +        final Observable o1 = Observable.create(new TestSynchronousObservable());
    +        final Observable o2 = Observable.create(new TestSynchronousObservable());
     
    -    @Override
    -    public Subscription onSubscribe(Observer observer) {
    +        Observable> observableOfObservables = Observable.create(new Observable.OnSubscribeFunc>() {
     
    -      observer.onNext("hello");
    -      observer.onCompleted();
    +            @Override
    +            public Subscription onSubscribe(Observer> observer) {
    +                // simulate what would happen in an observable
    +                observer.onNext(o1);
    +                observer.onNext(o2);
    +                observer.onCompleted();
     
    -      return new Subscription() {
    +                return new Subscription() {
     
    -        @Override
    -        public void unsubscribe() {
    -          // unregister ... will never be called here since we are executing synchronously
    -        }
    +                    @Override
    +                    public void unsubscribe() {
    +                        // unregister ... will never be called here since we are executing synchronously
    +                    }
    +
    +                };
    +            }
     
    -      };
    +        });
    +        Observable m = Observable.create(mergeDelayError(observableOfObservables));
    +        m.subscribe(stringObserver);
    +
    +        verify(stringObserver, never()).onError(any(Throwable.class));
    +        verify(stringObserver, times(1)).onCompleted();
    +        verify(stringObserver, times(2)).onNext("hello");
         }
    -  }
     
    -  private static class TestASynchronousObservable implements Observable.OnSubscribeFunc {
    -    Thread t;
    +    @Test
    +    public void testMergeArray() {
    +        final Observable o1 = Observable.create(new TestSynchronousObservable());
    +        final Observable o2 = Observable.create(new TestSynchronousObservable());
     
    -    @Override
    -    public Subscription onSubscribe(final Observer observer) {
    -      t = new Thread(new Runnable() {
    +        @SuppressWarnings("unchecked")
    +        Observable m = Observable.create(mergeDelayError(o1, o2));
    +        m.subscribe(stringObserver);
     
    -        @Override
    -        public void run() {
    -          observer.onNext("hello");
    -          observer.onCompleted();
    -        }
    +        verify(stringObserver, never()).onError(any(Throwable.class));
    +        verify(stringObserver, times(2)).onNext("hello");
    +        verify(stringObserver, times(1)).onCompleted();
    +    }
     
    -      });
    -      t.start();
    +    @Test
    +    public void testMergeList() {
    +        final Observable o1 = Observable.create(new TestSynchronousObservable());
    +        final Observable o2 = Observable.create(new TestSynchronousObservable());
    +        List> listOfObservables = new ArrayList>();
    +        listOfObservables.add(o1);
    +        listOfObservables.add(o2);
     
    -      return new Subscription() {
    +        Observable m = Observable.create(mergeDelayError(listOfObservables));
    +        m.subscribe(stringObserver);
     
    -        @Override
    -        public void unsubscribe() {
    +        verify(stringObserver, never()).onError(any(Throwable.class));
    +        verify(stringObserver, times(1)).onCompleted();
    +        verify(stringObserver, times(2)).onNext("hello");
    +    }
    +
    +    @Test
    +    public void testUnSubscribe() {
    +        TestObservable tA = new TestObservable();
    +        TestObservable tB = new TestObservable();
    +
    +        @SuppressWarnings("unchecked")
    +        Observable m = Observable.create(mergeDelayError(Observable.create(tA), Observable.create(tB)));
    +        Subscription s = m.subscribe(stringObserver);
    +
    +        tA.sendOnNext("Aone");
    +        tB.sendOnNext("Bone");
    +        s.unsubscribe();
    +        tA.sendOnNext("Atwo");
    +        tB.sendOnNext("Btwo");
    +        tA.sendOnCompleted();
    +        tB.sendOnCompleted();
    +
    +        verify(stringObserver, never()).onError(any(Throwable.class));
    +        verify(stringObserver, times(1)).onNext("Aone");
    +        verify(stringObserver, times(1)).onNext("Bone");
    +        assertTrue(tA.unsubscribed);
    +        assertTrue(tB.unsubscribed);
    +        verify(stringObserver, never()).onNext("Atwo");
    +        verify(stringObserver, never()).onNext("Btwo");
    +        verify(stringObserver, never()).onCompleted();
    +    }
    +
    +    @Test
    +    public void testMergeArrayWithThreading() {
    +        final TestASynchronousObservable o1 = new TestASynchronousObservable();
    +        final TestASynchronousObservable o2 = new TestASynchronousObservable();
    +
    +        @SuppressWarnings("unchecked")
    +        Observable m = Observable.create(mergeDelayError(Observable.create(o1), Observable.create(o2)));
    +        m.subscribe(stringObserver);
     
    +        try {
    +            o1.t.join();
    +            o2.t.join();
    +        } catch (InterruptedException e) {
    +            throw new RuntimeException(e);
             }
     
    -      };
    +        verify(stringObserver, never()).onError(any(Throwable.class));
    +        verify(stringObserver, times(2)).onNext("hello");
    +        verify(stringObserver, times(1)).onCompleted();
         }
    -  }
     
    -  /**
    -   * A Observable that doesn't do the right thing on UnSubscribe/Error/etc in that it will keep sending events down the pipe regardless of what happens.
    -   */
    -  private static class TestObservable implements Observable.OnSubscribeFunc {
    +    private static class TestSynchronousObservable implements Observable.OnSubscribeFunc {
     
    -    Observer observer = null;
    -    volatile boolean unsubscribed = false;
    -    Subscription s = new Subscription() {
    +        @Override
    +        public Subscription onSubscribe(Observer observer) {
     
    -      @Override
    -      public void unsubscribe() {
    -        unsubscribed = true;
    +            observer.onNext("hello");
    +            observer.onCompleted();
     
    -      }
    +            return new Subscription() {
     
    -    };
    +                @Override
    +                public void unsubscribe() {
    +                    // unregister ... will never be called here since we are executing synchronously
    +                }
     
    -    /* used to simulate subscription */
    -    public void sendOnCompleted() {
    -      observer.onCompleted();
    +            };
    +        }
         }
     
    -    /* used to simulate subscription */
    -    public void sendOnNext(String value) {
    -      observer.onNext(value);
    -    }
    +    private static class TestASynchronousObservable implements Observable.OnSubscribeFunc {
    +        Thread t;
     
    -    /* used to simulate subscription */
    -    @SuppressWarnings("unused")
    -    public void sendOnError(Throwable e) {
    -      observer.onError(e);
    -    }
    +        @Override
    +        public Subscription onSubscribe(final Observer observer) {
    +            t = new Thread(new Runnable() {
     
    -    @Override
    -    public Subscription onSubscribe(final Observer observer) {
    -      this.observer = observer;
    -      return s;
    -    }
    -  }
    +                @Override
    +                public void run() {
    +                    observer.onNext("hello");
    +                    observer.onCompleted();
    +                }
     
    -  private static class TestErrorObservable implements Observable.OnSubscribeFunc {
    +            });
    +            t.start();
     
    -    String[] valuesToReturn;
    +            return new Subscription() {
     
    -    TestErrorObservable(String... values) {
    -      valuesToReturn = values;
    -    }
    +                @Override
    +                public void unsubscribe() {
     
    -    @Override
    -    public Subscription onSubscribe(Observer observer) {
    -      boolean errorThrown = false;
    -      for (String s : valuesToReturn) {
    -        if (s == null) {
    -          System.out.println("throwing exception");
    -          observer.onError(new NullPointerException());
    -          errorThrown = true;
    -          // purposefully not returning here so it will continue calling onNext
    -          // so that we also test that we handle bad sequences like this
    -        } else {
    -          observer.onNext(s);
    +                }
    +
    +            };
             }
    -      }
    -      if (!errorThrown) {
    -        observer.onCompleted();
    -      }
    +    }
     
    -      return new Subscription() {
    +    /**
    +     * A Observable that doesn't do the right thing on UnSubscribe/Error/etc in that it will keep sending events down the pipe regardless of what happens.
    +     */
    +    private static class TestObservable implements Observable.OnSubscribeFunc {
     
    -        @Override
    -        public void unsubscribe() {
    -          // unregister ... will never be called here since we are executing synchronously
    -        }
    +        Observer observer = null;
    +        volatile boolean unsubscribed = false;
    +        Subscription s = new Subscription() {
     
    -      };
    -    }
    -  }
    +            @Override
    +            public void unsubscribe() {
    +                unsubscribed = true;
     
    -  private static class TestAsyncErrorObservable implements Observable.OnSubscribeFunc {
    +            }
     
    -    String[] valuesToReturn;
    +        };
     
    -    TestAsyncErrorObservable(String... values) {
    -      valuesToReturn = values;
    -    }
    +        /* used to simulate subscription */
    +        public void sendOnCompleted() {
    +            observer.onCompleted();
    +        }
     
    -    Thread t;
    +        /* used to simulate subscription */
    +        public void sendOnNext(String value) {
    +            observer.onNext(value);
    +        }
     
    -    @Override
    -    public Subscription onSubscribe(final Observer observer) {
    -      t = new Thread(new Runnable() {
    +        /* used to simulate subscription */
    +        @SuppressWarnings("unused")
    +        public void sendOnError(Throwable e) {
    +            observer.onError(e);
    +        }
     
             @Override
    -        public void run() {
    -          for (String s : valuesToReturn) {
    -            if (s == null) {
    -              System.out.println("throwing exception");
    -              try {
    -                Thread.sleep(100);
    -              } catch (Throwable e) {
    -
    -              }
    -              observer.onError(new NullPointerException());
    -              return;
    -            } else {
    -              observer.onNext(s);
    -            }
    -          }
    -          System.out.println("subscription complete");
    -          observer.onCompleted();
    +        public Subscription onSubscribe(final Observer observer) {
    +            this.observer = observer;
    +            return s;
             }
    +    }
    +
    +    private static class TestErrorObservable implements Observable.OnSubscribeFunc {
     
    -      });
    -      t.start();
    +        String[] valuesToReturn;
     
    -      return new Subscription() {
    +        TestErrorObservable(String... values) {
    +            valuesToReturn = values;
    +        }
     
             @Override
    -        public void unsubscribe() {
    +        public Subscription onSubscribe(Observer observer) {
    +            boolean errorThrown = false;
    +            for (String s : valuesToReturn) {
    +                if (s == null) {
    +                    System.out.println("throwing exception");
    +                    observer.onError(new NullPointerException());
    +                    errorThrown = true;
    +                    // purposefully not returning here so it will continue calling onNext
    +                    // so that we also test that we handle bad sequences like this
    +                } else {
    +                    observer.onNext(s);
    +                }
    +            }
    +            if (!errorThrown) {
    +                observer.onCompleted();
    +            }
     
    -        }
    +            return new Subscription() {
    +
    +                @Override
    +                public void unsubscribe() {
    +                    // unregister ... will never be called here since we are executing synchronously
    +                }
     
    -      };
    +            };
    +        }
         }
    -  }
     
    -  private static class CaptureObserver implements Observer {
    -    volatile Throwable e;
    +    private static class TestAsyncErrorObservable implements Observable.OnSubscribeFunc {
     
    -    @Override
    -    public void onCompleted() {
    +        String[] valuesToReturn;
     
    -    }
    +        TestAsyncErrorObservable(String... values) {
    +            valuesToReturn = values;
    +        }
     
    -    @Override
    -    public void onError(Throwable e) {
    -      this.e = e;
    +        Thread t;
    +
    +        @Override
    +        public Subscription onSubscribe(final Observer observer) {
    +            t = new Thread(new Runnable() {
    +
    +                @Override
    +                public void run() {
    +                    for (String s : valuesToReturn) {
    +                        if (s == null) {
    +                            System.out.println("throwing exception");
    +                            try {
    +                                Thread.sleep(100);
    +                            } catch (Throwable e) {
    +
    +                            }
    +                            observer.onError(new NullPointerException());
    +                            return;
    +                        } else {
    +                            observer.onNext(s);
    +                        }
    +                    }
    +                    System.out.println("subscription complete");
    +                    observer.onCompleted();
    +                }
    +
    +            });
    +            t.start();
    +
    +            return new Subscription() {
    +
    +                @Override
    +                public void unsubscribe() {
    +
    +                }
    +
    +            };
    +        }
         }
     
    -    @Override
    -    public void onNext(String args) {
    +    private static class CaptureObserver implements Observer {
    +        volatile Throwable e;
     
    -    }
    +        @Override
    +        public void onCompleted() {
     
    -  }
    +        }
    +
    +        @Override
    +        public void onError(Throwable e) {
    +            this.e = e;
    +        }
    +
    +        @Override
    +        public void onNext(String args) {
    +
    +        }
    +
    +    }
     }
    diff --git a/rxjava-core/src/test/java/rx/operators/OperationMergeTest.java b/rxjava-core/src/test/java/rx/operators/OperationMergeTest.java
    index b3bdf1423c..d7d399486e 100644
    --- a/rxjava-core/src/test/java/rx/operators/OperationMergeTest.java
    +++ b/rxjava-core/src/test/java/rx/operators/OperationMergeTest.java
    @@ -1,9 +1,22 @@
     package rx.operators;
     
    +import static org.junit.Assert.*;
    +import static org.mockito.Matchers.*;
    +import static org.mockito.Mockito.*;
    +import static rx.operators.OperationMerge.*;
    +
    +import java.util.ArrayList;
    +import java.util.List;
    +import java.util.concurrent.CountDownLatch;
    +import java.util.concurrent.TimeUnit;
    +import java.util.concurrent.atomic.AtomicBoolean;
    +import java.util.concurrent.atomic.AtomicInteger;
    +
     import org.junit.Before;
     import org.junit.Test;
     import org.mockito.Mock;
     import org.mockito.MockitoAnnotations;
    +
     import rx.Observable;
     import rx.Observer;
     import rx.Subscription;
    @@ -11,448 +24,436 @@
     import rx.util.functions.Action0;
     import rx.util.functions.Action1;
     
    -import java.util.ArrayList;
    -import java.util.List;
    -import java.util.concurrent.CountDownLatch;
    -import java.util.concurrent.TimeUnit;
    -import java.util.concurrent.atomic.AtomicBoolean;
    -import java.util.concurrent.atomic.AtomicInteger;
    -
    -import static org.junit.Assert.*;
    -import static org.mockito.Matchers.any;
    -import static org.mockito.Mockito.*;
    -import static rx.operators.OperationMerge.merge;
    -
     public class OperationMergeTest {
     
    -  @Mock
    -  Observer stringObserver;
    +    @Mock
    +    Observer stringObserver;
     
    -  @Before
    -  public void before() {
    -    MockitoAnnotations.initMocks(this);
    -  }
    +    @Before
    +    public void before() {
    +        MockitoAnnotations.initMocks(this);
    +    }
     
    -  @Test
    -  public void testMergeObservableOfObservables() {
    -    final Observable o1 = Observable.create(new TestSynchronousObservable());
    -    final Observable o2 = Observable.create(new TestSynchronousObservable());
    +    @Test
    +    public void testMergeObservableOfObservables() {
    +        final Observable o1 = Observable.create(new TestSynchronousObservable());
    +        final Observable o2 = Observable.create(new TestSynchronousObservable());
     
    -    Observable> observableOfObservables = Observable.create(new Observable.OnSubscribeFunc>() {
    +        Observable> observableOfObservables = Observable.create(new Observable.OnSubscribeFunc>() {
     
    -      @Override
    -      public Subscription onSubscribe(Observer> observer) {
    -        // simulate what would happen in an observable
    -        observer.onNext(o1);
    -        observer.onNext(o2);
    -        observer.onCompleted();
    +            @Override
    +            public Subscription onSubscribe(Observer> observer) {
    +                // simulate what would happen in an observable
    +                observer.onNext(o1);
    +                observer.onNext(o2);
    +                observer.onCompleted();
     
    -        return new Subscription() {
    +                return new Subscription() {
     
    -          @Override
    -          public void unsubscribe() {
    -            // unregister ... will never be called here since we are executing synchronously
    -          }
    +                    @Override
    +                    public void unsubscribe() {
    +                        // unregister ... will never be called here since we are executing synchronously
    +                    }
     
    -        };
    -      }
    -
    -    });
    -    Observable m = Observable.create(merge(observableOfObservables));
    -    m.subscribe(stringObserver);
    -
    -    verify(stringObserver, never()).onError(any(Throwable.class));
    -    verify(stringObserver, times(1)).onCompleted();
    -    verify(stringObserver, times(2)).onNext("hello");
    -  }
    -
    -  @Test
    -  public void testMergeArray() {
    -    final Observable o1 = Observable.create(new TestSynchronousObservable());
    -    final Observable o2 = Observable.create(new TestSynchronousObservable());
    -
    -    @SuppressWarnings("unchecked")
    -    Observable m = Observable.create(merge(o1, o2));
    -    m.subscribe(stringObserver);
    -
    -    verify(stringObserver, never()).onError(any(Throwable.class));
    -    verify(stringObserver, times(2)).onNext("hello");
    -    verify(stringObserver, times(1)).onCompleted();
    -  }
    -
    -  @Test
    -  public void testMergeList() {
    -    final Observable o1 = Observable.create(new TestSynchronousObservable());
    -    final Observable o2 = Observable.create(new TestSynchronousObservable());
    -    List> listOfObservables = new ArrayList>();
    -    listOfObservables.add(o1);
    -    listOfObservables.add(o2);
    -
    -    Observable m = Observable.create(merge(listOfObservables));
    -    m.subscribe(stringObserver);
    -
    -    verify(stringObserver, never()).onError(any(Throwable.class));
    -    verify(stringObserver, times(1)).onCompleted();
    -    verify(stringObserver, times(2)).onNext("hello");
    -  }
    -
    -  @Test
    -  public void testUnSubscribe() {
    -    TestObservable tA = new TestObservable();
    -    TestObservable tB = new TestObservable();
    -
    -    @SuppressWarnings("unchecked")
    -    Observable m = Observable.create(merge(Observable.create(tA), Observable.create(tB)));
    -    Subscription s = m.subscribe(stringObserver);
    -
    -    tA.sendOnNext("Aone");
    -    tB.sendOnNext("Bone");
    -    s.unsubscribe();
    -    tA.sendOnNext("Atwo");
    -    tB.sendOnNext("Btwo");
    -    tA.sendOnCompleted();
    -    tB.sendOnCompleted();
    -
    -    verify(stringObserver, never()).onError(any(Throwable.class));
    -    verify(stringObserver, times(1)).onNext("Aone");
    -    verify(stringObserver, times(1)).onNext("Bone");
    -    assertTrue(tA.unsubscribed);
    -    assertTrue(tB.unsubscribed);
    -    verify(stringObserver, never()).onNext("Atwo");
    -    verify(stringObserver, never()).onNext("Btwo");
    -    verify(stringObserver, never()).onCompleted();
    -  }
    -
    -  @Test
    -  public void testUnSubscribeObservableOfObservables() throws InterruptedException {
    -
    -    final AtomicBoolean unsubscribed = new AtomicBoolean();
    -    final CountDownLatch latch = new CountDownLatch(1);
    -
    -    Observable> source = Observable.create(new Observable.OnSubscribeFunc>() {
    -
    -      @Override
    -      public Subscription onSubscribe(final Observer> observer) {
    -        // verbose on purpose so I can track the inside of it
    -        final Subscription s = Subscriptions.create(new Action0() {
    -
    -          @Override
    -          public void call() {
    -            System.out.println("*** unsubscribed");
    -            unsubscribed.set(true);
    -          }
    +                };
    +            }
     
             });
    +        Observable m = Observable.create(merge(observableOfObservables));
    +        m.subscribe(stringObserver);
     
    -        new Thread(new Runnable() {
    +        verify(stringObserver, never()).onError(any(Throwable.class));
    +        verify(stringObserver, times(1)).onCompleted();
    +        verify(stringObserver, times(2)).onNext("hello");
    +    }
     
    -          @Override
    -          public void run() {
    +    @Test
    +    public void testMergeArray() {
    +        final Observable o1 = Observable.create(new TestSynchronousObservable());
    +        final Observable o2 = Observable.create(new TestSynchronousObservable());
     
    -            while (!unsubscribed.get()) {
    -              observer.onNext(Observable.from(1L, 2L));
    -            }
    -            System.out.println("Done looping after unsubscribe: " + unsubscribed.get());
    -            observer.onCompleted();
    +        @SuppressWarnings("unchecked")
    +        Observable m = Observable.create(merge(o1, o2));
    +        m.subscribe(stringObserver);
     
    -            // mark that the thread is finished
    -            latch.countDown();
    -          }
    -        }).start();
    +        verify(stringObserver, never()).onError(any(Throwable.class));
    +        verify(stringObserver, times(2)).onNext("hello");
    +        verify(stringObserver, times(1)).onCompleted();
    +    }
     
    -        return s;
    -      }
    +    @Test
    +    public void testMergeList() {
    +        final Observable o1 = Observable.create(new TestSynchronousObservable());
    +        final Observable o2 = Observable.create(new TestSynchronousObservable());
    +        List> listOfObservables = new ArrayList>();
    +        listOfObservables.add(o1);
    +        listOfObservables.add(o2);
     
    -      ;
    +        Observable m = Observable.create(merge(listOfObservables));
    +        m.subscribe(stringObserver);
     
    -    });
    +        verify(stringObserver, never()).onError(any(Throwable.class));
    +        verify(stringObserver, times(1)).onCompleted();
    +        verify(stringObserver, times(2)).onNext("hello");
    +    }
     
    -    final AtomicInteger count = new AtomicInteger();
    -    Observable.create(merge(source)).take(6).toBlockingObservable().forEach(new Action1() {
    +    @Test
    +    public void testUnSubscribe() {
    +        TestObservable tA = new TestObservable();
    +        TestObservable tB = new TestObservable();
    +
    +        @SuppressWarnings("unchecked")
    +        Observable m = Observable.create(merge(Observable.create(tA), Observable.create(tB)));
    +        Subscription s = m.subscribe(stringObserver);
    +
    +        tA.sendOnNext("Aone");
    +        tB.sendOnNext("Bone");
    +        s.unsubscribe();
    +        tA.sendOnNext("Atwo");
    +        tB.sendOnNext("Btwo");
    +        tA.sendOnCompleted();
    +        tB.sendOnCompleted();
    +
    +        verify(stringObserver, never()).onError(any(Throwable.class));
    +        verify(stringObserver, times(1)).onNext("Aone");
    +        verify(stringObserver, times(1)).onNext("Bone");
    +        assertTrue(tA.unsubscribed);
    +        assertTrue(tB.unsubscribed);
    +        verify(stringObserver, never()).onNext("Atwo");
    +        verify(stringObserver, never()).onNext("Btwo");
    +        verify(stringObserver, never()).onCompleted();
    +    }
     
    -      @Override
    -      public void call(Long v) {
    -        System.out.println("Value: " + v);
    -        int c = count.incrementAndGet();
    -        if (c > 6) {
    -          fail("Should be only 6");
    -        }
    +    @Test
    +    public void testUnSubscribeObservableOfObservables() throws InterruptedException {
     
    -      }
    -    });
    +        final AtomicBoolean unsubscribed = new AtomicBoolean();
    +        final CountDownLatch latch = new CountDownLatch(1);
     
    -    latch.await(1000, TimeUnit.MILLISECONDS);
    +        Observable> source = Observable.create(new Observable.OnSubscribeFunc>() {
     
    -    System.out.println("unsubscribed: " + unsubscribed.get());
    +            @Override
    +            public Subscription onSubscribe(final Observer> observer) {
    +                // verbose on purpose so I can track the inside of it
    +                final Subscription s = Subscriptions.create(new Action0() {
     
    -    assertTrue(unsubscribed.get());
    +                    @Override
    +                    public void call() {
    +                        System.out.println("*** unsubscribed");
    +                        unsubscribed.set(true);
    +                    }
     
    -  }
    +                });
     
    -  @Test
    -  public void testMergeArrayWithThreading() {
    -    final TestASynchronousObservable o1 = new TestASynchronousObservable();
    -    final TestASynchronousObservable o2 = new TestASynchronousObservable();
    +                new Thread(new Runnable() {
     
    -    @SuppressWarnings("unchecked")
    -    Observable m = Observable.create(merge(Observable.create(o1), Observable.create(o2)));
    -    m.subscribe(stringObserver);
    +                    @Override
    +                    public void run() {
     
    -    try {
    -      o1.t.join();
    -      o2.t.join();
    -    } catch (InterruptedException e) {
    -      throw new RuntimeException(e);
    -    }
    +                        while (!unsubscribed.get()) {
    +                            observer.onNext(Observable.from(1L, 2L));
    +                        }
    +                        System.out.println("Done looping after unsubscribe: " + unsubscribed.get());
    +                        observer.onCompleted();
     
    -    verify(stringObserver, never()).onError(any(Throwable.class));
    -    verify(stringObserver, times(2)).onNext("hello");
    -    verify(stringObserver, times(1)).onCompleted();
    -  }
    +                        // mark that the thread is finished
    +                        latch.countDown();
    +                    }
    +                }).start();
     
    -  @Test
    -  public void testSynchronizationOfMultipleSequences() throws Throwable {
    -    final TestASynchronousObservable o1 = new TestASynchronousObservable();
    -    final TestASynchronousObservable o2 = new TestASynchronousObservable();
    +                return s;
    +            }
     
    -    // use this latch to cause onNext to wait until we're ready to let it go
    -    final CountDownLatch endLatch = new CountDownLatch(1);
    +            ;
     
    -    final AtomicInteger concurrentCounter = new AtomicInteger();
    -    final AtomicInteger totalCounter = new AtomicInteger();
    +        });
     
    -    @SuppressWarnings("unchecked")
    -    Observable m = Observable.create(merge(Observable.create(o1), Observable.create(o2)));
    -    m.subscribe(new Observer() {
    +        final AtomicInteger count = new AtomicInteger();
    +        Observable.create(merge(source)).take(6).toBlockingObservable().forEach(new Action1() {
     
    -      @Override
    -      public void onCompleted() {
    +            @Override
    +            public void call(Long v) {
    +                System.out.println("Value: " + v);
    +                int c = count.incrementAndGet();
    +                if (c > 6) {
    +                    fail("Should be only 6");
    +                }
     
    -      }
    +            }
    +        });
     
    -      @Override
    -      public void onError(Throwable e) {
    -        throw new RuntimeException("failed", e);
    -      }
    +        latch.await(1000, TimeUnit.MILLISECONDS);
    +
    +        System.out.println("unsubscribed: " + unsubscribed.get());
    +
    +        assertTrue(unsubscribed.get());
    +
    +    }
    +
    +    @Test
    +    public void testMergeArrayWithThreading() {
    +        final TestASynchronousObservable o1 = new TestASynchronousObservable();
    +        final TestASynchronousObservable o2 = new TestASynchronousObservable();
    +
    +        @SuppressWarnings("unchecked")
    +        Observable m = Observable.create(merge(Observable.create(o1), Observable.create(o2)));
    +        m.subscribe(stringObserver);
     
    -      @Override
    -      public void onNext(String v) {
    -        totalCounter.incrementAndGet();
    -        concurrentCounter.incrementAndGet();
             try {
    -          // wait here until we're done asserting
    -          endLatch.await();
    +            o1.t.join();
    +            o2.t.join();
             } catch (InterruptedException e) {
    -          e.printStackTrace();
    -          throw new RuntimeException("failed", e);
    -        } finally {
    -          concurrentCounter.decrementAndGet();
    +            throw new RuntimeException(e);
             }
    -      }
     
    -    });
    +        verify(stringObserver, never()).onError(any(Throwable.class));
    +        verify(stringObserver, times(2)).onNext("hello");
    +        verify(stringObserver, times(1)).onCompleted();
    +    }
     
    -    // wait for both observables to send (one should be blocked)
    -    o1.onNextBeingSent.await();
    -    o2.onNextBeingSent.await();
    +    @Test
    +    public void testSynchronizationOfMultipleSequences() throws Throwable {
    +        final TestASynchronousObservable o1 = new TestASynchronousObservable();
    +        final TestASynchronousObservable o2 = new TestASynchronousObservable();
     
    -    // I can't think of a way to know for sure that both threads have or are trying to send onNext
    -    // since I can't use a CountDownLatch for "after" onNext since I want to catch during it
    -    // but I can't know for sure onNext is invoked
    -    // so I'm unfortunately reverting to using a Thread.sleep to allow the process scheduler time
    -    // to make sure after o1.onNextBeingSent and o2.onNextBeingSent are hit that the following
    -    // onNext is invoked.
    +        // use this latch to cause onNext to wait until we're ready to let it go
    +        final CountDownLatch endLatch = new CountDownLatch(1);
     
    -    Thread.sleep(300);
    +        final AtomicInteger concurrentCounter = new AtomicInteger();
    +        final AtomicInteger totalCounter = new AtomicInteger();
     
    -    try { // in try/finally so threads are released via latch countDown even if assertion fails
    -      assertEquals(1, concurrentCounter.get());
    -    } finally {
    -      // release so it can finish
    -      endLatch.countDown();
    -    }
    +        @SuppressWarnings("unchecked")
    +        Observable m = Observable.create(merge(Observable.create(o1), Observable.create(o2)));
    +        m.subscribe(new Observer() {
     
    -    try {
    -      o1.t.join();
    -      o2.t.join();
    -    } catch (InterruptedException e) {
    -      throw new RuntimeException(e);
    -    }
    +            @Override
    +            public void onCompleted() {
     
    -    assertEquals(2, totalCounter.get());
    -    assertEquals(0, concurrentCounter.get());
    -  }
    -
    -  /**
    -   * unit test from OperationMergeDelayError backported here to show how these use cases work with normal merge
    -   */
    -  @Test
    -  public void testError1() {
    -    // we are using synchronous execution to test this exactly rather than non-deterministic concurrent behavior
    -    final Observable o1 = Observable.create(new TestErrorObservable("four", null, "six")); // we expect to lose "six"
    -    final Observable o2 = Observable.create(new TestErrorObservable("one", "two", "three")); // we expect to lose all of these since o1 is done first and fails
    -
    -    @SuppressWarnings("unchecked")
    -    Observable m = Observable.create(merge(o1, o2));
    -    m.subscribe(stringObserver);
    -
    -    verify(stringObserver, times(1)).onError(any(NullPointerException.class));
    -    verify(stringObserver, never()).onCompleted();
    -    verify(stringObserver, times(0)).onNext("one");
    -    verify(stringObserver, times(0)).onNext("two");
    -    verify(stringObserver, times(0)).onNext("three");
    -    verify(stringObserver, times(1)).onNext("four");
    -    verify(stringObserver, times(0)).onNext("five");
    -    verify(stringObserver, times(0)).onNext("six");
    -  }
    -
    -  /**
    -   * unit test from OperationMergeDelayError backported here to show how these use cases work with normal merge
    -   */
    -  @Test
    -  public void testError2() {
    -    // we are using synchronous execution to test this exactly rather than non-deterministic concurrent behavior
    -    final Observable o1 = Observable.create(new TestErrorObservable("one", "two", "three"));
    -    final Observable o2 = Observable.create(new TestErrorObservable("four", null, "six")); // we expect to lose "six"
    -    final Observable o3 = Observable.create(new TestErrorObservable("seven", "eight", null));// we expect to lose all of these since o2 is done first and fails
    -    final Observable o4 = Observable.create(new TestErrorObservable("nine"));// we expect to lose all of these since o2 is done first and fails
    -
    -    @SuppressWarnings("unchecked")
    -    Observable m = Observable.create(merge(o1, o2, o3, o4));
    -    m.subscribe(stringObserver);
    -
    -    verify(stringObserver, times(1)).onError(any(NullPointerException.class));
    -    verify(stringObserver, never()).onCompleted();
    -    verify(stringObserver, times(1)).onNext("one");
    -    verify(stringObserver, times(1)).onNext("two");
    -    verify(stringObserver, times(1)).onNext("three");
    -    verify(stringObserver, times(1)).onNext("four");
    -    verify(stringObserver, times(0)).onNext("five");
    -    verify(stringObserver, times(0)).onNext("six");
    -    verify(stringObserver, times(0)).onNext("seven");
    -    verify(stringObserver, times(0)).onNext("eight");
    -    verify(stringObserver, times(0)).onNext("nine");
    -  }
    -
    -  private static class TestSynchronousObservable implements Observable.OnSubscribeFunc {
    -
    -    @Override
    -    public Subscription onSubscribe(Observer observer) {
    -
    -      observer.onNext("hello");
    -      observer.onCompleted();
    -
    -      return new Subscription() {
    +            }
     
    -        @Override
    -        public void unsubscribe() {
    -          // unregister ... will never be called here since we are executing synchronously
    +            @Override
    +            public void onError(Throwable e) {
    +                throw new RuntimeException("failed", e);
    +            }
    +
    +            @Override
    +            public void onNext(String v) {
    +                totalCounter.incrementAndGet();
    +                concurrentCounter.incrementAndGet();
    +                try {
    +                    // wait here until we're done asserting
    +                    endLatch.await();
    +                } catch (InterruptedException e) {
    +                    e.printStackTrace();
    +                    throw new RuntimeException("failed", e);
    +                } finally {
    +                    concurrentCounter.decrementAndGet();
    +                }
    +            }
    +
    +        });
    +
    +        // wait for both observables to send (one should be blocked)
    +        o1.onNextBeingSent.await();
    +        o2.onNextBeingSent.await();
    +
    +        // I can't think of a way to know for sure that both threads have or are trying to send onNext
    +        // since I can't use a CountDownLatch for "after" onNext since I want to catch during it
    +        // but I can't know for sure onNext is invoked
    +        // so I'm unfortunately reverting to using a Thread.sleep to allow the process scheduler time
    +        // to make sure after o1.onNextBeingSent and o2.onNextBeingSent are hit that the following
    +        // onNext is invoked.
    +
    +        Thread.sleep(300);
    +
    +        try { // in try/finally so threads are released via latch countDown even if assertion fails
    +            assertEquals(1, concurrentCounter.get());
    +        } finally {
    +            // release so it can finish
    +            endLatch.countDown();
             }
     
    -      };
    +        try {
    +            o1.t.join();
    +            o2.t.join();
    +        } catch (InterruptedException e) {
    +            throw new RuntimeException(e);
    +        }
    +
    +        assertEquals(2, totalCounter.get());
    +        assertEquals(0, concurrentCounter.get());
         }
    -  }
     
    -  private static class TestASynchronousObservable implements Observable.OnSubscribeFunc {
    -    Thread t;
    -    final CountDownLatch onNextBeingSent = new CountDownLatch(1);
    +    /**
    +     * unit test from OperationMergeDelayError backported here to show how these use cases work with normal merge
    +     */
    +    @Test
    +    public void testError1() {
    +        // we are using synchronous execution to test this exactly rather than non-deterministic concurrent behavior
    +        final Observable o1 = Observable.create(new TestErrorObservable("four", null, "six")); // we expect to lose "six"
    +        final Observable o2 = Observable.create(new TestErrorObservable("one", "two", "three")); // we expect to lose all of these since o1 is done first and fails
    +
    +        @SuppressWarnings("unchecked")
    +        Observable m = Observable.create(merge(o1, o2));
    +        m.subscribe(stringObserver);
    +
    +        verify(stringObserver, times(1)).onError(any(NullPointerException.class));
    +        verify(stringObserver, never()).onCompleted();
    +        verify(stringObserver, times(0)).onNext("one");
    +        verify(stringObserver, times(0)).onNext("two");
    +        verify(stringObserver, times(0)).onNext("three");
    +        verify(stringObserver, times(1)).onNext("four");
    +        verify(stringObserver, times(0)).onNext("five");
    +        verify(stringObserver, times(0)).onNext("six");
    +    }
    +
    +    /**
    +     * unit test from OperationMergeDelayError backported here to show how these use cases work with normal merge
    +     */
    +    @Test
    +    public void testError2() {
    +        // we are using synchronous execution to test this exactly rather than non-deterministic concurrent behavior
    +        final Observable o1 = Observable.create(new TestErrorObservable("one", "two", "three"));
    +        final Observable o2 = Observable.create(new TestErrorObservable("four", null, "six")); // we expect to lose "six"
    +        final Observable o3 = Observable.create(new TestErrorObservable("seven", "eight", null));// we expect to lose all of these since o2 is done first and fails
    +        final Observable o4 = Observable.create(new TestErrorObservable("nine"));// we expect to lose all of these since o2 is done first and fails
    +
    +        @SuppressWarnings("unchecked")
    +        Observable m = Observable.create(merge(o1, o2, o3, o4));
    +        m.subscribe(stringObserver);
    +
    +        verify(stringObserver, times(1)).onError(any(NullPointerException.class));
    +        verify(stringObserver, never()).onCompleted();
    +        verify(stringObserver, times(1)).onNext("one");
    +        verify(stringObserver, times(1)).onNext("two");
    +        verify(stringObserver, times(1)).onNext("three");
    +        verify(stringObserver, times(1)).onNext("four");
    +        verify(stringObserver, times(0)).onNext("five");
    +        verify(stringObserver, times(0)).onNext("six");
    +        verify(stringObserver, times(0)).onNext("seven");
    +        verify(stringObserver, times(0)).onNext("eight");
    +        verify(stringObserver, times(0)).onNext("nine");
    +    }
     
    -    @Override
    -    public Subscription onSubscribe(final Observer observer) {
    -      t = new Thread(new Runnable() {
    +    private static class TestSynchronousObservable implements Observable.OnSubscribeFunc {
     
             @Override
    -        public void run() {
    -          onNextBeingSent.countDown();
    -          observer.onNext("hello");
    -          // I can't use a countDownLatch to prove we are actually sending 'onNext'
    -          // since it will block if synchronized and I'll deadlock
    -          observer.onCompleted();
    -        }
    +        public Subscription onSubscribe(Observer observer) {
     
    -      });
    -      t.start();
    +            observer.onNext("hello");
    +            observer.onCompleted();
     
    -      return new Subscription() {
    +            return new Subscription() {
     
    -        @Override
    -        public void unsubscribe() {
    +                @Override
    +                public void unsubscribe() {
    +                    // unregister ... will never be called here since we are executing synchronously
    +                }
     
    +            };
             }
    -
    -      };
         }
    -  }
     
    -  /**
    -   * A Observable that doesn't do the right thing on UnSubscribe/Error/etc in that it will keep sending events down the pipe regardless of what happens.
    -   */
    -  private static class TestObservable implements Observable.OnSubscribeFunc {
    +    private static class TestASynchronousObservable implements Observable.OnSubscribeFunc {
    +        Thread t;
    +        final CountDownLatch onNextBeingSent = new CountDownLatch(1);
    +
    +        @Override
    +        public Subscription onSubscribe(final Observer observer) {
    +            t = new Thread(new Runnable() {
     
    -    Observer observer = null;
    -    volatile boolean unsubscribed = false;
    -    Subscription s = new Subscription() {
    +                @Override
    +                public void run() {
    +                    onNextBeingSent.countDown();
    +                    observer.onNext("hello");
    +                    // I can't use a countDownLatch to prove we are actually sending 'onNext'
    +                    // since it will block if synchronized and I'll deadlock
    +                    observer.onCompleted();
    +                }
     
    -      @Override
    -      public void unsubscribe() {
    -        unsubscribed = true;
    +            });
    +            t.start();
     
    -      }
    +            return new Subscription() {
     
    -    };
    +                @Override
    +                public void unsubscribe() {
     
    -    /* used to simulate subscription */
    -    public void sendOnCompleted() {
    -      observer.onCompleted();
    -    }
    +                }
     
    -    /* used to simulate subscription */
    -    public void sendOnNext(String value) {
    -      observer.onNext(value);
    +            };
    +        }
         }
     
    -    /* used to simulate subscription */
    -    @SuppressWarnings("unused")
    -    public void sendOnError(Throwable e) {
    -      observer.onError(e);
    -    }
    +    /**
    +     * A Observable that doesn't do the right thing on UnSubscribe/Error/etc in that it will keep sending events down the pipe regardless of what happens.
    +     */
    +    private static class TestObservable implements Observable.OnSubscribeFunc {
     
    -    @Override
    -    public Subscription onSubscribe(final Observer observer) {
    -      this.observer = observer;
    -      return s;
    -    }
    -  }
    +        Observer observer = null;
    +        volatile boolean unsubscribed = false;
    +        Subscription s = new Subscription() {
     
    -  private static class TestErrorObservable implements Observable.OnSubscribeFunc {
    +            @Override
    +            public void unsubscribe() {
    +                unsubscribed = true;
     
    -    String[] valuesToReturn;
    +            }
     
    -    TestErrorObservable(String... values) {
    -      valuesToReturn = values;
    -    }
    +        };
     
    -    @Override
    -    public Subscription onSubscribe(Observer observer) {
    +        /* used to simulate subscription */
    +        public void sendOnCompleted() {
    +            observer.onCompleted();
    +        }
     
    -      for (String s : valuesToReturn) {
    -        if (s == null) {
    -          System.out.println("throwing exception");
    -          observer.onError(new NullPointerException());
    -        } else {
    -          observer.onNext(s);
    +        /* used to simulate subscription */
    +        public void sendOnNext(String value) {
    +            observer.onNext(value);
             }
    -      }
    -      observer.onCompleted();
     
    -      return new Subscription() {
    +        /* used to simulate subscription */
    +        @SuppressWarnings("unused")
    +        public void sendOnError(Throwable e) {
    +            observer.onError(e);
    +        }
     
             @Override
    -        public void unsubscribe() {
    -          // unregister ... will never be called here since we are executing synchronously
    +        public Subscription onSubscribe(final Observer observer) {
    +            this.observer = observer;
    +            return s;
             }
    +    }
     
    -      };
    +    private static class TestErrorObservable implements Observable.OnSubscribeFunc {
    +
    +        String[] valuesToReturn;
    +
    +        TestErrorObservable(String... values) {
    +            valuesToReturn = values;
    +        }
    +
    +        @Override
    +        public Subscription onSubscribe(Observer observer) {
    +
    +            for (String s : valuesToReturn) {
    +                if (s == null) {
    +                    System.out.println("throwing exception");
    +                    observer.onError(new NullPointerException());
    +                } else {
    +                    observer.onNext(s);
    +                }
    +            }
    +            observer.onCompleted();
    +
    +            return new Subscription() {
    +
    +                @Override
    +                public void unsubscribe() {
    +                    // unregister ... will never be called here since we are executing synchronously
    +                }
    +
    +            };
    +        }
         }
    -  }
     }
    diff --git a/rxjava-core/src/test/java/rx/operators/OperationMostRecentTest.java b/rxjava-core/src/test/java/rx/operators/OperationMostRecentTest.java
    index 35c6c9fadf..9dfb1ef9c1 100644
    --- a/rxjava-core/src/test/java/rx/operators/OperationMostRecentTest.java
    +++ b/rxjava-core/src/test/java/rx/operators/OperationMostRecentTest.java
    @@ -1,59 +1,59 @@
     package rx.operators;
     
    -import org.junit.Test;
    -import rx.subjects.PublishSubject;
    -import rx.subjects.Subject;
    +import static org.junit.Assert.*;
    +import static rx.operators.OperationMostRecent.*;
     
     import java.util.Iterator;
     
    -import static org.junit.Assert.*;
    -import static rx.operators.OperationMostRecent.mostRecent;
    +import org.junit.Test;
     
    -public class OperationMostRecentTest {
    +import rx.subjects.PublishSubject;
    +import rx.subjects.Subject;
     
    +public class OperationMostRecentTest {
     
    -  @Test
    -  public void testMostRecent() {
    -    Subject observable = PublishSubject.create();
    +    @Test
    +    public void testMostRecent() {
    +        Subject observable = PublishSubject.create();
     
    -    Iterator it = mostRecent(observable, "default").iterator();
    +        Iterator it = mostRecent(observable, "default").iterator();
     
    -    assertTrue(it.hasNext());
    -    assertEquals("default", it.next());
    -    assertEquals("default", it.next());
    +        assertTrue(it.hasNext());
    +        assertEquals("default", it.next());
    +        assertEquals("default", it.next());
     
    -    observable.onNext("one");
    -    assertTrue(it.hasNext());
    -    assertEquals("one", it.next());
    -    assertEquals("one", it.next());
    +        observable.onNext("one");
    +        assertTrue(it.hasNext());
    +        assertEquals("one", it.next());
    +        assertEquals("one", it.next());
     
    -    observable.onNext("two");
    -    assertTrue(it.hasNext());
    -    assertEquals("two", it.next());
    -    assertEquals("two", it.next());
    +        observable.onNext("two");
    +        assertTrue(it.hasNext());
    +        assertEquals("two", it.next());
    +        assertEquals("two", it.next());
     
    -    observable.onCompleted();
    -    assertFalse(it.hasNext());
    +        observable.onCompleted();
    +        assertFalse(it.hasNext());
     
    -  }
    +    }
     
    -  @Test(expected = TestException.class)
    -  public void testMostRecentWithException() {
    -    Subject observable = PublishSubject.create();
    +    @Test(expected = TestException.class)
    +    public void testMostRecentWithException() {
    +        Subject observable = PublishSubject.create();
     
    -    Iterator it = mostRecent(observable, "default").iterator();
    +        Iterator it = mostRecent(observable, "default").iterator();
     
    -    assertTrue(it.hasNext());
    -    assertEquals("default", it.next());
    -    assertEquals("default", it.next());
    +        assertTrue(it.hasNext());
    +        assertEquals("default", it.next());
    +        assertEquals("default", it.next());
     
    -    observable.onError(new TestException());
    -    assertTrue(it.hasNext());
    +        observable.onError(new TestException());
    +        assertTrue(it.hasNext());
     
    -    it.next();
    -  }
    +        it.next();
    +    }
     
    -  private static class TestException extends RuntimeException {
    -    private static final long serialVersionUID = 1L;
    -  }
    +    private static class TestException extends RuntimeException {
    +        private static final long serialVersionUID = 1L;
    +    }
     }
    diff --git a/rxjava-core/src/test/java/rx/operators/OperationMulticastTest.java b/rxjava-core/src/test/java/rx/operators/OperationMulticastTest.java
    index e33ee00de3..9e0189941d 100644
    --- a/rxjava-core/src/test/java/rx/operators/OperationMulticastTest.java
    +++ b/rxjava-core/src/test/java/rx/operators/OperationMulticastTest.java
    @@ -1,97 +1,98 @@
     package rx.operators;
     
    +import static org.mockito.Mockito.*;
    +
     import org.junit.Test;
    +
     import rx.Observer;
     import rx.Subscription;
     import rx.observables.ConnectableObservable;
     import rx.subjects.PublishSubject;
     import rx.subjects.Subject;
     
    -import static org.mockito.Mockito.*;
    -
     public class OperationMulticastTest {
     
    -  @Test
    -  public void testMulticast() {
    -    Subject source = PublishSubject.create();
    +    @Test
    +    public void testMulticast() {
    +        Subject source = PublishSubject.create();
     
    -    ConnectableObservable multicasted = OperationMulticast.multicast(source,
    -        PublishSubject.create());
    +        ConnectableObservable multicasted = OperationMulticast.multicast(source,
    +                PublishSubject. create());
     
    -    @SuppressWarnings("unchecked")
    -    Observer observer = mock(Observer.class);
    -    multicasted.subscribe(observer);
    +        @SuppressWarnings("unchecked")
    +        Observer observer = mock(Observer.class);
    +        multicasted.subscribe(observer);
     
    -    source.onNext("one");
    -    source.onNext("two");
    +        source.onNext("one");
    +        source.onNext("two");
     
    -    multicasted.connect();
    +        multicasted.connect();
     
    -    source.onNext("three");
    -    source.onNext("four");
    -    source.onCompleted();
    +        source.onNext("three");
    +        source.onNext("four");
    +        source.onCompleted();
     
    -    verify(observer, never()).onNext("one");
    -    verify(observer, never()).onNext("two");
    -    verify(observer, times(1)).onNext("three");
    -    verify(observer, times(1)).onNext("four");
    -    verify(observer, times(1)).onCompleted();
    +        verify(observer, never()).onNext("one");
    +        verify(observer, never()).onNext("two");
    +        verify(observer, times(1)).onNext("three");
    +        verify(observer, times(1)).onNext("four");
    +        verify(observer, times(1)).onCompleted();
     
    -  }
    +    }
     
    -  @Test
    -  public void testMulticastConnectTwice() {
    -    Subject source = PublishSubject.create();
    +    @Test
    +    public void testMulticastConnectTwice() {
    +        Subject source = PublishSubject.create();
     
    -    ConnectableObservable multicasted = OperationMulticast.multicast(source,
    -        PublishSubject.create());
    +        ConnectableObservable multicasted = OperationMulticast.multicast(source,
    +                PublishSubject. create());
     
    -    @SuppressWarnings("unchecked")
    -    Observer observer = mock(Observer.class);
    -    multicasted.subscribe(observer);
    +        @SuppressWarnings("unchecked")
    +        Observer observer = mock(Observer.class);
    +        multicasted.subscribe(observer);
     
    -    source.onNext("one");
    +        source.onNext("one");
     
    -    multicasted.connect();
    -    multicasted.connect();
    +        multicasted.connect();
    +        multicasted.connect();
     
    -    source.onNext("two");
    -    source.onCompleted();
    +        source.onNext("two");
    +        source.onCompleted();
     
    -    verify(observer, never()).onNext("one");
    -    verify(observer, times(1)).onNext("two");
    -    verify(observer, times(1)).onCompleted();
    +        verify(observer, never()).onNext("one");
    +        verify(observer, times(1)).onNext("two");
    +        verify(observer, times(1)).onCompleted();
     
    -  }
    +    }
     
    -  @Test
    -  public void testMulticastDisconnect() {
    -    Subject source = PublishSubject.create();
    +    @Test
    +    public void testMulticastDisconnect() {
    +        Subject source = PublishSubject.create();
     
    -    ConnectableObservable multicasted = OperationMulticast.multicast(source,
    -        PublishSubject.create());
    +        ConnectableObservable multicasted = OperationMulticast.multicast(source,
    +                PublishSubject. create());
     
    -    @SuppressWarnings("unchecked")
    -    Observer observer = mock(Observer.class);
    -    multicasted.subscribe(observer);
    +        @SuppressWarnings("unchecked")
    +        Observer observer = mock(Observer.class);
    +        multicasted.subscribe(observer);
     
    -    source.onNext("one");
    +        source.onNext("one");
     
    -    Subscription connection = multicasted.connect();
    -    source.onNext("two");
    +        Subscription connection = multicasted.connect();
    +        source.onNext("two");
     
    -    connection.unsubscribe();
    -    source.onNext("three");
    +        connection.unsubscribe();
    +        source.onNext("three");
     
    -    multicasted.connect();
    -    source.onNext("four");
    -    source.onCompleted();
    +        multicasted.connect();
    +        source.onNext("four");
    +        source.onCompleted();
     
    -    verify(observer, never()).onNext("one");
    -    verify(observer, times(1)).onNext("two");
    -    verify(observer, never()).onNext("three");
    -    verify(observer, times(1)).onNext("four");
    -    verify(observer, times(1)).onCompleted();
    +        verify(observer, never()).onNext("one");
    +        verify(observer, times(1)).onNext("two");
    +        verify(observer, never()).onNext("three");
    +        verify(observer, times(1)).onNext("four");
    +        verify(observer, times(1)).onCompleted();
     
    -  }
    +    }
     }
    diff --git a/rxjava-core/src/test/java/rx/operators/OperationNextTest.java b/rxjava-core/src/test/java/rx/operators/OperationNextTest.java
    index c696a64c27..4b16458c4e 100644
    --- a/rxjava-core/src/test/java/rx/operators/OperationNextTest.java
    +++ b/rxjava-core/src/test/java/rx/operators/OperationNextTest.java
    @@ -1,6 +1,17 @@
     package rx.operators;
     
    +import static org.junit.Assert.*;
    +import static rx.operators.OperationNext.*;
    +
    +import java.util.Iterator;
    +import java.util.NoSuchElementException;
    +import java.util.concurrent.CountDownLatch;
    +import java.util.concurrent.TimeUnit;
    +import java.util.concurrent.atomic.AtomicBoolean;
    +import java.util.concurrent.atomic.AtomicInteger;
    +
     import org.junit.Test;
    +
     import rx.Observable;
     import rx.Observer;
     import rx.Subscription;
    @@ -9,273 +20,262 @@
     import rx.subjects.Subject;
     import rx.subscriptions.Subscriptions;
     
    -import java.util.Iterator;
    -import java.util.NoSuchElementException;
    -import java.util.concurrent.CountDownLatch;
    -import java.util.concurrent.TimeUnit;
    -import java.util.concurrent.atomic.AtomicBoolean;
    -import java.util.concurrent.atomic.AtomicInteger;
    +public class OperationNextTest {
     
    -import static org.junit.Assert.*;
    -import static rx.operators.OperationNext.next;
    +    private void fireOnNextInNewThread(final Subject o, final String value) {
    +        new Thread() {
    +            @Override
    +            public void run() {
    +                try {
    +                    Thread.sleep(500);
    +                } catch (InterruptedException e) {
    +                    // ignore
    +                }
    +                o.onNext(value);
    +            }
    +        }.start();
    +    }
     
    -public class OperationNextTest {
    +    private void fireOnErrorInNewThread(final Subject o) {
    +        new Thread() {
    +            @Override
    +            public void run() {
    +                try {
    +                    Thread.sleep(500);
    +                } catch (InterruptedException e) {
    +                    // ignore
    +                }
    +                o.onError(new TestException());
    +            }
    +        }.start();
    +    }
     
    -  private void fireOnNextInNewThread(final Subject o, final String value) {
    -    new Thread() {
    -      @Override
    -      public void run() {
    +    @Test
    +    public void testNext() {
    +        Subject obs = PublishSubject.create();
    +        Iterator it = next(obs).iterator();
    +        fireOnNextInNewThread(obs, "one");
    +        assertTrue(it.hasNext());
    +        assertEquals("one", it.next());
    +
    +        fireOnNextInNewThread(obs, "two");
    +        assertTrue(it.hasNext());
    +        assertEquals("two", it.next());
    +
    +        obs.onCompleted();
    +        assertFalse(it.hasNext());
             try {
    -          Thread.sleep(500);
    -        } catch (InterruptedException e) {
    -          // ignore
    +            it.next();
    +            fail("At the end of an iterator should throw a NoSuchElementException");
    +        } catch (NoSuchElementException e) {
             }
    -        o.onNext(value);
    -      }
    -    }.start();
    -  }
    -
    -  private void fireOnErrorInNewThread(final Subject o) {
    -    new Thread() {
    -      @Override
    -      public void run() {
    +
    +        // If the observable is completed, hasNext always returns false and next always throw a NoSuchElementException.
    +        assertFalse(it.hasNext());
             try {
    -          Thread.sleep(500);
    -        } catch (InterruptedException e) {
    -          // ignore
    +            it.next();
    +            fail("At the end of an iterator should throw a NoSuchElementException");
    +        } catch (NoSuchElementException e) {
             }
    -        o.onError(new TestException());
    -      }
    -    }.start();
    -  }
    -
    -
    -  @Test
    -  public void testNext() {
    -    Subject obs = PublishSubject.create();
    -    Iterator it = next(obs).iterator();
    -    fireOnNextInNewThread(obs, "one");
    -    assertTrue(it.hasNext());
    -    assertEquals("one", it.next());
    -
    -    fireOnNextInNewThread(obs, "two");
    -    assertTrue(it.hasNext());
    -    assertEquals("two", it.next());
    -
    -    obs.onCompleted();
    -    assertFalse(it.hasNext());
    -    try {
    -      it.next();
    -      fail("At the end of an iterator should throw a NoSuchElementException");
    -    } catch (NoSuchElementException e) {
         }
     
    -    // If the observable is completed, hasNext always returns false and next always throw a NoSuchElementException.
    -    assertFalse(it.hasNext());
    -    try {
    -      it.next();
    -      fail("At the end of an iterator should throw a NoSuchElementException");
    -    } catch (NoSuchElementException e) {
    -    }
    -  }
    -
    -  @Test
    -  public void testNextWithError() {
    -    Subject obs = PublishSubject.create();
    -    Iterator it = next(obs).iterator();
    -    fireOnNextInNewThread(obs, "one");
    -    assertTrue(it.hasNext());
    -    assertEquals("one", it.next());
    -
    -    fireOnErrorInNewThread(obs);
    -    try {
    -      it.hasNext();
    -      fail("Expected an TestException");
    -    } catch (TestException e) {
    +    @Test
    +    public void testNextWithError() {
    +        Subject obs = PublishSubject.create();
    +        Iterator it = next(obs).iterator();
    +        fireOnNextInNewThread(obs, "one");
    +        assertTrue(it.hasNext());
    +        assertEquals("one", it.next());
    +
    +        fireOnErrorInNewThread(obs);
    +        try {
    +            it.hasNext();
    +            fail("Expected an TestException");
    +        } catch (TestException e) {
    +        }
    +
    +        assertErrorAfterObservableFail(it);
         }
     
    -    assertErrorAfterObservableFail(it);
    -  }
    +    @Test
    +    public void testNextWithEmpty() {
    +        Observable obs = Observable. empty().observeOn(Schedulers.newThread());
    +        Iterator it = next(obs).iterator();
     
    -  @Test
    -  public void testNextWithEmpty() {
    -    Observable obs = Observable.empty().observeOn(Schedulers.newThread());
    -    Iterator it = next(obs).iterator();
    +        assertFalse(it.hasNext());
    +        try {
    +            it.next();
    +            fail("At the end of an iterator should throw a NoSuchElementException");
    +        } catch (NoSuchElementException e) {
    +        }
     
    -    assertFalse(it.hasNext());
    -    try {
    -      it.next();
    -      fail("At the end of an iterator should throw a NoSuchElementException");
    -    } catch (NoSuchElementException e) {
    +        // If the observable is completed, hasNext always returns false and next always throw a NoSuchElementException.
    +        assertFalse(it.hasNext());
    +        try {
    +            it.next();
    +            fail("At the end of an iterator should throw a NoSuchElementException");
    +        } catch (NoSuchElementException e) {
    +        }
         }
     
    -    // If the observable is completed, hasNext always returns false and next always throw a NoSuchElementException.
    -    assertFalse(it.hasNext());
    -    try {
    -      it.next();
    -      fail("At the end of an iterator should throw a NoSuchElementException");
    -    } catch (NoSuchElementException e) {
    -    }
    -  }
    -
    -  @Test
    -  public void testOnError() throws Throwable {
    -    Subject obs = PublishSubject.create();
    -    Iterator it = next(obs).iterator();
    -
    -    obs.onError(new TestException());
    -    try {
    -      it.hasNext();
    -      fail("Expected an TestException");
    -    } catch (TestException e) {
    -      // successful
    +    @Test
    +    public void testOnError() throws Throwable {
    +        Subject obs = PublishSubject.create();
    +        Iterator it = next(obs).iterator();
    +
    +        obs.onError(new TestException());
    +        try {
    +            it.hasNext();
    +            fail("Expected an TestException");
    +        } catch (TestException e) {
    +            // successful
    +        }
    +
    +        assertErrorAfterObservableFail(it);
         }
     
    -    assertErrorAfterObservableFail(it);
    -  }
    +    @Test
    +    public void testOnErrorInNewThread() {
    +        Subject obs = PublishSubject.create();
    +        Iterator it = next(obs).iterator();
     
    -  @Test
    -  public void testOnErrorInNewThread() {
    -    Subject obs = PublishSubject.create();
    -    Iterator it = next(obs).iterator();
    +        fireOnErrorInNewThread(obs);
     
    -    fireOnErrorInNewThread(obs);
    +        try {
    +            it.hasNext();
    +            fail("Expected an TestException");
    +        } catch (TestException e) {
    +            // successful
    +        }
     
    -    try {
    -      it.hasNext();
    -      fail("Expected an TestException");
    -    } catch (TestException e) {
    -      // successful
    +        assertErrorAfterObservableFail(it);
         }
     
    -    assertErrorAfterObservableFail(it);
    -  }
    -
    -  private void assertErrorAfterObservableFail(Iterator it) {
    -    // After the observable fails, hasNext and next always throw the exception.
    -    try {
    -      it.hasNext();
    -      fail("hasNext should throw a TestException");
    -    } catch (TestException e) {
    +    private void assertErrorAfterObservableFail(Iterator it) {
    +        // After the observable fails, hasNext and next always throw the exception.
    +        try {
    +            it.hasNext();
    +            fail("hasNext should throw a TestException");
    +        } catch (TestException e) {
    +        }
    +        try {
    +            it.next();
    +            fail("next should throw a TestException");
    +        } catch (TestException e) {
    +        }
         }
    -    try {
    -      it.next();
    -      fail("next should throw a TestException");
    -    } catch (TestException e) {
    +
    +    @Test
    +    public void testNextWithOnlyUsingNextMethod() {
    +        Subject obs = PublishSubject.create();
    +        Iterator it = next(obs).iterator();
    +        fireOnNextInNewThread(obs, "one");
    +        assertEquals("one", it.next());
    +
    +        fireOnNextInNewThread(obs, "two");
    +        assertEquals("two", it.next());
    +
    +        obs.onCompleted();
    +        try {
    +            it.next();
    +            fail("At the end of an iterator should throw a NoSuchElementException");
    +        } catch (NoSuchElementException e) {
    +        }
         }
    -  }
    -
    -  @Test
    -  public void testNextWithOnlyUsingNextMethod() {
    -    Subject obs = PublishSubject.create();
    -    Iterator it = next(obs).iterator();
    -    fireOnNextInNewThread(obs, "one");
    -    assertEquals("one", it.next());
    -
    -    fireOnNextInNewThread(obs, "two");
    -    assertEquals("two", it.next());
    -
    -    obs.onCompleted();
    -    try {
    -      it.next();
    -      fail("At the end of an iterator should throw a NoSuchElementException");
    -    } catch (NoSuchElementException e) {
    +
    +    @Test
    +    public void testNextWithCallingHasNextMultipleTimes() {
    +        Subject obs = PublishSubject.create();
    +        Iterator it = next(obs).iterator();
    +        fireOnNextInNewThread(obs, "one");
    +        assertTrue(it.hasNext());
    +        assertTrue(it.hasNext());
    +        assertTrue(it.hasNext());
    +        assertTrue(it.hasNext());
    +        assertEquals("one", it.next());
    +
    +        obs.onCompleted();
    +        try {
    +            it.next();
    +            fail("At the end of an iterator should throw a NoSuchElementException");
    +        } catch (NoSuchElementException e) {
    +        }
         }
    -  }
    -
    -  @Test
    -  public void testNextWithCallingHasNextMultipleTimes() {
    -    Subject obs = PublishSubject.create();
    -    Iterator it = next(obs).iterator();
    -    fireOnNextInNewThread(obs, "one");
    -    assertTrue(it.hasNext());
    -    assertTrue(it.hasNext());
    -    assertTrue(it.hasNext());
    -    assertTrue(it.hasNext());
    -    assertEquals("one", it.next());
    -
    -    obs.onCompleted();
    -    try {
    -      it.next();
    -      fail("At the end of an iterator should throw a NoSuchElementException");
    -    } catch (NoSuchElementException e) {
    +
    +    @SuppressWarnings("serial")
    +    private static class TestException extends RuntimeException {
    +
         }
    -  }
    -
    -  @SuppressWarnings("serial")
    -  private static class TestException extends RuntimeException {
    -
    -  }
    -
    -  /**
    -   * Confirm that no buffering or blocking of the Observable onNext calls occurs and it just grabs the next emitted value.
    -   * 

    - * This results in output such as => a: 1 b: 2 c: 89 - * - * @throws Throwable - */ - @Test - public void testNoBufferingOrBlockingOfSequence() throws Throwable { - final CountDownLatch finished = new CountDownLatch(1); - final int COUNT = 30; - final CountDownLatch timeHasPassed = new CountDownLatch(COUNT); - final AtomicBoolean running = new AtomicBoolean(true); - final AtomicInteger count = new AtomicInteger(0); - final Observable obs = Observable.create(new Observable.OnSubscribeFunc() { - - @Override - public Subscription onSubscribe(final Observer o) { - new Thread(new Runnable() { - - @Override - public void run() { - try { - while (running.get()) { - o.onNext(count.incrementAndGet()); - timeHasPassed.countDown(); - } - o.onCompleted(); - } catch (Throwable e) { - o.onError(e); - } finally { - finished.countDown(); + + /** + * Confirm that no buffering or blocking of the Observable onNext calls occurs and it just grabs the next emitted value. + *

    + * This results in output such as => a: 1 b: 2 c: 89 + * + * @throws Throwable + */ + @Test + public void testNoBufferingOrBlockingOfSequence() throws Throwable { + final CountDownLatch finished = new CountDownLatch(1); + final int COUNT = 30; + final CountDownLatch timeHasPassed = new CountDownLatch(COUNT); + final AtomicBoolean running = new AtomicBoolean(true); + final AtomicInteger count = new AtomicInteger(0); + final Observable obs = Observable.create(new Observable.OnSubscribeFunc() { + + @Override + public Subscription onSubscribe(final Observer o) { + new Thread(new Runnable() { + + @Override + public void run() { + try { + while (running.get()) { + o.onNext(count.incrementAndGet()); + timeHasPassed.countDown(); + } + o.onCompleted(); + } catch (Throwable e) { + o.onError(e); + } finally { + finished.countDown(); + } + } + }).start(); + return Subscriptions.empty(); } - } - }).start(); - return Subscriptions.empty(); - } - }); + }); - Iterator it = next(obs).iterator(); + Iterator it = next(obs).iterator(); - assertTrue(it.hasNext()); - int a = it.next(); - assertTrue(it.hasNext()); - int b = it.next(); - // we should have a different value - assertTrue("a and b should be different", a != b); + assertTrue(it.hasNext()); + int a = it.next(); + assertTrue(it.hasNext()); + int b = it.next(); + // we should have a different value + assertTrue("a and b should be different", a != b); - // wait for some time (if times out we are blocked somewhere so fail ... set very high for very slow, constrained machines) - timeHasPassed.await(8000, TimeUnit.MILLISECONDS); + // wait for some time (if times out we are blocked somewhere so fail ... set very high for very slow, constrained machines) + timeHasPassed.await(8000, TimeUnit.MILLISECONDS); - assertTrue(it.hasNext()); - int c = it.next(); + assertTrue(it.hasNext()); + int c = it.next(); - assertTrue("c should not just be the next in sequence", c != (b + 1)); - assertTrue("expected that c [" + c + "] is higher than or equal to " + COUNT, c >= COUNT); + assertTrue("c should not just be the next in sequence", c != (b + 1)); + assertTrue("expected that c [" + c + "] is higher than or equal to " + COUNT, c >= COUNT); - assertTrue(it.hasNext()); - int d = it.next(); - assertTrue(d > c); + assertTrue(it.hasNext()); + int d = it.next(); + assertTrue(d > c); - // shut down the thread - running.set(false); + // shut down the thread + running.set(false); - finished.await(); + finished.await(); - assertFalse(it.hasNext()); + assertFalse(it.hasNext()); - System.out.println("a: " + a + " b: " + b + " c: " + c); - } + System.out.println("a: " + a + " b: " + b + " c: " + c); + } } diff --git a/rxjava-core/src/test/java/rx/operators/OperationObserveOnTest.java b/rxjava-core/src/test/java/rx/operators/OperationObserveOnTest.java index 17b5292130..75f2603df7 100644 --- a/rxjava-core/src/test/java/rx/operators/OperationObserveOnTest.java +++ b/rxjava-core/src/test/java/rx/operators/OperationObserveOnTest.java @@ -1,68 +1,69 @@ package rx.operators; +import static org.junit.Assert.*; +import static org.mockito.Mockito.*; +import static rx.operators.OperationObserveOn.*; + +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; + import org.junit.Test; import org.mockito.InOrder; import org.mockito.invocation.InvocationOnMock; import org.mockito.stubbing.Answer; + import rx.Observable; import rx.Observer; import rx.concurrency.Schedulers; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.TimeUnit; - -import static org.junit.Assert.fail; -import static org.mockito.Mockito.*; -import static rx.operators.OperationObserveOn.observeOn; - public class OperationObserveOnTest { - /** - * This is testing a no-op path since it uses Schedulers.immediate() which will not do scheduling. - */ - @Test - @SuppressWarnings("unchecked") - public void testObserveOn() { - Observer observer = mock(Observer.class); - Observable.create(observeOn(Observable.from(1, 2, 3), Schedulers.immediate())).subscribe(observer); + /** + * This is testing a no-op path since it uses Schedulers.immediate() which will not do scheduling. + */ + @Test + @SuppressWarnings("unchecked") + public void testObserveOn() { + Observer observer = mock(Observer.class); + Observable.create(observeOn(Observable.from(1, 2, 3), Schedulers.immediate())).subscribe(observer); - verify(observer, times(1)).onNext(1); - verify(observer, times(1)).onNext(2); - verify(observer, times(1)).onNext(3); - verify(observer, times(1)).onCompleted(); - } + verify(observer, times(1)).onNext(1); + verify(observer, times(1)).onNext(2); + verify(observer, times(1)).onNext(3); + verify(observer, times(1)).onCompleted(); + } - @Test - @SuppressWarnings("unchecked") - public void testOrdering() throws InterruptedException { - Observable obs = Observable.from("one", null, "two", "three", "four"); + @Test + @SuppressWarnings("unchecked") + public void testOrdering() throws InterruptedException { + Observable obs = Observable.from("one", null, "two", "three", "four"); - Observer observer = mock(Observer.class); + Observer observer = mock(Observer.class); - InOrder inOrder = inOrder(observer); + InOrder inOrder = inOrder(observer); - final CountDownLatch completedLatch = new CountDownLatch(1); - doAnswer(new Answer() { + final CountDownLatch completedLatch = new CountDownLatch(1); + doAnswer(new Answer() { - @Override - public Void answer(InvocationOnMock invocation) throws Throwable { - completedLatch.countDown(); - return null; - } - }).when(observer).onCompleted(); + @Override + public Void answer(InvocationOnMock invocation) throws Throwable { + completedLatch.countDown(); + return null; + } + }).when(observer).onCompleted(); - obs.observeOn(Schedulers.threadPoolForComputation()).subscribe(observer); + obs.observeOn(Schedulers.threadPoolForComputation()).subscribe(observer); - if (!completedLatch.await(1000, TimeUnit.MILLISECONDS)) { - fail("timed out waiting"); - } + if (!completedLatch.await(1000, TimeUnit.MILLISECONDS)) { + fail("timed out waiting"); + } - inOrder.verify(observer, times(1)).onNext("one"); - inOrder.verify(observer, times(1)).onNext(null); - inOrder.verify(observer, times(1)).onNext("two"); - inOrder.verify(observer, times(1)).onNext("three"); - inOrder.verify(observer, times(1)).onNext("four"); - inOrder.verify(observer, times(1)).onCompleted(); - inOrder.verifyNoMoreInteractions(); - } + inOrder.verify(observer, times(1)).onNext("one"); + inOrder.verify(observer, times(1)).onNext(null); + inOrder.verify(observer, times(1)).onNext("two"); + inOrder.verify(observer, times(1)).onNext("three"); + inOrder.verify(observer, times(1)).onNext("four"); + inOrder.verify(observer, times(1)).onCompleted(); + inOrder.verifyNoMoreInteractions(); + } } diff --git a/rxjava-core/src/test/java/rx/operators/OperationOnErrorResumeNextViaFunctionTest.java b/rxjava-core/src/test/java/rx/operators/OperationOnErrorResumeNextViaFunctionTest.java index 3de89d6a49..ba81230ccf 100644 --- a/rxjava-core/src/test/java/rx/operators/OperationOnErrorResumeNextViaFunctionTest.java +++ b/rxjava-core/src/test/java/rx/operators/OperationOnErrorResumeNextViaFunctionTest.java @@ -1,168 +1,168 @@ package rx.operators; +import static org.junit.Assert.*; +import static org.mockito.Matchers.*; +import static org.mockito.Mockito.*; +import static rx.operators.OperationOnErrorResumeNextViaFunction.*; + +import java.util.concurrent.atomic.AtomicReference; + import org.junit.Test; import org.mockito.Mockito; + import rx.Observable; import rx.Observer; import rx.Subscription; import rx.subscriptions.Subscriptions; import rx.util.functions.Func1; -import java.util.concurrent.atomic.AtomicReference; +public class OperationOnErrorResumeNextViaFunctionTest { -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.fail; -import static org.mockito.Matchers.any; -import static org.mockito.Mockito.*; -import static rx.operators.OperationOnErrorResumeNextViaFunction.onErrorResumeNextViaFunction; + @Test + public void testResumeNextWithSynchronousExecution() { + final AtomicReference receivedException = new AtomicReference(); + Observable w = Observable.create(new Observable.OnSubscribeFunc() { -public class OperationOnErrorResumeNextViaFunctionTest { + @Override + public Subscription onSubscribe(Observer observer) { + observer.onNext("one"); + observer.onError(new Throwable("injected failure")); + return Subscriptions.empty(); + } + }); + + Func1> resume = new Func1>() { - @Test - public void testResumeNextWithSynchronousExecution() { - final AtomicReference receivedException = new AtomicReference(); - Observable w = Observable.create(new Observable.OnSubscribeFunc() { - - @Override - public Subscription onSubscribe(Observer observer) { - observer.onNext("one"); - observer.onError(new Throwable("injected failure")); - return Subscriptions.empty(); - } - }); - - Func1> resume = new Func1>() { - - @Override - public Observable call(Throwable t1) { - receivedException.set(t1); - return Observable.from("twoResume", "threeResume"); - } - - }; - Observable observable = Observable.create(onErrorResumeNextViaFunction(w, resume)); - - @SuppressWarnings("unchecked") - Observer aObserver = mock(Observer.class); - observable.subscribe(aObserver); - - verify(aObserver, Mockito.never()).onError(any(Throwable.class)); - verify(aObserver, times(1)).onCompleted(); - verify(aObserver, times(1)).onNext("one"); - verify(aObserver, Mockito.never()).onNext("two"); - verify(aObserver, Mockito.never()).onNext("three"); - verify(aObserver, times(1)).onNext("twoResume"); - verify(aObserver, times(1)).onNext("threeResume"); - assertNotNull(receivedException.get()); - } - - @Test - public void testResumeNextWithAsyncExecution() { - final AtomicReference receivedException = new AtomicReference(); - Subscription s = mock(Subscription.class); - TestObservable w = new TestObservable(s, "one"); - Func1> resume = new Func1>() { - - @Override - public Observable call(Throwable t1) { - receivedException.set(t1); - return Observable.from("twoResume", "threeResume"); - } - - }; - Observable observable = Observable.create(onErrorResumeNextViaFunction(Observable.create(w), resume)); - - @SuppressWarnings("unchecked") - Observer aObserver = mock(Observer.class); - observable.subscribe(aObserver); - - try { - w.t.join(); - } catch (InterruptedException e) { - fail(e.getMessage()); + @Override + public Observable call(Throwable t1) { + receivedException.set(t1); + return Observable.from("twoResume", "threeResume"); + } + + }; + Observable observable = Observable.create(onErrorResumeNextViaFunction(w, resume)); + + @SuppressWarnings("unchecked") + Observer aObserver = mock(Observer.class); + observable.subscribe(aObserver); + + verify(aObserver, Mockito.never()).onError(any(Throwable.class)); + verify(aObserver, times(1)).onCompleted(); + verify(aObserver, times(1)).onNext("one"); + verify(aObserver, Mockito.never()).onNext("two"); + verify(aObserver, Mockito.never()).onNext("three"); + verify(aObserver, times(1)).onNext("twoResume"); + verify(aObserver, times(1)).onNext("threeResume"); + assertNotNull(receivedException.get()); } - verify(aObserver, Mockito.never()).onError(any(Throwable.class)); - verify(aObserver, times(1)).onCompleted(); - verify(aObserver, times(1)).onNext("one"); - verify(aObserver, Mockito.never()).onNext("two"); - verify(aObserver, Mockito.never()).onNext("three"); - verify(aObserver, times(1)).onNext("twoResume"); - verify(aObserver, times(1)).onNext("threeResume"); - assertNotNull(receivedException.get()); - } - - /** - * Test that when a function throws an exception this is propagated through onError - */ - @Test - public void testFunctionThrowsError() { - Subscription s = mock(Subscription.class); - TestObservable w = new TestObservable(s, "one"); - Func1> resume = new Func1>() { - - @Override - public Observable call(Throwable t1) { - throw new RuntimeException("exception from function"); - } - - }; - Observable observable = Observable.create(onErrorResumeNextViaFunction(Observable.create(w), resume)); - - @SuppressWarnings("unchecked") - Observer aObserver = mock(Observer.class); - observable.subscribe(aObserver); - - try { - w.t.join(); - } catch (InterruptedException e) { - fail(e.getMessage()); + @Test + public void testResumeNextWithAsyncExecution() { + final AtomicReference receivedException = new AtomicReference(); + Subscription s = mock(Subscription.class); + TestObservable w = new TestObservable(s, "one"); + Func1> resume = new Func1>() { + + @Override + public Observable call(Throwable t1) { + receivedException.set(t1); + return Observable.from("twoResume", "threeResume"); + } + + }; + Observable observable = Observable.create(onErrorResumeNextViaFunction(Observable.create(w), resume)); + + @SuppressWarnings("unchecked") + Observer aObserver = mock(Observer.class); + observable.subscribe(aObserver); + + try { + w.t.join(); + } catch (InterruptedException e) { + fail(e.getMessage()); + } + + verify(aObserver, Mockito.never()).onError(any(Throwable.class)); + verify(aObserver, times(1)).onCompleted(); + verify(aObserver, times(1)).onNext("one"); + verify(aObserver, Mockito.never()).onNext("two"); + verify(aObserver, Mockito.never()).onNext("three"); + verify(aObserver, times(1)).onNext("twoResume"); + verify(aObserver, times(1)).onNext("threeResume"); + assertNotNull(receivedException.get()); } - // we should get the "one" value before the error - verify(aObserver, times(1)).onNext("one"); + /** + * Test that when a function throws an exception this is propagated through onError + */ + @Test + public void testFunctionThrowsError() { + Subscription s = mock(Subscription.class); + TestObservable w = new TestObservable(s, "one"); + Func1> resume = new Func1>() { + + @Override + public Observable call(Throwable t1) { + throw new RuntimeException("exception from function"); + } - // we should have received an onError call on the Observer since the resume function threw an exception - verify(aObserver, times(1)).onError(any(Throwable.class)); - verify(aObserver, times(0)).onCompleted(); - } + }; + Observable observable = Observable.create(onErrorResumeNextViaFunction(Observable.create(w), resume)); - private static class TestObservable implements Observable.OnSubscribeFunc { + @SuppressWarnings("unchecked") + Observer aObserver = mock(Observer.class); + observable.subscribe(aObserver); - final Subscription s; - final String[] values; - Thread t = null; + try { + w.t.join(); + } catch (InterruptedException e) { + fail(e.getMessage()); + } - public TestObservable(Subscription s, String... values) { - this.s = s; - this.values = values; + // we should get the "one" value before the error + verify(aObserver, times(1)).onNext("one"); + + // we should have received an onError call on the Observer since the resume function threw an exception + verify(aObserver, times(1)).onError(any(Throwable.class)); + verify(aObserver, times(0)).onCompleted(); } - @Override - public Subscription onSubscribe(final Observer observer) { - System.out.println("TestObservable subscribed to ..."); - t = new Thread(new Runnable() { + private static class TestObservable implements Observable.OnSubscribeFunc { + + final Subscription s; + final String[] values; + Thread t = null; + + public TestObservable(Subscription s, String... values) { + this.s = s; + this.values = values; + } @Override - public void run() { - try { - System.out.println("running TestObservable thread"); - for (String s : values) { - System.out.println("TestObservable onNext: " + s); - observer.onNext(s); - } - throw new RuntimeException("Forced Failure"); - } catch (Throwable e) { - observer.onError(e); - } + public Subscription onSubscribe(final Observer observer) { + System.out.println("TestObservable subscribed to ..."); + t = new Thread(new Runnable() { + + @Override + public void run() { + try { + System.out.println("running TestObservable thread"); + for (String s : values) { + System.out.println("TestObservable onNext: " + s); + observer.onNext(s); + } + throw new RuntimeException("Forced Failure"); + } catch (Throwable e) { + observer.onError(e); + } + } + + }); + System.out.println("starting TestObservable thread"); + t.start(); + System.out.println("done starting TestObservable thread"); + return s; } - }); - System.out.println("starting TestObservable thread"); - t.start(); - System.out.println("done starting TestObservable thread"); - return s; } - - } } diff --git a/rxjava-core/src/test/java/rx/operators/OperationOnErrorResumeNextViaObservableTest.java b/rxjava-core/src/test/java/rx/operators/OperationOnErrorResumeNextViaObservableTest.java index 69b62ec495..48ef273932 100644 --- a/rxjava-core/src/test/java/rx/operators/OperationOnErrorResumeNextViaObservableTest.java +++ b/rxjava-core/src/test/java/rx/operators/OperationOnErrorResumeNextViaObservableTest.java @@ -1,127 +1,128 @@ package rx.operators; +import static org.junit.Assert.*; +import static org.mockito.Matchers.*; +import static org.mockito.Mockito.*; +import static rx.operators.OperationOnErrorResumeNextViaObservable.*; + import org.junit.Test; import org.mockito.Mockito; + import rx.Observable; import rx.Observer; import rx.Subscription; import rx.util.functions.Func1; -import static org.junit.Assert.fail; -import static org.mockito.Matchers.any; -import static org.mockito.Mockito.*; -import static rx.operators.OperationOnErrorResumeNextViaObservable.onErrorResumeNextViaObservable; - public class OperationOnErrorResumeNextViaObservableTest { - @Test - public void testResumeNext() { - Subscription s = mock(Subscription.class); - // Trigger failure on second element - TestObservable f = new TestObservable(s, "one", "fail", "two", "three"); - Observable w = Observable.create(f); - Observable resume = Observable.from("twoResume", "threeResume"); - Observable observable = Observable.create(onErrorResumeNextViaObservable(w, resume)); - - @SuppressWarnings("unchecked") - Observer aObserver = mock(Observer.class); - observable.subscribe(aObserver); - - try { - f.t.join(); - } catch (InterruptedException e) { - fail(e.getMessage()); - } + @Test + public void testResumeNext() { + Subscription s = mock(Subscription.class); + // Trigger failure on second element + TestObservable f = new TestObservable(s, "one", "fail", "two", "three"); + Observable w = Observable.create(f); + Observable resume = Observable.from("twoResume", "threeResume"); + Observable observable = Observable.create(onErrorResumeNextViaObservable(w, resume)); + + @SuppressWarnings("unchecked") + Observer aObserver = mock(Observer.class); + observable.subscribe(aObserver); + + try { + f.t.join(); + } catch (InterruptedException e) { + fail(e.getMessage()); + } - verify(aObserver, Mockito.never()).onError(any(Throwable.class)); - verify(aObserver, times(1)).onCompleted(); - verify(aObserver, times(1)).onNext("one"); - verify(aObserver, Mockito.never()).onNext("two"); - verify(aObserver, Mockito.never()).onNext("three"); - verify(aObserver, times(1)).onNext("twoResume"); - verify(aObserver, times(1)).onNext("threeResume"); - } - - @Test - public void testMapResumeAsyncNext() { - Subscription sr = mock(Subscription.class); - // Trigger multiple failures - Observable w = Observable.from("one", "fail", "two", "three", "fail"); - // Resume Observable is async - TestObservable f = new TestObservable(sr, "twoResume", "threeResume"); - Observable resume = Observable.create(f); - - // Introduce map function that fails intermittently (Map does not prevent this when the observer is a - // rx.operator incl onErrorResumeNextViaObservable) - w = w.map(new Func1() { - public String call(String s) { - if ("fail".equals(s)) - throw new RuntimeException("Forced Failure"); - System.out.println("BadMapper:" + s); - return s; - } - }); - - Observable observable = Observable.create(onErrorResumeNextViaObservable(w, resume)); - - @SuppressWarnings("unchecked") - Observer aObserver = mock(Observer.class); - observable.subscribe(aObserver); - - try { - f.t.join(); - } catch (InterruptedException e) { - fail(e.getMessage()); + verify(aObserver, Mockito.never()).onError(any(Throwable.class)); + verify(aObserver, times(1)).onCompleted(); + verify(aObserver, times(1)).onNext("one"); + verify(aObserver, Mockito.never()).onNext("two"); + verify(aObserver, Mockito.never()).onNext("three"); + verify(aObserver, times(1)).onNext("twoResume"); + verify(aObserver, times(1)).onNext("threeResume"); } - verify(aObserver, Mockito.never()).onError(any(Throwable.class)); - verify(aObserver, times(1)).onCompleted(); - verify(aObserver, times(1)).onNext("one"); - verify(aObserver, Mockito.never()).onNext("two"); - verify(aObserver, Mockito.never()).onNext("three"); - verify(aObserver, times(1)).onNext("twoResume"); - verify(aObserver, times(1)).onNext("threeResume"); - } + @Test + public void testMapResumeAsyncNext() { + Subscription sr = mock(Subscription.class); + // Trigger multiple failures + Observable w = Observable.from("one", "fail", "two", "three", "fail"); + // Resume Observable is async + TestObservable f = new TestObservable(sr, "twoResume", "threeResume"); + Observable resume = Observable.create(f); + + // Introduce map function that fails intermittently (Map does not prevent this when the observer is a + // rx.operator incl onErrorResumeNextViaObservable) + w = w.map(new Func1() { + public String call(String s) { + if ("fail".equals(s)) + throw new RuntimeException("Forced Failure"); + System.out.println("BadMapper:" + s); + return s; + } + }); - private static class TestObservable implements Observable.OnSubscribeFunc { + Observable observable = Observable.create(onErrorResumeNextViaObservable(w, resume)); - final Subscription s; - final String[] values; - Thread t = null; + @SuppressWarnings("unchecked") + Observer aObserver = mock(Observer.class); + observable.subscribe(aObserver); - public TestObservable(Subscription s, String... values) { - this.s = s; - this.values = values; + try { + f.t.join(); + } catch (InterruptedException e) { + fail(e.getMessage()); + } + + verify(aObserver, Mockito.never()).onError(any(Throwable.class)); + verify(aObserver, times(1)).onCompleted(); + verify(aObserver, times(1)).onNext("one"); + verify(aObserver, Mockito.never()).onNext("two"); + verify(aObserver, Mockito.never()).onNext("three"); + verify(aObserver, times(1)).onNext("twoResume"); + verify(aObserver, times(1)).onNext("threeResume"); } - @Override - public Subscription onSubscribe(final Observer observer) { - System.out.println("TestObservable subscribed to ..."); - t = new Thread(new Runnable() { + private static class TestObservable implements Observable.OnSubscribeFunc { - @Override - public void run() { - try { - System.out.println("running TestObservable thread"); - for (String s : values) { - if ("fail".equals(s)) - throw new RuntimeException("Forced Failure"); - System.out.println("TestObservable onNext: " + s); - observer.onNext(s); - } - System.out.println("TestObservable onCompleted"); - observer.onCompleted(); - } catch (Throwable e) { - System.out.println("TestObservable onError: " + e); - observer.onError(e); - } + final Subscription s; + final String[] values; + Thread t = null; + + public TestObservable(Subscription s, String... values) { + this.s = s; + this.values = values; } - }); - System.out.println("starting TestObservable thread"); - t.start(); - System.out.println("done starting TestObservable thread"); - return s; + @Override + public Subscription onSubscribe(final Observer observer) { + System.out.println("TestObservable subscribed to ..."); + t = new Thread(new Runnable() { + + @Override + public void run() { + try { + System.out.println("running TestObservable thread"); + for (String s : values) { + if ("fail".equals(s)) + throw new RuntimeException("Forced Failure"); + System.out.println("TestObservable onNext: " + s); + observer.onNext(s); + } + System.out.println("TestObservable onCompleted"); + observer.onCompleted(); + } catch (Throwable e) { + System.out.println("TestObservable onError: " + e); + observer.onError(e); + } + } + + }); + System.out.println("starting TestObservable thread"); + t.start(); + System.out.println("done starting TestObservable thread"); + return s; + } } - } } diff --git a/rxjava-core/src/test/java/rx/operators/OperationOnErrorReturnTest.java b/rxjava-core/src/test/java/rx/operators/OperationOnErrorReturnTest.java index b19e60598f..288f4f4995 100644 --- a/rxjava-core/src/test/java/rx/operators/OperationOnErrorReturnTest.java +++ b/rxjava-core/src/test/java/rx/operators/OperationOnErrorReturnTest.java @@ -1,130 +1,130 @@ package rx.operators; +import static org.junit.Assert.*; +import static org.mockito.Matchers.*; +import static org.mockito.Mockito.*; +import static rx.operators.OperationOnErrorReturn.*; + +import java.util.concurrent.atomic.AtomicReference; + import org.junit.Test; import org.mockito.Mockito; + import rx.Observable; import rx.Observer; import rx.Subscription; import rx.util.functions.Func1; -import java.util.concurrent.atomic.AtomicReference; - -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.fail; -import static org.mockito.Matchers.any; -import static org.mockito.Mockito.*; -import static rx.operators.OperationOnErrorReturn.onErrorReturn; - public class OperationOnErrorReturnTest { - @Test - public void testResumeNext() { - Subscription s = mock(Subscription.class); - TestObservable f = new TestObservable(s, "one"); - Observable w = Observable.create(f); - final AtomicReference capturedException = new AtomicReference(); + @Test + public void testResumeNext() { + Subscription s = mock(Subscription.class); + TestObservable f = new TestObservable(s, "one"); + Observable w = Observable.create(f); + final AtomicReference capturedException = new AtomicReference(); + + Observable observable = Observable.create(onErrorReturn(w, new Func1() { - Observable observable = Observable.create(onErrorReturn(w, new Func1() { + @Override + public String call(Throwable e) { + capturedException.set(e); + return "failure"; + } - @Override - public String call(Throwable e) { - capturedException.set(e); - return "failure"; - } + })); - })); + @SuppressWarnings("unchecked") + Observer aObserver = mock(Observer.class); + observable.subscribe(aObserver); - @SuppressWarnings("unchecked") - Observer aObserver = mock(Observer.class); - observable.subscribe(aObserver); + try { + f.t.join(); + } catch (InterruptedException e) { + fail(e.getMessage()); + } - try { - f.t.join(); - } catch (InterruptedException e) { - fail(e.getMessage()); + verify(aObserver, Mockito.never()).onError(any(Throwable.class)); + verify(aObserver, times(1)).onCompleted(); + verify(aObserver, times(1)).onNext("one"); + verify(aObserver, times(1)).onNext("failure"); + assertNotNull(capturedException.get()); } - verify(aObserver, Mockito.never()).onError(any(Throwable.class)); - verify(aObserver, times(1)).onCompleted(); - verify(aObserver, times(1)).onNext("one"); - verify(aObserver, times(1)).onNext("failure"); - assertNotNull(capturedException.get()); - } - - /** - * Test that when a function throws an exception this is propagated through onError - */ - @Test - public void testFunctionThrowsError() { - Subscription s = mock(Subscription.class); - TestObservable f = new TestObservable(s, "one"); - Observable w = Observable.create(f); - final AtomicReference capturedException = new AtomicReference(); - - Observable observable = Observable.create(onErrorReturn(w, new Func1() { - - @Override - public String call(Throwable e) { - capturedException.set(e); - throw new RuntimeException("exception from function"); - } - - })); - - @SuppressWarnings("unchecked") - Observer aObserver = mock(Observer.class); - observable.subscribe(aObserver); - - try { - f.t.join(); - } catch (InterruptedException e) { - fail(e.getMessage()); - } + /** + * Test that when a function throws an exception this is propagated through onError + */ + @Test + public void testFunctionThrowsError() { + Subscription s = mock(Subscription.class); + TestObservable f = new TestObservable(s, "one"); + Observable w = Observable.create(f); + final AtomicReference capturedException = new AtomicReference(); + + Observable observable = Observable.create(onErrorReturn(w, new Func1() { + + @Override + public String call(Throwable e) { + capturedException.set(e); + throw new RuntimeException("exception from function"); + } - // we should get the "one" value before the error - verify(aObserver, times(1)).onNext("one"); + })); - // we should have received an onError call on the Observer since the resume function threw an exception - verify(aObserver, times(1)).onError(any(Throwable.class)); - verify(aObserver, times(0)).onCompleted(); - assertNotNull(capturedException.get()); - } + @SuppressWarnings("unchecked") + Observer aObserver = mock(Observer.class); + observable.subscribe(aObserver); - private static class TestObservable implements Observable.OnSubscribeFunc { + try { + f.t.join(); + } catch (InterruptedException e) { + fail(e.getMessage()); + } - final Subscription s; - final String[] values; - Thread t = null; + // we should get the "one" value before the error + verify(aObserver, times(1)).onNext("one"); - public TestObservable(Subscription s, String... values) { - this.s = s; - this.values = values; + // we should have received an onError call on the Observer since the resume function threw an exception + verify(aObserver, times(1)).onError(any(Throwable.class)); + verify(aObserver, times(0)).onCompleted(); + assertNotNull(capturedException.get()); } - @Override - public Subscription onSubscribe(final Observer observer) { - System.out.println("TestObservable subscribed to ..."); - t = new Thread(new Runnable() { + private static class TestObservable implements Observable.OnSubscribeFunc { - @Override - public void run() { - try { - System.out.println("running TestObservable thread"); - for (String s : values) { - System.out.println("TestObservable onNext: " + s); - observer.onNext(s); - } - throw new RuntimeException("Forced Failure"); - } catch (Throwable e) { - observer.onError(e); - } + final Subscription s; + final String[] values; + Thread t = null; + + public TestObservable(Subscription s, String... values) { + this.s = s; + this.values = values; } - }); - System.out.println("starting TestObservable thread"); - t.start(); - System.out.println("done starting TestObservable thread"); - return s; + @Override + public Subscription onSubscribe(final Observer observer) { + System.out.println("TestObservable subscribed to ..."); + t = new Thread(new Runnable() { + + @Override + public void run() { + try { + System.out.println("running TestObservable thread"); + for (String s : values) { + System.out.println("TestObservable onNext: " + s); + observer.onNext(s); + } + throw new RuntimeException("Forced Failure"); + } catch (Throwable e) { + observer.onError(e); + } + } + + }); + System.out.println("starting TestObservable thread"); + t.start(); + System.out.println("done starting TestObservable thread"); + return s; + } } - } } diff --git a/rxjava-core/src/test/java/rx/operators/OperationOnExceptionResumeNextViaObservableTest.java b/rxjava-core/src/test/java/rx/operators/OperationOnExceptionResumeNextViaObservableTest.java index ee85ed7517..18326a306b 100644 --- a/rxjava-core/src/test/java/rx/operators/OperationOnExceptionResumeNextViaObservableTest.java +++ b/rxjava-core/src/test/java/rx/operators/OperationOnExceptionResumeNextViaObservableTest.java @@ -1,224 +1,225 @@ package rx.operators; +import static org.junit.Assert.*; +import static org.mockito.Matchers.*; +import static org.mockito.Mockito.*; +import static rx.operators.OperationOnExceptionResumeNextViaObservable.*; + import org.junit.Test; import org.mockito.Mockito; + import rx.Observable; import rx.Observer; import rx.Subscription; import rx.util.functions.Func1; -import static org.junit.Assert.fail; -import static org.mockito.Matchers.any; -import static org.mockito.Mockito.*; -import static rx.operators.OperationOnExceptionResumeNextViaObservable.onExceptionResumeNextViaObservable; - public class OperationOnExceptionResumeNextViaObservableTest { - @Test - public void testResumeNextWithException() { - Subscription s = mock(Subscription.class); - // Trigger failure on second element - TestObservable f = new TestObservable(s, "one", "EXCEPTION", "two", "three"); - Observable w = Observable.create(f); - Observable resume = Observable.from("twoResume", "threeResume"); - Observable observable = Observable.create(onExceptionResumeNextViaObservable(w, resume)); - - @SuppressWarnings("unchecked") - Observer aObserver = mock(Observer.class); - observable.subscribe(aObserver); - - try { - f.t.join(); - } catch (InterruptedException e) { - fail(e.getMessage()); - } + @Test + public void testResumeNextWithException() { + Subscription s = mock(Subscription.class); + // Trigger failure on second element + TestObservable f = new TestObservable(s, "one", "EXCEPTION", "two", "three"); + Observable w = Observable.create(f); + Observable resume = Observable.from("twoResume", "threeResume"); + Observable observable = Observable.create(onExceptionResumeNextViaObservable(w, resume)); + + @SuppressWarnings("unchecked") + Observer aObserver = mock(Observer.class); + observable.subscribe(aObserver); + + try { + f.t.join(); + } catch (InterruptedException e) { + fail(e.getMessage()); + } - verify(aObserver, times(1)).onNext("one"); - verify(aObserver, Mockito.never()).onNext("two"); - verify(aObserver, Mockito.never()).onNext("three"); - verify(aObserver, times(1)).onNext("twoResume"); - verify(aObserver, times(1)).onNext("threeResume"); - verify(aObserver, Mockito.never()).onError(any(Throwable.class)); - verify(aObserver, times(1)).onCompleted(); - verifyNoMoreInteractions(aObserver); - } - - @Test - public void testResumeNextWithRuntimeException() { - Subscription s = mock(Subscription.class); - // Trigger failure on second element - TestObservable f = new TestObservable(s, "one", "RUNTIMEEXCEPTION", "two", "three"); - Observable w = Observable.create(f); - Observable resume = Observable.from("twoResume", "threeResume"); - Observable observable = Observable.create(onExceptionResumeNextViaObservable(w, resume)); - - @SuppressWarnings("unchecked") - Observer aObserver = mock(Observer.class); - observable.subscribe(aObserver); - - try { - f.t.join(); - } catch (InterruptedException e) { - fail(e.getMessage()); + verify(aObserver, times(1)).onNext("one"); + verify(aObserver, Mockito.never()).onNext("two"); + verify(aObserver, Mockito.never()).onNext("three"); + verify(aObserver, times(1)).onNext("twoResume"); + verify(aObserver, times(1)).onNext("threeResume"); + verify(aObserver, Mockito.never()).onError(any(Throwable.class)); + verify(aObserver, times(1)).onCompleted(); + verifyNoMoreInteractions(aObserver); } - verify(aObserver, times(1)).onNext("one"); - verify(aObserver, Mockito.never()).onNext("two"); - verify(aObserver, Mockito.never()).onNext("three"); - verify(aObserver, times(1)).onNext("twoResume"); - verify(aObserver, times(1)).onNext("threeResume"); - verify(aObserver, Mockito.never()).onError(any(Throwable.class)); - verify(aObserver, times(1)).onCompleted(); - verifyNoMoreInteractions(aObserver); - } - - @Test - public void testThrowablePassesThru() { - Subscription s = mock(Subscription.class); - // Trigger failure on second element - TestObservable f = new TestObservable(s, "one", "THROWABLE", "two", "three"); - Observable w = Observable.create(f); - Observable resume = Observable.from("twoResume", "threeResume"); - Observable observable = Observable.create(onExceptionResumeNextViaObservable(w, resume)); - - @SuppressWarnings("unchecked") - Observer aObserver = mock(Observer.class); - observable.subscribe(aObserver); - - try { - f.t.join(); - } catch (InterruptedException e) { - fail(e.getMessage()); + @Test + public void testResumeNextWithRuntimeException() { + Subscription s = mock(Subscription.class); + // Trigger failure on second element + TestObservable f = new TestObservable(s, "one", "RUNTIMEEXCEPTION", "two", "three"); + Observable w = Observable.create(f); + Observable resume = Observable.from("twoResume", "threeResume"); + Observable observable = Observable.create(onExceptionResumeNextViaObservable(w, resume)); + + @SuppressWarnings("unchecked") + Observer aObserver = mock(Observer.class); + observable.subscribe(aObserver); + + try { + f.t.join(); + } catch (InterruptedException e) { + fail(e.getMessage()); + } + + verify(aObserver, times(1)).onNext("one"); + verify(aObserver, Mockito.never()).onNext("two"); + verify(aObserver, Mockito.never()).onNext("three"); + verify(aObserver, times(1)).onNext("twoResume"); + verify(aObserver, times(1)).onNext("threeResume"); + verify(aObserver, Mockito.never()).onError(any(Throwable.class)); + verify(aObserver, times(1)).onCompleted(); + verifyNoMoreInteractions(aObserver); } - verify(aObserver, times(1)).onNext("one"); - verify(aObserver, never()).onNext("two"); - verify(aObserver, never()).onNext("three"); - verify(aObserver, never()).onNext("twoResume"); - verify(aObserver, never()).onNext("threeResume"); - verify(aObserver, times(1)).onError(any(Throwable.class)); - verify(aObserver, never()).onCompleted(); - verifyNoMoreInteractions(aObserver); - } - - @Test - public void testErrorPassesThru() { - Subscription s = mock(Subscription.class); - // Trigger failure on second element - TestObservable f = new TestObservable(s, "one", "ERROR", "two", "three"); - Observable w = Observable.create(f); - Observable resume = Observable.from("twoResume", "threeResume"); - Observable observable = Observable.create(onExceptionResumeNextViaObservable(w, resume)); - - @SuppressWarnings("unchecked") - Observer aObserver = mock(Observer.class); - observable.subscribe(aObserver); - - try { - f.t.join(); - } catch (InterruptedException e) { - fail(e.getMessage()); + @Test + public void testThrowablePassesThru() { + Subscription s = mock(Subscription.class); + // Trigger failure on second element + TestObservable f = new TestObservable(s, "one", "THROWABLE", "two", "three"); + Observable w = Observable.create(f); + Observable resume = Observable.from("twoResume", "threeResume"); + Observable observable = Observable.create(onExceptionResumeNextViaObservable(w, resume)); + + @SuppressWarnings("unchecked") + Observer aObserver = mock(Observer.class); + observable.subscribe(aObserver); + + try { + f.t.join(); + } catch (InterruptedException e) { + fail(e.getMessage()); + } + + verify(aObserver, times(1)).onNext("one"); + verify(aObserver, never()).onNext("two"); + verify(aObserver, never()).onNext("three"); + verify(aObserver, never()).onNext("twoResume"); + verify(aObserver, never()).onNext("threeResume"); + verify(aObserver, times(1)).onError(any(Throwable.class)); + verify(aObserver, never()).onCompleted(); + verifyNoMoreInteractions(aObserver); } - verify(aObserver, times(1)).onNext("one"); - verify(aObserver, never()).onNext("two"); - verify(aObserver, never()).onNext("three"); - verify(aObserver, never()).onNext("twoResume"); - verify(aObserver, never()).onNext("threeResume"); - verify(aObserver, times(1)).onError(any(Throwable.class)); - verify(aObserver, never()).onCompleted(); - verifyNoMoreInteractions(aObserver); - } - - @Test - public void testMapResumeAsyncNext() { - Subscription sr = mock(Subscription.class); - // Trigger multiple failures - Observable w = Observable.from("one", "fail", "two", "three", "fail"); - // Resume Observable is async - TestObservable f = new TestObservable(sr, "twoResume", "threeResume"); - Observable resume = Observable.create(f); - - // Introduce map function that fails intermittently (Map does not prevent this when the observer is a - // rx.operator incl onErrorResumeNextViaObservable) - w = w.map(new Func1() { - public String call(String s) { - if ("fail".equals(s)) - throw new RuntimeException("Forced Failure"); - System.out.println("BadMapper:" + s); - return s; - } - }); - - Observable observable = Observable.create(onExceptionResumeNextViaObservable(w, resume)); - - @SuppressWarnings("unchecked") - Observer aObserver = mock(Observer.class); - observable.subscribe(aObserver); - - try { - // if the thread gets started (which it shouldn't if it's working correctly) - if (f.t != null) { - f.t.join(); - } - } catch (InterruptedException e) { - fail(e.getMessage()); + @Test + public void testErrorPassesThru() { + Subscription s = mock(Subscription.class); + // Trigger failure on second element + TestObservable f = new TestObservable(s, "one", "ERROR", "two", "three"); + Observable w = Observable.create(f); + Observable resume = Observable.from("twoResume", "threeResume"); + Observable observable = Observable.create(onExceptionResumeNextViaObservable(w, resume)); + + @SuppressWarnings("unchecked") + Observer aObserver = mock(Observer.class); + observable.subscribe(aObserver); + + try { + f.t.join(); + } catch (InterruptedException e) { + fail(e.getMessage()); + } + + verify(aObserver, times(1)).onNext("one"); + verify(aObserver, never()).onNext("two"); + verify(aObserver, never()).onNext("three"); + verify(aObserver, never()).onNext("twoResume"); + verify(aObserver, never()).onNext("threeResume"); + verify(aObserver, times(1)).onError(any(Throwable.class)); + verify(aObserver, never()).onCompleted(); + verifyNoMoreInteractions(aObserver); } - verify(aObserver, times(1)).onNext("one"); - verify(aObserver, never()).onNext("two"); - verify(aObserver, never()).onNext("three"); - verify(aObserver, times(1)).onNext("twoResume"); - verify(aObserver, times(1)).onNext("threeResume"); - verify(aObserver, Mockito.never()).onError(any(Throwable.class)); - verify(aObserver, times(1)).onCompleted(); - } + @Test + public void testMapResumeAsyncNext() { + Subscription sr = mock(Subscription.class); + // Trigger multiple failures + Observable w = Observable.from("one", "fail", "two", "three", "fail"); + // Resume Observable is async + TestObservable f = new TestObservable(sr, "twoResume", "threeResume"); + Observable resume = Observable.create(f); + + // Introduce map function that fails intermittently (Map does not prevent this when the observer is a + // rx.operator incl onErrorResumeNextViaObservable) + w = w.map(new Func1() { + public String call(String s) { + if ("fail".equals(s)) + throw new RuntimeException("Forced Failure"); + System.out.println("BadMapper:" + s); + return s; + } + }); + + Observable observable = Observable.create(onExceptionResumeNextViaObservable(w, resume)); - private static class TestObservable implements Observable.OnSubscribeFunc { + @SuppressWarnings("unchecked") + Observer aObserver = mock(Observer.class); + observable.subscribe(aObserver); - final Subscription s; - final String[] values; - Thread t = null; + try { + // if the thread gets started (which it shouldn't if it's working correctly) + if (f.t != null) { + f.t.join(); + } + } catch (InterruptedException e) { + fail(e.getMessage()); + } - public TestObservable(Subscription s, String... values) { - this.s = s; - this.values = values; + verify(aObserver, times(1)).onNext("one"); + verify(aObserver, never()).onNext("two"); + verify(aObserver, never()).onNext("three"); + verify(aObserver, times(1)).onNext("twoResume"); + verify(aObserver, times(1)).onNext("threeResume"); + verify(aObserver, Mockito.never()).onError(any(Throwable.class)); + verify(aObserver, times(1)).onCompleted(); } - @Override - public Subscription onSubscribe(final Observer observer) { - System.out.println("TestObservable subscribed to ..."); - t = new Thread(new Runnable() { + private static class TestObservable implements Observable.OnSubscribeFunc { - @Override - public void run() { - try { - System.out.println("running TestObservable thread"); - for (String s : values) { - if ("EXCEPTION".equals(s)) - throw new Exception("Forced Exception"); - else if ("RUNTIMEEXCEPTION".equals(s)) - throw new RuntimeException("Forced RuntimeException"); - else if ("ERROR".equals(s)) - throw new Error("Forced Error"); - else if ("THROWABLE".equals(s)) - throw new Throwable("Forced Throwable"); - System.out.println("TestObservable onNext: " + s); - observer.onNext(s); - } - System.out.println("TestObservable onCompleted"); - observer.onCompleted(); - } catch (Throwable e) { - System.out.println("TestObservable onError: " + e); - observer.onError(e); - } + final Subscription s; + final String[] values; + Thread t = null; + + public TestObservable(Subscription s, String... values) { + this.s = s; + this.values = values; } - }); - System.out.println("starting TestObservable thread"); - t.start(); - System.out.println("done starting TestObservable thread"); - return s; + @Override + public Subscription onSubscribe(final Observer observer) { + System.out.println("TestObservable subscribed to ..."); + t = new Thread(new Runnable() { + + @Override + public void run() { + try { + System.out.println("running TestObservable thread"); + for (String s : values) { + if ("EXCEPTION".equals(s)) + throw new Exception("Forced Exception"); + else if ("RUNTIMEEXCEPTION".equals(s)) + throw new RuntimeException("Forced RuntimeException"); + else if ("ERROR".equals(s)) + throw new Error("Forced Error"); + else if ("THROWABLE".equals(s)) + throw new Throwable("Forced Throwable"); + System.out.println("TestObservable onNext: " + s); + observer.onNext(s); + } + System.out.println("TestObservable onCompleted"); + observer.onCompleted(); + } catch (Throwable e) { + System.out.println("TestObservable onError: " + e); + observer.onError(e); + } + } + + }); + System.out.println("starting TestObservable thread"); + t.start(); + System.out.println("done starting TestObservable thread"); + return s; + } } - } } diff --git a/rxjava-core/src/test/java/rx/operators/OperationParallelTest.java b/rxjava-core/src/test/java/rx/operators/OperationParallelTest.java index fd79f9e9fb..2a0959a14f 100644 --- a/rxjava-core/src/test/java/rx/operators/OperationParallelTest.java +++ b/rxjava-core/src/test/java/rx/operators/OperationParallelTest.java @@ -1,45 +1,46 @@ package rx.operators; +import static org.junit.Assert.*; + +import java.util.concurrent.atomic.AtomicInteger; + import org.junit.Test; + import rx.Observable; import rx.util.functions.Action1; import rx.util.functions.Func1; -import java.util.concurrent.atomic.AtomicInteger; - -import static org.junit.Assert.assertEquals; - public class OperationParallelTest { - @Test - public void testParallel() { - int NUM = 1000; - final AtomicInteger count = new AtomicInteger(); - Observable.range(1, NUM).parallel( - new Func1, Observable>() { - - @Override - public Observable call(Observable o) { - return o.map(new Func1() { - - @Override - public Integer[] call(Integer t) { - return new Integer[]{t, t * 99}; - } - - }); - } - }).toBlockingObservable().forEach(new Action1() { - - @Override - public void call(Integer[] v) { - count.incrementAndGet(); - System.out.println("V: " + v[0] + " R: " + v[1] + " Thread: " + Thread.currentThread()); - } - - }); - - // just making sure we finish and get the number we expect - assertEquals(NUM, count.get()); - } + @Test + public void testParallel() { + int NUM = 1000; + final AtomicInteger count = new AtomicInteger(); + Observable.range(1, NUM).parallel( + new Func1, Observable>() { + + @Override + public Observable call(Observable o) { + return o.map(new Func1() { + + @Override + public Integer[] call(Integer t) { + return new Integer[] { t, t * 99 }; + } + + }); + } + }).toBlockingObservable().forEach(new Action1() { + + @Override + public void call(Integer[] v) { + count.incrementAndGet(); + System.out.println("V: " + v[0] + " R: " + v[1] + " Thread: " + Thread.currentThread()); + } + + }); + + // just making sure we finish and get the number we expect + assertEquals(NUM, count.get()); + } } diff --git a/rxjava-core/src/test/java/rx/operators/OperationRetryTest.java b/rxjava-core/src/test/java/rx/operators/OperationRetryTest.java index 5132b84219..40845167c4 100644 --- a/rxjava-core/src/test/java/rx/operators/OperationRetryTest.java +++ b/rxjava-core/src/test/java/rx/operators/OperationRetryTest.java @@ -1,114 +1,115 @@ package rx.operators; +import static org.mockito.Matchers.*; +import static org.mockito.Mockito.*; +import static rx.operators.OperationRetry.*; + +import java.util.concurrent.atomic.AtomicInteger; + import org.junit.Test; import org.mockito.InOrder; + import rx.Observable; import rx.Observer; import rx.Subscription; import rx.subscriptions.Subscriptions; -import java.util.concurrent.atomic.AtomicInteger; +public class OperationRetryTest { -import static org.mockito.Matchers.any; -import static org.mockito.Mockito.*; -import static rx.operators.OperationRetry.retry; + @Test + public void testOriginFails() { + @SuppressWarnings("unchecked") + Observer observer = mock(Observer.class); + Observable origin = Observable.create(new FuncWithErrors(2)); + origin.subscribe(observer); + + InOrder inOrder = inOrder(observer); + inOrder.verify(observer, times(1)).onNext("beginningEveryTime"); + inOrder.verify(observer, times(1)).onError(any(RuntimeException.class)); + inOrder.verify(observer, never()).onNext("onSuccessOnly"); + inOrder.verify(observer, never()).onCompleted(); + } -public class OperationRetryTest { + @Test + public void testRetryFail() { + int NUM_RETRIES = 1; + int NUM_FAILURES = 2; + @SuppressWarnings("unchecked") + Observer observer = mock(Observer.class); + Observable origin = Observable.create(new FuncWithErrors(NUM_FAILURES)); + Observable.create(retry(origin, NUM_RETRIES)).subscribe(observer); + + InOrder inOrder = inOrder(observer); + // should show 2 attempts (first time fail, second time (1st retry) fail) + inOrder.verify(observer, times(1 + NUM_RETRIES)).onNext("beginningEveryTime"); + // should only retry once, fail again and emit onError + inOrder.verify(observer, times(1)).onError(any(RuntimeException.class)); + // no success + inOrder.verify(observer, never()).onNext("onSuccessOnly"); + inOrder.verify(observer, never()).onCompleted(); + inOrder.verifyNoMoreInteractions(); + } + + @Test + public void testRetrySuccess() { + int NUM_RETRIES = 3; + int NUM_FAILURES = 2; + @SuppressWarnings("unchecked") + Observer observer = mock(Observer.class); + Observable origin = Observable.create(new FuncWithErrors(NUM_FAILURES)); + Observable.create(retry(origin, NUM_RETRIES)).subscribe(observer); + + InOrder inOrder = inOrder(observer); + // should show 3 attempts + inOrder.verify(observer, times(1 + NUM_FAILURES)).onNext("beginningEveryTime"); + // should have no errors + inOrder.verify(observer, never()).onError(any(Throwable.class)); + // should have a single success + inOrder.verify(observer, times(1)).onNext("onSuccessOnly"); + // should have a single successful onCompleted + inOrder.verify(observer, times(1)).onCompleted(); + inOrder.verifyNoMoreInteractions(); + } - @Test - public void testOriginFails() { - @SuppressWarnings("unchecked") - Observer observer = mock(Observer.class); - Observable origin = Observable.create(new FuncWithErrors(2)); - origin.subscribe(observer); - - InOrder inOrder = inOrder(observer); - inOrder.verify(observer, times(1)).onNext("beginningEveryTime"); - inOrder.verify(observer, times(1)).onError(any(RuntimeException.class)); - inOrder.verify(observer, never()).onNext("onSuccessOnly"); - inOrder.verify(observer, never()).onCompleted(); - } - - @Test - public void testRetryFail() { - int NUM_RETRIES = 1; - int NUM_FAILURES = 2; - @SuppressWarnings("unchecked") - Observer observer = mock(Observer.class); - Observable origin = Observable.create(new FuncWithErrors(NUM_FAILURES)); - Observable.create(retry(origin, NUM_RETRIES)).subscribe(observer); - - InOrder inOrder = inOrder(observer); - // should show 2 attempts (first time fail, second time (1st retry) fail) - inOrder.verify(observer, times(1 + NUM_RETRIES)).onNext("beginningEveryTime"); - // should only retry once, fail again and emit onError - inOrder.verify(observer, times(1)).onError(any(RuntimeException.class)); - // no success - inOrder.verify(observer, never()).onNext("onSuccessOnly"); - inOrder.verify(observer, never()).onCompleted(); - inOrder.verifyNoMoreInteractions(); - } - - @Test - public void testRetrySuccess() { - int NUM_RETRIES = 3; - int NUM_FAILURES = 2; - @SuppressWarnings("unchecked") - Observer observer = mock(Observer.class); - Observable origin = Observable.create(new FuncWithErrors(NUM_FAILURES)); - Observable.create(retry(origin, NUM_RETRIES)).subscribe(observer); - - InOrder inOrder = inOrder(observer); - // should show 3 attempts - inOrder.verify(observer, times(1 + NUM_FAILURES)).onNext("beginningEveryTime"); - // should have no errors - inOrder.verify(observer, never()).onError(any(Throwable.class)); - // should have a single success - inOrder.verify(observer, times(1)).onNext("onSuccessOnly"); - // should have a single successful onCompleted - inOrder.verify(observer, times(1)).onCompleted(); - inOrder.verifyNoMoreInteractions(); - } - - @Test - public void testInfiniteRetry() { - int NUM_FAILURES = 20; - @SuppressWarnings("unchecked") - Observer observer = mock(Observer.class); - Observable origin = Observable.create(new FuncWithErrors(NUM_FAILURES)); - Observable.create(retry(origin)).subscribe(observer); - - InOrder inOrder = inOrder(observer); - // should show 3 attempts - inOrder.verify(observer, times(1 + NUM_FAILURES)).onNext("beginningEveryTime"); - // should have no errors - inOrder.verify(observer, never()).onError(any(Throwable.class)); - // should have a single success - inOrder.verify(observer, times(1)).onNext("onSuccessOnly"); - // should have a single successful onCompleted - inOrder.verify(observer, times(1)).onCompleted(); - inOrder.verifyNoMoreInteractions(); - } - - public static class FuncWithErrors implements Observable.OnSubscribeFunc { - - private final int numFailures; - private final AtomicInteger count = new AtomicInteger(0); - - FuncWithErrors(int count) { - this.numFailures = count; + @Test + public void testInfiniteRetry() { + int NUM_FAILURES = 20; + @SuppressWarnings("unchecked") + Observer observer = mock(Observer.class); + Observable origin = Observable.create(new FuncWithErrors(NUM_FAILURES)); + Observable.create(retry(origin)).subscribe(observer); + + InOrder inOrder = inOrder(observer); + // should show 3 attempts + inOrder.verify(observer, times(1 + NUM_FAILURES)).onNext("beginningEveryTime"); + // should have no errors + inOrder.verify(observer, never()).onError(any(Throwable.class)); + // should have a single success + inOrder.verify(observer, times(1)).onNext("onSuccessOnly"); + // should have a single successful onCompleted + inOrder.verify(observer, times(1)).onCompleted(); + inOrder.verifyNoMoreInteractions(); } - @Override - public Subscription onSubscribe(Observer o) { - o.onNext("beginningEveryTime"); - if (count.incrementAndGet() <= numFailures) { - o.onError(new RuntimeException("forced failure: " + count.get())); - } else { - o.onNext("onSuccessOnly"); - o.onCompleted(); - } - return Subscriptions.empty(); + public static class FuncWithErrors implements Observable.OnSubscribeFunc { + + private final int numFailures; + private final AtomicInteger count = new AtomicInteger(0); + + FuncWithErrors(int count) { + this.numFailures = count; + } + + @Override + public Subscription onSubscribe(Observer o) { + o.onNext("beginningEveryTime"); + if (count.incrementAndGet() <= numFailures) { + o.onError(new RuntimeException("forced failure: " + count.get())); + } else { + o.onNext("onSuccessOnly"); + o.onCompleted(); + } + return Subscriptions.empty(); + } } - } } diff --git a/rxjava-core/src/test/java/rx/operators/OperationSampleTest.java b/rxjava-core/src/test/java/rx/operators/OperationSampleTest.java index 789fa9cf2f..7ef3906eaa 100644 --- a/rxjava-core/src/test/java/rx/operators/OperationSampleTest.java +++ b/rxjava-core/src/test/java/rx/operators/OperationSampleTest.java @@ -1,8 +1,14 @@ package rx.operators; +import static org.mockito.Matchers.*; +import static org.mockito.Mockito.*; + +import java.util.concurrent.TimeUnit; + import org.junit.Before; import org.junit.Test; import org.mockito.InOrder; + import rx.Observable; import rx.Observer; import rx.Subscription; @@ -10,82 +16,78 @@ import rx.subscriptions.Subscriptions; import rx.util.functions.Action0; -import java.util.concurrent.TimeUnit; - -import static org.mockito.Matchers.any; -import static org.mockito.Mockito.*; - public class OperationSampleTest { - private TestScheduler scheduler; - private Observer observer; + private TestScheduler scheduler; + private Observer observer; - @Before - @SuppressWarnings("unchecked") // due to mocking - public void before() { - scheduler = new TestScheduler(); - observer = mock(Observer.class); - } + @Before + @SuppressWarnings("unchecked") + // due to mocking + public void before() { + scheduler = new TestScheduler(); + observer = mock(Observer.class); + } - @Test - public void testSample() { - Observable source = Observable.create(new Observable.OnSubscribeFunc() { - @Override - public Subscription onSubscribe(final Observer observer1) { - scheduler.schedule(new Action0() { - @Override - public void call() { - observer1.onNext(1L); - } - }, 1, TimeUnit.SECONDS); - scheduler.schedule(new Action0() { - @Override - public void call() { - observer1.onNext(2L); - } - }, 2, TimeUnit.SECONDS); - scheduler.schedule(new Action0() { - @Override - public void call() { - observer1.onCompleted(); - } - }, 3, TimeUnit.SECONDS); + @Test + public void testSample() { + Observable source = Observable.create(new Observable.OnSubscribeFunc() { + @Override + public Subscription onSubscribe(final Observer observer1) { + scheduler.schedule(new Action0() { + @Override + public void call() { + observer1.onNext(1L); + } + }, 1, TimeUnit.SECONDS); + scheduler.schedule(new Action0() { + @Override + public void call() { + observer1.onNext(2L); + } + }, 2, TimeUnit.SECONDS); + scheduler.schedule(new Action0() { + @Override + public void call() { + observer1.onCompleted(); + } + }, 3, TimeUnit.SECONDS); - return Subscriptions.empty(); - } - }); + return Subscriptions.empty(); + } + }); - Observable sampled = Observable.create(OperationSample.sample(source, 400L, TimeUnit.MILLISECONDS, scheduler)); - sampled.subscribe(observer); + Observable sampled = Observable.create(OperationSample.sample(source, 400L, TimeUnit.MILLISECONDS, scheduler)); + sampled.subscribe(observer); - InOrder inOrder = inOrder(observer); + InOrder inOrder = inOrder(observer); - scheduler.advanceTimeTo(800L, TimeUnit.MILLISECONDS); - verify(observer, never()).onNext(any(Long.class)); - verify(observer, never()).onCompleted(); - verify(observer, never()).onError(any(Throwable.class)); + scheduler.advanceTimeTo(800L, TimeUnit.MILLISECONDS); + verify(observer, never()).onNext(any(Long.class)); + verify(observer, never()).onCompleted(); + verify(observer, never()).onError(any(Throwable.class)); - scheduler.advanceTimeTo(1200L, TimeUnit.MILLISECONDS); - inOrder.verify(observer, times(1)).onNext(1L); - verify(observer, never()).onNext(2L); - verify(observer, never()).onCompleted(); - verify(observer, never()).onError(any(Throwable.class)); + scheduler.advanceTimeTo(1200L, TimeUnit.MILLISECONDS); + inOrder.verify(observer, times(1)).onNext(1L); + verify(observer, never()).onNext(2L); + verify(observer, never()).onCompleted(); + verify(observer, never()).onError(any(Throwable.class)); - scheduler.advanceTimeTo(1600L, TimeUnit.MILLISECONDS); - inOrder.verify(observer, times(1)).onNext(1L); - verify(observer, never()).onNext(2L); - verify(observer, never()).onCompleted(); - verify(observer, never()).onError(any(Throwable.class)); + scheduler.advanceTimeTo(1600L, TimeUnit.MILLISECONDS); + inOrder.verify(observer, times(1)).onNext(1L); + verify(observer, never()).onNext(2L); + verify(observer, never()).onCompleted(); + verify(observer, never()).onError(any(Throwable.class)); - scheduler.advanceTimeTo(2000L, TimeUnit.MILLISECONDS); - inOrder.verify(observer, never()).onNext(1L); - inOrder.verify(observer, times(1)).onNext(2L); - verify(observer, never()).onCompleted(); - verify(observer, never()).onError(any(Throwable.class)); + scheduler.advanceTimeTo(2000L, TimeUnit.MILLISECONDS); + inOrder.verify(observer, never()).onNext(1L); + inOrder.verify(observer, times(1)).onNext(2L); + verify(observer, never()).onCompleted(); + verify(observer, never()).onError(any(Throwable.class)); - scheduler.advanceTimeTo(3000L, TimeUnit.MILLISECONDS); - inOrder.verify(observer, never()).onNext(1L); - inOrder.verify(observer, times(2)).onNext(2L); - verify(observer, times(1)).onCompleted(); - verify(observer, never()).onError(any(Throwable.class)); - } + scheduler.advanceTimeTo(3000L, TimeUnit.MILLISECONDS); + inOrder.verify(observer, never()).onNext(1L); + inOrder.verify(observer, times(2)).onNext(2L); + verify(observer, times(1)).onCompleted(); + verify(observer, never()).onError(any(Throwable.class)); + } } diff --git a/rxjava-core/src/test/java/rx/operators/OperationScanTest.java b/rxjava-core/src/test/java/rx/operators/OperationScanTest.java index 691df4b0f1..5c28f9efdf 100644 --- a/rxjava-core/src/test/java/rx/operators/OperationScanTest.java +++ b/rxjava-core/src/test/java/rx/operators/OperationScanTest.java @@ -1,102 +1,100 @@ package rx.operators; +import static org.mockito.Matchers.*; +import static org.mockito.Mockito.*; +import static rx.operators.OperationScan.*; + import org.junit.Before; import org.junit.Test; import org.mockito.MockitoAnnotations; + import rx.Observable; import rx.Observer; import rx.util.functions.Func2; -import static org.mockito.Matchers.any; -import static org.mockito.Matchers.anyInt; -import static org.mockito.Matchers.anyString; -import static org.mockito.Mockito.*; -import static rx.operators.OperationScan.scan; - public class OperationScanTest { - - @Before - public void before() { - MockitoAnnotations.initMocks(this); - } - - @Test - public void testScanIntegersWithInitialValue() { - @SuppressWarnings("unchecked") - Observer observer = mock(Observer.class); - - Observable observable = Observable.from(1, 2, 3); - - Observable m = Observable.create(scan(observable, "", new Func2() { - - @Override - public String call(String s, Integer n) { - return s + n.toString(); - } - - })); - m.subscribe(observer); - - verify(observer, never()).onError(any(Throwable.class)); - verify(observer, times(1)).onNext(""); - verify(observer, times(1)).onNext("1"); - verify(observer, times(1)).onNext("12"); - verify(observer, times(1)).onNext("123"); - verify(observer, times(4)).onNext(anyString()); - verify(observer, times(1)).onCompleted(); - verify(observer, never()).onError(any(Throwable.class)); - } - - @Test - public void testScanIntegersWithoutInitialValue() { - @SuppressWarnings("unchecked") - Observer Observer = mock(Observer.class); - - Observable observable = Observable.from(1, 2, 3); - - Observable m = Observable.create(scan(observable, new Func2() { - - @Override - public Integer call(Integer t1, Integer t2) { - return t1 + t2; - } - - })); - m.subscribe(Observer); - - verify(Observer, never()).onError(any(Throwable.class)); - verify(Observer, never()).onNext(0); - verify(Observer, times(1)).onNext(1); - verify(Observer, times(1)).onNext(3); - verify(Observer, times(1)).onNext(6); - verify(Observer, times(3)).onNext(anyInt()); - verify(Observer, times(1)).onCompleted(); - verify(Observer, never()).onError(any(Throwable.class)); - } - - @Test - public void testScanIntegersWithoutInitialValueAndOnlyOneValue() { - @SuppressWarnings("unchecked") - Observer Observer = mock(Observer.class); - - Observable observable = Observable.from(1); - - Observable m = Observable.create(scan(observable, new Func2() { - - @Override - public Integer call(Integer t1, Integer t2) { - return t1 + t2; - } - - })); - m.subscribe(Observer); - - verify(Observer, never()).onError(any(Throwable.class)); - verify(Observer, never()).onNext(0); - verify(Observer, times(1)).onNext(1); - verify(Observer, times(1)).onNext(anyInt()); - verify(Observer, times(1)).onCompleted(); - verify(Observer, never()).onError(any(Throwable.class)); - } + @Before + public void before() { + MockitoAnnotations.initMocks(this); + } + + @Test + public void testScanIntegersWithInitialValue() { + @SuppressWarnings("unchecked") + Observer observer = mock(Observer.class); + + Observable observable = Observable.from(1, 2, 3); + + Observable m = Observable.create(scan(observable, "", new Func2() { + + @Override + public String call(String s, Integer n) { + return s + n.toString(); + } + + })); + m.subscribe(observer); + + verify(observer, never()).onError(any(Throwable.class)); + verify(observer, times(1)).onNext(""); + verify(observer, times(1)).onNext("1"); + verify(observer, times(1)).onNext("12"); + verify(observer, times(1)).onNext("123"); + verify(observer, times(4)).onNext(anyString()); + verify(observer, times(1)).onCompleted(); + verify(observer, never()).onError(any(Throwable.class)); + } + + @Test + public void testScanIntegersWithoutInitialValue() { + @SuppressWarnings("unchecked") + Observer Observer = mock(Observer.class); + + Observable observable = Observable.from(1, 2, 3); + + Observable m = Observable.create(scan(observable, new Func2() { + + @Override + public Integer call(Integer t1, Integer t2) { + return t1 + t2; + } + + })); + m.subscribe(Observer); + + verify(Observer, never()).onError(any(Throwable.class)); + verify(Observer, never()).onNext(0); + verify(Observer, times(1)).onNext(1); + verify(Observer, times(1)).onNext(3); + verify(Observer, times(1)).onNext(6); + verify(Observer, times(3)).onNext(anyInt()); + verify(Observer, times(1)).onCompleted(); + verify(Observer, never()).onError(any(Throwable.class)); + } + + @Test + public void testScanIntegersWithoutInitialValueAndOnlyOneValue() { + @SuppressWarnings("unchecked") + Observer Observer = mock(Observer.class); + + Observable observable = Observable.from(1); + + Observable m = Observable.create(scan(observable, new Func2() { + + @Override + public Integer call(Integer t1, Integer t2) { + return t1 + t2; + } + + })); + m.subscribe(Observer); + + verify(Observer, never()).onError(any(Throwable.class)); + verify(Observer, never()).onNext(0); + verify(Observer, times(1)).onNext(1); + verify(Observer, times(1)).onNext(anyInt()); + verify(Observer, times(1)).onCompleted(); + verify(Observer, never()).onError(any(Throwable.class)); + } } diff --git a/rxjava-core/src/test/java/rx/operators/OperationSkipLastTest.java b/rxjava-core/src/test/java/rx/operators/OperationSkipLastTest.java index 8b1dd163fb..ed213f3d5d 100644 --- a/rxjava-core/src/test/java/rx/operators/OperationSkipLastTest.java +++ b/rxjava-core/src/test/java/rx/operators/OperationSkipLastTest.java @@ -1,98 +1,99 @@ package rx.operators; +import static org.mockito.Matchers.*; +import static org.mockito.Mockito.*; +import static rx.operators.OperationSkipLast.*; + import org.junit.Test; import org.mockito.InOrder; + import rx.Observable; import rx.Observer; -import static org.mockito.Matchers.any; -import static org.mockito.Mockito.*; -import static rx.operators.OperationSkipLast.skipLast; - public class OperationSkipLastTest { - @Test - public void testSkipLastEmpty() { - Observable w = Observable.empty(); - Observable observable = Observable.create(skipLast(w, 2)); - - @SuppressWarnings("unchecked") - Observer aObserver = mock(Observer.class); - observable.subscribe(aObserver); - verify(aObserver, never()).onNext(any(String.class)); - verify(aObserver, never()).onError(any(Throwable.class)); - verify(aObserver, times(1)).onCompleted(); - } - - @Test - public void testSkipLast1() { - Observable w = Observable.from("one", "two", "three"); - Observable observable = Observable.create(skipLast(w, 2)); - - @SuppressWarnings("unchecked") - Observer aObserver = mock(Observer.class); - InOrder inOrder = inOrder(aObserver); - observable.subscribe(aObserver); - inOrder.verify(aObserver, never()).onNext("two"); - inOrder.verify(aObserver, never()).onNext("three"); - verify(aObserver, times(1)).onNext("one"); - verify(aObserver, never()).onError(any(Throwable.class)); - verify(aObserver, times(1)).onCompleted(); - } - - @Test - public void testSkipLast2() { - Observable w = Observable.from("one", "two"); - Observable observable = Observable.create(skipLast(w, 2)); - - @SuppressWarnings("unchecked") - Observer aObserver = mock(Observer.class); - observable.subscribe(aObserver); - verify(aObserver, never()).onNext(any(String.class)); - verify(aObserver, never()).onError(any(Throwable.class)); - verify(aObserver, times(1)).onCompleted(); - } - - @Test - public void testSkipLastWithZeroCount() { - Observable w = Observable.from("one", "two"); - Observable observable = Observable.create(skipLast(w, 0)); - - @SuppressWarnings("unchecked") - Observer aObserver = mock(Observer.class); - observable.subscribe(aObserver); - verify(aObserver, times(1)).onNext("one"); - verify(aObserver, times(1)).onNext("two"); - verify(aObserver, never()).onError(any(Throwable.class)); - verify(aObserver, times(1)).onCompleted(); - } - - @Test - public void testSkipLastWithNull() { - Observable w = Observable.from("one", null, "two"); - Observable observable = Observable.create(skipLast(w, 1)); - - @SuppressWarnings("unchecked") - Observer aObserver = mock(Observer.class); - observable.subscribe(aObserver); - verify(aObserver, times(1)).onNext("one"); - verify(aObserver, times(1)).onNext(null); - verify(aObserver, never()).onNext("two"); - verify(aObserver, never()).onError(any(Throwable.class)); - verify(aObserver, times(1)).onCompleted(); - } - - @Test - public void testSkipLastWithNegativeCount() { - Observable w = Observable.from("one"); - Observable observable = Observable.create(skipLast(w, -1)); - - @SuppressWarnings("unchecked") - Observer aObserver = mock(Observer.class); - observable.subscribe(aObserver); - verify(aObserver, never()).onNext(any(String.class)); - verify(aObserver, times(1)).onError( - any(IndexOutOfBoundsException.class)); - verify(aObserver, never()).onCompleted(); - } + @Test + public void testSkipLastEmpty() { + Observable w = Observable.empty(); + Observable observable = Observable.create(skipLast(w, 2)); + + @SuppressWarnings("unchecked") + Observer aObserver = mock(Observer.class); + observable.subscribe(aObserver); + verify(aObserver, never()).onNext(any(String.class)); + verify(aObserver, never()).onError(any(Throwable.class)); + verify(aObserver, times(1)).onCompleted(); + } + + @Test + public void testSkipLast1() { + Observable w = Observable.from("one", "two", "three"); + Observable observable = Observable.create(skipLast(w, 2)); + + @SuppressWarnings("unchecked") + Observer aObserver = mock(Observer.class); + InOrder inOrder = inOrder(aObserver); + observable.subscribe(aObserver); + inOrder.verify(aObserver, never()).onNext("two"); + inOrder.verify(aObserver, never()).onNext("three"); + verify(aObserver, times(1)).onNext("one"); + verify(aObserver, never()).onError(any(Throwable.class)); + verify(aObserver, times(1)).onCompleted(); + } + + @Test + public void testSkipLast2() { + Observable w = Observable.from("one", "two"); + Observable observable = Observable.create(skipLast(w, 2)); + + @SuppressWarnings("unchecked") + Observer aObserver = mock(Observer.class); + observable.subscribe(aObserver); + verify(aObserver, never()).onNext(any(String.class)); + verify(aObserver, never()).onError(any(Throwable.class)); + verify(aObserver, times(1)).onCompleted(); + } + + @Test + public void testSkipLastWithZeroCount() { + Observable w = Observable.from("one", "two"); + Observable observable = Observable.create(skipLast(w, 0)); + + @SuppressWarnings("unchecked") + Observer aObserver = mock(Observer.class); + observable.subscribe(aObserver); + verify(aObserver, times(1)).onNext("one"); + verify(aObserver, times(1)).onNext("two"); + verify(aObserver, never()).onError(any(Throwable.class)); + verify(aObserver, times(1)).onCompleted(); + } + + @Test + public void testSkipLastWithNull() { + Observable w = Observable.from("one", null, "two"); + Observable observable = Observable.create(skipLast(w, 1)); + + @SuppressWarnings("unchecked") + Observer aObserver = mock(Observer.class); + observable.subscribe(aObserver); + verify(aObserver, times(1)).onNext("one"); + verify(aObserver, times(1)).onNext(null); + verify(aObserver, never()).onNext("two"); + verify(aObserver, never()).onError(any(Throwable.class)); + verify(aObserver, times(1)).onCompleted(); + } + + @Test + public void testSkipLastWithNegativeCount() { + Observable w = Observable.from("one"); + Observable observable = Observable.create(skipLast(w, -1)); + + @SuppressWarnings("unchecked") + Observer aObserver = mock(Observer.class); + observable.subscribe(aObserver); + verify(aObserver, never()).onNext(any(String.class)); + verify(aObserver, times(1)).onError( + any(IndexOutOfBoundsException.class)); + verify(aObserver, never()).onCompleted(); + } } diff --git a/rxjava-core/src/test/java/rx/operators/OperationSkipTest.java b/rxjava-core/src/test/java/rx/operators/OperationSkipTest.java index acc351de34..9aa3985315 100644 --- a/rxjava-core/src/test/java/rx/operators/OperationSkipTest.java +++ b/rxjava-core/src/test/java/rx/operators/OperationSkipTest.java @@ -1,42 +1,43 @@ package rx.operators; +import static org.mockito.Matchers.*; +import static org.mockito.Mockito.*; +import static rx.operators.OperationSkip.*; + import org.junit.Test; + import rx.Observable; import rx.Observer; -import static org.mockito.Matchers.any; -import static org.mockito.Mockito.*; -import static rx.operators.OperationSkip.skip; - public class OperationSkipTest { - @Test - public void testSkip1() { - Observable w = Observable.from("one", "two", "three"); - Observable skip = Observable.create(skip(w, 2)); - - @SuppressWarnings("unchecked") - Observer aObserver = mock(Observer.class); - skip.subscribe(aObserver); - verify(aObserver, never()).onNext("one"); - verify(aObserver, never()).onNext("two"); - verify(aObserver, times(1)).onNext("three"); - verify(aObserver, never()).onError(any(Throwable.class)); - verify(aObserver, times(1)).onCompleted(); - } - - @Test - public void testSkip2() { - Observable w = Observable.from("one", "two", "three"); - Observable skip = Observable.create(skip(w, 1)); - - @SuppressWarnings("unchecked") - Observer aObserver = mock(Observer.class); - skip.subscribe(aObserver); - verify(aObserver, never()).onNext("one"); - verify(aObserver, times(1)).onNext("two"); - verify(aObserver, times(1)).onNext("three"); - verify(aObserver, never()).onError(any(Throwable.class)); - verify(aObserver, times(1)).onCompleted(); - } + @Test + public void testSkip1() { + Observable w = Observable.from("one", "two", "three"); + Observable skip = Observable.create(skip(w, 2)); + + @SuppressWarnings("unchecked") + Observer aObserver = mock(Observer.class); + skip.subscribe(aObserver); + verify(aObserver, never()).onNext("one"); + verify(aObserver, never()).onNext("two"); + verify(aObserver, times(1)).onNext("three"); + verify(aObserver, never()).onError(any(Throwable.class)); + verify(aObserver, times(1)).onCompleted(); + } + + @Test + public void testSkip2() { + Observable w = Observable.from("one", "two", "three"); + Observable skip = Observable.create(skip(w, 1)); + + @SuppressWarnings("unchecked") + Observer aObserver = mock(Observer.class); + skip.subscribe(aObserver); + verify(aObserver, never()).onNext("one"); + verify(aObserver, times(1)).onNext("two"); + verify(aObserver, times(1)).onNext("three"); + verify(aObserver, never()).onError(any(Throwable.class)); + verify(aObserver, times(1)).onCompleted(); + } } diff --git a/rxjava-core/src/test/java/rx/operators/OperationSkipWhileTest.java b/rxjava-core/src/test/java/rx/operators/OperationSkipWhileTest.java index 0c97f00c9b..17d7aced6a 100644 --- a/rxjava-core/src/test/java/rx/operators/OperationSkipWhileTest.java +++ b/rxjava-core/src/test/java/rx/operators/OperationSkipWhileTest.java @@ -14,89 +14,90 @@ public class OperationSkipWhileTest { - @SuppressWarnings("unchecked") - Observer w = mock(Observer.class); - - private static final Func1 LESS_THAN_FIVE = new Func1() { - @Override - public Boolean call(Integer v) { - if (v == 42) throw new RuntimeException("that's not the answer to everything!"); - return v < 5; + @SuppressWarnings("unchecked") + Observer w = mock(Observer.class); + + private static final Func1 LESS_THAN_FIVE = new Func1() { + @Override + public Boolean call(Integer v) { + if (v == 42) + throw new RuntimeException("that's not the answer to everything!"); + return v < 5; + } + }; + + private static final Func2 INDEX_LESS_THAN_THREE = new Func2() { + @Override + public Boolean call(Integer value, Integer index) { + return index < 3; + } + }; + + @Test + public void testSkipWithIndex() { + Observable src = Observable.from(1, 2, 3, 4, 5); + Observable.create(skipWhileWithIndex(src, INDEX_LESS_THAN_THREE)).subscribe(w); + + InOrder inOrder = inOrder(w); + inOrder.verify(w, times(1)).onNext(4); + inOrder.verify(w, times(1)).onNext(5); + inOrder.verify(w, times(1)).onCompleted(); + inOrder.verify(w, never()).onError(any(Throwable.class)); } - }; - private static final Func2 INDEX_LESS_THAN_THREE = new Func2() { - @Override - public Boolean call(Integer value, Integer index) { - return index < 3; + @Test + public void testSkipEmpty() { + Observable src = Observable.empty(); + Observable.create(skipWhile(src, LESS_THAN_FIVE)).subscribe(w); + verify(w, never()).onNext(anyInt()); + verify(w, never()).onError(any(Throwable.class)); + verify(w, times(1)).onCompleted(); + } + + @Test + public void testSkipEverything() { + Observable src = Observable.from(1, 2, 3, 4, 3, 2, 1); + Observable.create(skipWhile(src, LESS_THAN_FIVE)).subscribe(w); + verify(w, never()).onNext(anyInt()); + verify(w, never()).onError(any(Throwable.class)); + verify(w, times(1)).onCompleted(); + } + + @Test + public void testSkipNothing() { + Observable src = Observable.from(5, 3, 1); + Observable.create(skipWhile(src, LESS_THAN_FIVE)).subscribe(w); + + InOrder inOrder = inOrder(w); + inOrder.verify(w, times(1)).onNext(5); + inOrder.verify(w, times(1)).onNext(3); + inOrder.verify(w, times(1)).onNext(1); + inOrder.verify(w, times(1)).onCompleted(); + inOrder.verify(w, never()).onError(any(Throwable.class)); + } + + @Test + public void testSkipSome() { + Observable src = Observable.from(1, 2, 3, 4, 5, 3, 1, 5); + Observable.create(skipWhile(src, LESS_THAN_FIVE)).subscribe(w); + + InOrder inOrder = inOrder(w); + inOrder.verify(w, times(1)).onNext(5); + inOrder.verify(w, times(1)).onNext(3); + inOrder.verify(w, times(1)).onNext(1); + inOrder.verify(w, times(1)).onNext(5); + inOrder.verify(w, times(1)).onCompleted(); + inOrder.verify(w, never()).onError(any(Throwable.class)); + } + + @Test + public void testSkipError() { + Observable src = Observable.from(1, 2, 42, 5, 3, 1); + Observable.create(skipWhile(src, LESS_THAN_FIVE)).subscribe(w); + + InOrder inOrder = inOrder(w); + inOrder.verify(w, never()).onNext(anyInt()); + inOrder.verify(w, never()).onCompleted(); + inOrder.verify(w, times(1)).onError(any(RuntimeException.class)); } - }; - - @Test - public void testSkipWithIndex() { - Observable src = Observable.from(1, 2, 3, 4, 5); - Observable.create(skipWhileWithIndex(src, INDEX_LESS_THAN_THREE)).subscribe(w); - - InOrder inOrder = inOrder(w); - inOrder.verify(w, times(1)).onNext(4); - inOrder.verify(w, times(1)).onNext(5); - inOrder.verify(w, times(1)).onCompleted(); - inOrder.verify(w, never()).onError(any(Throwable.class)); - } - - @Test - public void testSkipEmpty() { - Observable src = Observable.empty(); - Observable.create(skipWhile(src, LESS_THAN_FIVE)).subscribe(w); - verify(w, never()).onNext(anyInt()); - verify(w, never()).onError(any(Throwable.class)); - verify(w, times(1)).onCompleted(); - } - - @Test - public void testSkipEverything() { - Observable src = Observable.from(1, 2, 3, 4, 3, 2, 1); - Observable.create(skipWhile(src, LESS_THAN_FIVE)).subscribe(w); - verify(w, never()).onNext(anyInt()); - verify(w, never()).onError(any(Throwable.class)); - verify(w, times(1)).onCompleted(); - } - - @Test - public void testSkipNothing() { - Observable src = Observable.from(5, 3, 1); - Observable.create(skipWhile(src, LESS_THAN_FIVE)).subscribe(w); - - InOrder inOrder = inOrder(w); - inOrder.verify(w, times(1)).onNext(5); - inOrder.verify(w, times(1)).onNext(3); - inOrder.verify(w, times(1)).onNext(1); - inOrder.verify(w, times(1)).onCompleted(); - inOrder.verify(w, never()).onError(any(Throwable.class)); - } - - @Test - public void testSkipSome() { - Observable src = Observable.from(1, 2, 3, 4, 5, 3, 1, 5); - Observable.create(skipWhile(src, LESS_THAN_FIVE)).subscribe(w); - - InOrder inOrder = inOrder(w); - inOrder.verify(w, times(1)).onNext(5); - inOrder.verify(w, times(1)).onNext(3); - inOrder.verify(w, times(1)).onNext(1); - inOrder.verify(w, times(1)).onNext(5); - inOrder.verify(w, times(1)).onCompleted(); - inOrder.verify(w, never()).onError(any(Throwable.class)); - } - - @Test - public void testSkipError() { - Observable src = Observable.from(1, 2, 42, 5, 3, 1); - Observable.create(skipWhile(src, LESS_THAN_FIVE)).subscribe(w); - - InOrder inOrder = inOrder(w); - inOrder.verify(w, never()).onNext(anyInt()); - inOrder.verify(w, never()).onCompleted(); - inOrder.verify(w, times(1)).onError(any(RuntimeException.class)); - } } diff --git a/rxjava-core/src/test/java/rx/operators/OperationSubscribeOnTest.java b/rxjava-core/src/test/java/rx/operators/OperationSubscribeOnTest.java index 0c260cf8e8..d95bfdfc8a 100644 --- a/rxjava-core/src/test/java/rx/operators/OperationSubscribeOnTest.java +++ b/rxjava-core/src/test/java/rx/operators/OperationSubscribeOnTest.java @@ -1,6 +1,11 @@ package rx.operators; +import static org.mockito.Matchers.*; +import static org.mockito.Mockito.*; +import static rx.operators.OperationSubscribeOn.*; + import org.junit.Test; + import rx.Observable; import rx.Observer; import rx.Scheduler; @@ -10,31 +15,26 @@ import rx.util.functions.Action0; import rx.util.functions.Func2; -import static org.mockito.Matchers.any; -import static org.mockito.Matchers.isNull; -import static org.mockito.Mockito.*; -import static rx.operators.OperationSubscribeOn.subscribeOn; - public class OperationSubscribeOnTest { - @Test - @SuppressWarnings("unchecked") - public void testSubscribeOn() { - Observable w = Observable.from(1, 2, 3); + @Test + @SuppressWarnings("unchecked") + public void testSubscribeOn() { + Observable w = Observable.from(1, 2, 3); - Scheduler scheduler = spy(OperatorTester.forwardingScheduler(Schedulers.immediate())); + Scheduler scheduler = spy(OperatorTester.forwardingScheduler(Schedulers.immediate())); - Observer observer = mock(Observer.class); - Subscription subscription = Observable.create(subscribeOn(w, scheduler)).subscribe(observer); + Observer observer = mock(Observer.class); + Subscription subscription = Observable.create(subscribeOn(w, scheduler)).subscribe(observer); - verify(scheduler, times(1)).schedule(isNull(), any(Func2.class)); - subscription.unsubscribe(); - verify(scheduler, times(1)).schedule(any(Action0.class)); - verifyNoMoreInteractions(scheduler); + verify(scheduler, times(1)).schedule(isNull(), any(Func2.class)); + subscription.unsubscribe(); + verify(scheduler, times(1)).schedule(any(Action0.class)); + verifyNoMoreInteractions(scheduler); - verify(observer, times(1)).onNext(1); - verify(observer, times(1)).onNext(2); - verify(observer, times(1)).onNext(3); - verify(observer, times(1)).onCompleted(); - } + verify(observer, times(1)).onNext(1); + verify(observer, times(1)).onNext(2); + verify(observer, times(1)).onNext(3); + verify(observer, times(1)).onCompleted(); + } } diff --git a/rxjava-core/src/test/java/rx/operators/OperationSumTest.java b/rxjava-core/src/test/java/rx/operators/OperationSumTest.java index 9e826d8343..98a75fd836 100644 --- a/rxjava-core/src/test/java/rx/operators/OperationSumTest.java +++ b/rxjava-core/src/test/java/rx/operators/OperationSumTest.java @@ -1,113 +1,110 @@ package rx.operators; +import static org.mockito.Matchers.*; +import static org.mockito.Mockito.*; +import static rx.operators.OperationSum.*; + import org.junit.Test; + import rx.Observable; import rx.Observer; -import static org.mockito.Matchers.any; -import static org.mockito.Matchers.anyDouble; -import static org.mockito.Matchers.anyFloat; -import static org.mockito.Matchers.anyInt; -import static org.mockito.Matchers.anyLong; -import static org.mockito.Mockito.*; -import static rx.operators.OperationSum.*; - public class OperationSumTest { - @SuppressWarnings("unchecked") - Observer w = mock(Observer.class); - @SuppressWarnings("unchecked") - Observer wl = mock(Observer.class); - @SuppressWarnings("unchecked") - Observer wf = mock(Observer.class); - @SuppressWarnings("unchecked") - Observer wd = mock(Observer.class); - - @Test - public void testSumOfAFewInts() throws Throwable { - Observable src = Observable.from(1, 2, 3, 4, 5); - sum(src).subscribe(w); - - verify(w, times(1)).onNext(anyInt()); - verify(w).onNext(15); - verify(w, never()).onError(any(Throwable.class)); - verify(w, times(1)).onCompleted(); - } - - @Test - public void testEmptySum() throws Throwable { - Observable src = Observable.empty(); - sum(src).subscribe(w); - - verify(w, times(1)).onNext(anyInt()); - verify(w).onNext(0); - verify(w, never()).onError(any(Throwable.class)); - verify(w, times(1)).onCompleted(); - } - - @Test - public void testSumOfAFewLongs() throws Throwable { - Observable src = Observable.from(1L, 2L, 3L, 4L, 5L); - sumLongs(src).subscribe(wl); - - verify(wl, times(1)).onNext(anyLong()); - verify(wl).onNext(15L); - verify(wl, never()).onError(any(Throwable.class)); - verify(wl, times(1)).onCompleted(); - } - - @Test - public void testEmptySumLongs() throws Throwable { - Observable src = Observable.empty(); - sumLongs(src).subscribe(wl); - - verify(wl, times(1)).onNext(anyLong()); - verify(wl).onNext(0L); - verify(wl, never()).onError(any(Throwable.class)); - verify(wl, times(1)).onCompleted(); - } - - @Test - public void testSumOfAFewFloats() throws Throwable { - Observable src = Observable.from(1.0f); - sumFloats(src).subscribe(wf); - - verify(wf, times(1)).onNext(anyFloat()); - verify(wf).onNext(1.0f); - verify(wf, never()).onError(any(Throwable.class)); - verify(wf, times(1)).onCompleted(); - } - - @Test - public void testEmptySumFloats() throws Throwable { - Observable src = Observable.empty(); - sumFloats(src).subscribe(wf); - - verify(wf, times(1)).onNext(anyFloat()); - verify(wf).onNext(0.0f); - verify(wf, never()).onError(any(Throwable.class)); - verify(wf, times(1)).onCompleted(); - } - - @Test - public void testSumOfAFewDoubles() throws Throwable { - Observable src = Observable.from(0.0d, 1.0d, 0.5d); - sumDoubles(src).subscribe(wd); - - verify(wd, times(1)).onNext(anyDouble()); - verify(wd).onNext(1.5d); - verify(wd, never()).onError(any(Throwable.class)); - verify(wd, times(1)).onCompleted(); - } - - @Test - public void testEmptySumDoubles() throws Throwable { - Observable src = Observable.empty(); - sumDoubles(src).subscribe(wd); - - verify(wd, times(1)).onNext(anyDouble()); - verify(wd).onNext(0.0d); - verify(wd, never()).onError(any(Throwable.class)); - verify(wd, times(1)).onCompleted(); - } + @SuppressWarnings("unchecked") + Observer w = mock(Observer.class); + @SuppressWarnings("unchecked") + Observer wl = mock(Observer.class); + @SuppressWarnings("unchecked") + Observer wf = mock(Observer.class); + @SuppressWarnings("unchecked") + Observer wd = mock(Observer.class); + + @Test + public void testSumOfAFewInts() throws Throwable { + Observable src = Observable.from(1, 2, 3, 4, 5); + sum(src).subscribe(w); + + verify(w, times(1)).onNext(anyInt()); + verify(w).onNext(15); + verify(w, never()).onError(any(Throwable.class)); + verify(w, times(1)).onCompleted(); + } + + @Test + public void testEmptySum() throws Throwable { + Observable src = Observable.empty(); + sum(src).subscribe(w); + + verify(w, times(1)).onNext(anyInt()); + verify(w).onNext(0); + verify(w, never()).onError(any(Throwable.class)); + verify(w, times(1)).onCompleted(); + } + + @Test + public void testSumOfAFewLongs() throws Throwable { + Observable src = Observable.from(1L, 2L, 3L, 4L, 5L); + sumLongs(src).subscribe(wl); + + verify(wl, times(1)).onNext(anyLong()); + verify(wl).onNext(15L); + verify(wl, never()).onError(any(Throwable.class)); + verify(wl, times(1)).onCompleted(); + } + + @Test + public void testEmptySumLongs() throws Throwable { + Observable src = Observable.empty(); + sumLongs(src).subscribe(wl); + + verify(wl, times(1)).onNext(anyLong()); + verify(wl).onNext(0L); + verify(wl, never()).onError(any(Throwable.class)); + verify(wl, times(1)).onCompleted(); + } + + @Test + public void testSumOfAFewFloats() throws Throwable { + Observable src = Observable.from(1.0f); + sumFloats(src).subscribe(wf); + + verify(wf, times(1)).onNext(anyFloat()); + verify(wf).onNext(1.0f); + verify(wf, never()).onError(any(Throwable.class)); + verify(wf, times(1)).onCompleted(); + } + + @Test + public void testEmptySumFloats() throws Throwable { + Observable src = Observable.empty(); + sumFloats(src).subscribe(wf); + + verify(wf, times(1)).onNext(anyFloat()); + verify(wf).onNext(0.0f); + verify(wf, never()).onError(any(Throwable.class)); + verify(wf, times(1)).onCompleted(); + } + + @Test + public void testSumOfAFewDoubles() throws Throwable { + Observable src = Observable.from(0.0d, 1.0d, 0.5d); + sumDoubles(src).subscribe(wd); + + verify(wd, times(1)).onNext(anyDouble()); + verify(wd).onNext(1.5d); + verify(wd, never()).onError(any(Throwable.class)); + verify(wd, times(1)).onCompleted(); + } + + @Test + public void testEmptySumDoubles() throws Throwable { + Observable src = Observable.empty(); + sumDoubles(src).subscribe(wd); + + verify(wd, times(1)).onNext(anyDouble()); + verify(wd).onNext(0.0d); + verify(wd, never()).onError(any(Throwable.class)); + verify(wd, times(1)).onCompleted(); + } } diff --git a/rxjava-core/src/test/java/rx/operators/OperationSwitchTest.java b/rxjava-core/src/test/java/rx/operators/OperationSwitchTest.java index 7c8c9ea21a..090e9e5d68 100644 --- a/rxjava-core/src/test/java/rx/operators/OperationSwitchTest.java +++ b/rxjava-core/src/test/java/rx/operators/OperationSwitchTest.java @@ -1,8 +1,14 @@ package rx.operators; +import static org.mockito.Matchers.*; +import static org.mockito.Mockito.*; + +import java.util.concurrent.TimeUnit; + import org.junit.Before; import org.junit.Test; import org.mockito.InOrder; + import rx.Observable; import rx.Observer; import rx.Subscription; @@ -10,359 +16,353 @@ import rx.subscriptions.Subscriptions; import rx.util.functions.Action0; -import java.util.concurrent.TimeUnit; - -import static org.mockito.Matchers.any; -import static org.mockito.Matchers.anyString; -import static org.mockito.Mockito.*; - public class OperationSwitchTest { - private TestScheduler scheduler; - private Observer observer; - - @Before - @SuppressWarnings("unchecked") - public void before() { - scheduler = new TestScheduler(); - observer = mock(Observer.class); - } - - @Test - public void testSwitchWhenOuterCompleteBeforeInner() { - Observable> source = Observable.create(new Observable.OnSubscribeFunc>() { - @Override - public Subscription onSubscribe(Observer> observer) { - publishNext(observer, 50, Observable.create(new Observable.OnSubscribeFunc() { - @Override - public Subscription onSubscribe(Observer observer) { - publishNext(observer, 70, "one"); - publishNext(observer, 100, "two"); - publishCompleted(observer, 200); - return Subscriptions.empty(); - } - })); - publishCompleted(observer, 60); - - return Subscriptions.empty(); - } - }); - - Observable sampled = Observable.create(OperationSwitch.switchDo(source)); - sampled.subscribe(observer); - - InOrder inOrder = inOrder(observer); - - scheduler.advanceTimeTo(350, TimeUnit.MILLISECONDS); - inOrder.verify(observer, times(2)).onNext(anyString()); - inOrder.verify(observer, times(1)).onCompleted(); - } - - @Test - public void testSwitchWhenInnerCompleteBeforeOuter() { - Observable> source = Observable.create(new Observable.OnSubscribeFunc>() { - @Override - public Subscription onSubscribe(Observer> observer) { - publishNext(observer, 10, Observable.create(new Observable.OnSubscribeFunc() { - @Override - public Subscription onSubscribe(Observer observer) { - publishNext(observer, 0, "one"); - publishNext(observer, 10, "two"); - publishCompleted(observer, 20); - return Subscriptions.empty(); - } - })); - - publishNext(observer, 100, Observable.create(new Observable.OnSubscribeFunc() { - @Override - public Subscription onSubscribe(Observer observer) { - publishNext(observer, 0, "three"); - publishNext(observer, 10, "four"); - publishCompleted(observer, 20); - return Subscriptions.empty(); - } - })); - publishCompleted(observer, 200); - - return Subscriptions.empty(); - } - }); - - Observable sampled = Observable.create(OperationSwitch.switchDo(source)); - sampled.subscribe(observer); - - InOrder inOrder = inOrder(observer); - - scheduler.advanceTimeTo(150, TimeUnit.MILLISECONDS); - inOrder.verify(observer, never()).onCompleted(); - inOrder.verify(observer, times(1)).onNext("one"); - inOrder.verify(observer, times(1)).onNext("two"); - inOrder.verify(observer, times(1)).onNext("three"); - inOrder.verify(observer, times(1)).onNext("four"); - - scheduler.advanceTimeTo(250, TimeUnit.MILLISECONDS); - inOrder.verify(observer, never()).onNext(anyString()); - inOrder.verify(observer, times(1)).onCompleted(); - } - - @Test - public void testSwitchWithComplete() { - Observable> source = Observable.create(new Observable.OnSubscribeFunc>() { - @Override - public Subscription onSubscribe(Observer> observer) { - publishNext(observer, 50, Observable.create(new Observable.OnSubscribeFunc() { - @Override - public Subscription onSubscribe(Observer observer) { - publishNext(observer, 60, "one"); - publishNext(observer, 100, "two"); - return Subscriptions.empty(); - } - })); - - publishNext(observer, 200, Observable.create(new Observable.OnSubscribeFunc() { - @Override - public Subscription onSubscribe(Observer observer) { - publishNext(observer, 0, "three"); - publishNext(observer, 100, "four"); - return Subscriptions.empty(); - } - })); - - publishCompleted(observer, 250); - - return Subscriptions.empty(); - } - }); - - Observable sampled = Observable.create(OperationSwitch.switchDo(source)); - sampled.subscribe(observer); - - InOrder inOrder = inOrder(observer); - - scheduler.advanceTimeTo(90, TimeUnit.MILLISECONDS); - inOrder.verify(observer, never()).onNext(anyString()); - verify(observer, never()).onCompleted(); - verify(observer, never()).onError(any(Throwable.class)); - - scheduler.advanceTimeTo(125, TimeUnit.MILLISECONDS); - inOrder.verify(observer, times(1)).onNext("one"); - verify(observer, never()).onCompleted(); - verify(observer, never()).onError(any(Throwable.class)); - - scheduler.advanceTimeTo(175, TimeUnit.MILLISECONDS); - inOrder.verify(observer, times(1)).onNext("two"); - verify(observer, never()).onCompleted(); - verify(observer, never()).onError(any(Throwable.class)); - - scheduler.advanceTimeTo(225, TimeUnit.MILLISECONDS); - inOrder.verify(observer, times(1)).onNext("three"); - verify(observer, never()).onCompleted(); - verify(observer, never()).onError(any(Throwable.class)); - - scheduler.advanceTimeTo(350, TimeUnit.MILLISECONDS); - inOrder.verify(observer, times(1)).onNext("four"); - verify(observer, never()).onCompleted(); - verify(observer, never()).onError(any(Throwable.class)); - } - - @Test - public void testSwitchWithError() { - Observable> source = Observable.create(new Observable.OnSubscribeFunc>() { - @Override - public Subscription onSubscribe(Observer> observer) { - publishNext(observer, 50, Observable.create(new Observable.OnSubscribeFunc() { - @Override - public Subscription onSubscribe(Observer observer) { - publishNext(observer, 50, "one"); - publishNext(observer, 100, "two"); - return Subscriptions.empty(); - } - })); - - publishNext(observer, 200, Observable.create(new Observable.OnSubscribeFunc() { - @Override - public Subscription onSubscribe(Observer observer) { - publishNext(observer, 0, "three"); - publishNext(observer, 100, "four"); - return Subscriptions.empty(); - } - })); - - publishError(observer, 250, new TestException()); - - return Subscriptions.empty(); - } - }); - - Observable sampled = Observable.create(OperationSwitch.switchDo(source)); - sampled.subscribe(observer); - - InOrder inOrder = inOrder(observer); - - scheduler.advanceTimeTo(90, TimeUnit.MILLISECONDS); - inOrder.verify(observer, never()).onNext(anyString()); - verify(observer, never()).onCompleted(); - verify(observer, never()).onError(any(Throwable.class)); - - scheduler.advanceTimeTo(125, TimeUnit.MILLISECONDS); - inOrder.verify(observer, times(1)).onNext("one"); - verify(observer, never()).onCompleted(); - verify(observer, never()).onError(any(Throwable.class)); - - scheduler.advanceTimeTo(175, TimeUnit.MILLISECONDS); - inOrder.verify(observer, times(1)).onNext("two"); - verify(observer, never()).onCompleted(); - verify(observer, never()).onError(any(Throwable.class)); - - scheduler.advanceTimeTo(225, TimeUnit.MILLISECONDS); - inOrder.verify(observer, times(1)).onNext("three"); - verify(observer, never()).onCompleted(); - verify(observer, never()).onError(any(Throwable.class)); - - scheduler.advanceTimeTo(350, TimeUnit.MILLISECONDS); - inOrder.verify(observer, never()).onNext(anyString()); - verify(observer, never()).onCompleted(); - verify(observer, times(1)).onError(any(TestException.class)); - } - - @Test - public void testSwitchWithSubsequenceComplete() { - Observable> source = Observable.create(new Observable.OnSubscribeFunc>() { - @Override - public Subscription onSubscribe(Observer> observer) { - publishNext(observer, 50, Observable.create(new Observable.OnSubscribeFunc() { - @Override - public Subscription onSubscribe(Observer observer) { - publishNext(observer, 50, "one"); - publishNext(observer, 100, "two"); - return Subscriptions.empty(); - } - })); - - publishNext(observer, 130, Observable.create(new Observable.OnSubscribeFunc() { - @Override - public Subscription onSubscribe(Observer observer) { - publishCompleted(observer, 0); - return Subscriptions.empty(); - } - })); - - publishNext(observer, 150, Observable.create(new Observable.OnSubscribeFunc() { - @Override - public Subscription onSubscribe(Observer observer) { - publishNext(observer, 50, "three"); - return Subscriptions.empty(); - } - })); - - return Subscriptions.empty(); - } - }); - - Observable sampled = Observable.create(OperationSwitch.switchDo(source)); - sampled.subscribe(observer); - - InOrder inOrder = inOrder(observer); - - scheduler.advanceTimeTo(90, TimeUnit.MILLISECONDS); - inOrder.verify(observer, never()).onNext(anyString()); - verify(observer, never()).onCompleted(); - verify(observer, never()).onError(any(Throwable.class)); - - scheduler.advanceTimeTo(125, TimeUnit.MILLISECONDS); - inOrder.verify(observer, times(1)).onNext("one"); - verify(observer, never()).onCompleted(); - verify(observer, never()).onError(any(Throwable.class)); - - scheduler.advanceTimeTo(250, TimeUnit.MILLISECONDS); - inOrder.verify(observer, times(1)).onNext("three"); - verify(observer, never()).onCompleted(); - verify(observer, never()).onError(any(Throwable.class)); - } - - @Test - public void testSwitchWithSubsequenceError() { - Observable> source = Observable.create(new Observable.OnSubscribeFunc>() { - @Override - public Subscription onSubscribe(Observer> observer) { - publishNext(observer, 50, Observable.create(new Observable.OnSubscribeFunc() { - @Override - public Subscription onSubscribe(Observer observer) { - publishNext(observer, 50, "one"); - publishNext(observer, 100, "two"); - return Subscriptions.empty(); - } - })); - - publishNext(observer, 130, Observable.create(new Observable.OnSubscribeFunc() { - @Override - public Subscription onSubscribe(Observer observer) { - publishError(observer, 0, new TestException()); - return Subscriptions.empty(); - } - })); - - publishNext(observer, 150, Observable.create(new Observable.OnSubscribeFunc() { - @Override - public Subscription onSubscribe(Observer observer) { - publishNext(observer, 50, "three"); - return Subscriptions.empty(); - } - })); - - return Subscriptions.empty(); - } - }); - - Observable sampled = Observable.create(OperationSwitch.switchDo(source)); - sampled.subscribe(observer); - - InOrder inOrder = inOrder(observer); - - scheduler.advanceTimeTo(90, TimeUnit.MILLISECONDS); - inOrder.verify(observer, never()).onNext(anyString()); - verify(observer, never()).onCompleted(); - verify(observer, never()).onError(any(Throwable.class)); - - scheduler.advanceTimeTo(125, TimeUnit.MILLISECONDS); - inOrder.verify(observer, times(1)).onNext("one"); - verify(observer, never()).onCompleted(); - verify(observer, never()).onError(any(Throwable.class)); - - scheduler.advanceTimeTo(250, TimeUnit.MILLISECONDS); - inOrder.verify(observer, never()).onNext("three"); - verify(observer, never()).onCompleted(); - verify(observer, times(1)).onError(any(TestException.class)); - } - - private void publishCompleted(final Observer observer, long delay) { - scheduler.schedule(new Action0() { - @Override - public void call() { - observer.onCompleted(); - } - }, delay, TimeUnit.MILLISECONDS); - } - - private void publishError(final Observer observer, long delay, final Throwable error) { - scheduler.schedule(new Action0() { - @Override - public void call() { - observer.onError(error); - } - }, delay, TimeUnit.MILLISECONDS); - } - - private void publishNext(final Observer observer, long delay, final T value) { - scheduler.schedule(new Action0() { - @Override - public void call() { - observer.onNext(value); - } - }, delay, TimeUnit.MILLISECONDS); - } - - @SuppressWarnings("serial") - private class TestException extends Throwable { - } + private TestScheduler scheduler; + private Observer observer; + + @Before + @SuppressWarnings("unchecked") + public void before() { + scheduler = new TestScheduler(); + observer = mock(Observer.class); + } + + @Test + public void testSwitchWhenOuterCompleteBeforeInner() { + Observable> source = Observable.create(new Observable.OnSubscribeFunc>() { + @Override + public Subscription onSubscribe(Observer> observer) { + publishNext(observer, 50, Observable.create(new Observable.OnSubscribeFunc() { + @Override + public Subscription onSubscribe(Observer observer) { + publishNext(observer, 70, "one"); + publishNext(observer, 100, "two"); + publishCompleted(observer, 200); + return Subscriptions.empty(); + } + })); + publishCompleted(observer, 60); + + return Subscriptions.empty(); + } + }); + + Observable sampled = Observable.create(OperationSwitch.switchDo(source)); + sampled.subscribe(observer); + + InOrder inOrder = inOrder(observer); + + scheduler.advanceTimeTo(350, TimeUnit.MILLISECONDS); + inOrder.verify(observer, times(2)).onNext(anyString()); + inOrder.verify(observer, times(1)).onCompleted(); + } + + @Test + public void testSwitchWhenInnerCompleteBeforeOuter() { + Observable> source = Observable.create(new Observable.OnSubscribeFunc>() { + @Override + public Subscription onSubscribe(Observer> observer) { + publishNext(observer, 10, Observable.create(new Observable.OnSubscribeFunc() { + @Override + public Subscription onSubscribe(Observer observer) { + publishNext(observer, 0, "one"); + publishNext(observer, 10, "two"); + publishCompleted(observer, 20); + return Subscriptions.empty(); + } + })); + + publishNext(observer, 100, Observable.create(new Observable.OnSubscribeFunc() { + @Override + public Subscription onSubscribe(Observer observer) { + publishNext(observer, 0, "three"); + publishNext(observer, 10, "four"); + publishCompleted(observer, 20); + return Subscriptions.empty(); + } + })); + publishCompleted(observer, 200); + + return Subscriptions.empty(); + } + }); + + Observable sampled = Observable.create(OperationSwitch.switchDo(source)); + sampled.subscribe(observer); + + InOrder inOrder = inOrder(observer); + + scheduler.advanceTimeTo(150, TimeUnit.MILLISECONDS); + inOrder.verify(observer, never()).onCompleted(); + inOrder.verify(observer, times(1)).onNext("one"); + inOrder.verify(observer, times(1)).onNext("two"); + inOrder.verify(observer, times(1)).onNext("three"); + inOrder.verify(observer, times(1)).onNext("four"); + + scheduler.advanceTimeTo(250, TimeUnit.MILLISECONDS); + inOrder.verify(observer, never()).onNext(anyString()); + inOrder.verify(observer, times(1)).onCompleted(); + } + + @Test + public void testSwitchWithComplete() { + Observable> source = Observable.create(new Observable.OnSubscribeFunc>() { + @Override + public Subscription onSubscribe(Observer> observer) { + publishNext(observer, 50, Observable.create(new Observable.OnSubscribeFunc() { + @Override + public Subscription onSubscribe(Observer observer) { + publishNext(observer, 60, "one"); + publishNext(observer, 100, "two"); + return Subscriptions.empty(); + } + })); + + publishNext(observer, 200, Observable.create(new Observable.OnSubscribeFunc() { + @Override + public Subscription onSubscribe(Observer observer) { + publishNext(observer, 0, "three"); + publishNext(observer, 100, "four"); + return Subscriptions.empty(); + } + })); + + publishCompleted(observer, 250); + + return Subscriptions.empty(); + } + }); + + Observable sampled = Observable.create(OperationSwitch.switchDo(source)); + sampled.subscribe(observer); + + InOrder inOrder = inOrder(observer); + + scheduler.advanceTimeTo(90, TimeUnit.MILLISECONDS); + inOrder.verify(observer, never()).onNext(anyString()); + verify(observer, never()).onCompleted(); + verify(observer, never()).onError(any(Throwable.class)); + + scheduler.advanceTimeTo(125, TimeUnit.MILLISECONDS); + inOrder.verify(observer, times(1)).onNext("one"); + verify(observer, never()).onCompleted(); + verify(observer, never()).onError(any(Throwable.class)); + + scheduler.advanceTimeTo(175, TimeUnit.MILLISECONDS); + inOrder.verify(observer, times(1)).onNext("two"); + verify(observer, never()).onCompleted(); + verify(observer, never()).onError(any(Throwable.class)); + + scheduler.advanceTimeTo(225, TimeUnit.MILLISECONDS); + inOrder.verify(observer, times(1)).onNext("three"); + verify(observer, never()).onCompleted(); + verify(observer, never()).onError(any(Throwable.class)); + + scheduler.advanceTimeTo(350, TimeUnit.MILLISECONDS); + inOrder.verify(observer, times(1)).onNext("four"); + verify(observer, never()).onCompleted(); + verify(observer, never()).onError(any(Throwable.class)); + } + + @Test + public void testSwitchWithError() { + Observable> source = Observable.create(new Observable.OnSubscribeFunc>() { + @Override + public Subscription onSubscribe(Observer> observer) { + publishNext(observer, 50, Observable.create(new Observable.OnSubscribeFunc() { + @Override + public Subscription onSubscribe(Observer observer) { + publishNext(observer, 50, "one"); + publishNext(observer, 100, "two"); + return Subscriptions.empty(); + } + })); + + publishNext(observer, 200, Observable.create(new Observable.OnSubscribeFunc() { + @Override + public Subscription onSubscribe(Observer observer) { + publishNext(observer, 0, "three"); + publishNext(observer, 100, "four"); + return Subscriptions.empty(); + } + })); + + publishError(observer, 250, new TestException()); + + return Subscriptions.empty(); + } + }); + + Observable sampled = Observable.create(OperationSwitch.switchDo(source)); + sampled.subscribe(observer); + + InOrder inOrder = inOrder(observer); + + scheduler.advanceTimeTo(90, TimeUnit.MILLISECONDS); + inOrder.verify(observer, never()).onNext(anyString()); + verify(observer, never()).onCompleted(); + verify(observer, never()).onError(any(Throwable.class)); + + scheduler.advanceTimeTo(125, TimeUnit.MILLISECONDS); + inOrder.verify(observer, times(1)).onNext("one"); + verify(observer, never()).onCompleted(); + verify(observer, never()).onError(any(Throwable.class)); + + scheduler.advanceTimeTo(175, TimeUnit.MILLISECONDS); + inOrder.verify(observer, times(1)).onNext("two"); + verify(observer, never()).onCompleted(); + verify(observer, never()).onError(any(Throwable.class)); + + scheduler.advanceTimeTo(225, TimeUnit.MILLISECONDS); + inOrder.verify(observer, times(1)).onNext("three"); + verify(observer, never()).onCompleted(); + verify(observer, never()).onError(any(Throwable.class)); + + scheduler.advanceTimeTo(350, TimeUnit.MILLISECONDS); + inOrder.verify(observer, never()).onNext(anyString()); + verify(observer, never()).onCompleted(); + verify(observer, times(1)).onError(any(TestException.class)); + } + + @Test + public void testSwitchWithSubsequenceComplete() { + Observable> source = Observable.create(new Observable.OnSubscribeFunc>() { + @Override + public Subscription onSubscribe(Observer> observer) { + publishNext(observer, 50, Observable.create(new Observable.OnSubscribeFunc() { + @Override + public Subscription onSubscribe(Observer observer) { + publishNext(observer, 50, "one"); + publishNext(observer, 100, "two"); + return Subscriptions.empty(); + } + })); + + publishNext(observer, 130, Observable.create(new Observable.OnSubscribeFunc() { + @Override + public Subscription onSubscribe(Observer observer) { + publishCompleted(observer, 0); + return Subscriptions.empty(); + } + })); + + publishNext(observer, 150, Observable.create(new Observable.OnSubscribeFunc() { + @Override + public Subscription onSubscribe(Observer observer) { + publishNext(observer, 50, "three"); + return Subscriptions.empty(); + } + })); + + return Subscriptions.empty(); + } + }); + + Observable sampled = Observable.create(OperationSwitch.switchDo(source)); + sampled.subscribe(observer); + + InOrder inOrder = inOrder(observer); + + scheduler.advanceTimeTo(90, TimeUnit.MILLISECONDS); + inOrder.verify(observer, never()).onNext(anyString()); + verify(observer, never()).onCompleted(); + verify(observer, never()).onError(any(Throwable.class)); + + scheduler.advanceTimeTo(125, TimeUnit.MILLISECONDS); + inOrder.verify(observer, times(1)).onNext("one"); + verify(observer, never()).onCompleted(); + verify(observer, never()).onError(any(Throwable.class)); + + scheduler.advanceTimeTo(250, TimeUnit.MILLISECONDS); + inOrder.verify(observer, times(1)).onNext("three"); + verify(observer, never()).onCompleted(); + verify(observer, never()).onError(any(Throwable.class)); + } + + @Test + public void testSwitchWithSubsequenceError() { + Observable> source = Observable.create(new Observable.OnSubscribeFunc>() { + @Override + public Subscription onSubscribe(Observer> observer) { + publishNext(observer, 50, Observable.create(new Observable.OnSubscribeFunc() { + @Override + public Subscription onSubscribe(Observer observer) { + publishNext(observer, 50, "one"); + publishNext(observer, 100, "two"); + return Subscriptions.empty(); + } + })); + + publishNext(observer, 130, Observable.create(new Observable.OnSubscribeFunc() { + @Override + public Subscription onSubscribe(Observer observer) { + publishError(observer, 0, new TestException()); + return Subscriptions.empty(); + } + })); + + publishNext(observer, 150, Observable.create(new Observable.OnSubscribeFunc() { + @Override + public Subscription onSubscribe(Observer observer) { + publishNext(observer, 50, "three"); + return Subscriptions.empty(); + } + })); + + return Subscriptions.empty(); + } + }); + + Observable sampled = Observable.create(OperationSwitch.switchDo(source)); + sampled.subscribe(observer); + + InOrder inOrder = inOrder(observer); + + scheduler.advanceTimeTo(90, TimeUnit.MILLISECONDS); + inOrder.verify(observer, never()).onNext(anyString()); + verify(observer, never()).onCompleted(); + verify(observer, never()).onError(any(Throwable.class)); + + scheduler.advanceTimeTo(125, TimeUnit.MILLISECONDS); + inOrder.verify(observer, times(1)).onNext("one"); + verify(observer, never()).onCompleted(); + verify(observer, never()).onError(any(Throwable.class)); + + scheduler.advanceTimeTo(250, TimeUnit.MILLISECONDS); + inOrder.verify(observer, never()).onNext("three"); + verify(observer, never()).onCompleted(); + verify(observer, times(1)).onError(any(TestException.class)); + } + + private void publishCompleted(final Observer observer, long delay) { + scheduler.schedule(new Action0() { + @Override + public void call() { + observer.onCompleted(); + } + }, delay, TimeUnit.MILLISECONDS); + } + + private void publishError(final Observer observer, long delay, final Throwable error) { + scheduler.schedule(new Action0() { + @Override + public void call() { + observer.onError(error); + } + }, delay, TimeUnit.MILLISECONDS); + } + + private void publishNext(final Observer observer, long delay, final T value) { + scheduler.schedule(new Action0() { + @Override + public void call() { + observer.onNext(value); + } + }, delay, TimeUnit.MILLISECONDS); + } + + @SuppressWarnings("serial") + private class TestException extends Throwable { + } } diff --git a/rxjava-core/src/test/java/rx/operators/OperationSynchronizeTest.java b/rxjava-core/src/test/java/rx/operators/OperationSynchronizeTest.java index 28d7676c66..2815ea03f4 100644 --- a/rxjava-core/src/test/java/rx/operators/OperationSynchronizeTest.java +++ b/rxjava-core/src/test/java/rx/operators/OperationSynchronizeTest.java @@ -1,203 +1,204 @@ package rx.operators; +import static org.mockito.Matchers.*; +import static org.mockito.Mockito.*; +import static rx.operators.OperationSynchronize.*; + import org.junit.Test; import org.mockito.Mockito; + import rx.Observable; import rx.Observer; import rx.Subscription; -import static org.mockito.Matchers.any; -import static org.mockito.Mockito.*; -import static rx.operators.OperationSynchronize.synchronize; - public class OperationSynchronizeTest { - /** - * Ensure onCompleted can not be called after an Unsubscribe - */ - @Test - public void testOnCompletedAfterUnSubscribe() { - TestObservable t = new TestObservable(null); - Observable st = Observable.create(synchronize(Observable.create(t))); - - @SuppressWarnings("unchecked") - Observer w = mock(Observer.class); - Subscription ws = st.subscribe(w); - - t.sendOnNext("one"); - ws.unsubscribe(); - t.sendOnCompleted(); - - verify(w, times(1)).onNext("one"); - verify(w, Mockito.never()).onCompleted(); - } - - /** - * Ensure onNext can not be called after an Unsubscribe - */ - @Test - public void testOnNextAfterUnSubscribe() { - TestObservable t = new TestObservable(null); - Observable st = Observable.create(synchronize(Observable.create(t))); - - @SuppressWarnings("unchecked") - Observer w = mock(Observer.class); - Subscription ws = st.subscribe(w); - - t.sendOnNext("one"); - ws.unsubscribe(); - t.sendOnNext("two"); - - verify(w, times(1)).onNext("one"); - verify(w, Mockito.never()).onNext("two"); - } - - /** - * Ensure onError can not be called after an Unsubscribe - */ - @Test - public void testOnErrorAfterUnSubscribe() { - TestObservable t = new TestObservable(null); - Observable st = Observable.create(synchronize(Observable.create(t))); - - @SuppressWarnings("unchecked") - Observer w = mock(Observer.class); - Subscription ws = st.subscribe(w); - - t.sendOnNext("one"); - ws.unsubscribe(); - t.sendOnError(new RuntimeException("bad")); - - verify(w, times(1)).onNext("one"); - verify(w, Mockito.never()).onError(any(Throwable.class)); - } - - /** - * Ensure onNext can not be called after onError - */ - @Test - public void testOnNextAfterOnError() { - TestObservable t = new TestObservable(null); - Observable st = Observable.create(synchronize(Observable.create(t))); - - @SuppressWarnings("unchecked") - Observer w = mock(Observer.class); - @SuppressWarnings("unused") - Subscription ws = st.subscribe(w); - - t.sendOnNext("one"); - t.sendOnError(new RuntimeException("bad")); - t.sendOnNext("two"); - - verify(w, times(1)).onNext("one"); - verify(w, times(1)).onError(any(Throwable.class)); - verify(w, Mockito.never()).onNext("two"); - } - - /** - * Ensure onCompleted can not be called after onError - */ - @Test - public void testOnCompletedAfterOnError() { - TestObservable t = new TestObservable(null); - Observable st = Observable.create(synchronize(Observable.create(t))); - - @SuppressWarnings("unchecked") - Observer w = mock(Observer.class); - @SuppressWarnings("unused") - Subscription ws = st.subscribe(w); - - t.sendOnNext("one"); - t.sendOnError(new RuntimeException("bad")); - t.sendOnCompleted(); - - verify(w, times(1)).onNext("one"); - verify(w, times(1)).onError(any(Throwable.class)); - verify(w, Mockito.never()).onCompleted(); - } - - /** - * Ensure onNext can not be called after onCompleted - */ - @Test - public void testOnNextAfterOnCompleted() { - TestObservable t = new TestObservable(null); - Observable st = Observable.create(synchronize(Observable.create(t))); - - @SuppressWarnings("unchecked") - Observer w = mock(Observer.class); - @SuppressWarnings("unused") - Subscription ws = st.subscribe(w); - - t.sendOnNext("one"); - t.sendOnCompleted(); - t.sendOnNext("two"); - - verify(w, times(1)).onNext("one"); - verify(w, Mockito.never()).onNext("two"); - verify(w, times(1)).onCompleted(); - verify(w, Mockito.never()).onError(any(Throwable.class)); - } - - /** - * Ensure onError can not be called after onCompleted - */ - @Test - public void testOnErrorAfterOnCompleted() { - TestObservable t = new TestObservable(null); - Observable st = Observable.create(synchronize(Observable.create(t))); - - @SuppressWarnings("unchecked") - Observer w = mock(Observer.class); - @SuppressWarnings("unused") - Subscription ws = st.subscribe(w); - - t.sendOnNext("one"); - t.sendOnCompleted(); - t.sendOnError(new RuntimeException("bad")); - - verify(w, times(1)).onNext("one"); - verify(w, times(1)).onCompleted(); - verify(w, Mockito.never()).onError(any(Throwable.class)); - } - - /** - * A Observable that doesn't do the right thing on UnSubscribe/Error/etc in that it will keep sending events down the pipe regardless of what happens. - */ - private static class TestObservable implements Observable.OnSubscribeFunc { - - Observer observer = null; - - public TestObservable(Subscription s) { + /** + * Ensure onCompleted can not be called after an Unsubscribe + */ + @Test + public void testOnCompletedAfterUnSubscribe() { + TestObservable t = new TestObservable(null); + Observable st = Observable.create(synchronize(Observable.create(t))); + + @SuppressWarnings("unchecked") + Observer w = mock(Observer.class); + Subscription ws = st.subscribe(w); + + t.sendOnNext("one"); + ws.unsubscribe(); + t.sendOnCompleted(); + + verify(w, times(1)).onNext("one"); + verify(w, Mockito.never()).onCompleted(); + } + + /** + * Ensure onNext can not be called after an Unsubscribe + */ + @Test + public void testOnNextAfterUnSubscribe() { + TestObservable t = new TestObservable(null); + Observable st = Observable.create(synchronize(Observable.create(t))); + + @SuppressWarnings("unchecked") + Observer w = mock(Observer.class); + Subscription ws = st.subscribe(w); + + t.sendOnNext("one"); + ws.unsubscribe(); + t.sendOnNext("two"); + + verify(w, times(1)).onNext("one"); + verify(w, Mockito.never()).onNext("two"); + } + + /** + * Ensure onError can not be called after an Unsubscribe + */ + @Test + public void testOnErrorAfterUnSubscribe() { + TestObservable t = new TestObservable(null); + Observable st = Observable.create(synchronize(Observable.create(t))); + + @SuppressWarnings("unchecked") + Observer w = mock(Observer.class); + Subscription ws = st.subscribe(w); + + t.sendOnNext("one"); + ws.unsubscribe(); + t.sendOnError(new RuntimeException("bad")); + + verify(w, times(1)).onNext("one"); + verify(w, Mockito.never()).onError(any(Throwable.class)); + } + + /** + * Ensure onNext can not be called after onError + */ + @Test + public void testOnNextAfterOnError() { + TestObservable t = new TestObservable(null); + Observable st = Observable.create(synchronize(Observable.create(t))); + + @SuppressWarnings("unchecked") + Observer w = mock(Observer.class); + @SuppressWarnings("unused") + Subscription ws = st.subscribe(w); + + t.sendOnNext("one"); + t.sendOnError(new RuntimeException("bad")); + t.sendOnNext("two"); + + verify(w, times(1)).onNext("one"); + verify(w, times(1)).onError(any(Throwable.class)); + verify(w, Mockito.never()).onNext("two"); } - /* used to simulate subscription */ - public void sendOnCompleted() { - observer.onCompleted(); + /** + * Ensure onCompleted can not be called after onError + */ + @Test + public void testOnCompletedAfterOnError() { + TestObservable t = new TestObservable(null); + Observable st = Observable.create(synchronize(Observable.create(t))); + + @SuppressWarnings("unchecked") + Observer w = mock(Observer.class); + @SuppressWarnings("unused") + Subscription ws = st.subscribe(w); + + t.sendOnNext("one"); + t.sendOnError(new RuntimeException("bad")); + t.sendOnCompleted(); + + verify(w, times(1)).onNext("one"); + verify(w, times(1)).onError(any(Throwable.class)); + verify(w, Mockito.never()).onCompleted(); } - /* used to simulate subscription */ - public void sendOnNext(String value) { - observer.onNext(value); + /** + * Ensure onNext can not be called after onCompleted + */ + @Test + public void testOnNextAfterOnCompleted() { + TestObservable t = new TestObservable(null); + Observable st = Observable.create(synchronize(Observable.create(t))); + + @SuppressWarnings("unchecked") + Observer w = mock(Observer.class); + @SuppressWarnings("unused") + Subscription ws = st.subscribe(w); + + t.sendOnNext("one"); + t.sendOnCompleted(); + t.sendOnNext("two"); + + verify(w, times(1)).onNext("one"); + verify(w, Mockito.never()).onNext("two"); + verify(w, times(1)).onCompleted(); + verify(w, Mockito.never()).onError(any(Throwable.class)); } - /* used to simulate subscription */ - public void sendOnError(Throwable e) { - observer.onError(e); + /** + * Ensure onError can not be called after onCompleted + */ + @Test + public void testOnErrorAfterOnCompleted() { + TestObservable t = new TestObservable(null); + Observable st = Observable.create(synchronize(Observable.create(t))); + + @SuppressWarnings("unchecked") + Observer w = mock(Observer.class); + @SuppressWarnings("unused") + Subscription ws = st.subscribe(w); + + t.sendOnNext("one"); + t.sendOnCompleted(); + t.sendOnError(new RuntimeException("bad")); + + verify(w, times(1)).onNext("one"); + verify(w, times(1)).onCompleted(); + verify(w, Mockito.never()).onError(any(Throwable.class)); } - @Override - public Subscription onSubscribe(final Observer observer) { - this.observer = observer; - return new Subscription() { + /** + * A Observable that doesn't do the right thing on UnSubscribe/Error/etc in that it will keep sending events down the pipe regardless of what happens. + */ + private static class TestObservable implements Observable.OnSubscribeFunc { + + Observer observer = null; + + public TestObservable(Subscription s) { + } + + /* used to simulate subscription */ + public void sendOnCompleted() { + observer.onCompleted(); + } + + /* used to simulate subscription */ + public void sendOnNext(String value) { + observer.onNext(value); + } + + /* used to simulate subscription */ + public void sendOnError(Throwable e) { + observer.onError(e); + } @Override - public void unsubscribe() { - // going to do nothing to pretend I'm a bad Observable that keeps allowing events to be sent + public Subscription onSubscribe(final Observer observer) { + this.observer = observer; + return new Subscription() { + + @Override + public void unsubscribe() { + // going to do nothing to pretend I'm a bad Observable that keeps allowing events to be sent + } + + }; } - }; } - - } } diff --git a/rxjava-core/src/test/java/rx/operators/OperationTakeLastTest.java b/rxjava-core/src/test/java/rx/operators/OperationTakeLastTest.java index 89fc932b51..2bc6ec2da8 100644 --- a/rxjava-core/src/test/java/rx/operators/OperationTakeLastTest.java +++ b/rxjava-core/src/test/java/rx/operators/OperationTakeLastTest.java @@ -1,97 +1,98 @@ package rx.operators; +import static org.mockito.Matchers.*; +import static org.mockito.Mockito.*; +import static rx.operators.OperationTakeLast.*; + import org.junit.Test; import org.mockito.InOrder; + import rx.Observable; import rx.Observer; -import static org.mockito.Matchers.any; -import static org.mockito.Mockito.*; -import static rx.operators.OperationTakeLast.takeLast; - public class OperationTakeLastTest { - @Test - public void testTakeLastEmpty() { - Observable w = Observable.empty(); - Observable take = Observable.create(takeLast(w, 2)); - - @SuppressWarnings("unchecked") - Observer aObserver = mock(Observer.class); - take.subscribe(aObserver); - verify(aObserver, never()).onNext(any(String.class)); - verify(aObserver, never()).onError(any(Throwable.class)); - verify(aObserver, times(1)).onCompleted(); - } - - @Test - public void testTakeLast1() { - Observable w = Observable.from("one", "two", "three"); - Observable take = Observable.create(takeLast(w, 2)); - - @SuppressWarnings("unchecked") - Observer aObserver = mock(Observer.class); - InOrder inOrder = inOrder(aObserver); - take.subscribe(aObserver); - inOrder.verify(aObserver, times(1)).onNext("two"); - inOrder.verify(aObserver, times(1)).onNext("three"); - verify(aObserver, never()).onNext("one"); - verify(aObserver, never()).onError(any(Throwable.class)); - verify(aObserver, times(1)).onCompleted(); - } - - @Test - public void testTakeLast2() { - Observable w = Observable.from("one"); - Observable take = Observable.create(takeLast(w, 10)); - - @SuppressWarnings("unchecked") - Observer aObserver = mock(Observer.class); - take.subscribe(aObserver); - verify(aObserver, times(1)).onNext("one"); - verify(aObserver, never()).onError(any(Throwable.class)); - verify(aObserver, times(1)).onCompleted(); - } - - @Test - public void testTakeLastWithZeroCount() { - Observable w = Observable.from("one"); - Observable take = Observable.create(takeLast(w, 0)); - - @SuppressWarnings("unchecked") - Observer aObserver = mock(Observer.class); - take.subscribe(aObserver); - verify(aObserver, never()).onNext("one"); - verify(aObserver, never()).onError(any(Throwable.class)); - verify(aObserver, times(1)).onCompleted(); - } - - @Test - public void testTakeLastWithNull() { - Observable w = Observable.from("one", null, "three"); - Observable take = Observable.create(takeLast(w, 2)); - - @SuppressWarnings("unchecked") - Observer aObserver = mock(Observer.class); - take.subscribe(aObserver); - verify(aObserver, never()).onNext("one"); - verify(aObserver, times(1)).onNext(null); - verify(aObserver, times(1)).onNext("three"); - verify(aObserver, never()).onError(any(Throwable.class)); - verify(aObserver, times(1)).onCompleted(); - } - - @Test - public void testTakeLastWithNegativeCount() { - Observable w = Observable.from("one"); - Observable take = Observable.create(takeLast(w, -1)); - - @SuppressWarnings("unchecked") - Observer aObserver = mock(Observer.class); - take.subscribe(aObserver); - verify(aObserver, never()).onNext("one"); - verify(aObserver, times(1)).onError( - any(IndexOutOfBoundsException.class)); - verify(aObserver, never()).onCompleted(); - } + @Test + public void testTakeLastEmpty() { + Observable w = Observable.empty(); + Observable take = Observable.create(takeLast(w, 2)); + + @SuppressWarnings("unchecked") + Observer aObserver = mock(Observer.class); + take.subscribe(aObserver); + verify(aObserver, never()).onNext(any(String.class)); + verify(aObserver, never()).onError(any(Throwable.class)); + verify(aObserver, times(1)).onCompleted(); + } + + @Test + public void testTakeLast1() { + Observable w = Observable.from("one", "two", "three"); + Observable take = Observable.create(takeLast(w, 2)); + + @SuppressWarnings("unchecked") + Observer aObserver = mock(Observer.class); + InOrder inOrder = inOrder(aObserver); + take.subscribe(aObserver); + inOrder.verify(aObserver, times(1)).onNext("two"); + inOrder.verify(aObserver, times(1)).onNext("three"); + verify(aObserver, never()).onNext("one"); + verify(aObserver, never()).onError(any(Throwable.class)); + verify(aObserver, times(1)).onCompleted(); + } + + @Test + public void testTakeLast2() { + Observable w = Observable.from("one"); + Observable take = Observable.create(takeLast(w, 10)); + + @SuppressWarnings("unchecked") + Observer aObserver = mock(Observer.class); + take.subscribe(aObserver); + verify(aObserver, times(1)).onNext("one"); + verify(aObserver, never()).onError(any(Throwable.class)); + verify(aObserver, times(1)).onCompleted(); + } + + @Test + public void testTakeLastWithZeroCount() { + Observable w = Observable.from("one"); + Observable take = Observable.create(takeLast(w, 0)); + + @SuppressWarnings("unchecked") + Observer aObserver = mock(Observer.class); + take.subscribe(aObserver); + verify(aObserver, never()).onNext("one"); + verify(aObserver, never()).onError(any(Throwable.class)); + verify(aObserver, times(1)).onCompleted(); + } + + @Test + public void testTakeLastWithNull() { + Observable w = Observable.from("one", null, "three"); + Observable take = Observable.create(takeLast(w, 2)); + + @SuppressWarnings("unchecked") + Observer aObserver = mock(Observer.class); + take.subscribe(aObserver); + verify(aObserver, never()).onNext("one"); + verify(aObserver, times(1)).onNext(null); + verify(aObserver, times(1)).onNext("three"); + verify(aObserver, never()).onError(any(Throwable.class)); + verify(aObserver, times(1)).onCompleted(); + } + + @Test + public void testTakeLastWithNegativeCount() { + Observable w = Observable.from("one"); + Observable take = Observable.create(takeLast(w, -1)); + + @SuppressWarnings("unchecked") + Observer aObserver = mock(Observer.class); + take.subscribe(aObserver); + verify(aObserver, never()).onNext("one"); + verify(aObserver, times(1)).onError( + any(IndexOutOfBoundsException.class)); + verify(aObserver, never()).onCompleted(); + } } diff --git a/rxjava-core/src/test/java/rx/operators/OperationTakeTest.java b/rxjava-core/src/test/java/rx/operators/OperationTakeTest.java index b02c4925cd..57a549e752 100644 --- a/rxjava-core/src/test/java/rx/operators/OperationTakeTest.java +++ b/rxjava-core/src/test/java/rx/operators/OperationTakeTest.java @@ -1,213 +1,212 @@ package rx.operators; +import static org.junit.Assert.*; +import static org.mockito.Matchers.*; +import static org.mockito.Mockito.*; +import static rx.operators.OperationTake.*; + +import java.util.concurrent.atomic.AtomicBoolean; + import org.junit.Test; import org.mockito.InOrder; + import rx.Observable; import rx.Observer; import rx.Subscription; import rx.subscriptions.Subscriptions; import rx.util.functions.Func1; -import java.util.concurrent.atomic.AtomicBoolean; - -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; -import static org.mockito.Matchers.any; -import static org.mockito.Matchers.anyString; -import static org.mockito.Mockito.*; -import static rx.operators.OperationTake.take; - public class OperationTakeTest { - @Test - public void testTake1() { - Observable w = Observable.from("one", "two", "three"); - Observable take = Observable.create(take(w, 2)); - - @SuppressWarnings("unchecked") - Observer aObserver = mock(Observer.class); - take.subscribe(aObserver); - verify(aObserver, times(1)).onNext("one"); - verify(aObserver, times(1)).onNext("two"); - verify(aObserver, never()).onNext("three"); - verify(aObserver, never()).onError(any(Throwable.class)); - verify(aObserver, times(1)).onCompleted(); - } - - @Test - public void testTake2() { - Observable w = Observable.from("one", "two", "three"); - Observable take = Observable.create(take(w, 1)); - - @SuppressWarnings("unchecked") - Observer aObserver = mock(Observer.class); - take.subscribe(aObserver); - verify(aObserver, times(1)).onNext("one"); - verify(aObserver, never()).onNext("two"); - verify(aObserver, never()).onNext("three"); - verify(aObserver, never()).onError(any(Throwable.class)); - verify(aObserver, times(1)).onCompleted(); - } - - @Test(expected = IllegalArgumentException.class) - public void testTakeWithError() { - Observable.from(1, 2, 3).take(1).map(new Func1() { - public Integer call(Integer t1) { - throw new IllegalArgumentException("some error"); - } - }).toBlockingObservable().single(); - } - - @Test - public void testTakeWithErrorHappeningInOnNext() { - Observable w = Observable.from(1, 2, 3).take(2).map(new Func1() { - public Integer call(Integer t1) { - throw new IllegalArgumentException("some error"); - } - }); - - @SuppressWarnings("unchecked") - Observer observer = mock(Observer.class); - w.subscribe(observer); - InOrder inOrder = inOrder(observer); - inOrder.verify(observer, times(1)).onError(any(IllegalArgumentException.class)); - inOrder.verifyNoMoreInteractions(); - } - - @Test - public void testTakeWithErrorHappeningInTheLastOnNext() { - Observable w = Observable.from(1, 2, 3).take(1).map(new Func1() { - public Integer call(Integer t1) { - throw new IllegalArgumentException("some error"); - } - }); - - @SuppressWarnings("unchecked") - Observer observer = mock(Observer.class); - w.subscribe(observer); - InOrder inOrder = inOrder(observer); - inOrder.verify(observer, times(1)).onError(any(IllegalArgumentException.class)); - inOrder.verifyNoMoreInteractions(); - } - - @Test - public void testTakeDoesntLeakErrors() { - Observable source = Observable.create(new Observable.OnSubscribeFunc() { - @Override - public Subscription onSubscribe(Observer observer) { - observer.onNext("one"); - observer.onError(new Throwable("test failed")); - return Subscriptions.empty(); - } - }); - - @SuppressWarnings("unchecked") - Observer aObserver = mock(Observer.class); - - Observable.create(take(source, 1)).subscribe(aObserver); - - verify(aObserver, times(1)).onNext("one"); - // even though onError is called we take(1) so shouldn't see it - verify(aObserver, never()).onError(any(Throwable.class)); - verify(aObserver, times(1)).onCompleted(); - verifyNoMoreInteractions(aObserver); - } - - @Test - public void testTakeZeroDoesntLeakError() { - final AtomicBoolean subscribed = new AtomicBoolean(false); - final AtomicBoolean unSubscribed = new AtomicBoolean(false); - Observable source = Observable.create(new Observable.OnSubscribeFunc() { - @Override - public Subscription onSubscribe(Observer observer) { - subscribed.set(true); - observer.onError(new Throwable("test failed")); - return new Subscription() { - @Override - public void unsubscribe() { - unSubscribed.set(true); - } - }; - } - }); - - @SuppressWarnings("unchecked") - Observer aObserver = mock(Observer.class); - - Observable.create(take(source, 0)).subscribe(aObserver); - assertTrue("source subscribed", subscribed.get()); - assertTrue("source unsubscribed", unSubscribed.get()); - - verify(aObserver, never()).onNext(anyString()); - // even though onError is called we take(0) so shouldn't see it - verify(aObserver, never()).onError(any(Throwable.class)); - verify(aObserver, times(1)).onCompleted(); - verifyNoMoreInteractions(aObserver); - } - - @Test - public void testUnsubscribeAfterTake() { - final Subscription s = mock(Subscription.class); - TestObservableFunc f = new TestObservableFunc(s, "one", "two", "three"); - Observable w = Observable.create(f); - - @SuppressWarnings("unchecked") - Observer aObserver = mock(Observer.class); - Observable take = Observable.create(take(w, 1)); - take.subscribe(aObserver); - - // wait for the Observable to complete - try { - f.t.join(); - } catch (Throwable e) { - e.printStackTrace(); - fail(e.getMessage()); + @Test + public void testTake1() { + Observable w = Observable.from("one", "two", "three"); + Observable take = Observable.create(take(w, 2)); + + @SuppressWarnings("unchecked") + Observer aObserver = mock(Observer.class); + take.subscribe(aObserver); + verify(aObserver, times(1)).onNext("one"); + verify(aObserver, times(1)).onNext("two"); + verify(aObserver, never()).onNext("three"); + verify(aObserver, never()).onError(any(Throwable.class)); + verify(aObserver, times(1)).onCompleted(); } - System.out.println("TestObservable thread finished"); - verify(aObserver, times(1)).onNext("one"); - verify(aObserver, never()).onNext("two"); - verify(aObserver, never()).onNext("three"); - verify(aObserver, times(1)).onCompleted(); - verify(s, times(1)).unsubscribe(); - verifyNoMoreInteractions(aObserver); - } + @Test + public void testTake2() { + Observable w = Observable.from("one", "two", "three"); + Observable take = Observable.create(take(w, 1)); + + @SuppressWarnings("unchecked") + Observer aObserver = mock(Observer.class); + take.subscribe(aObserver); + verify(aObserver, times(1)).onNext("one"); + verify(aObserver, never()).onNext("two"); + verify(aObserver, never()).onNext("three"); + verify(aObserver, never()).onError(any(Throwable.class)); + verify(aObserver, times(1)).onCompleted(); + } - private static class TestObservableFunc implements Observable.OnSubscribeFunc { + @Test(expected = IllegalArgumentException.class) + public void testTakeWithError() { + Observable.from(1, 2, 3).take(1).map(new Func1() { + public Integer call(Integer t1) { + throw new IllegalArgumentException("some error"); + } + }).toBlockingObservable().single(); + } - final Subscription s; - final String[] values; - Thread t = null; + @Test + public void testTakeWithErrorHappeningInOnNext() { + Observable w = Observable.from(1, 2, 3).take(2).map(new Func1() { + public Integer call(Integer t1) { + throw new IllegalArgumentException("some error"); + } + }); + + @SuppressWarnings("unchecked") + Observer observer = mock(Observer.class); + w.subscribe(observer); + InOrder inOrder = inOrder(observer); + inOrder.verify(observer, times(1)).onError(any(IllegalArgumentException.class)); + inOrder.verifyNoMoreInteractions(); + } - public TestObservableFunc(Subscription s, String... values) { - this.s = s; - this.values = values; + @Test + public void testTakeWithErrorHappeningInTheLastOnNext() { + Observable w = Observable.from(1, 2, 3).take(1).map(new Func1() { + public Integer call(Integer t1) { + throw new IllegalArgumentException("some error"); + } + }); + + @SuppressWarnings("unchecked") + Observer observer = mock(Observer.class); + w.subscribe(observer); + InOrder inOrder = inOrder(observer); + inOrder.verify(observer, times(1)).onError(any(IllegalArgumentException.class)); + inOrder.verifyNoMoreInteractions(); } - @Override - public Subscription onSubscribe(final Observer observer) { - System.out.println("TestObservable subscribed to ..."); - t = new Thread(new Runnable() { + @Test + public void testTakeDoesntLeakErrors() { + Observable source = Observable.create(new Observable.OnSubscribeFunc() { + @Override + public Subscription onSubscribe(Observer observer) { + observer.onNext("one"); + observer.onError(new Throwable("test failed")); + return Subscriptions.empty(); + } + }); - @Override - public void run() { - try { - System.out.println("running TestObservable thread"); - for (String s : values) { - System.out.println("TestObservable onNext: " + s); - observer.onNext(s); + @SuppressWarnings("unchecked") + Observer aObserver = mock(Observer.class); + + Observable.create(take(source, 1)).subscribe(aObserver); + + verify(aObserver, times(1)).onNext("one"); + // even though onError is called we take(1) so shouldn't see it + verify(aObserver, never()).onError(any(Throwable.class)); + verify(aObserver, times(1)).onCompleted(); + verifyNoMoreInteractions(aObserver); + } + + @Test + public void testTakeZeroDoesntLeakError() { + final AtomicBoolean subscribed = new AtomicBoolean(false); + final AtomicBoolean unSubscribed = new AtomicBoolean(false); + Observable source = Observable.create(new Observable.OnSubscribeFunc() { + @Override + public Subscription onSubscribe(Observer observer) { + subscribed.set(true); + observer.onError(new Throwable("test failed")); + return new Subscription() { + @Override + public void unsubscribe() { + unSubscribed.set(true); + } + }; } - observer.onCompleted(); - } catch (Throwable e) { - throw new RuntimeException(e); - } + }); + + @SuppressWarnings("unchecked") + Observer aObserver = mock(Observer.class); + + Observable.create(take(source, 0)).subscribe(aObserver); + assertTrue("source subscribed", subscribed.get()); + assertTrue("source unsubscribed", unSubscribed.get()); + + verify(aObserver, never()).onNext(anyString()); + // even though onError is called we take(0) so shouldn't see it + verify(aObserver, never()).onError(any(Throwable.class)); + verify(aObserver, times(1)).onCompleted(); + verifyNoMoreInteractions(aObserver); + } + + @Test + public void testUnsubscribeAfterTake() { + final Subscription s = mock(Subscription.class); + TestObservableFunc f = new TestObservableFunc(s, "one", "two", "three"); + Observable w = Observable.create(f); + + @SuppressWarnings("unchecked") + Observer aObserver = mock(Observer.class); + Observable take = Observable.create(take(w, 1)); + take.subscribe(aObserver); + + // wait for the Observable to complete + try { + f.t.join(); + } catch (Throwable e) { + e.printStackTrace(); + fail(e.getMessage()); } - }); - System.out.println("starting TestObservable thread"); - t.start(); - System.out.println("done starting TestObservable thread"); - return s; + System.out.println("TestObservable thread finished"); + verify(aObserver, times(1)).onNext("one"); + verify(aObserver, never()).onNext("two"); + verify(aObserver, never()).onNext("three"); + verify(aObserver, times(1)).onCompleted(); + verify(s, times(1)).unsubscribe(); + verifyNoMoreInteractions(aObserver); + } + + private static class TestObservableFunc implements Observable.OnSubscribeFunc { + + final Subscription s; + final String[] values; + Thread t = null; + + public TestObservableFunc(Subscription s, String... values) { + this.s = s; + this.values = values; + } + + @Override + public Subscription onSubscribe(final Observer observer) { + System.out.println("TestObservable subscribed to ..."); + t = new Thread(new Runnable() { + + @Override + public void run() { + try { + System.out.println("running TestObservable thread"); + for (String s : values) { + System.out.println("TestObservable onNext: " + s); + observer.onNext(s); + } + observer.onCompleted(); + } catch (Throwable e) { + throw new RuntimeException(e); + } + } + + }); + System.out.println("starting TestObservable thread"); + t.start(); + System.out.println("done starting TestObservable thread"); + return s; + } } - } } diff --git a/rxjava-core/src/test/java/rx/operators/OperationTakeUntilTest.java b/rxjava-core/src/test/java/rx/operators/OperationTakeUntilTest.java index 0e46af91e8..7033f9154a 100644 --- a/rxjava-core/src/test/java/rx/operators/OperationTakeUntilTest.java +++ b/rxjava-core/src/test/java/rx/operators/OperationTakeUntilTest.java @@ -1,164 +1,165 @@ package rx.operators; +import static org.mockito.Mockito.*; +import static rx.operators.OperationTakeUntil.*; + import org.junit.Test; + import rx.Observable; import rx.Observer; import rx.Subscription; -import static org.mockito.Mockito.*; -import static rx.operators.OperationTakeUntil.takeUntil; - public class OperationTakeUntilTest { - @Test - @SuppressWarnings("unchecked") - public void testTakeUntil() { - Subscription sSource = mock(Subscription.class); - Subscription sOther = mock(Subscription.class); - TestObservable source = new TestObservable(sSource); - TestObservable other = new TestObservable(sOther); - - Observer result = mock(Observer.class); - Observable stringObservable = takeUntil(Observable.create(source), Observable.create(other)); - stringObservable.subscribe(result); - source.sendOnNext("one"); - source.sendOnNext("two"); - other.sendOnNext("three"); - source.sendOnNext("four"); - source.sendOnCompleted(); - other.sendOnCompleted(); - - verify(result, times(1)).onNext("one"); - verify(result, times(1)).onNext("two"); - verify(result, times(0)).onNext("three"); - verify(result, times(0)).onNext("four"); - verify(sSource, times(1)).unsubscribe(); - verify(sOther, times(1)).unsubscribe(); - - } - - @Test - @SuppressWarnings("unchecked") - public void testTakeUntilSourceCompleted() { - Subscription sSource = mock(Subscription.class); - Subscription sOther = mock(Subscription.class); - TestObservable source = new TestObservable(sSource); - TestObservable other = new TestObservable(sOther); - - Observer result = mock(Observer.class); - Observable stringObservable = takeUntil(Observable.create(source), Observable.create(other)); - stringObservable.subscribe(result); - source.sendOnNext("one"); - source.sendOnNext("two"); - source.sendOnCompleted(); - - verify(result, times(1)).onNext("one"); - verify(result, times(1)).onNext("two"); - verify(sSource, times(1)).unsubscribe(); - verify(sOther, times(1)).unsubscribe(); - - } - - @Test - @SuppressWarnings("unchecked") - public void testTakeUntilSourceError() { - Subscription sSource = mock(Subscription.class); - Subscription sOther = mock(Subscription.class); - TestObservable source = new TestObservable(sSource); - TestObservable other = new TestObservable(sOther); - Throwable error = new Throwable(); - - Observer result = mock(Observer.class); - Observable stringObservable = takeUntil(Observable.create(source), Observable.create(other)); - stringObservable.subscribe(result); - source.sendOnNext("one"); - source.sendOnNext("two"); - source.sendOnError(error); - - verify(result, times(1)).onNext("one"); - verify(result, times(1)).onNext("two"); - verify(result, times(1)).onError(error); - verify(sSource, times(1)).unsubscribe(); - verify(sOther, times(1)).unsubscribe(); - - } - - @Test - @SuppressWarnings("unchecked") - public void testTakeUntilOtherError() { - Subscription sSource = mock(Subscription.class); - Subscription sOther = mock(Subscription.class); - TestObservable source = new TestObservable(sSource); - TestObservable other = new TestObservable(sOther); - Throwable error = new Throwable(); - - Observer result = mock(Observer.class); - Observable stringObservable = takeUntil(Observable.create(source), Observable.create(other)); - stringObservable.subscribe(result); - source.sendOnNext("one"); - source.sendOnNext("two"); - other.sendOnError(error); - - verify(result, times(1)).onNext("one"); - verify(result, times(1)).onNext("two"); - verify(result, times(1)).onError(error); - verify(result, times(0)).onCompleted(); - verify(sSource, times(1)).unsubscribe(); - verify(sOther, times(1)).unsubscribe(); - - } - - @Test - @SuppressWarnings("unchecked") - public void testTakeUntilOtherCompleted() { - Subscription sSource = mock(Subscription.class); - Subscription sOther = mock(Subscription.class); - TestObservable source = new TestObservable(sSource); - TestObservable other = new TestObservable(sOther); - - Observer result = mock(Observer.class); - Observable stringObservable = takeUntil(Observable.create(source), Observable.create(other)); - stringObservable.subscribe(result); - source.sendOnNext("one"); - source.sendOnNext("two"); - other.sendOnCompleted(); - - verify(result, times(1)).onNext("one"); - verify(result, times(1)).onNext("two"); - verify(result, times(0)).onCompleted(); - verify(sSource, times(0)).unsubscribe(); - verify(sOther, times(0)).unsubscribe(); - - } - - private static class TestObservable implements Observable.OnSubscribeFunc { - - Observer observer = null; - Subscription s; - - public TestObservable(Subscription s) { - this.s = s; + @Test + @SuppressWarnings("unchecked") + public void testTakeUntil() { + Subscription sSource = mock(Subscription.class); + Subscription sOther = mock(Subscription.class); + TestObservable source = new TestObservable(sSource); + TestObservable other = new TestObservable(sOther); + + Observer result = mock(Observer.class); + Observable stringObservable = takeUntil(Observable.create(source), Observable.create(other)); + stringObservable.subscribe(result); + source.sendOnNext("one"); + source.sendOnNext("two"); + other.sendOnNext("three"); + source.sendOnNext("four"); + source.sendOnCompleted(); + other.sendOnCompleted(); + + verify(result, times(1)).onNext("one"); + verify(result, times(1)).onNext("two"); + verify(result, times(0)).onNext("three"); + verify(result, times(0)).onNext("four"); + verify(sSource, times(1)).unsubscribe(); + verify(sOther, times(1)).unsubscribe(); + + } + + @Test + @SuppressWarnings("unchecked") + public void testTakeUntilSourceCompleted() { + Subscription sSource = mock(Subscription.class); + Subscription sOther = mock(Subscription.class); + TestObservable source = new TestObservable(sSource); + TestObservable other = new TestObservable(sOther); + + Observer result = mock(Observer.class); + Observable stringObservable = takeUntil(Observable.create(source), Observable.create(other)); + stringObservable.subscribe(result); + source.sendOnNext("one"); + source.sendOnNext("two"); + source.sendOnCompleted(); + + verify(result, times(1)).onNext("one"); + verify(result, times(1)).onNext("two"); + verify(sSource, times(1)).unsubscribe(); + verify(sOther, times(1)).unsubscribe(); + } - /* used to simulate subscription */ - public void sendOnCompleted() { - observer.onCompleted(); + @Test + @SuppressWarnings("unchecked") + public void testTakeUntilSourceError() { + Subscription sSource = mock(Subscription.class); + Subscription sOther = mock(Subscription.class); + TestObservable source = new TestObservable(sSource); + TestObservable other = new TestObservable(sOther); + Throwable error = new Throwable(); + + Observer result = mock(Observer.class); + Observable stringObservable = takeUntil(Observable.create(source), Observable.create(other)); + stringObservable.subscribe(result); + source.sendOnNext("one"); + source.sendOnNext("two"); + source.sendOnError(error); + + verify(result, times(1)).onNext("one"); + verify(result, times(1)).onNext("two"); + verify(result, times(1)).onError(error); + verify(sSource, times(1)).unsubscribe(); + verify(sOther, times(1)).unsubscribe(); + } - /* used to simulate subscription */ - public void sendOnNext(String value) { - observer.onNext(value); + @Test + @SuppressWarnings("unchecked") + public void testTakeUntilOtherError() { + Subscription sSource = mock(Subscription.class); + Subscription sOther = mock(Subscription.class); + TestObservable source = new TestObservable(sSource); + TestObservable other = new TestObservable(sOther); + Throwable error = new Throwable(); + + Observer result = mock(Observer.class); + Observable stringObservable = takeUntil(Observable.create(source), Observable.create(other)); + stringObservable.subscribe(result); + source.sendOnNext("one"); + source.sendOnNext("two"); + other.sendOnError(error); + + verify(result, times(1)).onNext("one"); + verify(result, times(1)).onNext("two"); + verify(result, times(1)).onError(error); + verify(result, times(0)).onCompleted(); + verify(sSource, times(1)).unsubscribe(); + verify(sOther, times(1)).unsubscribe(); + } - /* used to simulate subscription */ - public void sendOnError(Throwable e) { - observer.onError(e); + @Test + @SuppressWarnings("unchecked") + public void testTakeUntilOtherCompleted() { + Subscription sSource = mock(Subscription.class); + Subscription sOther = mock(Subscription.class); + TestObservable source = new TestObservable(sSource); + TestObservable other = new TestObservable(sOther); + + Observer result = mock(Observer.class); + Observable stringObservable = takeUntil(Observable.create(source), Observable.create(other)); + stringObservable.subscribe(result); + source.sendOnNext("one"); + source.sendOnNext("two"); + other.sendOnCompleted(); + + verify(result, times(1)).onNext("one"); + verify(result, times(1)).onNext("two"); + verify(result, times(0)).onCompleted(); + verify(sSource, times(0)).unsubscribe(); + verify(sOther, times(0)).unsubscribe(); + } - @Override - public Subscription onSubscribe(final Observer observer) { - this.observer = observer; - return s; + private static class TestObservable implements Observable.OnSubscribeFunc { + + Observer observer = null; + Subscription s; + + public TestObservable(Subscription s) { + this.s = s; + } + + /* used to simulate subscription */ + public void sendOnCompleted() { + observer.onCompleted(); + } + + /* used to simulate subscription */ + public void sendOnNext(String value) { + observer.onNext(value); + } + + /* used to simulate subscription */ + public void sendOnError(Throwable e) { + observer.onError(e); + } + + @Override + public Subscription onSubscribe(final Observer observer) { + this.observer = observer; + return s; + } } - } } diff --git a/rxjava-core/src/test/java/rx/operators/OperationTakeWhileTest.java b/rxjava-core/src/test/java/rx/operators/OperationTakeWhileTest.java index 8109c818e0..dee73d2cdf 100644 --- a/rxjava-core/src/test/java/rx/operators/OperationTakeWhileTest.java +++ b/rxjava-core/src/test/java/rx/operators/OperationTakeWhileTest.java @@ -1,6 +1,12 @@ package rx.operators; +import static org.junit.Assert.*; +import static org.mockito.Matchers.*; +import static org.mockito.Mockito.*; +import static rx.operators.OperationTakeWhile.*; + import org.junit.Test; + import rx.Observable; import rx.Observer; import rx.Subscription; @@ -10,195 +16,189 @@ import rx.util.functions.Func1; import rx.util.functions.Func2; -import static org.junit.Assert.fail; -import static org.mockito.Matchers.any; -import static org.mockito.Mockito.*; -import static rx.operators.OperationTakeWhile.takeWhile; -import static rx.operators.OperationTakeWhile.takeWhileWithIndex; - public class OperationTakeWhileTest { - @Test - public void testTakeWhile1() { - Observable w = Observable.from(1, 2, 3); - Observable take = Observable.create(takeWhile(w, new Func1() { - @Override - public Boolean call(Integer input) { - return input < 3; - } - })); - - @SuppressWarnings("unchecked") - Observer aObserver = mock(Observer.class); - take.subscribe(aObserver); - verify(aObserver, times(1)).onNext(1); - verify(aObserver, times(1)).onNext(2); - verify(aObserver, never()).onNext(3); - verify(aObserver, never()).onError(any(Throwable.class)); - verify(aObserver, times(1)).onCompleted(); - } - - @Test - public void testTakeWhileOnSubject1() { - Subject s = PublishSubject.create(); - Observable take = Observable.create(takeWhile(s, new Func1() { - @Override - public Boolean call(Integer input) { - return input < 3; - } - })); - - @SuppressWarnings("unchecked") - Observer aObserver = mock(Observer.class); - take.subscribe(aObserver); - - s.onNext(1); - s.onNext(2); - s.onNext(3); - s.onNext(4); - s.onNext(5); - s.onCompleted(); - - verify(aObserver, times(1)).onNext(1); - verify(aObserver, times(1)).onNext(2); - verify(aObserver, never()).onNext(3); - verify(aObserver, never()).onNext(4); - verify(aObserver, never()).onNext(5); - verify(aObserver, never()).onError(any(Throwable.class)); - verify(aObserver, times(1)).onCompleted(); - } - - @Test - public void testTakeWhile2() { - Observable w = Observable.from("one", "two", "three"); - Observable take = Observable.create(takeWhileWithIndex(w, new Func2() { - @Override - public Boolean call(String input, Integer index) { - return index < 2; - } - })); - - @SuppressWarnings("unchecked") - Observer aObserver = mock(Observer.class); - take.subscribe(aObserver); - verify(aObserver, times(1)).onNext("one"); - verify(aObserver, times(1)).onNext("two"); - verify(aObserver, never()).onNext("three"); - verify(aObserver, never()).onError(any(Throwable.class)); - verify(aObserver, times(1)).onCompleted(); - } - - @Test - public void testTakeWhileDoesntLeakErrors() { - Observable source = Observable.create(new Observable.OnSubscribeFunc() { - @Override - public Subscription onSubscribe(Observer observer) { - observer.onNext("one"); - observer.onError(new Throwable("test failed")); - return Subscriptions.empty(); - } - }); - - Observable.create(takeWhile(source, new Func1() { - @Override - public Boolean call(String s) { - return false; - } - })).toBlockingObservable().last(); - } - - @Test - public void testTakeWhileProtectsPredicateCall() { - TestObservable source = new TestObservable(mock(Subscription.class), "one"); - final RuntimeException testException = new RuntimeException("test exception"); - - @SuppressWarnings("unchecked") - Observer aObserver = mock(Observer.class); - Observable take = Observable.create(takeWhile(Observable.create(source), new Func1() { - @Override - public Boolean call(String s) { - throw testException; - } - })); - take.subscribe(aObserver); - - // wait for the Observable to complete - try { - source.t.join(); - } catch (Throwable e) { - e.printStackTrace(); - fail(e.getMessage()); + @Test + public void testTakeWhile1() { + Observable w = Observable.from(1, 2, 3); + Observable take = Observable.create(takeWhile(w, new Func1() { + @Override + public Boolean call(Integer input) { + return input < 3; + } + })); + + @SuppressWarnings("unchecked") + Observer aObserver = mock(Observer.class); + take.subscribe(aObserver); + verify(aObserver, times(1)).onNext(1); + verify(aObserver, times(1)).onNext(2); + verify(aObserver, never()).onNext(3); + verify(aObserver, never()).onError(any(Throwable.class)); + verify(aObserver, times(1)).onCompleted(); } - verify(aObserver, never()).onNext(any(String.class)); - verify(aObserver, times(1)).onError(testException); - } - - @Test - public void testUnsubscribeAfterTake() { - Subscription s = mock(Subscription.class); - TestObservable w = new TestObservable(s, "one", "two", "three"); - - @SuppressWarnings("unchecked") - Observer aObserver = mock(Observer.class); - Observable take = Observable.create(takeWhileWithIndex(Observable.create(w), new Func2() { - @Override - public Boolean call(String s, Integer index) { - return index < 1; - } - })); - take.subscribe(aObserver); - - // wait for the Observable to complete - try { - w.t.join(); - } catch (Throwable e) { - e.printStackTrace(); - fail(e.getMessage()); + @Test + public void testTakeWhileOnSubject1() { + Subject s = PublishSubject.create(); + Observable take = Observable.create(takeWhile(s, new Func1() { + @Override + public Boolean call(Integer input) { + return input < 3; + } + })); + + @SuppressWarnings("unchecked") + Observer aObserver = mock(Observer.class); + take.subscribe(aObserver); + + s.onNext(1); + s.onNext(2); + s.onNext(3); + s.onNext(4); + s.onNext(5); + s.onCompleted(); + + verify(aObserver, times(1)).onNext(1); + verify(aObserver, times(1)).onNext(2); + verify(aObserver, never()).onNext(3); + verify(aObserver, never()).onNext(4); + verify(aObserver, never()).onNext(5); + verify(aObserver, never()).onError(any(Throwable.class)); + verify(aObserver, times(1)).onCompleted(); } - System.out.println("TestObservable thread finished"); - verify(aObserver, times(1)).onNext("one"); - verify(aObserver, never()).onNext("two"); - verify(aObserver, never()).onNext("three"); - verify(s, times(1)).unsubscribe(); - } - - private static class TestObservable implements Observable.OnSubscribeFunc { + @Test + public void testTakeWhile2() { + Observable w = Observable.from("one", "two", "three"); + Observable take = Observable.create(takeWhileWithIndex(w, new Func2() { + @Override + public Boolean call(String input, Integer index) { + return index < 2; + } + })); + + @SuppressWarnings("unchecked") + Observer aObserver = mock(Observer.class); + take.subscribe(aObserver); + verify(aObserver, times(1)).onNext("one"); + verify(aObserver, times(1)).onNext("two"); + verify(aObserver, never()).onNext("three"); + verify(aObserver, never()).onError(any(Throwable.class)); + verify(aObserver, times(1)).onCompleted(); + } - final Subscription s; - final String[] values; - Thread t = null; + @Test + public void testTakeWhileDoesntLeakErrors() { + Observable source = Observable.create(new Observable.OnSubscribeFunc() { + @Override + public Subscription onSubscribe(Observer observer) { + observer.onNext("one"); + observer.onError(new Throwable("test failed")); + return Subscriptions.empty(); + } + }); - public TestObservable(Subscription s, String... values) { - this.s = s; - this.values = values; + Observable.create(takeWhile(source, new Func1() { + @Override + public Boolean call(String s) { + return false; + } + })).toBlockingObservable().last(); } - @Override - public Subscription onSubscribe(final Observer observer) { - System.out.println("TestObservable subscribed to ..."); - t = new Thread(new Runnable() { + @Test + public void testTakeWhileProtectsPredicateCall() { + TestObservable source = new TestObservable(mock(Subscription.class), "one"); + final RuntimeException testException = new RuntimeException("test exception"); + + @SuppressWarnings("unchecked") + Observer aObserver = mock(Observer.class); + Observable take = Observable.create(takeWhile(Observable.create(source), new Func1() { + @Override + public Boolean call(String s) { + throw testException; + } + })); + take.subscribe(aObserver); + + // wait for the Observable to complete + try { + source.t.join(); + } catch (Throwable e) { + e.printStackTrace(); + fail(e.getMessage()); + } - @Override - public void run() { - try { - System.out.println("running TestObservable thread"); - for (String s : values) { - System.out.println("TestObservable onNext: " + s); - observer.onNext(s); + verify(aObserver, never()).onNext(any(String.class)); + verify(aObserver, times(1)).onError(testException); + } + + @Test + public void testUnsubscribeAfterTake() { + Subscription s = mock(Subscription.class); + TestObservable w = new TestObservable(s, "one", "two", "three"); + + @SuppressWarnings("unchecked") + Observer aObserver = mock(Observer.class); + Observable take = Observable.create(takeWhileWithIndex(Observable.create(w), new Func2() { + @Override + public Boolean call(String s, Integer index) { + return index < 1; } - observer.onCompleted(); - } catch (Throwable e) { - throw new RuntimeException(e); - } + })); + take.subscribe(aObserver); + + // wait for the Observable to complete + try { + w.t.join(); + } catch (Throwable e) { + e.printStackTrace(); + fail(e.getMessage()); + } + + System.out.println("TestObservable thread finished"); + verify(aObserver, times(1)).onNext("one"); + verify(aObserver, never()).onNext("two"); + verify(aObserver, never()).onNext("three"); + verify(s, times(1)).unsubscribe(); + } + + private static class TestObservable implements Observable.OnSubscribeFunc { + + final Subscription s; + final String[] values; + Thread t = null; + + public TestObservable(Subscription s, String... values) { + this.s = s; + this.values = values; } - }); - System.out.println("starting TestObservable thread"); - t.start(); - System.out.println("done starting TestObservable thread"); - return s; + @Override + public Subscription onSubscribe(final Observer observer) { + System.out.println("TestObservable subscribed to ..."); + t = new Thread(new Runnable() { + + @Override + public void run() { + try { + System.out.println("running TestObservable thread"); + for (String s : values) { + System.out.println("TestObservable onNext: " + s); + observer.onNext(s); + } + observer.onCompleted(); + } catch (Throwable e) { + throw new RuntimeException(e); + } + } + + }); + System.out.println("starting TestObservable thread"); + t.start(); + System.out.println("done starting TestObservable thread"); + return s; + } } - } } diff --git a/rxjava-core/src/test/java/rx/operators/OperationThrottleFirstTest.java b/rxjava-core/src/test/java/rx/operators/OperationThrottleFirstTest.java index 76cac5dfe9..f5e75175d9 100644 --- a/rxjava-core/src/test/java/rx/operators/OperationThrottleFirstTest.java +++ b/rxjava-core/src/test/java/rx/operators/OperationThrottleFirstTest.java @@ -1,8 +1,14 @@ package rx.operators; +import static org.mockito.Matchers.*; +import static org.mockito.Mockito.*; + +import java.util.concurrent.TimeUnit; + import org.junit.Before; import org.junit.Test; import org.mockito.InOrder; + import rx.Observable; import rx.Observer; import rx.Subscription; @@ -10,105 +16,100 @@ import rx.subscriptions.Subscriptions; import rx.util.functions.Action0; -import java.util.concurrent.TimeUnit; - -import static org.mockito.Matchers.any; -import static org.mockito.Mockito.*; - public class OperationThrottleFirstTest { - private TestScheduler scheduler; - private Observer observer; - - @Before - @SuppressWarnings("unchecked") - public void before() { - scheduler = new TestScheduler(); - observer = mock(Observer.class); - } - - @Test - public void testThrottlingWithCompleted() { - Observable source = Observable.create(new Observable.OnSubscribeFunc() { - @Override - public Subscription onSubscribe(Observer observer) { - publishNext(observer, 100, "one"); // publish as it's first - publishNext(observer, 300, "two"); // skip as it's last within the first 400 - publishNext(observer, 900, "three"); // publish - publishNext(observer, 905, "four"); // skip - publishCompleted(observer, 1000); // Should be published as soon as the timeout expires. - - return Subscriptions.empty(); - } - }); - - Observable sampled = Observable.create(OperationThrottleFirst.throttleFirst(source, 400, TimeUnit.MILLISECONDS, scheduler)); - sampled.subscribe(observer); - - InOrder inOrder = inOrder(observer); - - scheduler.advanceTimeTo(1000, TimeUnit.MILLISECONDS); - inOrder.verify(observer, times(1)).onNext("one"); - inOrder.verify(observer, times(0)).onNext("two"); - inOrder.verify(observer, times(1)).onNext("three"); - inOrder.verify(observer, times(0)).onNext("four"); - inOrder.verify(observer, times(1)).onCompleted(); - inOrder.verifyNoMoreInteractions(); - } - - @Test - public void testThrottlingWithError() { - Observable source = Observable.create(new Observable.OnSubscribeFunc() { - @Override - public Subscription onSubscribe(Observer observer) { - Exception error = new TestException(); - publishNext(observer, 100, "one"); // Should be published since it is first - publishNext(observer, 200, "two"); // Should be skipped since onError will arrive before the timeout expires - publishError(observer, 300, error); // Should be published as soon as the timeout expires. - - return Subscriptions.empty(); - } - }); - - Observable sampled = Observable.create(OperationThrottleFirst.throttleFirst(source, 400, TimeUnit.MILLISECONDS, scheduler)); - sampled.subscribe(observer); - - InOrder inOrder = inOrder(observer); - - scheduler.advanceTimeTo(400, TimeUnit.MILLISECONDS); - inOrder.verify(observer).onNext("one"); - inOrder.verify(observer).onError(any(TestException.class)); - inOrder.verifyNoMoreInteractions(); - } - - private void publishCompleted(final Observer observer, long delay) { - scheduler.schedule(new Action0() { - @Override - public void call() { - observer.onCompleted(); - } - }, delay, TimeUnit.MILLISECONDS); - } - - private void publishError(final Observer observer, long delay, final Exception error) { - scheduler.schedule(new Action0() { - @Override - public void call() { - observer.onError(error); - } - }, delay, TimeUnit.MILLISECONDS); - } - - private void publishNext(final Observer observer, long delay, final T value) { - scheduler.schedule(new Action0() { - @Override - public void call() { - observer.onNext(value); - } - }, delay, TimeUnit.MILLISECONDS); - } - - @SuppressWarnings("serial") - private class TestException extends Exception { - } + private TestScheduler scheduler; + private Observer observer; + + @Before + @SuppressWarnings("unchecked") + public void before() { + scheduler = new TestScheduler(); + observer = mock(Observer.class); + } + + @Test + public void testThrottlingWithCompleted() { + Observable source = Observable.create(new Observable.OnSubscribeFunc() { + @Override + public Subscription onSubscribe(Observer observer) { + publishNext(observer, 100, "one"); // publish as it's first + publishNext(observer, 300, "two"); // skip as it's last within the first 400 + publishNext(observer, 900, "three"); // publish + publishNext(observer, 905, "four"); // skip + publishCompleted(observer, 1000); // Should be published as soon as the timeout expires. + + return Subscriptions.empty(); + } + }); + + Observable sampled = Observable.create(OperationThrottleFirst.throttleFirst(source, 400, TimeUnit.MILLISECONDS, scheduler)); + sampled.subscribe(observer); + + InOrder inOrder = inOrder(observer); + + scheduler.advanceTimeTo(1000, TimeUnit.MILLISECONDS); + inOrder.verify(observer, times(1)).onNext("one"); + inOrder.verify(observer, times(0)).onNext("two"); + inOrder.verify(observer, times(1)).onNext("three"); + inOrder.verify(observer, times(0)).onNext("four"); + inOrder.verify(observer, times(1)).onCompleted(); + inOrder.verifyNoMoreInteractions(); + } + + @Test + public void testThrottlingWithError() { + Observable source = Observable.create(new Observable.OnSubscribeFunc() { + @Override + public Subscription onSubscribe(Observer observer) { + Exception error = new TestException(); + publishNext(observer, 100, "one"); // Should be published since it is first + publishNext(observer, 200, "two"); // Should be skipped since onError will arrive before the timeout expires + publishError(observer, 300, error); // Should be published as soon as the timeout expires. + + return Subscriptions.empty(); + } + }); + + Observable sampled = Observable.create(OperationThrottleFirst.throttleFirst(source, 400, TimeUnit.MILLISECONDS, scheduler)); + sampled.subscribe(observer); + + InOrder inOrder = inOrder(observer); + + scheduler.advanceTimeTo(400, TimeUnit.MILLISECONDS); + inOrder.verify(observer).onNext("one"); + inOrder.verify(observer).onError(any(TestException.class)); + inOrder.verifyNoMoreInteractions(); + } + + private void publishCompleted(final Observer observer, long delay) { + scheduler.schedule(new Action0() { + @Override + public void call() { + observer.onCompleted(); + } + }, delay, TimeUnit.MILLISECONDS); + } + + private void publishError(final Observer observer, long delay, final Exception error) { + scheduler.schedule(new Action0() { + @Override + public void call() { + observer.onError(error); + } + }, delay, TimeUnit.MILLISECONDS); + } + + private void publishNext(final Observer observer, long delay, final T value) { + scheduler.schedule(new Action0() { + @Override + public void call() { + observer.onNext(value); + } + }, delay, TimeUnit.MILLISECONDS); + } + + @SuppressWarnings("serial") + private class TestException extends Exception { + } } diff --git a/rxjava-core/src/test/java/rx/operators/OperationTimeIntervalTest.java b/rxjava-core/src/test/java/rx/operators/OperationTimeIntervalTest.java index 6ce6504b05..ebbd27eb7a 100644 --- a/rxjava-core/src/test/java/rx/operators/OperationTimeIntervalTest.java +++ b/rxjava-core/src/test/java/rx/operators/OperationTimeIntervalTest.java @@ -1,60 +1,60 @@ package rx.operators; +import static org.mockito.Mockito.*; + +import java.util.concurrent.TimeUnit; + import org.junit.Before; import org.junit.Test; import org.mockito.InOrder; import org.mockito.Mock; import org.mockito.MockitoAnnotations; + import rx.Observable; import rx.Observer; import rx.concurrency.TestScheduler; import rx.subjects.PublishSubject; import rx.util.TimeInterval; -import java.util.concurrent.TimeUnit; - -import static org.mockito.Mockito.inOrder; -import static org.mockito.Mockito.times; - public class OperationTimeIntervalTest { - private static final TimeUnit TIME_UNIT = TimeUnit.MILLISECONDS; - - @Mock - private Observer> observer; - - private TestScheduler testScheduler; - private PublishSubject subject; - private Observable> observable; - - @Before - public void setUp() { - MockitoAnnotations.initMocks(this); - testScheduler = new TestScheduler(); - subject = PublishSubject.create(); - observable = subject.timeInterval(testScheduler); - } - - @Test - public void testTimeInterval() { - InOrder inOrder = inOrder(observer); - observable.subscribe(observer); - - testScheduler.advanceTimeBy(1000, TIME_UNIT); - subject.onNext(1); - testScheduler.advanceTimeBy(2000, TIME_UNIT); - subject.onNext(2); - testScheduler.advanceTimeBy(3000, TIME_UNIT); - subject.onNext(3); - subject.onCompleted(); - - inOrder.verify(observer, times(1)).onNext( - new TimeInterval(1000, 1)); - inOrder.verify(observer, times(1)).onNext( - new TimeInterval(2000, 2)); - inOrder.verify(observer, times(1)).onNext( - new TimeInterval(3000, 3)); - inOrder.verify(observer, times(1)).onCompleted(); - inOrder.verifyNoMoreInteractions(); - } + private static final TimeUnit TIME_UNIT = TimeUnit.MILLISECONDS; + + @Mock + private Observer> observer; + + private TestScheduler testScheduler; + private PublishSubject subject; + private Observable> observable; + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + testScheduler = new TestScheduler(); + subject = PublishSubject.create(); + observable = subject.timeInterval(testScheduler); + } + + @Test + public void testTimeInterval() { + InOrder inOrder = inOrder(observer); + observable.subscribe(observer); + + testScheduler.advanceTimeBy(1000, TIME_UNIT); + subject.onNext(1); + testScheduler.advanceTimeBy(2000, TIME_UNIT); + subject.onNext(2); + testScheduler.advanceTimeBy(3000, TIME_UNIT); + subject.onNext(3); + subject.onCompleted(); + + inOrder.verify(observer, times(1)).onNext( + new TimeInterval(1000, 1)); + inOrder.verify(observer, times(1)).onNext( + new TimeInterval(2000, 2)); + inOrder.verify(observer, times(1)).onNext( + new TimeInterval(3000, 3)); + inOrder.verify(observer, times(1)).onCompleted(); + inOrder.verifyNoMoreInteractions(); + } } diff --git a/rxjava-core/src/test/java/rx/operators/OperationToObservableFutureTest.java b/rxjava-core/src/test/java/rx/operators/OperationToObservableFutureTest.java index f3891128e1..a2f4daa711 100644 --- a/rxjava-core/src/test/java/rx/operators/OperationToObservableFutureTest.java +++ b/rxjava-core/src/test/java/rx/operators/OperationToObservableFutureTest.java @@ -1,47 +1,48 @@ package rx.operators; -import org.junit.Test; -import rx.Observer; -import rx.Subscription; +import static org.mockito.Mockito.*; import java.util.concurrent.Future; -import static org.mockito.Mockito.*; -import static rx.operators.OperationToObservableFuture.ToObservableFuture; +import org.junit.Test; + +import rx.Observer; +import rx.Subscription; +import rx.operators.OperationToObservableFuture.ToObservableFuture; public class OperationToObservableFutureTest { - @Test - public void testSuccess() throws Exception { - Future future = mock(Future.class); - Object value = new Object(); - when(future.get()).thenReturn(value); - ToObservableFuture ob = new ToObservableFuture(future); - Observer o = mock(Observer.class); - - Subscription sub = ob.onSubscribe(o); - sub.unsubscribe(); - - verify(o, times(1)).onNext(value); - verify(o, times(1)).onCompleted(); - verify(o, never()).onError(null); - verify(future, never()).cancel(true); - } - - @Test - public void testFailure() throws Exception { - Future future = mock(Future.class); - RuntimeException e = new RuntimeException(); - when(future.get()).thenThrow(e); - ToObservableFuture ob = new ToObservableFuture(future); - Observer o = mock(Observer.class); - - Subscription sub = ob.onSubscribe(o); - sub.unsubscribe(); - - verify(o, never()).onNext(null); - verify(o, never()).onCompleted(); - verify(o, times(1)).onError(e); - verify(future, never()).cancel(true); - } + @Test + public void testSuccess() throws Exception { + Future future = mock(Future.class); + Object value = new Object(); + when(future.get()).thenReturn(value); + ToObservableFuture ob = new ToObservableFuture(future); + Observer o = mock(Observer.class); + + Subscription sub = ob.onSubscribe(o); + sub.unsubscribe(); + + verify(o, times(1)).onNext(value); + verify(o, times(1)).onCompleted(); + verify(o, never()).onError(null); + verify(future, never()).cancel(true); + } + + @Test + public void testFailure() throws Exception { + Future future = mock(Future.class); + RuntimeException e = new RuntimeException(); + when(future.get()).thenThrow(e); + ToObservableFuture ob = new ToObservableFuture(future); + Observer o = mock(Observer.class); + + Subscription sub = ob.onSubscribe(o); + sub.unsubscribe(); + + verify(o, never()).onNext(null); + verify(o, never()).onCompleted(); + verify(o, times(1)).onError(e); + verify(future, never()).cancel(true); + } } diff --git a/rxjava-core/src/test/java/rx/operators/OperationToObservableIterableTest.java b/rxjava-core/src/test/java/rx/operators/OperationToObservableIterableTest.java index a24cb92694..f99bb27428 100644 --- a/rxjava-core/src/test/java/rx/operators/OperationToObservableIterableTest.java +++ b/rxjava-core/src/test/java/rx/operators/OperationToObservableIterableTest.java @@ -1,32 +1,30 @@ package rx.operators; -import org.junit.Ignore; +import static org.mockito.Matchers.*; +import static org.mockito.Mockito.*; +import static rx.operators.OperationToObservableIterable.*; + +import java.util.Arrays; + import org.junit.Test; import org.mockito.Mockito; + import rx.Observable; import rx.Observer; -import java.util.Arrays; - -import static org.mockito.Matchers.any; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; -import static rx.operators.OperationToObservableIterable.toObservableIterable; - public class OperationToObservableIterableTest { - @Test - public void testIterable() { - Observable observable = Observable.create(toObservableIterable(Arrays. asList("one", "two", "three"))); + @Test + public void testIterable() { + Observable observable = Observable.create(toObservableIterable(Arrays. asList("one", "two", "three"))); - @SuppressWarnings("unchecked") - Observer aObserver = mock(Observer.class); - observable.subscribe(aObserver); - verify(aObserver, times(1)).onNext("one"); - verify(aObserver, times(1)).onNext("two"); - verify(aObserver, times(1)).onNext("three"); - verify(aObserver, Mockito.never()).onError(any(Throwable.class)); - verify(aObserver, times(1)).onCompleted(); - } + @SuppressWarnings("unchecked") + Observer aObserver = mock(Observer.class); + observable.subscribe(aObserver); + verify(aObserver, times(1)).onNext("one"); + verify(aObserver, times(1)).onNext("two"); + verify(aObserver, times(1)).onNext("three"); + verify(aObserver, Mockito.never()).onError(any(Throwable.class)); + verify(aObserver, times(1)).onCompleted(); + } } diff --git a/rxjava-core/src/test/java/rx/operators/OperationToObservableListTest.java b/rxjava-core/src/test/java/rx/operators/OperationToObservableListTest.java index 12e47aa080..58d1456a80 100644 --- a/rxjava-core/src/test/java/rx/operators/OperationToObservableListTest.java +++ b/rxjava-core/src/test/java/rx/operators/OperationToObservableListTest.java @@ -1,53 +1,54 @@ package rx.operators; -import org.junit.Test; -import org.mockito.Mockito; -import rx.Observable; -import rx.Observer; +import static org.mockito.Matchers.*; +import static org.mockito.Mockito.*; +import static rx.operators.OperationToObservableList.*; import java.util.Arrays; import java.util.List; -import static org.mockito.Matchers.any; -import static org.mockito.Mockito.*; -import static rx.operators.OperationToObservableList.toObservableList; +import org.junit.Test; +import org.mockito.Mockito; + +import rx.Observable; +import rx.Observer; public class OperationToObservableListTest { - @Test - public void testList() { - Observable w = Observable.from("one", "two", "three"); - Observable> observable = Observable.create(toObservableList(w)); - - @SuppressWarnings("unchecked") - Observer> aObserver = mock(Observer.class); - observable.subscribe(aObserver); - verify(aObserver, times(1)).onNext(Arrays.asList("one", "two", "three")); - verify(aObserver, Mockito.never()).onError(any(Throwable.class)); - verify(aObserver, times(1)).onCompleted(); - } - - @Test - public void testListMultipleObservers() { - Observable w = Observable.from("one", "two", "three"); - Observable> observable = Observable.create(toObservableList(w)); - - @SuppressWarnings("unchecked") - Observer> o1 = mock(Observer.class); - observable.subscribe(o1); - - @SuppressWarnings("unchecked") - Observer> o2 = mock(Observer.class); - observable.subscribe(o2); - - List expected = Arrays.asList("one", "two", "three"); - - verify(o1, times(1)).onNext(expected); - verify(o1, Mockito.never()).onError(any(Throwable.class)); - verify(o1, times(1)).onCompleted(); - - verify(o2, times(1)).onNext(expected); - verify(o2, Mockito.never()).onError(any(Throwable.class)); - verify(o2, times(1)).onCompleted(); - } + @Test + public void testList() { + Observable w = Observable.from("one", "two", "three"); + Observable> observable = Observable.create(toObservableList(w)); + + @SuppressWarnings("unchecked") + Observer> aObserver = mock(Observer.class); + observable.subscribe(aObserver); + verify(aObserver, times(1)).onNext(Arrays.asList("one", "two", "three")); + verify(aObserver, Mockito.never()).onError(any(Throwable.class)); + verify(aObserver, times(1)).onCompleted(); + } + + @Test + public void testListMultipleObservers() { + Observable w = Observable.from("one", "two", "three"); + Observable> observable = Observable.create(toObservableList(w)); + + @SuppressWarnings("unchecked") + Observer> o1 = mock(Observer.class); + observable.subscribe(o1); + + @SuppressWarnings("unchecked") + Observer> o2 = mock(Observer.class); + observable.subscribe(o2); + + List expected = Arrays.asList("one", "two", "three"); + + verify(o1, times(1)).onNext(expected); + verify(o1, Mockito.never()).onError(any(Throwable.class)); + verify(o1, times(1)).onCompleted(); + + verify(o2, times(1)).onNext(expected); + verify(o2, Mockito.never()).onError(any(Throwable.class)); + verify(o2, times(1)).onCompleted(); + } } diff --git a/rxjava-core/src/test/java/rx/operators/OperationToObservableSortedListTest.java b/rxjava-core/src/test/java/rx/operators/OperationToObservableSortedListTest.java index 11b6c9ff6a..9dd78943a5 100644 --- a/rxjava-core/src/test/java/rx/operators/OperationToObservableSortedListTest.java +++ b/rxjava-core/src/test/java/rx/operators/OperationToObservableSortedListTest.java @@ -1,50 +1,51 @@ package rx.operators; +import static org.mockito.Matchers.*; +import static org.mockito.Mockito.*; +import static rx.operators.OperationToObservableSortedList.*; + +import java.util.Arrays; +import java.util.List; + import org.junit.Test; import org.mockito.Mockito; + import rx.Observable; import rx.Observer; import rx.util.functions.Func2; -import java.util.Arrays; -import java.util.List; - -import static org.mockito.Matchers.any; -import static org.mockito.Mockito.*; -import static rx.operators.OperationToObservableSortedList.toSortedList; - public class OperationToObservableSortedListTest { - @Test - public void testSortedList() { - Observable w = Observable.from(1, 3, 2, 5, 4); - Observable> observable = Observable.create(toSortedList(w)); - - @SuppressWarnings("unchecked") - Observer> aObserver = mock(Observer.class); - observable.subscribe(aObserver); - verify(aObserver, times(1)).onNext(Arrays.asList(1, 2, 3, 4, 5)); - verify(aObserver, Mockito.never()).onError(any(Throwable.class)); - verify(aObserver, times(1)).onCompleted(); - } - - @Test - public void testSortedListWithCustomFunction() { - Observable w = Observable.from(1, 3, 2, 5, 4); - Observable> observable = Observable.create(toSortedList(w, new Func2() { - - @Override - public Integer call(Integer t1, Integer t2) { - return t2 - t1; - } - - })); - - @SuppressWarnings("unchecked") - Observer> aObserver = mock(Observer.class); - observable.subscribe(aObserver); - verify(aObserver, times(1)).onNext(Arrays.asList(5, 4, 3, 2, 1)); - verify(aObserver, Mockito.never()).onError(any(Throwable.class)); - verify(aObserver, times(1)).onCompleted(); - } + @Test + public void testSortedList() { + Observable w = Observable.from(1, 3, 2, 5, 4); + Observable> observable = Observable.create(toSortedList(w)); + + @SuppressWarnings("unchecked") + Observer> aObserver = mock(Observer.class); + observable.subscribe(aObserver); + verify(aObserver, times(1)).onNext(Arrays.asList(1, 2, 3, 4, 5)); + verify(aObserver, Mockito.never()).onError(any(Throwable.class)); + verify(aObserver, times(1)).onCompleted(); + } + + @Test + public void testSortedListWithCustomFunction() { + Observable w = Observable.from(1, 3, 2, 5, 4); + Observable> observable = Observable.create(toSortedList(w, new Func2() { + + @Override + public Integer call(Integer t1, Integer t2) { + return t2 - t1; + } + + })); + + @SuppressWarnings("unchecked") + Observer> aObserver = mock(Observer.class); + observable.subscribe(aObserver); + verify(aObserver, times(1)).onNext(Arrays.asList(5, 4, 3, 2, 1)); + verify(aObserver, Mockito.never()).onError(any(Throwable.class)); + verify(aObserver, times(1)).onCompleted(); + } } diff --git a/rxjava-core/src/test/java/rx/operators/OperationWindowTest.java b/rxjava-core/src/test/java/rx/operators/OperationWindowTest.java index 8a552f534f..71a749a0ae 100644 --- a/rxjava-core/src/test/java/rx/operators/OperationWindowTest.java +++ b/rxjava-core/src/test/java/rx/operators/OperationWindowTest.java @@ -1,7 +1,15 @@ package rx.operators; +import static org.junit.Assert.*; +import static rx.operators.OperationWindow.*; + +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.TimeUnit; + import org.junit.Before; import org.junit.Test; + import rx.Observable; import rx.Observer; import rx.Subscription; @@ -16,300 +24,292 @@ import rx.util.functions.Func0; import rx.util.functions.Func1; -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.TimeUnit; +public class OperationWindowTest { -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.fail; -import static rx.operators.OperationWindow.window; + private TestScheduler scheduler; -public class OperationWindowTest { + @Before + public void before() { + scheduler = new TestScheduler(); + } + + private static List> toLists(Observable> observable) { + final List list = new ArrayList(); + final List> lists = new ArrayList>(); + + observable.subscribe(new Action1>() { + @Override + public void call(Observable tObservable) { + tObservable.subscribe(new Action1() { + @Override + public void call(T t) { + list.add(t); + } + }); + lists.add(new ArrayList(list)); + list.clear(); + } + }); + return lists; + } + + @Test + public void testNonOverlappingWindows() { + Observable subject = Observable.from("one", "two", "three", "four", "five"); + Observable> windowed = Observable.create(window(subject, 3)); + + List> windows = toLists(windowed); + + assertEquals(2, windows.size()); + assertEquals(list("one", "two", "three"), windows.get(0)); + assertEquals(list("four", "five"), windows.get(1)); + } + + @Test + public void testSkipAndCountGaplessEindows() { + Observable subject = Observable.from("one", "two", "three", "four", "five"); + Observable> windowed = Observable.create(window(subject, 3, 3)); + + List> windows = toLists(windowed); + + assertEquals(2, windows.size()); + assertEquals(list("one", "two", "three"), windows.get(0)); + assertEquals(list("four", "five"), windows.get(1)); + } + + @Test + public void testOverlappingWindows() { + Observable subject = Observable.from("zero", "one", "two", "three", "four", "five"); + Observable> windowed = Observable.create(window(subject, 3, 1)); + + List> windows = toLists(windowed); + + assertEquals(6, windows.size()); + assertEquals(list("zero", "one", "two"), windows.get(0)); + assertEquals(list("one", "two", "three"), windows.get(1)); + assertEquals(list("two", "three", "four"), windows.get(2)); + assertEquals(list("three", "four", "five"), windows.get(3)); + assertEquals(list("four", "five"), windows.get(4)); + assertEquals(list("five"), windows.get(5)); + } + + @Test + public void testSkipAndCountWindowsWithGaps() { + Observable subject = Observable.from("one", "two", "three", "four", "five"); + Observable> windowed = Observable.create(window(subject, 2, 3)); - private TestScheduler scheduler; - - @Before - public void before() { - scheduler = new TestScheduler(); - } - - private static List> toLists(Observable> observable) { - final List list = new ArrayList(); - final List> lists = new ArrayList>(); - - observable.subscribe(new Action1>() { - @Override - public void call(Observable tObservable) { - tObservable.subscribe(new Action1() { - @Override - public void call(T t) { - list.add(t); - } + List> windows = toLists(windowed); + + assertEquals(2, windows.size()); + assertEquals(list("one", "two"), windows.get(0)); + assertEquals(list("four", "five"), windows.get(1)); + } + + @Test + public void testTimedAndCount() { + final List list = new ArrayList(); + final List> lists = new ArrayList>(); + + Observable source = Observable.create(new Observable.OnSubscribeFunc() { + @Override + public Subscription onSubscribe(Observer observer) { + push(observer, "one", 10); + push(observer, "two", 90); + push(observer, "three", 110); + push(observer, "four", 190); + push(observer, "five", 210); + complete(observer, 250); + return Subscriptions.empty(); + } + }); + + Observable> windowed = Observable.create(window(source, 100, TimeUnit.MILLISECONDS, 2, scheduler)); + windowed.subscribe(observeWindow(list, lists)); + + scheduler.advanceTimeTo(100, TimeUnit.MILLISECONDS); + assertEquals(1, lists.size()); + assertEquals(lists.get(0), list("one", "two")); + + scheduler.advanceTimeTo(200, TimeUnit.MILLISECONDS); + assertEquals(2, lists.size()); + assertEquals(lists.get(1), list("three", "four")); + + scheduler.advanceTimeTo(300, TimeUnit.MILLISECONDS); + assertEquals(3, lists.size()); + assertEquals(lists.get(2), list("five")); + } + + @Test + public void testTimed() { + final List list = new ArrayList(); + final List> lists = new ArrayList>(); + + Observable source = Observable.create(new Observable.OnSubscribeFunc() { + @Override + public Subscription onSubscribe(Observer observer) { + push(observer, "one", 98); + push(observer, "two", 99); + push(observer, "three", 100); + push(observer, "four", 101); + push(observer, "five", 102); + complete(observer, 150); + return Subscriptions.empty(); + } }); - lists.add(new ArrayList(list)); - list.clear(); - } - }); - return lists; - } - - @Test - public void testNonOverlappingWindows() { - Observable subject = Observable.from("one", "two", "three", "four", "five"); - Observable> windowed = Observable.create(window(subject, 3)); - - List> windows = toLists(windowed); - - assertEquals(2, windows.size()); - assertEquals(list("one", "two", "three"), windows.get(0)); - assertEquals(list("four", "five"), windows.get(1)); - } - - @Test - public void testSkipAndCountGaplessEindows() { - Observable subject = Observable.from("one", "two", "three", "four", "five"); - Observable> windowed = Observable.create(window(subject, 3, 3)); - - List> windows = toLists(windowed); - - assertEquals(2, windows.size()); - assertEquals(list("one", "two", "three"), windows.get(0)); - assertEquals(list("four", "five"), windows.get(1)); - } - - @Test - public void testOverlappingWindows() { - Observable subject = Observable.from("zero", "one", "two", "three", "four", "five"); - Observable> windowed = Observable.create(window(subject, 3, 1)); - - List> windows = toLists(windowed); - - assertEquals(6, windows.size()); - assertEquals(list("zero", "one", "two"), windows.get(0)); - assertEquals(list("one", "two", "three"), windows.get(1)); - assertEquals(list("two", "three", "four"), windows.get(2)); - assertEquals(list("three", "four", "five"), windows.get(3)); - assertEquals(list("four", "five"), windows.get(4)); - assertEquals(list("five"), windows.get(5)); - } - - @Test - public void testSkipAndCountWindowsWithGaps() { - Observable subject = Observable.from("one", "two", "three", "four", "five"); - Observable> windowed = Observable.create(window(subject, 2, 3)); - - List> windows = toLists(windowed); - - assertEquals(2, windows.size()); - assertEquals(list("one", "two"), windows.get(0)); - assertEquals(list("four", "five"), windows.get(1)); - } - - @Test - public void testTimedAndCount() { - final List list = new ArrayList(); - final List> lists = new ArrayList>(); - - Observable source = Observable.create(new Observable.OnSubscribeFunc() { - @Override - public Subscription onSubscribe(Observer observer) { - push(observer, "one", 10); - push(observer, "two", 90); - push(observer, "three", 110); - push(observer, "four", 190); - push(observer, "five", 210); - complete(observer, 250); - return Subscriptions.empty(); - } - }); - - Observable> windowed = Observable.create(window(source, 100, TimeUnit.MILLISECONDS, 2, scheduler)); - windowed.subscribe(observeWindow(list, lists)); - - scheduler.advanceTimeTo(100, TimeUnit.MILLISECONDS); - assertEquals(1, lists.size()); - assertEquals(lists.get(0), list("one", "two")); - - scheduler.advanceTimeTo(200, TimeUnit.MILLISECONDS); - assertEquals(2, lists.size()); - assertEquals(lists.get(1), list("three", "four")); - - scheduler.advanceTimeTo(300, TimeUnit.MILLISECONDS); - assertEquals(3, lists.size()); - assertEquals(lists.get(2), list("five")); - } - - @Test - public void testTimed() { - final List list = new ArrayList(); - final List> lists = new ArrayList>(); - - Observable source = Observable.create(new Observable.OnSubscribeFunc() { - @Override - public Subscription onSubscribe(Observer observer) { - push(observer, "one", 98); - push(observer, "two", 99); - push(observer, "three", 100); - push(observer, "four", 101); - push(observer, "five", 102); - complete(observer, 150); - return Subscriptions.empty(); - } - }); - - Observable> windowed = Observable.create(window(source, 100, TimeUnit.MILLISECONDS, scheduler)); - windowed.subscribe(observeWindow(list, lists)); - - scheduler.advanceTimeTo(101, TimeUnit.MILLISECONDS); - assertEquals(1, lists.size()); - assertEquals(lists.get(0), list("one", "two", "three")); - - scheduler.advanceTimeTo(201, TimeUnit.MILLISECONDS); - assertEquals(2, lists.size()); - assertEquals(lists.get(1), list("four", "five")); - } - - @Test - public void testObservableBasedOpenerAndCloser() { - final List list = new ArrayList(); - final List> lists = new ArrayList>(); - - Observable source = Observable.create(new Observable.OnSubscribeFunc() { - @Override - public Subscription onSubscribe(Observer observer) { - push(observer, "one", 10); - push(observer, "two", 60); - push(observer, "three", 110); - push(observer, "four", 160); - push(observer, "five", 210); - complete(observer, 500); - return Subscriptions.empty(); - } - }); - - Observable openings = Observable.create(new Observable.OnSubscribeFunc() { - @Override - public Subscription onSubscribe(Observer observer) { - push(observer, Openings.create(), 50); - push(observer, Openings.create(), 200); - complete(observer, 250); - return Subscriptions.empty(); - } - }); - - Func1> closer = new Func1>() { - @Override - public Observable call(Opening opening) { - return Observable.create(new Observable.OnSubscribeFunc() { - @Override - public Subscription onSubscribe(Observer observer) { - push(observer, Closings.create(), 100); - complete(observer, 101); - return Subscriptions.empty(); - } + + Observable> windowed = Observable.create(window(source, 100, TimeUnit.MILLISECONDS, scheduler)); + windowed.subscribe(observeWindow(list, lists)); + + scheduler.advanceTimeTo(101, TimeUnit.MILLISECONDS); + assertEquals(1, lists.size()); + assertEquals(lists.get(0), list("one", "two", "three")); + + scheduler.advanceTimeTo(201, TimeUnit.MILLISECONDS); + assertEquals(2, lists.size()); + assertEquals(lists.get(1), list("four", "five")); + } + + @Test + public void testObservableBasedOpenerAndCloser() { + final List list = new ArrayList(); + final List> lists = new ArrayList>(); + + Observable source = Observable.create(new Observable.OnSubscribeFunc() { + @Override + public Subscription onSubscribe(Observer observer) { + push(observer, "one", 10); + push(observer, "two", 60); + push(observer, "three", 110); + push(observer, "four", 160); + push(observer, "five", 210); + complete(observer, 500); + return Subscriptions.empty(); + } }); - } - }; - - Observable> windowed = Observable.create(window(source, openings, closer)); - windowed.subscribe(observeWindow(list, lists)); - - scheduler.advanceTimeTo(500, TimeUnit.MILLISECONDS); - assertEquals(2, lists.size()); - assertEquals(lists.get(0), list("two", "three")); - assertEquals(lists.get(1), list("five")); - } - - @Test - public void testObservableBasedCloser() { - final List list = new ArrayList(); - final List> lists = new ArrayList>(); - - Observable source = Observable.create(new Observable.OnSubscribeFunc() { - @Override - public Subscription onSubscribe(Observer observer) { - push(observer, "one", 10); - push(observer, "two", 60); - push(observer, "three", 110); - push(observer, "four", 160); - push(observer, "five", 210); - complete(observer, 250); - return Subscriptions.empty(); - } - }); - - Func0> closer = new Func0>() { - @Override - public Observable call() { - return Observable.create(new Observable.OnSubscribeFunc() { - @Override - public Subscription onSubscribe(Observer observer) { - push(observer, Closings.create(), 100); - complete(observer, 101); - return Subscriptions.empty(); - } + + Observable openings = Observable.create(new Observable.OnSubscribeFunc() { + @Override + public Subscription onSubscribe(Observer observer) { + push(observer, Openings.create(), 50); + push(observer, Openings.create(), 200); + complete(observer, 250); + return Subscriptions.empty(); + } }); - } - }; - - Observable> windowed = Observable.create(window(source, closer)); - windowed.subscribe(observeWindow(list, lists)); - - scheduler.advanceTimeTo(500, TimeUnit.MILLISECONDS); - assertEquals(3, lists.size()); - assertEquals(lists.get(0), list("one", "two")); - assertEquals(lists.get(1), list("three", "four")); - assertEquals(lists.get(2), list("five")); - } - - private List list(String... args) { - List list = new ArrayList(); - for (String arg : args) { - list.add(arg); + + Func1> closer = new Func1>() { + @Override + public Observable call(Opening opening) { + return Observable.create(new Observable.OnSubscribeFunc() { + @Override + public Subscription onSubscribe(Observer observer) { + push(observer, Closings.create(), 100); + complete(observer, 101); + return Subscriptions.empty(); + } + }); + } + }; + + Observable> windowed = Observable.create(window(source, openings, closer)); + windowed.subscribe(observeWindow(list, lists)); + + scheduler.advanceTimeTo(500, TimeUnit.MILLISECONDS); + assertEquals(2, lists.size()); + assertEquals(lists.get(0), list("two", "three")); + assertEquals(lists.get(1), list("five")); } - return list; - } - - private void push(final Observer observer, final T value, int delay) { - scheduler.schedule(new Action0() { - @Override - public void call() { - observer.onNext(value); - } - }, delay, TimeUnit.MILLISECONDS); - } - - private void complete(final Observer observer, int delay) { - scheduler.schedule(new Action0() { - @Override - public void call() { - observer.onCompleted(); - } - }, delay, TimeUnit.MILLISECONDS); - } - - private Action1> observeWindow(final List list, final List> lists) { - return new Action1>() { - @Override - public void call(Observable stringObservable) { - stringObservable.subscribe(new Observer() { - @Override - public void onCompleted() { - lists.add(new ArrayList(list)); - list.clear(); - } - - @Override - public void onError(Throwable e) { - fail(e.getMessage()); - } - - @Override - public void onNext(String args) { - list.add(args); - } + + @Test + public void testObservableBasedCloser() { + final List list = new ArrayList(); + final List> lists = new ArrayList>(); + + Observable source = Observable.create(new Observable.OnSubscribeFunc() { + @Override + public Subscription onSubscribe(Observer observer) { + push(observer, "one", 10); + push(observer, "two", 60); + push(observer, "three", 110); + push(observer, "four", 160); + push(observer, "five", 210); + complete(observer, 250); + return Subscriptions.empty(); + } }); - } - }; - } + + Func0> closer = new Func0>() { + @Override + public Observable call() { + return Observable.create(new Observable.OnSubscribeFunc() { + @Override + public Subscription onSubscribe(Observer observer) { + push(observer, Closings.create(), 100); + complete(observer, 101); + return Subscriptions.empty(); + } + }); + } + }; + + Observable> windowed = Observable.create(window(source, closer)); + windowed.subscribe(observeWindow(list, lists)); + + scheduler.advanceTimeTo(500, TimeUnit.MILLISECONDS); + assertEquals(3, lists.size()); + assertEquals(lists.get(0), list("one", "two")); + assertEquals(lists.get(1), list("three", "four")); + assertEquals(lists.get(2), list("five")); + } + + private List list(String... args) { + List list = new ArrayList(); + for (String arg : args) { + list.add(arg); + } + return list; + } + + private void push(final Observer observer, final T value, int delay) { + scheduler.schedule(new Action0() { + @Override + public void call() { + observer.onNext(value); + } + }, delay, TimeUnit.MILLISECONDS); + } + + private void complete(final Observer observer, int delay) { + scheduler.schedule(new Action0() { + @Override + public void call() { + observer.onCompleted(); + } + }, delay, TimeUnit.MILLISECONDS); + } + + private Action1> observeWindow(final List list, final List> lists) { + return new Action1>() { + @Override + public void call(Observable stringObservable) { + stringObservable.subscribe(new Observer() { + @Override + public void onCompleted() { + lists.add(new ArrayList(list)); + list.clear(); + } + + @Override + public void onError(Throwable e) { + fail(e.getMessage()); + } + + @Override + public void onNext(String args) { + list.add(args); + } + }); + } + }; + } } diff --git a/rxjava-core/src/test/java/rx/operators/OperationZipTest.java b/rxjava-core/src/test/java/rx/operators/OperationZipTest.java index 2a73ac3eab..bab2d7d2fe 100644 --- a/rxjava-core/src/test/java/rx/operators/OperationZipTest.java +++ b/rxjava-core/src/test/java/rx/operators/OperationZipTest.java @@ -1,584 +1,583 @@ package rx.operators; -import org.junit.Ignore; +import static org.mockito.Matchers.*; +import static org.mockito.Mockito.*; +import static rx.operators.OperationZip.*; + +import java.util.Arrays; +import java.util.Collection; + import org.junit.Test; import org.mockito.InOrder; + import rx.Observable; import rx.Observer; import rx.Subscription; +import rx.operators.OperationZip.Aggregator; +import rx.operators.OperationZip.ZipObserver; import rx.subscriptions.Subscriptions; import rx.util.functions.Func2; import rx.util.functions.Func3; import rx.util.functions.FuncN; import rx.util.functions.Functions; -import java.util.Arrays; -import java.util.Collection; +public class OperationZipTest { -import static org.mockito.Matchers.any; -import static org.mockito.Matchers.anyString; -import static org.mockito.Mockito.*; -import static rx.operators.OperationZip.Aggregator; -import static rx.operators.OperationZip.ZipObserver; -import static rx.operators.OperationZip.zip; + @SuppressWarnings("unchecked") + @Test + public void testCollectionSizeDifferentThanFunction() { + FuncN zipr = Functions.fromFunc(getConcatStringIntegerIntArrayZipr()); + //Func3 + + /* define a Observer to receive aggregated events */ + Observer aObserver = mock(Observer.class); + + @SuppressWarnings("rawtypes") + Collection ws = java.util.Collections.singleton(Observable.from("one", "two")); + Observable w = Observable.create(zip(ws, zipr)); + w.subscribe(aObserver); + + verify(aObserver, times(1)).onError(any(Throwable.class)); + verify(aObserver, never()).onCompleted(); + verify(aObserver, never()).onNext(any(String.class)); + } -public class OperationZipTest { + @SuppressWarnings("unchecked") + /* mock calls don't do generics */ + @Test + public void testZippingDifferentLengthObservableSequences1() { + Observer w = mock(Observer.class); + + TestObservable w1 = new TestObservable(); + TestObservable w2 = new TestObservable(); + TestObservable w3 = new TestObservable(); + + Observable zipW = Observable.create(zip(Observable.create(w1), Observable.create(w2), Observable.create(w3), getConcat3StringsZipr())); + zipW.subscribe(w); + + /* simulate sending data */ + // once for w1 + w1.observer.onNext("1a"); + w1.observer.onCompleted(); + // twice for w2 + w2.observer.onNext("2a"); + w2.observer.onNext("2b"); + w2.observer.onCompleted(); + // 4 times for w3 + w3.observer.onNext("3a"); + w3.observer.onNext("3b"); + w3.observer.onNext("3c"); + w3.observer.onNext("3d"); + w3.observer.onCompleted(); + + /* we should have been called 1 time on the Observer */ + InOrder inOrder = inOrder(w); + inOrder.verify(w).onNext("1a2a3a"); + + inOrder.verify(w, times(1)).onCompleted(); + } + + @Test + public void testZippingDifferentLengthObservableSequences2() { + @SuppressWarnings("unchecked") + Observer w = mock(Observer.class); + + TestObservable w1 = new TestObservable(); + TestObservable w2 = new TestObservable(); + TestObservable w3 = new TestObservable(); + + Observable zipW = Observable.create(zip(Observable.create(w1), Observable.create(w2), Observable.create(w3), getConcat3StringsZipr())); + zipW.subscribe(w); + + /* simulate sending data */ + // 4 times for w1 + w1.observer.onNext("1a"); + w1.observer.onNext("1b"); + w1.observer.onNext("1c"); + w1.observer.onNext("1d"); + w1.observer.onCompleted(); + // twice for w2 + w2.observer.onNext("2a"); + w2.observer.onNext("2b"); + w2.observer.onCompleted(); + // 1 times for w3 + w3.observer.onNext("3a"); + w3.observer.onCompleted(); + + /* we should have been called 1 time on the Observer */ + InOrder inOrder = inOrder(w); + inOrder.verify(w).onNext("1a2a3a"); + + inOrder.verify(w, times(1)).onCompleted(); + + } + + /** + * Testing internal private logic due to the complexity so I want to use TDD to test as a I build it rather than relying purely on the overall functionality expected by the public methods. + */ + @SuppressWarnings("unchecked") + /* mock calls don't do generics */ + @Test + public void testAggregatorSimple() { + FuncN zipr = getConcatZipr(); + /* create the aggregator which will execute the zip function when all Observables provide values */ + Aggregator a = new Aggregator(zipr); + + /* define a Observer to receive aggregated events */ + Observer aObserver = mock(Observer.class); + a.onSubscribe(aObserver); + + /* mock the Observable Observers that are 'pushing' data for us */ + ZipObserver r1 = mock(ZipObserver.class); + ZipObserver r2 = mock(ZipObserver.class); + + /* pretend we're starting up */ + a.addObserver(r1); + a.addObserver(r2); + + /* simulate the Observables pushing data into the aggregator */ + a.next(r1, "hello"); + a.next(r2, "world"); + + InOrder inOrder = inOrder(aObserver); + + verify(aObserver, never()).onError(any(Throwable.class)); + verify(aObserver, never()).onCompleted(); + inOrder.verify(aObserver, times(1)).onNext("helloworld"); + + a.next(r1, "hello "); + a.next(r2, "again"); + + verify(aObserver, never()).onError(any(Throwable.class)); + verify(aObserver, never()).onCompleted(); + inOrder.verify(aObserver, times(1)).onNext("hello again"); + + a.complete(r1); + a.complete(r2); + + inOrder.verify(aObserver, never()).onNext(anyString()); + verify(aObserver, times(1)).onCompleted(); + } + + @SuppressWarnings("unchecked") + /* mock calls don't do generics */ + @Test + public void testAggregatorDifferentSizedResultsWithOnComplete() { + FuncN zipr = getConcatZipr(); + /* create the aggregator which will execute the zip function when all Observables provide values */ + Aggregator a = new Aggregator(zipr); + + /* define a Observer to receive aggregated events */ + Observer aObserver = mock(Observer.class); + a.onSubscribe(aObserver); + + /* mock the Observable Observers that are 'pushing' data for us */ + ZipObserver r1 = mock(ZipObserver.class); + ZipObserver r2 = mock(ZipObserver.class); + + /* pretend we're starting up */ + a.addObserver(r1); + a.addObserver(r2); + + /* simulate the Observables pushing data into the aggregator */ + a.next(r1, "hello"); + a.next(r2, "world"); + a.complete(r2); + + InOrder inOrder = inOrder(aObserver); + + inOrder.verify(aObserver, never()).onError(any(Throwable.class)); + inOrder.verify(aObserver, never()).onCompleted(); + inOrder.verify(aObserver, times(1)).onNext("helloworld"); + + a.next(r1, "hi"); + a.complete(r1); + + inOrder.verify(aObserver, never()).onError(any(Throwable.class)); + inOrder.verify(aObserver, times(1)).onCompleted(); + inOrder.verify(aObserver, never()).onNext(anyString()); + } + + @SuppressWarnings("unchecked") + /* mock calls don't do generics */ + @Test + public void testAggregateMultipleTypes() { + FuncN zipr = getConcatZipr(); + /* create the aggregator which will execute the zip function when all Observables provide values */ + Aggregator a = new Aggregator(zipr); + + /* define a Observer to receive aggregated events */ + Observer aObserver = mock(Observer.class); + a.onSubscribe(aObserver); + + /* mock the Observable Observers that are 'pushing' data for us */ + ZipObserver r1 = mock(ZipObserver.class); + ZipObserver r2 = mock(ZipObserver.class); + + /* pretend we're starting up */ + a.addObserver(r1); + a.addObserver(r2); + + /* simulate the Observables pushing data into the aggregator */ + a.next(r1, "hello"); + a.next(r2, "world"); + a.complete(r2); + + InOrder inOrder = inOrder(aObserver); + + inOrder.verify(aObserver, never()).onError(any(Throwable.class)); + inOrder.verify(aObserver, never()).onCompleted(); + inOrder.verify(aObserver, times(1)).onNext("helloworld"); + + a.next(r1, "hi"); + a.complete(r1); + + inOrder.verify(aObserver, never()).onError(any(Throwable.class)); + inOrder.verify(aObserver, times(1)).onCompleted(); + inOrder.verify(aObserver, never()).onNext(anyString()); + } + + @SuppressWarnings("unchecked") + /* mock calls don't do generics */ + @Test + public void testAggregate3Types() { + FuncN zipr = getConcatZipr(); + /* create the aggregator which will execute the zip function when all Observables provide values */ + Aggregator a = new Aggregator(zipr); + + /* define a Observer to receive aggregated events */ + Observer aObserver = mock(Observer.class); + a.onSubscribe(aObserver); + + /* mock the Observable Observers that are 'pushing' data for us */ + ZipObserver r1 = mock(ZipObserver.class); + ZipObserver r2 = mock(ZipObserver.class); + ZipObserver r3 = mock(ZipObserver.class); + + /* pretend we're starting up */ + a.addObserver(r1); + a.addObserver(r2); + a.addObserver(r3); + + /* simulate the Observables pushing data into the aggregator */ + a.next(r1, "hello"); + a.next(r2, 2); + a.next(r3, new int[] { 5, 6, 7 }); + + verify(aObserver, never()).onError(any(Throwable.class)); + verify(aObserver, never()).onCompleted(); + verify(aObserver, times(1)).onNext("hello2[5, 6, 7]"); + } + + @SuppressWarnings("unchecked") + /* mock calls don't do generics */ + @Test + public void testAggregatorsWithDifferentSizesAndTiming() { + FuncN zipr = getConcatZipr(); + /* create the aggregator which will execute the zip function when all Observables provide values */ + Aggregator a = new Aggregator(zipr); + + /* define a Observer to receive aggregated events */ + Observer aObserver = mock(Observer.class); + a.onSubscribe(aObserver); + + /* mock the Observable Observers that are 'pushing' data for us */ + ZipObserver r1 = mock(ZipObserver.class); + ZipObserver r2 = mock(ZipObserver.class); + + /* pretend we're starting up */ + a.addObserver(r1); + a.addObserver(r2); + + /* simulate the Observables pushing data into the aggregator */ + a.next(r1, "one"); + a.next(r1, "two"); + a.next(r1, "three"); + a.next(r2, "A"); + + verify(aObserver, never()).onError(any(Throwable.class)); + verify(aObserver, never()).onCompleted(); + verify(aObserver, times(1)).onNext("oneA"); + + a.next(r1, "four"); + a.complete(r1); + a.next(r2, "B"); + verify(aObserver, times(1)).onNext("twoB"); + a.next(r2, "C"); + verify(aObserver, times(1)).onNext("threeC"); + a.next(r2, "D"); + verify(aObserver, times(1)).onNext("fourD"); + a.next(r2, "E"); + verify(aObserver, never()).onNext("E"); + a.complete(r2); + + verify(aObserver, never()).onError(any(Throwable.class)); + verify(aObserver, times(1)).onCompleted(); + } + + @SuppressWarnings("unchecked") + /* mock calls don't do generics */ + @Test + public void testAggregatorError() { + FuncN zipr = getConcatZipr(); + /* create the aggregator which will execute the zip function when all Observables provide values */ + Aggregator a = new Aggregator(zipr); + + /* define a Observer to receive aggregated events */ + Observer aObserver = mock(Observer.class); + a.onSubscribe(aObserver); + + /* mock the Observable Observers that are 'pushing' data for us */ + ZipObserver r1 = mock(ZipObserver.class); + ZipObserver r2 = mock(ZipObserver.class); + + /* pretend we're starting up */ + a.addObserver(r1); + a.addObserver(r2); + + /* simulate the Observables pushing data into the aggregator */ + a.next(r1, "hello"); + a.next(r2, "world"); + + verify(aObserver, never()).onError(any(Throwable.class)); + verify(aObserver, never()).onCompleted(); + verify(aObserver, times(1)).onNext("helloworld"); + + a.error(r1, new RuntimeException("")); + a.next(r1, "hello"); + a.next(r2, "again"); + + verify(aObserver, times(1)).onError(any(Throwable.class)); + verify(aObserver, never()).onCompleted(); + // we don't want to be called again after an error + verify(aObserver, times(0)).onNext("helloagain"); + } + + @SuppressWarnings("unchecked") + /* mock calls don't do generics */ + @Test + public void testAggregatorUnsubscribe() { + FuncN zipr = getConcatZipr(); + /* create the aggregator which will execute the zip function when all Observables provide values */ + Aggregator a = new Aggregator(zipr); + + /* define a Observer to receive aggregated events */ + Observer aObserver = mock(Observer.class); + Subscription subscription = a.onSubscribe(aObserver); + + /* mock the Observable Observers that are 'pushing' data for us */ + ZipObserver r1 = mock(ZipObserver.class); + ZipObserver r2 = mock(ZipObserver.class); + + /* pretend we're starting up */ + a.addObserver(r1); + a.addObserver(r2); + + /* simulate the Observables pushing data into the aggregator */ + a.next(r1, "hello"); + a.next(r2, "world"); + + verify(aObserver, never()).onError(any(Throwable.class)); + verify(aObserver, never()).onCompleted(); + verify(aObserver, times(1)).onNext("helloworld"); + + subscription.unsubscribe(); + a.next(r1, "hello"); + a.next(r2, "again"); + + verify(aObserver, times(0)).onError(any(Throwable.class)); + verify(aObserver, never()).onCompleted(); + // we don't want to be called again after an error + verify(aObserver, times(0)).onNext("helloagain"); + } - @SuppressWarnings("unchecked") - @Test - public void testCollectionSizeDifferentThanFunction() { - FuncN zipr = Functions.fromFunc(getConcatStringIntegerIntArrayZipr()); - //Func3 - - /* define a Observer to receive aggregated events */ - Observer aObserver = mock(Observer.class); - - @SuppressWarnings("rawtypes") - Collection ws = java.util.Collections.singleton(Observable.from("one", "two")); - Observable w = Observable.create(zip(ws, zipr)); - w.subscribe(aObserver); - - verify(aObserver, times(1)).onError(any(Throwable.class)); - verify(aObserver, never()).onCompleted(); - verify(aObserver, never()).onNext(any(String.class)); - } - - @SuppressWarnings("unchecked") - /* mock calls don't do generics */ - @Test - public void testZippingDifferentLengthObservableSequences1() { - Observer w = mock(Observer.class); - - TestObservable w1 = new TestObservable(); - TestObservable w2 = new TestObservable(); - TestObservable w3 = new TestObservable(); - - Observable zipW = Observable.create(zip(Observable.create(w1), Observable.create(w2), Observable.create(w3), getConcat3StringsZipr())); - zipW.subscribe(w); - - /* simulate sending data */ - // once for w1 - w1.observer.onNext("1a"); - w1.observer.onCompleted(); - // twice for w2 - w2.observer.onNext("2a"); - w2.observer.onNext("2b"); - w2.observer.onCompleted(); - // 4 times for w3 - w3.observer.onNext("3a"); - w3.observer.onNext("3b"); - w3.observer.onNext("3c"); - w3.observer.onNext("3d"); - w3.observer.onCompleted(); - - /* we should have been called 1 time on the Observer */ - InOrder inOrder = inOrder(w); - inOrder.verify(w).onNext("1a2a3a"); - - inOrder.verify(w, times(1)).onCompleted(); - } - - @Test - public void testZippingDifferentLengthObservableSequences2() { @SuppressWarnings("unchecked") - Observer w = mock(Observer.class); - - TestObservable w1 = new TestObservable(); - TestObservable w2 = new TestObservable(); - TestObservable w3 = new TestObservable(); - - Observable zipW = Observable.create(zip(Observable.create(w1), Observable.create(w2), Observable.create(w3), getConcat3StringsZipr())); - zipW.subscribe(w); - - /* simulate sending data */ - // 4 times for w1 - w1.observer.onNext("1a"); - w1.observer.onNext("1b"); - w1.observer.onNext("1c"); - w1.observer.onNext("1d"); - w1.observer.onCompleted(); - // twice for w2 - w2.observer.onNext("2a"); - w2.observer.onNext("2b"); - w2.observer.onCompleted(); - // 1 times for w3 - w3.observer.onNext("3a"); - w3.observer.onCompleted(); - - /* we should have been called 1 time on the Observer */ - InOrder inOrder = inOrder(w); - inOrder.verify(w).onNext("1a2a3a"); - - inOrder.verify(w, times(1)).onCompleted(); - - } - - /** - * Testing internal private logic due to the complexity so I want to use TDD to test as a I build it rather than relying purely on the overall functionality expected by the public methods. - */ - @SuppressWarnings("unchecked") - /* mock calls don't do generics */ - @Test - public void testAggregatorSimple() { - FuncN zipr = getConcatZipr(); - /* create the aggregator which will execute the zip function when all Observables provide values */ - Aggregator a = new Aggregator(zipr); - - /* define a Observer to receive aggregated events */ - Observer aObserver = mock(Observer.class); - a.onSubscribe(aObserver); - - /* mock the Observable Observers that are 'pushing' data for us */ - ZipObserver r1 = mock(ZipObserver.class); - ZipObserver r2 = mock(ZipObserver.class); - - /* pretend we're starting up */ - a.addObserver(r1); - a.addObserver(r2); - - /* simulate the Observables pushing data into the aggregator */ - a.next(r1, "hello"); - a.next(r2, "world"); - - InOrder inOrder = inOrder(aObserver); - - verify(aObserver, never()).onError(any(Throwable.class)); - verify(aObserver, never()).onCompleted(); - inOrder.verify(aObserver, times(1)).onNext("helloworld"); - - a.next(r1, "hello "); - a.next(r2, "again"); - - verify(aObserver, never()).onError(any(Throwable.class)); - verify(aObserver, never()).onCompleted(); - inOrder.verify(aObserver, times(1)).onNext("hello again"); - - a.complete(r1); - a.complete(r2); - - inOrder.verify(aObserver, never()).onNext(anyString()); - verify(aObserver, times(1)).onCompleted(); - } - - @SuppressWarnings("unchecked") - /* mock calls don't do generics */ - @Test - public void testAggregatorDifferentSizedResultsWithOnComplete() { - FuncN zipr = getConcatZipr(); - /* create the aggregator which will execute the zip function when all Observables provide values */ - Aggregator a = new Aggregator(zipr); - - /* define a Observer to receive aggregated events */ - Observer aObserver = mock(Observer.class); - a.onSubscribe(aObserver); - - /* mock the Observable Observers that are 'pushing' data for us */ - ZipObserver r1 = mock(ZipObserver.class); - ZipObserver r2 = mock(ZipObserver.class); - - /* pretend we're starting up */ - a.addObserver(r1); - a.addObserver(r2); - - /* simulate the Observables pushing data into the aggregator */ - a.next(r1, "hello"); - a.next(r2, "world"); - a.complete(r2); - - InOrder inOrder = inOrder(aObserver); - - inOrder.verify(aObserver, never()).onError(any(Throwable.class)); - inOrder.verify(aObserver, never()).onCompleted(); - inOrder.verify(aObserver, times(1)).onNext("helloworld"); - - a.next(r1, "hi"); - a.complete(r1); - - inOrder.verify(aObserver, never()).onError(any(Throwable.class)); - inOrder.verify(aObserver, times(1)).onCompleted(); - inOrder.verify(aObserver, never()).onNext(anyString()); - } - - @SuppressWarnings("unchecked") - /* mock calls don't do generics */ - @Test - public void testAggregateMultipleTypes() { - FuncN zipr = getConcatZipr(); - /* create the aggregator which will execute the zip function when all Observables provide values */ - Aggregator a = new Aggregator(zipr); - - /* define a Observer to receive aggregated events */ - Observer aObserver = mock(Observer.class); - a.onSubscribe(aObserver); - - /* mock the Observable Observers that are 'pushing' data for us */ - ZipObserver r1 = mock(ZipObserver.class); - ZipObserver r2 = mock(ZipObserver.class); - - /* pretend we're starting up */ - a.addObserver(r1); - a.addObserver(r2); - - /* simulate the Observables pushing data into the aggregator */ - a.next(r1, "hello"); - a.next(r2, "world"); - a.complete(r2); - - InOrder inOrder = inOrder(aObserver); - - inOrder.verify(aObserver, never()).onError(any(Throwable.class)); - inOrder.verify(aObserver, never()).onCompleted(); - inOrder.verify(aObserver, times(1)).onNext("helloworld"); - - a.next(r1, "hi"); - a.complete(r1); - - inOrder.verify(aObserver, never()).onError(any(Throwable.class)); - inOrder.verify(aObserver, times(1)).onCompleted(); - inOrder.verify(aObserver, never()).onNext(anyString()); - } - - @SuppressWarnings("unchecked") - /* mock calls don't do generics */ - @Test - public void testAggregate3Types() { - FuncN zipr = getConcatZipr(); - /* create the aggregator which will execute the zip function when all Observables provide values */ - Aggregator a = new Aggregator(zipr); - - /* define a Observer to receive aggregated events */ - Observer aObserver = mock(Observer.class); - a.onSubscribe(aObserver); - - /* mock the Observable Observers that are 'pushing' data for us */ - ZipObserver r1 = mock(ZipObserver.class); - ZipObserver r2 = mock(ZipObserver.class); - ZipObserver r3 = mock(ZipObserver.class); - - /* pretend we're starting up */ - a.addObserver(r1); - a.addObserver(r2); - a.addObserver(r3); - - /* simulate the Observables pushing data into the aggregator */ - a.next(r1, "hello"); - a.next(r2, 2); - a.next(r3, new int[] { 5, 6, 7 }); - - verify(aObserver, never()).onError(any(Throwable.class)); - verify(aObserver, never()).onCompleted(); - verify(aObserver, times(1)).onNext("hello2[5, 6, 7]"); - } - - @SuppressWarnings("unchecked") - /* mock calls don't do generics */ - @Test - public void testAggregatorsWithDifferentSizesAndTiming() { - FuncN zipr = getConcatZipr(); - /* create the aggregator which will execute the zip function when all Observables provide values */ - Aggregator a = new Aggregator(zipr); - - /* define a Observer to receive aggregated events */ - Observer aObserver = mock(Observer.class); - a.onSubscribe(aObserver); - - /* mock the Observable Observers that are 'pushing' data for us */ - ZipObserver r1 = mock(ZipObserver.class); - ZipObserver r2 = mock(ZipObserver.class); - - /* pretend we're starting up */ - a.addObserver(r1); - a.addObserver(r2); - - /* simulate the Observables pushing data into the aggregator */ - a.next(r1, "one"); - a.next(r1, "two"); - a.next(r1, "three"); - a.next(r2, "A"); - - verify(aObserver, never()).onError(any(Throwable.class)); - verify(aObserver, never()).onCompleted(); - verify(aObserver, times(1)).onNext("oneA"); - - a.next(r1, "four"); - a.complete(r1); - a.next(r2, "B"); - verify(aObserver, times(1)).onNext("twoB"); - a.next(r2, "C"); - verify(aObserver, times(1)).onNext("threeC"); - a.next(r2, "D"); - verify(aObserver, times(1)).onNext("fourD"); - a.next(r2, "E"); - verify(aObserver, never()).onNext("E"); - a.complete(r2); - - verify(aObserver, never()).onError(any(Throwable.class)); - verify(aObserver, times(1)).onCompleted(); - } - - @SuppressWarnings("unchecked") - /* mock calls don't do generics */ - @Test - public void testAggregatorError() { - FuncN zipr = getConcatZipr(); - /* create the aggregator which will execute the zip function when all Observables provide values */ - Aggregator a = new Aggregator(zipr); - - /* define a Observer to receive aggregated events */ - Observer aObserver = mock(Observer.class); - a.onSubscribe(aObserver); - - /* mock the Observable Observers that are 'pushing' data for us */ - ZipObserver r1 = mock(ZipObserver.class); - ZipObserver r2 = mock(ZipObserver.class); - - /* pretend we're starting up */ - a.addObserver(r1); - a.addObserver(r2); - - /* simulate the Observables pushing data into the aggregator */ - a.next(r1, "hello"); - a.next(r2, "world"); - - verify(aObserver, never()).onError(any(Throwable.class)); - verify(aObserver, never()).onCompleted(); - verify(aObserver, times(1)).onNext("helloworld"); - - a.error(r1, new RuntimeException("")); - a.next(r1, "hello"); - a.next(r2, "again"); - - verify(aObserver, times(1)).onError(any(Throwable.class)); - verify(aObserver, never()).onCompleted(); - // we don't want to be called again after an error - verify(aObserver, times(0)).onNext("helloagain"); - } - - @SuppressWarnings("unchecked") - /* mock calls don't do generics */ - @Test - public void testAggregatorUnsubscribe() { - FuncN zipr = getConcatZipr(); - /* create the aggregator which will execute the zip function when all Observables provide values */ - Aggregator a = new Aggregator(zipr); - - /* define a Observer to receive aggregated events */ - Observer aObserver = mock(Observer.class); - Subscription subscription = a.onSubscribe(aObserver); - - /* mock the Observable Observers that are 'pushing' data for us */ - ZipObserver r1 = mock(ZipObserver.class); - ZipObserver r2 = mock(ZipObserver.class); - - /* pretend we're starting up */ - a.addObserver(r1); - a.addObserver(r2); - - /* simulate the Observables pushing data into the aggregator */ - a.next(r1, "hello"); - a.next(r2, "world"); - - verify(aObserver, never()).onError(any(Throwable.class)); - verify(aObserver, never()).onCompleted(); - verify(aObserver, times(1)).onNext("helloworld"); - - subscription.unsubscribe(); - a.next(r1, "hello"); - a.next(r2, "again"); - - verify(aObserver, times(0)).onError(any(Throwable.class)); - verify(aObserver, never()).onCompleted(); - // we don't want to be called again after an error - verify(aObserver, times(0)).onNext("helloagain"); - } - - @SuppressWarnings("unchecked") - /* mock calls don't do generics */ - @Test - public void testAggregatorEarlyCompletion() { - FuncN zipr = getConcatZipr(); - /* create the aggregator which will execute the zip function when all Observables provide values */ - Aggregator a = new Aggregator(zipr); - - /* define a Observer to receive aggregated events */ - Observer aObserver = mock(Observer.class); - a.onSubscribe(aObserver); - - /* mock the Observable Observers that are 'pushing' data for us */ - ZipObserver r1 = mock(ZipObserver.class); - ZipObserver r2 = mock(ZipObserver.class); - - /* pretend we're starting up */ - a.addObserver(r1); - a.addObserver(r2); - - /* simulate the Observables pushing data into the aggregator */ - a.next(r1, "one"); - a.next(r1, "two"); - a.complete(r1); - a.next(r2, "A"); - - InOrder inOrder = inOrder(aObserver); - - inOrder.verify(aObserver, never()).onError(any(Throwable.class)); - inOrder.verify(aObserver, never()).onCompleted(); - inOrder.verify(aObserver, times(1)).onNext("oneA"); - - a.complete(r2); - - inOrder.verify(aObserver, never()).onError(any(Throwable.class)); - inOrder.verify(aObserver, times(1)).onCompleted(); - inOrder.verify(aObserver, never()).onNext(anyString()); - } - - @SuppressWarnings("unchecked") - /* mock calls don't do generics */ - @Test - public void testZip2Types() { - Func2 zipr = getConcatStringIntegerZipr(); - - /* define a Observer to receive aggregated events */ - Observer aObserver = mock(Observer.class); - - Observable w = Observable.create(zip(Observable.from("one", "two"), Observable.from(2, 3, 4), zipr)); - w.subscribe(aObserver); - - verify(aObserver, never()).onError(any(Throwable.class)); - verify(aObserver, times(1)).onCompleted(); - verify(aObserver, times(1)).onNext("one2"); - verify(aObserver, times(1)).onNext("two3"); - verify(aObserver, never()).onNext("4"); - } - - @SuppressWarnings("unchecked") - /* mock calls don't do generics */ - @Test - public void testZip3Types() { - Func3 zipr = getConcatStringIntegerIntArrayZipr(); - - /* define a Observer to receive aggregated events */ - Observer aObserver = mock(Observer.class); - - Observable w = Observable.create(zip(Observable.from("one", "two"), Observable.from(2), Observable.from(new int[] { 4, 5, 6 }), zipr)); - w.subscribe(aObserver); - - verify(aObserver, never()).onError(any(Throwable.class)); - verify(aObserver, times(1)).onCompleted(); - verify(aObserver, times(1)).onNext("one2[4, 5, 6]"); - verify(aObserver, never()).onNext("two"); - } - - @Test - public void testOnNextExceptionInvokesOnError() { - Func2 zipr = getDivideZipr(); + /* mock calls don't do generics */ + @Test + public void testAggregatorEarlyCompletion() { + FuncN zipr = getConcatZipr(); + /* create the aggregator which will execute the zip function when all Observables provide values */ + Aggregator a = new Aggregator(zipr); + + /* define a Observer to receive aggregated events */ + Observer aObserver = mock(Observer.class); + a.onSubscribe(aObserver); + + /* mock the Observable Observers that are 'pushing' data for us */ + ZipObserver r1 = mock(ZipObserver.class); + ZipObserver r2 = mock(ZipObserver.class); + + /* pretend we're starting up */ + a.addObserver(r1); + a.addObserver(r2); + + /* simulate the Observables pushing data into the aggregator */ + a.next(r1, "one"); + a.next(r1, "two"); + a.complete(r1); + a.next(r2, "A"); + + InOrder inOrder = inOrder(aObserver); + + inOrder.verify(aObserver, never()).onError(any(Throwable.class)); + inOrder.verify(aObserver, never()).onCompleted(); + inOrder.verify(aObserver, times(1)).onNext("oneA"); + + a.complete(r2); + + inOrder.verify(aObserver, never()).onError(any(Throwable.class)); + inOrder.verify(aObserver, times(1)).onCompleted(); + inOrder.verify(aObserver, never()).onNext(anyString()); + } @SuppressWarnings("unchecked") - Observer aObserver = mock(Observer.class); + /* mock calls don't do generics */ + @Test + public void testZip2Types() { + Func2 zipr = getConcatStringIntegerZipr(); + + /* define a Observer to receive aggregated events */ + Observer aObserver = mock(Observer.class); + + Observable w = Observable.create(zip(Observable.from("one", "two"), Observable.from(2, 3, 4), zipr)); + w.subscribe(aObserver); + + verify(aObserver, never()).onError(any(Throwable.class)); + verify(aObserver, times(1)).onCompleted(); + verify(aObserver, times(1)).onNext("one2"); + verify(aObserver, times(1)).onNext("two3"); + verify(aObserver, never()).onNext("4"); + } - Observable w = Observable.create(zip(Observable.from(10, 20, 30), Observable.from(0, 1, 2), zipr)); - w.subscribe(aObserver); + @SuppressWarnings("unchecked") + /* mock calls don't do generics */ + @Test + public void testZip3Types() { + Func3 zipr = getConcatStringIntegerIntArrayZipr(); - verify(aObserver, times(1)).onError(any(Throwable.class)); - } + /* define a Observer to receive aggregated events */ + Observer aObserver = mock(Observer.class); - private Func2 getDivideZipr() { - Func2 zipr = new Func2() { + Observable w = Observable.create(zip(Observable.from("one", "two"), Observable.from(2), Observable.from(new int[] { 4, 5, 6 }), zipr)); + w.subscribe(aObserver); - @Override - public Integer call(Integer i1, Integer i2) { - return i1 / i2; - } + verify(aObserver, never()).onError(any(Throwable.class)); + verify(aObserver, times(1)).onCompleted(); + verify(aObserver, times(1)).onNext("one2[4, 5, 6]"); + verify(aObserver, never()).onNext("two"); + } - }; - return zipr; - } + @Test + public void testOnNextExceptionInvokesOnError() { + Func2 zipr = getDivideZipr(); - private Func3 getConcat3StringsZipr() { - Func3 zipr = new Func3() { + @SuppressWarnings("unchecked") + Observer aObserver = mock(Observer.class); - @Override - public String call(String a1, String a2, String a3) { - if (a1 == null) { - a1 = ""; - } - if (a2 == null) { - a2 = ""; - } - if (a3 == null) { - a3 = ""; - } - return a1 + a2 + a3; - } - - }; - return zipr; - } - - private FuncN getConcatZipr() { - FuncN zipr = new FuncN() { - - @Override - public String call(Object... args) { - String returnValue = ""; - for (Object o : args) { - if (o != null) { - returnValue += getStringValue(o); - } - } - System.out.println("returning: " + returnValue); - return returnValue; - } - - }; - return zipr; - } - - private Func2 getConcatStringIntegerZipr() { - Func2 zipr = new Func2() { - - @Override - public String call(String s, Integer i) { - return getStringValue(s) + getStringValue(i); - } - - }; - return zipr; - } - - private Func3 getConcatStringIntegerIntArrayZipr() { - Func3 zipr = new Func3() { - - @Override - public String call(String s, Integer i, int[] iArray) { - return getStringValue(s) + getStringValue(i) + getStringValue(iArray); - } - - }; - return zipr; - } - - private static String getStringValue(Object o) { - if (o == null) { - return ""; - } else { - if (o instanceof int[]) { - return Arrays.toString((int[]) o); - } else { - return String.valueOf(o); - } + Observable w = Observable.create(zip(Observable.from(10, 20, 30), Observable.from(0, 1, 2), zipr)); + w.subscribe(aObserver); + + verify(aObserver, times(1)).onError(any(Throwable.class)); } - } - private static class TestObservable implements Observable.OnSubscribeFunc { + private Func2 getDivideZipr() { + Func2 zipr = new Func2() { - Observer observer; + @Override + public Integer call(Integer i1, Integer i2) { + return i1 / i2; + } - @Override - public Subscription onSubscribe(Observer Observer) { - // just store the variable where it can be accessed so we can manually trigger it - this.observer = Observer; - return Subscriptions.empty(); + }; + return zipr; } - } + private Func3 getConcat3StringsZipr() { + Func3 zipr = new Func3() { + + @Override + public String call(String a1, String a2, String a3) { + if (a1 == null) { + a1 = ""; + } + if (a2 == null) { + a2 = ""; + } + if (a3 == null) { + a3 = ""; + } + return a1 + a2 + a3; + } + + }; + return zipr; + } + + private FuncN getConcatZipr() { + FuncN zipr = new FuncN() { + + @Override + public String call(Object... args) { + String returnValue = ""; + for (Object o : args) { + if (o != null) { + returnValue += getStringValue(o); + } + } + System.out.println("returning: " + returnValue); + return returnValue; + } + + }; + return zipr; + } + + private Func2 getConcatStringIntegerZipr() { + Func2 zipr = new Func2() { + + @Override + public String call(String s, Integer i) { + return getStringValue(s) + getStringValue(i); + } + + }; + return zipr; + } + + private Func3 getConcatStringIntegerIntArrayZipr() { + Func3 zipr = new Func3() { + + @Override + public String call(String s, Integer i, int[] iArray) { + return getStringValue(s) + getStringValue(i) + getStringValue(iArray); + } + + }; + return zipr; + } + + private static String getStringValue(Object o) { + if (o == null) { + return ""; + } else { + if (o instanceof int[]) { + return Arrays.toString((int[]) o); + } else { + return String.valueOf(o); + } + } + } + + private static class TestObservable implements Observable.OnSubscribeFunc { + + Observer observer; + + @Override + public Subscription onSubscribe(Observer Observer) { + // just store the variable where it can be accessed so we can manually trigger it + this.observer = Observer; + return Subscriptions.empty(); + } + + } } diff --git a/rxjava-core/src/test/java/rx/operators/SafeObservableSubscriptionTest.java b/rxjava-core/src/test/java/rx/operators/SafeObservableSubscriptionTest.java index a4bf9e8e8c..99120b4348 100644 --- a/rxjava-core/src/test/java/rx/operators/SafeObservableSubscriptionTest.java +++ b/rxjava-core/src/test/java/rx/operators/SafeObservableSubscriptionTest.java @@ -1,21 +1,19 @@ package rx.operators; -import org.junit.Ignore; +import static org.mockito.Mockito.*; + import org.junit.Test; -import rx.Subscription; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; +import rx.Subscription; public class SafeObservableSubscriptionTest { - @Test - public void testWrapAfterUnsubscribe() { - SafeObservableSubscription atomicObservableSubscription = new SafeObservableSubscription(); - atomicObservableSubscription.unsubscribe(); - Subscription innerSubscription = mock(Subscription.class); - atomicObservableSubscription.wrap(innerSubscription); - verify(innerSubscription, times(1)).unsubscribe(); - } + @Test + public void testWrapAfterUnsubscribe() { + SafeObservableSubscription atomicObservableSubscription = new SafeObservableSubscription(); + atomicObservableSubscription.unsubscribe(); + Subscription innerSubscription = mock(Subscription.class); + atomicObservableSubscription.wrap(innerSubscription); + verify(innerSubscription, times(1)).unsubscribe(); + } } diff --git a/rxjava-core/src/test/java/rx/operators/SynchronizedObserverTest.java b/rxjava-core/src/test/java/rx/operators/SynchronizedObserverTest.java index b9e4b2e278..2780eef712 100644 --- a/rxjava-core/src/test/java/rx/operators/SynchronizedObserverTest.java +++ b/rxjava-core/src/test/java/rx/operators/SynchronizedObserverTest.java @@ -1,751 +1,757 @@ package rx.operators; +import static org.junit.Assert.*; +import static org.mockito.Matchers.*; +import static org.mockito.Mockito.*; + +import java.util.Random; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; +import java.util.concurrent.LinkedBlockingQueue; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicInteger; + import org.junit.Before; import org.junit.Test; import org.mockito.Mock; import org.mockito.MockitoAnnotations; + import rx.Observable; import rx.Observer; import rx.Subscription; -import java.util.Random; -import java.util.concurrent.*; -import java.util.concurrent.atomic.AtomicInteger; - -import static org.junit.Assert.*; -import static org.mockito.Matchers.any; -import static org.mockito.Mockito.*; - public class SynchronizedObserverTest { - @Mock - Observer aObserver; - - @Before - public void before() { - MockitoAnnotations.initMocks(this); - } - - @Test - public void testSingleThreadedBasic() { - Subscription s = mock(Subscription.class); - TestSingleThreadedObservable onSubscribe = new TestSingleThreadedObservable(s, "one", "two", "three"); - Observable w = Observable.create(onSubscribe); - - SafeObservableSubscription as = new SafeObservableSubscription(s); - SynchronizedObserver aw = new SynchronizedObserver(aObserver, as); - - w.subscribe(aw); - onSubscribe.waitToFinish(); - - verify(aObserver, times(1)).onNext("one"); - verify(aObserver, times(1)).onNext("two"); - verify(aObserver, times(1)).onNext("three"); - verify(aObserver, never()).onError(any(Throwable.class)); - verify(aObserver, times(1)).onCompleted(); - // non-deterministic because unsubscribe happens after 'waitToFinish' releases - // so commenting out for now as this is not a critical thing to test here - // verify(s, times(1)).unsubscribe(); - } - - @Test - public void testMultiThreadedBasic() { - Subscription s = mock(Subscription.class); - TestMultiThreadedObservable onSubscribe = new TestMultiThreadedObservable(s, "one", "two", "three"); - Observable w = Observable.create(onSubscribe); - - SafeObservableSubscription as = new SafeObservableSubscription(s); - BusyObserver busyObserver = new BusyObserver(); - SynchronizedObserver aw = new SynchronizedObserver(busyObserver, as); - - w.subscribe(aw); - onSubscribe.waitToFinish(); - - assertEquals(3, busyObserver.onNextCount.get()); - assertFalse(busyObserver.onError); - assertTrue(busyObserver.onCompleted); - // non-deterministic because unsubscribe happens after 'waitToFinish' releases - // so commenting out for now as this is not a critical thing to test here - // verify(s, times(1)).unsubscribe(); - - // we can have concurrency ... - assertTrue(onSubscribe.maxConcurrentThreads.get() > 1); - // ... but the onNext execution should be single threaded - assertEquals(1, busyObserver.maxConcurrentThreads.get()); - } - - @Test - public void testMultiThreadedBasicWithLock() { - Subscription s = mock(Subscription.class); - TestMultiThreadedObservable onSubscribe = new TestMultiThreadedObservable(s, "one", "two", "three"); - Observable w = Observable.create(onSubscribe); - - SafeObservableSubscription as = new SafeObservableSubscription(s); - BusyObserver busyObserver = new BusyObserver(); - - Object lock = new Object(); - ExternalBusyThread externalBusyThread = new ExternalBusyThread(busyObserver, lock, 10, 100); - - SynchronizedObserver aw = new SynchronizedObserver(busyObserver, as, lock); - - externalBusyThread.start(); - - w.subscribe(aw); - onSubscribe.waitToFinish(); - - try { - externalBusyThread.join(10000); - assertFalse(externalBusyThread.isAlive()); - assertFalse(externalBusyThread.fail); - } catch (InterruptedException e) { - // ignore - } + @Mock + Observer aObserver; - assertEquals(3, busyObserver.onNextCount.get()); - assertFalse(busyObserver.onError); - assertTrue(busyObserver.onCompleted); - // non-deterministic because unsubscribe happens after 'waitToFinish' releases - // so commenting out for now as this is not a critical thing to test here - // verify(s, times(1)).unsubscribe(); - - // we can have concurrency ... - assertTrue(onSubscribe.maxConcurrentThreads.get() > 1); - // ... but the onNext execution should be single threaded - assertEquals(1, busyObserver.maxConcurrentThreads.get()); - } - - @Test - public void testMultiThreadedWithNPE() { - Subscription s = mock(Subscription.class); - TestMultiThreadedObservable onSubscribe = new TestMultiThreadedObservable(s, "one", "two", "three", null); - Observable w = Observable.create(onSubscribe); - - SafeObservableSubscription as = new SafeObservableSubscription(s); - BusyObserver busyObserver = new BusyObserver(); - SynchronizedObserver aw = new SynchronizedObserver(busyObserver, as); - - w.subscribe(aw); - onSubscribe.waitToFinish(); - - System.out.println("maxConcurrentThreads: " + onSubscribe.maxConcurrentThreads.get()); - - // we can't know how many onNext calls will occur since they each run on a separate thread - // that depends on thread scheduling so 0, 1, 2 and 3 are all valid options - // assertEquals(3, busyObserver.onNextCount.get()); - assertTrue(busyObserver.onNextCount.get() < 4); - assertTrue(busyObserver.onError); - // no onCompleted because onError was invoked - assertFalse(busyObserver.onCompleted); - // non-deterministic because unsubscribe happens after 'waitToFinish' releases - // so commenting out for now as this is not a critical thing to test here - //verify(s, times(1)).unsubscribe(); - - // we can have concurrency ... - assertTrue(onSubscribe.maxConcurrentThreads.get() > 1); - // ... but the onNext execution should be single threaded - assertEquals(1, busyObserver.maxConcurrentThreads.get()); - } - - @Test - public void testMultiThreadedWithNPEAndLock() { - Subscription s = mock(Subscription.class); - TestMultiThreadedObservable onSubscribe = new TestMultiThreadedObservable(s, "one", "two", "three", null); - Observable w = Observable.create(onSubscribe); - - SafeObservableSubscription as = new SafeObservableSubscription(s); - BusyObserver busyObserver = new BusyObserver(); - - Object lock = new Object(); - ExternalBusyThread externalBusyThread = new ExternalBusyThread(busyObserver, lock, 10, 100); - - SynchronizedObserver aw = new SynchronizedObserver(busyObserver, as, lock); - - externalBusyThread.start(); - - w.subscribe(aw); - onSubscribe.waitToFinish(); - - try { - externalBusyThread.join(10000); - assertFalse(externalBusyThread.isAlive()); - assertFalse(externalBusyThread.fail); - } catch (InterruptedException e) { - // ignore + @Before + public void before() { + MockitoAnnotations.initMocks(this); } - System.out.println("maxConcurrentThreads: " + onSubscribe.maxConcurrentThreads.get()); - - // we can't know how many onNext calls will occur since they each run on a separate thread - // that depends on thread scheduling so 0, 1, 2 and 3 are all valid options - // assertEquals(3, busyObserver.onNextCount.get()); - assertTrue(busyObserver.onNextCount.get() < 4); - assertTrue(busyObserver.onError); - // no onCompleted because onError was invoked - assertFalse(busyObserver.onCompleted); - // non-deterministic because unsubscribe happens after 'waitToFinish' releases - // so commenting out for now as this is not a critical thing to test here - //verify(s, times(1)).unsubscribe(); - - // we can have concurrency ... - assertTrue(onSubscribe.maxConcurrentThreads.get() > 1); - // ... but the onNext execution should be single threaded - assertEquals(1, busyObserver.maxConcurrentThreads.get()); - } - - @Test - public void testMultiThreadedWithNPEinMiddle() { - Subscription s = mock(Subscription.class); - TestMultiThreadedObservable onSubscribe = new TestMultiThreadedObservable(s, "one", "two", "three", null, "four", "five", "six", "seven", "eight", "nine"); - Observable w = Observable.create(onSubscribe); - - SafeObservableSubscription as = new SafeObservableSubscription(s); - BusyObserver busyObserver = new BusyObserver(); - SynchronizedObserver aw = new SynchronizedObserver(busyObserver, as); - - w.subscribe(aw); - onSubscribe.waitToFinish(); - - System.out.println("maxConcurrentThreads: " + onSubscribe.maxConcurrentThreads.get()); - // this should not be the full number of items since the error should stop it before it completes all 9 - System.out.println("onNext count: " + busyObserver.onNextCount.get()); - assertTrue(busyObserver.onNextCount.get() < 9); - assertTrue(busyObserver.onError); - // no onCompleted because onError was invoked - assertFalse(busyObserver.onCompleted); - // non-deterministic because unsubscribe happens after 'waitToFinish' releases - // so commenting out for now as this is not a critical thing to test here - // verify(s, times(1)).unsubscribe(); - - // we can have concurrency ... - assertTrue(onSubscribe.maxConcurrentThreads.get() > 1); - // ... but the onNext execution should be single threaded - assertEquals(1, busyObserver.maxConcurrentThreads.get()); - } - - @Test - public void testMultiThreadedWithNPEinMiddleAndLock() { - Subscription s = mock(Subscription.class); - TestMultiThreadedObservable onSubscribe = new TestMultiThreadedObservable(s, "one", "two", "three", null, "four", "five", "six", "seven", "eight", "nine"); - Observable w = Observable.create(onSubscribe); - - SafeObservableSubscription as = new SafeObservableSubscription(s); - BusyObserver busyObserver = new BusyObserver(); - - Object lock = new Object(); - ExternalBusyThread externalBusyThread = new ExternalBusyThread(busyObserver, lock, 10, 100); - - SynchronizedObserver aw = new SynchronizedObserver(busyObserver, as, lock); - - externalBusyThread.start(); - - w.subscribe(aw); - onSubscribe.waitToFinish(); - - try { - externalBusyThread.join(10000); - assertFalse(externalBusyThread.isAlive()); - assertFalse(externalBusyThread.fail); - } catch (InterruptedException e) { - // ignore + @Test + public void testSingleThreadedBasic() { + Subscription s = mock(Subscription.class); + TestSingleThreadedObservable onSubscribe = new TestSingleThreadedObservable(s, "one", "two", "three"); + Observable w = Observable.create(onSubscribe); + + SafeObservableSubscription as = new SafeObservableSubscription(s); + SynchronizedObserver aw = new SynchronizedObserver(aObserver, as); + + w.subscribe(aw); + onSubscribe.waitToFinish(); + + verify(aObserver, times(1)).onNext("one"); + verify(aObserver, times(1)).onNext("two"); + verify(aObserver, times(1)).onNext("three"); + verify(aObserver, never()).onError(any(Throwable.class)); + verify(aObserver, times(1)).onCompleted(); + // non-deterministic because unsubscribe happens after 'waitToFinish' releases + // so commenting out for now as this is not a critical thing to test here + // verify(s, times(1)).unsubscribe(); } - System.out.println("maxConcurrentThreads: " + onSubscribe.maxConcurrentThreads.get()); - // this should not be the full number of items since the error should stop it before it completes all 9 - System.out.println("onNext count: " + busyObserver.onNextCount.get()); - assertTrue(busyObserver.onNextCount.get() < 9); - assertTrue(busyObserver.onError); - // no onCompleted because onError was invoked - assertFalse(busyObserver.onCompleted); - // non-deterministic because unsubscribe happens after 'waitToFinish' releases - // so commenting out for now as this is not a critical thing to test here - // verify(s, times(1)).unsubscribe(); - - // we can have concurrency ... - assertTrue(onSubscribe.maxConcurrentThreads.get() > 1); - // ... but the onNext execution should be single threaded - assertEquals(1, busyObserver.maxConcurrentThreads.get()); - } - - /** - * A non-realistic use case that tries to expose thread-safety issues by throwing lots of out-of-order - * events on many threads. - * - * @param w - * @param tw - */ - @Test - public void runConcurrencyTest() { - ExecutorService tp = Executors.newFixedThreadPool(20); - try { - TestConcurrencyObserver tw = new TestConcurrencyObserver(); - SafeObservableSubscription s = new SafeObservableSubscription(); - SynchronizedObserver w = new SynchronizedObserver(tw, s); - - Future f1 = tp.submit(new OnNextThread(w, 12000)); - Future f2 = tp.submit(new OnNextThread(w, 5000)); - Future f3 = tp.submit(new OnNextThread(w, 75000)); - Future f4 = tp.submit(new OnNextThread(w, 13500)); - Future f5 = tp.submit(new OnNextThread(w, 22000)); - Future f6 = tp.submit(new OnNextThread(w, 15000)); - Future f7 = tp.submit(new OnNextThread(w, 7500)); - Future f8 = tp.submit(new OnNextThread(w, 23500)); - - Future f10 = tp.submit(new CompletionThread(w, TestConcurrencyObserverEvent.onCompleted, f1, f2, f3, f4)); - try { - Thread.sleep(1); - } catch (InterruptedException e) { - // ignore - } - Future f11 = tp.submit(new CompletionThread(w, TestConcurrencyObserverEvent.onCompleted, f4, f6, f7)); - Future f12 = tp.submit(new CompletionThread(w, TestConcurrencyObserverEvent.onCompleted, f4, f6, f7)); - Future f13 = tp.submit(new CompletionThread(w, TestConcurrencyObserverEvent.onCompleted, f4, f6, f7)); - Future f14 = tp.submit(new CompletionThread(w, TestConcurrencyObserverEvent.onCompleted, f4, f6, f7)); - // // the next 4 onError events should wait on same as f10 - Future f15 = tp.submit(new CompletionThread(w, TestConcurrencyObserverEvent.onError, f1, f2, f3, f4)); - Future f16 = tp.submit(new CompletionThread(w, TestConcurrencyObserverEvent.onError, f1, f2, f3, f4)); - Future f17 = tp.submit(new CompletionThread(w, TestConcurrencyObserverEvent.onError, f1, f2, f3, f4)); - Future f18 = tp.submit(new CompletionThread(w, TestConcurrencyObserverEvent.onError, f1, f2, f3, f4)); - - waitOnThreads(f1, f2, f3, f4, f5, f6, f7, f8, f10, f11, f12, f13, f14, f15, f16, f17, f18); - @SuppressWarnings("unused") - int numNextEvents = tw.assertEvents(null); // no check of type since we don't want to test barging results here, just interleaving behavior - // System.out.println("Number of events executed: " + numNextEvents); - } catch (Throwable e) { - fail("Concurrency test failed: " + e.getMessage()); - e.printStackTrace(); - } finally { - tp.shutdown(); - try { - tp.awaitTermination(5000, TimeUnit.MILLISECONDS); - } catch (InterruptedException e) { - e.printStackTrace(); - } - } - } - - private static void waitOnThreads(Future... futures) { - for (Future f : futures) { - try { - f.get(10, TimeUnit.SECONDS); - } catch (Throwable e) { - System.err.println("Failed while waiting on future."); - e.printStackTrace(); - } + @Test + public void testMultiThreadedBasic() { + Subscription s = mock(Subscription.class); + TestMultiThreadedObservable onSubscribe = new TestMultiThreadedObservable(s, "one", "two", "three"); + Observable w = Observable.create(onSubscribe); + + SafeObservableSubscription as = new SafeObservableSubscription(s); + BusyObserver busyObserver = new BusyObserver(); + SynchronizedObserver aw = new SynchronizedObserver(busyObserver, as); + + w.subscribe(aw); + onSubscribe.waitToFinish(); + + assertEquals(3, busyObserver.onNextCount.get()); + assertFalse(busyObserver.onError); + assertTrue(busyObserver.onCompleted); + // non-deterministic because unsubscribe happens after 'waitToFinish' releases + // so commenting out for now as this is not a critical thing to test here + // verify(s, times(1)).unsubscribe(); + + // we can have concurrency ... + assertTrue(onSubscribe.maxConcurrentThreads.get() > 1); + // ... but the onNext execution should be single threaded + assertEquals(1, busyObserver.maxConcurrentThreads.get()); } - } - /** - * A thread that will pass data to onNext - */ - public static class OnNextThread implements Runnable { + @Test + public void testMultiThreadedBasicWithLock() { + Subscription s = mock(Subscription.class); + TestMultiThreadedObservable onSubscribe = new TestMultiThreadedObservable(s, "one", "two", "three"); + Observable w = Observable.create(onSubscribe); - private final Observer Observer; - private final int numStringsToSend; + SafeObservableSubscription as = new SafeObservableSubscription(s); + BusyObserver busyObserver = new BusyObserver(); - OnNextThread(Observer Observer, int numStringsToSend) { - this.Observer = Observer; - this.numStringsToSend = numStringsToSend; - } - - @Override - public void run() { - for (int i = 0; i < numStringsToSend; i++) { - Observer.onNext("aString"); - } - } - } + Object lock = new Object(); + ExternalBusyThread externalBusyThread = new ExternalBusyThread(busyObserver, lock, 10, 100); - /** - * A thread that will call onError or onNext - */ - public static class CompletionThread implements Runnable { + SynchronizedObserver aw = new SynchronizedObserver(busyObserver, as, lock); - private final Observer Observer; - private final TestConcurrencyObserverEvent event; - private final Future[] waitOnThese; + externalBusyThread.start(); - CompletionThread(Observer Observer, TestConcurrencyObserverEvent event, Future... waitOnThese) { - this.Observer = Observer; - this.event = event; - this.waitOnThese = waitOnThese; - } + w.subscribe(aw); + onSubscribe.waitToFinish(); - @Override - public void run() { - /* if we have 'waitOnThese' futures, we'll wait on them before proceeding */ - if (waitOnThese != null) { - for (Future f : waitOnThese) { - try { - f.get(); - } catch (Throwable e) { - System.err.println("Error while waiting on future in CompletionThread"); - } + try { + externalBusyThread.join(10000); + assertFalse(externalBusyThread.isAlive()); + assertFalse(externalBusyThread.fail); + } catch (InterruptedException e) { + // ignore } - } - /* send the event */ - if (event == TestConcurrencyObserverEvent.onError) { - Observer.onError(new RuntimeException("mocked exception")); - } else if (event == TestConcurrencyObserverEvent.onCompleted) { - Observer.onCompleted(); + assertEquals(3, busyObserver.onNextCount.get()); + assertFalse(busyObserver.onError); + assertTrue(busyObserver.onCompleted); + // non-deterministic because unsubscribe happens after 'waitToFinish' releases + // so commenting out for now as this is not a critical thing to test here + // verify(s, times(1)).unsubscribe(); + + // we can have concurrency ... + assertTrue(onSubscribe.maxConcurrentThreads.get() > 1); + // ... but the onNext execution should be single threaded + assertEquals(1, busyObserver.maxConcurrentThreads.get()); + } - } else { - throw new IllegalArgumentException("Expecting either onError or onCompleted"); - } + @Test + public void testMultiThreadedWithNPE() { + Subscription s = mock(Subscription.class); + TestMultiThreadedObservable onSubscribe = new TestMultiThreadedObservable(s, "one", "two", "three", null); + Observable w = Observable.create(onSubscribe); + + SafeObservableSubscription as = new SafeObservableSubscription(s); + BusyObserver busyObserver = new BusyObserver(); + SynchronizedObserver aw = new SynchronizedObserver(busyObserver, as); + + w.subscribe(aw); + onSubscribe.waitToFinish(); + + System.out.println("maxConcurrentThreads: " + onSubscribe.maxConcurrentThreads.get()); + + // we can't know how many onNext calls will occur since they each run on a separate thread + // that depends on thread scheduling so 0, 1, 2 and 3 are all valid options + // assertEquals(3, busyObserver.onNextCount.get()); + assertTrue(busyObserver.onNextCount.get() < 4); + assertTrue(busyObserver.onError); + // no onCompleted because onError was invoked + assertFalse(busyObserver.onCompleted); + // non-deterministic because unsubscribe happens after 'waitToFinish' releases + // so commenting out for now as this is not a critical thing to test here + //verify(s, times(1)).unsubscribe(); + + // we can have concurrency ... + assertTrue(onSubscribe.maxConcurrentThreads.get() > 1); + // ... but the onNext execution should be single threaded + assertEquals(1, busyObserver.maxConcurrentThreads.get()); } - } - private static enum TestConcurrencyObserverEvent { - onCompleted, onError, onNext - } + @Test + public void testMultiThreadedWithNPEAndLock() { + Subscription s = mock(Subscription.class); + TestMultiThreadedObservable onSubscribe = new TestMultiThreadedObservable(s, "one", "two", "three", null); + Observable w = Observable.create(onSubscribe); - private static class TestConcurrencyObserver implements Observer { + SafeObservableSubscription as = new SafeObservableSubscription(s); + BusyObserver busyObserver = new BusyObserver(); - /** - * used to store the order and number of events received - */ - private final LinkedBlockingQueue events = new LinkedBlockingQueue(); - private final int waitTime; + Object lock = new Object(); + ExternalBusyThread externalBusyThread = new ExternalBusyThread(busyObserver, lock, 10, 100); - @SuppressWarnings("unused") - public TestConcurrencyObserver(int waitTimeInNext) { - this.waitTime = waitTimeInNext; - } + SynchronizedObserver aw = new SynchronizedObserver(busyObserver, as, lock); - public TestConcurrencyObserver() { - this.waitTime = 0; - } + externalBusyThread.start(); + + w.subscribe(aw); + onSubscribe.waitToFinish(); - @Override - public void onCompleted() { - events.add(TestConcurrencyObserverEvent.onCompleted); + try { + externalBusyThread.join(10000); + assertFalse(externalBusyThread.isAlive()); + assertFalse(externalBusyThread.fail); + } catch (InterruptedException e) { + // ignore + } + + System.out.println("maxConcurrentThreads: " + onSubscribe.maxConcurrentThreads.get()); + + // we can't know how many onNext calls will occur since they each run on a separate thread + // that depends on thread scheduling so 0, 1, 2 and 3 are all valid options + // assertEquals(3, busyObserver.onNextCount.get()); + assertTrue(busyObserver.onNextCount.get() < 4); + assertTrue(busyObserver.onError); + // no onCompleted because onError was invoked + assertFalse(busyObserver.onCompleted); + // non-deterministic because unsubscribe happens after 'waitToFinish' releases + // so commenting out for now as this is not a critical thing to test here + //verify(s, times(1)).unsubscribe(); + + // we can have concurrency ... + assertTrue(onSubscribe.maxConcurrentThreads.get() > 1); + // ... but the onNext execution should be single threaded + assertEquals(1, busyObserver.maxConcurrentThreads.get()); } - @Override - public void onError(Throwable e) { - events.add(TestConcurrencyObserverEvent.onError); + @Test + public void testMultiThreadedWithNPEinMiddle() { + Subscription s = mock(Subscription.class); + TestMultiThreadedObservable onSubscribe = new TestMultiThreadedObservable(s, "one", "two", "three", null, "four", "five", "six", "seven", "eight", "nine"); + Observable w = Observable.create(onSubscribe); + + SafeObservableSubscription as = new SafeObservableSubscription(s); + BusyObserver busyObserver = new BusyObserver(); + SynchronizedObserver aw = new SynchronizedObserver(busyObserver, as); + + w.subscribe(aw); + onSubscribe.waitToFinish(); + + System.out.println("maxConcurrentThreads: " + onSubscribe.maxConcurrentThreads.get()); + // this should not be the full number of items since the error should stop it before it completes all 9 + System.out.println("onNext count: " + busyObserver.onNextCount.get()); + assertTrue(busyObserver.onNextCount.get() < 9); + assertTrue(busyObserver.onError); + // no onCompleted because onError was invoked + assertFalse(busyObserver.onCompleted); + // non-deterministic because unsubscribe happens after 'waitToFinish' releases + // so commenting out for now as this is not a critical thing to test here + // verify(s, times(1)).unsubscribe(); + + // we can have concurrency ... + assertTrue(onSubscribe.maxConcurrentThreads.get() > 1); + // ... but the onNext execution should be single threaded + assertEquals(1, busyObserver.maxConcurrentThreads.get()); } - @Override - public void onNext(String args) { - events.add(TestConcurrencyObserverEvent.onNext); - // do some artificial work to make the thread scheduling/timing vary - int s = 0; - for (int i = 0; i < 20; i++) { - s += s * i; - } + @Test + public void testMultiThreadedWithNPEinMiddleAndLock() { + Subscription s = mock(Subscription.class); + TestMultiThreadedObservable onSubscribe = new TestMultiThreadedObservable(s, "one", "two", "three", null, "four", "five", "six", "seven", "eight", "nine"); + Observable w = Observable.create(onSubscribe); + + SafeObservableSubscription as = new SafeObservableSubscription(s); + BusyObserver busyObserver = new BusyObserver(); + + Object lock = new Object(); + ExternalBusyThread externalBusyThread = new ExternalBusyThread(busyObserver, lock, 10, 100); + + SynchronizedObserver aw = new SynchronizedObserver(busyObserver, as, lock); + + externalBusyThread.start(); + + w.subscribe(aw); + onSubscribe.waitToFinish(); - if (waitTime > 0) { try { - Thread.sleep(waitTime); + externalBusyThread.join(10000); + assertFalse(externalBusyThread.isAlive()); + assertFalse(externalBusyThread.fail); } catch (InterruptedException e) { - // ignore + // ignore } - } + + System.out.println("maxConcurrentThreads: " + onSubscribe.maxConcurrentThreads.get()); + // this should not be the full number of items since the error should stop it before it completes all 9 + System.out.println("onNext count: " + busyObserver.onNextCount.get()); + assertTrue(busyObserver.onNextCount.get() < 9); + assertTrue(busyObserver.onError); + // no onCompleted because onError was invoked + assertFalse(busyObserver.onCompleted); + // non-deterministic because unsubscribe happens after 'waitToFinish' releases + // so commenting out for now as this is not a critical thing to test here + // verify(s, times(1)).unsubscribe(); + + // we can have concurrency ... + assertTrue(onSubscribe.maxConcurrentThreads.get() > 1); + // ... but the onNext execution should be single threaded + assertEquals(1, busyObserver.maxConcurrentThreads.get()); } /** - * Assert the order of events is correct and return the number of onNext executions. - * - * @param expectedEndingEvent - * @return int count of onNext calls - * @throws IllegalStateException If order of events was invalid. + * A non-realistic use case that tries to expose thread-safety issues by throwing lots of out-of-order + * events on many threads. + * + * @param w + * @param tw */ - public int assertEvents(TestConcurrencyObserverEvent expectedEndingEvent) throws IllegalStateException { - int nextCount = 0; - boolean finished = false; - for (TestConcurrencyObserverEvent e : events) { - if (e == TestConcurrencyObserverEvent.onNext) { - if (finished) { - // already finished, we shouldn't get this again - throw new IllegalStateException("Received onNext but we're already finished."); - } - nextCount++; - } else if (e == TestConcurrencyObserverEvent.onError) { - if (finished) { - // already finished, we shouldn't get this again - throw new IllegalStateException("Received onError but we're already finished."); - } - if (expectedEndingEvent != null && TestConcurrencyObserverEvent.onError != expectedEndingEvent) { - throw new IllegalStateException("Received onError ending event but expected " + expectedEndingEvent); - } - finished = true; - } else if (e == TestConcurrencyObserverEvent.onCompleted) { - if (finished) { - // already finished, we shouldn't get this again - throw new IllegalStateException("Received onCompleted but we're already finished."); - } - if (expectedEndingEvent != null && TestConcurrencyObserverEvent.onCompleted != expectedEndingEvent) { - throw new IllegalStateException("Received onCompleted ending event but expected " + expectedEndingEvent); - } - finished = true; + @Test + public void runConcurrencyTest() { + ExecutorService tp = Executors.newFixedThreadPool(20); + try { + TestConcurrencyObserver tw = new TestConcurrencyObserver(); + SafeObservableSubscription s = new SafeObservableSubscription(); + SynchronizedObserver w = new SynchronizedObserver(tw, s); + + Future f1 = tp.submit(new OnNextThread(w, 12000)); + Future f2 = tp.submit(new OnNextThread(w, 5000)); + Future f3 = tp.submit(new OnNextThread(w, 75000)); + Future f4 = tp.submit(new OnNextThread(w, 13500)); + Future f5 = tp.submit(new OnNextThread(w, 22000)); + Future f6 = tp.submit(new OnNextThread(w, 15000)); + Future f7 = tp.submit(new OnNextThread(w, 7500)); + Future f8 = tp.submit(new OnNextThread(w, 23500)); + + Future f10 = tp.submit(new CompletionThread(w, TestConcurrencyObserverEvent.onCompleted, f1, f2, f3, f4)); + try { + Thread.sleep(1); + } catch (InterruptedException e) { + // ignore + } + Future f11 = tp.submit(new CompletionThread(w, TestConcurrencyObserverEvent.onCompleted, f4, f6, f7)); + Future f12 = tp.submit(new CompletionThread(w, TestConcurrencyObserverEvent.onCompleted, f4, f6, f7)); + Future f13 = tp.submit(new CompletionThread(w, TestConcurrencyObserverEvent.onCompleted, f4, f6, f7)); + Future f14 = tp.submit(new CompletionThread(w, TestConcurrencyObserverEvent.onCompleted, f4, f6, f7)); + // // the next 4 onError events should wait on same as f10 + Future f15 = tp.submit(new CompletionThread(w, TestConcurrencyObserverEvent.onError, f1, f2, f3, f4)); + Future f16 = tp.submit(new CompletionThread(w, TestConcurrencyObserverEvent.onError, f1, f2, f3, f4)); + Future f17 = tp.submit(new CompletionThread(w, TestConcurrencyObserverEvent.onError, f1, f2, f3, f4)); + Future f18 = tp.submit(new CompletionThread(w, TestConcurrencyObserverEvent.onError, f1, f2, f3, f4)); + + waitOnThreads(f1, f2, f3, f4, f5, f6, f7, f8, f10, f11, f12, f13, f14, f15, f16, f17, f18); + @SuppressWarnings("unused") + int numNextEvents = tw.assertEvents(null); // no check of type since we don't want to test barging results here, just interleaving behavior + // System.out.println("Number of events executed: " + numNextEvents); + } catch (Throwable e) { + fail("Concurrency test failed: " + e.getMessage()); + e.printStackTrace(); + } finally { + tp.shutdown(); + try { + tp.awaitTermination(5000, TimeUnit.MILLISECONDS); + } catch (InterruptedException e) { + e.printStackTrace(); + } } - } - - return nextCount; } - } + private static void waitOnThreads(Future... futures) { + for (Future f : futures) { + try { + f.get(10, TimeUnit.SECONDS); + } catch (Throwable e) { + System.err.println("Failed while waiting on future."); + e.printStackTrace(); + } + } + } - /** - * This spawns a single thread for the subscribe execution - */ - private static class TestSingleThreadedObservable implements Observable.OnSubscribeFunc { + /** + * A thread that will pass data to onNext + */ + public static class OnNextThread implements Runnable { - final Subscription s; - final String[] values; - private Thread t = null; + private final Observer Observer; + private final int numStringsToSend; - public TestSingleThreadedObservable(final Subscription s, final String... values) { - this.s = s; - this.values = values; + OnNextThread(Observer Observer, int numStringsToSend) { + this.Observer = Observer; + this.numStringsToSend = numStringsToSend; + } + @Override + public void run() { + for (int i = 0; i < numStringsToSend; i++) { + Observer.onNext("aString"); + } + } } - public Subscription onSubscribe(final Observer observer) { - System.out.println("TestSingleThreadedObservable subscribed to ..."); - t = new Thread(new Runnable() { + /** + * A thread that will call onError or onNext + */ + public static class CompletionThread implements Runnable { + + private final Observer Observer; + private final TestConcurrencyObserverEvent event; + private final Future[] waitOnThese; + + CompletionThread(Observer Observer, TestConcurrencyObserverEvent event, Future... waitOnThese) { + this.Observer = Observer; + this.event = event; + this.waitOnThese = waitOnThese; + } @Override public void run() { - try { - System.out.println("running TestSingleThreadedObservable thread"); - for (String s : values) { - System.out.println("TestSingleThreadedObservable onNext: " + s); - observer.onNext(s); + /* if we have 'waitOnThese' futures, we'll wait on them before proceeding */ + if (waitOnThese != null) { + for (Future f : waitOnThese) { + try { + f.get(); + } catch (Throwable e) { + System.err.println("Error while waiting on future in CompletionThread"); + } + } + } + + /* send the event */ + if (event == TestConcurrencyObserverEvent.onError) { + Observer.onError(new RuntimeException("mocked exception")); + } else if (event == TestConcurrencyObserverEvent.onCompleted) { + Observer.onCompleted(); + + } else { + throw new IllegalArgumentException("Expecting either onError or onCompleted"); } - observer.onCompleted(); - } catch (Throwable e) { - throw new RuntimeException(e); - } } + } - }); - System.out.println("starting TestSingleThreadedObservable thread"); - t.start(); - System.out.println("done starting TestSingleThreadedObservable thread"); - return s; + private static enum TestConcurrencyObserverEvent { + onCompleted, onError, onNext } - public void waitToFinish() { - try { - t.join(); - } catch (InterruptedException e) { - throw new RuntimeException(e); - } + private static class TestConcurrencyObserver implements Observer { + + /** + * used to store the order and number of events received + */ + private final LinkedBlockingQueue events = new LinkedBlockingQueue(); + private final int waitTime; + + @SuppressWarnings("unused") + public TestConcurrencyObserver(int waitTimeInNext) { + this.waitTime = waitTimeInNext; + } + + public TestConcurrencyObserver() { + this.waitTime = 0; + } + + @Override + public void onCompleted() { + events.add(TestConcurrencyObserverEvent.onCompleted); + } + + @Override + public void onError(Throwable e) { + events.add(TestConcurrencyObserverEvent.onError); + } + + @Override + public void onNext(String args) { + events.add(TestConcurrencyObserverEvent.onNext); + // do some artificial work to make the thread scheduling/timing vary + int s = 0; + for (int i = 0; i < 20; i++) { + s += s * i; + } + + if (waitTime > 0) { + try { + Thread.sleep(waitTime); + } catch (InterruptedException e) { + // ignore + } + } + } + + /** + * Assert the order of events is correct and return the number of onNext executions. + * + * @param expectedEndingEvent + * @return int count of onNext calls + * @throws IllegalStateException + * If order of events was invalid. + */ + public int assertEvents(TestConcurrencyObserverEvent expectedEndingEvent) throws IllegalStateException { + int nextCount = 0; + boolean finished = false; + for (TestConcurrencyObserverEvent e : events) { + if (e == TestConcurrencyObserverEvent.onNext) { + if (finished) { + // already finished, we shouldn't get this again + throw new IllegalStateException("Received onNext but we're already finished."); + } + nextCount++; + } else if (e == TestConcurrencyObserverEvent.onError) { + if (finished) { + // already finished, we shouldn't get this again + throw new IllegalStateException("Received onError but we're already finished."); + } + if (expectedEndingEvent != null && TestConcurrencyObserverEvent.onError != expectedEndingEvent) { + throw new IllegalStateException("Received onError ending event but expected " + expectedEndingEvent); + } + finished = true; + } else if (e == TestConcurrencyObserverEvent.onCompleted) { + if (finished) { + // already finished, we shouldn't get this again + throw new IllegalStateException("Received onCompleted but we're already finished."); + } + if (expectedEndingEvent != null && TestConcurrencyObserverEvent.onCompleted != expectedEndingEvent) { + throw new IllegalStateException("Received onCompleted ending event but expected " + expectedEndingEvent); + } + finished = true; + } + } + + return nextCount; + } + } - } + /** + * This spawns a single thread for the subscribe execution + */ + private static class TestSingleThreadedObservable implements Observable.OnSubscribeFunc { + + final Subscription s; + final String[] values; + private Thread t = null; + + public TestSingleThreadedObservable(final Subscription s, final String... values) { + this.s = s; + this.values = values; + + } + + public Subscription onSubscribe(final Observer observer) { + System.out.println("TestSingleThreadedObservable subscribed to ..."); + t = new Thread(new Runnable() { + + @Override + public void run() { + try { + System.out.println("running TestSingleThreadedObservable thread"); + for (String s : values) { + System.out.println("TestSingleThreadedObservable onNext: " + s); + observer.onNext(s); + } + observer.onCompleted(); + } catch (Throwable e) { + throw new RuntimeException(e); + } + } - /** - * This spawns a thread for the subscription, then a separate thread for each onNext call. - */ - private static class TestMultiThreadedObservable implements Observable.OnSubscribeFunc { + }); + System.out.println("starting TestSingleThreadedObservable thread"); + t.start(); + System.out.println("done starting TestSingleThreadedObservable thread"); + return s; + } - final Subscription s; - final String[] values; - Thread t = null; - AtomicInteger threadsRunning = new AtomicInteger(); - AtomicInteger maxConcurrentThreads = new AtomicInteger(); - ExecutorService threadPool; + public void waitToFinish() { + try { + t.join(); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + } - public TestMultiThreadedObservable(Subscription s, String... values) { - this.s = s; - this.values = values; - this.threadPool = Executors.newCachedThreadPool(); } - @Override - public Subscription onSubscribe(final Observer observer) { - System.out.println("TestMultiThreadedObservable subscribed to ..."); - t = new Thread(new Runnable() { + /** + * This spawns a thread for the subscription, then a separate thread for each onNext call. + */ + private static class TestMultiThreadedObservable implements Observable.OnSubscribeFunc { + + final Subscription s; + final String[] values; + Thread t = null; + AtomicInteger threadsRunning = new AtomicInteger(); + AtomicInteger maxConcurrentThreads = new AtomicInteger(); + ExecutorService threadPool; + + public TestMultiThreadedObservable(Subscription s, String... values) { + this.s = s; + this.values = values; + this.threadPool = Executors.newCachedThreadPool(); + } @Override - public void run() { - try { - System.out.println("running TestMultiThreadedObservable thread"); - for (final String s : values) { - threadPool.execute(new Runnable() { + public Subscription onSubscribe(final Observer observer) { + System.out.println("TestMultiThreadedObservable subscribed to ..."); + t = new Thread(new Runnable() { @Override public void run() { - threadsRunning.incrementAndGet(); - try { - // perform onNext call - System.out.println("TestMultiThreadedObservable onNext: " + s); - if (s == null) { - // force an error - throw new NullPointerException(); + try { + System.out.println("running TestMultiThreadedObservable thread"); + for (final String s : values) { + threadPool.execute(new Runnable() { + + @Override + public void run() { + threadsRunning.incrementAndGet(); + try { + // perform onNext call + System.out.println("TestMultiThreadedObservable onNext: " + s); + if (s == null) { + // force an error + throw new NullPointerException(); + } + observer.onNext(s); + // capture 'maxThreads' + int concurrentThreads = threadsRunning.get(); + int maxThreads = maxConcurrentThreads.get(); + if (concurrentThreads > maxThreads) { + maxConcurrentThreads.compareAndSet(maxThreads, concurrentThreads); + } + } catch (Throwable e) { + observer.onError(e); + } finally { + threadsRunning.decrementAndGet(); + } + } + }); + } + // we are done spawning threads + threadPool.shutdown(); + } catch (Throwable e) { + throw new RuntimeException(e); } - observer.onNext(s); - // capture 'maxThreads' - int concurrentThreads = threadsRunning.get(); - int maxThreads = maxConcurrentThreads.get(); - if (concurrentThreads > maxThreads) { - maxConcurrentThreads.compareAndSet(maxThreads, concurrentThreads); + + // wait until all threads are done, then mark it as COMPLETED + try { + // wait for all the threads to finish + threadPool.awaitTermination(2, TimeUnit.SECONDS); + } catch (InterruptedException e) { + throw new RuntimeException(e); } - } catch (Throwable e) { - observer.onError(e); - } finally { - threadsRunning.decrementAndGet(); - } + observer.onCompleted(); } - }); + }); + System.out.println("starting TestMultiThreadedObservable thread"); + t.start(); + System.out.println("done starting TestMultiThreadedObservable thread"); + return s; + } + + public void waitToFinish() { + try { + t.join(); + } catch (InterruptedException e) { + throw new RuntimeException(e); } - // we are done spawning threads - threadPool.shutdown(); - } catch (Throwable e) { - throw new RuntimeException(e); - } - - // wait until all threads are done, then mark it as COMPLETED - try { - // wait for all the threads to finish - threadPool.awaitTermination(2, TimeUnit.SECONDS); - } catch (InterruptedException e) { - throw new RuntimeException(e); - } - observer.onCompleted(); } - }); - System.out.println("starting TestMultiThreadedObservable thread"); - t.start(); - System.out.println("done starting TestMultiThreadedObservable thread"); - return s; } - public void waitToFinish() { - try { - t.join(); - } catch (InterruptedException e) { - throw new RuntimeException(e); - } - } - } - - private static class BusyObserver implements Observer { - volatile boolean onCompleted = false; - volatile boolean onError = false; - AtomicInteger onNextCount = new AtomicInteger(); - AtomicInteger threadsRunning = new AtomicInteger(); - AtomicInteger maxConcurrentThreads = new AtomicInteger(); - - @Override - public void onCompleted() { - threadsRunning.incrementAndGet(); - - System.out.println(">>> BusyObserver received onCompleted"); - onCompleted = true; - - int concurrentThreads = threadsRunning.get(); - int maxThreads = maxConcurrentThreads.get(); - if (concurrentThreads > maxThreads) { - maxConcurrentThreads.compareAndSet(maxThreads, concurrentThreads); - } - threadsRunning.decrementAndGet(); - } + private static class BusyObserver implements Observer { + volatile boolean onCompleted = false; + volatile boolean onError = false; + AtomicInteger onNextCount = new AtomicInteger(); + AtomicInteger threadsRunning = new AtomicInteger(); + AtomicInteger maxConcurrentThreads = new AtomicInteger(); - @Override - public void onError(Throwable e) { - threadsRunning.incrementAndGet(); + @Override + public void onCompleted() { + threadsRunning.incrementAndGet(); - System.out.println(">>> BusyObserver received onError: " + e.getMessage()); - onError = true; + System.out.println(">>> BusyObserver received onCompleted"); + onCompleted = true; - int concurrentThreads = threadsRunning.get(); - int maxThreads = maxConcurrentThreads.get(); - if (concurrentThreads > maxThreads) { - maxConcurrentThreads.compareAndSet(maxThreads, concurrentThreads); - } - threadsRunning.decrementAndGet(); - } + int concurrentThreads = threadsRunning.get(); + int maxThreads = maxConcurrentThreads.get(); + if (concurrentThreads > maxThreads) { + maxConcurrentThreads.compareAndSet(maxThreads, concurrentThreads); + } + threadsRunning.decrementAndGet(); + } - @Override - public void onNext(String args) { - threadsRunning.incrementAndGet(); - try { - onNextCount.incrementAndGet(); - System.out.println(">>> BusyObserver received onNext: " + args); - try { - // simulate doing something computational - Thread.sleep(200); - } catch (InterruptedException e) { - e.printStackTrace(); + @Override + public void onError(Throwable e) { + threadsRunning.incrementAndGet(); + + System.out.println(">>> BusyObserver received onError: " + e.getMessage()); + onError = true; + + int concurrentThreads = threadsRunning.get(); + int maxThreads = maxConcurrentThreads.get(); + if (concurrentThreads > maxThreads) { + maxConcurrentThreads.compareAndSet(maxThreads, concurrentThreads); + } + threadsRunning.decrementAndGet(); } - } finally { - // capture 'maxThreads' - int concurrentThreads = threadsRunning.get(); - int maxThreads = maxConcurrentThreads.get(); - if (concurrentThreads > maxThreads) { - maxConcurrentThreads.compareAndSet(maxThreads, concurrentThreads); + + @Override + public void onNext(String args) { + threadsRunning.incrementAndGet(); + try { + onNextCount.incrementAndGet(); + System.out.println(">>> BusyObserver received onNext: " + args); + try { + // simulate doing something computational + Thread.sleep(200); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } finally { + // capture 'maxThreads' + int concurrentThreads = threadsRunning.get(); + int maxThreads = maxConcurrentThreads.get(); + if (concurrentThreads > maxThreads) { + maxConcurrentThreads.compareAndSet(maxThreads, concurrentThreads); + } + threadsRunning.decrementAndGet(); + } } - threadsRunning.decrementAndGet(); - } - } - } + } - private static class ExternalBusyThread extends Thread { + private static class ExternalBusyThread extends Thread { - private BusyObserver observer; - private Object lock; - private int lockTimes; - private int waitTime; - public volatile boolean fail; + private BusyObserver observer; + private Object lock; + private int lockTimes; + private int waitTime; + public volatile boolean fail; - public ExternalBusyThread(BusyObserver observer, Object lock, int lockTimes, int waitTime) { - this.observer = observer; - this.lock = lock; - this.lockTimes = lockTimes; - this.waitTime = waitTime; - this.fail = false; - } + public ExternalBusyThread(BusyObserver observer, Object lock, int lockTimes, int waitTime) { + this.observer = observer; + this.lock = lock; + this.lockTimes = lockTimes; + this.waitTime = waitTime; + this.fail = false; + } - @Override - public void run() { - Random r = new Random(); - for (int i = 0; i < lockTimes; i++) { - synchronized (lock) { - int oldOnNextCount = observer.onNextCount.get(); - boolean oldOnCompleted = observer.onCompleted; - boolean oldOnError = observer.onError; - try { - Thread.sleep(r.nextInt(waitTime)); - } catch (InterruptedException e) { - // ignore - } - // Since we own the lock, onNextCount, onCompleted and - // onError must not be changed. - int newOnNextCount = observer.onNextCount.get(); - boolean newOnCompleted = observer.onCompleted; - boolean newOnError = observer.onError; - if (oldOnNextCount != newOnNextCount) { - System.out.println(">>> ExternalBusyThread received different onNextCount: " - + oldOnNextCount - + " -> " - + newOnNextCount); - fail = true; - break; - } - if (oldOnCompleted != newOnCompleted) { - System.out.println(">>> ExternalBusyThread received different onCompleted: " - + oldOnCompleted - + " -> " - + newOnCompleted); - fail = true; - break; - } - if (oldOnError != newOnError) { - System.out.println(">>> ExternalBusyThread received different onError: " - + oldOnError - + " -> " - + newOnError); - fail = true; - break; - } + @Override + public void run() { + Random r = new Random(); + for (int i = 0; i < lockTimes; i++) { + synchronized (lock) { + int oldOnNextCount = observer.onNextCount.get(); + boolean oldOnCompleted = observer.onCompleted; + boolean oldOnError = observer.onError; + try { + Thread.sleep(r.nextInt(waitTime)); + } catch (InterruptedException e) { + // ignore + } + // Since we own the lock, onNextCount, onCompleted and + // onError must not be changed. + int newOnNextCount = observer.onNextCount.get(); + boolean newOnCompleted = observer.onCompleted; + boolean newOnError = observer.onError; + if (oldOnNextCount != newOnNextCount) { + System.out.println(">>> ExternalBusyThread received different onNextCount: " + + oldOnNextCount + + " -> " + + newOnNextCount); + fail = true; + break; + } + if (oldOnCompleted != newOnCompleted) { + System.out.println(">>> ExternalBusyThread received different onCompleted: " + + oldOnCompleted + + " -> " + + newOnCompleted); + fail = true; + break; + } + if (oldOnError != newOnError) { + System.out.println(">>> ExternalBusyThread received different onError: " + + oldOnError + + " -> " + + newOnError); + fail = true; + break; + } + } + } } - } - } - } + } } diff --git a/rxjava-core/src/test/java/rx/plugins/RxJavaPluginsTest.java b/rxjava-core/src/test/java/rx/plugins/RxJavaPluginsTest.java index 3ea17bf152..94c4fdcc0d 100644 --- a/rxjava-core/src/test/java/rx/plugins/RxJavaPluginsTest.java +++ b/rxjava-core/src/test/java/rx/plugins/RxJavaPluginsTest.java @@ -1,77 +1,77 @@ package rx.plugins; -import org.junit.Test; +import static org.junit.Assert.*; -import static org.junit.Assert.assertTrue; +import org.junit.Test; public class RxJavaPluginsTest { - @Test - public void testErrorHandlerDefaultImpl() { - RxJavaErrorHandler impl = new RxJavaPlugins().getErrorHandler(); - assertTrue(impl instanceof RxJavaErrorHandlerDefault); - } + @Test + public void testErrorHandlerDefaultImpl() { + RxJavaErrorHandler impl = new RxJavaPlugins().getErrorHandler(); + assertTrue(impl instanceof RxJavaErrorHandlerDefault); + } - @Test - public void testErrorHandlerViaRegisterMethod() { - RxJavaPlugins p = new RxJavaPlugins(); - p.registerErrorHandler(new RxJavaErrorHandlerTestImpl()); - RxJavaErrorHandler impl = p.getErrorHandler(); - assertTrue(impl instanceof RxJavaErrorHandlerTestImpl); - } + @Test + public void testErrorHandlerViaRegisterMethod() { + RxJavaPlugins p = new RxJavaPlugins(); + p.registerErrorHandler(new RxJavaErrorHandlerTestImpl()); + RxJavaErrorHandler impl = p.getErrorHandler(); + assertTrue(impl instanceof RxJavaErrorHandlerTestImpl); + } - @Test - public void testErrorHandlerViaProperty() { - try { - RxJavaPlugins p = new RxJavaPlugins(); - String fullClass = getFullClassNameForTestClass(RxJavaErrorHandlerTestImpl.class); - System.setProperty("rxjava.plugin.RxJavaErrorHandler.implementation", fullClass); - RxJavaErrorHandler impl = p.getErrorHandler(); - assertTrue(impl instanceof RxJavaErrorHandlerTestImpl); - } finally { - System.clearProperty("rxjava.plugin.RxJavaErrorHandler.implementation"); + @Test + public void testErrorHandlerViaProperty() { + try { + RxJavaPlugins p = new RxJavaPlugins(); + String fullClass = getFullClassNameForTestClass(RxJavaErrorHandlerTestImpl.class); + System.setProperty("rxjava.plugin.RxJavaErrorHandler.implementation", fullClass); + RxJavaErrorHandler impl = p.getErrorHandler(); + assertTrue(impl instanceof RxJavaErrorHandlerTestImpl); + } finally { + System.clearProperty("rxjava.plugin.RxJavaErrorHandler.implementation"); + } } - } - // inside test so it is stripped from Javadocs - public static class RxJavaErrorHandlerTestImpl extends RxJavaErrorHandler { - // just use defaults - } + // inside test so it is stripped from Javadocs + public static class RxJavaErrorHandlerTestImpl extends RxJavaErrorHandler { + // just use defaults + } - @Test - public void testObservableExecutionHookDefaultImpl() { - RxJavaPlugins p = new RxJavaPlugins(); - RxJavaObservableExecutionHook impl = p.getObservableExecutionHook(); - assertTrue(impl instanceof RxJavaObservableExecutionHookDefault); - } + @Test + public void testObservableExecutionHookDefaultImpl() { + RxJavaPlugins p = new RxJavaPlugins(); + RxJavaObservableExecutionHook impl = p.getObservableExecutionHook(); + assertTrue(impl instanceof RxJavaObservableExecutionHookDefault); + } - @Test - public void testObservableExecutionHookViaRegisterMethod() { - RxJavaPlugins p = new RxJavaPlugins(); - p.registerObservableExecutionHook(new RxJavaObservableExecutionHookTestImpl()); - RxJavaObservableExecutionHook impl = p.getObservableExecutionHook(); - assertTrue(impl instanceof RxJavaObservableExecutionHookTestImpl); - } + @Test + public void testObservableExecutionHookViaRegisterMethod() { + RxJavaPlugins p = new RxJavaPlugins(); + p.registerObservableExecutionHook(new RxJavaObservableExecutionHookTestImpl()); + RxJavaObservableExecutionHook impl = p.getObservableExecutionHook(); + assertTrue(impl instanceof RxJavaObservableExecutionHookTestImpl); + } - @Test - public void testObservableExecutionHookViaProperty() { - try { - RxJavaPlugins p = new RxJavaPlugins(); - String fullClass = getFullClassNameForTestClass(RxJavaObservableExecutionHookTestImpl.class); - System.setProperty("rxjava.plugin.RxJavaObservableExecutionHook.implementation", fullClass); - RxJavaObservableExecutionHook impl = p.getObservableExecutionHook(); - assertTrue(impl instanceof RxJavaObservableExecutionHookTestImpl); - } finally { - System.clearProperty("rxjava.plugin.RxJavaObservableExecutionHook.implementation"); + @Test + public void testObservableExecutionHookViaProperty() { + try { + RxJavaPlugins p = new RxJavaPlugins(); + String fullClass = getFullClassNameForTestClass(RxJavaObservableExecutionHookTestImpl.class); + System.setProperty("rxjava.plugin.RxJavaObservableExecutionHook.implementation", fullClass); + RxJavaObservableExecutionHook impl = p.getObservableExecutionHook(); + assertTrue(impl instanceof RxJavaObservableExecutionHookTestImpl); + } finally { + System.clearProperty("rxjava.plugin.RxJavaObservableExecutionHook.implementation"); + } } - } - // inside test so it is stripped from Javadocs - public static class RxJavaObservableExecutionHookTestImpl extends RxJavaObservableExecutionHook { - // just use defaults - } + // inside test so it is stripped from Javadocs + public static class RxJavaObservableExecutionHookTestImpl extends RxJavaObservableExecutionHook { + // just use defaults + } - private static String getFullClassNameForTestClass(Class cls) { - return RxJavaPlugins.class.getPackage().getName() + "." + RxJavaPluginsTest.class.getSimpleName() + "$" + cls.getSimpleName(); - } + private static String getFullClassNameForTestClass(Class cls) { + return RxJavaPlugins.class.getPackage().getName() + "." + RxJavaPluginsTest.class.getSimpleName() + "$" + cls.getSimpleName(); + } } diff --git a/rxjava-core/src/test/java/rx/subjects/AsyncSubjectTest.java b/rxjava-core/src/test/java/rx/subjects/AsyncSubjectTest.java index fb5220640b..243dda02bf 100644 --- a/rxjava-core/src/test/java/rx/subjects/AsyncSubjectTest.java +++ b/rxjava-core/src/test/java/rx/subjects/AsyncSubjectTest.java @@ -1,135 +1,134 @@ package rx.subjects; +import static org.mockito.Matchers.*; +import static org.mockito.Mockito.*; + import org.junit.Test; import org.mockito.Mockito; + import rx.Observer; import rx.Subscription; import rx.util.functions.Action1; import rx.util.functions.Func0; -import static org.mockito.Matchers.any; -import static org.mockito.Matchers.anyString; -import static org.mockito.Mockito.*; - public class AsyncSubjectTest { - - private final Throwable testException = new Throwable(); - - @Test - public void testNeverCompleted() { - AsyncSubject subject = AsyncSubject.create(); - - @SuppressWarnings("unchecked") - Observer aObserver = mock(Observer.class); - subject.subscribe(aObserver); - - subject.onNext("one"); - subject.onNext("two"); - subject.onNext("three"); - - assertNeverCompletedObserver(aObserver); - } - - private void assertNeverCompletedObserver(Observer aObserver) { - verify(aObserver, Mockito.never()).onNext(anyString()); - verify(aObserver, Mockito.never()).onError(testException); - verify(aObserver, Mockito.never()).onCompleted(); - } - - @Test - public void testCompleted() { - AsyncSubject subject = AsyncSubject.create(); - - @SuppressWarnings("unchecked") - Observer aObserver = mock(Observer.class); - subject.subscribe(aObserver); - - subject.onNext("one"); - subject.onNext("two"); - subject.onNext("three"); - subject.onCompleted(); - - assertCompletedObserver(aObserver); - } - - private void assertCompletedObserver(Observer aObserver) { - verify(aObserver, times(1)).onNext("three"); - verify(aObserver, Mockito.never()).onError(any(Throwable.class)); - verify(aObserver, times(1)).onCompleted(); - } - - @Test - public void testError() { - AsyncSubject subject = AsyncSubject.create(); - - @SuppressWarnings("unchecked") - Observer aObserver = mock(Observer.class); - subject.subscribe(aObserver); - - subject.onNext("one"); - subject.onNext("two"); - subject.onNext("three"); - subject.onError(testException); - subject.onNext("four"); - subject.onError(new Throwable()); - subject.onCompleted(); - - assertErrorObserver(aObserver); - } - - private void assertErrorObserver(Observer aObserver) { - verify(aObserver, Mockito.never()).onNext(anyString()); - verify(aObserver, times(1)).onError(testException); - verify(aObserver, Mockito.never()).onCompleted(); - } - - @Test - public void testUnsubscribeBeforeCompleted() { - AsyncSubject subject = AsyncSubject.create(); - - @SuppressWarnings("unchecked") - Observer aObserver = mock(Observer.class); - Subscription subscription = subject.subscribe(aObserver); - - subject.onNext("one"); - subject.onNext("two"); - - subscription.unsubscribe(); - assertNoOnNextEventsReceived(aObserver); - - subject.onNext("three"); - subject.onCompleted(); - - assertNoOnNextEventsReceived(aObserver); - } - - private void assertNoOnNextEventsReceived(Observer aObserver) { - verify(aObserver, Mockito.never()).onNext(anyString()); - verify(aObserver, Mockito.never()).onError(any(Throwable.class)); - verify(aObserver, Mockito.never()).onCompleted(); - } - - @Test - public void testUnsubscribe() { - UnsubscribeTester.test( - new Func0>() { - @Override - public AsyncSubject call() { - return AsyncSubject.create(); - } - }, new Action1>() { - @Override - public void call(AsyncSubject DefaultSubject) { - DefaultSubject.onCompleted(); - } - }, new Action1>() { - @Override - public void call(AsyncSubject DefaultSubject) { - DefaultSubject.onError(new Throwable()); - } - }, - null - ); - } + private final Throwable testException = new Throwable(); + + @Test + public void testNeverCompleted() { + AsyncSubject subject = AsyncSubject.create(); + + @SuppressWarnings("unchecked") + Observer aObserver = mock(Observer.class); + subject.subscribe(aObserver); + + subject.onNext("one"); + subject.onNext("two"); + subject.onNext("three"); + + assertNeverCompletedObserver(aObserver); + } + + private void assertNeverCompletedObserver(Observer aObserver) { + verify(aObserver, Mockito.never()).onNext(anyString()); + verify(aObserver, Mockito.never()).onError(testException); + verify(aObserver, Mockito.never()).onCompleted(); + } + + @Test + public void testCompleted() { + AsyncSubject subject = AsyncSubject.create(); + + @SuppressWarnings("unchecked") + Observer aObserver = mock(Observer.class); + subject.subscribe(aObserver); + + subject.onNext("one"); + subject.onNext("two"); + subject.onNext("three"); + subject.onCompleted(); + + assertCompletedObserver(aObserver); + } + + private void assertCompletedObserver(Observer aObserver) { + verify(aObserver, times(1)).onNext("three"); + verify(aObserver, Mockito.never()).onError(any(Throwable.class)); + verify(aObserver, times(1)).onCompleted(); + } + + @Test + public void testError() { + AsyncSubject subject = AsyncSubject.create(); + + @SuppressWarnings("unchecked") + Observer aObserver = mock(Observer.class); + subject.subscribe(aObserver); + + subject.onNext("one"); + subject.onNext("two"); + subject.onNext("three"); + subject.onError(testException); + subject.onNext("four"); + subject.onError(new Throwable()); + subject.onCompleted(); + + assertErrorObserver(aObserver); + } + + private void assertErrorObserver(Observer aObserver) { + verify(aObserver, Mockito.never()).onNext(anyString()); + verify(aObserver, times(1)).onError(testException); + verify(aObserver, Mockito.never()).onCompleted(); + } + + @Test + public void testUnsubscribeBeforeCompleted() { + AsyncSubject subject = AsyncSubject.create(); + + @SuppressWarnings("unchecked") + Observer aObserver = mock(Observer.class); + Subscription subscription = subject.subscribe(aObserver); + + subject.onNext("one"); + subject.onNext("two"); + + subscription.unsubscribe(); + assertNoOnNextEventsReceived(aObserver); + + subject.onNext("three"); + subject.onCompleted(); + + assertNoOnNextEventsReceived(aObserver); + } + + private void assertNoOnNextEventsReceived(Observer aObserver) { + verify(aObserver, Mockito.never()).onNext(anyString()); + verify(aObserver, Mockito.never()).onError(any(Throwable.class)); + verify(aObserver, Mockito.never()).onCompleted(); + } + + @Test + public void testUnsubscribe() { + UnsubscribeTester.test( + new Func0>() { + @Override + public AsyncSubject call() { + return AsyncSubject.create(); + } + }, new Action1>() { + @Override + public void call(AsyncSubject DefaultSubject) { + DefaultSubject.onCompleted(); + } + }, new Action1>() { + @Override + public void call(AsyncSubject DefaultSubject) { + DefaultSubject.onError(new Throwable()); + } + }, + null + ); + } } diff --git a/rxjava-core/src/test/java/rx/subjects/BehaviorSubjectTest.java b/rxjava-core/src/test/java/rx/subjects/BehaviorSubjectTest.java index eae3ffbc06..8c7a52f61d 100644 --- a/rxjava-core/src/test/java/rx/subjects/BehaviorSubjectTest.java +++ b/rxjava-core/src/test/java/rx/subjects/BehaviorSubjectTest.java @@ -1,135 +1,135 @@ package rx.subjects; +import static org.mockito.Matchers.*; +import static org.mockito.Mockito.*; + import org.junit.Test; import org.mockito.Mockito; + import rx.Observer; import rx.util.functions.Action1; import rx.util.functions.Func0; -import static org.mockito.Matchers.any; -import static org.mockito.Mockito.*; - public class BehaviorSubjectTest { - - private final Throwable testException = new Throwable(); - - @Test - public void testThatObserverReceivesDefaultValueIfNothingWasPublished() { - BehaviorSubject subject = BehaviorSubject.createWithDefaultValue("default"); - - @SuppressWarnings("unchecked") - Observer aObserver = mock(Observer.class); - subject.subscribe(aObserver); - - subject.onNext("one"); - subject.onNext("two"); - subject.onNext("three"); - - assertReceivedAllEvents(aObserver); - } - - private void assertReceivedAllEvents(Observer aObserver) { - verify(aObserver, times(1)).onNext("default"); - verify(aObserver, times(1)).onNext("one"); - verify(aObserver, times(1)).onNext("two"); - verify(aObserver, times(1)).onNext("three"); - verify(aObserver, Mockito.never()).onError(testException); - verify(aObserver, Mockito.never()).onCompleted(); - } - - @Test - public void testThatObserverDoesNotReceiveDefaultValueIfSomethingWasPublished() { - BehaviorSubject subject = BehaviorSubject.createWithDefaultValue("default"); - - subject.onNext("one"); - - @SuppressWarnings("unchecked") - Observer aObserver = mock(Observer.class); - subject.subscribe(aObserver); - - subject.onNext("two"); - subject.onNext("three"); - - assertDidNotReceiveTheDefaultValue(aObserver); - } - - private void assertDidNotReceiveTheDefaultValue(Observer aObserver) { - verify(aObserver, Mockito.never()).onNext("default"); - verify(aObserver, times(1)).onNext("one"); - verify(aObserver, times(1)).onNext("two"); - verify(aObserver, times(1)).onNext("three"); - verify(aObserver, Mockito.never()).onError(testException); - verify(aObserver, Mockito.never()).onCompleted(); - } - - @Test - public void testCompleted() { - BehaviorSubject subject = BehaviorSubject.createWithDefaultValue("default"); - - @SuppressWarnings("unchecked") - Observer aObserver = mock(Observer.class); - subject.subscribe(aObserver); - - subject.onNext("one"); - subject.onCompleted(); - - assertCompletedObserver(aObserver); - } - - private void assertCompletedObserver(Observer aObserver) { - verify(aObserver, times(1)).onNext("default"); - verify(aObserver, times(1)).onNext("one"); - verify(aObserver, Mockito.never()).onError(any(Throwable.class)); - verify(aObserver, times(1)).onCompleted(); - } - - @Test - public void testCompletedAfterError() { - BehaviorSubject subject = BehaviorSubject.createWithDefaultValue("default"); - - @SuppressWarnings("unchecked") - Observer aObserver = mock(Observer.class); - subject.subscribe(aObserver); - - subject.onNext("one"); - subject.onError(testException); - subject.onNext("two"); - subject.onCompleted(); - - assertErrorObserver(aObserver); - } - - private void assertErrorObserver(Observer aObserver) { - verify(aObserver, times(1)).onNext("default"); - verify(aObserver, times(1)).onNext("one"); - verify(aObserver, times(1)).onError(testException); - } - - @Test - public void testUnsubscribe() { - UnsubscribeTester.test( - new Func0>() { - @Override - public BehaviorSubject call() { - return BehaviorSubject.createWithDefaultValue("default"); - } - }, new Action1>() { - @Override - public void call(BehaviorSubject DefaultSubject) { - DefaultSubject.onCompleted(); - } - }, new Action1>() { - @Override - public void call(BehaviorSubject DefaultSubject) { - DefaultSubject.onError(new Throwable()); - } - }, new Action1>() { - @Override - public void call(BehaviorSubject DefaultSubject) { - DefaultSubject.onNext("one"); - } - } - ); - } + private final Throwable testException = new Throwable(); + + @Test + public void testThatObserverReceivesDefaultValueIfNothingWasPublished() { + BehaviorSubject subject = BehaviorSubject.createWithDefaultValue("default"); + + @SuppressWarnings("unchecked") + Observer aObserver = mock(Observer.class); + subject.subscribe(aObserver); + + subject.onNext("one"); + subject.onNext("two"); + subject.onNext("three"); + + assertReceivedAllEvents(aObserver); + } + + private void assertReceivedAllEvents(Observer aObserver) { + verify(aObserver, times(1)).onNext("default"); + verify(aObserver, times(1)).onNext("one"); + verify(aObserver, times(1)).onNext("two"); + verify(aObserver, times(1)).onNext("three"); + verify(aObserver, Mockito.never()).onError(testException); + verify(aObserver, Mockito.never()).onCompleted(); + } + + @Test + public void testThatObserverDoesNotReceiveDefaultValueIfSomethingWasPublished() { + BehaviorSubject subject = BehaviorSubject.createWithDefaultValue("default"); + + subject.onNext("one"); + + @SuppressWarnings("unchecked") + Observer aObserver = mock(Observer.class); + subject.subscribe(aObserver); + + subject.onNext("two"); + subject.onNext("three"); + + assertDidNotReceiveTheDefaultValue(aObserver); + } + + private void assertDidNotReceiveTheDefaultValue(Observer aObserver) { + verify(aObserver, Mockito.never()).onNext("default"); + verify(aObserver, times(1)).onNext("one"); + verify(aObserver, times(1)).onNext("two"); + verify(aObserver, times(1)).onNext("three"); + verify(aObserver, Mockito.never()).onError(testException); + verify(aObserver, Mockito.never()).onCompleted(); + } + + @Test + public void testCompleted() { + BehaviorSubject subject = BehaviorSubject.createWithDefaultValue("default"); + + @SuppressWarnings("unchecked") + Observer aObserver = mock(Observer.class); + subject.subscribe(aObserver); + + subject.onNext("one"); + subject.onCompleted(); + + assertCompletedObserver(aObserver); + } + + private void assertCompletedObserver(Observer aObserver) { + verify(aObserver, times(1)).onNext("default"); + verify(aObserver, times(1)).onNext("one"); + verify(aObserver, Mockito.never()).onError(any(Throwable.class)); + verify(aObserver, times(1)).onCompleted(); + } + + @Test + public void testCompletedAfterError() { + BehaviorSubject subject = BehaviorSubject.createWithDefaultValue("default"); + + @SuppressWarnings("unchecked") + Observer aObserver = mock(Observer.class); + subject.subscribe(aObserver); + + subject.onNext("one"); + subject.onError(testException); + subject.onNext("two"); + subject.onCompleted(); + + assertErrorObserver(aObserver); + } + + private void assertErrorObserver(Observer aObserver) { + verify(aObserver, times(1)).onNext("default"); + verify(aObserver, times(1)).onNext("one"); + verify(aObserver, times(1)).onError(testException); + } + + @Test + public void testUnsubscribe() { + UnsubscribeTester.test( + new Func0>() { + @Override + public BehaviorSubject call() { + return BehaviorSubject.createWithDefaultValue("default"); + } + }, new Action1>() { + @Override + public void call(BehaviorSubject DefaultSubject) { + DefaultSubject.onCompleted(); + } + }, new Action1>() { + @Override + public void call(BehaviorSubject DefaultSubject) { + DefaultSubject.onError(new Throwable()); + } + }, new Action1>() { + @Override + public void call(BehaviorSubject DefaultSubject) { + DefaultSubject.onNext("one"); + } + } + ); + } } diff --git a/rxjava-core/src/test/java/rx/subjects/PublishSubjectTest.java b/rxjava-core/src/test/java/rx/subjects/PublishSubjectTest.java index da6abf7c44..9c2ca321ee 100644 --- a/rxjava-core/src/test/java/rx/subjects/PublishSubjectTest.java +++ b/rxjava-core/src/test/java/rx/subjects/PublishSubjectTest.java @@ -1,9 +1,21 @@ package rx.subjects; +import static org.junit.Assert.*; +import static org.mockito.Matchers.*; +import static org.mockito.Mockito.*; + +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.atomic.AtomicReference; + import junit.framework.Assert; + import org.junit.Test; import org.mockito.InOrder; import org.mockito.Mockito; + import rx.Notification; import rx.Observable; import rx.Observer; @@ -12,353 +24,343 @@ import rx.util.functions.Func0; import rx.util.functions.Func1; -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.atomic.AtomicBoolean; -import java.util.concurrent.atomic.AtomicInteger; -import java.util.concurrent.atomic.AtomicReference; +public class PublishSubjectTest { -import static org.junit.Assert.assertEquals; -import static org.mockito.Matchers.any; -import static org.mockito.Mockito.*; + @Test + public void test() { + PublishSubject subject = PublishSubject.create(); + final AtomicReference>> actualRef = new AtomicReference>>(); -public class PublishSubjectTest { + Observable>> wNotificationsList = subject.materialize().toList(); + wNotificationsList.subscribe(new Action1>>() { + @Override + public void call(List> actual) { + actualRef.set(actual); + } + }); - @Test - public void test() { - PublishSubject subject = PublishSubject.create(); - final AtomicReference>> actualRef = new AtomicReference>>(); - - Observable>> wNotificationsList = subject.materialize().toList(); - wNotificationsList.subscribe(new Action1>>() { - @Override - public void call(List> actual) { - actualRef.set(actual); - } - }); - - Subscription sub = Observable.create(new Observable.OnSubscribeFunc() { - @Override - public Subscription onSubscribe(final Observer observer) { - final AtomicBoolean stop = new AtomicBoolean(false); - new Thread() { - @Override - public void run() { - int i = 1; - while (!stop.get()) { - observer.onNext(i++); + Subscription sub = Observable.create(new Observable.OnSubscribeFunc() { + @Override + public Subscription onSubscribe(final Observer observer) { + final AtomicBoolean stop = new AtomicBoolean(false); + new Thread() { + @Override + public void run() { + int i = 1; + while (!stop.get()) { + observer.onNext(i++); + } + observer.onCompleted(); + } + }.start(); + return new Subscription() { + @Override + public void unsubscribe() { + stop.set(true); + } + }; } - observer.onCompleted(); - } - }.start(); - return new Subscription() { - @Override - public void unsubscribe() { - stop.set(true); - } - }; - } - }).subscribe(subject); - // the subject has received an onComplete from the first subscribe because - // it is synchronous and the next subscribe won't do anything. - Observable.from(-1, -2, -3).subscribe(subject); - - List> expected = new ArrayList>(); - expected.add(new Notification(-1)); - expected.add(new Notification(-2)); - expected.add(new Notification(-3)); - expected.add(new Notification()); - Assert.assertTrue(actualRef.get().containsAll(expected)); - - sub.unsubscribe(); - } - - private final Throwable testException = new Throwable(); - - @Test - public void testCompleted() { - PublishSubject subject = PublishSubject.create(); - - @SuppressWarnings("unchecked") - Observer aObserver = mock(Observer.class); - subject.subscribe(aObserver); - - subject.onNext("one"); - subject.onNext("two"); - subject.onNext("three"); - subject.onCompleted(); - - @SuppressWarnings("unchecked") - Observer anotherObserver = mock(Observer.class); - subject.subscribe(anotherObserver); - - subject.onNext("four"); - subject.onCompleted(); - subject.onError(new Throwable()); - - assertCompletedObserver(aObserver); - // todo bug? assertNeverObserver(anotherObserver); - } - - private void assertCompletedObserver(Observer aObserver) { - verify(aObserver, times(1)).onNext("one"); - verify(aObserver, times(1)).onNext("two"); - verify(aObserver, times(1)).onNext("three"); - verify(aObserver, Mockito.never()).onError(any(Throwable.class)); - verify(aObserver, times(1)).onCompleted(); - } - - @Test - public void testError() { - PublishSubject subject = PublishSubject.create(); - - @SuppressWarnings("unchecked") - Observer aObserver = mock(Observer.class); - subject.subscribe(aObserver); - - subject.onNext("one"); - subject.onNext("two"); - subject.onNext("three"); - subject.onError(testException); - - @SuppressWarnings("unchecked") - Observer anotherObserver = mock(Observer.class); - subject.subscribe(anotherObserver); - - subject.onNext("four"); - subject.onError(new Throwable()); - subject.onCompleted(); - - assertErrorObserver(aObserver); - // todo bug? assertNeverObserver(anotherObserver); - } - - private void assertErrorObserver(Observer aObserver) { - verify(aObserver, times(1)).onNext("one"); - verify(aObserver, times(1)).onNext("two"); - verify(aObserver, times(1)).onNext("three"); - verify(aObserver, times(1)).onError(testException); - verify(aObserver, Mockito.never()).onCompleted(); - } - - @Test - public void testSubscribeMidSequence() { - PublishSubject subject = PublishSubject.create(); - - @SuppressWarnings("unchecked") - Observer aObserver = mock(Observer.class); - subject.subscribe(aObserver); - - subject.onNext("one"); - subject.onNext("two"); - - assertObservedUntilTwo(aObserver); - - @SuppressWarnings("unchecked") - Observer anotherObserver = mock(Observer.class); - subject.subscribe(anotherObserver); - - subject.onNext("three"); - subject.onCompleted(); - - assertCompletedObserver(aObserver); - assertCompletedStartingWithThreeObserver(anotherObserver); - } - - private void assertCompletedStartingWithThreeObserver(Observer aObserver) { - verify(aObserver, Mockito.never()).onNext("one"); - verify(aObserver, Mockito.never()).onNext("two"); - verify(aObserver, times(1)).onNext("three"); - verify(aObserver, Mockito.never()).onError(any(Throwable.class)); - verify(aObserver, times(1)).onCompleted(); - } - - @Test - public void testUnsubscribeFirstObserver() { - PublishSubject subject = PublishSubject.create(); - - @SuppressWarnings("unchecked") - Observer aObserver = mock(Observer.class); - Subscription subscription = subject.subscribe(aObserver); - - subject.onNext("one"); - subject.onNext("two"); - - subscription.unsubscribe(); - assertObservedUntilTwo(aObserver); - - @SuppressWarnings("unchecked") - Observer anotherObserver = mock(Observer.class); - subject.subscribe(anotherObserver); - - subject.onNext("three"); - subject.onCompleted(); - - assertObservedUntilTwo(aObserver); - assertCompletedStartingWithThreeObserver(anotherObserver); - } - - private void assertObservedUntilTwo(Observer aObserver) { - verify(aObserver, times(1)).onNext("one"); - verify(aObserver, times(1)).onNext("two"); - verify(aObserver, Mockito.never()).onNext("three"); - verify(aObserver, Mockito.never()).onError(any(Throwable.class)); - verify(aObserver, Mockito.never()).onCompleted(); - } - - @Test - public void testUnsubscribe() { - UnsubscribeTester.test( - new Func0>() { - @Override - public PublishSubject call() { - return PublishSubject.create(); - } - }, new Action1>() { - @Override - public void call(PublishSubject DefaultSubject) { - DefaultSubject.onCompleted(); - } - }, new Action1>() { - @Override - public void call(PublishSubject DefaultSubject) { - DefaultSubject.onError(new Throwable()); - } - }, new Action1>() { - @Override - public void call(PublishSubject DefaultSubject) { - DefaultSubject.onNext("one"); - } - } - ); - } + }).subscribe(subject); + // the subject has received an onComplete from the first subscribe because + // it is synchronous and the next subscribe won't do anything. + Observable.from(-1, -2, -3).subscribe(subject); + + List> expected = new ArrayList>(); + expected.add(new Notification(-1)); + expected.add(new Notification(-2)); + expected.add(new Notification(-3)); + expected.add(new Notification()); + Assert.assertTrue(actualRef.get().containsAll(expected)); + + sub.unsubscribe(); + } - @Test - public void testNestedSubscribe() { - final PublishSubject s = PublishSubject.create(); + private final Throwable testException = new Throwable(); - final AtomicInteger countParent = new AtomicInteger(); - final AtomicInteger countChildren = new AtomicInteger(); - final AtomicInteger countTotal = new AtomicInteger(); + @Test + public void testCompleted() { + PublishSubject subject = PublishSubject.create(); - final ArrayList list = new ArrayList(); + @SuppressWarnings("unchecked") + Observer aObserver = mock(Observer.class); + subject.subscribe(aObserver); - s.mapMany(new Func1>() { + subject.onNext("one"); + subject.onNext("two"); + subject.onNext("three"); + subject.onCompleted(); - @Override - public Observable call(final Integer v) { - countParent.incrementAndGet(); + @SuppressWarnings("unchecked") + Observer anotherObserver = mock(Observer.class); + subject.subscribe(anotherObserver); - // then subscribe to subject again (it will not receive the previous value) - return s.map(new Func1() { + subject.onNext("four"); + subject.onCompleted(); + subject.onError(new Throwable()); - @Override - public String call(Integer v2) { - countChildren.incrementAndGet(); - return "Parent: " + v + " Child: " + v2; - } + assertCompletedObserver(aObserver); + // todo bug? assertNeverObserver(anotherObserver); + } - }); - } + private void assertCompletedObserver(Observer aObserver) { + verify(aObserver, times(1)).onNext("one"); + verify(aObserver, times(1)).onNext("two"); + verify(aObserver, times(1)).onNext("three"); + verify(aObserver, Mockito.never()).onError(any(Throwable.class)); + verify(aObserver, times(1)).onCompleted(); + } + + @Test + public void testError() { + PublishSubject subject = PublishSubject.create(); + + @SuppressWarnings("unchecked") + Observer aObserver = mock(Observer.class); + subject.subscribe(aObserver); + + subject.onNext("one"); + subject.onNext("two"); + subject.onNext("three"); + subject.onError(testException); + + @SuppressWarnings("unchecked") + Observer anotherObserver = mock(Observer.class); + subject.subscribe(anotherObserver); + + subject.onNext("four"); + subject.onError(new Throwable()); + subject.onCompleted(); + + assertErrorObserver(aObserver); + // todo bug? assertNeverObserver(anotherObserver); + } + + private void assertErrorObserver(Observer aObserver) { + verify(aObserver, times(1)).onNext("one"); + verify(aObserver, times(1)).onNext("two"); + verify(aObserver, times(1)).onNext("three"); + verify(aObserver, times(1)).onError(testException); + verify(aObserver, Mockito.never()).onCompleted(); + } + + @Test + public void testSubscribeMidSequence() { + PublishSubject subject = PublishSubject.create(); - }).subscribe(new Action1() { + @SuppressWarnings("unchecked") + Observer aObserver = mock(Observer.class); + subject.subscribe(aObserver); - @Override - public void call(String v) { - countTotal.incrementAndGet(); - list.add(v); - } + subject.onNext("one"); + subject.onNext("two"); - }); + assertObservedUntilTwo(aObserver); - for (int i = 0; i < 10; i++) { - s.onNext(i); + @SuppressWarnings("unchecked") + Observer anotherObserver = mock(Observer.class); + subject.subscribe(anotherObserver); + + subject.onNext("three"); + subject.onCompleted(); + + assertCompletedObserver(aObserver); + assertCompletedStartingWithThreeObserver(anotherObserver); } - s.onCompleted(); - // System.out.println("countParent: " + countParent.get()); - // System.out.println("countChildren: " + countChildren.get()); - // System.out.println("countTotal: " + countTotal.get()); + private void assertCompletedStartingWithThreeObserver(Observer aObserver) { + verify(aObserver, Mockito.never()).onNext("one"); + verify(aObserver, Mockito.never()).onNext("two"); + verify(aObserver, times(1)).onNext("three"); + verify(aObserver, Mockito.never()).onError(any(Throwable.class)); + verify(aObserver, times(1)).onCompleted(); + } + + @Test + public void testUnsubscribeFirstObserver() { + PublishSubject subject = PublishSubject.create(); + + @SuppressWarnings("unchecked") + Observer aObserver = mock(Observer.class); + Subscription subscription = subject.subscribe(aObserver); + + subject.onNext("one"); + subject.onNext("two"); + + subscription.unsubscribe(); + assertObservedUntilTwo(aObserver); + + @SuppressWarnings("unchecked") + Observer anotherObserver = mock(Observer.class); + subject.subscribe(anotherObserver); + + subject.onNext("three"); + subject.onCompleted(); - // 9+8+7+6+5+4+3+2+1+0 == 45 - assertEquals(45, list.size()); - } + assertObservedUntilTwo(aObserver); + assertCompletedStartingWithThreeObserver(anotherObserver); + } - /** - * Should be able to unsubscribe all Observers, have it stop emitting, then subscribe new ones and it start emitting again. - */ - @Test - public void testReSubscribe() { - final PublishSubject ps = PublishSubject.create(); + private void assertObservedUntilTwo(Observer aObserver) { + verify(aObserver, times(1)).onNext("one"); + verify(aObserver, times(1)).onNext("two"); + verify(aObserver, Mockito.never()).onNext("three"); + verify(aObserver, Mockito.never()).onError(any(Throwable.class)); + verify(aObserver, Mockito.never()).onCompleted(); + } - Observer o1 = mock(Observer.class); - Subscription s1 = ps.subscribe(o1); + @Test + public void testUnsubscribe() { + UnsubscribeTester.test( + new Func0>() { + @Override + public PublishSubject call() { + return PublishSubject.create(); + } + }, new Action1>() { + @Override + public void call(PublishSubject DefaultSubject) { + DefaultSubject.onCompleted(); + } + }, new Action1>() { + @Override + public void call(PublishSubject DefaultSubject) { + DefaultSubject.onError(new Throwable()); + } + }, new Action1>() { + @Override + public void call(PublishSubject DefaultSubject) { + DefaultSubject.onNext("one"); + } + } + ); + } - // emit - ps.onNext(1); + @Test + public void testNestedSubscribe() { + final PublishSubject s = PublishSubject.create(); - // validate we got it - InOrder inOrder1 = inOrder(o1); - inOrder1.verify(o1, times(1)).onNext(1); - inOrder1.verifyNoMoreInteractions(); + final AtomicInteger countParent = new AtomicInteger(); + final AtomicInteger countChildren = new AtomicInteger(); + final AtomicInteger countTotal = new AtomicInteger(); - // unsubscribe - s1.unsubscribe(); + final ArrayList list = new ArrayList(); - // emit again but nothing will be there to receive it - ps.onNext(2); + s.mapMany(new Func1>() { - Observer o2 = mock(Observer.class); - Subscription s2 = ps.subscribe(o2); + @Override + public Observable call(final Integer v) { + countParent.incrementAndGet(); - // emit - ps.onNext(3); + // then subscribe to subject again (it will not receive the previous value) + return s.map(new Func1() { - // validate we got it - InOrder inOrder2 = inOrder(o2); - inOrder2.verify(o2, times(1)).onNext(3); - inOrder2.verifyNoMoreInteractions(); + @Override + public String call(Integer v2) { + countChildren.incrementAndGet(); + return "Parent: " + v + " Child: " + v2; + } - s2.unsubscribe(); - } + }); + } - /** - * Even if subject received an onError/onCompleted, new subscriptions should be able to restart it. - */ - @Test - public void testReSubscribeAfterTerminalState() { - final PublishSubject ps = PublishSubject.create(); + }).subscribe(new Action1() { - Observer o1 = mock(Observer.class); - Subscription s1 = ps.subscribe(o1); + @Override + public void call(String v) { + countTotal.incrementAndGet(); + list.add(v); + } - // emit - ps.onNext(1); + }); + + for (int i = 0; i < 10; i++) { + s.onNext(i); + } + s.onCompleted(); - // validate we got it - InOrder inOrder1 = inOrder(o1); - inOrder1.verify(o1, times(1)).onNext(1); - inOrder1.verifyNoMoreInteractions(); + // System.out.println("countParent: " + countParent.get()); + // System.out.println("countChildren: " + countChildren.get()); + // System.out.println("countTotal: " + countTotal.get()); - // unsubscribe - s1.unsubscribe(); + // 9+8+7+6+5+4+3+2+1+0 == 45 + assertEquals(45, list.size()); + } - ps.onCompleted(); + /** + * Should be able to unsubscribe all Observers, have it stop emitting, then subscribe new ones and it start emitting again. + */ + @Test + public void testReSubscribe() { + final PublishSubject ps = PublishSubject.create(); - // emit again but nothing will be there to receive it - ps.onNext(2); + Observer o1 = mock(Observer.class); + Subscription s1 = ps.subscribe(o1); - Observer o2 = mock(Observer.class); - Subscription s2 = ps.subscribe(o2); + // emit + ps.onNext(1); - // emit - ps.onNext(3); + // validate we got it + InOrder inOrder1 = inOrder(o1); + inOrder1.verify(o1, times(1)).onNext(1); + inOrder1.verifyNoMoreInteractions(); - // validate we got it - InOrder inOrder2 = inOrder(o2); - inOrder2.verify(o2, times(1)).onNext(3); - inOrder2.verifyNoMoreInteractions(); + // unsubscribe + s1.unsubscribe(); - s2.unsubscribe(); - } + // emit again but nothing will be there to receive it + ps.onNext(2); + + Observer o2 = mock(Observer.class); + Subscription s2 = ps.subscribe(o2); + + // emit + ps.onNext(3); + + // validate we got it + InOrder inOrder2 = inOrder(o2); + inOrder2.verify(o2, times(1)).onNext(3); + inOrder2.verifyNoMoreInteractions(); + + s2.unsubscribe(); + } + + /** + * Even if subject received an onError/onCompleted, new subscriptions should be able to restart it. + */ + @Test + public void testReSubscribeAfterTerminalState() { + final PublishSubject ps = PublishSubject.create(); + + Observer o1 = mock(Observer.class); + Subscription s1 = ps.subscribe(o1); + + // emit + ps.onNext(1); + + // validate we got it + InOrder inOrder1 = inOrder(o1); + inOrder1.verify(o1, times(1)).onNext(1); + inOrder1.verifyNoMoreInteractions(); + + // unsubscribe + s1.unsubscribe(); + + ps.onCompleted(); + + // emit again but nothing will be there to receive it + ps.onNext(2); + + Observer o2 = mock(Observer.class); + Subscription s2 = ps.subscribe(o2); + + // emit + ps.onNext(3); + + // validate we got it + InOrder inOrder2 = inOrder(o2); + inOrder2.verify(o2, times(1)).onNext(3); + inOrder2.verifyNoMoreInteractions(); + + s2.unsubscribe(); + } } diff --git a/rxjava-core/src/test/java/rx/subjects/ReplaySubjectTest.java b/rxjava-core/src/test/java/rx/subjects/ReplaySubjectTest.java index dc0298a7e3..728f9e53f1 100644 --- a/rxjava-core/src/test/java/rx/subjects/ReplaySubjectTest.java +++ b/rxjava-core/src/test/java/rx/subjects/ReplaySubjectTest.java @@ -1,169 +1,170 @@ package rx.subjects; +import static org.mockito.Matchers.*; +import static org.mockito.Mockito.*; + import org.junit.Test; import org.mockito.InOrder; import org.mockito.Mockito; + import rx.Observer; import rx.Subscription; import rx.util.functions.Action1; import rx.util.functions.Func0; -import static org.mockito.Matchers.any; -import static org.mockito.Mockito.*; - public class ReplaySubjectTest { - private final Throwable testException = new Throwable(); + private final Throwable testException = new Throwable(); - @SuppressWarnings("unchecked") - @Test - public void testCompleted() { - ReplaySubject subject = ReplaySubject.create(); + @SuppressWarnings("unchecked") + @Test + public void testCompleted() { + ReplaySubject subject = ReplaySubject.create(); - Observer o1 = mock(Observer.class); - subject.subscribe(o1); + Observer o1 = mock(Observer.class); + subject.subscribe(o1); - subject.onNext("one"); - subject.onNext("two"); - subject.onNext("three"); - subject.onCompleted(); + subject.onNext("one"); + subject.onNext("two"); + subject.onNext("three"); + subject.onCompleted(); - subject.onNext("four"); - subject.onCompleted(); - subject.onError(new Throwable()); + subject.onNext("four"); + subject.onCompleted(); + subject.onError(new Throwable()); - assertCompletedObserver(o1); + assertCompletedObserver(o1); - // assert that subscribing a 2nd time gets the same data - Observer o2 = mock(Observer.class); - subject.subscribe(o2); - assertCompletedObserver(o2); - } + // assert that subscribing a 2nd time gets the same data + Observer o2 = mock(Observer.class); + subject.subscribe(o2); + assertCompletedObserver(o2); + } - private void assertCompletedObserver(Observer aObserver) { - InOrder inOrder = inOrder(aObserver); + private void assertCompletedObserver(Observer aObserver) { + InOrder inOrder = inOrder(aObserver); - inOrder.verify(aObserver, times(1)).onNext("one"); - inOrder.verify(aObserver, times(1)).onNext("two"); - inOrder.verify(aObserver, times(1)).onNext("three"); - inOrder.verify(aObserver, Mockito.never()).onError(any(Throwable.class)); - inOrder.verify(aObserver, times(1)).onCompleted(); - inOrder.verifyNoMoreInteractions(); - } - - @SuppressWarnings("unchecked") - @Test - public void testError() { - ReplaySubject subject = ReplaySubject.create(); - - Observer aObserver = mock(Observer.class); - subject.subscribe(aObserver); - - subject.onNext("one"); - subject.onNext("two"); - subject.onNext("three"); - subject.onError(testException); - - subject.onNext("four"); - subject.onError(new Throwable()); - subject.onCompleted(); - - assertErrorObserver(aObserver); - - aObserver = mock(Observer.class); - subject.subscribe(aObserver); - assertErrorObserver(aObserver); - } - - private void assertErrorObserver(Observer aObserver) { - verify(aObserver, times(1)).onNext("one"); - verify(aObserver, times(1)).onNext("two"); - verify(aObserver, times(1)).onNext("three"); - verify(aObserver, times(1)).onError(testException); - verify(aObserver, Mockito.never()).onCompleted(); - } - - @SuppressWarnings("unchecked") - @Test - public void testSubscribeMidSequence() { - ReplaySubject subject = ReplaySubject.create(); - - Observer aObserver = mock(Observer.class); - subject.subscribe(aObserver); - - subject.onNext("one"); - subject.onNext("two"); - - assertObservedUntilTwo(aObserver); - - Observer anotherObserver = mock(Observer.class); - subject.subscribe(anotherObserver); - assertObservedUntilTwo(anotherObserver); - - subject.onNext("three"); - subject.onCompleted(); - - assertCompletedObserver(aObserver); - assertCompletedObserver(anotherObserver); - } - - @SuppressWarnings("unchecked") - @Test - public void testUnsubscribeFirstObserver() { - ReplaySubject subject = ReplaySubject.create(); - - Observer aObserver = mock(Observer.class); - Subscription subscription = subject.subscribe(aObserver); - - subject.onNext("one"); - subject.onNext("two"); - - subscription.unsubscribe(); - assertObservedUntilTwo(aObserver); - - Observer anotherObserver = mock(Observer.class); - subject.subscribe(anotherObserver); - assertObservedUntilTwo(anotherObserver); - - subject.onNext("three"); - subject.onCompleted(); - - assertObservedUntilTwo(aObserver); - assertCompletedObserver(anotherObserver); - } - - private void assertObservedUntilTwo(Observer aObserver) { - verify(aObserver, times(1)).onNext("one"); - verify(aObserver, times(1)).onNext("two"); - verify(aObserver, Mockito.never()).onNext("three"); - verify(aObserver, Mockito.never()).onError(any(Throwable.class)); - verify(aObserver, Mockito.never()).onCompleted(); - } - - @Test - public void testUnsubscribe() { - UnsubscribeTester.test( - new Func0>() { - @Override - public ReplaySubject call() { - return ReplaySubject.create(); - } - }, new Action1>() { - @Override - public void call(ReplaySubject repeatSubject) { - repeatSubject.onCompleted(); - } - }, new Action1>() { - @Override - public void call(ReplaySubject repeatSubject) { - repeatSubject.onError(new Throwable()); - } - }, new Action1>() { - @Override - public void call(ReplaySubject repeatSubject) { - repeatSubject.onNext("one"); - } - } - ); - } + inOrder.verify(aObserver, times(1)).onNext("one"); + inOrder.verify(aObserver, times(1)).onNext("two"); + inOrder.verify(aObserver, times(1)).onNext("three"); + inOrder.verify(aObserver, Mockito.never()).onError(any(Throwable.class)); + inOrder.verify(aObserver, times(1)).onCompleted(); + inOrder.verifyNoMoreInteractions(); + } + + @SuppressWarnings("unchecked") + @Test + public void testError() { + ReplaySubject subject = ReplaySubject.create(); + + Observer aObserver = mock(Observer.class); + subject.subscribe(aObserver); + + subject.onNext("one"); + subject.onNext("two"); + subject.onNext("three"); + subject.onError(testException); + + subject.onNext("four"); + subject.onError(new Throwable()); + subject.onCompleted(); + + assertErrorObserver(aObserver); + + aObserver = mock(Observer.class); + subject.subscribe(aObserver); + assertErrorObserver(aObserver); + } + + private void assertErrorObserver(Observer aObserver) { + verify(aObserver, times(1)).onNext("one"); + verify(aObserver, times(1)).onNext("two"); + verify(aObserver, times(1)).onNext("three"); + verify(aObserver, times(1)).onError(testException); + verify(aObserver, Mockito.never()).onCompleted(); + } + + @SuppressWarnings("unchecked") + @Test + public void testSubscribeMidSequence() { + ReplaySubject subject = ReplaySubject.create(); + + Observer aObserver = mock(Observer.class); + subject.subscribe(aObserver); + + subject.onNext("one"); + subject.onNext("two"); + + assertObservedUntilTwo(aObserver); + + Observer anotherObserver = mock(Observer.class); + subject.subscribe(anotherObserver); + assertObservedUntilTwo(anotherObserver); + + subject.onNext("three"); + subject.onCompleted(); + + assertCompletedObserver(aObserver); + assertCompletedObserver(anotherObserver); + } + + @SuppressWarnings("unchecked") + @Test + public void testUnsubscribeFirstObserver() { + ReplaySubject subject = ReplaySubject.create(); + + Observer aObserver = mock(Observer.class); + Subscription subscription = subject.subscribe(aObserver); + + subject.onNext("one"); + subject.onNext("two"); + + subscription.unsubscribe(); + assertObservedUntilTwo(aObserver); + + Observer anotherObserver = mock(Observer.class); + subject.subscribe(anotherObserver); + assertObservedUntilTwo(anotherObserver); + + subject.onNext("three"); + subject.onCompleted(); + + assertObservedUntilTwo(aObserver); + assertCompletedObserver(anotherObserver); + } + + private void assertObservedUntilTwo(Observer aObserver) { + verify(aObserver, times(1)).onNext("one"); + verify(aObserver, times(1)).onNext("two"); + verify(aObserver, Mockito.never()).onNext("three"); + verify(aObserver, Mockito.never()).onError(any(Throwable.class)); + verify(aObserver, Mockito.never()).onCompleted(); + } + + @Test + public void testUnsubscribe() { + UnsubscribeTester.test( + new Func0>() { + @Override + public ReplaySubject call() { + return ReplaySubject.create(); + } + }, new Action1>() { + @Override + public void call(ReplaySubject repeatSubject) { + repeatSubject.onCompleted(); + } + }, new Action1>() { + @Override + public void call(ReplaySubject repeatSubject) { + repeatSubject.onError(new Throwable()); + } + }, new Action1>() { + @Override + public void call(ReplaySubject repeatSubject) { + repeatSubject.onNext("one"); + } + } + ); + } } diff --git a/rxjava-core/src/test/java/rx/subscriptions/CompositeSubscriptionTest.java b/rxjava-core/src/test/java/rx/subscriptions/CompositeSubscriptionTest.java index 3bb8b718a0..e7257d9f1a 100644 --- a/rxjava-core/src/test/java/rx/subscriptions/CompositeSubscriptionTest.java +++ b/rxjava-core/src/test/java/rx/subscriptions/CompositeSubscriptionTest.java @@ -1,70 +1,70 @@ package rx.subscriptions; +import static org.junit.Assert.*; + +import java.util.concurrent.atomic.AtomicInteger; + import org.junit.Test; + import rx.Subscription; import rx.util.CompositeException; -import java.util.concurrent.atomic.AtomicInteger; +public class CompositeSubscriptionTest { -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.fail; + @Test + public void testSuccess() { + final AtomicInteger counter = new AtomicInteger(); + CompositeSubscription s = new CompositeSubscription(); + s.add(new Subscription() { -public class CompositeSubscriptionTest { + @Override + public void unsubscribe() { + counter.incrementAndGet(); + } + }); + + s.add(new Subscription() { + + @Override + public void unsubscribe() { + counter.incrementAndGet(); + } + }); - @Test - public void testSuccess() { - final AtomicInteger counter = new AtomicInteger(); - CompositeSubscription s = new CompositeSubscription(); - s.add(new Subscription() { - - @Override - public void unsubscribe() { - counter.incrementAndGet(); - } - }); - - s.add(new Subscription() { - - @Override - public void unsubscribe() { - counter.incrementAndGet(); - } - }); - - s.unsubscribe(); - - assertEquals(2, counter.get()); - } - - @Test - public void testException() { - final AtomicInteger counter = new AtomicInteger(); - CompositeSubscription s = new CompositeSubscription(); - s.add(new Subscription() { - - @Override - public void unsubscribe() { - throw new RuntimeException("failed on first one"); - } - }); - - s.add(new Subscription() { - - @Override - public void unsubscribe() { - counter.incrementAndGet(); - } - }); - - try { - s.unsubscribe(); - fail("Expecting an exception"); - } catch (CompositeException e) { - // we expect this - assertEquals(1, e.getExceptions().size()); + s.unsubscribe(); + + assertEquals(2, counter.get()); } - // we should still have unsubscribed to the second one - assertEquals(1, counter.get()); - } + @Test + public void testException() { + final AtomicInteger counter = new AtomicInteger(); + CompositeSubscription s = new CompositeSubscription(); + s.add(new Subscription() { + + @Override + public void unsubscribe() { + throw new RuntimeException("failed on first one"); + } + }); + + s.add(new Subscription() { + + @Override + public void unsubscribe() { + counter.incrementAndGet(); + } + }); + + try { + s.unsubscribe(); + fail("Expecting an exception"); + } catch (CompositeException e) { + // we expect this + assertEquals(1, e.getExceptions().size()); + } + + // we should still have unsubscribed to the second one + assertEquals(1, counter.get()); + } } diff --git a/rxjava-core/src/test/java/rx/subscriptions/SerialSubscriptionTests.java b/rxjava-core/src/test/java/rx/subscriptions/SerialSubscriptionTests.java index 4ffc5cef27..cd63539c87 100644 --- a/rxjava-core/src/test/java/rx/subscriptions/SerialSubscriptionTests.java +++ b/rxjava-core/src/test/java/rx/subscriptions/SerialSubscriptionTests.java @@ -1,12 +1,12 @@ /** * Copyright 2013 Netflix, Inc. - * + * * 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. @@ -15,12 +15,13 @@ */ package rx.subscriptions; +import static org.mockito.Mockito.*; + import org.junit.Before; import org.junit.Test; import org.mockito.MockitoAnnotations; -import rx.Subscription; -import static org.mockito.Mockito.*; +import rx.Subscription; public class SerialSubscriptionTests { private SerialSubscription serialSubscription; diff --git a/rxjava-core/src/test/java/rx/subscriptions/SubscriptionsTest.java b/rxjava-core/src/test/java/rx/subscriptions/SubscriptionsTest.java index 5ac0242a95..806a5e52e9 100644 --- a/rxjava-core/src/test/java/rx/subscriptions/SubscriptionsTest.java +++ b/rxjava-core/src/test/java/rx/subscriptions/SubscriptionsTest.java @@ -1,20 +1,21 @@ package rx.subscriptions; +import static org.mockito.Mockito.*; +import static rx.subscriptions.Subscriptions.*; + import org.junit.Test; + import rx.Subscription; import rx.util.functions.Action0; -import static org.mockito.Mockito.*; -import static rx.subscriptions.Subscriptions.create; - public class SubscriptionsTest { - @Test - public void testUnsubscribeOnlyOnce() { - Action0 unsubscribe = mock(Action0.class); - Subscription subscription = create(unsubscribe); - subscription.unsubscribe(); - subscription.unsubscribe(); - verify(unsubscribe, times(1)).call(); - } + @Test + public void testUnsubscribeOnlyOnce() { + Action0 unsubscribe = mock(Action0.class); + Subscription subscription = create(unsubscribe); + subscription.unsubscribe(); + subscription.unsubscribe(); + verify(unsubscribe, times(1)).call(); + } } diff --git a/rxjava-core/src/test/java/rx/test/OperatorTester.java b/rxjava-core/src/test/java/rx/test/OperatorTester.java index ab64251583..6bd905c264 100644 --- a/rxjava-core/src/test/java/rx/test/OperatorTester.java +++ b/rxjava-core/src/test/java/rx/test/OperatorTester.java @@ -1,12 +1,12 @@ /** * Copyright 2013 Netflix, Inc. - * + * * 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. @@ -15,13 +15,13 @@ */ package rx.test; +import java.util.concurrent.TimeUnit; + import rx.Scheduler; import rx.Subscription; import rx.util.functions.Action0; import rx.util.functions.Func2; -import java.util.concurrent.TimeUnit; - /** * Common utility functions for testing operator implementations. */ @@ -36,59 +36,59 @@ public class OperatorTester { * If they are truly useful for everyone to use then an "rx.testing" package may make sense. */ - private OperatorTester() { - } + private OperatorTester() { + } - /** - * Used for mocking of Schedulers since many Scheduler implementations are static/final. - * - * @param underlying - * @return - */ - public static Scheduler forwardingScheduler(Scheduler underlying) { - return new ForwardingScheduler(underlying); - } + /** + * Used for mocking of Schedulers since many Scheduler implementations are static/final. + * + * @param underlying + * @return + */ + public static Scheduler forwardingScheduler(Scheduler underlying) { + return new ForwardingScheduler(underlying); + } - public static class ForwardingScheduler extends Scheduler { - private final Scheduler underlying; + public static class ForwardingScheduler extends Scheduler { + private final Scheduler underlying; - public ForwardingScheduler(Scheduler underlying) { - this.underlying = underlying; - } + public ForwardingScheduler(Scheduler underlying) { + this.underlying = underlying; + } - @Override - public Subscription schedule(Action0 action) { - return underlying.schedule(action); - } + @Override + public Subscription schedule(Action0 action) { + return underlying.schedule(action); + } - @Override - public Subscription schedule(T state, Func2 action) { - return underlying.schedule(state, action); - } + @Override + public Subscription schedule(T state, Func2 action) { + return underlying.schedule(state, action); + } - @Override - public Subscription schedule(Action0 action, long dueTime, TimeUnit unit) { - return underlying.schedule(action, dueTime, unit); - } + @Override + public Subscription schedule(Action0 action, long dueTime, TimeUnit unit) { + return underlying.schedule(action, dueTime, unit); + } - @Override - public Subscription schedule(T state, Func2 action, long dueTime, TimeUnit unit) { - return underlying.schedule(state, action, dueTime, unit); - } + @Override + public Subscription schedule(T state, Func2 action, long dueTime, TimeUnit unit) { + return underlying.schedule(state, action, dueTime, unit); + } - @Override - public Subscription schedulePeriodically(Action0 action, long initialDelay, long period, TimeUnit unit) { - return underlying.schedulePeriodically(action, initialDelay, period, unit); - } + @Override + public Subscription schedulePeriodically(Action0 action, long initialDelay, long period, TimeUnit unit) { + return underlying.schedulePeriodically(action, initialDelay, period, unit); + } - @Override - public Subscription schedulePeriodically(T state, Func2 action, long initialDelay, long period, TimeUnit unit) { - return underlying.schedulePeriodically(state, action, initialDelay, period, unit); - } + @Override + public Subscription schedulePeriodically(T state, Func2 action, long initialDelay, long period, TimeUnit unit) { + return underlying.schedulePeriodically(state, action, initialDelay, period, unit); + } - @Override - public long now() { - return underlying.now(); + @Override + public long now() { + return underlying.now(); + } } - } } \ No newline at end of file diff --git a/rxjava-core/src/test/java/rx/util/RangeTest.java b/rxjava-core/src/test/java/rx/util/RangeTest.java index 03ec6eef19..c788b32e82 100644 --- a/rxjava-core/src/test/java/rx/util/RangeTest.java +++ b/rxjava-core/src/test/java/rx/util/RangeTest.java @@ -1,50 +1,50 @@ package rx.util; -import org.junit.Test; +import static org.junit.Assert.*; import java.util.ArrayList; import java.util.Arrays; import java.util.List; -import static org.junit.Assert.assertEquals; +import org.junit.Test; public class RangeTest { - @Test - public void testSimpleRange() { - assertEquals(Arrays.asList(1, 2, 3, 4), toList(Range.create(1, 5))); - } - - @Test - public void testRangeWithStep() { - assertEquals(Arrays.asList(1, 3, 5, 7, 9), toList(Range.createWithStep(1, 10, 2))); - } - - @Test - public void testRangeWithCount() { - assertEquals(Arrays.asList(1, 2, 3, 4, 5), toList(Range.createWithCount(1, 5))); - } - - @Test - public void testRangeWithCount2() { - assertEquals(Arrays.asList(2, 3, 4, 5), toList(Range.createWithCount(2, 4))); - } - - @Test - public void testRangeWithCount3() { - assertEquals(Arrays.asList(0, 1, 2, 3), toList(Range.createWithCount(0, 4))); - } - - @Test - public void testRangeWithCount4() { - assertEquals(Arrays.asList(10, 11, 12, 13, 14), toList(Range.createWithCount(10, 5))); - } - - private static List toList(Iterable iterable) { - List result = new ArrayList(); - for (T element : iterable) { - result.add(element); + @Test + public void testSimpleRange() { + assertEquals(Arrays.asList(1, 2, 3, 4), toList(Range.create(1, 5))); + } + + @Test + public void testRangeWithStep() { + assertEquals(Arrays.asList(1, 3, 5, 7, 9), toList(Range.createWithStep(1, 10, 2))); + } + + @Test + public void testRangeWithCount() { + assertEquals(Arrays.asList(1, 2, 3, 4, 5), toList(Range.createWithCount(1, 5))); + } + + @Test + public void testRangeWithCount2() { + assertEquals(Arrays.asList(2, 3, 4, 5), toList(Range.createWithCount(2, 4))); + } + + @Test + public void testRangeWithCount3() { + assertEquals(Arrays.asList(0, 1, 2, 3), toList(Range.createWithCount(0, 4))); + } + + @Test + public void testRangeWithCount4() { + assertEquals(Arrays.asList(10, 11, 12, 13, 14), toList(Range.createWithCount(10, 5))); + } + + private static List toList(Iterable iterable) { + List result = new ArrayList(); + for (T element : iterable) { + result.add(element); + } + return result; } - return result; - } } From 6de7fd15b7b4f42263d847fe462552110c405bb3 Mon Sep 17 00:00:00 2001 From: Ben Christensen Date: Mon, 4 Nov 2013 20:03:56 -0800 Subject: [PATCH 5/6] Move last 6 remaining unit tests out. --- .../java/rx/operators/OperationToFuture.java | 55 --------------- .../rx/operators/OperationToIterator.java | 50 -------------- .../rx/operators/OperationToFutureTest.java | 68 +++++++++++++++++++ .../rx/operators/OperationToIteratorTest.java | 62 +++++++++++++++++ 4 files changed, 130 insertions(+), 105 deletions(-) create mode 100644 rxjava-core/src/test/java/rx/operators/OperationToFutureTest.java create mode 100644 rxjava-core/src/test/java/rx/operators/OperationToIteratorTest.java diff --git a/rxjava-core/src/main/java/rx/operators/OperationToFuture.java b/rxjava-core/src/main/java/rx/operators/OperationToFuture.java index a3ecc49efe..d4433da9d6 100644 --- a/rxjava-core/src/main/java/rx/operators/OperationToFuture.java +++ b/rxjava-core/src/main/java/rx/operators/OperationToFuture.java @@ -15,9 +15,6 @@ */ package rx.operators; -import static org.junit.Assert.*; - -import java.util.List; import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutionException; import java.util.concurrent.Future; @@ -25,13 +22,9 @@ import java.util.concurrent.TimeoutException; import java.util.concurrent.atomic.AtomicReference; -import org.junit.Test; - import rx.Observable; -import rx.Observable.OnSubscribeFunc; import rx.Observer; import rx.Subscription; -import rx.subscriptions.Subscriptions; /** * Returns a Future representing the single value emitted by an Observable. @@ -136,52 +129,4 @@ private T getValue() throws ExecutionException { } - @Test - public void testToFuture() throws InterruptedException, ExecutionException { - Observable obs = Observable.from("one"); - Future f = toFuture(obs); - assertEquals("one", f.get()); - } - - @Test - public void testToFutureList() throws InterruptedException, ExecutionException { - Observable obs = Observable.from("one", "two", "three"); - Future> f = toFuture(obs.toList()); - assertEquals("one", f.get().get(0)); - assertEquals("two", f.get().get(1)); - assertEquals("three", f.get().get(2)); - } - - @Test(expected = ExecutionException.class) - public void testExceptionWithMoreThanOneElement() throws InterruptedException, ExecutionException { - Observable obs = Observable.from("one", "two"); - Future f = toFuture(obs); - assertEquals("one", f.get()); - // we expect an exception since there are more than 1 element - } - - @Test - public void testToFutureWithException() { - Observable obs = Observable.create(new OnSubscribeFunc() { - - @Override - public Subscription onSubscribe(Observer observer) { - observer.onNext("one"); - observer.onError(new TestException()); - return Subscriptions.empty(); - } - }); - - Future f = toFuture(obs); - try { - f.get(); - fail("expected exception"); - } catch (Throwable e) { - assertEquals(TestException.class, e.getCause().getClass()); - } - } - - private static class TestException extends RuntimeException { - private static final long serialVersionUID = 1L; - } } diff --git a/rxjava-core/src/main/java/rx/operators/OperationToIterator.java b/rxjava-core/src/main/java/rx/operators/OperationToIterator.java index 59debafcb9..2fcd51872e 100644 --- a/rxjava-core/src/main/java/rx/operators/OperationToIterator.java +++ b/rxjava-core/src/main/java/rx/operators/OperationToIterator.java @@ -15,20 +15,13 @@ */ package rx.operators; -import static org.junit.Assert.*; - import java.util.Iterator; import java.util.concurrent.BlockingQueue; import java.util.concurrent.LinkedBlockingQueue; -import org.junit.Test; - import rx.Notification; import rx.Observable; -import rx.Observable.OnSubscribeFunc; import rx.Observer; -import rx.Subscription; -import rx.subscriptions.Subscriptions; import rx.util.Exceptions; /** @@ -108,47 +101,4 @@ public void remove() { }; } - @Test - public void testToIterator() { - Observable obs = Observable.from("one", "two", "three"); - - Iterator it = toIterator(obs); - - assertEquals(true, it.hasNext()); - assertEquals("one", it.next()); - - assertEquals(true, it.hasNext()); - assertEquals("two", it.next()); - - assertEquals(true, it.hasNext()); - assertEquals("three", it.next()); - - assertEquals(false, it.hasNext()); - - } - - @Test(expected = TestException.class) - public void testToIteratorWithException() { - Observable obs = Observable.create(new OnSubscribeFunc() { - - @Override - public Subscription onSubscribe(Observer observer) { - observer.onNext("one"); - observer.onError(new TestException()); - return Subscriptions.empty(); - } - }); - - Iterator it = toIterator(obs); - - assertEquals(true, it.hasNext()); - assertEquals("one", it.next()); - - assertEquals(true, it.hasNext()); - it.next(); - } - - private static class TestException extends RuntimeException { - private static final long serialVersionUID = 1L; - } } diff --git a/rxjava-core/src/test/java/rx/operators/OperationToFutureTest.java b/rxjava-core/src/test/java/rx/operators/OperationToFutureTest.java new file mode 100644 index 0000000000..c18131e5c7 --- /dev/null +++ b/rxjava-core/src/test/java/rx/operators/OperationToFutureTest.java @@ -0,0 +1,68 @@ +package rx.operators; + +import static org.junit.Assert.*; +import static rx.operators.OperationToFuture.*; + +import java.util.List; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.Future; + +import org.junit.Test; + +import rx.Observable; +import rx.Observable.OnSubscribeFunc; +import rx.Observer; +import rx.Subscription; +import rx.subscriptions.Subscriptions; + +public class OperationToFutureTest { + + @Test + public void testToFuture() throws InterruptedException, ExecutionException { + Observable obs = Observable.from("one"); + Future f = toFuture(obs); + assertEquals("one", f.get()); + } + + @Test + public void testToFutureList() throws InterruptedException, ExecutionException { + Observable obs = Observable.from("one", "two", "three"); + Future> f = toFuture(obs.toList()); + assertEquals("one", f.get().get(0)); + assertEquals("two", f.get().get(1)); + assertEquals("three", f.get().get(2)); + } + + @Test(expected = ExecutionException.class) + public void testExceptionWithMoreThanOneElement() throws InterruptedException, ExecutionException { + Observable obs = Observable.from("one", "two"); + Future f = toFuture(obs); + assertEquals("one", f.get()); + // we expect an exception since there are more than 1 element + } + + @Test + public void testToFutureWithException() { + Observable obs = Observable.create(new OnSubscribeFunc() { + + @Override + public Subscription onSubscribe(Observer observer) { + observer.onNext("one"); + observer.onError(new TestException()); + return Subscriptions.empty(); + } + }); + + Future f = toFuture(obs); + try { + f.get(); + fail("expected exception"); + } catch (Throwable e) { + assertEquals(TestException.class, e.getCause().getClass()); + } + } + + private static class TestException extends RuntimeException { + private static final long serialVersionUID = 1L; + } +} diff --git a/rxjava-core/src/test/java/rx/operators/OperationToIteratorTest.java b/rxjava-core/src/test/java/rx/operators/OperationToIteratorTest.java new file mode 100644 index 0000000000..1994bd4a0c --- /dev/null +++ b/rxjava-core/src/test/java/rx/operators/OperationToIteratorTest.java @@ -0,0 +1,62 @@ +package rx.operators; + +import static org.junit.Assert.*; +import static rx.operators.OperationToIterator.*; + +import java.util.Iterator; + +import org.junit.Test; + +import rx.Observable; +import rx.Observable.OnSubscribeFunc; +import rx.Observer; +import rx.Subscription; +import rx.subscriptions.Subscriptions; + +public class OperationToIteratorTest { + + @Test + public void testToIterator() { + Observable obs = Observable.from("one", "two", "three"); + + Iterator it = toIterator(obs); + + assertEquals(true, it.hasNext()); + assertEquals("one", it.next()); + + assertEquals(true, it.hasNext()); + assertEquals("two", it.next()); + + assertEquals(true, it.hasNext()); + assertEquals("three", it.next()); + + assertEquals(false, it.hasNext()); + + } + + @Test(expected = TestException.class) + public void testToIteratorWithException() { + Observable obs = Observable.create(new OnSubscribeFunc() { + + @Override + public Subscription onSubscribe(Observer observer) { + observer.onNext("one"); + observer.onError(new TestException()); + return Subscriptions.empty(); + } + }); + + Iterator it = toIterator(obs); + + assertEquals(true, it.hasNext()); + assertEquals("one", it.next()); + + assertEquals(true, it.hasNext()); + it.next(); + } + + private static class TestException extends RuntimeException { + private static final long serialVersionUID = 1L; + } + +} From 2319d0a00ad913699090a5b91c534d87e14efc06 Mon Sep 17 00:00:00 2001 From: Ben Christensen Date: Mon, 4 Nov 2013 20:07:34 -0800 Subject: [PATCH 6/6] Add missing license headers. --- .../groovy/rx/lang/groovy/TestParallel.groovy | 15 +++++++++++++++ .../rx/lang/scala/examples/MovieLibUsage.java | 15 +++++++++++++++ .../scala/rx/lang/scala/examples/Olympics.scala | 15 +++++++++++++++ .../main/scala/rx/lang/scala/Notification.scala | 15 +++++++++++++++ .../src/main/scala/rx/lang/scala/Scheduler.scala | 15 +++++++++++++++ .../rx/lang/scala/concurrency/Schedulers.scala | 15 +++++++++++++++ .../rx/lang/scala/concurrency/TestScheduler.scala | 15 +++++++++++++++ .../scala/rx/lang/scala/observables/package.scala | 15 +++++++++++++++ .../scala/rx/lang/scala/subjects/package.scala | 15 +++++++++++++++ .../scala/rx/lang/scala/CompletenessTest.scala | 15 +++++++++++++++ .../rx/android/concurrency/AndroidSchedulers.java | 15 +++++++++++++++ .../concurrency/HandlerThreadScheduler.java | 15 +++++++++++++++ .../rx/android/observables/AndroidObservable.java | 15 +++++++++++++++ .../OperationObserveFromAndroidComponent.java | 15 +++++++++++++++ .../http/examples/ExampleObservableHttp.java | 15 +++++++++++++++ .../src/main/java/rx/operators/OperationCast.java | 15 +++++++++++++++ .../rx/operators/OperationDefaultIfEmpty.java | 15 +++++++++++++++ .../MultipleAssignmentSubscription.java | 15 +++++++++++++++ .../src/test/java/rx/CombineLatestTests.java | 15 +++++++++++++++ rxjava-core/src/test/java/rx/ConcatTests.java | 15 +++++++++++++++ rxjava-core/src/test/java/rx/CovarianceTest.java | 15 +++++++++++++++ rxjava-core/src/test/java/rx/EventStream.java | 15 +++++++++++++++ rxjava-core/src/test/java/rx/GroupByTests.java | 15 +++++++++++++++ rxjava-core/src/test/java/rx/IntervalDemo.java | 15 +++++++++++++++ rxjava-core/src/test/java/rx/MergeTests.java | 15 +++++++++++++++ .../src/test/java/rx/ObservableWindowTests.java | 15 +++++++++++++++ rxjava-core/src/test/java/rx/ObserveOnTests.java | 15 +++++++++++++++ rxjava-core/src/test/java/rx/ReduceTests.java | 15 +++++++++++++++ rxjava-core/src/test/java/rx/RefCountTests.java | 15 +++++++++++++++ rxjava-core/src/test/java/rx/ScanTests.java | 15 +++++++++++++++ rxjava-core/src/test/java/rx/StartWithTests.java | 15 +++++++++++++++ .../src/test/java/rx/ThrottleFirstTests.java | 15 +++++++++++++++ .../src/test/java/rx/ThrottleLastTests.java | 15 +++++++++++++++ .../test/java/rx/ThrottleWithTimeoutTests.java | 15 +++++++++++++++ rxjava-core/src/test/java/rx/ZipTests.java | 15 +++++++++++++++ .../concurrency/CurrentThreadSchedulerTest.java | 15 +++++++++++++++ .../rx/concurrency/ImmediateSchedulerTest.java | 15 +++++++++++++++ .../rx/observables/BlockingObservableTest.java | 15 +++++++++++++++ .../test/java/rx/operators/OperationAllTest.java | 15 +++++++++++++++ .../test/java/rx/operators/OperationAnyTest.java | 15 +++++++++++++++ .../java/rx/operators/OperationAverageTest.java | 15 +++++++++++++++ .../java/rx/operators/OperationBufferTest.java | 15 +++++++++++++++ .../java/rx/operators/OperationCacheTest.java | 15 +++++++++++++++ .../test/java/rx/operators/OperationCastTest.java | 15 +++++++++++++++ .../rx/operators/OperationCombineLatestTest.java | 15 +++++++++++++++ .../java/rx/operators/OperationConcatTest.java | 15 +++++++++++++++ .../java/rx/operators/OperationDebounceTest.java | 15 +++++++++++++++ .../rx/operators/OperationDefaultIfEmptyTest.java | 15 +++++++++++++++ .../java/rx/operators/OperationDeferTest.java | 15 +++++++++++++++ .../rx/operators/OperationDematerializeTest.java | 15 +++++++++++++++ .../java/rx/operators/OperationDistinctTest.java | 15 +++++++++++++++ .../OperationDistinctUntilChangedTest.java | 15 +++++++++++++++ .../java/rx/operators/OperationElementAtTest.java | 15 +++++++++++++++ .../java/rx/operators/OperationFilterTest.java | 15 +++++++++++++++ .../java/rx/operators/OperationFinallyTest.java | 15 +++++++++++++++ .../rx/operators/OperationFirstOrDefaultTest.java | 15 +++++++++++++++ .../java/rx/operators/OperationGroupByTest.java | 15 +++++++++++++++ .../java/rx/operators/OperationIntervalTest.java | 15 +++++++++++++++ .../test/java/rx/operators/OperationMapTest.java | 15 +++++++++++++++ .../rx/operators/OperationMaterializeTest.java | 15 +++++++++++++++ .../operators/OperationMergeDelayErrorTest.java | 15 +++++++++++++++ .../java/rx/operators/OperationMergeTest.java | 15 +++++++++++++++ .../rx/operators/OperationMostRecentTest.java | 15 +++++++++++++++ .../java/rx/operators/OperationMulticastTest.java | 15 +++++++++++++++ .../test/java/rx/operators/OperationNextTest.java | 15 +++++++++++++++ .../java/rx/operators/OperationObserveOnTest.java | 15 +++++++++++++++ ...OperationOnErrorResumeNextViaFunctionTest.java | 15 +++++++++++++++ ...erationOnErrorResumeNextViaObservableTest.java | 15 +++++++++++++++ .../rx/operators/OperationOnErrorReturnTest.java | 15 +++++++++++++++ ...ionOnExceptionResumeNextViaObservableTest.java | 15 +++++++++++++++ .../java/rx/operators/OperationParallelTest.java | 15 +++++++++++++++ .../java/rx/operators/OperationRetryTest.java | 15 +++++++++++++++ .../java/rx/operators/OperationSampleTest.java | 15 +++++++++++++++ .../test/java/rx/operators/OperationScanTest.java | 15 +++++++++++++++ .../java/rx/operators/OperationSkipLastTest.java | 15 +++++++++++++++ .../test/java/rx/operators/OperationSkipTest.java | 15 +++++++++++++++ .../java/rx/operators/OperationSkipWhileTest.java | 15 +++++++++++++++ .../rx/operators/OperationSubscribeOnTest.java | 15 +++++++++++++++ .../test/java/rx/operators/OperationSumTest.java | 15 +++++++++++++++ .../java/rx/operators/OperationSwitchTest.java | 15 +++++++++++++++ .../rx/operators/OperationSynchronizeTest.java | 15 +++++++++++++++ .../java/rx/operators/OperationTakeLastTest.java | 15 +++++++++++++++ .../test/java/rx/operators/OperationTakeTest.java | 15 +++++++++++++++ .../java/rx/operators/OperationTakeUntilTest.java | 15 +++++++++++++++ .../java/rx/operators/OperationTakeWhileTest.java | 15 +++++++++++++++ .../rx/operators/OperationThrottleFirstTest.java | 15 +++++++++++++++ .../rx/operators/OperationTimeIntervalTest.java | 15 +++++++++++++++ .../java/rx/operators/OperationToFutureTest.java | 15 +++++++++++++++ .../rx/operators/OperationToIteratorTest.java | 15 +++++++++++++++ .../OperationToObservableFutureTest.java | 15 +++++++++++++++ .../OperationToObservableIterableTest.java | 15 +++++++++++++++ .../operators/OperationToObservableListTest.java | 15 +++++++++++++++ .../OperationToObservableSortedListTest.java | 15 +++++++++++++++ .../java/rx/operators/OperationWindowTest.java | 15 +++++++++++++++ .../test/java/rx/operators/OperationZipTest.java | 15 +++++++++++++++ .../java/rx/operators/OperatorTesterTest.java | 15 +++++++++++++++ .../operators/SafeObservableSubscriptionTest.java | 15 +++++++++++++++ .../rx/operators/SynchronizedObserverTest.java | 15 +++++++++++++++ .../src/test/java/rx/operators/TakeWhileTest.java | 15 +++++++++++++++ .../rx/operators/TimeIntervalObserverTest.java | 15 +++++++++++++++ .../test/java/rx/plugins/RxJavaPluginsTest.java | 15 +++++++++++++++ .../test/java/rx/subjects/AsyncSubjectTest.java | 15 +++++++++++++++ .../java/rx/subjects/BehaviorSubjectTest.java | 15 +++++++++++++++ .../test/java/rx/subjects/PublishSubjectTest.java | 15 +++++++++++++++ .../test/java/rx/subjects/ReplaySubjectTest.java | 15 +++++++++++++++ .../subscriptions/CompositeSubscriptionTest.java | 15 +++++++++++++++ .../java/rx/subscriptions/SubscriptionsTest.java | 15 +++++++++++++++ rxjava-core/src/test/java/rx/util/RangeTest.java | 15 +++++++++++++++ 108 files changed, 1620 insertions(+) diff --git a/language-adaptors/rxjava-groovy/src/test/groovy/rx/lang/groovy/TestParallel.groovy b/language-adaptors/rxjava-groovy/src/test/groovy/rx/lang/groovy/TestParallel.groovy index c2e2eb52bd..509b7b0ca5 100644 --- a/language-adaptors/rxjava-groovy/src/test/groovy/rx/lang/groovy/TestParallel.groovy +++ b/language-adaptors/rxjava-groovy/src/test/groovy/rx/lang/groovy/TestParallel.groovy @@ -1,3 +1,18 @@ +/** + * Copyright 2013 Netflix, Inc. + * + * 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 rx.lang.groovy import org.junit.Test diff --git a/language-adaptors/rxjava-scala/src/examples/java/rx/lang/scala/examples/MovieLibUsage.java b/language-adaptors/rxjava-scala/src/examples/java/rx/lang/scala/examples/MovieLibUsage.java index cacd48bd79..84920e0d12 100644 --- a/language-adaptors/rxjava-scala/src/examples/java/rx/lang/scala/examples/MovieLibUsage.java +++ b/language-adaptors/rxjava-scala/src/examples/java/rx/lang/scala/examples/MovieLibUsage.java @@ -1,3 +1,18 @@ +/** + * Copyright 2013 Netflix, Inc. + * + * 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 rx.lang.scala.examples; import org.junit.Test; diff --git a/language-adaptors/rxjava-scala/src/examples/scala/rx/lang/scala/examples/Olympics.scala b/language-adaptors/rxjava-scala/src/examples/scala/rx/lang/scala/examples/Olympics.scala index d2a0cdcbcb..699523ea55 100644 --- a/language-adaptors/rxjava-scala/src/examples/scala/rx/lang/scala/examples/Olympics.scala +++ b/language-adaptors/rxjava-scala/src/examples/scala/rx/lang/scala/examples/Olympics.scala @@ -1,3 +1,18 @@ +/** + * Copyright 2013 Netflix, Inc. + * + * 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 rx.lang.scala.examples import rx.lang.scala.Observable diff --git a/language-adaptors/rxjava-scala/src/main/scala/rx/lang/scala/Notification.scala b/language-adaptors/rxjava-scala/src/main/scala/rx/lang/scala/Notification.scala index 27fb82a69e..133157d5ca 100644 --- a/language-adaptors/rxjava-scala/src/main/scala/rx/lang/scala/Notification.scala +++ b/language-adaptors/rxjava-scala/src/main/scala/rx/lang/scala/Notification.scala @@ -1,3 +1,18 @@ +/** + * Copyright 2013 Netflix, Inc. + * + * 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 rx.lang.scala /** diff --git a/language-adaptors/rxjava-scala/src/main/scala/rx/lang/scala/Scheduler.scala b/language-adaptors/rxjava-scala/src/main/scala/rx/lang/scala/Scheduler.scala index c717a94af5..1165bd4620 100644 --- a/language-adaptors/rxjava-scala/src/main/scala/rx/lang/scala/Scheduler.scala +++ b/language-adaptors/rxjava-scala/src/main/scala/rx/lang/scala/Scheduler.scala @@ -1,3 +1,18 @@ +/** + * Copyright 2013 Netflix, Inc. + * + * 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 rx.lang.scala import java.util.Date diff --git a/language-adaptors/rxjava-scala/src/main/scala/rx/lang/scala/concurrency/Schedulers.scala b/language-adaptors/rxjava-scala/src/main/scala/rx/lang/scala/concurrency/Schedulers.scala index 8ba88ba2d0..960df660d4 100644 --- a/language-adaptors/rxjava-scala/src/main/scala/rx/lang/scala/concurrency/Schedulers.scala +++ b/language-adaptors/rxjava-scala/src/main/scala/rx/lang/scala/concurrency/Schedulers.scala @@ -1,3 +1,18 @@ +/** + * Copyright 2013 Netflix, Inc. + * + * 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 rx.lang.scala.concurrency import java.util.concurrent.Executor diff --git a/language-adaptors/rxjava-scala/src/main/scala/rx/lang/scala/concurrency/TestScheduler.scala b/language-adaptors/rxjava-scala/src/main/scala/rx/lang/scala/concurrency/TestScheduler.scala index 7023ca2f4e..a8090a887e 100644 --- a/language-adaptors/rxjava-scala/src/main/scala/rx/lang/scala/concurrency/TestScheduler.scala +++ b/language-adaptors/rxjava-scala/src/main/scala/rx/lang/scala/concurrency/TestScheduler.scala @@ -1,3 +1,18 @@ +/** + * Copyright 2013 Netflix, Inc. + * + * 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 rx.lang.scala.concurrency import scala.concurrent.duration.Duration diff --git a/language-adaptors/rxjava-scala/src/main/scala/rx/lang/scala/observables/package.scala b/language-adaptors/rxjava-scala/src/main/scala/rx/lang/scala/observables/package.scala index 8507f0a54c..2b43860b53 100644 --- a/language-adaptors/rxjava-scala/src/main/scala/rx/lang/scala/observables/package.scala +++ b/language-adaptors/rxjava-scala/src/main/scala/rx/lang/scala/observables/package.scala @@ -1,3 +1,18 @@ +/** + * Copyright 2013 Netflix, Inc. + * + * 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 rx.lang.scala /** diff --git a/language-adaptors/rxjava-scala/src/main/scala/rx/lang/scala/subjects/package.scala b/language-adaptors/rxjava-scala/src/main/scala/rx/lang/scala/subjects/package.scala index ec096e92eb..07076772f5 100644 --- a/language-adaptors/rxjava-scala/src/main/scala/rx/lang/scala/subjects/package.scala +++ b/language-adaptors/rxjava-scala/src/main/scala/rx/lang/scala/subjects/package.scala @@ -1,3 +1,18 @@ +/** + * Copyright 2013 Netflix, Inc. + * + * 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 rx.lang.scala /** diff --git a/language-adaptors/rxjava-scala/src/test/scala/rx/lang/scala/CompletenessTest.scala b/language-adaptors/rxjava-scala/src/test/scala/rx/lang/scala/CompletenessTest.scala index f38ac0d521..c5c13d3070 100644 --- a/language-adaptors/rxjava-scala/src/test/scala/rx/lang/scala/CompletenessTest.scala +++ b/language-adaptors/rxjava-scala/src/test/scala/rx/lang/scala/CompletenessTest.scala @@ -1,3 +1,18 @@ +/** + * Copyright 2013 Netflix, Inc. + * + * 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 rx.lang.scala import java.util.Calendar diff --git a/rxjava-contrib/rxjava-android/src/main/java/rx/android/concurrency/AndroidSchedulers.java b/rxjava-contrib/rxjava-android/src/main/java/rx/android/concurrency/AndroidSchedulers.java index 36a8154d16..0b238b1644 100644 --- a/rxjava-contrib/rxjava-android/src/main/java/rx/android/concurrency/AndroidSchedulers.java +++ b/rxjava-contrib/rxjava-android/src/main/java/rx/android/concurrency/AndroidSchedulers.java @@ -1,3 +1,18 @@ +/** + * Copyright 2013 Netflix, Inc. + * + * 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 rx.android.concurrency; import android.os.Handler; diff --git a/rxjava-contrib/rxjava-android/src/main/java/rx/android/concurrency/HandlerThreadScheduler.java b/rxjava-contrib/rxjava-android/src/main/java/rx/android/concurrency/HandlerThreadScheduler.java index cd1af987ae..ae01d17c1a 100644 --- a/rxjava-contrib/rxjava-android/src/main/java/rx/android/concurrency/HandlerThreadScheduler.java +++ b/rxjava-contrib/rxjava-android/src/main/java/rx/android/concurrency/HandlerThreadScheduler.java @@ -1,3 +1,18 @@ +/** + * Copyright 2013 Netflix, Inc. + * + * 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 rx.android.concurrency; import android.os.Handler; diff --git a/rxjava-contrib/rxjava-android/src/main/java/rx/android/observables/AndroidObservable.java b/rxjava-contrib/rxjava-android/src/main/java/rx/android/observables/AndroidObservable.java index e411074be3..c70ba970c3 100644 --- a/rxjava-contrib/rxjava-android/src/main/java/rx/android/observables/AndroidObservable.java +++ b/rxjava-contrib/rxjava-android/src/main/java/rx/android/observables/AndroidObservable.java @@ -1,3 +1,18 @@ +/** + * Copyright 2013 Netflix, Inc. + * + * 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 rx.android.observables; import rx.Observable; diff --git a/rxjava-contrib/rxjava-android/src/main/java/rx/operators/OperationObserveFromAndroidComponent.java b/rxjava-contrib/rxjava-android/src/main/java/rx/operators/OperationObserveFromAndroidComponent.java index a1aaff5354..cfce38f8bb 100644 --- a/rxjava-contrib/rxjava-android/src/main/java/rx/operators/OperationObserveFromAndroidComponent.java +++ b/rxjava-contrib/rxjava-android/src/main/java/rx/operators/OperationObserveFromAndroidComponent.java @@ -1,3 +1,18 @@ +/** + * Copyright 2013 Netflix, Inc. + * + * 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 rx.operators; import static org.mockito.Matchers.any; diff --git a/rxjava-contrib/rxjava-apache-http/src/test/java/rx/apache/http/examples/ExampleObservableHttp.java b/rxjava-contrib/rxjava-apache-http/src/test/java/rx/apache/http/examples/ExampleObservableHttp.java index 3f396a3894..4fe7e0549a 100644 --- a/rxjava-contrib/rxjava-apache-http/src/test/java/rx/apache/http/examples/ExampleObservableHttp.java +++ b/rxjava-contrib/rxjava-apache-http/src/test/java/rx/apache/http/examples/ExampleObservableHttp.java @@ -1,3 +1,18 @@ +/** + * Copyright 2013 Netflix, Inc. + * + * 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 rx.apache.http.examples; import java.io.IOException; diff --git a/rxjava-core/src/main/java/rx/operators/OperationCast.java b/rxjava-core/src/main/java/rx/operators/OperationCast.java index 0643624a02..dc54c204f6 100644 --- a/rxjava-core/src/main/java/rx/operators/OperationCast.java +++ b/rxjava-core/src/main/java/rx/operators/OperationCast.java @@ -1,3 +1,18 @@ +/** + * Copyright 2013 Netflix, Inc. + * + * 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 rx.operators; import rx.Observable; diff --git a/rxjava-core/src/main/java/rx/operators/OperationDefaultIfEmpty.java b/rxjava-core/src/main/java/rx/operators/OperationDefaultIfEmpty.java index 7c08aca675..7bc74ac156 100644 --- a/rxjava-core/src/main/java/rx/operators/OperationDefaultIfEmpty.java +++ b/rxjava-core/src/main/java/rx/operators/OperationDefaultIfEmpty.java @@ -1,3 +1,18 @@ +/** + * Copyright 2013 Netflix, Inc. + * + * 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 rx.operators; import rx.Observable; diff --git a/rxjava-core/src/main/java/rx/subscriptions/MultipleAssignmentSubscription.java b/rxjava-core/src/main/java/rx/subscriptions/MultipleAssignmentSubscription.java index 2af6501425..74ed285f77 100644 --- a/rxjava-core/src/main/java/rx/subscriptions/MultipleAssignmentSubscription.java +++ b/rxjava-core/src/main/java/rx/subscriptions/MultipleAssignmentSubscription.java @@ -1,3 +1,18 @@ +/** + * Copyright 2013 Netflix, Inc. + * + * 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 rx.subscriptions; import java.util.concurrent.atomic.AtomicBoolean; diff --git a/rxjava-core/src/test/java/rx/CombineLatestTests.java b/rxjava-core/src/test/java/rx/CombineLatestTests.java index 78dbd4c4e3..c52daa3870 100644 --- a/rxjava-core/src/test/java/rx/CombineLatestTests.java +++ b/rxjava-core/src/test/java/rx/CombineLatestTests.java @@ -1,3 +1,18 @@ +/** + * Copyright 2013 Netflix, Inc. + * + * 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 rx; import org.junit.Test; diff --git a/rxjava-core/src/test/java/rx/ConcatTests.java b/rxjava-core/src/test/java/rx/ConcatTests.java index a83e9f5a9b..80f7eb5ef7 100644 --- a/rxjava-core/src/test/java/rx/ConcatTests.java +++ b/rxjava-core/src/test/java/rx/ConcatTests.java @@ -1,3 +1,18 @@ +/** + * Copyright 2013 Netflix, Inc. + * + * 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 rx; import static org.junit.Assert.*; diff --git a/rxjava-core/src/test/java/rx/CovarianceTest.java b/rxjava-core/src/test/java/rx/CovarianceTest.java index 01f2030c52..48ca64f61e 100644 --- a/rxjava-core/src/test/java/rx/CovarianceTest.java +++ b/rxjava-core/src/test/java/rx/CovarianceTest.java @@ -1,3 +1,18 @@ +/** + * Copyright 2013 Netflix, Inc. + * + * 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 rx; import java.util.ArrayList; diff --git a/rxjava-core/src/test/java/rx/EventStream.java b/rxjava-core/src/test/java/rx/EventStream.java index 5fbffba528..f32787bac1 100644 --- a/rxjava-core/src/test/java/rx/EventStream.java +++ b/rxjava-core/src/test/java/rx/EventStream.java @@ -1,3 +1,18 @@ +/** + * Copyright 2013 Netflix, Inc. + * + * 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 rx; import java.util.Collections; diff --git a/rxjava-core/src/test/java/rx/GroupByTests.java b/rxjava-core/src/test/java/rx/GroupByTests.java index 87448f8510..de3310b35c 100644 --- a/rxjava-core/src/test/java/rx/GroupByTests.java +++ b/rxjava-core/src/test/java/rx/GroupByTests.java @@ -1,3 +1,18 @@ +/** + * Copyright 2013 Netflix, Inc. + * + * 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 rx; import org.junit.Test; diff --git a/rxjava-core/src/test/java/rx/IntervalDemo.java b/rxjava-core/src/test/java/rx/IntervalDemo.java index 2d16901674..0222bc1b55 100644 --- a/rxjava-core/src/test/java/rx/IntervalDemo.java +++ b/rxjava-core/src/test/java/rx/IntervalDemo.java @@ -1,3 +1,18 @@ +/** + * Copyright 2013 Netflix, Inc. + * + * 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 rx; import java.util.ArrayList; diff --git a/rxjava-core/src/test/java/rx/MergeTests.java b/rxjava-core/src/test/java/rx/MergeTests.java index 83a71044ef..1f697ce46a 100644 --- a/rxjava-core/src/test/java/rx/MergeTests.java +++ b/rxjava-core/src/test/java/rx/MergeTests.java @@ -1,3 +1,18 @@ +/** + * Copyright 2013 Netflix, Inc. + * + * 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 rx; import static org.junit.Assert.*; diff --git a/rxjava-core/src/test/java/rx/ObservableWindowTests.java b/rxjava-core/src/test/java/rx/ObservableWindowTests.java index 75e5cb565a..987ce255c9 100644 --- a/rxjava-core/src/test/java/rx/ObservableWindowTests.java +++ b/rxjava-core/src/test/java/rx/ObservableWindowTests.java @@ -1,3 +1,18 @@ +/** + * Copyright 2013 Netflix, Inc. + * + * 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 rx; import static org.junit.Assert.*; diff --git a/rxjava-core/src/test/java/rx/ObserveOnTests.java b/rxjava-core/src/test/java/rx/ObserveOnTests.java index e6e4e46b2d..57d13c3585 100644 --- a/rxjava-core/src/test/java/rx/ObserveOnTests.java +++ b/rxjava-core/src/test/java/rx/ObserveOnTests.java @@ -1,3 +1,18 @@ +/** + * Copyright 2013 Netflix, Inc. + * + * 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 rx; import static org.junit.Assert.*; diff --git a/rxjava-core/src/test/java/rx/ReduceTests.java b/rxjava-core/src/test/java/rx/ReduceTests.java index b812ba3638..08ff57405b 100644 --- a/rxjava-core/src/test/java/rx/ReduceTests.java +++ b/rxjava-core/src/test/java/rx/ReduceTests.java @@ -1,3 +1,18 @@ +/** + * Copyright 2013 Netflix, Inc. + * + * 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 rx; import static org.junit.Assert.*; diff --git a/rxjava-core/src/test/java/rx/RefCountTests.java b/rxjava-core/src/test/java/rx/RefCountTests.java index 94b4ed50d4..b83e94fcae 100644 --- a/rxjava-core/src/test/java/rx/RefCountTests.java +++ b/rxjava-core/src/test/java/rx/RefCountTests.java @@ -1,3 +1,18 @@ +/** + * Copyright 2013 Netflix, Inc. + * + * 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 rx; import static org.junit.Assert.*; diff --git a/rxjava-core/src/test/java/rx/ScanTests.java b/rxjava-core/src/test/java/rx/ScanTests.java index bef93e471b..d7948963d7 100644 --- a/rxjava-core/src/test/java/rx/ScanTests.java +++ b/rxjava-core/src/test/java/rx/ScanTests.java @@ -1,3 +1,18 @@ +/** + * Copyright 2013 Netflix, Inc. + * + * 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 rx; import java.util.HashMap; diff --git a/rxjava-core/src/test/java/rx/StartWithTests.java b/rxjava-core/src/test/java/rx/StartWithTests.java index 2204b6f081..5bf3c518c2 100644 --- a/rxjava-core/src/test/java/rx/StartWithTests.java +++ b/rxjava-core/src/test/java/rx/StartWithTests.java @@ -1,3 +1,18 @@ +/** + * Copyright 2013 Netflix, Inc. + * + * 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 rx; import static org.junit.Assert.*; diff --git a/rxjava-core/src/test/java/rx/ThrottleFirstTests.java b/rxjava-core/src/test/java/rx/ThrottleFirstTests.java index 5e8f3ef1cb..655754d398 100644 --- a/rxjava-core/src/test/java/rx/ThrottleFirstTests.java +++ b/rxjava-core/src/test/java/rx/ThrottleFirstTests.java @@ -1,3 +1,18 @@ +/** + * Copyright 2013 Netflix, Inc. + * + * 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 rx; import static org.mockito.Mockito.*; diff --git a/rxjava-core/src/test/java/rx/ThrottleLastTests.java b/rxjava-core/src/test/java/rx/ThrottleLastTests.java index 742bbc09ba..c3a037a78c 100644 --- a/rxjava-core/src/test/java/rx/ThrottleLastTests.java +++ b/rxjava-core/src/test/java/rx/ThrottleLastTests.java @@ -1,3 +1,18 @@ +/** + * Copyright 2013 Netflix, Inc. + * + * 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 rx; import static org.mockito.Mockito.*; diff --git a/rxjava-core/src/test/java/rx/ThrottleWithTimeoutTests.java b/rxjava-core/src/test/java/rx/ThrottleWithTimeoutTests.java index 3503fe7adb..ead4ddb24e 100644 --- a/rxjava-core/src/test/java/rx/ThrottleWithTimeoutTests.java +++ b/rxjava-core/src/test/java/rx/ThrottleWithTimeoutTests.java @@ -1,3 +1,18 @@ +/** + * Copyright 2013 Netflix, Inc. + * + * 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 rx; import static org.mockito.Mockito.*; diff --git a/rxjava-core/src/test/java/rx/ZipTests.java b/rxjava-core/src/test/java/rx/ZipTests.java index 64d96c904a..dd406ee2e0 100644 --- a/rxjava-core/src/test/java/rx/ZipTests.java +++ b/rxjava-core/src/test/java/rx/ZipTests.java @@ -1,3 +1,18 @@ +/** + * Copyright 2013 Netflix, Inc. + * + * 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 rx; import java.util.HashMap; diff --git a/rxjava-core/src/test/java/rx/concurrency/CurrentThreadSchedulerTest.java b/rxjava-core/src/test/java/rx/concurrency/CurrentThreadSchedulerTest.java index e9a1a1061a..3613b7c592 100644 --- a/rxjava-core/src/test/java/rx/concurrency/CurrentThreadSchedulerTest.java +++ b/rxjava-core/src/test/java/rx/concurrency/CurrentThreadSchedulerTest.java @@ -1,3 +1,18 @@ +/** + * Copyright 2013 Netflix, Inc. + * + * 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 rx.concurrency; import static org.mockito.Mockito.*; diff --git a/rxjava-core/src/test/java/rx/concurrency/ImmediateSchedulerTest.java b/rxjava-core/src/test/java/rx/concurrency/ImmediateSchedulerTest.java index fc2da52963..593f6b6a52 100644 --- a/rxjava-core/src/test/java/rx/concurrency/ImmediateSchedulerTest.java +++ b/rxjava-core/src/test/java/rx/concurrency/ImmediateSchedulerTest.java @@ -1,3 +1,18 @@ +/** + * Copyright 2013 Netflix, Inc. + * + * 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 rx.concurrency; import static org.mockito.Mockito.*; diff --git a/rxjava-core/src/test/java/rx/observables/BlockingObservableTest.java b/rxjava-core/src/test/java/rx/observables/BlockingObservableTest.java index e97765c6ab..b546fd64bb 100644 --- a/rxjava-core/src/test/java/rx/observables/BlockingObservableTest.java +++ b/rxjava-core/src/test/java/rx/observables/BlockingObservableTest.java @@ -1,3 +1,18 @@ +/** + * Copyright 2013 Netflix, Inc. + * + * 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 rx.observables; import static org.junit.Assert.*; diff --git a/rxjava-core/src/test/java/rx/operators/OperationAllTest.java b/rxjava-core/src/test/java/rx/operators/OperationAllTest.java index 8418e821d6..0b05ee1d4e 100644 --- a/rxjava-core/src/test/java/rx/operators/OperationAllTest.java +++ b/rxjava-core/src/test/java/rx/operators/OperationAllTest.java @@ -1,3 +1,18 @@ +/** + * Copyright 2013 Netflix, Inc. + * + * 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 rx.operators; import static org.mockito.Mockito.*; diff --git a/rxjava-core/src/test/java/rx/operators/OperationAnyTest.java b/rxjava-core/src/test/java/rx/operators/OperationAnyTest.java index f9e64791d8..f98149376a 100644 --- a/rxjava-core/src/test/java/rx/operators/OperationAnyTest.java +++ b/rxjava-core/src/test/java/rx/operators/OperationAnyTest.java @@ -1,3 +1,18 @@ +/** + * Copyright 2013 Netflix, Inc. + * + * 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 rx.operators; import static org.mockito.Mockito.*; diff --git a/rxjava-core/src/test/java/rx/operators/OperationAverageTest.java b/rxjava-core/src/test/java/rx/operators/OperationAverageTest.java index 5985959669..a8ffa4706b 100644 --- a/rxjava-core/src/test/java/rx/operators/OperationAverageTest.java +++ b/rxjava-core/src/test/java/rx/operators/OperationAverageTest.java @@ -1,3 +1,18 @@ +/** + * Copyright 2013 Netflix, Inc. + * + * 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 rx.operators; import static org.mockito.Matchers.*; diff --git a/rxjava-core/src/test/java/rx/operators/OperationBufferTest.java b/rxjava-core/src/test/java/rx/operators/OperationBufferTest.java index c9f0e8b8e7..9318af8fd6 100644 --- a/rxjava-core/src/test/java/rx/operators/OperationBufferTest.java +++ b/rxjava-core/src/test/java/rx/operators/OperationBufferTest.java @@ -1,3 +1,18 @@ +/** + * Copyright 2013 Netflix, Inc. + * + * 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 rx.operators; import static org.junit.Assert.*; diff --git a/rxjava-core/src/test/java/rx/operators/OperationCacheTest.java b/rxjava-core/src/test/java/rx/operators/OperationCacheTest.java index 60f4b5f4fc..79a811b6de 100644 --- a/rxjava-core/src/test/java/rx/operators/OperationCacheTest.java +++ b/rxjava-core/src/test/java/rx/operators/OperationCacheTest.java @@ -1,3 +1,18 @@ +/** + * Copyright 2013 Netflix, Inc. + * + * 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 rx.operators; import static org.junit.Assert.*; diff --git a/rxjava-core/src/test/java/rx/operators/OperationCastTest.java b/rxjava-core/src/test/java/rx/operators/OperationCastTest.java index f5c0b6b515..782fe6bc90 100644 --- a/rxjava-core/src/test/java/rx/operators/OperationCastTest.java +++ b/rxjava-core/src/test/java/rx/operators/OperationCastTest.java @@ -1,3 +1,18 @@ +/** + * Copyright 2013 Netflix, Inc. + * + * 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 rx.operators; import static org.mockito.Mockito.*; diff --git a/rxjava-core/src/test/java/rx/operators/OperationCombineLatestTest.java b/rxjava-core/src/test/java/rx/operators/OperationCombineLatestTest.java index b5bb863b2e..c576337e1e 100644 --- a/rxjava-core/src/test/java/rx/operators/OperationCombineLatestTest.java +++ b/rxjava-core/src/test/java/rx/operators/OperationCombineLatestTest.java @@ -1,3 +1,18 @@ +/** + * Copyright 2013 Netflix, Inc. + * + * 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 rx.operators; import static org.mockito.Matchers.*; diff --git a/rxjava-core/src/test/java/rx/operators/OperationConcatTest.java b/rxjava-core/src/test/java/rx/operators/OperationConcatTest.java index d6fc1e2d56..f42d8b81ad 100644 --- a/rxjava-core/src/test/java/rx/operators/OperationConcatTest.java +++ b/rxjava-core/src/test/java/rx/operators/OperationConcatTest.java @@ -1,3 +1,18 @@ +/** + * Copyright 2013 Netflix, Inc. + * + * 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 rx.operators; import static org.junit.Assert.*; diff --git a/rxjava-core/src/test/java/rx/operators/OperationDebounceTest.java b/rxjava-core/src/test/java/rx/operators/OperationDebounceTest.java index 667c607301..e831c7b829 100644 --- a/rxjava-core/src/test/java/rx/operators/OperationDebounceTest.java +++ b/rxjava-core/src/test/java/rx/operators/OperationDebounceTest.java @@ -1,3 +1,18 @@ +/** + * Copyright 2013 Netflix, Inc. + * + * 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 rx.operators; import static org.mockito.Matchers.*; diff --git a/rxjava-core/src/test/java/rx/operators/OperationDefaultIfEmptyTest.java b/rxjava-core/src/test/java/rx/operators/OperationDefaultIfEmptyTest.java index fa4910707c..68003ceb01 100644 --- a/rxjava-core/src/test/java/rx/operators/OperationDefaultIfEmptyTest.java +++ b/rxjava-core/src/test/java/rx/operators/OperationDefaultIfEmptyTest.java @@ -1,3 +1,18 @@ +/** + * Copyright 2013 Netflix, Inc. + * + * 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 rx.operators; import static org.mockito.Mockito.*; diff --git a/rxjava-core/src/test/java/rx/operators/OperationDeferTest.java b/rxjava-core/src/test/java/rx/operators/OperationDeferTest.java index 6ad98c9a8d..550f428134 100644 --- a/rxjava-core/src/test/java/rx/operators/OperationDeferTest.java +++ b/rxjava-core/src/test/java/rx/operators/OperationDeferTest.java @@ -1,3 +1,18 @@ +/** + * Copyright 2013 Netflix, Inc. + * + * 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 rx.operators; import static org.mockito.Mockito.*; diff --git a/rxjava-core/src/test/java/rx/operators/OperationDematerializeTest.java b/rxjava-core/src/test/java/rx/operators/OperationDematerializeTest.java index 3ca31f160c..1465b4f3d2 100644 --- a/rxjava-core/src/test/java/rx/operators/OperationDematerializeTest.java +++ b/rxjava-core/src/test/java/rx/operators/OperationDematerializeTest.java @@ -1,3 +1,18 @@ +/** + * Copyright 2013 Netflix, Inc. + * + * 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 rx.operators; import static org.mockito.Matchers.*; diff --git a/rxjava-core/src/test/java/rx/operators/OperationDistinctTest.java b/rxjava-core/src/test/java/rx/operators/OperationDistinctTest.java index 9d0e1569b5..de57e8fc1e 100644 --- a/rxjava-core/src/test/java/rx/operators/OperationDistinctTest.java +++ b/rxjava-core/src/test/java/rx/operators/OperationDistinctTest.java @@ -1,3 +1,18 @@ +/** + * Copyright 2013 Netflix, Inc. + * + * 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 rx.operators; import static org.mockito.Matchers.*; diff --git a/rxjava-core/src/test/java/rx/operators/OperationDistinctUntilChangedTest.java b/rxjava-core/src/test/java/rx/operators/OperationDistinctUntilChangedTest.java index bd31b91ebc..b4568baaf7 100644 --- a/rxjava-core/src/test/java/rx/operators/OperationDistinctUntilChangedTest.java +++ b/rxjava-core/src/test/java/rx/operators/OperationDistinctUntilChangedTest.java @@ -1,3 +1,18 @@ +/** + * Copyright 2013 Netflix, Inc. + * + * 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 rx.operators; import static org.mockito.Matchers.*; diff --git a/rxjava-core/src/test/java/rx/operators/OperationElementAtTest.java b/rxjava-core/src/test/java/rx/operators/OperationElementAtTest.java index 8642e78300..a28de23d08 100644 --- a/rxjava-core/src/test/java/rx/operators/OperationElementAtTest.java +++ b/rxjava-core/src/test/java/rx/operators/OperationElementAtTest.java @@ -1,3 +1,18 @@ +/** + * Copyright 2013 Netflix, Inc. + * + * 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 rx.operators; import static org.junit.Assert.*; diff --git a/rxjava-core/src/test/java/rx/operators/OperationFilterTest.java b/rxjava-core/src/test/java/rx/operators/OperationFilterTest.java index 88fb4deacb..c22c3d46b8 100644 --- a/rxjava-core/src/test/java/rx/operators/OperationFilterTest.java +++ b/rxjava-core/src/test/java/rx/operators/OperationFilterTest.java @@ -1,3 +1,18 @@ +/** + * Copyright 2013 Netflix, Inc. + * + * 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 rx.operators; import static org.mockito.Matchers.*; diff --git a/rxjava-core/src/test/java/rx/operators/OperationFinallyTest.java b/rxjava-core/src/test/java/rx/operators/OperationFinallyTest.java index c0fd0d9ef2..1ce2111fe9 100644 --- a/rxjava-core/src/test/java/rx/operators/OperationFinallyTest.java +++ b/rxjava-core/src/test/java/rx/operators/OperationFinallyTest.java @@ -1,3 +1,18 @@ +/** + * Copyright 2013 Netflix, Inc. + * + * 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 rx.operators; import static org.mockito.Mockito.*; diff --git a/rxjava-core/src/test/java/rx/operators/OperationFirstOrDefaultTest.java b/rxjava-core/src/test/java/rx/operators/OperationFirstOrDefaultTest.java index b17ba4740e..026caa1319 100644 --- a/rxjava-core/src/test/java/rx/operators/OperationFirstOrDefaultTest.java +++ b/rxjava-core/src/test/java/rx/operators/OperationFirstOrDefaultTest.java @@ -1,3 +1,18 @@ +/** + * Copyright 2013 Netflix, Inc. + * + * 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 rx.operators; import static org.mockito.Matchers.*; diff --git a/rxjava-core/src/test/java/rx/operators/OperationGroupByTest.java b/rxjava-core/src/test/java/rx/operators/OperationGroupByTest.java index 86d5af6e46..cf47d9e683 100644 --- a/rxjava-core/src/test/java/rx/operators/OperationGroupByTest.java +++ b/rxjava-core/src/test/java/rx/operators/OperationGroupByTest.java @@ -1,3 +1,18 @@ +/** + * Copyright 2013 Netflix, Inc. + * + * 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 rx.operators; import static org.junit.Assert.*; diff --git a/rxjava-core/src/test/java/rx/operators/OperationIntervalTest.java b/rxjava-core/src/test/java/rx/operators/OperationIntervalTest.java index 86764bd6ae..5f64452e3b 100644 --- a/rxjava-core/src/test/java/rx/operators/OperationIntervalTest.java +++ b/rxjava-core/src/test/java/rx/operators/OperationIntervalTest.java @@ -1,3 +1,18 @@ +/** + * Copyright 2013 Netflix, Inc. + * + * 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 rx.operators; import static org.mockito.Matchers.*; diff --git a/rxjava-core/src/test/java/rx/operators/OperationMapTest.java b/rxjava-core/src/test/java/rx/operators/OperationMapTest.java index 279a40eb7f..6d639d5235 100644 --- a/rxjava-core/src/test/java/rx/operators/OperationMapTest.java +++ b/rxjava-core/src/test/java/rx/operators/OperationMapTest.java @@ -1,3 +1,18 @@ +/** + * Copyright 2013 Netflix, Inc. + * + * 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 rx.operators; import static org.junit.Assert.*; diff --git a/rxjava-core/src/test/java/rx/operators/OperationMaterializeTest.java b/rxjava-core/src/test/java/rx/operators/OperationMaterializeTest.java index 0795ec03ed..54d1ab0474 100644 --- a/rxjava-core/src/test/java/rx/operators/OperationMaterializeTest.java +++ b/rxjava-core/src/test/java/rx/operators/OperationMaterializeTest.java @@ -1,3 +1,18 @@ +/** + * Copyright 2013 Netflix, Inc. + * + * 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 rx.operators; import static org.junit.Assert.*; diff --git a/rxjava-core/src/test/java/rx/operators/OperationMergeDelayErrorTest.java b/rxjava-core/src/test/java/rx/operators/OperationMergeDelayErrorTest.java index 50ebda0bb3..693b9d4801 100644 --- a/rxjava-core/src/test/java/rx/operators/OperationMergeDelayErrorTest.java +++ b/rxjava-core/src/test/java/rx/operators/OperationMergeDelayErrorTest.java @@ -1,3 +1,18 @@ +/** + * Copyright 2013 Netflix, Inc. + * + * 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 rx.operators; import static org.junit.Assert.*; diff --git a/rxjava-core/src/test/java/rx/operators/OperationMergeTest.java b/rxjava-core/src/test/java/rx/operators/OperationMergeTest.java index d7d399486e..311a838691 100644 --- a/rxjava-core/src/test/java/rx/operators/OperationMergeTest.java +++ b/rxjava-core/src/test/java/rx/operators/OperationMergeTest.java @@ -1,3 +1,18 @@ +/** + * Copyright 2013 Netflix, Inc. + * + * 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 rx.operators; import static org.junit.Assert.*; diff --git a/rxjava-core/src/test/java/rx/operators/OperationMostRecentTest.java b/rxjava-core/src/test/java/rx/operators/OperationMostRecentTest.java index 9dfb1ef9c1..d20f79e819 100644 --- a/rxjava-core/src/test/java/rx/operators/OperationMostRecentTest.java +++ b/rxjava-core/src/test/java/rx/operators/OperationMostRecentTest.java @@ -1,3 +1,18 @@ +/** + * Copyright 2013 Netflix, Inc. + * + * 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 rx.operators; import static org.junit.Assert.*; diff --git a/rxjava-core/src/test/java/rx/operators/OperationMulticastTest.java b/rxjava-core/src/test/java/rx/operators/OperationMulticastTest.java index 9e0189941d..8f824f1484 100644 --- a/rxjava-core/src/test/java/rx/operators/OperationMulticastTest.java +++ b/rxjava-core/src/test/java/rx/operators/OperationMulticastTest.java @@ -1,3 +1,18 @@ +/** + * Copyright 2013 Netflix, Inc. + * + * 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 rx.operators; import static org.mockito.Mockito.*; diff --git a/rxjava-core/src/test/java/rx/operators/OperationNextTest.java b/rxjava-core/src/test/java/rx/operators/OperationNextTest.java index 4b16458c4e..140cc0560c 100644 --- a/rxjava-core/src/test/java/rx/operators/OperationNextTest.java +++ b/rxjava-core/src/test/java/rx/operators/OperationNextTest.java @@ -1,3 +1,18 @@ +/** + * Copyright 2013 Netflix, Inc. + * + * 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 rx.operators; import static org.junit.Assert.*; diff --git a/rxjava-core/src/test/java/rx/operators/OperationObserveOnTest.java b/rxjava-core/src/test/java/rx/operators/OperationObserveOnTest.java index 75f2603df7..e114f637ff 100644 --- a/rxjava-core/src/test/java/rx/operators/OperationObserveOnTest.java +++ b/rxjava-core/src/test/java/rx/operators/OperationObserveOnTest.java @@ -1,3 +1,18 @@ +/** + * Copyright 2013 Netflix, Inc. + * + * 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 rx.operators; import static org.junit.Assert.*; diff --git a/rxjava-core/src/test/java/rx/operators/OperationOnErrorResumeNextViaFunctionTest.java b/rxjava-core/src/test/java/rx/operators/OperationOnErrorResumeNextViaFunctionTest.java index ba81230ccf..ab9293251e 100644 --- a/rxjava-core/src/test/java/rx/operators/OperationOnErrorResumeNextViaFunctionTest.java +++ b/rxjava-core/src/test/java/rx/operators/OperationOnErrorResumeNextViaFunctionTest.java @@ -1,3 +1,18 @@ +/** + * Copyright 2013 Netflix, Inc. + * + * 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 rx.operators; import static org.junit.Assert.*; diff --git a/rxjava-core/src/test/java/rx/operators/OperationOnErrorResumeNextViaObservableTest.java b/rxjava-core/src/test/java/rx/operators/OperationOnErrorResumeNextViaObservableTest.java index 48ef273932..dcbbdc3fb4 100644 --- a/rxjava-core/src/test/java/rx/operators/OperationOnErrorResumeNextViaObservableTest.java +++ b/rxjava-core/src/test/java/rx/operators/OperationOnErrorResumeNextViaObservableTest.java @@ -1,3 +1,18 @@ +/** + * Copyright 2013 Netflix, Inc. + * + * 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 rx.operators; import static org.junit.Assert.*; diff --git a/rxjava-core/src/test/java/rx/operators/OperationOnErrorReturnTest.java b/rxjava-core/src/test/java/rx/operators/OperationOnErrorReturnTest.java index 288f4f4995..e436dd29ee 100644 --- a/rxjava-core/src/test/java/rx/operators/OperationOnErrorReturnTest.java +++ b/rxjava-core/src/test/java/rx/operators/OperationOnErrorReturnTest.java @@ -1,3 +1,18 @@ +/** + * Copyright 2013 Netflix, Inc. + * + * 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 rx.operators; import static org.junit.Assert.*; diff --git a/rxjava-core/src/test/java/rx/operators/OperationOnExceptionResumeNextViaObservableTest.java b/rxjava-core/src/test/java/rx/operators/OperationOnExceptionResumeNextViaObservableTest.java index 18326a306b..8b5cc9271a 100644 --- a/rxjava-core/src/test/java/rx/operators/OperationOnExceptionResumeNextViaObservableTest.java +++ b/rxjava-core/src/test/java/rx/operators/OperationOnExceptionResumeNextViaObservableTest.java @@ -1,3 +1,18 @@ +/** + * Copyright 2013 Netflix, Inc. + * + * 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 rx.operators; import static org.junit.Assert.*; diff --git a/rxjava-core/src/test/java/rx/operators/OperationParallelTest.java b/rxjava-core/src/test/java/rx/operators/OperationParallelTest.java index 2a0959a14f..d52c8bc0b9 100644 --- a/rxjava-core/src/test/java/rx/operators/OperationParallelTest.java +++ b/rxjava-core/src/test/java/rx/operators/OperationParallelTest.java @@ -1,3 +1,18 @@ +/** + * Copyright 2013 Netflix, Inc. + * + * 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 rx.operators; import static org.junit.Assert.*; diff --git a/rxjava-core/src/test/java/rx/operators/OperationRetryTest.java b/rxjava-core/src/test/java/rx/operators/OperationRetryTest.java index 40845167c4..1b6006b923 100644 --- a/rxjava-core/src/test/java/rx/operators/OperationRetryTest.java +++ b/rxjava-core/src/test/java/rx/operators/OperationRetryTest.java @@ -1,3 +1,18 @@ +/** + * Copyright 2013 Netflix, Inc. + * + * 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 rx.operators; import static org.mockito.Matchers.*; diff --git a/rxjava-core/src/test/java/rx/operators/OperationSampleTest.java b/rxjava-core/src/test/java/rx/operators/OperationSampleTest.java index 7ef3906eaa..d868697f9f 100644 --- a/rxjava-core/src/test/java/rx/operators/OperationSampleTest.java +++ b/rxjava-core/src/test/java/rx/operators/OperationSampleTest.java @@ -1,3 +1,18 @@ +/** + * Copyright 2013 Netflix, Inc. + * + * 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 rx.operators; import static org.mockito.Matchers.*; diff --git a/rxjava-core/src/test/java/rx/operators/OperationScanTest.java b/rxjava-core/src/test/java/rx/operators/OperationScanTest.java index 5c28f9efdf..0dedef787c 100644 --- a/rxjava-core/src/test/java/rx/operators/OperationScanTest.java +++ b/rxjava-core/src/test/java/rx/operators/OperationScanTest.java @@ -1,3 +1,18 @@ +/** + * Copyright 2013 Netflix, Inc. + * + * 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 rx.operators; import static org.mockito.Matchers.*; diff --git a/rxjava-core/src/test/java/rx/operators/OperationSkipLastTest.java b/rxjava-core/src/test/java/rx/operators/OperationSkipLastTest.java index ed213f3d5d..9391424e07 100644 --- a/rxjava-core/src/test/java/rx/operators/OperationSkipLastTest.java +++ b/rxjava-core/src/test/java/rx/operators/OperationSkipLastTest.java @@ -1,3 +1,18 @@ +/** + * Copyright 2013 Netflix, Inc. + * + * 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 rx.operators; import static org.mockito.Matchers.*; diff --git a/rxjava-core/src/test/java/rx/operators/OperationSkipTest.java b/rxjava-core/src/test/java/rx/operators/OperationSkipTest.java index 9aa3985315..16bc76820f 100644 --- a/rxjava-core/src/test/java/rx/operators/OperationSkipTest.java +++ b/rxjava-core/src/test/java/rx/operators/OperationSkipTest.java @@ -1,3 +1,18 @@ +/** + * Copyright 2013 Netflix, Inc. + * + * 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 rx.operators; import static org.mockito.Matchers.*; diff --git a/rxjava-core/src/test/java/rx/operators/OperationSkipWhileTest.java b/rxjava-core/src/test/java/rx/operators/OperationSkipWhileTest.java index 17d7aced6a..153c9fb14e 100644 --- a/rxjava-core/src/test/java/rx/operators/OperationSkipWhileTest.java +++ b/rxjava-core/src/test/java/rx/operators/OperationSkipWhileTest.java @@ -1,3 +1,18 @@ +/** + * Copyright 2013 Netflix, Inc. + * + * 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 rx.operators; import static org.mockito.Matchers.*; diff --git a/rxjava-core/src/test/java/rx/operators/OperationSubscribeOnTest.java b/rxjava-core/src/test/java/rx/operators/OperationSubscribeOnTest.java index d95bfdfc8a..635d4d8755 100644 --- a/rxjava-core/src/test/java/rx/operators/OperationSubscribeOnTest.java +++ b/rxjava-core/src/test/java/rx/operators/OperationSubscribeOnTest.java @@ -1,3 +1,18 @@ +/** + * Copyright 2013 Netflix, Inc. + * + * 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 rx.operators; import static org.mockito.Matchers.*; diff --git a/rxjava-core/src/test/java/rx/operators/OperationSumTest.java b/rxjava-core/src/test/java/rx/operators/OperationSumTest.java index 98a75fd836..e124ad13d5 100644 --- a/rxjava-core/src/test/java/rx/operators/OperationSumTest.java +++ b/rxjava-core/src/test/java/rx/operators/OperationSumTest.java @@ -1,3 +1,18 @@ +/** + * Copyright 2013 Netflix, Inc. + * + * 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 rx.operators; import static org.mockito.Matchers.*; diff --git a/rxjava-core/src/test/java/rx/operators/OperationSwitchTest.java b/rxjava-core/src/test/java/rx/operators/OperationSwitchTest.java index 090e9e5d68..fa38f02ff8 100644 --- a/rxjava-core/src/test/java/rx/operators/OperationSwitchTest.java +++ b/rxjava-core/src/test/java/rx/operators/OperationSwitchTest.java @@ -1,3 +1,18 @@ +/** + * Copyright 2013 Netflix, Inc. + * + * 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 rx.operators; import static org.mockito.Matchers.*; diff --git a/rxjava-core/src/test/java/rx/operators/OperationSynchronizeTest.java b/rxjava-core/src/test/java/rx/operators/OperationSynchronizeTest.java index 2815ea03f4..73db076000 100644 --- a/rxjava-core/src/test/java/rx/operators/OperationSynchronizeTest.java +++ b/rxjava-core/src/test/java/rx/operators/OperationSynchronizeTest.java @@ -1,3 +1,18 @@ +/** + * Copyright 2013 Netflix, Inc. + * + * 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 rx.operators; import static org.mockito.Matchers.*; diff --git a/rxjava-core/src/test/java/rx/operators/OperationTakeLastTest.java b/rxjava-core/src/test/java/rx/operators/OperationTakeLastTest.java index 2bc6ec2da8..5ec876368b 100644 --- a/rxjava-core/src/test/java/rx/operators/OperationTakeLastTest.java +++ b/rxjava-core/src/test/java/rx/operators/OperationTakeLastTest.java @@ -1,3 +1,18 @@ +/** + * Copyright 2013 Netflix, Inc. + * + * 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 rx.operators; import static org.mockito.Matchers.*; diff --git a/rxjava-core/src/test/java/rx/operators/OperationTakeTest.java b/rxjava-core/src/test/java/rx/operators/OperationTakeTest.java index 57a549e752..773154eda0 100644 --- a/rxjava-core/src/test/java/rx/operators/OperationTakeTest.java +++ b/rxjava-core/src/test/java/rx/operators/OperationTakeTest.java @@ -1,3 +1,18 @@ +/** + * Copyright 2013 Netflix, Inc. + * + * 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 rx.operators; import static org.junit.Assert.*; diff --git a/rxjava-core/src/test/java/rx/operators/OperationTakeUntilTest.java b/rxjava-core/src/test/java/rx/operators/OperationTakeUntilTest.java index 7033f9154a..c5182a71ba 100644 --- a/rxjava-core/src/test/java/rx/operators/OperationTakeUntilTest.java +++ b/rxjava-core/src/test/java/rx/operators/OperationTakeUntilTest.java @@ -1,3 +1,18 @@ +/** + * Copyright 2013 Netflix, Inc. + * + * 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 rx.operators; import static org.mockito.Mockito.*; diff --git a/rxjava-core/src/test/java/rx/operators/OperationTakeWhileTest.java b/rxjava-core/src/test/java/rx/operators/OperationTakeWhileTest.java index dee73d2cdf..08c6d8e83f 100644 --- a/rxjava-core/src/test/java/rx/operators/OperationTakeWhileTest.java +++ b/rxjava-core/src/test/java/rx/operators/OperationTakeWhileTest.java @@ -1,3 +1,18 @@ +/** + * Copyright 2013 Netflix, Inc. + * + * 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 rx.operators; import static org.junit.Assert.*; diff --git a/rxjava-core/src/test/java/rx/operators/OperationThrottleFirstTest.java b/rxjava-core/src/test/java/rx/operators/OperationThrottleFirstTest.java index f5e75175d9..ad58e13604 100644 --- a/rxjava-core/src/test/java/rx/operators/OperationThrottleFirstTest.java +++ b/rxjava-core/src/test/java/rx/operators/OperationThrottleFirstTest.java @@ -1,3 +1,18 @@ +/** + * Copyright 2013 Netflix, Inc. + * + * 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 rx.operators; import static org.mockito.Matchers.*; diff --git a/rxjava-core/src/test/java/rx/operators/OperationTimeIntervalTest.java b/rxjava-core/src/test/java/rx/operators/OperationTimeIntervalTest.java index ebbd27eb7a..056b97bf11 100644 --- a/rxjava-core/src/test/java/rx/operators/OperationTimeIntervalTest.java +++ b/rxjava-core/src/test/java/rx/operators/OperationTimeIntervalTest.java @@ -1,3 +1,18 @@ +/** + * Copyright 2013 Netflix, Inc. + * + * 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 rx.operators; import static org.mockito.Mockito.*; diff --git a/rxjava-core/src/test/java/rx/operators/OperationToFutureTest.java b/rxjava-core/src/test/java/rx/operators/OperationToFutureTest.java index c18131e5c7..ffaf775f8b 100644 --- a/rxjava-core/src/test/java/rx/operators/OperationToFutureTest.java +++ b/rxjava-core/src/test/java/rx/operators/OperationToFutureTest.java @@ -1,3 +1,18 @@ +/** + * Copyright 2013 Netflix, Inc. + * + * 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 rx.operators; import static org.junit.Assert.*; diff --git a/rxjava-core/src/test/java/rx/operators/OperationToIteratorTest.java b/rxjava-core/src/test/java/rx/operators/OperationToIteratorTest.java index 1994bd4a0c..b40dd9b62b 100644 --- a/rxjava-core/src/test/java/rx/operators/OperationToIteratorTest.java +++ b/rxjava-core/src/test/java/rx/operators/OperationToIteratorTest.java @@ -1,3 +1,18 @@ +/** + * Copyright 2013 Netflix, Inc. + * + * 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 rx.operators; import static org.junit.Assert.*; diff --git a/rxjava-core/src/test/java/rx/operators/OperationToObservableFutureTest.java b/rxjava-core/src/test/java/rx/operators/OperationToObservableFutureTest.java index a2f4daa711..dcc6efcc6a 100644 --- a/rxjava-core/src/test/java/rx/operators/OperationToObservableFutureTest.java +++ b/rxjava-core/src/test/java/rx/operators/OperationToObservableFutureTest.java @@ -1,3 +1,18 @@ +/** + * Copyright 2013 Netflix, Inc. + * + * 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 rx.operators; import static org.mockito.Mockito.*; diff --git a/rxjava-core/src/test/java/rx/operators/OperationToObservableIterableTest.java b/rxjava-core/src/test/java/rx/operators/OperationToObservableIterableTest.java index f99bb27428..8d8be93dcb 100644 --- a/rxjava-core/src/test/java/rx/operators/OperationToObservableIterableTest.java +++ b/rxjava-core/src/test/java/rx/operators/OperationToObservableIterableTest.java @@ -1,3 +1,18 @@ +/** + * Copyright 2013 Netflix, Inc. + * + * 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 rx.operators; import static org.mockito.Matchers.*; diff --git a/rxjava-core/src/test/java/rx/operators/OperationToObservableListTest.java b/rxjava-core/src/test/java/rx/operators/OperationToObservableListTest.java index 58d1456a80..1124ea6211 100644 --- a/rxjava-core/src/test/java/rx/operators/OperationToObservableListTest.java +++ b/rxjava-core/src/test/java/rx/operators/OperationToObservableListTest.java @@ -1,3 +1,18 @@ +/** + * Copyright 2013 Netflix, Inc. + * + * 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 rx.operators; import static org.mockito.Matchers.*; diff --git a/rxjava-core/src/test/java/rx/operators/OperationToObservableSortedListTest.java b/rxjava-core/src/test/java/rx/operators/OperationToObservableSortedListTest.java index 9dd78943a5..8c572a31b6 100644 --- a/rxjava-core/src/test/java/rx/operators/OperationToObservableSortedListTest.java +++ b/rxjava-core/src/test/java/rx/operators/OperationToObservableSortedListTest.java @@ -1,3 +1,18 @@ +/** + * Copyright 2013 Netflix, Inc. + * + * 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 rx.operators; import static org.mockito.Matchers.*; diff --git a/rxjava-core/src/test/java/rx/operators/OperationWindowTest.java b/rxjava-core/src/test/java/rx/operators/OperationWindowTest.java index 71a749a0ae..b26cf42cae 100644 --- a/rxjava-core/src/test/java/rx/operators/OperationWindowTest.java +++ b/rxjava-core/src/test/java/rx/operators/OperationWindowTest.java @@ -1,3 +1,18 @@ +/** + * Copyright 2013 Netflix, Inc. + * + * 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 rx.operators; import static org.junit.Assert.*; diff --git a/rxjava-core/src/test/java/rx/operators/OperationZipTest.java b/rxjava-core/src/test/java/rx/operators/OperationZipTest.java index bab2d7d2fe..43cca02327 100644 --- a/rxjava-core/src/test/java/rx/operators/OperationZipTest.java +++ b/rxjava-core/src/test/java/rx/operators/OperationZipTest.java @@ -1,3 +1,18 @@ +/** + * Copyright 2013 Netflix, Inc. + * + * 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 rx.operators; import static org.mockito.Matchers.*; diff --git a/rxjava-core/src/test/java/rx/operators/OperatorTesterTest.java b/rxjava-core/src/test/java/rx/operators/OperatorTesterTest.java index f5a4161708..645cea8e3b 100644 --- a/rxjava-core/src/test/java/rx/operators/OperatorTesterTest.java +++ b/rxjava-core/src/test/java/rx/operators/OperatorTesterTest.java @@ -1,3 +1,18 @@ +/** + * Copyright 2013 Netflix, Inc. + * + * 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 rx.operators; import org.junit.Ignore; diff --git a/rxjava-core/src/test/java/rx/operators/SafeObservableSubscriptionTest.java b/rxjava-core/src/test/java/rx/operators/SafeObservableSubscriptionTest.java index 99120b4348..bb317884bc 100644 --- a/rxjava-core/src/test/java/rx/operators/SafeObservableSubscriptionTest.java +++ b/rxjava-core/src/test/java/rx/operators/SafeObservableSubscriptionTest.java @@ -1,3 +1,18 @@ +/** + * Copyright 2013 Netflix, Inc. + * + * 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 rx.operators; import static org.mockito.Mockito.*; diff --git a/rxjava-core/src/test/java/rx/operators/SynchronizedObserverTest.java b/rxjava-core/src/test/java/rx/operators/SynchronizedObserverTest.java index 2780eef712..f1c40c3674 100644 --- a/rxjava-core/src/test/java/rx/operators/SynchronizedObserverTest.java +++ b/rxjava-core/src/test/java/rx/operators/SynchronizedObserverTest.java @@ -1,3 +1,18 @@ +/** + * Copyright 2013 Netflix, Inc. + * + * 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 rx.operators; import static org.junit.Assert.*; diff --git a/rxjava-core/src/test/java/rx/operators/TakeWhileTest.java b/rxjava-core/src/test/java/rx/operators/TakeWhileTest.java index c81169eac2..25e17ba13b 100644 --- a/rxjava-core/src/test/java/rx/operators/TakeWhileTest.java +++ b/rxjava-core/src/test/java/rx/operators/TakeWhileTest.java @@ -1,3 +1,18 @@ +/** + * Copyright 2013 Netflix, Inc. + * + * 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 rx.operators; import org.junit.Ignore; diff --git a/rxjava-core/src/test/java/rx/operators/TimeIntervalObserverTest.java b/rxjava-core/src/test/java/rx/operators/TimeIntervalObserverTest.java index 6f073696f0..29337619ff 100644 --- a/rxjava-core/src/test/java/rx/operators/TimeIntervalObserverTest.java +++ b/rxjava-core/src/test/java/rx/operators/TimeIntervalObserverTest.java @@ -1,3 +1,18 @@ +/** + * Copyright 2013 Netflix, Inc. + * + * 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 rx.operators; import org.junit.Ignore; diff --git a/rxjava-core/src/test/java/rx/plugins/RxJavaPluginsTest.java b/rxjava-core/src/test/java/rx/plugins/RxJavaPluginsTest.java index 94c4fdcc0d..ce96b43edc 100644 --- a/rxjava-core/src/test/java/rx/plugins/RxJavaPluginsTest.java +++ b/rxjava-core/src/test/java/rx/plugins/RxJavaPluginsTest.java @@ -1,3 +1,18 @@ +/** + * Copyright 2013 Netflix, Inc. + * + * 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 rx.plugins; import static org.junit.Assert.*; diff --git a/rxjava-core/src/test/java/rx/subjects/AsyncSubjectTest.java b/rxjava-core/src/test/java/rx/subjects/AsyncSubjectTest.java index 243dda02bf..a0b82c7167 100644 --- a/rxjava-core/src/test/java/rx/subjects/AsyncSubjectTest.java +++ b/rxjava-core/src/test/java/rx/subjects/AsyncSubjectTest.java @@ -1,3 +1,18 @@ +/** + * Copyright 2013 Netflix, Inc. + * + * 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 rx.subjects; import static org.mockito.Matchers.*; diff --git a/rxjava-core/src/test/java/rx/subjects/BehaviorSubjectTest.java b/rxjava-core/src/test/java/rx/subjects/BehaviorSubjectTest.java index 8c7a52f61d..ac543b7a18 100644 --- a/rxjava-core/src/test/java/rx/subjects/BehaviorSubjectTest.java +++ b/rxjava-core/src/test/java/rx/subjects/BehaviorSubjectTest.java @@ -1,3 +1,18 @@ +/** + * Copyright 2013 Netflix, Inc. + * + * 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 rx.subjects; import static org.mockito.Matchers.*; diff --git a/rxjava-core/src/test/java/rx/subjects/PublishSubjectTest.java b/rxjava-core/src/test/java/rx/subjects/PublishSubjectTest.java index 9c2ca321ee..9e93c89e01 100644 --- a/rxjava-core/src/test/java/rx/subjects/PublishSubjectTest.java +++ b/rxjava-core/src/test/java/rx/subjects/PublishSubjectTest.java @@ -1,3 +1,18 @@ +/** + * Copyright 2013 Netflix, Inc. + * + * 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 rx.subjects; import static org.junit.Assert.*; diff --git a/rxjava-core/src/test/java/rx/subjects/ReplaySubjectTest.java b/rxjava-core/src/test/java/rx/subjects/ReplaySubjectTest.java index 728f9e53f1..fef45ca63d 100644 --- a/rxjava-core/src/test/java/rx/subjects/ReplaySubjectTest.java +++ b/rxjava-core/src/test/java/rx/subjects/ReplaySubjectTest.java @@ -1,3 +1,18 @@ +/** + * Copyright 2013 Netflix, Inc. + * + * 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 rx.subjects; import static org.mockito.Matchers.*; diff --git a/rxjava-core/src/test/java/rx/subscriptions/CompositeSubscriptionTest.java b/rxjava-core/src/test/java/rx/subscriptions/CompositeSubscriptionTest.java index e7257d9f1a..ce23bf1d68 100644 --- a/rxjava-core/src/test/java/rx/subscriptions/CompositeSubscriptionTest.java +++ b/rxjava-core/src/test/java/rx/subscriptions/CompositeSubscriptionTest.java @@ -1,3 +1,18 @@ +/** + * Copyright 2013 Netflix, Inc. + * + * 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 rx.subscriptions; import static org.junit.Assert.*; diff --git a/rxjava-core/src/test/java/rx/subscriptions/SubscriptionsTest.java b/rxjava-core/src/test/java/rx/subscriptions/SubscriptionsTest.java index 806a5e52e9..abeab16833 100644 --- a/rxjava-core/src/test/java/rx/subscriptions/SubscriptionsTest.java +++ b/rxjava-core/src/test/java/rx/subscriptions/SubscriptionsTest.java @@ -1,3 +1,18 @@ +/** + * Copyright 2013 Netflix, Inc. + * + * 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 rx.subscriptions; import static org.mockito.Mockito.*; diff --git a/rxjava-core/src/test/java/rx/util/RangeTest.java b/rxjava-core/src/test/java/rx/util/RangeTest.java index c788b32e82..297e7a769a 100644 --- a/rxjava-core/src/test/java/rx/util/RangeTest.java +++ b/rxjava-core/src/test/java/rx/util/RangeTest.java @@ -1,3 +1,18 @@ +/** + * Copyright 2013 Netflix, Inc. + * + * 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 rx.util; import static org.junit.Assert.*;