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