| Index: third_party/boto/tests/integration/dynamodb2/test_highlevel.py
|
| ===================================================================
|
| --- third_party/boto/tests/integration/dynamodb2/test_highlevel.py (revision 33376)
|
| +++ third_party/boto/tests/integration/dynamodb2/test_highlevel.py (working copy)
|
| @@ -31,7 +31,7 @@
|
| from tests.unit import unittest
|
| from boto.dynamodb2 import exceptions
|
| from boto.dynamodb2.fields import (HashKey, RangeKey, KeysOnlyIndex,
|
| - GlobalKeysOnlyIndex)
|
| + GlobalKeysOnlyIndex, GlobalIncludeIndex)
|
| from boto.dynamodb2.items import Item
|
| from boto.dynamodb2.table import Table
|
| from boto.dynamodb2.types import NUMBER
|
| @@ -109,6 +109,14 @@
|
|
|
| time.sleep(5)
|
|
|
| + # Does it exist? It should?
|
| + self.assertTrue(users.has_item(username='jane', friend_count=3))
|
| + # But this shouldn't be there...
|
| + self.assertFalse(users.has_item(
|
| + username='mrcarmichaeljones',
|
| + friend_count=72948
|
| + ))
|
| +
|
| # Test getting an item & updating it.
|
| # This is the "safe" variant (only write if there have been no
|
| # changes).
|
| @@ -211,7 +219,7 @@
|
| self.assertEqual(serverside_sadie['first_name'], 'Sadie')
|
|
|
| # Test the eventually consistent query.
|
| - results = users.query(
|
| + results = users.query_2(
|
| username__eq='johndoe',
|
| last_name__eq='Doe',
|
| index='LastNameIndex',
|
| @@ -223,9 +231,19 @@
|
| self.assertTrue(res['username'] in ['johndoe',])
|
| self.assertEqual(res.keys(), ['username'])
|
|
|
| + # Ensure that queries with attributes don't return the hash key.
|
| + results = users.query_2(
|
| + username__eq='johndoe',
|
| + friend_count__eq=4,
|
| + attributes=('first_name',)
|
| + )
|
|
|
| + for res in results:
|
| + self.assertTrue(res['first_name'] in ['John',])
|
| + self.assertEqual(res.keys(), ['first_name'])
|
| +
|
| # Test the strongly consistent query.
|
| - c_results = users.query(
|
| + c_results = users.query_2(
|
| username__eq='johndoe',
|
| last_name__eq='Doe',
|
| index='LastNameIndex',
|
| @@ -236,6 +254,18 @@
|
| for res in c_results:
|
| self.assertTrue(res['username'] in ['johndoe',])
|
|
|
| + # Test a query with query filters
|
| + results = users.query_2(
|
| + username__eq='johndoe',
|
| + query_filter={
|
| + 'first_name__beginswith': 'J'
|
| + },
|
| + attributes=('first_name',)
|
| + )
|
| +
|
| + for res in results:
|
| + self.assertTrue(res['first_name'] in ['John'])
|
| +
|
| # Test scans without filters.
|
| all_users = users.scan(limit=7)
|
| self.assertEqual(all_users.next()['username'], 'bob')
|
| @@ -304,7 +334,7 @@
|
| username__eq='johndoe'
|
| )
|
| # But it shouldn't break on more complex tables.
|
| - res = users.query(username__eq='johndoe')
|
| + res = users.query_2(username__eq='johndoe')
|
|
|
| # Test putting with/without sets.
|
| mau5_created = users.put_item(data={
|
| @@ -395,8 +425,65 @@
|
| )
|
|
|
| # Wait again for the changes to finish propagating.
|
| - time.sleep(120)
|
| + time.sleep(150)
|
|
|
| + def test_gsi_with_just_hash_key(self):
|
| + # GSI allows for querying off of different keys. This is behavior we
|
| + # previously disallowed (due to standard & LSI queries).
|
| + # See https://forums.aws.amazon.com/thread.jspa?threadID=146212&tstart=0
|
| + users = Table.create('gsi_query_users', schema=[
|
| + HashKey('user_id')
|
| + ], throughput={
|
| + 'read': 5,
|
| + 'write': 3,
|
| + },
|
| + global_indexes=[
|
| + GlobalIncludeIndex('UsernameIndex', parts=[
|
| + HashKey('username'),
|
| + ], includes=['user_id', 'username'], throughput={
|
| + 'read': 3,
|
| + 'write': 1,
|
| + })
|
| + ])
|
| + self.addCleanup(users.delete)
|
| +
|
| + # Wait for it.
|
| + time.sleep(60)
|
| +
|
| + users.put_item(data={
|
| + 'user_id': '7',
|
| + 'username': 'johndoe',
|
| + 'first_name': 'John',
|
| + 'last_name': 'Doe',
|
| + })
|
| + users.put_item(data={
|
| + 'user_id': '24',
|
| + 'username': 'alice',
|
| + 'first_name': 'Alice',
|
| + 'last_name': 'Expert',
|
| + })
|
| + users.put_item(data={
|
| + 'user_id': '35',
|
| + 'username': 'jane',
|
| + 'first_name': 'Jane',
|
| + 'last_name': 'Doe',
|
| + })
|
| +
|
| + # Try the main key. Should be fine.
|
| + rs = users.query_2(
|
| + user_id__eq='24'
|
| + )
|
| + results = sorted([user['username'] for user in rs])
|
| + self.assertEqual(results, ['alice'])
|
| +
|
| + # Now try the GSI. Also should work.
|
| + rs = users.query_2(
|
| + username__eq='johndoe',
|
| + index='UsernameIndex'
|
| + )
|
| + results = sorted([user['username'] for user in rs])
|
| + self.assertEqual(results, ['johndoe'])
|
| +
|
| def test_query_with_limits(self):
|
| # Per the DDB team, it's recommended to do many smaller gets with a
|
| # reduced page size.
|
| @@ -429,7 +516,7 @@
|
| time.sleep(5)
|
|
|
| # Test the reduced page size.
|
| - results = posts.query(
|
| + results = posts.query_2(
|
| thread__eq='Favorite chiptune band?',
|
| posted_on__gte='2013-12-24T00:00:00',
|
| max_page_size=2
|
| @@ -440,4 +527,117 @@
|
| [post['posted_by'] for post in all_posts],
|
| ['joe', 'jane', 'joe', 'joe', 'jane', 'joe']
|
| )
|
| - self.assertEqual(results._fetches, 3)
|
| + self.assertTrue(results._fetches >= 3)
|
| +
|
| + def test_query_with_reverse(self):
|
| + posts = Table.create('more-posts', schema=[
|
| + HashKey('thread'),
|
| + RangeKey('posted_on')
|
| + ], throughput={
|
| + 'read': 5,
|
| + 'write': 5,
|
| + })
|
| + self.addCleanup(posts.delete)
|
| +
|
| + # Wait for it.
|
| + time.sleep(60)
|
| +
|
| + # Add some data.
|
| + test_data_path = os.path.join(
|
| + os.path.dirname(__file__),
|
| + 'forum_test_data.json'
|
| + )
|
| + with open(test_data_path, 'r') as test_data:
|
| + data = json.load(test_data)
|
| +
|
| + with posts.batch_write() as batch:
|
| + for post in data:
|
| + batch.put_item(post)
|
| +
|
| + time.sleep(5)
|
| +
|
| + # Test the default order (ascending).
|
| + results = posts.query_2(
|
| + thread__eq='Favorite chiptune band?',
|
| + posted_on__gte='2013-12-24T00:00:00'
|
| + )
|
| + self.assertEqual(
|
| + [post['posted_on'] for post in results],
|
| + [
|
| + '2013-12-24T12:30:54',
|
| + '2013-12-24T12:35:40',
|
| + '2013-12-24T13:45:30',
|
| + '2013-12-24T14:15:14',
|
| + '2013-12-24T14:25:33',
|
| + '2013-12-24T15:22:22',
|
| + ]
|
| + )
|
| +
|
| + # Test the explicit ascending order.
|
| + results = posts.query_2(
|
| + thread__eq='Favorite chiptune band?',
|
| + posted_on__gte='2013-12-24T00:00:00',
|
| + reverse=False
|
| + )
|
| + self.assertEqual(
|
| + [post['posted_on'] for post in results],
|
| + [
|
| + '2013-12-24T12:30:54',
|
| + '2013-12-24T12:35:40',
|
| + '2013-12-24T13:45:30',
|
| + '2013-12-24T14:15:14',
|
| + '2013-12-24T14:25:33',
|
| + '2013-12-24T15:22:22',
|
| + ]
|
| + )
|
| +
|
| + # Test the explicit descending order.
|
| + results = posts.query_2(
|
| + thread__eq='Favorite chiptune band?',
|
| + posted_on__gte='2013-12-24T00:00:00',
|
| + reverse=True
|
| + )
|
| + self.assertEqual(
|
| + [post['posted_on'] for post in results],
|
| + [
|
| + '2013-12-24T15:22:22',
|
| + '2013-12-24T14:25:33',
|
| + '2013-12-24T14:15:14',
|
| + '2013-12-24T13:45:30',
|
| + '2013-12-24T12:35:40',
|
| + '2013-12-24T12:30:54',
|
| + ]
|
| + )
|
| +
|
| + # Test the old, broken style.
|
| + results = posts.query(
|
| + thread__eq='Favorite chiptune band?',
|
| + posted_on__gte='2013-12-24T00:00:00'
|
| + )
|
| + self.assertEqual(
|
| + [post['posted_on'] for post in results],
|
| + [
|
| + '2013-12-24T15:22:22',
|
| + '2013-12-24T14:25:33',
|
| + '2013-12-24T14:15:14',
|
| + '2013-12-24T13:45:30',
|
| + '2013-12-24T12:35:40',
|
| + '2013-12-24T12:30:54',
|
| + ]
|
| + )
|
| + results = posts.query(
|
| + thread__eq='Favorite chiptune band?',
|
| + posted_on__gte='2013-12-24T00:00:00',
|
| + reverse=True
|
| + )
|
| + self.assertEqual(
|
| + [post['posted_on'] for post in results],
|
| + [
|
| + '2013-12-24T12:30:54',
|
| + '2013-12-24T12:35:40',
|
| + '2013-12-24T13:45:30',
|
| + '2013-12-24T14:15:14',
|
| + '2013-12-24T14:25:33',
|
| + '2013-12-24T15:22:22',
|
| + ]
|
| + )
|
|
|