kubo/test/cli/init_test.go
Gus Eggert 579175f81d feat: add basic CLI tests using Go Test
This is intended as a replacement for sharness. These are vanilla Go
tests which can be run in your IDE for quick iteration on end-to-end
CLI tests.

This also removes IPTB by duplicating its functionality in the test
harness. This isn't a big deal...IPTB's complexity is mostly around
the fact that its state needs to be saved to disk in between `iptb`
command invocations, and that it uses Go plugins to inject
functionality, neither of which are relevant here.

If we merge this, we'll have to live with bifurcated tests for a while
until they are all migrated. I'd recommend we self-enforce a rule
that, if we need to touch a sharness test, we migrate it and one more
test over to Go tests first. Then eventually we will have migrated
everything.
2022-12-12 09:43:09 -05:00

165 lines
5.2 KiB
Go

package cli
import (
"fmt"
"os"
fp "path/filepath"
"strings"
"testing"
"github.com/ipfs/kubo/test/cli/harness"
. "github.com/ipfs/kubo/test/cli/testutils"
pb "github.com/libp2p/go-libp2p/core/crypto/pb"
"github.com/libp2p/go-libp2p/core/peer"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func validatePeerID(t *testing.T, peerID peer.ID, expErr error, expAlgo pb.KeyType) {
assert.NoError(t, peerID.Validate())
pub, err := peerID.ExtractPublicKey()
assert.ErrorIs(t, expErr, err)
if expAlgo != 0 {
assert.Equal(t, expAlgo, pub.Type())
}
}
func testInitAlgo(t *testing.T, initFlags []string, expOutputName string, expPeerIDPubKeyErr error, expPeerIDPubKeyType pb.KeyType) {
t.Run("init", func(t *testing.T) {
t.Parallel()
node := harness.NewT(t).NewNode()
initRes := node.IPFS(StrCat("init", initFlags)...)
lines := []string{
fmt.Sprintf("generating %s keypair...done", expOutputName),
fmt.Sprintf("peer identity: %s", node.PeerID().String()),
fmt.Sprintf("initializing IPFS node at %s", node.Dir),
"to get started, enter:",
fmt.Sprintf("\n\tipfs cat /ipfs/%s/readme\n\n", CIDWelcomeDocs),
}
expectedInitOutput := strings.Join(lines, "\n")
assert.Equal(t, expectedInitOutput, initRes.Stdout.String())
assert.DirExists(t, node.Dir)
assert.FileExists(t, fp.Join(node.Dir, "config"))
assert.DirExists(t, fp.Join(node.Dir, "datastore"))
assert.DirExists(t, fp.Join(node.Dir, "blocks"))
assert.NoFileExists(t, fp.Join(node.Dir, "._check_writeable"))
_, err := os.ReadDir(node.Dir)
assert.NoError(t, err, "ipfs dir should be listable")
validatePeerID(t, node.PeerID(), expPeerIDPubKeyErr, expPeerIDPubKeyType)
res := node.IPFS("config", "Mounts.IPFS")
assert.Equal(t, "/ipfs", res.Stdout.Trimmed())
node.IPFS("cat", fmt.Sprintf("/ipfs/%s/readme", CIDWelcomeDocs))
})
t.Run("init empty repo", func(t *testing.T) {
t.Parallel()
node := harness.NewT(t).NewNode()
initRes := node.IPFS(StrCat("init", "--empty-repo", initFlags)...)
validatePeerID(t, node.PeerID(), expPeerIDPubKeyErr, expPeerIDPubKeyType)
lines := []string{
fmt.Sprintf("generating %s keypair...done", expOutputName),
fmt.Sprintf("peer identity: %s", node.PeerID().String()),
fmt.Sprintf("initializing IPFS node at %s\n", node.Dir),
}
expectedEmptyInitOutput := strings.Join(lines, "\n")
assert.Equal(t, expectedEmptyInitOutput, initRes.Stdout.String())
catRes := node.RunIPFS("cat", fmt.Sprintf("/ipfs/%s/readme", CIDWelcomeDocs))
assert.NotEqual(t, 0, catRes.ExitErr.ExitCode(), "welcome readme doesn't exist")
idRes := node.IPFS("id", "-f", "<aver>")
version := node.IPFS("version", "-n").Stdout.Trimmed()
assert.Contains(t, idRes.Stdout.String(), version)
})
}
func TestInit(t *testing.T) {
t.Parallel()
t.Run("init fails if the repo dir has no perms", func(t *testing.T) {
t.Parallel()
node := harness.NewT(t).NewNode()
badDir := fp.Join(node.Dir, ".badipfs")
err := os.Mkdir(badDir, 0000)
require.NoError(t, err)
res := node.RunIPFS("init", "--repo-dir", badDir)
assert.NotEqual(t, 0, res.Cmd.ProcessState.ExitCode())
assert.Contains(t, res.Stderr.String(), "permission denied")
})
t.Run("init with ed25519", func(t *testing.T) {
t.Parallel()
testInitAlgo(t, []string{"--algorithm=ed25519"}, "ED25519", nil, pb.KeyType_Ed25519)
})
t.Run("init with rsa", func(t *testing.T) {
t.Parallel()
testInitAlgo(t, []string{"--bits=2048", "--algorithm=rsa"}, "2048-bit RSA", peer.ErrNoPublicKey, 0)
})
t.Run("init with default algorithm", func(t *testing.T) {
t.Parallel()
testInitAlgo(t, []string{}, "ED25519", nil, pb.KeyType_Ed25519)
})
t.Run("ipfs init --profile with invalid profile fails", func(t *testing.T) {
t.Parallel()
node := harness.NewT(t).NewNode()
res := node.RunIPFS("init", "--profile=invalid_profile")
assert.NotEqual(t, 0, res.ExitErr.ExitCode())
assert.Equal(t, "Error: invalid configuration profile: invalid_profile", res.Stderr.Trimmed())
})
t.Run("ipfs init --profile with valid profile succeeds", func(t *testing.T) {
t.Parallel()
node := harness.NewT(t).NewNode()
node.IPFS("init", "--profile=server")
})
t.Run("ipfs config looks good", func(t *testing.T) {
t.Parallel()
node := harness.NewT(t).NewNode().Init("--profile=server")
lines := node.IPFS("config", "Swarm.AddrFilters").Stdout.Lines()
assert.Len(t, lines, 18)
out := node.IPFS("config", "Bootstrap").Stdout.Trimmed()
assert.Equal(t, "[]", out)
out = node.IPFS("config", "Addresses.API").Stdout.Trimmed()
assert.Equal(t, "/ip4/127.0.0.1/tcp/0", out)
})
t.Run("ipfs init from existing config succeeds", func(t *testing.T) {
t.Parallel()
nodes := harness.NewT(t).NewNodes(2)
node1 := nodes[0]
node2 := nodes[1]
node1.Init("--profile=server")
node2.IPFS("init", fp.Join(node1.Dir, "config"))
out := node2.IPFS("config", "Addresses.API").Stdout.Trimmed()
assert.Equal(t, "/ip4/127.0.0.1/tcp/0", out)
})
t.Run("ipfs init should not run while daemon is running", func(t *testing.T) {
t.Parallel()
node := harness.NewT(t).NewNode().Init().StartDaemon()
res := node.RunIPFS("init")
assert.NotEqual(t, 0, res.ExitErr.ExitCode())
assert.Contains(t, res.Stderr.String(), "Error: ipfs daemon is running. please stop it to run this command")
})
}