From 5dd0b28b0c7ed59f6a9f4279e54005f91a8d49e0 Mon Sep 17 00:00:00 2001 From: Niklas Baudy Date: Mon, 24 Oct 2016 15:22:51 +0200 Subject: [PATCH 1/2] 2.x: Add Single.fromObservable(ObservableSource) --- src/main/java/io/reactivex/Single.java | 23 +++++++++++++- .../observable/ObservableSingleSingle.java | 4 +-- .../java/io/reactivex/single/SingleTest.java | 31 +++++++++++++++++++ 3 files changed, 55 insertions(+), 3 deletions(-) diff --git a/src/main/java/io/reactivex/Single.java b/src/main/java/io/reactivex/Single.java index 204b197523..85797f9c88 100644 --- a/src/main/java/io/reactivex/Single.java +++ b/src/main/java/io/reactivex/Single.java @@ -27,7 +27,7 @@ import io.reactivex.internal.operators.completable.*; import io.reactivex.internal.operators.flowable.*; import io.reactivex.internal.operators.maybe.*; -import io.reactivex.internal.operators.observable.ObservableConcatMap; +import io.reactivex.internal.operators.observable.*; import io.reactivex.internal.operators.single.*; import io.reactivex.internal.util.*; import io.reactivex.observers.TestObserver; @@ -573,6 +573,27 @@ public static Single fromPublisher(final Publisher publisher return RxJavaPlugins.onAssembly(new SingleFromPublisher(publisher)); } + /** + * Wraps a specific ObservableSource into a Single and signals its single element or error. + *

If the ObservableSource is empty, a NoSuchElementException is signalled. + * If the source has more than one element, an IndexOutOfBoundsException is signalled. + *

+ *

+ *
Scheduler:
+ *
{@code fromObservable} does not operate by default on a particular {@link Scheduler}.
+ *
+ * + * @param observableSource the source Observable, not null + * @param + * the type of the item emitted by the {@link Single}. + * @return the new Single instance + */ + @SchedulerSupport(SchedulerSupport.NONE) + public static Single fromObservable(ObservableSource observableSource) { + ObjectHelper.requireNonNull(observableSource, "observableSource is null"); + return RxJavaPlugins.onAssembly(new ObservableSingleSingle(observableSource, null)); + } + /** * Returns a {@code Single} that emits a specified item. *

diff --git a/src/main/java/io/reactivex/internal/operators/observable/ObservableSingleSingle.java b/src/main/java/io/reactivex/internal/operators/observable/ObservableSingleSingle.java index e4704d333a..fb33a11eac 100644 --- a/src/main/java/io/reactivex/internal/operators/observable/ObservableSingleSingle.java +++ b/src/main/java/io/reactivex/internal/operators/observable/ObservableSingleSingle.java @@ -21,11 +21,11 @@ public final class ObservableSingleSingle extends Single { - final ObservableSource source; + final ObservableSource source; final T defaultValue; - public ObservableSingleSingle(ObservableSource source, T defaultValue) { + public ObservableSingleSingle(ObservableSource source, T defaultValue) { this.source = source; this.defaultValue = defaultValue; } diff --git a/src/test/java/io/reactivex/single/SingleTest.java b/src/test/java/io/reactivex/single/SingleTest.java index cafd53e205..986b526df0 100644 --- a/src/test/java/io/reactivex/single/SingleTest.java +++ b/src/test/java/io/reactivex/single/SingleTest.java @@ -22,6 +22,7 @@ import org.junit.*; import io.reactivex.*; +import io.reactivex.Observable; import io.reactivex.disposables.*; import io.reactivex.exceptions.TestException; import io.reactivex.functions.*; @@ -541,5 +542,35 @@ public Integer apply(Single v) throws Exception { } }).intValue()); } + + @Test + public void fromObservableEmpty() { + Single.fromObservable(Observable.empty()) + .test() + .assertFailure(NoSuchElementException.class); + } + + @Test + public void fromObservableMoreThan1Elements() { + Single.fromObservable(Observable.just(1, 2)) + .test() + .assertFailure(IllegalArgumentException.class) + .assertErrorMessage("Sequence contains more than one element!"); + } + + @Test + public void fromObservableOneElement() { + Single.fromObservable(Observable.just(1)) + .test() + .assertResult(1); + } + + @Test + public void fromObservableError() { + Single.fromObservable(Observable.error(new RuntimeException("some error"))) + .test() + .assertFailure(RuntimeException.class) + .assertErrorMessage("some error"); + } } From b0978544f4aafca07710f9d33560908faa813de3 Mon Sep 17 00:00:00 2001 From: Niklas Baudy Date: Mon, 24 Oct 2016 15:28:25 +0200 Subject: [PATCH 2/2] Add Null test --- src/test/java/io/reactivex/single/SingleTest.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/test/java/io/reactivex/single/SingleTest.java b/src/test/java/io/reactivex/single/SingleTest.java index 986b526df0..280b1da007 100644 --- a/src/test/java/io/reactivex/single/SingleTest.java +++ b/src/test/java/io/reactivex/single/SingleTest.java @@ -543,6 +543,11 @@ public Integer apply(Single v) throws Exception { }).intValue()); } + @Test(expected = NullPointerException.class) + public void fromObservableNull() { + Single.fromObservable(null); + } + @Test public void fromObservableEmpty() { Single.fromObservable(Observable.empty())