mirror of
https://github.com/Ed1s0nZ/CyberStrikeAI.git
synced 2026-08-15 07:30:53 +02:00
139 lines
4.2 KiB
Go
139 lines
4.2 KiB
Go
package multiagent
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"testing"
|
|
|
|
"github.com/cloudwego/eino/adk"
|
|
"go.uber.org/zap"
|
|
"go.uber.org/zap/zaptest/observer"
|
|
)
|
|
|
|
func TestEinoCheckpointResumeHandlerSkipsWithoutCheckpoint(t *testing.T) {
|
|
called := false
|
|
handler := newEinoCheckpointResumeHandler(einoCheckpointResumeHandlerConfig{
|
|
Resume: func(string) (*adk.AsyncIterator[*adk.AgentEvent], error) {
|
|
called = true
|
|
return nil, nil
|
|
},
|
|
})
|
|
if iter := handler.TryResume(); iter != nil {
|
|
t.Fatalf("iter = %#v, want nil", iter)
|
|
}
|
|
if called {
|
|
t.Fatal("resume should not be called without checkpoint state")
|
|
}
|
|
}
|
|
|
|
func TestEinoCheckpointResumeHandlerResumesExistingCheckpoint(t *testing.T) {
|
|
store, err := newFileCheckPointStore(t.TempDir())
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if err := store.Set(context.Background(), "cp-1", []byte("checkpoint")); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
var progressMessages []string
|
|
var resumedID string
|
|
core, logs := observer.New(zap.InfoLevel)
|
|
wantIter, gen := adk.NewAsyncIteratorPair[*adk.AgentEvent]()
|
|
defer gen.Close()
|
|
handler := newEinoCheckpointResumeHandler(einoCheckpointResumeHandlerConfig{
|
|
Context: context.Background(),
|
|
ConversationID: "conv-1",
|
|
OrchMode: "deep",
|
|
Store: store,
|
|
CheckPointID: "cp-1",
|
|
Logger: zap.New(core),
|
|
Progress: func(eventType, message string, data interface{}) {
|
|
if eventType != "progress" {
|
|
return
|
|
}
|
|
progressMessages = append(progressMessages, message)
|
|
m, _ := data.(map[string]interface{})
|
|
if m["conversationId"] != "conv-1" || m["orchestration"] != "deep" || m["checkPointID"] != "cp-1" {
|
|
t.Fatalf("progress data = %#v", m)
|
|
}
|
|
},
|
|
Resume: func(checkPointID string) (*adk.AsyncIterator[*adk.AgentEvent], error) {
|
|
resumedID = checkPointID
|
|
return wantIter, nil
|
|
},
|
|
})
|
|
|
|
got := handler.TryResume()
|
|
if got != wantIter {
|
|
t.Fatalf("iter = %#v, want resume iterator", got)
|
|
}
|
|
if resumedID != "cp-1" {
|
|
t.Fatalf("resumed id = %q", resumedID)
|
|
}
|
|
if len(progressMessages) != 1 || progressMessages[0] != "检测到断点,正在从中断节点恢复执行..." {
|
|
t.Fatalf("progress messages = %#v", progressMessages)
|
|
}
|
|
if logs.FilterMessage("eino runner: resume from checkpoint").Len() != 1 {
|
|
t.Fatalf("expected resume log, got %d", logs.Len())
|
|
}
|
|
}
|
|
|
|
func TestEinoCheckpointResumeHandlerFallsBackOnResumeError(t *testing.T) {
|
|
store, err := newFileCheckPointStore(t.TempDir())
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if err := store.Set(context.Background(), "cp-1", []byte("checkpoint")); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
var progressMessages []string
|
|
core, logs := observer.New(zap.WarnLevel)
|
|
handler := newEinoCheckpointResumeHandler(einoCheckpointResumeHandlerConfig{
|
|
Context: context.Background(),
|
|
Store: store,
|
|
CheckPointID: "cp-1",
|
|
Logger: zap.New(core),
|
|
Progress: func(eventType, message string, _ interface{}) {
|
|
if eventType == "progress" {
|
|
progressMessages = append(progressMessages, message)
|
|
}
|
|
},
|
|
Resume: func(string) (*adk.AsyncIterator[*adk.AgentEvent], error) {
|
|
return nil, errors.New("resume failed")
|
|
},
|
|
})
|
|
|
|
if iter := handler.TryResume(); iter != nil {
|
|
t.Fatalf("iter = %#v, want nil fallback", iter)
|
|
}
|
|
if len(progressMessages) != 2 || progressMessages[1] != "断点恢复失败,已回退为全新执行。" {
|
|
t.Fatalf("progress messages = %#v", progressMessages)
|
|
}
|
|
if logs.FilterMessage("eino runner: resume failed, fallback to fresh run").Len() != 1 {
|
|
t.Fatalf("expected fallback log, got %d", logs.Len())
|
|
}
|
|
}
|
|
|
|
func TestEinoCheckpointResumeHandlerLogsPreflightError(t *testing.T) {
|
|
store, err := newFileCheckPointStore(t.TempDir())
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
core, logs := observer.New(zap.WarnLevel)
|
|
handler := newEinoCheckpointResumeHandler(einoCheckpointResumeHandlerConfig{
|
|
Context: context.Background(),
|
|
Store: store,
|
|
CheckPointID: "bad/id",
|
|
Logger: zap.New(core),
|
|
Resume: func(string) (*adk.AsyncIterator[*adk.AgentEvent], error) {
|
|
t.Fatal("resume should not be called after preflight error")
|
|
return nil, nil
|
|
},
|
|
})
|
|
if iter := handler.TryResume(); iter != nil {
|
|
t.Fatalf("iter = %#v, want nil", iter)
|
|
}
|
|
if logs.FilterMessage("eino checkpoint preflight get failed").Len() != 1 {
|
|
t.Fatalf("expected preflight warning, got %d", logs.Len())
|
|
}
|
|
}
|