platform_build_soong/tests/lib.sh
Spandan Das 0506361a60 Add errorHints to stdout when read-only file system errors are detected
The source tree will eventually be made ReadOnly, and recipes that write
directly to the source tree will fail. Use a pattern-match approach on
the results of stdout/stderr to provide hints to the user in such a
scenario.

If multiple patterns are found in raw output, print error hint
corresponding to first pattern match. first pattern match is chosen
since the failing function will be at the top of the stack, and hence
will be logged first

Test: Wrote a unit test to assert errorhint is added to output.
Wrote an integration test that writes to a file in the source tree
1. When source_tree is RO, the recipe fails and an error hint is printed
to stdout
2. When source tree is RW, the recipe succeeds and no error hint is
printed

Bug: 174726238
Change-Id: Id67b48f8094cdf8a571c239ae469d60464a1e89c
2021-06-29 00:20:21 +00:00

138 lines
3 KiB
Bash

#!/bin/bash -eu
set -o pipefail
HARDWIRED_MOCK_TOP=
# Uncomment this to be able to view the source tree after a test is run
# HARDWIRED_MOCK_TOP=/tmp/td
REAL_TOP="$(readlink -f "$(dirname "$0")"/../../..)"
if [[ ! -z "$HARDWIRED_MOCK_TOP" ]]; then
MOCK_TOP="$HARDWIRED_MOCK_TOP"
else
MOCK_TOP=$(mktemp -t -d st.XXXXX)
trap cleanup_mock_top EXIT
fi
WARMED_UP_MOCK_TOP=$(mktemp -t soong_integration_tests_warmup.XXXXXX.tar.gz)
trap 'rm -f "$WARMED_UP_MOCK_TOP"' EXIT
function warmup_mock_top {
info "Warming up mock top ..."
info "Mock top warmup archive: $WARMED_UP_MOCK_TOP"
cleanup_mock_top
mkdir -p "$MOCK_TOP"
cd "$MOCK_TOP"
create_mock_soong
run_soong
tar czf "$WARMED_UP_MOCK_TOP" *
}
function cleanup_mock_top {
cd /
rm -fr "$MOCK_TOP"
}
function info {
echo -e "\e[92;1m[TEST HARNESS INFO]\e[0m" $*
}
function fail {
echo -e "\e[91;1mFAILED:\e[0m" $*
exit 1
}
function copy_directory() {
local dir="$1"
local parent="$(dirname "$dir")"
mkdir -p "$MOCK_TOP/$parent"
cp -R "$REAL_TOP/$dir" "$MOCK_TOP/$parent"
}
function symlink_file() {
local file="$1"
mkdir -p "$MOCK_TOP/$(dirname "$file")"
ln -s "$REAL_TOP/$file" "$MOCK_TOP/$file"
}
function symlink_directory() {
local dir="$1"
mkdir -p "$MOCK_TOP/$dir"
# We need to symlink the contents of the directory individually instead of
# using one symlink for the whole directory because finder.go doesn't follow
# symlinks when looking for Android.bp files
for i in $(ls "$REAL_TOP/$dir"); do
local target="$MOCK_TOP/$dir/$i"
local source="$REAL_TOP/$dir/$i"
if [[ -e "$target" ]]; then
if [[ ! -d "$source" || ! -d "$target" ]]; then
fail "Trying to symlink $dir twice"
fi
else
ln -s "$REAL_TOP/$dir/$i" "$MOCK_TOP/$dir/$i";
fi
done
}
function create_mock_soong {
copy_directory build/blueprint
copy_directory build/soong
symlink_directory prebuilts/go
symlink_directory prebuilts/build-tools
symlink_directory external/golang-protobuf
touch "$MOCK_TOP/Android.bp"
}
function setup() {
cleanup_mock_top
mkdir -p "$MOCK_TOP"
echo
echo ----------------------------------------------------------------------------
info "Running test case \e[96;1m${FUNCNAME[1]}\e[0m"
cd "$MOCK_TOP"
tar xzf "$WARMED_UP_MOCK_TOP"
}
function run_soong() {
build/soong/soong_ui.bash --make-mode --skip-ninja --skip-make --skip-soong-tests "$@"
}
function create_mock_bazel() {
copy_directory build/bazel
symlink_directory prebuilts/bazel
symlink_directory prebuilts/jdk
symlink_file WORKSPACE
symlink_file BUILD
symlink_file tools/bazel
}
run_bazel() {
tools/bazel "$@"
}
run_bp2build() {
GENERATE_BAZEL_FILES=true build/soong/soong_ui.bash --make-mode --skip-ninja --skip-make --skip-soong-tests nothing
}
run_ninja() {
build/soong/soong_ui.bash --make-mode --skip-make --skip-soong-tests "$@"
}
info "Starting Soong integration test suite $(basename $0)"
info "Mock top: $MOCK_TOP"
export ALLOW_MISSING_DEPENDENCIES=true
warmup_mock_top