Update old and add new tests

This commit is contained in:
2025-03-27 23:28:49 +01:00
parent f91c2b4795
commit 5d10178bf9
5 changed files with 685 additions and 131 deletions

View File

@@ -1,6 +1,7 @@
package processor
import (
"modify/utils"
"regexp"
"strings"
"testing"
@@ -24,6 +25,22 @@ func normalizeWhitespace(s string) string {
return re.ReplaceAllString(strings.TrimSpace(s), " ")
}
func ApiAdaptor(content string, regex string, lua string) (string, int, int, error) {
command := utils.ModifyCommand{
Pattern: regex,
LuaExpr: lua,
LogLevel: "TRACE",
}
commands, err := ProcessRegex(content, command)
if err != nil {
return "", 0, 0, err
}
result, modifications := utils.ExecuteModifications(commands, content)
return result, modifications, len(commands), nil
}
func TestBuildLuaScript(t *testing.T) {
cases := []struct {
input string
@@ -59,8 +76,7 @@ func TestSimpleValueMultiplication(t *testing.T) {
</item>
</config>`
p := &RegexProcessor{}
result, mods, matches, err := p.ProcessContent(content, `(?s)<value>(\d+)</value>`, "v1 = v1*1.5")
result, mods, matches, err := ApiAdaptor(content, `(?s)<value>(\d+)</value>`, "v1 = v1*1.5")
if err != nil {
t.Fatalf("Error processing content: %v", err)
@@ -92,8 +108,7 @@ func TestShorthandNotation(t *testing.T) {
</item>
</config>`
p := &RegexProcessor{}
result, mods, matches, err := p.ProcessContent(content, `(?s)<value>(\d+)</value>`, "v1*1.5")
result, mods, matches, err := ApiAdaptor(content, `(?s)<value>(\d+)</value>`, "v1*1.5")
if err != nil {
t.Fatalf("Error processing content: %v", err)
@@ -125,8 +140,7 @@ func TestShorthandNotationFloats(t *testing.T) {
</item>
</config>`
p := &RegexProcessor{}
result, mods, matches, err := p.ProcessContent(content, `(?s)<value>(\d+\.\d+)</value>`, "v1*1.5")
result, mods, matches, err := ApiAdaptor(content, `(?s)<value>(\d+\.\d+)</value>`, "v1*1.5")
if err != nil {
t.Fatalf("Error processing content: %v", err)
@@ -162,8 +176,7 @@ func TestArrayNotation(t *testing.T) {
</prices>
</config>`
p := &RegexProcessor{}
result, mods, matches, err := p.ProcessContent(content, `(?s)<price>(\d+)</price>`, "v1*2")
result, mods, matches, err := ApiAdaptor(content, `(?s)<price>(\d+)</price>`, "v1*2")
if err != nil {
t.Fatalf("Error processing content: %v", err)
@@ -195,8 +208,7 @@ func TestMultipleNumericMatches(t *testing.T) {
<entry>400</entry>
</data>`
p := &RegexProcessor{}
result, mods, matches, err := p.ProcessContent(content, `<entry>(\d+)</entry>`, "v1*2")
result, mods, matches, err := ApiAdaptor(content, `<entry>(\d+)</entry>`, "v1*2")
if err != nil {
t.Fatalf("Error processing content: %v", err)
@@ -226,8 +238,7 @@ func TestMultipleStringMatches(t *testing.T) {
<name>Mary_modified</name>
</data>`
p := &RegexProcessor{}
result, mods, matches, err := p.ProcessContent(content, `<name>([A-Za-z]+)</name>`, `s1 = s1 .. "_modified"`)
result, mods, matches, err := ApiAdaptor(content, `<name>([A-Za-z]+)</name>`, `s1 = s1 .. "_modified"`)
if err != nil {
t.Fatalf("Error processing content: %v", err)
@@ -257,9 +268,7 @@ func TestStringUpperCase(t *testing.T) {
<user>MARY</user>
</users>`
p := &RegexProcessor{}
// Convert names to uppercase using Lua string function
result, mods, matches, err := p.ProcessContent(content, `<user>([A-Za-z]+)</user>`, `s1 = string.upper(s1)`)
result, mods, matches, err := ApiAdaptor(content, `<user>([A-Za-z]+)</user>`, `s1 = string.upper(s1)`)
if err != nil {
t.Fatalf("Error processing content: %v", err)
@@ -289,8 +298,7 @@ func TestStringConcatenation(t *testing.T) {
<product>Banana_fruit</product>
</products>`
p := &RegexProcessor{}
result, mods, matches, err := p.ProcessContent(content, `<product>([A-Za-z]+)</product>`, `s1 = s1 .. "_fruit"`)
result, mods, matches, err := ApiAdaptor(content, `<product>([A-Za-z]+)</product>`, `s1 = s1 .. "_fruit"`)
if err != nil {
t.Fatalf("Error processing content: %v", err)
@@ -329,15 +337,14 @@ func TestDecimalValues(t *testing.T) {
`
regex := regexp.MustCompile(`(?s)<value>([0-9.]+)</value>.*?<multiplier>([0-9.]+)</multiplier>`)
p := &RegexProcessor{}
luaExpr := BuildLuaScript("v1 = v1 * v2")
modifiedContent, _, _, err := p.ProcessContent(content, regex.String(), luaExpr)
result, _, _, err := ApiAdaptor(content, regex.String(), luaExpr)
if err != nil {
t.Fatalf("Error processing content: %v", err)
}
normalizedModified := normalizeWhitespace(modifiedContent)
normalizedModified := normalizeWhitespace(result)
normalizedExpected := normalizeWhitespace(expected)
if normalizedModified != normalizedExpected {
t.Fatalf("Expected modified content to be %q, but got %q", normalizedExpected, normalizedModified)
@@ -362,10 +369,9 @@ func TestLuaMathFunctions(t *testing.T) {
`
regex := regexp.MustCompile(`(?s)<value>(\d+)</value>`)
p := &RegexProcessor{}
luaExpr := BuildLuaScript("v1 = math.sqrt(v1)")
modifiedContent, _, _, err := p.ProcessContent(content, regex.String(), luaExpr)
modifiedContent, _, _, err := ApiAdaptor(content, regex.String(), luaExpr)
if err != nil {
t.Fatalf("Error processing content: %v", err)
}
@@ -395,10 +401,9 @@ func TestDirectAssignment(t *testing.T) {
`
regex := regexp.MustCompile(`(?s)<value>(\d+)</value>`)
p := &RegexProcessor{}
luaExpr := BuildLuaScript("=0")
modifiedContent, _, _, err := p.ProcessContent(content, regex.String(), luaExpr)
modifiedContent, _, _, err := ApiAdaptor(content, regex.String(), luaExpr)
if err != nil {
t.Fatalf("Error processing content: %v", err)
}
@@ -458,11 +463,10 @@ func TestStringAndNumericOperations(t *testing.T) {
t.Run(tt.name, func(t *testing.T) {
// Compile the regex pattern with multiline support
pattern := "(?s)" + tt.regexPattern
p := &RegexProcessor{}
luaExpr := BuildLuaScript(tt.luaExpression)
// Process with our function
result, modCount, _, err := p.ProcessContent(tt.input, pattern, luaExpr)
result, modCount, _, err := ApiAdaptor(tt.input, pattern, luaExpr)
if err != nil {
t.Fatalf("Process function failed: %v", err)
}
@@ -527,11 +531,10 @@ func TestEdgeCases(t *testing.T) {
t.Run(tt.name, func(t *testing.T) {
// Make sure the regex can match across multiple lines
pattern := "(?s)" + tt.regexPattern
p := &RegexProcessor{}
luaExpr := BuildLuaScript(tt.luaExpression)
// Process with our function
result, modCount, _, err := p.ProcessContent(tt.input, pattern, luaExpr)
result, modCount, _, err := ApiAdaptor(tt.input, pattern, luaExpr)
if err != nil {
t.Fatalf("Process function failed: %v", err)
}
@@ -561,8 +564,7 @@ func TestNamedCaptureGroups(t *testing.T) {
</item>
</config>`
p := &RegexProcessor{}
result, mods, matches, err := p.ProcessContent(content, `(?s)<value>(?<amount>\d+)</value>`, "amount = amount * 2")
result, mods, matches, err := ApiAdaptor(content, `(?s)<value>(?<amount>\d+)</value>`, "amount = amount * 2")
if err != nil {
t.Fatalf("Error processing content: %v", err)
@@ -594,8 +596,7 @@ func TestNamedCaptureGroupsNum(t *testing.T) {
</item>
</config>`
p := &RegexProcessor{}
result, mods, matches, err := p.ProcessContent(content, `(?s)<value>(?<amount>!num)</value>`, "amount = amount * 2")
result, mods, matches, err := ApiAdaptor(content, `(?s)<value>(?<amount>!num)</value>`, "amount = amount * 2")
if err != nil {
t.Fatalf("Error processing content: %v", err)
@@ -627,9 +628,7 @@ func TestMultipleNamedCaptureGroups(t *testing.T) {
<quantity>15</quantity>
</product>`
p := &RegexProcessor{}
result, mods, matches, err := p.ProcessContent(
content,
result, mods, matches, err := ApiAdaptor(content,
`(?s)<name>(?<prodName>[^<]+)</name>.*?<price>(?<prodPrice>\d+\.\d+)</price>.*?<quantity>(?<prodQty>\d+)</quantity>`,
`prodName = string.upper(prodName)
prodPrice = round(prodPrice + 8, 2)
@@ -639,12 +638,12 @@ func TestMultipleNamedCaptureGroups(t *testing.T) {
t.Fatalf("Error processing content: %v", err)
}
if matches != 1 {
t.Errorf("Expected 1 match, got %d", matches)
if matches != 3 {
t.Errorf("Expected 3 matches, got %d", matches)
}
if mods != 1 {
t.Errorf("Expected 1 modification, got %d", mods)
if mods != 3 {
t.Errorf("Expected 3 modifications, got %d", mods)
}
if result != expected {
@@ -663,9 +662,7 @@ func TestMixedIndexedAndNamedCaptures(t *testing.T) {
<data>VALUE</data>
</entry>`
p := &RegexProcessor{}
result, mods, matches, err := p.ProcessContent(
content,
result, mods, matches, err := ApiAdaptor(content,
`(?s)<id>(\d+)</id>.*?<data>(?<dataField>[^<]+)</data>`,
`v1 = v1 * 2
dataField = string.upper(dataField)`)
@@ -674,12 +671,12 @@ func TestMixedIndexedAndNamedCaptures(t *testing.T) {
t.Fatalf("Error processing content: %v", err)
}
if matches != 1 {
t.Errorf("Expected 1 match, got %d", matches)
if matches != 2 {
t.Errorf("Expected 2 matches, got %d", matches)
}
if mods != 1 {
t.Errorf("Expected 1 modification, got %d", mods)
if mods != 2 {
t.Errorf("Expected 2 modifications, got %d", mods)
}
if result != expected {
@@ -708,9 +705,7 @@ func TestComplexNestedNamedCaptures(t *testing.T) {
</contact>
</person>`
p := &RegexProcessor{}
result, mods, matches, err := p.ProcessContent(
content,
result, mods, matches, err := ApiAdaptor(content,
`(?s)<details>.*?<name>(?<fullName>[^<]+)</name>.*?<age>(?<age>\d+)</age>`,
`fullName = string.upper(fullName) .. " (" .. age .. ")"`)
@@ -742,9 +737,7 @@ func TestNamedCaptureWithVariableReadback(t *testing.T) {
<mana>300</mana>
</stats>`
p := &RegexProcessor{}
result, mods, matches, err := p.ProcessContent(
content,
result, mods, matches, err := ApiAdaptor(content,
`(?s)<health>(?<hp>\d+)</health>.*?<mana>(?<mp>\d+)</mana>`,
`hp = hp * 1.5
mp = mp * 1.5`)
@@ -753,12 +746,12 @@ func TestNamedCaptureWithVariableReadback(t *testing.T) {
t.Fatalf("Error processing content: %v", err)
}
if matches != 1 {
t.Errorf("Expected 1 match, got %d", matches)
if matches != 2 {
t.Errorf("Expected 2 matches, got %d", matches)
}
if mods != 1 {
t.Errorf("Expected 1 modification, got %d", mods)
if mods != 2 {
t.Errorf("Expected 2 modifications, got %d", mods)
}
if result != expected {
@@ -771,9 +764,7 @@ func TestNamedCaptureWithSpecialCharsInName(t *testing.T) {
expected := `<data value="84" min="10" max="100" />`
p := &RegexProcessor{}
result, mods, matches, err := p.ProcessContent(
content,
result, mods, matches, err := ApiAdaptor(content,
`<data value="(?<val_1>\d+)"`,
`val_1 = val_1 * 2`)
@@ -799,9 +790,7 @@ func TestEmptyNamedCapture(t *testing.T) {
expected := `<tag attr="default" />`
p := &RegexProcessor{}
result, mods, matches, err := p.ProcessContent(
content,
result, mods, matches, err := ApiAdaptor(content,
`attr="(?<value>.*?)"`,
`value = value == "" and "default" or value`)
@@ -827,9 +816,7 @@ func TestMultipleNamedCapturesInSameLine(t *testing.T) {
expected := `<rect x="20" y="40" width="200" height="100" />`
p := &RegexProcessor{}
result, mods, matches, err := p.ProcessContent(
content,
result, mods, matches, err := ApiAdaptor(content,
`x="(?<x>\d+)" y="(?<y>\d+)" width="(?<w>\d+)" height="(?<h>\d+)"`,
`x = x * 2
y = y * 2
@@ -840,12 +827,12 @@ func TestMultipleNamedCapturesInSameLine(t *testing.T) {
t.Fatalf("Error processing content: %v", err)
}
if matches != 1 {
t.Errorf("Expected 1 match, got %d", matches)
if matches != 4 {
t.Errorf("Expected 4 matches, got %d", matches)
}
if mods != 1 {
t.Errorf("Expected 1 modification, got %d", mods)
if mods != 4 {
t.Errorf("Expected 4 modifications, got %d", mods)
}
if result != expected {
@@ -864,9 +851,7 @@ func TestConditionalNamedCapture(t *testing.T) {
<item status="inactive" count="10" />
`
p := &RegexProcessor{}
result, mods, matches, err := p.ProcessContent(
content,
result, mods, matches, err := ApiAdaptor(content,
`<item status="(?<status>[^"]+)" count="(?<count>\d+)"`,
`count = status == "active" and count * 2 or count`)
@@ -874,12 +859,12 @@ func TestConditionalNamedCapture(t *testing.T) {
t.Fatalf("Error processing content: %v", err)
}
if matches != 2 {
t.Errorf("Expected 2 matches, got %d", matches)
if matches != 1 {
t.Errorf("Expected 1 matches, got %d", matches)
}
if mods != 2 {
t.Errorf("Expected 2 modifications, got %d", mods)
if mods != 1 {
t.Errorf("Expected 1 modification, got %d", mods)
}
if result != expected {
@@ -898,9 +883,7 @@ func TestLuaFunctionsOnNamedCaptures(t *testing.T) {
<user name="JANE SMITH" role="admin" />
`
p := &RegexProcessor{}
result, mods, matches, err := p.ProcessContent(
content,
result, mods, matches, err := ApiAdaptor(content,
`<user name="(?<name>[^"]+)" role="(?<role>[^"]+)"`,
`-- Capitalize first letters for regular users
if role == "user" then
@@ -940,9 +923,7 @@ func TestNamedCaptureWithMath(t *testing.T) {
<item price="19.99" quantity="3" total="59.97" />
`
p := &RegexProcessor{}
result, mods, matches, err := p.ProcessContent(
content,
result, mods, matches, err := ApiAdaptor(content,
`<item price="(?<price>\d+\.\d+)" quantity="(?<qty>\d+)"!any$`,
`-- Calculate and add total
replacement = string.format('<item price="%s" quantity="%s" total="%.2f" />',
@@ -973,9 +954,7 @@ func TestNamedCaptureWithGlobals(t *testing.T) {
expected := `<temp unit="F">77</temp>`
p := &RegexProcessor{}
result, mods, matches, err := p.ProcessContent(
content,
result, mods, matches, err := ApiAdaptor(content,
`<temp unit="(?<unit>[CF]?)">(?<value>\d+)</temp>`,
`if unit == "C" then
value = value * 9/5 + 32
@@ -989,12 +968,12 @@ func TestNamedCaptureWithGlobals(t *testing.T) {
t.Fatalf("Error processing content: %v", err)
}
if matches != 1 {
t.Errorf("Expected 1 match, got %d", matches)
if matches != 2 {
t.Errorf("Expected 2 matches, got %d", matches)
}
if mods != 1 {
t.Errorf("Expected 1 modification, got %d", mods)
if mods != 2 {
t.Errorf("Expected 2 modifications, got %d", mods)
}
if result != expected {
@@ -1013,9 +992,7 @@ func TestMixedDynamicAndNamedCaptures(t *testing.T) {
<color rgb="0,255,0" name="GREEN" hex="#00FF00" />
`
p := &RegexProcessor{}
result, mods, matches, err := p.ProcessContent(
content,
result, mods, matches, err := ApiAdaptor(content,
`<color rgb="(?<r>\d+),(?<g>\d+),(?<b>\d+)" name="(?<colorName>[^"]+)" />`,
`-- Uppercase the name
colorName = string.upper(colorName)
@@ -1052,9 +1029,7 @@ func TestNamedCapturesWithMultipleReferences(t *testing.T) {
expected := `<text format="uppercase" length="11">HELLO WORLD</text>`
p := &RegexProcessor{}
result, mods, matches, err := p.ProcessContent(
content,
result, mods, matches, err := ApiAdaptor(content,
`<text>(?<content>[^<]+)</text>`,
`local uppercaseContent = string.upper(content)
local contentLength = string.len(content)
@@ -1083,9 +1058,7 @@ func TestNamedCaptureWithJsonData(t *testing.T) {
expected := `<data>{"name":"JOHN","age":30}</data>`
p := &RegexProcessor{}
result, mods, matches, err := p.ProcessContent(
content,
result, mods, matches, err := ApiAdaptor(content,
`<data>(?<json>\{.*?\})</data>`,
`-- Parse JSON (simplified, assumes valid JSON)
local name = json:match('"name":"([^"]+)"')
@@ -1126,9 +1099,7 @@ func TestNamedCaptureInXML(t *testing.T) {
</product>
`
p := &RegexProcessor{}
result, mods, matches, err := p.ProcessContent(
content,
result, mods, matches, err := ApiAdaptor(content,
`(?s)<price currency="(?<currency>[^"]+)">(?<price>\d+\.\d+)</price>.*?<stock>(?<stock>\d+)</stock>`,
`-- Add 20% to price if USD
if currency == "USD" then
@@ -1142,12 +1113,12 @@ func TestNamedCaptureInXML(t *testing.T) {
t.Fatalf("Error processing content: %v", err)
}
if matches != 1 {
t.Errorf("Expected 1 match, got %d", matches)
if matches != 2 {
t.Errorf("Expected 2 matches, got %d", matches)
}
if mods != 1 {
t.Errorf("Expected 1 modification, got %d", mods)
if mods != 2 {
t.Errorf("Expected 2 modifications, got %d", mods)
}
if result != expected {
@@ -1196,9 +1167,7 @@ func TestComprehensiveNamedCaptures(t *testing.T) {
</products>
`
p := &RegexProcessor{}
result, mods, matches, err := p.ProcessContent(
content,
result, mods, matches, err := ApiAdaptor(content,
`(?s)<product sku="(?<sku>[^"]+)" status="(?<status>[^"]+)"[^>]*>\s*<name>(?<product_name>[^<]+)</name>\s*<price currency="(?<currency>[^"]+)">(?<price>\d+\.\d+)</price>\s*<quantity>(?<qty>\d+)</quantity>`,
`-- Only process in-stock items
if status == "in-stock" then
@@ -1263,9 +1232,7 @@ func TestVariousNamedCaptureFormats(t *testing.T) {
</data>
`
p := &RegexProcessor{}
result, mods, matches, err := p.ProcessContent(
content,
result, mods, matches, err := ApiAdaptor(content,
`<entry id="(?<id_num>\d+)" value="(?<val>\d+)"(?: status="(?<status>[^"]*)")? />`,
`-- Prefix the ID with "ID-"
id_num = "ID-" .. id_num
@@ -1315,9 +1282,7 @@ func TestSimpleNamedCapture(t *testing.T) {
expected := `<product name="WIDGET" price="19.99"/>`
p := &RegexProcessor{}
result, mods, matches, err := p.ProcessContent(
content,
result, mods, matches, err := ApiAdaptor(content,
`name="(?<product_name>[^"]+)"`,
`product_name = string.upper(product_name)`)