blob: a93f0640b7e7004757a7b2a5d0a0d25b66949b90 [file] [log] [blame]
#!/bin/bash
# Copyright 2020 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.
#
# Common helpers specific for Fuchsia in-tree testing.
btf::setup_fx() {
if [[ -z "${BT_TEMP_DIR}" ]]; then
echo "Cannot proceed, BT_TEMP_DIR is unset" 1>&2
exit 1
fi
local with_metrics=0
if [[ $# -gt 0 && "$1" == "1" ]]; then
with_metrics=1
fi
local _HOST_OUT_DIR="host_x64"
local _REL_BUILD_DIR="out/default"
local _FUCHSIA_DIR="${BT_TEMP_DIR}"
local _FUCHSIA_BUILD_DIR="${_FUCHSIA_DIR}/${_REL_BUILD_DIR}"
# Fake fuchsia dir configuration.
local _FX="${_FUCHSIA_DIR}/scripts/fx"
BT_ASSERT_FILE_EXISTS "${_FX}"
BT_ASSERT_FILE_EXISTS "${_FUCHSIA_DIR}/tools/devshell/lib/vars.sh"
BT_ASSERT_FILE_EXISTS "${_FUCHSIA_DIR}/tools/devshell/lib/platform.sh"
BT_ASSERT_FILE_EXISTS "${_FUCHSIA_DIR}/tools/devshell/lib/fx-optional-features.sh"
# Fake a build directory with the minimal content so that fx work
mkdir -p "${_FUCHSIA_BUILD_DIR}" "${_FUCHSIA_BUILD_DIR}/${_HOST_OUT_DIR}" \
"${_FUCHSIA_DIR}/.jiri_root/bin" "${_FUCHSIA_DIR}/.ssh"
ln -s "${_FX}" "${_FUCHSIA_DIR}/.jiri_root/bin/fx"
echo "${_REL_BUILD_DIR}" > "${_FUCHSIA_DIR}/.fx-build-dir"
touch "${_FUCHSIA_BUILD_DIR}/args.gn"
touch "${_FUCHSIA_DIR}/.ssh/fuchsia_ed25519" "${_FUCHSIA_DIR}/.ssh/fuchsia_authorized_keys"
echo -e "${_FUCHSIA_DIR}/.ssh/fuchsia_ed25519\n${_FUCHSIA_DIR}/.ssh/fuchsia_authorized_keys" > "${_FUCHSIA_DIR}/.fx-ssh-path"
cat > "${_FUCHSIA_BUILD_DIR}/fx.config" << EOF
# Generated by fuchsia-mock.sh.
FUCHSIA_BUILD_DIR='${_REL_BUILD_DIR}'
FUCHSIA_ARCH='x64'
FUCHSIA_BOARD_NAME=pc
FUCHSIA_ZBI_COMPRESSION=zstd
HOST_OUT_DIR='${_HOST_OUT_DIR}'
EOF
if (( with_metrics )); then
BT_ASSERT_FILE_EXISTS "${_FUCHSIA_DIR}/tools/devshell/lib/metrics.sh"
else
btf::make_mock "${_FUCHSIA_DIR}/tools/devshell/lib/metrics.sh"
cat > "${_FUCHSIA_DIR}/tools/devshell/lib/metrics.sh.mock_side_effects" <<EOF
function track-command-execution {
:
}
function track-command-finished {
:
}
EOF
fi
# If the host-tool command is not mocked, some code in vars.sh will
# not work well. If a custom mock of 'fx host-tool' is needed, mock it
# before calling 'setup_fx'
btf::_make_fx_host_tool_mock
echo "${_FX}"
}
btf::setup_fx_with_metrics() {
btf::setup_fx 1
}
btf::_make_buildtool_mock() {
local rel_path="$1"
local path="${BT_TEMP_DIR}/${rel_path}"
btf::make_mock "${path}"
echo "${path}" >> "${BT_TEMP_DIR}/.mocked_tools"
echo "${path}"
}
btf::make_installed_hosttools_mock() {
local hosttool_name="$1"
btf::_make_buildtool_mock "out/default/host-tools/${hosttool_name}"
}
btf::make_hosttools_mock() {
local hosttool_name="$1"
btf::_make_buildtool_mock "out/default/host_x64/${hosttool_name}"
}
btf::make_mock_binary() {
local -r _BIN_PATH="$(mktemp -d "${BT_TEMP_DIR}/binpath.XXXXXX")"
local tool_name="$1"
local tool_path="${_BIN_PATH}/${tool_name}"
btf::make_mock "${tool_path}"
echo "${tool_path}"
}
btf::add_binary_to_path() {
local tool_path="$(dirname "$1")"
export PATH="${tool_path}:$PATH"
}
btf::_make_fx_host_tool_mock() {
local tool="${BT_TEMP_DIR}/tools/devshell/host-tool"
if [[ -f "${tool}" ]]; then
return 0
fi
btf::make_mock "${tool}"
cat > "${tool}.mock_side_effects" <<EOF
# remove host-tool args (like --check-firewall)
print=false
while [[ \$# -gt 0 && \$1 =~ ^- ]]; do
if [[ \$1 == "--print" ]]; then
print=true
fi
shift
done
if [[ \$# == 0 ]]; then
echo >&2 "Invalid state, cannot find host tool name"
return 1
fi
tool="\$1"
p="\$(grep "/\${tool}$" "${BT_TEMP_DIR}/.mocked_tools")"
if [[ -z "\$p" ]]; then
echo >&2 "Invalid state, cannot find path for \$tool." \
"Use a btf::make_*_mock() method from fuchsia-mock.sh to mock it."
return 1
fi
if [[ ! -x "\$p" ]]; then
echo >&2 "Invalid state, \$p is not executable."
return 1
fi
if \$print; then
echo "\$p"
else
"\$p" "\$@"
fi
EOF
}
# Verifies that the arguments in BT_MOCK_ARGS match the arguments to this function.
# The number and order of arguments must match, or non-zero is returned.
# If a value of an argument is un-important it can be marked with the string
# _ANY_. This allows for matching arguments that may have unique values, such as temp
# filenames.
# Args: toolname|mock_state_file arg [arg] [arg] ...
# Returns: 0 if found; 1 if not found.
btf::expect-mock-args() {
local tool="$1"
if [[ ! "${tool}" =~ \.mock_state(\.[0-9]+)?$ ]]; then
tool="${tool}.mock_state"
fi
BT_ASSERT_FILE_EXISTS "${tool}"
shift
source "${tool}"
local expected=("$@")
local actual=("${BT_MOCK_ARGS[@]:1}") # ignore the first arg, the mocked command
if [[ ${#actual[@]} -ne ${#expected[@]} ]]; then
btf::_fail 1 "Unexpected number of arguments to ${tool}.\n Expected ${#expected[@]}: ${expected[*]}\n Actual ${#actual[@]}: ${actual[*]}"
return
fi
for (( i=0; i<"${#expected[@]}"; i++ )); do
if [[ "${expected[$i]}" != "_ANY_" ]]; then
if [[ "${actual[$i]}" != "${expected[$i]}" ]]; then
btf::_fail 1 "Unexpected arguments to ${tool}.\n Expected: ${expected[*]}\n Actual: ${actual[*]}"
return
fi
fi
done
return 0
}
btf::does-mock-args-contain() {
local state_file="$1"
BT_ASSERT_FILE_EXISTS "${state_file}"
shift
source "${state_file}"
local expected=("$@")
local actual=("${BT_MOCK_ARGS[@]}")
local al=${#actual[@]}
local el=${#expected[@]}
if [[ $el -gt $al ]]; then
return 1
fi
for (( a=1; a<"$(( al - el + 1 ))"; a++ )); do
for (( e=0; e<"${el}"; e++ )); do
local shifted="$((a + e))"
if [[ "${expected[$e]}" != "_ANY_" && "${actual[$shifted]}" != "${expected[$e]}" ]]; then
continue 2 # continue the outer loop
fi
done
# if we got here, we went through all the expected arguments, so success
return 0
done
return 1
}
btf::does-mock-args-not-contain() {
local state_file="$1"
BT_ASSERT_FILE_EXISTS "${state_file}"
shift
source "${state_file}"
local expected=("$@")
local actual=("${BT_MOCK_ARGS[@]}")
local al=${#actual[@]}
local el=${#expected[@]}
if [[ $el -gt $al ]]; then
return 0
fi
for (( a=1; a<"$(( al - el + 1 ))"; a++ )); do
for (( e=0; e<"${el}"; e++ )); do
local shifted="$((a + e))"
if [[ "${expected[$e]}" != "_ANY_" && "${actual[$shifted]}" != "${expected[$e]}" ]]; then
continue 2 # continue the outer loop
fi
done
# if we got here, we went through all the expected arguments, so we found it
return 1
done
}