@@ -25,7 +25,9 @@ class TestDownloadList:
2525
2626 remove_files_async:
2727 - remove_files_removes_only_specified_files: selective version removal
28- - remove_files_mismatched_version_leaves_file_in_cart: wrong/omitted version is a no-op
28+ - remove_files_wrong_version_leaves_file_in_cart: wrong version is a no-op
29+ - remove_files_no_version_leaves_file_in_cart: omitted version does not match explicit version
30+ - remove_files_no_version_matches_no_version_entry: omitted version removes no-version entry
2931
3032 clear_async:
3133 - clear_empties_cart: empties the cart
@@ -140,9 +142,17 @@ async def test_add_files_with_no_version_number(
140142 schedule_for_cleanup : Callable [..., None ],
141143 ) -> None :
142144 """add_files_async() with version_number=None adds the latest version."""
143- # GIVEN an empty cart and a file in Synapse
145+ # GIVEN an empty cart and a file with two versions
144146 await DownloadList .clear_async (synapse_client = syn )
145147 file = await self ._create_test_file (project , syn , schedule_for_cleanup )
148+ v1 = file .version_number
149+
150+ new_path = utils .make_bogus_uuid_file ()
151+ schedule_for_cleanup (new_path )
152+ file .path = new_path
153+ await file .store_async (synapse_client = syn )
154+ v2 = file .version_number
155+ assert v2 != v1 , "Expected a new version number"
146156
147157 # WHEN I add the file without specifying a version number
148158 count = await DownloadList .add_files_async (
@@ -152,17 +162,20 @@ async def test_add_files_with_no_version_number(
152162 synapse_client = syn ,
153163 )
154164
155- # THEN the file is added to the cart
165+ # THEN the file is added to the cart with the latest version
156166 assert count == 1 , f"Expected 1 file added, got { count } "
157167
158168 manifest_path = await DownloadList .get_manifest_async (synapse_client = syn )
159169 schedule_for_cleanup (manifest_path )
160170 with open (manifest_path , newline = "" ) as f :
161171 reader = csv .DictReader (f )
162- ids_in_cart = { row [ "ID" ] for row in reader }
172+ rows = list ( reader )
163173 await DownloadList .clear_async (synapse_client = syn )
164174
165- assert file .id in ids_in_cart , f"Expected { file .id } in the cart"
175+ file_row = next (r for r in rows if r ["ID" ] == file .id )
176+ assert (
177+ int (file_row ["versionNumber" ]) == v2
178+ ), f"Expected latest version { v2 } , got { file_row ['versionNumber' ]} "
166179
167180 async def test_remove_files_removes_only_specified_files (
168181 self ,
@@ -228,35 +241,60 @@ async def test_remove_files_removes_only_specified_files(
228241 assert (file_b .id , file_b_v1 ) in cart_entries , "file_b v1 should remain"
229242 assert (file_b .id , file_b_v2 ) not in cart_entries , "file_b v2 should be removed"
230243
231- @pytest .mark .parametrize (
232- "use_wrong_version" , [True , False ], ids = ["wrong_version" , "no_version" ]
233- )
234- async def test_remove_files_mismatched_version_leaves_file_in_cart (
244+ async def test_remove_files_wrong_version_leaves_file_in_cart (
235245 self ,
236- use_wrong_version : bool ,
237246 project : Synapse_Project ,
238247 syn : Synapse ,
239248 schedule_for_cleanup : Callable [..., None ],
240249 ) -> None :
241- """remove_files() with a wrong or omitted version is a no-op -- the file
242- stays in the cart because the API requires an exact
243- (fileEntityId, versionNumber) pair."""
250+ """remove_files() with a wrong version is a no-op -- the file stays in the cart."""
244251 # GIVEN a cart with one file (added with an explicit version)
245252 await DownloadList .clear_async (synapse_client = syn )
246253 file = await self ._create_test_file (project , syn , schedule_for_cleanup )
247254 await self ._add_to_cart (file , syn )
248255
249- # WHEN I try to remove the file with a mismatched version
250- if use_wrong_version :
251- mismatch_item = DownloadListItem (
252- file_entity_id = file .id ,
253- version_number = (file .version_number or 1 ) + 99 ,
254- )
255- else :
256- mismatch_item = DownloadListItem (file_entity_id = file .id )
256+ # WHEN I try to remove the file with a wrong version number
257+ removed = await DownloadList .remove_files_async (
258+ files = [
259+ DownloadListItem (
260+ file_entity_id = file .id ,
261+ version_number = (file .version_number or 1 ) + 99 ,
262+ )
263+ ],
264+ synapse_client = syn ,
265+ )
266+
267+ # THEN no files are removed and the file remains in the cart
268+ assert removed == 0 , f"Expected 0 files removed, got { removed } "
269+
270+ manifest_path = await DownloadList .get_manifest_async (synapse_client = syn )
271+ schedule_for_cleanup (manifest_path )
272+
273+ with open (manifest_path , newline = "" ) as f :
274+ reader = csv .DictReader (f )
275+ ids_in_cart = {row ["ID" ] for row in reader }
276+
277+ await DownloadList .clear_async (synapse_client = syn )
278+
279+ assert file .id in ids_in_cart , f"Expected { file .id } to remain in the cart"
280+
281+ async def test_remove_files_no_version_leaves_file_in_cart (
282+ self ,
283+ project : Synapse_Project ,
284+ syn : Synapse ,
285+ schedule_for_cleanup : Callable [..., None ],
286+ ) -> None :
287+ """remove_files() with no version does not match a cart entry that was
288+ added with an explicit version -- the API requires an exact
289+ (fileEntityId, versionNumber) pair."""
290+ # GIVEN a cart with one file (added with an explicit version)
291+ await DownloadList .clear_async (synapse_client = syn )
292+ file = await self ._create_test_file (project , syn , schedule_for_cleanup )
293+ await self ._add_to_cart (file , syn )
257294
295+ # WHEN I try to remove the file without specifying a version
258296 removed = await DownloadList .remove_files_async (
259- files = [mismatch_item ],
297+ files = [DownloadListItem ( file_entity_id = file . id ) ],
260298 synapse_client = syn ,
261299 )
262300
@@ -274,6 +312,34 @@ async def test_remove_files_mismatched_version_leaves_file_in_cart(
274312
275313 assert file .id in ids_in_cart , f"Expected { file .id } to remain in the cart"
276314
315+ async def test_remove_files_no_version_matches_no_version_entry (
316+ self ,
317+ project : Synapse_Project ,
318+ syn : Synapse ,
319+ schedule_for_cleanup : Callable [..., None ],
320+ ) -> None :
321+ """remove_files() with no version removes a cart entry that was also
322+ added without a version."""
323+ # GIVEN a cart with one file added without a version number
324+ await DownloadList .clear_async (synapse_client = syn )
325+ file = await self ._create_test_file (project , syn , schedule_for_cleanup )
326+ await DownloadList .add_files_async (
327+ files = [DownloadListItem (file_entity_id = file .id )],
328+ synapse_client = syn ,
329+ )
330+
331+ # WHEN I remove the file without specifying a version
332+ removed = await DownloadList .remove_files_async (
333+ files = [DownloadListItem (file_entity_id = file .id )],
334+ synapse_client = syn ,
335+ )
336+
337+ # THEN the file is removed from the cart
338+ assert removed == 1 , f"Expected 1 file removed, got { removed } "
339+
340+ with pytest .raises (SynapseHTTPError , match = "No files available for download" ):
341+ await DownloadList .get_manifest_async (synapse_client = syn )
342+
277343 async def test_clear_empties_cart (
278344 self ,
279345 project : Synapse_Project ,
0 commit comments