swift-sdk/Tests/MCPTests/ServerTests.swift
2025-03-18 09:47:54 -07:00

136 lines
4.3 KiB
Swift

import Foundation
import Testing
@testable import MCP
@Suite("Server Tests")
struct ServerTests {
@Test("Start and stop server")
func testServerStartAndStop() async throws {
let transport = MockTransport()
let server = Server(name: "TestServer", version: "1.0")
#expect(await transport.isConnected == false)
try await server.start(transport: transport)
#expect(await transport.isConnected == true)
await server.stop()
#expect(await transport.isConnected == false)
}
@Test("Initialize request handling")
func testServerHandleInitialize() async throws {
let transport = MockTransport()
// Queue an initialize request
try await transport.queueRequest(
Initialize.request(
.init(
protocolVersion: Version.latest,
capabilities: .init(),
clientInfo: .init(name: "TestClient", version: "1.0")
)
))
// Start the server
let server: Server = Server(
name: "TestServer",
version: "1.0"
)
try await server.start(transport: transport)
// Wait for message processing and response
try await Task.sleep(nanoseconds: 10_000_000) // 10ms
#expect(await transport.sentMessages.count == 1)
#expect(await transport.sentMessages[0].contains(Initialize.name))
// Clean up
await server.stop()
await transport.disconnect()
}
@Test("Initialize hook - successful")
func testInitializeHookSuccess() async throws {
let transport = MockTransport()
actor TestState {
var hookCalled = false
func setHookCalled() { hookCalled = true }
func wasHookCalled() -> Bool { hookCalled }
}
let state = TestState()
let server = Server(name: "TestServer", version: "1.0")
// Start with the hook directly
try await server.start(transport: transport) { clientInfo, capabilities in
#expect(clientInfo.name == "TestClient")
#expect(clientInfo.version == "1.0")
await state.setHookCalled()
}
// Wait for server to initialize
try await Task.sleep(nanoseconds: 10_000_000) // 10ms
// Queue an initialize request
try await transport.queueRequest(
Initialize.request(
.init(
protocolVersion: Version.latest,
capabilities: .init(),
clientInfo: .init(name: "TestClient", version: "1.0")
)
))
// Wait for message processing and hook execution
try await Task.sleep(nanoseconds: 200_000_000) // 200ms
#expect(await state.wasHookCalled() == true)
#expect(await transport.sentMessages.count >= 1)
let messages = await transport.sentMessages
if let response = messages.first {
#expect(response.contains("serverInfo"))
}
await server.stop()
}
@Test("Initialize hook - rejection")
func testInitializeHookRejection() async throws {
let transport = MockTransport()
let server = Server(name: "TestServer", version: "1.0")
try await server.start(transport: transport) { clientInfo, _ in
if clientInfo.name == "BlockedClient" {
throw Error.invalidRequest("Client not allowed")
}
}
// Wait for server to initialize
try await Task.sleep(nanoseconds: 10_000_000) // 10ms
// Queue an initialize request from blocked client
try await transport.queueRequest(
Initialize.request(
.init(
protocolVersion: Version.latest,
capabilities: .init(),
clientInfo: .init(name: "BlockedClient", version: "1.0")
)
))
// Wait for message processing
try await Task.sleep(nanoseconds: 200_000_000) // 200ms
#expect(await transport.sentMessages.count >= 2)
let messages = await transport.sentMessages
if let response = messages.first {
#expect(response.contains("error"))
#expect(response.contains("Client not allowed"))
}
await server.stop()
}
}