477 lines
13 KiB
Bash
Executable file
477 lines
13 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_build_files_take_precedence {
|
|
_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
|
|
_build_files_take_precedence
|
|
eval "${_save_trap}"
|
|
}
|
|
|
|
function _build_files_take_precedence {
|
|
setup
|
|
|
|
# This specific directory is hardcoded in bp2build as being one
|
|
# where the BUILD file should be intentionally kept.
|
|
mkdir -p testpkg/keep_build_file
|
|
cat > testpkg/keep_build_file/Android.bp <<'EOF'
|
|
genrule {
|
|
name: "print_origin",
|
|
cmd: "echo 'from_soong' > $(out)",
|
|
out: [
|
|
"origin.txt",
|
|
],
|
|
bazel_module: {
|
|
bp2build_available: true,
|
|
},
|
|
}
|
|
EOF
|
|
|
|
run_soong bp2build
|
|
run_bazel build --config=android --config=bp2build --config=ci //testpkg/keep_build_file:print_origin
|
|
|
|
local -r output_file="$(find -L bazel-out -name origin.txt)"
|
|
if [[ ! -f "${output_file}" ]]; then
|
|
fail "Expected origin.txt to be generated, but was missing"
|
|
fi
|
|
if ! grep from_soong "${output_file}"; then
|
|
fail "Expected to find 'from_soong' in '${output_file}'"
|
|
fi
|
|
|
|
cat > testpkg/keep_build_file/BUILD.bazel <<'EOF'
|
|
genrule(
|
|
name = "print_origin",
|
|
outs = ["origin.txt"],
|
|
cmd = "echo 'from_bazel' > $@",
|
|
)
|
|
EOF
|
|
|
|
# Clean the workspace. There is a test infrastructure bug where run_bazel
|
|
# will symlink Android.bp files in the source directory again and thus
|
|
# pollute the workspace.
|
|
# TODO: b/286059878 - Remove this clean after the underlying bug is fixed.
|
|
run_soong clean
|
|
run_soong bp2build
|
|
run_bazel build --config=android --config=bp2build --config=ci //testpkg/keep_build_file:print_origin
|
|
if ! grep from_bazel "${output_file}"; then
|
|
fail "Expected to find 'from_bazel' in '${output_file}'"
|
|
fi
|
|
}
|
|
|
|
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
|