import boto import sure # noqa from freezegun import freeze_time from moto import mock_dynamodb2 from boto.dynamodb2.fields import HashKey from boto.dynamodb2.fields import RangeKey from boto.dynamodb2.table import Table from boto.dynamodb2.table import Item from boto.dynamodb.exceptions import DynamoDBKeyNotFoundError from boto.dynamodb2.exceptions import ValidationException from boto.dynamodb2.exceptions import ConditionalCheckFailedException from boto.exception import JSONResponseError def create_table(): table = Table.create('messages', schema=[ HashKey('forum_name'), RangeKey('subject'), ], throughput={ 'read': 10, 'write': 10, }) return table def iterate_results(res): for i in res: print i @freeze_time("2012-01-14") @mock_dynamodb2 def test_create_table(): table = create_table() expected = { 'Table': { 'AttributeDefinitions': [ {'AttributeName': 'forum_name', 'AttributeType': 'S'}, {'AttributeName': 'subject', 'AttributeType': 'S'} ], 'ProvisionedThroughput': { 'NumberOfDecreasesToday': 0, 'WriteCapacityUnits': 10, 'ReadCapacityUnits': 10 }, 'TableSizeBytes': 0, 'TableName': 'messages', 'TableStatus': 'ACTIVE', 'KeySchema': [ {'KeyType': 'HASH', 'AttributeName': 'forum_name'}, {'KeyType': 'RANGE', 'AttributeName': 'subject'} ], 'ItemCount': 0, 'CreationDateTime': 1326499200.0 } } table.describe().should.equal(expected) @mock_dynamodb2 def test_delete_table(): conn = boto.dynamodb2.layer1.DynamoDBConnection() table = create_table() conn.list_tables()["TableNames"].should.have.length_of(1) table.delete() conn.list_tables()["TableNames"].should.have.length_of(0) conn.delete_table.when.called_with('messages').should.throw(JSONResponseError) @mock_dynamodb2 def test_update_table_throughput(): table = create_table() table.throughput["read"].should.equal(10) table.throughput["write"].should.equal(10) table.update(throughput={ 'read': 5, 'write': 15, }) table.throughput["read"].should.equal(5) table.throughput["write"].should.equal(15) table.update(throughput={ 'read': 5, 'write': 6, }) table.describe() table.throughput["read"].should.equal(5) table.throughput["write"].should.equal(6) @mock_dynamodb2 def test_item_add_and_describe_and_update(): table = create_table() ok = table.put_item(data={ 'forum_name': 'LOLCat Forum', 'subject': 'Check this out!', 'Body': 'http://url_to_lolcat.gif', 'SentBy': 'User A', 'ReceivedTime': '12/9/2011 11:36:03 PM', }) ok.should.equal(True) table.get_item(forum_name="LOLCat Forum",subject='Check this out!').should_not.be.none returned_item = table.get_item( forum_name='LOLCat Forum', subject='Check this out!' ) dict(returned_item).should.equal({ 'forum_name': 'LOLCat Forum', 'subject': 'Check this out!', 'Body': 'http://url_to_lolcat.gif', 'SentBy': 'User A', 'ReceivedTime': '12/9/2011 11:36:03 PM', }) returned_item['SentBy'] = 'User B' returned_item.save(overwrite=True) returned_item = table.get_item( forum_name='LOLCat Forum', subject='Check this out!' ) dict(returned_item).should.equal({ 'forum_name': 'LOLCat Forum', 'subject': 'Check this out!', 'Body': 'http://url_to_lolcat.gif', 'SentBy': 'User B', 'ReceivedTime': '12/9/2011 11:36:03 PM', }) @mock_dynamodb2 def test_item_put_without_table(): table = Table('undeclared-table') item_data = { 'forum_name': 'LOLCat Forum', 'Body': 'http://url_to_lolcat.gif', 'SentBy': 'User A', 'ReceivedTime': '12/9/2011 11:36:03 PM', } item =Item(table,item_data) item.save.when.called_with().should.throw(JSONResponseError) @mock_dynamodb2 def test_get_missing_item(): table = create_table() table.get_item.when.called_with( hash_key='tester', range_key='other', ).should.throw(ValidationException) @mock_dynamodb2 def test_get_item_with_undeclared_table(): table = Table('undeclared-table') table.get_item.when.called_with(test_hash=3241526475).should.throw(JSONResponseError) @mock_dynamodb2 def test_get_item_without_range_key(): table = Table.create('messages', schema=[ HashKey('test_hash'), RangeKey('test_range'), ], throughput={ 'read': 10, 'write': 10, }) hash_key = 3241526475 range_key = 1234567890987 table.put_item( data = {'test_hash':hash_key, 'test_range':range_key}) table.get_item.when.called_with(test_hash=hash_key).should.throw(ValidationException) @mock_dynamodb2 def test_delete_item(): table = create_table() item_data = { 'forum_name': 'LOLCat Forum', 'Body': 'http://url_to_lolcat.gif', 'SentBy': 'User A', 'ReceivedTime': '12/9/2011 11:36:03 PM', } item =Item(table,item_data) item['subject'] = 'Check this out!' item.save() table.count().should.equal(1) response = item.delete() response.should.equal(True) table.count().should.equal(0) item.delete.when.called_with().should.throw(ConditionalCheckFailedException) @mock_dynamodb2 def test_delete_item_with_undeclared_table(): conn = boto.connect_dynamodb() table = Table("undeclared-table") item_data = { 'forum_name': 'LOLCat Forum', 'Body': 'http://url_to_lolcat.gif', 'SentBy': 'User A', 'ReceivedTime': '12/9/2011 11:36:03 PM', } item =Item(table,item_data) item.delete.when.called_with().should.throw(JSONResponseError) @mock_dynamodb2 def test_query(): table = create_table() item_data = { 'forum_name': 'LOLCat Forum', 'Body': 'http://url_to_lolcat.gif', 'SentBy': 'User A', 'ReceivedTime': '12/9/2011 11:36:03 PM', 'subject': 'Check this out!' } item =Item(table,item_data) item.save(overwrite=True) item['forum_name'] = 'the-key' item['subject'] = '456' item.save(overwrite=True) item['forum_name'] = 'the-key' item['subject'] = '123' item.save(overwrite=True) item['forum_name'] = 'the-key' item['subject'] = '789' item.save(overwrite=True) table.count().should.equal(4) results = table.query(forum_name__eq='the-key', subject__gt='1',consistent=True) sum(1 for _ in results).should.equal(3) results = table.query(forum_name__eq='the-key', subject__gt='234',consistent=True) sum(1 for _ in results).should.equal(2) results = table.query(forum_name__eq='the-key', subject__gt='9999') sum(1 for _ in results).should.equal(0) results = table.query(forum_name__eq='the-key', subject__beginswith='12') sum(1 for _ in results).should.equal(1) results = table.query(forum_name__eq='the-key', subject__beginswith='7') sum(1 for _ in results).should.equal(1) results = table.query(forum_name__eq='the-key', subject__between=['567', '890']) sum(1 for _ in results).should.equal(1) @mock_dynamodb2 def test_query_with_undeclared_table(): table = Table('undeclared') results = table.query( forum_name__eq='Amazon DynamoDB', subject__beginswith='DynamoDB', limit=1 ) iterate_results.when.called_with(results).should.throw(JSONResponseError) @mock_dynamodb2 def test_scan(): table = create_table() item_data = { 'Body': 'http://url_to_lolcat.gif', 'SentBy': 'User A', 'ReceivedTime': '12/9/2011 11:36:03 PM', } item_data['forum_name'] = 'the-key' item_data['subject'] = '456' item = Item(table,item_data) item.save() item['forum_name'] = 'the-key' item['subject'] = '123' item.save() item_data = { 'Body': 'http://url_to_lolcat.gif', 'SentBy': 'User B', 'ReceivedTime': '12/9/2011 11:36:09 PM', 'Ids': set([1, 2, 3]), 'PK': 7, } item_data['forum_name'] = 'the-key' item_data['subject'] = '789' item = Item(table,item_data) item.save() results = table.scan() sum(1 for _ in results).should.equal(3) results = table.scan(SentBy__eq='User B') sum(1 for _ in results).should.equal(1) results = table.scan(Body__beginswith='http') sum(1 for _ in results).should.equal(3) results = table.scan(Ids__null=False) sum(1 for _ in results).should.equal(1) results = table.scan(Ids__null=True) sum(1 for _ in results).should.equal(2) results = table.scan(PK__between=[8, 9]) sum(1 for _ in results).should.equal(0) results = table.scan(PK__between=[5, 8]) sum(1 for _ in results).should.equal(1) @mock_dynamodb2 def test_scan_with_undeclared_table(): conn = boto.dynamodb2.layer1.DynamoDBConnection() conn.scan.when.called_with( table_name='undeclared-table', scan_filter={ "SentBy": { "AttributeValueList": [{ "S": "User B"} ], "ComparisonOperator": "EQ" } }, ).should.throw(JSONResponseError) @mock_dynamodb2 def test_write_batch(): table = create_table() with table.batch_write() as batch: batch.put_item(data={ 'forum_name': 'the-key', 'subject': '123', 'Body': 'http://url_to_lolcat.gif', 'SentBy': 'User A', 'ReceivedTime': '12/9/2011 11:36:03 PM', }) batch.put_item(data={ 'forum_name': 'the-key', 'subject': '789', 'Body': 'http://url_to_lolcat.gif', 'SentBy': 'User B', 'ReceivedTime': '12/9/2011 11:36:03 PM', }) table.count().should.equal(2) with table.batch_write() as batch: batch.delete_item( forum_name='the-key', subject='789' ) table.count().should.equal(1) @mock_dynamodb2 def test_batch_read(): table = create_table() item_data = { 'Body': 'http://url_to_lolcat.gif', 'SentBy': 'User A', 'ReceivedTime': '12/9/2011 11:36:03 PM', } item_data['forum_name'] = 'the-key' item_data['subject'] = '456' item = Item(table,item_data) item.save() item = Item(table,item_data) item_data['forum_name'] = 'the-key' item_data['subject'] = '123' item.save() item_data = { 'Body': 'http://url_to_lolcat.gif', 'SentBy': 'User B', 'ReceivedTime': '12/9/2011 11:36:03 PM', 'Ids': set([1, 2, 3]), 'PK': 7, } item = Item(table,item_data) item_data['forum_name'] = 'another-key' item_data['subject'] = '789' item.save() results = table.batch_get(keys=[ {'forum_name': 'the-key', 'subject': '123'}, {'forum_name': 'another-key', 'subject': '789'}]) # Iterate through so that batch_item gets called count = len([x for x in results]) count.should.equal(2) @mock_dynamodb2 def test_get_key_fields(): table = create_table() kf = table.get_key_fields() kf.should.equal(['forum_name','subject'])