module_test.go 25 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066
  1. // Copyright 2015 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 android
  15. import (
  16. "github.com/google/blueprint"
  17. "path/filepath"
  18. "runtime"
  19. "testing"
  20. )
  21. func TestSrcIsModule(t *testing.T) {
  22. type args struct {
  23. s string
  24. }
  25. tests := []struct {
  26. name string
  27. args args
  28. wantModule string
  29. }{
  30. {
  31. name: "file",
  32. args: args{
  33. s: "foo",
  34. },
  35. wantModule: "",
  36. },
  37. {
  38. name: "module",
  39. args: args{
  40. s: ":foo",
  41. },
  42. wantModule: "foo",
  43. },
  44. {
  45. name: "tag",
  46. args: args{
  47. s: ":foo{.bar}",
  48. },
  49. wantModule: "foo{.bar}",
  50. },
  51. {
  52. name: "extra colon",
  53. args: args{
  54. s: ":foo:bar",
  55. },
  56. wantModule: "foo:bar",
  57. },
  58. {
  59. name: "fully qualified",
  60. args: args{
  61. s: "//foo:bar",
  62. },
  63. wantModule: "//foo:bar",
  64. },
  65. {
  66. name: "fully qualified with tag",
  67. args: args{
  68. s: "//foo:bar{.tag}",
  69. },
  70. wantModule: "//foo:bar{.tag}",
  71. },
  72. {
  73. name: "invalid unqualified name",
  74. args: args{
  75. s: ":foo/bar",
  76. },
  77. wantModule: "",
  78. },
  79. }
  80. for _, tt := range tests {
  81. t.Run(tt.name, func(t *testing.T) {
  82. if gotModule := SrcIsModule(tt.args.s); gotModule != tt.wantModule {
  83. t.Errorf("SrcIsModule() = %v, want %v", gotModule, tt.wantModule)
  84. }
  85. })
  86. }
  87. }
  88. func TestSrcIsModuleWithTag(t *testing.T) {
  89. type args struct {
  90. s string
  91. }
  92. tests := []struct {
  93. name string
  94. args args
  95. wantModule string
  96. wantTag string
  97. }{
  98. {
  99. name: "file",
  100. args: args{
  101. s: "foo",
  102. },
  103. wantModule: "",
  104. wantTag: "",
  105. },
  106. {
  107. name: "module",
  108. args: args{
  109. s: ":foo",
  110. },
  111. wantModule: "foo",
  112. wantTag: "",
  113. },
  114. {
  115. name: "tag",
  116. args: args{
  117. s: ":foo{.bar}",
  118. },
  119. wantModule: "foo",
  120. wantTag: ".bar",
  121. },
  122. {
  123. name: "empty tag",
  124. args: args{
  125. s: ":foo{}",
  126. },
  127. wantModule: "foo",
  128. wantTag: "",
  129. },
  130. {
  131. name: "extra colon",
  132. args: args{
  133. s: ":foo:bar",
  134. },
  135. wantModule: "foo:bar",
  136. },
  137. {
  138. name: "invalid tag",
  139. args: args{
  140. s: ":foo{.bar",
  141. },
  142. wantModule: "foo{.bar",
  143. },
  144. {
  145. name: "invalid tag 2",
  146. args: args{
  147. s: ":foo.bar}",
  148. },
  149. wantModule: "foo.bar}",
  150. },
  151. {
  152. name: "fully qualified",
  153. args: args{
  154. s: "//foo:bar",
  155. },
  156. wantModule: "//foo:bar",
  157. },
  158. {
  159. name: "fully qualified with tag",
  160. args: args{
  161. s: "//foo:bar{.tag}",
  162. },
  163. wantModule: "//foo:bar",
  164. wantTag: ".tag",
  165. },
  166. {
  167. name: "invalid unqualified name",
  168. args: args{
  169. s: ":foo/bar",
  170. },
  171. wantModule: "",
  172. },
  173. {
  174. name: "invalid unqualified name with tag",
  175. args: args{
  176. s: ":foo/bar{.tag}",
  177. },
  178. wantModule: "",
  179. },
  180. }
  181. for _, tt := range tests {
  182. t.Run(tt.name, func(t *testing.T) {
  183. gotModule, gotTag := SrcIsModuleWithTag(tt.args.s)
  184. if gotModule != tt.wantModule {
  185. t.Errorf("SrcIsModuleWithTag() gotModule = %v, want %v", gotModule, tt.wantModule)
  186. }
  187. if gotTag != tt.wantTag {
  188. t.Errorf("SrcIsModuleWithTag() gotTag = %v, want %v", gotTag, tt.wantTag)
  189. }
  190. })
  191. }
  192. }
  193. type depsModule struct {
  194. ModuleBase
  195. props struct {
  196. Deps []string
  197. }
  198. }
  199. func (m *depsModule) GenerateAndroidBuildActions(ctx ModuleContext) {
  200. outputFile := PathForModuleOut(ctx, ctx.ModuleName())
  201. ctx.Build(pctx, BuildParams{
  202. Rule: Touch,
  203. Output: outputFile,
  204. })
  205. installFile := ctx.InstallFile(PathForModuleInstall(ctx), ctx.ModuleName(), outputFile)
  206. ctx.InstallSymlink(PathForModuleInstall(ctx, "symlinks"), ctx.ModuleName(), installFile)
  207. }
  208. func (m *depsModule) DepsMutator(ctx BottomUpMutatorContext) {
  209. ctx.AddDependency(ctx.Module(), installDepTag{}, m.props.Deps...)
  210. }
  211. func depsModuleFactory() Module {
  212. m := &depsModule{}
  213. m.AddProperties(&m.props)
  214. InitAndroidArchModule(m, HostAndDeviceDefault, MultilibCommon)
  215. return m
  216. }
  217. var prepareForModuleTests = FixtureRegisterWithContext(func(ctx RegistrationContext) {
  218. ctx.RegisterModuleType("deps", depsModuleFactory)
  219. })
  220. func TestErrorDependsOnDisabledModule(t *testing.T) {
  221. bp := `
  222. deps {
  223. name: "foo",
  224. deps: ["bar"],
  225. }
  226. deps {
  227. name: "bar",
  228. enabled: false,
  229. }
  230. `
  231. prepareForModuleTests.
  232. ExtendWithErrorHandler(FixtureExpectsAtLeastOneErrorMatchingPattern(`module "foo": depends on disabled module "bar"`)).
  233. RunTestWithBp(t, bp)
  234. }
  235. func TestValidateCorrectBuildParams(t *testing.T) {
  236. config := TestConfig(t.TempDir(), nil, "", nil)
  237. pathContext := PathContextForTesting(config)
  238. bparams := convertBuildParams(BuildParams{
  239. // Test with Output
  240. Output: PathForOutput(pathContext, "undeclared_symlink"),
  241. SymlinkOutput: PathForOutput(pathContext, "undeclared_symlink"),
  242. })
  243. err := validateBuildParams(bparams)
  244. if err != nil {
  245. t.Error(err)
  246. }
  247. bparams = convertBuildParams(BuildParams{
  248. // Test with ImplicitOutput
  249. ImplicitOutput: PathForOutput(pathContext, "undeclared_symlink"),
  250. SymlinkOutput: PathForOutput(pathContext, "undeclared_symlink"),
  251. })
  252. err = validateBuildParams(bparams)
  253. if err != nil {
  254. t.Error(err)
  255. }
  256. }
  257. func TestValidateIncorrectBuildParams(t *testing.T) {
  258. config := TestConfig(t.TempDir(), nil, "", nil)
  259. pathContext := PathContextForTesting(config)
  260. params := BuildParams{
  261. Output: PathForOutput(pathContext, "regular_output"),
  262. Outputs: PathsForOutput(pathContext, []string{"out1", "out2"}),
  263. ImplicitOutput: PathForOutput(pathContext, "implicit_output"),
  264. ImplicitOutputs: PathsForOutput(pathContext, []string{"i_out1", "_out2"}),
  265. SymlinkOutput: PathForOutput(pathContext, "undeclared_symlink"),
  266. }
  267. bparams := convertBuildParams(params)
  268. err := validateBuildParams(bparams)
  269. if err != nil {
  270. FailIfNoMatchingErrors(t, "undeclared_symlink is not a declared output or implicit output", []error{err})
  271. } else {
  272. t.Errorf("Expected build params to fail validation: %+v", bparams)
  273. }
  274. }
  275. func TestDistErrorChecking(t *testing.T) {
  276. bp := `
  277. deps {
  278. name: "foo",
  279. dist: {
  280. dest: "../invalid-dest",
  281. dir: "../invalid-dir",
  282. suffix: "invalid/suffix",
  283. },
  284. dists: [
  285. {
  286. dest: "../invalid-dest0",
  287. dir: "../invalid-dir0",
  288. suffix: "invalid/suffix0",
  289. },
  290. {
  291. dest: "../invalid-dest1",
  292. dir: "../invalid-dir1",
  293. suffix: "invalid/suffix1",
  294. },
  295. ],
  296. }
  297. `
  298. expectedErrs := []string{
  299. "\\QAndroid.bp:5:13: module \"foo\": dist.dest: Path is outside directory: ../invalid-dest\\E",
  300. "\\QAndroid.bp:6:12: module \"foo\": dist.dir: Path is outside directory: ../invalid-dir\\E",
  301. "\\QAndroid.bp:7:15: module \"foo\": dist.suffix: Suffix may not contain a '/' character.\\E",
  302. "\\QAndroid.bp:11:15: module \"foo\": dists[0].dest: Path is outside directory: ../invalid-dest0\\E",
  303. "\\QAndroid.bp:12:14: module \"foo\": dists[0].dir: Path is outside directory: ../invalid-dir0\\E",
  304. "\\QAndroid.bp:13:17: module \"foo\": dists[0].suffix: Suffix may not contain a '/' character.\\E",
  305. "\\QAndroid.bp:16:15: module \"foo\": dists[1].dest: Path is outside directory: ../invalid-dest1\\E",
  306. "\\QAndroid.bp:17:14: module \"foo\": dists[1].dir: Path is outside directory: ../invalid-dir1\\E",
  307. "\\QAndroid.bp:18:17: module \"foo\": dists[1].suffix: Suffix may not contain a '/' character.\\E",
  308. }
  309. prepareForModuleTests.
  310. ExtendWithErrorHandler(FixtureExpectsAllErrorsToMatchAPattern(expectedErrs)).
  311. RunTestWithBp(t, bp)
  312. }
  313. func TestInstall(t *testing.T) {
  314. if runtime.GOOS != "linux" {
  315. t.Skip("requires linux")
  316. }
  317. bp := `
  318. deps {
  319. name: "foo",
  320. deps: ["bar"],
  321. }
  322. deps {
  323. name: "bar",
  324. deps: ["baz", "qux"],
  325. }
  326. deps {
  327. name: "baz",
  328. deps: ["qux"],
  329. }
  330. deps {
  331. name: "qux",
  332. }
  333. `
  334. result := GroupFixturePreparers(
  335. prepareForModuleTests,
  336. PrepareForTestWithArchMutator,
  337. ).RunTestWithBp(t, bp)
  338. module := func(name string, host bool) TestingModule {
  339. variant := "android_common"
  340. if host {
  341. variant = result.Config.BuildOSCommonTarget.String()
  342. }
  343. return result.ModuleForTests(name, variant)
  344. }
  345. outputRule := func(name string) TestingBuildParams { return module(name, false).Output(name) }
  346. installRule := func(name string) TestingBuildParams {
  347. return module(name, false).Output(filepath.Join("out/soong/target/product/test_device/system", name))
  348. }
  349. symlinkRule := func(name string) TestingBuildParams {
  350. return module(name, false).Output(filepath.Join("out/soong/target/product/test_device/system/symlinks", name))
  351. }
  352. hostOutputRule := func(name string) TestingBuildParams { return module(name, true).Output(name) }
  353. hostInstallRule := func(name string) TestingBuildParams {
  354. return module(name, true).Output(filepath.Join("out/soong/host/linux-x86", name))
  355. }
  356. hostSymlinkRule := func(name string) TestingBuildParams {
  357. return module(name, true).Output(filepath.Join("out/soong/host/linux-x86/symlinks", name))
  358. }
  359. assertInputs := func(params TestingBuildParams, inputs ...Path) {
  360. t.Helper()
  361. AssertArrayString(t, "expected inputs", Paths(inputs).Strings(),
  362. append(PathsIfNonNil(params.Input), params.Inputs...).Strings())
  363. }
  364. assertImplicits := func(params TestingBuildParams, implicits ...Path) {
  365. t.Helper()
  366. AssertArrayString(t, "expected implicit dependencies", Paths(implicits).Strings(),
  367. append(PathsIfNonNil(params.Implicit), params.Implicits...).Strings())
  368. }
  369. assertOrderOnlys := func(params TestingBuildParams, orderonlys ...Path) {
  370. t.Helper()
  371. AssertArrayString(t, "expected orderonly dependencies", Paths(orderonlys).Strings(),
  372. params.OrderOnly.Strings())
  373. }
  374. // Check host install rule dependencies
  375. assertInputs(hostInstallRule("foo"), hostOutputRule("foo").Output)
  376. assertImplicits(hostInstallRule("foo"),
  377. hostInstallRule("bar").Output,
  378. hostSymlinkRule("bar").Output,
  379. hostInstallRule("baz").Output,
  380. hostSymlinkRule("baz").Output,
  381. hostInstallRule("qux").Output,
  382. hostSymlinkRule("qux").Output,
  383. )
  384. assertOrderOnlys(hostInstallRule("foo"))
  385. // Check host symlink rule dependencies. Host symlinks must use a normal dependency, not an
  386. // order-only dependency, so that the tool gets updated when the symlink is depended on.
  387. assertInputs(hostSymlinkRule("foo"), hostInstallRule("foo").Output)
  388. assertImplicits(hostSymlinkRule("foo"))
  389. assertOrderOnlys(hostSymlinkRule("foo"))
  390. // Check device install rule dependencies
  391. assertInputs(installRule("foo"), outputRule("foo").Output)
  392. assertImplicits(installRule("foo"))
  393. assertOrderOnlys(installRule("foo"),
  394. installRule("bar").Output,
  395. symlinkRule("bar").Output,
  396. installRule("baz").Output,
  397. symlinkRule("baz").Output,
  398. installRule("qux").Output,
  399. symlinkRule("qux").Output,
  400. )
  401. // Check device symlink rule dependencies. Device symlinks could use an order-only dependency,
  402. // but the current implementation uses a normal dependency.
  403. assertInputs(symlinkRule("foo"), installRule("foo").Output)
  404. assertImplicits(symlinkRule("foo"))
  405. assertOrderOnlys(symlinkRule("foo"))
  406. }
  407. func TestInstallKatiEnabled(t *testing.T) {
  408. if runtime.GOOS != "linux" {
  409. t.Skip("requires linux")
  410. }
  411. bp := `
  412. deps {
  413. name: "foo",
  414. deps: ["bar"],
  415. }
  416. deps {
  417. name: "bar",
  418. deps: ["baz", "qux"],
  419. }
  420. deps {
  421. name: "baz",
  422. deps: ["qux"],
  423. }
  424. deps {
  425. name: "qux",
  426. }
  427. `
  428. result := GroupFixturePreparers(
  429. prepareForModuleTests,
  430. PrepareForTestWithArchMutator,
  431. FixtureModifyConfig(SetKatiEnabledForTests),
  432. PrepareForTestWithMakevars,
  433. ).RunTestWithBp(t, bp)
  434. rules := result.InstallMakeRulesForTesting(t)
  435. module := func(name string, host bool) TestingModule {
  436. variant := "android_common"
  437. if host {
  438. variant = result.Config.BuildOSCommonTarget.String()
  439. }
  440. return result.ModuleForTests(name, variant)
  441. }
  442. outputRule := func(name string) TestingBuildParams { return module(name, false).Output(name) }
  443. ruleForOutput := func(output string) InstallMakeRule {
  444. for _, rule := range rules {
  445. if rule.Target == output {
  446. return rule
  447. }
  448. }
  449. t.Fatalf("no make install rule for %s", output)
  450. return InstallMakeRule{}
  451. }
  452. installRule := func(name string) InstallMakeRule {
  453. return ruleForOutput(filepath.Join("out/target/product/test_device/system", name))
  454. }
  455. symlinkRule := func(name string) InstallMakeRule {
  456. return ruleForOutput(filepath.Join("out/target/product/test_device/system/symlinks", name))
  457. }
  458. hostOutputRule := func(name string) TestingBuildParams { return module(name, true).Output(name) }
  459. hostInstallRule := func(name string) InstallMakeRule {
  460. return ruleForOutput(filepath.Join("out/host/linux-x86", name))
  461. }
  462. hostSymlinkRule := func(name string) InstallMakeRule {
  463. return ruleForOutput(filepath.Join("out/host/linux-x86/symlinks", name))
  464. }
  465. assertDeps := func(rule InstallMakeRule, deps ...string) {
  466. t.Helper()
  467. AssertArrayString(t, "expected inputs", deps, rule.Deps)
  468. }
  469. assertOrderOnlys := func(rule InstallMakeRule, orderonlys ...string) {
  470. t.Helper()
  471. AssertArrayString(t, "expected orderonly dependencies", orderonlys, rule.OrderOnlyDeps)
  472. }
  473. // Check host install rule dependencies
  474. assertDeps(hostInstallRule("foo"),
  475. hostOutputRule("foo").Output.String(),
  476. hostInstallRule("bar").Target,
  477. hostSymlinkRule("bar").Target,
  478. hostInstallRule("baz").Target,
  479. hostSymlinkRule("baz").Target,
  480. hostInstallRule("qux").Target,
  481. hostSymlinkRule("qux").Target,
  482. )
  483. assertOrderOnlys(hostInstallRule("foo"))
  484. // Check host symlink rule dependencies. Host symlinks must use a normal dependency, not an
  485. // order-only dependency, so that the tool gets updated when the symlink is depended on.
  486. assertDeps(hostSymlinkRule("foo"), hostInstallRule("foo").Target)
  487. assertOrderOnlys(hostSymlinkRule("foo"))
  488. // Check device install rule dependencies
  489. assertDeps(installRule("foo"), outputRule("foo").Output.String())
  490. assertOrderOnlys(installRule("foo"),
  491. installRule("bar").Target,
  492. symlinkRule("bar").Target,
  493. installRule("baz").Target,
  494. symlinkRule("baz").Target,
  495. installRule("qux").Target,
  496. symlinkRule("qux").Target,
  497. )
  498. // Check device symlink rule dependencies. Device symlinks could use an order-only dependency,
  499. // but the current implementation uses a normal dependency.
  500. assertDeps(symlinkRule("foo"), installRule("foo").Target)
  501. assertOrderOnlys(symlinkRule("foo"))
  502. }
  503. type PropsTestModuleEmbedded struct {
  504. Embedded_prop *string
  505. }
  506. type StructInSlice struct {
  507. G string
  508. H bool
  509. I []string
  510. }
  511. type propsTestModule struct {
  512. ModuleBase
  513. DefaultableModuleBase
  514. props struct {
  515. A string `android:"arch_variant"`
  516. B *bool
  517. C []string
  518. }
  519. otherProps struct {
  520. PropsTestModuleEmbedded
  521. D *int64
  522. Nested struct {
  523. E *string
  524. }
  525. F *string `blueprint:"mutated"`
  526. Slice_of_struct []StructInSlice
  527. }
  528. }
  529. func propsTestModuleFactory() Module {
  530. module := &propsTestModule{}
  531. module.AddProperties(&module.props, &module.otherProps)
  532. InitAndroidArchModule(module, HostAndDeviceSupported, MultilibBoth)
  533. InitDefaultableModule(module)
  534. return module
  535. }
  536. type propsTestModuleDefaults struct {
  537. ModuleBase
  538. DefaultsModuleBase
  539. }
  540. func propsTestModuleDefaultsFactory() Module {
  541. defaults := &propsTestModuleDefaults{}
  542. module := propsTestModule{}
  543. defaults.AddProperties(&module.props, &module.otherProps)
  544. InitDefaultsModule(defaults)
  545. return defaults
  546. }
  547. func (p *propsTestModule) GenerateAndroidBuildActions(ctx ModuleContext) {
  548. str := "abc"
  549. p.otherProps.F = &str
  550. }
  551. func TestUsedProperties(t *testing.T) {
  552. testCases := []struct {
  553. desc string
  554. bp string
  555. expectedProps []propInfo
  556. }{
  557. {
  558. desc: "only name",
  559. bp: `test {
  560. name: "foo",
  561. }
  562. `,
  563. expectedProps: []propInfo{
  564. propInfo{Name: "Name", Type: "string", Value: "foo"},
  565. },
  566. },
  567. {
  568. desc: "some props",
  569. bp: `test {
  570. name: "foo",
  571. a: "abc",
  572. b: true,
  573. d: 123,
  574. }
  575. `,
  576. expectedProps: []propInfo{
  577. propInfo{Name: "A", Type: "string", Value: "abc"},
  578. propInfo{Name: "B", Type: "bool", Value: "true"},
  579. propInfo{Name: "D", Type: "int64", Value: "123"},
  580. propInfo{Name: "Name", Type: "string", Value: "foo"},
  581. },
  582. },
  583. {
  584. desc: "unused non-pointer prop",
  585. bp: `test {
  586. name: "foo",
  587. b: true,
  588. d: 123,
  589. }
  590. `,
  591. expectedProps: []propInfo{
  592. // for non-pointer cannot distinguish between unused and intentionally set to empty
  593. propInfo{Name: "A", Type: "string", Value: ""},
  594. propInfo{Name: "B", Type: "bool", Value: "true"},
  595. propInfo{Name: "D", Type: "int64", Value: "123"},
  596. propInfo{Name: "Name", Type: "string", Value: "foo"},
  597. },
  598. },
  599. {
  600. desc: "nested props",
  601. bp: `test {
  602. name: "foo",
  603. nested: {
  604. e: "abc",
  605. }
  606. }
  607. `,
  608. expectedProps: []propInfo{
  609. propInfo{Name: "Name", Type: "string", Value: "foo"},
  610. propInfo{Name: "Nested.E", Type: "string", Value: "abc"},
  611. },
  612. },
  613. {
  614. desc: "arch props",
  615. bp: `test {
  616. name: "foo",
  617. arch: {
  618. x86_64: {
  619. a: "abc",
  620. },
  621. }
  622. }
  623. `,
  624. expectedProps: []propInfo{
  625. propInfo{Name: "Arch.X86_64.A", Type: "string", Value: "abc"},
  626. propInfo{Name: "Name", Type: "string", Value: "foo"},
  627. },
  628. },
  629. {
  630. desc: "embedded props",
  631. bp: `test {
  632. name: "foo",
  633. embedded_prop: "a",
  634. }
  635. `,
  636. expectedProps: []propInfo{
  637. propInfo{Name: "Embedded_prop", Type: "string", Value: "a"},
  638. propInfo{Name: "Name", Type: "string", Value: "foo"},
  639. },
  640. },
  641. {
  642. desc: "struct slice",
  643. bp: `test {
  644. name: "foo",
  645. slice_of_struct: [
  646. {
  647. g: "abc",
  648. h: false,
  649. i: ["baz"],
  650. },
  651. {
  652. g: "def",
  653. h: true,
  654. i: [],
  655. },
  656. ]
  657. }
  658. `,
  659. expectedProps: []propInfo{
  660. propInfo{Name: "Name", Type: "string", Value: "foo"},
  661. propInfo{Name: "Slice_of_struct", Type: "struct slice", Values: []string{
  662. `android.StructInSlice{G: abc, H: false, I: [baz]}`,
  663. `android.StructInSlice{G: def, H: true, I: []}`,
  664. }},
  665. },
  666. },
  667. {
  668. desc: "defaults",
  669. bp: `
  670. test_defaults {
  671. name: "foo_defaults",
  672. a: "a",
  673. b: true,
  674. c: ["default_c"],
  675. embedded_prop:"a",
  676. arch: {
  677. x86_64: {
  678. a: "x86_64 a",
  679. },
  680. },
  681. }
  682. test {
  683. name: "foo",
  684. defaults: ["foo_defaults"],
  685. c: ["c"],
  686. nested: {
  687. e: "nested e",
  688. },
  689. target: {
  690. linux: {
  691. a: "a",
  692. },
  693. },
  694. }
  695. `,
  696. expectedProps: []propInfo{
  697. propInfo{Name: "A", Type: "string", Value: "a"},
  698. propInfo{Name: "Arch.X86_64.A", Type: "string", Value: "x86_64 a"},
  699. propInfo{Name: "B", Type: "bool", Value: "true"},
  700. propInfo{Name: "C", Type: "string slice", Values: []string{"default_c", "c"}},
  701. propInfo{Name: "Defaults", Type: "string slice", Values: []string{"foo_defaults"}},
  702. propInfo{Name: "Embedded_prop", Type: "string", Value: "a"},
  703. propInfo{Name: "Name", Type: "string", Value: "foo"},
  704. propInfo{Name: "Nested.E", Type: "string", Value: "nested e"},
  705. propInfo{Name: "Target.Linux.A", Type: "string", Value: "a"},
  706. },
  707. },
  708. }
  709. for _, tc := range testCases {
  710. t.Run(tc.desc, func(t *testing.T) {
  711. result := GroupFixturePreparers(
  712. PrepareForTestWithAllowMissingDependencies,
  713. PrepareForTestWithDefaults,
  714. FixtureRegisterWithContext(func(ctx RegistrationContext) {
  715. ctx.RegisterModuleType("test", propsTestModuleFactory)
  716. ctx.RegisterModuleType("test_defaults", propsTestModuleDefaultsFactory)
  717. }),
  718. FixtureWithRootAndroidBp(tc.bp),
  719. ).RunTest(t)
  720. foo := result.ModuleForTests("foo", "").Module().base()
  721. AssertDeepEquals(t, "foo ", tc.expectedProps, foo.propertiesWithValues())
  722. })
  723. }
  724. }
  725. func TestSortedUniqueNamedPaths(t *testing.T) {
  726. type np struct {
  727. path, name string
  728. }
  729. makePaths := func(l []np) NamedPaths {
  730. result := make(NamedPaths, 0, len(l))
  731. for _, p := range l {
  732. result = append(result, NamedPath{PathForTesting(p.path), p.name})
  733. }
  734. return result
  735. }
  736. tests := []struct {
  737. name string
  738. in []np
  739. expectedOut []np
  740. }{
  741. {
  742. name: "empty",
  743. in: []np{},
  744. expectedOut: []np{},
  745. },
  746. {
  747. name: "all_same",
  748. in: []np{
  749. {"a.txt", "A"},
  750. {"a.txt", "A"},
  751. {"a.txt", "A"},
  752. {"a.txt", "A"},
  753. {"a.txt", "A"},
  754. },
  755. expectedOut: []np{
  756. {"a.txt", "A"},
  757. },
  758. },
  759. {
  760. name: "same_path_different_names",
  761. in: []np{
  762. {"a.txt", "C"},
  763. {"a.txt", "A"},
  764. {"a.txt", "D"},
  765. {"a.txt", "B"},
  766. {"a.txt", "E"},
  767. },
  768. expectedOut: []np{
  769. {"a.txt", "A"},
  770. {"a.txt", "B"},
  771. {"a.txt", "C"},
  772. {"a.txt", "D"},
  773. {"a.txt", "E"},
  774. },
  775. },
  776. {
  777. name: "different_paths_same_name",
  778. in: []np{
  779. {"b/b.txt", "A"},
  780. {"a/a.txt", "A"},
  781. {"a/txt", "A"},
  782. {"b", "A"},
  783. {"a/b/d", "A"},
  784. },
  785. expectedOut: []np{
  786. {"a/a.txt", "A"},
  787. {"a/b/d", "A"},
  788. {"a/txt", "A"},
  789. {"b/b.txt", "A"},
  790. {"b", "A"},
  791. },
  792. },
  793. {
  794. name: "all_different",
  795. in: []np{
  796. {"b/b.txt", "A"},
  797. {"a/a.txt", "B"},
  798. {"a/txt", "D"},
  799. {"b", "C"},
  800. {"a/b/d", "E"},
  801. },
  802. expectedOut: []np{
  803. {"a/a.txt", "B"},
  804. {"a/b/d", "E"},
  805. {"a/txt", "D"},
  806. {"b/b.txt", "A"},
  807. {"b", "C"},
  808. },
  809. },
  810. {
  811. name: "some_different",
  812. in: []np{
  813. {"b/b.txt", "A"},
  814. {"a/a.txt", "B"},
  815. {"a/txt", "D"},
  816. {"a/b/d", "E"},
  817. {"b", "C"},
  818. {"a/a.txt", "B"},
  819. {"a/b/d", "E"},
  820. },
  821. expectedOut: []np{
  822. {"a/a.txt", "B"},
  823. {"a/b/d", "E"},
  824. {"a/txt", "D"},
  825. {"b/b.txt", "A"},
  826. {"b", "C"},
  827. },
  828. },
  829. }
  830. for _, tt := range tests {
  831. t.Run(tt.name, func(t *testing.T) {
  832. actual := SortedUniqueNamedPaths(makePaths(tt.in))
  833. expected := makePaths(tt.expectedOut)
  834. t.Logf("actual: %v", actual)
  835. t.Logf("expected: %v", expected)
  836. AssertDeepEquals(t, "SortedUniqueNamedPaths ", expected, actual)
  837. })
  838. }
  839. }
  840. func TestSetAndroidMkEntriesWithTestOptions(t *testing.T) {
  841. tests := []struct {
  842. name string
  843. testOptions CommonTestOptions
  844. expected map[string][]string
  845. }{
  846. {
  847. name: "empty",
  848. testOptions: CommonTestOptions{},
  849. expected: map[string][]string{},
  850. },
  851. {
  852. name: "is unit test",
  853. testOptions: CommonTestOptions{
  854. Unit_test: boolPtr(true),
  855. },
  856. expected: map[string][]string{
  857. "LOCAL_IS_UNIT_TEST": []string{"true"},
  858. },
  859. },
  860. {
  861. name: "is not unit test",
  862. testOptions: CommonTestOptions{
  863. Unit_test: boolPtr(false),
  864. },
  865. expected: map[string][]string{},
  866. },
  867. {
  868. name: "empty tag",
  869. testOptions: CommonTestOptions{
  870. Tags: []string{},
  871. },
  872. expected: map[string][]string{},
  873. },
  874. {
  875. name: "single tag",
  876. testOptions: CommonTestOptions{
  877. Tags: []string{"tag1"},
  878. },
  879. expected: map[string][]string{
  880. "LOCAL_TEST_OPTIONS_TAGS": []string{"tag1"},
  881. },
  882. },
  883. {
  884. name: "multiple tag",
  885. testOptions: CommonTestOptions{
  886. Tags: []string{"tag1", "tag2", "tag3"},
  887. },
  888. expected: map[string][]string{
  889. "LOCAL_TEST_OPTIONS_TAGS": []string{"tag1", "tag2", "tag3"},
  890. },
  891. },
  892. }
  893. for _, tt := range tests {
  894. t.Run(tt.name, func(t *testing.T) {
  895. actualEntries := AndroidMkEntries{
  896. EntryMap: map[string][]string{},
  897. }
  898. tt.testOptions.SetAndroidMkEntries(&actualEntries)
  899. actual := actualEntries.EntryMap
  900. t.Logf("actual: %v", actual)
  901. t.Logf("expected: %v", tt.expected)
  902. AssertDeepEquals(t, "TestProcessCommonTestOptions ", tt.expected, actual)
  903. })
  904. }
  905. }
  906. type fakeBlueprintModule struct{}
  907. func (fakeBlueprintModule) Name() string { return "foo" }
  908. func (fakeBlueprintModule) GenerateBuildActions(blueprint.ModuleContext) {}
  909. type sourceProducerTestModule struct {
  910. fakeBlueprintModule
  911. source Path
  912. }
  913. func (s sourceProducerTestModule) Srcs() Paths { return Paths{s.source} }
  914. type outputFileProducerTestModule struct {
  915. fakeBlueprintModule
  916. output map[string]Path
  917. error map[string]error
  918. }
  919. func (o outputFileProducerTestModule) OutputFiles(tag string) (Paths, error) {
  920. return PathsIfNonNil(o.output[tag]), o.error[tag]
  921. }
  922. type pathContextAddMissingDependenciesWrapper struct {
  923. PathContext
  924. missingDeps []string
  925. }
  926. func (p *pathContextAddMissingDependenciesWrapper) AddMissingDependencies(deps []string) {
  927. p.missingDeps = append(p.missingDeps, deps...)
  928. }
  929. func (p *pathContextAddMissingDependenciesWrapper) OtherModuleName(module blueprint.Module) string {
  930. return module.Name()
  931. }
  932. func TestOutputFileForModule(t *testing.T) {
  933. testcases := []struct {
  934. name string
  935. module blueprint.Module
  936. tag string
  937. env map[string]string
  938. config func(*config)
  939. expected string
  940. missingDeps []string
  941. }{
  942. {
  943. name: "SourceFileProducer",
  944. module: &sourceProducerTestModule{source: PathForTesting("foo.txt")},
  945. expected: "foo.txt",
  946. },
  947. {
  948. name: "OutputFileProducer",
  949. module: &outputFileProducerTestModule{output: map[string]Path{"": PathForTesting("foo.txt")}},
  950. expected: "foo.txt",
  951. },
  952. {
  953. name: "OutputFileProducer_tag",
  954. module: &outputFileProducerTestModule{output: map[string]Path{"foo": PathForTesting("foo.txt")}},
  955. tag: "foo",
  956. expected: "foo.txt",
  957. },
  958. {
  959. name: "OutputFileProducer_AllowMissingDependencies",
  960. config: func(config *config) {
  961. config.TestProductVariables.Allow_missing_dependencies = boolPtr(true)
  962. },
  963. module: &outputFileProducerTestModule{},
  964. missingDeps: []string{"foo"},
  965. expected: "missing_output_file/foo",
  966. },
  967. }
  968. for _, tt := range testcases {
  969. config := TestConfig(buildDir, tt.env, "", nil)
  970. if tt.config != nil {
  971. tt.config(config.config)
  972. }
  973. ctx := &pathContextAddMissingDependenciesWrapper{
  974. PathContext: PathContextForTesting(config),
  975. }
  976. got := OutputFileForModule(ctx, tt.module, tt.tag)
  977. AssertPathRelativeToTopEquals(t, "expected source path", tt.expected, got)
  978. AssertArrayString(t, "expected missing deps", tt.missingDeps, ctx.missingDeps)
  979. }
  980. }