1#!/bin/bash -eu 2 3set -o pipefail 4 5# This test exercises the bootstrapping process of the build system 6# in a source tree that only contains enough files for Bazel and Soong to work. 7 8source "$(dirname "$0")/lib.sh" 9 10readonly GENERATED_BUILD_FILE_NAME="BUILD.bazel" 11 12function test_smoke { 13 setup 14 run_soong 15} 16 17function test_null_build() { 18 setup 19 run_soong 20 local -r bootstrap_mtime1=$(stat -c "%y" out/soong/bootstrap.ninja) 21 local -r output_mtime1=$(stat -c "%y" out/soong/build.ninja) 22 run_soong 23 local -r bootstrap_mtime2=$(stat -c "%y" out/soong/bootstrap.ninja) 24 local -r output_mtime2=$(stat -c "%y" out/soong/build.ninja) 25 26 if [[ "$bootstrap_mtime1" == "$bootstrap_mtime2" ]]; then 27 # Bootstrapping is always done. It doesn't take a measurable amount of time. 28 fail "Bootstrap Ninja file did not change on null build" 29 fi 30 31 if [[ "$output_mtime1" != "$output_mtime2" ]]; then 32 fail "Output Ninja file changed on null build" 33 fi 34} 35 36function test_soong_build_rebuilt_if_blueprint_changes() { 37 setup 38 run_soong 39 local -r mtime1=$(stat -c "%y" out/soong/bootstrap.ninja) 40 41 sed -i 's/pluginGenSrcCmd/pluginGenSrcCmd2/g' build/blueprint/bootstrap/bootstrap.go 42 43 run_soong 44 local -r mtime2=$(stat -c "%y" out/soong/bootstrap.ninja) 45 46 if [[ "$mtime1" == "$mtime2" ]]; then 47 fail "Bootstrap Ninja file did not change" 48 fi 49} 50 51function test_change_android_bp() { 52 setup 53 mkdir -p a 54 cat > a/Android.bp <<'EOF' 55python_binary_host { 56 name: "my_little_binary_host", 57 srcs: ["my_little_binary_host.py"] 58} 59EOF 60 touch a/my_little_binary_host.py 61 run_soong 62 63 grep -q "^# Module:.*my_little_binary_host" out/soong/build.ninja || fail "module not found" 64 65 cat > a/Android.bp <<'EOF' 66python_binary_host { 67 name: "my_great_binary_host", 68 srcs: ["my_great_binary_host.py"] 69} 70EOF 71 touch a/my_great_binary_host.py 72 run_soong 73 74 grep -q "^# Module:.*my_little_binary_host" out/soong/build.ninja && fail "old module found" 75 grep -q "^# Module:.*my_great_binary_host" out/soong/build.ninja || fail "new module not found" 76} 77 78function test_add_android_bp() { 79 setup 80 run_soong 81 local -r mtime1=$(stat -c "%y" out/soong/build.ninja) 82 83 mkdir -p a 84 cat > a/Android.bp <<'EOF' 85python_binary_host { 86 name: "my_little_binary_host", 87 srcs: ["my_little_binary_host.py"] 88} 89EOF 90 touch a/my_little_binary_host.py 91 run_soong 92 93 local -r mtime2=$(stat -c "%y" out/soong/build.ninja) 94 if [[ "$mtime1" == "$mtime2" ]]; then 95 fail "Output Ninja file did not change" 96 fi 97 98 grep -q "^# Module:.*my_little_binary_host$" out/soong/build.ninja || fail "New module not in output" 99 100 run_soong 101} 102 103function test_delete_android_bp() { 104 setup 105 mkdir -p a 106 cat > a/Android.bp <<'EOF' 107python_binary_host { 108 name: "my_little_binary_host", 109 srcs: ["my_little_binary_host.py"] 110} 111EOF 112 touch a/my_little_binary_host.py 113 run_soong 114 115 grep -q "^# Module:.*my_little_binary_host$" out/soong/build.ninja || fail "Module not in output" 116 117 rm a/Android.bp 118 run_soong 119 120 if grep -q "^# Module:.*my_little_binary_host$" out/soong/build.ninja; then 121 fail "Old module in output" 122 fi 123} 124 125# Test that an incremental build with a glob doesn't rerun soong_build, and 126# only regenerates the globs on the first but not the second incremental build. 127function test_glob_noop_incremental() { 128 setup 129 130 # This test needs to start from a clean build, but setup creates an 131 # initialized tree that has already been built once. Clear the out 132 # directory to start from scratch (see b/185591972) 133 rm -rf out 134 135 mkdir -p a 136 cat > a/Android.bp <<'EOF' 137python_binary_host { 138 name: "my_little_binary_host", 139 srcs: ["*.py"], 140} 141EOF 142 touch a/my_little_binary_host.py 143 run_soong 144 local -r ninja_mtime1=$(stat -c "%y" out/soong/build.ninja) 145 146 local glob_deps_file=out/soong/globs/build/0.d 147 148 if [ -e "$glob_deps_file" ]; then 149 fail "Glob deps file unexpectedly written on first build" 150 fi 151 152 run_soong 153 local -r ninja_mtime2=$(stat -c "%y" out/soong/build.ninja) 154 155 # There is an ineffiencency in glob that requires bpglob to rerun once for each glob to update 156 # the entry in the .ninja_log. It doesn't update the output file, but we can detect the rerun 157 # by checking if the deps file was created. 158 if [ ! -e "$glob_deps_file" ]; then 159 fail "Glob deps file missing after second build" 160 fi 161 162 local -r glob_deps_mtime2=$(stat -c "%y" "$glob_deps_file") 163 164 if [[ "$ninja_mtime1" != "$ninja_mtime2" ]]; then 165 fail "Ninja file rewritten on null incremental build" 166 fi 167 168 run_soong 169 local -r ninja_mtime3=$(stat -c "%y" out/soong/build.ninja) 170 local -r glob_deps_mtime3=$(stat -c "%y" "$glob_deps_file") 171 172 if [[ "$ninja_mtime2" != "$ninja_mtime3" ]]; then 173 fail "Ninja file rewritten on null incremental build" 174 fi 175 176 # The bpglob commands should not rerun after the first incremental build. 177 if [[ "$glob_deps_mtime2" != "$glob_deps_mtime3" ]]; then 178 fail "Glob deps file rewritten on second null incremental build" 179 fi 180} 181 182function test_add_file_to_glob() { 183 setup 184 185 mkdir -p a 186 cat > a/Android.bp <<'EOF' 187python_binary_host { 188 name: "my_little_binary_host", 189 srcs: ["*.py"], 190} 191EOF 192 touch a/my_little_binary_host.py 193 run_soong 194 local -r mtime1=$(stat -c "%y" out/soong/build.ninja) 195 196 touch a/my_little_library.py 197 run_soong 198 199 local -r mtime2=$(stat -c "%y" out/soong/build.ninja) 200 if [[ "$mtime1" == "$mtime2" ]]; then 201 fail "Output Ninja file did not change" 202 fi 203 204 grep -q my_little_library.py out/soong/build.ninja || fail "new file is not in output" 205} 206 207function test_soong_build_rerun_iff_environment_changes() { 208 setup 209 210 mkdir -p cherry 211 cat > cherry/Android.bp <<'EOF' 212bootstrap_go_package { 213 name: "cherry", 214 pkgPath: "android/soong/cherry", 215 deps: [ 216 "blueprint", 217 "soong", 218 "soong-android", 219 ], 220 srcs: [ 221 "cherry.go", 222 ], 223 pluginFor: ["soong_build"], 224} 225EOF 226 227 cat > cherry/cherry.go <<'EOF' 228package cherry 229 230import ( 231 "android/soong/android" 232 "github.com/google/blueprint" 233) 234 235var ( 236 pctx = android.NewPackageContext("cherry") 237) 238 239func init() { 240 android.RegisterSingletonType("cherry", CherrySingleton) 241} 242 243func CherrySingleton() android.Singleton { 244 return &cherrySingleton{} 245} 246 247type cherrySingleton struct{} 248 249func (p *cherrySingleton) GenerateBuildActions(ctx android.SingletonContext) { 250 cherryRule := ctx.Rule(pctx, "cherry", 251 blueprint.RuleParams{ 252 Command: "echo CHERRY IS " + ctx.Config().Getenv("CHERRY") + " > ${out}", 253 CommandDeps: []string{}, 254 Description: "Cherry", 255 }) 256 257 outputFile := android.PathForOutput(ctx, "cherry", "cherry.txt") 258 var deps android.Paths 259 260 ctx.Build(pctx, android.BuildParams{ 261 Rule: cherryRule, 262 Output: outputFile, 263 Inputs: deps, 264 }) 265} 266EOF 267 268 export CHERRY=TASTY 269 run_soong 270 grep -q "CHERRY IS TASTY" out/soong/build.ninja \ 271 || fail "first value of environment variable is not used" 272 273 export CHERRY=RED 274 run_soong 275 grep -q "CHERRY IS RED" out/soong/build.ninja \ 276 || fail "second value of environment variable not used" 277 local -r mtime1=$(stat -c "%y" out/soong/build.ninja) 278 279 run_soong 280 local -r mtime2=$(stat -c "%y" out/soong/build.ninja) 281 if [[ "$mtime1" != "$mtime2" ]]; then 282 fail "Output Ninja file changed when environment variable did not" 283 fi 284 285} 286 287function test_create_global_include_directory() { 288 setup 289 run_soong 290 local -r mtime1=$(stat -c "%y" out/soong/build.ninja) 291 292 # Soong needs to know if top level directories like hardware/ exist for use 293 # as global include directories. Make sure that doesn't cause regens for 294 # unrelated changes to the top level directory. 295 mkdir -p system/core 296 297 run_soong 298 local -r mtime2=$(stat -c "%y" out/soong/build.ninja) 299 if [[ "$mtime1" != "$mtime2" ]]; then 300 fail "Output Ninja file changed when top level directory changed" 301 fi 302 303 # Make sure it does regen if a missing directory in the path of a global 304 # include directory is added. 305 mkdir -p system/core/include 306 307 run_soong 308 local -r mtime3=$(stat -c "%y" out/soong/build.ninja) 309 if [[ "$mtime2" = "$mtime3" ]]; then 310 fail "Output Ninja file did not change when global include directory created" 311 fi 312 313} 314 315function test_add_file_to_soong_build() { 316 setup 317 run_soong 318 local -r mtime1=$(stat -c "%y" out/soong/build.ninja) 319 320 mkdir -p a 321 cat > a/Android.bp <<'EOF' 322bootstrap_go_package { 323 name: "picard-soong-rules", 324 pkgPath: "android/soong/picard", 325 deps: [ 326 "blueprint", 327 "soong", 328 "soong-android", 329 ], 330 srcs: [ 331 "picard.go", 332 ], 333 pluginFor: ["soong_build"], 334} 335EOF 336 337 cat > a/picard.go <<'EOF' 338package picard 339 340import ( 341 "android/soong/android" 342 "github.com/google/blueprint" 343) 344 345var ( 346 pctx = android.NewPackageContext("picard") 347) 348 349func init() { 350 android.RegisterSingletonType("picard", PicardSingleton) 351} 352 353func PicardSingleton() android.Singleton { 354 return &picardSingleton{} 355} 356 357type picardSingleton struct{} 358 359func (p *picardSingleton) GenerateBuildActions(ctx android.SingletonContext) { 360 picardRule := ctx.Rule(pctx, "picard", 361 blueprint.RuleParams{ 362 Command: "echo Make it so. > ${out}", 363 CommandDeps: []string{}, 364 Description: "Something quotable", 365 }) 366 367 outputFile := android.PathForOutput(ctx, "picard", "picard.txt") 368 var deps android.Paths 369 370 ctx.Build(pctx, android.BuildParams{ 371 Rule: picardRule, 372 Output: outputFile, 373 Inputs: deps, 374 }) 375} 376 377EOF 378 379 run_soong 380 local -r mtime2=$(stat -c "%y" out/soong/build.ninja) 381 if [[ "$mtime1" == "$mtime2" ]]; then 382 fail "Output Ninja file did not change" 383 fi 384 385 grep -q "Make it so" out/soong/build.ninja || fail "New action not present" 386} 387 388# Tests a glob in a build= statement in an Android.bp file, which is interpreted 389# during bootstrapping. 390function test_glob_during_bootstrapping() { 391 setup 392 393 mkdir -p a 394 cat > a/Android.bp <<'EOF' 395build=["foo*.bp"] 396EOF 397 cat > a/fooa.bp <<'EOF' 398bootstrap_go_package { 399 name: "picard-soong-rules", 400 pkgPath: "android/soong/picard", 401 deps: [ 402 "blueprint", 403 "soong", 404 "soong-android", 405 ], 406 srcs: [ 407 "picard.go", 408 ], 409 pluginFor: ["soong_build"], 410} 411EOF 412 413 cat > a/picard.go <<'EOF' 414package picard 415 416import ( 417 "android/soong/android" 418 "github.com/google/blueprint" 419) 420 421var ( 422 pctx = android.NewPackageContext("picard") 423) 424 425func init() { 426 android.RegisterSingletonType("picard", PicardSingleton) 427} 428 429func PicardSingleton() android.Singleton { 430 return &picardSingleton{} 431} 432 433type picardSingleton struct{} 434 435var Message = "Make it so." 436 437func (p *picardSingleton) GenerateBuildActions(ctx android.SingletonContext) { 438 picardRule := ctx.Rule(pctx, "picard", 439 blueprint.RuleParams{ 440 Command: "echo " + Message + " > ${out}", 441 CommandDeps: []string{}, 442 Description: "Something quotable", 443 }) 444 445 outputFile := android.PathForOutput(ctx, "picard", "picard.txt") 446 var deps android.Paths 447 448 ctx.Build(pctx, android.BuildParams{ 449 Rule: picardRule, 450 Output: outputFile, 451 Inputs: deps, 452 }) 453} 454 455EOF 456 457 run_soong 458 local -r mtime1=$(stat -c "%y" out/soong/build.ninja) 459 460 grep -q "Make it so" out/soong/build.ninja || fail "Original action not present" 461 462 cat > a/foob.bp <<'EOF' 463bootstrap_go_package { 464 name: "worf-soong-rules", 465 pkgPath: "android/soong/worf", 466 deps: [ 467 "blueprint", 468 "soong", 469 "soong-android", 470 "picard-soong-rules", 471 ], 472 srcs: [ 473 "worf.go", 474 ], 475 pluginFor: ["soong_build"], 476} 477EOF 478 479 cat > a/worf.go <<'EOF' 480package worf 481 482import "android/soong/picard" 483 484func init() { 485 picard.Message = "Engage." 486} 487EOF 488 489 run_soong 490 local -r mtime2=$(stat -c "%y" out/soong/build.ninja) 491 if [[ "$mtime1" == "$mtime2" ]]; then 492 fail "Output Ninja file did not change" 493 fi 494 495 grep -q "Engage" out/soong/build.ninja || fail "New action not present" 496 497 if grep -q "Make it so" out/soong/build.ninja; then 498 fail "Original action still present" 499 fi 500} 501 502function test_soong_docs_smoke() { 503 setup 504 505 run_soong soong_docs 506 507 [[ -e "out/soong/docs/soong_build.html" ]] || fail "Documentation for main page not created" 508 [[ -e "out/soong/docs/cc.html" ]] || fail "Documentation for C++ modules not created" 509} 510 511function test_null_build_after_soong_docs() { 512 setup 513 514 run_soong 515 local -r ninja_mtime1=$(stat -c "%y" out/soong/build.ninja) 516 517 run_soong soong_docs 518 local -r docs_mtime1=$(stat -c "%y" out/soong/docs/soong_build.html) 519 520 run_soong soong_docs 521 local -r docs_mtime2=$(stat -c "%y" out/soong/docs/soong_build.html) 522 523 if [[ "$docs_mtime1" != "$docs_mtime2" ]]; then 524 fail "Output Ninja file changed on null build" 525 fi 526 527 run_soong 528 local -r ninja_mtime2=$(stat -c "%y" out/soong/build.ninja) 529 530 if [[ "$ninja_mtime1" != "$ninja_mtime2" ]]; then 531 fail "Output Ninja file changed on null build" 532 fi 533} 534 535function test_write_to_source_tree { 536 setup 537 mkdir -p a 538 cat > a/Android.bp <<EOF 539genrule { 540 name: "write_to_source_tree", 541 out: ["write_to_source_tree"], 542 cmd: "touch file_in_source_tree && touch \$(out)", 543} 544EOF 545 readonly EXPECTED_OUT=out/soong/.intermediates/a/write_to_source_tree/gen/write_to_source_tree 546 readonly ERROR_LOG=${MOCK_TOP}/out/error.log 547 readonly ERROR_MSG="Read-only file system" 548 readonly ERROR_HINT_PATTERN="BUILD_BROKEN_SRC_DIR" 549 # Test in ReadOnly source tree 550 run_ninja BUILD_BROKEN_SRC_DIR_IS_WRITABLE=false ${EXPECTED_OUT} &> /dev/null && \ 551 fail "Write to source tree should not work in a ReadOnly source tree" 552 553 if grep -q "${ERROR_MSG}" "${ERROR_LOG}" && grep -q "${ERROR_HINT_PATTERN}" "${ERROR_LOG}" ; then 554 echo Error message and error hint found in logs >/dev/null 555 else 556 fail "Did not find Read-only error AND error hint in error.log" 557 fi 558 559 # Test in ReadWrite source tree 560 run_ninja BUILD_BROKEN_SRC_DIR_IS_WRITABLE=true ${EXPECTED_OUT} &> /dev/null || \ 561 fail "Write to source tree did not succeed in a ReadWrite source tree" 562 563 if grep -q "${ERROR_MSG}\|${ERROR_HINT_PATTERN}" "${ERROR_LOG}" ; then 564 fail "Found read-only error OR error hint in error.log" 565 fi 566} 567 568function test_bp2build_smoke { 569 setup 570 run_soong bp2build 571 [[ -e out/soong/bp2build_workspace_marker ]] || fail "bp2build marker file not created" 572 [[ -e out/soong/workspace ]] || fail "Bazel workspace not created" 573} 574 575function test_bp2build_generates_marker_file { 576 setup 577 578 run_soong bp2build 579 580 if [[ ! -f "./out/soong/bp2build_files_marker" ]]; then 581 fail "bp2build marker file was not generated" 582 fi 583 584 if [[ ! -f "./out/soong/bp2build_workspace_marker" ]]; then 585 fail "symlink forest marker file was not generated" 586 fi 587} 588 589function test_bp2build_add_irrelevant_file { 590 setup 591 592 mkdir -p a/b 593 touch a/b/c.txt 594 cat > a/b/Android.bp <<'EOF' 595filegroup { 596 name: "c", 597 srcs: ["c.txt"], 598 bazel_module: { bp2build_available: true }, 599} 600EOF 601 602 run_soong bp2build 603 if [[ ! -e out/soong/bp2build/a/b/BUILD.bazel ]]; then 604 fail "BUILD file in symlink forest was not created"; 605 fi 606 607 local -r mtime1=$(stat -c "%y" out/soong/bp2build/a/b/BUILD.bazel) 608 609 touch a/irrelevant.txt 610 run_soong bp2build 611 local -r mtime2=$(stat -c "%y" out/soong/bp2build/a/b/BUILD.bazel) 612 613 if [[ "$mtime1" != "$mtime2" ]]; then 614 fail "BUILD.bazel file was regenerated" 615 fi 616 617 if [[ ! -e "out/soong/workspace/a/irrelevant.txt" ]]; then 618 fail "New file was not symlinked into symlink forest" 619 fi 620} 621 622function test_bp2build_add_android_bp { 623 setup 624 625 mkdir -p a 626 touch a/a.txt 627 cat > a/Android.bp <<'EOF' 628filegroup { 629 name: "a", 630 srcs: ["a.txt"], 631 bazel_module: { bp2build_available: true }, 632} 633EOF 634 635 run_soong bp2build 636 [[ -e out/soong/bp2build/a/${GENERATED_BUILD_FILE_NAME} ]] || fail "a/${GENERATED_BUILD_FILE_NAME} not created" 637 [[ -L out/soong/workspace/a/${GENERATED_BUILD_FILE_NAME} ]] || fail "a/${GENERATED_BUILD_FILE_NAME} not symlinked" 638 639 mkdir -p b 640 touch b/b.txt 641 cat > b/Android.bp <<'EOF' 642filegroup { 643 name: "b", 644 srcs: ["b.txt"], 645 bazel_module: { bp2build_available: true }, 646} 647EOF 648 649 run_soong bp2build 650 [[ -e out/soong/bp2build/b/${GENERATED_BUILD_FILE_NAME} ]] || fail "a/${GENERATED_BUILD_FILE_NAME} not created" 651 [[ -L out/soong/workspace/b/${GENERATED_BUILD_FILE_NAME} ]] || fail "a/${GENERATED_BUILD_FILE_NAME} not symlinked" 652} 653 654function test_bp2build_null_build { 655 setup 656 657 run_soong bp2build 658 local -r mtime1=$(stat -c "%y" out/soong/bp2build_workspace_marker) 659 660 run_soong bp2build 661 local -r mtime2=$(stat -c "%y" out/soong/bp2build_workspace_marker) 662 663 if [[ "$mtime1" != "$mtime2" ]]; then 664 fail "Output Ninja file changed on null build" 665 fi 666} 667 668function test_bp2build_add_to_glob { 669 setup 670 671 mkdir -p a 672 touch a/a1.txt 673 cat > a/Android.bp <<'EOF' 674filegroup { 675 name: "a", 676 srcs: ["*.txt"], 677 bazel_module: { bp2build_available: true }, 678} 679EOF 680 681 run_soong bp2build 682 grep -q a1.txt "out/soong/bp2build/a/${GENERATED_BUILD_FILE_NAME}" || fail "a1.txt not in ${GENERATED_BUILD_FILE_NAME} file" 683 684 touch a/a2.txt 685 run_soong bp2build 686 grep -q a2.txt "out/soong/bp2build/a/${GENERATED_BUILD_FILE_NAME}" || fail "a2.txt not in ${GENERATED_BUILD_FILE_NAME} file" 687} 688 689function test_multiple_soong_build_modes() { 690 setup 691 run_soong json-module-graph bp2build nothing 692 if [[ ! -f "out/soong/bp2build_workspace_marker" ]]; then 693 fail "bp2build marker file was not generated" 694 fi 695 696 697 if [[ ! -f "out/soong/module-graph.json" ]]; then 698 fail "JSON file was not created" 699 fi 700 701 if [[ ! -f "out/soong/build.ninja" ]]; then 702 fail "Main build.ninja file was not created" 703 fi 704} 705 706function test_dump_json_module_graph() { 707 setup 708 run_soong json-module-graph 709 if [[ ! -r "out/soong/module-graph.json" ]]; then 710 fail "JSON file was not created" 711 fi 712} 713 714function test_json_module_graph_back_and_forth_null_build() { 715 setup 716 717 run_soong 718 local -r ninja_mtime1=$(stat -c "%y" out/soong/build.ninja) 719 720 run_soong json-module-graph 721 local -r json_mtime1=$(stat -c "%y" out/soong/module-graph.json) 722 723 run_soong 724 local -r ninja_mtime2=$(stat -c "%y" out/soong/build.ninja) 725 if [[ "$ninja_mtime1" != "$ninja_mtime2" ]]; then 726 fail "Output Ninja file changed after writing JSON module graph" 727 fi 728 729 run_soong json-module-graph 730 local -r json_mtime2=$(stat -c "%y" out/soong/module-graph.json) 731 if [[ "$json_mtime1" != "$json_mtime2" ]]; then 732 fail "JSON module graph file changed after writing Ninja file" 733 fi 734 735} 736 737function test_bp2build_bazel_workspace_structure { 738 setup 739 740 mkdir -p a/b 741 touch a/a.txt 742 touch a/b/b.txt 743 cat > a/b/Android.bp <<'EOF' 744filegroup { 745 name: "b", 746 srcs: ["b.txt"], 747 bazel_module: { bp2build_available: true }, 748} 749EOF 750 751 run_soong bp2build 752 [[ -e out/soong/workspace ]] || fail "Bazel workspace not created" 753 [[ -d out/soong/workspace/a/b ]] || fail "module directory not a directory" 754 [[ -L "out/soong/workspace/a/b/${GENERATED_BUILD_FILE_NAME}" ]] || fail "${GENERATED_BUILD_FILE_NAME} file not symlinked" 755 [[ "$(readlink -f out/soong/workspace/a/b/${GENERATED_BUILD_FILE_NAME})" =~ "bp2build/a/b/${GENERATED_BUILD_FILE_NAME}"$ ]] \ 756 || fail "BUILD files symlinked at the wrong place" 757 [[ -L out/soong/workspace/a/b/b.txt ]] || fail "a/b/b.txt not symlinked" 758 [[ -L out/soong/workspace/a/a.txt ]] || fail "a/b/a.txt not symlinked" 759 [[ ! -e out/soong/workspace/out ]] || fail "out directory symlinked" 760} 761 762function test_bp2build_bazel_workspace_add_file { 763 setup 764 765 mkdir -p a 766 touch a/a.txt 767 cat > a/Android.bp <<EOF 768filegroup { 769 name: "a", 770 srcs: ["a.txt"], 771 bazel_module: { bp2build_available: true }, 772} 773EOF 774 775 run_soong bp2build 776 777 touch a/a2.txt # No reference in the .bp file needed 778 run_soong bp2build 779 [[ -L out/soong/workspace/a/a2.txt ]] || fail "a/a2.txt not symlinked" 780} 781 782function test_bp2build_build_file_precedence { 783 setup 784 785 mkdir -p a 786 touch a/a.txt 787 touch a/${GENERATED_BUILD_FILE_NAME} 788 cat > a/Android.bp <<EOF 789filegroup { 790 name: "a", 791 srcs: ["a.txt"], 792 bazel_module: { bp2build_available: true }, 793} 794EOF 795 796 run_soong bp2build 797 [[ -L "out/soong/workspace/a/${GENERATED_BUILD_FILE_NAME}" ]] || fail "${GENERATED_BUILD_FILE_NAME} file not symlinked" 798 [[ "$(readlink -f out/soong/workspace/a/${GENERATED_BUILD_FILE_NAME})" =~ "bp2build/a/${GENERATED_BUILD_FILE_NAME}"$ ]] \ 799 || fail "${GENERATED_BUILD_FILE_NAME} files symlinked to the wrong place" 800} 801 802function test_bp2build_fails_fast { 803 setup 804 805 mkdir -p "a/${GENERATED_BUILD_FILE_NAME}" 806 cat > a/Android.bp <<EOF 807filegroup { 808 name: "a", 809 srcs: ["a.txt"], 810 bazel_module: { bp2build_available: true }, 811} 812EOF 813 814 mkdir -p "b/${GENERATED_BUILD_FILE_NAME}" 815 cat > b/Android.bp <<EOF 816filegroup { 817 name: "b", 818 srcs: ["b.txt"], 819 bazel_module: { bp2build_available: true }, 820} 821EOF 822 823 if run_soong bp2build >& "$MOCK_TOP/errors"; then 824 fail "Build should have failed" 825 fi 826 827 # we should expect at least one error 828 grep -q -E "(a|b)/${GENERATED_BUILD_FILE_NAME}' exist" "$MOCK_TOP/errors" || fail "Error for ${GENERATED_BUILD_FILE_NAME} not found" 829} 830 831function test_bp2build_back_and_forth_null_build { 832 setup 833 834 run_soong 835 local -r output_mtime1=$(stat -c "%y" out/soong/build.ninja) 836 837 run_soong bp2build 838 local -r output_mtime2=$(stat -c "%y" out/soong/build.ninja) 839 if [[ "$output_mtime1" != "$output_mtime2" ]]; then 840 fail "Output Ninja file changed when switching to bp2build" 841 fi 842 843 local -r marker_mtime1=$(stat -c "%y" out/soong/bp2build_workspace_marker) 844 845 run_soong 846 local -r output_mtime3=$(stat -c "%y" out/soong/build.ninja) 847 local -r marker_mtime2=$(stat -c "%y" out/soong/bp2build_workspace_marker) 848 if [[ "$output_mtime1" != "$output_mtime3" ]]; then 849 fail "Output Ninja file changed when switching to regular build from bp2build" 850 fi 851 if [[ "$marker_mtime1" != "$marker_mtime2" ]]; then 852 fail "bp2build marker file changed when switching to regular build from bp2build" 853 fi 854 855 run_soong bp2build 856 local -r output_mtime4=$(stat -c "%y" out/soong/build.ninja) 857 local -r marker_mtime3=$(stat -c "%y" out/soong/bp2build_workspace_marker) 858 if [[ "$output_mtime1" != "$output_mtime4" ]]; then 859 fail "Output Ninja file changed when switching back to bp2build" 860 fi 861 if [[ "$marker_mtime1" != "$marker_mtime3" ]]; then 862 fail "bp2build marker file changed when switching back to bp2build" 863 fi 864} 865 866function test_queryview_smoke() { 867 setup 868 869 run_soong queryview 870 [[ -e out/soong/queryview/WORKSPACE ]] || fail "queryview WORKSPACE file not created" 871 872} 873 874function test_queryview_null_build() { 875 setup 876 877 run_soong queryview 878 local -r output_mtime1=$(stat -c "%y" out/soong/queryview.marker) 879 880 run_soong queryview 881 local -r output_mtime2=$(stat -c "%y" out/soong/queryview.marker) 882 883 if [[ "$output_mtime1" != "$output_mtime2" ]]; then 884 fail "Queryview marker file changed on null build" 885 fi 886} 887 888# This test verifies that adding a new glob to a blueprint file only 889# causes build.ninja to be regenerated on the *next* build, and *not* 890# the build after. (This is a regression test for a bug where globs 891# resulted in two successive regenerations.) 892function test_new_glob_incrementality { 893 setup 894 895 run_soong nothing 896 local -r mtime1=$(stat -c "%y" out/soong/build.ninja) 897 898 mkdir -p globdefpkg/ 899 cat > globdefpkg/Android.bp <<'EOF' 900filegroup { 901 name: "fg_with_glob", 902 srcs: ["*.txt"], 903} 904EOF 905 906 run_soong nothing 907 local -r mtime2=$(stat -c "%y" out/soong/build.ninja) 908 909 if [[ "$mtime1" == "$mtime2" ]]; then 910 fail "Ninja file was not regenerated, despite a new bp file" 911 fi 912 913 run_soong nothing 914 local -r mtime3=$(stat -c "%y" out/soong/build.ninja) 915 916 if [[ "$mtime2" != "$mtime3" ]]; then 917 fail "Ninja file was regenerated despite no previous bp changes" 918 fi 919} 920 921scan_and_run_tests 922