mirror of
https://github.com/httprunner/httprunner.git
synced 2026-09-05 23:51:25 +08:00
refactor: split plugin files
This commit is contained in:
@@ -0,0 +1,70 @@
|
|||||||
|
package common
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"plugin"
|
||||||
|
"reflect"
|
||||||
|
"runtime"
|
||||||
|
|
||||||
|
"github.com/rs/zerolog/log"
|
||||||
|
)
|
||||||
|
|
||||||
|
// GoPlugin implements golang official plugin
|
||||||
|
type GoPlugin struct {
|
||||||
|
*plugin.Plugin
|
||||||
|
cachedFunctions map[string]reflect.Value // cache loaded functions to improve performance
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *GoPlugin) Init(path string) error {
|
||||||
|
if runtime.GOOS == "windows" {
|
||||||
|
log.Warn().Msg("go plugin does not support windows")
|
||||||
|
return fmt.Errorf("go plugin does not support windows")
|
||||||
|
}
|
||||||
|
|
||||||
|
var err error
|
||||||
|
p.Plugin, err = plugin.Open(path)
|
||||||
|
if err != nil {
|
||||||
|
log.Error().Err(err).Str("path", path).Msg("load go plugin failed")
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
p.cachedFunctions = make(map[string]reflect.Value)
|
||||||
|
log.Info().Str("path", path).Msg("load go plugin success")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *GoPlugin) Has(funcName string) bool {
|
||||||
|
fn, ok := p.cachedFunctions[funcName]
|
||||||
|
if ok {
|
||||||
|
return fn.IsValid()
|
||||||
|
}
|
||||||
|
|
||||||
|
sym, err := p.Plugin.Lookup(funcName)
|
||||||
|
if err != nil {
|
||||||
|
p.cachedFunctions[funcName] = reflect.Value{} // mark as invalid
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
fn = reflect.ValueOf(sym)
|
||||||
|
|
||||||
|
// check function type
|
||||||
|
if fn.Kind() != reflect.Func {
|
||||||
|
p.cachedFunctions[funcName] = reflect.Value{} // mark as invalid
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
p.cachedFunctions[funcName] = fn
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *GoPlugin) Call(funcName string, args ...interface{}) (interface{}, error) {
|
||||||
|
if !p.Has(funcName) {
|
||||||
|
return nil, fmt.Errorf("function %s not found", funcName)
|
||||||
|
}
|
||||||
|
fn := p.cachedFunctions[funcName]
|
||||||
|
return CallFunc(fn, args...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *GoPlugin) Quit() error {
|
||||||
|
// no need to quit for go plugin
|
||||||
|
return nil
|
||||||
|
}
|
||||||
@@ -0,0 +1,60 @@
|
|||||||
|
package common
|
||||||
|
|
||||||
|
import (
|
||||||
|
pluginHost "github.com/httprunner/hrp/plugin/host"
|
||||||
|
pluginShared "github.com/httprunner/hrp/plugin/shared"
|
||||||
|
"github.com/rs/zerolog/log"
|
||||||
|
)
|
||||||
|
|
||||||
|
// HashicorpPlugin implements hashicorp/go-plugin
|
||||||
|
type HashicorpPlugin struct {
|
||||||
|
pluginShared.FuncCaller
|
||||||
|
cachedFunctions map[string]bool // cache loaded functions to improve performance
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *HashicorpPlugin) Init(path string) error {
|
||||||
|
|
||||||
|
f, err := pluginHost.Init(path)
|
||||||
|
if err != nil {
|
||||||
|
log.Error().Err(err).Str("path", path).Msg("load go hashicorp plugin failed")
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
p.FuncCaller = f
|
||||||
|
|
||||||
|
p.cachedFunctions = make(map[string]bool)
|
||||||
|
log.Info().Str("path", path).Msg("load hashicorp go plugin success")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *HashicorpPlugin) Has(funcName string) bool {
|
||||||
|
flag, ok := p.cachedFunctions[funcName]
|
||||||
|
if ok {
|
||||||
|
return flag
|
||||||
|
}
|
||||||
|
|
||||||
|
funcNames, err := p.GetNames()
|
||||||
|
if err != nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, name := range funcNames {
|
||||||
|
if name == funcName {
|
||||||
|
p.cachedFunctions[funcName] = true // cache as exists
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
p.cachedFunctions[funcName] = false // cache as not exists
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *HashicorpPlugin) Call(funcName string, args ...interface{}) (interface{}, error) {
|
||||||
|
return p.FuncCaller.Call(funcName, args...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *HashicorpPlugin) Quit() error {
|
||||||
|
// kill hashicorp plugin process
|
||||||
|
log.Info().Msg("quit hashicorp plugin process")
|
||||||
|
pluginHost.Quit()
|
||||||
|
return nil
|
||||||
|
}
|
||||||
@@ -4,13 +4,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"plugin"
|
|
||||||
"reflect"
|
|
||||||
"runtime"
|
|
||||||
|
|
||||||
"github.com/rs/zerolog/log"
|
|
||||||
|
|
||||||
pluginHost "github.com/httprunner/hrp/plugin/host"
|
|
||||||
pluginShared "github.com/httprunner/hrp/plugin/shared"
|
pluginShared "github.com/httprunner/hrp/plugin/shared"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -29,119 +23,6 @@ type Plugin interface {
|
|||||||
Quit() error // quit plugin
|
Quit() error // quit plugin
|
||||||
}
|
}
|
||||||
|
|
||||||
// GoPlugin implements golang official plugin
|
|
||||||
type GoPlugin struct {
|
|
||||||
*plugin.Plugin
|
|
||||||
cachedFunctions map[string]reflect.Value // cache loaded functions to improve performance
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *GoPlugin) Init(path string) error {
|
|
||||||
if runtime.GOOS == "windows" {
|
|
||||||
log.Warn().Msg("go plugin does not support windows")
|
|
||||||
return fmt.Errorf("go plugin does not support windows")
|
|
||||||
}
|
|
||||||
|
|
||||||
var err error
|
|
||||||
p.Plugin, err = plugin.Open(path)
|
|
||||||
if err != nil {
|
|
||||||
log.Error().Err(err).Str("path", path).Msg("load go plugin failed")
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
p.cachedFunctions = make(map[string]reflect.Value)
|
|
||||||
log.Info().Str("path", path).Msg("load go plugin success")
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *GoPlugin) Has(funcName string) bool {
|
|
||||||
fn, ok := p.cachedFunctions[funcName]
|
|
||||||
if ok {
|
|
||||||
return fn.IsValid()
|
|
||||||
}
|
|
||||||
|
|
||||||
sym, err := p.Plugin.Lookup(funcName)
|
|
||||||
if err != nil {
|
|
||||||
p.cachedFunctions[funcName] = reflect.Value{} // mark as invalid
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
fn = reflect.ValueOf(sym)
|
|
||||||
|
|
||||||
// check function type
|
|
||||||
if fn.Kind() != reflect.Func {
|
|
||||||
p.cachedFunctions[funcName] = reflect.Value{} // mark as invalid
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
p.cachedFunctions[funcName] = fn
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *GoPlugin) Call(funcName string, args ...interface{}) (interface{}, error) {
|
|
||||||
if !p.Has(funcName) {
|
|
||||||
return nil, fmt.Errorf("function %s not found", funcName)
|
|
||||||
}
|
|
||||||
fn := p.cachedFunctions[funcName]
|
|
||||||
return CallFunc(fn, args...)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *GoPlugin) Quit() error {
|
|
||||||
// no need to quit for go plugin
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// HashicorpPlugin implements hashicorp/go-plugin
|
|
||||||
type HashicorpPlugin struct {
|
|
||||||
pluginShared.FuncCaller
|
|
||||||
cachedFunctions map[string]bool // cache loaded functions to improve performance
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *HashicorpPlugin) Init(path string) error {
|
|
||||||
|
|
||||||
f, err := pluginHost.Init(path)
|
|
||||||
if err != nil {
|
|
||||||
log.Error().Err(err).Str("path", path).Msg("load go hashicorp plugin failed")
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
p.FuncCaller = f
|
|
||||||
|
|
||||||
p.cachedFunctions = make(map[string]bool)
|
|
||||||
log.Info().Str("path", path).Msg("load hashicorp go plugin success")
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *HashicorpPlugin) Has(funcName string) bool {
|
|
||||||
flag, ok := p.cachedFunctions[funcName]
|
|
||||||
if ok {
|
|
||||||
return flag
|
|
||||||
}
|
|
||||||
|
|
||||||
funcNames, err := p.GetNames()
|
|
||||||
if err != nil {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, name := range funcNames {
|
|
||||||
if name == funcName {
|
|
||||||
p.cachedFunctions[funcName] = true // cache as exists
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
p.cachedFunctions[funcName] = false // cache as not exists
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *HashicorpPlugin) Call(funcName string, args ...interface{}) (interface{}, error) {
|
|
||||||
return p.FuncCaller.Call(funcName, args...)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *HashicorpPlugin) Quit() error {
|
|
||||||
// kill hashicorp plugin process
|
|
||||||
log.Info().Msg("quit hashicorp plugin process")
|
|
||||||
pluginHost.Quit()
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func Init(path string) (Plugin, error) {
|
func Init(path string) (Plugin, error) {
|
||||||
if path == "" {
|
if path == "" {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
|
|||||||
Reference in New Issue
Block a user