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  }