@@ -2,6 +2,7 @@ package storage
22
33import (
44 "context"
5+ "fmt"
56 "net/url"
67 "os"
78 "path/filepath"
@@ -330,3 +331,158 @@ func (b *bufferWriter) Write(p []byte) (n int, err error) {
330331 * b .buf = append (* b .buf , p ... )
331332 return len (p ), nil
332333}
334+
335+ func TestLocalService_List_Empty (t * testing.T ) {
336+ basePath := t .TempDir ()
337+ svc := NewLocalService (basePath , "oregon" , "usr-123" )
338+
339+ result , err := svc .List (context .Background (), "" , 10 )
340+ require .NoError (t , err )
341+ require .Empty (t , result .Objects )
342+ require .Empty (t , result .Cursor )
343+ }
344+
345+ func TestLocalService_List_SingleFile (t * testing.T ) {
346+ basePath := t .TempDir ()
347+ svc := NewLocalService (basePath , "oregon" , "usr-123" )
348+
349+ // Upload a file
350+ key := "test/file.txt"
351+ srcFile := filepath .Join (t .TempDir (), "source.txt" )
352+ require .NoError (t , os .WriteFile (srcFile , []byte ("content" ), 0644 ))
353+ _ , err := svc .Upload (context .Background (), key , srcFile )
354+ require .NoError (t , err )
355+
356+ // List
357+ result , err := svc .List (context .Background (), "" , 10 )
358+ require .NoError (t , err )
359+ require .Len (t , result .Objects , 1 )
360+ require .Equal (t , key , result .Objects [0 ].Key )
361+ require .Equal (t , int64 (7 ), result .Objects [0 ].SizeBytes )
362+ require .Empty (t , result .Cursor ) // No more items
363+ }
364+
365+ func TestLocalService_List_MultipleFiles (t * testing.T ) {
366+ basePath := t .TempDir ()
367+ svc := NewLocalService (basePath , "oregon" , "usr-123" )
368+
369+ // Upload multiple files
370+ keys := []string {"a.txt" , "b.txt" , "c.txt" }
371+ for _ , key := range keys {
372+ srcFile := filepath .Join (t .TempDir (), "source.txt" )
373+ require .NoError (t , os .WriteFile (srcFile , []byte ("content" ), 0644 ))
374+ _ , err := svc .Upload (context .Background (), key , srcFile )
375+ require .NoError (t , err )
376+ }
377+
378+ // List all
379+ result , err := svc .List (context .Background (), "" , 10 )
380+ require .NoError (t , err )
381+ require .Len (t , result .Objects , len (keys ))
382+ require .Empty (t , result .Cursor ) // No more items
383+
384+ // Verify all keys are returned (order depends on filesystem)
385+ returnedKeys := extractKeys (result .Objects )
386+ require .ElementsMatch (t , keys , returnedKeys )
387+ }
388+
389+ // extractKeys returns the keys from a slice of ObjectInfo
390+ func extractKeys (objects []ObjectInfo ) []string {
391+ keys := make ([]string , len (objects ))
392+ for i , obj := range objects {
393+ keys [i ] = obj .Key
394+ }
395+ return keys
396+ }
397+
398+ func TestLocalService_List_Pagination (t * testing.T ) {
399+ basePath := t .TempDir ()
400+ svc := NewLocalService (basePath , "oregon" , "usr-123" )
401+
402+ // Upload 5 files
403+ for i := 0 ; i < 5 ; i ++ {
404+ key := fmt .Sprintf ("file%d.txt" , i )
405+ srcFile := filepath .Join (t .TempDir (), "source.txt" )
406+ require .NoError (t , os .WriteFile (srcFile , []byte ("content" ), 0644 ))
407+ _ , err := svc .Upload (context .Background (), key , srcFile )
408+ require .NoError (t , err )
409+ }
410+
411+ // List with limit 2
412+ result , err := svc .List (context .Background (), "" , 2 )
413+ require .NoError (t , err )
414+ require .Len (t , result .Objects , 2 )
415+ require .NotEmpty (t , result .Cursor ) // More items available
416+
417+ // List next page using cursor
418+ result2 , err := svc .List (context .Background (), result .Cursor , 2 )
419+ require .NoError (t , err )
420+ require .Len (t , result2 .Objects , 2 )
421+ require .NotEmpty (t , result2 .Cursor ) // Still more items
422+
423+ // List final page
424+ result3 , err := svc .List (context .Background (), result2 .Cursor , 2 )
425+ require .NoError (t , err )
426+ require .Len (t , result3 .Objects , 1 ) // Only 1 left
427+ require .Empty (t , result3 .Cursor ) // No more items
428+
429+ // Verify all unique keys returned
430+ allKeys := make (map [string ]bool )
431+ for _ , b := range result .Objects {
432+ allKeys [b .Key ] = true
433+ }
434+ for _ , b := range result2 .Objects {
435+ allKeys [b .Key ] = true
436+ }
437+ for _ , b := range result3 .Objects {
438+ allKeys [b .Key ] = true
439+ }
440+ require .Len (t , allKeys , 5 )
441+ }
442+
443+ func TestLocalService_List_PaginationEvenlyDivides (t * testing.T ) {
444+ basePath := t .TempDir ()
445+ svc := NewLocalService (basePath , "oregon" , "usr-123" )
446+
447+ // Upload exactly 4 files
448+ for i := 0 ; i < 4 ; i ++ {
449+ key := fmt .Sprintf ("file%d.txt" , i )
450+ srcFile := filepath .Join (t .TempDir (), "source.txt" )
451+ require .NoError (t , os .WriteFile (srcFile , []byte ("content" ), 0644 ))
452+ _ , err := svc .Upload (context .Background (), key , srcFile )
453+ require .NoError (t , err )
454+ }
455+
456+ // List with limit 2 (exactly divides total)
457+ result , err := svc .List (context .Background (), "" , 2 )
458+ require .NoError (t , err )
459+ require .Len (t , result .Objects , 2 )
460+ require .NotEmpty (t , result .Cursor )
461+
462+ // Second page - should return remaining 2 with no cursor
463+ result2 , err := svc .List (context .Background (), result .Cursor , 2 )
464+ require .NoError (t , err )
465+ require .Len (t , result2 .Objects , 2 )
466+ require .Empty (t , result2 .Cursor ) // No more items
467+ }
468+
469+ func TestLocalService_List_LimitEqualsTotal (t * testing.T ) {
470+ basePath := t .TempDir ()
471+ svc := NewLocalService (basePath , "oregon" , "usr-123" )
472+
473+ // Upload exactly 3 files
474+ numFiles := 3
475+ for i := 0 ; i < numFiles ; i ++ {
476+ key := fmt .Sprintf ("file%d.txt" , i )
477+ srcFile := filepath .Join (t .TempDir (), "source.txt" )
478+ require .NoError (t , os .WriteFile (srcFile , []byte ("content" ), 0644 ))
479+ _ , err := svc .Upload (context .Background (), key , srcFile )
480+ require .NoError (t , err )
481+ }
482+
483+ // List with limit = exact number of files
484+ result , err := svc .List (context .Background (), "" , numFiles )
485+ require .NoError (t , err )
486+ require .Len (t , result .Objects , numFiles )
487+ require .Empty (t , result .Cursor ) // No cursor when limit equals total
488+ }
0 commit comments