snapshot of https://github.com/grpc/grpc-go.git (master, 2026-09-15; blobs > 131072B omitted)
Some checks failed
codecov / upload (push) Failing after 13m59s
CodeQL / Analyze (push) Failing after 1s
Testing / vet-proto (push) Failing after 1s
Testing / tests (arm, latest) (push) Waiting to run
Testing / extras (latest) (push) Failing after 1s
Testing / static checks (latest-1) (push) Failing after 1s
Testing / tests (-race, latest) (push) Failing after 1s
Testing / tests (i386, latest) (push) Failing after 1s
Testing / tests (latest) (push) Failing after 1s
Testing / tests (latest-1) (push) Failing after 1s
Lock Threads / lock (push) Failing after 1s
govulncheck / govulncheck (.) (push) Failing after 1s
govulncheck / govulncheck (./cmd/protoc-gen-go-grpc) (push) Failing after 1s
govulncheck / govulncheck (./gcp/observability) (push) Failing after 1s
govulncheck / govulncheck (./security/advancedtls) (push) Failing after 1s
govulncheck / govulncheck (./stats/opencensus) (push) Failing after 1s
Stale bot / stale (push) Failing after 1s

This commit is contained in:
upstream-mirror
2026-09-15 20:40:15 +05:00
commit e241b33f26
1365 changed files with 339570 additions and 0 deletions

View File

@@ -0,0 +1,349 @@
/*
*
* 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: "regex with ignore case",
inputProto: &v3matcherpb.StringMatcher{
MatchPattern: &v3matcherpb.StringMatcher_SafeRegex{
SafeRegex: &v3matcherpb.RegexMatcher{Regex: "good?regex?"},
},
IgnoreCase: true,
},
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 = NewExactStringMatcher("exact", false)
exactMatcherIgnoreCase = NewExactStringMatcher("exact", true)
prefixMatcher = NewPrefixStringMatcher("prefix", false)
prefixMatcherIgnoreCase = NewPrefixStringMatcher("prefix", true)
suffixMatcher = NewSuffixStringMatcher("suffix", false)
suffixMatcherIgnoreCase = NewSuffixStringMatcher("suffix", true)
containsMatcher = NewContainsStringMatcher("contains", false)
containsMatcherIgnoreCase = NewContainsStringMatcher("contains", true)
regexMatcher = NewRegexStringMatcher(regexp.MustCompile("^(?:good?regex?)$"))
)
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
}
func TestCompileSafeRegex(t *testing.T) {
tests := []struct {
desc string
pattern string
wantRegex string
wantErr bool
}{
{
desc: "ValidPattern",
pattern: "abc",
wantRegex: "^(?:abc)$",
},
{
desc: "UnmatchedParenthesis",
pattern: "abc(",
wantErr: true,
},
}
for _, test := range tests {
t.Run(test.desc, func(t *testing.T) {
re, err := CompileSafeRegex(test.pattern)
if (err != nil) != test.wantErr {
t.Fatalf("CompileSafeRegex(%q) returned error %q, wantErr=%v", test.pattern, err, test.wantErr)
}
if err == nil {
if re.String() != test.wantRegex {
t.Fatalf("CompileSafeRegex(%q) = %q, want %q", test.pattern, re.String(), test.wantRegex)
}
}
})
}
}