Skip to content

Commit 91b1e53

Browse files
author
Lucas McDonald
committed
sync
1 parent 38979de commit 91b1e53

File tree

3 files changed

+190
-77
lines changed

3 files changed

+190
-77
lines changed

DynamoDbEncryption/runtimes/python/src/aws_dbesdk_dynamodb/encrypted/table.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -328,6 +328,7 @@ def _table_operation_logic(
328328
329329
"""
330330
table_input = deepcopy(operation_input)
331+
331332
# EncryptedTable inputs are formatted as standard dictionaries, but DBESDK transformations expect DynamoDB JSON.
332333
# Convert from standard dictionaries to DynamoDB JSON.
333334
input_transform_input = input_resource_to_client_shape_transform_method(table_input)

DynamoDbEncryption/runtimes/python/test/integ/encrypted/test_table.py

Lines changed: 64 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
import uuid
2+
from copy import deepcopy
3+
14
import boto3
25
import pytest
36

@@ -10,7 +13,7 @@
1013
INTEG_TEST_DEFAULT_DYNAMODB_TABLE_NAME,
1114
INTEG_TEST_DEFAULT_TABLE_CONFIGS,
1215
)
13-
from ...items import complex_item_dict, simple_item_dict
16+
from ...items import complex_item_dict, complex_key_dict, simple_item_dict, simple_key_dict
1417
from ...requests import (
1518
basic_delete_item_request_dict,
1619
basic_get_item_request_dict,
@@ -58,13 +61,20 @@ def table(encrypted):
5861
return plaintext_table()
5962

6063

64+
@pytest.fixture(scope="module")
65+
def test_run_suffix():
66+
return "-" + str(uuid.uuid4())
67+
68+
6169
# Creates a matrix of tests for each value in param,
6270
# with a user-friendly string for test output:
6371
# use_complex_item = True -> "complex_item"
6472
# use_complex_item = False -> "simple_item"
6573
@pytest.fixture(params=[simple_item_dict, complex_item_dict], ids=["simple_item", "complex_item"])
66-
def test_item(request):
67-
return request.param
74+
def test_item(request, test_run_suffix):
75+
item = deepcopy(request.param)
76+
item["partition_key"] += test_run_suffix
77+
return item
6878

6979

7080
def test_GIVEN_item_WHEN_basic_put_AND_basic_get_AND_basic_delete_THEN_round_trip_passes(table, test_item):
@@ -99,51 +109,57 @@ def test_GIVEN_item_WHEN_basic_put_AND_basic_get_AND_basic_delete_THEN_round_tri
99109
assert "Item" not in get_response
100110

101111

112+
@pytest.fixture
113+
def multiple_test_items(test_run_suffix):
114+
"""Get two test items in the appropriate format for the client."""
115+
items = [deepcopy(simple_item_dict), deepcopy(complex_item_dict)]
116+
for item in items:
117+
item["partition_key"] += test_run_suffix
118+
return items
119+
120+
121+
@pytest.fixture
122+
def multiple_test_keys(test_run_suffix):
123+
"""Get two test keys in the appropriate format for the client."""
124+
keys = [deepcopy(simple_key_dict), deepcopy(complex_key_dict)]
125+
for key in keys:
126+
key["partition_key"] += test_run_suffix
127+
return keys
128+
129+
102130
def test_GIVEN_items_WHEN_batch_write_and_get_THEN_round_trip_passes(
103131
table,
132+
multiple_test_items,
133+
multiple_test_keys,
104134
):
105135
# Given: Simple and complex items in appropriate format for client
106136
# When: Batch put items
107137
with table.batch_writer() as batch_writer:
108138
# boto3 documentation for batch_writer.put_item() is incorrect;
109139
# the method accepts the item directly, not the item inside an "Item" key.
110-
batch_writer.put_item(simple_item_dict)
111-
batch_writer.put_item(complex_item_dict)
140+
for item in multiple_test_items:
141+
batch_writer.put_item(item)
112142

113143
# When: Get items
114-
get_item_request_dict = basic_get_item_request_dict(simple_item_dict)
115-
get_response = table.get_item(**get_item_request_dict)
116-
# Then: All items are encrypted and decrypted correctly
117-
assert get_response["ResponseMetadata"]["HTTPStatusCode"] == 200
118-
assert get_response["Item"] == simple_item_dict
119-
120-
get_item_request_dict = basic_get_item_request_dict(complex_item_dict)
121-
get_response = table.get_item(**get_item_request_dict)
122-
# Then: All items are encrypted and decrypted correctly
123-
assert get_response["ResponseMetadata"]["HTTPStatusCode"] == 200
124-
assert get_response["Item"] == complex_item_dict
144+
for item in multiple_test_items:
145+
get_item_request_dict = basic_get_item_request_dict(item)
146+
get_response = table.get_item(**get_item_request_dict)
147+
# Then: All items are encrypted and decrypted correctly
148+
assert get_response["ResponseMetadata"]["HTTPStatusCode"] == 200
149+
assert get_response["Item"] == item
125150

126151
# When: Batch delete items
127152
with table.batch_writer() as batch_writer:
128-
batch_writer.delete_item(
129-
{"partition_key": simple_item_dict["partition_key"], "sort_key": simple_item_dict["sort_key"]}
130-
)
131-
batch_writer.delete_item(
132-
{"partition_key": complex_item_dict["partition_key"], "sort_key": complex_item_dict["sort_key"]}
133-
)
153+
for key in multiple_test_keys:
154+
batch_writer.delete_item(key)
134155

135156
# When: Get items
136-
get_item_request_dict = basic_get_item_request_dict(simple_item_dict)
137-
get_response = table.get_item(**get_item_request_dict)
138-
# Then: All items are encrypted and decrypted correctly
139-
assert get_response["ResponseMetadata"]["HTTPStatusCode"] == 200
140-
assert "Item" not in get_response
141-
142-
get_item_request_dict = basic_get_item_request_dict(complex_item_dict)
143-
get_response = table.get_item(**get_item_request_dict)
144-
# Then: All items are encrypted and decrypted correctly
145-
assert get_response["ResponseMetadata"]["HTTPStatusCode"] == 200
146-
assert "Item" not in get_response
157+
for item in multiple_test_items:
158+
get_item_request_dict = basic_get_item_request_dict(item)
159+
get_response = table.get_item(**get_item_request_dict)
160+
# Then: All items are encrypted and decrypted correctly
161+
assert get_response["ResponseMetadata"]["HTTPStatusCode"] == 200
162+
assert "Item" not in get_response
147163

148164

149165
def test_GIVEN_items_in_table_WHEN_query_THEN_items_are_decrypted_correctly(table, test_item):
@@ -183,7 +199,10 @@ def test_GIVEN_valid_put_and_scan_requests_WHEN_put_and_scan_THEN_round_trip_pas
183199
# When: Scanning items
184200
scan_request_dict = scan_request
185201
scan_response = table.scan(**scan_request_dict)
186-
# Then: Scan returns both test items
202+
# Then: Scan succeeds
203+
# Can't assert anything about the scan;
204+
# there are too many items.
205+
# The critical assertion is that the scan succeeds.
187206
assert scan_response["ResponseMetadata"]["HTTPStatusCode"] == 200
188207

189208

@@ -228,3 +247,14 @@ def test_WHEN_call_passthrough_method_THEN_correct_response_is_returned():
228247
response = encrypted_table().table_name
229248
# Then: Correct response is returned, i.e. EncryptedTable forwards the call to the underlying boto3 table
230249
assert response == INTEG_TEST_DEFAULT_DYNAMODB_TABLE_NAME
250+
251+
252+
# Delete the items in the table after the module runs
253+
@pytest.fixture(scope="module", autouse=True)
254+
def cleanup_after_module(test_run_suffix):
255+
yield
256+
table = boto3.resource("dynamodb").Table(INTEG_TEST_DEFAULT_DYNAMODB_TABLE_NAME)
257+
items = [deepcopy(simple_item_dict), deepcopy(complex_item_dict)]
258+
for item in items:
259+
item["partition_key"] = item["partition_key"] + test_run_suffix
260+
table.delete_item(**basic_delete_item_request_dict(item))

0 commit comments

Comments
 (0)