mirror of
https://github.com/idanoo/autobrr
synced 2025-07-23 16:59:12 +00:00
feat(filters): wildcard slice matching optimizations (#1716)
* chore(tests): add more test cases * chore(tests): add code comments for matching patterns * chore(tests): fix typos --------- Co-authored-by: martylukyy <35452459+martylukyy@users.noreply.github.com>
This commit is contained in:
parent
3af06553e7
commit
e9f8730ca0
5 changed files with 279 additions and 48 deletions
|
@ -3,10 +3,13 @@
|
|||
|
||||
package wildcard
|
||||
|
||||
import "testing"
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
// TestMatch - Tests validate the logic of wild card matching.
|
||||
// `Match` supports '*' and '?' wildcards.
|
||||
// `Match` supports '*' (zero or more characters) and '?' (one character) wildcards in typical glob style filtering.
|
||||
// A '*' in a provided string will not result in matching the strings before and after the '*' of the string provided.
|
||||
// Sample usage: In resource matching for bucket policy validation.
|
||||
func TestMatch(t *testing.T) {
|
||||
testCases := []struct {
|
||||
|
@ -59,8 +62,33 @@ func TestMatch(t *testing.T) {
|
|||
text: "Good show shift S02 2160p ATVP WEB-DL DDP 5.1 Atmos DV HEVC-GROUP",
|
||||
matched: true,
|
||||
},
|
||||
{
|
||||
pattern: "The God of the Brr*The Power of Brr",
|
||||
text: "The Power of Brr",
|
||||
matched: false,
|
||||
},
|
||||
{
|
||||
pattern: "The God of the Brr*The Power of Brr",
|
||||
text: "The God of the Brr",
|
||||
matched: false,
|
||||
},
|
||||
{
|
||||
pattern: "The God of the Brr*The Power of Brr",
|
||||
text: "The God of the Brr The Power of Brr",
|
||||
matched: true,
|
||||
},
|
||||
{
|
||||
pattern: "The God of the Brr*The Power of Brr",
|
||||
text: "The God of the Brr - The Power of Brr",
|
||||
matched: true,
|
||||
},
|
||||
{
|
||||
pattern: "The God of the Brr*The Power of Brr",
|
||||
text: "The God of the BrrThe Power of Brr",
|
||||
matched: true,
|
||||
},
|
||||
}
|
||||
// Iterating over the test cases, call the function under test and asert the output.
|
||||
// Iterating over the test cases, call the function under test and assert the output.
|
||||
for i, testCase := range testCases {
|
||||
actualResult := Match(testCase.pattern, testCase.text)
|
||||
if testCase.matched != actualResult {
|
||||
|
@ -68,3 +96,97 @@ func TestMatch(t *testing.T) {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestMatchSimple(t *testing.T) {
|
||||
tests := []struct {
|
||||
pattern string
|
||||
name string
|
||||
want bool
|
||||
}{
|
||||
{"", "", true},
|
||||
{"*", "test", true},
|
||||
{"t*t", "test", true},
|
||||
{"t*t", "tost", true},
|
||||
{"t?st", "test", false},
|
||||
{"t?st", "tast", false},
|
||||
{"test", "test", true},
|
||||
{"test", "toast", false},
|
||||
{"", "non-empty", false},
|
||||
{"*", "", true},
|
||||
{"te*t", "test", true},
|
||||
{"te*", "te", true},
|
||||
{"te*", "ten", true},
|
||||
{"?est", "test", false},
|
||||
{"best", "best", true},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
if got := MatchSimple(tt.pattern, tt.name); got != tt.want {
|
||||
t.Errorf("MatchSimple(%q, %q) = %v, want %v", tt.pattern, tt.name, got, tt.want)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestMatchSliceSimple(t *testing.T) {
|
||||
tests := []struct {
|
||||
patterns []string
|
||||
name string
|
||||
want bool
|
||||
}{
|
||||
{[]string{"*", "test"}, "test", true},
|
||||
{[]string{"te?t", "tost", "random"}, "tost", true},
|
||||
{[]string{"*st", "n?st", "l*st"}, "list", true},
|
||||
{[]string{"?", "?*", "?**"}, "t", false},
|
||||
{[]string{"a", "b", "c"}, "d", false},
|
||||
{[]string{}, "test", false},
|
||||
{[]string{"*"}, "any", true},
|
||||
{[]string{"abc", "def", "ghi"}, "ghi", true},
|
||||
{[]string{"abc", "def", "ghi"}, "xyz", false},
|
||||
{[]string{"abc*", "def*", "ghi*"}, "ghi-test", true},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
if got := MatchSliceSimple(tt.patterns, tt.name); got != tt.want {
|
||||
t.Errorf("MatchSliceSimple(%v, %q) = %v, want %v", tt.patterns, tt.name, got, tt.want)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestMatchSlice(t *testing.T) {
|
||||
tests := []struct {
|
||||
patterns []string
|
||||
name string
|
||||
want bool
|
||||
}{
|
||||
{[]string{"*", "test", "t?st"}, "test", true},
|
||||
{[]string{"te?t", "t?st", "random"}, "tost", true},
|
||||
{[]string{"*st", "n?st", "l*st"}, "list", true},
|
||||
{[]string{"?", "??", "???"}, "t", true},
|
||||
{[]string{"a", "b", "c"}, "d", false},
|
||||
{[]string{}, "test", false},
|
||||
{[]string{"*"}, "any", true},
|
||||
{[]string{"abc", "def", "ghi"}, "ghi", true},
|
||||
{[]string{"abc", "def", "ghi"}, "xyz", false},
|
||||
{[]string{"abc*", "def*", "ghi*"}, "ghi-test", true},
|
||||
{[]string{"abc?", "def?", "ghi?"}, "ghiz", true},
|
||||
{[]string{"abc?", "def?", "ghi?"}, "ghizz", false},
|
||||
{[]string{"a*?", "b*?", "c*?"}, "cwhatever", true},
|
||||
{[]string{"a*?", "b*?", "c*?"}, "dwhatever", false},
|
||||
{[]string{"*"}, "", true},
|
||||
{[]string{"abc"}, "abc", true},
|
||||
{[]string{"?bc"}, "abc", true},
|
||||
{[]string{"abc*"}, "abcd", true},
|
||||
{[]string{"guacamole", "The?Simpsons*"}, "The Simpsons S12", true},
|
||||
{[]string{"guacamole*", "The?Sompsons*"}, "The Simpsons S12", false},
|
||||
{[]string{"guac?mole*", "The?S?mpson"}, "The Simpsons S12", false},
|
||||
{[]string{"guac?mole*", "The?S?mpson"}, "guacamole Tornado", true},
|
||||
{[]string{"mole*", "The?S?mpson"}, "guacamole Tornado", false},
|
||||
{[]string{"??**mole*", "The?S?mpson"}, "guacamole Tornado", true},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
if got := MatchSlice(tt.patterns, tt.name); got != tt.want {
|
||||
t.Errorf("MatchSlice(%v, %q) = %v, want %v", tt.patterns, tt.name, got, tt.want)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue