diff --git a/CHANGELOG.md b/CHANGELOG.md index e0380bda7c..a659cc213e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -22,6 +22,7 @@ childA == childC ``` ### Enhancements +* Fulltext queries now support prefix search by using the * operator, like `description TEXT 'alex*'`. (Core issue [#6860](https://github.com/realm/realm-core/issues/6860)) * Realm model classes now generate custom `toString`, `equals` and `hashCode` implementations. This makes it possible to compare by object reference across multiple collections. Note that two objects at different versions will not be considered equal, even if the content is the same. Custom implementations of these methods will be respected if they are present. (Issue [#1097](https://github.com/realm/realm-kotlin/issues/1097)) * Support for performing geospatial queries using the new classes: `GeoPoint`, `GeoCircle`, `GeoBox`, and `GeoPolygon`. See `GeoPoint` documentation on how to persist locations. (Issue [#1403](https://github.com/realm/realm-kotlin/pull/1403)) @@ -46,7 +47,7 @@ if the content is the same. Custom implementations of these methods will be resp * Minimum Android SDK: 16. ### Internal -* None. +* Updated to Realm Core 13.19.0, commit ea7c5d5e2900b8411a295aea3d1aa56aa55fff1d. ## 1.10.2 (2023-07-21) diff --git a/packages/cinterop/src/androidInstrumentedTest/kotlin/io/realm/kotlin/test/sync/SyncEnumTests.kt b/packages/cinterop/src/androidInstrumentedTest/kotlin/io/realm/kotlin/test/sync/SyncEnumTests.kt index 4f9490dbe9..1effc3cd32 100644 --- a/packages/cinterop/src/androidInstrumentedTest/kotlin/io/realm/kotlin/test/sync/SyncEnumTests.kt +++ b/packages/cinterop/src/androidInstrumentedTest/kotlin/io/realm/kotlin/test/sync/SyncEnumTests.kt @@ -16,6 +16,7 @@ package io.realm.kotlin.test.sync +import io.realm.kotlin.internal.interop.CategoryFlags import io.realm.kotlin.internal.interop.ErrorCategory import io.realm.kotlin.internal.interop.ErrorCode import io.realm.kotlin.internal.interop.realm_auth_provider_e @@ -23,23 +24,21 @@ import io.realm.kotlin.internal.interop.realm_errno_e import io.realm.kotlin.internal.interop.realm_error_category_e import io.realm.kotlin.internal.interop.realm_sync_client_metadata_mode_e import io.realm.kotlin.internal.interop.realm_sync_connection_state_e -import io.realm.kotlin.internal.interop.realm_sync_errno_client_e import io.realm.kotlin.internal.interop.realm_sync_errno_connection_e import io.realm.kotlin.internal.interop.realm_sync_errno_session_e -import io.realm.kotlin.internal.interop.realm_sync_error_category_e import io.realm.kotlin.internal.interop.realm_sync_session_resync_mode_e import io.realm.kotlin.internal.interop.realm_sync_session_state_e import io.realm.kotlin.internal.interop.realm_user_state_e +import io.realm.kotlin.internal.interop.realm_web_socket_errno_e import io.realm.kotlin.internal.interop.sync.AuthProvider import io.realm.kotlin.internal.interop.sync.CoreConnectionState import io.realm.kotlin.internal.interop.sync.CoreSyncSessionState import io.realm.kotlin.internal.interop.sync.CoreUserState import io.realm.kotlin.internal.interop.sync.MetadataMode -import io.realm.kotlin.internal.interop.sync.ProtocolClientErrorCode -import io.realm.kotlin.internal.interop.sync.ProtocolConnectionErrorCode -import io.realm.kotlin.internal.interop.sync.ProtocolSessionErrorCode -import io.realm.kotlin.internal.interop.sync.SyncErrorCodeCategory +import io.realm.kotlin.internal.interop.sync.SyncConnectionErrorCode +import io.realm.kotlin.internal.interop.sync.SyncSessionErrorCode import io.realm.kotlin.internal.interop.sync.SyncSessionResyncMode +import io.realm.kotlin.internal.interop.sync.WebsocketErrorCode import org.junit.Test import kotlin.reflect.KClass import kotlin.test.BeforeTest @@ -59,10 +58,11 @@ class SyncEnumTests { } @Test - fun appErrorCategory() { + fun errorCategory() { checkEnum(realm_error_category_e::class) { nativeValue -> ErrorCategory.of(nativeValue) } + assertEquals(ErrorCategory.values().size, CategoryFlags.CATEGORY_ORDER.size) } @Test @@ -94,30 +94,23 @@ class SyncEnumTests { } @Test - fun protocolClientErrorCode() { - checkEnum(realm_sync_errno_client_e::class) { nativeValue -> - ProtocolClientErrorCode.of(nativeValue) - } - } - - @Test - fun protocolConnectionErrorCode() { + fun syncConnectionErrorCode() { checkEnum(realm_sync_errno_connection_e::class) { nativeValue -> - ProtocolConnectionErrorCode.of(nativeValue) + SyncConnectionErrorCode.of(nativeValue) } } @Test - fun protocolSessionErrorCode() { + fun syncSessionErrorCode() { checkEnum(realm_sync_errno_session_e::class) { nativeValue -> - ProtocolSessionErrorCode.of(nativeValue) + SyncSessionErrorCode.of(nativeValue) } } @Test - fun syncErrorCodeCategory() { - checkEnum(realm_sync_error_category_e::class) { nativeValue -> - SyncErrorCodeCategory.of(nativeValue) + fun websocketErrorCode() { + checkEnum(realm_web_socket_errno_e::class) { nativeValue -> + WebsocketErrorCode.of(nativeValue) } } diff --git a/packages/cinterop/src/commonMain/kotlin/io/realm/kotlin/internal/interop/Callback.kt b/packages/cinterop/src/commonMain/kotlin/io/realm/kotlin/internal/interop/Callback.kt index b8534d0b67..4d262f206d 100644 --- a/packages/cinterop/src/commonMain/kotlin/io/realm/kotlin/internal/interop/Callback.kt +++ b/packages/cinterop/src/commonMain/kotlin/io/realm/kotlin/internal/interop/Callback.kt @@ -19,7 +19,6 @@ package io.realm.kotlin.internal.interop import io.realm.kotlin.internal.interop.sync.AppError import io.realm.kotlin.internal.interop.sync.CoreSubscriptionSetState import io.realm.kotlin.internal.interop.sync.SyncError -import io.realm.kotlin.internal.interop.sync.SyncErrorCode // TODO Could be replace by lambda. See realm_app_config_new networkTransportFactory for example. interface Callback { @@ -39,7 +38,7 @@ fun interface SyncErrorCallback { // Interface exposed towards `library-sync` interface SyncSessionTransferCompletionCallback { - fun invoke(error: SyncErrorCode?) + fun invoke(error: CoreError?) } interface LogCallback { diff --git a/packages/cinterop/src/commonMain/kotlin/io/realm/kotlin/internal/interop/CoreError.kt b/packages/cinterop/src/commonMain/kotlin/io/realm/kotlin/internal/interop/CoreError.kt new file mode 100644 index 0000000000..3d7334fcd7 --- /dev/null +++ b/packages/cinterop/src/commonMain/kotlin/io/realm/kotlin/internal/interop/CoreError.kt @@ -0,0 +1,66 @@ +package io.realm.kotlin.internal.interop + +/** + * Wrapper for C-API `realm_error_t`. + * See https://github.com/realm/realm-core/blob/master/src/realm.h#L231 + */ +class CoreError( + categoriesNativeValue: Int, + val errorCodeNativeValue: Int, + messageNativeValue: String?, +) { + val categories: CategoryFlags = CategoryFlags((categoriesNativeValue)) + val errorCode: ErrorCode? = ErrorCode.of(errorCodeNativeValue) + val message = messageNativeValue + + operator fun contains(category: ErrorCategory): Boolean = category in categories +} + +data class CategoryFlags(val categoryFlags: Int) { + + companion object { + /** + * See error code mapping to categories here: + * https://github.com/realm/realm-core/blob/master/src/realm/error_codes.cpp#L29 + * + * In most cases, only 1 category is assigned, but some errors have multiple. So instead of + * overwhelming the user with many categories, we only select the most important to show + * in the error message. "important" is of course tricky to define, but generally + * we consider vague categories like [ErrorCategory.RLM_ERR_CAT_RUNTIME] as less important + * than more specific ones like [ErrorCategory.RLM_ERR_CAT_JSON_ERROR]. + * + * In the current implementation, categories between index 0 and 7 are considered equal + * and the order is somewhat arbitrary. No error codes has multiple of these categories + * associated either. + */ + val CATEGORY_ORDER: List = listOf( + ErrorCategory.RLM_ERR_CAT_CUSTOM_ERROR, + ErrorCategory.RLM_ERR_CAT_WEBSOCKET_ERROR, + ErrorCategory.RLM_ERR_CAT_SYNC_ERROR, + ErrorCategory.RLM_ERR_CAT_SERVICE_ERROR, + ErrorCategory.RLM_ERR_CAT_JSON_ERROR, + ErrorCategory.RLM_ERR_CAT_CLIENT_ERROR, + ErrorCategory.RLM_ERR_CAT_SYSTEM_ERROR, + ErrorCategory.RLM_ERR_CAT_FILE_ACCESS, + ErrorCategory.RLM_ERR_CAT_HTTP_ERROR, + ErrorCategory.RLM_ERR_CAT_INVALID_ARG, + ErrorCategory.RLM_ERR_CAT_APP_ERROR, + ErrorCategory.RLM_ERR_CAT_LOGIC, + ErrorCategory.RLM_ERR_CAT_RUNTIME, + ) + } + + /** + * Returns a description of the most important category defined in [categoryFlags]. + * If no known categories are found, the integer values for all the categories is returned + * as debugging information. + */ + val description: String = CATEGORY_ORDER.firstOrNull { category -> + this.contains(category) + }?.description ?: "$categoryFlags" + + /** + * Check whether a given [ErrorCategory] is included in the [categoryFlags]. + */ + operator fun contains(category: ErrorCategory): Boolean = (categoryFlags and category.nativeValue) != 0 +} diff --git a/packages/cinterop/src/commonMain/kotlin/io/realm/kotlin/internal/interop/CoreErrorConverter.kt b/packages/cinterop/src/commonMain/kotlin/io/realm/kotlin/internal/interop/CoreErrorConverter.kt index fddf363cdf..0a60a8aa7b 100644 --- a/packages/cinterop/src/commonMain/kotlin/io/realm/kotlin/internal/interop/CoreErrorConverter.kt +++ b/packages/cinterop/src/commonMain/kotlin/io/realm/kotlin/internal/interop/CoreErrorConverter.kt @@ -31,22 +31,21 @@ object CoreErrorConverter { path: String?, userError: Throwable? ): Throwable { - val categories: CategoryFlag = CategoryFlag(categoriesNativeValue) + val categories: CategoryFlags = CategoryFlags(categoriesNativeValue) val errorCode: ErrorCode? = ErrorCode.of(errorCodeNativeValue) val message: String = "[$errorCode]: $messageNativeValue" return userError ?: when { ErrorCode.RLM_ERR_INDEX_OUT_OF_BOUNDS == errorCode -> IndexOutOfBoundsException(message) - ErrorCategory.RLM_ERR_CAT_INVALID_ARG in categories -> + ErrorCategory.RLM_ERR_CAT_INVALID_ARG in categories && ErrorCategory.RLM_ERR_CAT_SYNC_ERROR !in categories -> { + // Some sync errors flagged as both logical and illegal. In our case, we consider those + // IllegalState, so discard them them here and let them fall through to the bottom case IllegalArgumentException(message) + } ErrorCategory.RLM_ERR_CAT_LOGIC in categories || ErrorCategory.RLM_ERR_CAT_RUNTIME in categories -> IllegalStateException(message) else -> Error(message) // This can happen when propagating user level exceptions. } } - - data class CategoryFlag(val categoryCode: Int) { - operator fun contains(other: ErrorCategory): Boolean = categoryCode and other.nativeValue != 0 - } } diff --git a/packages/cinterop/src/commonMain/kotlin/io/realm/kotlin/internal/interop/ErrorCategory.kt b/packages/cinterop/src/commonMain/kotlin/io/realm/kotlin/internal/interop/ErrorCategory.kt index fb1716377d..53053fc1da 100644 --- a/packages/cinterop/src/commonMain/kotlin/io/realm/kotlin/internal/interop/ErrorCategory.kt +++ b/packages/cinterop/src/commonMain/kotlin/io/realm/kotlin/internal/interop/ErrorCategory.kt @@ -32,7 +32,8 @@ expect enum class ErrorCategory : CodeDescription { RLM_ERR_CAT_SERVICE_ERROR, RLM_ERR_CAT_HTTP_ERROR, RLM_ERR_CAT_CUSTOM_ERROR, - RLM_ERR_CAT_WEBSOCKET_ERROR; + RLM_ERR_CAT_WEBSOCKET_ERROR, + RLM_ERR_CAT_SYNC_ERROR; companion object { internal fun of(nativeValue: Int): ErrorCategory? diff --git a/packages/cinterop/src/commonMain/kotlin/io/realm/kotlin/internal/interop/ErrorCode.kt b/packages/cinterop/src/commonMain/kotlin/io/realm/kotlin/internal/interop/ErrorCode.kt index 13138a5605..b4d95acbf2 100644 --- a/packages/cinterop/src/commonMain/kotlin/io/realm/kotlin/internal/interop/ErrorCode.kt +++ b/packages/cinterop/src/commonMain/kotlin/io/realm/kotlin/internal/interop/ErrorCode.kt @@ -50,6 +50,22 @@ expect enum class ErrorCode : CodeDescription { RLM_ERR_SCHEMA_VERSION_MISMATCH, RLM_ERR_NO_SUBSCRIPTION_FOR_WRITE, RLM_ERR_OPERATION_ABORTED, + RLM_ERR_AUTO_CLIENT_RESET_FAILED, + RLM_ERR_BAD_SYNC_PARTITION_VALUE, + RLM_ERR_CONNECTION_CLOSED, + RLM_ERR_INVALID_SUBSCRIPTION_QUERY, + RLM_ERR_SYNC_CLIENT_RESET_REQUIRED, + RLM_ERR_SYNC_COMPENSATING_WRITE, + RLM_ERR_SYNC_CONNECT_FAILED, + RLM_ERR_SYNC_INVALID_SCHEMA_CHANGE, + RLM_ERR_SYNC_PERMISSION_DENIED, + RLM_ERR_SYNC_PROTOCOL_INVARIANT_FAILED, + RLM_ERR_SYNC_PROTOCOL_NEGOTIATION_FAILED, + RLM_ERR_SYNC_SERVER_PERMISSIONS_CHANGED, + RLM_ERR_SYNC_USER_MISMATCH, + RLM_ERR_TLS_HANDSHAKE_FAILED, + RLM_ERR_WRONG_SYNC_TYPE, + RLM_ERR_SYNC_WRITE_NOT_ALLOWED, RLM_ERR_SYSTEM_ERROR, RLM_ERR_LOGIC, RLM_ERR_NOT_SUPPORTED, @@ -162,9 +178,7 @@ expect enum class ErrorCode : CodeDescription { RLM_ERR_MAINTENANCE_IN_PROGRESS, RLM_ERR_USERPASS_TOKEN_INVALID, RLM_ERR_INVALID_SERVER_RESPONSE, - RLM_ERR_WEBSOCKET_RESOLVE_FAILED_ERROR, - RLM_ERR_WEBSOCKET_CONNECTION_CLOSED_CLIENT_ERROR, - RLM_ERR_WEBSOCKET_CONNECTION_CLOSED_SERVER_ERROR, + REALM_ERR_APP_SERVER_ERROR, RLM_ERR_CALLBACK, RLM_ERR_UNKNOWN; diff --git a/packages/cinterop/src/commonMain/kotlin/io/realm/kotlin/internal/interop/RealmInterop.kt b/packages/cinterop/src/commonMain/kotlin/io/realm/kotlin/internal/interop/RealmInterop.kt index 33332f2450..731a6a1e57 100644 --- a/packages/cinterop/src/commonMain/kotlin/io/realm/kotlin/internal/interop/RealmInterop.kt +++ b/packages/cinterop/src/commonMain/kotlin/io/realm/kotlin/internal/interop/RealmInterop.kt @@ -27,8 +27,6 @@ import io.realm.kotlin.internal.interop.sync.CoreUserState import io.realm.kotlin.internal.interop.sync.MetadataMode import io.realm.kotlin.internal.interop.sync.NetworkTransport import io.realm.kotlin.internal.interop.sync.ProgressDirection -import io.realm.kotlin.internal.interop.sync.ProtocolClientErrorCode -import io.realm.kotlin.internal.interop.sync.SyncErrorCodeCategory import io.realm.kotlin.internal.interop.sync.SyncSessionResyncMode import io.realm.kotlin.internal.interop.sync.SyncUserIdentity import kotlinx.coroutines.CoroutineDispatcher @@ -127,8 +125,6 @@ typealias RealmMutableSubscriptionSetPointer = NativePointer ) : this( - SyncErrorCode.newInstance(category, value, message), - detailedMessage, + CoreError(categoryFlags, value, message), originalFilePath, recoveryFilePath, isFatal, diff --git a/packages/cinterop/src/commonMain/kotlin/io/realm/kotlin/internal/interop/sync/SyncErrorCode.kt b/packages/cinterop/src/commonMain/kotlin/io/realm/kotlin/internal/interop/sync/SyncErrorCode.kt deleted file mode 100644 index 93a9b78052..0000000000 --- a/packages/cinterop/src/commonMain/kotlin/io/realm/kotlin/internal/interop/sync/SyncErrorCode.kt +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright 2022 Realm 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 io.realm.kotlin.internal.interop.sync - -import io.realm.kotlin.internal.interop.CodeDescription -import io.realm.kotlin.internal.interop.UnknownCodeDescription - -/** - * Wrapper for C-API `realm_sync_error_code`. - * See https://github.com/realm/realm-core/blob/master/src/realm.h#L3306 - */ -data class SyncErrorCode internal constructor( - val category: CodeDescription, - val code: CodeDescription, - val message: String -) { - companion object { - fun newInstance( - categoryCode: Int, - errorCode: Int, - message: String - ): SyncErrorCode { - val category = SyncErrorCodeCategory.of(categoryCode) ?: UnknownCodeDescription(categoryCode) - - val code: CodeDescription = when (category) { - SyncErrorCodeCategory.RLM_SYNC_ERROR_CATEGORY_CLIENT -> ProtocolClientErrorCode.of(errorCode) - SyncErrorCodeCategory.RLM_SYNC_ERROR_CATEGORY_CONNECTION -> ProtocolConnectionErrorCode.of(errorCode) - SyncErrorCodeCategory.RLM_SYNC_ERROR_CATEGORY_SESSION -> ProtocolSessionErrorCode.of(errorCode) - // SyncErrorCodeCategory.RLM_SYNC_ERROR_CATEGORY_SYSTEM -> // no mapping available - // SyncErrorCodeCategory.RLM_SYNC_ERROR_CATEGORY_UNKNOWN -> // no mapping available - else -> null - } ?: UnknownCodeDescription(errorCode) - - return SyncErrorCode( - category, - code, - message - ) - } - } -} diff --git a/packages/cinterop/src/commonMain/kotlin/io/realm/kotlin/internal/interop/sync/SyncErrorCodeCategory.kt b/packages/cinterop/src/commonMain/kotlin/io/realm/kotlin/internal/interop/sync/SyncErrorCodeCategory.kt deleted file mode 100644 index 049e3fbd1b..0000000000 --- a/packages/cinterop/src/commonMain/kotlin/io/realm/kotlin/internal/interop/sync/SyncErrorCodeCategory.kt +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright 2022 Realm 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 io.realm.kotlin.internal.interop.sync - -import io.realm.kotlin.internal.interop.CodeDescription - -/** - * Wrapper for C-API `realm_sync_error_category`. - * See https://github.com/realm/realm-core/blob/master/src/realm.h#L3198 - */ -expect enum class SyncErrorCodeCategory : CodeDescription { - RLM_SYNC_ERROR_CATEGORY_CLIENT, - RLM_SYNC_ERROR_CATEGORY_CONNECTION, - RLM_SYNC_ERROR_CATEGORY_SESSION, - RLM_SYNC_ERROR_CATEGORY_WEBSOCKET, - RLM_SYNC_ERROR_CATEGORY_SYSTEM, - RLM_SYNC_ERROR_CATEGORY_UNKNOWN; - - companion object { - internal fun of(nativeValue: Int): SyncErrorCodeCategory? - } -} diff --git a/packages/cinterop/src/jvm/kotlin/io/realm/kotlin/internal/interop/ErrorCategory.kt b/packages/cinterop/src/jvm/kotlin/io/realm/kotlin/internal/interop/ErrorCategory.kt index 423f657111..5319d0bc90 100644 --- a/packages/cinterop/src/jvm/kotlin/io/realm/kotlin/internal/interop/ErrorCategory.kt +++ b/packages/cinterop/src/jvm/kotlin/io/realm/kotlin/internal/interop/ErrorCategory.kt @@ -31,7 +31,8 @@ actual enum class ErrorCategory( RLM_ERR_CAT_SERVICE_ERROR("Service", realm_error_category_e.RLM_ERR_CAT_SERVICE_ERROR), RLM_ERR_CAT_HTTP_ERROR("Http", realm_error_category_e.RLM_ERR_CAT_HTTP_ERROR), RLM_ERR_CAT_CUSTOM_ERROR("Custom", realm_error_category_e.RLM_ERR_CAT_CUSTOM_ERROR), - RLM_ERR_CAT_WEBSOCKET_ERROR("Websocket", realm_error_category_e.RLM_ERR_CAT_WEBSOCKET_ERROR); + RLM_ERR_CAT_WEBSOCKET_ERROR("Websocket", realm_error_category_e.RLM_ERR_CAT_WEBSOCKET_ERROR), + RLM_ERR_CAT_SYNC_ERROR("Sync", realm_error_category_e.RLM_ERR_CAT_SYNC_ERROR); actual companion object { internal actual fun of(nativeValue: Int): ErrorCategory? = diff --git a/packages/cinterop/src/jvm/kotlin/io/realm/kotlin/internal/interop/ErrorCode.kt b/packages/cinterop/src/jvm/kotlin/io/realm/kotlin/internal/interop/ErrorCode.kt index 935354e9cb..36bcd30327 100644 --- a/packages/cinterop/src/jvm/kotlin/io/realm/kotlin/internal/interop/ErrorCode.kt +++ b/packages/cinterop/src/jvm/kotlin/io/realm/kotlin/internal/interop/ErrorCode.kt @@ -47,6 +47,22 @@ actual enum class ErrorCode(override val description: String, override val nativ RLM_ERR_SCHEMA_VERSION_MISMATCH("SchemaVersionMismatch", realm_errno_e.RLM_ERR_SCHEMA_VERSION_MISMATCH), RLM_ERR_NO_SUBSCRIPTION_FOR_WRITE("NoSubscriptionForWrite", realm_errno_e.RLM_ERR_NO_SUBSCRIPTION_FOR_WRITE), RLM_ERR_OPERATION_ABORTED("OperationAborted", realm_errno_e.RLM_ERR_OPERATION_ABORTED), + RLM_ERR_AUTO_CLIENT_RESET_FAILED("AutoClientResetFailed", realm_errno_e.RLM_ERR_AUTO_CLIENT_RESET_FAILED), + RLM_ERR_BAD_SYNC_PARTITION_VALUE("BadSyncPartitionValue", realm_errno_e.RLM_ERR_BAD_SYNC_PARTITION_VALUE), + RLM_ERR_CONNECTION_CLOSED("ConnectionClosed", realm_errno_e.RLM_ERR_CONNECTION_CLOSED), + RLM_ERR_INVALID_SUBSCRIPTION_QUERY("InvalidSubscriptionQuery", realm_errno_e.RLM_ERR_INVALID_SUBSCRIPTION_QUERY), + RLM_ERR_SYNC_CLIENT_RESET_REQUIRED("SyncClientResetRequired", realm_errno_e.RLM_ERR_SYNC_CLIENT_RESET_REQUIRED), + RLM_ERR_SYNC_COMPENSATING_WRITE("CompensatingWrite", realm_errno_e.RLM_ERR_SYNC_COMPENSATING_WRITE), + RLM_ERR_SYNC_CONNECT_FAILED("SyncConnectFailed", realm_errno_e.RLM_ERR_SYNC_CONNECT_FAILED), + RLM_ERR_SYNC_INVALID_SCHEMA_CHANGE("SyncInvalidSchemaChange", realm_errno_e.RLM_ERR_SYNC_INVALID_SCHEMA_CHANGE), + RLM_ERR_SYNC_PERMISSION_DENIED("SyncPermissionDenied", realm_errno_e.RLM_ERR_SYNC_PERMISSION_DENIED), + RLM_ERR_SYNC_PROTOCOL_INVARIANT_FAILED("SyncProtocolInvariantFailed", realm_errno_e.RLM_ERR_SYNC_PROTOCOL_INVARIANT_FAILED), + RLM_ERR_SYNC_PROTOCOL_NEGOTIATION_FAILED("SyncProtocolNegotiationFailed", realm_errno_e.RLM_ERR_SYNC_PROTOCOL_NEGOTIATION_FAILED), + RLM_ERR_SYNC_SERVER_PERMISSIONS_CHANGED("SyncServerPermissionsChanged", realm_errno_e.RLM_ERR_SYNC_SERVER_PERMISSIONS_CHANGED), + RLM_ERR_SYNC_USER_MISMATCH("SyncUserMismatch", realm_errno_e.RLM_ERR_SYNC_USER_MISMATCH), + RLM_ERR_TLS_HANDSHAKE_FAILED("TLSHandshakeFailed", realm_errno_e.RLM_ERR_TLS_HANDSHAKE_FAILED), + RLM_ERR_WRONG_SYNC_TYPE("WrongSyncType", realm_errno_e.RLM_ERR_WRONG_SYNC_TYPE), + RLM_ERR_SYNC_WRITE_NOT_ALLOWED("SyncWriteNotAllowed", realm_errno_e.RLM_ERR_SYNC_WRITE_NOT_ALLOWED), RLM_ERR_SYSTEM_ERROR("SystemError", realm_errno_e.RLM_ERR_SYSTEM_ERROR), RLM_ERR_LOGIC("Logic", realm_errno_e.RLM_ERR_LOGIC), RLM_ERR_NOT_SUPPORTED("NotSupported", realm_errno_e.RLM_ERR_NOT_SUPPORTED), @@ -118,7 +134,7 @@ actual enum class ErrorCode(override val description: String, override val nativ RLM_ERR_MONGODB_ERROR("MongodbError", realm_errno_e.RLM_ERR_MONGODB_ERROR), RLM_ERR_ARGUMENTS_NOT_ALLOWED("ArgumentsNotAllowed", realm_errno_e.RLM_ERR_ARGUMENTS_NOT_ALLOWED), RLM_ERR_FUNCTION_EXECUTION_ERROR("FunctionExecutionError", realm_errno_e.RLM_ERR_FUNCTION_EXECUTION_ERROR), - RLM_ERR_NO_MATCHING_RULE("NoMatchingRule", realm_errno_e.RLM_ERR_NO_MATCHING_RULE), + RLM_ERR_NO_MATCHING_RULE("NoMatchingRule", realm_errno_e.RLM_ERR_NO_MATCHING_RULE_FOUND), RLM_ERR_INTERNAL_SERVER_ERROR("InternalServerError", realm_errno_e.RLM_ERR_INTERNAL_SERVER_ERROR), RLM_ERR_AUTH_PROVIDER_NOT_FOUND("AuthProviderNotFound", realm_errno_e.RLM_ERR_AUTH_PROVIDER_NOT_FOUND), RLM_ERR_AUTH_PROVIDER_ALREADY_EXISTS("AuthProviderAlreadyExists", realm_errno_e.RLM_ERR_AUTH_PROVIDER_ALREADY_EXISTS), @@ -159,9 +175,7 @@ actual enum class ErrorCode(override val description: String, override val nativ RLM_ERR_MAINTENANCE_IN_PROGRESS("MaintenanceInProgress", realm_errno_e.RLM_ERR_MAINTENANCE_IN_PROGRESS), RLM_ERR_USERPASS_TOKEN_INVALID("UserpassTokenInvalid", realm_errno_e.RLM_ERR_USERPASS_TOKEN_INVALID), RLM_ERR_INVALID_SERVER_RESPONSE("InvalidServerResponse", realm_errno_e.RLM_ERR_INVALID_SERVER_RESPONSE), - RLM_ERR_WEBSOCKET_RESOLVE_FAILED_ERROR("ResolveFailedError", realm_errno_e.RLM_ERR_WEBSOCKET_RESOLVE_FAILED_ERROR), - RLM_ERR_WEBSOCKET_CONNECTION_CLOSED_CLIENT_ERROR("ConnectionClosedClientError", realm_errno_e.RLM_ERR_WEBSOCKET_CONNECTION_CLOSED_CLIENT_ERROR), - RLM_ERR_WEBSOCKET_CONNECTION_CLOSED_SERVER_ERROR("ConnectionClosedServerError", realm_errno_e.RLM_ERR_WEBSOCKET_CONNECTION_CLOSED_SERVER_ERROR), + REALM_ERR_APP_SERVER_ERROR("AppServerError", realm_errno_e.RLM_ERR_APP_SERVER_ERROR), RLM_ERR_CALLBACK("Callback", realm_errno_e.RLM_ERR_CALLBACK), RLM_ERR_UNKNOWN("Unknown", realm_errno_e.RLM_ERR_UNKNOWN); diff --git a/packages/cinterop/src/jvm/kotlin/io/realm/kotlin/internal/interop/RealmInterop.kt b/packages/cinterop/src/jvm/kotlin/io/realm/kotlin/internal/interop/RealmInterop.kt index 88b254ca0b..35a6a7e8b2 100644 --- a/packages/cinterop/src/jvm/kotlin/io/realm/kotlin/internal/interop/RealmInterop.kt +++ b/packages/cinterop/src/jvm/kotlin/io/realm/kotlin/internal/interop/RealmInterop.kt @@ -27,8 +27,6 @@ import io.realm.kotlin.internal.interop.sync.JVMSyncSessionTransferCompletionCal import io.realm.kotlin.internal.interop.sync.MetadataMode import io.realm.kotlin.internal.interop.sync.NetworkTransport import io.realm.kotlin.internal.interop.sync.ProgressDirection -import io.realm.kotlin.internal.interop.sync.ProtocolClientErrorCode -import io.realm.kotlin.internal.interop.sync.SyncErrorCodeCategory import io.realm.kotlin.internal.interop.sync.SyncSessionResyncMode import io.realm.kotlin.internal.interop.sync.SyncUserIdentity import kotlinx.coroutines.CoroutineDispatcher @@ -1340,15 +1338,13 @@ actual object RealmInterop { actual fun realm_sync_session_handle_error_for_testing( syncSession: RealmSyncSessionPointer, - errorCode: ProtocolClientErrorCode, - category: SyncErrorCodeCategory, + error: ErrorCode, errorMessage: String, isFatal: Boolean ) { realmc.realm_sync_session_handle_error_for_testing( syncSession.cptr(), - errorCode.nativeValue, - category.nativeValue, + error.nativeValue, errorMessage, isFatal ) @@ -1396,12 +1392,6 @@ actual object RealmInterop { baseUrl?.let { realmc.realm_app_config_set_base_url(config, it) } // Sync Connection Parameters - connectionParams.localAppName?.let { appName -> - realmc.realm_app_config_set_local_app_name(config, appName) - } - connectionParams.localAppVersion?.let { appVersion -> - realmc.realm_app_config_set_local_app_name(config, appVersion) - } realmc.realm_app_config_set_sdk(config, connectionParams.sdkName) realmc.realm_app_config_set_sdk_version(config, connectionParams.sdkVersion) realmc.realm_app_config_set_platform_version(config, connectionParams.platformVersion) diff --git a/packages/cinterop/src/jvm/kotlin/io/realm/kotlin/internal/interop/sync/JVMSyncSessionTransferCompletionCallback.kt b/packages/cinterop/src/jvm/kotlin/io/realm/kotlin/internal/interop/sync/JVMSyncSessionTransferCompletionCallback.kt index d06b775d09..8c3cf2c981 100644 --- a/packages/cinterop/src/jvm/kotlin/io/realm/kotlin/internal/interop/sync/JVMSyncSessionTransferCompletionCallback.kt +++ b/packages/cinterop/src/jvm/kotlin/io/realm/kotlin/internal/interop/sync/JVMSyncSessionTransferCompletionCallback.kt @@ -16,6 +16,7 @@ package io.realm.kotlin.internal.interop.sync +import io.realm.kotlin.internal.interop.CoreError import io.realm.kotlin.internal.interop.SyncSessionTransferCompletionCallback // Interface used internally as a bridge between Kotlin (JVM) and JNI. @@ -28,7 +29,7 @@ internal class JVMSyncSessionTransferCompletionCallback( fun onSuccess() { callback.invoke(null) } - fun onError(category: Int, value: Int, message: String) { - callback.invoke(SyncErrorCode.newInstance(category, value, message)) + fun onError(categoryFlags: Int, value: Int, message: String) { + callback.invoke(CoreError(categoryFlags, value, message)) } } diff --git a/packages/cinterop/src/jvm/kotlin/io/realm/kotlin/internal/interop/sync/ProtocolErrorCode.kt b/packages/cinterop/src/jvm/kotlin/io/realm/kotlin/internal/interop/sync/ProtocolErrorCode.kt index bfc9f20ec5..8ba8028fa8 100644 --- a/packages/cinterop/src/jvm/kotlin/io/realm/kotlin/internal/interop/sync/ProtocolErrorCode.kt +++ b/packages/cinterop/src/jvm/kotlin/io/realm/kotlin/internal/interop/sync/ProtocolErrorCode.kt @@ -17,55 +17,11 @@ package io.realm.kotlin.internal.interop.sync import io.realm.kotlin.internal.interop.CodeDescription -import io.realm.kotlin.internal.interop.realm_sync_errno_client_e import io.realm.kotlin.internal.interop.realm_sync_errno_connection_e import io.realm.kotlin.internal.interop.realm_sync_errno_session_e +import io.realm.kotlin.internal.interop.realm_web_socket_errno_e -actual enum class ProtocolClientErrorCode( - override val description: String, - override val nativeValue: Int -) : CodeDescription { - RLM_SYNC_ERR_CLIENT_CONNECTION_CLOSED("ConnectionClosed", realm_sync_errno_client_e.RLM_SYNC_ERR_CLIENT_CONNECTION_CLOSED), - RLM_SYNC_ERR_CLIENT_UNKNOWN_MESSAGE("UnknownMessage", realm_sync_errno_client_e.RLM_SYNC_ERR_CLIENT_UNKNOWN_MESSAGE), - RLM_SYNC_ERR_CLIENT_BAD_SYNTAX("BadSyntax", realm_sync_errno_client_e.RLM_SYNC_ERR_CLIENT_BAD_SYNTAX), - RLM_SYNC_ERR_CLIENT_LIMITS_EXCEEDED("LimitsExceeded", realm_sync_errno_client_e.RLM_SYNC_ERR_CLIENT_LIMITS_EXCEEDED), - RLM_SYNC_ERR_CLIENT_BAD_SESSION_IDENT("BadSessionIdent", realm_sync_errno_client_e.RLM_SYNC_ERR_CLIENT_BAD_SESSION_IDENT), - RLM_SYNC_ERR_CLIENT_BAD_MESSAGE_ORDER("BadMessageOrder", realm_sync_errno_client_e.RLM_SYNC_ERR_CLIENT_BAD_MESSAGE_ORDER), - RLM_SYNC_ERR_CLIENT_BAD_CLIENT_FILE_IDENT("BadClientFileIdent", realm_sync_errno_client_e.RLM_SYNC_ERR_CLIENT_BAD_CLIENT_FILE_IDENT), - RLM_SYNC_ERR_CLIENT_BAD_PROGRESS("BadProgress", realm_sync_errno_client_e.RLM_SYNC_ERR_CLIENT_BAD_PROGRESS), - RLM_SYNC_ERR_CLIENT_BAD_CHANGESET_HEADER_SYNTAX("BadChangesetHeaderSyntax", realm_sync_errno_client_e.RLM_SYNC_ERR_CLIENT_BAD_CHANGESET_HEADER_SYNTAX), - RLM_SYNC_ERR_CLIENT_BAD_CHANGESET_SIZE("BadChangesetSize", realm_sync_errno_client_e.RLM_SYNC_ERR_CLIENT_BAD_CHANGESET_SIZE), - RLM_SYNC_ERR_CLIENT_BAD_ORIGIN_FILE_IDENT("BadOriginFileIdent", realm_sync_errno_client_e.RLM_SYNC_ERR_CLIENT_BAD_ORIGIN_FILE_IDENT), - RLM_SYNC_ERR_CLIENT_BAD_SERVER_VERSION("BadServerVersion", realm_sync_errno_client_e.RLM_SYNC_ERR_CLIENT_BAD_SERVER_VERSION), - RLM_SYNC_ERR_CLIENT_BAD_CHANGESET("BadChangeset", realm_sync_errno_client_e.RLM_SYNC_ERR_CLIENT_BAD_CHANGESET), - RLM_SYNC_ERR_CLIENT_BAD_REQUEST_IDENT("BadRequestIdent", realm_sync_errno_client_e.RLM_SYNC_ERR_CLIENT_BAD_REQUEST_IDENT), - RLM_SYNC_ERR_CLIENT_BAD_ERROR_CODE("BadErrorCode", realm_sync_errno_client_e.RLM_SYNC_ERR_CLIENT_BAD_ERROR_CODE), - RLM_SYNC_ERR_CLIENT_BAD_COMPRESSION("BadCompression", realm_sync_errno_client_e.RLM_SYNC_ERR_CLIENT_BAD_COMPRESSION), - RLM_SYNC_ERR_CLIENT_BAD_CLIENT_VERSION("BadClientVersion", realm_sync_errno_client_e.RLM_SYNC_ERR_CLIENT_BAD_CLIENT_VERSION), - RLM_SYNC_ERR_CLIENT_SSL_SERVER_CERT_REJECTED("SslServerCertRejected", realm_sync_errno_client_e.RLM_SYNC_ERR_CLIENT_SSL_SERVER_CERT_REJECTED), - RLM_SYNC_ERR_CLIENT_PONG_TIMEOUT("PongTimeout", realm_sync_errno_client_e.RLM_SYNC_ERR_CLIENT_PONG_TIMEOUT), - RLM_SYNC_ERR_CLIENT_BAD_CLIENT_FILE_IDENT_SALT("BadClientFileIdentSalt", realm_sync_errno_client_e.RLM_SYNC_ERR_CLIENT_BAD_CLIENT_FILE_IDENT_SALT), - RLM_SYNC_ERR_CLIENT_BAD_FILE_IDENT("BadFileIdent", realm_sync_errno_client_e.RLM_SYNC_ERR_CLIENT_BAD_FILE_IDENT), - RLM_SYNC_ERR_CLIENT_CONNECT_TIMEOUT("ConnectTimeout", realm_sync_errno_client_e.RLM_SYNC_ERR_CLIENT_CONNECT_TIMEOUT), - RLM_SYNC_ERR_CLIENT_BAD_TIMESTAMP("BadTimestamp", realm_sync_errno_client_e.RLM_SYNC_ERR_CLIENT_BAD_TIMESTAMP), - RLM_SYNC_ERR_CLIENT_BAD_PROTOCOL_FROM_SERVER("BadProtocolFromServer", realm_sync_errno_client_e.RLM_SYNC_ERR_CLIENT_BAD_PROTOCOL_FROM_SERVER), - RLM_SYNC_ERR_CLIENT_CLIENT_TOO_OLD_FOR_SERVER("ClientTooOldForServer", realm_sync_errno_client_e.RLM_SYNC_ERR_CLIENT_CLIENT_TOO_OLD_FOR_SERVER), - RLM_SYNC_ERR_CLIENT_CLIENT_TOO_NEW_FOR_SERVER("ClientTooNewForServer", realm_sync_errno_client_e.RLM_SYNC_ERR_CLIENT_CLIENT_TOO_NEW_FOR_SERVER), - RLM_SYNC_ERR_CLIENT_PROTOCOL_MISMATCH("ProtocolMismatch", realm_sync_errno_client_e.RLM_SYNC_ERR_CLIENT_PROTOCOL_MISMATCH), - RLM_SYNC_ERR_CLIENT_BAD_STATE_MESSAGE("BadStateMessage", realm_sync_errno_client_e.RLM_SYNC_ERR_CLIENT_BAD_STATE_MESSAGE), - RLM_SYNC_ERR_CLIENT_MISSING_PROTOCOL_FEATURE("MissingProtocolFeature", realm_sync_errno_client_e.RLM_SYNC_ERR_CLIENT_MISSING_PROTOCOL_FEATURE), - RLM_SYNC_ERR_CLIENT_HTTP_TUNNEL_FAILED("HttpTunnelFailed", realm_sync_errno_client_e.RLM_SYNC_ERR_CLIENT_HTTP_TUNNEL_FAILED), - RLM_SYNC_ERR_CLIENT_AUTO_CLIENT_RESET_FAILURE("AutoClientResetFailure", realm_sync_errno_client_e.RLM_SYNC_ERR_CLIENT_AUTO_CLIENT_RESET_FAILURE); - - actual companion object { - internal actual fun of(nativeValue: Int): ProtocolClientErrorCode? = - values().firstOrNull { value -> - value.nativeValue == nativeValue - } - } -} - -actual enum class ProtocolConnectionErrorCode( +actual enum class SyncConnectionErrorCode( override val description: String, override val nativeValue: Int ) : CodeDescription { @@ -74,7 +30,7 @@ actual enum class ProtocolConnectionErrorCode( RLM_SYNC_ERR_CONNECTION_UNKNOWN_MESSAGE("UnknownMessage", realm_sync_errno_connection_e.RLM_SYNC_ERR_CONNECTION_UNKNOWN_MESSAGE), RLM_SYNC_ERR_CONNECTION_BAD_SYNTAX("BadSyntax", realm_sync_errno_connection_e.RLM_SYNC_ERR_CONNECTION_BAD_SYNTAX), RLM_SYNC_ERR_CONNECTION_LIMITS_EXCEEDED("LimitsExceeded", realm_sync_errno_connection_e.RLM_SYNC_ERR_CONNECTION_LIMITS_EXCEEDED), - RLM_SYNC_ERR_CONNECTION_WRONG_PROTOCOL_VERSION("WrongProtocolVersion", realm_sync_errno_connection_e.RLM_SYNC_ERR_CONNECTION_WRONG_PROTOCOL_VERSION), + RLM_SYNC_ERR_CONNECTION_WRONG_PROTOCOL_VERSION("WrongBadSyncPartitionValueProtocolVersion", realm_sync_errno_connection_e.RLM_SYNC_ERR_CONNECTION_WRONG_PROTOCOL_VERSION), RLM_SYNC_ERR_CONNECTION_BAD_SESSION_IDENT("BadSessionIdent", realm_sync_errno_connection_e.RLM_SYNC_ERR_CONNECTION_BAD_SESSION_IDENT), RLM_SYNC_ERR_CONNECTION_REUSE_OF_SESSION_IDENT("ReuseOfSessionIdent", realm_sync_errno_connection_e.RLM_SYNC_ERR_CONNECTION_REUSE_OF_SESSION_IDENT), RLM_SYNC_ERR_CONNECTION_BOUND_IN_OTHER_SESSION("BoundInOtherSession", realm_sync_errno_connection_e.RLM_SYNC_ERR_CONNECTION_BOUND_IN_OTHER_SESSION), @@ -86,14 +42,14 @@ actual enum class ProtocolConnectionErrorCode( RLM_SYNC_ERR_CONNECTION_SWITCH_TO_PBS("SwitchToPbs", realm_sync_errno_connection_e.RLM_SYNC_ERR_CONNECTION_SWITCH_TO_PBS); actual companion object { - internal actual fun of(nativeValue: Int): ProtocolConnectionErrorCode? = + internal actual fun of(nativeValue: Int): SyncConnectionErrorCode? = values().firstOrNull { value -> value.nativeValue == nativeValue } } } -actual enum class ProtocolSessionErrorCode( +actual enum class SyncSessionErrorCode( override val description: String, override val nativeValue: Int ) : CodeDescription { @@ -133,7 +89,47 @@ actual enum class ProtocolSessionErrorCode( RLM_SYNC_ERR_SESSION_REVERT_TO_PBS("RevertToPartitionBasedSync", realm_sync_errno_session_e.RLM_SYNC_ERR_SESSION_REVERT_TO_PBS); actual companion object { - internal actual fun of(nativeValue: Int): ProtocolSessionErrorCode? = + internal actual fun of(nativeValue: Int): SyncSessionErrorCode? = + values().firstOrNull { value -> + value.nativeValue == nativeValue + } + } +} + +actual enum class WebsocketErrorCode( + override val description: String, + override val nativeValue: Int +) : CodeDescription { + RLM_ERR_WEBSOCKET_OK("Ok", realm_web_socket_errno_e.RLM_ERR_WEBSOCKET_OK), + RLM_ERR_WEBSOCKET_GOINGAWAY("GoingAway", realm_web_socket_errno_e.RLM_ERR_WEBSOCKET_GOINGAWAY), + RLM_ERR_WEBSOCKET_PROTOCOLERROR("ProtocolError", realm_web_socket_errno_e.RLM_ERR_WEBSOCKET_PROTOCOLERROR), + RLM_ERR_WEBSOCKET_UNSUPPORTEDDATA("UnsupportedData", realm_web_socket_errno_e.RLM_ERR_WEBSOCKET_UNSUPPORTEDDATA), + RLM_ERR_WEBSOCKET_RESERVED("Reserved", realm_web_socket_errno_e.RLM_ERR_WEBSOCKET_RESERVED), + RLM_ERR_WEBSOCKET_NOSTATUSRECEIVED("NoStatusReceived", realm_web_socket_errno_e.RLM_ERR_WEBSOCKET_NOSTATUSRECEIVED), + RLM_ERR_WEBSOCKET_ABNORMALCLOSURE("AbnormalClosure", realm_web_socket_errno_e.RLM_ERR_WEBSOCKET_ABNORMALCLOSURE), + RLM_ERR_WEBSOCKET_INVALIDPAYLOADDATA("InvalidPayloadData", realm_web_socket_errno_e.RLM_ERR_WEBSOCKET_INVALIDPAYLOADDATA), + RLM_ERR_WEBSOCKET_POLICYVIOLATION("PolicyViolation", realm_web_socket_errno_e.RLM_ERR_WEBSOCKET_POLICYVIOLATION), + RLM_ERR_WEBSOCKET_MESSAGETOOBIG("MessageToBig", realm_web_socket_errno_e.RLM_ERR_WEBSOCKET_MESSAGETOOBIG), + RLM_ERR_WEBSOCKET_INAVALIDEXTENSION("InvalidExtension", realm_web_socket_errno_e.RLM_ERR_WEBSOCKET_INAVALIDEXTENSION), + RLM_ERR_WEBSOCKET_INTERNALSERVERERROR("InternalServerError", realm_web_socket_errno_e.RLM_ERR_WEBSOCKET_INTERNALSERVERERROR), + RLM_ERR_WEBSOCKET_TLSHANDSHAKEFAILED("TlsHandshakeFailed", realm_web_socket_errno_e.RLM_ERR_WEBSOCKET_TLSHANDSHAKEFAILED), + + RLM_ERR_WEBSOCKET_UNAUTHORIZED("Unauthorized", realm_web_socket_errno_e.RLM_ERR_WEBSOCKET_UNAUTHORIZED), + RLM_ERR_WEBSOCKET_FORBIDDEN("Forbidden", realm_web_socket_errno_e.RLM_ERR_WEBSOCKET_FORBIDDEN), + RLM_ERR_WEBSOCKET_MOVEDPERMANENTLY("MovedPermanently", realm_web_socket_errno_e.RLM_ERR_WEBSOCKET_MOVEDPERMANENTLY), + RLM_ERR_WEBSOCKET_CLIENT_TOO_OLD("ClientTooOld", realm_web_socket_errno_e.RLM_ERR_WEBSOCKET_CLIENT_TOO_OLD), + RLM_ERR_WEBSOCKET_CLIENT_TOO_NEW("ClientTooNew", realm_web_socket_errno_e.RLM_ERR_WEBSOCKET_CLIENT_TOO_NEW), + RLM_ERR_WEBSOCKET_PROTOCOL_MISMATCH("ProtocolMismatch", realm_web_socket_errno_e.RLM_ERR_WEBSOCKET_PROTOCOL_MISMATCH), + + RLM_ERR_WEBSOCKET_RESOLVE_FAILED("ResolveFailed", realm_web_socket_errno_e.RLM_ERR_WEBSOCKET_RESOLVE_FAILED), + RLM_ERR_WEBSOCKET_CONNECTION_FAILED("ConnectionFailed", realm_web_socket_errno_e.RLM_ERR_WEBSOCKET_CONNECTION_FAILED), + RLM_ERR_WEBSOCKET_READ_ERROR("ReadError", realm_web_socket_errno_e.RLM_ERR_WEBSOCKET_READ_ERROR), + RLM_ERR_WEBSOCKET_WRITE_ERROR("WriteError", realm_web_socket_errno_e.RLM_ERR_WEBSOCKET_WRITE_ERROR), + RLM_ERR_WEBSOCKET_RETRY_ERROR("RetryError", realm_web_socket_errno_e.RLM_ERR_WEBSOCKET_RETRY_ERROR), + RLM_ERR_WEBSOCKET_FATAL_ERROR("FatalError", realm_web_socket_errno_e.RLM_ERR_WEBSOCKET_FATAL_ERROR); + + actual companion object { + internal actual fun of(nativeValue: Int): WebsocketErrorCode? = values().firstOrNull { value -> value.nativeValue == nativeValue } diff --git a/packages/cinterop/src/jvm/kotlin/io/realm/kotlin/internal/interop/sync/SyncErrorCodeCategory.kt b/packages/cinterop/src/jvm/kotlin/io/realm/kotlin/internal/interop/sync/SyncErrorCodeCategory.kt deleted file mode 100644 index 6c66bfbd38..0000000000 --- a/packages/cinterop/src/jvm/kotlin/io/realm/kotlin/internal/interop/sync/SyncErrorCodeCategory.kt +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright 2022 Realm 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 io.realm.kotlin.internal.interop.sync - -import io.realm.kotlin.internal.interop.CodeDescription -import io.realm.kotlin.internal.interop.realm_sync_error_category_e - -actual enum class SyncErrorCodeCategory(override val description: String, override val nativeValue: Int) : - CodeDescription { - RLM_SYNC_ERROR_CATEGORY_CLIENT("Client", realm_sync_error_category_e.RLM_SYNC_ERROR_CATEGORY_CLIENT), - RLM_SYNC_ERROR_CATEGORY_CONNECTION("Connection", realm_sync_error_category_e.RLM_SYNC_ERROR_CATEGORY_CONNECTION), - RLM_SYNC_ERROR_CATEGORY_SESSION("Session", realm_sync_error_category_e.RLM_SYNC_ERROR_CATEGORY_SESSION), - RLM_SYNC_ERROR_CATEGORY_WEBSOCKET("Websocket", realm_sync_error_category_e.RLM_SYNC_ERROR_CATEGORY_WEBSOCKET), - RLM_SYNC_ERROR_CATEGORY_SYSTEM("System", realm_sync_error_category_e.RLM_SYNC_ERROR_CATEGORY_SYSTEM), - RLM_SYNC_ERROR_CATEGORY_UNKNOWN("Unknown", realm_sync_error_category_e.RLM_SYNC_ERROR_CATEGORY_UNKNOWN); - - actual companion object { - internal actual fun of(nativeValue: Int): SyncErrorCodeCategory? = - values().firstOrNull { value -> - value.nativeValue == nativeValue - } - } -} diff --git a/packages/cinterop/src/native/realm.def b/packages/cinterop/src/native/realm.def index d5f34c6379..0c92edfbee 100644 --- a/packages/cinterop/src/native/realm.def +++ b/packages/cinterop/src/native/realm.def @@ -11,7 +11,7 @@ headerFilter = realm.h realm/error_codes.h // libraryPaths.macos_x64 = ../external/core/build-macos_x64/src/realm/object-store/c_api ../external/core/build-macos_x64/src/realm ../external/core/build-macos_x64/src/realm/parser ../external/core/build-macos_x64/src/realm/object-store/ // libraryPaths.ios_x64 = ../external/core/build-macos_x64/src/realm/object-store/c_api ../external/core/build-macos_x64/src/realm ../external/core/build-macos_x64/src/realm/parser ../external/core/build-macos_x64/src/realm/object-store/ linkerOpts = -lcompression -lz -framework Foundation -framework CoreFoundation -framework Security -strictEnums = realm_errno realm_error_category realm_sync_errno_client realm_sync_errno_connection realm_sync_errno_session +strictEnums = realm_errno realm_error_category realm_sync_errno_client realm_sync_errno_connection realm_sync_errno_session realm_web_socket_errno --- #include #include diff --git a/packages/cinterop/src/nativeDarwin/kotlin/io/realm/kotlin/internal/interop/ErrorCategory.kt b/packages/cinterop/src/nativeDarwin/kotlin/io/realm/kotlin/internal/interop/ErrorCategory.kt index a792b233d7..ab2a7bfad5 100644 --- a/packages/cinterop/src/nativeDarwin/kotlin/io/realm/kotlin/internal/interop/ErrorCategory.kt +++ b/packages/cinterop/src/nativeDarwin/kotlin/io/realm/kotlin/internal/interop/ErrorCategory.kt @@ -35,7 +35,8 @@ actual enum class ErrorCategory( RLM_ERR_CAT_SERVICE_ERROR("Service", realm_error_category.RLM_ERR_CAT_SERVICE_ERROR.value.toInt()), RLM_ERR_CAT_HTTP_ERROR("Http", realm_error_category.RLM_ERR_CAT_HTTP_ERROR.value.toInt()), RLM_ERR_CAT_CUSTOM_ERROR("Custom", realm_error_category.RLM_ERR_CAT_CUSTOM_ERROR.value.toInt()), - RLM_ERR_CAT_WEBSOCKET_ERROR("Websocket", realm_error_category.RLM_ERR_CAT_WEBSOCKET_ERROR.value.toInt()); + RLM_ERR_CAT_WEBSOCKET_ERROR("Websocket", realm_error_category.RLM_ERR_CAT_WEBSOCKET_ERROR.value.toInt()), + RLM_ERR_CAT_SYNC_ERROR("Sync", realm_error_category.RLM_ERR_CAT_SYNC_ERROR.value.toInt()); actual companion object { diff --git a/packages/cinterop/src/nativeDarwin/kotlin/io/realm/kotlin/internal/interop/ErrorCode.kt b/packages/cinterop/src/nativeDarwin/kotlin/io/realm/kotlin/internal/interop/ErrorCode.kt index 70987acd03..3fb35d665c 100644 --- a/packages/cinterop/src/nativeDarwin/kotlin/io/realm/kotlin/internal/interop/ErrorCode.kt +++ b/packages/cinterop/src/nativeDarwin/kotlin/io/realm/kotlin/internal/interop/ErrorCode.kt @@ -20,7 +20,7 @@ import realm_wrapper.realm_errno actual enum class ErrorCode( override val description: String, - error: realm_errno + private val nativeError: realm_errno ) : CodeDescription { RLM_ERR_NONE("None", realm_errno.RLM_ERR_NONE), RLM_ERR_RUNTIME("Runtime", realm_errno.RLM_ERR_RUNTIME), @@ -51,6 +51,22 @@ actual enum class ErrorCode( RLM_ERR_SCHEMA_VERSION_MISMATCH("SchemaVersionMismatch", realm_errno.RLM_ERR_SCHEMA_VERSION_MISMATCH), RLM_ERR_NO_SUBSCRIPTION_FOR_WRITE("NoSubscriptionForWrite", realm_errno.RLM_ERR_NO_SUBSCRIPTION_FOR_WRITE), RLM_ERR_OPERATION_ABORTED("OperationAborted", realm_errno.RLM_ERR_OPERATION_ABORTED), + RLM_ERR_AUTO_CLIENT_RESET_FAILED("AutoClientResetFailed", realm_errno.RLM_ERR_AUTO_CLIENT_RESET_FAILED), + RLM_ERR_BAD_SYNC_PARTITION_VALUE("BadSyncPartitionValue", realm_errno.RLM_ERR_BAD_SYNC_PARTITION_VALUE), + RLM_ERR_CONNECTION_CLOSED("ConnectionClosed", realm_errno.RLM_ERR_CONNECTION_CLOSED), + RLM_ERR_INVALID_SUBSCRIPTION_QUERY("InvalidSubscriptionQuery", realm_errno.RLM_ERR_INVALID_SUBSCRIPTION_QUERY), + RLM_ERR_SYNC_CLIENT_RESET_REQUIRED("SyncClientResetRequired", realm_errno.RLM_ERR_SYNC_CLIENT_RESET_REQUIRED), + RLM_ERR_SYNC_COMPENSATING_WRITE("CompensatingWrite", realm_errno.RLM_ERR_SYNC_COMPENSATING_WRITE), + RLM_ERR_SYNC_CONNECT_FAILED("SyncConnectFailed", realm_errno.RLM_ERR_SYNC_CONNECT_FAILED), + RLM_ERR_SYNC_INVALID_SCHEMA_CHANGE("SyncInvalidSchemaChange", realm_errno.RLM_ERR_SYNC_INVALID_SCHEMA_CHANGE), + RLM_ERR_SYNC_PERMISSION_DENIED("SyncPermissionDenied", realm_errno.RLM_ERR_SYNC_PERMISSION_DENIED), + RLM_ERR_SYNC_PROTOCOL_INVARIANT_FAILED("SyncProtocolInvariantFailed", realm_errno.RLM_ERR_SYNC_PROTOCOL_INVARIANT_FAILED), + RLM_ERR_SYNC_PROTOCOL_NEGOTIATION_FAILED("SyncProtocolNegotiationFailed", realm_errno.RLM_ERR_SYNC_PROTOCOL_NEGOTIATION_FAILED), + RLM_ERR_SYNC_SERVER_PERMISSIONS_CHANGED("SyncServerPermissionsChanged", realm_errno.RLM_ERR_SYNC_SERVER_PERMISSIONS_CHANGED), + RLM_ERR_SYNC_USER_MISMATCH("SyncUserMismatch", realm_errno.RLM_ERR_SYNC_USER_MISMATCH), + RLM_ERR_TLS_HANDSHAKE_FAILED("TLSHandshakeFailed", realm_errno.RLM_ERR_TLS_HANDSHAKE_FAILED), + RLM_ERR_WRONG_SYNC_TYPE("WrongSyncType", realm_errno.RLM_ERR_WRONG_SYNC_TYPE), + RLM_ERR_SYNC_WRITE_NOT_ALLOWED("SyncWriteNotAllowed", realm_errno.RLM_ERR_SYNC_WRITE_NOT_ALLOWED), RLM_ERR_SYSTEM_ERROR("SystemError", realm_errno.RLM_ERR_SYSTEM_ERROR), RLM_ERR_LOGIC("Logic", realm_errno.RLM_ERR_LOGIC), RLM_ERR_NOT_SUPPORTED("NotSupported", realm_errno.RLM_ERR_NOT_SUPPORTED), @@ -122,7 +138,7 @@ actual enum class ErrorCode( RLM_ERR_MONGODB_ERROR("MongodbError", realm_errno.RLM_ERR_MONGODB_ERROR), RLM_ERR_ARGUMENTS_NOT_ALLOWED("ArgumentsNotAllowed", realm_errno.RLM_ERR_ARGUMENTS_NOT_ALLOWED), RLM_ERR_FUNCTION_EXECUTION_ERROR("FunctionExecutionError", realm_errno.RLM_ERR_FUNCTION_EXECUTION_ERROR), - RLM_ERR_NO_MATCHING_RULE("NoMatchingRule", realm_errno.RLM_ERR_NO_MATCHING_RULE), + RLM_ERR_NO_MATCHING_RULE("NoMatchingRule", realm_errno.RLM_ERR_NO_MATCHING_RULE_FOUND), RLM_ERR_INTERNAL_SERVER_ERROR("InternalServerError", realm_errno.RLM_ERR_INTERNAL_SERVER_ERROR), RLM_ERR_AUTH_PROVIDER_NOT_FOUND("AuthProviderNotFound", realm_errno.RLM_ERR_AUTH_PROVIDER_NOT_FOUND), RLM_ERR_AUTH_PROVIDER_ALREADY_EXISTS("AuthProviderAlreadyExists", realm_errno.RLM_ERR_AUTH_PROVIDER_ALREADY_EXISTS), @@ -163,13 +179,13 @@ actual enum class ErrorCode( RLM_ERR_MAINTENANCE_IN_PROGRESS("MaintenanceInProgress", realm_errno.RLM_ERR_MAINTENANCE_IN_PROGRESS), RLM_ERR_USERPASS_TOKEN_INVALID("UserpassTokenInvalid", realm_errno.RLM_ERR_USERPASS_TOKEN_INVALID), RLM_ERR_INVALID_SERVER_RESPONSE("InvalidServerResponse", realm_errno.RLM_ERR_INVALID_SERVER_RESPONSE), - RLM_ERR_WEBSOCKET_RESOLVE_FAILED_ERROR("ResolveFailedError", realm_errno.RLM_ERR_WEBSOCKET_RESOLVE_FAILED_ERROR), - RLM_ERR_WEBSOCKET_CONNECTION_CLOSED_CLIENT_ERROR("ConnectionClosedClientError", realm_errno.RLM_ERR_WEBSOCKET_CONNECTION_CLOSED_CLIENT_ERROR), - RLM_ERR_WEBSOCKET_CONNECTION_CLOSED_SERVER_ERROR("ConnectionClosedServerError", realm_errno.RLM_ERR_WEBSOCKET_CONNECTION_CLOSED_SERVER_ERROR), + REALM_ERR_APP_SERVER_ERROR("AppServerError", realm_errno.RLM_ERR_APP_SERVER_ERROR), RLM_ERR_CALLBACK("Callback", realm_errno.RLM_ERR_CALLBACK), RLM_ERR_UNKNOWN("Unknown", realm_errno.RLM_ERR_UNKNOWN); - override val nativeValue: Int = error.value.toInt() + override val nativeValue: Int = nativeError.value.toInt() + + val asNativeEnum: realm_errno = nativeError actual companion object { actual fun of(nativeValue: Int): ErrorCode? = diff --git a/packages/cinterop/src/nativeDarwin/kotlin/io/realm/kotlin/internal/interop/RealmInterop.kt b/packages/cinterop/src/nativeDarwin/kotlin/io/realm/kotlin/internal/interop/RealmInterop.kt index 96a5d86e00..1f25cf704d 100644 --- a/packages/cinterop/src/nativeDarwin/kotlin/io/realm/kotlin/internal/interop/RealmInterop.kt +++ b/packages/cinterop/src/nativeDarwin/kotlin/io/realm/kotlin/internal/interop/RealmInterop.kt @@ -19,7 +19,6 @@ package io.realm.kotlin.internal.interop import io.realm.kotlin.internal.interop.Constants.ENCRYPTION_KEY_LENGTH -import io.realm.kotlin.internal.interop.RealmInterop.safeKString import io.realm.kotlin.internal.interop.sync.ApiKeyWrapper import io.realm.kotlin.internal.interop.sync.AppError import io.realm.kotlin.internal.interop.sync.AuthProvider @@ -31,11 +30,8 @@ import io.realm.kotlin.internal.interop.sync.CoreUserState import io.realm.kotlin.internal.interop.sync.MetadataMode import io.realm.kotlin.internal.interop.sync.NetworkTransport import io.realm.kotlin.internal.interop.sync.ProgressDirection -import io.realm.kotlin.internal.interop.sync.ProtocolClientErrorCode import io.realm.kotlin.internal.interop.sync.Response import io.realm.kotlin.internal.interop.sync.SyncError -import io.realm.kotlin.internal.interop.sync.SyncErrorCode -import io.realm.kotlin.internal.interop.sync.SyncErrorCodeCategory import io.realm.kotlin.internal.interop.sync.SyncSessionResyncMode import io.realm.kotlin.internal.interop.sync.SyncUserIdentity import kotlinx.atomicfu.AtomicBoolean @@ -121,7 +117,6 @@ import realm_wrapper.realm_scheduler_t import realm_wrapper.realm_set_t import realm_wrapper.realm_string_t import realm_wrapper.realm_sync_client_metadata_mode -import realm_wrapper.realm_sync_error_code_t import realm_wrapper.realm_sync_session_resync_mode import realm_wrapper.realm_sync_session_state_e import realm_wrapper.realm_sync_session_stop_policy_e @@ -562,7 +557,7 @@ actual object RealmInterop { ) err.usercode_error?.let { disposeUserData(it) } } else { - realm_wrapper.realm_release(realm) + realm_release(realm) } safeUserData(userData).invoke(exception) } @@ -2391,10 +2386,10 @@ actual object RealmInterop { syncConfig.cptr(), staticCFunction { userData, syncSession, error -> val syncError: SyncError = error.useContents { - val code = SyncErrorCode.newInstance( - error_code.category.value.toInt(), - error_code.value, - error_code.message.safeKString() + val code = CoreError( + this.status.categories.toInt(), + this.status.error.value.toInt(), + this.status.message.safeKString() ) val userInfoMap = (0 until user_info_length.toInt()) @@ -2421,7 +2416,6 @@ actual object RealmInterop { SyncError( errorCode = code, - detailedMessage = detailed_message.safeKString(), originalFilePath = userInfoMap[c_original_file_path_key.safeKString()], recoveryFilePath = userInfoMap[c_recovery_file_path_key.safeKString()], isFatal = is_fatal, @@ -2527,7 +2521,7 @@ actual object RealmInterop { ) { realm_wrapper.realm_sync_session_wait_for_download_completion( syncSession.cptr(), - staticCFunction?, Unit> { userData, error -> + staticCFunction?, Unit> { userData, error -> handleCompletionCallback(userData, error) }, StableRef.create(callback).asCPointer(), @@ -2543,7 +2537,7 @@ actual object RealmInterop { ) { realm_wrapper.realm_sync_session_wait_for_upload_completion( syncSession.cptr(), - staticCFunction?, Unit> { userData, error -> + staticCFunction?, Unit> { userData, error -> handleCompletionCallback(userData, error) }, StableRef.create(callback).asCPointer(), @@ -2574,15 +2568,13 @@ actual object RealmInterop { actual fun realm_sync_session_handle_error_for_testing( syncSession: RealmSyncSessionPointer, - errorCode: ProtocolClientErrorCode, - category: SyncErrorCodeCategory, + error: ErrorCode, errorMessage: String, isFatal: Boolean ) { realm_wrapper.realm_sync_session_handle_error_for_testing( syncSession.cptr(), - errorCode.nativeValue.toInt(), - category.nativeValue, + error.asNativeEnum, errorMessage, isFatal ) @@ -2636,14 +2628,14 @@ actual object RealmInterop { private fun handleCompletionCallback( userData: CPointer?, - error: CPointer? + error: CPointer? ) { val completionCallback = safeUserData(userData) if (error != null) { - val category = error.pointed.category.value.toInt() - val value: Int = error.pointed.value + val category = error.pointed.categories.toInt() + val value: Int = error.pointed.error.value.toInt() val message = error.pointed.message.safeKString() - completionCallback.invoke(SyncErrorCode.newInstance(category, value, message)) + completionCallback.invoke(CoreError(category, value, message)) } else { completionCallback.invoke(null) } @@ -2672,12 +2664,6 @@ actual object RealmInterop { baseUrl?.let { realm_wrapper.realm_app_config_set_base_url(appConfig, it) } // Sync Connection Parameters - connectionParams.localAppName?.let { appName -> - realm_wrapper.realm_app_config_set_local_app_name(appConfig, appName) - } - connectionParams.localAppVersion?.let { appVersion -> - realm_wrapper.realm_app_config_set_local_app_name(appConfig, appVersion) - } realm_wrapper.realm_app_config_set_sdk(appConfig, connectionParams.sdkName) realm_wrapper.realm_app_config_set_sdk_version(appConfig, connectionParams.sdkVersion) realm_wrapper.realm_app_config_set_platform_version(appConfig, connectionParams.platformVersion) diff --git a/packages/cinterop/src/nativeDarwin/kotlin/io/realm/kotlin/internal/interop/sync/ProtocolErrorCode.kt b/packages/cinterop/src/nativeDarwin/kotlin/io/realm/kotlin/internal/interop/sync/ProtocolErrorCode.kt index 6504d9b0ea..20817a0ae5 100644 --- a/packages/cinterop/src/nativeDarwin/kotlin/io/realm/kotlin/internal/interop/sync/ProtocolErrorCode.kt +++ b/packages/cinterop/src/nativeDarwin/kotlin/io/realm/kotlin/internal/interop/sync/ProtocolErrorCode.kt @@ -16,57 +16,11 @@ package io.realm.kotlin.internal.interop.sync import io.realm.kotlin.internal.interop.CodeDescription -import realm_wrapper.realm_sync_errno_client import realm_wrapper.realm_sync_errno_connection import realm_wrapper.realm_sync_errno_session +import realm_wrapper.realm_web_socket_errno -actual enum class ProtocolClientErrorCode( - override val description: String, - errorCode: realm_sync_errno_client -) : CodeDescription { - RLM_SYNC_ERR_CLIENT_CONNECTION_CLOSED("ConnectionClosed", realm_sync_errno_client.RLM_SYNC_ERR_CLIENT_CONNECTION_CLOSED), - RLM_SYNC_ERR_CLIENT_UNKNOWN_MESSAGE("UnknownMessage", realm_sync_errno_client.RLM_SYNC_ERR_CLIENT_UNKNOWN_MESSAGE), - RLM_SYNC_ERR_CLIENT_BAD_SYNTAX("BadSyntax", realm_sync_errno_client.RLM_SYNC_ERR_CLIENT_BAD_SYNTAX), - RLM_SYNC_ERR_CLIENT_LIMITS_EXCEEDED("LimitsExceeded", realm_sync_errno_client.RLM_SYNC_ERR_CLIENT_LIMITS_EXCEEDED), - RLM_SYNC_ERR_CLIENT_BAD_SESSION_IDENT("BadSessionIdent", realm_sync_errno_client.RLM_SYNC_ERR_CLIENT_BAD_SESSION_IDENT), - RLM_SYNC_ERR_CLIENT_BAD_MESSAGE_ORDER("BadMessageOrder", realm_sync_errno_client.RLM_SYNC_ERR_CLIENT_BAD_MESSAGE_ORDER), - RLM_SYNC_ERR_CLIENT_BAD_CLIENT_FILE_IDENT("BadClientFileIdent", realm_sync_errno_client.RLM_SYNC_ERR_CLIENT_BAD_CLIENT_FILE_IDENT), - RLM_SYNC_ERR_CLIENT_BAD_PROGRESS("BadProgress", realm_sync_errno_client.RLM_SYNC_ERR_CLIENT_BAD_PROGRESS), - RLM_SYNC_ERR_CLIENT_BAD_CHANGESET_HEADER_SYNTAX("BadChangesetHeaderSyntax", realm_sync_errno_client.RLM_SYNC_ERR_CLIENT_BAD_CHANGESET_HEADER_SYNTAX), - RLM_SYNC_ERR_CLIENT_BAD_CHANGESET_SIZE("BadChangesetSize", realm_sync_errno_client.RLM_SYNC_ERR_CLIENT_BAD_CHANGESET_SIZE), - RLM_SYNC_ERR_CLIENT_BAD_ORIGIN_FILE_IDENT("BadOriginFileIdent", realm_sync_errno_client.RLM_SYNC_ERR_CLIENT_BAD_ORIGIN_FILE_IDENT), - RLM_SYNC_ERR_CLIENT_BAD_SERVER_VERSION("BadServerVersion", realm_sync_errno_client.RLM_SYNC_ERR_CLIENT_BAD_SERVER_VERSION), - RLM_SYNC_ERR_CLIENT_BAD_CHANGESET("BadChangeset", realm_sync_errno_client.RLM_SYNC_ERR_CLIENT_BAD_CHANGESET), - RLM_SYNC_ERR_CLIENT_BAD_REQUEST_IDENT("BadRequestIdent", realm_sync_errno_client.RLM_SYNC_ERR_CLIENT_BAD_REQUEST_IDENT), - RLM_SYNC_ERR_CLIENT_BAD_ERROR_CODE("BadErrorCode", realm_sync_errno_client.RLM_SYNC_ERR_CLIENT_BAD_ERROR_CODE), - RLM_SYNC_ERR_CLIENT_BAD_COMPRESSION("BadCompression", realm_sync_errno_client.RLM_SYNC_ERR_CLIENT_BAD_COMPRESSION), - RLM_SYNC_ERR_CLIENT_BAD_CLIENT_VERSION("BadClientVersion", realm_sync_errno_client.RLM_SYNC_ERR_CLIENT_BAD_CLIENT_VERSION), - RLM_SYNC_ERR_CLIENT_SSL_SERVER_CERT_REJECTED("SslServerCertRejected", realm_sync_errno_client.RLM_SYNC_ERR_CLIENT_SSL_SERVER_CERT_REJECTED), - RLM_SYNC_ERR_CLIENT_PONG_TIMEOUT("PongTimeout", realm_sync_errno_client.RLM_SYNC_ERR_CLIENT_PONG_TIMEOUT), - RLM_SYNC_ERR_CLIENT_BAD_CLIENT_FILE_IDENT_SALT("BadClientFileIdentSalt", realm_sync_errno_client.RLM_SYNC_ERR_CLIENT_BAD_CLIENT_FILE_IDENT_SALT), - RLM_SYNC_ERR_CLIENT_BAD_FILE_IDENT("BadFileIdent", realm_sync_errno_client.RLM_SYNC_ERR_CLIENT_BAD_FILE_IDENT), - RLM_SYNC_ERR_CLIENT_CONNECT_TIMEOUT("ConnectTimeout", realm_sync_errno_client.RLM_SYNC_ERR_CLIENT_CONNECT_TIMEOUT), - RLM_SYNC_ERR_CLIENT_BAD_TIMESTAMP("BadTimestamp", realm_sync_errno_client.RLM_SYNC_ERR_CLIENT_BAD_TIMESTAMP), - RLM_SYNC_ERR_CLIENT_BAD_PROTOCOL_FROM_SERVER("BadProtocolFromServer", realm_sync_errno_client.RLM_SYNC_ERR_CLIENT_BAD_PROTOCOL_FROM_SERVER), - RLM_SYNC_ERR_CLIENT_CLIENT_TOO_OLD_FOR_SERVER("ClientTooOldForServer", realm_sync_errno_client.RLM_SYNC_ERR_CLIENT_CLIENT_TOO_OLD_FOR_SERVER), - RLM_SYNC_ERR_CLIENT_CLIENT_TOO_NEW_FOR_SERVER("ClientTooNewForServer", realm_sync_errno_client.RLM_SYNC_ERR_CLIENT_CLIENT_TOO_NEW_FOR_SERVER), - RLM_SYNC_ERR_CLIENT_PROTOCOL_MISMATCH("ProtocolMismatch", realm_sync_errno_client.RLM_SYNC_ERR_CLIENT_PROTOCOL_MISMATCH), - RLM_SYNC_ERR_CLIENT_BAD_STATE_MESSAGE("BadStateMessage", realm_sync_errno_client.RLM_SYNC_ERR_CLIENT_BAD_STATE_MESSAGE), - RLM_SYNC_ERR_CLIENT_MISSING_PROTOCOL_FEATURE("MissingProtocolFeature", realm_sync_errno_client.RLM_SYNC_ERR_CLIENT_MISSING_PROTOCOL_FEATURE), - RLM_SYNC_ERR_CLIENT_HTTP_TUNNEL_FAILED("HttpTunnelFailed", realm_sync_errno_client.RLM_SYNC_ERR_CLIENT_HTTP_TUNNEL_FAILED), - RLM_SYNC_ERR_CLIENT_AUTO_CLIENT_RESET_FAILURE("AutoClientResetFailure", realm_sync_errno_client.RLM_SYNC_ERR_CLIENT_AUTO_CLIENT_RESET_FAILURE); - - override val nativeValue: Int = errorCode.value.toInt() - - actual companion object { - internal actual fun of(nativeValue: Int): ProtocolClientErrorCode? = - values().firstOrNull { value -> - value.nativeValue == nativeValue - } - } -} - -actual enum class ProtocolConnectionErrorCode( +actual enum class SyncConnectionErrorCode( override val description: String, errorCode: realm_sync_errno_connection ) : CodeDescription { @@ -89,14 +43,14 @@ actual enum class ProtocolConnectionErrorCode( override val nativeValue: Int = errorCode.value.toInt() actual companion object { - internal actual fun of(nativeValue: Int): ProtocolConnectionErrorCode? = + internal actual fun of(nativeValue: Int): SyncConnectionErrorCode? = values().firstOrNull { value -> value.nativeValue == nativeValue } } } -actual enum class ProtocolSessionErrorCode( +actual enum class SyncSessionErrorCode( override val description: String, errorCode: realm_sync_errno_session ) : CodeDescription { @@ -138,7 +92,47 @@ actual enum class ProtocolSessionErrorCode( override val nativeValue: Int = errorCode.value.toInt() actual companion object { - internal actual fun of(nativeValue: Int): ProtocolSessionErrorCode? = + internal actual fun of(nativeValue: Int): SyncSessionErrorCode? = + values().firstOrNull { value -> + value.nativeValue == nativeValue + } + } +} + +actual enum class WebsocketErrorCode( + override val description: String, + errorCode: realm_web_socket_errno, +) : CodeDescription { + RLM_ERR_WEBSOCKET_OK("Ok", realm_web_socket_errno.RLM_ERR_WEBSOCKET_OK), + RLM_ERR_WEBSOCKET_GOINGAWAY("GoingAway", realm_web_socket_errno.RLM_ERR_WEBSOCKET_GOINGAWAY), + RLM_ERR_WEBSOCKET_PROTOCOLERROR("ProtocolError", realm_web_socket_errno.RLM_ERR_WEBSOCKET_PROTOCOLERROR), + RLM_ERR_WEBSOCKET_UNSUPPORTEDDATA("UnsupportedData", realm_web_socket_errno.RLM_ERR_WEBSOCKET_UNSUPPORTEDDATA), + RLM_ERR_WEBSOCKET_RESERVED("Reserved", realm_web_socket_errno.RLM_ERR_WEBSOCKET_RESERVED), + RLM_ERR_WEBSOCKET_NOSTATUSRECEIVED("NoStatusReceived", realm_web_socket_errno.RLM_ERR_WEBSOCKET_NOSTATUSRECEIVED), + RLM_ERR_WEBSOCKET_ABNORMALCLOSURE("AbnormalClosure", realm_web_socket_errno.RLM_ERR_WEBSOCKET_ABNORMALCLOSURE), + RLM_ERR_WEBSOCKET_INVALIDPAYLOADDATA("InvalidPayloadData", realm_web_socket_errno.RLM_ERR_WEBSOCKET_INVALIDPAYLOADDATA), + RLM_ERR_WEBSOCKET_POLICYVIOLATION("PolicyViolation", realm_web_socket_errno.RLM_ERR_WEBSOCKET_POLICYVIOLATION), + RLM_ERR_WEBSOCKET_MESSAGETOOBIG("MessageToBig", realm_web_socket_errno.RLM_ERR_WEBSOCKET_MESSAGETOOBIG), + RLM_ERR_WEBSOCKET_INAVALIDEXTENSION("InvalidExtension", realm_web_socket_errno.RLM_ERR_WEBSOCKET_INAVALIDEXTENSION), + RLM_ERR_WEBSOCKET_INTERNALSERVERERROR("InternalServerError", realm_web_socket_errno.RLM_ERR_WEBSOCKET_INTERNALSERVERERROR), + RLM_ERR_WEBSOCKET_TLSHANDSHAKEFAILED("TlsHandshakeFailed", realm_web_socket_errno.RLM_ERR_WEBSOCKET_TLSHANDSHAKEFAILED), + RLM_ERR_WEBSOCKET_UNAUTHORIZED("Unauthorized", realm_web_socket_errno.RLM_ERR_WEBSOCKET_UNAUTHORIZED), + RLM_ERR_WEBSOCKET_FORBIDDEN("Forbidden", realm_web_socket_errno.RLM_ERR_WEBSOCKET_FORBIDDEN), + RLM_ERR_WEBSOCKET_MOVEDPERMANENTLY("MovedPermanently", realm_web_socket_errno.RLM_ERR_WEBSOCKET_MOVEDPERMANENTLY), + RLM_ERR_WEBSOCKET_CLIENT_TOO_OLD("ClientTooOld", realm_web_socket_errno.RLM_ERR_WEBSOCKET_CLIENT_TOO_OLD), + RLM_ERR_WEBSOCKET_CLIENT_TOO_NEW("ClientTooNew", realm_web_socket_errno.RLM_ERR_WEBSOCKET_CLIENT_TOO_NEW), + RLM_ERR_WEBSOCKET_PROTOCOL_MISMATCH("ProtocolMismatch", realm_web_socket_errno.RLM_ERR_WEBSOCKET_PROTOCOL_MISMATCH), + RLM_ERR_WEBSOCKET_RESOLVE_FAILED("ResolveFailed", realm_web_socket_errno.RLM_ERR_WEBSOCKET_RESOLVE_FAILED), + RLM_ERR_WEBSOCKET_CONNECTION_FAILED("ConnectionFailed", realm_web_socket_errno.RLM_ERR_WEBSOCKET_CONNECTION_FAILED), + RLM_ERR_WEBSOCKET_READ_ERROR("ReadError", realm_web_socket_errno.RLM_ERR_WEBSOCKET_READ_ERROR), + RLM_ERR_WEBSOCKET_WRITE_ERROR("WriteError", realm_web_socket_errno.RLM_ERR_WEBSOCKET_WRITE_ERROR), + RLM_ERR_WEBSOCKET_RETRY_ERROR("RetryError", realm_web_socket_errno.RLM_ERR_WEBSOCKET_RETRY_ERROR), + RLM_ERR_WEBSOCKET_FATAL_ERROR("FatalError", realm_web_socket_errno.RLM_ERR_WEBSOCKET_FATAL_ERROR); + + override val nativeValue: Int = errorCode.value.toInt() + + actual companion object { + internal actual fun of(nativeValue: Int): WebsocketErrorCode? = values().firstOrNull { value -> value.nativeValue == nativeValue } diff --git a/packages/cinterop/src/nativeDarwin/kotlin/io/realm/kotlin/internal/interop/sync/SyncErrorCodeCategory.kt b/packages/cinterop/src/nativeDarwin/kotlin/io/realm/kotlin/internal/interop/sync/SyncErrorCodeCategory.kt deleted file mode 100644 index 80254655ff..0000000000 --- a/packages/cinterop/src/nativeDarwin/kotlin/io/realm/kotlin/internal/interop/sync/SyncErrorCodeCategory.kt +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright 2022 Realm 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 io.realm.kotlin.internal.interop.sync - -import io.realm.kotlin.internal.interop.CodeDescription -import realm_wrapper.realm_sync_error_category - -actual enum class SyncErrorCodeCategory( - override val description: String, - override val nativeValue: Int -) : CodeDescription { - RLM_SYNC_ERROR_CATEGORY_CLIENT("Client", realm_sync_error_category.RLM_SYNC_ERROR_CATEGORY_CLIENT.value.toInt()), - RLM_SYNC_ERROR_CATEGORY_CONNECTION("Connection", realm_sync_error_category.RLM_SYNC_ERROR_CATEGORY_CONNECTION.value.toInt()), - RLM_SYNC_ERROR_CATEGORY_SESSION("Session", realm_sync_error_category.RLM_SYNC_ERROR_CATEGORY_SESSION.value.toInt()), - RLM_SYNC_ERROR_CATEGORY_WEBSOCKET("Websocket", realm_sync_error_category.RLM_SYNC_ERROR_CATEGORY_WEBSOCKET.value.toInt()), - RLM_SYNC_ERROR_CATEGORY_SYSTEM("System", realm_sync_error_category.RLM_SYNC_ERROR_CATEGORY_SYSTEM.value.toInt()), - RLM_SYNC_ERROR_CATEGORY_UNKNOWN("Unknown", realm_sync_error_category.RLM_SYNC_ERROR_CATEGORY_UNKNOWN.value.toInt()); - - actual companion object { - - internal actual fun of(nativeValue: Int): SyncErrorCodeCategory? = - values().firstOrNull { value -> - value.nativeValue == nativeValue - } - } -} diff --git a/packages/external/core b/packages/external/core index f1e962cd44..ea7c5d5e29 160000 --- a/packages/external/core +++ b/packages/external/core @@ -1 +1 @@ -Subproject commit f1e962cd447f8b69f8f7cf46a188b1c6246923c5 +Subproject commit ea7c5d5e2900b8411a295aea3d1aa56aa55fff1d diff --git a/packages/jni-swig-stub/src/main/jni/realm_api_helpers.cpp b/packages/jni-swig-stub/src/main/jni/realm_api_helpers.cpp index 9848fc99c4..bc8a0ed658 100644 --- a/packages/jni-swig-stub/src/main/jni/realm_api_helpers.cpp +++ b/packages/jni-swig-stub/src/main/jni/realm_api_helpers.cpp @@ -714,12 +714,11 @@ jobject convert_to_jvm_sync_error(JNIEnv* jenv, const realm_sync_error_t& error) static JavaMethod sync_error_constructor(jenv, JavaClassGlobalDef::sync_error(), "", - "(IILjava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ZZZ[Lio/realm/kotlin/internal/interop/sync/CoreCompensatingWriteInfo;)V"); + "(IILjava/lang/String;Ljava/lang/String;Ljava/lang/String;ZZZ[Lio/realm/kotlin/internal/interop/sync/CoreCompensatingWriteInfo;)V"); - jint category = static_cast(error.error_code.category); - jint value = error.error_code.value; - jstring msg = to_jstring(jenv, error.error_code.message); - jstring detailed_msg = to_jstring(jenv, error.detailed_message); + jint category = static_cast(error.status.categories); + jint value = static_cast(error.status.error); + jstring msg = to_jstring(jenv, error.status.message); jstring joriginal_file_path = nullptr; jstring jrecovery_file_path = nullptr; jboolean is_fatal = error.is_fatal; @@ -793,7 +792,6 @@ jobject convert_to_jvm_sync_error(JNIEnv* jenv, const realm_sync_error_t& error) category, value, msg, - detailed_msg, joriginal_file_path, jrecovery_file_path, is_fatal, @@ -827,7 +825,7 @@ void sync_set_error_handler(realm_sync_config_t* sync_config, jobject error_hand }); } -void transfer_completion_callback(void* userdata, realm_sync_error_code_t* error) { +void transfer_completion_callback(void* userdata, realm_error_t* error) { auto env = get_env(true); static JavaMethod java_success_callback_method(env, JavaClassGlobalDef::sync_session_transfer_completion_callback(), @@ -838,8 +836,8 @@ void transfer_completion_callback(void* userdata, realm_sync_error_code_t* error "onError", "(IILjava/lang/String;)V"); if (error) { - jint category = static_cast(error->category); - jint value = error->value; + jint category = static_cast(error->categories); + jint value = error->error; jstring msg = to_jstring(env, error->message); env->CallVoidMethod(static_cast(userdata), java_error_callback_method, category, value, msg); } else { diff --git a/packages/jni-swig-stub/src/main/jni/realm_api_helpers.h b/packages/jni-swig-stub/src/main/jni/realm_api_helpers.h index 0854631d72..133b0095ee 100644 --- a/packages/jni-swig-stub/src/main/jni/realm_api_helpers.h +++ b/packages/jni-swig-stub/src/main/jni/realm_api_helpers.h @@ -72,7 +72,7 @@ void complete_http_request(void* request_context, jobject j_response); void -transfer_completion_callback(void* userdata, realm_sync_error_code_t* error); +transfer_completion_callback(void* userdata, realm_error_t* error); void realm_subscriptionset_changed_callback(void* userdata, diff --git a/packages/library-sync/src/commonMain/kotlin/io/realm/kotlin/mongodb/internal/AppConfigurationImpl.kt b/packages/library-sync/src/commonMain/kotlin/io/realm/kotlin/mongodb/internal/AppConfigurationImpl.kt index 98f9edb155..cb8fa12c7a 100644 --- a/packages/library-sync/src/commonMain/kotlin/io/realm/kotlin/mongodb/internal/AppConfigurationImpl.kt +++ b/packages/library-sync/src/commonMain/kotlin/io/realm/kotlin/mongodb/internal/AppConfigurationImpl.kt @@ -73,7 +73,7 @@ public class AppConfigurationImpl @OptIn(ExperimentalKBsonSerializerApi::class) val appDispatcher = appNetworkDispatcherFactory.create() val networkTransport = networkTransportFactory(appDispatcher) val appConfigPointer: RealmAppConfigurationPointer = - initializeRealmAppConfig(appName, appVersion, bundleId, networkTransport) + initializeRealmAppConfig(bundleId, networkTransport) var applicationInfo: String? = null // Define user agent strings sent when making the WebSocket connection to Device Sync if (appName != null || appVersion == null) { @@ -121,8 +121,6 @@ public class AppConfigurationImpl @OptIn(ExperimentalKBsonSerializerApi::class) // Only freeze anything after all properties are setup as this triggers freezing the actual // AppConfigurationImpl instance itself private fun initializeRealmAppConfig( - localAppName: String?, - localAppVersion: String?, bundleId: String, networkTransport: NetworkTransport ): RealmAppConfigurationPointer { @@ -133,8 +131,6 @@ public class AppConfigurationImpl @OptIn(ExperimentalKBsonSerializerApi::class) connectionParams = SyncConnectionParams( sdkVersion = SDK_VERSION, bundleId = bundleId, - localAppName = localAppName, - localAppVersion = localAppVersion, platformVersion = OS_VERSION, device = DEVICE_MANUFACTURER, deviceVersion = DEVICE_MODEL, diff --git a/packages/library-sync/src/commonMain/kotlin/io/realm/kotlin/mongodb/internal/RealmSyncUtils.kt b/packages/library-sync/src/commonMain/kotlin/io/realm/kotlin/mongodb/internal/RealmSyncUtils.kt index e5c3d424bb..fb72304c78 100644 --- a/packages/library-sync/src/commonMain/kotlin/io/realm/kotlin/mongodb/internal/RealmSyncUtils.kt +++ b/packages/library-sync/src/commonMain/kotlin/io/realm/kotlin/mongodb/internal/RealmSyncUtils.kt @@ -1,14 +1,11 @@ package io.realm.kotlin.mongodb.internal import io.realm.kotlin.internal.interop.AppCallback +import io.realm.kotlin.internal.interop.CoreError import io.realm.kotlin.internal.interop.ErrorCategory import io.realm.kotlin.internal.interop.ErrorCode import io.realm.kotlin.internal.interop.sync.AppError -import io.realm.kotlin.internal.interop.sync.ProtocolConnectionErrorCode -import io.realm.kotlin.internal.interop.sync.ProtocolSessionErrorCode import io.realm.kotlin.internal.interop.sync.SyncError -import io.realm.kotlin.internal.interop.sync.SyncErrorCode -import io.realm.kotlin.internal.interop.sync.SyncErrorCodeCategory import io.realm.kotlin.mongodb.exceptions.AppException import io.realm.kotlin.mongodb.exceptions.AuthException import io.realm.kotlin.mongodb.exceptions.BadFlexibleSyncQueryException @@ -80,64 +77,26 @@ internal fun channelResultCallback( internal fun convertSyncError(syncError: SyncError): SyncException { val errorCode = syncError.errorCode - // FIXME Client Reset errors are just reported as normal Sync Errors for now. - // Will be fixed by https://github.com/realm/realm-kotlin/issues/417 val message = createMessageFromSyncError(errorCode) - return when (errorCode.category) { - SyncErrorCodeCategory.RLM_SYNC_ERROR_CATEGORY_CLIENT -> { - // See https://github.com/realm/realm-core/blob/master/src/realm/sync/client_base.hpp#L73 - // For now, it is unclear how to categorize these, so for now, just report as generic - // errors. - SyncException(message) - } - SyncErrorCodeCategory.RLM_SYNC_ERROR_CATEGORY_CONNECTION -> { - // See https://github.com/realm/realm-core/blob/master/src/realm/sync/protocol.hpp#L200 - // Use https://docs.google.com/spreadsheets/d/1SmiRxhFpD1XojqCKC-xAjjV-LKa9azeeWHg-zgr07lE/edit - // as guide for how to categorize Connection type errors. - when (errorCode.code) { - ProtocolConnectionErrorCode.RLM_SYNC_ERR_CONNECTION_UNKNOWN_MESSAGE, // Unknown type of input message - ProtocolConnectionErrorCode.RLM_SYNC_ERR_CONNECTION_BAD_SYNTAX, // Bad syntax in input message head - ProtocolConnectionErrorCode.RLM_SYNC_ERR_CONNECTION_WRONG_PROTOCOL_VERSION, // Wrong protocol version (CLIENT) (obsolete) - ProtocolConnectionErrorCode.RLM_SYNC_ERR_CONNECTION_BAD_SESSION_IDENT, // Bad session identifier in input message - ProtocolConnectionErrorCode.RLM_SYNC_ERR_CONNECTION_REUSE_OF_SESSION_IDENT, // Overlapping reuse of session identifier (BIND) - ProtocolConnectionErrorCode.RLM_SYNC_ERR_CONNECTION_BOUND_IN_OTHER_SESSION, // Client file bound in other session (IDENT) - ProtocolConnectionErrorCode.RLM_SYNC_ERR_CONNECTION_BAD_MESSAGE_ORDER, // Bad input message order - ProtocolConnectionErrorCode.RLM_SYNC_ERR_CONNECTION_BAD_DECOMPRESSION, // Error in decompression (UPLOAD) - ProtocolConnectionErrorCode.RLM_SYNC_ERR_CONNECTION_BAD_CHANGESET_HEADER_SYNTAX, // Bad syntax in a changeset header (UPLOAD) - ProtocolConnectionErrorCode.RLM_SYNC_ERR_CONNECTION_BAD_CHANGESET_SIZE -> { // Bad size specified in changeset header (UPLOAD) - UnrecoverableSyncException(message) - } - ProtocolConnectionErrorCode.RLM_SYNC_ERR_CONNECTION_SWITCH_TO_FLX_SYNC, // Connected with wrong wire protocol - should switch to FLX sync - ProtocolConnectionErrorCode.RLM_SYNC_ERR_CONNECTION_SWITCH_TO_PBS -> { // Connected with wrong wire protocol - should switch to PBS - WrongSyncTypeException(message) - } - else -> SyncException(message) - } - } - SyncErrorCodeCategory.RLM_SYNC_ERROR_CATEGORY_SESSION -> { - // See https://github.com/realm/realm-core/blob/master/src/realm/sync/protocol.hpp#L217 - // Use https://docs.google.com/spreadsheets/d/1SmiRxhFpD1XojqCKC-xAjjV-LKa9azeeWHg-zgr07lE/edit - // as guide for how to categorize Session type errors. - when (errorCode.code) { - ProtocolSessionErrorCode.RLM_SYNC_ERR_SESSION_BAD_QUERY -> { // Flexible Sync Query was rejected by the server - BadFlexibleSyncQueryException(message) - } - ProtocolSessionErrorCode.RLM_SYNC_ERR_SESSION_PERMISSION_DENIED -> - // Permission denied errors should be unrecoverable according to Core, i.e. the - // client will disconnect sync and transition to the "inactive" state - UnrecoverableSyncException(message) - ProtocolSessionErrorCode.RLM_SYNC_ERR_SESSION_COMPENSATING_WRITE -> - CompensatingWriteException(message, syncError.compensatingWrites) - else -> SyncException(message) - } + return when (errorCode.errorCode) { + ErrorCode.RLM_ERR_WRONG_SYNC_TYPE -> WrongSyncTypeException(message) + + ErrorCode.RLM_ERR_INVALID_SUBSCRIPTION_QUERY -> { + // Flexible Sync Query was rejected by the server + BadFlexibleSyncQueryException(message) } - SyncErrorCodeCategory.RLM_SYNC_ERROR_CATEGORY_SYSTEM, - SyncErrorCodeCategory.RLM_SYNC_ERROR_CATEGORY_UNKNOWN -> { - // It is unclear how to handle system level errors, so even though some of them - // are probably benign, report as top-level errors for now. - SyncException(message) + ErrorCode.RLM_ERR_SYNC_COMPENSATING_WRITE -> CompensatingWriteException(message, syncError.compensatingWrites) + + ErrorCode.RLM_ERR_SYNC_PROTOCOL_INVARIANT_FAILED, + ErrorCode.RLM_ERR_SYNC_PROTOCOL_NEGOTIATION_FAILED, + ErrorCode.RLM_ERR_SYNC_PERMISSION_DENIED -> { + // Permission denied errors should be unrecoverable according to Core, i.e. the + // client will disconnect sync and transition to the "inactive" state + UnrecoverableSyncException(message) } else -> { + // An error happened we are not sure how to handle. Just report as a generic + // SyncException. SyncException(message) } } @@ -277,30 +236,27 @@ internal fun convertAppError(appError: AppError): Throwable { } } -internal fun createMessageFromSyncError(error: SyncErrorCode): String { - val categoryDesc = error.category.description ?: error.category.nativeValue.toString() - val errorCodeDesc: String? = error.code.description ?: when (error.category) { - SyncErrorCodeCategory.RLM_SYNC_ERROR_CATEGORY_SYSTEM, - SyncErrorCodeCategory.RLM_SYNC_ERROR_CATEGORY_UNKNOWN, - -> { - // We lack information about these kinds of errors, - // so rather than returning a potentially misleading - // name, just return nothing. - null - } - else -> "Unknown" +internal fun createMessageFromSyncError(error: CoreError): String { + val categoryDesc = error.categories.description + val errorCodeDesc: String? = error.errorCode?.description ?: if (ErrorCategory.RLM_ERR_CAT_SYSTEM_ERROR in error.categories) { + // We lack information about these kinds of errors, + // so rather than returning a potentially misleading + // name, just return nothing. + null + } else { + "Unknown" } // Combine all the parts to form an error format that is human-readable. // An example could be this: `[Connection][WrongProtocolVersion(104)] Wrong protocol version was used: 25` val errorDesc: String = - if (errorCodeDesc == null) error.code.nativeValue.toString() else "$errorCodeDesc(${error.code.nativeValue})" + if (errorCodeDesc == null) error.errorCodeNativeValue.toString() else "$errorCodeDesc(${error.errorCodeNativeValue})" // Make sure that messages are uniformly formatted, so it looks nice if we append the // server log. - val msg = error.message.let { message: String -> + val msg = error.message?.let { message: String -> " $message${if (!message.endsWith(".")) "." else ""}" - } + } ?: "" return "[$categoryDesc][$errorDesc]$msg" } diff --git a/packages/library-sync/src/commonMain/kotlin/io/realm/kotlin/mongodb/internal/SyncSessionImpl.kt b/packages/library-sync/src/commonMain/kotlin/io/realm/kotlin/mongodb/internal/SyncSessionImpl.kt index 8409b7c556..720d2e4de2 100644 --- a/packages/library-sync/src/commonMain/kotlin/io/realm/kotlin/mongodb/internal/SyncSessionImpl.kt +++ b/packages/library-sync/src/commonMain/kotlin/io/realm/kotlin/mongodb/internal/SyncSessionImpl.kt @@ -19,16 +19,15 @@ package io.realm.kotlin.mongodb.internal import io.realm.kotlin.internal.InternalConfiguration import io.realm.kotlin.internal.NotificationToken import io.realm.kotlin.internal.RealmImpl +import io.realm.kotlin.internal.interop.CoreError +import io.realm.kotlin.internal.interop.ErrorCode import io.realm.kotlin.internal.interop.RealmInterop import io.realm.kotlin.internal.interop.RealmSyncSessionPointer import io.realm.kotlin.internal.interop.SyncSessionTransferCompletionCallback import io.realm.kotlin.internal.interop.sync.CoreConnectionState import io.realm.kotlin.internal.interop.sync.CoreSyncSessionState import io.realm.kotlin.internal.interop.sync.ProgressDirection -import io.realm.kotlin.internal.interop.sync.ProtocolClientErrorCode import io.realm.kotlin.internal.interop.sync.SyncError -import io.realm.kotlin.internal.interop.sync.SyncErrorCode -import io.realm.kotlin.internal.interop.sync.SyncErrorCodeCategory import io.realm.kotlin.internal.util.Validation import io.realm.kotlin.internal.util.trySendWithBufferOverflowCheck import io.realm.kotlin.mongodb.User @@ -165,15 +164,13 @@ internal open class SyncSessionImpl( /** * Simulates a sync error. Internal visibility only for testing. */ - internal fun simulateError( - errorCode: ProtocolClientErrorCode, - category: SyncErrorCodeCategory, + internal fun simulateSyncError( + error: ErrorCode, message: String = "Simulate Client Reset" ) { RealmInterop.realm_sync_session_handle_error_for_testing( nativePointer, - errorCode, - category, + error, message, true ) @@ -201,7 +198,7 @@ internal open class SyncSessionImpl( val result: Any = withTimeout(timeout) { withContext(realm.notificationDispatcherHolder.dispatcher) { val callback = object : SyncSessionTransferCompletionCallback { - override fun invoke(errorCode: SyncErrorCode?) { + override fun invoke(errorCode: CoreError?) { if (errorCode != null) { // Transform the errorCode into a dummy syncError so we can have a // common path. diff --git a/packages/test-base/src/commonTest/kotlin/io/realm/kotlin/test/common/QueryTests.kt b/packages/test-base/src/commonTest/kotlin/io/realm/kotlin/test/common/QueryTests.kt index 23745dbffc..3f7267c8a0 100644 --- a/packages/test-base/src/commonTest/kotlin/io/realm/kotlin/test/common/QueryTests.kt +++ b/packages/test-base/src/commonTest/kotlin/io/realm/kotlin/test/common/QueryTests.kt @@ -2361,7 +2361,7 @@ class QueryTests { assertEquals(1, realm.query("fulltextField TEXT 'quick dog'").find().size) // words at different locations assertEquals(0, realm.query("fulltextField TEXT 'brown -fox'").find().size) // exclusion - assertEquals(0, realm.query("fulltextField TEXT 'fo*'").find().size) // token prefix search does not work + assertEquals(2, realm.query("fulltextField TEXT 'fo*'").find().size) // token prefix search is supported. assertEquals(1, realm.query("fulltextField TEXT 'cafe big'").find().size) // case- and diacritics-insensitive assertEquals(1, realm.query("fulltextField TEXT 'rødgrød'").find().size) // Latin-1 supplement assertEquals(0, realm.query("fulltextField TEXT '😊'").find().size) // Searching outside supported chars return nothing diff --git a/packages/test-sync/src/commonTest/kotlin/io/realm/kotlin/test/mongodb/common/FlexibleSyncIntegrationTests.kt b/packages/test-sync/src/commonTest/kotlin/io/realm/kotlin/test/mongodb/common/FlexibleSyncIntegrationTests.kt index 661a2538fb..1922c55e7a 100644 --- a/packages/test-sync/src/commonTest/kotlin/io/realm/kotlin/test/mongodb/common/FlexibleSyncIntegrationTests.kt +++ b/packages/test-sync/src/commonTest/kotlin/io/realm/kotlin/test/mongodb/common/FlexibleSyncIntegrationTests.kt @@ -22,6 +22,7 @@ import io.realm.kotlin.entities.sync.flx.FlexEmbeddedObject import io.realm.kotlin.entities.sync.flx.FlexParentObject import io.realm.kotlin.ext.query import io.realm.kotlin.internal.platform.runBlocking +import io.realm.kotlin.log.LogLevel import io.realm.kotlin.mongodb.exceptions.CompensatingWriteException import io.realm.kotlin.mongodb.exceptions.DownloadingRealmTimeOutException import io.realm.kotlin.mongodb.exceptions.SyncException @@ -63,7 +64,7 @@ class FlexibleSyncIntegrationTests { @BeforeTest fun setup() { - app = TestApp(appName = TEST_APP_FLEX) + app = TestApp(appName = TEST_APP_FLEX, logLevel = LogLevel.ALL) val (email, password) = TestHelper.randomEmail() to "password1234" runBlocking { app.createUserAndLogIn(email, password) @@ -332,7 +333,7 @@ class FlexibleSyncIntegrationTests { val exception: CompensatingWriteException = channel.receiveOrFail() - assertEquals("[Session][CompensatingWrite(231)] Client attempted a write that is disallowed by permissions, or modifies an object outside the current query, and the server undid the change.", exception.message) + assertTrue(exception.message!!.startsWith("[Sync][CompensatingWrite(1033)] Client attempted a write that is outside of permissions or query filters; it has been reverted Logs:"), exception.message) assertEquals(1, exception.writes.size) exception.writes[0].run { diff --git a/packages/test-sync/src/commonTest/kotlin/io/realm/kotlin/test/mongodb/common/SyncClientResetIntegrationTests.kt b/packages/test-sync/src/commonTest/kotlin/io/realm/kotlin/test/mongodb/common/SyncClientResetIntegrationTests.kt index 6dbadc3571..d1e362e6f0 100644 --- a/packages/test-sync/src/commonTest/kotlin/io/realm/kotlin/test/mongodb/common/SyncClientResetIntegrationTests.kt +++ b/packages/test-sync/src/commonTest/kotlin/io/realm/kotlin/test/mongodb/common/SyncClientResetIntegrationTests.kt @@ -25,8 +25,7 @@ import io.realm.kotlin.entities.sync.flx.FlexChildObject import io.realm.kotlin.entities.sync.flx.FlexEmbeddedObject import io.realm.kotlin.entities.sync.flx.FlexParentObject import io.realm.kotlin.ext.query -import io.realm.kotlin.internal.interop.sync.ProtocolClientErrorCode -import io.realm.kotlin.internal.interop.sync.SyncErrorCodeCategory +import io.realm.kotlin.internal.interop.ErrorCode import io.realm.kotlin.internal.platform.fileExists import io.realm.kotlin.internal.platform.runBlocking import io.realm.kotlin.log.LogLevel @@ -596,7 +595,7 @@ class SyncClientResetIntegrationTests { // testing the server will send a different message. This just ensures that // we don't accidentally modify or remove the message. assertEquals( - "[Client][AutoClientResetFailure(132)] Automatic recovery from client reset failed.", + "[Sync][AutoClientResetFailed(1028)] Simulate Client Reset.", exception.message ) @@ -609,10 +608,7 @@ class SyncClientResetIntegrationTests { realm.syncSession.downloadAllServerChanges(defaultTimeout) with(realm.syncSession as SyncSessionImpl) { - simulateError( - ProtocolClientErrorCode.RLM_SYNC_ERR_CLIENT_AUTO_CLIENT_RESET_FAILURE, - SyncErrorCodeCategory.RLM_SYNC_ERROR_CATEGORY_CLIENT - ) + simulateSyncError(ErrorCode.RLM_ERR_AUTO_CLIENT_RESET_FAILED) // TODO Twice until the deprecated method is removed assertEquals(ClientResetEvents.ON_MANUAL_RESET_FALLBACK, channel.receiveOrFail()) @@ -682,10 +678,7 @@ class SyncClientResetIntegrationTests { realm.syncSession.downloadAllServerChanges(defaultTimeout) with(realm.syncSession as SyncSessionImpl) { - simulateError( - ProtocolClientErrorCode.RLM_SYNC_ERR_CLIENT_AUTO_CLIENT_RESET_FAILURE, - SyncErrorCodeCategory.RLM_SYNC_ERROR_CATEGORY_CLIENT - ) + simulateSyncError(ErrorCode.RLM_ERR_AUTO_CLIENT_RESET_FAILED) // TODO Twice until the deprecated method is removed assertEquals(ClientResetEvents.ON_MANUAL_RESET_FALLBACK, channel.receiveOrFail()) @@ -735,7 +728,7 @@ class SyncClientResetIntegrationTests { ) { // Notify that this callback has been invoked assertEquals( - "[Client][AutoClientResetFailure(132)] Automatic recovery from client reset failed.", + "[Sync][AutoClientResetFailed(1028)] A fatal error occurred during client reset: 'User-provided callback failed'.", exception.message ) channel.trySend(ClientResetEvents.ON_MANUAL_RESET_FALLBACK) @@ -747,7 +740,7 @@ class SyncClientResetIntegrationTests { ) { // Notify that this callback has been invoked assertEquals( - "[Client][AutoClientResetFailure(132)] Automatic recovery from client reset failed.", + "[Sync][AutoClientResetFailed(1028)] A fatal error occurred during client reset: 'User-provided callback failed'.", exception.message ) channel.trySend(ClientResetEvents.ON_MANUAL_RESET_FALLBACK) @@ -819,7 +812,7 @@ class SyncClientResetIntegrationTests { ) { // Notify that this callback has been invoked assertEquals( - "[Client][AutoClientResetFailure(132)] Automatic recovery from client reset failed.", + "[Sync][AutoClientResetFailed(1028)] A fatal error occurred during client reset: 'User-provided callback failed'.", exception.message ) channel.trySend(ClientResetEvents.ON_MANUAL_RESET_FALLBACK) @@ -831,7 +824,7 @@ class SyncClientResetIntegrationTests { ) { // Notify that this callback has been invoked assertEquals( - "[Client][AutoClientResetFailure(132)] Automatic recovery from client reset failed.", + "[Sync][AutoClientResetFailed(1028)] A fatal error occurred during client reset: 'User-provided callback failed'.", exception.message ) channel.trySend(ClientResetEvents.ON_MANUAL_RESET_FALLBACK) @@ -898,9 +891,8 @@ class SyncClientResetIntegrationTests { ) // assertEquals(ClientResetLogEvents.DISCARD_LOCAL_ON_AFTER_RESET, logChannel.receiveOrFail()) - (realm.syncSession as SyncSessionImpl).simulateError( - ProtocolClientErrorCode.RLM_SYNC_ERR_CLIENT_AUTO_CLIENT_RESET_FAILURE, - SyncErrorCodeCategory.RLM_SYNC_ERROR_CATEGORY_CLIENT + (realm.syncSession as SyncSessionImpl).simulateSyncError( + ErrorCode.RLM_ERR_AUTO_CLIENT_RESET_FAILED ) // Validate that we receive logs on the error callback val actual = logChannel.receiveOrFail() @@ -948,10 +940,7 @@ class SyncClientResetIntegrationTests { realm.syncSession.downloadAllServerChanges(defaultTimeout) with((realm.syncSession as SyncSessionImpl)) { - simulateError( - ProtocolClientErrorCode.RLM_SYNC_ERR_CLIENT_AUTO_CLIENT_RESET_FAILURE, - SyncErrorCodeCategory.RLM_SYNC_ERROR_CATEGORY_CLIENT - ) + simulateSyncError(ErrorCode.RLM_ERR_AUTO_CLIENT_RESET_FAILED) val exception = channel.receiveOrFail() val originalFilePath = assertNotNull(exception.originalFilePath) @@ -959,7 +948,7 @@ class SyncClientResetIntegrationTests { assertTrue(fileExists(originalFilePath)) assertFalse(fileExists(recoveryFilePath)) assertEquals( - "[Client][AutoClientResetFailure(132)] Automatic recovery from client reset failed.", + "[Sync][AutoClientResetFailed(1028)] Simulate Client Reset.", exception.message ) } @@ -1002,10 +991,7 @@ class SyncClientResetIntegrationTests { realm.syncSession.downloadAllServerChanges(defaultTimeout) with(realm.syncSession as SyncSessionImpl) { - simulateError( - ProtocolClientErrorCode.RLM_SYNC_ERR_CLIENT_AUTO_CLIENT_RESET_FAILURE, - SyncErrorCodeCategory.RLM_SYNC_ERROR_CATEGORY_CLIENT - ) + simulateSyncError(ErrorCode.RLM_ERR_AUTO_CLIENT_RESET_FAILED) val exception = channel.receiveOrFail() @@ -1121,17 +1107,14 @@ class SyncClientResetIntegrationTests { runBlocking { realm.syncSession.downloadAllServerChanges(defaultTimeout) - (realm.syncSession as SyncSessionImpl).simulateError( - ProtocolClientErrorCode.RLM_SYNC_ERR_CLIENT_AUTO_CLIENT_RESET_FAILURE, - SyncErrorCodeCategory.RLM_SYNC_ERROR_CATEGORY_CLIENT - ) + (realm.syncSession as SyncSessionImpl).simulateSyncError(ErrorCode.RLM_ERR_AUTO_CLIENT_RESET_FAILED) val exception = channel.receiveOrFail() assertNotNull(exception.recoveryFilePath) assertNotNull(exception.originalFilePath) assertFalse(fileExists(exception.recoveryFilePath)) assertTrue(fileExists(exception.originalFilePath)) - assertTrue(exception.message!!.contains("Automatic recovery from client reset failed")) + assertTrue(exception.message!!.contains("Simulate Client Reset")) } } } @@ -1174,7 +1157,7 @@ class SyncClientResetIntegrationTests { ) { // Notify that this callback has been invoked assertEquals( - "[Client][AutoClientResetFailure(132)] Automatic recovery from client reset failed.", + "[Sync][AutoClientResetFailed(1028)] A fatal error occurred during client reset: 'User-provided callback failed'.", exception.message ) channel.trySend(ClientResetEvents.ON_MANUAL_RESET_FALLBACK) @@ -1235,7 +1218,7 @@ class SyncClientResetIntegrationTests { assertTrue(fileExists(recoveryFilePath)) assertEquals( - "[Client][AutoClientResetFailure(132)] Automatic recovery from client reset failed.", + "[Sync][AutoClientResetFailed(1028)] Simulate Client Reset.", exception.message ) @@ -1248,10 +1231,7 @@ class SyncClientResetIntegrationTests { realm.syncSession.downloadAllServerChanges(defaultTimeout) with(realm.syncSession as SyncSessionImpl) { - simulateError( - ProtocolClientErrorCode.RLM_SYNC_ERR_CLIENT_AUTO_CLIENT_RESET_FAILURE, - SyncErrorCodeCategory.RLM_SYNC_ERROR_CATEGORY_CLIENT - ) + simulateSyncError(ErrorCode.RLM_ERR_AUTO_CLIENT_RESET_FAILED) // TODO Twice until the deprecated method is removed assertEquals(ClientResetEvents.ON_MANUAL_RESET_FALLBACK, channel.receiveOrFail()) @@ -1436,7 +1416,7 @@ class SyncClientResetIntegrationTests { assertTrue(fileExists(recoveryFilePath)) assertEquals( - "[Client][AutoClientResetFailure(132)] Automatic recovery from client reset failed.", + "[Sync][AutoClientResetFailed(1028)] Simulate Client Reset.", exception.message ) @@ -1449,10 +1429,7 @@ class SyncClientResetIntegrationTests { realm.syncSession.downloadAllServerChanges(defaultTimeout) with(realm.syncSession as SyncSessionImpl) { - simulateError( - ProtocolClientErrorCode.RLM_SYNC_ERR_CLIENT_AUTO_CLIENT_RESET_FAILURE, - SyncErrorCodeCategory.RLM_SYNC_ERROR_CATEGORY_CLIENT - ) + simulateSyncError(ErrorCode.RLM_ERR_AUTO_CLIENT_RESET_FAILED) // TODO Twice until the deprecated method is removed assertEquals(ClientResetEvents.ON_MANUAL_RESET_FALLBACK, channel.receiveOrFail()) diff --git a/packages/test-sync/src/commonTest/kotlin/io/realm/kotlin/test/mongodb/common/SyncedRealmTests.kt b/packages/test-sync/src/commonTest/kotlin/io/realm/kotlin/test/mongodb/common/SyncedRealmTests.kt index 38e0fa85b4..8ddaa64cb7 100644 --- a/packages/test-sync/src/commonTest/kotlin/io/realm/kotlin/test/mongodb/common/SyncedRealmTests.kt +++ b/packages/test-sync/src/commonTest/kotlin/io/realm/kotlin/test/mongodb/common/SyncedRealmTests.kt @@ -386,15 +386,9 @@ class SyncedRealmTests { exception.message.let { errorMessage -> assertNotNull(errorMessage) // Some race on JVM in particular mean that different errors can be reported. - if (errorMessage.contains("[Client]")) { - assertTrue(errorMessage.contains("[BadChangeset(112)]"), errorMessage) - assertTrue(errorMessage.contains("Bad changeset (DOWNLOAD)"), errorMessage) - } else if (errorMessage.contains("[Session]")) { - assertTrue(errorMessage.contains("InvalidSchemaChange(225)"), errorMessage) - assertTrue( - errorMessage.contains("Invalid schema change (UPLOAD)"), - errorMessage - ) + if (errorMessage.contains("[Sync]")) { + assertTrue(errorMessage.contains("[BadChangeset(1015)]"), errorMessage) + assertTrue(errorMessage.contains("Schema mismatch"), errorMessage) } else { fail("Unexpected error message: $errorMessage") } diff --git a/packages/test-sync/src/commonTest/kotlin/io/realm/kotlin/test/mongodb/common/internal/RealmSyncUtilsTest.kt b/packages/test-sync/src/commonTest/kotlin/io/realm/kotlin/test/mongodb/common/internal/RealmSyncUtilsTest.kt index 9cf0bd49fd..6c6f5a1fc0 100644 --- a/packages/test-sync/src/commonTest/kotlin/io/realm/kotlin/test/mongodb/common/internal/RealmSyncUtilsTest.kt +++ b/packages/test-sync/src/commonTest/kotlin/io/realm/kotlin/test/mongodb/common/internal/RealmSyncUtilsTest.kt @@ -18,67 +18,74 @@ package io.realm.kotlin.test.mongodb.common.internal +import io.realm.kotlin.internal.interop.CoreError import io.realm.kotlin.internal.interop.ErrorCategory +import io.realm.kotlin.internal.interop.ErrorCode import io.realm.kotlin.internal.interop.UnknownCodeDescription import io.realm.kotlin.internal.interop.sync.AppError import io.realm.kotlin.internal.interop.sync.SyncError -import io.realm.kotlin.internal.interop.sync.SyncErrorCode -import io.realm.kotlin.internal.interop.sync.SyncErrorCodeCategory import io.realm.kotlin.mongodb.internal.convertAppError import io.realm.kotlin.mongodb.internal.convertSyncError import kotlin.test.Test import kotlin.test.assertEquals -const val UNMAPPED_CODE: Int = 0 +const val UNMAPPED_CATEGORY_CODE: Int = 0 +const val UNMAPPED_ERROR_CODE: Int = -1 class RealmSyncUtilsTest { + @Test - fun convertSyncErrorCode_unmappedErrorCode_categoryTypeUnknown() { + fun convertSyncErrorCode_unmappedErrorCode2() { val syncException = convertSyncError( SyncError( - SyncErrorCode( - category = SyncErrorCodeCategory.RLM_SYNC_ERROR_CATEGORY_UNKNOWN, - code = UnknownCodeDescription(UNMAPPED_CODE), - message = "Placeholder message" + CoreError( + categoriesNativeValue = ErrorCategory.RLM_ERR_CAT_CLIENT_ERROR.nativeValue, + errorCodeNativeValue = UNMAPPED_ERROR_CODE, + messageNativeValue = "Placeholder message" ) ) ) - assertEquals("[Unknown][$UNMAPPED_CODE] Placeholder message.", syncException.message) + assertEquals( + "[Client][Unknown($UNMAPPED_ERROR_CODE)] Placeholder message.", + syncException.message + ) } @Test - fun convertSyncErrorCode_unmappedErrorCode2() { + fun convertSyncErrorCode_unmappedErrorCategory() { val syncException = convertSyncError( SyncError( - SyncErrorCode( - category = SyncErrorCodeCategory.RLM_SYNC_ERROR_CATEGORY_CONNECTION, - code = UnknownCodeDescription(UNMAPPED_CODE), - message = "Placeholder message" + CoreError( + categoriesNativeValue = UNMAPPED_CATEGORY_CODE, + errorCodeNativeValue = UNMAPPED_ERROR_CODE, + messageNativeValue = "Placeholder message" ) ) ) assertEquals( - "[Connection][Unknown($UNMAPPED_CODE)] Placeholder message.", + "[$UNMAPPED_CATEGORY_CODE][Unknown($UNMAPPED_ERROR_CODE)] Placeholder message.", syncException.message ) } + // Core also has a concept of an "unknown" error code. It is being reported the same way + // as a truly unknown code with the description "Unknown()" @Test - fun convertSyncErrorCode_unmappedErrorCategory() { + fun convertSyncErrorCode_unknownNativeErrrorCode() { val syncException = convertSyncError( SyncError( - SyncErrorCode( - category = UnknownCodeDescription(UNMAPPED_CODE), - code = UnknownCodeDescription(UNMAPPED_CODE), - message = "Placeholder message" + CoreError( + categoriesNativeValue = ErrorCategory.RLM_ERR_CAT_CLIENT_ERROR.nativeValue, + errorCodeNativeValue = ErrorCode.RLM_ERR_UNKNOWN.nativeValue, + messageNativeValue = "Placeholder message" ) ) ) assertEquals( - "[$UNMAPPED_CODE][Unknown($UNMAPPED_CODE)] Placeholder message.", + "[Client][Unknown(2000000)] Placeholder message.", syncException.message ) } @@ -88,30 +95,30 @@ class RealmSyncUtilsTest { val appException = convertAppError( AppError( categoryFlags = ErrorCategory.RLM_ERR_CAT_CUSTOM_ERROR.nativeValue, - code = UnknownCodeDescription(UNMAPPED_CODE), + code = UnknownCodeDescription(UNMAPPED_ERROR_CODE), message = "Placeholder message", - httpStatusCode = UNMAPPED_CODE, + httpStatusCode = UNMAPPED_ERROR_CODE, linkToServerLog = null ) ) - assertEquals("[Custom][Unknown($UNMAPPED_CODE)] Placeholder message.", appException.message) + assertEquals("[Custom][Unknown($UNMAPPED_ERROR_CODE)] Placeholder message.", appException.message) } @Test fun convertAppError_unmappedErrorCategory() { val appException = convertAppError( AppError( - categoryFlags = UnknownCodeDescription(UNMAPPED_CODE).nativeValue, - code = UnknownCodeDescription(UNMAPPED_CODE), + categoryFlags = UnknownCodeDescription(UNMAPPED_CATEGORY_CODE).nativeValue, + code = UnknownCodeDescription(UNMAPPED_ERROR_CODE), message = "Placeholder message", - httpStatusCode = UNMAPPED_CODE, + httpStatusCode = UNMAPPED_ERROR_CODE, linkToServerLog = null ) ) assertEquals( - "[$UNMAPPED_CODE][Unknown($UNMAPPED_CODE)] Placeholder message.", + "[$UNMAPPED_CATEGORY_CODE][Unknown($UNMAPPED_ERROR_CODE)] Placeholder message.", appException.message ) } @@ -120,31 +127,31 @@ class RealmSyncUtilsTest { fun convertAppError_unmappedErrorCategoryAndErrorCode_noMessage() { val appException = convertAppError( AppError( - categoryFlags = UnknownCodeDescription(UNMAPPED_CODE).nativeValue, - code = UnknownCodeDescription(UNMAPPED_CODE), + categoryFlags = UnknownCodeDescription(UNMAPPED_CATEGORY_CODE).nativeValue, + code = UnknownCodeDescription(UNMAPPED_ERROR_CODE), message = null, - httpStatusCode = UNMAPPED_CODE, + httpStatusCode = UNMAPPED_ERROR_CODE, linkToServerLog = null ) ) - assertEquals("[$UNMAPPED_CODE][Unknown($UNMAPPED_CODE)]", appException.message) + assertEquals("[$UNMAPPED_CATEGORY_CODE][Unknown($UNMAPPED_ERROR_CODE)]", appException.message) } @Test fun convertAppError_unmappedErrorCategoryAndErrorCode_linkServerLog() { val appException = convertAppError( AppError( - categoryFlags = UnknownCodeDescription(UNMAPPED_CODE).nativeValue, - code = UnknownCodeDescription(UNMAPPED_CODE), + categoryFlags = UnknownCodeDescription(UNMAPPED_CATEGORY_CODE).nativeValue, + code = UnknownCodeDescription(UNMAPPED_ERROR_CODE), message = "Placeholder message", - httpStatusCode = UNMAPPED_CODE, + httpStatusCode = UNMAPPED_ERROR_CODE, linkToServerLog = "http://realm.io" ) ) assertEquals( - "[$UNMAPPED_CODE][Unknown($UNMAPPED_CODE)] Placeholder message. Server log entry: http://realm.io", + "[$UNMAPPED_CATEGORY_CODE][Unknown($UNMAPPED_ERROR_CODE)] Placeholder message. Server log entry: http://realm.io", appException.message ) } @@ -153,16 +160,16 @@ class RealmSyncUtilsTest { fun convertAppError_unmappedErrorCategoryAndErrorCode_noMessage_linkServerLog() { val appException = convertAppError( AppError( - categoryFlags = UnknownCodeDescription(UNMAPPED_CODE).nativeValue, - code = UnknownCodeDescription(UNMAPPED_CODE), + categoryFlags = UnknownCodeDescription(UNMAPPED_CATEGORY_CODE).nativeValue, + code = UnknownCodeDescription(UNMAPPED_ERROR_CODE), message = null, - httpStatusCode = UNMAPPED_CODE, + httpStatusCode = UNMAPPED_ERROR_CODE, linkToServerLog = "http://realm.io" ) ) assertEquals( - "[$UNMAPPED_CODE][Unknown($UNMAPPED_CODE)] Server log entry: http://realm.io", + "[$UNMAPPED_CATEGORY_CODE][Unknown($UNMAPPED_ERROR_CODE)] Server log entry: http://realm.io", appException.message ) } diff --git a/packages/test-sync/src/commonTest/kotlin/io/realm/kotlin/test/mongodb/common/internal/SyncConnectionParamsTests.kt b/packages/test-sync/src/commonTest/kotlin/io/realm/kotlin/test/mongodb/common/internal/SyncConnectionParamsTests.kt index 6ef9b2f491..4ece5ae87c 100644 --- a/packages/test-sync/src/commonTest/kotlin/io/realm/kotlin/test/mongodb/common/internal/SyncConnectionParamsTests.kt +++ b/packages/test-sync/src/commonTest/kotlin/io/realm/kotlin/test/mongodb/common/internal/SyncConnectionParamsTests.kt @@ -29,8 +29,6 @@ internal class SyncConnectionParamsTests { fun allProperties() { val props = SyncConnectionParams( sdkVersion = "sdkVersion", - localAppName = "appName", - localAppVersion = "appVersion", bundleId = "bundleId", platformVersion = "platformVersion", device = "device", @@ -40,8 +38,6 @@ internal class SyncConnectionParamsTests { ) assertEquals("Kotlin", props.sdkName) assertEquals("sdkVersion", props.sdkVersion) - assertEquals("appName", props.localAppName) - assertEquals("appVersion", props.localAppVersion) assertEquals("bundleId", props.bundleId) assertEquals("platformVersion", props.platformVersion) assertEquals("device", props.device)