Beispiel #1
0
    def describe_table(self, context, table_name):
        table_info = self._table_info_repo.get(
            context, table_name, ['status', 'last_update_date_time'])

        if timeutils.is_older_than(table_info.last_update_date_time,
                                   self._schema_operation_timeout):
            if table_info.status == models.TableMeta.TABLE_STATUS_CREATING:
                table_info.status = models.TableMeta.TABLE_STATUS_CREATE_FAILED
                self._table_info_repo.update(context, table_info, ['status'])
                LOG.debug("Table '{}' creation timed out."
                          " Setting status to {}".format(
                              table_info.name,
                              models.TableMeta.TABLE_STATUS_CREATE_FAILED))

            if table_info.status == models.TableMeta.TABLE_STATUS_DELETING:
                table_info.status = models.TableMeta.TABLE_STATUS_DELETE_FAILED
                self._table_info_repo.update(context, table_info, ['status'])
                LOG.debug("Table '{}' deletion timed out."
                          " Setting status to {}".format(
                              table_info.name,
                              models.TableMeta.TABLE_STATUS_DELETE_FAILED))

        return models.TableMeta(table_info.id, table_info.schema,
                                table_info.status,
                                table_info.creation_date_time)
Beispiel #2
0
    def test_describe_table(self):

        self.storage_mocker.StubOutWithMock(storage, 'describe_table')

        storage.describe_table(IgnoreArg(), 'test_table').AndReturn(
            models.TableMeta(
                models.TableSchema(
                    {
                        'city1': models.ATTRIBUTE_TYPE_STRING,
                        'id': models.ATTRIBUTE_TYPE_STRING,
                        'name': models.ATTRIBUTE_TYPE_STRING
                    }, ['id', 'name'],
                    {'index_name': models.IndexDefinition('city1')}),
                models.TableMeta.TABLE_STATUS_ACTIVE))

        self.storage_mocker.ReplayAll()

        table = Table('test_table', connection=self.DYNAMODB_CON)

        table_description = table.describe()

        self.storage_mocker.VerifyAll()

        self.assertEquals('test_table',
                          table_description['Table']['TableName'])
        self.assertItemsEqual([{
            "AttributeName": "city1",
            "AttributeType": "S"
        }, {
            "AttributeName": "id",
            "AttributeType": "S"
        }, {
            "AttributeName": "name",
            "AttributeType": "S"
        }], table_description['Table']['AttributeDefinitions'])
Beispiel #3
0
    def test_create_table_no_range(self):
        self.storage_mocker.StubOutWithMock(storage, 'create_table')
        storage.create_table(IgnoreArg(), IgnoreArg(), IgnoreArg()).AndReturn(
            models.TableMeta(
                models.TableSchema(
                    {
                        'hash': models.ATTRIBUTE_TYPE_NUMBER,
                        'indexed_field': models.ATTRIBUTE_TYPE_STRING
                    }, ['hash'],
                    {"index_name": models.IndexDefinition('indexed_field')}),
                models.TableMeta.TABLE_STATUS_ACTIVE))
        self.storage_mocker.ReplayAll()

        Table.create("test",
                     schema=[
                         fields.HashKey('hash', data_type=schema_types.NUMBER),
                     ],
                     throughput={
                         'read': 20,
                         'write': 10,
                     },
                     indexes=[
                         fields.KeysOnlyIndex(
                             'index_name',
                             parts=[
                                 fields.RangeKey('indexed_field',
                                                 data_type=schema_types.STRING)
                             ])
                     ],
                     connection=self.DYNAMODB_CON)

        self.storage_mocker.VerifyAll()
Beispiel #4
0
    def test_update_item(self):
        self.storage_mocker.StubOutWithMock(storage, 'get_item')

        hash_key = "4.5621201231232132132132132132132142354E126"
        range_key = "range"

        storage.get_item(
            mox.IgnoreArg(), mox.IgnoreArg(), mox.IgnoreArg(),
            select_type=mox.IgnoreArg(),
            consistent=mox.IgnoreArg()
        ).AndReturn(
            models.SelectResult(
                items=[
                    {
                        "hash_key": models.AttributeValue('N', hash_key),
                        "range_key": models.AttributeValue('S', range_key),
                        "attr_value": models.AttributeValue('S', 'val')
                    }
                ]
            )
        )

        self.storage_mocker.StubOutWithMock(storage, 'describe_table')

        storage.describe_table(mox.IgnoreArg(), 'test_table').AndReturn(
            models.TableMeta(
                '00000000-0000-0000-0000-000000000000',
                models.TableSchema(
                    {
                        'hash_key': models.AttributeType('N'),
                        'range_key': models.AttributeType('S')
                    },
                    ['hash_key', 'range_key'],
                ),
                models.TableMeta.TABLE_STATUS_ACTIVE,
                None
            )
        )

        self.storage_mocker.StubOutWithMock(storage, 'update_item')
        storage.update_item(
            mox.IgnoreArg(), mox.IgnoreArg(),
            key_attribute_map=mox.IgnoreArg(),
            attribute_action_map=mox.IgnoreArg(),
            expected_condition_map=mox.IgnoreArg()).AndReturn((True, None))

        self.storage_mocker.ReplayAll()

        table = ddb_table.Table(
            'test_table',
            connection=self.DYNAMODB_CON
        )

        item = table.get_item(consistent=False, hash_key=1, range_key="range")

        item['attr_value'] = 'updated'

        item.partial_save()

        self.storage_mocker.VerifyAll()
Beispiel #5
0
    def test_delete_table(self):
        self.storage_mocker.StubOutWithMock(storage, 'delete_table')
        self.storage_mocker.StubOutWithMock(storage, 'describe_table')
        storage.delete_table(mox.IgnoreArg(), 'test_table')

        storage.describe_table(mox.IgnoreArg(), 'test_table').AndReturn(
            models.TableMeta(
                '00000000-0000-0000-0000-000000000000',
                models.TableSchema(
                    {
                        'city1': models.AttributeType('S'),
                        'id': models.AttributeType('S'),
                        'name': models.AttributeType('S')
                    },
                    ['id', 'name'],
                    {'index_name': models.IndexDefinition('id', 'city1')}
                ),
                models.TableMeta.TABLE_STATUS_ACTIVE,
                None
            )
        )

        self.storage_mocker.ReplayAll()

        table = ddb_table.Table(
            'test_table',
            connection=self.DYNAMODB_CON
        )

        self.assertTrue(table.delete())

        self.storage_mocker.VerifyAll()
Beispiel #6
0
    def delete_table(self, context, table_name):
        try:
            table_info = self._table_info_repo.get(context, table_name,
                                                   ['status'])
        except exception.TableNotExistsException:
            raise

        if table_info.status == models.TableMeta.TABLE_STATUS_DELETING:
            # table is already being deleted, just return immediately
            return models.TableMeta(table_info.id, table_info.schema,
                                    table_info.status,
                                    table_info.creation_date_time)
        elif table_info.in_use:
            raise exception.ResourceInUseException()

        table_info.status = models.TableMeta.TABLE_STATUS_DELETING

        self._table_info_repo.update(context, table_info, ["status"])

        if not table_info.internal_name:
            # if table internal name is missing, table is not actually created
            # just remove the table_info entry for the table and
            # send notification
            msg = ("Table '{}' with tenant id '{}', id '{}' does not have "
                   "valid internal name. Unable or no need to delete.").format(
                       table_info.name, context.tenant, table_info.id)
            LOG.info(msg)
            self._table_info_repo.delete(context, table_info.name)

            self._notifier.info(
                context, notifier.EVENT_TYPE_TABLE_DELETE,
                dict(table_name=table_name, message=msg, value=time.time()))
        else:
            self._do_delete_table(context, table_info)

        return models.TableMeta(table_info.id, table_info.schema,
                                table_info.status,
                                table_info.creation_date_time)
Beispiel #7
0
    def test_update_item(self):
        self.storage_mocker.StubOutWithMock(storage, 'select_item')

        hash_key = "4.5621201231232132132132132132132142354E126"
        range_key = "range"

        storage.select_item(
            IgnoreArg(),
            IgnoreArg(),
            IgnoreArg(),
            select_type=IgnoreArg(),
            limit=IgnoreArg(),
            consistent=IgnoreArg()).AndReturn(
                models.SelectResult(
                    items=[{
                        "hash_key": models.AttributeValue.number(hash_key),
                        "range_key": models.AttributeValue.str(range_key),
                        "attr_value": models.AttributeValue.str('val')
                    }]))

        self.storage_mocker.StubOutWithMock(storage, 'describe_table')

        storage.describe_table(IgnoreArg(), 'test_table').AndReturn(
            models.TableMeta(
                models.TableSchema(
                    {
                        'hash_key': models.ATTRIBUTE_TYPE_NUMBER,
                        'range_key': models.ATTRIBUTE_TYPE_STRING
                    },
                    ['hash_key', 'range_key'],
                ), models.TableMeta.TABLE_STATUS_ACTIVE))

        self.storage_mocker.StubOutWithMock(storage, 'update_item')
        storage.update_item(IgnoreArg(),
                            IgnoreArg(),
                            key_attribute_map=IgnoreArg(),
                            attribute_action_map=IgnoreArg(),
                            expected_condition_map=IgnoreArg()).AndReturn(True)

        self.storage_mocker.ReplayAll()

        table = Table('test_table', connection=self.DYNAMODB_CON)

        item = table.get_item(consistent=False, hash_key=1, range_key="range")

        item['attr_value'] = 'updated'

        item.partial_save()

        self.storage_mocker.VerifyAll()
Beispiel #8
0
    def test_create_table(self):
        self.storage_mocker.StubOutWithMock(storage, 'create_table')
        storage.create_table(
            mox.IgnoreArg(), mox.IgnoreArg(), mox.IgnoreArg()
        ).AndReturn(
            models.TableMeta(
                '00000000-0000-0000-0000-000000000000',
                models.TableSchema(
                    {
                        'hash': models.AttributeType('N'),
                        'range': models.AttributeType('S'),
                        'indexed_field': models.AttributeType('S')
                    },
                    ['hash', 'range'],
                    {
                        "index_name": models.IndexDefinition('hash',
                                                             'indexed_field')
                    }
                ),
                models.TableMeta.TABLE_STATUS_ACTIVE,
                None
            )
        )
        self.storage_mocker.ReplayAll()

        ddb_table.Table.create(
            "test",
            schema=[
                fields.HashKey('hash', data_type=schema_types.NUMBER),
                fields.RangeKey('range', data_type=schema_types.STRING)
            ],
            throughput={
                'read': 20,
                'write': 10,
            },
            indexes=[
                fields.KeysOnlyIndex(
                    'index_name',
                    parts=[
                        fields.HashKey('hash', data_type=schema_types.NUMBER),
                        fields.RangeKey('indexed_field',
                                        data_type=schema_types.STRING)
                    ]
                )
            ],
            connection=self.DYNAMODB_CON
        )

        self.storage_mocker.VerifyAll()
Beispiel #9
0
    def create_table(self, context, table_name, table_schema):
        table_id = self._get_table_id(table_name)
        table_info = table_info_repo.TableInfo(
            table_name, table_id, table_schema,
            models.TableMeta.TABLE_STATUS_CREATING)

        try:
            self._table_info_repo.save(context, table_info)
        except exception.TableAlreadyExistsException:
            raise

        self._do_create_table(context, table_info)

        return models.TableMeta(table_info.id, table_info.schema,
                                table_info.status,
                                table_info.creation_date_time)
Beispiel #10
0
    def test_delete_table(self):
        self.storage_mocker.StubOutWithMock(storage, 'delete_table')
        self.storage_mocker.StubOutWithMock(storage, 'describe_table')
        storage.delete_table(IgnoreArg(), 'test_table')

        storage.describe_table(IgnoreArg(), 'test_table').AndReturn(
            models.TableMeta(
                models.TableSchema(
                    {
                        'city1': models.ATTRIBUTE_TYPE_STRING,
                        'id': models.ATTRIBUTE_TYPE_STRING,
                        'name': models.ATTRIBUTE_TYPE_STRING
                    }, ['id', 'name'],
                    {'index_name': models.IndexDefinition('city1')}),
                models.TableMeta.TABLE_STATUS_ACTIVE))

        self.storage_mocker.ReplayAll()

        table = Table('test_table', connection=self.DYNAMODB_CON)

        self.assertTrue(table.delete())

        self.storage_mocker.VerifyAll()
Beispiel #11
0
    def test_describe_table(self, mock_describe_table):

        attr_map = {
            'ForumName': models.AttributeType('S'),
            'Subject': models.AttributeType('S'),
            'LastPostDateTime': models.AttributeType('S')
        }

        key_attrs = ['ForumName', 'Subject']

        index_map = {
            'LastPostIndex':
            models.IndexDefinition('ForumName', 'LastPostDateTime')
        }

        table_meta = models.TableMeta(
            '00000000-0000-0000-0000-000000000000',
            models.TableSchema(attr_map, key_attrs, index_map),
            models.TableMeta.TABLE_STATUS_ACTIVE, 123)

        mock_describe_table.return_value = table_meta

        headers = {
            'Content-Type': 'application/json',
            'Accept': 'application/json'
        }

        conn = httplib.HTTPConnection('localhost:8080')
        url = '/v1/data/default_tenant/tables/Thread'

        table_url = ('http://localhost:8080/v1/data/default_tenant'
                     '/tables/Thread')
        expected_response = {
            'table': {
                'attribute_definitions': [{
                    'attribute_name': 'Subject',
                    'attribute_type': 'S'
                }, {
                    'attribute_name': 'LastPostDateTime',
                    'attribute_type': 'S'
                }, {
                    'attribute_name': 'ForumName',
                    'attribute_type': 'S'
                }],
                'creation_date_time':
                123,
                'item_count':
                0,
                'key_schema': [{
                    'attribute_name': 'ForumName',
                    'key_type': 'HASH'
                }, {
                    'attribute_name': 'Subject',
                    'key_type': 'RANGE'
                }],
                'local_secondary_indexes': [{
                    'index_name':
                    'LastPostIndex',
                    'index_size_bytes':
                    0,
                    'item_count':
                    0,
                    'key_schema': [{
                        'attribute_name': 'ForumName',
                        'key_type': 'HASH'
                    }, {
                        'attribute_name': 'LastPostDateTime',
                        'key_type': 'RANGE'
                    }],
                    'projection': {
                        'projection_type': 'ALL'
                    }
                }],
                'table_id':
                '00000000-0000-0000-0000-000000000000',
                'table_name':
                'Thread',
                'table_size_bytes':
                0,
                'table_status':
                'ACTIVE',
                'links': [{
                    'href': table_url,
                    'rel': 'self'
                }, {
                    'href': table_url,
                    'rel': 'bookmark'
                }]
            }
        }

        conn.request("GET", url, headers=headers)

        response = conn.getresponse()

        self.assertTrue(mock_describe_table.called)

        json_response = response.read()
        response_payload = json.loads(json_response)

        self.assertEqual(expected_response, response_payload)
Beispiel #12
0
    def test_create_table(self, mock_create_table):
        mock_create_table.return_value = models.TableMeta(
            '00000000-0000-0000-0000-000000000000',
            models.TableSchema(attribute_type_map={
                "ForumName": models.AttributeType('S'),
                "Subject": models.AttributeType('S'),
                "LastPostDateTime": models.AttributeType('S')
            },
                               key_attributes=["ForumName", "Subject"],
                               index_def_map={
                                   "LastPostIndex":
                                   models.IndexDefinition(
                                       "ForumName", "LastPostDateTime")
                               }), models.TableMeta.TABLE_STATUS_ACTIVE, 123)

        conn = httplib.HTTPConnection('localhost:8080')
        body = """
            {
                "attribute_definitions": [
                    {
                        "attribute_name": "ForumName",
                        "attribute_type": "S"
                    },
                    {
                        "attribute_name": "Subject",
                        "attribute_type": "S"
                    },
                    {
                        "attribute_name": "LastPostDateTime",
                        "attribute_type": "S"
                    }
                ],
                "table_name": "Thread",
                "key_schema": [
                    {
                        "attribute_name": "ForumName",
                        "key_type": "HASH"
                    },
                    {
                        "attribute_name": "Subject",
                        "key_type": "RANGE"
                    }
                ],
                "local_secondary_indexes": [
                    {
                        "index_name": "LastPostIndex",
                        "key_schema": [
                            {
                                "attribute_name": "ForumName",
                                "key_type": "HASH"
                            },
                            {
                                "attribute_name": "LastPostDateTime",
                                "key_type": "RANGE"
                            }
                        ],
                        "projection": {
                            "projection_type": "KEYS_ONLY"
                        }
                    }
                ]
            }
        """

        expected_response = {
            'table_description': {
                'attribute_definitions': [{
                    'attribute_name': 'Subject',
                    'attribute_type': 'S'
                }, {
                    'attribute_name': 'LastPostDateTime',
                    'attribute_type': 'S'
                }, {
                    'attribute_name': 'ForumName',
                    'attribute_type': 'S'
                }],
                'creation_date_time':
                123,
                'item_count':
                0,
                'key_schema': [{
                    'attribute_name': 'ForumName',
                    'key_type': 'HASH'
                }, {
                    'attribute_name': 'Subject',
                    'key_type': 'RANGE'
                }],
                'local_secondary_indexes': [{
                    'index_name':
                    'LastPostIndex',
                    'index_size_bytes':
                    0,
                    'item_count':
                    0,
                    'key_schema': [{
                        'attribute_name': 'ForumName',
                        'key_type': 'HASH'
                    }, {
                        'attribute_name': 'LastPostDateTime',
                        'key_type': 'RANGE'
                    }],
                    'projection': {
                        'projection_type': 'ALL'
                    }
                }],
                'table_id':
                '00000000-0000-0000-0000-000000000000',
                'table_name':
                'Thread',
                'table_size_bytes':
                0,
                'table_status':
                'ACTIVE',
                'links': [{
                    'href': self.table_url,
                    'rel': 'self'
                }, {
                    'href': self.table_url,
                    'rel': 'bookmark'
                }]
            }
        }

        conn.request("POST", self.url, headers=self.headers, body=body)

        response = conn.getresponse()

        self.assertTrue(mock_create_table.called)

        json_response = response.read()
        response_payload = json.loads(json_response)

        self.assertEqual(expected_response, response_payload)
Beispiel #13
0
    def test_create_table_duplicate(self):
        self.storage_mocker.StubOutWithMock(storage, 'create_table')
        storage.create_table(IgnoreArg(), IgnoreArg(), IgnoreArg()).AndReturn(
            models.TableMeta(
                models.TableSchema(
                    {
                        'hash': models.ATTRIBUTE_TYPE_NUMBER,
                        'range': models.ATTRIBUTE_TYPE_STRING,
                        'indexed_field': models.ATTRIBUTE_TYPE_STRING
                    }, ['hash', 'range'],
                    {"index_name": models.IndexDefinition('indexed_field')}),
                models.TableMeta.TABLE_STATUS_ACTIVE))
        storage.create_table(IgnoreArg(), IgnoreArg(),
                             IgnoreArg()).AndRaise(TableAlreadyExistsException)
        self.storage_mocker.ReplayAll()

        Table.create("test",
                     schema=[
                         fields.HashKey('hash', data_type=schema_types.NUMBER),
                         fields.RangeKey('range',
                                         data_type=schema_types.STRING)
                     ],
                     throughput={
                         'read': 20,
                         'write': 10,
                     },
                     indexes=[
                         fields.KeysOnlyIndex(
                             'index_name',
                             parts=[
                                 fields.RangeKey('indexed_field',
                                                 data_type=schema_types.STRING)
                             ])
                     ],
                     connection=self.DYNAMODB_CON)

        try:
            Table.create("test",
                         schema=[
                             fields.HashKey('hash',
                                            data_type=schema_types.NUMBER),
                             fields.RangeKey('range',
                                             data_type=schema_types.STRING)
                         ],
                         throughput={
                             'read': 20,
                             'write': 10,
                         },
                         indexes=[
                             fields.KeysOnlyIndex(
                                 'index_name',
                                 parts=[
                                     fields.RangeKey(
                                         'indexed_field',
                                         data_type=schema_types.STRING)
                                 ])
                         ],
                         connection=self.DYNAMODB_CON)

            self.fail()
        except JSONResponseError as e:
            self.assertEqual('ResourceInUseException', e.error_code)
            self.storage_mocker.VerifyAll()
        except Exception as e:
            self.fail()
Beispiel #14
0
    def test_create_table_no_sec_indexes(self, mock_create_table):
        mock_create_table.return_value = models.TableMeta(
            models.TableSchema(attribute_type_map={
                "ForumName": models.ATTRIBUTE_TYPE_STRING,
                "Subject": models.ATTRIBUTE_TYPE_STRING,
                "LastPostDateTime": models.ATTRIBUTE_TYPE_STRING
            },
                               key_attributes=["ForumName", "Subject"]),
            models.TableMeta.TABLE_STATUS_ACTIVE)

        conn = httplib.HTTPConnection('localhost:8080')
        body = """
            {
                "attribute_definitions": [
                    {
                        "attribute_name": "ForumName",
                        "attribute_type": "S"
                    },
                    {
                        "attribute_name": "Subject",
                        "attribute_type": "S"
                    },
                    {
                        "attribute_name": "LastPostDateTime",
                        "attribute_type": "S"
                    }
                ],
                "table_name": "Thread",
                "key_schema": [
                    {
                        "attribute_name": "ForumName",
                        "key_type": "HASH"
                    },
                    {
                        "attribute_name": "Subject",
                        "key_type": "RANGE"
                    }
                ]
            }
        """

        expected_response = {
            'table_description': {
                'attribute_definitions': [{
                    'attribute_name': 'Subject',
                    'attribute_type': 'S'
                }, {
                    'attribute_name': 'LastPostDateTime',
                    'attribute_type': 'S'
                }, {
                    'attribute_name': 'ForumName',
                    'attribute_type': 'S'
                }],
                'creation_date_time':
                0,
                'item_count':
                0,
                'key_schema': [{
                    'attribute_name': 'ForumName',
                    'key_type': 'HASH'
                }, {
                    'attribute_name': 'Subject',
                    'key_type': 'RANGE'
                }],
                'table_name':
                'Thread',
                'table_size_bytes':
                0,
                'table_status':
                'ACTIVE',
                'links': [{
                    'href': self.table_url,
                    'rel': 'self'
                }, {
                    'href': self.table_url,
                    'rel': 'bookmark'
                }]
            }
        }

        conn.request("POST", self.url, headers=self.headers, body=body)

        response = conn.getresponse()

        self.assertTrue(mock_create_table.called)

        json_response = response.read()
        response_payload = json.loads(json_response)

        self.assertEqual(expected_response, response_payload)
Beispiel #15
0
    def test_create_table_duplicate(self):
        self.storage_mocker.StubOutWithMock(storage, 'create_table')
        storage.create_table(
            mox.IgnoreArg(), mox.IgnoreArg(), mox.IgnoreArg()
        ).AndReturn(
            models.TableMeta(
                '00000000-0000-0000-0000-000000000000',
                models.TableSchema(
                    {
                        'hash': models.AttributeType('N'),
                        'range': models.AttributeType('S'),
                        'indexed_field': models.AttributeType('S')
                    },
                    ['hash', 'range'],
                    {
                        "index_name": models.IndexDefinition('hash',
                                                             'indexed_field')
                    }
                ),
                models.TableMeta.TABLE_STATUS_ACTIVE,
                None
            )
        )
        storage.create_table(
            mox.IgnoreArg(), mox.IgnoreArg(), mox.IgnoreArg()
        ).AndRaise(exception.TableAlreadyExistsException)
        self.storage_mocker.ReplayAll()

        ddb_table.Table.create(
            "test",
            schema=[
                fields.HashKey('hash', data_type=schema_types.NUMBER),
                fields.RangeKey('range', data_type=schema_types.STRING)
            ],
            throughput={
                'read': 20,
                'write': 10,
            },
            indexes=[
                fields.KeysOnlyIndex(
                    'index_name',
                    parts=[
                        fields.HashKey('hash', data_type=schema_types.NUMBER),
                        fields.RangeKey('indexed_field',
                                        data_type=schema_types.STRING)
                    ]
                )
            ],
            connection=self.DYNAMODB_CON
        )

        try:
            ddb_table.Table.create(
                "test",
                schema=[
                    fields.HashKey('hash', data_type=schema_types.NUMBER),
                    fields.RangeKey('range', data_type=schema_types.STRING)
                ],
                throughput={
                    'read': 20,
                    'write': 10,
                },
                indexes=[
                    fields.KeysOnlyIndex(
                        'index_name',
                        parts=[
                            fields.HashKey('hash',
                                           data_type=schema_types.NUMBER),
                            fields.RangeKey('indexed_field',
                                            data_type=schema_types.STRING)
                        ]
                    )
                ],
                connection=self.DYNAMODB_CON
            )

            self.fail()
        except boto_exc.JSONResponseError as e:
            self.assertEqual('ResourceInUseException', e.error_code)
            self.assertEqual('Table already exists: test', e.body['message'])
            self.storage_mocker.VerifyAll()
        except Exception as e:
            self.fail()