You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
286 lines
7.1 KiB
286 lines
7.1 KiB
// Copyright 2019 PingCAP, Inc.
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
package plugin
|
|
|
|
import (
|
|
"context"
|
|
"io"
|
|
"strconv"
|
|
"testing"
|
|
|
|
"github.com/pingcap/check"
|
|
"github.com/pingcap/tidb/sessionctx/variable"
|
|
)
|
|
|
|
func TestT(t *testing.T) {
|
|
check.TestingT(t)
|
|
}
|
|
|
|
func TestLoadPluginSuccess(t *testing.T) {
|
|
ctx := context.Background()
|
|
|
|
pluginName := "tplugin"
|
|
pluginVersion := uint16(1)
|
|
pluginSign := pluginName + "-" + strconv.Itoa(int(pluginVersion))
|
|
|
|
cfg := Config{
|
|
Plugins: []string{pluginSign},
|
|
PluginDir: "",
|
|
GlobalSysVar: &variable.SysVars,
|
|
PluginVarNames: &variable.PluginVarNames,
|
|
EnvVersion: map[string]uint16{"go": 1112},
|
|
}
|
|
|
|
// setup load test hook.
|
|
testHook = &struct{ loadOne loadFn }{loadOne: func(plugin *Plugin, dir string, pluginID ID) (manifest func() *Manifest, err error) {
|
|
return func() *Manifest {
|
|
m := &AuditManifest{
|
|
Manifest: Manifest{
|
|
Kind: Authentication,
|
|
Name: pluginName,
|
|
Version: pluginVersion,
|
|
SysVars: map[string]*variable.SysVar{pluginName + "_key": {Scope: variable.ScopeGlobal, Name: pluginName + "_key", Value: "v1"}},
|
|
OnInit: func(ctx context.Context, manifest *Manifest) error {
|
|
return nil
|
|
},
|
|
OnShutdown: func(ctx context.Context, manifest *Manifest) error {
|
|
return nil
|
|
},
|
|
Validate: func(ctx context.Context, manifest *Manifest) error {
|
|
return nil
|
|
},
|
|
},
|
|
OnGeneralEvent: func(ctx context.Context, sctx *variable.SessionVars, event GeneralEvent, cmd string) {
|
|
},
|
|
}
|
|
return ExportManifest(m)
|
|
}, nil
|
|
}}
|
|
defer func() {
|
|
testHook = nil
|
|
}()
|
|
|
|
// trigger load.
|
|
err := Load(ctx, cfg)
|
|
if err != nil {
|
|
t.Errorf("load plugin [%s] fail", pluginSign)
|
|
}
|
|
|
|
err = Init(ctx, cfg)
|
|
if err != nil {
|
|
t.Errorf("init plugin [%s] fail", pluginSign)
|
|
}
|
|
|
|
// load all.
|
|
ps := GetAll()
|
|
if len(ps) != 1 {
|
|
t.Errorf("loaded plugins is empty")
|
|
}
|
|
|
|
// find plugin by type and name
|
|
p := Get(Authentication, "tplugin")
|
|
if p == nil {
|
|
t.Errorf("tplugin can not be load")
|
|
}
|
|
p = Get(Authentication, "tplugin2")
|
|
if p != nil {
|
|
t.Errorf("found miss plugin")
|
|
}
|
|
p = getByName("tplugin")
|
|
if p == nil {
|
|
t.Errorf("can not find miss plugin")
|
|
}
|
|
|
|
// foreach plugin
|
|
err = ForeachPlugin(Authentication, func(plugin *Plugin) error {
|
|
return nil
|
|
})
|
|
if err != nil {
|
|
t.Errorf("foreach error %v", err)
|
|
}
|
|
err = ForeachPlugin(Authentication, func(plugin *Plugin) error {
|
|
return io.EOF
|
|
})
|
|
if err != io.EOF {
|
|
t.Errorf("foreach should return EOF error")
|
|
}
|
|
|
|
Shutdown(ctx)
|
|
}
|
|
|
|
func TestLoadPluginSkipError(t *testing.T) {
|
|
ctx := context.Background()
|
|
|
|
pluginName := "tplugin"
|
|
pluginVersion := uint16(1)
|
|
pluginSign := pluginName + "-" + strconv.Itoa(int(pluginVersion))
|
|
|
|
cfg := Config{
|
|
Plugins: []string{pluginSign, pluginSign, "notExists-2"},
|
|
PluginDir: "",
|
|
PluginVarNames: &variable.PluginVarNames,
|
|
EnvVersion: map[string]uint16{"go": 1112},
|
|
SkipWhenFail: true,
|
|
}
|
|
|
|
// setup load test hook.
|
|
testHook = &struct{ loadOne loadFn }{loadOne: func(plugin *Plugin, dir string, pluginID ID) (manifest func() *Manifest, err error) {
|
|
return func() *Manifest {
|
|
m := &AuditManifest{
|
|
Manifest: Manifest{
|
|
Kind: Audit,
|
|
Name: pluginName,
|
|
Version: pluginVersion,
|
|
SysVars: map[string]*variable.SysVar{pluginName + "_key": {Scope: variable.ScopeGlobal, Name: pluginName + "_key", Value: "v1"}},
|
|
OnInit: func(ctx context.Context, manifest *Manifest) error {
|
|
return io.EOF
|
|
},
|
|
OnShutdown: func(ctx context.Context, manifest *Manifest) error {
|
|
return io.EOF
|
|
},
|
|
Validate: func(ctx context.Context, manifest *Manifest) error {
|
|
return io.EOF
|
|
},
|
|
},
|
|
OnGeneralEvent: func(ctx context.Context, sctx *variable.SessionVars, event GeneralEvent, cmd string) {
|
|
},
|
|
}
|
|
return ExportManifest(m)
|
|
}, nil
|
|
}}
|
|
defer func() {
|
|
testHook = nil
|
|
}()
|
|
|
|
// trigger load.
|
|
err := Load(ctx, cfg)
|
|
if err != nil {
|
|
t.Errorf("load plugin [%s] fail %v", pluginSign, err)
|
|
}
|
|
|
|
err = Init(ctx, cfg)
|
|
if err != nil {
|
|
t.Errorf("init plugin [%s] fail", pluginSign)
|
|
}
|
|
|
|
// load all.
|
|
ps := GetAll()
|
|
if len(ps) != 1 {
|
|
t.Errorf("loaded plugins is empty")
|
|
}
|
|
|
|
// find plugin by type and name
|
|
p := Get(Audit, "tplugin")
|
|
if p == nil {
|
|
t.Errorf("tplugin can not be load")
|
|
}
|
|
p = Get(Audit, "tplugin2")
|
|
if p != nil {
|
|
t.Errorf("found miss plugin")
|
|
}
|
|
p = getByName("tplugin")
|
|
if p == nil {
|
|
t.Errorf("can not find miss plugin")
|
|
}
|
|
p = getByName("not exists")
|
|
if p != nil {
|
|
t.Errorf("got not exists plugin")
|
|
}
|
|
|
|
// foreach plugin
|
|
readyCount := 0
|
|
err = ForeachPlugin(Authentication, func(plugin *Plugin) error {
|
|
readyCount++
|
|
return nil
|
|
})
|
|
if err != nil {
|
|
t.Errorf("foreach meet error %v", err)
|
|
}
|
|
if readyCount != 0 {
|
|
t.Errorf("validate fail can be load but no ready")
|
|
}
|
|
|
|
Shutdown(ctx)
|
|
}
|
|
|
|
func TestLoadFail(t *testing.T) {
|
|
ctx := context.Background()
|
|
|
|
pluginName := "tplugin"
|
|
pluginVersion := uint16(1)
|
|
pluginSign := pluginName + "-" + strconv.Itoa(int(pluginVersion))
|
|
|
|
cfg := Config{
|
|
Plugins: []string{pluginSign, pluginSign, "notExists-2"},
|
|
PluginDir: "",
|
|
PluginVarNames: &variable.PluginVarNames,
|
|
EnvVersion: map[string]uint16{"go": 1112},
|
|
SkipWhenFail: false,
|
|
}
|
|
|
|
// setup load test hook.
|
|
testHook = &struct{ loadOne loadFn }{loadOne: func(plugin *Plugin, dir string, pluginID ID) (manifest func() *Manifest, err error) {
|
|
return func() *Manifest {
|
|
m := &AuditManifest{
|
|
Manifest: Manifest{
|
|
Kind: Audit,
|
|
Name: pluginName,
|
|
Version: pluginVersion,
|
|
SysVars: map[string]*variable.SysVar{pluginName + "_key": {Scope: variable.ScopeGlobal, Name: pluginName + "_key", Value: "v1"}},
|
|
OnInit: func(ctx context.Context, manifest *Manifest) error {
|
|
return io.EOF
|
|
},
|
|
OnShutdown: func(ctx context.Context, manifest *Manifest) error {
|
|
return io.EOF
|
|
},
|
|
Validate: func(ctx context.Context, manifest *Manifest) error {
|
|
return io.EOF
|
|
},
|
|
},
|
|
OnGeneralEvent: func(ctx context.Context, sctx *variable.SessionVars, event GeneralEvent, cmd string) {
|
|
},
|
|
}
|
|
return ExportManifest(m)
|
|
}, nil
|
|
}}
|
|
defer func() {
|
|
testHook = nil
|
|
}()
|
|
|
|
err := Load(ctx, cfg)
|
|
if err == nil {
|
|
t.Errorf("load plugin should fail")
|
|
}
|
|
}
|
|
|
|
func TestPluginsClone(t *testing.T) {
|
|
ps := &plugins{
|
|
plugins: map[Kind][]Plugin{
|
|
Audit: {{}},
|
|
},
|
|
versions: map[string]uint16{
|
|
"whitelist": 1,
|
|
},
|
|
dyingPlugins: []Plugin{{}},
|
|
}
|
|
cps := ps.clone()
|
|
ps.dyingPlugins = append(ps.dyingPlugins, Plugin{})
|
|
ps.versions["w"] = 2
|
|
as := ps.plugins[Audit]
|
|
ps.plugins[Audit] = append(as, Plugin{})
|
|
|
|
if len(cps.plugins) != 1 || len(cps.plugins[Audit]) != 1 || len(cps.versions) != 1 || len(cps.dyingPlugins) != 1 {
|
|
t.Errorf("clone plugins failure")
|
|
}
|
|
}
|
|
|