From f5594597755e4bda85ecc096106331a1c9f05c1e Mon Sep 17 00:00:00 2001 From: Christian Melchior Date: Wed, 11 Oct 2023 15:29:40 +0200 Subject: [PATCH] Fix network requests sometimes returning `null` instead of either returning success or failure --- CHANGELOG.md | 1 + .../internal/network/NetworkRequestTests.kt | 41 +++++++++++++++++++ .../internal/network/NetworkRequest.java | 16 +++----- .../internal/network/VoidNetworkRequest.java | 2 +- 4 files changed, 48 insertions(+), 12 deletions(-) create mode 100644 realm/realm-library/src/androidTestObjectServer/kotlin/io/realm/internal/network/NetworkRequestTests.kt diff --git a/CHANGELOG.md b/CHANGELOG.md index 451a0ae2ec..e6b0bc0202 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ ### Fixed * Realm objects accessors behave as an unmanaged object after an incremental build. (Issue [#7844](https://github.com/realm/realm-java/pull/7844)) * [RealmApp] Crash when opening a Realm with a proxy enabled. (Issue [#7828](https://github.com/realm/realm-java/issues/7828)) +* [RealmApp] It was possible to create a `User` object with invalid state that would throw a `NullPointerException` when accessed. (Issue [#7847](https://github.com/realm/realm-java/issues/7847)) ### Compatibility * File format: Generates Realms with format v23. Unsynced Realms will be upgraded from Realm Java 2.0 and later. Synced Realms can only be read and upgraded if created with Realm Java v10.0.0-BETA.1. diff --git a/realm/realm-library/src/androidTestObjectServer/kotlin/io/realm/internal/network/NetworkRequestTests.kt b/realm/realm-library/src/androidTestObjectServer/kotlin/io/realm/internal/network/NetworkRequestTests.kt new file mode 100644 index 0000000000..422eb9a6ad --- /dev/null +++ b/realm/realm-library/src/androidTestObjectServer/kotlin/io/realm/internal/network/NetworkRequestTests.kt @@ -0,0 +1,41 @@ +package io.realm.internal.network + +import androidx.test.platform.app.InstrumentationRegistry +import io.realm.Realm +import io.realm.mongodb.App +import io.realm.mongodb.AppException +import io.realm.mongodb.ErrorCode +import junit.framework.TestCase.assertEquals +import org.junit.Before +import org.junit.Test +import kotlin.test.assertFailsWith + +class NetworkRequestTests { + + private lateinit var app: App + + @Before + fun setUp() { + Realm.init(InstrumentationRegistry.getInstrumentation().targetContext) + } + + // Test for https://github.com/realm/realm-java/issues/7847 + @Test + fun interruptedRequestReturnsError() { + val request = object: NetworkRequest() { + override fun mapSuccess(result: Any?): Unit { + Unit + } + + override fun execute(callback: NetworkRequest) { + Thread.currentThread().interrupt() + } + } + assertFailsWith { + request.resultOrThrow() + }.also { + assertEquals(it.errorCode, ErrorCode.NETWORK_INTERRUPTED) + assertEquals(it.errorMessage, "Network request interrupted.") + } + } +} \ No newline at end of file diff --git a/realm/realm-library/src/objectServer/java/io/realm/internal/network/NetworkRequest.java b/realm/realm-library/src/objectServer/java/io/realm/internal/network/NetworkRequest.java index f877a004d9..88ec0876ab 100644 --- a/realm/realm-library/src/objectServer/java/io/realm/internal/network/NetworkRequest.java +++ b/realm/realm-library/src/objectServer/java/io/realm/internal/network/NetworkRequest.java @@ -48,9 +48,7 @@ public abstract class NetworkRequest extends OsJavaNetworkTransport.NetworkTr @Override public void onSuccess(Object result) { T mappedResult = mapSuccess(result); - if (success != null) { - success.set(mappedResult); - } + success.set(mappedResult); latch.countDown(); } @@ -87,11 +85,11 @@ public T resultOrThrow() { execute(this); try { - // Wait indefinitely. Timeouts should be handled by the Network layer, - // so will eventually bubble up as an exception. + // Wait indefinitely. Timeouts should be handled by the Network layer, otherwise + // it can be interrupted manually by calling `RealmAsyncTask.cancel()` latch.await(); } catch (InterruptedException e) { - RealmLog.debug("Network request interrupted."); + error.set(new AppException(ErrorCode.NETWORK_INTERRUPTED, "Network request interrupted.")); } // Result of request should be available. Throw if an error happened, otherwise return @@ -99,11 +97,7 @@ public T resultOrThrow() { if (error.get() != null) { throw error.get(); } else { - if (success != null) { - return success.get(); - } else { - return null; - } + return success.get(); } } } diff --git a/realm/realm-library/src/objectServer/java/io/realm/internal/network/VoidNetworkRequest.java b/realm/realm-library/src/objectServer/java/io/realm/internal/network/VoidNetworkRequest.java index fb4bd9b5df..e86618f679 100644 --- a/realm/realm-library/src/objectServer/java/io/realm/internal/network/VoidNetworkRequest.java +++ b/realm/realm-library/src/objectServer/java/io/realm/internal/network/VoidNetworkRequest.java @@ -11,7 +11,7 @@ /** * Specialized case of {@link NetworkRequest} where we are not interested in the response value, - * just wether or not the request succeeded. + * just whether or not the request succeeded. */ public abstract class VoidNetworkRequest extends NetworkRequest {