From 3d6f58bf4608f3a2a8e130734c64c192130ca8a9 Mon Sep 17 00:00:00 2001 From: Mohammed Al Sahaf Date: Tue, 21 Oct 2025 00:40:48 +0300 Subject: [PATCH] rewrite utility funcs tests Signed-off-by: Mohammed Al Sahaf --- .../caddyhttp/rewrite/rewrite_utils_test.go | 194 ++++++++++++++++++ 1 file changed, 194 insertions(+) create mode 100644 modules/caddyhttp/rewrite/rewrite_utils_test.go diff --git a/modules/caddyhttp/rewrite/rewrite_utils_test.go b/modules/caddyhttp/rewrite/rewrite_utils_test.go new file mode 100644 index 000000000..e1d0878f9 --- /dev/null +++ b/modules/caddyhttp/rewrite/rewrite_utils_test.go @@ -0,0 +1,194 @@ +// Copyright 2015 Matthew Holt and The Caddy Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package rewrite + +import ( + "testing" +) + +func TestReverse(t *testing.T) { + tests := []struct { + name string + input string + expected string + }{ + { + name: "simple string", + input: "hello", + expected: "olleh", + }, + { + name: "empty string", + input: "", + expected: "", + }, + { + name: "single character", + input: "a", + expected: "a", + }, + { + name: "two characters", + input: "ab", + expected: "ba", + }, + { + name: "palindrome", + input: "racecar", + expected: "racecar", + }, + { + name: "with spaces", + input: "hello world", + expected: "dlrow olleh", + }, + { + name: "with numbers", + input: "abc123", + expected: "321cba", + }, + { + name: "unicode characters", + input: "helloไธ–็•Œ", + expected: "็•Œไธ–olleh", + }, + { + name: "emoji", + input: "๐ŸŽ‰๐ŸŽŠ๐ŸŽˆ", + expected: "๐ŸŽˆ๐ŸŽŠ๐ŸŽ‰", + }, + { + name: "mixed unicode and ascii", + input: "cafรฉโ˜•", + expected: "โ˜•รฉfac", + }, + { + name: "special characters", + input: "a!b@c#d$", + expected: "$d#c@b!a", + }, + { + name: "path-like string", + input: "/path/to/file", + expected: "elif/ot/htap/", + }, + { + name: "url-like string", + input: "https://example.com", + expected: "moc.elpmaxe//:sptth", + }, + { + name: "long string", + input: "The quick brown fox jumps over the lazy dog", + expected: "god yzal eht revo spmuj xof nworb kciuq ehT", + }, + { + name: "newlines", + input: "line1\nline2\nline3", + expected: "3enil\n2enil\n1enil", + }, + { + name: "tabs", + input: "a\tb\tc", + expected: "c\tb\ta", + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + result := reverse(tt.input) + if result != tt.expected { + t.Errorf("reverse(%q) = %q; want %q", tt.input, result, tt.expected) + } + + // Test that reversing twice gives the original string + if tt.input != "" { + doubleReverse := reverse(reverse(tt.input)) + if doubleReverse != tt.input { + t.Errorf("reverse(reverse(%q)) = %q; want %q", tt.input, doubleReverse, tt.input) + } + } + }) + } +} + +func TestReverse_LengthPreservation(t *testing.T) { + // Test that reverse preserves string length + testStrings := []string{ + "", + "a", + "ab", + "abc", + "hello world", + "๐ŸŽ‰๐ŸŽŠ๐ŸŽˆ", + "cafรฉโ˜•", + "The quick brown fox jumps over the lazy dog", + } + + for _, s := range testStrings { + reversed := reverse(s) + if len([]rune(s)) != len([]rune(reversed)) { + t.Errorf("reverse(%q) changed length: original %d, reversed %d", s, len([]rune(s)), len([]rune(reversed))) + } + } +} + +// BenchmarkReverse benchmarks the reverse function +func BenchmarkReverse(b *testing.B) { + testCases := []struct { + name string + input string + }{ + {"empty", ""}, + {"short", "hello"}, + {"medium", "The quick brown fox jumps over the lazy dog"}, + {"long", "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua."}, + {"unicode", "helloไธ–็•Œ๐ŸŽ‰"}, + } + + for _, tc := range testCases { + b.Run(tc.name, func(b *testing.B) { + for i := 0; i < b.N; i++ { + reverse(tc.input) + } + }) + } +} + +func TestReverse_EdgeCases(t *testing.T) { + tests := []struct { + name string + input string + }{ + {"null byte", "\x00"}, + {"multiple null bytes", "\x00\x00\x00"}, + {"control characters", "\t\n\r"}, + {"high unicode", "๐•ณ๐–Š๐–‘๐–‘๐–”"}, + {"zero-width characters", "a\u200Bb\u200Cc"}, + {"combining characters", "รฉ"}, // e + combining acute + {"rtl text", "ู…ุฑุญุจุง"}, + {"mixed rtl/ltr", "Hello ู…ุฑุญุจุง World"}, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + result := reverse(tt.input) + // Just ensure it doesn't panic and returns something + if result == "" && tt.input != "" { + t.Errorf("reverse(%q) returned empty string", tt.input) + } + }) + } +}