Use slice filter for In filter (#2735)

Have the `In` filter take a slice of values instead
of a joined string. Change negated slice filter behavior
to be the boolean negation instead of
(!filter-val-1 || !filter-val-2 || ...)

---

#### Does this PR need a docs update or release note?

- [ ]  Yes, it's included
- [ ] 🕐 Yes, but in a later PR
- [x]  No

#### Type of change

- [ ] 🌻 Feature
- [ ] 🐛 Bugfix
- [ ] 🗺️ Documentation
- [ ] 🤖 Test
- [ ] 💻 CI/Deployment
- [x] 🧹 Tech Debt/Cleanup

#### Issue(s)

* #1535

#### Test Plan

- [ ] 💪 Manual
- [x]  Unit test
- [ ] 💚 E2E
This commit is contained in:
ashmrtn 2023-03-08 17:02:32 -08:00 committed by GitHub
parent 23b90f9bec
commit f28da24153
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 76 additions and 26 deletions

View File

@ -129,14 +129,14 @@ func NotContains(target string) Filter {
// In creates a filter where Compare(v) is true if
// v.Contains(target)
func In(target string) Filter {
return newFilter(TargetIn, target, false)
func In(targets []string) Filter {
return newSliceFilter(TargetIn, targets, targets, false)
}
// NotIn creates a filter where Compare(v) is true if
// !v.Contains(target)
func NotIn(target string) Filter {
return newFilter(TargetIn, target, true)
func NotIn(targets []string) Filter {
return newSliceFilter(TargetIn, targets, targets, true)
}
// Pass creates a filter where Compare(v) always returns true
@ -394,6 +394,7 @@ func (f Filter) Compare(input string) bool {
cmp = contains
case TargetIn:
cmp = in
hasSlice = true
case TargetPrefixes:
cmp = prefixed
case TargetSuffixes:
@ -416,24 +417,29 @@ func (f Filter) Compare(input string) bool {
return false
}
targets := []string{f.Target}
var (
res bool
targets = []string{f.Target}
)
if hasSlice {
targets = f.NormalizedTargets
}
for _, tgt := range targets {
success := cmp(norm(tgt), norm(input))
if f.Negate {
success = !success
}
res = cmp(norm(tgt), norm(input))
// any-match
if success {
return true
if res {
break
}
}
return false
if f.Negate {
res = !res
}
return res
}
// true if t == i

View File

@ -155,8 +155,8 @@ func (suite *FiltersSuite) TestContains_Joined() {
}
func (suite *FiltersSuite) TestIn() {
f := filters.In("murf")
nf := filters.NotIn("murf")
f := filters.In([]string{"murf"})
nf := filters.NotIn([]string{"murf"})
table := []struct {
input string
@ -176,9 +176,53 @@ func (suite *FiltersSuite) TestIn() {
}
}
func (suite *FiltersSuite) TestIn_MultipleTargets() {
f := filters.In([]string{"murf", "foo"})
nf := filters.NotIn([]string{"murf", "foo"})
table := []struct {
input string
expectF assert.BoolAssertionFunc
expectNF assert.BoolAssertionFunc
}{
{"smurfs", assert.True, assert.False},
{"foo", assert.True, assert.False},
{"sfrums", assert.False, assert.True},
{"oof", assert.False, assert.True},
}
for _, test := range table {
suite.T().Run(test.input, func(t *testing.T) {
test.expectF(t, f.Compare(test.input), "filter")
test.expectNF(t, nf.Compare(test.input), "negated filter")
})
}
}
func (suite *FiltersSuite) TestIn_MultipleTargets_Joined() {
f := filters.In([]string{"userid", "foo"})
nf := filters.NotIn([]string{"userid", "foo"})
table := []struct {
input string
expectF assert.BoolAssertionFunc
expectNF assert.BoolAssertionFunc
}{
{"smarf,userid", assert.True, assert.False},
{"smarf,foo", assert.True, assert.False},
{"arf,user", assert.False, assert.True},
{"arf,oof", assert.False, assert.True},
}
for _, test := range table {
suite.T().Run(test.input, func(t *testing.T) {
test.expectF(t, f.Compare(test.input), "filter")
test.expectNF(t, nf.Compare(test.input), "negated filter")
})
}
}
func (suite *FiltersSuite) TestIn_Joined() {
f := filters.In("userid")
nf := filters.NotIn("userid")
f := filters.In([]string{"userid"})
nf := filters.NotIn([]string{"userid"})
table := []struct {
input string
@ -287,7 +331,7 @@ func (suite *FiltersSuite) TestPathPrefix() {
{"Prefix - input variations - prefix", []string{"fA"}, "/fA/fb", assert.True, assert.False},
{"Prefix - input variations - suffix", []string{"fA"}, "fA/fb/", assert.True, assert.False},
{"Prefix - input variations - both", []string{"fA"}, "/fA/fb/", assert.True, assert.False},
{"Slice - one matches", []string{"foo", "fa/f", "fA"}, "/fA/fb", assert.True, assert.True},
{"Slice - one matches", []string{"foo", "fa/f", "fA"}, "/fA/fb", assert.True, assert.False},
{"Slice - none match", []string{"foo", "fa/f", "f"}, "/fA/fb", assert.False, assert.True},
}
for _, test := range table {
@ -370,7 +414,7 @@ func (suite *FiltersSuite) TestPathContains() {
{"Cont - input variations - prefix", []string{"fA"}, "/fA/fb", assert.True, assert.False},
{"Cont - input variations - suffix", []string{"fA"}, "fA/fb/", assert.True, assert.False},
{"Cont - input variations - both", []string{"fA"}, "/fA/fb/", assert.True, assert.False},
{"Slice - one matches", []string{"foo", "fa/f", "fA"}, "/fA/fb", assert.True, assert.True},
{"Slice - one matches", []string{"foo", "fa/f", "fA"}, "/fA/fb", assert.True, assert.False},
{"Slice - none match", []string{"foo", "fa/f", "f"}, "/fA/fb", assert.False, assert.True},
}
for _, test := range table {
@ -450,7 +494,7 @@ func (suite *FiltersSuite) TestPathSuffix() {
{"Suffix - input variations - prefix", []string{"fb"}, "/fA/fb", assert.True, assert.False},
{"Suffix - input variations - suffix", []string{"fb"}, "fA/fb/", assert.True, assert.False},
{"Suffix - input variations - both", []string{"fb"}, "/fA/fb/", assert.True, assert.False},
{"Slice - one matches", []string{"foo", "fa/f", "fb"}, "/fA/fb", assert.True, assert.True},
{"Slice - one matches", []string{"foo", "fa/f", "fb"}, "/fA/fb", assert.True, assert.False},
{"Slice - none match", []string{"foo", "fa/f", "f"}, "/fA/fb", assert.False, assert.True},
}
for _, test := range table {
@ -521,7 +565,7 @@ func (suite *FiltersSuite) TestPathEquals() {
{"Prefix - different case", []string{"fa"}, "/fA/fB", assert.False, assert.True},
{"Contains - same case", []string{"fB"}, "/fA/fB/fC", assert.False, assert.True},
{"Contains - different case", []string{"fb"}, "/fA/fB/fC", assert.False, assert.True},
{"Slice - one matches", []string{"foo", "/fA/fb", "fb"}, "/fA/fb", assert.True, assert.True},
{"Slice - one matches", []string{"foo", "/fA/fb", "fb"}, "/fA/fb", assert.True, assert.False},
{"Slice - none match", []string{"foo", "fa/f", "f"}, "/fA/fb", assert.False, assert.True},
}
for _, test := range table {

View File

@ -334,7 +334,7 @@ func (sr *ExchangeRestore) ContactName(senderID string) []ExchangeScope {
ExchangeContact,
ExchangeFilterContactName,
[]string{senderID},
wrapFilter(filters.In)),
wrapSliceFilter(filters.In)),
}
}
@ -349,7 +349,7 @@ func (sr *ExchangeRestore) EventOrganizer(organizer string) []ExchangeScope {
ExchangeEvent,
ExchangeFilterEventOrganizer,
[]string{organizer},
wrapFilter(filters.In)),
wrapSliceFilter(filters.In)),
}
}
@ -407,7 +407,7 @@ func (sr *ExchangeRestore) EventSubject(subject string) []ExchangeScope {
ExchangeEvent,
ExchangeFilterEventSubject,
[]string{subject},
wrapFilter(filters.In)),
wrapSliceFilter(filters.In)),
}
}
@ -450,7 +450,7 @@ func (sr *ExchangeRestore) MailSender(sender string) []ExchangeScope {
ExchangeMail,
ExchangeFilterMailSender,
[]string{sender},
wrapFilter(filters.In)),
wrapSliceFilter(filters.In)),
}
}
@ -465,7 +465,7 @@ func (sr *ExchangeRestore) MailSubject(subject string) []ExchangeScope {
ExchangeMail,
ExchangeFilterMailSubject,
[]string{subject},
wrapFilter(filters.In)),
wrapSliceFilter(filters.In)),
}
}

View File

@ -518,7 +518,7 @@ func (suite *SelectorScopesSuite) TestWrapFilter() {
},
{
name: "none",
filter: filters.In,
filter: filters.Greater,
input: None(),
comparator: int(filters.Fails),
target: NoneTgt,