Browse Source

100% tests passed

main
pvincent 1 week ago
parent
commit
0cb5f5501d
  1. 52
      bin/miaou-bash
  2. 3
      locales/en.sh
  3. 6
      locales/es.sh
  4. 10
      locales/fr.sh
  5. 51
      test/miaou-bash.test.bash

52
bin/miaou-bash

@ -153,31 +153,39 @@ function on_error {
print_miaou_error "${BASH_SOURCE[1]}" "${BASH_LINENO[0]}" "${failure_code}" "${failure_type}" "${failure_payload}" print_miaou_error "${BASH_SOURCE[1]}" "${BASH_LINENO[0]}" "${failure_code}" "${failure_type}" "${failure_payload}"
load_tmp_error # cannot print_miaou_error after investigation load_tmp_error # cannot print_miaou_error after investigation
miaou_debug "<investigate_tmp_error pid=${BASHPID}>"
miaou_debug "<investigate_tmp_error_pass1 pid=${BASHPID}>"
if [[ ${#tmp_error[@]} -gt 1 ]]; then if [[ ${#tmp_error[@]} -gt 1 ]]; then
local last_error regex local last_error regex
last_error="${tmp_error[-2]}" # the second latest cause previous print_miaou_error above last_error="${tmp_error[-2]}" # the second latest cause previous print_miaou_error above
miaou_debug "<analyze last_error={${last_error}} locale=$MIAOU_LOCALE>"
if [[ "$MIAOU_LOCALE" == 'fr' ]]; then
NBSP=$'\xc2\xa0'
last_error="${last_error//$NBSP/ }"
miaou_debug "<strip_nbsp locale=$MIAOU_LOCALE/>" # FIXME: raise issue 'commande introuvable NBSP' within fr.po!
fi
regex='^(.*): line ([0-9]+): (.*): command not found$'
regex="$MSG_COMMAND_NOT_FOUND_REGEX"
if [[ $failure_code == 127 && "$last_error" =~ $regex ]]; then if [[ $failure_code == 127 && "$last_error" =~ $regex ]]; then
failure_type='COMMAND_NOT_FOUND' failure_type='COMMAND_NOT_FOUND'
failure_payload="${BASH_REMATCH[3]}" failure_payload="${BASH_REMATCH[3]}"
miaou_debug "<command_not_found payload=${failure_payload}/>" miaou_debug "<command_not_found payload=${failure_payload}/>"
else else
regex='^(.*): line ([0-9]+): (.*): No such file or directory$'
regex="$MSG_FILE_NOT_FOUND_REGEX"
if [[ $failure_code == 127 && "$last_error" =~ $regex ]]; then if [[ $failure_code == 127 && "$last_error" =~ $regex ]]; then
failure_type='FILE_NOT_FOUND' failure_type='FILE_NOT_FOUND'
failure_payload="${BASH_REMATCH[3]}" failure_payload="${BASH_REMATCH[3]}"
miaou_debug "<file_not_found payload=${failure_payload}/>" miaou_debug "<file_not_found payload=${failure_payload}/>"
elif ! is_true "$CHILD_PROCESS"; then elif ! is_true "$CHILD_PROCESS"; then
miaou_debug "<miaou_trace only=main>"
# in main process only, not from children! # in main process only, not from children!
local regex2 source lineno funcname local regex2 source lineno funcname
last_error="${tmp_error[-1]}" last_error="${tmp_error[-1]}"
regex2='^[[:space:]]+miaou_trace: source=(.*) lineno=(.*) funcname=(.*)$' regex2='^[[:space:]]+miaou_trace: source=(.*) lineno=(.*) funcname=(.*)$'
if [[ "$last_error" =~ $regex2 ]]; then if [[ "$last_error" =~ $regex2 ]]; then
miaou_debug "<miaou_trace>"
source="${BASH_REMATCH[1]}" source="${BASH_REMATCH[1]}"
lineno="${BASH_REMATCH[2]}" lineno="${BASH_REMATCH[2]}"
funcname="${BASH_REMATCH[3]}" funcname="${BASH_REMATCH[3]}"
@ -213,14 +221,14 @@ function on_error {
fi fi
break break
fi fi
# miaou_debug '</index>'
done done
miaou_debug "</miaou_trace/>"
fi fi
miaou_debug "</miaou_trace/>"
fi fi
fi fi
miaou_debug "</analyze>"
fi fi
miaou_debug '</investigate_tmp_error>'
miaou_debug '</investigate_tmp_error_pass1>'
fi fi
fi fi
@ -371,7 +379,7 @@ function dump_failure {
} }
function save_err_trace_to_main { function save_err_trace_to_main {
miaou_debug "<save_stacktrace_to_stderr count=${#error_source[@]} to=${MIAOU_BASH_ERROR_CHILDREN}>"
miaou_debug "<save_backtrace_to_stderr count=${#error_source[@]} to=${MIAOU_BASH_ERROR_CHILDREN}>"
local i source lineno funcname local i source lineno funcname
for i in "${tmp_error[@]}"; do >>"$MIAOU_BASH_ERROR_CHILDREN" echo "$i"; done for i in "${tmp_error[@]}"; do >>"$MIAOU_BASH_ERROR_CHILDREN" echo "$i"; done
for i in "${!error_source[@]}"; do for i in "${!error_source[@]}"; do
@ -381,15 +389,15 @@ function save_err_trace_to_main {
# miaou_debug "<trace source=${source} lineno=${lineno} funcname=${funcname}/>" # miaou_debug "<trace source=${source} lineno=${lineno} funcname=${funcname}/>"
>>"$MIAOU_BASH_ERROR_CHILDREN" echo -e "\tmiaou_trace: source=${source} lineno=${lineno} funcname=${funcname}" >>"$MIAOU_BASH_ERROR_CHILDREN" echo -e "\tmiaou_trace: source=${source} lineno=${lineno} funcname=${funcname}"
done done
miaou_debug "</save_stacktrace_to_stderr>"
miaou_debug "</save_backtrace_to_stderr>"
} }
function dump_stacktrace {
miaou_debug "<stacktrace count=${#error_source[@]}>"
function dump_backtrace {
miaou_debug "<backtrace count=${#error_source[@]}>"
local i source lineno funcname local i source lineno funcname
for i in "${!error_source[@]}"; do for i in "${!error_source[@]}"; do
tty_ansi FG_MAGENTA tty_ansi FG_MAGENTA
echo -n " ╟──▷"
echo -n " ╟──▷ "
tty_ansi STYLE_ITALIC tty_ansi STYLE_ITALIC
source="${error_source[$i]}" source="${error_source[$i]}"
lineno="${error_lineno[$i]}" lineno="${error_lineno[$i]}"
@ -404,7 +412,8 @@ function dump_stacktrace {
[[ $i -gt 0 ]] && tty_ansi FG_GRAY [[ $i -gt 0 ]] && tty_ansi FG_GRAY
fi fi
printf "%40s:%.4s" "$source" "$lineno"
local min_length=45 # TODO: compute from previous backtrace (children) and get the max
printf "%${min_length}s:%.4s" "$source" "$lineno"
tty_ansi RESET tty_ansi RESET
printf " \t%s" "$funcname" printf " \t%s" "$funcname"
@ -417,7 +426,7 @@ function dump_stacktrace {
echo echo
done done
miaou_debug '</stacktrace>'
miaou_debug '</backtrace>'
} }
function load_tmp_error { function load_tmp_error {
@ -517,9 +526,8 @@ function on_exit {
elif [[ ! -v failure_type ]]; then elif [[ ! -v failure_type ]]; then
if [[ ${#tmp_error[@]} -gt 0 ]]; then if [[ ${#tmp_error[@]} -gt 0 ]]; then
last_error="${tmp_error[-1]}" last_error="${tmp_error[-1]}"
miaou_debug "<investigate_tmp_error last={$last_error}>"
regex='^(.*): line ([0-9]+): (.*): unbound variable$'
miaou_debug "<investigate_tmp_error_pass2 last={$last_error}>"
regex="$MSG_UNBOUND_VARIABLE_REGEX"
if [[ $failure_code -eq 1 ]] && [[ "$last_error" =~ $regex ]]; then if [[ $failure_code -eq 1 ]] && [[ "$last_error" =~ $regex ]]; then
failure_type='UNBOUND_VARIABLE' failure_type='UNBOUND_VARIABLE'
failure_payload="${BASH_REMATCH[3]}" failure_payload="${BASH_REMATCH[3]}"
@ -535,7 +543,7 @@ function on_exit {
add_miaou_error "$source" "$line" "${failure_code}" "${failure_type}" "${failure_payload}" add_miaou_error "$source" "$line" "${failure_code}" "${failure_type}" "${failure_payload}"
miaou_debug "<unbound_variable source=${source} line=${line} payload=${failure_payload}/>" miaou_debug "<unbound_variable source=${source} line=${line} payload=${failure_payload}/>"
else else
regex='^(.*): line ([0-9]+): (.*): No such file or directory$'
regex="$MSG_SOURCE_NOT_FOUND_REGEX"
if [[ $failure_code -eq 1 ]] && [[ "$last_error" =~ $regex ]]; then if [[ $failure_code -eq 1 ]] && [[ "$last_error" =~ $regex ]]; then
failure_type='SOURCE_NOT_FOUND' failure_type='SOURCE_NOT_FOUND'
failure_payload="${BASH_REMATCH[3]}" failure_payload="${BASH_REMATCH[3]}"
@ -555,7 +563,7 @@ function on_exit {
failure_payload="$BASH_COMMAND" failure_payload="$BASH_COMMAND"
fi fi
fi fi
miaou_debug "</investigate_tmp_error>"
miaou_debug "</investigate_tmp_error_pass2>"
fi fi
fi fi
fi fi
@ -568,7 +576,7 @@ function on_exit {
else else
2>&3 >&4 dump_failure 2>&3 >&4 dump_failure
if [[ -v error_source ]]; then if [[ -v error_source ]]; then
2>&3 >&4 dump_stacktrace
2>&3 >&4 dump_backtrace
fi fi
fi fi
fi fi
@ -688,6 +696,7 @@ if [[ -v SCRIPT ]]; then
miaou_debug "<script found=$SCRIPT args_count=$#/>" miaou_debug "<script found=$SCRIPT args_count=$#/>"
[[ $# -gt 0 ]] && shift [[ $# -gt 0 ]] && shift
fi fi
if is_true "$CHILD_PROCESS"; then if is_true "$CHILD_PROCESS"; then
# any nested children # any nested children
exec 4>/dev/tty 2>"$MIAOU_BASH_ERROR" exec 4>/dev/tty 2>"$MIAOU_BASH_ERROR"
@ -702,10 +711,11 @@ else
exec 4>/dev/tty exec 4>/dev/tty
fi fi
exec 3>&2 2>"$MIAOU_BASH_ERROR" exec 3>&2 2>"$MIAOU_BASH_ERROR"
load_locale
miaou_debug "<main file=$BASH_ARGV0 pid=${BASHPID}/>" miaou_debug "<main file=$BASH_ARGV0 pid=${BASHPID}/>"
fi fi
load_locale
# shellcheck source=/dev/null # shellcheck source=/dev/null
if [[ "$HEREDOC" == true ]]; then if [[ "$HEREDOC" == true ]]; then
miaou_debug '<source heredoc/>' miaou_debug '<source heredoc/>'

3
locales/en.sh

@ -1,2 +1,5 @@
# shellcheck disable=SC2034 # shellcheck disable=SC2034
MSG_UNBOUND_VARIABLE_REGEX='^(.*): line ([0-9]+): (.*): unbound variable$' MSG_UNBOUND_VARIABLE_REGEX='^(.*): line ([0-9]+): (.*): unbound variable$'
MSG_COMMAND_NOT_FOUND_REGEX='^(.*): line ([0-9]+): (.*): command not found$'
MSG_FILE_NOT_FOUND_REGEX='^(.*): line ([0-9]+): (.*): No such file or directory$'
MSG_SOURCE_NOT_FOUND_REGEX='^(.*): line ([0-9]+): (.*): No such file or directory$'

6
locales/es.sh

@ -1,3 +1,5 @@
# shellcheck disable=SC2034 # shellcheck disable=SC2034
MSG_UNBOUND_VARIABLE_REGEX='^(.*): line ([0-9]+): (.*): unbound variable$'
MSG_UNBOUND_VARIABLE_REGEX='^(.*): línea ([0-9]+): (.*): variable sin asignar$' #note the extra ' ' (compare with locale en)
MSG_COMMAND_NOT_FOUND_REGEX='^(.*): línea ([0-9]+): (.*): orden no encontrada$'
MSG_FILE_NOT_FOUND_REGEX='^(.*): línea ([0-9]+): (.*): No existe el fichero o el directorio$'
MSG_SOURCE_NOT_FOUND_REGEX='^(.*): línea ([0-9]+): (.*): No existe el fichero o el directorio$'

10
locales/fr.sh

@ -1,2 +1,10 @@
# shellcheck disable=SC2034 # shellcheck disable=SC2034
MSG_UNBOUND_VARIABLE_REGEX='^(.*): line ([0-9]+): (.*): unbound variable$'
# note the extra ' ' (compare with locale en) => raise issue fr.po
MSG_UNBOUND_VARIABLE_REGEX='^(.*): ligne ([0-9]+): (.*) : variable sans liaison$'
# extra ' ' + weird NBSP (removed programmatically) => raise issue fr.po too
MSG_COMMAND_NOT_FOUND_REGEX='^(.*): ligne ([0-9]+): (.*) : commande introuvable$'
MSG_FILE_NOT_FOUND_REGEX='^(.*): ligne ([0-9]+): (.*): Aucun fichier ou dossier de ce nom$'
MSG_SOURCE_NOT_FOUND_REGEX='^(.*): ligne ([0-9]+): (.*): Aucun fichier ou dossier de ce nom$'

51
test/miaou-bash.test.bash

@ -61,13 +61,18 @@ function assert_grep {
function fail_type { function fail_type {
((test_count++)) ((test_count++))
local success regex hint_message
local success regex hint_message cmd
success=false success=false
hint_message="${3:-}" hint_message="${3:-}"
[[ -v TEST_LANG ]] && cmd="LANG=$TEST_LANG " || cmd=''
cmd="$MIAOU_BASH_DIR/test/stub/scenario.bash $1" cmd="$MIAOU_BASH_DIR/test/stub/scenario.bash $1"
# mapfile -t stderr <<<"$(miaou-bash ./test/stub/scenario.bash "$1" 2>&1 >/dev/null 3>/dev/null)"
$cmd >/dev/null 2>"$TMP_ERR" 3>"$TMP_MIAOU"
if [[ -v TEST_LANG ]]; then
LANG="$TEST_LANG" $cmd >/dev/null 2>"$TMP_ERR" 3>"$TMP_MIAOU"
else
$cmd >/dev/null 2>"$TMP_ERR" 3>"$TMP_MIAOU"
fi
mapfile -t stderr <"$TMP_ERR" mapfile -t stderr <"$TMP_ERR"
last_error="${stderr[-1]}" last_error="${stderr[-1]}"
@ -83,7 +88,11 @@ function fail_type {
return return
fi fi
echo -n F echo -n F
failures+=("$cmd")
if [[ -v TEST_LANG ]]; then
failures+=("LANG=$TEST_LANG $cmd")
else
failures+=("$cmd")
fi
return 1 return 1
} }
@ -199,17 +208,32 @@ time {
assert pipe1 assert pipe1
assert pipe2 assert pipe2
TEST_LANG=en_US.UTF-8 fail_type unbound_variable UNBOUND_VARIABLE
TEST_LANG=es_ES.UTF-8 fail_type unbound_variable UNBOUND_VARIABLE
TEST_LANG=fr_FR.UTF-8 fail_type unbound_variable UNBOUND_VARIABLE
TEST_LANG=en_US.UTF-8 fail_type unbound_associative UNBOUND_VARIABLE
TEST_LANG=es_ES.UTF-8 fail_type unbound_associative UNBOUND_VARIABLE
TEST_LANG=fr_FR.UTF-8 fail_type unbound_associative UNBOUND_VARIABLE
TEST_LANG=en_US.UTF-8 fail_type command_not_found COMMAND_NOT_FOUND
TEST_LANG=es_ES.UTF-8 fail_type command_not_found COMMAND_NOT_FOUND
TEST_LANG=fr_FR.UTF-8 fail_type command_not_found COMMAND_NOT_FOUND
TEST_LANG=en_US.UTF-8 fail_type source_not_found SOURCE_NOT_FOUND
TEST_LANG=es_ES.UTF-8 fail_type source_not_found SOURCE_NOT_FOUND
TEST_LANG=fr_FR.UTF-8 fail_type source_not_found SOURCE_NOT_FOUND
TEST_LANG=en_US.UTF-8 fail_type file_not_found FILE_NOT_FOUND
TEST_LANG=es_ES.UTF-8 fail_type file_not_found FILE_NOT_FOUND
TEST_LANG=fr_FR.UTF-8 fail_type file_not_found FILE_NOT_FOUND
fail_type command_error COMMAND_ERROR
fail_type subshell_term SUBSHELL_ERROR fail_type subshell_term SUBSHELL_ERROR
fail_type unbound_variable UNBOUND_VARIABLE
fail_type unbound_associative UNBOUND_VARIABLE
fail_type false FALSE fail_type false FALSE
fail_type last_false COMMAND_ERROR fail_type last_false COMMAND_ERROR
fail_type command_error COMMAND_ERROR
fail_type subshell_term SUBSHELL_ERROR fail_type subshell_term SUBSHELL_ERROR
fail_type exit EXIT fail_type exit EXIT
fail_type command_not_found COMMAND_NOT_FOUND
fail_type source_not_found SOURCE_NOT_FOUND
fail_type file_not_found FILE_NOT_FOUND
fail_type child_error CHILD_ERROR 'prefer source than child process' fail_type child_error CHILD_ERROR 'prefer source than child process'
fail_stderr_count unbound_variable 1 fail_stderr_count unbound_variable 1
@ -223,13 +247,6 @@ time {
fail_stderr_grep no_script 'ERROR: script expected!' fail_stderr_grep no_script 'ERROR: script expected!'
assert_locales_equally_populated en es fr assert_locales_equally_populated en es fr
# TODO: I18n tests for:
# /opt/miaou-bash/test/stub/scenario.bash unbound_variable
# /opt/miaou-bash/test/stub/scenario.bash unbound_associative
# /opt/miaou-bash/test/stub/scenario.bash command_not_found
# /opt/miaou-bash/test/stub/scenario.bash source_not_found
# /opt/miaou-bash/test/stub/scenario.bash file_not_found
} }
failed=${#failures[@]} failed=${#failures[@]}
success=$((test_count - failed)) success=$((test_count - failed))

Loading…
Cancel
Save