bootstrap_test.sh 23 KB

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