diff --git a/android/neverallow.go b/android/neverallow.go index 23b645413..8355bb3b8 100644 --- a/android/neverallow.go +++ b/android/neverallow.go @@ -175,6 +175,8 @@ func neverallowMutator(ctx BottomUpMutatorContext) { dir := ctx.ModuleDir() + "/" properties := m.GetProperties() + osClass := ctx.Module().Target().Os.Class + for _, r := range neverallows { n := r.(*rule) if !n.appliesToPath(dir) { @@ -189,6 +191,14 @@ func neverallowMutator(ctx BottomUpMutatorContext) { continue } + if !n.appliesToOsClass(osClass) { + continue + } + + if !n.appliesToDirectDeps(ctx) { + continue + } + ctx.ModuleErrorf("violates " + n.String()) } } @@ -246,6 +256,10 @@ type Rule interface { NotIn(path ...string) Rule + InDirectDeps(deps ...string) Rule + + WithOsClass(osClasses ...OsClass) Rule + ModuleType(types ...string) Rule NotModuleType(types ...string) Rule @@ -268,6 +282,10 @@ type rule struct { paths []string unlessPaths []string + directDeps map[string]bool + + osClasses []OsClass + moduleTypes []string unlessModuleTypes []string @@ -277,7 +295,7 @@ type rule struct { // Create a new NeverAllow rule. func NeverAllow() Rule { - return &rule{} + return &rule{directDeps: make(map[string]bool)} } func (r *rule) In(path ...string) Rule { @@ -290,6 +308,18 @@ func (r *rule) NotIn(path ...string) Rule { return r } +func (r *rule) InDirectDeps(deps ...string) Rule { + for _, d := range deps { + r.directDeps[d] = true + } + return r +} + +func (r *rule) WithOsClass(osClasses ...OsClass) Rule { + r.osClasses = append(r.osClasses, osClasses...) + return r +} + func (r *rule) ModuleType(types ...string) Rule { r.moduleTypes = append(r.moduleTypes, types...) return r @@ -356,6 +386,12 @@ func (r *rule) String() string { for _, v := range r.unlessProps { s += " -" + strings.Join(v.fields, ".") + v.matcher.String() } + for k := range r.directDeps { + s += " deps:" + k + } + for _, v := range r.osClasses { + s += " os:" + v.String() + } if len(r.reason) != 0 { s += " which is restricted because " + r.reason } @@ -368,6 +404,36 @@ func (r *rule) appliesToPath(dir string) bool { return includePath && !excludePath } +func (r *rule) appliesToDirectDeps(ctx BottomUpMutatorContext) bool { + if len(r.directDeps) == 0 { + return true + } + + matches := false + ctx.VisitDirectDeps(func(m Module) { + if !matches { + name := ctx.OtherModuleName(m) + matches = r.directDeps[name] + } + }) + + return matches +} + +func (r *rule) appliesToOsClass(osClass OsClass) bool { + if len(r.osClasses) == 0 { + return true + } + + for _, c := range r.osClasses { + if c == osClass { + return true + } + } + + return false +} + func (r *rule) appliesToModuleType(moduleType string) bool { return (len(r.moduleTypes) == 0 || InList(moduleType, r.moduleTypes)) && !InList(moduleType, r.unlessModuleTypes) } diff --git a/android/neverallow_test.go b/android/neverallow_test.go index 02b436211..920b9a55c 100644 --- a/android/neverallow_test.go +++ b/android/neverallow_test.go @@ -16,13 +16,43 @@ package android import ( "testing" + + "github.com/google/blueprint" ) +func init() { + // Add extra rules needed for testing. + AddNeverAllowRules( + NeverAllow().InDirectDeps("not_allowed_in_direct_deps"), + ) +} + var neverallowTests = []struct { name string fs map[string][]byte expectedError string }{ + // Test General Functionality + + // in direct deps tests + { + name: "not_allowed_in_direct_deps", + fs: map[string][]byte{ + "top/Blueprints": []byte(` + cc_library { + name: "not_allowed_in_direct_deps", + }`), + "other/Blueprints": []byte(` + cc_library { + name: "libother", + static_libs: ["not_allowed_in_direct_deps"], + }`), + }, + expectedError: `module "libother": violates neverallow deps:not_allowed_in_direct_deps`, + }, + + // Test specific rules + // include_dir rule tests { name: "include_dir not allowed to reference art", @@ -242,6 +272,7 @@ func testNeverallow(t *testing.T, config Config, fs map[string][]byte) (*TestCon type mockCcLibraryProperties struct { Include_dirs []string Vendor_available *bool + Static_libs []string Vndk struct { Enabled *bool @@ -272,6 +303,19 @@ func newMockCcLibraryModule() Module { return m } +type neverallowTestDependencyTag struct { + blueprint.BaseDependencyTag + name string +} + +var staticDepTag = neverallowTestDependencyTag{name: "static"} + +func (c *mockCcLibraryModule) DepsMutator(ctx BottomUpMutatorContext) { + for _, lib := range c.properties.Static_libs { + ctx.AddDependency(ctx.Module(), staticDepTag, lib) + } +} + func (p *mockCcLibraryModule) GenerateAndroidBuildActions(ModuleContext) { }