@@ -168,6 +168,25 @@ async def test_upload_and_search(
168168 assert file .file_name in {"file1" , "file2" }
169169
170170
171+ async def _search_files_by_pattern (
172+ simcore_s3_dsm : SimcoreS3DataManager ,
173+ user_id : UserID ,
174+ name_pattern : str ,
175+ project_id : ProjectID | None = None ,
176+ items_per_page : int = 10 ,
177+ ) -> list [FileMetaData ]:
178+ """Helper function to search files and collect all results."""
179+ results = []
180+ async for page in simcore_s3_dsm .search (
181+ user_id = user_id ,
182+ name_pattern = name_pattern ,
183+ project_id = project_id ,
184+ items_per_page = items_per_page ,
185+ ):
186+ results .extend (page )
187+ return results
188+
189+
171190@pytest .mark .parametrize (
172191 "location_id" ,
173192 [SimcoreS3DataManager .get_location_id ()],
@@ -191,6 +210,11 @@ async def test_search_files(
191210 ("backup_file.bak" , "backup_*" ),
192211 ("config.json" , "*.json" ),
193212 ("temp_data.tmp" , "temp_*" ),
213+ ("file_a.log" , "file_?.log" ),
214+ ("file_b.log" , "file_?.log" ),
215+ ("file_10.log" , "file_??.log" ),
216+ ("report1.txt" , "report?.txt" ),
217+ ("report2.txt" , "report?.txt" ),
194218 ]
195219
196220 uploaded_files = []
@@ -200,70 +224,42 @@ async def test_search_files(
200224 uploaded_files .append ((file_name , file_id , checksum ))
201225
202226 # Test 1: Search for all .txt files
203- txt_results = []
204- async for page in simcore_s3_dsm .search (
205- user_id = user_id ,
206- name_pattern = "*.txt" ,
207- project_id = project_id ,
208- items_per_page = 10 ,
209- ):
210- txt_results .extend (page )
211-
212- # Should find 2 txt files
213- assert len (txt_results ) == 2
227+ txt_results = await _search_files_by_pattern (
228+ simcore_s3_dsm , user_id , "*.txt" , project_id
229+ )
230+ assert (
231+ len (txt_results ) == 4
232+ ) # test_file1.txt, test_file2.txt, report1.txt, report2.txt
214233 txt_names = {file .file_name for file in txt_results }
215- assert txt_names == {"test_file1.txt" , "test_file2.txt" }
234+ assert txt_names == {
235+ "test_file1.txt" ,
236+ "test_file2.txt" ,
237+ "report1.txt" ,
238+ "report2.txt" ,
239+ }
216240
217241 # Test 2: Search with specific prefix pattern
218- data_results = []
219- async for page in simcore_s3_dsm .search (
220- user_id = user_id ,
221- name_pattern = "data_*" ,
222- project_id = project_id ,
223- items_per_page = 10 ,
224- ):
225- data_results .extend (page )
226-
227- # Should find 1 data file
242+ data_results = await _search_files_by_pattern (
243+ simcore_s3_dsm , user_id , "data_*" , project_id
244+ )
228245 assert len (data_results ) == 1
229246 assert data_results [0 ].file_name == "data_file.csv"
230247
231248 # Test 3: Search with pattern that matches multiple extensions
232- temp_results = []
233- async for page in simcore_s3_dsm .search (
234- user_id = user_id ,
235- name_pattern = "temp_*" ,
236- project_id = project_id ,
237- items_per_page = 10 ,
238- ):
239- temp_results .extend (page )
240-
241- # Should find 1 temp file
249+ temp_results = await _search_files_by_pattern (
250+ simcore_s3_dsm , user_id , "temp_*" , project_id
251+ )
242252 assert len (temp_results ) == 1
243253 assert temp_results [0 ].file_name == "temp_data.tmp"
244254
245255 # Test 4: Search with pattern that doesn't match anything
246- no_match_results = []
247- async for page in simcore_s3_dsm .search (
248- user_id = user_id ,
249- name_pattern = "nonexistent_*" ,
250- project_id = project_id ,
251- items_per_page = 10 ,
252- ):
253- no_match_results .extend (page )
254-
256+ no_match_results = await _search_files_by_pattern (
257+ simcore_s3_dsm , user_id , "nonexistent_*" , project_id
258+ )
255259 assert len (no_match_results ) == 0
256260
257261 # Test 5: Search without project_id restriction (all accessible projects)
258- all_results = []
259- async for page in simcore_s3_dsm .search (
260- user_id = user_id ,
261- name_pattern = "*" ,
262- items_per_page = 10 ,
263- ):
264- all_results .extend (page )
265-
266- # Should find at least our uploaded files
262+ all_results = await _search_files_by_pattern (simcore_s3_dsm , user_id , "*" )
267263 assert len (all_results ) >= len (test_files )
268264
269265 # Verify that each result has expected FileMetaData structure
@@ -274,7 +270,33 @@ async def test_search_files(
274270 assert file_meta .user_id == user_id
275271 assert file_meta .project_id is not None
276272
277- # Test 6: Test pagination with small page size
273+ # Test 6: Test ? wildcard - single character match
274+ single_char_results = await _search_files_by_pattern (
275+ simcore_s3_dsm , user_id , "file_?.log" , project_id
276+ )
277+ # Should find 2 files: file_a.log and file_b.log (but not file_10.log)
278+ assert len (single_char_results ) == 2
279+ single_char_names = {file .file_name for file in single_char_results }
280+ assert single_char_names == {"file_a.log" , "file_b.log" }
281+
282+ # Test 7: Test ?? wildcard - two character match
283+ double_char_results = await _search_files_by_pattern (
284+ simcore_s3_dsm , user_id , "file_??.log" , project_id
285+ )
286+ # Should find 1 file: file_10.log
287+ assert len (double_char_results ) == 1
288+ assert double_char_results [0 ].file_name == "file_10.log"
289+
290+ # Test 8: Test ? wildcard with specific prefix and suffix
291+ report_results = await _search_files_by_pattern (
292+ simcore_s3_dsm , user_id , "report?.txt" , project_id
293+ )
294+ # Should find 2 files: report1.txt and report2.txt
295+ assert len (report_results ) == 2
296+ report_names = {file .file_name for file in report_results }
297+ assert report_names == {"report1.txt" , "report2.txt" }
298+
299+ # Test 9: Test pagination with small page size
278300 paginated_results = []
279301 page_count = 0
280302 async for page in simcore_s3_dsm .search (
@@ -289,7 +311,7 @@ async def test_search_files(
289311 assert len (page ) <= 2
290312
291313 # Should have multiple pages and all our files
292- assert page_count >= 4 # At least 7 files / 2 per page = 4 pages
314+ assert page_count >= 6 # At least 12 files / 2 per page = 6 pages
293315 assert len (paginated_results ) == len (test_files )
294316
295317
0 commit comments