mirror of
https://github.com/moby/moby.git
synced 2022-11-09 12:21:53 -05:00
Increase the Coverage of pkg/plugins
Increases the test coverage of pkg/plugins. Changed signature of function NewClientWithTimeout in pkg/plugin/client, to take time.Duration instead of integers. Signed-off-by: Raja Sami <raja.sami@tenpearl.com>
This commit is contained in:
parent
3f6b6c2981
commit
8dd100a229
6 changed files with 259 additions and 9 deletions
|
@ -57,20 +57,20 @@ func NewClient(addr string, tlsConfig *tlsconfig.Options) (*Client, error) {
|
|||
}
|
||||
|
||||
// NewClientWithTimeout creates a new plugin client (http).
|
||||
func NewClientWithTimeout(addr string, tlsConfig *tlsconfig.Options, timeoutInSecs int) (*Client, error) {
|
||||
func NewClientWithTimeout(addr string, tlsConfig *tlsconfig.Options, timeout time.Duration) (*Client, error) {
|
||||
clientTransport, err := newTransport(addr, tlsConfig)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return newClientWithTransport(clientTransport, timeoutInSecs), nil
|
||||
return newClientWithTransport(clientTransport, timeout), nil
|
||||
}
|
||||
|
||||
// newClientWithTransport creates a new plugin client with a given transport.
|
||||
func newClientWithTransport(tr transport.Transport, timeoutInSecs int) *Client {
|
||||
func newClientWithTransport(tr transport.Transport, timeout time.Duration) *Client {
|
||||
return &Client{
|
||||
http: &http.Client{
|
||||
Transport: tr,
|
||||
Timeout: time.Duration(timeoutInSecs) * time.Second,
|
||||
Timeout: timeout,
|
||||
},
|
||||
requestFactory: tr,
|
||||
}
|
||||
|
|
|
@ -1,17 +1,19 @@
|
|||
package plugins
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"io"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"net/url"
|
||||
"reflect"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/docker/docker/pkg/plugins/transport"
|
||||
"github.com/docker/go-connections/tlsconfig"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
var (
|
||||
|
@ -83,9 +85,7 @@ func TestEchoInputOutput(t *testing.T) {
|
|||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if !reflect.DeepEqual(output, m) {
|
||||
t.Fatalf("Expected %v, was %v\n", m, output)
|
||||
}
|
||||
assert.Equal(t, m, output)
|
||||
err = c.Call("Test.Echo", nil, nil)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
|
@ -153,3 +153,82 @@ func TestClientScheme(t *testing.T) {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestNewClientWithTimeout(t *testing.T) {
|
||||
addr := setupRemotePluginServer()
|
||||
defer teardownRemotePluginServer()
|
||||
|
||||
m := Manifest{[]string{"VolumeDriver", "NetworkDriver"}}
|
||||
|
||||
mux.HandleFunc("/Test.Echo", func(w http.ResponseWriter, r *http.Request) {
|
||||
time.Sleep(time.Duration(600) * time.Millisecond)
|
||||
io.Copy(w, r.Body)
|
||||
})
|
||||
|
||||
// setting timeout of 500ms
|
||||
timeout := time.Duration(500) * time.Millisecond
|
||||
c, _ := NewClientWithTimeout(addr, &tlsconfig.Options{InsecureSkipVerify: true}, timeout)
|
||||
var output Manifest
|
||||
err := c.Call("Test.Echo", m, &output)
|
||||
if err == nil {
|
||||
t.Fatal("Expected timeout error")
|
||||
}
|
||||
}
|
||||
|
||||
func TestClientStream(t *testing.T) {
|
||||
addr := setupRemotePluginServer()
|
||||
defer teardownRemotePluginServer()
|
||||
|
||||
m := Manifest{[]string{"VolumeDriver", "NetworkDriver"}}
|
||||
var output Manifest
|
||||
|
||||
mux.HandleFunc("/Test.Echo", func(w http.ResponseWriter, r *http.Request) {
|
||||
if r.Method != "POST" {
|
||||
t.Fatalf("Expected POST, got %s", r.Method)
|
||||
}
|
||||
|
||||
header := w.Header()
|
||||
header.Set("Content-Type", transport.VersionMimetype)
|
||||
|
||||
io.Copy(w, r.Body)
|
||||
})
|
||||
|
||||
c, _ := NewClient(addr, &tlsconfig.Options{InsecureSkipVerify: true})
|
||||
body, err := c.Stream("Test.Echo", m)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer body.Close()
|
||||
if err := json.NewDecoder(body).Decode(&output); err != nil {
|
||||
t.Fatalf("Test.Echo: error reading plugin resp: %v", err)
|
||||
}
|
||||
assert.Equal(t, m, output)
|
||||
}
|
||||
|
||||
func TestClientSendFile(t *testing.T) {
|
||||
addr := setupRemotePluginServer()
|
||||
defer teardownRemotePluginServer()
|
||||
|
||||
m := Manifest{[]string{"VolumeDriver", "NetworkDriver"}}
|
||||
var output Manifest
|
||||
var buf bytes.Buffer
|
||||
if err := json.NewEncoder(&buf).Encode(m); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
mux.HandleFunc("/Test.Echo", func(w http.ResponseWriter, r *http.Request) {
|
||||
if r.Method != "POST" {
|
||||
t.Fatalf("Expected POST, got %s\n", r.Method)
|
||||
}
|
||||
|
||||
header := w.Header()
|
||||
header.Set("Content-Type", transport.VersionMimetype)
|
||||
|
||||
io.Copy(w, r.Body)
|
||||
})
|
||||
|
||||
c, _ := NewClient(addr, &tlsconfig.Options{InsecureSkipVerify: true})
|
||||
if err := c.SendFile("Test.Echo", &buf, &output); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
assert.Equal(t, m, output)
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@ package plugins
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
@ -59,3 +60,41 @@ func TestLocalSocket(t *testing.T) {
|
|||
l.Close()
|
||||
}
|
||||
}
|
||||
|
||||
func TestScan(t *testing.T) {
|
||||
tmpdir, unregister := Setup(t)
|
||||
defer unregister()
|
||||
|
||||
pluginNames, err := Scan()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if pluginNames != nil {
|
||||
t.Fatal("Plugin names should be empty.")
|
||||
}
|
||||
|
||||
path := filepath.Join(tmpdir, "echo.spec")
|
||||
addr := "unix://var/lib/docker/plugins/echo.sock"
|
||||
name := "echo"
|
||||
|
||||
err = os.MkdirAll(filepath.Dir(path), 0755)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
err = ioutil.WriteFile(path, []byte(addr), 0644)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
r := newLocalRegistry()
|
||||
p, err := r.Plugin(name)
|
||||
|
||||
pluginNamesNotEmpty, err := Scan()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if p.Name() != pluginNamesNotEmpty[0] {
|
||||
t.Fatalf("Unable to scan plugin with name %s", p.name)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,12 +1,26 @@
|
|||
package plugins
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"sync"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/docker/docker/pkg/plugins/transport"
|
||||
"github.com/docker/go-connections/tlsconfig"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
const (
|
||||
fruitPlugin = "fruit"
|
||||
fruitImplements = "apple"
|
||||
)
|
||||
|
||||
// regression test for deadlock in handlers
|
||||
|
@ -42,3 +56,101 @@ func testActive(t *testing.T, p *Plugin) {
|
|||
}
|
||||
|
||||
}
|
||||
|
||||
func TestGet(t *testing.T) {
|
||||
p := &Plugin{name: fruitPlugin, activateWait: sync.NewCond(&sync.Mutex{})}
|
||||
p.Manifest = &Manifest{Implements: []string{fruitImplements}}
|
||||
storage.plugins[fruitPlugin] = p
|
||||
|
||||
plugin, err := Get(fruitPlugin, fruitImplements)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if p.Name() != plugin.Name() {
|
||||
t.Fatalf("No matching plugin with name %s found", plugin.Name())
|
||||
}
|
||||
if plugin.Client() != nil {
|
||||
t.Fatal("expected nil Client but found one")
|
||||
}
|
||||
if !plugin.IsV1() {
|
||||
t.Fatal("Expected true for V1 plugin")
|
||||
}
|
||||
|
||||
// check negative case where plugin fruit doesn't implement banana
|
||||
_, err = Get("fruit", "banana")
|
||||
assert.Equal(t, err, ErrNotImplements)
|
||||
|
||||
// check negative case where plugin vegetable doesn't exist
|
||||
_, err = Get("vegetable", "potato")
|
||||
assert.Equal(t, err, ErrNotFound)
|
||||
|
||||
}
|
||||
|
||||
func TestPluginWithNoManifest(t *testing.T) {
|
||||
addr := setupRemotePluginServer()
|
||||
defer teardownRemotePluginServer()
|
||||
|
||||
m := Manifest{[]string{fruitImplements}}
|
||||
var buf bytes.Buffer
|
||||
if err := json.NewEncoder(&buf).Encode(m); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
mux.HandleFunc("/Plugin.Activate", func(w http.ResponseWriter, r *http.Request) {
|
||||
if r.Method != "POST" {
|
||||
t.Fatalf("Expected POST, got %s\n", r.Method)
|
||||
}
|
||||
|
||||
header := w.Header()
|
||||
header.Set("Content-Type", transport.VersionMimetype)
|
||||
|
||||
io.Copy(w, &buf)
|
||||
})
|
||||
|
||||
p := &Plugin{
|
||||
name: fruitPlugin,
|
||||
activateWait: sync.NewCond(&sync.Mutex{}),
|
||||
Addr: addr,
|
||||
TLSConfig: &tlsconfig.Options{InsecureSkipVerify: true},
|
||||
}
|
||||
storage.plugins[fruitPlugin] = p
|
||||
|
||||
plugin, err := Get(fruitPlugin, fruitImplements)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if p.Name() != plugin.Name() {
|
||||
t.Fatalf("No matching plugin with name %s found", plugin.Name())
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetAll(t *testing.T) {
|
||||
tmpdir, unregister := Setup(t)
|
||||
defer unregister()
|
||||
|
||||
p := filepath.Join(tmpdir, "example.json")
|
||||
spec := `{
|
||||
"Name": "example",
|
||||
"Addr": "https://example.com/docker/plugin"
|
||||
}`
|
||||
|
||||
if err := ioutil.WriteFile(p, []byte(spec), 0644); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
r := newLocalRegistry()
|
||||
plugin, err := r.Plugin("example")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
plugin.Manifest = &Manifest{Implements: []string{"apple"}}
|
||||
storage.plugins["example"] = plugin
|
||||
|
||||
fetchedPlugins, err := GetAll("apple")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if fetchedPlugins[0].Name() != plugin.Name() {
|
||||
t.Fatalf("Expected to get plugin with name %s", plugin.Name())
|
||||
}
|
||||
}
|
||||
|
|
20
pkg/plugins/transport/http_test.go
Normal file
20
pkg/plugins/transport/http_test.go
Normal file
|
@ -0,0 +1,20 @@
|
|||
package transport
|
||||
|
||||
import (
|
||||
"io"
|
||||
"net/http"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestHTTPTransport(t *testing.T) {
|
||||
var r io.Reader
|
||||
roundTripper := &http.Transport{}
|
||||
newTransport := NewHTTPTransport(roundTripper, "http", "0.0.0.0")
|
||||
request, err := newTransport.NewRequest("", r)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
assert.Equal(t, "POST", request.Method)
|
||||
}
|
|
@ -80,7 +80,7 @@ func (pm *Manager) enable(p *v2.Plugin, c *controller, force bool) error {
|
|||
|
||||
func (pm *Manager) pluginPostStart(p *v2.Plugin, c *controller) error {
|
||||
sockAddr := filepath.Join(pm.config.ExecRoot, p.GetID(), p.GetSocket())
|
||||
client, err := plugins.NewClientWithTimeout("unix://"+sockAddr, nil, c.timeoutInSecs)
|
||||
client, err := plugins.NewClientWithTimeout("unix://"+sockAddr, nil, time.Duration(c.timeoutInSecs)*time.Second)
|
||||
if err != nil {
|
||||
c.restart = false
|
||||
shutdownPlugin(p, c, pm.containerdClient)
|
||||
|
|
Loading…
Reference in a new issue