372 lines
8.2 KiB
Go
372 lines
8.2 KiB
Go
package routing
|
|||
|
|
|
||
|
|
import (
|
||
|
|
"os"
|
||
|
|
"testing"
|
||
|
|
)
|
||
|
|
|
||
|
|
func getKBPath() string {
|
||
|
|
// Try direct name (when running from this directory)
|
||
|
|
if _, err := os.Stat("activity_knowledge_base.json"); err == nil {
|
||
|
|
return "activity_knowledge_base.json"
|
||
|
|
}
|
||
|
|
// Try relative path
|
||
|
|
if _, err := os.Stat("./internal/routing/activity_knowledge_base.json"); err == nil {
|
||
|
|
return "./internal/routing/activity_knowledge_base.json"
|
||
|
|
}
|
||
|
|
return ""
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestLoadKnowledgeBase(t *testing.T) {
|
||
|
|
kbPath := getKBPath()
|
||
|
|
if kbPath == "" {
|
||
|
|
t.Skip("Knowledge base file not found, skipping test")
|
||
|
|
}
|
||
|
|
|
||
|
|
kb, err := LoadKnowledgeBase(kbPath)
|
||
|
|
if err != nil {
|
||
|
|
t.Fatalf("Failed to load knowledge base: %v", err)
|
||
|
|
}
|
||
|
|
|
||
|
|
if kb == nil {
|
||
|
|
t.Error("Knowledge base is nil")
|
||
|
|
}
|
||
|
|
|
||
|
|
if kb.Version == "" {
|
||
|
|
t.Error("Knowledge base version is empty")
|
||
|
|
}
|
||
|
|
|
||
|
|
if len(kb.Activities) == 0 {
|
||
|
|
t.Error("Knowledge base has no activities")
|
||
|
|
}
|
||
|
|
|
||
|
|
if len(kb.byName) != len(kb.Activities) {
|
||
|
|
t.Errorf("Index size (%d) doesn't match activities (%d)", len(kb.byName), len(kb.Activities))
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestGetActivity(t *testing.T) {
|
||
|
|
kbPath := getKBPath()
|
||
|
|
if kbPath == "" {
|
||
|
|
t.Skip("Knowledge base file not found, skipping test")
|
||
|
|
}
|
||
|
|
|
||
|
|
kb, err := LoadKnowledgeBase(kbPath)
|
||
|
|
if err != nil {
|
||
|
|
t.Fatalf("Failed to load knowledge base: %v", err)
|
||
|
|
}
|
||
|
|
|
||
|
|
activity := kb.GetActivity("CloneRepoActivity")
|
||
|
|
if activity == nil {
|
||
|
|
t.Error("CloneRepoActivity not found")
|
||
|
|
} else {
|
||
|
|
if activity.Name != "CloneRepoActivity" {
|
||
|
|
t.Errorf("Activity name mismatch: %s", activity.Name)
|
||
|
|
}
|
||
|
|
if activity.Description == "" {
|
||
|
|
t.Error("Activity description is empty")
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
missing := kb.GetActivity("NonExistentActivity")
|
||
|
|
if missing != nil {
|
||
|
|
t.Error("NonExistentActivity should be nil")
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestHasActivity(t *testing.T) {
|
||
|
|
kbPath := getKBPath()
|
||
|
|
if kbPath == "" {
|
||
|
|
t.Skip("Knowledge base file not found, skipping test")
|
||
|
|
}
|
||
|
|
|
||
|
|
kb, err := LoadKnowledgeBase(kbPath)
|
||
|
|
if err != nil {
|
||
|
|
t.Fatalf("Failed to load knowledge base: %v", err)
|
||
|
|
}
|
||
|
|
|
||
|
|
if !kb.HasActivity("CloneRepoActivity") {
|
||
|
|
t.Error("CloneRepoActivity should exist")
|
||
|
|
}
|
||
|
|
|
||
|
|
if kb.HasActivity("NonExistentActivity") {
|
||
|
|
t.Error("NonExistentActivity should not exist")
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestListActivities(t *testing.T) {
|
||
|
|
kbPath := getKBPath()
|
||
|
|
if kbPath == "" {
|
||
|
|
t.Skip("Knowledge base file not found, skipping test")
|
||
|
|
}
|
||
|
|
|
||
|
|
kb, err := LoadKnowledgeBase(kbPath)
|
||
|
|
if err != nil {
|
||
|
|
t.Fatalf("Failed to load knowledge base: %v", err)
|
||
|
|
}
|
||
|
|
|
||
|
|
activities := kb.ListActivities()
|
||
|
|
if len(activities) == 0 {
|
||
|
|
t.Error("ListActivities returned empty list")
|
||
|
|
}
|
||
|
|
|
||
|
|
for _, activity := range activities {
|
||
|
|
if activity.Name == "" {
|
||
|
|
t.Error("Activity name is empty")
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestListActivitiesByCategory(t *testing.T) {
|
||
|
|
kbPath := getKBPath()
|
||
|
|
if kbPath == "" {
|
||
|
|
t.Skip("Knowledge base file not found, skipping test")
|
||
|
|
}
|
||
|
|
|
||
|
|
kb, err := LoadKnowledgeBase(kbPath)
|
||
|
|
if err != nil {
|
||
|
|
t.Fatalf("Failed to load knowledge base: %v", err)
|
||
|
|
}
|
||
|
|
|
||
|
|
repoActivities := kb.ListActivitiesByCategory("repository")
|
||
|
|
if len(repoActivities) == 0 {
|
||
|
|
t.Error("No repository activities found")
|
||
|
|
}
|
||
|
|
|
||
|
|
for _, activity := range repoActivities {
|
||
|
|
if activity.Category != "repository" {
|
||
|
|
t.Errorf("Activity %s has wrong category: %s", activity.Name, activity.Category)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
unknown := kb.ListActivitiesByCategory("unknown")
|
||
|
|
if len(unknown) != 0 {
|
||
|
|
t.Error("Unknown category should return empty list")
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestGetActivityNames(t *testing.T) {
|
||
|
|
kbPath := getKBPath()
|
||
|
|
if kbPath == "" {
|
||
|
|
t.Skip("Knowledge base file not found, skipping test")
|
||
|
|
}
|
||
|
|
|
||
|
|
kb, err := LoadKnowledgeBase(kbPath)
|
||
|
|
if err != nil {
|
||
|
|
t.Fatalf("Failed to load knowledge base: %v", err)
|
||
|
|
}
|
||
|
|
|
||
|
|
names := kb.GetActivityNames()
|
||
|
|
if len(names) == 0 {
|
||
|
|
t.Error("GetActivityNames returned empty list")
|
||
|
|
}
|
||
|
|
|
||
|
|
found := false
|
||
|
|
for _, name := range names {
|
||
|
|
if name == "CloneRepoActivity" {
|
||
|
|
found = true
|
||
|
|
break
|
||
|
|
}
|
||
|
|
}
|
||
|
|
if !found {
|
||
|
|
t.Error("CloneRepoActivity not found in activity names")
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestGetDependencies(t *testing.T) {
|
||
|
|
kbPath := getKBPath()
|
||
|
|
if kbPath == "" {
|
||
|
|
t.Skip("Knowledge base file not found, skipping test")
|
||
|
|
}
|
||
|
|
|
||
|
|
kb, err := LoadKnowledgeBase(kbPath)
|
||
|
|
if err != nil {
|
||
|
|
t.Fatalf("Failed to load knowledge base: %v", err)
|
||
|
|
}
|
||
|
|
|
||
|
|
deps := kb.GetDependencies("AnalyzeCodeActivity")
|
||
|
|
if len(deps) == 0 {
|
||
|
|
t.Error("AnalyzeCodeActivity should have dependencies")
|
||
|
|
}
|
||
|
|
|
||
|
|
found := false
|
||
|
|
for _, dep := range deps {
|
||
|
|
if dep == "CloneRepoActivity" {
|
||
|
|
found = true
|
||
|
|
break
|
||
|
|
}
|
||
|
|
}
|
||
|
|
if !found {
|
||
|
|
t.Error("CloneRepoActivity should be a dependency of AnalyzeCodeActivity")
|
||
|
|
}
|
||
|
|
|
||
|
|
noDeps := kb.GetDependencies("CloneRepoActivity")
|
||
|
|
if len(noDeps) != 0 {
|
||
|
|
t.Error("CloneRepoActivity should have no dependencies")
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestGetTimeout(t *testing.T) {
|
||
|
|
kbPath := getKBPath()
|
||
|
|
if kbPath == "" {
|
||
|
|
t.Skip("Knowledge base file not found, skipping test")
|
||
|
|
}
|
||
|
|
|
||
|
|
kb, err := LoadKnowledgeBase(kbPath)
|
||
|
|
if err != nil {
|
||
|
|
t.Fatalf("Failed to load knowledge base: %v", err)
|
||
|
|
}
|
||
|
|
|
||
|
|
timeout := kb.GetTimeoutForActivity("CloneRepoActivity")
|
||
|
|
if timeout == "" {
|
||
|
|
t.Error("Timeout should not be empty")
|
||
|
|
}
|
||
|
|
|
||
|
|
defaultTimeout := kb.GetTimeoutForActivity("NonExistent")
|
||
|
|
if defaultTimeout != "5m" {
|
||
|
|
t.Errorf("Default timeout should be 5m, got %s", defaultTimeout)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestGetRetryPolicy(t *testing.T) {
|
||
|
|
kbPath := getKBPath()
|
||
|
|
if kbPath == "" {
|
||
|
|
t.Skip("Knowledge base file not found, skipping test")
|
||
|
|
}
|
||
|
|
|
||
|
|
kb, err := LoadKnowledgeBase(kbPath)
|
||
|
|
if err != nil {
|
||
|
|
t.Fatalf("Failed to load knowledge base: %v", err)
|
||
|
|
}
|
||
|
|
|
||
|
|
policy := kb.GetRetryPolicyForActivity("AnalyzeCodeActivity")
|
||
|
|
if policy == nil {
|
||
|
|
t.Error("Retry policy should not be nil")
|
||
|
|
} else {
|
||
|
|
if policy.MaxAttempts < 2 {
|
||
|
|
t.Errorf("Flaky activity should have multiple retries, got %d", policy.MaxAttempts)
|
||
|
|
}
|
||
|
|
if policy.BackoffRate == 0 {
|
||
|
|
t.Error("Backoff rate should be set")
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
stablePolicy := kb.GetRetryPolicyForActivity("CloneRepoActivity")
|
||
|
|
if stablePolicy == nil {
|
||
|
|
t.Error("Retry policy should not be nil")
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestIsFlaky(t *testing.T) {
|
||
|
|
kbPath := getKBPath()
|
||
|
|
if kbPath == "" {
|
||
|
|
t.Skip("Knowledge base file not found, skipping test")
|
||
|
|
}
|
||
|
|
|
||
|
|
kb, err := LoadKnowledgeBase(kbPath)
|
||
|
|
if err != nil {
|
||
|
|
t.Fatalf("Failed to load knowledge base: %v", err)
|
||
|
|
}
|
||
|
|
|
||
|
|
if !kb.IsFlaky("AnalyzeCodeActivity") {
|
||
|
|
t.Error("AnalyzeCodeActivity should be marked as flaky")
|
||
|
|
}
|
||
|
|
|
||
|
|
if kb.IsFlaky("CloneRepoActivity") {
|
||
|
|
t.Error("CloneRepoActivity should not be marked as flaky")
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestGetNotes(t *testing.T) {
|
||
|
|
kbPath := getKBPath()
|
||
|
|
if kbPath == "" {
|
||
|
|
t.Skip("Knowledge base file not found, skipping test")
|
||
|
|
}
|
||
|
|
|
||
|
|
kb, err := LoadKnowledgeBase(kbPath)
|
||
|
|
if err != nil {
|
||
|
|
t.Fatalf("Failed to load knowledge base: %v", err)
|
||
|
|
}
|
||
|
|
|
||
|
|
notes := kb.GetNotes("AnalyzeCodeActivity")
|
||
|
|
if notes == "" {
|
||
|
|
t.Error("Notes should not be empty")
|
||
|
|
}
|
||
|
|
|
||
|
|
missingNotes := kb.GetNotes("NonExistent")
|
||
|
|
if missingNotes != "" {
|
||
|
|
t.Error("Non-existent activity should have empty notes")
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestValidate(t *testing.T) {
|
||
|
|
kbPath := getKBPath()
|
||
|
|
if kbPath == "" {
|
||
|
|
t.Skip("Knowledge base file not found, skipping test")
|
||
|
|
}
|
||
|
|
|
||
|
|
kb, err := LoadKnowledgeBase(kbPath)
|
||
|
|
if err != nil {
|
||
|
|
t.Fatalf("Failed to load knowledge base: %v", err)
|
||
|
|
}
|
||
|
|
|
||
|
|
if err := kb.Validate(); err != nil {
|
||
|
|
t.Fatalf("Knowledge base validation failed: %v", err)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestString(t *testing.T) {
|
||
|
|
kbPath := getKBPath()
|
||
|
|
if kbPath == "" {
|
||
|
|
t.Skip("Knowledge base file not found, skipping test")
|
||
|
|
}
|
||
|
|
|
||
|
|
kb, err := LoadKnowledgeBase(kbPath)
|
||
|
|
if err != nil {
|
||
|
|
t.Fatalf("Failed to load knowledge base: %v", err)
|
||
|
|
}
|
||
|
|
|
||
|
|
str := kb.String()
|
||
|
|
if str == "" {
|
||
|
|
t.Error("String() returned empty string")
|
||
|
|
}
|
||
|
|
|
||
|
|
if !contains(str, "KnowledgeBase") {
|
||
|
|
t.Error("String should contain 'KnowledgeBase'")
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestPrintSummary(t *testing.T) {
|
||
|
|
kbPath := getKBPath()
|
||
|
|
if kbPath == "" {
|
||
|
|
t.Skip("Knowledge base file not found, skipping test")
|
||
|
|
}
|
||
|
|
|
||
|
|
kb, err := LoadKnowledgeBase(kbPath)
|
||
|
|
if err != nil {
|
||
|
|
t.Fatalf("Failed to load knowledge base: %v", err)
|
||
|
|
}
|
||
|
|
|
||
|
|
summary := kb.PrintSummary()
|
||
|
|
if summary == "" {
|
||
|
|
t.Error("PrintSummary() returned empty string")
|
||
|
|
}
|
||
|
|
|
||
|
|
if !contains(summary, "Activity Knowledge Base") {
|
||
|
|
t.Error("Summary should contain 'Activity Knowledge Base'")
|
||
|
|
}
|
||
|
|
|
||
|
|
if !contains(summary, "CloneRepoActivity") {
|
||
|
|
t.Error("Summary should list activities")
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func contains(str, substr string) bool {
|
||
|
|
for i := 0; i < len(str)-len(substr)+1; i++ {
|
||
|
|
if str[i:i+len(substr)] == substr {
|
||
|
|
return true
|
||
|
|
}
|
||
|
|
}
|
||
|
|
return false
|
||
|
|
}
|