@cryptotaxi247 / kubo / commits / b8a1aa471

chore: replace random test utils with equivalents in go-test/random (#10915)

Replace test functionality that is dublicated in go-test/random

Andrew Gillis committed Aug 14, 2025 at 10:37 UTC b8a1aa471c806c2b0df0e6f91fdfff15429cfc9e
13 files changed +54 -185
test/cli/bitswap_config_test.go
+2 -2
@@ -6,9 +6,9 @@ import (
6 "time"
7
8 "github.com/ipfs/boxo/bitswap/network/bsnet"
9 + "github.com/ipfs/go-test/random"
10 "github.com/ipfs/kubo/config"
11 "github.com/ipfs/kubo/test/cli/harness"
11 - "github.com/ipfs/kubo/test/cli/testutils"
12 "github.com/stretchr/testify/assert"
13 )
14
@@ -16,7 +16,7 @@ func TestBitswapConfig(t *testing.T) {
16 t.Parallel()
17
18 // Create test data that will be shared between nodes
19 - testData := testutils.RandomBytes(100)
19 + testData := random.Bytes(100)
20
21 t.Run("server enabled (default)", func(t *testing.T) {
22 t.Parallel()
test/cli/content_routing_http_test.go
+2 -2
@@ -8,9 +8,9 @@ import (
8 "time"
9
10 "github.com/ipfs/boxo/routing/http/server"
11 + "github.com/ipfs/go-test/random"
12 "github.com/ipfs/kubo/config"
13 "github.com/ipfs/kubo/test/cli/harness"
13 - "github.com/ipfs/kubo/test/cli/testutils"
14 "github.com/ipfs/kubo/test/cli/testutils/httprouting"
15 "github.com/stretchr/testify/assert"
16 )
@@ -43,7 +43,7 @@ func TestContentRoutingHTTP(t *testing.T) {
43 node.StartDaemon()
44
45 // compute a random CID
46 - randStr := string(testutils.RandomBytes(100))
46 + randStr := string(random.Bytes(100))
47 res := node.PipeStrToIPFS(randStr, "add", "-qn")
48 wantCIDStr := res.Stdout.Trimmed()
49
test/cli/delegated_routing_v1_http_proxy_test.go
+5 -5
@@ -4,9 +4,9 @@ import (
4 "testing"
5
6 "github.com/ipfs/boxo/ipns"
7 + "github.com/ipfs/go-test/random"
8 "github.com/ipfs/kubo/config"
9 "github.com/ipfs/kubo/test/cli/harness"
9 - "github.com/ipfs/kubo/test/cli/testutils"
10 "github.com/stretchr/testify/assert"
11 "github.com/stretchr/testify/require"
12 )
@@ -70,7 +70,7 @@ func TestRoutingV1Proxy(t *testing.T) {
70 t.Parallel()
71 nodes := setupNodes(t)
72
73 - cidStr := nodes[0].IPFSAddStr(testutils.RandomStr(1000))
73 + cidStr := nodes[0].IPFSAddStr(string(random.Bytes(1000)))
74 // Reprovide as initialProviderDelay still ongoing
75 res := nodes[0].IPFS("routing", "reprovide")
76 require.NoError(t, res.Err)
@@ -109,7 +109,7 @@ func TestRoutingV1Proxy(t *testing.T) {
109 require.Error(t, res.ExitErr)
110
111 // Publish record on Node 0.
112 - path := "/ipfs/" + nodes[0].IPFSAddStr(testutils.RandomStr(1000))
112 + path := "/ipfs/" + nodes[0].IPFSAddStr(string(random.Bytes(1000)))
113 nodes[0].IPFS("name", "publish", "--allow-offline", path)
114
115 // Get record on Node 1 (no DHT).
@@ -132,7 +132,7 @@ func TestRoutingV1Proxy(t *testing.T) {
132 require.Error(t, res.ExitErr)
133
134 // Publish name.
135 - path := "/ipfs/" + nodes[0].IPFSAddStr(testutils.RandomStr(1000))
135 + path := "/ipfs/" + nodes[0].IPFSAddStr(string(random.Bytes(1000)))
136 nodes[0].IPFS("name", "publish", "--allow-offline", path)
137
138 // Resolve IPNS name
@@ -146,7 +146,7 @@ func TestRoutingV1Proxy(t *testing.T) {
146
147 // Publish something on Node 1 (no DHT).
148 nodeName := "/ipns/" + ipns.NameFromPeer(nodes[1].PeerID()).String()
149 - path := "/ipfs/" + nodes[1].IPFSAddStr(testutils.RandomStr(1000))
149 + path := "/ipfs/" + nodes[1].IPFSAddStr(string(random.Bytes(1000)))
150 nodes[1].IPFS("name", "publish", "--allow-offline", path)
151
152 // Retrieve through Node 0.
test/cli/dht_autoclient_test.go
+3 -3
@@ -4,8 +4,8 @@ import (
4 "bytes"
5 "testing"
6
7 + "github.com/ipfs/go-test/random"
8 "github.com/ipfs/kubo/test/cli/harness"
8 - "github.com/ipfs/kubo/test/cli/testutils"
9 "github.com/stretchr/testify/assert"
10 )
11
@@ -19,7 +19,7 @@ func TestDHTAutoclient(t *testing.T) {
19
20 t.Run("file added on node in client mode is retrievable from node in client mode", func(t *testing.T) {
21 t.Parallel()
22 - randomBytes := testutils.RandomBytes(1000)
22 + randomBytes := random.Bytes(1000)
23 randomBytes = append(randomBytes, '\r')
24 hash := nodes[8].IPFSAdd(bytes.NewReader(randomBytes))
25
@@ -29,7 +29,7 @@ func TestDHTAutoclient(t *testing.T) {
29
30 t.Run("file added on node in server mode is retrievable from all nodes", func(t *testing.T) {
31 t.Parallel()
32 - randomBytes := testutils.RandomBytes(1000)
32 + randomBytes := random.Bytes(1000)
33 hash := nodes[0].IPFSAdd(bytes.NewReader(randomBytes))
34
35 for i := 0; i < 10; i++ {
test/cli/dht_opt_prov_test.go
+2 -2
@@ -3,9 +3,9 @@ package cli
3 import (
4 "testing"
5
6 + "github.com/ipfs/go-test/random"
7 "github.com/ipfs/kubo/config"
8 "github.com/ipfs/kubo/test/cli/harness"
8 - "github.com/ipfs/kubo/test/cli/testutils"
9 "github.com/stretchr/testify/assert"
10 )
11
@@ -21,7 +21,7 @@ func TestDHTOptimisticProvide(t *testing.T) {
21
22 nodes.StartDaemons().Connect()
23
24 - hash := nodes[0].IPFSAddStr(testutils.RandomStr(100))
24 + hash := nodes[0].IPFSAddStr(string(random.Bytes(100)))
25 nodes[0].IPFS("routing", "provide", hash)
26
27 res := nodes[1].IPFS("routing", "findprovs", "--num-providers=1", hash)
test/cli/http_retrieval_client_test.go
+2 -2
@@ -13,9 +13,9 @@ import (
13 "github.com/ipfs/boxo/routing/http/server"
14 "github.com/ipfs/boxo/routing/http/types"
15 "github.com/ipfs/go-cid"
16 + "github.com/ipfs/go-test/random"
17 "github.com/ipfs/kubo/config"
18 "github.com/ipfs/kubo/test/cli/harness"
18 - "github.com/ipfs/kubo/test/cli/testutils"
19 "github.com/ipfs/kubo/test/cli/testutils/httprouting"
20 "github.com/libp2p/go-libp2p/core/peer"
21 "github.com/multiformats/go-multiaddr"
@@ -51,7 +51,7 @@ func TestHTTPRetrievalClient(t *testing.T) {
51 })
52
53 // compute a random CID
54 - randStr := string(testutils.RandomBytes(100))
54 + randStr := string(random.Bytes(100))
55 res := node.PipeStrToIPFS(randStr, "add", "-qn", "--cid-version", "1") // -n means dont add to local repo, just produce CID
56 wantCIDStr := res.Stdout.Trimmed()
57 testCid := cid.MustParse(wantCIDStr)
test/cli/pinning_remote_test.go
+6 -6
@@ -9,8 +9,8 @@ import (
9 "time"
10
11 "github.com/google/uuid"
12 + "github.com/ipfs/go-test/random"
13 "github.com/ipfs/kubo/test/cli/harness"
13 - "github.com/ipfs/kubo/test/cli/testutils"
14 "github.com/ipfs/kubo/test/cli/testutils/pinningservice"
15 "github.com/stretchr/testify/assert"
16 "github.com/stretchr/testify/require"
@@ -350,7 +350,7 @@ func TestRemotePinning(t *testing.T) {
350 pin.Status = "pinned"
351 transitionedCh <- struct{}{}
352 }
353 - hash := node.IPFSAddStr(string(testutils.RandomBytes(1000)))
353 + hash := node.IPFSAddStr(string(random.Bytes(1000)))
354 node.IPFS("pin", "remote", "add", "--background=false", "--service=svc", hash)
355 <-transitionedCh
356 res := node.IPFS("pin", "remote", "ls", "--service=svc", "--cid="+hash, "--enc=json").Stdout.String()
@@ -368,7 +368,7 @@ func TestRemotePinning(t *testing.T) {
368 defer pin.M.Unlock()
369 pin.Status = "pinned"
370 }
371 - hash := node.IPFSAddStr(string(testutils.RandomBytes(1000)))
371 + hash := node.IPFSAddStr(string(random.Bytes(1000)))
372 node.IPFS("pin", "remote", "add", "--service=svc", "--name=force-test-name", hash)
373 node.IPFS("pin", "remote", "add", "--service=svc", "--name=force-test-name", hash)
374
@@ -396,7 +396,7 @@ func TestRemotePinning(t *testing.T) {
396 defer pin.M.Unlock()
397 pin.Status = "pinned"
398 }
399 - hash := node.IPFSAddStr(string(testutils.RandomBytes(1000)))
399 + hash := node.IPFSAddStr(string(random.Bytes(1000)))
400 node.IPFS("pin", "remote", "add", "--service=svc", "--name=force-test-name", hash)
401 node.IPFS("pin", "remote", "add", "--service=svc", "--name=force-test-name", hash)
402
@@ -417,7 +417,7 @@ func TestRemotePinning(t *testing.T) {
417 pin.Status = "pinned"
418 }
419 for i := 0; i < 4; i++ {
420 - hash := node.IPFSAddStr(string(testutils.RandomBytes(1000)))
420 + hash := node.IPFSAddStr(string(random.Bytes(1000)))
421 name := fmt.Sprintf("--name=%d", i)
422 node.IPFS("pin", "remote", "add", "--service=svc", "--name="+name, hash)
423 }
@@ -438,7 +438,7 @@ func TestRemotePinning(t *testing.T) {
438 _, svcURL := runPinningService(t, authToken)
439 node.IPFS("pin", "remote", "service", "add", "svc", svcURL, authToken)
440
441 - hash := node.IPFSAddStr(string(testutils.RandomBytes(1000)))
441 + hash := node.IPFSAddStr(string(random.Bytes(1000)))
442 res := node.IPFS("pin", "remote", "add", "--service=svc", "--background", hash)
443 warningMsg := "WARNING: the local node is offline and remote pinning may fail if there is no other provider for this CID"
444 assert.Contains(t, res.Stdout.String(), warningMsg)
test/cli/pins_test.go
+11 -10
@@ -6,6 +6,7 @@ import (
6 "testing"
7
8 "github.com/ipfs/go-cid"
9 + "github.com/ipfs/go-test/random"
10 "github.com/ipfs/kubo/test/cli/harness"
11 . "github.com/ipfs/kubo/test/cli/testutils"
12 "github.com/stretchr/testify/assert"
@@ -142,7 +143,7 @@ func testPinDAG(t *testing.T, args testPinsArgs) {
143 if args.runDaemon {
144 node.StartDaemon("--offline")
145 }
145 - bytes := RandomBytes(1 << 20) // 1 MiB
146 + bytes := random.Bytes(1 << 20) // 1 MiB
147 tmpFile := h.WriteToTemp(string(bytes))
148 cid := node.IPFS(StrCat("add", args.pinArg, "--pin=false", "-q", tmpFile)...).Stdout.Trimmed()
149
@@ -169,7 +170,7 @@ func testPinProgress(t *testing.T, args testPinsArgs) {
170 node.StartDaemon("--offline")
171 }
172
172 - bytes := RandomBytes(1 << 20) // 1 MiB
173 + bytes := random.Bytes(1 << 20) // 1 MiB
174 tmpFile := h.WriteToTemp(string(bytes))
175 cid := node.IPFS(StrCat("add", args.pinArg, "--pin=false", "-q", tmpFile)...).Stdout.Trimmed()
176
@@ -218,8 +219,8 @@ func TestPins(t *testing.T) {
219 t.Parallel()
220
221 node := harness.NewT(t).NewNode().Init()
221 - cidAStr := node.IPFSAddStr(RandomStr(1000), "--pin=false")
222 - cidBStr := node.IPFSAddStr(RandomStr(1000), "--pin=false")
222 + cidAStr := node.IPFSAddStr(string(random.Bytes(1000)), "--pin=false")
223 + cidBStr := node.IPFSAddStr(string(random.Bytes(1000)), "--pin=false")
224
225 _ = node.IPFS("pin", "add", "--name", "testPin", cidAStr)
226
@@ -246,9 +247,9 @@ func TestPins(t *testing.T) {
247 t.Parallel()
248
249 node := harness.NewT(t).NewNode().Init()
249 - cidAStr := node.IPFSAddStr(RandomStr(1000), "--pin=false")
250 - cidBStr := node.IPFSAddStr(RandomStr(1000), "--pin=false")
251 - cidCStr := node.IPFSAddStr(RandomStr(1000), "--pin=false")
250 + cidAStr := node.IPFSAddStr(string(random.Bytes(1000)), "--pin=false")
251 + cidBStr := node.IPFSAddStr(string(random.Bytes(1000)), "--pin=false")
252 + cidCStr := node.IPFSAddStr(string(random.Bytes(1000)), "--pin=false")
253
254 outA := cidAStr + " recursive testPin"
255 outB := cidBStr + " recursive testPin"
@@ -284,7 +285,7 @@ func TestPins(t *testing.T) {
285 t.Parallel()
286
287 node := harness.NewT(t).NewNode().Init()
287 - cidStr := node.IPFSAddStr(RandomStr(1000), "--pin=false")
288 + cidStr := node.IPFSAddStr(string(random.Bytes(1000)), "--pin=false")
289
290 outBefore := cidStr + " recursive A"
291 outAfter := cidStr + " recursive B"
@@ -305,8 +306,8 @@ func TestPins(t *testing.T) {
306 t.Parallel()
307
308 node := harness.NewT(t).NewNode().Init()
308 - cidAStr := node.IPFSAddStr(RandomStr(1000), "--pin=false")
309 - cidBStr := node.IPFSAddStr(RandomStr(1000), "--pin=false")
309 + cidAStr := node.IPFSAddStr(string(random.Bytes(1000)), "--pin=false")
310 + cidBStr := node.IPFSAddStr(string(random.Bytes(1000)), "--pin=false")
311
312 _ = node.IPFS("pin", "add", "--name", "testPinJson", cidAStr)
313
test/cli/provider_test.go
+8 -8
@@ -6,8 +6,8 @@ import (
6 "testing"
7 "time"
8
9 + "github.com/ipfs/go-test/random"
10 "github.com/ipfs/kubo/test/cli/harness"
10 - "github.com/ipfs/kubo/test/cli/testutils"
11 "github.com/stretchr/testify/assert"
12 "github.com/stretchr/testify/require"
13 )
@@ -75,7 +75,7 @@ func TestProvider(t *testing.T) {
75 })
76 defer nodes.StopDaemons()
77
78 - data := testutils.RandomBytes(256)
78 + data := random.Bytes(256)
79 cid := nodes[0].IPFSBlockPut(bytes.NewReader(data), "--pin=false")
80 expectProviders(t, cid, nodes[0].PeerID().String(), nodes[1:]...)
81 })
@@ -262,7 +262,7 @@ func TestProvider(t *testing.T) {
262 defer nodes.StopDaemons()
263
264 // Add a file to MFS (should be provided)
265 - data := testutils.RandomBytes(1000)
265 + data := random.Bytes(1000)
266 cid := nodes[0].IPFSAdd(bytes.NewReader(data), "-Q")
267
268 // not yet in MFS
@@ -329,8 +329,8 @@ func TestProvider(t *testing.T) {
329 t.Run("Reprovides with 'pinned' strategy", func(t *testing.T) {
330 t.Parallel()
331
332 - foo := testutils.RandomBytes(1000)
333 - bar := testutils.RandomBytes(1000)
332 + foo := random.Bytes(1000)
333 + bar := random.Bytes(1000)
334
335 nodes := initNodesWithoutStart(t, 2, func(n *harness.Node) {
336 n.SetIPFSConfig("Reprovider.Strategy", "pinned")
@@ -364,8 +364,8 @@ func TestProvider(t *testing.T) {
364 t.Run("Reprovides with 'roots' strategy", func(t *testing.T) {
365 t.Parallel()
366
367 - foo := testutils.RandomBytes(1000)
368 - bar := testutils.RandomBytes(1000)
367 + foo := random.Bytes(1000)
368 + bar := random.Bytes(1000)
369
370 nodes := initNodesWithoutStart(t, 2, func(n *harness.Node) {
371 n.SetIPFSConfig("Reprovider.Strategy", "roots")
@@ -396,7 +396,7 @@ func TestProvider(t *testing.T) {
396 t.Run("Reprovides with 'mfs' strategy", func(t *testing.T) {
397 t.Parallel()
398
399 - bar := testutils.RandomBytes(1000)
399 + bar := random.Bytes(1000)
400
401 nodes := initNodesWithoutStart(t, 2, func(n *harness.Node) {
402 n.SetIPFSConfig("Reprovider.Strategy", "mfs")
test/cli/testutils/random.go deleted
-16
@@ -1,16 +0,0 @@
1 -package testutils
2 -
3 -import "crypto/rand"
4 -
5 -func RandomBytes(n int) []byte {
6 - bytes := make([]byte, n)
7 - _, err := rand.Read(bytes)
8 - if err != nil {
9 - panic(err)
10 - }
11 - return bytes
12 -}
13 -
14 -func RandomStr(n int) string {
15 - return string(RandomBytes(n))
16 -}
test/cli/testutils/random_files.go deleted
-123
@@ -1,123 +0,0 @@
1 -package testutils
2 -
3 -import (
4 - "fmt"
5 - "io"
6 - "math/rand"
7 - "os"
8 - "path"
9 - "time"
10 -)
11 -
12 -var (
13 - AlphabetEasy = []rune("abcdefghijklmnopqrstuvwxyz01234567890-_")
14 - AlphabetHard = []rune("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890!@#$%^&*()-_+= ;.,<>'\"[]{}() ")
15 -)
16 -
17 -type RandFiles struct {
18 - Rand *rand.Rand
19 - FileSize int // the size per file.
20 - FilenameSize int
21 - Alphabet []rune // for filenames
22 -
23 - FanoutDepth int // how deep the hierarchy goes
24 - FanoutFiles int // how many files per dir
25 - FanoutDirs int // how many dirs per dir
26 -
27 - RandomSize bool // randomize file sizes
28 - RandomNameSize bool // randomize filename lengths
29 - RandomFanout bool // randomize fanout numbers
30 -}
31 -
32 -func NewRandFiles() *RandFiles {
33 - return &RandFiles{
34 - Rand: rand.New(rand.NewSource(time.Now().UnixNano())),
35 - FileSize: 4096,
36 - FilenameSize: 16,
37 - Alphabet: AlphabetEasy,
38 - FanoutDepth: 2,
39 - FanoutDirs: 5,
40 - FanoutFiles: 10,
41 - RandomSize: true,
42 - RandomNameSize: true,
43 - }
44 -}
45 -
46 -func (r *RandFiles) WriteRandomFiles(root string, depth int) error {
47 - numfiles := r.FanoutFiles
48 - if r.RandomFanout {
49 - numfiles = rand.Intn(r.FanoutFiles) + 1
50 - }
51 -
52 - for i := 0; i < numfiles; i++ {
53 - if err := r.WriteRandomFile(root); err != nil {
54 - return err
55 - }
56 - }
57 -
58 - if depth+1 <= r.FanoutDepth {
59 - numdirs := r.FanoutDirs
60 - if r.RandomFanout {
61 - numdirs = r.Rand.Intn(numdirs) + 1
62 - }
63 -
64 - for i := 0; i < numdirs; i++ {
65 - if err := r.WriteRandomDir(root, depth+1); err != nil {
66 - return err
67 - }
68 - }
69 - }
70 -
71 - return nil
72 -}
73 -
74 -func (r *RandFiles) RandomFilename(length int) string {
75 - b := make([]rune, length)
76 - for i := range b {
77 - b[i] = r.Alphabet[r.Rand.Intn(len(r.Alphabet))]
78 - }
79 - return string(b)
80 -}
81 -
82 -func (r *RandFiles) WriteRandomFile(root string) error {
83 - filesize := int64(r.FileSize)
84 - if r.RandomSize {
85 - filesize = r.Rand.Int63n(filesize) + 1
86 - }
87 -
88 - n := r.FilenameSize
89 - if r.RandomNameSize {
90 - n = rand.Intn(r.FilenameSize-4) + 4
91 - }
92 - name := r.RandomFilename(n)
93 - filepath := path.Join(root, name)
94 - f, err := os.Create(filepath)
95 - if err != nil {
96 - return fmt.Errorf("creating random file: %w", err)
97 - }
98 -
99 - if _, err := io.CopyN(f, r.Rand, filesize); err != nil {
100 - return fmt.Errorf("copying random file: %w", err)
101 - }
102 -
103 - return f.Close()
104 -}
105 -
106 -func (r *RandFiles) WriteRandomDir(root string, depth int) error {
107 - if depth > r.FanoutDepth {
108 - return nil
109 - }
110 -
111 - n := rand.Intn(r.FilenameSize-4) + 4
112 - name := r.RandomFilename(n)
113 - root = path.Join(root, name)
114 - if err := os.MkdirAll(root, 0o755); err != nil {
115 - return fmt.Errorf("creating random dir: %w", err)
116 - }
117 -
118 - err := r.WriteRandomFiles(root, depth)
119 - if err != nil {
120 - return fmt.Errorf("writing random files in random dir: %w", err)
121 - }
122 - return nil
123 -}
test/cli/testutils/strings.go
+5
@@ -13,6 +13,11 @@ import (
13 manet "github.com/multiformats/go-multiaddr/net"
14 )
15
16 +var (
17 + AlphabetEasy = []rune("abcdefghijklmnopqrstuvwxyz01234567890-_")
18 + AlphabetHard = []rune("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890!@#$%^&*()-_+= ;.,<>'\"[]{}() ")
19 +)
20 +
21 // StrCat takes a bunch of strings or string slices
22 // and concats them all together into one string slice.
23 // If an arg is not one of those types, this panics.
test/cli/transports_test.go
+8 -6
@@ -6,9 +6,10 @@ import (
6 "path/filepath"
7 "testing"
8
9 + "github.com/ipfs/go-test/random"
10 + "github.com/ipfs/go-test/random/files"
11 "github.com/ipfs/kubo/config"
12 "github.com/ipfs/kubo/test/cli/harness"
11 - "github.com/ipfs/kubo/test/cli/testutils"
13 "github.com/stretchr/testify/assert"
14 "github.com/stretchr/testify/require"
15 )
@@ -23,7 +24,7 @@ func TestTransports(t *testing.T) {
24 })
25 }
26 checkSingleFile := func(nodes harness.Nodes) {
26 - s := testutils.RandomStr(100)
27 + s := string(random.Bytes(100))
28 hash := nodes[0].IPFSAddStr(s)
29 nodes.ForEachPar(func(n *harness.Node) {
30 val := n.IPFS("cat", hash).Stdout.String()
@@ -33,10 +34,11 @@ func TestTransports(t *testing.T) {
34 checkRandomDir := func(nodes harness.Nodes) {
35 randDir := filepath.Join(nodes[0].Dir, "foobar")
36 require.NoError(t, os.Mkdir(randDir, 0o777))
36 - rf := testutils.NewRandFiles()
37 - rf.FanoutDirs = 3
38 - rf.FanoutFiles = 6
39 - require.NoError(t, rf.WriteRandomFiles(randDir, 4))
37 + rfCfg := files.DefaultConfig()
38 + rfCfg.Dirs = 3
39 + rfCfg.Files = 6
40 + rfCfg.Depth = 4
41 + require.NoError(t, files.Create(rfCfg, randDir))
42
43 hash := nodes[1].IPFS("add", "-r", "-Q", randDir).Stdout.Trimmed()
44 nodes.ForEachPar(func(n *harness.Node) {