github.com/haraldrudell/parl@v0.4.176/pruntime/invocation-id_test.go (about) 1 /* 2 © 2022–present Harald Rudell <harald.rudell@gmail.com> (https://haraldrudell.github.io/haraldrudell/) 3 ISC License 4 */ 5 6 package pruntime 7 8 import ( 9 "runtime/debug" 10 "strings" 11 "sync" 12 "testing" 13 ) 14 15 type InvocationTestType struct{} 16 17 func (tt *InvocationTestType) FuncName(wg *sync.WaitGroup, stack *string) { 18 defer wg.Done() 19 20 *stack = tt.Func2() // second-level funciton to get more levels in the stack trace 21 } 22 23 func (tt *InvocationTestType) Func2() (stack string) { 24 return string(debug.Stack()) 25 } 26 27 func (tt *InvocationTestType) DoInvocation() (debugStack, actual string) { 28 var wg sync.WaitGroup 29 wg.Add(1) 30 go tt.Invocation(&wg, &debugStack, &actual) 31 wg.Wait() 32 return 33 } 34 35 func (tt *InvocationTestType) Invocation(wg *sync.WaitGroup, debugStack, actual *string) { 36 *debugStack = string(debug.Stack()) 37 *actual = Invocation(0) 38 wg.Done() 39 return 40 } 41 42 /* 43 We are generating a stack trace and want a real function name. 44 This means the function must be in the package scope. 45 Secondly, we want a short and predictable stack trace. 46 This means the function must be invoked as a goroutine. 47 */ 48 func TestInvocation(t *testing.T) { 49 invocationIndex := 1 50 debugStackIndex := 3 51 var tt InvocationTestType 52 debugStack, invocationResult := tt.DoInvocation() 53 54 // get the Invocation caller’s function name: 55 // github.com/haraldrudell/parl/runt.(*InvocationTestType).Invocation(0x0?, 0x0?, 0x14000104570, 0x14000104580) 56 actual := strings.Split(invocationResult, "\n")[invocationIndex] // github.com/haraldrudell/parl/runt.(*InvocationTestType).Invocation(0x0?, 0x0?, 0x14000104570, 0x14000104580) 57 58 // get our own debug.Stack value 59 expected := strings.Split(debugStack, "\n")[debugStackIndex] 60 61 if actual != expected { 62 t.Errorf("Invocation failed :\n%q expected:\n%q", actual, expected) 63 } 64 } 65 func TestDebugStack(t *testing.T) { 66 /* 67 var stack string 68 var wg sync.WaitGroup 69 var tt InvocationTestType 70 wg.Add(1) 71 go tt.FuncName(&wg, &stack) 72 wg.Wait() 73 */ 74 /* 75 stack string for go1.18: " 76 goroutine 19 [running]:\n 77 runtime/debug.Stack()\n 78 \t/opt/homebrew/Cellar/go/1.18/libexec/src/runtime/debug/stack.go:24 +0x68\n 79 github.com/haraldrudell/parl/runt.(*InvocationTestType).Func2(...)\n 80 \t/opt/sw/parl/runt/invocation_test.go:25\n 81 github.com/haraldrudell/parl/runt.(*InvocationTestType).FuncName(0x0?, 0x0?, 0x14000104570)\n 82 \t/opt/sw/parl/runt/invocation_test.go:21 +0x50 83 \ncreated by github.com/haraldrudell/parl/runt.TestInvocation\n 84 \t/opt/sw/parl/runt/invocation_test.go:37 +0xb0\n" 85 */ 86 //t.Errorf("stack string for %s:\n%s", runtime.Version(), strconv.Quote(stack)) 87 /* 88 the stack trace contains multiple newline-separated lines 89 first line is a goroutine line 90 then there are a series of 2-line stack frames, second line beginning with a tab 91 first frame is debug.Stack 92 last frame is the go statement creating the goroutine 93 the stack trace ends with a newline 94 */ 95 }