Skip to content

Commit

Permalink
test: port twonode test to Go, remove multinode test
Browse files Browse the repository at this point in the history
The multinode test is effectively the same as the twonode test. There
are some problems with it too: it *looks* like it's testing the
Websocket transport with the "listentype,ws" IPTB attribute, but that
attribute doesn't actually exist in ipfs/iptb-plugins, so it does
nothing, so that test actually just runs the same test twice (Yamux
disabled). Furthermore, this is just the same test as in the mplex
twonode test. So this just removes the useless multinode test
entirely.

Also, this removes the part of the twonode test that checks the amount
of data transferred over Bitswap. This is an implementation detail of
Bitswap, it's not appropriate to test this in an end-to-end test as it
depends on algorithmic details of how Bitswap works, and has nothing
to do with transports. This is probably more appropriate as a perf or
benchmark test of Bitswap.

This also moves equivalent functionality from jbenet/go-random-files
into the testutils package. This just copies the code and modifies it
slightly for better ergonomics.
  • Loading branch information
guseggert committed Apr 10, 2023
1 parent a97bf42 commit 03a9828
Show file tree
Hide file tree
Showing 4 changed files with 243 additions and 293 deletions.
116 changes: 116 additions & 0 deletions test/cli/testutils/random_files.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
package testutils

import (
"fmt"
"io"
"math/rand"
"os"
"path"
"time"
)

var AlphabetEasy = []rune("abcdefghijklmnopqrstuvwxyz01234567890-_")
var AlphabetHard = []rune("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890!@#$%^&*()-_+= ;.,<>'\"[]{}() ")

type RandFiles struct {
Rand *rand.Rand
FileSize int // the size per file.
FilenameSize int
Alphabet []rune // for filenames

FanoutDepth int // how deep the hierarchy goes
FanoutFiles int // how many files per dir
FanoutDirs int // how many dirs per dir

RandomSize bool // randomize file sizes
RandomFanout bool // randomize fanout numbers
}

func NewRandFiles() *RandFiles {
return &RandFiles{
Rand: rand.New(rand.NewSource(time.Now().UnixNano())),
FileSize: 4096,
FilenameSize: 16,
Alphabet: AlphabetEasy,
FanoutDepth: 2,
FanoutDirs: 5,
FanoutFiles: 10,
RandomSize: true,
}
}

func (r *RandFiles) WriteRandomFiles(root string, depth int) error {
numfiles := r.FanoutFiles
if r.RandomFanout {
numfiles = rand.Intn(r.FanoutFiles) + 1
}

for i := 0; i < numfiles; i++ {
if err := r.WriteRandomFile(root); err != nil {
return err
}
}

if depth+1 <= r.FanoutDepth {
numdirs := r.FanoutDirs
if r.RandomFanout {
numdirs = r.Rand.Intn(numdirs) + 1
}

for i := 0; i < numdirs; i++ {
if err := r.WriteRandomDir(root, depth+1); err != nil {
return err
}
}
}

return nil
}

func (r *RandFiles) RandomFilename(length int) string {
b := make([]rune, length)
for i := range b {
b[i] = r.Alphabet[r.Rand.Intn(len(r.Alphabet))]
}
return string(b)
}

func (r *RandFiles) WriteRandomFile(root string) error {
filesize := int64(r.FileSize)
if r.RandomSize {
filesize = r.Rand.Int63n(filesize) + 1
}

n := rand.Intn(r.FilenameSize-4) + 4
name := r.RandomFilename(n)
filepath := path.Join(root, name)
f, err := os.Create(filepath)
if err != nil {
return fmt.Errorf("creating random file: %w", err)
}

if _, err := io.CopyN(f, r.Rand, filesize); err != nil {
return fmt.Errorf("copying random file: %w", err)
}

return f.Close()
}

func (r *RandFiles) WriteRandomDir(root string, depth int) error {
if depth > r.FanoutDepth {
return nil
}

n := rand.Intn(r.FilenameSize-4) + 4
name := r.RandomFilename(n)
root = path.Join(root, name)
if err := os.MkdirAll(root, 0755); err != nil {
return fmt.Errorf("creating random dir: %w", err)
}

err := r.WriteRandomFiles(root, depth)
if err != nil {
return fmt.Errorf("writing random files in random dir: %w", err)
}
return nil
}
127 changes: 127 additions & 0 deletions test/cli/transports_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
package cli

import (
"os"
"path/filepath"
"testing"

"github.com/ipfs/kubo/config"
"github.com/ipfs/kubo/test/cli/harness"
"github.com/ipfs/kubo/test/cli/testutils"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)

func TestTransports(t *testing.T) {
disableRouting := func(nodes harness.Nodes) {
nodes.ForEachPar(func(n *harness.Node) {
n.UpdateConfig(func(cfg *config.Config) {
cfg.Routing.Type = config.NewOptionalString("none")
cfg.Bootstrap = nil
})
})
}
checkSingleFile := func(nodes harness.Nodes) {
s := testutils.RandomStr(100)
hash := nodes[0].IPFSAddStr(s)
nodes.ForEachPar(func(n *harness.Node) {
val := n.IPFS("cat", hash).Stdout.String()
assert.Equal(t, s, val)
})
}
checkRandomDir := func(nodes harness.Nodes) {
randDir := filepath.Join(nodes[0].Dir, "foobar")
require.NoError(t, os.Mkdir(randDir, 0777))
rf := testutils.NewRandFiles()
rf.FanoutDirs = 3
rf.FanoutFiles = 6
require.NoError(t, rf.WriteRandomFiles(randDir, 4))

hash := nodes[1].IPFS("add", "-r", "-Q", randDir).Stdout.Trimmed()
nodes.ForEachPar(func(n *harness.Node) {
res := n.RunIPFS("refs", "-r", hash)
assert.Equal(t, 0, res.ExitCode())
})
}

runTests := func(nodes harness.Nodes) {
checkSingleFile(nodes)
checkRandomDir(nodes)
}

tcpNodes := func(t *testing.T) harness.Nodes {
nodes := harness.NewT(t).NewNodes(2).Init()
nodes.ForEachPar(func(n *harness.Node) {
n.UpdateConfig(func(cfg *config.Config) {
cfg.Addresses.Swarm = []string{"/ip4/127.0.0.1/tcp/0"}
cfg.Swarm.Transports.Network.QUIC = config.False
cfg.Swarm.Transports.Network.Relay = config.False
cfg.Swarm.Transports.Network.WebTransport = config.False
cfg.Swarm.Transports.Network.Websocket = config.False
})
})
disableRouting(nodes)
return nodes
}

t.Run("tcp", func(t *testing.T) {
t.Parallel()
nodes := tcpNodes(t).StartDaemons().Connect()
runTests(nodes)
})

t.Run("tcp with mplex", func(t *testing.T) {
t.Parallel()
nodes := tcpNodes(t)
nodes.ForEachPar(func(n *harness.Node) {
n.UpdateConfig(func(cfg *config.Config) {
cfg.Swarm.Transports.Multiplexers.Yamux = config.Disabled
})
})
nodes.StartDaemons().Connect()
runTests(nodes)
})

t.Run("tcp with NOISE", func(t *testing.T) {
t.Parallel()
nodes := tcpNodes(t)
nodes.ForEachPar(func(n *harness.Node) {
n.UpdateConfig(func(cfg *config.Config) {
cfg.Swarm.Transports.Security.TLS = config.Disabled
})
})
nodes.StartDaemons().Connect()
runTests(nodes)
})

t.Run("QUIC", func(t *testing.T) {
t.Parallel()
nodes := harness.NewT(t).NewNodes(5).Init()
nodes.ForEachPar(func(n *harness.Node) {
n.UpdateConfig(func(cfg *config.Config) {
cfg.Addresses.Swarm = []string{"/ip4/127.0.0.1/udp/0/quic-v1"}
cfg.Swarm.Transports.Network.QUIC = config.True
cfg.Swarm.Transports.Network.TCP = config.False
})
})
disableRouting(nodes)
nodes.StartDaemons().Connect()
runTests(nodes)
})

t.Run("QUIC", func(t *testing.T) {
t.Parallel()
nodes := harness.NewT(t).NewNodes(5).Init()
nodes.ForEachPar(func(n *harness.Node) {
n.UpdateConfig(func(cfg *config.Config) {
cfg.Addresses.Swarm = []string{"/ip4/127.0.0.1/udp/0/quic-v1/webtransport"}
cfg.Swarm.Transports.Network.QUIC = config.True
cfg.Swarm.Transports.Network.WebTransport = config.True
})
})
disableRouting(nodes)
nodes.StartDaemons().Connect()
runTests(nodes)
})

}
Loading

0 comments on commit 03a9828

Please sign in to comment.