xds_url_map_testcase.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 """A test framework built for urlMap related xDS test cases."""
15 
16 import abc
17 from dataclasses import dataclass
18 import datetime
19 import json
20 import os
21 import re
22 import sys
23 import time
24 from typing import Any, Iterable, Mapping, Optional, Tuple
25 import unittest
26 
27 from absl import flags
28 from absl import logging
29 from absl.testing import absltest
30 from google.protobuf import json_format
31 import grpc
32 
33 from framework import xds_k8s_testcase
34 from framework import xds_url_map_test_resources
35 from framework.helpers import retryers
36 from framework.helpers import skips
37 from framework.test_app import client_app
38 
39 # Load existing flags
40 flags.adopt_module_key_flags(xds_k8s_testcase)
41 flags.adopt_module_key_flags(xds_url_map_test_resources)
42 
43 # Define urlMap specific flags
44 QPS = flags.DEFINE_integer('qps', default=25, help='The QPS client is sending')
45 
46 # Test configs
47 _URL_MAP_PROPAGATE_TIMEOUT_SEC = 600
48 # With the per-run IAM change, the first xDS response has a several minutes
49 # delay. We want to increase the interval, reduce the log spam.
50 _URL_MAP_PROPAGATE_CHECK_INTERVAL_SEC = 15
51 URL_MAP_TESTCASE_FILE_SUFFIX = '_test.py'
52 _CLIENT_CONFIGURE_WAIT_SEC = 2
53 
54 # Type aliases
55 XdsTestClient = client_app.XdsTestClient
57 HostRule = xds_url_map_test_resources.HostRule
58 PathMatcher = xds_url_map_test_resources.PathMatcher
59 JsonType = Any
60 
61 # ProtoBuf translatable RpcType enums
62 RpcTypeUnaryCall = 'UNARY_CALL'
63 RpcTypeEmptyCall = 'EMPTY_CALL'
64 
65 
66 def _split_camel(s: str, delimiter: str = '-') -> str:
67  """Turn camel case name to snake-case-like name."""
68  return ''.join(delimiter + c.lower() if c.isupper() else c
69  for c in s).lstrip(delimiter)
70 
71 
72 class DumpedXdsConfig(dict):
73  """A convenience class to check xDS config.
74 
75  Feel free to add more pre-compute fields.
76  """
77 
78  def __init__(self, xds_json: JsonType): # pylint: disable=too-many-branches
79  super().__init__(xds_json)
80  self.json_config = xds_json
81  self.lds = None
82  self.rds = None
83  self.rds_version = None
84  self.cds = []
85  self.eds = []
86  self.endpoints = []
87  for xds_config in self.get('xdsConfig', []):
88  try:
89  if 'listenerConfig' in xds_config:
90  self.lds = xds_config['listenerConfig']['dynamicListeners'][
91  0]['activeState']['listener']
92  elif 'routeConfig' in xds_config:
93  self.rds = xds_config['routeConfig']['dynamicRouteConfigs'][
94  0]['routeConfig']
95  self.rds_version = xds_config['routeConfig'][
96  'dynamicRouteConfigs'][0]['versionInfo']
97  elif 'clusterConfig' in xds_config:
98  for cluster in xds_config['clusterConfig'][
99  'dynamicActiveClusters']:
100  self.cds.append(cluster['cluster'])
101  elif 'endpointConfig' in xds_config:
102  for endpoint in xds_config['endpointConfig'][
103  'dynamicEndpointConfigs']:
104  self.eds.append(endpoint['endpointConfig'])
105  # TODO(lidiz) reduce the catch to LookupError
106  except Exception as e: # pylint: disable=broad-except
107  logging.debug('Parsing dumped xDS config failed with %s: %s',
108  type(e), e)
109  for generic_xds_config in self.get('genericXdsConfigs', []):
110  try:
111  if re.search(r'\.Listener$', generic_xds_config['typeUrl']):
112  self.lds = generic_xds_config["xdsConfig"]
113  elif re.search(r'\.RouteConfiguration$',
114  generic_xds_config['typeUrl']):
115  self.rds = generic_xds_config["xdsConfig"]
116  self.rds_version = generic_xds_config["versionInfo"]
117  elif re.search(r'\.Cluster$', generic_xds_config['typeUrl']):
118  self.cds.append(generic_xds_config["xdsConfig"])
119  elif re.search(r'\.ClusterLoadAssignment$',
120  generic_xds_config['typeUrl']):
121  self.eds.append(generic_xds_config["xdsConfig"])
122  # TODO(lidiz) reduce the catch to LookupError
123  except Exception as e: # pylint: disable=broad-except
124  logging.debug('Parsing dumped xDS config failed with %s: %s',
125  type(e), e)
126  for endpoint_config in self.eds:
127  for endpoint in endpoint_config.get('endpoints', {}):
128  for lb_endpoint in endpoint.get('lbEndpoints', {}):
129  try:
130  if lb_endpoint['healthStatus'] == 'HEALTHY':
131  self.endpoints.append(
132  '%s:%s' % (lb_endpoint['endpoint']['address']
133  ['socketAddress']['address'],
134  lb_endpoint['endpoint']['address']
135  ['socketAddress']['portValue']))
136  # TODO(lidiz) reduce the catch to LookupError
137  except Exception as e: # pylint: disable=broad-except
138  logging.debug('Parse endpoint failed with %s: %s',
139  type(e), e)
140 
141  def __str__(self) -> str:
142  return json.dumps(self, indent=2)
143 
144 
146  """A convenience class to check RPC distribution.
147 
148  Feel free to add more pre-compute fields.
149  """
150  num_failures: int
151  num_oks: int
152  default_service_rpc_count: int
153  alternative_service_rpc_count: int
154  unary_call_default_service_rpc_count: int
155  empty_call_default_service_rpc_count: int
156  unary_call_alternative_service_rpc_count: int
157  empty_call_alternative_service_rpc_count: int
158 
159  def __init__(self, json_lb_stats: JsonType):
160  self.num_failures = json_lb_stats.get('numFailures', 0)
161 
162  self.num_peers = 0
163  self.num_oks = 0
170  self.raw = json_lb_stats
171 
172  if 'rpcsByPeer' in json_lb_stats:
173  self.num_peers = len(json_lb_stats['rpcsByPeer'])
174  if 'rpcsByMethod' in json_lb_stats:
175  for rpc_type in json_lb_stats['rpcsByMethod']:
176  for peer in json_lb_stats['rpcsByMethod'][rpc_type][
177  'rpcsByPeer']:
178  count = json_lb_stats['rpcsByMethod'][rpc_type][
179  'rpcsByPeer'][peer]
180  self.num_oks += count
181  if rpc_type == 'UnaryCall':
182  if 'alternative' in peer:
184  self.alternative_service_rpc_count += count
185  else:
187  self.default_service_rpc_count += count
188  else:
189  if 'alternative' in peer:
191  self.alternative_service_rpc_count += count
192  else:
194  self.default_service_rpc_count += count
195 
196 
197 @dataclass
199  """Describes the expected result of assertRpcStatusCode method below."""
200  rpc_type: str = RpcTypeUnaryCall
201  status_code: grpc.StatusCode = grpc.StatusCode.OK
202  ratio: float = 1
203 
204 
206  """Tracking test case subclasses."""
207 
208  # Automatic discover of all subclasses
209  _test_case_classes = []
210  _test_case_names = set()
211  # Keep track of started and finished test cases, so we know when to setup
212  # and tear down GCP resources.
213  _started_test_cases = set()
214  _finished_test_cases = set()
215 
216  def __new__(cls, name: str, bases: Iterable[Any],
217  attrs: Mapping[str, Any]) -> Any:
218  # Hand over the tracking objects
219  attrs['test_case_classes'] = cls._test_case_classes
220  attrs['test_case_names'] = cls._test_case_names
221  attrs['started_test_cases'] = cls._started_test_cases
222  attrs['finished_test_cases'] = cls._finished_test_cases
223  # Handle the test name reflection
224  module_name = os.path.split(
225  sys.modules[attrs['__module__']].__file__)[-1]
226  if module_name.endswith(URL_MAP_TESTCASE_FILE_SUFFIX):
227  module_name = module_name.replace(URL_MAP_TESTCASE_FILE_SUFFIX, '')
228  attrs['short_module_name'] = module_name.replace('_', '-')
229  # Create the class and track
230  new_class = type.__new__(cls, name, bases, attrs)
231  if name.startswith('Test'):
232  cls._test_case_names.add(name)
233  cls._test_case_classes.append(new_class)
234  else:
235  logging.debug('Skipping test case class: %s', name)
236  return new_class
237 
238 
239 class XdsUrlMapTestCase(absltest.TestCase, metaclass=_MetaXdsUrlMapTestCase):
240  """XdsUrlMapTestCase is the base class for urlMap related tests.
241 
242  The subclass is expected to implement 3 methods:
243 
244  - url_map_change: Updates the urlMap components for this test case
245  - xds_config_validate: Validates if the client received legit xDS configs
246  - rpc_distribution_validate: Validates if the routing behavior is correct
247  """
248 
249  @staticmethod
250  def is_supported(config: skips.TestConfig) -> bool:
251  """Allow the test case to decide whether it supports the given config.
252 
253  Returns:
254  A bool indicates if the given config is supported.
255  """
256  del config
257  return True
258 
259  @staticmethod
260  def client_init_config(rpc: str, metadata: str) -> Tuple[str, str]:
261  """Updates the initial RPC configs for this test case.
262 
263  Each test case will start a test client. The client takes RPC configs
264  and starts to send RPCs immediately. The config returned by this
265  function will be used to replace the default configs.
266 
267  The default configs are passed in as arguments, so this method can
268  modify part of them.
269 
270  Args:
271  rpc: The default rpc config, specifying RPCs to send, format
272  'UnaryCall,EmptyCall'
273  metadata: The metadata config, specifying metadata to send with each
274  RPC, format 'EmptyCall:key1:value1,UnaryCall:key2:value2'.
275 
276  Returns:
277  A tuple contains the updated rpc and metadata config.
278  """
279  return rpc, metadata
280 
281  @staticmethod
282  @abc.abstractmethod
284  host_rule: HostRule,
285  path_matcher: PathMatcher) -> Tuple[HostRule, PathMatcher]:
286  """Updates the dedicated urlMap components for this test case.
287 
288  Each test case will have a dedicated HostRule, where the hostname is
289  generated from the test case name. The HostRule will be linked to a
290  PathMatcher, where stores the routing logic.
291 
292  Args:
293  host_rule: A HostRule GCP resource as a JSON dict.
294  path_matcher: A PathMatcher GCP resource as a JSON dict.
295 
296  Returns:
297  A tuple contains the updated version of given HostRule and
298  PathMatcher.
299  """
300 
301  @abc.abstractmethod
302  def xds_config_validate(self, xds_config: DumpedXdsConfig) -> None:
303  """Validates received xDS config, if anything is wrong, raise.
304 
305  This stage only ends when the control plane failed to send a valid
306  config within a given time range, like 600s.
307 
308  Args:
309  xds_config: A DumpedXdsConfig instance can be used as a JSON dict,
310  but also provides helper fields for commonly checked xDS config.
311  """
312 
313  @abc.abstractmethod
314  def rpc_distribution_validate(self, test_client: XdsTestClient) -> None:
315  """Validates the routing behavior, if any is wrong, raise.
316 
317  Args:
318  test_client: A XdsTestClient instance for all sorts of end2end testing.
319  """
320 
321  @classmethod
322  def hostname(cls):
323  return "%s.%s:%s" % (cls.short_module_name, _split_camel(
324  cls.__name__), GcpResourceManager().server_xds_port)
325 
326  @classmethod
328  # Path matcher name must match r'(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?)'
329  return "%s-%s-pm" % (cls.short_module_name, _split_camel(cls.__name__))
330 
331  @classmethod
332  def setUpClass(cls):
333  logging.info('----- Testing %s -----', cls.__name__)
334  logging.info('Logs timezone: %s', time.localtime().tm_zone)
335 
336  # Raises unittest.SkipTest if given client/server/version does not
337  # support current test case.
338  skips.evaluate_test_config(cls.is_supported)
339 
340  if not cls.started_test_cases:
341  # Create the GCP resource once before the first test start
342  GcpResourceManager().setup(cls.test_case_classes)
343  cls.started_test_cases.add(cls.__name__)
344 
345  # Create the test case's own client runner with it's own namespace,
346  # enables concurrent running with other test cases.
347  cls.test_client_runner = GcpResourceManager().create_test_client_runner(
348  )
349  # Start the client, and allow the test to override the initial RPC config.
350  rpc, metadata = cls.client_init_config(rpc="UnaryCall,EmptyCall",
351  metadata="")
353  server_target=f'xds:///{cls.hostname()}',
354  rpc=rpc,
355  metadata=metadata,
356  qps=QPS.value,
357  print_response=True)
358 
359  @classmethod
360  def tearDownClass(cls):
361  cls.test_client_runner.cleanup(force=True, force_namespace=True)
362  cls.finished_test_cases.add(cls.__name__)
363  if cls.finished_test_cases == cls.test_case_names:
364  # Tear down the GCP resource after all tests finished
366 
368  # TODO(lidiz) find another way to store last seen xDS config
369  # Cleanup state for this attempt
370  self._xds_json_config = None # pylint: disable=attribute-defined-outside-init
371  # Fetch client config
372  config = self.test_client.csds.fetch_client_status(
373  log_level=logging.INFO)
374  self.assertIsNotNone(config)
375  # Found client config, test it.
376  self._xds_json_config = json_format.MessageToDict(config) # pylint: disable=attribute-defined-outside-init
377  # Execute the child class provided validation logic
379 
380  def run(self, result: unittest.TestResult = None) -> None:
381  """Abort this test case if CSDS check is failed.
382 
383  This prevents the test runner to waste time on RPC distribution test,
384  and yields clearer signal.
385  """
386  if result.failures or result.errors:
387  logging.info('Aborting %s', self.__class__.__name__)
388  else:
389  super().run(result)
390 
392  retryer = retryers.constant_retryer(
393  wait_fixed=datetime.timedelta(
394  seconds=_URL_MAP_PROPAGATE_CHECK_INTERVAL_SEC),
395  timeout=datetime.timedelta(seconds=_URL_MAP_PROPAGATE_TIMEOUT_SEC),
396  logger=logging,
397  log_level=logging.INFO)
398  try:
399  retryer(self._fetch_and_check_xds_config)
400  finally:
401  logging.info(
402  'latest xDS config:\n%s',
403  GcpResourceManager().td.compute.resource_pretty_format(
404  self._xds_json_config))
405 
408 
409  @staticmethod
410  def configure_and_send(test_client: XdsTestClient,
411  *,
412  rpc_types: Iterable[str],
413  metadata: Optional[Iterable[Tuple[str, str,
414  str]]] = None,
415  app_timeout: Optional[int] = None,
416  num_rpcs: int) -> RpcDistributionStats:
417  test_client.update_config.configure(rpc_types=rpc_types,
418  metadata=metadata,
419  app_timeout=app_timeout)
420  # Configure RPC might race with get stats RPC on slower machines.
421  time.sleep(_CLIENT_CONFIGURE_WAIT_SEC)
422  json_lb_stats = json_format.MessageToDict(
423  test_client.get_load_balancer_stats(num_rpcs=num_rpcs))
424  logging.info(
425  'Received LoadBalancerStatsResponse from test client %s:\n%s',
426  test_client.ip, json.dumps(json_lb_stats, indent=2))
427  return RpcDistributionStats(json_lb_stats)
428 
429  def assertNumEndpoints(self, xds_config: DumpedXdsConfig, k: int) -> None:
430  self.assertLen(
431  xds_config.endpoints, k,
432  f'insufficient endpoints in EDS: want={k} seen={xds_config.endpoints}'
433  )
434 
435  def assertRpcStatusCode( # pylint: disable=too-many-locals
436  self, test_client: XdsTestClient, *,
437  expected: Iterable[ExpectedResult], length: int,
438  tolerance: float) -> None:
439  """Assert the distribution of RPC statuses over a period of time."""
440  # Sending with pre-set QPS for a period of time
441  before_stats = test_client.get_load_balancer_accumulated_stats()
442  logging.info(
443  'Received LoadBalancerAccumulatedStatsResponse from test client %s: before:\n%s',
444  test_client.ip, before_stats)
445  time.sleep(length)
446  after_stats = test_client.get_load_balancer_accumulated_stats()
447  logging.info(
448  'Received LoadBalancerAccumulatedStatsResponse from test client %s: after: \n%s',
449  test_client.ip, after_stats)
450 
451  # Validate the diff
452  for expected_result in expected:
453  rpc = expected_result.rpc_type
454  status = expected_result.status_code.value[0]
455  # Compute observation
456  # ProtoBuf messages has special magic dictionary that we don't need
457  # to catch exceptions:
458  # https://developers.google.com/protocol-buffers/docs/reference/python-generated#undefined
459  seen_after = after_stats.stats_per_method[rpc].result[status]
460  seen_before = before_stats.stats_per_method[rpc].result[status]
461  seen = seen_after - seen_before
462  # Compute total number of RPC started
463  stats_per_method_after = after_stats.stats_per_method.get(
464  rpc, {}).result.items()
465  total_after = sum(
466  x[1] for x in stats_per_method_after) # (status_code, count)
467  stats_per_method_before = before_stats.stats_per_method.get(
468  rpc, {}).result.items()
469  total_before = sum(
470  x[1] for x in stats_per_method_before) # (status_code, count)
471  total = total_after - total_before
472  # Compute and validate the number
473  want = total * expected_result.ratio
474  diff_ratio = abs(seen - want) / total
475  self.assertLessEqual(
476  diff_ratio, tolerance,
477  (f'Expect rpc [{rpc}] to return '
478  f'[{expected_result.status_code}] at '
479  f'{expected_result.ratio:.2f} ratio: '
480  f'seen={seen} want={want} total={total} '
481  f'diff_ratio={diff_ratio:.4f} > {tolerance:.2f}'))
framework.xds_url_map_testcase.XdsUrlMapTestCase.assertRpcStatusCode
None assertRpcStatusCode(self, XdsTestClient test_client, *Iterable[ExpectedResult] expected, int length, float tolerance)
Definition: xds_url_map_testcase.py:435
setup
Definition: setup.py:1
framework.xds_url_map_testcase.DumpedXdsConfig.cds
cds
Definition: xds_url_map_testcase.py:84
framework.xds_url_map_testcase.XdsUrlMapTestCase.finished_test_cases
finished_test_cases
Definition: xds_url_map_testcase.py:363
framework.xds_url_map_testcase.XdsUrlMapTestCase.client_init_config
Tuple[str, str] client_init_config(str rpc, str metadata)
Definition: xds_url_map_testcase.py:260
framework.xds_url_map_testcase.RpcDistributionStats.num_failures
num_failures
Definition: xds_url_map_testcase.py:160
framework.xds_url_map_testcase.RpcDistributionStats.num_oks
num_oks
Definition: xds_url_map_testcase.py:163
framework.xds_url_map_testcase._split_camel
str _split_camel(str s, str delimiter='-')
Definition: xds_url_map_testcase.py:66
framework.xds_url_map_testcase.RpcDistributionStats.num_peers
num_peers
Definition: xds_url_map_testcase.py:162
grpc::testing::sum
double sum(const T &container, F functor)
Definition: test/cpp/qps/stats.h:30
framework.xds_url_map_testcase.DumpedXdsConfig.rds
rds
Definition: xds_url_map_testcase.py:82
framework.xds_url_map_testcase.DumpedXdsConfig.endpoints
endpoints
Definition: xds_url_map_testcase.py:86
framework.xds_url_map_testcase.DumpedXdsConfig.__str__
str __str__(self)
Definition: xds_url_map_testcase.py:141
framework.xds_url_map_testcase.RpcDistributionStats
Definition: xds_url_map_testcase.py:145
google::protobuf
Definition: bloaty/third_party/protobuf/benchmarks/util/data_proto2_to_proto3_util.h:12
framework.xds_url_map_testcase.DumpedXdsConfig.rds_version
rds_version
Definition: xds_url_map_testcase.py:83
framework.xds_url_map_testcase.XdsUrlMapTestCase.xds_config_validate
None xds_config_validate(self, DumpedXdsConfig xds_config)
Definition: xds_url_map_testcase.py:302
framework.xds_url_map_testcase.DumpedXdsConfig
Definition: xds_url_map_testcase.py:72
framework.xds_url_map_testcase.XdsUrlMapTestCase.setUpClass
def setUpClass(cls)
Definition: xds_url_map_testcase.py:332
framework.xds_url_map_testcase.RpcDistributionStats.unary_call_default_service_rpc_count
unary_call_default_service_rpc_count
Definition: xds_url_map_testcase.py:166
framework.xds_url_map_testcase.DumpedXdsConfig.eds
eds
Definition: xds_url_map_testcase.py:85
framework.xds_url_map_testcase.XdsUrlMapTestCase.test_client_config
def test_client_config(self)
Definition: xds_url_map_testcase.py:391
framework.xds_url_map_testcase.XdsUrlMapTestCase.test_client
test_client
Definition: xds_url_map_testcase.py:352
framework.xds_url_map_testcase.XdsUrlMapTestCase.assertNumEndpoints
None assertNumEndpoints(self, DumpedXdsConfig xds_config, int k)
Definition: xds_url_map_testcase.py:429
framework.helpers
Definition: tools/run_tests/xds_k8s_test_driver/framework/helpers/__init__.py:1
framework.xds_url_map_testcase.XdsUrlMapTestCase.url_map_change
Tuple[HostRule, PathMatcher] url_map_change(HostRule host_rule, PathMatcher path_matcher)
Definition: xds_url_map_testcase.py:283
framework.xds_url_map_testcase.XdsUrlMapTestCase.tearDownClass
def tearDownClass(cls)
Definition: xds_url_map_testcase.py:360
framework.xds_url_map_testcase.RpcDistributionStats.raw
raw
Definition: xds_url_map_testcase.py:170
framework.xds_url_map_testcase.XdsUrlMapTestCase.rpc_distribution_validate
None rpc_distribution_validate(self, XdsTestClient test_client)
Definition: xds_url_map_testcase.py:314
framework.test_app
Definition: tools/run_tests/xds_k8s_test_driver/framework/test_app/__init__.py:1
framework.xds_url_map_testcase.XdsUrlMapTestCase._xds_json_config
_xds_json_config
Definition: xds_url_map_testcase.py:370
grpc.StatusCode
Definition: src/python/grpcio/grpc/__init__.py:232
framework.xds_url_map_testcase.GcpResourceManager
GcpResourceManager
Definition: xds_url_map_testcase.py:56
framework.xds_url_map_testcase.ExpectedResult
Definition: xds_url_map_testcase.py:198
framework.xds_url_map_testcase.DumpedXdsConfig.__init__
def __init__(self, JsonType xds_json)
Definition: xds_url_map_testcase.py:78
framework.xds_url_map_testcase._MetaXdsUrlMapTestCase._finished_test_cases
_finished_test_cases
Definition: xds_url_map_testcase.py:214
framework.xds_url_map_testcase.XdsUrlMapTestCase
Definition: xds_url_map_testcase.py:239
framework.xds_url_map_testcase.XdsUrlMapTestCase.is_supported
bool is_supported(skips.TestConfig config)
Definition: xds_url_map_testcase.py:250
add
static void add(const char *beg, const char *end, char ***ss, size_t *ns)
Definition: debug/trace.cc:96
framework.xds_url_map_test_resources.GcpResourceManager
Definition: xds_url_map_test_resources.py:122
framework.xds_url_map_testcase._MetaXdsUrlMapTestCase
Definition: xds_url_map_testcase.py:205
framework.xds_url_map_testcase._MetaXdsUrlMapTestCase._started_test_cases
_started_test_cases
Definition: xds_url_map_testcase.py:213
framework.xds_url_map_testcase.XdsUrlMapTestCase._fetch_and_check_xds_config
def _fetch_and_check_xds_config(self)
Definition: xds_url_map_testcase.py:367
framework.xds_url_map_testcase.DumpedXdsConfig.json_config
json_config
Definition: xds_url_map_testcase.py:80
framework.xds_url_map_testcase.XdsUrlMapTestCase.path_matcher_name
def path_matcher_name(cls)
Definition: xds_url_map_testcase.py:327
cpp.gmock_class.set
set
Definition: bloaty/third_party/googletest/googlemock/scripts/generator/cpp/gmock_class.py:44
framework.xds_url_map_testcase.RpcDistributionStats.unary_call_alternative_service_rpc_count
unary_call_alternative_service_rpc_count
Definition: xds_url_map_testcase.py:168
framework.xds_url_map_testcase._MetaXdsUrlMapTestCase.__new__
Any __new__(cls, str name, Iterable[Any] bases, Mapping[str, Any] attrs)
Definition: xds_url_map_testcase.py:216
framework.xds_url_map_testcase._MetaXdsUrlMapTestCase._test_case_names
_test_case_names
Definition: xds_url_map_testcase.py:210
framework.xds_url_map_testcase._MetaXdsUrlMapTestCase._test_case_classes
list _test_case_classes
Definition: xds_url_map_testcase.py:209
framework.xds_url_map_testcase.XdsUrlMapTestCase.hostname
def hostname(cls)
Definition: xds_url_map_testcase.py:322
framework.xds_url_map_testcase.XdsUrlMapTestCase.test_rpc_distribution
def test_rpc_distribution(self)
Definition: xds_url_map_testcase.py:406
framework.xds_url_map_testcase.XdsUrlMapTestCase.run
None run(self, unittest.TestResult result=None)
Definition: xds_url_map_testcase.py:380
framework.xds_url_map_testcase.XdsUrlMapTestCase.configure_and_send
RpcDistributionStats configure_and_send(XdsTestClient test_client, *Iterable[str] rpc_types, Optional[Iterable[Tuple[str, str, str]]] metadata=None, Optional[int] app_timeout=None, int num_rpcs)
Definition: xds_url_map_testcase.py:410
asyncio_get_stats.type
type
Definition: asyncio_get_stats.py:37
len
int len
Definition: abseil-cpp/absl/base/internal/low_level_alloc_test.cc:46
cleanup
Definition: cleanup.py:1
framework.xds_url_map_testcase.DumpedXdsConfig.lds
lds
Definition: xds_url_map_testcase.py:81
framework.xds_url_map_testcase.RpcDistributionStats.__init__
def __init__(self, JsonType json_lb_stats)
Definition: xds_url_map_testcase.py:159
framework.xds_url_map_testcase.XdsUrlMapTestCase.test_client_runner
test_client_runner
Definition: xds_url_map_testcase.py:347
framework.xds_url_map_testcase.RpcDistributionStats.default_service_rpc_count
default_service_rpc_count
Definition: xds_url_map_testcase.py:164
framework.xds_url_map_testcase.RpcDistributionStats.alternative_service_rpc_count
alternative_service_rpc_count
Definition: xds_url_map_testcase.py:165
framework.xds_url_map_testcase.RpcDistributionStats.empty_call_default_service_rpc_count
empty_call_default_service_rpc_count
Definition: xds_url_map_testcase.py:167
framework.xds_url_map_testcase.RpcDistributionStats.empty_call_alternative_service_rpc_count
empty_call_alternative_service_rpc_count
Definition: xds_url_map_testcase.py:169


grpc
Author(s):
autogenerated on Fri May 16 2025 03:01:00