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")) +}