3
3
4
4
from aws_dbesdk_dynamodb .encrypted .client import EncryptedClient
5
5
6
+ from . import sort_dynamodb_json_lists
7
+
6
8
from ...constants import (
7
9
INTEG_TEST_DEFAULT_DYNAMODB_TABLE_NAME ,
8
10
INTEG_TEST_DEFAULT_TABLE_CONFIGS ,
21
23
basic_put_item_request_ddb ,
22
24
basic_put_item_request_dict ,
23
25
basic_query_paginator_request ,
24
- basic_scan_request_ddb ,
25
- basic_scan_request_dict ,
26
+ basic_scan_paginator_request ,
26
27
)
27
28
28
- BOTO3_CLIENT = boto3 .client ("dynamodb" )
29
- ENCRYPTED_CLIENT = EncryptedClient (client = BOTO3_CLIENT , encryption_config = INTEG_TEST_DEFAULT_TABLE_CONFIGS )
30
- SCAN_PAGINATOR = ENCRYPTED_CLIENT .get_paginator ("scan" )
31
- QUERY_PAGINATOR = ENCRYPTED_CLIENT .get_paginator ("query" )
32
-
33
29
30
+ # Creates a matrix of tests for each value in param,
31
+ # with a user-friendly string for test output:
32
+ # expect_standard_dictionaries = True -> "standard_dicts"
33
+ # expect_standard_dictionaries = False -> "ddb_json"
34
34
@pytest .fixture (params = [True , False ], ids = ["standard_dicts" , "ddb_json" ])
35
35
def expect_standard_dictionaries (request ):
36
36
return request .param
@@ -52,6 +52,10 @@ def plaintext_client(expect_standard_dictionaries):
52
52
return client
53
53
54
54
55
+ # Creates a matrix of tests for each value in param,
56
+ # with a user-friendly string for test output:
57
+ # encrypted = True -> "encrypted"
58
+ # encrypted = False -> "plaintext"
55
59
@pytest .fixture (params = [True , False ], ids = ["encrypted" , "plaintext" ])
56
60
def encrypted (request ):
57
61
return request .param
@@ -74,7 +78,10 @@ def query_paginator(client):
74
78
def scan_paginator (client ):
75
79
return client .get_paginator ("scan" )
76
80
77
-
81
+ # Creates a matrix of tests for each value in param,
82
+ # with a user-friendly string for test output:
83
+ # use_complex_item = True -> "complex_item"
84
+ # use_complex_item = False -> "simple_item"
78
85
@pytest .fixture (params = [True , False ], ids = ["complex_item" , "simple_item" ])
79
86
def use_complex_item (request ):
80
87
return request .param
@@ -127,23 +134,6 @@ def put_item_request(expect_standard_dictionaries, test_item):
127
134
return {** basic_put_item_request_dict (test_item ), "TableName" : INTEG_TEST_DEFAULT_DYNAMODB_TABLE_NAME }
128
135
return basic_put_item_request_ddb (test_item )
129
136
130
-
131
- def sort_dynamodb_json_lists (obj ):
132
- """
133
- Utility that recursively sorts all lists in a DynamoDB JSON-like structure.
134
- DynamoDB JSON uses lists to represent sets, so strict equality can fail.
135
- Sort lists to ensure consistent ordering when comparing expected and actual items.
136
- """
137
- if isinstance (obj , dict ):
138
- return {k : sort_dynamodb_json_lists (v ) for k , v in obj .items ()}
139
- elif isinstance (obj , list ):
140
- try :
141
- return sorted (obj ) # Sort lists for consistent comparison
142
- except TypeError :
143
- return obj # Not all lists are sortable; ex. complex_item_ddb's "list" attribute
144
- return obj
145
-
146
-
147
137
def test_GIVEN_query_paginator_WHEN_paginate_THEN_returns_expected_items (
148
138
client , query_paginator , paginate_query_request , put_item_request , test_item
149
139
):
@@ -168,15 +158,11 @@ def test_GIVEN_query_paginator_WHEN_paginate_THEN_returns_expected_items(
168
158
169
159
170
160
@pytest .fixture
171
- def paginate_scan_request (expect_standard_dictionaries , encrypted , test_item ):
161
+ def paginate_scan_request (expect_standard_dictionaries , test_item ):
172
162
if expect_standard_dictionaries :
173
- request = {** basic_scan_request_dict (test_item ), "TableName" : INTEG_TEST_DEFAULT_DYNAMODB_TABLE_NAME }
163
+ request = {** basic_scan_paginator_request (test_item ), "TableName" : INTEG_TEST_DEFAULT_DYNAMODB_TABLE_NAME }
174
164
else :
175
- request = basic_scan_request_ddb (test_item )
176
- if encrypted :
177
- request ["FilterExpression" ] = request ["FilterExpression" ] + " AND attribute_exists (#sig)"
178
- request ["ExpressionAttributeNames" ] = {}
179
- request ["ExpressionAttributeNames" ]["#sig" ] = "amzn-ddb-map-sig"
165
+ request = basic_scan_paginator_request (test_item )
180
166
return request
181
167
182
168
@@ -194,70 +180,10 @@ def test_GIVEN_scan_paginator_WHEN_paginate_THEN_returns_expected_items(
194
180
if "Items" in page :
195
181
for item in page ["Items" ]:
196
182
items .append (item )
197
-
198
-
199
- # TODO: set up scan table and tests
200
-
201
- # @pytest.fixture
202
- # def default_requests(simple_item_ddb):
203
- # """Fixture to provide default scan and query requests."""
204
- # return {
205
- # "scan": get_scan_request(simple_item_ddb["partition_key"]),
206
- # "query": get_query_request(simple_item_ddb["partition_key"]),
207
- # }
208
-
209
- # @pytest.fixture(scope="module", autouse=True)
210
- # def setup_module_fixture(simple_item_ddb):
211
- # # Runs before all tests in this module
212
- # for i in range(10):
213
- # ENCRYPTED_CLIENT.put_item(
214
- # TableName=INTEG_TEST_DEFAULT_DYNAMODB_TABLE_NAME,
215
- # Item={
216
- # "partition_key": simple_item_ddb["partition_key"],
217
- # "sort_key": {"N": str(i)},
218
- # "attribute1": {"S": "encrypt and sign me!"},
219
- # "attribute2": {"S": "sign me!"},
220
- # ":attribute3": {"S": "ignore me!"},
221
- # },
222
- # )
223
- # # Yield to all tests in this module
224
- # yield
225
- # # TODO: Delete items? not needed but nice
226
-
227
- # @pytest.mark.parametrize("paginator_name, request_key", [
228
- # ("scan", "scan"),
229
- # ("query", "query")
230
- # ])
231
- # def test_GIVEN_incomplete_search_WHEN_build_full_result_THEN_NextToken_completes_search(
232
- # paginator_name,
233
- # request_key,
234
- # default_requests,
235
- # ):
236
- # # TODO: test
237
- # return
238
- # # Given: PaginationConfig that will result in an incomplete search.
239
- # # There are 10 items, and returning 2 per operation results in multiple uses of NextToken.
240
- # pagination_config = {
241
- # "MaxItems": 2,
242
- # }
243
-
244
- # paginator = getattr(ENCRYPTED_CLIENT, f"get_paginator")(paginator_name)
245
- # incomplete_search_request = default_requests[request_key].copy()
246
- # incomplete_search_request["PaginationConfig"] = pagination_config
247
-
248
- # # When: Build full result from paginator
249
- # full_result = paginator.paginate(**incomplete_search_request)
250
-
251
- # print(f"{full_result=}")
252
-
253
- # collected_items = []
254
-
255
- # print(f'{full_result=}')
256
-
257
- # for item in full_result:
258
- # # assert item["attribute1"]["S"] == "encrypt and sign me!"
259
- # collected_items.append(item)
260
-
261
- # # Then: NextToken should be present
262
- # # assert "NextToken" in full_result
263
- # # Then: NextToken is able to complete the search
183
+ assert len (items ) == 1
184
+ # DynamoDB JSON uses lists to represent sets, so strict equality can fail.
185
+ # Sort lists to ensure consistent ordering when comparing expected and actual items.
186
+ expected_item = sort_dynamodb_json_lists (test_item )
187
+ actual_item = sort_dynamodb_json_lists (items [0 ])
188
+ # Then: Items are equal
189
+ assert expected_item == actual_item
0 commit comments