docker_cli_stats_test.go 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182
  1. package main
  2. import (
  3. "bufio"
  4. "os/exec"
  5. "regexp"
  6. "strings"
  7. "testing"
  8. "time"
  9. "github.com/docker/docker/integration-cli/cli"
  10. "gotest.tools/v3/assert"
  11. is "gotest.tools/v3/assert/cmp"
  12. )
  13. func (s *DockerSuite) TestStatsNoStream(c *testing.T) {
  14. // Windows does not support stats
  15. testRequires(c, DaemonIsLinux)
  16. out, _ := dockerCmd(c, "run", "-d", "busybox", "top")
  17. id := strings.TrimSpace(out)
  18. assert.NilError(c, waitRun(id))
  19. statsCmd := exec.Command(dockerBinary, "stats", "--no-stream", id)
  20. type output struct {
  21. out []byte
  22. err error
  23. }
  24. ch := make(chan output, 1)
  25. go func() {
  26. out, err := statsCmd.Output()
  27. ch <- output{out, err}
  28. }()
  29. select {
  30. case outerr := <-ch:
  31. assert.NilError(c, outerr.err, "Error running stats: %v", outerr.err)
  32. assert.Assert(c, is.Contains(string(outerr.out), id[:12]), "running container wasn't present in output")
  33. case <-time.After(3 * time.Second):
  34. statsCmd.Process.Kill()
  35. c.Fatalf("stats did not return immediately when not streaming")
  36. }
  37. }
  38. func (s *DockerSuite) TestStatsContainerNotFound(c *testing.T) {
  39. // Windows does not support stats
  40. testRequires(c, DaemonIsLinux)
  41. out, _, err := dockerCmdWithError("stats", "notfound")
  42. assert.ErrorContains(c, err, "")
  43. assert.Assert(c, is.Contains(out, "No such container: notfound"), "Expected to fail on not found container stats, got %q instead", out)
  44. out, _, err = dockerCmdWithError("stats", "--no-stream", "notfound")
  45. assert.ErrorContains(c, err, "")
  46. assert.Assert(c, is.Contains(out, "No such container: notfound"), "Expected to fail on not found container stats with --no-stream, got %q instead", out)
  47. }
  48. func (s *DockerSuite) TestStatsAllRunningNoStream(c *testing.T) {
  49. // Windows does not support stats
  50. testRequires(c, DaemonIsLinux)
  51. out, _ := dockerCmd(c, "run", "-d", "busybox", "top")
  52. id1 := strings.TrimSpace(out)[:12]
  53. assert.NilError(c, waitRun(id1))
  54. out, _ = dockerCmd(c, "run", "-d", "busybox", "top")
  55. id2 := strings.TrimSpace(out)[:12]
  56. assert.NilError(c, waitRun(id2))
  57. out, _ = dockerCmd(c, "run", "-d", "busybox", "top")
  58. id3 := strings.TrimSpace(out)[:12]
  59. assert.NilError(c, waitRun(id3))
  60. dockerCmd(c, "stop", id3)
  61. out, _ = dockerCmd(c, "stats", "--no-stream")
  62. if !strings.Contains(out, id1) || !strings.Contains(out, id2) {
  63. c.Fatalf("Expected stats output to contain both %s and %s, got %s", id1, id2, out)
  64. }
  65. if strings.Contains(out, id3) {
  66. c.Fatalf("Did not expect %s in stats, got %s", id3, out)
  67. }
  68. // check output contains real data, but not all zeros
  69. reg, _ := regexp.Compile("[1-9]+")
  70. // split output with "\n", outLines[1] is id2's output
  71. // outLines[2] is id1's output
  72. outLines := strings.Split(out, "\n")
  73. // check stat result of id2 contains real data
  74. realData := reg.Find([]byte(outLines[1][12:]))
  75. assert.Assert(c, realData != nil, "stat result are empty: %s", out)
  76. // check stat result of id1 contains real data
  77. realData = reg.Find([]byte(outLines[2][12:]))
  78. assert.Assert(c, realData != nil, "stat result are empty: %s", out)
  79. }
  80. func (s *DockerSuite) TestStatsAllNoStream(c *testing.T) {
  81. // Windows does not support stats
  82. testRequires(c, DaemonIsLinux)
  83. out, _ := dockerCmd(c, "run", "-d", "busybox", "top")
  84. id1 := strings.TrimSpace(out)[:12]
  85. assert.NilError(c, waitRun(id1))
  86. dockerCmd(c, "stop", id1)
  87. out, _ = dockerCmd(c, "run", "-d", "busybox", "top")
  88. id2 := strings.TrimSpace(out)[:12]
  89. assert.NilError(c, waitRun(id2))
  90. out, _ = dockerCmd(c, "stats", "--all", "--no-stream")
  91. if !strings.Contains(out, id1) || !strings.Contains(out, id2) {
  92. c.Fatalf("Expected stats output to contain both %s and %s, got %s", id1, id2, out)
  93. }
  94. // check output contains real data, but not all zeros
  95. reg, _ := regexp.Compile("[1-9]+")
  96. // split output with "\n", outLines[1] is id2's output
  97. outLines := strings.Split(out, "\n")
  98. // check stat result of id2 contains real data
  99. realData := reg.Find([]byte(outLines[1][12:]))
  100. assert.Assert(c, realData != nil, "stat result of %s is empty: %s", id2, out)
  101. // check stat result of id1 contains all zero
  102. realData = reg.Find([]byte(outLines[2][12:]))
  103. assert.Assert(c, realData == nil, "stat result of %s should be empty : %s", id1, out)
  104. }
  105. func (s *DockerSuite) TestStatsAllNewContainersAdded(c *testing.T) {
  106. // Windows does not support stats
  107. testRequires(c, DaemonIsLinux)
  108. id := make(chan string)
  109. addedChan := make(chan struct{})
  110. runSleepingContainer(c, "-d")
  111. statsCmd := exec.Command(dockerBinary, "stats")
  112. stdout, err := statsCmd.StdoutPipe()
  113. assert.NilError(c, err)
  114. assert.NilError(c, statsCmd.Start())
  115. go statsCmd.Wait()
  116. defer statsCmd.Process.Kill()
  117. go func() {
  118. containerID := <-id
  119. matchID := regexp.MustCompile(containerID)
  120. scanner := bufio.NewScanner(stdout)
  121. for scanner.Scan() {
  122. switch {
  123. case matchID.MatchString(scanner.Text()):
  124. close(addedChan)
  125. return
  126. }
  127. }
  128. }()
  129. out := runSleepingContainer(c, "-d")
  130. assert.NilError(c, waitRun(strings.TrimSpace(out)))
  131. id <- strings.TrimSpace(out)[:12]
  132. select {
  133. case <-time.After(30 * time.Second):
  134. c.Fatal("failed to observe new container created added to stats")
  135. case <-addedChan:
  136. // ignore, done
  137. }
  138. }
  139. func (s *DockerSuite) TestStatsFormatAll(c *testing.T) {
  140. // Windows does not support stats
  141. testRequires(c, DaemonIsLinux)
  142. cli.DockerCmd(c, "run", "-d", "--name=RunningOne", "busybox", "top")
  143. cli.WaitRun(c, "RunningOne")
  144. cli.DockerCmd(c, "run", "-d", "--name=ExitedOne", "busybox", "top")
  145. cli.DockerCmd(c, "stop", "ExitedOne")
  146. cli.WaitExited(c, "ExitedOne", 5*time.Second)
  147. out := cli.DockerCmd(c, "stats", "--no-stream", "--format", "{{.Name}}").Combined()
  148. assert.Assert(c, is.Contains(out, "RunningOne"))
  149. assert.Assert(c, !strings.Contains(out, "ExitedOne"))
  150. out = cli.DockerCmd(c, "stats", "--all", "--no-stream", "--format", "{{.Name}}").Combined()
  151. assert.Assert(c, is.Contains(out, "RunningOne"))
  152. assert.Assert(c, is.Contains(out, "ExitedOne"))
  153. }