daemon/list_test.go
05e7f2cf
 package daemon
 
641c73d2
 import (
5c8da2e9
 	"io/ioutil"
 	"os"
 	"path/filepath"
05e7f2cf
 	"testing"
 
 	"github.com/docker/docker/api/types"
5c8da2e9
 	containertypes "github.com/docker/docker/api/types/container"
05e7f2cf
 	"github.com/docker/docker/api/types/filters"
641c73d2
 	"github.com/docker/docker/container"
5c8da2e9
 	"github.com/docker/docker/image"
c435551c
 	"github.com/google/uuid"
07ff4f1d
 	digest "github.com/opencontainers/go-digest"
9f0b3f56
 	"gotest.tools/v3/assert"
 	is "gotest.tools/v3/assert/cmp"
05e7f2cf
 )
 
5c8da2e9
 var root string
 
 func TestMain(m *testing.M) {
 	var err error
 	root, err = ioutil.TempDir("", "docker-container-test-")
 	if err != nil {
 		panic(err)
 	}
 	defer os.RemoveAll(root)
 
 	os.Exit(m.Run())
 }
 
 // This sets up a container with a name so that name filters
 // work against it. It takes in a pointer to Daemon so that
 // minor operations are not repeated by the caller
 func setupContainerWithName(t *testing.T, name string, daemon *Daemon) *container.Container {
6f9b5ba8
 	t.Helper()
5c8da2e9
 	var (
c435551c
 		id              = uuid.New().String()
5c8da2e9
 		computedImageID = digest.FromString(id)
 		cRoot           = filepath.Join(root, id)
 	)
 	if err := os.MkdirAll(cRoot, 0755); err != nil {
 		t.Fatal(err)
 	}
 
 	c := container.NewBaseContainer(id, cRoot)
 	// these are for passing includeContainerInList
6f9b5ba8
 	if name[0] != '/' {
 		name = "/" + name
 	}
5c8da2e9
 	c.Name = name
 	c.Running = true
 	c.HostConfig = &containertypes.HostConfig{}
 
 	// these are for passing the refreshImage reducer
 	c.ImageID = image.IDFromDigest(computedImageID)
 	c.Config = &containertypes.Config{
 		Image: computedImageID.String(),
 	}
 
 	// this is done here to avoid requiring these
 	// operations n x number of containers in the
 	// calling function
 	daemon.containersReplica.Save(c)
 	daemon.reserveName(id, name)
 
 	return c
 }
 
 func containerListContainsName(containers []*types.Container, name string) bool {
eb14d936
 	for _, ctr := range containers {
 		for _, containerName := range ctr.Names {
6f9b5ba8
 			if containerName == name {
5c8da2e9
 				return true
 			}
 		}
 	}
 
 	return false
 }
 
05e7f2cf
 func TestListInvalidFilter(t *testing.T) {
 	db, err := container.NewViewDB()
 	assert.Assert(t, err == nil)
 	d := &Daemon{
 		containersReplica: db,
 	}
 
 	f := filters.NewArgs(filters.Arg("invalid", "foo"))
 
 	_, err = d.Containers(&types.ContainerListOptions{
 		Filters: f,
 	})
 	assert.Assert(t, is.Error(err, "Invalid filter 'invalid'"))
641c73d2
 }
5c8da2e9
 
 func TestNameFilter(t *testing.T) {
 	db, err := container.NewViewDB()
 	assert.Assert(t, err == nil)
 	d := &Daemon{
 		containersReplica: db,
 	}
 
 	var (
 		one   = setupContainerWithName(t, "a1", d)
 		two   = setupContainerWithName(t, "a2", d)
 		three = setupContainerWithName(t, "b1", d)
 	)
 
 	// moby/moby #37453 - ^ regex not working due to prefix slash
 	// not being stripped
 	containerList, err := d.Containers(&types.ContainerListOptions{
 		Filters: filters.NewArgs(filters.Arg("name", "^a")),
 	})
6f9b5ba8
 	assert.NilError(t, err)
5c8da2e9
 	assert.Assert(t, is.Len(containerList, 2))
 	assert.Assert(t, containerListContainsName(containerList, one.Name))
 	assert.Assert(t, containerListContainsName(containerList, two.Name))
 
6f9b5ba8
 	// Same as above but with slash prefix should produce the same result
 	containerListWithPrefix, err := d.Containers(&types.ContainerListOptions{
 		Filters: filters.NewArgs(filters.Arg("name", "^/a")),
 	})
 	assert.NilError(t, err)
 	assert.Assert(t, is.Len(containerListWithPrefix, 2))
 	assert.Assert(t, containerListContainsName(containerListWithPrefix, one.Name))
 	assert.Assert(t, containerListContainsName(containerListWithPrefix, two.Name))
 
5c8da2e9
 	// Same as above but make sure it works for exact names
 	containerList, err = d.Containers(&types.ContainerListOptions{
 		Filters: filters.NewArgs(filters.Arg("name", "b1")),
 	})
6f9b5ba8
 	assert.NilError(t, err)
5c8da2e9
 	assert.Assert(t, is.Len(containerList, 1))
 	assert.Assert(t, containerListContainsName(containerList, three.Name))
6f9b5ba8
 
 	// Same as above but with slash prefix should produce the same result
 	containerListWithPrefix, err = d.Containers(&types.ContainerListOptions{
 		Filters: filters.NewArgs(filters.Arg("name", "/b1")),
 	})
 	assert.NilError(t, err)
 	assert.Assert(t, is.Len(containerListWithPrefix, 1))
 	assert.Assert(t, containerListContainsName(containerListWithPrefix, three.Name))
5c8da2e9
 }