diff options
55 files changed, 1482 insertions, 826 deletions
diff --git a/android/config.go b/android/config.go index c10ad09ae..bc1aa3a4d 100644 --- a/android/config.go +++ b/android/config.go @@ -287,24 +287,21 @@ func TestArchConfigNativeBridge(buildDir string, env map[string]string, bp strin 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 @@ func (c *config) HostJavaToolPath(ctx PathContext, path string) Path { 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/fixture.go b/android/fixture.go index 2085e43ed..25dee2762 100644 --- a/android/fixture.go +++ b/android/fixture.go @@ -15,6 +15,7 @@ package android import ( + "fmt" "reflect" "strings" "testing" @@ -182,12 +183,12 @@ type FixtureFactory interface { // 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 +199,24 @@ type FixtureFactory interface { // // 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. @@ -286,6 +305,45 @@ 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. // @@ -484,6 +542,18 @@ func (h *TestHelper) AssertStringEquals(message string, expected string, 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 (h *TestHelper) AssertErrorMessageEquals(message string, expected string, actual error) { + h.Helper() + if actual == nil { + h.Errorf("Expected error but was nil") + } else if actual.Error() != expected { + h.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. @@ -511,6 +581,16 @@ func (h *TestHelper) AssertStringDoesNotContain(message string, s string, unexpe } } +// 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 (h *TestHelper) AssertStringListContains(message string, list []string, expected string) { + h.Helper() + if !InList(expected, list) { + h.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 (h *TestHelper) AssertArrayString(message string, expected, actual []string) { @@ -538,6 +618,23 @@ func (h *TestHelper) AssertDeepEquals(message string, expected interface{}, actu } } +// AssertPanic checks that the supplied function panics as expected. +func (h *TestHelper) AssertPanic(message string, funcThatShouldPanic func()) { + h.Helper() + panicked := false + func() { + defer func() { + if x := recover(); x != nil { + panicked = true + } + }() + funcThatShouldPanic() + }() + if !panicked { + h.Error(message) + } +} + // Struct to allow TestResult to embed a *TestContext and allow call forwarding to its methods. type testContext struct { *TestContext @@ -600,7 +697,7 @@ func (f *fixtureFactory) Fixture(t *testing.T, preparers ...FixturePreparer) Fix return fixture } -func (f *fixtureFactory) SetErrorHandler(errorHandler FixtureErrorHandler) FixtureFactory { +func (f *fixtureFactory) ExtendWithErrorHandler(errorHandler FixtureErrorHandler) FixtureFactory { newFactory := &fixtureFactory{} *newFactory = *f newFactory.errorHandler = errorHandler @@ -618,6 +715,28 @@ func (f *fixtureFactory) RunTestWithBp(t *testing.T, bp string) *TestResult { 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 @@ -643,17 +762,22 @@ func (f *fixture) RunTest() *TestResult { 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() diff --git a/android/license_kind_test.go b/android/license_kind_test.go index 767b64e82..83e83cef8 100644 --- a/android/license_kind_test.go +++ b/android/license_kind_test.go @@ -8,7 +8,7 @@ import ( var licenseKindTests = []struct { name string - fs map[string][]byte + fs MockFS expectedErrors []string }{ { @@ -97,48 +97,18 @@ var licenseKindTests = []struct { 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 9f6871374..a564827e6 100644 --- a/android/license_test.go +++ b/android/license_test.go @@ -4,9 +4,24 @@ import ( "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 @@ var licenseTests = []struct { 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 c04379108..d0e35330a 100644 --- a/android/licenses_test.go +++ b/android/licenses_test.go @@ -6,9 +6,21 @@ import ( "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 @@ var licensesTests = []struct { 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(result, test.effectiveLicenses) } if test.effectivePackage != nil { - checkEffectivePackage(t, ctx, test.effectivePackage) + checkEffectivePackage(result, test.effectivePackage) } if test.effectiveNotices != nil { - checkEffectiveNotices(t, ctx, test.effectiveNotices) + checkEffectiveNotices(result, test.effectiveNotices) } if test.effectiveKinds != nil { - checkEffectiveKinds(t, ctx, test.effectiveKinds) + checkEffectiveKinds(result, test.effectiveKinds) } if test.effectiveConditions != nil { - checkEffectiveConditions(t, ctx, test.effectiveConditions) + checkEffectiveConditions(result, test.effectiveConditions) } if test.effectiveInheritedLicenses != nil { - checkEffectiveInheritedLicenses(t, ctx, test.effectiveInheritedLicenses) + checkEffectiveInheritedLicenses(result, test.effectiveInheritedLicenses) } }) } } -func checkEffectiveLicenses(t *testing.T, ctx *TestContext, effectiveLicenses map[string][]string) { +func checkEffectiveLicenses(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 } @@ -502,7 +522,7 @@ func checkEffectiveLicenses(t *testing.T, ctx *TestContext, effectiveLicenses ma } module, ok := m.(Module) if !ok { - t.Errorf("%q not a module", m.Name()) + result.Errorf("%q not a module", m.Name()) return } base := module.base() @@ -518,14 +538,14 @@ func checkEffectiveLicenses(t *testing.T, ctx *TestContext, effectiveLicenses ma licenses = []string{} } if !compareUnorderedStringArrays(expectedLicenses, licenses) { - t.Errorf("effective licenses mismatch for module %q: expected %q, found %q", moduleName, expectedLicenses, licenses) + result.Errorf("effective licenses mismatch for module %q: expected %q, found %q", moduleName, expectedLicenses, licenses) } } } -func checkEffectiveInheritedLicenses(t *testing.T, ctx *TestContext, effectiveInheritedLicenses map[string][]string) { +func checkEffectiveInheritedLicenses(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 } @@ -537,7 +557,7 @@ func checkEffectiveInheritedLicenses(t *testing.T, ctx *TestContext, effectiveIn } module, ok := m.(Module) if !ok { - t.Errorf("%q not a module", m.Name()) + result.Errorf("%q not a module", m.Name()) return } base := module.base() @@ -548,7 +568,7 @@ func checkEffectiveInheritedLicenses(t *testing.T, ctx *TestContext, effectiveIn 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 } @@ -560,7 +580,7 @@ func checkEffectiveInheritedLicenses(t *testing.T, ctx *TestContext, effectiveIn } cmodule, ok := c.(Module) if !ok { - t.Errorf("%q not a module", c.Name()) + result.Errorf("%q not a module", c.Name()) return } cbase := cmodule.base() @@ -583,14 +603,14 @@ func checkEffectiveInheritedLicenses(t *testing.T, ctx *TestContext, effectiveIn licenses = []string{} } if !compareUnorderedStringArrays(expectedInheritedLicenses, licenses) { - t.Errorf("effective inherited licenses mismatch for module %q: expected %q, found %q", moduleName, expectedInheritedLicenses, licenses) + result.Errorf("effective inherited licenses mismatch for module %q: expected %q, found %q", moduleName, expectedInheritedLicenses, licenses) } } } -func checkEffectivePackage(t *testing.T, ctx *TestContext, effectivePackage map[string]string) { +func checkEffectivePackage(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 } @@ -602,7 +622,7 @@ func checkEffectivePackage(t *testing.T, ctx *TestContext, effectivePackage map[ } module, ok := m.(Module) if !ok { - t.Errorf("%q not a module", m.Name()) + result.Errorf("%q not a module", m.Name()) return } base := module.base() @@ -623,14 +643,14 @@ func checkEffectivePackage(t *testing.T, ctx *TestContext, effectivePackage map[ packageName = "" } if expectedPackage != packageName { - t.Errorf("effective package mismatch for module %q: expected %q, found %q", moduleName, expectedPackage, packageName) + result.Errorf("effective package mismatch for module %q: expected %q, found %q", moduleName, expectedPackage, packageName) } } } -func checkEffectiveNotices(t *testing.T, ctx *TestContext, effectiveNotices map[string][]string) { +func checkEffectiveNotices(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 } @@ -642,7 +662,7 @@ func checkEffectiveNotices(t *testing.T, ctx *TestContext, effectiveNotices map[ } module, ok := m.(Module) if !ok { - t.Errorf("%q not a module", m.Name()) + result.Errorf("%q not a module", m.Name()) return } base := module.base() @@ -658,14 +678,14 @@ func checkEffectiveNotices(t *testing.T, ctx *TestContext, effectiveNotices map[ notices = []string{} } if !compareUnorderedStringArrays(expectedNotices, notices) { - t.Errorf("effective notice files mismatch for module %q: expected %q, found %q", moduleName, expectedNotices, notices) + result.Errorf("effective notice files mismatch for module %q: expected %q, found %q", moduleName, expectedNotices, notices) } } } -func checkEffectiveKinds(t *testing.T, ctx *TestContext, effectiveKinds map[string][]string) { +func checkEffectiveKinds(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 } @@ -677,7 +697,7 @@ func checkEffectiveKinds(t *testing.T, ctx *TestContext, effectiveKinds map[stri } module, ok := m.(Module) if !ok { - t.Errorf("%q not a module", m.Name()) + result.Errorf("%q not a module", m.Name()) return } base := module.base() @@ -693,14 +713,14 @@ func checkEffectiveKinds(t *testing.T, ctx *TestContext, effectiveKinds map[stri kinds = []string{} } if !compareUnorderedStringArrays(expectedKinds, kinds) { - t.Errorf("effective license kinds mismatch for module %q: expected %q, found %q", moduleName, expectedKinds, kinds) + result.Errorf("effective license kinds mismatch for module %q: expected %q, found %q", moduleName, expectedKinds, kinds) } } } -func checkEffectiveConditions(t *testing.T, ctx *TestContext, effectiveConditions map[string][]string) { +func checkEffectiveConditions(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 } @@ -712,7 +732,7 @@ func checkEffectiveConditions(t *testing.T, ctx *TestContext, effectiveCondition } module, ok := m.(Module) if !ok { - t.Errorf("%q not a module", m.Name()) + result.Errorf("%q not a module", m.Name()) return } base := module.base() @@ -728,7 +748,7 @@ func checkEffectiveConditions(t *testing.T, ctx *TestContext, effectiveCondition conditions = []string{} } if !compareUnorderedStringArrays(expectedConditions, conditions) { - t.Errorf("effective license conditions mismatch for module %q: expected %q, found %q", moduleName, expectedConditions, conditions) + result.Errorf("effective license conditions mismatch for module %q: expected %q, found %q", moduleName, expectedConditions, conditions) } } } @@ -754,41 +774,6 @@ func compareUnorderedStringArrays(expected, actual []string) bool { 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/override_module.go b/android/override_module.go index fa0856631..97acc5c36 100644 --- a/android/override_module.go +++ b/android/override_module.go @@ -215,7 +215,14 @@ func RegisterOverridePostDepsMutators(ctx RegisterMutatorsContext) { 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 853e5a9a7..2c8d27c56 100644 --- a/android/path_properties.go +++ b/android/path_properties.go @@ -118,6 +118,13 @@ func fieldsByIndex(v reflect.Value, index []int, values *[]reflect.Value) { *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 2aab74835..85c96eee3 100644 --- a/android/path_properties_test.go +++ b/android/path_properties_test.go @@ -26,6 +26,9 @@ type pathDepsMutatorTestModule struct { 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 @@ func TestPathDepsMutator(t *testing.T) { ], }, ], + 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 @@ func TestPathDepsMutator(t *testing.T) { } filegroup { + name: "w", + } + + filegroup { name: "x", } diff --git a/android/testing.go b/android/testing.go index 4eb616a04..03d7bd5a6 100644 --- a/android/testing.go +++ b/android/testing.go @@ -73,17 +73,36 @@ var PrepareForTestWithOverrides = FixtureRegisterWithContext(func(ctx Registrati 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, + PrepareForTestWithDefaults, + PrepareForTestWithFilegroup, PrepareForTestWithOverrides, + PrepareForTestWithPackageModule, + PrepareForTestWithPrebuilts, + PrepareForTestWithVisibility, +) - // Modules - PrepareForTestWithFilegroup, +// 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, ) func NewTestArchContext(config Config) *TestContext { diff --git a/android/variable.go b/android/variable.go index dd000ad22..be12a0ad9 100644 --- a/android/variable.go +++ b/android/variable.go @@ -24,11 +24,17 @@ import ( ) 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 631e88ff9..5d1be6b47 100644 --- a/android/visibility.go +++ b/android/visibility.go @@ -202,17 +202,14 @@ type ExcludeFromVisibilityEnforcementTag interface { ExcludeFromVisibilityEnforcement() } -var PrepareForTestWithVisibilityRuleChecker = FixtureRegisterWithContext(func(ctx RegistrationContext) { - ctx.PreArchMutators(RegisterVisibilityRuleChecker) -}) +// The visibility mutators. +var PrepareForTestWithVisibility = FixtureRegisterWithContext(registerVisibilityMutators) -var PrepareForTestWithVisibilityRuleGatherer = FixtureRegisterWithContext(func(ctx RegistrationContext) { +func registerVisibilityMutators(ctx RegistrationContext) { + ctx.PreArchMutators(RegisterVisibilityRuleChecker) 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 30cdcbf8f..eb4071eb7 100644 --- a/android/visibility_test.go +++ b/android/visibility_test.go @@ -1143,25 +1143,26 @@ func TestVisibility(t *testing.T) { 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 { diff --git a/android/writedocs.go b/android/writedocs.go index 6cb2f1024..67b9aa3ad 100644 --- a/android/writedocs.go +++ b/android/writedocs.go @@ -35,10 +35,11 @@ type docsSingleton struct{} 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) diff --git a/apex/allowed_deps.txt b/apex/allowed_deps.txt index faa6569d3..170302c36 100644 --- a/apex/allowed_deps.txt +++ b/apex/allowed_deps.txt @@ -168,7 +168,9 @@ 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) @@ -504,8 +506,10 @@ netd_aidl_interface-unstable-java(minSdkVersion:29) 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) diff --git a/apex/apex.go b/apex/apex.go index efd1736db..e5b5c9272 100644 --- a/apex/apex.go +++ b/apex/apex.go @@ -39,16 +39,20 @@ import ( ) 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) +} + +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) - android.PreDepsMutators(RegisterPreDepsMutators) - android.PostDepsMutators(RegisterPostDepsMutators) + ctx.PreDepsMutators(RegisterPreDepsMutators) + ctx.PostDepsMutators(RegisterPostDepsMutators) } func RegisterPreDepsMutators(ctx android.RegisterMutatorsContext) { @@ -970,6 +974,10 @@ func markPlatformAvailability(mctx android.BottomUpMutatorContext) { // 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 991f5c9e9..08f54f724 100644 --- a/apex/apex_test.go +++ b/apex/apex_test.go @@ -229,14 +229,8 @@ func testApexContext(_ *testing.T, bp string, handlers ...testCustomizer) (*andr 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 +257,8 @@ func testApexContext(_ *testing.T, bp string, handlers ...testCustomizer) (*andr 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 @@ -5207,8 +5197,7 @@ func TestApexWithAppImportsPrefer(t *testing.T) { })) 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", }) } diff --git a/apex/key.go b/apex/key.go index 752888da2..8b33b593f 100644 --- a/apex/key.go +++ b/apex/key.go @@ -27,8 +27,12 @@ import ( 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/bp2build/Android.bp b/bp2build/Android.bp index 8deb5a217..99d706cc5 100644 --- a/bp2build/Android.bp +++ b/bp2build/Android.bp @@ -19,6 +19,7 @@ bootstrap_go_package { "soong-bazel", "soong-cc", "soong-genrule", + "soong-python", "soong-sh", ], testSrcs: [ @@ -27,6 +28,7 @@ bootstrap_go_package { "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 000000000..7600e3651 --- /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 8142f10a5..fa1a84d04 100644 --- a/bpf/bpf.go +++ b/bpf/bpf.go @@ -26,7 +26,7 @@ import ( ) func init() { - android.RegisterModuleType("bpf", BpfFactory) + registerBpfBuildComponents(android.InitRegistrationContext) pctx.Import("android/soong/cc/config") } @@ -43,6 +43,12 @@ var ( "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 be9e36ea5..eb0d8c8f7 100644 --- a/bpf/bpf_test.go +++ b/bpf/bpf_test.go @@ -46,24 +46,20 @@ func TestMain(m *testing.M) { } 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 @@ func TestBpfDataDependency(t *testing.T) { } ` - 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/cc/cc_test.go b/cc/cc_test.go index e640f123e..cc1f7d082 100644 --- a/cc/cc_test.go +++ b/cc/cc_test.go @@ -52,29 +52,50 @@ func TestMain(m *testing.M) { 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 +104,11 @@ func testCcNoVndk(t *testing.T, bp string) *android.TestContext { 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 +118,24 @@ func testCcNoProductVndk(t *testing.T, bp string) *android.TestContext { 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 +145,11 @@ func testCcError(t *testing.T, pattern string, bp string) { 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 +181,12 @@ func TestFuchsiaDeps(t *testing.T) { }, }` - 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 +217,13 @@ func TestFuchsiaTargetDecl(t *testing.T) { }, }` - 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) - } + result.AssertArrayString("libTest inputs", []string{"foo.o", "bar.o"}, objs) } func TestVendorSrc(t *testing.T) { diff --git a/cc/cmakelists.go b/cc/cmakelists.go index d441c57fe..04536fc56 100644 --- a/cc/cmakelists.go +++ b/cc/cmakelists.go @@ -319,6 +319,9 @@ func categorizeParameter(parameter string) parameterType { 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 1035df35b..b0344af84 100644 --- a/cc/config/x86_darwin_host.go +++ b/cc/config/x86_darwin_host.go @@ -136,7 +136,7 @@ var macTools = &macPlatformTools{} 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/testing.go b/cc/testing.go index f62c5f114..6840ef4c5 100644 --- a/cc/testing.go +++ b/cc/testing.go @@ -37,7 +37,31 @@ func RegisterRequiredBuildComponentsForTest(ctx android.RegistrationContext) { } 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 @@ func GatherRequiredDepsForTest(oses ...android.OsType) string { 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 @@ func GatherRequiredDepsForTest(oses ...android.OsType) string { 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,112 @@ func GatherRequiredDepsForTest(oses ...android.OsType) string { }, } ` - } - } +} - 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. + android.FixtureAddTextFile(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 +693,7 @@ func TestConfig(buildDir string, os android.OsType, env map[string]string, 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 +701,11 @@ func TestConfig(buildDir string, os android.OsType, env map[string]string, 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 +716,15 @@ func CreateTestContext(config android.Config) *android.TestContext { 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/dexpreopt/testing.go b/dexpreopt/testing.go index bccbfc1e5..8e90295b1 100644 --- a/dexpreopt/testing.go +++ b/dexpreopt/testing.go @@ -45,3 +45,36 @@ func BpToolModulesForTest() string { } ` } + +// 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 b07ad9115..6291325f4 100644 --- a/etc/prebuilt_etc.go +++ b/etc/prebuilt_etc.go @@ -54,6 +54,8 @@ func RegisterPrebuiltEtcBuildComponents(ctx android.RegistrationContext) { 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 585760d47..6727e59e4 100644 --- a/etc/prebuilt_etc_test.go +++ b/etc/prebuilt_etc_test.go @@ -18,7 +18,6 @@ import ( "io/ioutil" "os" "path/filepath" - "reflect" "testing" "android/soong/android" @@ -49,60 +48,19 @@ func TestMain(m *testing.M) { 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 @@ func TestPrebuiltEtcVariants(t *testing.T) { } `) - 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 @@ func TestPrebuiltEtcOutputPath(t *testing.T) { } `) - 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) + result.AssertStringEquals("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 @@ func TestPrebuiltEtcGlob(t *testing.T) { } `) - 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) + result.AssertStringEquals("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) + result.AssertStringEquals("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 @@ func TestPrebuiltEtcAndroidMk(t *testing.T) { "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) - } + result.AssertDeepEquals(k, expectedValue, value) } else { t.Errorf("No %s defined, saw %q", k, entries.EntryMap) } @@ -211,7 +161,7 @@ func TestPrebuiltEtcAndroidMk(t *testing.T) { } func TestPrebuiltEtcRelativeInstallPathInstallDirPath(t *testing.T) { - ctx, _ := testPrebuiltEtc(t, ` + result := prebuiltEtcFixtureFactory.RunTestWithBp(t, ` prebuilt_etc { name: "foo.conf", src: "foo.conf", @@ -219,26 +169,26 @@ func TestPrebuiltEtcRelativeInstallPathInstallDirPath(t *testing.T) { } `) - 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()) - } + result.AssertStringEquals("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 @@ func TestPrebuiltEtcHost(t *testing.T) { `) 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 @@ func TestPrebuiltUserShareInstallDirPath(t *testing.T) { } `) - 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()) - } + result.AssertStringEquals("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 @@ func TestPrebuiltUserShareHostInstallDirPath(t *testing.T) { `) 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") + result.AssertStringEquals("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()) - } + result.AssertStringEquals("install dir", expected, p.installDirPath.String()) } func TestPrebuiltFirmwareDirPath(t *testing.T) { @@ -327,11 +271,9 @@ func TestPrebuiltFirmwareDirPath(t *testing.T) { }} 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) + result.AssertStringEquals("install dir", tt.expectedPath, p.installDirPath.String()) }) } } @@ -363,11 +305,9 @@ func TestPrebuiltDSPDirPath(t *testing.T) { }} 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) + result.AssertStringEquals("install dir", tt.expectedPath, p.installDirPath.String()) }) } } diff --git a/genrule/genrule.go b/genrule/genrule.go index 50c77cf9a..53499068c 100644 --- a/genrule/genrule.go +++ b/genrule/genrule.go @@ -37,6 +37,27 @@ func init() { 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 2f5605e94..0873704ba 100644 --- a/genrule/genrule_test.go +++ b/genrule/genrule_test.go @@ -17,8 +17,7 @@ package genrule import ( "io/ioutil" "os" - "reflect" - "strings" + "regexp" "testing" "android/soong/android" @@ -51,22 +50,30 @@ func TestMain(m *testing.M) { os.Exit(run()) } -func testContext(config android.Config) *android.TestContext { - - ctx := android.NewTestArchContext(config) - ctx.RegisterModuleType("filegroup", android.FileGroupFactory) - ctx.RegisterModuleType("tool", toolFactory) - - RegisterGenruleBuildComponents(ctx) - - ctx.PreArchMutators(android.RegisterDefaultsPreArchMutators) - ctx.Register() - - return ctx -} +var genruleFixtureFactory = android.NewFixtureFactory( + &buildDir, + android.PrepareForTestWithArchMutator, + android.PrepareForTestWithDefaults, + + 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, + }), +) -func testConfig(bp string, fs map[string][]byte) android.Config { - bp += ` +func testGenruleBp() string { + return ` tool { name: "tool", } @@ -105,23 +112,6 @@ func testConfig(bp string, fs map[string][]byte) android.Config { 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 @@ func TestGenruleCmd(t *testing.T) { 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) + result.AssertStringEquals("raw commands", test.expect, gen.rawCommands[0]) }) } } @@ -557,25 +537,16 @@ func TestGenruleHashInputs(t *testing.T) { }, } - 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, "") + subResult := result.ResultForSubTest(t) + gen := subResult.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) - } + subResult.AssertStringEquals("hash", test.expectedHash, hash) }) } } @@ -630,46 +601,27 @@ func TestGenSrcs(t *testing.T) { 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) + result.AssertDeepEquals("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) - } + result.AssertDeepEquals("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) - } + result.AssertDeepEquals("files", test.files, gen.outputFiles.Strings()) }) } - } func TestGenruleDefaults(t *testing.T) { @@ -690,26 +642,16 @@ func TestGenruleDefaults(t *testing.T) { 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]) - } + result.AssertStringEquals("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) - } + result.AssertDeepEquals("srcs", expectedSrcs, gen.properties.Srcs) } func TestGenruleWithBazel(t *testing.T) { @@ -721,29 +663,18 @@ func TestGenruleWithBazel(t *testing.T) { } ` - 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) - } + result.AssertDeepEquals("output files", expectedOutputFiles, gen.outputFiles.Strings()) + result.AssertDeepEquals("output deps", expectedOutputFiles, gen.outputDeps.Strings()) } type testTool struct { diff --git a/java/app.go b/java/app.go index 0660aa62e..e98fe3114 100755 --- a/java/app.go +++ b/java/app.go @@ -122,8 +122,8 @@ type overridableAppProperties struct { // 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 diff --git a/java/app_import.go b/java/app_import.go index d38f63e06..d4da64da5 100644 --- a/java/app_import.go +++ b/java/app_import.go @@ -74,8 +74,8 @@ type AndroidAppImportProperties struct { // 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. diff --git a/java/app_import_test.go b/java/app_import_test.go index 00406aa2e..cae41d0e7 100644 --- a/java/app_import_test.go +++ b/java/app_import_test.go @@ -138,6 +138,32 @@ func TestAndroidAppImport_SigningLineage(t *testing.T) { } } +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 { + t.Errorf("Incorrect signing flags, expected: %q, got: %q", expected, signingFlag) + } +} + func TestAndroidAppImport_DefaultDevCert(t *testing.T) { ctx, _ := testJava(t, ` android_app_import { diff --git a/java/app_test.go b/java/app_test.go index f41047aa6..78e1a57a9 100644 --- a/java/app_test.go +++ b/java/app_test.go @@ -1576,6 +1576,31 @@ func TestCertificates(t *testing.T) { 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/droiddoc.go b/java/droiddoc.go index 8f1644c7f..f0decec74 100644 --- a/java/droiddoc.go +++ b/java/droiddoc.go @@ -1203,8 +1203,14 @@ func (d *Droidstubs) apiLevelsAnnotationsFlags(ctx android.ModuleContext, cmd *a } 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 @@ func metalavaCmd(ctx android.ModuleContext, rule *android.RuleBuilder, javaVersi 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 @@ func (d *Droidstubs) GenerateAndroidBuildActions(ctx android.ModuleContext) { 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_test.go b/java/java_test.go index 911265532..e8c4a0f50 100644 --- a/java/java_test.go +++ b/java/java_test.go @@ -48,6 +48,26 @@ func tearDown() { 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 @@ func TestMain(m *testing.M) { 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 @@ func testContext(config android.Config) *android.TestContext { 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 @@ func run(t *testing.T, ctx *android.TestContext, config android.Config) { 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 @@ func runWithErrors(t *testing.T, ctx *android.TestContext, config android.Config 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 @@ func moduleToPath(name string) string { } } +// 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,7 +2429,7 @@ func TestPatchModule(t *testing.T) { 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) }) } diff --git a/java/legacy_core_platform_api_usage.go b/java/legacy_core_platform_api_usage.go index 021920af6..874338d10 100644 --- a/java/legacy_core_platform_api_usage.go +++ b/java/legacy_core_platform_api_usage.go @@ -19,10 +19,6 @@ import ( "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 @@ var legacyCorePlatformApiModules = []string{ "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 @@ var legacyCorePlatformApiModules = []string{ "FrameworksServicesRoboTests", "FrameworksServicesTests", "FrameworksUtilTests", + "FrameworksWifiTests", "hid", "hidl_test_java_java", "hwbinder", @@ -95,6 +107,9 @@ var legacyCorePlatformApiModules = []string{ "platform_library-docs", "PrintSpooler", "RollbackTest", + "service-blobstore", + "service-connectivity", + "service-jobscheduler", "services", "services.accessibility", "services.backup", @@ -136,10 +151,6 @@ var legacyCorePlatformApiModules = []string{ "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,8 @@ func init() { } 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 + _, found := legacyCorePlatformApiLookup[ctx.ModuleName()] + return found } func corePlatformSystemModules(ctx android.EarlyModuleContext) string { diff --git a/java/lint.go b/java/lint.go index 50b84dc71..5940eac61 100644 --- a/java/lint.go +++ b/java/lint.go @@ -22,6 +22,8 @@ import ( "github.com/google/blueprint/proptools" "android/soong/android" + "android/soong/java/config" + "android/soong/remoteexec" ) type LintProperties struct { @@ -172,8 +174,40 @@ func (l *linter) deps(ctx android.BottomUpMutatorContext) { 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 (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 +218,27 @@ func (l *linter) writeLintProjectXML(ctx android.ModuleContext, 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 +253,39 @@ func (l *linter) writeLintProjectXML(ctx android.ModuleContext, 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") { + // 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 +299,18 @@ func (l *linter) writeLintProjectXML(ctx android.ModuleContext, 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 +353,7 @@ func (l *linter) lint(ctx android.ModuleContext) { 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 +367,8 @@ func (l *linter) lint(ctx android.ModuleContext) { } }) - 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 +380,52 @@ func (l *linter) lint(ctx android.ModuleContext) { 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 := ctx.Config().GetenvWithDefault("RBE_LINT_EXEC_STRATEGY", remoteexec.RemoteExecStrategy) + 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", + }, + 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 +435,9 @@ func (l *linter) lint(ctx android.ModuleContext) { 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 +456,9 @@ func (l *linter) lint(ctx android.ModuleContext) { } } - 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/testing.go b/java/testing.go index bfa1e6b2a..4e1997e45 100644 --- a/java/testing.go +++ b/java/testing.go @@ -29,10 +29,40 @@ import ( "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" + +// 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()), +) - mockFS := map[string][]byte{ +// 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 @@ func TestConfig(buildDir string, env map[string]string, bp string, fs map[string 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 416a7eec0..372b8a8c1 100644 --- a/python/binary.go +++ b/python/binary.go @@ -20,10 +20,92 @@ import ( "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 NewBinary(hod android.HostOrDeviceSupported) (*Module, *binaryDecorator) { 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 b3e3d13b2..a078c0b58 100644 --- a/python/python.go +++ b/python/python.go @@ -125,6 +125,7 @@ type pathMapping struct { 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 d6e2c0a75..5f0426a7f 100644 --- a/remoteexec/remoteexec.go +++ b/remoteexec/remoteexec.go @@ -81,6 +81,9 @@ type REParams struct { // 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 @@ func (r *REParams) wrapperArgs() string { 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/config/allowed_list.go b/rust/config/allowed_list.go index fc11d2901..408d433c9 100644 --- a/rust/config/allowed_list.go +++ b/rust/config/allowed_list.go @@ -14,6 +14,7 @@ var ( "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/scripts/build-mainline-modules.sh b/scripts/build-mainline-modules.sh index 0813f1a10..18174a452 100755 --- a/scripts/build-mainline-modules.sh +++ b/scripts/build-mainline-modules.sh @@ -36,8 +36,9 @@ MODULES_SDK_AND_EXPORTS=( # 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/bp_test.go b/sdk/bp_test.go index e1edc5131..a7164a5e9 100644 --- a/sdk/bp_test.go +++ b/sdk/bp_test.go @@ -54,7 +54,7 @@ func propertyStructFixture() interface{} { return str } -func checkPropertySetFixture(h *TestHelper, val interface{}, hasTags bool) { +func checkPropertySetFixture(h android.TestHelper, 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")) @@ -73,7 +73,7 @@ func checkPropertySetFixture(h *TestHelper, val interface{}, hasTags bool) { } func TestAddPropertySimple(t *testing.T) { - h := &TestHelper{t} + h := android.TestHelper{t} set := newPropertySet() for name, val := range map[string]interface{}{ "x": "taxi", @@ -92,7 +92,7 @@ func TestAddPropertySimple(t *testing.T) { } func TestAddPropertySubset(t *testing.T) { - h := &TestHelper{t} + h := android.TestHelper{t} getFixtureMap := map[string]func() interface{}{ "property set": propertySetFixture, "property struct": propertyStructFixture, @@ -139,7 +139,7 @@ func TestAddPropertySubset(t *testing.T) { } func TestAddPropertySetNew(t *testing.T) { - h := &TestHelper{t} + h := android.TestHelper{t} set := newPropertySet() subset := set.AddPropertySet("sub") subset.AddProperty("new", "d^^b") @@ -147,7 +147,7 @@ func TestAddPropertySetNew(t *testing.T) { } func TestAddPropertySetExisting(t *testing.T) { - h := &TestHelper{t} + h := android.TestHelper{t} set := propertySetFixture().(*bpPropertySet) subset := set.AddPropertySet("sub") subset.AddProperty("new", "d^^b") @@ -181,7 +181,7 @@ func (t removeFredTransformation) transformPropertySetAfterContents(name string, func TestTransformRemoveProperty(t *testing.T) { - helper := &TestHelper{t} + helper := android.TestHelper{t} set := newPropertySet() set.AddProperty("name", "name") @@ -196,7 +196,7 @@ func TestTransformRemoveProperty(t *testing.T) { func TestTransformRemovePropertySet(t *testing.T) { - helper := &TestHelper{t} + helper := android.TestHelper{t} set := newPropertySet() set.AddProperty("name", "name") diff --git a/sdk/exports.go b/sdk/exports.go index d3130574e..9a0ba4e32 100644 --- a/sdk/exports.go +++ b/sdk/exports.go @@ -17,8 +17,12 @@ package sdk 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/sdk.go b/sdk/sdk.go index f3d075022..2c84a2e88 100644 --- a/sdk/sdk.go +++ b/sdk/sdk.go @@ -33,10 +33,14 @@ func init() { 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 c4dc41beb..a7acd0c5f 100644 --- a/sdk/sdk_test.go +++ b/sdk/sdk_test.go @@ -309,16 +309,13 @@ func TestPrebuiltVisibilityProperty_AddPrivate(t *testing.T) { `) } -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`), @@ -390,7 +387,7 @@ func TestCommonValueOptimization(t *testing.T) { extractor := newCommonValueExtractor(common) - h := TestHelper{t} + h := android.TestHelper{t} err := extractor.extractCommonProperties(common, structs) h.AssertDeepEquals("unexpected error", nil, err) @@ -465,7 +462,7 @@ func TestCommonValueOptimization_InvalidArchSpecificVariants(t *testing.T) { extractor := newCommonValueExtractor(common) - h := TestHelper{t} + h := android.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: diff --git a/sdk/testing.go b/sdk/testing.go index 7a2540a27..e291bdbdf 100644 --- a/sdk/testing.go +++ b/sdk/testing.go @@ -19,7 +19,6 @@ import ( "io/ioutil" "os" "path/filepath" - "reflect" "strings" "testing" @@ -122,12 +121,8 @@ func testSdkContext(bp string, fs map[string][]byte, extraOsTypes []android.OsTy 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) + registerModuleExportsBuildComponents(ctx) + registerSdkBuildComponents(ctx) ctx.Register() @@ -141,7 +136,7 @@ func runTests(t *testing.T, ctx *android.TestContext, config android.Config) *te _, errs = ctx.PrepareBuildActions(config) android.FailIfErrored(t, errs) return &testSdkResult{ - TestHelper: TestHelper{t: t}, + TestHelper: android.TestHelper{T: t}, ctx: ctx, config: config, } @@ -185,63 +180,10 @@ func pathsToStrings(paths android.Paths) []string { 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 + android.TestHelper ctx *android.TestContext config android.Config } @@ -295,7 +237,7 @@ func (r *testSdkResult) getSdkSnapshotBuildInfo(sdk *sdk) *snapshotBuildInfo { 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", + r.Errorf("Expected intermediate zip %s to be an input to merge zips but found %s instead", info.intermediateZip, mergeInput) } @@ -328,7 +270,7 @@ func (r *testSdkResult) ModuleForTests(name string, variant string) android.Test // 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() + r.Helper() // The sdk CommonOS variant is always responsible for generating the snapshot. variant := android.CommonOS.Name @@ -358,7 +300,7 @@ func (r *testSdkResult) CheckSnapshot(name string, dir string, checkers ...snaps } // Process the generated bp file to make sure it is valid. - testSdkWithFs(r.t, snapshotBuildInfo.androidBpContents, fs) + testSdkWithFs(r.T, snapshotBuildInfo.androidBpContents, fs) } type snapshotBuildInfoChecker func(info *snapshotBuildInfo) @@ -368,7 +310,7 @@ type snapshotBuildInfoChecker func(info *snapshotBuildInfo) // 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.Helper() info.r.AssertTrimmedStringEquals("Android.bp contents do not match", expected, info.androidBpContents) } } @@ -380,7 +322,7 @@ func checkAndroidBpContents(expected string) snapshotBuildInfoChecker { // 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.Helper() info.r.AssertTrimmedStringEquals("unversioned Android.bp contents do not match", expected, info.androidUnversionedBpContents) } } @@ -395,7 +337,7 @@ func checkUnversionedAndroidBpContents(expected string) snapshotBuildInfoChecker // 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.Helper() info.r.AssertTrimmedStringEquals("versioned Android.bp contents do not match", expected, info.androidVersionedBpContents) } } @@ -407,14 +349,14 @@ func checkVersionedAndroidBpContents(expected string) snapshotBuildInfoChecker { // before comparing. func checkAllCopyRules(expected string) snapshotBuildInfoChecker { return func(info *snapshotBuildInfo) { - info.r.t.Helper() + info.r.Helper() info.r.AssertTrimmedStringEquals("Incorrect copy rules", expected, info.copyRules) } } func checkAllOtherCopyRules(expected string) snapshotBuildInfoChecker { return func(info *snapshotBuildInfo) { - info.r.t.Helper() + info.r.Helper() info.r.AssertTrimmedStringEquals("Incorrect copy rules", expected, info.otherCopyRules) } } @@ -422,9 +364,9 @@ func checkAllOtherCopyRules(expected string) snapshotBuildInfoChecker { // 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.r.Helper() if info.intermediateZip == "" { - info.r.t.Errorf("No intermediate zip file was created") + info.r.Errorf("No intermediate zip file was created") } info.r.AssertDeepEquals("mismatching merge zip files", expected, info.mergeZips) diff --git a/sh/sh_binary.go b/sh/sh_binary.go index 031cd4717..49f4961f2 100644 --- a/sh/sh_binary.go +++ b/sh/sh_binary.go @@ -40,14 +40,32 @@ var pctx = android.NewPackageContext("android/soong/sh") 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 f48f7fb29..7a24168e5 100644 --- a/sh/sh_binary_test.go +++ b/sh/sh_binary_test.go @@ -37,28 +37,32 @@ func TestMain(m *testing.M) { 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) - - 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) +// 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) - return ctx, config + return result.TestContext, result.Config } func TestShTestSubDir(t *testing.T) { diff --git a/ui/build/config.go b/ui/build/config.go index 15da1bc8c..1152cd790 100644 --- a/ui/build/config.go +++ b/ui/build/config.go @@ -56,7 +56,6 @@ type configImpl struct { katiSuffix string targetDevice string targetDeviceDir string - fullBuild bool // Autodetected totalRAM uint64 @@ -792,14 +791,6 @@ func (c *configImpl) SetTargetDevice(device string) { 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 be6f00a18..fe0aca983 100644 --- a/ui/build/dumpvars.go +++ b/ui/build/dumpvars.go @@ -214,9 +214,6 @@ func runMakeProductConfig(ctx Context, config Config) { // 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 @@ func runMakeProductConfig(ctx Context, config Config) { 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 668b20eed..06ec64607 100644 --- a/ui/build/kati.go +++ b/ui/build/kati.go @@ -229,11 +229,7 @@ func runKatiBuild(ctx Context, config Config) { // 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 c2fa427bf..884e95741 100644 --- a/ui/build/soong.go +++ b/ui/build/soong.go @@ -116,7 +116,7 @@ func runSoong(ctx Context, config Config) { 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 { @@ -170,12 +170,20 @@ func runSoong(ctx Context, config Config) { "--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") != "" { - // SOONG_DELVE is already in cmd.Environment - cmd.Environment.Set("SOONG_DELVE_PATH", shared.ResolveDelveBinary()) + ninjaEnv.Set("SOONG_DELVE", os.Getenv("SOONG_DELVE")) + ninjaEnv.Set("SOONG_DELVE_PATH", shared.ResolveDelveBinary()) } + cmd.Environment = &ninjaEnv cmd.Sandbox = soongSandbox cmd.RunAndStreamOrFatal() } |