Files
build_soong/android/packaging_test.go
Cole Faust 502da3987a Export non-apex variants of modules to make
Currently, non-apex variants of modules that are in apexes are not
exported to make unless they're apex_available to the platform. This
means that you can't `m` those modules directly.

However, there is a workaround in the apex androidmk implementation that
emits make rules for the removed modules, but just redirects them to
build the apex itself. We want to remove that, but one of the problems
with doing so is that you can no longer `m` many modules afterwards.

To fix that, unhide the apex's dependencies from make. To ensure they're
not installed, call SkipInstall() on them, and update SkipInstall() to
be more strict by setting `LOCAL_UNINSTALLABLE_MODULE := true`.

Bug: 254205429
Test: Presubmits
Change-Id: Ib971981559f3b642ce6be8890679e994e1b44be0
2023-03-16 11:13:23 -07:00

441 lines
8.5 KiB
Go

// Copyright 2020 Google Inc. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package android
import (
"strings"
"testing"
"github.com/google/blueprint"
"github.com/google/blueprint/proptools"
)
// Module to be packaged
type componentTestModule struct {
ModuleBase
props struct {
Deps []string
Skip_install *bool
}
builtFile Path
}
// dep tag used in this test. All dependencies are considered as installable.
type installDepTag struct {
blueprint.BaseDependencyTag
InstallAlwaysNeededDependencyTag
}
func componentTestModuleFactory() Module {
m := &componentTestModule{}
m.AddProperties(&m.props)
InitAndroidArchModule(m, HostAndDeviceSupported, MultilibBoth)
return m
}
func (m *componentTestModule) DepsMutator(ctx BottomUpMutatorContext) {
ctx.AddDependency(ctx.Module(), installDepTag{}, m.props.Deps...)
}
func (m *componentTestModule) GenerateAndroidBuildActions(ctx ModuleContext) {
m.builtFile = PathForModuleOut(ctx, m.Name())
dir := ctx.Target().Arch.ArchType.Multilib
installDir := PathForModuleInstall(ctx, dir)
if proptools.Bool(m.props.Skip_install) {
m.SkipInstall()
}
ctx.InstallFile(installDir, m.Name(), m.builtFile)
}
func (m *componentTestModule) AndroidMkEntries() []AndroidMkEntries {
return []AndroidMkEntries{
{
OutputFile: OptionalPathForPath(m.builtFile),
},
}
}
// Module that itself is a package
type packageTestModule struct {
ModuleBase
PackagingBase
properties struct {
Install_deps []string `android:`
}
entries []string
}
func packageMultiTargetTestModuleFactory() Module {
module := &packageTestModule{}
InitPackageModule(module)
InitAndroidMultiTargetsArchModule(module, DeviceSupported, MultilibCommon)
module.AddProperties(&module.properties)
return module
}
func packageTestModuleFactory() Module {
module := &packageTestModule{}
InitPackageModule(module)
InitAndroidArchModule(module, DeviceSupported, MultilibBoth)
module.AddProperties(&module.properties)
return module
}
type packagingDepTag struct {
blueprint.BaseDependencyTag
PackagingItemAlwaysDepTag
}
func (m *packageTestModule) DepsMutator(ctx BottomUpMutatorContext) {
m.AddDeps(ctx, packagingDepTag{})
ctx.AddDependency(ctx.Module(), installDepTag{}, m.properties.Install_deps...)
}
func (m *packageTestModule) GenerateAndroidBuildActions(ctx ModuleContext) {
zipFile := PathForModuleOut(ctx, "myzip.zip")
m.entries = m.CopyDepsToZip(ctx, m.GatherPackagingSpecs(ctx), zipFile)
}
func runPackagingTest(t *testing.T, multitarget bool, bp string, expected []string) {
t.Helper()
var archVariant string
var moduleFactory ModuleFactory
if multitarget {
archVariant = "android_common"
moduleFactory = packageMultiTargetTestModuleFactory
} else {
archVariant = "android_arm64_armv8-a"
moduleFactory = packageTestModuleFactory
}
result := GroupFixturePreparers(
PrepareForTestWithArchMutator,
FixtureRegisterWithContext(func(ctx RegistrationContext) {
ctx.RegisterModuleType("component", componentTestModuleFactory)
ctx.RegisterModuleType("package_module", moduleFactory)
}),
FixtureWithRootAndroidBp(bp),
).RunTest(t)
p := result.Module("package", archVariant).(*packageTestModule)
actual := p.entries
actual = SortedUniqueStrings(actual)
expected = SortedUniqueStrings(expected)
AssertDeepEquals(t, "package entries", expected, actual)
}
func TestPackagingBaseMultiTarget(t *testing.T) {
multiTarget := true
runPackagingTest(t, multiTarget,
`
component {
name: "foo",
}
package_module {
name: "package",
deps: ["foo"],
}
`, []string{"lib64/foo"})
runPackagingTest(t, multiTarget,
`
component {
name: "foo",
deps: ["bar"],
}
component {
name: "bar",
}
package_module {
name: "package",
deps: ["foo"],
}
`, []string{"lib64/foo", "lib64/bar"})
runPackagingTest(t, multiTarget,
`
component {
name: "foo",
deps: ["bar"],
}
component {
name: "bar",
}
package_module {
name: "package",
deps: ["foo"],
compile_multilib: "both",
}
`, []string{"lib32/foo", "lib32/bar", "lib64/foo", "lib64/bar"})
runPackagingTest(t, multiTarget,
`
component {
name: "foo",
}
component {
name: "bar",
compile_multilib: "32",
}
package_module {
name: "package",
deps: ["foo"],
multilib: {
lib32: {
deps: ["bar"],
},
},
compile_multilib: "both",
}
`, []string{"lib32/foo", "lib32/bar", "lib64/foo"})
runPackagingTest(t, multiTarget,
`
component {
name: "foo",
}
component {
name: "bar",
}
package_module {
name: "package",
deps: ["foo"],
multilib: {
first: {
deps: ["bar"],
},
},
compile_multilib: "both",
}
`, []string{"lib32/foo", "lib64/foo", "lib64/bar"})
runPackagingTest(t, multiTarget,
`
component {
name: "foo",
}
component {
name: "bar",
}
component {
name: "baz",
}
package_module {
name: "package",
deps: ["foo"],
arch: {
arm64: {
deps: ["bar"],
},
x86_64: {
deps: ["baz"],
},
},
compile_multilib: "both",
}
`, []string{"lib32/foo", "lib64/foo", "lib64/bar"})
}
func TestSkipInstallProducesLocalUninstallableModule(t *testing.T) {
result := GroupFixturePreparers(
PrepareForTestWithArchMutator,
FixtureRegisterWithContext(func(ctx RegistrationContext) {
ctx.RegisterModuleType("component", componentTestModuleFactory)
ctx.RegisterModuleType("package_module", packageTestModuleFactory)
}),
FixtureWithRootAndroidBp(`
component {
name: "foo",
skip_install: true,
}
package_module {
name: "package",
deps: ["foo"],
}
`),
).RunTest(t)
module := result.ModuleForTests("foo", "android_arm64_armv8-a").Module().(*componentTestModule)
entries := AndroidMkEntriesForTest(t, result.TestContext, module)
builder := &strings.Builder{}
entries[0].write(builder)
androidMkString := builder.String()
if !strings.Contains(androidMkString, "LOCAL_UNINSTALLABLE_MODULE := true") {
t.Errorf("Expected android mk entries to contain \"LOCAL_UNINSTALLABLE_MODULE := true\", got: \n%s", androidMkString)
}
}
func TestPackagingBaseSingleTarget(t *testing.T) {
multiTarget := false
runPackagingTest(t, multiTarget,
`
component {
name: "foo",
}
package_module {
name: "package",
deps: ["foo"],
}
`, []string{"lib64/foo"})
runPackagingTest(t, multiTarget,
`
component {
name: "foo",
deps: ["bar"],
}
component {
name: "bar",
}
package_module {
name: "package",
deps: ["foo"],
}
`, []string{"lib64/foo", "lib64/bar"})
runPackagingTest(t, multiTarget,
`
component {
name: "foo",
}
component {
name: "bar",
compile_multilib: "32",
}
package_module {
name: "package",
deps: ["foo"],
multilib: {
lib32: {
deps: ["bar"],
},
},
}
`, []string{"lib64/foo"})
runPackagingTest(t, multiTarget,
`
component {
name: "foo",
}
component {
name: "bar",
}
package_module {
name: "package",
deps: ["foo"],
multilib: {
lib64: {
deps: ["bar"],
},
},
}
`, []string{"lib64/foo", "lib64/bar"})
runPackagingTest(t, multiTarget,
`
component {
name: "foo",
}
component {
name: "bar",
}
component {
name: "baz",
}
package_module {
name: "package",
deps: ["foo"],
arch: {
arm64: {
deps: ["bar"],
},
x86_64: {
deps: ["baz"],
},
},
}
`, []string{"lib64/foo", "lib64/bar"})
runPackagingTest(t, multiTarget,
`
component {
name: "foo",
}
component {
name: "bar",
}
package_module {
name: "package",
deps: ["foo"],
install_deps: ["bar"],
}
`, []string{"lib64/foo"})
}
func TestPackagingWithSkipInstallDeps(t *testing.T) {
// package -[dep]-> foo -[dep]-> bar -[dep]-> baz
// OK SKIPPED
multiTarget := false
runPackagingTest(t, multiTarget,
`
component {
name: "foo",
deps: ["bar"],
}
component {
name: "bar",
deps: ["baz"],
skip_install: true,
}
component {
name: "baz",
}
package_module {
name: "package",
deps: ["foo"],
}
`, []string{"lib64/foo"})
}