bazel_test.go 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585
  1. // Copyright 2021 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. "fmt"
  17. "testing"
  18. "android/soong/android/allowlists"
  19. "android/soong/bazel"
  20. "github.com/google/blueprint"
  21. "github.com/google/blueprint/proptools"
  22. )
  23. func TestConvertAllModulesInPackage(t *testing.T) {
  24. testCases := []struct {
  25. prefixes allowlists.Bp2BuildConfig
  26. packageDir string
  27. }{
  28. {
  29. prefixes: allowlists.Bp2BuildConfig{
  30. "a": allowlists.Bp2BuildDefaultTrueRecursively,
  31. },
  32. packageDir: "a",
  33. },
  34. {
  35. prefixes: allowlists.Bp2BuildConfig{
  36. "a/b": allowlists.Bp2BuildDefaultTrueRecursively,
  37. },
  38. packageDir: "a/b",
  39. },
  40. {
  41. prefixes: allowlists.Bp2BuildConfig{
  42. "a/b": allowlists.Bp2BuildDefaultTrueRecursively,
  43. "a/b/c": allowlists.Bp2BuildDefaultTrueRecursively,
  44. },
  45. packageDir: "a/b",
  46. },
  47. {
  48. prefixes: allowlists.Bp2BuildConfig{
  49. "a": allowlists.Bp2BuildDefaultTrueRecursively,
  50. "d/e/f": allowlists.Bp2BuildDefaultTrueRecursively,
  51. },
  52. packageDir: "a/b",
  53. },
  54. {
  55. prefixes: allowlists.Bp2BuildConfig{
  56. "a": allowlists.Bp2BuildDefaultFalse,
  57. "a/b": allowlists.Bp2BuildDefaultTrueRecursively,
  58. "a/b/c": allowlists.Bp2BuildDefaultFalse,
  59. },
  60. packageDir: "a/b",
  61. },
  62. {
  63. prefixes: allowlists.Bp2BuildConfig{
  64. "a": allowlists.Bp2BuildDefaultTrueRecursively,
  65. "a/b": allowlists.Bp2BuildDefaultFalse,
  66. "a/b/c": allowlists.Bp2BuildDefaultTrueRecursively,
  67. },
  68. packageDir: "a",
  69. },
  70. {
  71. prefixes: allowlists.Bp2BuildConfig{
  72. "a": allowlists.Bp2BuildDefaultFalseRecursively,
  73. "a/b": allowlists.Bp2BuildDefaultTrue,
  74. },
  75. packageDir: "a/b",
  76. },
  77. {
  78. prefixes: allowlists.Bp2BuildConfig{
  79. "a": allowlists.Bp2BuildDefaultFalseRecursively,
  80. "a/b": allowlists.Bp2BuildDefaultTrueRecursively,
  81. },
  82. packageDir: "a/b/c",
  83. },
  84. }
  85. for _, test := range testCases {
  86. if ok, _ := bp2buildDefaultTrueRecursively(test.packageDir, test.prefixes); !ok {
  87. t.Errorf("Expected to convert all modules in %s based on %v, but failed.", test.packageDir, test.prefixes)
  88. }
  89. }
  90. }
  91. func TestModuleOptIn(t *testing.T) {
  92. testCases := []struct {
  93. prefixes allowlists.Bp2BuildConfig
  94. packageDir string
  95. }{
  96. {
  97. prefixes: allowlists.Bp2BuildConfig{
  98. "a/b": allowlists.Bp2BuildDefaultFalse,
  99. },
  100. packageDir: "a/b",
  101. },
  102. {
  103. prefixes: allowlists.Bp2BuildConfig{
  104. "a": allowlists.Bp2BuildDefaultFalse,
  105. "a/b": allowlists.Bp2BuildDefaultTrueRecursively,
  106. },
  107. packageDir: "a",
  108. },
  109. {
  110. prefixes: allowlists.Bp2BuildConfig{
  111. "a/b": allowlists.Bp2BuildDefaultTrueRecursively,
  112. },
  113. packageDir: "a", // opt-in by default
  114. },
  115. {
  116. prefixes: allowlists.Bp2BuildConfig{
  117. "a/b/c": allowlists.Bp2BuildDefaultTrueRecursively,
  118. },
  119. packageDir: "a/b",
  120. },
  121. {
  122. prefixes: allowlists.Bp2BuildConfig{
  123. "a": allowlists.Bp2BuildDefaultTrueRecursively,
  124. "d/e/f": allowlists.Bp2BuildDefaultTrueRecursively,
  125. },
  126. packageDir: "foo/bar",
  127. },
  128. {
  129. prefixes: allowlists.Bp2BuildConfig{
  130. "a": allowlists.Bp2BuildDefaultTrueRecursively,
  131. "a/b": allowlists.Bp2BuildDefaultFalse,
  132. "a/b/c": allowlists.Bp2BuildDefaultTrueRecursively,
  133. },
  134. packageDir: "a/b",
  135. },
  136. {
  137. prefixes: allowlists.Bp2BuildConfig{
  138. "a": allowlists.Bp2BuildDefaultFalse,
  139. "a/b": allowlists.Bp2BuildDefaultTrueRecursively,
  140. "a/b/c": allowlists.Bp2BuildDefaultFalse,
  141. },
  142. packageDir: "a",
  143. },
  144. {
  145. prefixes: allowlists.Bp2BuildConfig{
  146. "a": allowlists.Bp2BuildDefaultFalseRecursively,
  147. "a/b": allowlists.Bp2BuildDefaultTrue,
  148. },
  149. packageDir: "a/b/c",
  150. },
  151. {
  152. prefixes: allowlists.Bp2BuildConfig{
  153. "a": allowlists.Bp2BuildDefaultTrueRecursively,
  154. "a/b": allowlists.Bp2BuildDefaultFalseRecursively,
  155. },
  156. packageDir: "a/b/c",
  157. },
  158. }
  159. for _, test := range testCases {
  160. if ok, _ := bp2buildDefaultTrueRecursively(test.packageDir, test.prefixes); ok {
  161. t.Errorf("Expected to allow module opt-in in %s based on %v, but failed.", test.packageDir, test.prefixes)
  162. }
  163. }
  164. }
  165. type TestBazelModule struct {
  166. bazel.TestModuleInfo
  167. BazelModuleBase
  168. }
  169. var _ blueprint.Module = TestBazelModule{}
  170. func (m TestBazelModule) Name() string {
  171. return m.TestModuleInfo.ModuleName
  172. }
  173. func (m TestBazelModule) GenerateBuildActions(blueprint.ModuleContext) {
  174. }
  175. type TestBazelConversionContext struct {
  176. omc bazel.OtherModuleTestContext
  177. allowlist Bp2BuildConversionAllowlist
  178. errors []string
  179. }
  180. var _ bazelOtherModuleContext = &TestBazelConversionContext{}
  181. func (bcc *TestBazelConversionContext) OtherModuleType(m blueprint.Module) string {
  182. return bcc.omc.OtherModuleType(m)
  183. }
  184. func (bcc *TestBazelConversionContext) OtherModuleName(m blueprint.Module) string {
  185. return bcc.omc.OtherModuleName(m)
  186. }
  187. func (bcc *TestBazelConversionContext) OtherModuleDir(m blueprint.Module) string {
  188. return bcc.omc.OtherModuleDir(m)
  189. }
  190. func (bcc *TestBazelConversionContext) ModuleErrorf(format string, args ...interface{}) {
  191. bcc.errors = append(bcc.errors, fmt.Sprintf(format, args...))
  192. }
  193. func (bcc *TestBazelConversionContext) Config() Config {
  194. return Config{
  195. &config{
  196. Bp2buildPackageConfig: bcc.allowlist,
  197. },
  198. }
  199. }
  200. var bazelableBazelModuleBase = BazelModuleBase{
  201. bazelProperties: properties{
  202. Bazel_module: BazelModuleProperties{
  203. CanConvertToBazel: true,
  204. },
  205. },
  206. }
  207. func TestBp2BuildAllowlist(t *testing.T) {
  208. testCases := []struct {
  209. description string
  210. shouldConvert bool
  211. expectedErrors []string
  212. module TestBazelModule
  213. allowlist Bp2BuildConversionAllowlist
  214. }{
  215. {
  216. description: "allowlist enables module",
  217. shouldConvert: true,
  218. module: TestBazelModule{
  219. TestModuleInfo: bazel.TestModuleInfo{
  220. ModuleName: "foo",
  221. Typ: "rule1",
  222. Dir: "dir1",
  223. },
  224. BazelModuleBase: bazelableBazelModuleBase,
  225. },
  226. allowlist: Bp2BuildConversionAllowlist{
  227. moduleAlwaysConvert: map[string]bool{
  228. "foo": true,
  229. },
  230. },
  231. },
  232. {
  233. description: "module in name allowlist and type allowlist fails",
  234. shouldConvert: false,
  235. expectedErrors: []string{"A module cannot be in moduleAlwaysConvert and also be in moduleTypeAlwaysConvert"},
  236. module: TestBazelModule{
  237. TestModuleInfo: bazel.TestModuleInfo{
  238. ModuleName: "foo",
  239. Typ: "rule1",
  240. Dir: "dir1",
  241. },
  242. BazelModuleBase: bazelableBazelModuleBase,
  243. },
  244. allowlist: Bp2BuildConversionAllowlist{
  245. moduleAlwaysConvert: map[string]bool{
  246. "foo": true,
  247. },
  248. moduleTypeAlwaysConvert: map[string]bool{
  249. "rule1": true,
  250. },
  251. },
  252. },
  253. {
  254. description: "module in allowlist and denylist fails",
  255. shouldConvert: false,
  256. expectedErrors: []string{"a module cannot be in moduleDoNotConvert and also be in moduleAlwaysConvert"},
  257. module: TestBazelModule{
  258. TestModuleInfo: bazel.TestModuleInfo{
  259. ModuleName: "foo",
  260. Typ: "rule1",
  261. Dir: "dir1",
  262. },
  263. BazelModuleBase: bazelableBazelModuleBase,
  264. },
  265. allowlist: Bp2BuildConversionAllowlist{
  266. moduleAlwaysConvert: map[string]bool{
  267. "foo": true,
  268. },
  269. moduleDoNotConvert: map[string]bool{
  270. "foo": true,
  271. },
  272. },
  273. },
  274. {
  275. description: "module allowlist and enabled directory",
  276. shouldConvert: false,
  277. expectedErrors: []string{"A module cannot be in a directory marked Bp2BuildDefaultTrue or Bp2BuildDefaultTrueRecursively and also be in moduleAlwaysConvert. Directory: 'existing/build/dir' Module: 'foo'"},
  278. module: TestBazelModule{
  279. TestModuleInfo: bazel.TestModuleInfo{
  280. ModuleName: "foo",
  281. Typ: "rule1",
  282. Dir: "existing/build/dir",
  283. },
  284. BazelModuleBase: bazelableBazelModuleBase,
  285. },
  286. allowlist: Bp2BuildConversionAllowlist{
  287. moduleAlwaysConvert: map[string]bool{
  288. "foo": true,
  289. },
  290. defaultConfig: allowlists.Bp2BuildConfig{
  291. "existing/build/dir": allowlists.Bp2BuildDefaultTrue,
  292. },
  293. },
  294. },
  295. {
  296. description: "module allowlist and enabled subdirectory",
  297. shouldConvert: false,
  298. expectedErrors: []string{"A module cannot be in a directory marked Bp2BuildDefaultTrue or Bp2BuildDefaultTrueRecursively and also be in moduleAlwaysConvert. Directory: 'existing/build/dir' Module: 'foo'"},
  299. module: TestBazelModule{
  300. TestModuleInfo: bazel.TestModuleInfo{
  301. ModuleName: "foo",
  302. Typ: "rule1",
  303. Dir: "existing/build/dir/subdir",
  304. },
  305. BazelModuleBase: bazelableBazelModuleBase,
  306. },
  307. allowlist: Bp2BuildConversionAllowlist{
  308. moduleAlwaysConvert: map[string]bool{
  309. "foo": true,
  310. },
  311. defaultConfig: allowlists.Bp2BuildConfig{
  312. "existing/build/dir": allowlists.Bp2BuildDefaultTrueRecursively,
  313. },
  314. },
  315. },
  316. {
  317. description: "module enabled in unit test short-circuits other allowlists",
  318. shouldConvert: true,
  319. module: TestBazelModule{
  320. TestModuleInfo: bazel.TestModuleInfo{
  321. ModuleName: "foo",
  322. Typ: "rule1",
  323. Dir: ".",
  324. },
  325. BazelModuleBase: BazelModuleBase{
  326. bazelProperties: properties{
  327. Bazel_module: BazelModuleProperties{
  328. CanConvertToBazel: true,
  329. Bp2build_available: proptools.BoolPtr(true),
  330. },
  331. },
  332. },
  333. },
  334. allowlist: Bp2BuildConversionAllowlist{
  335. moduleAlwaysConvert: map[string]bool{
  336. "foo": true,
  337. },
  338. moduleDoNotConvert: map[string]bool{
  339. "foo": true,
  340. },
  341. },
  342. },
  343. }
  344. for _, test := range testCases {
  345. t.Run(test.description, func(t *testing.T) {
  346. bcc := &TestBazelConversionContext{
  347. omc: bazel.OtherModuleTestContext{
  348. Modules: []bazel.TestModuleInfo{
  349. test.module.TestModuleInfo,
  350. },
  351. },
  352. allowlist: test.allowlist,
  353. }
  354. shouldConvert := test.module.shouldConvertWithBp2build(bcc, test.module.TestModuleInfo)
  355. if test.shouldConvert != shouldConvert {
  356. t.Errorf("Module shouldConvert expected to be: %v, but was: %v", test.shouldConvert, shouldConvert)
  357. }
  358. errorsMatch := true
  359. if len(test.expectedErrors) != len(bcc.errors) {
  360. errorsMatch = false
  361. } else {
  362. for i, err := range test.expectedErrors {
  363. if err != bcc.errors[i] {
  364. errorsMatch = false
  365. }
  366. }
  367. }
  368. if !errorsMatch {
  369. t.Errorf("Expected errors to be: %v, but were: %v", test.expectedErrors, bcc.errors)
  370. }
  371. })
  372. }
  373. }
  374. func TestBp2buildAllowList(t *testing.T) {
  375. allowlist := GetBp2BuildAllowList()
  376. for k, v := range allowlists.Bp2buildDefaultConfig {
  377. if allowlist.defaultConfig[k] != v {
  378. t.Errorf("bp2build default config of %s: expected: %v, got: %v", k, v, allowlist.defaultConfig[k])
  379. }
  380. }
  381. for k, v := range allowlists.Bp2buildKeepExistingBuildFile {
  382. if allowlist.keepExistingBuildFile[k] != v {
  383. t.Errorf("bp2build keep existing build file of %s: expected: %v, got: %v", k, v, allowlist.keepExistingBuildFile[k])
  384. }
  385. }
  386. for _, k := range allowlists.Bp2buildModuleTypeAlwaysConvertList {
  387. if !allowlist.moduleTypeAlwaysConvert[k] {
  388. t.Errorf("bp2build module type always convert of %s: expected: true, got: %v", k, allowlist.moduleTypeAlwaysConvert[k])
  389. }
  390. }
  391. for _, k := range allowlists.Bp2buildModuleDoNotConvertList {
  392. if !allowlist.moduleDoNotConvert[k] {
  393. t.Errorf("bp2build module do not convert of %s: expected: true, got: %v", k, allowlist.moduleDoNotConvert[k])
  394. }
  395. }
  396. }
  397. func TestShouldKeepExistingBuildFileForDir(t *testing.T) {
  398. allowlist := NewBp2BuildAllowlist()
  399. // entry "a/b2/c2" is moot because of its parent "a/b2"
  400. allowlist.SetKeepExistingBuildFile(map[string]bool{"a": false, "a/b1": false, "a/b2": true, "a/b1/c1": true, "a/b2/c2": false})
  401. truths := []string{"a", "a/b1", "a/b2", "a/b1/c1", "a/b2/c", "a/b2/c2", "a/b2/c2/d"}
  402. falsities := []string{"a1", "a/b", "a/b1/c"}
  403. for _, dir := range truths {
  404. if !allowlist.ShouldKeepExistingBuildFileForDir(dir) {
  405. t.Errorf("%s expected TRUE but was FALSE", dir)
  406. }
  407. }
  408. for _, dir := range falsities {
  409. if allowlist.ShouldKeepExistingBuildFileForDir(dir) {
  410. t.Errorf("%s expected FALSE but was TRUE", dir)
  411. }
  412. }
  413. }
  414. type mixedBuildModule struct {
  415. ModuleBase
  416. BazelModuleBase
  417. props struct {
  418. Deps []string
  419. Mixed_build_incompatible *bool
  420. QueuedBazelCall bool `blueprint:"mutated"`
  421. }
  422. }
  423. type mixedBuildModuleInfo struct {
  424. QueuedBazelCall bool
  425. }
  426. var mixedBuildModuleProvider = blueprint.NewProvider(mixedBuildModuleInfo{})
  427. func mixedBuildModuleFactory() Module {
  428. m := &mixedBuildModule{}
  429. m.AddProperties(&m.props)
  430. InitAndroidArchModule(m, HostAndDeviceDefault, MultilibBoth)
  431. InitBazelModule(m)
  432. return m
  433. }
  434. func (m *mixedBuildModule) ConvertWithBp2build(ctx TopDownMutatorContext) {
  435. }
  436. func (m *mixedBuildModule) DepsMutator(ctx BottomUpMutatorContext) {
  437. ctx.AddDependency(ctx.Module(), installDepTag{}, m.props.Deps...)
  438. }
  439. func (m *mixedBuildModule) GenerateAndroidBuildActions(ctx ModuleContext) {
  440. }
  441. func (m *mixedBuildModule) IsMixedBuildSupported(ctx BaseModuleContext) bool {
  442. return !proptools.Bool(m.props.Mixed_build_incompatible)
  443. }
  444. func (m *mixedBuildModule) QueueBazelCall(ctx BaseModuleContext) {
  445. m.props.QueuedBazelCall = true
  446. }
  447. func (m *mixedBuildModule) ProcessBazelQueryResponse(ctx ModuleContext) {
  448. ctx.SetProvider(mixedBuildModuleProvider, mixedBuildModuleInfo{
  449. QueuedBazelCall: m.props.QueuedBazelCall,
  450. })
  451. }
  452. var prepareForMixedBuildTests = FixtureRegisterWithContext(func(ctx RegistrationContext) {
  453. ctx.RegisterModuleType("deps", mixedBuildModuleFactory)
  454. RegisterMixedBuildsMutator(ctx)
  455. })
  456. func TestMixedBuildsEnabledForType(t *testing.T) {
  457. baseBp := `
  458. deps {
  459. name: "foo",
  460. deps: ["bar"],
  461. target: { windows: { enabled: true } },
  462. %s
  463. }
  464. `
  465. depBp := `
  466. deps {
  467. name: "bar",
  468. target: {
  469. windows: {
  470. enabled: true,
  471. },
  472. },
  473. }
  474. `
  475. testCases := []struct {
  476. desc string
  477. variant *string
  478. missingDeps bool
  479. extraBpInfo string
  480. mixedBuildsEnabled bool
  481. }{
  482. {
  483. desc: "mixed builds works",
  484. mixedBuildsEnabled: true,
  485. extraBpInfo: `bazel_module: { bp2build_available: true },`,
  486. },
  487. {
  488. desc: "missing deps",
  489. missingDeps: true,
  490. mixedBuildsEnabled: false,
  491. extraBpInfo: `bazel_module: { bp2build_available: true },`,
  492. },
  493. {
  494. desc: "windows no mixed builds",
  495. mixedBuildsEnabled: false,
  496. variant: proptools.StringPtr("windows_x86"),
  497. extraBpInfo: `bazel_module: { bp2build_available: true },`,
  498. },
  499. {
  500. desc: "mixed builds disabled by type",
  501. mixedBuildsEnabled: false,
  502. extraBpInfo: `mixed_build_incompatible: true,
  503. bazel_module: { bp2build_available: true },`,
  504. },
  505. {
  506. desc: "mixed builds not bp2build available",
  507. mixedBuildsEnabled: false,
  508. extraBpInfo: `bazel_module: { bp2build_available: false },`,
  509. },
  510. }
  511. for _, tc := range testCases {
  512. t.Run(tc.desc, func(t *testing.T) {
  513. handlers := GroupFixturePreparers(
  514. prepareForMixedBuildTests,
  515. PrepareForTestWithArchMutator,
  516. FixtureModifyConfig(func(config Config) {
  517. config.BazelContext = MockBazelContext{
  518. OutputBaseDir: "base",
  519. }
  520. config.Targets[Windows] = []Target{
  521. {Windows, Arch{ArchType: X86_64}, NativeBridgeDisabled, "", "", true},
  522. {Windows, Arch{ArchType: X86}, NativeBridgeDisabled, "", "", true},
  523. }
  524. }),
  525. )
  526. bp := fmt.Sprintf(baseBp, tc.extraBpInfo)
  527. if tc.missingDeps {
  528. handlers = GroupFixturePreparers(
  529. handlers,
  530. PrepareForTestWithAllowMissingDependencies,
  531. )
  532. } else {
  533. bp += depBp
  534. }
  535. result := handlers.RunTestWithBp(t, bp)
  536. variant := proptools.StringDefault(tc.variant, "android_arm64_armv8-a")
  537. m := result.ModuleForTests("foo", variant)
  538. mixedBuildModuleInfo := result.TestContext.ModuleProvider(m.Module(), mixedBuildModuleProvider).(mixedBuildModuleInfo)
  539. if w, g := tc.mixedBuildsEnabled, mixedBuildModuleInfo.QueuedBazelCall; w != g {
  540. t.Errorf("Expected mixed builds enabled %t, got mixed builds enabled %t", w, g)
  541. }
  542. })
  543. }
  544. }