platform_build_soong/tests/bp2build_bazel_test.sh
Cole Faust 24af24e0f2 Remove --noexperimental_platform_in_output_dir
This is a followup to aosp/2606989.

This flag is not necessary now that we're using one platform name
for all of mixed builds.

Also rename current_product to mixed_builds_product so that it's clear
that that this platform should only be used for mixed builds.

In addition, make the bazelrc files point to the named products again
instead of the mixed build product so that b builds will still have
qualified outputs, but mixed builds won't.

Test: Presubmit
Change-Id: I5acbd18869589f67efb0ad3ebfda2c4d5a6a3850
2023-06-07 11:08:44 -07:00

420 lines
11 KiB
Bash
Executable file

#!/bin/bash -eu
set -o pipefail
# Test that bp2build and Bazel can play nicely together
source "$(dirname "$0")/lib.sh"
readonly GENERATED_BUILD_FILE_NAME="BUILD.bazel"
function test_bp2build_null_build {
setup
run_soong bp2build
local -r output_mtime1=$(stat -c "%y" out/soong/bp2build_workspace_marker)
run_soong bp2build
local -r output_mtime2=$(stat -c "%y" out/soong/bp2build_workspace_marker)
if [[ "$output_mtime1" != "$output_mtime2" ]]; then
fail "Output bp2build marker file changed on null build"
fi
}
# Tests that, if bp2build reruns due to a blueprint file changing, that
# BUILD files whose contents are unchanged are not regenerated.
function test_bp2build_unchanged {
setup
mkdir -p pkg
touch pkg/x.txt
cat > pkg/Android.bp <<'EOF'
filegroup {
name: "x",
srcs: ["x.txt"],
bazel_module: {bp2build_available: true},
}
EOF
run_soong bp2build
local -r buildfile_mtime1=$(stat -c "%y" out/soong/bp2build/pkg/BUILD.bazel)
local -r marker_mtime1=$(stat -c "%y" out/soong/bp2build_workspace_marker)
# Force bp2build to rerun by updating the timestamp of a blueprint file.
touch pkg/Android.bp
run_soong bp2build
local -r buildfile_mtime2=$(stat -c "%y" out/soong/bp2build/pkg/BUILD.bazel)
local -r marker_mtime2=$(stat -c "%y" out/soong/bp2build_workspace_marker)
if [[ "$marker_mtime1" == "$marker_mtime2" ]]; then
fail "Expected bp2build marker file to change"
fi
if [[ "$buildfile_mtime1" != "$buildfile_mtime2" ]]; then
fail "BUILD.bazel was updated even though contents are same"
fi
# Force bp2build to rerun by updating the timestamp of the constants_exported_to_soong.bzl file.
touch build/bazel/constants_exported_to_soong.bzl
run_soong bp2build
local -r buildfile_mtime3=$(stat -c "%y" out/soong/bp2build/pkg/BUILD.bazel)
local -r marker_mtime3=$(stat -c "%y" out/soong/bp2build_workspace_marker)
if [[ "$marker_mtime2" == "$marker_mtime3" ]]; then
fail "Expected bp2build marker file to change"
fi
if [[ "$buildfile_mtime2" != "$buildfile_mtime3" ]]; then
fail "BUILD.bazel was updated even though contents are same"
fi
}
# Tests that blueprint files that are deleted are not present when the
# bp2build tree is regenerated.
function test_bp2build_deleted_blueprint {
setup
mkdir -p pkg
touch pkg/x.txt
cat > pkg/Android.bp <<'EOF'
filegroup {
name: "x",
srcs: ["x.txt"],
bazel_module: {bp2build_available: true},
}
EOF
run_soong bp2build
if [[ ! -e "./out/soong/bp2build/pkg/BUILD.bazel" ]]; then
fail "Expected pkg/BUILD.bazel to be generated"
fi
rm pkg/Android.bp
run_soong bp2build
if [[ -e "./out/soong/bp2build/pkg/BUILD.bazel" ]]; then
fail "Expected pkg/BUILD.bazel to be deleted"
fi
}
function test_bp2build_null_build_with_globs {
setup
mkdir -p foo/bar
cat > foo/bar/Android.bp <<'EOF'
filegroup {
name: "globs",
srcs: ["*.txt"],
}
EOF
touch foo/bar/a.txt foo/bar/b.txt
run_soong bp2build
local -r output_mtime1=$(stat -c "%y" out/soong/bp2build_workspace_marker)
run_soong bp2build
local -r output_mtime2=$(stat -c "%y" out/soong/bp2build_workspace_marker)
if [[ "$output_mtime1" != "$output_mtime2" ]]; then
fail "Output bp2build marker file changed on null build"
fi
}
function test_different_relative_outdir {
setup
mkdir -p a
touch a/g.txt
cat > a/Android.bp <<'EOF'
filegroup {
name: "g",
srcs: ["g.txt"],
bazel_module: {bp2build_available: true},
}
EOF
# A directory under $MOCK_TOP
outdir=out2
trap "rm -rf $outdir" EXIT
# Modify OUT_DIR in a subshell so it doesn't affect the top level one.
(export OUT_DIR=$outdir; run_soong bp2build && run_bazel build --config=bp2build --config=ci //a:g)
}
function test_different_absolute_outdir {
setup
mkdir -p a
touch a/g.txt
cat > a/Android.bp <<'EOF'
filegroup {
name: "g",
srcs: ["g.txt"],
bazel_module: {bp2build_available: true},
}
EOF
# A directory under /tmp/...
outdir=$(mktemp -t -d st.XXXXX)
trap 'rm -rf $outdir' EXIT
# Modify OUT_DIR in a subshell so it doesn't affect the top level one.
(export OUT_DIR=$outdir; run_soong bp2build && run_bazel build --config=bp2build --config=ci //a:g)
}
function _bp2build_generates_all_buildfiles {
setup
mkdir -p foo/convertible_soong_module
cat > foo/convertible_soong_module/Android.bp <<'EOF'
genrule {
name: "the_answer",
cmd: "echo '42' > $(out)",
out: [
"the_answer.txt",
],
bazel_module: {
bp2build_available: true,
},
}
EOF
mkdir -p foo/unconvertible_soong_module
cat > foo/unconvertible_soong_module/Android.bp <<'EOF'
genrule {
name: "not_the_answer",
cmd: "echo '43' > $(out)",
out: [
"not_the_answer.txt",
],
bazel_module: {
bp2build_available: false,
},
}
EOF
run_soong bp2build
if [[ ! -f "./out/soong/workspace/foo/convertible_soong_module/${GENERATED_BUILD_FILE_NAME}" ]]; then
fail "./out/soong/workspace/foo/convertible_soong_module/${GENERATED_BUILD_FILE_NAME} was not generated"
fi
if [[ ! -f "./out/soong/workspace/foo/unconvertible_soong_module/${GENERATED_BUILD_FILE_NAME}" ]]; then
fail "./out/soong/workspace/foo/unconvertible_soong_module/${GENERATED_BUILD_FILE_NAME} was not generated"
fi
if ! grep "the_answer" "./out/soong/workspace/foo/convertible_soong_module/${GENERATED_BUILD_FILE_NAME}"; then
fail "missing BUILD target the_answer in convertible_soong_module/${GENERATED_BUILD_FILE_NAME}"
fi
if grep "not_the_answer" "./out/soong/workspace/foo/unconvertible_soong_module/${GENERATED_BUILD_FILE_NAME}"; then
fail "found unexpected BUILD target not_the_answer in unconvertible_soong_module/${GENERATED_BUILD_FILE_NAME}"
fi
if ! grep "filegroup" "./out/soong/workspace/foo/unconvertible_soong_module/${GENERATED_BUILD_FILE_NAME}"; then
fail "missing filegroup in unconvertible_soong_module/${GENERATED_BUILD_FILE_NAME}"
fi
# NOTE: We don't actually use the extra BUILD file for anything here
run_bazel build --config=android --config=bp2build --config=ci //foo/...
local -r the_answer_file="$(find -L bazel-out -name the_answer.txt)"
if [[ ! -f "${the_answer_file}" ]]; then
fail "Expected the_answer.txt to be generated, but was missing"
fi
if ! grep 42 "${the_answer_file}"; then
fail "Expected to find 42 in '${the_answer_file}'"
fi
}
function test_bp2build_generates_all_buildfiles {
_save_trap=$(trap -p EXIT)
trap '[[ $? -ne 0 ]] && echo Are you running this locally? Try changing --sandbox_tmpfs_path to something other than /tmp/ in build/bazel/linux.bazelrc.' EXIT
_bp2build_generates_all_buildfiles
eval "${_save_trap}"
}
function test_bp2build_symlinks_files {
setup
mkdir -p foo
touch foo/BLANK1
touch foo/BLANK2
touch foo/F2D
touch foo/BUILD
run_soong bp2build
if [[ -e "./out/soong/workspace/foo/BUILD" ]]; then
fail "./out/soong/workspace/foo/BUILD should be omitted"
fi
for file in BLANK1 BLANK2 F2D
do
if [[ ! -L "./out/soong/workspace/foo/$file" ]]; then
fail "./out/soong/workspace/foo/$file should exist"
fi
done
local -r BLANK1_BEFORE=$(stat -c %y "./out/soong/workspace/foo/BLANK1")
rm foo/BLANK2
rm foo/F2D
mkdir foo/F2D
touch foo/F2D/BUILD
run_soong bp2build
if [[ -e "./out/soong/workspace/foo/BUILD" ]]; then
fail "./out/soong/workspace/foo/BUILD should be omitted"
fi
local -r BLANK1_AFTER=$(stat -c %y "./out/soong/workspace/foo/BLANK1")
if [[ "$BLANK1_AFTER" != "$BLANK1_BEFORE" ]]; then
fail "./out/soong/workspace/foo/BLANK1 should be untouched"
fi
if [[ -e "./out/soong/workspace/foo/BLANK2" ]]; then
fail "./out/soong/workspace/foo/BLANK2 should be removed"
fi
if [[ -L "./out/soong/workspace/foo/F2D" ]] || [[ ! -d "./out/soong/workspace/foo/F2D" ]]; then
fail "./out/soong/workspace/foo/F2D should be a dir"
fi
}
function test_cc_correctness {
setup
mkdir -p a
cat > a/Android.bp <<EOF
cc_object {
name: "qq",
srcs: ["qq.cc"],
bazel_module: {
bp2build_available: true,
},
stl: "none",
system_shared_libs: [],
}
EOF
cat > a/qq.cc <<EOF
#include "qq.h"
int qq() {
return QQ;
}
EOF
cat > a/qq.h <<EOF
#define QQ 1
EOF
run_soong bp2build
run_bazel build --config=android --config=bp2build --config=ci //a:qq
local -r output_mtime1=$(stat -c "%y" bazel-bin/a/_objs/qq/qq.o)
run_bazel build --config=android --config=bp2build --config=ci //a:qq
local -r output_mtime2=$(stat -c "%y" bazel-bin/a/_objs/qq/qq.o)
if [[ "$output_mtime1" != "$output_mtime2" ]]; then
fail "output changed on null build"
fi
cat > a/qq.h <<EOF
#define QQ 2
EOF
run_bazel build --config=android --config=bp2build --config=ci //a:qq
local -r output_mtime3=$(stat -c "%y" bazel-bin/a/_objs/qq/qq.o)
if [[ "$output_mtime1" == "$output_mtime3" ]]; then
fail "output not changed when included header changed"
fi
}
# Regression test for the following failure during symlink forest creation:
#
# Cannot stat '/tmp/st.rr054/foo/bar/unresolved_symlink': stat /tmp/st.rr054/foo/bar/unresolved_symlink: no such file or directory
#
function test_bp2build_null_build_with_unresolved_symlink_in_source() {
setup
mkdir -p foo/bar
ln -s /tmp/non-existent foo/bar/unresolved_symlink
cat > foo/bar/Android.bp <<'EOF'
filegroup {
name: "fg",
srcs: ["unresolved_symlink/non-existent-file.txt"],
}
EOF
run_soong bp2build
dest=$(readlink -f out/soong/workspace/foo/bar/unresolved_symlink)
if [[ "$dest" != "/tmp/non-existent" ]]; then
fail "expected to plant an unresolved symlink out/soong/workspace/foo/bar/unresolved_symlink that resolves to /tmp/non-existent"
fi
}
# Smoke test to verify api_bp2build worksapce does not contain any errors
function test_api_bp2build_empty_build() {
setup
run_soong api_bp2build
run_bazel build --config=android --config=api_bp2build //:empty
}
# Verify that an *_api_contribution target can refer to an api file from
# another Bazel package.
function test_api_export_from_another_bazel_package() {
setup
# Parent dir Android.bp
mkdir -p foo
cat > foo/Android.bp << 'EOF'
cc_library {
name: "libfoo",
stubs: {
symbol_file: "api/libfoo.map.txt",
},
}
EOF
# Child dir Android.bp
mkdir -p foo/api
cat > foo/api/Android.bp << 'EOF'
package{}
EOF
touch foo/api/libfoo.map.txt
# Run test
run_soong api_bp2build
run_bazel build --config=android --config=api_bp2build //foo:libfoo.contribution
}
function test_bazel_standalone_output_paths_contain_product_name {
setup
mkdir -p a
cat > a/Android.bp <<EOF
cc_object {
name: "qq",
srcs: ["qq.cc"],
bazel_module: {
bp2build_available: true,
},
stl: "none",
system_shared_libs: [],
}
EOF
cat > a/qq.cc <<EOF
#include "qq.h"
int qq() {
return QQ;
}
EOF
cat > a/qq.h <<EOF
#define QQ 1
EOF
export TARGET_PRODUCT=aosp_arm; run_soong bp2build
local -r output=$(run_bazel cquery //a:qq --output=files --config=android --config=bp2build --config=ci)
if [[ ! $(echo ${output} | grep "bazel-out/aosp_arm") ]]; then
fail "Did not find the product name '${TARGET_PRODUCT}' in the output path. This can cause " \
"unnecessary rebuilds when toggling between products as bazel outputs for different products will " \
"clobber each other. Output paths are: \n${output}"
fi
}
scan_and_run_tests