diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-16 19:23:18 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-16 19:23:18 +0000 |
commit | 43a123c1ae6613b3efeed291fa552ecd909d3acf (patch) | |
tree | fd92518b7024bc74031f78a1cf9e454b65e73665 /src/runtime/start_line_test.go | |
parent | Initial commit. (diff) | |
download | golang-1.20-43a123c1ae6613b3efeed291fa552ecd909d3acf.tar.xz golang-1.20-43a123c1ae6613b3efeed291fa552ecd909d3acf.zip |
Adding upstream version 1.20.14.upstream/1.20.14upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/runtime/start_line_test.go')
-rw-r--r-- | src/runtime/start_line_test.go | 138 |
1 files changed, 138 insertions, 0 deletions
diff --git a/src/runtime/start_line_test.go b/src/runtime/start_line_test.go new file mode 100644 index 0000000..6c4faa8 --- /dev/null +++ b/src/runtime/start_line_test.go @@ -0,0 +1,138 @@ +// Copyright 2022 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package runtime_test + +import ( + "fmt" + "internal/testenv" + "runtime" + "testing" +) + +// The tests in this file test the function start line metadata included in +// _func and inlinedCall. TestStartLine hard-codes the start lines of functions +// in this file. If code moves, the test will need to be updated. +// +// The "start line" of a function should be the line containing the func +// keyword. + +func normalFunc() int { + return callerStartLine(false) +} + +func multilineDeclarationFunc() int { + return multilineDeclarationFunc1(0, 0, 0) +} + +//go:noinline +func multilineDeclarationFunc1( + a, b, c int) int { + return callerStartLine(false) +} + +func blankLinesFunc() int { + + // Some + // lines + // without + // code + + return callerStartLine(false) +} + +func inlineFunc() int { + return inlineFunc1() +} + +func inlineFunc1() int { + return callerStartLine(true) +} + +var closureFn func() int + +func normalClosure() int { + // Assign to global to ensure this isn't inlined. + closureFn = func() int { + return callerStartLine(false) + } + return closureFn() +} + +func inlineClosure() int { + return func() int { + return callerStartLine(true) + }() +} + +func TestStartLine(t *testing.T) { + // We test inlined vs non-inlined variants. We can't do that if + // optimizations are disabled. + testenv.SkipIfOptimizationOff(t) + + testCases := []struct{ + name string + fn func() int + want int + }{ + { + name: "normal", + fn: normalFunc, + want: 21, + }, + { + name: "multiline-declaration", + fn: multilineDeclarationFunc, + want: 30, + }, + { + name: "blank-lines", + fn: blankLinesFunc, + want: 35, + }, + { + name: "inline", + fn: inlineFunc, + want: 49, + }, + { + name: "normal-closure", + fn: normalClosure, + want: 57, + }, + { + name: "inline-closure", + fn: inlineClosure, + want: 64, + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + got := tc.fn() + if got != tc.want { + t.Errorf("start line got %d want %d", got, tc.want) + } + }) + } +} + +//go:noinline +func callerStartLine(wantInlined bool) int { + var pcs [1]uintptr + n := runtime.Callers(2, pcs[:]) + if n != 1 { + panic(fmt.Sprintf("no caller of callerStartLine? n = %d", n)) + } + + frames := runtime.CallersFrames(pcs[:]) + frame, _ := frames.Next() + + inlined := frame.Func == nil // Func always set to nil for inlined frames + if wantInlined != inlined { + panic(fmt.Sprintf("caller %s inlined got %v want %v", frame.Function, inlined, wantInlined)) + } + + return runtime.FrameStartLine(&frame) +} |