mirror of
https://github.com/httprunner/httprunner.git
synced 2026-05-31 13:29:35 +08:00
refactor: plugin structure
This commit is contained in:
24
parser.go
24
parser.go
@@ -11,6 +11,9 @@ import (
|
|||||||
"github.com/maja42/goval"
|
"github.com/maja42/goval"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"github.com/rs/zerolog/log"
|
"github.com/rs/zerolog/log"
|
||||||
|
|
||||||
|
"github.com/httprunner/hrp/internal/builtin"
|
||||||
|
"github.com/httprunner/hrp/plugin/common"
|
||||||
)
|
)
|
||||||
|
|
||||||
func newParser() *parser {
|
func newParser() *parser {
|
||||||
@@ -18,7 +21,7 @@ func newParser() *parser {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type parser struct {
|
type parser struct {
|
||||||
plugin hrpPlugin // plugin is used to call functions
|
plugin common.Plugin // plugin is used to call functions
|
||||||
}
|
}
|
||||||
|
|
||||||
func buildURL(baseURL, stepURL string) string {
|
func buildURL(baseURL, stepURL string) string {
|
||||||
@@ -233,6 +236,25 @@ func (p *parser) parseString(raw string, variablesMapping map[string]interface{}
|
|||||||
return parsedString, nil
|
return parsedString, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// callFunc calls function with arguments
|
||||||
|
// only support return at most one result value
|
||||||
|
func (p *parser) callFunc(funcName string, arguments ...interface{}) (interface{}, error) {
|
||||||
|
// call with plugin function
|
||||||
|
if p.plugin != nil && p.plugin.Has(funcName) {
|
||||||
|
return p.plugin.Call(funcName, arguments...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// get builtin function
|
||||||
|
function, ok := builtin.Functions[funcName]
|
||||||
|
if !ok {
|
||||||
|
return nil, fmt.Errorf("function %s is not found", funcName)
|
||||||
|
}
|
||||||
|
fn := reflect.ValueOf(function)
|
||||||
|
|
||||||
|
// call with builtin function
|
||||||
|
return common.CallFunc(fn, arguments...)
|
||||||
|
}
|
||||||
|
|
||||||
// merge two variables mapping, the first variables have higher priority
|
// merge two variables mapping, the first variables have higher priority
|
||||||
func mergeVariables(variables, overriddenVariables map[string]interface{}) map[string]interface{} {
|
func mergeVariables(variables, overriddenVariables map[string]interface{}) map[string]interface{} {
|
||||||
if overriddenVariables == nil {
|
if overriddenVariables == nil {
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
package shared
|
package common
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package shared
|
package common
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
// +build linux freebsd darwin
|
// +build linux freebsd darwin
|
||||||
// go plugin doesn't support windows
|
// go plugin doesn't support windows
|
||||||
|
|
||||||
package hrp
|
package common
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
@@ -16,7 +16,7 @@ func buildGoPlugin() {
|
|||||||
fmt.Println("[setup] build go plugin")
|
fmt.Println("[setup] build go plugin")
|
||||||
// flag -race is necessary in order to be consistent with go test
|
// flag -race is necessary in order to be consistent with go test
|
||||||
cmd := exec.Command("go", "build", "-buildmode=plugin", "-race",
|
cmd := exec.Command("go", "build", "-buildmode=plugin", "-race",
|
||||||
"-o=examples/debugtalk.so", "examples/plugin/debugtalk.go")
|
"-o=debugtalk.so", "../../examples/plugin/debugtalk.go")
|
||||||
if err := cmd.Run(); err != nil {
|
if err := cmd.Run(); err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
@@ -24,50 +24,43 @@ func buildGoPlugin() {
|
|||||||
|
|
||||||
func removeGoPlugin() {
|
func removeGoPlugin() {
|
||||||
fmt.Println("[teardown] remove go plugin")
|
fmt.Println("[teardown] remove go plugin")
|
||||||
os.Remove("examples/debugtalk.so")
|
os.Remove("debugtalk.so")
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestLocatePlugin(t *testing.T) {
|
func TestLocatePlugin(t *testing.T) {
|
||||||
buildGoPlugin()
|
buildGoPlugin()
|
||||||
defer removeGoPlugin()
|
defer removeGoPlugin()
|
||||||
|
|
||||||
cwd, _ := os.Getwd()
|
_, err := locateFile("../", goPluginFile)
|
||||||
_, err := locatePlugin(cwd, goPluginFile)
|
|
||||||
if !assert.Error(t, err) {
|
if !assert.Error(t, err) {
|
||||||
t.Fail()
|
t.Fail()
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err = locatePlugin("", goPluginFile)
|
_, err = locateFile("", goPluginFile)
|
||||||
if !assert.Error(t, err) {
|
if !assert.Error(t, err) {
|
||||||
t.Fail()
|
t.Fail()
|
||||||
}
|
}
|
||||||
|
|
||||||
startPath := "examples/debugtalk.so"
|
startPath := "debugtalk.so"
|
||||||
_, err = locatePlugin(startPath, goPluginFile)
|
_, err = locateFile(startPath, goPluginFile)
|
||||||
if !assert.Nil(t, err) {
|
if !assert.Nil(t, err) {
|
||||||
t.Fail()
|
t.Fail()
|
||||||
}
|
}
|
||||||
|
|
||||||
startPath = "examples/demo.json"
|
startPath = "call.go"
|
||||||
_, err = locatePlugin(startPath, goPluginFile)
|
_, err = locateFile(startPath, goPluginFile)
|
||||||
if !assert.Nil(t, err) {
|
if !assert.Nil(t, err) {
|
||||||
t.Fail()
|
t.Fail()
|
||||||
}
|
}
|
||||||
|
|
||||||
startPath = "examples/"
|
startPath = "."
|
||||||
_, err = locatePlugin(startPath, goPluginFile)
|
_, err = locateFile(startPath, goPluginFile)
|
||||||
if !assert.Nil(t, err) {
|
|
||||||
t.Fail()
|
|
||||||
}
|
|
||||||
|
|
||||||
startPath = "examples/plugin/debugtalk.go"
|
|
||||||
_, err = locatePlugin(startPath, goPluginFile)
|
|
||||||
if !assert.Nil(t, err) {
|
if !assert.Nil(t, err) {
|
||||||
t.Fail()
|
t.Fail()
|
||||||
}
|
}
|
||||||
|
|
||||||
startPath = "/abc"
|
startPath = "/abc"
|
||||||
_, err = locatePlugin(startPath, goPluginFile)
|
_, err = locateFile(startPath, goPluginFile)
|
||||||
if !assert.Error(t, err) {
|
if !assert.Error(t, err) {
|
||||||
t.Fail()
|
t.Fail()
|
||||||
}
|
}
|
||||||
@@ -75,17 +68,19 @@ func TestLocatePlugin(t *testing.T) {
|
|||||||
|
|
||||||
func TestCallPluginFunction(t *testing.T) {
|
func TestCallPluginFunction(t *testing.T) {
|
||||||
buildGoPlugin()
|
buildGoPlugin()
|
||||||
removeHashicorpPlugin()
|
|
||||||
defer removeGoPlugin()
|
defer removeGoPlugin()
|
||||||
|
|
||||||
parser := newParser()
|
plugin, err := Init("debugtalk.so")
|
||||||
err := parser.initPlugin("examples/debugtalk.so")
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if !assert.True(t, plugin.Has("Concatenate")) {
|
||||||
|
t.Fail()
|
||||||
|
}
|
||||||
|
|
||||||
// call function without arguments
|
// call function without arguments
|
||||||
result, err := parser.callFunc("Concatenate", "1", 2, "3.14")
|
result, err := plugin.Call("Concatenate", "1", 2, "3.14")
|
||||||
if !assert.NoError(t, err) {
|
if !assert.NoError(t, err) {
|
||||||
t.Fail()
|
t.Fail()
|
||||||
}
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package hrp
|
package common
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
@@ -6,15 +6,14 @@ import (
|
|||||||
"os/exec"
|
"os/exec"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/httprunner/hrp/plugin/host"
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
)
|
)
|
||||||
|
|
||||||
func buildHashicorpPlugin() {
|
func buildHashicorpPlugin() {
|
||||||
fmt.Println("[init] build hashicorp go plugin")
|
fmt.Println("[init] build hashicorp go plugin")
|
||||||
cmd := exec.Command("go", "build",
|
cmd := exec.Command("go", "build",
|
||||||
"-o=examples/debugtalk.bin",
|
"-o=debugtalk.bin",
|
||||||
"examples/plugin/hashicorp.go", "examples/plugin/debugtalk.go")
|
"../../examples/plugin/hashicorp.go", "../../examples/plugin/debugtalk.go")
|
||||||
if err := cmd.Run(); err != nil {
|
if err := cmd.Run(); err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
@@ -22,46 +21,42 @@ func buildHashicorpPlugin() {
|
|||||||
|
|
||||||
func removeHashicorpPlugin() {
|
func removeHashicorpPlugin() {
|
||||||
fmt.Println("[teardown] remove hashicorp plugin")
|
fmt.Println("[teardown] remove hashicorp plugin")
|
||||||
os.Remove("examples/debugtalk.bin")
|
os.Remove("debugtalk.bin")
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestInitHashicorpPlugin(t *testing.T) {
|
func TestInitHashicorpPlugin(t *testing.T) {
|
||||||
buildHashicorpPlugin()
|
buildHashicorpPlugin()
|
||||||
defer removeHashicorpPlugin()
|
defer removeHashicorpPlugin()
|
||||||
|
|
||||||
f, err := host.Init("examples/debugtalk.bin")
|
plugin, err := Init("debugtalk.bin")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
defer host.Quit()
|
defer plugin.Quit()
|
||||||
|
|
||||||
v1, err := f.GetNames()
|
if !assert.True(t, plugin.Has("sum_ints")) {
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
if !assert.Contains(t, v1, "sum_ints") {
|
if !assert.True(t, plugin.Has("concatenate")) {
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
if !assert.Contains(t, v1, "concatenate") {
|
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
var v2 interface{}
|
var v2 interface{}
|
||||||
v2, err = f.Call("sum_ints", 1, 2, 3, 4)
|
v2, err = plugin.Call("sum_ints", 1, 2, 3, 4)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
if !assert.Equal(t, 10, v2) {
|
if !assert.Equal(t, 10, v2) {
|
||||||
t.Fail()
|
t.Fail()
|
||||||
}
|
}
|
||||||
v2, err = f.Call("sum_two_int", 1, 2)
|
v2, err = plugin.Call("sum_two_int", 1, 2)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
if !assert.Equal(t, 3, v2) {
|
if !assert.Equal(t, 3, v2) {
|
||||||
t.Fail()
|
t.Fail()
|
||||||
}
|
}
|
||||||
v2, err = f.Call("sum", 1, 2, 3.4, 5)
|
v2, err = plugin.Call("sum", 1, 2, 3.4, 5)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@@ -70,14 +65,14 @@ func TestInitHashicorpPlugin(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var v3 interface{}
|
var v3 interface{}
|
||||||
v3, err = f.Call("sum_two_string", "a", "b")
|
v3, err = plugin.Call("sum_two_string", "a", "b")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
if !assert.Equal(t, "ab", v3) {
|
if !assert.Equal(t, "ab", v3) {
|
||||||
t.Fail()
|
t.Fail()
|
||||||
}
|
}
|
||||||
v3, err = f.Call("sum_strings", "a", "b", "c")
|
v3, err = plugin.Call("sum_strings", "a", "b", "c")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@@ -85,7 +80,7 @@ func TestInitHashicorpPlugin(t *testing.T) {
|
|||||||
t.Fail()
|
t.Fail()
|
||||||
}
|
}
|
||||||
|
|
||||||
v3, err = f.Call("concatenate", "a", 2, "c", 3.4)
|
v3, err = plugin.Call("concatenate", "a", 2, "c", 3.4)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package hrp
|
package common
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
@@ -10,7 +10,6 @@ import (
|
|||||||
|
|
||||||
"github.com/rs/zerolog/log"
|
"github.com/rs/zerolog/log"
|
||||||
|
|
||||||
"github.com/httprunner/hrp/internal/builtin"
|
|
||||||
"github.com/httprunner/hrp/internal/ga"
|
"github.com/httprunner/hrp/internal/ga"
|
||||||
pluginHost "github.com/httprunner/hrp/plugin/host"
|
pluginHost "github.com/httprunner/hrp/plugin/host"
|
||||||
pluginShared "github.com/httprunner/hrp/plugin/shared"
|
pluginShared "github.com/httprunner/hrp/plugin/shared"
|
||||||
@@ -24,11 +23,11 @@ const (
|
|||||||
hashicorpPyPluginFile pluginFile = pluginShared.Name + ".py"
|
hashicorpPyPluginFile pluginFile = pluginShared.Name + ".py"
|
||||||
)
|
)
|
||||||
|
|
||||||
type hrpPlugin interface {
|
type Plugin interface {
|
||||||
init(path string) error // init plugin
|
Init(path string) error // init plugin
|
||||||
has(funcName string) bool // check if plugin has function
|
Has(funcName string) bool // check if plugin has function
|
||||||
call(funcName string, args ...interface{}) (interface{}, error) // call function
|
Call(funcName string, args ...interface{}) (interface{}, error) // call function
|
||||||
quit() error // quit plugin
|
Quit() error // quit plugin
|
||||||
}
|
}
|
||||||
|
|
||||||
// goPlugin implements golang official plugin
|
// goPlugin implements golang official plugin
|
||||||
@@ -37,7 +36,7 @@ type goPlugin struct {
|
|||||||
cachedFunctions map[string]reflect.Value // cache loaded functions to improve performance
|
cachedFunctions map[string]reflect.Value // cache loaded functions to improve performance
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *goPlugin) init(path string) error {
|
func (p *goPlugin) Init(path string) error {
|
||||||
if runtime.GOOS == "windows" {
|
if runtime.GOOS == "windows" {
|
||||||
log.Warn().Msg("go plugin does not support windows")
|
log.Warn().Msg("go plugin does not support windows")
|
||||||
return fmt.Errorf("go plugin does not support windows")
|
return fmt.Errorf("go plugin does not support windows")
|
||||||
@@ -67,7 +66,7 @@ func (p *goPlugin) init(path string) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *goPlugin) has(funcName string) bool {
|
func (p *goPlugin) Has(funcName string) bool {
|
||||||
fn, ok := p.cachedFunctions[funcName]
|
fn, ok := p.cachedFunctions[funcName]
|
||||||
if ok {
|
if ok {
|
||||||
return fn.IsValid()
|
return fn.IsValid()
|
||||||
@@ -90,12 +89,15 @@ func (p *goPlugin) has(funcName string) bool {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *goPlugin) call(funcName string, args ...interface{}) (interface{}, error) {
|
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]
|
fn := p.cachedFunctions[funcName]
|
||||||
return pluginShared.CallFunc(fn, args...)
|
return CallFunc(fn, args...)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *goPlugin) quit() error {
|
func (p *goPlugin) Quit() error {
|
||||||
// no need to quit for go plugin
|
// no need to quit for go plugin
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@@ -106,7 +108,7 @@ type hashicorpPlugin struct {
|
|||||||
cachedFunctions map[string]bool // cache loaded functions to improve performance
|
cachedFunctions map[string]bool // cache loaded functions to improve performance
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *hashicorpPlugin) init(path string) error {
|
func (p *hashicorpPlugin) Init(path string) error {
|
||||||
|
|
||||||
f, err := pluginHost.Init(path)
|
f, err := pluginHost.Init(path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -120,7 +122,7 @@ func (p *hashicorpPlugin) init(path string) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *hashicorpPlugin) has(funcName string) bool {
|
func (p *hashicorpPlugin) Has(funcName string) bool {
|
||||||
flag, ok := p.cachedFunctions[funcName]
|
flag, ok := p.cachedFunctions[funcName]
|
||||||
if ok {
|
if ok {
|
||||||
return flag
|
return flag
|
||||||
@@ -142,45 +144,48 @@ func (p *hashicorpPlugin) has(funcName string) bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *hashicorpPlugin) call(funcName string, args ...interface{}) (interface{}, error) {
|
func (p *hashicorpPlugin) Call(funcName string, args ...interface{}) (interface{}, error) {
|
||||||
return p.FuncCaller.Call(funcName, args...)
|
return p.FuncCaller.Call(funcName, args...)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *hashicorpPlugin) quit() error {
|
func (p *hashicorpPlugin) Quit() error {
|
||||||
// kill hashicorp plugin process
|
// kill hashicorp plugin process
|
||||||
pluginHost.Quit()
|
pluginHost.Quit()
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *parser) initPlugin(path string) error {
|
func Init(path string) (Plugin, error) {
|
||||||
if path == "" {
|
if path == "" {
|
||||||
return nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
var plugin Plugin
|
||||||
|
|
||||||
// priority: hashicorp plugin > go plugin > builtin functions
|
// priority: hashicorp plugin > go plugin > builtin functions
|
||||||
// locate hashicorp plugin file
|
// locate hashicorp plugin file
|
||||||
pluginPath, err := locatePlugin(path, hashicorpGoPluginFile)
|
pluginPath, err := locateFile(path, hashicorpGoPluginFile)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
// found hashicorp go plugin file
|
// found hashicorp go plugin file
|
||||||
p.plugin = &hashicorpPlugin{}
|
plugin = &hashicorpPlugin{}
|
||||||
return p.plugin.init(pluginPath)
|
err = plugin.Init(pluginPath)
|
||||||
|
return plugin, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// locate go plugin file
|
// locate go plugin file
|
||||||
pluginPath, err = locatePlugin(path, goPluginFile)
|
pluginPath, err = locateFile(path, goPluginFile)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
// found go plugin file
|
// found go plugin file
|
||||||
p.plugin = &goPlugin{}
|
plugin = &goPlugin{}
|
||||||
return p.plugin.init(pluginPath)
|
err = plugin.Init(pluginPath)
|
||||||
|
return plugin, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// plugin not found
|
// plugin not found
|
||||||
return nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// locatePlugin searches destPluginFile upward recursively until current
|
// locateFile searches destFile upward recursively until current
|
||||||
// working directory or system root dir.
|
// working directory or system root dir.
|
||||||
func locatePlugin(startPath string, destPluginFile pluginFile) (string, error) {
|
func locateFile(startPath string, destFile pluginFile) (string, error) {
|
||||||
stat, err := os.Stat(startPath)
|
stat, err := os.Stat(startPath)
|
||||||
if os.IsNotExist(err) {
|
if os.IsNotExist(err) {
|
||||||
return "", err
|
return "", err
|
||||||
@@ -195,7 +200,7 @@ func locatePlugin(startPath string, destPluginFile pluginFile) (string, error) {
|
|||||||
startDir, _ = filepath.Abs(startDir)
|
startDir, _ = filepath.Abs(startDir)
|
||||||
|
|
||||||
// convention over configuration
|
// convention over configuration
|
||||||
pluginPath := filepath.Join(startDir, string(destPluginFile))
|
pluginPath := filepath.Join(startDir, string(destFile))
|
||||||
if _, err := os.Stat(pluginPath); err == nil {
|
if _, err := os.Stat(pluginPath); err == nil {
|
||||||
return pluginPath, nil
|
return pluginPath, nil
|
||||||
}
|
}
|
||||||
@@ -212,24 +217,5 @@ func locatePlugin(startPath string, destPluginFile pluginFile) (string, error) {
|
|||||||
return "", fmt.Errorf("searched to system root dir, plugin file not found")
|
return "", fmt.Errorf("searched to system root dir, plugin file not found")
|
||||||
}
|
}
|
||||||
|
|
||||||
return locatePlugin(parentDir, destPluginFile)
|
return locateFile(parentDir, destFile)
|
||||||
}
|
|
||||||
|
|
||||||
// callFunc calls function with arguments
|
|
||||||
// only support return at most one result value
|
|
||||||
func (p *parser) callFunc(funcName string, arguments ...interface{}) (interface{}, error) {
|
|
||||||
// call with plugin function
|
|
||||||
if p.plugin != nil && p.plugin.has(funcName) {
|
|
||||||
return p.plugin.call(funcName, arguments...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// get builtin function
|
|
||||||
function, ok := builtin.Functions[funcName]
|
|
||||||
if !ok {
|
|
||||||
return nil, fmt.Errorf("function %s is not found", funcName)
|
|
||||||
}
|
|
||||||
fn := reflect.ValueOf(function)
|
|
||||||
|
|
||||||
// call with builtin function
|
|
||||||
return pluginShared.CallFunc(fn, arguments...)
|
|
||||||
}
|
}
|
||||||
@@ -8,6 +8,7 @@ import (
|
|||||||
hclog "github.com/hashicorp/go-hclog"
|
hclog "github.com/hashicorp/go-hclog"
|
||||||
"github.com/hashicorp/go-plugin"
|
"github.com/hashicorp/go-plugin"
|
||||||
|
|
||||||
|
"github.com/httprunner/hrp/plugin/common"
|
||||||
pluginShared "github.com/httprunner/hrp/plugin/shared"
|
pluginShared "github.com/httprunner/hrp/plugin/shared"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -36,7 +37,7 @@ func (p *functionPlugin) Call(funcName string, args ...interface{}) (interface{}
|
|||||||
return nil, fmt.Errorf("function %s not found", funcName)
|
return nil, fmt.Errorf("function %s not found", funcName)
|
||||||
}
|
}
|
||||||
|
|
||||||
return pluginShared.CallFunc(fn, args...)
|
return common.CallFunc(fn, args...)
|
||||||
}
|
}
|
||||||
|
|
||||||
var functions = make(functionsMap)
|
var functions = make(functionsMap)
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ import (
|
|||||||
"github.com/rs/zerolog/log"
|
"github.com/rs/zerolog/log"
|
||||||
|
|
||||||
"github.com/httprunner/hrp/internal/ga"
|
"github.com/httprunner/hrp/internal/ga"
|
||||||
|
"github.com/httprunner/hrp/plugin/common"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Run starts to run API test with default configs.
|
// Run starts to run API test with default configs.
|
||||||
@@ -157,7 +158,7 @@ func (r *caseRunner) reset() *caseRunner {
|
|||||||
func (r *caseRunner) run() error {
|
func (r *caseRunner) run() error {
|
||||||
defer func() {
|
defer func() {
|
||||||
if r.parser.plugin != nil {
|
if r.parser.plugin != nil {
|
||||||
r.parser.plugin.quit()
|
r.parser.plugin.Quit()
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
config := r.TestCase.Config
|
config := r.TestCase.Config
|
||||||
@@ -504,7 +505,8 @@ func (r *caseRunner) parseConfig(config IConfig) error {
|
|||||||
cfg := config.ToStruct()
|
cfg := config.ToStruct()
|
||||||
|
|
||||||
// init plugin
|
// init plugin
|
||||||
err := r.parser.initPlugin(cfg.Path)
|
var err error
|
||||||
|
r.parser.plugin, err = common.Init(cfg.Path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user