Fix indentation & tests (partial) + update logging

This commit is contained in:
JeremyStar™ 2024-11-17 16:14:49 +01:00
parent 6368928cc2
commit 946263a453
Signed by: JeremyStarTM
GPG key ID: E366BAEF67E4704D
3 changed files with 255 additions and 274 deletions

View file

@ -25,88 +25,62 @@
# unless it licensed under the same license without modifications. # unless it licensed under the same license without modifications.
# Environment control
## => Restores the environment
## => Arguments: none
## => Returns: 0
function _bashutils_restore_environment() {
if [ -n "${_BASHUTILS_ENVIRONMENT_PREVIOUS_OPTIONS}" ]; then
[[ "${_BASHUTILS_ENVIRONMENT_PREVIOUS_OPTIONS}" == *"e"* ]] && set -e
[[ "${_BASHUTILS_ENVIRONMENT_PREVIOUS_OPTIONS}" != *"e"* ]] && set +e
[[ "${_BASHUTILS_ENVIRONMENT_PREVIOUS_OPTIONS}" == *"u"* ]] && set -u
[[ "${_BASHUTILS_ENVIRONMENT_PREVIOUS_OPTIONS}" != *"u"* ]] && set +u
[[ "${_BASHUTILS_ENVIRONMENT_PREVIOUS_OPTIONS}" == *"x"* ]] && set -x
[[ "${_BASHUTILS_ENVIRONMENT_PREVIOUS_OPTIONS}" != *"x"* ]] && set +x
[ -n "${_BASHUTILS_ENVIRONMENT_PREVIOUS_PIPEFAIL}" ] && set -o pipefail
[ -z "${_BASHUTILS_ENVIRONMENT_PREVIOUS_PIPEFAIL}" ] && set +o pipefail
unset _BASHUTILS_ENVIRONMENT_PREVIOUS_OPTIONS
fi
return 0
}
## => Resets the environment to optimal conditions for bashutils
## => Arguments:
## -> 1. none
## -> 2. [?...:command to execute]
## => Returns: 0 or the command's exit code if one is supplied
function _bashutils_reset_environment() {
export "_BASHUTILS_ENVIRONMENT_PREVIOUS_OPTIONS=${-}"
[ -o "pipefail" ] && export "_BASHUTILS_ENVIRONMENT_PREVIOUS_PIPEFAIL=true"
[ ! -o "pipefail" ] && export "_BASHUTILS_ENVIRONMENT_PREVIOUS_PIPEFAIL="
set -eo pipefail
set +ux
if [ -n "${*}" ]; then
# shellcheck disable=SC2068
${@}
EXITCODE="${?}"
_bashutils_restore_environment
return "${EXITCODE}"
fi
return 0
}
## => Resets the environment and returns the first argument.
## This is useful in situations where the environment shall
## be reset and the exit code preserved.
## => Arguments: <byte:exit code>
## => Returns: the provided exit code
function _bashutils_return_environment() {
_bashutils_restore_environment
return "${1:-0}"
}
# Logging # Logging
## => Handles log calls and prints the specified message correctly.
## => Arguments: <int:level_id> <str:level_name> <str...:message>
## => Returns: 0
function _bashutils_log() {
# Cancel if disallowed
[ ! "${BASHUTILS_LOGLEVEL}" -lt "${1}" ] && return
# Set variables
# -> Level
#LEVEL_ID=${1}
LEVEL_NAME=${2}
# -> Message
shift 2
MESSAGE=${*}
# -> Indentation
unset INDENTATION
for ((i=1; i <= BASHUTILS_SUBSHELL; i++))
do
INDENTATION="${INDENTATION}${BASHUTILS_LOGINDENTATION}"
done
# Add shadow
MESSAGE=${MESSAGE//\\n/\\n }
# Print
echo -e "${LEVEL_NAME} ${INDENTATION} ${MESSAGE}";
}
## => Prints a diagnostic message. ## => Prints a diagnostic message.
## => Arguments: <str...:message> ## => Arguments: <str...:message>
## => Returns: 0 ## => Returns: 0
function diag() { [ "${BASHUTILS_LOGLEVEL}" -lt 1 ] && echo -e "DIAG ${*//\\n/\\n }"; } function diag() { _bashutils_log "1" "DIAG" "${*}"; }
## => Prints a verbose message. ## => Prints a verbose message.
## => Arguments: <str...:message> ## => Arguments: <str...:message>
## => Returns: 0 ## => Returns: 0
function verb() { [ "${BASHUTILS_LOGLEVEL}" -lt 2 ] && echo -e "VERB ${*//\\n/\\n }"; } function verb() { _bashutils_log "2" "VERB" "${*}"; }
## => Prints a silent warning message. ## => Prints a silent warning message.
## => Arguments: <str...:message> ## => Arguments: <str...:message>
## => Returns: 0 ## => Returns: 0
function sarn() { [ "${BASHUTILS_LOGLEVEL}" -lt 3 ] && echo -e "SARN ${*//\\n/\\n }"; } function sarn() { _bashutils_log "3" "SARN" "${*}"; }
## => Prints an informational message. ## => Prints an informational message.
## => Arguments: <str...:message> ## => Arguments: <str...:message>
## => Returns: 0 ## => Returns: 0
function info() { [ "${BASHUTILS_LOGLEVEL}" -lt 4 ] && echo -e "INFO ${*//\\n/\\n }"; } function info() { _bashutils_log "4" "INFO" "${*}"; }
## => Prints a warning message. ## => Prints a warning message.
## => Arguments: <str...:message> ## => Arguments: <str...:message>
## => Returns: 0 ## => Returns: 0
function warn() { [ "${BASHUTILS_LOGLEVEL}" -lt 5 ] && echo -e "WARN ${*//\\n/\\n }"; } function warn() { _bashutils_log "5" "WARN" "${*}"; }
## => Prints an error message. ## => Prints an error message.
## => Arguments: <str...:message> ## => Arguments: <str...:message>
## => Returns: 0 ## => Returns: 0
function error() { [ "${BASHUTILS_LOGLEVEL}" -lt 6 ] && echo -e "ERR! ${*//\\n/\\n }" &> /dev/stderr; } function error() { _bashutils_log "6" "ERR!" "${*}" &> /dev/stderr; }
## => Handles crashes. ## => Handles crashes.
## => Arguments: <bool:terminate?> <str...:message> ## => Arguments: <bool:terminate?> <str...:message>
## => Returns: 0 ## => Returns: 0
function crash() { function crash() {
_bashutils_reset_environment
[ "${1}" == "true" ] && CRASH_TERMINATE=true || CRASH_TERMINATE=false [ "${1}" == "true" ] && CRASH_TERMINATE=true || CRASH_TERMINATE=false
shift shift
# shellcheck disable=SC2002 # shellcheck disable=SC2002
@ -135,7 +109,6 @@ $(for index in $(seq 0 1000); do if [ -z "$(caller "${index}")" ]; then break; e
$([ "${CRASH_TERMINATE}" == "false" ] && echo "!!! This crash will not terminate the shell !!!") $([ "${CRASH_TERMINATE}" == "false" ] && echo "!!! This crash will not terminate the shell !!!")
EOF EOF
[ "${CRASH_TERMINATE}" == "true" ] && exit 69 [ "${CRASH_TERMINATE}" == "true" ] && exit 69
_bashutils_restore_environment
} }
# Checks # Checks
@ -143,60 +116,60 @@ EOF
## => Checks whether the provided command name is an alias. ## => Checks whether the provided command name is an alias.
## => Arguments: <str:command name> ## => Arguments: <str:command name>
## => Returns: 0 if it is, 1 otherwise ## => Returns: 0 if it is, 1 otherwise
function is_command_alias() { _bashutils_reset_environment; [[ "$(type -t "${1}")" == alias ]]; _bashutils_return_environment ${?}; } function is_command_alias() { [[ "$(type -t "${1}")" == alias ]]; }
## => Checks whether the provided command name is a keyword. ## => Checks whether the provided command name is a keyword.
## => Arguments: <str:command name> ## => Arguments: <str:command name>
## => Returns: 0 if it is, 1 otherwise ## => Returns: 0 if it is, 1 otherwise
function is_command_keyword() { _bashutils_reset_environment; [[ "$(type -t "${1}")" == keyword ]]; _bashutils_return_environment ${?}; } function is_command_keyword() { [[ "$(type -t "${1}")" == keyword ]]; }
## => Checks whether the provided command name is a function. ## => Checks whether the provided command name is a function.
## => Arguments: <str:command name> ## => Arguments: <str:command name>
## => Returns: 0 if it is, 1 otherwise ## => Returns: 0 if it is, 1 otherwise
function is_command_function() { _bashutils_reset_environment; [[ "$(type -t "${1}")" == function ]]; _bashutils_return_environment ${?}; } function is_command_function() { [[ "$(type -t "${1}")" == function ]]; }
## => Checks whether the provided command name is a builtin. ## => Checks whether the provided command name is a builtin.
## => Arguments: <str:command name> ## => Arguments: <str:command name>
## => Returns: 0 if it is, 1 otherwise ## => Returns: 0 if it is, 1 otherwise
function is_command_builtin() { _bashutils_reset_environment; [[ "$(type -t "${1}")" == builtin ]]; _bashutils_return_environment ${?}; } function is_command_builtin() { [[ "$(type -t "${1}")" == builtin ]]; }
## => Checks whether the provided command name is a file. ## => Checks whether the provided command name is a file.
## => Arguments: <str:command name> ## => Arguments: <str:command name>
## => Returns: 0 if it is, 1 otherwise ## => Returns: 0 if it is, 1 otherwise
function is_command_file() { _bashutils_reset_environment; [[ "$(type -t "${1}")" == file ]]; _bashutils_return_environment ${?}; } function is_command_file() { [[ "$(type -t "${1}")" == file ]]; }
## => Checks whether the provided command name is defined. ## => Checks whether the provided command name is defined.
## => Arguments: <str:command name> ## => Arguments: <str:command name>
## => Returns: 0 if it is, 1 otherwise ## => Returns: 0 if it is, 1 otherwise
function is_command_defined() { _bashutils_reset_environment; [[ "$(type -t "${1}")" == "" ]]; _bashutils_return_environment ${?}; } function is_command_defined() { [[ "$(type -t "${1}")" == "" ]]; }
## Input type ## Input type
## => Checks whether the provided input is a bool. ## => Checks whether the provided input is a bool.
## => Arguments: <str:input> ## => Arguments: <str:input>
## => Returns: 0 if it is, 1 otherwise ## => Returns: 0 if it is, 1 otherwise
function is_input_bool() { _bashutils_reset_environment; [ "${1}" == "true" ] || [ "${1}" == "false" ]; _bashutils_return_environment "${?}"; } function is_input_bool() { [ "${1}" == "true" ] || [ "${1}" == "false" ]; }
## => Checks whether the provided input is a byte. ## => Checks whether the provided input is a byte.
## => Arguments: <str:input> ## => Arguments: <str:input>
## => Returns: 0 if it is, 1 otherwise ## => Returns: 0 if it is, 1 otherwise
function is_input_byte() { _bashutils_reset_environment; [[ "${1}" =~ ^[0-9]+$ ]] && [[ "${1}" -gt -1 ]] && [["${1}" -lt 256 ]]; _bashutils_return_environment "${?}"; } function is_input_byte() { [[ "${1}" =~ ^[0-9]+$ ]] && [[ "${1}" -gt -1 ]] && [[ "${1}" -lt 256 ]]; }
## => Checks whether the provided input is a integer/number. ## => Checks whether the provided input is a integer/number.
## => Arguments: <str:input> ## => Arguments: <str:input>
## => Returns: 0 if it is, 1 otherwise ## => Returns: 0 if it is, 1 otherwise
function is_input_int() { _bashutils_reset_environment; [[ "${1}" =~ ^[0-9]+$ ]]; _bashutils_return_environment "${?}"; } function is_input_int() { [[ "${1}" =~ ^[0-9]+$ ]]; }
## => Checks whether the provided input is a char. ## => Checks whether the provided input is a char.
## => Arguments: <str:input> ## => Arguments: <str:input>
## => Returns: 0 if it is, 1 otherwise ## => Returns: 0 if it is, 1 otherwise
function is_input_char() { _bashutils_reset_environment; [[ "${1}" =~ ^.$ ]]; _bashutils_return_environment "${?}"; } function is_input_char() { [[ "${1}" =~ ^.$ ]]; }
# Variable definition # Variable definition
## => Sets the specified variable to the specified value if it is undefined. ## => Sets the specified variable to the specified value if it is undefined.
## => Arguments: <str:variable> <?:value> ## => Arguments: <str:variable> <?:value>
## => Returns: 0 if it is, 1 otherwise ## => Returns: 0 if it is, 1 otherwise
function set_undefined() { _bashutils_reset_environment; [ -z "${!1}" ] && export "${1}=${2}"; _bashutils_restore_environment; } function set_undefined() { [ -z "${!1}" ] && export "${1}=${2}"; }
## => Sets the specified variable to the specified value if it is defined. ## => Sets the specified variable to the specified value if it is defined.
## => Arguments: <str:variable> <?:value> ## => Arguments: <str:variable> <?:value>
## => Returns: 0 if it is, 1 otherwise ## => Returns: 0 if it is, 1 otherwise
function set_defined() { _bashutils_reset_environment; [ -n "${!1}" ] && export "${1}=${2}"; _bashutils_restore_environment; } function set_defined() { [ -n "${!1}" ] && export "${1}=${2}"; }
# Initialize variables # Initialize variables
unset _BASHUTILS_ENVIRONMENT_PREVIOUS_OPTIONS
unset _BASHUTILS_ENVIRONMENT_PREVIOUS_PIPEFAIL
set_undefined "BASHUTILS_LOGLEVEL" "3" set_undefined "BASHUTILS_LOGLEVEL" "3"
set_undefined "BASHUTILS_LOGINDENTATION" ">"
set_undefined "BASHUTILS_SUBSHELL" "1"
################################ ################################

View file

@ -61,4 +61,6 @@ To trigger a crash, simply invoke `crash <bool:terminate> <str...:message>`.
## Customization ## Customization
bashutils allows you to customize the logging system via environment variables. bashutils allows you to customize the logging system via environment variables.
### `BASHUTILS_LOGLEVEL` ### `BASHUTILS_LOGLEVEL`
Set it to the desired minimum log level ID. Defaults to `3` (informational). The desired minimum log level ID. Defaults to `3` (informational).
### `BASHUTILS_SUBSHELL`
Subshell identifier. Increase this variable by `1` each time you invoke another script. Defaults to `1` (**DO NOT LOWER THIS VALUE**).

404
test.sh
View file

@ -31,224 +31,230 @@ check_input_char
" "
# Utility methods # Utility methods
function bashutils() {
set +uo pipefail
source "bashutils.sh"
set -uo pipefail
}
function invalid() { echo ":: Error: Invalid test ${TEST}, skipping"; } function invalid() { echo ":: Error: Invalid test ${TEST}, skipping"; }
function fail() { function fail() {
echo -e ":: Test ${TEST} failed during stage ${STAGE}\n ${*//\\n/\\n }" echo -e ":: Test ${TEST} failed during stage ${STAGE}\n ${*//\\n/\\n }"
[ "${TEST_FAILFAST:-true}" == "true" ] && exit 1 [ "${TEST_FAILFAST:-true}" == "true" ] && exit 1
} }
## Assertions ## Assertions
function assert_equals() { function assert_equals() {
EXPECTED="${1}" EXPECTED="${1}"
ACTUAL="${2}" ACTUAL="${2}"
[[ "${ACTUAL}" != "${EXPECTED}" ]] && fail "String does not match expected string\nExpected: '${EXPECTED}'\nActual: '${ACTUAL}'" [[ "${ACTUAL}" != "${EXPECTED}" ]] && fail "String does not match expected string\nExpected: '${EXPECTED}'\nActual: '${ACTUAL}'"
} }
function assert_contains() { function assert_contains() {
EXPECTED="${1}" EXPECTED="${1}"
ACTUAL="${2}" ACTUAL="${2}"
[[ "${ACTUAL}" != *"${EXPECTED}"* ]] && fail "String does not contain expected string\nExpected: '${EXPECTED}'\nActual: '${ACTUAL}'" [[ "${ACTUAL}" != *"${EXPECTED}"* ]] && fail "String does not contain expected string\nExpected: '${EXPECTED}'\nActual: '${ACTUAL}'"
} }
# Test loop # Test loop
for TEST in ${TESTS}; do for TEST in ${TESTS}; do
[ -z "${TEST}" ] || [[ "${TEST}" == "#"* ]] && continue [ -z "${TEST}" ] || [[ "${TEST}" == "#"* ]] && continue
echo ":: Running test ${TEST}" echo ":: Running test ${TEST}"
export "TEST" export "TEST"
export "STAGE=0" export "STAGE=0"
# Logging # Logging
if [[ "${TEST}" == "logger_"* ]]; then if [[ "${TEST}" == "logger_"* ]]; then
if [ "${TEST}" == "logger_crash" ]; then if [ "${TEST}" == "logger_crash" ]; then
assert_contains "It crashed!" "$( ( assert_contains "It crashed!" "$( (
source "bashutils.sh" bashutils
crash "true" "It crashed!" crash "true" "It crashed!"
) &> /dev/stdout)" ) &>/dev/stdout)"
else else
assert_contains "This is a test message" "$( ( assert_contains "This is a test message" "$( (
source "bashutils.sh" bashutils
# shellcheck disable=SC2034 # shellcheck disable=SC2034
BASHUTILS_LOGLEVEL=0 BASHUTILS_LOGLEVEL=0
${TEST//logger_/} "This is a test message" ${TEST//logger_/} "This is a test message"
) &> /dev/stdout)" ) &>/dev/stdout)"
fi fi
# Checks # Checks
elif [[ "${TEST}" == "check_"* ]]; then elif [[ "${TEST}" == "check_"* ]]; then
# Command checks # Command checks
if [[ "${TEST}" == "check_command_"* ]]; then if [[ "${TEST}" == "check_command_"* ]]; then
case "${TEST//check_command_/}" in case "${TEST//check_command_/}" in
"alias") "alias")
assert_equals "0" "$( assert_equals "0" "$(
source "bashutils.sh" bashutils
alias "verynicealias=ls" alias "verynicealias=ls"
is_command_alias "verynicealias" is_command_alias "verynicealias"
echo "${?}" echo "!$(type -t "verynicealias")!"
)" #echo -n "${?}"
;; )"
"keyword") ;;
assert_equals "0" "$( "keyword")
source "bashutils.sh" assert_equals "0" "$(
is_command_keyword "continue" bashutils
echo "${?}" is_command_keyword "continue"
)" echo "${?}"
;; )"
"function") ;;
assert_equals "0" "$( "function")
source "bashutils.sh" assert_equals "0" "$(
is_command_function "is_command_function" bashutils
echo "${?}" is_command_function "is_command_function"
)" echo "${?}"
;; )"
"builtin") ;;
assert_equals "0" "$( "builtin")
source "bashutils.sh" assert_equals "0" "$(
is_command_builtin "set" bashutils
echo "${?}" is_command_builtin "set"
)" echo "${?}"
;; )"
"file") ;;
assert_equals "0" "$( "file")
source "bashutils.sh" assert_equals "0" "$(
is_command_file "clear" bashutils
echo "${?}" is_command_file "clear"
)" echo "${?}"
;; )"
"defined") ;;
assert_equals "0" "$( "defined")
source "bashutils.sh" assert_equals "0" "$(
is_command_defined "echo" bashutils
echo "${?}" is_command_defined "echo"
)" echo "${?}"
;; )"
*) ;;
invalid *)
;; invalid
esac ;;
esac
# Input checks # Input checks
elif [[ "${TEST}" == "check_input_"* ]]; then elif [[ "${TEST}" == "check_input_"* ]]; then
case "${TEST//check_input_/}" in case "${TEST//check_input_/}" in
"bool") "bool")
assert_equals "0" "$( assert_equals "0" "$(
source "bashutils.sh" bashutils
is_input_bool "true" is_input_bool "true"
echo "${?}" echo "${?}"
)" )"
export "STAGE=1" export "STAGE=1"
assert_equals "0" "$( assert_equals "0" "$(
source "bashutils.sh" bashutils
is_input_bool "false" is_input_bool "false"
echo "${?}" echo "${?}"
)" )"
export "STAGE=2" export "STAGE=2"
assert_equals "1" "$( assert_equals "1" "$(
source "bashutils.sh" bashutils
is_input_bool "0" is_input_bool "0"
echo "${?}" echo "${?}"
)" )"
export "STAGE=3" export "STAGE=3"
assert_equals "1" "$( assert_equals "1" "$(
source "bashutils.sh" bashutils
is_input_bool "1" is_input_bool "1"
echo "${?}" echo "${?}"
)" )"
;; ;;
"byte") "byte")
assert_equals "0" "$( assert_equals "0" "$(
source "bashutils.sh" bashutils
is_input_byte "0" is_input_byte "0"
echo "${?}" echo "${?}"
)" )"
export "STAGE=1" export "STAGE=1"
assert_equals "0" "$( assert_equals "0" "$(
source "bashutils.sh" bashutils
is_input_byte "255" is_input_byte "255"
echo "${?}" echo "${?}"
)" )"
export "STAGE=2" export "STAGE=2"
assert_equals "0" "$( assert_equals "0" "$(
source "bashutils.sh" bashutils
is_input_byte "69" is_input_byte "69"
echo "${?}" echo "${?}"
)" )"
export "STAGE=3" export "STAGE=3"
assert_equals "1" "$( assert_equals "1" "$(
source "bashutils.sh" bashutils
is_input_byte "256" is_input_byte "256"
echo "${?}" echo "${?}"
)" )"
export "STAGE=4" export "STAGE=4"
assert_equals "1" "$( assert_equals "1" "$(
source "bashutils.sh" bashutils
is_input_byte "-1" is_input_byte "-1"
echo "${?}" echo "${?}"
)" )"
export "STAGE=5" export "STAGE=5"
assert_equals "1" "$( assert_equals "1" "$(
source "bashutils.sh" bashutils
is_input_int "asd" is_input_int "asd"
echo "${?}" echo "${?}"
)" )"
;; ;;
"int") "int")
assert_equals "0" "$( assert_equals "0" "$(
source "bashutils.sh" bashutils
is_input_int "9223372036854775807" is_input_int "9223372036854775807"
echo "${?}" echo "${?}"
)" )"
export "STAGE=1" export "STAGE=1"
assert_equals "1" "$( assert_equals "1" "$(
source "bashutils.sh" bashutils
is_input_int "asd" is_input_int "asd"
echo "${?}" echo "${?}"
)" )"
;; ;;
"char") "char")
assert_equals "0" "$( assert_equals "0" "$(
source "bashutils.sh" bashutils
is_input_int "!" is_input_int "!"
echo "${?}" echo "${?}"
)" )"
export "STAGE=1" export "STAGE=1"
assert_equals "0" "$( assert_equals "0" "$(
source "bashutils.sh" bashutils
is_input_int "™" is_input_int "™"
echo "${?}" echo "${?}"
)" )"
export "STAGE=2" export "STAGE=2"
assert_equals "0" "$( assert_equals "0" "$(
source "bashutils.sh" bashutils
is_input_int "5" is_input_int "5"
echo "${?}" echo "${?}"
)" )"
export "STAGE=3" export "STAGE=3"
assert_equals "1" "$( assert_equals "1" "$(
source "bashutils.sh" bashutils
is_input_int "asd" is_input_int "asd"
echo "${?}" echo "${?}"
)" )"
export "STAGE=4" export "STAGE=4"
assert_equals "1" "$( assert_equals "1" "$(
source "bashutils.sh" bashutils
is_input_int "666" is_input_int "666"
echo "${?}" echo "${?}"
)" )"
;; ;;
*) *)
invalid invalid
;; ;;
esac esac
# Invalid command
else
invalid
fi
# Invalid command # Invalid command
else else
invalid invalid
fi fi
# Invalid command
else
invalid
fi
done done