1
0
mirror of https://github.com/ipfs/kubo.git synced 2025-08-06 11:31:54 +08:00
Files
kubo/test/cli/bitswap_config_test.go
Sergey Gorbunov 7c844bacea feat(fuse): Expose MFS as FUSE mount point (#10781)
* Add MFS command line options, extend existing mount functions for MFS, set defaults.

* Directory listing and file stat.

* Add a read-only MFS view.

* Add mkdir and interface checks.

* Add remove and rename functionality.

* Implement all required write interfaces.

* Adjust mount  functions for other architechtures.

* Merge branch 'master' into feat/10710-mfs-fuse-mount

* Write a basic read/write test.

* Write more basic tests, add a mutex to the file object, fix modtime.

* Add a concurrency test, remove mutexes from file and directory structures.

* Refactor naming(mfdir -> mfsdir) and add documentation.

* Add CID retrieval through ipfs_cid xattr.

* Add docs, add xattr listing, fix bugs for mv and stat, refactor.

* Add MFS command line options, extend existing mount functions for MFS, set defaults.

* docs phrasing

* docs: Mounts.MFS

* docs: warn about lazy-loaded DAGs

* test: TEST_FUSE=1 ./t0030-mount.sh -v

---------

Co-authored-by: Guillaume Michel <guillaumemichel@users.noreply.github.com>
Co-authored-by: guillaumemichel <guillaume@michel.id>
Co-authored-by: Marcin Rataj <lidel@lidel.org>
2025-05-06 21:55:53 +02:00

177 lines
6.2 KiB
Go

package cli
import (
"strings"
"testing"
"time"
"github.com/ipfs/boxo/bitswap/network/bsnet"
"github.com/ipfs/kubo/config"
"github.com/ipfs/kubo/test/cli/harness"
"github.com/ipfs/kubo/test/cli/testutils"
"github.com/stretchr/testify/assert"
)
func TestBitswapConfig(t *testing.T) {
t.Parallel()
// Create test data that will be shared between nodes
testData := testutils.RandomBytes(100)
t.Run("server enabled (default)", func(t *testing.T) {
t.Parallel()
h := harness.NewT(t)
provider := h.NewNode().Init().StartDaemon()
requester := h.NewNode().Init().StartDaemon()
hash := provider.IPFSAddStr(string(testData))
requester.Connect(provider)
res := requester.IPFS("cat", hash)
assert.Equal(t, testData, res.Stdout.Bytes(), "retrieved data should match original")
})
t.Run("server disabled", func(t *testing.T) {
t.Parallel()
h := harness.NewT(t)
provider := h.NewNode().Init()
provider.SetIPFSConfig("Bitswap.ServerEnabled", false)
provider = provider.StartDaemon()
requester := h.NewNode().Init().StartDaemon()
hash := provider.IPFSAddStr(string(testData))
requester.Connect(provider)
// If the data was available, it would be retrieved immediately.
// Therefore, after the timeout, we can assume the data is not available
// i.e. the server is disabled
timeout := time.After(3 * time.Second)
dataChan := make(chan []byte)
go func() {
res := requester.RunIPFS("cat", hash)
dataChan <- res.Stdout.Bytes()
}()
select {
case data := <-dataChan:
assert.NotEqual(t, testData, data, "retrieved data should not match original")
case <-timeout:
t.Log("Test passed: operation timed out after 3 seconds as expected")
}
})
t.Run("client still works when server disabled", func(t *testing.T) {
t.Parallel()
h := harness.NewT(t)
requester := h.NewNode().Init()
requester.SetIPFSConfig("Bitswap.ServerEnabled", false)
requester.StartDaemon()
provider := h.NewNode().Init().StartDaemon()
hash := provider.IPFSAddStr(string(testData))
requester.Connect(provider)
// Even when the server is disabled, the client should be able to retrieve data
res := requester.RunIPFS("cat", hash)
assert.Equal(t, testData, res.Stdout.Bytes(), "retrieved data should match original")
})
t.Run("bitswap over libp2p disabled", func(t *testing.T) {
t.Parallel()
h := harness.NewT(t)
requester := h.NewNode().Init()
requester.UpdateConfig(func(cfg *config.Config) {
cfg.Bitswap.Libp2pEnabled = config.False
cfg.Bitswap.ServerEnabled = config.False
cfg.HTTPRetrieval.Enabled = config.True
})
requester.StartDaemon()
provider := h.NewNode().Init().StartDaemon()
hash := provider.IPFSAddStr(string(testData))
requester.Connect(provider)
res := requester.RunIPFS("cat", hash)
assert.Equal(t, []byte{}, res.Stdout.Bytes(), "cat should not return any data")
assert.Contains(t, res.Stderr.String(), "Error: ipld: could not find")
// Verify that basic operations still work with bitswap disabled
res = requester.IPFS("id")
assert.Equal(t, 0, res.ExitCode(), "basic IPFS operations should work")
res = requester.IPFS("bitswap", "stat")
assert.Equal(t, 0, res.ExitCode(), "bitswap stat should work even with bitswap disabled")
res = requester.IPFS("bitswap", "wantlist")
assert.Equal(t, 0, res.ExitCode(), "bitswap wantlist should work even with bitswap disabled")
// Verify local operations still work
hashNew := requester.IPFSAddStr("random")
res = requester.IPFS("cat", hashNew)
assert.Equal(t, []byte("random"), res.Stdout.Bytes(), "cat should return the added data")
})
// Disabling Bitswap.Libp2pEnabled should remove /ipfs/bitswap* protocols from `ipfs id`
t.Run("disabling bitswap over libp2p removes it from identify protocol list", func(t *testing.T) {
t.Parallel()
h := harness.NewT(t)
provider := h.NewNode().Init()
provider.UpdateConfig(func(cfg *config.Config) {
cfg.Bitswap.Libp2pEnabled = config.False
cfg.Bitswap.ServerEnabled = config.False
cfg.HTTPRetrieval.Enabled = config.True
})
provider = provider.StartDaemon()
requester := h.NewNode().Init().StartDaemon()
requester.Connect(provider)
// read libp2p identify from remote peer, and print protocols
res := requester.IPFS("id", "-f", "<protocols>", provider.PeerID().String())
protocols := strings.Split(strings.TrimSpace(res.Stdout.String()), "\n")
// No bitswap protocols should be present
for _, proto := range protocols {
assert.NotContains(t, proto, bsnet.ProtocolBitswap, "bitswap protocol %s should not be advertised when server is disabled", proto)
assert.NotContains(t, proto, bsnet.ProtocolBitswapNoVers, "bitswap protocol %s should not be advertised when server is disabled", proto)
assert.NotContains(t, proto, bsnet.ProtocolBitswapOneOne, "bitswap protocol %s should not be advertised when server is disabled", proto)
assert.NotContains(t, proto, bsnet.ProtocolBitswapOneZero, "bitswap protocol %s should not be advertised when server is disabled", proto)
}
})
// HTTPRetrieval uses bitswap engine, we need it
t.Run("errors when both HTTP and libp2p are disabled", func(t *testing.T) {
t.Parallel()
// init Kubo repo
node := harness.NewT(t).NewNode().Init()
node.UpdateConfig(func(cfg *config.Config) {
cfg.HTTPRetrieval.Enabled = config.False
cfg.Bitswap.Libp2pEnabled = config.False
cfg.Bitswap.ServerEnabled = config.Default
})
res := node.RunIPFS("daemon")
assert.Contains(t, res.Stderr.Trimmed(), "invalid configuration: Bitswap.Libp2pEnabled and HTTPRetrieval.Enabled are both disabled, unable to initialize Bitswap")
assert.Equal(t, 1, res.ExitCode())
})
// HTTPRetrieval uses bitswap engine, we need it
t.Run("errors when user set conflicting HTTP and libp2p flags", func(t *testing.T) {
t.Parallel()
// init Kubo repo
node := harness.NewT(t).NewNode().Init()
node.UpdateConfig(func(cfg *config.Config) {
cfg.HTTPRetrieval.Enabled = config.False
cfg.Bitswap.Libp2pEnabled = config.False
cfg.Bitswap.ServerEnabled = config.True // bad user config: can't enable server when libp2p is down
})
res := node.RunIPFS("daemon")
assert.Contains(t, res.Stderr.Trimmed(), "invalid configuration: Bitswap.Libp2pEnabled and HTTPRetrieval.Enabled are both disabled, unable to initialize Bitswap")
assert.Equal(t, 1, res.ExitCode())
})
}