mirror of https://github.com/docker/cli.git
Add unit tests to docker container ls
Signed-off-by: Vincent Demeester <vincent@sbr.pm>
This commit is contained in:
parent
3e5f2f29ad
commit
581b8d9d72
|
@ -22,9 +22,17 @@ type fakeClient struct {
|
|||
containerCopyFromFunc func(container, srcPath string) (io.ReadCloser, types.ContainerPathStat, error)
|
||||
logFunc func(string, types.ContainerLogsOptions) (io.ReadCloser, error)
|
||||
waitFunc func(string) (<-chan container.ContainerWaitOKBody, <-chan error)
|
||||
containerListFunc func(types.ContainerListOptions) ([]types.Container, error)
|
||||
Version string
|
||||
}
|
||||
|
||||
func (f *fakeClient) ContainerList(_ context.Context, options types.ContainerListOptions) ([]types.Container, error) {
|
||||
if f.containerListFunc != nil {
|
||||
return f.containerListFunc(options)
|
||||
}
|
||||
return []types.Container{}, nil
|
||||
}
|
||||
|
||||
func (f *fakeClient) ContainerInspect(_ context.Context, containerID string) (types.ContainerJSON, error) {
|
||||
if f.inspectFunc != nil {
|
||||
return f.inspectFunc(containerID)
|
||||
|
|
|
@ -0,0 +1,165 @@
|
|||
package container
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"testing"
|
||||
|
||||
"github.com/docker/cli/cli/config/configfile"
|
||||
"github.com/docker/cli/internal/test"
|
||||
"github.com/docker/cli/internal/test/testutil"
|
||||
"github.com/docker/docker/api/types"
|
||||
"github.com/stretchr/testify/assert"
|
||||
// Import builders to get the builder function as package function
|
||||
. "github.com/docker/cli/internal/test/builders"
|
||||
"github.com/gotestyourself/gotestyourself/golden"
|
||||
)
|
||||
|
||||
func TestContainerListErrors(t *testing.T) {
|
||||
testCases := []struct {
|
||||
args []string
|
||||
flags map[string]string
|
||||
containerListFunc func(types.ContainerListOptions) ([]types.Container, error)
|
||||
expectedError string
|
||||
}{
|
||||
{
|
||||
flags: map[string]string{
|
||||
"format": "{{invalid}}",
|
||||
},
|
||||
expectedError: `function "invalid" not defined`,
|
||||
},
|
||||
{
|
||||
flags: map[string]string{
|
||||
"format": "{{join}}",
|
||||
},
|
||||
expectedError: `wrong number of args for join`,
|
||||
},
|
||||
{
|
||||
containerListFunc: func(_ types.ContainerListOptions) ([]types.Container, error) {
|
||||
return nil, fmt.Errorf("error listing containers")
|
||||
},
|
||||
expectedError: "error listing containers",
|
||||
},
|
||||
}
|
||||
for _, tc := range testCases {
|
||||
cmd := newListCommand(
|
||||
test.NewFakeCli(&fakeClient{
|
||||
containerListFunc: tc.containerListFunc,
|
||||
}),
|
||||
)
|
||||
cmd.SetArgs(tc.args)
|
||||
for key, value := range tc.flags {
|
||||
cmd.Flags().Set(key, value)
|
||||
}
|
||||
cmd.SetOutput(ioutil.Discard)
|
||||
testutil.ErrorContains(t, cmd.Execute(), tc.expectedError)
|
||||
}
|
||||
}
|
||||
|
||||
func TestContainerListWithoutFormat(t *testing.T) {
|
||||
cli := test.NewFakeCli(&fakeClient{
|
||||
containerListFunc: func(_ types.ContainerListOptions) ([]types.Container, error) {
|
||||
return []types.Container{
|
||||
*Container("c1"),
|
||||
*Container("c2", WithName("foo")),
|
||||
*Container("c3", WithPort(80, 80, TCP), WithPort(81, 81, TCP), WithPort(82, 82, TCP)),
|
||||
*Container("c4", WithPort(81, 81, UDP)),
|
||||
*Container("c5", WithPort(82, 82, IP("8.8.8.8"), TCP)),
|
||||
}, nil
|
||||
},
|
||||
})
|
||||
cmd := newListCommand(cli)
|
||||
assert.NoError(t, cmd.Execute())
|
||||
golden.Assert(t, cli.OutBuffer().String(), "container-list-without-format.golden")
|
||||
}
|
||||
|
||||
func TestContainerListNoTrunc(t *testing.T) {
|
||||
cli := test.NewFakeCli(&fakeClient{
|
||||
containerListFunc: func(_ types.ContainerListOptions) ([]types.Container, error) {
|
||||
return []types.Container{
|
||||
*Container("c1"),
|
||||
*Container("c2", WithName("foo/bar")),
|
||||
}, nil
|
||||
},
|
||||
})
|
||||
cmd := newListCommand(cli)
|
||||
cmd.Flags().Set("no-trunc", "true")
|
||||
assert.NoError(t, cmd.Execute())
|
||||
golden.Assert(t, cli.OutBuffer().String(), "container-list-without-format-no-trunc.golden")
|
||||
}
|
||||
|
||||
// Test for GitHub issue docker/docker#21772
|
||||
func TestContainerListNamesMultipleTime(t *testing.T) {
|
||||
cli := test.NewFakeCli(&fakeClient{
|
||||
containerListFunc: func(_ types.ContainerListOptions) ([]types.Container, error) {
|
||||
return []types.Container{
|
||||
*Container("c1"),
|
||||
*Container("c2", WithName("foo/bar")),
|
||||
}, nil
|
||||
},
|
||||
})
|
||||
cmd := newListCommand(cli)
|
||||
cmd.Flags().Set("format", "{{.Names}} {{.Names}}")
|
||||
assert.NoError(t, cmd.Execute())
|
||||
golden.Assert(t, cli.OutBuffer().String(), "container-list-format-name-name.golden")
|
||||
}
|
||||
|
||||
// Test for GitHub issue docker/docker#30291
|
||||
func TestContainerListFormatTemplateWithArg(t *testing.T) {
|
||||
cli := test.NewFakeCli(&fakeClient{
|
||||
containerListFunc: func(_ types.ContainerListOptions) ([]types.Container, error) {
|
||||
return []types.Container{
|
||||
*Container("c1", WithLabel("some.label", "value")),
|
||||
*Container("c2", WithName("foo/bar"), WithLabel("foo", "bar")),
|
||||
}, nil
|
||||
},
|
||||
})
|
||||
cmd := newListCommand(cli)
|
||||
cmd.Flags().Set("format", `{{.Names}} {{.Label "some.label"}}`)
|
||||
assert.NoError(t, cmd.Execute())
|
||||
golden.Assert(t, cli.OutBuffer().String(), "container-list-format-with-arg.golden")
|
||||
}
|
||||
|
||||
func TestContainerListFormatSizeSetsOption(t *testing.T) {
|
||||
cli := test.NewFakeCli(&fakeClient{
|
||||
containerListFunc: func(options types.ContainerListOptions) ([]types.Container, error) {
|
||||
assert.True(t, options.Size)
|
||||
return []types.Container{}, nil
|
||||
},
|
||||
})
|
||||
cmd := newListCommand(cli)
|
||||
cmd.Flags().Set("format", `{{.Size}}`)
|
||||
assert.NoError(t, cmd.Execute())
|
||||
}
|
||||
|
||||
func TestContainerListWithConfigFormat(t *testing.T) {
|
||||
cli := test.NewFakeCli(&fakeClient{
|
||||
containerListFunc: func(_ types.ContainerListOptions) ([]types.Container, error) {
|
||||
return []types.Container{
|
||||
*Container("c1", WithLabel("some.label", "value")),
|
||||
*Container("c2", WithName("foo/bar"), WithLabel("foo", "bar")),
|
||||
}, nil
|
||||
},
|
||||
})
|
||||
cli.SetConfigFile(&configfile.ConfigFile{
|
||||
PsFormat: "{{ .Names }} {{ .Image }} {{ .Labels }}",
|
||||
})
|
||||
cmd := newListCommand(cli)
|
||||
assert.NoError(t, cmd.Execute())
|
||||
golden.Assert(t, cli.OutBuffer().String(), "container-list-with-config-format.golden")
|
||||
}
|
||||
|
||||
func TestContainerListWithFormat(t *testing.T) {
|
||||
cli := test.NewFakeCli(&fakeClient{
|
||||
containerListFunc: func(_ types.ContainerListOptions) ([]types.Container, error) {
|
||||
return []types.Container{
|
||||
*Container("c1", WithLabel("some.label", "value")),
|
||||
*Container("c2", WithName("foo/bar"), WithLabel("foo", "bar")),
|
||||
}, nil
|
||||
},
|
||||
})
|
||||
cmd := newListCommand(cli)
|
||||
cmd.Flags().Set("format", "{{ .Names }} {{ .Image }} {{ .Labels }}")
|
||||
assert.NoError(t, cmd.Execute())
|
||||
golden.Assert(t, cli.OutBuffer().String(), "container-list-with-format.golden")
|
||||
}
|
|
@ -0,0 +1,2 @@
|
|||
c1 c1
|
||||
c2 c2
|
|
@ -0,0 +1,2 @@
|
|||
c1 value
|
||||
c2
|
|
@ -0,0 +1,2 @@
|
|||
c1 busybox:latest some.label=value
|
||||
c2 busybox:latest foo=bar
|
|
@ -0,0 +1,2 @@
|
|||
c1 busybox:latest some.label=value
|
||||
c2 busybox:latest foo=bar
|
|
@ -0,0 +1,3 @@
|
|||
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
|
||||
container_id busybox:latest "top" Less than a second ago Up 1 second c1
|
||||
container_id busybox:latest "top" Less than a second ago Up 1 second c2,foo/bar
|
|
@ -0,0 +1,6 @@
|
|||
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
|
||||
container_id busybox:latest "top" Less than a second ago Up 1 second c1
|
||||
container_id busybox:latest "top" Less than a second ago Up 1 second c2
|
||||
container_id busybox:latest "top" Less than a second ago Up 1 second 80-82/tcp c3
|
||||
container_id busybox:latest "top" Less than a second ago Up 1 second 81/udp c4
|
||||
container_id busybox:latest "top" Less than a second ago Up 1 second 8.8.8.8:82->82/tcp c5
|
|
@ -0,0 +1,79 @@
|
|||
package builders
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/docker/docker/api/types"
|
||||
)
|
||||
|
||||
// Container creates a container with default values.
|
||||
// Any number of container function builder can be passed to augment it.
|
||||
func Container(name string, builders ...func(container *types.Container)) *types.Container {
|
||||
// now := time.Now()
|
||||
// onehourago := now.Add(-120 * time.Minute)
|
||||
container := &types.Container{
|
||||
ID: "container_id",
|
||||
Names: []string{"/" + name},
|
||||
Command: "top",
|
||||
Image: "busybox:latest",
|
||||
Status: "Up 1 second",
|
||||
Created: time.Now().UnixNano(),
|
||||
}
|
||||
|
||||
for _, builder := range builders {
|
||||
builder(container)
|
||||
}
|
||||
|
||||
return container
|
||||
}
|
||||
|
||||
// WithLabel adds a label to the container
|
||||
func WithLabel(key, value string) func(*types.Container) {
|
||||
return func(c *types.Container) {
|
||||
if c.Labels == nil {
|
||||
c.Labels = map[string]string{}
|
||||
}
|
||||
c.Labels[key] = value
|
||||
}
|
||||
}
|
||||
|
||||
// WithName adds a name to the container
|
||||
func WithName(name string) func(*types.Container) {
|
||||
return func(c *types.Container) {
|
||||
c.Names = append(c.Names, "/"+name)
|
||||
}
|
||||
}
|
||||
|
||||
// WithPort adds a port mapping to the container
|
||||
func WithPort(privateport, publicport uint16, builders ...func(*types.Port)) func(*types.Container) {
|
||||
return func(c *types.Container) {
|
||||
if c.Ports == nil {
|
||||
c.Ports = []types.Port{}
|
||||
}
|
||||
port := &types.Port{
|
||||
PrivatePort: privateport,
|
||||
PublicPort: publicport,
|
||||
}
|
||||
for _, builder := range builders {
|
||||
builder(port)
|
||||
}
|
||||
c.Ports = append(c.Ports, *port)
|
||||
}
|
||||
}
|
||||
|
||||
// IP sets the ip of the port
|
||||
func IP(ip string) func(*types.Port) {
|
||||
return func(p *types.Port) {
|
||||
p.IP = ip
|
||||
}
|
||||
}
|
||||
|
||||
// TCP sets the port to tcp
|
||||
func TCP(p *types.Port) {
|
||||
p.Type = "tcp"
|
||||
}
|
||||
|
||||
// UDP sets the port to udp
|
||||
func UDP(p *types.Port) {
|
||||
p.Type = "udp"
|
||||
}
|
|
@ -5,7 +5,7 @@ import (
|
|||
)
|
||||
|
||||
// Volume creates a volume with default values.
|
||||
// Any number of volume function builder can be pass to augment it.
|
||||
// Any number of volume function builder can be passed to augment it.
|
||||
func Volume(builders ...func(volume *types.Volume)) *types.Volume {
|
||||
volume := &types.Volume{
|
||||
Name: "volume",
|
||||
|
|
Loading…
Reference in New Issue