Skip to content

Commit 4c6ca5c

Browse files
ci(validation): add testing workflow
1 parent 14d364f commit 4c6ca5c

5 files changed

Lines changed: 185 additions & 78 deletions

File tree

.github/workflows/regex.yml

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
name: Validate Regex Patterns
1+
name: Regular Expressions
22

33
on:
44
push:
@@ -26,6 +26,4 @@ jobs:
2626
run: pwsh scripts/validateAllPatterns.ps1
2727

2828
- name: test
29-
run: |
30-
echo "TODO: Implement unit tests for all patterns"
31-
# TODO: Add test runner command here
29+
run: pwsh scripts/testPatterns.ps1

scripts/testPatterns.ps1

Lines changed: 183 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,183 @@
1+
param(
2+
[string]$YamlFilePath
3+
)
4+
5+
# Function to run tests for a single file
6+
function Test-Pattern {
7+
param([string]$FilePath)
8+
9+
$fileName = (Get-Item $FilePath).BaseName
10+
11+
try {
12+
# Read YAML content
13+
$yamlContent = Get-Content -Path $FilePath -Raw
14+
15+
# Extract pattern
16+
$patternMatch = [regex]::Match($yamlContent, 'pattern:\s*(.+)')
17+
$pattern = $patternMatch.Groups[1].Value.Trim()
18+
19+
# Create regex object with case-insensitive and multiline options
20+
$regexOptions = [System.Text.RegularExpressions.RegexOptions]::IgnoreCase -bor [System.Text.RegularExpressions.RegexOptions]::Multiline
21+
$regex = New-Object System.Text.RegularExpressions.Regex($pattern, $regexOptions)
22+
23+
# Extract tests
24+
$testsSection = [regex]::Match($yamlContent, '(?s)tests:(.*?)(?:\n\w|\z)').Groups[1].Value
25+
26+
if ([string]::IsNullOrWhiteSpace($testsSection)) {
27+
return @{
28+
File = $fileName
29+
Passed = 0
30+
Failed = 0
31+
Total = 0
32+
}
33+
}
34+
35+
# Parse each test
36+
$tests = [regex]::Matches($testsSection, '(?s)- expected:\s*(true|false).*?input:\s*(.+?)(?=\n\s*\w|\n-|\z)')
37+
38+
$passed = 0
39+
$failed = 0
40+
$failureDetails = @()
41+
42+
foreach ($test in $tests) {
43+
$expected = $test.Groups[1].Value -eq 'true'
44+
$input = $test.Groups[2].Value.Trim()
45+
46+
# Run the test
47+
$matches = $regex.IsMatch($input)
48+
49+
if ($matches -eq $expected) {
50+
$passed++
51+
}
52+
else {
53+
$failed++
54+
$failureDetails += " Input: '$input' - Expected: $expected, Got: $matches"
55+
}
56+
}
57+
58+
return @{
59+
File = $fileName
60+
Passed = $passed
61+
Failed = $failed
62+
Total = $tests.Count
63+
Failures = $failureDetails
64+
}
65+
}
66+
catch {
67+
return @{
68+
File = $fileName
69+
Error = $_.Exception.Message
70+
}
71+
}
72+
}
73+
74+
# Main execution
75+
if ($YamlFilePath) {
76+
# Test single file
77+
$result = Test-Pattern -FilePath $YamlFilePath
78+
79+
if ($result.Error) {
80+
Write-Host "ERROR: $($result.File): $($result.Error)" -ForegroundColor Red
81+
exit 1
82+
}
83+
84+
if ($result.Failed -gt 0) {
85+
Write-Host "$($result.File): $($result.Failed)/$($result.Total) tests failed" -ForegroundColor Red
86+
foreach ($failure in $result.Failures) {
87+
Write-Host $failure
88+
}
89+
exit 1
90+
}
91+
else {
92+
Write-Host "$($result.File): All $($result.Total) tests passed"
93+
exit 0
94+
}
95+
}
96+
else {
97+
# Test all files
98+
$patternFiles = @()
99+
$patternFiles += Get-ChildItem -Path "regex_patterns" -Filter "*.yml" -File
100+
$patternFiles += Get-ChildItem -Path "regex_patterns" -Filter "*.yaml" -File
101+
102+
if ($patternFiles.Count -eq 0) {
103+
Write-Host "No pattern files found"
104+
exit 1
105+
}
106+
107+
$results = @()
108+
$totalFiles = $patternFiles.Count
109+
$filesWithFailures = @()
110+
111+
foreach ($file in $patternFiles) {
112+
$result = Test-Pattern -FilePath $file.FullName
113+
$results += $result
114+
115+
if ($result.Error) {
116+
$filesWithFailures += $result
117+
}
118+
elseif ($result.Failed -gt 0) {
119+
$filesWithFailures += $result
120+
}
121+
}
122+
123+
# Report failures
124+
if ($filesWithFailures.Count -gt 0) {
125+
Write-Host "ERRORS:"
126+
127+
# Find global max input length across all failures
128+
$globalMaxInputLength = 0
129+
foreach ($failure in $filesWithFailures) {
130+
if (-not $failure.Error) {
131+
foreach ($detail in $failure.Failures) {
132+
if ($detail -match "Input: '(.+?)' -") {
133+
$inputLength = $matches[1].Length
134+
if ($inputLength -gt $globalMaxInputLength) {
135+
$globalMaxInputLength = $inputLength
136+
}
137+
}
138+
}
139+
}
140+
}
141+
142+
# Limit padding to 150 characters
143+
if ($globalMaxInputLength -gt 150) {
144+
$globalMaxInputLength = 150
145+
}
146+
147+
foreach ($failure in $filesWithFailures) {
148+
Write-Host " $($failure.File):"
149+
150+
if ($failure.Error) {
151+
# Extract cleaner error message
152+
$errorMsg = $failure.Error
153+
if ($errorMsg -match "at offset (\d+)\. (.+?)\.?`"") {
154+
$errorMsg = "offset $($matches[1]): $($matches[2])"
155+
}
156+
Write-Host " $errorMsg"
157+
}
158+
else {
159+
foreach ($detail in $failure.Failures) {
160+
if ($detail -match "Input: '(.+?)' - Expected: (\w+), Got: (\w+)") {
161+
$input = $matches[1]
162+
$expected = $matches[2]
163+
$got = $matches[3]
164+
165+
# Truncate only if longer than 150
166+
if ($input.Length -gt 150) {
167+
$input = $input.Substring(0, 147) + "..."
168+
}
169+
170+
$paddedInput = $input.PadRight($globalMaxInputLength)
171+
Write-Host " $paddedInput | Expected: $expected | Got: $got"
172+
}
173+
}
174+
}
175+
}
176+
177+
exit 1
178+
}
179+
else {
180+
Write-Host "All tests passed"
181+
exit 0
182+
}
183+
}

scripts/unitTest.ps1

Lines changed: 0 additions & 1 deletion
This file was deleted.

scripts/validatePattern.ps1

Lines changed: 0 additions & 73 deletions
This file was deleted.

0 commit comments

Comments
 (0)