master
go 186 lines 6.5 KB
Raw
1 package cli
2
3 import (
4 "strings"
5 "testing"
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"
12 "github.com/stretchr/testify/assert"
13 )
14
15 func TestBitswapConfig(t *testing.T) {
16 t.Parallel()
17
18 // Create test data that will be shared between nodes
19 testData := random.Bytes(100)
20
21 t.Run("server enabled (default)", func(t *testing.T) {
22 t.Parallel()
23 h := harness.NewT(t)
24 provider := h.NewNode().Init().StartDaemon()
25 defer provider.StopDaemon()
26 requester := h.NewNode().Init().StartDaemon()
27 defer requester.StopDaemon()
28
29 hash := provider.IPFSAddStr(string(testData))
30 requester.Connect(provider)
31
32 res := requester.IPFS("cat", hash)
33 assert.Equal(t, testData, res.Stdout.Bytes(), "retrieved data should match original")
34 })
35
36 t.Run("server disabled", func(t *testing.T) {
37 t.Parallel()
38 h := harness.NewT(t)
39
40 provider := h.NewNode().Init()
41 provider.SetIPFSConfig("Bitswap.ServerEnabled", false)
42 provider = provider.StartDaemon()
43 defer provider.StopDaemon()
44
45 requester := h.NewNode().Init().StartDaemon()
46 defer requester.StopDaemon()
47
48 hash := provider.IPFSAddStr(string(testData))
49 requester.Connect(provider)
50
51 // If the data was available, it would be retrieved immediately.
52 // Therefore, after the timeout, we can assume the data is not available
53 // i.e. the server is disabled
54 timeout := time.After(3 * time.Second)
55 dataChan := make(chan []byte)
56
57 go func() {
58 res := requester.RunIPFS("cat", hash)
59 dataChan <- res.Stdout.Bytes()
60 }()
61
62 select {
63 case data := <-dataChan:
64 assert.NotEqual(t, testData, data, "retrieved data should not match original")
65 case <-timeout:
66 t.Log("Test passed: operation timed out after 3 seconds as expected")
67 }
68 })
69
70 t.Run("client still works when server disabled", func(t *testing.T) {
71 t.Parallel()
72 h := harness.NewT(t)
73
74 requester := h.NewNode().Init()
75 requester.SetIPFSConfig("Bitswap.ServerEnabled", false)
76 requester.StartDaemon()
77 defer requester.StopDaemon()
78
79 provider := h.NewNode().Init().StartDaemon()
80 defer provider.StopDaemon()
81 hash := provider.IPFSAddStr(string(testData))
82 requester.Connect(provider)
83
84 // Even when the server is disabled, the client should be able to retrieve data
85 res := requester.RunIPFS("cat", hash)
86 assert.Equal(t, testData, res.Stdout.Bytes(), "retrieved data should match original")
87 })
88
89 t.Run("bitswap over libp2p disabled", func(t *testing.T) {
90 t.Parallel()
91 h := harness.NewT(t)
92
93 requester := h.NewNode().Init()
94 requester.UpdateConfig(func(cfg *config.Config) {
95 cfg.Bitswap.Libp2pEnabled = config.False
96 cfg.Bitswap.ServerEnabled = config.False
97 cfg.HTTPRetrieval.Enabled = config.True
98 })
99 requester.StartDaemon()
100 defer requester.StopDaemon()
101
102 provider := h.NewNode().Init().StartDaemon()
103 defer provider.StopDaemon()
104 hash := provider.IPFSAddStr(string(testData))
105
106 requester.Connect(provider)
107 res := requester.RunIPFS("cat", hash)
108 assert.Equal(t, []byte{}, res.Stdout.Bytes(), "cat should not return any data")
109 assert.Contains(t, res.Stderr.String(), "Error: ipld: could not find")
110
111 // Verify that basic operations still work with bitswap disabled
112 res = requester.IPFS("id")
113 assert.Equal(t, 0, res.ExitCode(), "basic IPFS operations should work")
114 res = requester.IPFS("bitswap", "stat")
115 assert.Equal(t, 0, res.ExitCode(), "bitswap stat should work even with bitswap disabled")
116 res = requester.IPFS("bitswap", "wantlist")
117 assert.Equal(t, 0, res.ExitCode(), "bitswap wantlist should work even with bitswap disabled")
118
119 // Verify local operations still work
120 hashNew := requester.IPFSAddStr("random")
121 res = requester.IPFS("cat", hashNew)
122 assert.Equal(t, []byte("random"), res.Stdout.Bytes(), "cat should return the added data")
123 })
124
125 // Disabling Bitswap.Libp2pEnabled should remove /ipfs/bitswap* protocols from `ipfs id`
126 t.Run("disabling bitswap over libp2p removes it from identify protocol list", func(t *testing.T) {
127 t.Parallel()
128 h := harness.NewT(t)
129
130 provider := h.NewNode().Init()
131 provider.UpdateConfig(func(cfg *config.Config) {
132 cfg.Bitswap.Libp2pEnabled = config.False
133 cfg.Bitswap.ServerEnabled = config.False
134 cfg.HTTPRetrieval.Enabled = config.True
135 })
136 provider = provider.StartDaemon()
137 defer provider.StopDaemon()
138 requester := h.NewNode().Init().StartDaemon()
139 defer requester.StopDaemon()
140 requester.Connect(provider)
141
142 // read libp2p identify from remote peer, and print protocols
143 res := requester.IPFS("id", "-f", "<protocols>", provider.PeerID().String())
144 protocols := strings.SplitSeq(strings.TrimSpace(res.Stdout.String()), "\n")
145
146 // No bitswap protocols should be present
147 for proto := range protocols {
148 assert.NotContains(t, proto, bsnet.ProtocolBitswap, "bitswap protocol %s should not be advertised when server is disabled", proto)
149 assert.NotContains(t, proto, bsnet.ProtocolBitswapNoVers, "bitswap protocol %s should not be advertised when server is disabled", proto)
150 assert.NotContains(t, proto, bsnet.ProtocolBitswapOneOne, "bitswap protocol %s should not be advertised when server is disabled", proto)
151 assert.NotContains(t, proto, bsnet.ProtocolBitswapOneZero, "bitswap protocol %s should not be advertised when server is disabled", proto)
152 }
153 })
154
155 // HTTPRetrieval uses bitswap engine, we need it
156 t.Run("errors when both HTTP and libp2p are disabled", func(t *testing.T) {
157 t.Parallel()
158
159 // init Kubo repo
160 node := harness.NewT(t).NewNode().Init()
161 node.UpdateConfig(func(cfg *config.Config) {
162 cfg.HTTPRetrieval.Enabled = config.False
163 cfg.Bitswap.Libp2pEnabled = config.False
164 cfg.Bitswap.ServerEnabled = config.Default
165 })
166 res := node.RunIPFS("daemon")
167 assert.Contains(t, res.Stderr.Trimmed(), "invalid configuration: Bitswap.Libp2pEnabled and HTTPRetrieval.Enabled are both disabled, unable to initialize Bitswap")
168 assert.Equal(t, 1, res.ExitCode())
169 })
170
171 // HTTPRetrieval uses bitswap engine, we need it
172 t.Run("errors when user set conflicting HTTP and libp2p flags", func(t *testing.T) {
173 t.Parallel()
174
175 // init Kubo repo
176 node := harness.NewT(t).NewNode().Init()
177 node.UpdateConfig(func(cfg *config.Config) {
178 cfg.HTTPRetrieval.Enabled = config.False
179 cfg.Bitswap.Libp2pEnabled = config.False
180 cfg.Bitswap.ServerEnabled = config.True // bad user config: can't enable server when libp2p is down
181 })
182 res := node.RunIPFS("daemon")
183 assert.Contains(t, res.Stderr.Trimmed(), "invalid configuration: Bitswap.Libp2pEnabled and HTTPRetrieval.Enabled are both disabled, unable to initialize Bitswap")
184 assert.Equal(t, 1, res.ExitCode())
185 })
186 }