Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b1ed497c authored by Logan Chien's avatar Logan Chien
Browse files

Add unit tests for android/neverallow.go

Bug: 74506774
Test: lunch aosp_walleye-userdebug && make  # runs unit tests

Merged-In: Ibde685d7213713be219681cb039ad58a43d9c377
Change-Id: Ibde685d7213713be219681cb039ad58a43d9c377
parent d44aa3b5
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -71,6 +71,7 @@ bootstrap_go_package {
        "android/config_test.go",
        "android/expand_test.go",
        "android/namespace_test.go",
        "android/neverallow_test.go",
        "android/paths_test.go",
        "android/prebuilt_test.go",
        "android/util_test.go",
+195 −0
Original line number Diff line number Diff line
// 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: "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) {
}
+24 −0
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@ package android
import (
	"fmt"
	"path/filepath"
	"regexp"
	"strings"
	"testing"

@@ -163,3 +164,26 @@ func FailIfErrored(t *testing.T, errs []error) {
		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)
		}
	}
}
+2 −26
Original line number Diff line number Diff line
@@ -22,7 +22,6 @@ import (
	"io/ioutil"
	"os"
	"reflect"
	"regexp"
	"sort"
	"strings"
	"testing"
@@ -178,13 +177,13 @@ func testCcError(t *testing.T, pattern string, bp string) {

	_, errs := ctx.ParseFileList(".", []string{"Android.bp"})
	if len(errs) > 0 {
		failIfNoMatchingErrors(t, pattern, errs)
		android.FailIfNoMatchingErrors(t, pattern, errs)
		return
	}

	_, errs = ctx.PrepareBuildActions(config)
	if len(errs) > 0 {
		failIfNoMatchingErrors(t, pattern, errs)
		android.FailIfNoMatchingErrors(t, pattern, errs)
		return
	}

@@ -1064,29 +1063,6 @@ func TestLinkReordering(t *testing.T) {
	}
}

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) {
	for _, moduleName := range moduleNames {
		module := ctx.ModuleForTests(moduleName, variant).Module().(*Module)