mirror of https://github.com/grpc/grpc-go.git
316 lines
8.8 KiB
Go
316 lines
8.8 KiB
Go
/*
|
|
*
|
|
* Copyright 2021 gRPC 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 matcher
|
|
|
|
import (
|
|
"regexp"
|
|
"testing"
|
|
|
|
v3matcherpb "github.com/envoyproxy/go-control-plane/envoy/type/matcher/v3"
|
|
"github.com/google/go-cmp/cmp"
|
|
)
|
|
|
|
func TestStringMatcherFromProto(t *testing.T) {
|
|
tests := []struct {
|
|
desc string
|
|
inputProto *v3matcherpb.StringMatcher
|
|
wantMatcher StringMatcher
|
|
wantErr bool
|
|
}{
|
|
{
|
|
desc: "nil proto",
|
|
wantErr: true,
|
|
},
|
|
{
|
|
desc: "empty prefix",
|
|
inputProto: &v3matcherpb.StringMatcher{
|
|
MatchPattern: &v3matcherpb.StringMatcher_Prefix{Prefix: ""},
|
|
},
|
|
wantErr: true,
|
|
},
|
|
{
|
|
desc: "empty suffix",
|
|
inputProto: &v3matcherpb.StringMatcher{
|
|
MatchPattern: &v3matcherpb.StringMatcher_Suffix{Suffix: ""},
|
|
},
|
|
wantErr: true,
|
|
},
|
|
{
|
|
desc: "empty contains",
|
|
inputProto: &v3matcherpb.StringMatcher{
|
|
MatchPattern: &v3matcherpb.StringMatcher_Contains{Contains: ""},
|
|
},
|
|
wantErr: true,
|
|
},
|
|
{
|
|
desc: "invalid regex",
|
|
inputProto: &v3matcherpb.StringMatcher{
|
|
MatchPattern: &v3matcherpb.StringMatcher_SafeRegex{
|
|
SafeRegex: &v3matcherpb.RegexMatcher{Regex: "??"},
|
|
},
|
|
},
|
|
wantErr: true,
|
|
},
|
|
{
|
|
desc: "happy case exact",
|
|
inputProto: &v3matcherpb.StringMatcher{
|
|
MatchPattern: &v3matcherpb.StringMatcher_Exact{Exact: "exact"},
|
|
},
|
|
wantMatcher: StringMatcher{exactMatch: newStringP("exact")},
|
|
},
|
|
{
|
|
desc: "happy case exact ignore case",
|
|
inputProto: &v3matcherpb.StringMatcher{
|
|
MatchPattern: &v3matcherpb.StringMatcher_Exact{Exact: "EXACT"},
|
|
IgnoreCase: true,
|
|
},
|
|
wantMatcher: StringMatcher{
|
|
exactMatch: newStringP("exact"),
|
|
ignoreCase: true,
|
|
},
|
|
},
|
|
{
|
|
desc: "happy case prefix",
|
|
inputProto: &v3matcherpb.StringMatcher{
|
|
MatchPattern: &v3matcherpb.StringMatcher_Prefix{Prefix: "prefix"},
|
|
},
|
|
wantMatcher: StringMatcher{prefixMatch: newStringP("prefix")},
|
|
},
|
|
{
|
|
desc: "happy case prefix ignore case",
|
|
inputProto: &v3matcherpb.StringMatcher{
|
|
MatchPattern: &v3matcherpb.StringMatcher_Prefix{Prefix: "PREFIX"},
|
|
IgnoreCase: true,
|
|
},
|
|
wantMatcher: StringMatcher{
|
|
prefixMatch: newStringP("prefix"),
|
|
ignoreCase: true,
|
|
},
|
|
},
|
|
{
|
|
desc: "happy case suffix",
|
|
inputProto: &v3matcherpb.StringMatcher{
|
|
MatchPattern: &v3matcherpb.StringMatcher_Suffix{Suffix: "suffix"},
|
|
},
|
|
wantMatcher: StringMatcher{suffixMatch: newStringP("suffix")},
|
|
},
|
|
{
|
|
desc: "happy case suffix ignore case",
|
|
inputProto: &v3matcherpb.StringMatcher{
|
|
MatchPattern: &v3matcherpb.StringMatcher_Suffix{Suffix: "SUFFIX"},
|
|
IgnoreCase: true,
|
|
},
|
|
wantMatcher: StringMatcher{
|
|
suffixMatch: newStringP("suffix"),
|
|
ignoreCase: true,
|
|
},
|
|
},
|
|
{
|
|
desc: "happy case regex",
|
|
inputProto: &v3matcherpb.StringMatcher{
|
|
MatchPattern: &v3matcherpb.StringMatcher_SafeRegex{
|
|
SafeRegex: &v3matcherpb.RegexMatcher{Regex: "good?regex?"},
|
|
},
|
|
},
|
|
wantMatcher: StringMatcher{regexMatch: regexp.MustCompile("good?regex?")},
|
|
},
|
|
{
|
|
desc: "happy case contains",
|
|
inputProto: &v3matcherpb.StringMatcher{
|
|
MatchPattern: &v3matcherpb.StringMatcher_Contains{Contains: "contains"},
|
|
},
|
|
wantMatcher: StringMatcher{containsMatch: newStringP("contains")},
|
|
},
|
|
{
|
|
desc: "happy case contains ignore case",
|
|
inputProto: &v3matcherpb.StringMatcher{
|
|
MatchPattern: &v3matcherpb.StringMatcher_Contains{Contains: "CONTAINS"},
|
|
IgnoreCase: true,
|
|
},
|
|
wantMatcher: StringMatcher{
|
|
containsMatch: newStringP("contains"),
|
|
ignoreCase: true,
|
|
},
|
|
},
|
|
}
|
|
|
|
for _, test := range tests {
|
|
t.Run(test.desc, func(t *testing.T) {
|
|
gotMatcher, err := StringMatcherFromProto(test.inputProto)
|
|
if (err != nil) != test.wantErr {
|
|
t.Fatalf("StringMatcherFromProto(%+v) returned err: %v, wantErr: %v", test.inputProto, err, test.wantErr)
|
|
}
|
|
if diff := cmp.Diff(gotMatcher, test.wantMatcher, cmp.AllowUnexported(regexp.Regexp{})); diff != "" {
|
|
t.Fatalf("StringMatcherFromProto(%+v) returned unexpected diff (-got, +want):\n%s", test.inputProto, diff)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestMatch(t *testing.T) {
|
|
var (
|
|
exactMatcher, _ = StringMatcherFromProto(&v3matcherpb.StringMatcher{MatchPattern: &v3matcherpb.StringMatcher_Exact{Exact: "exact"}})
|
|
prefixMatcher, _ = StringMatcherFromProto(&v3matcherpb.StringMatcher{MatchPattern: &v3matcherpb.StringMatcher_Prefix{Prefix: "prefix"}})
|
|
suffixMatcher, _ = StringMatcherFromProto(&v3matcherpb.StringMatcher{MatchPattern: &v3matcherpb.StringMatcher_Suffix{Suffix: "suffix"}})
|
|
regexMatcher, _ = StringMatcherFromProto(&v3matcherpb.StringMatcher{MatchPattern: &v3matcherpb.StringMatcher_SafeRegex{SafeRegex: &v3matcherpb.RegexMatcher{Regex: "good?regex?"}}})
|
|
containsMatcher, _ = StringMatcherFromProto(&v3matcherpb.StringMatcher{MatchPattern: &v3matcherpb.StringMatcher_Contains{Contains: "contains"}})
|
|
exactMatcherIgnoreCase, _ = StringMatcherFromProto(&v3matcherpb.StringMatcher{
|
|
MatchPattern: &v3matcherpb.StringMatcher_Exact{Exact: "exact"},
|
|
IgnoreCase: true,
|
|
})
|
|
prefixMatcherIgnoreCase, _ = StringMatcherFromProto(&v3matcherpb.StringMatcher{
|
|
MatchPattern: &v3matcherpb.StringMatcher_Prefix{Prefix: "prefix"},
|
|
IgnoreCase: true,
|
|
})
|
|
suffixMatcherIgnoreCase, _ = StringMatcherFromProto(&v3matcherpb.StringMatcher{
|
|
MatchPattern: &v3matcherpb.StringMatcher_Suffix{Suffix: "suffix"},
|
|
IgnoreCase: true,
|
|
})
|
|
containsMatcherIgnoreCase, _ = StringMatcherFromProto(&v3matcherpb.StringMatcher{
|
|
MatchPattern: &v3matcherpb.StringMatcher_Contains{Contains: "contains"},
|
|
IgnoreCase: true,
|
|
})
|
|
)
|
|
|
|
tests := []struct {
|
|
desc string
|
|
matcher StringMatcher
|
|
input string
|
|
wantMatch bool
|
|
}{
|
|
{
|
|
desc: "exact match success",
|
|
matcher: exactMatcher,
|
|
input: "exact",
|
|
wantMatch: true,
|
|
},
|
|
{
|
|
desc: "exact match failure",
|
|
matcher: exactMatcher,
|
|
input: "not-exact",
|
|
},
|
|
{
|
|
desc: "exact match success with ignore case",
|
|
matcher: exactMatcherIgnoreCase,
|
|
input: "EXACT",
|
|
wantMatch: true,
|
|
},
|
|
{
|
|
desc: "exact match failure with ignore case",
|
|
matcher: exactMatcherIgnoreCase,
|
|
input: "not-exact",
|
|
},
|
|
{
|
|
desc: "prefix match success",
|
|
matcher: prefixMatcher,
|
|
input: "prefixIsHere",
|
|
wantMatch: true,
|
|
},
|
|
{
|
|
desc: "prefix match failure",
|
|
matcher: prefixMatcher,
|
|
input: "not-prefix",
|
|
},
|
|
{
|
|
desc: "prefix match success with ignore case",
|
|
matcher: prefixMatcherIgnoreCase,
|
|
input: "PREFIXisHere",
|
|
wantMatch: true,
|
|
},
|
|
{
|
|
desc: "prefix match failure with ignore case",
|
|
matcher: prefixMatcherIgnoreCase,
|
|
input: "not-PREFIX",
|
|
},
|
|
{
|
|
desc: "suffix match success",
|
|
matcher: suffixMatcher,
|
|
input: "hereIsThesuffix",
|
|
wantMatch: true,
|
|
},
|
|
{
|
|
desc: "suffix match failure",
|
|
matcher: suffixMatcher,
|
|
input: "suffix-is-not-here",
|
|
},
|
|
{
|
|
desc: "suffix match success with ignore case",
|
|
matcher: suffixMatcherIgnoreCase,
|
|
input: "hereIsTheSuFFix",
|
|
wantMatch: true,
|
|
},
|
|
{
|
|
desc: "suffix match failure with ignore case",
|
|
matcher: suffixMatcherIgnoreCase,
|
|
input: "SUFFIX-is-not-here",
|
|
},
|
|
{
|
|
desc: "regex match success",
|
|
matcher: regexMatcher,
|
|
input: "goodregex",
|
|
wantMatch: true,
|
|
},
|
|
{
|
|
desc: "regex match failure because only part match",
|
|
matcher: regexMatcher,
|
|
input: "goodregexa",
|
|
wantMatch: false,
|
|
},
|
|
{
|
|
desc: "regex match failure",
|
|
matcher: regexMatcher,
|
|
input: "regex-is-not-here",
|
|
},
|
|
{
|
|
desc: "contains match success",
|
|
matcher: containsMatcher,
|
|
input: "IScontainsHERE",
|
|
wantMatch: true,
|
|
},
|
|
{
|
|
desc: "contains match failure",
|
|
matcher: containsMatcher,
|
|
input: "con-tains-is-not-here",
|
|
},
|
|
{
|
|
desc: "contains match success with ignore case",
|
|
matcher: containsMatcherIgnoreCase,
|
|
input: "isCONTAINShere",
|
|
wantMatch: true,
|
|
},
|
|
{
|
|
desc: "contains match failure with ignore case",
|
|
matcher: containsMatcherIgnoreCase,
|
|
input: "CON-TAINS-is-not-here",
|
|
},
|
|
}
|
|
|
|
for _, test := range tests {
|
|
t.Run(test.desc, func(t *testing.T) {
|
|
if gotMatch := test.matcher.Match(test.input); gotMatch != test.wantMatch {
|
|
t.Errorf("StringMatcher.Match(%s) returned %v, want %v", test.input, gotMatch, test.wantMatch)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func newStringP(s string) *string {
|
|
return &s
|
|
}
|