#!/data/data/com.termux/files/usr/bin/bash
# shellcheck disable=SC2016

# Title:         sudo_tests
# Description:   A script to run automated tests for the sudo command types.
# Homepage:      https://github.com/agnostic-apollo/sudo
# SPDX-License-Identifier: MIT
# Usage:         Run "sudo_tests --help" for detailed list of usages.
# Bash version:  4.1 or higher



if [ -z "${BASH_VERSION:-}" ]; then
    echo "The 'sudo_tests' script must be run from a 'bash' shell."; return 64 2>/dev/null|| exit 64 # EX__USAGE
fi



SUDO_TESTS_HELP="$(cat<<'SUDO_TESTS_HELP_EOF'
sudo_tests is a script that run tests for the sudo script.


Usage:
  sudo_tests [command_options]
  sudo_tests [command_options] <su|asu|path|script>
  sudo_tests [command_options] <su|asu|path|script> <shell> <test_number>


Available command_options:
  [ -h | --help ]    Display this help screen.
  [ --help-extra ]   Display more help about how sudo_tests command
                     works.
  [ -q | --quiet ]   Set log level to 'OFF'.
  [ -v | -vv | -vvv | -vvvvv ]  Set log level to 'DEBUG', 'VERBOSE',
                                'VVERBOSE' and 'VVVERBOSE'.
  [ --only-bash-tests ] Run only bash shell tests.


Setting log level '>= DEBUG' will fail test validation for tests that
match the output, its mainly for debugging.
SUDO_TESTS_HELP_EOF
)"

SUDO_TESTS_HELP_EXTRA="$(cat<<'SUDO_TESTS_HELP_EXTRA'

### Install and Usage Instructions For Termux In Android:

# Install sudo and sudo_tests scripts and set ownership and executable permission
curl -L 'https://github.com/agnostic-apollo/sudo/raw/master/sudo' -o "${TERMUX__PREFIX:-$PREFIX}/bin/sudo"; chmod +x "${TERMUX__PREFIX:-$PREFIX}/bin/sudo";
curl -L 'https://github.com/agnostic-apollo/sudo/raw/master/tests/sudo_tests' -o ~/sudo_tests; chmod +x ~/sudo_tests;
or
cat "/sdcard/Download/sudo" > "${TERMUX__PREFIX:-$PREFIX}/bin/sudo"; chmod +x "${TERMUX__PREFIX:-$PREFIX}/bin/sudo";
cat "/sdcard/Download/sudo_tests" > ~/sudo_tests; chmod +x ~/sudo_tests;

export termux_bin_path="${TERMUX__PREFIX:-$PREFIX}/bin"; export owner="$(stat -c "%u" "$termux_bin_path")"; chown "$owner:$owner" "$termux_bin_path/sudo" && chmod 700 "$termux_bin_path/sudo"; chown "$owner:$owner" ~/sudo_tests && chmod 700 ~/sudo_tests;


# Install shells used by sudo_tests script
pkg install bash zsh dash fish python ruby nodejs perl lua52 lua53 lua54 php rlwrap


# Install termux_tasker_basic_bash_test and termux_tasker_basic_python_test script and set permissions
mkdir -p ~/.termux/tasker
chmod 700 -R ~/.termux

curl -L 'https://github.com/termux/termux-tasker/raw/master/templates/scripts/termux_tasker_basic_bash_test' -o ~/.termux/tasker/termux_tasker_basic_bash_test
curl -L 'https://github.com/termux/termux-tasker/raw/master/templates/scripts/termux_tasker_basic_python_test' -o ~/.termux/tasker/termux_tasker_basic_python_test
or
cat "/sdcard/Download/termux_tasker_basic_bash_test" > ~/.termux/tasker/termux_tasker_basic_bash_test
cat "/sdcard/Download/termux_tasker_basic_python_test" > ~/.termux/tasker/termux_tasker_basic_python_test

chmod 700 ~/.termux/tasker/termux_tasker_basic_bash_test
chmod 700 ~/.termux/tasker/termux_tasker_basic_python_test


# Install yt-dlp
pkg install ffmpeg python
python3 -m pip install -U yt-dlp

# Fix shebang, must be run on install and on each update,
# otherwise will get "bad interpreter: /usr/bin/env" errors when running with root shell, plugin or TermuxCommand,
# because termux-exec doesn't work for those cases and LD_PRELOAD isn't set,
# but its not required for usage with sudo since it sets the LD_PRELOAD
termux-fix-shebang "${TERMUX__PREFIX:-$PREFIX}/bin/yt-dlp"
#
# Update yt-dlp
python3 -m pip install -U yt-dlp


# Install bandcamp-dl
pip3 install bandcamp-downloader
#
# Update bandcamp-dl
pkg install git
pip install git+https://github.com/iheanyi/bandcamp-dl --upgrade



# Following are not required for the tests currently

# Install pry, the ruby interactive shell alternative
gem install pry

# Install python2
pkg install python2

# Install ksh
pkg intsall loksh



# Follow instructions in `RC File Variables` section of README.md to fix `rc` files.
sed -i'' -E 's/^(PS1=.*)$/\(\[ -z "\$PS1" \] \|\| \[\[ "\$PS1" == '\''\\s-\\v\\\$ '\'' \]\]\) \&\& \1/' "${TERMUX__PREFIX:-$PREFIX}/etc/bash.bashrc"
sed -i'' -E 's/^(PS1=.*)$/\(\[ -z "\$PS1" \] \|\| \[\[ "\$PS1" == '\''%m%# '\'' \]\]\) \&\& \1/' "${TERMUX__PREFIX:-$PREFIX}/etc/zshrc"



# Finally run tests

# Run all tests
bash ~/sudo_tests -vv

# Run only script command type tests
bash ~/sudo_tests -vv script

# Run only script command type bash shell test 1
bash ~/sudo_tests -vv script bash 1

# Run only script command type bash shell test 1 with sudo log level 'VERBOSE'
SUDO__LOG_LEVEL=3 bash ~/sudo_tests -vv script bash 1

# For some tests **sometimes** where *-stdin-string option is used to pass a string to an interactive shell using stdin,
# the stdout is returned in an unsynchronized manner which fails the validation, possibly due to magisk su or maybe an android 10 issue
# The tests run fine with SuperSU v2.82 on android 7 without issues. Currently not sure of the real reason
# If that happens, just rerun the test and it should ideally work
# This is also the reason why su and asu tests use matches instead of equality checks, some script type tests still use exact matches

SUDO_TESTS_HELP_EXTRA
)"



### Set Default Variables Start

SUDO_TESTS_MAX_LOG_LEVEL=5 # Default: `5` (VVVERBOSE=5)
# shellcheck disable=SC2153
SUDO_TESTS_LOG_LEVEL="$SUDO_TESTS__LOG_LEVEL"
{ [[ ! "$SUDO_TESTS_LOG_LEVEL" =~ ^[0-9]+$ ]] || [[ "$SUDO_TESTS_LOG_LEVEL" -gt "$SUDO_TESTS_MAX_LOG_LEVEL" ]]; } && \
SUDO_TESTS_LOG_LEVEL=1 # Default: `1` (OFF=0, NORMAL=1, DEBUG=2, VERBOSE=3, VVERBOSE=4 and VVVERBOSE=5)
SUDO_TESTS_LOG_ARGS="${SUDO_TESTS__LOG_ARGS:-0}" # Default: `0` (Export or manually set to `1` if you want to debug arguments received)

SUDO_TESTS_COMMAND_TYPE="" # Default: ``
SUDO_TESTS_NOOP_COMMAND=0 # Default: `0`
SUDO_TESTS_ONLY_BASH_TESTS=0 # Default: `0`
SUDO_TESTS_PREVIOUS_TEMP_TEST_SHELL="" # Default: ``
SUDO_TESTS_PREVIOUS_TEST_SHELL="" # Default: ``
SUDO_TESTS_PREVIOUS_TEST_NUMBER="" # Default: ``
SUDO_TESTS_CURRENT_TEST_SHELL="" # Default: ``
SUDO_TESTS_CURRENT_TEST_NUMBER="" # Default: ``
SUDO_TESTS_USER_TEST_SHELL="" # Default: ``
SUDO_TESTS_USER_TEST_NUMBER="" # Default: ``

SUDO_TESTS_TEMP_DIRECTORY_SUFFIX="" # Default: ``

declare -ga SUDO_TESTS_DIRECTORIES=()

# Set regexes for validation
VALID_NUMBER_REGEX='^[0-9]+$'
VALID_ABSOLUTE_PATH_REGEX='^(/[^/]+)+$'

### Set Default Variables



function sudo_tests_log() { local log_level="${1}"; shift; if [[ $SUDO_TESTS_LOG_LEVEL -ge $log_level ]]; then echo "sudo-tests:" "$@"; fi }
function sudo_tests_log_no_tag() { local log_level="${1}"; shift; if [[ $SUDO_TESTS_LOG_LEVEL -ge $log_level ]]; then echo "$@"; fi }
function sudo_tests_log_literal() { local log_level="${1}"; shift; if [[ $SUDO_TESTS_LOG_LEVEL -ge $log_level ]]; then echo -e "sudo-tests:" "$@"; fi }
function sudo_tests_log_errors() { echo "sudo-tests:" "$@" 1>&2; }
function sudo_tests_log_args() { if [[ $SUDO_TESTS_LOG_ARGS == "1" ]]; then echo "sudo-tests:" "$@"; fi }
function sudo_tests_log_arg_errors() { echo "sudo-tests:" "$@" 1>&2; }

# stdin in closed for some tests as a patch to SuperSU automatic redirection of stderr to stdout when running in interactive mode
function close_stdin () {  if [ -t 0 ]; then exec <&-; fi }
function reopen_stdin () {  if [[ "$SUDO_TESTS_TTY_PATH" == "/dev/"* ]]; then exec <"$SUDO_TESTS_TTY_PATH"; fi }



##
# `sudo_tests_main` [`<argument...>`]
##
sudo_tests_main() {

    local return_value

    # Find the sudo script path
    SUDO_SCRIPT_PATH="$(command -v sudo)"
    return_value=$?
    if [ $return_value -ne 0 ] || [[ ! "$SUDO_SCRIPT_PATH" =~ $VALID_ABSOLUTE_PATH_REGEX ]]; then
        sudo_log_errors "Failure while finding SUDO_SCRIPT_PATH"
        sudo_log_errors "SUDO_SCRIPT_PATH='$SUDO_SCRIPT_PATH'"
        if [ $return_value -eq 0 ]; then
            return_value=1
        fi
        return $return_value
    fi

    # Source the sudo script
    if [ ! -x "$SUDO_SCRIPT_PATH" ]; then
        sudo_tests_log_errors "The SUDO_SCRIPT_PATH '$SUDO_SCRIPT_PATH' found is not executable"
        return 1
    else
        # shellcheck source=sudo
        source "$SUDO_SCRIPT_PATH" || return $?
        sudo_set_termux_env_variables || return $?
        sudo_set_sudo_default_variables || return $?
    fi

    local -a SUDO_TESTS_REQUIRED_VARIABLES_ARRAY=(
        TERMUX_ROOTFS
        TERMUX_PREFIX
        TERMUX_HOME
        TERMUX_LD_LIBRARY_PATH
    )

    local var

    for var in "${SUDO_TESTS_REQUIRED_VARIABLES_ARRAY[@]}"; do
        # If var is not set
        if [ -z "${!var}" ]; then
            sudo_tests_log_errors "The required variable '$var' for sudo_tests is not set"
            return 1
        fi
    done


    # Set pre required variables to be used by this script
    sudo_tests_set_pre_required_variables || return $?


    # Process the command arguments passed to the script
    sudo_tests_process_script_arguments "$@" || return $?

    [ "$SUDO_TESTS_NOOP_COMMAND" = "1" ] && return 0

    sudo_tests_run || return $?

}

sudo_tests_run() {

    local return_value

    # Set required variables to be used by this script
    sudo_tests_set_required_variables || return $?


    cd "$SUDO_TESTS_WORKING_DIR"

    local tests_start_time
    local tests_end_time
    tests_start_time="$(date "+%s")" || return $?

    # Run tests
    if [ -z "$SUDO_TESTS_COMMAND_TYPE" ]; then
        sudo_tests_log 1 "Running 'sudo' tests"
        sudo_tests_log 5 $'\n\n'; sudo_tests_run_su_tests || return $?
        sudo_tests_log 5 $'\n\n'; sudo_tests_run_asu_tests || return $?
        sudo_tests_log 5 $'\n\n'; sudo_tests_run_path_tests || return $?
        sudo_tests_log 5 $'\n\n'; sudo_tests_run_script_tests || return $?
    elif [[ "$SUDO_TESTS_COMMAND_TYPE" != *,* ]] && [[ ",su,asu,path,script," == *",$SUDO_TESTS_COMMAND_TYPE,"* ]]; then
        sudo_tests_run_"${SUDO_TESTS_COMMAND_TYPE,,}"_tests || return $?
    else
        sudo_tests_log_errors "Unknown tests command type $SUDO_TESTS_COMMAND_TYPE"
        sudo_tests_show_help
        return 1
    fi

    tests_end_time=$(($(date "+%s") - tests_start_time)) || return $?
    sudo_tests_log 5 $'\n\n'
    sudo_tests_log 1 "All 'sudo' tests successful in \
$((tests_end_time / 3600 )) hours $(((tests_end_time % 3600) / 60)) minutes $((tests_end_time % 60)) seconds"

    return 0

}



sudo_tests_set_pre_required_variables() {

    local return_value

    termux_core__bash__termux_scoped_env_variable get-value "TERMUX_APP__PACKAGE_NAME" \
        ss="$TERMUX_ENV__SS_TERMUX_APP" "PACKAGE_NAME" r+="^[a-zA-Z][a-zA-Z0-9_]*(\.[a-zA-Z][a-zA-Z0-9_]*)+$" "com.termux" "com.termux" || return $?

    # Find android sdk/os version
    # Termux app exports ANDROID__BUILD_VERSION_SDK for `>= v0.119.0`
    if [[ ! "$ANDROID__BUILD_VERSION_SDK" =~ $VALID_NUMBER_REGEX ]]; then
        ANDROID__BUILD_VERSION_SDK="$(unset LD_LIBRARY_PATH; unset LD_PRELOAD; getprop "ro.build.version.sdk")"
        return_value=$?
        if [ $return_value -ne 0 ] || [[ ! "$ANDROID__BUILD_VERSION_SDK" =~ $VALID_NUMBER_REGEX ]]; then
            sudo_tests_log_errors "Failure while finding 'ro.build.version.sdk' property"
            sudo_tests_log_errors "ANDROID__BUILD_VERSION_SDK='$ANDROID__BUILD_VERSION_SDK'"
            if [ $return_value -eq 0 ]; then
                return_value=1
            fi
            return $return_value
        fi
    fi

    sudo_tests_log 5 "ANDROID__BUILD_VERSION_SDK='$ANDROID__BUILD_VERSION_SDK'"



    # Set LD_LIBRARY_PATH for all external commands that may be run
    # If on Android `< 7`
    if [ "$ANDROID__BUILD_VERSION_SDK" -lt 24 ]; then
        # Set only termux library path
        LD_LIBRARY_PATH="$TERMUX_LD_LIBRARY_PATH"
    else
        # Do not set termux or android library paths
        LD_LIBRARY_PATH=""
    fi

    # Used by sudo_set_post_su_variables
    SUDO_LD_LIBRARY_PATH="$LD_LIBRARY_PATH"

    sudo_tests_log 5 "LD_LIBRARY_PATH='$LD_LIBRARY_PATH'"

    return 0

}

sudo_tests_set_required_variables() {

    local return_value

    if [ -t 0 ]; then
        SUDO_TESTS_TTY_PATH="$(tty 2>/dev/null)"
    fi


    # Set `SU_BIN_PATH` as its used in `ANDROID_PATH` when `sudo_set_path_priority_variables()` is called.
    sudo_set_su_variables || return $?


    # Set SUDO_TESTS_WORKING_DIR to use for tests
    SUDO_TESTS_WORKING_DIR="$TERMUX_HOME"

    # Generate unique suffix to use for sudo_tests directories
    SUDO_TESTS_TEMP_DIRECTORY_SUFFIX="$(mktemp -d --dry-run sudo.XXXXXX)"
    return_value=$?
    if [ $return_value -ne 0 ] || [[ ! "$SUDO_TESTS_TEMP_DIRECTORY_SUFFIX" =~  ^sudo\.......$ ]]; then
        sudo_tests_log_errors "Failure while running mktemp to create SUDO_TESTS_TEMP_DIRECTORY_SUFFIX"
        sudo_tests_log_errors "SUDO_TESTS_TEMP_DIRECTORY_SUFFIX='$SUDO_TESTS_TEMP_DIRECTORY_SUFFIX'"
        if [ $return_value -eq 0 ]; then
            return_value=1
        fi
        return $return_value
    fi

    SUDO_SHELL_HOME="$SUDO_TESTS_WORKING_DIR/.shell_home.$SUDO_TESTS_TEMP_DIRECTORY_SUFFIX"
    SUDO_POST_SHELL_HOME="$SUDO_TESTS_WORKING_DIR/.post_shell_home.$SUDO_TESTS_TEMP_DIRECTORY_SUFFIX"

    export SUDO__SHELL_HOME="$SUDO_SHELL_HOME"
    export SUDO__POST_SHELL_HOME="$SUDO_POST_SHELL_HOME"

    SUDO_SHELL_HOME_BASENAME="${SUDO_SHELL_HOME##*/}" # Strip longest match of */ from start
    SUDO_POST_SHELL_HOME_BASENAME="${SUDO_POST_SHELL_HOME##*/}" # Strip longest match of */ from start

    SUDO_TESTS_DIRECTORIES+=("$SUDO_SHELL_HOME")
    SUDO_TESTS_DIRECTORIES+=("$SUDO_POST_SHELL_HOME")



    if [[ "$(cat /proc/self/mounts)" == *"/.magisk/mirror/system"* ]]; then
        SUDO_TESTS_SYSTEM_PARTITION_IS_RO=1
    else
        SUDO_TESTS_SYSTEM_PARTITION_IS_RO=0
    fi



    # Set traps to run commands before exiting sudo_tests
    trap 'sudo_tests_cleanup' EXIT
    trap 'sudo_tests_cleanup TERM' TERM
    trap 'sudo_tests_cleanup INT' INT
    trap 'sudo_tests_cleanup HUP' HUP
    trap 'sudo_tests_cleanup QUIT' QUIT

    return 0

}



sudo_tests_run_su_tests() {

    local return_value

    SUDO_TESTS_COMMAND_TYPE="su"
    sudo_tests_log 2 "Start '$SUDO_TESTS_COMMAND_TYPE' tests"



    # Run bash tests

    set_sudo_tests_current_test_shell "bash"
    shell="bash"

    run_sudo_test 1 && \
    output="$(sudo --dry-run --shell-stdin-string='cd "$HOME"; pwd; exit;' su)"
    validate_sudo_test 0 $? "$output" ""

    run_sudo_test 2 && \
    output="$(sudo --shell-stdin-string='cd "$HOME"; pwd; exit;' su)"
    validate_sudo_test 0 $? "$output" "*" "$SUDO_SHELL_HOME" "*"


    # If on Android `< 7`
    if [ "$ANDROID__BUILD_VERSION_SDK" -lt 24 ]; then
        sudo_set_path_priority_variables "1"
        run_sudo_test 3 && \
        output="$(sudo --shell-stdin-string='echo "PATH=$PATH; LD_LIBRARY_PATH=$LD_LIBRARY_PATH; LD_PRELOAD=$LD_PRELOAD;"; exit;' su)"
        validate_sudo_test 0 $? "$output" "*" "PATH=$TERMUX_BIN:$TERMUX_BIN_APPLETS:$ANDROID_PATH; LD_LIBRARY_PATH=$TERMUX_LD_LIBRARY_PATH; LD_PRELOAD=$TERMUX_LD_PRELOAD;" "*"

        sudo_set_path_priority_variables "0"
        run_sudo_test 4 && \
        output="$(sudo -T --shell-stdin-string='echo "PATH=$PATH; LD_LIBRARY_PATH=$LD_LIBRARY_PATH; LD_PRELOAD=$LD_PRELOAD;"; exit;' su)"
        validate_sudo_test 0 $? "$output" "*" "PATH=$TERMUX_BIN; LD_LIBRARY_PATH=$TERMUX_LD_LIBRARY_PATH; LD_PRELOAD=$TERMUX_LD_PRELOAD;" "*"

        sudo_set_path_priority_variables "1"
        run_sudo_test 5 && \
        output="$(sudo -TT --shell-stdin-string='echo "PATH=$PATH; LD_LIBRARY_PATH=$LD_LIBRARY_PATH; LD_PRELOAD=$LD_PRELOAD;"; exit;' su)"
        validate_sudo_test 0 $? "$output" "*" "PATH=$TERMUX_BIN:$TERMUX_BIN_APPLETS; LD_LIBRARY_PATH=$TERMUX_LD_LIBRARY_PATH; LD_PRELOAD=$TERMUX_LD_PRELOAD;" "*"
    else
        sudo_set_path_priority_variables "1"
        run_sudo_test 3 && \
        output="$(sudo --shell-stdin-string='echo "PATH=$PATH; LD_LIBRARY_PATH=$LD_LIBRARY_PATH; LD_PRELOAD=$LD_PRELOAD;"; exit;' su)"
        validate_sudo_test 0 $? "$output" "*" "PATH=$TERMUX_BIN:$TERMUX_BIN_APPLETS:$ANDROID_PATH; LD_LIBRARY_PATH=; LD_PRELOAD=$TERMUX_LD_PRELOAD;" "*"

        sudo_set_path_priority_variables "0"
        run_sudo_test 4 && \
        output="$(sudo -T --shell-stdin-string='echo "PATH=$PATH; LD_LIBRARY_PATH=$LD_LIBRARY_PATH; LD_PRELOAD=$LD_PRELOAD;"; exit;' su)"
        validate_sudo_test 0 $? "$output" "*" "PATH=$TERMUX_BIN; LD_LIBRARY_PATH=; LD_PRELOAD=$TERMUX_LD_PRELOAD;" "*"

        sudo_set_path_priority_variables "1"
        run_sudo_test 5 && \
        output="$(sudo -TT --shell-stdin-string='echo "PATH=$PATH; LD_LIBRARY_PATH=$LD_LIBRARY_PATH; LD_PRELOAD=$LD_PRELOAD;"; exit;' su)"
        validate_sudo_test 0 $? "$output" "*" "PATH=$TERMUX_BIN:$TERMUX_BIN_APPLETS; LD_LIBRARY_PATH=; LD_PRELOAD=$TERMUX_LD_PRELOAD;" "*"
    fi


    sudo_tests_log 5 $'\n\n'
    sudo_tests_log 2 "End '$SUDO_TESTS_COMMAND_TYPE' tests"

    return 0

}

sudo_tests_run_asu_tests() {

    local return_value

    SUDO_TESTS_COMMAND_TYPE="asu"
    sudo_tests_log 2 "Start '$SUDO_TESTS_COMMAND_TYPE' tests"



    # Run bash tests

    set_sudo_tests_current_test_shell "bash"
    shell="bash"

    run_sudo_test 1 && \
    output="$(sudo --dry-run --shell-stdin-string='cd "$HOME"; pwd; exit;' asu)"
    validate_sudo_test 0 $? "$output" ""

    run_sudo_test 2 && \
    output="$(sudo --shell-stdin-string='cd "$HOME"; pwd; exit;' asu)"
    validate_sudo_test 0 $? "$output" "*" "$SUDO_SHELL_HOME" "*"


    # If on Android `< 7`
    if [ "$ANDROID__BUILD_VERSION_SDK" -lt 24 ]; then
        sudo_set_path_priority_variables "1"
        run_sudo_test 3 && \
        output="$(sudo --shell-stdin-string='echo "PATH=$PATH; LD_LIBRARY_PATH=$LD_LIBRARY_PATH; LD_PRELOAD=$LD_PRELOAD;"; exit;' asu)"
        validate_sudo_test 0 $? "$output" "*" "PATH=$ANDROID_PATH:$TERMUX_BIN:$TERMUX_BIN_APPLETS; LD_LIBRARY_PATH=$TERMUX_LD_LIBRARY_PATH; LD_PRELOAD=;" "*"

        sudo_set_path_priority_variables "0"
        run_sudo_test 4 && \
        output="$(sudo -A --shell-stdin-string='echo "PATH=$PATH; LD_LIBRARY_PATH=$LD_LIBRARY_PATH; LD_PRELOAD=$LD_PRELOAD;"; exit;' asu)"
        validate_sudo_test 0 $? "$output" "*" "PATH=$SYS_BIN; LD_LIBRARY_PATH=; LD_PRELOAD=;" "*"

        sudo_set_path_priority_variables "1"
        run_sudo_test 5 && \
        output="$(sudo -AA --shell-stdin-string='echo "PATH=$PATH; LD_LIBRARY_PATH=$LD_LIBRARY_PATH; LD_PRELOAD=$LD_PRELOAD;"; exit;' asu)"
        validate_sudo_test 0 $? "$output" "*" "PATH=$ANDROID_PATH; LD_LIBRARY_PATH=; LD_PRELOAD=;" "*"
    else
        sudo_set_path_priority_variables "1"
        run_sudo_test 3 && \
        output="$(sudo --shell-stdin-string='echo "PATH=$PATH; LD_LIBRARY_PATH=$LD_LIBRARY_PATH; LD_PRELOAD=$LD_PRELOAD;"; exit;' asu)"
        validate_sudo_test 0 $? "$output" "*" "PATH=$ANDROID_PATH:$TERMUX_BIN:$TERMUX_BIN_APPLETS; LD_LIBRARY_PATH=; LD_PRELOAD=;" "*"

        sudo_set_path_priority_variables "0"
        run_sudo_test 4 && \
        output="$(sudo -A --shell-stdin-string='echo "PATH=$PATH; LD_LIBRARY_PATH=$LD_LIBRARY_PATH; LD_PRELOAD=$LD_PRELOAD;"; exit;' asu)"
        validate_sudo_test 0 $? "$output" "*" "PATH=$SYS_BIN; LD_LIBRARY_PATH=; LD_PRELOAD=;" "*"

        sudo_set_path_priority_variables "1"
        run_sudo_test 5 && \
        output="$(sudo -AA --shell-stdin-string='echo "PATH=$PATH; LD_LIBRARY_PATH=$LD_LIBRARY_PATH; LD_PRELOAD=$LD_PRELOAD;"; exit;' asu)"
        validate_sudo_test 0 $? "$output" "*" "PATH=$ANDROID_PATH; LD_LIBRARY_PATH=; LD_PRELOAD=;" "*"
    fi


    sudo_tests_log 5 $'\n\n'
    sudo_tests_log 2 "End '$SUDO_TESTS_COMMAND_TYPE' tests"

    return 0
}

sudo_tests_run_path_tests() {

    local return_value

    SUDO_TESTS_COMMAND_TYPE="path"
    sudo_tests_log 2 "Start '$SUDO_TESTS_COMMAND_TYPE' tests"



    # Run bash tests

    set_sudo_tests_current_test_shell "bash"
    shell="bash"

    if [ -x "$TERMUX_HOME/.termux/tasker/termux_tasker_basic_bash_test" ]; then
        run_sudo_test 1 && \
        output="$(sudo "$TERMUX_HOME/.termux/tasker/termux_tasker_basic_bash_test" "$shell" "shell")"
        validate_sudo_test 0 $? "$output" "\$1=\`$shell\`"$'\n'"\$2=\`shell\`"

        run_sudo_test 2 && \
        output="$(sudo '~/.termux/tasker/termux_tasker_basic_bash_test' "$shell" "shell")"
        validate_sudo_test 0 $? "$output" "\$1=\`$shell\`"$'\n'"\$2=\`shell\`"

        run_sudo_test 3 && \
        output="$(cd "$TERMUX_HOME"; sudo './.termux/tasker/termux_tasker_basic_bash_test' "$shell" "shell")"
        validate_sudo_test 0 $? "$output" "\$1=\`$shell\`"$'\n'"\$2=\`shell\`"

        run_sudo_test 4 && \
        output="$(cd "$TERMUX_HOME/.termux/tasker"; sudo './termux_tasker_basic_bash_test' "$shell" "shell")"
        validate_sudo_test 0 $? "$output" "\$1=\`$shell\`"$'\n'"\$2=\`shell\`"

        run_sudo_test 5 && \
        output="$(cd "$TERMUX_HOME/.termux/tasker"; sudo '../tasker/termux_tasker_basic_bash_test' "$shell" "shell")"
        validate_sudo_test 0 $? "$output" "\$1=\`$shell\`"$'\n'"\$2=\`shell\`"
    else
        skip_sudo_test 1
        skip_sudo_test 2
        skip_sudo_test 3
        skip_sudo_test 4
        skip_sudo_test 5
    fi



    run_sudo_test 6 && \
    output="$(sudo ps -e -o cmd | grep "$TERMUX_PREFIX/bin/ps")"
    validate_sudo_test 0 $? "$output" "*" "$TERMUX_PREFIX/bin/ps -e -o cmd" "*"



    run_sudo_test 7 && \
    output="$(sudo dumpsys activity services | grep -aE 'ServiceRecord\{.*'"${TERMUX_APP__PACKAGE_NAME//./\\.}"'/.*\}')"
    validate_sudo_test 0 $? "$output" "*" "$TERMUX_APP__PACKAGE_NAME/" "*"



    run_sudo_test 8 && \
    output="$(sudo -r echo "$COMMA_ALTERNATIVE")"
    validate_sudo_test 0 $? "$output" ","



    sudo_tests_log 5 $'\n\n'
    sudo_tests_log 2 "End '$SUDO_TESTS_COMMAND_TYPE' tests"

    return 0

}

sudo_tests_run_script_tests() {

    local return_value

    SUDO_TESTS_COMMAND_TYPE="script"
    sudo_tests_log 2 "Start '$SUDO_TESTS_COMMAND_TYPE' tests"



    ### Run bash tests

    set_sudo_tests_current_test_shell "bash"
    shell="bash"


    run_sudo_test 1 && \
    output="$(sudo -s --dry-run 'cd "$HOME"; pwd;')"
    validate_sudo_test 0 $? "$output" ""

    run_sudo_test 2 && \
    output="$(sudo -s 'cd "$HOME"; pwd;')"
    validate_sudo_test 0 $? "$output" "$SUDO_SHELL_HOME"

    run_sudo_test 3 && \
    output="$(cd "$SUDO_TESTS_WORKING_DIR"; sudo -s --shell-home="./$SUDO_SHELL_HOME_BASENAME" 'cd "$HOME"; pwd;')"
    validate_sudo_test 0 $? "$output" "$SUDO_SHELL_HOME"

    run_sudo_test 4 && \
    output="$(cd "$SUDO_TESTS_WORKING_DIR"; sudo -s --shell-home="$SUDO_SHELL_HOME_BASENAME" 'cd "$HOME"; pwd;')"
    validate_sudo_test 0 $? "$output" "$SUDO_SHELL_HOME"

    run_sudo_test 5 && \
    output="$(sudo -si --post-shell-home="$SUDO_POST_SHELL_HOME" --post-shell-stdin-string='exit' --post-shell-pre-commands='cd "$HOME"; pwd;')"
    validate_sudo_test 0 $? "$output" "" "$SUDO_POST_SHELL_HOME" "*"



    run_sudo_test 6 && \
    output="$(sudo -s 'readlink -f /proc/$$/exe')"
    validate_sudo_test 0 $? "$output" "$TERMUX_PREFIX/bin/bash"

    run_sudo_test 7 && \
    output="$(sudo -s --shell="$TERMUX_PREFIX/bin/bash" 'readlink -f /proc/$$/exe')"
    validate_sudo_test 0 $? "$output" "$TERMUX_PREFIX/bin/bash"

    run_sudo_test 8 && \
    output="$(sudo -si --post-shell-stdin-string='readlink -f /proc/$$/exe; exit;')"
    validate_sudo_test 0 $? "$output" "*" '# readlink -f /proc/$$/exe; exit;'$'\n'"$TERMUX_PREFIX/bin/bash"$'\n'"exit" ""

    run_sudo_test 9 && \
    output="$(sudo -si --post-shell="$TERMUX_PREFIX/bin/bash" --post-shell-stdin-string='readlink -f /proc/$$/exe; exit;')"
    validate_sudo_test 0 $? "$output" "*" '# readlink -f /proc/$$/exe; exit;'$'\n'"$TERMUX_PREFIX/bin/bash"$'\n'"exit" ""



    run_sudo_test 10 && \
    output="$(sudo -s --shell="$shell" <(cat <<'SUDO_EOF'
echo "Hi, $1 $2."
SUDO_EOF
) "$shell" "shell"
    )"
    validate_sudo_test 0 $? "$output" "Hi, $shell shell."



    run_sudo_test 11 && \
    output="$(sudo -s --shell="$shell" --shell-stdin-string="$shell" '
echo '\''What is your name?'\''
read name
echo "Hi, $name."
'
    )"
    validate_sudo_test 0 $? "$output" "What is your name?"$'\n'"Hi, $shell."



    run_sudo_test 12 && \
    output="$(sudo -sd --shell="$shell" '
echo '\''What is your name?'\''
read name
echo "Hi, $name."
'
    )"
    validate_sudo_test 0 $? "$output" "What is your name?"$'\n'"Hi, ."



    run_sudo_test 13 && \
    output="$(sudo -so --shell="$shell" --shell-stdin-string="$shell" '
echo '\''What is your name?'\''
read name
echo "Hi, $name." 1>&2
'
    )"
    validate_sudo_test 0 $? "$output" "What is your name?"$'\n'"Hi, $shell."



    run_sudo_test 14 && \
    output="$(sudo -sf 'echo "Running $1 $2 script: $(basename "$0")"' "$shell" "shell")"
    validate_sudo_test 0 $? "$output" "Running $shell shell script: sudo_script__core_script"


    run_sudo_test 15 && \
    output="$(sudo -sf --script-name="sudo_script__core_script_custom" 'echo "Running $1 $2 script: $(basename "$0")"' "$shell" "shell")"
    validate_sudo_test 0 $? "$output" "Running $shell shell script: sudo_script__core_script_custom"



    if [ -x "$TERMUX_HOME/.termux/tasker/termux_tasker_basic_bash_test" ]; then
        run_sudo_test 16 && \
        output="$(sudo -sF '~/.termux/tasker/termux_tasker_basic_bash_test' "$shell" "shell")"
        validate_sudo_test 0 $? "$output" "\$1=\`$shell\`"$'\n'"\$2=\`shell\`"
    else
        skip_sudo_test 16
    fi


    if [ -x "$TERMUX_PREFIX/bin/tasker_config_utils" ]; then
        run_sudo_test 17 && \
        output="$(sudo -s --script-name="tasker_config_utils" <(cat "$TERMUX_PREFIX/bin/tasker_config_utils") --help 1>/dev/null)"
        validate_sudo_test 0 $? "$output"
    else
        skip_sudo_test 17
    fi


    if [ -x "$TERMUX_PREFIX/bin/tasker_config_utils" ]; then
        run_sudo_test 18 && \
        output="$(sudo -sf --script-name="tasker_config_utils" <(cat "$TERMUX_PREFIX/bin/tasker_config_utils") --help 1>/dev/null)"
        validate_sudo_test 0 $? "$output"
    else
        skip_sudo_test 18
    fi





    run_sudo_test 19 && \
    output="$(sudo -s --shell-pre-commands='
export VARIABLE_1="VARIABLE_VALUE_1"
export VARIABLE_2="VARIABLE_VALUE_2"
' '
echo "Hi, $1 $2."
echo "VARIABLE_1=\`$VARIABLE_1\`"
echo "VARIABLE_2=\`$VARIABLE_2\`"
' "$shell" "shell"
    )"
    validate_sudo_test 0 $? "$output" "Hi, $shell shell."$'\n'"VARIABLE_1=\`VARIABLE_VALUE_1\`"$'\n'"VARIABLE_2=\`VARIABLE_VALUE_2\`"



    run_sudo_test 20 && \
    output="$(sudo -si --post-shell-stdin-string='exit' --shell-pre-commands='echo "Start script"' --shell-post-commands='echo "Exited script"' --post-shell-pre-commands='echo "Starting interactive shell"' --post-shell-post-commands='echo "Exited interactive shell"' 'echo "Hi, $1 $2."' "$shell" "shell")"
    validate_sudo_test 0 $? "$output" r+="^Start script"$'\n'"Hi, $shell shell\."$'\n'"Exited script"$'\n'"Starting interactive shell"$'\n'"([^"$'\n'"#]+)?# exit"$'\n'"exit"$'\n'"Exited interactive shell$"





    sudo_test_temp_shell_home="/shell_home.$SUDO_TESTS_TEMP_DIRECTORY_SUFFIX"
    SUDO_TESTS_DIRECTORIES+=("$sudo_test_temp_shell_home")
    run_sudo_test 21 && \
    output="$(sudo -s --shell-home="$sudo_test_temp_shell_home" 'cd "$HOME"; pwd;' 2>&1)"
    return_value=$?
    # If android >= 10
    if [ "$ANDROID__BUILD_VERSION_SDK" -ge 29 ]; then
        validate_sudo_test 1 $return_value "$output" "" "The rootfs '/' partition cannot be mounted as rw to be used for SUDO_SHELL_HOME '$sudo_test_temp_shell_home'" "*"
    else
        validate_sudo_test 0 $return_value "$output" "$sudo_test_temp_shell_home"
    fi



    sudo_test_temp_post_shell_home="/post_shell_home.$SUDO_TESTS_TEMP_DIRECTORY_SUFFIX"
    SUDO_TESTS_DIRECTORIES+=("$sudo_test_temp_post_shell_home")
    run_sudo_test 22 && \
    output="$(sudo -si --post-shell-home="$sudo_test_temp_post_shell_home" --post-shell-stdin-string='exit' --post-shell-pre-commands='cd "$HOME"; pwd;' 2>&1)"
    return_value=$?
    # If android >= 10
    if [ "$ANDROID__BUILD_VERSION_SDK" -ge 29 ]; then
        validate_sudo_test 1 $return_value "$output" "" "The rootfs '/' partition cannot be mounted as rw to be used for SUDO_POST_SHELL_HOME '$sudo_test_temp_post_shell_home'" "*"
    else
        validate_sudo_test 0 $return_value "$output" r+="^${sudo_test_temp_post_shell_home}"$'\n'"([^"$'\n'"#]+)?# exit"$'\n'"exit$"
    fi



    sudo_test_temp_shell_home="/system/shell_home.$SUDO_TESTS_TEMP_DIRECTORY_SUFFIX"
    SUDO_TESTS_DIRECTORIES+=("$sudo_test_temp_shell_home")
    run_sudo_test 23 && \
    output="$(sudo -s --shell-home="$sudo_test_temp_shell_home" 'cd "$HOME"; pwd;' 2>&1)"
    return_value=$?
    # If android >= 10
    if [ "$ANDROID__BUILD_VERSION_SDK" -ge 29 ] || [[ "$SUDO_TESTS_SYSTEM_PARTITION_IS_RO" == "1" ]]; then
        validate_sudo_test 1 $return_value "$output" "" "The system '/system' partition cannot be mounted as rw to be used for SUDO_SHELL_HOME '$sudo_test_temp_shell_home'" "*"
    else
        validate_sudo_test 0 $return_value "$output" "$sudo_test_temp_shell_home"
    fi



    sudo_test_temp_post_shell_home="/system/post_shell_home.$SUDO_TESTS_TEMP_DIRECTORY_SUFFIX"
    SUDO_TESTS_DIRECTORIES+=("$sudo_test_temp_post_shell_home")
    run_sudo_test 24 && \
    output="$(sudo -si --post-shell-home="$sudo_test_temp_post_shell_home" --post-shell-stdin-string='exit' --post-shell-pre-commands='cd "$HOME"; pwd;' 2>&1)"
    return_value=$?
    # If android >= 10
    if [ "$ANDROID__BUILD_VERSION_SDK" -ge 29 ] || [[ "$SUDO_TESTS_SYSTEM_PARTITION_IS_RO" == "1" ]]; then
        validate_sudo_test 1 $return_value "$output" "" "The system '/system' partition cannot be mounted as rw to be used for SUDO_POST_SHELL_HOME '$sudo_test_temp_post_shell_home'" "*"
    else
        validate_sudo_test 0 $return_value "$output" r+="^${sudo_test_temp_post_shell_home}"$'\n'"([^"$'\n'"#]+)?# exit"$'\n'"exit$"
    fi




    sudo_test_temp_work_dir="$SUDO_TESTS_WORKING_DIR/work_dir.$SUDO_TESTS_TEMP_DIRECTORY_SUFFIX"
    SUDO_TESTS_DIRECTORIES+=("$sudo_test_temp_work_dir")

    run_sudo_test 25 && \
    output="$(sudo -s --work-dir="$sudo_test_temp_work_dir" 'pwd' 2>&1)"
    return_value=$?
    validate_sudo_test 0 $return_value "$output" "$sudo_test_temp_work_dir"

    run_sudo_test 26 && \
    output="$(sudo -s --work-dir='~/work_dir.'"$SUDO_TESTS_TEMP_DIRECTORY_SUFFIX" 'pwd' 2>&1)"
    return_value=$?
    validate_sudo_test 0 $return_value "$output" "$sudo_test_temp_work_dir"

    run_sudo_test 27 && \
    output="$(cd "$SUDO_TESTS_WORKING_DIR"; sudo -s --work-dir="./work_dir.$SUDO_TESTS_TEMP_DIRECTORY_SUFFIX" 'pwd' 2>&1)"
    return_value=$?
    validate_sudo_test 0 $return_value "$output" "$sudo_test_temp_work_dir"

    run_sudo_test 28 && \
    output="$(cd "$SUDO_TESTS_WORKING_DIR"; sudo -s --work-dir="work_dir.$SUDO_TESTS_TEMP_DIRECTORY_SUFFIX" 'pwd' 2>&1)"
    return_value=$?
    validate_sudo_test 0 $return_value "$output" "$sudo_test_temp_work_dir"

    run_sudo_test 29 && \
    output="$(sudo -s --work-dir="/" 'pwd' 2>&1)"
    return_value=$?
    validate_sudo_test 0 $return_value "$output" "/"

    run_sudo_test 30 && \
    output="$(sudo -s --work-dir="/system" 'pwd' 2>&1)"
    return_value=$?
    validate_sudo_test 0 $return_value "$output" "/system"





    # Redirect stderr to stdout, same as `--script-redirect=0`
    close_stdin
    run_sudo_test 31 && \
    sudo_tests_run_subshell_command stdout stderr sudo -so --shell="$shell" 'echo stdout; echo stderr 1>&2'
    return_value=$?
    reopen_stdin
    validate_sudo_test 0 $return_value "$stdout" "stdout"$'\n'"stderr"
    validate_sudo_test 0 $return_value "$stderr" ""

    # Redirect stdout to stderr, same as `--script-redirect=1`
    close_stdin
    run_sudo_test 32 && \
    sudo_tests_run_subshell_command stdout stderr sudo -sO --shell="$shell" 'echo stdout; echo stderr 1>&2'
    return_value=$?
    reopen_stdin
    validate_sudo_test 0 $return_value "$stdout" ""
    validate_sudo_test 0 $return_value "$stderr" "stdout"$'\n'"stderr"

    # Redirect redirect stdout to /dev/null
    close_stdin
    run_sudo_test 33 && \
    sudo_tests_run_subshell_command stdout stderr sudo -s --script-redirect=2 --shell="$shell" 'echo stdout; echo stderr 1>&2'
    return_value=$?
    reopen_stdin
    validate_sudo_test 0 $return_value "$stdout" ""
    validate_sudo_test 0 $return_value "$stderr" "stderr"

    # Redirect stderr to /dev/null for core_script, same as `--script-redirect=3`
    close_stdin
    run_sudo_test 34 && \
    sudo_tests_run_subshell_command stdout stderr sudo -sn --shell="$shell" 'echo stdout; echo stderr 1>&2'
    return_value=$?
    reopen_stdin
    validate_sudo_test 0 $return_value "$stdout" "stdout"
    validate_sudo_test 0 $return_value "$stderr" ""

    # Redirect both stdout and stderr to /dev/null, same as `--script-redirect=4`
    close_stdin
    run_sudo_test 35 && \
    sudo_tests_run_subshell_command stdout stderr sudo -sN --shell="$shell" 'echo stdout; echo stderr 1>&2'
    return_value=$?
    reopen_stdin
    validate_sudo_test 0 $return_value "$stdout" ""
    validate_sudo_test 0 $return_value "$stderr" ""

    # Redirect stderr to stdout and redirect stdout to stderr
    close_stdin
    run_sudo_test 36 && \
    sudo_tests_run_subshell_command stdout stderr sudo -s --script-redirect=5 --shell="$shell" 'echo stdout; echo stderr 1>&2'
    return_value=$?
    reopen_stdin
    validate_sudo_test 0 $return_value "$stdout" "stderr"
    validate_sudo_test 0 $return_value "$stderr" "stdout"

    # Redirect stderr to stdout and redirect stdout to /dev/null
    close_stdin
    run_sudo_test 37 && \
    sudo_tests_run_subshell_command stdout stderr sudo -s --script-redirect=6 --shell="$shell" 'echo stdout; echo stderr 1>&2'
    return_value=$?
    reopen_stdin
    validate_sudo_test 0 $return_value "$stdout" "stderr"
    validate_sudo_test 0 $return_value "$stderr" ""



    close_stdin
    run_sudo_test 38 && \
    sudo_tests_run_subshell_command stdout stderr sudo -sie --post-shell-stdin-string='exit' --shell="$shell" <(cat <<'SUDO_EOF'
# If argument count is not 2
if [ $# -ne 2 ]; then
        echo "Invalid argument count '$#' to 'termux_tasker_basic_bash_test'" 1>&2
        echo "$*" 1>&2
        exit 1
fi

echo "\$1=\`$1\`"
echo "\$2=\`$2\`"

exit 0
SUDO_EOF
) "$shell"
    return_value=$?
    reopen_stdin
    validate_sudo_test 1 $return_value "$stdout" ""
    validate_sudo_test 1 $return_value "$stderr" "Invalid argument count '1' to 'termux_tasker_basic_bash_test'"$'\n'"$shell"





    run_sudo_test 39 && \
    output="$(sudo -s --shell=bas 'echo "Hi, $1 $2."' "$shell" "shell" 2>&1)"
    validate_sudo_test 1 $? "$output" "" "The SUDO_SHELL 'bas' is not supported. It must be one of" "*"



    run_sudo_test 40 && \
    output="$(sudo -si --post-shell=bas 'echo "Hi, $1 $2."' "$shell" "shell" 2>&1)"
    validate_sudo_test 1 $? "$output" "" "The SUDO_POST_SHELL 'bas' is not supported. It must be one of" "*"



    run_sudo_test 41 && \
    output="$(sudo -s --shell-home='~/.config' 'echo "Hi, $1 $2."' "$shell" "shell" 2>&1)"
    validate_sudo_test 1 $? "$output" "" "The '$TERMUX_HOME/.config' cannot be used as SUDO_SHELL_HOME" "*"



    run_sudo_test 42 && \
    output="$(sudo -s --shell-home='$PREFIX/' 'echo "Hi, $1 $2."' "$shell" "shell" 2>&1)"
    validate_sudo_test 1 $? "$output" "" "The '$TERMUX_PREFIX' cannot be used as SUDO_SHELL_HOME" "*"



    run_sudo_test 43 && \
    output="$(sudo -s --shell-home='$PREFIX/home' 'echo "Hi, $1 $2."' "$shell" "shell" 2>&1)"
    validate_sudo_test 1 $? "$output" "" "The '$TERMUX_PREFIX/home' cannot be used as SUDO_SHELL_HOME" "*"



    run_sudo_test 44 && \
    output="$(sudo -si --post-shell-home='~/.config' 'echo "Hi, $1 $2."' "$shell" "shell" 2>&1)"
    validate_sudo_test 1 $? "$output" "" "The '$TERMUX_HOME/.config' cannot be used as SUDO_POST_SHELL_HOME" "*"



    run_sudo_test 45 && \
    output="$(sudo -si --post-shell-home='$PREFIX/' 'echo "Hi, $1 $2."' "$shell" "shell" 2>&1)"
    validate_sudo_test 1 $? "$output" "" "The '$TERMUX_PREFIX' cannot be used as SUDO_POST_SHELL_HOME" "*"



    run_sudo_test 46 && \
    output="$(sudo -si --post-shell-home='$PREFIX/home' 'echo "Hi, $1 $2."' "$shell" "shell" 2>&1)"
    validate_sudo_test 1 $? "$output" "" "The '$TERMUX_PREFIX/home' cannot be used as SUDO_POST_SHELL_HOME" "*"





    run_sudo_test 47 && \
    output="$(sudo -sr "[[ \",\" == \"$COMMA_ALTERNATIVE\" ]] && [[ "\$1" == \"$COMMA_ALTERNATIVE\" ]] && echo \"arg1 equals simple comma\"" "$COMMA_ALTERNATIVE")"
    validate_sudo_test 0 $? "$output" "arg1 equals simple comma"



    if [[ "$SUDO_TESTS_ONLY_BASH_TESTS" == "1" ]]; then
        return 0
    fi



    if [ -x "$TERMUX_PREFIX/bin/python" ]; then
        run_sudo_test 48 && \
        output="$(sudo -si --post-shell="python" --post-shell-stdin-string='exit(0)' 2>&1)"
        validate_sudo_test 0 $? "$output" "*" "Python" "*"
    fi





    ### Run zsh tests
    if [ -x "$TERMUX_PREFIX/bin/zsh" ]; then

        set_sudo_tests_current_test_shell "zsh"
        shell="zsh"


        run_sudo_test 1 && \
        output="$(sudo -s --shell="$shell" 'readlink -f /proc/$$/exe')"
        validate_sudo_test 0 $? "$output" "$TERMUX_PREFIX/bin/zsh"



        run_sudo_test 2 && \
        output="$(sudo -s --shell="$shell" <(cat <<'SUDO_EOF'
echo "Hi, $1 $2."
SUDO_EOF
) "$shell" "shell"
        )"
        validate_sudo_test 0 $? "$output" "Hi, $shell shell."



        run_sudo_test 3 && \
        output="$(sudo -s --shell="$shell" --shell-stdin-string="$shell" <(cat <<'SUDO_EOF'
echo "What is your name?"
read name
echo "Hi, $name."
SUDO_EOF
)
        )"
        validate_sudo_test 0 $? "$output" "What is your name?"$'\n'"Hi, $shell."

    else
        sudo_tests_log 3 "Skipping zsh tests since its not installed"
    fi





    ### Run dash tests
    if [ -x "$TERMUX_PREFIX/bin/dash" ]; then

        set_sudo_tests_current_test_shell "dash"
        shell="dash"


        run_sudo_test 1 && \
        output="$(sudo -s --shell="$shell" <(cat <<'SUDO_EOF'
echo "Hi, $1 $2."
SUDO_EOF
) "$shell" "shell"
        )"
        validate_sudo_test 0 $? "$output" "Hi, $shell shell."



        run_sudo_test 2 && \
        output="$(sudo -s --shell="$shell" --shell-stdin-string="$shell" <(cat <<'SUDO_EOF'
echo "What is your name?"
read name
echo "Hi, $name."
SUDO_EOF
)
        )"
        validate_sudo_test 0 $? "$output" "What is your name?"$'\n'"Hi, $shell."

    else
        sudo_tests_log 3 "Skipping dash tests since its not installed"
    fi





    ### Run sh tests
    if [ -x "$TERMUX_PREFIX/bin/sh" ]; then

        set_sudo_tests_current_test_shell "sh"
        shell="sh"


        run_sudo_test 1 && \
        output="$(sudo -s --shell="$shell" <(cat <<'SUDO_EOF'
echo "Hi, $1 $2."
SUDO_EOF
) "$shell" "shell"
        )"
        validate_sudo_test 0 $? "$output" "Hi, $shell shell."



        run_sudo_test 2 && \
        output="$(sudo -s --shell="$shell" --shell-stdin-string="$shell" <(cat <<'SUDO_EOF'
echo "What is your name?"
read name
echo "Hi, $name."
SUDO_EOF
)
        )"
        validate_sudo_test 0 $? "$output" "What is your name?"$'\n'"Hi, $shell."

    else
        sudo_tests_log 3 "Skipping sh tests since its not installed"
    fi





    ### Run fish tests
    if [ -x "$TERMUX_PREFIX/bin/fish" ]; then

        set_sudo_tests_current_test_shell "fish"
        shell="fish"

        run_sudo_test 1 && \
        output="$(sudo -s --shell="$shell" 'readlink -f /proc/$fish_pid/exe')"
        validate_sudo_test 0 $? "$output" "$TERMUX_PREFIX/bin/fish"


        run_sudo_test 2 && \
        output="$(sudo -s --shell="$shell" <(cat <<'SUDO_EOF'
echo "Hi, $argv[1] $argv[2]."
SUDO_EOF
) "$shell" "shell"
        )"
        validate_sudo_test 0 $? "$output" "Hi, $shell shell."



        run_sudo_test 3 && \
        output="$(sudo -s --shell="$shell" --shell-stdin-string="$shell" <(cat <<'SUDO_EOF'
echo "What is your name?"
read -p "" name
echo "Hi, $name."
SUDO_EOF
)
        )"
        validate_sudo_test 0 $? "$output" "What is your name?"$'\n'"Hi, $shell."

    else
        sudo_tests_log 3 "Skipping fish tests since its not installed"
    fi





    ### Run python tests
    if [ -x "$TERMUX_PREFIX/bin/python" ]; then

        set_sudo_tests_current_test_shell "python"
        shell="python"


        run_sudo_test 1 && \
        output="$(sudo -s --shell="$shell" <(cat <<'SUDO_EOF'
import sys
print("Hi, %s %s." % (sys.argv[1], sys.argv[2]))
SUDO_EOF
) "$shell" "shell"
        )"
        validate_sudo_test 0 $? "$output" "Hi, $shell shell."



        run_sudo_test 2 && \
        output="$(sudo -s --shell="$shell" --shell-stdin-string="$shell" <(cat <<'SUDO_EOF'
name = input("What is your name?\n")
print("Hi, %s." % name)
SUDO_EOF
)
        )"
        validate_sudo_test 0 $? "$output" "What is your name?"$'\n'"Hi, $shell."


        if [ -x "$TERMUX_HOME/.termux/tasker/termux_tasker_basic_python_test" ]; then
            run_sudo_test 3 && \
            output="$(sudo '~/.termux/tasker/termux_tasker_basic_python_test' "$shell" "shell")"
            validate_sudo_test 0 $? "$output" "\$1=\`$shell\`"$'\n'"\$2=\`shell\`"
        else
            skip_sudo_test 3
        fi

        if [ -x "$TERMUX_PREFIX/bin/yt-dlp" ]; then
            run_sudo_test 4 && \
            output="$(sudo -s --shell=python --script-name="yt-dlp" <(cat "$TERMUX_PREFIX/bin/yt-dlp") --help 1>/dev/null)"
            validate_sudo_test 0 $? "$output"
        else
            skip_sudo_test 4
        fi

        if [ -x "$TERMUX_PREFIX/bin/yt-dlp" ]; then
            run_sudo_test 5 && \
            output="$(sudo -sF --shell=python "$TERMUX_PREFIX/bin/yt-dlp" --help 1>/dev/null)"
            validate_sudo_test 0 $? "$output"
        else
            skip_sudo_test 5
        fi

        if [ -x "$TERMUX_PREFIX/bin/bandcamp-dl" ]; then
            run_sudo_test 6 && \
            output="$(sudo -s --shell=python "$(cat "$TERMUX_PREFIX/bin/bandcamp-dl")" --help)"
            validate_sudo_test 0 $? "$output"
        else
            skip_sudo_test 6
        fi

        if [ -x "$TERMUX_PREFIX/bin/bandcamp-dl" ]; then
            run_sudo_test 7 && \
            output="$(sudo -s --script-decode --shell=python "$(cat "$TERMUX_PREFIX/bin/bandcamp-dl" | base64)" --help)"
            validate_sudo_test 0 $? "$output"
        else
            skip_sudo_test 7
        fi

    else
        sudo_tests_log 3 "Skipping python tests since its not installed"
    fi





    ### Run ruby tests
    if [ -x "$TERMUX_PREFIX/bin/ruby" ]; then

        set_sudo_tests_current_test_shell "ruby"
        shell="ruby"


        run_sudo_test 1 && \
        output="$(sudo -s --shell="$shell" <(cat <<'SUDO_EOF'
puts "Hi, " + ARGV[0] + " " + ARGV[1] + "."
SUDO_EOF
) "$shell" "shell"
        )"
        validate_sudo_test 0 $? "$output" "Hi, $shell shell."



        run_sudo_test 2 && \
        output="$(sudo -s --shell="$shell" --shell-stdin-string="$shell" <(cat <<'SUDO_EOF'
puts "What is your name?"
name = STDIN.gets
name = '' if name.nil?
puts "Hi, " + name.chomp.to_s + "."
SUDO_EOF
)
        )"
        validate_sudo_test 0 $? "$output" "What is your name?"$'\n'"Hi, $shell."

    else
        sudo_tests_log 3 "Skipping ruby tests since its not installed"
    fi





    ### Run node tests
    if [ -x "$TERMUX_PREFIX/bin/node" ]; then

        set_sudo_tests_current_test_shell "node"
        shell="node"


        run_sudo_test 1 && \
        output="$(sudo -s --shell="$shell" <(cat <<'SUDO_EOF'
console.log(`Hi, ${process.argv[2]} ${process.argv[3]}.`)
SUDO_EOF
) "$shell" "shell"
        )"
        validate_sudo_test 0 $? "$output" "Hi, $shell shell."



        run_sudo_test 2 && \
        output="$(sudo -s --shell="$shell" --shell-stdin-string="$shell" <(cat <<'SUDO_EOF'
const readline = require('readline').createInterface({
    input: process.stdin,
    output: process.stdout
})

readline.question(`What is your name?\n`, (name) => {
    console.log(`Hi, ${name}.`)
    readline.close()
})
SUDO_EOF
)
                )"
                validate_sudo_test 0 $? "$output" "*" "Hi, $shell." ""

    else
        sudo_tests_log 3 "Skipping node tests since its not installed"
    fi





    ### Run perl tests
    if [ -x "$TERMUX_PREFIX/bin/perl" ]; then

        set_sudo_tests_current_test_shell "perl"
        shell="perl"


        run_sudo_test 1 && \
        output="$(sudo -s --shell="$shell" <(cat <<'SUDO_EOF'
print "Hi, ", $ARGV[0], " ", $ARGV[1], ".\n";
SUDO_EOF
) "$shell" "shell"
        )"
        validate_sudo_test 0 $? "$output" "Hi, $shell shell."



        run_sudo_test 2 && \
        output="$(sudo -s --shell="$shell" --shell-stdin-string="$shell" <(cat <<'SUDO_EOF'
print "What is your name?\n";
$name = <STDIN>;
chomp($name);
print "Hi, ", $name, ".\n";
SUDO_EOF
)
        )"
        validate_sudo_test 0 $? "$output" "What is your name?"$'\n'"Hi, $shell."

    else
        sudo_tests_log 3 "Skipping perl tests since its not installed"
    fi





    ### Run lua5.2 tests
    if [ -x "$TERMUX_PREFIX/bin/lua5.2" ]; then

        set_sudo_tests_current_test_shell "lua5.2"
        shell="lua5.2"


        run_sudo_test 1 && \
        output="$(sudo -s --shell="$shell" <(cat <<'SUDO_EOF'
io.write('Hi, ', arg[1], ' ', arg[2], '.\n')
SUDO_EOF
) "$shell" "shell"
        )"
        validate_sudo_test 0 $? "$output" "Hi, $shell shell."



        run_sudo_test 2 && \
        output="$(sudo -s --shell="$shell" --shell-stdin-string="$shell" <(cat <<'SUDO_EOF'
io.write('What is your name?\n')
local name = io.read()
io.write('Hi, ', name, '.\n')
SUDO_EOF
)
        )"
        validate_sudo_test 0 $? "$output" "What is your name?"$'\n'"Hi, $shell."

    else
        sudo_tests_log 3 "Skipping lua5.2 tests since its not installed"
    fi





    ### Run lua5.3 tests
    if [ -x "$TERMUX_PREFIX/bin/lua5.3" ]; then

        set_sudo_tests_current_test_shell "lua5.3"
        shell="lua5.3"


        run_sudo_test 1 && \
        output="$(sudo -s --shell="$shell" <(cat <<'SUDO_EOF'
io.write('Hi, ', arg[1], ' ', arg[2], '.\n')
SUDO_EOF
) "$shell" "shell"
        )"
        validate_sudo_test 0 $? "$output" "Hi, $shell shell."



        run_sudo_test 2 && \
        output="$(sudo -s --shell="$shell" --shell-stdin-string="$shell" <(cat <<'SUDO_EOF'
io.write('What is your name?\n')
local name = io.read()
io.write('Hi, ', name, '.\n')
SUDO_EOF
)
        )"
        validate_sudo_test 0 $? "$output" "What is your name?"$'\n'"Hi, $shell."

    else
        sudo_tests_log 3 "Skipping lua5.3 tests since its not installed"
    fi





    ### Run lua5.4 tests
    if [ -x "$TERMUX_PREFIX/bin/lua5.4" ]; then

        set_sudo_tests_current_test_shell "lua5.4"
        shell="lua5.4"


        run_sudo_test 1 && \
        output="$(sudo -s --shell="$shell" <(cat <<'SUDO_EOF'
io.write('Hi, ', arg[1], ' ', arg[2], '.\n')
SUDO_EOF
) "$shell" "shell"
        )"
        validate_sudo_test 0 $? "$output" "Hi, $shell shell."



        run_sudo_test 1 && \
        output="$(sudo -s --shell="$shell" --shell-stdin-string="$shell" <(cat <<'SUDO_EOF'
io.write('What is your name?\n')
local name = io.read()
io.write('Hi, ', name, '.\n')
SUDO_EOF
)
        )"
        validate_sudo_test 0 $? "$output" "What is your name?"$'\n'"Hi, $shell."

    else
        sudo_tests_log 3 "Skipping lua5.4 tests since its not installed"
    fi





    ### Run php tests
    if [ -x "$TERMUX_PREFIX/bin/php" ]; then

        set_sudo_tests_current_test_shell "php"
        shell="php"


        run_sudo_test 1 && \
        output="$(sudo -s --shell="$shell" <(cat <<'SUDO_EOF'
<?php
echo "Hi, " . $argv[1] . " " . $argv[2] . ".\n";
SUDO_EOF
) "$shell" "shell"
        )"
        validate_sudo_test 0 $? "$output" "Hi, $shell shell."



        run_sudo_test 2 && \
        output="$(sudo -s --shell="$shell" --shell-stdin-string="$shell" <(cat <<'SUDO_EOF'
<?php
echo "What is your name?\n";
$name = readline();
echo "Hi, " . $name . ".\n";
SUDO_EOF
)
        )"
        validate_sudo_test 0 $? "$output" "What is your name?"$'\n'"php"$'\n'"Hi, $shell."

    else
        sudo_tests_log 3 "Skipping php tests since its not installed"
    fi



    sudo_tests_log 5 $'\n\n'
    sudo_tests_log 2 "End '$SUDO_TESTS_COMMAND_TYPE' tests"

    return 0

}

##
# Capture stdout and stderr of command in separate variables.
#
# `sudo_tests_run_subshell_command` `<stdout_variable_name>` `<stderr_variable_name>` `<command>` [`<arguments...>`]
##
sudo_tests_run_subshell_command() {

    local return_value

    local stdout_variable_name="$1";
    local stderr_variable_name="$2"
    shift 2

    local valid_bash_variable_name_regex='^[a-zA-Z_][a-zA-Z0-9_]*(\[[0-9]+\])?$'

    # If stdout_variable_name does equals "stdout_variable_name" and or is not a valid bash variable_name
    if [[ "$stdout_variable_name" == "stdout_variable_name" ]]|| [[ ! "$stdout_variable_name" =~ $valid_bash_variable_name_regex ]]; then
        sudo_tests_log_errors "stdout_variable_name '$1' passed to 'sudo_tests_run_subshell_command' equals 'stdout_variable_name' or is not a valid bash variable name"
        return 1
    fi

    # If stderr_variable_name does equals "stderr_variable_name" and or is not a valid bash variable_name
    if [[ "$stderr_variable_name" == "stderr_variable_name" ]]|| [[ ! "$stderr_variable_name" =~ $valid_bash_variable_name_regex ]]; then
        sudo_tests_log_errors "stderr_variable_name '$1' passed to 'sudo_tests_run_subshell_command' equals 'stderr_variable_name' or is not a valid bash variable name"
        return 1
    fi

    unset "$stdout_variable_name"
    unset "$stderr_variable_name"

    # Credits madmurphy https://stackoverflow.com/a/59592881/14686958

    # some_command is launched

    # We then have some_command's stdout on the descriptor 1,
    # some_command's stderr on the descriptor 2 and
    # some_command's exit code redirected to the descriptor 3

    # stdout is piped to tr (sanitization) to remove NUL

    # stderr is swapped with stdout (using temporarily the descriptor 4) and piped to tr (sanitization)

    # The exit code (descriptor 3) is swapped with stderr (now descriptor 1) and piped to exit $(cat)

    # stderr (now descriptor 3) is redirected to the descriptor 1, end expanded as the second argument of printf

    # The exit code of exit $(cat) is captured by the third argument of printf

    # The output of printf is redirected to the descriptor 2, where stdout was already present

    # The concatenation of stdout and the output of printf is piped to read
    # shellcheck disable=SC1102,SC1105
    {
        IFS=$'\n' read -r -d '' "$stdout_variable_name";
        IFS=$'\n' read -r -d '' "$stderr_variable_name";
        (IFS=$'\n' read -r -d '' return_value; return $return_value);
    } < <((printf '\0%s\0%d\0' "$(((({ "$@"; echo "$?" 1>&3-; } | tr -d '\0' 1>&4-) 4>&2- 2>&1- | tr -d '\0' 1>&4-) 3>&1- | exit "$(cat)") 4>&1-)" "$?" 1>&2) 2>&1)
    # Fix syntax highlight `{

}

set_sudo_tests_current_test_shell () {

    sudo_tests_log 3 "$1()"

    SUDO_TESTS_PREVIOUS_TEMP_TEST_SHELL="$SUDO_TESTS_CURRENT_TEST_SHELL";
    SUDO_TESTS_CURRENT_TEST_SHELL="$1"

}

set_sudo_tests_current_test_number () {

    # To handle the case when SUDO_TESTS_USER_TEST_NUMBER was the last test of a shell
    if [[ -n "$SUDO_TESTS_PREVIOUS_TEMP_TEST_SHELL" ]]; then
        SUDO_TESTS_PREVIOUS_TEST_SHELL="$SUDO_TESTS_PREVIOUS_TEMP_TEST_SHELL"
        SUDO_TESTS_PREVIOUS_TEMP_TEST_SHELL=""
    else
        SUDO_TESTS_PREVIOUS_TEST_SHELL="$SUDO_TESTS_CURRENT_TEST_SHELL"
    fi

    SUDO_TESTS_PREVIOUS_TEST_NUMBER="$SUDO_TESTS_CURRENT_TEST_NUMBER";
    SUDO_TESTS_CURRENT_TEST_NUMBER="$1";

    # If SUDO_TESTS_USER_TEST_SHELL and SUDO_TESTS_USER_TEST_NUMBER are set
    # and
    # SUDO_TESTS_PREVIOUS_TEST_SHELL equals SUDO_TESTS_USER_TEST_SHELL
    # and
    # SUDO_TESTS_PREVIOUS_TEST_NUMBER equals SUDO_TESTS_USER_TEST_NUMBER,
    # then exit
    if [ -n "$SUDO_TESTS_USER_TEST_SHELL" ] && [ -n "$SUDO_TESTS_USER_TEST_NUMBER" ] && \
            [[ "$SUDO_TESTS_PREVIOUS_TEST_SHELL" == "$SUDO_TESTS_USER_TEST_SHELL" ]] && \
                [[ "$SUDO_TESTS_PREVIOUS_TEST_NUMBER" == "$SUDO_TESTS_USER_TEST_NUMBER" ]]; then
        sudo_tests_log 5 $'\n\n'
        sudo_tests_log 1 "User 'sudo' test successful"
        exit 0
    fi

    # If SUDO_TESTS_USER_TEST_SHELL and SUDO_TESTS_USER_TEST_NUMBER are set
    # and
    # SUDO_TESTS_CURRENT_TEST_SHELL does not equal SUDO_TESTS_USER_TEST_SHELL
    #     or
    # SUDO_TESTS_CURRENT_TEST_NUMBER does not equal SUDO_TESTS_USER_TEST_NUMBER,
    # then skip the current test
    if [ -n "$SUDO_TESTS_USER_TEST_SHELL" ] && [ -n "$SUDO_TESTS_USER_TEST_NUMBER" ] && \
            { [[ "$SUDO_TESTS_CURRENT_TEST_SHELL" != "$SUDO_TESTS_USER_TEST_SHELL" ]] || \
                [[ "$SUDO_TESTS_CURRENT_TEST_NUMBER" != "$SUDO_TESTS_USER_TEST_NUMBER" ]]; }; then
        return 112
    else
        sudo_tests_run_test=1
        return 0
    fi

}

##
# `run_sudo_test` `<current_test_number>`
##
run_sudo_test () {

    set_sudo_tests_current_test_number "$1" || return $?
    sudo_tests_log 5 $'\n\n'
    sudo_tests_log 4 "$SUDO_TESTS_CURRENT_TEST_NUMBER()"

}

##
# `skip_sudo_test` `<current_test_number>`
##
skip_sudo_test () {

    set_sudo_tests_current_test_number "$1" || return $?
    sudo_tests_log 5 $'\n\n'"Skipping $SUDO_TESTS_CURRENT_TEST_SHELL shell test $SUDO_TESTS_CURRENT_TEST_NUMBER";

}

##
# `validate_sudo_test` `<expected_result_value>` `<actual_result_value>` `<actual_output>` `<expected_output>`
# `validate_sudo_test` `<expected_result_value>` `<actual_result_value>` `<actual_output>` `<expected_output_prefix_glob>` `<expected_output>` `<expected_output_suffix_glob>`
##
validate_sudo_test () {

    local return_value

    if [[ "$sudo_tests_run_test" != "1" ]]; then
        return 0
    fi

    local expected_result_value="$1"
    local actual_result_value="$2"

    # Remove all escape sequences and strip all characters except tab(11), linefeed(12) and characters in range 40-176
    local actual_output="$(sed 's/\x1b\[[0-9;]*[a-zA-Z]//g' <<< "$3" | tr -cd '\11\12\40-\176')"

    local expected_output
    local output_match_test_failed=0

    # If actual_output is set
    if [ -n "$actual_output" ]; then
        sudo_tests_log_no_tag 5 "$(cat -v <<<"$actual_output")"
    fi

    # If argument count equals 4 and actual_output does not exactly match $4
    if [ $# -eq 4 ]; then
        if [[  "$4" == "r+="* ]]; then
            if [[ ! "$actual_output" =~ ${4:3} ]]; then
                output_match_test_failed=1
                expected_output="$4"
            fi
        elif [[ "$actual_output" != "$4" ]]; then
            output_match_test_failed=1
            expected_output="$4"
        fi
    fi

    # If argument count greater than 4 and actual_output does not exactly match $5 with $4 and $6 as optional globs
    if [ $# -gt 4 ] && [[ "$actual_output" != $4"$5"$6 ]]; then
        output_match_test_failed=1
        expected_output="$4$5$6"
    fi

    # If output_match_test_failed is enabled
    if [[  "$output_match_test_failed" == "1" ]]; then
        sudo_tests_log_errors $'\n'"$SUDO_TESTS_CURRENT_TEST_SHELL shell test $SUDO_TESTS_CURRENT_TEST_NUMBER for '$SUDO_TESTS_COMMAND_TYPE' command type failed since expected_output does not match actual_output"
        sudo_tests_log_errors $'\n'"expected_output=\`$expected_output\`"
        sudo_tests_log_errors $'\n'"actual_output=\`$actual_output\`"
        exit 1
    fi

    # If actual_result_value is not a valid exit code
    if [[ ! "$actual_result_value" =~ $VALID_NUMBER_REGEX ]]; then
        sudo_tests_log_errors $'\n'"$SUDO_TESTS_CURRENT_TEST_SHELL shell test $SUDO_TESTS_CURRENT_TEST_NUMBER for '$SUDO_TESTS_COMMAND_TYPE' command type exit code '$actual_result_value' is invalid"
        exit 1
    fi

    # If expected_result_value is not a valid exit code
    if [[ ! "$expected_result_value" =~ $VALID_NUMBER_REGEX ]]; then
        sudo_tests_log_errors $'\n'"$SUDO_TESTS_CURRENT_TEST_SHELL shell test $SUDO_TESTS_CURRENT_TEST_NUMBER for '$SUDO_TESTS_COMMAND_TYPE' command type exit code '$expected_result_value' is invalid"
        exit 1
    fi

    # If actual_result_value does not equal expected_result_value
    if [[ "$actual_result_value" != "$expected_result_value" ]]; then
        sudo_tests_log_errors $'\n'"$SUDO_TESTS_CURRENT_TEST_SHELL shell test $SUDO_TESTS_CURRENT_TEST_NUMBER for '$SUDO_TESTS_COMMAND_TYPE' command type failed with exit code $actual_result_value but expected exit code was $expected_result_value"
        exit "$actual_result_value"
    fi

    return 0

}

sudo_tests_cleanup() {

    # The sudo_tests_cleanup will do the following:
    # Remove the EXIT trap so its not called again.
    # Remove temp_directory if set.
    # If a signal argument was passed, then remove its trap and
    # then exit with the same signal
    # so that parent processes can be notified if necessary.

    local sudo_tests_exit_code=$?
    trap - EXIT
    sudo_tests_remove_sudo_tests_temp_directories
    [ -n "$1" ] && trap - "$1"; exit $sudo_tests_exit_code;

}

sudo_tests_remove_sudo_tests_temp_directories() {

    # Set SU and SU_BIN_PATH
    # Redirecting stderr to /dev/null since the following would ideally also fail on the first test run
    sudo_set_su_variables &>/dev/null || return $?

    # If SU, SUDO_TESTS_DIRECTORIES and SUDO_TESTS_TEMP_DIRECTORY_SUFFIX are set
    if [ -n "$SU" ] && [ ${#SUDO_TESTS_DIRECTORIES[@]} -ne 0 ] && [ -n "$SUDO_TESTS_TEMP_DIRECTORY_SUFFIX" ]; then

        sudo_tests_log 5 $'\n\n'"Running sudo_tests_remove_sudo_tests_temp_directories"

        local rootfs_partition_dependent_paths=""
        local system_partition_dependent_paths=""

        # Set rootfs_partition_dependent_paths and system_partition_dependent_paths
        # which are required by the sudo_set_su_env_command function to add '--mount-master option' to SU_ENV_COMMAND

        for i in "${!SUDO_TESTS_DIRECTORIES[@]}"; do
            SUDO_TESTS_DIRECTORY="${SUDO_TESTS_DIRECTORIES[$i]}"

            # Find the parent directory of the SUDO_TESTS_DIRECTORY
            SUDO_TESTS_DIRECTORY_BASENAME="${SUDO_TESTS_DIRECTORY##*/}" #strip longest match of */ from start
            SUDO_TESTS_DIRECTORY_PARENT_DIR="${SUDO_TESTS_DIRECTORY:0:${#SUDO_TESTS_DIRECTORY} - ${#SUDO_TESTS_DIRECTORY_BASENAME}}" # Substring from 0 to position of basename
            case "$SUDO_TESTS_DIRECTORY_PARENT_DIR" in *[!/]*/) SUDO_TESTS_DIRECTORY_PARENT_DIR=${SUDO_TESTS_DIRECTORY_PARENT_DIR%"${SUDO_TESTS_DIRECTORY_PARENT_DIR##*[!/]}"};; *[/]) SUDO_TESTS_DIRECTORY_PARENT_DIR="/";; esac # Remove trailing slashes if not root

            # If SUDO_TESTS_DIRECTORY_PARENT_DIR is in rootfs "/" partition
            if [[ "$SUDO_TESTS_DIRECTORY_PARENT_DIR" =~ $VALID_PATH_IN_ROOTFS_PARTITION_REGEX ]]; then
                rootfs_partition_dependent_paths+=" '$SUDO_TESTS_DIRECTORY'"
            fi

            # If SUDO_TESTS_DIRECTORY is in system "/system" partition
            if [[ "$SUDO_TESTS_DIRECTORY" =~ $VALID_PATH_IN_SYSTEM_PARTITION_REGEX ]] && [[ "$SUDO_TESTS_SYSTEM_PARTITION_IS_RO" != "1" ]]; then
                system_partition_dependent_paths+=" '$SUDO_TESTS_DIRECTORY'"
            fi
        done


        # If android < 10
        if [[ "$ANDROID__BUILD_VERSION_SDK" =~ $VALID_NUMBER_REGEX ]] && [ "$ANDROID__BUILD_VERSION_SDK" -lt 29 ]; then
            # If rootfs_partition_dependent_paths is set
            if [ -n "$rootfs_partition_dependent_paths" ]; then
                # Remount android rootfs partition as rw
                sudo_tests_log 5 "Remounting rootfs '/' partition as rw to be used for$rootfs_partition_dependent_paths"
                sudo_remount_partition "rootfs" "rw" 0
                return_value=$?
                if [ $return_value -ne 0 ] && [ $return_value -ne 112 ]; then
                    sudo_tests_log_errors "Failed to mount rootfs '/' partition as rw to be used for$rootfs_partition_dependent_paths"
                    return $return_value
                fi
            fi

            # If system_partition_dependent_paths is set
            if [ -n "$system_partition_dependent_paths" ]; then
                # Remount android system partition as rw
                sudo_tests_log 5 "Remounting system '/system' partition as rw to be used for$system_partition_dependent_paths"
                sudo_remount_partition "system" "rw" 0
                return_value=$?
                if [ $return_value -ne 0 ] && [ $return_value -ne 112 ]; then
                    sudo_tests_log_errors "Failed to mount system '/system' partition as rw to be used for$system_partition_dependent_paths"
                    return $return_value
                fi
            fi
        fi


        # Remove all directories in SUDO_TESTS_DIRECTORIES if they match the SUDO_TESTS_TEMP_DIRECTORY_SUFFIX
        for i in "${!SUDO_TESTS_DIRECTORIES[@]}"; do
            if [[ "${SUDO_TESTS_DIRECTORIES[$i]}" == *"$SUDO_TESTS_TEMP_DIRECTORY_SUFFIX" ]]; then
                sudo_unset_pre_su_variables
                "$SU" --mount-master -c "[ -d \"${SUDO_TESTS_DIRECTORIES[$i]}\" ] && rm -rf \"${SUDO_TESTS_DIRECTORIES[$i]}\""
                sudo_set_post_su_variables
            fi
        done


        # If android < 10
        if [[ "$ANDROID__BUILD_VERSION_SDK" =~ $VALID_NUMBER_REGEX ]] && [ "$ANDROID__BUILD_VERSION_SDK" -lt 29 ]; then
            # If rootfs_partition_dependent_paths is set
            if [ -n "$rootfs_partition_dependent_paths" ]; then
                sudo_remount_partition "rootfs" "ro" "0"
            fi

            # If system_partition_dependent_paths is set
            if [ -n "$system_partition_dependent_paths" ]; then
                sudo_remount_partition "system" "ro" "0"
            fi
        fi

    fi

    return 0

}

##
# `sudo_tests_process_script_arguments` [`<argument...>`]
##
sudo_tests_process_script_arguments() {

    local opt; local opt_arg; local OPTARG=""; local OPTIND=1;

    # Parse options to main command
    while getopts ":hqv-:" opt; do
        case "${opt}" in
            -)
                case "${OPTARG}" in *?=*) opt_arg="${OPTARG#*=}";; *) opt_arg="";; esac
                case "${OPTARG}" in
                    help-extra)
                        sudo_tests_log_args "Parsing option: '--${OPTARG%=*}'"
                        sudo_tests_show_help_extra || return $?
                        SUDO_TESTS_NOOP_COMMAND=1; return 0
                        ;;
                    help-extra=*)
                        sudo_tests_log_arg_errors "Arguments not allowed for flag option '--${OPTARG%=*}': \`--${OPTARG:-}\`."
                        sudo_tests_exit_on_args_error || return $?
                        ;;
                    help)
                        sudo_tests_log_args "Parsing option: '--${OPTARG%=*}'"
                        sudo_tests_show_help || return $?
                        SUDO_TESTS_NOOP_COMMAND=1; return 0
                        ;;
                    help=*)
                        sudo_tests_log_arg_errors "Arguments not allowed for flag option '--${OPTARG%=*}': \`--${OPTARG:-}\`."
                        sudo_tests_exit_on_args_error || return $?
                        ;;
                    only-bash-tests)
                        sudo_tests_log_args "Parsing option: '--${OPTARG%=*}'"
                        SUDO_TESTS_ONLY_BASH_TESTS=1
                        ;;
                    only-bash-tests=*)
                        sudo_tests_log_arg_errors "Arguments not allowed for flag option '--${OPTARG%=*}': \`--${OPTARG:-}\`."
                        sudo_tests_exit_on_args_error || return $?
                        ;;
                    quiet)
                        sudo_tests_log_args "Parsing option: '--${OPTARG%=*}'"
                        SUDO_TESTS_LOG_LEVEL=0
                        ;;
                    quiet=*)
                        sudo_tests_log_arg_errors "Arguments not allowed for flag option '--${OPTARG%=*}': \`--${OPTARG:-}\`."
                        sudo_tests_exit_on_args_error || return $?
                        ;;
                    '')
                        sudo_tests_log_args "Parsing option: '--'"
                        break # End of options '--'.
                        ;;
                    *)
                        sudo_tests_log_arg_errors "Unknown option: '--${OPTARG:-}'."
                        sudo_tests_exit_on_args_error || return $?
                        ;;
                esac
                ;;
            h)
                sudo_tests_log_args "Parsing option: '-${opt}'"
                sudo_tests_show_help || return $?
                SUDO_TESTS_NOOP_COMMAND=1; return 0
                ;;
            q)
                sudo_tests_log_args "Parsing option: '-${opt}'"
                SUDO_TESTS_LOG_LEVEL=0
                ;;
            v)
                sudo_tests_log_args "Parsing option: '-${opt}'"
                if [ "$SUDO_TESTS_LOG_LEVEL" -lt "$SUDO_TESTS_MAX_LOG_LEVEL" ]; then
                    SUDO_TESTS_LOG_LEVEL=$((SUDO_TESTS_LOG_LEVEL+1));
                else
                    sudo_tests_log_arg_errors "Invalid Option, max log level is $SUDO_TESTS_MAX_LOG_LEVEL"
                    sudo_tests_exit_on_args_error || return $?
                fi
                ;;
            :)
                sudo_tests_log_arg_errors "No argument passed for arg option '-$OPTARG'."
                sudo_tests_exit_on_args_error || return $?
                ;;
            \?)
                sudo_tests_log_arg_errors "Unknown option${OPTARG:+": '-${OPTARG:-}'"}."
                sudo_tests_exit_on_args_error || return $?
                ;;
        esac
    done
    shift $((OPTIND - 1)) # Remove already processed arguments from arguments array

    SUDO_TESTS_COMMAND_TYPE="$1"
    SUDO_TESTS_USER_TEST_SHELL="$2"
    SUDO_TESTS_USER_TEST_NUMBER="$3"

}

sudo_tests_show_help() {

    cat<<<"$SUDO_TESTS_HELP"

}

sudo_tests_show_help_extra() {

    sudo_tests_show_help

    cat<<<"$SUDO_TESTS_HELP_EXTRA"

}

sudo_tests_exit_on_args_error() {

    sudo_tests_show_help || return $?
    return 64 # EX__USAGE

}



# Call main function
sudo_tests_main "$@"
