header_matching_test.py
Go to the documentation of this file.
1 # Copyright 2021 The gRPC Authors
2 #
3 # Licensed under the Apache License, Version 2.0 (the "License");
4 # you may not use this file except in compliance with the License.
5 # You may obtain a copy of the License at
6 #
7 # http://www.apache.org/licenses/LICENSE-2.0
8 #
9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 # See the License for the specific language governing permissions and
13 # limitations under the License.
14 import logging
15 from typing import Tuple
16 
17 from absl import flags
18 from absl.testing import absltest
19 
20 from framework import xds_url_map_testcase
21 from framework.helpers import skips
22 from framework.test_app import client_app
23 
24 # Type aliases
25 HostRule = xds_url_map_testcase.HostRule
26 PathMatcher = xds_url_map_testcase.PathMatcher
27 GcpResourceManager = xds_url_map_testcase.GcpResourceManager
28 DumpedXdsConfig = xds_url_map_testcase.DumpedXdsConfig
29 RpcTypeUnaryCall = xds_url_map_testcase.RpcTypeUnaryCall
30 RpcTypeEmptyCall = xds_url_map_testcase.RpcTypeEmptyCall
31 XdsTestClient = client_app.XdsTestClient
32 _Lang = skips.Lang
33 
34 logger = logging.getLogger(__name__)
35 flags.adopt_module_key_flags(xds_url_map_testcase)
36 
37 _NUM_RPCS = 150
38 _TEST_METADATA_KEY = 'xds_md'
39 _TEST_METADATA_VALUE_UNARY = 'unary_yranu'
40 _TEST_METADATA_VALUE_EMPTY = 'empty_ytpme'
41 _TEST_METADATA_NUMERIC_KEY = 'xds_md_numeric'
42 _TEST_METADATA_NUMERIC_VALUE = '159'
43 
44 _TEST_METADATA = (
45  (RpcTypeUnaryCall, _TEST_METADATA_KEY, _TEST_METADATA_VALUE_UNARY),
46  (RpcTypeEmptyCall, _TEST_METADATA_KEY, _TEST_METADATA_VALUE_EMPTY),
47  (RpcTypeUnaryCall, _TEST_METADATA_NUMERIC_KEY,
48  _TEST_METADATA_NUMERIC_VALUE),
49 )
50 
51 
52 def _is_supported(config: skips.TestConfig) -> bool:
53  if config.client_lang == _Lang.NODE:
54  return config.version_gte('v1.3.x')
55  return True
56 
57 
58 class TestExactMatch(xds_url_map_testcase.XdsUrlMapTestCase):
59 
60  @staticmethod
61  def is_supported(config: skips.TestConfig) -> bool:
62  return _is_supported(config)
63 
64  @staticmethod
66  host_rule: HostRule,
67  path_matcher: PathMatcher) -> Tuple[HostRule, PathMatcher]:
68  path_matcher["routeRules"] = [{
69  'priority': 0,
70  # Header ExactMatch -> alternate_backend_service.
71  # EmptyCall is sent with the metadata.
72  'matchRules': [{
73  'prefixMatch':
74  '/',
75  'headerMatches': [{
76  'headerName': _TEST_METADATA_KEY,
77  'exactMatch': _TEST_METADATA_VALUE_EMPTY
78  }]
79  }],
80  'service': GcpResourceManager().alternative_backend_service()
81  }]
82  return host_rule, path_matcher
83 
84  def xds_config_validate(self, xds_config: DumpedXdsConfig):
85  self.assertNumEndpoints(xds_config, 2)
86  self.assertEqual(
87  xds_config.rds['virtualHosts'][0]['routes'][0]['match']['headers']
88  [0]['name'], _TEST_METADATA_KEY)
89  self.assertEqual(
90  xds_config.rds['virtualHosts'][0]['routes'][0]['match']['headers']
91  [0]['exactMatch'], _TEST_METADATA_VALUE_EMPTY)
92 
93  def rpc_distribution_validate(self, test_client: XdsTestClient):
94  rpc_distribution = self.configure_and_send(test_client,
95  rpc_types=[RpcTypeEmptyCall],
96  metadata=_TEST_METADATA,
97  num_rpcs=_NUM_RPCS)
98  self.assertEqual(
99  _NUM_RPCS,
100  rpc_distribution.empty_call_alternative_service_rpc_count)
101 
102 
103 @absltest.skip('the xDS config is good, but distribution is wrong.')
104 class TestPrefixMatch(xds_url_map_testcase.XdsUrlMapTestCase):
105 
106  @staticmethod
107  def is_supported(config: skips.TestConfig) -> bool:
108  return _is_supported(config)
109 
110  @staticmethod
112  host_rule: HostRule,
113  path_matcher: PathMatcher) -> Tuple[HostRule, PathMatcher]:
114  path_matcher["routeRules"] = [{
115  'priority': 0,
116  # Header PrefixMatch -> alternate_backend_service.
117  # UnaryCall is sent with the metadata.
118  'matchRules': [{
119  'prefixMatch':
120  '/',
121  'headerMatches': [{
122  'headerName': _TEST_METADATA_KEY,
123  'prefixMatch': _TEST_METADATA_VALUE_UNARY[:2]
124  }]
125  }],
126  'service': GcpResourceManager().alternative_backend_service()
127  }]
128  return host_rule, path_matcher
129 
130  def xds_config_validate(self, xds_config: DumpedXdsConfig):
131  self.assertNumEndpoints(xds_config, 2)
132  self.assertEqual(
133  xds_config.rds['virtualHosts'][0]['routes'][0]['match']['headers']
134  [0]['name'], _TEST_METADATA_KEY)
135  self.assertEqual(
136  xds_config.rds['virtualHosts'][0]['routes'][0]['match']['headers']
137  [0]['prefixMatch'], _TEST_METADATA_VALUE_UNARY[:2])
138 
139  def rpc_distribution_validate(self, test_client: XdsTestClient):
140  rpc_distribution = self.configure_and_send(
141  test_client,
142  rpc_types=(RpcTypeUnaryCall,),
143  metadata=_TEST_METADATA,
144  num_rpcs=_NUM_RPCS)
145  self.assertEqual(
146  _NUM_RPCS,
147  rpc_distribution.unary_call_alternative_service_rpc_count)
148 
149 
150 class TestSuffixMatch(xds_url_map_testcase.XdsUrlMapTestCase):
151 
152  @staticmethod
153  def is_supported(config: skips.TestConfig) -> bool:
154  return _is_supported(config)
155 
156  @staticmethod
158  host_rule: HostRule,
159  path_matcher: PathMatcher) -> Tuple[HostRule, PathMatcher]:
160  path_matcher["routeRules"] = [{
161  'priority': 0,
162  # Header SuffixMatch -> alternate_backend_service.
163  # EmptyCall is sent with the metadata.
164  'matchRules': [{
165  'prefixMatch':
166  '/',
167  'headerMatches': [{
168  'headerName': _TEST_METADATA_KEY,
169  'suffixMatch': _TEST_METADATA_VALUE_EMPTY[-2:]
170  }]
171  }],
172  'service': GcpResourceManager().alternative_backend_service()
173  }]
174  return host_rule, path_matcher
175 
176  def xds_config_validate(self, xds_config: DumpedXdsConfig):
177  self.assertNumEndpoints(xds_config, 2)
178  self.assertEqual(
179  xds_config.rds['virtualHosts'][0]['routes'][0]['match']['headers']
180  [0]['name'], _TEST_METADATA_KEY)
181  self.assertEqual(
182  xds_config.rds['virtualHosts'][0]['routes'][0]['match']['headers']
183  [0]['suffixMatch'], _TEST_METADATA_VALUE_EMPTY[-2:])
184 
185  def rpc_distribution_validate(self, test_client: XdsTestClient):
186  rpc_distribution = self.configure_and_send(test_client,
187  rpc_types=[RpcTypeEmptyCall],
188  metadata=_TEST_METADATA,
189  num_rpcs=_NUM_RPCS)
190  self.assertEqual(
191  _NUM_RPCS,
192  rpc_distribution.empty_call_alternative_service_rpc_count)
193 
194 
195 class TestPresentMatch(xds_url_map_testcase.XdsUrlMapTestCase):
196 
197  @staticmethod
198  def is_supported(config: skips.TestConfig) -> bool:
199  return _is_supported(config)
200 
201  @staticmethod
203  host_rule: HostRule,
204  path_matcher: PathMatcher) -> Tuple[HostRule, PathMatcher]:
205  path_matcher["routeRules"] = [{
206  'priority': 0,
207  # Header 'xds_md_numeric' present -> alternate_backend_service.
208  # UnaryCall is sent with the metadata, so will be sent to alternative.
209  'matchRules': [{
210  'prefixMatch':
211  '/',
212  'headerMatches': [{
213  'headerName': _TEST_METADATA_NUMERIC_KEY,
214  'presentMatch': True
215  }]
216  }],
217  'service': GcpResourceManager().alternative_backend_service()
218  }]
219  return host_rule, path_matcher
220 
221  def xds_config_validate(self, xds_config: DumpedXdsConfig):
222  self.assertNumEndpoints(xds_config, 2)
223  self.assertEqual(
224  xds_config.rds['virtualHosts'][0]['routes'][0]['match']['headers']
225  [0]['name'], _TEST_METADATA_NUMERIC_KEY)
226  self.assertEqual(
227  xds_config.rds['virtualHosts'][0]['routes'][0]['match']['headers']
228  [0]['presentMatch'], True)
229 
230  def rpc_distribution_validate(self, test_client: XdsTestClient):
231  rpc_distribution = self.configure_and_send(
232  test_client,
233  rpc_types=(RpcTypeUnaryCall,),
234  metadata=_TEST_METADATA,
235  num_rpcs=_NUM_RPCS)
236  self.assertEqual(
237  _NUM_RPCS,
238  rpc_distribution.unary_call_alternative_service_rpc_count)
239 
240 
241 class TestInvertMatch(xds_url_map_testcase.XdsUrlMapTestCase):
242 
243  @staticmethod
244  def is_supported(config: skips.TestConfig) -> bool:
245  return _is_supported(config)
246 
247  @staticmethod
249  host_rule: HostRule,
250  path_matcher: PathMatcher) -> Tuple[HostRule, PathMatcher]:
251  path_matcher["routeRules"] = [{
252  'priority': 0,
253  # Header invert ExactMatch -> alternate_backend_service.
254  # UnaryCall is sent with the metadata, so will be sent to
255  # default. EmptyCall will be sent to alternative.
256  'matchRules': [{
257  'prefixMatch':
258  '/',
259  'headerMatches': [{
260  'headerName': _TEST_METADATA_KEY,
261  'exactMatch': _TEST_METADATA_VALUE_UNARY,
262  'invertMatch': True
263  }]
264  }],
265  'service': GcpResourceManager().alternative_backend_service()
266  }]
267  return host_rule, path_matcher
268 
269  def xds_config_validate(self, xds_config: DumpedXdsConfig):
270  self.assertNumEndpoints(xds_config, 2)
271  self.assertEqual(
272  xds_config.rds['virtualHosts'][0]['routes'][0]['match']['headers']
273  [0]['name'], _TEST_METADATA_KEY)
274  self.assertEqual(
275  xds_config.rds['virtualHosts'][0]['routes'][0]['match']['headers']
276  [0]['invertMatch'], True)
277 
278  def rpc_distribution_validate(self, test_client: XdsTestClient):
279  rpc_distribution = self.configure_and_send(
280  test_client,
281  rpc_types=[RpcTypeUnaryCall, RpcTypeEmptyCall],
282  metadata=_TEST_METADATA,
283  num_rpcs=_NUM_RPCS)
284  self.assertEqual(_NUM_RPCS, rpc_distribution.num_oks)
285  self.assertEqual(
286  0, rpc_distribution.unary_call_alternative_service_rpc_count)
287  self.assertEqual(0,
288  rpc_distribution.empty_call_default_service_rpc_count)
289 
290 
291 class TestRangeMatch(xds_url_map_testcase.XdsUrlMapTestCase):
292 
293  @staticmethod
294  def is_supported(config: skips.TestConfig) -> bool:
295  return _is_supported(config)
296 
297  @staticmethod
299  host_rule: HostRule,
300  path_matcher: PathMatcher) -> Tuple[HostRule, PathMatcher]:
301  path_matcher["routeRules"] = [{
302  'priority': 0,
303  # Header 'xds_md_numeric' range [100,200] -> alternate_backend_service.
304  # UnaryCall is sent with the metadata in range.
305  'matchRules': [{
306  'prefixMatch':
307  '/',
308  'headerMatches': [{
309  'headerName': _TEST_METADATA_NUMERIC_KEY,
310  'rangeMatch': {
311  'rangeStart': '100',
312  'rangeEnd': '200'
313  }
314  }]
315  }],
316  'service': GcpResourceManager().alternative_backend_service()
317  }]
318  return host_rule, path_matcher
319 
320  def xds_config_validate(self, xds_config: DumpedXdsConfig):
321  self.assertNumEndpoints(xds_config, 2)
322  self.assertEqual(
323  xds_config.rds['virtualHosts'][0]['routes'][0]['match']['headers']
324  [0]['name'], _TEST_METADATA_NUMERIC_KEY)
325  self.assertEqual(
326  xds_config.rds['virtualHosts'][0]['routes'][0]['match']['headers']
327  [0]['rangeMatch']['start'], '100')
328  self.assertEqual(
329  xds_config.rds['virtualHosts'][0]['routes'][0]['match']['headers']
330  [0]['rangeMatch']['end'], '200')
331 
332  def rpc_distribution_validate(self, test_client: XdsTestClient):
333  rpc_distribution = self.configure_and_send(
334  test_client,
335  rpc_types=[RpcTypeUnaryCall, RpcTypeEmptyCall],
336  metadata=_TEST_METADATA,
337  num_rpcs=_NUM_RPCS)
338  self.assertEqual(_NUM_RPCS, rpc_distribution.num_oks)
339  self.assertEqual(0,
340  rpc_distribution.unary_call_default_service_rpc_count)
341  self.assertEqual(
342  0, rpc_distribution.empty_call_alternative_service_rpc_count)
343 
344 
345 class TestRegexMatch(xds_url_map_testcase.XdsUrlMapTestCase):
346 
347  @staticmethod
348  def is_supported(config: skips.TestConfig) -> bool:
349  return _is_supported(config)
350 
351  @staticmethod
353  host_rule: HostRule,
354  path_matcher: PathMatcher) -> Tuple[HostRule, PathMatcher]:
355  path_matcher["routeRules"] = [{
356  'priority': 0,
357  # Header RegexMatch -> alternate_backend_service.
358  # EmptyCall is sent with the metadata.
359  'matchRules': [{
360  'prefixMatch':
361  '/',
362  'headerMatches': [{
363  'headerName':
364  _TEST_METADATA_KEY,
365  'regexMatch':
366  "^%s.*%s$" % (_TEST_METADATA_VALUE_EMPTY[:2],
367  _TEST_METADATA_VALUE_EMPTY[-2:])
368  }]
369  }],
370  'service': GcpResourceManager().alternative_backend_service()
371  }],
372  return host_rule, path_matcher
373 
374  def xds_config_validate(self, xds_config: DumpedXdsConfig):
375  self.assertNumEndpoints(xds_config, 2)
376  self.assertEqual(
377  xds_config.rds['virtualHosts'][0]['routes'][0]['match']['headers']
378  [0]['name'], _TEST_METADATA_KEY)
379  self.assertEqual(
380  xds_config.rds['virtualHosts'][0]['routes'][0]['match']['headers']
381  [0]['safeRegexMatch']['regex'], "^%s.*%s$" %
382  (_TEST_METADATA_VALUE_EMPTY[:2], _TEST_METADATA_VALUE_EMPTY[-2:]))
383 
384  def rpc_distribution_validate(self, test_client: XdsTestClient):
385  rpc_distribution = self.configure_and_send(test_client,
386  rpc_types=[RpcTypeEmptyCall],
387  metadata=_TEST_METADATA,
388  num_rpcs=_NUM_RPCS)
389  self.assertEqual(
390  _NUM_RPCS,
391  rpc_distribution.empty_call_alternative_service_rpc_count)
392 
393 
394 if __name__ == '__main__':
395  absltest.main()
tests.url_map.header_matching_test.TestInvertMatch.url_map_change
Tuple[HostRule, PathMatcher] url_map_change(HostRule host_rule, PathMatcher path_matcher)
Definition: header_matching_test.py:248
tests.url_map.header_matching_test.TestRangeMatch.xds_config_validate
def xds_config_validate(self, DumpedXdsConfig xds_config)
Definition: header_matching_test.py:320
tests.url_map.header_matching_test.TestPrefixMatch.rpc_distribution_validate
def rpc_distribution_validate(self, XdsTestClient test_client)
Definition: header_matching_test.py:139
tests.url_map.header_matching_test.TestPresentMatch.rpc_distribution_validate
def rpc_distribution_validate(self, XdsTestClient test_client)
Definition: header_matching_test.py:230
tests.url_map.header_matching_test.TestSuffixMatch
Definition: header_matching_test.py:150
tests.url_map.header_matching_test.TestPrefixMatch.is_supported
bool is_supported(skips.TestConfig config)
Definition: header_matching_test.py:107
tests.url_map.header_matching_test.TestSuffixMatch.rpc_distribution_validate
def rpc_distribution_validate(self, XdsTestClient test_client)
Definition: header_matching_test.py:185
tests.url_map.header_matching_test.TestExactMatch.url_map_change
Tuple[HostRule, PathMatcher] url_map_change(HostRule host_rule, PathMatcher path_matcher)
Definition: header_matching_test.py:65
tests.url_map.header_matching_test.TestExactMatch
Definition: header_matching_test.py:58
tests.url_map.header_matching_test.GcpResourceManager
GcpResourceManager
Definition: header_matching_test.py:27
tests.url_map.header_matching_test.TestInvertMatch.is_supported
bool is_supported(skips.TestConfig config)
Definition: header_matching_test.py:244
tests.url_map.header_matching_test.TestRegexMatch
Definition: header_matching_test.py:345
tests.url_map.header_matching_test.TestRegexMatch.rpc_distribution_validate
def rpc_distribution_validate(self, XdsTestClient test_client)
Definition: header_matching_test.py:384
tests.url_map.header_matching_test.TestPresentMatch.url_map_change
Tuple[HostRule, PathMatcher] url_map_change(HostRule host_rule, PathMatcher path_matcher)
Definition: header_matching_test.py:202
tests.url_map.header_matching_test.TestExactMatch.xds_config_validate
def xds_config_validate(self, DumpedXdsConfig xds_config)
Definition: header_matching_test.py:84
tests.url_map.header_matching_test.TestRegexMatch.url_map_change
Tuple[HostRule, PathMatcher] url_map_change(HostRule host_rule, PathMatcher path_matcher)
Definition: header_matching_test.py:352
framework.helpers
Definition: tools/run_tests/xds_k8s_test_driver/framework/helpers/__init__.py:1
tests.url_map.header_matching_test.TestRegexMatch.is_supported
bool is_supported(skips.TestConfig config)
Definition: header_matching_test.py:348
tests.url_map.header_matching_test.TestInvertMatch.rpc_distribution_validate
def rpc_distribution_validate(self, XdsTestClient test_client)
Definition: header_matching_test.py:278
tests.url_map.header_matching_test.TestSuffixMatch.xds_config_validate
def xds_config_validate(self, DumpedXdsConfig xds_config)
Definition: header_matching_test.py:176
framework.test_app
Definition: tools/run_tests/xds_k8s_test_driver/framework/test_app/__init__.py:1
tests.url_map.header_matching_test.TestExactMatch.is_supported
bool is_supported(skips.TestConfig config)
Definition: header_matching_test.py:61
tests.url_map.header_matching_test.TestPrefixMatch
Definition: header_matching_test.py:104
tests.url_map.header_matching_test.TestPresentMatch.is_supported
bool is_supported(skips.TestConfig config)
Definition: header_matching_test.py:198
tests.url_map.header_matching_test.TestPresentMatch.xds_config_validate
def xds_config_validate(self, DumpedXdsConfig xds_config)
Definition: header_matching_test.py:221
tests.url_map.header_matching_test.TestInvertMatch
Definition: header_matching_test.py:241
tests.url_map.header_matching_test.TestPrefixMatch.url_map_change
Tuple[HostRule, PathMatcher] url_map_change(HostRule host_rule, PathMatcher path_matcher)
Definition: header_matching_test.py:111
tests.url_map.header_matching_test.TestSuffixMatch.url_map_change
Tuple[HostRule, PathMatcher] url_map_change(HostRule host_rule, PathMatcher path_matcher)
Definition: header_matching_test.py:157
tests.url_map.header_matching_test.TestInvertMatch.xds_config_validate
def xds_config_validate(self, DumpedXdsConfig xds_config)
Definition: header_matching_test.py:269
tests.url_map.header_matching_test.TestSuffixMatch.is_supported
bool is_supported(skips.TestConfig config)
Definition: header_matching_test.py:153
tests.url_map.header_matching_test.TestRegexMatch.xds_config_validate
def xds_config_validate(self, DumpedXdsConfig xds_config)
Definition: header_matching_test.py:374
tests.url_map.header_matching_test.TestRangeMatch.rpc_distribution_validate
def rpc_distribution_validate(self, XdsTestClient test_client)
Definition: header_matching_test.py:332
tests.url_map.header_matching_test.TestExactMatch.rpc_distribution_validate
def rpc_distribution_validate(self, XdsTestClient test_client)
Definition: header_matching_test.py:93
tests.url_map.header_matching_test.TestPresentMatch
Definition: header_matching_test.py:195
tests.url_map.header_matching_test.TestRangeMatch.is_supported
bool is_supported(skips.TestConfig config)
Definition: header_matching_test.py:294
tests.url_map.header_matching_test.TestRangeMatch.url_map_change
Tuple[HostRule, PathMatcher] url_map_change(HostRule host_rule, PathMatcher path_matcher)
Definition: header_matching_test.py:298
tests.url_map.header_matching_test.TestPrefixMatch.xds_config_validate
def xds_config_validate(self, DumpedXdsConfig xds_config)
Definition: header_matching_test.py:130
tests.url_map.header_matching_test._is_supported
bool _is_supported(skips.TestConfig config)
Definition: header_matching_test.py:52
tests.url_map.header_matching_test.TestRangeMatch
Definition: header_matching_test.py:291


grpc
Author(s):
autogenerated on Thu Mar 13 2025 03:00:12