Skip to content

Commit 8424338

Browse files
committed
print_stack_trace: Make skip_callers arg numerical
Realized it'd be very handy to support the removal of callers beyond the immediate caller in the `lib/log` module after experimenting with `@go.print_stack_trace` to `@go.log FATAL` calls.
1 parent 7416a7a commit 8424338

File tree

3 files changed

+60
-8
lines changed

3 files changed

+60
-8
lines changed

go-core.bash

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -141,16 +141,36 @@ declare _GO_SEARCH_PATHS=("$_GO_CORE_DIR/libexec")
141141

142142
# Prints the stack trace at the point of the call.
143143
#
144+
# If supplied, the `skip_callers` argument should be a positive integer (i.e. 1
145+
# or greater) to remove the caller (and possibly the caller's caller, and so on)
146+
# from the resulting stack trace.
147+
#
144148
# Arguments:
145-
# omit_caller: If set, this function's caller is removed from the output
149+
# skip_callers: The number of callers to skip over when printing the stack
146150
@go.print_stack_trace() {
147-
local start_index="${1:+2}"
151+
local skip_callers="$1"
152+
local result=0
148153
local i
149154

150-
for ((i=${start_index:-1}; i != ${#FUNCNAME[@]}; ++i)); do
155+
if [[ -n "$skip_callers" && ! "$skip_callers" =~ ^[1-9][0-9]*$ ]]; then
156+
@go.printf '%s argument %s not a positive integer; printing full stack\n' \
157+
"$FUNCNAME" "'$skip_callers'" >&2
158+
result=1
159+
elif [[ "$skip_callers" -ge "${#FUNCNAME[@]}" ]]; then
160+
@go.printf '%s argument %d exceeds stack size %d; printing full stack\n' \
161+
"$FUNCNAME" "$skip_callers" "$((${#FUNCNAME[@]} - 1))" >&2
162+
result=1
163+
fi
164+
165+
if [[ "$result" -ne '0' ]]; then
166+
skip_callers=0
167+
fi
168+
169+
for ((i=$skip_callers + 1; i != ${#FUNCNAME[@]}; ++i)); do
151170
@go.printf ' %s:%s %s\n' "${BASH_SOURCE[$i]}" "${BASH_LINENO[$((i-1))]}" \
152171
"${FUNCNAME[$i]}"
153172
done
173+
return "$result"
154174
}
155175

156176
# Main driver of ./go script functionality.

lib/internal/use

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ for __go_module_name in "$@"; do
9191

9292
if [[ ! -f "$__go_module_file" ]]; then
9393
@go.printf 'ERROR: Module %s not found at:\n' "$__go_module_name" >&2
94-
@go.print_stack_trace omit_caller >&2
94+
@go.print_stack_trace 1 >&2
9595
exit 1
9696
fi
9797
fi
@@ -100,7 +100,7 @@ for __go_module_name in "$@"; do
100100
if ! . "$__go_module_file"; then
101101
@go.printf 'ERROR: Failed to import %s module from %s at:\n' \
102102
"$__go_module_name" "$__go_module_file" >&2
103-
@go.print_stack_trace omit_caller >&2
103+
@go.print_stack_trace 1 >&2
104104
exit 1
105105
fi
106106
done

tests/core/print-stack-trace.bats

Lines changed: 35 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ teardown() {
1313
}
1414

1515
@test "$SUITE: stack trace from top level of main ./go script without caller" {
16-
create_test_go_script '@go.print_stack_trace omit_caller'
16+
create_test_go_script '@go.print_stack_trace 1'
1717
run "$TEST_GO_SCRIPT"
1818
assert_success ''
1919
}
@@ -35,13 +35,45 @@ teardown() {
3535
@test "$SUITE: omit function caller from stack trace" {
3636
create_test_go_script \
3737
'print_stack() {' \
38-
" @go.print_stack_trace omit_caller" \
38+
" @go.print_stack_trace 1" \
3939
'}' \
4040
'print_stack'
4141
run "$TEST_GO_SCRIPT"
4242
assert_success " $TEST_GO_SCRIPT:6 main"
4343
}
4444

45+
@test "$SUITE: bad skip_callers argument prints entire trace" {
46+
create_test_go_script \
47+
'print_stack() {' \
48+
" @go.print_stack_trace foobar" \
49+
'}' \
50+
'print_stack'
51+
run "$TEST_GO_SCRIPT"
52+
53+
local error_msg=("@go.print_stack_trace argument 'foobar' not a positive"
54+
'integer; printing full stack')
55+
assert_failure
56+
assert_line_equals 0 "${error_msg[*]}"
57+
assert_line_equals 1 " $TEST_GO_SCRIPT:4 print_stack"
58+
assert_line_equals 2 " $TEST_GO_SCRIPT:6 main"
59+
}
60+
61+
@test "$SUITE: skipping too many callers prints entire trace" {
62+
create_test_go_script \
63+
'print_stack() {' \
64+
" @go.print_stack_trace 100" \
65+
'}' \
66+
'print_stack'
67+
run "$TEST_GO_SCRIPT"
68+
69+
local error_msg=('@go.print_stack_trace argument 100 exceeds stack size 2;'
70+
'printing full stack')
71+
assert_failure
72+
assert_line_equals 0 "${error_msg[*]}"
73+
assert_line_equals 1 " $TEST_GO_SCRIPT:4 print_stack"
74+
assert_line_equals 2 " $TEST_GO_SCRIPT:6 main"
75+
}
76+
4577
@test "$SUITE: stack trace from subcommand script" {
4678
create_test_go_script '@go "$@"'
4779
create_test_command_script 'foo' \
@@ -51,7 +83,7 @@ teardown() {
5183
'foo_func'
5284
create_test_command_script 'foo.d/bar' \
5385
'bar_func() {' \
54-
' @go.print_stack_trace omit_caller' \
86+
' @go.print_stack_trace 1' \
5587
'}' \
5688
'bar_func'
5789

0 commit comments

Comments
 (0)