projection_test.go raw
1 package projection
2
3 import (
4 "testing"
5
6 "git.mleku.dev/mleku/dendrite/pkg/permutation"
7 "git.mleku.dev/mleku/dendrite/pkg/state"
8 )
9
10 func TestVertexTrigramRoundTrip(t *testing.T) {
11 for v := Vertex(0); v < VertexCount; v++ {
12 tri := v.Trigram()
13 if uint8(tri) != uint8(v) {
14 t.Errorf("vertex %d: trigram = %d, want %d", v, tri, v)
15 }
16 }
17 }
18
19 func TestPackUnpack(t *testing.T) {
20 for v := Vertex(0); v < VertexCount; v++ {
21 for k := Key(0); k < KeyCount; k++ {
22 p := Pack(v, k)
23 if p.Vertex() != v {
24 t.Errorf("Pack(%d,%d).Vertex() = %d", v, k, p.Vertex())
25 }
26 if p.Key() != k {
27 t.Errorf("Pack(%d,%d).Key() = %d", v, k, p.Key())
28 }
29 }
30 }
31 }
32
33 func TestProjectionCount(t *testing.T) {
34 // 8 vertices × 8 keys = 64 projections.
35 seen := make(map[Projection]bool)
36 for v := Vertex(0); v < VertexCount; v++ {
37 for k := Key(0); k < KeyCount; k++ {
38 seen[Pack(v, k)] = true
39 }
40 }
41 if len(seen) != ProjectionCount {
42 t.Errorf("unique projections = %d, want %d", len(seen), ProjectionCount)
43 }
44 }
45
46 func TestKeyPermutation(t *testing.T) {
47 cases := []struct {
48 key Key
49 perm permutation.Perm
50 }{
51 {KeyFaceXY, permutation.Identity},
52 {KeyFaceXZ, permutation.Swap12},
53 {KeyFaceYZ, permutation.Swap02},
54 {KeyEdgeBias, permutation.Swap01},
55 {KeyVertexA, permutation.Cycle012},
56 {KeyVertexB, permutation.Cycle021},
57 // Collapse keys alias to existing permutations.
58 {KeyCollapseA, permutation.Identity},
59 {KeyCollapseB, permutation.Swap12},
60 }
61 for _, tc := range cases {
62 got := tc.key.Permutation()
63 if got != tc.perm {
64 t.Errorf("Key(%d).Permutation() = %v, want %v", tc.key, got, tc.perm)
65 }
66 }
67 }
68
69 func TestKeyOrder(t *testing.T) {
70 cases := []struct {
71 key Key
72 order int
73 }{
74 {KeyFaceXY, 2},
75 {KeyFaceXZ, 2},
76 {KeyFaceYZ, 2},
77 {KeyEdgeBias, 2},
78 {KeyVertexA, 3},
79 {KeyVertexB, 3},
80 {KeyCollapseA, 1},
81 {KeyCollapseB, 1},
82 }
83 for _, tc := range cases {
84 got := tc.key.Order()
85 if got != tc.order {
86 t.Errorf("Key(%d).Order() = %d, want %d", tc.key, got, tc.order)
87 }
88 }
89 }
90
91 func TestCollapseKeys(t *testing.T) {
92 for k := Key(0); k < KeyCount; k++ {
93 isCollapse := k.IsCollapse()
94 wantCollapse := k >= KeyCollapseA
95 if isCollapse != wantCollapse {
96 t.Errorf("Key(%d).IsCollapse() = %v, want %v", k, isCollapse, wantCollapse)
97 }
98 }
99 }
100
101 func TestVisibleEdgesOrder3(t *testing.T) {
102 // Vertex-on projection (order 3) should show all 12 edges.
103 edges := VisibleEdges(KeyVertexA)
104 if len(edges) != 12 {
105 t.Errorf("VertexA visible edges = %d, want 12", len(edges))
106 }
107 edges = VisibleEdges(KeyVertexB)
108 if len(edges) != 12 {
109 t.Errorf("VertexB visible edges = %d, want 12", len(edges))
110 }
111 }
112
113 func TestVisibleEdgesCollapse(t *testing.T) {
114 // Collapse projections should show fewer edges.
115 edgesA := VisibleEdges(KeyCollapseA)
116 edgesB := VisibleEdges(KeyCollapseB)
117 if len(edgesA) >= 12 {
118 t.Errorf("CollapseA should show fewer than 12 edges, got %d", len(edgesA))
119 }
120 if len(edgesB) >= 12 {
121 t.Errorf("CollapseB should show fewer than 12 edges, got %d", len(edgesB))
122 }
123 }
124
125 func TestPathCountPositive(t *testing.T) {
126 // Every non-collapse key should have positive path count.
127 for k := Key(0); k < KeyCount; k++ {
128 pc := PathCount(k)
129 edges := VisibleEdges(k)
130 if len(edges) > 0 && pc == 0 {
131 t.Errorf("Key(%d) has %d edges but PathCount = 0", k, len(edges))
132 }
133 }
134 }
135
136 func TestProjectionPermutationApplied(t *testing.T) {
137 // Verify that applying a projection key's permutation to a trigram
138 // produces a valid (different or same) trigram.
139 for k := Key(0); k < KeyCount; k++ {
140 p := k.Permutation()
141 for tri := state.Trigram(0); tri < 8; tri++ {
142 result := p.ApplyTrigram(tri)
143 if result > 7 {
144 t.Errorf("Key(%d) perm applied to trigram %d gave invalid %d", k, tri, result)
145 }
146 }
147 }
148 }
149
150 func TestEncodeFullEncoding(t *testing.T) {
151 enc := Encode(V101, KeyVertexA, 42)
152 if enc.Proj.Vertex() != V101 {
153 t.Errorf("vertex = %d, want %d", enc.Proj.Vertex(), V101)
154 }
155 if enc.Proj.Key() != KeyVertexA {
156 t.Errorf("key = %d, want %d", enc.Proj.Key(), KeyVertexA)
157 }
158 if enc.Path != 42 {
159 t.Errorf("path = %d, want 42", enc.Path)
160 }
161 }
162
163 func TestVertexString(t *testing.T) {
164 if V000.String() != "Earth(000)" {
165 t.Errorf("V000.String() = %q", V000.String())
166 }
167 if V111.String() != "Mountain(111)" {
168 t.Errorf("V111.String() = %q", V111.String())
169 }
170 }
171
172 func TestKeyString(t *testing.T) {
173 if KeyFaceXY.String() != "FaceXY" {
174 t.Errorf("KeyFaceXY.String() = %q", KeyFaceXY.String())
175 }
176 if KeyCollapseA.String() != "CollapseA" {
177 t.Errorf("KeyCollapseA.String() = %q", KeyCollapseA.String())
178 }
179 }
180