From 46b360b0598ecd30cde506bc4c6b19a2292b2336 Mon Sep 17 00:00:00 2001 From: Stavros Panakakis Date: Mon, 23 Sep 2024 15:45:26 +0300 Subject: [PATCH] command: add tests for container diff and rename This commit adds tests for the commands docker diff and docker rename. Also, it creates the mock methods of the docker client ContainerDiff and ContainerRename so they can be used in the tests. For docker diff, it covers the cases that: - the command runs successfully - the client returns an error - the container id is empty For docker rename, it covers the cases that: - the command runs successfully - the container old name is empty - the container new name is empty - the client returns an error Co-authored-by: Laura Brehm Signed-off-by: Stavros Panakakis --- cli/command/container/client_test.go | 18 ++++++ cli/command/container/diff_test.go | 93 ++++++++++++++++++++++++++++ cli/command/container/rename_test.go | 77 +++++++++++++++++++++++ 3 files changed, 188 insertions(+) create mode 100644 cli/command/container/diff_test.go create mode 100644 cli/command/container/rename_test.go diff --git a/cli/command/container/client_test.go b/cli/command/container/client_test.go index deae11a73b..8097cf78bd 100644 --- a/cli/command/container/client_test.go +++ b/cli/command/container/client_test.go @@ -38,6 +38,8 @@ type fakeClient struct { containerKillFunc func(ctx context.Context, containerID, signal string) error containerPruneFunc func(ctx context.Context, pruneFilters filters.Args) (container.PruneReport, error) containerAttachFunc func(ctx context.Context, containerID string, options container.AttachOptions) (types.HijackedResponse, error) + containerDiffFunc func(ctx context.Context, containerID string) ([]container.FilesystemChange, error) + containerRenameFunc func(ctx context.Context, oldName, newName string) error Version string } @@ -181,3 +183,19 @@ func (f *fakeClient) ContainerAttach(ctx context.Context, containerID string, op } return types.HijackedResponse{}, nil } + +func (f *fakeClient) ContainerDiff(ctx context.Context, containerID string) ([]container.FilesystemChange, error) { + if f.containerDiffFunc != nil { + return f.containerDiffFunc(ctx, containerID) + } + + return []container.FilesystemChange{}, nil +} + +func (f *fakeClient) ContainerRename(ctx context.Context, oldName, newName string) error { + if f.containerRenameFunc != nil { + return f.containerRenameFunc(ctx, oldName, newName) + } + + return nil +} diff --git a/cli/command/container/diff_test.go b/cli/command/container/diff_test.go new file mode 100644 index 0000000000..2fb191fe81 --- /dev/null +++ b/cli/command/container/diff_test.go @@ -0,0 +1,93 @@ +package container + +import ( + "context" + "io" + "strings" + "testing" + + "github.com/docker/cli/internal/test" + "github.com/docker/docker/api/types/container" + "github.com/pkg/errors" + "gotest.tools/v3/assert" + is "gotest.tools/v3/assert/cmp" +) + +func TestRunDiff(t *testing.T) { + cli := test.NewFakeCli(&fakeClient{ + containerDiffFunc: func( + ctx context.Context, + containerID string, + ) ([]container.FilesystemChange, error) { + return []container.FilesystemChange{ + { + Kind: container.ChangeModify, + Path: "/path/to/file0", + }, + { + Kind: container.ChangeAdd, + Path: "/path/to/file1", + }, + { + Kind: container.ChangeDelete, + Path: "/path/to/file2", + }, + }, nil + }, + }) + + cmd := NewDiffCommand(cli) + cmd.SetOut(io.Discard) + + cmd.SetArgs([]string{"container-id"}) + + err := cmd.Execute() + assert.NilError(t, err) + + diff := strings.SplitN(cli.OutBuffer().String(), "\n", 3) + assert.Assert(t, is.Len(diff, 3)) + + file0 := strings.TrimSpace(diff[0]) + file1 := strings.TrimSpace(diff[1]) + file2 := strings.TrimSpace(diff[2]) + + assert.Check(t, is.Equal(file0, "C /path/to/file0")) + assert.Check(t, is.Equal(file1, "A /path/to/file1")) + assert.Check(t, is.Equal(file2, "D /path/to/file2")) +} + +func TestRunDiffClientError(t *testing.T) { + clientError := errors.New("client error") + + cli := test.NewFakeCli(&fakeClient{ + containerDiffFunc: func( + ctx context.Context, + containerID string, + ) ([]container.FilesystemChange, error) { + return nil, clientError + }, + }) + + cmd := NewDiffCommand(cli) + cmd.SetOut(io.Discard) + cmd.SetErr(io.Discard) + + cmd.SetArgs([]string{"container-id"}) + + err := cmd.Execute() + assert.ErrorIs(t, err, clientError) +} + +func TestRunDiffEmptyContainerError(t *testing.T) { + cli := test.NewFakeCli(&fakeClient{}) + + cmd := NewDiffCommand(cli) + cmd.SetOut(io.Discard) + cmd.SetErr(io.Discard) + + containerID := "" + cmd.SetArgs([]string{containerID}) + + err := cmd.Execute() + assert.Error(t, err, "Container name cannot be empty") +} diff --git a/cli/command/container/rename_test.go b/cli/command/container/rename_test.go new file mode 100644 index 0000000000..4d9c3f664d --- /dev/null +++ b/cli/command/container/rename_test.go @@ -0,0 +1,77 @@ +package container + +import ( + "context" + "io" + "testing" + + "github.com/docker/cli/internal/test" + "github.com/pkg/errors" + "gotest.tools/v3/assert" + is "gotest.tools/v3/assert/cmp" +) + +func TestRunRename(t *testing.T) { + testcases := []struct { + doc, oldName, newName, expectedErr string + }{ + { + doc: "success", + oldName: "oldName", + newName: "newName", + expectedErr: "", + }, + { + doc: "empty old name", + oldName: "", + newName: "newName", + expectedErr: "Error: Neither old nor new names may be empty", + }, + { + doc: "empty new name", + oldName: "oldName", + newName: "", + expectedErr: "Error: Neither old nor new names may be empty", + }, + } + + for _, tc := range testcases { + t.Run(tc.doc, func(t *testing.T) { + cli := test.NewFakeCli(&fakeClient{ + containerRenameFunc: func(ctx context.Context, oldName, newName string) error { + return nil + }, + }) + + cmd := NewRenameCommand(cli) + cmd.SetOut(io.Discard) + cmd.SetErr(io.Discard) + cmd.SetArgs([]string{tc.oldName, tc.newName}) + + err := cmd.Execute() + + if tc.expectedErr != "" { + assert.ErrorContains(t, err, tc.expectedErr) + } else { + assert.NilError(t, err) + } + }) + } +} + +func TestRunRenameClientError(t *testing.T) { + cli := test.NewFakeCli(&fakeClient{ + containerRenameFunc: func(ctx context.Context, oldName, newName string) error { + return errors.New("client error") + }, + }) + + cmd := NewRenameCommand(cli) + cmd.SetOut(io.Discard) + cmd.SetErr(io.Discard) + cmd.SetArgs([]string{"oldName", "newName"}) + + err := cmd.Execute() + + assert.Check(t, is.Error(err, "Error: failed to rename container named oldName")) +}