@@ -431,10 +431,10 @@ func TestGCSListFilePaths(t *testing.T) {
431
431
require .NoError (t , err )
432
432
t .Cleanup (func () { _ = store .Close () })
433
433
434
- paths , err := store .ListFilePaths (context .Background (), "" , 2 )
434
+ paths , err := store .ListFilePaths (context .Background (), ListFileOptions { Limit : 2 } )
435
435
require .NoError (t , err )
436
436
437
- require .Equal (t , []string {"objects/testnet/ a" , "objects/testnet/ b" }, paths )
437
+ require .Equal (t , []string {"a" , "b" }, paths )
438
438
}
439
439
440
440
func TestGCSListFilePaths_WithPrefix (t * testing.T ) {
@@ -458,9 +458,9 @@ func TestGCSListFilePaths_WithPrefix(t *testing.T) {
458
458
require .NoError (t , err )
459
459
t .Cleanup (func () { _ = store .Close () })
460
460
461
- paths , err := store .ListFilePaths (context .Background (), "a" , 10 )
461
+ paths , err := store .ListFilePaths (context .Background (), ListFileOptions { Prefix : "a" , Limit : 10 } )
462
462
require .NoError (t , err )
463
- require .Equal (t , []string {"objects/testnet/ a/x" , "objects/testnet/ a/y" }, paths )
463
+ require .Equal (t , []string {"a/x" , "a/y" }, paths )
464
464
}
465
465
466
466
func TestGCSListFilePaths_LimitDefaultAndCap (t * testing.T ) {
@@ -478,11 +478,164 @@ func TestGCSListFilePaths_LimitDefaultAndCap(t *testing.T) {
478
478
require .NoError (t , err )
479
479
t .Cleanup (func () { _ = store .Close () })
480
480
481
- paths , err := store .ListFilePaths (context .Background (), "" , 0 )
481
+ paths , err := store .ListFilePaths (context .Background (), ListFileOptions {} )
482
482
require .NoError (t , err )
483
483
require .Equal (t , 1000 , len (paths ))
484
484
485
- paths , err = store .ListFilePaths (context .Background (), "" , 5000 )
485
+ paths , err = store .ListFilePaths (context .Background (), ListFileOptions { Limit : 5000 } )
486
486
require .NoError (t , err )
487
487
require .Equal (t , 1000 , len (paths ))
488
488
}
489
+
490
+ func TestGCSListFilePaths_StartAfter (t * testing.T ) {
491
+ t .Run ("basic start-after (no Prefix)" , func (t * testing.T ) {
492
+ objects := make ([]fakestorage.Object , 0 , 11 )
493
+ for i := 0 ; i < 10 ; i ++ {
494
+ objects = append (objects , fakestorage.Object {
495
+ ObjectAttrs : fakestorage.ObjectAttrs {
496
+ BucketName : "test-bucket" ,
497
+ Name : fmt .Sprintf ("objects/testnet/%04d" , i )},
498
+ Content : []byte ("x" ),
499
+ })
500
+ }
501
+ // decoy outside the prefix directory style
502
+ objects = append (objects , fakestorage.Object {
503
+ ObjectAttrs : fakestorage.ObjectAttrs {BucketName : "test-bucket" , Name : "objects/testnet-foo/0000" },
504
+ Content : []byte ("x" ),
505
+ })
506
+
507
+ server := fakestorage .NewServer (objects )
508
+ defer server .Stop ()
509
+
510
+ store , err := FromGCSClient (context .Background (), server .Client (), "test-bucket/objects/testnet" )
511
+ require .NoError (t , err )
512
+ t .Cleanup (func () { _ = store .Close () })
513
+
514
+ paths , err := store .ListFilePaths (context .Background (), ListFileOptions {
515
+ StartAfter : "0005" ,
516
+ })
517
+ require .NoError (t , err )
518
+ require .Equal (t , []string {"0006" , "0007" , "0008" , "0009" }, paths ,
519
+ "should start strictly after 0005 and trim prefix" )
520
+ })
521
+
522
+ t .Run ("with Prefix directory and start-after inside it" , func (t * testing.T ) {
523
+ objects := []fakestorage.Object {
524
+ {ObjectAttrs : fakestorage.ObjectAttrs {BucketName : "test-bucket" , Name : "objects/testnet/a/0001" }},
525
+ {ObjectAttrs : fakestorage.ObjectAttrs {BucketName : "test-bucket" , Name : "objects/testnet/a/0002" }},
526
+ {ObjectAttrs : fakestorage.ObjectAttrs {BucketName : "test-bucket" , Name : "objects/testnet/b/0002" }}, // different subdir
527
+ // decoy outside the prefix directory style
528
+ {ObjectAttrs : fakestorage.ObjectAttrs {BucketName : "test-bucket" , Name : "objects/testnet-foo/0002" }},
529
+ }
530
+ server := fakestorage .NewServer (objects )
531
+ defer server .Stop ()
532
+
533
+ store , err := FromGCSClient (context .Background (), server .Client (), "test-bucket/objects/testnet" )
534
+ require .NoError (t , err )
535
+ t .Cleanup (func () { _ = store .Close () })
536
+
537
+ paths , err := store .ListFilePaths (context .Background (), ListFileOptions {
538
+ Prefix : "a/" ,
539
+ StartAfter : "a/0001" ,
540
+ })
541
+ require .NoError (t , err )
542
+ require .Equal (t , []string {"a/0002" }, paths )
543
+ })
544
+
545
+ t .Run ("start-after equals last key -> empty" , func (t * testing.T ) {
546
+ objects := []fakestorage.Object {
547
+ {ObjectAttrs : fakestorage.ObjectAttrs {BucketName : "test-bucket" , Name : "objects/testnet/0000" }},
548
+ {ObjectAttrs : fakestorage.ObjectAttrs {BucketName : "test-bucket" , Name : "objects/testnet/0001" }},
549
+ {ObjectAttrs : fakestorage.ObjectAttrs {BucketName : "test-bucket" , Name : "objects/testnet/0002" }},
550
+ // decoy outside the prefix directory style
551
+ {ObjectAttrs : fakestorage.ObjectAttrs {BucketName : "test-bucket" , Name : "objects/testnet-foo/0002" }},
552
+ }
553
+ server := fakestorage .NewServer (objects )
554
+ defer server .Stop ()
555
+
556
+ store , err := FromGCSClient (context .Background (), server .Client (), "test-bucket/objects/testnet" )
557
+ require .NoError (t , err )
558
+ t .Cleanup (func () { _ = store .Close () })
559
+
560
+ paths , err := store .ListFilePaths (context .Background (), ListFileOptions {
561
+ StartAfter : "0002" ,
562
+ })
563
+ require .NoError (t , err )
564
+ require .Empty (t , paths )
565
+ })
566
+
567
+ t .Run ("start-after before first key -> all returned" , func (t * testing.T ) {
568
+ objects := []fakestorage.Object {
569
+ {ObjectAttrs : fakestorage.ObjectAttrs {BucketName : "test-bucket" , Name : "objects/testnet/0001" }},
570
+ {ObjectAttrs : fakestorage.ObjectAttrs {BucketName : "test-bucket" , Name : "objects/testnet/0002" }},
571
+ {ObjectAttrs : fakestorage.ObjectAttrs {BucketName : "test-bucket" , Name : "objects/testnet/0003" }},
572
+ // decoy outside the prefix directory style
573
+ {ObjectAttrs : fakestorage.ObjectAttrs {BucketName : "test-bucket" , Name : "objects/testnet-foo/0002" }},
574
+ }
575
+ server := fakestorage .NewServer (objects )
576
+ defer server .Stop ()
577
+
578
+ store , err := FromGCSClient (context .Background (), server .Client (), "test-bucket/objects/testnet" )
579
+ require .NoError (t , err )
580
+ t .Cleanup (func () { _ = store .Close () })
581
+
582
+ paths , err := store .ListFilePaths (context .Background (), ListFileOptions {
583
+ StartAfter : "0000" ,
584
+ })
585
+ require .NoError (t , err )
586
+ require .Equal (t , []string {"0001" , "0002" , "0003" }, paths )
587
+ })
588
+
589
+ t .Run ("start-after missing-but-between keys -> next greater" , func (t * testing.T ) {
590
+ objects := []fakestorage.Object {
591
+ {ObjectAttrs : fakestorage.ObjectAttrs {BucketName : "test-bucket" , Name : "objects/testnet/0002" }},
592
+ {ObjectAttrs : fakestorage.ObjectAttrs {BucketName : "test-bucket" , Name : "objects/testnet/0004" }},
593
+ {ObjectAttrs : fakestorage.ObjectAttrs {BucketName : "test-bucket" , Name : "objects/testnet/0006" }},
594
+ // decoy outside the prefix directory style
595
+ {ObjectAttrs : fakestorage.ObjectAttrs {BucketName : "test-bucket" , Name : "objects/testnet-foo/0002" }},
596
+ }
597
+ server := fakestorage .NewServer (objects )
598
+ defer server .Stop ()
599
+
600
+ store , err := FromGCSClient (context .Background (), server .Client (), "test-bucket/objects/testnet" )
601
+ require .NoError (t , err )
602
+ t .Cleanup (func () { _ = store .Close () })
603
+
604
+ paths , err := store .ListFilePaths (context .Background (), ListFileOptions {
605
+ StartAfter : "0003" ,
606
+ })
607
+ require .NoError (t , err )
608
+ require .Equal (t , []string {"0004" , "0006" }, paths )
609
+ })
610
+
611
+ t .Run ("respects limit together with start-after" , func (t * testing.T ) {
612
+ objects := make ([]fakestorage.Object , 0 , 10 )
613
+ for i := 0 ; i < 10 ; i ++ {
614
+ objects = append (objects , fakestorage.Object {
615
+ ObjectAttrs : fakestorage.ObjectAttrs {
616
+ BucketName : "test-bucket" ,
617
+ Name : fmt .Sprintf ("objects/testnet/%04d" , i )},
618
+ Content : []byte ("x" ),
619
+ })
620
+ }
621
+ // decoy outside the prefix directory style
622
+ objects = append (objects , fakestorage.Object {
623
+ ObjectAttrs : fakestorage.ObjectAttrs {BucketName : "test-bucket" , Name : "objects/testnet-foo/0002" },
624
+ Content : []byte ("x" ),
625
+ })
626
+
627
+ server := fakestorage .NewServer (objects )
628
+ defer server .Stop ()
629
+
630
+ store , err := FromGCSClient (context .Background (), server .Client (), "test-bucket/objects/testnet" )
631
+ require .NoError (t , err )
632
+ t .Cleanup (func () { _ = store .Close () })
633
+
634
+ paths , err := store .ListFilePaths (context .Background (), ListFileOptions {
635
+ StartAfter : "0004" ,
636
+ Limit : 3 ,
637
+ })
638
+ require .NoError (t , err )
639
+ require .Equal (t , []string {"0005" , "0006" , "0007" }, paths )
640
+ })
641
+ }
0 commit comments