@@ -464,28 +464,31 @@ var _ = Describe("OsvMcpServer", Label("mcp", "streamable-http", "e2e"), Serial,
464464 serverName := generateUniqueServerName ("osv-foreground-test" )
465465
466466 // 1) Start the foreground process in the background (goroutine) with a generous timeout.
467- done := make (chan struct {})
468467 fgStdout := ""
469468 fgStderr := ""
469+
470+ // maintain a reference to the command so we can interrupt it when we're done.
471+ runCommand := e2e .NewTHVCommand (
472+ config , "run" ,
473+ "--name" , serverName ,
474+ "--transport" , "streamable-http" ,
475+ "--foreground" ,
476+ "osv" ,
477+ )
470478 go func () {
471- out , errOut , _ := e2e .NewTHVCommand (
472- config , "run" ,
473- "--name" , serverName ,
474- "--transport" , "streamable-http" ,
475- "--foreground" ,
476- "osv" ,
477- ).RunWithTimeout (5 * time .Minute )
479+ out , errOut , _ := runCommand .RunWithTimeout (5 * time .Minute )
478480 fgStdout , fgStderr = out , errOut
479- close (done )
480481 }()
481482
482483 // Always try to stop the server at the end so the goroutine returns.
483484 defer func () {
484- _ , _ , _ = e2e .NewTHVCommand (config , "stop" , serverName ).Run ()
485- select {
486- case <- done :
487- case <- time .After (15 * time .Second ):
488- // Nothing else we can signal directly; the RunWithTimeout will eventually kill it.
485+ // If this takes too long, the timeout willl kill the server eventually.
486+ ctx , cancel := context .WithTimeout (context .Background (), 15 * time .Second )
487+ defer cancel ()
488+ err := runCommand .InterruptAndWaitForExit (ctx )
489+ if err != nil {
490+ // This may be safe to ignore if the server is already stopped.
491+ GinkgoWriter .Printf ("Error interrupting foreground server during last cleanup: %v\n " , err )
489492 }
490493 }()
491494
@@ -530,15 +533,11 @@ var _ = Describe("OsvMcpServer", Label("mcp", "streamable-http", "e2e"), Serial,
530533
531534 // 6) Stop the server; this should unblock the goroutine.
532535 By ("stopping the foreground server" )
533- _ , _ = e2e .NewTHVCommand (config , "stop" , serverName ).ExpectSuccess ()
534-
535- // Wait for the run goroutine to exit.
536- select {
537- case <- done :
538- // ok
539- case <- time .After (15 * time .Second ):
540- Fail ("foreground run did not exit after stop; stdout=" + fgStdout + " stderr=" + fgStderr , 1 )
541- }
536+
537+ ctx , cancel := context .WithTimeout (context .Background (), 15 * time .Second )
538+ defer cancel ()
539+ err = runCommand .InterruptAndWaitForExit (ctx )
540+ Expect (err ).ToNot (HaveOccurred (), "server should be stopped; stdout=" + fgStdout + " stderr=" + fgStderr )
542541
543542 // 7) Workload should be stopped via workload manager.
544543 By ("verifying workload status is stopped via workload manager" )
@@ -556,9 +555,11 @@ var _ = Describe("OsvMcpServer", Label("mcp", "streamable-http", "e2e"), Serial,
556555 return workload .Status
557556 }, 15 * time .Second , 200 * time .Millisecond ).Should (Equal (runtime .WorkloadStatusStopped ), "workload should be in stopped status after stop" )
558557
559- // 8) Verify status file still exists with stopped status (it's not deleted, just marked as stopped)
560- By ("verifying status file still exists after stop" )
561- Expect (statusFileExists (serverName )).To (BeTrue (), "status file should still exist after stop" )
558+ // 8) Verify status file does NOT exist. Interrupting a foreground server should delete the status file.
559+ // We may want to change this behavior and prefer the status to remain in a stopped state.
560+ // For now, this test documents the current behavior.
561+ By ("verifying status file does not exist after stop" )
562+ Expect (! statusFileExists (serverName )).To (BeTrue (), "status file should not exist after stop" )
562563
563564 })
564565 })
0 commit comments