package processor
import (
"regexp"
"strings"
"testing"
)
// TestLogger implements the Logger interface for testing
type TestLogger struct {
T *testing.T // Reference to the test's *testing.T
}
func (l *TestLogger) Printf(format string, v ...interface{}) {
if l.T != nil {
l.T.Logf(format, v...)
}
}
// 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) {
content := `
-
100
`
expected := `
-
150
`
// Create a regex pattern with the (?s) flag for multiline matching
regex := regexp.MustCompile(`(?s)(\d+)`)
processor := NewRegexProcessor(regex, &TestLogger{T: t})
luaExpr := BuildLuaScript("*1.5")
// Enable verbose logging for this test
t.Logf("Running test with regex pattern: %s", regex.String())
t.Logf("Original content: %s", content)
t.Logf("Lua expression: %s", luaExpr)
modifiedContent, modCount, matchCount, err := processor.ProcessContent(content, luaExpr, "test", "*1.5")
if err != nil {
t.Fatalf("Error processing content: %v", err)
}
// Verify match and modification counts
if matchCount != 1 {
t.Errorf("Expected 1 match, got %d", matchCount)
}
if modCount != 1 {
t.Errorf("Expected 1 modification, got %d", modCount)
}
t.Logf("Modified content: %s", modifiedContent)
t.Logf("Expected content: %s", expected)
// 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) {
content := `
-
100
`
expected := `
-
150
`
regex := regexp.MustCompile(`(?s)(\d+)`)
processor := NewRegexProcessor(regex, &TestLogger{})
luaExpr := BuildLuaScript("v1 * 1.5") // Use direct assignment syntax
modifiedContent, modCount, matchCount, err := processor.ProcessContent(content, luaExpr, "test", "v1 * 1.5")
if err != nil {
t.Fatalf("Error processing content: %v", err)
}
// Verify match and modification counts
if matchCount != 1 {
t.Errorf("Expected 1 match, got %d", matchCount)
}
if modCount != 1 {
t.Errorf("Expected 1 modification, got %d", modCount)
}
normalizedModified := normalizeWhitespace(modifiedContent)
normalizedExpected := normalizeWhitespace(expected)
if normalizedModified != normalizedExpected {
t.Fatalf("Expected modified content to be %q, but got %q", normalizedExpected, normalizedModified)
}
}
func TestShorthandNotationFloats(t *testing.T) {
content := `
-
132.671327
`
expected := `
-
176.01681007940928
`
regex := regexp.MustCompile(`(?s)(\d*\.?\d+)`)
processor := NewRegexProcessor(regex, &TestLogger{})
luaExpr := BuildLuaScript("v1 * 1.32671327") // Use direct assignment syntax
modifiedContent, modCount, matchCount, err := processor.ProcessContent(content, luaExpr, "test", "v1 * 1.32671327")
if err != nil {
t.Fatalf("Error processing content: %v", err)
}
// Verify match and modification counts
if matchCount != 1 {
t.Errorf("Expected 1 match, got %d", matchCount)
}
if modCount != 1 {
t.Errorf("Expected 1 modification, got %d", modCount)
}
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) {
content := `
-
100
`
expected := `
-
150
`
regex := regexp.MustCompile(`(?s)(\d+)`)
processor := NewRegexProcessor(regex, &TestLogger{})
luaExpr := BuildLuaScript("v1 = v1 * 1.5") // Use direct assignment syntax
modifiedContent, modCount, matchCount, err := processor.ProcessContent(content, luaExpr, "test", "v1 = v1 * 1.5")
if err != nil {
t.Fatalf("Error processing content: %v", err)
}
// Verify match and modification counts
if matchCount != 1 {
t.Errorf("Expected 1 match, got %d", matchCount)
}
if modCount != 1 {
t.Errorf("Expected 1 modification, got %d", modCount)
}
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) {
content := `
-
100
-
200
- 300
`
expected := `
-
150
-
300
- 450
`
regex := regexp.MustCompile(`(?s)(\d+)`)
processor := NewRegexProcessor(regex, &TestLogger{})
luaExpr := BuildLuaScript("*1.5")
modifiedContent, modCount, matchCount, err := processor.ProcessContent(content, luaExpr, "test", "*1.5")
if err != nil {
t.Fatalf("Error processing content: %v", err)
}
// Verify match and modification counts
if matchCount != 3 {
t.Errorf("Expected 3 matches, got %d", matchCount)
}
if modCount != 3 {
t.Errorf("Expected 3 modifications, got %d", modCount)
}
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) {
content := `
-
10
5
`
expected := `
-
50
5
`
// Use (?s) flag to match across multiple lines
regex := regexp.MustCompile(`(?s)(\d+).*?(\d+)`)
processor := NewRegexProcessor(regex, &TestLogger{})
luaExpr := BuildLuaScript("v1 = v1 * v2") // Use direct assignment syntax
// Verify the regex matches before processing
matches := regex.FindStringSubmatch(content)
if len(matches) <= 1 {
t.Fatalf("Regex didn't match any capture groups in test input: %v", content)
}
modifiedContent, modCount, matchCount, err := processor.ProcessContent(content, luaExpr, "test", "v1 = v1 * v2")
if err != nil {
t.Fatalf("Error processing content: %v", err)
}
// Verify match and modification counts
if matchCount != 1 {
t.Errorf("Expected 1 match, got %d", matchCount)
}
if modCount != 1 {
t.Errorf("Expected 1 modification, got %d", modCount)
}
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) {
content := `
-
50
3
2
`
expected := `
-
75
5
1
`
regex := regexp.MustCompile(`(?s)(\d+).*?(\d+).*?(\d+)`)
processor := NewRegexProcessor(regex, &TestLogger{})
luaExpr := BuildLuaScript("v1 = v1 * v2 / v3; v2 = min(v2 * 2, 5); v3 = max(1, v3 / 2)")
modifiedContent, modCount, matchCount, err := processor.ProcessContent(content, luaExpr, "test",
"v1 = v1 * v2 / v3; v2 = min(v2 * 2, 5); v3 = max(1, v3 / 2)")
if err != nil {
t.Fatalf("Error processing content: %v", err)
}
// Verify match and modification counts
if matchCount != 1 {
t.Errorf("Expected 1 match, got %d", matchCount)
}
if modCount != 1 {
t.Errorf("Expected 1 modification, got %d", modCount)
}
normalizedModified := normalizeWhitespace(modifiedContent)
normalizedExpected := normalizeWhitespace(expected)
if normalizedModified != normalizedExpected {
t.Fatalf("Expected modified content to be %q, but got %q", normalizedExpected, normalizedModified)
}
}
// Added from main_test.go
func TestDecimalValues(t *testing.T) {
content := `
-
10.5
2.5
`
expected := `
-
26.25
2.5
`
regex := regexp.MustCompile(`(?s)([0-9.]+).*?([0-9.]+)`)
processor := NewRegexProcessor(regex, &TestLogger{})
luaExpr := BuildLuaScript("v1 = v1 * v2")
modifiedContent, _, _, err := processor.ProcessContent(content, luaExpr, "test", "v1 = v1 * v2")
if err != nil {
t.Fatalf("Error processing content: %v", err)
}
normalizedModified := normalizeWhitespace(modifiedContent)
normalizedExpected := normalizeWhitespace(expected)
if normalizedModified != normalizedExpected {
t.Fatalf("Expected modified content to be %q, but got %q", normalizedExpected, normalizedModified)
}
}
// Added from main_test.go
func TestLuaMathFunctions(t *testing.T) {
content := `
-
16
`
expected := `
-
4
`
regex := regexp.MustCompile(`(?s)(\d+)`)
processor := NewRegexProcessor(regex, &TestLogger{})
luaExpr := BuildLuaScript("v1 = math.sqrt(v1)")
modifiedContent, _, _, err := processor.ProcessContent(content, luaExpr, "test", "v1 = math.sqrt(v1)")
if err != nil {
t.Fatalf("Error processing content: %v", err)
}
normalizedModified := normalizeWhitespace(modifiedContent)
normalizedExpected := normalizeWhitespace(expected)
if normalizedModified != normalizedExpected {
t.Fatalf("Expected modified content to be %q, but got %q", normalizedExpected, normalizedModified)
}
}
// Added from main_test.go
func TestDirectAssignment(t *testing.T) {
content := `
-
100
`
expected := `
-
0
`
regex := regexp.MustCompile(`(?s)(\d+)`)
processor := NewRegexProcessor(regex, &TestLogger{})
luaExpr := BuildLuaScript("=0")
modifiedContent, _, _, err := processor.ProcessContent(content, luaExpr, "test", "=0")
if err != nil {
t.Fatalf("Error processing content: %v", err)
}
normalizedModified := normalizeWhitespace(modifiedContent)
normalizedExpected := normalizeWhitespace(expected)
if normalizedModified != normalizedExpected {
t.Fatalf("Expected modified content to be %q, but got %q", normalizedExpected, normalizedModified)
}
}
// Added from main_test.go
func TestStringAndNumericOperations(t *testing.T) {
tests := []struct {
name string
input string
regexPattern string
luaExpression string
expectedOutput string
expectedMods int
}{
{
name: "Basic numeric multiplication",
input: "42",
regexPattern: "(\\d+)",
luaExpression: "v1 = v1 * 2",
expectedOutput: "84",
expectedMods: 1,
},
{
name: "Basic string manipulation",
input: "test",
regexPattern: "(.*?)",
luaExpression: "s1 = string.upper(s1)",
expectedOutput: "TEST",
expectedMods: 1,
},
{
name: "String concatenation",
input: "abc123",
regexPattern: "(.*?)",
luaExpression: "s1 = s1 .. '_modified'",
expectedOutput: "abc123_modified",
expectedMods: 1,
},
{
name: "Numeric value from string using num()",
input: "19.99",
regexPattern: "(.*?)",
luaExpression: "v1 = num(s1) * 1.2",
expectedOutput: "23.987999999999996",
expectedMods: 1,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
// Compile the regex pattern with multiline support
pattern := regexp.MustCompile("(?s)" + tt.regexPattern)
processor := NewRegexProcessor(pattern, &TestLogger{})
luaExpr := BuildLuaScript(tt.luaExpression)
// Process with our function
result, modCount, _, err := processor.ProcessContent(tt.input, luaExpr, "test", tt.luaExpression)
if err != nil {
t.Fatalf("Process function failed: %v", err)
}
// Check results
if result != tt.expectedOutput {
t.Errorf("Expected output: %s, got: %s", tt.expectedOutput, result)
}
if modCount != tt.expectedMods {
t.Errorf("Expected %d modifications, got %d", tt.expectedMods, modCount)
}
})
}
}
// Added from main_test.go
func TestEdgeCases(t *testing.T) {
tests := []struct {
name string
input string
regexPattern string
luaExpression string
expectedOutput string
expectedMods int
}{
{
name: "Empty capture group",
input: "",
regexPattern: "(.*?)",
luaExpression: "s1 = 'filled'",
expectedOutput: "filled",
expectedMods: 1,
},
{
name: "Non-numeric string with numeric operation",
input: "abc",
regexPattern: "(.*?)",
luaExpression: "v1 = v1 * 2", // This would fail if we didn't handle strings properly
expectedOutput: "abc", // Should remain unchanged
expectedMods: 0, // No modifications
},
{
name: "Invalid number conversion",
input: "abc",
regexPattern: "(.*?)",
luaExpression: "v1 = num(s1) + 10", // num(s1) should return 0
expectedOutput: "10",
expectedMods: 1,
},
{
name: "Multiline string",
input: "Line 1\nLine 2",
regexPattern: "(.*?)",
luaExpression: "s1 = string.gsub(s1, '\\n', ' - ')",
expectedOutput: "Line 1 - Line 2",
expectedMods: 1,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
// Make sure the regex can match across multiple lines
pattern := regexp.MustCompile("(?s)" + tt.regexPattern)
processor := NewRegexProcessor(pattern, &TestLogger{})
luaExpr := BuildLuaScript(tt.luaExpression)
// Process with our function
result, modCount, _, err := processor.ProcessContent(tt.input, luaExpr, "test", tt.luaExpression)
if err != nil {
t.Fatalf("Process function failed: %v", err)
}
// Check results
if result != tt.expectedOutput {
t.Errorf("Expected output: %s, got: %s", tt.expectedOutput, result)
}
if modCount != tt.expectedMods {
t.Errorf("Expected %d modifications, got %d", tt.expectedMods, modCount)
}
})
}
}
func TestBuildLuaScript(t *testing.T) {
testCases := []struct {
input string
expected string
}{
{"*1.5", "v1 = v1*1.5"},
{"/2", "v1 = v1/2"},
{"+10", "v1 = v1+10"},
{"-5", "v1 = v1-5"},
{"^2", "v1 = v1^2"},
{"%2", "v1 = v1%2"},
{"=100", "v1 =100"},
{"v1 * 2", "v1 = v1 * 2"},
{"v1 + v2", "v1 = v1 + v2"},
{"math.max(v1, 100)", "v1 = math.max(v1, 100)"},
// Added from main_test.go
{"s1 .. '_suffix'", "v1 = s1 .. '_suffix'"},
{"v1 * v2", "v1 = v1 * v2"},
{"s1 .. s2", "v1 = s1 .. s2"},
}
for _, tc := range testCases {
result := BuildLuaScript(tc.input)
if result != tc.expected {
t.Errorf("BuildLuaScript(%q): expected %q, got %q", tc.input, tc.expected, result)
}
}
}