#!/usr/bin/env bash # Automatic tests for rdlink # Two kinds of tests are supported # * `tocompete` : competition between readlink and rdlink # * `toassert` : assert expected path and input path # test_rdlink.sh [OPTIONS] [PATH TO COMPETE] # [OPTIONS] # -a, --run-all : Run all tests (failed and successful) # -x, --extended-output : Show more information for each test # -xd : set -x and also show rdlink debug run for failed tests # -oa, --only-assert : Run only assert tests # -oc, --only-compete : Run only competion tests # -e, --error : Print only failed tests # # Internal tests will be executed if no arguments are found readonly test_dir="$(cd "$(dirname -- "${BASH_SOURCE[0]}")" >/dev/null 2>&1 && pwd)" readonly tool_rdlink="${test_dir}/../rdlink.sh" readonly tool_readlink="$(command -v readlink) -f --" readonly config_path_width=45 readonly color_red='\033[1;31m' readonly color_yellow='\033[1;33m' readonly color_green='\033[1;32m' readonly color_less='\033[0m' flag_runall=0 flag_extendedOutput=0 flag_verbose=0 flag_onlyassert=0 flag_onlycompete=0 flag_printerror=0 toassert=() tocompete=() . "${test_dir}/totest.sh" rl::printPath() { local testnum="${1:-0}" local input="${2:-"-"}" local truncate_graphic= local inputwidth=${config_path_width} if (( flag_extendedOutput )); then printf -- "%-3d Inp: %-${config_path_width}s ---" ${testnum} "${input}" else # Truncate input string on the left if longer than $config_path_width if (( ${#input} > ${config_path_width} )) ; then # +1 : prepending truncate_graphic input="${input:$(( ${#input} - ${config_path_width} + 1 ))}" # -1 : prepending truncate_graphic inputwidth=$((config_path_width - 1)) truncate_graphic="✀" fi # Print input and expected printf "%b%${inputwidth}s" "${truncate_graphic}" "${input}" fi } rl::printTestSummary() { local success=${1:-0} local failed=${2:-0} local skipped=${3:-0} local total=$(( success + failed + skipped )) readonly columnwidth=7 readonly tableformat="%${columnwidth}s | %${columnwidth}s | %${columnwidth}s | %${columnwidth}s\n" printf "\n# Result : ${tableformat}" "success" "failed" "skipped" "total" printf " ${tableformat}" "${success}" "${failed}" "${skipped}" "${total}" } # rl::testcmp # Compare results and print summary rl::testcmp() { local testnum="${1:-0}" local input="${2:-"-"}" local expect="${3:-"-"}" local actual="${4:-"-"}" local testresult=0 #failed local testresult_graphic="${color_red}✗${color_less}" # alt. symbol ≠ if [[ "${expect}" == "${actual}" ]] ; then # Don't print success for this flag (( flag_printerror )) && return 0 testresult=1 testresult_graphic="${color_green}✔${color_less}" # alt. symbol ✓ fi # Show only reslult as quick overview if (( flag_extendedOutput )); then rl::printPath ${testnum} "${input}" printf " %b\n" "${testresult_graphic}" if (( ! testresult )); then # Test failed printf " Result: %s\n Exp: %s\n" "${actual}" "${expect}" if (( flag_verbose )); then [ -e "${input}" ] && printf "\n Subject:\n" && ls -al "${input}" # Print debug output of tool_a printf "\n Debug:\n" ( ${tool_rdlink} -d -- "${input}" ) fi return 1 fi return 0 fi # Change result graphic if test failed (( ! testresult )) && testresult_graphic="→" # "${color_green}→${color_less}" rl::printPath "" "${input}" printf " %b %s\n" "${testresult_graphic}" "${expect}" # Print actual result if test failed if (( ! testresult )); then printf "%$((config_path_width))s %b %s\n" " " "${color_red}✗${color_less}" "${actual}" return 1 fi return 0 } rl::test() { local i=0 local path= local arraywalker= local firstelement= local testend=0 local arg= local excludemsg= local tests_success=0 local tests_failed=0 local tests_skipped=0 for arg in "$@"; do case "$1" in --) ## End of options shift && break ;; -a|--run-all) ## Run all even if tests fail flag_runall=1 shift ;; -x|--extended-output) flag_extendedOutput=1 shift ;; -xd|--verbose) flag_extendedOutput=1 flag_verbose=1 shift ;; -oa|--only-assert) flag_onlyassert=1 shift ;; -oc|--only-compete) flag_onlycompete=1 shift ;; -e|--error) flag_printerror=1 shift ;; -*|--*) printf "Invalid argument\n" exit 1 ;; esac done # Cmd line arguments (( ! flag_onlycompete )) && [[ ! "$@" ]] && toassert_init # Compare against expected result if (( ${#toassert[@]} )) ; then printf "\n# Assertion tests (\"Expected path\" == rdlink)\n" fi for testarray in "${toassert[@]}"; do i=0 arraywalker="$testarray"[@] for path in "${!arraywalker}"; do if (( ! i )); then # Print title in array element 0 printf " ### %b ###\n" "${color_yellow}${path}${color_less}" (( ! flag_extendedOutput )) && printf "%${config_path_width}s %s %s\n" "" "" "✗ [ACTUAL]" elif [ -z "$firstelement" ]; then # Save first element for string compare firstelement="${path}" # Check for excludes elif excludemsg="$(toexclude "${firstelement}")"; then (( tests_skipped++ )) rl::printPath "$(( i/2 ))" "${firstelement}" && printf " %b skip (%s)\n" "🛇" "${excludemsg}" # Execute tests else # Do the compare between two following elements if ! rl::testcmp "$(( i/2 ))" "${firstelement}" \ "${path}" "$($tool_rdlink -- "${firstelement}")"; then (( tests_failed++ )) # Run all tests if option -a is pressend (( ! $flag_runall )) && testend=1 && break else (( tests_success++ )) fi firstelement= fi ((i++)) done (( testend )) && break done (( testend )) && rl::printTestSummary $tests_success $tests_failed $tests_skipped && return 1 # Initialize competition tests (( ! flag_onlyassert )) && tocompete_init # Only run `compete_args` if arguments are available if [[ "$@" ]]; then compete_args=( "Tests from command line" "$@" ) tocompete=(compete_args) fi # Compare output of rdlink and readlink -f if (( ${#tocompete[@]} )) ; then printf "\n# Competition tests (readlink -f == rdlink)\n" fi for testarray in "${tocompete[@]}"; do i=0 arraywalker="$testarray"[@] for path in "${!arraywalker}"; do if (( ! i )); then # Print title in array element 0 printf " ### %b ###\n" "${color_yellow}${path}${color_less}" (( ! flag_extendedOutput )) && printf "%${config_path_width}s %s %s\n" "" "" "✗ [ACTUAL]" else # Check for excludes if excludemsg="$(toexclude "${path}")" ; then (( tests_skipped++ )) rl::printPath "${i}" "${path}" && printf " %b skip (%s)\n" "🛇" "${excludemsg}" # Execute tests elif ! rl::testcmp "${i}" "${path}" \ "$(${tool_readlink} "$path")" "$(${tool_rdlink} -- "$path")"; then (( tests_failed++ )) # Run all tests if option -a is pressend (( ! $flag_runall )) && testend=1 && break else (( tests_success++ )) fi fi ((i++)) done (( testend )) && break done rl::printTestSummary $tests_success $tests_failed $tests_skipped (( testend )) && return 1 || return 0 } #time rl::test "$@" rl::test "$@"