Skip to content

Commit 0e5e9a8

Browse files
authored
Bump ktor and add a test for gzip content encoding in JS (#4554)
* fix JS mockserver with binary content * add a gzip test * bump ktor * revert uneeded changes * remove debug
1 parent ead5363 commit 0e5e9a8

File tree

10 files changed

+720
-2
lines changed

10 files changed

+720
-2
lines changed

build-logic/src/main/kotlin/org/jetbrains/kotlin/gradle/internal/testing/TCServiceMessagesClient.kt

Lines changed: 554 additions & 0 deletions
Large diffs are not rendered by default.

gradle/libraries.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ kotlinx-datetime = "0.4.0"
2424
kotlinx-serialization-json = "1.4.1"
2525
ksp = "1.7.21-1.0.8"
2626
ksp-duringideasync = "1.6.10-1.0.2"
27-
ktor = "2.0.2"
27+
ktor = "2.1.3"
2828
moshi = "1.12.0"
2929
moshix = "0.14.1"
3030
okhttp = "4.9.3"

libraries/apollo-mockserver/src/jsMain/kotlin/com/apollographql/apollo3/mockserver/MockServer.kt

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import okio.Timeout
1313
import okio.buffer
1414
import org.khronos.webgl.Int8Array
1515
import org.khronos.webgl.Uint8Array
16+
import org.khronos.webgl.set
1617
import kotlin.coroutines.resume
1718
import kotlin.coroutines.suspendCoroutine
1819

@@ -76,9 +77,19 @@ actual class MockServer actual constructor(override val mockServerHandler: MockS
7677

7778
private class SocketSink(private val socket: Socket) : Sink {
7879
override fun write(source: okio.Buffer, byteCount: Long) {
79-
socket.write(source.readUtf8(byteCount))
80+
socket.write(source.toUint8Array(byteCount))
8081
}
8182

83+
private fun okio.Buffer.toUint8Array(count: Long): Uint8Array {
84+
val array = Uint8Array(count.toInt())
85+
86+
for (i in 0.until(count.toInt())) {
87+
array.set(i.toInt(), get(i.toLong()))
88+
}
89+
90+
skip(count)
91+
return array
92+
}
8293
override fun close() {}
8394
override fun flush() {}
8495
override fun timeout() = Timeout.NONE
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
package com.apollographql.apollo3.network
2+
3+
import com.apollographql.apollo3.mockserver.MockResponse
4+
import com.apollographql.apollo3.mockserver.MockServer
5+
import com.apollographql.apollo3.network.http.DefaultHttpEngine
6+
import com.apollographql.apollo3.network.http.get
7+
import com.apollographql.apollo3.testing.internal.runTest
8+
import okio.Buffer
9+
import okio.ByteString
10+
import kotlin.test.Test
11+
import kotlin.test.assertEquals
12+
13+
class HttpEngineTest {
14+
// "Hello World" gzipped and hex encoded
15+
val gzipData = """
16+
1f8b 0800 0000 0000 0003 f348 cdc9 c957
17+
08cf 2fca 4901 0056 b117 4a0b 0000 00
18+
""".replace(Regex("\\s"), "")
19+
20+
private fun String.toByteString(): ByteString {
21+
val buffer = Buffer()
22+
chunked(2).forEach {
23+
buffer.writeByte(it.toInt(16))
24+
}
25+
26+
return buffer.readByteString()
27+
}
28+
29+
@Test
30+
fun gzipTest() = runTest {
31+
val mockServer = MockServer()
32+
33+
try {
34+
mockServer.enqueue(MockResponse.Builder()
35+
.addHeader("content-type", "application/text")
36+
.addHeader("content-encoding", "gzip")
37+
.body(gzipData.toByteString())
38+
.build())
39+
40+
val engine = DefaultHttpEngine()
41+
42+
val response = engine.get(mockServer.url())
43+
.execute()
44+
45+
val result = response.body?.readUtf8()
46+
assertEquals("Hello World", result)
47+
48+
} catch (e: Exception) {
49+
e.printStackTrace()
50+
}
51+
52+
mockServer.stop()
53+
}
54+
}

libraries/apollo-testing-support/src/commonMain/kotlin/com/apollographql/apollo3/testing/runTest.kt

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
11
package com.apollographql.apollo3.testing
22

3+
import com.apollographql.apollo3.ApolloClient
34
import com.apollographql.apollo3.annotations.ApolloDeprecatedSince
45
import com.apollographql.apollo3.annotations.ApolloDeprecatedSince.Version.v3_4_1
56
import com.apollographql.apollo3.annotations.ApolloExperimental
7+
import com.apollographql.apollo3.mockserver.MockServer
68
import kotlinx.coroutines.CoroutineScope
9+
import okio.use
710
import kotlin.coroutines.CoroutineContext
811
import kotlin.coroutines.EmptyCoroutineContext
912

@@ -18,3 +21,26 @@ fun runTest(
1821
) {
1922
com.apollographql.apollo3.testing.internal.runTest(skipDelays = false, context, before, after, block)
2023
}
24+
25+
@ApolloExperimental
26+
class MockServerTest(val mockServer: MockServer, val apolloClient: ApolloClient, val scope: CoroutineScope)
27+
28+
/**
29+
* A convenience function that makes sure the MockServer and ApolloClient are properly closed at the end of the test
30+
*/
31+
@ApolloExperimental
32+
fun mockServerTest(block: suspend MockServerTest.() -> Unit) = com.apollographql.apollo3.testing.internal.runTest(true) {
33+
val mockServer = MockServer()
34+
35+
val apolloClient = ApolloClient.Builder()
36+
.serverUrl(mockServer.url())
37+
.build()
38+
39+
try {
40+
apolloClient.use {
41+
MockServerTest(mockServer, it, this).block()
42+
}
43+
} finally {
44+
mockServer.stop()
45+
}
46+
}

tests/gzip/build.gradle.kts

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
import org.jetbrains.kotlin.gradle.targets.jvm.tasks.KotlinJvmTest
2+
3+
plugins {
4+
id("org.jetbrains.kotlin.multiplatform")
5+
id("apollo.test")
6+
id("com.apollographql.apollo3")
7+
}
8+
9+
apolloTest {
10+
mpp {}
11+
}
12+
13+
kotlin {
14+
sourceSets {
15+
val commonMain by getting {
16+
dependencies {
17+
implementation(golatac.lib("apollo.runtime"))
18+
}
19+
}
20+
21+
val commonTest by getting {
22+
dependencies {
23+
implementation(golatac.lib("apollo.testingsupport"))
24+
}
25+
}
26+
}
27+
}
28+
29+
apollo {
30+
service("service") {
31+
packageName.set("gzip")
32+
}
33+
}

tests/gzip/lorem.txt.gz

334 Bytes
Binary file not shown.
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
query GetString {
2+
longString
3+
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
type Query {
2+
longString: String!
3+
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
package test
2+
3+
import com.apollographql.apollo3.mockserver.MockResponse
4+
import com.apollographql.apollo3.testing.HostFileSystem
5+
import com.apollographql.apollo3.testing.mockServerTest
6+
import com.apollographql.apollo3.testing.testsPath
7+
import gzip.GetStringQuery
8+
import okio.Path.Companion.toPath
9+
import okio.buffer
10+
import okio.use
11+
import kotlin.test.Test
12+
import kotlin.test.assertEquals
13+
import kotlin.test.assertTrue
14+
15+
class GzipTest {
16+
@Test
17+
fun gzipTest() = mockServerTest {
18+
// This contains a valid response encoded with gzip
19+
val byteString = HostFileSystem.openReadOnly(testsPath.toPath().resolve("gzip/lorem.txt.gz")).use {
20+
it.source().buffer().readByteString()
21+
}
22+
23+
mockServer.enqueue(
24+
MockResponse.Builder()
25+
.addHeader("content-type", "application/text")
26+
.addHeader("content-encoding", "gzip")
27+
.body(byteString)
28+
.build()
29+
)
30+
val response = apolloClient.query(GetStringQuery()).execute()
31+
assertEquals(2225, response.data?.longString?.length)
32+
assertTrue(response.data?.longString?.startsWith("Lorem ipsum dolor sit amet") == true)
33+
}
34+
}

0 commit comments

Comments
 (0)