package memory import ( "context" "encoding/json" "net/http" "net/http/httptest" "testing" ) func TestServiceCreateKnowledge(t *testing.T) { server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { if r.URL.Path != "/memory/ingest" { t.Errorf("unexpected path: %s", r.URL.Path) } var req IngestRequest if err := json.NewDecoder(r.Body).Decode(&req); err != nil { t.Fatalf("decode request: %v", err) } if req.Project != "poimen" { t.Errorf("expected project poimen, got %s", req.Project) } w.WriteHeader(http.StatusCreated) json.NewEncoder(w).Encode(IngestResponse{ ID: "chunk-123", QueueStatus: "pending", }) })) defer server.Close() svc := NewService(server.URL, "test-token", "poimen") id, err := svc.CreateKnowledge(context.Background(), &KnowledgeRecord{ Content: "test knowledge", Level: "L1", }) if err != nil { t.Fatalf("create knowledge failed: %v", err) } if id != "chunk-123" { t.Errorf("expected ID chunk-123, got %s", id) } } func TestServiceRetrieveKnowledge(t *testing.T) { server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { if r.URL.Path != "/memory/query" { t.Errorf("unexpected path: %s", r.URL.Path) } w.WriteHeader(http.StatusOK) json.NewEncoder(w).Encode(QueryResponse{ Query: "test", Results: []QueryResult{ { ID: "chunk-123", Level: "L1", Score: 0.95, SemanticScore: 0.96, LexicalScore: 0.94, Text: "knowledge content", Breadcrumb: "path > to > doc", Source: "test", }, }, TotalHits: 1, SearchTimeMS: 50, }) })) defer server.Close() svc := NewService(server.URL, "test-token", "poimen") records, err := svc.RetrieveKnowledge(context.Background(), "test", nil) if err != nil { t.Fatalf("retrieve knowledge failed: %v", err) } if len(records) != 1 { t.Errorf("expected 1 record, got %d", len(records)) } if records[0].Content != "knowledge content" { t.Errorf("unexpected content") } meta := records[0].Metadata if score, ok := meta["score"].(float32); ok { if score != 0.95 { t.Errorf("expected score 0.95, got %f", score) } } } func TestServiceRetrieveContext(t *testing.T) { server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { if r.URL.Path != "/memory/context" { t.Errorf("unexpected path: %s", r.URL.Path) } w.WriteHeader(http.StatusOK) json.NewEncoder(w).Encode(ContextResponse{ Tier: 1, Lessons: []ContextLesson{ { Tier: 1, Level: "L1", Score: 1.0, Text: "first lesson", MatchedKind: "signature", }, { Tier: 2, Level: "L2", Score: 0.87, Text: "second lesson", }, }, Skills: []ContextSkill{ { Name: "debug-skill", Why: "tier 1 matched", }, }, Budget: ContextBudget{ Requested: 8192, Used: 2048, Dropped: 0, }, }) })) defer server.Close() svc := NewService(server.URL, "test-token", "poimen") ctx, err := svc.RetrieveContext(context.Background(), "kubectl", "debug-pod", 8192) if err != nil { t.Fatalf("retrieve context failed: %v", err) } if ctx.Tier != 1 { t.Errorf("expected tier 1, got %d", ctx.Tier) } if len(ctx.Lessons) != 2 { t.Errorf("expected 2 lessons, got %d", len(ctx.Lessons)) } if len(ctx.Skills) != 1 { t.Errorf("expected 1 skill, got %d", len(ctx.Skills)) } if ctx.BudgetUsed != 2048 { t.Errorf("expected budget used 2048, got %d", ctx.BudgetUsed) } } func TestServiceGetVault(t *testing.T) { server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { if r.URL.Path != "/memory/vault" { t.Errorf("unexpected path: %s", r.URL.Path) } w.WriteHeader(http.StatusOK) json.NewEncoder(w).Encode(VaultResponse{ Project: "poimen", TotalRecords: 100, Files: []VaultFile{ { Path: "docs/guide.md", Title: "Guide", Level: "L1", RecordCount: 25, }, { Path: "reference/api.md", Title: "API", Level: "R", RecordCount: 75, }, }, }) })) defer server.Close() svc := NewService(server.URL, "test-token", "poimen") files, err := svc.GetVault(context.Background()) if err != nil { t.Fatalf("get vault failed: %v", err) } if len(files) != 2 { t.Errorf("expected 2 files, got %d", len(files)) } if files[0].Title != "Guide" { t.Errorf("expected title Guide, got %s", files[0].Title) } } func TestServiceIsHealthy(t *testing.T) { server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.WriteHeader(http.StatusOK) })) defer server.Close() svc := NewService(server.URL, "test-token", "poimen") if !svc.IsHealthy(context.Background()) { t.Error("expected service to be healthy") } } func TestServiceUpdateKnowledge(t *testing.T) { callCount := 0 server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { callCount++ if r.URL.Path != "/memory/ingest" { t.Errorf("unexpected path: %s", r.URL.Path) } w.WriteHeader(http.StatusCreated) json.NewEncoder(w).Encode(IngestResponse{ ID: "chunk-123", QueueStatus: "pending", }) })) defer server.Close() svc := NewService(server.URL, "test-token", "poimen") record := &KnowledgeRecord{ ID: "chunk-123", Content: "updated knowledge", Level: "L1", } id, err := svc.UpdateKnowledge(context.Background(), record) if err != nil { t.Fatalf("update knowledge failed: %v", err) } if id != "chunk-123" { t.Errorf("expected ID chunk-123, got %s", id) } if callCount != 1 { t.Errorf("expected 1 call, got %d", callCount) } }