From a6f14eee3fc1570f8bb26929001aa1cea4973816 Mon Sep 17 00:00:00 2001 From: Asher Foa <1268088+asherf@users.noreply.github.com> Date: Fri, 20 Dec 2019 11:16:17 -0800 Subject: [PATCH 1/5] Add test to repo stream issue --- tests/test_dynamodb2/test_dynamodb.py | 29 +++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/tests/test_dynamodb2/test_dynamodb.py b/tests/test_dynamodb2/test_dynamodb.py index 1a8a70615..01768e8e4 100644 --- a/tests/test_dynamodb2/test_dynamodb.py +++ b/tests/test_dynamodb2/test_dynamodb.py @@ -348,6 +348,35 @@ def test_put_item_with_special_chars(): '"': {"S": "foo"}, }, ) +@requires_boto_gte("2.9") +@mock_dynamodb2 +def test_put_item_with_streams(): + name = "TestTable" + conn = boto3.client( + "dynamodb", + region_name="us-west-2", + aws_access_key_id="ak", + aws_secret_access_key="sk", + ) + + conn.create_table( + TableName=name, + KeySchema=[{"AttributeName": "forum_name", "KeyType": "HASH"}], + AttributeDefinitions=[{"AttributeName": "forum_name", "AttributeType": "S"}], + StreamSpecification={'StreamEnabled': True, 'StreamViewType': 'NEW_AND_OLD_IMAGES'}, + ProvisionedThroughput={"ReadCapacityUnits": 5, "WriteCapacityUnits": 5}, + ) + + conn.put_item( + TableName=name, + Item={ + "forum_name": {"S": "LOLCat Forum"}, + "subject": {"S": "Check this out!"}, + "Body": {"S": "http://url_to_lolcat.gif"}, + "SentBy": {"S": "test"}, + "Data": {"M": {"Key1": {"S": "Value1"}, "Key2": {"S": "Value2"}}} + }, + ) @requires_boto_gte("2.9") From 0a7d299da3594ca90082c2389c39dd3e750a57a8 Mon Sep 17 00:00:00 2001 From: Asher Foa <1268088+asherf@users.noreply.github.com> Date: Fri, 20 Dec 2019 11:18:04 -0800 Subject: [PATCH 2/5] Fix json encoding issue. --- moto/dynamodb2/models.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/moto/dynamodb2/models.py b/moto/dynamodb2/models.py index 121f564a4..784dfc5d7 100644 --- a/moto/dynamodb2/models.py +++ b/moto/dynamodb2/models.py @@ -586,7 +586,7 @@ class StreamRecord(BaseModel): self.record["dynamodb"]["OldImage"] = old_a # This is a substantial overestimate but it's the easiest to do now - self.record["dynamodb"]["SizeBytes"] = len(json.dumps(self.record["dynamodb"])) + self.record["dynamodb"]["SizeBytes"] = len(dynamo_json_dump(self.record["dynamodb"])) def to_json(self): return self.record From 5bd3827b26109199e03ed609c1020540dc101e69 Mon Sep 17 00:00:00 2001 From: Asher Foa <1268088+asherf@users.noreply.github.com> Date: Fri, 20 Dec 2019 11:30:36 -0800 Subject: [PATCH 3/5] run black --- moto/dynamodb2/models.py | 4 +++- tests/test_dynamodb2/test_dynamodb.py | 9 +++++++-- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/moto/dynamodb2/models.py b/moto/dynamodb2/models.py index 784dfc5d7..0a1b2679f 100644 --- a/moto/dynamodb2/models.py +++ b/moto/dynamodb2/models.py @@ -586,7 +586,9 @@ class StreamRecord(BaseModel): self.record["dynamodb"]["OldImage"] = old_a # This is a substantial overestimate but it's the easiest to do now - self.record["dynamodb"]["SizeBytes"] = len(dynamo_json_dump(self.record["dynamodb"])) + self.record["dynamodb"]["SizeBytes"] = len( + dynamo_json_dump(self.record["dynamodb"]) + ) def to_json(self): return self.record diff --git a/tests/test_dynamodb2/test_dynamodb.py b/tests/test_dynamodb2/test_dynamodb.py index 01768e8e4..a64ba4a8a 100644 --- a/tests/test_dynamodb2/test_dynamodb.py +++ b/tests/test_dynamodb2/test_dynamodb.py @@ -348,6 +348,8 @@ def test_put_item_with_special_chars(): '"': {"S": "foo"}, }, ) + + @requires_boto_gte("2.9") @mock_dynamodb2 def test_put_item_with_streams(): @@ -363,7 +365,10 @@ def test_put_item_with_streams(): TableName=name, KeySchema=[{"AttributeName": "forum_name", "KeyType": "HASH"}], AttributeDefinitions=[{"AttributeName": "forum_name", "AttributeType": "S"}], - StreamSpecification={'StreamEnabled': True, 'StreamViewType': 'NEW_AND_OLD_IMAGES'}, + StreamSpecification={ + "StreamEnabled": True, + "StreamViewType": "NEW_AND_OLD_IMAGES", + }, ProvisionedThroughput={"ReadCapacityUnits": 5, "WriteCapacityUnits": 5}, ) @@ -374,7 +379,7 @@ def test_put_item_with_streams(): "subject": {"S": "Check this out!"}, "Body": {"S": "http://url_to_lolcat.gif"}, "SentBy": {"S": "test"}, - "Data": {"M": {"Key1": {"S": "Value1"}, "Key2": {"S": "Value2"}}} + "Data": {"M": {"Key1": {"S": "Value1"}, "Key2": {"S": "Value2"}}}, }, ) From 299e7851d6bfbdbf0c10e18d1c3ae991a15428e1 Mon Sep 17 00:00:00 2001 From: Asher Foa <1268088+asherf@users.noreply.github.com> Date: Tue, 24 Dec 2019 10:23:46 -0800 Subject: [PATCH 4/5] Add assertions. --- tests/test_dynamodb2/test_dynamodb.py | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/tests/test_dynamodb2/test_dynamodb.py b/tests/test_dynamodb2/test_dynamodb.py index a64ba4a8a..773ff61e1 100644 --- a/tests/test_dynamodb2/test_dynamodb.py +++ b/tests/test_dynamodb2/test_dynamodb.py @@ -9,7 +9,7 @@ from boto3.dynamodb.conditions import Attr, Key import sure # noqa import requests from moto import mock_dynamodb2, mock_dynamodb2_deprecated -from moto.dynamodb2 import dynamodb_backend2 +from moto.dynamodb2 import dynamodb_backend2, dynamodb_backends2 from boto.exception import JSONResponseError from botocore.exceptions import ClientError, ParamValidationError from tests.helpers import requires_boto_gte @@ -383,6 +383,23 @@ def test_put_item_with_streams(): }, ) + result = conn.get_item(TableName=name, Key={"forum_name": {"S": "LOLCat Forum"}}) + + result["Item"].should.be.equal( + { + "forum_name": {"S": "LOLCat Forum"}, + "subject": {"S": "Check this out!"}, + "Body": {"S": "http://url_to_lolcat.gif"}, + "SentBy": {"S": "test"}, + "Data": {"M": {"Key1": {"S": "Value1"}, "Key2": {"S": "Value2"}}}, + } + ) + stream_shard = dynamodb_backends2["us-west-2"].get_table(name).stream_shard + len(stream_shard.items).should.be.equal(1) + stream_record = stream_shard.items[0].record + stream_record["eventName"].should.be.equal("INSERT") + stream_record["dynamodb"]["SizeBytes"].should.be.equal(447) + @requires_boto_gte("2.9") @mock_dynamodb2 From 7d4c15d53e41b19d8b341d38bba8c6caa9847100 Mon Sep 17 00:00:00 2001 From: Asher Foa <1268088+asherf@users.noreply.github.com> Date: Tue, 24 Dec 2019 11:01:54 -0800 Subject: [PATCH 5/5] skip part of the test in server mode. --- tests/test_dynamodb2/test_dynamodb.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/tests/test_dynamodb2/test_dynamodb.py b/tests/test_dynamodb2/test_dynamodb.py index 773ff61e1..831538054 100644 --- a/tests/test_dynamodb2/test_dynamodb.py +++ b/tests/test_dynamodb2/test_dynamodb.py @@ -394,9 +394,12 @@ def test_put_item_with_streams(): "Data": {"M": {"Key1": {"S": "Value1"}, "Key2": {"S": "Value2"}}}, } ) - stream_shard = dynamodb_backends2["us-west-2"].get_table(name).stream_shard - len(stream_shard.items).should.be.equal(1) - stream_record = stream_shard.items[0].record + table = dynamodb_backends2["us-west-2"].get_table(name) + if not table: + # There is no way to access stream data over the API, so this part can't run in server-tests mode. + return + len(table.stream_shard.items).should.be.equal(1) + stream_record = table.stream_shard.items[0].record stream_record["eventName"].should.be.equal("INSERT") stream_record["dynamodb"]["SizeBytes"].should.be.equal(447)