github.com/toplink-cn/moby@v0.0.0-20240305205811-460b4aebdf81/integration-cli/docker_cli_ps_test.go (about)

     1  package main
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  	"sort"
     7  	"strings"
     8  	"testing"
     9  	"time"
    10  
    11  	"github.com/docker/docker/integration-cli/cli"
    12  	"github.com/docker/docker/integration-cli/cli/build"
    13  	"github.com/docker/docker/pkg/stringid"
    14  	"github.com/docker/go-units"
    15  	"gotest.tools/v3/assert"
    16  	is "gotest.tools/v3/assert/cmp"
    17  	"gotest.tools/v3/icmd"
    18  	"gotest.tools/v3/skip"
    19  )
    20  
    21  type DockerCLIPsSuite struct {
    22  	ds *DockerSuite
    23  }
    24  
    25  func (s *DockerCLIPsSuite) TearDownTest(ctx context.Context, c *testing.T) {
    26  	s.ds.TearDownTest(ctx, c)
    27  }
    28  
    29  func (s *DockerCLIPsSuite) OnTimeout(c *testing.T) {
    30  	s.ds.OnTimeout(c)
    31  }
    32  
    33  func (s *DockerCLIPsSuite) TestPsListContainersBase(c *testing.T) {
    34  	existingContainers := ExistingContainerIDs(c)
    35  
    36  	firstID := runSleepingContainer(c, "-d")
    37  	secondID := runSleepingContainer(c, "-d")
    38  
    39  	// not long running
    40  	out := cli.DockerCmd(c, "run", "-d", "busybox", "true").Stdout()
    41  	thirdID := strings.TrimSpace(out)
    42  
    43  	fourthID := runSleepingContainer(c, "-d")
    44  
    45  	// make sure the second is running
    46  	cli.WaitRun(c, secondID)
    47  
    48  	// make sure third one is not running
    49  	cli.DockerCmd(c, "wait", thirdID)
    50  
    51  	// make sure the forth is running
    52  	cli.WaitRun(c, fourthID)
    53  
    54  	// all
    55  	out = cli.DockerCmd(c, "ps", "-a").Stdout()
    56  	assert.Equal(c, assertContainerList(RemoveOutputForExistingElements(out, existingContainers), []string{fourthID, thirdID, secondID, firstID}), true, fmt.Sprintf("ALL: Container list is not in the correct order: \n%s", out))
    57  
    58  	// running
    59  	out = cli.DockerCmd(c, "ps").Stdout()
    60  	assert.Equal(c, assertContainerList(RemoveOutputForExistingElements(out, existingContainers), []string{fourthID, secondID, firstID}), true, fmt.Sprintf("RUNNING: Container list is not in the correct order: \n%s", out))
    61  
    62  	// limit
    63  	out = cli.DockerCmd(c, "ps", "-n=2", "-a").Stdout()
    64  	expected := []string{fourthID, thirdID}
    65  	assert.Equal(c, assertContainerList(RemoveOutputForExistingElements(out, existingContainers), expected), true, fmt.Sprintf("LIMIT & ALL: Container list is not in the correct order: \n%s", out))
    66  
    67  	out = cli.DockerCmd(c, "ps", "-n=2").Stdout()
    68  	assert.Equal(c, assertContainerList(RemoveOutputForExistingElements(out, existingContainers), expected), true, fmt.Sprintf("LIMIT: Container list is not in the correct order: \n%s", out))
    69  
    70  	// filter since
    71  	out = cli.DockerCmd(c, "ps", "-f", "since="+firstID, "-a").Stdout()
    72  	expected = []string{fourthID, thirdID, secondID}
    73  	assert.Equal(c, assertContainerList(RemoveOutputForExistingElements(out, existingContainers), expected), true, fmt.Sprintf("SINCE filter & ALL: Container list is not in the correct order: \n%s", out))
    74  
    75  	out = cli.DockerCmd(c, "ps", "-f", "since="+firstID).Stdout()
    76  	expected = []string{fourthID, secondID}
    77  	assert.Equal(c, assertContainerList(RemoveOutputForExistingElements(out, existingContainers), expected), true, fmt.Sprintf("SINCE filter: Container list is not in the correct order: \n%s", out))
    78  
    79  	out = cli.DockerCmd(c, "ps", "-f", "since="+thirdID).Stdout()
    80  	expected = []string{fourthID}
    81  	assert.Equal(c, assertContainerList(RemoveOutputForExistingElements(out, existingContainers), expected), true, fmt.Sprintf("SINCE filter: Container list is not in the correct order: \n%s", out))
    82  
    83  	// filter before
    84  	out = cli.DockerCmd(c, "ps", "-f", "before="+fourthID, "-a").Stdout()
    85  	expected = []string{thirdID, secondID, firstID}
    86  	assert.Equal(c, assertContainerList(RemoveOutputForExistingElements(out, existingContainers), expected), true, fmt.Sprintf("BEFORE filter & ALL: Container list is not in the correct order: \n%s", out))
    87  
    88  	out = cli.DockerCmd(c, "ps", "-f", "before="+fourthID).Stdout()
    89  	expected = []string{secondID, firstID}
    90  	assert.Equal(c, assertContainerList(RemoveOutputForExistingElements(out, existingContainers), expected), true, fmt.Sprintf("BEFORE filter: Container list is not in the correct order: \n%s", out))
    91  
    92  	out = cli.DockerCmd(c, "ps", "-f", "before="+thirdID).Stdout()
    93  	expected = []string{secondID, firstID}
    94  	assert.Equal(c, assertContainerList(RemoveOutputForExistingElements(out, existingContainers), expected), true, fmt.Sprintf("SINCE filter: Container list is not in the correct order: \n%s", out))
    95  
    96  	// filter since & before
    97  	out = cli.DockerCmd(c, "ps", "-f", "since="+firstID, "-f", "before="+fourthID, "-a").Stdout()
    98  	expected = []string{thirdID, secondID}
    99  	assert.Equal(c, assertContainerList(RemoveOutputForExistingElements(out, existingContainers), expected), true, fmt.Sprintf("SINCE filter, BEFORE filter & ALL: Container list is not in the correct order: \n%s", out))
   100  
   101  	out = cli.DockerCmd(c, "ps", "-f", "since="+firstID, "-f", "before="+fourthID).Stdout()
   102  	expected = []string{secondID}
   103  	assert.Equal(c, assertContainerList(RemoveOutputForExistingElements(out, existingContainers), expected), true, fmt.Sprintf("SINCE filter, BEFORE filter: Container list is not in the correct order: \n%s", out))
   104  
   105  	// filter since & limit
   106  	out = cli.DockerCmd(c, "ps", "-f", "since="+firstID, "-n=2", "-a").Stdout()
   107  	expected = []string{fourthID, thirdID}
   108  
   109  	assert.Equal(c, assertContainerList(RemoveOutputForExistingElements(out, existingContainers), expected), true, fmt.Sprintf("SINCE filter, LIMIT & ALL: Container list is not in the correct order: \n%s", out))
   110  
   111  	out = cli.DockerCmd(c, "ps", "-f", "since="+firstID, "-n=2").Stdout()
   112  	assert.Equal(c, assertContainerList(RemoveOutputForExistingElements(out, existingContainers), expected), true, fmt.Sprintf("SINCE filter, LIMIT: Container list is not in the correct order: \n%s", out))
   113  
   114  	// filter before & limit
   115  	out = cli.DockerCmd(c, "ps", "-f", "before="+fourthID, "-n=1", "-a").Stdout()
   116  	expected = []string{thirdID}
   117  	assert.Equal(c, assertContainerList(RemoveOutputForExistingElements(out, existingContainers), expected), true, fmt.Sprintf("BEFORE filter, LIMIT & ALL: Container list is not in the correct order: \n%s", out))
   118  
   119  	out = cli.DockerCmd(c, "ps", "-f", "before="+fourthID, "-n=1").Stdout()
   120  	assert.Equal(c, assertContainerList(RemoveOutputForExistingElements(out, existingContainers), expected), true, fmt.Sprintf("BEFORE filter, LIMIT: Container list is not in the correct order: \n%s", out))
   121  
   122  	// filter since & filter before & limit
   123  	out = cli.DockerCmd(c, "ps", "-f", "since="+firstID, "-f", "before="+fourthID, "-n=1", "-a").Stdout()
   124  	expected = []string{thirdID}
   125  	assert.Equal(c, assertContainerList(RemoveOutputForExistingElements(out, existingContainers), expected), true, fmt.Sprintf("SINCE filter, BEFORE filter, LIMIT & ALL: Container list is not in the correct order: \n%s", out))
   126  
   127  	out = cli.DockerCmd(c, "ps", "-f", "since="+firstID, "-f", "before="+fourthID, "-n=1").Stdout()
   128  	assert.Equal(c, assertContainerList(RemoveOutputForExistingElements(out, existingContainers), expected), true, fmt.Sprintf("SINCE filter, BEFORE filter, LIMIT: Container list is not in the correct order: \n%s", out))
   129  }
   130  
   131  func assertContainerList(out string, expected []string) bool {
   132  	lines := strings.Split(strings.Trim(out, "\n "), "\n")
   133  
   134  	if len(lines)-1 != len(expected) {
   135  		return false
   136  	}
   137  
   138  	containerIDIndex := strings.Index(lines[0], "CONTAINER ID")
   139  	for i := 0; i < len(expected); i++ {
   140  		foundID := lines[i+1][containerIDIndex : containerIDIndex+12]
   141  		if foundID != expected[i][:12] {
   142  			return false
   143  		}
   144  	}
   145  
   146  	return true
   147  }
   148  
   149  func (s *DockerCLIPsSuite) TestPsListContainersSize(c *testing.T) {
   150  	// Problematic on Windows as it doesn't report the size correctly @swernli
   151  	testRequires(c, DaemonIsLinux)
   152  	cli.DockerCmd(c, "run", "-d", "busybox")
   153  
   154  	baseOut := cli.DockerCmd(c, "ps", "-s", "-n=1").Stdout()
   155  	baseLines := strings.Split(strings.Trim(baseOut, "\n "), "\n")
   156  	baseSizeIndex := strings.Index(baseLines[0], "SIZE")
   157  	baseFoundsize, _, _ := strings.Cut(baseLines[1][baseSizeIndex:], " ")
   158  	baseBytes, err := units.FromHumanSize(baseFoundsize)
   159  	assert.NilError(c, err)
   160  
   161  	const name = "test_size"
   162  	cli.DockerCmd(c, "run", "--name", name, "busybox", "sh", "-c", "echo 1 > test")
   163  	id := getIDByName(c, name)
   164  
   165  	var result *icmd.Result
   166  
   167  	wait := make(chan struct{})
   168  	go func() {
   169  		result = icmd.RunCommand(dockerBinary, "ps", "-s", "-n=1")
   170  		close(wait)
   171  	}()
   172  	select {
   173  	case <-wait:
   174  	case <-time.After(3 * time.Second):
   175  		c.Fatalf(`Calling "docker ps -s" timed out!`)
   176  	}
   177  	result.Assert(c, icmd.Success)
   178  	lines := strings.Split(strings.Trim(result.Combined(), "\n "), "\n")
   179  	assert.Equal(c, len(lines), 2, "Expected 2 lines for 'ps -s -n=1' output, got %d", len(lines))
   180  	sizeIndex := strings.Index(lines[0], "SIZE")
   181  	idIndex := strings.Index(lines[0], "CONTAINER ID")
   182  	foundID := lines[1][idIndex : idIndex+12]
   183  	assert.Equal(c, foundID, id[:12], fmt.Sprintf("Expected id %s, got %s", id[:12], foundID))
   184  	foundSize, _, _ := strings.Cut(strings.TrimSpace(lines[1][sizeIndex:]), " ")
   185  
   186  	// With snapshotters the reported usage is the real space occupied on the
   187  	// filesystem (also includes metadata), so this new file can actually
   188  	// result in a bigger increase depending on the underlying filesystem (on
   189  	// ext4 this would be 4096 which is a minimum allocation unit).
   190  	if testEnv.UsingSnapshotter() {
   191  		newBytes, err := units.FromHumanSize(foundSize)
   192  		assert.NilError(c, err)
   193  		// Check if size increased by at least 2 bytes.
   194  		assert.Check(c, newBytes >= baseBytes+2)
   195  	} else {
   196  		expectedSize := units.HumanSize(float64(baseBytes + 2))
   197  		assert.Assert(c, strings.Contains(foundSize, expectedSize), "Expected size %q, got %q", expectedSize, foundSize)
   198  	}
   199  }
   200  
   201  func (s *DockerCLIPsSuite) TestPsListContainersFilterStatus(c *testing.T) {
   202  	existingContainers := ExistingContainerIDs(c)
   203  
   204  	// start exited container
   205  	out := cli.DockerCmd(c, "run", "-d", "busybox").Combined()
   206  	firstID := strings.TrimSpace(out)
   207  
   208  	// make sure the exited container is not running
   209  	cli.DockerCmd(c, "wait", firstID)
   210  
   211  	// start running container
   212  	out = cli.DockerCmd(c, "run", "-itd", "busybox").Combined()
   213  	secondID := strings.TrimSpace(out)
   214  
   215  	// filter containers by exited
   216  	out = cli.DockerCmd(c, "ps", "--no-trunc", "-q", "--filter=status=exited").Combined()
   217  	containerOut := strings.TrimSpace(out)
   218  	assert.Equal(c, RemoveOutputForExistingElements(containerOut, existingContainers), firstID)
   219  
   220  	out = cli.DockerCmd(c, "ps", "-a", "--no-trunc", "-q", "--filter=status=running").Combined()
   221  	containerOut = strings.TrimSpace(out)
   222  	assert.Equal(c, RemoveOutputForExistingElements(containerOut, existingContainers), secondID)
   223  
   224  	result := cli.Docker(cli.Args("ps", "-a", "-q", "--filter=status=rubbish"), cli.WithTimeout(time.Second*60))
   225  	result.Assert(c, icmd.Expected{
   226  		ExitCode: 1,
   227  		Err:      "invalid filter 'status=rubbish'",
   228  	})
   229  	// Windows doesn't support pausing of containers
   230  	if testEnv.DaemonInfo.OSType != "windows" {
   231  		// pause running container
   232  		out = cli.DockerCmd(c, "run", "-itd", "busybox").Combined()
   233  		pausedID := strings.TrimSpace(out)
   234  		cli.DockerCmd(c, "pause", pausedID)
   235  		// make sure the container is unpaused to let the daemon stop it properly
   236  		defer func() { cli.DockerCmd(c, "unpause", pausedID) }()
   237  
   238  		out = cli.DockerCmd(c, "ps", "--no-trunc", "-q", "--filter=status=paused").Combined()
   239  		containerOut = strings.TrimSpace(out)
   240  		assert.Equal(c, RemoveOutputForExistingElements(containerOut, existingContainers), pausedID)
   241  	}
   242  }
   243  
   244  func (s *DockerCLIPsSuite) TestPsListContainersFilterHealth(c *testing.T) {
   245  	skip.If(c, RuntimeIsWindowsContainerd(), "FIXME. Hang on Windows + containerd combination")
   246  	existingContainers := ExistingContainerIDs(c)
   247  	// Test legacy no health check
   248  	containerID := runSleepingContainer(c, "--name=none_legacy")
   249  
   250  	cli.WaitRun(c, containerID)
   251  
   252  	out := cli.DockerCmd(c, "ps", "-q", "-l", "--no-trunc", "--filter=health=none").Combined()
   253  	containerOut := strings.TrimSpace(out)
   254  	assert.Equal(c, containerOut, containerID, fmt.Sprintf("Expected id %s, got %s for legacy none filter, output: %q", containerID, containerOut, out))
   255  
   256  	// Test no health check specified explicitly
   257  	containerID = runSleepingContainer(c, "--name=none", "--no-healthcheck")
   258  
   259  	cli.WaitRun(c, containerID)
   260  
   261  	out = cli.DockerCmd(c, "ps", "-q", "-l", "--no-trunc", "--filter=health=none").Combined()
   262  	containerOut = strings.TrimSpace(out)
   263  	assert.Equal(c, containerOut, containerID, fmt.Sprintf("Expected id %s, got %s for none filter, output: %q", containerID, containerOut, out))
   264  
   265  	// Test failing health check
   266  	out = runSleepingContainer(c, "--name=failing_container", "--health-cmd=exit 1", "--health-interval=1s")
   267  	containerID = strings.TrimSpace(out)
   268  
   269  	waitForHealthStatus(c, "failing_container", "starting", "unhealthy")
   270  
   271  	out = cli.DockerCmd(c, "ps", "-q", "--no-trunc", "--filter=health=unhealthy").Combined()
   272  	containerOut = strings.TrimSpace(out)
   273  	assert.Equal(c, containerOut, containerID, fmt.Sprintf("Expected containerID %s, got %s for unhealthy filter, output: %q", containerID, containerOut, out))
   274  
   275  	// Check passing healthcheck
   276  	containerID = runSleepingContainer(c, "--name=passing_container", "--health-cmd=exit 0", "--health-interval=1s")
   277  
   278  	waitForHealthStatus(c, "passing_container", "starting", "healthy")
   279  
   280  	out = cli.DockerCmd(c, "ps", "-q", "--no-trunc", "--filter=health=healthy").Combined()
   281  	containerOut = strings.TrimSpace(RemoveOutputForExistingElements(out, existingContainers))
   282  	assert.Equal(c, containerOut, containerID, fmt.Sprintf("Expected containerID %s, got %s for healthy filter, output: %q", containerID, containerOut, out))
   283  }
   284  
   285  func (s *DockerCLIPsSuite) TestPsListContainersFilterID(c *testing.T) {
   286  	// start container
   287  	out := cli.DockerCmd(c, "run", "-d", "busybox").Stdout()
   288  	firstID := strings.TrimSpace(out)
   289  
   290  	// start another container
   291  	runSleepingContainer(c)
   292  
   293  	// filter containers by id
   294  	out = cli.DockerCmd(c, "ps", "-a", "-q", "--filter=id="+firstID).Stdout()
   295  	containerOut := strings.TrimSpace(out)
   296  	assert.Equal(c, containerOut, firstID[:12], fmt.Sprintf("Expected id %s, got %s for exited filter, output: %q", firstID[:12], containerOut, out))
   297  }
   298  
   299  func (s *DockerCLIPsSuite) TestPsListContainersFilterName(c *testing.T) {
   300  	// start container
   301  	cli.DockerCmd(c, "run", "--name=a_name_to_match", "busybox")
   302  	id := getIDByName(c, "a_name_to_match")
   303  
   304  	// start another container
   305  	runSleepingContainer(c, "--name=b_name_to_match")
   306  
   307  	// filter containers by name
   308  	out := cli.DockerCmd(c, "ps", "-a", "-q", "--filter=name=a_name_to_match").Stdout()
   309  	containerOut := strings.TrimSpace(out)
   310  	assert.Equal(c, containerOut, id[:12], fmt.Sprintf("Expected id %s, got %s for exited filter, output: %q", id[:12], containerOut, out))
   311  }
   312  
   313  // Test for the ancestor filter for ps.
   314  // There is also the same test but with image:tag@digest in docker_cli_by_digest_test.go
   315  //
   316  // What the test setups :
   317  // - Create 2 image based on busybox using the same repository but different tags
   318  // - Create an image based on the previous image (images_ps_filter_test2)
   319  // - Run containers for each of those image (busybox, images_ps_filter_test1, images_ps_filter_test2)
   320  // - Filter them out :P
   321  func (s *DockerCLIPsSuite) TestPsListContainersFilterAncestorImage(c *testing.T) {
   322  	existingContainers := ExistingContainerIDs(c)
   323  
   324  	// Build images
   325  	imageName1 := "images_ps_filter_test1"
   326  	buildImageSuccessfully(c, imageName1, build.WithDockerfile(`FROM busybox
   327  		 LABEL match me 1`))
   328  	imageID1 := getIDByName(c, imageName1)
   329  
   330  	imageName1Tagged := "images_ps_filter_test1:tag"
   331  	buildImageSuccessfully(c, imageName1Tagged, build.WithDockerfile(`FROM busybox
   332  		 LABEL match me 1 tagged`))
   333  	imageID1Tagged := getIDByName(c, imageName1Tagged)
   334  
   335  	imageName2 := "images_ps_filter_test2"
   336  	buildImageSuccessfully(c, imageName2, build.WithDockerfile(fmt.Sprintf(`FROM %s
   337  		 LABEL match me 2`, imageName1)))
   338  	imageID2 := getIDByName(c, imageName2)
   339  
   340  	// start containers
   341  	cli.DockerCmd(c, "run", "--name=first", "busybox", "echo", "hello")
   342  	firstID := getIDByName(c, "first")
   343  
   344  	// start another container
   345  	cli.DockerCmd(c, "run", "--name=second", "busybox", "echo", "hello")
   346  	secondID := getIDByName(c, "second")
   347  
   348  	// start third container
   349  	cli.DockerCmd(c, "run", "--name=third", imageName1, "echo", "hello")
   350  	thirdID := getIDByName(c, "third")
   351  
   352  	// start fourth container
   353  	cli.DockerCmd(c, "run", "--name=fourth", imageName1Tagged, "echo", "hello")
   354  	fourthID := getIDByName(c, "fourth")
   355  
   356  	// start fifth container
   357  	cli.DockerCmd(c, "run", "--name=fifth", imageName2, "echo", "hello")
   358  	fifthID := getIDByName(c, "fifth")
   359  
   360  	filterTestSuite := []struct {
   361  		filterName  string
   362  		expectedIDs []string
   363  	}{
   364  		// non existent stuff
   365  		{"nonexistent", []string{}},
   366  		{"nonexistent:tag", []string{}},
   367  		// image
   368  		{"busybox", []string{firstID, secondID, thirdID, fourthID, fifthID}},
   369  		{imageName1, []string{thirdID, fifthID}},
   370  		{imageName2, []string{fifthID}},
   371  		// image:tag
   372  		{fmt.Sprintf("%s:latest", imageName1), []string{thirdID, fifthID}},
   373  		{imageName1Tagged, []string{fourthID}},
   374  		// short-id
   375  		{stringid.TruncateID(imageID1), []string{thirdID, fifthID}},
   376  		{stringid.TruncateID(imageID2), []string{fifthID}},
   377  		// full-id
   378  		{imageID1, []string{thirdID, fifthID}},
   379  		{imageID1Tagged, []string{fourthID}},
   380  		{imageID2, []string{fifthID}},
   381  	}
   382  
   383  	var out string
   384  	for _, filter := range filterTestSuite {
   385  		out = cli.DockerCmd(c, "ps", "-a", "-q", "--no-trunc", "--filter=ancestor="+filter.filterName).Stdout()
   386  		checkPsAncestorFilterOutput(c, RemoveOutputForExistingElements(out, existingContainers), filter.filterName, filter.expectedIDs)
   387  	}
   388  
   389  	// Multiple ancestor filter
   390  	out = cli.DockerCmd(c, "ps", "-a", "-q", "--no-trunc", "--filter=ancestor="+imageName2, "--filter=ancestor="+imageName1Tagged).Stdout()
   391  	checkPsAncestorFilterOutput(c, RemoveOutputForExistingElements(out, existingContainers), imageName2+","+imageName1Tagged, []string{fourthID, fifthID})
   392  }
   393  
   394  func checkPsAncestorFilterOutput(c *testing.T, out string, filterName string, expectedIDs []string) {
   395  	var actualIDs []string
   396  	if out != "" {
   397  		actualIDs = strings.Split(out[:len(out)-1], "\n")
   398  	}
   399  	sort.Strings(actualIDs)
   400  	sort.Strings(expectedIDs)
   401  
   402  	assert.Equal(c, len(actualIDs), len(expectedIDs), fmt.Sprintf("Expected filtered container(s) for %s ancestor filter to be %v:%v, got %v:%v", filterName, len(expectedIDs), expectedIDs, len(actualIDs), actualIDs))
   403  	if len(expectedIDs) > 0 {
   404  		same := true
   405  		for i := range expectedIDs {
   406  			if actualIDs[i] != expectedIDs[i] {
   407  				c.Logf("%s, %s", actualIDs[i], expectedIDs[i])
   408  				same = false
   409  				break
   410  			}
   411  		}
   412  		assert.Equal(c, same, true, fmt.Sprintf("Expected filtered container(s) for %s ancestor filter to be %v, got %v", filterName, expectedIDs, actualIDs))
   413  	}
   414  }
   415  
   416  func (s *DockerCLIPsSuite) TestPsListContainersFilterLabel(c *testing.T) {
   417  	// start container
   418  	cli.DockerCmd(c, "run", "--name=first", "-l", "match=me", "-l", "second=tag", "busybox")
   419  	firstID := getIDByName(c, "first")
   420  
   421  	// start another container
   422  	cli.DockerCmd(c, "run", "--name=second", "-l", "match=me too", "busybox")
   423  	secondID := getIDByName(c, "second")
   424  
   425  	// start third container
   426  	cli.DockerCmd(c, "run", "--name=third", "-l", "nomatch=me", "busybox")
   427  	thirdID := getIDByName(c, "third")
   428  
   429  	// filter containers by exact match
   430  	out := cli.DockerCmd(c, "ps", "-a", "-q", "--no-trunc", "--filter=label=match=me").Stdout()
   431  	containerOut := strings.TrimSpace(out)
   432  	assert.Equal(c, containerOut, firstID, fmt.Sprintf("Expected id %s, got %s for exited filter, output: %q", firstID, containerOut, out))
   433  
   434  	// filter containers by two labels
   435  	out = cli.DockerCmd(c, "ps", "-a", "-q", "--no-trunc", "--filter=label=match=me", "--filter=label=second=tag").Stdout()
   436  	containerOut = strings.TrimSpace(out)
   437  	assert.Equal(c, containerOut, firstID, fmt.Sprintf("Expected id %s, got %s for exited filter, output: %q", firstID, containerOut, out))
   438  
   439  	// filter containers by two labels, but expect not found because of AND behavior
   440  	out = cli.DockerCmd(c, "ps", "-a", "-q", "--no-trunc", "--filter=label=match=me", "--filter=label=second=tag-no").Stdout()
   441  	containerOut = strings.TrimSpace(out)
   442  	assert.Equal(c, containerOut, "", fmt.Sprintf("Expected nothing, got %s for exited filter, output: %q", containerOut, out))
   443  
   444  	// filter containers by exact key
   445  	out = cli.DockerCmd(c, "ps", "-a", "-q", "--no-trunc", "--filter=label=match").Stdout()
   446  	containerOut = strings.TrimSpace(out)
   447  	assert.Assert(c, strings.Contains(containerOut, firstID))
   448  	assert.Assert(c, strings.Contains(containerOut, secondID))
   449  	assert.Assert(c, !strings.Contains(containerOut, thirdID))
   450  }
   451  
   452  func (s *DockerCLIPsSuite) TestPsListContainersFilterExited(c *testing.T) {
   453  	// TODO Flaky on  Windows CI [both RS1 and RS5]
   454  	// On slower machines the container may not have exited
   455  	// yet when we filter below by exit status/exit value.
   456  	skip.If(c, DaemonIsWindows(), "FLAKY on Windows, see #20819")
   457  	runSleepingContainer(c, "--name=sleep")
   458  
   459  	firstZero := cli.DockerCmd(c, "run", "-d", "busybox", "true").Stdout()
   460  	secondZero := cli.DockerCmd(c, "run", "-d", "busybox", "true").Stdout()
   461  
   462  	out, _, err := dockerCmdWithError("run", "--name", "nonzero1", "busybox", "false")
   463  	assert.Assert(c, err != nil, "Should fail. out: %s", out)
   464  	firstNonZero := getIDByName(c, "nonzero1")
   465  
   466  	out, _, err = dockerCmdWithError("run", "--name", "nonzero2", "busybox", "false")
   467  	assert.Assert(c, err != nil, "Should fail. out: %s", out)
   468  	secondNonZero := getIDByName(c, "nonzero2")
   469  
   470  	// filter containers by exited=0
   471  	out = cli.DockerCmd(c, "ps", "-a", "-q", "--no-trunc", "--filter=exited=0").Stdout()
   472  	assert.Assert(c, strings.Contains(out, strings.TrimSpace(firstZero)))
   473  	assert.Assert(c, strings.Contains(out, strings.TrimSpace(secondZero)))
   474  	assert.Assert(c, !strings.Contains(out, strings.TrimSpace(firstNonZero)))
   475  	assert.Assert(c, !strings.Contains(out, strings.TrimSpace(secondNonZero)))
   476  	out = cli.DockerCmd(c, "ps", "-a", "-q", "--no-trunc", "--filter=exited=1").Stdout()
   477  	assert.Assert(c, strings.Contains(out, strings.TrimSpace(firstNonZero)))
   478  	assert.Assert(c, strings.Contains(out, strings.TrimSpace(secondNonZero)))
   479  	assert.Assert(c, !strings.Contains(out, strings.TrimSpace(firstZero)))
   480  	assert.Assert(c, !strings.Contains(out, strings.TrimSpace(secondZero)))
   481  }
   482  
   483  func (s *DockerCLIPsSuite) TestPsRightTagName(c *testing.T) {
   484  	// TODO Investigate further why this fails on Windows to Windows CI
   485  	testRequires(c, DaemonIsLinux)
   486  
   487  	existingContainers := ExistingContainerNames(c)
   488  
   489  	tag := "asybox:shmatest"
   490  	cli.DockerCmd(c, "tag", "busybox", tag)
   491  
   492  	id1 := runSleepingContainer(c)
   493  	id2 := runSleepingContainerInImage(c, tag)
   494  
   495  	imageID := inspectField(c, "busybox", "Id")
   496  
   497  	id3 := runSleepingContainerInImage(c, imageID)
   498  
   499  	out := cli.DockerCmd(c, "ps", "--no-trunc").Stdout()
   500  	lines := strings.Split(strings.TrimSpace(out), "\n")
   501  	lines = RemoveLinesForExistingElements(lines, existingContainers)
   502  	// skip header
   503  	lines = lines[1:]
   504  	assert.Equal(c, len(lines), 3, "There should be 3 running container, got %d", len(lines))
   505  	for _, line := range lines {
   506  		f := strings.Fields(line)
   507  		switch f[0] {
   508  		case id1:
   509  			assert.Equal(c, f[1], "busybox", fmt.Sprintf("Expected %s tag for id %s, got %s", "busybox", id1, f[1]))
   510  		case id2:
   511  			assert.Equal(c, f[1], tag, fmt.Sprintf("Expected %s tag for id %s, got %s", tag, id2, f[1]))
   512  		case id3:
   513  			assert.Equal(c, f[1], imageID, fmt.Sprintf("Expected %s imageID for id %s, got %s", tag, id3, f[1]))
   514  		default:
   515  			c.Fatalf("Unexpected id %s, expected %s and %s and %s", f[0], id1, id2, id3)
   516  		}
   517  	}
   518  }
   519  
   520  func (s *DockerCLIPsSuite) TestPsListContainersFilterCreated(c *testing.T) {
   521  	// create a container
   522  	out := cli.DockerCmd(c, "create", "busybox").Stdout()
   523  	cID := strings.TrimSpace(out)
   524  	shortCID := cID[:12]
   525  
   526  	// Make sure it DOESN'T show up w/o a '-a' for normal 'ps'
   527  	out = cli.DockerCmd(c, "ps", "-q").Stdout()
   528  	assert.Assert(c, !strings.Contains(out, shortCID), "Should have not seen '%s' in ps output:\n%s", shortCID, out)
   529  	// Make sure it DOES show up as 'Created' for 'ps -a'
   530  	out = cli.DockerCmd(c, "ps", "-a").Stdout()
   531  
   532  	hits := 0
   533  	for _, line := range strings.Split(out, "\n") {
   534  		if !strings.Contains(line, shortCID) {
   535  			continue
   536  		}
   537  		hits++
   538  		assert.Assert(c, strings.Contains(line, "Created"), "Missing 'Created' on '%s'", line)
   539  	}
   540  
   541  	assert.Equal(c, hits, 1, fmt.Sprintf("Should have seen '%s' in ps -a output once:%d\n%s", shortCID, hits, out))
   542  
   543  	// filter containers by 'create' - note, no -a needed
   544  	out = cli.DockerCmd(c, "ps", "-q", "-f", "status=created").Stdout()
   545  	containerOut := strings.TrimSpace(out)
   546  	assert.Assert(c, strings.Contains(containerOut, shortCID), "Should have seen '%s' in ps output:\n%s", shortCID, out)
   547  }
   548  
   549  // Test for GitHub issue #12595
   550  func (s *DockerCLIPsSuite) TestPsImageIDAfterUpdate(c *testing.T) {
   551  	// TODO: Investigate why this fails on Windows to Windows CI further.
   552  	testRequires(c, DaemonIsLinux)
   553  	originalImageName := "busybox:TestPsImageIDAfterUpdate-original"
   554  	updatedImageName := "busybox:TestPsImageIDAfterUpdate-updated"
   555  
   556  	existingContainers := ExistingContainerIDs(c)
   557  
   558  	icmd.RunCommand(dockerBinary, "tag", "busybox:latest", originalImageName).Assert(c, icmd.Success)
   559  
   560  	originalImageID := getIDByName(c, originalImageName)
   561  
   562  	result := icmd.RunCommand(dockerBinary, append([]string{"run", "-d", originalImageName}, sleepCommandForDaemonPlatform()...)...)
   563  	result.Assert(c, icmd.Success)
   564  	containerID := strings.TrimSpace(result.Combined())
   565  
   566  	result = icmd.RunCommand(dockerBinary, "ps", "--no-trunc")
   567  	result.Assert(c, icmd.Success)
   568  
   569  	lines := strings.Split(strings.TrimSpace(result.Combined()), "\n")
   570  	lines = RemoveLinesForExistingElements(lines, existingContainers)
   571  	// skip header
   572  	lines = lines[1:]
   573  	assert.Equal(c, len(lines), 1)
   574  
   575  	for _, line := range lines {
   576  		f := strings.Fields(line)
   577  		assert.Equal(c, f[1], originalImageName)
   578  	}
   579  
   580  	icmd.RunCommand(dockerBinary, "commit", containerID, updatedImageName).Assert(c, icmd.Success)
   581  	icmd.RunCommand(dockerBinary, "tag", updatedImageName, originalImageName).Assert(c, icmd.Success)
   582  
   583  	result = icmd.RunCommand(dockerBinary, "ps", "--no-trunc")
   584  	result.Assert(c, icmd.Success)
   585  
   586  	lines = strings.Split(strings.TrimSpace(result.Combined()), "\n")
   587  	lines = RemoveLinesForExistingElements(lines, existingContainers)
   588  	// skip header
   589  	lines = lines[1:]
   590  	assert.Equal(c, len(lines), 1)
   591  
   592  	for _, line := range lines {
   593  		f := strings.Fields(line)
   594  		assert.Equal(c, f[1], originalImageID)
   595  	}
   596  }
   597  
   598  func (s *DockerCLIPsSuite) TestPsNotShowPortsOfStoppedContainer(c *testing.T) {
   599  	testRequires(c, DaemonIsLinux)
   600  	cli.DockerCmd(c, "run", "--name=foo", "-d", "-p", "6000:5000", "busybox", "top")
   601  	cli.WaitRun(c, "foo")
   602  	ports := cli.DockerCmd(c, "ps", "--format", "{{ .Ports }}", "--filter", "name=foo").Stdout()
   603  	expected := ":6000->5000/tcp"
   604  	assert.Assert(c, is.Contains(ports, expected), "Expected: %v, got: %v", expected, ports)
   605  
   606  	cli.DockerCmd(c, "kill", "foo")
   607  	cli.DockerCmd(c, "wait", "foo")
   608  	ports = cli.DockerCmd(c, "ps", "--format", "{{ .Ports }}", "--filter", "name=foo").Stdout()
   609  	assert.Equal(c, ports, "", "Should not got %v", expected)
   610  }
   611  
   612  func (s *DockerCLIPsSuite) TestPsShowMounts(c *testing.T) {
   613  	existingContainers := ExistingContainerNames(c)
   614  
   615  	prefix, slash := getPrefixAndSlashFromDaemonPlatform()
   616  
   617  	mp := prefix + slash + "test"
   618  
   619  	cli.DockerCmd(c, "volume", "create", "ps-volume-test")
   620  	// volume mount containers
   621  	runSleepingContainer(c, "--name=volume-test-1", "--volume", "ps-volume-test:"+mp)
   622  	cli.WaitRun(c, "volume-test-1")
   623  	runSleepingContainer(c, "--name=volume-test-2", "--volume", mp)
   624  	cli.WaitRun(c, "volume-test-2")
   625  	// bind mount container
   626  	var bindMountSource string
   627  	var bindMountDestination string
   628  	if DaemonIsWindows() {
   629  		bindMountSource = `c:\`
   630  		bindMountDestination = `c:\t`
   631  	} else {
   632  		bindMountSource = "/tmp"
   633  		bindMountDestination = "/t"
   634  	}
   635  	runSleepingContainer(c, "--name=bind-mount-test", "-v", bindMountSource+":"+bindMountDestination)
   636  	cli.WaitRun(c, "bind-mount-test")
   637  
   638  	out := cli.DockerCmd(c, "ps", "--format", "{{.Names}} {{.Mounts}}").Stdout()
   639  
   640  	lines := strings.Split(strings.TrimSpace(out), "\n")
   641  	lines = RemoveLinesForExistingElements(lines, existingContainers)
   642  	assert.Equal(c, len(lines), 3)
   643  
   644  	fields := strings.Fields(lines[0])
   645  	assert.Equal(c, len(fields), 2)
   646  	assert.Equal(c, fields[0], "bind-mount-test")
   647  	assert.Equal(c, fields[1], bindMountSource)
   648  
   649  	fields = strings.Fields(lines[1])
   650  	assert.Equal(c, len(fields), 2)
   651  
   652  	anonymousVolumeID := fields[1]
   653  
   654  	fields = strings.Fields(lines[2])
   655  	assert.Equal(c, fields[1], "ps-volume-test")
   656  
   657  	// filter by volume name
   658  	out = cli.DockerCmd(c, "ps", "--format", "{{.Names}} {{.Mounts}}", "--filter", "volume=ps-volume-test").Stdout()
   659  
   660  	lines = strings.Split(strings.TrimSpace(out), "\n")
   661  	lines = RemoveLinesForExistingElements(lines, existingContainers)
   662  	assert.Equal(c, len(lines), 1)
   663  
   664  	fields = strings.Fields(lines[0])
   665  	assert.Equal(c, fields[1], "ps-volume-test")
   666  
   667  	// empty results filtering by unknown volume
   668  	out = cli.DockerCmd(c, "ps", "--format", "{{.Names}} {{.Mounts}}", "--filter", "volume=this-volume-should-not-exist").Stdout()
   669  	assert.Equal(c, len(strings.TrimSpace(out)), 0)
   670  
   671  	// filter by mount destination
   672  	out = cli.DockerCmd(c, "ps", "--format", "{{.Names}} {{.Mounts}}", "--filter", "volume="+mp).Stdout()
   673  
   674  	lines = strings.Split(strings.TrimSpace(out), "\n")
   675  	lines = RemoveLinesForExistingElements(lines, existingContainers)
   676  	assert.Equal(c, len(lines), 2)
   677  
   678  	fields = strings.Fields(lines[0])
   679  	assert.Equal(c, fields[1], anonymousVolumeID)
   680  	fields = strings.Fields(lines[1])
   681  	assert.Equal(c, fields[1], "ps-volume-test")
   682  
   683  	// filter by bind mount source
   684  	out = cli.DockerCmd(c, "ps", "--format", "{{.Names}} {{.Mounts}}", "--filter", "volume="+bindMountSource).Stdout()
   685  
   686  	lines = strings.Split(strings.TrimSpace(out), "\n")
   687  	lines = RemoveLinesForExistingElements(lines, existingContainers)
   688  	assert.Equal(c, len(lines), 1)
   689  
   690  	fields = strings.Fields(lines[0])
   691  	assert.Equal(c, len(fields), 2)
   692  	assert.Equal(c, fields[0], "bind-mount-test")
   693  	assert.Equal(c, fields[1], bindMountSource)
   694  
   695  	// filter by bind mount destination
   696  	out = cli.DockerCmd(c, "ps", "--format", "{{.Names}} {{.Mounts}}", "--filter", "volume="+bindMountDestination).Stdout()
   697  
   698  	lines = strings.Split(strings.TrimSpace(out), "\n")
   699  	lines = RemoveLinesForExistingElements(lines, existingContainers)
   700  	assert.Equal(c, len(lines), 1)
   701  
   702  	fields = strings.Fields(lines[0])
   703  	assert.Equal(c, len(fields), 2)
   704  	assert.Equal(c, fields[0], "bind-mount-test")
   705  	assert.Equal(c, fields[1], bindMountSource)
   706  
   707  	// empty results filtering by unknown mount point
   708  	out = cli.DockerCmd(c, "ps", "--format", "{{.Names}} {{.Mounts}}", "--filter", "volume="+prefix+slash+"this-path-was-never-mounted").Stdout()
   709  	assert.Equal(c, len(strings.TrimSpace(out)), 0)
   710  }
   711  
   712  func (s *DockerCLIPsSuite) TestPsListContainersFilterNetwork(c *testing.T) {
   713  	existing := ExistingContainerIDs(c)
   714  
   715  	// TODO default network on Windows is not called "bridge", and creating a
   716  	// custom network fails on Windows fails with "Error response from daemon: plugin not found")
   717  	testRequires(c, DaemonIsLinux)
   718  
   719  	// create some containers
   720  	runSleepingContainer(c, "--net=bridge", "--name=onbridgenetwork")
   721  	runSleepingContainer(c, "--net=none", "--name=onnonenetwork")
   722  
   723  	// Filter docker ps on non existing network
   724  	out := cli.DockerCmd(c, "ps", "--filter", "network=doesnotexist").Stdout()
   725  	containerOut := strings.TrimSpace(out)
   726  	lines := strings.Split(containerOut, "\n")
   727  
   728  	// skip header
   729  	lines = lines[1:]
   730  
   731  	// ps output should have no containers
   732  	assert.Equal(c, len(RemoveLinesForExistingElements(lines, existing)), 0)
   733  
   734  	// Filter docker ps on network bridge
   735  	out = cli.DockerCmd(c, "ps", "--filter", "network=bridge").Stdout()
   736  	containerOut = strings.TrimSpace(out)
   737  
   738  	lines = strings.Split(containerOut, "\n")
   739  
   740  	// skip header
   741  	lines = lines[1:]
   742  
   743  	// ps output should have only one container
   744  	assert.Equal(c, len(RemoveLinesForExistingElements(lines, existing)), 1)
   745  
   746  	// Making sure onbridgenetwork is on the output
   747  	assert.Assert(c, strings.Contains(containerOut, "onbridgenetwork"), "Missing the container on network\n")
   748  	// Filter docker ps on networks bridge and none
   749  	out = cli.DockerCmd(c, "ps", "--filter", "network=bridge", "--filter", "network=none").Stdout()
   750  	containerOut = strings.TrimSpace(out)
   751  
   752  	lines = strings.Split(containerOut, "\n")
   753  
   754  	// skip header
   755  	lines = lines[1:]
   756  
   757  	// ps output should have both the containers
   758  	assert.Equal(c, len(RemoveLinesForExistingElements(lines, existing)), 2)
   759  
   760  	// Making sure onbridgenetwork and onnonenetwork is on the output
   761  	assert.Assert(c, strings.Contains(containerOut, "onnonenetwork"), "Missing the container on none network\n")
   762  	assert.Assert(c, strings.Contains(containerOut, "onbridgenetwork"), "Missing the container on bridge network\n")
   763  	nwID := cli.DockerCmd(c, "network", "inspect", "--format", "{{.ID}}", "bridge").Stdout()
   764  
   765  	// Filter by network ID
   766  	out = cli.DockerCmd(c, "ps", "--filter", "network="+nwID).Stdout()
   767  	containerOut = strings.TrimSpace(out)
   768  
   769  	assert.Assert(c, is.Contains(containerOut, "onbridgenetwork"))
   770  
   771  	// Filter by partial network ID
   772  	partialNwID := nwID[0:4]
   773  
   774  	out = cli.DockerCmd(c, "ps", "--filter", "network="+partialNwID).Stdout()
   775  	containerOut = strings.TrimSpace(out)
   776  
   777  	lines = strings.Split(containerOut, "\n")
   778  
   779  	// skip header
   780  	lines = lines[1:]
   781  
   782  	// ps output should have only one container
   783  	assert.Equal(c, len(RemoveLinesForExistingElements(lines, existing)), 1)
   784  
   785  	// Making sure onbridgenetwork is on the output
   786  	assert.Assert(c, strings.Contains(containerOut, "onbridgenetwork"), "Missing the container on network\n")
   787  }
   788  
   789  func (s *DockerCLIPsSuite) TestPsByOrder(c *testing.T) {
   790  	container1 := runSleepingContainer(c, "--name", "xyz-abc")
   791  	container2 := runSleepingContainer(c, "--name", "xyz-123")
   792  
   793  	runSleepingContainer(c, "--name", "789-abc")
   794  	runSleepingContainer(c, "--name", "789-123")
   795  
   796  	// Run multiple time should have the same result
   797  	out := cli.DockerCmd(c, "ps", "--no-trunc", "-q", "-f", "name=xyz").Combined()
   798  	assert.Equal(c, strings.TrimSpace(out), fmt.Sprintf("%s\n%s", container2, container1))
   799  
   800  	// Run multiple time should have the same result
   801  	out = cli.DockerCmd(c, "ps", "--no-trunc", "-q", "-f", "name=xyz").Combined()
   802  	assert.Equal(c, strings.TrimSpace(out), fmt.Sprintf("%s\n%s", container2, container1))
   803  }
   804  
   805  func (s *DockerCLIPsSuite) TestPsListContainersFilterPorts(c *testing.T) {
   806  	testRequires(c, DaemonIsLinux)
   807  	existingContainers := ExistingContainerIDs(c)
   808  
   809  	out := cli.DockerCmd(c, "run", "-d", "--publish=80", "busybox", "top").Stdout()
   810  	id1 := strings.TrimSpace(out)
   811  
   812  	out = cli.DockerCmd(c, "run", "-d", "--expose=8080", "busybox", "top").Stdout()
   813  	id2 := strings.TrimSpace(out)
   814  
   815  	out = cli.DockerCmd(c, "run", "-d", "-p", "1090:90", "busybox", "top").Stdout()
   816  	id3 := strings.TrimSpace(out)
   817  
   818  	out = cli.DockerCmd(c, "ps", "--no-trunc", "-q").Stdout()
   819  	assert.Assert(c, strings.Contains(strings.TrimSpace(out), id1))
   820  	assert.Assert(c, strings.Contains(strings.TrimSpace(out), id2))
   821  	assert.Assert(c, strings.Contains(strings.TrimSpace(out), id3))
   822  
   823  	out = cli.DockerCmd(c, "ps", "--no-trunc", "-q", "--filter", "publish=80-8080/udp").Stdout()
   824  	assert.Assert(c, strings.TrimSpace(out) != id1)
   825  	assert.Assert(c, strings.TrimSpace(out) != id2)
   826  	assert.Assert(c, strings.TrimSpace(out) != id3)
   827  
   828  	out = cli.DockerCmd(c, "ps", "--no-trunc", "-q", "--filter", "expose=8081").Stdout()
   829  	assert.Assert(c, strings.TrimSpace(out) != id1)
   830  	assert.Assert(c, strings.TrimSpace(out) != id2)
   831  	assert.Assert(c, strings.TrimSpace(out) != id3)
   832  
   833  	out = cli.DockerCmd(c, "ps", "--no-trunc", "-q", "--filter", "publish=80-81").Stdout()
   834  	assert.Assert(c, strings.TrimSpace(out) != id1)
   835  	assert.Assert(c, strings.TrimSpace(out) != id2)
   836  	assert.Assert(c, strings.TrimSpace(out) != id3)
   837  
   838  	out = cli.DockerCmd(c, "ps", "--no-trunc", "-q", "--filter", "expose=80/tcp").Stdout()
   839  	assert.Equal(c, strings.TrimSpace(out), id1)
   840  	assert.Assert(c, strings.TrimSpace(out) != id2)
   841  	assert.Assert(c, strings.TrimSpace(out) != id3)
   842  
   843  	out = cli.DockerCmd(c, "ps", "--no-trunc", "-q", "--filter", "publish=1090").Stdout()
   844  	assert.Assert(c, strings.TrimSpace(out) != id1)
   845  	assert.Assert(c, strings.TrimSpace(out) != id2)
   846  	assert.Equal(c, strings.TrimSpace(out), id3)
   847  
   848  	out = cli.DockerCmd(c, "ps", "--no-trunc", "-q", "--filter", "expose=8080/tcp").Stdout()
   849  	out = RemoveOutputForExistingElements(out, existingContainers)
   850  	assert.Assert(c, strings.TrimSpace(out) != id1)
   851  	assert.Equal(c, strings.TrimSpace(out), id2)
   852  	assert.Assert(c, strings.TrimSpace(out) != id3)
   853  }
   854  
   855  func (s *DockerCLIPsSuite) TestPsNotShowLinknamesOfDeletedContainer(c *testing.T) {
   856  	testRequires(c, DaemonIsLinux)
   857  	existingContainers := ExistingContainerNames(c)
   858  
   859  	cli.DockerCmd(c, "create", "--name=aaa", "busybox", "top")
   860  	cli.DockerCmd(c, "create", "--name=bbb", "--link=aaa", "busybox", "top")
   861  
   862  	out := cli.DockerCmd(c, "ps", "--no-trunc", "-a", "--format", "{{.Names}}").Stdout()
   863  	lines := strings.Split(strings.TrimSpace(out), "\n")
   864  	lines = RemoveLinesForExistingElements(lines, existingContainers)
   865  	expected := []string{"bbb", "aaa,bbb/aaa"}
   866  	var names []string
   867  	names = append(names, lines...)
   868  	assert.Assert(c, is.DeepEqual(names, expected), "Expected array with non-truncated names: %v, got: %v", expected, names)
   869  
   870  	cli.DockerCmd(c, "rm", "bbb")
   871  
   872  	out = cli.DockerCmd(c, "ps", "--no-trunc", "-a", "--format", "{{.Names}}").Stdout()
   873  	out = RemoveOutputForExistingElements(out, existingContainers)
   874  	assert.Equal(c, strings.TrimSpace(out), "aaa")
   875  }