package semantic import ( "testing" "github.com/kami/maven/internal/router" ) func TestValidRoute(t *testing.T) { for _, r := range AllRoutes { if !ValidRoute(r) { t.Errorf("ValidRoute(%q) = false, want true", r) } } if ValidRoute("bogus") { t.Error("ValidRoute(\"bogus\") = true, want false") } } func TestIntentToRouteMapping(t *testing.T) { cases := []struct { intent router.Intent route SemanticRoute }{ {router.IntentChat, RouteConversation}, {router.IntentQuery, RouteKnowledge}, {router.IntentAct, RouteAction}, {router.IntentReminder, RouteAction}, {router.IntentFact, RouteMemoryWrite}, {router.IntentNote, RouteMemoryWrite}, {router.IntentSystem, RouteSystem}, {router.Intent("unknown"), RouteUncertain}, {router.Intent(""), RouteUncertain}, } for _, c := range cases { got := IntentToRoute(c.intent) if got != c.route { t.Errorf("IntentToRoute(%q) = %q, want %q", c.intent, got, c.route) } } } func TestLoadCorpus(t *testing.T) { exs, err := LoadCorpus() if err != nil { t.Fatal(err) } if len(exs) == 0 { t.Fatal("corpus is empty") } for _, e := range exs { if !ValidRoute(e.Route) { t.Errorf("example %q has invalid route %q", e.SourceID, e.Route) } if e.Source == "" { t.Errorf("example %q has empty source", e.SourceID) } if e.SplitGroup == "" { t.Errorf("example %q has empty split_group", e.SourceID) } } fastPath, residual := SplitCounts(exs) if fastPath == 0 { t.Error("no fast_path_resolved examples in corpus") } if residual == 0 { t.Error("no residual examples in corpus") } t.Logf("corpus: %d examples (%d fast-path, %d residual)", len(exs), fastPath, residual) } func TestCorpusByRoute(t *testing.T) { exs, err := LoadCorpus() if err != nil { t.Fatal(err) } byRoute := ByRoute(exs) for _, route := range AllRoutes { count := len(byRoute[route]) if count == 0 { t.Errorf("no examples for route %q", route) } t.Logf(" %s: %d examples", route, count) } } func TestSplitByFamily(t *testing.T) { exs, err := LoadCorpus() if err != nil { t.Fatal(err) } train, eval := SplitByFamily(exs, 0.8) total := len(train) + len(eval) if total != len(exs) { t.Errorf("split lost examples: train=%d eval=%d total=%d, want %d", len(train), len(eval), total, len(exs)) } trainGroups := map[string]bool{} for _, e := range train { trainGroups[e.SplitGroup] = true } for _, e := range eval { if trainGroups[e.SplitGroup] { t.Errorf("split_group %q leaked across train/eval (example %q)", e.SplitGroup, e.SourceID) } } t.Logf("split: %d train, %d eval", len(train), len(eval)) } func TestFamilyID(t *testing.T) { id1 := FamilyID("ru-act-002", "negation") id2 := FamilyID("ru-act-002", "question") id3 := FamilyID("ru-act-002", "") id4 := FamilyID("ru-act-001", "negation") if id1 == id2 { t.Error("different transforms produced same FamilyID") } if id1 == id3 { t.Error("transform and base produced same FamilyID") } if id1 == id4 { t.Error("different base IDs produced same FamilyID") } }