Skip to content

Commit bf850ab

Browse files
authored
Add Unit tests for UX and Engine packages (#58)
* add unit tests for engine and eval path * Expand tests for engine and eval * Test ux utils * Fix engine test panic and update coverage badge% * Remove broken contains method
1 parent 656a76f commit bf850ab

4 files changed

Lines changed: 708 additions & 1 deletion

File tree

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
# preq
2-
![Coverage](https://img.shields.io/badge/Coverage-45.2%25-orange)
2+
![Coverage](https://img.shields.io/badge/Coverage-49.43%25-orange)
33
[![Unit Tests](https://github.com/prequel-dev/cre/actions/workflows/build.yml/badge.svg)](https://github.com/prequel-dev/cre/actions/workflows/build.yml)
44
[![Unit Tests](https://github.com/prequel-dev/preq/actions/workflows/build.yml/badge.svg)](https://github.com/prequel-dev/preq/actions/workflows/build.yml)
55
[![Unit Tests](https://github.com/prequel-dev/prequel-compiler/actions/workflows/build.yml/badge.svg)](https://github.com/prequel-dev/prequel-compiler/actions/workflows/build.yml)

internal/pkg/engine/engine_test.go

Lines changed: 296 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,296 @@
1+
package engine
2+
3+
import (
4+
"context"
5+
"testing"
6+
7+
"github.com/prequel-dev/preq/internal/pkg/ux"
8+
"github.com/prequel-dev/prequel-compiler/pkg/compiler"
9+
"github.com/prequel-dev/prequel-compiler/pkg/parser"
10+
)
11+
12+
func TestNew(t *testing.T) {
13+
t.Run("creates new runtime with correct initial values", func(t *testing.T) {
14+
stop := int64(100)
15+
uxFactory := ux.NewUxEval()
16+
17+
runtime := New(stop, uxFactory)
18+
19+
if runtime == nil {
20+
t.Fatal("Expected runtime to not be nil")
21+
}
22+
if runtime.Stop != stop {
23+
t.Errorf("Expected Stop to be %d, got %d", stop, runtime.Stop)
24+
}
25+
if runtime.Ux != uxFactory {
26+
t.Error("Expected Ux to match provided factory")
27+
}
28+
if runtime.Rules == nil {
29+
t.Error("Expected Rules map to be initialized")
30+
}
31+
if len(runtime.Rules) != 0 {
32+
t.Error("Expected Rules map to be empty")
33+
}
34+
})
35+
36+
t.Run("handles nil ux factory", func(t *testing.T) {
37+
runtime := New(100, nil)
38+
if runtime == nil {
39+
t.Fatal("Expected runtime to not be nil")
40+
}
41+
if runtime.Ux != nil {
42+
t.Error("Expected Ux to be nil")
43+
}
44+
})
45+
46+
t.Run("handles zero stop value", func(t *testing.T) {
47+
runtime := New(0, ux.NewUxEval())
48+
if runtime == nil {
49+
t.Fatal("Expected runtime to not be nil")
50+
}
51+
if runtime.Stop != 0 {
52+
t.Errorf("Expected Stop to be 0, got %d", runtime.Stop)
53+
}
54+
})
55+
}
56+
57+
func TestRuntimeT_AddRules(t *testing.T) {
58+
t.Run("adds rules successfully", func(t *testing.T) {
59+
runtime := New(100, ux.NewUxEval())
60+
rules := &parser.RulesT{
61+
Rules: []parser.ParseRuleT{
62+
{
63+
Metadata: parser.ParseRuleMetadataT{
64+
Id: "test-rule-1",
65+
Hash: "hash1",
66+
},
67+
Cre: parser.ParseCreT{
68+
Id: "cre1",
69+
},
70+
},
71+
},
72+
}
73+
74+
err := runtime.AddRules(rules)
75+
if err != nil {
76+
t.Errorf("Expected no error, got %v", err)
77+
}
78+
if len(runtime.Rules) != 1 {
79+
t.Errorf("Expected 1 rule, got %d", len(runtime.Rules))
80+
}
81+
if runtime.Rules["hash1"].Id != rules.Rules[0].Cre.Id {
82+
t.Error("Expected rule ID to match")
83+
}
84+
})
85+
86+
t.Run("handles duplicate rules", func(t *testing.T) {
87+
runtime := New(100, ux.NewUxEval())
88+
rules := &parser.RulesT{
89+
Rules: []parser.ParseRuleT{
90+
{
91+
Metadata: parser.ParseRuleMetadataT{
92+
Id: "test-rule-1",
93+
Hash: "hash1",
94+
},
95+
Cre: parser.ParseCreT{
96+
Id: "cre1",
97+
},
98+
},
99+
},
100+
}
101+
102+
// Add first rule
103+
err := runtime.AddRules(rules)
104+
if err != nil {
105+
t.Errorf("Expected no error on first add, got %v", err)
106+
}
107+
108+
// Try to add duplicate rule
109+
err = runtime.AddRules(rules)
110+
if err != ErrDuplicateRule {
111+
t.Errorf("Expected ErrDuplicateRule, got %v", err)
112+
}
113+
})
114+
115+
t.Run("handles multiple rules", func(t *testing.T) {
116+
runtime := New(100, ux.NewUxEval())
117+
rules := &parser.RulesT{
118+
Rules: []parser.ParseRuleT{
119+
{
120+
Metadata: parser.ParseRuleMetadataT{
121+
Id: "test-rule-1",
122+
Hash: "hash1",
123+
},
124+
Cre: parser.ParseCreT{
125+
Id: "cre1",
126+
},
127+
},
128+
{
129+
Metadata: parser.ParseRuleMetadataT{
130+
Id: "test-rule-2",
131+
Hash: "hash2",
132+
},
133+
Cre: parser.ParseCreT{
134+
Id: "cre2",
135+
},
136+
},
137+
},
138+
}
139+
140+
err := runtime.AddRules(rules)
141+
if err != nil {
142+
t.Errorf("Expected no error, got %v", err)
143+
}
144+
if len(runtime.Rules) != 2 {
145+
t.Errorf("Expected 2 rules, got %d", len(runtime.Rules))
146+
}
147+
})
148+
149+
t.Run("handles empty rules slice", func(t *testing.T) {
150+
runtime := New(100, ux.NewUxEval())
151+
rules := &parser.RulesT{
152+
Rules: []parser.ParseRuleT{},
153+
}
154+
155+
err := runtime.AddRules(rules)
156+
if err != nil {
157+
t.Errorf("Expected no error for empty rules, got %v", err)
158+
}
159+
if len(runtime.Rules) != 0 {
160+
t.Error("Expected no rules to be added")
161+
}
162+
})
163+
}
164+
165+
func TestRuntimeT_GetCre(t *testing.T) {
166+
t.Run("returns rule when found", func(t *testing.T) {
167+
runtime := New(100, ux.NewUxEval())
168+
expectedCre := parser.ParseCreT{Id: "test-cre"}
169+
runtime.Rules["test-hash"] = expectedCre
170+
171+
cre, err := runtime.getCre("test-hash")
172+
if err != nil {
173+
t.Errorf("Expected no error, got %v", err)
174+
}
175+
if cre.Id != expectedCre.Id {
176+
t.Error("Expected CRE ID to match")
177+
}
178+
})
179+
180+
t.Run("returns error when rule not found", func(t *testing.T) {
181+
runtime := New(100, ux.NewUxEval())
182+
183+
cre, err := runtime.getCre("non-existent")
184+
if err != ErrRuleNotFound {
185+
t.Errorf("Expected ErrRuleNotFound, got %v", err)
186+
}
187+
if cre.Id != "" {
188+
t.Error("Expected empty CRE ID when rule not found")
189+
}
190+
})
191+
192+
t.Run("handles empty hash", func(t *testing.T) {
193+
runtime := New(100, ux.NewUxEval())
194+
195+
cre, err := runtime.getCre("")
196+
if err != ErrRuleNotFound {
197+
t.Errorf("Expected ErrRuleNotFound, got %v", err)
198+
}
199+
if cre.Id != "" {
200+
t.Error("Expected empty CRE ID when rule not found")
201+
}
202+
})
203+
}
204+
205+
func TestRuntimeT_Close(t *testing.T) {
206+
t.Run("closes runtime without error", func(t *testing.T) {
207+
runtime := New(100, ux.NewUxEval())
208+
err := runtime.Close()
209+
if err != nil {
210+
t.Errorf("Expected no error, got %v", err)
211+
}
212+
})
213+
214+
t.Run("handles multiple close calls", func(t *testing.T) {
215+
runtime := New(100, ux.NewUxEval())
216+
err := runtime.Close()
217+
if err != nil {
218+
t.Errorf("Expected no error on first close, got %v", err)
219+
}
220+
err = runtime.Close()
221+
if err != nil {
222+
t.Errorf("Expected no error on second close, got %v", err)
223+
}
224+
})
225+
}
226+
227+
func TestRuntimeT_Run(t *testing.T) {
228+
t.Run("handles empty sources", func(t *testing.T) {
229+
runtime := New(100, ux.NewUxEval())
230+
matchers := &RuleMatchersT{
231+
match: make(map[string]any),
232+
cb: make(map[string]compiler.CallbackT),
233+
eventSrc: make(map[string]parser.ParseEventT),
234+
}
235+
report := ux.NewReport(nil)
236+
237+
err := runtime.Run(context.Background(), matchers, []*LogData{}, report)
238+
if err != nil {
239+
t.Errorf("Expected no error, got %v", err)
240+
}
241+
})
242+
243+
t.Run("handles nil matchers", func(t *testing.T) {
244+
runtime := New(100, ux.NewUxEval())
245+
report := ux.NewReport(nil)
246+
247+
err := runtime.Run(context.Background(), nil, []*LogData{}, report)
248+
if err != nil {
249+
t.Errorf("Expected no error, got %v", err)
250+
}
251+
})
252+
253+
t.Run("handles nil report", func(t *testing.T) {
254+
runtime := New(100, ux.NewUxEval())
255+
matchers := &RuleMatchersT{
256+
match: make(map[string]any),
257+
cb: make(map[string]compiler.CallbackT),
258+
eventSrc: make(map[string]parser.ParseEventT),
259+
}
260+
261+
err := runtime.Run(context.Background(), matchers, []*LogData{}, nil)
262+
if err != nil {
263+
t.Errorf("Expected no error, got %v", err)
264+
}
265+
})
266+
267+
t.Run("handles nil context", func(t *testing.T) {
268+
runtime := New(100, ux.NewUxEval())
269+
matchers := &RuleMatchersT{
270+
match: make(map[string]any),
271+
cb: make(map[string]compiler.CallbackT),
272+
eventSrc: make(map[string]parser.ParseEventT),
273+
}
274+
report := ux.NewReport(nil)
275+
276+
err := runtime.Run(nil, matchers, []*LogData{}, report)
277+
if err != nil {
278+
t.Errorf("Expected no error, got %v", err)
279+
}
280+
})
281+
282+
t.Run("handles nil sources", func(t *testing.T) {
283+
runtime := New(100, ux.NewUxEval())
284+
matchers := &RuleMatchersT{
285+
match: make(map[string]any),
286+
cb: make(map[string]compiler.CallbackT),
287+
eventSrc: make(map[string]parser.ParseEventT),
288+
}
289+
report := ux.NewReport(nil)
290+
291+
err := runtime.Run(context.Background(), matchers, nil, report)
292+
if err != nil {
293+
t.Errorf("Expected no error, got %v", err)
294+
}
295+
})
296+
}

0 commit comments

Comments
 (0)