@cryptotaxi247 / kubo / commits / ad5a0fea0

test: port legacy DHT tests to Go

Gus Eggert committed Mar 8, 2023 at 15:48 UTC ad5a0fea0e4627e66902c5ae5690892b67bf8d23
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