github.com/jwhonce/docker@v0.6.7-0.20190327063223-da823cf3a5a3/client/ping_test.go (about)

     1  package client // import "github.com/docker/docker/client"
     2  
     3  import (
     4  	"context"
     5  	"errors"
     6  	"io/ioutil"
     7  	"net/http"
     8  	"strings"
     9  	"testing"
    10  
    11  	"gotest.tools/assert"
    12  	is "gotest.tools/assert/cmp"
    13  )
    14  
    15  // TestPingFail tests that when a server sends a non-successful response that we
    16  // can still grab API details, when set.
    17  // Some of this is just exercising the code paths to make sure there are no
    18  // panics.
    19  func TestPingFail(t *testing.T) {
    20  	var withHeader bool
    21  	client := &Client{
    22  		client: newMockClient(func(req *http.Request) (*http.Response, error) {
    23  			resp := &http.Response{StatusCode: http.StatusInternalServerError}
    24  			if withHeader {
    25  				resp.Header = http.Header{}
    26  				resp.Header.Set("API-Version", "awesome")
    27  				resp.Header.Set("Docker-Experimental", "true")
    28  			}
    29  			resp.Body = ioutil.NopCloser(strings.NewReader("some error with the server"))
    30  			return resp, nil
    31  		}),
    32  	}
    33  
    34  	ping, err := client.Ping(context.Background())
    35  	assert.ErrorContains(t, err, "some error with the server")
    36  	assert.Check(t, is.Equal(false, ping.Experimental))
    37  	assert.Check(t, is.Equal("", ping.APIVersion))
    38  
    39  	withHeader = true
    40  	ping2, err := client.Ping(context.Background())
    41  	assert.ErrorContains(t, err, "some error with the server")
    42  	assert.Check(t, is.Equal(true, ping2.Experimental))
    43  	assert.Check(t, is.Equal("awesome", ping2.APIVersion))
    44  }
    45  
    46  // TestPingWithError tests the case where there is a protocol error in the ping.
    47  // This test is mostly just testing that there are no panics in this code path.
    48  func TestPingWithError(t *testing.T) {
    49  	client := &Client{
    50  		client: newMockClient(func(req *http.Request) (*http.Response, error) {
    51  			resp := &http.Response{StatusCode: http.StatusInternalServerError}
    52  			resp.Header = http.Header{}
    53  			resp.Header.Set("API-Version", "awesome")
    54  			resp.Header.Set("Docker-Experimental", "true")
    55  			resp.Body = ioutil.NopCloser(strings.NewReader("some error with the server"))
    56  			return resp, errors.New("some error")
    57  		}),
    58  	}
    59  
    60  	ping, err := client.Ping(context.Background())
    61  	assert.ErrorContains(t, err, "some error")
    62  	assert.Check(t, is.Equal(false, ping.Experimental))
    63  	assert.Check(t, is.Equal("", ping.APIVersion))
    64  }
    65  
    66  // TestPingSuccess tests that we are able to get the expected API headers/ping
    67  // details on success.
    68  func TestPingSuccess(t *testing.T) {
    69  	client := &Client{
    70  		client: newMockClient(func(req *http.Request) (*http.Response, error) {
    71  			resp := &http.Response{StatusCode: http.StatusOK}
    72  			resp.Header = http.Header{}
    73  			resp.Header.Set("API-Version", "awesome")
    74  			resp.Header.Set("Docker-Experimental", "true")
    75  			resp.Body = ioutil.NopCloser(strings.NewReader("OK"))
    76  			return resp, nil
    77  		}),
    78  	}
    79  	ping, err := client.Ping(context.Background())
    80  	assert.NilError(t, err)
    81  	assert.Check(t, is.Equal(true, ping.Experimental))
    82  	assert.Check(t, is.Equal("awesome", ping.APIVersion))
    83  }
    84  
    85  // TestPingHeadFallback tests that the client falls back to GET if HEAD fails.
    86  func TestPingHeadFallback(t *testing.T) {
    87  	tests := []struct {
    88  		status   int
    89  		expected string
    90  	}{
    91  		{
    92  			status:   http.StatusOK,
    93  			expected: "HEAD",
    94  		},
    95  		{
    96  			status:   http.StatusInternalServerError,
    97  			expected: "HEAD",
    98  		},
    99  		{
   100  			status:   http.StatusNotFound,
   101  			expected: "HEAD, GET",
   102  		},
   103  		{
   104  			status:   http.StatusMethodNotAllowed,
   105  			expected: "HEAD, GET",
   106  		},
   107  	}
   108  
   109  	for _, tc := range tests {
   110  		tc := tc
   111  		t.Run(http.StatusText(tc.status), func(t *testing.T) {
   112  			var reqs []string
   113  			client := &Client{
   114  				client: newMockClient(func(req *http.Request) (*http.Response, error) {
   115  					reqs = append(reqs, req.Method)
   116  					resp := &http.Response{StatusCode: http.StatusOK}
   117  					if req.Method == http.MethodHead {
   118  						resp.StatusCode = tc.status
   119  					}
   120  					resp.Header = http.Header{}
   121  					resp.Header.Add("API-Version", strings.Join(reqs, ", "))
   122  					return resp, nil
   123  				}),
   124  			}
   125  			ping, _ := client.Ping(context.Background())
   126  			assert.Check(t, is.Equal(ping.APIVersion, tc.expected))
   127  		})
   128  	}
   129  }