github.com/sams1990/dockerrepo@v17.12.1-ce-rc2+incompatible/pkg/plugins/plugin_test.go (about) 1 package plugins 2 3 import ( 4 "bytes" 5 "encoding/json" 6 "errors" 7 "io" 8 "io/ioutil" 9 "net/http" 10 "path/filepath" 11 "runtime" 12 "sync" 13 "testing" 14 "time" 15 16 "github.com/docker/docker/pkg/plugins/transport" 17 "github.com/docker/go-connections/tlsconfig" 18 "github.com/stretchr/testify/assert" 19 ) 20 21 const ( 22 fruitPlugin = "fruit" 23 fruitImplements = "apple" 24 ) 25 26 // regression test for deadlock in handlers 27 func TestPluginAddHandler(t *testing.T) { 28 // make a plugin which is pre-activated 29 p := &Plugin{activateWait: sync.NewCond(&sync.Mutex{})} 30 p.Manifest = &Manifest{Implements: []string{"bananas"}} 31 storage.plugins["qwerty"] = p 32 33 testActive(t, p) 34 Handle("bananas", func(_ string, _ *Client) {}) 35 testActive(t, p) 36 } 37 38 func TestPluginWaitBadPlugin(t *testing.T) { 39 p := &Plugin{activateWait: sync.NewCond(&sync.Mutex{})} 40 p.activateErr = errors.New("some junk happened") 41 testActive(t, p) 42 } 43 44 func testActive(t *testing.T, p *Plugin) { 45 done := make(chan struct{}) 46 go func() { 47 p.waitActive() 48 close(done) 49 }() 50 51 select { 52 case <-time.After(100 * time.Millisecond): 53 _, f, l, _ := runtime.Caller(1) 54 t.Fatalf("%s:%d: deadlock in waitActive", filepath.Base(f), l) 55 case <-done: 56 } 57 58 } 59 60 func TestGet(t *testing.T) { 61 p := &Plugin{name: fruitPlugin, activateWait: sync.NewCond(&sync.Mutex{})} 62 p.Manifest = &Manifest{Implements: []string{fruitImplements}} 63 storage.plugins[fruitPlugin] = p 64 65 plugin, err := Get(fruitPlugin, fruitImplements) 66 if err != nil { 67 t.Fatal(err) 68 } 69 if p.Name() != plugin.Name() { 70 t.Fatalf("No matching plugin with name %s found", plugin.Name()) 71 } 72 if plugin.Client() != nil { 73 t.Fatal("expected nil Client but found one") 74 } 75 if !plugin.IsV1() { 76 t.Fatal("Expected true for V1 plugin") 77 } 78 79 // check negative case where plugin fruit doesn't implement banana 80 _, err = Get("fruit", "banana") 81 assert.Equal(t, err, ErrNotImplements) 82 83 // check negative case where plugin vegetable doesn't exist 84 _, err = Get("vegetable", "potato") 85 assert.Equal(t, err, ErrNotFound) 86 87 } 88 89 func TestPluginWithNoManifest(t *testing.T) { 90 addr := setupRemotePluginServer() 91 defer teardownRemotePluginServer() 92 93 m := Manifest{[]string{fruitImplements}} 94 var buf bytes.Buffer 95 if err := json.NewEncoder(&buf).Encode(m); err != nil { 96 t.Fatal(err) 97 } 98 99 mux.HandleFunc("/Plugin.Activate", func(w http.ResponseWriter, r *http.Request) { 100 if r.Method != "POST" { 101 t.Fatalf("Expected POST, got %s\n", r.Method) 102 } 103 104 header := w.Header() 105 header.Set("Content-Type", transport.VersionMimetype) 106 107 io.Copy(w, &buf) 108 }) 109 110 p := &Plugin{ 111 name: fruitPlugin, 112 activateWait: sync.NewCond(&sync.Mutex{}), 113 Addr: addr, 114 TLSConfig: &tlsconfig.Options{InsecureSkipVerify: true}, 115 } 116 storage.plugins[fruitPlugin] = p 117 118 plugin, err := Get(fruitPlugin, fruitImplements) 119 if err != nil { 120 t.Fatal(err) 121 } 122 if p.Name() != plugin.Name() { 123 t.Fatalf("No matching plugin with name %s found", plugin.Name()) 124 } 125 } 126 127 func TestGetAll(t *testing.T) { 128 tmpdir, unregister := Setup(t) 129 defer unregister() 130 131 p := filepath.Join(tmpdir, "example.json") 132 spec := `{ 133 "Name": "example", 134 "Addr": "https://example.com/docker/plugin" 135 }` 136 137 if err := ioutil.WriteFile(p, []byte(spec), 0644); err != nil { 138 t.Fatal(err) 139 } 140 141 r := newLocalRegistry() 142 plugin, err := r.Plugin("example") 143 if err != nil { 144 t.Fatal(err) 145 } 146 plugin.Manifest = &Manifest{Implements: []string{"apple"}} 147 storage.plugins["example"] = plugin 148 149 fetchedPlugins, err := GetAll("apple") 150 if err != nil { 151 t.Fatal(err) 152 } 153 if fetchedPlugins[0].Name() != plugin.Name() { 154 t.Fatalf("Expected to get plugin with name %s", plugin.Name()) 155 } 156 }