mirror of
https://github.com/httprunner/httprunner.git
synced 2026-05-13 17:29:56 +08:00
feat: parse functions
This commit is contained in:
38
parser.go
38
parser.go
@@ -55,6 +55,12 @@ func parseData(raw interface{}, variablesMapping map[string]interface{}) interfa
|
||||
value := rawValue.String()
|
||||
value = strings.TrimSpace(value)
|
||||
return parseString(value, variablesMapping)
|
||||
case reflect.Slice:
|
||||
parsedSlice := make([]interface{}, rawValue.Len())
|
||||
for i := 0; i < rawValue.Len(); i++ {
|
||||
parsedSlice[i] = parseData(rawValue.Index(i).Interface(), variablesMapping)
|
||||
}
|
||||
return parsedSlice
|
||||
case reflect.Map: // convert any map to map[string]interface{}
|
||||
parsedMap := make(map[string]interface{})
|
||||
for _, k := range rawValue.MapKeys() {
|
||||
@@ -109,6 +115,9 @@ func parseString(raw string, variablesMapping map[string]interface{}) interface{
|
||||
parsedString += remainedString[0:startPosition]
|
||||
remainedString = remainedString[startPosition:]
|
||||
|
||||
// Notice: notation priority
|
||||
// $$ > ${func($a, $b)} > $var
|
||||
|
||||
// search $$, use $$ to escape $ notation
|
||||
if strings.HasPrefix(remainedString, "$$") { // found $$
|
||||
matchStartPosition += 2
|
||||
@@ -117,6 +126,35 @@ func parseString(raw string, variablesMapping map[string]interface{}) interface{
|
||||
continue
|
||||
}
|
||||
|
||||
// search function like ${func($a, $b)}
|
||||
funcMatched := regexCompileFunction.FindStringSubmatch(remainedString)
|
||||
if len(funcMatched) == 3 {
|
||||
funcName := funcMatched[1]
|
||||
argsStr := funcMatched[2]
|
||||
arguments, err := parseFunctionArguments(argsStr)
|
||||
if err != nil {
|
||||
return raw
|
||||
}
|
||||
parsedArgs := parseData(arguments, variablesMapping).([]interface{})
|
||||
|
||||
result, err := callFunc(funcName, parsedArgs...)
|
||||
if err != nil {
|
||||
return raw
|
||||
}
|
||||
|
||||
if funcMatched[0] == raw {
|
||||
// raw_string is a function, e.g. "${add_one(3)}", return its eval value directly
|
||||
return result
|
||||
}
|
||||
|
||||
// raw_string contains one or many functions, e.g. "abc${add_one(3)}def"
|
||||
matchStartPosition += len(funcMatched[0])
|
||||
parsedString += fmt.Sprintf("%v", result)
|
||||
remainedString = raw[matchStartPosition:]
|
||||
log.Printf("[parseString] parsedString: %v, matchStartPosition: %v", parsedString, matchStartPosition)
|
||||
continue
|
||||
}
|
||||
|
||||
// search variable like ${var} or $var
|
||||
varMatched := regexCompileVariable.FindStringSubmatch(remainedString)
|
||||
if len(varMatched) == 3 {
|
||||
|
||||
@@ -166,6 +166,7 @@ func TestParseDataStringWithVariables(t *testing.T) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestParseDataStringWithVariablesAbnormal(t *testing.T) {
|
||||
variablesMapping := map[string]interface{}{
|
||||
"var_1": "abc",
|
||||
@@ -374,3 +375,35 @@ func TestParseFunctionArguments(t *testing.T) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestParseDataStringWithFunctions(t *testing.T) {
|
||||
variablesMapping := map[string]interface{}{
|
||||
"n": 5,
|
||||
"a": 12.3,
|
||||
"b": 3.45,
|
||||
}
|
||||
|
||||
if !assert.Len(t, parseData("${gen_random_string(5)}", variablesMapping), 5) {
|
||||
t.Fail()
|
||||
}
|
||||
if !assert.Len(t, parseData("${gen_random_string($n)}", variablesMapping), 5) {
|
||||
t.Fail()
|
||||
}
|
||||
|
||||
if !assert.Len(t, parseData("123${gen_random_string(5)}abc", variablesMapping), 11) {
|
||||
t.Fail()
|
||||
}
|
||||
if !assert.Len(t, parseData("123${gen_random_string($n)}abc", variablesMapping), 11) {
|
||||
t.Fail()
|
||||
}
|
||||
|
||||
if !assert.Equal(t, parseData("${max($a, $b)}", variablesMapping), 12.3) {
|
||||
t.Fail()
|
||||
}
|
||||
if !assert.Equal(t, parseData("abc${max($a, $b)}123", variablesMapping), "abc12.3123") {
|
||||
t.Fail()
|
||||
}
|
||||
if !assert.Equal(t, parseData("abc${max($a, 3.45)}123", variablesMapping), "abc12.3123") {
|
||||
t.Fail()
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user