commands_test.go 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  1. package docker
  2. import (
  3. "bufio"
  4. "fmt"
  5. "github.com/dotcloud/docker/utils"
  6. "io"
  7. "io/ioutil"
  8. "strings"
  9. "testing"
  10. "time"
  11. )
  12. func closeWrap(args ...io.Closer) error {
  13. e := false
  14. ret := fmt.Errorf("Error closing elements")
  15. for _, c := range args {
  16. if err := c.Close(); err != nil {
  17. e = true
  18. ret = fmt.Errorf("%s\n%s", ret, err)
  19. }
  20. }
  21. if e {
  22. return ret
  23. }
  24. return nil
  25. }
  26. func setTimeout(t *testing.T, msg string, d time.Duration, f func()) {
  27. c := make(chan bool)
  28. // Make sure we are not too long
  29. go func() {
  30. time.Sleep(d)
  31. c <- true
  32. }()
  33. go func() {
  34. f()
  35. c <- false
  36. }()
  37. if <-c && msg != "" {
  38. t.Fatal(msg)
  39. }
  40. }
  41. func assertPipe(input, output string, r io.Reader, w io.Writer, count int) error {
  42. for i := 0; i < count; i++ {
  43. if _, err := w.Write([]byte(input)); err != nil {
  44. return err
  45. }
  46. o, err := bufio.NewReader(r).ReadString('\n')
  47. if err != nil {
  48. return err
  49. }
  50. if strings.Trim(o, " \r\n") != output {
  51. return fmt.Errorf("Unexpected output. Expected [%s], received [%s]", output, o)
  52. }
  53. }
  54. return nil
  55. }
  56. // TestRunHostname checks that 'docker run -h' correctly sets a custom hostname
  57. func TestRunHostname(t *testing.T) {
  58. stdout, stdoutPipe := io.Pipe()
  59. cli := NewDockerCli(nil, stdoutPipe, ioutil.Discard, testDaemonProto, testDaemonAddr)
  60. defer cleanup(globalRuntime)
  61. c := make(chan struct{})
  62. go func() {
  63. defer close(c)
  64. if err := cli.CmdRun("-h", "foobar", unitTestImageID, "hostname"); err != nil {
  65. t.Fatal(err)
  66. }
  67. }()
  68. utils.Debugf("--")
  69. setTimeout(t, "Reading command output time out", 2*time.Second, func() {
  70. cmdOutput, err := bufio.NewReader(stdout).ReadString('\n')
  71. if err != nil {
  72. t.Fatal(err)
  73. }
  74. if cmdOutput != "foobar\n" {
  75. t.Fatalf("'hostname' should display '%s', not '%s'", "foobar\n", cmdOutput)
  76. }
  77. })
  78. setTimeout(t, "CmdRun timed out", 5*time.Second, func() {
  79. <-c
  80. })
  81. }
  82. // TestAttachStdin checks attaching to stdin without stdout and stderr.
  83. // 'docker run -i -a stdin' should sends the client's stdin to the command,
  84. // then detach from it and print the container id.
  85. func TestRunAttachStdin(t *testing.T) {
  86. stdin, stdinPipe := io.Pipe()
  87. stdout, stdoutPipe := io.Pipe()
  88. cli := NewDockerCli(stdin, stdoutPipe, ioutil.Discard, testDaemonProto, testDaemonAddr)
  89. defer cleanup(globalRuntime)
  90. ch := make(chan struct{})
  91. go func() {
  92. defer close(ch)
  93. cli.CmdRun("-i", "-a", "stdin", unitTestImageID, "sh", "-c", "echo hello && cat")
  94. }()
  95. // Send input to the command, close stdin
  96. setTimeout(t, "Write timed out", 10*time.Second, func() {
  97. if _, err := stdinPipe.Write([]byte("hi there\n")); err != nil {
  98. t.Fatal(err)
  99. }
  100. if err := stdinPipe.Close(); err != nil {
  101. t.Fatal(err)
  102. }
  103. })
  104. container := globalRuntime.List()[0]
  105. // Check output
  106. setTimeout(t, "Reading command output time out", 10*time.Second, func() {
  107. cmdOutput, err := bufio.NewReader(stdout).ReadString('\n')
  108. if err != nil {
  109. t.Fatal(err)
  110. }
  111. if cmdOutput != container.ShortID()+"\n" {
  112. t.Fatalf("Wrong output: should be '%s', not '%s'\n", container.ShortID()+"\n", cmdOutput)
  113. }
  114. })
  115. // wait for CmdRun to return
  116. setTimeout(t, "Waiting for CmdRun timed out", 5*time.Second, func() {
  117. // Unblock hijack end
  118. stdout.Read([]byte{})
  119. <-ch
  120. })
  121. setTimeout(t, "Waiting for command to exit timed out", 5*time.Second, func() {
  122. container.Wait()
  123. })
  124. // Check logs
  125. if cmdLogs, err := container.ReadLog("json"); err != nil {
  126. t.Fatal(err)
  127. } else {
  128. if output, err := ioutil.ReadAll(cmdLogs); err != nil {
  129. t.Fatal(err)
  130. } else {
  131. expectedLogs := []string{"{\"log\":\"hello\\n\",\"stream\":\"stdout\"", "{\"log\":\"hi there\\n\",\"stream\":\"stdout\""}
  132. for _, expectedLog := range expectedLogs {
  133. if !strings.Contains(string(output), expectedLog) {
  134. t.Fatalf("Unexpected logs: should contains '%s', it is not '%s'\n", expectedLog, output)
  135. }
  136. }
  137. }
  138. }
  139. }