File size: 1,826 Bytes
ca7217f
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
package testkit

import (
	"errors"
	"fmt"
	"reflect"
	"regexp"
	"runtime"
	"strings"
)

// getFrame: https://stackoverflow.com/a/35213181/9243111
func getFrame(skipFrames int) runtime.Frame {
	targetFrameIndex := skipFrames + 2
	programCounters := make([]uintptr, targetFrameIndex+2)
	n := runtime.Callers(0, programCounters)
	frame := runtime.Frame{Function: "unknown"}
	if n > 0 {
		frames := runtime.CallersFrames(programCounters[:n])
		for more, frameIndex := true, 0; more && frameIndex <= targetFrameIndex; frameIndex++ {
			var frameCandidate runtime.Frame
			frameCandidate, more = frames.Next()
			if frameIndex == targetFrameIndex {
				frame = frameCandidate
			}
		}
	}
	return frame
}

func getStructFieldByName(s any, n string) (any, error) {
	if strings.TrimSpace(n) == "" {
		return nil, errors.New("field name cannot be empty")
	}
	v := reflect.ValueOf(s)
	switch v.Kind() {
	case reflect.Struct:
	case reflect.Pointer:
		return getStructFieldByName(v.Elem().Interface(), n)
	default:
		return nil, fmt.Errorf("wrong type: %s is a %s", v.Type(), v.Kind())
	}
	if !v.IsValid() {
		return nil, fmt.Errorf("invalid value of %s: %s", v.Type(), v)
	}
	for i, t := 0, v.Type(); i < t.NumField(); i++ {
		field := t.Field(i)
		if strings.EqualFold(field.Name, n) ||
			strings.EqualFold(field.Tag.Get("json"), n) {
			return v.Field(i).Interface(), nil
		}
	}
	return nil, fmt.Errorf("%s: field '%s' doesn't exist", v.Type(), n)
}

var _functionParser = regexp.MustCompile(`\.Test([^\W_]+)_([^\W_]+)`)

func parseTestFunction(function string) (string, string, error) {
	results := _functionParser.FindStringSubmatch(function)
	if len(results) != 3 {
		return "", "", fmt.Errorf("invalid test function name: %s", function)
	}
	return results[1] /* provider struct name */, results[2] /* test function name */, nil
}