blob: b6e6dc5320ab6b2a1cbcaf42c74ad8580668edcf [file]
#!/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.
source "$(cd "$(dirname "${BASH_SOURCE[0]}")" >/dev/null 2>&1 && pwd)"/../../lib/vars.sh || exit $?
BT_FILE_DEPS=(
"prebuilt/third_party/jq/${HOST_PLATFORM}/bin/jq"
"tools/devshell/jq.fx"
"tools/devshell/lib/fx-cmd-locator.sh"
"tools/devshell/lib/fx-optional-features.sh"
"tools/devshell/lib/generate-ssh-config.sh"
"tools/devshell/lib/vars.sh"
"tools/devshell/lib/is_invoked_by_agent.sh"
"tools/devshell/lib/agents.txt"
"tools/devshell/lib/platform.sh"
)
# Replace fx-regenerator with stub.
unset -f fx-regenerator
function fx-regenerator {
ln -sf "${BT_TEMP_DIR}/${BUILD_DIR}"/rust-project.json "${FUCHSIA_DIR}"/rust-project.json
ln -sf "${BT_TEMP_DIR}/${BUILD_DIR}"/compile_commands.json "${FUCHSIA_DIR}"/compile_commands.json
}
BT_SET_UP() {
source "${BT_TEMP_DIR}/tools/devshell/tests/lib/fuchsia-mock.sh"
local _BUILD_DIR="out/default"
echo "${_BUILD_DIR}" > "${BT_TEMP_DIR}/.fx-build-dir"
_create_build_dir "$_BUILD_DIR"
ffx="$(btf::make_installed_hosttools_mock ffx)"
btf::make_mock "${BT_TEMP_DIR}/tools/devshell/host-tool"
cat > "${BT_TEMP_DIR}/tools/devshell/host-tool.mock_side_effects" <<EOF
if [[ "\$2" == "ffx" ]]; then
shift
"${ffx}" "\$@"
fi
EOF
}
_create_build_dir() {
local _BUILD_DIR="$1"
mkdir -p "${BT_TEMP_DIR}/${_BUILD_DIR}"
touch "${BT_TEMP_DIR}/${_BUILD_DIR}/args.gn"
touch "${BT_TEMP_DIR}/${_BUILD_DIR}/fx.config"
}
TEST_environment() {
# This variable should be empty.
BT_EXPECT_EMPTY "${devshell_lib_dir}"
}
TEST_fx-warn() {
BT_ASSERT_FUNCTION_EXISTS fx-warn
# Capture stderr.
local result
result=$( fx-warn some warning 2>&1 )
BT_EXPECT_STRING_CONTAINS_SUBSTRING "${result}" "some warning"
}
TEST_fx-error() {
BT_ASSERT_FUNCTION_EXISTS fx-error
# Capture stderr.
local result
result=$( fx-error some error 2>&1 )
BT_EXPECT_STRING_CONTAINS_SUBSTRING "${result}" "some error"
}
TEST_fx-change-build-dir() {
BT_ASSERT_FUNCTION_EXISTS fx-change-build-dir
local -r BUILD_DIR="out/nondefault"
_create_build_dir "$BUILD_DIR"
fx-change-build-dir "${BUILD_DIR}"
local -r EXPECTED_FILE="${FUCHSIA_DIR}/.fx-build-dir"
BT_EXPECT_FILE_CONTAINS "${EXPECTED_FILE}" "${BUILD_DIR}"
}
TEST_fx-change-build-dir-links-artifacts() {
BT_ASSERT_FUNCTION_EXISTS fx-change-build-dir
local -r BUILD_DIR="out/nondefault"
_create_build_dir "$BUILD_DIR"
touch "${BT_TEMP_DIR}/${BUILD_DIR}/compile_commands.json"
touch "${BT_TEMP_DIR}/${BUILD_DIR}/rust-project.json"
fx-change-build-dir "${BUILD_DIR}"
local -r EXPECTED_FILE="${FUCHSIA_DIR}/.fx-build-dir"
BT_EXPECT_FILE_CONTAINS "${EXPECTED_FILE}" "${BUILD_DIR}"
# The build directory's compile_commands.json and rust-project.json should
# now be symlinked to the source root.
BT_EXPECT_FILE_EXISTS "${FUCHSIA_DIR}/compile_commands.json"
BT_EXPECT_FILE_EXISTS "${FUCHSIA_DIR}/rust-project.json"
}
TEST_fx-build-dir-if-present() {
BT_ASSERT_FUNCTION_EXISTS fx-build-dir-if-present
FUCHSIA_BUILD_DIR=""
local -r FX_BUILD_DIR_FILE_PATH="${FUCHSIA_DIR}/.fx-build-dir"
local -r BUILD_DIR_PATH="out/mybuild"
echo "${BUILD_DIR_PATH}" > "${FX_BUILD_DIR_FILE_PATH}"
BT_EXPECT fx-build-dir-if-present
# Expect an absolute path.
BT_EXPECT_EQ "${FUCHSIA_BUILD_DIR}" "${FUCHSIA_DIR}/${BUILD_DIR_PATH}"
}
TEST_fx-build-config-load() {
BT_ASSERT_FUNCTION_EXISTS fx-build-config-load
FUCHSIA_BUILD_DIR="out"
local -r EXPECT_BUILD_DIR="${FUCHSIA_DIR}/${FUCHSIA_BUILD_DIR}"
mkdir -p "${EXPECT_BUILD_DIR}"
local -r FX_CONFIG_FILE_PATH="${EXPECT_BUILD_DIR}/fx.config"
# Confirm testvar is not set before setting up the config file.
BT_EXPECT_EQ "${testvar}" ""
local -r TESTVAR_VALUE="my_value"
echo "testvar=${TESTVAR_VALUE}" > "${FX_CONFIG_FILE_PATH}"
BT_EXPECT fx-build-config-load
# fx-build-config-load ensures FUCHSIA_BUILD_DIR is an absolute path.
BT_EXPECT_EQ "${FUCHSIA_BUILD_DIR}" "${EXPECT_BUILD_DIR}"
# fx-build-config-load should have loaded testvar from fx.config.
BT_EXPECT_EQ "${testvar}" "${TESTVAR_VALUE}" \
"testvar has unexpected value (${testvar})"
}
TEST_fx-rbe-enabled-exists() {
BT_ASSERT_FUNCTION_EXISTS fx-rbe-enabled
}
TEST_fx-rbe-enabled-default-disabled() {
local -r BUILD_DIR="out/nondefault-2"
_create_build_dir "${BUILD_DIR}"
fx-change-build-dir "${BUILD_DIR}"
local -r RBE_SETTINGS_FILE="${BT_TEMP_DIR}/${BUILD_DIR}"/rbe_settings.json
# RBE is default disabled.
echo "" > "${RBE_SETTINGS_FILE}"
BT_EXPECT_FAIL fx-rbe-enabled
}
TEST_fx-rbe-enabled-disabled() {
local -r BUILD_DIR="out/nondefault-3"
_create_build_dir "${BUILD_DIR}"
fx-change-build-dir "${BUILD_DIR}"
local -r RBE_SETTINGS_FILE="${BT_TEMP_DIR}/${BUILD_DIR}"/rbe_settings.json
# RBE is disabled.
echo '{ "final": { "needs_reproxy": false }}' > "${RBE_SETTINGS_FILE}"
BT_EXPECT_FAIL fx-rbe-enabled
}
TEST_fx-rbe-enabled-enabled() {
local -r BUILD_DIR="out/nondefault-4"
_create_build_dir "${BUILD_DIR}"
fx-change-build-dir "${BUILD_DIR}"
local -r RBE_SETTINGS_FILE="${BT_TEMP_DIR}/${BUILD_DIR}"/rbe_settings.json
# RBE is disabled.
echo '{ "final": { "needs_reproxy": true }}' > "${RBE_SETTINGS_FILE}"
BT_EXPECT fx-rbe-enabled
}
# Test parsing valid and invalid device names passed to "fx -t"
TEST_fx-getdeviceraw-and-isvaliddevice() {
# Use subshells (parenthesis) in calls to get-device-raw to avoid premature exit
local valids=(
"127.0.0.1" "127.0.0.1:8022"
":8122"
"strut-wind-ahead-turf" "strut-wind-ahead-turf:8111"
"[::1]:22" "[fe80::7:8%eth0]:222" "[fe80::7:8%eth0]"
"[fe80::4607:bff:fe68:41c9%zircon1-4]"
# no brackets but also no port:
"::1" "::1:22" "fe80::7:8%eth0"
# serial and id:
"serial:EM-C0B2F2D96" "serial:12345" "serial:my-target_device.0"
"id:EM-C0B2F2D96" "id:12345" "id:my-target_device.0"
# valid uart targets:
"uart:/dev/ttyUSB0" "uart:/tmp/pontis/serial-0403-6001" "uart:user" "uart:1234"
)
for valid in "${valids[@]}"; do
BT_EXPECT is-valid-device "${valid}"
echo "${valid}" > "${ffx}.mock_stdout"
BT_EXPECT "(" get-device-raw ")" > /dev/null
done
local invalids=(
# no brackets but has a port
"fe80::7:8%eth0:222"
# invalid host names:
"AAbbb" "aa_bbb" "xyz@bla.com"
# more than 7 colons:
"[2001:db8:aaaa:bbbb:cccc:dddd:0:1:0]" "[2001:db8:aaaa:bbbb:cccc:dddd:0:1:44f%enx44070ba0044e]"
# invalid port numbers:
":122333" ":232a" ":-1"
# invalid serial and id:
"serial:" "id:" "serial:foo@bar" "id:foo#bar" "serial:foo/bar" "id:foo:bar"
# invalid uart targets:
"uart:" "uart: "
)
for invalid in "${invalids[@]}"; do
BT_EXPECT_FAIL is-valid-device "${invalid}"
echo "${invalid}" > "${ffx}.mock_stdout"
BT_EXPECT_FAIL "("get-device-raw ")" 2> /dev/null
done
}
# Test get-device-name with various device formats
TEST_fx-get-device-name() {
local targets=(
"strut-wind-ahead-turf:8111" "strut-wind-ahead-turf"
"127.0.0.1:8022" "127.0.0.1"
"[fe80::7:8%eth0]:222" "[fe80::7:8%eth0]"
"serial:EM-C0B2F2D96" "serial:EM-C0B2F2D96"
"serial:12345" "serial:12345"
"id:EM-C0B2F2D96" "id:EM-C0B2F2D96"
"id:12345" "id:12345"
"uart:/dev/ttyUSB0" "uart:/dev/ttyUSB0"
"uart:1234" "uart:1234"
)
for ((i=0; i<${#targets[@]}; i+=2)); do
local input="${targets[i]}"
local expected="${targets[i+1]}"
echo "${input}" > "${ffx}.mock_stdout"
BT_EXPECT_EQ "$(get-device-name)" "${expected}"
done
}
# Test extracting port from device name passed to "fx -t"
TEST_fx-get-device-ssh-port() {
FUCHSIA_NODENAME="127.0.0.1"
echo "${FUCHSIA_NODENAME}" > "${ffx}.mock_stdout"
BT_EXPECT_EQ "$(get-device-ssh-port)" ""
FUCHSIA_NODENAME="127.0.0.1:8811"
echo "${FUCHSIA_NODENAME}" > "${ffx}.mock_stdout"
BT_EXPECT_EQ "$(get-device-ssh-port)" "8811"
FUCHSIA_NODENAME=":8812"
echo "${FUCHSIA_NODENAME}" > "${ffx}.mock_stdout"
BT_EXPECT_EQ "$(get-device-ssh-port)" "8812"
FUCHSIA_NODENAME="[::1]"
echo "${FUCHSIA_NODENAME}" > "${ffx}.mock_stdout"
BT_EXPECT_EQ "$(get-device-ssh-port)" ""
FUCHSIA_NODENAME="[::1]:22"
echo "${FUCHSIA_NODENAME}" > "${ffx}.mock_stdout"
BT_EXPECT_EQ "$(get-device-ssh-port)" "22"
FUCHSIA_NODENAME="strut-wind-ahead-turf:822"
echo "${FUCHSIA_NODENAME}" > "${ffx}.mock_stdout"
BT_EXPECT_EQ "$(get-device-ssh-port)" "822"
FUCHSIA_NODENAME="[2001:db8:aaaa:bbbb:cccc:dddd:0:44f%enx44070ba0044e]"
echo "${FUCHSIA_NODENAME}" > "${ffx}.mock_stdout"
BT_EXPECT_EQ "$(get-device-ssh-port)" ""
# seven colons inside the brackets plus the one prefixing the port, so 8 total
FUCHSIA_NODENAME="[2001:db8:aaaa:bbbb:cccc:dddd:0:44f%enx44070ba0044e]:22"
echo "${FUCHSIA_NODENAME}" > "${ffx}.mock_stdout"
BT_EXPECT_EQ "$(get-device-ssh-port)" "22"
}
TEST_fx-get-device-addr-resource() {
FUCHSIA_NODENAME="127.0.0.1"
echo "${FUCHSIA_NODENAME}" > "${ffx}.mock_stdout"
BT_EXPECT_EQ "$(get-device-addr-resource)" "127.0.0.1"
FUCHSIA_NODENAME="127.0.0.1:8811"
echo "${FUCHSIA_NODENAME}" > "${ffx}.mock_stdout"
BT_EXPECT_EQ "$(get-device-addr-resource)" "127.0.0.1"
FUCHSIA_NODENAME="[::1]"
echo "${FUCHSIA_NODENAME}" > "${ffx}.mock_stdout"
BT_EXPECT_EQ "$(get-device-addr-resource)" "[::1]"
FUCHSIA_NODENAME="[::1]:22"
echo "${FUCHSIA_NODENAME}" > "${ffx}.mock_stdout"
BT_EXPECT_EQ "$(get-device-addr-resource)" "[::1]"
FUCHSIA_NODENAME="[2001:db8:aaaa:bbbb:cccc:dddd:0:44f%enx44070ba0044e]"
echo "${FUCHSIA_NODENAME}" > "${ffx}.mock_stdout"
BT_EXPECT_EQ "$(get-device-addr-resource)" "[2001:db8:aaaa:bbbb:cccc:dddd:0:44f%enx44070ba0044e]"
}
TEST_fx-get-device-addr-url() {
FUCHSIA_NODENAME="127.0.0.1"
echo "${FUCHSIA_NODENAME}" > "${ffx}.mock_stdout"
BT_EXPECT_EQ "$(get-device-addr-url)" "127.0.0.1"
FUCHSIA_NODENAME="127.0.0.1:8811"
echo "${FUCHSIA_NODENAME}" > "${ffx}.mock_stdout"
BT_EXPECT_EQ "$(get-device-addr-url)" "127.0.0.1"
FUCHSIA_NODENAME="[::1]"
echo "${FUCHSIA_NODENAME}" > "${ffx}.mock_stdout"
BT_EXPECT_EQ "$(get-device-addr-url)" "[::1]"
FUCHSIA_NODENAME="[::1]:22"
echo "${FUCHSIA_NODENAME}" > "${ffx}.mock_stdout"
BT_EXPECT_EQ "$(get-device-addr-url)" "[::1]"
FUCHSIA_NODENAME="[2001:db8:aaaa:bbbb:cccc:dddd:0:44f%enx44070ba0044e]"
echo "${FUCHSIA_NODENAME}" > "${ffx}.mock_stdout"
BT_EXPECT_EQ "$(get-device-addr-url)" "[2001:db8:aaaa:bbbb:cccc:dddd:0:44f%25enx44070ba0044e]"
}
# `ffx target default get` gives stderr when no default target is set.
# This stderr should be suppressed.
TEST_fx-unset-device-stderr() {
cat >"${ffx}.mock_side_effects" <<INPUT
case "\$@" in
*"target list --format a"*)
echo '[fe80::dd57:127d:366d:28bb%5]:22'
echo '127.0.0.1:34715'
;;
*)
echo "No default target set." >&2
exit 1
;;
esac
INPUT
BT_EXPECT_EQ "$(get-device-raw 2>&1)" ""
BT_EXPECT_EQ "$(get-device-name 2>&1)" ""
BT_EXPECT_EQ "$(get-device-ssh-port 2>&1)" ""
}
TEST_fx-export-device-address() {
unset FUCHSIA_NODENAME
unset FX_DEVICE_NAME
unset FX_DEVICE_ADDR
unset FX_SSH_ADDR
unset FX_SSH_PORT
export FUCHSIA_NODENAME="[::2%lo0]:1234"
echo "${FUCHSIA_NODENAME}" > "${ffx}.mock_stdout"
fx-export-device-address
BT_EXPECT_EQ "${FX_DEVICE_NAME}" "[::2%lo0]"
BT_EXPECT_EQ "${FX_DEVICE_ADDR}" "::2%lo0"
BT_EXPECT_EQ "${FX_SSH_ADDR}" "[::2%lo0]"
BT_EXPECT_EQ "${FX_SSH_PORT}" "1234"
unset -f fx-target-finder-resolve
fx-target-finder-resolve() {
echo "::3%lo0:1234"
}
export FUCHSIA_NODENAME="foo-bar-baz-quux:1234"
echo "${FUCHSIA_NODENAME}" > "${ffx}.mock_stdout"
fx-export-device-address
BT_EXPECT_EQ "${FX_DEVICE_NAME}" "foo-bar-baz-quux"
BT_EXPECT_EQ "${FX_DEVICE_ADDR}" "::3%lo0"
BT_EXPECT_EQ "${FX_SSH_ADDR}" "[::3%lo0]"
BT_EXPECT_EQ "${FX_SSH_PORT}" "1234"
}
# Ensure that fx-zbi uses FUCHSIA_ZBI_COMPRESSION
TEST_fx-zbi() {
export FUCHSIA_ZBI_COMPRESSION="zstd.max"
export FUCHSIA_BUILD_DIR="${BT_TEMP_DIR}/out/default"
local zbi="${FUCHSIA_BUILD_DIR}/host/zbi"
btf::make_mock "${zbi}"
btf::make_mock "${BT_TEMP_DIR}/tools/devshell/list-build-artifacts"
cat > "${BT_TEMP_DIR}/tools/devshell/list-build-artifacts.mock_side_effects" << "EOF"
if [[ "$@" == "--name zbi --expect-one tools" ]] ; then
echo "host/zbi"
fi
EOF
BT_EXPECT fx-zbi
source "${zbi}.mock_state"
BT_EXPECT_EQ "${BT_MOCK_ARGS[1]}" "--compressed=${FUCHSIA_ZBI_COMPRESSION}" \
"Expected a --compressed=${FUCHSIA_ZBI_COMPRESSION} argument to zbi binary, got '${BT_MOCK_ARGS[@]:1}'"
}
# Ensure that fx-zbi-default-compression doesn't use FUCHSIA_ZBI_COMPRESSION.
TEST_fx-zbi-default-compression() {
export FUCHSIA_ZBI_COMPRESSION="zstd.max"
export FUCHSIA_BUILD_DIR="${BT_TEMP_DIR}/out/default"
local zbi="${FUCHSIA_BUILD_DIR}/host/zbi"
btf::make_mock "${zbi}"
btf::make_mock "${BT_TEMP_DIR}/tools/devshell/list-build-artifacts"
cat > "${BT_TEMP_DIR}/tools/devshell/list-build-artifacts.mock_side_effects" << "EOF"
if [[ "$@" == "--name zbi --expect-one tools" ]] ; then
echo "host/zbi"
fi
EOF
BT_EXPECT fx-zbi-default-compression
source "${zbi}.mock_state"
BT_EXPECT_EQ "${#BT_MOCK_ARGS[@]}" "1" \
"Expected no args to zbi binary, got '${BT_MOCK_ARGS[@]:1}'"
}
TEST_fx-is-bringup() {
export FUCHSIA_BUILD_DIR="${BT_TEMP_DIR}"
echo 'import("//products/bringup.gni")' > "${BT_TEMP_DIR}/args.gn"
BT_EXPECT fx-is-bringup
echo ' import("//products/bringup.gni")' > "${BT_TEMP_DIR}/args.gn"
BT_EXPECT fx-is-bringup
echo 'import("foo") import("//products/bringup.gni")' > "${BT_TEMP_DIR}/args.gn"
BT_EXPECT fx-is-bringup
echo 'import("//products/core.gni")' > "${BT_TEMP_DIR}/args.gn"
BT_EXPECT_FAIL fx-is-bringup
echo '#import("//products/bringup.gni")' > "${BT_TEMP_DIR}/args.gn"
BT_EXPECT_FAIL fx-is-bringup
echo 'import("//products/core.gni") #import("//products/bringup.gni")' > "${BT_TEMP_DIR}/args.gn"
BT_EXPECT_FAIL fx-is-bringup
}
# Ensure that fx-command-run can find and execute a command defined in a
# metadata (*.fx) file.
TEST_fx-command-run() {
local mycmd="${BT_TEMP_DIR}/prebuilt/third_party/mycmdexec"
btf::make_mock "${mycmd}"
local mymetadata="${BT_TEMP_DIR}/tools/devshell/mycmd.fx"
echo "#### EXECUTABLE=\${PREBUILT_3P_DIR}/mycmdexec" > "${mymetadata}"
BT_EXPECT fx-command-run mycmd myarg1
source "${mycmd}.mock_state"
BT_EXPECT_EQ "${BT_MOCK_ARGS[1]}" "myarg1" \
"Expected a single argument 'myarg1' to mycmd, got '${BT_MOCK_ARGS[@]:1}'"
}
# Ensure that FX_CALLER is set as expected
TEST_fx-caller() {
local called_cmd="${BT_TEMP_DIR}/tools/devshell/called_cmd"
btf::make_mock "${called_cmd}"
{
echo "#!/bin/bash"
echo 'echo $FX_CALLER'
} > "${called_cmd}.mock_side_effects"
BT_EXPECT_EQ "$($called_cmd)" ""
local caller_run_cmd="${BT_TEMP_DIR}/tools/devshell/caller_run_cmd"
btf::make_mock "${caller_run_cmd}"
{
echo "#!/bin/bash"
echo "source ${BT_TEMP_DIR}/tools/devshell/lib/vars.sh || exit \$?"
echo "fx-command-run called_cmd"
} > "${caller_run_cmd}.mock_side_effects"
BT_EXPECT_EQ "$($caller_run_cmd)" "$caller_run_cmd"
local caller_exec_cmd="${BT_TEMP_DIR}/tools/devshell/caller_exec_cmd"
btf::make_mock "${caller_exec_cmd}"
{
echo "#!/bin/bash"
echo "source ${BT_TEMP_DIR}/tools/devshell/lib/vars.sh || exit \$?"
echo "fx-command-exec called_cmd"
} > "${caller_exec_cmd}.mock_side_effects"
BT_EXPECT_EQ "$($caller_exec_cmd)" "$caller_exec_cmd"
}
TEST_get-ssh-components() {
cat >"${ffx}.mock_side_effects" <<INPUT
if [[ "\$7" == "ssh.pub" ]]; then
echo "${BT_TEMP_DIR}/.ssh/fuchsia_authorized_keys"
elif [[ "\$7" == "ssh.priv" ]]; then
echo "${BT_TEMP_DIR}/.ssh/fuchsia_private"
fi
INPUT
local privkey="${BT_TEMP_DIR}/.ssh/fuchsia_private"
local authkey="${BT_TEMP_DIR}/.ssh/fuchsia_authorized_keys"
BT_EXPECT_EQ "$(get-ssh-privkey 2>/dev/null)" "${privkey}"
BT_EXPECT_EQ "$(get-ssh-authkeys 2>/dev/null)" "${authkey}"
}
TEST_get-ssh-components-unbuilt-ffx() {
local ffx_backup="${ffx}.bak"
mv "${ffx}" "${ffx_backup}"
# Test with FUCHSIA_SSH_KEY and FUCHSIA_AUTHORIZED_KEYS pointing to existing files
local custom_priv="${BT_TEMP_DIR}/custom_priv"
local custom_auth="${BT_TEMP_DIR}/custom_auth"
touch "${custom_priv}" "${custom_auth}"
(
export FUCHSIA_SSH_KEY="${custom_priv}"
export FUCHSIA_AUTHORIZED_KEYS="${custom_auth}"
BT_EXPECT_EQ "$(get-ssh-privkey)" "${custom_priv}"
BT_EXPECT_EQ "$(get-ssh-authkeys)" "${custom_auth}"
)
# Test with default HOME/.ssh keys
local fake_home="${BT_TEMP_DIR}/fake_home"
mkdir -p "${fake_home}/.ssh"
local default_priv="${fake_home}/.ssh/fuchsia_ed25519"
local default_auth="${fake_home}/.ssh/fuchsia_authorized_keys"
touch "${default_priv}" "${default_auth}"
(
export HOME="${fake_home}"
unset FUCHSIA_SSH_KEY
unset FUCHSIA_AUTHORIZED_KEYS
BT_EXPECT_EQ "$(get-ssh-privkey)" "${default_priv}"
BT_EXPECT_EQ "$(get-ssh-authkeys)" "${default_auth}"
)
mv "${ffx_backup}" "${ffx}"
}
TEST_check-ssh-config-unbuilt-ffx() {
local ffx_backup="${ffx}.bak"
mv "${ffx}" "${ffx_backup}"
local fake_home="${BT_TEMP_DIR}/fake_home_config"
mkdir -p "${fake_home}/.ssh"
local default_priv="${fake_home}/.ssh/fuchsia_ed25519"
touch "${default_priv}"
(
export HOME="${fake_home}"
unset FUCHSIA_SSH_KEY
unset FUCHSIA_AUTHORIZED_KEYS
check-ssh-config
local conffile="${FUCHSIA_BUILD_DIR}/ssh-keys/ssh_config"
BT_EXPECT_FILE_EXISTS "${conffile}"
BT_EXPECT_FILE_CONTAINS_SUBSTRING "${conffile}" "IdentityFile ${default_priv}"
BT_EXPECT_FILE_CONTAINS_SUBSTRING "${conffile}" "IdentitiesOnly no"
)
mv "${ffx_backup}" "${ffx}"
}
TEST_json_config() {
local json_test_file="${BT_TEMP_DIR}/config.json"
# expect the file doesn't already exist
BT_EXPECT_FILE_DOES_NOT_EXIST "${json_test_file}"
# Fail if there's no file there
BT_EXPECT_FAIL json-config-del "${json_test_file}" "something"
json-config-set "${json_test_file}" "test.value" "something"
BT_EXPECT_FILE_CONTAINS "${json_test_file}" '{"test":{"value":"something"}}'
json-config-set "${json_test_file}" "test.something" "else"
BT_EXPECT_FILE_CONTAINS "${json_test_file}" '{"test":{"something":"else","value":"something"}}'
json-config-del "${json_test_file}" "test.value"
BT_EXPECT_FILE_CONTAINS "${json_test_file}" '{"test":{"something":"else"}}'
BT_EXPECT_FAIL json-config-del "${json_test_file}" "not.existing"
BT_EXPECT_FILE_CONTAINS "${json_test_file}" '{"test":{"something":"else"}}'
}
TEST_device_addr() {
local addrs=(
# default-target address-with-port address-without-port
"foo 1.2.3.4" "1.2.3.4"
"foo 1.2.3.4:5678" "1.2.3.4"
"foo fe80::4607:bff:fe68:41c9%zircon1-4" "fe80::4607:bff:fe68:41c9%zircon1-4"
"foo [fe80::4607:bff:fe68:41c9%zircon1-4]:1234" "fe80::4607:bff:fe68:41c9%zircon1-4"
"1.2.3.4" "1.2.3.4" "1.2.3.4"
"1.2.3.4:5678" "1.2.3.4:5678" "1.2.3.4"
"fe80::4607:bff:fe68:41c9%zircon1-4" "fe80::4607:bff:fe68:41c9%zircon1-4" "fe80::4607:bff:fe68:41c9%zircon1-4"
"[fe80::4607:bff:fe68:41c9%zircon1-4]:1234" "[fe80::4607:bff:fe68:41c9%zircon1-4]:1234" "fe80::4607:bff:fe68:41c9%zircon1-4"
)
echo "${addrs[@]}" | xargs -n 3 |while read default_target addr_port addr; do
cat >"${ffx}.mock_side_effects" <<INPUT
echo "\$@" >> /tmp/xxx
case "\$@" in
*"target default get")
echo $default_target
;;
*"target list --format a"*)
echo $addr_port
;;
*)
exit 1
;;
esac
INPUT
BT_ASSERT_EQ "$(get-fuchsia-device-addr)" $addr
done
}
TEST_ffx-default-repository-name() {
FUCHSIA_BUILD_DIR="${FUCHSIA_DIR}/out/default"
BT_EXPECT_EQ "$(ffx-default-repository-name)" "default"
FUCHSIA_BUILD_DIR="${FUCHSIA_DIR}/out/core.x64"
BT_EXPECT_EQ "$(ffx-default-repository-name)" "core-x64"
FUCHSIA_BUILD_DIR="${FUCHSIA_DIR}/out/fuchsia_internal.arm64-balanced.2"
BT_EXPECT_EQ "$(ffx-default-repository-name)" "fuchsia-internal-arm64-balanced-2"
FUCHSIA_BUILD_DIR="${FUCHSIA_DIR}/out/Custom_Build.ARM64.1"
BT_EXPECT_EQ "$(ffx-default-repository-name)" "custom-build-arm64-1"
}
_run_fx-wait-ignoring-signals_test_case() {
local -r expected_child_exit_code="$1"
local -r test_name_suffix="$2"
BT_ASSERT_FUNCTION_EXISTS fx-wait-ignoring-signals
local -r suffix="${expected_child_exit_code}_${test_name_suffix}"
local -r temp_file="${BT_TEMP_DIR}/signal_received_${suffix}"
local -r child_script="${BT_TEMP_DIR}/child_${suffix}.sh"
local -r child_pid_file="${BT_TEMP_DIR}/child_${suffix}.pid"
local -r child_ready_file="${BT_TEMP_DIR}/child_${suffix}.ready"
local -r handler_stderr="${BT_TEMP_DIR}/handler_stderr_${suffix}"
cat > "${child_script}" <<EOF
#!/bin/bash
child_pid_file="\$1"
temp_file="\$2"
child_ready_file="\$3"
echo \$\$ > "\${child_pid_file}"
cleanup() {
if [[ -n "\$sleep_pid" ]]; then
kill "\$sleep_pid" 2>/dev/null || true
fi
echo 'child_terminated' > "\${temp_file}"
exit ${expected_child_exit_code}
}
trap cleanup TERM
# Signal that we are ready (trap is set) before sleeping
echo "ready" > "\${child_ready_file}"
sleep 30 >/dev/null 2>&1 &
sleep_pid=\$!
wait \$sleep_pid
EOF
chmod +x "${child_script}"
# Run in background
fx-wait-ignoring-signals test_caller "${child_script}" "${child_pid_file}" "${temp_file}" "${child_ready_file}" 2>"${handler_stderr}" &
local -r parent_pid=$!
# Wait for child to write its PID
local child_pid=""
for i in {1..20}; do
if [[ -f "${child_pid_file}" ]]; then
child_pid=$(cat "${child_pid_file}")
break
fi
sleep 0.1
done
if [[ -z "${child_pid}" ]]; then
BT_FAIL "Could not find child PID"
kill "${parent_pid}" 2>/dev/null || true
return
fi
# Wait for child to be ready (trap set)
local child_ready=false
for i in {1..20}; do
if [[ -f "${child_ready_file}" ]]; then
child_ready=true
break
fi
sleep 0.1
done
if ! $child_ready; then
BT_FAIL "Child did not signal ready (trap not set)"
kill "${parent_pid}" 2>/dev/null || true
return
fi
# Send SIGTERM to parent
kill -TERM "${parent_pid}"
# Wait for parent to exit
wait "${parent_pid}"
local -r exit_status=$?
BT_EXPECT_EQ "${exit_status}" "${expected_child_exit_code}"
BT_EXPECT_FILE_CONTAINS "${temp_file}" "child_terminated"
BT_EXPECT_FILE_CONTAINS "${handler_stderr}" "[test_caller] Received SIGTERM. Waiting for command to shut down gracefully..."
}
TEST_fx-wait-ignoring-signals_exit_143() {
_run_fx-wait-ignoring-signals_test_case 143 "exit_143"
}
TEST_fx-wait-ignoring-signals_exit_0() {
_run_fx-wait-ignoring-signals_test_case 0 "exit_0"
}
TEST_fx-wait-ignoring-signals_exit_1() {
_run_fx-wait-ignoring-signals_test_case 1 "exit_1"
}
TEST_fx-wait-ignoring-signals_normal_exit_0() {
BT_ASSERT_FUNCTION_EXISTS fx-wait-ignoring-signals
local -r handler_stderr="${BT_TEMP_DIR}/handler_stderr_normal_0"
fx-wait-ignoring-signals test_caller true 2>"${handler_stderr}"
local -r exit_status=$?
BT_EXPECT_EQ "${exit_status}" 0
BT_EXPECT [[ ! -s "${handler_stderr}" ]]
}
TEST_fx-wait-ignoring-signals_normal_exit_non_zero() {
BT_ASSERT_FUNCTION_EXISTS fx-wait-ignoring-signals
local -r handler_stderr="${BT_TEMP_DIR}/handler_stderr_normal_42"
fx-wait-ignoring-signals test_caller bash -c "exit 42" 2>"${handler_stderr}"
local -r exit_status=$?
BT_EXPECT_EQ "${exit_status}" 42
BT_EXPECT [[ ! -s "${handler_stderr}" ]]
}
TEST_fx-wait-ignoring-signals_trap_restoration() {
BT_ASSERT_FUNCTION_EXISTS fx-wait-ignoring-signals
local initial_term initial_hup
initial_term=$(trap -p TERM)
initial_hup=$(trap -p HUP)
# Set a custom trap for INT
trap 'echo "original_int"' INT
fx-wait-ignoring-signals test_caller true >/dev/null 2>&1
# Check that INT is restored and others match their initial states
local current_int current_term current_hup
current_int=$(trap -p INT)
current_term=$(trap -p TERM)
current_hup=$(trap -p HUP)
BT_EXPECT_STRING_CONTAINS_SUBSTRING "${current_int}" "original_int"
BT_EXPECT_EQ "${current_term}" "${initial_term}"
BT_EXPECT_EQ "${current_hup}" "${initial_hup}"
# Restore default INT trap for the test environment
trap - INT
}
BT_RUN_TESTS "$@"