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) } } }