github.com/whtcorpsinc/milevadb-prod@v0.0.0-20211104133533-f57f4be3b597/causetstore/petri/plugin/plugin_test.go (about)

     1  // Copyright 2020 WHTCORPS INC, Inc.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // See the License for the specific language governing permissions and
    12  // limitations under the License.
    13  
    14  package plugin
    15  
    16  import (
    17  	"context"
    18  	"io"
    19  	"strconv"
    20  	"testing"
    21  
    22  	"github.com/whtcorpsinc/check"
    23  	"github.com/whtcorpsinc/milevadb/stochastikctx/variable"
    24  )
    25  
    26  func TestT(t *testing.T) {
    27  	check.TestingT(t)
    28  }
    29  
    30  func TestLoadPluginSuccess(t *testing.T) {
    31  	ctx := context.Background()
    32  
    33  	pluginName := "tplugin"
    34  	pluginVersion := uint16(1)
    35  	pluginSign := pluginName + "-" + strconv.Itoa(int(pluginVersion))
    36  
    37  	cfg := Config{
    38  		Plugins:        []string{pluginSign},
    39  		PluginDir:      "",
    40  		GlobalSysVar:   &variable.SysVars,
    41  		PluginVarNames: &variable.PluginVarNames,
    42  		EnvVersion:     map[string]uint16{"go": 1112},
    43  	}
    44  
    45  	// setup load test hook.
    46  	testHook = &struct{ loadOne loadFn }{loadOne: func(plugin *Plugin, dir string, pluginID ID) (manifest func() *Manifest, err error) {
    47  		return func() *Manifest {
    48  			m := &AuditManifest{
    49  				Manifest: Manifest{
    50  					HoTT:    Authentication,
    51  					Name:    pluginName,
    52  					Version: pluginVersion,
    53  					SysVars: map[string]*variable.SysVar{pluginName + "_key": {Scope: variable.ScopeGlobal, Name: pluginName + "_key", Value: "v1"}},
    54  					OnInit: func(ctx context.Context, manifest *Manifest) error {
    55  						return nil
    56  					},
    57  					OnShutdown: func(ctx context.Context, manifest *Manifest) error {
    58  						return nil
    59  					},
    60  					Validate: func(ctx context.Context, manifest *Manifest) error {
    61  						return nil
    62  					},
    63  				},
    64  				OnGeneralEvent: func(ctx context.Context, sctx *variable.StochastikVars, event GeneralEvent, cmd string) {
    65  				},
    66  			}
    67  			return ExportManifest(m)
    68  		}, nil
    69  	}}
    70  	defer func() {
    71  		testHook = nil
    72  	}()
    73  
    74  	// trigger load.
    75  	err := Load(ctx, cfg)
    76  	if err != nil {
    77  		t.Errorf("load plugin [%s] fail", pluginSign)
    78  	}
    79  
    80  	err = Init(ctx, cfg)
    81  	if err != nil {
    82  		t.Errorf("init plugin [%s] fail", pluginSign)
    83  	}
    84  
    85  	// load all.
    86  	ps := GetAll()
    87  	if len(ps) != 1 {
    88  		t.Errorf("loaded plugins is empty")
    89  	}
    90  
    91  	// find plugin by type and name
    92  	p := Get(Authentication, "tplugin")
    93  	if p == nil {
    94  		t.Errorf("tplugin can not be load")
    95  	}
    96  	p = Get(Authentication, "tplugin2")
    97  	if p != nil {
    98  		t.Errorf("found miss plugin")
    99  	}
   100  	p = getByName("tplugin")
   101  	if p == nil {
   102  		t.Errorf("can not find miss plugin")
   103  	}
   104  
   105  	// foreach plugin
   106  	err = ForeachPlugin(Authentication, func(plugin *Plugin) error {
   107  		return nil
   108  	})
   109  	if err != nil {
   110  		t.Errorf("foreach error %v", err)
   111  	}
   112  	err = ForeachPlugin(Authentication, func(plugin *Plugin) error {
   113  		return io.EOF
   114  	})
   115  	if err != io.EOF {
   116  		t.Errorf("foreach should return EOF error")
   117  	}
   118  
   119  	Shutdown(ctx)
   120  }
   121  
   122  func TestLoadPluginSkipError(t *testing.T) {
   123  	ctx := context.Background()
   124  
   125  	pluginName := "tplugin"
   126  	pluginVersion := uint16(1)
   127  	pluginSign := pluginName + "-" + strconv.Itoa(int(pluginVersion))
   128  
   129  	cfg := Config{
   130  		Plugins:        []string{pluginSign, pluginSign, "notExists-2"},
   131  		PluginDir:      "",
   132  		PluginVarNames: &variable.PluginVarNames,
   133  		EnvVersion:     map[string]uint16{"go": 1112},
   134  		SkipWhenFail:   true,
   135  	}
   136  
   137  	// setup load test hook.
   138  	testHook = &struct{ loadOne loadFn }{loadOne: func(plugin *Plugin, dir string, pluginID ID) (manifest func() *Manifest, err error) {
   139  		return func() *Manifest {
   140  			m := &AuditManifest{
   141  				Manifest: Manifest{
   142  					HoTT:    Audit,
   143  					Name:    pluginName,
   144  					Version: pluginVersion,
   145  					SysVars: map[string]*variable.SysVar{pluginName + "_key": {Scope: variable.ScopeGlobal, Name: pluginName + "_key", Value: "v1"}},
   146  					OnInit: func(ctx context.Context, manifest *Manifest) error {
   147  						return io.EOF
   148  					},
   149  					OnShutdown: func(ctx context.Context, manifest *Manifest) error {
   150  						return io.EOF
   151  					},
   152  					Validate: func(ctx context.Context, manifest *Manifest) error {
   153  						return io.EOF
   154  					},
   155  				},
   156  				OnGeneralEvent: func(ctx context.Context, sctx *variable.StochastikVars, event GeneralEvent, cmd string) {
   157  				},
   158  			}
   159  			return ExportManifest(m)
   160  		}, nil
   161  	}}
   162  	defer func() {
   163  		testHook = nil
   164  	}()
   165  
   166  	// trigger load.
   167  	err := Load(ctx, cfg)
   168  	if err != nil {
   169  		t.Errorf("load plugin [%s] fail %v", pluginSign, err)
   170  	}
   171  
   172  	err = Init(ctx, cfg)
   173  	if err != nil {
   174  		t.Errorf("init plugin [%s] fail", pluginSign)
   175  	}
   176  
   177  	// load all.
   178  	ps := GetAll()
   179  	if len(ps) != 1 {
   180  		t.Errorf("loaded plugins is empty")
   181  	}
   182  
   183  	// find plugin by type and name
   184  	p := Get(Audit, "tplugin")
   185  	if p == nil {
   186  		t.Errorf("tplugin can not be load")
   187  	}
   188  	p = Get(Audit, "tplugin2")
   189  	if p != nil {
   190  		t.Errorf("found miss plugin")
   191  	}
   192  	p = getByName("tplugin")
   193  	if p == nil {
   194  		t.Errorf("can not find miss plugin")
   195  	}
   196  	p = getByName("not exists")
   197  	if p != nil {
   198  		t.Errorf("got not exists plugin")
   199  	}
   200  
   201  	// foreach plugin
   202  	readyCount := 0
   203  	err = ForeachPlugin(Authentication, func(plugin *Plugin) error {
   204  		readyCount++
   205  		return nil
   206  	})
   207  	if err != nil {
   208  		t.Errorf("foreach meet error %v", err)
   209  	}
   210  	if readyCount != 0 {
   211  		t.Errorf("validate fail can be load but no ready")
   212  	}
   213  
   214  	Shutdown(ctx)
   215  }
   216  
   217  func TestLoadFail(t *testing.T) {
   218  	ctx := context.Background()
   219  
   220  	pluginName := "tplugin"
   221  	pluginVersion := uint16(1)
   222  	pluginSign := pluginName + "-" + strconv.Itoa(int(pluginVersion))
   223  
   224  	cfg := Config{
   225  		Plugins:        []string{pluginSign, pluginSign, "notExists-2"},
   226  		PluginDir:      "",
   227  		PluginVarNames: &variable.PluginVarNames,
   228  		EnvVersion:     map[string]uint16{"go": 1112},
   229  		SkipWhenFail:   false,
   230  	}
   231  
   232  	// setup load test hook.
   233  	testHook = &struct{ loadOne loadFn }{loadOne: func(plugin *Plugin, dir string, pluginID ID) (manifest func() *Manifest, err error) {
   234  		return func() *Manifest {
   235  			m := &AuditManifest{
   236  				Manifest: Manifest{
   237  					HoTT:    Audit,
   238  					Name:    pluginName,
   239  					Version: pluginVersion,
   240  					SysVars: map[string]*variable.SysVar{pluginName + "_key": {Scope: variable.ScopeGlobal, Name: pluginName + "_key", Value: "v1"}},
   241  					OnInit: func(ctx context.Context, manifest *Manifest) error {
   242  						return io.EOF
   243  					},
   244  					OnShutdown: func(ctx context.Context, manifest *Manifest) error {
   245  						return io.EOF
   246  					},
   247  					Validate: func(ctx context.Context, manifest *Manifest) error {
   248  						return io.EOF
   249  					},
   250  				},
   251  				OnGeneralEvent: func(ctx context.Context, sctx *variable.StochastikVars, event GeneralEvent, cmd string) {
   252  				},
   253  			}
   254  			return ExportManifest(m)
   255  		}, nil
   256  	}}
   257  	defer func() {
   258  		testHook = nil
   259  	}()
   260  
   261  	err := Load(ctx, cfg)
   262  	if err == nil {
   263  		t.Errorf("load plugin should fail")
   264  	}
   265  }
   266  
   267  func TestPluginsClone(t *testing.T) {
   268  	ps := &plugins{
   269  		plugins: map[HoTT][]Plugin{
   270  			Audit: {{}},
   271  		},
   272  		versions: map[string]uint16{
   273  			"whitelist": 1,
   274  		},
   275  		dyingPlugins: []Plugin{{}},
   276  	}
   277  	cps := ps.clone()
   278  	ps.dyingPlugins = append(ps.dyingPlugins, Plugin{})
   279  	ps.versions["w"] = 2
   280  	as := ps.plugins[Audit]
   281  	ps.plugins[Audit] = append(as, Plugin{})
   282  
   283  	if len(cps.plugins) != 1 || len(cps.plugins[Audit]) != 1 || len(cps.versions) != 1 || len(cps.dyingPlugins) != 1 {
   284  		t.Errorf("clone plugins failure")
   285  	}
   286  }