Esempio n. 1
0
def test_save_set_only(engine):
    user = User(id=uuid.uuid4())

    # Expect a SET on email
    user.email = "*****@*****.**"

    expected = {
        "Key": {
            "id": {
                "S": str(user.id)
            }
        },
        "ExpressionAttributeNames": {
            "#n0": "email"
        },
        "TableName": "User",
        "UpdateExpression": "SET #n0=:v1",
        "ExpressionAttributeValues": {
            ":v1": {
                "S": "*****@*****.**"
            }
        }
    }
    engine.save(user)
    engine.client.update_item.assert_called_once_with(expected)
Esempio n. 2
0
def test_save_update_multiple(User, engine):
    user1 = User(id=uuid.uuid4(), age=4)
    user2 = User(id=uuid.uuid4(), age=5)

    expected = [
        {"UpdateExpression": "SET #n0=:v1",
         "Key": {"id": {"S": str(user1.id)}},
         "TableName": "User",
         "ExpressionAttributeNames": {"#n0": "age"},
         "ExpressionAttributeValues": {":v1": {"N": "4"}}},
        {"UpdateExpression": "SET #n0=:v1",
         "Key": {"id": {"S": str(user2.id)}},
         "TableName": "User",
         "ExpressionAttributeNames": {"#n0": "age"},
         "ExpressionAttributeValues": {":v1": {"N": "5"}}}
    ]
    calls = 0

    def validate(item):
        nonlocal calls
        calls += 1
        assert item in expected
        expected.remove(item)
    engine.client.update_item = validate
    engine.save((user1, user2))
    assert calls == 2
Esempio n. 3
0
def test_save_atomic_new(engine):
    """atomic save on new object should expect no columns to exist"""
    user = User(id=uuid.uuid4())
    expected = {
        'ExpressionAttributeNames': {
            '#n0': 'age',
            '#n3': 'j',
            '#n1': 'email',
            '#n4': 'name',
            '#n2': 'id'
        },
        'Key': {
            'id': {
                'S': str(user.id)
            }
        },
        'TableName':
        'User',
        'ConditionExpression':
        ('((attribute_not_exists(#n0)) AND (attribute_not_exists(#n1)) '
         'AND (attribute_not_exists(#n2)) AND (attribute_not_exists(#n3))'
         ' AND (attribute_not_exists(#n4)))')
    }
    engine.config["atomic"] = True
    engine.save(user)
    engine.client.update_item.assert_called_once_with(expected)
Esempio n. 4
0
def test_save_condition(User, engine):
    user_id = uuid.uuid4()
    user = User(id=user_id)
    condition = User.id.is_(None)
    expected = {"TableName": "User",
                "ExpressionAttributeNames": {"#n0": "id"},
                "ConditionExpression": "(attribute_not_exists(#n0))",
                "Key": {"id": {"S": str(user_id)}}}

    def validate(item):
        assert item == expected
    engine.client.update_item = validate
    engine.save(user, condition=condition)
Esempio n. 5
0
def test_save_multiple(User, engine):
    user1 = User(id=uuid.uuid4())
    user2 = User(id=uuid.uuid4())

    expected = [
        {"Key": {"id": {"S": str(user1.id)}}, "TableName": "User"},
        {"Key": {"id": {"S": str(user2.id)}}, "TableName": "User"}]
    calls = 0

    def validate(item):
        assert item in expected
        nonlocal calls
        calls += 1
    engine.client.update_item = validate
    engine.save((user1, user2))
    assert calls == 2
Esempio n. 6
0
def test_save_update_condition_key_only(User, engine):
    """
    Even when the diff is empty, an UpdateItem should be issued
    (in case this is really a create - the item doesn't exist yet)
    """
    user = User(id=uuid.uuid4())
    condition = User.id.is_(None)
    expected = {"ConditionExpression": "(attribute_not_exists(#n0))",
                "TableName": "User",
                "ExpressionAttributeNames": {"#n0": "id"},
                "Key": {"id": {"S": str(user.id)}}}

    def validate(item):
        assert item == expected
    engine.client.update_item = validate
    engine.save(user, condition=condition)
Esempio n. 7
0
def test_save_update_condition(User, engine):
    """
    Non-empty diff
    """
    user = User(id=uuid.uuid4(), age=4)
    condition = User.id.is_(None)
    expected = {"ConditionExpression": "(attribute_not_exists(#n2))",
                "ExpressionAttributeNames": {"#n2": "id", "#n0": "age"},
                "TableName": "User",
                "Key": {"id": {"S": str(user.id)}},
                "ExpressionAttributeValues": {":v1": {"N": "4"}},
                "UpdateExpression": "SET #n0=:v1"}

    def validate(item):
        assert item == expected
    engine.client.update_item = validate
    engine.save(user, condition=condition)
Esempio n. 8
0
def test_save_single_with_condition(engine):
    user = User(id=uuid.uuid4())
    condition = User.id.is_(None)
    expected = {
        "TableName": "User",
        "ExpressionAttributeNames": {
            "#n0": "id"
        },
        "ConditionExpression": "(attribute_not_exists(#n0))",
        "Key": {
            "id": {
                "S": str(user.id)
            }
        }
    }
    engine.save(user, condition=condition)
    engine.client.update_item.assert_called_once_with(expected)
Esempio n. 9
0
def test_save_multiple_condition(User, engine):
    users = [User(id=uuid.uuid4()) for _ in range(3)]
    condition = User.id.is_(None)

    expected = [{"ConditionExpression": "(attribute_not_exists(#n0))",
                 "ExpressionAttributeNames": {"#n0": "id"},
                 "Key": {"id": {"S": str(user.id)}},
                 "TableName": "User"} for user in users]
    calls = 0

    def validate(item):
        assert item in expected
        nonlocal calls
        calls += 1

    engine.client.update_item = validate
    engine.save(users, condition=condition)
    assert calls == 3
Esempio n. 10
0
def test_save_update_del_field(User, engine):
    user = User(id=uuid.uuid4(), age=4)

    # Manually snapshot so we think age is persisted
    bloop.tracking.sync(user, engine)

    # Expect to see a REMOVE on age, and a SET on email
    del user.age

    expected = {"Key": {"id": {"S": str(user.id)}},
                "ExpressionAttributeNames": {"#n0": "age"},
                "TableName": "User",
                "UpdateExpression": "REMOVE #n0"}

    def validate(item):
        assert item == expected
    engine.client.update_item = validate
    engine.save(user)
Esempio n. 11
0
def test_save_list_with_condition(engine):
    users = [User(id=uuid.uuid4()) for _ in range(3)]
    condition = User.id.is_(None)
    expected_calls = [{
        "ConditionExpression": "(attribute_not_exists(#n0))",
        "ExpressionAttributeNames": {
            "#n0": "id"
        },
        "Key": {
            "id": {
                "S": str(user.id)
            }
        },
        "TableName": "User"
    } for user in users]
    engine.save(users, condition=condition)
    for expected in expected_calls:
        engine.client.update_item.assert_any_call(expected)
    assert engine.client.update_item.call_count == 3
Esempio n. 12
0
def test_save_del_only(engine):
    user = User(id=uuid.uuid4(), age=4)

    # Expect a REMOVE on age
    del user.age

    expected = {
        "Key": {
            "id": {
                "S": str(user.id)
            }
        },
        "ExpressionAttributeNames": {
            "#n0": "age"
        },
        "TableName": "User",
        "UpdateExpression": "REMOVE #n0"
    }
    engine.save(user)
    engine.client.update_item.assert_called_once_with(expected)
Esempio n. 13
0
def test_save_set_del_field(User, engine):
    """ UpdateItem can REMOVE fields as well as SET """
    user = User(id=uuid.uuid4(), age=4)

    for field in [User.id, User.age, User.email]:
        bloop.tracking.mark(user, field)

    # Expect to see a REMOVE on age, and a SET on email
    del user.age
    user.email = "*****@*****.**"

    expected = {"Key": {"id": {"S": str(user.id)}},
                "ExpressionAttributeNames": {"#n0": "email", "#n2": "age"},
                "TableName": "User",
                "UpdateExpression": "SET #n0=:v1 REMOVE #n2",
                "ExpressionAttributeValues": {":v1": {"S": "*****@*****.**"}}}

    def validate(item):
        assert item == expected
    engine.client.update_item = validate
    engine.save(user)
Esempio n. 14
0
def test_save_condition_key_only(engine):
    """
    Even when the diff is empty, an UpdateItem should be issued
    (in case this is really a create - the item doesn't exist yet)
    """
    user = User(id=uuid.uuid4())
    condition = User.id.is_(None)
    expected = {
        "ConditionExpression": "(attribute_not_exists(#n0))",
        "TableName": "User",
        "ExpressionAttributeNames": {
            "#n0": "id"
        },
        "Key": {
            "id": {
                "S": str(user.id)
            }
        }
    }
    engine.save(user, condition=condition)
    engine.client.update_item.assert_called_once_with(expected)
Esempio n. 15
0
def test_update_noop_save(engine, User):
    """ Saves should send all fields that have been set, every time """
    user = User(id=uuid.uuid4(), age=5)

    expected = {
        "Key": {"id": {"S": str(user.id)}},
        "TableName": "User",
        "ExpressionAttributeNames": {"#n0": "age"},
        "ExpressionAttributeValues": {":v1": {"N": "5"}},
        "UpdateExpression": "SET #n0=:v1"}
    calls = 0

    def validate(item):
        assert item == expected
        nonlocal calls
        calls += 1

    engine.client.update_item = validate
    engine.save(user)
    engine.save(user)
    assert calls == 2
Esempio n. 16
0
def test_save_atomic_new(User, engine):
    """
    When an object is first created, an atomic save should expect no columns
    to exist.
    """
    user_id = uuid.uuid4()
    user = User(id=user_id)
    expected = {
        'ExpressionAttributeNames': {
            '#n0': 'age', '#n3': 'j', '#n1': 'email',
            '#n4': 'name', '#n2': 'id'},
        'Key': {'id': {'S': str(user_id)}},
        'TableName': 'User',
        'ConditionExpression': (
            '((attribute_not_exists(#n0)) AND (attribute_not_exists(#n1)) '
            'AND (attribute_not_exists(#n2)) AND (attribute_not_exists(#n3))'
            ' AND (attribute_not_exists(#n4)))')}

    def validate(item):
        assert item == expected
    engine.client.update_item = validate
    engine.config["atomic"] = True
    engine.save(user)
Esempio n. 17
0
def test_save_twice(engine):
    """Save sends full local values, not just deltas from last save"""
    user = User(id=uuid.uuid4(), age=5)
    expected = {
        "Key": {
            "id": {
                "S": str(user.id)
            }
        },
        "TableName": "User",
        "ExpressionAttributeNames": {
            "#n0": "age"
        },
        "ExpressionAttributeValues": {
            ":v1": {
                "N": "5"
            }
        },
        "UpdateExpression": "SET #n0=:v1"
    }
    engine.save(user)
    engine.save(user)
    engine.client.update_item.assert_called_with(expected)
    assert engine.client.update_item.call_count == 2