traefik/pkg/provider/kubernetes/gateway/grpcroute_test.go
Kevin Pollet 5ed972ccd8
Support GRPC routes
Co-authored-by: Romain <rtribotte@users.noreply.github.com>
2024-08-30 10:36:06 +02:00

227 lines
5.3 KiB
Go

package gateway
import (
"testing"
"github.com/stretchr/testify/assert"
"k8s.io/utils/ptr"
gatev1 "sigs.k8s.io/gateway-api/apis/v1"
)
func Test_buildGRPCMatchRule(t *testing.T) {
testCases := []struct {
desc string
match gatev1.GRPCRouteMatch
hostnames []gatev1.Hostname
expectedRule string
expectedPriority int
expectedError bool
}{
{
desc: "Empty rule and matches",
expectedRule: "PathPrefix(`/`)",
expectedPriority: 15,
},
{
desc: "One Host rule without match",
hostnames: []gatev1.Hostname{"foo.com"},
expectedRule: "Host(`foo.com`) && PathPrefix(`/`)",
expectedPriority: 22,
},
{
desc: "One GRPCRouteMatch with no GRPCHeaderMatch",
match: gatev1.GRPCRouteMatch{
Method: &gatev1.GRPCMethodMatch{
Type: ptr.To(gatev1.GRPCMethodMatchExact),
Service: ptr.To("foo"),
Method: ptr.To("bar"),
},
},
expectedRule: "PathRegexp(`/foo/bar`)",
expectedPriority: 22,
},
{
desc: "One GRPCRouteMatch with one GRPCHeaderMatch",
match: gatev1.GRPCRouteMatch{
Method: &gatev1.GRPCMethodMatch{
Type: ptr.To(gatev1.GRPCMethodMatchExact),
Service: ptr.To("foo"),
Method: ptr.To("bar"),
},
Headers: []gatev1.GRPCHeaderMatch{
{
Type: ptr.To(gatev1.HeaderMatchExact),
Name: "foo",
Value: "bar",
},
},
},
expectedRule: "PathRegexp(`/foo/bar`) && Header(`foo`,`bar`)",
expectedPriority: 45,
},
{
desc: "One GRPCRouteMatch with one GRPCHeaderMatch and one Host",
hostnames: []gatev1.Hostname{"foo.com"},
match: gatev1.GRPCRouteMatch{
Method: &gatev1.GRPCMethodMatch{
Type: ptr.To(gatev1.GRPCMethodMatchExact),
Service: ptr.To("foo"),
Method: ptr.To("bar"),
},
Headers: []gatev1.GRPCHeaderMatch{
{
Type: ptr.To(gatev1.HeaderMatchExact),
Name: "foo",
Value: "bar",
},
},
},
expectedRule: "Host(`foo.com`) && PathRegexp(`/foo/bar`) && Header(`foo`,`bar`)",
expectedPriority: 52,
},
}
for _, test := range testCases {
t.Run(test.desc, func(t *testing.T) {
t.Parallel()
rule, priority := buildGRPCMatchRule(test.hostnames, test.match)
assert.Equal(t, test.expectedRule, rule)
assert.Equal(t, test.expectedPriority, priority)
})
}
}
func Test_buildGRPCMethodRule(t *testing.T) {
testCases := []struct {
desc string
method *gatev1.GRPCMethodMatch
expectedRule string
}{
{
desc: "Empty",
expectedRule: "PathPrefix(`/`)",
},
{
desc: "Exact service matching",
method: &gatev1.GRPCMethodMatch{
Type: ptr.To(gatev1.GRPCMethodMatchExact),
Service: ptr.To("foo"),
},
expectedRule: "PathRegexp(`/foo/[^/]+`)",
},
{
desc: "Exact method matching",
method: &gatev1.GRPCMethodMatch{
Type: ptr.To(gatev1.GRPCMethodMatchExact),
Method: ptr.To("bar"),
},
expectedRule: "PathRegexp(`/[^/]+/bar`)",
},
{
desc: "Exact service and method matching",
method: &gatev1.GRPCMethodMatch{
Type: ptr.To(gatev1.GRPCMethodMatchExact),
Service: ptr.To("foo"),
Method: ptr.To("bar"),
},
expectedRule: "PathRegexp(`/foo/bar`)",
},
{
desc: "Regexp service matching",
method: &gatev1.GRPCMethodMatch{
Type: ptr.To(gatev1.GRPCMethodMatchRegularExpression),
Service: ptr.To("[^1-9/]"),
},
expectedRule: "PathRegexp(`/[^1-9/]/[^/]+`)",
},
{
desc: "Regexp method matching",
method: &gatev1.GRPCMethodMatch{
Type: ptr.To(gatev1.GRPCMethodMatchRegularExpression),
Method: ptr.To("[^1-9/]"),
},
expectedRule: "PathRegexp(`/[^/]+/[^1-9/]`)",
},
{
desc: "Regexp service and method matching",
method: &gatev1.GRPCMethodMatch{
Type: ptr.To(gatev1.GRPCMethodMatchRegularExpression),
Service: ptr.To("[^1-9/]"),
Method: ptr.To("[^1-9/]"),
},
expectedRule: "PathRegexp(`/[^1-9/]/[^1-9/]`)",
},
}
for _, test := range testCases {
t.Run(test.desc, func(t *testing.T) {
t.Parallel()
rule := buildGRPCMethodRule(test.method)
assert.Equal(t, test.expectedRule, rule)
})
}
}
func Test_buildGRPCHeaderRules(t *testing.T) {
testCases := []struct {
desc string
headers []gatev1.GRPCHeaderMatch
expectedRules []string
}{
{
desc: "Empty",
},
{
desc: "One exact match type",
headers: []gatev1.GRPCHeaderMatch{
{
Type: ptr.To(gatev1.HeaderMatchExact),
Name: "foo",
Value: "bar",
},
},
expectedRules: []string{"Header(`foo`,`bar`)"},
},
{
desc: "One regexp match type",
headers: []gatev1.GRPCHeaderMatch{
{
Type: ptr.To(gatev1.HeaderMatchRegularExpression),
Name: "foo",
Value: ".*",
},
},
expectedRules: []string{"HeaderRegexp(`foo`,`.*`)"},
},
{
desc: "One exact and regexp match type",
headers: []gatev1.GRPCHeaderMatch{
{
Type: ptr.To(gatev1.HeaderMatchExact),
Name: "foo",
Value: "bar",
},
{
Type: ptr.To(gatev1.HeaderMatchRegularExpression),
Name: "foo",
Value: ".*",
},
},
expectedRules: []string{
"Header(`foo`,`bar`)",
"HeaderRegexp(`foo`,`.*`)",
},
},
}
for _, test := range testCases {
t.Run(test.desc, func(t *testing.T) {
t.Parallel()
rule := buildGRPCHeaderRules(test.headers)
assert.Equal(t, test.expectedRules, rule)
})
}
}