MCPcopy Create free account
hub / github.com/modelcontextprotocol/go-sdk / testStreamableHandler

Function testStreamableHandler

mcp/streamable_test.go:1291–1413  ·  view source on GitHub ↗
(t *testing.T, handler http.Handler, requests []streamableRequest)

Source from the content-addressed store, hash-verified

1289}
1290
1291func testStreamableHandler(t *testing.T, handler http.Handler, requests []streamableRequest) {
1292 httpServer := httptest.NewServer(mustNotPanic(t, handler))
1293 defer httpServer.Close()
1294
1295 // blocks records request blocks by jsonrpc. ID.
1296 //
1297 // When an OnRequest step is encountered, it waits on the corresponding
1298 // block. When a request with that ID is received, the block is closed.
1299 var mu sync.Mutex
1300 blocks := make(map[int64]chan struct{})
1301 for _, req := range requests {
1302 if req.onRequest > 0 {
1303 blocks[req.onRequest] = make(chan struct{})
1304 }
1305 }
1306
1307 // signal when all synchronous requests have executed, so we can fail
1308 // async requests that are blocked.
1309 syncRequestsDone := make(chan struct{})
1310
1311 // To avoid complicated accounting for session ID, just set the first
1312 // non-empty session ID from a response.
1313 var sessionID atomic.Value
1314 sessionID.Store("")
1315
1316 // doStep executes a single step.
1317 doStep := func(t *testing.T, i int, request streamableRequest) {
1318 if request.onRequest > 0 {
1319 // Block the step until we've received the server->client request.
1320 mu.Lock()
1321 block := blocks[request.onRequest]
1322 mu.Unlock()
1323 select {
1324 case <-block:
1325 case <-syncRequestsDone:
1326 t.Errorf("after all sync requests are complete, request still blocked on %d", request.onRequest)
1327 return
1328 }
1329 }
1330
1331 // Collect messages received during this request, unblock other steps
1332 // when requests are received.
1333 var got []jsonrpc.Message
1334 out := make(chan jsonrpc.Message)
1335 // Cancel the step if we encounter a request that isn't going to be
1336 // handled.
1337 //
1338 // Also, add a timeout (hopefully generous).
1339 ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
1340
1341 var wg sync.WaitGroup
1342 wg.Go(func() {
1343
1344 for m := range out {
1345 if req, ok := m.(*jsonrpc.Request); ok && req.IsCall() {
1346 // Encountered a server->client request. We should have a
1347 // response queued. Otherwise, we may deadlock.
1348 mu.Lock()

Calls 8

mustNotPanicFunction · 0.85
IsCallMethod · 0.80
RawMethod · 0.80
doMethod · 0.80
CompareAndSwapMethod · 0.80
CloseMethod · 0.65
ErrMethod · 0.45
WaitMethod · 0.45

Tested by

no test coverage detected

Used in the wild real call sites across dependent graphs

searching dependent graphs…