package cartography import ( "os" "path/filepath" "strings" "testing" ) func TestSplitCamelCase(t *testing.T) { tests := []struct { in string want []string }{ {"ExtractSelfKnowledge", []string{"extract", "self", "knowledge"}}, {"Bond", []string{"bond"}}, {"A", nil}, // single char filtered out {"goRoot", []string{"go", "root"}}, {"HTTPServer", []string{"h", "t", "t", "p", "server"}}, // not perfect but acceptable } for _, tt := range tests { got := splitCamelCase(tt.in) // Filter single chars for comparison. var filtered []string for _, w := range got { if len(w) >= 2 { filtered = append(filtered, w) } } if len(filtered) == 0 { filtered = nil } var wantFiltered []string for _, w := range tt.want { if len(w) >= 2 { wantFiltered = append(wantFiltered, w) } } if len(wantFiltered) == 0 { wantFiltered = nil } if len(filtered) != len(wantFiltered) { t.Errorf("splitCamelCase(%q) = %v, want %v", tt.in, filtered, wantFiltered) } } } func TestTypeBaseName(t *testing.T) { tests := []struct { in, want string }{ {"*lattice.Lattice", "lattice"}, {"[]int", "int"}, {"string", "string"}, {"*Node", "node"}, {"context.Context", "context"}, } for _, tt := range tests { got := typeBaseName(tt.in) if got != tt.want { t.Errorf("typeBaseName(%q) = %q, want %q", tt.in, got, tt.want) } } } func TestExtractAll_LiveCodebase(t *testing.T) { // Extract from the actual dendrite project. root := findProjectRoot(t) atlas, err := ExtractAll(root) if err != nil { t.Fatal(err) } if atlas.TotalEntries == 0 { t.Fatal("expected entries from live codebase, got 0") } // Should have multiple packages. pkgs := atlas.Packages() if len(pkgs) < 5 { t.Errorf("expected at least 5 packages, got %d: %v", len(pkgs), pkgs) } // Should have the lattice package. latticeEntries := atlas.LookupPackage("lattice") if len(latticeEntries) == 0 { t.Error("expected entries in lattice package") } // Should find a known function. e := atlas.LookupGo("lattice.New") if e == nil { // Try NewLattice or similar. for _, entry := range latticeEntries { if entry.Kind == "func" && strings.Contains(entry.Name, "New") { e = entry break } } } if e != nil { if e.Description == "" { t.Error("expected non-empty description for lattice entry") } if e.Confidence != 0.3 { t.Errorf("expected mechanical confidence 0.3, got %.1f", e.Confidence) } } t.Logf("atlas: %d entries across %d packages, mean confidence %.2f", atlas.TotalEntries, len(pkgs), atlas.MeanConfidence) } func TestExtractTests_LiveCodebase(t *testing.T) { root := findProjectRoot(t) atlas, err := ExtractAll(root) if err != nil { t.Fatal(err) } before := countTested(atlas) if err := ExtractTests(atlas, root); err != nil { t.Fatal(err) } after := countTested(atlas) if after <= before { t.Error("expected test extraction to associate some tests") } // Check that confidence was bumped for tested entries. for _, e := range atlas.Entries { if e.HasTest && e.Source == "mechanical" && e.Confidence < 0.5 { t.Errorf("%s has test but confidence %.1f < 0.5", e.ID, e.Confidence) } } t.Logf("entries with tests: %d/%d", after, atlas.TotalEntries) } func TestLookupEnglish(t *testing.T) { atlas := NewAtlas() atlas.Add(&Entry{ ID: "lattice.Bond", Kind: "method", Package: "lattice", Name: "Bond", Description: "Bonds an element to a lattice node.", Concepts: []string{"lattice", "bond", "element"}, }) atlas.Add(&Entry{ ID: "grow.Run", Kind: "func", Package: "grow", Name: "Run", Description: "Runs the growth engine with Brownian walkers.", Concepts: []string{"grow", "run", "brownian", "walker"}, }) atlas.BuildIndexes() // Search for "bond". results := atlas.LookupEnglish("bond element") if len(results) == 0 { t.Fatal("expected results for 'bond element'") } if results[0].ID != "lattice.Bond" { t.Errorf("expected lattice.Bond first, got %s", results[0].ID) } // Search for "brownian". results = atlas.LookupEnglish("brownian walker") if len(results) == 0 { t.Fatal("expected results for 'brownian walker'") } if results[0].ID != "grow.Run" { t.Errorf("expected grow.Run first, got %s", results[0].ID) } } func TestMerge_PreservesOracle(t *testing.T) { old := NewAtlas() old.Add(&Entry{ ID: "lattice.Bond", Kind: "method", Package: "lattice", Name: "Bond", Description: "Oracle says: bonds element with constraint check.", Contract: "Takes *Node and Element, returns bool.", Confidence: 0.7, Source: "oracle", Revision: 5, }) fresh := NewAtlas() fresh.Add(&Entry{ ID: "lattice.Bond", Kind: "method", Package: "lattice", Name: "Bond", Description: "Method Bond on *Node takes (e Element) returns (bool).", Signature: "func (*Node) Bond(e Element) bool", Confidence: 0.3, Source: "mechanical", }) old.Merge(fresh) e := old.Entries["lattice.Bond"] if e == nil { t.Fatal("entry lost during merge") } // Oracle description should be preserved. if !strings.Contains(e.Description, "Oracle says") { t.Error("oracle description lost during merge") } // But mechanical signature should be updated. if e.Signature != "func (*Node) Bond(e Element) bool" { t.Errorf("signature not updated: %s", e.Signature) } if e.Confidence != 0.7 { t.Errorf("confidence should stay 0.7, got %.1f", e.Confidence) } } func TestSummary(t *testing.T) { atlas := NewAtlas() atlas.Add(&Entry{ ID: "lattice.New", Kind: "func", Package: "lattice", Name: "New", Exported: true, Signature: "func New() *Lattice", Description: "Creates a new empty lattice structure.", }) atlas.Add(&Entry{ ID: "lattice.Node", Kind: "type", Package: "lattice", Name: "Node", Exported: true, Signature: "type Node", Description: "A position in the lattice with constraint envelope.", }) atlas.BuildIndexes() summary := atlas.Summary(0) if !strings.Contains(summary, "Package lattice") { t.Error("summary missing package header") } if !strings.Contains(summary, "func New()") { t.Error("summary missing function signature") } } func TestSaveAndLoad(t *testing.T) { dir := t.TempDir() path := filepath.Join(dir, "atlas.json") atlas := NewAtlas() atlas.Add(&Entry{ ID: "test.Foo", Kind: "func", Package: "test", Name: "Foo", Description: "Does foo.", Concepts: []string{"foo", "test"}, Confidence: 0.3, }) if err := atlas.Save(path); err != nil { t.Fatal(err) } loaded, err := Load(path) if err != nil { t.Fatal(err) } if loaded.TotalEntries != 1 { t.Errorf("expected 1 entry, got %d", loaded.TotalEntries) } e := loaded.Entries["test.Foo"] if e == nil { t.Fatal("entry not found after load") } if e.Description != "Does foo." { t.Errorf("description mismatch: %q", e.Description) } // Indexes should be rebuilt. results := loaded.LookupEnglish("foo") if len(results) == 0 { t.Error("index not rebuilt after load") } } func TestParseEnrichResponse(t *testing.T) { entry := &Entry{ID: "test.Foo"} answer := `DESCRIPTION: This function computes the hash of its input. It uses SHA-256 for consistency. CONTRACT: Takes a byte slice, returns a 32-byte hash and nil error. Returns error if input is nil. EDGE CASES: Nil input returns ErrNilInput. Empty input returns hash of empty string. VALIDATION: Verify hash of "hello" matches known SHA-256 digest.` parseEnrichResponse(entry, answer) if !strings.Contains(entry.Description, "SHA-256") { t.Errorf("description not parsed: %q", entry.Description) } if !strings.Contains(entry.Contract, "32-byte hash") { t.Errorf("contract not parsed: %q", entry.Contract) } if !strings.Contains(entry.EdgeCases, "ErrNilInput") { t.Errorf("edge cases not parsed: %q", entry.EdgeCases) } if !strings.Contains(entry.Validation, "SHA-256 digest") { t.Errorf("validation not parsed: %q", entry.Validation) } } // findProjectRoot walks up from the test file to find the go.mod. func findProjectRoot(t *testing.T) string { t.Helper() dir, err := os.Getwd() if err != nil { t.Fatal(err) } for { if _, err := os.Stat(filepath.Join(dir, "go.mod")); err == nil { return dir } parent := filepath.Dir(dir) if parent == dir { t.Fatal("could not find project root (no go.mod)") } dir = parent } } func countTested(atlas *Atlas) int { n := 0 for _, e := range atlas.Entries { if e.HasTest { n++ } } return n }