Add test with new schema types (#389)

Add tests with new schema types

## Motivation and Context
<!-- Why is this change needed? What problem does it solve? -->

## How Has This Been Tested?
The repository currently contains duplicated tests:
- tests using the new schema
- tests using the old schema for compatibility checks. they will be
removed once the deprecation level is raised

## Breaking Changes
No

## Types of changes
- [ ] Bug fix (non-breaking change which fixes an issue)
- [ ] New feature (non-breaking change which adds functionality)
- [ ] Breaking change (fix or feature that would cause existing
functionality to change)
- [ ] Documentation update
- [x] Testing

## Checklist
- [x] I have read the [MCP
Documentation](https://modelcontextprotocol.io)
- [x] My code follows the repository's style guidelines
- [x] New and existing tests pass locally
- [x] I have added appropriate error handling
- [x] I have added or updated documentation as needed

---------

Co-authored-by: Konstantin Pavlov <1517853+kpavlov@users.noreply.github.com>
This commit is contained in:
Pavel Gorgulov 2025-11-14 10:39:43 +01:00 • committed by GitHub
commit 666cfd6b82
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 7286 additions and 55 deletions

View file

@ -0,0 +1,140 @@
package io.modelcontextprotocol.kotlin.sdk.server
import io.modelcontextprotocol.kotlin.sdk.InitializedNotification
import io.modelcontextprotocol.kotlin.sdk.JSONRPCMessage
import io.modelcontextprotocol.kotlin.sdk.PingRequest
import io.modelcontextprotocol.kotlin.sdk.shared.ReadBuffer
import io.modelcontextprotocol.kotlin.sdk.shared.serializeMessage
import io.modelcontextprotocol.kotlin.sdk.toJSON
import kotlinx.coroutines.CompletableDeferred
import kotlinx.coroutines.runBlocking
import kotlinx.coroutines.test.runTest
import kotlinx.io.Sink
import kotlinx.io.Source
import kotlinx.io.asSink
import kotlinx.io.asSource
import kotlinx.io.buffered
import java.io.ByteArrayOutputStream
import java.io.PipedInputStream
import java.io.PipedOutputStream
import kotlin.test.BeforeTest
import kotlin.test.Test
import kotlin.test.assertEquals
import kotlin.test.assertFalse
import kotlin.test.assertTrue
class OldSchemaStdioServerTransportTest {
private lateinit var input: PipedInputStream
private lateinit var inputWriter: PipedOutputStream
private lateinit var outputBuffer: ReadBuffer
private lateinit var output: ByteArrayOutputStream
// We'll store the wrapped streams that meet the constructor requirements
private lateinit var bufferedInput: Source
private lateinit var printOutput: Sink
@BeforeTest
fun setUp() {
// Simulate an input stream that we can push data into using inputWriter.
input = PipedInputStream()
inputWriter = PipedOutputStream(input)
outputBuffer = ReadBuffer()
// A custom ByteArrayOutputStream that appends all written data into outputBuffer
output = object : ByteArrayOutputStream() {
override fun write(b: ByteArray, off: Int, len: Int) {
super.write(b, off, len)
outputBuffer.append(b.copyOfRange(off, off + len))
}
}
bufferedInput = input.asSource().buffered()
printOutput = output.asSink().buffered()
}
@Test
fun `should start then close cleanly`() {
runBlocking {
val server = StdioServerTransport(bufferedInput, printOutput)
server.onError { error ->
throw error
}
var didClose = false
server.onClose {
didClose = true
}
server.start()
assertFalse(didClose, "Should not have closed yet")
server.close()
assertTrue(didClose, "Should have closed after calling close()")
}
}
@Test
fun `should not read until started`() = runTest {
val server = StdioServerTransport(bufferedInput, printOutput)
server.onError { error ->
throw error
}
var didRead = false
val readMessage = CompletableDeferred<JSONRPCMessage>()
server.onMessage { message ->
didRead = true
readMessage.complete(message)
}
val message = PingRequest().toJSON()
// Push a message before the server started
val serialized = serializeMessage(message)
inputWriter.write(serialized)
inputWriter.flush()
assertFalse(didRead, "Should not have read message before start")
server.start()
val received = readMessage.await()
assertEquals(message, received)
}
@Test
fun `should read multiple messages`() = runTest {
val server = StdioServerTransport(bufferedInput, printOutput)
server.onError { error ->
throw error
}
val messages = listOf(
PingRequest().toJSON(),
InitializedNotification().toJSON(),
)
val readMessages = mutableListOf<JSONRPCMessage>()
val finished = CompletableDeferred<Unit>()
server.onMessage { message ->
readMessages.add(message)
if (message == messages[1]) {
finished.complete(Unit)
}
}
// Push both messages before starting the server
for (m in messages) {
inputWriter.write(serializeMessage(m))
}
inputWriter.flush()
server.start()
finished.await()
assertEquals(messages, readMessages)
}
}

View file

@ -1,11 +1,11 @@
package io.modelcontextprotocol.kotlin.sdk.server
import io.modelcontextprotocol.kotlin.sdk.InitializedNotification
import io.modelcontextprotocol.kotlin.sdk.JSONRPCMessage
import io.modelcontextprotocol.kotlin.sdk.PingRequest
import io.modelcontextprotocol.kotlin.sdk.shared.ReadBuffer
import io.modelcontextprotocol.kotlin.sdk.shared.serializeMessage
import io.modelcontextprotocol.kotlin.sdk.toJSON
import io.modelcontextprotocol.kotlin.sdk.types.InitializedNotification
import io.modelcontextprotocol.kotlin.sdk.types.JSONRPCMessage
import io.modelcontextprotocol.kotlin.sdk.types.PingRequest
import io.modelcontextprotocol.kotlin.sdk.types.toJSON
import kotlinx.coroutines.CompletableDeferred
import kotlinx.coroutines.runBlocking
import kotlinx.coroutines.test.runTest