mirror of
https://github.com/Ed1s0nZ/CyberStrikeAI.git
synced 2026-09-17 23:22:27 +02:00
77 lines
2.5 KiB
Go
77 lines
2.5 KiB
Go
package mcp
|
|
|
|
import (
|
|
"context"
|
|
"cyberstrike-ai/internal/runlease"
|
|
"errors"
|
|
"testing"
|
|
"time"
|
|
)
|
|
|
|
func TestExecutionOwnedAfterContextDetached(t *testing.T) {
|
|
scope := runlease.New()
|
|
parent, cancel := context.WithCancel(runlease.WithScope(context.Background(), scope))
|
|
service := NewExecutionService(nil, nil)
|
|
entered := make(chan struct{})
|
|
handle, err := service.Submit(parent, ExecutionRequest{Run: func(ctx context.Context) (*ToolResult, error) { close(entered); <-ctx.Done(); return nil, ctx.Err() }})
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
<-entered
|
|
cancel()
|
|
snapshot, _ := service.Get(handle.ID)
|
|
if snapshot.Execution.Status != ToolExecutionStatusRunning {
|
|
t.Fatal("caller cancellation ended detached worker")
|
|
}
|
|
scope.Cancel()
|
|
deadline, stop := context.WithTimeout(context.Background(), time.Second)
|
|
defer stop()
|
|
if err = scope.Wait(deadline); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
snapshot, _ = service.Get(handle.ID)
|
|
if snapshot.Execution.Status != ToolExecutionStatusCancelled {
|
|
t.Fatalf("unexpected state: %s", snapshot.Execution.Status)
|
|
}
|
|
if _, err = service.Submit(parent, ExecutionRequest{Run: func(context.Context) (*ToolResult, error) { t.Error("closed task executed tool"); return nil, nil }}); !errors.Is(err, runlease.ErrClosed) {
|
|
t.Fatalf("late submit: %v", err)
|
|
}
|
|
}
|
|
func TestRemoteCancellationRequiresAcknowledgement(t *testing.T) {
|
|
for _, confirm := range []bool{false, true} {
|
|
name := "unconfirmed"
|
|
if confirm {
|
|
name = "confirmed"
|
|
}
|
|
t.Run(name, func(t *testing.T) {
|
|
scope := runlease.New()
|
|
ctx := runlease.WithScope(context.Background(), scope)
|
|
service := NewExecutionService(nil, nil)
|
|
entered := make(chan struct{})
|
|
req := ExecutionRequest{Remote: true, Run: func(ctx context.Context) (*ToolResult, error) { close(entered); <-ctx.Done(); return nil, ctx.Err() }}
|
|
if confirm {
|
|
req.ConfirmCancellation = func(context.Context) error { return nil }
|
|
}
|
|
handle, err := service.Submit(ctx, req)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
<-entered
|
|
scope.Cancel()
|
|
deadline, stop := context.WithTimeout(context.Background(), time.Second)
|
|
defer stop()
|
|
err = scope.Wait(deadline)
|
|
snapshot, _ := service.Get(handle.ID)
|
|
if confirm {
|
|
if err != nil || snapshot.Execution.Status != ToolExecutionStatusCancelled {
|
|
t.Fatalf("confirmed: %v %+v", err, snapshot.Execution)
|
|
}
|
|
} else {
|
|
if !errors.Is(err, runlease.ErrUnconfirmed) || snapshot.Execution.Status != ToolExecutionStatusOrphaned {
|
|
t.Fatalf("notification treated as confirmation: %v %+v", err, snapshot.Execution)
|
|
}
|
|
}
|
|
})
|
|
}
|
|
}
|