blob: f567f31982428256e0d9831f8259466c4968cc2e [file] [log] [blame]
/*
*
* Copyright 2020 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"
"google.golang.org/grpc/metadata"
)
func TestHeaderExactMatcherMatch(t *testing.T) {
tests := []struct {
name string
key, exact string
md metadata.MD
want bool
invert bool
}{
{
name: "one value one match",
key: "th",
exact: "tv",
md: metadata.Pairs("th", "tv"),
want: true,
},
{
name: "two value one match",
key: "th",
exact: "tv",
md: metadata.Pairs("th", "abc", "th", "tv"),
// Doesn't match comma-concatenated string.
want: false,
},
{
name: "two value match concatenated",
key: "th",
exact: "abc,tv",
md: metadata.Pairs("th", "abc", "th", "tv"),
want: true,
},
{
name: "not match",
key: "th",
exact: "tv",
md: metadata.Pairs("th", "abc"),
want: false,
},
{
name: "invert header not present",
key: "th",
exact: "tv",
md: metadata.Pairs(":method", "GET"),
want: false,
invert: true,
},
{
name: "invert header match",
key: "th",
exact: "tv",
md: metadata.Pairs("th", "tv"),
want: false,
invert: true,
},
{
name: "invert header not match",
key: "th",
exact: "tv",
md: metadata.Pairs("th", "tvv"),
want: true,
invert: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
hem := NewHeaderExactMatcher(tt.key, tt.exact, tt.invert)
if got := hem.Match(tt.md); got != tt.want {
t.Errorf("match() = %v, want %v", got, tt.want)
}
})
}
}
func TestHeaderRegexMatcherMatch(t *testing.T) {
tests := []struct {
name string
key, regexStr string
md metadata.MD
want bool
invert bool
}{
{
name: "one value one match",
key: "th",
regexStr: "^t+v*$",
md: metadata.Pairs("th", "tttvv"),
want: true,
},
{
name: "two value one match",
key: "th",
regexStr: "^t+v*$",
md: metadata.Pairs("th", "abc", "th", "tttvv"),
want: false,
},
{
name: "two value match concatenated",
key: "th",
regexStr: "^[abc]*,t+v*$",
md: metadata.Pairs("th", "abc", "th", "tttvv"),
want: true,
},
{
name: "no match",
key: "th",
regexStr: "^t+v*$",
md: metadata.Pairs("th", "abc"),
want: false,
},
{
name: "no match because only part of value matches with regex",
key: "header",
regexStr: "^a+$",
md: metadata.Pairs("header", "ab"),
want: false,
},
{
name: "match because full value matches with regex",
key: "header",
regexStr: "^a+$",
md: metadata.Pairs("header", "aa"),
want: true,
},
{
name: "invert header not present",
key: "th",
regexStr: "^t+v*$",
md: metadata.Pairs(":method", "GET"),
want: false,
invert: true,
},
{
name: "invert header match",
key: "th",
regexStr: "^t+v*$",
md: metadata.Pairs("th", "tttvv"),
want: false,
invert: true,
},
{
name: "invert header not match",
key: "th",
regexStr: "^t+v*$",
md: metadata.Pairs("th", "abc"),
want: true,
invert: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
hrm := NewHeaderRegexMatcher(tt.key, regexp.MustCompile(tt.regexStr), tt.invert)
if got := hrm.Match(tt.md); got != tt.want {
t.Errorf("match() = %v, want %v", got, tt.want)
}
})
}
}
func TestHeaderRangeMatcherMatch(t *testing.T) {
tests := []struct {
name string
key string
start, end int64
md metadata.MD
want bool
invert bool
}{
{
name: "match",
key: "th",
start: 1, end: 10,
md: metadata.Pairs("th", "5"),
want: true,
},
{
name: "equal to start",
key: "th",
start: 1, end: 10,
md: metadata.Pairs("th", "1"),
want: true,
},
{
name: "equal to end",
key: "th",
start: 1, end: 10,
md: metadata.Pairs("th", "10"),
want: false,
},
{
name: "negative",
key: "th",
start: -10, end: 10,
md: metadata.Pairs("th", "-5"),
want: true,
},
{
name: "invert header not present",
key: "th",
start: 1, end: 10,
md: metadata.Pairs(":method", "GET"),
want: false,
invert: true,
},
{
name: "invert header match",
key: "th",
start: 1, end: 10,
md: metadata.Pairs("th", "5"),
want: false,
invert: true,
},
{
name: "invert header not match",
key: "th",
start: 1, end: 9,
md: metadata.Pairs("th", "10"),
want: true,
invert: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
hrm := NewHeaderRangeMatcher(tt.key, tt.start, tt.end, tt.invert)
if got := hrm.Match(tt.md); got != tt.want {
t.Errorf("match() = %v, want %v", got, tt.want)
}
})
}
}
func TestHeaderPresentMatcherMatch(t *testing.T) {
tests := []struct {
name string
key string
present bool
md metadata.MD
want bool
invert bool
}{
{
name: "want present is present",
key: "th",
present: true,
md: metadata.Pairs("th", "tv"),
want: true,
},
{
name: "want present not present",
key: "th",
present: true,
md: metadata.Pairs("abc", "tv"),
want: false,
},
{
name: "want not present is present",
key: "th",
present: false,
md: metadata.Pairs("th", "tv"),
want: false,
},
{
name: "want not present is not present",
key: "th",
present: false,
md: metadata.Pairs("abc", "tv"),
want: true,
},
{
name: "invert header not present",
key: "th",
present: true,
md: metadata.Pairs(":method", "GET"),
want: true,
invert: true,
},
{
name: "invert header match",
key: "th",
present: true,
md: metadata.Pairs("th", "tv"),
want: false,
invert: true,
},
{
name: "invert header not match",
key: "th",
present: true,
md: metadata.Pairs(":method", "GET"),
want: true,
invert: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
hpm := NewHeaderPresentMatcher(tt.key, tt.present, tt.invert)
if got := hpm.Match(tt.md); got != tt.want {
t.Errorf("match() = %v, want %v", got, tt.want)
}
})
}
}
func TestHeaderPrefixMatcherMatch(t *testing.T) {
tests := []struct {
name string
key, prefix string
md metadata.MD
want bool
invert bool
}{
{
name: "one value one match",
key: "th",
prefix: "tv",
md: metadata.Pairs("th", "tv123"),
want: true,
},
{
name: "two value one match",
key: "th",
prefix: "tv",
md: metadata.Pairs("th", "abc", "th", "tv123"),
want: false,
},
{
name: "two value match concatenated",
key: "th",
prefix: "tv",
md: metadata.Pairs("th", "tv123", "th", "abc"),
want: true,
},
{
name: "not match",
key: "th",
prefix: "tv",
md: metadata.Pairs("th", "abc"),
want: false,
},
{
name: "invert header not present",
key: "th",
prefix: "tv",
md: metadata.Pairs(":method", "GET"),
want: false,
invert: true,
},
{
name: "invert header match",
key: "th",
prefix: "tv",
md: metadata.Pairs("th", "tv123"),
want: false,
invert: true,
},
{
name: "invert header not match",
key: "th",
prefix: "tv",
md: metadata.Pairs("th", "abc"),
want: true,
invert: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
hpm := NewHeaderPrefixMatcher(tt.key, tt.prefix, tt.invert)
if got := hpm.Match(tt.md); got != tt.want {
t.Errorf("match() = %v, want %v", got, tt.want)
}
})
}
}
func TestHeaderSuffixMatcherMatch(t *testing.T) {
tests := []struct {
name string
key, suffix string
md metadata.MD
want bool
invert bool
}{
{
name: "one value one match",
key: "th",
suffix: "tv",
md: metadata.Pairs("th", "123tv"),
want: true,
},
{
name: "two value one match",
key: "th",
suffix: "tv",
md: metadata.Pairs("th", "123tv", "th", "abc"),
want: false,
},
{
name: "two value match concatenated",
key: "th",
suffix: "tv",
md: metadata.Pairs("th", "abc", "th", "123tv"),
want: true,
},
{
name: "not match",
key: "th",
suffix: "tv",
md: metadata.Pairs("th", "abc"),
want: false,
},
{
name: "invert header not present",
key: "th",
suffix: "tv",
md: metadata.Pairs(":method", "GET"),
want: false,
invert: true,
},
{
name: "invert header match",
key: "th",
suffix: "tv",
md: metadata.Pairs("th", "123tv"),
want: false,
invert: true,
},
{
name: "invert header not match",
key: "th",
suffix: "tv",
md: metadata.Pairs("th", "abc"),
want: true,
invert: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
hsm := NewHeaderSuffixMatcher(tt.key, tt.suffix, tt.invert)
if got := hsm.Match(tt.md); got != tt.want {
t.Errorf("match() = %v, want %v", got, tt.want)
}
})
}
}