github.com/rhatdan/docker@v0.7.7-0.20180119204836-47a0dcbcd20a/pkg/plugins/client_test.go (about)

     1  package plugins
     2  
     3  import (
     4  	"bytes"
     5  	"encoding/json"
     6  	"io"
     7  	"net/http"
     8  	"net/http/httptest"
     9  	"net/url"
    10  	"strings"
    11  	"testing"
    12  	"time"
    13  
    14  	"github.com/docker/docker/pkg/plugins/transport"
    15  	"github.com/docker/go-connections/tlsconfig"
    16  	"github.com/stretchr/testify/assert"
    17  )
    18  
    19  var (
    20  	mux    *http.ServeMux
    21  	server *httptest.Server
    22  )
    23  
    24  func setupRemotePluginServer() string {
    25  	mux = http.NewServeMux()
    26  	server = httptest.NewServer(mux)
    27  	return server.URL
    28  }
    29  
    30  func teardownRemotePluginServer() {
    31  	if server != nil {
    32  		server.Close()
    33  	}
    34  }
    35  
    36  func TestFailedConnection(t *testing.T) {
    37  	c, _ := NewClient("tcp://127.0.0.1:1", &tlsconfig.Options{InsecureSkipVerify: true})
    38  	_, err := c.callWithRetry("Service.Method", nil, false)
    39  	if err == nil {
    40  		t.Fatal("Unexpected successful connection")
    41  	}
    42  }
    43  
    44  func TestFailOnce(t *testing.T) {
    45  	addr := setupRemotePluginServer()
    46  	defer teardownRemotePluginServer()
    47  
    48  	failed := false
    49  	mux.HandleFunc("/Test.FailOnce", func(w http.ResponseWriter, r *http.Request) {
    50  		if !failed {
    51  			failed = true
    52  			panic("Plugin not ready")
    53  		}
    54  	})
    55  
    56  	c, _ := NewClient(addr, &tlsconfig.Options{InsecureSkipVerify: true})
    57  	b := strings.NewReader("body")
    58  	_, err := c.callWithRetry("Test.FailOnce", b, true)
    59  	if err != nil {
    60  		t.Fatal(err)
    61  	}
    62  }
    63  
    64  func TestEchoInputOutput(t *testing.T) {
    65  	addr := setupRemotePluginServer()
    66  	defer teardownRemotePluginServer()
    67  
    68  	m := Manifest{[]string{"VolumeDriver", "NetworkDriver"}}
    69  
    70  	mux.HandleFunc("/Test.Echo", func(w http.ResponseWriter, r *http.Request) {
    71  		if r.Method != "POST" {
    72  			t.Fatalf("Expected POST, got %s\n", r.Method)
    73  		}
    74  
    75  		header := w.Header()
    76  		header.Set("Content-Type", transport.VersionMimetype)
    77  
    78  		io.Copy(w, r.Body)
    79  	})
    80  
    81  	c, _ := NewClient(addr, &tlsconfig.Options{InsecureSkipVerify: true})
    82  	var output Manifest
    83  	err := c.Call("Test.Echo", m, &output)
    84  	if err != nil {
    85  		t.Fatal(err)
    86  	}
    87  
    88  	assert.Equal(t, m, output)
    89  	err = c.Call("Test.Echo", nil, nil)
    90  	if err != nil {
    91  		t.Fatal(err)
    92  	}
    93  }
    94  
    95  func TestBackoff(t *testing.T) {
    96  	cases := []struct {
    97  		retries    int
    98  		expTimeOff time.Duration
    99  	}{
   100  		{0, time.Duration(1)},
   101  		{1, time.Duration(2)},
   102  		{2, time.Duration(4)},
   103  		{4, time.Duration(16)},
   104  		{6, time.Duration(30)},
   105  		{10, time.Duration(30)},
   106  	}
   107  
   108  	for _, c := range cases {
   109  		s := c.expTimeOff * time.Second
   110  		if d := backoff(c.retries); d != s {
   111  			t.Fatalf("Retry %v, expected %v, was %v\n", c.retries, s, d)
   112  		}
   113  	}
   114  }
   115  
   116  func TestAbortRetry(t *testing.T) {
   117  	cases := []struct {
   118  		timeOff  time.Duration
   119  		expAbort bool
   120  	}{
   121  		{time.Duration(1), false},
   122  		{time.Duration(2), false},
   123  		{time.Duration(10), false},
   124  		{time.Duration(30), true},
   125  		{time.Duration(40), true},
   126  	}
   127  
   128  	for _, c := range cases {
   129  		s := c.timeOff * time.Second
   130  		if a := abort(time.Now(), s); a != c.expAbort {
   131  			t.Fatalf("Duration %v, expected %v, was %v\n", c.timeOff, s, a)
   132  		}
   133  	}
   134  }
   135  
   136  func TestClientScheme(t *testing.T) {
   137  	cases := map[string]string{
   138  		"tcp://127.0.0.1:8080":          "http",
   139  		"unix:///usr/local/plugins/foo": "http",
   140  		"http://127.0.0.1:8080":         "http",
   141  		"https://127.0.0.1:8080":        "https",
   142  	}
   143  
   144  	for addr, scheme := range cases {
   145  		u, err := url.Parse(addr)
   146  		if err != nil {
   147  			t.Fatal(err)
   148  		}
   149  		s := httpScheme(u)
   150  
   151  		if s != scheme {
   152  			t.Fatalf("URL scheme mismatch, expected %s, got %s", scheme, s)
   153  		}
   154  	}
   155  }
   156  
   157  func TestNewClientWithTimeout(t *testing.T) {
   158  	addr := setupRemotePluginServer()
   159  	defer teardownRemotePluginServer()
   160  
   161  	m := Manifest{[]string{"VolumeDriver", "NetworkDriver"}}
   162  
   163  	mux.HandleFunc("/Test.Echo", func(w http.ResponseWriter, r *http.Request) {
   164  		time.Sleep(time.Duration(600) * time.Millisecond)
   165  		io.Copy(w, r.Body)
   166  	})
   167  
   168  	// setting timeout of 500ms
   169  	timeout := time.Duration(500) * time.Millisecond
   170  	c, _ := NewClientWithTimeout(addr, &tlsconfig.Options{InsecureSkipVerify: true}, timeout)
   171  	var output Manifest
   172  	err := c.Call("Test.Echo", m, &output)
   173  	if err == nil {
   174  		t.Fatal("Expected timeout error")
   175  	}
   176  }
   177  
   178  func TestClientStream(t *testing.T) {
   179  	addr := setupRemotePluginServer()
   180  	defer teardownRemotePluginServer()
   181  
   182  	m := Manifest{[]string{"VolumeDriver", "NetworkDriver"}}
   183  	var output Manifest
   184  
   185  	mux.HandleFunc("/Test.Echo", func(w http.ResponseWriter, r *http.Request) {
   186  		if r.Method != "POST" {
   187  			t.Fatalf("Expected POST, got %s", r.Method)
   188  		}
   189  
   190  		header := w.Header()
   191  		header.Set("Content-Type", transport.VersionMimetype)
   192  
   193  		io.Copy(w, r.Body)
   194  	})
   195  
   196  	c, _ := NewClient(addr, &tlsconfig.Options{InsecureSkipVerify: true})
   197  	body, err := c.Stream("Test.Echo", m)
   198  	if err != nil {
   199  		t.Fatal(err)
   200  	}
   201  	defer body.Close()
   202  	if err := json.NewDecoder(body).Decode(&output); err != nil {
   203  		t.Fatalf("Test.Echo: error reading plugin resp: %v", err)
   204  	}
   205  	assert.Equal(t, m, output)
   206  }
   207  
   208  func TestClientSendFile(t *testing.T) {
   209  	addr := setupRemotePluginServer()
   210  	defer teardownRemotePluginServer()
   211  
   212  	m := Manifest{[]string{"VolumeDriver", "NetworkDriver"}}
   213  	var output Manifest
   214  	var buf bytes.Buffer
   215  	if err := json.NewEncoder(&buf).Encode(m); err != nil {
   216  		t.Fatal(err)
   217  	}
   218  	mux.HandleFunc("/Test.Echo", func(w http.ResponseWriter, r *http.Request) {
   219  		if r.Method != "POST" {
   220  			t.Fatalf("Expected POST, got %s\n", r.Method)
   221  		}
   222  
   223  		header := w.Header()
   224  		header.Set("Content-Type", transport.VersionMimetype)
   225  
   226  		io.Copy(w, r.Body)
   227  	})
   228  
   229  	c, _ := NewClient(addr, &tlsconfig.Options{InsecureSkipVerify: true})
   230  	if err := c.SendFile("Test.Echo", &buf, &output); err != nil {
   231  		t.Fatal(err)
   232  	}
   233  	assert.Equal(t, m, output)
   234  }