prebuilt_etc_test.go 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535
  1. // Copyright 2018 Google Inc. All rights reserved.
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. package etc
  15. import (
  16. "fmt"
  17. "os"
  18. "path/filepath"
  19. "testing"
  20. "github.com/google/blueprint/proptools"
  21. "android/soong/android"
  22. "android/soong/bazel/cquery"
  23. "android/soong/snapshot"
  24. )
  25. func TestMain(m *testing.M) {
  26. os.Exit(m.Run())
  27. }
  28. var prepareForPrebuiltEtcTest = android.GroupFixturePreparers(
  29. android.PrepareForTestWithArchMutator,
  30. PrepareForTestWithPrebuiltEtc,
  31. android.FixtureMergeMockFs(android.MockFS{
  32. "foo.conf": nil,
  33. "bar.conf": nil,
  34. "baz.conf": nil,
  35. }),
  36. )
  37. var prepareForPrebuiltEtcSnapshotTest = android.GroupFixturePreparers(
  38. prepareForPrebuiltEtcTest,
  39. android.FixtureRegisterWithContext(func(ctx android.RegistrationContext) {
  40. snapshot.VendorSnapshotImageSingleton.Init(ctx)
  41. snapshot.RecoverySnapshotImageSingleton.Init(ctx)
  42. }),
  43. android.FixtureModifyConfig(func(config android.Config) {
  44. config.TestProductVariables.DeviceVndkVersion = proptools.StringPtr("current")
  45. config.TestProductVariables.RecoverySnapshotVersion = proptools.StringPtr("current")
  46. }),
  47. )
  48. func TestPrebuiltEtcVariants(t *testing.T) {
  49. result := prepareForPrebuiltEtcTest.RunTestWithBp(t, `
  50. prebuilt_etc {
  51. name: "foo.conf",
  52. src: "foo.conf",
  53. }
  54. prebuilt_etc {
  55. name: "bar.conf",
  56. src: "bar.conf",
  57. recovery_available: true,
  58. }
  59. prebuilt_etc {
  60. name: "baz.conf",
  61. src: "baz.conf",
  62. recovery: true,
  63. }
  64. `)
  65. foo_variants := result.ModuleVariantsForTests("foo.conf")
  66. if len(foo_variants) != 1 {
  67. t.Errorf("expected 1, got %#v", foo_variants)
  68. }
  69. bar_variants := result.ModuleVariantsForTests("bar.conf")
  70. if len(bar_variants) != 2 {
  71. t.Errorf("expected 2, got %#v", bar_variants)
  72. }
  73. baz_variants := result.ModuleVariantsForTests("baz.conf")
  74. if len(baz_variants) != 1 {
  75. t.Errorf("expected 1, got %#v", bar_variants)
  76. }
  77. }
  78. func TestPrebuiltEtcOutputPath(t *testing.T) {
  79. result := prepareForPrebuiltEtcTest.RunTestWithBp(t, `
  80. prebuilt_etc {
  81. name: "foo.conf",
  82. src: "foo.conf",
  83. filename: "foo.installed.conf",
  84. }
  85. `)
  86. p := result.Module("foo.conf", "android_arm64_armv8-a").(*PrebuiltEtc)
  87. android.AssertStringEquals(t, "output file path", "foo.installed.conf", p.outputFilePath.Base())
  88. }
  89. func TestPrebuiltEtcGlob(t *testing.T) {
  90. result := prepareForPrebuiltEtcTest.RunTestWithBp(t, `
  91. prebuilt_etc {
  92. name: "my_foo",
  93. src: "foo.*",
  94. }
  95. prebuilt_etc {
  96. name: "my_bar",
  97. src: "bar.*",
  98. filename_from_src: true,
  99. }
  100. `)
  101. p := result.Module("my_foo", "android_arm64_armv8-a").(*PrebuiltEtc)
  102. android.AssertStringEquals(t, "my_foo output file path", "my_foo", p.outputFilePath.Base())
  103. p = result.Module("my_bar", "android_arm64_armv8-a").(*PrebuiltEtc)
  104. android.AssertStringEquals(t, "my_bar output file path", "bar.conf", p.outputFilePath.Base())
  105. }
  106. func TestPrebuiltEtcAndroidMk(t *testing.T) {
  107. result := prepareForPrebuiltEtcTest.RunTestWithBp(t, `
  108. prebuilt_etc {
  109. name: "foo",
  110. src: "foo.conf",
  111. owner: "abc",
  112. filename_from_src: true,
  113. required: ["modA", "moduleB"],
  114. host_required: ["hostModA", "hostModB"],
  115. target_required: ["targetModA"],
  116. }
  117. `)
  118. expected := map[string][]string{
  119. "LOCAL_MODULE": {"foo"},
  120. "LOCAL_MODULE_CLASS": {"ETC"},
  121. "LOCAL_MODULE_OWNER": {"abc"},
  122. "LOCAL_INSTALLED_MODULE_STEM": {"foo.conf"},
  123. "LOCAL_REQUIRED_MODULES": {"modA", "moduleB"},
  124. "LOCAL_HOST_REQUIRED_MODULES": {"hostModA", "hostModB"},
  125. "LOCAL_TARGET_REQUIRED_MODULES": {"targetModA"},
  126. "LOCAL_SOONG_MODULE_TYPE": {"prebuilt_etc"},
  127. }
  128. mod := result.Module("foo", "android_arm64_armv8-a").(*PrebuiltEtc)
  129. entries := android.AndroidMkEntriesForTest(t, result.TestContext, mod)[0]
  130. for k, expectedValue := range expected {
  131. if value, ok := entries.EntryMap[k]; ok {
  132. android.AssertDeepEquals(t, k, expectedValue, value)
  133. } else {
  134. t.Errorf("No %s defined, saw %q", k, entries.EntryMap)
  135. }
  136. }
  137. }
  138. func TestPrebuiltEtcRelativeInstallPathInstallDirPath(t *testing.T) {
  139. result := prepareForPrebuiltEtcTest.RunTestWithBp(t, `
  140. prebuilt_etc {
  141. name: "foo.conf",
  142. src: "foo.conf",
  143. relative_install_path: "bar",
  144. }
  145. `)
  146. p := result.Module("foo.conf", "android_arm64_armv8-a").(*PrebuiltEtc)
  147. expected := "out/soong/target/product/test_device/system/etc/bar"
  148. android.AssertPathRelativeToTopEquals(t, "install dir", expected, p.installDirPath)
  149. }
  150. func TestPrebuiltEtcCannotSetRelativeInstallPathAndSubDir(t *testing.T) {
  151. prepareForPrebuiltEtcTest.
  152. ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern("relative_install_path is set. Cannot set sub_dir")).
  153. RunTestWithBp(t, `
  154. prebuilt_etc {
  155. name: "foo.conf",
  156. src: "foo.conf",
  157. sub_dir: "bar",
  158. relative_install_path: "bar",
  159. }
  160. `)
  161. }
  162. func TestPrebuiltEtcHost(t *testing.T) {
  163. result := prepareForPrebuiltEtcTest.RunTestWithBp(t, `
  164. prebuilt_etc_host {
  165. name: "foo.conf",
  166. src: "foo.conf",
  167. }
  168. `)
  169. buildOS := result.Config.BuildOS.String()
  170. p := result.Module("foo.conf", buildOS+"_common").(*PrebuiltEtc)
  171. if !p.Host() {
  172. t.Errorf("host bit is not set for a prebuilt_etc_host module.")
  173. }
  174. }
  175. func TestPrebuiltEtcAllowMissingDependencies(t *testing.T) {
  176. result := android.GroupFixturePreparers(
  177. prepareForPrebuiltEtcTest,
  178. android.PrepareForTestDisallowNonExistentPaths,
  179. android.FixtureModifyConfig(
  180. func(config android.Config) {
  181. config.TestProductVariables.Allow_missing_dependencies = proptools.BoolPtr(true)
  182. }),
  183. ).RunTestWithBp(t, `
  184. prebuilt_etc {
  185. name: "foo.conf",
  186. filename_from_src: true,
  187. arch: {
  188. x86: {
  189. src: "x86.conf",
  190. },
  191. },
  192. }
  193. `)
  194. android.AssertStringEquals(t, "expected error rule", "android/soong/android.Error",
  195. result.ModuleForTests("foo.conf", "android_arm64_armv8-a").Output("foo.conf").Rule.String())
  196. }
  197. func TestPrebuiltRootInstallDirPath(t *testing.T) {
  198. result := prepareForPrebuiltEtcTest.RunTestWithBp(t, `
  199. prebuilt_root {
  200. name: "foo.conf",
  201. src: "foo.conf",
  202. filename: "foo.conf",
  203. }
  204. `)
  205. p := result.Module("foo.conf", "android_arm64_armv8-a").(*PrebuiltEtc)
  206. expected := "out/soong/target/product/test_device/system"
  207. android.AssertPathRelativeToTopEquals(t, "install dir", expected, p.installDirPath)
  208. }
  209. func TestPrebuiltRootInstallDirPathValidate(t *testing.T) {
  210. prepareForPrebuiltEtcTest.ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern("filename cannot contain separator")).RunTestWithBp(t, `
  211. prebuilt_root {
  212. name: "foo.conf",
  213. src: "foo.conf",
  214. filename: "foo/bar.conf",
  215. }
  216. `)
  217. }
  218. func TestPrebuiltUserShareInstallDirPath(t *testing.T) {
  219. result := prepareForPrebuiltEtcTest.RunTestWithBp(t, `
  220. prebuilt_usr_share {
  221. name: "foo.conf",
  222. src: "foo.conf",
  223. sub_dir: "bar",
  224. }
  225. `)
  226. p := result.Module("foo.conf", "android_arm64_armv8-a").(*PrebuiltEtc)
  227. expected := "out/soong/target/product/test_device/system/usr/share/bar"
  228. android.AssertPathRelativeToTopEquals(t, "install dir", expected, p.installDirPath)
  229. }
  230. func TestPrebuiltUserShareHostInstallDirPath(t *testing.T) {
  231. result := prepareForPrebuiltEtcTest.RunTestWithBp(t, `
  232. prebuilt_usr_share_host {
  233. name: "foo.conf",
  234. src: "foo.conf",
  235. sub_dir: "bar",
  236. }
  237. `)
  238. buildOS := result.Config.BuildOS.String()
  239. p := result.Module("foo.conf", buildOS+"_common").(*PrebuiltEtc)
  240. expected := filepath.Join("out/soong/host", result.Config.PrebuiltOS(), "usr", "share", "bar")
  241. android.AssertPathRelativeToTopEquals(t, "install dir", expected, p.installDirPath)
  242. }
  243. func TestPrebuiltFontInstallDirPath(t *testing.T) {
  244. result := prepareForPrebuiltEtcTest.RunTestWithBp(t, `
  245. prebuilt_font {
  246. name: "foo.conf",
  247. src: "foo.conf",
  248. }
  249. `)
  250. p := result.Module("foo.conf", "android_arm64_armv8-a").(*PrebuiltEtc)
  251. expected := "out/soong/target/product/test_device/system/fonts"
  252. android.AssertPathRelativeToTopEquals(t, "install dir", expected, p.installDirPath)
  253. }
  254. func TestPrebuiltFirmwareDirPath(t *testing.T) {
  255. targetPath := "out/soong/target/product/test_device"
  256. tests := []struct {
  257. description string
  258. config string
  259. expectedPath string
  260. }{{
  261. description: "prebuilt: system firmware",
  262. config: `
  263. prebuilt_firmware {
  264. name: "foo.conf",
  265. src: "foo.conf",
  266. }`,
  267. expectedPath: filepath.Join(targetPath, "system/etc/firmware"),
  268. }, {
  269. description: "prebuilt: vendor firmware",
  270. config: `
  271. prebuilt_firmware {
  272. name: "foo.conf",
  273. src: "foo.conf",
  274. soc_specific: true,
  275. sub_dir: "sub_dir",
  276. }`,
  277. expectedPath: filepath.Join(targetPath, "vendor/firmware/sub_dir"),
  278. }}
  279. for _, tt := range tests {
  280. t.Run(tt.description, func(t *testing.T) {
  281. result := prepareForPrebuiltEtcTest.RunTestWithBp(t, tt.config)
  282. p := result.Module("foo.conf", "android_arm64_armv8-a").(*PrebuiltEtc)
  283. android.AssertPathRelativeToTopEquals(t, "install dir", tt.expectedPath, p.installDirPath)
  284. })
  285. }
  286. }
  287. func TestPrebuiltDSPDirPath(t *testing.T) {
  288. targetPath := "out/soong/target/product/test_device"
  289. tests := []struct {
  290. description string
  291. config string
  292. expectedPath string
  293. }{{
  294. description: "prebuilt: system dsp",
  295. config: `
  296. prebuilt_dsp {
  297. name: "foo.conf",
  298. src: "foo.conf",
  299. }`,
  300. expectedPath: filepath.Join(targetPath, "system/etc/dsp"),
  301. }, {
  302. description: "prebuilt: vendor dsp",
  303. config: `
  304. prebuilt_dsp {
  305. name: "foo.conf",
  306. src: "foo.conf",
  307. soc_specific: true,
  308. sub_dir: "sub_dir",
  309. }`,
  310. expectedPath: filepath.Join(targetPath, "vendor/dsp/sub_dir"),
  311. }}
  312. for _, tt := range tests {
  313. t.Run(tt.description, func(t *testing.T) {
  314. result := prepareForPrebuiltEtcTest.RunTestWithBp(t, tt.config)
  315. p := result.Module("foo.conf", "android_arm64_armv8-a").(*PrebuiltEtc)
  316. android.AssertPathRelativeToTopEquals(t, "install dir", tt.expectedPath, p.installDirPath)
  317. })
  318. }
  319. }
  320. func TestPrebuiltRFSADirPath(t *testing.T) {
  321. targetPath := "out/soong/target/product/test_device"
  322. tests := []struct {
  323. description string
  324. config string
  325. expectedPath string
  326. }{{
  327. description: "prebuilt: system rfsa",
  328. config: `
  329. prebuilt_rfsa {
  330. name: "foo.conf",
  331. src: "foo.conf",
  332. }`,
  333. expectedPath: filepath.Join(targetPath, "system/lib/rfsa"),
  334. }, {
  335. description: "prebuilt: vendor rfsa",
  336. config: `
  337. prebuilt_rfsa {
  338. name: "foo.conf",
  339. src: "foo.conf",
  340. soc_specific: true,
  341. sub_dir: "sub_dir",
  342. }`,
  343. expectedPath: filepath.Join(targetPath, "vendor/lib/rfsa/sub_dir"),
  344. }}
  345. for _, tt := range tests {
  346. t.Run(tt.description, func(t *testing.T) {
  347. result := prepareForPrebuiltEtcTest.RunTestWithBp(t, tt.config)
  348. p := result.Module("foo.conf", "android_arm64_armv8-a").(*PrebuiltEtc)
  349. android.AssertPathRelativeToTopEquals(t, "install dir", tt.expectedPath, p.installDirPath)
  350. })
  351. }
  352. }
  353. func checkIfSnapshotTaken(t *testing.T, result *android.TestResult, image string, moduleName string) {
  354. checkIfSnapshotExistAsExpected(t, result, image, moduleName, true)
  355. }
  356. func checkIfSnapshotNotTaken(t *testing.T, result *android.TestResult, image string, moduleName string) {
  357. checkIfSnapshotExistAsExpected(t, result, image, moduleName, false)
  358. }
  359. func checkIfSnapshotExistAsExpected(t *testing.T, result *android.TestResult, image string, moduleName string, expectToExist bool) {
  360. snapshotSingleton := result.SingletonForTests(image + "-snapshot")
  361. archType := "arm64"
  362. archVariant := "armv8-a"
  363. archDir := fmt.Sprintf("arch-%s", archType)
  364. snapshotDir := fmt.Sprintf("%s-snapshot", image)
  365. snapshotVariantPath := filepath.Join(snapshotDir, archType)
  366. outputDir := filepath.Join(snapshotVariantPath, archDir, "etc")
  367. imageVariant := ""
  368. if image == "recovery" {
  369. imageVariant = "recovery_"
  370. }
  371. mod := result.ModuleForTests(moduleName, fmt.Sprintf("android_%s%s_%s", imageVariant, archType, archVariant))
  372. outputFiles := mod.OutputFiles(t, "")
  373. if len(outputFiles) != 1 {
  374. t.Errorf("%q must have single output\n", moduleName)
  375. return
  376. }
  377. snapshotPath := filepath.Join(outputDir, moduleName)
  378. if expectToExist {
  379. out := snapshotSingleton.Output(snapshotPath)
  380. if out.Input.String() != outputFiles[0].String() {
  381. t.Errorf("The input of snapshot %q must be %q, but %q", "prebuilt_vendor", out.Input.String(), outputFiles[0])
  382. }
  383. snapshotJsonPath := snapshotPath + ".json"
  384. if snapshotSingleton.MaybeOutput(snapshotJsonPath).Rule == nil {
  385. t.Errorf("%q expected but not found", snapshotJsonPath)
  386. }
  387. } else {
  388. out := snapshotSingleton.MaybeOutput(snapshotPath)
  389. if out.Rule != nil {
  390. t.Errorf("There must be no rule for module %q output file %q", moduleName, outputFiles[0])
  391. }
  392. }
  393. }
  394. func TestPrebuiltTakeSnapshot(t *testing.T) {
  395. var testBp = `
  396. prebuilt_etc {
  397. name: "prebuilt_vendor",
  398. src: "foo.conf",
  399. vendor: true,
  400. }
  401. prebuilt_etc {
  402. name: "prebuilt_vendor_indirect",
  403. src: "foo.conf",
  404. vendor: true,
  405. }
  406. prebuilt_etc {
  407. name: "prebuilt_recovery",
  408. src: "bar.conf",
  409. recovery: true,
  410. }
  411. prebuilt_etc {
  412. name: "prebuilt_recovery_indirect",
  413. src: "bar.conf",
  414. recovery: true,
  415. }
  416. `
  417. t.Run("prebuilt: vendor and recovery snapshot", func(t *testing.T) {
  418. result := prepareForPrebuiltEtcSnapshotTest.RunTestWithBp(t, testBp)
  419. checkIfSnapshotTaken(t, result, "vendor", "prebuilt_vendor")
  420. checkIfSnapshotTaken(t, result, "vendor", "prebuilt_vendor_indirect")
  421. checkIfSnapshotTaken(t, result, "recovery", "prebuilt_recovery")
  422. checkIfSnapshotTaken(t, result, "recovery", "prebuilt_recovery_indirect")
  423. })
  424. t.Run("prebuilt: directed snapshot", func(t *testing.T) {
  425. prepareForPrebuiltEtcDirectedSnapshotTest := android.GroupFixturePreparers(
  426. prepareForPrebuiltEtcSnapshotTest,
  427. android.FixtureModifyConfig(func(config android.Config) {
  428. config.TestProductVariables.DirectedVendorSnapshot = true
  429. config.TestProductVariables.VendorSnapshotModules = make(map[string]bool)
  430. config.TestProductVariables.VendorSnapshotModules["prebuilt_vendor"] = true
  431. config.TestProductVariables.DirectedRecoverySnapshot = true
  432. config.TestProductVariables.RecoverySnapshotModules = make(map[string]bool)
  433. config.TestProductVariables.RecoverySnapshotModules["prebuilt_recovery"] = true
  434. }),
  435. )
  436. result := prepareForPrebuiltEtcDirectedSnapshotTest.RunTestWithBp(t, testBp)
  437. checkIfSnapshotTaken(t, result, "vendor", "prebuilt_vendor")
  438. checkIfSnapshotNotTaken(t, result, "vendor", "prebuilt_vendor_indirect")
  439. checkIfSnapshotTaken(t, result, "recovery", "prebuilt_recovery")
  440. checkIfSnapshotNotTaken(t, result, "recovery", "prebuilt_recovery_indirect")
  441. })
  442. }
  443. func TestPrebuiltEtcAndroidMkEntriesWithBazel(t *testing.T) {
  444. t.Parallel()
  445. bp := `
  446. prebuilt_etc {
  447. name: "myetc",
  448. src: "prebuilt_etc.rc", // filename in src tree
  449. filename: "init.rc", // target filename on device
  450. sub_dir: "subdir", // relative subdir for installation
  451. bazel_module: { label: "//foo/bar:myetc" },
  452. }
  453. `
  454. res := android.GroupFixturePreparers(
  455. prepareForPrebuiltEtcTest,
  456. android.FixtureModifyConfig(func(cfg android.Config) {
  457. cfg.BazelContext = android.MockBazelContext{
  458. LabelToPrebuiltFileInfo: map[string]cquery.PrebuiltFileInfo{
  459. "//foo/bar:myetc": cquery.PrebuiltFileInfo{
  460. Src: "foo/bar/prebuilt_etc.rc",
  461. Dir: "etc/subdir",
  462. Filename: "init.rc",
  463. Installable: true,
  464. },
  465. },
  466. }
  467. }),
  468. ).RunTestWithBp(t, bp)
  469. ctx := res.ModuleForTests("myetc", "android_arm64_armv8-a")
  470. mod := ctx.Module()
  471. entries := android.AndroidMkEntriesForTest(t, res.TestContext, mod)[0]
  472. // verify androidmk entries
  473. android.AssertStringDoesContain(t, "LOCAL_MODULE_PATH should contain", entries.EntryMap["LOCAL_MODULE_PATH"][0], "etc/subdir")
  474. android.AssertStringEquals(t, "LOCAL_INSTALLED_MODULE_STEM is incorrect", "init.rc", entries.EntryMap["LOCAL_INSTALLED_MODULE_STEM"][0])
  475. // verify installation rules
  476. install := ctx.Description("install")
  477. android.AssertStringEquals(t, "Source location of prebuilt_etc installation", "out/soong/.intermediates/myetc/android_arm64_armv8-a/init.rc", install.Input.String())
  478. android.AssertStringEquals(t, "Target location of prebuilt_etc installation", "out/soong/target/product/test_device/system/etc/subdir/init.rc", install.Output.String())
  479. }