github.com/rish1988/moby@v25.0.2+incompatible/client/request_test.go (about)

     1  package client // import "github.com/docker/docker/client"
     2  
     3  import (
     4  	"bytes"
     5  	"context"
     6  	"errors"
     7  	"fmt"
     8  	"io"
     9  	"math/rand"
    10  	"net/http"
    11  	"strings"
    12  	"testing"
    13  	"time"
    14  
    15  	"github.com/docker/docker/api/types/container"
    16  	"github.com/docker/docker/errdefs"
    17  	"gotest.tools/v3/assert"
    18  	is "gotest.tools/v3/assert/cmp"
    19  )
    20  
    21  // TestSetHostHeader should set fake host for local communications, set real host
    22  // for normal communications.
    23  func TestSetHostHeader(t *testing.T) {
    24  	const testEndpoint = "/test"
    25  	testCases := []struct {
    26  		host            string
    27  		expectedHost    string
    28  		expectedURLHost string
    29  	}{
    30  		{
    31  			host:            "unix:///var/run/docker.sock",
    32  			expectedHost:    DummyHost,
    33  			expectedURLHost: "/var/run/docker.sock",
    34  		},
    35  		{
    36  			host:            "npipe:////./pipe/docker_engine",
    37  			expectedHost:    DummyHost,
    38  			expectedURLHost: "//./pipe/docker_engine",
    39  		},
    40  		{
    41  			host:            "tcp://0.0.0.0:4243",
    42  			expectedHost:    "",
    43  			expectedURLHost: "0.0.0.0:4243",
    44  		},
    45  		{
    46  			host:            "tcp://localhost:4243",
    47  			expectedHost:    "",
    48  			expectedURLHost: "localhost:4243",
    49  		},
    50  	}
    51  
    52  	for _, tc := range testCases {
    53  		tc := tc
    54  		t.Run(tc.host, func(t *testing.T) {
    55  			hostURL, err := ParseHostURL(tc.host)
    56  			assert.Check(t, err)
    57  
    58  			client := &Client{
    59  				client: newMockClient(func(req *http.Request) (*http.Response, error) {
    60  					if !strings.HasPrefix(req.URL.Path, testEndpoint) {
    61  						return nil, fmt.Errorf("expected URL %q, got %q", testEndpoint, req.URL)
    62  					}
    63  					if req.Host != tc.expectedHost {
    64  						return nil, fmt.Errorf("wxpected host %q, got %q", tc.expectedHost, req.Host)
    65  					}
    66  					if req.URL.Host != tc.expectedURLHost {
    67  						return nil, fmt.Errorf("expected URL host %q, got %q", tc.expectedURLHost, req.URL.Host)
    68  					}
    69  					return &http.Response{
    70  						StatusCode: http.StatusOK,
    71  						Body:       io.NopCloser(bytes.NewReader([]byte(""))),
    72  					}, nil
    73  				}),
    74  
    75  				proto:    hostURL.Scheme,
    76  				addr:     hostURL.Host,
    77  				basePath: hostURL.Path,
    78  			}
    79  
    80  			_, err = client.sendRequest(context.Background(), http.MethodGet, testEndpoint, nil, nil, nil)
    81  			assert.Check(t, err)
    82  		})
    83  	}
    84  }
    85  
    86  // TestPlainTextError tests the server returning an error in plain text for
    87  // backwards compatibility with API versions <1.24. All other tests use
    88  // errors returned as JSON
    89  func TestPlainTextError(t *testing.T) {
    90  	client := &Client{
    91  		client: newMockClient(plainTextErrorMock(http.StatusInternalServerError, "Server error")),
    92  	}
    93  	_, err := client.ContainerList(context.Background(), container.ListOptions{})
    94  	assert.Check(t, is.ErrorType(err, errdefs.IsSystem))
    95  }
    96  
    97  func TestInfiniteError(t *testing.T) {
    98  	infinitR := rand.New(rand.NewSource(42))
    99  	client := &Client{
   100  		client: newMockClient(func(req *http.Request) (*http.Response, error) {
   101  			resp := &http.Response{
   102  				StatusCode: http.StatusInternalServerError,
   103  				Header:     http.Header{},
   104  				Body:       io.NopCloser(infinitR),
   105  			}
   106  			return resp, nil
   107  		}),
   108  	}
   109  
   110  	_, err := client.Ping(context.Background())
   111  	assert.Check(t, is.ErrorContains(err, "request returned Internal Server Error"))
   112  }
   113  
   114  func TestCanceledContext(t *testing.T) {
   115  	const testEndpoint = "/test"
   116  
   117  	client := &Client{
   118  		client: newMockClient(func(req *http.Request) (*http.Response, error) {
   119  			assert.Check(t, is.ErrorType(req.Context().Err(), context.Canceled))
   120  			return nil, context.Canceled
   121  		}),
   122  	}
   123  
   124  	ctx, cancel := context.WithCancel(context.Background())
   125  	cancel()
   126  
   127  	_, err := client.sendRequest(ctx, http.MethodGet, testEndpoint, nil, nil, nil)
   128  	assert.Check(t, is.ErrorType(err, errdefs.IsCancelled))
   129  	assert.Check(t, errors.Is(err, context.Canceled))
   130  }
   131  
   132  func TestDeadlineExceededContext(t *testing.T) {
   133  	const testEndpoint = "/test"
   134  
   135  	client := &Client{
   136  		client: newMockClient(func(req *http.Request) (*http.Response, error) {
   137  			assert.Check(t, is.ErrorType(req.Context().Err(), context.DeadlineExceeded))
   138  			return nil, context.DeadlineExceeded
   139  		}),
   140  	}
   141  
   142  	ctx, cancel := context.WithDeadline(context.Background(), time.Now())
   143  	defer cancel()
   144  
   145  	<-ctx.Done()
   146  
   147  	_, err := client.sendRequest(ctx, http.MethodGet, testEndpoint, nil, nil, nil)
   148  	assert.Check(t, is.ErrorType(err, errdefs.IsDeadline))
   149  	assert.Check(t, errors.Is(err, context.DeadlineExceeded))
   150  }