352 lines
8.1 KiB
Go
352 lines
8.1 KiB
Go
package memory
|
|||
|
|
|
||
|
|
import (
|
||
|
|
"context"
|
||
|
|
"encoding/json"
|
||
|
|
"net/http"
|
||
|
|
"net/http/httptest"
|
||
|
|
"testing"
|
||
|
|
|
||
|
|
"go.temporal.io/sdk/testsuite"
|
||
|
|
)
|
||
|
|
|
||
|
|
func TestActivityCreateKnowledge(t *testing.T) {
|
||
|
|
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||
|
|
w.WriteHeader(http.StatusCreated)
|
||
|
|
json.NewEncoder(w).Encode(IngestResponse{ID: "chunk-123"})
|
||
|
|
}))
|
||
|
|
defer server.Close()
|
||
|
|
|
||
|
|
suite := &testsuite.WorkflowTestSuite{}
|
||
|
|
env := suite.NewTestActivityEnvironment()
|
||
|
|
|
||
|
|
svc := NewService(server.URL, "test-token", "poimen")
|
||
|
|
activities := NewActivities(svc)
|
||
|
|
|
||
|
|
env.RegisterActivity(activities.CreateKnowledgeActivity)
|
||
|
|
|
||
|
|
record := &KnowledgeRecord{
|
||
|
|
Level: "L1",
|
||
|
|
Content: "test",
|
||
|
|
}
|
||
|
|
|
||
|
|
result, err := env.ExecuteActivity(activities.CreateKnowledgeActivity, record)
|
||
|
|
|
||
|
|
if err != nil {
|
||
|
|
t.Fatalf("activity failed: %v", err)
|
||
|
|
}
|
||
|
|
|
||
|
|
var id string
|
||
|
|
if err := result.Get(&id); err != nil {
|
||
|
|
t.Fatalf("get result failed: %v", err)
|
||
|
|
}
|
||
|
|
|
||
|
|
if id != "chunk-123" {
|
||
|
|
t.Errorf("expected chunk-123, got %s", id)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestActivitySearchKnowledge(t *testing.T) {
|
||
|
|
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||
|
|
w.WriteHeader(http.StatusOK)
|
||
|
|
json.NewEncoder(w).Encode(QueryResponse{
|
||
|
|
Results: []QueryResult{
|
||
|
|
{
|
||
|
|
ID: "chunk-123",
|
||
|
|
Text: "matching knowledge",
|
||
|
|
},
|
||
|
|
},
|
||
|
|
})
|
||
|
|
}))
|
||
|
|
defer server.Close()
|
||
|
|
|
||
|
|
suite := &testsuite.WorkflowTestSuite{}
|
||
|
|
env := suite.NewTestActivityEnvironment()
|
||
|
|
|
||
|
|
svc := NewService(server.URL, "test-token", "poimen")
|
||
|
|
activities := NewActivities(svc)
|
||
|
|
|
||
|
|
env.RegisterActivity(activities.SearchKnowledgeActivity)
|
||
|
|
|
||
|
|
result, err := env.ExecuteActivity(activities.SearchKnowledgeActivity, "test query", nil)
|
||
|
|
|
||
|
|
if err != nil {
|
||
|
|
t.Fatalf("activity failed: %v", err)
|
||
|
|
}
|
||
|
|
|
||
|
|
var records []KnowledgeRecord
|
||
|
|
if err := result.Get(&records); err != nil {
|
||
|
|
t.Fatalf("get result failed: %v", err)
|
||
|
|
}
|
||
|
|
|
||
|
|
if len(records) != 1 {
|
||
|
|
t.Errorf("expected 1 record, got %d", len(records))
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestActivityGetContext(t *testing.T) {
|
||
|
|
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||
|
|
w.WriteHeader(http.StatusOK)
|
||
|
|
json.NewEncoder(w).Encode(ContextResponse{
|
||
|
|
Tier: 1,
|
||
|
|
Lessons: []ContextLesson{
|
||
|
|
{
|
||
|
|
Tier: 1,
|
||
|
|
Text: "lesson text",
|
||
|
|
},
|
||
|
|
},
|
||
|
|
})
|
||
|
|
}))
|
||
|
|
defer server.Close()
|
||
|
|
|
||
|
|
suite := &testsuite.WorkflowTestSuite{}
|
||
|
|
env := suite.NewTestActivityEnvironment()
|
||
|
|
|
||
|
|
svc := NewService(server.URL, "test-token", "poimen")
|
||
|
|
activities := NewActivities(svc)
|
||
|
|
|
||
|
|
env.RegisterActivity(activities.GetContextActivity)
|
||
|
|
|
||
|
|
result, err := env.ExecuteActivity(activities.GetContextActivity, "kubectl", "debug", 8192)
|
||
|
|
|
||
|
|
if err != nil {
|
||
|
|
t.Fatalf("activity failed: %v", err)
|
||
|
|
}
|
||
|
|
|
||
|
|
var ctx *ServiceContext
|
||
|
|
if err := result.Get(&ctx); err != nil {
|
||
|
|
t.Fatalf("get result failed: %v", err)
|
||
|
|
}
|
||
|
|
|
||
|
|
if ctx.Tier != 1 {
|
||
|
|
t.Errorf("expected tier 1, got %d", ctx.Tier)
|
||
|
|
}
|
||
|
|
|
||
|
|
if len(ctx.Lessons) != 1 {
|
||
|
|
t.Errorf("expected 1 lesson, got %d", len(ctx.Lessons))
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestActivityDiagnoseIssue(t *testing.T) {
|
||
|
|
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||
|
|
w.WriteHeader(http.StatusOK)
|
||
|
|
json.NewEncoder(w).Encode(ContextResponse{
|
||
|
|
Tier: 1,
|
||
|
|
Lessons: []ContextLesson{
|
||
|
|
{
|
||
|
|
Tier: 1,
|
||
|
|
Text: "diagnosis: check logs",
|
||
|
|
},
|
||
|
|
},
|
||
|
|
Skills: []ContextSkill{
|
||
|
|
{
|
||
|
|
Name: "debug-skill",
|
||
|
|
Why: "matched",
|
||
|
|
},
|
||
|
|
},
|
||
|
|
})
|
||
|
|
}))
|
||
|
|
defer server.Close()
|
||
|
|
|
||
|
|
suite := &testsuite.WorkflowTestSuite{}
|
||
|
|
env := suite.NewTestActivityEnvironment()
|
||
|
|
|
||
|
|
svc := NewService(server.URL, "test-token", "poimen")
|
||
|
|
activities := NewActivities(svc)
|
||
|
|
|
||
|
|
env.RegisterActivity(activities.DiagnoseIssueActivity)
|
||
|
|
|
||
|
|
result, err := env.ExecuteActivity(activities.DiagnoseIssueActivity, "kubectl", "pod-crash")
|
||
|
|
|
||
|
|
if err != nil {
|
||
|
|
t.Fatalf("activity failed: %v", err)
|
||
|
|
}
|
||
|
|
|
||
|
|
var recommendations []string
|
||
|
|
if err := result.Get(&recommendations); err != nil {
|
||
|
|
t.Fatalf("get result failed: %v", err)
|
||
|
|
}
|
||
|
|
|
||
|
|
if len(recommendations) == 0 {
|
||
|
|
t.Error("expected recommendations")
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestActivityAnalyzeError(t *testing.T) {
|
||
|
|
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||
|
|
w.WriteHeader(http.StatusOK)
|
||
|
|
json.NewEncoder(w).Encode(QueryResponse{
|
||
|
|
Results: []QueryResult{
|
||
|
|
{
|
||
|
|
ID: "chunk-123",
|
||
|
|
Level: "L1",
|
||
|
|
Text: "solution: restart pod",
|
||
|
|
},
|
||
|
|
},
|
||
|
|
})
|
||
|
|
}))
|
||
|
|
defer server.Close()
|
||
|
|
|
||
|
|
suite := &testsuite.WorkflowTestSuite{}
|
||
|
|
env := suite.NewTestActivityEnvironment()
|
||
|
|
|
||
|
|
svc := NewService(server.URL, "test-token", "poimen")
|
||
|
|
activities := NewActivities(svc)
|
||
|
|
|
||
|
|
env.RegisterActivity(activities.AnalyzeErrorActivity)
|
||
|
|
|
||
|
|
result, err := env.ExecuteActivity(activities.AnalyzeErrorActivity, "CrashLoopBackOff")
|
||
|
|
|
||
|
|
if err != nil {
|
||
|
|
t.Fatalf("activity failed: %v", err)
|
||
|
|
}
|
||
|
|
|
||
|
|
var records []KnowledgeRecord
|
||
|
|
if err := result.Get(&records); err != nil {
|
||
|
|
t.Fatalf("get result failed: %v", err)
|
||
|
|
}
|
||
|
|
|
||
|
|
if len(records) != 1 {
|
||
|
|
t.Errorf("expected 1 record, got %d", len(records))
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestActivityHealthCheck(t *testing.T) {
|
||
|
|
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||
|
|
w.WriteHeader(http.StatusOK)
|
||
|
|
}))
|
||
|
|
defer server.Close()
|
||
|
|
|
||
|
|
suite := &testsuite.WorkflowTestSuite{}
|
||
|
|
env := suite.NewTestActivityEnvironment()
|
||
|
|
|
||
|
|
svc := NewService(server.URL, "test-token", "poimen")
|
||
|
|
activities := NewActivities(svc)
|
||
|
|
|
||
|
|
env.RegisterActivity(activities.HealthCheckActivity)
|
||
|
|
|
||
|
|
result, err := env.ExecuteActivity(activities.HealthCheckActivity)
|
||
|
|
|
||
|
|
if err != nil {
|
||
|
|
t.Fatalf("activity failed: %v", err)
|
||
|
|
}
|
||
|
|
|
||
|
|
var healthy bool
|
||
|
|
if err := result.Get(&healthy); err != nil {
|
||
|
|
t.Fatalf("get result failed: %v", err)
|
||
|
|
}
|
||
|
|
|
||
|
|
if !healthy {
|
||
|
|
t.Error("expected healthy")
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestActivityLearnFromExecution(t *testing.T) {
|
||
|
|
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||
|
|
w.WriteHeader(http.StatusCreated)
|
||
|
|
json.NewEncoder(w).Encode(IngestResponse{ID: "chunk-456"})
|
||
|
|
}))
|
||
|
|
defer server.Close()
|
||
|
|
|
||
|
|
suite := &testsuite.WorkflowTestSuite{}
|
||
|
|
env := suite.NewTestActivityEnvironment()
|
||
|
|
|
||
|
|
svc := NewService(server.URL, "test-token", "poimen")
|
||
|
|
activities := NewActivities(svc)
|
||
|
|
|
||
|
|
env.RegisterActivity(activities.LearnFromExecutionActivity)
|
||
|
|
|
||
|
|
result, err := env.ExecuteActivity(activities.LearnFromExecutionActivity, "task-123", "success", []string{"tag1"})
|
||
|
|
|
||
|
|
if err != nil {
|
||
|
|
t.Fatalf("activity failed: %v", err)
|
||
|
|
}
|
||
|
|
|
||
|
|
var id string
|
||
|
|
if err := result.Get(&id); err != nil {
|
||
|
|
t.Fatalf("get result failed: %v", err)
|
||
|
|
}
|
||
|
|
|
||
|
|
if id != "chunk-456" {
|
||
|
|
t.Errorf("expected chunk-456, got %s", id)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestActivityDocumentDecision(t *testing.T) {
|
||
|
|
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||
|
|
w.WriteHeader(http.StatusCreated)
|
||
|
|
json.NewEncoder(w).Encode(IngestResponse{ID: "chunk-789"})
|
||
|
|
}))
|
||
|
|
defer server.Close()
|
||
|
|
|
||
|
|
suite := &testsuite.WorkflowTestSuite{}
|
||
|
|
env := suite.NewTestActivityEnvironment()
|
||
|
|
|
||
|
|
svc := NewService(server.URL, "test-token", "poimen")
|
||
|
|
activities := NewActivities(svc)
|
||
|
|
|
||
|
|
env.RegisterActivity(activities.DocumentDecisionActivity)
|
||
|
|
|
||
|
|
result, err := env.ExecuteActivity(
|
||
|
|
activities.DocumentDecisionActivity,
|
||
|
|
"scaling",
|
||
|
|
"scale to 5 replicas",
|
||
|
|
"high CPU usage",
|
||
|
|
)
|
||
|
|
|
||
|
|
if err != nil {
|
||
|
|
t.Fatalf("activity failed: %v", err)
|
||
|
|
}
|
||
|
|
|
||
|
|
var id string
|
||
|
|
if err := result.Get(&id); err != nil {
|
||
|
|
t.Fatalf("get result failed: %v", err)
|
||
|
|
}
|
||
|
|
|
||
|
|
if id != "chunk-789" {
|
||
|
|
t.Errorf("expected chunk-789, got %s", id)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestActivityOptions(t *testing.T) {
|
||
|
|
opts := DefaultActivityOptions()
|
||
|
|
|
||
|
|
if opts.RetryAttempts != 3 {
|
||
|
|
t.Errorf("expected 3 retry attempts, got %d", opts.RetryAttempts)
|
||
|
|
}
|
||
|
|
|
||
|
|
if opts.StartTimeout == 0 {
|
||
|
|
t.Error("expected non-zero start timeout")
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestActivityError(t *testing.T) {
|
||
|
|
err := &MemoryActivityError{
|
||
|
|
ActivityName: "test-activity",
|
||
|
|
Attempt: 2,
|
||
|
|
Err: context.Canceled,
|
||
|
|
}
|
||
|
|
|
||
|
|
msg := err.Error()
|
||
|
|
if msg == "" {
|
||
|
|
t.Error("expected error message")
|
||
|
|
}
|
||
|
|
|
||
|
|
if !contains(msg, "test-activity") {
|
||
|
|
t.Error("expected activity name in error")
|
||
|
|
}
|
||
|
|
|
||
|
|
if !contains(msg, "attempt 2") {
|
||
|
|
t.Error("expected attempt number in error")
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func contains(s, substr string) bool {
|
||
|
|
for i := 0; i < len(s)-len(substr)+1; i++ {
|
||
|
|
if s[i:i+len(substr)] == substr {
|
||
|
|
return true
|
||
|
|
}
|
||
|
|
}
|
||
|
|
return false
|
||
|
|
}
|