diff --git a/src/pkg/filters/filters.go b/src/pkg/filters/filters.go index 4998c6684..8a2504f27 100644 --- a/src/pkg/filters/filters.go +++ b/src/pkg/filters/filters.go @@ -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 diff --git a/src/pkg/filters/filters_test.go b/src/pkg/filters/filters_test.go index 88c9c0e15..7ee32e3e0 100644 --- a/src/pkg/filters/filters_test.go +++ b/src/pkg/filters/filters_test.go @@ -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 { diff --git a/src/pkg/selectors/exchange.go b/src/pkg/selectors/exchange.go index 415c4106e..cc69fac58 100644 --- a/src/pkg/selectors/exchange.go +++ b/src/pkg/selectors/exchange.go @@ -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)), } } diff --git a/src/pkg/selectors/scopes_test.go b/src/pkg/selectors/scopes_test.go index 80b94b06f..8c033763c 100644 --- a/src/pkg/selectors/scopes_test.go +++ b/src/pkg/selectors/scopes_test.go @@ -518,7 +518,7 @@ func (suite *SelectorScopesSuite) TestWrapFilter() { }, { name: "none", - filter: filters.In, + filter: filters.Greater, input: None(), comparator: int(filters.Fails), target: NoneTgt,