retry_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 import grpc
20 
21 from framework import xds_url_map_testcase
22 from framework.helpers import skips
23 from framework.test_app import client_app
24 
25 # Type aliases
26 HostRule = xds_url_map_testcase.HostRule
27 PathMatcher = xds_url_map_testcase.PathMatcher
28 GcpResourceManager = xds_url_map_testcase.GcpResourceManager
29 DumpedXdsConfig = xds_url_map_testcase.DumpedXdsConfig
30 RpcTypeUnaryCall = xds_url_map_testcase.RpcTypeUnaryCall
31 XdsTestClient = client_app.XdsTestClient
32 ExpectedResult = xds_url_map_testcase.ExpectedResult
33 _Lang = skips.Lang
34 
35 logger = logging.getLogger(__name__)
36 flags.adopt_module_key_flags(xds_url_map_testcase)
37 
38 # The first batch of RPCs don't count towards the result of test case. They are
39 # meant to prove the communication between driver and client is fine.
40 _NUM_RPCS = 10
41 _LENGTH_OF_RPC_SENDING_SEC = 16
42 # We are using sleep to synchronize test driver and the client... Even though
43 # the client is sending at QPS rate, we can't assert that exactly QPS *
44 # SLEEP_DURATION number of RPC is finished. The final completed RPC might be
45 # slightly more or less.
46 _NON_RANDOM_ERROR_TOLERANCE = 0.01
47 _RPC_BEHAVIOR_HEADER_NAME = 'rpc-behavior'
48 
49 
50 def _build_retry_route_rule(retryConditions, num_retries):
51  return {
52  'priority': 0,
53  'matchRules': [{
54  'fullPathMatch': '/grpc.testing.TestService/UnaryCall'
55  }],
56  'service': GcpResourceManager().default_backend_service(),
57  'routeAction': {
58  'retryPolicy': {
59  'retryConditions': retryConditions,
60  'numRetries': num_retries,
61  }
62  },
63  }
64 
65 
66 def _is_supported(config: skips.TestConfig) -> bool:
67  # Per "Retry" in
68  # https://github.com/grpc/grpc/blob/master/doc/grpc_xds_features.md
69  if config.client_lang in _Lang.CPP | _Lang.JAVA | _Lang.PYTHON:
70  return config.version_gte('v1.40.x')
71  elif config.client_lang == _Lang.GO:
72  return config.version_gte('v1.41.x')
73  elif config.client_lang == _Lang.NODE:
74  return False
75  return True
76 
77 
78 class TestRetryUpTo3AttemptsAndFail(xds_url_map_testcase.XdsUrlMapTestCase):
79 
80  @staticmethod
81  def is_supported(config: skips.TestConfig) -> bool:
82  return _is_supported(config)
83 
84  @staticmethod
86  host_rule: HostRule,
87  path_matcher: PathMatcher) -> Tuple[HostRule, PathMatcher]:
88  path_matcher["routeRules"] = [
89  _build_retry_route_rule(retryConditions=["unavailable"],
90  num_retries=3)
91  ]
92  return host_rule, path_matcher
93 
94  def xds_config_validate(self, xds_config: DumpedXdsConfig):
95  self.assertNumEndpoints(xds_config, 1)
96  retry_config = xds_config.rds['virtualHosts'][0]['routes'][0]['route'][
97  'retryPolicy']
98  self.assertEqual(3, retry_config['numRetries'])
99  self.assertEqual('unavailable', retry_config['retryOn'])
100 
101  def rpc_distribution_validate(self, test_client: XdsTestClient):
102  self.configure_and_send(test_client,
103  rpc_types=(RpcTypeUnaryCall,),
104  metadata=[
105  (RpcTypeUnaryCall,
106  _RPC_BEHAVIOR_HEADER_NAME,
107  'error-code-14,succeed-on-retry-attempt-4')
108  ],
109  num_rpcs=_NUM_RPCS)
110  self.assertRpcStatusCode(test_client,
111  expected=(ExpectedResult(
112  rpc_type=RpcTypeUnaryCall,
113  status_code=grpc.StatusCode.UNAVAILABLE,
114  ratio=1),),
115  length=_LENGTH_OF_RPC_SENDING_SEC,
116  tolerance=_NON_RANDOM_ERROR_TOLERANCE)
117 
118 
119 class TestRetryUpTo4AttemptsAndSucceed(xds_url_map_testcase.XdsUrlMapTestCase):
120 
121  @staticmethod
122  def is_supported(config: skips.TestConfig) -> bool:
123  return _is_supported(config)
124 
125  @staticmethod
127  host_rule: HostRule,
128  path_matcher: PathMatcher) -> Tuple[HostRule, PathMatcher]:
129  path_matcher["routeRules"] = [
130  _build_retry_route_rule(retryConditions=["unavailable"],
131  num_retries=4)
132  ]
133  return host_rule, path_matcher
134 
135  def xds_config_validate(self, xds_config: DumpedXdsConfig):
136  self.assertNumEndpoints(xds_config, 1)
137  retry_config = xds_config.rds['virtualHosts'][0]['routes'][0]['route'][
138  'retryPolicy']
139  self.assertEqual(4, retry_config['numRetries'])
140  self.assertEqual('unavailable', retry_config['retryOn'])
141 
142  def rpc_distribution_validate(self, test_client: XdsTestClient):
143  self.configure_and_send(test_client,
144  rpc_types=(RpcTypeUnaryCall,),
145  metadata=[
146  (RpcTypeUnaryCall,
147  _RPC_BEHAVIOR_HEADER_NAME,
148  'error-code-14,succeed-on-retry-attempt-4')
149  ],
150  num_rpcs=_NUM_RPCS)
151  self.assertRpcStatusCode(test_client,
152  expected=(ExpectedResult(
153  rpc_type=RpcTypeUnaryCall,
154  status_code=grpc.StatusCode.OK,
155  ratio=1),),
156  length=_LENGTH_OF_RPC_SENDING_SEC,
157  tolerance=_NON_RANDOM_ERROR_TOLERANCE)
158 
159 
160 if __name__ == '__main__':
161  absltest.main()
tests.url_map.retry_test.TestRetryUpTo4AttemptsAndSucceed.rpc_distribution_validate
def rpc_distribution_validate(self, XdsTestClient test_client)
Definition: retry_test.py:142
tests.url_map.retry_test.TestRetryUpTo4AttemptsAndSucceed.xds_config_validate
def xds_config_validate(self, DumpedXdsConfig xds_config)
Definition: retry_test.py:135
tests.url_map.retry_test.GcpResourceManager
GcpResourceManager
Definition: retry_test.py:28
framework.helpers
Definition: tools/run_tests/xds_k8s_test_driver/framework/helpers/__init__.py:1
tests.url_map.retry_test.TestRetryUpTo3AttemptsAndFail
Definition: retry_test.py:78
tests.url_map.retry_test.TestRetryUpTo3AttemptsAndFail.xds_config_validate
def xds_config_validate(self, DumpedXdsConfig xds_config)
Definition: retry_test.py:94
tests.url_map.retry_test.TestRetryUpTo3AttemptsAndFail.is_supported
bool is_supported(skips.TestConfig config)
Definition: retry_test.py:81
tests.url_map.retry_test._build_retry_route_rule
def _build_retry_route_rule(retryConditions, num_retries)
Definition: retry_test.py:50
framework.test_app
Definition: tools/run_tests/xds_k8s_test_driver/framework/test_app/__init__.py:1
tests.url_map.retry_test.ExpectedResult
ExpectedResult
Definition: retry_test.py:32
tests.url_map.retry_test._is_supported
bool _is_supported(skips.TestConfig config)
Definition: retry_test.py:66
tests.url_map.retry_test.TestRetryUpTo3AttemptsAndFail.rpc_distribution_validate
def rpc_distribution_validate(self, XdsTestClient test_client)
Definition: retry_test.py:101
tests.url_map.retry_test.TestRetryUpTo4AttemptsAndSucceed.is_supported
bool is_supported(skips.TestConfig config)
Definition: retry_test.py:122
tests.url_map.retry_test.TestRetryUpTo3AttemptsAndFail.url_map_change
Tuple[HostRule, PathMatcher] url_map_change(HostRule host_rule, PathMatcher path_matcher)
Definition: retry_test.py:85
tests.url_map.retry_test.TestRetryUpTo4AttemptsAndSucceed.url_map_change
Tuple[HostRule, PathMatcher] url_map_change(HostRule host_rule, PathMatcher path_matcher)
Definition: retry_test.py:126
tests.url_map.retry_test.TestRetryUpTo4AttemptsAndSucceed
Definition: retry_test.py:119


grpc
Author(s):
autogenerated on Thu Mar 13 2025 03:01:11