container_wait_test.go 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172
  1. package client // import "github.com/docker/docker/client"
  2. import (
  3. "bytes"
  4. "context"
  5. "encoding/json"
  6. "fmt"
  7. "io"
  8. "log"
  9. "net/http"
  10. "strings"
  11. "syscall"
  12. "testing"
  13. "testing/iotest"
  14. "time"
  15. "github.com/docker/docker/api/types/container"
  16. "github.com/docker/docker/errdefs"
  17. "github.com/pkg/errors"
  18. "gotest.tools/v3/assert"
  19. is "gotest.tools/v3/assert/cmp"
  20. )
  21. func TestContainerWaitError(t *testing.T) {
  22. client := &Client{
  23. client: newMockClient(errorMock(http.StatusInternalServerError, "Server error")),
  24. }
  25. resultC, errC := client.ContainerWait(context.Background(), "nothing", "")
  26. select {
  27. case result := <-resultC:
  28. t.Fatalf("expected to not get a wait result, got %d", result.StatusCode)
  29. case err := <-errC:
  30. assert.Check(t, is.ErrorType(err, errdefs.IsSystem))
  31. }
  32. }
  33. func TestContainerWait(t *testing.T) {
  34. expectedURL := "/containers/container_id/wait"
  35. client := &Client{
  36. client: newMockClient(func(req *http.Request) (*http.Response, error) {
  37. if !strings.HasPrefix(req.URL.Path, expectedURL) {
  38. return nil, fmt.Errorf("Expected URL '%s', got '%s'", expectedURL, req.URL)
  39. }
  40. b, err := json.Marshal(container.WaitResponse{
  41. StatusCode: 15,
  42. })
  43. if err != nil {
  44. return nil, err
  45. }
  46. return &http.Response{
  47. StatusCode: http.StatusOK,
  48. Body: io.NopCloser(bytes.NewReader(b)),
  49. }, nil
  50. }),
  51. }
  52. resultC, errC := client.ContainerWait(context.Background(), "container_id", "")
  53. select {
  54. case err := <-errC:
  55. t.Fatal(err)
  56. case result := <-resultC:
  57. if result.StatusCode != 15 {
  58. t.Fatalf("expected a status code equal to '15', got %d", result.StatusCode)
  59. }
  60. }
  61. }
  62. func TestContainerWaitProxyInterrupt(t *testing.T) {
  63. expectedURL := "/v1.30/containers/container_id/wait"
  64. msg := "copying response body from Docker: unexpected EOF"
  65. client := &Client{
  66. version: "1.30",
  67. client: newMockClient(func(req *http.Request) (*http.Response, error) {
  68. if !strings.HasPrefix(req.URL.Path, expectedURL) {
  69. return nil, fmt.Errorf("Expected URL '%s', got '%s'", expectedURL, req.URL)
  70. }
  71. return &http.Response{
  72. StatusCode: http.StatusOK,
  73. Body: io.NopCloser(strings.NewReader(msg)),
  74. }, nil
  75. }),
  76. }
  77. resultC, errC := client.ContainerWait(context.Background(), "container_id", "")
  78. select {
  79. case err := <-errC:
  80. if !strings.Contains(err.Error(), msg) {
  81. t.Fatalf("Expected: %s, Actual: %s", msg, err.Error())
  82. }
  83. case result := <-resultC:
  84. t.Fatalf("Unexpected result: %v", result)
  85. }
  86. }
  87. func TestContainerWaitProxyInterruptLong(t *testing.T) {
  88. expectedURL := "/v1.30/containers/container_id/wait"
  89. msg := strings.Repeat("x", containerWaitErrorMsgLimit*5)
  90. client := &Client{
  91. version: "1.30",
  92. client: newMockClient(func(req *http.Request) (*http.Response, error) {
  93. if !strings.HasPrefix(req.URL.Path, expectedURL) {
  94. return nil, fmt.Errorf("Expected URL '%s', got '%s'", expectedURL, req.URL)
  95. }
  96. return &http.Response{
  97. StatusCode: http.StatusOK,
  98. Body: io.NopCloser(strings.NewReader(msg)),
  99. }, nil
  100. }),
  101. }
  102. resultC, errC := client.ContainerWait(context.Background(), "container_id", "")
  103. select {
  104. case err := <-errC:
  105. // LimitReader limiting isn't exact, because of how the Readers do chunking.
  106. if len(err.Error()) > containerWaitErrorMsgLimit*2 {
  107. t.Fatalf("Expected error to be limited around %d, actual length: %d", containerWaitErrorMsgLimit, len(err.Error()))
  108. }
  109. case result := <-resultC:
  110. t.Fatalf("Unexpected result: %v", result)
  111. }
  112. }
  113. func TestContainerWaitErrorHandling(t *testing.T) {
  114. for _, test := range []struct {
  115. name string
  116. rdr io.Reader
  117. exp error
  118. }{
  119. {name: "invalid json", rdr: strings.NewReader(`{]`), exp: errors.New("{]")},
  120. {name: "context canceled", rdr: iotest.ErrReader(context.Canceled), exp: context.Canceled},
  121. {name: "context deadline exceeded", rdr: iotest.ErrReader(context.DeadlineExceeded), exp: context.DeadlineExceeded},
  122. {name: "connection reset", rdr: iotest.ErrReader(syscall.ECONNRESET), exp: syscall.ECONNRESET},
  123. } {
  124. t.Run(test.name, func(t *testing.T) {
  125. ctx, cancel := context.WithCancel(context.Background())
  126. defer cancel()
  127. client := &Client{
  128. version: "1.30",
  129. client: newMockClient(func(req *http.Request) (*http.Response, error) {
  130. return &http.Response{
  131. StatusCode: http.StatusOK,
  132. Body: io.NopCloser(test.rdr),
  133. }, nil
  134. }),
  135. }
  136. resultC, errC := client.ContainerWait(ctx, "container_id", "")
  137. select {
  138. case err := <-errC:
  139. if err.Error() != test.exp.Error() {
  140. t.Fatalf("ContainerWait() errC = %v; want %v", err, test.exp)
  141. }
  142. return
  143. case result := <-resultC:
  144. t.Fatalf("expected to not get a wait result, got %d", result.StatusCode)
  145. return
  146. }
  147. // Unexpected - we should not reach this line
  148. })
  149. }
  150. }
  151. func ExampleClient_ContainerWait_withTimeout() {
  152. ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
  153. defer cancel()
  154. client, _ := NewClientWithOpts(FromEnv)
  155. _, errC := client.ContainerWait(ctx, "container_id", "")
  156. if err := <-errC; err != nil {
  157. log.Fatal(err)
  158. }
  159. }