arch_test.go 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470
  1. // Copyright 2019 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. "reflect"
  17. "runtime"
  18. "testing"
  19. "github.com/google/blueprint/proptools"
  20. )
  21. type Named struct {
  22. A *string `android:"arch_variant"`
  23. B *string
  24. }
  25. type NamedAllFiltered struct {
  26. A *string
  27. }
  28. type NamedNoneFiltered struct {
  29. A *string `android:"arch_variant"`
  30. }
  31. func TestFilterArchStruct(t *testing.T) {
  32. tests := []struct {
  33. name string
  34. in interface{}
  35. out interface{}
  36. filtered bool
  37. }{
  38. // Property tests
  39. {
  40. name: "basic",
  41. in: &struct {
  42. A *string `android:"arch_variant"`
  43. B *string
  44. }{},
  45. out: &struct {
  46. A *string
  47. }{},
  48. filtered: true,
  49. },
  50. {
  51. name: "tags",
  52. in: &struct {
  53. A *string `android:"arch_variant"`
  54. B *string `android:"arch_variant,path"`
  55. C *string `android:"arch_variant,path,variant_prepend"`
  56. D *string `android:"path,variant_prepend,arch_variant"`
  57. E *string `android:"path"`
  58. F *string
  59. }{},
  60. out: &struct {
  61. A *string
  62. B *string
  63. C *string
  64. D *string
  65. }{},
  66. filtered: true,
  67. },
  68. {
  69. name: "all filtered",
  70. in: &struct {
  71. A *string
  72. }{},
  73. out: nil,
  74. filtered: true,
  75. },
  76. {
  77. name: "none filtered",
  78. in: &struct {
  79. A *string `android:"arch_variant"`
  80. }{},
  81. out: &struct {
  82. A *string `android:"arch_variant"`
  83. }{},
  84. filtered: false,
  85. },
  86. // Sub-struct tests
  87. {
  88. name: "substruct",
  89. in: &struct {
  90. A struct {
  91. A *string `android:"arch_variant"`
  92. B *string
  93. } `android:"arch_variant"`
  94. }{},
  95. out: &struct {
  96. A struct {
  97. A *string
  98. }
  99. }{},
  100. filtered: true,
  101. },
  102. {
  103. name: "substruct all filtered",
  104. in: &struct {
  105. A struct {
  106. A *string
  107. } `android:"arch_variant"`
  108. }{},
  109. out: nil,
  110. filtered: true,
  111. },
  112. {
  113. name: "substruct none filtered",
  114. in: &struct {
  115. A struct {
  116. A *string `android:"arch_variant"`
  117. } `android:"arch_variant"`
  118. }{},
  119. out: &struct {
  120. A struct {
  121. A *string `android:"arch_variant"`
  122. } `android:"arch_variant"`
  123. }{},
  124. filtered: false,
  125. },
  126. // Named sub-struct tests
  127. {
  128. name: "named substruct",
  129. in: &struct {
  130. A Named `android:"arch_variant"`
  131. }{},
  132. out: &struct {
  133. A struct {
  134. A *string
  135. }
  136. }{},
  137. filtered: true,
  138. },
  139. {
  140. name: "substruct all filtered",
  141. in: &struct {
  142. A NamedAllFiltered `android:"arch_variant"`
  143. }{},
  144. out: nil,
  145. filtered: true,
  146. },
  147. {
  148. name: "substruct none filtered",
  149. in: &struct {
  150. A NamedNoneFiltered `android:"arch_variant"`
  151. }{},
  152. out: &struct {
  153. A NamedNoneFiltered `android:"arch_variant"`
  154. }{},
  155. filtered: false,
  156. },
  157. // Pointer to sub-struct tests
  158. {
  159. name: "pointer substruct",
  160. in: &struct {
  161. A *struct {
  162. A *string `android:"arch_variant"`
  163. B *string
  164. } `android:"arch_variant"`
  165. }{},
  166. out: &struct {
  167. A *struct {
  168. A *string
  169. }
  170. }{},
  171. filtered: true,
  172. },
  173. {
  174. name: "pointer substruct all filtered",
  175. in: &struct {
  176. A *struct {
  177. A *string
  178. } `android:"arch_variant"`
  179. }{},
  180. out: nil,
  181. filtered: true,
  182. },
  183. {
  184. name: "pointer substruct none filtered",
  185. in: &struct {
  186. A *struct {
  187. A *string `android:"arch_variant"`
  188. } `android:"arch_variant"`
  189. }{},
  190. out: &struct {
  191. A *struct {
  192. A *string `android:"arch_variant"`
  193. } `android:"arch_variant"`
  194. }{},
  195. filtered: false,
  196. },
  197. // Pointer to named sub-struct tests
  198. {
  199. name: "pointer named substruct",
  200. in: &struct {
  201. A *Named `android:"arch_variant"`
  202. }{},
  203. out: &struct {
  204. A *struct {
  205. A *string
  206. }
  207. }{},
  208. filtered: true,
  209. },
  210. {
  211. name: "pointer substruct all filtered",
  212. in: &struct {
  213. A *NamedAllFiltered `android:"arch_variant"`
  214. }{},
  215. out: nil,
  216. filtered: true,
  217. },
  218. {
  219. name: "pointer substruct none filtered",
  220. in: &struct {
  221. A *NamedNoneFiltered `android:"arch_variant"`
  222. }{},
  223. out: &struct {
  224. A *NamedNoneFiltered `android:"arch_variant"`
  225. }{},
  226. filtered: false,
  227. },
  228. }
  229. for _, test := range tests {
  230. t.Run(test.name, func(t *testing.T) {
  231. out, filtered := proptools.FilterPropertyStruct(reflect.TypeOf(test.in), filterArchStruct)
  232. if filtered != test.filtered {
  233. t.Errorf("expected filtered %v, got %v", test.filtered, filtered)
  234. }
  235. expected := reflect.TypeOf(test.out)
  236. if out != expected {
  237. t.Errorf("expected type %v, got %v", expected, out)
  238. }
  239. })
  240. }
  241. }
  242. type archTestModule struct {
  243. ModuleBase
  244. props struct {
  245. Deps []string
  246. }
  247. }
  248. func (m *archTestModule) GenerateAndroidBuildActions(ctx ModuleContext) {
  249. }
  250. func (m *archTestModule) DepsMutator(ctx BottomUpMutatorContext) {
  251. ctx.AddDependency(ctx.Module(), nil, m.props.Deps...)
  252. }
  253. func archTestModuleFactory() Module {
  254. m := &archTestModule{}
  255. m.AddProperties(&m.props)
  256. InitAndroidArchModule(m, HostAndDeviceSupported, MultilibBoth)
  257. return m
  258. }
  259. func TestArchMutator(t *testing.T) {
  260. var buildOSVariants []string
  261. var buildOS32Variants []string
  262. switch runtime.GOOS {
  263. case "linux":
  264. buildOSVariants = []string{"linux_glibc_x86_64", "linux_glibc_x86"}
  265. buildOS32Variants = []string{"linux_glibc_x86"}
  266. case "darwin":
  267. buildOSVariants = []string{"darwin_x86_64"}
  268. buildOS32Variants = nil
  269. }
  270. bp := `
  271. module {
  272. name: "foo",
  273. }
  274. module {
  275. name: "bar",
  276. host_supported: true,
  277. }
  278. module {
  279. name: "baz",
  280. device_supported: false,
  281. }
  282. module {
  283. name: "qux",
  284. host_supported: true,
  285. compile_multilib: "32",
  286. }
  287. `
  288. testCases := []struct {
  289. name string
  290. config func(Config)
  291. fooVariants []string
  292. barVariants []string
  293. bazVariants []string
  294. quxVariants []string
  295. }{
  296. {
  297. name: "normal",
  298. config: nil,
  299. fooVariants: []string{"android_arm64_armv8-a", "android_arm_armv7-a-neon"},
  300. barVariants: append(buildOSVariants, "android_arm64_armv8-a", "android_arm_armv7-a-neon"),
  301. bazVariants: nil,
  302. quxVariants: append(buildOS32Variants, "android_arm_armv7-a-neon"),
  303. },
  304. {
  305. name: "host-only",
  306. config: func(config Config) {
  307. config.BuildOSTarget = Target{}
  308. config.BuildOSCommonTarget = Target{}
  309. config.Targets[Android] = nil
  310. },
  311. fooVariants: nil,
  312. barVariants: buildOSVariants,
  313. bazVariants: nil,
  314. quxVariants: buildOS32Variants,
  315. },
  316. }
  317. enabledVariants := func(ctx *TestContext, name string) []string {
  318. var ret []string
  319. variants := ctx.ModuleVariantsForTests(name)
  320. for _, variant := range variants {
  321. m := ctx.ModuleForTests(name, variant)
  322. if m.Module().Enabled() {
  323. ret = append(ret, variant)
  324. }
  325. }
  326. return ret
  327. }
  328. for _, tt := range testCases {
  329. t.Run(tt.name, func(t *testing.T) {
  330. config := TestArchConfig(buildDir, nil, bp, nil)
  331. ctx := NewTestArchContext()
  332. ctx.RegisterModuleType("module", archTestModuleFactory)
  333. ctx.Register(config)
  334. if tt.config != nil {
  335. tt.config(config)
  336. }
  337. _, errs := ctx.ParseFileList(".", []string{"Android.bp"})
  338. FailIfErrored(t, errs)
  339. _, errs = ctx.PrepareBuildActions(config)
  340. FailIfErrored(t, errs)
  341. if g, w := enabledVariants(ctx, "foo"), tt.fooVariants; !reflect.DeepEqual(w, g) {
  342. t.Errorf("want foo variants:\n%q\ngot:\n%q\n", w, g)
  343. }
  344. if g, w := enabledVariants(ctx, "bar"), tt.barVariants; !reflect.DeepEqual(w, g) {
  345. t.Errorf("want bar variants:\n%q\ngot:\n%q\n", w, g)
  346. }
  347. if g, w := enabledVariants(ctx, "baz"), tt.bazVariants; !reflect.DeepEqual(w, g) {
  348. t.Errorf("want baz variants:\n%q\ngot:\n%q\n", w, g)
  349. }
  350. if g, w := enabledVariants(ctx, "qux"), tt.quxVariants; !reflect.DeepEqual(w, g) {
  351. t.Errorf("want qux variants:\n%q\ngot:\n%q\n", w, g)
  352. }
  353. })
  354. }
  355. }
  356. func TestArchMutatorNativeBridge(t *testing.T) {
  357. bp := `
  358. // This module is only enabled for x86.
  359. module {
  360. name: "foo",
  361. }
  362. // This module is enabled for x86 and arm (via native bridge).
  363. module {
  364. name: "bar",
  365. native_bridge_supported: true,
  366. }
  367. // This module is enabled for arm (native_bridge) only.
  368. module {
  369. name: "baz",
  370. native_bridge_supported: true,
  371. enabled: false,
  372. target: {
  373. native_bridge: {
  374. enabled: true,
  375. }
  376. }
  377. }
  378. `
  379. testCases := []struct {
  380. name string
  381. config func(Config)
  382. fooVariants []string
  383. barVariants []string
  384. bazVariants []string
  385. }{
  386. {
  387. name: "normal",
  388. config: nil,
  389. fooVariants: []string{"android_x86_64_silvermont", "android_x86_silvermont"},
  390. barVariants: []string{"android_x86_64_silvermont", "android_native_bridge_arm64_armv8-a", "android_x86_silvermont", "android_native_bridge_arm_armv7-a-neon"},
  391. bazVariants: []string{"android_native_bridge_arm64_armv8-a", "android_native_bridge_arm_armv7-a-neon"},
  392. },
  393. }
  394. enabledVariants := func(ctx *TestContext, name string) []string {
  395. var ret []string
  396. variants := ctx.ModuleVariantsForTests(name)
  397. for _, variant := range variants {
  398. m := ctx.ModuleForTests(name, variant)
  399. if m.Module().Enabled() {
  400. ret = append(ret, variant)
  401. }
  402. }
  403. return ret
  404. }
  405. for _, tt := range testCases {
  406. t.Run(tt.name, func(t *testing.T) {
  407. config := TestArchConfigNativeBridge(buildDir, nil, bp, nil)
  408. ctx := NewTestArchContext()
  409. ctx.RegisterModuleType("module", archTestModuleFactory)
  410. ctx.Register(config)
  411. if tt.config != nil {
  412. tt.config(config)
  413. }
  414. _, errs := ctx.ParseFileList(".", []string{"Android.bp"})
  415. FailIfErrored(t, errs)
  416. _, errs = ctx.PrepareBuildActions(config)
  417. FailIfErrored(t, errs)
  418. if g, w := enabledVariants(ctx, "foo"), tt.fooVariants; !reflect.DeepEqual(w, g) {
  419. t.Errorf("want foo variants:\n%q\ngot:\n%q\n", w, g)
  420. }
  421. if g, w := enabledVariants(ctx, "bar"), tt.barVariants; !reflect.DeepEqual(w, g) {
  422. t.Errorf("want bar variants:\n%q\ngot:\n%q\n", w, g)
  423. }
  424. if g, w := enabledVariants(ctx, "baz"), tt.bazVariants; !reflect.DeepEqual(w, g) {
  425. t.Errorf("want qux variants:\n%q\ngot:\n%q\n", w, g)
  426. }
  427. })
  428. }
  429. }