package organ import ( "testing" "git.mleku.dev/mleku/dendrite/pkg/axiom" "git.mleku.dev/mleku/dendrite/pkg/dissolve" "git.mleku.dev/mleku/dendrite/pkg/lattice" "git.mleku.dev/mleku/dendrite/pkg/ratio" ) func TestDirectiveElementInterface(t *testing.T) { d := NewDirectiveElement("evolve faster") // Implements axiom.Element. var _ axiom.Element = d if d.Type() != "directive" { t.Errorf("expected type 'directive', got %q", d.Type()) } if d.Value().(string) != "evolve faster" { t.Errorf("expected value 'evolve faster', got %q", d.Value()) } // Implements axiom.StickyElement. var _ axiom.StickyElement = d if !d.IsSticky() { t.Error("default directive should be sticky") } // Non-sticky directive. d2 := DirectiveElement{Directive: Directive{Text: "test", Sticky: false}} if d2.IsSticky() { t.Error("non-sticky directive should not be sticky") } } func TestDirectiveConstraint(t *testing.T) { c := DirectiveConstraint{} if c.Tag() != "directive" { t.Errorf("expected tag 'directive', got %q", c.Tag()) } // Should admit DirectiveElement. d := NewDirectiveElement("test") if !c.Admits(d) { t.Error("should admit DirectiveElement") } // Should not admit other element types. other := mockElement{typ: "fragment", val: "foo"} if c.Admits(other) { t.Error("should not admit non-directive element") } } // mockElement implements axiom.Element for testing. type mockElement struct { typ string val any } func (m mockElement) Type() string { return m.typ } func (m mockElement) Value() any { return m.val } func TestTokenizeDirective(t *testing.T) { tokens := TokenizeDirective("learn to compile Go code", true, ratio.One) expected := []string{"learn", "to", "compile", "Go", "code"} if len(tokens) != len(expected) { t.Fatalf("expected %d tokens, got %d", len(expected), len(tokens)) } for i, tok := range tokens { if tok.Directive.Text != expected[i] { t.Errorf("token %d: expected %q, got %q", i, expected[i], tok.Directive.Text) } if !tok.IsSticky() { t.Errorf("token %d should be sticky", i) } if !tok.Directive.Priority.Equal(ratio.One) { t.Errorf("token %d priority: expected 1/1, got %s", i, tok.Directive.Priority) } } // Non-sticky tokens. tokens = TokenizeDirective("soft hint", false, ratio.Half) if len(tokens) != 2 { t.Fatalf("expected 2 tokens, got %d", len(tokens)) } for _, tok := range tokens { if tok.IsSticky() { t.Error("should not be sticky") } if !tok.Directive.Priority.Equal(ratio.Half) { t.Errorf("expected priority 1/2, got %s", tok.Directive.Priority) } } } func TestTokenizeDirectiveEdgeCases(t *testing.T) { // Empty string. if tokens := TokenizeDirective("", true, ratio.One); len(tokens) != 0 { t.Errorf("empty string should produce 0 tokens, got %d", len(tokens)) } // Only whitespace. if tokens := TokenizeDirective(" \t\n ", true, ratio.One); len(tokens) != 0 { t.Errorf("whitespace should produce 0 tokens, got %d", len(tokens)) } // Single word. tokens := TokenizeDirective("optimize", true, ratio.One) if len(tokens) != 1 || tokens[0].Directive.Text != "optimize" { t.Errorf("single word: expected ['optimize'], got %v", tokens) } // Multiple spaces. tokens = TokenizeDirective("a b c", true, ratio.One) if len(tokens) != 3 { t.Errorf("multiple spaces: expected 3 tokens, got %d", len(tokens)) } } func TestStickyDirectiveSurvivesDissolution(t *testing.T) { l := lattice.New() // Create a directive site with one constraint. dirNode := l.AddNode([]axiom.Constraint{DirectiveConstraint{}}) // Bond a sticky directive. d := NewDirectiveElement("persist") if !dirNode.Bond(d) { t.Fatal("directive should bond") } // Create a regular site with a weak constraint. regNode := l.AddNode([]axiom.Constraint{mockConstraint{tag: "text", admitAll: true}}) regular := mockElement{typ: "text", val: "ephemeral"} if !regNode.Bond(regular) { t.Fatal("regular element should bond") } // Both nodes occupied. if !dirNode.Occupied() || !regNode.Occupied() { t.Fatal("both should be occupied") } // Run dissolution with a high threshold that would dissolve everything. dissolved := make(chan axiom.Element, 10) events := make(chan dissolve.Event, 10) dissolve.ScanOnce(l, dissolve.Config{Threshold: ratio.FromInt(999)}, dissolved, events) // The sticky directive should survive. if !dirNode.Occupied() { t.Error("sticky directive should survive dissolution") } // The regular element should be dissolved. if regNode.Occupied() { t.Error("regular element should be dissolved") } // One element should have been dissolved. select { case elem := <-dissolved: if elem.Type() != "text" { t.Errorf("expected dissolved element type 'text', got %q", elem.Type()) } default: t.Error("expected one dissolved element") } } func TestNonStickyDirectiveDissolvable(t *testing.T) { l := lattice.New() dirNode := l.AddNode([]axiom.Constraint{DirectiveConstraint{}}) // Bond a non-sticky directive. d := DirectiveElement{Directive: Directive{Text: "soft hint", Sticky: false}} if !dirNode.Bond(d) { t.Fatal("directive should bond") } // High threshold — should dissolve non-sticky. dissolved := make(chan axiom.Element, 10) events := make(chan dissolve.Event, 10) dissolve.ScanOnce(l, dissolve.Config{Threshold: ratio.FromInt(999)}, dissolved, events) if dirNode.Occupied() { t.Error("non-sticky directive should be dissolved") } } // mockConstraint is a simple constraint for testing. type mockConstraint struct { tag string admitAll bool } func (c mockConstraint) Tag() string { return c.tag } func (c mockConstraint) Admits(e axiom.Element) bool { return c.admitAll }