22import pytest
33
44from aws_dbesdk_dynamodb .encrypted .table import EncryptedTable
5+ from aws_dbesdk_dynamodb .smithygenerated .aws_cryptography_dbencryptionsdk_dynamodb_transforms .errors import (
6+ DynamoDbEncryptionTransformsException ,
7+ )
58
69from ...constants import (
710 INTEG_TEST_DEFAULT_DYNAMODB_TABLE_NAME ,
811 INTEG_TEST_DEFAULT_TABLE_CONFIGS ,
912)
1013from ...items import complex_item_dict , simple_item_dict
1114from ...requests import (
15+ basic_delete_item_request_dict ,
1216 basic_get_item_request_dict ,
1317 basic_put_item_request_dict ,
1418 basic_query_request_dict ,
1519 basic_scan_request_dict ,
20+ basic_update_item_request_dict_signed_attribute ,
21+ basic_update_item_request_dict_unsigned_attribute ,
1622)
1723
1824
@@ -61,21 +67,37 @@ def test_item(request):
6167 return request .param
6268
6369
64- def test_GIVEN_item_WHEN_basic_put_and_basic_get_THEN_round_trip_passes (table , test_item ):
65- """Test put_item and get_item operations."""
66- # Given: Simple and complex items in appropriate format for client
70+ def test_GIVEN_item_WHEN_basic_put_AND_basic_get_AND_basic_delete_THEN_round_trip_passes (table , test_item ):
71+ """Test put_item, get_item, and delete_item operations."""
72+ # Given: Valid put_item request
6773 put_item_request_dict = basic_put_item_request_dict (test_item )
68-
69- # When: Putting and getting item
74+ # When: put_item
7075 put_response = table .put_item (** put_item_request_dict )
76+ # Then: put_item succeeds
7177 assert put_response ["ResponseMetadata" ]["HTTPStatusCode" ] == 200
7278
79+ # Given: Valid get_item request for the same item
7380 get_item_request_dict = basic_get_item_request_dict (test_item )
81+ # When: get_item
7482 get_response = table .get_item (** get_item_request_dict )
7583 # Then: Simple item is encrypted and decrypted correctly
7684 assert get_response ["ResponseMetadata" ]["HTTPStatusCode" ] == 200
7785 assert get_response ["Item" ] == put_item_request_dict ["Item" ]
7886
87+ # Given: Valid delete_item request for the same item
88+ delete_item_request_dict = basic_delete_item_request_dict (test_item )
89+ # When: delete_item
90+ delete_response = table .delete_item (** delete_item_request_dict )
91+ # Then: delete_item succeeds
92+ assert delete_response ["ResponseMetadata" ]["HTTPStatusCode" ] == 200
93+
94+ # Given: Valid get_item request for the same item
95+ get_item_request_dict = basic_get_item_request_dict (test_item )
96+ # When: get_item
97+ get_response = table .get_item (** get_item_request_dict )
98+ # Then: get_item is empty (i.e. the item was deleted)
99+ assert "Item" not in get_response
100+
79101
80102def test_GIVEN_items_WHEN_batch_write_and_get_THEN_round_trip_passes (
81103 table ,
@@ -154,7 +176,6 @@ def scan_request(encrypted, test_item):
154176
155177
156178def test_GIVEN_valid_put_and_scan_requests_WHEN_put_and_scan_THEN_round_trip_passes (table , test_item , scan_request ):
157- """Test put_item and scan operations."""
158179 # Given: Simple and complex items in appropriate format for client
159180 put_item_request_dict = basic_put_item_request_dict (test_item )
160181 table .put_item (** put_item_request_dict )
@@ -166,24 +187,44 @@ def test_GIVEN_valid_put_and_scan_requests_WHEN_put_and_scan_THEN_round_trip_pas
166187 assert scan_response ["ResponseMetadata" ]["HTTPStatusCode" ] == 200
167188
168189
169- def test_WHEN_update_item_THEN_raises_not_implemented_error ():
170- # Given: Encrypted client and update item parameters
190+ def test_GIVEN_update_for_unsigned_attribute_WHEN_update_item_THEN_passes (table , test_item ):
191+ # Given: some item is already in the table
192+ put_response = table .put_item (** basic_put_item_request_dict (test_item ))
193+ assert put_response ["ResponseMetadata" ]["HTTPStatusCode" ] == 200
194+
195+ # Given: Valid update item request for unsigned attribute
196+ update_item_request = basic_update_item_request_dict_unsigned_attribute (test_item )
197+
171198 # When: Calling update_item
172- with pytest .raises (NotImplementedError ):
173- encrypted_table ().update_item (
174- TableName = INTEG_TEST_DEFAULT_DYNAMODB_TABLE_NAME ,
175- Key = {"partition_key" : "test-key" , "sort_key" : 1 },
176- UpdateExpression = "SET attribute1 = :val" ,
177- ExpressionAttributeValues = {":val" : {"S" : "new value" }},
178- )
179- # Then: NotImplementedError is raised
199+ update_response = table .update_item (** update_item_request )
200+ # Then: update_item succeeds
201+ assert update_response ["ResponseMetadata" ]["HTTPStatusCode" ] == 200
202+
203+
204+ def test_GIVEN_update_for_signed_attribute_WHEN_update_item_THEN_raises_DynamoDbEncryptionTransformsException (
205+ table , test_item , encrypted
206+ ):
207+ if not encrypted :
208+ pytest .skip ("Skipping negative test for plaintext client" )
209+
210+ # Given: some item is already in the table
211+ put_response = table .put_item (** basic_put_item_request_dict (test_item ))
212+ assert put_response ["ResponseMetadata" ]["HTTPStatusCode" ] == 200
213+
214+ # Given: Valid update item request for signed attribute
215+ update_item_request = basic_update_item_request_dict_signed_attribute (test_item )
216+
217+ # Then: raises DynamoDbEncryptionTransformsException
218+ with pytest .raises (DynamoDbEncryptionTransformsException ):
219+ # When: Calling update_item
220+ table .update_item (** update_item_request )
180221
181222
182223def test_WHEN_call_passthrough_method_THEN_correct_response_is_returned ():
183224 """Test that calling a passthrough method returns the correct response."""
184- # Given: Encrypted client
185- # When: Calling some passthrough method that does not explicitly exist on EncryptedClient ,
186- # but exists on the underlying boto3 client
187- response = encrypted_table ().meta . client . list_backups ()
188- # Then: Correct response is returned, i.e. EncryptedClient forwards the call to the underlying boto3 client
189- assert response [ "ResponseMetadata" ][ "HTTPStatusCode" ] == 200
225+ # Given: Encrypted or plaintext table
226+ # When: Calling some passthrough method that does not explicitly exist on EncryptedTable ,
227+ # but exists on the underlying boto3 table
228+ response = encrypted_table ().table_name
229+ # Then: Correct response is returned, i.e. EncryptedTable forwards the call to the underlying boto3 table
230+ assert response == INTEG_TEST_DEFAULT_DYNAMODB_TABLE_NAME
0 commit comments