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