stacktrace.go 1.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566
  1. package httpexpect
  2. import (
  3. "regexp"
  4. "runtime"
  5. )
  6. // Stacktrace entry.
  7. type StacktraceEntry struct {
  8. Pc uintptr // Program counter
  9. File string // File path
  10. Line int // Line number
  11. Func *runtime.Func // Function information
  12. FuncName string // Function name (without package and parenthesis)
  13. FuncPackage string // Function package
  14. FuncOffset uintptr // Program counter offset relative to function start
  15. // True if this is program entry point
  16. // (like main.main or testing.tRunner)
  17. IsEntrypoint bool
  18. }
  19. var stacktraceFuncRe = regexp.MustCompile(`^(.+/[^.]+)\.(.+)$`)
  20. func stacktrace() []StacktraceEntry {
  21. callers := []StacktraceEntry{}
  22. for i := 1; ; i++ {
  23. pc, file, line, ok := runtime.Caller(i)
  24. if !ok {
  25. break
  26. }
  27. f := runtime.FuncForPC(pc)
  28. if f == nil {
  29. break
  30. }
  31. entry := StacktraceEntry{
  32. Pc: pc,
  33. File: file,
  34. Line: line,
  35. Func: f,
  36. }
  37. if m := stacktraceFuncRe.FindStringSubmatch(f.Name()); m != nil {
  38. entry.FuncName = m[2]
  39. entry.FuncPackage = m[1]
  40. } else {
  41. entry.FuncName = f.Name()
  42. }
  43. entry.FuncOffset = pc - f.Entry()
  44. switch f.Name() {
  45. case "main.main", "testing.tRunner":
  46. entry.IsEntrypoint = true
  47. }
  48. callers = append(callers, entry)
  49. }
  50. return callers
  51. }