strategy_test.go raw
1 package strategy
2
3 import (
4 "strings"
5 "testing"
6
7 "git.mleku.dev/mleku/dendrite/pkg/axiom"
8 "git.mleku.dev/mleku/dendrite/pkg/lattice"
9 )
10
11 func TestChaptersParse(t *testing.T) {
12 chs := Chapters()
13 for i, ch := range chs {
14 if ch.Number != i+1 {
15 t.Errorf("chapter %d: got Number=%d", i+1, ch.Number)
16 }
17 if ch.Title == "" {
18 t.Errorf("chapter %d: empty title", i+1)
19 }
20 if ch.Text == "" {
21 t.Errorf("chapter %d %q: empty text", i+1, ch.Title)
22 }
23 if int(ch.Category) != i {
24 t.Errorf("chapter %d: expected category %d, got %d", i+1, i, ch.Category)
25 }
26 }
27 }
28
29 func TestChaptersHaveMaxims(t *testing.T) {
30 chs := Chapters()
31 total := 0
32 for _, ch := range chs {
33 total += len(ch.Maxims)
34 }
35 if total < 20 {
36 t.Errorf("expected at least 20 maxims across all chapters, got %d", total)
37 }
38 t.Logf("total maxims across 13 chapters: %d", total)
39 }
40
41 func TestStrategyElementInterfaces(t *testing.T) {
42 e := StrategyElement{
43 Content: "All warfare is based on deception.",
44 Ch: 1,
45 Cat: CatAssessment,
46 Lvl: LevelMaxim,
47 }
48
49 // axiom.Element
50 var elem axiom.Element = e
51 if elem.Type() != "strategy:assessment:maxim" {
52 t.Errorf("unexpected type: %s", elem.Type())
53 }
54 if elem.Value().(string) != "All warfare is based on deception." {
55 t.Errorf("unexpected value: %v", elem.Value())
56 }
57
58 // axiom.StickyElement
59 var sticky axiom.StickyElement = e
60 if !sticky.IsSticky() {
61 t.Error("strategy element should be sticky")
62 }
63
64 // axiom.LayeredElement
65 var layered axiom.LayeredElement = e
66 if layered.Layer().Name != "strategy" {
67 t.Errorf("unexpected layer: %s", layered.Layer().Name)
68 }
69 if layered.Layer().Depth != int(LevelMaxim) {
70 t.Errorf("unexpected depth: %d", layered.Layer().Depth)
71 }
72 }
73
74 func TestStrategyConstraintAdmits(t *testing.T) {
75 c := StrategyConstraint{Cat: CatAssessment, MinLevel: LevelMaxim}
76
77 // Should admit matching element.
78 good := StrategyElement{Cat: CatAssessment, Lvl: LevelMaxim}
79 if !c.Admits(good) {
80 t.Error("constraint should admit matching element")
81 }
82
83 // Should admit finer level.
84 finer := StrategyElement{Cat: CatAssessment, Lvl: LevelTactic}
85 if !c.Admits(finer) {
86 t.Error("constraint should admit finer-grained element")
87 }
88
89 // Should reject coarser level.
90 coarser := StrategyElement{Cat: CatAssessment, Lvl: LevelChapter}
91 if c.Admits(coarser) {
92 t.Error("constraint should reject coarser element")
93 }
94
95 // Should reject wrong category.
96 wrong := StrategyElement{Cat: CatIntelligence, Lvl: LevelMaxim}
97 if c.Admits(wrong) {
98 t.Error("constraint should reject wrong category")
99 }
100 }
101
102 func TestCategoryConstraint(t *testing.T) {
103 c := CategoryConstraint{}
104 if c.Tag() != "strategy" {
105 t.Errorf("unexpected tag: %s", c.Tag())
106 }
107
108 good := StrategyElement{Cat: CatForce, Lvl: LevelTactic}
109 if !c.Admits(good) {
110 t.Error("category constraint should admit any strategy element")
111 }
112 }
113
114 func TestEnzymeDigest(t *testing.T) {
115 ch := DigestEmbedded()
116
117 counts := map[Level]int{}
118 total := 0
119 for elem := range ch {
120 se, ok := elem.(StrategyElement)
121 if !ok {
122 t.Fatalf("expected StrategyElement, got %T", elem)
123 }
124 counts[se.Lvl]++
125 total++
126 }
127
128 if counts[LevelChapter] != 13 {
129 t.Errorf("expected 13 chapter elements, got %d", counts[LevelChapter])
130 }
131 if counts[LevelPrinciple] < 10 {
132 t.Errorf("expected at least 10 principle elements, got %d", counts[LevelPrinciple])
133 }
134 if counts[LevelMaxim] < 10 {
135 t.Errorf("expected at least 10 maxim elements, got %d", counts[LevelMaxim])
136 }
137
138 t.Logf("enzyme emitted %d elements: chapter=%d principle=%d maxim=%d tactic=%d",
139 total, counts[LevelChapter], counts[LevelPrinciple],
140 counts[LevelMaxim], counts[LevelTactic])
141 }
142
143 func TestSeed(t *testing.T) {
144 l := lattice.New()
145 bonded := Seed(l)
146
147 if bonded == 0 {
148 t.Error("expected at least some elements to bond")
149 }
150 if l.Size() < 260 {
151 t.Errorf("expected at least 260 nodes, got %d", l.Size())
152 }
153
154 // Check that bonded elements are sticky.
155 for _, n := range l.Nodes() {
156 if !n.Occupied() {
157 continue
158 }
159 if sticky, ok := n.Occupant().(axiom.StickyElement); ok {
160 if !sticky.IsSticky() {
161 t.Error("strategy element should be sticky")
162 }
163 }
164 }
165
166 t.Logf("seed: %d elements bonded to %d-node lattice", bonded, l.Size())
167 }
168
169 func TestSplitSentences(t *testing.T) {
170 text := "All warfare is based on deception. Hence, when able to attack, we must seem unable."
171 sentences := splitSentences(text)
172 if len(sentences) != 2 {
173 t.Errorf("expected 2 sentences, got %d", len(sentences))
174 }
175 }
176
177 func TestCategoryString(t *testing.T) {
178 if CatAssessment.String() != "assessment" {
179 t.Errorf("unexpected: %s", CatAssessment.String())
180 }
181 if CatIntelligence.String() != "intelligence" {
182 t.Errorf("unexpected: %s", CatIntelligence.String())
183 }
184 }
185
186 func TestLevelString(t *testing.T) {
187 if LevelChapter.String() != "chapter" {
188 t.Errorf("unexpected: %s", LevelChapter.String())
189 }
190 if LevelTactic.String() != "tactic" {
191 t.Errorf("unexpected: %s", LevelTactic.String())
192 }
193 }
194
195 func TestEmbeddedTextPresent(t *testing.T) {
196 if len(artOfWarText) < 1000 {
197 t.Errorf("embedded Art of War text too short: %d bytes", len(artOfWarText))
198 }
199 if !strings.Contains(artOfWarText, "## I.") {
200 t.Error("embedded text missing chapter I marker")
201 }
202 if !strings.Contains(artOfWarText, "## XIII.") {
203 t.Error("embedded text missing chapter XIII marker")
204 }
205 }
206