| #!/bin/bash | |
| # Copyright 2019 The Fuchsia Authors. All rights reserved. | |
| # Use of this source code is governed by a BSD-style license that can be | |
| # found in the LICENSE file. | |
| #### CATEGORY=Other | |
| ### run tests of fx and subcommands | |
| ## Usage: | |
| ## fx self-test --all | |
| ## Run all tests from all test scripts. | |
| ## | |
| ## fx self-test TEST_SCRIPT|TEST_DIR [TEST_SCRIPT|TEST_DIR ...] | |
| ## Run all tests from the specified test script(s) or in the | |
| ## test scripts in the specified test subdirectory(ies), recursively. | |
| ## | |
| ## TEST_SCRIPT Name of a test script file containing tests. | |
| ## Test script filenames end with "_test" and are | |
| ## relative to //tools/devshell/tests. | |
| ## See the existing test scripts below. | |
| ## | |
| ## TEST_DIR A subdirectory of //tools/devshell/tests. | |
| ## | |
| ## fx self-test TEST_SCRIPT [--test TEST_NAME] [--help] | |
| ## Executes a single test script. | |
| ## --test TEST_NAME Only run the specified test | |
| ## --help List the tests and test options in the test script | |
| ## | |
| ## | |
| ## Examples: | |
| ## fx self-test --all # run all tests from all tests scripts | |
| ## fx self-test subcommands # run all tests scripts in //tools/devshell/tests/subcommands | |
| ## fx self-test subcommands/fx_set_test # run all tests in //tools/devshell/tests/subcommands/fx_set_test | |
| ## fx self-test fx-internal/fx_test # run all tests in //tools/devshell/tests/fx-internal/fx_test | |
| ## fx self-test fx-internal/fx_test --test TEST_fx-subcommand-run # run a single test from fx-internal/fx_test | |
| source "$(cd "$(dirname "${BASH_SOURCE[0]}")" >/dev/null 2>&1 && pwd)"/lib/vars.sh \ | |
| || exit $? | |
| source "$(cd "$(dirname "${BASH_SOURCE[0]}")" >/dev/null 2>&1 && pwd)"/lib/style.sh \ | |
| || exit $? | |
| declare -r test_framework_dir="${FUCHSIA_DIR}/tools/devshell/tests/lib" | |
| usage() { | |
| fx-command-help | |
| echo | |
| echo "Available test scripts:" | |
| local has_not_in_cq=false | |
| for script_name in $(list_tests | sort); do | |
| local simple="${script_name#${FUCHSIA_DIR}/}" | |
| echo -n " //${simple}" | |
| if ! is_in_buildgn "$simple"; then | |
| echo " $(style::echo --color red -n "(not in CQ)")" | |
| has_not_in_cq=true | |
| else | |
| echo | |
| fi | |
| done | |
| if $has_not_in_cq; then | |
| fx-warn "Some tests are not configured to run in CQ." | |
| fx-warn "If possible, add them to //tools/devshell/BUILD.gn or //vendor/*/scripts/devshell/BUILD.gn" | |
| fi | |
| } | |
| is_in_buildgn() { | |
| # for performance reasons, this method uses a regular expression | |
| # to look up in the corresponding BUILD.gn file. The exact search would | |
| # require a more extensive GN walk and some assumptions about infra | |
| # setup. The current heuristics is sufficiently stable as long as the | |
| # corresponding BUILD.gn files keep the same structure. | |
| local n="$1" | |
| local buildgn="tools/devshell/BUILD.gn" | |
| if [[ "$1" =~ ^vendor/(.*)/scripts/devshell/tests ]]; then | |
| v="${BASH_REMATCH[1]}" | |
| buildgn="vendor/${v}/scripts/devshell/BUILD.gn" | |
| fi | |
| local p="$(dirname "$buildgn")" | |
| n="${n#$p/}" | |
| grep -q "^\\s*\"$n\"" $buildgn | |
| } | |
| # //<dir> | |
| # //<file> | |
| #if dir exists, use it. If file exists, use it | |
| #otherwise, prefix with tools/devshell/tests and test again | |
| # ./<dir> | |
| # ./<file> | |
| # <dir_or_file_inside_tools/devshell/tests/...> | |
| list_tests() { | |
| local file=$1 | |
| # expand // to FUCHSIA_DIR: | |
| if [[ "$file" =~ ^// ]]; then | |
| file="${FUCHSIA_DIR}/${file#\//}" | |
| fi | |
| if [[ -f "$file" && "$file" =~ _test$ ]]; then | |
| echo "$file" | |
| else | |
| file="/${file}" | |
| list_tests_in_dir "${FUCHSIA_DIR}/tools/devshell/tests${file}" | |
| list_tests_in_dir "${FUCHSIA_DIR}"/vendor/*/scripts/devshell/tests"${file}" | |
| fi | |
| } | |
| list_tests_in_dir() { | |
| # the old 'find' tool in MacOS does not handle trailing slashs correctly. | |
| local d="${1%/}" | |
| if [[ -d "$d" ]]; then | |
| find "$d" -type f -path "*/devshell/*" -not -path "*/lib/*" -not -path "*/data/*" -name "*_test" | |
| elif [[ -f "$d" ]]; then | |
| echo "$d" | |
| fi | |
| } | |
| launch_script() { | |
| declare -r test_script_path="$1" | |
| shift | |
| if [[ ! -f "${test_script_path}" ]]; then | |
| fx-error "Test script '${test_script_path}' not found. Aborting." | |
| return 1 | |
| fi | |
| # propagate certain bash flags if present | |
| local shell_flags=() | |
| if [[ $- == *x* ]]; then | |
| shell_flags+=( -x ) | |
| fi | |
| # Start a clean environment, load the bash_test_framework.sh, | |
| # then start the test script. | |
| local -r launch_script="$(cat << EOF | |
| source "${test_framework_dir}/bash_test_framework.sh" || exit \$? | |
| source "${test_script_path}" || exit \$? | |
| EOF | |
| )" | |
| /usr/bin/env -i \ | |
| USER="${USER}" \ | |
| HOME="${HOME}" \ | |
| bash "${shell_flags[@]}" \ | |
| -c "${launch_script}" "${test_script_path}" "$@" | |
| } | |
| if [[ $# -eq 0 || "$1" == "--help" ]]; then | |
| usage | |
| exit 0 | |
| fi | |
| all=0 | |
| test_args=() | |
| if [[ "$1" == "--all" ]]; then | |
| tests="$(list_tests)" | |
| else | |
| tests_arr=() | |
| while [[ $# -gt 0 && "$1" != "--"* ]]; do | |
| arg="$1" | |
| expanded_tests=( $(list_tests "$arg") ) | |
| if [[ "${#expanded_tests[@]}" -eq 0 ]]; then | |
| fx-error "Invalid test name or directory '$arg'" | |
| usage | |
| exit 1 | |
| fi | |
| tests_arr+=( "${expanded_tests[@]}" ) | |
| shift | |
| done | |
| tests="${tests_arr[@]}" | |
| if [[ $# -gt 0 && "$1" == "--"* ]]; then | |
| test_args+=( "$@" ) | |
| fi | |
| fi | |
| for script_name in ${tests}; do | |
| echo "Running test script ${script_name}" | |
| launch_script "${script_name}" "${test_args[@]}" | |
| done |