@@ -12,6 +12,7 @@ import (
1212 "fmt"
1313 "io"
1414 "maps"
15+ "math/rand"
1516 "os"
1617 "path"
1718 "slices"
@@ -524,9 +525,9 @@ func TestGetBackupTreeIndexMetadata(t *testing.T) {
524525 t * testing.T , subdirEnd , start , end int ,
525526 ) {
526527 t .Helper ()
527- subdirTS := intToTime (subdirEnd ).GoTime ()
528- startTS := intToTime (start )
529- endTS := intToTime (end )
528+ subdirTS := intToTimeWithNano (subdirEnd ).GoTime ()
529+ startTS := intToTimeWithNano (start )
530+ endTS := intToTimeWithNano (end )
530531 subdir := subdirTS .Format (backupbase .DateBasedIntoFolderName )
531532
532533 details := jobspb.BackupDetails {
@@ -548,6 +549,21 @@ func TestGetBackupTreeIndexMetadata(t *testing.T) {
548549 ))
549550 }
550551
552+ randIdx := func (n int ) []int {
553+ idxs := make ([]int , n )
554+ for i := 0 ; i < n ; i ++ {
555+ idxs [i ] = i
556+ }
557+ rand .Shuffle (n , func (i , j int ) {
558+ // Don't shuffle the full backup as it must be written before incs.
559+ if i == 0 || j == 0 {
560+ return
561+ }
562+ idxs [i ], idxs [j ] = idxs [j ], idxs [i ]
563+ })
564+ return idxs
565+ }
566+
551567 type chain = [][2 ]int
552568 simpleChain := chain {{0 , 2 }, {2 , 4 }, {4 , 6 }, {6 , 8 }}
553569 compactedChain := chain {{0 , 10 }, {10 , 11 }, {10 , 12 }, {11 , 12 }, {12 , 14 }, {14 , 16 }}
@@ -560,9 +576,13 @@ func TestGetBackupTreeIndexMetadata(t *testing.T) {
560576 doubleCompactedChain ,
561577 fullOnly ,
562578 }
579+
563580 for _ , index := range indexes {
564- for _ , time := range index {
565- writeIndex (t , index [0 ][1 ], time [0 ], time [1 ])
581+ // Write the index files in random time order to ensure the read always
582+ // returns in them in the correct order.
583+ rndIdxs := randIdx (len (index ))
584+ for _ , idx := range rndIdxs {
585+ writeIndex (t , index [0 ][1 ], index [idx ][0 ], index [idx ][1 ])
566586 }
567587 }
568588
@@ -600,7 +620,7 @@ func TestGetBackupTreeIndexMetadata(t *testing.T) {
600620
601621 for _ , tc := range testcases {
602622 t .Run (tc .name , func (t * testing.T ) {
603- subdirTS := intToTime (tc .chain [0 ][1 ]).GoTime ()
623+ subdirTS := intToTimeWithNano (tc .chain [0 ][1 ]).GoTime ()
604624 subdir := subdirTS .Format (backupbase .DateBasedIntoFolderName )
605625
606626 metadatas , err := GetBackupTreeIndexMetadata (ctx , externalStorage , subdir )
@@ -615,8 +635,8 @@ func TestGetBackupTreeIndexMetadata(t *testing.T) {
615635 // Using [2]int64 makes test outputs in event of failure more readable.
616636 expectedIndexTimes := util .Map (tc .expectedIndexTimes , func (t [2 ]int ) [2 ]int64 {
617637 return [... ]int64 {
618- intToTime (t [0 ]).WallTime ,
619- intToTime (t [1 ]).WallTime ,
638+ intToTimeWithNano (t [0 ]).WallTime ,
639+ intToTimeWithNano (t [1 ]).WallTime ,
620640 }
621641 })
622642 actualIndexTimes := util .Map (metadatas , func (m backuppb.BackupIndexMetadata ) [2 ]int64 {
@@ -733,10 +753,12 @@ func (f *fakeExternalStorage) List(
733753 return nil
734754}
735755
736- // intToTime converts the integer time an easy to read hlc.Timestamp (i.e. XX00000000000...).
737- // We use ints to more easily write times for test cases.
738- func intToTime (t int ) hlc.Timestamp {
756+ // intToTimeWithNano converts the integer time an easy to read hlc.Timestamp
757+ // (i.e. XX000000000XX). Note that the int is also added as nanoseconds to
758+ // stress backup's handling of nanosecond precision timestamps. We use ints to
759+ // more easily write times for test cases.
760+ func intToTimeWithNano (t int ) hlc.Timestamp {
739761 // Value needs to be large enough to be represented in milliseconds and be
740762 // larger than GoTime zero.
741- return hlc.Timestamp {WallTime : int64 (t ) * 1e9 }
763+ return hlc.Timestamp {WallTime : int64 (t )* 1e9 + int64 ( t ) }
742764}
0 commit comments