Skip to content

Commit 122a729

Browse files
committed
[CHAT-5063] feat: add tests for agent propagation
Add tests to verify agent propagation in the WrapperSdkProxy clients
1 parent ab1badf commit 122a729

7 files changed

Lines changed: 387 additions & 2 deletions

File tree

gradle/libs.versions.toml

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ lombok = "8.10"
2020
okhttp = "4.12.0"
2121
test-retry = "1.6.0"
2222
kotlin = "2.1.10"
23+
coroutine = "1.9.0"
24+
turbine = "1.2.0"
2325

2426
[libraries]
2527
gson = { group = "com.google.code.gson", name = "gson", version.ref = "gson" }
@@ -41,11 +43,14 @@ dexmaker = { group = "com.crittercism.dexmaker", name = "dexmaker", version.ref
4143
dexmaker-dx = { group = "com.crittercism.dexmaker", name = "dexmaker-dx", version.ref = "dexmaker" }
4244
dexmaker-mockito = { group = "com.crittercism.dexmaker", name = "dexmaker-mockito", version.ref = "dexmaker" }
4345
android-retrostreams = { group = "net.sourceforge.streamsupport", name = "android-retrostreams", version.ref = "android-retrostreams" }
44-
okhttp = { group ="com.squareup.okhttp3", name = "okhttp", version.ref = "okhttp" }
46+
okhttp = { group = "com.squareup.okhttp3", name = "okhttp", version.ref = "okhttp" }
47+
coroutine-core = { group = "org.jetbrains.kotlinx", name = "kotlinx-coroutines-core", version.ref = "coroutine" }
48+
coroutine-test = { group = "org.jetbrains.kotlinx", name = "kotlinx-coroutines-test", version.ref = "coroutine" }
49+
turbine = { group = "app.cash.turbine", name = "turbine", version.ref = "turbine" }
4550

4651
[bundles]
4752
common = ["msgpack", "vcdiff-core"]
48-
tests = ["junit","hamcrest-all", "nanohttpd", "nanohttpd-nanolets", "nanohttpd-websocket", "mockito-core", "concurrentunit", "slf4j-simple"]
53+
tests = ["junit", "hamcrest-all", "nanohttpd", "nanohttpd-nanolets", "nanohttpd-websocket", "mockito-core", "concurrentunit", "slf4j-simple"]
4954
instrumental-android = ["android-test-runner", "android-test-rules", "dexmaker", "dexmaker-dx", "dexmaker-mockito", "android-retrostreams"]
5055

5156
[plugins]

pubsub-adapter/build.gradle.kts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,5 +6,18 @@ plugins {
66

77
dependencies {
88
compileOnly(project(":java"))
9+
testImplementation(kotlin("test"))
910
testImplementation(project(":java"))
11+
testImplementation(libs.nanohttpd)
12+
testImplementation(libs.coroutine.core)
13+
testImplementation(libs.coroutine.test)
14+
testImplementation(libs.turbine)
15+
}
16+
17+
tasks.withType<Test> {
18+
useJUnitPlatform()
19+
}
20+
21+
tasks.register<Test>("runUnitTests") {
22+
beforeTest(closureOf<TestDescriptor> { logger.lifecycle("-> $this") })
1023
}
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
package com.ably
2+
3+
import fi.iki.elonen.NanoHTTPD
4+
import kotlinx.coroutines.channels.BufferOverflow
5+
import kotlinx.coroutines.flow.Flow
6+
import kotlinx.coroutines.flow.MutableSharedFlow
7+
import java.io.ByteArrayInputStream
8+
9+
data class Request(
10+
val path: String,
11+
val params: Map<String, String> = emptyMap(),
12+
val headers: Map<String, String> = emptyMap(),
13+
)
14+
15+
data class Response(
16+
val mimeType: String,
17+
val data: ByteArray,
18+
)
19+
20+
fun json(json: String): Response = Response(
21+
mimeType = "application/json",
22+
data = json.toByteArray(),
23+
)
24+
25+
fun interface RequestHandler {
26+
fun handle(request: Request): Response
27+
}
28+
29+
class EmbeddedServer(port: Int, private val requestHandler: RequestHandler? = null) : NanoHTTPD(port) {
30+
private val _servedRequests = MutableSharedFlow<Request>(
31+
extraBufferCapacity = 1,
32+
onBufferOverflow = BufferOverflow.DROP_OLDEST,
33+
)
34+
35+
val servedRequests: Flow<Request> = _servedRequests
36+
37+
override fun serve(session: IHTTPSession): Response {
38+
val request = Request(
39+
path = session.uri,
40+
params = session.parms,
41+
headers = session.headers,
42+
)
43+
_servedRequests.tryEmit(request)
44+
val response = requestHandler?.handle(request)
45+
return response?.toNanoHttp() ?: newFixedLengthResponse("<!DOCTYPE html><title>404</title>")
46+
}
47+
}
48+
49+
private fun Response.toNanoHttp(): NanoHTTPD.Response = NanoHTTPD.newFixedLengthResponse(
50+
NanoHTTPD.Response.Status.OK,
51+
mimeType,
52+
ByteArrayInputStream(data),
53+
data.size.toLong(),
54+
)
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
package com.ably
2+
3+
import kotlinx.coroutines.Dispatchers
4+
import kotlinx.coroutines.delay
5+
import kotlinx.coroutines.withContext
6+
import kotlinx.coroutines.withTimeout
7+
8+
suspend fun waitFor(timeoutInMs: Long = 10_000, block: suspend () -> Boolean) {
9+
withContext(Dispatchers.Default) {
10+
withTimeout(timeoutInMs) {
11+
do {
12+
val success = block()
13+
delay(100)
14+
} while (!success)
15+
}
16+
}
17+
}
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
package com.ably.pubsub
2+
3+
import io.ably.lib.realtime.AblyRealtime
4+
import io.ably.lib.realtime.RealtimeClient
5+
import io.ably.lib.realtime.RealtimeClientAdapter
6+
import io.ably.lib.realtime.channelOptions
7+
import io.ably.lib.types.ChannelMode
8+
import io.ably.lib.types.ChannelOptions
9+
import io.ably.lib.types.ClientOptions
10+
import kotlinx.coroutines.test.runTest
11+
import kotlin.test.Test
12+
import kotlin.test.assertEquals
13+
import kotlin.test.assertNull
14+
import kotlin.test.assertTrue
15+
16+
class SdkWrapperAgentChannelParamTest {
17+
18+
@Test
19+
fun `should add agent information to Realtime channels params`() = runTest {
20+
val javaRealtimeClient = createAblyRealtime()
21+
val realtimeClient = RealtimeClientAdapter(javaRealtimeClient)
22+
val wrapperSdkClient =
23+
realtimeClient.createWrapperSdkProxy(WrapperSdkProxyOptions(agents = mapOf("chat-android" to "0.1.0")))
24+
25+
// create channel from sdk proxy wrapper
26+
wrapperSdkClient.channels.get("chat-channel")
27+
28+
// create channel without sdk proxy wrapper
29+
realtimeClient.channels.get("regular-channel")
30+
31+
assertEquals(
32+
"chat-android/0.1.0",
33+
javaRealtimeClient.channels.get("chat-channel").channelOptions?.params?.get("agent")
34+
)
35+
36+
assertNull(
37+
javaRealtimeClient.channels.get("regular-channel").channelOptions?.params?.get("agent")
38+
)
39+
}
40+
41+
@Test
42+
fun `should add agent information to Realtime channels params when channel created with custom options`() = runTest {
43+
val javaRealtimeClient = createAblyRealtime()
44+
val realtimeClient = RealtimeClient(javaRealtimeClient)
45+
val wrapperSdkClient =
46+
realtimeClient.createWrapperSdkProxy(WrapperSdkProxyOptions(agents = mapOf("chat-android" to "0.1.0")))
47+
48+
// create channel from sdk proxy wrapper
49+
wrapperSdkClient.channels.get("chat-channel", ChannelOptions().apply {
50+
params = mapOf("foo" to "bar")
51+
modes = arrayOf(ChannelMode.presence)
52+
})
53+
54+
// create channel without sdk proxy wrapper
55+
realtimeClient.channels.get("regular-channel", ChannelOptions().apply {
56+
encrypted = true
57+
})
58+
59+
assertEquals(
60+
"chat-android/0.1.0",
61+
javaRealtimeClient.channels.get("chat-channel").channelOptions?.params?.get("agent")
62+
)
63+
64+
assertEquals(
65+
"bar",
66+
javaRealtimeClient.channels.get("chat-channel").channelOptions?.params?.get("foo")
67+
)
68+
69+
assertEquals(
70+
ChannelMode.presence,
71+
javaRealtimeClient.channels.get("chat-channel").channelOptions?.modes?.get(0)
72+
)
73+
74+
assertNull(
75+
javaRealtimeClient.channels.get("regular-channel").channelOptions?.params?.get("agent")
76+
)
77+
78+
assertTrue(
79+
javaRealtimeClient.channels.get("regular-channel").channelOptions?.encrypted ?: false
80+
)
81+
}
82+
}
83+
84+
private fun createAblyRealtime(): AblyRealtime {
85+
val options = ClientOptions("xxxxx:yyyyyyy").apply {
86+
autoConnect = false
87+
}
88+
return AblyRealtime(options)
89+
}

0 commit comments

Comments
 (0)