def test_normal_backoff(self):
        config = self.client_config
        config.max_retry_times = 10
        config.endpoint = "somewhere.you.will.never.get"
        client = EcsClient(config, self.init_credentials_provider())
        request = APIRequest('DescribeInstances', 'GET', 'http', 'RPC')

        globals()['_test_compute_delay'] = []

        def record_sleep(delay):
            global _test_compute_delay
            _test_compute_delay.append(delay)

        with patch.object(time, "sleep", wraps=record_sleep) as monkey:
            try:
                client._handle_request(request)
                assert False
            except HttpErrorException as e:
                self.assertTrue(
                    e.error_message.startswith(
                        "HTTPConnectionPool(host='somewhere.you.will.never.get', port=80)"
                    ))
        # self.assertEqual(10, monkey.call_count)
        self.assertEqual([0.1, 0.2, 0.4, 0.8, 1.6, 3.2, 6.4, 12.8, 20.0, 20.0],
                         _test_compute_delay)
 def test_connect_timeout_priority(self):
     # read config
     config = self.client_config
     config.connection_timeout = "20"
     client = EcsClient(config, self.init_credentials_provider())
     api_request = APIRequest('RunInstances', 'GET', 'http', 'RPC')
     context = client._handle_request(api_request, _raise_exception=False)
     self.assertEqual((20.0, 86), context.http_request.timeout)
     # read file
     config = self.client_config
     config.connection_timeout = None
     client = EcsClient(config, self.init_credentials_provider())
     context = client._handle_request(api_request, _raise_exception=False)
     self.assertEqual((5, 86), context.http_request.timeout)
    def test_throttled_backoff(self):
        def _handle_response(context):
            context.exception = ServerException("Throttling", "some error")

        config = self.client_config
        config.max_retry_times = 10
        config.endpoint = "somewhere.you.will.never.get"
        client = EcsClient(config, self.init_credentials_provider())
        api_request = APIRequest('DescribeInstances', 'GET', 'http', 'RPC')
        globals()["_test_compute_delay"] = []

        def record_sleep(delay):
            global _test_compute_delay
            _test_compute_delay.append(delay)

        from alibabacloud.handlers.api_protocol_handler import APIProtocolHandler
        from alibabacloud.handlers.credentials_handler import CredentialsHandler
        from alibabacloud.handlers.signer_handler import SignerHandler
        from alibabacloud.handlers.timeout_config_reader import TimeoutConfigReader
        from alibabacloud.handlers.endpoint_handler import EndpointHandler
        from alibabacloud.handlers.retry_handler import RetryHandler
        from alibabacloud.handlers.server_error_handler import ServerErrorHandler
        from alibabacloud.handlers.http_handler import HttpHandler
        DEFAULT_HANDLERS = [
            RetryHandler(),
            APIProtocolHandler(),
            CredentialsHandler(),
            SignerHandler(),
            TimeoutConfigReader(),
            EndpointHandler(),
            ServerErrorHandler(),
            HttpHandler(),
        ]

        client.handlers = DEFAULT_HANDLERS
        client.config = config

        with patch.object(time, "sleep", wraps=record_sleep) as monkey:
            with patch.object(ServerErrorHandler,
                              "handle_response",
                              wraps=_handle_response):
                try:
                    client._handle_request(api_request)
                    assert False
                except ServerException as e:
                    self.assertEqual("Throttling", e.error_code)
        self.assertEqual(10, monkey.call_count)
        self.assertEqual(10, len(_test_compute_delay))
 def test_client_customized_timeout(self):
     config = self.client_config
     config.read_timeout = 7
     config.connection_timeout = 8
     client = EcsClient(config, self.init_credentials_provider())
     api_request = APIRequest('DescribeInstances', 'GET', 'http', 'RPC')
     context = client._handle_request(api_request, _raise_exception=False)
     self.assertEqual((8, 7), context.http_request.timeout)
    def test_default_timeout(self):
        config = self.client_config
        config.connection_timeout = None
        config.enable_retry = False
        client = EcsClient(config, self.init_credentials_provider())
        api_request = APIRequest('DescribeInstances', 'GET', 'http', 'RPC')
        context = client._handle_request(api_request, _raise_exception=False)

        self.assertEqual((5, 10), context.http_request.timeout)
    def test_retry_with_client_token(self):
        config = self.client_config
        client = EcsClient(config, self.init_credentials_provider())
        client.max_retry_times = 3
        client.handlers = DEFAULT_HANDLERS
        api_request = APIRequest('CreateInstance', 'GET', 'http', 'RPC')
        api_request._params = {
            'ImageId': "coreos_1745_7_0_64_30G_alibase_20180705.vhd",
            'InstanceType': "ecs.n2.small",
        }

        globals()['_test_client_token'] = None
        globals()['_test_retry_times'] = 0

        def _handle_request(context):
            global _test_client_token
            global _test_retry_times
            context.retry_flag = False
            request = context.api_request
            if _test_retry_times > 0:
                assert _test_client_token == request._params.get("ClientToken")
            _test_retry_times += 1
            _test_client_token = request._params.get("ClientToken")
            context.exception = HttpErrorException(http_error="some error")
            from alibabacloud.request import HTTPResponse
            context.http_response = HTTPResponse('', None, {}, None)

        def no_sleep(delay):
            pass

        with patch.object(time, "sleep", no_sleep):
            with patch.object(client.handlers[6],
                              "handle_request",
                              wraps=_handle_request) as monkey:
                try:
                    ret = client._handle_request(api_request)
                    assert False
                except HttpErrorException as e:
                    self.assertEqual("some error", e.error_message)
            self.assertEqual(4, monkey.call_count)