blob: 6710cc6f736308bf5d2628905188e6b0780754a8 [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.
#
# Tests that femu is able to correctly interact with the fx emu command and
# its dependencies like fvm and aemu. These tests do not actually start up
# the emulator, but check the arguments are as expected.
set -e
# Specify a simulated CIPD instance id for prebuilts
AEMU_VERSION="git_revision:unknown"
AEMU_LABEL="$(echo "${AEMU_VERSION}" | tr ':/' '_')"
GRPCWEBPROXY_VERSION="git_revision:unknown"
GRPCWEBPROXY_LABEL="$(echo "${GRPCWEBPROXY_VERSION}" | tr ':/' '_')"
function run_femu_wrapper() {
# femu.sh will run "fvm decompress" to convert the given fvm image format into
# an intermediate raw image suffixed by ".decompress". The image is then used for
# extension. Since the fvm tool is faked and does nothing in the test, we need
# to fake the intermediate decompressed image.
cp "${FUCHSIA_WORK_DIR}/image/storage-full.blk" \
"${FUCHSIA_WORK_DIR}/image/storage-full.blk.decompressed"
gn-test-run-bash-script "${BT_TEMP_DIR}/scripts/sdk/gn/base/bin/femu.sh" "$@"
}
# Verifies that the correct emulator command is run by femu, do not activate the network interface
TEST_femu_standalone() {
PATH_DIR_FOR_TEST="${BT_TEMP_DIR}/_isolated_path_for"
export PATH="${PATH_DIR_FOR_TEST}:${PATH}"
# Create fake ZIP file download so femu.sh doesn't try to download it, and
# later on provide a mocked emulator script so it doesn't try to unzip it.
touch "${FUCHSIA_WORK_DIR}/emulator/aemu-${PLATFORM}-${AEMU_LABEL}.zip"
# Need to configure a DISPLAY so that we can get past the graphics error checks
export DISPLAY="fakedisplay"
# Run command.
BT_EXPECT run_femu_wrapper
# Verify that the image first goes through a decompress process by fvm
source "${MOCKED_FVM}.mock_state.1"
gn-test-check-mock-args _ANY_ _ANY_ decompress --default _ANY_
# Verify that the image will be extended to double the size
source "${MOCKED_FVM}.mock_state.2"
gn-test-check-mock-args _ANY_ _ANY_ extend --length 2048 --length-is-lowerbound
# Check that fpave.sh was called to download the needed system images
# shellcheck disable=SC1090
source "${BT_TEMP_DIR}/scripts/sdk/gn/base/bin/fpave.sh.mock_state"
gn-test-check-mock-args _ANY_ --prepare --image qemu-x64 --bucket fuchsia --work-dir "${FUCHSIA_WORK_DIR}"
# Check that fserve.sh was called to download the needed system images
# shellcheck disable=SC1090
source "${BT_TEMP_DIR}/scripts/sdk/gn/base/bin/fserve.sh.mock_state"
gn-test-check-mock-args _ANY_ --prepare --image qemu-x64 --bucket fuchsia --work-dir "${FUCHSIA_WORK_DIR}"
# Verify that zbi was called to add the authorized_keys
# shellcheck disable=SC1090
source "${MOCKED_ZBI}.mock_state"
gn-test-check-mock-args _ANY_ -o _ANY_ "${FUCHSIA_WORK_DIR}/image/zircon-a.zbi" --entry "data/ssh/authorized_keys=${HOME}/.ssh/fuchsia_authorized_keys"
# Verify some of the arguments passed to the emulator binary
# shellcheck disable=SC1090
source "${FUCHSIA_WORK_DIR}/emulator/aemu-${PLATFORM}-${AEMU_LABEL}/emulator.mock_state"
gn-test-check-mock-partial -fuchsia
}
TEST_femu_fallback_to_fvm_fastboot_if_raw_image_not_exist() {
PATH_DIR_FOR_TEST="${BT_TEMP_DIR}/_isolated_path_for"
export PATH="${PATH_DIR_FOR_TEST}:${PATH}"
# Create fake ZIP file download so femu.sh doesn't try to download it, and
# later on provide a mocked emulator script so it doesn't try to unzip it.
touch "${FUCHSIA_WORK_DIR}/emulator/aemu-${PLATFORM}-${AEMU_LABEL}.zip"
# Need to configure a DISPLAY so that we can get past the graphics error checks
export DISPLAY="fakedisplay"
# Renamed the fvm image
src="${FUCHSIA_WORK_DIR}/image/storage-full.blk"
dst="${FUCHSIA_WORK_DIR}/image/storage-fastboot.blk"
mv "${src}" "${dst}"
cp "${dst}" "${dst}.decompressed"
export IMAGE_FVM_FASTBOOT="storage-fastboot.blk"
# Run command.
BT_EXPECT gn-test-run-bash-script "${BT_TEMP_DIR}/scripts/sdk/gn/base/bin/femu.sh"
# Verify that the image first goes through a decompress process by fvm
source "${MOCKED_FVM}.mock_state.1"
gn-test-check-mock-args _ANY_ _ANY_ decompress --default "${dst}"
# Verify that the image will be extended to double the size
source "${MOCKED_FVM}.mock_state.2"
gn-test-check-mock-args _ANY_ _ANY_ extend --length 2048 --length-is-lowerbound
}
# Verifies that the --experiment-arm64 option selects arm64 support
TEST_femu_arm64() {
PATH_DIR_FOR_TEST="${BT_TEMP_DIR}/_isolated_path_for"
export PATH="${PATH_DIR_FOR_TEST}:${PATH}"
# Create fake ZIP file download so femu.sh doesn't try to download it, and
# later on provide a mocked emulator script so it doesn't try to unzip it.
touch "${FUCHSIA_WORK_DIR}/emulator/aemu-${PLATFORM}-${AEMU_LABEL}.zip"
# Need to configure a DISPLAY so that we can get past the graphics error checks
export DISPLAY="fakedisplay"
# Run command.
BT_EXPECT run_femu_wrapper \
--experiment-arm64 \
--image qemu-arm64 \
--software-gpu
# Check that fpave.sh was called to download the needed system images
# shellcheck disable=SC1090
source "${BT_TEMP_DIR}/scripts/sdk/gn/base/bin/fpave.sh.mock_state"
gn-test-check-mock-args _ANY_ --prepare --image qemu-arm64 --bucket fuchsia --work-dir "${FUCHSIA_WORK_DIR}"
# Check that fserve.sh was called to download the needed system images
# shellcheck disable=SC1090
source "${BT_TEMP_DIR}/scripts/sdk/gn/base/bin/fserve.sh.mock_state"
gn-test-check-mock-args _ANY_ --prepare --image qemu-arm64 --bucket fuchsia --work-dir "${FUCHSIA_WORK_DIR}"
# Verify some of the arguments passed to the emulator binary
# shellcheck disable=SC1090
source "${FUCHSIA_WORK_DIR}/emulator/aemu-${PLATFORM}-${AEMU_LABEL}/emulator.mock_state"
gn-test-check-mock-partial -fuchsia
gn-test-check-mock-partial -avd-arch arm64
gn-test-check-mock-partial -cpu cortex-a53
gn-test-check-mock-partial -gpu swiftshader_indirect
}
# Verifies that the correct emulator command is run by femu, along with the image setup.
# This tests the -N option for networking.
TEST_femu_networking() {
PATH_DIR_FOR_TEST="${BT_TEMP_DIR}/_isolated_path_for"
export PATH="${PATH_DIR_FOR_TEST}:${PATH}"
# Create fake "ip tuntap show" command to let fx emu know the network is configured with some mocked output
cat >"${PATH_DIR_FOR_TEST}/ip.mock_side_effects" <<INPUT
echo "qemu: tap persist user 238107"
INPUT
# Create fake ZIP file download so femu.sh doesn't try to download it, and
# later on provide a mocked emulator script so it doesn't try to unzip it.
touch "${FUCHSIA_WORK_DIR}/emulator/aemu-${PLATFORM}-${AEMU_LABEL}.zip"
# Need to configure a DISPLAY so that we can get past the graphics error checks
export DISPLAY="fakedisplay"
# OSX may not have the tun/tap driver installed, and you cannot bypass the
# network checks, so need to work around this for the test. Linux does not
# need a fake network because we use a fake ip command.
if is-mac && [[ ! -c /dev/tap0 || ! -w /dev/tap0 ]]; then
NETWORK_ARGS=( -N -I fakenetwork )
else
NETWORK_ARGS=( -N )
fi
# Run command.
BT_EXPECT run_femu_wrapper \
"${NETWORK_ARGS[*]}" \
--unknown-arg1-to-qemu \
--authorized-keys "${BT_TEMP_DIR}/scripts/sdk/gn/base/testdata/authorized_keys" \
--unknown-arg2-to-qemu
# Verify that the image first goes through a decompress process by fvm
source "${MOCKED_FVM}.mock_state.1"
gn-test-check-mock-args _ANY_ _ANY_ decompress --default _ANY_
# Verify that the image will be extended to double the size
source "${MOCKED_FVM}.mock_state.2"
gn-test-check-mock-args _ANY_ _ANY_ extend --length 2048 --length-is-lowerbound
# Check that fpave.sh was called to download the needed system images
# shellcheck disable=SC1090
source "${BT_TEMP_DIR}/scripts/sdk/gn/base/bin/fpave.sh.mock_state"
gn-test-check-mock-args _ANY_ --prepare --image qemu-x64 --bucket fuchsia --work-dir "${FUCHSIA_WORK_DIR}"
# Check that fserve.sh was called to download the needed system images
# shellcheck disable=SC1090
source "${BT_TEMP_DIR}/scripts/sdk/gn/base/bin/fserve.sh.mock_state"
gn-test-check-mock-args _ANY_ --prepare --image qemu-x64 --bucket fuchsia --work-dir "${FUCHSIA_WORK_DIR}"
# Verify that zbi was called to add the authorized_keys
# shellcheck disable=SC1090
source "${MOCKED_ZBI}.mock_state"
gn-test-check-mock-args _ANY_ -o _ANY_ "${FUCHSIA_WORK_DIR}/image/zircon-a.zbi" --entry "data/ssh/authorized_keys=${BT_TEMP_DIR}/scripts/sdk/gn/base/testdata/authorized_keys"
# Verify some of the arguments passed to the emulator binary
# shellcheck disable=SC1090
source "${FUCHSIA_WORK_DIR}/emulator/aemu-${PLATFORM}-${AEMU_LABEL}/emulator.mock_state"
# The mac address is computed with a hash function in fx emu based on the device name.
# We test the generated mac address since other scripts hard code this to SSH into the device.
gn-test-check-mock-partial -fuchsia
if is-mac; then
if [[ -c /dev/tap0 && -w /dev/tap0 ]]; then
gn-test-check-mock-partial -netdev type=tap,ifname=tap0,id=net0,script="${BT_TEMP_DIR}/scripts/sdk/gn/base/bin/devshell/lib/emu-ifup-macos.sh"
gn-test-check-mock-partial -device e1000,netdev=net0,mac=52:54:00:4d:27:96
else
gn-test-check-mock-partial -netdev type=tap,ifname=fakenetwork,id=net0,script="${BT_TEMP_DIR}/scripts/sdk/gn/base/bin/devshell/lib/emu-ifup-macos.sh"
gn-test-check-mock-partial -device e1000,netdev=net0,mac=52:54:00:95:03:66
fi
else
gn-test-check-mock-partial -netdev type=tap,ifname=qemu,id=net0,script=no
gn-test-check-mock-partial -device e1000,netdev=net0,mac=52:54:00:63:5e:7a
fi
gn-test-check-mock-partial --unknown-arg1-to-qemu
gn-test-check-mock-partial --unknown-arg2-to-qemu
}
# Verifies that fx emu starts up grpcwebproxy correctly
TEST_femu_grpcwebproxy() {
PATH_DIR_FOR_TEST="${BT_TEMP_DIR}/_isolated_path_for"
export PATH="${PATH_DIR_FOR_TEST}:${PATH}"
# Create fake "kill" command so when emu tries to kill grpcwebproxy, it doesn't fail
# this test. Need to embed "enable -n kill" into fx-image-common.sh to disable the
# bash builtin kill so we can intercept it.
cat >"${PATH_DIR_FOR_TEST}/kill.mock_side_effects" <<INPUT
echo "$@"
INPUT
echo "enable -n kill" >> "${BT_TEMP_DIR}/scripts/sdk/gn/base/bin/fx-image-common.sh"
# Create fake ZIP file download so femu.sh doesn't try to download it, and
# later on provide a mocked emulator script so it doesn't try to unzip it.
touch "${FUCHSIA_WORK_DIR}/emulator/aemu-${PLATFORM}-${AEMU_LABEL}.zip"
touch "${FUCHSIA_WORK_DIR}/emulator/grpcwebproxy-${PLATFORM}-${AEMU_LABEL}.zip"
# Need to configure a DISPLAY so that we can get past the graphics error checks
export DISPLAY="fakedisplay"
if is-mac; then
# grpcwebproxy does not work on OSX, so check there is an error message
BT_EXPECT_FAIL run_femu_wrapper \
-x 1234 \
> femu_error_output.txt 2>&1
else
# Run command with the default grpcwebproxy.
BT_EXPECT run_femu_wrapper \
-x 1234
# Verify that the default grpcwebproxy binary is called correctly
# shellcheck disable=SC1090
source "${FUCHSIA_WORK_DIR}/emulator/grpcwebproxy-${PLATFORM}-${GRPCWEBPROXY_LABEL}/grpcwebproxy.mock_state"
gn-test-check-mock-partial --backend_addr localhost:5556
gn-test-check-mock-partial --server_http_debug_port 1234
# Run command and test the -X for a manually provided grpcwebproxy.
BT_EXPECT run_femu_wrapper \
-x 1234 -X "${BT_TEMP_DIR}/mocked/grpcwebproxy-dir"
# Verify that the grpcwebproxy binary is called correctly
# shellcheck disable=SC1090
source "${BT_TEMP_DIR}/mocked/grpcwebproxy-dir/grpcwebproxy.mock_state"
gn-test-check-mock-partial --backend_addr localhost:5556
gn-test-check-mock-partial --server_http_debug_port 1234
fi
}
# Verifies that the --setup-ufw option runs ufw
TEST_femu_ufw() {
PATH_DIR_FOR_TEST="${BT_TEMP_DIR}/_isolated_path_for"
export PATH="${PATH_DIR_FOR_TEST}:${PATH}"
if is-mac; then
BT_EXPECT_FAIL run_femu_wrapper \
--setup-ufw > femu_ufw_error.txt 2>&1
else
BT_EXPECT run_femu_wrapper \
--setup-ufw
# Check that ufw was called via sudo
# shellcheck disable=SC1090
source "${BT_TEMP_DIR}/_isolated_path_for/sudo.mock_state.1"
gn-test-check-mock-args _ANY_ ufw allow proto _ANY_ from _ANY_ to any port _ANY_ comment _ANY_
fi
}
# Test initialization. Note that we copy various tools/devshell files and need to replicate the
# behavior of generate.py by copying these files into scripts/sdk/gn/base/bin/devshell
# shellcheck disable=SC2034
BT_FILE_DEPS=(
scripts/sdk/gn/base/bin/femu.sh
scripts/sdk/gn/base/bin/devshell/lib/image_build_vars.sh
scripts/sdk/gn/base/bin/fuchsia-common.sh
scripts/sdk/gn/base/bin/fx-image-common.sh
scripts/sdk/gn/bash_tests/gn-bash-test-lib.sh
tools/devshell/emu
tools/devshell/lib/fvm.sh
tools/devshell/lib/emu-ifup-macos.sh
)
# shellcheck disable=SC2034
BT_MOCKED_TOOLS=(
# mock both mac and linux so the test runs successfully on both.
test-home/.fuchsia/emulator/aemu-linux-amd64-"${AEMU_LABEL}"/emulator
test-home/.fuchsia/emulator/aemu-mac-amd64-"${AEMU_LABEL}"/emulator
test-home/.fuchsia/emulator/grpcwebproxy-mac-amd64-"${GRPCWEBPROXY_LABEL}"/grpcwebproxy
test-home/.fuchsia/emulator/grpcwebproxy-linux-amd64-"${GRPCWEBPROXY_LABEL}"/grpcwebproxy
scripts/sdk/gn/base/bin/fpave.sh
scripts/sdk/gn/base/bin/fserve.sh
scripts/sdk/gn/base/tools/x64/zbi
scripts/sdk/gn/base/tools/arm64/zbi
scripts/sdk/gn/base/tools/x64/fvm
scripts/sdk/gn/base/tools/arm64/fvm
mocked/grpcwebproxy-dir/grpcwebproxy
_isolated_path_for/ip
_isolated_path_for/kill
_isolated_path_for/sudo
# Create fake "stty sane" command so that fx emu test succeeds when < /dev/null is being used
_isolated_path_for/stty
)
BT_SET_UP() {
# shellcheck disable=SC1090
source "${BT_TEMP_DIR}/scripts/sdk/gn/bash_tests/gn-bash-test-lib.sh"
# Make "home" directory in the test dir so the paths are stable."
mkdir -p "${BT_TEMP_DIR}/test-home"
export HOME="${BT_TEMP_DIR}/test-home"
FUCHSIA_WORK_DIR="${HOME}/.fuchsia"
if is-mac; then
PLATFORM="mac-amd64"
else
PLATFORM="linux-amd64"
fi
MOCKED_FVM="${BT_TEMP_DIR}/scripts/sdk/gn/base/$(gn-test-tools-subdir)/fvm"
MOCKED_ZBI="${BT_TEMP_DIR}/scripts/sdk/gn/base/$(gn-test-tools-subdir)/zbi"
# Create a small disk image to avoid downloading, and test if it is doubled in size as expected
mkdir -p "${FUCHSIA_WORK_DIR}/image"
dd if=/dev/zero of="${FUCHSIA_WORK_DIR}/image/storage-full.blk" bs=1024 count=1 > /dev/null 2>/dev/null
}
BT_INIT_TEMP_DIR() {
# Generate the prebuilt version file based on the simulated version string
echo "${AEMU_VERSION}" > "${BT_TEMP_DIR}/scripts/sdk/gn/base/bin/aemu.version"
echo "${GRPCWEBPROXY_VERSION}" > "${BT_TEMP_DIR}/scripts/sdk/gn/base/bin/grpcwebproxy.version"
# Create empty authorized_keys file to add to the system image, but the contents are not used.
mkdir -p "${BT_TEMP_DIR}/scripts/sdk/gn/base/testdata"
echo ssh-ed25519 00000000000000000000000000000000000000000000000000000000000000000000 \
>"${BT_TEMP_DIR}/scripts/sdk/gn/base/testdata/authorized_keys"
# Stage the files we copy from the fx emu implementation, replicating behavior of generate.py
cp -r "${BT_TEMP_DIR}/tools/devshell" "${BT_TEMP_DIR}/scripts/sdk/gn/base/bin/"
}
BT_RUN_TESTS "$@"