Skip to content

Commit

Permalink
Unit tests for cli/commands/image (except build and tag)
Browse files Browse the repository at this point in the history
Signed-off-by: Ignacio Capurro <[email protected]>
  • Loading branch information
icapurro committed Apr 23, 2017
1 parent 0e9148b commit b2551c6
Show file tree
Hide file tree
Showing 58 changed files with 1,445 additions and 123 deletions.
7 changes: 7 additions & 0 deletions cli/command/cli.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,9 @@ type Cli interface {
Out() *OutStream
Err() io.Writer
In() *InStream
SetIn(in *InStream)
ConfigFile() *configfile.ConfigFile
CredentialsStore(serverAddress string) credentials.Store
}

// DockerCli is an instance the docker command line client.
Expand Down Expand Up @@ -75,6 +77,11 @@ func (cli *DockerCli) Err() io.Writer {
return cli.err
}

// SetIn sets the reader used for stdin
func (cli *DockerCli) SetIn(in *InStream) {
cli.in = in
}

// In returns the reader used for stdin
func (cli *DockerCli) In() *InStream {
return cli.in
Expand Down
10 changes: 5 additions & 5 deletions cli/command/container/exec_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,21 +13,21 @@ type arguments struct {

func TestParseExec(t *testing.T) {
valids := map[*arguments]*types.ExecConfig{
&arguments{
{
execCmd: []string{"command"},
}: {
Cmd: []string{"command"},
AttachStdout: true,
AttachStderr: true,
},
&arguments{
{
execCmd: []string{"command1", "command2"},
}: {
Cmd: []string{"command1", "command2"},
AttachStdout: true,
AttachStderr: true,
},
&arguments{
{
options: execOptions{
interactive: true,
tty: true,
Expand All @@ -42,7 +42,7 @@ func TestParseExec(t *testing.T) {
Tty: true,
Cmd: []string{"command"},
},
&arguments{
{
options: execOptions{
detach: true,
},
Expand All @@ -54,7 +54,7 @@ func TestParseExec(t *testing.T) {
Detach: true,
Cmd: []string{"command"},
},
&arguments{
{
options: execOptions{
tty: true,
interactive: true,
Expand Down
116 changes: 116 additions & 0 deletions cli/command/image/client_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
package image

import (
"io"
"io/ioutil"
"strings"
"time"

"github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/filters"
"github.com/docker/docker/api/types/image"
"github.com/docker/docker/client"
"golang.org/x/net/context"
)

type fakeClient struct {
client.Client
imageTagFunc func(string, string) error
imageSaveFunc func(images []string) (io.ReadCloser, error)
imageRemoveFunc func(image string, options types.ImageRemoveOptions) ([]types.ImageDeleteResponseItem, error)
imagePushFunc func(ref string, options types.ImagePushOptions) (io.ReadCloser, error)
infoFunc func() (types.Info, error)
imagePullFunc func(ref string, options types.ImagePullOptions) (io.ReadCloser, error)
imagesPruneFunc func(pruneFilter filters.Args) (types.ImagesPruneReport, error)
imageLoadFunc func(input io.Reader, quiet bool) (types.ImageLoadResponse, error)
imageListFunc func(options types.ImageListOptions) ([]types.ImageSummary, error)
imageInspectFunc func(image string) (types.ImageInspect, []byte, error)
imageImportFunc func(source types.ImageImportSource, ref string, options types.ImageImportOptions) (io.ReadCloser, error)
imageHistoryFunc func(image string) ([]image.HistoryResponseItem, error)
}

func (cli *fakeClient) ImageTag(_ context.Context, image, ref string) error {
if cli.imageTagFunc != nil {
return cli.imageTagFunc(image, ref)
}
return nil
}

func (cli *fakeClient) ImageSave(_ context.Context, images []string) (io.ReadCloser, error) {
if cli.imageSaveFunc != nil {
return cli.imageSaveFunc(images)
}
return ioutil.NopCloser(strings.NewReader("")), nil
}

func (cli *fakeClient) ImageRemove(_ context.Context, image string,
options types.ImageRemoveOptions) ([]types.ImageDeleteResponseItem, error) {
if cli.imageRemoveFunc != nil {
return cli.imageRemoveFunc(image, options)
}
return []types.ImageDeleteResponseItem{}, nil
}

func (cli *fakeClient) ImagePush(_ context.Context, ref string, options types.ImagePushOptions) (io.ReadCloser, error) {
if cli.imagePushFunc != nil {
return cli.imagePushFunc(ref, options)
}
return ioutil.NopCloser(strings.NewReader("")), nil
}

func (cli *fakeClient) Info(_ context.Context) (types.Info, error) {
if cli.infoFunc != nil {
return cli.infoFunc()
}
return types.Info{}, nil
}

func (cli *fakeClient) ImagePull(_ context.Context, ref string, options types.ImagePullOptions) (io.ReadCloser, error) {
if cli.imagePullFunc != nil {
cli.imagePullFunc(ref, options)
}
return ioutil.NopCloser(strings.NewReader("")), nil
}

func (cli *fakeClient) ImagesPrune(_ context.Context, pruneFilter filters.Args) (types.ImagesPruneReport, error) {
if cli.imagesPruneFunc != nil {
return cli.imagesPruneFunc(pruneFilter)
}
return types.ImagesPruneReport{}, nil
}

func (cli *fakeClient) ImageLoad(_ context.Context, input io.Reader, quiet bool) (types.ImageLoadResponse, error) {
if cli.imageLoadFunc != nil {
return cli.imageLoadFunc(input, quiet)
}
return types.ImageLoadResponse{}, nil
}

func (cli *fakeClient) ImageList(ctx context.Context, options types.ImageListOptions) ([]types.ImageSummary, error) {
if cli.imageListFunc != nil {
return cli.imageListFunc(options)
}
return []types.ImageSummary{{}}, nil
}

func (cli *fakeClient) ImageInspectWithRaw(_ context.Context, image string) (types.ImageInspect, []byte, error) {
if cli.imageInspectFunc != nil {
return cli.imageInspectFunc(image)
}
return types.ImageInspect{}, nil, nil
}

func (cli *fakeClient) ImageImport(_ context.Context, source types.ImageImportSource, ref string,
options types.ImageImportOptions) (io.ReadCloser, error) {
if cli.imageImportFunc != nil {
return cli.imageImportFunc(source, ref, options)
}
return ioutil.NopCloser(strings.NewReader("")), nil
}

func (cli *fakeClient) ImageHistory(_ context.Context, img string) ([]image.HistoryResponseItem, error) {
if cli.imageHistoryFunc != nil {
return cli.imageHistoryFunc(img)
}
return []image.HistoryResponseItem{{ID: img, Created: time.Now().Unix()}}, nil
}
4 changes: 2 additions & 2 deletions cli/command/image/history.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ type historyOptions struct {
}

// NewHistoryCommand creates a new `docker history` command
func NewHistoryCommand(dockerCli *command.DockerCli) *cobra.Command {
func NewHistoryCommand(dockerCli command.Cli) *cobra.Command {
var opts historyOptions

cmd := &cobra.Command{
Expand All @@ -42,7 +42,7 @@ func NewHistoryCommand(dockerCli *command.DockerCli) *cobra.Command {
return cmd
}

func runHistory(dockerCli *command.DockerCli, opts historyOptions) error {
func runHistory(dockerCli command.Cli, opts historyOptions) error {
ctx := context.Background()

history, err := dockerCli.Client().ImageHistory(ctx, opts.image)
Expand Down
108 changes: 108 additions & 0 deletions cli/command/image/history_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
package image

import (
"bytes"
"fmt"
"io/ioutil"
"regexp"
"testing"
"time"

"github.com/docker/docker/api/types/image"
"github.com/docker/docker/cli/internal/test"
"github.com/docker/docker/pkg/testutil"
"github.com/docker/docker/pkg/testutil/golden"
"github.com/pkg/errors"
"github.com/stretchr/testify/assert"
)

func TestNewHistoryCommandErrors(t *testing.T) {
testCases := []struct {
name string
args []string
expectedError string
imageHistoryFunc func(img string) ([]image.HistoryResponseItem, error)
}{
{
name: "wrong-args",
args: []string{},
expectedError: "requires exactly 1 argument(s).",
},
{
name: "client-error",
args: []string{"image:tag"},
expectedError: "something went wrong",
imageHistoryFunc: func(img string) ([]image.HistoryResponseItem, error) {
return []image.HistoryResponseItem{{}}, errors.Errorf("something went wrong")
},
},
}
for _, tc := range testCases {
buf := new(bytes.Buffer)
cmd := NewHistoryCommand(test.NewFakeCli(&fakeClient{imageHistoryFunc: tc.imageHistoryFunc}, buf))
cmd.SetOutput(ioutil.Discard)
cmd.SetArgs(tc.args)
testutil.ErrorContains(t, cmd.Execute(), tc.expectedError)
}
}

func TestNewHistoryCommandSuccess(t *testing.T) {
testCases := []struct {
name string
args []string
outputRegex string
imageHistoryFunc func(img string) ([]image.HistoryResponseItem, error)
}{
{
name: "simple",
args: []string{"image:tag"},
imageHistoryFunc: func(img string) ([]image.HistoryResponseItem, error) {
return []image.HistoryResponseItem{{
ID: "1234567890123456789",
Created: time.Now().Unix(),
}}, nil
},
},
{
name: "quiet",
args: []string{"--quiet", "image:tag"},
},
// TODO: This test is failing since the output does not contain an RFC3339 date
//{
// name: "non-human",
// args: []string{"--human=false", "image:tag"},
// outputRegex: "\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}", // RFC3339 date format match
//},
{
name: "non-human-header",
args: []string{"--human=false", "image:tag"},
outputRegex: "CREATED\\sAT",
},
{
name: "quiet-no-trunc",
args: []string{"--quiet", "--no-trunc", "image:tag"},
imageHistoryFunc: func(img string) ([]image.HistoryResponseItem, error) {
return []image.HistoryResponseItem{{
ID: "1234567890123456789",
Created: time.Now().Unix(),
}}, nil
},
},
}
for _, tc := range testCases {
buf := new(bytes.Buffer)
cmd := NewHistoryCommand(test.NewFakeCli(&fakeClient{imageHistoryFunc: tc.imageHistoryFunc}, buf))
cmd.SetOutput(ioutil.Discard)
cmd.SetArgs(tc.args)
err := cmd.Execute()
assert.NoError(t, err)
actual := buf.String()
if tc.outputRegex == "" {
expected := string(golden.Get(t, []byte(actual), fmt.Sprintf("history-command-success.%s.golden", tc.name))[:])
testutil.EqualNormalizedString(t, testutil.RemoveSpace, actual, expected)
} else {
match, _ := regexp.MatchString(tc.outputRegex, actual)
assert.Equal(t, match, true)
}
}
}
4 changes: 2 additions & 2 deletions cli/command/image/import.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ type importOptions struct {
}

// NewImportCommand creates a new `docker import` command
func NewImportCommand(dockerCli *command.DockerCli) *cobra.Command {
func NewImportCommand(dockerCli command.Cli) *cobra.Command {
var opts importOptions

cmd := &cobra.Command{
Expand All @@ -48,7 +48,7 @@ func NewImportCommand(dockerCli *command.DockerCli) *cobra.Command {
return cmd
}

func runImport(dockerCli *command.DockerCli, opts importOptions) error {
func runImport(dockerCli command.Cli, opts importOptions) error {
var (
in io.Reader
srcName = opts.source
Expand Down
Loading

0 comments on commit b2551c6

Please sign in to comment.