Ejemplo n.º 1
0
    def setUp(self):
        from ddbmock.database.db import dynamodb
        from ddbmock.database.table import Table
        from ddbmock.database.key import PrimaryKey

        from ddbmock import main
        app = main({})
        from webtest import TestApp
        self.app = TestApp(app)

        dynamodb.hard_reset()

        hash_key = PrimaryKey(TABLE_HK_NAME, TABLE_HK_TYPE)
        range_key = PrimaryKey(TABLE_RK_NAME, TABLE_RK_TYPE)

        self.t1 = Table(TABLE_NAME1, TABLE_RT, TABLE_WT, hash_key, range_key)
        self.t2 = Table(TABLE_NAME2, TABLE_RT, TABLE_WT, hash_key, None)

        dynamodb.data[TABLE_NAME1] = self.t1
        dynamodb.data[TABLE_NAME2] = self.t2

        self.t1.put(ITEM1, {})
        self.t1.put(ITEM2, {})
        self.t1.put(ITEM3, {})
        self.t2.put(ITEM4, {})
        self.t2.put(ITEM5, {})
Ejemplo n.º 2
0
    def setUp(self):
        from ddbmock.database.db import dynamodb
        from ddbmock.database.table import Table
        from ddbmock.database.key import PrimaryKey

        from ddbmock import main
        app = main({})
        from webtest import TestApp
        self.app = TestApp(app)

        dynamodb.hard_reset()

        hash_key = PrimaryKey(TABLE_HK_NAME, TABLE_HK_TYPE)
        range_key = PrimaryKey(TABLE_RK_NAME, TABLE_RK_TYPE)

        self.t1 = Table(TABLE_NAME1, TABLE_RT, TABLE_WT, hash_key, range_key)
        self.t2 = Table(TABLE_NAME2, TABLE_RT, TABLE_WT, hash_key, None)

        dynamodb.data[TABLE_NAME1]  = self.t1
        dynamodb.data[TABLE_NAME2]  = self.t2

        self.t1.put(ITEM1, {})
        self.t1.put(ITEM2, {})
        self.t1.put(ITEM3, {})
        self.t2.put(ITEM4, {})
        self.t2.put(ITEM5, {})
Ejemplo n.º 3
0
class TestTable(unittest.TestCase):
    def setUp(self):
        from ddbmock.database.table import Table
        self.table = Table(NAME, RT, WT, None, None, status="ACTIVE")

    def tearDown(self):
        self.table = None

    def test_update_throughput_nominal(self):
        self.table.update_throughput(RT2, WT2)

        self.assertEqual(RT2, self.table.rt)
        self.assertEqual(WT2, self.table.wt)

    def test_increase_throughtput_max_100_percents(self):
        from ddbmock.errors import LimitExceededException

        # Try on RT
        self.assertRaisesRegexp(LimitExceededException,
                                "ReadCapacityUnits .* at most 100",
                                self.table.update_throughput,
                                RT100, WT)
        self.assertEqual(RT, self.table.rt)
        self.assertEqual(WT, self.table.wt)

        # Try on WT
        self.assertRaisesRegexp(LimitExceededException,
                                "WriteCapacityUnits .* at most 100",
                                self.table.update_throughput,
                                RT, WT100)
        self.assertEqual(RT, self.table.rt)
        self.assertEqual(WT, self.table.wt)

    @mock.patch("ddbmock.database.table.time")
    def test_decrease_max_once_a_day(self, m_time):
        from ddbmock.errors import LimitExceededException

        # 1st decrease 1 hour after creation (ok)
        m_time.time.return_value = CREATION + 1*3600
        self.table.update_throughput(RT3, WT3)
        self.assertEqual(RT3, self.table.rt)
        self.assertEqual(WT3, self.table.wt)

        # bypass the timer
        self.table.status = "ACTIVE"

        # 2nd decrease 2 hour after creation (fail)
        m_time.time.return_value = CREATION + 2*3600
        self.assertRaisesRegexp(LimitExceededException,
                                "once .* day",
                                self.table.update_throughput,
                                RT4, WT4)
        self.assertEqual(RT3, self.table.rt)
        self.assertEqual(WT3, self.table.wt)
Ejemplo n.º 4
0
    def setUp(self):
        from ddbmock.database.db import dynamodb
        from ddbmock.database.table import Table
        from ddbmock.database.key import PrimaryKey

        dynamodb.hard_reset()

        hash_key = PrimaryKey('hash_key', 'N')
        range_key = PrimaryKey('range_key', 'S')

        t1 = Table(TABLE_NAME1, 10, 10, hash_key, range_key)
        t2 = Table(TABLE_NAME2, 10, 10, hash_key, range_key)

        dynamodb.data[TABLE_NAME1] = t1
        dynamodb.data[TABLE_NAME2] = t2
Ejemplo n.º 5
0
    def setUp(self):
        from ddbmock.database.db import dynamodb
        from ddbmock.database.table import Table
        from ddbmock.database.key import PrimaryKey

        dynamodb.hard_reset()

        hash_key = PrimaryKey(TABLE_HK_NAME, TABLE_HK_TYPE)
        range_key = PrimaryKey(TABLE_RK_NAME, TABLE_RK_TYPE)

        t1 = Table(TABLE_NAME , TABLE_RT, TABLE_WT, hash_key, range_key, status="ACTIVE")
        t2 = Table(TABLE_NAME2, TABLE_RT, TABLE_WT, hash_key, range_key)

        dynamodb.data[TABLE_NAME]  = t1
        dynamodb.data[TABLE_NAME2] = t2
Ejemplo n.º 6
0
class TestUpdateItem(unittest.TestCase):
    def setUp(self):
        from ddbmock.database.db import dynamodb
        from ddbmock.database.table import Table
        from ddbmock.database.key import PrimaryKey

        from ddbmock import main
        app = main({})
        from webtest import TestApp
        self.app = TestApp(app)

        dynamodb.hard_reset()

        hash_key = PrimaryKey(TABLE_HK_NAME, TABLE_HK_TYPE)
        range_key = PrimaryKey(TABLE_RK_NAME, TABLE_RK_TYPE)

        self.t1 = Table(TABLE_NAME, TABLE_RT, TABLE_WT, hash_key, range_key)
        dynamodb.data[TABLE_NAME] = self.t1
        self.t1.put(ITEM, {})

    def tearDown(self):
        from ddbmock.database.db import dynamodb
        dynamodb.hard_reset()

    def test_update_item_put_hr(self):
        request = {
            "TableName": TABLE_NAME,
            "Key": {
                "HashKeyElement": HK,
                "RangeKeyElement": RK,
            },
            "AttributeUpdates": {
                'relevant_data': {
                    'Value': RELEVANT_FIELD
                }
            },
        }
        expected = {"ConsumedCapacityUnits": 1}

        # Protocol check
        res = self.app.post_json('/', request, headers=HEADERS, status=200)
        self.assertEqual(expected, json.loads(res.body))
        self.assertEqual('application/x-amz-json-1.0; charset=UTF-8',
                         res.headers['Content-Type'])

        # Live data check
        self.assertEqual(RELEVANT_FIELD,
                         self.t1.store[HK_VALUE, RK_VALUE]['relevant_data'])
Ejemplo n.º 7
0
class TestGetItem(unittest.TestCase):
    def setUp(self):
        from ddbmock.database.db import dynamodb
        from ddbmock.database.table import Table
        from ddbmock.database.key import PrimaryKey

        from ddbmock.database.db import dynamodb
        from ddbmock import main
        app = main({})
        from webtest import TestApp
        self.app = TestApp(app)
        dynamodb.hard_reset()

        hash_key = PrimaryKey(TABLE_HK_NAME, TABLE_HK_TYPE)
        range_key = PrimaryKey(TABLE_RK_NAME, TABLE_RK_TYPE)

        self.t1 = Table(TABLE_NAME, TABLE_RT, TABLE_WT, hash_key, range_key)
        dynamodb.data[TABLE_NAME]  = self.t1
        self.t1.put(ITEM, {})

    def tearDown(self):
        from ddbmock.database.db import dynamodb
        dynamodb.hard_reset()

    def test_get_hr_attr_to_get(self):
        from ddbmock.database.db import dynamodb

        request = {
            "TableName": TABLE_NAME,
            "Key": {
                "HashKeyElement":  HK,
                "RangeKeyElement": RK,
            },
            "AttributesToGet": ["relevant_data"],
        }

        expected = {
            u'ConsumedCapacityUnits': 0.5,
            u'Item': {
                u'relevant_data': ITEM[u'relevant_data'],
            }
        }


        # Protocol check
        res = self.app.post_json('/', request, headers=HEADERS, status=200)
        self.assertEqual(expected, json.loads(res.body))
        self.assertEqual('application/x-amz-json-1.0; charset=UTF-8', res.headers['Content-Type'])
Ejemplo n.º 8
0
    def setUp(self):
        from ddbmock.database.db import dynamodb
        from ddbmock.database.table import Table
        from ddbmock.database.key import PrimaryKey

        dynamodb.hard_reset()

        hash_key = PrimaryKey(TABLE_HK_NAME, TABLE_HK_TYPE)
        range_key = PrimaryKey(TABLE_RK_NAME, TABLE_RK_TYPE)

        t1 = Table(TABLE_NAME, TABLE_RT, TABLE_WT, hash_key, range_key, status='ACTIVE')

        t1.put(ITEM1, {})
        t1.put(ITEM2, {})

        dynamodb.data[TABLE_NAME] = t1
Ejemplo n.º 9
0
    def setUp(self):
        from ddbmock.database.db import dynamodb
        from ddbmock.database.table import Table
        from ddbmock.database.key import PrimaryKey

        dynamodb.hard_reset()

        hash_key = PrimaryKey(TABLE_HK_NAME, TABLE_HK_TYPE)
        range_key = PrimaryKey(TABLE_RK_NAME, TABLE_RK_TYPE)

        t1 = Table(TABLE_NAME, TABLE_RT, TABLE_WT, hash_key, range_key, status='ACTIVE')

        t1.put(ITEM1, {})
        t1.put(ITEM2, {})

        dynamodb.data[TABLE_NAME] = t1
Ejemplo n.º 10
0
class TestGetItem(unittest.TestCase):
    def setUp(self):
        from ddbmock.database.db import dynamodb
        from ddbmock.database.table import Table
        from ddbmock.database.key import PrimaryKey

        from ddbmock import main
        app = main({})
        from webtest import TestApp
        self.app = TestApp(app)
        dynamodb.hard_reset()

        hash_key = PrimaryKey(TABLE_HK_NAME, TABLE_HK_TYPE)
        range_key = PrimaryKey(TABLE_RK_NAME, TABLE_RK_TYPE)

        self.t1 = Table(TABLE_NAME, TABLE_RT, TABLE_WT, hash_key, range_key)
        dynamodb.data[TABLE_NAME] = self.t1
        self.t1.put(ITEM, {})

    def tearDown(self):
        from ddbmock.database.db import dynamodb
        dynamodb.hard_reset()

    def test_get_hr_attr_to_get(self):

        request = {
            "TableName": TABLE_NAME,
            "Key": {
                "HashKeyElement": HK,
                "RangeKeyElement": RK,
            },
            "AttributesToGet": ["relevant_data"],
        }

        expected = {
            u'ConsumedCapacityUnits': 0.5,
            u'Item': {
                u'relevant_data': ITEM[u'relevant_data'],
            }
        }

        # Protocol check
        res = self.app.post_json('/', request, headers=HEADERS, status=200)
        self.assertEqual(expected, json.loads(res.body))
        self.assertEqual('application/x-amz-json-1.0; charset=UTF-8',
                         res.headers['Content-Type'])
Ejemplo n.º 11
0
class TestDeleteItem(unittest.TestCase):
    def setUp(self):
        from ddbmock.database.db import dynamodb
        from ddbmock.database.table import Table
        from ddbmock.database.key import PrimaryKey

        from ddbmock.database.db import dynamodb
        from ddbmock import main
        app = main({})
        from webtest import TestApp
        self.app = TestApp(app)
        dynamodb.hard_reset()

        hash_key = PrimaryKey(TABLE_HK_NAME, TABLE_HK_TYPE)
        range_key = PrimaryKey(TABLE_RK_NAME, TABLE_RK_TYPE)

        self.t1 = Table(TABLE_NAME, TABLE_RT, TABLE_WT, hash_key, range_key)
        dynamodb.data[TABLE_NAME]  = self.t1
        self.t1.put(ITEM, {})

    def tearDown(self):
        from ddbmock.database.db import dynamodb
        dynamodb.hard_reset()

    def test_delete_item_hr(self):
        from ddbmock.database.db import dynamodb

        request = {
            "TableName": TABLE_NAME,
            "Key": {
                "HashKeyElement":  HK,
                "RangeKeyElement": RK,
            },
        }
        expected = {
            u"ConsumedCapacityUnits": 1,
        }

        # Protocol check
        res = self.app.post_json('/', request, headers=HEADERS, status=200)
        self.assertEqual(expected, json.loads(res.body))
        self.assertEqual('application/x-amz-json-1.0; charset=UTF-8', res.headers['Content-Type'])

        # Live data check
        self.assertNotIn((HK_VALUE, RK_VALUE), self.t1.store)
Ejemplo n.º 12
0
    def setUp(self):
        from ddbmock.database.db import dynamodb
        from ddbmock.database.table import Table
        from ddbmock.database.key import PrimaryKey

        dynamodb.hard_reset()

        hash_key = PrimaryKey(TABLE_HK_NAME, TABLE_HK_TYPE)
        range_key = PrimaryKey(TABLE_RK_NAME, TABLE_RK_TYPE)

        self.t1 = Table(TABLE_NAME, TABLE_RT, TABLE_WT, hash_key, range_key)
        self.t2 = Table(TABLE_NAME2, TABLE_RT, TABLE_WT, hash_key, None)

        dynamodb.data[TABLE_NAME] = self.t1
        dynamodb.data[TABLE_NAME2] = self.t2

        self.t1.put(cp(ITEM), {})
        self.t2.put(cp(ITEM2), {})
Ejemplo n.º 13
0
    def setUp(self):
        from ddbmock.database.db import dynamodb
        from ddbmock.database.table import Table
        from ddbmock.database.key import PrimaryKey

        dynamodb.hard_reset()

        hash_key = PrimaryKey(TABLE_HK_NAME, TABLE_HK_TYPE)
        range_key = PrimaryKey(TABLE_RK_NAME, TABLE_RK_TYPE)

        self.t1 = Table(TABLE_NAME, TABLE_RT, TABLE_WT, hash_key, range_key)
        self.t2 = Table(TABLE_NAME2, TABLE_RT, TABLE_WT, hash_key, None)

        dynamodb.data[TABLE_NAME]  = self.t1
        dynamodb.data[TABLE_NAME2] = self.t2

        self.t1.put(cp(ITEM), {})
        self.t2.put(cp(ITEM2), {})
Ejemplo n.º 14
0
    def setUp(self):
        from ddbmock.database.db import dynamodb
        from ddbmock.database.table import Table
        from ddbmock.database.key import PrimaryKey

        dynamodb.hard_reset()

        hash_key = PrimaryKey(TABLE_HK_NAME, TABLE_HK_TYPE)
        range_key = PrimaryKey(TABLE_RK_NAME, TABLE_RK_TYPE)

        self.t1 = Table(TABLE_NAME, TABLE_RT, TABLE_WT, hash_key, range_key)

        dynamodb.data[TABLE_NAME] = self.t1

        self.t1.put(ITEM1, {})
        self.t1.put(ITEM2, {})
        self.t1.put(ITEM3, {})
        self.t1.put(ITEM4, {})
        self.t1.put(ITEM5, {})
Ejemplo n.º 15
0
class TestUpdateItem(unittest.TestCase):
    def setUp(self):
        from ddbmock.database.db import dynamodb
        from ddbmock.database.table import Table
        from ddbmock.database.key import PrimaryKey

        import helpers
        self.app = helpers.makeTestApp()

        dynamodb.hard_reset()

        hash_key = PrimaryKey(TABLE_HK_NAME, TABLE_HK_TYPE)
        range_key = PrimaryKey(TABLE_RK_NAME, TABLE_RK_TYPE)

        self.t1 = Table(TABLE_NAME, TABLE_RT, TABLE_WT, hash_key, range_key)
        dynamodb.data[TABLE_NAME] = self.t1
        self.t1.put(ITEM, {})

    def tearDown(self):
        from ddbmock.database.db import dynamodb
        dynamodb.hard_reset()

    def test_update_item_put_hr(self):
        request = {
            "TableName": TABLE_NAME,
            "Key": {
                "HashKeyElement": HK,
                "RangeKeyElement": RK,
            },
            "AttributeUpdates": {'relevant_data': {'Value': RELEVANT_FIELD}},
        }
        expected = {"ConsumedCapacityUnits": 1}

        # Protocol check
        res = self.app.post_json('/', request, headers=HEADERS, status=200)
        self.assertEqual(expected, json.loads(res.body))
        self.assertEqual('application/x-amz-json-1.0; charset=UTF-8',
                         res.headers['Content-Type'])

        # Live data check
        self.assertEqual(RELEVANT_FIELD,
                         self.t1.store[HK_VALUE, RK_VALUE]['relevant_data'])
Ejemplo n.º 16
0
    def setUp(self):
        from ddbmock.database.db import dynamodb
        from ddbmock.database.table import Table
        from ddbmock.database.key import PrimaryKey

        from ddbmock import main
        app = main({})
        from webtest import TestApp
        self.app = TestApp(app)

        dynamodb.hard_reset()

        hash_key = PrimaryKey('hash_key', 'N')
        range_key = PrimaryKey('range_key', 'S')

        t1 = Table(TABLE_NAME1, 10, 10, hash_key, range_key)
        t2 = Table(TABLE_NAME2, 10, 10, hash_key, range_key)

        dynamodb.data[TABLE_NAME1] = t1
        dynamodb.data[TABLE_NAME2] = t2
Ejemplo n.º 17
0
    def setUp(self):
        from ddbmock.database.db import dynamodb
        from ddbmock.database.table import Table
        from ddbmock.database.key import PrimaryKey

        import helpers
        self.app = helpers.makeTestApp()

        dynamodb.hard_reset()

        hash_key = PrimaryKey(TABLE_HK_NAME, TABLE_HK_TYPE)
        range_key = PrimaryKey(TABLE_RK_NAME, TABLE_RK_TYPE)

        self.t1 = Table(TABLE_NAME1, TABLE_RT, TABLE_WT, hash_key, range_key)
        self.t2 = Table(TABLE_NAME2, TABLE_RT, TABLE_WT, hash_key, None)

        dynamodb.data[TABLE_NAME1] = self.t1
        dynamodb.data[TABLE_NAME2] = self.t2

        self.t1.put(ITEM1, {})
        self.t2.put(ITEM4, {})
Ejemplo n.º 18
0
    def setUp(self):
        from ddbmock.database.db import dynamodb
        from ddbmock.database.table import Table
        from ddbmock.database.key import PrimaryKey

        from ddbmock import main
        app = main({})
        from webtest import TestApp
        self.app = TestApp(app)

        dynamodb.hard_reset()

        hash_key = PrimaryKey(TABLE_HK_NAME, TABLE_HK_TYPE)
        range_key = PrimaryKey(TABLE_RK_NAME, TABLE_RK_TYPE)
        self.t1 = Table(TABLE_NAME, TABLE_RT, TABLE_WT, hash_key, range_key)
        dynamodb.data[TABLE_NAME] = self.t1
Ejemplo n.º 19
0
    def setUp(self, m_time):
        from ddbmock.database.db import dynamodb
        from ddbmock.database.table import Table
        from ddbmock.database.key import PrimaryKey
        from ddbmock import main
        app = main({})
        from webtest import TestApp
        self.app = TestApp(app)

        m_time.time.return_value = NOW

        dynamodb.hard_reset()

        hash_key = PrimaryKey(TABLE_HK_NAME, TABLE_HK_TYPE)
        range_key = PrimaryKey(TABLE_RK_NAME, TABLE_RK_TYPE)
        t1 = Table(TABLE_NAME, TABLE_RT, TABLE_WT, hash_key, range_key,
                   status='ACTIVE')
        dynamodb.data[TABLE_NAME] = t1
Ejemplo n.º 20
0
    def setUp(self):
        from ddbmock.database.db import dynamodb
        from ddbmock.database.table import Table
        from ddbmock.database.key import PrimaryKey

        dynamodb.hard_reset()

        hash_key = PrimaryKey(TABLE_HK_NAME, TABLE_HK_TYPE)
        range_key = PrimaryKey(TABLE_RK_NAME, TABLE_RK_TYPE)

        self.t1 = Table(TABLE_NAME, TABLE_RT, TABLE_WT, hash_key, range_key)

        dynamodb.data[TABLE_NAME]  = self.t1

        self.t1.put(ITEM1, {})
        self.t1.put(ITEM2, {})
        self.t1.put(ITEM3, {})
        self.t1.put(ITEM4, {})
        self.t1.put(ITEM5, {})
Ejemplo n.º 21
0
class TestBatchWriteItem(unittest.TestCase):
    def setUp(self):
        from ddbmock.database.db import dynamodb
        from ddbmock.database.table import Table
        from ddbmock.database.key import PrimaryKey

        from ddbmock import main
        app = main({})
        from webtest import TestApp
        self.app = TestApp(app)

        dynamodb.hard_reset()

        hash_key = PrimaryKey(TABLE_HK_NAME, TABLE_HK_TYPE)
        range_key = PrimaryKey(TABLE_RK_NAME, TABLE_RK_TYPE)

        self.t1 = Table(TABLE_NAME1, TABLE_RT, TABLE_WT, hash_key, range_key)
        self.t2 = Table(TABLE_NAME2, TABLE_RT, TABLE_WT, hash_key, None)

        dynamodb.data[TABLE_NAME1] = self.t1
        dynamodb.data[TABLE_NAME2] = self.t2

        self.t1.put(ITEM1, {})
        self.t2.put(ITEM4, {})

    def tearDown(self):
        from ddbmock.database.db import dynamodb
        dynamodb.hard_reset()

    def test_batch_write_item(self):
        request = {
            u"RequestItems": {
                TABLE_NAME1: [
                    {
                        u"DeleteRequest": {
                            u"Key": {
                                u"HashKeyElement": {TABLE_HK_TYPE: HK_VALUE1},
                                u"RangeKeyElement": {TABLE_RK_TYPE: RK_VALUE1},
                            },
                        },
                    },
                    {u"PutRequest": {u"Item": ITEM2}},
                    {u"PutRequest": {u"Item": ITEM3}},
                ],
                TABLE_NAME2: [
                    {
                        u"DeleteRequest": {
                            u"Key": {
                                u"HashKeyElement": {TABLE_HK_TYPE: HK_VALUE2},
                            },
                        },
                    },
                    {u"PutRequest": {u"Item":ITEM5}},
                ],
            }
        }

        expected = {
            "Responses": {
                TABLE_NAME1: {
                    "ConsumedCapacityUnits": 3
                },
                TABLE_NAME2: {
                    "ConsumedCapacityUnits": 2
                }
            }
        }

        # Protocol check
        res = self.app.post_json('/', request, headers=HEADERS, status=200)
        self.assertEqual(expected, json.loads(res.body))
        self.assertEqual('application/x-amz-json-1.0; charset=UTF-8',
                         res.headers['Content-Type'])
Ejemplo n.º 22
0
class TestBatchGetItem(unittest.TestCase):
    def setUp(self):
        from ddbmock.database.db import dynamodb
        from ddbmock.database.table import Table
        from ddbmock.database.key import PrimaryKey

        dynamodb.hard_reset()

        hash_key = PrimaryKey(TABLE_HK_NAME, TABLE_HK_TYPE)
        range_key = PrimaryKey(TABLE_RK_NAME, TABLE_RK_TYPE)

        self.t1 = Table(TABLE_NAME1, TABLE_RT, TABLE_WT, hash_key, range_key)
        self.t2 = Table(TABLE_NAME2, TABLE_RT, TABLE_WT, hash_key, None)

        dynamodb.data[TABLE_NAME1]  = self.t1
        dynamodb.data[TABLE_NAME2]  = self.t2

        self.t1.put(ITEM1, {})
        self.t1.put(ITEM2, {})
        self.t1.put(ITEM3, {})
        self.t2.put(ITEM4, {})
        self.t2.put(ITEM5, {})
        self.t2.put(ITEM_BIG, {})

    def tearDown(self):
        from ddbmock.database.db import dynamodb
        from ddbmock import clean_boto_patch
        dynamodb.hard_reset()
        clean_boto_patch()

    def test_batch_get_item_nominal(self):
        from ddbmock import connect_boto_patch
        from ddbmock.database.db import dynamodb

        db = connect_boto_patch()

        expected = {
            "Responses": {
                "Table-HR": {
                    "Items": [ITEM1, ITEM2],
                    "ConsumedCapacityUnits": 1.0
                },
                "Table-H": {
                    "Items": [ITEM5, ITEM_BIG],
                    "ConsumedCapacityUnits": 1.5
                }
            }
        }

        ret = db.layer1.batch_get_item({
            TABLE_NAME1: {
                u"Keys": [
                    {u"HashKeyElement": {TABLE_HK_TYPE: HK_VALUE1}, u"RangeKeyElement": {TABLE_RK_TYPE: RK_VALUE1}},
                    {u"HashKeyElement": {TABLE_HK_TYPE: HK_VALUE1}, u"RangeKeyElement": {TABLE_RK_TYPE: RK_VALUE2}},
                ],
            },
            TABLE_NAME2: {
                u"Keys": [
                    {u"HashKeyElement": {TABLE_HK_TYPE: HK_VALUE3}},
                    {u"HashKeyElement": {TABLE_HK_TYPE: HK_VALUE1}},
                    {u"HashKeyElement": {TABLE_HK_TYPE: u"404"}},
                ],
            },
        })
        self.assertEqual(expected, ret)

    def test_batch_get_item_filter_one(self):
        from ddbmock import connect_boto_patch
        from ddbmock.database.db import dynamodb

        db = connect_boto_patch()

        expected = {
            "Responses": {
                "Table-HR": {
                    "Items": [
                        {"relevant_data": {"S": "tata"}},
                        {"relevant_data": {"S": "tata"}},
                    ],
                    "ConsumedCapacityUnits": 1.0
                },
                "Table-H": {
                    "Items": [
                        {"relevant_data": {"S": "tutu"}, "hash_key": {"N": "789"}, "range_key": {"S": "Waldo-5"}},
                    ],
                    "ConsumedCapacityUnits": 0.5
                }
            }
        }

        ret = db.layer1.batch_get_item({
            TABLE_NAME1: {
                u"Keys": [
                    {u"HashKeyElement": {TABLE_HK_TYPE: HK_VALUE1}, u"RangeKeyElement": {TABLE_RK_TYPE: RK_VALUE1}},
                    {u"HashKeyElement": {TABLE_HK_TYPE: HK_VALUE1}, u"RangeKeyElement": {TABLE_RK_TYPE: RK_VALUE1}},
                ],
                u"AttributesToGet": [u"relevant_data"],
            },
            TABLE_NAME2: {
                u"Keys": [
                    {u"HashKeyElement": {TABLE_HK_TYPE: HK_VALUE3}},
                ],
            },
        })
        self.assertEqual(expected, ret)

    def test_batch_get_item_table_404(self):
        from ddbmock import connect_boto_patch
        from ddbmock.database.db import dynamodb
        from boto.exception import BotoServerError

        db = connect_boto_patch()

        self.assertRaises(BotoServerError, db.layer1.batch_get_item, {
            TABLE_NAME_404: {
                u"Keys": [
                    {u"HashKeyElement": {TABLE_HK_TYPE: HK_VALUE1}, u"RangeKeyElement": {TABLE_RK_TYPE: RK_VALUE1}},
                    {u"HashKeyElement": {TABLE_HK_TYPE: HK_VALUE1}, u"RangeKeyElement": {TABLE_RK_TYPE: RK_VALUE1}},
                ],
            },
            TABLE_NAME2: {
                u"Keys": [
                    {u"HashKeyElement": {TABLE_HK_TYPE: HK_VALUE3}},
                ],
            },
        })

    def test_batch_get_item_bad_key(self):
        from ddbmock import connect_boto_patch
        from ddbmock.database.db import dynamodb
        from boto.dynamodb.exceptions import DynamoDBValidationError

        db = connect_boto_patch()

        self.assertRaises(DynamoDBValidationError, db.layer1.batch_get_item,
        {
            TABLE_NAME1: {
                u"Keys": [
                    {u"HashKeyElement": {TABLE_HK_TYPE: HK_VALUE1}, u"RangeKeyElement": {TABLE_RK_TYPE: RK_VALUE1}},
                    {u"HashKeyElement": {TABLE_HK_TYPE: HK_VALUE1}},
                ],
            },
            TABLE_NAME2: {
                u"Keys": [
                    {u"HashKeyElement": {TABLE_HK_TYPE: HK_VALUE3}},
                ],
            },
        })

        self.assertRaises(DynamoDBValidationError, db.layer1.batch_get_item,
        {
            TABLE_NAME1: {
                u"Keys": [
                    {u"HashKeyElement": {TABLE_HK_TYPE: HK_VALUE1}, u"RangeKeyElement": {TABLE_RK_TYPE: RK_VALUE1}},
                    {u"HashKeyElement": {TABLE_HK_TYPE: HK_VALUE1}, u"RangeKeyElement": {TABLE_RK_TYPE: RK_VALUE1}},
                ],
            },
            TABLE_NAME2: {
                u"Keys": [
                    {u"HashKeyElement": {TABLE_HK_TYPE: HK_VALUE3}, u"RangeKeyElement": {TABLE_RK_TYPE: RK_VALUE1}},
                ],
            },
        })
Ejemplo n.º 23
0
class TestQuery(unittest.TestCase):
    def setUp(self):
        from ddbmock.database.db import dynamodb
        from ddbmock.database.table import Table
        from ddbmock.database.key import PrimaryKey
        from ddbmock import main
        app = main({})
        from webtest import TestApp
        self.app = TestApp(app)

        dynamodb.hard_reset()

        hash_key = PrimaryKey(TABLE_HK_NAME, TABLE_HK_TYPE)
        range_key = PrimaryKey(TABLE_RK_NAME, TABLE_RK_TYPE)

        self.t1 = Table(TABLE_NAME, TABLE_RT, TABLE_WT, hash_key, range_key)

        dynamodb.data[TABLE_NAME] = self.t1

        self.t1.put(ITEM1, {})
        self.t1.put(ITEM2, {})
        self.t1.put(ITEM3, {})
        self.t1.put(ITEM4, {})
        self.t1.put(ITEM5, {})

    def tearDown(self):
        from ddbmock.database.db import dynamodb
        dynamodb.hard_reset()

    def test_query_condition_filter_fields(self):
        request = {
            "TableName": TABLE_NAME,
            "HashKeyValue": {TABLE_HK_TYPE: HK_VALUE},
            "RangeKeyCondition": {
                "AttributeValueList": [{"S":"Waldo-2"}],
                "ComparisonOperator": "GT",
                },
            "AttributesToGet": [u'relevant_data'],
        }

        expected = {
            u"Count": 3,
            u"Items": [
                {u"relevant_data": {u"S": u"titi"}},
                {u"relevant_data": {u"S": u"toto"}},
                {u"relevant_data": {u"S": u"tutu"}},
            ],
            u"ConsumedCapacityUnits": 0.5,
        }

        # Protocol check
        res = self.app.post_json('/', request, headers=HEADERS, status=200)
        self.assertEqual(expected, json.loads(res.body))
        self.assertEqual('application/x-amz-json-1.0; charset=UTF-8',
                         res.headers['Content-Type'])

    def test_query_count_and_attrs_to_get_fails(self):
        request = {
            "TableName": TABLE_NAME,
            "HashKeyValue": {TABLE_HK_TYPE: HK_VALUE},
            "RangeKeyCondition": {
                "AttributeValueList": [{"S":"Waldo-2"}],
                "ComparisonOperator": "GT",
                },
            "AttributesToGet": [u'relevant_data'],
            "Count": True,
        }

        expected = {
            u'__type': u'com.amazonaws.dynamodb.v20111205#ValidationException',
            u'message': u'Can filter fields when only count is requested'
        }

        # Protocol check
        res = self.app.post_json('/', request, headers=HEADERS, status=400)
        self.assertEqual(expected, json.loads(res.body))
        self.assertEqual('application/x-amz-json-1.0; charset=UTF-8',
                         res.headers['Content-Type'])

    # Regression test for #9
    def test_query_all_404(self):
        request = {
            "TableName": TABLE_NAME,
            "HashKeyValue": {TABLE_HK_TYPE: HK_VALUE_404},
        }

        expected = {
            u"Count": 0,
            u'Items': [],
            u"ConsumedCapacityUnits": 0.5,
        }

        # Protocol check
        res = self.app.post_json('/', request, headers=HEADERS, status=200)
        self.assertEqual(expected, json.loads(res.body))
        self.assertEqual('application/x-amz-json-1.0; charset=UTF-8',
                         res.headers['Content-Type'])
Ejemplo n.º 24
0
class TestDeleteItem(unittest.TestCase):
    def setUp(self):
        from ddbmock.database.db import dynamodb
        from ddbmock.database.table import Table
        from ddbmock.database.key import PrimaryKey

        dynamodb.hard_reset()

        hash_key = PrimaryKey(TABLE_HK_NAME, TABLE_HK_TYPE)
        range_key = PrimaryKey(TABLE_RK_NAME, TABLE_RK_TYPE)

        self.t1 = Table(TABLE_NAME, TABLE_RT, TABLE_WT, hash_key, range_key)
        self.t2 = Table(TABLE_NAME2, TABLE_RT, TABLE_WT, hash_key, None)

        dynamodb.data[TABLE_NAME]  = self.t1
        dynamodb.data[TABLE_NAME2] = self.t2

        self.t1.put(ITEM, {})
        self.t2.put(ITEM2, {})
        self.t2.put(ITEM_BIG, {})

    def tearDown(self):
        from ddbmock.database.db import dynamodb
        from ddbmock import clean_boto_patch
        dynamodb.hard_reset()
        clean_boto_patch()

    def test_delete_item_hr(self):
        from ddbmock import connect_boto_patch
        from ddbmock.database.db import dynamodb

        db = connect_boto_patch()

        key = {
            u"HashKeyElement":  {TABLE_HK_TYPE: HK_VALUE},
            u"RangeKeyElement": {TABLE_RK_TYPE: RK_VALUE},
        }

        self.assertEqual({
                u'ConsumedCapacityUnits': 1,
            },
            db.layer1.delete_item(TABLE_NAME, key),
        )
        self.assertNotIn((HK_VALUE, RK_VALUE), self.t1.store)

    def test_delete_item_hr_404(self):
        # same behavior as found
        from ddbmock import connect_boto_patch
        from ddbmock.database.db import dynamodb

        db = connect_boto_patch()

        key = {
            u"HashKeyElement":  {TABLE_HK_TYPE: HK_VALUE_404},
            u"RangeKeyElement": {TABLE_RK_TYPE: RK_VALUE},
        }

        self.assertEqual({
                u'ConsumedCapacityUnits': 1,
            },
            db.layer1.delete_item(TABLE_NAME, key),
        )
        self.assertNotIn((HK_VALUE_404, RK_VALUE), self.t1.store)

    def test_delete_item_hr_old(self):
        from ddbmock import connect_boto_patch
        from ddbmock.database.db import dynamodb

        db = connect_boto_patch()

        expected = {
            u'ConsumedCapacityUnits': 1,
            u'Attributes': ITEM,
        }

        key = {
            u"HashKeyElement":  {TABLE_HK_TYPE: HK_VALUE},
            u"RangeKeyElement": {TABLE_RK_TYPE: RK_VALUE},
        }

        self.assertEqual(
            expected,
            db.layer1.delete_item(TABLE_NAME, key, return_values=u'ALL_OLD'),
        )
        self.assertNotIn((HK_VALUE, RK_VALUE), self.t1.store)

    def test_delete_item_h(self):
        from ddbmock import connect_boto_patch
        from ddbmock.database.db import dynamodb

        db = connect_boto_patch()

        key = {
            u"HashKeyElement":  {TABLE_HK_TYPE: HK_VALUE},
        }

        self.assertEqual({
                u'ConsumedCapacityUnits': 1,
            },
            db.layer1.delete_item(TABLE_NAME2, key),
        )
        self.assertNotIn((HK_VALUE, False), self.t2.store)

    def test_delete_item_h_big(self):
        from ddbmock import connect_boto_patch
        from ddbmock.database.db import dynamodb

        db = connect_boto_patch()

        key = {
            u"HashKeyElement":  {TABLE_HK_TYPE: HK_VALUE2},
        }

        self.assertEqual({
                u'ConsumedCapacityUnits': 2,
            },
            db.layer1.delete_item(TABLE_NAME2, key),
        )
        self.assertNotIn((HK_VALUE2, False), self.t2.store)

    def test_delete_item_h_old(self):
        from ddbmock import connect_boto_patch
        from ddbmock.database.db import dynamodb

        db = connect_boto_patch()

        expected = {
            u'ConsumedCapacityUnits': 1,
            u'Attributes': ITEM2,
        }

        key = {
            u"HashKeyElement":  {TABLE_HK_TYPE: HK_VALUE},
        }

        self.assertEqual(
            expected,
            db.layer1.delete_item(TABLE_NAME2, key, return_values=u'ALL_OLD'),
        )
        self.assertNotIn((HK_VALUE, False), self.t1.store)

    def test_delete_item_hr_missing_r(self):
        from ddbmock import connect_boto_patch
        from ddbmock.database.db import dynamodb
        from boto.dynamodb.exceptions import DynamoDBValidationError

        db = connect_boto_patch()

        key = {
            u"HashKeyElement":  {TABLE_HK_TYPE: HK_VALUE},
        }

        self.assertRaises(DynamoDBValidationError,
                          db.layer1.delete_item,
                          TABLE_NAME, key)

    def test_delete_item_h_missing_h(self):
        from ddbmock import connect_boto_patch
        from ddbmock.database.db import dynamodb
        from boto.dynamodb.exceptions import DynamoDBValidationError

        db = connect_boto_patch()

        key = {}

        self.assertRaises(DynamoDBValidationError,
                          db.layer1.delete_item,
                          TABLE_NAME2, key)

    def test_delete_item_h_expect_field_value_ok(self):
        from ddbmock import connect_boto_patch
        from ddbmock.database.db import dynamodb
        from boto.exception import DynamoDBResponseError

        db = connect_boto_patch()

        ddb_expected = {
            u'relevant_data': {
                u'Exists': True,
                u'Value': {u'B': u'THVkaWEgaXMgdGhlIGJlc3QgY29tcGFueSBldmVyIQ=='}
            }
        }

        key = {
            u"HashKeyElement":  {TABLE_HK_TYPE: HK_VALUE},
            u"RangeKeyElement": {TABLE_RK_TYPE: RK_VALUE},
        }

        db.layer1.delete_item(TABLE_NAME, key, expected=ddb_expected)
        self.assertNotIn((HK_VALUE, False), self.t1.store)

    def test_delete_item_h_expect_field_value_fail(self):
        from ddbmock import connect_boto_patch
        from ddbmock.database.db import dynamodb
        from boto.dynamodb.exceptions import DynamoDBConditionalCheckFailedError

        db = connect_boto_patch()

        ddb_expected = {
            u'relevant_data_et_bah_non': {
                u'Exists': True,
                u'Value': {u'B': u'THVkaWEgaXMgdGhlIGJlc3QgY29tcGFueSBldmVyIQ=='}
            }
        }

        key = {
            u"HashKeyElement":  {TABLE_HK_TYPE: HK_VALUE},
            u"RangeKeyElement": {TABLE_RK_TYPE: RK_VALUE},
        }

        self.assertRaisesRegexp(DynamoDBConditionalCheckFailedError, 'ConditionalCheckFailedException',
            db.layer1.delete_item,
            TABLE_NAME, key, expected=ddb_expected
        )
        self.assertEqual(ITEM, self.t1.store[HK_VALUE, RK_VALUE])
Ejemplo n.º 25
0
class TestDeleteItem(unittest.TestCase):
    def setUp(self):
        from ddbmock.database.db import dynamodb
        from ddbmock.database.table import Table
        from ddbmock.database.key import PrimaryKey

        dynamodb.hard_reset()

        hash_key = PrimaryKey(TABLE_HK_NAME, TABLE_HK_TYPE)
        range_key = PrimaryKey(TABLE_RK_NAME, TABLE_RK_TYPE)

        self.t1 = Table(TABLE_NAME, TABLE_RT, TABLE_WT, hash_key, range_key)
        self.t2 = Table(TABLE_NAME2, TABLE_RT, TABLE_WT, hash_key, None)

        dynamodb.data[TABLE_NAME] = self.t1
        dynamodb.data[TABLE_NAME2] = self.t2

        self.t1.put(ITEM, {})
        self.t2.put(ITEM2, {})
        self.t2.put(ITEM_BIG, {})

    def tearDown(self):
        from ddbmock.database.db import dynamodb
        from ddbmock import clean_boto_patch
        dynamodb.hard_reset()
        clean_boto_patch()

    def test_delete_item_hr(self):
        from ddbmock import connect_boto_patch
        from ddbmock.database.db import dynamodb

        db = connect_boto_patch()

        key = {
            u"HashKeyElement": {
                TABLE_HK_TYPE: HK_VALUE
            },
            u"RangeKeyElement": {
                TABLE_RK_TYPE: RK_VALUE
            },
        }

        self.assertEqual(
            {
                u'ConsumedCapacityUnits': 1,
            },
            db.layer1.delete_item(TABLE_NAME, key),
        )
        self.assertNotIn((HK_VALUE, RK_VALUE), self.t1.store)

    def test_delete_item_hr_404(self):
        # same behavior as found
        from ddbmock import connect_boto_patch
        from ddbmock.database.db import dynamodb

        db = connect_boto_patch()

        key = {
            u"HashKeyElement": {
                TABLE_HK_TYPE: HK_VALUE_404
            },
            u"RangeKeyElement": {
                TABLE_RK_TYPE: RK_VALUE
            },
        }

        self.assertEqual(
            {
                u'ConsumedCapacityUnits': 1,
            },
            db.layer1.delete_item(TABLE_NAME, key),
        )
        self.assertNotIn((HK_VALUE_404, RK_VALUE), self.t1.store)

    def test_delete_item_hr_old(self):
        from ddbmock import connect_boto_patch
        from ddbmock.database.db import dynamodb

        db = connect_boto_patch()

        expected = {
            u'ConsumedCapacityUnits': 1,
            u'Attributes': ITEM,
        }

        key = {
            u"HashKeyElement": {
                TABLE_HK_TYPE: HK_VALUE
            },
            u"RangeKeyElement": {
                TABLE_RK_TYPE: RK_VALUE
            },
        }

        self.assertEqual(
            expected,
            db.layer1.delete_item(TABLE_NAME, key, return_values=u'ALL_OLD'),
        )
        self.assertNotIn((HK_VALUE, RK_VALUE), self.t1.store)

    def test_delete_item_h(self):
        from ddbmock import connect_boto_patch
        from ddbmock.database.db import dynamodb

        db = connect_boto_patch()

        key = {
            u"HashKeyElement": {
                TABLE_HK_TYPE: HK_VALUE
            },
        }

        self.assertEqual(
            {
                u'ConsumedCapacityUnits': 1,
            },
            db.layer1.delete_item(TABLE_NAME2, key),
        )
        self.assertNotIn((HK_VALUE, False), self.t2.store)

    def test_delete_item_h_big(self):
        from ddbmock import connect_boto_patch
        from ddbmock.database.db import dynamodb

        db = connect_boto_patch()

        key = {
            u"HashKeyElement": {
                TABLE_HK_TYPE: HK_VALUE2
            },
        }

        self.assertEqual(
            {
                u'ConsumedCapacityUnits': 2,
            },
            db.layer1.delete_item(TABLE_NAME2, key),
        )
        self.assertNotIn((HK_VALUE2, False), self.t2.store)

    def test_delete_item_h_old(self):
        from ddbmock import connect_boto_patch
        from ddbmock.database.db import dynamodb

        db = connect_boto_patch()

        expected = {
            u'ConsumedCapacityUnits': 1,
            u'Attributes': ITEM2,
        }

        key = {
            u"HashKeyElement": {
                TABLE_HK_TYPE: HK_VALUE
            },
        }

        self.assertEqual(
            expected,
            db.layer1.delete_item(TABLE_NAME2, key, return_values=u'ALL_OLD'),
        )
        self.assertNotIn((HK_VALUE, False), self.t1.store)

    def test_delete_item_hr_missing_r(self):
        from ddbmock import connect_boto_patch
        from ddbmock.database.db import dynamodb
        from boto.dynamodb.exceptions import DynamoDBValidationError

        db = connect_boto_patch()

        key = {
            u"HashKeyElement": {
                TABLE_HK_TYPE: HK_VALUE
            },
        }

        self.assertRaises(DynamoDBValidationError, db.layer1.delete_item,
                          TABLE_NAME, key)

    def test_delete_item_h_missing_h(self):
        from ddbmock import connect_boto_patch
        from ddbmock.database.db import dynamodb
        from boto.dynamodb.exceptions import DynamoDBValidationError

        db = connect_boto_patch()

        key = {}

        self.assertRaises(DynamoDBValidationError, db.layer1.delete_item,
                          TABLE_NAME2, key)

    def test_delete_item_h_expect_field_value_ok(self):
        from ddbmock import connect_boto_patch
        from ddbmock.database.db import dynamodb
        from boto.exception import DynamoDBResponseError

        db = connect_boto_patch()

        ddb_expected = {
            u'relevant_data': {
                u'Exists': True,
                u'Value': {
                    u'B': u'THVkaWEgaXMgdGhlIGJlc3QgY29tcGFueSBldmVyIQ=='
                }
            }
        }

        key = {
            u"HashKeyElement": {
                TABLE_HK_TYPE: HK_VALUE
            },
            u"RangeKeyElement": {
                TABLE_RK_TYPE: RK_VALUE
            },
        }

        db.layer1.delete_item(TABLE_NAME, key, expected=ddb_expected)
        self.assertNotIn((HK_VALUE, False), self.t1.store)

    def test_delete_item_h_expect_field_value_fail(self):
        from ddbmock import connect_boto_patch
        from ddbmock.database.db import dynamodb
        from boto.dynamodb.exceptions import DynamoDBConditionalCheckFailedError

        db = connect_boto_patch()

        ddb_expected = {
            u'relevant_data_et_bah_non': {
                u'Exists': True,
                u'Value': {
                    u'B': u'THVkaWEgaXMgdGhlIGJlc3QgY29tcGFueSBldmVyIQ=='
                }
            }
        }

        key = {
            u"HashKeyElement": {
                TABLE_HK_TYPE: HK_VALUE
            },
            u"RangeKeyElement": {
                TABLE_RK_TYPE: RK_VALUE
            },
        }

        self.assertRaisesRegexp(DynamoDBConditionalCheckFailedError,
                                'ConditionalCheckFailedException',
                                db.layer1.delete_item,
                                TABLE_NAME,
                                key,
                                expected=ddb_expected)
        self.assertEqual(ITEM, self.t1.store[HK_VALUE, RK_VALUE])
Ejemplo n.º 26
0
class TestBatchGetItem(unittest.TestCase):
    def setUp(self):
        from ddbmock.database.db import dynamodb
        from ddbmock.database.table import Table
        from ddbmock.database.key import PrimaryKey

        import helpers
        self.app = helpers.makeTestApp()

        dynamodb.hard_reset()

        hash_key = PrimaryKey(TABLE_HK_NAME, TABLE_HK_TYPE)
        range_key = PrimaryKey(TABLE_RK_NAME, TABLE_RK_TYPE)

        self.t1 = Table(TABLE_NAME1, TABLE_RT, TABLE_WT, hash_key, range_key)
        self.t2 = Table(TABLE_NAME2, TABLE_RT, TABLE_WT, hash_key, None)

        dynamodb.data[TABLE_NAME1] = self.t1
        dynamodb.data[TABLE_NAME2] = self.t2

        self.t1.put(ITEM1, {})
        self.t1.put(ITEM2, {})
        self.t1.put(ITEM3, {})
        self.t2.put(ITEM4, {})
        self.t2.put(ITEM5, {})

    def tearDown(self):
        from ddbmock.database.db import dynamodb
        dynamodb.hard_reset()

    def test_batch_get_item_filter_one(self):
        request = {
            u"RequestItems": {
                TABLE_NAME1: {
                    u"Keys": [
                        {u"HashKeyElement": {TABLE_HK_TYPE: HK_VALUE1},
                         u"RangeKeyElement": {TABLE_RK_TYPE: RK_VALUE1},
                         },
                        {u"HashKeyElement": {TABLE_HK_TYPE: HK_VALUE1},
                         u"RangeKeyElement": {TABLE_RK_TYPE: RK_VALUE1}
                         },
                        ],
                    u"AttributesToGet": [u"relevant_data"],
                    },
                TABLE_NAME2: {
                    u"Keys": [
                        {u"HashKeyElement": {TABLE_HK_TYPE: HK_VALUE3}},
                        ],
                    },
                }
            }

        expected = {
            "Responses": {
                "Table-HR": {
                    "Items": [
                        {"relevant_data": {"S": "tata"}},
                        {"relevant_data": {"S": "tata"}},
                    ],
                    "ConsumedCapacityUnits": 1.0
                },
                "Table-H": {
                    "Items": [
                        {"relevant_data": {"S": "tutu"},
                         "hash_key": {"N": "789"},
                         "range_key": {"S": "Waldo-5"}
                         },
                    ],
                    "ConsumedCapacityUnits": 0.5
                }
            }
        }

        # Protocol check

        res = self.app.post_json('/', request, headers=HEADERS, status=200)
        self.assertEqual(expected, json.loads(res.body))
        self.assertEqual('application/x-amz-json-1.0; charset=UTF-8',
                         res.headers['Content-Type'])

    def test_batch_get_item_filter_one_consistent(self):
        request = {
            u"RequestItems": {
                TABLE_NAME1: {
                    u"Keys": [
                        {u"HashKeyElement": {TABLE_HK_TYPE: HK_VALUE1},
                         u"RangeKeyElement": {TABLE_RK_TYPE: RK_VALUE1}
                         },
                        {u"HashKeyElement": {TABLE_HK_TYPE: HK_VALUE1},
                         u"RangeKeyElement": {TABLE_RK_TYPE: RK_VALUE1}
                         },
                        ],
                    u"AttributesToGet": [u"relevant_data"],
                    u"ConsistentRead": True,
                },
                TABLE_NAME2: {
                    u"Keys": [
                        {u"HashKeyElement": {TABLE_HK_TYPE: HK_VALUE3}},
                    ],
                },
            }
        }

        expected = {
            "Responses": {
                "Table-HR": {
                    "Items": [
                        {"relevant_data": {"S": "tata"}},
                        {"relevant_data": {"S": "tata"}},
                    ],
                    "ConsumedCapacityUnits": 2.0
                },
                "Table-H": {
                    "Items": [
                        {"relevant_data": {"S": "tutu"},
                         "hash_key": {"N": "789"},
                         "range_key": {"S": "Waldo-5"}
                         },
                    ],
                    "ConsumedCapacityUnits": 0.5
                }
            }
        }

        # Protocol check
        res = self.app.post_json('/', request, headers=HEADERS, status=200)
        self.assertEqual(expected, json.loads(res.body))
        self.assertEqual('application/x-amz-json-1.0; charset=UTF-8',
                         res.headers['Content-Type'])
Ejemplo n.º 27
0
class TestUpdateItem(unittest.TestCase):
    def setUp(self):
        from ddbmock.database.db import dynamodb
        from ddbmock.database.table import Table
        from ddbmock.database.key import PrimaryKey

        dynamodb.hard_reset()

        hash_key = PrimaryKey(TABLE_HK_NAME, TABLE_HK_TYPE)
        range_key = PrimaryKey(TABLE_RK_NAME, TABLE_RK_TYPE)

        self.t1 = Table(TABLE_NAME, TABLE_RT, TABLE_WT, hash_key, range_key)
        self.t2 = Table(TABLE_NAME2, TABLE_RT, TABLE_WT, hash_key, None)

        dynamodb.data[TABLE_NAME] = self.t1
        dynamodb.data[TABLE_NAME2] = self.t2

        self.t1.put(cp(ITEM), {})
        self.t2.put(cp(ITEM2), {})

    def tearDown(self):
        from ddbmock.database.db import dynamodb
        from ddbmock import clean_boto_patch

        dynamodb.hard_reset()
        clean_boto_patch()

    def test_update_item_put_hr(self):
        from ddbmock import connect_boto_patch

        db = connect_boto_patch()

        key = {u"HashKeyElement": {TABLE_HK_TYPE: HK_VALUE}, u"RangeKeyElement": {TABLE_RK_TYPE: RK_VALUE}}

        key2 = {u"HashKeyElement": {TABLE_HK_TYPE: HK_VALUE2}, u"RangeKeyElement": {TABLE_RK_TYPE: RK_VALUE}}

        # use PUT as default action, champs existant
        db.layer1.update_item(
            TABLE_NAME, key, {"relevant_data": {"Value": RELEVANT_FIELD}}  # Move type from 'B' to 'S'
        )
        self.assertEqual(RELEVANT_FIELD, self.t1.store[HK_VALUE, RK_VALUE]["relevant_data"])

        # PUT explicite, champ non existant
        db.layer1.update_item(TABLE_NAME, key, {"irelevant_data": {"Action": "PUT", "Value": IRELEVANT_FIELD}})
        self.assertEqual(RELEVANT_FIELD, self.t1.store[HK_VALUE, RK_VALUE]["relevant_data"])
        self.assertEqual(IRELEVANT_FIELD, self.t1.store[HK_VALUE, RK_VALUE]["irelevant_data"])

        # PUT explicite, item non existant(full item creation)
        db.layer1.update_item(TABLE_NAME, key2, {"relevant_data": {"Action": "PUT", "Value": RELEVANT_FIELD}})
        self.assertEqual({TABLE_HK_TYPE: HK_VALUE2}, self.t1.store[HK_VALUE2, RK_VALUE][TABLE_HK_NAME])
        self.assertEqual({TABLE_RK_TYPE: RK_VALUE}, self.t1.store[HK_VALUE2, RK_VALUE][TABLE_RK_NAME])
        self.assertEqual(RELEVANT_FIELD, self.t1.store[HK_VALUE2, RK_VALUE]["relevant_data"])

    def test_update_item_put_h(self):
        from ddbmock import connect_boto_patch

        db = connect_boto_patch()

        key = {u"HashKeyElement": {TABLE_HK_TYPE: HK_VALUE}}

        key2 = {u"HashKeyElement": {TABLE_HK_TYPE: HK_VALUE2}}

        # use PUT as default action, champs existant
        db.layer1.update_item(
            TABLE_NAME2, key, {"relevant_data": {"Value": RELEVANT_FIELD}}  # Move type from 'B' to 'S'
        )
        self.assertEqual(RELEVANT_FIELD, self.t2.store[HK_VALUE, False]["relevant_data"])

        # PUT explicite, champ non existant
        db.layer1.update_item(TABLE_NAME2, key, {"irelevant_data": {"Action": "PUT", "Value": IRELEVANT_FIELD}})
        self.assertEqual(RELEVANT_FIELD, self.t2.store[HK_VALUE, False]["relevant_data"])
        self.assertEqual(IRELEVANT_FIELD, self.t2.store[HK_VALUE, False]["irelevant_data"])

        # PUT explicite, item non existant(full item creation)
        db.layer1.update_item(TABLE_NAME2, key2, {"relevant_data": {"Action": "PUT", "Value": RELEVANT_FIELD}})
        self.assertEqual({TABLE_HK_TYPE: HK_VALUE2}, self.t2.store[HK_VALUE2, False][TABLE_HK_NAME])
        self.assertEqual(RELEVANT_FIELD, self.t2.store[HK_VALUE2, False]["relevant_data"])

    def test_put_check_throughput_max_old_new(self):
        from ddbmock import connect_boto_patch
        from ddbmock.database.db import dynamodb

        db = connect_boto_patch()

        key = {u"HashKeyElement": {TABLE_HK_TYPE: HK_VALUE}}

        self.assertEqual(
            {u"ConsumedCapacityUnits": 1},
            db.layer1.update_item(TABLE_NAME2, key, {FIELD_NAME: {"Action": "PUT", "Value": FIELD_SMALL}}),
        )
        self.assertEqual(
            {u"ConsumedCapacityUnits": 2},
            db.layer1.update_item(TABLE_NAME2, key, {FIELD_NAME: {"Action": "PUT", "Value": FIELD_BIG}}),
        )
        self.assertEqual(
            {u"ConsumedCapacityUnits": 2},
            db.layer1.update_item(TABLE_NAME2, key, {FIELD_NAME: {"Action": "PUT", "Value": FIELD_SMALL}}),
        )

    def test_update_item_delete_primary_key_fails(self):
        from ddbmock import connect_boto_patch
        from boto.dynamodb.exceptions import DynamoDBValidationError

        db = connect_boto_patch()

        key = {u"HashKeyElement": {TABLE_HK_TYPE: HK_VALUE}, u"RangeKeyElement": {TABLE_RK_TYPE: RK_VALUE}}

        self.assertRaises(
            DynamoDBValidationError, db.layer1.update_item, TABLE_NAME, key, {TABLE_RK_NAME: {"Action": "DELETE"}}
        )
        self.assertEqual({TABLE_RK_TYPE: RK_VALUE}, self.t1.store[HK_VALUE, RK_VALUE][TABLE_RK_NAME])

        self.assertRaises(
            DynamoDBValidationError, db.layer1.update_item, TABLE_NAME, key, {TABLE_HK_NAME: {"Action": "DELETE"}}
        )
        self.assertEqual({TABLE_HK_TYPE: HK_VALUE}, self.t1.store[HK_VALUE, RK_VALUE][TABLE_HK_NAME])

    def test_update_item_delete_field_ok(self):
        from ddbmock import connect_boto_patch
        from boto.dynamodb.exceptions import DynamoDBValidationError

        db = connect_boto_patch()

        key = {u"HashKeyElement": {TABLE_HK_TYPE: HK_VALUE}, u"RangeKeyElement": {TABLE_RK_TYPE: RK_VALUE}}

        db.layer1.update_item(TABLE_NAME, key, {FIELD_NAME: {"Action": "DELETE"}})
        self.assertNotIn(FIELD_NAME, self.t1.store[HK_VALUE, RK_VALUE])

        # Attempt to delete non-existing field, do nothing
        db.layer1.update_item(TABLE_NAME, key, {FIELD_NAME_404: {"Action": "DELETE"}})

    def test_update_item_delete_field_set_ok(self):
        from ddbmock import connect_boto_patch
        from boto.dynamodb.exceptions import DynamoDBValidationError

        db = connect_boto_patch()

        expected1 = {u"SS": [u"item1", u"item2", u"item3", u"item4"]}
        expected2 = {u"SS": [u"item3", u"item1"]}

        key = {u"HashKeyElement": {TABLE_HK_TYPE: HK_VALUE}, u"RangeKeyElement": {TABLE_RK_TYPE: RK_VALUE}}

        # Can not remove a scalar value, even from a set
        self.assertRaises(
            DynamoDBValidationError,
            db.layer1.update_item,
            TABLE_NAME,
            key,
            {FIELD_SET_NAME: {"Action": "DELETE", u"Value": {u"S": u"item1"}}},
        )
        self.assertEqual(expected1, self.t1.store[HK_VALUE, RK_VALUE][FIELD_SET_NAME])

        # remove a couple of existing or not item from the field
        db.layer1.update_item(
            TABLE_NAME, key, {FIELD_SET_NAME: {"Action": "DELETE", u"Value": {u"SS": [u"item2", u"item4", u"item6"]}}}
        )
        self.assertEqual(expected2, self.t1.store[HK_VALUE, RK_VALUE][FIELD_SET_NAME])

        # Field shoud disapear (Empty)
        db.layer1.update_item(
            TABLE_NAME, key, {FIELD_SET_NAME: {"Action": "DELETE", u"Value": {u"SS": [u"item1", u"item3", u"item6"]}}}
        )
        self.assertNotIn(FIELD_SET_NAME, self.t1.store[HK_VALUE, RK_VALUE])

    def test_update_item_delete_field_set_bad_type(self):
        from ddbmock import connect_boto_patch
        from boto.dynamodb.exceptions import DynamoDBValidationError

        db = connect_boto_patch()

        expected = {u"SS": [u"item1", u"item2", u"item3", u"item4"]}

        key = {u"HashKeyElement": {TABLE_HK_TYPE: HK_VALUE}, u"RangeKeyElement": {TABLE_RK_TYPE: RK_VALUE}}

        self.assertRaises(
            DynamoDBValidationError,
            db.layer1.update_item,
            TABLE_NAME,
            key,
            {FIELD_SET_NAME: {"Action": "DELETE", u"Value": {u"B": u"item1"}}},
        )
        self.assertEqual(expected, self.t1.store[HK_VALUE, RK_VALUE][FIELD_SET_NAME])

        self.assertRaises(
            DynamoDBValidationError,
            db.layer1.update_item,
            TABLE_NAME,
            key,
            {FIELD_SET_NAME: {"Action": "DELETE", u"Value": {u"BS": [u"item2", u"item4", u"item6"]}}},
        )
        self.assertEqual(expected, self.t1.store[HK_VALUE, RK_VALUE][FIELD_SET_NAME])

    def test_update_item_increment(self):
        from ddbmock import connect_boto_patch
        from boto.dynamodb.exceptions import DynamoDBValidationError

        db = connect_boto_patch()

        key = {u"HashKeyElement": {TABLE_HK_TYPE: HK_VALUE}}

        ADD_VALUE = 2

        expected = {u"N": unicode(42 + ADD_VALUE)}

        # regular increment
        db.layer1.update_item(
            TABLE_NAME2, key, {FIELD_NUM_NAME: {"Action": "ADD", u"Value": {u"N": unicode(ADD_VALUE)}}}
        )
        self.assertEqual(expected, self.t2.store[HK_VALUE, False][FIELD_NUM_NAME])

    def test_update_item_push_to_set_ok(self):
        from ddbmock import connect_boto_patch
        from boto.dynamodb.exceptions import DynamoDBValidationError

        db = connect_boto_patch()

        expected1 = {u"SS": [u"item1", u"item2", u"item3", u"item4"]}
        expected2 = {u"SS": [u"item2", u"item3", u"item1", u"item4", u"item5"]}

        key = {u"HashKeyElement": {TABLE_HK_TYPE: HK_VALUE}, u"RangeKeyElement": {TABLE_RK_TYPE: RK_VALUE}}

        self.assertRaises(
            DynamoDBValidationError,
            db.layer1.update_item,
            TABLE_NAME,
            key,
            {FIELD_SET_NAME: {"Action": "ADD", u"Value": {u"S": u"item5"}}},
        )
        self.assertEqual(expected1, self.t1.store[HK_VALUE, RK_VALUE][FIELD_SET_NAME])

        db.layer1.update_item(TABLE_NAME, key, {FIELD_SET_NAME: {"Action": "ADD", u"Value": {u"SS": [u"item5"]}}})
        self.assertEqual(expected2, self.t1.store[HK_VALUE, RK_VALUE][FIELD_SET_NAME])

    def test_update_item_push_to_non_set_fail(self):
        # sometimes weird black magic types occures in test. these are related
        # to internal "DB" logic. it does not affect real API output at all
        from ddbmock import connect_boto_patch
        from boto.dynamodb.exceptions import DynamoDBValidationError

        db = connect_boto_patch()

        expected1 = {u"SS": [u"item1", u"item2", u"item3", u"item4"]}

        key = {u"HashKeyElement": {TABLE_HK_TYPE: HK_VALUE}, u"RangeKeyElement": {TABLE_RK_TYPE: RK_VALUE}}

        self.assertRaises(
            DynamoDBValidationError,
            db.layer1.update_item,
            TABLE_NAME,
            key,
            {FIELD_NAME: {"Action": "ADD", u"Value": {u"B": u"item5"}}},
        )
        self.assertEqual(expected1, self.t1.store[HK_VALUE, RK_VALUE][FIELD_SET_NAME])

    def test_update_return_all_old(self):
        from ddbmock import connect_boto_patch
        from boto.dynamodb.exceptions import DynamoDBValidationError

        key = {u"HashKeyElement": {TABLE_HK_TYPE: HK_VALUE}}
        ADD_VALUE = 1

        db = connect_boto_patch()
        expected = cp(ITEM2)

        # regular increment
        ret = db.layer1.update_item(
            TABLE_NAME2,
            key,
            {FIELD_NUM_NAME: {"Action": "ADD", u"Value": {u"N": unicode(ADD_VALUE)}}},
            return_values=u"ALL_OLD",
        )
        self.assertEqual(expected, ret[u"Attributes"])

    def test_update_return_all_new(self):
        from ddbmock import connect_boto_patch
        from boto.dynamodb.exceptions import DynamoDBValidationError

        key = {u"HashKeyElement": {TABLE_HK_TYPE: HK_VALUE}}
        ADD_VALUE = 1

        db = connect_boto_patch()
        expected = cp(ITEM2)
        expected[FIELD_NUM_NAME][u"N"] = unicode(int(expected[FIELD_NUM_NAME][u"N"]) + ADD_VALUE)

        # regular increment
        ret = db.layer1.update_item(
            TABLE_NAME2,
            key,
            {FIELD_NUM_NAME: {"Action": "ADD", u"Value": {u"N": unicode(ADD_VALUE)}}},
            return_values=u"ALL_NEW",
        )
        self.assertEqual(expected, ret[u"Attributes"])

    def test_update_return_updated_old(self):
        from ddbmock import connect_boto_patch
        from boto.dynamodb.exceptions import DynamoDBValidationError

        key = {u"HashKeyElement": {TABLE_HK_TYPE: HK_VALUE}}
        ADD_VALUE = 1

        db = connect_boto_patch()
        expected = {FIELD_NUM_NAME: cp(ITEM2[FIELD_NUM_NAME])}

        # regular increment
        ret = db.layer1.update_item(
            TABLE_NAME2,
            key,
            {FIELD_NUM_NAME: {"Action": "ADD", u"Value": {u"N": unicode(ADD_VALUE)}}},
            return_values=u"UPDATED_OLD",
        )
        self.assertEqual(expected, ret[u"Attributes"])

    def test_update_return_updated_new(self):
        from ddbmock import connect_boto_patch
        from boto.dynamodb.exceptions import DynamoDBValidationError

        key = {u"HashKeyElement": {TABLE_HK_TYPE: HK_VALUE}}
        ADD_VALUE = 1

        db = connect_boto_patch()
        expected = {FIELD_NUM_NAME: cp(ITEM2[FIELD_NUM_NAME])}
        expected[FIELD_NUM_NAME][u"N"] = unicode(int(expected[FIELD_NUM_NAME][u"N"]) + ADD_VALUE)

        # regular increment
        ret = db.layer1.update_item(
            TABLE_NAME2,
            key,
            {FIELD_NUM_NAME: {"Action": "ADD", u"Value": {u"N": unicode(ADD_VALUE)}}},
            return_values=u"UPDATED_NEW",
        )
        self.assertEqual(expected, ret[u"Attributes"])

    def test_update_item_put_h_oversized(self):
        from boto.dynamodb.exceptions import DynamoDBValidationError
        from ddbmock import connect_boto_patch

        db = connect_boto_patch()

        key = {u"HashKeyElement": {TABLE_HK_TYPE: HK_VALUE}}

        # PUT explicite, existing field
        self.assertRaisesRegexp(
            DynamoDBValidationError,
            "Item size.*exceeded",
            db.layer1.update_item,
            TABLE_NAME2,
            key,
            {"relevant_data": {"Value": RELEVANT_HUGE_FIELD}},
        )
        self.assertEqual(ITEM[FIELD_NAME], self.t2.store[HK_VALUE, False]["relevant_data"])
Ejemplo n.º 28
0
 def setUp(self):
     from ddbmock.database.table import Table
     self.table = Table(NAME, RT, WT, None, None, status="ACTIVE")
Ejemplo n.º 29
0
class TestQuery(unittest.TestCase):
    def setUp(self):
        from ddbmock.database.db import dynamodb
        from ddbmock.database.table import Table
        from ddbmock.database.key import PrimaryKey

        dynamodb.hard_reset()

        hash_key = PrimaryKey(TABLE_HK_NAME, TABLE_HK_TYPE)
        range_key = PrimaryKey(TABLE_RK_NAME, TABLE_RK_TYPE)

        self.t1 = Table(TABLE_NAME, TABLE_RT, TABLE_WT, hash_key, range_key)

        dynamodb.data[TABLE_NAME]  = self.t1

        self.t1.put(ITEM1, {})
        self.t1.put(ITEM2, {})
        self.t1.put(ITEM3, {})
        self.t1.put(ITEM4, {})
        self.t1.put(ITEM5, {})

    def tearDown(self):
        from ddbmock.database.db import dynamodb
        from ddbmock import clean_boto_patch
        dynamodb.hard_reset()
        clean_boto_patch()

    def test_query_all(self):
        from ddbmock import connect_boto_patch
        from ddbmock.database.db import dynamodb

        expected = {
            u"Count": 5,
            u"Items": [ITEM1, ITEM2, ITEM3, ITEM4, ITEM5],
            u"ConsumedCapacityUnits": 0.5,
        }

        db = connect_boto_patch()

        ret = db.layer1.query(TABLE_NAME, {TABLE_HK_TYPE: HK_VALUE})
        self.assertEqual(expected, ret)

    # Regression test for #9
    def test_query_all_404(self):
        from ddbmock import connect_boto_patch
        from ddbmock.database.db import dynamodb

        expected = {
            u"Count": 0,
            u'Items': [],
            u"ConsumedCapacityUnits": 0.5,
        }

        db = connect_boto_patch()

        ret = db.layer1.query(TABLE_NAME, {TABLE_HK_TYPE: HK_VALUE_404})
        self.assertEqual(expected, ret)

    def test_query_2_first(self):
        from ddbmock import connect_boto_patch
        from ddbmock.database.db import dynamodb

        expected = {
            u"Count": 2,
            u"Items": [ITEM1, ITEM2],
            u"ConsumedCapacityUnits": 0.5,
            u'LastEvaluatedKey': {
                u'HashKeyElement': {u'N': u'123'},
                u'RangeKeyElement': {u'S': u'Waldo-2'},
            },
        }

        db = connect_boto_patch()

        ret = db.layer1.query(TABLE_NAME, {TABLE_HK_TYPE: HK_VALUE}, limit=2)
        self.assertEqual(expected, ret)

    def test_query_paged(self):
        from ddbmock import connect_boto_patch
        from ddbmock.database.db import dynamodb
        from boto.dynamodb.exceptions import DynamoDBValidationError

        esk = {
            u'HashKeyElement': {u'N': u'123'},
            u'RangeKeyElement': {u'S': u'Waldo-3'},
        }

        bad_esk = {
            u'HashKeyElement': {u'N': u'123.43'},
            u'RangeKeyElement': {u'S': u'Waldo-3'},
        }

        expected1 = {
            u"Count": 3,
            u"Items": [ITEM1, ITEM2, ITEM3],
            u"ConsumedCapacityUnits": 0.5,
            u'LastEvaluatedKey': esk,
        }
        expected2 = {
            u"Count": 2,
            u"Items": [ITEM4, ITEM5],
            u"ConsumedCapacityUnits": 0.5,
        }

        db = connect_boto_patch()

        ret = db.layer1.query(TABLE_NAME, {TABLE_HK_TYPE: HK_VALUE}, limit=3)
        self.assertEqual(expected1, ret)
        ret = db.layer1.query(TABLE_NAME, {TABLE_HK_TYPE: HK_VALUE}, limit=3, exclusive_start_key=esk)
        self.assertEqual(expected2, ret)
        self.assertRaises(DynamoDBValidationError,
                          db.layer1.query,
                          TABLE_NAME, {TABLE_HK_TYPE: HK_VALUE}, limit=3, exclusive_start_key=bad_esk)

    def test_query_2_last(self):
        from ddbmock import connect_boto_patch
        from ddbmock.database.db import dynamodb

        expected = {
            u"Count": 2,
            u"Items": [ITEM5, ITEM4],
            u"ConsumedCapacityUnits": 0.5,
            u'LastEvaluatedKey': {
                u'HashKeyElement': {u'N': u'123'},
                u'RangeKeyElement': {u'S': u'Waldo-4'},
            }
        }

        db = connect_boto_patch()

        ret = db.layer1.query(TABLE_NAME, {TABLE_HK_TYPE: HK_VALUE}, limit=2, scan_index_forward=False)
        self.assertEqual(expected, ret)

    def test_query_all_filter_fields(self):
        from ddbmock import connect_boto_patch
        from ddbmock.database.db import dynamodb

        expected = {
            u"Count": 5,
            u"Items": [
                {u"relevant_data": {u"S": "tata"}},
                {u"relevant_data": {u"S": "tete"}},
                {u"relevant_data": {u"S": "titi"}},
                {u"relevant_data": {u"S": "toto"}},
                {u"relevant_data": {u"S": "tutu"}},
            ],
            u"ConsumedCapacityUnits": 0.5,
        }
        fields = [u'relevant_data']

        db = connect_boto_patch()

        ret = db.layer1.query(TABLE_NAME, {TABLE_HK_TYPE: HK_VALUE}, None, fields)
        self.assertEqual(expected, ret)

    # No need to test all conditions/type mismatch as they are unit tested
    def test_query_condition_filter_fields(self):
        from ddbmock import connect_boto_patch
        from ddbmock.database.db import dynamodb

        expected = {
            u"Count": 3,
            u"Items": [
                {u"relevant_data": {u"S": u"titi"}},
                {u"relevant_data": {u"S": u"toto"}},
                {u"relevant_data": {u"S": u"tutu"}},
            ],
            u"ConsumedCapacityUnits": 0.5,
        }

        condition = {"AttributeValueList":[{"S":"Waldo-2"}],"ComparisonOperator":"GT"}
        fields = [u'relevant_data']

        db = connect_boto_patch()

        ret = db.layer1.query(TABLE_NAME, {TABLE_HK_TYPE: HK_VALUE}, condition, fields)
        self.assertEqual(expected, ret)

    def test_query_all_consistent(self):
        from ddbmock import connect_boto_patch
        from ddbmock.database.db import dynamodb

        expected = {
            u"Count": 5,
            u"Items": [ITEM1, ITEM2, ITEM3, ITEM4, ITEM5],
            u"ConsumedCapacityUnits": 1,
        }

        db = connect_boto_patch()

        ret = db.layer1.query(TABLE_NAME, {TABLE_HK_TYPE: HK_VALUE}, consistent_read=True)
        self.assertEqual(expected, ret)

    def test_query_invalid_condition_multiple_data_in_field(self):
        from ddbmock import connect_boto_patch
        from ddbmock.database.db import dynamodb
        from boto.dynamodb.exceptions import DynamoDBValidationError

        condition = {
            "AttributeValueList":[
                {"S":"Waldo-2"},
                {"S":"Waldo-3"},
            ],
            "ComparisonOperator":"GT"
        }
        fields = [u'relevant_data']

        db = connect_boto_patch()

        self.assertRaises(DynamoDBValidationError,
                          db.layer1.query,
                          TABLE_NAME, {TABLE_HK_TYPE: HK_VALUE}, condition, fields)
Ejemplo n.º 30
0
class TestScan(unittest.TestCase):
    def setUp(self):
        from ddbmock.database.db import dynamodb
        from ddbmock.database.table import Table
        from ddbmock.database.key import PrimaryKey

        import helpers
        self.app = helpers.makeTestApp()
        dynamodb.hard_reset()

        hash_key = PrimaryKey(TABLE_HK_NAME, TABLE_HK_TYPE)
        range_key = PrimaryKey(TABLE_RK_NAME, TABLE_RK_TYPE)

        self.t1 = Table(TABLE_NAME, TABLE_RT, TABLE_WT, hash_key, range_key)

        dynamodb.data[TABLE_NAME] = self.t1

        self.t1.put(ITEM1, {})
        self.t1.put(ITEM2, {})
        self.t1.put(ITEM3, {})
        self.t1.put(ITEM4, {})
        self.t1.put(ITEM5, {})

    def tearDown(self):
        from ddbmock.database.db import dynamodb
        dynamodb.hard_reset()

    def test_scan_condition_filter_fields(self):
        request = {
            "TableName": TABLE_NAME,
            "ScanFilter": {
                "relevant_data": {
                    "AttributeValueList": [
                        {"S":"toto"},
                        {"S":"titi"},
                        {"S":"tata"},
                        ],
                    "ComparisonOperator": "IN",
                },
            },
            "AttributesToGet": [u'relevant_data'],
        }

        expected = {
            u"Count": 3,
            u"ScannedCount": 5,
            u"Items": [
                {u"relevant_data": {u"S": u"tata"}},
                {u"relevant_data": {u"S": u"toto"}},
                {u"relevant_data": {u"S": u"titi"}},
            ],
            u"ConsumedCapacityUnits": 0.5,
        }

        # Protocol check
        res = self.app.post_json('/', request, headers=HEADERS, status=200)
        self.assertEqual(expected, json.loads(res.body))
        self.assertEqual('application/x-amz-json-1.0; charset=UTF-8',
                         res.headers['Content-Type'])

    def test_scan_count_and_attrs_to_get_fails(self):
        request = {
            "TableName": TABLE_NAME,
            "ScanFilter": {
                "relevant_data": {
                    "AttributeValueList": [
                        {"S":"toto"},
                        {"S":"titi"},
                        {"S":"tata"},
                        ],
                    "ComparisonOperator": "IN",
                },
            },
            "AttributesToGet": [u'relevant_data'],
            "Count": True,
        }

        expected = {
            u'__type': u'com.amazonaws.dynamodb.v20120810#ValidationException',
            u'message': u'Can not filter fields when only count is requested'
        }

        # Protocol check
        res = self.app.post_json('/', request, headers=HEADERS, status=400)
        self.assertEqual(expected, json.loads(res.body))
        self.assertEqual('application/x-amz-json-1.0; charset=UTF-8',
                         res.headers['Content-Type'])
Ejemplo n.º 31
0
class TestBatchWriteItem(unittest.TestCase):
    def setUp(self):
        from ddbmock.database.db import dynamodb
        from ddbmock.database.table import Table
        from ddbmock.database.key import PrimaryKey

        dynamodb.hard_reset()

        hash_key = PrimaryKey(TABLE_HK_NAME, TABLE_HK_TYPE)
        range_key = PrimaryKey(TABLE_RK_NAME, TABLE_RK_TYPE)

        self.t1 = Table(TABLE_NAME1, TABLE_RT, TABLE_WT, hash_key, range_key)
        self.t2 = Table(TABLE_NAME2, TABLE_RT, TABLE_WT, hash_key, None)

        dynamodb.data[TABLE_NAME1] = self.t1
        dynamodb.data[TABLE_NAME2] = self.t2

        self.t1.put(ITEM1, {})
        self.t2.put(ITEM4, {})

    def tearDown(self):
        from ddbmock.database.db import dynamodb
        from ddbmock import clean_boto_patch
        dynamodb.hard_reset()
        clean_boto_patch()

    def test_batch_write_item_nominal(self):
        from ddbmock import connect_boto_patch
        from ddbmock.database.db import dynamodb

        db = connect_boto_patch()

        expected = {
            "Responses": {
                TABLE_NAME1: {
                    "ConsumedCapacityUnits": 3
                },
                TABLE_NAME2: {
                    "ConsumedCapacityUnits": 2
                }
            }
        }

        ret = db.layer1.batch_write_item({
            TABLE_NAME1: [
                {
                    u"DeleteRequest": {
                        u"Key": {
                            u"HashKeyElement": {
                                TABLE_HK_TYPE: HK_VALUE1
                            },
                            u"RangeKeyElement": {
                                TABLE_RK_TYPE: RK_VALUE1
                            },
                        },
                    },
                },
                {
                    u"PutRequest": {
                        u"Item": ITEM2
                    }
                },
                {
                    u"PutRequest": {
                        u"Item": ITEM3
                    }
                },
            ],
            TABLE_NAME2: [
                {
                    u"DeleteRequest": {
                        u"Key": {
                            u"HashKeyElement": {
                                TABLE_HK_TYPE: HK_VALUE2
                            },
                        },
                    },
                },
                {
                    u"PutRequest": {
                        u"Item": ITEM5
                    }
                },
            ],
        })

        self.assertEqual(expected, ret)

    def test_batch_write_item_table_404(self):
        from ddbmock import connect_boto_patch
        from ddbmock.database.db import dynamodb
        from boto.exception import BotoServerError

        db = connect_boto_patch()

        self.assertRaises(
            BotoServerError, db.layer1.batch_write_item, {
                TABLE_NAME_404: [
                    {
                        u"DeleteRequest": {
                            u"Key": {
                                u"HashKeyElement": {
                                    TABLE_HK_TYPE: HK_VALUE1
                                },
                                u"RangeKeyElement": {
                                    TABLE_RK_TYPE: RK_VALUE1
                                },
                            },
                        },
                    },
                    {
                        u"PutRequest": {
                            u"Item": ITEM2
                        }
                    },
                    {
                        u"PutRequest": {
                            u"Item": ITEM3
                        }
                    },
                ],
                TABLE_NAME2: [
                    {
                        u"DeleteRequest": {
                            u"Key": {
                                u"HashKeyElement": {
                                    TABLE_HK_TYPE: HK_VALUE2
                                },
                            },
                        },
                    },
                    {
                        u"PutRequest": {
                            u"Item": ITEM5
                        }
                    },
                ],
            })
Ejemplo n.º 32
0
class TestUpdateItem(unittest.TestCase):
    def setUp(self):
        from ddbmock.database.db import dynamodb
        from ddbmock.database.table import Table
        from ddbmock.database.key import PrimaryKey

        dynamodb.hard_reset()

        hash_key = PrimaryKey(TABLE_HK_NAME, TABLE_HK_TYPE)
        range_key = PrimaryKey(TABLE_RK_NAME, TABLE_RK_TYPE)

        self.t1 = Table(TABLE_NAME, TABLE_RT, TABLE_WT, hash_key, range_key)
        self.t2 = Table(TABLE_NAME2, TABLE_RT, TABLE_WT, hash_key, None)

        dynamodb.data[TABLE_NAME]  = self.t1
        dynamodb.data[TABLE_NAME2] = self.t2

        self.t1.put(cp(ITEM), {})
        self.t2.put(cp(ITEM2), {})

    def tearDown(self):
        from ddbmock.database.db import dynamodb
        from ddbmock import clean_boto_patch
        dynamodb.hard_reset()
        clean_boto_patch()

    def test_update_item_put_hr(self):
        from ddbmock import connect_boto_patch
        db = connect_boto_patch()

        key = {
            u"HashKeyElement":  {TABLE_HK_TYPE: HK_VALUE},
            u"RangeKeyElement": {TABLE_RK_TYPE: RK_VALUE},
        }

        key2 = {
            u"HashKeyElement":  {TABLE_HK_TYPE: HK_VALUE2},
            u"RangeKeyElement": {TABLE_RK_TYPE: RK_VALUE},
        }

        # use PUT as default action, champs existant
        db.layer1.update_item(TABLE_NAME, key, {
            'relevant_data': {'Value': RELEVANT_FIELD}  # Move type from 'B' to 'S'
        })
        self.assertEqual(RELEVANT_FIELD, self.t1.store[HK_VALUE, RK_VALUE]['relevant_data'])

        # PUT explicite, champ non existant
        db.layer1.update_item(TABLE_NAME, key, {
            'irelevant_data': {'Action': 'PUT', 'Value': IRELEVANT_FIELD}
        })
        self.assertEqual(RELEVANT_FIELD, self.t1.store[HK_VALUE, RK_VALUE]['relevant_data'])
        self.assertEqual(IRELEVANT_FIELD, self.t1.store[HK_VALUE, RK_VALUE]['irelevant_data'])

        # PUT explicite, item non existant(full item creation)
        db.layer1.update_item(TABLE_NAME, key2, {
            'relevant_data': {'Action': 'PUT', 'Value': RELEVANT_FIELD}
        })
        self.assertEqual({TABLE_HK_TYPE: HK_VALUE2}, self.t1.store[HK_VALUE2, RK_VALUE][TABLE_HK_NAME])
        self.assertEqual({TABLE_RK_TYPE: RK_VALUE}, self.t1.store[HK_VALUE2, RK_VALUE][TABLE_RK_NAME])
        self.assertEqual(RELEVANT_FIELD, self.t1.store[HK_VALUE2, RK_VALUE]['relevant_data'])

    def test_update_item_put_h(self):
        from ddbmock import connect_boto_patch
        db = connect_boto_patch()

        key = {
            u"HashKeyElement":  {TABLE_HK_TYPE: HK_VALUE},
        }

        key2 = {
            u"HashKeyElement":  {TABLE_HK_TYPE: HK_VALUE2},
        }

        # use PUT as default action, champs existant
        db.layer1.update_item(TABLE_NAME2, key, {
            'relevant_data': {'Value': RELEVANT_FIELD}  # Move type from 'B' to 'S'
        })
        self.assertEqual(RELEVANT_FIELD, self.t2.store[HK_VALUE, False]['relevant_data'])

        # PUT explicite, champ non existant
        db.layer1.update_item(TABLE_NAME2, key, {
            'irelevant_data': {'Action': 'PUT', 'Value': IRELEVANT_FIELD}
        })
        self.assertEqual(RELEVANT_FIELD, self.t2.store[HK_VALUE, False]['relevant_data'])
        self.assertEqual(IRELEVANT_FIELD, self.t2.store[HK_VALUE, False]['irelevant_data'])

        # PUT explicite, item non existant(full item creation)
        db.layer1.update_item(TABLE_NAME2, key2, {
            'relevant_data': {'Action': 'PUT', 'Value': RELEVANT_FIELD}
        })
        self.assertEqual({TABLE_HK_TYPE: HK_VALUE2}, self.t2.store[HK_VALUE2, False][TABLE_HK_NAME])
        self.assertEqual(RELEVANT_FIELD, self.t2.store[HK_VALUE2, False]['relevant_data'])

    def test_put_check_throughput_max_old_new(self):
        from ddbmock import connect_boto_patch
        from ddbmock.database.db import dynamodb

        db = connect_boto_patch()

        key = {u"HashKeyElement":  {TABLE_HK_TYPE: HK_VALUE}}

        self.assertEqual(
            {u'ConsumedCapacityUnits': 1},
            db.layer1.update_item(TABLE_NAME2, key,
                                  {FIELD_NAME: {'Action': 'PUT', 'Value': FIELD_SMALL}}),
        )
        self.assertEqual(
            {u'ConsumedCapacityUnits': 2},
            db.layer1.update_item(TABLE_NAME2, key,
                                  {FIELD_NAME: {'Action': 'PUT', 'Value': FIELD_BIG}}),
        )
        self.assertEqual(
            {u'ConsumedCapacityUnits': 2},
            db.layer1.update_item(TABLE_NAME2, key,
                                  {FIELD_NAME: {'Action': 'PUT', 'Value': FIELD_SMALL}}),
        )

    def test_update_item_delete_primary_key_fails(self):
        from ddbmock import connect_boto_patch
        from boto.dynamodb.exceptions import DynamoDBValidationError

        db = connect_boto_patch()

        key = {
            u"HashKeyElement":  {TABLE_HK_TYPE: HK_VALUE},
            u"RangeKeyElement": {TABLE_RK_TYPE: RK_VALUE},
        }

        self.assertRaises(DynamoDBValidationError,
            db.layer1.update_item,
            TABLE_NAME, key, {TABLE_RK_NAME: {'Action': 'DELETE'}}
        )
        self.assertEqual({TABLE_RK_TYPE: RK_VALUE}, self.t1.store[HK_VALUE, RK_VALUE][TABLE_RK_NAME])

        self.assertRaises(DynamoDBValidationError,
            db.layer1.update_item,
            TABLE_NAME, key, {TABLE_HK_NAME: {'Action': 'DELETE'}}
        )
        self.assertEqual({TABLE_HK_TYPE: HK_VALUE}, self.t1.store[HK_VALUE, RK_VALUE][TABLE_HK_NAME])

    def test_update_item_delete_field_ok(self):
        from ddbmock import connect_boto_patch
        from boto.dynamodb.exceptions import DynamoDBValidationError

        db = connect_boto_patch()

        key = {
            u"HashKeyElement":  {TABLE_HK_TYPE: HK_VALUE},
            u"RangeKeyElement": {TABLE_RK_TYPE: RK_VALUE},
        }

        db.layer1.update_item(TABLE_NAME, key, {
            FIELD_NAME: {'Action': 'DELETE'},
        })
        self.assertNotIn(FIELD_NAME, self.t1.store[HK_VALUE, RK_VALUE])

        # Attempt to delete non-existing field, do nothing
        db.layer1.update_item(TABLE_NAME, key, {
            FIELD_NAME_404: {'Action': 'DELETE'},
        })

    def test_update_item_delete_field_set_ok(self):
        from ddbmock import connect_boto_patch
        from boto.dynamodb.exceptions import DynamoDBValidationError

        db = connect_boto_patch()

        expected1 = {u'SS': [u'item1', u'item2', u'item3', u'item4']}
        expected2 = {u'SS': [u'item3', u'item1']}

        key = {
            u"HashKeyElement":  {TABLE_HK_TYPE: HK_VALUE},
            u"RangeKeyElement": {TABLE_RK_TYPE: RK_VALUE},
        }

        # Can not remove a scalar value, even from a set
        self.assertRaises(DynamoDBValidationError,
            db.layer1.update_item,
            TABLE_NAME, key, {
                FIELD_SET_NAME: {'Action': 'DELETE', u'Value': {u'S': u'item1'}},
            }
        )
        self.assertEqual(expected1, self.t1.store[HK_VALUE, RK_VALUE][FIELD_SET_NAME])

        # remove a couple of existing or not item from the field
        db.layer1.update_item(TABLE_NAME, key, {
            FIELD_SET_NAME: {'Action': 'DELETE', u'Value': {u'SS': [u'item2', u'item4', u'item6']}},
        })
        self.assertEqual(expected2, self.t1.store[HK_VALUE, RK_VALUE][FIELD_SET_NAME])

        # Field shoud disapear (Empty)
        db.layer1.update_item(TABLE_NAME, key, {
            FIELD_SET_NAME: {'Action': 'DELETE', u'Value': {u'SS': [u'item1', u'item3', u'item6']}},
        })
        self.assertNotIn(FIELD_SET_NAME, self.t1.store[HK_VALUE, RK_VALUE])

    def test_update_item_delete_field_set_bad_type(self):
        from ddbmock import connect_boto_patch
        from boto.dynamodb.exceptions import DynamoDBValidationError

        db = connect_boto_patch()

        expected = {u'SS': [u'item1', u'item2', u'item3', u'item4']}

        key = {
            u"HashKeyElement":  {TABLE_HK_TYPE: HK_VALUE},
            u"RangeKeyElement": {TABLE_RK_TYPE: RK_VALUE},
        }

        self.assertRaises(DynamoDBValidationError,
            db.layer1.update_item,
            TABLE_NAME, key, {
                FIELD_SET_NAME: {'Action': 'DELETE', u'Value': {u'B': u'item1'}},
            }
        )
        self.assertEqual(expected, self.t1.store[HK_VALUE, RK_VALUE][FIELD_SET_NAME])

        self.assertRaises(DynamoDBValidationError,
            db.layer1.update_item,
            TABLE_NAME, key, {
                FIELD_SET_NAME: {'Action': 'DELETE', u'Value': {u'BS': [u'item2', u'item4', u'item6']}},
            }
        )
        self.assertEqual(expected, self.t1.store[HK_VALUE, RK_VALUE][FIELD_SET_NAME])

    def test_update_item_increment(self):
        from ddbmock import connect_boto_patch
        from boto.dynamodb.exceptions import DynamoDBValidationError

        db = connect_boto_patch()

        key = {
            u"HashKeyElement":  {TABLE_HK_TYPE: HK_VALUE},
        }

        ADD_VALUE = 2

        expected = {u'N': unicode(42 + ADD_VALUE)}

        # regular increment
        db.layer1.update_item(TABLE_NAME2, key, {
            FIELD_NUM_NAME: {'Action': 'ADD', u'Value': {u'N': unicode(ADD_VALUE)}},
        })
        self.assertEqual(expected, self.t2.store[HK_VALUE, False][FIELD_NUM_NAME])

    def test_update_item_push_to_set_ok(self):
        from ddbmock import connect_boto_patch
        from boto.dynamodb.exceptions import DynamoDBValidationError

        db = connect_boto_patch()

        expected1 = {u'SS': [u'item1', u'item2', u'item3', u'item4']}
        expected2 = {u'SS': [u'item2', u'item3', u'item1', u'item4', u'item5']}

        key = {
            u"HashKeyElement":  {TABLE_HK_TYPE: HK_VALUE},
            u"RangeKeyElement": {TABLE_RK_TYPE: RK_VALUE},
        }

        self.assertRaises(DynamoDBValidationError,
            db.layer1.update_item,
            TABLE_NAME, key, {
                FIELD_SET_NAME: {'Action': 'ADD', u'Value': {u'S': u'item5'}},
            }
        )
        self.assertEqual(expected1, self.t1.store[HK_VALUE, RK_VALUE][FIELD_SET_NAME])

        db.layer1.update_item(TABLE_NAME, key, {
            FIELD_SET_NAME: {'Action': 'ADD', u'Value': {u'SS': [u'item5']}},
        })
        self.assertEqual(expected2, self.t1.store[HK_VALUE, RK_VALUE][FIELD_SET_NAME])

    def test_update_item_push_to_non_set_fail(self):
        # sometimes weird black magic types occures in test. these are related
        # to internal "DB" logic. it does not affect real API output at all
        from ddbmock import connect_boto_patch
        from boto.dynamodb.exceptions import DynamoDBValidationError

        db = connect_boto_patch()

        expected1 = {u'SS': [u'item1', u'item2', u'item3', u'item4']}

        key = {
            u"HashKeyElement":  {TABLE_HK_TYPE: HK_VALUE},
            u"RangeKeyElement": {TABLE_RK_TYPE: RK_VALUE},
        }

        self.assertRaises(DynamoDBValidationError,
            db.layer1.update_item,
            TABLE_NAME, key, {
                FIELD_NAME: {'Action': 'ADD', u'Value': {u'B': u'item5'}},
            }
        )
        self.assertEqual(expected1, self.t1.store[HK_VALUE, RK_VALUE][FIELD_SET_NAME])

    def test_update_return_all_old(self):
        from ddbmock import connect_boto_patch
        from boto.dynamodb.exceptions import DynamoDBValidationError

        key = {u"HashKeyElement": {TABLE_HK_TYPE: HK_VALUE}}
        ADD_VALUE = 1

        db = connect_boto_patch()
        expected = cp(ITEM2)

        # regular increment
        ret = db.layer1.update_item(TABLE_NAME2, key, {
                FIELD_NUM_NAME: {'Action': 'ADD', u'Value': {u'N': unicode(ADD_VALUE)}},
            },
            return_values=u'ALL_OLD',
         )
        self.assertEqual(expected, ret[u'Attributes'])

    def test_update_return_all_new(self):
        from ddbmock import connect_boto_patch
        from boto.dynamodb.exceptions import DynamoDBValidationError

        key = {u"HashKeyElement": {TABLE_HK_TYPE: HK_VALUE}}
        ADD_VALUE = 1

        db = connect_boto_patch()
        expected = cp(ITEM2)
        expected[FIELD_NUM_NAME][u'N'] = unicode(int(expected[FIELD_NUM_NAME][u'N']) + ADD_VALUE)

        # regular increment
        ret = db.layer1.update_item(TABLE_NAME2, key, {
                FIELD_NUM_NAME: {'Action': 'ADD', u'Value': {u'N': unicode(ADD_VALUE)}},
            },
            return_values=u'ALL_NEW',
        )
        self.assertEqual(expected, ret[u'Attributes'])

    def test_update_return_updated_old(self):
        from ddbmock import connect_boto_patch
        from boto.dynamodb.exceptions import DynamoDBValidationError

        key = {u"HashKeyElement": {TABLE_HK_TYPE: HK_VALUE}}
        ADD_VALUE = 1

        db = connect_boto_patch()
        expected = {FIELD_NUM_NAME: cp(ITEM2[FIELD_NUM_NAME])}

        # regular increment
        ret = db.layer1.update_item(TABLE_NAME2, key, {
                FIELD_NUM_NAME: {'Action': 'ADD', u'Value': {u'N': unicode(ADD_VALUE)}},
            },
            return_values=u'UPDATED_OLD',
         )
        self.assertEqual(expected, ret[u'Attributes'])

    def test_update_return_updated_new(self):
        from ddbmock import connect_boto_patch
        from boto.dynamodb.exceptions import DynamoDBValidationError

        key = {u"HashKeyElement": {TABLE_HK_TYPE: HK_VALUE}}
        ADD_VALUE = 1

        db = connect_boto_patch()
        expected = {FIELD_NUM_NAME: cp(ITEM2[FIELD_NUM_NAME])}
        expected[FIELD_NUM_NAME][u'N'] = unicode(int(expected[FIELD_NUM_NAME][u'N']) + ADD_VALUE)

        # regular increment
        ret = db.layer1.update_item(TABLE_NAME2, key, {
                FIELD_NUM_NAME: {'Action': 'ADD', u'Value': {u'N': unicode(ADD_VALUE)}},
            },
            return_values=u'UPDATED_NEW',
         )
        self.assertEqual(expected, ret[u'Attributes'])

    def test_update_item_put_h_oversized(self):
        from boto.dynamodb.exceptions import DynamoDBValidationError
        from ddbmock import connect_boto_patch
        db = connect_boto_patch()

        key = {
            u"HashKeyElement":  {TABLE_HK_TYPE: HK_VALUE},
        }

        # PUT explicite, existing field
        self.assertRaisesRegexp(DynamoDBValidationError, 'Item size.*exceeded',
        db.layer1.update_item, TABLE_NAME2, key, {
            'relevant_data': {'Value': RELEVANT_HUGE_FIELD},
        })
        self.assertEqual(ITEM[FIELD_NAME], self.t2.store[HK_VALUE, False]['relevant_data'])
Ejemplo n.º 33
0
class TestBatchGetItem(unittest.TestCase):
    def setUp(self):
        from ddbmock.database.db import dynamodb
        from ddbmock.database.table import Table
        from ddbmock.database.key import PrimaryKey

        dynamodb.hard_reset()

        hash_key = PrimaryKey(TABLE_HK_NAME, TABLE_HK_TYPE)
        range_key = PrimaryKey(TABLE_RK_NAME, TABLE_RK_TYPE)

        self.t1 = Table(TABLE_NAME1, TABLE_RT, TABLE_WT, hash_key, range_key)
        self.t2 = Table(TABLE_NAME2, TABLE_RT, TABLE_WT, hash_key, None)

        dynamodb.data[TABLE_NAME1] = self.t1
        dynamodb.data[TABLE_NAME2] = self.t2

        self.t1.put(ITEM1, {})
        self.t1.put(ITEM2, {})
        self.t1.put(ITEM3, {})
        self.t2.put(ITEM4, {})
        self.t2.put(ITEM5, {})
        self.t2.put(ITEM_BIG, {})

    def tearDown(self):
        from ddbmock.database.db import dynamodb
        from ddbmock import clean_boto_patch

        dynamodb.hard_reset()
        clean_boto_patch()

    def test_batch_get_item_nominal(self):
        from ddbmock import connect_boto_patch
        from ddbmock.database.db import dynamodb

        db = connect_boto_patch()

        expected = {
            "Responses": {
                "Table-HR": {"Items": [ITEM1, ITEM2], "ConsumedCapacityUnits": 1.0},
                "Table-H": {"Items": [ITEM5, ITEM_BIG], "ConsumedCapacityUnits": 1.5},
            }
        }

        ret = db.layer1.batch_get_item(
            {
                TABLE_NAME1: {
                    u"Keys": [
                        {u"HashKeyElement": {TABLE_HK_TYPE: HK_VALUE1}, u"RangeKeyElement": {TABLE_RK_TYPE: RK_VALUE1}},
                        {u"HashKeyElement": {TABLE_HK_TYPE: HK_VALUE1}, u"RangeKeyElement": {TABLE_RK_TYPE: RK_VALUE2}},
                    ]
                },
                TABLE_NAME2: {
                    u"Keys": [
                        {u"HashKeyElement": {TABLE_HK_TYPE: HK_VALUE3}},
                        {u"HashKeyElement": {TABLE_HK_TYPE: HK_VALUE1}},
                        {u"HashKeyElement": {TABLE_HK_TYPE: u"404"}},
                    ]
                },
            }
        )
        self.assertEqual(expected, ret)

    def test_batch_get_item_filter_one(self):
        from ddbmock import connect_boto_patch
        from ddbmock.database.db import dynamodb

        db = connect_boto_patch()

        expected = {
            "Responses": {
                "Table-HR": {
                    "Items": [{"relevant_data": {"S": "tata"}}, {"relevant_data": {"S": "tata"}}],
                    "ConsumedCapacityUnits": 1.0,
                },
                "Table-H": {
                    "Items": [
                        {"relevant_data": {"S": "tutu"}, "hash_key": {"N": "789"}, "range_key": {"S": "Waldo-5"}}
                    ],
                    "ConsumedCapacityUnits": 0.5,
                },
            }
        }

        ret = db.layer1.batch_get_item(
            {
                TABLE_NAME1: {
                    u"Keys": [
                        {u"HashKeyElement": {TABLE_HK_TYPE: HK_VALUE1}, u"RangeKeyElement": {TABLE_RK_TYPE: RK_VALUE1}},
                        {u"HashKeyElement": {TABLE_HK_TYPE: HK_VALUE1}, u"RangeKeyElement": {TABLE_RK_TYPE: RK_VALUE1}},
                    ],
                    u"AttributesToGet": [u"relevant_data"],
                },
                TABLE_NAME2: {u"Keys": [{u"HashKeyElement": {TABLE_HK_TYPE: HK_VALUE3}}]},
            }
        )
        self.assertEqual(expected, ret)

    def test_batch_get_item_table_404(self):
        from ddbmock import connect_boto_patch
        from ddbmock.database.db import dynamodb
        from boto.exception import BotoServerError

        db = connect_boto_patch()

        self.assertRaises(
            BotoServerError,
            db.layer1.batch_get_item,
            {
                TABLE_NAME_404: {
                    u"Keys": [
                        {u"HashKeyElement": {TABLE_HK_TYPE: HK_VALUE1}, u"RangeKeyElement": {TABLE_RK_TYPE: RK_VALUE1}},
                        {u"HashKeyElement": {TABLE_HK_TYPE: HK_VALUE1}, u"RangeKeyElement": {TABLE_RK_TYPE: RK_VALUE1}},
                    ]
                },
                TABLE_NAME2: {u"Keys": [{u"HashKeyElement": {TABLE_HK_TYPE: HK_VALUE3}}]},
            },
        )

    def test_batch_get_item_bad_key(self):
        from ddbmock import connect_boto_patch
        from ddbmock.database.db import dynamodb
        from boto.dynamodb.exceptions import DynamoDBValidationError

        db = connect_boto_patch()

        self.assertRaises(
            DynamoDBValidationError,
            db.layer1.batch_get_item,
            {
                TABLE_NAME1: {
                    u"Keys": [
                        {u"HashKeyElement": {TABLE_HK_TYPE: HK_VALUE1}, u"RangeKeyElement": {TABLE_RK_TYPE: RK_VALUE1}},
                        {u"HashKeyElement": {TABLE_HK_TYPE: HK_VALUE1}},
                    ]
                },
                TABLE_NAME2: {u"Keys": [{u"HashKeyElement": {TABLE_HK_TYPE: HK_VALUE3}}]},
            },
        )

        self.assertRaises(
            DynamoDBValidationError,
            db.layer1.batch_get_item,
            {
                TABLE_NAME1: {
                    u"Keys": [
                        {u"HashKeyElement": {TABLE_HK_TYPE: HK_VALUE1}, u"RangeKeyElement": {TABLE_RK_TYPE: RK_VALUE1}},
                        {u"HashKeyElement": {TABLE_HK_TYPE: HK_VALUE1}, u"RangeKeyElement": {TABLE_RK_TYPE: RK_VALUE1}},
                    ]
                },
                TABLE_NAME2: {
                    u"Keys": [
                        {u"HashKeyElement": {TABLE_HK_TYPE: HK_VALUE3}, u"RangeKeyElement": {TABLE_RK_TYPE: RK_VALUE1}}
                    ]
                },
            },
        )
Ejemplo n.º 34
0
class TestGetItem(unittest.TestCase):
    def setUp(self):
        from ddbmock.database.db import dynamodb
        from ddbmock.database.table import Table
        from ddbmock.database.key import PrimaryKey

        dynamodb.hard_reset()

        hash_key = PrimaryKey(TABLE_HK_NAME, TABLE_HK_TYPE)
        range_key = PrimaryKey(TABLE_RK_NAME, TABLE_RK_TYPE)

        self.t1 = Table(TABLE_NAME, TABLE_RT, TABLE_WT, hash_key, range_key)
        self.t2 = Table(TABLE_NAME2, TABLE_RT, TABLE_WT, hash_key, None)

        dynamodb.data[TABLE_NAME] = self.t1
        dynamodb.data[TABLE_NAME2] = self.t2

        self.t1.put(ITEM, {})
        self.t2.put(ITEM2, {})
        self.t2.put(ITEM_BIG, {})

    def tearDown(self):
        from ddbmock.database.db import dynamodb
        from ddbmock import clean_boto_patch
        dynamodb.hard_reset()
        clean_boto_patch()

    def test_get_hr(self):
        from ddbmock import connect_boto_patch
        from ddbmock.database.db import dynamodb

        db = connect_boto_patch()

        expected = {
            u'ConsumedCapacityUnits': 0.5,
            u'Item': ITEM,
        }

        key = {
            u"HashKeyElement": {
                TABLE_HK_TYPE: HK_VALUE
            },
            u"RangeKeyElement": {
                TABLE_RK_TYPE: RK_VALUE
            },
        }

        self.assertEquals(expected, db.layer1.get_item(TABLE_NAME, key))

    def test_get_hr_consistent(self):
        from ddbmock import connect_boto_patch
        from ddbmock.database.db import dynamodb

        db = connect_boto_patch()

        expected = {
            u'ConsumedCapacityUnits': 1,
            u'Item': ITEM,
        }

        key = {
            u"HashKeyElement": {
                TABLE_HK_TYPE: HK_VALUE
            },
            u"RangeKeyElement": {
                TABLE_RK_TYPE: RK_VALUE
            },
        }

        self.assertEquals(
            expected, db.layer1.get_item(TABLE_NAME, key,
                                         consistent_read=True))

    def test_get_h(self):
        from ddbmock import connect_boto_patch
        from ddbmock.database.db import dynamodb

        db = connect_boto_patch()

        expected = {
            u'ConsumedCapacityUnits': 0.5,
            u'Item': ITEM2,
        }

        key = {
            u"HashKeyElement": {
                TABLE_HK_TYPE: HK_VALUE
            },
        }

        self.assertEquals(expected, db.layer1.get_item(TABLE_NAME2, key))

    def test_get_consistent_big_attributes_to_get(self):
        from ddbmock import connect_boto_patch
        from ddbmock.database.db import dynamodb

        db = connect_boto_patch()

        expected = {
            u'ConsumedCapacityUnits': 2,
            u'Item': {
                TABLE_HK_NAME: {
                    TABLE_HK_TYPE: HK_VALUE2
                }
            },
        }

        key = {
            u"HashKeyElement": {
                TABLE_HK_TYPE: HK_VALUE2
            },
        }

        self.assertEquals(
            expected,
            db.layer1.get_item(TABLE_NAME2,
                               key,
                               consistent_read=True,
                               attributes_to_get=[TABLE_HK_NAME]))

    def test_get_h_404(self):
        from ddbmock import connect_boto_patch
        from ddbmock.database.db import dynamodb
        from boto.dynamodb.exceptions import DynamoDBKeyNotFoundError

        db = connect_boto_patch()

        key = {
            u"HashKeyElement": {
                TABLE_HK_TYPE: HK_VALUE_404
            },
        }

        self.assertRaises(DynamoDBKeyNotFoundError, db.layer1.get_item,
                          TABLE_NAME2, key)

    def test_get_hr_attr_to_get(self):
        from ddbmock import connect_boto_patch
        from ddbmock.database.db import dynamodb

        db = connect_boto_patch()

        expected = {
            u'ConsumedCapacityUnits': 0.5,
            u'Item': {
                u'relevant_data': {
                    u'B': u'THVkaWEgaXMgdGhlIGJlc3QgY29tcGFueSBldmVyIQ=='
                }
            }
        }

        key = {
            u"HashKeyElement": {
                TABLE_HK_TYPE: HK_VALUE
            },
            u"RangeKeyElement": {
                TABLE_RK_TYPE: RK_VALUE
            },
        }

        self.assertEquals(
            expected,
            db.layer1.get_item(TABLE_NAME,
                               key,
                               attributes_to_get=[u'relevant_data']))
Ejemplo n.º 35
0
class TestQuery(unittest.TestCase):
    def setUp(self):
        from ddbmock.database.db import dynamodb
        from ddbmock.database.table import Table
        from ddbmock.database.key import PrimaryKey

        dynamodb.hard_reset()

        hash_key = PrimaryKey(TABLE_HK_NAME, TABLE_HK_TYPE)
        range_key = PrimaryKey(TABLE_RK_NAME, TABLE_RK_TYPE)

        self.t1 = Table(TABLE_NAME, TABLE_RT, TABLE_WT, hash_key, range_key)

        dynamodb.data[TABLE_NAME] = self.t1

        self.t1.put(ITEM1, {})
        self.t1.put(ITEM2, {})
        self.t1.put(ITEM3, {})
        self.t1.put(ITEM4, {})
        self.t1.put(ITEM5, {})

    def tearDown(self):
        from ddbmock.database.db import dynamodb
        from ddbmock import clean_boto_patch
        dynamodb.hard_reset()
        clean_boto_patch()

    def test_query_all(self):
        from ddbmock import connect_boto_patch
        from ddbmock.database.db import dynamodb

        expected = {
            u"Count": 5,
            u"Items": [ITEM1, ITEM2, ITEM3, ITEM4, ITEM5],
            u"ConsumedCapacityUnits": 0.5,
        }

        db = connect_boto_patch()

        ret = db.layer1.query(TABLE_NAME, {TABLE_HK_TYPE: HK_VALUE})
        self.assertEqual(expected, ret)

    # Regression test for #9
    def test_query_all_404(self):
        from ddbmock import connect_boto_patch
        from ddbmock.database.db import dynamodb

        expected = {
            u"Count": 0,
            u'Items': [],
            u"ConsumedCapacityUnits": 0.5,
        }

        db = connect_boto_patch()

        ret = db.layer1.query(TABLE_NAME, {TABLE_HK_TYPE: HK_VALUE_404})
        self.assertEqual(expected, ret)

    def test_query_2_first(self):
        from ddbmock import connect_boto_patch
        from ddbmock.database.db import dynamodb

        expected = {
            u"Count": 2,
            u"Items": [ITEM1, ITEM2],
            u"ConsumedCapacityUnits": 0.5,
            u'LastEvaluatedKey': {
                u'HashKeyElement': {
                    u'N': u'123'
                },
                u'RangeKeyElement': {
                    u'S': u'Waldo-2'
                },
            },
        }

        db = connect_boto_patch()

        ret = db.layer1.query(TABLE_NAME, {TABLE_HK_TYPE: HK_VALUE}, limit=2)
        self.assertEqual(expected, ret)

    def test_query_paged(self):
        from ddbmock import connect_boto_patch
        from ddbmock.database.db import dynamodb
        from boto.dynamodb.exceptions import DynamoDBValidationError

        esk = {
            u'HashKeyElement': {
                u'N': u'123'
            },
            u'RangeKeyElement': {
                u'S': u'Waldo-3'
            },
        }

        bad_esk = {
            u'HashKeyElement': {
                u'N': u'123.43'
            },
            u'RangeKeyElement': {
                u'S': u'Waldo-3'
            },
        }

        expected1 = {
            u"Count": 3,
            u"Items": [ITEM1, ITEM2, ITEM3],
            u"ConsumedCapacityUnits": 0.5,
            u'LastEvaluatedKey': esk,
        }
        expected2 = {
            u"Count": 2,
            u"Items": [ITEM4, ITEM5],
            u"ConsumedCapacityUnits": 0.5,
        }

        db = connect_boto_patch()

        ret = db.layer1.query(TABLE_NAME, {TABLE_HK_TYPE: HK_VALUE}, limit=3)
        self.assertEqual(expected1, ret)
        ret = db.layer1.query(TABLE_NAME, {TABLE_HK_TYPE: HK_VALUE},
                              limit=3,
                              exclusive_start_key=esk)
        self.assertEqual(expected2, ret)
        self.assertRaises(DynamoDBValidationError,
                          db.layer1.query,
                          TABLE_NAME, {TABLE_HK_TYPE: HK_VALUE},
                          limit=3,
                          exclusive_start_key=bad_esk)

    def test_query_2_last(self):
        from ddbmock import connect_boto_patch
        from ddbmock.database.db import dynamodb

        expected = {
            u"Count": 2,
            u"Items": [ITEM5, ITEM4],
            u"ConsumedCapacityUnits": 0.5,
            u'LastEvaluatedKey': {
                u'HashKeyElement': {
                    u'N': u'123'
                },
                u'RangeKeyElement': {
                    u'S': u'Waldo-4'
                },
            }
        }

        db = connect_boto_patch()

        ret = db.layer1.query(TABLE_NAME, {TABLE_HK_TYPE: HK_VALUE},
                              limit=2,
                              scan_index_forward=False)
        self.assertEqual(expected, ret)

    def test_query_all_filter_fields(self):
        from ddbmock import connect_boto_patch
        from ddbmock.database.db import dynamodb

        expected = {
            u"Count":
            5,
            u"Items": [
                {
                    u"relevant_data": {
                        u"S": "tata"
                    }
                },
                {
                    u"relevant_data": {
                        u"S": "tete"
                    }
                },
                {
                    u"relevant_data": {
                        u"S": "titi"
                    }
                },
                {
                    u"relevant_data": {
                        u"S": "toto"
                    }
                },
                {
                    u"relevant_data": {
                        u"S": "tutu"
                    }
                },
            ],
            u"ConsumedCapacityUnits":
            0.5,
        }
        fields = [u'relevant_data']

        db = connect_boto_patch()

        ret = db.layer1.query(TABLE_NAME, {TABLE_HK_TYPE: HK_VALUE}, None,
                              fields)
        self.assertEqual(expected, ret)

    # No need to test all conditions/type mismatch as they are unit tested
    def test_query_condition_filter_fields(self):
        from ddbmock import connect_boto_patch
        from ddbmock.database.db import dynamodb

        expected = {
            u"Count":
            3,
            u"Items": [
                {
                    u"relevant_data": {
                        u"S": u"titi"
                    }
                },
                {
                    u"relevant_data": {
                        u"S": u"toto"
                    }
                },
                {
                    u"relevant_data": {
                        u"S": u"tutu"
                    }
                },
            ],
            u"ConsumedCapacityUnits":
            0.5,
        }

        condition = {
            "AttributeValueList": [{
                "S": "Waldo-2"
            }],
            "ComparisonOperator": "GT"
        }
        fields = [u'relevant_data']

        db = connect_boto_patch()

        ret = db.layer1.query(TABLE_NAME, {TABLE_HK_TYPE: HK_VALUE}, condition,
                              fields)
        self.assertEqual(expected, ret)

    def test_query_all_consistent(self):
        from ddbmock import connect_boto_patch
        from ddbmock.database.db import dynamodb

        expected = {
            u"Count": 5,
            u"Items": [ITEM1, ITEM2, ITEM3, ITEM4, ITEM5],
            u"ConsumedCapacityUnits": 1,
        }

        db = connect_boto_patch()

        ret = db.layer1.query(TABLE_NAME, {TABLE_HK_TYPE: HK_VALUE},
                              consistent_read=True)
        self.assertEqual(expected, ret)

    def test_query_invalid_condition_multiple_data_in_field(self):
        from ddbmock import connect_boto_patch
        from ddbmock.database.db import dynamodb
        from boto.dynamodb.exceptions import DynamoDBValidationError

        condition = {
            "AttributeValueList": [
                {
                    "S": "Waldo-2"
                },
                {
                    "S": "Waldo-3"
                },
            ],
            "ComparisonOperator": "GT"
        }
        fields = [u'relevant_data']

        db = connect_boto_patch()

        self.assertRaises(DynamoDBValidationError, db.layer1.query, TABLE_NAME,
                          {TABLE_HK_TYPE: HK_VALUE}, condition, fields)
Ejemplo n.º 36
0
class TestBatchGetItem(unittest.TestCase):
    def setUp(self):
        from ddbmock.database.db import dynamodb
        from ddbmock.database.table import Table
        from ddbmock.database.key import PrimaryKey

        from ddbmock import main
        app = main({})
        from webtest import TestApp
        self.app = TestApp(app)

        dynamodb.hard_reset()

        hash_key = PrimaryKey(TABLE_HK_NAME, TABLE_HK_TYPE)
        range_key = PrimaryKey(TABLE_RK_NAME, TABLE_RK_TYPE)

        self.t1 = Table(TABLE_NAME1, TABLE_RT, TABLE_WT, hash_key, range_key)
        self.t2 = Table(TABLE_NAME2, TABLE_RT, TABLE_WT, hash_key, None)

        dynamodb.data[TABLE_NAME1] = self.t1
        dynamodb.data[TABLE_NAME2] = self.t2

        self.t1.put(ITEM1, {})
        self.t1.put(ITEM2, {})
        self.t1.put(ITEM3, {})
        self.t2.put(ITEM4, {})
        self.t2.put(ITEM5, {})

    def tearDown(self):
        from ddbmock.database.db import dynamodb
        dynamodb.hard_reset()

    def test_batch_get_item_filter_one(self):
        request = {
            u"RequestItems": {
                TABLE_NAME1: {
                    u"Keys": [
                        {
                            u"HashKeyElement": {
                                TABLE_HK_TYPE: HK_VALUE1
                            },
                            u"RangeKeyElement": {
                                TABLE_RK_TYPE: RK_VALUE1
                            },
                        },
                        {
                            u"HashKeyElement": {
                                TABLE_HK_TYPE: HK_VALUE1
                            },
                            u"RangeKeyElement": {
                                TABLE_RK_TYPE: RK_VALUE1
                            }
                        },
                    ],
                    u"AttributesToGet": [u"relevant_data"],
                },
                TABLE_NAME2: {
                    u"Keys": [
                        {
                            u"HashKeyElement": {
                                TABLE_HK_TYPE: HK_VALUE3
                            }
                        },
                    ],
                },
            }
        }

        expected = {
            "Responses": {
                "Table-HR": {
                    "Items": [
                        {
                            "relevant_data": {
                                "S": "tata"
                            }
                        },
                        {
                            "relevant_data": {
                                "S": "tata"
                            }
                        },
                    ],
                    "ConsumedCapacityUnits":
                    1.0
                },
                "Table-H": {
                    "Items": [
                        {
                            "relevant_data": {
                                "S": "tutu"
                            },
                            "hash_key": {
                                "N": "789"
                            },
                            "range_key": {
                                "S": "Waldo-5"
                            }
                        },
                    ],
                    "ConsumedCapacityUnits":
                    0.5
                }
            }
        }

        # Protocol check

        res = self.app.post_json('/', request, headers=HEADERS, status=200)
        self.assertEqual(expected, json.loads(res.body))
        self.assertEqual('application/x-amz-json-1.0; charset=UTF-8',
                         res.headers['Content-Type'])

    def test_batch_get_item_filter_one_consistent(self):
        request = {
            u"RequestItems": {
                TABLE_NAME1: {
                    u"Keys": [
                        {
                            u"HashKeyElement": {
                                TABLE_HK_TYPE: HK_VALUE1
                            },
                            u"RangeKeyElement": {
                                TABLE_RK_TYPE: RK_VALUE1
                            }
                        },
                        {
                            u"HashKeyElement": {
                                TABLE_HK_TYPE: HK_VALUE1
                            },
                            u"RangeKeyElement": {
                                TABLE_RK_TYPE: RK_VALUE1
                            }
                        },
                    ],
                    u"AttributesToGet": [u"relevant_data"],
                    u"ConsistentRead":
                    True,
                },
                TABLE_NAME2: {
                    u"Keys": [
                        {
                            u"HashKeyElement": {
                                TABLE_HK_TYPE: HK_VALUE3
                            }
                        },
                    ],
                },
            }
        }

        expected = {
            "Responses": {
                "Table-HR": {
                    "Items": [
                        {
                            "relevant_data": {
                                "S": "tata"
                            }
                        },
                        {
                            "relevant_data": {
                                "S": "tata"
                            }
                        },
                    ],
                    "ConsumedCapacityUnits":
                    2.0
                },
                "Table-H": {
                    "Items": [
                        {
                            "relevant_data": {
                                "S": "tutu"
                            },
                            "hash_key": {
                                "N": "789"
                            },
                            "range_key": {
                                "S": "Waldo-5"
                            }
                        },
                    ],
                    "ConsumedCapacityUnits":
                    0.5
                }
            }
        }

        # Protocol check
        res = self.app.post_json('/', request, headers=HEADERS, status=200)
        self.assertEqual(expected, json.loads(res.body))
        self.assertEqual('application/x-amz-json-1.0; charset=UTF-8',
                         res.headers['Content-Type'])
Ejemplo n.º 37
0
class TestGetItem(unittest.TestCase):
    def setUp(self):
        from ddbmock.database.db import dynamodb
        from ddbmock.database.table import Table
        from ddbmock.database.key import PrimaryKey

        dynamodb.hard_reset()

        hash_key = PrimaryKey(TABLE_HK_NAME, TABLE_HK_TYPE)
        range_key = PrimaryKey(TABLE_RK_NAME, TABLE_RK_TYPE)

        self.t1 = Table(TABLE_NAME, TABLE_RT, TABLE_WT, hash_key, range_key)
        self.t2 = Table(TABLE_NAME2, TABLE_RT, TABLE_WT, hash_key, None)

        dynamodb.data[TABLE_NAME]  = self.t1
        dynamodb.data[TABLE_NAME2] = self.t2

        self.t1.put(ITEM, {})
        self.t2.put(ITEM2, {})
        self.t2.put(ITEM_BIG, {})

    def tearDown(self):
        from ddbmock.database.db import dynamodb
        from ddbmock import clean_boto_patch
        dynamodb.hard_reset()
        clean_boto_patch()

    def test_get_hr(self):
        from ddbmock import connect_boto_patch
        from ddbmock.database.db import dynamodb

        db = connect_boto_patch()

        expected = {
            u'ConsumedCapacityUnits': 0.5,
            u'Item': ITEM,
        }

        key = {
            u"HashKeyElement":  {TABLE_HK_TYPE: HK_VALUE},
            u"RangeKeyElement": {TABLE_RK_TYPE: RK_VALUE},
        }

        self.assertEquals(expected, db.layer1.get_item(TABLE_NAME, key))

    def test_get_hr_consistent(self):
        from ddbmock import connect_boto_patch
        from ddbmock.database.db import dynamodb

        db = connect_boto_patch()

        expected = {
            u'ConsumedCapacityUnits': 1,
            u'Item': ITEM,
        }

        key = {
            u"HashKeyElement":  {TABLE_HK_TYPE: HK_VALUE},
            u"RangeKeyElement": {TABLE_RK_TYPE: RK_VALUE},
        }

        self.assertEquals(expected, db.layer1.get_item(TABLE_NAME, key, consistent_read=True))

    def test_get_h(self):
        from ddbmock import connect_boto_patch
        from ddbmock.database.db import dynamodb

        db = connect_boto_patch()

        expected = {
            u'ConsumedCapacityUnits': 0.5,
            u'Item': ITEM2,
        }

        key = {
            u"HashKeyElement":  {TABLE_HK_TYPE: HK_VALUE},
        }

        self.assertEquals(expected, db.layer1.get_item(TABLE_NAME2, key))

    def test_get_consistent_big_attributes_to_get(self):
        from ddbmock import connect_boto_patch
        from ddbmock.database.db import dynamodb

        db = connect_boto_patch()

        expected = {
            u'ConsumedCapacityUnits': 2,
            u'Item': {TABLE_HK_NAME: {TABLE_HK_TYPE: HK_VALUE2}},
        }

        key = {
            u"HashKeyElement":  {TABLE_HK_TYPE: HK_VALUE2},
        }

        self.assertEquals(expected, db.layer1.get_item(TABLE_NAME2, key, consistent_read=True, attributes_to_get=[TABLE_HK_NAME]))

    def test_get_h_404(self):
        from ddbmock import connect_boto_patch
        from ddbmock.database.db import dynamodb
        from boto.dynamodb.exceptions import DynamoDBKeyNotFoundError

        db = connect_boto_patch()

        key = {
            u"HashKeyElement":  {TABLE_HK_TYPE: HK_VALUE_404},
        }

        self.assertRaises(DynamoDBKeyNotFoundError,
                          db.layer1.get_item,
                          TABLE_NAME2, key)

    def test_get_hr_attr_to_get(self):
        from ddbmock import connect_boto_patch
        from ddbmock.database.db import dynamodb

        db = connect_boto_patch()

        expected = {
            u'ConsumedCapacityUnits': 0.5,
            u'Item': {
                u'relevant_data': {u'B': u'THVkaWEgaXMgdGhlIGJlc3QgY29tcGFueSBldmVyIQ=='}}
        }

        key = {
            u"HashKeyElement":  {TABLE_HK_TYPE: HK_VALUE},
            u"RangeKeyElement": {TABLE_RK_TYPE: RK_VALUE},
        }

        self.assertEquals(expected, db.layer1.get_item(TABLE_NAME, key, attributes_to_get=[u'relevant_data']))
Ejemplo n.º 38
0
class TestBatchWriteItem(unittest.TestCase):
    def setUp(self):
        from ddbmock.database.db import dynamodb
        from ddbmock.database.table import Table
        from ddbmock.database.key import PrimaryKey

        from ddbmock import main
        app = main({})
        from webtest import TestApp
        self.app = TestApp(app)

        dynamodb.hard_reset()

        hash_key = PrimaryKey(TABLE_HK_NAME, TABLE_HK_TYPE)
        range_key = PrimaryKey(TABLE_RK_NAME, TABLE_RK_TYPE)

        self.t1 = Table(TABLE_NAME1, TABLE_RT, TABLE_WT, hash_key, range_key)
        self.t2 = Table(TABLE_NAME2, TABLE_RT, TABLE_WT, hash_key, None)

        dynamodb.data[TABLE_NAME1] = self.t1
        dynamodb.data[TABLE_NAME2] = self.t2

        self.t1.put(ITEM1, {})
        self.t2.put(ITEM4, {})

    def tearDown(self):
        from ddbmock.database.db import dynamodb
        dynamodb.hard_reset()

    def test_batch_write_item(self):
        request = {
            u"RequestItems": {
                TABLE_NAME1: [
                    {
                        u"DeleteRequest": {
                            u"Key": {
                                u"HashKeyElement": {
                                    TABLE_HK_TYPE: HK_VALUE1
                                },
                                u"RangeKeyElement": {
                                    TABLE_RK_TYPE: RK_VALUE1
                                },
                            },
                        },
                    },
                    {
                        u"PutRequest": {
                            u"Item": ITEM2
                        }
                    },
                    {
                        u"PutRequest": {
                            u"Item": ITEM3
                        }
                    },
                ],
                TABLE_NAME2: [
                    {
                        u"DeleteRequest": {
                            u"Key": {
                                u"HashKeyElement": {
                                    TABLE_HK_TYPE: HK_VALUE2
                                },
                            },
                        },
                    },
                    {
                        u"PutRequest": {
                            u"Item": ITEM5
                        }
                    },
                ],
            }
        }

        expected = {
            "Responses": {
                TABLE_NAME1: {
                    "ConsumedCapacityUnits": 3
                },
                TABLE_NAME2: {
                    "ConsumedCapacityUnits": 2
                }
            }
        }

        # Protocol check
        res = self.app.post_json('/', request, headers=HEADERS, status=200)
        self.assertEqual(expected, json.loads(res.body))
        self.assertEqual('application/x-amz-json-1.0; charset=UTF-8',
                         res.headers['Content-Type'])
Ejemplo n.º 39
0
class TestQuery(unittest.TestCase):
    def setUp(self):
        from ddbmock.database.db import dynamodb
        from ddbmock.database.table import Table
        from ddbmock.database.key import PrimaryKey
        from ddbmock import main
        app = main({})
        from webtest import TestApp
        self.app = TestApp(app)

        dynamodb.hard_reset()

        hash_key = PrimaryKey(TABLE_HK_NAME, TABLE_HK_TYPE)
        range_key = PrimaryKey(TABLE_RK_NAME, TABLE_RK_TYPE)

        self.t1 = Table(TABLE_NAME, TABLE_RT, TABLE_WT, hash_key, range_key)

        dynamodb.data[TABLE_NAME] = self.t1

        self.t1.put(ITEM1, {})
        self.t1.put(ITEM2, {})
        self.t1.put(ITEM3, {})
        self.t1.put(ITEM4, {})
        self.t1.put(ITEM5, {})

    def tearDown(self):
        from ddbmock.database.db import dynamodb
        dynamodb.hard_reset()

    def test_query_condition_filter_fields(self):
        request = {
            "TableName": TABLE_NAME,
            "HashKeyValue": {
                TABLE_HK_TYPE: HK_VALUE
            },
            "RangeKeyCondition": {
                "AttributeValueList": [{
                    "S": "Waldo-2"
                }],
                "ComparisonOperator": "GT",
            },
            "AttributesToGet": [u'relevant_data'],
        }

        expected = {
            u"Count":
            3,
            u"Items": [
                {
                    u"relevant_data": {
                        u"S": u"titi"
                    }
                },
                {
                    u"relevant_data": {
                        u"S": u"toto"
                    }
                },
                {
                    u"relevant_data": {
                        u"S": u"tutu"
                    }
                },
            ],
            u"ConsumedCapacityUnits":
            0.5,
        }

        # Protocol check
        res = self.app.post_json('/', request, headers=HEADERS, status=200)
        self.assertEqual(expected, json.loads(res.body))
        self.assertEqual('application/x-amz-json-1.0; charset=UTF-8',
                         res.headers['Content-Type'])

    def test_query_count_and_attrs_to_get_fails(self):
        request = {
            "TableName": TABLE_NAME,
            "HashKeyValue": {
                TABLE_HK_TYPE: HK_VALUE
            },
            "RangeKeyCondition": {
                "AttributeValueList": [{
                    "S": "Waldo-2"
                }],
                "ComparisonOperator": "GT",
            },
            "AttributesToGet": [u'relevant_data'],
            "Count": True,
        }

        expected = {
            u'__type': u'com.amazonaws.dynamodb.v20111205#ValidationException',
            u'message': u'Can filter fields when only count is requested'
        }

        # Protocol check
        res = self.app.post_json('/', request, headers=HEADERS, status=400)
        self.assertEqual(expected, json.loads(res.body))
        self.assertEqual('application/x-amz-json-1.0; charset=UTF-8',
                         res.headers['Content-Type'])

    # Regression test for #9
    def test_query_all_404(self):
        request = {
            "TableName": TABLE_NAME,
            "HashKeyValue": {
                TABLE_HK_TYPE: HK_VALUE_404
            },
        }

        expected = {
            u"Count": 0,
            u'Items': [],
            u"ConsumedCapacityUnits": 0.5,
        }

        # Protocol check
        res = self.app.post_json('/', request, headers=HEADERS, status=200)
        self.assertEqual(expected, json.loads(res.body))
        self.assertEqual('application/x-amz-json-1.0; charset=UTF-8',
                         res.headers['Content-Type'])
Ejemplo n.º 40
0
class TestScan(unittest.TestCase):
    def setUp(self):
        from ddbmock.database.db import dynamodb
        from ddbmock.database.table import Table
        from ddbmock.database.key import PrimaryKey

        dynamodb.hard_reset()

        hash_key = PrimaryKey(TABLE_HK_NAME, TABLE_HK_TYPE)
        range_key = PrimaryKey(TABLE_RK_NAME, TABLE_RK_TYPE)

        self.t1 = Table(TABLE_NAME, TABLE_RT, TABLE_WT, hash_key, range_key)

        dynamodb.data[TABLE_NAME]  = self.t1

        self.t1.put(ITEM1, {})
        self.t1.put(ITEM2, {})
        self.t1.put(ITEM3, {})
        self.t1.put(ITEM4, {})
        self.t1.put(ITEM5, {})
        self.t1.put(ITEM6, {})

    def tearDown(self):
        from ddbmock.database.db import dynamodb
        from ddbmock import clean_boto_patch
        dynamodb.hard_reset()
        clean_boto_patch()

    def test_scan_all(self):
        from ddbmock import connect_boto_patch
        from ddbmock.database.db import dynamodb

        expected = {
            u"Count": 6,
            u"ScannedCount": 6,
            u"Items": [ITEM2, ITEM1, ITEM6, ITEM5, ITEM4, ITEM3],
            u"ConsumedCapacityUnits": 1.5,
        }

        db = connect_boto_patch()

        ret = db.layer1.scan(TABLE_NAME, None)
        self.assertEqual(expected, ret)

    def test_scan_paged(self):
        from ddbmock import connect_boto_patch
        from ddbmock.database.db import dynamodb
        from boto.dynamodb.exceptions import DynamoDBValidationError

        esk = {
            u'HashKeyElement': {u'N': u'789'},
            u'RangeKeyElement': {u'S': u'Waldo-5'},
        }

        expected1 = {
            u"Count": 4,
            u"ScannedCount": 4,
            u"Items": [ITEM2, ITEM1, ITEM6, ITEM5],
            u"ConsumedCapacityUnits": 1.5,
            u'LastEvaluatedKey': esk,
        }
        expected2 = {
            u"Count": 2,
            u"ScannedCount": 2,
            u"Items": [ITEM4, ITEM3],
            u"ConsumedCapacityUnits": 0.5,
        }

        db = connect_boto_patch()

        ret = db.layer1.scan(TABLE_NAME, limit=4)
        self.assertEqual(expected1, ret)
        ret = db.layer1.scan(TABLE_NAME, exclusive_start_key=esk)
        self.assertEqual(expected2, ret)

    def test_scan_all_filter_fields(self):
        from ddbmock import connect_boto_patch
        from ddbmock.database.db import dynamodb

        self.maxDiff = None

        expected = {
            u"Count": 6,
            u"ScannedCount": 6,
            u"Items": [
                {u"relevant_data": {u"S": u"tete"}},
                {u"relevant_data": {u"S": u"tata"}},
                {u"relevant_data": {u"S": u"tyty"}},
                {u"relevant_data": {u"S": u"tutu"}},
                {u"relevant_data": {u"S": u"toto"}},
                {u"relevant_data": {u"S": u"titi"}},
            ],
            u"ConsumedCapacityUnits": 1.5,
        }
        fields = [u'relevant_data']

        db = connect_boto_patch()

        ret = db.layer1.scan(TABLE_NAME, None, fields)
        self.assertEqual(expected, ret)

    # No need to test all conditions/type mismatch as they are unit tested
    def test_scan_condition_filter_fields_in(self):
        from ddbmock import connect_boto_patch
        from ddbmock.database.db import dynamodb

        expected = {
            u"Count": 3,
            u"ScannedCount": 6,
            u"Items": [
                {u"relevant_data": {u"S": u"tata"}},
                {u"relevant_data": {u"S": u"toto"}},
                {u"relevant_data": {u"S": u"titi"}},
            ],
            u"ConsumedCapacityUnits": 1.5,
        }

        conditions = {
            "relevant_data": {
                "AttributeValueList": [{"S":"toto"},{"S":"titi"},{"S":"tata"}],
                "ComparisonOperator": "IN",
            }
        }
        fields = [u'relevant_data']

        db = connect_boto_patch()

        ret = db.layer1.scan(TABLE_NAME, conditions, fields)
        self.assertEqual(expected, ret)

    def test_scan_condition_filter_fields_contains(self):
        from ddbmock import connect_boto_patch
        from ddbmock.database.db import dynamodb

        expected = {
            u"Count": 1,
            u"ScannedCount": 6,
            u"Items": [
                {u"relevant_data": {u"S": u"toto"}},
            ],
            u"ConsumedCapacityUnits": 1.5,
        }

        conditions = {
            "relevant_data": {
                "AttributeValueList": [{"S":"to"}],
                "ComparisonOperator": "CONTAINS",
            },
        }
        fields = [u'relevant_data']

        db = connect_boto_patch()

        ret = db.layer1.scan(TABLE_NAME, conditions, fields)
        self.assertEqual(expected, ret)

    def test_scan_filter_ghost_fields(self):
        from ddbmock import connect_boto_patch
        from ddbmock.database.db import dynamodb

        expected = {
            u"Count": 0,
            u"ScannedCount": 6,
            u"Items": [],
            u"ConsumedCapacityUnits": 1.5,
        }

        conditions = {
            "ghost field": {
                "AttributeValueList": [{"N":"123"}],
                "ComparisonOperator": "LT",
            },
        }
        fields = [u'relevant_data']

        db = connect_boto_patch()

        ret = db.layer1.scan(TABLE_NAME, conditions, fields)
        self.assertEqual(expected, ret)

    def test_scan_validation_error(self):
        from ddbmock import connect_boto_patch
        from ddbmock.database.db import dynamodb
        from boto.dynamodb.exceptions import DynamoDBValidationError

        expected = {
            u"Count": 1,
            u"ScannedCount": 6,
            u"Items": [
                {u"relevant_data": {u"S": u"toto"}},
            ],
            u"ConsumedCapacityUnits": 1.5,
        }

        conditions = {
            "relevant_data": {
                "AttributeValueList": [{"S":"to"},{"S":"ta"}],
                "ComparisonOperator": "CONTAINS",
            }
        }
        fields = [u'relevant_data']

        db = connect_boto_patch()

        self.assertRaises(DynamoDBValidationError, db.layer1.scan,
            TABLE_NAME, conditions, fields
        )
Ejemplo n.º 41
0
class TestBatchWriteItem(unittest.TestCase):
    def setUp(self):
        from ddbmock.database.db import dynamodb
        from ddbmock.database.table import Table
        from ddbmock.database.key import PrimaryKey

        dynamodb.hard_reset()

        hash_key = PrimaryKey(TABLE_HK_NAME, TABLE_HK_TYPE)
        range_key = PrimaryKey(TABLE_RK_NAME, TABLE_RK_TYPE)

        self.t1 = Table(TABLE_NAME1, TABLE_RT, TABLE_WT, hash_key, range_key)
        self.t2 = Table(TABLE_NAME2, TABLE_RT, TABLE_WT, hash_key, None)

        dynamodb.data[TABLE_NAME1]  = self.t1
        dynamodb.data[TABLE_NAME2]  = self.t2

        self.t1.put(ITEM1, {})
        self.t2.put(ITEM4, {})

    def tearDown(self):
        from ddbmock.database.db import dynamodb
        from ddbmock import clean_boto_patch
        dynamodb.hard_reset()
        clean_boto_patch()

    def test_batch_write_item_nominal(self):
        from ddbmock import connect_boto_patch
        from ddbmock.database.db import dynamodb

        db = connect_boto_patch()

        expected = {
            "Responses": {
                TABLE_NAME1: {
                    "ConsumedCapacityUnits": 3
                },
                TABLE_NAME2: {
                    "ConsumedCapacityUnits": 2
                }
            }
        }

        ret = db.layer1.batch_write_item({
            TABLE_NAME1: [
                {
                    u"DeleteRequest": {
                        u"Key": {
                            u"HashKeyElement": {TABLE_HK_TYPE: HK_VALUE1},
                            u"RangeKeyElement": {TABLE_RK_TYPE: RK_VALUE1},
                        },
                    },
                },
                {u"PutRequest": {u"Item": ITEM2}},
                {u"PutRequest": {u"Item": ITEM3}},
            ],
            TABLE_NAME2: [
                {
                    u"DeleteRequest": {
                        u"Key": {
                            u"HashKeyElement": {TABLE_HK_TYPE: HK_VALUE2},
                        },
                    },
                },
                {u"PutRequest": {u"Item":ITEM5}},
            ],
        })

        self.assertEqual(expected, ret)

    def test_batch_write_item_table_404(self):
        from ddbmock import connect_boto_patch
        from ddbmock.database.db import dynamodb
        from boto.exception import BotoServerError

        db = connect_boto_patch()

        self.assertRaises(BotoServerError, db.layer1.batch_write_item, {
            TABLE_NAME_404: [
                {
                    u"DeleteRequest": {
                        u"Key": {
                            u"HashKeyElement": {TABLE_HK_TYPE: HK_VALUE1},
                            u"RangeKeyElement": {TABLE_RK_TYPE: RK_VALUE1},
                        },
                    },
                },
                {u"PutRequest": {u"Item": ITEM2}},
                {u"PutRequest": {u"Item": ITEM3}},
            ],
            TABLE_NAME2: [
                {
                    u"DeleteRequest": {
                        u"Key": {
                            u"HashKeyElement": {TABLE_HK_TYPE: HK_VALUE2},
                        },
                    },
                },
                {u"PutRequest": {u"Item":ITEM5}},
            ],
        })