Merge changes I406c5bef,Ibde685d7,I1c09412d

* changes:
  Allow VNDK extensions under vendor or device
  Add unit tests for android/neverallow.go
  Extract failIfErrored() to android/testing.go
This commit is contained in:
Logan Chien
2018-03-16 01:57:31 +00:00
committed by Gerrit Code Review
10 changed files with 274 additions and 94 deletions

View File

@@ -71,6 +71,7 @@ bootstrap_go_package {
"android/config_test.go", "android/config_test.go",
"android/expand_test.go", "android/expand_test.go",
"android/namespace_test.go", "android/namespace_test.go",
"android/neverallow_test.go",
"android/paths_test.go", "android/paths_test.go",
"android/prebuilt_test.go", "android/prebuilt_test.go",
"android/util_test.go", "android/util_test.go",

View File

@@ -628,7 +628,7 @@ func setupTestExpectErrs(bps map[string]string) (ctx *TestContext, errs []error)
func setupTest(t *testing.T, bps map[string]string) (ctx *TestContext) { func setupTest(t *testing.T, bps map[string]string) (ctx *TestContext) {
ctx, errs := setupTestExpectErrs(bps) ctx, errs := setupTestExpectErrs(bps)
failIfErrored(t, errs) FailIfErrored(t, errs)
return ctx return ctx
} }
@@ -692,12 +692,3 @@ func newTestModule() Module {
InitAndroidModule(m) InitAndroidModule(m)
return m return m
} }
func failIfErrored(t *testing.T, errs []error) {
if len(errs) > 0 {
for _, err := range errs {
t.Error(err)
}
t.FailNow()
}
}

View File

@@ -46,9 +46,15 @@ func registerNeverallowMutator(ctx RegisterMutatorsContext) {
} }
var neverallows = []*rule{ var neverallows = []*rule{
neverallow().in("vendor", "device").with("vndk.enabled", "true"). neverallow().
in("vendor", "device").
with("vndk.enabled", "true").
without("vendor", "true").
because("the VNDK can never contain a library that is device dependent."), because("the VNDK can never contain a library that is device dependent."),
neverallow().with("vndk.enabled", "true").without("owner", ""). neverallow().
with("vndk.enabled", "true").
without("vendor", "true").
without("owner", "").
because("a VNDK module can never have an owner."), because("a VNDK module can never have an owner."),
neverallow().notIn("libcore", "development").with("no_standard_libs", "true"), neverallow().notIn("libcore", "development").with("no_standard_libs", "true"),

217
android/neverallow_test.go Normal file
View File

@@ -0,0 +1,217 @@
// Copyright 2018 Google Inc. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package android
import (
"io/ioutil"
"os"
"testing"
)
var neverallowTests = []struct {
name string
fs map[string][]byte
expectedError string
}{
{
name: "no vndk.enabled under vendor directory",
fs: map[string][]byte{
"vendor/Blueprints": []byte(`
cc_library {
name: "libvndk",
vendor_available: true,
vndk: {
enabled: true,
},
}`),
},
expectedError: "VNDK can never contain a library that is device dependent",
},
{
name: "no vndk.enabled under device directory",
fs: map[string][]byte{
"device/Blueprints": []byte(`
cc_library {
name: "libvndk",
vendor_available: true,
vndk: {
enabled: true,
},
}`),
},
expectedError: "VNDK can never contain a library that is device dependent",
},
{
name: "vndk-ext under vendor or device directory",
fs: map[string][]byte{
"device/Blueprints": []byte(`
cc_library {
name: "libvndk1_ext",
vendor: true,
vndk: {
enabled: true,
},
}`),
"vendor/Blueprints": []byte(`
cc_library {
name: "libvndk2_ext",
vendor: true,
vndk: {
enabled: true,
},
}`),
},
expectedError: "",
},
{
name: "no enforce_vintf_manifest.cflags",
fs: map[string][]byte{
"Blueprints": []byte(`
cc_library {
name: "libexample",
product_variables: {
enforce_vintf_manifest: {
cflags: ["-DSHOULD_NOT_EXIST"],
},
},
}`),
},
expectedError: "manifest enforcement should be independent",
},
{
name: "libhidltransport enforce_vintf_manifest.cflags",
fs: map[string][]byte{
"Blueprints": []byte(`
cc_library {
name: "libhidltransport",
product_variables: {
enforce_vintf_manifest: {
cflags: ["-DSHOULD_NOT_EXIST"],
},
},
}`),
},
expectedError: "",
},
{
name: "no treble_linker_namespaces.cflags",
fs: map[string][]byte{
"Blueprints": []byte(`
cc_library {
name: "libexample",
product_variables: {
treble_linker_namespaces: {
cflags: ["-DSHOULD_NOT_EXIST"],
},
},
}`),
},
expectedError: "nothing should care if linker namespaces are enabled or not",
},
{
name: "libc_bionic_ndk treble_linker_namespaces.cflags",
fs: map[string][]byte{
"Blueprints": []byte(`
cc_library {
name: "libc_bionic_ndk",
product_variables: {
treble_linker_namespaces: {
cflags: ["-DSHOULD_NOT_EXIST"],
},
},
}`),
},
expectedError: "",
},
}
func TestNeverallow(t *testing.T) {
buildDir, err := ioutil.TempDir("", "soong_neverallow_test")
if err != nil {
t.Fatal(err)
}
defer os.RemoveAll(buildDir)
config := TestConfig(buildDir, nil)
for _, test := range neverallowTests {
t.Run(test.name, func(t *testing.T) {
_, errs := testNeverallow(t, config, test.fs)
if test.expectedError == "" {
FailIfErrored(t, errs)
} else {
FailIfNoMatchingErrors(t, test.expectedError, errs)
}
})
}
}
func testNeverallow(t *testing.T, config Config, fs map[string][]byte) (*TestContext, []error) {
ctx := NewTestContext()
ctx.RegisterModuleType("cc_library", ModuleFactoryAdaptor(newMockCcLibraryModule))
ctx.PostDepsMutators(registerNeverallowMutator)
ctx.Register()
ctx.MockFileSystem(fs)
_, errs := ctx.ParseBlueprintsFiles("Blueprints")
if len(errs) > 0 {
return ctx, errs
}
_, errs = ctx.PrepareBuildActions(config)
return ctx, errs
}
type mockProperties struct {
Vendor_available *bool
Vndk struct {
Enabled *bool
Support_system_process *bool
Extends *string
}
Product_variables struct {
Enforce_vintf_manifest struct {
Cflags []string
}
Treble_linker_namespaces struct {
Cflags []string
}
}
}
type mockCcLibraryModule struct {
ModuleBase
properties mockProperties
}
func newMockCcLibraryModule() Module {
m := &mockCcLibraryModule{}
m.AddProperties(&m.properties)
InitAndroidModule(m)
return m
}
func (p *mockCcLibraryModule) DepsMutator(ctx BottomUpMutatorContext) {
}
func (p *mockCcLibraryModule) GenerateAndroidBuildActions(ModuleContext) {
}

View File

@@ -138,9 +138,9 @@ func TestPrebuilts(t *testing.T) {
}) })
_, errs := ctx.ParseBlueprintsFiles("Blueprints") _, errs := ctx.ParseBlueprintsFiles("Blueprints")
fail(t, errs) FailIfErrored(t, errs)
_, errs = ctx.PrepareBuildActions(config) _, errs = ctx.PrepareBuildActions(config)
fail(t, errs) FailIfErrored(t, errs)
foo := ctx.ModuleForTests("foo", "") foo := ctx.ModuleForTests("foo", "")
@@ -231,12 +231,3 @@ func (s *sourceModule) DepsMutator(ctx BottomUpMutatorContext) {
func (s *sourceModule) GenerateAndroidBuildActions(ctx ModuleContext) { func (s *sourceModule) GenerateAndroidBuildActions(ctx ModuleContext) {
} }
func fail(t *testing.T, errs []error) {
if len(errs) > 0 {
for _, err := range errs {
t.Error(err)
}
t.FailNow()
}
}

View File

@@ -17,7 +17,9 @@ package android
import ( import (
"fmt" "fmt"
"path/filepath" "path/filepath"
"regexp"
"strings" "strings"
"testing"
"github.com/google/blueprint" "github.com/google/blueprint"
) )
@@ -152,3 +154,36 @@ func (m TestingModule) Output(file string) BuildParams {
panic(fmt.Errorf("couldn't find output %q.\nall outputs: %v", panic(fmt.Errorf("couldn't find output %q.\nall outputs: %v",
file, searchedOutputs)) file, searchedOutputs))
} }
func FailIfErrored(t *testing.T, errs []error) {
t.Helper()
if len(errs) > 0 {
for _, err := range errs {
t.Error(err)
}
t.FailNow()
}
}
func FailIfNoMatchingErrors(t *testing.T, pattern string, errs []error) {
t.Helper()
matcher, err := regexp.Compile(pattern)
if err != nil {
t.Errorf("failed to compile regular expression %q because %s", pattern, err)
}
found := false
for _, err := range errs {
if matcher.FindStringIndex(err.Error()) != nil {
found = true
break
}
}
if !found {
t.Errorf("missing the expected error %q (checked %d error(s))", pattern, len(errs))
for i, err := range errs {
t.Errorf("errs[%d] = %s", i, err)
}
}
}

View File

@@ -22,7 +22,6 @@ import (
"io/ioutil" "io/ioutil"
"os" "os"
"reflect" "reflect"
"regexp"
"sort" "sort"
"strings" "strings"
"testing" "testing"
@@ -147,9 +146,9 @@ func testCcWithConfig(t *testing.T, bp string, config android.Config) *android.T
ctx := createTestContext(t, config, bp) ctx := createTestContext(t, config, bp)
_, errs := ctx.ParseFileList(".", []string{"Android.bp"}) _, errs := ctx.ParseFileList(".", []string{"Android.bp"})
failIfErrored(t, errs) android.FailIfErrored(t, errs)
_, errs = ctx.PrepareBuildActions(config) _, errs = ctx.PrepareBuildActions(config)
failIfErrored(t, errs) android.FailIfErrored(t, errs)
return ctx return ctx
} }
@@ -178,13 +177,13 @@ func testCcError(t *testing.T, pattern string, bp string) {
_, errs := ctx.ParseFileList(".", []string{"Android.bp"}) _, errs := ctx.ParseFileList(".", []string{"Android.bp"})
if len(errs) > 0 { if len(errs) > 0 {
failIfNoMatchingErrors(t, pattern, errs) android.FailIfNoMatchingErrors(t, pattern, errs)
return return
} }
_, errs = ctx.PrepareBuildActions(config) _, errs = ctx.PrepareBuildActions(config)
if len(errs) > 0 { if len(errs) > 0 {
failIfNoMatchingErrors(t, pattern, errs) android.FailIfNoMatchingErrors(t, pattern, errs)
return return
} }
@@ -1064,38 +1063,6 @@ func TestLinkReordering(t *testing.T) {
} }
} }
func failIfErrored(t *testing.T, errs []error) {
if len(errs) > 0 {
for _, err := range errs {
t.Error(err)
}
t.FailNow()
}
}
func failIfNoMatchingErrors(t *testing.T, pattern string, errs []error) {
matcher, err := regexp.Compile(pattern)
if err != nil {
t.Errorf("failed to compile regular expression %q because %s", pattern, err)
}
found := false
for _, err := range errs {
if matcher.FindStringIndex(err.Error()) != nil {
found = true
break
}
}
if !found {
t.Errorf("missing the expected error %q (checked %d error(s))", pattern, len(errs))
for i, err := range errs {
t.Errorf("errs[%d] = %s", i, err)
}
}
}
func getOutputPaths(ctx *android.TestContext, variant string, moduleNames []string) (paths android.Paths) { func getOutputPaths(ctx *android.TestContext, variant string, moduleNames []string) (paths android.Paths) {
for _, moduleName := range moduleNames { for _, moduleName := range moduleNames {
module := ctx.ModuleForTests(moduleName, variant).Module().(*Module) module := ctx.ModuleForTests(moduleName, variant).Module().(*Module)

View File

@@ -135,9 +135,9 @@ func TestDataTests(t *testing.T) {
ctx.Register() ctx.Register()
_, errs := ctx.ParseBlueprintsFiles("Blueprints") _, errs := ctx.ParseBlueprintsFiles("Blueprints")
fail(t, errs) android.FailIfErrored(t, errs)
_, errs = ctx.PrepareBuildActions(config) _, errs = ctx.PrepareBuildActions(config)
fail(t, errs) android.FailIfErrored(t, errs)
foo := ctx.ModuleForTests("foo", "") foo := ctx.ModuleForTests("foo", "")
@@ -186,12 +186,3 @@ func (test *testDataTest) DepsMutator(ctx android.BottomUpMutatorContext) {
func (test *testDataTest) GenerateAndroidBuildActions(ctx android.ModuleContext) { func (test *testDataTest) GenerateAndroidBuildActions(ctx android.ModuleContext) {
test.data = ctx.ExpandSources(test.Properties.Data, nil) test.data = ctx.ExpandSources(test.Properties.Data, nil)
} }
func fail(t *testing.T, errs []error) {
if len(errs) > 0 {
for _, err := range errs {
t.Error(err)
}
t.FailNow()
}
}

View File

@@ -190,9 +190,9 @@ func testContext(config android.Config, bp string,
func run(t *testing.T, ctx *android.TestContext, config android.Config) { func run(t *testing.T, ctx *android.TestContext, config android.Config) {
t.Helper() t.Helper()
_, errs := ctx.ParseFileList(".", []string{"Android.bp"}) _, errs := ctx.ParseFileList(".", []string{"Android.bp"})
fail(t, errs) android.FailIfErrored(t, errs)
_, errs = ctx.PrepareBuildActions(config) _, errs = ctx.PrepareBuildActions(config)
fail(t, errs) android.FailIfErrored(t, errs)
} }
func testJava(t *testing.T, bp string) *android.TestContext { func testJava(t *testing.T, bp string) *android.TestContext {
@@ -977,13 +977,3 @@ func TestExcludeFileGroupInSrcs(t *testing.T) {
t.Errorf(`foo inputs %v != ["java-fg/c.java"]`, javac.Inputs) t.Errorf(`foo inputs %v != ["java-fg/c.java"]`, javac.Inputs)
} }
} }
func fail(t *testing.T, errs []error) {
t.Helper()
if len(errs) > 0 {
for _, err := range errs {
t.Error(err)
}
t.FailNow()
}
}

View File

@@ -342,7 +342,7 @@ func TestPythonModule(t *testing.T) {
ctx.Register() ctx.Register()
ctx.MockFileSystem(d.mockFiles) ctx.MockFileSystem(d.mockFiles)
_, testErrs := ctx.ParseBlueprintsFiles(bpFile) _, testErrs := ctx.ParseBlueprintsFiles(bpFile)
fail(t, testErrs) android.FailIfErrored(t, testErrs)
_, actErrs := ctx.PrepareBuildActions(config) _, actErrs := ctx.PrepareBuildActions(config)
if len(actErrs) > 0 { if len(actErrs) > 0 {
testErrs = append(testErrs, expectErrors(t, actErrs, d.errors)...) testErrs = append(testErrs, expectErrors(t, actErrs, d.errors)...)
@@ -356,7 +356,7 @@ func TestPythonModule(t *testing.T) {
e.depsSrcsZips)...) e.depsSrcsZips)...)
} }
} }
fail(t, testErrs) android.FailIfErrored(t, testErrs)
}) })
} }
} }
@@ -442,12 +442,3 @@ func setupBuildEnv(t *testing.T) (config android.Config, buildDir string) {
func tearDownBuildEnv(buildDir string) { func tearDownBuildEnv(buildDir string) {
os.RemoveAll(buildDir) os.RemoveAll(buildDir)
} }
func fail(t *testing.T, errs []error) {
if len(errs) > 0 {
for _, err := range errs {
t.Error(err)
}
t.FailNow()
}
}