From 2f561af95da1ae800cb1df3b32a59035f21ebdeb Mon Sep 17 00:00:00 2001 From: nikitin-da Date: Wed, 21 Nov 2018 23:15:41 +0300 Subject: [PATCH 1/2] #855 Add asRxCompletable to PreparedExecuteSQL --- .../execute/PreparedExecuteSQL.java | 19 +++- .../execute/PreparedExecuteSQLTest.java | 89 +++++++++++++++++++ 2 files changed, 107 insertions(+), 1 deletion(-) diff --git a/storio-sqlite/src/main/java/com/pushtorefresh/storio3/sqlite/operations/execute/PreparedExecuteSQL.java b/storio-sqlite/src/main/java/com/pushtorefresh/storio3/sqlite/operations/execute/PreparedExecuteSQL.java index 4dc6fcdc0..dc619cce8 100644 --- a/storio-sqlite/src/main/java/com/pushtorefresh/storio3/sqlite/operations/execute/PreparedExecuteSQL.java +++ b/storio-sqlite/src/main/java/com/pushtorefresh/storio3/sqlite/operations/execute/PreparedExecuteSQL.java @@ -5,6 +5,7 @@ import android.support.annotation.WorkerThread; import com.pushtorefresh.storio3.StorIOException; +import com.pushtorefresh.storio3.operations.PreparedCompletableOperation; import com.pushtorefresh.storio3.operations.PreparedOperation; import com.pushtorefresh.storio3.sqlite.Changes; import com.pushtorefresh.storio3.Interceptor; @@ -15,6 +16,7 @@ import java.util.Set; import io.reactivex.BackpressureStrategy; +import io.reactivex.Completable; import io.reactivex.Flowable; import io.reactivex.Single; @@ -24,7 +26,7 @@ /** * Prepared Execute SQL Operation for {@link StorIOSQLite}. */ -public class PreparedExecuteSQL implements PreparedOperation { +public class PreparedExecuteSQL implements PreparedCompletableOperation { @NonNull private final StorIOSQLite storIOSQLite; @@ -98,6 +100,21 @@ public Single asRxSingle() { return RxJavaUtils.createSingle(storIOSQLite, this); } + /** + * Creates {@link Completable} which will perform Execute SQL Operation lazily when somebody subscribes to it. + *
+ *
Scheduler:
+ *
Operates on {@link StorIOSQLite#defaultRxScheduler()} if not {@code null}.
+ *
+ * + * @return non-null {@link Completable} which will perform Execute SQL Operation. + */ + @NonNull + @Override + public Completable asRxCompletable() { + return RxJavaUtils.createCompletable(storIOSQLite, this); + } + private class RealCallInterceptor implements Interceptor { @NonNull @Override diff --git a/storio-sqlite/src/test/java/com/pushtorefresh/storio3/sqlite/operations/execute/PreparedExecuteSQLTest.java b/storio-sqlite/src/test/java/com/pushtorefresh/storio3/sqlite/operations/execute/PreparedExecuteSQLTest.java index 0d701173b..1b452031f 100644 --- a/storio-sqlite/src/test/java/com/pushtorefresh/storio3/sqlite/operations/execute/PreparedExecuteSQLTest.java +++ b/storio-sqlite/src/test/java/com/pushtorefresh/storio3/sqlite/operations/execute/PreparedExecuteSQLTest.java @@ -17,6 +17,7 @@ import java.util.HashSet; import java.util.List; +import io.reactivex.Completable; import io.reactivex.Flowable; import io.reactivex.Single; import io.reactivex.functions.Consumer; @@ -136,6 +137,34 @@ public void executeSQLSingleWithoutNotifications() { stub.verifyBehavior(single); } + @Test + public void executeSQLCompletableWithNotification() { + final Stub stub = Stub.newInstanceApplyNotEmptyAffectedTablesAndTags(); + + final Completable completable = stub.storIOSQLite + .executeSQL() + .withQuery(stub.rawQuery) + .prepare() + .asRxCompletable(); + + verify(stub.storIOSQLite).defaultRxScheduler(); + stub.verifyBehavior(completable); + } + + @Test + public void executeSQLCompletableWithoutNotifications() { + final Stub stub = Stub.newInstanceDoNotApplyAffectedTablesAndTags(); + + final Completable completable = stub.storIOSQLite + .executeSQL() + .withQuery(stub.rawQuery) + .prepare() + .asRxCompletable(); + + verify(stub.storIOSQLite).defaultRxScheduler(); + stub.verifyBehavior(completable); + } + @Test public void executeSQLFlowableWithNotification() { final Stub stub = Stub.newInstanceApplyNotEmptyAffectedTablesAndTags(); @@ -176,6 +205,19 @@ public void executeSQLSingleExecutesOnSpecifiedScheduler() { schedulerChecker.checkAsSingle(operation); } + @Test + public void executeSQLCompletableExecutesOnSpecifiedScheduler() { + final Stub stub = Stub.newInstanceApplyNotEmptyAffectedTablesAndTags(); + final SchedulerChecker schedulerChecker = SchedulerChecker.create(stub.storIOSQLite); + + final PreparedExecuteSQL operation = stub.storIOSQLite + .executeSQL() + .withQuery(stub.rawQuery) + .prepare(); + + schedulerChecker.checkAsCompletable(operation); + } + @Test public void shouldWrapExceptionIntoStorIOExceptionBlocking() { final Stub stub = Stub.newInstanceApplyNotEmptyAffectedTablesAndTags(); @@ -264,6 +306,40 @@ public void shouldWrapExceptionIntoStorIOExceptionSingle() { verifyNoMoreInteractions(stub.storIOSQLite, stub.lowLevel); } + @Test + public void shouldWrapExceptionIntoStorIOExceptionCompletable() { + final Stub stub = Stub.newInstanceApplyNotEmptyAffectedTablesAndTags(); + + IllegalStateException testException = new IllegalStateException("test exception"); + doThrow(testException).when(stub.lowLevel).executeSQL(stub.rawQuery); + + final TestObserver testObserver = new TestObserver(); + + stub.storIOSQLite + .executeSQL() + .withQuery(stub.rawQuery) + .prepare() + .asRxCompletable() + .subscribe(testObserver); + + testObserver.awaitTerminalEvent(); + testObserver.assertNoValues(); + testObserver.assertError(StorIOException.class); + + //noinspection ThrowableResultOfMethodCallIgnored + StorIOException expected = (StorIOException) testObserver.errors().get(0); + + IllegalStateException cause = (IllegalStateException) expected.getCause(); + assertThat(cause).hasMessage("test exception"); + + verify(stub.storIOSQLite).executeSQL(); + verify(stub.storIOSQLite).defaultRxScheduler(); + verify(stub.storIOSQLite).lowLevel(); + verify(stub.lowLevel).executeSQL(stub.rawQuery); + verify(stub.storIOSQLite).interceptors(); + verifyNoMoreInteractions(stub.storIOSQLite, stub.lowLevel); + } + static class Stub { private final StorIOSQLite storIOSQLite; @@ -375,5 +451,18 @@ public void accept(Object anObject) { }) .checkBehaviorOfFlowable(); } + + void verifyBehavior(@NonNull Completable completable) { + new FlowableBehaviorChecker() + .flowable(completable.toFlowable()) + .expectedNumberOfEmissions(1) + .testAction(new Consumer() { + @Override + public void accept(Object anObject) { + verifyBehavior(); + } + }) + .checkBehaviorOfFlowable(); + } } } From 6517a88c17d19b6cb879864ebdc6cb8fb69736af Mon Sep 17 00:00:00 2001 From: nikitin-da Date: Wed, 21 Nov 2018 23:38:40 +0300 Subject: [PATCH 2/2] Update changelog --- CHANGELOG.md | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 43dd3bddd..45cb3f0bf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,9 +19,15 @@ _2018_05_09_ * AutoValue 1.0-rc4 and AutoParcel 0.3.1. * Private constructor checker 1.2.0. * EqualsVerifier 1.7.8. - +* Gradle Nexus plugin 0.12.0. +* Nexus publish plugin. +* `executeSQL()` now for sure can be executed via `asRxCompletable()`. + **Changes:** +* [PR 905](https://github.com/pushtorefresh/storio/pull/905): executeSQL() can be executed via asRxCompletable(). +* [PR 903](https://github.com/pushtorefresh/storio/pull/903): Nexus publish plugin. +* [PR 901](https://github.com/pushtorefresh/storio/pull/901): Gradle Nexus plugin 0.12.0. * [PR 899](https://github.com/pushtorefresh/storio/pull/899): AndroidX support. * [PR 898](https://github.com/pushtorefresh/storio/pull/898): Dagger 2.18 and temporary disable SQLDelight. * [PR 897](https://github.com/pushtorefresh/storio/pull/897): Compile sdk 28 and support library 28.0.0.