def __init__(self):
     self._client = ibm_botocore.session.get_session().create_client(
         's3', 'us-west-2', aws_access_key_id='foo',
         aws_secret_access_key='bar')
     self._stubber = Stubber(self._client)
     self._stubber.activate()
     self._caught_stubber_errors = []
Beispiel #2
0
 def setUp(self):
     session = ibm_botocore.session.get_session()
     config = ibm_botocore.config.Config(
         signature_version=ibm_botocore.UNSIGNED,
         s3={'addressing_style': 'path'})
     self.client = session.create_client('s3',
                                         region_name='us-east-1',
                                         config=config)
     self.stubber = Stubber(self.client)
 def setUp(self):
     self.session = ibm_botocore.session.get_session()
     self.region = 'us-west-2'
     self.client = self.session.create_client('s3',
                                              self.region,
                                              aws_access_key_id='foo',
                                              aws_secret_access_key='bar')
     self.stubber = Stubber(self.client)
     self.stubber.activate()
Beispiel #4
0
 def setUp(self):
     super(TestAutoscalingPagination, self).setUp()
     self.region = 'us-west-2'
     self.client = self.session.create_client('autoscaling',
                                              self.region,
                                              aws_secret_access_key='foo',
                                              aws_access_key_id='bar',
                                              aws_session_token='baz')
     self.stubber = Stubber(self.client)
     self.stubber.activate()
 def reset_stubber_with_new_client(self, override_client_kwargs):
     client_kwargs = {
         'service_name': 's3',
         'region_name': self.region,
         'aws_access_key_id': 'foo',
         'aws_secret_access_key': 'bar'
     }
     client_kwargs.update(override_client_kwargs)
     self.client = self.session.create_client(**client_kwargs)
     self.stubber = Stubber(self.client)
     self.stubber.activate()
Beispiel #6
0
 def setUp(self):
     self.event_emitter = hooks.HierarchicalEmitter()
     self.client = mock.Mock()
     self.client.meta.events = self.event_emitter
     self.client.meta.method_to_api_mapping.get.return_value = 'foo'
     self.stubber = Stubber(self.client)
     self.validate_parameters_mock = mock.Mock()
     self.validate_parameters_patch = mock.patch(
         'ibm_botocore.stub.validate_parameters',
         self.validate_parameters_mock)
     self.validate_parameters_patch.start()
 def setUp(self):
     self.session = ibm_boto3.session.Session(
         aws_access_key_id='foo', aws_secret_access_key='bar',
         region_name='us-west-2')
     self.s3 = self.session.resource('s3')
     self.stubber = Stubber(self.s3.meta.client)
     self.bucket = 'mybucket'
     self.key = 'mykey'
     self.upload_id = 'uploadid'
     self.etag = '"example0etag"'
     self.progress = 0
     self.progress_times_called = 0
Beispiel #8
0
class TestCloudwatchLogsPagination(BaseSessionTest):
    def setUp(self):
        super(TestCloudwatchLogsPagination, self).setUp()
        self.region = 'us-west-2'
        self.client = self.session.create_client('logs',
                                                 self.region,
                                                 aws_secret_access_key='foo',
                                                 aws_access_key_id='bar',
                                                 aws_session_token='baz')
        self.stubber = Stubber(self.client)
        self.stubber.activate()

    def test_token_with_triple_underscores(self):
        response = {
            'events': [{
                'logStreamName': 'foobar',
                'timestamp': 1560195817,
                'message': 'a thing happened',
                'ingestionTime': 1560195817,
                'eventId': 'foo',
            }],
            'searchedLogStreams': [{
                'logStreamName': 'foobar',
                'searchedCompletely': False,
            }],
        }
        group_name = 'foo'
        token = 'foo___bar'
        expected_args = {
            'logGroupName': group_name,
            'nextToken': token,
        }
        self.stubber.add_response('filter_log_events', response, expected_args)
        paginator = self.client.get_paginator('filter_log_events')
        pages = paginator.paginate(
            PaginationConfig={
                'MaxItems': 1,
                'StartingToken': token,
            },
            logGroupName=group_name,
        )
        result = pages.build_full_result()
        self.assertEqual(len(result['events']), 1)
Beispiel #9
0
 def setUp(self):
     self.session = ibm_boto3.session.Session(aws_access_key_id='foo',
                                              aws_secret_access_key='bar',
                                              region_name='us-west-2')
     self.s3 = self.session.resource('s3')
     self.obj_summary = self.s3.ObjectSummary('my_bucket', 'my_key')
     self.obj_summary_size = 12
     self.stubber = Stubber(self.s3.meta.client)
     self.stubber.activate()
     self.stubber.add_response(method='head_object',
                               service_response={
                                   'ContentLength': self.obj_summary_size,
                                   'ETag': 'my-etag',
                                   'ContentType': 'binary'
                               },
                               expected_params={
                                   'Bucket': 'my_bucket',
                                   'Key': 'my_key'
                               })
class StubbedClientTest(unittest.TestCase):
    def setUp(self):
        self.session = ibm_botocore.session.get_session()
        self.region = 'us-west-2'
        self.client = self.session.create_client('s3',
                                                 self.region,
                                                 aws_access_key_id='foo',
                                                 aws_secret_access_key='bar')
        self.stubber = Stubber(self.client)
        self.stubber.activate()

    def tearDown(self):
        self.stubber.deactivate()

    def reset_stubber_with_new_client(self, override_client_kwargs):
        client_kwargs = {
            'service_name': 's3',
            'region_name': self.region,
            'aws_access_key_id': 'foo',
            'aws_secret_access_key': 'bar'
        }
        client_kwargs.update(override_client_kwargs)
        self.client = self.session.create_client(**client_kwargs)
        self.stubber = Stubber(self.client)
        self.stubber.activate()
Beispiel #11
0
class TestRDSPagination(BaseSessionTest):
    def setUp(self):
        super(TestRDSPagination, self).setUp()
        self.region = 'us-west-2'
        self.client = self.session.create_client('rds', self.region)
        self.stubber = Stubber(self.client)

    def test_can_specify_zero_marker(self):
        service_response = {
            'LogFileData': 'foo',
            'Marker': '2',
            'AdditionalDataPending': True
        }
        expected_params = {
            'DBInstanceIdentifier': 'foo',
            'LogFileName': 'bar',
            'NumberOfLines': 2,
            'Marker': '0'
        }
        function_name = 'download_db_log_file_portion'

        # The stubber will assert that the function is called with the expected
        # parameters.
        self.stubber.add_response(function_name, service_response,
                                  expected_params)
        self.stubber.activate()

        try:
            paginator = self.client.get_paginator(function_name)
            result = paginator.paginate(DBInstanceIdentifier='foo',
                                        LogFileName='bar',
                                        NumberOfLines=2,
                                        PaginationConfig={
                                            'StartingToken': '0',
                                            'MaxItems': 3
                                        }).build_full_result()
            self.assertEqual(result['LogFileData'], 'foo')
            self.assertIn('NextToken', result)
        except StubAssertionError as e:
            self.fail(str(e))
Beispiel #12
0
 def create_client_sts_stub(service, *args, **kwargs):
     client = _original_create_client(service, *args, **kwargs)
     stub = Stubber(client)
     response = self.create_assume_role_response(expected_creds)
     self.actual_client_region = client.meta.region_name
     stub.add_response('assume_role', response)
     stub.activate()
     return client
Beispiel #13
0
class TestS3ObjectSummary(unittest.TestCase):
    def setUp(self):
        self.session = ibm_boto3.session.Session(
            aws_access_key_id='foo',
            aws_secret_access_key='bar',
            region_name='us-west-2',
        )
        self.s3 = self.session.resource('s3')
        self.obj_summary = self.s3.ObjectSummary('my_bucket', 'my_key')
        self.obj_summary_size = 12
        self.stubber = Stubber(self.s3.meta.client)
        self.stubber.activate()
        self.stubber.add_response(
            method='head_object',
            service_response={
                'ContentLength': self.obj_summary_size,
                'ETag': 'my-etag',
                'ContentType': 'binary',
            },
            expected_params={
                'Bucket': 'my_bucket',
                'Key': 'my_key'
            },
        )

    def tearDown(self):
        self.stubber.deactivate()

    def test_has_load(self):
        # Validate load was injected onto ObjectSummary.
        assert hasattr(self.obj_summary, 'load')

    def test_autoloads_correctly(self):
        # In HeadObject the parameter returned is ContentLength, this
        # should get mapped to Size of ListObject since the resource uses
        # the shape returned to by ListObjects.
        assert self.obj_summary.size == self.obj_summary_size

    def test_cannot_access_other_non_related_parameters(self):
        # Even though an HeadObject was used to load this, it should
        # only expose the attributes from its shape defined in ListObjects.
        assert not hasattr(self.obj_summary, 'content_length')
    def test_provide_copy_source_client(self):
        source_client = self.session.create_client(
            's3', 'eu-central-1', aws_access_key_id='foo',
            aws_secret_access_key='bar')
        source_stubber = Stubber(source_client)
        source_stubber.activate()
        self.addCleanup(source_stubber.deactivate)

        self.add_head_object_response(stubber=source_stubber)
        self.add_successful_copy_responses()

        call_kwargs = self.create_call_kwargs()
        call_kwargs['source_client'] = source_client
        future = self.manager.copy(**call_kwargs)
        future.result()

        # Make sure that all of the responses were properly
        # used for both clients.
        source_stubber.assert_no_pending_responses()
        self.stubber.assert_no_pending_responses()
class StubbedClient(object):
    def __init__(self):
        self._client = ibm_botocore.session.get_session().create_client(
            's3', 'us-west-2', aws_access_key_id='foo',
            aws_secret_access_key='bar')
        self._stubber = Stubber(self._client)
        self._stubber.activate()
        self._caught_stubber_errors = []

    def get_object(self, **kwargs):
        return self._client.get_object(**kwargs)

    def head_object(self, **kwargs):
        return self._client.head_object(**kwargs)

    def add_response(self, *args, **kwargs):
        self._stubber.add_response(*args, **kwargs)

    def add_client_error(self, *args, **kwargs):
        self._stubber.add_client_error(*args, **kwargs)
Beispiel #16
0
class TestAutoscalingPagination(BaseSessionTest):
    def setUp(self):
        super(TestAutoscalingPagination, self).setUp()
        self.region = 'us-west-2'
        self.client = self.session.create_client('autoscaling',
                                                 self.region,
                                                 aws_secret_access_key='foo',
                                                 aws_access_key_id='bar',
                                                 aws_session_token='baz')
        self.stubber = Stubber(self.client)
        self.stubber.activate()

    def _setup_scaling_pagination(self,
                                  page_size=200,
                                  max_items=100,
                                  total_items=600):
        """
        Add to the stubber to test paginating describe_scaling_activities.

        WARNING: This only handles cases where max_items cleanly divides
        page_size.
        """
        requests_per_page = page_size / max_items
        if requests_per_page != ceil(requests_per_page):
            raise NotImplementedError(
                "This only handles setup where max_items is less than "
                "page_size and where max_items evenly divides page_size.")
        requests_per_page = int(requests_per_page)
        num_pages = int(ceil(total_items / page_size))

        previous_next_token = None
        for i in range(num_pages):
            page = self.create_describe_scaling_response(page_size=page_size)

            # Don't create a next_token for the final page
            if i + 1 == num_pages:
                next_token = None
            else:
                next_token = random_chars(10)

            expected_args = {}
            if previous_next_token:
                expected_args['StartingToken'] = previous_next_token

            # The same page may be accessed multiple times because we are
            # truncating it at max_items
            for _ in range(requests_per_page - 1):
                # The page is copied because the paginator will modify the
                # response object, causing issues when using the stubber.
                self.stubber.add_response('describe_scaling_activities',
                                          page.copy())

            if next_token is not None:
                page['NextToken'] = next_token

            # Copying the page here isn't necessary because it is about to
            # be blown away anyway.
            self.stubber.add_response('describe_scaling_activities', page)

            previous_next_token = next_token

    def create_describe_scaling_response(self, page_size=200):
        """Create a valid describe_scaling_activities response."""
        page = []
        date = datetime.now()
        for _ in range(page_size):
            page.append({
                'AutoScalingGroupName': 'test',
                'ActivityId': random_chars(10),
                'Cause': 'test',
                'StartTime': date,
                'StatusCode': '200',
            })
        return {'Activities': page}

    def test_repeated_build_full_results(self):
        # This ensures that we can cleanly paginate using build_full_results.
        max_items = 100
        total_items = 600
        self._setup_scaling_pagination(max_items=max_items,
                                       total_items=total_items,
                                       page_size=200)
        paginator = self.client.get_paginator('describe_scaling_activities')
        conf = {'MaxItems': max_items}

        pagination_tokens = []

        result = paginator.paginate(PaginationConfig=conf).build_full_result()
        all_results = result['Activities']
        while 'NextToken' in result:
            starting_token = result['NextToken']
            # We should never get a duplicate pagination token.
            self.assertNotIn(starting_token, pagination_tokens)
            pagination_tokens.append(starting_token)

            conf['StartingToken'] = starting_token
            pages = paginator.paginate(PaginationConfig=conf)
            result = pages.build_full_result()
            all_results.extend(result['Activities'])

        self.assertEqual(len(all_results), total_items)
Beispiel #17
0
 def setUp(self):
     super(TestRDSPagination, self).setUp()
     self.region = 'us-west-2'
     self.client = self.session.create_client('rds', self.region)
     self.stubber = Stubber(self.client)
class BaseTransferTest(unittest.TestCase):
    def setUp(self):
        self.session = ibm_boto3.session.Session(
            aws_access_key_id='foo', aws_secret_access_key='bar',
            region_name='us-west-2')
        self.s3 = self.session.resource('s3')
        self.stubber = Stubber(self.s3.meta.client)
        self.bucket = 'mybucket'
        self.key = 'mykey'
        self.upload_id = 'uploadid'
        self.etag = '"example0etag"'
        self.progress = 0
        self.progress_times_called = 0

    def stub_head(self, content_length=4, expected_params=None):
        head_response = {
            'AcceptRanges': 'bytes',
            'ContentLength': content_length,
            'ContentType': 'binary/octet-stream',
            'ETag': self.etag,
            'Metadata': {},
            'ResponseMetadata': {
                'HTTPStatusCode': 200,
            }
        }

        if expected_params is None:
            expected_params = {
                'Bucket': self.bucket,
                'Key': self.key
            }

        self.stubber.add_response(
            method='head_object', service_response=head_response,
            expected_params=expected_params)

    def stub_create_multipart_upload(self):
        # Add the response and assert params for CreateMultipartUpload
        create_upload_response = {
            "Bucket": self.bucket,
            "Key": self.key,
            "UploadId": self.upload_id
        }
        expected_params = {
            "Bucket": self.bucket,
            "Key": self.key,
        }
        self.stubber.add_response(
            method='create_multipart_upload',
            service_response=create_upload_response,
            expected_params=expected_params)

    def stub_complete_multipart_upload(self, parts):
        complete_upload_response = {
            "Location": "us-west-2",
            "Bucket": self.bucket,
            "Key": self.key,
            "ETag": self.etag
        }
        expected_params = {
            "Bucket": self.bucket,
            "Key": self.key,
            "MultipartUpload": {
                "Parts": parts
            },
            "UploadId": self.upload_id
        }

        self.stubber.add_response(
            method='complete_multipart_upload',
            service_response=complete_upload_response,
            expected_params=expected_params)
Beispiel #19
0
class TestStubber(unittest.TestCase):
    def setUp(self):
        self.event_emitter = hooks.HierarchicalEmitter()
        self.client = mock.Mock()
        self.client.meta.events = self.event_emitter
        self.client.meta.method_to_api_mapping.get.return_value = 'foo'
        self.stubber = Stubber(self.client)
        self.validate_parameters_mock = mock.Mock()
        self.validate_parameters_patch = mock.patch(
            'ibm_botocore.stub.validate_parameters',
            self.validate_parameters_mock)
        self.validate_parameters_patch.start()

    def tearDown(self):
        self.validate_parameters_patch.stop()

    def emit_get_response_event(self,
                                model=None,
                                request_dict=None,
                                signer=None,
                                context=None):
        if model is None:
            model = mock.Mock()
            model.name = 'foo'

        handler, response = self.event_emitter.emit_until_response(
            event_name='before-call.myservice.foo',
            model=model,
            params=request_dict,
            request_signer=signer,
            context=context)

        return response

    def test_stubber_registers_events(self):
        self.event_emitter = mock.Mock()
        self.client.meta.events = self.event_emitter
        self.stubber.activate()
        # This just ensures that we register at the correct event
        # and nothing more
        self.event_emitter.register_first.assert_called_with(
            'before-parameter-build.*.*', mock.ANY, unique_id=mock.ANY)
        self.event_emitter.register.assert_called_with('before-call.*.*',
                                                       mock.ANY,
                                                       unique_id=mock.ANY)

    def test_stubber_unregisters_events(self):
        self.event_emitter = mock.Mock()
        self.client.meta.events = self.event_emitter
        self.stubber.activate()
        self.stubber.deactivate()
        self.event_emitter.unregister.assert_any_call(
            'before-parameter-build.*.*', mock.ANY, unique_id=mock.ANY)
        self.event_emitter.unregister.assert_any_call('before-call.*.*',
                                                      mock.ANY,
                                                      unique_id=mock.ANY)

    def test_context_manager(self):
        self.event_emitter = mock.Mock()
        self.client.meta.events = self.event_emitter

        with self.stubber:
            # Ensure events are registered in context
            self.event_emitter.register_first.assert_called_with(
                'before-parameter-build.*.*', mock.ANY, unique_id=mock.ANY)
            self.event_emitter.register.assert_called_with('before-call.*.*',
                                                           mock.ANY,
                                                           unique_id=mock.ANY)

        # Ensure events are no longer registered once we leave the context
        self.event_emitter.unregister.assert_any_call(
            'before-parameter-build.*.*', mock.ANY, unique_id=mock.ANY)
        self.event_emitter.unregister.assert_any_call('before-call.*.*',
                                                      mock.ANY,
                                                      unique_id=mock.ANY)

    def test_add_response(self):
        response = {'foo': 'bar'}
        self.stubber.add_response('foo', response)

        with self.assertRaises(AssertionError):
            self.stubber.assert_no_pending_responses()

    def test_add_response_fails_when_missing_client_method(self):
        del self.client.foo
        with self.assertRaises(ValueError):
            self.stubber.add_response('foo', {})

    def test_validates_service_response(self):
        self.stubber.add_response('foo', {})
        self.assertTrue(self.validate_parameters_mock.called)

    def test_validate_ignores_response_metadata(self):
        service_response = {'ResponseMetadata': {'foo': 'bar'}}
        service_model = ServiceModel({
            'documentation': '',
            'operations': {
                'foo': {
                    'name': 'foo',
                    'input': {
                        'shape': 'StringShape'
                    },
                    'output': {
                        'shape': 'StringShape'
                    }
                }
            },
            'shapes': {
                'StringShape': {
                    'type': 'string'
                }
            }
        })
        op_name = service_model.operation_names[0]
        output_shape = service_model.operation_model(op_name).output_shape

        self.client.meta.service_model = service_model
        self.stubber.add_response('TestOperation', service_response)
        self.validate_parameters_mock.assert_called_with({}, output_shape)

        # Make sure service response hasn't been mutated
        self.assertEqual(service_response,
                         {'ResponseMetadata': {
                             'foo': 'bar'
                         }})

    def test_validates_on_empty_output_shape(self):
        service_model = ServiceModel({
            'documentation': '',
            'operations': {
                'foo': {
                    'name': 'foo'
                }
            }
        })
        self.client.meta.service_model = service_model

        with self.assertRaises(ParamValidationError):
            self.stubber.add_response('TestOperation', {'foo': 'bar'})

    def test_get_response(self):
        service_response = {'bar': 'baz'}
        self.stubber.add_response('foo', service_response)
        self.stubber.activate()
        response = self.emit_get_response_event()
        self.assertEqual(response[1], service_response)
        self.assertEqual(response[0].status_code, 200)

    def test_get_client_error_response(self):
        error_code = "foo"
        service_message = "bar"
        self.stubber.add_client_error('foo', error_code, service_message)
        self.stubber.activate()
        response = self.emit_get_response_event()
        self.assertEqual(response[1]['Error']['Message'], service_message)
        self.assertEqual(response[1]['Error']['Code'], error_code)

    def test_get_client_error_with_extra_error_meta(self):
        error_code = "foo"
        error_message = "bar"
        error_meta = {
            "Endpoint": "https://foo.bar.baz",
        }
        self.stubber.add_client_error('foo',
                                      error_code,
                                      error_message,
                                      http_status_code=301,
                                      service_error_meta=error_meta)
        with self.stubber:
            response = self.emit_get_response_event()
        error = response[1]['Error']
        self.assertIn('Endpoint', error)
        self.assertEqual(error['Endpoint'], "https://foo.bar.baz")

    def test_get_client_error_with_extra_response_meta(self):
        error_code = "foo"
        error_message = "bar"
        stub_response_meta = {
            "RequestId": "79104EXAMPLEB723",
        }
        self.stubber.add_client_error('foo',
                                      error_code,
                                      error_message,
                                      http_status_code=301,
                                      response_meta=stub_response_meta)
        with self.stubber:
            response = self.emit_get_response_event()
        actual_response_meta = response[1]['ResponseMetadata']
        self.assertIn('RequestId', actual_response_meta)
        self.assertEqual(actual_response_meta['RequestId'], "79104EXAMPLEB723")

    def test_get_response_errors_with_no_stubs(self):
        self.stubber.activate()
        with self.assertRaises(UnStubbedResponseError):
            self.emit_get_response_event()

    def test_assert_no_responses_remaining(self):
        self.stubber.add_response('foo', {})
        with self.assertRaises(AssertionError):
            self.stubber.assert_no_pending_responses()
Beispiel #20
0
 def _create_stubbed_client(self, service_name, *args, **kwargs):
     client = super(StubbedSession,
                    self).create_client(service_name, *args, **kwargs)
     stubber = Stubber(client)
     self._client_stubs[service_name] = stubber
     return client
    def setUp(self):
        session = ibm_botocore.session.get_session()
        config = ibm_botocore.config.Config(signature_version=ibm_botocore.UNSIGNED)
        self.client = session.create_client('s3', config=config)

        self.stubber = Stubber(self.client)
class TestStubber(unittest.TestCase):
    def setUp(self):
        session = ibm_botocore.session.get_session()
        config = ibm_botocore.config.Config(signature_version=ibm_botocore.UNSIGNED)
        self.client = session.create_client('s3', config=config)

        self.stubber = Stubber(self.client)

    def test_stubber_returns_response(self):
        service_response = {'ResponseMetadata': {'foo': 'bar'}}
        self.stubber.add_response('list_objects', service_response)
        self.stubber.activate()
        response = self.client.list_objects(Bucket='foo')
        self.assertEqual(response, service_response)

    def test_context_manager_returns_response(self):
        service_response = {'ResponseMetadata': {'foo': 'bar'}}
        self.stubber.add_response('list_objects', service_response)

        with self.stubber:
            response = self.client.list_objects(Bucket='foo')
        self.assertEqual(response, service_response)

    def test_activated_stubber_errors_with_no_registered_stubs(self):
        self.stubber.activate()
        # Params one per line for readability.
        with self.assertRaisesRegexp(StubResponseError,
                                     "'Bucket': 'asdfasdfasdfasdf',\n"):
            self.client.list_objects(
                Bucket='asdfasdfasdfasdf',
                Delimiter='asdfasdfasdfasdf',
                Prefix='asdfasdfasdfasdf',
                EncodingType='url')

    def test_stubber_errors_when_stubs_are_used_up(self):
        self.stubber.add_response('list_objects', {})
        self.stubber.activate()
        self.client.list_objects(Bucket='foo')

        with self.assertRaises(StubResponseError):
            self.client.list_objects(Bucket='foo')

    def test_client_error_response(self):
        error_code = "AccessDenied"
        error_message = "Access Denied"
        self.stubber.add_client_error(
            'list_objects', error_code, error_message)
        self.stubber.activate()

        with self.assertRaises(ClientError):
            self.client.list_objects(Bucket='foo')

    def test_can_add_expected_params_to_client_error(self):
        self.stubber.add_client_error(
            'list_objects', 'Error', 'error',
            expected_params={'Bucket': 'foo'}
        )
        self.stubber.activate()
        with self.assertRaises(ClientError):
            self.client.list_objects(Bucket='foo')

    def test_can_expected_param_fails_in_client_error(self):
        self.stubber.add_client_error(
            'list_objects', 'Error', 'error',
            expected_params={'Bucket': 'foo'}
        )
        self.stubber.activate()
        # We expect an AssertionError instead of a ClientError
        # because we're calling the operation with the wrong
        # param value.
        with self.assertRaises(AssertionError):
            self.client.list_objects(Bucket='wrong-argument-value')

    def test_expected_params_success(self):
        service_response = {}
        expected_params = {'Bucket': 'foo'}
        self.stubber.add_response(
            'list_objects', service_response, expected_params)
        self.stubber.activate()
        # This should be called successfully with no errors being thrown
        # for mismatching expected params.
        response = self.client.list_objects(Bucket='foo')
        self.assertEqual(response, service_response)

    def test_expected_params_fail(self):
        service_response = {}
        expected_params = {'Bucket': 'bar'}
        self.stubber.add_response(
            'list_objects', service_response, expected_params)
        self.stubber.activate()
        # This should call should raise an for mismatching expected params.
        with self.assertRaisesRegexp(StubResponseError,
                                     "{'Bucket': 'bar'},\n"):
            self.client.list_objects(Bucket='foo')

    def test_expected_params_mixed_with_errors_responses(self):
        # Add an error response
        error_code = "AccessDenied"
        error_message = "Access Denied"
        self.stubber.add_client_error(
            'list_objects', error_code, error_message)

        # Add a response with incorrect expected params
        service_response = {}
        expected_params = {'Bucket': 'bar'}
        self.stubber.add_response(
            'list_objects', service_response, expected_params)

        self.stubber.activate()

        # The first call should throw and error as expected.
        with self.assertRaises(ClientError):
            self.client.list_objects(Bucket='foo')

        # The second call should throw an error for unexpected parameters
        with self.assertRaisesRegexp(StubResponseError, 'Expected parameters'):
            self.client.list_objects(Bucket='foo')

    def test_can_continue_to_call_after_expected_params_fail(self):
        service_response = {}
        expected_params = {'Bucket': 'bar'}

        self.stubber.add_response(
            'list_objects', service_response, expected_params)

        self.stubber.activate()
        # Throw an error for unexpected parameters
        with self.assertRaises(StubResponseError):
            self.client.list_objects(Bucket='foo')

        # The stubber should still have the responses queued up
        # even though the original parameters did not match the expected ones.
        self.client.list_objects(Bucket='bar')
        self.stubber.assert_no_pending_responses()

    def test_still_relies_on_param_validation_with_expected_params(self):
        service_response = {}
        expected_params = {'Buck': 'bar'}

        self.stubber.add_response(
            'list_objects', service_response, expected_params)

        self.stubber.activate()
        # Throw an error for invalid parameters
        with self.assertRaises(ParamValidationError):
            self.client.list_objects(Buck='bar')

    def test_any_ignores_param_for_validation(self):
        service_response = {}
        expected_params = {'Bucket': stub.ANY}

        self.stubber.add_response(
            'list_objects', service_response, expected_params)
        self.stubber.add_response(
            'list_objects', service_response, expected_params)

        try:
            with self.stubber:
                self.client.list_objects(Bucket='foo')
                self.client.list_objects(Bucket='bar')
        except StubAssertionError:
            self.fail("stub.ANY failed to ignore parameter for validation.")

    def test_mixed_any_and_concrete_params(self):
        service_response = {}
        expected_params = {'Bucket': stub.ANY, 'Key': 'foo.txt'}

        self.stubber.add_response(
            'head_object', service_response, expected_params)
        self.stubber.add_response(
            'head_object', service_response, expected_params)

        try:
            with self.stubber:
                self.client.head_object(Bucket='foo', Key='foo.txt')
                self.client.head_object(Bucket='bar', Key='foo.txt')
        except StubAssertionError:
            self.fail("stub.ANY failed to ignore parameter for validation.")

    def test_nested_any_param(self):
        service_response = {}
        expected_params = {
            'Bucket': 'foo',
            'Key': 'bar.txt',
            'Metadata': {
                'MyMeta': stub.ANY,
            }
        }

        self.stubber.add_response(
            'put_object', service_response, expected_params)
        self.stubber.add_response(
            'put_object', service_response, expected_params)

        try:
            with self.stubber:
                self.client.put_object(
                    Bucket='foo',
                    Key='bar.txt',
                    Metadata={
                        'MyMeta': 'Foo',
                    }
                )
                self.client.put_object(
                    Bucket='foo',
                    Key='bar.txt',
                    Metadata={
                        'MyMeta': 'Bar',
                    }
                )
        except StubAssertionError:
            self.fail(
                "stub.ANY failed to ignore nested parameter for validation.")

    def test_ANY_repr(self):
        self.assertEqual(repr(stub.ANY), '<ANY>')

    def test_none_param(self):
        service_response = {}
        expected_params = {'Buck': None}

        self.stubber.add_response(
            'list_objects', service_response, expected_params)

        self.stubber.activate()
        # Throw an error for invalid parameters
        with self.assertRaises(StubAssertionError):
            self.client.list_objects(Buck='bar')

    def test_many_expected_params(self):
        service_response = {}
        expected_params = {
            'Bucket': 'mybucket',
            'Prefix': 'myprefix',
            'Delimiter': '/',
            'EncodingType': 'url'
        }
        self.stubber.add_response(
            'list_objects', service_response, expected_params)
        try:
            with self.stubber:
                self.client.list_objects(**expected_params)
        except StubAssertionError:
            self.fail(
                "Stubber inappropriately raised error for same parameters.")