From ffe45a2bd6192efdb7f32b6580d2f871c29f91ee Mon Sep 17 00:00:00 2001 From: gammazero <11790789+gammazero@users.noreply.github.com> Date: Wed, 8 Jul 2026 22:53:47 -1000 Subject: [PATCH 01/11] wip --- .../providerquerymanager_test.go | 80 +++++++++++-------- util/util.go | 19 ----- 2 files changed, 48 insertions(+), 51 deletions(-) diff --git a/routing/providerquerymanager/providerquerymanager_test.go b/routing/providerquerymanager/providerquerymanager_test.go index 8987998e0..1a056d6fc 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/util.go b/util/util.go index 3a76dd238..ffbeb4922 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)) From f2c858de5a9a0fd1ee0a1347f801359ab0c36b60 Mon Sep 17 00:00:00 2001 From: gammazero <11790789+gammazero@users.noreply.github.com> Date: Thu, 9 Jul 2026 05:35:37 -1000 Subject: [PATCH 02/11] migrate to next major version of go-test Replace all use of `math/rand` with `math/rand/v2` --- autoconf/client.go | 4 +- autoconf/expansion.go | 4 +- bitswap/benchmarks_test.go | 34 +++--- .../blockpresencemanager_test.go | 15 +-- .../messagequeue/messagequeue_test.go | 101 ++++++++++-------- .../internal/peermanager/peermanager_test.go | 27 ++--- .../peermanager/peerwantmanager_test.go | 64 ++++++----- .../internal/session/peerresponsetracker.go | 2 +- .../client/internal/session/session_test.go | 35 +++--- .../client/internal/session/sessionwants.go | 4 +- .../internal/session/sessionwants_test.go | 5 +- .../session/sessionwantsender_test.go | 67 +++++++----- .../sessioninterestmanager_test.go | 15 +-- bitswap/message/message_test.go | 5 +- .../decision/blockstoremanager_test.go | 15 ++- .../server/internal/decision/engine_test.go | 5 +- .../internet_latency_delay_generator.go | 11 +- .../internet_latency_delay_generator_test.go | 5 +- bitswap/testnet/rate_limit_generators.go | 6 +- blockstore/twoqueue_cache_test.go | 9 +- bootstrap/bootstrap.go | 2 +- chunker/benchmark_test.go | 10 +- chunker/buzhash_test.go | 8 +- chunker/gen/main.go | 4 +- chunker/rabin_test.go | 14 +-- chunker/splitting_test.go | 8 +- examples/bitswap-transfer/main.go | 7 +- examples/go.sum | 4 +- exchange/offline/offline_test.go | 7 +- gateway/backend_car_fetcher.go | 11 +- gateway/blockstore.go | 11 +- gateway/value_store.go | 11 +- go.mod | 2 +- go.sum | 4 +- ipld/merkledag/merkledag_test.go | 21 ++-- ipld/unixfs/hamt/hamt_stress_test.go | 24 +++-- ipld/unixfs/hamt/hamt_test.go | 50 +++++---- .../unixfs/importer/balanced/balanced_test.go | 10 +- ipld/unixfs/importer/importer_test.go | 11 +- ipld/unixfs/importer/trickle/trickle_test.go | 39 +++---- ipld/unixfs/mod/dagmodifier_test.go | 18 ++-- ipld/unixfs/test/utils.go | 2 +- ipns/validation_test.go | 4 +- mfs/mfs_test.go | 97 ++++++++--------- path/resolver/resolver_test.go | 52 ++++++--- peering/peering.go | 6 +- pinning/pinner/dspinner/pin_test.go | 2 +- routing/mock/centralized_server.go | 4 +- util/file_test.go | 10 +- util/time_test.go | 6 +- util/util_test.go | 21 ++-- 51 files changed, 496 insertions(+), 417 deletions(-) diff --git a/autoconf/client.go b/autoconf/client.go index 674f14b29..602733886 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 e8099acc6..fea688cd6 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 c0ca60e32..3298cef14 100644 --- a/bitswap/benchmarks_test.go +++ b/bitswap/benchmarks_test.go @@ -5,7 +5,6 @@ import ( "encoding/json" "fmt" "math" - "math/rand" "os" "strconv" "sync" @@ -135,6 +134,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 +169,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 @@ -210,9 +210,9 @@ const ( func BenchmarkRealWorld(b *testing.B) { benchmarkLog = nil benchmarkSeed, err := strconv.ParseInt(os.Getenv("BENCHMARK_SEED"), 10, 64) - var randomGen *rand.Rand = nil + var randomGen *random.Random if err == nil { - randomGen = rand.New(rand.NewSource(benchmarkSeed)) + randomGen = random.NewSeeded(random.MakeSeed(uint64(benchmarkSeed))) } fastNetworkDelayGenerator := tn.InternetLatencyDelayGenerator( @@ -249,9 +249,9 @@ 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 + var randomGen *random.Random if err == nil { - randomGen = rand.New(rand.NewSource(benchmarkSeed)) + randomGen = random.NewSeeded(random.MakeSeed(uint64(benchmarkSeed))) } datacenterNetworkDelayGenerator := tn.InternetLatencyDelayGenerator( @@ -272,9 +272,9 @@ 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 + var randomGen *random.Random if err == nil { - randomGen = rand.New(rand.NewSource(benchmarkSeed)) + randomGen = random.NewSeeded(random.MakeSeed(uint64(benchmarkSeed))) } datacenterNetworkDelayGenerator := tn.InternetLatencyDelayGenerator( @@ -292,6 +292,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 +302,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 +313,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 +329,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 +337,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 +493,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 bde71676a..c261bdbee 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 5c46c77c0..1279f1276 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 1ee412189..99f883804 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 d369520d0..822ecdf14 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 941f6c0ed..0f2e32e1a 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 02c78a019..bfe8a8bb2 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 ae7b2733f..7ed559ac5 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 5a8075518..5018d5dd9 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 b3d5d3704..c4498d963 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 242630273..94cb235af 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 c58eb22f7..433d3d7ef 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 ebecb9f29..a9300ab42 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 418f3eb7b..4a4bf390b 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 4ad758130..12827831f 100644 --- a/bitswap/testnet/internet_latency_delay_generator.go +++ b/bitswap/testnet/internet_latency_delay_generator.go @@ -1,13 +1,13 @@ 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())) +var sharedRNG = random.New() // InternetLatencyDelayGenerator generates three clusters of delays, // typical of the type of peers you would encounter on the interenet. @@ -27,7 +27,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 +49,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 +57,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 1361f288a..d50f7d940 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.MakeSeed(testSeed))) buckets["fast"] = 0 buckets["medium"] = 0 diff --git a/bitswap/testnet/rate_limit_generators.go b/bitswap/testnet/rate_limit_generators.go index 2c4a1cd56..e03f03eca 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 297d32f13..85f494fc1 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 5a2e6dab7..9b7ed0b9b 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 e37a82359..535ccf753 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.MakeSeed(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.MakeSeed(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 a9ede266c..3600ded7a 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 d5fd8c53d..5a2eef05e 100644 --- a/chunker/gen/main.go +++ b/chunker/gen/main.go @@ -3,13 +3,13 @@ package main import ( "fmt" - "math/rand" + "math/rand/v2" ) const nRounds = 200 func main() { - rnd := rand.New(rand.NewSource(0)) + rnd := rand.New(rand.NewChaCha8([32]byte{})) lut := make([]uint32, 256) for i := range 256 / 2 { diff --git a/chunker/rabin_test.go b/chunker/rabin_test.go index 98939d36d..9f0c317f0 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 b6746b0a9..de325367f 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 f3e80d5e0..06d232454 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 729668dda..a9f1f508d 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.3.1-0.20260709153022-f4de4addda9d h1:xcVKB+9plrms4phJ7VSZw7w9QVgDuqaM00TeaAtcDRo= +github.com/ipfs/go-test v0.3.1-0.20260709153022-f4de4addda9d/go.mod h1:JK+U8pRpATZb7lsYNSJlCj3WYB3cFfWIbI6nWRM/GFk= 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 cc344a0f0..ded2eed92 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 3333fab80..b8908e9eb 100644 --- a/gateway/backend_car_fetcher.go +++ b/gateway/backend_car_fetcher.go @@ -2,15 +2,15 @@ package gateway import ( "context" + crand "crypto/rand" "errors" "fmt" "io" - "math/rand" + "math/rand/v2" "net/http" "net/url" "strconv" "strings" - "time" "github.com/ipfs/boxo/path" ) @@ -43,10 +43,13 @@ func NewRemoteCarFetcher(gatewayURL []string, httpClient *http.Client) (CarFetch httpClient = newRemoteHTTPClient() } + var seed [32]byte + _, _ = crand.Read(seed[:]) + return &remoteCarFetcher{ gatewayURL: gatewayURL, httpClient: httpClient, - rand: rand.New(rand.NewSource(time.Now().Unix())), + rand: rand.New(rand.NewChaCha8(seed)), }, nil } @@ -81,7 +84,7 @@ func (ps *remoteCarFetcher) Fetch(ctx context.Context, path path.ImmutablePath, } func (ps *remoteCarFetcher) getRandomGatewayURL() string { - return ps.gatewayURL[ps.rand.Intn(len(ps.gatewayURL))] + return ps.gatewayURL[ps.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 6e7493ab1..ac64db56d 100644 --- a/gateway/blockstore.go +++ b/gateway/blockstore.go @@ -2,13 +2,13 @@ package gateway import ( "context" + crand "crypto/rand" "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" @@ -159,10 +159,13 @@ func NewRemoteBlockstore(gatewayURL []string, httpClient *http.Client) (blocksto httpClient = newRemoteHTTPClient() } + var seed [32]byte + _, _ = crand.Read(seed[:]) + return &remoteBlockstore{ gatewayURL: gatewayURL, httpClient: httpClient, - rand: rand.New(rand.NewSource(time.Now().Unix())), + rand: rand.New(rand.NewChaCha8(seed)), // Enables block validation by default. Important since we are // proxying block requests to untrusted gateways. validate: true, @@ -250,5 +253,5 @@ func (c *remoteBlockstore) DeleteBlock(context.Context, cid.Cid) error { } func (ps *remoteBlockstore) getRandomGatewayURL() string { - return ps.gatewayURL[ps.rand.Intn(len(ps.gatewayURL))] + return ps.gatewayURL[ps.rand.IntN(len(ps.gatewayURL))] } diff --git a/gateway/value_store.go b/gateway/value_store.go index ead5a44e7..e800cbbda 100644 --- a/gateway/value_store.go +++ b/gateway/value_store.go @@ -2,13 +2,13 @@ package gateway import ( "context" + crand "crypto/rand" "errors" "fmt" "io" - "math/rand" + "math/rand/v2" "net/http" "strings" - "time" "github.com/ipfs/boxo/ipns" "github.com/libp2p/go-libp2p/core/routing" @@ -34,10 +34,13 @@ func NewRemoteValueStore(gatewayURL []string, httpClient *http.Client) (routing. httpClient = newRemoteHTTPClient() } + var seed [32]byte + _, _ = crand.Read(seed[:]) + return &remoteValueStore{ gatewayURL: gatewayURL, httpClient: httpClient, - rand: rand.New(rand.NewSource(time.Now().Unix())), + rand: rand.New(rand.NewChaCha8(seed)), }, nil } @@ -119,5 +122,5 @@ 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))] + return ps.gatewayURL[ps.rand.IntN(len(ps.gatewayURL))] } diff --git a/go.mod b/go.mod index 58b8b1769..eeab0fa44 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.3.1-0.20260709153022-f4de4addda9d 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 0df98d4a9..05431f51a 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.3.1-0.20260709153022-f4de4addda9d h1:xcVKB+9plrms4phJ7VSZw7w9QVgDuqaM00TeaAtcDRo= +github.com/ipfs/go-test v0.3.1-0.20260709153022-f4de4addda9d/go.mod h1:JK+U8pRpATZb7lsYNSJlCj3WYB3cFfWIbI6nWRM/GFk= 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 04e43b055..c05f95778 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 3ede0e7a2..f73b34d37 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 f877b7714..9a0116618 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 439875071..f6b61f815 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 b14d67862..eb74e844d 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 f9311db94..4d6b91a2e 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 3245980d2..00e9497fb 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 38e24dba8..23b7e72a6 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 a288616ee..7062d3728 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 8f0f03b70..eb27082f6 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 6e4cbf1f5..f9b18be77 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 77d313958..f20b540a2 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 2deff46c3..3763c1b84 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 85c768814..f36ff44a8 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/util/file_test.go b/util/file_test.go index 040b22927..a2374461b 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 b5a98caa6..8b27e416d 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_test.go b/util/util_test.go index b3733ec45..52ddc22fa 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 } From 8e07a7b71383d9b133a2933f1e680d9a52cf4f1b Mon Sep 17 00:00:00 2001 From: gammazero <11790789+gammazero@users.noreply.github.com> Date: Thu, 9 Jul 2026 06:06:45 -1000 Subject: [PATCH 03/11] update go-test --- examples/go.sum | 4 ++-- go.mod | 2 +- go.sum | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/examples/go.sum b/examples/go.sum index a9f1f508d..be2ac094f 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.1-0.20260709153022-f4de4addda9d h1:xcVKB+9plrms4phJ7VSZw7w9QVgDuqaM00TeaAtcDRo= -github.com/ipfs/go-test v0.3.1-0.20260709153022-f4de4addda9d/go.mod h1:JK+U8pRpATZb7lsYNSJlCj3WYB3cFfWIbI6nWRM/GFk= +github.com/ipfs/go-test v0.3.1-0.20260709160526-27b54c53fe50 h1:cpWm5BZTPXaxXkmOzRLtP4gjVJeTwssNe2+9tYG2uO0= +github.com/ipfs/go-test v0.3.1-0.20260709160526-27b54c53fe50/go.mod h1:JK+U8pRpATZb7lsYNSJlCj3WYB3cFfWIbI6nWRM/GFk= 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/go.mod b/go.mod index eeab0fa44..b8a2bca64 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.1-0.20260709153022-f4de4addda9d + github.com/ipfs/go-test v0.3.1-0.20260709160526-27b54c53fe50 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 05431f51a..6e515010d 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.1-0.20260709153022-f4de4addda9d h1:xcVKB+9plrms4phJ7VSZw7w9QVgDuqaM00TeaAtcDRo= -github.com/ipfs/go-test v0.3.1-0.20260709153022-f4de4addda9d/go.mod h1:JK+U8pRpATZb7lsYNSJlCj3WYB3cFfWIbI6nWRM/GFk= +github.com/ipfs/go-test v0.3.1-0.20260709160526-27b54c53fe50 h1:cpWm5BZTPXaxXkmOzRLtP4gjVJeTwssNe2+9tYG2uO0= +github.com/ipfs/go-test v0.3.1-0.20260709160526-27b54c53fe50/go.mod h1:JK+U8pRpATZb7lsYNSJlCj3WYB3cFfWIbI6nWRM/GFk= 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= From 03dfabdd429f2bc40452854916aba72b0ee06657 Mon Sep 17 00:00:00 2001 From: gammazero <11790789+gammazero@users.noreply.github.com> Date: Sun, 12 Jul 2026 19:19:39 -1000 Subject: [PATCH 04/11] update go-test --- bitswap/benchmarks_test.go | 19 +++++++++---------- .../internet_latency_delay_generator_test.go | 2 +- chunker/benchmark_test.go | 4 ++-- examples/go.sum | 4 ++-- go.mod | 2 +- go.sum | 4 ++-- 6 files changed, 17 insertions(+), 18 deletions(-) diff --git a/bitswap/benchmarks_test.go b/bitswap/benchmarks_test.go index 3298cef14..304cb333e 100644 --- a/bitswap/benchmarks_test.go +++ b/bitswap/benchmarks_test.go @@ -6,7 +6,6 @@ import ( "fmt" "math" "os" - "strconv" "sync" "testing" "time" @@ -209,10 +208,10 @@ const ( func BenchmarkRealWorld(b *testing.B) { benchmarkLog = nil - benchmarkSeed, err := strconv.ParseInt(os.Getenv("BENCHMARK_SEED"), 10, 64) var randomGen *random.Random - if err == nil { - randomGen = random.NewSeeded(random.MakeSeed(uint64(benchmarkSeed))) + 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 *random.Random - if err == nil { - randomGen = random.NewSeeded(random.MakeSeed(uint64(benchmarkSeed))) + 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 *random.Random - if err == nil { - randomGen = random.NewSeeded(random.MakeSeed(uint64(benchmarkSeed))) + seed := os.Getenv("BENCHMARK_SEED") + if seed != "" { + randomGen = random.NewSeeded(random.StringToSeed(seed)) } datacenterNetworkDelayGenerator := tn.InternetLatencyDelayGenerator( diff --git a/bitswap/testnet/internet_latency_delay_generator_test.go b/bitswap/testnet/internet_latency_delay_generator_test.go index d50f7d940..d0368ce8d 100644 --- a/bitswap/testnet/internet_latency_delay_generator_test.go +++ b/bitswap/testnet/internet_latency_delay_generator_test.go @@ -24,7 +24,7 @@ func TestInternetLatencyDelayNextWaitTimeDistribution(t *testing.T) { percentMedium, percentLarge, deviation, - random.NewSeeded(random.MakeSeed(testSeed))) + random.NewSeeded(random.Uint64ToSeed(testSeed))) buckets["fast"] = 0 buckets["medium"] = 0 diff --git a/chunker/benchmark_test.go b/chunker/benchmark_test.go index 535ccf753..ef146f778 100644 --- a/chunker/benchmark_test.go +++ b/chunker/benchmark_test.go @@ -31,7 +31,7 @@ func benchmarkChunker(b *testing.B, ns newSplitter) { } func benchmarkChunkerSize(b *testing.B, ns newSplitter, size int) { - rng := random.NewSeeded(random.MakeSeed(1)) + rng := random.NewSeeded(random.Uint64ToSeed(1)) data := make([]byte, size) rng.Read(data) @@ -66,7 +66,7 @@ func benchmarkFilesAlloc(b *testing.B, ns newSplitter) { fileCount = 10000 ) - rng := random.NewSeeded(random.MakeSeed(1)) + rng := random.NewSeeded(random.Uint64ToSeed(1)) data := make([]byte, maxDataSize) rng.Read(data) diff --git a/examples/go.sum b/examples/go.sum index be2ac094f..c43f41e13 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.1-0.20260709160526-27b54c53fe50 h1:cpWm5BZTPXaxXkmOzRLtP4gjVJeTwssNe2+9tYG2uO0= -github.com/ipfs/go-test v0.3.1-0.20260709160526-27b54c53fe50/go.mod h1:JK+U8pRpATZb7lsYNSJlCj3WYB3cFfWIbI6nWRM/GFk= +github.com/ipfs/go-test v0.3.1-0.20260713001830-e9e6d6b05737 h1:34LJghR980JwiLQHxil4SGO8wDC9omOGikmEMvTbTj8= +github.com/ipfs/go-test v0.3.1-0.20260713001830-e9e6d6b05737/go.mod h1:JK+U8pRpATZb7lsYNSJlCj3WYB3cFfWIbI6nWRM/GFk= 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/go.mod b/go.mod index b8a2bca64..be67aeef8 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.1-0.20260709160526-27b54c53fe50 + github.com/ipfs/go-test v0.3.1-0.20260713001830-e9e6d6b05737 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 6e515010d..7845905d2 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.1-0.20260709160526-27b54c53fe50 h1:cpWm5BZTPXaxXkmOzRLtP4gjVJeTwssNe2+9tYG2uO0= -github.com/ipfs/go-test v0.3.1-0.20260709160526-27b54c53fe50/go.mod h1:JK+U8pRpATZb7lsYNSJlCj3WYB3cFfWIbI6nWRM/GFk= +github.com/ipfs/go-test v0.3.1-0.20260713001830-e9e6d6b05737 h1:34LJghR980JwiLQHxil4SGO8wDC9omOGikmEMvTbTj8= +github.com/ipfs/go-test v0.3.1-0.20260713001830-e9e6d6b05737/go.mod h1:JK+U8pRpATZb7lsYNSJlCj3WYB3cFfWIbI6nWRM/GFk= 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= From a8dacc3bde150f317ec38d4e345ab6385c473b75 Mon Sep 17 00:00:00 2001 From: gammazero <11790789+gammazero@users.noreply.github.com> Date: Mon, 13 Jul 2026 00:04:22 -1000 Subject: [PATCH 05/11] update go-test --- examples/go.sum | 4 ++-- go.mod | 2 +- go.sum | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/examples/go.sum b/examples/go.sum index c43f41e13..3c11b6600 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.1-0.20260713001830-e9e6d6b05737 h1:34LJghR980JwiLQHxil4SGO8wDC9omOGikmEMvTbTj8= -github.com/ipfs/go-test v0.3.1-0.20260713001830-e9e6d6b05737/go.mod h1:JK+U8pRpATZb7lsYNSJlCj3WYB3cFfWIbI6nWRM/GFk= +github.com/ipfs/go-test v0.3.1-0.20260713090104-29b7f73d680f h1:+XCRw77Ql6njoPz4vueYWCT4xOpeKzG40wfoV8L8MIU= +github.com/ipfs/go-test v0.3.1-0.20260713090104-29b7f73d680f/go.mod h1:JK+U8pRpATZb7lsYNSJlCj3WYB3cFfWIbI6nWRM/GFk= 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/go.mod b/go.mod index be67aeef8..fa82c0f02 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.1-0.20260713001830-e9e6d6b05737 + github.com/ipfs/go-test v0.3.1-0.20260713090104-29b7f73d680f 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 7845905d2..baea34dd4 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.1-0.20260713001830-e9e6d6b05737 h1:34LJghR980JwiLQHxil4SGO8wDC9omOGikmEMvTbTj8= -github.com/ipfs/go-test v0.3.1-0.20260713001830-e9e6d6b05737/go.mod h1:JK+U8pRpATZb7lsYNSJlCj3WYB3cFfWIbI6nWRM/GFk= +github.com/ipfs/go-test v0.3.1-0.20260713090104-29b7f73d680f h1:+XCRw77Ql6njoPz4vueYWCT4xOpeKzG40wfoV8L8MIU= +github.com/ipfs/go-test v0.3.1-0.20260713090104-29b7f73d680f/go.mod h1:JK+U8pRpATZb7lsYNSJlCj3WYB3cFfWIbI6nWRM/GFk= 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= From 8672059df6372d36a656fda975cd78fd5c67b2a8 Mon Sep 17 00:00:00 2001 From: gammazero <11790789+gammazero@users.noreply.github.com> Date: Mon, 13 Jul 2026 07:47:51 -1000 Subject: [PATCH 06/11] use tagged version of go-test --- examples/go.sum | 4 ++-- go.mod | 2 +- go.sum | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/examples/go.sum b/examples/go.sum index 3c11b6600..6cb89550f 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.1-0.20260713090104-29b7f73d680f h1:+XCRw77Ql6njoPz4vueYWCT4xOpeKzG40wfoV8L8MIU= -github.com/ipfs/go-test v0.3.1-0.20260713090104-29b7f73d680f/go.mod h1:JK+U8pRpATZb7lsYNSJlCj3WYB3cFfWIbI6nWRM/GFk= +github.com/ipfs/go-test v0.4.0 h1:9tXekF1a80k5mCFZ4+Whc43FTtJJ7WqPz57vXezAg/E= +github.com/ipfs/go-test v0.4.0/go.mod h1:JK+U8pRpATZb7lsYNSJlCj3WYB3cFfWIbI6nWRM/GFk= 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/go.mod b/go.mod index fa82c0f02..b18eef0af 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.1-0.20260713090104-29b7f73d680f + github.com/ipfs/go-test v0.4.0 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 baea34dd4..bc97e61f8 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.1-0.20260713090104-29b7f73d680f h1:+XCRw77Ql6njoPz4vueYWCT4xOpeKzG40wfoV8L8MIU= -github.com/ipfs/go-test v0.3.1-0.20260713090104-29b7f73d680f/go.mod h1:JK+U8pRpATZb7lsYNSJlCj3WYB3cFfWIbI6nWRM/GFk= +github.com/ipfs/go-test v0.4.0 h1:9tXekF1a80k5mCFZ4+Whc43FTtJJ7WqPz57vXezAg/E= +github.com/ipfs/go-test v0.4.0/go.mod h1:JK+U8pRpATZb7lsYNSJlCj3WYB3cFfWIbI6nWRM/GFk= 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= From 693185ab0930a01223f096c4480887869d66fee1 Mon Sep 17 00:00:00 2001 From: gammazero <11790789+gammazero@users.noreply.github.com> Date: Mon, 13 Jul 2026 20:28:03 -1000 Subject: [PATCH 07/11] update chngelog --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e431d1ac2..ee57b62e1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -33,7 +33,7 @@ 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`: use new `go-test` and `math/rand/v2`. The `go-test/random` package now allows reuse of the random number generator for more efficiently generating sets of random values. The package also removes support for a global seed and sequence, which could lead to multiple tests interferring with each other when generatng deterministic values. - 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) From c7a2307404c2ca58542a22333a990894d8d16cd7 Mon Sep 17 00:00:00 2001 From: Marcin Rataj Date: Tue, 14 Jul 2026 19:51:57 +0200 Subject: [PATCH 08/11] fix(chunker): keep gen reproducing the committed table The bytehash table in chunker/buzhash.go was generated with math/rand seeded by NewSource(0). Switching gen to math/rand/v2 made it print a different table, so re-running it and pasting the output would have changed buzhash chunk boundaries, and with them the CID of anything chunked with buzhash. Pin gen back to the old source and say why. --- chunker/gen/main.go | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/chunker/gen/main.go b/chunker/gen/main.go index 5a2eef05e..97191911d 100644 --- a/chunker/gen/main.go +++ b/chunker/gen/main.go @@ -3,13 +3,17 @@ package main import ( "fmt" - "math/rand/v2" + "math/rand" ) const nRounds = 200 func main() { - rnd := rand.New(rand.NewChaCha8([32]byte{})) + // 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) for i := range 256 / 2 { From 3b10577eff17bb4cd3c1bb04f533bd75513d51aa Mon Sep 17 00:00:00 2001 From: Marcin Rataj Date: Tue, 14 Jul 2026 19:52:03 +0200 Subject: [PATCH 09/11] fix(gateway): data race when picking a gateway url The remote blockstore, CAR fetcher, and value store each held their own *rand.Rand and used it to pick a URL on every request. A *rand.Rand cannot be used from more than one goroutine, so a gateway serving requests in parallel was racing. Use the top-level math/rand/v2 functions instead, which are safe to share, and drop the seeding code. --- gateway/backend_car_fetcher.go | 10 +++------- gateway/blockstore.go | 10 +++------- gateway/value_store.go | 10 +++------- 3 files changed, 9 insertions(+), 21 deletions(-) diff --git a/gateway/backend_car_fetcher.go b/gateway/backend_car_fetcher.go index b8908e9eb..56f8e4bda 100644 --- a/gateway/backend_car_fetcher.go +++ b/gateway/backend_car_fetcher.go @@ -2,7 +2,6 @@ package gateway import ( "context" - crand "crypto/rand" "errors" "fmt" "io" @@ -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 @@ -43,13 +41,9 @@ func NewRemoteCarFetcher(gatewayURL []string, httpClient *http.Client) (CarFetch httpClient = newRemoteHTTPClient() } - var seed [32]byte - _, _ = crand.Read(seed[:]) - return &remoteCarFetcher{ gatewayURL: gatewayURL, httpClient: httpClient, - rand: rand.New(rand.NewChaCha8(seed)), }, nil } @@ -84,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 ac64db56d..7cbeefa1c 100644 --- a/gateway/blockstore.go +++ b/gateway/blockstore.go @@ -2,7 +2,6 @@ package gateway import ( "context" - crand "crypto/rand" "errors" "fmt" "io" @@ -140,7 +139,6 @@ func (l *cacheBlockStore) HashOnRead(enabled bool) { type remoteBlockstore struct { httpClient *http.Client gatewayURL []string - rand *rand.Rand validate bool } @@ -159,13 +157,9 @@ func NewRemoteBlockstore(gatewayURL []string, httpClient *http.Client) (blocksto httpClient = newRemoteHTTPClient() } - var seed [32]byte - _, _ = crand.Read(seed[:]) - return &remoteBlockstore{ gatewayURL: gatewayURL, httpClient: httpClient, - rand: rand.New(rand.NewChaCha8(seed)), // Enables block validation by default. Important since we are // proxying block requests to untrusted gateways. validate: true, @@ -253,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 e800cbbda..9e6ad3cce 100644 --- a/gateway/value_store.go +++ b/gateway/value_store.go @@ -2,7 +2,6 @@ package gateway import ( "context" - crand "crypto/rand" "errors" "fmt" "io" @@ -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 @@ -34,13 +32,9 @@ func NewRemoteValueStore(gatewayURL []string, httpClient *http.Client) (routing. httpClient = newRemoteHTTPClient() } - var seed [32]byte - _, _ = crand.Read(seed[:]) - return &remoteValueStore{ gatewayURL: gatewayURL, httpClient: httpClient, - rand: rand.New(rand.NewChaCha8(seed)), }, nil } @@ -122,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))] } From 5ecaf9b4bcdad5332e68b4c04e900cea89c22549 Mon Sep 17 00:00:00 2001 From: Marcin Rataj Date: Tue, 14 Jul 2026 19:52:09 +0200 Subject: [PATCH 10/11] docs: changelog entries and a concurrency note Record the removal of util.NewSeededRand and NewTimeSeededRand, which were exported, and the gateway race fix. Fix two typos in the go-test entry and say what dropping the global seed is good for. Note on sharedRNG that a random.Random cannot be shared between goroutines. --- CHANGELOG.md | 5 ++++- bitswap/testnet/internet_latency_delay_generator.go | 4 ++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ee57b62e1..f02d77f3d 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`: use new `go-test` and `math/rand/v2`. The `go-test/random` package now allows reuse of the random number generator for more efficiently generating sets of random values. The package also removes support for a global seed and sequence, which could lead to multiple tests interferring with each other when generatng deterministic values. +- ๐Ÿงช `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/bitswap/testnet/internet_latency_delay_generator.go b/bitswap/testnet/internet_latency_delay_generator.go index 12827831f..f5aceab81 100644 --- a/bitswap/testnet/internet_latency_delay_generator.go +++ b/bitswap/testnet/internet_latency_delay_generator.go @@ -7,6 +7,10 @@ import ( "github.com/ipfs/go-test/random" ) +// 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, From d9933c4e54d212fb149de0602dfc5badc920a139 Mon Sep 17 00:00:00 2001 From: gammazero <11790789+gammazero@users.noreply.github.com> Date: Thu, 16 Jul 2026 19:00:39 -1000 Subject: [PATCH 11/11] use latest go-test --- examples/go.sum | 4 ++-- go.mod | 2 +- go.sum | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/examples/go.sum b/examples/go.sum index 6cb89550f..1689769b0 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.4.0 h1:9tXekF1a80k5mCFZ4+Whc43FTtJJ7WqPz57vXezAg/E= -github.com/ipfs/go-test v0.4.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/go.mod b/go.mod index b18eef0af..ca4eb7b13 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.4.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 bc97e61f8..14e1e16c0 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.4.0 h1:9tXekF1a80k5mCFZ4+Whc43FTtJJ7WqPz57vXezAg/E= -github.com/ipfs/go-test v0.4.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=