Merge "bootimg supports v4 header"
diff --git a/android/Android.bp b/android/Android.bp
index f17a8a0..588ad5e 100644
--- a/android/Android.bp
+++ b/android/Android.bp
@@ -67,6 +67,7 @@
"singleton.go",
"singleton_module.go",
"soong_config_modules.go",
+ "test_asserts.go",
"test_suites.go",
"testing.go",
"util.go",
diff --git a/android/androidmk.go b/android/androidmk.go
index 32d7712..9317567 100644
--- a/android/androidmk.go
+++ b/android/androidmk.go
@@ -44,6 +44,14 @@
ctx.RegisterSingletonType("androidmk", AndroidMkSingleton)
}
+// Enable androidmk support.
+// * Register the singleton
+// * Configure that we are inside make
+var PrepareForTestWithAndroidMk = GroupFixturePreparers(
+ FixtureRegisterWithContext(RegisterAndroidMkBuildComponents),
+ FixtureModifyConfig(SetKatiEnabledForTests),
+)
+
// Deprecated: Use AndroidMkEntriesProvider instead, especially if you're not going to use the
// Custom function. It's easier to use and test.
type AndroidMkDataProvider interface {
diff --git a/android/apex.go b/android/apex.go
index a014592..79d8cdd 100644
--- a/android/apex.go
+++ b/android/apex.go
@@ -719,6 +719,8 @@
// Generate two module out files:
// 1. FullList with transitive deps and their parents in the dep graph
// 2. FlatList with a flat list of transitive deps
+// In both cases transitive deps of external deps are not included. Neither are deps that are only
+// available to APEXes; they are developed with updatability in mind and don't need manual approval.
func (d *ApexBundleDepsInfo) BuildDepsInfoLists(ctx ModuleContext, minSdkVersion string, depInfos DepNameToDepInfoMap) {
var fullContent strings.Builder
var flatContent strings.Builder
diff --git a/android/bazel_handler.go b/android/bazel_handler.go
index 9cd9fad..6675840 100644
--- a/android/bazel_handler.go
+++ b/android/bazel_handler.go
@@ -37,6 +37,7 @@
const (
getAllFiles CqueryRequestType = iota
getCcObjectFiles
+ getAllFilesAndCcObjectFiles
)
// Map key to describe bazel cquery requests.
@@ -58,7 +59,9 @@
// Retrieves these files from Bazel's CcInfo provider.
GetCcObjectFiles(label string, archType ArchType) ([]string, bool)
- // TODO(cparsons): Other cquery-related methods should be added here.
+ // Returns the results of GetAllFiles and GetCcObjectFiles in a single query (in that order).
+ GetAllFilesAndCcObjectFiles(label string, archType ArchType) ([]string, []string, bool)
+
// ** End cquery methods
// Issues commands to Bazel to receive results for all cquery requests
@@ -116,6 +119,11 @@
return result, ok
}
+func (m MockBazelContext) GetAllFilesAndCcObjectFiles(label string, archType ArchType) ([]string, []string, bool) {
+ result, ok := m.AllFiles[label]
+ return result, result, ok
+}
+
func (m MockBazelContext) InvokeBazel() error {
panic("unimplemented")
}
@@ -154,6 +162,22 @@
}
}
+func (bazelCtx *bazelContext) GetAllFilesAndCcObjectFiles(label string, archType ArchType) ([]string, []string, bool) {
+ var allFiles []string
+ var ccObjects []string
+
+ result, ok := bazelCtx.cquery(label, getAllFilesAndCcObjectFiles, archType)
+ if ok {
+ bazelOutput := strings.TrimSpace(result)
+ splitString := strings.Split(bazelOutput, "|")
+ allFilesString := splitString[0]
+ ccObjectsString := splitString[1]
+ allFiles = strings.Split(allFilesString, ", ")
+ ccObjects = strings.Split(ccObjectsString, ", ")
+ }
+ return allFiles, ccObjects, ok
+}
+
func (n noopBazelContext) GetAllFiles(label string, archType ArchType) ([]string, bool) {
panic("unimplemented")
}
@@ -162,6 +186,10 @@
panic("unimplemented")
}
+func (n noopBazelContext) GetAllFilesAndCcObjectFiles(label string, archType ArchType) ([]string, []string, bool) {
+ panic("unimplemented")
+}
+
func (n noopBazelContext) InvokeBazel() error {
panic("unimplemented")
}
@@ -253,8 +281,12 @@
return ""
}
+// Issues the given bazel command with given build label and additional flags.
+// Returns (stdout, stderr, error). The first and second return values are strings
+// containing the stdout and stderr of the run command, and an error is returned if
+// the invocation returned an error code.
func (context *bazelContext) issueBazelCommand(runName bazel.RunName, command string, labels []string,
- extraFlags ...string) (string, error) {
+ extraFlags ...string) (string, string, error) {
cmdFlags := []string{"--output_base=" + context.outputBase, command}
cmdFlags = append(cmdFlags, labels...)
@@ -281,9 +313,10 @@
bazelCmd.Stderr = stderr
if output, err := bazelCmd.Output(); err != nil {
- return "", fmt.Errorf("bazel command failed. command: [%s], env: [%s], error [%s]", bazelCmd, bazelCmd.Env, stderr)
+ return "", string(stderr.Bytes()),
+ fmt.Errorf("bazel command failed. command: [%s], env: [%s], error [%s]", bazelCmd, bazelCmd.Env, stderr)
} else {
- return string(output), nil
+ return string(output), string(stderr.Bytes()), nil
}
}
@@ -452,6 +485,11 @@
strings.Join(deps_arm, ",\n ")))
}
+// Returns the file contents of the buildroot.cquery file that should be used for the cquery
+// expression in order to obtain information about buildroot and its dependencies.
+// The contents of this file depend on the bazelContext's requests; requests are enumerated
+// and grouped by their request type. The data retrieved for each label depends on its
+// request type.
func (context *bazelContext) cqueryStarlarkFileContents() []byte {
formatString := `
# This file is generated by soong_build. Do not edit.
@@ -463,6 +501,13 @@
%s
}
+getAllFilesAndCcObjectFilesLabels = {
+ %s
+}
+
+def get_all_files(target):
+ return [f.path for f in target.files.to_list()]
+
def get_cc_object_files(target):
result = []
linker_inputs = providers(target)["CcInfo"].linking_context.linker_inputs.to_list()
@@ -492,9 +537,11 @@
def format(target):
id_string = str(target.label) + "|" + get_arch(target)
if id_string in getAllFilesLabels:
- return id_string + ">>" + ', '.join([f.path for f in target.files.to_list()])
+ return id_string + ">>" + ', '.join(get_all_files(target))
elif id_string in getCcObjectFilesLabels:
return id_string + ">>" + ', '.join(get_cc_object_files(target))
+ elif id_string in getAllFilesAndCcObjectFilesLabels:
+ return id_string + ">>" + ', '.join(get_all_files(target)) + "|" + ', '.join(get_cc_object_files(target))
else:
# This target was not requested via cquery, and thus must be a dependency
# of a requested target.
@@ -502,6 +549,7 @@
`
var getAllFilesDeps []string = nil
var getCcObjectFilesDeps []string = nil
+ var getAllFilesAndCcObjectFilesDeps []string = nil
for val, _ := range context.requests {
labelWithArch := getCqueryId(val)
@@ -511,12 +559,16 @@
getAllFilesDeps = append(getAllFilesDeps, mapEntryString)
case getCcObjectFiles:
getCcObjectFilesDeps = append(getCcObjectFilesDeps, mapEntryString)
+ case getAllFilesAndCcObjectFiles:
+ getAllFilesAndCcObjectFilesDeps = append(getAllFilesAndCcObjectFilesDeps, mapEntryString)
}
}
getAllFilesDepsString := strings.Join(getAllFilesDeps, ",\n ")
getCcObjectFilesDepsString := strings.Join(getCcObjectFilesDeps, ",\n ")
+ getAllFilesAndCcObjectFilesDepsString := strings.Join(getAllFilesAndCcObjectFilesDeps, ",\n ")
- return []byte(fmt.Sprintf(formatString, getAllFilesDepsString, getCcObjectFilesDepsString))
+ return []byte(fmt.Sprintf(formatString, getAllFilesDepsString, getCcObjectFilesDepsString,
+ getAllFilesAndCcObjectFilesDepsString))
}
// Returns a workspace-relative path containing build-related metadata required
@@ -531,6 +583,7 @@
context.results = make(map[cqueryKey]string)
var cqueryOutput string
+ var cqueryErr string
var err error
intermediatesDirPath := absolutePath(context.intermediatesDir())
@@ -568,7 +621,7 @@
return err
}
buildrootLabel := "//:buildroot"
- cqueryOutput, err = context.issueBazelCommand(bazel.CqueryBuildRootRunName, "cquery",
+ cqueryOutput, cqueryErr, err = context.issueBazelCommand(bazel.CqueryBuildRootRunName, "cquery",
[]string{fmt.Sprintf("kind(rule, deps(%s))", buildrootLabel)},
"--output=starlark",
"--starlark:file="+cqueryFileRelpath)
@@ -595,7 +648,8 @@
if cqueryResult, ok := cqueryResults[getCqueryId(val)]; ok {
context.results[val] = string(cqueryResult)
} else {
- return fmt.Errorf("missing result for bazel target %s. query output: [%s]", getCqueryId(val), cqueryOutput)
+ return fmt.Errorf("missing result for bazel target %s. query output: [%s], cquery err: [%s]",
+ getCqueryId(val), cqueryOutput, cqueryErr)
}
}
@@ -603,7 +657,7 @@
//
// TODO(cparsons): Use --target_pattern_file to avoid command line limits.
var aqueryOutput string
- aqueryOutput, err = context.issueBazelCommand(bazel.AqueryBuildRootRunName, "aquery",
+ aqueryOutput, _, err = context.issueBazelCommand(bazel.AqueryBuildRootRunName, "aquery",
[]string{fmt.Sprintf("deps(%s)", buildrootLabel),
// Use jsonproto instead of proto; actual proto parsing would require a dependency on Bazel's
// proto sources, which would add a number of unnecessary dependencies.
@@ -621,7 +675,7 @@
// Issue a build command of the phony root to generate symlink forests for dependencies of the
// Bazel build. This is necessary because aquery invocations do not generate this symlink forest,
// but some of symlinks may be required to resolve source dependencies of the build.
- _, err = context.issueBazelCommand(bazel.BazelBuildPhonyRootRunName, "build",
+ _, _, err = context.issueBazelCommand(bazel.BazelBuildPhonyRootRunName, "build",
[]string{"//:phonyroot"})
if err != nil {
diff --git a/android/config.go b/android/config.go
index c10ad09..bc1aa3a 100644
--- a/android/config.go
+++ b/android/config.go
@@ -287,24 +287,21 @@
return testConfig
}
-// TestArchConfigFuchsia returns a Config object suitable for using for
-// tests that need to run the arch mutator for the Fuchsia arch.
-func TestArchConfigFuchsia(buildDir string, env map[string]string, bp string, fs map[string][]byte) Config {
- testConfig := TestConfig(buildDir, env, bp, fs)
- config := testConfig.config
-
- config.Targets = map[OsType][]Target{
- Fuchsia: []Target{
+func fuchsiaTargets() map[OsType][]Target {
+ return map[OsType][]Target{
+ Fuchsia: {
{Fuchsia, Arch{ArchType: Arm64, ArchVariant: "", Abi: []string{"arm64-v8a"}}, NativeBridgeDisabled, "", "", false},
},
- BuildOs: []Target{
+ BuildOs: {
{BuildOs, Arch{ArchType: X86_64}, NativeBridgeDisabled, "", "", false},
},
}
-
- return testConfig
}
+var PrepareForTestSetDeviceToFuchsia = FixtureModifyConfig(func(config Config) {
+ config.Targets = fuchsiaTargets()
+})
+
func modifyTestConfigToSupportArchMutator(testConfig Config) {
config := testConfig.config
@@ -527,26 +524,6 @@
return PathForOutput(ctx, "host", c.PrebuiltOS(), "framework", path)
}
-// NonHermeticHostSystemTool looks for non-hermetic tools from the system we're
-// running on. These tools are not checked-in to AOSP, and therefore could lead
-// to reproducibility problems. Should not be used for other than finding the
-// XCode SDK (xcrun, sw_vers), etc. See ui/build/paths/config.go for the
-// allowlist of host system tools.
-func (c *config) NonHermeticHostSystemTool(name string) string {
- for _, dir := range filepath.SplitList(c.Getenv("PATH")) {
- path := filepath.Join(dir, name)
- if s, err := os.Stat(path); err != nil {
- continue
- } else if m := s.Mode(); !s.IsDir() && m&0111 != 0 {
- return path
- }
- }
- panic(fmt.Errorf(
- "Unable to use '%s' as a host system tool for build system "+
- "hermeticity reasons. See build/soong/ui/build/paths/config.go "+
- "for the full list of allowed host tools on your system.", name))
-}
-
// PrebuiltOS returns the name of the host OS used in prebuilts directories.
func (c *config) PrebuiltOS() string {
switch runtime.GOOS {
diff --git a/android/env.go b/android/env.go
index 58ad0b6..289d803 100644
--- a/android/env.go
+++ b/android/env.go
@@ -15,11 +15,6 @@
package android
import (
- "fmt"
- "os"
- "strings"
- "syscall"
-
"android/soong/shared"
)
@@ -31,9 +26,6 @@
// a manifest regeneration.
var originalEnv map[string]string
-var soongDelveListen string
-var soongDelvePath string
-var isDebugging bool
func InitEnvironment(envFile string) {
var err error
@@ -41,51 +33,6 @@
if err != nil {
panic(err)
}
-
- soongDelveListen = originalEnv["SOONG_DELVE"]
- soongDelvePath = originalEnv["SOONG_DELVE_PATH"]
-}
-
-// Returns whether the current process is running under Delve due to
-// ReexecWithDelveMaybe().
-func IsDebugging() bool {
- return isDebugging
-}
-func ReexecWithDelveMaybe() {
- isDebugging = os.Getenv("SOONG_DELVE_REEXECUTED") == "true"
- if isDebugging || soongDelveListen == "" {
- return
- }
-
- if soongDelvePath == "" {
- fmt.Fprintln(os.Stderr, "SOONG_DELVE is set but failed to find dlv")
- os.Exit(1)
- }
-
- soongDelveEnv := []string{}
- for _, env := range os.Environ() {
- idx := strings.IndexRune(env, '=')
- if idx != -1 {
- soongDelveEnv = append(soongDelveEnv, env)
- }
- }
-
- soongDelveEnv = append(soongDelveEnv, "SOONG_DELVE_REEXECUTED=true")
-
- dlvArgv := []string{
- soongDelvePath,
- "--listen=:" + soongDelveListen,
- "--headless=true",
- "--api-version=2",
- "exec",
- os.Args[0],
- "--",
- }
- dlvArgv = append(dlvArgv, os.Args[1:]...)
- os.Chdir(absSrcDir)
- syscall.Exec(soongDelvePath, dlvArgv, soongDelveEnv)
- fmt.Fprintln(os.Stderr, "exec() failed while trying to reexec with Delve")
- os.Exit(1)
}
func EnvSingleton() Singleton {
diff --git a/android/fixture.go b/android/fixture.go
index 2c8997b..d8893f7 100644
--- a/android/fixture.go
+++ b/android/fixture.go
@@ -15,8 +15,7 @@
package android
import (
- "reflect"
- "strings"
+ "fmt"
"testing"
)
@@ -182,12 +181,12 @@
// Create a Fixture.
Fixture(t *testing.T, preparers ...FixturePreparer) Fixture
- // SetErrorHandler creates a new FixtureFactory that will use the supplied error handler to check
- // the errors (may be 0) reported by the test.
+ // ExtendWithErrorHandler creates a new FixtureFactory that will use the supplied error handler
+ // to check the errors (may be 0) reported by the test.
//
// The default handlers is FixtureExpectsNoErrors which will fail the go test immediately if any
// errors are reported.
- SetErrorHandler(errorHandler FixtureErrorHandler) FixtureFactory
+ ExtendWithErrorHandler(errorHandler FixtureErrorHandler) FixtureFactory
// Run the test, checking any errors reported and returning a TestResult instance.
//
@@ -198,6 +197,24 @@
//
// Shorthand for RunTest(t, android.FixtureWithRootAndroidBp(bp))
RunTestWithBp(t *testing.T, bp string) *TestResult
+
+ // RunTestWithConfig is a temporary method added to help ease the migration of existing tests to
+ // the test fixture.
+ //
+ // In order to allow the Config object to be customized separately to the TestContext a lot of
+ // existing test code has `test...WithConfig` funcs that allow the Config object to be supplied
+ // from the test and then have the TestContext created and configured automatically. e.g.
+ // testCcWithConfig, testCcErrorWithConfig, testJavaWithConfig, etc.
+ //
+ // This method allows those methods to be migrated to use the test fixture pattern without
+ // requiring that every test that uses those methods be migrated at the same time. That allows
+ // those tests to benefit from correctness in the order of registration quickly.
+ //
+ // This method discards the config (along with its mock file system, product variables,
+ // environment, etc.) that may have been set up by FixturePreparers.
+ //
+ // deprecated
+ RunTestWithConfig(t *testing.T, config Config) *TestResult
}
// Create a new FixtureFactory that will apply the supplied preparers.
@@ -218,8 +235,14 @@
// A set of mock files to add to the mock file system.
type MockFS map[string][]byte
+// Merge adds the extra entries from the supplied map to this one.
+//
+// Fails if the supplied map files with the same paths are present in both of them.
func (fs MockFS) Merge(extra map[string][]byte) {
for p, c := range extra {
+ if _, ok := fs[p]; ok {
+ panic(fmt.Errorf("attempted to add file %s to the mock filesystem but it already exists", p))
+ }
fs[p] = c
}
}
@@ -270,22 +293,84 @@
}
// Add a file to the mock filesystem
+//
+// Fail if the filesystem already contains a file with that path, use FixtureOverrideFile instead.
func FixtureAddFile(path string, contents []byte) FixturePreparer {
return FixtureModifyMockFS(func(fs MockFS) {
+ if _, ok := fs[path]; ok {
+ panic(fmt.Errorf("attempted to add file %s to the mock filesystem but it already exists, use FixtureOverride*File instead", path))
+ }
fs[path] = contents
})
}
// Add a text file to the mock filesystem
+//
+// Fail if the filesystem already contains a file with that path.
func FixtureAddTextFile(path string, contents string) FixturePreparer {
return FixtureAddFile(path, []byte(contents))
}
+// Override a file in the mock filesystem
+//
+// If the file does not exist this behaves as FixtureAddFile.
+func FixtureOverrideFile(path string, contents []byte) FixturePreparer {
+ return FixtureModifyMockFS(func(fs MockFS) {
+ fs[path] = contents
+ })
+}
+
+// Override a text file in the mock filesystem
+//
+// If the file does not exist this behaves as FixtureAddTextFile.
+func FixtureOverrideTextFile(path string, contents string) FixturePreparer {
+ return FixtureOverrideFile(path, []byte(contents))
+}
+
// Add the root Android.bp file with the supplied contents.
func FixtureWithRootAndroidBp(contents string) FixturePreparer {
return FixtureAddTextFile("Android.bp", contents)
}
+// Merge some environment variables into the fixture.
+func FixtureMergeEnv(env map[string]string) FixturePreparer {
+ return FixtureModifyConfig(func(config Config) {
+ for k, v := range env {
+ if k == "PATH" {
+ panic("Cannot set PATH environment variable")
+ }
+ config.env[k] = v
+ }
+ })
+}
+
+// Modify the env.
+//
+// Will panic if the mutator changes the PATH environment variable.
+func FixtureModifyEnv(mutator func(env map[string]string)) FixturePreparer {
+ return FixtureModifyConfig(func(config Config) {
+ oldPath := config.env["PATH"]
+ mutator(config.env)
+ newPath := config.env["PATH"]
+ if newPath != oldPath {
+ panic(fmt.Errorf("Cannot change PATH environment variable from %q to %q", oldPath, newPath))
+ }
+ })
+}
+
+// Allow access to the product variables when preparing the fixture.
+type FixtureProductVariables struct {
+ *productVariables
+}
+
+// Modify product variables.
+func FixtureModifyProductVariables(mutator func(variables FixtureProductVariables)) FixturePreparer {
+ return FixtureModifyConfig(func(config Config) {
+ productVariables := FixtureProductVariables{&config.productVariables}
+ mutator(productVariables)
+ })
+}
+
// GroupFixturePreparers creates a composite FixturePreparer that is equivalent to applying each of
// the supplied FixturePreparer instances in order.
//
@@ -382,16 +467,16 @@
// The supplied result can be used to access the state of the code under test just as the main
// body of the test would but if any errors other than ones expected are reported the state may
// be indeterminate.
- CheckErrors(result *TestResult)
+ CheckErrors(t *testing.T, result *TestResult)
}
type simpleErrorHandler struct {
- function func(result *TestResult)
+ function func(t *testing.T, result *TestResult)
}
-func (h simpleErrorHandler) CheckErrors(result *TestResult) {
- result.Helper()
- h.function(result)
+func (h simpleErrorHandler) CheckErrors(t *testing.T, result *TestResult) {
+ t.Helper()
+ h.function(t, result)
}
// The default fixture error handler.
@@ -401,9 +486,9 @@
// If the test fails this handler will call `result.FailNow()` which will exit the goroutine within
// which the test is being run which means that the RunTest() method will not return.
var FixtureExpectsNoErrors = FixtureCustomErrorHandler(
- func(result *TestResult) {
- result.Helper()
- FailIfErrored(result.T, result.Errs)
+ func(t *testing.T, result *TestResult) {
+ t.Helper()
+ FailIfErrored(t, result.Errs)
},
)
@@ -420,10 +505,10 @@
// If the test fails this handler will call `result.FailNow()` which will exit the goroutine within
// which the test is being run which means that the RunTest() method will not return.
func FixtureExpectsAtLeastOneErrorMatchingPattern(pattern string) FixtureErrorHandler {
- return FixtureCustomErrorHandler(func(result *TestResult) {
- result.Helper()
- if !FailIfNoMatchingErrors(result.T, pattern, result.Errs) {
- result.FailNow()
+ return FixtureCustomErrorHandler(func(t *testing.T, result *TestResult) {
+ t.Helper()
+ if !FailIfNoMatchingErrors(t, pattern, result.Errs) {
+ t.FailNow()
}
})
}
@@ -442,14 +527,14 @@
// If the test fails this handler will call `result.FailNow()` which will exit the goroutine within
// which the test is being run which means that the RunTest() method will not return.
func FixtureExpectsAllErrorsToMatchAPattern(patterns []string) FixtureErrorHandler {
- return FixtureCustomErrorHandler(func(result *TestResult) {
- result.Helper()
- CheckErrorsAgainstExpectations(result.T, result.Errs, patterns)
+ return FixtureCustomErrorHandler(func(t *testing.T, result *TestResult) {
+ t.Helper()
+ CheckErrorsAgainstExpectations(t, result.Errs, patterns)
})
}
// FixtureCustomErrorHandler creates a custom error handler
-func FixtureCustomErrorHandler(function func(result *TestResult)) FixtureErrorHandler {
+func FixtureCustomErrorHandler(function func(t *testing.T, result *TestResult)) FixtureErrorHandler {
return simpleErrorHandler{
function: function,
}
@@ -461,83 +546,6 @@
RunTest() *TestResult
}
-// Provides general test support.
-type TestHelper struct {
- *testing.T
-}
-
-// AssertBoolEquals checks if the expected and actual values are equal and if they are not then it
-// reports an error prefixed with the supplied message and including a reason for why it failed.
-func (h *TestHelper) AssertBoolEquals(message string, expected bool, actual bool) {
- h.Helper()
- if actual != expected {
- h.Errorf("%s: expected %t, actual %t", message, expected, actual)
- }
-}
-
-// AssertStringEquals checks if the expected and actual values are equal and if they are not then
-// it reports an error prefixed with the supplied message and including a reason for why it failed.
-func (h *TestHelper) AssertStringEquals(message string, expected string, actual string) {
- h.Helper()
- if actual != expected {
- h.Errorf("%s: expected %s, actual %s", message, expected, actual)
- }
-}
-
-// AssertTrimmedStringEquals checks if the expected and actual values are the same after trimming
-// leading and trailing spaces from them both. If they are not then it reports an error prefixed
-// with the supplied message and including a reason for why it failed.
-func (h *TestHelper) AssertTrimmedStringEquals(message string, expected string, actual string) {
- h.Helper()
- h.AssertStringEquals(message, strings.TrimSpace(expected), strings.TrimSpace(actual))
-}
-
-// AssertStringDoesContain checks if the string contains the expected substring. If it does not
-// then it reports an error prefixed with the supplied message and including a reason for why it
-// failed.
-func (h *TestHelper) AssertStringDoesContain(message string, s string, expectedSubstring string) {
- h.Helper()
- if !strings.Contains(s, expectedSubstring) {
- h.Errorf("%s: could not find %q within %q", message, expectedSubstring, s)
- }
-}
-
-// AssertStringDoesNotContain checks if the string contains the expected substring. If it does then
-// it reports an error prefixed with the supplied message and including a reason for why it failed.
-func (h *TestHelper) AssertStringDoesNotContain(message string, s string, unexpectedSubstring string) {
- h.Helper()
- if strings.Contains(s, unexpectedSubstring) {
- h.Errorf("%s: unexpectedly found %q within %q", message, unexpectedSubstring, s)
- }
-}
-
-// AssertArrayString checks if the expected and actual values are equal and if they are not then it
-// reports an error prefixed with the supplied message and including a reason for why it failed.
-func (h *TestHelper) AssertArrayString(message string, expected, actual []string) {
- h.Helper()
- if len(actual) != len(expected) {
- h.Errorf("%s: expected %d (%q), actual (%d) %q", message, len(expected), expected, len(actual), actual)
- return
- }
- for i := range actual {
- if actual[i] != expected[i] {
- h.Errorf("%s: expected %d-th, %q (%q), actual %q (%q)",
- message, i, expected[i], expected, actual[i], actual)
- return
- }
- }
-}
-
-// AssertArrayString checks if the expected and actual values are equal using reflect.DeepEqual and
-// if they are not then it reports an error prefixed with the supplied message and including a
-// reason for why it failed.
-func (h *TestHelper) AssertDeepEquals(message string, expected interface{}, actual interface{}) {
- h.Helper()
- if !reflect.DeepEqual(actual, expected) {
- h.Errorf("%s: expected:\n %#v\n got:\n %#v", message, expected, actual)
- }
-}
-
// Struct to allow TestResult to embed a *TestContext and allow call forwarding to its methods.
type testContext struct {
*TestContext
@@ -545,7 +553,6 @@
// The result of running a test.
type TestResult struct {
- TestHelper
testContext
fixture *fixture
@@ -564,7 +571,11 @@
}
func (f *fixtureFactory) Extend(preparers ...FixturePreparer) FixtureFactory {
- all := append(f.preparers, dedupAndFlattenPreparers(f.preparers, preparers)...)
+ // Create a new slice to avoid accidentally sharing the preparers slice from this factory with
+ // the extending factories.
+ var all []*simpleFixturePreparer
+ all = append(all, f.preparers...)
+ all = append(all, dedupAndFlattenPreparers(f.preparers, preparers)...)
// Copy the existing factory.
extendedFactory := &fixtureFactory{}
*extendedFactory = *f
@@ -596,7 +607,7 @@
return fixture
}
-func (f *fixtureFactory) SetErrorHandler(errorHandler FixtureErrorHandler) FixtureFactory {
+func (f *fixtureFactory) ExtendWithErrorHandler(errorHandler FixtureErrorHandler) FixtureFactory {
newFactory := &fixtureFactory{}
*newFactory = *f
newFactory.errorHandler = errorHandler
@@ -614,6 +625,28 @@
return f.RunTest(t, FixtureWithRootAndroidBp(bp))
}
+func (f *fixtureFactory) RunTestWithConfig(t *testing.T, config Config) *TestResult {
+ t.Helper()
+ // Create the fixture as normal.
+ fixture := f.Fixture(t).(*fixture)
+
+ // Discard the mock filesystem as otherwise that will override the one in the config.
+ fixture.mockFS = nil
+
+ // Replace the config with the supplied one in the fixture.
+ fixture.config = config
+
+ // Ditto with config derived information in the TestContext.
+ ctx := fixture.ctx
+ ctx.config = config
+ ctx.SetFs(ctx.config.fs)
+ if ctx.config.mockBpList != "" {
+ ctx.SetModuleListFile(ctx.config.mockBpList)
+ }
+
+ return fixture.RunTest()
+}
+
type fixture struct {
// The factory used to create this fixture.
factory *fixtureFactory
@@ -639,17 +672,22 @@
ctx := f.ctx
- // The TestConfig() method assumes that the mock filesystem is available when creating so creates
- // the mock file system immediately. Similarly, the NewTestContext(Config) method assumes that the
- // supplied Config's FileSystem has been properly initialized before it is called and so it takes
- // its own reference to the filesystem. However, fixtures create the Config and TestContext early
- // so they can be modified by preparers at which time the mockFS has not been populated (because
- // it too is modified by preparers). So, this reinitializes the Config and TestContext's
- // FileSystem using the now populated mockFS.
- f.config.mockFileSystem("", f.mockFS)
- ctx.SetFs(ctx.config.fs)
- if ctx.config.mockBpList != "" {
- ctx.SetModuleListFile(ctx.config.mockBpList)
+ // Do not use the fixture's mockFS to initialize the config's mock file system if it has been
+ // cleared by RunTestWithConfig.
+ if f.mockFS != nil {
+ // The TestConfig() method assumes that the mock filesystem is available when creating so
+ // creates the mock file system immediately. Similarly, the NewTestContext(Config) method
+ // assumes that the supplied Config's FileSystem has been properly initialized before it is
+ // called and so it takes its own reference to the filesystem. However, fixtures create the
+ // Config and TestContext early so they can be modified by preparers at which time the mockFS
+ // has not been populated (because it too is modified by preparers). So, this reinitializes the
+ // Config and TestContext's FileSystem using the now populated mockFS.
+ f.config.mockFileSystem("", f.mockFS)
+
+ ctx.SetFs(ctx.config.fs)
+ if ctx.config.mockBpList != "" {
+ ctx.SetModuleListFile(ctx.config.mockBpList)
+ }
}
ctx.Register()
@@ -659,14 +697,13 @@
}
result := &TestResult{
- TestHelper: TestHelper{T: f.t},
testContext: testContext{ctx},
fixture: f,
Config: f.config,
Errs: errs,
}
- f.errorHandler.CheckErrors(result)
+ f.errorHandler.CheckErrors(f.t, result)
return result
}
@@ -702,36 +739,7 @@
return result
}
-// NewFixture creates a new test fixture that is based on the one that created this result. It is
-// intended to test the output of module types that generate content to be processed by the build,
-// e.g. sdk snapshots.
-func (r *TestResult) NewFixture(preparers ...FixturePreparer) Fixture {
- return r.fixture.factory.Fixture(r.T, preparers...)
-}
-
-// RunTest is shorthand for NewFixture(preparers...).RunTest().
-func (r *TestResult) RunTest(preparers ...FixturePreparer) *TestResult {
- r.Helper()
- return r.fixture.factory.Fixture(r.T, preparers...).RunTest()
-}
-
// Module returns the module with the specific name and of the specified variant.
func (r *TestResult) Module(name string, variant string) Module {
return r.ModuleForTests(name, variant).Module()
}
-
-// Create a *TestResult object suitable for use within a subtest.
-//
-// This ensures that any errors reported by the TestResult, e.g. from within one of its
-// Assert... methods, will be associated with the sub test and not the main test.
-//
-// result := ....RunTest()
-// t.Run("subtest", func(t *testing.T) {
-// subResult := result.ResultForSubTest(t)
-// subResult.AssertStringEquals("something", ....)
-// })
-func (r *TestResult) ResultForSubTest(t *testing.T) *TestResult {
- subTestResult := *r
- r.T = t
- return &subTestResult
-}
diff --git a/android/fixture_test.go b/android/fixture_test.go
index 5a7bf3b..a31ef16 100644
--- a/android/fixture_test.go
+++ b/android/fixture_test.go
@@ -43,7 +43,6 @@
extension.Fixture(t, preparer1, preparer2, preparer2Then1, preparer3)
- h := TestHelper{t}
- h.AssertDeepEquals("preparers called in wrong order",
+ AssertDeepEquals(t, "preparers called in wrong order",
[]string{"preparer1", "preparer2", "preparer4", "preparer3"}, list)
}
diff --git a/android/license_kind_test.go b/android/license_kind_test.go
index 767b64e..83e83ce 100644
--- a/android/license_kind_test.go
+++ b/android/license_kind_test.go
@@ -8,7 +8,7 @@
var licenseKindTests = []struct {
name string
- fs map[string][]byte
+ fs MockFS
expectedErrors []string
}{
{
@@ -97,48 +97,18 @@
func TestLicenseKind(t *testing.T) {
for _, test := range licenseKindTests {
t.Run(test.name, func(t *testing.T) {
- _, errs := testLicenseKind(test.fs)
-
- expectedErrors := test.expectedErrors
- if expectedErrors == nil {
- FailIfErrored(t, errs)
- } else {
- for _, expectedError := range expectedErrors {
- FailIfNoMatchingErrors(t, expectedError, errs)
- }
- if len(errs) > len(expectedErrors) {
- t.Errorf("additional errors found, expected %d, found %d", len(expectedErrors), len(errs))
- for i, expectedError := range expectedErrors {
- t.Errorf("expectedErrors[%d] = %s", i, expectedError)
- }
- for i, err := range errs {
- t.Errorf("errs[%d] = %s", i, err)
- }
- }
- }
+ licenseTestFixtureFactory.
+ Extend(
+ FixtureRegisterWithContext(func(ctx RegistrationContext) {
+ ctx.RegisterModuleType("mock_license", newMockLicenseModule)
+ }),
+ test.fs.AddToFixture(),
+ ).ExtendWithErrorHandler(FixtureExpectsAllErrorsToMatchAPattern(test.expectedErrors)).
+ RunTest(t)
})
}
}
-func testLicenseKind(fs map[string][]byte) (*TestContext, []error) {
-
- // Create a new config per test as license_kind information is stored in the config.
- config := TestArchConfig(buildDir, nil, "", fs)
-
- ctx := NewTestArchContext(config)
- RegisterLicenseKindBuildComponents(ctx)
- ctx.RegisterModuleType("mock_license", newMockLicenseModule)
- ctx.Register()
-
- _, errs := ctx.ParseBlueprintsFiles(".")
- if len(errs) > 0 {
- return ctx, errs
- }
-
- _, errs = ctx.PrepareBuildActions(config)
- return ctx, errs
-}
-
type mockLicenseProperties struct {
License_kinds []string
}
diff --git a/android/license_test.go b/android/license_test.go
index 9f68713..a564827 100644
--- a/android/license_test.go
+++ b/android/license_test.go
@@ -4,9 +4,24 @@
"testing"
)
+// Common test set up for license tests.
+var licenseTestFixtureFactory = emptyTestFixtureFactory.Extend(
+ // General preparers in alphabetical order.
+ PrepareForTestWithDefaults,
+ prepareForTestWithLicenses,
+ PrepareForTestWithOverrides,
+ PrepareForTestWithPackageModule,
+ PrepareForTestWithPrebuilts,
+ PrepareForTestWithVisibility,
+
+ // Additional test specific stuff
+ prepareForTestWithFakePrebuiltModules,
+ FixtureMergeEnv(map[string]string{"ANDROID_REQUIRE_LICENSES": "1"}),
+)
+
var licenseTests = []struct {
name string
- fs map[string][]byte
+ fs MockFS
expectedErrors []string
}{
{
@@ -163,58 +178,20 @@
func TestLicense(t *testing.T) {
for _, test := range licenseTests {
t.Run(test.name, func(t *testing.T) {
- _, errs := testLicense(test.fs)
-
- expectedErrors := test.expectedErrors
- if expectedErrors == nil {
- FailIfErrored(t, errs)
- } else {
- for _, expectedError := range expectedErrors {
- FailIfNoMatchingErrors(t, expectedError, errs)
- }
- if len(errs) > len(expectedErrors) {
- t.Errorf("additional errors found, expected %d, found %d", len(expectedErrors), len(errs))
- for i, expectedError := range expectedErrors {
- t.Errorf("expectedErrors[%d] = %s", i, expectedError)
- }
- for i, err := range errs {
- t.Errorf("errs[%d] = %s", i, err)
- }
- }
- }
+ // Customize the common license text fixture factory.
+ licenseTestFixtureFactory.Extend(
+ FixtureRegisterWithContext(func(ctx RegistrationContext) {
+ ctx.RegisterModuleType("rule", newMockRuleModule)
+ }),
+ test.fs.AddToFixture(),
+ ).
+ ExtendWithErrorHandler(FixtureExpectsAllErrorsToMatchAPattern(test.expectedErrors)).
+ RunTest(t)
})
}
}
-func testLicense(fs map[string][]byte) (*TestContext, []error) {
-
- // Create a new config per test as visibility information is stored in the config.
- env := make(map[string]string)
- env["ANDROID_REQUIRE_LICENSES"] = "1"
- config := TestArchConfig(buildDir, env, "", fs)
-
- ctx := NewTestArchContext(config)
- RegisterPackageBuildComponents(ctx)
- registerTestPrebuiltBuildComponents(ctx)
- RegisterLicenseKindBuildComponents(ctx)
- RegisterLicenseBuildComponents(ctx)
- ctx.RegisterModuleType("rule", newMockRuleModule)
- ctx.PreArchMutators(RegisterVisibilityRuleChecker)
- ctx.PreArchMutators(RegisterLicensesPackageMapper)
- ctx.PreArchMutators(RegisterDefaultsPreArchMutators)
- ctx.PreArchMutators(RegisterLicensesPropertyGatherer)
- ctx.PreArchMutators(RegisterVisibilityRuleGatherer)
- ctx.PostDepsMutators(RegisterVisibilityRuleEnforcer)
- ctx.PostDepsMutators(RegisterLicensesDependencyChecker)
- ctx.Register()
-
- _, errs := ctx.ParseBlueprintsFiles(".")
- if len(errs) > 0 {
- return ctx, errs
- }
-
- _, errs = ctx.PrepareBuildActions(config)
- return ctx, errs
+func testLicense(t *testing.T, fs MockFS, expectedErrors []string) {
}
type mockRuleModule struct {
diff --git a/android/licenses_test.go b/android/licenses_test.go
index c043791..a581932 100644
--- a/android/licenses_test.go
+++ b/android/licenses_test.go
@@ -6,9 +6,21 @@
"github.com/google/blueprint"
)
+var prepareForTestWithLicenses = GroupFixturePreparers(
+ FixtureRegisterWithContext(RegisterLicenseKindBuildComponents),
+ FixtureRegisterWithContext(RegisterLicenseBuildComponents),
+ FixtureRegisterWithContext(registerLicenseMutators),
+)
+
+func registerLicenseMutators(ctx RegistrationContext) {
+ ctx.PreArchMutators(RegisterLicensesPackageMapper)
+ ctx.PreArchMutators(RegisterLicensesPropertyGatherer)
+ ctx.PostDepsMutators(RegisterLicensesDependencyChecker)
+}
+
var licensesTests = []struct {
name string
- fs map[string][]byte
+ fs MockFS
expectedErrors []string
effectiveLicenses map[string][]string
effectiveInheritedLicenses map[string][]string
@@ -457,40 +469,48 @@
func TestLicenses(t *testing.T) {
for _, test := range licensesTests {
t.Run(test.name, func(t *testing.T) {
- ctx, errs := testLicenses(buildDir, test.fs)
-
- CheckErrorsAgainstExpectations(t, errs, test.expectedErrors)
+ // Customize the common license text fixture factory.
+ result := licenseTestFixtureFactory.Extend(
+ FixtureRegisterWithContext(func(ctx RegistrationContext) {
+ ctx.RegisterModuleType("mock_bad_module", newMockLicensesBadModule)
+ ctx.RegisterModuleType("mock_library", newMockLicensesLibraryModule)
+ ctx.RegisterModuleType("mock_defaults", defaultsLicensesFactory)
+ }),
+ test.fs.AddToFixture(),
+ ).
+ ExtendWithErrorHandler(FixtureExpectsAllErrorsToMatchAPattern(test.expectedErrors)).
+ RunTest(t)
if test.effectiveLicenses != nil {
- checkEffectiveLicenses(t, ctx, test.effectiveLicenses)
+ checkEffectiveLicenses(t, result, test.effectiveLicenses)
}
if test.effectivePackage != nil {
- checkEffectivePackage(t, ctx, test.effectivePackage)
+ checkEffectivePackage(t, result, test.effectivePackage)
}
if test.effectiveNotices != nil {
- checkEffectiveNotices(t, ctx, test.effectiveNotices)
+ checkEffectiveNotices(t, result, test.effectiveNotices)
}
if test.effectiveKinds != nil {
- checkEffectiveKinds(t, ctx, test.effectiveKinds)
+ checkEffectiveKinds(t, result, test.effectiveKinds)
}
if test.effectiveConditions != nil {
- checkEffectiveConditions(t, ctx, test.effectiveConditions)
+ checkEffectiveConditions(t, result, test.effectiveConditions)
}
if test.effectiveInheritedLicenses != nil {
- checkEffectiveInheritedLicenses(t, ctx, test.effectiveInheritedLicenses)
+ checkEffectiveInheritedLicenses(t, result, test.effectiveInheritedLicenses)
}
})
}
}
-func checkEffectiveLicenses(t *testing.T, ctx *TestContext, effectiveLicenses map[string][]string) {
+func checkEffectiveLicenses(t *testing.T, result *TestResult, effectiveLicenses map[string][]string) {
actualLicenses := make(map[string][]string)
- ctx.Context.Context.VisitAllModules(func(m blueprint.Module) {
+ result.Context.Context.VisitAllModules(func(m blueprint.Module) {
if _, ok := m.(*licenseModule); ok {
return
}
@@ -523,9 +543,9 @@
}
}
-func checkEffectiveInheritedLicenses(t *testing.T, ctx *TestContext, effectiveInheritedLicenses map[string][]string) {
+func checkEffectiveInheritedLicenses(t *testing.T, result *TestResult, effectiveInheritedLicenses map[string][]string) {
actualLicenses := make(map[string][]string)
- ctx.Context.Context.VisitAllModules(func(m blueprint.Module) {
+ result.Context.Context.VisitAllModules(func(m blueprint.Module) {
if _, ok := m.(*licenseModule); ok {
return
}
@@ -548,7 +568,7 @@
for _, l := range base.commonProperties.Effective_licenses {
inherited[l] = true
}
- ctx.Context.Context.VisitDepsDepthFirst(m, func(c blueprint.Module) {
+ result.Context.Context.VisitDepsDepthFirst(m, func(c blueprint.Module) {
if _, ok := c.(*licenseModule); ok {
return
}
@@ -588,9 +608,9 @@
}
}
-func checkEffectivePackage(t *testing.T, ctx *TestContext, effectivePackage map[string]string) {
+func checkEffectivePackage(t *testing.T, result *TestResult, effectivePackage map[string]string) {
actualPackage := make(map[string]string)
- ctx.Context.Context.VisitAllModules(func(m blueprint.Module) {
+ result.Context.Context.VisitAllModules(func(m blueprint.Module) {
if _, ok := m.(*licenseModule); ok {
return
}
@@ -628,9 +648,9 @@
}
}
-func checkEffectiveNotices(t *testing.T, ctx *TestContext, effectiveNotices map[string][]string) {
+func checkEffectiveNotices(t *testing.T, result *TestResult, effectiveNotices map[string][]string) {
actualNotices := make(map[string][]string)
- ctx.Context.Context.VisitAllModules(func(m blueprint.Module) {
+ result.Context.Context.VisitAllModules(func(m blueprint.Module) {
if _, ok := m.(*licenseModule); ok {
return
}
@@ -663,9 +683,9 @@
}
}
-func checkEffectiveKinds(t *testing.T, ctx *TestContext, effectiveKinds map[string][]string) {
+func checkEffectiveKinds(t *testing.T, result *TestResult, effectiveKinds map[string][]string) {
actualKinds := make(map[string][]string)
- ctx.Context.Context.VisitAllModules(func(m blueprint.Module) {
+ result.Context.Context.VisitAllModules(func(m blueprint.Module) {
if _, ok := m.(*licenseModule); ok {
return
}
@@ -698,9 +718,9 @@
}
}
-func checkEffectiveConditions(t *testing.T, ctx *TestContext, effectiveConditions map[string][]string) {
+func checkEffectiveConditions(t *testing.T, result *TestResult, effectiveConditions map[string][]string) {
actualConditions := make(map[string][]string)
- ctx.Context.Context.VisitAllModules(func(m blueprint.Module) {
+ result.Context.Context.VisitAllModules(func(m blueprint.Module) {
if _, ok := m.(*licenseModule); ok {
return
}
@@ -754,41 +774,6 @@
return true
}
-func testLicenses(buildDir string, fs map[string][]byte) (*TestContext, []error) {
-
- // Create a new config per test as licenses information is stored in the config.
- env := make(map[string]string)
- env["ANDROID_REQUIRE_LICENSES"] = "1"
- config := TestArchConfig(buildDir, env, "", fs)
-
- ctx := NewTestArchContext(config)
- ctx.RegisterModuleType("mock_bad_module", newMockLicensesBadModule)
- ctx.RegisterModuleType("mock_library", newMockLicensesLibraryModule)
- ctx.RegisterModuleType("mock_defaults", defaultsLicensesFactory)
-
- // Order of the following method calls is significant.
- RegisterPackageBuildComponents(ctx)
- registerTestPrebuiltBuildComponents(ctx)
- RegisterLicenseKindBuildComponents(ctx)
- RegisterLicenseBuildComponents(ctx)
- ctx.PreArchMutators(RegisterVisibilityRuleChecker)
- ctx.PreArchMutators(RegisterLicensesPackageMapper)
- ctx.PreArchMutators(RegisterDefaultsPreArchMutators)
- ctx.PreArchMutators(RegisterLicensesPropertyGatherer)
- ctx.PreArchMutators(RegisterVisibilityRuleGatherer)
- ctx.PostDepsMutators(RegisterVisibilityRuleEnforcer)
- ctx.PostDepsMutators(RegisterLicensesDependencyChecker)
- ctx.Register()
-
- _, errs := ctx.ParseBlueprintsFiles(".")
- if len(errs) > 0 {
- return ctx, errs
- }
-
- _, errs = ctx.PrepareBuildActions(config)
- return ctx, errs
-}
-
type mockLicensesBadProperties struct {
Visibility []string
}
diff --git a/android/mutator.go b/android/mutator.go
index b023001..9552aa1 100644
--- a/android/mutator.go
+++ b/android/mutator.go
@@ -33,22 +33,8 @@
// run FinalDeps mutators (CreateVariations disallowed in this phase)
// continue on to GenerateAndroidBuildActions
-func registerMutatorsToContext(ctx *blueprint.Context, mutators []*mutator) {
- for _, t := range mutators {
- var handle blueprint.MutatorHandle
- if t.bottomUpMutator != nil {
- handle = ctx.RegisterBottomUpMutator(t.name, t.bottomUpMutator)
- } else if t.topDownMutator != nil {
- handle = ctx.RegisterTopDownMutator(t.name, t.topDownMutator)
- }
- if t.parallel {
- handle.Parallel()
- }
- }
-}
-
// RegisterMutatorsForBazelConversion is a alternate registration pipeline for bp2build. Exported for testing.
-func RegisterMutatorsForBazelConversion(ctx *blueprint.Context, preArchMutators, depsMutators, bp2buildMutators []RegisterMutatorFunc) {
+func RegisterMutatorsForBazelConversion(ctx *Context, preArchMutators, depsMutators, bp2buildMutators []RegisterMutatorFunc) {
mctx := ®isterMutatorsContext{
bazelConversionMode: true,
}
@@ -80,10 +66,17 @@
f(mctx)
}
- registerMutatorsToContext(ctx, mctx.mutators)
+ mctx.mutators.registerAll(ctx)
}
-func registerMutators(ctx *blueprint.Context, preArch, preDeps, postDeps, finalDeps []RegisterMutatorFunc) {
+// collateGloballyRegisteredMutators constructs the list of mutators that have been registered
+// with the InitRegistrationContext and will be used at runtime.
+func collateGloballyRegisteredMutators() sortableComponents {
+ return collateRegisteredMutators(preArch, preDeps, postDeps, finalDeps)
+}
+
+// collateRegisteredMutators constructs a single list of mutators from the separate lists.
+func collateRegisteredMutators(preArch, preDeps, postDeps, finalDeps []RegisterMutatorFunc) sortableComponents {
mctx := ®isterMutatorsContext{}
register := func(funcs []RegisterMutatorFunc) {
@@ -103,11 +96,11 @@
mctx.finalPhase = true
register(finalDeps)
- registerMutatorsToContext(ctx, mctx.mutators)
+ return mctx.mutators
}
type registerMutatorsContext struct {
- mutators []*mutator
+ mutators sortableComponents
finalPhase bool
bazelConversionMode bool
}
@@ -473,6 +466,23 @@
return mutator
}
+func (mutator *mutator) componentName() string {
+ return mutator.name
+}
+
+func (mutator *mutator) register(ctx *Context) {
+ blueprintCtx := ctx.Context
+ var handle blueprint.MutatorHandle
+ if mutator.bottomUpMutator != nil {
+ handle = blueprintCtx.RegisterBottomUpMutator(mutator.name, mutator.bottomUpMutator)
+ } else if mutator.topDownMutator != nil {
+ handle = blueprintCtx.RegisterTopDownMutator(mutator.name, mutator.topDownMutator)
+ }
+ if mutator.parallel {
+ handle.Parallel()
+ }
+}
+
type MutatorHandle interface {
Parallel() MutatorHandle
}
diff --git a/android/override_module.go b/android/override_module.go
index fa08566..97acc5c 100644
--- a/android/override_module.go
+++ b/android/override_module.go
@@ -215,7 +215,14 @@
ctx.BottomUp("override_deps", overrideModuleDepsMutator).Parallel()
ctx.TopDown("register_override", registerOverrideMutator).Parallel()
ctx.BottomUp("perform_override", performOverrideMutator).Parallel()
+ // overridableModuleDepsMutator calls OverridablePropertiesDepsMutator so that overridable modules can
+ // add deps from overridable properties.
ctx.BottomUp("overridable_deps", overridableModuleDepsMutator).Parallel()
+ // Because overridableModuleDepsMutator is run after PrebuiltPostDepsMutator,
+ // prebuilt's ReplaceDependencies doesn't affect to those deps added by overridable properties.
+ // By running PrebuiltPostDepsMutator again after overridableModuleDepsMutator, deps via overridable properties
+ // can be replaced with prebuilts.
+ ctx.BottomUp("replace_deps_on_prebuilts_for_overridable_deps_again", PrebuiltPostDepsMutator).Parallel()
ctx.BottomUp("replace_deps_on_override", replaceDepsOnOverridingModuleMutator).Parallel()
}
diff --git a/android/path_properties.go b/android/path_properties.go
index 853e5a9..2c8d27c 100644
--- a/android/path_properties.go
+++ b/android/path_properties.go
@@ -118,6 +118,13 @@
*values = append(*values, v.Index(i).Field(index[0]))
}
} else {
+ // Dereference it if it's a pointer.
+ if v.Kind() == reflect.Ptr {
+ if v.IsNil() {
+ return
+ }
+ v = v.Elem()
+ }
*values = append(*values, v.Field(index[0]))
}
return
diff --git a/android/path_properties_test.go b/android/path_properties_test.go
index 2aab748..85c96ee 100644
--- a/android/path_properties_test.go
+++ b/android/path_properties_test.go
@@ -26,6 +26,9 @@
Bar []string `android:"path,arch_variant"`
Baz *string `android:"path"`
Qux string
+ V *struct {
+ W string `android:"path"`
+ }
}
// A second property struct with a duplicate property name
@@ -94,8 +97,11 @@
],
},
],
+ v: {
+ w: ":w",
+ },
}`,
- deps: []string{"a", "b", "c", "x", "y", "z"},
+ deps: []string{"a", "b", "c", "w", "x", "y", "z"},
},
{
name: "arch variant",
@@ -136,6 +142,10 @@
}
filegroup {
+ name: "w",
+ }
+
+ filegroup {
name: "x",
}
diff --git a/android/queryview.go b/android/queryview.go
index 9e3e45a..12d14df 100644
--- a/android/queryview.go
+++ b/android/queryview.go
@@ -66,12 +66,20 @@
bazelQueryView := ctx.Rule(pctx, "bazelQueryView",
blueprint.RuleParams{
Command: fmt.Sprintf(
- "rm -rf ${outDir}/* && "+
- "%s --bazel_queryview_dir ${outDir} %s && "+
- "echo WORKSPACE: `cat %s` > ${outDir}/.queryview-depfile.d",
- primaryBuilder.String(),
- strings.Join(os.Args[1:], " "),
+ `rm -rf "${outDir}/"* && `+
+ `mkdir -p "${outDir}" && `+
+ `echo WORKSPACE: cat "%s" > "${outDir}/.queryview-depfile.d" && `+
+ `BUILDER="%s" && `+
+ `echo BUILDER=$$BUILDER && `+
+ `cd "$$(dirname "$$BUILDER")" && `+
+ `echo PWD=$$PWD && `+
+ `ABSBUILDER="$$PWD/$$(basename "$$BUILDER")" && `+
+ `echo ABSBUILDER=$$ABSBUILDER && `+
+ `cd / && `+
+ `env -i "$$ABSBUILDER" --bazel_queryview_dir "${outDir}" "%s"`,
moduleListFilePath.String(), // Use the contents of Android.bp.list as the depfile.
+ primaryBuilder.String(),
+ strings.Join(os.Args[1:], "\" \""),
),
CommandDeps: []string{primaryBuilder.String()},
Description: fmt.Sprintf(
diff --git a/android/register.go b/android/register.go
index 47df972..c9e66e9 100644
--- a/android/register.go
+++ b/android/register.go
@@ -21,21 +21,78 @@
"github.com/google/blueprint"
)
+// A sortable component is one whose registration order affects the order in which it is executed
+// and so affects the behavior of the build system. As a result it is important for the order in
+// which they are registered during tests to match the order used at runtime and so the test
+// infrastructure will sort them to match.
+//
+// The sortable components are mutators, singletons and pre-singletons. Module types are not
+// sortable because their order of registration does not affect the runtime behavior.
+type sortableComponent interface {
+ // componentName returns the name of the component.
+ //
+ // Uniquely identifies the components within the set of components used at runtimr and during
+ // tests.
+ componentName() string
+
+ // register registers this component in the supplied context.
+ register(ctx *Context)
+}
+
+type sortableComponents []sortableComponent
+
+// registerAll registers all components in this slice with the supplied context.
+func (r sortableComponents) registerAll(ctx *Context) {
+ for _, c := range r {
+ c.register(ctx)
+ }
+}
+
type moduleType struct {
name string
factory ModuleFactory
}
+func (t moduleType) register(ctx *Context) {
+ ctx.RegisterModuleType(t.name, ModuleFactoryAdaptor(t.factory))
+}
+
var moduleTypes []moduleType
var moduleTypesForDocs = map[string]reflect.Value{}
type singleton struct {
+ // True if this should be registered as a pre-singleton, false otherwise.
+ pre bool
+
name string
factory SingletonFactory
}
-var singletons []singleton
-var preSingletons []singleton
+func newSingleton(name string, factory SingletonFactory) singleton {
+ return singleton{false, name, factory}
+}
+
+func newPreSingleton(name string, factory SingletonFactory) singleton {
+ return singleton{true, name, factory}
+}
+
+func (s singleton) componentName() string {
+ return s.name
+}
+
+func (s singleton) register(ctx *Context) {
+ adaptor := SingletonFactoryAdaptor(ctx, s.factory)
+ if s.pre {
+ ctx.RegisterPreSingletonType(s.name, adaptor)
+ } else {
+ ctx.RegisterSingletonType(s.name, adaptor)
+ }
+}
+
+var _ sortableComponent = singleton{}
+
+var singletons sortableComponents
+var preSingletons sortableComponents
type mutator struct {
name string
@@ -44,6 +101,8 @@
parallel bool
}
+var _ sortableComponent = &mutator{}
+
type ModuleFactory func() Module
// ModuleFactoryAdaptor wraps a ModuleFactory into a blueprint.ModuleFactory by converting a Module
@@ -84,11 +143,11 @@
}
func RegisterSingletonType(name string, factory SingletonFactory) {
- singletons = append(singletons, singleton{name, factory})
+ singletons = append(singletons, newSingleton(name, factory))
}
func RegisterPreSingletonType(name string, factory SingletonFactory) {
- preSingletons = append(preSingletons, singleton{name, factory})
+ preSingletons = append(preSingletons, newPreSingleton(name, factory))
}
type Context struct {
@@ -107,46 +166,51 @@
// files to semantically equivalent BUILD files.
func (ctx *Context) RegisterForBazelConversion() {
for _, t := range moduleTypes {
- ctx.RegisterModuleType(t.name, ModuleFactoryAdaptor(t.factory))
+ t.register(ctx)
}
// Required for SingletonModule types, even though we are not using them.
for _, t := range singletons {
- ctx.RegisterSingletonType(t.name, SingletonFactoryAdaptor(ctx, t.factory))
+ t.register(ctx)
}
- RegisterMutatorsForBazelConversion(ctx.Context, bp2buildPreArchMutators, bp2buildDepsMutators, bp2buildMutators)
+ RegisterMutatorsForBazelConversion(ctx, bp2buildPreArchMutators, bp2buildDepsMutators, bp2buildMutators)
}
// Register the pipeline of singletons, module types, and mutators for
// generating build.ninja and other files for Kati, from Android.bp files.
func (ctx *Context) Register() {
- for _, t := range preSingletons {
- ctx.RegisterPreSingletonType(t.name, SingletonFactoryAdaptor(ctx, t.factory))
- }
+ preSingletons.registerAll(ctx)
for _, t := range moduleTypes {
- ctx.RegisterModuleType(t.name, ModuleFactoryAdaptor(t.factory))
+ t.register(ctx)
}
- for _, t := range singletons {
- ctx.RegisterSingletonType(t.name, SingletonFactoryAdaptor(ctx, t.factory))
- }
+ mutators := collateGloballyRegisteredMutators()
+ mutators.registerAll(ctx)
- registerMutators(ctx.Context, preArch, preDeps, postDeps, finalDeps)
+ singletons := collateGloballyRegisteredSingletons()
+ singletons.registerAll(ctx)
+}
- ctx.RegisterSingletonType("bazeldeps", SingletonFactoryAdaptor(ctx, BazelSingleton))
+func collateGloballyRegisteredSingletons() sortableComponents {
+ allSingletons := append(sortableComponents(nil), singletons...)
+ allSingletons = append(allSingletons,
+ singleton{false, "bazeldeps", BazelSingleton},
- // Register phony just before makevars so it can write out its phony rules as Make rules
- ctx.RegisterSingletonType("phony", SingletonFactoryAdaptor(ctx, phonySingletonFactory))
+ // Register phony just before makevars so it can write out its phony rules as Make rules
+ singleton{false, "phony", phonySingletonFactory},
- // Register makevars after other singletons so they can export values through makevars
- ctx.RegisterSingletonType("makevars", SingletonFactoryAdaptor(ctx, makeVarsSingletonFunc))
+ // Register makevars after other singletons so they can export values through makevars
+ singleton{false, "makevars", makeVarsSingletonFunc},
- // Register env and ninjadeps last so that they can track all used environment variables and
- // Ninja file dependencies stored in the config.
- ctx.RegisterSingletonType("env", SingletonFactoryAdaptor(ctx, EnvSingleton))
- ctx.RegisterSingletonType("ninjadeps", SingletonFactoryAdaptor(ctx, ninjaDepsSingletonFactory))
+ // Register env and ninjadeps last so that they can track all used environment variables and
+ // Ninja file dependencies stored in the config.
+ singleton{false, "env", EnvSingleton},
+ singleton{false, "ninjadeps", ninjaDepsSingletonFactory},
+ )
+
+ return allSingletons
}
func ModuleTypeFactories() map[string]ModuleFactory {
diff --git a/android/soongconfig/modules.go b/android/soongconfig/modules.go
index c62e76d..34b180d 100644
--- a/android/soongconfig/modules.go
+++ b/android/soongconfig/modules.go
@@ -295,18 +295,25 @@
recurse = func(prefix string, aps []string) ([]string, reflect.Type) {
var fields []reflect.StructField
+ // Iterate while the list is non-empty so it can be modified in the loop.
for len(affectableProperties) > 0 {
p := affectableProperties[0]
if !strings.HasPrefix(affectableProperties[0], prefix) {
+ // The properties are sorted and recurse is always called with a prefix that matches
+ // the first property in the list, so if we've reached one that doesn't match the
+ // prefix we are done with this prefix.
break
}
- affectableProperties = affectableProperties[1:]
nestedProperty := strings.TrimPrefix(p, prefix)
if i := strings.IndexRune(nestedProperty, '.'); i >= 0 {
var nestedType reflect.Type
nestedPrefix := nestedProperty[:i+1]
+ // Recurse to handle the properties with the found prefix. This will return
+ // an updated affectableProperties with the handled entries removed from the front
+ // of the list, and the type that contains the handled entries. The type may be
+ // nil if none of the entries matched factoryProps.
affectableProperties, nestedType = recurse(prefix+nestedPrefix, affectableProperties)
if nestedType != nil {
@@ -325,6 +332,8 @@
Type: typ,
})
}
+ // The first element in the list has been handled, remove it from the list.
+ affectableProperties = affectableProperties[1:]
}
}
diff --git a/android/soongconfig/modules_test.go b/android/soongconfig/modules_test.go
index b824c78..48cdfe7 100644
--- a/android/soongconfig/modules_test.go
+++ b/android/soongconfig/modules_test.go
@@ -235,6 +235,44 @@
}{},
want: "",
},
+ {
+ name: "nested",
+ affectableProperties: []string{"multilib.lib32.cflags"},
+ factoryProps: struct {
+ Multilib struct {
+ Lib32 struct {
+ Cflags string
+ }
+ }
+ }{},
+ want: "*struct { Multilib struct { Lib32 struct { Cflags string } } }",
+ },
+ {
+ name: "complex",
+ affectableProperties: []string{
+ "cflags",
+ "multilib.lib32.cflags",
+ "multilib.lib32.ldflags",
+ "multilib.lib64.cflags",
+ "multilib.lib64.ldflags",
+ "zflags",
+ },
+ factoryProps: struct {
+ Cflags string
+ Multilib struct {
+ Lib32 struct {
+ Cflags string
+ Ldflags string
+ }
+ Lib64 struct {
+ Cflags string
+ Ldflags string
+ }
+ }
+ Zflags string
+ }{},
+ want: "*struct { Cflags string; Multilib struct { Lib32 struct { Cflags string; Ldflags string }; Lib64 struct { Cflags string; Ldflags string } }; Zflags string }",
+ },
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
diff --git a/android/test_asserts.go b/android/test_asserts.go
new file mode 100644
index 0000000..d0de523
--- /dev/null
+++ b/android/test_asserts.go
@@ -0,0 +1,134 @@
+// Copyright 2021 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 (
+ "reflect"
+ "strings"
+ "testing"
+)
+
+// This file contains general purpose test assert functions.
+
+// AssertBoolEquals checks if the expected and actual values are equal and if they are not then it
+// reports an error prefixed with the supplied message and including a reason for why it failed.
+func AssertBoolEquals(t *testing.T, message string, expected bool, actual bool) {
+ t.Helper()
+ if actual != expected {
+ t.Errorf("%s: expected %t, actual %t", message, expected, actual)
+ }
+}
+
+// AssertStringEquals checks if the expected and actual values are equal and if they are not then
+// it reports an error prefixed with the supplied message and including a reason for why it failed.
+func AssertStringEquals(t *testing.T, message string, expected string, actual string) {
+ t.Helper()
+ if actual != expected {
+ t.Errorf("%s: expected %s, actual %s", message, expected, actual)
+ }
+}
+
+// AssertErrorMessageEquals checks if the error is not nil and has the expected message. If it does
+// not then this reports an error prefixed with the supplied message and including a reason for why
+// it failed.
+func AssertErrorMessageEquals(t *testing.T, message string, expected string, actual error) {
+ t.Helper()
+ if actual == nil {
+ t.Errorf("Expected error but was nil")
+ } else if actual.Error() != expected {
+ t.Errorf("%s: expected %s, actual %s", message, expected, actual.Error())
+ }
+}
+
+// AssertTrimmedStringEquals checks if the expected and actual values are the same after trimming
+// leading and trailing spaces from them both. If they are not then it reports an error prefixed
+// with the supplied message and including a reason for why it failed.
+func AssertTrimmedStringEquals(t *testing.T, message string, expected string, actual string) {
+ t.Helper()
+ AssertStringEquals(t, message, strings.TrimSpace(expected), strings.TrimSpace(actual))
+}
+
+// AssertStringDoesContain checks if the string contains the expected substring. If it does not
+// then it reports an error prefixed with the supplied message and including a reason for why it
+// failed.
+func AssertStringDoesContain(t *testing.T, message string, s string, expectedSubstring string) {
+ t.Helper()
+ if !strings.Contains(s, expectedSubstring) {
+ t.Errorf("%s: could not find %q within %q", message, expectedSubstring, s)
+ }
+}
+
+// AssertStringDoesNotContain checks if the string contains the expected substring. If it does then
+// it reports an error prefixed with the supplied message and including a reason for why it failed.
+func AssertStringDoesNotContain(t *testing.T, message string, s string, unexpectedSubstring string) {
+ t.Helper()
+ if strings.Contains(s, unexpectedSubstring) {
+ t.Errorf("%s: unexpectedly found %q within %q", message, unexpectedSubstring, s)
+ }
+}
+
+// AssertStringListContains checks if the list of strings contains the expected string. If it does
+// not then it reports an error prefixed with the supplied message and including a reason for why it
+// failed.
+func AssertStringListContains(t *testing.T, message string, list []string, expected string) {
+ t.Helper()
+ if !InList(expected, list) {
+ t.Errorf("%s: could not find %q within %q", message, expected, list)
+ }
+}
+
+// AssertArrayString checks if the expected and actual values are equal and if they are not then it
+// reports an error prefixed with the supplied message and including a reason for why it failed.
+func AssertArrayString(t *testing.T, message string, expected, actual []string) {
+ t.Helper()
+ if len(actual) != len(expected) {
+ t.Errorf("%s: expected %d (%q), actual (%d) %q", message, len(expected), expected, len(actual), actual)
+ return
+ }
+ for i := range actual {
+ if actual[i] != expected[i] {
+ t.Errorf("%s: expected %d-th, %q (%q), actual %q (%q)",
+ message, i, expected[i], expected, actual[i], actual)
+ return
+ }
+ }
+}
+
+// AssertDeepEquals checks if the expected and actual values are equal using reflect.DeepEqual and
+// if they are not then it reports an error prefixed with the supplied message and including a
+// reason for why it failed.
+func AssertDeepEquals(t *testing.T, message string, expected interface{}, actual interface{}) {
+ t.Helper()
+ if !reflect.DeepEqual(actual, expected) {
+ t.Errorf("%s: expected:\n %#v\n got:\n %#v", message, expected, actual)
+ }
+}
+
+// AssertPanic checks that the supplied function panics as expected.
+func AssertPanic(t *testing.T, message string, funcThatShouldPanic func()) {
+ t.Helper()
+ panicked := false
+ func() {
+ defer func() {
+ if x := recover(); x != nil {
+ panicked = true
+ }
+ }()
+ funcThatShouldPanic()
+ }()
+ if !panicked {
+ t.Error(message)
+ }
+}
diff --git a/android/testing.go b/android/testing.go
index d8c123b..dd3d607 100644
--- a/android/testing.go
+++ b/android/testing.go
@@ -20,9 +20,11 @@
"regexp"
"sort"
"strings"
+ "sync"
"testing"
"github.com/google/blueprint"
+ "github.com/google/blueprint/proptools"
)
func NewTestContext(config Config) *TestContext {
@@ -72,17 +74,47 @@
ctx.PostDepsMutators(RegisterOverridePostDepsMutators)
})
-// Prepares an integration test with build components from the android package.
-var PrepareForIntegrationTestWithAndroid = GroupFixturePreparers(
- // Mutators. Must match order in mutator.go.
+// Test fixture preparer that will register most java build components.
+//
+// Singletons and mutators should only be added here if they are needed for a majority of java
+// module types, otherwise they should be added under a separate preparer to allow them to be
+// selected only when needed to reduce test execution time.
+//
+// Module types do not have much of an overhead unless they are used so this should include as many
+// module types as possible. The exceptions are those module types that require mutators and/or
+// singletons in order to function in which case they should be kept together in a separate
+// preparer.
+//
+// The mutators in this group were chosen because they are needed by the vast majority of tests.
+var PrepareForTestWithAndroidBuildComponents = GroupFixturePreparers(
+ // Sorted alphabetically as the actual order does not matter as tests automatically enforce the
+ // correct order.
PrepareForTestWithArchMutator,
- PrepareForTestWithDefaults,
PrepareForTestWithComponentsMutator,
- PrepareForTestWithPrebuilts,
- PrepareForTestWithOverrides,
-
- // Modules
+ PrepareForTestWithDefaults,
PrepareForTestWithFilegroup,
+ PrepareForTestWithOverrides,
+ PrepareForTestWithPackageModule,
+ PrepareForTestWithPrebuilts,
+ PrepareForTestWithVisibility,
+)
+
+// Prepares an integration test with all build components from the android package.
+//
+// This should only be used by tests that want to run with as much of the build enabled as possible.
+var PrepareForIntegrationTestWithAndroid = GroupFixturePreparers(
+ PrepareForTestWithAndroidBuildComponents,
+)
+
+// Prepares a test that may be missing dependencies by setting allow_missing_dependencies to
+// true.
+var PrepareForTestWithAllowMissingDependencies = GroupFixturePreparers(
+ FixtureModifyProductVariables(func(variables FixtureProductVariables) {
+ variables.Allow_missing_dependencies = proptools.BoolPtr(true)
+ }),
+ FixtureModifyContext(func(ctx *TestContext) {
+ ctx.SetAllowMissingDependencies(true)
+ }),
)
func NewTestArchContext(config Config) *TestContext {
@@ -96,6 +128,13 @@
preArch, preDeps, postDeps, finalDeps []RegisterMutatorFunc
bp2buildPreArch, bp2buildDeps, bp2buildMutators []RegisterMutatorFunc
NameResolver *NameResolver
+
+ // The list of pre-singletons and singletons registered for the test.
+ preSingletons, singletons sortableComponents
+
+ // The order in which the pre-singletons, mutators and singletons will be run in this test
+ // context; for debugging.
+ preSingletonOrder, mutatorOrder, singletonOrder []string
}
func (ctx *TestContext) PreArchMutators(f RegisterMutatorFunc) {
@@ -140,15 +179,244 @@
ctx.bp2buildDeps = append(ctx.bp2buildDeps, f)
}
-func (ctx *TestContext) Register() {
- registerMutators(ctx.Context.Context, ctx.preArch, ctx.preDeps, ctx.postDeps, ctx.finalDeps)
+// registeredComponentOrder defines the order in which a sortableComponent type is registered at
+// runtime and provides support for reordering the components registered for a test in the same
+// way.
+type registeredComponentOrder struct {
+ // The name of the component type, used for error messages.
+ componentType string
+ // The names of the registered components in the order in which they were registered.
+ namesInOrder []string
+
+ // Maps from the component name to its position in the runtime ordering.
+ namesToIndex map[string]int
+
+ // A function that defines the order between two named components that can be used to sort a slice
+ // of component names into the same order as they appear in namesInOrder.
+ less func(string, string) bool
+}
+
+// registeredComponentOrderFromExistingOrder takes an existing slice of sortableComponents and
+// creates a registeredComponentOrder that contains a less function that can be used to sort a
+// subset of that list of names so it is in the same order as the original sortableComponents.
+func registeredComponentOrderFromExistingOrder(componentType string, existingOrder sortableComponents) registeredComponentOrder {
+ // Only the names from the existing order are needed for this so create a list of component names
+ // in the correct order.
+ namesInOrder := componentsToNames(existingOrder)
+
+ // Populate the map from name to position in the list.
+ nameToIndex := make(map[string]int)
+ for i, n := range namesInOrder {
+ nameToIndex[n] = i
+ }
+
+ // A function to use to map from a name to an index in the original order.
+ indexOf := func(name string) int {
+ index, ok := nameToIndex[name]
+ if !ok {
+ // Should never happen as tests that use components that are not known at runtime do not sort
+ // so should never use this function.
+ panic(fmt.Errorf("internal error: unknown %s %q should be one of %s", componentType, name, strings.Join(namesInOrder, ", ")))
+ }
+ return index
+ }
+
+ // The less function.
+ less := func(n1, n2 string) bool {
+ i1 := indexOf(n1)
+ i2 := indexOf(n2)
+ return i1 < i2
+ }
+
+ return registeredComponentOrder{
+ componentType: componentType,
+ namesInOrder: namesInOrder,
+ namesToIndex: nameToIndex,
+ less: less,
+ }
+}
+
+// componentsToNames maps from the slice of components to a slice of their names.
+func componentsToNames(components sortableComponents) []string {
+ names := make([]string, len(components))
+ for i, c := range components {
+ names[i] = c.componentName()
+ }
+ return names
+}
+
+// enforceOrdering enforces the supplied components are in the same order as is defined in this
+// object.
+//
+// If the supplied components contains any components that are not registered at runtime, i.e. test
+// specific components, then it is impossible to sort them into an order that both matches the
+// runtime and also preserves the implicit ordering defined in the test. In that case it will not
+// sort the components, instead it will just check that the components are in the correct order.
+//
+// Otherwise, this will sort the supplied components in place.
+func (o *registeredComponentOrder) enforceOrdering(components sortableComponents) {
+ // Check to see if the list of components contains any components that are
+ // not registered at runtime.
+ var unknownComponents []string
+ testOrder := componentsToNames(components)
+ for _, name := range testOrder {
+ if _, ok := o.namesToIndex[name]; !ok {
+ unknownComponents = append(unknownComponents, name)
+ break
+ }
+ }
+
+ // If the slice contains some unknown components then it is not possible to
+ // sort them into an order that matches the runtime while also preserving the
+ // order expected from the test, so in that case don't sort just check that
+ // the order of the known mutators does match.
+ if len(unknownComponents) > 0 {
+ // Check order.
+ o.checkTestOrder(testOrder, unknownComponents)
+ } else {
+ // Sort the components.
+ sort.Slice(components, func(i, j int) bool {
+ n1 := components[i].componentName()
+ n2 := components[j].componentName()
+ return o.less(n1, n2)
+ })
+ }
+}
+
+// checkTestOrder checks that the supplied testOrder matches the one defined by this object,
+// panicking if it does not.
+func (o *registeredComponentOrder) checkTestOrder(testOrder []string, unknownComponents []string) {
+ lastMatchingTest := -1
+ matchCount := 0
+ // Take a copy of the runtime order as it is modified during the comparison.
+ runtimeOrder := append([]string(nil), o.namesInOrder...)
+ componentType := o.componentType
+ for i, j := 0, 0; i < len(testOrder) && j < len(runtimeOrder); {
+ test := testOrder[i]
+ runtime := runtimeOrder[j]
+
+ if test == runtime {
+ testOrder[i] = test + fmt.Sprintf(" <-- matched with runtime %s %d", componentType, j)
+ runtimeOrder[j] = runtime + fmt.Sprintf(" <-- matched with test %s %d", componentType, i)
+ lastMatchingTest = i
+ i += 1
+ j += 1
+ matchCount += 1
+ } else if _, ok := o.namesToIndex[test]; !ok {
+ // The test component is not registered globally so assume it is the correct place, treat it
+ // as having matched and skip it.
+ i += 1
+ matchCount += 1
+ } else {
+ // Assume that the test list is in the same order as the runtime list but the runtime list
+ // contains some components that are not present in the tests. So, skip the runtime component
+ // to try and find the next one that matches the current test component.
+ j += 1
+ }
+ }
+
+ // If every item in the test order was either test specific or matched one in the runtime then
+ // it is in the correct order. Otherwise, it was not so fail.
+ if matchCount != len(testOrder) {
+ // The test component names were not all matched with a runtime component name so there must
+ // either be a component present in the test that is not present in the runtime or they must be
+ // in the wrong order.
+ testOrder[lastMatchingTest+1] = testOrder[lastMatchingTest+1] + " <--- unmatched"
+ panic(fmt.Errorf("the tests uses test specific components %q and so cannot be automatically sorted."+
+ " Unfortunately it uses %s components in the wrong order.\n"+
+ "test order:\n %s\n"+
+ "runtime order\n %s\n",
+ SortedUniqueStrings(unknownComponents),
+ componentType,
+ strings.Join(testOrder, "\n "),
+ strings.Join(runtimeOrder, "\n ")))
+ }
+}
+
+// registrationSorter encapsulates the information needed to ensure that the test mutators are
+// registered, and thereby executed, in the same order as they are at runtime.
+//
+// It MUST be populated lazily AFTER all package initialization has been done otherwise it will
+// only define the order for a subset of all the registered build components that are available for
+// the packages being tested.
+//
+// e.g if this is initialized during say the cc package initialization then any tests run in the
+// java package will not sort build components registered by the java package's init() functions.
+type registrationSorter struct {
+ // Used to ensure that this is only created once.
+ once sync.Once
+
+ // The order of pre-singletons
+ preSingletonOrder registeredComponentOrder
+
+ // The order of mutators
+ mutatorOrder registeredComponentOrder
+
+ // The order of singletons
+ singletonOrder registeredComponentOrder
+}
+
+// populate initializes this structure from globally registered build components.
+//
+// Only the first call has any effect.
+func (s *registrationSorter) populate() {
+ s.once.Do(func() {
+ // Create an ordering from the globally registered pre-singletons.
+ s.preSingletonOrder = registeredComponentOrderFromExistingOrder("pre-singleton", preSingletons)
+
+ // Created an ordering from the globally registered mutators.
+ globallyRegisteredMutators := collateGloballyRegisteredMutators()
+ s.mutatorOrder = registeredComponentOrderFromExistingOrder("mutator", globallyRegisteredMutators)
+
+ // Create an ordering from the globally registered singletons.
+ globallyRegisteredSingletons := collateGloballyRegisteredSingletons()
+ s.singletonOrder = registeredComponentOrderFromExistingOrder("singleton", globallyRegisteredSingletons)
+ })
+}
+
+// Provides support for enforcing the same order in which build components are registered globally
+// to the order in which they are registered during tests.
+//
+// MUST only be accessed via the globallyRegisteredComponentsOrder func.
+var globalRegistrationSorter registrationSorter
+
+// globallyRegisteredComponentsOrder returns the globalRegistrationSorter after ensuring it is
+// correctly populated.
+func globallyRegisteredComponentsOrder() *registrationSorter {
+ globalRegistrationSorter.populate()
+ return &globalRegistrationSorter
+}
+
+func (ctx *TestContext) Register() {
+ globalOrder := globallyRegisteredComponentsOrder()
+
+ // Ensure that the pre-singletons used in the test are in the same order as they are used at
+ // runtime.
+ globalOrder.preSingletonOrder.enforceOrdering(ctx.preSingletons)
+ ctx.preSingletons.registerAll(ctx.Context)
+
+ mutators := collateRegisteredMutators(ctx.preArch, ctx.preDeps, ctx.postDeps, ctx.finalDeps)
+ // Ensure that the mutators used in the test are in the same order as they are used at runtime.
+ globalOrder.mutatorOrder.enforceOrdering(mutators)
+ mutators.registerAll(ctx.Context)
+
+ // Register the env singleton with this context before sorting.
ctx.RegisterSingletonType("env", EnvSingleton)
+
+ // Ensure that the singletons used in the test are in the same order as they are used at runtime.
+ globalOrder.singletonOrder.enforceOrdering(ctx.singletons)
+ ctx.singletons.registerAll(ctx.Context)
+
+ // Save the sorted components order away to make them easy to access while debugging.
+ ctx.preSingletonOrder = componentsToNames(preSingletons)
+ ctx.mutatorOrder = componentsToNames(mutators)
+ ctx.singletonOrder = componentsToNames(singletons)
}
// RegisterForBazelConversion prepares a test context for bp2build conversion.
func (ctx *TestContext) RegisterForBazelConversion() {
- RegisterMutatorsForBazelConversion(ctx.Context.Context, ctx.bp2buildPreArch, ctx.bp2buildDeps, ctx.bp2buildMutators)
+ RegisterMutatorsForBazelConversion(ctx.Context, ctx.bp2buildPreArch, ctx.bp2buildDeps, ctx.bp2buildMutators)
}
func (ctx *TestContext) ParseFileList(rootDir string, filePaths []string) (deps []string, errs []error) {
@@ -174,11 +442,11 @@
}
func (ctx *TestContext) RegisterSingletonType(name string, factory SingletonFactory) {
- ctx.Context.RegisterSingletonType(name, SingletonFactoryAdaptor(ctx.Context, factory))
+ ctx.singletons = append(ctx.singletons, newSingleton(name, factory))
}
func (ctx *TestContext) RegisterPreSingletonType(name string, factory SingletonFactory) {
- ctx.Context.RegisterPreSingletonType(name, SingletonFactoryAdaptor(ctx.Context, factory))
+ ctx.preSingletons = append(ctx.preSingletons, newPreSingleton(name, factory))
}
func (ctx *TestContext) ModuleForTests(name, variant string) TestingModule {
@@ -550,10 +818,6 @@
return "<nil path>"
}
p := path.String()
- // Allow absolute paths to /dev/
- if strings.HasPrefix(p, "/dev/") {
- return p
- }
if w, ok := path.(WritablePath); ok {
rel, err := filepath.Rel(w.buildDir(), p)
if err != nil {
diff --git a/android/variable.go b/android/variable.go
index dd000ad..be12a0a 100644
--- a/android/variable.go
+++ b/android/variable.go
@@ -24,11 +24,17 @@
)
func init() {
- PreDepsMutators(func(ctx RegisterMutatorsContext) {
+ registerVariableBuildComponents(InitRegistrationContext)
+}
+
+func registerVariableBuildComponents(ctx RegistrationContext) {
+ ctx.PreDepsMutators(func(ctx RegisterMutatorsContext) {
ctx.BottomUp("variable", VariableMutator).Parallel()
})
}
+var PrepareForTestWithVariables = FixtureRegisterWithContext(registerVariableBuildComponents)
+
type variableProperties struct {
Product_variables struct {
Platform_sdk_version struct {
diff --git a/android/visibility.go b/android/visibility.go
index 631e88f..5d1be6b 100644
--- a/android/visibility.go
+++ b/android/visibility.go
@@ -202,17 +202,14 @@
ExcludeFromVisibilityEnforcement()
}
-var PrepareForTestWithVisibilityRuleChecker = FixtureRegisterWithContext(func(ctx RegistrationContext) {
+// The visibility mutators.
+var PrepareForTestWithVisibility = FixtureRegisterWithContext(registerVisibilityMutators)
+
+func registerVisibilityMutators(ctx RegistrationContext) {
ctx.PreArchMutators(RegisterVisibilityRuleChecker)
-})
-
-var PrepareForTestWithVisibilityRuleGatherer = FixtureRegisterWithContext(func(ctx RegistrationContext) {
ctx.PreArchMutators(RegisterVisibilityRuleGatherer)
-})
-
-var PrepareForTestWithVisibilityRuleEnforcer = FixtureRegisterWithContext(func(ctx RegistrationContext) {
ctx.PostDepsMutators(RegisterVisibilityRuleEnforcer)
-})
+}
// The rule checker needs to be registered before defaults expansion to correctly check that
// //visibility:xxx isn't combined with other packages in the same list in any one module.
diff --git a/android/visibility_test.go b/android/visibility_test.go
index 30cdcbf..fdf18ce 100644
--- a/android/visibility_test.go
+++ b/android/visibility_test.go
@@ -1143,39 +1143,40 @@
for _, test := range visibilityTests {
t.Run(test.name, func(t *testing.T) {
result := emptyTestFixtureFactory.Extend(
+ // General preparers in alphabetical order as test infrastructure will enforce correct
+ // registration order.
+ PrepareForTestWithArchMutator,
+ PrepareForTestWithDefaults,
+ PrepareForTestWithOverrides,
+ PrepareForTestWithPackageModule,
+ PrepareForTestWithPrebuilts,
+ PrepareForTestWithVisibility,
+
+ // Additional test specific preparers.
FixtureRegisterWithContext(func(ctx RegistrationContext) {
ctx.RegisterModuleType("mock_library", newMockLibraryModule)
ctx.RegisterModuleType("mock_parent", newMockParentFactory)
ctx.RegisterModuleType("mock_defaults", defaultsFactory)
}),
prepareForTestWithFakePrebuiltModules,
- PrepareForTestWithPackageModule,
- // Order of the following method calls is significant as they register mutators.
- PrepareForTestWithArchMutator,
- PrepareForTestWithPrebuilts,
- PrepareForTestWithOverrides,
- PrepareForTestWithVisibilityRuleChecker,
- PrepareForTestWithDefaults,
- PrepareForTestWithVisibilityRuleGatherer,
- PrepareForTestWithVisibilityRuleEnforcer,
// Add additional files to the mock filesystem
test.fs.AddToFixture(),
).
- SetErrorHandler(FixtureExpectsAllErrorsToMatchAPattern(test.expectedErrors)).
+ ExtendWithErrorHandler(FixtureExpectsAllErrorsToMatchAPattern(test.expectedErrors)).
RunTest(t)
if test.effectiveVisibility != nil {
- checkEffectiveVisibility(result, test.effectiveVisibility)
+ checkEffectiveVisibility(t, result, test.effectiveVisibility)
}
})
}
}
-func checkEffectiveVisibility(result *TestResult, effectiveVisibility map[qualifiedModuleName][]string) {
+func checkEffectiveVisibility(t *testing.T, result *TestResult, effectiveVisibility map[qualifiedModuleName][]string) {
for moduleName, expectedRules := range effectiveVisibility {
rule := effectiveVisibilityRules(result.Config, moduleName)
stringRules := rule.Strings()
- result.AssertDeepEquals("effective rules mismatch", expectedRules, stringRules)
+ AssertDeepEquals(t, "effective rules mismatch", expectedRules, stringRules)
}
}
diff --git a/android/writedocs.go b/android/writedocs.go
index 6417690..67b9aa3 100644
--- a/android/writedocs.go
+++ b/android/writedocs.go
@@ -35,10 +35,11 @@
func primaryBuilderPath(ctx SingletonContext) Path {
buildDir := absolutePath(ctx.Config().BuildDir())
- primaryBuilder, err := filepath.Rel(buildDir, os.Args[0])
+ binary := absolutePath(os.Args[0])
+ primaryBuilder, err := filepath.Rel(buildDir, binary)
if err != nil {
- ctx.Errorf("path to primary builder %q is not in build dir %q",
- os.Args[0], ctx.Config().BuildDir())
+ ctx.Errorf("path to primary builder %q is not in build dir %q (%q)",
+ os.Args[0], ctx.Config().BuildDir(), err)
}
return PathForOutput(ctx, primaryBuilder)
@@ -66,7 +67,9 @@
soongDocs := ctx.Rule(pctx, "soongDocs",
blueprint.RuleParams{
Command: fmt.Sprintf("rm -f ${outDir}/* && %s --soong_docs %s %s",
- primaryBuilder.String(), docsFile.String(), strings.Join(os.Args[1:], " ")),
+ primaryBuilder.String(),
+ docsFile.String(),
+ "\""+strings.Join(os.Args[1:], "\" \"")+"\""),
CommandDeps: []string{primaryBuilder.String()},
Description: fmt.Sprintf("%s docs $out", primaryBuilder.Base()),
},
diff --git a/apex/Android.bp b/apex/Android.bp
index 8a2edeb..1890b89 100644
--- a/apex/Android.bp
+++ b/apex/Android.bp
@@ -25,6 +25,7 @@
"deapexer.go",
"key.go",
"prebuilt.go",
+ "testing.go",
"vndk.go",
],
testSrcs: [
diff --git a/apex/allowed_deps.txt b/apex/allowed_deps.txt
index 476ac4a..154b9aa 100644
--- a/apex/allowed_deps.txt
+++ b/apex/allowed_deps.txt
@@ -163,11 +163,14 @@
crtend_so(minSdkVersion:16)
crtend_so(minSdkVersion:apex_inherit)
datastallprotosnano(minSdkVersion:29)
+derive_classpath(minSdkVersion:30)
derive_sdk(minSdkVersion:30)
derive_sdk(minSdkVersion:current)
derive_sdk_prefer32(minSdkVersion:30)
derive_sdk_prefer32(minSdkVersion:current)
+dnsresolver_aidl_interface-lateststable-ndk_platform(minSdkVersion:29)
dnsresolver_aidl_interface-unstable-ndk_platform(minSdkVersion:29)
+dnsresolver_aidl_interface-V7-ndk_platform(minSdkVersion:29)
dnsresolver_aidl_interface-V8-ndk_platform(minSdkVersion:29)
DocumentsUI-res-lib(minSdkVersion:29)
exoplayer2-extractor(minSdkVersion:16)
@@ -192,7 +195,7 @@
GoogleCellBroadcastApp(minSdkVersion:29)
GoogleCellBroadcastServiceModule(minSdkVersion:29)
GoogleExtServices(minSdkVersion:current)
-GooglePermissionController(minSdkVersion:28)
+GooglePermissionController(minSdkVersion:30)
guava(minSdkVersion:current)
gwp_asan_headers(minSdkVersion:(no version))
i18n.module.public.api.stubs(minSdkVersion:(no version))
@@ -306,6 +309,7 @@
libcutils(minSdkVersion:29)
libcutils_headers(minSdkVersion:29)
libcutils_sockets(minSdkVersion:29)
+libderive_classpath(minSdkVersion:30)
libderive_sdk(minSdkVersion:30)
libdiagnose_usb(minSdkVersion:(no version))
libdl(minSdkVersion:(no version))
@@ -404,6 +408,7 @@
libring(minSdkVersion:29)
libring-core(minSdkVersion:29)
librustc_demangle.rust_sysroot(minSdkVersion:29)
+libruy_static(minSdkVersion:30)
libsdk_proto(minSdkVersion:30)
libsfplugin_ccodec_utils(minSdkVersion:29)
libsonivoxwithoutjet(minSdkVersion:29)
@@ -502,8 +507,10 @@
netd_aidl_interface-V5-java(minSdkVersion:29)
netd_aidl_interface-V6-java(minSdkVersion:29)
netd_event_listener_interface-java(minSdkVersion:29)
+netd_event_listener_interface-lateststable-ndk_platform(minSdkVersion:29)
netd_event_listener_interface-ndk_platform(minSdkVersion:29)
netd_event_listener_interface-unstable-ndk_platform(minSdkVersion:29)
+netd_event_listener_interface-V1-ndk_platform(minSdkVersion:29)
netd_event_listener_interface-V2-ndk_platform(minSdkVersion:29)
netlink-client(minSdkVersion:29)
networkstack-aidl-interfaces-unstable-java(minSdkVersion:29)
@@ -527,7 +534,7 @@
no_op(minSdkVersion:current)
note_memtag_heap_async(minSdkVersion:16)
note_memtag_heap_sync(minSdkVersion:16)
-PermissionController(minSdkVersion:28)
+PermissionController(minSdkVersion:30)
permissioncontroller-statsd(minSdkVersion:current)
philox_random(minSdkVersion:(no version))
philox_random_headers(minSdkVersion:(no version))
diff --git a/apex/apex.go b/apex/apex.go
index efd1736..e5b5c92 100644
--- a/apex/apex.go
+++ b/apex/apex.go
@@ -39,16 +39,20 @@
)
func init() {
- android.RegisterModuleType("apex", BundleFactory)
- android.RegisterModuleType("apex_test", testApexBundleFactory)
- android.RegisterModuleType("apex_vndk", vndkApexBundleFactory)
- android.RegisterModuleType("apex_defaults", defaultsFactory)
- android.RegisterModuleType("prebuilt_apex", PrebuiltFactory)
- android.RegisterModuleType("override_apex", overrideApexFactory)
- android.RegisterModuleType("apex_set", apexSetFactory)
+ registerApexBuildComponents(android.InitRegistrationContext)
+}
- android.PreDepsMutators(RegisterPreDepsMutators)
- android.PostDepsMutators(RegisterPostDepsMutators)
+func registerApexBuildComponents(ctx android.RegistrationContext) {
+ ctx.RegisterModuleType("apex", BundleFactory)
+ ctx.RegisterModuleType("apex_test", testApexBundleFactory)
+ ctx.RegisterModuleType("apex_vndk", vndkApexBundleFactory)
+ ctx.RegisterModuleType("apex_defaults", defaultsFactory)
+ ctx.RegisterModuleType("prebuilt_apex", PrebuiltFactory)
+ ctx.RegisterModuleType("override_apex", overrideApexFactory)
+ ctx.RegisterModuleType("apex_set", apexSetFactory)
+
+ ctx.PreDepsMutators(RegisterPreDepsMutators)
+ ctx.PostDepsMutators(RegisterPostDepsMutators)
}
func RegisterPreDepsMutators(ctx android.RegisterMutatorsContext) {
@@ -970,6 +974,10 @@
// If any of the dep is not available to platform, this module is also considered as being
// not available to platform even if it has "//apex_available:platform"
mctx.VisitDirectDeps(func(child android.Module) {
+ depTag := mctx.OtherModuleDependencyTag(child)
+ if _, ok := depTag.(android.ExcludeFromApexContentsTag); ok {
+ return
+ }
if !am.DepIsInSameApex(mctx, child) {
// if the dependency crosses apex boundary, don't consider it
return
diff --git a/apex/apex_test.go b/apex/apex_test.go
index e3b7f95..dd290d3 100644
--- a/apex/apex_test.go
+++ b/apex/apex_test.go
@@ -67,14 +67,14 @@
t.Fatalf("missing expected error %q (0 errors are returned)", pattern)
}
-func testApex(t *testing.T, bp string, handlers ...testCustomizer) (*android.TestContext, android.Config) {
+func testApex(t *testing.T, bp string, handlers ...testCustomizer) *android.TestContext {
t.Helper()
ctx, config := testApexContext(t, bp, handlers...)
_, errs := ctx.ParseBlueprintsFiles(".")
android.FailIfErrored(t, errs)
_, errs = ctx.PrepareBuildActions(config)
android.FailIfErrored(t, errs)
- return ctx, config
+ return ctx
}
type testCustomizer func(fs map[string][]byte, config android.Config)
@@ -127,6 +127,96 @@
config.TestProductVariables.Unbundled_build = proptools.BoolPtr(true)
}
+var emptyFixtureFactory = android.NewFixtureFactory(&buildDir)
+
+var apexFixtureFactory = android.NewFixtureFactory(
+ &buildDir,
+ // General preparers in alphabetical order as test infrastructure will enforce correct
+ // registration order.
+ android.PrepareForTestWithAndroidBuildComponents,
+ bpf.PrepareForTestWithBpf,
+ cc.PrepareForTestWithCcBuildComponents,
+ java.PrepareForTestWithJavaDefaultModules,
+ prebuilt_etc.PrepareForTestWithPrebuiltEtc,
+ rust.PrepareForTestWithRustDefaultModules,
+ sh.PrepareForTestWithShBuildComponents,
+
+ PrepareForTestWithApexBuildComponents,
+
+ // Additional apex test specific preparers.
+ android.FixtureAddTextFile("system/sepolicy/Android.bp", `
+ filegroup {
+ name: "myapex-file_contexts",
+ srcs: [
+ "apex/myapex-file_contexts",
+ ],
+ }
+ `),
+ android.FixtureMergeMockFs(android.MockFS{
+ "a.java": nil,
+ "PrebuiltAppFoo.apk": nil,
+ "PrebuiltAppFooPriv.apk": nil,
+ "build/make/target/product/security": nil,
+ "apex_manifest.json": nil,
+ "AndroidManifest.xml": nil,
+ "system/sepolicy/apex/myapex-file_contexts": nil,
+ "system/sepolicy/apex/myapex.updatable-file_contexts": nil,
+ "system/sepolicy/apex/myapex2-file_contexts": nil,
+ "system/sepolicy/apex/otherapex-file_contexts": nil,
+ "system/sepolicy/apex/com.android.vndk-file_contexts": nil,
+ "system/sepolicy/apex/com.android.vndk.current-file_contexts": nil,
+ "mylib.cpp": nil,
+ "mytest.cpp": nil,
+ "mytest1.cpp": nil,
+ "mytest2.cpp": nil,
+ "mytest3.cpp": nil,
+ "myprebuilt": nil,
+ "my_include": nil,
+ "foo/bar/MyClass.java": nil,
+ "prebuilt.jar": nil,
+ "prebuilt.so": nil,
+ "vendor/foo/devkeys/test.x509.pem": nil,
+ "vendor/foo/devkeys/test.pk8": nil,
+ "testkey.x509.pem": nil,
+ "testkey.pk8": nil,
+ "testkey.override.x509.pem": nil,
+ "testkey.override.pk8": nil,
+ "vendor/foo/devkeys/testkey.avbpubkey": nil,
+ "vendor/foo/devkeys/testkey.pem": nil,
+ "NOTICE": nil,
+ "custom_notice": nil,
+ "custom_notice_for_static_lib": nil,
+ "testkey2.avbpubkey": nil,
+ "testkey2.pem": nil,
+ "myapex-arm64.apex": nil,
+ "myapex-arm.apex": nil,
+ "myapex.apks": nil,
+ "frameworks/base/api/current.txt": nil,
+ "framework/aidl/a.aidl": nil,
+ "build/make/core/proguard.flags": nil,
+ "build/make/core/proguard_basic_keeps.flags": nil,
+ "dummy.txt": nil,
+ "baz": nil,
+ "bar/baz": nil,
+ "testdata/baz": nil,
+ "AppSet.apks": nil,
+ "foo.rs": nil,
+ "libfoo.jar": nil,
+ "libbar.jar": nil,
+ },
+ ),
+
+ android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
+ variables.DeviceVndkVersion = proptools.StringPtr("current")
+ variables.DefaultAppCertificate = proptools.StringPtr("vendor/foo/devkeys/test")
+ variables.CertificateOverrides = []string{"myapex_keytest:myapex.certificate.override"}
+ variables.Platform_sdk_codename = proptools.StringPtr("Q")
+ variables.Platform_sdk_final = proptools.BoolPtr(false)
+ variables.Platform_version_active_codenames = []string{"Q"}
+ variables.Platform_vndk_version = proptools.StringPtr("VER")
+ }),
+)
+
func testApexContext(_ *testing.T, bp string, handlers ...testCustomizer) (*android.TestContext, android.Config) {
bp = bp + `
filegroup {
@@ -229,14 +319,8 @@
android.RegisterPackageBuildComponents(ctx)
ctx.PreArchMutators(android.RegisterVisibilityRuleChecker)
- ctx.RegisterModuleType("apex", BundleFactory)
- ctx.RegisterModuleType("apex_test", testApexBundleFactory)
- ctx.RegisterModuleType("apex_vndk", vndkApexBundleFactory)
- ctx.RegisterModuleType("apex_key", ApexKeyFactory)
- ctx.RegisterModuleType("apex_defaults", defaultsFactory)
- ctx.RegisterModuleType("prebuilt_apex", PrebuiltFactory)
- ctx.RegisterModuleType("override_apex", overrideApexFactory)
- ctx.RegisterModuleType("apex_set", apexSetFactory)
+ registerApexBuildComponents(ctx)
+ registerApexKeyBuildComponents(ctx)
ctx.PreArchMutators(android.RegisterDefaultsPreArchMutators)
ctx.PreArchMutators(android.RegisterComponentsMutator)
@@ -263,12 +347,8 @@
ctx.RegisterModuleType("platform_compat_config", java.PlatformCompatConfigFactory)
ctx.RegisterModuleType("sh_binary", sh.ShBinaryFactory)
ctx.RegisterModuleType("filegroup", android.FileGroupFactory)
- ctx.RegisterSingletonType("apex_keys_text", apexKeysTextFactory)
ctx.RegisterModuleType("bpf", bpf.BpfFactory)
- ctx.PreDepsMutators(RegisterPreDepsMutators)
- ctx.PostDepsMutators(RegisterPostDepsMutators)
-
ctx.Register()
return ctx, config
@@ -360,7 +440,7 @@
// Minimal test
func TestBasicApex(t *testing.T) {
- ctx, _ := testApex(t, `
+ ctx := testApex(t, `
apex_defaults {
name: "myapex-defaults",
manifest: ":myapex.manifest",
@@ -442,7 +522,7 @@
}
rust_binary {
- name: "foo.rust",
+ name: "foo.rust",
srcs: ["foo.rs"],
rlibs: ["libfoo.rlib.rust"],
dylibs: ["libfoo.dylib.rust"],
@@ -450,14 +530,14 @@
}
rust_library_rlib {
- name: "libfoo.rlib.rust",
+ name: "libfoo.rlib.rust",
srcs: ["foo.rs"],
crate_name: "foo",
apex_available: ["myapex"],
}
rust_library_dylib {
- name: "libfoo.dylib.rust",
+ name: "libfoo.dylib.rust",
srcs: ["foo.rs"],
crate_name: "foo",
apex_available: ["myapex"],
@@ -652,21 +732,19 @@
fullDepsInfo := strings.Split(ctx.ModuleForTests("myapex", "android_common_myapex_image").Output("depsinfo/fulllist.txt").Args["content"], "\\n")
ensureListContains(t, fullDepsInfo, " myjar(minSdkVersion:(no version)) <- myapex")
- ensureListContains(t, fullDepsInfo, " mylib(minSdkVersion:(no version)) <- myapex")
ensureListContains(t, fullDepsInfo, " mylib2(minSdkVersion:(no version)) <- mylib")
ensureListContains(t, fullDepsInfo, " myotherjar(minSdkVersion:(no version)) <- myjar")
ensureListContains(t, fullDepsInfo, " mysharedjar(minSdkVersion:(no version)) (external) <- myjar")
flatDepsInfo := strings.Split(ctx.ModuleForTests("myapex", "android_common_myapex_image").Output("depsinfo/flatlist.txt").Args["content"], "\\n")
ensureListContains(t, flatDepsInfo, "myjar(minSdkVersion:(no version))")
- ensureListContains(t, flatDepsInfo, "mylib(minSdkVersion:(no version))")
ensureListContains(t, flatDepsInfo, "mylib2(minSdkVersion:(no version))")
ensureListContains(t, flatDepsInfo, "myotherjar(minSdkVersion:(no version))")
ensureListContains(t, flatDepsInfo, "mysharedjar(minSdkVersion:(no version)) (external)")
}
func TestDefaults(t *testing.T) {
- ctx, _ := testApex(t, `
+ ctx := testApex(t, `
apex_defaults {
name: "myapex-defaults",
key: "myapex.key",
@@ -741,7 +819,7 @@
}
func TestApexManifest(t *testing.T) {
- ctx, _ := testApex(t, `
+ ctx := testApex(t, `
apex {
name: "myapex",
key: "myapex.key",
@@ -763,7 +841,7 @@
}
func TestBasicZipApex(t *testing.T) {
- ctx, _ := testApex(t, `
+ ctx := testApex(t, `
apex {
name: "myapex",
key: "myapex.key",
@@ -814,7 +892,7 @@
}
func TestApexWithStubs(t *testing.T) {
- ctx, _ := testApex(t, `
+ ctx := testApex(t, `
apex {
name: "myapex",
key: "myapex.key",
@@ -909,7 +987,7 @@
func TestApexWithStubsWithMinSdkVersion(t *testing.T) {
t.Parallel()
- ctx, _ := testApex(t, `
+ ctx := testApex(t, `
apex {
name: "myapex",
key: "myapex.key",
@@ -1016,7 +1094,7 @@
// |
// <platform> |
// libplatform ----------------'
- ctx, _ := testApex(t, `
+ ctx := testApex(t, `
apex {
name: "myapex",
key: "myapex.key",
@@ -1081,7 +1159,7 @@
}
func TestApexWithExplicitStubsDependency(t *testing.T) {
- ctx, _ := testApex(t, `
+ ctx := testApex(t, `
apex {
name: "myapex2",
key: "myapex2.key",
@@ -1158,13 +1236,9 @@
ensureNotContains(t, libFooStubsLdFlags, "libbar.so")
fullDepsInfo := strings.Split(ctx.ModuleForTests("myapex2", "android_common_myapex2_image").Output("depsinfo/fulllist.txt").Args["content"], "\\n")
- ensureListContains(t, fullDepsInfo, " mylib(minSdkVersion:(no version)) <- myapex2")
- ensureListContains(t, fullDepsInfo, " libbaz(minSdkVersion:(no version)) <- mylib")
ensureListContains(t, fullDepsInfo, " libfoo(minSdkVersion:(no version)) (external) <- mylib")
flatDepsInfo := strings.Split(ctx.ModuleForTests("myapex2", "android_common_myapex2_image").Output("depsinfo/flatlist.txt").Args["content"], "\\n")
- ensureListContains(t, flatDepsInfo, "mylib(minSdkVersion:(no version))")
- ensureListContains(t, flatDepsInfo, "libbaz(minSdkVersion:(no version))")
ensureListContains(t, flatDepsInfo, "libfoo(minSdkVersion:(no version)) (external)")
}
@@ -1177,7 +1251,7 @@
|
`------> libbar
*/
- ctx, _ := testApex(t, `
+ ctx := testApex(t, `
apex {
name: "myapex",
key: "myapex.key",
@@ -1238,9 +1312,10 @@
}
-func TestRuntimeApexShouldInstallHwasanIfLibcDependsOnIt(t *testing.T) {
- ctx, _ := testApex(t, "", func(fs map[string][]byte, config android.Config) {
- bp := `
+var prepareForTestOfRuntimeApexWithHwasan = android.GroupFixturePreparers(
+ cc.PrepareForTestWithCcBuildComponents,
+ PrepareForTestWithApexBuildComponents,
+ android.FixtureAddTextFile("bionic/apex/Android.bp", `
apex {
name: "com.android.runtime",
key: "com.android.runtime.key",
@@ -1253,7 +1328,12 @@
public_key: "testkey.avbpubkey",
private_key: "testkey.pem",
}
+ `),
+ android.FixtureAddFile("system/sepolicy/apex/com.android.runtime-file_contexts", nil),
+)
+func TestRuntimeApexShouldInstallHwasanIfLibcDependsOnIt(t *testing.T) {
+ result := emptyFixtureFactory.Extend(prepareForTestOfRuntimeApexWithHwasan).RunTestWithBp(t, `
cc_library {
name: "libc",
no_libcrt: true,
@@ -1280,12 +1360,8 @@
sanitize: {
never: true,
},
- }
- `
- // override bp to use hard-coded names: com.android.runtime and libc
- fs["Android.bp"] = []byte(bp)
- fs["system/sepolicy/apex/com.android.runtime-file_contexts"] = nil
- })
+ } `)
+ ctx := result.TestContext
ensureExactContents(t, ctx, "com.android.runtime", "android_common_hwasan_com.android.runtime_image", []string{
"lib64/bionic/libc.so",
@@ -1303,21 +1379,12 @@
}
func TestRuntimeApexShouldInstallHwasanIfHwaddressSanitized(t *testing.T) {
- ctx, _ := testApex(t, "", func(fs map[string][]byte, config android.Config) {
- bp := `
- apex {
- name: "com.android.runtime",
- key: "com.android.runtime.key",
- native_shared_libs: ["libc"],
- updatable: false,
- }
-
- apex_key {
- name: "com.android.runtime.key",
- public_key: "testkey.avbpubkey",
- private_key: "testkey.pem",
- }
-
+ result := emptyFixtureFactory.Extend(
+ prepareForTestOfRuntimeApexWithHwasan,
+ android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
+ variables.SanitizeDevice = []string{"hwaddress"}
+ }),
+ ).RunTestWithBp(t, `
cc_library {
name: "libc",
no_libcrt: true,
@@ -1341,13 +1408,8 @@
never: true,
},
}
- `
- // override bp to use hard-coded names: com.android.runtime and libc
- fs["Android.bp"] = []byte(bp)
- fs["system/sepolicy/apex/com.android.runtime-file_contexts"] = nil
-
- config.TestProductVariables.SanitizeDevice = []string{"hwaddress"}
- })
+ `)
+ ctx := result.TestContext
ensureExactContents(t, ctx, "com.android.runtime", "android_common_hwasan_com.android.runtime_image", []string{
"lib64/bionic/libc.so",
@@ -1389,7 +1451,7 @@
}
for _, tc := range testcases {
t.Run(tc.name, func(t *testing.T) {
- ctx, _ := testApex(t, `
+ ctx := testApex(t, `
apex {
name: "myapex",
key: "myapex.key",
@@ -1456,7 +1518,7 @@
}
func TestApexWithSystemLibsStubs(t *testing.T) {
- ctx, _ := testApex(t, `
+ ctx := testApex(t, `
apex {
name: "myapex",
key: "myapex.key",
@@ -1552,7 +1614,7 @@
// 1) myapex -> libx -> liba -> libz : this should be #30 link
// 2) otherapex -> liby -> liba -> libz : this should be #30 link
// 3) (platform) -> liba -> libz : this should be non-stub link
- ctx, _ := testApex(t, `
+ ctx := testApex(t, `
apex {
name: "myapex",
key: "myapex.key",
@@ -1634,7 +1696,7 @@
}
func TestApexMinSdkVersion_SupportsCodeNames(t *testing.T) {
- ctx, _ := testApex(t, `
+ ctx := testApex(t, `
apex {
name: "myapex",
key: "myapex.key",
@@ -1683,7 +1745,7 @@
}
func TestApexMinSdkVersion_DefaultsToLatest(t *testing.T) {
- ctx, _ := testApex(t, `
+ ctx := testApex(t, `
apex {
name: "myapex",
key: "myapex.key",
@@ -1729,7 +1791,7 @@
}
func TestPlatformUsesLatestStubsFromApexes(t *testing.T) {
- ctx, _ := testApex(t, `
+ ctx := testApex(t, `
apex {
name: "myapex",
key: "myapex.key",
@@ -1777,7 +1839,7 @@
}
func TestQApexesUseLatestStubsInBundledBuildsAndHWASAN(t *testing.T) {
- ctx, _ := testApex(t, `
+ ctx := testApex(t, `
apex {
name: "myapex",
key: "myapex.key",
@@ -1816,7 +1878,7 @@
}
func TestQTargetApexUsesStaticUnwinder(t *testing.T) {
- ctx, _ := testApex(t, `
+ ctx := testApex(t, `
apex {
name: "myapex",
key: "myapex.key",
@@ -1971,7 +2033,7 @@
java_library {
name: "myjar",
srcs: ["foo/bar/MyClass.java"],
- sdk_version: "core_platform",
+ sdk_version: "test_current",
apex_available: ["myapex"],
}
`,
@@ -2018,13 +2080,16 @@
java_library {
name: "myjar",
srcs: ["foo/bar/MyClass.java"],
- sdk_version: "core_platform",
+ sdk_version: "test_current",
apex_available: ["myapex"],
}
`,
},
{
- name: "Updatable apex with non-stable transitive dep",
+ name: "Updatable apex with non-stable transitive dep",
+ // This is not actually detecting that the transitive dependency is unstable, rather it is
+ // detecting that the transitive dependency is building against a wider API surface than the
+ // module that depends on it is using.
expectedError: "compiles against Android API, but dependency \"transitive-jar\" is compiling against private API.",
bp: `
apex {
@@ -2143,7 +2208,7 @@
}
func TestApexMinSdkVersion_OkayEvenWhenDepIsNewer_IfItSatisfiesApexMinSdkVersion(t *testing.T) {
- ctx, _ := testApex(t, `
+ ctx := testApex(t, `
apex {
name: "myapex",
key: "myapex.key",
@@ -2230,7 +2295,7 @@
config.TestProductVariables.Platform_sdk_codename = proptools.StringPtr("S")
config.TestProductVariables.Platform_version_active_codenames = []string{"S", "T"}
}
- ctx, _ := testApex(t, `
+ ctx := testApex(t, `
apex {
name: "myapex",
key: "myapex.key",
@@ -2264,7 +2329,7 @@
}
func TestFilesInSubDir(t *testing.T) {
- ctx, _ := testApex(t, `
+ ctx := testApex(t, `
apex {
name: "myapex",
key: "myapex.key",
@@ -2327,7 +2392,7 @@
}
func TestFilesInSubDirWhenNativeBridgeEnabled(t *testing.T) {
- ctx, _ := testApex(t, `
+ ctx := testApex(t, `
apex {
name: "myapex",
key: "myapex.key",
@@ -2386,7 +2451,7 @@
}
func TestUseVendor(t *testing.T) {
- ctx, _ := testApex(t, `
+ ctx := testApex(t, `
apex {
name: "myapex",
key: "myapex.key",
@@ -2499,7 +2564,7 @@
}
func TestVendorApex(t *testing.T) {
- ctx, _ := testApex(t, `
+ ctx := testApex(t, `
apex {
name: "myapex",
key: "myapex.key",
@@ -2546,7 +2611,7 @@
}
func TestVendorApex_use_vndk_as_stable(t *testing.T) {
- ctx, _ := testApex(t, `
+ ctx := testApex(t, `
apex {
name: "myapex",
key: "myapex.key",
@@ -2610,7 +2675,7 @@
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
- ctx, _ := testApex(t, `
+ ctx := testApex(t, `
apex {
name: "myapex",
key: "myapex.key",
@@ -2638,7 +2703,7 @@
}
func TestAndroidMk_UseVendorRequired(t *testing.T) {
- ctx, _ := testApex(t, `
+ ctx := testApex(t, `
apex {
name: "myapex",
key: "myapex.key",
@@ -2673,7 +2738,7 @@
}
func TestAndroidMk_VendorApexRequired(t *testing.T) {
- ctx, _ := testApex(t, `
+ ctx := testApex(t, `
apex {
name: "myapex",
key: "myapex.key",
@@ -2705,7 +2770,7 @@
}
func TestAndroidMkWritesCommonProperties(t *testing.T) {
- ctx, _ := testApex(t, `
+ ctx := testApex(t, `
apex {
name: "myapex",
key: "myapex.key",
@@ -2735,7 +2800,7 @@
}
func TestStaticLinking(t *testing.T) {
- ctx, _ := testApex(t, `
+ ctx := testApex(t, `
apex {
name: "myapex",
key: "myapex.key",
@@ -2780,7 +2845,7 @@
}
func TestKeys(t *testing.T) {
- ctx, _ := testApex(t, `
+ ctx := testApex(t, `
apex {
name: "myapex_keytest",
key: "myapex.key",
@@ -2838,7 +2903,7 @@
func TestCertificate(t *testing.T) {
t.Run("if unspecified, it defaults to DefaultAppCertificate", func(t *testing.T) {
- ctx, _ := testApex(t, `
+ ctx := testApex(t, `
apex {
name: "myapex",
key: "myapex.key",
@@ -2856,7 +2921,7 @@
}
})
t.Run("override when unspecified", func(t *testing.T) {
- ctx, _ := testApex(t, `
+ ctx := testApex(t, `
apex {
name: "myapex_keytest",
key: "myapex.key",
@@ -2879,7 +2944,7 @@
}
})
t.Run("if specified as :module, it respects the prop", func(t *testing.T) {
- ctx, _ := testApex(t, `
+ ctx := testApex(t, `
apex {
name: "myapex",
key: "myapex.key",
@@ -2902,7 +2967,7 @@
}
})
t.Run("override when specifiec as <:module>", func(t *testing.T) {
- ctx, _ := testApex(t, `
+ ctx := testApex(t, `
apex {
name: "myapex_keytest",
key: "myapex.key",
@@ -2926,7 +2991,7 @@
}
})
t.Run("if specified as name, finds it from DefaultDevKeyDir", func(t *testing.T) {
- ctx, _ := testApex(t, `
+ ctx := testApex(t, `
apex {
name: "myapex",
key: "myapex.key",
@@ -2945,7 +3010,7 @@
}
})
t.Run("override when specified as <name>", func(t *testing.T) {
- ctx, _ := testApex(t, `
+ ctx := testApex(t, `
apex {
name: "myapex_keytest",
key: "myapex.key",
@@ -2971,7 +3036,7 @@
}
func TestMacro(t *testing.T) {
- ctx, _ := testApex(t, `
+ ctx := testApex(t, `
apex {
name: "myapex",
key: "myapex.key",
@@ -3099,7 +3164,7 @@
}
func TestHeaderLibsDependency(t *testing.T) {
- ctx, _ := testApex(t, `
+ ctx := testApex(t, `
apex {
name: "myapex",
key: "myapex.key",
@@ -3243,7 +3308,7 @@
}
func TestVndkApexCurrent(t *testing.T) {
- ctx, _ := testApex(t, `
+ ctx := testApex(t, `
apex_vndk {
name: "com.android.vndk.current",
key: "com.android.vndk.current.key",
@@ -3300,7 +3365,7 @@
}
func TestVndkApexWithPrebuilt(t *testing.T) {
- ctx, _ := testApex(t, `
+ ctx := testApex(t, `
apex_vndk {
name: "com.android.vndk.current",
key: "com.android.vndk.current.key",
@@ -3384,7 +3449,7 @@
}
func TestVndkApexVersion(t *testing.T) {
- ctx, _ := testApex(t, `
+ ctx := testApex(t, `
apex_vndk {
name: "com.android.vndk.v27",
key: "myapex.key",
@@ -3453,7 +3518,7 @@
}
func TestVndkApexNameRule(t *testing.T) {
- ctx, _ := testApex(t, `
+ ctx := testApex(t, `
apex_vndk {
name: "com.android.vndk.current",
key: "myapex.key",
@@ -3486,7 +3551,7 @@
}
func TestVndkApexSkipsNativeBridgeSupportedModules(t *testing.T) {
- ctx, _ := testApex(t, `
+ ctx := testApex(t, `
apex_vndk {
name: "com.android.vndk.current",
key: "com.android.vndk.current.key",
@@ -3558,7 +3623,7 @@
}
func TestVndkApexWithBinder32(t *testing.T) {
- ctx, _ := testApex(t, `
+ ctx := testApex(t, `
apex_vndk {
name: "com.android.vndk.v27",
key: "myapex.key",
@@ -3627,7 +3692,7 @@
}
func TestVndkApexShouldNotProvideNativeLibs(t *testing.T) {
- ctx, _ := testApex(t, `
+ ctx := testApex(t, `
apex_vndk {
name: "com.android.vndk.current",
key: "com.android.vndk.current.key",
@@ -3663,7 +3728,7 @@
}
func TestDependenciesInApexManifest(t *testing.T) {
- ctx, _ := testApex(t, `
+ ctx := testApex(t, `
apex {
name: "myapex_nodep",
key: "myapex.key",
@@ -3771,7 +3836,7 @@
}
func TestApexName(t *testing.T) {
- ctx, _ := testApex(t, `
+ ctx := testApex(t, `
apex {
name: "myapex",
key: "myapex.key",
@@ -3816,7 +3881,7 @@
}
func TestNonTestApex(t *testing.T) {
- ctx, _ := testApex(t, `
+ ctx := testApex(t, `
apex {
name: "myapex",
key: "myapex.key",
@@ -3869,7 +3934,7 @@
}
func TestTestApex(t *testing.T) {
- ctx, _ := testApex(t, `
+ ctx := testApex(t, `
apex_test {
name: "myapex",
key: "myapex.key",
@@ -3918,7 +3983,7 @@
}
func TestApexWithTarget(t *testing.T) {
- ctx, _ := testApex(t, `
+ ctx := testApex(t, `
apex {
name: "myapex",
key: "myapex.key",
@@ -4009,7 +4074,7 @@
}
func TestApexWithArch(t *testing.T) {
- ctx, _ := testApex(t, `
+ ctx := testApex(t, `
apex {
name: "myapex",
key: "myapex.key",
@@ -4068,7 +4133,7 @@
}
func TestApexWithShBinary(t *testing.T) {
- ctx, _ := testApex(t, `
+ ctx := testApex(t, `
apex {
name: "myapex",
key: "myapex.key",
@@ -4109,7 +4174,7 @@
}
for _, tc := range testcases {
t.Run(tc.propName+":"+tc.parition, func(t *testing.T) {
- ctx, _ := testApex(t, `
+ ctx := testApex(t, `
apex {
name: "myapex",
key: "myapex.key",
@@ -4142,7 +4207,7 @@
}
func TestFileContexts_FindInDefaultLocationIfNotSet(t *testing.T) {
- ctx, _ := testApex(t, `
+ ctx := testApex(t, `
apex {
name: "myapex",
key: "myapex.key",
@@ -4196,7 +4261,7 @@
}
`)
- ctx, _ := testApex(t, `
+ ctx := testApex(t, `
apex {
name: "myapex",
key: "myapex.key",
@@ -4219,7 +4284,7 @@
}
func TestFileContexts_SetViaFileGroup(t *testing.T) {
- ctx, _ := testApex(t, `
+ ctx := testApex(t, `
apex {
name: "myapex",
key: "myapex.key",
@@ -4247,7 +4312,7 @@
}
func TestApexKeyFromOtherModule(t *testing.T) {
- ctx, _ := testApex(t, `
+ ctx := testApex(t, `
apex_key {
name: "myapex.key",
public_key: ":my.avbpubkey",
@@ -4280,7 +4345,7 @@
}
func TestPrebuilt(t *testing.T) {
- ctx, _ := testApex(t, `
+ ctx := testApex(t, `
prebuilt_apex {
name: "myapex",
arch: {
@@ -4303,7 +4368,7 @@
}
func TestPrebuiltFilenameOverride(t *testing.T) {
- ctx, _ := testApex(t, `
+ ctx := testApex(t, `
prebuilt_apex {
name: "myapex",
src: "myapex-arm.apex",
@@ -4320,7 +4385,7 @@
}
func TestPrebuiltOverrides(t *testing.T) {
- ctx, _ := testApex(t, `
+ ctx := testApex(t, `
prebuilt_apex {
name: "myapex.prebuilt",
src: "myapex-arm.apex",
@@ -4831,7 +4896,7 @@
}
func TestApexWithTests(t *testing.T) {
- ctx, _ := testApex(t, `
+ ctx := testApex(t, `
apex_test {
name: "myapex",
key: "myapex.key",
@@ -4943,7 +5008,7 @@
}
func TestInstallExtraFlattenedApexes(t *testing.T) {
- ctx, _ := testApex(t, `
+ ctx := testApex(t, `
apex {
name: "myapex",
key: "myapex.key",
@@ -5013,7 +5078,7 @@
}
func TestApexWithJavaImport(t *testing.T) {
- ctx, _ := testApex(t, `
+ ctx := testApex(t, `
apex {
name: "myapex",
key: "myapex.key",
@@ -5042,7 +5107,7 @@
}
func TestApexWithApps(t *testing.T) {
- ctx, _ := testApex(t, `
+ ctx := testApex(t, `
apex {
name: "myapex",
key: "myapex.key",
@@ -5121,7 +5186,7 @@
}
func TestApexWithAppImports(t *testing.T) {
- ctx, _ := testApex(t, `
+ ctx := testApex(t, `
apex {
name: "myapex",
key: "myapex.key",
@@ -5170,7 +5235,7 @@
}
func TestApexWithAppImportsPrefer(t *testing.T) {
- ctx, _ := testApex(t, `
+ ctx := testApex(t, `
apex {
name: "myapex",
key: "myapex.key",
@@ -5207,13 +5272,12 @@
}))
ensureExactContents(t, ctx, "myapex", "android_common_myapex_image", []string{
- // TODO(b/181974714) - this is wrong it should be "app/AppFoo/AppFooPrebuilt.apk"
- "app/AppFoo/AppFoo.apk",
+ "app/AppFoo/AppFooPrebuilt.apk",
})
}
func TestApexWithTestHelperApp(t *testing.T) {
- ctx, _ := testApex(t, `
+ ctx := testApex(t, `
apex {
name: "myapex",
key: "myapex.key",
@@ -5424,7 +5488,7 @@
}
func TestApexAvailable_CheckForPlatform(t *testing.T) {
- ctx, _ := testApex(t, `
+ ctx := testApex(t, `
apex {
name: "myapex",
key: "myapex.key",
@@ -5487,7 +5551,7 @@
}
func TestApexAvailable_CreatedForApex(t *testing.T) {
- ctx, _ := testApex(t, `
+ ctx := testApex(t, `
apex {
name: "myapex",
key: "myapex.key",
@@ -5522,7 +5586,7 @@
}
func TestOverrideApex(t *testing.T) {
- ctx, _ := testApex(t, `
+ ctx := testApex(t, `
apex {
name: "myapex",
key: "myapex.key",
@@ -5606,7 +5670,7 @@
}
func TestLegacyAndroid10Support(t *testing.T) {
- ctx, _ := testApex(t, `
+ ctx := testApex(t, `
apex {
name: "myapex",
key: "myapex.key",
@@ -5666,7 +5730,7 @@
}
func TestJavaSDKLibrary(t *testing.T) {
- ctx, _ := testApex(t, `
+ ctx := testApex(t, `
apex {
name: "myapex",
key: "myapex.key",
@@ -5704,7 +5768,7 @@
}
func TestJavaSDKLibrary_WithinApex(t *testing.T) {
- ctx, _ := testApex(t, `
+ ctx := testApex(t, `
apex {
name: "myapex",
key: "myapex.key",
@@ -5757,7 +5821,7 @@
}
func TestJavaSDKLibrary_CrossBoundary(t *testing.T) {
- ctx, _ := testApex(t, `
+ ctx := testApex(t, `
apex {
name: "myapex",
key: "myapex.key",
@@ -5808,7 +5872,7 @@
}
func TestJavaSDKLibrary_ImportPreferred(t *testing.T) {
- ctx, _ := testApex(t, `
+ ctx := testApex(t, `
prebuilt_apis {
name: "sdk",
api_dirs: ["100"],
@@ -5925,7 +5989,7 @@
}
func TestCompatConfig(t *testing.T) {
- ctx, _ := testApex(t, `
+ ctx := testApex(t, `
apex {
name: "myapex",
key: "myapex.key",
@@ -5986,7 +6050,7 @@
}
func TestCarryRequiredModuleNames(t *testing.T) {
- ctx, _ := testApex(t, `
+ ctx := testApex(t, `
apex {
name: "myapex",
key: "myapex.key",
@@ -6130,7 +6194,7 @@
// For unbundled build, symlink shouldn't exist regardless of whether an APEX
// is updatable or not
- ctx, _ := testApex(t, bp, withUnbundledBuild)
+ ctx := testApex(t, bp, withUnbundledBuild)
files := getFiles(t, ctx, "myapex", "android_common_myapex_image")
ensureRealfileExists(t, files, "javalib/myjar.jar")
ensureRealfileExists(t, files, "lib64/mylib.so")
@@ -6142,7 +6206,7 @@
ensureRealfileExists(t, files, "lib64/myotherlib.so")
// For bundled build, symlink to the system for the non-updatable APEXes only
- ctx, _ = testApex(t, bp)
+ ctx = testApex(t, bp)
files = getFiles(t, ctx, "myapex", "android_common_myapex_image")
ensureRealfileExists(t, files, "javalib/myjar.jar")
ensureRealfileExists(t, files, "lib64/mylib.so")
@@ -6155,7 +6219,7 @@
}
func TestSymlinksFromApexToSystemRequiredModuleNames(t *testing.T) {
- ctx, _ := testApex(t, `
+ ctx := testApex(t, `
apex {
name: "myapex",
key: "myapex.key",
@@ -6207,7 +6271,7 @@
}
func TestApexWithJniLibs(t *testing.T) {
- ctx, _ := testApex(t, `
+ ctx := testApex(t, `
apex {
name: "myapex",
key: "myapex.key",
@@ -6249,7 +6313,7 @@
}
func TestApexMutatorsDontRunIfDisabled(t *testing.T) {
- ctx, _ := testApex(t, `
+ ctx := testApex(t, `
apex {
name: "myapex",
key: "myapex.key",
@@ -6271,7 +6335,7 @@
}
func TestAppBundle(t *testing.T) {
- ctx, _ := testApex(t, `
+ ctx := testApex(t, `
apex {
name: "myapex",
key: "myapex.key",
@@ -6302,7 +6366,7 @@
}
func TestAppSetBundle(t *testing.T) {
- ctx, _ := testApex(t, `
+ ctx := testApex(t, `
apex {
name: "myapex",
key: "myapex.key",
@@ -6335,7 +6399,7 @@
}
func TestAppSetBundlePrebuilt(t *testing.T) {
- ctx, _ := testApex(t, "", func(fs map[string][]byte, config android.Config) {
+ ctx := testApex(t, "", func(fs map[string][]byte, config android.Config) {
bp := `
apex_set {
name: "myapex",
@@ -6820,7 +6884,7 @@
}
func TestTestFor(t *testing.T) {
- ctx, _ := testApex(t, `
+ ctx := testApex(t, `
apex {
name: "myapex",
key: "myapex.key",
@@ -6906,7 +6970,7 @@
}
func TestApexSet(t *testing.T) {
- ctx, _ := testApex(t, `
+ ctx := testApex(t, `
apex_set {
name: "myapex",
set: "myapex.apks",
@@ -6982,7 +7046,7 @@
}
func TestApexKeysTxt(t *testing.T) {
- ctx, _ := testApex(t, `
+ ctx := testApex(t, `
apex {
name: "myapex",
key: "myapex.key",
@@ -7023,7 +7087,7 @@
}
func TestAllowedFiles(t *testing.T) {
- ctx, _ := testApex(t, `
+ ctx := testApex(t, `
apex {
name: "myapex",
key: "myapex.key",
@@ -7079,7 +7143,7 @@
}
func TestNonPreferredPrebuiltDependency(t *testing.T) {
- _, _ = testApex(t, `
+ testApex(t, `
apex {
name: "myapex",
key: "myapex.key",
@@ -7115,7 +7179,7 @@
}
func TestCompressedApex(t *testing.T) {
- ctx, _ := testApex(t, `
+ ctx := testApex(t, `
apex {
name: "myapex",
key: "myapex.key",
@@ -7150,7 +7214,7 @@
}
func TestPreferredPrebuiltSharedLibDep(t *testing.T) {
- ctx, _ := testApex(t, `
+ ctx := testApex(t, `
apex {
name: "myapex",
key: "myapex.key",
@@ -7202,7 +7266,7 @@
}
func TestExcludeDependency(t *testing.T) {
- ctx, _ := testApex(t, `
+ ctx := testApex(t, `
apex {
name: "myapex",
key: "myapex.key",
@@ -7346,7 +7410,7 @@
t.Run(test.name, func(t *testing.T) {
for _, otherApexEnabled := range test.otherApexEnabled {
t.Run("otherapex_enabled_"+otherApexEnabled, func(t *testing.T) {
- ctx, _ := testApex(t, fmt.Sprintf(bpBase, otherApexEnabled)+test.stublibBp)
+ ctx := testApex(t, fmt.Sprintf(bpBase, otherApexEnabled)+test.stublibBp)
type modAndMkEntries struct {
mod *cc.Module
diff --git a/apex/boot_image_test.go b/apex/boot_image_test.go
index ff779e1..2e6ed82 100644
--- a/apex/boot_image_test.go
+++ b/apex/boot_image_test.go
@@ -28,7 +28,7 @@
// modules from the ART apex.
func TestBootImages(t *testing.T) {
- ctx, _ := testApex(t, `
+ ctx := testApex(t, `
java_sdk_library {
name: "foo",
srcs: ["b.java"],
@@ -181,7 +181,7 @@
}
func TestBootImageInApex(t *testing.T) {
- ctx, _ := testApex(t, `
+ ctx := testApex(t, `
apex {
name: "myapex",
key: "myapex.key",
diff --git a/apex/builder.go b/apex/builder.go
index 2663a67..da800d4 100644
--- a/apex/builder.go
+++ b/apex/builder.go
@@ -926,9 +926,15 @@
return !externalDep
}
+ // Skip dependencies that are only available to APEXes; they are developed with updatability
+ // in mind and don't need manual approval.
+ if to.(android.ApexModule).NotAvailableForPlatform() {
+ return !externalDep
+ }
+
depTag := ctx.OtherModuleDependencyTag(to)
+ // Check to see if dependency been marked to skip the dependency check
if skipDepCheck, ok := depTag.(android.SkipApexAllowedDependenciesCheck); ok && skipDepCheck.SkipApexAllowedDependenciesCheck() {
- // Check to see if dependency been marked to skip the dependency check
return !externalDep
}
diff --git a/apex/key.go b/apex/key.go
index 752888d..8b33b59 100644
--- a/apex/key.go
+++ b/apex/key.go
@@ -27,8 +27,12 @@
var String = proptools.String
func init() {
- android.RegisterModuleType("apex_key", ApexKeyFactory)
- android.RegisterSingletonType("apex_keys_text", apexKeysTextFactory)
+ registerApexKeyBuildComponents(android.InitRegistrationContext)
+}
+
+func registerApexKeyBuildComponents(ctx android.RegistrationContext) {
+ ctx.RegisterModuleType("apex_key", ApexKeyFactory)
+ ctx.RegisterSingletonType("apex_keys_text", apexKeysTextFactory)
}
type apexKey struct {
diff --git a/apex/testing.go b/apex/testing.go
new file mode 100644
index 0000000..e662cad
--- /dev/null
+++ b/apex/testing.go
@@ -0,0 +1,22 @@
+// Copyright 2021 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 apex
+
+import "android/soong/android"
+
+var PrepareForTestWithApexBuildComponents = android.GroupFixturePreparers(
+ android.FixtureRegisterWithContext(registerApexBuildComponents),
+ android.FixtureRegisterWithContext(registerApexKeyBuildComponents),
+)
diff --git a/apex/vndk_test.go b/apex/vndk_test.go
index 5e9a11f..34b9408 100644
--- a/apex/vndk_test.go
+++ b/apex/vndk_test.go
@@ -9,7 +9,7 @@
)
func TestVndkApexForVndkLite(t *testing.T) {
- ctx, _ := testApex(t, `
+ ctx := testApex(t, `
apex_vndk {
name: "com.android.vndk.current",
key: "com.android.vndk.current.key",
@@ -100,7 +100,7 @@
}
t.Run("VNDK lib doesn't have an apex variant", func(t *testing.T) {
- ctx, _ := testApex(t, bp)
+ ctx := testApex(t, bp)
// libfoo doesn't have apex variants
for _, variant := range ctx.ModuleVariantsForTests("libfoo") {
@@ -113,7 +113,7 @@
})
t.Run("VNDK APEX gathers only vendor variants even if product variants are available", func(t *testing.T) {
- ctx, _ := testApex(t, bp, func(fs map[string][]byte, config android.Config) {
+ ctx := testApex(t, bp, func(fs map[string][]byte, config android.Config) {
// Now product variant is available
config.TestProductVariables.ProductVndkVersion = proptools.StringPtr("current")
})
@@ -123,7 +123,7 @@
})
t.Run("VNDK APEX supports coverage variants", func(t *testing.T) {
- ctx, _ := testApex(t, bp, func(fs map[string][]byte, config android.Config) {
+ ctx := testApex(t, bp, func(fs map[string][]byte, config android.Config) {
config.TestProductVariables.GcovCoverage = proptools.BoolPtr(true)
config.TestProductVariables.Native_coverage = proptools.BoolPtr(true)
})
diff --git a/bazel/Android.bp b/bazel/Android.bp
index 117fd46..b7c185a 100644
--- a/bazel/Android.bp
+++ b/bazel/Android.bp
@@ -12,6 +12,7 @@
],
testSrcs: [
"aquery_test.go",
+ "properties_test.go",
],
pluginFor: [
"soong_build",
diff --git a/bazel/properties.go b/bazel/properties.go
index a5ffa55..cb47758 100644
--- a/bazel/properties.go
+++ b/bazel/properties.go
@@ -14,7 +14,10 @@
package bazel
-import "fmt"
+import (
+ "fmt"
+ "sort"
+)
type bazelModuleProperties struct {
// The label of the Bazel target replacing this Soong module.
@@ -66,6 +69,28 @@
}
}
+func UniqueBazelLabels(originalLabels []Label) []Label {
+ uniqueLabelsSet := make(map[Label]bool)
+ for _, l := range originalLabels {
+ uniqueLabelsSet[l] = true
+ }
+ var uniqueLabels []Label
+ for l, _ := range uniqueLabelsSet {
+ uniqueLabels = append(uniqueLabels, l)
+ }
+ sort.SliceStable(uniqueLabels, func(i, j int) bool {
+ return uniqueLabels[i].Label < uniqueLabels[j].Label
+ })
+ return uniqueLabels
+}
+
+func UniqueBazelLabelList(originalLabelList LabelList) LabelList {
+ var uniqueLabelList LabelList
+ uniqueLabelList.Includes = UniqueBazelLabels(originalLabelList.Includes)
+ uniqueLabelList.Excludes = UniqueBazelLabels(originalLabelList.Excludes)
+ return uniqueLabelList
+}
+
// StringListAttribute corresponds to the string_list Bazel attribute type with
// support for additional metadata, like configurations.
type StringListAttribute struct {
diff --git a/bazel/properties_test.go b/bazel/properties_test.go
new file mode 100644
index 0000000..0fcb904
--- /dev/null
+++ b/bazel/properties_test.go
@@ -0,0 +1,89 @@
+// Copyright 2021 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 bazel
+
+import (
+ "reflect"
+ "testing"
+)
+
+func TestUniqueBazelLabels(t *testing.T) {
+ testCases := []struct {
+ originalLabels []Label
+ expectedUniqueLabels []Label
+ }{
+ {
+ originalLabels: []Label{
+ {Label: "a"},
+ {Label: "b"},
+ {Label: "a"},
+ {Label: "c"},
+ },
+ expectedUniqueLabels: []Label{
+ {Label: "a"},
+ {Label: "b"},
+ {Label: "c"},
+ },
+ },
+ }
+ for _, tc := range testCases {
+ actualUniqueLabels := UniqueBazelLabels(tc.originalLabels)
+ if !reflect.DeepEqual(tc.expectedUniqueLabels, actualUniqueLabels) {
+ t.Fatalf("Expected %v, got %v", tc.expectedUniqueLabels, actualUniqueLabels)
+ }
+ }
+}
+
+func TestUniqueBazelLabelList(t *testing.T) {
+ testCases := []struct {
+ originalLabelList LabelList
+ expectedUniqueLabelList LabelList
+ }{
+ {
+ originalLabelList: LabelList{
+ Includes: []Label{
+ {Label: "a"},
+ {Label: "b"},
+ {Label: "a"},
+ {Label: "c"},
+ },
+ Excludes: []Label{
+ {Label: "x"},
+ {Label: "x"},
+ {Label: "y"},
+ {Label: "z"},
+ },
+ },
+ expectedUniqueLabelList: LabelList{
+ Includes: []Label{
+ {Label: "a"},
+ {Label: "b"},
+ {Label: "c"},
+ },
+ Excludes: []Label{
+ {Label: "x"},
+ {Label: "y"},
+ {Label: "z"},
+ },
+ },
+ },
+ }
+ for _, tc := range testCases {
+ actualUniqueLabelList := UniqueBazelLabelList(tc.originalLabelList)
+ if !reflect.DeepEqual(tc.expectedUniqueLabelList, actualUniqueLabelList) {
+ t.Fatalf("Expected %v, got %v", tc.expectedUniqueLabelList, actualUniqueLabelList)
+ }
+ }
+}
diff --git a/bp2build/Android.bp b/bp2build/Android.bp
index 8deb5a2..99d706c 100644
--- a/bp2build/Android.bp
+++ b/bp2build/Android.bp
@@ -19,6 +19,7 @@
"soong-bazel",
"soong-cc",
"soong-genrule",
+ "soong-python",
"soong-sh",
],
testSrcs: [
@@ -27,6 +28,7 @@
"cc_library_headers_conversion_test.go",
"cc_object_conversion_test.go",
"conversion_test.go",
+ "python_binary_conversion_test.go",
"sh_conversion_test.go",
"testing.go",
],
diff --git a/bp2build/python_binary_conversion_test.go b/bp2build/python_binary_conversion_test.go
new file mode 100644
index 0000000..7600e36
--- /dev/null
+++ b/bp2build/python_binary_conversion_test.go
@@ -0,0 +1,170 @@
+package bp2build
+
+import (
+ "android/soong/android"
+ "android/soong/python"
+ "fmt"
+ "strings"
+ "testing"
+)
+
+func TestPythonBinaryHost(t *testing.T) {
+ testCases := []struct {
+ description string
+ moduleTypeUnderTest string
+ moduleTypeUnderTestFactory android.ModuleFactory
+ moduleTypeUnderTestBp2BuildMutator func(android.TopDownMutatorContext)
+ blueprint string
+ expectedBazelTargets []string
+ filesystem map[string]string
+ }{
+ {
+ description: "simple python_binary_host converts to a native py_binary",
+ moduleTypeUnderTest: "python_binary_host",
+ moduleTypeUnderTestFactory: python.PythonBinaryHostFactory,
+ moduleTypeUnderTestBp2BuildMutator: python.PythonBinaryBp2Build,
+ filesystem: map[string]string{
+ "a.py": "",
+ "b/c.py": "",
+ "b/d.py": "",
+ "b/e.py": "",
+ "files/data.txt": "",
+ },
+ blueprint: `python_binary_host {
+ name: "foo",
+ main: "a.py",
+ srcs: [
+ "**/*.py"
+ ],
+ exclude_srcs: [
+ "b/e.py"
+ ],
+ data: [
+ "files/data.txt",
+ ],
+
+ bazel_module: { bp2build_available: true },
+}
+`,
+ expectedBazelTargets: []string{`py_binary(
+ name = "foo",
+ data = [
+ "files/data.txt",
+ ],
+ main = "a.py",
+ srcs = [
+ "a.py",
+ "b/c.py",
+ "b/d.py",
+ ],
+)`,
+ },
+ },
+ {
+ description: "py2 python_binary_host",
+ moduleTypeUnderTest: "python_binary_host",
+ moduleTypeUnderTestFactory: python.PythonBinaryHostFactory,
+ moduleTypeUnderTestBp2BuildMutator: python.PythonBinaryBp2Build,
+ blueprint: `python_binary_host {
+ name: "foo",
+ srcs: ["a.py"],
+ version: {
+ py2: {
+ enabled: true,
+ },
+ py3: {
+ enabled: false,
+ },
+ },
+
+ bazel_module: { bp2build_available: true },
+}
+`,
+ expectedBazelTargets: []string{`py_binary(
+ name = "foo",
+ python_version = "PY2",
+ srcs = [
+ "a.py",
+ ],
+)`,
+ },
+ },
+ {
+ description: "py3 python_binary_host",
+ moduleTypeUnderTest: "python_binary_host",
+ moduleTypeUnderTestFactory: python.PythonBinaryHostFactory,
+ moduleTypeUnderTestBp2BuildMutator: python.PythonBinaryBp2Build,
+ blueprint: `python_binary_host {
+ name: "foo",
+ srcs: ["a.py"],
+ version: {
+ py2: {
+ enabled: false,
+ },
+ py3: {
+ enabled: true,
+ },
+ },
+
+ bazel_module: { bp2build_available: true },
+}
+`,
+ expectedBazelTargets: []string{
+ // python_version is PY3 by default.
+ `py_binary(
+ name = "foo",
+ srcs = [
+ "a.py",
+ ],
+)`,
+ },
+ },
+ }
+
+ dir := "."
+ for _, testCase := range testCases {
+ filesystem := make(map[string][]byte)
+ toParse := []string{
+ "Android.bp",
+ }
+ for f, content := range testCase.filesystem {
+ if strings.HasSuffix(f, "Android.bp") {
+ toParse = append(toParse, f)
+ }
+ filesystem[f] = []byte(content)
+ }
+ config := android.TestConfig(buildDir, nil, testCase.blueprint, filesystem)
+ ctx := android.NewTestContext(config)
+
+ ctx.RegisterModuleType(testCase.moduleTypeUnderTest, testCase.moduleTypeUnderTestFactory)
+ ctx.RegisterBp2BuildMutator(testCase.moduleTypeUnderTest, testCase.moduleTypeUnderTestBp2BuildMutator)
+ ctx.RegisterForBazelConversion()
+
+ _, errs := ctx.ParseFileList(dir, toParse)
+ if Errored(t, testCase.description, errs) {
+ continue
+ }
+ _, errs = ctx.ResolveDependencies(config)
+ if Errored(t, testCase.description, errs) {
+ continue
+ }
+
+ codegenCtx := NewCodegenContext(config, *ctx.Context, Bp2Build)
+ bazelTargets := generateBazelTargetsForDir(codegenCtx, dir)
+ if actualCount, expectedCount := len(bazelTargets), len(testCase.expectedBazelTargets); actualCount != expectedCount {
+ fmt.Println(bazelTargets)
+ t.Errorf("%s: Expected %d bazel target, got %d", testCase.description, expectedCount, actualCount)
+ } else {
+ for i, target := range bazelTargets {
+ if w, g := testCase.expectedBazelTargets[i], target.content; w != g {
+ t.Errorf(
+ "%s: Expected generated Bazel target to be '%s', got '%s'",
+ testCase.description,
+ w,
+ g,
+ )
+ }
+ }
+ }
+ }
+}
diff --git a/bpf/bpf.go b/bpf/bpf.go
index 8142f10..fa1a84d 100644
--- a/bpf/bpf.go
+++ b/bpf/bpf.go
@@ -26,7 +26,7 @@
)
func init() {
- android.RegisterModuleType("bpf", BpfFactory)
+ registerBpfBuildComponents(android.InitRegistrationContext)
pctx.Import("android/soong/cc/config")
}
@@ -43,6 +43,12 @@
"ccCmd", "cFlags")
)
+func registerBpfBuildComponents(ctx android.RegistrationContext) {
+ ctx.RegisterModuleType("bpf", BpfFactory)
+}
+
+var PrepareForTestWithBpf = android.FixtureRegisterWithContext(registerBpfBuildComponents)
+
// BpfModule interface is used by the apex package to gather information from a bpf module.
type BpfModule interface {
android.Module
diff --git a/bpf/bpf_test.go b/bpf/bpf_test.go
index be9e36e..eb0d8c8 100644
--- a/bpf/bpf_test.go
+++ b/bpf/bpf_test.go
@@ -46,24 +46,20 @@
}
os.Exit(run())
+
}
-func testConfig(buildDir string, env map[string]string, bp string) android.Config {
- mockFS := map[string][]byte{
- "bpf.c": nil,
- "BpfTest.cpp": nil,
- }
-
- return cc.TestConfig(buildDir, android.Android, env, bp, mockFS)
-}
-
-func testContext(config android.Config) *android.TestContext {
- ctx := cc.CreateTestContext(config)
- ctx.RegisterModuleType("bpf", BpfFactory)
- ctx.Register()
-
- return ctx
-}
+var bpfFactory = android.NewFixtureFactory(
+ &buildDir,
+ cc.PrepareForTestWithCcDefaultModules,
+ android.FixtureMergeMockFs(
+ map[string][]byte{
+ "bpf.c": nil,
+ "BpfTest.cpp": nil,
+ },
+ ),
+ PrepareForTestWithBpf,
+)
func TestBpfDataDependency(t *testing.T) {
bp := `
@@ -80,16 +76,7 @@
}
`
- config := testConfig(buildDir, nil, bp)
- ctx := testContext(config)
-
- _, errs := ctx.ParseFileList(".", []string{"Android.bp"})
- if errs == nil {
- _, errs = ctx.PrepareBuildActions(config)
- }
- if errs != nil {
- t.Fatal(errs)
- }
+ bpfFactory.RunTestWithBp(t, bp)
// We only verify the above BP configuration is processed successfully since the data property
// value is not available for testing from this package.
diff --git a/build_kzip.bash b/build_kzip.bash
index 9564723..a4659d4 100755
--- a/build_kzip.bash
+++ b/build_kzip.bash
@@ -16,6 +16,7 @@
: ${BUILD_NUMBER:=$(uuidgen)}
: ${KYTHE_JAVA_SOURCE_BATCH_SIZE:=500}
: ${KYTHE_KZIP_ENCODING:=proto}
+: ${XREF_CORPUS:?should be set}
export KYTHE_JAVA_SOURCE_BATCH_SIZE KYTHE_KZIP_ENCODING
# The extraction might fail for some source files, so run with -k and then check that
@@ -29,11 +30,15 @@
declare -r abspath_out=$(realpath "${out}")
declare -r go_extractor=$(realpath prebuilts/build-tools/linux-x86/bin/go_extractor)
declare -r go_root=$(realpath prebuilts/go/linux-x86)
-declare -r vnames_path=$(realpath build/soong/vnames.go.json)
declare -r source_root=$PWD
+
+# TODO(asmundak): Until b/182183061 is fixed, default corpus has to be specified
+# in the rules file. Generate this file on the fly with corpus value set from the
+# environment variable.
for dir in blueprint soong; do
(cd "build/$dir";
- KYTHE_ROOT_DIRECTORY="${source_root}" "$go_extractor" --goroot="$go_root" --rules="${vnames_path}" \
+ KYTHE_ROOT_DIRECTORY="${source_root}" "$go_extractor" --goroot="$go_root" \
+ --rules=<(printf '[{"pattern": "(.*)","vname": {"path": "@1@", "corpus":"%s"}}]' "${XREF_CORPUS}") \
--canonicalize_package_corpus --output "${abspath_out}/soong/build_${dir}.go.kzip" ./...
)
done
diff --git a/cc/cc_test.go b/cc/cc_test.go
index e640f12..16ae7ee 100644
--- a/cc/cc_test.go
+++ b/cc/cc_test.go
@@ -52,29 +52,49 @@
os.Exit(run())
}
+var ccFixtureFactory = android.NewFixtureFactory(
+ &buildDir,
+ PrepareForTestWithCcIncludeVndk,
+ android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
+ variables.DeviceVndkVersion = StringPtr("current")
+ variables.ProductVndkVersion = StringPtr("current")
+ variables.Platform_vndk_version = StringPtr("VER")
+ }),
+)
+
+// testCcWithConfig runs tests using the ccFixtureFactory
+//
+// See testCc for an explanation as to how to stop using this deprecated method.
+//
+// deprecated
func testCcWithConfig(t *testing.T, config android.Config) *android.TestContext {
t.Helper()
- ctx := CreateTestContext(config)
- ctx.Register()
-
- _, errs := ctx.ParseFileList(".", []string{"Android.bp"})
- android.FailIfErrored(t, errs)
- _, errs = ctx.PrepareBuildActions(config)
- android.FailIfErrored(t, errs)
-
- return ctx
+ result := ccFixtureFactory.RunTestWithConfig(t, config)
+ return result.TestContext
}
+// testCc runs tests using the ccFixtureFactory
+//
+// Do not add any new usages of this, instead use the ccFixtureFactory directly as it makes it much
+// easier to customize the test behavior.
+//
+// If it is necessary to customize the behavior of an existing test that uses this then please first
+// convert the test to using ccFixtureFactory first and then in a following change add the
+// appropriate fixture preparers. Keeping the conversion change separate makes it easy to verify
+// that it did not change the test behavior unexpectedly.
+//
+// deprecated
func testCc(t *testing.T, bp string) *android.TestContext {
t.Helper()
- config := TestConfig(buildDir, android.Android, nil, bp, nil)
- config.TestProductVariables.DeviceVndkVersion = StringPtr("current")
- config.TestProductVariables.ProductVndkVersion = StringPtr("current")
- config.TestProductVariables.Platform_vndk_version = StringPtr("VER")
-
- return testCcWithConfig(t, config)
+ result := ccFixtureFactory.RunTestWithBp(t, bp)
+ return result.TestContext
}
+// testCcNoVndk runs tests using the ccFixtureFactory
+//
+// See testCc for an explanation as to how to stop using this deprecated method.
+//
+// deprecated
func testCcNoVndk(t *testing.T, bp string) *android.TestContext {
t.Helper()
config := TestConfig(buildDir, android.Android, nil, bp, nil)
@@ -83,6 +103,11 @@
return testCcWithConfig(t, config)
}
+// testCcNoProductVndk runs tests using the ccFixtureFactory
+//
+// See testCc for an explanation as to how to stop using this deprecated method.
+//
+// deprecated
func testCcNoProductVndk(t *testing.T, bp string) *android.TestContext {
t.Helper()
config := TestConfig(buildDir, android.Android, nil, bp, nil)
@@ -92,27 +117,24 @@
return testCcWithConfig(t, config)
}
+// testCcErrorWithConfig runs tests using the ccFixtureFactory
+//
+// See testCc for an explanation as to how to stop using this deprecated method.
+//
+// deprecated
func testCcErrorWithConfig(t *testing.T, pattern string, config android.Config) {
t.Helper()
- ctx := CreateTestContext(config)
- ctx.Register()
-
- _, errs := ctx.ParseFileList(".", []string{"Android.bp"})
- if len(errs) > 0 {
- android.FailIfNoMatchingErrors(t, pattern, errs)
- return
- }
-
- _, errs = ctx.PrepareBuildActions(config)
- if len(errs) > 0 {
- android.FailIfNoMatchingErrors(t, pattern, errs)
- return
- }
-
- t.Fatalf("missing expected error %q (0 errors are returned)", pattern)
+ ccFixtureFactory.Extend().
+ ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern(pattern)).
+ RunTestWithConfig(t, config)
}
+// testCcError runs tests using the ccFixtureFactory
+//
+// See testCc for an explanation as to how to stop using this deprecated method.
+//
+// deprecated
func testCcError(t *testing.T, pattern string, bp string) {
t.Helper()
config := TestConfig(buildDir, android.Android, nil, bp, nil)
@@ -122,6 +144,11 @@
return
}
+// testCcErrorProductVndk runs tests using the ccFixtureFactory
+//
+// See testCc for an explanation as to how to stop using this deprecated method.
+//
+// deprecated
func testCcErrorProductVndk(t *testing.T, pattern string, bp string) {
t.Helper()
config := TestConfig(buildDir, android.Android, nil, bp, nil)
@@ -153,13 +180,12 @@
},
}`
- config := TestConfig(buildDir, android.Fuchsia, nil, bp, nil)
- ctx := testCcWithConfig(t, config)
+ result := ccFixtureFactory.Extend(PrepareForTestOnFuchsia).RunTestWithBp(t, bp)
rt := false
fb := false
- ld := ctx.ModuleForTests("libTest", "fuchsia_arm64_shared").Rule("ld")
+ ld := result.ModuleForTests("libTest", "fuchsia_arm64_shared").Rule("ld")
implicits := ld.Implicits
for _, lib := range implicits {
if strings.Contains(lib.Rel(), "libcompiler_rt") {
@@ -190,16 +216,13 @@
},
}`
- config := TestConfig(buildDir, android.Fuchsia, nil, bp, nil)
- ctx := testCcWithConfig(t, config)
- ld := ctx.ModuleForTests("libTest", "fuchsia_arm64_shared").Rule("ld")
+ result := ccFixtureFactory.Extend(PrepareForTestOnFuchsia).RunTestWithBp(t, bp)
+ ld := result.ModuleForTests("libTest", "fuchsia_arm64_shared").Rule("ld")
var objs []string
for _, o := range ld.Inputs {
objs = append(objs, o.Base())
}
- if len(objs) != 2 || objs[0] != "foo.o" || objs[1] != "bar.o" {
- t.Errorf("inputs of libTest must be []string{\"foo.o\", \"bar.o\"}, but was %#v.", objs)
- }
+ android.AssertArrayString(t, "libTest inputs", []string{"foo.o", "bar.o"}, objs)
}
func TestVendorSrc(t *testing.T) {
@@ -3397,24 +3420,16 @@
}
`
- config := TestConfig(buildDir, android.Android, nil, bp, nil)
- config.TestProductVariables.Debuggable = BoolPtr(true)
+ result := ccFixtureFactory.Extend(
+ android.PrepareForTestWithVariables,
- ctx := CreateTestContext(config)
- ctx.PreDepsMutators(func(ctx android.RegisterMutatorsContext) {
- ctx.BottomUp("variable", android.VariableMutator).Parallel()
- })
- ctx.Register()
+ android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
+ variables.Debuggable = BoolPtr(true)
+ }),
+ ).RunTestWithBp(t, bp)
- _, errs := ctx.ParseFileList(".", []string{"Android.bp"})
- android.FailIfErrored(t, errs)
- _, errs = ctx.PrepareBuildActions(config)
- android.FailIfErrored(t, errs)
-
- libfoo := ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_static").Module().(*Module)
- if !android.InList("-DBAR", libfoo.flags.Local.CppFlags) {
- t.Errorf("expected -DBAR in cppflags, got %q", libfoo.flags.Local.CppFlags)
- }
+ libfoo := result.Module("libfoo", "android_arm64_armv8-a_static").(*Module)
+ android.AssertStringListContains(t, "cppflags", libfoo.flags.Local.CppFlags, "-DBAR")
}
func TestEmptyWholeStaticLibsAllowMissingDependencies(t *testing.T) {
@@ -3432,32 +3447,17 @@
}
`
- config := TestConfig(buildDir, android.Android, nil, bp, nil)
- config.TestProductVariables.Allow_missing_dependencies = BoolPtr(true)
+ result := ccFixtureFactory.Extend(
+ android.PrepareForTestWithAllowMissingDependencies,
+ ).RunTestWithBp(t, bp)
- ctx := CreateTestContext(config)
- ctx.SetAllowMissingDependencies(true)
- ctx.Register()
+ libbar := result.ModuleForTests("libbar", "android_arm64_armv8-a_static").Output("libbar.a")
+ android.AssertDeepEquals(t, "libbar rule", android.ErrorRule, libbar.Rule)
- _, errs := ctx.ParseFileList(".", []string{"Android.bp"})
- android.FailIfErrored(t, errs)
- _, errs = ctx.PrepareBuildActions(config)
- android.FailIfErrored(t, errs)
+ android.AssertStringDoesContain(t, "libbar error", libbar.Args["error"], "missing dependencies: libmissing")
- libbar := ctx.ModuleForTests("libbar", "android_arm64_armv8-a_static").Output("libbar.a")
- if g, w := libbar.Rule, android.ErrorRule; g != w {
- t.Fatalf("Expected libbar rule to be %q, got %q", w, g)
- }
-
- if g, w := libbar.Args["error"], "missing dependencies: libmissing"; !strings.Contains(g, w) {
- t.Errorf("Expected libbar error to contain %q, was %q", w, g)
- }
-
- libfoo := ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_static").Output("libfoo.a")
- if g, w := libfoo.Inputs.Strings(), libbar.Output.String(); !android.InList(w, g) {
- t.Errorf("Expected libfoo.a to depend on %q, got %q", w, g)
- }
-
+ libfoo := result.ModuleForTests("libfoo", "android_arm64_armv8-a_static").Output("libfoo.a")
+ android.AssertStringListContains(t, "libfoo.a dependencies", libfoo.Inputs.Strings(), libbar.Output.String())
}
func TestInstallSharedLibs(t *testing.T) {
@@ -3647,8 +3647,9 @@
}
}
-func makeMemtagTestConfig(t *testing.T) android.Config {
- templateBp := `
+var prepareForTestWithMemtagHeap = android.GroupFixturePreparers(
+ android.FixtureModifyMockFS(func(fs android.MockFS) {
+ templateBp := `
cc_test {
name: "%[1]s_test",
gtest: false,
@@ -3702,35 +3703,30 @@
sanitize: { memtag_heap: true, diag: { memtag_heap: true } },
}
`
- subdirDefaultBp := fmt.Sprintf(templateBp, "default")
- subdirExcludeBp := fmt.Sprintf(templateBp, "exclude")
- subdirSyncBp := fmt.Sprintf(templateBp, "sync")
- subdirAsyncBp := fmt.Sprintf(templateBp, "async")
+ subdirDefaultBp := fmt.Sprintf(templateBp, "default")
+ subdirExcludeBp := fmt.Sprintf(templateBp, "exclude")
+ subdirSyncBp := fmt.Sprintf(templateBp, "sync")
+ subdirAsyncBp := fmt.Sprintf(templateBp, "async")
- mockFS := map[string][]byte{
- "subdir_default/Android.bp": []byte(subdirDefaultBp),
- "subdir_exclude/Android.bp": []byte(subdirExcludeBp),
- "subdir_sync/Android.bp": []byte(subdirSyncBp),
- "subdir_async/Android.bp": []byte(subdirAsyncBp),
- }
-
- return TestConfig(buildDir, android.Android, nil, "", mockFS)
-}
+ fs.Merge(android.MockFS{
+ "subdir_default/Android.bp": []byte(subdirDefaultBp),
+ "subdir_exclude/Android.bp": []byte(subdirExcludeBp),
+ "subdir_sync/Android.bp": []byte(subdirSyncBp),
+ "subdir_async/Android.bp": []byte(subdirAsyncBp),
+ })
+ }),
+ android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
+ variables.MemtagHeapExcludePaths = []string{"subdir_exclude"}
+ variables.MemtagHeapSyncIncludePaths = []string{"subdir_sync"}
+ variables.MemtagHeapAsyncIncludePaths = []string{"subdir_async"}
+ }),
+)
func TestSanitizeMemtagHeap(t *testing.T) {
variant := "android_arm64_armv8-a"
- config := makeMemtagTestConfig(t)
- config.TestProductVariables.MemtagHeapExcludePaths = []string{"subdir_exclude"}
- config.TestProductVariables.MemtagHeapSyncIncludePaths = []string{"subdir_sync"}
- config.TestProductVariables.MemtagHeapAsyncIncludePaths = []string{"subdir_async"}
- ctx := CreateTestContext(config)
- ctx.Register()
-
- _, errs := ctx.ParseFileList(".", []string{"Android.bp", "subdir_default/Android.bp", "subdir_exclude/Android.bp", "subdir_sync/Android.bp", "subdir_async/Android.bp"})
- android.FailIfErrored(t, errs)
- _, errs = ctx.PrepareBuildActions(config)
- android.FailIfErrored(t, errs)
+ result := ccFixtureFactory.Extend(prepareForTestWithMemtagHeap).RunTest(t)
+ ctx := result.TestContext
checkHasMemtagNote(t, ctx.ModuleForTests("default_test", variant), Sync)
checkHasMemtagNote(t, ctx.ModuleForTests("default_test_false", variant), None)
@@ -3784,18 +3780,13 @@
func TestSanitizeMemtagHeapWithSanitizeDevice(t *testing.T) {
variant := "android_arm64_armv8-a"
- config := makeMemtagTestConfig(t)
- config.TestProductVariables.MemtagHeapExcludePaths = []string{"subdir_exclude"}
- config.TestProductVariables.MemtagHeapSyncIncludePaths = []string{"subdir_sync"}
- config.TestProductVariables.MemtagHeapAsyncIncludePaths = []string{"subdir_async"}
- config.TestProductVariables.SanitizeDevice = []string{"memtag_heap"}
- ctx := CreateTestContext(config)
- ctx.Register()
-
- _, errs := ctx.ParseFileList(".", []string{"Android.bp", "subdir_default/Android.bp", "subdir_exclude/Android.bp", "subdir_sync/Android.bp", "subdir_async/Android.bp"})
- android.FailIfErrored(t, errs)
- _, errs = ctx.PrepareBuildActions(config)
- android.FailIfErrored(t, errs)
+ result := ccFixtureFactory.Extend(
+ prepareForTestWithMemtagHeap,
+ android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
+ variables.SanitizeDevice = []string{"memtag_heap"}
+ }),
+ ).RunTest(t)
+ ctx := result.TestContext
checkHasMemtagNote(t, ctx.ModuleForTests("default_test", variant), Sync)
checkHasMemtagNote(t, ctx.ModuleForTests("default_test_false", variant), None)
@@ -3849,19 +3840,14 @@
func TestSanitizeMemtagHeapWithSanitizeDeviceDiag(t *testing.T) {
variant := "android_arm64_armv8-a"
- config := makeMemtagTestConfig(t)
- config.TestProductVariables.MemtagHeapExcludePaths = []string{"subdir_exclude"}
- config.TestProductVariables.MemtagHeapSyncIncludePaths = []string{"subdir_sync"}
- config.TestProductVariables.MemtagHeapAsyncIncludePaths = []string{"subdir_async"}
- config.TestProductVariables.SanitizeDevice = []string{"memtag_heap"}
- config.TestProductVariables.SanitizeDeviceDiag = []string{"memtag_heap"}
- ctx := CreateTestContext(config)
- ctx.Register()
-
- _, errs := ctx.ParseFileList(".", []string{"Android.bp", "subdir_default/Android.bp", "subdir_exclude/Android.bp", "subdir_sync/Android.bp", "subdir_async/Android.bp"})
- android.FailIfErrored(t, errs)
- _, errs = ctx.PrepareBuildActions(config)
- android.FailIfErrored(t, errs)
+ result := ccFixtureFactory.Extend(
+ prepareForTestWithMemtagHeap,
+ android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
+ variables.SanitizeDevice = []string{"memtag_heap"}
+ variables.SanitizeDeviceDiag = []string{"memtag_heap"}
+ }),
+ ).RunTest(t)
+ ctx := result.TestContext
checkHasMemtagNote(t, ctx.ModuleForTests("default_test", variant), Sync)
checkHasMemtagNote(t, ctx.ModuleForTests("default_test_false", variant), None)
diff --git a/cc/cmakelists.go b/cc/cmakelists.go
index d441c57..04536fc 100644
--- a/cc/cmakelists.go
+++ b/cc/cmakelists.go
@@ -319,6 +319,9 @@
if strings.HasPrefix(parameter, "-fsanitize-blacklist") {
return relativeFilePathFlag
}
+ if strings.HasPrefix(parameter, "-fprofile-sample-use") {
+ return relativeFilePathFlag
+ }
return flag
}
diff --git a/cc/config/x86_darwin_host.go b/cc/config/x86_darwin_host.go
index 1035df3..b0344af 100644
--- a/cc/config/x86_darwin_host.go
+++ b/cc/config/x86_darwin_host.go
@@ -136,7 +136,7 @@
func getMacTools(ctx android.PackageVarContext) *macPlatformTools {
macTools.once.Do(func() {
- xcrunTool := ctx.Config().NonHermeticHostSystemTool("xcrun")
+ xcrunTool := "/usr/bin/xcrun"
xcrun := func(args ...string) string {
if macTools.err != nil {
diff --git a/cc/library.go b/cc/library.go
index 0e6e107..6a3b876 100644
--- a/cc/library.go
+++ b/cc/library.go
@@ -230,6 +230,7 @@
module, library := NewLibrary(android.HostAndDeviceSupported)
library.BuildOnlyStatic()
module.sdkMemberTypes = []android.SdkMemberType{staticLibrarySdkMemberType}
+ module.bazelHandler = &staticLibraryBazelHandler{module: module}
return module.Init()
}
@@ -406,6 +407,49 @@
collectedSnapshotHeaders android.Paths
}
+type staticLibraryBazelHandler struct {
+ bazelHandler
+
+ module *Module
+}
+
+func (handler *staticLibraryBazelHandler) generateBazelBuildActions(ctx android.ModuleContext, label string) bool {
+ bazelCtx := ctx.Config().BazelContext
+ outputPaths, objPaths, ok := bazelCtx.GetAllFilesAndCcObjectFiles(label, ctx.Arch().ArchType)
+ if ok {
+ if len(outputPaths) != 1 {
+ // TODO(cparsons): This is actually expected behavior for static libraries with no srcs.
+ // We should support this.
+ ctx.ModuleErrorf("expected exactly one output file for '%s', but got %s", label, objPaths)
+ return false
+ }
+ outputFilePath := android.PathForBazelOut(ctx, outputPaths[0])
+ handler.module.outputFile = android.OptionalPathForPath(outputFilePath)
+
+ objFiles := make(android.Paths, len(objPaths))
+ for i, objPath := range objPaths {
+ objFiles[i] = android.PathForBazelOut(ctx, objPath)
+ }
+ objects := Objects{
+ objFiles: objFiles,
+ }
+
+ ctx.SetProvider(StaticLibraryInfoProvider, StaticLibraryInfo{
+ StaticLibrary: outputFilePath,
+ ReuseObjects: objects,
+ Objects: objects,
+
+ // TODO(cparsons): Include transitive static libraries in this provider to support
+ // static libraries with deps.
+ TransitiveStaticLibrariesForOrdering: android.NewDepSetBuilder(android.TOPOLOGICAL).
+ Direct(outputFilePath).
+ Build(),
+ })
+ handler.module.outputFile = android.OptionalPathForPath(android.PathForBazelOut(ctx, objPaths[0]))
+ }
+ return ok
+}
+
// collectHeadersForSnapshot collects all exported headers from library.
// It globs header files in the source tree for exported include directories,
// and tracks generated header files separately.
diff --git a/cc/prebuilt_test.go b/cc/prebuilt_test.go
index ee4de6e..20274b2 100644
--- a/cc/prebuilt_test.go
+++ b/cc/prebuilt_test.go
@@ -23,27 +23,16 @@
"github.com/google/blueprint"
)
-func testPrebuilt(t *testing.T, bp string, fs map[string][]byte, handlers ...configCustomizer) *android.TestContext {
- config := TestConfig(buildDir, android.Android, nil, bp, fs)
- ctx := CreateTestContext(config)
+var prebuiltFixtureFactory = ccFixtureFactory.Extend(
+ android.PrepareForTestWithAndroidMk,
+)
- // Enable androidmk support.
- // * Register the singleton
- // * Configure that we are inside make
- // * Add CommonOS to ensure that androidmk processing works.
- android.RegisterAndroidMkBuildComponents(ctx)
- android.SetKatiEnabledForTests(config)
+func testPrebuilt(t *testing.T, bp string, fs android.MockFS, handlers ...android.FixturePreparer) *android.TestContext {
+ result := prebuiltFixtureFactory.Extend(
+ fs.AddToFixture(),
+ ).Extend(handlers...).RunTestWithBp(t, bp)
- for _, handler := range handlers {
- handler(config)
- }
-
- ctx.Register()
- _, errs := ctx.ParseFileList(".", []string{"Android.bp"})
- android.FailIfErrored(t, errs)
- _, errs = ctx.PrepareBuildActions(config)
- android.FailIfErrored(t, errs)
- return ctx
+ return result.TestContext
}
type configCustomizer func(config android.Config)
@@ -370,9 +359,11 @@
assertString(t, static2.OutputFile().Path().Base(), "libf.a")
// With SANITIZE_TARGET=hwaddress
- ctx = testPrebuilt(t, bp, fs, func(config android.Config) {
- config.TestProductVariables.SanitizeDevice = []string{"hwaddress"}
- })
+ ctx = testPrebuilt(t, bp, fs,
+ android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
+ variables.SanitizeDevice = []string{"hwaddress"}
+ }),
+ )
shared_rule = ctx.ModuleForTests("libtest", "android_arm64_armv8-a_shared_hwasan").Rule("android/soong/cc.strip")
assertString(t, shared_rule.Input.String(), "hwasan/libf.so")
diff --git a/cc/sanitize.go b/cc/sanitize.go
index 8218d97..cd09e6e 100644
--- a/cc/sanitize.go
+++ b/cc/sanitize.go
@@ -404,12 +404,6 @@
s.Diag.Cfi = boolPtr(false)
}
- // Also disable CFI for arm32 until b/35157333 is fixed.
- if ctx.Arch().ArchType == android.Arm {
- s.Cfi = boolPtr(false)
- s.Diag.Cfi = boolPtr(false)
- }
-
// HWASan requires AArch64 hardware feature (top-byte-ignore).
if ctx.Arch().ArchType != android.Arm64 {
s.Hwaddress = nil
diff --git a/cc/testing.go b/cc/testing.go
index f62c5f1..d8adc61 100644
--- a/cc/testing.go
+++ b/cc/testing.go
@@ -37,7 +37,31 @@
}
func GatherRequiredDepsForTest(oses ...android.OsType) string {
- ret := `
+ ret := commonDefaultModules()
+
+ supportLinuxBionic := false
+ for _, os := range oses {
+ if os == android.Fuchsia {
+ ret += withFuchsiaModules()
+ }
+ if os == android.Windows {
+ ret += withWindowsModules()
+ }
+ if os == android.LinuxBionic {
+ supportLinuxBionic = true
+ ret += withLinuxBionic()
+ }
+ }
+
+ if !supportLinuxBionic {
+ ret += withoutLinuxBionic()
+ }
+
+ return ret
+}
+
+func commonDefaultModules() string {
+ return `
toolchain_library {
name: "libatomic",
defaults: ["linux_bionic_supported"],
@@ -475,23 +499,10 @@
name: "note_memtag_heap_sync",
}
`
+}
- supportLinuxBionic := false
- for _, os := range oses {
- if os == android.Fuchsia {
- ret += `
- cc_library {
- name: "libbioniccompat",
- stl: "none",
- }
- cc_library {
- name: "libcompiler_rt",
- stl: "none",
- }
- `
- }
- if os == android.Windows {
- ret += `
+func withWindowsModules() string {
+ return `
toolchain_library {
name: "libwinpthread",
host_supported: true,
@@ -504,10 +515,23 @@
src: "",
}
`
+}
+
+func withFuchsiaModules() string {
+ return `
+ cc_library {
+ name: "libbioniccompat",
+ stl: "none",
}
- if os == android.LinuxBionic {
- supportLinuxBionic = true
- ret += `
+ cc_library {
+ name: "libcompiler_rt",
+ stl: "none",
+ }
+ `
+}
+
+func withLinuxBionic() string {
+ return `
cc_binary {
name: "linker",
defaults: ["linux_bionic_supported"],
@@ -547,23 +571,115 @@
},
}
`
- }
- }
+}
- if !supportLinuxBionic {
- ret += `
+func withoutLinuxBionic() string {
+ return `
cc_defaults {
name: "linux_bionic_supported",
}
`
- }
-
- return ret
}
func GatherRequiredFilesForTest(fs map[string][]byte) {
}
+// The directory in which cc linux bionic default modules will be defined.
+//
+// Placing them here ensures that their location does not conflict with default test modules
+// defined by other packages.
+const linuxBionicDefaultsPath = "defaults/cc/linux-bionic/Android.bp"
+
+// The directory in which the default cc common test modules will be defined.
+//
+// Placing them here ensures that their location does not conflict with default test modules
+// defined by other packages.
+const DefaultCcCommonTestModulesDir = "defaults/cc/common/"
+
+// Test fixture preparer that will register most cc build components.
+//
+// Singletons and mutators should only be added here if they are needed for a majority of cc
+// module types, otherwise they should be added under a separate preparer to allow them to be
+// selected only when needed to reduce test execution time.
+//
+// Module types do not have much of an overhead unless they are used so this should include as many
+// module types as possible. The exceptions are those module types that require mutators and/or
+// singletons in order to function in which case they should be kept together in a separate
+// preparer.
+var PrepareForTestWithCcBuildComponents = android.GroupFixturePreparers(
+ android.PrepareForTestWithAndroidBuildComponents,
+ android.FixtureRegisterWithContext(RegisterRequiredBuildComponentsForTest),
+ android.FixtureRegisterWithContext(func(ctx android.RegistrationContext) {
+ ctx.RegisterModuleType("cc_fuzz", FuzzFactory)
+ ctx.RegisterModuleType("cc_test", TestFactory)
+ ctx.RegisterModuleType("cc_test_library", TestLibraryFactory)
+ ctx.RegisterModuleType("llndk_headers", llndkHeadersFactory)
+ ctx.RegisterModuleType("vendor_public_library", vendorPublicLibraryFactory)
+ ctx.RegisterModuleType("vndk_prebuilt_shared", VndkPrebuiltSharedFactory)
+
+ RegisterVndkLibraryTxtTypes(ctx)
+ }),
+)
+
+// Preparer that will define default cc modules, e.g. standard prebuilt modules.
+var PrepareForTestWithCcDefaultModules = android.GroupFixturePreparers(
+ PrepareForTestWithCcBuildComponents,
+ // Place the default cc test modules that are common to all platforms in a location that will not
+ // conflict with default test modules defined by other packages.
+ android.FixtureAddTextFile(DefaultCcCommonTestModulesDir+"Android.bp", commonDefaultModules()),
+ // Disable linux bionic by default.
+ android.FixtureAddTextFile(linuxBionicDefaultsPath, withoutLinuxBionic()),
+)
+
+// Prepare a fixture to use all cc module types, mutators and singletons fully.
+//
+// This should only be used by tests that want to run with as much of the build enabled as possible.
+var PrepareForIntegrationTestWithCc = android.GroupFixturePreparers(
+ android.PrepareForIntegrationTestWithAndroid,
+ genrule.PrepareForIntegrationTestWithGenrule,
+ PrepareForTestWithCcDefaultModules,
+)
+
+// The preparer to include if running a cc related test for windows.
+var PrepareForTestOnWindows = android.GroupFixturePreparers(
+ // Place the default cc test modules for windows platforms in a location that will not conflict
+ // with default test modules defined by other packages.
+ android.FixtureAddTextFile("defaults/cc/windows/Android.bp", withWindowsModules()),
+)
+
+// The preparer to include if running a cc related test for linux bionic.
+var PrepareForTestOnLinuxBionic = android.GroupFixturePreparers(
+ // Enable linux bionic
+ //
+ // Can be used after PrepareForTestWithCcDefaultModules to override its default behavior of
+ // disabling linux bionic, hence why this uses FixtureOverrideTextFile.
+ android.FixtureOverrideTextFile(linuxBionicDefaultsPath, withLinuxBionic()),
+)
+
+// The preparer to include if running a cc related test for fuchsia.
+var PrepareForTestOnFuchsia = android.GroupFixturePreparers(
+ // Place the default cc test modules for fuschia in a location that will not conflict with default
+ // test modules defined by other packages.
+ android.FixtureAddTextFile("defaults/cc/fuschia/Android.bp", withFuchsiaModules()),
+ android.PrepareForTestSetDeviceToFuchsia,
+)
+
+// This adds some additional modules and singletons which might negatively impact the performance
+// of tests so they are not included in the PrepareForIntegrationTestWithCc.
+var PrepareForTestWithCcIncludeVndk = android.GroupFixturePreparers(
+ PrepareForIntegrationTestWithCc,
+ android.FixtureRegisterWithContext(func(ctx android.RegistrationContext) {
+ vendorSnapshotImageSingleton.init(ctx)
+ recoverySnapshotImageSingleton.init(ctx)
+ ctx.RegisterSingletonType("vndk-snapshot", VndkSnapshotSingleton)
+ }),
+)
+
+// TestConfig is the legacy way of creating a test Config for testing cc modules.
+//
+// See testCc for an explanation as to how to stop using this deprecated method.
+//
+// deprecated
func TestConfig(buildDir string, os android.OsType, env map[string]string,
bp string, fs map[string][]byte) android.Config {
@@ -580,7 +696,7 @@
var config android.Config
if os == android.Fuchsia {
- config = android.TestArchConfigFuchsia(buildDir, env, bp, mockFS)
+ panic("Fuchsia not supported use test fixture instead")
} else {
config = android.TestArchConfig(buildDir, env, bp, mockFS)
}
@@ -588,6 +704,11 @@
return config
}
+// CreateTestContext is the legacy way of creating a TestContext for testing cc modules.
+//
+// See testCc for an explanation as to how to stop using this deprecated method.
+//
+// deprecated
func CreateTestContext(config android.Config) *android.TestContext {
ctx := android.NewTestArchContext(config)
genrule.RegisterGenruleBuildComponents(ctx)
@@ -598,13 +719,15 @@
ctx.RegisterModuleType("vendor_public_library", vendorPublicLibraryFactory)
ctx.RegisterModuleType("filegroup", android.FileGroupFactory)
ctx.RegisterModuleType("vndk_prebuilt_shared", VndkPrebuiltSharedFactory)
+
vendorSnapshotImageSingleton.init(ctx)
recoverySnapshotImageSingleton.init(ctx)
+ ctx.RegisterSingletonType("vndk-snapshot", VndkSnapshotSingleton)
RegisterVndkLibraryTxtTypes(ctx)
+
ctx.PreArchMutators(android.RegisterDefaultsPreArchMutators)
android.RegisterPrebuiltMutators(ctx)
RegisterRequiredBuildComponentsForTest(ctx)
- ctx.RegisterSingletonType("vndk-snapshot", VndkSnapshotSingleton)
return ctx
}
diff --git a/cmd/soong_build/main.go b/cmd/soong_build/main.go
index e7f995f..4586f44 100644
--- a/cmd/soong_build/main.go
+++ b/cmd/soong_build/main.go
@@ -33,13 +33,17 @@
outDir string
docFile string
bazelQueryViewDir string
+ delveListen string
+ delvePath string
)
func init() {
flag.StringVar(&topDir, "top", "", "Top directory of the Android source tree")
flag.StringVar(&outDir, "out", "", "Soong output directory (usually $TOP/out/soong)")
+ flag.StringVar(&delveListen, "delve_listen", "", "Delve port to listen on for debugging")
+ flag.StringVar(&delvePath, "delve_path", "", "Path to Delve. Only used if --delve_listen is set")
flag.StringVar(&docFile, "soong_docs", "", "build documentation file to output")
- flag.StringVar(&bazelQueryViewDir, "bazel_queryview_dir", "", "path to the bazel queryview directory")
+ flag.StringVar(&bazelQueryViewDir, "bazel_queryview_dir", "", "path to the bazel queryview directory relative to --top")
}
func newNameResolver(config android.Config) *android.NameResolver {
@@ -87,9 +91,9 @@
func main() {
flag.Parse()
+ shared.ReexecWithDelveMaybe(delveListen, delvePath)
android.InitSandbox(topDir)
android.InitEnvironment(shared.JoinPath(topDir, outDir, "soong.environment.available"))
- android.ReexecWithDelveMaybe()
// The top-level Blueprints file is passed as the first argument.
srcDir := filepath.Dir(flag.Arg(0))
@@ -101,9 +105,7 @@
// user sets SOONG_DELVE the first time.
configuration.Getenv("SOONG_DELVE")
configuration.Getenv("SOONG_DELVE_PATH")
- // Read the SOONG_DELVE again through configuration so that there is a dependency on the environment variable
- // and soong_build will rerun when it is set for the first time.
- if listen := configuration.Getenv("SOONG_DELVE"); listen != "" {
+ if shared.IsDebugging() {
// Add a non-existent file to the dependencies so that soong_build will rerun when the debugger is
// enabled even if it completed successfully.
extraNinjaDeps = append(extraNinjaDeps, filepath.Join(configuration.BuildDir(), "always_rerun_for_delve"))
@@ -148,7 +150,8 @@
if bazelQueryViewDir != "" {
// Run the code-generation phase to convert BazelTargetModules to BUILD files.
codegenContext := bp2build.NewCodegenContext(configuration, *ctx, bp2build.QueryView)
- if err := createBazelQueryView(codegenContext, bazelQueryViewDir); err != nil {
+ absoluteQueryViewDir := shared.JoinPath(topDir, bazelQueryViewDir)
+ if err := createBazelQueryView(codegenContext, absoluteQueryViewDir); err != nil {
fmt.Fprintf(os.Stderr, "%s", err)
os.Exit(1)
}
diff --git a/cmd/soong_ui/main.go b/cmd/soong_ui/main.go
index 74ede68..1c5e78a 100644
--- a/cmd/soong_ui/main.go
+++ b/cmd/soong_ui/main.go
@@ -25,6 +25,7 @@
"strings"
"time"
+ "android/soong/shared"
"android/soong/ui/build"
"android/soong/ui/logger"
"android/soong/ui/metrics"
@@ -118,6 +119,8 @@
// Command is the type of soong_ui execution. Only one type of
// execution is specified. The args are specific to the command.
func main() {
+ shared.ReexecWithDelveMaybe(os.Getenv("SOONG_UI_DELVE"), shared.ResolveDelveBinary())
+
buildStarted := time.Now()
c, args, err := getCommand(os.Args)
diff --git a/dexpreopt/dexpreopt.go b/dexpreopt/dexpreopt.go
index 737773f..fdb00bd 100644
--- a/dexpreopt/dexpreopt.go
+++ b/dexpreopt/dexpreopt.go
@@ -288,12 +288,9 @@
} else {
// Other libraries or APKs for which the exact <uses-library> list is unknown.
- // Pass special class loader context to skip the classpath and collision check.
- // This will get removed once LOCAL_USES_LIBRARIES is enforced.
- // Right now LOCAL_USES_LIBRARIES is opt in, for the case where it's not specified we still default
- // to the &.
+ // We assume the class loader context is empty.
rule.Command().
- Text(`class_loader_context_arg=--class-loader-context=\&`).
+ Text(`class_loader_context_arg=--class-loader-context=PCL[]`).
Text(`stored_class_loader_context_arg=""`)
}
diff --git a/dexpreopt/testing.go b/dexpreopt/testing.go
index bccbfc1..8e90295 100644
--- a/dexpreopt/testing.go
+++ b/dexpreopt/testing.go
@@ -45,3 +45,36 @@
}
`
}
+
+// Prepares a test fixture by enabling dexpreopt.
+var PrepareForTestWithDexpreopt = FixtureModifyGlobalConfig(func(*GlobalConfig) {})
+
+// FixtureModifyGlobalConfig enables dexpreopt (unless modified by the mutator) and modifies the
+// configuration.
+func FixtureModifyGlobalConfig(configModifier func(dexpreoptConfig *GlobalConfig)) android.FixturePreparer {
+ return android.FixtureModifyConfig(func(config android.Config) {
+ // Initialize the dexpreopt GlobalConfig to an empty structure. This has no effect if it has
+ // already been set.
+ pathCtx := android.PathContextForTesting(config)
+ dexpreoptConfig := GlobalConfigForTests(pathCtx)
+ SetTestGlobalConfig(config, dexpreoptConfig)
+
+ // Retrieve the existing configuration and modify it.
+ dexpreoptConfig = GetGlobalConfig(pathCtx)
+ configModifier(dexpreoptConfig)
+ })
+}
+
+// FixtureSetArtBootJars enables dexpreopt and sets the ArtApexJars property.
+func FixtureSetArtBootJars(bootJars ...string) android.FixturePreparer {
+ return FixtureModifyGlobalConfig(func(dexpreoptConfig *GlobalConfig) {
+ dexpreoptConfig.ArtApexJars = android.CreateTestConfiguredJarList(bootJars)
+ })
+}
+
+// FixtureSetBootJars enables dexpreopt and sets the BootJars property.
+func FixtureSetBootJars(bootJars ...string) android.FixturePreparer {
+ return FixtureModifyGlobalConfig(func(dexpreoptConfig *GlobalConfig) {
+ dexpreoptConfig.BootJars = android.CreateTestConfiguredJarList(bootJars)
+ })
+}
diff --git a/etc/prebuilt_etc.go b/etc/prebuilt_etc.go
index b07ad91..6291325 100644
--- a/etc/prebuilt_etc.go
+++ b/etc/prebuilt_etc.go
@@ -54,6 +54,8 @@
ctx.RegisterModuleType("prebuilt_dsp", PrebuiltDSPFactory)
}
+var PrepareForTestWithPrebuiltEtc = android.FixtureRegisterWithContext(RegisterPrebuiltEtcBuildComponents)
+
type prebuiltEtcProperties struct {
// Source file of this prebuilt. Can reference a genrule type module with the ":module" syntax.
Src *string `android:"path,arch_variant"`
diff --git a/etc/prebuilt_etc_test.go b/etc/prebuilt_etc_test.go
index 585760d..09f2e8c 100644
--- a/etc/prebuilt_etc_test.go
+++ b/etc/prebuilt_etc_test.go
@@ -18,7 +18,6 @@
"io/ioutil"
"os"
"path/filepath"
- "reflect"
"testing"
"android/soong/android"
@@ -49,60 +48,19 @@
os.Exit(run())
}
-func testPrebuiltEtcContext(t *testing.T, bp string) (*android.TestContext, android.Config) {
- fs := map[string][]byte{
+var prebuiltEtcFixtureFactory = android.NewFixtureFactory(
+ &buildDir,
+ android.PrepareForTestWithArchMutator,
+ PrepareForTestWithPrebuiltEtc,
+ android.FixtureMergeMockFs(android.MockFS{
"foo.conf": nil,
"bar.conf": nil,
"baz.conf": nil,
- }
+ }),
+)
- config := android.TestArchConfig(buildDir, nil, bp, fs)
-
- ctx := android.NewTestArchContext(config)
- ctx.RegisterModuleType("prebuilt_etc", PrebuiltEtcFactory)
- ctx.RegisterModuleType("prebuilt_etc_host", PrebuiltEtcHostFactory)
- ctx.RegisterModuleType("prebuilt_usr_share", PrebuiltUserShareFactory)
- ctx.RegisterModuleType("prebuilt_usr_share_host", PrebuiltUserShareHostFactory)
- ctx.RegisterModuleType("prebuilt_font", PrebuiltFontFactory)
- ctx.RegisterModuleType("prebuilt_firmware", PrebuiltFirmwareFactory)
- ctx.RegisterModuleType("prebuilt_dsp", PrebuiltDSPFactory)
- ctx.Register()
-
- return ctx, config
-}
-
-func testPrebuiltEtc(t *testing.T, bp string) (*android.TestContext, android.Config) {
- t.Helper()
-
- ctx, config := testPrebuiltEtcContext(t, bp)
- _, errs := ctx.ParseFileList(".", []string{"Android.bp"})
- android.FailIfErrored(t, errs)
- _, errs = ctx.PrepareBuildActions(config)
- android.FailIfErrored(t, errs)
-
- return ctx, config
-}
-
-func testPrebuiltEtcError(t *testing.T, pattern, bp string) {
- t.Helper()
-
- ctx, config := testPrebuiltEtcContext(t, bp)
- _, errs := ctx.ParseFileList(".", []string{"Android.bp"})
- if len(errs) > 0 {
- android.FailIfNoMatchingErrors(t, pattern, errs)
- return
- }
-
- _, errs = ctx.PrepareBuildActions(config)
- if len(errs) > 0 {
- android.FailIfNoMatchingErrors(t, pattern, errs)
- return
- }
-
- t.Fatalf("missing expected error %q (0 errors are returned)", pattern)
-}
func TestPrebuiltEtcVariants(t *testing.T) {
- ctx, _ := testPrebuiltEtc(t, `
+ result := prebuiltEtcFixtureFactory.RunTestWithBp(t, `
prebuilt_etc {
name: "foo.conf",
src: "foo.conf",
@@ -119,24 +77,24 @@
}
`)
- foo_variants := ctx.ModuleVariantsForTests("foo.conf")
+ foo_variants := result.ModuleVariantsForTests("foo.conf")
if len(foo_variants) != 1 {
t.Errorf("expected 1, got %#v", foo_variants)
}
- bar_variants := ctx.ModuleVariantsForTests("bar.conf")
+ bar_variants := result.ModuleVariantsForTests("bar.conf")
if len(bar_variants) != 2 {
t.Errorf("expected 2, got %#v", bar_variants)
}
- baz_variants := ctx.ModuleVariantsForTests("baz.conf")
+ baz_variants := result.ModuleVariantsForTests("baz.conf")
if len(baz_variants) != 1 {
t.Errorf("expected 1, got %#v", bar_variants)
}
}
func TestPrebuiltEtcOutputPath(t *testing.T) {
- ctx, _ := testPrebuiltEtc(t, `
+ result := prebuiltEtcFixtureFactory.RunTestWithBp(t, `
prebuilt_etc {
name: "foo.conf",
src: "foo.conf",
@@ -144,14 +102,12 @@
}
`)
- p := ctx.ModuleForTests("foo.conf", "android_arm64_armv8-a").Module().(*PrebuiltEtc)
- if p.outputFilePath.Base() != "foo.installed.conf" {
- t.Errorf("expected foo.installed.conf, got %q", p.outputFilePath.Base())
- }
+ p := result.Module("foo.conf", "android_arm64_armv8-a").(*PrebuiltEtc)
+ android.AssertStringEquals(t, "output file path", "foo.installed.conf", p.outputFilePath.Base())
}
func TestPrebuiltEtcGlob(t *testing.T) {
- ctx, _ := testPrebuiltEtc(t, `
+ result := prebuiltEtcFixtureFactory.RunTestWithBp(t, `
prebuilt_etc {
name: "my_foo",
src: "foo.*",
@@ -163,19 +119,15 @@
}
`)
- p := ctx.ModuleForTests("my_foo", "android_arm64_armv8-a").Module().(*PrebuiltEtc)
- if p.outputFilePath.Base() != "my_foo" {
- t.Errorf("expected my_foo, got %q", p.outputFilePath.Base())
- }
+ p := result.Module("my_foo", "android_arm64_armv8-a").(*PrebuiltEtc)
+ android.AssertStringEquals(t, "my_foo output file path", "my_foo", p.outputFilePath.Base())
- p = ctx.ModuleForTests("my_bar", "android_arm64_armv8-a").Module().(*PrebuiltEtc)
- if p.outputFilePath.Base() != "bar.conf" {
- t.Errorf("expected bar.conf, got %q", p.outputFilePath.Base())
- }
+ p = result.Module("my_bar", "android_arm64_armv8-a").(*PrebuiltEtc)
+ android.AssertStringEquals(t, "my_bar output file path", "bar.conf", p.outputFilePath.Base())
}
func TestPrebuiltEtcAndroidMk(t *testing.T) {
- ctx, _ := testPrebuiltEtc(t, `
+ result := prebuiltEtcFixtureFactory.RunTestWithBp(t, `
prebuilt_etc {
name: "foo",
src: "foo.conf",
@@ -197,13 +149,11 @@
"LOCAL_TARGET_REQUIRED_MODULES": {"targetModA"},
}
- mod := ctx.ModuleForTests("foo", "android_arm64_armv8-a").Module().(*PrebuiltEtc)
- entries := android.AndroidMkEntriesForTest(t, ctx, mod)[0]
+ mod := result.Module("foo", "android_arm64_armv8-a").(*PrebuiltEtc)
+ entries := android.AndroidMkEntriesForTest(t, result.TestContext, mod)[0]
for k, expectedValue := range expected {
if value, ok := entries.EntryMap[k]; ok {
- if !reflect.DeepEqual(value, expectedValue) {
- t.Errorf("Incorrect %s '%s', expected '%s'", k, value, expectedValue)
- }
+ android.AssertDeepEquals(t, k, expectedValue, value)
} else {
t.Errorf("No %s defined, saw %q", k, entries.EntryMap)
}
@@ -211,7 +161,7 @@
}
func TestPrebuiltEtcRelativeInstallPathInstallDirPath(t *testing.T) {
- ctx, _ := testPrebuiltEtc(t, `
+ result := prebuiltEtcFixtureFactory.RunTestWithBp(t, `
prebuilt_etc {
name: "foo.conf",
src: "foo.conf",
@@ -219,26 +169,26 @@
}
`)
- p := ctx.ModuleForTests("foo.conf", "android_arm64_armv8-a").Module().(*PrebuiltEtc)
+ p := result.Module("foo.conf", "android_arm64_armv8-a").(*PrebuiltEtc)
expected := buildDir + "/target/product/test_device/system/etc/bar"
- if p.installDirPath.String() != expected {
- t.Errorf("expected %q, got %q", expected, p.installDirPath.String())
- }
+ android.AssertStringEquals(t, "install dir", expected, p.installDirPath.String())
}
func TestPrebuiltEtcCannotSetRelativeInstallPathAndSubDir(t *testing.T) {
- testPrebuiltEtcError(t, "relative_install_path is set. Cannot set sub_dir", `
- prebuilt_etc {
- name: "foo.conf",
- src: "foo.conf",
- sub_dir: "bar",
- relative_install_path: "bar",
- }
- `)
+ prebuiltEtcFixtureFactory.
+ ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern("relative_install_path is set. Cannot set sub_dir")).
+ RunTestWithBp(t, `
+ prebuilt_etc {
+ name: "foo.conf",
+ src: "foo.conf",
+ sub_dir: "bar",
+ relative_install_path: "bar",
+ }
+ `)
}
func TestPrebuiltEtcHost(t *testing.T) {
- ctx, _ := testPrebuiltEtc(t, `
+ result := prebuiltEtcFixtureFactory.RunTestWithBp(t, `
prebuilt_etc_host {
name: "foo.conf",
src: "foo.conf",
@@ -246,14 +196,14 @@
`)
buildOS := android.BuildOs.String()
- p := ctx.ModuleForTests("foo.conf", buildOS+"_common").Module().(*PrebuiltEtc)
+ p := result.Module("foo.conf", buildOS+"_common").(*PrebuiltEtc)
if !p.Host() {
t.Errorf("host bit is not set for a prebuilt_etc_host module.")
}
}
func TestPrebuiltUserShareInstallDirPath(t *testing.T) {
- ctx, _ := testPrebuiltEtc(t, `
+ result := prebuiltEtcFixtureFactory.RunTestWithBp(t, `
prebuilt_usr_share {
name: "foo.conf",
src: "foo.conf",
@@ -261,15 +211,13 @@
}
`)
- p := ctx.ModuleForTests("foo.conf", "android_arm64_armv8-a").Module().(*PrebuiltEtc)
+ p := result.Module("foo.conf", "android_arm64_armv8-a").(*PrebuiltEtc)
expected := buildDir + "/target/product/test_device/system/usr/share/bar"
- if p.installDirPath.String() != expected {
- t.Errorf("expected %q, got %q", expected, p.installDirPath.String())
- }
+ android.AssertStringEquals(t, "install dir", expected, p.installDirPath.String())
}
func TestPrebuiltUserShareHostInstallDirPath(t *testing.T) {
- ctx, config := testPrebuiltEtc(t, `
+ result := prebuiltEtcFixtureFactory.RunTestWithBp(t, `
prebuilt_usr_share_host {
name: "foo.conf",
src: "foo.conf",
@@ -278,26 +226,22 @@
`)
buildOS := android.BuildOs.String()
- p := ctx.ModuleForTests("foo.conf", buildOS+"_common").Module().(*PrebuiltEtc)
- expected := filepath.Join(buildDir, "host", config.PrebuiltOS(), "usr", "share", "bar")
- if p.installDirPath.String() != expected {
- t.Errorf("expected %q, got %q", expected, p.installDirPath.String())
- }
+ p := result.Module("foo.conf", buildOS+"_common").(*PrebuiltEtc)
+ expected := filepath.Join(buildDir, "host", result.Config.PrebuiltOS(), "usr", "share", "bar")
+ android.AssertStringEquals(t, "install dir", expected, p.installDirPath.String())
}
func TestPrebuiltFontInstallDirPath(t *testing.T) {
- ctx, _ := testPrebuiltEtc(t, `
+ result := prebuiltEtcFixtureFactory.RunTestWithBp(t, `
prebuilt_font {
name: "foo.conf",
src: "foo.conf",
}
`)
- p := ctx.ModuleForTests("foo.conf", "android_arm64_armv8-a").Module().(*PrebuiltEtc)
+ p := result.Module("foo.conf", "android_arm64_armv8-a").(*PrebuiltEtc)
expected := buildDir + "/target/product/test_device/system/fonts"
- if p.installDirPath.String() != expected {
- t.Errorf("expected %q, got %q", expected, p.installDirPath.String())
- }
+ android.AssertStringEquals(t, "install dir", expected, p.installDirPath.String())
}
func TestPrebuiltFirmwareDirPath(t *testing.T) {
@@ -327,11 +271,9 @@
}}
for _, tt := range tests {
t.Run(tt.description, func(t *testing.T) {
- ctx, _ := testPrebuiltEtc(t, tt.config)
- p := ctx.ModuleForTests("foo.conf", "android_arm64_armv8-a").Module().(*PrebuiltEtc)
- if p.installDirPath.String() != tt.expectedPath {
- t.Errorf("expected %q, got %q", tt.expectedPath, p.installDirPath)
- }
+ result := prebuiltEtcFixtureFactory.RunTestWithBp(t, tt.config)
+ p := result.Module("foo.conf", "android_arm64_armv8-a").(*PrebuiltEtc)
+ android.AssertStringEquals(t, "install dir", tt.expectedPath, p.installDirPath.String())
})
}
}
@@ -363,11 +305,9 @@
}}
for _, tt := range tests {
t.Run(tt.description, func(t *testing.T) {
- ctx, _ := testPrebuiltEtc(t, tt.config)
- p := ctx.ModuleForTests("foo.conf", "android_arm64_armv8-a").Module().(*PrebuiltEtc)
- if p.installDirPath.String() != tt.expectedPath {
- t.Errorf("expected %q, got %q", tt.expectedPath, p.installDirPath)
- }
+ result := prebuiltEtcFixtureFactory.RunTestWithBp(t, tt.config)
+ p := result.Module("foo.conf", "android_arm64_armv8-a").(*PrebuiltEtc)
+ android.AssertStringEquals(t, "install dir", tt.expectedPath, p.installDirPath.String())
})
}
}
diff --git a/filesystem/bootimg.go b/filesystem/bootimg.go
index 4e58737..372a610 100644
--- a/filesystem/bootimg.go
+++ b/filesystem/bootimg.go
@@ -157,7 +157,7 @@
if vendor {
flag = "--vendor_cmdline "
}
- cmd.FlagWithArg(flag, "\""+proptools.ShellEscape(cmdline)+"\"")
+ cmd.FlagWithArg(flag, proptools.ShellEscapeIncludingSpaces(cmdline))
}
headerVersion := proptools.String(b.properties.Header_version)
@@ -254,3 +254,13 @@
func (b *bootimg) OutputPath() android.Path {
return b.output
}
+
+var _ android.OutputFileProducer = (*bootimg)(nil)
+
+// Implements android.OutputFileProducer
+func (b *bootimg) OutputFiles(tag string) (android.Paths, error) {
+ if tag == "" {
+ return []android.Path{b.output}, nil
+ }
+ return nil, fmt.Errorf("unsupported module reference tag %q", tag)
+}
diff --git a/filesystem/logical_partition.go b/filesystem/logical_partition.go
index e547203..16b6037 100644
--- a/filesystem/logical_partition.go
+++ b/filesystem/logical_partition.go
@@ -208,3 +208,13 @@
func (l *logicalPartition) OutputPath() android.Path {
return l.output
}
+
+var _ android.OutputFileProducer = (*logicalPartition)(nil)
+
+// Implements android.OutputFileProducer
+func (l *logicalPartition) OutputFiles(tag string) (android.Paths, error) {
+ if tag == "" {
+ return []android.Path{l.output}, nil
+ }
+ return nil, fmt.Errorf("unsupported module reference tag %q", tag)
+}
diff --git a/genrule/genrule.go b/genrule/genrule.go
index 50c77cf..5349906 100644
--- a/genrule/genrule.go
+++ b/genrule/genrule.go
@@ -37,6 +37,27 @@
RegisterGenruleBuildComponents(android.InitRegistrationContext)
}
+// Test fixture preparer that will register most genrule build components.
+//
+// Singletons and mutators should only be added here if they are needed for a majority of genrule
+// module types, otherwise they should be added under a separate preparer to allow them to be
+// selected only when needed to reduce test execution time.
+//
+// Module types do not have much of an overhead unless they are used so this should include as many
+// module types as possible. The exceptions are those module types that require mutators and/or
+// singletons in order to function in which case they should be kept together in a separate
+// preparer.
+var PrepareForTestWithGenRuleBuildComponents = android.GroupFixturePreparers(
+ android.FixtureRegisterWithContext(RegisterGenruleBuildComponents),
+)
+
+// Prepare a fixture to use all genrule module types, mutators and singletons fully.
+//
+// This should only be used by tests that want to run with as much of the build enabled as possible.
+var PrepareForIntegrationTestWithGenrule = android.GroupFixturePreparers(
+ PrepareForTestWithGenRuleBuildComponents,
+)
+
func RegisterGenruleBuildComponents(ctx android.RegistrationContext) {
ctx.RegisterModuleType("genrule_defaults", defaultsFactory)
diff --git a/genrule/genrule_test.go b/genrule/genrule_test.go
index 2f5605e..690277c 100644
--- a/genrule/genrule_test.go
+++ b/genrule/genrule_test.go
@@ -17,8 +17,7 @@
import (
"io/ioutil"
"os"
- "reflect"
- "strings"
+ "regexp"
"testing"
"android/soong/android"
@@ -51,22 +50,30 @@
os.Exit(run())
}
-func testContext(config android.Config) *android.TestContext {
+var genruleFixtureFactory = android.NewFixtureFactory(
+ &buildDir,
+ android.PrepareForTestWithArchMutator,
+ android.PrepareForTestWithDefaults,
- ctx := android.NewTestArchContext(config)
- ctx.RegisterModuleType("filegroup", android.FileGroupFactory)
- ctx.RegisterModuleType("tool", toolFactory)
+ android.PrepareForTestWithFilegroup,
+ PrepareForTestWithGenRuleBuildComponents,
+ android.FixtureRegisterWithContext(func(ctx android.RegistrationContext) {
+ ctx.RegisterModuleType("tool", toolFactory)
+ }),
+ android.FixtureMergeMockFs(android.MockFS{
+ "tool": nil,
+ "tool_file1": nil,
+ "tool_file2": nil,
+ "in1": nil,
+ "in2": nil,
+ "in1.txt": nil,
+ "in2.txt": nil,
+ "in3.txt": nil,
+ }),
+)
- RegisterGenruleBuildComponents(ctx)
-
- ctx.PreArchMutators(android.RegisterDefaultsPreArchMutators)
- ctx.Register()
-
- return ctx
-}
-
-func testConfig(bp string, fs map[string][]byte) android.Config {
- bp += `
+func testGenruleBp() string {
+ return `
tool {
name: "tool",
}
@@ -105,23 +112,6 @@
name: "empty",
}
`
-
- mockFS := map[string][]byte{
- "tool": nil,
- "tool_file1": nil,
- "tool_file2": nil,
- "in1": nil,
- "in2": nil,
- "in1.txt": nil,
- "in2.txt": nil,
- "in3.txt": nil,
- }
-
- for k, v := range fs {
- mockFS[k] = v
- }
-
- return android.TestArchConfig(buildDir, nil, bp, mockFS)
}
func TestGenruleCmd(t *testing.T) {
@@ -466,38 +456,28 @@
bp += test.prop
bp += "}\n"
- config := testConfig(bp, nil)
- config.TestProductVariables.Allow_missing_dependencies = proptools.BoolPtr(test.allowMissingDependencies)
-
- ctx := testContext(config)
- ctx.SetAllowMissingDependencies(test.allowMissingDependencies)
-
- _, errs := ctx.ParseFileList(".", []string{"Android.bp"})
- if errs == nil {
- _, errs = ctx.PrepareBuildActions(config)
+ var expectedErrors []string
+ if test.err != "" {
+ expectedErrors = append(expectedErrors, regexp.QuoteMeta(test.err))
}
- if errs == nil && test.err != "" {
- t.Fatalf("want error %q, got no error", test.err)
- } else if errs != nil && test.err == "" {
- android.FailIfErrored(t, errs)
- } else if test.err != "" {
- if len(errs) != 1 {
- t.Errorf("want 1 error, got %d errors:", len(errs))
- for _, err := range errs {
- t.Errorf(" %s", err.Error())
- }
- t.FailNow()
- }
- if !strings.Contains(errs[0].Error(), test.err) {
- t.Fatalf("want %q, got %q", test.err, errs[0].Error())
- }
+
+ result := genruleFixtureFactory.Extend(
+ android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
+ variables.Allow_missing_dependencies = proptools.BoolPtr(test.allowMissingDependencies)
+ }),
+ android.FixtureModifyContext(func(ctx *android.TestContext) {
+ ctx.SetAllowMissingDependencies(test.allowMissingDependencies)
+ }),
+ ).
+ ExtendWithErrorHandler(android.FixtureExpectsAllErrorsToMatchAPattern(expectedErrors)).
+ RunTestWithBp(t, testGenruleBp()+bp)
+
+ if expectedErrors != nil {
return
}
- gen := ctx.ModuleForTests("gen", "").Module().(*Module)
- if g, w := gen.rawCommands[0], test.expect; w != g {
- t.Errorf("want %q, got %q", w, g)
- }
+ gen := result.Module("gen", "").(*Module)
+ android.AssertStringEquals(t, "raw commands", test.expect, gen.rawCommands[0])
})
}
}
@@ -557,25 +537,15 @@
},
}
- config := testConfig(bp, nil)
- ctx := testContext(config)
- _, errs := ctx.ParseFileList(".", []string{"Android.bp"})
- if errs == nil {
- _, errs = ctx.PrepareBuildActions(config)
- }
- if errs != nil {
- t.Fatal(errs)
- }
+ result := genruleFixtureFactory.RunTestWithBp(t, testGenruleBp()+bp)
for _, test := range testcases {
t.Run(test.name, func(t *testing.T) {
- gen := ctx.ModuleForTests(test.name, "")
+ gen := result.ModuleForTests(test.name, "")
manifest := android.RuleBuilderSboxProtoForTests(t, gen.Output("genrule.sbox.textproto"))
hash := manifest.Commands[0].GetInputHash()
- if g, w := hash, test.expectedHash; g != w {
- t.Errorf("Expected has %q, got %q", w, g)
- }
+ android.AssertStringEquals(t, "hash", test.expectedHash, hash)
})
}
}
@@ -630,46 +600,27 @@
bp += test.prop
bp += "}\n"
- config := testConfig(bp, nil)
- ctx := testContext(config)
-
- _, errs := ctx.ParseFileList(".", []string{"Android.bp"})
- if errs == nil {
- _, errs = ctx.PrepareBuildActions(config)
+ var expectedErrors []string
+ if test.err != "" {
+ expectedErrors = append(expectedErrors, regexp.QuoteMeta(test.err))
}
- if errs == nil && test.err != "" {
- t.Fatalf("want error %q, got no error", test.err)
- } else if errs != nil && test.err == "" {
- android.FailIfErrored(t, errs)
- } else if test.err != "" {
- if len(errs) != 1 {
- t.Errorf("want 1 error, got %d errors:", len(errs))
- for _, err := range errs {
- t.Errorf(" %s", err.Error())
- }
- t.FailNow()
- }
- if !strings.Contains(errs[0].Error(), test.err) {
- t.Fatalf("want %q, got %q", test.err, errs[0].Error())
- }
+
+ result := genruleFixtureFactory.
+ ExtendWithErrorHandler(android.FixtureExpectsAllErrorsToMatchAPattern(expectedErrors)).
+ RunTestWithBp(t, testGenruleBp()+bp)
+
+ if expectedErrors != nil {
return
}
- gen := ctx.ModuleForTests("gen", "").Module().(*Module)
- if g, w := gen.rawCommands, test.cmds; !reflect.DeepEqual(w, g) {
- t.Errorf("want %q, got %q", w, g)
- }
+ gen := result.Module("gen", "").(*Module)
+ android.AssertDeepEquals(t, "cmd", test.cmds, gen.rawCommands)
- if g, w := gen.outputDeps.Strings(), test.deps; !reflect.DeepEqual(w, g) {
- t.Errorf("want deps %q, got %q", w, g)
- }
+ android.AssertDeepEquals(t, "deps", test.deps, gen.outputDeps.Strings())
- if g, w := gen.outputFiles.Strings(), test.files; !reflect.DeepEqual(w, g) {
- t.Errorf("want files %q, got %q", w, g)
- }
+ android.AssertDeepEquals(t, "files", test.files, gen.outputFiles.Strings())
})
}
-
}
func TestGenruleDefaults(t *testing.T) {
@@ -690,26 +641,16 @@
defaults: ["gen_defaults1", "gen_defaults2"],
}
`
- config := testConfig(bp, nil)
- ctx := testContext(config)
- _, errs := ctx.ParseFileList(".", []string{"Android.bp"})
- if errs == nil {
- _, errs = ctx.PrepareBuildActions(config)
- }
- if errs != nil {
- t.Fatal(errs)
- }
- gen := ctx.ModuleForTests("gen", "").Module().(*Module)
+
+ result := genruleFixtureFactory.RunTestWithBp(t, testGenruleBp()+bp)
+
+ gen := result.Module("gen", "").(*Module)
expectedCmd := "cp in1 __SBOX_SANDBOX_DIR__/out/out"
- if gen.rawCommands[0] != expectedCmd {
- t.Errorf("Expected cmd: %q, actual: %q", expectedCmd, gen.rawCommands[0])
- }
+ android.AssertStringEquals(t, "cmd", expectedCmd, gen.rawCommands[0])
expectedSrcs := []string{"in1"}
- if !reflect.DeepEqual(expectedSrcs, gen.properties.Srcs) {
- t.Errorf("Expected srcs: %q, actual: %q", expectedSrcs, gen.properties.Srcs)
- }
+ android.AssertDeepEquals(t, "srcs", expectedSrcs, gen.properties.Srcs)
}
func TestGenruleWithBazel(t *testing.T) {
@@ -721,29 +662,18 @@
}
`
- config := testConfig(bp, nil)
- config.BazelContext = android.MockBazelContext{
- AllFiles: map[string][]string{
- "//foo/bar:bar": []string{"bazelone.txt", "bazeltwo.txt"}}}
+ result := genruleFixtureFactory.Extend(android.FixtureModifyConfig(func(config android.Config) {
+ config.BazelContext = android.MockBazelContext{
+ AllFiles: map[string][]string{
+ "//foo/bar:bar": []string{"bazelone.txt", "bazeltwo.txt"}}}
+ })).RunTestWithBp(t, testGenruleBp()+bp)
- ctx := testContext(config)
- _, errs := ctx.ParseFileList(".", []string{"Android.bp"})
- if errs == nil {
- _, errs = ctx.PrepareBuildActions(config)
- }
- if errs != nil {
- t.Fatal(errs)
- }
- gen := ctx.ModuleForTests("foo", "").Module().(*Module)
+ gen := result.Module("foo", "").(*Module)
expectedOutputFiles := []string{"outputbase/execroot/__main__/bazelone.txt",
"outputbase/execroot/__main__/bazeltwo.txt"}
- if !reflect.DeepEqual(gen.outputFiles.Strings(), expectedOutputFiles) {
- t.Errorf("Expected output files: %q, actual: %q", expectedOutputFiles, gen.outputFiles)
- }
- if !reflect.DeepEqual(gen.outputDeps.Strings(), expectedOutputFiles) {
- t.Errorf("Expected output deps: %q, actual: %q", expectedOutputFiles, gen.outputDeps)
- }
+ android.AssertDeepEquals(t, "output files", expectedOutputFiles, gen.outputFiles.Strings())
+ android.AssertDeepEquals(t, "output deps", expectedOutputFiles, gen.outputDeps.Strings())
}
type testTool struct {
diff --git a/java/Android.bp b/java/Android.bp
index 461b16d..9e2db83 100644
--- a/java/Android.bp
+++ b/java/Android.bp
@@ -78,6 +78,7 @@
"plugin_test.go",
"rro_test.go",
"sdk_test.go",
+ "system_modules_test.go",
],
pluginFor: ["soong_build"],
}
diff --git a/java/app.go b/java/app.go
index 2d918e9..eef627c 100755
--- a/java/app.go
+++ b/java/app.go
@@ -122,8 +122,8 @@
// or an android_app_certificate module name in the form ":module".
Certificate *string
- // Name of the signing certificate lineage file.
- Lineage *string
+ // Name of the signing certificate lineage file or filegroup module.
+ Lineage *string `android:"path"`
// the package name of this app. The package name in the manifest file is used if one was not given.
Package_name *string
@@ -812,6 +812,13 @@
depsInfo := android.DepNameToDepInfoMap{}
a.WalkPayloadDeps(ctx, func(ctx android.ModuleContext, from blueprint.Module, to android.ApexModule, externalDep bool) bool {
depName := to.Name()
+
+ // Skip dependencies that are only available to APEXes; they are developed with updatability
+ // in mind and don't need manual approval.
+ if to.(android.ApexModule).NotAvailableForPlatform() {
+ return true
+ }
+
if info, exist := depsInfo[depName]; exist {
info.From = append(info.From, from.Name())
info.IsExternal = info.IsExternal && externalDep
@@ -1280,6 +1287,14 @@
outputFile := android.PathForModuleOut(ctx, "manifest_check", "AndroidManifest.xml")
statusFile := dexpreopt.UsesLibrariesStatusFile(ctx)
+ // Disable verify_uses_libraries check if dexpreopt is globally disabled. Without dexpreopt the
+ // check is not necessary, and although it is good to have, it is difficult to maintain on
+ // non-linux build platforms where dexpreopt is generally disabled (the check may fail due to
+ // various unrelated reasons, such as a failure to get manifest from an APK).
+ if dexpreopt.GetGlobalConfig(ctx).DisablePreopt {
+ return manifest
+ }
+
rule := android.NewRuleBuilder(pctx, ctx)
cmd := rule.Command().BuiltTool("manifest_check").
Flag("--enforce-uses-libraries").
@@ -1310,6 +1325,14 @@
outputFile := android.PathForModuleOut(ctx, "verify_uses_libraries", apk.Base())
statusFile := dexpreopt.UsesLibrariesStatusFile(ctx)
+ // Disable verify_uses_libraries check if dexpreopt is globally disabled. Without dexpreopt the
+ // check is not necessary, and although it is good to have, it is difficult to maintain on
+ // non-linux build platforms where dexpreopt is generally disabled (the check may fail due to
+ // various unrelated reasons, such as a failure to get manifest from an APK).
+ if dexpreopt.GetGlobalConfig(ctx).DisablePreopt {
+ return apk
+ }
+
rule := android.NewRuleBuilder(pctx, ctx)
aapt := ctx.Config().HostToolPath(ctx, "aapt")
rule.Command().
diff --git a/java/app_import.go b/java/app_import.go
index d69dd10..d4da64d 100644
--- a/java/app_import.go
+++ b/java/app_import.go
@@ -67,12 +67,15 @@
// module name in the form ":module". Should be empty if presigned or default_dev_cert is set.
Certificate *string
+ // Names of extra android_app_certificate modules to sign the apk with in the form ":module".
+ Additional_certificates []string
+
// Set this flag to true if the prebuilt apk is already signed. The certificate property must not
// be set for presigned modules.
Presigned *bool
- // Name of the signing certificate lineage file.
- Lineage *string
+ // Name of the signing certificate lineage file or filegroup module.
+ Lineage *string `android:"path"`
// Sign with the default system dev certificate. Must be used judiciously. Most imported apps
// need to either specify a specific certificate or be presigned.
@@ -156,6 +159,16 @@
ctx.AddDependency(ctx.Module(), certificateTag, cert)
}
+ for _, cert := range a.properties.Additional_certificates {
+ cert = android.SrcIsModule(cert)
+ if cert != "" {
+ ctx.AddDependency(ctx.Module(), certificateTag, cert)
+ } else {
+ ctx.PropertyErrorf("additional_certificates",
+ `must be names of android_app_certificate modules in the form ":module"`)
+ }
+ }
+
a.usesLibrary.deps(ctx, !a.isPrebuiltFrameworkRes())
}
@@ -303,9 +316,6 @@
// If the certificate property is empty at this point, default_dev_cert must be set to true.
// Which makes processMainCert's behavior for the empty cert string WAI.
certificates = processMainCert(a.ModuleBase, String(a.properties.Certificate), certificates, ctx)
- if len(certificates) != 1 {
- ctx.ModuleErrorf("Unexpected number of certificates were extracted: %q", certificates)
- }
a.certificate = certificates[0]
signed := android.PathForModuleOut(ctx, "signed", apkFilename)
var lineageFile android.Path
diff --git a/java/app_import_test.go b/java/app_import_test.go
index dc31d07..cae41d0 100644
--- a/java/app_import_test.go
+++ b/java/app_import_test.go
@@ -109,14 +109,54 @@
name: "foo",
apk: "prebuilts/apk/app.apk",
certificate: "platform",
+ additional_certificates: [":additional_certificate"],
lineage: "lineage.bin",
}
+
+ android_app_certificate {
+ name: "additional_certificate",
+ certificate: "cert/additional_cert",
+ }
`)
variant := ctx.ModuleForTests("foo", "android_common")
- // Check cert signing lineage flag.
signedApk := variant.Output("signed/foo.apk")
+ // Check certificates
+ certificatesFlag := signedApk.Args["certificates"]
+ expected := "build/make/target/product/security/platform.x509.pem " +
+ "build/make/target/product/security/platform.pk8 " +
+ "cert/additional_cert.x509.pem cert/additional_cert.pk8"
+ if expected != certificatesFlag {
+ t.Errorf("Incorrect certificates flags, expected: %q, got: %q", expected, certificatesFlag)
+ }
+ // Check cert signing lineage flag.
+ signingFlag := signedApk.Args["flags"]
+ expected = "--lineage lineage.bin"
+ if expected != signingFlag {
+ t.Errorf("Incorrect signing flags, expected: %q, got: %q", expected, signingFlag)
+ }
+}
+
+func TestAndroidAppImport_SigningLineageFilegroup(t *testing.T) {
+ ctx, _ := testJava(t, `
+ android_app_import {
+ name: "foo",
+ apk: "prebuilts/apk/app.apk",
+ certificate: "platform",
+ lineage: ":lineage_bin",
+ }
+
+ filegroup {
+ name: "lineage_bin",
+ srcs: ["lineage.bin"],
+ }
+ `)
+
+ variant := ctx.ModuleForTests("foo", "android_common")
+
+ signedApk := variant.Output("signed/foo.apk")
+ // Check cert signing lineage flag.
signingFlag := signedApk.Args["flags"]
expected := "--lineage lineage.bin"
if expected != signingFlag {
diff --git a/java/app_test.go b/java/app_test.go
index f41047a..78e1a57 100644
--- a/java/app_test.go
+++ b/java/app_test.go
@@ -1576,6 +1576,31 @@
expectedLineage: "--lineage lineage.bin",
expectedCertificate: "cert/new_cert.x509.pem cert/new_cert.pk8",
},
+ {
+ name: "lineage from filegroup",
+ bp: `
+ android_app {
+ name: "foo",
+ srcs: ["a.java"],
+ certificate: ":new_certificate",
+ lineage: ":lineage_bin",
+ sdk_version: "current",
+ }
+
+ android_app_certificate {
+ name: "new_certificate",
+ certificate: "cert/new_cert",
+ }
+
+ filegroup {
+ name: "lineage_bin",
+ srcs: ["lineage.bin"],
+ }
+ `,
+ certificateOverride: "",
+ expectedLineage: "--lineage lineage.bin",
+ expectedCertificate: "cert/new_cert.x509.pem cert/new_cert.pk8",
+ },
}
for _, test := range testCases {
diff --git a/java/boot_image.go b/java/boot_image.go
index 8a1e3c9..12e2874 100644
--- a/java/boot_image.go
+++ b/java/boot_image.go
@@ -25,10 +25,18 @@
func init() {
RegisterBootImageBuildComponents(android.InitRegistrationContext)
+
+ android.RegisterSdkMemberType(&bootImageMemberType{
+ SdkMemberTypeBase: android.SdkMemberTypeBase{
+ PropertyName: "boot_images",
+ SupportsSdk: true,
+ },
+ })
}
func RegisterBootImageBuildComponents(ctx android.RegistrationContext) {
ctx.RegisterModuleType("boot_image", bootImageFactory)
+ ctx.RegisterModuleType("prebuilt_boot_image", prebuiltBootImageFactory)
}
type bootImageProperties struct {
@@ -41,7 +49,7 @@
type BootImageModule struct {
android.ModuleBase
android.ApexModuleBase
-
+ android.SdkBase
properties bootImageProperties
}
@@ -50,6 +58,7 @@
m.AddProperties(&m.properties)
android.InitAndroidArchModule(m, android.HostAndDeviceSupported, android.MultilibCommon)
android.InitApexModule(m)
+ android.InitSdkAwareModule(m)
return m
}
@@ -138,3 +147,74 @@
// Make it available for other modules.
ctx.SetProvider(BootImageInfoProvider, info)
}
+
+type bootImageMemberType struct {
+ android.SdkMemberTypeBase
+}
+
+func (b *bootImageMemberType) AddDependencies(mctx android.BottomUpMutatorContext, dependencyTag blueprint.DependencyTag, names []string) {
+ mctx.AddVariationDependencies(nil, dependencyTag, names...)
+}
+
+func (b *bootImageMemberType) IsInstance(module android.Module) bool {
+ _, ok := module.(*BootImageModule)
+ return ok
+}
+
+func (b *bootImageMemberType) AddPrebuiltModule(ctx android.SdkMemberContext, member android.SdkMember) android.BpModule {
+ return ctx.SnapshotBuilder().AddPrebuiltModule(member, "prebuilt_boot_image")
+}
+
+func (b *bootImageMemberType) CreateVariantPropertiesStruct() android.SdkMemberProperties {
+ return &bootImageSdkMemberProperties{}
+}
+
+type bootImageSdkMemberProperties struct {
+ android.SdkMemberPropertiesBase
+
+ Image_name string
+}
+
+func (b *bootImageSdkMemberProperties) PopulateFromVariant(ctx android.SdkMemberContext, variant android.Module) {
+ module := variant.(*BootImageModule)
+
+ b.Image_name = module.properties.Image_name
+}
+
+func (b *bootImageSdkMemberProperties) AddToPropertySet(ctx android.SdkMemberContext, propertySet android.BpPropertySet) {
+ if b.Image_name != "" {
+ propertySet.AddProperty("image_name", b.Image_name)
+ }
+}
+
+var _ android.SdkMemberType = (*bootImageMemberType)(nil)
+
+// A prebuilt version of the boot image module.
+//
+// At the moment this is basically just a boot image module that can be used as a prebuilt.
+// Eventually as more functionality is migrated into the boot image module from the singleton then
+// this will diverge.
+type prebuiltBootImageModule struct {
+ BootImageModule
+ prebuilt android.Prebuilt
+}
+
+func (module *prebuiltBootImageModule) Prebuilt() *android.Prebuilt {
+ return &module.prebuilt
+}
+
+func (module *prebuiltBootImageModule) Name() string {
+ return module.prebuilt.Name(module.ModuleBase.Name())
+}
+
+func prebuiltBootImageFactory() android.Module {
+ m := &prebuiltBootImageModule{}
+ m.AddProperties(&m.properties)
+ android.InitAndroidArchModule(m, android.HostAndDeviceSupported, android.MultilibCommon)
+ // This doesn't actually have any prebuilt files of its own so pass a placeholder for the srcs
+ // array.
+ android.InitPrebuiltModule(m, &[]string{"placeholder"})
+ android.InitApexModule(m)
+ android.InitSdkAwareModule(m)
+ return m
+}
diff --git a/java/boot_image_test.go b/java/boot_image_test.go
index a295782..65e590d 100644
--- a/java/boot_image_test.go
+++ b/java/boot_image_test.go
@@ -29,3 +29,12 @@
}
`)
}
+
+func TestUnknownPrebuiltBootImage(t *testing.T) {
+ testJavaError(t, "image_name: Unknown image name \\\"unknown\\\", expected one of art, boot", `
+ prebuilt_boot_image {
+ name: "unknown-boot-image",
+ image_name: "unknown",
+ }
+`)
+}
diff --git a/java/dexpreopt_bootjars_test.go b/java/dexpreopt_bootjars_test.go
index 48bc244..1b910fa 100644
--- a/java/dexpreopt_bootjars_test.go
+++ b/java/dexpreopt_bootjars_test.go
@@ -16,7 +16,6 @@
import (
"path/filepath"
- "reflect"
"sort"
"testing"
@@ -44,17 +43,11 @@
}
`
- config := testConfig(nil, bp, nil)
+ result := javaFixtureFactory.
+ Extend(dexpreopt.FixtureSetBootJars("platform:foo", "platform:bar", "platform:baz")).
+ RunTestWithBp(t, bp)
- pathCtx := android.PathContextForTesting(config)
- dexpreoptConfig := dexpreopt.GlobalConfigForTests(pathCtx)
- dexpreoptConfig.BootJars = android.CreateTestConfiguredJarList([]string{"platform:foo", "platform:bar", "platform:baz"})
- dexpreopt.SetTestGlobalConfig(config, dexpreoptConfig)
-
- ctx := testContext(config)
- run(t, ctx, config)
-
- dexpreoptBootJars := ctx.SingletonForTests("dex_bootjars")
+ dexpreoptBootJars := result.SingletonForTests("dex_bootjars")
rule := dexpreoptBootJars.Output(ruleFile)
for i := range expectedInputs {
@@ -73,13 +66,9 @@
sort.Strings(outputs)
sort.Strings(expectedOutputs)
- if !reflect.DeepEqual(inputs, expectedInputs) {
- t.Errorf("want inputs %q\n got inputs %q", expectedInputs, inputs)
- }
+ android.AssertDeepEquals(t, "inputs", expectedInputs, inputs)
- if !reflect.DeepEqual(outputs, expectedOutputs) {
- t.Errorf("want outputs %q\n got outputs %q", expectedOutputs, outputs)
- }
+ android.AssertDeepEquals(t, "outputs", expectedOutputs, outputs)
}
func TestDexpreoptBootJars(t *testing.T) {
diff --git a/java/droiddoc.go b/java/droiddoc.go
index 8f1644c..f0decec 100644
--- a/java/droiddoc.go
+++ b/java/droiddoc.go
@@ -1203,8 +1203,14 @@
}
func metalavaCmd(ctx android.ModuleContext, rule *android.RuleBuilder, javaVersion javaVersion, srcs android.Paths,
- srcJarList android.Path, bootclasspath, classpath classpath, sourcepaths android.Paths, implicitsRsp android.WritablePath, sandbox bool) *android.RuleBuilderCommand {
+ srcJarList android.Path, bootclasspath, classpath classpath, sourcepaths android.Paths,
+ implicitsRsp, homeDir android.WritablePath, sandbox bool) *android.RuleBuilderCommand {
+ rule.Command().Text("rm -rf").Flag(homeDir.String())
+ rule.Command().Text("mkdir -p").Flag(homeDir.String())
+
cmd := rule.Command()
+ cmd.FlagWithArg("ANDROID_SDK_HOME=", homeDir.String())
+
if ctx.Config().UseRBE() && ctx.Config().IsEnvTrue("RBE_METALAVA") {
rule.Remoteable(android.RemoteRuleSupports{RBE: true})
pool := ctx.Config().GetenvWithDefault("RBE_METALAVA_POOL", "metalava")
@@ -1214,17 +1220,21 @@
execStrategy = remoteexec.LocalExecStrategy
labels["shallow"] = "true"
}
- inputs := []string{android.PathForOutput(ctx, "host", ctx.Config().PrebuiltOS(), "framework", "metalava.jar").String()}
+ inputs := []string{
+ ctx.Config().HostJavaToolPath(ctx, "metalava").String(),
+ homeDir.String(),
+ }
if v := ctx.Config().Getenv("RBE_METALAVA_INPUTS"); v != "" {
inputs = append(inputs, strings.Split(v, ",")...)
}
cmd.Text((&remoteexec.REParams{
- Labels: labels,
- ExecStrategy: execStrategy,
- Inputs: inputs,
- RSPFile: implicitsRsp.String(),
- ToolchainInputs: []string{config.JavaCmd(ctx).String()},
- Platform: map[string]string{remoteexec.PoolKey: pool},
+ Labels: labels,
+ ExecStrategy: execStrategy,
+ Inputs: inputs,
+ RSPFile: implicitsRsp.String(),
+ ToolchainInputs: []string{config.JavaCmd(ctx).String()},
+ Platform: map[string]string{remoteexec.PoolKey: pool},
+ EnvironmentVariables: []string{"ANDROID_SDK_HOME"},
}).NoVarTemplate(ctx.Config()))
}
@@ -1302,9 +1312,9 @@
srcJarList := zipSyncCmd(ctx, rule, srcJarDir, d.Javadoc.srcJars)
implicitsRsp := android.PathForModuleOut(ctx, ctx.ModuleName()+"-"+"implicits.rsp")
-
+ homeDir := android.PathForModuleOut(ctx, "metalava-home")
cmd := metalavaCmd(ctx, rule, javaVersion, d.Javadoc.srcFiles, srcJarList,
- deps.bootClasspath, deps.classpath, d.Javadoc.sourcepaths, implicitsRsp,
+ deps.bootClasspath, deps.classpath, d.Javadoc.sourcepaths, implicitsRsp, homeDir,
Bool(d.Javadoc.properties.Sandbox))
cmd.Implicits(d.Javadoc.implicits)
diff --git a/java/java.go b/java/java.go
index 9e35835..036c7af 100644
--- a/java/java.go
+++ b/java/java.go
@@ -122,7 +122,16 @@
if sdkVersion.stable() {
return nil
}
- return fmt.Errorf("non stable SDK %v", sdkVersion)
+ if sdkVersion.kind == sdkCorePlatform {
+ if useLegacyCorePlatformApiByName(j.BaseModuleName()) {
+ return fmt.Errorf("non stable SDK %v - uses legacy core platform", sdkVersion)
+ } else {
+ // Treat stable core platform as stable.
+ return nil
+ }
+ } else {
+ return fmt.Errorf("non stable SDK %v", sdkVersion)
+ }
}
func (j *Module) checkSdkVersions(ctx android.ModuleContext) {
@@ -2499,7 +2508,7 @@
func (j *Test) GenerateAndroidBuildActions(ctx android.ModuleContext) {
if j.testProperties.Test_options.Unit_test == nil && ctx.Host() {
// TODO(b/): Clean temporary heuristic to avoid unexpected onboarding.
- defaultUnitTest := !inList("tradefed", j.properties.Static_libs) && !inList("tradefed", j.properties.Libs) && !inList("cts", j.testProperties.Test_suites) && !inList("robolectric-host-android_all", j.properties.Static_libs) && !inList("robolectric-host-android_all", j.properties.Libs)
+ defaultUnitTest := !inList("tradefed", j.properties.Static_libs) && !inList("tradefed", j.properties.Libs) && !inList("cts", j.testProperties.Test_suites)
j.testProperties.Test_options.Unit_test = proptools.BoolPtr(defaultUnitTest)
}
j.testConfig = tradefed.AutoGenJavaTestConfig(ctx, j.testProperties.Test_config, j.testProperties.Test_config_template,
@@ -3319,10 +3328,6 @@
// ],
// javacflags: ["-Xlint:all"],
// }
-func defaultsFactory() android.Module {
- return DefaultsFactory()
-}
-
func DefaultsFactory() android.Module {
module := &Defaults{}
diff --git a/java/java_test.go b/java/java_test.go
index 9112655..670eefc 100644
--- a/java/java_test.go
+++ b/java/java_test.go
@@ -48,6 +48,26 @@
os.RemoveAll(buildDir)
}
+// Factory to use to create fixtures for tests in this package.
+var javaFixtureFactory = android.NewFixtureFactory(
+ &buildDir,
+ genrule.PrepareForTestWithGenRuleBuildComponents,
+ // Get the CC build components but not default modules.
+ cc.PrepareForTestWithCcBuildComponents,
+ // Include all the default java modules.
+ PrepareForTestWithJavaDefaultModules,
+ android.FixtureRegisterWithContext(func(ctx android.RegistrationContext) {
+ ctx.RegisterModuleType("java_plugin", PluginFactory)
+ ctx.RegisterModuleType("python_binary_host", python.PythonBinaryHostFactory)
+
+ ctx.PreDepsMutators(python.RegisterPythonPreDepsMutators)
+ ctx.RegisterPreSingletonType("overlay", OverlaySingletonFactory)
+ ctx.RegisterPreSingletonType("sdk_versions", sdkPreSingletonFactory)
+ }),
+ javaMockFS().AddToFixture(),
+ dexpreopt.PrepareForTestWithDexpreopt,
+)
+
func TestMain(m *testing.M) {
run := func() int {
setUp()
@@ -59,10 +79,20 @@
os.Exit(run())
}
+// testConfig is a legacy way of creating a test Config for testing java modules.
+//
+// See testJava for an explanation as to how to stop using this deprecated method.
+//
+// deprecated
func testConfig(env map[string]string, bp string, fs map[string][]byte) android.Config {
return TestConfig(buildDir, env, bp, fs)
}
+// testContext is a legacy way of creating a TestContext for testing java modules.
+//
+// See testJava for an explanation as to how to stop using this deprecated method.
+//
+// deprecated
func testContext(config android.Config) *android.TestContext {
ctx := android.NewTestArchContext(config)
@@ -92,6 +122,11 @@
return ctx
}
+// run is a legacy way of running tests of java modules.
+//
+// See testJava for an explanation as to how to stop using this deprecated method.
+//
+// deprecated
func run(t *testing.T, ctx *android.TestContext, config android.Config) {
t.Helper()
@@ -105,23 +140,38 @@
android.FailIfErrored(t, errs)
}
+// testJavaError is a legacy way of running tests of java modules that expect errors.
+//
+// See testJava for an explanation as to how to stop using this deprecated method.
+//
+// deprecated
func testJavaError(t *testing.T, pattern string, bp string) (*android.TestContext, android.Config) {
t.Helper()
return testJavaErrorWithConfig(t, pattern, testConfig(nil, bp, nil))
}
+// testJavaErrorWithConfig is a legacy way of running tests of java modules that expect errors.
+//
+// See testJava for an explanation as to how to stop using this deprecated method.
+//
+// deprecated
func testJavaErrorWithConfig(t *testing.T, pattern string, config android.Config) (*android.TestContext, android.Config) {
t.Helper()
- ctx := testContext(config)
-
+ // This must be done on the supplied config and not as part of the fixture because any changes to
+ // the fixture's config will be ignored when RunTestWithConfig replaces it.
pathCtx := android.PathContextForTesting(config)
dexpreopt.SetTestGlobalConfig(config, dexpreopt.GlobalConfigForTests(pathCtx))
-
- runWithErrors(t, ctx, config, pattern)
-
- return ctx, config
+ result := javaFixtureFactory.
+ ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern(pattern)).
+ RunTestWithConfig(t, config)
+ return result.TestContext, result.Config
}
+// runWithErrors is a legacy way of running tests of java modules that expect errors.
+//
+// See testJava for an explanation as to how to stop using this deprecated method.
+//
+// deprecated
func runWithErrors(t *testing.T, ctx *android.TestContext, config android.Config, pattern string) {
ctx.Register()
_, errs := ctx.ParseBlueprintsFiles("Android.bp")
@@ -139,22 +189,43 @@
return
}
-func testJavaWithFS(t *testing.T, bp string, fs map[string][]byte) (*android.TestContext, android.Config) {
+// testJavaWithFS runs tests using the javaFixtureFactory
+//
+// See testJava for an explanation as to how to stop using this deprecated method.
+//
+// deprecated
+func testJavaWithFS(t *testing.T, bp string, fs android.MockFS) (*android.TestContext, android.Config) {
t.Helper()
- return testJavaWithConfig(t, testConfig(nil, bp, fs))
+ result := javaFixtureFactory.Extend(fs.AddToFixture()).RunTestWithBp(t, bp)
+ return result.TestContext, result.Config
}
+// testJava runs tests using the javaFixtureFactory
+//
+// Do not add any new usages of this, instead use the javaFixtureFactory directly as it makes it
+// much easier to customize the test behavior.
+//
+// If it is necessary to customize the behavior of an existing test that uses this then please first
+// convert the test to using javaFixtureFactory first and then in a following change add the
+// appropriate fixture preparers. Keeping the conversion change separate makes it easy to verify
+// that it did not change the test behavior unexpectedly.
+//
+// deprecated
func testJava(t *testing.T, bp string) (*android.TestContext, android.Config) {
t.Helper()
- return testJavaWithFS(t, bp, nil)
+ result := javaFixtureFactory.RunTestWithBp(t, bp)
+ return result.TestContext, result.Config
}
+// testJavaWithConfig runs tests using the javaFixtureFactory
+//
+// See testJava for an explanation as to how to stop using this deprecated method.
+//
+// deprecated
func testJavaWithConfig(t *testing.T, config android.Config) (*android.TestContext, android.Config) {
t.Helper()
- ctx := testContext(config)
- run(t, ctx, config)
-
- return ctx, config
+ result := javaFixtureFactory.RunTestWithConfig(t, config)
+ return result.TestContext, result.Config
}
func moduleToPath(name string) string {
@@ -168,6 +239,12 @@
}
}
+// defaultModuleToPath constructs a path to the turbine generate jar for a default test module that
+// is defined in PrepareForIntegrationTestWithJava
+func defaultModuleToPath(name string) string {
+ return filepath.Join(buildDir, ".intermediates", defaultJavaDir, name, "android_common", "turbine-combined", name+".jar")
+}
+
func TestJavaLinkType(t *testing.T) {
testJava(t, `
java_library {
@@ -2352,75 +2429,11 @@
expected := "java.base=.:" + buildDir
checkPatchModuleFlag(t, ctx, "bar", expected)
expected = "java.base=" + strings.Join([]string{
- ".", buildDir, "dir", "dir2", "nested", moduleToPath("ext"), moduleToPath("framework")}, ":")
+ ".", buildDir, "dir", "dir2", "nested", defaultModuleToPath("ext"), defaultModuleToPath("framework")}, ":")
checkPatchModuleFlag(t, ctx, "baz", expected)
})
}
-func TestJavaSystemModules(t *testing.T) {
- ctx, _ := testJava(t, `
- java_system_modules {
- name: "system-modules",
- libs: ["system-module1", "system-module2"],
- }
- java_library {
- name: "system-module1",
- srcs: ["a.java"],
- sdk_version: "none",
- system_modules: "none",
- }
- java_library {
- name: "system-module2",
- srcs: ["b.java"],
- sdk_version: "none",
- system_modules: "none",
- }
- `)
-
- // check the existence of the module
- systemModules := ctx.ModuleForTests("system-modules", "android_common")
-
- cmd := systemModules.Rule("jarsTosystemModules")
-
- // make sure the command compiles against the supplied modules.
- for _, module := range []string{"system-module1.jar", "system-module2.jar"} {
- if !strings.Contains(cmd.Args["classpath"], module) {
- t.Errorf("system modules classpath %v does not contain %q", cmd.Args["classpath"],
- module)
- }
- }
-}
-
-func TestJavaSystemModulesImport(t *testing.T) {
- ctx, _ := testJava(t, `
- java_system_modules_import {
- name: "system-modules",
- libs: ["system-module1", "system-module2"],
- }
- java_import {
- name: "system-module1",
- jars: ["a.jar"],
- }
- java_import {
- name: "system-module2",
- jars: ["b.jar"],
- }
- `)
-
- // check the existence of the module
- systemModules := ctx.ModuleForTests("system-modules", "android_common")
-
- cmd := systemModules.Rule("jarsTosystemModules")
-
- // make sure the command compiles against the supplied modules.
- for _, module := range []string{"system-module1.jar", "system-module2.jar"} {
- if !strings.Contains(cmd.Args["classpath"], module) {
- t.Errorf("system modules classpath %v does not contain %q", cmd.Args["classpath"],
- module)
- }
- }
-}
-
func TestJavaLibraryWithSystemModules(t *testing.T) {
ctx, _ := testJava(t, `
java_library {
diff --git a/java/legacy_core_platform_api_usage.go b/java/legacy_core_platform_api_usage.go
index 021920a..cae9dc5 100644
--- a/java/legacy_core_platform_api_usage.go
+++ b/java/legacy_core_platform_api_usage.go
@@ -19,10 +19,6 @@
"android/soong/java/config"
)
-// This variable is effectively unused in pre-master branches, and is
-// included (with the same value as it has in AOSP) only to ease
-// merges between branches (see the comment in the
-// useLegacyCorePlatformApi() function):
var legacyCorePlatformApiModules = []string{
"ahat-test-dump",
"android.car",
@@ -34,29 +30,44 @@
"art_cts_jvmti_test_library",
"art-gtest-jars-MyClassNatives",
"BackupFrameworksServicesRoboTests",
+ "backuplib",
"BandwidthEnforcementTest",
"BlockedNumberProvider",
"BluetoothInstrumentationTests",
"BluetoothMidiService",
+ "CarDeveloperOptions",
+ "CarService",
+ "CarServiceTest",
"car-apps-common",
+ "car-service-test-lib",
+ "car-service-test-static-lib",
"CertInstaller",
"ConnectivityManagerTest",
"ContactsProvider",
+ "CorePerfTests",
"core-tests-support",
+ "CtsAppExitTestCases",
"CtsContentTestCases",
"CtsIkeTestCases",
+ "CtsAppExitTestCases",
"CtsLibcoreWycheproofBCTestCases",
"CtsMediaTestCases",
"CtsNetTestCases",
"CtsNetTestCasesLatestSdk",
"CtsSecurityTestCases",
+ "CtsSuspendAppsTestCases",
"CtsUsageStatsTestCases",
+ "DeadpoolService",
+ "DeadpoolServiceBtServices",
+ "DeviceInfo",
+ "DiagnosticTools",
"DisplayCutoutEmulationEmu01Overlay",
"DocumentsUIPerfTests",
"DocumentsUITests",
"DownloadProvider",
"DownloadProviderTests",
"DownloadProviderUi",
+ "ds-car-docs", // for AAOS API documentation only
"DynamicSystemInstallationService",
"EmergencyInfo-lib",
"ethernet-service",
@@ -73,6 +84,7 @@
"FrameworksServicesRoboTests",
"FrameworksServicesTests",
"FrameworksUtilTests",
+ "FrameworksWifiTests",
"hid",
"hidl_test_java_java",
"hwbinder",
@@ -95,6 +107,9 @@
"platform_library-docs",
"PrintSpooler",
"RollbackTest",
+ "service-blobstore",
+ "service-connectivity-pre-jarjar",
+ "service-jobscheduler",
"services",
"services.accessibility",
"services.backup",
@@ -136,10 +151,6 @@
"wifi-service",
}
-// This variable is effectively unused in pre-master branches, and is
-// included (with the same value as it has in AOSP) only to ease
-// merges between branches (see the comment in the
-// useLegacyCorePlatformApi() function):
var legacyCorePlatformApiLookup = make(map[string]struct{})
func init() {
@@ -149,12 +160,12 @@
}
func useLegacyCorePlatformApi(ctx android.EarlyModuleContext) bool {
- // In pre-master branches, we don't attempt to force usage of the stable
- // version of the core/platform API. Instead, we always use the legacy
- // version --- except in tests, where we always use stable, so that we
- // can make the test assertions the same as other branches.
- // This should be false in tests and true otherwise:
- return ctx.Config().TestProductVariables == nil
+ return useLegacyCorePlatformApiByName(ctx.ModuleName())
+}
+
+func useLegacyCorePlatformApiByName(name string) bool {
+ _, found := legacyCorePlatformApiLookup[name]
+ return found
}
func corePlatformSystemModules(ctx android.EarlyModuleContext) string {
diff --git a/java/lint.go b/java/lint.go
index 50b84dc..9f677db 100644
--- a/java/lint.go
+++ b/java/lint.go
@@ -22,6 +22,8 @@
"github.com/google/blueprint/proptools"
"android/soong/android"
+ "android/soong/java/config"
+ "android/soong/remoteexec"
)
type LintProperties struct {
@@ -172,8 +174,44 @@
extraLintCheckTag, extraCheckModules...)
}
-func (l *linter) writeLintProjectXML(ctx android.ModuleContext,
- rule *android.RuleBuilder) (projectXMLPath, configXMLPath, cacheDir, homeDir android.WritablePath, deps android.Paths) {
+// lintPaths contains the paths to lint's inputs and outputs to make it easier to pass them
+// around.
+type lintPaths struct {
+ projectXML android.WritablePath
+ configXML android.WritablePath
+ cacheDir android.WritablePath
+ homeDir android.WritablePath
+ srcjarDir android.WritablePath
+
+ deps android.Paths
+
+ remoteInputs android.Paths
+ remoteRSPInputs android.Paths
+}
+
+func lintRBEExecStrategy(ctx android.ModuleContext) string {
+ return ctx.Config().GetenvWithDefault("RBE_LINT_EXEC_STRATEGY", remoteexec.LocalExecStrategy)
+}
+
+func (l *linter) writeLintProjectXML(ctx android.ModuleContext, rule *android.RuleBuilder) lintPaths {
+ var deps android.Paths
+ var remoteInputs android.Paths
+ var remoteRSPInputs android.Paths
+
+ // Paths passed to trackInputDependency will be added as dependencies of the rule that runs
+ // lint and passed as inputs to the remote execution proxy.
+ trackInputDependency := func(paths ...android.Path) {
+ deps = append(deps, paths...)
+ remoteInputs = append(remoteInputs, paths...)
+ }
+
+ // Paths passed to trackRSPDependency will be added as dependencies of the rule that runs
+ // lint, but the RSP file will be used by the remote execution proxy to find the files so that
+ // it doesn't overflow command line limits.
+ trackRSPDependency := func(paths android.Paths, rsp android.Path) {
+ deps = append(deps, paths...)
+ remoteRSPInputs = append(remoteRSPInputs, rsp)
+ }
var resourcesList android.WritablePath
if len(l.resources) > 0 {
@@ -184,17 +222,27 @@
resListRule := android.NewRuleBuilder(pctx, ctx)
resListRule.Command().Text("cp").FlagWithRspFileInputList("", l.resources).Output(resourcesList)
resListRule.Build("lint_resources_list", "lint resources list")
- deps = append(deps, l.resources...)
+ trackRSPDependency(l.resources, resourcesList)
}
- projectXMLPath = android.PathForModuleOut(ctx, "lint", "project.xml")
+ projectXMLPath := android.PathForModuleOut(ctx, "lint", "project.xml")
// Lint looks for a lint.xml file next to the project.xml file, give it one.
- configXMLPath = android.PathForModuleOut(ctx, "lint", "lint.xml")
- cacheDir = android.PathForModuleOut(ctx, "lint", "cache")
- homeDir = android.PathForModuleOut(ctx, "lint", "home")
+ configXMLPath := android.PathForModuleOut(ctx, "lint", "lint.xml")
+ cacheDir := android.PathForModuleOut(ctx, "lint", "cache")
+ homeDir := android.PathForModuleOut(ctx, "lint", "home")
srcJarDir := android.PathForModuleOut(ctx, "lint-srcjars")
srcJarList := zipSyncCmd(ctx, rule, srcJarDir, l.srcJars)
+ // TODO(ccross): this is a little fishy. The files extracted from the srcjars are referenced
+ // by the project.xml and used by the later lint rule, but the lint rule depends on the srcjars,
+ // not the extracted files.
+ trackRSPDependency(l.srcJars, srcJarList)
+
+ // TODO(ccross): some of the files in l.srcs are generated sources and should be passed to
+ // lint separately.
+ srcsList := android.PathForModuleOut(ctx, "lint", "srcs.list")
+ rule.Command().Text("cp").FlagWithRspFileInputList("", l.srcs).Output(srcsList)
+ trackRSPDependency(l.srcs, srcsList)
cmd := rule.Command().
BuiltTool("lint-project-xml").
@@ -209,38 +257,40 @@
cmd.Flag("--test")
}
if l.manifest != nil {
- deps = append(deps, l.manifest)
cmd.FlagWithArg("--manifest ", l.manifest.String())
+ trackInputDependency(l.manifest)
}
if l.mergedManifest != nil {
- deps = append(deps, l.mergedManifest)
cmd.FlagWithArg("--merged_manifest ", l.mergedManifest.String())
+ trackInputDependency(l.mergedManifest)
}
- // TODO(ccross): some of the files in l.srcs are generated sources and should be passed to
- // lint separately.
- cmd.FlagWithRspFileInputList("--srcs ", l.srcs)
- deps = append(deps, l.srcs...)
+ cmd.FlagWithInput("--srcs ", srcsList)
cmd.FlagWithInput("--generated_srcs ", srcJarList)
- deps = append(deps, l.srcJars...)
if resourcesList != nil {
cmd.FlagWithInput("--resources ", resourcesList)
}
if l.classes != nil {
- deps = append(deps, l.classes)
cmd.FlagWithArg("--classes ", l.classes.String())
+ trackInputDependency(l.classes)
}
cmd.FlagForEachArg("--classpath ", l.classpath.Strings())
- deps = append(deps, l.classpath...)
+ trackInputDependency(l.classpath...)
cmd.FlagForEachArg("--extra_checks_jar ", l.extraLintCheckJars.Strings())
- deps = append(deps, l.extraLintCheckJars...)
+ trackInputDependency(l.extraLintCheckJars...)
- cmd.FlagWithArg("--root_dir ", "$PWD")
+ if ctx.Config().UseRBE() && ctx.Config().IsEnvTrue("RBE_LINT") &&
+ lintRBEExecStrategy(ctx) != remoteexec.LocalExecStrategy {
+ // TODO(b/181912787): remove these and use "." instead.
+ cmd.FlagWithArg("--root_dir ", "/b/f/w")
+ } else {
+ cmd.FlagWithArg("--root_dir ", "$PWD")
+ }
// The cache tag in project.xml is relative to the root dir, or the project.xml file if
// the root dir is not set.
@@ -254,7 +304,18 @@
cmd.FlagForEachArg("--error_check ", l.properties.Lint.Error_checks)
cmd.FlagForEachArg("--fatal_check ", l.properties.Lint.Fatal_checks)
- return projectXMLPath, configXMLPath, cacheDir, homeDir, deps
+ return lintPaths{
+ projectXML: projectXMLPath,
+ configXML: configXMLPath,
+ cacheDir: cacheDir,
+ homeDir: homeDir,
+
+ deps: deps,
+
+ remoteInputs: remoteInputs,
+ remoteRSPInputs: remoteRSPInputs,
+ }
+
}
// generateManifest adds a command to the rule to write a simple manifest that contains the
@@ -297,7 +358,7 @@
l.manifest = manifest
}
- projectXML, lintXML, cacheDir, homeDir, deps := l.writeLintProjectXML(ctx, rule)
+ lintPaths := l.writeLintProjectXML(ctx, rule)
html := android.PathForModuleOut(ctx, "lint-report.html")
text := android.PathForModuleOut(ctx, "lint-report.txt")
@@ -311,8 +372,8 @@
}
})
- rule.Command().Text("rm -rf").Flag(cacheDir.String()).Flag(homeDir.String())
- rule.Command().Text("mkdir -p").Flag(cacheDir.String()).Flag(homeDir.String())
+ rule.Command().Text("rm -rf").Flag(lintPaths.cacheDir.String()).Flag(lintPaths.homeDir.String())
+ rule.Command().Text("mkdir -p").Flag(lintPaths.cacheDir.String()).Flag(lintPaths.homeDir.String())
rule.Command().Text("rm -f").Output(html).Output(text).Output(xml)
var annotationsZipPath, apiVersionsXMLPath android.Path
@@ -324,16 +385,53 @@
apiVersionsXMLPath = copiedAPIVersionsXmlPath(ctx)
}
- cmd := rule.Command().
- Text("(").
- Flag("JAVA_OPTS=-Xmx3072m").
- FlagWithArg("ANDROID_SDK_HOME=", homeDir.String()).
+ cmd := rule.Command()
+
+ cmd.Flag("JAVA_OPTS=-Xmx3072m").
+ FlagWithArg("ANDROID_SDK_HOME=", lintPaths.homeDir.String()).
FlagWithInput("SDK_ANNOTATIONS=", annotationsZipPath).
- FlagWithInput("LINT_OPTS=-DLINT_API_DATABASE=", apiVersionsXMLPath).
- BuiltTool("lint").
+ FlagWithInput("LINT_OPTS=-DLINT_API_DATABASE=", apiVersionsXMLPath)
+
+ if ctx.Config().UseRBE() && ctx.Config().IsEnvTrue("RBE_LINT") {
+ pool := ctx.Config().GetenvWithDefault("RBE_LINT_POOL", "java16")
+ // TODO(b/181912787): this should be local fallback once the hack that passes /b/f/w in project.xml
+ // is removed.
+ execStrategy := lintRBEExecStrategy(ctx)
+ labels := map[string]string{"type": "tool", "name": "lint"}
+ rule.Remoteable(android.RemoteRuleSupports{RBE: true})
+ remoteInputs := lintPaths.remoteInputs
+ remoteInputs = append(remoteInputs,
+ lintPaths.projectXML,
+ lintPaths.configXML,
+ lintPaths.homeDir,
+ lintPaths.cacheDir,
+ ctx.Config().HostJavaToolPath(ctx, "lint.jar"),
+ annotationsZipPath,
+ apiVersionsXMLPath,
+ )
+
+ cmd.Text((&remoteexec.REParams{
+ Labels: labels,
+ ExecStrategy: execStrategy,
+ ToolchainInputs: []string{config.JavaCmd(ctx).String()},
+ Inputs: remoteInputs.Strings(),
+ OutputFiles: android.Paths{html, text, xml}.Strings(),
+ RSPFile: strings.Join(lintPaths.remoteRSPInputs.Strings(), ","),
+ EnvironmentVariables: []string{
+ "JAVA_OPTS",
+ "ANDROID_SDK_HOME",
+ "SDK_ANNOTATIONS",
+ "LINT_OPTS",
+ "LANG",
+ },
+ Platform: map[string]string{remoteexec.PoolKey: pool},
+ }).NoVarTemplate(ctx.Config()))
+ }
+
+ cmd.BuiltTool("lint").
Flag("--quiet").
- FlagWithInput("--project ", projectXML).
- FlagWithInput("--config ", lintXML).
+ FlagWithInput("--project ", lintPaths.projectXML).
+ FlagWithInput("--config ", lintPaths.configXML).
FlagWithOutput("--html ", html).
FlagWithOutput("--text ", text).
FlagWithOutput("--xml ", xml).
@@ -343,7 +441,9 @@
FlagWithArg("--url ", fmt.Sprintf(".=.,%s=out", android.PathForOutput(ctx).String())).
Flag("--exitcode").
Flags(l.properties.Lint.Flags).
- Implicits(deps)
+ Implicit(annotationsZipPath).
+ Implicit(apiVersionsXMLPath).
+ Implicits(lintPaths.deps)
if checkOnly := ctx.Config().Getenv("ANDROID_LINT_CHECK"); checkOnly != "" {
cmd.FlagWithArg("--check ", checkOnly)
@@ -362,9 +462,9 @@
}
}
- cmd.Text("|| (").Text("if [ -e").Input(text).Text("]; then cat").Input(text).Text("; fi; exit 7)").Text(")")
+ cmd.Text("|| (").Text("if [ -e").Input(text).Text("]; then cat").Input(text).Text("; fi; exit 7)")
- rule.Command().Text("rm -rf").Flag(cacheDir.String()).Flag(homeDir.String())
+ rule.Command().Text("rm -rf").Flag(lintPaths.cacheDir.String()).Flag(lintPaths.homeDir.String())
rule.Build("lint", "lint")
diff --git a/java/prebuilt_apis.go b/java/prebuilt_apis.go
index c91b321..8a442b5 100644
--- a/java/prebuilt_apis.go
+++ b/java/prebuilt_apis.go
@@ -178,7 +178,7 @@
props.Name = proptools.StringPtr(prebuiltApiModuleName(mctx, "system_modules", "public", apiver))
props.Libs = append(props.Libs, prebuiltApiModuleName(mctx, "core-for-system-modules", "public", apiver))
- mctx.CreateModule(SystemModulesFactory, &props)
+ mctx.CreateModule(systemModulesImportFactory, &props)
}
func prebuiltSdkSystemModules(mctx android.LoadHookContext, p *prebuiltApis) {
@@ -248,9 +248,9 @@
}
// Create incompatibilities tracking files for all modules, if we have a "next" api.
+ incompatibilities := make(map[string]bool)
if nextApiDir := String(p.properties.Next_api_dir); nextApiDir != "" {
files := getPrebuiltFilesInSubdir(mctx, nextApiDir, "api/*incompatibilities.txt")
- incompatibilities := make(map[string]bool)
for _, f := range files {
localPath := strings.TrimPrefix(f, mydir)
module, _, scope := parseApiFilePath(mctx, localPath)
@@ -266,11 +266,11 @@
incompatibilities[referencedModule+"."+scope] = true
}
- // Create empty incompatibilities files for remaining modules
- for _, k := range android.SortedStringKeys(m) {
- if _, ok := incompatibilities[k]; !ok {
- createEmptyFile(mctx, apiModuleName(m[k].module+"-incompatibilities", m[k].scope, "latest"))
- }
+ }
+ // Create empty incompatibilities files for remaining modules
+ for _, k := range android.SortedStringKeys(m) {
+ if _, ok := incompatibilities[k]; !ok {
+ createEmptyFile(mctx, apiModuleName(m[k].module+"-incompatibilities", m[k].scope, "latest"))
}
}
}
diff --git a/java/robolectric.go b/java/robolectric.go
index 98bb710..00f233e 100644
--- a/java/robolectric.go
+++ b/java/robolectric.go
@@ -31,13 +31,15 @@
}
var robolectricDefaultLibs = []string{
- "Robolectric_all-target",
"mockito-robolectric-prebuilt",
"truth-prebuilt",
// TODO(ccross): this is not needed at link time
"junitxml",
}
+const robolectricCurrentLib = "Robolectric_all-target"
+const robolectricPrebuiltLibPattern = "platform-robolectric-%s-prebuilt"
+
var (
roboCoverageLibsTag = dependencyTag{name: "roboCoverageLibs"}
roboRuntimesTag = dependencyTag{name: "roboRuntimes"}
@@ -57,6 +59,10 @@
// Number of shards to use when running the tests.
Shards *int64
}
+
+ // The version number of a robolectric prebuilt to use from prebuilts/misc/common/robolectric
+ // instead of the one built from source in external/robolectric-shadows.
+ Robolectric_prebuilt_version *string
}
type robolectricTest struct {
@@ -94,6 +100,12 @@
ctx.PropertyErrorf("instrumentation_for", "missing required instrumented module")
}
+ if v := String(r.robolectricProperties.Robolectric_prebuilt_version); v != "" {
+ ctx.AddVariationDependencies(nil, libTag, fmt.Sprintf(robolectricPrebuiltLibPattern, v))
+ } else {
+ ctx.AddVariationDependencies(nil, libTag, robolectricCurrentLib)
+ }
+
ctx.AddVariationDependencies(nil, libTag, robolectricDefaultLibs...)
ctx.AddVariationDependencies(nil, roboCoverageLibsTag, r.robolectricProperties.Coverage_libs...)
@@ -298,7 +310,11 @@
if t := r.robolectricProperties.Test_options.Timeout; t != nil {
fmt.Fprintln(w, "LOCAL_ROBOTEST_TIMEOUT :=", *t)
}
- fmt.Fprintln(w, "-include external/robolectric-shadows/run_robotests.mk")
+ if v := String(r.robolectricProperties.Robolectric_prebuilt_version); v != "" {
+ fmt.Fprintf(w, "-include prebuilts/misc/common/robolectric/%s/run_robotests.mk\n", v)
+ } else {
+ fmt.Fprintln(w, "-include external/robolectric-shadows/run_robotests.mk")
+ }
}
// An android_robolectric_test module compiles tests against the Robolectric framework that can run on the local host
diff --git a/java/sdk_library.go b/java/sdk_library.go
index 30d120d..b03f90c 100644
--- a/java/sdk_library.go
+++ b/java/sdk_library.go
@@ -452,6 +452,7 @@
// that references the latest released API and remove API specification files.
// * API specification filegroup -> <dist-stem>.api.<scope>.latest
// * Removed API specification filegroup -> <dist-stem>-removed.api.<scope>.latest
+ // * API incompatibilities baseline filegroup -> <dist-stem>-incompatibilities.api.<scope>.latest
Dist_stem *string
// A compatibility mode that allows historical API-tracking files to not exist.
@@ -1059,6 +1060,9 @@
if m := android.SrcIsModule(module.latestRemovedApiFilegroupName(apiScope)); !ctx.OtherModuleExists(m) {
missingApiModules = append(missingApiModules, m)
}
+ if m := android.SrcIsModule(module.latestIncompatibilitiesFilegroupName(apiScope)); !ctx.OtherModuleExists(m) {
+ missingApiModules = append(missingApiModules, m)
+ }
}
if len(missingApiModules) != 0 && !module.sdkLibraryProperties.Unsafe_ignore_missing_latest_api {
m := module.Name() + " is missing tracking files for previously released library versions.\n"
@@ -1165,6 +1169,10 @@
return ":" + module.distStem() + "-removed.api." + apiScope.name + ".latest"
}
+func (module *SdkLibrary) latestIncompatibilitiesFilegroupName(apiScope *apiScope) string {
+ return ":" + module.distStem() + "-incompatibilities.api." + apiScope.name + ".latest"
+}
+
func childModuleVisibility(childVisibility []string) []string {
if childVisibility == nil {
// No child visibility set. The child will use the visibility of the sdk_library.
@@ -1389,6 +1397,8 @@
props.Check_api.Last_released.Api_file = latestApiFilegroupName
props.Check_api.Last_released.Removed_api_file = proptools.StringPtr(
module.latestRemovedApiFilegroupName(apiScope))
+ props.Check_api.Last_released.Baseline_file = proptools.StringPtr(
+ module.latestIncompatibilitiesFilegroupName(apiScope))
if proptools.Bool(module.sdkLibraryProperties.Api_lint.Enabled) {
// Enable api lint.
diff --git a/java/system_modules.go b/java/system_modules.go
index 95f71b8..8c69051 100644
--- a/java/system_modules.go
+++ b/java/system_modules.go
@@ -169,7 +169,13 @@
system.outputDir, system.outputDeps = TransformJarsToSystemModules(ctx, jars)
}
-func (system *SystemModules) DepsMutator(ctx android.BottomUpMutatorContext) {
+// ComponentDepsMutator is called before prebuilt modules without a corresponding source module are
+// renamed so unless the supplied libs specifically includes the prebuilt_ prefix this is guaranteed
+// to only add dependencies on source modules.
+//
+// The systemModuleLibsTag will prevent the prebuilt mutators from replacing this dependency so it
+// will never be changed to depend on a prebuilt either.
+func (system *SystemModules) ComponentDepsMutator(ctx android.BottomUpMutatorContext) {
ctx.AddVariationDependencies(nil, systemModulesLibsTag, system.properties.Libs...)
}
@@ -225,6 +231,15 @@
return &system.prebuilt
}
+// ComponentDepsMutator is called before prebuilt modules without a corresponding source module are
+// renamed so as this adds a prebuilt_ prefix this is guaranteed to only add dependencies on source
+// modules.
+func (system *systemModulesImport) ComponentDepsMutator(ctx android.BottomUpMutatorContext) {
+ for _, lib := range system.properties.Libs {
+ ctx.AddVariationDependencies(nil, systemModulesLibsTag, "prebuilt_"+lib)
+ }
+}
+
type systemModulesSdkMemberType struct {
android.SdkMemberTypeBase
}
diff --git a/java/system_modules_test.go b/java/system_modules_test.go
new file mode 100644
index 0000000..3d9f398
--- /dev/null
+++ b/java/system_modules_test.go
@@ -0,0 +1,112 @@
+// Copyright 2021 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 java
+
+import (
+ "testing"
+
+ "android/soong/android"
+)
+
+func getModuleHeaderJarsAsNormalizedPaths(result *android.TestResult, moduleNames ...string) []string {
+ paths := []string{}
+ for _, moduleName := range moduleNames {
+ module := result.Module(moduleName, "android_common")
+ info := result.ModuleProvider(module, JavaInfoProvider).(JavaInfo)
+ paths = append(paths, result.NormalizePathsForTesting(info.HeaderJars)...)
+ }
+ return paths
+}
+
+var addSourceSystemModules = android.FixtureAddTextFile("source/Android.bp", `
+ java_system_modules {
+ name: "system-modules",
+ libs: ["system-module1", "system-module2"],
+ }
+ java_library {
+ name: "system-module1",
+ srcs: ["a.java"],
+ sdk_version: "none",
+ system_modules: "none",
+ }
+ java_library {
+ name: "system-module2",
+ srcs: ["b.java"],
+ sdk_version: "none",
+ system_modules: "none",
+ }
+`)
+
+func TestJavaSystemModules(t *testing.T) {
+ result := javaFixtureFactory.RunTest(t, addSourceSystemModules)
+
+ // check the existence of the source module
+ sourceSystemModules := result.ModuleForTests("system-modules", "android_common")
+ sourceInputs := sourceSystemModules.Rule("jarsTosystemModules").Inputs
+
+ // The expected paths are the header jars from the source input modules.
+ expectedSourcePaths := getModuleHeaderJarsAsNormalizedPaths(result, "system-module1", "system-module2")
+ android.AssertArrayString(t, "source system modules inputs", expectedSourcePaths, result.NormalizePathsForTesting(sourceInputs))
+}
+
+var addPrebuiltSystemModules = android.FixtureAddTextFile("prebuilts/Android.bp", `
+ java_system_modules_import {
+ name: "system-modules",
+ libs: ["system-module1", "system-module2"],
+ }
+ java_import {
+ name: "system-module1",
+ jars: ["a.jar"],
+ }
+ java_import {
+ name: "system-module2",
+ jars: ["b.jar"],
+ }
+`)
+
+func TestJavaSystemModulesImport(t *testing.T) {
+ result := javaFixtureFactory.RunTest(t, addPrebuiltSystemModules)
+
+ // check the existence of the renamed prebuilt module
+ prebuiltSystemModules := result.ModuleForTests("system-modules", "android_common")
+ prebuiltInputs := prebuiltSystemModules.Rule("jarsTosystemModules").Inputs
+
+ // The expected paths are the header jars from the renamed prebuilt input modules.
+ expectedPrebuiltPaths := getModuleHeaderJarsAsNormalizedPaths(result, "system-module1", "system-module2")
+ android.AssertArrayString(t, "renamed prebuilt system modules inputs", expectedPrebuiltPaths, result.NormalizePathsForTesting(prebuiltInputs))
+}
+
+func TestJavaSystemModulesMixSourceAndPrebuilt(t *testing.T) {
+ result := javaFixtureFactory.RunTest(t,
+ addSourceSystemModules,
+ addPrebuiltSystemModules,
+ )
+
+ // check the existence of the source module
+ sourceSystemModules := result.ModuleForTests("system-modules", "android_common")
+ sourceInputs := sourceSystemModules.Rule("jarsTosystemModules").Inputs
+
+ // The expected paths are the header jars from the source input modules.
+ expectedSourcePaths := getModuleHeaderJarsAsNormalizedPaths(result, "system-module1", "system-module2")
+ android.AssertArrayString(t, "source system modules inputs", expectedSourcePaths, result.NormalizePathsForTesting(sourceInputs))
+
+ // check the existence of the renamed prebuilt module
+ prebuiltSystemModules := result.ModuleForTests("prebuilt_system-modules", "android_common")
+ prebuiltInputs := prebuiltSystemModules.Rule("jarsTosystemModules").Inputs
+
+ // The expected paths are the header jars from the renamed prebuilt input modules.
+ expectedPrebuiltPaths := getModuleHeaderJarsAsNormalizedPaths(result, "prebuilt_system-module1", "prebuilt_system-module2")
+ android.AssertArrayString(t, "prebuilt system modules inputs", expectedPrebuiltPaths, result.NormalizePathsForTesting(prebuiltInputs))
+}
diff --git a/java/testing.go b/java/testing.go
index bfa1e6b..4e1997e 100644
--- a/java/testing.go
+++ b/java/testing.go
@@ -29,10 +29,40 @@
"github.com/google/blueprint"
)
-func TestConfig(buildDir string, env map[string]string, bp string, fs map[string][]byte) android.Config {
- bp += GatherRequiredDepsForTest()
+const defaultJavaDir = "default/java"
- mockFS := map[string][]byte{
+// Test fixture preparer that will register most java build components.
+//
+// Singletons and mutators should only be added here if they are needed for a majority of java
+// module types, otherwise they should be added under a separate preparer to allow them to be
+// selected only when needed to reduce test execution time.
+//
+// Module types do not have much of an overhead unless they are used so this should include as many
+// module types as possible. The exceptions are those module types that require mutators and/or
+// singletons in order to function in which case they should be kept together in a separate
+// preparer.
+var PrepareForTestWithJavaBuildComponents = android.FixtureRegisterWithContext(RegisterRequiredBuildComponentsForTest)
+
+// Test fixture preparer that will define default java modules, e.g. standard prebuilt modules.
+var PrepareForTestWithJavaDefaultModules = android.GroupFixturePreparers(
+ // Make sure that mutators and module types, e.g. prebuilt mutators available.
+ android.PrepareForTestWithAndroidBuildComponents,
+ // Make sure that all the module types used in the defaults are registered.
+ PrepareForTestWithJavaBuildComponents,
+ // The java default module definitions.
+ android.FixtureAddTextFile(defaultJavaDir+"/Android.bp", GatherRequiredDepsForTest()),
+)
+
+// Prepare a fixture to use all java module types, mutators and singletons fully.
+//
+// This should only be used by tests that want to run with as much of the build enabled as possible.
+var PrepareForIntegrationTestWithJava = android.GroupFixturePreparers(
+ cc.PrepareForIntegrationTestWithCc,
+ PrepareForTestWithJavaDefaultModules,
+)
+
+func javaMockFS() android.MockFS {
+ mockFS := android.MockFS{
"api/current.txt": nil,
"api/removed.txt": nil,
"api/system-current.txt": nil,
@@ -64,6 +94,14 @@
mockFS[k] = v
}
+ return mockFS
+}
+
+func TestConfig(buildDir string, env map[string]string, bp string, fs map[string][]byte) android.Config {
+ bp += GatherRequiredDepsForTest()
+
+ mockFS := javaMockFS()
+
cc.GatherRequiredFilesForTest(mockFS)
for k, v := range fs {
diff --git a/python/binary.go b/python/binary.go
index 416a7ee..372b8a8 100644
--- a/python/binary.go
+++ b/python/binary.go
@@ -20,10 +20,92 @@
"fmt"
"android/soong/android"
+ "android/soong/bazel"
+
+ "github.com/google/blueprint/proptools"
)
func init() {
android.RegisterModuleType("python_binary_host", PythonBinaryHostFactory)
+ android.RegisterBp2BuildMutator("python_binary_host", PythonBinaryBp2Build)
+}
+
+type bazelPythonBinaryAttributes struct {
+ Main string
+ Srcs bazel.LabelList
+ Data bazel.LabelList
+ Python_version string
+}
+
+type bazelPythonBinary struct {
+ android.BazelTargetModuleBase
+ bazelPythonBinaryAttributes
+}
+
+func BazelPythonBinaryFactory() android.Module {
+ module := &bazelPythonBinary{}
+ module.AddProperties(&module.bazelPythonBinaryAttributes)
+ android.InitBazelTargetModule(module)
+ return module
+}
+
+func (m *bazelPythonBinary) Name() string {
+ return m.BaseModuleName()
+}
+
+func (m *bazelPythonBinary) GenerateAndroidBuildActions(ctx android.ModuleContext) {}
+
+func PythonBinaryBp2Build(ctx android.TopDownMutatorContext) {
+ m, ok := ctx.Module().(*Module)
+ if !ok || !m.ConvertWithBp2build() {
+ return
+ }
+
+ // a Module can be something other than a python_binary_host
+ if ctx.ModuleType() != "python_binary_host" {
+ return
+ }
+
+ var main string
+ for _, propIntf := range m.GetProperties() {
+ if props, ok := propIntf.(*BinaryProperties); ok {
+ // main is optional.
+ if props.Main != nil {
+ main = *props.Main
+ break
+ }
+ }
+ }
+ // TODO(b/182306917): this doesn't fully handle all nested props versioned
+ // by the python version, which would have been handled by the version split
+ // mutator. This is sufficient for very simple python_binary_host modules
+ // under Bionic.
+ py3Enabled := proptools.BoolDefault(m.properties.Version.Py3.Enabled, false)
+ py2Enabled := proptools.BoolDefault(m.properties.Version.Py2.Enabled, false)
+ var python_version string
+ if py3Enabled && py2Enabled {
+ panic(fmt.Errorf(
+ "error for '%s' module: bp2build's python_binary_host converter does not support "+
+ "converting a module that is enabled for both Python 2 and 3 at the same time.", m.Name()))
+ } else if py2Enabled {
+ python_version = "PY2"
+ } else {
+ // do nothing, since python_version defaults to PY3.
+ }
+
+ attrs := &bazelPythonBinaryAttributes{
+ Main: main,
+ Srcs: android.BazelLabelForModuleSrcExcludes(ctx, m.properties.Srcs, m.properties.Exclude_srcs),
+ Data: android.BazelLabelForModuleSrc(ctx, m.properties.Data),
+ Python_version: python_version,
+ }
+
+ props := bazel.BazelTargetModuleProperties{
+ // Use the native py_binary rule.
+ Rule_class: "py_binary",
+ }
+
+ ctx.CreateBazelTargetModule(BazelPythonBinaryFactory, m.Name(), props, attrs)
}
type BinaryProperties struct {
@@ -81,6 +163,8 @@
func PythonBinaryHostFactory() android.Module {
module, _ := NewBinary(android.HostSupported)
+ android.InitBazelModule(module)
+
return module.init()
}
diff --git a/python/python.go b/python/python.go
index b3e3d13..a078c0b 100644
--- a/python/python.go
+++ b/python/python.go
@@ -125,6 +125,7 @@
type Module struct {
android.ModuleBase
android.DefaultableModuleBase
+ android.BazelModuleBase
properties BaseProperties
protoProperties android.ProtoProperties
diff --git a/remoteexec/remoteexec.go b/remoteexec/remoteexec.go
index d6e2c0a..5f0426a 100644
--- a/remoteexec/remoteexec.go
+++ b/remoteexec/remoteexec.go
@@ -81,6 +81,9 @@
// ToolchainInputs is a list of paths or ninja variables pointing to the location of
// toolchain binaries used by the rule.
ToolchainInputs []string
+ // EnvironmentVariables is a list of environment variables whose values should be passed through
+ // to the remote execution.
+ EnvironmentVariables []string
}
func init() {
@@ -162,6 +165,10 @@
args += " --toolchain_inputs=" + strings.Join(r.ToolchainInputs, ",")
}
+ if len(r.EnvironmentVariables) > 0 {
+ args += " --env_var_allowlist=" + strings.Join(r.EnvironmentVariables, ",")
+ }
+
return args + " -- "
}
diff --git a/rust/builder.go b/rust/builder.go
index 6326124..9d462d4 100644
--- a/rust/builder.go
+++ b/rust/builder.go
@@ -194,8 +194,7 @@
}
if len(deps.SrcDeps) > 0 {
- genSubDir := "out/"
- moduleGenDir := android.PathForModuleOut(ctx, genSubDir)
+ moduleGenDir := ctx.RustModule().compiler.CargoOutDir()
var outputs android.WritablePaths
for _, genSrc := range deps.SrcDeps {
@@ -208,7 +207,7 @@
ctx.Build(pctx, android.BuildParams{
Rule: cp,
- Description: "cp " + moduleGenDir.Rel(),
+ Description: "cp " + moduleGenDir.Path().Rel(),
Outputs: outputs,
Inputs: deps.SrcDeps,
Args: map[string]string{
diff --git a/rust/compiler.go b/rust/compiler.go
index c26f208..98ad7ad 100644
--- a/rust/compiler.go
+++ b/rust/compiler.go
@@ -60,6 +60,7 @@
InstallInData = iota
incorrectSourcesError = "srcs can only contain one path for a rust file and source providers prefixed by \":\""
+ genSubDir = "out/"
)
type BaseCompilerProperties struct {
@@ -154,6 +155,10 @@
distFile android.OptionalPath
// Stripped output file. If Valid(), this file will be installed instead of outputFile.
strippedOutputFile android.OptionalPath
+
+ // If a crate has a source-generated dependency, a copy of the source file
+ // will be available in cargoOutDir (equivalent to Cargo OUT_DIR).
+ cargoOutDir android.ModuleOutPath
}
func (compiler *baseCompiler) Disabled() bool {
@@ -243,6 +248,14 @@
panic(fmt.Errorf("baseCrater doesn't know how to crate things!"))
}
+func (compiler *baseCompiler) initialize(ctx ModuleContext) {
+ compiler.cargoOutDir = android.PathForModuleOut(ctx, genSubDir)
+}
+
+func (compiler *baseCompiler) CargoOutDir() android.OptionalPath {
+ return android.OptionalPathForPath(compiler.cargoOutDir)
+}
+
func (compiler *baseCompiler) isDependencyRoot() bool {
return false
}
diff --git a/rust/config/allowed_list.go b/rust/config/allowed_list.go
index fc11d29..408d433 100644
--- a/rust/config/allowed_list.go
+++ b/rust/config/allowed_list.go
@@ -14,6 +14,7 @@
"external/rust",
"external/vm_tools/p9",
"frameworks/native/libs/binder/rust",
+ "frameworks/proto_logging/stats",
"packages/modules/DnsResolver",
"packages/modules/Virtualization",
"prebuilts/rust",
diff --git a/rust/project_json.go b/rust/project_json.go
index 32ce6f4..8d3d250 100644
--- a/rust/project_json.go
+++ b/rust/project_json.go
@@ -45,11 +45,12 @@
}
type rustProjectCrate struct {
- DisplayName string `json:"display_name"`
- RootModule string `json:"root_module"`
- Edition string `json:"edition,omitempty"`
- Deps []rustProjectDep `json:"deps"`
- Cfgs []string `json:"cfgs"`
+ DisplayName string `json:"display_name"`
+ RootModule string `json:"root_module"`
+ Edition string `json:"edition,omitempty"`
+ Deps []rustProjectDep `json:"deps"`
+ Cfgs []string `json:"cfgs"`
+ Env map[string]string `json:"env"`
}
type rustProjectJson struct {
@@ -136,7 +137,7 @@
}
})
if !foundSource {
- fmt.Errorf("No valid source for source provider found: %v\n", rModule)
+ ctx.Errorf("No valid source for source provider found: %v\n", rModule)
}
return sourceSrc, foundSource
}
@@ -220,7 +221,7 @@
func (singleton *projectGeneratorSingleton) addCrate(ctx android.SingletonContext, rModule *Module, comp *baseCompiler) (int, bool) {
rootModule, ok := crateSource(ctx, rModule, comp)
if !ok {
- fmt.Errorf("Unable to find source for valid module: %v", rModule)
+ ctx.Errorf("Unable to find source for valid module: %v", rModule)
return 0, false
}
@@ -230,6 +231,11 @@
Edition: comp.edition(),
Deps: make([]rustProjectDep, 0),
Cfgs: make([]string, 0),
+ Env: make(map[string]string),
+ }
+
+ if comp.CargoOutDir().Valid() {
+ crate.Env["OUT_DIR"] = comp.CargoOutDir().String()
}
deps := make(map[string]int)
diff --git a/rust/project_json_test.go b/rust/project_json_test.go
index ba66215..289bcb8 100644
--- a/rust/project_json_test.go
+++ b/rust/project_json_test.go
@@ -190,8 +190,8 @@
}
}
}
- // Check that liba depends on libbindings1
if strings.Contains(rootModule, "d/src/lib.rs") {
+ // Check that libd depends on libbindings1
found := false
for _, depName := range validateDependencies(t, crate) {
if depName == "bindings1" {
@@ -200,8 +200,17 @@
}
}
if !found {
- t.Errorf("liba does not depend on libbindings1: %v", crate)
+ t.Errorf("libd does not depend on libbindings1: %v", crate)
}
+ // Check that OUT_DIR is populated.
+ env, ok := crate["env"].(map[string]interface{})
+ if !ok {
+ t.Errorf("libd does not have its environment variables set: %v", crate)
+ }
+ if _, ok = env["OUT_DIR"]; !ok {
+ t.Errorf("libd does not have its OUT_DIR set: %v", env)
+ }
+
}
}
}
diff --git a/rust/rust.go b/rust/rust.go
index dc23abb..8ebdb72 100644
--- a/rust/rust.go
+++ b/rust/rust.go
@@ -320,12 +320,16 @@
}
type compiler interface {
+ initialize(ctx ModuleContext)
compilerFlags(ctx ModuleContext, flags Flags) Flags
compilerProps() []interface{}
compile(ctx ModuleContext, flags Flags, deps PathDeps) android.Path
compilerDeps(ctx DepsContext, deps Deps) Deps
crateName() string
+ // Output directory in which source-generated code from dependencies is
+ // copied. This is equivalent to Cargo's OUT_DIR variable.
+ CargoOutDir() android.OptionalPath
inData() bool
install(ctx ModuleContext)
relativeInstallPath() string
@@ -711,6 +715,7 @@
}
if mod.compiler != nil && !mod.compiler.Disabled() {
+ mod.compiler.initialize(ctx)
outputFile := mod.compiler.compile(ctx, flags, deps)
mod.outputFile = android.OptionalPathForPath(outputFile)
diff --git a/rust/testing.go b/rust/testing.go
index 9534ab5..5be71c9 100644
--- a/rust/testing.go
+++ b/rust/testing.go
@@ -20,6 +20,30 @@
"android/soong/genrule"
)
+// Preparer that will define all cc module types and a limited set of mutators and singletons that
+// make those module types usable.
+var PrepareForTestWithRustBuildComponents = android.GroupFixturePreparers(
+ android.FixtureRegisterWithContext(RegisterRequiredBuildComponentsForTest),
+)
+
+// The directory in which rust test default modules will be defined.
+//
+// Placing them here ensures that their location does not conflict with default test modules
+// defined by other packages.
+const rustDefaultsDir = "defaults/rust/"
+
+// Preparer that will define default rust modules, e.g. standard prebuilt modules.
+var PrepareForTestWithRustDefaultModules = android.GroupFixturePreparers(
+ cc.PrepareForTestWithCcDefaultModules,
+ PrepareForTestWithRustBuildComponents,
+ android.FixtureAddTextFile(rustDefaultsDir+"Android.bp", GatherRequiredDepsForTest()),
+)
+
+// Preparer that will allow use of all rust modules fully.
+var PrepareForIntegrationTestWithRust = android.GroupFixturePreparers(
+ PrepareForTestWithRustDefaultModules,
+)
+
func GatherRequiredDepsForTest() string {
bp := `
rust_prebuilt_library {
diff --git a/scripts/build-mainline-modules.sh b/scripts/build-mainline-modules.sh
index 0813f1a..18174a4 100755
--- a/scripts/build-mainline-modules.sh
+++ b/scripts/build-mainline-modules.sh
@@ -36,8 +36,9 @@
# List of libraries installed on the platform that are needed for ART chroot
# testing.
PLATFORM_LIBRARIES=(
- liblog
+ heapprofd_client_api
libartpalette-system
+ liblog
)
# We want to create apex modules for all supported architectures.
diff --git a/sdk/Android.bp b/sdk/Android.bp
index 8a3119c..6e49c6d 100644
--- a/sdk/Android.bp
+++ b/sdk/Android.bp
@@ -20,6 +20,7 @@
"update.go",
],
testSrcs: [
+ "boot_image_sdk_test.go",
"bp_test.go",
"cc_sdk_test.go",
"exports_test.go",
diff --git a/sdk/boot_image_sdk_test.go b/sdk/boot_image_sdk_test.go
new file mode 100644
index 0000000..9805a6a
--- /dev/null
+++ b/sdk/boot_image_sdk_test.go
@@ -0,0 +1,62 @@
+// Copyright (C) 2021 The Android Open Source Project
+//
+// 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 sdk
+
+import "testing"
+
+func TestSnapshotWithBootImage(t *testing.T) {
+ result := testSdkWithJava(t, `
+ sdk {
+ name: "mysdk",
+ boot_images: ["mybootimage"],
+ }
+
+ boot_image {
+ name: "mybootimage",
+ image_name: "art",
+ }
+ `)
+
+ CheckSnapshot(t, result, "mysdk", "",
+ checkUnversionedAndroidBpContents(`
+// This is auto-generated. DO NOT EDIT.
+
+prebuilt_boot_image {
+ name: "mybootimage",
+ prefer: false,
+ visibility: ["//visibility:public"],
+ apex_available: ["//apex_available:platform"],
+ image_name: "art",
+}
+`),
+ checkVersionedAndroidBpContents(`
+// This is auto-generated. DO NOT EDIT.
+
+prebuilt_boot_image {
+ name: "mysdk_mybootimage@current",
+ sdk_member_name: "mybootimage",
+ visibility: ["//visibility:public"],
+ apex_available: ["//apex_available:platform"],
+ image_name: "art",
+}
+
+sdk_snapshot {
+ name: "mysdk@current",
+ visibility: ["//visibility:public"],
+ boot_images: ["mysdk_mybootimage@current"],
+}
+`),
+ checkAllCopyRules(""))
+}
diff --git a/sdk/bp_test.go b/sdk/bp_test.go
index e1edc51..2bd8a43 100644
--- a/sdk/bp_test.go
+++ b/sdk/bp_test.go
@@ -54,26 +54,25 @@
return str
}
-func checkPropertySetFixture(h *TestHelper, val interface{}, hasTags bool) {
+func checkPropertySetFixture(t *testing.T, val interface{}, hasTags bool) {
set := val.(*bpPropertySet)
- h.AssertDeepEquals("wrong x value", "taxi", set.getValue("x"))
- h.AssertDeepEquals("wrong y value", 1729, set.getValue("y"))
+ android.AssertDeepEquals(t, "wrong x value", "taxi", set.getValue("x"))
+ android.AssertDeepEquals(t, "wrong y value", 1729, set.getValue("y"))
subset := set.getValue("sub").(*bpPropertySet)
- h.AssertDeepEquals("wrong sub.x value", "taxi", subset.getValue("x"))
- h.AssertDeepEquals("wrong sub.y value", 1729, subset.getValue("y"))
+ android.AssertDeepEquals(t, "wrong sub.x value", "taxi", subset.getValue("x"))
+ android.AssertDeepEquals(t, "wrong sub.y value", 1729, subset.getValue("y"))
if hasTags {
- h.AssertDeepEquals("wrong y tag", "tag_y", set.getTag("y"))
- h.AssertDeepEquals("wrong sub.x tag", "tag_x", subset.getTag("x"))
+ android.AssertDeepEquals(t, "wrong y tag", "tag_y", set.getTag("y"))
+ android.AssertDeepEquals(t, "wrong sub.x tag", "tag_x", subset.getTag("x"))
} else {
- h.AssertDeepEquals("wrong y tag", nil, set.getTag("y"))
- h.AssertDeepEquals("wrong sub.x tag", nil, subset.getTag("x"))
+ android.AssertDeepEquals(t, "wrong y tag", nil, set.getTag("y"))
+ android.AssertDeepEquals(t, "wrong sub.x tag", nil, subset.getTag("x"))
}
}
func TestAddPropertySimple(t *testing.T) {
- h := &TestHelper{t}
set := newPropertySet()
for name, val := range map[string]interface{}{
"x": "taxi",
@@ -83,16 +82,15 @@
"arr": []string{"a", "b", "c"},
} {
set.AddProperty(name, val)
- h.AssertDeepEquals("wrong value", val, set.getValue(name))
+ android.AssertDeepEquals(t, "wrong value", val, set.getValue(name))
}
- h.AssertPanic("adding x again should panic",
+ android.AssertPanic(t, "adding x again should panic",
func() { set.AddProperty("x", "taxi") })
- h.AssertPanic("adding arr again should panic",
+ android.AssertPanic(t, "adding arr again should panic",
func() { set.AddProperty("arr", []string{"d"}) })
}
func TestAddPropertySubset(t *testing.T) {
- h := &TestHelper{t}
getFixtureMap := map[string]func() interface{}{
"property set": propertySetFixture,
"property struct": propertyStructFixture,
@@ -103,8 +101,8 @@
t.Run(name, func(t *testing.T) {
set := propertySetFixture().(*bpPropertySet)
set.AddProperty("new", getFixture())
- checkPropertySetFixture(h, set, true)
- checkPropertySetFixture(h, set.getValue("new"), name == "property set")
+ checkPropertySetFixture(t, set, true)
+ checkPropertySetFixture(t, set.getValue("new"), name == "property set")
})
}
})
@@ -118,40 +116,38 @@
subset.AddPropertySet("sub")
set.AddProperty("sub", getFixture())
merged := set.getValue("sub").(*bpPropertySet)
- h.AssertDeepEquals("wrong flag value", false, merged.getValue("flag"))
- checkPropertySetFixture(h, merged, name == "property set")
+ android.AssertDeepEquals(t, "wrong flag value", false, merged.getValue("flag"))
+ checkPropertySetFixture(t, merged, name == "property set")
})
}
})
t.Run("add conflicting subset", func(t *testing.T) {
set := propertySetFixture().(*bpPropertySet)
- h.AssertPanic("adding x again should panic",
+ android.AssertPanic(t, "adding x again should panic",
func() { set.AddProperty("x", propertySetFixture()) })
})
t.Run("add non-pointer struct", func(t *testing.T) {
set := propertySetFixture().(*bpPropertySet)
str := propertyStructFixture().(*propertyStruct)
- h.AssertPanic("adding a non-pointer struct should panic",
+ android.AssertPanic(t, "adding a non-pointer struct should panic",
func() { set.AddProperty("new", *str) })
})
}
func TestAddPropertySetNew(t *testing.T) {
- h := &TestHelper{t}
set := newPropertySet()
subset := set.AddPropertySet("sub")
subset.AddProperty("new", "d^^b")
- h.AssertDeepEquals("wrong sub.new value", "d^^b", set.getValue("sub").(*bpPropertySet).getValue("new"))
+ android.AssertDeepEquals(t, "wrong sub.new value", "d^^b", set.getValue("sub").(*bpPropertySet).getValue("new"))
}
func TestAddPropertySetExisting(t *testing.T) {
- h := &TestHelper{t}
set := propertySetFixture().(*bpPropertySet)
subset := set.AddPropertySet("sub")
subset.AddProperty("new", "d^^b")
- h.AssertDeepEquals("wrong sub.new value", "d^^b", set.getValue("sub").(*bpPropertySet).getValue("new"))
+ android.AssertDeepEquals(t, "wrong sub.new value", "d^^b", set.getValue("sub").(*bpPropertySet).getValue("new"))
}
type removeFredTransformation struct {
@@ -180,9 +176,6 @@
}
func TestTransformRemoveProperty(t *testing.T) {
-
- helper := &TestHelper{t}
-
set := newPropertySet()
set.AddProperty("name", "name")
set.AddProperty("fred", "12")
@@ -191,13 +184,10 @@
contents := &generatedContents{}
outputPropertySet(contents, set)
- helper.AssertTrimmedStringEquals("removing property failed", "name: \"name\",\n", contents.content.String())
+ android.AssertTrimmedStringEquals(t, "removing property failed", "name: \"name\",\n", contents.content.String())
}
func TestTransformRemovePropertySet(t *testing.T) {
-
- helper := &TestHelper{t}
-
set := newPropertySet()
set.AddProperty("name", "name")
set.AddPropertySet("fred")
@@ -206,5 +196,5 @@
contents := &generatedContents{}
outputPropertySet(contents, set)
- helper.AssertTrimmedStringEquals("removing property set failed", "name: \"name\",\n", contents.content.String())
+ android.AssertTrimmedStringEquals(t, "removing property set failed", "name: \"name\",\n", contents.content.String())
}
diff --git a/sdk/cc_sdk_test.go b/sdk/cc_sdk_test.go
index 3591777..a2539c9 100644
--- a/sdk/cc_sdk_test.go
+++ b/sdk/cc_sdk_test.go
@@ -21,7 +21,7 @@
"android/soong/cc"
)
-var ccTestFs = map[string][]byte{
+var ccTestFs = android.MockFS{
"Test.cpp": nil,
"myinclude/Test.h": nil,
"myinclude-android/AndroidTest.h": nil,
@@ -32,7 +32,7 @@
"some/where/stubslib.map.txt": nil,
}
-func testSdkWithCc(t *testing.T, bp string) *testSdkResult {
+func testSdkWithCc(t *testing.T, bp string) *android.TestResult {
t.Helper()
return testSdkWithFs(t, bp, ccTestFs)
}
@@ -101,7 +101,7 @@
}
`)
- result.CheckSnapshot("mysdk", "",
+ CheckSnapshot(t, result, "mysdk", "",
checkUnversionedAndroidBpContents(`
// This is auto-generated. DO NOT EDIT.
@@ -353,7 +353,7 @@
}
`)
- result.CheckSnapshot("mysdk", "",
+ CheckSnapshot(t, result, "mysdk", "",
checkUnversionedAndroidBpContents(`
// This is auto-generated. DO NOT EDIT.
@@ -440,7 +440,7 @@
}
`)
- result.CheckSnapshot("mysdk", "",
+ CheckSnapshot(t, result, "mysdk", "",
checkAllCopyRules(`
myinclude/Test.h -> include/myinclude/Test.h
.intermediates/mynativelib1/android_arm64_armv8-a_shared/mynativelib1.so -> arm64/lib/mynativelib1.so
@@ -486,7 +486,7 @@
}
`)
- result.CheckSnapshot("mysdk", "",
+ CheckSnapshot(t, result, "mysdk", "",
checkUnversionedAndroidBpContents(`
// This is auto-generated. DO NOT EDIT.
@@ -556,7 +556,7 @@
}
`)
- result.CheckSnapshot("mysdk", "",
+ CheckSnapshot(t, result, "mysdk", "",
checkUnversionedAndroidBpContents(`
// This is auto-generated. DO NOT EDIT.
@@ -615,7 +615,7 @@
}
`)
- result.CheckSnapshot("mymodule_exports", "",
+ CheckSnapshot(t, result, "mymodule_exports", "",
checkUnversionedAndroidBpContents(`
// This is auto-generated. DO NOT EDIT.
@@ -700,7 +700,7 @@
}
`)
- result.CheckSnapshot("myexports", "",
+ CheckSnapshot(t, result, "myexports", "",
checkUnversionedAndroidBpContents(`
// This is auto-generated. DO NOT EDIT.
@@ -808,7 +808,15 @@
}
func TestSnapshotWithSingleHostOsType(t *testing.T) {
- ctx, config := testSdkContext(`
+ result := sdkFixtureFactory.Extend(
+ ccTestFs.AddToFixture(),
+ cc.PrepareForTestOnLinuxBionic,
+ android.FixtureModifyConfig(func(config android.Config) {
+ config.Targets[android.LinuxBionic] = []android.Target{
+ {android.LinuxBionic, android.Arch{ArchType: android.X86_64}, android.NativeBridgeDisabled, "", "", false},
+ }
+ }),
+ ).RunTestWithBp(t, `
cc_defaults {
name: "mydefaults",
device_supported: false,
@@ -849,11 +857,9 @@
],
stl: "none",
}
- `, ccTestFs, []android.OsType{android.LinuxBionic})
+ `)
- result := runTests(t, ctx, config)
-
- result.CheckSnapshot("myexports", "",
+ CheckSnapshot(t, result, "myexports", "",
checkUnversionedAndroidBpContents(`
// This is auto-generated. DO NOT EDIT.
@@ -991,7 +997,7 @@
}
`)
- result.CheckSnapshot("mymodule_exports", "",
+ CheckSnapshot(t, result, "mymodule_exports", "",
checkUnversionedAndroidBpContents(`
// This is auto-generated. DO NOT EDIT.
@@ -1099,7 +1105,7 @@
}
`)
- result.CheckSnapshot("mysdk", "",
+ CheckSnapshot(t, result, "mysdk", "",
checkUnversionedAndroidBpContents(`
// This is auto-generated. DO NOT EDIT.
@@ -1200,7 +1206,7 @@
}
`)
- result.CheckSnapshot("mysdk", "",
+ CheckSnapshot(t, result, "mysdk", "",
checkUnversionedAndroidBpContents(`
// This is auto-generated. DO NOT EDIT.
@@ -1297,7 +1303,7 @@
}
`)
- result.CheckSnapshot("mysdk", "",
+ CheckSnapshot(t, result, "mysdk", "",
checkUnversionedAndroidBpContents(`
// This is auto-generated. DO NOT EDIT.
@@ -1424,7 +1430,7 @@
}
`)
- result.CheckSnapshot("mysdk", "",
+ CheckSnapshot(t, result, "mysdk", "",
checkUnversionedAndroidBpContents(`
// This is auto-generated. DO NOT EDIT.
@@ -1552,7 +1558,7 @@
}
`)
- result.CheckSnapshot("myexports", "",
+ CheckSnapshot(t, result, "myexports", "",
checkUnversionedAndroidBpContents(`
// This is auto-generated. DO NOT EDIT.
@@ -1615,7 +1621,7 @@
}
`)
- result.CheckSnapshot("myexports", "",
+ CheckSnapshot(t, result, "myexports", "",
checkUnversionedAndroidBpContents(`
// This is auto-generated. DO NOT EDIT.
@@ -1729,7 +1735,7 @@
}
`)
- result.CheckSnapshot("myexports", "",
+ CheckSnapshot(t, result, "myexports", "",
checkUnversionedAndroidBpContents(`
// This is auto-generated. DO NOT EDIT.
@@ -1843,7 +1849,7 @@
}
`)
- result.CheckSnapshot("myexports", "",
+ CheckSnapshot(t, result, "myexports", "",
checkUnversionedAndroidBpContents(`
// This is auto-generated. DO NOT EDIT.
@@ -1940,7 +1946,7 @@
}
`)
- result.CheckSnapshot("mysdk", "",
+ CheckSnapshot(t, result, "mysdk", "",
checkUnversionedAndroidBpContents(`
// This is auto-generated. DO NOT EDIT.
@@ -1978,7 +1984,7 @@
}
`)
- result.CheckSnapshot("mysdk", "",
+ CheckSnapshot(t, result, "mysdk", "",
checkUnversionedAndroidBpContents(`
// This is auto-generated. DO NOT EDIT.
@@ -2080,7 +2086,7 @@
}
`)
- result.CheckSnapshot("mysdk", "",
+ CheckSnapshot(t, result, "mysdk", "",
checkUnversionedAndroidBpContents(`
// This is auto-generated. DO NOT EDIT.
@@ -2112,7 +2118,6 @@
},
}
`),
- // Verifi
checkVersionedAndroidBpContents(`
// This is auto-generated. DO NOT EDIT.
@@ -2193,7 +2198,7 @@
}
`)
- result.CheckSnapshot("mysdk", "",
+ CheckSnapshot(t, result, "mysdk", "",
checkUnversionedAndroidBpContents(`
// This is auto-generated. DO NOT EDIT.
@@ -2266,7 +2271,7 @@
}
`)
- result.CheckSnapshot("mysdk", "",
+ CheckSnapshot(t, result, "mysdk", "",
checkUnversionedAndroidBpContents(`
// This is auto-generated. DO NOT EDIT.
@@ -2377,7 +2382,7 @@
}
`)
- result.CheckSnapshot("mysdk", "",
+ CheckSnapshot(t, result, "mysdk", "",
checkUnversionedAndroidBpContents(`
// This is auto-generated. DO NOT EDIT.
@@ -2430,7 +2435,7 @@
}
`)
- result.CheckSnapshot("mysdk", "",
+ CheckSnapshot(t, result, "mysdk", "",
checkUnversionedAndroidBpContents(`
// This is auto-generated. DO NOT EDIT.
@@ -2543,7 +2548,7 @@
}
`)
- result.CheckSnapshot("mysdk", "",
+ CheckSnapshot(t, result, "mysdk", "",
checkUnversionedAndroidBpContents(`
// This is auto-generated. DO NOT EDIT.
@@ -2658,7 +2663,7 @@
}
`)
- result.CheckSnapshot("mysdk", "",
+ CheckSnapshot(t, result, "mysdk", "",
checkUnversionedAndroidBpContents(`
// This is auto-generated. DO NOT EDIT.
diff --git a/sdk/exports.go b/sdk/exports.go
index d313057..9a0ba4e 100644
--- a/sdk/exports.go
+++ b/sdk/exports.go
@@ -17,8 +17,12 @@
import "android/soong/android"
func init() {
- android.RegisterModuleType("module_exports", ModuleExportsFactory)
- android.RegisterModuleType("module_exports_snapshot", ModuleExportsSnapshotsFactory)
+ registerModuleExportsBuildComponents(android.InitRegistrationContext)
+}
+
+func registerModuleExportsBuildComponents(ctx android.RegistrationContext) {
+ ctx.RegisterModuleType("module_exports", ModuleExportsFactory)
+ ctx.RegisterModuleType("module_exports_snapshot", ModuleExportsSnapshotsFactory)
}
// module_exports defines the exports of a mainline module. The exports are Soong modules
diff --git a/sdk/exports_test.go b/sdk/exports_test.go
index 1c59244..fd7741c 100644
--- a/sdk/exports_test.go
+++ b/sdk/exports_test.go
@@ -42,7 +42,7 @@
"package/Android.bp": []byte(packageBp),
})
- result.CheckSnapshot("myexports", "package",
+ CheckSnapshot(t, result, "myexports", "package",
checkAndroidBpContents(`
// This is auto-generated. DO NOT EDIT.
diff --git a/sdk/java_sdk_test.go b/sdk/java_sdk_test.go
index 111b22c..f4e9380 100644
--- a/sdk/java_sdk_test.go
+++ b/sdk/java_sdk_test.go
@@ -17,10 +17,11 @@
import (
"testing"
+ "android/soong/android"
"android/soong/java"
)
-func testSdkWithJava(t *testing.T, bp string) *testSdkResult {
+func testSdkWithJava(t *testing.T, bp string) *android.TestResult {
t.Helper()
fs := map[string][]byte{
@@ -125,9 +126,9 @@
`)
// Make sure that the mysdk module depends on "sdkmember" and not "prebuilt_sdkmember".
- java.CheckModuleDependencies(t, result.ctx, "mysdk", "android_common", []string{"sdkmember"})
+ java.CheckModuleDependencies(t, result.TestContext, "mysdk", "android_common", []string{"sdkmember"})
- result.CheckSnapshot("mysdk", "",
+ CheckSnapshot(t, result, "mysdk", "",
checkAndroidBpContents(`// This is auto-generated. DO NOT EDIT.
java_import {
@@ -224,11 +225,11 @@
}
`)
- sdkMemberV1 := result.ctx.ModuleForTests("sdkmember_mysdk_1", "android_common").Rule("combineJar").Output
- sdkMemberV2 := result.ctx.ModuleForTests("sdkmember_mysdk_2", "android_common").Rule("combineJar").Output
+ sdkMemberV1 := result.ModuleForTests("sdkmember_mysdk_1", "android_common").Rule("combineJar").Output
+ sdkMemberV2 := result.ModuleForTests("sdkmember_mysdk_2", "android_common").Rule("combineJar").Output
- javalibForMyApex := result.ctx.ModuleForTests("myjavalib", "android_common_apex10000_mysdk_1")
- javalibForMyApex2 := result.ctx.ModuleForTests("myjavalib", "android_common_apex10000_mysdk_2")
+ javalibForMyApex := result.ModuleForTests("myjavalib", "android_common_apex10000_mysdk_1")
+ javalibForMyApex2 := result.ModuleForTests("myjavalib", "android_common_apex10000_mysdk_2")
// Depending on the uses_sdks value, different libs are linked
ensureListContains(t, pathsToStrings(javalibForMyApex.Rule("javac").Implicits), sdkMemberV1.String())
@@ -255,7 +256,7 @@
}
`)
- result.CheckSnapshot("mysdk", "",
+ CheckSnapshot(t, result, "mysdk", "",
checkAndroidBpContents(`
// This is auto-generated. DO NOT EDIT.
@@ -312,7 +313,7 @@
}
`)
- result.CheckSnapshot("mysdk", "",
+ CheckSnapshot(t, result, "mysdk", "",
checkAndroidBpContents(`
// This is auto-generated. DO NOT EDIT.
@@ -369,7 +370,7 @@
}
`)
- result.CheckSnapshot("mysdk", "",
+ CheckSnapshot(t, result, "mysdk", "",
checkAndroidBpContents(`
// This is auto-generated. DO NOT EDIT.
@@ -440,7 +441,7 @@
}
`)
- result.CheckSnapshot("myexports", "",
+ CheckSnapshot(t, result, "myexports", "",
checkAndroidBpContents(`
// This is auto-generated. DO NOT EDIT.
@@ -496,7 +497,7 @@
}
`)
- result.CheckSnapshot("myexports", "",
+ CheckSnapshot(t, result, "myexports", "",
checkAndroidBpContents(`
// This is auto-generated. DO NOT EDIT.
@@ -551,7 +552,7 @@
}
`)
- result.CheckSnapshot("myexports", "",
+ CheckSnapshot(t, result, "myexports", "",
checkAndroidBpContents(`
// This is auto-generated. DO NOT EDIT.
@@ -607,7 +608,7 @@
}
`)
- result.CheckSnapshot("myexports", "",
+ CheckSnapshot(t, result, "myexports", "",
checkAndroidBpContents(`
// This is auto-generated. DO NOT EDIT.
@@ -662,7 +663,7 @@
}
`)
- result.CheckSnapshot("myexports", "",
+ CheckSnapshot(t, result, "myexports", "",
checkAndroidBpContents(`
// This is auto-generated. DO NOT EDIT.
@@ -731,7 +732,7 @@
}
`)
- result.CheckSnapshot("mysdk", "",
+ CheckSnapshot(t, result, "mysdk", "",
checkAndroidBpContents(`
// This is auto-generated. DO NOT EDIT.
@@ -827,7 +828,7 @@
}
`)
- result.CheckSnapshot("mysdk", "",
+ CheckSnapshot(t, result, "mysdk", "",
checkAndroidBpContents(`
// This is auto-generated. DO NOT EDIT.
@@ -918,7 +919,7 @@
}
`)
- result.CheckSnapshot("myexports", "",
+ CheckSnapshot(t, result, "myexports", "",
checkAndroidBpContents(`
// This is auto-generated. DO NOT EDIT.
@@ -1032,7 +1033,7 @@
}
`)
- result.CheckSnapshot("mysdk", "",
+ CheckSnapshot(t, result, "mysdk", "",
checkAndroidBpContents(`
// This is auto-generated. DO NOT EDIT.
@@ -1133,7 +1134,7 @@
}
`)
- result.CheckSnapshot("mysdk", "",
+ CheckSnapshot(t, result, "mysdk", "",
checkAndroidBpContents(`
// This is auto-generated. DO NOT EDIT.
@@ -1202,7 +1203,7 @@
}
`)
- result.CheckSnapshot("mysdk", "",
+ CheckSnapshot(t, result, "mysdk", "",
checkAndroidBpContents(`
// This is auto-generated. DO NOT EDIT.
@@ -1274,7 +1275,7 @@
}
`)
- result.CheckSnapshot("mysdk", "",
+ CheckSnapshot(t, result, "mysdk", "",
checkAndroidBpContents(`
// This is auto-generated. DO NOT EDIT.
@@ -1367,7 +1368,7 @@
}
`)
- result.CheckSnapshot("mysdk", "",
+ CheckSnapshot(t, result, "mysdk", "",
checkAndroidBpContents(`
// This is auto-generated. DO NOT EDIT.
@@ -1475,7 +1476,7 @@
}
`)
- result.CheckSnapshot("mysdk", "",
+ CheckSnapshot(t, result, "mysdk", "",
checkAndroidBpContents(`
// This is auto-generated. DO NOT EDIT.
@@ -1563,7 +1564,7 @@
}
`)
- result.CheckSnapshot("mysdk", "",
+ CheckSnapshot(t, result, "mysdk", "",
checkAndroidBpContents(`
// This is auto-generated. DO NOT EDIT.
@@ -1639,7 +1640,7 @@
}
`)
- result.CheckSnapshot("mysdk", "",
+ CheckSnapshot(t, result, "mysdk", "",
checkAndroidBpContents(`
// This is auto-generated. DO NOT EDIT.
diff --git a/sdk/sdk.go b/sdk/sdk.go
index f3d0750..2c84a2e 100644
--- a/sdk/sdk.go
+++ b/sdk/sdk.go
@@ -33,10 +33,14 @@
pctx.Import("android/soong/android")
pctx.Import("android/soong/java/config")
- android.RegisterModuleType("sdk", SdkModuleFactory)
- android.RegisterModuleType("sdk_snapshot", SnapshotModuleFactory)
- android.PreDepsMutators(RegisterPreDepsMutators)
- android.PostDepsMutators(RegisterPostDepsMutators)
+ registerSdkBuildComponents(android.InitRegistrationContext)
+}
+
+func registerSdkBuildComponents(ctx android.RegistrationContext) {
+ ctx.RegisterModuleType("sdk", SdkModuleFactory)
+ ctx.RegisterModuleType("sdk_snapshot", SnapshotModuleFactory)
+ ctx.PreDepsMutators(RegisterPreDepsMutators)
+ ctx.PostDepsMutators(RegisterPostDepsMutators)
}
type sdk struct {
diff --git a/sdk/sdk_test.go b/sdk/sdk_test.go
index c4dc41b..05d8bdb 100644
--- a/sdk/sdk_test.go
+++ b/sdk/sdk_test.go
@@ -169,7 +169,7 @@
"package/Android.bp": []byte(packageBp),
})
- result.CheckSnapshot("mysdk", "package",
+ CheckSnapshot(t, result, "mysdk", "package",
checkAndroidBpContents(`
// This is auto-generated. DO NOT EDIT.
@@ -309,20 +309,16 @@
`)
}
-func TestSDkInstall(t *testing.T) {
+func TestSdkInstall(t *testing.T) {
sdk := `
sdk {
name: "mysdk",
}
`
- result := testSdkWithFs(t, ``,
- map[string][]byte{
- "Android.bp": []byte(sdk),
- })
+ result := testSdkWithFs(t, sdk, nil)
- result.CheckSnapshot("mysdk", "",
- checkAllOtherCopyRules(`.intermediates/mysdk/common_os/mysdk-current.zip -> mysdk-current.zip`),
- )
+ CheckSnapshot(t, result, "mysdk", "",
+ checkAllOtherCopyRules(`.intermediates/mysdk/common_os/mysdk-current.zip -> mysdk-current.zip`))
}
type EmbeddedPropertiesStruct struct {
@@ -390,12 +386,10 @@
extractor := newCommonValueExtractor(common)
- h := TestHelper{t}
-
err := extractor.extractCommonProperties(common, structs)
- h.AssertDeepEquals("unexpected error", nil, err)
+ android.AssertDeepEquals(t, "unexpected error", nil, err)
- h.AssertDeepEquals("common properties not correct",
+ android.AssertDeepEquals(t, "common properties not correct",
&testPropertiesStruct{
name: "common",
private: "",
@@ -413,7 +407,7 @@
},
common)
- h.AssertDeepEquals("updated properties[0] not correct",
+ android.AssertDeepEquals(t, "updated properties[0] not correct",
&testPropertiesStruct{
name: "struct-0",
private: "common",
@@ -431,7 +425,7 @@
},
structs[0])
- h.AssertDeepEquals("updated properties[1] not correct",
+ android.AssertDeepEquals(t, "updated properties[1] not correct",
&testPropertiesStruct{
name: "struct-1",
private: "common",
@@ -465,10 +459,8 @@
extractor := newCommonValueExtractor(common)
- h := TestHelper{t}
-
err := extractor.extractCommonProperties(common, structs)
- h.AssertErrorMessageEquals("unexpected error", `field "S_Common" is not tagged as "arch_variant" but has arch specific properties:
+ android.AssertErrorMessageEquals(t, "unexpected error", `field "S_Common" is not tagged as "arch_variant" but has arch specific properties:
"struct-0" has value "should-be-but-is-not-common0"
"struct-1" has value "should-be-but-is-not-common1"`, err)
}
diff --git a/sdk/testing.go b/sdk/testing.go
index 7a2540a..a5519f8 100644
--- a/sdk/testing.go
+++ b/sdk/testing.go
@@ -19,7 +19,6 @@
"io/ioutil"
"os"
"path/filepath"
- "reflect"
"strings"
"testing"
@@ -30,10 +29,15 @@
"android/soong/java"
)
-func testSdkContext(bp string, fs map[string][]byte, extraOsTypes []android.OsType) (*android.TestContext, android.Config) {
- extraOsTypes = append(extraOsTypes, android.Android, android.Windows)
+var sdkFixtureFactory = android.NewFixtureFactory(
+ &buildDir,
+ apex.PrepareForTestWithApexBuildComponents,
+ cc.PrepareForTestWithCcDefaultModules,
+ genrule.PrepareForTestWithGenRuleBuildComponents,
+ java.PrepareForTestWithJavaBuildComponents,
+ PrepareForTestWithSdkBuildComponents,
- bp = bp + `
+ android.FixtureAddTextFile("sdk/tests/Android.bp", `
apex_key {
name: "myapex.key",
public_key: "myapex.avbpubkey",
@@ -44,9 +48,9 @@
name: "myapex.cert",
certificate: "myapex",
}
- ` + cc.GatherRequiredDepsForTest(extraOsTypes...)
+ `),
- mockFS := map[string][]byte{
+ android.FixtureMergeMockFs(map[string][]byte{
"build/make/target/product/security": nil,
"apex_manifest.json": nil,
"system/sepolicy/apex/myapex-file_contexts": nil,
@@ -56,118 +60,33 @@
"myapex.pem": nil,
"myapex.x509.pem": nil,
"myapex.pk8": nil,
- }
+ }),
- cc.GatherRequiredFilesForTest(mockFS)
-
- for k, v := range fs {
- mockFS[k] = v
- }
-
- config := android.TestArchConfig(buildDir, nil, bp, mockFS)
-
- // Add windows as a default disable OS to test behavior when some OS variants
- // are disabled.
- config.Targets[android.Windows] = []android.Target{
- {android.Windows, android.Arch{ArchType: android.X86_64}, android.NativeBridgeDisabled, "", "", true},
- }
-
- for _, extraOsType := range extraOsTypes {
- switch extraOsType {
- case android.LinuxBionic:
- config.Targets[android.LinuxBionic] = []android.Target{
- {android.LinuxBionic, android.Arch{ArchType: android.X86_64}, android.NativeBridgeDisabled, "", "", false},
- }
+ cc.PrepareForTestOnWindows,
+ android.FixtureModifyConfig(func(config android.Config) {
+ // Add windows as a default disable OS to test behavior when some OS variants
+ // are disabled.
+ config.Targets[android.Windows] = []android.Target{
+ {android.Windows, android.Arch{ArchType: android.X86_64}, android.NativeBridgeDisabled, "", "", true},
}
- }
+ }),
+)
- ctx := android.NewTestArchContext(config)
+var PrepareForTestWithSdkBuildComponents = android.GroupFixturePreparers(
+ android.FixtureRegisterWithContext(registerModuleExportsBuildComponents),
+ android.FixtureRegisterWithContext(registerSdkBuildComponents),
+)
- // Enable androidmk support.
- // * Register the singleton
- // * Configure that we are inside make
- // * Add CommonOS to ensure that androidmk processing works.
- android.RegisterAndroidMkBuildComponents(ctx)
- android.SetKatiEnabledForTests(config)
- config.Targets[android.CommonOS] = []android.Target{
- {android.CommonOS, android.Arch{ArchType: android.Common}, android.NativeBridgeDisabled, "", "", true},
- }
-
- // from android package
- android.RegisterPackageBuildComponents(ctx)
- ctx.RegisterModuleType("filegroup", android.FileGroupFactory)
- ctx.PreArchMutators(android.RegisterVisibilityRuleChecker)
- ctx.PreArchMutators(android.RegisterDefaultsPreArchMutators)
- ctx.PreArchMutators(android.RegisterComponentsMutator)
-
- android.RegisterPrebuiltMutators(ctx)
-
- // Register these after the prebuilt mutators have been registered to match what
- // happens at runtime.
- ctx.PreArchMutators(android.RegisterVisibilityRuleGatherer)
- ctx.PostDepsMutators(android.RegisterVisibilityRuleEnforcer)
-
- // from java package
- java.RegisterRequiredBuildComponentsForTest(ctx)
-
- // from genrule package
- genrule.RegisterGenruleBuildComponents(ctx)
-
- // from cc package
- cc.RegisterRequiredBuildComponentsForTest(ctx)
-
- // from apex package
- ctx.RegisterModuleType("apex", apex.BundleFactory)
- ctx.RegisterModuleType("apex_key", apex.ApexKeyFactory)
- ctx.PostDepsMutators(apex.RegisterPostDepsMutators)
-
- // from this package
- ctx.RegisterModuleType("sdk", SdkModuleFactory)
- ctx.RegisterModuleType("sdk_snapshot", SnapshotModuleFactory)
- ctx.RegisterModuleType("module_exports", ModuleExportsFactory)
- ctx.RegisterModuleType("module_exports_snapshot", ModuleExportsSnapshotsFactory)
- ctx.PreDepsMutators(RegisterPreDepsMutators)
- ctx.PostDepsMutators(RegisterPostDepsMutators)
-
- ctx.Register()
-
- return ctx, config
-}
-
-func runTests(t *testing.T, ctx *android.TestContext, config android.Config) *testSdkResult {
+func testSdkWithFs(t *testing.T, bp string, fs android.MockFS) *android.TestResult {
t.Helper()
- _, errs := ctx.ParseBlueprintsFiles(".")
- android.FailIfErrored(t, errs)
- _, errs = ctx.PrepareBuildActions(config)
- android.FailIfErrored(t, errs)
- return &testSdkResult{
- TestHelper: TestHelper{t: t},
- ctx: ctx,
- config: config,
- }
-}
-
-func testSdkWithFs(t *testing.T, bp string, fs map[string][]byte) *testSdkResult {
- t.Helper()
- ctx, config := testSdkContext(bp, fs, nil)
- return runTests(t, ctx, config)
+ return sdkFixtureFactory.RunTest(t, fs.AddToFixture(), android.FixtureWithRootAndroidBp(bp))
}
func testSdkError(t *testing.T, pattern, bp string) {
t.Helper()
- ctx, config := testSdkContext(bp, nil, nil)
- _, errs := ctx.ParseFileList(".", []string{"Android.bp"})
- if len(errs) > 0 {
- android.FailIfNoMatchingErrors(t, pattern, errs)
- return
- }
- _, errs = ctx.PrepareBuildActions(config)
- if len(errs) > 0 {
- android.FailIfNoMatchingErrors(t, pattern, errs)
- return
- }
-
- t.Fatalf("missing expected error %q (0 errors are returned)", pattern)
+ sdkFixtureFactory.
+ ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern(pattern)).
+ RunTestWithBp(t, bp)
}
func ensureListContains(t *testing.T, result []string, expected string) {
@@ -185,74 +104,14 @@
return ret
}
-// Provides general test support.
-type TestHelper struct {
- t *testing.T
-}
-
-func (h *TestHelper) AssertStringEquals(message string, expected string, actual string) {
- h.t.Helper()
- if actual != expected {
- h.t.Errorf("%s: expected %s, actual %s", message, expected, actual)
- }
-}
-
-func (h *TestHelper) AssertErrorMessageEquals(message string, expected string, actual error) {
- h.t.Helper()
- if actual == nil {
- h.t.Errorf("Expected error but was nil")
- } else if actual.Error() != expected {
- h.t.Errorf("%s: expected %s, actual %s", message, expected, actual.Error())
- }
-}
-
-func (h *TestHelper) AssertTrimmedStringEquals(message string, expected string, actual string) {
- h.t.Helper()
- expected = strings.TrimSpace(expected)
- actual = strings.TrimSpace(actual)
- if actual != expected {
- h.t.Errorf("%s: expected:\n%s\nactual:\n%s\n", message, expected, actual)
- }
-}
-
-func (h *TestHelper) AssertDeepEquals(message string, expected interface{}, actual interface{}) {
- h.t.Helper()
- if !reflect.DeepEqual(actual, expected) {
- h.t.Errorf("%s: expected %#v, actual %#v", message, expected, actual)
- }
-}
-
-func (h *TestHelper) AssertPanic(message string, funcThatShouldPanic func()) {
- h.t.Helper()
- panicked := false
- func() {
- defer func() {
- if x := recover(); x != nil {
- panicked = true
- }
- }()
- funcThatShouldPanic()
- }()
- if !panicked {
- h.t.Error(message)
- }
-}
-
-// Encapsulates result of processing an SDK definition. Provides support for
-// checking the state of the build structures.
-type testSdkResult struct {
- TestHelper
- ctx *android.TestContext
- config android.Config
-}
-
// Analyse the sdk build rules to extract information about what it is doing.
-
+//
// e.g. find the src/dest pairs from each cp command, the various zip files
// generated, etc.
-func (r *testSdkResult) getSdkSnapshotBuildInfo(sdk *sdk) *snapshotBuildInfo {
+func getSdkSnapshotBuildInfo(t *testing.T, result *android.TestResult, sdk *sdk) *snapshotBuildInfo {
info := &snapshotBuildInfo{
- r: r,
+ t: t,
+ r: result,
androidBpContents: sdk.GetAndroidBpContentsForTests(),
androidUnversionedBpContents: sdk.GetUnversionedAndroidBpContentsForTests(),
androidVersionedBpContents: sdk.GetVersionedAndroidBpContentsForTests(),
@@ -295,7 +154,7 @@
info.intermediateZip = info.outputZip
mergeInput := android.NormalizePathForTesting(bp.Input)
if info.intermediateZip != mergeInput {
- r.t.Errorf("Expected intermediate zip %s to be an input to merge zips but found %s instead",
+ t.Errorf("Expected intermediate zip %s to be an input to merge zips but found %s instead",
info.intermediateZip, mergeInput)
}
@@ -314,28 +173,20 @@
return info
}
-func (r *testSdkResult) Module(name string, variant string) android.Module {
- return r.ctx.ModuleForTests(name, variant).Module()
-}
-
-func (r *testSdkResult) ModuleForTests(name string, variant string) android.TestingModule {
- return r.ctx.ModuleForTests(name, variant)
-}
-
// Check the snapshot build rules.
//
// Takes a list of functions which check different facets of the snapshot build rules.
// Allows each test to customize what is checked without duplicating lots of code
// or proliferating check methods of different flavors.
-func (r *testSdkResult) CheckSnapshot(name string, dir string, checkers ...snapshotBuildInfoChecker) {
- r.t.Helper()
+func CheckSnapshot(t *testing.T, result *android.TestResult, name string, dir string, checkers ...snapshotBuildInfoChecker) {
+ t.Helper()
// The sdk CommonOS variant is always responsible for generating the snapshot.
variant := android.CommonOS.Name
- sdk := r.Module(name, variant).(*sdk)
+ sdk := result.Module(name, variant).(*sdk)
- snapshotBuildInfo := r.getSdkSnapshotBuildInfo(sdk)
+ snapshotBuildInfo := getSdkSnapshotBuildInfo(t, result, sdk)
// Check state of the snapshot build.
for _, checker := range checkers {
@@ -347,7 +198,7 @@
if dir != "" {
dir = filepath.Clean(dir) + "/"
}
- r.AssertStringEquals("Snapshot zip file in wrong place",
+ android.AssertStringEquals(t, "Snapshot zip file in wrong place",
fmt.Sprintf(".intermediates/%s%s/%s/%s-current.zip", dir, name, variant, name), actual)
// Populate a mock filesystem with the files that would have been copied by
@@ -358,7 +209,7 @@
}
// Process the generated bp file to make sure it is valid.
- testSdkWithFs(r.t, snapshotBuildInfo.androidBpContents, fs)
+ testSdkWithFs(t, snapshotBuildInfo.androidBpContents, fs)
}
type snapshotBuildInfoChecker func(info *snapshotBuildInfo)
@@ -368,8 +219,8 @@
// Both the expected and actual string are both trimmed before comparing.
func checkAndroidBpContents(expected string) snapshotBuildInfoChecker {
return func(info *snapshotBuildInfo) {
- info.r.t.Helper()
- info.r.AssertTrimmedStringEquals("Android.bp contents do not match", expected, info.androidBpContents)
+ info.t.Helper()
+ android.AssertTrimmedStringEquals(info.t, "Android.bp contents do not match", expected, info.androidBpContents)
}
}
@@ -380,8 +231,8 @@
// Both the expected and actual string are both trimmed before comparing.
func checkUnversionedAndroidBpContents(expected string) snapshotBuildInfoChecker {
return func(info *snapshotBuildInfo) {
- info.r.t.Helper()
- info.r.AssertTrimmedStringEquals("unversioned Android.bp contents do not match", expected, info.androidUnversionedBpContents)
+ info.t.Helper()
+ android.AssertTrimmedStringEquals(info.t, "unversioned Android.bp contents do not match", expected, info.androidUnversionedBpContents)
}
}
@@ -395,8 +246,8 @@
// Both the expected and actual string are both trimmed before comparing.
func checkVersionedAndroidBpContents(expected string) snapshotBuildInfoChecker {
return func(info *snapshotBuildInfo) {
- info.r.t.Helper()
- info.r.AssertTrimmedStringEquals("versioned Android.bp contents do not match", expected, info.androidVersionedBpContents)
+ info.t.Helper()
+ android.AssertTrimmedStringEquals(info.t, "versioned Android.bp contents do not match", expected, info.androidVersionedBpContents)
}
}
@@ -407,27 +258,27 @@
// before comparing.
func checkAllCopyRules(expected string) snapshotBuildInfoChecker {
return func(info *snapshotBuildInfo) {
- info.r.t.Helper()
- info.r.AssertTrimmedStringEquals("Incorrect copy rules", expected, info.copyRules)
+ info.t.Helper()
+ android.AssertTrimmedStringEquals(info.t, "Incorrect copy rules", expected, info.copyRules)
}
}
func checkAllOtherCopyRules(expected string) snapshotBuildInfoChecker {
return func(info *snapshotBuildInfo) {
- info.r.t.Helper()
- info.r.AssertTrimmedStringEquals("Incorrect copy rules", expected, info.otherCopyRules)
+ info.t.Helper()
+ android.AssertTrimmedStringEquals(info.t, "Incorrect copy rules", expected, info.otherCopyRules)
}
}
// Check that the specified paths match the list of zips to merge with the intermediate zip.
func checkMergeZips(expected ...string) snapshotBuildInfoChecker {
return func(info *snapshotBuildInfo) {
- info.r.t.Helper()
+ info.t.Helper()
if info.intermediateZip == "" {
- info.r.t.Errorf("No intermediate zip file was created")
+ info.t.Errorf("No intermediate zip file was created")
}
- info.r.AssertDeepEquals("mismatching merge zip files", expected, info.mergeZips)
+ android.AssertDeepEquals(info.t, "mismatching merge zip files", expected, info.mergeZips)
}
}
@@ -437,7 +288,10 @@
// All source/input paths are relative either the build directory. All dest/output paths are
// relative to the snapshot root directory.
type snapshotBuildInfo struct {
- r *testSdkResult
+ t *testing.T
+
+ // The result from RunTest()
+ r *android.TestResult
// The contents of the generated Android.bp file
androidBpContents string
diff --git a/sh/sh_binary.go b/sh/sh_binary.go
index 031cd47..49f4961 100644
--- a/sh/sh_binary.go
+++ b/sh/sh_binary.go
@@ -40,14 +40,32 @@
func init() {
pctx.Import("android/soong/android")
- android.RegisterModuleType("sh_binary", ShBinaryFactory)
- android.RegisterModuleType("sh_binary_host", ShBinaryHostFactory)
- android.RegisterModuleType("sh_test", ShTestFactory)
- android.RegisterModuleType("sh_test_host", ShTestHostFactory)
+ registerShBuildComponents(android.InitRegistrationContext)
android.RegisterBp2BuildMutator("sh_binary", ShBinaryBp2Build)
}
+func registerShBuildComponents(ctx android.RegistrationContext) {
+ ctx.RegisterModuleType("sh_binary", ShBinaryFactory)
+ ctx.RegisterModuleType("sh_binary_host", ShBinaryHostFactory)
+ ctx.RegisterModuleType("sh_test", ShTestFactory)
+ ctx.RegisterModuleType("sh_test_host", ShTestHostFactory)
+}
+
+// Test fixture preparer that will register most sh build components.
+//
+// Singletons and mutators should only be added here if they are needed for a majority of sh
+// module types, otherwise they should be added under a separate preparer to allow them to be
+// selected only when needed to reduce test execution time.
+//
+// Module types do not have much of an overhead unless they are used so this should include as many
+// module types as possible. The exceptions are those module types that require mutators and/or
+// singletons in order to function in which case they should be kept together in a separate
+// preparer.
+var PrepareForTestWithShBuildComponents = android.GroupFixturePreparers(
+ android.FixtureRegisterWithContext(registerShBuildComponents),
+)
+
type shBinaryProperties struct {
// Source file of this prebuilt.
Src *string `android:"path,arch_variant"`
diff --git a/sh/sh_binary_test.go b/sh/sh_binary_test.go
index f48f7fb..7a24168 100644
--- a/sh/sh_binary_test.go
+++ b/sh/sh_binary_test.go
@@ -37,28 +37,32 @@
os.Exit(run())
}
-func testShBinary(t *testing.T, bp string) (*android.TestContext, android.Config) {
- fs := map[string][]byte{
+var shFixtureFactory = android.NewFixtureFactory(
+ &buildDir,
+ cc.PrepareForTestWithCcBuildComponents,
+ PrepareForTestWithShBuildComponents,
+ android.FixtureMergeMockFs(android.MockFS{
"test.sh": nil,
"testdata/data1": nil,
"testdata/sub/data2": nil,
- }
+ }),
+)
- config := android.TestArchConfig(buildDir, nil, bp, fs)
+// testShBinary runs tests using the shFixtureFactory
+//
+// Do not add any new usages of this, instead use the shFixtureFactory directly as it makes it much
+// easier to customize the test behavior.
+//
+// If it is necessary to customize the behavior of an existing test that uses this then please first
+// convert the test to using shFixtureFactory first and then in a following change add the
+// appropriate fixture preparers. Keeping the conversion change separate makes it easy to verify
+// that it did not change the test behavior unexpectedly.
+//
+// deprecated
+func testShBinary(t *testing.T, bp string) (*android.TestContext, android.Config) {
+ result := shFixtureFactory.RunTestWithBp(t, bp)
- ctx := android.NewTestArchContext(config)
- ctx.RegisterModuleType("sh_test", ShTestFactory)
- ctx.RegisterModuleType("sh_test_host", ShTestHostFactory)
-
- cc.RegisterRequiredBuildComponentsForTest(ctx)
-
- ctx.Register()
- _, errs := ctx.ParseFileList(".", []string{"Android.bp"})
- android.FailIfErrored(t, errs)
- _, errs = ctx.PrepareBuildActions(config)
- android.FailIfErrored(t, errs)
-
- return ctx, config
+ return result.TestContext, result.Config
}
func TestShTestSubDir(t *testing.T) {
diff --git a/shared/debug.go b/shared/debug.go
index 0c9ba4f..5392f2b 100644
--- a/shared/debug.go
+++ b/shared/debug.go
@@ -1,8 +1,15 @@
package shared
import (
+ "fmt"
"os"
"os/exec"
+ "strings"
+ "syscall"
+)
+
+var (
+ isDebugging bool
)
// Finds the Delve binary to use. Either uses the SOONG_DELVE_PATH environment
@@ -15,3 +22,48 @@
return result
}
+
+// Returns whether the current process is running under Delve due to
+// ReexecWithDelveMaybe().
+func IsDebugging() bool {
+ return isDebugging
+}
+
+// Re-executes the binary in question under the control of Delve when
+// delveListen is not the empty string. delvePath gives the path to the Delve.
+func ReexecWithDelveMaybe(delveListen, delvePath string) {
+ isDebugging = os.Getenv("SOONG_DELVE_REEXECUTED") == "true"
+ if isDebugging || delveListen == "" {
+ return
+ }
+
+ if delvePath == "" {
+ fmt.Fprintln(os.Stderr, "Delve debugging requested but failed to find dlv")
+ os.Exit(1)
+ }
+
+ soongDelveEnv := []string{}
+ for _, env := range os.Environ() {
+ idx := strings.IndexRune(env, '=')
+ if idx != -1 {
+ soongDelveEnv = append(soongDelveEnv, env)
+ }
+ }
+
+ soongDelveEnv = append(soongDelveEnv, "SOONG_DELVE_REEXECUTED=true")
+
+ dlvArgv := []string{
+ delvePath,
+ "--listen=:" + delveListen,
+ "--headless=true",
+ "--api-version=2",
+ "exec",
+ os.Args[0],
+ "--",
+ }
+
+ dlvArgv = append(dlvArgv, os.Args[1:]...)
+ syscall.Exec(delvePath, dlvArgv, soongDelveEnv)
+ fmt.Fprintln(os.Stderr, "exec() failed while trying to reexec with Delve")
+ os.Exit(1)
+}
diff --git a/sysprop/sysprop_library.go b/sysprop/sysprop_library.go
index 4ad68ea..892a16c 100644
--- a/sysprop/sysprop_library.go
+++ b/sysprop/sysprop_library.go
@@ -165,6 +165,12 @@
// Forwarded to cc_library.min_sdk_version
Min_sdk_version *string
}
+
+ Java struct {
+ // Minimum sdk version that the artifact should support when it runs as part of mainline modules(APEX).
+ // Forwarded to java_library.min_sdk_version
+ Min_sdk_version *string
+ }
}
var (
@@ -403,6 +409,8 @@
Libs []string
Stem *string
SyspropPublicStub string
+ Apex_available []string
+ Min_sdk_version *string
}
func syspropLibraryHook(ctx android.LoadHookContext, m *syspropLibrary) {
@@ -508,6 +516,8 @@
Sdk_version: proptools.StringPtr("core_current"),
Libs: []string{javaSyspropStub},
SyspropPublicStub: publicStub,
+ Apex_available: m.ApexProperties.Apex_available,
+ Min_sdk_version: m.properties.Java.Min_sdk_version,
})
if publicStub != "" {
diff --git a/sysprop/sysprop_test.go b/sysprop/sysprop_test.go
index 9d914e3..fde41d6 100644
--- a/sysprop/sysprop_test.go
+++ b/sysprop/sysprop_test.go
@@ -81,6 +81,51 @@
}
func testConfig(env map[string]string, bp string, fs map[string][]byte) android.Config {
+ bp += `
+ cc_library {
+ name: "libbase",
+ host_supported: true,
+ }
+
+ cc_library_headers {
+ name: "libbase_headers",
+ vendor_available: true,
+ recovery_available: true,
+ }
+
+ cc_library {
+ name: "liblog",
+ no_libcrt: true,
+ nocrt: true,
+ system_shared_libs: [],
+ recovery_available: true,
+ host_supported: true,
+ llndk_stubs: "liblog.llndk",
+ }
+
+ llndk_library {
+ name: "liblog.llndk",
+ symbol_file: "",
+ }
+
+ java_library {
+ name: "sysprop-library-stub-platform",
+ sdk_version: "core_current",
+ }
+
+ java_library {
+ name: "sysprop-library-stub-vendor",
+ soc_specific: true,
+ sdk_version: "core_current",
+ }
+
+ java_library {
+ name: "sysprop-library-stub-product",
+ product_specific: true,
+ sdk_version: "core_current",
+ }
+ `
+
bp += cc.GatherRequiredDepsForTest(android.Android)
mockFS := map[string][]byte{
@@ -250,54 +295,11 @@
static_libs: ["sysprop-platform", "sysprop-vendor"],
}
- cc_library {
- name: "libbase",
- host_supported: true,
- }
-
- cc_library_headers {
- name: "libbase_headers",
- vendor_available: true,
- recovery_available: true,
- }
-
- cc_library {
- name: "liblog",
- no_libcrt: true,
- nocrt: true,
- system_shared_libs: [],
- recovery_available: true,
- host_supported: true,
- llndk_stubs: "liblog.llndk",
- }
-
cc_binary_host {
name: "hostbin",
static_libs: ["sysprop-platform"],
}
-
- llndk_library {
- name: "liblog.llndk",
- symbol_file: "",
- }
-
- java_library {
- name: "sysprop-library-stub-platform",
- sdk_version: "core_current",
- }
-
- java_library {
- name: "sysprop-library-stub-vendor",
- soc_specific: true,
- sdk_version: "core_current",
- }
-
- java_library {
- name: "sysprop-library-stub-product",
- product_specific: true,
- sdk_version: "core_current",
- }
- `)
+ `)
// Check for generated cc_library
for _, variant := range []string{
@@ -391,3 +393,62 @@
t.Errorf("system api client should use public stub %q, got %q", w, g)
}
}
+
+func TestApexAvailabilityIsForwarded(t *testing.T) {
+ ctx := test(t, `
+ sysprop_library {
+ name: "sysprop-platform",
+ apex_available: ["//apex_available:platform"],
+ srcs: ["android/sysprop/PlatformProperties.sysprop"],
+ api_packages: ["android.sysprop"],
+ property_owner: "Platform",
+ }
+ `)
+
+ expected := []string{"//apex_available:platform"}
+
+ ccModule := ctx.ModuleForTests("libsysprop-platform", "android_arm64_armv8-a_shared").Module().(*cc.Module)
+ propFromCc := ccModule.ApexProperties.Apex_available
+ if !reflect.DeepEqual(propFromCc, expected) {
+ t.Errorf("apex_available not forwarded to cc module. expected %#v, got %#v",
+ expected, propFromCc)
+ }
+
+ javaModule := ctx.ModuleForTests("sysprop-platform", "android_common").Module().(*java.Library)
+ propFromJava := javaModule.ApexProperties.Apex_available
+ if !reflect.DeepEqual(propFromJava, expected) {
+ t.Errorf("apex_available not forwarded to java module. expected %#v, got %#v",
+ expected, propFromJava)
+ }
+}
+
+func TestMinSdkVersionIsForwarded(t *testing.T) {
+ ctx := test(t, `
+ sysprop_library {
+ name: "sysprop-platform",
+ srcs: ["android/sysprop/PlatformProperties.sysprop"],
+ api_packages: ["android.sysprop"],
+ property_owner: "Platform",
+ cpp: {
+ min_sdk_version: "29",
+ },
+ java: {
+ min_sdk_version: "30",
+ },
+ }
+ `)
+
+ ccModule := ctx.ModuleForTests("libsysprop-platform", "android_arm64_armv8-a_shared").Module().(*cc.Module)
+ propFromCc := proptools.String(ccModule.Properties.Min_sdk_version)
+ if propFromCc != "29" {
+ t.Errorf("min_sdk_version not forwarded to cc module. expected %#v, got %#v",
+ "29", propFromCc)
+ }
+
+ javaModule := ctx.ModuleForTests("sysprop-platform", "android_common").Module().(*java.Library)
+ propFromJava := javaModule.MinSdkVersion()
+ if propFromJava != "30" {
+ t.Errorf("min_sdk_version not forwarded to java module. expected %#v, got %#v",
+ "30", propFromJava)
+ }
+}
diff --git a/ui/build/config.go b/ui/build/config.go
index 15da1bc..1152cd7 100644
--- a/ui/build/config.go
+++ b/ui/build/config.go
@@ -56,7 +56,6 @@
katiSuffix string
targetDevice string
targetDeviceDir string
- fullBuild bool
// Autodetected
totalRAM uint64
@@ -792,14 +791,6 @@
c.targetDevice = device
}
-func (c *configImpl) FullBuild() bool {
- return c.fullBuild
-}
-
-func (c *configImpl) SetFullBuild(fullBuild bool) {
- c.fullBuild = fullBuild
-}
-
func (c *configImpl) TargetBuildVariant() string {
if v, ok := c.environ.Get("TARGET_BUILD_VARIANT"); ok {
return v
diff --git a/ui/build/dumpvars.go b/ui/build/dumpvars.go
index be6f00a..fe0aca9 100644
--- a/ui/build/dumpvars.go
+++ b/ui/build/dumpvars.go
@@ -214,9 +214,6 @@
// So that later Kati runs can find BoardConfig.mk faster
"TARGET_DEVICE_DIR",
- // To decide whether to skip the old installed cleanup step.
- "FULL_BUILD",
-
// Whether --werror_overriding_commands will work
"BUILD_BROKEN_DUP_RULES",
@@ -281,7 +278,6 @@
config.SetNinjaArgs(strings.Fields(makeVars["NINJA_GOALS"]))
config.SetTargetDevice(makeVars["TARGET_DEVICE"])
config.SetTargetDeviceDir(makeVars["TARGET_DEVICE_DIR"])
- config.SetFullBuild(makeVars["FULL_BUILD"] == "true")
config.SetBuildBrokenDupRules(makeVars["BUILD_BROKEN_DUP_RULES"] == "true")
config.SetBuildBrokenUsesNetwork(makeVars["BUILD_BROKEN_USES_NETWORK"] == "true")
diff --git a/ui/build/kati.go b/ui/build/kati.go
index 668b20e..06ec646 100644
--- a/ui/build/kati.go
+++ b/ui/build/kati.go
@@ -229,11 +229,7 @@
// Cleanup steps.
cleanCopyHeaders(ctx, config)
- // Skip the old installed file cleanup step for few non-full build goals as we don't create
- // an installed file list for them.
- if config.FullBuild() {
- cleanOldInstalledFiles(ctx, config)
- }
+ cleanOldInstalledFiles(ctx, config)
}
// Clean out obsolete header files on the disk that were *not copied* during the
diff --git a/ui/build/soong.go b/ui/build/soong.go
index 242282b..884e957 100644
--- a/ui/build/soong.go
+++ b/ui/build/soong.go
@@ -105,11 +105,6 @@
soongBuildEnv.Set("BAZEL_WORKSPACE", absPath(ctx, "."))
soongBuildEnv.Set("BAZEL_METRICS_DIR", config.BazelMetricsDir())
- if os.Getenv("SOONG_DELVE") != "" {
- // SOONG_DELVE is already in cmd.Environment
- soongBuildEnv.Set("SOONG_DELVE_PATH", shared.ResolveDelveBinary())
- }
-
err := writeEnvironmentFile(ctx, envFile, soongBuildEnv.AsMap())
if err != nil {
ctx.Fatalf("failed to write environment file %s: %s", envFile, err)
@@ -121,7 +116,7 @@
envFile := filepath.Join(config.SoongOutDir(), "soong.environment.used")
getenv := func(k string) string {
- v, _ := config.Environment().Get(k)
+ v, _ := soongBuildEnv.Get(k)
return v
}
if stale, _ := shared.StaleEnvFile(envFile, getenv); stale {
@@ -175,7 +170,20 @@
"--frontend_file", fifo,
"-f", filepath.Join(config.SoongOutDir(), file))
- cmd.Environment.Set("SOONG_OUTDIR", config.SoongOutDir())
+ var ninjaEnv Environment
+
+ // This is currently how the command line to invoke soong_build finds the
+ // root of the source tree and the output root
+ ninjaEnv.Set("TOP", os.Getenv("TOP"))
+ ninjaEnv.Set("SOONG_OUTDIR", config.SoongOutDir())
+
+ // For debugging
+ if os.Getenv("SOONG_DELVE") != "" {
+ ninjaEnv.Set("SOONG_DELVE", os.Getenv("SOONG_DELVE"))
+ ninjaEnv.Set("SOONG_DELVE_PATH", shared.ResolveDelveBinary())
+ }
+
+ cmd.Environment = &ninjaEnv
cmd.Sandbox = soongSandbox
cmd.RunAndStreamOrFatal()
}
diff --git a/vnames.go.json b/vnames.go.json
deleted file mode 100644
index f8c6b7f..0000000
--- a/vnames.go.json
+++ /dev/null
@@ -1,8 +0,0 @@
-[
- {
- "pattern": "(.*)",
- "vname": {
- "path": "@1@"
- }
- }
-]