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