mirror of
https://github.com/httprunner/httprunner.git
synced 2026-09-04 23:16:57 +08:00
feat: call function with two argument
This commit is contained in:
+4
-2
@@ -1,13 +1,15 @@
|
|||||||
package builtin
|
package builtin
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"math"
|
||||||
"math/rand"
|
"math/rand"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
var Functions = map[string]interface{}{
|
var Functions = map[string]interface{}{
|
||||||
"sleep": sleep,
|
"sleep": sleep, // call with one argument
|
||||||
"gen_random_string": genRandomString,
|
"gen_random_string": genRandomString, // call with one argument
|
||||||
|
"max": math.Max, // call with two arguments
|
||||||
}
|
}
|
||||||
|
|
||||||
func sleep(nSecs int) {
|
func sleep(nSecs int) {
|
||||||
|
|||||||
@@ -169,9 +169,9 @@ func mergeVariables(variables, overriddenVariables map[string]interface{}) map[s
|
|||||||
return mergedVariables
|
return mergedVariables
|
||||||
}
|
}
|
||||||
|
|
||||||
// callFunction call function with arguments
|
// callFunc call function with arguments
|
||||||
// only support return at most one result value
|
// only support return at most one result value
|
||||||
func callFunction(funcName string, arguments []interface{}) (interface{}, error) {
|
func callFunc(funcName string, arguments []interface{}) (interface{}, error) {
|
||||||
function, ok := builtin.Functions[funcName]
|
function, ok := builtin.Functions[funcName]
|
||||||
if !ok {
|
if !ok {
|
||||||
// function not found
|
// function not found
|
||||||
@@ -184,25 +184,45 @@ func callFunction(funcName string, arguments []interface{}) (interface{}, error)
|
|||||||
return nil, fmt.Errorf("function %s is invalid", funcName)
|
return nil, fmt.Errorf("function %s is invalid", funcName)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if funcValue.Type().NumIn() != len(arguments) {
|
||||||
|
// function arguments not match
|
||||||
|
return nil, fmt.Errorf("function %s arguments number not match", funcName)
|
||||||
|
}
|
||||||
|
|
||||||
argumentsValue := make([]reflect.Value, len(arguments))
|
argumentsValue := make([]reflect.Value, len(arguments))
|
||||||
for index, argument := range arguments {
|
for index, argument := range arguments {
|
||||||
|
// ensure each argument type match
|
||||||
|
expectArgumentType := funcValue.Type().In(index)
|
||||||
|
actualArgumentType := reflect.TypeOf(argument)
|
||||||
|
if expectArgumentType != actualArgumentType {
|
||||||
|
// function argument type not match
|
||||||
|
err := fmt.Errorf("function %s argument %d type not match, expect %v, actual %v",
|
||||||
|
funcName, index, expectArgumentType, actualArgumentType)
|
||||||
|
log.Printf("[callFunction] error: %s", err.Error())
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
argumentsValue[index] = reflect.ValueOf(argument)
|
argumentsValue[index] = reflect.ValueOf(argument)
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Printf("[callFunction] func: %v, input arguments: %v", funcName, arguments)
|
log.Printf("[callFunction] func: %v, input arguments: %v", funcName, arguments)
|
||||||
resultValues := funcValue.Call(argumentsValue)
|
resultValues := funcValue.Call(argumentsValue)
|
||||||
log.Printf("[callFunction] output results: %v", resultValues)
|
log.Printf("[callFunction] output values: %v", resultValues)
|
||||||
|
|
||||||
if len(resultValues) == 0 {
|
if len(resultValues) > 1 {
|
||||||
return nil, nil
|
|
||||||
} else if len(resultValues) > 1 {
|
|
||||||
// function should return at most one value
|
// function should return at most one value
|
||||||
err := fmt.Errorf("function %s should return at most one value", funcName)
|
err := fmt.Errorf("function %s should return at most one value", funcName)
|
||||||
log.Printf("[callFunction] error: %s", err.Error())
|
log.Printf("[callFunction] error: %s", err.Error())
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// no return value
|
||||||
|
if len(resultValues) == 0 {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// return one value
|
||||||
// convert reflect.Value to interface{}
|
// convert reflect.Value to interface{}
|
||||||
result := resultValues[0].Interface()
|
result := resultValues[0].Interface()
|
||||||
|
log.Printf("[callFunction] output result: %+v(%T)", result, result)
|
||||||
return result, nil
|
return result, nil
|
||||||
}
|
}
|
||||||
|
|||||||
+15
-4
@@ -283,9 +283,9 @@ func TestMergeVariables(t *testing.T) {
|
|||||||
func TestCallFunction(t *testing.T) {
|
func TestCallFunction(t *testing.T) {
|
||||||
// call function without arguments
|
// call function without arguments
|
||||||
funcName := "sleep"
|
funcName := "sleep"
|
||||||
params := []interface{}{1}
|
arguments := []interface{}{1}
|
||||||
timeStart := time.Now()
|
timeStart := time.Now()
|
||||||
_, err := callFunction(funcName, params)
|
_, err := callFunc(funcName, arguments)
|
||||||
if !assert.Nil(t, err) {
|
if !assert.Nil(t, err) {
|
||||||
t.Fail()
|
t.Fail()
|
||||||
}
|
}
|
||||||
@@ -295,12 +295,23 @@ func TestCallFunction(t *testing.T) {
|
|||||||
|
|
||||||
// call function with one argument
|
// call function with one argument
|
||||||
funcName = "gen_random_string"
|
funcName = "gen_random_string"
|
||||||
params = []interface{}{10}
|
arguments = []interface{}{10}
|
||||||
result, err := callFunction(funcName, params)
|
result, err := callFunc(funcName, arguments)
|
||||||
if !assert.Nil(t, err) {
|
if !assert.Nil(t, err) {
|
||||||
t.Fail()
|
t.Fail()
|
||||||
}
|
}
|
||||||
if !assert.Equal(t, 10, len(result.(string))) {
|
if !assert.Equal(t, 10, len(result.(string))) {
|
||||||
t.Fail()
|
t.Fail()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// call function with two argument
|
||||||
|
funcName = "max"
|
||||||
|
arguments = []interface{}{float64(10), 9.99}
|
||||||
|
result, err = callFunc(funcName, arguments)
|
||||||
|
if !assert.Nil(t, err) {
|
||||||
|
t.Fail()
|
||||||
|
}
|
||||||
|
if !assert.Equal(t, float64(10), result.(float64)) {
|
||||||
|
t.Fail()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user