Skip to content

Commit a0f4413

Browse files
committed
stack-trace: Move, add helpers to environment.bash
Seems less awkward to move `set_go_core_stack_trace_components` where every test that might possibly call `@go.log FATAL` can get to it. Also defined the generic `stack_trace_item` and the specific `log_command_stack_trace_item` in preparation for updates to the `log/log-command` test.
1 parent cd57da0 commit a0f4413

File tree

3 files changed

+91
-29
lines changed

3 files changed

+91
-29
lines changed

tests/core/helpers.bash

Lines changed: 0 additions & 26 deletions
This file was deleted.

tests/core/print-stack-trace.bats

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
#! /usr/bin/env bats
22

33
load ../environment
4-
load helpers
54

65
teardown() {
76
remove_test_go_rootdir
@@ -94,9 +93,9 @@ teardown() {
9493

9594
local IFS=$'\n'
9695
assert_lines_equal " $TEST_GO_SCRIPTS_DIR/foo.d/bar:5 source" \
97-
"${_GO_CORE_STACK_TRACE_COMPONENTS[@]}" \
96+
"${GO_CORE_STACK_TRACE_COMPONENTS[@]}" \
9897
" $TEST_GO_SCRIPTS_DIR/foo:3 foo_func" \
9998
" $TEST_GO_SCRIPTS_DIR/foo:5 source" \
100-
"${_GO_CORE_STACK_TRACE_COMPONENTS[@]}" \
99+
"${GO_CORE_STACK_TRACE_COMPONENTS[@]}" \
101100
" $TEST_GO_SCRIPT:3 main"
102101
}

tests/environment.bash

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,3 +81,92 @@ create_parent_and_subcommands() {
8181
remove_test_go_rootdir() {
8282
remove_bats_test_dirs
8383
}
84+
85+
# Get the stack trace of a line from a file or function as it would appear in
86+
# @go.print_stack_trace output.
87+
#
88+
# Arguments:
89+
# haystack_file: File containing the line
90+
# function_name: Function in which the line appears, 'main', or 'source'
91+
# needle_line: Line for which to produce a stack trace line
92+
stack_trace_item() {
93+
# Seriously, it's faster to create a script containing a `for` or `while read`
94+
# loop over a file and run it as a new process than it is to run it in-process
95+
# under Bats. Haven't yet figured out why.
96+
create_bats_test_script 'stack-trace-item' \
97+
"$(declare -f __stack_trace_item_impl)" \
98+
'__stack_trace_item_impl "$@"'
99+
"$BATS_TEST_ROOTDIR/stack-trace-item" "$@"
100+
}
101+
102+
log_command_stack_trace_item() {
103+
if [[ -z "$LOG_COMMAND_STACK_TRACE_ITEM" ]]; then
104+
export LOG_COMMAND_STACK_TRACE_ITEM="$(stack_trace_item \
105+
"$_GO_CORE_DIR/lib/log" '@go.log_command' ' "${args[@]}"')"
106+
fi
107+
echo "$LOG_COMMAND_STACK_TRACE_ITEM"
108+
}
109+
110+
# Call this before using "${GO_CORE_STACK_TRACE_COMPONENTS[@]}" to inject
111+
# entries from go-core.bash into your expected stack trace output.
112+
set_go_core_stack_trace_components() {
113+
local go_core_file="$_GO_CORE_DIR/go-core.bash"
114+
local stack_item
115+
local IFS=$'\n'
116+
117+
if [[ "${#GO_CORE_STACK_TRACE_COMPONENTS[@]}" -eq '0' ]]; then
118+
create_test_go_script '@go "$@"'
119+
create_test_command_script 'print-stack-trace' '@go.print_stack_trace'
120+
121+
for stack_item in $("$TEST_GO_SCRIPT" 'print-stack-trace'); do
122+
if [[ "$stack_item" =~ $go_core_file ]]; then
123+
GO_CORE_STACK_TRACE_COMPONENTS+=("$stack_item")
124+
elif [[ "${#_GO_CORE_STACK_TRACE_COMPONENTS[@]}" -ne '0' ]]; then
125+
return
126+
fi
127+
done
128+
export GO_CORE_STACK_TRACE_COMPONENTS
129+
fi
130+
}
131+
132+
__stack_trace_item_impl() {
133+
local haystack_file="$1"
134+
local function_name="$2"
135+
local function_pattern="^$function_name\\(\\) ?{\$"
136+
local needle="$3"
137+
local skip
138+
local inside_function
139+
local lineno=0
140+
local line
141+
local result=1
142+
143+
if [[ "$function_name" == 'main' || "$function_name" == 'source' ]]; then
144+
inside_function='false'
145+
fi
146+
147+
local IFS=$'\n'
148+
while read -r line; do
149+
((++lineno))
150+
if [[ -n "$skip" ]]; then
151+
if [[ "$line" == '}' ]]; then
152+
skip=
153+
fi
154+
elif [[ -z "$inside_function" && "$line" =~ $function_pattern ]]; then
155+
inside_function='true'
156+
elif [[ "$line" =~ ()\ {$ ]]; then
157+
skip='true'
158+
elif [[ "$inside_function" == 'true' && "$line" == '}' ]]; then
159+
break
160+
elif [[ "$line" == "$needle" ]]; then
161+
result=0
162+
break
163+
fi
164+
done <"$haystack_file"
165+
166+
if [[ "$result" -eq '0' ]]; then
167+
echo " $haystack_file:$lineno $function_name"
168+
else
169+
printf "ERROR: Line not found in $function_name: \"$needle\"\nat:\n" >&2
170+
fi
171+
return "$result"
172+
}

0 commit comments

Comments
 (0)