neverallow_test.go 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469
  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 android
  15. import (
  16. "regexp"
  17. "testing"
  18. "github.com/google/blueprint"
  19. )
  20. var neverallowTests = []struct {
  21. // The name of the test.
  22. name string
  23. // Optional test specific rules. If specified then they are used instead of the default rules.
  24. rules []Rule
  25. // Additional contents to add to the virtual filesystem used by the tests.
  26. fs MockFS
  27. // The expected error patterns. If empty then no errors are expected, otherwise each error
  28. // reported must be matched by at least one of these patterns. A pattern matches if the error
  29. // message contains the pattern. A pattern does not have to match the whole error message.
  30. expectedErrors []string
  31. }{
  32. // Test General Functionality
  33. // in direct deps tests
  34. {
  35. name: "not_allowed_in_direct_deps",
  36. rules: []Rule{
  37. NeverAllow().InDirectDeps("not_allowed_in_direct_deps"),
  38. },
  39. fs: map[string][]byte{
  40. "top/Android.bp": []byte(`
  41. cc_library {
  42. name: "not_allowed_in_direct_deps",
  43. }`),
  44. "other/Android.bp": []byte(`
  45. cc_library {
  46. name: "libother",
  47. static_libs: ["not_allowed_in_direct_deps"],
  48. }`),
  49. },
  50. expectedErrors: []string{
  51. regexp.QuoteMeta("module \"libother\": violates neverallow requirements. Not allowed:\n\tdep(s): [\"not_allowed_in_direct_deps\"]"),
  52. },
  53. },
  54. {
  55. name: "multiple constraints",
  56. rules: []Rule{
  57. NeverAllow().
  58. InDirectDeps("not_allowed_in_direct_deps").
  59. In("other").
  60. ModuleType("cc_library").
  61. NotIn("top").
  62. NotModuleType("cc_binary"),
  63. },
  64. fs: map[string][]byte{
  65. "top/Android.bp": []byte(`
  66. cc_library {
  67. name: "not_allowed_in_direct_deps",
  68. }`),
  69. "other/Android.bp": []byte(`
  70. cc_library {
  71. name: "libother",
  72. static_libs: ["not_allowed_in_direct_deps"],
  73. }`),
  74. },
  75. expectedErrors: []string{
  76. regexp.QuoteMeta(`module "libother": violates neverallow requirements. Not allowed:
  77. in dirs: ["other/"]
  78. module types: ["cc_library"]
  79. dep(s): ["not_allowed_in_direct_deps"]
  80. EXCEPT in dirs: ["top/"]
  81. EXCEPT module types: ["cc_binary"]`),
  82. },
  83. },
  84. // Test android specific rules
  85. // include_dir rule tests
  86. {
  87. name: "include_dir not allowed to reference art",
  88. fs: map[string][]byte{
  89. "other/Android.bp": []byte(`
  90. cc_library {
  91. name: "libother",
  92. include_dirs: ["art/libdexfile/include"],
  93. }`),
  94. },
  95. expectedErrors: []string{
  96. "all usages of 'art' have been migrated",
  97. },
  98. },
  99. {
  100. name: "include_dir not allowed to reference art",
  101. fs: map[string][]byte{
  102. "system/libfmq/Android.bp": []byte(`
  103. cc_library {
  104. name: "libother",
  105. include_dirs: ["any/random/file"],
  106. }`),
  107. },
  108. expectedErrors: []string{
  109. "all usages of them in 'system/libfmq' have been migrated",
  110. },
  111. },
  112. {
  113. name: "include_dir can work",
  114. fs: map[string][]byte{
  115. "other/Android.bp": []byte(`
  116. cc_library {
  117. name: "libother",
  118. include_dirs: ["another/include"],
  119. }`),
  120. },
  121. },
  122. // Treble rule tests
  123. {
  124. name: "no vndk.enabled under vendor directory",
  125. fs: map[string][]byte{
  126. "vendor/Android.bp": []byte(`
  127. cc_library {
  128. name: "libvndk",
  129. vendor_available: true,
  130. vndk: {
  131. enabled: true,
  132. },
  133. }`),
  134. },
  135. expectedErrors: []string{
  136. "VNDK can never contain a library that is device dependent",
  137. },
  138. },
  139. {
  140. name: "no vndk.enabled under device directory",
  141. fs: map[string][]byte{
  142. "device/Android.bp": []byte(`
  143. cc_library {
  144. name: "libvndk",
  145. vendor_available: true,
  146. vndk: {
  147. enabled: true,
  148. },
  149. }`),
  150. },
  151. expectedErrors: []string{
  152. "VNDK can never contain a library that is device dependent",
  153. },
  154. },
  155. {
  156. name: "vndk-ext under vendor or device directory",
  157. fs: map[string][]byte{
  158. "device/Android.bp": []byte(`
  159. cc_library {
  160. name: "libvndk1_ext",
  161. vendor: true,
  162. vndk: {
  163. enabled: true,
  164. },
  165. }`),
  166. "vendor/Android.bp": []byte(`
  167. cc_library {
  168. name: "libvndk2_ext",
  169. vendor: true,
  170. vndk: {
  171. enabled: true,
  172. },
  173. }`),
  174. },
  175. },
  176. {
  177. name: "no enforce_vintf_manifest.cflags",
  178. fs: map[string][]byte{
  179. "Android.bp": []byte(`
  180. cc_library {
  181. name: "libexample",
  182. product_variables: {
  183. enforce_vintf_manifest: {
  184. cflags: ["-DSHOULD_NOT_EXIST"],
  185. },
  186. },
  187. }`),
  188. },
  189. expectedErrors: []string{
  190. "manifest enforcement should be independent",
  191. },
  192. },
  193. {
  194. name: "no treble_linker_namespaces.cflags",
  195. fs: map[string][]byte{
  196. "Android.bp": []byte(`
  197. cc_library {
  198. name: "libexample",
  199. product_variables: {
  200. treble_linker_namespaces: {
  201. cflags: ["-DSHOULD_NOT_EXIST"],
  202. },
  203. },
  204. }`),
  205. },
  206. expectedErrors: []string{
  207. "nothing should care if linker namespaces are enabled or not",
  208. },
  209. },
  210. {
  211. name: "libc_bionic_ndk treble_linker_namespaces.cflags",
  212. fs: map[string][]byte{
  213. "Android.bp": []byte(`
  214. cc_library {
  215. name: "libc_bionic_ndk",
  216. product_variables: {
  217. treble_linker_namespaces: {
  218. cflags: ["-DSHOULD_NOT_EXIST"],
  219. },
  220. },
  221. }`),
  222. },
  223. },
  224. {
  225. name: "java_device_for_host",
  226. fs: map[string][]byte{
  227. "Android.bp": []byte(`
  228. java_device_for_host {
  229. name: "device_for_host",
  230. libs: ["core-libart"],
  231. }`),
  232. },
  233. expectedErrors: []string{
  234. "java_device_for_host can only be used in allowed projects",
  235. },
  236. },
  237. // CC sdk rule tests
  238. {
  239. name: `"sdk_variant_only" outside allowed list`,
  240. fs: map[string][]byte{
  241. "Android.bp": []byte(`
  242. cc_library {
  243. name: "outside_allowed_list",
  244. sdk_version: "current",
  245. sdk_variant_only: true,
  246. }`),
  247. },
  248. expectedErrors: []string{
  249. `module "outside_allowed_list": violates neverallow`,
  250. },
  251. },
  252. {
  253. name: `"sdk_variant_only: false" outside allowed list`,
  254. fs: map[string][]byte{
  255. "Android.bp": []byte(`
  256. cc_library {
  257. name: "outside_allowed_list",
  258. sdk_version: "current",
  259. sdk_variant_only: false,
  260. }`),
  261. },
  262. expectedErrors: []string{
  263. `module "outside_allowed_list": violates neverallow`,
  264. },
  265. },
  266. {
  267. name: `"platform" outside allowed list`,
  268. fs: map[string][]byte{
  269. "Android.bp": []byte(`
  270. cc_library {
  271. name: "outside_allowed_list",
  272. platform: {
  273. shared_libs: ["libfoo"],
  274. },
  275. }`),
  276. },
  277. expectedErrors: []string{
  278. `module "outside_allowed_list": violates neverallow`,
  279. },
  280. },
  281. {
  282. name: "uncompress_dex inside art",
  283. fs: map[string][]byte{
  284. "art/Android.bp": []byte(`
  285. java_library {
  286. name: "inside_art_libraries",
  287. uncompress_dex: true,
  288. }`),
  289. },
  290. },
  291. {
  292. name: "uncompress_dex outside art",
  293. fs: map[string][]byte{
  294. "other/Android.bp": []byte(`
  295. java_library {
  296. name: "outside_art_libraries",
  297. uncompress_dex: true,
  298. }`),
  299. },
  300. expectedErrors: []string{
  301. "module \"outside_art_libraries\": violates neverallow",
  302. },
  303. },
  304. // Tests for the rule prohibiting the use of framework
  305. {
  306. name: "prohibit framework",
  307. fs: map[string][]byte{
  308. "Android.bp": []byte(`
  309. java_library {
  310. name: "foo",
  311. libs: ["framework"],
  312. sdk_version: "current",
  313. }`),
  314. },
  315. expectedErrors: []string{
  316. "framework can't be used when building against SDK",
  317. },
  318. },
  319. // Test for the rule restricting use of implementation_installable
  320. {
  321. name: `"implementation_installable" outside allowed list`,
  322. fs: map[string][]byte{
  323. "Android.bp": []byte(`
  324. cc_library {
  325. name: "outside_allowed_list",
  326. stubs: {
  327. implementation_installable: true,
  328. },
  329. }`),
  330. },
  331. expectedErrors: []string{
  332. `module "outside_allowed_list": violates neverallow`,
  333. },
  334. },
  335. // Test for the rule restricting use of exclude_static_libs
  336. {
  337. name: `"exclude_static_libs" outside allowed directory`,
  338. fs: map[string][]byte{
  339. "a/b/Android.bp": []byte(`
  340. java_library {
  341. name: "baz",
  342. exclude_static_libs: [
  343. "bar",
  344. ],
  345. }
  346. `),
  347. },
  348. expectedErrors: []string{
  349. `exclude_static_libs property is only allowed for java modules defined in build/soong, libcore, and frameworks/base/api`,
  350. },
  351. },
  352. }
  353. var prepareForNeverAllowTest = GroupFixturePreparers(
  354. FixtureRegisterWithContext(func(ctx RegistrationContext) {
  355. ctx.RegisterModuleType("cc_library", newMockCcLibraryModule)
  356. ctx.RegisterModuleType("java_library", newMockJavaLibraryModule)
  357. ctx.RegisterModuleType("java_library_host", newMockJavaLibraryModule)
  358. ctx.RegisterModuleType("java_device_for_host", newMockJavaLibraryModule)
  359. }),
  360. )
  361. func TestNeverallow(t *testing.T) {
  362. for _, test := range neverallowTests {
  363. t.Run(test.name, func(t *testing.T) {
  364. GroupFixturePreparers(
  365. prepareForNeverAllowTest,
  366. PrepareForTestWithNeverallowRules(test.rules),
  367. test.fs.AddToFixture(),
  368. ).
  369. ExtendWithErrorHandler(FixtureExpectsAllErrorsToMatchAPattern(test.expectedErrors)).
  370. RunTest(t)
  371. })
  372. }
  373. }
  374. type mockCcLibraryProperties struct {
  375. Include_dirs []string
  376. Vendor_available *bool
  377. Static_libs []string
  378. Sdk_version *string
  379. Sdk_variant_only *bool
  380. Vndk struct {
  381. Enabled *bool
  382. Support_system_process *bool
  383. Extends *string
  384. }
  385. Product_variables struct {
  386. Enforce_vintf_manifest struct {
  387. Cflags []string
  388. }
  389. Treble_linker_namespaces struct {
  390. Cflags []string
  391. }
  392. }
  393. Platform struct {
  394. Shared_libs []string
  395. }
  396. Stubs struct {
  397. Implementation_installable *bool
  398. }
  399. }
  400. type mockCcLibraryModule struct {
  401. ModuleBase
  402. properties mockCcLibraryProperties
  403. }
  404. func newMockCcLibraryModule() Module {
  405. m := &mockCcLibraryModule{}
  406. m.AddProperties(&m.properties)
  407. InitAndroidModule(m)
  408. return m
  409. }
  410. type neverallowTestDependencyTag struct {
  411. blueprint.BaseDependencyTag
  412. name string
  413. }
  414. var staticDepTag = neverallowTestDependencyTag{name: "static"}
  415. func (c *mockCcLibraryModule) DepsMutator(ctx BottomUpMutatorContext) {
  416. for _, lib := range c.properties.Static_libs {
  417. ctx.AddDependency(ctx.Module(), staticDepTag, lib)
  418. }
  419. }
  420. func (p *mockCcLibraryModule) GenerateAndroidBuildActions(ModuleContext) {
  421. }
  422. type mockJavaLibraryProperties struct {
  423. Libs []string
  424. Sdk_version *string
  425. Uncompress_dex *bool
  426. Exclude_static_libs []string
  427. }
  428. type mockJavaLibraryModule struct {
  429. ModuleBase
  430. properties mockJavaLibraryProperties
  431. }
  432. func newMockJavaLibraryModule() Module {
  433. m := &mockJavaLibraryModule{}
  434. m.AddProperties(&m.properties)
  435. InitAndroidModule(m)
  436. return m
  437. }
  438. func (p *mockJavaLibraryModule) GenerateAndroidBuildActions(ModuleContext) {
  439. }