Add bdl-lib to assist the programmer in debugging scripts and tests.
---
bdl-exmpl.sh | 46 ++++++++++++
bdl-lib.sh | 215 +++++++++++++++++++++++++++++++++++++++++++++++++++++
t/t0014-bdl-lib.sh | 115 ++++++++++++++++++++++++++++
t/test-lib.sh | 4 +
4 files changed, 380 insertions(+)
create mode 100755 bdl-exmpl.sh
create mode 100644 bdl-lib.sh
create mode 100755 t/t0014-bdl-lib.sh
diff --git a/bdl-exmpl.sh b/bdl-exmpl.sh
new file mode 100755
index 000000000..a47d82bca
--- /dev/null
+++ b/bdl-exmpl.sh
@@ -0,0 +1,46 @@
+#!/usr/bin/env bash
+# Examples using bdl-lib.sh
+
+# Source bdl-lib.sh
+. bdl-lib.sh
+
+# These both output to the default bdl_stdout=1
+bdl
+bdl "hi"
+bdl 1 "hi"
+
+# Output to a file as parameter
+echo -n >bdl_out.txt
+bdl bdl_out.txt "hi to bdl_out.txt"
+cat bdl_out.txt
+
+# Output to a file via bdl_dst
+echo -n >bdl_out.txt
+bdl_dst=bdl_out.txt
+bdl "hi to bdl_out.txt"
+cat bdl_out.txt
+bdl_dst=
+
+# Output to FD 5 connected to 1 via bdl_stdout
+bdl_stdout=5
+exec 5>&1
+bdl
+bdl "hi"
+bdl 5 "hi"
+exec 1>&5
+bdl_stdout=1
+
+# No printing to stdout
+echo -n >bdl_out.txt
+bdl_stdout=1
+bdl_dst=
+bdl 0 "not printed"
+bdl_stdout=0
+bdl
+bdl bdl_out.txt "printed to bdl_out.txt"
+bdl "not printed"
+bdl_stdout=1
+cat bdl_out.txt
+
+# This prints a "0" since there is only one parameter
+bdl 0
diff --git a/bdl-lib.sh b/bdl-lib.sh
new file mode 100644
index 000000000..cecf726bb
--- /dev/null
+++ b/bdl-lib.sh
@@ -0,0 +1,215 @@
+# ##################################################################
+# Bash Debug logger scriplet, source into your script to use.
+#
+# Write debug info with file name and line number.
+#
+# If the number of parameters == 0 then just the file
+# name and line number are printed to the destination.
+#
+# If the number of parameters == 1 then the file
+# name and line number are printed followed by a space
+# and then the parameter.
+#
+# If number of parameters > 1 then the first parameter
+# is the destination and the other parameters are written
+# to the destination.
+#
+# The destination can be the first parameter to bdl
+# or bdl_stdout or bdl_dst. If the destination is empty
+# then the data is written to bdl_stdout unless bdl_stdout
+# is empty or 0 then no data is written. Also, if the
+# destination is 0 no data is written.
+#
+# Examples:
+#$ cat -n bdl-exmpl.sh
+# 1 #!/usr/bin/env bash
+# 2 # Examples using bdl-lib.sh
+# 3
+# 4 # Source bdl-lib.sh
+# 5 . bdl-lib.sh
+# 6
+# 7 # These both output to the default bdl_stdout=1
+# 8 bdl
+# 9 bdl "hi"
+# 10 bdl 1 "hi"
+# 11
+# 12 # Output to a file as parameter
+# 13 echo -n >bdl_out.txt
+# 14 bdl bdl_out.txt "hi to bdl_out.txt"
+# 15 cat bdl_out.txt
+# 16
+# 17 # Output to a file via bdl_dst
+# 18 echo -n >bdl_out.txt
+# 19 bdl_dst=bdl_out.txt
+# 20 bdl "hi to bdl_out.txt"
+# 21 cat bdl_out.txt
+# 22 bdl_dst=
+# 23
+# 24 # Output to FD 5 connected to 1 via bdl_stdout
+# 25 bdl_stdout=5
+# 26 exec 5>&1
+# 27 bdl
+# 28 bdl "hi"
+# 29 bdl 5 "hi"
+# 30 exec 1>&5
+# 31 bdl_stdout=1
+# 32
+# 33 # No printing to stdout
+# 34 echo -n >bdl_out.txt
+# 35 bdl_stdout=1
+# 36 bdl_dst=
+# 37 bdl 0 "not printed"
+# 38 bdl_stdout=0
+# 39 bdl
+# 40 bdl bdl_out.txt "printed to bdl_out.txt"
+# 41 bdl "not printed"
+# 42 bdl_stdout=1
+# 43 cat bdl_out.txt
+# 44
+# 45 # This prints a "0" since there is only one parameter
+# 46 bdl 0
+#
+#
+# This is the output of bdl-exmpl.sh
+#
+# $ /bin/bash ./bdl-exmpl.sh
+# bdl-exmpl.sh:8:
+# bdl-exmpl.sh:9: hi
+# bdl-exmpl.sh:10: hi
+# bdl-exmpl.sh:14: hi to bdl_out.txt
+# bdl-exmpl.sh:20: hi to bdl_out.txt
+# bdl-exmpl.sh:27:
+# bdl-exmpl.sh:28: hi
+# bdl-exmpl.sh:29: hi
+# bdl-exmpl.sh:40: printed to bdl_out.txt
+# bdl-exmpl.sh:46: 0
+# ##################################################################
+
+BDL_LOADED=t
+
+# Prompt waitng for a return, q will exit
+bdl_pause () {
+ read -p "Line ${BASH_LINENO}: $@" bdl_pause_v_
+ [[ "$bdl_pause_v_" == "q" ]] && exit 1
+}
+
+# Initialize bdl variables if user didn't
+[[ "$bdl_dst" == "" ]] && bdl_dst=
+[[ "$bdl_stdout" == "" ]] && bdl_stdout=1
+[[ "$bdl_call_depth" == "" ]] && bdl_call_depth=0
+[[ "$bdl_call_stack_view" == "" ]] && bdl_call_stack_view=f
+
+# Initialize priviate bdl variables
+_bdl_call_lineno_offset_array=()
+_bdl_call_lineno_offset_array_idx=0
+_bdl_call_save=()
+_bdl_call_save_idx=0
+
+# Push bdl state and initialize call meta data.
+#
+# $1 is value for bdl_call_depth
+# $2 Optional text of a script with where bdl calls
+# will be found and used to compute lineno info.
+bdl_push () {
+ # Push the bdl data
+ _bdl_call_save[$_bdl_call_save_idx]="bdl_dst=$bdl_dst; \
+bdl_stdout=$bdl_stdout; \
+bdl_call_depth=$bdl_call_depth; \
+bdl_call_stack_view=$bdl_call_stack_view; \
+_bdl_call_lineno_offset_array=(${_bdl_call_lineno_offset_array[*]}); \
+_bdl_call_lineno_offset_array_idx=$_bdl_call_lineno_offset_array_idx"
+ _bdl_call_save_idx=$((_bdl_call_save_idx+1))
+
+ # Set meta data to fudge line numbers when bdl is used in tests.
+ bdl_call_depth=$1
+ shift
+ _bdl_call_lineno_offset_array_idx=0
+ _bdl_call_lineno_offset_array=()
+
+ if test "$1" != ""
+ then
+ # Read the script and find lines that begin with "bdl "
+ # and compute their offsets and saving them in an array
+ # that bdl will use to compute compute the lineno.
+ IFS=$'\n' read -d '' -r -a test_run_script_array <<< "$@"
+ for i in "${!test_run_script_array[@]}"; do
+ ln=${test_run_script_array[$i]}
+ tln="$(sed -e 's/^[[:space:]]*//' <<<$ln)"
+ if [[ "$tln" =~ ^bdl\ ]]
+ then
+ _bdl_call_lineno_offset_array+=$((i+1))
+ fi
+ done
+ fi
+}
+
+# Pop a previously save state.
+bdl_pop () {
+ _bdl_call_save_idx=$((_bdl_call_save_idx-1))
+ eval "${_bdl_call_save[$_bdl_call_save_idx]}"
+}
+
+# Write debug info with no source or line number
+bdl_nsl () {
+ if (( $# > 1 )); then
+ bdl_nsl_v_=$1
+ shift
+ else
+ bdl_nsl_v_=$bdl_dst
+ fi
+ [[ "$bdl_nsl_v_" == "" ]] && bdl_nsl_v_=$bdl_stdout
+ if [[ "$bdl_nsl_v_" != "" && "$@" != "" ]]; then
+ if [[ $bdl_nsl_v_ =~ ^[0-9] ]]; then
+ # There's probably a better way, but this "works":
+ case $bdl_nsl_v_ in
+ 1) echo "$@" 1>&1 ;;
+ 2) echo "$@" 1>&2 ;;
+ 3) echo "$@" 1>&3 ;;
+ 4) echo "$@" 1>&4 ;;
+ 5) echo "$@" 1>&5 ;;
+ 6) echo "$@" 1>&6 ;;
+ 7) echo "$@" 1>&7 ;;
+ 8) echo "$@" 1>&8 ;;
+ 9) echo "$@" 1>&9 ;;
+ *) : ;; # 0 and all other characters are nop's
+ esac
+ else
+ echo "$@" >> $bdl_nsl_v_
+ fi
+ fi
+ return 0
+}
+
+# Write debug info with file name and line number.
+bdl () {
+ #View the call stack
+ if test "$bdl_call_stack_view" != "f"
+ then
+ for i in "${!BASH_SOURCE[@]}"; do
+ (( $i == 0 )) && ln=${LINENO} ||
ln=${BASH_LINENO[${i}-1]}
+ bdl_nsl "[$i]
${BASH_SOURCE[$i]##*/}:${FUNCNAME[$i]}:${ln}"
+ done
+ fi
+
+ # The ${@:+ } only adds a space if $@ isn't empty.
+ # This is done because We allow the call to bdl to
+ # have no parameters and bdl then just prints the
+ # file name and line number which can be useful
+ # to know a line was processed but there is no need
+ # to print any other data.
+ bdl_ln=${BASH_LINENO[${bdl_call_depth}]}
+ if (( ${_bdl_call_lineno_offset_array_idx} <
${#_bdl_call_lineno_offset_array[@]} ))
+ then
+
bdl_offset=${_bdl_call_lineno_offset_array[$_bdl_call_lineno_offset_array_idx]}
+ bdl_ln=$((bdl_ln+bdl_offset))
+
_bdl_call_lineno_offset_array_idx=$((_bdl_call_lineno_offset_array_idx+1))
+ fi
+ if (( $# <= 1 )); then
+ bdl_nsl $bdl_dst
"${BASH_SOURCE[${bdl_call_depth}+1]##*/}:${bdl_ln}:${@:+ }$@"
+ else
+ v_=$1
+ shift
+ bdl_nsl $v_
"${BASH_SOURCE[${bdl_call_depth}+1]##*/}:${bdl_ln}:${@:+ }$@"
+ fi
+ return 0
+}
diff --git a/t/t0014-bdl-lib.sh b/t/t0014-bdl-lib.sh
new file mode 100755
index 000000000..a0546189a
--- /dev/null
+++ b/t/t0014-bdl-lib.sh
@@ -0,0 +1,115 @@
+#!/bin/sh
+
+test_description='test bash debug logger'
+
+# Only execute if shell is bash
+if test "$BASH_VERSION" != ""
+then
+
+. ../bdl-lib.sh
+bdl_dst=output
+
+fi
+
+. ./test-lib.sh
+
+test_expect_success 'do nothing' '
+ printf "" >output &&
+ printf "" >expected &&
+ test_cmp expected output
+'
+
+# Only execute if shell is bash
+if test "$BASH_VERSION" != ""
+then
+
+test_expect_success 'bdl_nsl only prints nothing' '
+ printf "" >output &&
+ bdl_nsl &&
+ printf "" >expected &&
+ test_cmp expected output
+'
+
+test_expect_success 'bdl_nsl with string prints string only' '
+ printf "" >output &&
+ bdl_nsl "test 1" &&
+ printf "test 1\n" >expected &&
+ test_cmp expected output
+'
+
+test_lineno=$LINENO
+test_expect_success 'bdl only print source and linenumber' '
+ printf "" >output &&
+ bdl &&
+ printf "t0014-bdl-lib.sh:$((test_lineno+3)):\n" >expected &&
+ test_cmp expected output
+'
+
+test_lineno=$LINENO
+test_expect_success 'bdl with string prints source and linenumber and string' '
+ printf "" >output &&
+ bdl "test 1" &&
+ printf "t0014-bdl-lib.sh:$((test_lineno+3)): test 1\n" >expected &&
+ test_cmp expected output
+'
+
+test_expect_success 'bdl 0 "nothing printed"' '
+ printf "" >output &&
+ printf "" >expected &&
+ bdl 0 "nothing printed" &&
+ test_cmp expected output
+'
+
+# Save current bdl_dst and restore when test completes
+#bdl_dst_save=$bdl_dst
+#bdl_stdout_save=$bdl_stdout
+bdl_push
+test_expect_success 'bdl bdl_dst empty bdl_stdout=0 nothing printed' '
+ bdl_dst= &&
+ bdl_stdout=0 &&
+ printf "" >output &&
+ printf "" >expected &&
+ bdl "nothing printed" &&
+ test_cmp expected output
+'
+#bdl_dst=$bdl_dst_save
+#bdl_stdout=$bdl_stdout_save
+bdl_pop
+
+# Testing subroutine calls from a test verify bdl_push/pop works
+# for direct calls and nested calls
+subsub_lineno=$LINENO
+subsub () {
+ bdl_push 0
+ bdl "subsub line"
+ bdl_pop
+ return "0"
+}
+
+sub_lineno=$LINENO
+sub () {
+ bdl_push 0
+ bdl "sub line"
+ subsub
+ bdl_pop
+ return "0"
+}
+
+test_expect_success 'test calls subsub' '
+ printf "" >output &&
+ subsub &&
+ printf "t0014-bdl-lib.sh:$((subsub_lineno+3)): subsub line\n" >expected
&&
+ test_cmp expected output
+'
+
+test_expect_success 'test sub calls subsub' '
+ printf "" >output &&
+ sub &&
+ printf "t0014-bdl-lib.sh:$((sub_lineno+3)): sub line
+t0014-bdl-lib.sh:$((subsub_lineno+3)): subsub line\n" >expected &&
+ test_cmp expected output
+'
+
+fi
+
+test_done
diff --git a/t/test-lib.sh b/t/test-lib.sh
index 7740d511d..85142e462 100644
--- a/t/test-lib.sh
+++ b/t/test-lib.sh
@@ -680,11 +680,15 @@ test_run_ () {
trace=$trace_tmp
fi
+ test "$BDL_LOADED" = "t" && bdl_push 4 "$@"
+
setup_malloc_check
test_eval_ "$1"
eval_ret=$?
teardown_malloc_check
+ test "$BDL_LOADED" = "t" && bdl_pop
+
if test -z "$immediate" || test $eval_ret = 0 ||
test -n "$expecting_failure" && test "$test_cleanup" != ":"
then
--
2.16.3