315 lines
7.9 KiB
YAML
315 lines
7.9 KiB
YAML
name: "Options: functrace (-T)"
|
|||
|
|
cases:
|
||
|
|
#
|
||
|
|
# Basic functrace option behavior
|
||
|
|
#
|
||
|
|
- name: "functrace can be enabled and disabled"
|
||
|
|
stdin: |
|
||
|
|
set -T
|
||
|
|
echo "enabled: $-" | grep -q T && echo "T is set"
|
||
|
|
set +T
|
||
|
|
echo "disabled: $-" | grep -qv T && echo "T is unset"
|
||
|
|
|
||
|
|
#
|
||
|
|
# DEBUG trap inheritance in functions
|
||
|
|
#
|
||
|
|
- name: "DEBUG trap - does not fire in function without set -T"
|
||
|
|
known_failure: true # TODO(BASH_COMMAND): quotes differ
|
||
|
|
stdin: |
|
||
|
|
trap 'echo "[debug: $BASH_COMMAND]"' DEBUG
|
||
|
|
myfunc() {
|
||
|
|
echo "in func"
|
||
|
|
}
|
||
|
|
echo "before func"
|
||
|
|
myfunc
|
||
|
|
echo "after func"
|
||
|
|
|
||
|
|
- name: "DEBUG trap - fires in function with set -T"
|
||
|
|
known_failure: true # TODO(BASH_COMMAND): quotes differ
|
||
|
|
stdin: |
|
||
|
|
set -T
|
||
|
|
trap 'echo "[debug: $BASH_COMMAND]"' DEBUG
|
||
|
|
myfunc() {
|
||
|
|
echo "in func"
|
||
|
|
}
|
||
|
|
echo "before func"
|
||
|
|
myfunc
|
||
|
|
echo "after func"
|
||
|
|
|
||
|
|
#
|
||
|
|
# DEBUG trap inheritance in subshells
|
||
|
|
#
|
||
|
|
- name: "DEBUG trap - does not fire in subshell without set -T"
|
||
|
|
known_failure: true # TODO(BASH_COMMAND): quotes differ
|
||
|
|
stdin: |
|
||
|
|
trap 'echo "[debug: $BASH_COMMAND]"' DEBUG
|
||
|
|
echo "before subshell"
|
||
|
|
(echo "in subshell")
|
||
|
|
echo "after subshell"
|
||
|
|
|
||
|
|
- name: "DEBUG trap - fires in subshell with set -T"
|
||
|
|
known_failure: true # TODO(BASH_COMMAND): quotes differ
|
||
|
|
stdin: |
|
||
|
|
set -T
|
||
|
|
trap 'echo "[debug: $BASH_COMMAND]"' DEBUG
|
||
|
|
echo "before subshell"
|
||
|
|
(echo "in subshell")
|
||
|
|
echo "after subshell"
|
||
|
|
|
||
|
|
#
|
||
|
|
# DEBUG trap inheritance in command substitution
|
||
|
|
#
|
||
|
|
- name: "DEBUG trap - does not fire in command substitution without set -T"
|
||
|
|
known_failure: true # TODO(BASH_COMMAND): quotes differ
|
||
|
|
stdin: |
|
||
|
|
trap 'echo "[debug: $BASH_COMMAND]" >&2' DEBUG
|
||
|
|
echo "before"
|
||
|
|
result=$(echo "in substitution")
|
||
|
|
echo "result: $result"
|
||
|
|
|
||
|
|
- name: "DEBUG trap - fires in command substitution with set -T"
|
||
|
|
known_failure: true # TODO(BASH_COMMAND): quotes differ
|
||
|
|
stdin: |
|
||
|
|
set -T
|
||
|
|
trap 'echo "[debug: $BASH_COMMAND]" >&2' DEBUG
|
||
|
|
echo "before"
|
||
|
|
result=$(echo "in substitution")
|
||
|
|
echo "result: $result"
|
||
|
|
|
||
|
|
#
|
||
|
|
# DEBUG trap inheritance in pipelines
|
||
|
|
#
|
||
|
|
- name: "DEBUG trap - does not fire in pipeline without set -T"
|
||
|
|
known_failure: true # TODO(BASH_COMMAND): quotes differ
|
||
|
|
stdin: |
|
||
|
|
trap 'echo "[debug: $BASH_COMMAND]" >&2' DEBUG
|
||
|
|
echo "before"
|
||
|
|
echo "hello" | cat | cat
|
||
|
|
echo "after"
|
||
|
|
|
||
|
|
- name: "DEBUG trap - fires in pipeline with set -T"
|
||
|
|
known_failure: true # TODO(BASH_COMMAND): quotes differ
|
||
|
|
stdin: |
|
||
|
|
set -T
|
||
|
|
trap 'echo "[debug: $BASH_COMMAND]" >&2' DEBUG
|
||
|
|
echo "before"
|
||
|
|
echo "hello" | cat | cat
|
||
|
|
echo "after"
|
||
|
|
|
||
|
|
#
|
||
|
|
# RETURN trap inheritance in functions
|
||
|
|
#
|
||
|
|
- name: "RETURN trap - does not fire in called function without set -T"
|
||
|
|
stdin: |
|
||
|
|
trap 'echo "[return: $FUNCNAME]"' RETURN
|
||
|
|
inner() {
|
||
|
|
echo "in inner"
|
||
|
|
}
|
||
|
|
outer() {
|
||
|
|
echo "in outer"
|
||
|
|
inner
|
||
|
|
echo "outer continuing"
|
||
|
|
}
|
||
|
|
outer
|
||
|
|
echo "after"
|
||
|
|
|
||
|
|
- name: "RETURN trap - fires in called function with set -T"
|
||
|
|
known_failure: true # TODO(functrace): RETURN trap inheritance not implemented
|
||
|
|
stdin: |
|
||
|
|
set -T
|
||
|
|
trap 'echo "[return: ${FUNCNAME:-main}]"' RETURN
|
||
|
|
inner() {
|
||
|
|
echo "in inner"
|
||
|
|
}
|
||
|
|
outer() {
|
||
|
|
echo "in outer"
|
||
|
|
inner
|
||
|
|
echo "outer continuing"
|
||
|
|
}
|
||
|
|
outer
|
||
|
|
echo "after"
|
||
|
|
|
||
|
|
- name: "RETURN trap - fires for each nested function return with set -T"
|
||
|
|
known_failure: true # TODO(functrace): RETURN trap inheritance not implemented
|
||
|
|
stdin: |
|
||
|
|
set -T
|
||
|
|
trap 'echo "[return: ${FUNCNAME:-main} -> $?]"' RETURN
|
||
|
|
level3() { echo "level3"; return 3; }
|
||
|
|
level2() { echo "level2"; level3; return 2; }
|
||
|
|
level1() { echo "level1"; level2; return 1; }
|
||
|
|
level1
|
||
|
|
echo "done"
|
||
|
|
|
||
|
|
#
|
||
|
|
# Function-specific trace attribute (declare -t)
|
||
|
|
#
|
||
|
|
- name: "declare -t - enables trace for specific function"
|
||
|
|
known_failure: true # TODO(BASH_COMMAND): quotes differ
|
||
|
|
stdin: |
|
||
|
|
trap 'echo "[debug: $BASH_COMMAND]"' DEBUG
|
||
|
|
traced_func() {
|
||
|
|
echo "in traced"
|
||
|
|
}
|
||
|
|
untraced_func() {
|
||
|
|
echo "in untraced"
|
||
|
|
}
|
||
|
|
declare -t traced_func
|
||
|
|
echo "calling untraced"
|
||
|
|
untraced_func
|
||
|
|
echo "calling traced"
|
||
|
|
traced_func
|
||
|
|
echo "done"
|
||
|
|
|
||
|
|
- name: "declare +t - disables trace for specific function"
|
||
|
|
known_failure: true # TODO(BASH_COMMAND): quotes differ
|
||
|
|
stdin: |
|
||
|
|
set -T
|
||
|
|
trap 'echo "[debug: $BASH_COMMAND]"' DEBUG
|
||
|
|
myfunc() {
|
||
|
|
echo "in func"
|
||
|
|
}
|
||
|
|
declare +t myfunc
|
||
|
|
echo "calling func"
|
||
|
|
myfunc
|
||
|
|
echo "done"
|
||
|
|
|
||
|
|
- name: "declare -f - shows trace attribute"
|
||
|
|
stdin: |
|
||
|
|
myfunc() { echo hi; }
|
||
|
|
declare -t myfunc
|
||
|
|
declare -f myfunc | head -1
|
||
|
|
|
||
|
|
#
|
||
|
|
# Toggling set -T mid-script
|
||
|
|
#
|
||
|
|
- name: "set -T enabled mid-script affects subsequent calls"
|
||
|
|
known_failure: true # TODO(BASH_COMMAND): quotes differ
|
||
|
|
stdin: |
|
||
|
|
trap 'echo "[debug: $BASH_COMMAND]"' DEBUG
|
||
|
|
func1() { echo "in func1"; }
|
||
|
|
func2() { echo "in func2"; }
|
||
|
|
echo "calling func1 without -T"
|
||
|
|
func1
|
||
|
|
set -T
|
||
|
|
echo "calling func2 with -T"
|
||
|
|
func2
|
||
|
|
echo "done"
|
||
|
|
|
||
|
|
- name: "set +T disables inheritance mid-script"
|
||
|
|
known_failure: true # TODO(BASH_COMMAND): quotes differ
|
||
|
|
stdin: |
|
||
|
|
set -T
|
||
|
|
trap 'echo "[debug: $BASH_COMMAND]"' DEBUG
|
||
|
|
func1() { echo "in func1"; }
|
||
|
|
func2() { echo "in func2"; }
|
||
|
|
echo "calling func1 with -T"
|
||
|
|
func1
|
||
|
|
set +T
|
||
|
|
echo "calling func2 without -T"
|
||
|
|
func2
|
||
|
|
echo "done"
|
||
|
|
|
||
|
|
#
|
||
|
|
# DEBUG trap inheritance in background jobs
|
||
|
|
#
|
||
|
|
- name: "DEBUG trap - in background job with set -T"
|
||
|
|
stdin: |
|
||
|
|
set -T
|
||
|
|
trap 'echo "[debug]" >&2' DEBUG
|
||
|
|
{
|
||
|
|
echo "in background"
|
||
|
|
} &
|
||
|
|
wait
|
||
|
|
echo "done"
|
||
|
|
|
||
|
|
#
|
||
|
|
# DEBUG trap inheritance in process substitution
|
||
|
|
#
|
||
|
|
- name: "DEBUG trap - in process substitution with set -T"
|
||
|
|
stdin: |
|
||
|
|
set -T
|
||
|
|
trap 'echo "[debug]" >&2' DEBUG
|
||
|
|
cat <(echo "from procsub")
|
||
|
|
echo "done"
|
||
|
|
|
||
|
|
#
|
||
|
|
# BASH_COMMAND visibility in DEBUG trap with functrace
|
||
|
|
#
|
||
|
|
- name: "BASH_COMMAND in function with set -T"
|
||
|
|
known_failure: true # TODO(BASH_COMMAND): quotes differ
|
||
|
|
stdin: |
|
||
|
|
set -T
|
||
|
|
trap 'echo "cmd: $BASH_COMMAND"' DEBUG
|
||
|
|
myfunc() {
|
||
|
|
local v=10
|
||
|
|
echo "v=$v"
|
||
|
|
}
|
||
|
|
myfunc
|
||
|
|
|
||
|
|
#
|
||
|
|
# Nested functions with varying trace states
|
||
|
|
#
|
||
|
|
- name: "Outer function traced, inner function not traced"
|
||
|
|
stdin: |
|
||
|
|
trap 'echo "[debug in ${FUNCNAME:-main}]"' DEBUG
|
||
|
|
inner() {
|
||
|
|
echo "inner"
|
||
|
|
}
|
||
|
|
outer() {
|
||
|
|
echo "outer start"
|
||
|
|
inner
|
||
|
|
echo "outer end"
|
||
|
|
}
|
||
|
|
declare -t outer
|
||
|
|
outer
|
||
|
|
echo "done"
|
||
|
|
|
||
|
|
- name: "Only inner function traced"
|
||
|
|
stdin: |
|
||
|
|
trap 'echo "[debug in ${FUNCNAME:-main}]"' DEBUG
|
||
|
|
inner() {
|
||
|
|
echo "inner"
|
||
|
|
}
|
||
|
|
outer() {
|
||
|
|
echo "outer start"
|
||
|
|
inner
|
||
|
|
echo "outer end"
|
||
|
|
}
|
||
|
|
declare -t inner
|
||
|
|
outer
|
||
|
|
echo "done"
|
||
|
|
|
||
|
|
#
|
||
|
|
# RETURN trap with sourced scripts and set -T
|
||
|
|
#
|
||
|
|
- name: "RETURN trap - fires for function in sourced script with set -T"
|
||
|
|
known_failure: true # TODO(functrace): RETURN trap inheritance not implemented
|
||
|
|
test_files:
|
||
|
|
- path: "sourced.sh"
|
||
|
|
contents: |
|
||
|
|
sourced_func() {
|
||
|
|
echo "in sourced_func"
|
||
|
|
}
|
||
|
|
sourced_func
|
||
|
|
stdin: |
|
||
|
|
set -T
|
||
|
|
trap 'echo "[return: ${FUNCNAME:-main}]"' RETURN
|
||
|
|
. ./sourced.sh
|
||
|
|
echo "after source"
|
||
|
|
|
||
|
|
#
|
||
|
|
# Edge cases
|
||
|
|
#
|
||
|
|
- name: "DEBUG trap - count in deeply nested function calls with set -T"
|
||
|
|
known_failure: true # TODO(functrace): DEBUG trap count differs
|
||
|
|
stdin: |
|
||
|
|
set -T
|
||
|
|
count=0
|
||
|
|
trap 'count=$((count + 1))' DEBUG
|
||
|
|
a() { b; }
|
||
|
|
b() { c; }
|
||
|
|
c() { echo "deep"; }
|
||
|
|
a
|
||
|
|
echo "debug count: $count"
|
||
|
|
|