mirror of
https://github.com/httprunner/httprunner.git
synced 2026-08-28 19:47:14 +08:00
feat: parse functions
This commit is contained in:
@@ -55,6 +55,12 @@ func parseData(raw interface{}, variablesMapping map[string]interface{}) interfa
|
|||||||
value := rawValue.String()
|
value := rawValue.String()
|
||||||
value = strings.TrimSpace(value)
|
value = strings.TrimSpace(value)
|
||||||
return parseString(value, variablesMapping)
|
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{}
|
case reflect.Map: // convert any map to map[string]interface{}
|
||||||
parsedMap := make(map[string]interface{})
|
parsedMap := make(map[string]interface{})
|
||||||
for _, k := range rawValue.MapKeys() {
|
for _, k := range rawValue.MapKeys() {
|
||||||
@@ -109,6 +115,9 @@ func parseString(raw string, variablesMapping map[string]interface{}) interface{
|
|||||||
parsedString += remainedString[0:startPosition]
|
parsedString += remainedString[0:startPosition]
|
||||||
remainedString = remainedString[startPosition:]
|
remainedString = remainedString[startPosition:]
|
||||||
|
|
||||||
|
// Notice: notation priority
|
||||||
|
// $$ > ${func($a, $b)} > $var
|
||||||
|
|
||||||
// search $$, use $$ to escape $ notation
|
// search $$, use $$ to escape $ notation
|
||||||
if strings.HasPrefix(remainedString, "$$") { // found $$
|
if strings.HasPrefix(remainedString, "$$") { // found $$
|
||||||
matchStartPosition += 2
|
matchStartPosition += 2
|
||||||
@@ -117,6 +126,35 @@ func parseString(raw string, variablesMapping map[string]interface{}) interface{
|
|||||||
continue
|
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
|
// search variable like ${var} or $var
|
||||||
varMatched := regexCompileVariable.FindStringSubmatch(remainedString)
|
varMatched := regexCompileVariable.FindStringSubmatch(remainedString)
|
||||||
if len(varMatched) == 3 {
|
if len(varMatched) == 3 {
|
||||||
|
|||||||
@@ -166,6 +166,7 @@ func TestParseDataStringWithVariables(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestParseDataStringWithVariablesAbnormal(t *testing.T) {
|
func TestParseDataStringWithVariablesAbnormal(t *testing.T) {
|
||||||
variablesMapping := map[string]interface{}{
|
variablesMapping := map[string]interface{}{
|
||||||
"var_1": "abc",
|
"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