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
4 changed files with 7286 additions and 55 deletions

View file

@ -0,0 +1,33 @@
package io.modelcontextprotocol.kotlin.sdk
import io.kotest.assertions.json.shouldEqualJson
import io.modelcontextprotocol.kotlin.sdk.shared.McpJson
import kotlin.test.Test
import kotlin.test.assertEquals
class OldSchemaAudioContentSerializationTest {
private val audioContentJson = """
{
"data": "base64-encoded-audio-data",
"mimeType": "audio/wav",
"type": "audio"
}
""".trimIndent()
private val audioContent = AudioContent(
data = "base64-encoded-audio-data",
mimeType = "audio/wav",
)
@Test
fun `should serialize audio content`() {
McpJson.encodeToString(audioContent) shouldEqualJson audioContentJson
}
@Test
fun `should deserialize audio content`() {
val content = McpJson.decodeFromString<AudioContent>(audioContentJson)
assertEquals(expected = audioContent, actual = content)
}
}

View file

@ -0,0 +1,72 @@
package io.modelcontextprotocol.kotlin.sdk.models
import io.kotest.matchers.shouldBe
import io.modelcontextprotocol.kotlin.sdk.types.McpJson
import io.modelcontextprotocol.kotlin.sdk.types.ProgressNotification
import io.modelcontextprotocol.kotlin.sdk.types.ProgressNotificationParams
import io.modelcontextprotocol.kotlin.sdk.types.RequestId
import kotlin.test.Test
class ProgressNotificationsTest {
/**
* https://modelcontextprotocol.io/specification/2025-06-18/basic/utilities/progress#progress-flow
*/
@Test
fun `Read ProgressNotifications with string token`() {
//language=json
val json = """
{
"jsonrpc": "2.0",
"method": "notifications/progress",
"params": {
"progressToken": "abc123",
"progress": 50,
"total": 100,
"message": "Reticulating splines..."
}
}
""".trimIndent()
val result = McpJson.decodeFromString<ProgressNotification>(json)
result shouldBe ProgressNotification(
params = ProgressNotificationParams(
progressToken = RequestId.StringId("abc123"),
progress = 50.0,
message = "Reticulating splines...",
total = 100.0,
),
)
}
/**
* https://modelcontextprotocol.io/specification/2025-06-18/basic/utilities/progress#progress-flow
*/
@Test
fun `Read ProgressNotifications with integer token`() {
//language=json
val json = """
{
"jsonrpc": "2.0",
"method": "notifications/progress",
"params": {
"progressToken": 100500,
"progress": 50,
"total": 100,
"message": "Reticulating splines..."
}
}
""".trimIndent()
val result = McpJson.decodeFromString<ProgressNotification>(json)
result shouldBe ProgressNotification(
params = ProgressNotificationParams(
progressToken = RequestId.NumberId(100500),
progress = 50.0,
message = "Reticulating splines...",
total = 100.0,
),
)
}
}

View file

@ -0,0 +1,62 @@
package io.modelcontextprotocol.kotlin.sdk.shared
import io.ktor.utils.io.charsets.Charsets
import io.ktor.utils.io.core.toByteArray
import io.modelcontextprotocol.kotlin.sdk.JSONRPCMessage
import io.modelcontextprotocol.kotlin.sdk.JSONRPCNotification
import kotlinx.serialization.json.Json
import kotlin.test.Test
import kotlin.test.assertEquals
import kotlin.test.assertNull
class OldSchemaReadBufferTest {
private val testMessage: JSONRPCMessage = JSONRPCNotification(method = "foobar")
private val json = Json {
ignoreUnknownKeys = true
encodeDefaults = true
}
@Test
fun `should have no messages after initialization`() {
val readBuffer = ReadBuffer()
assertNull(readBuffer.readMessage())
}
@Test
fun `should only yield a message after a newline`() {
val readBuffer = ReadBuffer()
// Append message without a newline
val messageBytes = json.encodeToString(testMessage).encodeToByteArray()
readBuffer.append(messageBytes)
assertNull(readBuffer.readMessage())
// Append a newline and verify message is now available
readBuffer.append("\n".encodeToByteArray())
assertEquals(testMessage, readBuffer.readMessage())
assertNull(readBuffer.readMessage())
}
@Test
fun `skip empty line`() {
val readBuffer = ReadBuffer()
readBuffer.append("\n".toByteArray())
assertNull(readBuffer.readMessage())
}
@Test
fun `should be reusable after clearing`() {
val readBuffer = ReadBuffer()
readBuffer.append("foobar".toByteArray(Charsets.UTF_8))
readBuffer.clear()
assertNull(readBuffer.readMessage())
val messageJson = serializeMessage(testMessage)
readBuffer.append(messageJson.toByteArray(Charsets.UTF_8))
readBuffer.append("\n".toByteArray(Charsets.UTF_8))
val message = readBuffer.readMessage()
assertEquals(testMessage, message)
}
}

View file

@ -2,8 +2,8 @@ package io.modelcontextprotocol.kotlin.sdk.shared
import io.ktor.utils.io.charsets.Charsets
import io.ktor.utils.io.core.toByteArray
import io.modelcontextprotocol.kotlin.sdk.JSONRPCMessage
import io.modelcontextprotocol.kotlin.sdk.JSONRPCNotification
import io.modelcontextprotocol.kotlin.sdk.types.JSONRPCMessage
import io.modelcontextprotocol.kotlin.sdk.types.JSONRPCNotification
import kotlinx.serialization.json.Json
import kotlin.test.Test
import kotlin.test.assertEquals