From 750010b71abf3364dc0fbbe59f64fa1bc6f5b5c4 Mon Sep 17 00:00:00 2001 From: PhatPhuckDave Date: Fri, 28 Mar 2025 00:26:50 +0100 Subject: [PATCH] Add more tests to regex --- processor/regex_test.go | 367 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 366 insertions(+), 1 deletion(-) diff --git a/processor/regex_test.go b/processor/regex_test.go index d727c79..8af9f35 100644 --- a/processor/regex_test.go +++ b/processor/regex_test.go @@ -1,10 +1,16 @@ package processor import ( + "bytes" + "fmt" + "io" "modify/utils" + "os" "regexp" "strings" "testing" + + "github.com/stretchr/testify/assert" ) // TestLogger implements the Logger interface for testing @@ -12,7 +18,7 @@ type TestLogger struct { T *testing.T // Reference to the test's *testing.T } -func (l *TestLogger) Printf(format string, v ...interface{}) { +func (l *TestLogger) Printf(format string, v ...any) { if l.T != nil { l.T.Logf(format, v...) } @@ -1302,3 +1308,362 @@ func TestSimpleNamedCapture(t *testing.T) { t.Errorf("Expected content to be:\n%s\n\nGot:\n%s", expected, result) } } + +// Returns empty slice when input is empty +func TestDeduplicateGroupsWithEmptyInput(t *testing.T) { + // Arrange + var captureGroups []*CaptureGroup + + // Act + result := deduplicateGroups(captureGroups) + + // Assert + assert.Empty(t, result, "Expected empty slice when input is empty") +} + +// Input with all overlapping groups returns empty slice +func TestDeduplicateGroupsWithAllOverlappingGroups(t *testing.T) { + // Arrange + captureGroups := []*CaptureGroup{ + { + Name: "group1", + Range: [2]int{10, 20}, + }, + { + Name: "group2", + Range: [2]int{15, 25}, + }, + { + Name: "group3", + Range: [2]int{5, 15}, + }, + } + + // Act + result := deduplicateGroups(captureGroups) + + // Assert + assert.Len(t, result, 1, "Expected only one group to remain after deduplication") + assert.Equal(t, "group1", result[0].Name, "Expected first group to be kept") +} + +// Successfully adds non-overlapping capture groups to result +func TestDeduplicateGroupsWithNonOverlappingInput(t *testing.T) { + // Arrange + captureGroups := []*CaptureGroup{ + {Name: "Group1", Range: [2]int{0, 5}}, + {Name: "Group2", Range: [2]int{6, 10}}, + {Name: "Group3", Range: [2]int{11, 15}}, + } + + // Act + result := deduplicateGroups(captureGroups) + + // Assert + assert.Equal(t, 3, len(result), "Expected all non-overlapping groups to be added") + assert.Equal(t, "Group1", result[0].Name, "Expected Group1 to be in the result") + assert.Equal(t, "Group2", result[1].Name, "Expected Group2 to be in the result") + assert.Equal(t, "Group3", result[2].Name, "Expected Group3 to be in the result") +} + +// Correctly identifies and filters out overlapping capture groups +func TestDeduplicateGroupsWithOverlappingInput(t *testing.T) { + // Arrange + captureGroups := []*CaptureGroup{ + {Name: "group1", Range: [2]int{0, 5}}, + {Name: "group2", Range: [2]int{3, 8}}, // Overlaps with group1 + {Name: "group3", Range: [2]int{10, 15}}, + } + + // Act + result := deduplicateGroups(captureGroups) + + // Assert + assert.Len(t, result, 2, "Expected two non-overlapping capture groups") + assert.Equal(t, "group1", result[0].Name, "Expected group1 to be in the result") + assert.Equal(t, "group3", result[1].Name, "Expected group3 to be in the result") +} + +// Handles multiple non-overlapping groups correctly +func TestDeduplicateGroupsWithNonOverlappingGroups(t *testing.T) { + // Arrange + captureGroups := []*CaptureGroup{ + {Name: "Group1", Range: [2]int{0, 5}}, + {Name: "Group2", Range: [2]int{6, 10}}, + {Name: "Group3", Range: [2]int{11, 15}}, + } + + // Act + result := deduplicateGroups(captureGroups) + + // Assert + assert.Equal(t, 3, len(result), "Expected all groups to be included as they do not overlap") + assert.Equal(t, "Group1", result[0].Name, "Expected Group1 to be the first in the result") + assert.Equal(t, "Group2", result[1].Name, "Expected Group2 to be the second in the result") + assert.Equal(t, "Group3", result[2].Name, "Expected Group3 to be the third in the result") +} + +// Groups with identical ranges are considered overlapping +func TestDeduplicateGroupsWithIdenticalRanges(t *testing.T) { + // Arrange + captureGroups := []*CaptureGroup{ + {Name: "Group1", Range: [2]int{0, 5}}, + {Name: "Group2", Range: [2]int{0, 5}}, // Identical range to Group1 + } + + // Act + result := deduplicateGroups(captureGroups) + + // Assert + assert.Len(t, result, 1, "Expected only one group in the result due to identical ranges") + assert.Equal(t, "Group1", result[0].Name, "Expected Group1 to be in the result") +} + +// Groups with adjacent but non-overlapping ranges (end of one = start of another) +func TestDeduplicateGroupsWithAdjacentNonOverlappingRanges(t *testing.T) { + // Arrange + captureGroups := []*CaptureGroup{ + {Name: "Group1", Range: [2]int{0, 5}}, + {Name: "Group2", Range: [2]int{5, 10}}, + {Name: "Group3", Range: [2]int{10, 15}}, + } + + // Act + result := deduplicateGroups(captureGroups) + + // Assert + assert.Equal(t, 3, len(result), "Expected all groups to be included as they are adjacent but non-overlapping") + assert.Equal(t, "Group1", result[0].Name, "Expected Group1 to be the first in the result") + assert.Equal(t, "Group2", result[1].Name, "Expected Group2 to be the second in the result") + assert.Equal(t, "Group3", result[2].Name, "Expected Group3 to be the third in the result") +} + +// Pattern without "(?s)" prefix gets modified to include it +func TestPatternWithoutPrefixGetsModified(t *testing.T) { + // Setup + pattern := "some.*pattern" + + // Redirect stdout to capture fmt.Printf output + oldStdout := os.Stdout + r, w, _ := os.Pipe() + os.Stdout = w + + // Execute function + result := resolveRegexPlaceholders(pattern) + + // Restore stdout + w.Close() + os.Stdout = oldStdout + + // Read captured output + var buf bytes.Buffer + io.Copy(&buf, r) + output := buf.String() + + // Verify results + expectedPattern := "(?s)some.*pattern" + if result != expectedPattern { + t.Errorf("Expected pattern to be %q, got %q", expectedPattern, result) + } + + expectedOutput := fmt.Sprintf("Pattern modified to include (?s): %s\n", expectedPattern) + if output != expectedOutput { + t.Errorf("Expected output message %q, got %q", expectedOutput, output) + } +} + +// Empty string input returns "(?s)" +func TestEmptyStringReturnsWithPrefix(t *testing.T) { + // Setup + pattern := "" + + // Redirect stdout to capture fmt.Printf output + oldStdout := os.Stdout + r, w, _ := os.Pipe() + os.Stdout = w + + // Execute function + result := resolveRegexPlaceholders(pattern) + + // Restore stdout + w.Close() + os.Stdout = oldStdout + + // Read captured output + var buf bytes.Buffer + io.Copy(&buf, r) + output := buf.String() + + // Verify results + expectedPattern := "(?s)" + if result != expectedPattern { + t.Errorf("Expected pattern to be %q, got %q", expectedPattern, result) + } + + expectedOutput := fmt.Sprintf("Pattern modified to include (?s): %s\n", expectedPattern) + if output != expectedOutput { + t.Errorf("Expected output message %q, got %q", expectedOutput, output) + } +} + +// Named group with "!num" pattern gets replaced with proper regex for numbers +func TestNamedGroupNumPatternReplacement(t *testing.T) { + // Setup + pattern := "(?!num)" + + // Execute function + result := resolveRegexPlaceholders(pattern) + + // Verify results + expectedPattern := "(?s)(?-?\\d*\\.?\\d+)" + if result != expectedPattern { + t.Errorf("Expected pattern to be %q, got %q", expectedPattern, result) + } +} + +// "!any" placeholder gets replaced with ".*?" pattern +func TestAnyPlaceholderReplacement(t *testing.T) { + // Setup + pattern := "start!anyend" + + // Execute function + result := resolveRegexPlaceholders(pattern) + + // Verify results + expectedPattern := "(?s)start.*?end" + if result != expectedPattern { + t.Errorf("Expected pattern to be %q, got %q", expectedPattern, result) + } +} + +// "!rep(pattern, count)" correctly repeats the pattern with separators +func TestRepPatternRepetition(t *testing.T) { + // Setup + pattern := "!rep(a, 3)" + + // Execute function + result := resolveRegexPlaceholders(pattern) + + // Verify results + expectedPattern := "a.*?a.*?a" + if result != expectedPattern { + t.Errorf("Expected pattern to be %q, got %q", expectedPattern, result) + } +} + +// Multiple different placeholders in the same pattern are all correctly replaced +func TestMultiplePlaceholdersReplacedCorrectly(t *testing.T) { + // Setup + pattern := "(?s)some(?!num)text!anymore!rep(!num, 3)" + + // Redirect stdout to capture fmt.Printf output + oldStdout := os.Stdout + r, w, _ := os.Pipe() + os.Stdout = w + + // Execute function + result := resolveRegexPlaceholders(pattern) + + // Restore stdout + w.Close() + os.Stdout = oldStdout + + // Read captured output + var buf bytes.Buffer + io.Copy(&buf, r) + output := buf.String() + + // Verify results + expectedPattern := "(?s)some(?-?\\d*\\.?\\d+)text.*?more-?\\d*\\.?\\d+.*?-?\\d*\\.?\\d+.*?-?\\d*\\.?\\d+" + if result != expectedPattern { + t.Errorf("Expected pattern to be %q, got %q", expectedPattern, result) + } + + expectedOutput := fmt.Sprintf("Pattern modified to include (?s): %s\n", pattern) + if output != expectedOutput { + t.Errorf("Expected output message %q, got %q", expectedOutput, output) + } +} + +// Pattern already containing "(?s)" prefix remains unchanged +func TestPatternWithPrefixRemainsUnchanged(t *testing.T) { + // Setup + pattern := "(?s)some.*pattern" + + // Redirect stdout to capture fmt.Printf output + oldStdout := os.Stdout + r, w, _ := os.Pipe() + os.Stdout = w + + // Execute function + result := resolveRegexPlaceholders(pattern) + + // Restore stdout + w.Close() + os.Stdout = oldStdout + + // Read captured output + var buf bytes.Buffer + io.Copy(&buf, r) + output := buf.String() + + // Verify results + expectedPattern := "(?s)some.*pattern" + if result != expectedPattern { + t.Errorf("Expected pattern to remain %q, got %q", expectedPattern, result) + } + + expectedOutput := "" + if output != expectedOutput { + t.Errorf("Expected no output message, got %q", output) + } +} + +// Malformed "!rep" pattern without proper parameters returns unchanged match +func TestMalformedRepPatternReturnsUnchanged(t *testing.T) { + // Setup + pattern := "!rep(somepattern)" // Malformed !rep pattern without count + + // Execute function + result := resolveRegexPlaceholders(pattern) + + // Verify results + expectedPattern := "!rep(somepattern)" + if result != expectedPattern { + t.Errorf("Expected pattern to be %q, got %q", expectedPattern, result) + } +} + +// Nested placeholder patterns (e.g., "!rep(!num, 3)") +func TestNestedPlaceholderPatterns(t *testing.T) { + // Setup + pattern := "!rep(!num, 3)" + + // Redirect stdout to capture fmt.Printf output + oldStdout := os.Stdout + r, w, _ := os.Pipe() + os.Stdout = w + + // Execute function + result := resolveRegexPlaceholders(pattern) + + // Restore stdout + w.Close() + os.Stdout = oldStdout + + // Read captured output + var buf bytes.Buffer + io.Copy(&buf, r) + output := buf.String() + + // Verify results + expectedPattern := `"?(-?\d*\.?\d+)".*?"?(-?\d*\.?\d+)".*?"?(-?\d*\.?\d+)"` + if result != expectedPattern { + t.Errorf("Expected pattern to be %q, got %q", expectedPattern, result) + } + + expectedOutput := fmt.Sprintf("Pattern modified to include (?s): %s\n", expectedPattern) + if output != expectedOutput { + t.Errorf("Expected output message %q, got %q", expectedOutput, output) + } +}