module_test.go 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617
  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. "bytes"
  17. "path/filepath"
  18. "runtime"
  19. "testing"
  20. mkparser "android/soong/androidmk/parser"
  21. )
  22. func TestSrcIsModule(t *testing.T) {
  23. type args struct {
  24. s string
  25. }
  26. tests := []struct {
  27. name string
  28. args args
  29. wantModule string
  30. }{
  31. {
  32. name: "file",
  33. args: args{
  34. s: "foo",
  35. },
  36. wantModule: "",
  37. },
  38. {
  39. name: "module",
  40. args: args{
  41. s: ":foo",
  42. },
  43. wantModule: "foo",
  44. },
  45. {
  46. name: "tag",
  47. args: args{
  48. s: ":foo{.bar}",
  49. },
  50. wantModule: "foo{.bar}",
  51. },
  52. {
  53. name: "extra colon",
  54. args: args{
  55. s: ":foo:bar",
  56. },
  57. wantModule: "foo:bar",
  58. },
  59. {
  60. name: "fully qualified",
  61. args: args{
  62. s: "//foo:bar",
  63. },
  64. wantModule: "//foo:bar",
  65. },
  66. {
  67. name: "fully qualified with tag",
  68. args: args{
  69. s: "//foo:bar{.tag}",
  70. },
  71. wantModule: "//foo:bar{.tag}",
  72. },
  73. {
  74. name: "invalid unqualified name",
  75. args: args{
  76. s: ":foo/bar",
  77. },
  78. wantModule: "",
  79. },
  80. }
  81. for _, tt := range tests {
  82. t.Run(tt.name, func(t *testing.T) {
  83. if gotModule := SrcIsModule(tt.args.s); gotModule != tt.wantModule {
  84. t.Errorf("SrcIsModule() = %v, want %v", gotModule, tt.wantModule)
  85. }
  86. })
  87. }
  88. }
  89. func TestSrcIsModuleWithTag(t *testing.T) {
  90. type args struct {
  91. s string
  92. }
  93. tests := []struct {
  94. name string
  95. args args
  96. wantModule string
  97. wantTag string
  98. }{
  99. {
  100. name: "file",
  101. args: args{
  102. s: "foo",
  103. },
  104. wantModule: "",
  105. wantTag: "",
  106. },
  107. {
  108. name: "module",
  109. args: args{
  110. s: ":foo",
  111. },
  112. wantModule: "foo",
  113. wantTag: "",
  114. },
  115. {
  116. name: "tag",
  117. args: args{
  118. s: ":foo{.bar}",
  119. },
  120. wantModule: "foo",
  121. wantTag: ".bar",
  122. },
  123. {
  124. name: "empty tag",
  125. args: args{
  126. s: ":foo{}",
  127. },
  128. wantModule: "foo",
  129. wantTag: "",
  130. },
  131. {
  132. name: "extra colon",
  133. args: args{
  134. s: ":foo:bar",
  135. },
  136. wantModule: "foo:bar",
  137. },
  138. {
  139. name: "invalid tag",
  140. args: args{
  141. s: ":foo{.bar",
  142. },
  143. wantModule: "foo{.bar",
  144. },
  145. {
  146. name: "invalid tag 2",
  147. args: args{
  148. s: ":foo.bar}",
  149. },
  150. wantModule: "foo.bar}",
  151. },
  152. {
  153. name: "fully qualified",
  154. args: args{
  155. s: "//foo:bar",
  156. },
  157. wantModule: "//foo:bar",
  158. },
  159. {
  160. name: "fully qualified with tag",
  161. args: args{
  162. s: "//foo:bar{.tag}",
  163. },
  164. wantModule: "//foo:bar",
  165. wantTag: ".tag",
  166. },
  167. {
  168. name: "invalid unqualified name",
  169. args: args{
  170. s: ":foo/bar",
  171. },
  172. wantModule: "",
  173. },
  174. {
  175. name: "invalid unqualified name with tag",
  176. args: args{
  177. s: ":foo/bar{.tag}",
  178. },
  179. wantModule: "",
  180. },
  181. }
  182. for _, tt := range tests {
  183. t.Run(tt.name, func(t *testing.T) {
  184. gotModule, gotTag := SrcIsModuleWithTag(tt.args.s)
  185. if gotModule != tt.wantModule {
  186. t.Errorf("SrcIsModuleWithTag() gotModule = %v, want %v", gotModule, tt.wantModule)
  187. }
  188. if gotTag != tt.wantTag {
  189. t.Errorf("SrcIsModuleWithTag() gotTag = %v, want %v", gotTag, tt.wantTag)
  190. }
  191. })
  192. }
  193. }
  194. type depsModule struct {
  195. ModuleBase
  196. props struct {
  197. Deps []string
  198. }
  199. }
  200. func (m *depsModule) GenerateAndroidBuildActions(ctx ModuleContext) {
  201. outputFile := PathForModuleOut(ctx, ctx.ModuleName())
  202. ctx.Build(pctx, BuildParams{
  203. Rule: Touch,
  204. Output: outputFile,
  205. })
  206. installFile := ctx.InstallFile(PathForModuleInstall(ctx), ctx.ModuleName(), outputFile)
  207. ctx.InstallSymlink(PathForModuleInstall(ctx, "symlinks"), ctx.ModuleName(), installFile)
  208. }
  209. func (m *depsModule) DepsMutator(ctx BottomUpMutatorContext) {
  210. ctx.AddDependency(ctx.Module(), installDepTag{}, m.props.Deps...)
  211. }
  212. func depsModuleFactory() Module {
  213. m := &depsModule{}
  214. m.AddProperties(&m.props)
  215. InitAndroidArchModule(m, HostAndDeviceDefault, MultilibCommon)
  216. return m
  217. }
  218. var prepareForModuleTests = FixtureRegisterWithContext(func(ctx RegistrationContext) {
  219. ctx.RegisterModuleType("deps", depsModuleFactory)
  220. })
  221. func TestErrorDependsOnDisabledModule(t *testing.T) {
  222. bp := `
  223. deps {
  224. name: "foo",
  225. deps: ["bar"],
  226. }
  227. deps {
  228. name: "bar",
  229. enabled: false,
  230. }
  231. `
  232. prepareForModuleTests.
  233. ExtendWithErrorHandler(FixtureExpectsAtLeastOneErrorMatchingPattern(`module "foo": depends on disabled module "bar"`)).
  234. RunTestWithBp(t, bp)
  235. }
  236. func TestValidateCorrectBuildParams(t *testing.T) {
  237. config := TestConfig(t.TempDir(), nil, "", nil)
  238. pathContext := PathContextForTesting(config)
  239. bparams := convertBuildParams(BuildParams{
  240. // Test with Output
  241. Output: PathForOutput(pathContext, "undeclared_symlink"),
  242. SymlinkOutput: PathForOutput(pathContext, "undeclared_symlink"),
  243. })
  244. err := validateBuildParams(bparams)
  245. if err != nil {
  246. t.Error(err)
  247. }
  248. bparams = convertBuildParams(BuildParams{
  249. // Test with ImplicitOutput
  250. ImplicitOutput: PathForOutput(pathContext, "undeclared_symlink"),
  251. SymlinkOutput: PathForOutput(pathContext, "undeclared_symlink"),
  252. })
  253. err = validateBuildParams(bparams)
  254. if err != nil {
  255. t.Error(err)
  256. }
  257. }
  258. func TestValidateIncorrectBuildParams(t *testing.T) {
  259. config := TestConfig(t.TempDir(), nil, "", nil)
  260. pathContext := PathContextForTesting(config)
  261. params := BuildParams{
  262. Output: PathForOutput(pathContext, "regular_output"),
  263. Outputs: PathsForOutput(pathContext, []string{"out1", "out2"}),
  264. ImplicitOutput: PathForOutput(pathContext, "implicit_output"),
  265. ImplicitOutputs: PathsForOutput(pathContext, []string{"i_out1", "_out2"}),
  266. SymlinkOutput: PathForOutput(pathContext, "undeclared_symlink"),
  267. }
  268. bparams := convertBuildParams(params)
  269. err := validateBuildParams(bparams)
  270. if err != nil {
  271. FailIfNoMatchingErrors(t, "undeclared_symlink is not a declared output or implicit output", []error{err})
  272. } else {
  273. t.Errorf("Expected build params to fail validation: %+v", bparams)
  274. }
  275. }
  276. func TestDistErrorChecking(t *testing.T) {
  277. bp := `
  278. deps {
  279. name: "foo",
  280. dist: {
  281. dest: "../invalid-dest",
  282. dir: "../invalid-dir",
  283. suffix: "invalid/suffix",
  284. },
  285. dists: [
  286. {
  287. dest: "../invalid-dest0",
  288. dir: "../invalid-dir0",
  289. suffix: "invalid/suffix0",
  290. },
  291. {
  292. dest: "../invalid-dest1",
  293. dir: "../invalid-dir1",
  294. suffix: "invalid/suffix1",
  295. },
  296. ],
  297. }
  298. `
  299. expectedErrs := []string{
  300. "\\QAndroid.bp:5:13: module \"foo\": dist.dest: Path is outside directory: ../invalid-dest\\E",
  301. "\\QAndroid.bp:6:12: module \"foo\": dist.dir: Path is outside directory: ../invalid-dir\\E",
  302. "\\QAndroid.bp:7:15: module \"foo\": dist.suffix: Suffix may not contain a '/' character.\\E",
  303. "\\QAndroid.bp:11:15: module \"foo\": dists[0].dest: Path is outside directory: ../invalid-dest0\\E",
  304. "\\QAndroid.bp:12:14: module \"foo\": dists[0].dir: Path is outside directory: ../invalid-dir0\\E",
  305. "\\QAndroid.bp:13:17: module \"foo\": dists[0].suffix: Suffix may not contain a '/' character.\\E",
  306. "\\QAndroid.bp:16:15: module \"foo\": dists[1].dest: Path is outside directory: ../invalid-dest1\\E",
  307. "\\QAndroid.bp:17:14: module \"foo\": dists[1].dir: Path is outside directory: ../invalid-dir1\\E",
  308. "\\QAndroid.bp:18:17: module \"foo\": dists[1].suffix: Suffix may not contain a '/' character.\\E",
  309. }
  310. prepareForModuleTests.
  311. ExtendWithErrorHandler(FixtureExpectsAllErrorsToMatchAPattern(expectedErrs)).
  312. RunTestWithBp(t, bp)
  313. }
  314. func TestInstall(t *testing.T) {
  315. if runtime.GOOS != "linux" {
  316. t.Skip("requires linux")
  317. }
  318. bp := `
  319. deps {
  320. name: "foo",
  321. deps: ["bar"],
  322. }
  323. deps {
  324. name: "bar",
  325. deps: ["baz", "qux"],
  326. }
  327. deps {
  328. name: "baz",
  329. deps: ["qux"],
  330. }
  331. deps {
  332. name: "qux",
  333. }
  334. `
  335. result := GroupFixturePreparers(
  336. prepareForModuleTests,
  337. PrepareForTestWithArchMutator,
  338. ).RunTestWithBp(t, bp)
  339. module := func(name string, host bool) TestingModule {
  340. variant := "android_common"
  341. if host {
  342. variant = result.Config.BuildOSCommonTarget.String()
  343. }
  344. return result.ModuleForTests(name, variant)
  345. }
  346. outputRule := func(name string) TestingBuildParams { return module(name, false).Output(name) }
  347. installRule := func(name string) TestingBuildParams {
  348. return module(name, false).Output(filepath.Join("out/soong/target/product/test_device/system", name))
  349. }
  350. symlinkRule := func(name string) TestingBuildParams {
  351. return module(name, false).Output(filepath.Join("out/soong/target/product/test_device/system/symlinks", name))
  352. }
  353. hostOutputRule := func(name string) TestingBuildParams { return module(name, true).Output(name) }
  354. hostInstallRule := func(name string) TestingBuildParams {
  355. return module(name, true).Output(filepath.Join("out/soong/host/linux-x86", name))
  356. }
  357. hostSymlinkRule := func(name string) TestingBuildParams {
  358. return module(name, true).Output(filepath.Join("out/soong/host/linux-x86/symlinks", name))
  359. }
  360. assertInputs := func(params TestingBuildParams, inputs ...Path) {
  361. t.Helper()
  362. AssertArrayString(t, "expected inputs", Paths(inputs).Strings(),
  363. append(PathsIfNonNil(params.Input), params.Inputs...).Strings())
  364. }
  365. assertImplicits := func(params TestingBuildParams, implicits ...Path) {
  366. t.Helper()
  367. AssertArrayString(t, "expected implicit dependencies", Paths(implicits).Strings(),
  368. append(PathsIfNonNil(params.Implicit), params.Implicits...).Strings())
  369. }
  370. assertOrderOnlys := func(params TestingBuildParams, orderonlys ...Path) {
  371. t.Helper()
  372. AssertArrayString(t, "expected orderonly dependencies", Paths(orderonlys).Strings(),
  373. params.OrderOnly.Strings())
  374. }
  375. // Check host install rule dependencies
  376. assertInputs(hostInstallRule("foo"), hostOutputRule("foo").Output)
  377. assertImplicits(hostInstallRule("foo"),
  378. hostInstallRule("bar").Output,
  379. hostSymlinkRule("bar").Output,
  380. hostInstallRule("baz").Output,
  381. hostSymlinkRule("baz").Output,
  382. hostInstallRule("qux").Output,
  383. hostSymlinkRule("qux").Output,
  384. )
  385. assertOrderOnlys(hostInstallRule("foo"))
  386. // Check host symlink rule dependencies. Host symlinks must use a normal dependency, not an
  387. // order-only dependency, so that the tool gets updated when the symlink is depended on.
  388. assertInputs(hostSymlinkRule("foo"), hostInstallRule("foo").Output)
  389. assertImplicits(hostSymlinkRule("foo"))
  390. assertOrderOnlys(hostSymlinkRule("foo"))
  391. // Check device install rule dependencies
  392. assertInputs(installRule("foo"), outputRule("foo").Output)
  393. assertImplicits(installRule("foo"))
  394. assertOrderOnlys(installRule("foo"),
  395. installRule("bar").Output,
  396. symlinkRule("bar").Output,
  397. installRule("baz").Output,
  398. symlinkRule("baz").Output,
  399. installRule("qux").Output,
  400. symlinkRule("qux").Output,
  401. )
  402. // Check device symlink rule dependencies. Device symlinks could use an order-only dependency,
  403. // but the current implementation uses a normal dependency.
  404. assertInputs(symlinkRule("foo"), installRule("foo").Output)
  405. assertImplicits(symlinkRule("foo"))
  406. assertOrderOnlys(symlinkRule("foo"))
  407. }
  408. func TestInstallKatiEnabled(t *testing.T) {
  409. if runtime.GOOS != "linux" {
  410. t.Skip("requires linux")
  411. }
  412. bp := `
  413. deps {
  414. name: "foo",
  415. deps: ["bar"],
  416. }
  417. deps {
  418. name: "bar",
  419. deps: ["baz", "qux"],
  420. }
  421. deps {
  422. name: "baz",
  423. deps: ["qux"],
  424. }
  425. deps {
  426. name: "qux",
  427. }
  428. `
  429. result := GroupFixturePreparers(
  430. prepareForModuleTests,
  431. PrepareForTestWithArchMutator,
  432. FixtureModifyConfig(SetKatiEnabledForTests),
  433. FixtureRegisterWithContext(func(ctx RegistrationContext) {
  434. ctx.RegisterSingletonType("makevars", makeVarsSingletonFunc)
  435. }),
  436. ).RunTestWithBp(t, bp)
  437. installs := result.SingletonForTests("makevars").Singleton().(*makeVarsSingleton).installsForTesting
  438. buf := bytes.NewBuffer(append([]byte(nil), installs...))
  439. parser := mkparser.NewParser("makevars", buf)
  440. nodes, errs := parser.Parse()
  441. if len(errs) > 0 {
  442. t.Fatalf("error parsing install rules: %s", errs[0])
  443. }
  444. rules := parseMkRules(t, result.Config, nodes)
  445. module := func(name string, host bool) TestingModule {
  446. variant := "android_common"
  447. if host {
  448. variant = result.Config.BuildOSCommonTarget.String()
  449. }
  450. return result.ModuleForTests(name, variant)
  451. }
  452. outputRule := func(name string) TestingBuildParams { return module(name, false).Output(name) }
  453. ruleForOutput := func(output string) installMakeRule {
  454. for _, rule := range rules {
  455. if rule.target == output {
  456. return rule
  457. }
  458. }
  459. t.Fatalf("no make install rule for %s", output)
  460. return installMakeRule{}
  461. }
  462. installRule := func(name string) installMakeRule {
  463. return ruleForOutput(filepath.Join("out/target/product/test_device/system", name))
  464. }
  465. symlinkRule := func(name string) installMakeRule {
  466. return ruleForOutput(filepath.Join("out/target/product/test_device/system/symlinks", name))
  467. }
  468. hostOutputRule := func(name string) TestingBuildParams { return module(name, true).Output(name) }
  469. hostInstallRule := func(name string) installMakeRule {
  470. return ruleForOutput(filepath.Join("out/host/linux-x86", name))
  471. }
  472. hostSymlinkRule := func(name string) installMakeRule {
  473. return ruleForOutput(filepath.Join("out/host/linux-x86/symlinks", name))
  474. }
  475. assertDeps := func(rule installMakeRule, deps ...string) {
  476. t.Helper()
  477. AssertArrayString(t, "expected inputs", deps, rule.deps)
  478. }
  479. assertOrderOnlys := func(rule installMakeRule, orderonlys ...string) {
  480. t.Helper()
  481. AssertArrayString(t, "expected orderonly dependencies", orderonlys, rule.orderOnlyDeps)
  482. }
  483. // Check host install rule dependencies
  484. assertDeps(hostInstallRule("foo"),
  485. hostOutputRule("foo").Output.String(),
  486. hostInstallRule("bar").target,
  487. hostSymlinkRule("bar").target,
  488. hostInstallRule("baz").target,
  489. hostSymlinkRule("baz").target,
  490. hostInstallRule("qux").target,
  491. hostSymlinkRule("qux").target,
  492. )
  493. assertOrderOnlys(hostInstallRule("foo"))
  494. // Check host symlink rule dependencies. Host symlinks must use a normal dependency, not an
  495. // order-only dependency, so that the tool gets updated when the symlink is depended on.
  496. assertDeps(hostSymlinkRule("foo"), hostInstallRule("foo").target)
  497. assertOrderOnlys(hostSymlinkRule("foo"))
  498. // Check device install rule dependencies
  499. assertDeps(installRule("foo"), outputRule("foo").Output.String())
  500. assertOrderOnlys(installRule("foo"),
  501. installRule("bar").target,
  502. symlinkRule("bar").target,
  503. installRule("baz").target,
  504. symlinkRule("baz").target,
  505. installRule("qux").target,
  506. symlinkRule("qux").target,
  507. )
  508. // Check device symlink rule dependencies. Device symlinks could use an order-only dependency,
  509. // but the current implementation uses a normal dependency.
  510. assertDeps(symlinkRule("foo"), installRule("foo").target)
  511. assertOrderOnlys(symlinkRule("foo"))
  512. }
  513. type installMakeRule struct {
  514. target string
  515. deps []string
  516. orderOnlyDeps []string
  517. }
  518. func parseMkRules(t *testing.T, config Config, nodes []mkparser.Node) []installMakeRule {
  519. var rules []installMakeRule
  520. for _, node := range nodes {
  521. if mkParserRule, ok := node.(*mkparser.Rule); ok {
  522. var rule installMakeRule
  523. if targets := mkParserRule.Target.Words(); len(targets) == 0 {
  524. t.Fatalf("no targets for rule %s", mkParserRule.Dump())
  525. } else if len(targets) > 1 {
  526. t.Fatalf("unsupported multiple targets for rule %s", mkParserRule.Dump())
  527. } else if !targets[0].Const() {
  528. t.Fatalf("unsupported non-const target for rule %s", mkParserRule.Dump())
  529. } else {
  530. rule.target = normalizeStringRelativeToTop(config, targets[0].Value(nil))
  531. }
  532. prereqList := &rule.deps
  533. for _, prereq := range mkParserRule.Prerequisites.Words() {
  534. if !prereq.Const() {
  535. t.Fatalf("unsupported non-const prerequisite for rule %s", mkParserRule.Dump())
  536. }
  537. if prereq.Value(nil) == "|" {
  538. prereqList = &rule.orderOnlyDeps
  539. continue
  540. }
  541. *prereqList = append(*prereqList, normalizeStringRelativeToTop(config, prereq.Value(nil)))
  542. }
  543. rules = append(rules, rule)
  544. }
  545. }
  546. return rules
  547. }