test: port legacy DHT tests to Go
Gus Eggert committed
Mar 8, 2023 at 15:48 UTC
bfa425fc67b5a6125412cd2453d6fa7f83a4bc96
6 files changed
+192
-136
test/cli/dht_legacy_test.go
new
+137
@@ -0,0 +1,137 @@
1
+package cli
2
+
3
+import (
4
+ "sort"
5
+ "sync"
6
+ "testing"
7
+
8
+ "github.com/ipfs/kubo/test/cli/harness"
9
+ "github.com/ipfs/kubo/test/cli/testutils"
10
+ "github.com/libp2p/go-libp2p/core/peer"
11
+ "github.com/stretchr/testify/assert"
12
+ "github.com/stretchr/testify/require"
13
+)
14
+
15
+func TestLegacyDHT(t *testing.T) {
16
+ nodes := harness.NewT(t).NewNodes(5).Init()
17
+ nodes.ForEachPar(func(node *harness.Node) {
18
+ node.IPFS("config", "Routing.Type", "dht")
19
+ })
20
+ nodes.StartDaemons().Connect()
21
+
22
+ t.Run("ipfs dht findpeer", func(t *testing.T) {
23
+ t.Parallel()
24
+ res := nodes[1].RunIPFS("dht", "findpeer", nodes[0].PeerID().String())
25
+ assert.Equal(t, 0, res.ExitCode())
26
+
27
+ swarmAddr := nodes[0].SwarmAddrsWithoutPeerIDs()[0]
28
+ require.Equal(t, swarmAddr.String(), res.Stdout.Trimmed())
29
+ })
30
+
31
+ t.Run("ipfs dht get <key>", func(t *testing.T) {
32
+ t.Parallel()
33
+ hash := nodes[2].IPFSAddStr("hello world")
34
+ nodes[2].IPFS("name", "publish", "/ipfs/"+hash)
35
+
36
+ res := nodes[1].IPFS("dht", "get", "/ipns/"+nodes[2].PeerID().String())
37
+ assert.Contains(t, res.Stdout.String(), "/ipfs/"+hash)
38
+
39
+ t.Run("put round trips (#3124)", func(t *testing.T) {
40
+ t.Parallel()
41
+ nodes[0].WriteBytes("get_result", res.Stdout.Bytes())
42
+ res := nodes[0].IPFS("dht", "put", "/ipns/"+nodes[2].PeerID().String(), "get_result")
43
+ assert.Greater(t, len(res.Stdout.Lines()), 0, "should put to at least one node")
44
+ })
45
+
46
+ t.Run("put with bad keys fails (issue #5113, #4611)", func(t *testing.T) {
47
+ t.Parallel()
48
+ keys := []string{"foo", "/pk/foo", "/ipns/foo"}
49
+ for _, key := range keys {
50
+ key := key
51
+ t.Run(key, func(t *testing.T) {
52
+ t.Parallel()
53
+ res := nodes[0].RunIPFS("dht", "put", key)
54
+ assert.Equal(t, 1, res.ExitCode())
55
+ assert.Contains(t, res.Stderr.String(), "invalid")
56
+ assert.Empty(t, res.Stdout.String())
57
+ })
58
+ }
59
+ })
60
+
61
+ t.Run("get with bad keys (issue #4611)", func(t *testing.T) {
62
+ for _, key := range []string{"foo", "/pk/foo"} {
63
+ key := key
64
+ t.Run(key, func(t *testing.T) {
65
+ t.Parallel()
66
+ res := nodes[0].RunIPFS("dht", "get", key)
67
+ assert.Equal(t, 1, res.ExitCode())
68
+ assert.Contains(t, res.Stderr.String(), "invalid")
69
+ assert.Empty(t, res.Stdout.String())
70
+ })
71
+ }
72
+ })
73
+ })
74
+
75
+ t.Run("ipfs dht findprovs", func(t *testing.T) {
76
+ t.Parallel()
77
+ hash := nodes[3].IPFSAddStr("some stuff")
78
+ res := nodes[4].IPFS("dht", "findprovs", hash)
79
+ assert.Equal(t, nodes[3].PeerID().String(), res.Stdout.Trimmed())
80
+ })
81
+
82
+ t.Run("ipfs dht query <peerID>", func(t *testing.T) {
83
+ t.Parallel()
84
+ t.Run("normal DHT configuration", func(t *testing.T) {
85
+ t.Parallel()
86
+ hash := nodes[0].IPFSAddStr("some other stuff")
87
+ peerCounts := map[string]int{}
88
+ peerCountsMut := sync.Mutex{}
89
+ harness.Nodes(nodes).ForEachPar(func(node *harness.Node) {
90
+ res := node.IPFS("dht", "query", hash)
91
+ closestPeer := res.Stdout.Lines()[0]
92
+ // check that it's a valid peer ID
93
+ _, err := peer.Decode(closestPeer)
94
+ require.NoError(t, err)
95
+
96
+ peerCountsMut.Lock()
97
+ peerCounts[closestPeer]++
98
+ peerCountsMut.Unlock()
99
+ })
100
+ // 4 nodes should see the same peer ID
101
+ // 1 node (the closest) should see a different one
102
+ var counts []int
103
+ for _, count := range peerCounts {
104
+ counts = append(counts, count)
105
+ }
106
+ sort.IntSlice(counts).Sort()
107
+ assert.Equal(t, []int{1, 4}, counts)
108
+ })
109
+
110
+ })
111
+
112
+ t.Run("dht commands fail when offline", func(t *testing.T) {
113
+ t.Parallel()
114
+ node := harness.NewT(t).NewNode().Init()
115
+
116
+ // these cannot be run in parallel due to repo locking (seems like a bug)
117
+
118
+ t.Run("dht findprovs", func(t *testing.T) {
119
+ res := node.RunIPFS("dht", "findprovs", testutils.CIDEmptyDir)
120
+ assert.Equal(t, 1, res.ExitCode())
121
+ assert.Contains(t, res.Stderr.String(), "this command must be run in online mode")
122
+ })
123
+
124
+ t.Run("dht findpeer", func(t *testing.T) {
125
+ res := node.RunIPFS("dht", "findpeer", testutils.CIDEmptyDir)
126
+ assert.Equal(t, 1, res.ExitCode())
127
+ assert.Contains(t, res.Stderr.String(), "this command must be run in online mode")
128
+ })
129
+
130
+ t.Run("dht put", func(t *testing.T) {
131
+ node.WriteBytes("foo", []byte("foo"))
132
+ res := node.RunIPFS("dht", "put", "/ipns/"+node.PeerID().String(), "foo")
133
+ assert.Equal(t, 1, res.ExitCode())
134
+ assert.Contains(t, res.Stderr.String(), "this action must be run in online mode")
135
+ })
136
+ })
137
+}
test/cli/harness/harness.go
+1
-1
@@ -171,7 +171,7 @@ func (h *Harness) Mkdirs(paths ...string) {
171
}
172
}
173
174
-func (h *Harness) Sh(expr string) RunResult {
174
+func (h *Harness) Sh(expr string) *RunResult {
175
return h.Runner.Run(RunRequest{
176
Path: "bash",
177
Args: []string{"-c", expr},
test/cli/harness/node.go
+34
-10
@@ -129,23 +129,23 @@ func (n *Node) UpdateConfigAndUserSuppliedResourceManagerOverrides(f func(cfg *c
129
n.WriteUserSuppliedResourceOverrides(overrides)
130
}
131
132
-func (n *Node) IPFS(args ...string) RunResult {
132
+func (n *Node) IPFS(args ...string) *RunResult {
133
res := n.RunIPFS(args...)
134
n.Runner.AssertNoError(res)
135
return res
136
}
137
138
-func (n *Node) PipeStrToIPFS(s string, args ...string) RunResult {
138
+func (n *Node) PipeStrToIPFS(s string, args ...string) *RunResult {
139
return n.PipeToIPFS(strings.NewReader(s), args...)
140
}
141
142
-func (n *Node) PipeToIPFS(reader io.Reader, args ...string) RunResult {
142
+func (n *Node) PipeToIPFS(reader io.Reader, args ...string) *RunResult {
143
res := n.RunPipeToIPFS(reader, args...)
144
n.Runner.AssertNoError(res)
145
return res
146
}
147
148
-func (n *Node) RunPipeToIPFS(reader io.Reader, args ...string) RunResult {
148
+func (n *Node) RunPipeToIPFS(reader io.Reader, args ...string) *RunResult {
149
return n.Runner.Run(RunRequest{
150
Path: n.IPFSBin,
151
Args: args,
@@ -153,7 +153,7 @@ func (n *Node) RunPipeToIPFS(reader io.Reader, args ...string) RunResult {
153
})
154
}
155
156
-func (n *Node) RunIPFS(args ...string) RunResult {
156
+func (n *Node) RunIPFS(args ...string) *RunResult {
157
return n.Runner.Run(RunRequest{
158
Path: n.IPFSBin,
159
Args: args,
@@ -216,7 +216,7 @@ func (n *Node) StartDaemon(ipfsArgs ...string) *Node {
216
RunFunc: (*exec.Cmd).Start,
217
})
218
219
- n.Daemon = &res
219
+ n.Daemon = res
220
221
log.Debugf("node %d started, checking API", n.ID)
222
n.WaitOnAPI()
@@ -399,8 +399,6 @@ func (n *Node) SwarmAddrs() []multiaddr.Multiaddr {
399
Path: n.IPFSBin,
400
Args: []string{"swarm", "addrs", "local"},
401
})
402
- ipfsProtocol := multiaddr.ProtocolWithCode(multiaddr.P_IPFS).Name
403
- peerID := n.PeerID()
402
out := strings.TrimSpace(res.Stdout.String())
403
outLines := strings.Split(out, "\n")
404
var addrs []multiaddr.Multiaddr
@@ -409,9 +407,18 @@ func (n *Node) SwarmAddrs() []multiaddr.Multiaddr {
407
if err != nil {
408
panic(err)
409
}
410
+ addrs = append(addrs, ma)
411
+ }
412
+ return addrs
413
+}
414
415
+func (n *Node) SwarmAddrsWithPeerIDs() []multiaddr.Multiaddr {
416
+ ipfsProtocol := multiaddr.ProtocolWithCode(multiaddr.P_IPFS).Name
417
+ peerID := n.PeerID()
418
+ var addrs []multiaddr.Multiaddr
419
+ for _, ma := range n.SwarmAddrs() {
420
// add the peer ID to the multiaddr if it doesn't have it
414
- _, err = ma.ValueForProtocol(multiaddr.P_IPFS)
421
+ _, err := ma.ValueForProtocol(multiaddr.P_IPFS)
422
if errors.Is(err, multiaddr.ErrProtocolNotFound) {
423
comp, err := multiaddr.NewComponent(ipfsProtocol, peerID.String())
424
if err != nil {
@@ -424,10 +431,27 @@ func (n *Node) SwarmAddrs() []multiaddr.Multiaddr {
431
return addrs
432
}
433
434
+func (n *Node) SwarmAddrsWithoutPeerIDs() []multiaddr.Multiaddr {
435
+ var addrs []multiaddr.Multiaddr
436
+ for _, ma := range n.SwarmAddrs() {
437
+ var components []multiaddr.Multiaddr
438
+ multiaddr.ForEach(ma, func(c multiaddr.Component) bool {
439
+ if c.Protocol().Code == multiaddr.P_IPFS {
440
+ return true
441
+ }
442
+ components = append(components, &c)
443
+ return true
444
+ })
445
+ ma = multiaddr.Join(components...)
446
+ addrs = append(addrs, ma)
447
+ }
448
+ return addrs
449
+}
450
+
451
func (n *Node) Connect(other *Node) *Node {
452
n.Runner.MustRun(RunRequest{
453
Path: n.IPFSBin,
430
- Args: []string{"swarm", "connect", other.SwarmAddrs()[0].String()},
454
+ Args: []string{"swarm", "connect", other.SwarmAddrsWithPeerIDs()[0].String()},
455
})
456
return n
457
}
test/cli/harness/nodes.go
+16
@@ -4,6 +4,7 @@ import (
4
"sync"
5
6
"github.com/multiformats/go-multiaddr"
7
+ "golang.org/x/sync/errgroup"
8
)
9
10
// Nodes is a collection of Kubo nodes along with operations on groups of nodes.
@@ -16,6 +17,21 @@ func (n Nodes) Init(args ...string) Nodes {
17
return n
18
}
19
20
+func (n Nodes) ForEachPar(f func(*Node)) {
21
+ group := &errgroup.Group{}
22
+ for _, node := range n {
23
+ node := node
24
+ group.Go(func() error {
25
+ f(node)
26
+ return nil
27
+ })
28
+ }
29
+ err := group.Wait()
30
+ if err != nil {
31
+ panic(err)
32
+ }
33
+}
34
+
35
func (n Nodes) Connect() Nodes {
36
wg := sync.WaitGroup{}
37
for i, node := range n {
test/cli/harness/run.go
+4
-4
@@ -51,7 +51,7 @@ func environToMap(environ []string) map[string]string {
51
return m
52
}
53
54
-func (r *Runner) Run(req RunRequest) RunResult {
54
+func (r *Runner) Run(req RunRequest) *RunResult {
55
cmd := exec.Command(req.Path, req.Args...)
56
stdout := &Buffer{}
57
stderr := &Buffer{}
@@ -86,17 +86,17 @@ func (r *Runner) Run(req RunRequest) RunResult {
86
result.ExitErr = exitErr
87
}
88
89
- return result
89
+ return &result
90
}
91
92
// MustRun runs the command and fails the test if the command fails.
93
-func (r *Runner) MustRun(req RunRequest) RunResult {
93
+func (r *Runner) MustRun(req RunRequest) *RunResult {
94
result := r.Run(req)
95
r.AssertNoError(result)
96
return result
97
}
98
99
-func (r *Runner) AssertNoError(result RunResult) {
99
+func (r *Runner) AssertNoError(result *RunResult) {
100
if result.ExitErr != nil {
101
log.Panicf("'%s' returned error, code: %d, err: %s\nstdout:%s\nstderr:%s\n",
102
result.Cmd.Args, result.ExitErr.ExitCode(), result.ExitErr.Error(), result.Stdout.String(), result.Stderr.String())
test/sharness/t0170-legacy-dht.sh
deleted
-121
@@ -1,121 +0,0 @@
1
-#!/usr/bin/env bash
2
-
3
-# Legacy / deprecated, see: t0170-routing-dht.sh
4
-test_description="Test dht command"
5
-
6
-. lib/test-lib.sh
7
-
8
-test_dht() {
9
- NUM_NODES=5
10
-
11
- test_expect_success 'init iptb' '
12
- rm -rf .iptb/ &&
13
- iptb testbed create -type localipfs -count $NUM_NODES -init
14
- '
15
-
16
- test_expect_success 'DHT-only routing' '
17
- iptb run -- ipfs config Routing.Type dht
18
- '
19
-
20
- startup_cluster $NUM_NODES $@
21
-
22
- test_expect_success 'peer ids' '
23
- PEERID_0=$(iptb attr get 0 id) &&
24
- PEERID_2=$(iptb attr get 2 id)
25
- '
26
-
27
- # ipfs dht findpeer <peerID>
28
- test_expect_success 'findpeer' '
29
- ipfsi 1 dht findpeer $PEERID_0 | sort >actual &&
30
- ipfsi 0 id -f "<addrs>" | cut -d / -f 1-5 | sort >expected &&
31
- test_cmp actual expected
32
- '
33
-
34
- # ipfs dht get <key>
35
- test_expect_success 'get with good keys works' '
36
- HASH="$(echo "hello world" | ipfsi 2 add -q)" &&
37
- ipfsi 2 name publish "/ipfs/$HASH" &&
38
- ipfsi 1 dht get "/ipns/$PEERID_2" >get_result
39
- '
40
-
41
- test_expect_success 'get with good keys contains the right value' '
42
- cat get_result | grep -aq "/ipfs/$HASH"
43
- '
44
-
45
- test_expect_success 'put round trips (#3124)' '
46
- ipfsi 0 dht put "/ipns/$PEERID_2" get_result | sort >putted &&
47
- [ -s putted ] ||
48
- test_fsh cat putted
49
- '
50
-
51
- test_expect_success 'put with bad keys fails (issue #5113)' '
52
- ipfsi 0 dht put "foo" <<<bar >putted
53
- ipfsi 0 dht put "/pk/foo" <<<bar >>putted
54
- ipfsi 0 dht put "/ipns/foo" <<<bar >>putted
55
- [ ! -s putted ] ||
56
- test_fsh cat putted
57
- '
58
-
59
- test_expect_success 'put with bad keys returns error (issue #4611)' '
60
- test_must_fail ipfsi 0 dht put "foo" <<<bar &&
61
- test_must_fail ipfsi 0 dht put "/pk/foo" <<<bar &&
62
- test_must_fail ipfsi 0 dht put "/ipns/foo" <<<bar
63
- '
64
-
65
- test_expect_success 'get with bad keys (issue #4611)' '
66
- test_must_fail ipfsi 0 dht get "foo" &&
67
- test_must_fail ipfsi 0 dht get "/pk/foo"
68
- '
69
-
70
- test_expect_success "add a ref so we can find providers for it" '
71
- echo "some stuff" > afile &&
72
- HASH=$(ipfsi 3 add -q afile)
73
- '
74
-
75
- # ipfs dht findprovs <key>
76
- test_expect_success 'findprovs' '
77
- ipfsi 4 dht findprovs $HASH > provs &&
78
- iptb attr get 3 id > expected &&
79
- test_cmp provs expected
80
- '
81
-
82
-
83
- # ipfs dht query <peerID>
84
- #
85
- # We test all nodes. 4 nodes should see the same peer ID, one node (the
86
- # closest) should see a different one.
87
-
88
- for i in $(test_seq 0 4); do
89
- test_expect_success "query from $i" '
90
- ipfsi "$i" dht query "$HASH" | head -1 >closest-$i
91
- '
92
- done
93
-
94
- test_expect_success "collecting results" '
95
- cat closest-* | sort | uniq -c | sed -e "s/ *\([0-9]\+\) .*/\1/g" | sort -g > actual &&
96
- echo 1 > expected &&
97
- echo 4 >> expected
98
- '
99
-
100
- test_expect_success "checking results" '
101
- test_cmp actual expected
102
- '
103
-
104
- test_expect_success 'stop iptb' '
105
- iptb stop
106
- '
107
-
108
- test_expect_success "dht commands fail when offline" '
109
- test_must_fail ipfsi 0 dht findprovs "$HASH" 2>err_findprovs &&
110
- test_must_fail ipfsi 0 dht findpeer "$HASH" 2>err_findpeer &&
111
- test_must_fail ipfsi 0 dht put "/ipns/$PEERID_2" "get_result" 2>err_put &&
112
- test_should_contain "this command must be run in online mode" err_findprovs &&
113
- test_should_contain "this command must be run in online mode" err_findpeer &&
114
- test_should_contain "this action must be run in online mode" err_put
115
- '
116
-}
117
-
118
-test_dht
119
-test_dht --enable-pubsub-experiment --enable-namesys-pubsub
120
-
121
-test_done