Skip to content

Commit f2b708b

Browse files
committed
fixup! Introduce Kotlin integration tests
1 parent f94f4c1 commit f2b708b

File tree

3 files changed

+37
-61
lines changed

3 files changed

+37
-61
lines changed

kotlin-sdk-test/src/jvmTest/kotlin/io/modelcontextprotocol/kotlin/sdk/integration/typescript/TypeScriptClientKotlinServerTest.kt

Lines changed: 7 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -41,13 +41,10 @@ class TypeScriptClientKotlinServerTest : TypeScriptTestBase() {
4141
@Test
4242
@Timeout(20, unit = TimeUnit.SECONDS)
4343
fun testToolCall() {
44-
val projectRoot = File(System.getProperty("user.dir"))
45-
val clientDir = File(projectRoot, "src/jvmTest/kotlin/io/modelcontextprotocol/kotlin/sdk/integration/utils")
46-
4744
// call the "greet" tool
4845
val testName = "TestUser"
4946
val command = "npx tsx myClient.ts $serverUrl greet $testName"
50-
val output = executeCommand(command, clientDir)
47+
val output = executeCommand(command, tsClientDir)
5148

5249
assertTrue(
5350
output.contains("Hello, $testName!"),
@@ -65,12 +62,9 @@ class TypeScriptClientKotlinServerTest : TypeScriptTestBase() {
6562
@Test
6663
@Timeout(20, unit = TimeUnit.SECONDS)
6764
fun testToolCallWithSessionManagement() {
68-
val projectRoot = File(System.getProperty("user.dir"))
69-
val clientDir = File(projectRoot, "src/jvmTest/kotlin/io/modelcontextprotocol/kotlin/sdk/integration/utils")
70-
7165
val testName = "SessionTest"
7266
val command = "npx tsx myClient.ts $serverUrl greet $testName"
73-
val output = executeCommand(command, clientDir)
67+
val output = executeCommand(command, tsClientDir)
7468

7569
assertTrue(output.contains("Connected to server"), "Client should connect to server")
7670
assertTrue(
@@ -82,7 +76,7 @@ class TypeScriptClientKotlinServerTest : TypeScriptTestBase() {
8276

8377
val multiGreetName = "NotificationTest"
8478
val multiGreetCommand = "npx tsx myClient.ts $serverUrl multi-greet $multiGreetName"
85-
val multiGreetOutput = executeCommand(multiGreetCommand, clientDir)
79+
val multiGreetOutput = executeCommand(multiGreetCommand, tsClientDir)
8680

8781
assertTrue(multiGreetOutput.contains("Connected to server"), "Client should connect to server")
8882
assertTrue(
@@ -95,20 +89,17 @@ class TypeScriptClientKotlinServerTest : TypeScriptTestBase() {
9589
@Test
9690
@Timeout(30, unit = TimeUnit.SECONDS)
9791
fun testMultipleClientSequence() {
98-
val projectRoot = File(System.getProperty("user.dir"))
99-
val clientDir = File(projectRoot, "src/jvmTest/kotlin/io/modelcontextprotocol/kotlin/sdk/integration/utils")
100-
10192
val testName1 = "FirstClient"
10293
val command1 = "npx tsx myClient.ts $serverUrl greet $testName1"
103-
val output1 = executeCommand(command1, clientDir)
94+
val output1 = executeCommand(command1, tsClientDir)
10495

10596
assertTrue(output1.contains("Connected to server"), "First client should connect to server")
10697
assertTrue(output1.contains("Hello, $testName1!"), "Tool response should contain the greeting for first client")
10798
assertTrue(output1.contains("Disconnected from server"), "First client should disconnect cleanly")
10899

109100
val testName2 = "SecondClient"
110101
val command2 = "npx tsx myClient.ts $serverUrl multi-greet $testName2"
111-
val output2 = executeCommand(command2, clientDir)
102+
val output2 = executeCommand(command2, tsClientDir)
112103

113104
assertTrue(output2.contains("Connected to server"), "Second client should connect to server")
114105
assertTrue(
@@ -118,7 +109,7 @@ class TypeScriptClientKotlinServerTest : TypeScriptTestBase() {
118109
assertTrue(output2.contains("Disconnected from server"), "Second client should disconnect cleanly")
119110

120111
val command3 = "npx tsx myClient.ts $serverUrl"
121-
val output3 = executeCommand(command3, clientDir)
112+
val output3 = executeCommand(command3, tsClientDir)
122113

123114
assertTrue(output3.contains("Connected to server"), "Third client should connect to server")
124115
assertTrue(output3.contains("Available utils:"), "Third client should list available utils")
@@ -130,9 +121,6 @@ class TypeScriptClientKotlinServerTest : TypeScriptTestBase() {
130121
@Test
131122
@Timeout(30, unit = TimeUnit.SECONDS)
132123
fun testMultipleClientParallel() {
133-
val projectRoot = File(System.getProperty("user.dir"))
134-
val clientDir = File(projectRoot, "src/jvmTest/kotlin/io/modelcontextprotocol/kotlin/sdk/integration/utils")
135-
136124
val clientCount = 3
137125
val clients = listOf(
138126
"FirstClient" to "greet",
@@ -154,7 +142,7 @@ class TypeScriptClientKotlinServerTest : TypeScriptTestBase() {
154142
"npx tsx myClient.ts $serverUrl $toolName $clientName"
155143
}
156144

157-
val output = executeCommand(command, clientDir)
145+
val output = executeCommand(command, tsClientDir)
158146
synchronized(outputs) {
159147
outputs.add(i to output)
160148
}

kotlin-sdk-test/src/jvmTest/kotlin/io/modelcontextprotocol/kotlin/sdk/integration/typescript/TypeScriptEdgeCasesTest.kt

Lines changed: 8 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -42,19 +42,16 @@ class TypeScriptEdgeCasesTest : TypeScriptTestBase() {
4242
@Test
4343
@Timeout(20, unit = TimeUnit.SECONDS)
4444
fun testErrorHandling() {
45-
val projectRoot = File(System.getProperty("user.dir"))
46-
val clientDir = File(projectRoot, "src/jvmTest/kotlin/io/modelcontextprotocol/kotlin/sdk/integration/utils")
47-
4845
val nonExistentToolCommand = "npx tsx myClient.ts $serverUrl non-existent-tool"
49-
val nonExistentToolOutput = executeCommandAllowingFailure(nonExistentToolCommand, clientDir)
46+
val nonExistentToolOutput = executeCommandAllowingFailure(nonExistentToolCommand, tsClientDir)
5047

5148
assertTrue(
5249
nonExistentToolOutput.contains("Tool \"non-existent-tool\" not found"),
5350
"Client should handle non-existent tool gracefully"
5451
)
5552

5653
val invalidUrlCommand = "npx tsx myClient.ts http://localhost:${port + 1000}/mcp greet TestUser"
57-
val invalidUrlOutput = executeCommandAllowingFailure(invalidUrlCommand, clientDir)
54+
val invalidUrlOutput = executeCommandAllowingFailure(invalidUrlCommand, tsClientDir)
5855

5956
assertTrue(
6057
invalidUrlOutput.contains("Error:") || invalidUrlOutput.contains("ECONNREFUSED"),
@@ -65,16 +62,13 @@ class TypeScriptEdgeCasesTest : TypeScriptTestBase() {
6562
@Test
6663
@Timeout(20, unit = TimeUnit.SECONDS)
6764
fun testSpecialCharacters() {
68-
val projectRoot = File(System.getProperty("user.dir"))
69-
val clientDir = File(projectRoot, "src/jvmTest/kotlin/io/modelcontextprotocol/kotlin/sdk/integration/utils")
70-
7165
val specialChars = "!@#$+-[].,?"
7266

73-
val tempFile = File(clientDir, "special_chars.txt")
67+
val tempFile = File(tsClientDir, "special_chars.txt")
7468
tempFile.writeText(specialChars)
7569

7670
val specialCharsCommand = "npx tsx myClient.ts $serverUrl greet \"$(cat special_chars.txt)\""
77-
val specialCharsOutput = executeCommand(specialCharsCommand, clientDir)
71+
val specialCharsOutput = executeCommand(specialCharsCommand, tsClientDir)
7872

7973
tempFile.delete()
8074

@@ -91,16 +85,13 @@ class TypeScriptEdgeCasesTest : TypeScriptTestBase() {
9185
@Test
9286
@Timeout(30, unit = TimeUnit.SECONDS)
9387
fun testLargePayload() {
94-
val projectRoot = File(System.getProperty("user.dir"))
95-
val clientDir = File(projectRoot, "src/jvmTest/kotlin/io/modelcontextprotocol/kotlin/sdk/integration/utils")
96-
9788
val largeName = "A".repeat(10 * 1024)
9889

99-
val tempFile = File(clientDir, "large_name.txt")
90+
val tempFile = File(tsClientDir, "large_name.txt")
10091
tempFile.writeText(largeName)
10192

10293
val largePayloadCommand = "npx tsx myClient.ts $serverUrl greet \"$(cat large_name.txt)\""
103-
val largePayloadOutput = executeCommand(largePayloadCommand, clientDir)
94+
val largePayloadOutput = executeCommand(largePayloadCommand, tsClientDir)
10495

10596
tempFile.delete()
10697

@@ -117,9 +108,6 @@ class TypeScriptEdgeCasesTest : TypeScriptTestBase() {
117108
@Test
118109
@Timeout(60, unit = TimeUnit.SECONDS)
119110
fun testComplexConcurrentRequests() {
120-
val projectRoot = File(System.getProperty("user.dir"))
121-
val clientDir = File(projectRoot, "src/jvmTest/kotlin/io/modelcontextprotocol/kotlin/sdk/integration/utils")
122-
123111
val commands = listOf(
124112
"npx tsx myClient.ts $serverUrl greet \"Client1\"",
125113
"npx tsx myClient.ts $serverUrl multi-greet \"Client2\"",
@@ -131,7 +119,7 @@ class TypeScriptEdgeCasesTest : TypeScriptTestBase() {
131119
val threads = commands.mapIndexed { index, command ->
132120
Thread {
133121
println("Starting client $index")
134-
val output = executeCommand(command, clientDir)
122+
val output = executeCommand(command, tsClientDir)
135123
println("Client $index completed")
136124

137125
assertTrue(
@@ -168,12 +156,9 @@ class TypeScriptEdgeCasesTest : TypeScriptTestBase() {
168156
@Test
169157
@Timeout(120, unit = TimeUnit.SECONDS)
170158
fun testRapidSequentialRequests() {
171-
val projectRoot = File(System.getProperty("user.dir"))
172-
val clientDir = File(projectRoot, "src/jvmTest/kotlin/io/modelcontextprotocol/kotlin/sdk/integration/utils")
173-
174159
val outputs = (1..10).map { i ->
175160
val command = "npx tsx myClient.ts $serverUrl greet \"RapidClient$i\""
176-
val output = executeCommand(command, clientDir)
161+
val output = executeCommand(command, tsClientDir)
177162

178163
assertTrue(
179164
output.contains("Connected to server"),
@@ -193,23 +178,4 @@ class TypeScriptEdgeCasesTest : TypeScriptTestBase() {
193178

194179
assertEquals(10, outputs.size, "All 10 rapid requests should complete successfully")
195180
}
196-
197-
private fun executeCommandAllowingFailure(command: String, workingDir: File): String {
198-
val process = ProcessBuilder()
199-
.command("bash", "-c", command)
200-
.directory(workingDir)
201-
.redirectErrorStream(true)
202-
.start()
203-
204-
val output = StringBuilder()
205-
process.inputStream.bufferedReader().useLines { lines ->
206-
for (line in lines) {
207-
println(line)
208-
output.append(line).append("\n")
209-
}
210-
}
211-
212-
process.waitFor(20, TimeUnit.SECONDS)
213-
return output.toString()
214-
}
215181
}

kotlin-sdk-test/src/jvmTest/kotlin/io/modelcontextprotocol/kotlin/sdk/integration/typescript/TypeScriptTestBase.kt

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,9 @@ import java.util.concurrent.TimeUnit
1111

1212
abstract class TypeScriptTestBase {
1313

14+
protected val projectRoot: File get() = File(System.getProperty("user.dir"))
15+
protected val tsClientDir: File get() = File(projectRoot, "src/jvmTest/kotlin/io/modelcontextprotocol/kotlin/sdk/integration/utils")
16+
1417
companion object {
1518
@JvmStatic
1619
protected val sdkDir = File("src/jvmTest/resources/typescript-sdk")
@@ -120,4 +123,23 @@ abstract class TypeScriptTestBase {
120123
}
121124
return false
122125
}
126+
127+
protected fun executeCommandAllowingFailure(command: String, workingDir: File, timeoutSeconds: Long = 20): String {
128+
val process = ProcessBuilder()
129+
.command("bash", "-c", command)
130+
.directory(workingDir)
131+
.redirectErrorStream(true)
132+
.start()
133+
134+
val output = StringBuilder()
135+
process.inputStream.bufferedReader().useLines { lines ->
136+
for (line in lines) {
137+
println(line)
138+
output.append(line).append("\n")
139+
}
140+
}
141+
142+
process.waitFor(timeoutSeconds, TimeUnit.SECONDS)
143+
return output.toString()
144+
}
123145
}

0 commit comments

Comments
 (0)