aboutsummaryrefslogtreecommitdiff
path: root/tools/run_tests/xds_k8s_test_driver/tests/url_map/retry_test.py
diff options
context:
space:
mode:
Diffstat (limited to 'tools/run_tests/xds_k8s_test_driver/tests/url_map/retry_test.py')
-rw-r--r--tools/run_tests/xds_k8s_test_driver/tests/url_map/retry_test.py143
1 files changed, 143 insertions, 0 deletions
diff --git a/tools/run_tests/xds_k8s_test_driver/tests/url_map/retry_test.py b/tools/run_tests/xds_k8s_test_driver/tests/url_map/retry_test.py
new file mode 100644
index 0000000000..8f61b10e1f
--- /dev/null
+++ b/tools/run_tests/xds_k8s_test_driver/tests/url_map/retry_test.py
@@ -0,0 +1,143 @@
+# Copyright 2021 The gRPC Authors
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+import logging
+import time
+from typing import Tuple
+
+from absl import flags
+from absl.testing import absltest
+import grpc
+
+from framework import xds_k8s_flags
+from framework import xds_url_map_testcase
+from framework.test_app import client_app
+
+# Type aliases
+HostRule = xds_url_map_testcase.HostRule
+PathMatcher = xds_url_map_testcase.PathMatcher
+GcpResourceManager = xds_url_map_testcase.GcpResourceManager
+DumpedXdsConfig = xds_url_map_testcase.DumpedXdsConfig
+RpcTypeUnaryCall = xds_url_map_testcase.RpcTypeUnaryCall
+XdsTestClient = client_app.XdsTestClient
+ExpectedResult = xds_url_map_testcase.ExpectedResult
+
+logger = logging.getLogger(__name__)
+flags.adopt_module_key_flags(xds_url_map_testcase)
+
+# The first batch of RPCs don't count towards the result of test case. They are
+# meant to prove the communication between driver and client is fine.
+_NUM_RPCS = 10
+_LENGTH_OF_RPC_SENDING_SEC = 16
+# We are using sleep to synchronize test driver and the client... Even though
+# the client is sending at QPS rate, we can't assert that exactly QPS *
+# SLEEP_DURATION number of RPC is finished. The final completed RPC might be
+# slightly more or less.
+_NON_RANDOM_ERROR_TOLERANCE = 0.01
+_RPC_BEHAVIOR_HEADER_NAME = 'rpc-behavior'
+
+
+def _build_retry_route_rule(retryConditions, num_retries):
+ return {
+ 'priority': 0,
+ 'matchRules': [{
+ 'fullPathMatch': '/grpc.testing.TestService/UnaryCall'
+ }],
+ 'service': GcpResourceManager().default_backend_service(),
+ 'routeAction': {
+ 'retryPolicy': {
+ 'retryConditions': retryConditions,
+ 'numRetries': num_retries,
+ }
+ },
+ }
+
+
+@absltest.skipUnless('cpp-client' in xds_k8s_flags.CLIENT_IMAGE.value or \
+ 'java-client' in xds_k8s_flags.CLIENT_IMAGE.value,
+ 'Xds-retry is currently only implemented in C++ and Java.')
+class TestRetryUpTo3AttemptsAndFail(xds_url_map_testcase.XdsUrlMapTestCase):
+
+ @staticmethod
+ def url_map_change(
+ host_rule: HostRule,
+ path_matcher: PathMatcher) -> Tuple[HostRule, PathMatcher]:
+ path_matcher["routeRules"] = [
+ _build_retry_route_rule(retryConditions=["unavailable"],
+ num_retries=3)
+ ]
+ return host_rule, path_matcher
+
+ def xds_config_validate(self, xds_config: DumpedXdsConfig):
+ self.assertNumEndpoints(xds_config, 1)
+ retry_config = xds_config.rds['virtualHosts'][0]['routes'][0]['route'][
+ 'retryPolicy']
+ self.assertEqual(3, retry_config['numRetries'])
+ self.assertEqual('unavailable', retry_config['retryOn'])
+
+ def rpc_distribution_validate(self, test_client: XdsTestClient):
+ rpc_distribution = self.configure_and_send(
+ test_client,
+ rpc_types=[RpcTypeUnaryCall],
+ metadata=[(RpcTypeUnaryCall, _RPC_BEHAVIOR_HEADER_NAME,
+ 'error-code-14,succeed-on-retry-attempt-4')],
+ num_rpcs=_NUM_RPCS)
+ self.assertRpcStatusCode(test_client,
+ expected=(ExpectedResult(
+ rpc_type=RpcTypeUnaryCall,
+ status_code=grpc.StatusCode.UNAVAILABLE,
+ ratio=1),),
+ length=_LENGTH_OF_RPC_SENDING_SEC,
+ tolerance=_NON_RANDOM_ERROR_TOLERANCE)
+
+
+@absltest.skipUnless('cpp-client' in xds_k8s_flags.CLIENT_IMAGE.value or \
+ 'java-client' in xds_k8s_flags.CLIENT_IMAGE.value,
+ 'Xds-retry is currently only implemented in C++ Java.')
+class TestRetryUpTo4AttemptsAndSucceed(xds_url_map_testcase.XdsUrlMapTestCase):
+
+ @staticmethod
+ def url_map_change(
+ host_rule: HostRule,
+ path_matcher: PathMatcher) -> Tuple[HostRule, PathMatcher]:
+ path_matcher["routeRules"] = [
+ _build_retry_route_rule(retryConditions=["unavailable"],
+ num_retries=4)
+ ]
+ return host_rule, path_matcher
+
+ def xds_config_validate(self, xds_config: DumpedXdsConfig):
+ self.assertNumEndpoints(xds_config, 1)
+ retry_config = xds_config.rds['virtualHosts'][0]['routes'][0]['route'][
+ 'retryPolicy']
+ self.assertEqual(4, retry_config['numRetries'])
+ self.assertEqual('unavailable', retry_config['retryOn'])
+
+ def rpc_distribution_validate(self, test_client: XdsTestClient):
+ rpc_distribution = self.configure_and_send(
+ test_client,
+ rpc_types=[RpcTypeUnaryCall],
+ metadata=[(RpcTypeUnaryCall, _RPC_BEHAVIOR_HEADER_NAME,
+ 'error-code-14,succeed-on-retry-attempt-4')],
+ num_rpcs=_NUM_RPCS)
+ self.assertRpcStatusCode(test_client,
+ expected=(ExpectedResult(
+ rpc_type=RpcTypeUnaryCall,
+ status_code=grpc.StatusCode.OK,
+ ratio=1),),
+ length=_LENGTH_OF_RPC_SENDING_SEC,
+ tolerance=_NON_RANDOM_ERROR_TOLERANCE)
+
+
+if __name__ == '__main__':
+ absltest.main()