docker_cli_history_test.go 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160
  1. package main
  2. import (
  3. "fmt"
  4. "os/exec"
  5. "regexp"
  6. "strconv"
  7. "strings"
  8. "github.com/go-check/check"
  9. )
  10. // This is a heisen-test. Because the created timestamp of images and the behavior of
  11. // sort is not predictable it doesn't always fail.
  12. func (s *DockerSuite) TestBuildHistory(c *check.C) {
  13. name := "testbuildhistory"
  14. _, err := buildImage(name, `FROM busybox
  15. RUN echo "A"
  16. RUN echo "B"
  17. RUN echo "C"
  18. RUN echo "D"
  19. RUN echo "E"
  20. RUN echo "F"
  21. RUN echo "G"
  22. RUN echo "H"
  23. RUN echo "I"
  24. RUN echo "J"
  25. RUN echo "K"
  26. RUN echo "L"
  27. RUN echo "M"
  28. RUN echo "N"
  29. RUN echo "O"
  30. RUN echo "P"
  31. RUN echo "Q"
  32. RUN echo "R"
  33. RUN echo "S"
  34. RUN echo "T"
  35. RUN echo "U"
  36. RUN echo "V"
  37. RUN echo "W"
  38. RUN echo "X"
  39. RUN echo "Y"
  40. RUN echo "Z"`,
  41. true)
  42. if err != nil {
  43. c.Fatal(err)
  44. }
  45. out, exitCode, err := runCommandWithOutput(exec.Command(dockerBinary, "history", "testbuildhistory"))
  46. if err != nil || exitCode != 0 {
  47. c.Fatalf("failed to get image history: %s, %v", out, err)
  48. }
  49. actualValues := strings.Split(out, "\n")[1:27]
  50. expectedValues := [26]string{"Z", "Y", "X", "W", "V", "U", "T", "S", "R", "Q", "P", "O", "N", "M", "L", "K", "J", "I", "H", "G", "F", "E", "D", "C", "B", "A"}
  51. for i := 0; i < 26; i++ {
  52. echoValue := fmt.Sprintf("echo \"%s\"", expectedValues[i])
  53. actualValue := actualValues[i]
  54. if !strings.Contains(actualValue, echoValue) {
  55. c.Fatalf("Expected layer \"%s\", but was: %s", expectedValues[i], actualValue)
  56. }
  57. }
  58. }
  59. func (s *DockerSuite) TestHistoryExistentImage(c *check.C) {
  60. historyCmd := exec.Command(dockerBinary, "history", "busybox")
  61. _, exitCode, err := runCommandWithOutput(historyCmd)
  62. if err != nil || exitCode != 0 {
  63. c.Fatal("failed to get image history")
  64. }
  65. }
  66. func (s *DockerSuite) TestHistoryNonExistentImage(c *check.C) {
  67. historyCmd := exec.Command(dockerBinary, "history", "testHistoryNonExistentImage")
  68. _, exitCode, err := runCommandWithOutput(historyCmd)
  69. if err == nil || exitCode == 0 {
  70. c.Fatal("history on a non-existent image didn't result in a non-zero exit status")
  71. }
  72. }
  73. func (s *DockerSuite) TestHistoryImageWithComment(c *check.C) {
  74. name := "testhistoryimagewithcomment"
  75. // make a image through docker commit <container id> [ -m messages ]
  76. //runCmd := exec.Command(dockerBinary, "run", "-i", "-a", "stdin", "busybox", "echo", "foo")
  77. runCmd := exec.Command(dockerBinary, "run", "--name", name, "busybox", "true")
  78. out, _, err := runCommandWithOutput(runCmd)
  79. if err != nil {
  80. c.Fatalf("failed to run container: %s, %v", out, err)
  81. }
  82. waitCmd := exec.Command(dockerBinary, "wait", name)
  83. if out, _, err := runCommandWithOutput(waitCmd); err != nil {
  84. c.Fatalf("error thrown while waiting for container: %s, %v", out, err)
  85. }
  86. comment := "This_is_a_comment"
  87. commitCmd := exec.Command(dockerBinary, "commit", "-m="+comment, name, name)
  88. if out, _, err := runCommandWithOutput(commitCmd); err != nil {
  89. c.Fatalf("failed to commit container to image: %s, %v", out, err)
  90. }
  91. // test docker history <image id> to check comment messages
  92. historyCmd := exec.Command(dockerBinary, "history", name)
  93. out, exitCode, err := runCommandWithOutput(historyCmd)
  94. if err != nil || exitCode != 0 {
  95. c.Fatalf("failed to get image history: %s, %v", out, err)
  96. }
  97. outputTabs := strings.Fields(strings.Split(out, "\n")[1])
  98. //outputTabs := regexp.MustCompile(" +").Split(outputLine, -1)
  99. actualValue := outputTabs[len(outputTabs)-1]
  100. if !strings.Contains(actualValue, comment) {
  101. c.Fatalf("Expected comments %q, but found %q", comment, actualValue)
  102. }
  103. }
  104. func (s *DockerSuite) TestHistoryHumanOptionFalse(c *check.C) {
  105. out, _, _ := runCommandWithOutput(exec.Command(dockerBinary, "history", "--human=false", "busybox"))
  106. lines := strings.Split(out, "\n")
  107. sizeColumnRegex, _ := regexp.Compile("SIZE +")
  108. indices := sizeColumnRegex.FindStringIndex(lines[0])
  109. startIndex := indices[0]
  110. endIndex := indices[1]
  111. for i := 1; i < len(lines)-1; i++ {
  112. if endIndex > len(lines[i]) {
  113. endIndex = len(lines[i])
  114. }
  115. sizeString := lines[i][startIndex:endIndex]
  116. if _, err := strconv.Atoi(strings.TrimSpace(sizeString)); err != nil {
  117. c.Fatalf("The size '%s' was not an Integer", sizeString)
  118. }
  119. }
  120. }
  121. func (s *DockerSuite) TestHistoryHumanOptionTrue(c *check.C) {
  122. out, _, _ := runCommandWithOutput(exec.Command(dockerBinary, "history", "--human=true", "busybox"))
  123. lines := strings.Split(out, "\n")
  124. sizeColumnRegex, _ := regexp.Compile("SIZE +")
  125. humanSizeRegex, _ := regexp.Compile("^\\d+.*B$") // Matches human sizes like 10 MB, 3.2 KB, etc
  126. indices := sizeColumnRegex.FindStringIndex(lines[0])
  127. startIndex := indices[0]
  128. endIndex := indices[1]
  129. for i := 1; i < len(lines)-1; i++ {
  130. if endIndex > len(lines[i]) {
  131. endIndex = len(lines[i])
  132. }
  133. sizeString := lines[i][startIndex:endIndex]
  134. if matchSuccess := humanSizeRegex.MatchString(strings.TrimSpace(sizeString)); !matchSuccess {
  135. c.Fatalf("The size '%s' was not in human format", sizeString)
  136. }
  137. }
  138. }