package main
import (
"os"
"regexp"
"strings"
"testing"
)
// Helper function to normalize whitespace for comparison
func normalizeWhitespace(s string) string {
// Replace all whitespace with a single space
re := regexp.MustCompile(`\s+`)
return re.ReplaceAllString(strings.TrimSpace(s), " ")
}
func TestSimpleValueMultiplication(t *testing.T) {
fileContents := `
-
100
`
expected := `
-
150
`
// Create a regex pattern with the (?s) flag for multiline matching
regex := regexp.MustCompile(`(?s)(\d+)`)
luaExpr := `*1.5`
luaScript := buildLuaScript(luaExpr)
modifiedContent, err := process(fileContents, regex, luaScript)
if err != nil {
t.Fatalf("Error processing file: %v", err)
}
// Compare normalized content
normalizedModified := normalizeWhitespace(modifiedContent)
normalizedExpected := normalizeWhitespace(expected)
if normalizedModified != normalizedExpected {
t.Fatalf("Expected modified content to be %q, but got %q", normalizedExpected, normalizedModified)
}
}
func TestShorthandNotation(t *testing.T) {
fileContents := `
-
100
`
expected := `
-
150
`
regex := regexp.MustCompile(`(?s)(\d+)`)
luaExpr := `v1 * 1.5` // Use direct assignment syntax
luaScript := buildLuaScript(luaExpr)
modifiedContent, err := process(fileContents, regex, luaScript)
if err != nil {
t.Fatalf("Error processing file: %v", err)
}
normalizedModified := normalizeWhitespace(modifiedContent)
normalizedExpected := normalizeWhitespace(expected)
if normalizedModified != normalizedExpected {
t.Fatalf("Expected modified content to be %q, but got %q", normalizedExpected, normalizedModified)
}
}
func TestArrayNotation(t *testing.T) {
fileContents := `
-
100
`
expected := `
-
150
`
regex := regexp.MustCompile(`(?s)(\d+)`)
luaExpr := `v1 = v1 * 1.5` // Use direct assignment syntax
luaScript := buildLuaScript(luaExpr)
modifiedContent, err := process(fileContents, regex, luaScript)
if err != nil {
t.Fatalf("Error processing file: %v", err)
}
normalizedModified := normalizeWhitespace(modifiedContent)
normalizedExpected := normalizeWhitespace(expected)
if normalizedModified != normalizedExpected {
t.Fatalf("Expected modified content to be %q, but got %q", normalizedExpected, normalizedModified)
}
}
func TestMultipleMatches(t *testing.T) {
fileContents := `
-
100
-
200
- 300
`
expected := `
-
150
-
300
- 450
`
regex := regexp.MustCompile(`(?s)(\d+)`)
luaExpr := `*1.5`
luaScript := buildLuaScript(luaExpr)
modifiedContent, err := process(fileContents, regex, luaScript)
if err != nil {
t.Fatalf("Error processing file: %v", err)
}
normalizedModified := normalizeWhitespace(modifiedContent)
normalizedExpected := normalizeWhitespace(expected)
if normalizedModified != normalizedExpected {
t.Fatalf("Expected modified content to be %q, but got %q", normalizedExpected, normalizedModified)
}
}
func TestMultipleCaptureGroups(t *testing.T) {
fileContents := `
-
10
5
`
expected := `
-
50
5
`
// Use (?s) flag to match across multiple lines
regex := regexp.MustCompile(`(?s)(\d+).*?(\d+)`)
luaExpr := `v1 = v1 * v2` // Use direct assignment syntax
luaScript := buildLuaScript(luaExpr)
// Verify the regex matches before processing
matches := regex.FindStringSubmatch(fileContents)
if len(matches) <= 1 {
t.Fatalf("Regex didn't match any capture groups in test input: %v", fileContents)
}
t.Logf("Matches: %v", matches)
modifiedContent, err := process(fileContents, regex, luaScript)
if err != nil {
t.Fatalf("Error processing file: %v", err)
}
normalizedModified := normalizeWhitespace(modifiedContent)
normalizedExpected := normalizeWhitespace(expected)
if normalizedModified != normalizedExpected {
t.Fatalf("Expected modified content to be %q, but got %q", normalizedExpected, normalizedModified)
}
}
func TestModifyingMultipleValues(t *testing.T) {
fileContents := `
-
50
3
2
`
expected := `
-
75
5
1
`
regex := regexp.MustCompile(`(?s)(\d+).*?(\d+).*?(\d+)`)
luaExpr := `v1 = v1 * v2 / v3; v2 = min(v2 * 2, 5); v3 = max(1, v3 / 2)`
luaScript := buildLuaScript(luaExpr)
// Verify the regex matches before processing
matches := regex.FindStringSubmatch(fileContents)
if len(matches) <= 1 {
t.Fatalf("Regex didn't match any capture groups in test input: %v", fileContents)
}
t.Logf("Matches: %v", matches)
modifiedContent, err := process(fileContents, regex, luaScript)
if err != nil {
t.Fatalf("Error processing file: %v", err)
}
normalizedModified := normalizeWhitespace(modifiedContent)
normalizedExpected := normalizeWhitespace(expected)
if normalizedModified != normalizedExpected {
t.Fatalf("Expected modified content to be %q, but got %q", normalizedExpected, normalizedModified)
}
}
func TestDecimalValues(t *testing.T) {
fileContents := `
-
10.5
2.5
`
expected := `
-
26.25
2.5
`
regex := regexp.MustCompile(`(?s)([0-9.]+).*?([0-9.]+)`)
luaExpr := `v1 = v1 * v2` // Use direct assignment syntax
luaScript := buildLuaScript(luaExpr)
modifiedContent, err := process(fileContents, regex, luaScript)
if err != nil {
t.Fatalf("Error processing file: %v", err)
}
normalizedModified := normalizeWhitespace(modifiedContent)
normalizedExpected := normalizeWhitespace(expected)
if normalizedModified != normalizedExpected {
t.Fatalf("Expected modified content to be %q, but got %q", normalizedExpected, normalizedModified)
}
}
func TestLuaMathFunctions(t *testing.T) {
fileContents := `
-
16
`
expected := `
-
4
`
regex := regexp.MustCompile(`(?s)(\d+)`)
luaExpr := `v1 = math.sqrt(v1)` // Use direct assignment syntax
luaScript := buildLuaScript(luaExpr)
modifiedContent, err := process(fileContents, regex, luaScript)
if err != nil {
t.Fatalf("Error processing file: %v", err)
}
normalizedModified := normalizeWhitespace(modifiedContent)
normalizedExpected := normalizeWhitespace(expected)
if normalizedModified != normalizedExpected {
t.Fatalf("Expected modified content to be %q, but got %q", normalizedExpected, normalizedModified)
}
}
func TestDirectAssignment(t *testing.T) {
fileContents := `
-
100
`
expected := `
-
0
`
regex := regexp.MustCompile(`(?s)(\d+)`)
luaExpr := `=0`
luaScript := buildLuaScript(luaExpr)
t.Logf("Lua script: %s", luaScript) // Log the generated script for debugging
modifiedContent, err := process(fileContents, regex, luaScript)
if err != nil {
t.Fatalf("Error processing file: %v", err)
}
normalizedModified := normalizeWhitespace(modifiedContent)
normalizedExpected := normalizeWhitespace(expected)
if normalizedModified != normalizedExpected {
t.Fatalf("Expected modified content to be %q, but got %q", normalizedExpected, normalizedModified)
}
}
// Test with actual files
func TestProcessingSampleFiles(t *testing.T) {
// Read test files
complexFile, err := os.ReadFile("test_complex.xml")
if err != nil {
t.Fatalf("Error reading test_complex.xml: %v", err)
}
testDataFile, err := os.ReadFile("test_data.xml")
if err != nil {
t.Fatalf("Error reading test_data.xml: %v", err)
}
testCases := []struct {
name string
fileContent string
regexPattern string
luaExpr string
expectedFunc func(string) string // Function to generate expected output
}{
{
name: "Complex file - multiply values by multiplier and divide by divider",
fileContent: string(complexFile),
regexPattern: `(?s)(\d+).*?(\d+).*?(\d+)`,
luaExpr: `v1 = v1 * v2 / v3`,
expectedFunc: func(content string) string {
// Replace values manually for verification
r := regexp.MustCompile(`(?s)- \s*150\s*2\s*4\s*
`)
content = r.ReplaceAllString(content, "- \n 75\n 2\n 4\n
")
r = regexp.MustCompile(`(?s)- \s*300\s*3\s*2\s*
`)
content = r.ReplaceAllString(content, "- \n 450\n 3\n 2\n
")
return content
},
},
{
name: "Test data - simple multiplication",
fileContent: string(testDataFile),
regexPattern: `(?s).*?(\d+).*?`,
luaExpr: `v1 = v1 * 1.5`,
expectedFunc: func(content string) string {
r := regexp.MustCompile(`100`)
return r.ReplaceAllString(content, "150")
},
},
{
name: "Test data - multiple capture groups",
fileContent: string(testDataFile),
regexPattern: `(?s).*?(\d+).*?(\d+).*?(\d+).*?`,
luaExpr: `v1 = v1 * v2 / v3`,
expectedFunc: func(content string) string {
r := regexp.MustCompile(`50`)
return r.ReplaceAllString(content, "75")
},
},
{
name: "Test data - decimal values",
fileContent: string(testDataFile),
regexPattern: `(?s).*?([0-9.]+).*?([0-9.]+).*?`,
luaExpr: `v1 = v1 * v2`,
expectedFunc: func(content string) string {
r := regexp.MustCompile(`10.5`)
return r.ReplaceAllString(content, "26.25")
},
},
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
regex := regexp.MustCompile(tc.regexPattern)
luaScript := buildLuaScript(tc.luaExpr)
// Debug information
t.Logf("Regex pattern: %s", tc.regexPattern)
t.Logf("Lua expression: %s", tc.luaExpr)
// Process the content
modifiedContent, err := process(tc.fileContent, regex, luaScript)
if err != nil {
t.Fatalf("Error processing file: %v", err)
}
t.Logf("Modified content has length: %d", len(modifiedContent))
// Generate expected content
expectedContent := tc.expectedFunc(tc.fileContent)
t.Logf("Expected content has length: %d", len(expectedContent))
// Compare normalized content
normalizedModified := normalizeWhitespace(modifiedContent)
normalizedExpected := normalizeWhitespace(expectedContent)
// Check if the specific section was modified as expected
if !strings.Contains(normalizedModified, normalizeWhitespace(expectedContent)) {
t.Logf("Modified content: %s", normalizedModified)
t.Logf("Expected content: %s", normalizedExpected)
t.Fatalf("Expected modification not found in result")
} else {
t.Logf("Test passed - expected modification found in result")
}
})
}
}
func TestFileOperations(t *testing.T) {
// Test file operations with sample XML files
// Test 1: Complex file with multiple items
t.Run("Complex file operations", func(t *testing.T) {
// Read test file
complexFile, err := os.ReadFile("test_complex.xml")
if err != nil {
t.Fatalf("Error reading test_complex.xml: %v", err)
}
fileContent := string(complexFile)
// Configure test
regexPattern := `(?s)(\d+).*?(\d+).*?(\d+)`
luaExpr := `v1 = v1 * v2 / v3` // Use direct assignment
// Execute test
regex := regexp.MustCompile(regexPattern)
luaScript := buildLuaScript(luaExpr)
t.Logf("Regex pattern: %s", regexPattern)
t.Logf("Lua expression: %s", luaExpr)
// Process the content
modifiedContent, err := process(fileContent, regex, luaScript)
if err != nil {
t.Fatalf("Error processing file: %v", err)
}
// Verify results - should have 75 and 450 as values
t.Logf("Modified content: %s", modifiedContent)
if !strings.Contains(modifiedContent, "75") {
t.Errorf("First value not modified correctly, expected 75")
}
if !strings.Contains(modifiedContent, "450") {
t.Errorf("Second value not modified correctly, expected 450")
}
t.Logf("Complex file test completed successfully")
})
// Test 2: Test data file with simple multiplication
t.Run("Simple multiplication in test data", func(t *testing.T) {
// Read test file
testDataFile, err := os.ReadFile("test_data.xml")
if err != nil {
t.Fatalf("Error reading test_data.xml: %v", err)
}
fileContent := string(testDataFile)
// Configure test for simple value
regexPattern := `(?s).*?(\d+).*?`
luaExpr := `v1 = v1 * 1.5` // Use direct assignment
// Execute test
regex := regexp.MustCompile(regexPattern)
luaScript := buildLuaScript(luaExpr)
t.Logf("Regex pattern: %s", regexPattern)
t.Logf("Lua expression: %s", luaExpr)
// Process the content
modifiedContent, err := process(fileContent, regex, luaScript)
if err != nil {
t.Fatalf("Error processing file: %v", err)
}
// Check for expected value (100 * 1.5 = 150)
if !strings.Contains(modifiedContent, "150") {
t.Errorf("Value not modified correctly, expected 150 in the simple test")
t.Logf("Modified content: %s", modifiedContent)
} else {
t.Logf("Simple test passed - found 150")
}
})
// Test 3: Decimal values
t.Run("Decimal values in test data", func(t *testing.T) {
// Read test file
testDataFile, err := os.ReadFile("test_data.xml")
if err != nil {
t.Fatalf("Error reading test_data.xml: %v", err)
}
fileContent := string(testDataFile)
// Configure test for decimal values
regexPattern := `(?s).*?([0-9.]+).*?([0-9.]+).*?`
luaExpr := `v1 = v1 * v2` // Use direct assignment
// Execute test
regex := regexp.MustCompile(regexPattern)
luaScript := buildLuaScript(luaExpr)
t.Logf("Regex pattern: %s", regexPattern)
t.Logf("Lua expression: %s", luaExpr)
// Process the content
modifiedContent, err := process(fileContent, regex, luaScript)
if err != nil {
t.Fatalf("Error processing file: %v", err)
}
// Check for expected value (10.5 * 2.5 = 26.25)
if !strings.Contains(modifiedContent, "26.25") {
t.Errorf("Decimal value not modified correctly, expected 26.25")
t.Logf("Modified content: %s", modifiedContent)
} else {
t.Logf("Decimal test passed - found 26.25")
}
})
}
func TestHigherVariableIndices(t *testing.T) {
fileContents := `
-
10
20
30
40
50
110
`
// Test using v3, v4, v5 in the expression
t.Run("Using v3-v5 variables", func(t *testing.T) {
regex := regexp.MustCompile(`(?s)(\d+).*?(\d+).*?(\d+).*?(\d+).*?(\d+)`)
luaExpr := `v1 = v1 + v2 * v3 / v4 - v5`
luaScript := buildLuaScript(luaExpr)
// Expected: 10 + 20 * 30 / 40 - 50 = 10 + 15 - 50 = -25
modifiedContent, err := process(fileContents, regex, luaScript)
if err != nil {
t.Fatalf("Error processing with v3-v5: %v", err)
}
// The result should replace the first value
if !strings.Contains(modifiedContent, "-25") {
t.Fatalf("Failed to process v3-v5 correctly. Expected -25, got: %s", modifiedContent)
}
})
// Test using v11 (double digit index)
// For double digit indexes, we need to capture it as the second variable (v2)
t.Run("Using v11 variable", func(t *testing.T) {
regex := regexp.MustCompile(`(?s)(\d+).*?(\d+)`)
luaExpr := `v1 = v1 * v2`
luaScript := buildLuaScript(luaExpr)
// Expected: 10 * 110 = 1100
modifiedContent, err := process(fileContents, regex, luaScript)
if err != nil {
t.Fatalf("Error processing with v11: %v", err)
}
// The result should replace the first value
if !strings.Contains(modifiedContent, "1100") {
t.Fatalf("Failed to process v11 correctly. Expected 1100, got: %s", modifiedContent)
}
})
// Test using v0 (zero index)
t.Run("Using v0 variable", func(t *testing.T) {
// For this test, we'll capture the tag content and manipulate it
regex := regexp.MustCompile(`(?s)(\d+)`)
luaExpr := `v1 = tonumber(v1) * 2`
luaScript := buildLuaScript(luaExpr)
// This should double the value
modifiedContent, err := process(fileContents, regex, luaScript)
if err != nil {
t.Fatalf("Error processing with v0: %v", err)
}
// Should replace 10 with 20
if !strings.Contains(modifiedContent, "20") {
t.Fatalf("Failed to process test correctly. Expected 20, got: %s", modifiedContent)
}
})
}
func TestMultiStatementExpression(t *testing.T) {
fileContents := `
-
100
200
`
expected := `
-
0
0
`
regex := regexp.MustCompile(`(?s)(\d+).*?(\d+)`)
luaExpr := `v1=0 v2=0` // Multiple statements without semicolons
luaScript := buildLuaScript(luaExpr)
t.Logf("Generated Lua script: %s", luaScript)
modifiedContent, err := process(fileContents, regex, luaScript)
if err != nil {
t.Fatalf("Error processing file: %v", err)
}
normalizedModified := normalizeWhitespace(modifiedContent)
normalizedExpected := normalizeWhitespace(expected)
if normalizedModified != normalizedExpected {
t.Fatalf("Expected modified content to be %q, but got %q", normalizedExpected, normalizedModified)
}
}
func TestComplexLuaScripts(t *testing.T) {
fileContents := `
-
100
200
50
`
expected := `
-
300
0
150
`
regex := regexp.MustCompile(`(?s)(\d+).*?(\d+).*?(\d+)`)
luaExpr := `
local sum = v1 + v2
if sum > 250 then
v1 = sum
v2 = 0
v3 = v3 * 3
else
v1 = 0
v2 = sum
v3 = v3 * 2
end
`
luaScript := buildLuaScript(luaExpr)
t.Logf("Generated Lua script: %s", luaScript)
modifiedContent, err := process(fileContents, regex, luaScript)
if err != nil {
t.Fatalf("Error processing file: %v", err)
}
normalizedModified := normalizeWhitespace(modifiedContent)
normalizedExpected := normalizeWhitespace(expected)
if normalizedModified != normalizedExpected {
t.Fatalf("Expected modified content to be %q, but got %q", normalizedExpected, normalizedModified)
}
}