diff options
author | Android Build Coastguard Worker <android-build-coastguard-worker@google.com> | 2022-11-30 09:33:59 +0000 |
---|---|---|
committer | Android Build Coastguard Worker <android-build-coastguard-worker@google.com> | 2022-11-30 09:33:59 +0000 |
commit | b97173ff0b8fc1c19229ded5fba9317329e51909 (patch) | |
tree | 7076364875be4ce36b86a2809f87291ee13bdeeb | |
parent | 501c89ff789fed9b9966a0b510e7d6274a80bd66 (diff) | |
parent | c21336e7cd011ccb3bbe0f855f4a4471ffcca5c2 (diff) | |
download | soong-b97173ff0b8fc1c19229ded5fba9317329e51909.tar.gz |
Snap for 9350704 from c21336e7cd011ccb3bbe0f855f4a4471ffcca5c2 to mainline-extservices-releaseaml_ext_331814220aml_ext_331412000
Change-Id: Ia24a843ee466d2a9292b63888957e6bb9a103b9d
-rw-r--r-- | android/fixture.go | 24 | ||||
-rw-r--r-- | android/namespace.go | 22 | ||||
-rw-r--r-- | android/namespace_test.go | 922 | ||||
-rw-r--r-- | android/neverallow.go | 1 | ||||
-rw-r--r-- | android/testing.go | 22 | ||||
-rw-r--r-- | cmd/soong_build/main.go | 14 | ||||
-rw-r--r-- | java/robolectric.go | 12 | ||||
-rw-r--r-- | sdk/sdk_test.go | 54 | ||||
-rw-r--r-- | sdk/update.go | 54 | ||||
-rw-r--r-- | ui/build/dumpvars.go | 3 |
10 files changed, 527 insertions, 601 deletions
diff --git a/android/fixture.go b/android/fixture.go index 3a15ad3a5..3f01f5a0d 100644 --- a/android/fixture.go +++ b/android/fixture.go @@ -588,6 +588,18 @@ func FixtureExpectsAllErrorsToMatchAPattern(patterns []string) FixtureErrorHandl }) } +// FixtureExpectsOneErrorPattern returns an error handler that will cause the test to fail +// if there is more than one error or the error does not match the pattern. +// +// If the test fails this handler will call `result.FailNow()` which will exit the goroutine within +// which the test is being run which means that the RunTest() method will not return. +func FixtureExpectsOneErrorPattern(pattern string) FixtureErrorHandler { + return FixtureCustomErrorHandler(func(t *testing.T, result *TestResult) { + t.Helper() + CheckErrorsAgainstExpectations(t, result.Errs, []string{pattern}) + }) +} + // FixtureCustomErrorHandler creates a custom error handler func FixtureCustomErrorHandler(function func(t *testing.T, result *TestResult)) FixtureErrorHandler { return simpleErrorHandler{ @@ -646,7 +658,7 @@ func (t *TestPathContext) AddNinjaFileDeps(deps ...string) { func createFixture(t *testing.T, buildDir string, preparers []*simpleFixturePreparer) Fixture { config := TestConfig(buildDir, nil, "", nil) - ctx := NewTestContext(config) + ctx := newTestContextForFixture(config) fixture := &fixture{ preparers: preparers, t: t, @@ -778,6 +790,16 @@ func (f *fixture) RunTest() *TestResult { } } + // Create and set the Context's NameInterface. It needs to be created here as it depends on the + // configuration that has been prepared for this fixture. + resolver := NewNameResolver(ctx.config) + + // Set the NameInterface in the main Context. + ctx.SetNameInterface(resolver) + + // Set the NameResolver in the TestContext. + ctx.NameResolver = resolver + ctx.Register() var ninjaDeps []string extraNinjaDeps, errs := ctx.ParseBlueprintsFiles("ignored") diff --git a/android/namespace.go b/android/namespace.go index fc7bc290f..1f821ff84 100644 --- a/android/namespace.go +++ b/android/namespace.go @@ -91,7 +91,27 @@ type NameResolver struct { namespaceExportFilter func(*Namespace) bool } -func NewNameResolver(namespaceExportFilter func(*Namespace) bool) *NameResolver { +// NameResolverConfig provides the subset of the Config interface needed by the +// NewNameResolver function. +type NameResolverConfig interface { + // ExportedNamespaces is the list of namespaces that Soong must export to + // make. + ExportedNamespaces() []string +} + +func NewNameResolver(config NameResolverConfig) *NameResolver { + namespacePathsToExport := make(map[string]bool) + + for _, namespaceName := range config.ExportedNamespaces() { + namespacePathsToExport[namespaceName] = true + } + + namespacePathsToExport["."] = true // always export the root namespace + + namespaceExportFilter := func(namespace *Namespace) bool { + return namespacePathsToExport[namespace.Path] + } + r := &NameResolver{ namespacesByDir: sync.Map{}, namespaceExportFilter: namespaceExportFilter, diff --git a/android/namespace_test.go b/android/namespace_test.go index ea399da06..7a387a0bd 100644 --- a/android/namespace_test.go +++ b/android/namespace_test.go @@ -15,7 +15,6 @@ package android import ( - "errors" "path/filepath" "reflect" "testing" @@ -24,577 +23,555 @@ import ( ) func TestDependingOnModuleInSameNamespace(t *testing.T) { - ctx := setupTest(t, - map[string]string{ + result := GroupFixturePreparers( + prepareForTestWithNamespace, + dirBpToPreparer(map[string]string{ "dir1": ` - soong_namespace { - } - test_module { - name: "a", - } - test_module { - name: "b", - deps: ["a"], - } + soong_namespace { + } + test_module { + name: "a", + } + test_module { + name: "b", + deps: ["a"], + } `, - }, - ) + }), + ).RunTest(t) - a := getModule(ctx, "a") - b := getModule(ctx, "b") - if !dependsOn(ctx, b, a) { + a := getModule(result, "a") + b := getModule(result, "b") + if !dependsOn(result, b, a) { t.Errorf("module b does not depend on module a in the same namespace") } } func TestDependingOnModuleInRootNamespace(t *testing.T) { - ctx := setupTest(t, - map[string]string{ + result := GroupFixturePreparers( + prepareForTestWithNamespace, + dirBpToPreparer(map[string]string{ ".": ` - test_module { - name: "b", - deps: ["a"], - } - test_module { - name: "a", - } + test_module { + name: "b", + deps: ["a"], + } + test_module { + name: "a", + } `, - }, - ) + }), + ).RunTest(t) - a := getModule(ctx, "a") - b := getModule(ctx, "b") - if !dependsOn(ctx, b, a) { + a := getModule(result, "a") + b := getModule(result, "b") + if !dependsOn(result, b, a) { t.Errorf("module b in root namespace does not depend on module a in the root namespace") } } func TestImplicitlyImportRootNamespace(t *testing.T) { - _ = setupTest(t, - map[string]string{ + GroupFixturePreparers( + prepareForTestWithNamespace, + dirBpToPreparer(map[string]string{ ".": ` - test_module { - name: "a", - } + test_module { + name: "a", + } `, "dir1": ` - soong_namespace { - } - test_module { - name: "b", - deps: ["a"], - } + soong_namespace { + } + test_module { + name: "b", + deps: ["a"], + } `, - }, - ) + }), + ).RunTest(t) - // setupTest will report any errors + // RunTest will report any errors } func TestDependingOnBlueprintModuleInRootNamespace(t *testing.T) { - _ = setupTest(t, - map[string]string{ + GroupFixturePreparers( + prepareForTestWithNamespace, + dirBpToPreparer(map[string]string{ ".": ` - blueprint_test_module { - name: "a", - } + blueprint_test_module { + name: "a", + } `, "dir1": ` - soong_namespace { - } - blueprint_test_module { - name: "b", - deps: ["a"], - } + soong_namespace { + } + blueprint_test_module { + name: "b", + deps: ["a"], + } `, - }, - ) + }), + ).RunTest(t) - // setupTest will report any errors + // RunTest will report any errors } func TestDependingOnModuleInImportedNamespace(t *testing.T) { - ctx := setupTest(t, - map[string]string{ + result := GroupFixturePreparers( + prepareForTestWithNamespace, + dirBpToPreparer(map[string]string{ "dir1": ` - soong_namespace { - } - test_module { - name: "a", - } + soong_namespace { + } + test_module { + name: "a", + } `, "dir2": ` - soong_namespace { - imports: ["dir1"], - } - test_module { - name: "b", - deps: ["a"], - } + soong_namespace { + imports: ["dir1"], + } + test_module { + name: "b", + deps: ["a"], + } `, - }, - ) + }), + ).RunTest(t) - a := getModule(ctx, "a") - b := getModule(ctx, "b") - if !dependsOn(ctx, b, a) { + a := getModule(result, "a") + b := getModule(result, "b") + if !dependsOn(result, b, a) { t.Errorf("module b does not depend on module a in the same namespace") } } func TestDependingOnModuleInNonImportedNamespace(t *testing.T) { - _, errs := setupTestExpectErrs(t, - map[string]string{ + GroupFixturePreparers( + prepareForTestWithNamespace, + dirBpToPreparer(map[string]string{ "dir1": ` - soong_namespace { - } - test_module { - name: "a", - } + soong_namespace { + } + test_module { + name: "a", + } `, "dir2": ` - soong_namespace { - } - test_module { - name: "a", - } + soong_namespace { + } + test_module { + name: "a", + } `, "dir3": ` - soong_namespace { - } - test_module { - name: "b", - deps: ["a"], - } + soong_namespace { + } + test_module { + name: "b", + deps: ["a"], + } `, - }, - ) - - expectedErrors := []error{ - errors.New( - `dir3/Android.bp:4:4: "b" depends on undefined module "a" + }), + ). + ExtendWithErrorHandler(FixtureExpectsOneErrorPattern(`\Qdir3/Android.bp:4:5: "b" depends on undefined module "a" Module "b" is defined in namespace "dir3" which can read these 2 namespaces: ["dir3" "."] -Module "a" can be found in these namespaces: ["dir1" "dir2"]`), - } - - if len(errs) != 1 || errs[0].Error() != expectedErrors[0].Error() { - t.Errorf("Incorrect errors. Expected:\n%v\n, got:\n%v\n", expectedErrors, errs) - } +Module "a" can be found in these namespaces: ["dir1" "dir2"]\E`)). + RunTest(t) } func TestDependingOnModuleByFullyQualifiedReference(t *testing.T) { - ctx := setupTest(t, - map[string]string{ + result := GroupFixturePreparers( + prepareForTestWithNamespace, + dirBpToPreparer(map[string]string{ "dir1": ` - soong_namespace { - } - test_module { - name: "a", - } + soong_namespace { + } + test_module { + name: "a", + } `, "dir2": ` - soong_namespace { - } - test_module { - name: "b", - deps: ["//dir1:a"], - } + soong_namespace { + } + test_module { + name: "b", + deps: ["//dir1:a"], + } `, - }, - ) - a := getModule(ctx, "a") - b := getModule(ctx, "b") - if !dependsOn(ctx, b, a) { + }), + ).RunTest(t) + + a := getModule(result, "a") + b := getModule(result, "b") + if !dependsOn(result, b, a) { t.Errorf("module b does not depend on module a") } } func TestSameNameInTwoNamespaces(t *testing.T) { - ctx := setupTest(t, - map[string]string{ + result := GroupFixturePreparers( + prepareForTestWithNamespace, + dirBpToPreparer(map[string]string{ "dir1": ` - soong_namespace { - } - test_module { - name: "a", - id: "1", - } - test_module { - name: "b", - deps: ["a"], - id: "2", - } + soong_namespace { + } + test_module { + name: "a", + id: "1", + } + test_module { + name: "b", + deps: ["a"], + id: "2", + } `, "dir2": ` - soong_namespace { - } - test_module { - name: "a", - id:"3", - } - test_module { - name: "b", - deps: ["a"], - id:"4", - } + soong_namespace { + } + test_module { + name: "a", + id:"3", + } + test_module { + name: "b", + deps: ["a"], + id:"4", + } `, - }, - ) + }), + ).RunTest(t) - one := findModuleById(ctx, "1") - two := findModuleById(ctx, "2") - three := findModuleById(ctx, "3") - four := findModuleById(ctx, "4") - if !dependsOn(ctx, two, one) { + one := findModuleById(result, "1") + two := findModuleById(result, "2") + three := findModuleById(result, "3") + four := findModuleById(result, "4") + if !dependsOn(result, two, one) { t.Fatalf("Module 2 does not depend on module 1 in its namespace") } - if dependsOn(ctx, two, three) { + if dependsOn(result, two, three) { t.Fatalf("Module 2 depends on module 3 in another namespace") } - if !dependsOn(ctx, four, three) { + if !dependsOn(result, four, three) { t.Fatalf("Module 4 does not depend on module 3 in its namespace") } - if dependsOn(ctx, four, one) { + if dependsOn(result, four, one) { t.Fatalf("Module 4 depends on module 1 in another namespace") } } func TestSearchOrder(t *testing.T) { - ctx := setupTest(t, - map[string]string{ + result := GroupFixturePreparers( + prepareForTestWithNamespace, + dirBpToPreparer(map[string]string{ "dir1": ` - soong_namespace { - } - test_module { - name: "a", - id: "1", - } + soong_namespace { + } + test_module { + name: "a", + id: "1", + } `, "dir2": ` - soong_namespace { - } - test_module { - name: "a", - id:"2", - } - test_module { - name: "b", - id:"3", - } + soong_namespace { + } + test_module { + name: "a", + id:"2", + } + test_module { + name: "b", + id:"3", + } `, "dir3": ` - soong_namespace { - } - test_module { - name: "a", - id:"4", - } - test_module { - name: "b", - id:"5", - } - test_module { - name: "c", - id:"6", - } + soong_namespace { + } + test_module { + name: "a", + id:"4", + } + test_module { + name: "b", + id:"5", + } + test_module { + name: "c", + id:"6", + } `, ".": ` - test_module { - name: "a", - id: "7", - } - test_module { - name: "b", - id: "8", - } - test_module { - name: "c", - id: "9", - } - test_module { - name: "d", - id: "10", - } + test_module { + name: "a", + id: "7", + } + test_module { + name: "b", + id: "8", + } + test_module { + name: "c", + id: "9", + } + test_module { + name: "d", + id: "10", + } `, "dir4": ` - soong_namespace { - imports: ["dir1", "dir2", "dir3"] - } - test_module { - name: "test_me", - id:"0", - deps: ["a", "b", "c", "d"], - } + soong_namespace { + imports: ["dir1", "dir2", "dir3"] + } + test_module { + name: "test_me", + id:"0", + deps: ["a", "b", "c", "d"], + } `, - }, - ) + }), + ).RunTest(t) - testMe := findModuleById(ctx, "0") - if !dependsOn(ctx, testMe, findModuleById(ctx, "1")) { + testMe := findModuleById(result, "0") + if !dependsOn(result, testMe, findModuleById(result, "1")) { t.Errorf("test_me doesn't depend on id 1") } - if !dependsOn(ctx, testMe, findModuleById(ctx, "3")) { + if !dependsOn(result, testMe, findModuleById(result, "3")) { t.Errorf("test_me doesn't depend on id 3") } - if !dependsOn(ctx, testMe, findModuleById(ctx, "6")) { + if !dependsOn(result, testMe, findModuleById(result, "6")) { t.Errorf("test_me doesn't depend on id 6") } - if !dependsOn(ctx, testMe, findModuleById(ctx, "10")) { + if !dependsOn(result, testMe, findModuleById(result, "10")) { t.Errorf("test_me doesn't depend on id 10") } - if numDeps(ctx, testMe) != 4 { - t.Errorf("num dependencies of test_me = %v, not 4\n", numDeps(ctx, testMe)) + if numDeps(result, testMe) != 4 { + t.Errorf("num dependencies of test_me = %v, not 4\n", numDeps(result, testMe)) } } func TestTwoNamespacesCanImportEachOther(t *testing.T) { - _ = setupTest(t, - map[string]string{ + GroupFixturePreparers( + prepareForTestWithNamespace, + dirBpToPreparer(map[string]string{ "dir1": ` - soong_namespace { - imports: ["dir2"] - } - test_module { - name: "a", - } - test_module { - name: "c", - deps: ["b"], - } + soong_namespace { + imports: ["dir2"] + } + test_module { + name: "a", + } + test_module { + name: "c", + deps: ["b"], + } `, "dir2": ` - soong_namespace { - imports: ["dir1"], - } - test_module { - name: "b", - deps: ["a"], - } + soong_namespace { + imports: ["dir1"], + } + test_module { + name: "b", + deps: ["a"], + } `, - }, - ) + }), + ).RunTest(t) - // setupTest will report any errors + // RunTest will report any errors } func TestImportingNonexistentNamespace(t *testing.T) { - _, errs := setupTestExpectErrs(t, - map[string]string{ + GroupFixturePreparers( + prepareForTestWithNamespace, + dirBpToPreparer(map[string]string{ "dir1": ` - soong_namespace { - imports: ["a_nonexistent_namespace"] - } - test_module { - name: "a", - deps: ["a_nonexistent_module"] - } + soong_namespace { + imports: ["a_nonexistent_namespace"] + } + test_module { + name: "a", + deps: ["a_nonexistent_module"] + } `, - }, - ) - - // should complain about the missing namespace and not complain about the unresolvable dependency - expectedErrors := []error{ - errors.New(`dir1/Android.bp:2:4: module "soong_namespace": namespace a_nonexistent_namespace does not exist`), - } - if len(errs) != 1 || errs[0].Error() != expectedErrors[0].Error() { - t.Errorf("Incorrect errors. Expected:\n%v\n, got:\n%v\n", expectedErrors, errs) - } + }), + ). + // should complain about the missing namespace and not complain about the unresolvable dependency + ExtendWithErrorHandler(FixtureExpectsOneErrorPattern(`\Qdir1/Android.bp:2:5: module "soong_namespace": namespace a_nonexistent_namespace does not exist\E`)). + RunTest(t) } func TestNamespacesDontInheritParentNamespaces(t *testing.T) { - _, errs := setupTestExpectErrs(t, - map[string]string{ + GroupFixturePreparers( + prepareForTestWithNamespace, + dirBpToPreparer(map[string]string{ "dir1": ` - soong_namespace { - } - test_module { - name: "a", - } + soong_namespace { + } + test_module { + name: "a", + } `, "dir1/subdir1": ` - soong_namespace { - } - test_module { - name: "b", - deps: ["a"], - } + soong_namespace { + } + test_module { + name: "b", + deps: ["a"], + } `, - }, - ) - - expectedErrors := []error{ - errors.New(`dir1/subdir1/Android.bp:4:4: "b" depends on undefined module "a" + }), + ). + ExtendWithErrorHandler(FixtureExpectsOneErrorPattern(`\Qdir1/subdir1/Android.bp:4:5: "b" depends on undefined module "a" Module "b" is defined in namespace "dir1/subdir1" which can read these 2 namespaces: ["dir1/subdir1" "."] -Module "a" can be found in these namespaces: ["dir1"]`), - } - if len(errs) != 1 || errs[0].Error() != expectedErrors[0].Error() { - t.Errorf("Incorrect errors. Expected:\n%v\n, got:\n%v\n", expectedErrors, errs) - } +Module "a" can be found in these namespaces: ["dir1"]\E`)). + RunTest(t) } func TestModulesDoReceiveParentNamespace(t *testing.T) { - _ = setupTest(t, - map[string]string{ + GroupFixturePreparers( + prepareForTestWithNamespace, + dirBpToPreparer(map[string]string{ "dir1": ` - soong_namespace { - } - test_module { - name: "a", - } + soong_namespace { + } + test_module { + name: "a", + } `, "dir1/subdir": ` - test_module { - name: "b", - deps: ["a"], - } + test_module { + name: "b", + deps: ["a"], + } `, - }, - ) + }), + ).RunTest(t) - // setupTest will report any errors + // RunTest will report any errors } func TestNamespaceImportsNotTransitive(t *testing.T) { - _, errs := setupTestExpectErrs(t, - map[string]string{ + GroupFixturePreparers( + prepareForTestWithNamespace, + dirBpToPreparer(map[string]string{ "dir1": ` - soong_namespace { - } - test_module { - name: "a", - } + soong_namespace { + } + test_module { + name: "a", + } `, "dir2": ` - soong_namespace { - imports: ["dir1"], - } - test_module { - name: "b", - deps: ["a"], - } + soong_namespace { + imports: ["dir1"], + } + test_module { + name: "b", + deps: ["a"], + } `, "dir3": ` - soong_namespace { - imports: ["dir2"], - } - test_module { - name: "c", - deps: ["a"], - } + soong_namespace { + imports: ["dir2"], + } + test_module { + name: "c", + deps: ["a"], + } `, - }, - ) - - expectedErrors := []error{ - errors.New(`dir3/Android.bp:5:4: "c" depends on undefined module "a" + }), + ). + ExtendWithErrorHandler(FixtureExpectsOneErrorPattern(`\Qdir3/Android.bp:5:5: "c" depends on undefined module "a" Module "c" is defined in namespace "dir3" which can read these 3 namespaces: ["dir3" "dir2" "."] -Module "a" can be found in these namespaces: ["dir1"]`), - } - if len(errs) != 1 || errs[0].Error() != expectedErrors[0].Error() { - t.Errorf("Incorrect errors. Expected:\n%v\n, got:\n%v\n", expectedErrors, errs) - } +Module "a" can be found in these namespaces: ["dir1"]\E`)). + RunTest(t) } func TestTwoNamepacesInSameDir(t *testing.T) { - _, errs := setupTestExpectErrs(t, - map[string]string{ + GroupFixturePreparers( + prepareForTestWithNamespace, + dirBpToPreparer(map[string]string{ "dir1": ` - soong_namespace { - } - soong_namespace { - } + soong_namespace { + } + soong_namespace { + } `, - }, - ) - - expectedErrors := []error{ - errors.New(`dir1/Android.bp:4:4: namespace dir1 already exists`), - } - if len(errs) != 1 || errs[0].Error() != expectedErrors[0].Error() { - t.Errorf("Incorrect errors. Expected:\n%v\n, got:\n%v\n", expectedErrors, errs) - } + }), + ). + ExtendWithErrorHandler(FixtureExpectsOneErrorPattern(`\Qdir1/Android.bp:4:5: namespace dir1 already exists\E`)). + RunTest(t) } func TestNamespaceNotAtTopOfFile(t *testing.T) { - _, errs := setupTestExpectErrs(t, - map[string]string{ + GroupFixturePreparers( + prepareForTestWithNamespace, + dirBpToPreparer(map[string]string{ "dir1": ` - test_module { - name: "a" - } - soong_namespace { - } + test_module { + name: "a" + } + soong_namespace { + } `, - }, - ) - - expectedErrors := []error{ - errors.New(`dir1/Android.bp:5:4: a namespace must be the first module in the file`), - } - if len(errs) != 1 || errs[0].Error() != expectedErrors[0].Error() { - t.Errorf("Incorrect errors. Expected:\n%v\n, got:\n%v\n", expectedErrors, errs) - } + }), + ). + ExtendWithErrorHandler(FixtureExpectsOneErrorPattern(`\Qdir1/Android.bp:5:5: a namespace must be the first module in the file\E`)). + RunTest(t) } func TestTwoModulesWithSameNameInSameNamespace(t *testing.T) { - _, errs := setupTestExpectErrs(t, - map[string]string{ + GroupFixturePreparers( + prepareForTestWithNamespace, + dirBpToPreparer(map[string]string{ "dir1": ` - soong_namespace { - } - test_module { - name: "a" - } - test_module { - name: "a" - } + soong_namespace { + } + test_module { + name: "a" + } + test_module { + name: "a" + } `, - }, - ) - - expectedErrors := []error{ - errors.New(`dir1/Android.bp:7:4: module "a" already defined - dir1/Android.bp:4:4 <-- previous definition here`), - } - if len(errs) != 1 || errs[0].Error() != expectedErrors[0].Error() { - t.Errorf("Incorrect errors. Expected:\n%v\n, got:\n%v\n", expectedErrors, errs) - } + }), + ). + ExtendWithErrorHandler(FixtureExpectsOneErrorPattern(`\Qdir1/Android.bp:7:5: module "a" already defined + dir1/Android.bp:4:5 <-- previous definition here\E`)). + RunTest(t) } func TestDeclaringNamespaceInNonAndroidBpFile(t *testing.T) { - _, errs := setupTestFromFiles(t, - map[string][]byte{ - "Android.bp": []byte(` + GroupFixturePreparers( + prepareForTestWithNamespace, + FixtureWithRootAndroidBp(` build = ["include.bp"] - `), - "include.bp": []byte(` + `), + FixtureAddTextFile("include.bp", ` soong_namespace { } - `), - }, - ) - - expectedErrors := []error{ - errors.New(`include.bp:2:5: A namespace may only be declared in a file named Android.bp`), - } - - if len(errs) != 1 || errs[0].Error() != expectedErrors[0].Error() { - t.Errorf("Incorrect errors. Expected:\n%v\n, got:\n%v\n", expectedErrors, errs) - } + `), + ). + ExtendWithErrorHandler(FixtureExpectsOneErrorPattern( + `\Qinclude.bp:2:5: A namespace may only be declared in a file named Android.bp\E`, + )). + RunTest(t) } // so that the generated .ninja file will have consistent names func TestConsistentNamespaceNames(t *testing.T) { - ctx := setupTest(t, - map[string]string{ + result := GroupFixturePreparers( + prepareForTestWithNamespace, + dirBpToPreparer(map[string]string{ "dir1": "soong_namespace{}", "dir2": "soong_namespace{}", "dir3": "soong_namespace{}", - }) + }), + ).RunTest(t) - ns1, _ := ctx.NameResolver.namespaceAt("dir1") - ns2, _ := ctx.NameResolver.namespaceAt("dir2") - ns3, _ := ctx.NameResolver.namespaceAt("dir3") + ns1, _ := result.NameResolver.namespaceAt("dir1") + ns2, _ := result.NameResolver.namespaceAt("dir2") + ns3, _ := result.NameResolver.namespaceAt("dir3") actualIds := []string{ns1.id, ns2.id, ns3.id} expectedIds := []string{"1", "2", "3"} if !reflect.DeepEqual(actualIds, expectedIds) { @@ -604,103 +581,118 @@ func TestConsistentNamespaceNames(t *testing.T) { // so that the generated .ninja file will have consistent names func TestRename(t *testing.T) { - _ = setupTest(t, - map[string]string{ + GroupFixturePreparers( + prepareForTestWithNamespace, + dirBpToPreparer(map[string]string{ "dir1": ` - soong_namespace { - } - test_module { - name: "a", - deps: ["c"], - } - test_module { - name: "b", - rename: "c", - } - `}) - // setupTest will report any errors -} - -// some utils to support the tests + soong_namespace { + } + test_module { + name: "a", + deps: ["c"], + } + test_module { + name: "b", + rename: "c", + } + `, + }), + ).RunTest(t) -func mockFiles(bps map[string]string) (files map[string][]byte) { - files = make(map[string][]byte, len(bps)) - files["Android.bp"] = []byte("") - for dir, text := range bps { - files[filepath.Join(dir, "Android.bp")] = []byte(text) - } - return files + // RunTest will report any errors } -func setupTestFromFiles(t *testing.T, bps MockFS) (ctx *TestContext, errs []error) { +func TestNamespace_Exports(t *testing.T) { result := GroupFixturePreparers( - FixtureModifyContext(func(ctx *TestContext) { - ctx.RegisterModuleType("test_module", newTestModule) - ctx.Context.RegisterModuleType("blueprint_test_module", newBlueprintTestModule) - ctx.PreDepsMutators(func(ctx RegisterMutatorsContext) { - ctx.BottomUp("rename", renameMutator) - }) + prepareForTestWithNamespace, + FixtureModifyProductVariables(func(variables FixtureProductVariables) { + variables.NamespacesToExport = []string{"dir1"} }), - PrepareForTestWithNamespace, - bps.AddToFixture(), - ). - // Ignore errors for now so tests can check them later. - ExtendWithErrorHandler(FixtureIgnoreErrors). - RunTest(t) + dirBpToPreparer(map[string]string{ + "dir1": ` + soong_namespace { + } + test_module { + name: "a", + } + `, + "dir2": ` + soong_namespace { + } + test_module { + name: "b", + } + `, + }), + ).RunTest(t) - return result.TestContext, result.Errs + aModule := result.Module("a", "") + AssertBoolEquals(t, "a exported", true, aModule.ExportedToMake()) + bModule := result.Module("b", "") + AssertBoolEquals(t, "b not exported", false, bModule.ExportedToMake()) } -func setupTestExpectErrs(t *testing.T, bps map[string]string) (ctx *TestContext, errs []error) { - files := make(map[string][]byte, len(bps)) +// some utils to support the tests + +var prepareForTestWithNamespace = GroupFixturePreparers( + FixtureRegisterWithContext(registerNamespaceBuildComponents), + FixtureRegisterWithContext(func(ctx RegistrationContext) { + ctx.PreArchMutators(RegisterNamespaceMutator) + }), + FixtureModifyContext(func(ctx *TestContext) { + ctx.RegisterModuleType("test_module", newTestModule) + ctx.Context.RegisterModuleType("blueprint_test_module", newBlueprintTestModule) + ctx.PreDepsMutators(func(ctx RegisterMutatorsContext) { + ctx.BottomUp("rename", renameMutator) + }) + }), +) + +// dirBpToPreparer takes a map from directory to the contents of the Android.bp file and produces a +// FixturePreparer. +func dirBpToPreparer(bps map[string]string) FixturePreparer { + files := make(MockFS, len(bps)) files["Android.bp"] = []byte("") for dir, text := range bps { files[filepath.Join(dir, "Android.bp")] = []byte(text) } - return setupTestFromFiles(t, files) -} - -func setupTest(t *testing.T, bps map[string]string) (ctx *TestContext) { - t.Helper() - ctx, errs := setupTestExpectErrs(t, bps) - FailIfErrored(t, errs) - return ctx + return files.AddToFixture() } -func dependsOn(ctx *TestContext, module TestingModule, possibleDependency TestingModule) bool { +func dependsOn(result *TestResult, module TestingModule, possibleDependency TestingModule) bool { depends := false visit := func(dependency blueprint.Module) { if dependency == possibleDependency.module { depends = true } } - ctx.VisitDirectDeps(module.module, visit) + result.VisitDirectDeps(module.module, visit) return depends } -func numDeps(ctx *TestContext, module TestingModule) int { +func numDeps(result *TestResult, module TestingModule) int { count := 0 visit := func(dependency blueprint.Module) { count++ } - ctx.VisitDirectDeps(module.module, visit) + result.VisitDirectDeps(module.module, visit) return count } -func getModule(ctx *TestContext, moduleName string) TestingModule { - return ctx.ModuleForTests(moduleName, "") +func getModule(result *TestResult, moduleName string) TestingModule { + return result.ModuleForTests(moduleName, "") } -func findModuleById(ctx *TestContext, id string) (module TestingModule) { +func findModuleById(result *TestResult, id string) (module TestingModule) { visit := func(candidate blueprint.Module) { testModule, ok := candidate.(*testModule) if ok { if testModule.properties.Id == id { - module = newTestingModule(ctx.config, testModule) + module = newTestingModule(result.config, testModule) } } } - ctx.VisitAllModules(visit) + result.VisitAllModules(visit) return module } @@ -747,7 +739,7 @@ type blueprintTestModule struct { } } -func (b *blueprintTestModule) DynamicDependencies(ctx blueprint.DynamicDependerModuleContext) []string { +func (b *blueprintTestModule) DynamicDependencies(_ blueprint.DynamicDependerModuleContext) []string { return b.properties.Deps } diff --git a/android/neverallow.go b/android/neverallow.go index aa47bcaeb..5f069b877 100644 --- a/android/neverallow.go +++ b/android/neverallow.go @@ -154,6 +154,7 @@ func createJavaDeviceForHostRules() []Rule { "development/build", "external/guava", "external/robolectric-shadows", + "external/robolectric", "frameworks/layoutlib", } diff --git a/android/testing.go b/android/testing.go index 1b36c903a..f5210d185 100644 --- a/android/testing.go +++ b/android/testing.go @@ -30,19 +30,11 @@ import ( "github.com/google/blueprint/proptools" ) -func NewTestContext(config Config) *TestContext { - namespaceExportFilter := func(namespace *Namespace) bool { - return true - } - - nameResolver := NewNameResolver(namespaceExportFilter) +func newTestContextForFixture(config Config) *TestContext { ctx := &TestContext{ - Context: &Context{blueprint.NewContext(), config}, - NameResolver: nameResolver, + Context: &Context{blueprint.NewContext(), config}, } - ctx.SetNameInterface(nameResolver) - ctx.postDeps = append(ctx.postDeps, registerPathDepsMutator) ctx.SetFs(ctx.config.fs) @@ -53,6 +45,16 @@ func NewTestContext(config Config) *TestContext { return ctx } +func NewTestContext(config Config) *TestContext { + ctx := newTestContextForFixture(config) + + nameResolver := NewNameResolver(config) + ctx.NameResolver = nameResolver + ctx.SetNameInterface(nameResolver) + + return ctx +} + var PrepareForTestWithArchMutator = GroupFixturePreparers( // Configure architecture targets in the fixture config. FixtureModifyConfig(modifyTestConfigToSupportArchMutator), diff --git a/cmd/soong_build/main.go b/cmd/soong_build/main.go index 3f8105c88..7c500b76c 100644 --- a/cmd/soong_build/main.go +++ b/cmd/soong_build/main.go @@ -97,19 +97,7 @@ func init() { } func newNameResolver(config android.Config) *android.NameResolver { - namespacePathsToExport := make(map[string]bool) - - for _, namespaceName := range config.ExportedNamespaces() { - namespacePathsToExport[namespaceName] = true - } - - namespacePathsToExport["."] = true // always export the root namespace - - exportFilter := func(namespace *android.Namespace) bool { - return namespacePathsToExport[namespace.Path] - } - - return android.NewNameResolver(exportFilter) + return android.NewNameResolver(config) } func newContext(configuration android.Config) *android.Context { diff --git a/java/robolectric.go b/java/robolectric.go index f71952172..80be04612 100644 --- a/java/robolectric.go +++ b/java/robolectric.go @@ -23,6 +23,8 @@ import ( "android/soong/android" "android/soong/java/config" "android/soong/tradefed" + + "github.com/google/blueprint/proptools" ) func init() { @@ -63,6 +65,10 @@ type robolectricProperties struct { // The version number of a robolectric prebuilt to use from prebuilts/misc/common/robolectric // instead of the one built from source in external/robolectric-shadows. Robolectric_prebuilt_version *string + + // Use /external/robolectric rather than /external/robolectric-shadows as the version of robolectri + // to use. /external/robolectric closely tracks github's master, and will fully replace /external/robolectric-shadows + Upstream *bool } type robolectricTest struct { @@ -106,7 +112,11 @@ func (r *robolectricTest) DepsMutator(ctx android.BottomUpMutatorContext) { if v := String(r.robolectricProperties.Robolectric_prebuilt_version); v != "" { ctx.AddVariationDependencies(nil, libTag, fmt.Sprintf(robolectricPrebuiltLibPattern, v)) } else { - ctx.AddVariationDependencies(nil, libTag, robolectricCurrentLib) + if proptools.Bool(r.robolectricProperties.Upstream) { + ctx.AddVariationDependencies(nil, libTag, robolectricCurrentLib+"_upstream") + } else { + ctx.AddVariationDependencies(nil, libTag, robolectricCurrentLib) + } } ctx.AddVariationDependencies(nil, libTag, robolectricDefaultLibs...) diff --git a/sdk/sdk_test.go b/sdk/sdk_test.go index 2f9aee9da..108a664ea 100644 --- a/sdk/sdk_test.go +++ b/sdk/sdk_test.go @@ -409,60 +409,6 @@ java_import { ) }) - t.Run("SOONG_SDK_SNAPSHOT_PREFER=true", func(t *testing.T) { - result := android.GroupFixturePreparers( - preparer, - android.FixtureMergeEnv(map[string]string{ - "SOONG_SDK_SNAPSHOT_PREFER": "true", - }), - ).RunTest(t) - - checkZipFile(t, result, "out/soong/.intermediates/mysdk/common_os/mysdk-current.zip") - - CheckSnapshot(t, result, "mysdk", "", - checkAndroidBpContents(` -// This is auto-generated. DO NOT EDIT. - -java_import { - name: "myjavalib", - prefer: true, - visibility: ["//visibility:public"], - apex_available: ["//apex_available:platform"], - jars: ["java/myjavalib.jar"], -} - `), - ) - }) - - t.Run("SOONG_SDK_SNAPSHOT_USE_SOURCE_CONFIG_VAR=module:build_from_source", func(t *testing.T) { - result := android.GroupFixturePreparers( - preparer, - android.FixtureMergeEnv(map[string]string{ - "SOONG_SDK_SNAPSHOT_USE_SOURCE_CONFIG_VAR": "module:build_from_source", - }), - ).RunTest(t) - - checkZipFile(t, result, "out/soong/.intermediates/mysdk/common_os/mysdk-current.zip") - - CheckSnapshot(t, result, "mysdk", "", - checkAndroidBpContents(` -// This is auto-generated. DO NOT EDIT. - -java_import { - name: "myjavalib", - prefer: false, - use_source_config_var: { - config_namespace: "module", - var_name: "build_from_source", - }, - visibility: ["//visibility:public"], - apex_available: ["//apex_available:platform"], - jars: ["java/myjavalib.jar"], -} - `), - ) - }) - t.Run("SOONG_SDK_SNAPSHOT_TARGET_BUILD_RELEASE=S", func(t *testing.T) { result := android.GroupFixturePreparers( prepareForSdkTestWithJava, diff --git a/sdk/update.go b/sdk/update.go index 92a13fa7f..baa203302 100644 --- a/sdk/update.go +++ b/sdk/update.go @@ -34,41 +34,6 @@ import ( // Environment variables that affect the generated snapshot // ======================================================== // -// SOONG_SDK_SNAPSHOT_PREFER -// By default every module in the generated snapshot has prefer: false. Building it -// with SOONG_SDK_SNAPSHOT_PREFER=true will force them to use prefer: true. -// -// SOONG_SDK_SNAPSHOT_USE_SOURCE_CONFIG_VAR -// If set this specifies the Soong config var that can be used to control whether the prebuilt -// modules from the generated snapshot or the original source modules. Values must be a colon -// separated pair of strings, the first of which is the Soong config namespace, and the second -// is the name of the variable within that namespace. -// -// The config namespace and var name are used to set the `use_source_config_var` property. That -// in turn will cause the generated prebuilts to use the soong config variable to select whether -// source or the prebuilt is used. -// e.g. If an sdk snapshot is built using: -// m SOONG_SDK_SNAPSHOT_USE_SOURCE_CONFIG_VAR=acme:build_from_source sdkextensions-sdk -// Then the resulting snapshot will include: -// use_source_config_var: { -// config_namespace: "acme", -// var_name: "build_from_source", -// } -// -// Assuming that the config variable is defined in .mk using something like: -// $(call add_soong_config_namespace,acme) -// $(call add_soong_config_var_value,acme,build_from_source,true) -// -// Then when the snapshot is unpacked in the repository it will have the following behavior: -// m droid - will use the sdkextensions-sdk prebuilts if present. Otherwise, it will use the -// sources. -// m SOONG_CONFIG_acme_build_from_source=true droid - will use the sdkextensions-sdk -// sources, if present. Otherwise, it will use the prebuilts. -// -// This is a temporary mechanism to control the prefer flags and will be removed once a more -// maintainable solution has been implemented. -// TODO(b/174997203): Remove when no longer necessary. -// // SOONG_SDK_SNAPSHOT_TARGET_BUILD_RELEASE // This allows the target build release (i.e. the release version of the build within which // the snapshot will be used) of the snapshot to be specified. If unspecified then it defaults @@ -2019,29 +1984,12 @@ func (s *sdk) createMemberSnapshot(ctx *memberContext, member *sdkMember, bpModu // Do not add the prefer property if the member snapshot module is a source module type. moduleCtx := ctx.sdkMemberContext - config := moduleCtx.Config() if !memberType.UsesSourceModuleTypeInSnapshot() { - // Set the prefer based on the environment variable. This is a temporary work around to allow a - // snapshot to be created that sets prefer: true. - // TODO(b/174997203): Remove once the ability to select the modules to prefer can be done - // dynamically at build time not at snapshot generation time. - prefer := config.IsEnvTrue("SOONG_SDK_SNAPSHOT_PREFER") - // Set prefer. Setting this to false is not strictly required as that is the default but it does // provide a convenient hook to post-process the generated Android.bp file, e.g. in tests to // check the behavior when a prebuilt is preferred. It also makes it explicit what the default // behavior is for the module. - bpModule.insertAfter("name", "prefer", prefer) - - configVar := config.Getenv("SOONG_SDK_SNAPSHOT_USE_SOURCE_CONFIG_VAR") - if configVar != "" { - parts := strings.Split(configVar, ":") - cfp := android.ConfigVarProperties{ - Config_namespace: proptools.StringPtr(parts[0]), - Var_name: proptools.StringPtr(parts[1]), - } - bpModule.insertAfter("prefer", "use_source_config_var", cfp) - } + bpModule.insertAfter("name", "prefer", false) } variants := selectApexVariantsWhereAvailable(ctx, member.variants) diff --git a/ui/build/dumpvars.go b/ui/build/dumpvars.go index 285f1569b..45bfe5dfa 100644 --- a/ui/build/dumpvars.go +++ b/ui/build/dumpvars.go @@ -162,10 +162,7 @@ var BannerVars = []string{ "OUT_DIR", "AUX_OS_VARIANT_LIST", "PRODUCT_SOONG_NAMESPACES", - "SOONG_SDK_SNAPSHOT_PREFER", "SOONG_SDK_SNAPSHOT_TARGET_BUILD_RELEASE", - "SOONG_SDK_SNAPSHOT_USE_SOURCE_CONFIG_VAR", - "SOONG_SDK_SNAPSHOT_VERSION", } func Banner(make_vars map[string]string) string { |