test: port rcmgr sharness tests to Go
Gus Eggert committed
Feb 27, 2023 at 17:42 UTC
145795b14815cc2a0b6f1599ca734966b3bcebf6
4 files changed
+394
-284
test/cli/harness/node.go
+13
@@ -1,6 +1,7 @@
1
package harness
2
3
import (
4
+ "bytes"
5
"encoding/json"
6
"errors"
7
"fmt"
@@ -62,6 +63,18 @@ func BuildNode(ipfsBin, baseDir string, id int) *Node {
63
}
64
}
65
66
+func (n *Node) WriteBytes(filename string, b []byte) {
67
+ f, err := os.Create(filepath.Join(n.Dir, filename))
68
+ if err != nil {
69
+ panic(err)
70
+ }
71
+ defer f.Close()
72
+ _, err = io.Copy(f, bytes.NewReader(b))
73
+ if err != nil {
74
+ panic(err)
75
+ }
76
+}
77
+
78
func (n *Node) ReadConfig() *config.Config {
79
cfg, err := serial.Load(filepath.Join(n.Dir, "config"))
80
if err != nil {
test/cli/harness/run.go
+4
@@ -38,6 +38,10 @@ type RunResult struct {
38
Cmd *exec.Cmd
39
}
40
41
+func (r *RunResult) ExitCode() int {
42
+ return r.Cmd.ProcessState.ExitCode()
43
+}
44
+
45
func environToMap(environ []string) map[string]string {
46
m := map[string]string{}
47
for _, e := range environ {
test/cli/rcmgr_test.go
new
+377
@@ -0,0 +1,377 @@
1
+package cli
2
+
3
+import (
4
+ "encoding/json"
5
+ "testing"
6
+
7
+ "github.com/ipfs/kubo/config"
8
+ "github.com/ipfs/kubo/core/node/libp2p"
9
+ "github.com/ipfs/kubo/test/cli/harness"
10
+ rcmgr "github.com/libp2p/go-libp2p/p2p/host/resource-manager"
11
+ "github.com/stretchr/testify/assert"
12
+ "github.com/stretchr/testify/require"
13
+)
14
+
15
+func TestRcmgr(t *testing.T) {
16
+ t.Parallel()
17
+
18
+ t.Run("Resource manager disabled", func(t *testing.T) {
19
+ t.Parallel()
20
+ node := harness.NewT(t).NewNode().Init()
21
+ node.UpdateConfig(func(cfg *config.Config) {
22
+ cfg.Swarm.ResourceMgr.Enabled = config.False
23
+ })
24
+
25
+ node.StartDaemon()
26
+
27
+ t.Run("swarm limit should fail", func(t *testing.T) {
28
+ res := node.RunIPFS("swarm", "limit", "system")
29
+ assert.Equal(t, 1, res.ExitCode())
30
+ assert.Contains(t, res.Stderr.Lines()[0], "missing ResourceMgr")
31
+ })
32
+ t.Run("swarm stats should fail", func(t *testing.T) {
33
+ res := node.RunIPFS("swarm", "stats", "all")
34
+ assert.Equal(t, 1, res.ExitCode())
35
+ assert.Contains(t, res.Stderr.Lines()[0], "missing ResourceMgr")
36
+ })
37
+ })
38
+
39
+ t.Run("Node in offline mode", func(t *testing.T) {
40
+ t.Parallel()
41
+ node := harness.NewT(t).NewNode().Init()
42
+ node.UpdateConfig(func(cfg *config.Config) {
43
+ cfg.Swarm.ResourceMgr.Enabled = config.False
44
+ })
45
+ node.StartDaemon()
46
+
47
+ t.Run("swarm limit should fail", func(t *testing.T) {
48
+ res := node.RunIPFS("swarm", "limit", "system")
49
+ assert.Equal(t, 1, res.ExitCode())
50
+ assert.Contains(t, res.Stderr.Lines()[0], "missing ResourceMgr")
51
+ })
52
+ t.Run("swarm stats should fail", func(t *testing.T) {
53
+ res := node.RunIPFS("swarm", "stats", "all")
54
+ assert.Equal(t, 1, res.ExitCode())
55
+ assert.Contains(t, res.Stderr.Lines()[0], "missing ResourceMgr")
56
+ })
57
+ })
58
+
59
+ t.Run("Very high connmgr highwater", func(t *testing.T) {
60
+ node := harness.NewT(t).NewNode().Init()
61
+ node.UpdateConfig(func(cfg *config.Config) {
62
+ cfg.Swarm.ConnMgr.HighWater = config.NewOptionalInteger(1000)
63
+ })
64
+ node.StartDaemon()
65
+
66
+ res := node.RunIPFS("swarm", "limit", "system", "--enc=json")
67
+ require.Equal(t, 0, res.ExitCode())
68
+ limits := unmarshalLimits(t, res.Stdout.Bytes())
69
+
70
+ assert.GreaterOrEqual(t, limits.ConnsInbound, 2000)
71
+ assert.GreaterOrEqual(t, limits.StreamsInbound, 2000)
72
+ })
73
+
74
+ t.Run("default configuration", func(t *testing.T) {
75
+ t.Parallel()
76
+ node := harness.NewT(t).NewNode().Init()
77
+ node.UpdateConfig(func(cfg *config.Config) {
78
+ cfg.Swarm.ConnMgr.HighWater = config.NewOptionalInteger(1000)
79
+ })
80
+ node.StartDaemon()
81
+
82
+ t.Run("conns and streams are above 800 for default connmgr settings", func(t *testing.T) {
83
+ res := node.RunIPFS("swarm", "limit", "system", "--enc=json")
84
+ require.Equal(t, 0, res.ExitCode())
85
+ limits := unmarshalLimits(t, res.Stdout.Bytes())
86
+
87
+ assert.GreaterOrEqual(t, limits.ConnsInbound, 800)
88
+ assert.GreaterOrEqual(t, limits.StreamsInbound, 800)
89
+ })
90
+
91
+ t.Run("limits|stats should succeed", func(t *testing.T) {
92
+ res := node.RunIPFS("swarm", "limit", "all")
93
+ assert.Equal(t, 0, res.ExitCode())
94
+
95
+ limits := map[string]rcmgr.ResourceLimits{}
96
+ err := json.Unmarshal(res.Stdout.Bytes(), &limits)
97
+ require.NoError(t, err)
98
+
99
+ assert.Greater(t, limits["System"].Memory, int64(0))
100
+ assert.Greater(t, limits["System"].FD, 0)
101
+ assert.Greater(t, limits["System"].Conns, 0)
102
+ assert.Greater(t, limits["System"].ConnsInbound, 0)
103
+ assert.Greater(t, limits["System"].ConnsOutbound, 0)
104
+ assert.Greater(t, limits["System"].Streams, 0)
105
+ assert.Greater(t, limits["System"].StreamsInbound, 0)
106
+ assert.Greater(t, limits["System"].StreamsOutbound, 0)
107
+ assert.Greater(t, limits["Transient"].Memory, int64(0))
108
+ })
109
+
110
+ t.Run("resetting limits should produce the same default limits", func(t *testing.T) {
111
+ resetRes := node.RunIPFS("swarm", "limit", "system", "--reset", "--enc=json")
112
+ require.Equal(t, 0, resetRes.ExitCode())
113
+ limitRes := node.RunIPFS("swarm", "limit", "system", "--enc=json")
114
+ require.Equal(t, 0, limitRes.ExitCode())
115
+
116
+ assert.Equal(t, resetRes.Stdout.Bytes(), limitRes.Stdout.Bytes())
117
+ })
118
+
119
+ t.Run("swarm stats system with filter should fail", func(t *testing.T) {
120
+ res := node.RunIPFS("swarm", "stats", "system", "--min-used-limit-perc=99")
121
+ assert.Equal(t, 1, res.ExitCode())
122
+ assert.Contains(t, res.Stderr.Lines()[0], `Error: "min-used-limit-perc" can only be used when scope is "all"`)
123
+ })
124
+
125
+ t.Run("swarm limit reset on map values should work", func(t *testing.T) {
126
+ resetRes := node.RunIPFS("swarm", "limit", "peer:12D3KooWL7i1T9VSPeF8AgQApbyM51GNKZsYPvNvL347aMDmvNzG", "--reset", "--enc=json")
127
+ require.Equal(t, 0, resetRes.ExitCode())
128
+ limitRes := node.RunIPFS("swarm", "limit", "peer:12D3KooWL7i1T9VSPeF8AgQApbyM51GNKZsYPvNvL347aMDmvNzG", "--enc=json")
129
+ require.Equal(t, 0, limitRes.ExitCode())
130
+
131
+ assert.Equal(t, resetRes.Stdout.Bytes(), limitRes.Stdout.Bytes())
132
+ })
133
+
134
+ t.Run("scope is required using reset flags", func(t *testing.T) {
135
+ res := node.RunIPFS("swarm", "limit", "--reset")
136
+ assert.Equal(t, 1, res.ExitCode())
137
+ assert.Contains(t, res.Stderr.Lines()[0], `Error: argument "scope" is required`)
138
+ })
139
+
140
+ t.Run("swarm stats works", func(t *testing.T) {
141
+ res := node.RunIPFS("swarm", "stats", "all", "--enc=json")
142
+ require.Equal(t, 0, res.ExitCode())
143
+
144
+ stats := libp2p.NetStatOut{}
145
+ err := json.Unmarshal(res.Stdout.Bytes(), &stats)
146
+ require.NoError(t, err)
147
+
148
+ // every scope has the same fields, so we only inspect system
149
+ assert.Equal(t, rcmgr.LimitVal64(0), stats.System.Memory)
150
+ assert.Equal(t, rcmgr.LimitVal(0), stats.System.FD)
151
+ assert.Equal(t, rcmgr.LimitVal(0), stats.System.Conns)
152
+ assert.Equal(t, rcmgr.LimitVal(0), stats.System.ConnsInbound)
153
+ assert.Equal(t, rcmgr.LimitVal(0), stats.System.ConnsOutbound)
154
+ assert.Equal(t, rcmgr.LimitVal(0), stats.System.Streams)
155
+ assert.Equal(t, rcmgr.LimitVal(0), stats.System.StreamsInbound)
156
+ assert.Equal(t, rcmgr.LimitVal(0), stats.System.StreamsOutbound)
157
+ assert.Equal(t, rcmgr.LimitVal64(0), stats.Transient.Memory)
158
+ })
159
+ })
160
+
161
+ t.Run("set system conns limit while daemon is not running", func(t *testing.T) {
162
+ node := harness.NewT(t).NewNode().Init()
163
+ res := node.RunIPFS("config", "--json", "Swarm.ResourceMgr.Limits.System.Conns", "99999")
164
+ require.Equal(t, 0, res.ExitCode())
165
+
166
+ t.Run("set an invalid limit which should result in a failure", func(t *testing.T) {
167
+ res := node.RunIPFS("config", "--json", "Swarm.ResourceMgr.Limits.System.Conns", "asdf")
168
+ assert.Equal(t, 1, res.ExitCode())
169
+ assert.Contains(t, res.Stderr.String(), "failed to unmarshal")
170
+ })
171
+
172
+ node.StartDaemon()
173
+
174
+ t.Run("new system conns limit is applied", func(t *testing.T) {
175
+ res := node.RunIPFS("swarm", "limit", "system", "--enc=json")
176
+ limits := unmarshalLimits(t, res.Stdout.Bytes())
177
+ assert.Equal(t, limits.Conns, rcmgr.LimitVal(99999))
178
+ })
179
+ })
180
+
181
+ t.Run("set the system memory limit while the daemon is running", func(t *testing.T) {
182
+ node := harness.NewT(t).NewNode().Init().StartDaemon()
183
+ updateLimitsWithFile(t, node, "system", func(limits *rcmgr.ResourceLimits) {
184
+ limits.Memory = 99998
185
+ })
186
+
187
+ assert.Equal(t, rcmgr.LimitVal64(99998), node.ReadConfig().Swarm.ResourceMgr.Limits.System.Memory)
188
+
189
+ res := node.RunIPFS("swarm", "limit", "system", "--enc=json")
190
+ limits := unmarshalLimits(t, res.Stdout.Bytes())
191
+ assert.Equal(t, rcmgr.LimitVal64(99998), limits.Memory)
192
+ })
193
+
194
+ t.Run("smoke test transient scope", func(t *testing.T) {
195
+ node := harness.NewT(t).NewNode().Init().StartDaemon()
196
+ updateLimitsWithFile(t, node, "transient", func(limits *rcmgr.ResourceLimits) {
197
+ limits.Memory = 88888
198
+ })
199
+
200
+ res := node.RunIPFS("swarm", "limit", "transient", "--enc=json")
201
+ limits := unmarshalLimits(t, res.Stdout.Bytes())
202
+ assert.Equal(t, rcmgr.LimitVal64(88888), limits.Memory)
203
+ })
204
+
205
+ t.Run("smoke test service scope", func(t *testing.T) {
206
+ node := harness.NewT(t).NewNode().Init().StartDaemon()
207
+ updateLimitsWithFile(t, node, "svc:foo", func(limits *rcmgr.ResourceLimits) {
208
+ limits.Memory = 77777
209
+ })
210
+
211
+ res := node.RunIPFS("swarm", "limit", "svc:foo", "--enc=json")
212
+ limits := unmarshalLimits(t, res.Stdout.Bytes())
213
+ assert.Equal(t, rcmgr.LimitVal64(77777), limits.Memory)
214
+ })
215
+
216
+ t.Run("smoke test protocol scope", func(t *testing.T) {
217
+ node := harness.NewT(t).NewNode().Init().StartDaemon()
218
+ updateLimitsWithFile(t, node, "proto:foo", func(limits *rcmgr.ResourceLimits) {
219
+ limits.Memory = 66666
220
+ })
221
+
222
+ res := node.RunIPFS("swarm", "limit", "proto:foo", "--enc=json")
223
+ limits := unmarshalLimits(t, res.Stdout.Bytes())
224
+ assert.Equal(t, rcmgr.LimitVal64(66666), limits.Memory)
225
+ })
226
+
227
+ t.Run("smoke test peer scope", func(t *testing.T) {
228
+ validPeerID := "QmNnooDu7bfjPFoTZYxMNLWUQJyrVwtbZg5gBMjTezGAJN"
229
+ node := harness.NewT(t).NewNode().Init().StartDaemon()
230
+ updateLimitsWithFile(t, node, "peer:"+validPeerID, func(limits *rcmgr.ResourceLimits) {
231
+ limits.Memory = 66666
232
+ })
233
+
234
+ res := node.RunIPFS("swarm", "limit", "peer:"+validPeerID, "--enc=json")
235
+ limits := unmarshalLimits(t, res.Stdout.Bytes())
236
+ assert.Equal(t, rcmgr.LimitVal64(66666), limits.Memory)
237
+
238
+ t.Parallel()
239
+
240
+ t.Run("getting limit for invalid peer ID fails", func(t *testing.T) {
241
+ res := node.RunIPFS("swarm", "limit", "peer:foo")
242
+ assert.Equal(t, 1, res.ExitCode())
243
+ assert.Contains(t, res.Stderr.String(), "invalid peer ID")
244
+ })
245
+
246
+ t.Run("setting limit for invalid peer ID fails", func(t *testing.T) {
247
+ filename := "invalid-peer-id.json"
248
+ node.WriteBytes(filename, []byte(`{"Memory":"99"}`))
249
+ res := node.RunIPFS("swarm", "limit", "peer:foo", filename)
250
+ assert.Equal(t, 1, res.ExitCode())
251
+ assert.Contains(t, res.Stderr.String(), "invalid peer ID")
252
+ })
253
+ })
254
+
255
+ t.Run("", func(t *testing.T) {
256
+ nodes := harness.NewT(t).NewNodes(3).Init()
257
+ node0, node1, node2 := nodes[0], nodes[1], nodes[2]
258
+ // peerID0, peerID1, peerID2 := node0.PeerID(), node1.PeerID(), node2.PeerID()
259
+ peerID1, peerID2 := node1.PeerID().String(), node2.PeerID().String()
260
+
261
+ node0.UpdateConfig(func(cfg *config.Config) {
262
+ cfg.Swarm.ResourceMgr.Enabled = config.True
263
+ cfg.Swarm.ResourceMgr.Allowlist = []string{"/ip4/0.0.0.0/ipcidr/0/p2p/" + peerID2}
264
+ })
265
+
266
+ nodes.StartDaemons()
267
+
268
+ // change system limits on node 0
269
+ updateLimitsWithFile(t, node0, "system", func(limits *rcmgr.ResourceLimits) {
270
+ limits.Conns = rcmgr.BlockAllLimit
271
+ limits.ConnsInbound = rcmgr.BlockAllLimit
272
+ limits.ConnsOutbound = rcmgr.BlockAllLimit
273
+ })
274
+
275
+ t.Parallel()
276
+ t.Run("node 0 should fail to connect to node 1", func(t *testing.T) {
277
+ res := node0.Runner.Run(harness.RunRequest{
278
+ Path: node0.IPFSBin,
279
+ Args: []string{"swarm", "connect", node1.SwarmAddrs()[0].String()},
280
+ })
281
+ assert.Equal(t, 1, res.ExitCode())
282
+ assert.Contains(t, res.Stderr.String(), "failed to find any peer in table")
283
+ })
284
+
285
+ t.Run("node 0 should connect to node 2 since it is allowlisted", func(t *testing.T) {
286
+ res := node0.Runner.Run(harness.RunRequest{
287
+ Path: node0.IPFSBin,
288
+ Args: []string{"swarm", "connect", node2.SwarmAddrs()[0].String()},
289
+ })
290
+ assert.Equal(t, 0, res.ExitCode())
291
+ })
292
+
293
+ t.Run("node 0 should fail to ping node 1", func(t *testing.T) {
294
+ res := node0.RunIPFS("ping", "-n2", peerID1)
295
+ assert.Equal(t, 1, res.ExitCode())
296
+ assert.Contains(t, res.Stderr.String(), "Error: ping failed")
297
+ })
298
+
299
+ t.Run("node 0 should be able to ping node 2", func(t *testing.T) {
300
+ res := node0.RunIPFS("ping", "-n2", peerID2)
301
+ assert.Equal(t, 0, res.ExitCode())
302
+ })
303
+ })
304
+
305
+ t.Run("daemon should refuse to start if connmgr.highwater < resources inbound", func(t *testing.T) {
306
+ t.Parallel()
307
+ t.Run("system conns", func(t *testing.T) {
308
+ node := harness.NewT(t).NewNode().Init()
309
+ node.UpdateConfig(func(cfg *config.Config) {
310
+ cfg.Swarm.ResourceMgr.Limits = &rcmgr.PartialLimitConfig{}
311
+ cfg.Swarm.ResourceMgr.Limits.System.Conns = 128
312
+ cfg.Swarm.ConnMgr.HighWater = config.NewOptionalInteger(128)
313
+ cfg.Swarm.ConnMgr.LowWater = config.NewOptionalInteger(64)
314
+ })
315
+
316
+ res := node.RunIPFS("daemon")
317
+ assert.Equal(t, 1, res.ExitCode())
318
+ })
319
+ t.Run("system conns inbound", func(t *testing.T) {
320
+ node := harness.NewT(t).NewNode().Init()
321
+ node.UpdateConfig(func(cfg *config.Config) {
322
+ cfg.Swarm.ResourceMgr.Limits = &rcmgr.PartialLimitConfig{}
323
+ cfg.Swarm.ResourceMgr.Limits.System.ConnsInbound = 128
324
+ cfg.Swarm.ConnMgr.HighWater = config.NewOptionalInteger(128)
325
+ cfg.Swarm.ConnMgr.LowWater = config.NewOptionalInteger(64)
326
+ })
327
+
328
+ res := node.RunIPFS("daemon")
329
+ assert.Equal(t, 1, res.ExitCode())
330
+ })
331
+ t.Run("system streams", func(t *testing.T) {
332
+ node := harness.NewT(t).NewNode().Init()
333
+ node.UpdateConfig(func(cfg *config.Config) {
334
+ cfg.Swarm.ResourceMgr.Limits = &rcmgr.PartialLimitConfig{}
335
+ cfg.Swarm.ResourceMgr.Limits.System.Streams = 128
336
+ cfg.Swarm.ConnMgr.HighWater = config.NewOptionalInteger(128)
337
+ cfg.Swarm.ConnMgr.LowWater = config.NewOptionalInteger(64)
338
+ })
339
+
340
+ res := node.RunIPFS("daemon")
341
+ assert.Equal(t, 1, res.ExitCode())
342
+ })
343
+ t.Run("system streams inbound", func(t *testing.T) {
344
+ node := harness.NewT(t).NewNode().Init()
345
+ node.UpdateConfig(func(cfg *config.Config) {
346
+ cfg.Swarm.ResourceMgr.Limits = &rcmgr.PartialLimitConfig{}
347
+ cfg.Swarm.ResourceMgr.Limits.System.StreamsInbound = 128
348
+ cfg.Swarm.ConnMgr.HighWater = config.NewOptionalInteger(128)
349
+ cfg.Swarm.ConnMgr.LowWater = config.NewOptionalInteger(64)
350
+ })
351
+
352
+ res := node.RunIPFS("daemon")
353
+ assert.Equal(t, 1, res.ExitCode())
354
+ })
355
+ })
356
+}
357
+
358
+func updateLimitsWithFile(t *testing.T, node *harness.Node, limit string, f func(*rcmgr.ResourceLimits)) {
359
+ filename := limit + ".json"
360
+ res := node.RunIPFS("swarm", "limit", limit)
361
+ limits := unmarshalLimits(t, res.Stdout.Bytes())
362
+
363
+ f(limits)
364
+
365
+ limitsOut, err := json.Marshal(limits)
366
+ require.NoError(t, err)
367
+ node.WriteBytes(filename, limitsOut)
368
+ res = node.RunIPFS("swarm", "limit", limit, filename)
369
+ assert.Equal(t, 0, res.ExitCode())
370
+}
371
+
372
+func unmarshalLimits(t *testing.T, b []byte) *rcmgr.ResourceLimits {
373
+ limits := &rcmgr.ResourceLimits{}
374
+ err := json.Unmarshal(b, limits)
375
+ require.NoError(t, err)
376
+ return limits
377
+}
test/sharness/t0139-swarm-rcmgr.sh
deleted
-284
@@ -1,284 +0,0 @@
1
-#!/usr/bin/env bash
2
-#
3
-test_description="Test ipfs swarm ResourceMgr config and commands"
4
-
5
-. lib/test-lib.sh
6
-
7
-test_init_ipfs
8
-
9
-test_expect_success 'Disable resource manager' '
10
- ipfs config --bool Swarm.ResourceMgr.Enabled false
11
-'
12
-
13
-# test correct behavior when resource manager is disabled
14
-test_launch_ipfs_daemon
15
-
16
-test_expect_success 'Swarm limit should fail since RM is disabled' '
17
- test_expect_code 1 ipfs swarm limit system 2> actual &&
18
- test_should_contain "missing ResourceMgr" actual
19
-'
20
-
21
-test_expect_success 'Swarm stats should fail since RM is disabled' '
22
- test_expect_code 1 ipfs swarm stats all 2> actual &&
23
- test_should_contain "missing ResourceMgr" actual
24
-'
25
-
26
-test_kill_ipfs_daemon
27
-
28
-test_expect_success 'Enable resource manager' '
29
- ipfs config --bool Swarm.ResourceMgr.Enabled true
30
-'
31
-
32
-# swarm limit|stats should fail in offline mode
33
-
34
-test_expect_success 'disconnected: swarm limit requires running daemon' '
35
- test_expect_code 1 ipfs swarm limit system 2> actual &&
36
- test_should_contain "missing ResourceMgr" actual
37
-'
38
-test_expect_success 'disconnected: swarm stats requires running daemon' '
39
- test_expect_code 1 ipfs swarm stats all 2> actual &&
40
- test_should_contain "missing ResourceMgr" actual
41
-'
42
-
43
-# test sanity scaling
44
-test_expect_success 'set very high connmgr highwater' '
45
- ipfs config --json Swarm.ConnMgr.HighWater 1000
46
-'
47
-
48
-test_launch_ipfs_daemon
49
-
50
-test_expect_success 'conns and streams are above 2000' '
51
- ipfs swarm limit system --enc=json | tee json &&
52
- [ "$(jq -r .ConnsInbound < json)" -ge 2000 ] &&
53
- [ "$(jq -r .StreamsInbound < json)" -ge 2000 ]
54
-'
55
-
56
-test_kill_ipfs_daemon
57
-
58
-test_expect_success 'set previous connmgr highwater' '
59
- ipfs config --json Swarm.ConnMgr.HighWater 96
60
-'
61
-
62
-test_launch_ipfs_daemon
63
-
64
-test_expect_success 'conns and streams are above 800' '
65
- ipfs swarm limit system --enc=json | tee json &&
66
- [ "$(jq -r .ConnsInbound < json)" -ge 800 ] &&
67
- [ "$(jq -r .StreamsInbound < json)" -ge 800 ]
68
-'
69
-
70
-# swarm limit|stats should succeed in online mode by default
71
-# because Resource Manager is opt-out
72
-
73
-# every scope has the same fields, so we only inspect System
74
-test_expect_success 'ResourceMgr enabled: swarm limit' '
75
- ipfs swarm limit system --enc=json | tee json &&
76
- jq -e .Conns < json &&
77
- jq -e .ConnsInbound < json &&
78
- jq -e .ConnsOutbound < json &&
79
- jq -e .FD < json &&
80
- jq -e .Memory < json &&
81
- jq -e .Streams < json &&
82
- jq -e .StreamsInbound < json &&
83
- jq -e .StreamsOutbound < json
84
-'
85
-test_expect_success 'ResourceMgr enabled: swarm limit reset' '
86
- ipfs swarm limit system --reset --enc=json 2> reset &&
87
- ipfs swarm limit system --enc=json 2> actual &&
88
- test_cmp reset actual
89
-'
90
-
91
-test_expect_success 'Swarm stats system with filter should fail' '
92
- test_expect_code 1 ipfs swarm stats system --min-used-limit-perc=99 2> actual &&
93
- test_should_contain "Error: \"min-used-limit-perc\" can only be used when scope is \"all\"" actual
94
-'
95
-
96
-test_expect_success 'ResourceMgr enabled: swarm limit reset on map values' '
97
- ipfs swarm limit peer:12D3KooWL7i1T9VSPeF8AgQApbyM51GNKZsYPvNvL347aMDmvNzG --reset --enc=json 2> reset &&
98
- ipfs swarm limit peer:12D3KooWL7i1T9VSPeF8AgQApbyM51GNKZsYPvNvL347aMDmvNzG --enc=json 2> actual &&
99
- test_cmp reset actual
100
-'
101
-
102
-test_expect_success 'ResourceMgr enabled: scope is required using reset flag' '
103
- test_expect_code 1 ipfs swarm limit --reset 2> actual &&
104
- test_should_contain "Error: argument \"scope\" is required" actual
105
-'
106
-
107
-test_expect_success 'connected: swarm stats all working properly' '
108
- test_expect_code 0 ipfs swarm stats all
109
-'
110
-
111
-# every scope has the same fields, so we only inspect System
112
-test_expect_success 'ResourceMgr enabled: swarm stats' '
113
- ipfs swarm stats all --enc=json | tee json &&
114
- jq -e .System.Memory < json &&
115
- jq -e .System.FD < json &&
116
- jq -e .System.Conns < json &&
117
- jq -e .System.ConnsInbound < json &&
118
- jq -e .System.ConnsOutbound < json &&
119
- jq -e .System.Streams < json &&
120
- jq -e .System.StreamsInbound < json &&
121
- jq -e .System.StreamsOutbound < json &&
122
- jq -e .Transient.Memory < json
123
-'
124
-
125
-# shut down the daemon, set a limit in the config, and verify that it's applied
126
-test_kill_ipfs_daemon
127
-
128
-test_expect_success "Set system conns limit while daemon is not running" "
129
- ipfs config --json Swarm.ResourceMgr.Limits.System.Conns 99999
130
-"
131
-
132
-test_expect_success "Set an invalid limit, which should result in a failure" "
133
- test_expect_code 1 ipfs config --json Swarm.ResourceMgr.Limits.System.Conns 'asdf' 2> actual &&
134
- test_should_contain 'failed to unmarshal' actual
135
-"
136
-
137
-test_launch_ipfs_daemon
138
-
139
-test_expect_success 'Ensure the new system conns limit is applied' '
140
- ipfs swarm limit system --enc=json | tee json &&
141
- jq -e ".Conns == 99999" < json
142
-'
143
-
144
-test_expect_success 'Set system memory limit while the daemon is running' '
145
- ipfs swarm limit system | jq ".Memory = 99998" > system.json &&
146
- ipfs swarm limit system system.json
147
-'
148
-
149
-test_expect_success 'The new system limits were written to the config' '
150
- jq -e ".Swarm.ResourceMgr.Limits.System.Memory == \"99998\"" < "$IPFS_PATH/config"
151
-'
152
-
153
-test_expect_success 'The new system limits are in the swarm limit output' '
154
- ipfs swarm limit system --enc=json | jq -e ".Memory == \"99998\""
155
-'
156
-
157
-# now test all the other scopes
158
-test_expect_success 'Set limit on transient scope' '
159
- ipfs swarm limit transient | jq ".Memory = 88888" > transient.json &&
160
- ipfs swarm limit transient transient.json &&
161
- jq -e ".Swarm.ResourceMgr.Limits.Transient.Memory == \"88888\"" < "$IPFS_PATH/config" &&
162
- ipfs swarm limit transient --enc=json | tee limits &&
163
- jq -e ".Memory == \"88888\"" < limits
164
-'
165
-
166
-test_expect_success 'Set limit on service scope' '
167
- ipfs swarm limit svc:foo | jq ".Memory = 77777" > service-foo.json &&
168
- ipfs swarm limit svc:foo service-foo.json --enc=json &&
169
- jq -e ".Swarm.ResourceMgr.Limits.Service.foo.Memory == \"77777\"" < "$IPFS_PATH/config" &&
170
- ipfs swarm limit svc:foo --enc=json | tee limits &&
171
- jq -e ".Memory == \"77777\"" < limits
172
-'
173
-
174
-test_expect_success 'Set limit on protocol scope' '
175
- ipfs swarm limit proto:foo | jq ".Memory = 66666" > proto-foo.json &&
176
- ipfs swarm limit proto:foo proto-foo.json --enc=json &&
177
- jq -e ".Swarm.ResourceMgr.Limits.Protocol.foo.Memory == \"66666\"" < "$IPFS_PATH/config" &&
178
- ipfs swarm limit proto:foo --enc=json | tee limits &&
179
- jq -e ".Memory == \"66666\"" < limits
180
-'
181
-
182
-# any valid peer id
183
-PEER_ID=QmNnooDu7bfjPFoTZYxMNLWUQJyrVwtbZg5gBMjTezGAJN
184
-
185
-test_expect_success 'Set limit on peer scope' '
186
- ipfs swarm limit peer:$PEER_ID | jq ".Memory = 66666" > peer-$PEER_ID.json &&
187
- ipfs swarm limit peer:$PEER_ID peer-$PEER_ID.json --enc=json &&
188
- jq -e ".Swarm.ResourceMgr.Limits.Peer.${PEER_ID}.Memory == \"66666\"" < "$IPFS_PATH/config" &&
189
- ipfs swarm limit peer:$PEER_ID --enc=json | tee limits &&
190
- jq -e ".Memory == \"66666\"" < limits
191
-'
192
-
193
-test_expect_success 'Get limit for peer scope with an invalid peer ID' '
194
- test_expect_code 1 ipfs swarm limit peer:foo 2> actual &&
195
- test_should_contain "invalid peer ID" actual
196
-'
197
-
198
-test_expect_success 'Set limit for peer scope with an invalid peer ID' '
199
- echo "{\"Memory\": 99}" > invalid-peer-id.json &&
200
- test_expect_code 1 ipfs swarm limit peer:foo invalid-peer-id.json 2> actual &&
201
- test_should_contain "invalid peer ID" actual
202
-'
203
-
204
-test_kill_ipfs_daemon
205
-
206
-## Test allowlist
207
-
208
-test_expect_success 'init iptb' '
209
- iptb testbed create -type localipfs -count 3 -init
210
-'
211
-
212
-test_expect_success 'peer ids' '
213
- PEERID_0=$(iptb attr get 0 id) &&
214
- PEERID_1=$(iptb attr get 1 id) &&
215
- PEERID_2=$(iptb attr get 2 id)
216
-'
217
-
218
-#enable resource manager
219
-test_expect_success 'enable RCMGR' '
220
- ipfsi 0 config --bool Swarm.ResourceMgr.Enabled true &&
221
- ipfsi 0 config --json Swarm.ResourceMgr.Allowlist "[\"/ip4/0.0.0.0/ipcidr/0/p2p/$PEERID_2\"]"
222
-'
223
-
224
-test_expect_success 'start nodes' '
225
- iptb start -wait [0-2]
226
-'
227
-
228
-test_expect_success "change system limits on node 0" '
229
- ipfsi 0 swarm limit system | jq ". + {Conns: 0,ConnsInbound: 0, ConnsOutbound: 0}" > system.json &&
230
- ipfsi 0 swarm limit system system.json
231
-'
232
-
233
-test_expect_success "node 0 fails to connect to 1" '
234
- test_expect_code 1 iptb connect 0 1
235
-'
236
-
237
-test_expect_success "node 0 connects to 2 because it's allowlisted" '
238
- iptb connect 0 2
239
-'
240
-
241
-test_expect_success "node 0 fails to ping 1" '
242
- test_expect_code 1 ipfsi 0 ping -n2 -- "$PEERID_1" 2> actual &&
243
- test_should_contain "Error: ping failed" actual
244
-'
245
-
246
-test_expect_success "node 1 can ping 2" '
247
- ipfsi 0 ping -n2 -- "$PEERID_2"
248
-'
249
-
250
-test_expect_success 'stop iptb' '
251
- iptb stop 0 &&
252
- iptb stop 1 &&
253
- iptb stop 2
254
-'
255
-
256
-## Test daemon refuse to start if connmgr.highwater < ressources inbound
257
-
258
-test_expect_success "node refuse to start if Swarm.ResourceMgr.Limits.System.Conns <= Swarm.ConnMgr.HighWater" '
259
- ipfs config --json Swarm.ResourceMgr.Limits.System.Conns 128 &&
260
- ipfs config --json Swarm.ConnMgr.HighWater 128 &&
261
- ipfs config --json Swarm.ConnMgr.LowWater 64 &&
262
- test_expect_code 1 ipfs daemon &&
263
- ipfs config --json Swarm.ResourceMgr.Limits.System.Conns 256
264
-'
265
-
266
-test_expect_success "node refuse to start if Swarm.ResourceMgr.Limits.System.ConnsInbound <= Swarm.ConnMgr.HighWater" '
267
- ipfs config --json Swarm.ResourceMgr.Limits.System.ConnsInbound 128 &&
268
- test_expect_code 1 ipfs daemon &&
269
- ipfs config --json Swarm.ResourceMgr.Limits.System.ConnsInbound 256
270
-'
271
-
272
-test_expect_success "node refuse to start if Swarm.ResourceMgr.Limits.System.Streams <= Swarm.ConnMgr.HighWater" '
273
- ipfs config --json Swarm.ResourceMgr.Limits.System.Streams 128 &&
274
- test_expect_code 1 ipfs daemon &&
275
- ipfs config --json Swarm.ResourceMgr.Limits.System.Streams 256
276
-'
277
-
278
-test_expect_success "node refuse to start if Swarm.ResourceMgr.Limits.System.StreamsInbound <= Swarm.ConnMgr.HighWater" '
279
- ipfs config --json Swarm.ResourceMgr.Limits.System.StreamsInbound 128 &&
280
- test_expect_code 1 ipfs daemon &&
281
- ipfs config --json Swarm.ResourceMgr.Limits.System.StreamsInbound 256
282
-'
283
-
284
-test_done