Beispiel #1
0
def test_delete_grant_by_alias():
    kms = botocore.session.get_session().create_client("kms")
    stubber = Stubber(kms)
    revoke_grant_response = {}
    revoke_grant_request = {
        "GrantId":
        "12312312312",
        "KeyId":
        "arn:aws:kms:eu-central-1:123123123123:key/85fff602-d2eb-42d9-b467-f68d5a19b8ef",
    }
    stubber.add_response("list_aliases", list_aliases_response, {})
    stubber.add_response("revoke_grant", revoke_grant_response,
                         revoke_grant_request)
    stubber.activate()
    provider._kms = kms
    request = Request(
        "Delete",
        {
            "GrantId": revoke_grant_request["GrantId"],
            "KeyAliasArn":
            "arn:aws:kms:eu-central-1:123123123123:alias/aws/ebs",
        },
        physical_resource_id=revoke_grant_request["GrantId"],
    )
    response = handler(request, ())
    assert response["Status"] == "SUCCESS", response["Reason"]
    stubber.assert_no_pending_responses()
    stubber.deactivate()
Beispiel #2
0
    def test_lock_persistent_graph_locked(self):
        """Error raised when when object is locked."""
        code = "0000"
        context = Context(config=self.persist_graph_config)
        context._s3_bucket_verified = True
        context._persistent_graph = Graph()
        stubber = Stubber(context.s3_conn)
        expected_params = {
            "Tagging": {
                "TagSet":
                gen_tagset({context._persistent_graph_lock_tag: code})
            }
        }
        expected_params.update(context.persistent_graph_location)

        stubber.add_response(
            "get_object_tagging",
            {
                "TagSet": gen_tagset(
                    {context._persistent_graph_lock_tag: "1111"})
            },
            context.persistent_graph_location,
        )

        with stubber:
            with self.assertRaises(PersistentGraphLocked):
                context.lock_persistent_graph(code)
            stubber.assert_no_pending_responses()
Beispiel #3
0
def test_support_package_url_no_match(create_command):
    "If there is no plausible candidate support package, raise an error"
    # Prime the s3 client, and wrap it in a stubber.
    s3 = create_command._anonymous_s3_client('us-west-2')
    stub_s3 = Stubber(s3)

    # Add the expected request/responses from S3
    stub_s3.add_response(method='list_objects_v2',
                         expected_params={
                             'Bucket': 'briefcase-support',
                             'Prefix': 'python/3.X/tester/'
                         },
                         service_response={
                             'KeyCount': 0,
                         })

    # We've set up all the expected S3 responses, so activate the stub
    stub_s3.activate()

    # Retrieve the property, retrieving the support package URL.
    with pytest.raises(NoSupportPackage):
        create_command.support_package_url

    # Check the S3 calls have been exhausted
    stub_s3.assert_no_pending_responses()
Beispiel #4
0
    def test_put_persistent_graph(self):
        """Return 'None' when put is successful."""
        code = '0000'
        context = Context(config=self.persist_graph_config)
        context._s3_bucket_verified = True
        graph_dict = {'stack1': [], 'stack2': ['stack1']}
        context._persistent_graph = Graph.from_dict(graph_dict, context)
        stubber = Stubber(context.s3_conn)
        expected_params = {
            'Body': json.dumps(graph_dict, indent=4),
            'ServerSideEncryption': 'AES256',
            'ACL': 'bucket-owner-full-control',
            'ContentType': 'application/json',
            'Tagging': '{}={}'.format(context._persistent_graph_lock_tag, code)
        }
        expected_params.update(context.persistent_graph_location)

        stubber.add_response(
            'get_object_tagging',
            {'TagSet': gen_tagset({context._persistent_graph_lock_tag: code})},
            context.persistent_graph_location)
        stubber.add_response('put_object', {}, expected_params)

        with stubber:
            self.assertIsNone(context.put_persistent_graph(code))
            stubber.assert_no_pending_responses()
Beispiel #5
0
    def test_persistent_graph_no_object(self):
        """Create object if one does not exist and return empty Graph."""
        context = Context(config=self.persist_graph_config)
        context._s3_bucket_verified = True
        stubber = Stubber(context.s3_conn)
        expected_get_params = {'ResponseContentType': 'application/json'}
        expected_get_params.update(context.persistent_graph_location)
        expected_put_params = {
            'Body': '{}',
            'ServerSideEncryption': 'AES256',
            'ACL': 'bucket-owner-full-control',
            'ContentType': 'application/json'
        }
        expected_put_params.update(context.persistent_graph_location)

        stubber.add_client_error('get_object',
                                 'NoSuchKey',
                                 expected_params=expected_get_params)
        stubber.add_response('put_object', {}, expected_put_params)

        with stubber:
            self.assertIsNone(context._persistent_graph)
            self.assertIsInstance(context.persistent_graph, Graph)
            self.assertIsInstance(context._persistent_graph, Graph)
            self.assertEqual({}, context.persistent_graph.to_dict())
            stubber.assert_no_pending_responses()
Beispiel #6
0
def test_delete_packages_if_spec_deleted(stubbed_s3_client: stub.Stubber):
    """
    GIVEN notification, packages and mocked S3 client
    WHEN delete_packages_if_spec_deleted is called with the notification and packages
    THEN delete objects is called.
    """
    bucket_name = "bucket1"
    object_key = "key 1"
    notification = app.Notification(bucket_name=bucket_name, object_key=object_key)
    packages = [
        library.Package(
            storage_location="storage location 1",
            path=pathlib.Path("some/location1.tar.gz"),
        ),
        library.Package(
            storage_location="storage location 2",
            path=pathlib.Path("some/location2.tar.gz"),
        ),
    ]

    expected_params = {
        "Bucket": bucket_name,
        "Delete": {
            "Objects": [{"Key": package.storage_location} for package in packages]
        },
    }
    stubbed_s3_client.add_response("delete_objects", {}, expected_params)
    stubbed_s3_client.activate()

    app.delete_packages_if_spec_deleted(False, notification, packages)

    stubbed_s3_client.assert_no_pending_responses()
    def test_wait_for_stack(self):
        cfn = boto3.client('cloudformation', region_name="eu-west-1")
        stubber = Stubber(cfn)
        stubber.add_response('describe_stacks',
                             service_response={
                                 "Stacks": [{
                                     "StackName":
                                     "some_stack",
                                     "CreationTime":
                                     datetime.datetime.today(),
                                     "StackStatus":
                                     "",
                                 }],
                             },
                             expected_params={"StackName": "some_stack"})
        stubber.add_response('describe_stacks',
                             service_response={
                                 "Stacks": [{
                                     "StackName":
                                     "some_stack",
                                     "CreationTime":
                                     datetime.datetime.today(),
                                     "StackStatus":
                                     "CREATE_COMPLETE",
                                     "Description":
                                     "bar",
                                 }],
                             },
                             expected_params={"StackName": "some_stack"})
        stubber.activate()

        stack = setup.CfnStack(cfn, "some_stack")
        response = stack.wait_for_stack()
        self.assertEqual(response["Description"], "bar")
        stubber.assert_no_pending_responses()
def test_verification_failed():
    ses = botocore.session.get_session().create_client("ses",
                                                       region_name="eu-west-1")
    stubber = Stubber(ses)
    stubber.add_response(
        "get_identity_verification_attributes",
        GetIdentityVerificationAttributesReponse({
            "lists.binx.io": {
                "VerificationStatus": "Failed",
                "VerificationToken": "123",
            }
        }),
        {"Identities": ["lists.binx.io"]},
    )
    stubber.activate()
    provider._ses = ses
    counter = Counter()
    provider.invoke_lambda = counter.increment
    assert provider.interval_in_seconds == 15
    provider.interval_in_seconds = 1

    request = Request("Create", "lists.binx.io", "eu-west-1")
    response = handler(request, ())
    assert response["Status"] == "FAILED", response["Reason"]
    assert not provider.asynchronous
    stubber.assert_no_pending_responses()
Beispiel #9
0
def test_support_package_url_single_match(create_command):
    # Prime the s3 client, and wrap it in a stubber.
    s3 = create_command._anonymous_s3_client('us-west-2')
    stub_s3 = Stubber(s3)

    # Add the expected request/responses from S3
    stub_s3.add_response(
        method='list_objects_v2',
        expected_params={
            'Bucket': 'briefcase-support',
            'Prefix': 'python/3.X/tester/'
        },
        service_response={
            'Contents': [{
                'Key':
                'python/3.X/tester/Python-3.X-tester-support.b1.tar.gz'
            }],
            'KeyCount':
            1,
        })

    # We've set up all the expected S3 responses, so activate the stub
    stub_s3.activate()

    # Retrieve the property, retrieving the support package URL.
    url = 'https://briefcase-support.s3-us-west-2.amazonaws.com/python/3.X/tester/Python-3.X-tester-support.b1.tar.gz'
    assert create_command.support_package_url == url

    # Check the S3 calls have been exhausted
    stub_s3.assert_no_pending_responses()
Beispiel #10
0
def test_create(ddb_stubber: Stubber):
    response = {}

    now = 1234567890.01234567
    release_id = 290012

    params = {
        'ConditionExpression':
        'attribute_not_exists(category) AND attribute_not_exists(#model_release_id)',
        'ExpressionAttributeNames': {
            '#model_release_id': 'release-id'
        },
        'Item': {
            'category': 'AVATAR',
            'description': 'An item description',
            'price': 100,
            'release-id': -release_id,
            'rarity': 'RARE'
        },
        'ReturnValues': 'NONE',
        'TableName': 'rewards'
    }

    ddb_stubber.add_response('put_item', response, params)

    with patch('time.time', lambda: now):
        RewardsService.create("An item description", RewardType.AVATAR, 3,
                              RewardRarity.RARE, 100)

    ddb_stubber.assert_no_pending_responses()
Beispiel #11
0
    def test_resolve_ssm_params(self, caplog, kwargs, parameters, expected):
        """Test resolve_ssm_params."""
        # this test is not compatable with python 2 due to how it handles dicts
        caplog.set_level('WARNING', logger='runway')

        client = boto3.client('ssm')
        stubber = Stubber(client)

        for param in parameters:
            stubber.add_response(
                'get_parameter', {
                    'Parameter': {
                        'Name': param['name'],
                        'Value': param['value'],
                        'LastModifiedDate': datetime.now()
                    }
                }, {
                    'Name': param['name'],
                    'WithDecryption': True
                })

        with stubber:
            assert TerraformBackendConfig.resolve_ssm_params(
                client, **kwargs) == expected
        stubber.assert_no_pending_responses()
        assert 'deprecated' in caplog.records[0].msg
Beispiel #12
0
def test_no_revisions(s3):
    "If there are no files for the version, and a revision is requested, raise an error"
    stub_s3 = Stubber(s3)

    # Add the expected request/responses from S3
    stub_s3.add_response(method='list_objects_v2',
                         expected_params={
                             'Bucket': 'briefcase-support',
                             'Prefix': 'python/3.X/tester/'
                         },
                         service_response={
                             'KeyCount': 0,
                         })

    # We've set up all the expected S3 responses, so activate the stub
    stub_s3.activate()

    # Retrieve the property, retrieving the support package URL.
    with pytest.raises(ValueError):
        support_url(
            s3,
            bucket='briefcase-support',
            platform='tester',
            version='3.X',
            host_arch=None,
            revision='b8',
        )

    # Check the S3 calls have been exhausted
    stub_s3.assert_no_pending_responses()
Beispiel #13
0
    def test_renew_tokens(self, _):

        stub = Stubber(self.user.client)

        # By the stubber nature, we need to add the sequence
        # of calls for the AWS SRP auth to test the whole process
        stub.add_response(
            method="initiate_auth",
            service_response={
                "AuthenticationResult": {
                    "TokenType": "admin",
                    "IdToken": "dummy_token",
                    "AccessToken": "dummy_token",
                    "RefreshToken": "dummy_token",
                },
                "ResponseMetadata": {"HTTPStatusCode": 200},
            },
            expected_params={
                "ClientId": self.app_id,
                "AuthFlow": "REFRESH_TOKEN_AUTH",
                "AuthParameters": {"REFRESH_TOKEN": "dummy_token"},
            },
        )

        with stub:
            self.user.authenticate(self.password)
            self.user.renew_access_token()
            stub.assert_no_pending_responses()
Beispiel #14
0
    def test_lock_persistent_graph_no_object(self):
        """Error raised when when there is no object to lock."""
        code = "0000"
        context = Context(config=self.persist_graph_config)
        context._s3_bucket_verified = True
        context._persistent_graph = Graph()
        stubber = Stubber(context.s3_conn)
        expected_params = {
            "Tagging": {
                "TagSet":
                gen_tagset({context._persistent_graph_lock_tag: code})
            }
        }
        expected_params.update(context.persistent_graph_location)

        stubber.add_client_error(
            "get_object_tagging",
            "NoSuchKey",
            expected_params=context.persistent_graph_location,
        )
        stubber.add_client_error("put_object_tagging",
                                 "NoSuchKey",
                                 expected_params=expected_params)

        with stubber:
            with self.assertRaises(PersistentGraphCannotLock):
                context.lock_persistent_graph(code)
            stubber.assert_no_pending_responses()
Beispiel #15
0
    def test_s3_bucket_does_not_exist_us_west(self):
        """Create S3 bucket with loc constraints when it does not exist."""
        region = "us-west-1"
        context = Context(config=self.config, region=region)
        stubber = Stubber(context.s3_conn)

        stubber.add_client_error(
            "head_bucket",
            service_error_code="NoSuchBucket",
            service_message="Not Found",
            http_status_code=404,
        )
        stubber.add_response(
            "create_bucket",
            service_response={},
            expected_params={
                "Bucket": ANY,
                "CreateBucketConfiguration": {
                    "LocationConstraint": region
                },
            },
        )

        with stubber:
            self.assertIsNone(context._s3_bucket_verified)
            self.assertTrue(context.s3_bucket_verified)
            self.assertTrue(context._s3_bucket_verified)
            stubber.assert_no_pending_responses()
Beispiel #16
0
    def test_renew_tokens(self, _):

        stub = Stubber(self.user.client)

        # By the stubber nature, we need to add the sequence
        # of calls for the AWS SRP auth to test the whole process
        stub.add_response(method='initiate_auth',
                          service_response={
                              'AuthenticationResult': {
                                  'TokenType': 'admin',
                                  'IdToken': 'dummy_token',
                                  'AccessToken': 'dummy_token',
                                  'RefreshToken': 'dummy_token'
                              },
                              'ResponseMetadata': {
                                  'HTTPStatusCode': 200
                              }
                          },
                          expected_params={
                              'ClientId': self.app_id,
                              'AuthFlow': 'REFRESH_TOKEN',
                              'AuthParameters': {
                                  'REFRESH_TOKEN': 'dummy_token'
                              }
                          })

        with stub:
            self.user.authenticate(self.password)
            self.user.renew_access_token()
            stub.assert_no_pending_responses()
    def test_prune_snapshots(self):
        """
        Tests snapshot pruning by providing three snapshots - one manual and
        two automatic of which one is has an elapsed retention period. The
        test asserts that only the eligible snapshot is pruned via stubbing
        the API call to delete_instance_snapshot and verifying the output.
        """
        mock_dt = MagicMock()
        mock_dt.now.return_value = datetime(2016, 12, 2)
        logger = StringIO()
        client = boto3.client('lightsail')
        stubber = Stubber(client)
        stubber.add_response(
            'get_instance_snapshots', {
                'instanceSnapshots': [{
                    'name': 'snapshot-manual',
                    'createdAt': datetime(2016, 12, 1)
                }, {
                    'name': 'new-snapshot-auto',
                    'createdAt': datetime(2016, 12, 1)
                }, {
                    'name': 'old-snapshot-auto',
                    'createdAt': datetime(2016, 10, 15)
                }]
            })
        stubber.add_response('delete_instance_snapshot', {},
                             {'instanceSnapshotName': 'old-snapshot-auto'})
        stubber.activate()

        index._prune_snapshots(client, timedelta(days=5), mock_dt, logger)

        stubber.assert_no_pending_responses()
        self.assertEqual('Deleted Snapshot name="old-snapshot-auto"',
                         logger.getvalue().strip())
    def test_read_s3_file_content_exists(self, mock_s3_resource):
        """
        read_s3_file_content
        Tests that s3 file is read correctly
        """
        body_mock = Mock()
        body_mock.read.return_value.decode.return_value = "body"

        s3 = boto3.resource('s3')
        stubber = Stubber(s3.meta.client)

        mock_response = {
            'Body': body_mock,
            'ResponseMetadata': {
                'RequestId': '2CA0C8ABC59ED601',
                'HostId':
                'W81yYPFfh/26bdCJGImLxHYIKQxKIABbu6uLSF8XhuDoPL3gtRsP9x39VyePZeP/XE4C8LHrp6Q=',
                'HTTPStatusCode': 200
            }
        }
        stubber.add_response('get_object',
                             expected_params={
                                 'Bucket': 'bucket',
                                 'Key': 'key'
                             },
                             service_response=mock_response)

        mock_s3_resource.return_value = s3

        with stubber:
            content = read_s3_file_content("bucket", "key")

        self.assertEqual('body', content)
        stubber.assert_no_pending_responses()
Beispiel #19
0
    def test_get_certificate(self, cfngin_context, patch_time):
        """Test get_certificate."""
        # setup context
        cfngin_context.add_stubber('acm', 'us-east-1')
        cfngin_context.add_stubber('route53', 'us-east-1')
        cfngin_context.config.namespace = 'test'

        provider = MagicMock(cloudformation=boto3.client('cloudformation'))
        cfn_stubber = Stubber(provider.cloudformation)

        cert = Certificate(context=cfngin_context,
                           provider=provider,
                           domain='example.com',
                           hosted_zone_id='test')

        expected_request = {
            'StackName': 'test-example-com',
            'LogicalResourceId': 'Certificate'
        }

        cfn_stubber.add_response('describe_stack_resources',
                                 {'StackResources': []}, expected_request)
        cfn_stubber.add_response('describe_stack_resources',
                                 {'StackResources': [gen_stack_resource()]},
                                 expected_request)
        cfn_stubber.add_response('describe_stack_resources', {
            'StackResources':
            [gen_stack_resource(PhysicalResourceId='success')]
        }, expected_request)

        with cfn_stubber:
            assert cert.get_certificate() == 'success'

        cfn_stubber.assert_no_pending_responses()
    def test_snapshot_instances(self):
        """
        Tests instance snapshotting by stubbing one instance in the response to
        the get_instances call and verifying the create_instance_snapshot API
        endpoint is called with the expected parameters and verifying the
        output.
        """
        mock_time = MagicMock()
        mock_time.return_value = 1485044158
        logger = StringIO()
        client = boto3.client('lightsail')
        stubber = Stubber(client)
        stubber.add_response('get_instances',
                             {'instances': [{
                                 'name': 'LinuxBox1'
                             }]})
        stubber.add_response(
            'create_instance_snapshot', {}, {
                'instanceName': 'LinuxBox1',
                'instanceSnapshotName': 'LinuxBox1-system-1485044158000-auto'
            })
        stubber.activate()

        index._snapshot_instances(client, mock_time, logger)

        stubber.assert_no_pending_responses()
        self.assertEqual(
            'Created Snapshot name="LinuxBox1-system-1485044158000-auto"',
            logger.getvalue().strip())
Beispiel #21
0
def test_creates_dead_letter_queue():
    # Given that I have an SQS broker with dead letters turned on
    broker = SQSBroker(
        namespace="dramatiq_sqs_tests",
        dead_letter=True,
        max_receives=20,
    )

    # And I've stubbed out all the relevant API calls
    stubber = Stubber(broker.sqs.meta.client)
    stubber.add_response("create_queue", {"QueueUrl": ""})
    stubber.add_response("create_queue", {"QueueUrl": ""})
    stubber.add_response("get_queue_attributes",
                         {"Attributes": {
                             "QueueArn": "dlq"
                         }})
    stubber.add_response("set_queue_attributes", {}, {
        "QueueUrl": "",
        "Attributes": {
            "RedrivePolicy":
            json.dumps({
                "deadLetterTargetArn": "dlq",
                "maxReceiveCount": "20"
            })
        }
    })

    # When I create a queue
    # Then a dead-letter queue should be created
    # And a redrive policy matching the queue and max receives should be added
    with stubber:
        broker.declare_queue("test")
        stubber.assert_no_pending_responses()
Beispiel #22
0
    def test_admin_authenticate(self):

        stub = Stubber(self.user.client)

        # By the stubber nature, we need to add the sequence
        # of calls for the AWS SRP auth to test the whole process
        stub.add_response(
            method="admin_initiate_auth",
            service_response={
                "AuthenticationResult": {
                    "TokenType": "admin",
                    "IdToken": "dummy_token",
                    "AccessToken": "dummy_token",
                    "RefreshToken": "dummy_token",
                }
            },
            expected_params={
                "UserPoolId": self.cognito_user_pool_id,
                "ClientId": self.app_id,
                "AuthFlow": "ADMIN_NO_SRP_AUTH",
                "AuthParameters": {
                    "USERNAME": self.username,
                    "PASSWORD": self.password,
                },
            },
        )

        with stub:
            self.user.admin_authenticate(self.password)
            self.assertNotEqual(self.user.access_token, None)
            self.assertNotEqual(self.user.id_token, None)
            self.assertNotEqual(self.user.refresh_token, None)
            stub.assert_no_pending_responses()
Beispiel #23
0
    def test_put_persistent_graph(self):
        """Return 'None' when put is successful."""
        code = "0000"
        context = Context(config=self.persist_graph_config)
        context._s3_bucket_verified = True
        graph_dict = {"stack1": [], "stack2": ["stack1"]}
        context._persistent_graph = Graph.from_dict(graph_dict, context)
        stubber = Stubber(context.s3_conn)
        expected_params = {
            "Body": json.dumps(graph_dict, indent=4),
            "ServerSideEncryption": "AES256",
            "ACL": "bucket-owner-full-control",
            "ContentType": "application/json",
            "Tagging": "{}={}".format(context._persistent_graph_lock_tag,
                                      code),
        }
        expected_params.update(context.persistent_graph_location)

        stubber.add_response(
            "get_object_tagging",
            {"TagSet": gen_tagset({context._persistent_graph_lock_tag: code})},
            context.persistent_graph_location,
        )
        stubber.add_response("put_object", {}, expected_params)

        with stubber:
            self.assertIsNone(context.put_persistent_graph(code))
            stubber.assert_no_pending_responses()
Beispiel #24
0
    def test_admin_authenticate(self):

        stub = Stubber(self.user.client)

        # By the stubber nature, we need to add the sequence
        # of calls for the AWS SRP auth to test the whole process
        stub.add_response(method='admin_initiate_auth',
                          service_response={
                              'AuthenticationResult': {
                                  'TokenType': 'admin',
                                  'IdToken': 'dummy_token',
                                  'AccessToken': 'dummy_token',
                                  'RefreshToken': 'dummy_token'
                              }
                          },
                          expected_params={
                              'UserPoolId': self.cognito_user_pool_id,
                              'ClientId': self.app_id,
                              'AuthFlow': 'ADMIN_NO_SRP_AUTH',
                              'AuthParameters': {
                                  'USERNAME': self.username,
                                  'PASSWORD': self.password
                              }
                          })

        with stub:
            self.user.admin_authenticate(self.password)
            self.assertNotEqual(self.user.access_token, None)
            self.assertNotEqual(self.user.id_token, None)
            self.assertNotEqual(self.user.refresh_token, None)
            stub.assert_no_pending_responses()
Beispiel #25
0
    def test_get_snsname_arn_auth_exception_handling(self, aws_res_mock):
        """AuthorizationError is intercepted and re-raised as AssertionError"""
        # local imports of code-under-test ensure moto has mocks
        # registered before any possible calls out to AWS
        from awstools.awstools import get_snsname_arn

        # create a mock SNS client that returns what we tell it to
        client = boto3.client('sns')
        stub = Stubber(client)
        stub.add_client_error('create_topic', service_error_code='AuthorizationError')
        stub.activate()


        # since firesim manager code doesn't take clients as method parameters
        # now we mock boto3.client to return our stubbed client
        with patch.object(boto3._get_default_session(), 'client', return_value=client) as mock_session:
            topic_arn = get_snsname_arn()

            stub.assert_no_pending_responses()
            assert topic_arn == None

            # TODO we could mock rootLogger.critical to capture it's calls and args and validate that we're seeing the correct "nice" message

            # make sure get_snsname_arn() actually called out to get a sns
            # client, otherwise we aren't testing what we think we are
            mock_session.assert_called_once_with('sns')

        aws_res_mock.assert_called_once()
Beispiel #26
0
    def test_mutating_filters(self):
        stubber = Stubber(self.service_resource.meta.client)
        instance_filters = [{
            'Name': 'instance-state-name',
            'Values': ['running']
        }]
        running_instances = self.service_resource.instances.filter(
            Filters=instance_filters)

        # This should not impact the already-created filter.
        instance_filters.append({
            'Name': 'instance-type',
            'Values': ['c4.large']
        })

        stubber.add_response(method='describe_instances',
                             service_response={'Reservations': []},
                             expected_params={
                                 'Filters': [{
                                     'Name': 'instance-state-name',
                                     'Values': ['running']
                                 }]
                             })

        with stubber:
            list(running_instances)

        stubber.assert_no_pending_responses()
Beispiel #27
0
    def test_persistent_graph_no_object(self):
        """Create object if one does not exist and return empty Graph."""
        context = Context(config=self.persist_graph_config)
        context._s3_bucket_verified = True
        stubber = Stubber(context.s3_conn)
        expected_get_params = {"ResponseContentType": "application/json"}
        expected_get_params.update(context.persistent_graph_location)
        expected_put_params = {
            "Body": "{}",
            "ServerSideEncryption": "AES256",
            "ACL": "bucket-owner-full-control",
            "ContentType": "application/json",
        }
        expected_put_params.update(context.persistent_graph_location)

        stubber.add_client_error("get_object",
                                 "NoSuchKey",
                                 expected_params=expected_get_params)
        stubber.add_response("put_object", {}, expected_put_params)

        with stubber:
            self.assertIsNone(context._persistent_graph)
            self.assertIsInstance(context.persistent_graph, Graph)
            self.assertIsInstance(context._persistent_graph, Graph)
            self.assertEqual({}, context.persistent_graph.to_dict())
            stubber.assert_no_pending_responses()
Beispiel #28
0
    def test_change_password(self, _):
        # u = cognito_user(self.cognito_user_pool_id, self.app_id,
        #                  username=self.username)
        self.user.authenticate(self.password)

        stub = Stubber(self.user.client)

        stub.add_response(
            method="change_password",
            service_response={"ResponseMetadata": {
                "HTTPStatusCode": 200
            }},
            expected_params={
                "PreviousPassword": self.password,
                "ProposedPassword": "******",
                "AccessToken": self.user.access_token,
            },
        )

        with stub:
            self.user.change_password(self.password, "crazypassword$45DOG")
            stub.assert_no_pending_responses()

        with self.assertRaises(ParamValidationError):
            self.user.change_password(self.password, None)
Beispiel #29
0
def test_put_s3():
    client = boto3.client('s3')
    stub = Stubber(client)

    bucket = 'test-bucket'
    key = 'file'
    body = 'test'.encode()
    contentType = 'application/json'
    response = {
        'Expiration': 'expiration',
        'ETag': 'etag',
    }
    params = {
        'Bucket': bucket,
        'Key': key,
        'Body': body,
        'ContentType': contentType
    }
    stub.add_response('put_object',
                      service_response=response,
                      expected_params=params)

    with stub:
        resource.put_s3(client, bucket, key, body, contentType)
        stub.assert_no_pending_responses()
    def test_write_s3_file_basic(self, mock_s3_resource,
                                 mock_filedata_is_already_on_s3):
        """
        write_s3_file
        Tests that s3 put_object gets called with the basic parameters
        """
        s3 = boto3.resource('s3')
        stubber = Stubber(s3.meta.client)
        mock_response = {
            'ResponseMetadata': {
                'RequestId': '2CA0C8ABC59ED601',
                'HostId':
                'W81yYPFfh/26bdCJGImLxHYIKQxKIABbu6uLSF8XhuDoPL3gtRsP9x39VyePZeP/XE4C8LHrp6Q=',
                'HTTPStatusCode': 200
            }
        }

        # TEST that it calls put object with the basic params
        stubber.add_response('put_object',
                             expected_params={
                                 'Bucket': 'bucket',
                                 'Key': 'key',
                                 'Body': "data"
                             },
                             service_response=mock_response)

        mock_s3_resource.return_value = s3
        mock_filedata_is_already_on_s3.return_value = False

        with stubber:
            write_s3_file("bucket", "key", "data")

        stubber.assert_no_pending_responses()
Beispiel #31
0
    def test_mutating_filters(self):
        stubber = Stubber(self.service_resource.meta.client)
        instance_filters = [
            {'Name': 'instance-state-name', 'Values': ['running']}
        ]
        running_instances = self.service_resource.instances.filter(
            Filters=instance_filters
        )

        # This should not impact the already-created filter.
        instance_filters.append(
            {'Name': 'instance-type', 'Values': ['c4.large']}
        )

        stubber.add_response(
            method='describe_instances',
            service_response={
                'Reservations': []
            },
            expected_params={
                'Filters': [{
                    'Name': 'instance-state-name',
                    'Values': ['running']
                }]
            }
        )

        with stubber:
            list(running_instances)

        stubber.assert_no_pending_responses()
Beispiel #32
0
 def test_delete_tags(self):
     stubber = Stubber(self.instance_resource.meta.client)
     stubber.add_response('delete_tags', {})
     stubber.activate()
     response = self.instance_resource.delete_tags(Tags=[{'Key': 'foo'}])
     stubber.assert_no_pending_responses()
     self.assertEqual(response, {})
     stubber.deactivate()
Beispiel #33
0
    def test_operation_without_output(self):
        table = self.resource.Table('mytable')
        stubber = Stubber(table.meta.client)
        stubber.add_response('tag_resource', {})
        arn = 'arn:aws:dynamodb:us-west-2:123456789:table/mytable'

        with stubber:
            table.meta.client.tag_resource(
                ResourceArn=arn,
                Tags=[{'Key': 'project', 'Value': 'val'}]
            )

        stubber.assert_no_pending_responses()
Beispiel #34
0
 def test_multipart_download_with_multiple_parts_and_extra_args(self):
     client = Session().create_client('s3')
     stubber = Stubber(client)
     response_body = b'foobarbaz'
     response = {'Body': six.BytesIO(response_body)}
     expected_params = {
         'Range': mock.ANY, 'Bucket': mock.ANY, 'Key': mock.ANY,
         'RequestPayer': 'requester'}
     stubber.add_response('get_object', response, expected_params)
     stubber.activate()
     downloader = MultipartDownloader(
         client, TransferConfig(), InMemoryOSLayer({}), SequentialExecutor)
     downloader.download_file(
         'bucket', 'key', 'filename', len(response_body),
         {'RequestPayer': 'requester'})
     stubber.assert_no_pending_responses()
Beispiel #35
0
    def test_table_scan_can_be_stubbed_with_expressions(self):
        table = self.resource.Table('mytable')
        filter_expr = Attr('myattr').eq('foo') & (
                Attr('myattr2').lte('buzz') | Attr('myattr2').gte('fizz')
        )

        stubber = Stubber(table.meta.client)
        stubber.add_response('scan', dict(Items=list()), expected_params=dict(
                TableName='mytable',
                FilterExpression=filter_expr
        ))

        with stubber:
            response = table.scan(FilterExpression=filter_expr)

        self.assertEqual(list(), response['Items'])
        stubber.assert_no_pending_responses()
Beispiel #36
0
    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()
Beispiel #37
0
class TestMturk(BaseSessionTest):
    def setUp(self):
        super(TestMturk, self).setUp()
        self.region = 'us-west-2'
        self.client = self.session.create_client(
            'mturk', self.region)
        self.stubber = Stubber(self.client)
        self.stubber.activate()

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

    def test_list_hits_aliased(self):
        self.stubber.add_response('list_hits_for_qualification_type', {})
        self.stubber.add_response('list_hits_for_qualification_type', {})

        params = {'QualificationTypeId': 'foo'}

        self.client.list_hi_ts_for_qualification_type(**params)
        self.client.list_hits_for_qualification_type(**params)

        self.stubber.assert_no_pending_responses()
Beispiel #38
0
class TestStubber(unittest.TestCase):
    def setUp(self):
        session = botocore.session.get_session()
        config = botocore.config.Config(
            signature_version=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 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(UnStubbedResponseError,
                                     "Unexpected API Call"):
            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(UnStubbedResponseError):
            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.")

    def test_no_stub_for_presign_url(self):
        try:
            with self.stubber:
                url = self.client.generate_presigned_url(
                    ClientMethod='get_object',
                    Params={
                        'Bucket': 'mybucket',
                        'Key': 'mykey'
                    }
                )
                self.assertEqual(
                    url, 'https://s3.amazonaws.com/mybucket/mykey')
        except StubResponseError:
            self.fail(
                'Stubbed responses should not be required for generating '
                'presigned requests'
            )

    def test_can_stub_with_presign_url_mixed_in(self):
        desired_response = {}
        expected_params = {
            'Bucket': 'mybucket',
            'Prefix': 'myprefix',
        }
        self.stubber.add_response(
            'list_objects', desired_response, expected_params)
        with self.stubber:
            url = self.client.generate_presigned_url(
                ClientMethod='get_object',
                Params={
                    'Bucket': 'myotherbucket',
                    'Key': 'myotherkey'
                }
            )
            self.assertEqual(
                    url, 'https://s3.amazonaws.com/myotherbucket/myotherkey')
            actual_response = self.client.list_objects(**expected_params)
            self.assertEqual(desired_response, actual_response)
        self.stubber.assert_no_pending_responses()
Beispiel #39
0
class TestStubber(unittest.TestCase):
    def setUp(self):
        session = botocore.session.get_session()
        config = botocore.config.Config(signature_version=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_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_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.")
Beispiel #40
0
class TestStubber(unittest.TestCase):
    def setUp(self):
        session = botocore.session.get_session()
        config = botocore.client.Config(signature_version=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_activated_stubber_errors_with_no_registered_stubs(self):
        self.stubber.activate()
        with self.assertRaises(StubResponseError):
            self.client.list_objects(Bucket='foo')

    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_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.assertRaises(StubResponseError):
            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')
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(
            '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_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_response_errors_with_no_stubs(self):
        self.stubber.activate()
        with self.assertRaises(StubResponseError):
            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()
    def test_bundle_ran_and_output_same(self):
        goal = self.create_goal('apply')

        # The local bundle has a payload that will *always* do something
        # It's an execute - there is no way for fuselage to skip running it
        # So we expect the lambda
        self.test_dir = tempfile.mkdtemp()
        self.addCleanup(shutil.rmtree, self.test_dir)

        bundle = self.workspace.add_fuselage_bundle(
            target=self.workspace.add_local()
        )
        lambda_zip = os.path.join(os.path.dirname(__file__), 'assets/lambda.zip')
        bundle.add_file(
            name=os.path.join(self.test_dir, 'lambda.zip'),
            source=lambda_zip,
        )
        fn = self.aws.add_lambda_function(
            name='myfunction',
            role=self.aws.get_role(name='myrole'),
            handler='mymodule.myfunction',
            code=bundle.add_output(name=lambda_zip),
        )

        role_service = goal.get_service(fn.role, 'describe')
        fn_service = goal.get_service(fn, 'apply')

        role_stubber = Stubber(role_service.client)
        role_stubber.add_response(
            'list_roles',
            service_response={
                'Roles': [{
                    'RoleName': 'myrole',
                    'Path': '/iam/myrole',
                    'RoleId': '1234567890123456',
                    'Arn': '12345678901234567890',
                    'CreateDate': datetime.datetime.now(),
                }],
            },
            expected_params={},
        )

        fn_stubber = Stubber(fn_service.client)
        fn_stubber.add_response(
            'get_function_configuration',
            service_response={
                'FunctionName': 'myfunction',
                'CodeSha256': 'LjWn8H6iob8nXeoTeRwWTGctKEUJb6L6epmiwUQVCr0=',
                'Handler': 'mymodule.myfunction',
                'Role': '12345678901234567890',
            },
            expected_params={
                'FunctionName': 'myfunction',
            },
        )
        fn_stubber.add_response(
            'list_versions_by_function',
            service_response={
                'Versions': [],
            },
            expected_params={
                'FunctionName': 'myfunction',
            },
        )
        fn_stubber.add_response(
            'list_aliases',
            service_response={
                'Aliases': [],
            },
            expected_params={
                'FunctionName': 'myfunction',
            },
        )

        with role_stubber:
            with fn_stubber:
                goal.execute()
                self.assertEqual(len(goal.get_changes(bundle)), 1)
                self.assertEqual(len(goal.get_changes(fn)), 1)
                fn_stubber.assert_no_pending_responses()