[RFC PATCH 1/1] bdl-lib.sh: add bash debug logger

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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




[Index of Archives]     [Linux Kernel Development]     [Gcc Help]     [IETF Annouce]     [DCCP]     [Netdev]     [Networking]     [Security]     [V4L]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux SCSI]     [Fedora Users]

  Powered by Linux