PageRenderTime 29ms CodeModel.GetById 13ms app.highlight 12ms RepoModel.GetById 2ms app.codeStats 0ms

/boto-2.5.2/tests/integration/dynamodb/test_layer1.py

#
Python | 222 lines | 195 code | 3 blank | 24 comment | 0 complexity | 563d6881cc666ced6a2223888857a63a MD5 | raw file
  1# Copyright (c) 2012 Mitch Garnaat http://garnaat.org/
  2# All rights reserved.
  3#
  4# Permission is hereby granted, free of charge, to any person obtaining a
  5# copy of this software and associated documentation files (the
  6# "Software"), to deal in the Software without restriction, including
  7# without limitation the rights to use, copy, modify, merge, publish, dis-
  8# tribute, sublicense, and/or sell copies of the Software, and to permit
  9# persons to whom the Software is furnished to do so, subject to the fol-
 10# lowing conditions:
 11#
 12# The above copyright notice and this permission notice shall be included
 13# in all copies or substantial portions of the Software.
 14#
 15# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
 16# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL-
 17# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
 18# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 
 19# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 20# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
 21# IN THE SOFTWARE.
 22
 23"""
 24Tests for Layer1 of DynamoDB
 25"""
 26
 27import unittest
 28import time
 29from boto.dynamodb.exceptions import DynamoDBKeyNotFoundError
 30from boto.dynamodb.exceptions import DynamoDBConditionalCheckFailedError
 31from boto.dynamodb.exceptions import DynamoDBValidationError
 32from boto.dynamodb.layer1 import Layer1
 33from boto.sts.credentials import Credentials
 34
 35json_doc = """{"access_key": "ASIAIV7R2NUUJ6SB7GKQ", "secret_key": "eIfijGxJlejHDSQiaGr6b7U805U0GKWmllCTt2ZM", "request_id": "28c17897-4555-11e1-8bb1-2529f165f2f0", "expiration": "2012-01-23T00:59:45.617Z", "session_token": "AQoDYXdzEPn//////////wEasAGDXeGY8bx36NLRSA1v3dy2x00k3FNA2KVsMEXkQuKY08gPTtYs2tefZTBsTjgjC+O6j8ieoB1on2bPyCq872+Yq3cipls8jna+PNSEcsXtC8CJBKai/FfYNg1XUHam6EUCtRiUHvqztOVgaGqUUS1UbrBKB7kKSXzgKrJ9AT0bvqi4hZS0ayaU8969f2HIbN9psXhRBKpJyB9FUPuVYpYYZsz9NY3y2kGtK+dgfrKvxyDxxfL4BA=="}"""
 36
 37class DynamoDBLayer1Test (unittest.TestCase):
 38    dynamodb = True
 39
 40    def test_layer1_basic(self):
 41        print '--- running DynamoDB Layer1 tests ---'
 42
 43        # Create a Layer1 connection with an expired set of
 44        # credentials to test the automatic renewal of tokens
 45
 46        bad_creds = Credentials.from_json(json_doc)
 47        c = Layer1(session_token=bad_creds)
 48
 49        # First create a table
 50        table_name = 'test-%d' % int(time.time())
 51        hash_key_name = 'forum_name'
 52        hash_key_type = 'S'
 53        range_key_name = 'subject'
 54        range_key_type = 'S'
 55        read_units = 5
 56        write_units = 5
 57        schema = {'HashKeyElement': {'AttributeName': hash_key_name,
 58                                     'AttributeType': hash_key_type},
 59                  'RangeKeyElement': {'AttributeName': range_key_name,
 60                                      'AttributeType': range_key_type}}
 61        provisioned_throughput = {'ReadCapacityUnits': read_units,
 62                                  'WriteCapacityUnits': write_units}
 63
 64        result = c.create_table(table_name, schema, provisioned_throughput)
 65        assert result['TableDescription']['TableName'] == table_name
 66        result_schema = result['TableDescription']['KeySchema']
 67        assert result_schema['HashKeyElement']['AttributeName'] == hash_key_name
 68        assert result_schema['HashKeyElement']['AttributeType'] == hash_key_type
 69        assert result_schema['RangeKeyElement']['AttributeName'] == range_key_name
 70        assert result_schema['RangeKeyElement']['AttributeType'] == range_key_type
 71        result_thruput = result['TableDescription']['ProvisionedThroughput']
 72        assert result_thruput['ReadCapacityUnits'] == read_units
 73        assert result_thruput['WriteCapacityUnits'] == write_units
 74
 75        # Wait for table to become active
 76        result = c.describe_table(table_name)
 77        while result['Table']['TableStatus'] != 'ACTIVE':
 78            time.sleep(5)
 79            result = c.describe_table(table_name)
 80
 81        # List tables and make sure new one is there
 82        result = c.list_tables()
 83        assert table_name in result['TableNames']
 84
 85        # Update the tables ProvisionedThroughput
 86        new_read_units = 10
 87        new_write_units = 5
 88        new_provisioned_throughput = {'ReadCapacityUnits': new_read_units,
 89                                      'WriteCapacityUnits': new_write_units}
 90        result = c.update_table(table_name, new_provisioned_throughput)
 91
 92        # Wait for table to be updated
 93        result = c.describe_table(table_name)
 94        while result['Table']['TableStatus'] == 'UPDATING':
 95            time.sleep(5)
 96            result = c.describe_table(table_name)
 97
 98        result_thruput = result['Table']['ProvisionedThroughput']
 99        assert result_thruput['ReadCapacityUnits'] == new_read_units
100        assert result_thruput['WriteCapacityUnits'] == new_write_units
101
102        # Put an item
103        item1_key = 'Amazon DynamoDB'
104        item1_range = 'DynamoDB Thread 1'
105        item1_data = {
106            hash_key_name: {hash_key_type: item1_key},
107            range_key_name: {range_key_type: item1_range},
108            'Message': {'S': 'DynamoDB thread 1 message text'},
109            'LastPostedBy': {'S': 'User A'},
110            'Views': {'N': '0'},
111            'Replies': {'N': '0'},
112            'Answered': {'N': '0'},
113            'Tags': {'SS': ["index", "primarykey", "table"]},
114            'LastPostDateTime':  {'S': '12/9/2011 11:36:03 PM'}
115            }
116        result = c.put_item(table_name, item1_data)
117
118        # Now do a consistent read and check results
119        key1 = {'HashKeyElement': {hash_key_type: item1_key},
120               'RangeKeyElement': {range_key_type: item1_range}}
121        result = c.get_item(table_name, key=key1, consistent_read=True)
122        for name in item1_data:
123            assert name in result['Item']
124
125        # Try to get an item that does not exist.
126        invalid_key = {'HashKeyElement': {hash_key_type: 'bogus_key'},
127                       'RangeKeyElement': {range_key_type: item1_range}}
128        self.assertRaises(DynamoDBKeyNotFoundError,
129                          c.get_item, table_name, key=invalid_key)
130
131        # Try retrieving only select attributes
132        attributes = ['Message', 'Views']
133        result = c.get_item(table_name, key=key1, consistent_read=True,
134                            attributes_to_get=attributes)
135        for name in result['Item']:
136            assert name in attributes
137
138        # Try to delete the item with the wrong Expected value
139        expected = {'Views': {'Value': {'N': '1'}}}
140        self.assertRaises(DynamoDBConditionalCheckFailedError,
141                          c.delete_item, table_name, key=key1,
142                          expected=expected)
143
144        # Now update the existing object
145        attribute_updates = {'Views': {'Value': {'N': '5'},
146                                       'Action': 'PUT'},
147                             'Tags': {'Value': {'SS': ['foobar']},
148                                      'Action': 'ADD'}}
149        result = c.update_item(table_name, key=key1,
150                               attribute_updates=attribute_updates)
151
152        # Try and update an item, in a fashion which makes it too large.
153        # The new message text is the item size limit minus 32 bytes and
154        # the current object is larger than 32 bytes.
155        item_size_overflow_text = 'Text to be padded'.zfill(64*1024-32)
156        attribute_updates = {'Message': {'Value': {'S': item_size_overflow_text},
157                                       'Action': 'PUT'}}
158        self.assertRaises(DynamoDBValidationError,
159                          c.update_item, table_name, key=key1,
160                           attribute_updates=attribute_updates)
161
162
163        # Put a few more items into the table
164        item2_key = 'Amazon DynamoDB'
165        item2_range = 'DynamoDB Thread 2'
166        item2_data = {
167            hash_key_name: {hash_key_type: item2_key},
168            range_key_name: {range_key_type: item2_range},
169            'Message': {'S': 'DynamoDB thread 2 message text'},
170            'LastPostedBy': {'S': 'User A'},
171            'Views': {'N': '0'},
172            'Replies': {'N': '0'},
173            'Answered': {'N': '0'},
174            'Tags': {'SS': ["index", "primarykey", "table"]},
175            'LastPostDateTime':  {'S': '12/9/2011 11:36:03 PM'}
176            }
177        result = c.put_item(table_name, item2_data)
178        key2 = {'HashKeyElement': {hash_key_type: item2_key},
179               'RangeKeyElement': {range_key_type: item2_range}}
180
181        item3_key = 'Amazon S3'
182        item3_range = 'S3 Thread 1'
183        item3_data = {
184            hash_key_name: {hash_key_type: item3_key},
185            range_key_name: {range_key_type: item3_range},
186            'Message': {'S': 'S3 Thread 1 message text'},
187            'LastPostedBy': {'S': 'User A'},
188            'Views': {'N': '0'},
189            'Replies': {'N': '0'},
190            'Answered': {'N': '0'},
191            'Tags': {'SS': ['largeobject', 'multipart upload']},
192            'LastPostDateTime':  {'S': '12/9/2011 11:36:03 PM'}
193            }
194        result = c.put_item(table_name, item3_data)
195        key3 = {'HashKeyElement': {hash_key_type: item3_key},
196               'RangeKeyElement': {range_key_type: item3_range}}
197
198        # Try a few queries
199        result = c.query(table_name, {'S': 'Amazon DynamoDB'},
200                         {'AttributeValueList': [{'S': 'DynamoDB'}],
201                          'ComparisonOperator': 'BEGINS_WITH'})
202        assert 'Count' in result
203        assert result['Count'] == 2
204
205        # Try a few scans
206        result = c.scan(table_name,
207                        {'Tags': {'AttributeValueList':[{'S': 'table'}],
208                                  'ComparisonOperator': 'CONTAINS'}})
209        assert 'Count' in result
210        assert result['Count'] == 2
211
212        # Now delete the items
213        result = c.delete_item(table_name, key=key1)
214        result = c.delete_item(table_name, key=key2)
215        result = c.delete_item(table_name, key=key3)
216
217        # Now delete the table
218        result = c.delete_table(table_name)
219        assert result['TableDescription']['TableStatus'] == 'DELETING'
220
221        print '--- tests completed ---'
222