Skip to content

Commit

Permalink
Migrating cmd/nerdctl to the new framework
Browse files Browse the repository at this point in the history
Signed-off-by: apostasie <[email protected]>
  • Loading branch information
apostasie committed Sep 7, 2024
1 parent 2aa72c0 commit 8cb9f25
Show file tree
Hide file tree
Showing 4 changed files with 141 additions and 61 deletions.
38 changes: 30 additions & 8 deletions cmd/nerdctl/main_linux_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,17 +20,39 @@ import (
"testing"

"github.com/containerd/nerdctl/v2/pkg/testutil"
"github.com/containerd/nerdctl/v2/pkg/testutil/testcase"
)

// TestIssue108 tests https://github.com/containerd/nerdctl/issues/108
// ("`nerdctl run --net=host -it` fails while `nerdctl run -it --net=host` works")
func TestIssue108(t *testing.T) {
base := testutil.NewBase(t)
// unbuffer(1) emulates tty, which is required by `nerdctl run -t`.
// unbuffer(1) can be installed with `apt-get install expect`.
unbuffer := []string{"unbuffer"}
base.CmdWithHelper(unbuffer, "run", "-it", "--rm", "--net=host", testutil.AlpineImage,
"echo", "this was always working").AssertOK()
base.CmdWithHelper(unbuffer, "run", "--rm", "--net=host", "-it", testutil.AlpineImage,
"echo", "this was not working due to issue #108").AssertOK()
t.Parallel()
testutil.RequireExecutable(t, "unbuffer")

testCases := []*testcase.TestCase{
{
Description: "-it --net=host",
Command: func(data *testcase.Data) testcase.Command {
c := &testcase.BaseCommand{}
c.WithHelper("unbuffer")
c.WithArgs("run", "-it", "--rm", "--net=host", testutil.AlpineImage, "echo", "this was always working")
return c
},
Expected: testcase.Expects(0, nil, nil),
},
{
Description: "--net=host -it",
Command: func(data *testcase.Data) testcase.Command {
c := &testcase.BaseCommand{}
c.WithHelper("unbuffer")
c.WithArgs("run", "--rm", "--net=host", "-it", testutil.AlpineImage, "echo", "this was not working due to issue #108")
return c
},
Expected: testcase.Expects(0, nil, nil),
},
}

for _, tc := range testCases {
tc.Run(t)
}
}
141 changes: 91 additions & 50 deletions cmd/nerdctl/main_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,13 @@
package main

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

"gotest.tools/v3/assert"

"github.com/containerd/containerd/v2/defaults"

"github.com/containerd/nerdctl/v2/pkg/testutil"
"github.com/containerd/nerdctl/v2/pkg/testutil/testcase"
)

func TestMain(m *testing.M) {
Expand All @@ -35,55 +33,98 @@ func TestMain(m *testing.M) {
// TestUnknownCommand tests https://github.com/containerd/nerdctl/issues/487
func TestUnknownCommand(t *testing.T) {
t.Parallel()
base := testutil.NewBase(t)
base.Cmd("non-existent-command").AssertFail()
base.Cmd("non-existent-command", "info").AssertFail()
base.Cmd("system", "non-existent-command").AssertFail()
base.Cmd("system", "non-existent-command", "info").AssertFail()
base.Cmd("system").AssertOK() // show help without error
base.Cmd("system", "info").AssertOutContains("Kernel Version:")
base.Cmd("info").AssertOutContains("Kernel Version:")

testCases := []*testcase.TestCase{
{
Description: "non-existent-command",
NoParallel: true,
Command: testcase.NewCommand("non-existent-command"),
Expected: testcase.Expects(1, []error{errors.New("unknown subcommand")}, nil),
},
{
Description: "non-existent-command info",
Command: testcase.NewCommand("non-existent-command", "info"),
Expected: testcase.Expects(1, []error{errors.New("unknown subcommand")}, nil),
},
{
Description: "system non-existent-command",
Command: testcase.NewCommand("system", "non-existent-command"),
Expected: testcase.Expects(1, []error{errors.New("unknown subcommand")}, nil),
},
{
Description: "system non-existent-command info",
Command: testcase.NewCommand("system", "non-existent-command", "info"),
Expected: testcase.Expects(1, []error{errors.New("unknown subcommand")}, nil),
},
{
Description: "system",
Command: testcase.NewCommand("system"),
Expected: testcase.Expects(0, nil, nil),
},
{
Description: "system info",
Command: testcase.NewCommand("system", "info"),
Expected: testcase.Expects(0, nil, testcase.Contains("Kernel Version:")),
},
{
Description: "info",
Command: testcase.NewCommand("info"),
Expected: testcase.Expects(0, nil, testcase.Contains("Kernel Version:")),
},
}

for _, tc := range testCases {
tc.Run(t)
}
}

// TestNerdctlConfig validates the configuration precedence [CLI, Env, TOML, Default].
// TestNerdctlConfig validates the configuration precedence [CLI, Env, TOML, Default] and broken config rejection
func TestNerdctlConfig(t *testing.T) {
testutil.DockerIncompatible(t)
t.Parallel()
tomlPath := filepath.Join(t.TempDir(), "nerdctl.toml")
err := os.WriteFile(tomlPath, []byte(`
snapshotter = "dummy-snapshotter-via-toml"
`), 0400)
assert.NilError(t, err)
base := testutil.NewBase(t)

// [Default]
base.Cmd("info", "-f", "{{.Driver}}").AssertOutExactly(defaults.DefaultSnapshotter + "\n")

// [TOML, Default]
base.Env = append(base.Env, "NERDCTL_TOML="+tomlPath)
base.Cmd("info", "-f", "{{.Driver}}").AssertOutExactly("dummy-snapshotter-via-toml\n")

// [CLI, TOML, Default]
base.Cmd("info", "-f", "{{.Driver}}", "--snapshotter=dummy-snapshotter-via-cli").AssertOutExactly("dummy-snapshotter-via-cli\n")

// [Env, TOML, Default]
base.Env = append(base.Env, "CONTAINERD_SNAPSHOTTER=dummy-snapshotter-via-env")
base.Cmd("info", "-f", "{{.Driver}}").AssertOutExactly("dummy-snapshotter-via-env\n")

// [CLI, Env, TOML, Default]
base.Cmd("info", "-f", "{{.Driver}}", "--snapshotter=dummy-snapshotter-via-cli").AssertOutExactly("dummy-snapshotter-via-cli\n")
}

func TestNerdctlConfigBad(t *testing.T) {
testutil.DockerIncompatible(t)
t.Parallel()
tomlPath := filepath.Join(t.TempDir(), "config.toml")
err := os.WriteFile(tomlPath, []byte(`
# containerd config, not nerdctl config
version = 2
`), 0400)
assert.NilError(t, err)
base := testutil.NewBase(t)
base.Env = append(base.Env, "NERDCTL_TOML="+tomlPath)
base.Cmd("info").AssertFail()

testCases := []*testcase.TestCase{
{
Description: "Default",
Command: testcase.NewCommand("info", "-f", "{{.Driver}}"),
Expected: testcase.Expects(0, nil, testcase.Equals(defaults.DefaultSnapshotter+"\n")),
},
{
Description: "TOML > Default",
NerdctlToml: `snapshotter = "dummy-snapshotter-via-toml"`,
Command: testcase.NewCommand("info", "-f", "{{.Driver}}"),
Expected: testcase.Expects(0, nil, testcase.Equals("dummy-snapshotter-via-toml\n")),
},
{
Description: "Cli > TOML > Default",
NerdctlToml: `snapshotter = "dummy-snapshotter-via-toml"`,
Command: testcase.NewCommand("info", "-f", "{{.Driver}}", "--snapshotter=dummy-snapshotter-via-cli"),
Expected: testcase.Expects(0, nil, testcase.Equals("dummy-snapshotter-via-cli\n")),
},
{
Description: "Env > TOML > Default",
NerdctlToml: `snapshotter = "dummy-snapshotter-via-toml"`,
Command: testcase.NewCommand("info", "-f", "{{.Driver}}"),
Env: map[string]string{"CONTAINERD_SNAPSHOTTER": "dummy-snapshotter-via-env"},
Expected: testcase.Expects(0, nil, testcase.Equals("dummy-snapshotter-via-env\n")),
},
{
Description: "Cli > Env > TOML > Default",
NerdctlToml: `snapshotter = "dummy-snapshotter-via-toml"`,
Command: testcase.NewCommand("info", "-f", "{{.Driver}}", "--snapshotter=dummy-snapshotter-via-cli"),
Env: map[string]string{"CONTAINERD_SNAPSHOTTER": "dummy-snapshotter-via-env"},
Expected: testcase.Expects(0, nil, testcase.Equals("dummy-snapshotter-via-cli\n")),
},
{
Description: "Broken config",
NerdctlToml: `# containerd config, not nerdctl config
version = 2`,
Command: testcase.NewCommand("info"),
Expected: testcase.Expects(1, []error{errors.New("failed to load nerdctl config")}, nil),
},
}

for _, tc := range testCases {
tc.Run(t)
}
}
16 changes: 16 additions & 0 deletions pkg/testutil/testcase/command.go
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,22 @@ func (cc *GenericCommand) WithBase(base *testutil.Base) Command {
return cc
}

func Ensure(t *testing.T, args ...string) {
(func() Command {
bc := &BaseCommand{}
bc.WithArgs(args...)
return bc
})().Run(t, &Expected{})
}

func Anyway(t *testing.T, args ...string) {
(func() Command {
bc := &BaseCommand{}
bc.WithArgs(args...)
return bc
})().Run(t, nil)
}

func NewCommand(args ...string) func(data *Data) Command {
return func(data *Data) Command {
bc := &BaseCommand{}
Expand Down
7 changes: 4 additions & 3 deletions pkg/testutil/testcase/testcase.go
Original file line number Diff line number Diff line change
Expand Up @@ -119,10 +119,9 @@ func (test *TestCase) Run(t *testing.T) {
var base *testutil.Base
// If private, set hosts-dir, data-root, and DOCKER_CONFIG to tempDir, create a dedicated namespace, and make
// sure we clean it up - for nerdctl
// Docker does not have these facilities to isolate as much, so, disable parallel
if test.PrivateMode {
pvNamespace := "nerdctl-test-" + test.Data.testID
base = testutil.NewBaseWithNamespace(t, pvNamespace)
base = testutil.NewBaseWithNamespace(tt, pvNamespace)
test.Env["DOCKER_CONFIG"] = test.Data.tempDir
if base.Target == testutil.Nerdctl {
test.Env["NERDCTL_TOML"] = filepath.Join(test.Data.tempDir, "nerdctl.toml")
Expand All @@ -137,10 +136,12 @@ func (test *TestCase) Run(t *testing.T) {
cleanup()
tt.Cleanup(cleanup)
} else {
// Docker does not have these facilities to isolate as much, so, just disable parallel
// NOTE there then may be side effects to other tests. Obviously use caution.
test.NoParallel = true
}
} else {
base = testutil.NewBase(t)
base = testutil.NewBase(tt)
}

if test.NerdctlToml != "" {
Expand Down

0 comments on commit 8cb9f25

Please sign in to comment.