From 23bb3948ee2c36b237050ed0eadfa494855486fb Mon Sep 17 00:00:00 2001 From: Nadav Har'El Date: Mon, 9 Sep 2019 15:51:47 +0300 Subject: [PATCH] alternator-test: reproduce bug in Expected with EQ of set value Our implementation of the "EQ" operator in Expected (conditional operation) just compares the JSON represntation of the values. This is almost always correct, but unfortunately incorrect for sets - where we can have two equal sets despite having a different order. This patch just adds an (xfailing) test for this bug. The bug itself can be fixed in the future in one of several ways including changing the implementation of EQ, or changing the serialization of sets so they'll always be sorted in the same way. Signed-off-by: Nadav Har'El Message-Id: <20190909125147.16484-1-nyh@scylladb.com> --- alternator-test/test_expected.py | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/alternator-test/test_expected.py b/alternator-test/test_expected.py index a48084fe7f..5febcf9402 100644 --- a/alternator-test/test_expected.py +++ b/alternator-test/test_expected.py @@ -82,6 +82,29 @@ def test_update_expected_1_eq_true(test_table_s): 'AttributeValueList': [2, 3]}} ) +# Check that set equality is checked correctly. Unlike string equality (for +# example), it cannot be done with just naive string comparison of the JSON +# representation, and we need to allow for any order. +@pytest.mark.xfail(reason="bug in EQ test of sets") +def test_update_expected_1_eq_set(test_table_s): + p = random_string() + # Because boto3 sorts the set values we give it, in order to generate a + # set with a different order, we need to build it incrementally. + test_table_s.update_item(Key={'p': p}, + AttributeUpdates={'a': {'Value': set(['dog', 'chinchilla']), 'Action': 'PUT'}}) + test_table_s.update_item(Key={'p': p}, + UpdateExpression='ADD a :val1', + ExpressionAttributeValues={':val1': set(['cat', 'mouse'])}) + # Sanity check - the attribute contains the set we think it does + assert test_table_s.get_item(Key={'p': p}, ConsistentRead=True)['Item']['a'] == set(['chinchilla', 'cat', 'dog', 'mouse']) + # Now finally check that "Expected"'s equality check knows the equality too. + test_table_s.update_item(Key={'p': p}, + AttributeUpdates={'b': {'Value': 3, 'Action': 'PUT'}}, + Expected={'a': {'ComparisonOperator': 'EQ', + 'AttributeValueList': [set(['chinchilla', 'cat', 'dog', 'mouse'])]}} + ) + assert 'b' in test_table_s.get_item(Key={'p': p}, ConsistentRead=True)['Item'] + def test_update_expected_1_eq_false(test_table_s): p = random_string() test_table_s.update_item(Key={'p': p},