diff --git a/chat-android/src/main/java/com/ably/chat/AtomicCoroutineScope.kt b/chat-android/src/main/java/com/ably/chat/AtomicCoroutineScope.kt index e977063..f2f3a99 100644 --- a/chat-android/src/main/java/com/ably/chat/AtomicCoroutineScope.kt +++ b/chat-android/src/main/java/com/ably/chat/AtomicCoroutineScope.kt @@ -15,7 +15,7 @@ import kotlinx.coroutines.launch * Accepts scope as a constructor parameter to run operations under the given scope. * See [Kotlin Dispatchers](https://kt.academy/article/cc-dispatchers) for more information. */ -class AtomicCoroutineScope(private val scope: CoroutineScope = CoroutineScope(Dispatchers.Default)) { +internal class AtomicCoroutineScope(private val scope: CoroutineScope = CoroutineScope(Dispatchers.Default)) { private val sequentialScope: CoroutineScope = CoroutineScope(Dispatchers.Default.limitedParallelism(1)) diff --git a/chat-android/src/main/java/com/ably/chat/Connection.kt b/chat-android/src/main/java/com/ably/chat/Connection.kt index cfbafa1..e14c7a5 100644 --- a/chat-android/src/main/java/com/ably/chat/Connection.kt +++ b/chat-android/src/main/java/com/ably/chat/Connection.kt @@ -16,7 +16,7 @@ import io.ably.lib.realtime.Connection as PubSubConnection /** * Default timeout for transient states before we attempt handle them as a state change. */ -const val TRANSIENT_TIMEOUT = 5000 +internal const val TRANSIENT_TIMEOUT = 5000 /** * (CHA-CS1) The different states that the connection can be in through its lifecycle. diff --git a/chat-android/src/main/java/com/ably/chat/EventTypes.kt b/chat-android/src/main/java/com/ably/chat/EventTypes.kt index 9219f81..91a13aa 100644 --- a/chat-android/src/main/java/com/ably/chat/EventTypes.kt +++ b/chat-android/src/main/java/com/ably/chat/EventTypes.kt @@ -24,7 +24,7 @@ object PubSubMessageNames { const val ChatMessage = "chat.message" } -val messageActionNameToAction = mapOf( +internal val messageActionNameToAction = mapOf( /** Represents a message with no action set. */ "message.unset" to MessageAction.MESSAGE_UNSET, diff --git a/chat-android/src/main/java/com/ably/chat/Messages.kt b/chat-android/src/main/java/com/ably/chat/Messages.kt index 0245149..63561b4 100644 --- a/chat-android/src/main/java/com/ably/chat/Messages.kt +++ b/chat-android/src/main/java/com/ably/chat/Messages.kt @@ -12,8 +12,8 @@ import java.util.concurrent.ConcurrentHashMap import kotlinx.coroutines.CompletableDeferred import io.ably.lib.realtime.Channel as AblyRealtimeChannel -typealias PubSubMessageListener = AblyRealtimeChannel.MessageListener -typealias PubSubMessage = io.ably.lib.types.Message +internal typealias PubSubMessageListener = AblyRealtimeChannel.MessageListener +internal typealias PubSubMessage = io.ably.lib.types.Message /** * This interface is used to interact with messages in a chat room: subscribing @@ -131,7 +131,7 @@ data class MessageEvent( /** * Params for sending a text message. Only `text` is mandatory. */ -data class SendMessageParams( +internal data class SendMessageParams( /** * The text of the message. */ diff --git a/chat-android/src/main/java/com/ably/chat/PaginatedResult.kt b/chat-android/src/main/java/com/ably/chat/PaginatedResult.kt index 38473e6..106be22 100644 --- a/chat-android/src/main/java/com/ably/chat/PaginatedResult.kt +++ b/chat-android/src/main/java/com/ably/chat/PaginatedResult.kt @@ -31,7 +31,7 @@ interface PaginatedResult { fun hasNext(): Boolean } -fun AsyncHttpPaginatedResponse?.toPaginatedResult(transform: (JsonElement) -> T?): PaginatedResult = +internal fun AsyncHttpPaginatedResponse?.toPaginatedResult(transform: (JsonElement) -> T?): PaginatedResult = this?.let { AsyncPaginatedResultWrapper(it, transform) } ?: EmptyPaginatedResult() private class EmptyPaginatedResult : PaginatedResult { diff --git a/chat-android/src/main/java/com/ably/chat/RoomLifecycleManager.kt b/chat-android/src/main/java/com/ably/chat/RoomLifecycleManager.kt index 4da631b..5ffb3be 100644 --- a/chat-android/src/main/java/com/ably/chat/RoomLifecycleManager.kt +++ b/chat-android/src/main/java/com/ably/chat/RoomLifecycleManager.kt @@ -16,7 +16,7 @@ import io.ably.lib.realtime.Channel as AblyRealtimeChannel /** * An interface for features that contribute to the room status. */ -interface ContributesToRoomLifecycle : EmitsDiscontinuities, HandlesDiscontinuity { +internal interface ContributesToRoomLifecycle : EmitsDiscontinuities, HandlesDiscontinuity { /** * Name of the feature @@ -67,7 +67,7 @@ internal abstract class ContributesToRoomLifecycleImpl(logger: Logger) : Contrib * The order of precedence for lifecycle operations, passed to PriorityQueueExecutor which allows * us to ensure that internal operations take precedence over user-driven operations. */ -enum class LifecycleOperationPrecedence(val priority: Int) { +internal enum class LifecycleOperationPrecedence(val priority: Int) { Internal(1), Release(2), AttachOrDetach(3), @@ -76,17 +76,17 @@ enum class LifecycleOperationPrecedence(val priority: Int) { /** * A map of contributors to pending discontinuity events. */ -typealias DiscontinuityEventMap = MutableMap +internal typealias DiscontinuityEventMap = MutableMap /** * An internal interface that represents the result of a room attachment operation. */ -interface RoomAttachmentResult : NewRoomStatus { +internal interface RoomAttachmentResult : NewRoomStatus { val failedFeature: ContributesToRoomLifecycle? val exception: AblyException } -class DefaultRoomAttachmentResult : RoomAttachmentResult { +internal class DefaultRoomAttachmentResult : RoomAttachmentResult { internal var statusField: RoomStatus = RoomStatus.Attached override val status: RoomStatus get() = statusField diff --git a/chat-android/src/main/java/com/ably/chat/RoomReactions.kt b/chat-android/src/main/java/com/ably/chat/RoomReactions.kt index 2412200..9cfcf6d 100644 --- a/chat-android/src/main/java/com/ably/chat/RoomReactions.kt +++ b/chat-android/src/main/java/com/ably/chat/RoomReactions.kt @@ -61,7 +61,7 @@ interface RoomReactions : EmitsDiscontinuities { /** * Params for sending a room-level reactions. Only `type` is mandatory. */ -data class SendReactionParams( +internal data class SendReactionParams( /** * The type of the reaction, for example an emoji or a short string such as * "like". diff --git a/chat-android/src/main/java/com/ably/chat/RoomStatus.kt b/chat-android/src/main/java/com/ably/chat/RoomStatus.kt index 6fd3820..75adddc 100644 --- a/chat-android/src/main/java/com/ably/chat/RoomStatus.kt +++ b/chat-android/src/main/java/com/ably/chat/RoomStatus.kt @@ -128,7 +128,7 @@ interface RoomLifecycle { /** * A new room status that can be set. */ -interface NewRoomStatus { +internal interface NewRoomStatus { /** * The new status of the room. */ @@ -146,7 +146,7 @@ interface NewRoomStatus { * internal functionality from user listeners. * @internal */ -interface InternalRoomLifecycle : RoomLifecycle { +internal interface InternalRoomLifecycle : RoomLifecycle { /** * Registers a listener that will be called once when the room status changes. * @param listener The function to call when the status changes. diff --git a/chat-android/src/main/java/com/ably/chat/Typing.kt b/chat-android/src/main/java/com/ably/chat/Typing.kt index 4b85fd1..ebec90d 100644 --- a/chat-android/src/main/java/com/ably/chat/Typing.kt +++ b/chat-android/src/main/java/com/ably/chat/Typing.kt @@ -23,17 +23,17 @@ import kotlinx.coroutines.launch /** * base retry interval, we double it each time */ -const val PRESENCE_GET_RETRY_INTERVAL_MS: Long = 1500 +internal const val PRESENCE_GET_RETRY_INTERVAL_MS: Long = 1500 /** * max retry interval */ -const val PRESENCE_GET_RETRY_MAX_INTERVAL_MS: Long = 30_000 +internal const val PRESENCE_GET_RETRY_MAX_INTERVAL_MS: Long = 30_000 /** * max num of retries */ -const val PRESENCE_GET_MAX_RETRIES = 5 +internal const val PRESENCE_GET_MAX_RETRIES = 5 /** * This interface is used to interact with typing in a chat room including subscribing to typing events and diff --git a/chat-android/src/main/java/com/ably/chat/Utils.kt b/chat-android/src/main/java/com/ably/chat/Utils.kt index d9a02c1..92b1803 100644 --- a/chat-android/src/main/java/com/ably/chat/Utils.kt +++ b/chat-android/src/main/java/com/ably/chat/Utils.kt @@ -20,9 +20,9 @@ import kotlinx.coroutines.suspendCancellableCoroutine import kotlinx.coroutines.withContext import io.ably.lib.realtime.Presence as PubSubPresence -const val AGENT_PARAMETER_NAME = "agent" +internal const val AGENT_PARAMETER_NAME = "agent" -suspend fun Channel.attachCoroutine() = suspendCancellableCoroutine { continuation -> +internal suspend fun Channel.attachCoroutine() = suspendCancellableCoroutine { continuation -> attach(object : CompletionListener { override fun onSuccess() { continuation.resume(Unit) @@ -34,7 +34,7 @@ suspend fun Channel.attachCoroutine() = suspendCancellableCoroutine { continuati }) } -suspend fun Channel.detachCoroutine() = suspendCancellableCoroutine { continuation -> +internal suspend fun Channel.detachCoroutine() = suspendCancellableCoroutine { continuation -> detach(object : CompletionListener { override fun onSuccess() { continuation.resume(Unit) @@ -46,7 +46,7 @@ suspend fun Channel.detachCoroutine() = suspendCancellableCoroutine { continuati }) } -suspend fun Channel.publishCoroutine(message: PubSubMessage) = suspendCancellableCoroutine { continuation -> +internal suspend fun Channel.publishCoroutine(message: PubSubMessage) = suspendCancellableCoroutine { continuation -> publish( message, object : CompletionListener { @@ -62,7 +62,7 @@ suspend fun Channel.publishCoroutine(message: PubSubMessage) = suspendCancellabl } @Suppress("SpreadOperator") -suspend fun PubSubPresence.getCoroutine( +internal suspend fun PubSubPresence.getCoroutine( waitForSync: Boolean = true, clientId: String? = null, connectionId: String? = null, @@ -75,7 +75,7 @@ suspend fun PubSubPresence.getCoroutine( get(*params.toTypedArray()).asList() } -suspend fun PubSubPresence.enterClientCoroutine(clientId: String, data: JsonElement? = JsonNull.INSTANCE) = +internal suspend fun PubSubPresence.enterClientCoroutine(clientId: String, data: JsonElement? = JsonNull.INSTANCE) = suspendCancellableCoroutine { continuation -> enterClient( clientId, @@ -92,7 +92,7 @@ suspend fun PubSubPresence.enterClientCoroutine(clientId: String, data: JsonElem ) } -suspend fun PubSubPresence.updateClientCoroutine(clientId: String, data: JsonElement? = JsonNull.INSTANCE) = +internal suspend fun PubSubPresence.updateClientCoroutine(clientId: String, data: JsonElement? = JsonNull.INSTANCE) = suspendCancellableCoroutine { continuation -> updateClient( clientId, @@ -109,7 +109,7 @@ suspend fun PubSubPresence.updateClientCoroutine(clientId: String, data: JsonEle ) } -suspend fun PubSubPresence.leaveClientCoroutine(clientId: String, data: JsonElement? = JsonNull.INSTANCE) = +internal suspend fun PubSubPresence.leaveClientCoroutine(clientId: String, data: JsonElement? = JsonNull.INSTANCE) = suspendCancellableCoroutine { continuation -> leaveClient( clientId, @@ -126,7 +126,7 @@ suspend fun PubSubPresence.leaveClientCoroutine(clientId: String, data: JsonElem ) } -val Channel.errorMessage: String +internal val Channel.errorMessage: String get() = if (reason == null) { "" } else { @@ -134,7 +134,7 @@ val Channel.errorMessage: String } @Suppress("FunctionName") -fun ChatChannelOptions(init: (ChannelOptions.() -> Unit)? = null): ChannelOptions { +internal fun ChatChannelOptions(init: (ChannelOptions.() -> Unit)? = null): ChannelOptions { val options = ChannelOptions() init?.let { options.it() } options.params = (options.params ?: mapOf()) + mapOf( @@ -145,32 +145,32 @@ fun ChatChannelOptions(init: (ChannelOptions.() -> Unit)? = null): ChannelOption return options } -fun generateUUID() = UUID.randomUUID().toString() +internal fun generateUUID() = UUID.randomUUID().toString() -fun lifeCycleErrorInfo( +internal fun lifeCycleErrorInfo( errorMessage: String, errorCode: ErrorCode, ) = createErrorInfo(errorMessage, errorCode, HttpStatusCode.InternalServerError) -fun lifeCycleException( +internal fun lifeCycleException( errorMessage: String, errorCode: ErrorCode, cause: Throwable? = null, ): AblyException = createAblyException(lifeCycleErrorInfo(errorMessage, errorCode), cause) -fun lifeCycleException( +internal fun lifeCycleException( errorInfo: ErrorInfo, cause: Throwable? = null, ): AblyException = createAblyException(errorInfo, cause) -fun roomInvalidStateException(roomId: String, roomStatus: RoomStatus, statusCode: Int) = +internal fun roomInvalidStateException(roomId: String, roomStatus: RoomStatus, statusCode: Int) = ablyException( "Can't perform operation; the room '$roomId' is in an invalid state: $roomStatus", ErrorCode.RoomInInvalidState, statusCode, ) -fun ablyException( +internal fun ablyException( errorMessage: String, errorCode: ErrorCode, statusCode: Int = HttpStatusCode.BadRequest, @@ -180,7 +180,7 @@ fun ablyException( return createAblyException(errorInfo, cause) } -fun ablyException( +internal fun ablyException( errorInfo: ErrorInfo, cause: Throwable? = null, ): AblyException = createAblyException(errorInfo, cause) @@ -197,6 +197,6 @@ private fun createAblyException( ) = cause?.let { AblyException.fromErrorInfo(it, errorInfo) } ?: AblyException.fromErrorInfo(errorInfo) -fun clientError(errorMessage: String) = ablyException(errorMessage, ErrorCode.BadRequest, HttpStatusCode.BadRequest) +internal fun clientError(errorMessage: String) = ablyException(errorMessage, ErrorCode.BadRequest, HttpStatusCode.BadRequest) -fun serverError(errorMessage: String) = ablyException(errorMessage, ErrorCode.InternalError, HttpStatusCode.InternalServerError) +internal fun serverError(errorMessage: String) = ablyException(errorMessage, ErrorCode.InternalError, HttpStatusCode.InternalServerError) diff --git a/chat-android/src/test/java/com/ably/chat/AtomicCoroutineScopeTest.kt b/chat-android/src/test/java/com/ably/chat/AtomicCoroutineScopeTest.kt index 3fc94c5..6376391 100644 --- a/chat-android/src/test/java/com/ably/chat/AtomicCoroutineScopeTest.kt +++ b/chat-android/src/test/java/com/ably/chat/AtomicCoroutineScopeTest.kt @@ -16,6 +16,7 @@ import kotlinx.coroutines.runBlocking import kotlinx.coroutines.test.runTest import kotlinx.coroutines.withContext import org.hamcrest.CoreMatchers.containsString +import org.hamcrest.MatcherAssert.assertThat import org.junit.Assert import org.junit.Test @@ -156,7 +157,7 @@ class AtomicCoroutineScopeTest { repeat(10) { Assert.assertEquals(it, results[it]) Assert.assertEquals("roomId", contextNames[it]) - Assert.assertThat(contexts[it], containsString("Dispatchers.Default.limitedParallelism(1)")) + assertThat(contexts[it], containsString("Dispatchers.Default.limitedParallelism(1)")) } assertWaiter { atomicCoroutineScope.finishedProcessing } } @@ -198,7 +199,7 @@ class AtomicCoroutineScopeTest { val expectedResults = listOf(99, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0) repeat(10) { Assert.assertEquals(expectedResults[it], results[it]) - Assert.assertThat(contexts[it], containsString("Dispatchers.Default")) + assertThat(contexts[it], containsString("Dispatchers.Default")) } assertWaiter { atomicCoroutineScope.finishedProcessing } } diff --git a/chat-android/src/test/java/com/ably/chat/room/RoomGetTest.kt b/chat-android/src/test/java/com/ably/chat/room/RoomGetTest.kt index ae3bc85..4a640de 100644 --- a/chat-android/src/test/java/com/ably/chat/room/RoomGetTest.kt +++ b/chat-android/src/test/java/com/ably/chat/room/RoomGetTest.kt @@ -15,6 +15,7 @@ import io.mockk.every import io.mockk.mockk import io.mockk.spyk import io.mockk.verify +import kotlinx.coroutines.DelicateCoroutinesApi import kotlinx.coroutines.async import kotlinx.coroutines.channels.Channel import kotlinx.coroutines.launch @@ -132,6 +133,7 @@ class RoomGetTest { Assert.assertEquals(room, rooms.RoomIdToRoom[roomId]) } + @OptIn(DelicateCoroutinesApi::class) @Suppress("MaximumLineLength", "LongMethod") @Test fun `(CHA-RC1f4, CHA-RC1f5) If CHA-RC1g release operation is in progress, new instance should not be returned until release operation completes`() = runTest { diff --git a/chat-android/src/test/java/com/ably/chat/room/RoomReleaseTest.kt b/chat-android/src/test/java/com/ably/chat/room/RoomReleaseTest.kt index dde7660..f0e4d6b 100644 --- a/chat-android/src/test/java/com/ably/chat/room/RoomReleaseTest.kt +++ b/chat-android/src/test/java/com/ably/chat/room/RoomReleaseTest.kt @@ -19,6 +19,7 @@ import io.mockk.mockk import io.mockk.spyk import io.mockk.verify import kotlinx.coroutines.Deferred +import kotlinx.coroutines.DelicateCoroutinesApi import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.SupervisorJob import kotlinx.coroutines.async @@ -180,6 +181,7 @@ class RoomReleaseTest { } } + @OptIn(DelicateCoroutinesApi::class) @Suppress("MaximumLineLength", "LongMethod") @Test fun `(CHA-RC1g4, CHA-RC1f6) Pending room get operation waiting for room release should be cancelled and deferred associated with previous release operation will be resolved`() = runTest { diff --git a/chat-android/src/test/java/com/ably/chat/room/RoomTestHelpers.kt b/chat-android/src/test/java/com/ably/chat/room/RoomTestHelpers.kt index a550efb..0cd7b38 100644 --- a/chat-android/src/test/java/com/ably/chat/room/RoomTestHelpers.kt +++ b/chat-android/src/test/java/com/ably/chat/room/RoomTestHelpers.kt @@ -92,7 +92,10 @@ internal suspend fun RoomLifecycleManager.atomicRetry(exceptContributor: Contrib }.await() } -fun createRoomFeatureMocks(roomId: String = DEFAULT_ROOM_ID, clientId: String = DEFAULT_CLIENT_ID): List { +internal fun createRoomFeatureMocks( + roomId: String = DEFAULT_ROOM_ID, + clientId: String = DEFAULT_CLIENT_ID, +): List { val realtimeClient = createMockRealtimeClient() val chatApi = createMockChatApi() val logger = createMockLogger()