1#!/bin/bash -eu 2 3set -o pipefail 4 5# Test that bp2build and Bazel can play nicely together 6 7source "$(dirname "$0")/lib.sh" 8 9readonly GENERATED_BUILD_FILE_NAME="BUILD.bazel" 10 11function test_bp2build_null_build { 12 setup 13 run_soong bp2build 14 local -r output_mtime1=$(stat -c "%y" out/soong/bp2build_workspace_marker) 15 16 run_soong bp2build 17 local -r output_mtime2=$(stat -c "%y" out/soong/bp2build_workspace_marker) 18 19 if [[ "$output_mtime1" != "$output_mtime2" ]]; then 20 fail "Output bp2build marker file changed on null build" 21 fi 22} 23 24# Tests that, if bp2build reruns due to a blueprint file changing, that 25# BUILD files whose contents are unchanged are not regenerated. 26function test_bp2build_unchanged { 27 setup 28 29 mkdir -p pkg 30 touch pkg/x.txt 31 cat > pkg/Android.bp <<'EOF' 32filegroup { 33 name: "x", 34 srcs: ["x.txt"], 35 bazel_module: {bp2build_available: true}, 36 } 37EOF 38 39 run_soong bp2build 40 local -r buildfile_mtime1=$(stat -c "%y" out/soong/bp2build/pkg/BUILD.bazel) 41 local -r marker_mtime1=$(stat -c "%y" out/soong/bp2build_workspace_marker) 42 43 # Force bp2build to rerun by updating the timestamp of a blueprint file. 44 touch pkg/Android.bp 45 46 run_soong bp2build 47 local -r buildfile_mtime2=$(stat -c "%y" out/soong/bp2build/pkg/BUILD.bazel) 48 local -r marker_mtime2=$(stat -c "%y" out/soong/bp2build_workspace_marker) 49 50 if [[ "$marker_mtime1" == "$marker_mtime2" ]]; then 51 fail "Expected bp2build marker file to change" 52 fi 53 if [[ "$buildfile_mtime1" != "$buildfile_mtime2" ]]; then 54 fail "BUILD.bazel was updated even though contents are same" 55 fi 56} 57 58# Tests that blueprint files that are deleted are not present when the 59# bp2build tree is regenerated. 60function test_bp2build_deleted_blueprint { 61 setup 62 63 mkdir -p pkg 64 touch pkg/x.txt 65 cat > pkg/Android.bp <<'EOF' 66filegroup { 67 name: "x", 68 srcs: ["x.txt"], 69 bazel_module: {bp2build_available: true}, 70 } 71EOF 72 73 run_soong bp2build 74 if [[ ! -e "./out/soong/bp2build/pkg/BUILD.bazel" ]]; then 75 fail "Expected pkg/BUILD.bazel to be generated" 76 fi 77 78 rm pkg/Android.bp 79 80 run_soong bp2build 81 if [[ -e "./out/soong/bp2build/pkg/BUILD.bazel" ]]; then 82 fail "Expected pkg/BUILD.bazel to be deleted" 83 fi 84} 85 86function test_bp2build_null_build_with_globs { 87 setup 88 89 mkdir -p foo/bar 90 cat > foo/bar/Android.bp <<'EOF' 91filegroup { 92 name: "globs", 93 srcs: ["*.txt"], 94 } 95EOF 96 touch foo/bar/a.txt foo/bar/b.txt 97 98 run_soong bp2build 99 local -r output_mtime1=$(stat -c "%y" out/soong/bp2build_workspace_marker) 100 101 run_soong bp2build 102 local -r output_mtime2=$(stat -c "%y" out/soong/bp2build_workspace_marker) 103 104 if [[ "$output_mtime1" != "$output_mtime2" ]]; then 105 fail "Output bp2build marker file changed on null build" 106 fi 107} 108 109function test_different_relative_outdir { 110 setup 111 112 mkdir -p a 113 touch a/g.txt 114 cat > a/Android.bp <<'EOF' 115filegroup { 116 name: "g", 117 srcs: ["g.txt"], 118 bazel_module: {bp2build_available: true}, 119 } 120EOF 121 122 # A directory under $MOCK_TOP 123 outdir=out2 124 trap "rm -rf $outdir" EXIT 125 # Modify OUT_DIR in a subshell so it doesn't affect the top level one. 126 (export OUT_DIR=$outdir; run_soong bp2build && run_bazel build --config=bp2build --config=ci //a:g) 127} 128 129function test_different_absolute_outdir { 130 setup 131 132 mkdir -p a 133 touch a/g.txt 134 cat > a/Android.bp <<'EOF' 135filegroup { 136 name: "g", 137 srcs: ["g.txt"], 138 bazel_module: {bp2build_available: true}, 139 } 140EOF 141 142 # A directory under /tmp/... 143 outdir=$(mktemp -t -d st.XXXXX) 144 trap 'rm -rf $outdir' EXIT 145 # Modify OUT_DIR in a subshell so it doesn't affect the top level one. 146 (export OUT_DIR=$outdir; run_soong bp2build && run_bazel build --config=bp2build --config=ci //a:g) 147} 148 149function _bp2build_generates_all_buildfiles { 150 setup 151 152 mkdir -p foo/convertible_soong_module 153 cat > foo/convertible_soong_module/Android.bp <<'EOF' 154genrule { 155 name: "the_answer", 156 cmd: "echo '42' > $(out)", 157 out: [ 158 "the_answer.txt", 159 ], 160 bazel_module: { 161 bp2build_available: true, 162 }, 163 } 164EOF 165 166 mkdir -p foo/unconvertible_soong_module 167 cat > foo/unconvertible_soong_module/Android.bp <<'EOF' 168genrule { 169 name: "not_the_answer", 170 cmd: "echo '43' > $(out)", 171 out: [ 172 "not_the_answer.txt", 173 ], 174 bazel_module: { 175 bp2build_available: false, 176 }, 177 } 178EOF 179 180 run_soong bp2build 181 182 if [[ ! -f "./out/soong/workspace/foo/convertible_soong_module/${GENERATED_BUILD_FILE_NAME}" ]]; then 183 fail "./out/soong/workspace/foo/convertible_soong_module/${GENERATED_BUILD_FILE_NAME} was not generated" 184 fi 185 186 if [[ ! -f "./out/soong/workspace/foo/unconvertible_soong_module/${GENERATED_BUILD_FILE_NAME}" ]]; then 187 fail "./out/soong/workspace/foo/unconvertible_soong_module/${GENERATED_BUILD_FILE_NAME} was not generated" 188 fi 189 190 if ! grep "the_answer" "./out/soong/workspace/foo/convertible_soong_module/${GENERATED_BUILD_FILE_NAME}"; then 191 fail "missing BUILD target the_answer in convertible_soong_module/${GENERATED_BUILD_FILE_NAME}" 192 fi 193 194 if grep "not_the_answer" "./out/soong/workspace/foo/unconvertible_soong_module/${GENERATED_BUILD_FILE_NAME}"; then 195 fail "found unexpected BUILD target not_the_answer in unconvertible_soong_module/${GENERATED_BUILD_FILE_NAME}" 196 fi 197 198 if ! grep "filegroup" "./out/soong/workspace/foo/unconvertible_soong_module/${GENERATED_BUILD_FILE_NAME}"; then 199 fail "missing filegroup in unconvertible_soong_module/${GENERATED_BUILD_FILE_NAME}" 200 fi 201 202 # NOTE: We don't actually use the extra BUILD file for anything here 203 run_bazel build --config=android --config=bp2build --config=ci //foo/... 204 205 local -r the_answer_file="$(find -L bazel-out -name the_answer.txt)" 206 if [[ ! -f "${the_answer_file}" ]]; then 207 fail "Expected the_answer.txt to be generated, but was missing" 208 fi 209 if ! grep 42 "${the_answer_file}"; then 210 fail "Expected to find 42 in '${the_answer_file}'" 211 fi 212} 213 214function test_bp2build_generates_all_buildfiles { 215 _save_trap=$(trap -p EXIT) 216 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 217 _bp2build_generates_all_buildfiles 218 eval "${_save_trap}" 219} 220 221function test_bp2build_symlinks_files { 222 setup 223 mkdir -p foo 224 touch foo/BLANK1 225 touch foo/BLANK2 226 touch foo/F2D 227 touch foo/BUILD 228 229 run_soong bp2build 230 231 if [[ -e "./out/soong/workspace/foo/BUILD" ]]; then 232 fail "./out/soong/workspace/foo/BUILD should be omitted" 233 fi 234 for file in BLANK1 BLANK2 F2D 235 do 236 if [[ ! -L "./out/soong/workspace/foo/$file" ]]; then 237 fail "./out/soong/workspace/foo/$file should exist" 238 fi 239 done 240 local -r BLANK1_BEFORE=$(stat -c %y "./out/soong/workspace/foo/BLANK1") 241 242 rm foo/BLANK2 243 rm foo/F2D 244 mkdir foo/F2D 245 touch foo/F2D/BUILD 246 247 run_soong bp2build 248 249 if [[ -e "./out/soong/workspace/foo/BUILD" ]]; then 250 fail "./out/soong/workspace/foo/BUILD should be omitted" 251 fi 252 local -r BLANK1_AFTER=$(stat -c %y "./out/soong/workspace/foo/BLANK1") 253 if [[ "$BLANK1_AFTER" != "$BLANK1_BEFORE" ]]; then 254 fail "./out/soong/workspace/foo/BLANK1 should be untouched" 255 fi 256 if [[ -e "./out/soong/workspace/foo/BLANK2" ]]; then 257 fail "./out/soong/workspace/foo/BLANK2 should be removed" 258 fi 259 if [[ -L "./out/soong/workspace/foo/F2D" ]] || [[ ! -d "./out/soong/workspace/foo/F2D" ]]; then 260 fail "./out/soong/workspace/foo/F2D should be a dir" 261 fi 262} 263 264function test_cc_correctness { 265 setup 266 267 mkdir -p a 268 cat > a/Android.bp <<EOF 269cc_object { 270 name: "qq", 271 srcs: ["qq.cc"], 272 bazel_module: { 273 bp2build_available: true, 274 }, 275 stl: "none", 276 system_shared_libs: [], 277} 278EOF 279 280 cat > a/qq.cc <<EOF 281#include "qq.h" 282int qq() { 283 return QQ; 284} 285EOF 286 287 cat > a/qq.h <<EOF 288#define QQ 1 289EOF 290 291 run_soong bp2build 292 293 run_bazel build --config=android --config=bp2build --config=ci //a:qq 294 local -r output_mtime1=$(stat -c "%y" bazel-bin/a/_objs/qq/qq.o) 295 296 run_bazel build --config=android --config=bp2build --config=ci //a:qq 297 local -r output_mtime2=$(stat -c "%y" bazel-bin/a/_objs/qq/qq.o) 298 299 if [[ "$output_mtime1" != "$output_mtime2" ]]; then 300 fail "output changed on null build" 301 fi 302 303 cat > a/qq.h <<EOF 304#define QQ 2 305EOF 306 307 run_bazel build --config=android --config=bp2build --config=ci //a:qq 308 local -r output_mtime3=$(stat -c "%y" bazel-bin/a/_objs/qq/qq.o) 309 310 if [[ "$output_mtime1" == "$output_mtime3" ]]; then 311 fail "output not changed when included header changed" 312 fi 313} 314 315# Regression test for the following failure during symlink forest creation: 316# 317# Cannot stat '/tmp/st.rr054/foo/bar/unresolved_symlink': stat /tmp/st.rr054/foo/bar/unresolved_symlink: no such file or directory 318# 319function test_bp2build_null_build_with_unresolved_symlink_in_source() { 320 setup 321 322 mkdir -p foo/bar 323 ln -s /tmp/non-existent foo/bar/unresolved_symlink 324 cat > foo/bar/Android.bp <<'EOF' 325filegroup { 326 name: "fg", 327 srcs: ["unresolved_symlink/non-existent-file.txt"], 328 } 329EOF 330 331 run_soong bp2build 332 333 dest=$(readlink -f out/soong/workspace/foo/bar/unresolved_symlink) 334 if [[ "$dest" != "/tmp/non-existent" ]]; then 335 fail "expected to plant an unresolved symlink out/soong/workspace/foo/bar/unresolved_symlink that resolves to /tmp/non-existent" 336 fi 337} 338 339# Smoke test to verify api_bp2build worksapce does not contain any errors 340function test_api_bp2build_empty_build() { 341 setup 342 run_soong api_bp2build 343 run_bazel build --config=android --config=api_bp2build //:empty 344} 345 346# Verify that an *_api_contribution target can refer to an api file from 347# another Bazel package. 348function test_api_export_from_another_bazel_package() { 349 setup 350 # Parent dir Android.bp 351 mkdir -p foo 352 cat > foo/Android.bp << 'EOF' 353cc_library { 354 name: "libfoo", 355 stubs: { 356 symbol_file: "api/libfoo.map.txt", 357 }, 358} 359EOF 360 # Child dir Android.bp 361 mkdir -p foo/api 362 cat > foo/api/Android.bp << 'EOF' 363package{} 364EOF 365 touch foo/api/libfoo.map.txt 366 # Run test 367 run_soong api_bp2build 368 run_bazel build --config=android --config=api_bp2build //foo:libfoo.contribution 369} 370 371scan_and_run_tests 372