diff --git a/internal/backend/cache/file_test.go b/internal/backend/cache/file_test.go index 331e3251d..ed2cd295a 100644 --- a/internal/backend/cache/file_test.go +++ b/internal/backend/cache/file_test.go @@ -19,10 +19,10 @@ import ( "golang.org/x/sync/errgroup" ) -func generateRandomFiles(t testing.TB, tpe backend.FileType, c *Cache) restic.IDSet { +func generateRandomFiles(t testing.TB, random *rand.Rand, tpe backend.FileType, c *Cache) restic.IDSet { ids := restic.NewIDSet() - for i := 0; i < rand.Intn(15)+10; i++ { - buf := rtest.Random(rand.Int(), 1<<19) + for i := 0; i < random.Intn(15)+10; i++ { + buf := rtest.Random(random.Int(), 1<<19) id := restic.Hash(buf) h := backend.Handle{Type: tpe, Name: id.String()} @@ -88,7 +88,7 @@ func clearFiles(t testing.TB, c *Cache, tpe restic.FileType, valid restic.IDSet) func TestFiles(t *testing.T) { seed := time.Now().Unix() t.Logf("seed is %v", seed) - rand.Seed(seed) + random := rand.New(rand.NewSource(seed)) c := TestNewCache(t) @@ -100,7 +100,7 @@ func TestFiles(t *testing.T) { for _, tpe := range tests { t.Run(tpe.String(), func(t *testing.T) { - ids := generateRandomFiles(t, tpe, c) + ids := generateRandomFiles(t, random, tpe, c) id := randomID(ids) h := backend.Handle{Type: tpe, Name: id.String()} @@ -140,12 +140,12 @@ func TestFiles(t *testing.T) { func TestFileLoad(t *testing.T) { seed := time.Now().Unix() t.Logf("seed is %v", seed) - rand.Seed(seed) + random := rand.New(rand.NewSource(seed)) c := TestNewCache(t) // save about 5 MiB of data in the cache - data := rtest.Random(rand.Int(), 5234142) + data := rtest.Random(random.Int(), 5234142) id := restic.ID{} copy(id[:], data) h := backend.Handle{ @@ -223,6 +223,10 @@ func TestFileSaveConcurrent(t *testing.T) { t.Skip("may not work due to FILE_SHARE_DELETE issue") } + seed := time.Now().Unix() + t.Logf("seed is %v", seed) + random := rand.New(rand.NewSource(seed)) + const nproc = 40 var ( @@ -231,7 +235,8 @@ func TestFileSaveConcurrent(t *testing.T) { g errgroup.Group id restic.ID ) - rand.Read(id[:]) + + random.Read(id[:]) h := backend.Handle{ Type: restic.PackFile, diff --git a/internal/backend/test/tests.go b/internal/backend/test/tests.go index 800d1f8c0..add2f531a 100644 --- a/internal/backend/test/tests.go +++ b/internal/backend/test/tests.go @@ -21,10 +21,11 @@ import ( "github.com/restic/restic/internal/backend" ) -func seedRand(t testing.TB) { +func seedRand(t testing.TB) *rand.Rand { seed := time.Now().UnixNano() - rand.Seed(seed) + random := rand.New(rand.NewSource(seed)) t.Logf("rand initialized with seed %d", seed) + return random } func beTest(ctx context.Context, be backend.Backend, h backend.Handle) (bool, error) { @@ -128,7 +129,7 @@ func (s *Suite[C]) TestConfig(t *testing.T) { // TestLoad tests the backend's Load function. func (s *Suite[C]) TestLoad(t *testing.T) { - seedRand(t) + random := seedRand(t) b := s.open(t) defer s.close(t, b) @@ -140,7 +141,7 @@ func (s *Suite[C]) TestLoad(t *testing.T) { test.Assert(t, b.IsNotExist(err), "IsNotExist() did not recognize non-existing blob: %v", err) test.Assert(t, b.IsPermanentError(err), "IsPermanentError() did not recognize non-existing blob: %v", err) - length := rand.Intn(1<<24) + 2000 + length := random.Intn(1<<24) + 2000 data := test.Random(23, length) id := restic.Hash(data) @@ -173,8 +174,8 @@ func (s *Suite[C]) TestLoad(t *testing.T) { } for i := 0; i < loadTests; i++ { - l := rand.Intn(length + 2000) - o := rand.Intn(length + 2000) + l := random.Intn(length + 2000) + o := random.Intn(length + 2000) d := data if o < len(d) { @@ -186,7 +187,7 @@ func (s *Suite[C]) TestLoad(t *testing.T) { getlen := l if l >= len(d) { - if rand.Float32() >= 0.5 { + if random.Float32() >= 0.5 { getlen = 0 } else { getlen = len(d) @@ -254,9 +255,9 @@ type setter interface { // TestList makes sure that the backend implements List() pagination correctly. func (s *Suite[C]) TestList(t *testing.T) { - seedRand(t) + random := seedRand(t) - numTestFiles := rand.Intn(20) + 20 + numTestFiles := random.Intn(20) + 20 b := s.open(t) defer s.close(t, b) @@ -277,7 +278,7 @@ func (s *Suite[C]) TestList(t *testing.T) { list1 := make(map[restic.ID]int64) for i := 0; i < numTestFiles; i++ { - data := test.Random(rand.Int(), rand.Intn(100)+55) + data := test.Random(random.Int(), random.Intn(100)+55) id := restic.Hash(data) h := backend.Handle{Type: backend.PackFile, Name: id.String()} err := b.Save(context.TODO(), h, backend.NewByteReader(data, b.Hasher())) @@ -353,8 +354,6 @@ func (s *Suite[C]) TestList(t *testing.T) { // TestListCancel tests that the context is respected and the error is returned by List. func (s *Suite[C]) TestListCancel(t *testing.T) { - seedRand(t) - numTestFiles := 5 b := s.open(t) @@ -498,7 +497,7 @@ func (ec errorCloser) Rewind() error { // TestSave tests saving data in the backend. func (s *Suite[C]) TestSave(t *testing.T) { - seedRand(t) + random := seedRand(t) b := s.open(t) defer s.close(t, b) @@ -510,7 +509,7 @@ func (s *Suite[C]) TestSave(t *testing.T) { } for i := 0; i < saveTests; i++ { - length := rand.Intn(1<<23) + 200000 + length := random.Intn(1<<23) + 200000 data := test.Random(23, length) id = sha256.Sum256(data) @@ -554,7 +553,7 @@ func (s *Suite[C]) TestSave(t *testing.T) { t.Fatal(err) } - length := rand.Intn(1<<23) + 200000 + length := random.Intn(1<<23) + 200000 data := test.Random(23, length) id = sha256.Sum256(data) @@ -614,7 +613,7 @@ func (r *incompleteByteReader) Length() int64 { // TestSaveError tests saving data in the backend. func (s *Suite[C]) TestSaveError(t *testing.T) { - seedRand(t) + random := seedRand(t) b := s.open(t) defer func() { @@ -623,7 +622,7 @@ func (s *Suite[C]) TestSaveError(t *testing.T) { _ = b.Close() }() - length := rand.Intn(1<<23) + 200000 + length := random.Intn(1<<23) + 200000 data := test.Random(24, length) var id restic.ID copy(id[:], data) @@ -653,7 +652,7 @@ func (b *wrongByteReader) Hash() []byte { // TestSaveWrongHash tests that uploads with a wrong hash fail func (s *Suite[C]) TestSaveWrongHash(t *testing.T) { - seedRand(t) + random := seedRand(t) b := s.open(t) defer s.close(t, b) @@ -662,7 +661,7 @@ func (s *Suite[C]) TestSaveWrongHash(t *testing.T) { return } - length := rand.Intn(1<<23) + 200000 + length := random.Intn(1<<23) + 200000 data := test.Random(25, length) var id restic.ID copy(id[:], data) diff --git a/internal/repository/prune_test.go b/internal/repository/prune_test.go index 02eefc463..94d0dfa94 100644 --- a/internal/repository/prune_test.go +++ b/internal/repository/prune_test.go @@ -3,7 +3,9 @@ package repository_test import ( "context" "math" + "math/rand" "testing" + "time" "github.com/restic/restic/internal/checker" "github.com/restic/restic/internal/repository" @@ -14,10 +16,14 @@ import ( ) func testPrune(t *testing.T, opts repository.PruneOptions, errOnUnused bool) { + seed := time.Now().UnixNano() + random := rand.New(rand.NewSource(seed)) + t.Logf("rand initialized with seed %d", seed) + repo, be := repository.TestRepositoryWithVersion(t, 0) - createRandomBlobs(t, repo, 4, 0.5, true) - createRandomBlobs(t, repo, 5, 0.5, true) - keep, _ := selectBlobs(t, repo, 0.5) + createRandomBlobs(t, random, repo, 4, 0.5, true) + createRandomBlobs(t, random, repo, 5, 0.5, true) + keep, _ := selectBlobs(t, random, repo, 0.5) var wg errgroup.Group repo.StartPackUploader(context.TODO(), &wg) diff --git a/internal/repository/repack_test.go b/internal/repository/repack_test.go index 476e63b47..59bafe84c 100644 --- a/internal/repository/repack_test.go +++ b/internal/repository/repack_test.go @@ -14,11 +14,11 @@ import ( "golang.org/x/sync/errgroup" ) -func randomSize(min, max int) int { - return rand.Intn(max-min) + min +func randomSize(random *rand.Rand, min, max int) int { + return random.Intn(max-min) + min } -func createRandomBlobs(t testing.TB, repo restic.Repository, blobs int, pData float32, smallBlobs bool) { +func createRandomBlobs(t testing.TB, random *rand.Rand, repo restic.Repository, blobs int, pData float32, smallBlobs bool) { var wg errgroup.Group repo.StartPackUploader(context.TODO(), &wg) @@ -28,20 +28,20 @@ func createRandomBlobs(t testing.TB, repo restic.Repository, blobs int, pData fl length int ) - if rand.Float32() < pData { + if random.Float32() < pData { tpe = restic.DataBlob if smallBlobs { - length = randomSize(1*1024, 20*1024) // 1KiB to 20KiB of data + length = randomSize(random, 1*1024, 20*1024) // 1KiB to 20KiB of data } else { - length = randomSize(10*1024, 1024*1024) // 10KiB to 1MiB of data + length = randomSize(random, 10*1024, 1024*1024) // 10KiB to 1MiB of data } } else { tpe = restic.TreeBlob - length = randomSize(1*1024, 20*1024) // 1KiB to 20KiB + length = randomSize(random, 1*1024, 20*1024) // 1KiB to 20KiB } buf := make([]byte, length) - rand.Read(buf) + random.Read(buf) id, exists, _, err := repo.SaveBlob(context.TODO(), tpe, buf, restic.ID{}, false) if err != nil { @@ -66,10 +66,10 @@ func createRandomBlobs(t testing.TB, repo restic.Repository, blobs int, pData fl } } -func createRandomWrongBlob(t testing.TB, repo restic.Repository) restic.BlobHandle { - length := randomSize(10*1024, 1024*1024) // 10KiB to 1MiB of data +func createRandomWrongBlob(t testing.TB, random *rand.Rand, repo restic.Repository) restic.BlobHandle { + length := randomSize(random, 10*1024, 1024*1024) // 10KiB to 1MiB of data buf := make([]byte, length) - rand.Read(buf) + random.Read(buf) id := restic.Hash(buf) // invert first data byte buf[0] ^= 0xff @@ -89,7 +89,7 @@ func createRandomWrongBlob(t testing.TB, repo restic.Repository) restic.BlobHand // selectBlobs splits the list of all blobs randomly into two lists. A blob // will be contained in the firstone with probability p. -func selectBlobs(t *testing.T, repo restic.Repository, p float32) (list1, list2 restic.BlobSet) { +func selectBlobs(t *testing.T, random *rand.Rand, repo restic.Repository, p float32) (list1, list2 restic.BlobSet) { list1 = restic.NewBlobSet() list2 = restic.NewBlobSet() @@ -109,7 +109,7 @@ func selectBlobs(t *testing.T, repo restic.Repository, p float32) (list1, list2 } blobs.Insert(h) - if rand.Float32() <= p { + if random.Float32() <= p { list1.Insert(restic.BlobHandle{ID: entry.ID, Type: entry.Type}) } else { list2.Insert(restic.BlobHandle{ID: entry.ID, Type: entry.Type}) @@ -189,12 +189,12 @@ func testRepack(t *testing.T, version uint) { repo, _ := repository.TestRepositoryWithVersion(t, version) seed := time.Now().UnixNano() - rand.Seed(seed) + random := rand.New(rand.NewSource(seed)) t.Logf("rand seed is %v", seed) // add a small amount of blobs twice to create multiple pack files - createRandomBlobs(t, repo, 10, 0.7, false) - createRandomBlobs(t, repo, 10, 0.7, false) + createRandomBlobs(t, random, repo, 10, 0.7, false) + createRandomBlobs(t, random, repo, 10, 0.7, false) packsBefore := listPacks(t, repo) @@ -208,7 +208,7 @@ func testRepack(t *testing.T, version uint) { packsBefore, packsAfter) } - removeBlobs, keepBlobs := selectBlobs(t, repo, 0.2) + removeBlobs, keepBlobs := selectBlobs(t, random, repo, 0.2) removePacks := findPacksForBlobs(t, repo, removeBlobs) @@ -269,14 +269,14 @@ func testRepackCopy(t *testing.T, version uint) { dstRepoWrapped := &oneConnectionRepo{dstRepo} seed := time.Now().UnixNano() - rand.Seed(seed) + random := rand.New(rand.NewSource(seed)) t.Logf("rand seed is %v", seed) // add a small amount of blobs twice to create multiple pack files - createRandomBlobs(t, repo, 10, 0.7, false) - createRandomBlobs(t, repo, 10, 0.7, false) + createRandomBlobs(t, random, repo, 10, 0.7, false) + createRandomBlobs(t, random, repo, 10, 0.7, false) - _, keepBlobs := selectBlobs(t, repo, 0.2) + _, keepBlobs := selectBlobs(t, random, repo, 0.2) copyPacks := findPacksForBlobs(t, repo, keepBlobs) _, err := repository.Repack(context.TODO(), repoWrapped, dstRepoWrapped, copyPacks, keepBlobs, nil) @@ -308,14 +308,14 @@ func testRepackWrongBlob(t *testing.T, version uint) { repo, _ := repository.TestRepositoryWithBackend(t, nil, version, repository.Options{NoExtraVerify: true}) seed := time.Now().UnixNano() - rand.Seed(seed) + random := rand.New(rand.NewSource(seed)) t.Logf("rand seed is %v", seed) - createRandomBlobs(t, repo, 5, 0.7, false) - createRandomWrongBlob(t, repo) + createRandomBlobs(t, random, repo, 5, 0.7, false) + createRandomWrongBlob(t, random, repo) // just keep all blobs, but also rewrite every pack - _, keepBlobs := selectBlobs(t, repo, 0) + _, keepBlobs := selectBlobs(t, random, repo, 0) rewritePacks := findPacksForBlobs(t, repo, keepBlobs) _, err := repository.Repack(context.TODO(), repo, repo, rewritePacks, keepBlobs, nil) @@ -334,12 +334,12 @@ func testRepackBlobFallback(t *testing.T, version uint) { repo, _ := repository.TestRepositoryWithBackend(t, nil, version, repository.Options{NoExtraVerify: true}) seed := time.Now().UnixNano() - rand.Seed(seed) + random := rand.New(rand.NewSource(seed)) t.Logf("rand seed is %v", seed) - length := randomSize(10*1024, 1024*1024) // 10KiB to 1MiB of data + length := randomSize(random, 10*1024, 1024*1024) // 10KiB to 1MiB of data buf := make([]byte, length) - rand.Read(buf) + random.Read(buf) id := restic.Hash(buf) // corrupted copy diff --git a/internal/repository/repair_index_test.go b/internal/repository/repair_index_test.go index ac47d59ff..3b0af4e22 100644 --- a/internal/repository/repair_index_test.go +++ b/internal/repository/repair_index_test.go @@ -2,7 +2,9 @@ package repository_test import ( "context" + "math/rand" "testing" + "time" "github.com/restic/restic/internal/backend" "github.com/restic/restic/internal/checker" @@ -17,9 +19,13 @@ func listIndex(t *testing.T, repo restic.Lister) restic.IDSet { } func testRebuildIndex(t *testing.T, readAllPacks bool, damage func(t *testing.T, repo *repository.Repository, be backend.Backend)) { + seed := time.Now().UnixNano() + random := rand.New(rand.NewSource(seed)) + t.Logf("rand initialized with seed %d", seed) + repo, be := repository.TestRepositoryWithVersion(t, 0) - createRandomBlobs(t, repo, 4, 0.5, true) - createRandomBlobs(t, repo, 5, 0.5, true) + createRandomBlobs(t, random, repo, 4, 0.5, true) + createRandomBlobs(t, random, repo, 5, 0.5, true) indexes := listIndex(t, repo) t.Logf("old indexes %v", indexes) diff --git a/internal/repository/repair_pack_test.go b/internal/repository/repair_pack_test.go index 0d6d340f4..e5f7a7f22 100644 --- a/internal/repository/repair_pack_test.go +++ b/internal/repository/repair_pack_test.go @@ -38,25 +38,25 @@ func TestRepairBrokenPack(t *testing.T) { func testRepairBrokenPack(t *testing.T, version uint) { tests := []struct { name string - damage func(t *testing.T, repo *repository.Repository, be backend.Backend, packsBefore restic.IDSet) (restic.IDSet, restic.BlobSet) + damage func(t *testing.T, random *rand.Rand, repo *repository.Repository, be backend.Backend, packsBefore restic.IDSet) (restic.IDSet, restic.BlobSet) }{ { "valid pack", - func(t *testing.T, repo *repository.Repository, be backend.Backend, packsBefore restic.IDSet) (restic.IDSet, restic.BlobSet) { + func(t *testing.T, random *rand.Rand, repo *repository.Repository, be backend.Backend, packsBefore restic.IDSet) (restic.IDSet, restic.BlobSet) { return packsBefore, restic.NewBlobSet() }, }, { "broken pack", - func(t *testing.T, repo *repository.Repository, be backend.Backend, packsBefore restic.IDSet) (restic.IDSet, restic.BlobSet) { - wrongBlob := createRandomWrongBlob(t, repo) + func(t *testing.T, random *rand.Rand, repo *repository.Repository, be backend.Backend, packsBefore restic.IDSet) (restic.IDSet, restic.BlobSet) { + wrongBlob := createRandomWrongBlob(t, random, repo) damagedPacks := findPacksForBlobs(t, repo, restic.NewBlobSet(wrongBlob)) return damagedPacks, restic.NewBlobSet(wrongBlob) }, }, { "partially broken pack", - func(t *testing.T, repo *repository.Repository, be backend.Backend, packsBefore restic.IDSet) (restic.IDSet, restic.BlobSet) { + func(t *testing.T, random *rand.Rand, repo *repository.Repository, be backend.Backend, packsBefore restic.IDSet) (restic.IDSet, restic.BlobSet) { // damage one of the pack files damagedID := packsBefore.List()[0] replaceFile(t, be, backend.Handle{Type: backend.PackFile, Name: damagedID.String()}, @@ -79,7 +79,7 @@ func testRepairBrokenPack(t *testing.T, version uint) { }, }, { "truncated pack", - func(t *testing.T, repo *repository.Repository, be backend.Backend, packsBefore restic.IDSet) (restic.IDSet, restic.BlobSet) { + func(t *testing.T, random *rand.Rand, repo *repository.Repository, be backend.Backend, packsBefore restic.IDSet) (restic.IDSet, restic.BlobSet) { // damage one of the pack files damagedID := packsBefore.List()[0] replaceFile(t, be, backend.Handle{Type: backend.PackFile, Name: damagedID.String()}, @@ -106,14 +106,14 @@ func testRepairBrokenPack(t *testing.T, version uint) { repo, be := repository.TestRepositoryWithBackend(t, nil, version, repository.Options{NoExtraVerify: true}) seed := time.Now().UnixNano() - rand.Seed(seed) + random := rand.New(rand.NewSource(seed)) t.Logf("rand seed is %v", seed) - createRandomBlobs(t, repo, 5, 0.7, true) + createRandomBlobs(t, random, repo, 5, 0.7, true) packsBefore := listPacks(t, repo) blobsBefore := listBlobs(repo) - toRepair, damagedBlobs := test.damage(t, repo, be, packsBefore) + toRepair, damagedBlobs := test.damage(t, random, repo, be, packsBefore) rtest.OK(t, repository.RepairPacks(context.TODO(), repo, toRepair, &progress.NoopPrinter{})) // reload index diff --git a/internal/restic/blob_set_test.go b/internal/restic/blob_set_test.go index e26b48fe9..4e0961aa5 100644 --- a/internal/restic/blob_set_test.go +++ b/internal/restic/blob_set_test.go @@ -9,6 +9,8 @@ import ( ) func TestBlobSetString(t *testing.T) { + random := rand.New(rand.NewSource(42)) + s := NewBlobSet() rtest.Equals(t, "{}", s.String()) @@ -21,7 +23,7 @@ func TestBlobSetString(t *testing.T) { var h BlobHandle for i := 0; i < 100; i++ { h.Type = DataBlob - _, _ = rand.Read(h.ID[:]) + _, _ = random.Read(h.ID[:]) s.Insert(h) }