diff --git a/CHANGELOG.md b/CHANGELOG.md index e431d1ac2e..f02d77f3dc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -33,15 +33,18 @@ enumeration. [#1184](https://github.com/ipfs/boxo/pull/1184) ### Changed - ๐Ÿ›  `mfs`: `File.Open` now takes a `context.Context`. Writing to a file whose data has to be fetched from the network (for example, a lazy reference created with `ipfs files cp`) now uses that context, so the write stops when the context is cancelled, such as on a client timeout or when MFS shuts down, instead of waiting forever for a block that never arrives. Callers must add a context argument; pass the request's context to let a timeout cancel the write. [#1185](https://github.com/ipfs/boxo/pull/1185) - +- ๐Ÿงช `testing`: tests now use `go-test` v0.4.0 and `math/rand/v2`. `go-test/random` no longer has a global seed or a global sequence, so one test can no longer change the values another test expects to generate deterministically, a class of failure that showed up as an intermittent break in an unrelated test. A generator can also be reused now, instead of being rebuilt for every value. [#1187](https://github.com/ipfs/boxo/pull/1187) - upgrade to `go-libp2p-kad-dht` [v0.41.0](https://github.com/libp2p/go-libp2p-kad-dht/releases/tag/v0.41.0) - upgrade to `go-unixfsnode` [v1.10.5](https://github.com/ipfs/go-unixfsnode/releases/tag/v1.10.5) - upgrade to `go-cid` [v0.6.2](https://github.com/ipfs/go-cid/releases/tag/v0.6.2) ### Removed +- ๐Ÿ›  `util`: removed the deprecated `NewSeededRand` and `NewTimeSeededRand`. Use [`go-test/random`](https://github.com/ipfs/go-test) instead. [#1187](https://github.com/ipfs/boxo/pull/1187) + ### Fixed +- `gateway`: fixed a data race in the remote blockstore, CAR fetcher, and value store. Each picked a gateway URL out of its list using a per-instance `*rand.Rand`, which is not safe to use from more than one goroutine, so a gateway serving requests in parallel was racing on every request. They now use the top-level `math/rand/v2` functions, which are safe to share. [#1187](https://github.com/ipfs/boxo/pull/1187) - `blockstore`: the Bloom filter cache no longer activates after an incomplete build. Previously, if `AllKeysChan` enumeration was truncated by a mid-iteration datastore error (which was only logged, never propagated) or by a diff --git a/autoconf/client.go b/autoconf/client.go index 674f14b297..602733886b 100644 --- a/autoconf/client.go +++ b/autoconf/client.go @@ -4,7 +4,7 @@ import ( "crypto/tls" "fmt" "hash/fnv" - "math/rand" + "math/rand/v2" "net/http" "os" "path/filepath" @@ -279,7 +279,7 @@ func (c *Client) selectURL() string { if len(c.urls) == 1 { return c.urls[0] } - return c.urls[rand.Intn(len(c.urls))] + return c.urls[rand.IntN(len(c.urls))] } // readMetadata reads cached ETag and Last-Modified values diff --git a/autoconf/expansion.go b/autoconf/expansion.go index e8099acc60..fea688cd6e 100644 --- a/autoconf/expansion.go +++ b/autoconf/expansion.go @@ -1,7 +1,7 @@ package autoconf import ( - "math/rand" + "math/rand/v2" "slices" "strings" ) @@ -40,7 +40,7 @@ func selectRandom(items []string) string { if len(items) == 0 { return "" } - return items[rand.Intn(len(items))] + return items[rand.IntN(len(items))] } // ExpandDNSResolvers expands DNS resolvers with "auto" values replaced by autoconf values. diff --git a/bitswap/benchmarks_test.go b/bitswap/benchmarks_test.go index c0ca60e32a..304cb333eb 100644 --- a/bitswap/benchmarks_test.go +++ b/bitswap/benchmarks_test.go @@ -5,9 +5,7 @@ import ( "encoding/json" "fmt" "math" - "math/rand" "os" - "strconv" "sync" "testing" "time" @@ -135,6 +133,7 @@ func BenchmarkFetchFromOldBitswap(b *testing.B) { fixedDelay := delay.Fixed(10 * time.Millisecond) bstoreLatency := time.Duration(0) router := mockrouting.NewServer() + rnd := random.New() for _, bch := range mixedBenches { b.Run(bch.name, func(b *testing.B) { @@ -169,8 +168,8 @@ func BenchmarkFetchFromOldBitswap(b *testing.B) { testinstance.ConnectInstances(instances) // Generate blocks, with a smaller root block - rootBlock := random.BlocksOfSize(1, rootBlockSize) - blocks := random.BlocksOfSize(bch.blockCount, stdBlockSize) + rootBlock := rnd.BlocksOfSize(1, rootBlockSize) + blocks := rnd.BlocksOfSize(bch.blockCount, stdBlockSize) blocks[0] = rootBlock[0] // Run the distribution @@ -209,10 +208,10 @@ const ( func BenchmarkRealWorld(b *testing.B) { benchmarkLog = nil - benchmarkSeed, err := strconv.ParseInt(os.Getenv("BENCHMARK_SEED"), 10, 64) - var randomGen *rand.Rand = nil - if err == nil { - randomGen = rand.New(rand.NewSource(benchmarkSeed)) + var randomGen *random.Random + seed := os.Getenv("BENCHMARK_SEED") + if seed != "" { + randomGen = random.NewSeeded(random.StringToSeed(seed)) } fastNetworkDelayGenerator := tn.InternetLatencyDelayGenerator( @@ -248,10 +247,10 @@ func BenchmarkRealWorld(b *testing.B) { func BenchmarkDatacenter(b *testing.B) { benchmarkLog = nil - benchmarkSeed, err := strconv.ParseInt(os.Getenv("BENCHMARK_SEED"), 10, 64) - var randomGen *rand.Rand = nil - if err == nil { - randomGen = rand.New(rand.NewSource(benchmarkSeed)) + var randomGen *random.Random + seed := os.Getenv("BENCHMARK_SEED") + if seed != "" { + randomGen = random.NewSeeded(random.StringToSeed(seed)) } datacenterNetworkDelayGenerator := tn.InternetLatencyDelayGenerator( @@ -271,10 +270,10 @@ func BenchmarkDatacenter(b *testing.B) { func BenchmarkDatacenterMultiLeechMultiSeed(b *testing.B) { benchmarkLog = nil - benchmarkSeed, err := strconv.ParseInt(os.Getenv("BENCHMARK_SEED"), 10, 64) - var randomGen *rand.Rand = nil - if err == nil { - randomGen = rand.New(rand.NewSource(benchmarkSeed)) + var randomGen *random.Random + seed := os.Getenv("BENCHMARK_SEED") + if seed != "" { + randomGen = random.NewSeeded(random.StringToSeed(seed)) } datacenterNetworkDelayGenerator := tn.InternetLatencyDelayGenerator( @@ -292,6 +291,7 @@ func BenchmarkDatacenterMultiLeechMultiSeed(b *testing.B) { ff := unixfsFileFetchLarge numnodes := 6 numblks := 1000 + rnd := random.New() for i := 0; i < b.N; i++ { net := tn.RateLimitedVirtualNetwork(d, rateLimitGenerator) @@ -301,7 +301,7 @@ func BenchmarkDatacenterMultiLeechMultiSeed(b *testing.B) { defer ig.Close() instances := ig.Instances(numnodes) - blocks := random.BlocksOfSize(numblks, int(blockSize)) + blocks := rnd.BlocksOfSize(numblks, blockSize) runDistributionMulti(b, instances[:3], instances[3:], blocks, bstoreLatency, df, ff) } }) @@ -312,14 +312,15 @@ func BenchmarkDatacenterMultiLeechMultiSeed(b *testing.B) { } func subtestDistributeAndFetch(b *testing.B, numnodes, numblks int, d delay.D, bstoreLatency time.Duration, df distFunc, ff fetchFunc) { + rnd := random.New() for i := 0; i < b.N; i++ { net := tn.VirtualNetwork(d) router := mockrouting.NewServer() ig := testinstance.NewTestInstanceGenerator(net, router, nil, nil) instances := ig.Instances(numnodes) - rootBlock := random.BlocksOfSize(1, rootBlockSize) - blocks := random.BlocksOfSize(numblks, stdBlockSize) + rootBlock := rnd.BlocksOfSize(1, rootBlockSize) + blocks := rnd.BlocksOfSize(numblks, stdBlockSize) blocks[0] = rootBlock[0] runDistribution(b, instances, blocks, bstoreLatency, df, ff) ig.Close() @@ -327,6 +328,7 @@ func subtestDistributeAndFetch(b *testing.B, numnodes, numblks int, d delay.D, b } func subtestDistributeAndFetchRateLimited(b *testing.B, numnodes, numblks int, d delay.D, rateLimitGenerator tn.RateLimitGenerator, blockSize int64, bstoreLatency time.Duration, df distFunc, ff fetchFunc) { + rnd := random.New() for i := 0; i < b.N; i++ { net := tn.RateLimitedVirtualNetwork(d, rateLimitGenerator) router := mockrouting.NewServer() @@ -334,8 +336,8 @@ func subtestDistributeAndFetchRateLimited(b *testing.B, numnodes, numblks int, d defer ig.Close() instances := ig.Instances(numnodes) - rootBlock := random.BlocksOfSize(1, rootBlockSize) - blocks := random.BlocksOfSize(numblks, int(blockSize)) + rootBlock := rnd.BlocksOfSize(1, rootBlockSize) + blocks := rnd.BlocksOfSize(numblks, blockSize) blocks[0] = rootBlock[0] runDistribution(b, instances, blocks, bstoreLatency, df, ff) } @@ -490,8 +492,9 @@ func overlap2(b *testing.B, provs []testinstance.Instance, blks []blocks.Block) // with this layout, we shouldnt actually ever see any duplicate blocks // but we're mostly just testing performance of the sync algorithm func onePeerPerBlock(b *testing.B, provs []testinstance.Instance, blks []blocks.Block) { + rnd := random.New() for _, blk := range blks { - err := provs[rand.Intn(len(provs))].Blockstore.Put(context.Background(), blk) + err := provs[rnd.IntN(len(provs))].Blockstore.Put(context.Background(), blk) if err != nil { b.Fatal(err) } diff --git a/bitswap/client/internal/blockpresencemanager/blockpresencemanager_test.go b/bitswap/client/internal/blockpresencemanager/blockpresencemanager_test.go index bde71676a6..c261bdbee6 100644 --- a/bitswap/client/internal/blockpresencemanager/blockpresencemanager_test.go +++ b/bitswap/client/internal/blockpresencemanager/blockpresencemanager_test.go @@ -19,8 +19,9 @@ const ( func TestBlockPresenceManager(t *testing.T) { bpm := New() - p := random.Peers(1)[0] - cids := random.Cids(2) + rnd := random.New() + p := rnd.Peers(1)[0] + cids := rnd.Cids(2) c0 := cids[0] c1 := cids[1] @@ -81,10 +82,11 @@ func TestBlockPresenceManager(t *testing.T) { func TestAddRemoveMulti(t *testing.T) { bpm := New() - peers := random.Peers(2) + rnd := random.New() + peers := rnd.Peers(2) p0 := peers[0] p1 := peers[1] - cids := random.Cids(3) + cids := rnd.Cids(3) c0 := cids[0] c1 := cids[1] c2 := cids[2] @@ -132,12 +134,13 @@ func TestAddRemoveMulti(t *testing.T) { func TestAllPeersDoNotHaveBlock(t *testing.T) { bpm := New() - peers := random.Peers(3) + rnd := random.New() + peers := rnd.Peers(3) p0 := peers[0] p1 := peers[1] p2 := peers[2] - cids := random.Cids(3) + cids := rnd.Cids(3) c0 := cids[0] c1 := cids[1] c2 := cids[2] diff --git a/bitswap/client/internal/messagequeue/messagequeue_test.go b/bitswap/client/internal/messagequeue/messagequeue_test.go index 5c46c77c08..1279f12760 100644 --- a/bitswap/client/internal/messagequeue/messagequeue_test.go +++ b/bitswap/client/internal/messagequeue/messagequeue_test.go @@ -6,7 +6,6 @@ import ( "context" "errors" "math" - "math/rand" "sync" "testing" "testing/synctest" @@ -172,9 +171,10 @@ func TestStartupAndShutdown(t *testing.T) { resetChan := make(chan struct{}, 1) fakeSender := newFakeMessageSender(resetChan, messagesSent, true) fakenet := &fakeMessageNetwork{nil, nil, fakeSender} - peerID := random.Peers(1)[0] + rnd := random.New() + peerID := rnd.Peers(1)[0] messageQueue := New(ctx, peerID, fakenet, mockTimeoutCb) - bcstwh := random.Cids(10) + bcstwh := rnd.Cids(10) messageQueue.Startup() messageQueue.AddBroadcastWantHaves(bcstwh) @@ -211,10 +211,11 @@ func TestSendingMessagesDeduped(t *testing.T) { resetChan := make(chan struct{}, 1) fakeSender := newFakeMessageSender(resetChan, messagesSent, true) fakenet := &fakeMessageNetwork{nil, nil, fakeSender} - peerID := random.Peers(1)[0] + rnd := random.New() + peerID := rnd.Peers(1)[0] messageQueue := New(ctx, peerID, fakenet, mockTimeoutCb) - wantHaves := random.Cids(10) - wantBlocks := random.Cids(10) + wantHaves := rnd.Cids(10) + wantBlocks := rnd.Cids(10) messageQueue.Startup() defer messageQueue.Shutdown() @@ -234,10 +235,11 @@ func TestSendingMessagesPartialDupe(t *testing.T) { resetChan := make(chan struct{}, 1) fakeSender := newFakeMessageSender(resetChan, messagesSent, true) fakenet := &fakeMessageNetwork{nil, nil, fakeSender} - peerID := random.Peers(1)[0] + rnd := random.New() + peerID := rnd.Peers(1)[0] messageQueue := New(ctx, peerID, fakenet, mockTimeoutCb) - wantHaves := random.Cids(10) - wantBlocks := random.Cids(10) + wantHaves := rnd.Cids(10) + wantBlocks := rnd.Cids(10) messageQueue.Startup() defer messageQueue.Shutdown() @@ -257,13 +259,14 @@ func TestSendingMessagesPriority(t *testing.T) { resetChan := make(chan struct{}, 1) fakeSender := newFakeMessageSender(resetChan, messagesSent, true) fakenet := &fakeMessageNetwork{nil, nil, fakeSender} - peerID := random.Peers(1)[0] + rnd := random.New() + peerID := rnd.Peers(1)[0] messageQueue := New(ctx, peerID, fakenet, mockTimeoutCb) - wantHaves1 := random.Cids(5) - wantHaves2 := random.Cids(5) + wantHaves1 := rnd.Cids(5) + wantHaves2 := rnd.Cids(5) wantHaves := append(wantHaves1, wantHaves2...) - wantBlocks1 := random.Cids(5) - wantBlocks2 := random.Cids(5) + wantBlocks1 := rnd.Cids(5) + wantBlocks2 := rnd.Cids(5) wantBlocks := append(wantBlocks1, wantBlocks2...) messageQueue.Startup() @@ -326,11 +329,12 @@ func TestCancelOverridesPendingWants(t *testing.T) { resetChan := make(chan struct{}, 1) fakeSender := newFakeMessageSender(resetChan, messagesSent, true) fakenet := &fakeMessageNetwork{nil, nil, fakeSender} - peerID := random.Peers(1)[0] + rnd := random.New() + peerID := rnd.Peers(1)[0] messageQueue := New(ctx, peerID, fakenet, mockTimeoutCb) - wantHaves := random.Cids(2) - wantBlocks := random.Cids(2) + wantHaves := rnd.Cids(2) + wantBlocks := rnd.Cids(2) cancels := []cid.Cid{wantBlocks[0], wantHaves[0]} messageQueue.Startup() @@ -390,10 +394,11 @@ func TestWantOverridesPendingCancels(t *testing.T) { resetChan := make(chan struct{}, 1) fakeSender := newFakeMessageSender(resetChan, messagesSent, true) fakenet := &fakeMessageNetwork{nil, nil, fakeSender} - peerID := random.Peers(1)[0] + rnd := random.New() + peerID := rnd.Peers(1)[0] messageQueue := New(ctx, peerID, fakenet, mockTimeoutCb) - cids := random.Cids(3) + cids := rnd.Cids(3) wantBlocks := cids[:1] wantHaves := cids[1:] @@ -439,13 +444,14 @@ func TestWantlistRebroadcast(t *testing.T) { resetChan := make(chan struct{}, 1) fakeSender := newFakeMessageSender(resetChan, messagesSent, true) fakenet := &fakeMessageNetwork{nil, nil, fakeSender} - peerID := random.Peers(1)[0] + rnd := random.New() + peerID := rnd.Peers(1)[0] dhtm := &fakeDontHaveTimeoutMgr{} events := make(chan messageEvent, 1) messageQueue := newMessageQueue(ctx, peerID, fakenet, maxMessageSize, sendErrorBackoff, maxValidLatency, dhtm, events) - bcstwh := random.Cids(10) - wantHaves := random.Cids(10) - wantBlocks := random.Cids(10) + bcstwh := rnd.Cids(10) + wantHaves := rnd.Cids(10) + wantBlocks := rnd.Cids(10) // Add some broadcast want-haves messageQueue.Startup() @@ -546,9 +552,10 @@ func TestSendingLargeMessages(t *testing.T) { fakeSender := newFakeMessageSender(resetChan, messagesSent, true) fakenet := &fakeMessageNetwork{nil, nil, fakeSender} dhtm := &fakeDontHaveTimeoutMgr{} - peerID := random.Peers(1)[0] + rnd := random.New() + peerID := rnd.Peers(1)[0] - wantBlocks := random.Cids(10) + wantBlocks := rnd.Cids(10) entrySize := 44 maxMsgSize := entrySize * 3 // 3 wants messageQueue := newMessageQueue(ctx, peerID, fakenet, maxMsgSize, sendErrorBackoff, maxValidLatency, dhtm, nil) @@ -576,7 +583,8 @@ func TestSendToPeerThatDoesntSupportHave(t *testing.T) { resetChan := make(chan struct{}, 1) fakeSender := newFakeMessageSender(resetChan, messagesSent, false) fakenet := &fakeMessageNetwork{nil, nil, fakeSender} - peerID := random.Peers(1)[0] + rnd := random.New() + peerID := rnd.Peers(1)[0] messageQueue := New(ctx, peerID, fakenet, mockTimeoutCb) messageQueue.Startup() @@ -588,7 +596,7 @@ func TestSendToPeerThatDoesntSupportHave(t *testing.T) { // - broadcast want-haves should be sent as want-blocks // Check broadcast want-haves - bcwh := random.Cids(10) + bcwh := rnd.Cids(10) messageQueue.AddBroadcastWantHaves(bcwh) messages := collectMessages(ctx, t, messagesSent, collectTimeout) @@ -606,8 +614,8 @@ func TestSendToPeerThatDoesntSupportHave(t *testing.T) { } // Check regular want-haves and want-blocks - wbs := random.Cids(10) - whs := random.Cids(10) + wbs := rnd.Cids(10) + whs := rnd.Cids(10) messageQueue.AddWants(wbs, whs) messages = collectMessages(ctx, t, messagesSent, collectTimeout) @@ -632,14 +640,15 @@ func TestSendToPeerThatDoesntSupportHaveMonitorsTimeouts(t *testing.T) { resetChan := make(chan struct{}, 1) fakeSender := newFakeMessageSender(resetChan, messagesSent, false) fakenet := &fakeMessageNetwork{nil, nil, fakeSender} - peerID := random.Peers(1)[0] + rnd := random.New() + peerID := rnd.Peers(1)[0] dhtm := &fakeDontHaveTimeoutMgr{} messageQueue := newMessageQueue(ctx, peerID, fakenet, maxMessageSize, sendErrorBackoff, maxValidLatency, dhtm, nil) messageQueue.Startup() defer messageQueue.Shutdown() - wbs := random.Cids(10) + wbs := rnd.Cids(10) messageQueue.AddWants(wbs, nil) collectMessages(ctx, t, messagesSent, collectTimeout) @@ -666,7 +675,8 @@ func TestResponseReceived(t *testing.T) { resetChan := make(chan struct{}, 1) fakeSender := newFakeMessageSender(resetChan, messagesSent, false) fakenet := &fakeMessageNetwork{nil, nil, fakeSender} - peerID := random.Peers(1)[0] + rnd := random.New() + peerID := rnd.Peers(1)[0] dhtm := &fakeDontHaveTimeoutMgr{} events := make(chan messageEvent) @@ -674,7 +684,7 @@ func TestResponseReceived(t *testing.T) { messageQueue.Startup() defer messageQueue.Shutdown() - cids := random.Cids(10) + cids := rnd.Cids(10) // Add some wants messageQueue.AddWants(cids[:5], nil) @@ -719,14 +729,15 @@ func TestResponseReceivedAppliesForFirstResponseOnly(t *testing.T) { resetChan := make(chan struct{}, 1) fakeSender := newFakeMessageSender(resetChan, messagesSent, false) fakenet := &fakeMessageNetwork{nil, nil, fakeSender} - peerID := random.Peers(1)[0] + rnd := random.New() + peerID := rnd.Peers(1)[0] dhtm := &fakeDontHaveTimeoutMgr{} messageQueue := newMessageQueue(ctx, peerID, fakenet, maxMessageSize, sendErrorBackoff, maxValidLatency, dhtm, nil) messageQueue.Startup() defer messageQueue.Shutdown() - cids := random.Cids(2) + cids := rnd.Cids(2) // Add some wants and wait messageQueue.AddWants(cids, nil) @@ -766,7 +777,8 @@ func TestResponseReceivedDiscardsOutliers(t *testing.T) { resetChan := make(chan struct{}, 1) fakeSender := newFakeMessageSender(resetChan, messagesSent, false) fakenet := &fakeMessageNetwork{nil, nil, fakeSender} - peerID := random.Peers(1)[0] + rnd := random.New() + peerID := rnd.Peers(1)[0] maxValLatency := 30 * time.Millisecond dhtm := &fakeDontHaveTimeoutMgr{} @@ -775,7 +787,7 @@ func TestResponseReceivedDiscardsOutliers(t *testing.T) { messageQueue.Startup() defer messageQueue.Shutdown() - cids := random.Cids(4) + cids := rnd.Cids(4) // Add some wants and wait 20ms messageQueue.AddWants(cids[:2], nil) @@ -832,7 +844,8 @@ func filterWantTypes(wantlist []bsmsg.Entry) ([]cid.Cid, []cid.Cid, []cid.Cid) { // Simplistic benchmark to allow us to simulate conditions on the gateways func BenchmarkMessageQueue(b *testing.B) { - ctx := context.Background() + ctx := b.Context() + rnd := random.New() createQueue := func() *MessageQueue { messagesSent := make(chan []bsmsg.Entry) @@ -840,7 +853,7 @@ func BenchmarkMessageQueue(b *testing.B) { fakeSender := newFakeMessageSender(resetChan, messagesSent, true) fakenet := &fakeMessageNetwork{nil, nil, fakeSender} dhtm := &fakeDontHaveTimeoutMgr{} - peerID := random.Peers(1)[0] + peerID := rnd.Peers(1)[0] messageQueue := newMessageQueue(ctx, peerID, fakenet, maxMessageSize, sendErrorBackoff, maxValidLatency, dhtm, nil) messageQueue.Startup() @@ -848,7 +861,7 @@ func BenchmarkMessageQueue(b *testing.B) { go func() { for { <-messagesSent - time.Sleep(time.Duration(rand.Intn(1000)) * time.Millisecond) + time.Sleep(time.Duration(rnd.IntN(1000)) * time.Millisecond) } }() @@ -869,17 +882,17 @@ func BenchmarkMessageQueue(b *testing.B) { // Pick a random message queue, favoring those created later qn := len(qs) - i := int(math.Floor(float64(qn) * float64(1-rand.Float32()*rand.Float32()))) + i := int(math.Floor(float64(qn) * float64(1-rnd.Float32()*rnd.Float32()))) if i >= qn { // because of floating point math i = qn - 1 } // Alternately add either a few wants or a lot of broadcast wants - if rand.Intn(2) == 0 { - wants := random.Cids(10) + if rnd.IntN(2) == 0 { + wants := rnd.Cids(10) qs[i].AddWants(wants[:2], wants[2:]) } else { - wants := random.Cids(60) + wants := rnd.Cids(60) qs[i].AddBroadcastWantHaves(wants) } } diff --git a/bitswap/client/internal/peermanager/peermanager_test.go b/bitswap/client/internal/peermanager/peermanager_test.go index 1ee4121891..99f8838045 100644 --- a/bitswap/client/internal/peermanager/peermanager_test.go +++ b/bitswap/client/internal/peermanager/peermanager_test.go @@ -2,7 +2,6 @@ package peermanager import ( "context" - "math/rand" "slices" "testing" "time" @@ -131,11 +130,12 @@ func TestBroadcastOnConnect(t *testing.T) { defer cancel() msgs := make(chan msg, 16) peerQueueFactory := makePeerQueueFactory(msgs) - tp := random.Peers(2) + rnd := random.New() + tp := rnd.Peers(2) peer1 := tp[0] peerManager := New(ctx, peerQueueFactory, bcastAlways) - cids := random.Cids(2) + cids := rnd.Cids(2) peerManager.BroadcastWantHaves(cids) // Connect with two broadcast wants for first peer @@ -152,11 +152,12 @@ func TestBroadcastWantHaves(t *testing.T) { defer cancel() msgs := make(chan msg, 16) peerQueueFactory := makePeerQueueFactory(msgs) - tp := random.Peers(3) + rnd := random.New() + tp := rnd.Peers(3) peer1, peer2 := tp[0], tp[1] peerManager := New(ctx, peerQueueFactory, bcastAlways) - cids := random.Cids(3) + cids := rnd.Cids(3) // Broadcast the first two. peerManager.BroadcastWantHaves(cids[:2]) @@ -193,10 +194,11 @@ func TestSendWants(t *testing.T) { defer cancel() msgs := make(chan msg, 16) peerQueueFactory := makePeerQueueFactory(msgs) - tp := random.Peers(2) + rnd := random.New() + tp := rnd.Peers(2) peer1 := tp[0] peerManager := New(ctx, peerQueueFactory, bcastAlways) - cids := random.Cids(4) + cids := rnd.Cids(4) peerManager.Connected(peer1) peerManager.SendWants(peer1, []cid.Cid{cids[0]}, []cid.Cid{cids[2]}) @@ -349,7 +351,8 @@ func BenchmarkPeerManager(b *testing.B) { return &benchPeerQueue{} } - peers := random.Peers(500) + rnd := random.New() + peers := rnd.Peers(500) peerManager := New(ctx, peerQueueFactory, bcastAlways) // Create a bunch of connections @@ -364,16 +367,16 @@ func BenchmarkPeerManager(b *testing.B) { b.StartTimer() for n := 0; n < b.N; n++ { // Pick a random peer - i := rand.Intn(connected) + i := rnd.IntN(connected) // Alternately add either a few wants or many broadcast wants - r := rand.Intn(8) + r := rnd.IntN(8) if r == 0 { - wants := random.Cids(10) + wants := rnd.Cids(10) peerManager.SendWants(peers[i], wants[:2], wants[2:]) wanted = append(wanted, wants...) } else if r == 1 { - wants := random.Cids(30) + wants := rnd.Cids(30) peerManager.BroadcastWantHaves(wants) wanted = append(wanted, wants...) } else { diff --git a/bitswap/client/internal/peermanager/peerwantmanager_test.go b/bitswap/client/internal/peermanager/peerwantmanager_test.go index d369520d0b..822ecdf149 100644 --- a/bitswap/client/internal/peermanager/peerwantmanager_test.go +++ b/bitswap/client/internal/peermanager/peerwantmanager_test.go @@ -77,10 +77,11 @@ func TestEmpty(t *testing.T) { func TestPWMBroadcastWantHaves(t *testing.T) { pwm := newPeerWantManager(&gauge{}, &gauge{}, bcastAlways) - peers := random.Peers(3) - cids := random.Cids(2) - cids2 := random.Cids(2) - cids3 := random.Cids(2) + rnd := random.New() + peers := rnd.Peers(3) + cids := rnd.Cids(2) + cids2 := rnd.Cids(2) + cids3 := rnd.Cids(2) peerQueues := make(map[peer.ID]PeerQueue) for _, p := range peers[:2] { @@ -127,7 +128,7 @@ func TestPWMBroadcastWantHaves(t *testing.T) { // Sending want-block for a cid should prevent broadcast to that peer clearSent(peerQueues) - cids4 := random.Cids(4) + cids4 := rnd.Cids(4) wantBlocks := []cid.Cid{cids4[0], cids4[2]} p0 := peers[0] p1 := peers[1] @@ -163,11 +164,12 @@ func TestPWMBroadcastWantHaves(t *testing.T) { func TestPWMSendWants(t *testing.T) { pwm := newPeerWantManager(&gauge{}, &gauge{}, bcastAlways) - peers := random.Peers(2) + rnd := random.New() + peers := rnd.Peers(2) p0 := peers[0] p1 := peers[1] - cids := random.Cids(2) - cids2 := random.Cids(2) + cids := rnd.Cids(2) + cids2 := rnd.Cids(2) peerQueues := make(map[peer.ID]PeerQueue) for _, p := range peers[:2] { @@ -188,15 +190,15 @@ func TestPWMSendWants(t *testing.T) { // - 1 old want-block and 2 new want-blocks // - 1 old want-have and 2 new want-haves clearSent(peerQueues) - cids3 := random.Cids(2) - cids4 := random.Cids(2) + cids3 := rnd.Cids(2) + cids4 := rnd.Cids(2) pwm.sendWants(p0, append(cids3, cids[0]), append(cids4, cids2[0])) require.ElementsMatch(t, pq0.wbs, cids3, "Expected 2 want-blocks") require.ElementsMatch(t, pq0.whs, cids4, "Expected 2 want-haves") // Send to p0 as want-blocks: 1 new want-block, 1 old want-have clearSent(peerQueues) - cids5 := random.Cids(1) + cids5 := rnd.Cids(1) newWantBlockOldWantHave := append(cids5, cids2[0]) pwm.sendWants(p0, newWantBlockOldWantHave, []cid.Cid{}) // If a want was sent as a want-have, it should be ok to now send it as a @@ -206,7 +208,7 @@ func TestPWMSendWants(t *testing.T) { // Send to p0 as want-haves: 1 new want-have, 1 old want-block clearSent(peerQueues) - cids6 := random.Cids(1) + cids6 := rnd.Cids(1) newWantHaveOldWantBlock := append(cids6, cids[0]) pwm.sendWants(p0, []cid.Cid{}, newWantHaveOldWantBlock) // If a want was previously sent as a want-block, it should not be @@ -223,13 +225,14 @@ func TestPWMSendWants(t *testing.T) { func TestPWMSendCancels(t *testing.T) { pwm := newPeerWantManager(&gauge{}, &gauge{}, bcastAlways) - peers := random.Peers(2) + rnd := random.New() + peers := rnd.Peers(2) p0 := peers[0] p1 := peers[1] - wb1 := random.Cids(2) - wh1 := random.Cids(2) - wb2 := random.Cids(2) - wh2 := random.Cids(2) + wb1 := rnd.Cids(2) + wh1 := rnd.Cids(2) + wb2 := rnd.Cids(2) + wh2 := rnd.Cids(2) allwb := append(wb1, wb2...) allwh := append(wh1, wh2...) @@ -281,11 +284,12 @@ func TestStats(t *testing.T) { wbg := &gauge{} pwm := newPeerWantManager(g, wbg, bcastAlways) - peers := random.Peers(2) + rnd := random.New() + peers := rnd.Peers(2) p0 := peers[0] p1 := peers[1] - cids := random.Cids(2) - cids2 := random.Cids(2) + cids := rnd.Cids(2) + cids2 := rnd.Cids(2) peerQueues := make(map[peer.ID]PeerQueue) pq := &mockPQ{} @@ -299,14 +303,14 @@ func TestStats(t *testing.T) { require.Equal(t, 2, wbg.count, "Expected 2 want-blocks") // Send 1 old want-block and 2 new want-blocks to p0 - cids3 := random.Cids(2) + cids3 := rnd.Cids(2) pwm.sendWants(p0, append(cids3, cids[0]), []cid.Cid{}) require.Equal(t, 6, g.count, "Expected 6 wants") require.Equal(t, 4, wbg.count, "Expected 4 want-blocks") // Broadcast 1 old want-have and 2 new want-haves - cids4 := random.Cids(2) + cids4 := rnd.Cids(2) pwm.broadcastWantHaves(append(cids4, cids2[0])) require.Equal(t, 8, g.count, "Expected 8 wants") require.Equal(t, 4, wbg.count, "Expected 4 want-blocks") @@ -319,7 +323,7 @@ func TestStats(t *testing.T) { // Cancel 1 want-block that was sent to p0 // and 1 want-block that was not sent - cids5 := random.Cids(1) + cids5 := rnd.Cids(1) pwm.sendCancels(append(cids5, cids[0])) require.Equal(t, 7, g.count, "Expected 7 wants") @@ -350,11 +354,12 @@ func TestStatsOverlappingWantBlockWantHave(t *testing.T) { wbg := &gauge{} pwm := newPeerWantManager(g, wbg, bcastAlways) - peers := random.Peers(2) + rnd := random.New() + peers := rnd.Peers(2) p0 := peers[0] p1 := peers[1] - cids := random.Cids(2) - cids2 := random.Cids(2) + cids := rnd.Cids(2) + cids2 := rnd.Cids(2) pwm.addPeer(&mockPQ{}, p0) pwm.addPeer(&mockPQ{}, p1) @@ -381,11 +386,12 @@ func TestStatsRemovePeerOverlappingWantBlockWantHave(t *testing.T) { wbg := &gauge{} pwm := newPeerWantManager(g, wbg, bcastAlways) - peers := random.Peers(2) + rnd := random.New() + peers := rnd.Peers(2) p0 := peers[0] p1 := peers[1] - cids := random.Cids(2) - cids2 := random.Cids(2) + cids := rnd.Cids(2) + cids2 := rnd.Cids(2) pwm.addPeer(&mockPQ{}, p0) pwm.addPeer(&mockPQ{}, p1) diff --git a/bitswap/client/internal/session/peerresponsetracker.go b/bitswap/client/internal/session/peerresponsetracker.go index 941f6c0edf..0f2e32e1ac 100644 --- a/bitswap/client/internal/session/peerresponsetracker.go +++ b/bitswap/client/internal/session/peerresponsetracker.go @@ -1,7 +1,7 @@ package session import ( - "math/rand" + "math/rand/v2" peer "github.com/libp2p/go-libp2p/core/peer" ) diff --git a/bitswap/client/internal/session/session_test.go b/bitswap/client/internal/session/session_test.go index 02c78a0193..bfe8a8bb22 100644 --- a/bitswap/client/internal/session/session_test.go +++ b/bitswap/client/internal/session/session_test.go @@ -21,6 +21,12 @@ import ( const blockSize = 4 +var testSeq *random.Sequence + +func init() { + testSeq = random.NewSequence() +} + type mockSessionMgr struct { lk sync.Mutex sim *bssim.SessionInterestManager @@ -165,11 +171,12 @@ func TestSessionGetBlocks(t *testing.T) { bpm := bsbpm.New() notif := notifications.New(false) defer notif.Shutdown() - id := random.SequenceNext() + id := testSeq.Next() sm := newMockSessionMgr(sim) session := New(ctx, sm, id, fspm, fpf, sim, fpm, bpm, notif, time.Second, time.Minute, "", nil) defer session.Close() - blks := random.BlocksOfSize(broadcastLiveWantsLimit*2, blockSize) + rnd := random.New() + blks := rnd.BlocksOfSize(broadcastLiveWantsLimit*2, blockSize) var cids []cid.Cid for _, block := range blks { cids = append(cids, block.Cid()) @@ -189,7 +196,7 @@ func TestSessionGetBlocks(t *testing.T) { require.Len(t, receivedWantReq.cids, broadcastLiveWantsLimit, "did not enqueue correct initial number of wants") // Simulate receiving HAVEs from several peers - peers := random.Peers(5) + peers := rnd.Peers(5) for i, p := range peers { blkIndex := slices.IndexFunc(blks, func(blk blocks.Block) bool { return blk.Cid() == receivedWantReq.cids[i] @@ -247,12 +254,13 @@ func TestSessionFindMorePeers(t *testing.T) { bpm := bsbpm.New() notif := notifications.New(false) defer notif.Shutdown() - id := random.SequenceNext() + id := testSeq.Next() sm := newMockSessionMgr(sim) session := New(ctx, sm, id, fspm, fpf, sim, fpm, bpm, notif, time.Second, time.Minute, "", nil) defer session.Close() session.SetBaseTickDelay(200 * time.Microsecond) - blks := random.BlocksOfSize(broadcastLiveWantsLimit*2, blockSize) + rnd := random.New() + blks := rnd.BlocksOfSize(broadcastLiveWantsLimit*2, blockSize) var cids []cid.Cid for _, block := range blks { cids = append(cids, block.Cid()) @@ -272,7 +280,7 @@ func TestSessionFindMorePeers(t *testing.T) { time.Sleep(20 * time.Millisecond) // need to make sure some latency registers // or there will be no tick set -- time precision on Windows in go is in the // millisecond range - p := random.Peers(1)[0] + p := rnd.Peers(1)[0] blk := blks[0] session.ReceiveFrom(p, []cid.Cid{blk.Cid()}, []cid.Cid{}, []cid.Cid{}) @@ -319,7 +327,7 @@ func TestSessionOnPeersExhausted(t *testing.T) { bpm := bsbpm.New() notif := notifications.New(false) defer notif.Shutdown() - id := random.SequenceNext() + id := testSeq.Next() sm := newMockSessionMgr(sim) session := New(ctx, sm, id, fspm, fpf, sim, fpm, bpm, notif, time.Second, time.Minute, "", nil) defer session.Close() @@ -358,7 +366,7 @@ func TestSessionFailingToGetFirstBlock(t *testing.T) { bpm := bsbpm.New() notif := notifications.New(false) defer notif.Shutdown() - id := random.SequenceNext() + id := testSeq.Next() sm := newMockSessionMgr(sim) session := New(ctx, sm, id, fspm, fpf, sim, fpm, bpm, notif, 10*time.Millisecond, 100*time.Millisecond, "", nil) defer session.Close() @@ -458,7 +466,7 @@ func TestSessionCtxCancelClosesGetBlocksChannel(t *testing.T) { bpm := bsbpm.New() notif := notifications.New(false) defer notif.Shutdown() - id := random.SequenceNext() + id := testSeq.Next() sm := newMockSessionMgr(sim) // Create a new session with its own context @@ -505,7 +513,7 @@ func TestSessionOnShutdownCalled(t *testing.T) { bpm := bsbpm.New() notif := notifications.New(false) defer notif.Shutdown() - id := random.SequenceNext() + id := testSeq.Next() sm := newMockSessionMgr(sim) // Create a new session @@ -531,12 +539,13 @@ func TestSessionReceiveMessageAfterClose(t *testing.T) { bpm := bsbpm.New() notif := notifications.New(false) defer notif.Shutdown() - id := random.SequenceNext() + id := testSeq.Next() sm := newMockSessionMgr(sim) session := New(ctx, sm, id, fspm, fpf, sim, fpm, bpm, notif, time.Second, time.Minute, "", nil) defer session.Close() - blks := random.BlocksOfSize(2, blockSize) + rnd := random.New() + blks := rnd.BlocksOfSize(2, blockSize) cids := []cid.Cid{blks[0].Cid(), blks[1].Cid()} _, err := session.GetBlocks(ctx, cids) @@ -549,7 +558,7 @@ func TestSessionReceiveMessageAfterClose(t *testing.T) { session.Close() // Simulate receiving block for a CID - peer := random.Peers(1)[0] + peer := rnd.Peers(1)[0] session.ReceiveFrom(peer, []cid.Cid{blks[0].Cid()}, []cid.Cid{}, []cid.Cid{}) time.Sleep(5 * time.Millisecond) diff --git a/bitswap/client/internal/session/sessionwants.go b/bitswap/client/internal/session/sessionwants.go index ae7b2733fc..7ed559ac52 100644 --- a/bitswap/client/internal/session/sessionwants.go +++ b/bitswap/client/internal/session/sessionwants.go @@ -2,7 +2,7 @@ package session import ( "fmt" - "math/rand" + "math/rand/v2" "slices" "time" @@ -174,7 +174,7 @@ func (sw *sessionWants) RandomLiveWant() cid.Cid { } // picking a random live want - i := rand.Intn(len(sw.liveWants)) + i := rand.IntN(len(sw.liveWants)) for k := range sw.liveWants { if i == 0 { return k diff --git a/bitswap/client/internal/session/sessionwants_test.go b/bitswap/client/internal/session/sessionwants_test.go index 5a80755188..5018d5dd90 100644 --- a/bitswap/client/internal/session/sessionwants_test.go +++ b/bitswap/client/internal/session/sessionwants_test.go @@ -30,8 +30,9 @@ func TestEmptySessionWants(t *testing.T) { func TestSessionWants(t *testing.T) { sw := newSessionWants(5) - cids := random.Cids(10) - others := random.Cids(1) + rnd := random.New() + cids := rnd.Cids(10) + others := rnd.Cids(1) // Add 10 new wants // toFetch Live diff --git a/bitswap/client/internal/session/sessionwantsender_test.go b/bitswap/client/internal/session/sessionwantsender_test.go index b3d5d3704a..c4498d9630 100644 --- a/bitswap/client/internal/session/sessionwantsender_test.go +++ b/bitswap/client/internal/session/sessionwantsender_test.go @@ -140,8 +140,9 @@ func (ep *exhaustedPeers) exhausted() []cid.Cid { } func TestSendWants(t *testing.T) { - cids := random.Cids(4) - peers := random.Peers(1) + rnd := random.New() + cids := rnd.Cids(4) + peers := rnd.Peers(1) peerA := peers[0] const sid = uint64(1) pm := newMockPeerManager() @@ -174,8 +175,9 @@ func TestSendWants(t *testing.T) { } func TestSendsWantBlockToOnePeerOnly(t *testing.T) { - cids := random.Cids(4) - peers := random.Peers(2) + rnd := random.New() + cids := rnd.Cids(4) + peers := rnd.Peers(2) peerA := peers[0] peerB := peers[1] const sid = uint64(1) @@ -225,8 +227,9 @@ func TestSendsWantBlockToOnePeerOnly(t *testing.T) { } func TestReceiveBlock(t *testing.T) { - cids := random.Cids(2) - peers := random.Peers(2) + rnd := random.New() + cids := rnd.Cids(2) + peers := rnd.Peers(2) peerA := peers[0] peerB := peers[1] const sid = uint64(1) @@ -315,8 +318,9 @@ func TestCancelWants(t *testing.T) { } func TestRegisterSessionWithPeerManager(t *testing.T) { - cids := random.Cids(2) - peers := random.Peers(2) + rnd := random.New() + cids := rnd.Cids(2) + peers := rnd.Peers(2) peerA := peers[0] peerB := peers[1] const sid = uint64(1) @@ -352,8 +356,9 @@ func TestRegisterSessionWithPeerManager(t *testing.T) { } func TestProtectConnFirstPeerToSendWantedBlock(t *testing.T) { - cids := random.Cids(2) - peers := random.Peers(3) + rnd := random.New() + cids := rnd.Cids(2) + peers := rnd.Peers(3) peerA := peers[0] peerB := peers[1] peerC := peers[2] @@ -409,8 +414,9 @@ func TestProtectConnFirstPeerToSendWantedBlock(t *testing.T) { } func TestPeerUnavailable(t *testing.T) { - cids := random.Cids(2) - peers := random.Peers(2) + rnd := random.New() + cids := rnd.Cids(2) + peers := rnd.Peers(2) peerA := peers[0] peerB := peers[1] const sid = uint64(1) @@ -469,8 +475,9 @@ func TestPeerUnavailable(t *testing.T) { } func TestPeersExhausted(t *testing.T) { - cids := random.Cids(3) - peers := random.Peers(2) + rnd := random.New() + cids := rnd.Cids(3) + peers := rnd.Peers(2) peerA := peers[0] peerB := peers[1] const sid = uint64(1) @@ -543,8 +550,9 @@ func TestPeersExhausted(t *testing.T) { // - the remaining peer becomes unavailable // onPeersExhausted should be sent for that CID func TestPeersExhaustedLastWaitingPeerUnavailable(t *testing.T) { - cids := random.Cids(2) - peers := random.Peers(2) + rnd := random.New() + cids := rnd.Cids(2) + peers := rnd.Peers(2) peerA := peers[0] peerB := peers[1] const sid = uint64(1) @@ -591,8 +599,9 @@ func TestPeersExhaustedLastWaitingPeerUnavailable(t *testing.T) { // Tests that when all the peers are removed from the session // onPeersExhausted should be called with all outstanding CIDs func TestPeersExhaustedAllPeersUnavailable(t *testing.T) { - cids := random.Cids(3) - peers := random.Peers(2) + rnd := random.New() + cids := rnd.Cids(3) + peers := rnd.Peers(2) peerA := peers[0] peerB := peers[1] const sid = uint64(1) @@ -632,8 +641,9 @@ func TestPeersExhaustedAllPeersUnavailable(t *testing.T) { } func TestConsecutiveDontHaveLimit(t *testing.T) { - cids := random.Cids(peerDontHaveLimit + 10) - p := random.Peers(1)[0] + rnd := random.New() + cids := rnd.Cids(peerDontHaveLimit + 10) + p := rnd.Peers(1)[0] const sid = uint64(1) pm := newMockPeerManager() fpm := newFakeSessionPeerManager() @@ -685,8 +695,9 @@ func TestConsecutiveDontHaveLimit(t *testing.T) { } func TestConsecutiveDontHaveLimitInterrupted(t *testing.T) { - cids := random.Cids(peerDontHaveLimit + 10) - p := random.Peers(1)[0] + rnd := random.New() + cids := rnd.Cids(peerDontHaveLimit + 10) + p := rnd.Peers(1)[0] const sid = uint64(1) pm := newMockPeerManager() fpm := newFakeSessionPeerManager() @@ -739,8 +750,9 @@ func TestConsecutiveDontHaveLimitInterrupted(t *testing.T) { } func TestConsecutiveDontHaveReinstateAfterRemoval(t *testing.T) { - cids := random.Cids(peerDontHaveLimit + 10) - p := random.Peers(1)[0] + rnd := random.New() + cids := rnd.Cids(peerDontHaveLimit + 10) + p := rnd.Peers(1)[0] const sid = uint64(1) pm := newMockPeerManager() fpm := newFakeSessionPeerManager() @@ -788,7 +800,7 @@ func TestConsecutiveDontHaveReinstateAfterRemoval(t *testing.T) { // Peer should be available require.True(t, fpm.HasPeer(p), "Expected peer to be available") - cids2 := random.Cids(peerDontHaveLimit + 10) + cids2 := rnd.Cids(peerDontHaveLimit + 10) // Receive DONT_HAVEs from peer that don't exceed limit for _, c := range cids2[1:peerDontHaveLimit] { @@ -816,8 +828,9 @@ func TestConsecutiveDontHaveReinstateAfterRemoval(t *testing.T) { } func TestConsecutiveDontHaveDontRemoveIfHasWantedBlock(t *testing.T) { - cids := random.Cids(peerDontHaveLimit + 10) - p := random.Peers(1)[0] + rnd := random.New() + cids := rnd.Cids(peerDontHaveLimit + 10) + p := rnd.Peers(1)[0] const sid = uint64(1) pm := newMockPeerManager() fpm := newFakeSessionPeerManager() diff --git a/bitswap/client/internal/sessioninterestmanager/sessioninterestmanager_test.go b/bitswap/client/internal/sessioninterestmanager/sessioninterestmanager_test.go index 2426302734..94cb235afd 100644 --- a/bitswap/client/internal/sessioninterestmanager/sessioninterestmanager_test.go +++ b/bitswap/client/internal/sessioninterestmanager/sessioninterestmanager_test.go @@ -26,8 +26,9 @@ func TestBasic(t *testing.T) { const ses1 = 1 const ses2 = 2 - cids1 := random.Cids(2) - cids2 := append(random.Cids(1), cids1[1]) + rnd := random.New() + cids1 := rnd.Cids(2) + cids2 := append(rnd.Cids(1), cids1[1]) sim.RecordSessionInterest(ses1, cids1) res := sim.FilterSessionInterested(ses1, cids1) @@ -88,8 +89,9 @@ func TestRemoveSession(t *testing.T) { const ses1 = 1 const ses2 = 2 - cids1 := random.Cids(2) - cids2 := append(random.Cids(1), cids1[1]) + rnd := random.New() + cids1 := rnd.Cids(2) + cids2 := append(rnd.Cids(1), cids1[1]) sim.RecordSessionInterest(ses1, cids1) sim.RecordSessionInterest(ses2, cids2) sim.RemoveSession(ses1) @@ -116,8 +118,9 @@ func TestRemoveSessionInterested(t *testing.T) { const ses1 = uint64(1) const ses2 = uint64(2) - cids1 := random.Cids(2) - cids2 := append(random.Cids(1), cids1[1]) + rnd := random.New() + cids1 := rnd.Cids(2) + cids2 := append(rnd.Cids(1), cids1[1]) sim.RecordSessionInterest(ses1, cids1) sim.RecordSessionInterest(ses2, cids2) diff --git a/bitswap/message/message_test.go b/bitswap/message/message_test.go index c58eb22f7a..433d3d7eff 100644 --- a/bitswap/message/message_test.go +++ b/bitswap/message/message_test.go @@ -17,7 +17,10 @@ import ( ) func mkFakeCid(s string) cid.Cid { - return random.Cids(1)[0] + var seed [32]byte + copy(seed[:], s) + rnd := random.NewSeeded(seed) + return rnd.Cids(1)[0] } func TestAppendWanted(t *testing.T) { diff --git a/bitswap/server/internal/decision/blockstoremanager_test.go b/bitswap/server/internal/decision/blockstoremanager_test.go index ebecb9f296..a9300ab420 100644 --- a/bitswap/server/internal/decision/blockstoremanager_test.go +++ b/bitswap/server/internal/decision/blockstoremanager_test.go @@ -2,7 +2,6 @@ package decision import ( "context" - "crypto/rand" "sync" "testing" "time" @@ -33,7 +32,7 @@ func newBlockstoreManagerForTesting( } func TestBlockstoreManagerNotFoundKey(t *testing.T) { - ctx := context.Background() + ctx := t.Context() bsdelay := delay.Fixed(3 * time.Millisecond) dstore := ds_sync.MutexWrap(delayed.New(ds.NewMapDatastore(), bsdelay)) bstore := blockstore.NewBlockstore(ds_sync.MutexWrap(dstore)) @@ -71,18 +70,18 @@ func TestBlockstoreManagerNotFoundKey(t *testing.T) { } func TestBlockstoreManager(t *testing.T) { - ctx := context.Background() + ctx := t.Context() bsdelay := delay.Fixed(3 * time.Millisecond) dstore := ds_sync.MutexWrap(delayed.New(ds.NewMapDatastore(), bsdelay)) bstore := blockstore.NewBlockstore(ds_sync.MutexWrap(dstore)) bsm := newBlockstoreManagerForTesting(t, ctx, bstore, 5) + rnd := random.New() exp := make(map[cid.Cid]blocks.Block) var blks []blocks.Block for i := range 32 { - buf := make([]byte, 1024*(i+1)) - _, _ = rand.Read(buf) + buf := rnd.Bytes(int64(1024 * (i + 1))) b := blocks.NewBlock(buf) blks = append(blks, b) exp[b.Cid()] = b @@ -146,7 +145,7 @@ func TestBlockstoreManager(t *testing.T) { } func TestBlockstoreManagerConcurrency(t *testing.T) { - ctx := context.Background() + ctx := t.Context() bsdelay := delay.Fixed(3 * time.Millisecond) dstore := ds_sync.MutexWrap(delayed.New(ds.NewMapDatastore(), bsdelay)) bstore := blockstore.NewBlockstore(ds_sync.MutexWrap(dstore)) @@ -187,7 +186,7 @@ func TestBlockstoreManagerConcurrency(t *testing.T) { } func TestBlockstoreManagerClose(t *testing.T) { - ctx := context.Background() + ctx := t.Context() const delayTime = 20 * time.Millisecond bsdelay := delay.Fixed(delayTime) dstore := ds_sync.MutexWrap(delayed.New(ds.NewMapDatastore(), bsdelay)) @@ -228,7 +227,7 @@ func TestBlockstoreManagerCtxDone(t *testing.T) { underlyingBstore := blockstore.NewBlockstore(underlyingDstore) bstore := blockstore.NewBlockstore(dstore) - ctx := context.Background() + ctx := t.Context() bsm := newBlockstoreManagerForTesting(t, ctx, bstore, 3) blks := random.BlocksOfSize(100, 128) diff --git a/bitswap/server/internal/decision/engine_test.go b/bitswap/server/internal/decision/engine_test.go index 418f3eb7b4..4a4bf390b5 100644 --- a/bitswap/server/internal/decision/engine_test.go +++ b/bitswap/server/internal/decision/engine_test.go @@ -5,7 +5,6 @@ package decision import ( "bytes" "context" - "crypto/rand" "encoding/binary" "errors" "fmt" @@ -1656,7 +1655,7 @@ func TestIgnoresCidsAboveLimit(t *testing.T) { hash = binary.AppendUvarint(hash, cidLimit) startOfDigest := len(hash) hash = append(hash, make(mh.Multihash, cidLimit)...) - rand.Read(hash[startOfDigest:]) + random.New().Read(hash[startOfDigest:]) return cid.NewCidV1(cid.Raw, hash) } @@ -1777,7 +1776,7 @@ func TestIgnoresIdentityCid(t *testing.T) { hash = binary.AppendUvarint(hash, digestSize) startOfDigest := len(hash) hash = append(hash, make(mh.Multihash, digestSize)...) - rand.Read(hash[startOfDigest:]) + random.New().Read(hash[startOfDigest:]) return cid.NewCidV1(cid.Raw, hash) } diff --git a/bitswap/testnet/internet_latency_delay_generator.go b/bitswap/testnet/internet_latency_delay_generator.go index 4ad758130d..f5aceab816 100644 --- a/bitswap/testnet/internet_latency_delay_generator.go +++ b/bitswap/testnet/internet_latency_delay_generator.go @@ -1,13 +1,17 @@ package bitswap import ( - "math/rand" "time" delay "github.com/ipfs/go-ipfs-delay" + "github.com/ipfs/go-test/random" ) -var sharedRNG = rand.New(rand.NewSource(time.Now().UnixNano())) +// sharedRNG is the fallback source for generators constructed with a nil rng. +// A [random.Random] must not be used concurrently, so a test that drives +// several generators from different goroutines has to pass each one its own +// [random.Random] rather than rely on this. +var sharedRNG = random.New() // InternetLatencyDelayGenerator generates three clusters of delays, // typical of the type of peers you would encounter on the interenet. @@ -27,7 +31,7 @@ func InternetLatencyDelayGenerator( percentMedium float64, percentLarge float64, std time.Duration, - rng *rand.Rand, + rng *random.Random, ) delay.Generator { if rng == nil { rng = sharedRNG @@ -49,7 +53,7 @@ type internetLatencyDelayGenerator struct { percentLarge float64 percentMedium float64 std time.Duration - rng *rand.Rand + rng *random.Random } func (d *internetLatencyDelayGenerator) NextWaitTime(t time.Duration) time.Duration { @@ -57,7 +61,8 @@ func (d *internetLatencyDelayGenerator) NextWaitTime(t time.Duration) time.Durat baseDelay := time.Duration(d.rng.NormFloat64()*float64(d.std)) + t if clusterDistribution < d.percentLarge { return baseDelay + d.largeDelay - } else if clusterDistribution < d.percentMedium+d.percentLarge { + } + if clusterDistribution < d.percentMedium+d.percentLarge { return baseDelay + d.mediumDelay } return baseDelay diff --git a/bitswap/testnet/internet_latency_delay_generator_test.go b/bitswap/testnet/internet_latency_delay_generator_test.go index 1361f288a4..d0368ce8d1 100644 --- a/bitswap/testnet/internet_latency_delay_generator_test.go +++ b/bitswap/testnet/internet_latency_delay_generator_test.go @@ -2,9 +2,10 @@ package bitswap import ( "math" - "math/rand" "testing" "time" + + "github.com/ipfs/go-test/random" ) const testSeed = 99 @@ -23,7 +24,7 @@ func TestInternetLatencyDelayNextWaitTimeDistribution(t *testing.T) { percentMedium, percentLarge, deviation, - rand.New(rand.NewSource(testSeed))) + random.NewSeeded(random.Uint64ToSeed(testSeed))) buckets["fast"] = 0 buckets["medium"] = 0 diff --git a/bitswap/testnet/rate_limit_generators.go b/bitswap/testnet/rate_limit_generators.go index 2c4a1cd563..e03f03ecaa 100644 --- a/bitswap/testnet/rate_limit_generators.go +++ b/bitswap/testnet/rate_limit_generators.go @@ -1,7 +1,7 @@ package bitswap import ( - "math/rand" + "github.com/ipfs/go-test/random" ) type fixedRateLimitGenerator struct { @@ -21,11 +21,11 @@ func (rateLimitGenerator *fixedRateLimitGenerator) NextRateLimit() float64 { type variableRateLimitGenerator struct { rateLimit float64 std float64 - rng *rand.Rand + rng *random.Random } // VariableRateLimitGenerator makes rate limites that following a normal distribution. -func VariableRateLimitGenerator(rateLimit float64, std float64, rng *rand.Rand) RateLimitGenerator { +func VariableRateLimitGenerator(rateLimit float64, std float64, rng *random.Random) RateLimitGenerator { if rng == nil { rng = sharedRNG } diff --git a/blockstore/twoqueue_cache_test.go b/blockstore/twoqueue_cache_test.go index 297d32f132..85f494fc10 100644 --- a/blockstore/twoqueue_cache_test.go +++ b/blockstore/twoqueue_cache_test.go @@ -3,16 +3,15 @@ package blockstore import ( "context" "io" - "math/rand" "sync/atomic" "testing" - "time" blocks "github.com/ipfs/go-block-format" cid "github.com/ipfs/go-cid" ds "github.com/ipfs/go-datastore" syncds "github.com/ipfs/go-datastore/sync" ipld "github.com/ipfs/go-ipld-format" + "github.com/ipfs/go-test/random" ) var exampleBlock = blocks.NewBlock([]byte("foo")) @@ -293,7 +292,7 @@ func BenchmarkTwoQueueCacheConcurrentOps(b *testing.B) { { // scope dummyRand to prevent its unsafe concurrent use below - dummyRand := rand.New(rand.NewSource(time.Now().UnixNano())) + dummyRand := random.New() for i := range dummyBlocks { dummy := make([]byte, 32) if _, err := io.ReadFull(dummyRand, dummy); err != nil { @@ -358,9 +357,9 @@ func BenchmarkTwoQueueCacheConcurrentOps(b *testing.B) { b.ReportAllocs() b.RunParallel(func(pb *testing.PB) { - rnd := rand.New(rand.NewSource(time.Now().UnixNano())) + rnd := random.New() for pb.Next() { - n := rnd.Int63() + n := rnd.Int64() blockIdx := n % numBlocks // lower bits decide the block opIdx := (n / numBlocks) % numOps // higher bits decide what operation diff --git a/bootstrap/bootstrap.go b/bootstrap/bootstrap.go index 5a2e6dab71..9b7ed0b9b9 100644 --- a/bootstrap/bootstrap.go +++ b/bootstrap/bootstrap.go @@ -4,7 +4,7 @@ import ( "context" "errors" "io" - "math/rand" + "math/rand/v2" "sync" "sync/atomic" "time" diff --git a/chunker/benchmark_test.go b/chunker/benchmark_test.go index e37a82359a..ef146f778e 100644 --- a/chunker/benchmark_test.go +++ b/chunker/benchmark_test.go @@ -3,8 +3,9 @@ package chunk import ( "bytes" "io" - "math/rand" "testing" + + random "github.com/ipfs/go-test/random" ) type newSplitter func(io.Reader) Splitter @@ -30,7 +31,7 @@ func benchmarkChunker(b *testing.B, ns newSplitter) { } func benchmarkChunkerSize(b *testing.B, ns newSplitter, size int) { - rng := rand.New(rand.NewSource(1)) + rng := random.NewSeeded(random.Uint64ToSeed(1)) data := make([]byte, size) rng.Read(data) @@ -64,7 +65,8 @@ func benchmarkFilesAlloc(b *testing.B, ns newSplitter) { maxDataSize = 60000 fileCount = 10000 ) - rng := rand.New(rand.NewSource(1)) + + rng := random.NewSeeded(random.Uint64ToSeed(1)) data := make([]byte, maxDataSize) rng.Read(data) @@ -76,7 +78,7 @@ func benchmarkFilesAlloc(b *testing.B, ns newSplitter) { for i := 0; i < b.N; i++ { for range fileCount { - fileSize := rng.Intn(maxDataSize-minDataSize) + minDataSize + fileSize := rng.IntN(maxDataSize-minDataSize) + minDataSize r := ns(bytes.NewReader(data[:fileSize])) for { chunk, err := r.NextBytes() diff --git a/chunker/buzhash_test.go b/chunker/buzhash_test.go index a9ede266c6..3600ded7aa 100644 --- a/chunker/buzhash_test.go +++ b/chunker/buzhash_test.go @@ -11,13 +11,7 @@ import ( func testBuzhashChunking(t *testing.T, buf []byte) (chunkCount int) { t.Parallel() - n, err := random.NewRand().Read(buf) - if n < len(buf) { - t.Fatalf("expected %d bytes, got %d", len(buf), n) - } - if err != nil { - t.Fatal(err) - } + _, _ = random.New().Read(buf) r := NewBuzhash(bytes.NewReader(buf)) diff --git a/chunker/gen/main.go b/chunker/gen/main.go index d5fd8c53de..97191911d6 100644 --- a/chunker/gen/main.go +++ b/chunker/gen/main.go @@ -9,6 +9,10 @@ import ( const nRounds = 200 func main() { + // Stay on math/rand seeded with NewSource(0). The table this prints is + // committed as bytehash in chunker/buzhash.go, and buzhash chunk + // boundaries, so the CID of anything chunked with buzhash, depend on it. + // Any other generator or seed prints a different table. rnd := rand.New(rand.NewSource(0)) lut := make([]uint32, 256) diff --git a/chunker/rabin_test.go b/chunker/rabin_test.go index 98939d36d7..9f0c317f02 100644 --- a/chunker/rabin_test.go +++ b/chunker/rabin_test.go @@ -13,14 +13,7 @@ import ( func TestRabinChunking(t *testing.T) { t.Parallel() - data := make([]byte, 1024*1024*16) - n, err := random.NewRand().Read(data) - if n < len(data) { - t.Fatalf("expected %d bytes, got %d", len(data), n) - } - if err != nil { - t.Fatal(err) - } + data := random.Bytes(1024 * 1024 * 16) r := NewRabin(bytes.NewReader(data), 1024*256) @@ -72,13 +65,10 @@ func testReuse(t *testing.T, cr newSplitter) { t.Parallel() data := make([]byte, 1024*1024*16) - n, err := random.NewRand().Read(data) + n, _ := random.New().Read(data) if n < len(data) { t.Fatalf("expected %d bytes, got %d", len(data), n) } - if err != nil { - t.Fatal(err) - } ch1 := chunkData(t, cr, data[1000:]) ch2 := chunkData(t, cr, data) diff --git a/chunker/splitting_test.go b/chunker/splitting_test.go index b6746b0a9d..de325367ff 100644 --- a/chunker/splitting_test.go +++ b/chunker/splitting_test.go @@ -9,12 +9,8 @@ import ( "github.com/ipfs/go-test/random" ) -func randBuf(t *testing.T, size int) []byte { - buf := make([]byte, size) - if _, err := random.NewRand().Read(buf); err != nil { - t.Fatal("failed to read enough randomness") - } - return buf +func randBuf(t *testing.T, size int64) []byte { + return random.Bytes(size) } func copyBuf(buf []byte) []byte { diff --git a/examples/bitswap-transfer/main.go b/examples/bitswap-transfer/main.go index f3e80d5e05..06d232454d 100644 --- a/examples/bitswap-transfer/main.go +++ b/examples/bitswap-transfer/main.go @@ -4,11 +4,12 @@ import ( "bytes" "context" "crypto/rand" + "encoding/binary" "flag" "fmt" "io" "log" - mrand "math/rand" + mrand "math/rand/v2" "strconv" "strings" @@ -90,7 +91,9 @@ func makeHost(listenPort int, randseed int64) (host.Host, error) { if randseed == 0 { r = rand.Reader } else { - r = mrand.New(mrand.NewSource(randseed)) + var seed [32]byte + binary.BigEndian.PutUint64(seed[:], uint64(randseed)) + r = mrand.NewChaCha8(seed) } // Generate a key pair for this host. We will use it at least diff --git a/examples/go.sum b/examples/go.sum index 729668dda9..1689769b00 100644 --- a/examples/go.sum +++ b/examples/go.sum @@ -141,8 +141,8 @@ github.com/ipfs/go-metrics-interface v0.3.0 h1:YwG7/Cy4R94mYDUuwsBfeziJCVm9pBMJ6 github.com/ipfs/go-metrics-interface v0.3.0/go.mod h1:OxxQjZDGocXVdyTPocns6cOLwHieqej/jos7H4POwoY= github.com/ipfs/go-peertaskqueue v0.8.3 h1:tBPpGJy+A92RqtRFq5amJn0Uuj8Pw8tXi0X3eHfHM8w= github.com/ipfs/go-peertaskqueue v0.8.3/go.mod h1:OqVync4kPOcXEGdj/LKvox9DCB5mkSBeXsPczCxLtYA= -github.com/ipfs/go-test v0.3.0 h1:0Y4Uve3tp9HI+2lIJjfOliOrOgv/YpXg/l1y3P4DEYE= -github.com/ipfs/go-test v0.3.0/go.mod h1:JK+U8pRpATZb7lsYNSJlCj3WYB3cFfWIbI6nWRM/GFk= +github.com/ipfs/go-test v0.4.1 h1:n6uNSakIgpTQIRorqNg2O02aMIFDLQk2z4rBfrlD3Uw= +github.com/ipfs/go-test v0.4.1/go.mod h1:QmvVBf9kClNtRuFow4DASq03eFvjKla4Fy/UAkeeLO8= github.com/ipfs/go-unixfsnode v1.10.5 h1:V34JV7fM90y+2ZUef7ToShjmwAZ8oo1yP7zrpWzC5L4= github.com/ipfs/go-unixfsnode v1.10.5/go.mod h1:u/9Ukl+XYpfKTMu+NXQqxbzAJVTwSCoyTYBGgE+JdSE= github.com/ipld/go-car/v2 v2.17.0 h1:zgjSxf/lQNYcQPX08cvb5rSdEY8sv5OOnQIsZhZMPx4= diff --git a/exchange/offline/offline_test.go b/exchange/offline/offline_test.go index cc344a0f00..ded2eed920 100644 --- a/exchange/offline/offline_test.go +++ b/exchange/offline/offline_test.go @@ -29,12 +29,13 @@ func TestGetBlocks(t *testing.T) { ex := Exchange(store) expected := random.BlocksOfSize(2, blockSize) + ctx := t.Context() for _, b := range expected { - if err := store.Put(context.Background(), b); err != nil { + if err := store.Put(ctx, b); err != nil { t.Fatal(err) } - if err := ex.NotifyNewBlocks(context.Background(), b); err != nil { + if err := ex.NotifyNewBlocks(ctx, b); err != nil { t.Fail() } } @@ -48,7 +49,7 @@ func TestGetBlocks(t *testing.T) { return ks }() - received, err := ex.GetBlocks(context.Background(), request) + received, err := ex.GetBlocks(ctx, request) if err != nil { t.Fatal(err) } diff --git a/gateway/backend_car_fetcher.go b/gateway/backend_car_fetcher.go index 3333fab80f..56f8e4bda4 100644 --- a/gateway/backend_car_fetcher.go +++ b/gateway/backend_car_fetcher.go @@ -5,12 +5,11 @@ import ( "errors" "fmt" "io" - "math/rand" + "math/rand/v2" "net/http" "net/url" "strconv" "strings" - "time" "github.com/ipfs/boxo/path" ) @@ -25,7 +24,6 @@ type CarFetcher interface { type remoteCarFetcher struct { httpClient *http.Client gatewayURL []string - rand *rand.Rand } // NewRemoteCarFetcher returns a [CarFetcher] that is backed by one or more gateways @@ -46,7 +44,6 @@ func NewRemoteCarFetcher(gatewayURL []string, httpClient *http.Client) (CarFetch return &remoteCarFetcher{ gatewayURL: gatewayURL, httpClient: httpClient, - rand: rand.New(rand.NewSource(time.Now().Unix())), }, nil } @@ -81,7 +78,9 @@ func (ps *remoteCarFetcher) Fetch(ctx context.Context, path path.ImmutablePath, } func (ps *remoteCarFetcher) getRandomGatewayURL() string { - return ps.gatewayURL[ps.rand.Intn(len(ps.gatewayURL))] + // The top-level math/rand/v2 functions are safe to call from the concurrent + // request handlers that reach here; a *rand.Rand field would not be. + return ps.gatewayURL[rand.IntN(len(ps.gatewayURL))] } // contentPathToCarUrl returns an URL that allows retrieval of specified resource diff --git a/gateway/blockstore.go b/gateway/blockstore.go index 6e7493ab13..7cbeefa1c6 100644 --- a/gateway/blockstore.go +++ b/gateway/blockstore.go @@ -5,10 +5,9 @@ import ( "errors" "fmt" "io" - "math/rand" + "math/rand/v2" "net/http" "sync/atomic" - "time" lru "github.com/hashicorp/golang-lru/v2" blockstore "github.com/ipfs/boxo/blockstore" @@ -140,7 +139,6 @@ func (l *cacheBlockStore) HashOnRead(enabled bool) { type remoteBlockstore struct { httpClient *http.Client gatewayURL []string - rand *rand.Rand validate bool } @@ -162,7 +160,6 @@ func NewRemoteBlockstore(gatewayURL []string, httpClient *http.Client) (blocksto return &remoteBlockstore{ gatewayURL: gatewayURL, httpClient: httpClient, - rand: rand.New(rand.NewSource(time.Now().Unix())), // Enables block validation by default. Important since we are // proxying block requests to untrusted gateways. validate: true, @@ -250,5 +247,7 @@ func (c *remoteBlockstore) DeleteBlock(context.Context, cid.Cid) error { } func (ps *remoteBlockstore) getRandomGatewayURL() string { - return ps.gatewayURL[ps.rand.Intn(len(ps.gatewayURL))] + // The top-level math/rand/v2 functions are safe to call from the concurrent + // request handlers that reach here; a *rand.Rand field would not be. + return ps.gatewayURL[rand.IntN(len(ps.gatewayURL))] } diff --git a/gateway/value_store.go b/gateway/value_store.go index ead5a44e77..9e6ad3cce1 100644 --- a/gateway/value_store.go +++ b/gateway/value_store.go @@ -5,10 +5,9 @@ import ( "errors" "fmt" "io" - "math/rand" + "math/rand/v2" "net/http" "strings" - "time" "github.com/ipfs/boxo/ipns" "github.com/libp2p/go-libp2p/core/routing" @@ -17,7 +16,6 @@ import ( type remoteValueStore struct { httpClient *http.Client gatewayURL []string - rand *rand.Rand } // NewRemoteValueStore creates a new [routing.ValueStore] backed by one or more @@ -37,7 +35,6 @@ func NewRemoteValueStore(gatewayURL []string, httpClient *http.Client) (routing. return &remoteValueStore{ gatewayURL: gatewayURL, httpClient: httpClient, - rand: rand.New(rand.NewSource(time.Now().Unix())), }, nil } @@ -119,5 +116,7 @@ func (ps *remoteValueStore) fetch(ctx context.Context, name ipns.Name) ([]byte, } func (ps *remoteValueStore) getRandomGatewayURL() string { - return ps.gatewayURL[ps.rand.Intn(len(ps.gatewayURL))] + // The top-level math/rand/v2 functions are safe to call from the concurrent + // request handlers that reach here; a *rand.Rand field would not be. + return ps.gatewayURL[rand.IntN(len(ps.gatewayURL))] } diff --git a/go.mod b/go.mod index 58b8b1769b..ca4eb7b136 100644 --- a/go.mod +++ b/go.mod @@ -29,7 +29,7 @@ require ( github.com/ipfs/go-log/v2 v2.9.2 github.com/ipfs/go-metrics-interface v0.3.0 github.com/ipfs/go-peertaskqueue v0.8.3 - github.com/ipfs/go-test v0.3.0 + github.com/ipfs/go-test v0.4.1 github.com/ipfs/go-unixfsnode v1.10.5 github.com/ipld/go-car/v2 v2.17.0 github.com/ipld/go-codec-dagpb v1.7.0 diff --git a/go.sum b/go.sum index 0df98d4a9f..14e1e16c05 100644 --- a/go.sum +++ b/go.sum @@ -142,8 +142,8 @@ github.com/ipfs/go-metrics-interface v0.3.0 h1:YwG7/Cy4R94mYDUuwsBfeziJCVm9pBMJ6 github.com/ipfs/go-metrics-interface v0.3.0/go.mod h1:OxxQjZDGocXVdyTPocns6cOLwHieqej/jos7H4POwoY= github.com/ipfs/go-peertaskqueue v0.8.3 h1:tBPpGJy+A92RqtRFq5amJn0Uuj8Pw8tXi0X3eHfHM8w= github.com/ipfs/go-peertaskqueue v0.8.3/go.mod h1:OqVync4kPOcXEGdj/LKvox9DCB5mkSBeXsPczCxLtYA= -github.com/ipfs/go-test v0.3.0 h1:0Y4Uve3tp9HI+2lIJjfOliOrOgv/YpXg/l1y3P4DEYE= -github.com/ipfs/go-test v0.3.0/go.mod h1:JK+U8pRpATZb7lsYNSJlCj3WYB3cFfWIbI6nWRM/GFk= +github.com/ipfs/go-test v0.4.1 h1:n6uNSakIgpTQIRorqNg2O02aMIFDLQk2z4rBfrlD3Uw= +github.com/ipfs/go-test v0.4.1/go.mod h1:QmvVBf9kClNtRuFow4DASq03eFvjKla4Fy/UAkeeLO8= github.com/ipfs/go-unixfsnode v1.10.5 h1:V34JV7fM90y+2ZUef7ToShjmwAZ8oo1yP7zrpWzC5L4= github.com/ipfs/go-unixfsnode v1.10.5/go.mod h1:u/9Ukl+XYpfKTMu+NXQqxbzAJVTwSCoyTYBGgE+JdSE= github.com/ipld/go-car/v2 v2.17.0 h1:zgjSxf/lQNYcQPX08cvb5rSdEY8sv5OOnQIsZhZMPx4= diff --git a/ipld/merkledag/merkledag_test.go b/ipld/merkledag/merkledag_test.go index 04e43b0551..c05f957780 100644 --- a/ipld/merkledag/merkledag_test.go +++ b/ipld/merkledag/merkledag_test.go @@ -3,7 +3,6 @@ package merkledag_test import ( "bytes" "context" - "crypto/rand" "encoding/hex" "encoding/json" "errors" @@ -353,7 +352,7 @@ func (devZero) Read(b []byte) (int, error) { } func TestBatchFetch(t *testing.T) { - read := io.LimitReader(random.NewRand(), 1024*32) + read := io.LimitReader(random.New(), 1024*32) runBatchFetchTest(t, read) } @@ -513,7 +512,7 @@ func TestFetchGraph(t *testing.T) { dservs = append(dservs, NewDAGService(bsi)) } - read := io.LimitReader(random.NewRand(), 1024*32) + read := io.LimitReader(random.New(), 1024*32) root := makeTestDAG(t, read, dservs[0]) err := FetchGraph(context.TODO(), root.Cid(), dservs[1]) @@ -595,12 +594,12 @@ func TestWalk(t *testing.T) { bsi := bstest.Mocks(1) ds := NewDAGService(bsi[0]) - read := io.LimitReader(random.NewRand(), 1024*1024) + read := io.LimitReader(random.New(), 1024*1024) root := makeTestDAG(t, read, ds) set := cid.NewSet() - err := Walk(context.Background(), ds.GetLinks, root.Cid(), set.Visit) + err := Walk(t.Context(), ds.GetLinks, root.Cid(), set.Visit) if err != nil { t.Fatal(err) } @@ -1160,11 +1159,11 @@ func TestProgressIndicatorNoChildren(t *testing.T) { func testProgressIndicator(t *testing.T, depth int) { ds := dstest.Mock() - - top, numChildren, totalSize := mkDag(ds, depth) + ctx := t.Context() + top, numChildren, totalSize := mkDag(ctx, ds, depth) v := new(ProgressTracker) - ctx := v.DeriveContext(context.Background()) + ctx = v.DeriveContext(ctx) err := FetchGraph(ctx, top, ds) if err != nil { @@ -1187,14 +1186,14 @@ func testProgressIndicator(t *testing.T, depth int) { } } -func mkDag(ds ipld.DAGService, depth int) (cid.Cid, int, uint64) { - ctx := context.Background() +func mkDag(ctx context.Context, ds ipld.DAGService, depth int) (cid.Cid, int, uint64) { + rnd := random.New() totalChildren := 0 f := func() *ProtoNode { p := new(ProtoNode) buf := make([]byte, 16) - rand.Read(buf) + rnd.Read(buf) p.SetData(buf) err := ds.Add(ctx, p) diff --git a/ipld/unixfs/hamt/hamt_stress_test.go b/ipld/unixfs/hamt/hamt_stress_test.go index 3ede0e7a2e..f73b34d37b 100644 --- a/ipld/unixfs/hamt/hamt_stress_test.go +++ b/ipld/unixfs/hamt/hamt_stress_test.go @@ -1,12 +1,11 @@ package hamt import ( - "context" + crand "crypto/rand" "fmt" - "math/rand" + "math/rand/v2" "os" "testing" - "time" mdtest "github.com/ipfs/boxo/ipld/merkledag/test" ft "github.com/ipfs/boxo/ipld/unixfs" @@ -36,8 +35,9 @@ type testOp struct { // ending directory (same set of entries at the end) and execute each of them // in turn, then compare to ensure the output is the same on each. func TestOrderConsistency(t *testing.T) { - seed := time.Now().UnixNano() - t.Logf("using seed = %d", seed) + var seed [32]byte + _, _ = crand.Read(seed[:]) + t.Logf("using seed = %x", seed) ds := mdtest.Mock() shardWidth := 1024 @@ -56,7 +56,8 @@ func TestOrderConsistency(t *testing.T) { t.Fatal(err) } - ops2 := genOpSet(seed+1000, keep, temp) + rand.NewChaCha8(seed).Read(seed[:]) + ops2 := genOpSet(seed, keep, temp) s2, err := executeOpSet(t, ds, shardWidth, ops2) if err != nil { t.Fatal(err) @@ -86,7 +87,7 @@ func TestOrderConsistency(t *testing.T) { } func validateOpSetCompletion(t *testing.T, s *Shard, keep, temp []string) error { - ctx := context.TODO() + ctx := t.Context() for _, n := range keep { _, err := s.Find(ctx, n) if err != nil { @@ -105,7 +106,7 @@ func validateOpSetCompletion(t *testing.T, s *Shard, keep, temp []string) error } func executeOpSet(t *testing.T, ds ipld.DAGService, width int, ops []testOp) (*Shard, error) { - ctx := context.TODO() + ctx := t.Context() s, err := NewShard(ds, width) if err != nil { return nil, err @@ -137,7 +138,7 @@ func executeOpSet(t *testing.T, ds ipld.DAGService, width int, ops []testOp) (*S return s, nil } -func genOpSet(seed int64, keep, temp []string) []testOp { +func genOpSet(seed [32]byte, keep, temp []string) []testOp { tempSet := make(map[string]struct{}, len(temp)) for _, s := range temp { tempSet[s] = struct{}{} @@ -156,7 +157,7 @@ func genOpSet(seed int64, keep, temp []string) []testOp { return ops } - rn := rand.Intn(n) + rn := rand.IntN(n) if rn < len(allnames) { next := allnames[0] @@ -170,7 +171,8 @@ func genOpSet(seed int64, keep, temp []string) []testOp { todel = append(todel, next) } } else { - shuffle(seed+100, todel) + rand.NewChaCha8(seed).Read(seed[:]) + shuffle(seed, todel) next := todel[0] todel = todel[1:] diff --git a/ipld/unixfs/hamt/hamt_test.go b/ipld/unixfs/hamt/hamt_test.go index f877b77140..9a0116618d 100644 --- a/ipld/unixfs/hamt/hamt_test.go +++ b/ipld/unixfs/hamt/hamt_test.go @@ -2,15 +2,15 @@ package hamt import ( "context" + crand "crypto/rand" "errors" "fmt" - "math/rand" + "math/rand/v2" "os" "slices" "strconv" "strings" "testing" - "time" dag "github.com/ipfs/boxo/ipld/merkledag" mdtest "github.com/ipfs/boxo/ipld/merkledag/test" @@ -18,11 +18,11 @@ import ( ipld "github.com/ipfs/go-ipld-format" ) -func shuffle(seed int64, arr []string) { - r := rand.New(rand.NewSource(seed)) +func shuffle(seed [32]byte, arr []string) { + r := rand.New(rand.NewChaCha8(seed)) for range arr { - a := r.Intn(len(arr)) - b := r.Intn(len(arr)) + a := r.IntN(len(arr)) + b := r.IntN(len(arr)) arr[a], arr[b] = arr[b], arr[a] } } @@ -44,7 +44,9 @@ func makeDirWidth(ds ipld.DAGService, size, width int) ([]string, *Shard, error) dirs = append(dirs, fmt.Sprintf("DIRNAME%d", i)) } - shuffle(time.Now().UnixNano(), dirs) + var seed [32]byte + _, _ = crand.Read(seed[:]) + shuffle(seed, dirs) for i := 0; i < len(dirs); i++ { nd := ft.EmptyDirNode() @@ -146,7 +148,7 @@ func TestBasicSet(t *testing.T) { if err != nil { t.Fatal(err) } - ctx := context.Background() + ctx := t.Context() for _, d := range names { _, err := s.Find(ctx, d) @@ -239,7 +241,7 @@ func TestRemoveElems(t *testing.T) { if err != nil { t.Fatal(err) } - ctx := context.Background() + ctx := t.Context() for range 100 { err := s.Remove(ctx, fmt.Sprintf("NOTEXIST%d", rand.Int())) @@ -255,7 +257,9 @@ func TestRemoveElems(t *testing.T) { } } - shuffle(time.Now().UnixNano(), dirs) + var seed [32]byte + _, _ = crand.Read(seed[:]) + shuffle(seed, dirs) for _, d := range dirs { err := s.Remove(ctx, d) @@ -295,9 +299,11 @@ func TestRemoveAfterMarshal(t *testing.T) { t.Fatal(err) } - ctx := context.Background() + ctx := t.Context() - shuffle(time.Now().UnixNano(), dirs) + var seed [32]byte + _, _ = crand.Read(seed[:]) + shuffle(seed, dirs) for i, d := range dirs { err := s.Remove(ctx, d) @@ -327,7 +333,7 @@ func TestSetAfterMarshal(t *testing.T) { if err != nil { t.Fatal(err) } - ctx := context.Background() + ctx := t.Context() nd, err := s.Node() if err != nil { @@ -377,7 +383,7 @@ func TestEnumLinksAsync(t *testing.T) { if err != nil { t.Fatal(err) } - ctx := context.Background() + ctx := t.Context() nd, err := s.Node() if err != nil { @@ -415,7 +421,7 @@ func TestDuplicateAddShard(t *testing.T) { ds := mdtest.Mock() dir, _ := NewShard(ds, 256) nd := new(dag.ProtoNode) - ctx := context.Background() + ctx := t.Context() err := dir.Set(ctx, "test", nd) if err != nil { @@ -460,7 +466,7 @@ func TestSetLink(t *testing.T) { t.Fatal(err) } - ctx := context.Background() + ctx := t.Context() err = dir.SetLink(ctx, "test", lnk) if err != nil { @@ -501,7 +507,7 @@ func TestFindNonExisting(t *testing.T) { if err != nil { t.Fatal(err) } - ctx := context.Background() + ctx := t.Context() for i := range 200 { _, err := s.Find(ctx, fmt.Sprintf("notfound%d", i)) @@ -517,7 +523,7 @@ func TestRemoveElemsAfterMarshal(t *testing.T) { if err != nil { t.Fatal(err) } - ctx := context.Background() + ctx := t.Context() slices.Sort(dirs) @@ -619,7 +625,7 @@ func TestBitfieldIndexing(t *testing.T) { // if improperly implemented, the parent hamt may assume the child is a part of // itself. func TestSetHamtChild(t *testing.T) { - ctx := context.Background() + ctx := t.Context() ds := mdtest.Mock() s, _ := NewShard(ds, 256) @@ -669,7 +675,7 @@ func TestSetHamtChild(t *testing.T) { } func BenchmarkHAMTWalk(b *testing.B) { - ctx := context.Background() + ctx := b.Context() ds := mdtest.Mock() sh, _ := NewShard(ds, 256) @@ -712,7 +718,7 @@ func BenchmarkHAMTWalk(b *testing.B) { } func BenchmarkHAMTSet(b *testing.B) { - ctx := context.Background() + ctx := b.Context() ds := mdtest.Mock() sh, _ := NewShard(ds, 256) @@ -733,7 +739,7 @@ func BenchmarkHAMTSet(b *testing.B) { b.Fatal(err) } - err = s.Set(context.TODO(), strconv.Itoa(i), ft.EmptyDirNode()) + err = s.Set(ctx, strconv.Itoa(i), ft.EmptyDirNode()) if err != nil { b.Fatal(err) } diff --git a/ipld/unixfs/importer/balanced/balanced_test.go b/ipld/unixfs/importer/balanced/balanced_test.go index 4398750716..f6b61f815f 100644 --- a/ipld/unixfs/importer/balanced/balanced_test.go +++ b/ipld/unixfs/importer/balanced/balanced_test.go @@ -5,7 +5,6 @@ import ( "context" "fmt" "io" - mrand "math/rand" "testing" "time" @@ -45,7 +44,7 @@ func buildTestDagWithParams(spl chunker.Splitter, dbp h.DagBuilderParams) (*dag. func getTestDag(t *testing.T, ds ipld.DAGService, size int64, blksize int64) (*dag.ProtoNode, []byte) { data := make([]byte, size) - random.NewRand().Read(data) + random.New().Read(data) r := bytes.NewReader(data) nd, err := buildTestDag(ds, chunker.NewSizeSplitter(r, blksize)) @@ -272,14 +271,15 @@ func TestSeekingStress(t *testing.T) { ds := mdtest.Mock() nd, should := getTestDag(t, ds, nbytes, 1000) - rs, err := uio.NewDagReader(context.Background(), nd, ds) + rs, err := uio.NewDagReader(t.Context(), nd, ds) if err != nil { t.Fatal(err) } + rnd := random.New() testbuf := make([]byte, nbytes) for range 50 { - offset := mrand.Intn(int(nbytes)) + offset := rnd.IntN(int(nbytes)) l := int(nbytes) - offset n, err := rs.Seek(int64(offset), io.SeekStart) if err != nil { @@ -347,7 +347,7 @@ func TestMetadataNoData(t *testing.T) { func TestMetadata(t *testing.T) { nbytes := 3 * chunker.DefaultBlockSize buf := new(bytes.Buffer) - _, err := io.CopyN(buf, random.NewRand(), nbytes) + _, err := io.CopyN(buf, random.New(), nbytes) if err != nil { t.Fatal(err) } diff --git a/ipld/unixfs/importer/importer_test.go b/ipld/unixfs/importer/importer_test.go index b14d67862d..eb74e844d6 100644 --- a/ipld/unixfs/importer/importer_test.go +++ b/ipld/unixfs/importer/importer_test.go @@ -16,7 +16,7 @@ import ( func getBalancedDag(t testing.TB, size int64, blksize int64) (ipld.Node, ipld.DAGService) { ds := mdtest.Mock() - r := io.LimitReader(random.NewRand(), size) + r := io.LimitReader(random.New(), size) nd, err := BuildDagFromReader(ds, chunker.NewSizeSplitter(r, blksize)) if err != nil { t.Fatal(err) @@ -26,7 +26,7 @@ func getBalancedDag(t testing.TB, size int64, blksize int64) (ipld.Node, ipld.DA func getTrickleDag(t testing.TB, size int64, blksize int64) (ipld.Node, ipld.DAGService) { ds := mdtest.Mock() - r := io.LimitReader(random.NewRand(), size) + r := io.LimitReader(random.New(), size) nd, err := BuildTrickleDagFromReader(ds, chunker.NewSizeSplitter(r, blksize)) if err != nil { t.Fatal(err) @@ -37,7 +37,8 @@ func getTrickleDag(t testing.TB, size int64, blksize int64) (ipld.Node, ipld.DAG func TestStableCid(t *testing.T) { ds := mdtest.Mock() buf := make([]byte, 10*1024*1024) - random.NewSeededRand(0xdeadbeef).Read(buf) + seed := [32]byte([]byte("abcdefghijklmnopqrstuvwxyz012345")) + random.NewSeeded(seed).Read(buf) r := bytes.NewReader(buf) nd, err := BuildDagFromReader(ds, chunker.DefaultSplitter(r)) @@ -45,7 +46,7 @@ func TestStableCid(t *testing.T) { t.Fatal(err) } - expected, err := cid.Decode("QmPu94p2EkpSpgKdyz8eWomA7edAQN6maztoBycMZFixyz") + expected, err := cid.Decode("QmPpSdhVHqJwoQoiudm4H43xDc2ayJJM37DDFDyzHSVAKL") if err != nil { t.Fatal(err) } @@ -71,7 +72,7 @@ func TestStableCid(t *testing.T) { func TestBalancedDag(t *testing.T) { ds := mdtest.Mock() buf := make([]byte, 10000) - random.NewRand().Read(buf) + random.New().Read(buf) r := bytes.NewReader(buf) nd, err := BuildDagFromReader(ds, chunker.DefaultSplitter(r)) diff --git a/ipld/unixfs/importer/trickle/trickle_test.go b/ipld/unixfs/importer/trickle/trickle_test.go index f9311db946..4d6b91a2e4 100644 --- a/ipld/unixfs/importer/trickle/trickle_test.go +++ b/ipld/unixfs/importer/trickle/trickle_test.go @@ -5,7 +5,6 @@ import ( "context" "fmt" "io" - mrand "math/rand" "runtime" "testing" "time" @@ -77,14 +76,15 @@ func testSizeBasedSplit(t *testing.T, rawLeaves UseRawLeaves) { if testing.Short() { t.SkipNow() } + rnd := random.New() bs := chunker.SizeSplitterGen(512) - testFileConsistency(t, bs, 32*512, rawLeaves) + testFileConsistency(t, rnd, bs, 32*512, rawLeaves) bs = chunker.SizeSplitterGen(4096) - testFileConsistency(t, bs, 32*4096, rawLeaves) + testFileConsistency(t, rnd, bs, 32*4096, rawLeaves) // Uneven offset - testFileConsistency(t, bs, 31*4095, rawLeaves) + testFileConsistency(t, rnd, bs, 31*4095, rawLeaves) } func dup(b []byte) []byte { @@ -93,9 +93,9 @@ func dup(b []byte) []byte { return o } -func testFileConsistency(t *testing.T, bs chunker.SplitterGen, nbytes int, rawLeaves UseRawLeaves) { +func testFileConsistency(t *testing.T, rnd *random.Random, bs chunker.SplitterGen, nbytes int, rawLeaves UseRawLeaves) { should := make([]byte, nbytes) - random.NewRand().Read(should) + rnd.Read(should) read := bytes.NewReader(should) ds := mdtest.Mock() @@ -127,7 +127,7 @@ func TestBuilderConsistency(t *testing.T) { func testBuilderConsistency(t *testing.T, rawLeaves UseRawLeaves) { const nbytes = 100000 buf := new(bytes.Buffer) - io.CopyN(buf, random.NewRand(), int64(nbytes)) + io.CopyN(buf, random.New(), int64(nbytes)) should := dup(buf.Bytes()) dagserv := mdtest.Mock() @@ -171,7 +171,7 @@ func testIndirectBlocks(t *testing.T, rawLeaves UseRawLeaves) { splitter := chunker.SizeSplitterGen(512) const nbytes = 1024 * 1024 buf := make([]byte, nbytes) - random.NewRand().Read(buf) + random.New().Read(buf) read := bytes.NewReader(buf) @@ -203,7 +203,7 @@ func TestSeekingBasic(t *testing.T) { func testSeekingBasic(t *testing.T, rawLeaves UseRawLeaves) { const nbytes = 10 * 1024 should := make([]byte, nbytes) - random.NewRand().Read(should) + random.New().Read(should) read := bytes.NewReader(should) ds := mdtest.Mock() @@ -244,7 +244,7 @@ func TestSeekToBegin(t *testing.T) { func testSeekToBegin(t *testing.T, rawLeaves UseRawLeaves) { const nbytes = 10 * 1024 should := make([]byte, nbytes) - random.NewRand().Read(should) + random.New().Read(should) read := bytes.NewReader(should) ds := mdtest.Mock() @@ -292,7 +292,7 @@ func TestSeekToAlmostBegin(t *testing.T) { func testSeekToAlmostBegin(t *testing.T, rawLeaves UseRawLeaves) { const nbytes = 10 * 1024 should := make([]byte, nbytes) - random.NewRand().Read(should) + random.New().Read(should) read := bytes.NewReader(should) ds := mdtest.Mock() @@ -340,7 +340,7 @@ func TestSeekEnd(t *testing.T) { func testSeekEnd(t *testing.T, rawLeaves UseRawLeaves) { const nbytes = 50 * 1024 should := make([]byte, nbytes) - random.NewRand().Read(should) + random.New().Read(should) read := bytes.NewReader(should) ds := mdtest.Mock() @@ -370,7 +370,7 @@ func TestSeekEndSingleBlockFile(t *testing.T) { func testSeekEndSingleBlockFile(t *testing.T, rawLeaves UseRawLeaves) { const nbytes = 100 should := make([]byte, nbytes) - random.NewRand().Read(should) + random.New().Read(should) read := bytes.NewReader(should) ds := mdtest.Mock() @@ -400,7 +400,8 @@ func TestSeekingStress(t *testing.T) { func testSeekingStress(t *testing.T, rawLeaves UseRawLeaves) { const nbytes = 1024 * 1024 should := make([]byte, nbytes) - random.NewRand().Read(should) + rnd := random.New() + rnd.Read(should) read := bytes.NewReader(should) ds := mdtest.Mock() @@ -416,7 +417,7 @@ func testSeekingStress(t *testing.T, rawLeaves UseRawLeaves) { testbuf := make([]byte, nbytes) for range 50 { - offset := mrand.Intn(int(nbytes)) + offset := rnd.IntN(int(nbytes)) l := int(nbytes) - offset n, err := rs.Seek(int64(offset), io.SeekStart) if err != nil { @@ -448,7 +449,7 @@ func TestSeekingConsistency(t *testing.T) { func testSeekingConsistency(t *testing.T, rawLeaves UseRawLeaves) { const nbytes = 128 * 1024 should := make([]byte, nbytes) - random.NewRand().Read(should) + random.New().Read(should) read := bytes.NewReader(should) ds := mdtest.Mock() @@ -495,7 +496,7 @@ func TestAppend(t *testing.T) { func testAppend(t *testing.T, rawLeaves UseRawLeaves) { const nbytes = 128 * 1024 should := make([]byte, nbytes) - random.NewRand().Read(should) + random.New().Read(should) // Reader for half the bytes read := bytes.NewReader(should[:nbytes/2]) @@ -562,7 +563,7 @@ func testMultipleAppends(t *testing.T, rawLeaves UseRawLeaves) { // TODO: fix small size appends and make this number bigger const nbytes = 1000 should := make([]byte, nbytes) - random.NewRand().Read(should) + random.New().Read(should) read := bytes.NewReader(nil) nd, err := buildTestDag(ds, chunker.NewSizeSplitter(read, 500), rawLeaves) @@ -748,7 +749,7 @@ func TestMetadata(t *testing.T) { func testMetadata(t *testing.T, rawLeaves UseRawLeaves) { nbytes := 3 * chunker.DefaultBlockSize buf := new(bytes.Buffer) - _, err := io.CopyN(buf, random.NewRand(), nbytes) + _, err := io.CopyN(buf, random.New(), nbytes) if err != nil { t.Fatal(err) } diff --git a/ipld/unixfs/mod/dagmodifier_test.go b/ipld/unixfs/mod/dagmodifier_test.go index 3245980d27..00e9497fb4 100644 --- a/ipld/unixfs/mod/dagmodifier_test.go +++ b/ipld/unixfs/mod/dagmodifier_test.go @@ -23,7 +23,7 @@ import ( func testModWrite(t *testing.T, beg, size uint64, orig []byte, dm *DagModifier, opts testu.NodeOpts) []byte { newdata := make([]byte, size) - random.NewRand().Read(newdata) + random.New().Read(newdata) if size+beg > uint64(len(orig)) { orig = append(orig, make([]byte, (size+beg)-uint64(len(orig)))...) @@ -165,7 +165,7 @@ func testMultiWrite(t *testing.T, opts testu.NodeOpts) { } data := make([]byte, 4000) - random.NewRand().Read(data) + random.New().Read(data) for i := range data { n, err := dagmod.WriteAt(data[i:i+1], int64(i)) @@ -209,7 +209,7 @@ func testMultiWriteAndFlush(t *testing.T, opts testu.NodeOpts) { } data := make([]byte, 20) - random.NewRand().Read(data) + random.New().Read(data) for i := range data { n, err := dagmod.WriteAt(data[i:i+1], int64(i)) @@ -248,7 +248,7 @@ func testWriteNewFile(t *testing.T, opts testu.NodeOpts) { } towrite := make([]byte, 2000) - random.NewRand().Read(towrite) + random.New().Read(towrite) nw, err := dagmod.Write(towrite) if err != nil { @@ -281,7 +281,7 @@ func testMultiWriteCoal(t *testing.T, opts testu.NodeOpts) { } data := make([]byte, 1000) - random.NewRand().Read(data) + random.New().Read(data) for i := range data { n, err := dagmod.WriteAt(data[:i+1], 0) @@ -321,7 +321,7 @@ func testLargeWriteChunks(t *testing.T, opts testu.NodeOpts) { const datasize = 10000000 data := make([]byte, datasize) - random.NewRand().Read(data) + random.New().Read(data) for i := range datasize / wrsize { n, err := dagmod.WriteAt(data[i*wrsize:(i+1)*wrsize], int64(i*wrsize)) @@ -535,7 +535,7 @@ func testSparseWrite(t *testing.T, opts testu.NodeOpts) { } buf := make([]byte, 5000) - random.NewRand().Read(buf[2500:]) + random.New().Read(buf[2500:]) wrote, err := dagmod.WriteAt(buf[2500:], 2500) if err != nil { @@ -580,7 +580,7 @@ func testSeekPastEndWrite(t *testing.T, opts testu.NodeOpts) { } buf := make([]byte, 5000) - random.NewRand().Read(buf[2500:]) + random.New().Read(buf[2500:]) nseek, err := dagmod.Seek(2500, io.SeekStart) if err != nil { @@ -923,7 +923,7 @@ func BenchmarkDagmodWrite(b *testing.B) { } buf := make([]byte, b.N*wrsize) - random.NewRand().Read(buf) + random.New().Read(buf) b.StartTimer() b.SetBytes(int64(wrsize)) for i := 0; i < b.N; i++ { diff --git a/ipld/unixfs/test/utils.go b/ipld/unixfs/test/utils.go index 38e24dba80..23b7e72a6f 100644 --- a/ipld/unixfs/test/utils.go +++ b/ipld/unixfs/test/utils.go @@ -84,7 +84,7 @@ func GetEmptyNode(t testing.TB, dserv ipld.DAGService, opts NodeOpts) ipld.Node // GetRandomNode returns a random unixfs file node. func GetRandomNode(t testing.TB, dserv ipld.DAGService, size int64, opts NodeOpts) ([]byte, ipld.Node) { - buf := random.Bytes(int(size)) + buf := random.New().Bytes(size) return buf, GetNode(t, dserv, buf, opts) } diff --git a/ipns/validation_test.go b/ipns/validation_test.go index a288616ee8..7062d37282 100644 --- a/ipns/validation_test.go +++ b/ipns/validation_test.go @@ -1,7 +1,7 @@ package ipns import ( - "math/rand" + "math/rand/v2" "testing" "time" @@ -18,7 +18,7 @@ import ( func shuffle[T any](a []T) { for range 5 { for i := range a { - j := rand.Intn(len(a)) + j := rand.IntN(len(a)) a[i], a[j] = a[j], a[i] } } diff --git a/mfs/mfs_test.go b/mfs/mfs_test.go index 8f0f03b706..eb27082f6e 100644 --- a/mfs/mfs_test.go +++ b/mfs/mfs_test.go @@ -3,12 +3,10 @@ package mfs import ( "bytes" "context" - crand "crypto/rand" "encoding/binary" "errors" "fmt" "io" - "math/rand" "os" gopath "path" "runtime" @@ -47,7 +45,7 @@ func getDagserv(t testing.TB) ipld.DAGService { } func getRandFile(t *testing.T, ds ipld.DAGService, size int64) ipld.Node { - r := io.LimitReader(random.NewRand(), size) + r := io.LimitReader(random.New(), size) return fileNodeFromReader(t, ds, r) } @@ -800,7 +798,8 @@ func TestMfsRawNodeSetModeAndMtime(t *testing.T) { rootdir := rt.GetDirectory() // Create raw-node file. - nd := dag.NewRawNode(random.Bytes(256)) + rnd := random.New() + nd := dag.NewRawNode(rnd.Bytes(256)) _, err := ft.ExtractFSNode(nd) if !errors.Is(err, ft.ErrNotProtoNode) { t.Fatal("Expected non-proto node") @@ -874,13 +873,14 @@ func TestMfsDirListNames(t *testing.T) { rootdir := rt.GetDirectory() - total := rand.Intn(10) + 1 + rnd := random.New() + total := rnd.IntN(10) + 1 fNames := make([]string, 0, total) for range total { - fn := randomName() + fn := randomName(rnd) fNames = append(fNames, fn) - nd := getRandFile(t, ds, rand.Int63n(1000)+1) + nd := getRandFile(t, ds, rnd.Int64N(1000)+1) err := rootdir.AddChild(fn, nd) if err != nil { t.Fatal(err) @@ -900,7 +900,7 @@ func TestMfsDirListNames(t *testing.T) { } } -func randomWalk(d *Directory, n int) (*Directory, error) { +func randomWalk(rnd *random.Random, d *Directory, n int) (*Directory, error) { for range n { dirents, err := d.List(context.Background()) if err != nil { @@ -917,7 +917,7 @@ func randomWalk(d *Directory, n int) (*Directory, error) { return d, nil } - next := childdirs[rand.Intn(len(childdirs))].Name + next := childdirs[rnd.IntN(len(childdirs))].Name nextD, err := d.Child(next) if err != nil { @@ -929,24 +929,17 @@ func randomWalk(d *Directory, n int) (*Directory, error) { return d, nil } -func randomName() string { - set := "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890_" - length := rand.Intn(10) + 2 - var out strings.Builder - for range length { - j := rand.Intn(len(set)) - out.WriteString(set[j : j+1]) - } - return out.String() +func randomName(rnd *random.Random) string { + return rnd.NameSize(2, 11) } -func actorMakeFile(d *Directory) error { - d, err := randomWalk(d, rand.Intn(7)) +func actorMakeFile(rnd *random.Random, d *Directory) error { + d, err := randomWalk(rnd, d, rnd.IntN(7)) if err != nil { return err } - name := randomName() + name := randomName(rnd) prov := new(fakeProvider) f, err := NewFile(name, dag.NodeWithData(ft.FilePBData(nil, 0)), d, d.dagService, prov) if err != nil { @@ -958,8 +951,7 @@ func actorMakeFile(d *Directory) error { return err } - rread := rand.New(rand.NewSource(time.Now().UnixNano())) - r := io.LimitReader(rread, int64(77*rand.Intn(123)+1)) + r := io.LimitReader(rnd, int64(77*rnd.IntN(123)+1)) _, err = io.Copy(wfd, r) if err != nil { return err @@ -968,19 +960,19 @@ func actorMakeFile(d *Directory) error { return wfd.Close() } -func actorMkdir(d *Directory) error { - d, err := randomWalk(d, rand.Intn(7)) +func actorMkdir(rnd *random.Random, d *Directory) error { + d, err := randomWalk(rnd, d, rnd.IntN(7)) if err != nil { return err } - _, err = d.Mkdir(randomName()) + _, err = d.Mkdir(randomName(rnd)) return err } -func randomFile(d *Directory) (*File, error) { - d, err := randomWalk(d, rand.Intn(6)) +func randomFile(rnd *random.Random, d *Directory) (*File, error) { + d, err := randomWalk(rnd, d, rnd.IntN(6)) if err != nil { return nil, err } @@ -1001,7 +993,7 @@ func randomFile(d *Directory) (*File, error) { return nil, nil } - fname := files[rand.Intn(len(files))] + fname := files[rnd.IntN(len(files))] fsn, err := d.Child(fname) if err != nil { return nil, err @@ -1015,8 +1007,8 @@ func randomFile(d *Directory) (*File, error) { return fi, nil } -func actorWriteFile(d *Directory) error { - fi, err := randomFile(d) +func actorWriteFile(rnd *random.Random, d *Directory) error { + fi, err := randomFile(rnd, d) if err != nil { return err } @@ -1024,11 +1016,9 @@ func actorWriteFile(d *Directory) error { return nil } - size := rand.Intn(1024) + 1 + size := rnd.IntN(1024) + 1 buf := make([]byte, size) - if _, err := crand.Read(buf); err != nil { - return err - } + _, _ = rnd.Read(buf) s, err := fi.Size() if err != nil { @@ -1040,7 +1030,7 @@ func actorWriteFile(d *Directory) error { return err } - offset := rand.Int63n(s) + offset := rnd.Int64N(s) n, err := wfd.WriteAt(buf, offset) if err != nil { @@ -1053,8 +1043,8 @@ func actorWriteFile(d *Directory) error { return wfd.Close() } -func actorReadFile(d *Directory) error { - fi, err := randomFile(d) +func actorReadFile(rnd *random.Random, d *Directory) error { + fi, err := randomFile(rnd, d) if err != nil { return err } @@ -1081,26 +1071,27 @@ func actorReadFile(d *Directory) error { } func testActor(rt *Root, iterations int, errs chan error) { + rnd := random.New() d := rt.GetDirectory() for range iterations { - switch rand.Intn(5) { + switch rnd.IntN(5) { case 0: - if err := actorMkdir(d); err != nil { + if err := actorMkdir(rnd, d); err != nil { errs <- err return } case 1, 2: - if err := actorMakeFile(d); err != nil { + if err := actorMakeFile(rnd, d); err != nil { errs <- err return } case 3: - if err := actorWriteFile(d); err != nil { + if err := actorWriteFile(rnd, d); err != nil { errs <- err return } case 4: - if err := actorReadFile(d); err != nil { + if err := actorReadFile(rnd, d); err != nil { errs <- err return } @@ -1298,9 +1289,7 @@ func TestConcurrentReads(t *testing.T) { d := mkdirP(t, rootdir, path) buf := make([]byte, 2048) - if _, err := crand.Read(buf); err != nil { - t.Fatal(err) - } + _, _ = random.New().Read(buf) fi := fileNodeFromReader(t, ds, bytes.NewReader(buf)) err := d.AddChild("afile", fi) if err != nil { @@ -1313,10 +1302,11 @@ func TestConcurrentReads(t *testing.T) { wg.Add(1) go func(me int) { defer wg.Done() + rnd := random.New() mybuf := make([]byte, len(buf)) for range nloops { - offset := rand.Intn(len(buf)) - length := rand.Intn(len(buf) - offset) + offset := rnd.IntN(len(buf)) + length := rnd.IntN(len(buf) - offset) err := readFile(rt, "/a/b/c/afile", int64(offset), mybuf[:length]) if err != nil { @@ -1482,21 +1472,18 @@ func TestConcurrentFlushAndClose(t *testing.T) { // and then observe a consistent state (either flushed or // closed). Neither should panic. var wg sync.WaitGroup - wg.Add(2) - go func() { - defer wg.Done() + wg.Go(func() { // Flush may succeed or return ErrClosed if Close wins. err := fd.Flush() if err != nil && !errors.Is(err, ErrClosed) { t.Errorf("Flush: unexpected error: %v", err) } - }() - go func() { - defer wg.Done() + }) + wg.Go(func() { if err := fd.Close(); err != nil { t.Errorf("Close: %v", err) } - }() + }) wg.Wait() // A second Close must return ErrClosed. diff --git a/path/resolver/resolver_test.go b/path/resolver/resolver_test.go index 6e4cbf1f54..f9b18be77d 100644 --- a/path/resolver/resolver_test.go +++ b/path/resolver/resolver_test.go @@ -3,10 +3,11 @@ package resolver_test import ( "bytes" "context" - "math/rand" + crand "crypto/rand" + "io" + "math/rand/v2" "strings" "testing" - "time" bsfetcher "github.com/ipfs/boxo/fetcher/impl/blockservice" merkledag "github.com/ipfs/boxo/ipld/merkledag" @@ -28,10 +29,9 @@ import ( "github.com/stretchr/testify/require" ) -func randNode() *merkledag.ProtoNode { +func randNode(r io.Reader) *merkledag.ProtoNode { node := new(merkledag.ProtoNode) node.SetData(make([]byte, 32)) - r := rand.New(rand.NewSource(time.Now().UnixNano())) r.Read(node.Data()) return node } @@ -40,9 +40,13 @@ func TestRecursivePathResolution(t *testing.T) { ctx := context.Background() bsrv := dagmock.Bserv() - a := randNode() - b := randNode() - c := randNode() + var seed [32]byte + _, _ = crand.Read(seed[:]) + cc8 := rand.NewChaCha8(seed) + + a := randNode(cc8) + b := randNode(cc8) + c := randNode(cc8) err := b.AddNodeLink("grandchild", c) require.NoError(t, err) @@ -97,9 +101,13 @@ func TestResolveToLastNode_ErrNoLink(t *testing.T) { ctx := context.Background() bsrv := dagmock.Bserv() - a := randNode() - b := randNode() - c := randNode() + var seed [32]byte + _, _ = crand.Read(seed[:]) + cc8 := rand.NewChaCha8(seed) + + a := randNode(cc8) + b := randNode(cc8) + c := randNode(cc8) err := b.AddNodeLink("grandchild", c) require.NoError(t, err) @@ -150,8 +158,12 @@ func TestResolveToLastNode_NoUnnecessaryFetching(t *testing.T) { ctx := context.Background() bsrv := dagmock.Bserv() - a := randNode() - b := randNode() + var seed [32]byte + _, _ = crand.Read(seed[:]) + cc8 := rand.NewChaCha8(seed) + + a := randNode(cc8) + b := randNode(cc8) err := a.AddNodeLink("child", b) require.NoError(t, err) @@ -226,7 +238,11 @@ func TestResolveToLastNode_MixedSegmentTypes(t *testing.T) { ctx := t.Context() bsrv := dagmock.Bserv() - a := randNode() + var seed [32]byte + _, _ = crand.Read(seed[:]) + cc8 := rand.NewChaCha8(seed) + + a := randNode(cc8) err := bsrv.AddBlock(ctx, a) require.NoError(t, err) @@ -275,9 +291,13 @@ func TestResolveToLastNode_MixedSegmentTypes(t *testing.T) { func TestRetrievalStatePropagation(t *testing.T) { bsrv := dagmock.Bserv() - root := randNode() - mid := randNode() - leaf := randNode() + var seed [32]byte + _, _ = crand.Read(seed[:]) + cc8 := rand.NewChaCha8(seed) + + root := randNode(cc8) + mid := randNode(cc8) + leaf := randNode(cc8) require.NoError(t, mid.AddNodeLink("grandchild", leaf)) require.NoError(t, root.AddNodeLink("child", mid)) for _, n := range []*merkledag.ProtoNode{root, mid, leaf} { diff --git a/peering/peering.go b/peering/peering.go index 77d3139580..f20b540a2b 100644 --- a/peering/peering.go +++ b/peering/peering.go @@ -3,7 +3,7 @@ package peering import ( "context" "errors" - "math/rand" + "math/rand/v2" "slices" "strconv" "sync" @@ -97,14 +97,14 @@ func (ph *peerHandler) stop() { func (ph *peerHandler) nextBackoff() time.Duration { if ph.nextDelay < maxBackoff { - ph.nextDelay += ph.nextDelay/2 + time.Duration(rand.Int63n(int64(ph.nextDelay))) + ph.nextDelay += ph.nextDelay/2 + time.Duration(rand.Int64N(int64(ph.nextDelay))) } // If we've gone over the max backoff, reduce it under the max. if ph.nextDelay > maxBackoff { ph.nextDelay = maxBackoff // randomize the backoff a bit (10%). - ph.nextDelay -= time.Duration(rand.Int63n(int64(maxBackoff) * maxBackoffJitter / 100)) + ph.nextDelay -= time.Duration(rand.Int64N(int64(maxBackoff) * maxBackoffJitter / 100)) } return ph.nextDelay diff --git a/pinning/pinner/dspinner/pin_test.go b/pinning/pinner/dspinner/pin_test.go index 2deff46c33..3763c1b844 100644 --- a/pinning/pinner/dspinner/pin_test.go +++ b/pinning/pinner/dspinner/pin_test.go @@ -41,7 +41,7 @@ func (f *fakeLogger) Errorf(format string, args ...any) { func randNode() (*mdag.ProtoNode, cid.Cid) { nd := new(mdag.ProtoNode) - nd.SetData(random.Bytes(32)) + nd.SetData(random.New().Bytes(32)) return nd, nd.Cid() } diff --git a/routing/mock/centralized_server.go b/routing/mock/centralized_server.go index 85c7688146..f36ff44a8d 100644 --- a/routing/mock/centralized_server.go +++ b/routing/mock/centralized_server.go @@ -2,7 +2,7 @@ package mockrouting import ( "context" - "math/rand" + "math/rand/v2" "sync" "time" @@ -71,7 +71,7 @@ func (rs *s) Providers(c cid.Cid) []peer.AddrInfo { } for i := range ret { - j := rand.Intn(i + 1) + j := rand.IntN(i + 1) ret[i], ret[j] = ret[j], ret[i] } return ret diff --git a/routing/providerquerymanager/providerquerymanager_test.go b/routing/providerquerymanager/providerquerymanager_test.go index 8987998e08..1a056d6fc5 100644 --- a/routing/providerquerymanager/providerquerymanager_test.go +++ b/routing/providerquerymanager/providerquerymanager_test.go @@ -69,7 +69,8 @@ func mustNotErr[T any](out T, err error) T { } func TestNormalSimultaneousFetch(t *testing.T) { - peers := random.Peers(10) + rnd := random.New() + peers := rnd.Peers(10) fpd := &fakeProviderDialer{} fpn := &fakeProviderDiscovery{ peersFound: peers, @@ -77,7 +78,7 @@ func TestNormalSimultaneousFetch(t *testing.T) { } providerQueryManager := mustNotErr(New(fpd, fpn)) defer providerQueryManager.Close() - keys := random.Cids(2) + keys := rnd.Cids(2) sessionCtx, cancel := context.WithTimeout(context.Background(), 5*time.Second) defer cancel() @@ -106,7 +107,8 @@ func TestNormalSimultaneousFetch(t *testing.T) { } func TestDedupingProviderRequests(t *testing.T) { - peers := random.Peers(10) + rnd := random.New() + peers := rnd.Peers(10) fpd := &fakeProviderDialer{} fpn := &fakeProviderDiscovery{ peersFound: peers, @@ -114,7 +116,7 @@ func TestDedupingProviderRequests(t *testing.T) { } providerQueryManager := mustNotErr(New(fpd, fpn)) defer providerQueryManager.Close() - key := random.Cids(1)[0] + key := rnd.Cids(1)[0] sessionCtx, cancel := context.WithTimeout(context.Background(), 5*time.Second) defer cancel() @@ -146,7 +148,8 @@ func TestDedupingProviderRequests(t *testing.T) { } func TestCancelOneRequestDoesNotTerminateAnother(t *testing.T) { - peers := random.Peers(10) + rnd := random.New() + peers := rnd.Peers(10) fpd := &fakeProviderDialer{} fpn := &fakeProviderDiscovery{ peersFound: peers, @@ -155,7 +158,7 @@ func TestCancelOneRequestDoesNotTerminateAnother(t *testing.T) { providerQueryManager := mustNotErr(New(fpd, fpn)) defer providerQueryManager.Close() - key := random.Cids(1)[0] + key := rnd.Cids(1)[0] // first session will cancel before done ctx := context.Background() @@ -191,7 +194,8 @@ func TestCancelOneRequestDoesNotTerminateAnother(t *testing.T) { } func TestCancelManagerExitsGracefully(t *testing.T) { - peers := random.Peers(10) + rnd := random.New() + peers := rnd.Peers(10) fpd := &fakeProviderDialer{} fpn := &fakeProviderDiscovery{ peersFound: peers, @@ -201,7 +205,7 @@ func TestCancelManagerExitsGracefully(t *testing.T) { defer providerQueryManager.Close() time.AfterFunc(5*time.Millisecond, providerQueryManager.Close) - key := random.Cids(1)[0] + key := rnd.Cids(1)[0] sessionCtx, cancel := context.WithTimeout(context.Background(), 20*time.Millisecond) defer cancel() @@ -225,7 +229,8 @@ func TestCancelManagerExitsGracefully(t *testing.T) { } func TestPeersWithConnectionErrorsNotAddedToPeerList(t *testing.T) { - peers := random.Peers(10) + rnd := random.New() + peers := rnd.Peers(10) fpd := &fakeProviderDialer{ connectError: errors.New("not able to connect"), } @@ -236,7 +241,7 @@ func TestPeersWithConnectionErrorsNotAddedToPeerList(t *testing.T) { providerQueryManager := mustNotErr(New(fpd, fpn)) defer providerQueryManager.Close() - key := random.Cids(1)[0] + key := rnd.Cids(1)[0] sessionCtx, cancel := context.WithTimeout(context.Background(), 20*time.Millisecond) defer cancel() @@ -261,7 +266,8 @@ func TestPeersWithConnectionErrorsNotAddedToPeerList(t *testing.T) { func TestRateLimitingRequests(t *testing.T) { const maxInProcessRequests = 6 - peers := random.Peers(10) + rnd := random.New() + peers := rnd.Peers(10) fpd := &fakeProviderDialer{} fpn := &fakeProviderDiscovery{ peersFound: peers, @@ -270,7 +276,7 @@ func TestRateLimitingRequests(t *testing.T) { providerQueryManager := mustNotErr(New(fpd, fpn, WithMaxInProcessRequests(maxInProcessRequests))) defer providerQueryManager.Close() - keys := random.Cids(maxInProcessRequests + 1) + keys := rnd.Cids(maxInProcessRequests + 1) sessionCtx, cancel := context.WithTimeout(context.Background(), 5*time.Second) defer cancel() var requestChannels []<-chan peer.AddrInfo @@ -300,7 +306,8 @@ func TestRateLimitingRequests(t *testing.T) { func TestUnlimitedRequests(t *testing.T) { const inProcessRequests = 11 - peers := random.Peers(10) + rnd := random.New() + peers := rnd.Peers(10) fpd := &fakeProviderDialer{} fpn := &fakeProviderDiscovery{ peersFound: peers, @@ -311,7 +318,7 @@ func TestUnlimitedRequests(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - keys := random.Cids(inProcessRequests) + keys := rnd.Cids(inProcessRequests) sessionCtx, cancel := context.WithTimeout(ctx, 5*time.Second) defer cancel() var requestChannels []<-chan peer.AddrInfo @@ -339,7 +346,8 @@ func TestUnlimitedRequests(t *testing.T) { } func TestFindProviderTimeout(t *testing.T) { - peers := random.Peers(10) + rnd := random.New() + peers := rnd.Peers(10) fpd := &fakeProviderDialer{} fpn := &fakeProviderDiscovery{ peersFound: peers, @@ -347,7 +355,7 @@ func TestFindProviderTimeout(t *testing.T) { } providerQueryManager := mustNotErr(New(fpd, fpn, WithMaxTimeout(2*time.Millisecond))) defer providerQueryManager.Close() - keys := random.Cids(1) + keys := rnd.Cids(1) sessionCtx, cancel := context.WithTimeout(context.Background(), 5*time.Second) defer cancel() @@ -362,7 +370,8 @@ func TestFindProviderTimeout(t *testing.T) { } func TestFindProviderPreCanceled(t *testing.T) { - peers := random.Peers(10) + rnd := random.New() + peers := rnd.Peers(10) fpd := &fakeProviderDialer{} fpn := &fakeProviderDiscovery{ peersFound: peers, @@ -370,7 +379,7 @@ func TestFindProviderPreCanceled(t *testing.T) { } providerQueryManager := mustNotErr(New(fpd, fpn, WithMaxTimeout(100*time.Millisecond))) defer providerQueryManager.Close() - keys := random.Cids(1) + keys := rnd.Cids(1) sessionCtx, cancel := context.WithCancel(context.Background()) cancel() @@ -386,7 +395,8 @@ func TestFindProviderPreCanceled(t *testing.T) { } func TestCancelFindProvidersAfterCompletion(t *testing.T) { - peers := random.Peers(2) + rnd := random.New() + peers := rnd.Peers(2) fpd := &fakeProviderDialer{} fpn := &fakeProviderDiscovery{ peersFound: peers, @@ -394,7 +404,7 @@ func TestCancelFindProvidersAfterCompletion(t *testing.T) { } providerQueryManager := mustNotErr(New(fpd, fpn, WithMaxTimeout(100*time.Millisecond))) defer providerQueryManager.Close() - keys := random.Cids(1) + keys := rnd.Cids(1) sessionCtx, cancel := context.WithCancel(context.Background()) firstRequestChan := providerQueryManager.FindProvidersAsync(sessionCtx, keys[0], 0) @@ -417,8 +427,9 @@ func TestCancelFindProvidersAfterCompletion(t *testing.T) { } func TestLimitedProviders(t *testing.T) { - max := 5 - peers := random.Peers(10) + const max = 5 + rnd := random.New() + peers := rnd.Peers(10) fpd := &fakeProviderDialer{} fpn := &fakeProviderDiscovery{ peersFound: peers, @@ -439,7 +450,8 @@ func TestLimitedProviders(t *testing.T) { } func TestIgnorePeers(t *testing.T) { - peers := random.Peers(5) + rnd := random.New() + peers := rnd.Peers(5) fpd := &fakeProviderDialer{} fpn := &fakeProviderDiscovery{ peersFound: peers, @@ -449,7 +461,7 @@ func TestIgnorePeers(t *testing.T) { WithIgnoreProviders(peers[0:4]...), )) defer providerQueryManager.Close() - keys := random.Cids(1) + keys := rnd.Cids(1) providersChan := providerQueryManager.FindProvidersAsync(context.Background(), keys[0], 0) total := 0 @@ -547,7 +559,8 @@ func collect(ch <-chan peer.AddrInfo) []peer.AddrInfo { } func TestFindPeerFallbackRescuesFailedDial(t *testing.T) { - peers := random.Peers(1) + rnd := random.New() + peers := rnd.Peers(1) p := peers[0] freshAddr := ma.StringCast("/ip4/198.51.100.7/tcp/4001") @@ -562,7 +575,7 @@ func TestFindPeerFallbackRescuesFailedDial(t *testing.T) { sessionCtx, cancel := context.WithTimeout(context.Background(), 5*time.Second) defer cancel() - received := collect(pqm.FindProvidersAsync(sessionCtx, random.Cids(1)[0], 0)) + received := collect(pqm.FindProvidersAsync(sessionCtx, rnd.Cids(1)[0], 0)) if len(received) != 1 { t.Fatalf("expected 1 provider after retry, got %d", len(received)) @@ -576,7 +589,8 @@ func TestFindPeerFallbackRescuesFailedDial(t *testing.T) { } func TestFindPeerFallbackSkippedWhenNoAddrs(t *testing.T) { - peers := random.Peers(1) + rnd := random.New() + peers := rnd.Peers(1) p := peers[0] dialer := &callCountingDialer{} @@ -590,7 +604,7 @@ func TestFindPeerFallbackSkippedWhenNoAddrs(t *testing.T) { sessionCtx, cancel := context.WithTimeout(context.Background(), 5*time.Second) defer cancel() - received := collect(pqm.FindProvidersAsync(sessionCtx, random.Cids(1)[0], 0)) + received := collect(pqm.FindProvidersAsync(sessionCtx, rnd.Cids(1)[0], 0)) if len(received) != 0 { t.Fatalf("expected 0 providers, got %d", len(received)) @@ -604,7 +618,8 @@ func TestFindPeerFallbackSkippedWhenNoAddrs(t *testing.T) { } func TestFindPeerFallbackSkippedWhenErrors(t *testing.T) { - peers := random.Peers(1) + rnd := random.New() + peers := rnd.Peers(1) p := peers[0] dialer := &callCountingDialer{} @@ -616,7 +631,7 @@ func TestFindPeerFallbackSkippedWhenErrors(t *testing.T) { sessionCtx, cancel := context.WithTimeout(context.Background(), 5*time.Second) defer cancel() - received := collect(pqm.FindProvidersAsync(sessionCtx, random.Cids(1)[0], 0)) + received := collect(pqm.FindProvidersAsync(sessionCtx, rnd.Cids(1)[0], 0)) if len(received) != 0 { t.Fatalf("expected 0 providers, got %d", len(received)) @@ -631,7 +646,8 @@ func TestFindPeerFallbackSkippedWhenErrors(t *testing.T) { // the routing-record AddrInfo just tried, we don't retry (it would just // dial the same broken set again). func TestFindPeerFallbackSkippedWhenNoNewAddrs(t *testing.T) { - peers := random.Peers(1) + rnd := random.New() + peers := rnd.Peers(1) p := peers[0] knownAddr := ma.StringCast("/ip4/198.51.100.7/tcp/4001") @@ -651,7 +667,7 @@ func TestFindPeerFallbackSkippedWhenNoNewAddrs(t *testing.T) { sessionCtx, cancel := context.WithTimeout(context.Background(), 5*time.Second) defer cancel() - received := collect(pqm.FindProvidersAsync(sessionCtx, random.Cids(1)[0], 0)) + received := collect(pqm.FindProvidersAsync(sessionCtx, rnd.Cids(1)[0], 0)) if len(received) != 0 { t.Fatalf("expected 0 providers (retry skipped, dial stays failed), got %d", len(received)) diff --git a/util/file_test.go b/util/file_test.go index 040b229270..a2374461b3 100644 --- a/util/file_test.go +++ b/util/file_test.go @@ -1,10 +1,14 @@ -package util +package util_test -import "testing" +import ( + "testing" + + "github.com/ipfs/boxo/util" +) func TestFileDoesNotExist(t *testing.T) { t.Parallel() - if FileExists("i would be surprised to discover that this file exists") { + if util.FileExists("i would be surprised to discover that this file exists") { t.Fail() } } diff --git a/util/time_test.go b/util/time_test.go index b5a98caa62..8b27e416db 100644 --- a/util/time_test.go +++ b/util/time_test.go @@ -1,12 +1,14 @@ -package util +package util_test import ( "testing" "time" + + "github.com/ipfs/boxo/util" ) func TestTimeFormatParseInversion(t *testing.T) { - v, err := ParseRFC3339(FormatRFC3339(time.Now())) + v, err := util.ParseRFC3339(util.FormatRFC3339(time.Now())) if err != nil { t.Fatal(err) } diff --git a/util/util.go b/util/util.go index 3a76dd2389..ffbeb49222 100644 --- a/util/util.go +++ b/util/util.go @@ -5,13 +5,10 @@ package util import ( "crypto/subtle" "errors" - "io" - "math/rand" "os" "path/filepath" "runtime/debug" "strings" - "time" b58 "github.com/mr-tron/base58/base58" mh "github.com/multiformats/go-multihash" @@ -54,22 +51,6 @@ func ExpandPathnames(paths []string) ([]string, error) { return out, nil } -// NewTimeSeededRand returns a random bytes reader -// which has been initialized with the current time. -// -// Deprecated: use github.com/ipfs/go-test/random instead. -func NewTimeSeededRand() io.Reader { - return NewSeededRand(time.Now().UnixNano()) -} - -// NewSeededRand returns a random bytes reader -// initialized with the given seed. -// -// Deprecated: use github.com/ipfs/go-test/random instead. -func NewSeededRand(seed int64) io.Reader { - return rand.New(rand.NewSource(seed)) -} - // GetenvBool is the way to check an env var as a boolean func GetenvBool(name string) bool { v := strings.ToLower(os.Getenv(name)) diff --git a/util/util_test.go b/util/util_test.go index b3733ec450..52ddc22fad 100644 --- a/util/util_test.go +++ b/util/util_test.go @@ -1,9 +1,12 @@ -package util +package util_test import ( "bytes" - "math/rand" + "encoding/binary" + "math/rand/v2" "testing" + + "github.com/ipfs/boxo/util" ) func TestXOR(t *testing.T) { @@ -26,7 +29,7 @@ func TestXOR(t *testing.T) { } for _, c := range cases { - r := XOR(c[0], c[1]) + r := util.XOR(c[0], c[1]) if !bytes.Equal(r, c[2]) { t.Error("XOR failed") } @@ -39,7 +42,7 @@ func BenchmarkHash256K(b *testing.B) { b.SetBytes(size) b.ResetTimer() for i := 0; i < b.N; i++ { - Hash(buf) + util.Hash(buf) } } @@ -49,7 +52,7 @@ func BenchmarkHash512K(b *testing.B) { b.SetBytes(size) b.ResetTimer() for i := 0; i < b.N; i++ { - Hash(buf) + util.Hash(buf) } } @@ -59,13 +62,15 @@ func BenchmarkHash1M(b *testing.B) { b.SetBytes(size) b.ResetTimer() for i := 0; i < b.N; i++ { - Hash(buf) + util.Hash(buf) } } func randomBytes(n int) []byte { + var seed [32]byte + binary.BigEndian.PutUint64(seed[:], uint64(n)) + cc8 := rand.NewChaCha8(seed) data := make([]byte, n) - r := rand.New(rand.NewSource(int64(n))) - r.Read(data) + cc8.Read(data) return data }