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 MockFS 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 not allowed to reference art", 80 fs: map[string][]byte{ 81 "system/libfmq/Android.bp": []byte(` 82 cc_library { 83 name: "libother", 84 include_dirs: ["any/random/file"], 85 }`), 86 }, 87 expectedErrors: []string{ 88 "all usages of them in 'system/libfmq' have been migrated", 89 }, 90 }, 91 { 92 name: "include_dir can work", 93 fs: map[string][]byte{ 94 "other/Android.bp": []byte(` 95 cc_library { 96 name: "libother", 97 include_dirs: ["another/include"], 98 }`), 99 }, 100 }, 101 // Treble rule tests 102 { 103 name: "no vndk.enabled under vendor directory", 104 fs: map[string][]byte{ 105 "vendor/Android.bp": []byte(` 106 cc_library { 107 name: "libvndk", 108 vendor_available: true, 109 vndk: { 110 enabled: true, 111 }, 112 }`), 113 }, 114 expectedErrors: []string{ 115 "VNDK can never contain a library that is device dependent", 116 }, 117 }, 118 { 119 name: "no vndk.enabled under device directory", 120 fs: map[string][]byte{ 121 "device/Android.bp": []byte(` 122 cc_library { 123 name: "libvndk", 124 vendor_available: true, 125 vndk: { 126 enabled: true, 127 }, 128 }`), 129 }, 130 expectedErrors: []string{ 131 "VNDK can never contain a library that is device dependent", 132 }, 133 }, 134 { 135 name: "vndk-ext under vendor or device directory", 136 fs: map[string][]byte{ 137 "device/Android.bp": []byte(` 138 cc_library { 139 name: "libvndk1_ext", 140 vendor: true, 141 vndk: { 142 enabled: true, 143 }, 144 }`), 145 "vendor/Android.bp": []byte(` 146 cc_library { 147 name: "libvndk2_ext", 148 vendor: true, 149 vndk: { 150 enabled: true, 151 }, 152 }`), 153 }, 154 }, 155 156 { 157 name: "no enforce_vintf_manifest.cflags", 158 fs: map[string][]byte{ 159 "Android.bp": []byte(` 160 cc_library { 161 name: "libexample", 162 product_variables: { 163 enforce_vintf_manifest: { 164 cflags: ["-DSHOULD_NOT_EXIST"], 165 }, 166 }, 167 }`), 168 }, 169 expectedErrors: []string{ 170 "manifest enforcement should be independent", 171 }, 172 }, 173 174 { 175 name: "no treble_linker_namespaces.cflags", 176 fs: map[string][]byte{ 177 "Android.bp": []byte(` 178 cc_library { 179 name: "libexample", 180 product_variables: { 181 treble_linker_namespaces: { 182 cflags: ["-DSHOULD_NOT_EXIST"], 183 }, 184 }, 185 }`), 186 }, 187 expectedErrors: []string{ 188 "nothing should care if linker namespaces are enabled or not", 189 }, 190 }, 191 { 192 name: "libc_bionic_ndk treble_linker_namespaces.cflags", 193 fs: map[string][]byte{ 194 "Android.bp": []byte(` 195 cc_library { 196 name: "libc_bionic_ndk", 197 product_variables: { 198 treble_linker_namespaces: { 199 cflags: ["-DSHOULD_NOT_EXIST"], 200 }, 201 }, 202 }`), 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 // CC sdk rule tests 219 { 220 name: `"sdk_variant_only" outside allowed list`, 221 fs: map[string][]byte{ 222 "Android.bp": []byte(` 223 cc_library { 224 name: "outside_allowed_list", 225 sdk_version: "current", 226 sdk_variant_only: true, 227 }`), 228 }, 229 expectedErrors: []string{ 230 `module "outside_allowed_list": violates neverallow`, 231 }, 232 }, 233 { 234 name: `"sdk_variant_only: false" outside allowed list`, 235 fs: map[string][]byte{ 236 "Android.bp": []byte(` 237 cc_library { 238 name: "outside_allowed_list", 239 sdk_version: "current", 240 sdk_variant_only: false, 241 }`), 242 }, 243 expectedErrors: []string{ 244 `module "outside_allowed_list": violates neverallow`, 245 }, 246 }, 247 { 248 name: `"platform" outside allowed list`, 249 fs: map[string][]byte{ 250 "Android.bp": []byte(` 251 cc_library { 252 name: "outside_allowed_list", 253 platform: { 254 shared_libs: ["libfoo"], 255 }, 256 }`), 257 }, 258 expectedErrors: []string{ 259 `module "outside_allowed_list": violates neverallow`, 260 }, 261 }, 262 { 263 name: "uncompress_dex inside art", 264 fs: map[string][]byte{ 265 "art/Android.bp": []byte(` 266 java_library { 267 name: "inside_art_libraries", 268 uncompress_dex: true, 269 }`), 270 }, 271 }, 272 { 273 name: "uncompress_dex outside art", 274 fs: map[string][]byte{ 275 "other/Android.bp": []byte(` 276 java_library { 277 name: "outside_art_libraries", 278 uncompress_dex: true, 279 }`), 280 }, 281 expectedErrors: []string{ 282 "module \"outside_art_libraries\": violates neverallow", 283 }, 284 }, 285 { 286 name: "disallowed makefile_goal", 287 fs: map[string][]byte{ 288 "Android.bp": []byte(` 289 makefile_goal { 290 name: "foo", 291 product_out_path: "boot/trap.img" 292 } 293 `), 294 }, 295 expectedErrors: []string{ 296 "Only boot images may be imported as a makefile goal.", 297 }, 298 }, 299} 300 301var prepareForNeverAllowTest = GroupFixturePreparers( 302 FixtureRegisterWithContext(func(ctx RegistrationContext) { 303 ctx.RegisterModuleType("cc_library", newMockCcLibraryModule) 304 ctx.RegisterModuleType("java_library", newMockJavaLibraryModule) 305 ctx.RegisterModuleType("java_library_host", newMockJavaLibraryModule) 306 ctx.RegisterModuleType("java_device_for_host", newMockJavaLibraryModule) 307 ctx.RegisterModuleType("makefile_goal", newMockMakefileGoalModule) 308 }), 309) 310 311func TestNeverallow(t *testing.T) { 312 for _, test := range neverallowTests { 313 t.Run(test.name, func(t *testing.T) { 314 GroupFixturePreparers( 315 prepareForNeverAllowTest, 316 PrepareForTestWithNeverallowRules(test.rules), 317 test.fs.AddToFixture(), 318 ). 319 ExtendWithErrorHandler(FixtureExpectsAllErrorsToMatchAPattern(test.expectedErrors)). 320 RunTest(t) 321 }) 322 } 323} 324 325type mockCcLibraryProperties struct { 326 Include_dirs []string 327 Vendor_available *bool 328 Static_libs []string 329 Sdk_version *string 330 Sdk_variant_only *bool 331 332 Vndk struct { 333 Enabled *bool 334 Support_system_process *bool 335 Extends *string 336 } 337 338 Product_variables struct { 339 Enforce_vintf_manifest struct { 340 Cflags []string 341 } 342 343 Treble_linker_namespaces struct { 344 Cflags []string 345 } 346 } 347 348 Platform struct { 349 Shared_libs []string 350 } 351} 352 353type mockCcLibraryModule struct { 354 ModuleBase 355 properties mockCcLibraryProperties 356} 357 358func newMockCcLibraryModule() Module { 359 m := &mockCcLibraryModule{} 360 m.AddProperties(&m.properties) 361 InitAndroidModule(m) 362 return m 363} 364 365type neverallowTestDependencyTag struct { 366 blueprint.BaseDependencyTag 367 name string 368} 369 370var staticDepTag = neverallowTestDependencyTag{name: "static"} 371 372func (c *mockCcLibraryModule) DepsMutator(ctx BottomUpMutatorContext) { 373 for _, lib := range c.properties.Static_libs { 374 ctx.AddDependency(ctx.Module(), staticDepTag, lib) 375 } 376} 377 378func (p *mockCcLibraryModule) GenerateAndroidBuildActions(ModuleContext) { 379} 380 381type mockJavaLibraryProperties struct { 382 Libs []string 383 Sdk_version *string 384 Uncompress_dex *bool 385} 386 387type mockJavaLibraryModule struct { 388 ModuleBase 389 properties mockJavaLibraryProperties 390} 391 392func newMockJavaLibraryModule() Module { 393 m := &mockJavaLibraryModule{} 394 m.AddProperties(&m.properties) 395 InitAndroidModule(m) 396 return m 397} 398 399func (p *mockJavaLibraryModule) GenerateAndroidBuildActions(ModuleContext) { 400} 401 402type mockMakefileGoalProperties struct { 403 Product_out_path *string 404} 405 406type mockMakefileGoalModule struct { 407 ModuleBase 408 properties mockMakefileGoalProperties 409} 410 411func newMockMakefileGoalModule() Module { 412 m := &mockMakefileGoalModule{} 413 m.AddProperties(&m.properties) 414 InitAndroidModule(m) 415 return m 416} 417 418func (p *mockMakefileGoalModule) GenerateAndroidBuildActions(ModuleContext) { 419} 420