From a99e38c24796cd80cbc6ceb91992df0709fd55ff Mon Sep 17 00:00:00 2001 From: Julio Lopez <1953782+julio-lopez@users.noreply.github.com> Date: Mon, 27 Mar 2023 18:44:09 -0700 Subject: [PATCH] fix(lint): remove uses of deprecated rand.Read (#2858) Lint fixes in preparation for moving to Go 1.20 Remove deprecated calls to `rand.Seed` In Go 1.20 the default generator is seeded randomly at program startup, which is the desired behavior for these tests. Remove uses of deprecated rand.Read: replace with calls to rand.Uint64() Remove deprecated uses of rand.Read in content manager tests and S3 versioned tests. Adds a concurrency-safe helpers to provide functionality similar to that provided by `rand.Read(b []byte) (int, error)` --- internal/epoch/epoch_manager_test.go | 18 +++++---------- repo/blob/s3/s3_versioned_test.go | 22 +++++++++++++++++-- repo/content/content_manager_test.go | 17 ++++++++++++-- .../indexblob/index_blob_manager_v0_test.go | 8 ------- repo/object/object_manager_test.go | 3 --- .../repository_stress_test.go | 4 ---- 6 files changed, 40 insertions(+), 32 deletions(-) diff --git a/internal/epoch/epoch_manager_test.go b/internal/epoch/epoch_manager_test.go index 808c24fd5..6b31cedbd 100644 --- a/internal/epoch/epoch_manager_test.go +++ b/internal/epoch/epoch_manager_test.go @@ -173,14 +173,11 @@ func TestIndexEpochManager_Parallel(t *testing.T) { indexNum++ - var rnd [8]byte - - rand.Read(rnd[:]) - + rnd := rand.Uint64() ndx := newFakeIndexWithEntries(indexNum) if _, err := te2.mgr.WriteIndex(ctx, map[blob.ID]blob.Bytes{ - blob.ID(fmt.Sprintf("w%vr%x", worker, rnd)): gather.FromSlice(ndx.Bytes()), + blob.ID(fmt.Sprintf("w%vr%0x", worker, rnd)): gather.FromSlice(ndx.Bytes()), }); err != nil { if errors.Is(err, ErrVerySlowIndexWrite) { indexNum-- @@ -713,17 +710,12 @@ func (te *epochManagerTestEnv) getMergedIndexContents(ctx context.Context, blobI func (te *epochManagerTestEnv) writeIndexFiles(ctx context.Context, ndx ...*fakeIndex) ([]blob.Metadata, error) { shards := map[blob.ID]blob.Bytes{} - - var sessionID [8]byte - - rand.Read(sessionID[:]) + sessionID := rand.Uint64() for _, n := range ndx { - var rnd [8]byte + rnd := rand.Uint64() - rand.Read(rnd[:]) - - shards[blob.ID(fmt.Sprintf("%x-c%v-s%x", rnd[:], len(ndx), sessionID))] = gather.FromSlice(n.Bytes()) + shards[blob.ID(fmt.Sprintf("%0x-c%v-s%0x", rnd, len(ndx), sessionID))] = gather.FromSlice(n.Bytes()) } return te.mgr.WriteIndex(ctx, shards) diff --git a/repo/blob/s3/s3_versioned_test.go b/repo/blob/s3/s3_versioned_test.go index 160c4f2dc..705482429 100644 --- a/repo/blob/s3/s3_versioned_test.go +++ b/repo/blob/s3/s3_versioned_test.go @@ -9,6 +9,7 @@ "math/rand" "path" "sort" + "sync" "testing" "time" @@ -640,12 +641,29 @@ func randHex(tb testing.TB, length int) string { return fmt.Sprintf("%0x", rand.Uint64())[0:length] } + return randLongHex(tb, length) +} + +// Protects the initialization of a random number generator for byte sequences +// that are larger than 16 characters (8 bytes) +// Notice that this is not a crypto RNG. +var ( + rMu sync.Mutex + r = rand.New(rand.NewSource(clock.Now().UnixNano())) +) + +func randLongHex(tb testing.TB, length int) string { + tb.Helper() + byteLength := (length + 1) / 2 b := make([]byte, byteLength) - n, err := rand.Read(b) + + rMu.Lock() + n, err := r.Read(b) + rMu.Unlock() require.NoError(tb, err) - require.Equal(tb, byteLength, n, "unexpected number of bytes from rand.Read") + require.Equal(tb, byteLength, n, "unexpected number of bytes while reading RNG") return hex.EncodeToString(b)[:length] } diff --git a/repo/content/content_manager_test.go b/repo/content/content_manager_test.go index 7da6b759b..bfdefb0b1 100644 --- a/repo/content/content_manager_test.go +++ b/repo/content/content_manager_test.go @@ -2083,7 +2083,7 @@ func (s *contentManagerSuite) TestCompression_NonCompressibleData(t *testing.T) nonCompressibleData := make([]byte, 65000) headerID := compression.ByName["pgzip"].HeaderID() - rand.Read(nonCompressibleData) + randRead(nonCompressibleData) cid, err := bm.WriteContent(ctx, gather.FromSlice(nonCompressibleData), "", headerID) require.NoError(t, err) @@ -2630,7 +2630,7 @@ func makeRandomHexID(t *testing.T, length int) index.ID { t.Helper() b := make([]byte, length/2) - if _, err := rand.Read(b); err != nil { + if _, err := randRead(b); err != nil { t.Fatal("Could not read random bytes", err) } @@ -2681,3 +2681,16 @@ type withDeleted struct { func (o withDeleted) GetDeleted() bool { return o.deleted } + +var ( + r = rand.New(rand.NewSource(rand.Int63())) + rMu sync.Mutex +) + +func randRead(b []byte) (n int, err error) { + rMu.Lock() + n, err = r.Read(b) + rMu.Unlock() + + return +} diff --git a/repo/content/indexblob/index_blob_manager_v0_test.go b/repo/content/indexblob/index_blob_manager_v0_test.go index 2ca9f6f30..23efad31b 100644 --- a/repo/content/indexblob/index_blob_manager_v0_test.go +++ b/repo/content/indexblob/index_blob_manager_v0_test.go @@ -167,8 +167,6 @@ func TestIndexBlobManagerStress(t *testing.T) { return } - rand.Seed(clock.Now().UnixNano()) - for i := range actionsTestIndexBlobManagerStress { actionsTestIndexBlobManagerStress[i].weight = rand.Intn(100) t.Logf("weight[%v] = %v", i, actionsTestIndexBlobManagerStress[i].weight) @@ -268,8 +266,6 @@ func TestIndexBlobManagerStress(t *testing.T) { } func TestIndexBlobManagerPreventsResurrectOfDeletedContents(t *testing.T) { - rand.Seed(clock.Now().UnixNano()) - // the test is randomized and runs very quickly, run it lots of times failed := false for i := 0; i < 100 && !failed; i++ { @@ -282,8 +278,6 @@ func TestIndexBlobManagerPreventsResurrectOfDeletedContents(t *testing.T) { } func TestCompactionCreatesPreviousIndex(t *testing.T) { - rand.Seed(clock.Now().UnixNano()) - storageData := blobtesting.DataMap{} fakeTime := faketime.NewTimeAdvance(fakeLocalStartTime, 0) @@ -333,8 +327,6 @@ func TestCompactionCreatesPreviousIndex(t *testing.T) { } func TestIndexBlobManagerPreventsResurrectOfDeletedContents_RandomizedTimings(t *testing.T) { - rand.Seed(clock.Now().UnixNano()) - numAttempts := 1000 if testutil.ShouldReduceTestComplexity() { numAttempts = 100 diff --git a/repo/object/object_manager_test.go b/repo/object/object_manager_test.go index 43eedaf6b..702850319 100644 --- a/repo/object/object_manager_test.go +++ b/repo/object/object_manager_test.go @@ -18,7 +18,6 @@ "github.com/stretchr/testify/require" "golang.org/x/sync/errgroup" - "github.com/kopia/kopia/internal/clock" "github.com/kopia/kopia/internal/gather" "github.com/kopia/kopia/internal/impossible" "github.com/kopia/kopia/internal/testlogging" @@ -273,8 +272,6 @@ func TestCheckpointing(t *testing.T) { } func TestObjectWriterRaceBetweenCheckpointAndResult(t *testing.T) { - rand.Seed(clock.Now().UnixNano()) - ctx := testlogging.Context(t) data := map[content.ID][]byte{} fcm := &fakeContentManager{ diff --git a/tests/repository_stress_test/repository_stress_test.go b/tests/repository_stress_test/repository_stress_test.go index 445343fbb..02dff7926 100644 --- a/tests/repository_stress_test/repository_stress_test.go +++ b/tests/repository_stress_test/repository_stress_test.go @@ -78,10 +78,6 @@ type StressOptions struct { const masterPassword = "foo-bar-baz-1234" -func init() { - rand.Seed(clock.Now().UnixNano()) -} - func TestStressRepositoryMixAll(t *testing.T) { runStress(t, &StressOptions{ ConfigsPerRepository: 2,