blob: 3239fcdce6ef0c684056c4eb05fb8bd4583ee6a8 [file] [log] [blame]
#!/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.
### Test expected usage of host-tool in fx scripts
BT_FILE_DEPS=(
"scripts/fx"
"tools/devshell/lib/fx-cmd-locator.sh"
"tools/devshell/lib/fx-optional-features.sh"
"tools/devshell/lib/host_symbolizer.sh"
"tools/devshell/lib/vars.sh"
"tools/devshell/lib/platform.sh"
"tools/devshell/host-tool"
)
BT_MOCKED_TOOLS=(
"tools/devshell/list-build-artifacts"
"tools/devshell/build"
)
declare fx ffx macfw
BT_SET_UP() {
source "${BT_TEMP_DIR}/tools/devshell/tests/lib/fuchsia-mock.sh"
fx="$(btf::setup_fx)"
source "${BT_TEMP_DIR}/tools/devshell/lib/vars.sh"
fx-config-read
ffx="$(btf::make_installed_hosttools_mock ffx)"
ffx_rel="${ffx##${FUCHSIA_BUILD_DIR}/}"
cat >"${BT_TEMP_DIR}/tools/devshell/list-build-artifacts.mock_side_effects" <<EOF
[[ \$2 == "ffx" ]] && echo ${ffx_rel} && exit 0
exit 1
EOF
local uname="$(btf::make_mock_binary uname)"
btf::add_binary_to_path "$uname"
macfw="$(btf::make_mock_binary socketfilterfw)"
btf::add_binary_to_path "$macfw"
# Fake uname as MacOS
cat > "${uname}.mock_side_effects" <<'EOF'
[[ $1 == '-s' ]] && echo "Darwin"
[[ $1 == '-m' ]] && echo "x86_64"
EOF
}
TEST_tool_executed() {
BT_EXPECT ${fx} host-tool "ffx" "--flag1" "arg1"
btf::expect-mock-args "${ffx}" "--flag1" "arg1"
}
TEST_tool_not_built() {
BT_EXPECT ${fx} host-tool "ffx" "--flag1" "arg1"
# tool exists, so build should not be called
BT_ASSERT_FILE_DOES_NOT_EXIST "${BT_TEMP_DIR}/tools/devshell/build.mock_state"
}
TEST_build_if_not_found() {
# tool does not exist, but is known to the build, so build should be called
mv "${ffx}" "${ffx}_backup"
# recreate the tool when 'fx build' is called
cat >"${BT_TEMP_DIR}/tools/devshell/build.mock_side_effects" <<EOF
mv "${ffx}_backup" "${ffx}"
EOF
# When run under the fx test framework, stdout is not a tty, so
# host-tool will not build, instead it will print an error.
BT_EXPECT_FAIL ${fx} host-tool "ffx" "--flag1" "arg1" 2>/dev/null
BT_ASSERT_FILE_DOES_NOT_EXIST "${BT_TEMP_DIR}/tools/devshell/build.mock_state"
# HACK: this tool checks to see if stdout is a tty, and builds iff it
# is, so it is mocked.
cat >>"${BT_TEMP_DIR}/tools/devshell/lib/vars.sh" <<EOF
function fx-is-stderr-tty {
return 0
}
EOF
BT_EXPECT ${fx} host-tool "ffx" "--flag1" "arg1"
BT_ASSERT_FILE_EXISTS "${BT_TEMP_DIR}/tools/devshell/build.mock_state"
btf::expect-mock-args "${ffx}" "--flag1" "arg1"
}
TEST_no_build() {
# tool does not exist, is known to the build, but --no-build is specified
mv "${ffx}" "${ffx}_backup"
# should fail because tool cannot be found
BT_EXPECT_FAIL ${fx} host-tool "--no-build" "ffx" "--flag1" "arg1" 2> /dev/null
# ensure that build was not called
BT_ASSERT_FILE_DOES_NOT_EXIST "${BT_TEMP_DIR}/tools/devshell/build.mock_state"
}
TEST_firewall_disabled() {
echo "firewall disabled" > "${macfw}.mock_stdout"
BT_EXPECT ${fx} host-tool --check-firewall "ffx" "--flag1" "arg1"
btf::expect-mock-args "${macfw}.mock_state" "--getglobalstate"
}
TEST_firewall_check_success() {
echo "${ffx} permitted" > "${macfw}.mock_stdout"
BT_EXPECT ${fx} host-tool --check-firewall "ffx" "--flag1" "arg1"
btf::expect-mock-args "${macfw}.mock_state.2" "--getappblocked" "${ffx}"
}
TEST_firewall_check_fail() {
echo "ffx cannot be allowed" > "${macfw}.mock_stdout"
BT_EXPECT ${fx} host-tool --check-firewall "ffx" "--flag1" "arg1" >/dev/null 2>&1
btf::expect-mock-args "${macfw}.mock_state.2" "--getappblocked" "${ffx}"
}
# test if sending the host-tool to the background and killing it effectively
# kills it as expected.
# the logic for this test is the following:
# - execute a custom fx command (mycmd)
# - 'fx mycmd' runs 'host-tool slow_tool' in the background, waits a bit and
# attempts to kill it with SIGTERM, simulating a user Ctrl+C in the foreground
# command. SIGINT can't be used because old versions of Bash ignore it
# when the process is running in background.
# - 'slow_tool' should be stopped and have a chance to clean up resources, in
# this case a lock file in a known location, which is checked as a condition
# for the test to succeeed.
TEST_kill_bg_process() {
lockfile="${BT_TEMP_DIR}/.slow_tool.lock"
local frontend_cmd="${BT_TEMP_DIR}/tools/devshell/mycmd"
cat >"${frontend_cmd}" <<EOF
#!/bin/bash
source ${BT_TEMP_DIR}/tools/devshell/lib/vars.sh
fx-command-exec host-tool slow_tool &
pid=\$!
# give some time for slow_tool to create the lockfile
SECONDS=0
while [[ ! -f "$lockfile" ]] ; do
if [[ $SECONDS -gt 10 ]]; then
echo >&2 "ERROR, timed out waiting for lockfile to be created"
exit 1
fi
done
kill -TERM \$pid
wait \$pid
EOF
chmod +x "${frontend_cmd}"
local slow_tool="$(btf::make_installed_hosttools_mock slow_tool)"
local slow_tool_rel="${slow_tool##${FUCHSIA_BUILD_DIR}/}"
cat >"${BT_TEMP_DIR}/tools/devshell/list-build-artifacts.mock_side_effects" <<EOF
[[ \$2 == "slow_tool" ]] && echo ${slow_tool_rel} && exit 0
exit 1
EOF
cat >"${slow_tool}.mock_side_effects" <<EOF
cleanup() {
local st=\$1
echo >&2 "cleanup executed, status \$st."
rm -f "$lockfile"
exit \$st
}
trap 'cleanup 0' SIGTERM
touch "$lockfile"
c=0
while (( c < 10 )); do
sleep 1
echo >&2 "sleeping inside slow_tool"
(( c++ ))
done
echo >&2 "ERROR! timeout passed without slow_tool being killed: $slow_tool"
cleanup 1
EOF
local _out="${BT_TEMP_DIR}/_out.log"
BT_EXPECT ${fx} mycmd >"$_out" 2>&1
BT_EXPECT_FILE_DOES_NOT_EXIST "$lockfile"
}
BT_RUN_TESTS "$@"