Skip to content

Commit

Permalink
Migrate system tests to new tooling
Browse files Browse the repository at this point in the history
Signed-off-by: apostasie <[email protected]>
  • Loading branch information
apostasie committed Sep 22, 2024
1 parent fd0ce97 commit d9ee983
Show file tree
Hide file tree
Showing 3 changed files with 174 additions and 167 deletions.
128 changes: 58 additions & 70 deletions cmd/nerdctl/system/system_events_linux_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,96 +17,84 @@
package system

import (
"fmt"
"strings"
"testing"
"time"

"gotest.tools/v3/assert"

"github.com/containerd/nerdctl/v2/pkg/testutil"
"github.com/containerd/nerdctl/v2/pkg/testutil/nerdtest"
"github.com/containerd/nerdctl/v2/pkg/testutil/test"
)

func testEventFilter(t *testing.T, args ...string) string {
t.Parallel()
base := testutil.NewBase(t)
testContainerName := testutil.Identifier(t)
defer base.Cmd("rm", "-f", testContainerName).Run()

fullArgs := []string{"events", "--filter"}
fullArgs = append(fullArgs, args...)
fullArgs = append(fullArgs,
"--format",
"json",
)

eventsCmd := base.Cmd(fullArgs...).Start()
base.Cmd("run", "--rm", testutil.CommonImage).Start()
time.Sleep(3 * time.Second)
return eventsCmd.Stdout()
func testEventFilterExecutor(data test.Data, helpers test.Helpers) test.Command {
cmd := helpers.Command("events", "--filter", data.Get("filter"), "--format", "json")
cmd.Background(1 * time.Second)
helpers.Ensure("run", "--rm", testutil.CommonImage)
return cmd
}

func TestEventFilters(t *testing.T) {
nerdtest.Setup()

type testCase struct {
name string
args []string
nerdctlOut string
dockerOut string
dockerSkip bool
}
testCases := []testCase{
testGroup := &test.Group{
{
name: "CapitializedFilter",
args: []string{"event=START"},
nerdctlOut: "\"Status\":\"start\"",
dockerOut: "\"status\":\"start\"",
dockerSkip: true,
Description: "CapitalizedFilter",
Require: test.Not(nerdtest.Docker),
Command: testEventFilterExecutor,
Expected: func(data test.Data, helpers test.Helpers) *test.Expected {
return &test.Expected{
Output: test.Contains(data.Get("output")),
}
},
Data: test.WithData("filter", "event=START").
Set("output", "\"Status\":\"start\""),
},
{
name: "StartEventFilter",
args: []string{"event=start"},
nerdctlOut: "\"Status\":\"start\"",
dockerOut: "\"status\":\"start\"",
dockerSkip: false,
Description: "StartEventFilter",
Command: testEventFilterExecutor,
Expected: func(data test.Data, helpers test.Helpers) *test.Expected {
return &test.Expected{
Output: test.Contains(data.Get("output")),
}
},
Data: test.WithData("filter", "event=start").
Set("output", "tatus\":\"start\""),
},
{
name: "UnsupportedEventFilter",
args: []string{"event=unknown"},
nerdctlOut: "\"Status\":\"unknown\"",
dockerSkip: true,
Description: "UnsupportedEventFilter",
Require: test.Not(nerdtest.Docker),
Command: testEventFilterExecutor,
Expected: func(data test.Data, helpers test.Helpers) *test.Expected {
return &test.Expected{
Output: test.Contains(data.Get("output")),
}
},
Data: test.WithData("filter", "event=unknown").
Set("output", "\"Status\":\"unknown\""),
},
{
name: "StatusFilter",
args: []string{"status=start"},
nerdctlOut: "\"Status\":\"start\"",
dockerOut: "\"status\":\"start\"",
dockerSkip: false,
Description: "StatusFilter",
Command: testEventFilterExecutor,
Expected: func(data test.Data, helpers test.Helpers) *test.Expected {
return &test.Expected{
Output: test.Contains(data.Get("output")),
}
},
Data: test.WithData("filter", "status=start").
Set("output", "tatus\":\"start\""),
},
{
name: "UnsupportedStatusFilter",
args: []string{"status=unknown"},
nerdctlOut: "\"Status\":\"unknown\"",
dockerSkip: true,
Description: "UnsupportedStatusFilter",
Require: test.Not(nerdtest.Docker),
Command: testEventFilterExecutor,
Expected: func(data test.Data, helpers test.Helpers) *test.Expected {
return &test.Expected{
Output: test.Contains(data.Get("output")),
}
},
Data: test.WithData("filter", "status=unknown").
Set("output", "\"Status\":\"unknown\""),
},
}

for _, tc := range testCases {
tc := tc
t.Run(tc.name, func(t *testing.T) {
actualOut := testEventFilter(t, tc.args...)
errorMsg := fmt.Sprintf("%s failed;\nActual Filter Result: '%s'", tc.name, actualOut)

isDocker := testutil.GetTarget() == testutil.Docker
if isDocker && tc.dockerSkip {
t.Skip("test is incompatible with Docker")
}

if isDocker {
assert.Equal(t, true, strings.Contains(actualOut, tc.dockerOut), errorMsg)
} else {
assert.Equal(t, true, strings.Contains(actualOut, tc.nerdctlOut), errorMsg)
}
})
}
testGroup.Run(t)
}
69 changes: 42 additions & 27 deletions cmd/nerdctl/system/system_info_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,41 +21,56 @@ import (
"fmt"
"testing"

"gotest.tools/v3/assert"

"github.com/containerd/nerdctl/v2/pkg/infoutil"
"github.com/containerd/nerdctl/v2/pkg/inspecttypes/dockercompat"
"github.com/containerd/nerdctl/v2/pkg/testutil"
"github.com/containerd/nerdctl/v2/pkg/testutil/nerdtest"
"github.com/containerd/nerdctl/v2/pkg/testutil/test"
)

func testInfoJSON(stdout string) error {
var info dockercompat.Info
if err := json.Unmarshal([]byte(stdout), &info); err != nil {
return err
}
func testInfoComparator(stdout string, info string, t *testing.T) {
var dinf dockercompat.Info
err := json.Unmarshal([]byte(stdout), &dinf)
assert.NilError(t, err, "failed to unmarshal stdout"+info)
unameM := infoutil.UnameM()
if info.Architecture != unameM {
return fmt.Errorf("expected info.Architecture to be %q, got %q", unameM, info.Architecture)
}
return nil
assert.Assert(t, dinf.Architecture == unameM, fmt.Sprintf("expected info.Architecture to be %q, got %q", unameM, dinf.Architecture)+info)
}

func TestInfo(t *testing.T) {
base := testutil.NewBase(t)
base.Cmd("info", "--format", "{{json .}}").AssertOutWithFunc(testInfoJSON)
}
nerdtest.Setup()

func TestInfoConvenienceForm(t *testing.T) {
testutil.DockerIncompatible(t) // until https://github.com/docker/cli/pull/3355 gets merged
base := testutil.NewBase(t)
base.Cmd("info", "--format", "json").AssertOutWithFunc(testInfoJSON)
}

func TestInfoWithNamespace(t *testing.T) {
testutil.DockerIncompatible(t)
base := testutil.NewBase(t)
base.Args = nil // unset "--namespace=nerdctl-test"

base.Cmd("info").AssertOutContains("Namespace: default")
testGroup := &test.Group{
{
Description: "info",
Command: test.RunCommand("info", "--format", "{{json .}}"),
Expected: test.Expects(0, nil, testInfoComparator),
},
{
Description: "info convenience form",
Command: test.RunCommand("info", "--format", "json"),
Expected: test.Expects(0, nil, testInfoComparator),
},
{
Description: "info with namespace",
Require: test.Not(nerdtest.Docker),
Command: func(data test.Data, helpers test.Helpers) test.Command {
return helpers.Command().Clear().WithBinary("nerdctl").WithArgs("info")
},
Expected: test.Expects(0, nil, test.Contains("Namespace: default")),
},
{
Description: "info with namespace env var",
Env: map[string]string{
"CONTAINERD_NAMESPACE": "test",
},
Require: test.Not(nerdtest.Docker),
Command: func(data test.Data, helpers test.Helpers) test.Command {
return helpers.Command().Clear().WithBinary("nerdctl").WithArgs("info")
},
Expected: test.Expects(0, nil, test.Contains("Namespace: test")),
},
}

base.Env = append(base.Env, "CONTAINERD_NAMESPACE=test")
base.Cmd("info").AssertOutContains("Namespace: test")
testGroup.Run(t)
}
144 changes: 74 additions & 70 deletions cmd/nerdctl/system/system_prune_linux_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,86 +17,90 @@
package system

import (
"bytes"
"fmt"
"io"
"os"
"os/exec"
"strings"
"testing"

"github.com/containerd/log"
"gotest.tools/v3/assert"

"github.com/containerd/nerdctl/v2/pkg/buildkitutil"
"github.com/containerd/nerdctl/v2/pkg/testutil"
"github.com/containerd/nerdctl/v2/pkg/testutil/nerdtest"
"github.com/containerd/nerdctl/v2/pkg/testutil/test"
)

func TestSystemPrune(t *testing.T) {
testutil.RequiresBuild(t)
// FIXME: using a dedicated namespace does not work with rootful (because of buildkit running)
// t.Parallel()
// namespaceID := testutil.Identifier(t)
// base := testutil.NewBaseWithNamespace(t, namespaceID)
base := testutil.NewBase(t)
base.Cmd("container", "prune", "-f").AssertOK()
base.Cmd("network", "prune", "-f").AssertOK()
base.Cmd("volume", "prune", "-f").AssertOK()
base.Cmd("image", "prune", "-f", "--all").AssertOK()

nID := testutil.Identifier(t)
base.Cmd("network", "create", nID).AssertOK()
defer base.Cmd("network", "rm", nID).Run()

vID := testutil.Identifier(t)
base.Cmd("volume", "create", vID).AssertOK()
defer base.Cmd("volume", "rm", vID).Run()

vID2 := base.Cmd("volume", "create").Out()
defer base.Cmd("volume", "rm", vID2).Run()

tID := testutil.Identifier(t)
base.Cmd("run", "-v", fmt.Sprintf("%s:/volume", vID), "--net", nID,
"--name", tID, testutil.CommonImage).AssertOK()
defer base.Cmd("rm", "-f", tID).Run()

base.Cmd("ps", "-a").AssertOutContains(tID)
base.Cmd("images").AssertOutContains(testutil.ImageRepo(testutil.CommonImage))

base.Cmd("system", "prune", "-f", "--volumes", "--all").AssertOK()
base.Cmd("volume", "ls").AssertOutContains(vID) // docker system prune --all --volume does not prune named volume
base.Cmd("volume", "ls").AssertOutNotContains(vID2) // docker system prune --all --volume prune anonymous volume
base.Cmd("ps", "-a").AssertOutNotContains(tID)
base.Cmd("network", "ls").AssertOutNotContains(nID)
base.Cmd("images").AssertOutNotContains(testutil.ImageRepo(testutil.CommonImage))

if testutil.GetTarget() != testutil.Nerdctl {
t.Skip("test skipped for buildkitd is not available with docker-compatible tests")
nerdtest.Setup()

testGroup := &test.Group{
{
Description: "volume prune all success",
// Private because of prune evidently
Require: nerdtest.Private,
Setup: func(data test.Data, helpers test.Helpers) {
helpers.Ensure("network", "create", data.Identifier())
helpers.Ensure("volume", "create", data.Identifier())
anonIdentifier := helpers.Capture("volume", "create")
helpers.Ensure("run", "-v", fmt.Sprintf("%s:/volume", data.Identifier()),
"--net", data.Identifier(), "--name", data.Identifier(), testutil.CommonImage)

data.Set("anonIdentifier", anonIdentifier)
},
Cleanup: func(data test.Data, helpers test.Helpers) {
helpers.Anyhow("network", "rm", data.Identifier())
helpers.Anyhow("volume", "rm", data.Identifier())
helpers.Anyhow("volume", "rm", data.Get("anonIdentifier"))
helpers.Anyhow("rm", "-f", data.Identifier())
},
Command: test.RunCommand("system", "prune", "-f", "--volumes", "--all"),
Expected: func(data test.Data, helpers test.Helpers) *test.Expected {
return &test.Expected{
ExitCode: 0,
Output: func(stdout string, info string, t *testing.T) {
volumes := helpers.Capture("volume", "ls")
networks := helpers.Capture("network", "ls")
images := helpers.Capture("images")
containers := helpers.Capture("ps", "-a")
assert.Assert(t, strings.Contains(volumes, data.Identifier()), volumes)
assert.Assert(t, !strings.Contains(volumes, data.Get("anonIdentifier")), volumes)
assert.Assert(t, !strings.Contains(containers, data.Identifier()), containers)
assert.Assert(t, !strings.Contains(networks, data.Identifier()), networks)
assert.Assert(t, !strings.Contains(images, testutil.CommonImage), images)
},
}
},
},
{
Description: "buildkit",
// FIXME: using a dedicated namespace does not work with rootful (because of buildkitd)
NoParallel: true,
// buildkitd is not available with docker
Require: test.Require(nerdtest.Build, test.Not(nerdtest.Docker)),
// FIXME: this test will happily say "green" even if the command actually fails to do its duty
// if there is nothing in the build cache.
// Ensure with setup here that we DO build something first
Setup: func(data test.Data, helpers test.Helpers) {
helpers.Ensure("system", "prune", "-f", "--volumes", "--all")
},
Command: func(data test.Data, helpers test.Helpers) test.Command {
buildctlBinary, err := buildkitutil.BuildctlBinary()
if err != nil {
t.Fatal(err)
}

host, err := buildkitutil.GetBuildkitHost(testutil.Namespace)
if err != nil {
t.Fatal(err)
}

buildctlArgs := buildkitutil.BuildctlBaseArgs(host)
buildctlArgs = append(buildctlArgs, "du")

return helpers.CustomCommand(buildctlBinary, buildctlArgs...)
},
Expected: test.Expects(0, nil, test.Contains("Total:\t\t0B")),
},
}

buildctlBinary, err := buildkitutil.BuildctlBinary()
if err != nil {
t.Fatal(err)
}
host, err := buildkitutil.GetBuildkitHost(testutil.Namespace)
if err != nil {
t.Fatal(err)
}

buildctlArgs := buildkitutil.BuildctlBaseArgs(host)
buildctlArgs = append(buildctlArgs, "du")
log.L.Debugf("running %s %v", buildctlBinary, buildctlArgs)
buildctlCmd := exec.Command(buildctlBinary, buildctlArgs...)
buildctlCmd.Env = os.Environ()
stdout := bytes.NewBuffer(nil)
buildctlCmd.Stdout = stdout
if err := buildctlCmd.Run(); err != nil {
t.Fatal(err)
}
readAll, err := io.ReadAll(stdout)
if err != nil {
t.Fatal(err)
}
if !strings.Contains(string(readAll), "Total:\t\t0B") {
t.Errorf("buildkit cache is not pruned: %s", string(readAll))
}
testGroup.Run(t)
}

0 comments on commit d9ee983

Please sign in to comment.