sigs.k8s.io/gateway-api@v1.0.0/conformance/tests/httproute-query-param-matching.go (about) 1 /* 2 Copyright 2022 The Kubernetes Authors. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package tests 18 19 import ( 20 "testing" 21 22 "k8s.io/apimachinery/pkg/types" 23 24 "sigs.k8s.io/gateway-api/conformance/utils/http" 25 "sigs.k8s.io/gateway-api/conformance/utils/kubernetes" 26 "sigs.k8s.io/gateway-api/conformance/utils/suite" 27 ) 28 29 func init() { 30 ConformanceTests = append(ConformanceTests, HTTPRouteQueryParamMatching) 31 } 32 33 var HTTPRouteQueryParamMatching = suite.ConformanceTest{ 34 ShortName: "HTTPRouteQueryParamMatching", 35 Description: "A single HTTPRoute with query param matching for different backends", 36 Manifests: []string{"tests/httproute-query-param-matching.yaml"}, 37 Features: []suite.SupportedFeature{ 38 suite.SupportGateway, 39 suite.SupportHTTPRoute, 40 suite.SupportHTTPRouteQueryParamMatching, 41 }, 42 Test: func(t *testing.T, suite *suite.ConformanceTestSuite) { 43 ns := "gateway-conformance-infra" 44 routeNN := types.NamespacedName{Namespace: ns, Name: "query-param-matching"} 45 gwNN := types.NamespacedName{Namespace: ns, Name: "same-namespace"} 46 gwAddr := kubernetes.GatewayAndHTTPRoutesMustBeAccepted(t, suite.Client, suite.TimeoutConfig, suite.ControllerName, kubernetes.NewGatewayRef(gwNN), routeNN) 47 kubernetes.HTTPRouteMustHaveResolvedRefsConditionsTrue(t, suite.Client, suite.TimeoutConfig, routeNN, gwNN) 48 49 testCases := []http.ExpectedResponse{{ 50 Request: http.Request{Path: "/?animal=whale"}, 51 Backend: "infra-backend-v1", 52 Namespace: ns, 53 }, { 54 Request: http.Request{Path: "/?animal=dolphin"}, 55 Backend: "infra-backend-v2", 56 Namespace: ns, 57 }, { 58 Request: http.Request{Path: "/?animal=dolphin&color=blue"}, 59 Backend: "infra-backend-v3", 60 Namespace: ns, 61 }, { 62 Request: http.Request{Path: "/?ANIMAL=Whale"}, 63 Backend: "infra-backend-v3", 64 Namespace: ns, 65 }, { 66 Request: http.Request{Path: "/?animal=whale&otherparam=irrelevant"}, 67 Backend: "infra-backend-v1", 68 Namespace: ns, 69 }, { 70 Request: http.Request{Path: "/?animal=dolphin&color=yellow"}, 71 Backend: "infra-backend-v2", 72 Namespace: ns, 73 }, { 74 Request: http.Request{Path: "/?color=blue"}, 75 Response: http.Response{StatusCode: 404}, 76 }, { 77 Request: http.Request{Path: "/?animal=dog"}, 78 Response: http.Response{StatusCode: 404}, 79 }, { 80 Request: http.Request{Path: "/?animal=whaledolphin"}, 81 Response: http.Response{StatusCode: 404}, 82 }, { 83 Request: http.Request{Path: "/"}, 84 Response: http.Response{StatusCode: 404}, 85 }} 86 87 // Combinations of query param matching with other core matches. 88 testCases = append(testCases, []http.ExpectedResponse{ 89 { 90 Request: http.Request{Path: "/path1?animal=whale"}, 91 Backend: "infra-backend-v1", 92 Namespace: ns, 93 }, 94 { 95 Request: http.Request{Headers: map[string]string{"version": "one"}, Path: "/?animal=whale"}, 96 Backend: "infra-backend-v2", 97 Namespace: ns, 98 }, 99 { 100 Request: http.Request{Headers: map[string]string{"version": "two"}, Path: "/path2?animal=whale"}, 101 Backend: "infra-backend-v3", 102 Namespace: ns, 103 }, 104 }...) 105 106 // Ensure that combinations of matches which are OR'd together match 107 // even if only one of them is used in the request. 108 testCases = append(testCases, []http.ExpectedResponse{ 109 { 110 Request: http.Request{Path: "/path3?animal=shark"}, 111 Backend: "infra-backend-v1", 112 Namespace: ns, 113 }, 114 { 115 Request: http.Request{Headers: map[string]string{"version": "three"}, Path: "/path4?animal=kraken"}, 116 Backend: "infra-backend-v1", 117 Namespace: ns, 118 }, 119 }...) 120 121 // Ensure that combinations of match types which are ANDed together do not match 122 // when only a subset of match types is used in the request. 123 testCases = append(testCases, []http.ExpectedResponse{ 124 { 125 Request: http.Request{Path: "/?animal=shark"}, 126 Response: http.Response{StatusCode: 404}, 127 }, 128 { 129 Request: http.Request{Path: "/path4?animal=kraken"}, 130 Response: http.Response{StatusCode: 404}, 131 }, 132 }...) 133 134 // For requests that satisfy multiple matches, ensure precedence order 135 // defined by the Gateway API spec is maintained. 136 testCases = append(testCases, []http.ExpectedResponse{ 137 { 138 Request: http.Request{Path: "/path5?animal=hydra"}, 139 Backend: "infra-backend-v1", 140 Namespace: ns, 141 }, 142 { 143 Request: http.Request{Headers: map[string]string{"version": "four"}, Path: "/?animal=hydra"}, 144 Backend: "infra-backend-v3", 145 Namespace: ns, 146 }, 147 }...) 148 149 for i := range testCases { 150 tc := testCases[i] 151 t.Run(tc.GetTestCaseName(i), func(t *testing.T) { 152 t.Parallel() 153 http.MakeRequestAndExpectEventuallyConsistentResponse(t, suite.RoundTripper, suite.TimeoutConfig, gwAddr, tc) 154 }) 155 } 156 }, 157 }