Add "test-only" flag for java modules
As part of aosp/3022586 where we added the idea of "test-only" modules and top_level_test_targets, this CL implements that for java modules. We let users set "test-only" on java_library, but not on other modules where the module kind is implicitly test-only, like java_test. The implementation, not the user decides it is test-only. We also exclude it from java_defaults. % gqui from "flatten(~/aosp-main-with-phones/out/soong/ownership/all_teams.pb, teams)" proto team.proto:AllTeams 'select teams.kind, count(*) where teams.test_only = true and teams.kind not like "%cc_%" group by teams.kind' +--------------------------+----------+ | teams.kind | count(*) | +--------------------------+----------+ | android_test | 1382 | | android_test_helper_app | 1680 | | java_fuzz | 5 | | java_test | 774 | | java_test_helper_library | 29 | +--------------------------+----------+ % gqui from "flatten(~/aosp-main-with-phones/out/soong/ownership/all_teams.pb, teams)" proto team.proto:AllTeams 'select teams.kind, count(*) where teams.top_level_target = true and teams.kind not like "%cc_%" group by teams.kind' +--------------+----------+ | teams.kind | count(*) | +--------------+----------+ | android_test | 1382 | | java_fuzz | 5 | | java_test | 774 | +--------------+----------+ Test: m nothing --no-skip-soong-tests Test: go test ./java Test: m all_teams Bug: b/327280661 Change-Id: I9c3ad947dc3d68d6427abada27449526d69daa6b
This commit is contained in:
parent
fc5cdcbdf5
commit
cdc66f4268
7 changed files with 195 additions and 4 deletions
|
@ -922,7 +922,8 @@ func AndroidLibraryFactory() android.Module {
|
||||||
module.Module.addHostAndDeviceProperties()
|
module.Module.addHostAndDeviceProperties()
|
||||||
module.AddProperties(
|
module.AddProperties(
|
||||||
&module.aaptProperties,
|
&module.aaptProperties,
|
||||||
&module.androidLibraryProperties)
|
&module.androidLibraryProperties,
|
||||||
|
&module.sourceProperties)
|
||||||
|
|
||||||
module.androidLibraryProperties.BuildAAR = true
|
module.androidLibraryProperties.BuildAAR = true
|
||||||
module.Module.linter.library = true
|
module.Module.linter.library = true
|
||||||
|
|
18
java/app.go
18
java/app.go
|
@ -329,6 +329,10 @@ func (a *AndroidTestHelperApp) GenerateAndroidBuildActions(ctx android.ModuleCon
|
||||||
a.aapt.manifestValues.applicationId = *applicationId
|
a.aapt.manifestValues.applicationId = *applicationId
|
||||||
}
|
}
|
||||||
a.generateAndroidBuildActions(ctx)
|
a.generateAndroidBuildActions(ctx)
|
||||||
|
android.SetProvider(ctx, android.TestOnlyProviderKey, android.TestModuleInformation{
|
||||||
|
TestOnly: true,
|
||||||
|
})
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *AndroidApp) GenerateAndroidBuildActions(ctx android.ModuleContext) {
|
func (a *AndroidApp) GenerateAndroidBuildActions(ctx android.ModuleContext) {
|
||||||
|
@ -1191,7 +1195,8 @@ func AndroidAppFactory() android.Module {
|
||||||
module.AddProperties(
|
module.AddProperties(
|
||||||
&module.aaptProperties,
|
&module.aaptProperties,
|
||||||
&module.appProperties,
|
&module.appProperties,
|
||||||
&module.overridableAppProperties)
|
&module.overridableAppProperties,
|
||||||
|
&module.Library.sourceProperties)
|
||||||
|
|
||||||
module.usesLibrary.enforce = true
|
module.usesLibrary.enforce = true
|
||||||
|
|
||||||
|
@ -1340,6 +1345,11 @@ func (a *AndroidTest) GenerateAndroidBuildActions(ctx android.ModuleContext) {
|
||||||
TestSuites: a.testProperties.Test_suites,
|
TestSuites: a.testProperties.Test_suites,
|
||||||
IsHost: false,
|
IsHost: false,
|
||||||
})
|
})
|
||||||
|
android.SetProvider(ctx, android.TestOnlyProviderKey, android.TestModuleInformation{
|
||||||
|
TestOnly: true,
|
||||||
|
TopLevelTarget: true,
|
||||||
|
})
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *AndroidTest) FixTestConfig(ctx android.ModuleContext, testConfig android.Path) android.Path {
|
func (a *AndroidTest) FixTestConfig(ctx android.ModuleContext, testConfig android.Path) android.Path {
|
||||||
|
@ -1532,9 +1542,13 @@ type OverrideAndroidTest struct {
|
||||||
android.OverrideModuleBase
|
android.OverrideModuleBase
|
||||||
}
|
}
|
||||||
|
|
||||||
func (i *OverrideAndroidTest) GenerateAndroidBuildActions(_ android.ModuleContext) {
|
func (i *OverrideAndroidTest) GenerateAndroidBuildActions(ctx android.ModuleContext) {
|
||||||
// All the overrides happen in the base module.
|
// All the overrides happen in the base module.
|
||||||
// TODO(jungjw): Check the base module type.
|
// TODO(jungjw): Check the base module type.
|
||||||
|
android.SetProvider(ctx, android.TestOnlyProviderKey, android.TestModuleInformation{
|
||||||
|
TestOnly: true,
|
||||||
|
TopLevelTarget: true,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// override_android_test is used to create an android_app module based on another android_test by overriding
|
// override_android_test is used to create an android_app module based on another android_test by overriding
|
||||||
|
|
|
@ -4432,6 +4432,44 @@ func TestNoDexpreoptOptionalUsesLibDoesNotHaveImpl(t *testing.T) {
|
||||||
android.AssertBoolEquals(t, "dexpreopt should be disabled if optional_uses_libs does not have an implementation", true, dexpreopt == nil)
|
android.AssertBoolEquals(t, "dexpreopt should be disabled if optional_uses_libs does not have an implementation", true, dexpreopt == nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestTestOnlyApp(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
ctx := android.GroupFixturePreparers(
|
||||||
|
prepareForJavaTest,
|
||||||
|
).RunTestWithBp(t, `
|
||||||
|
// These should be test-only
|
||||||
|
android_test {
|
||||||
|
name: "android-test",
|
||||||
|
}
|
||||||
|
android_test_helper_app {
|
||||||
|
name: "helper-app",
|
||||||
|
}
|
||||||
|
override_android_test {
|
||||||
|
name: "override-test",
|
||||||
|
base: "android-app",
|
||||||
|
}
|
||||||
|
// And these should not be
|
||||||
|
android_app {
|
||||||
|
name: "android-app",
|
||||||
|
srcs: ["b.java"],
|
||||||
|
sdk_version: "current",
|
||||||
|
}
|
||||||
|
`)
|
||||||
|
|
||||||
|
expectedTestOnly := []string{
|
||||||
|
"android-test",
|
||||||
|
"helper-app",
|
||||||
|
"override-test",
|
||||||
|
}
|
||||||
|
|
||||||
|
expectedTopLevel := []string{
|
||||||
|
"android-test",
|
||||||
|
"override-test",
|
||||||
|
}
|
||||||
|
|
||||||
|
assertTestOnlyAndTopLevel(t, ctx, expectedTestOnly, expectedTopLevel)
|
||||||
|
}
|
||||||
|
|
||||||
func TestAppStem(t *testing.T) {
|
func TestAppStem(t *testing.T) {
|
||||||
ctx := testApp(t, `
|
ctx := testApp(t, `
|
||||||
android_app {
|
android_app {
|
||||||
|
|
|
@ -435,6 +435,7 @@ type Module struct {
|
||||||
deviceProperties DeviceProperties
|
deviceProperties DeviceProperties
|
||||||
|
|
||||||
overridableProperties OverridableProperties
|
overridableProperties OverridableProperties
|
||||||
|
sourceProperties android.SourceProperties
|
||||||
|
|
||||||
// jar file containing header classes including static library dependencies, suitable for
|
// jar file containing header classes including static library dependencies, suitable for
|
||||||
// inserting into the bootclasspath/classpath of another compile
|
// inserting into the bootclasspath/classpath of another compile
|
||||||
|
|
|
@ -64,6 +64,8 @@ func JavaFuzzFactory() android.Module {
|
||||||
module.Module.properties.Installable = proptools.BoolPtr(true)
|
module.Module.properties.Installable = proptools.BoolPtr(true)
|
||||||
module.Module.dexpreopter.isTest = true
|
module.Module.dexpreopter.isTest = true
|
||||||
module.Module.linter.properties.Lint.Test = proptools.BoolPtr(true)
|
module.Module.linter.properties.Lint.Test = proptools.BoolPtr(true)
|
||||||
|
module.Module.sourceProperties.Test_only = proptools.BoolPtr(true)
|
||||||
|
module.Module.sourceProperties.Top_level_test_target = true
|
||||||
|
|
||||||
android.AddLoadHook(module, func(ctx android.LoadHookContext) {
|
android.AddLoadHook(module, func(ctx android.LoadHookContext) {
|
||||||
disableLinuxBionic := struct {
|
disableLinuxBionic := struct {
|
||||||
|
|
13
java/java.go
13
java/java.go
|
@ -958,6 +958,11 @@ func (j *Library) GenerateAndroidBuildActions(ctx android.ModuleContext) {
|
||||||
}
|
}
|
||||||
j.installFile = ctx.InstallFile(installDir, j.Stem()+".jar", j.outputFile, extraInstallDeps...)
|
j.installFile = ctx.InstallFile(installDir, j.Stem()+".jar", j.outputFile, extraInstallDeps...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
android.SetProvider(ctx, android.TestOnlyProviderKey, android.TestModuleInformation{
|
||||||
|
TestOnly: Bool(j.sourceProperties.Test_only),
|
||||||
|
TopLevelTarget: j.sourceProperties.Top_level_test_target,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (j *Library) DepsMutator(ctx android.BottomUpMutatorContext) {
|
func (j *Library) DepsMutator(ctx android.BottomUpMutatorContext) {
|
||||||
|
@ -1123,6 +1128,7 @@ func LibraryFactory() android.Module {
|
||||||
module := &Library{}
|
module := &Library{}
|
||||||
|
|
||||||
module.addHostAndDeviceProperties()
|
module.addHostAndDeviceProperties()
|
||||||
|
module.AddProperties(&module.sourceProperties)
|
||||||
|
|
||||||
module.initModuleAndImport(module)
|
module.initModuleAndImport(module)
|
||||||
|
|
||||||
|
@ -1604,6 +1610,8 @@ func TestFactory() android.Module {
|
||||||
module.Module.properties.Installable = proptools.BoolPtr(true)
|
module.Module.properties.Installable = proptools.BoolPtr(true)
|
||||||
module.Module.dexpreopter.isTest = true
|
module.Module.dexpreopter.isTest = true
|
||||||
module.Module.linter.properties.Lint.Test = proptools.BoolPtr(true)
|
module.Module.linter.properties.Lint.Test = proptools.BoolPtr(true)
|
||||||
|
module.Module.sourceProperties.Test_only = proptools.BoolPtr(true)
|
||||||
|
module.Module.sourceProperties.Top_level_test_target = true
|
||||||
|
|
||||||
InitJavaModule(module, android.HostAndDeviceSupported)
|
InitJavaModule(module, android.HostAndDeviceSupported)
|
||||||
return module
|
return module
|
||||||
|
@ -1619,6 +1627,7 @@ func TestHelperLibraryFactory() android.Module {
|
||||||
module.Module.properties.Installable = proptools.BoolPtr(true)
|
module.Module.properties.Installable = proptools.BoolPtr(true)
|
||||||
module.Module.dexpreopter.isTest = true
|
module.Module.dexpreopter.isTest = true
|
||||||
module.Module.linter.properties.Lint.Test = proptools.BoolPtr(true)
|
module.Module.linter.properties.Lint.Test = proptools.BoolPtr(true)
|
||||||
|
module.Module.sourceProperties.Test_only = proptools.BoolPtr(true)
|
||||||
|
|
||||||
InitJavaModule(module, android.HostAndDeviceSupported)
|
InitJavaModule(module, android.HostAndDeviceSupported)
|
||||||
return module
|
return module
|
||||||
|
@ -1674,6 +1683,8 @@ func InitTestHost(th *TestHost, installable *bool, testSuites []string, autoGenC
|
||||||
th.properties.Installable = installable
|
th.properties.Installable = installable
|
||||||
th.testProperties.Auto_gen_config = autoGenConfig
|
th.testProperties.Auto_gen_config = autoGenConfig
|
||||||
th.testProperties.Test_suites = testSuites
|
th.testProperties.Test_suites = testSuites
|
||||||
|
th.sourceProperties.Test_only = proptools.BoolPtr(true)
|
||||||
|
th.sourceProperties.Top_level_test_target = true
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
|
@ -1799,7 +1810,7 @@ func BinaryFactory() android.Module {
|
||||||
module := &Binary{}
|
module := &Binary{}
|
||||||
|
|
||||||
module.addHostAndDeviceProperties()
|
module.addHostAndDeviceProperties()
|
||||||
module.AddProperties(&module.binaryProperties)
|
module.AddProperties(&module.binaryProperties, &module.sourceProperties)
|
||||||
|
|
||||||
module.Module.properties.Installable = proptools.BoolPtr(true)
|
module.Module.properties.Installable = proptools.BoolPtr(true)
|
||||||
|
|
||||||
|
|
|
@ -2838,6 +2838,99 @@ func TestApiLibraryAconfigDeclarations(t *testing.T) {
|
||||||
android.AssertStringDoesContain(t, "flagged api hide command not included", cmdline, "revert-annotations-exportable.txt")
|
android.AssertStringDoesContain(t, "flagged api hide command not included", cmdline, "revert-annotations-exportable.txt")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestTestOnly(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
ctx := android.GroupFixturePreparers(
|
||||||
|
prepareForJavaTest,
|
||||||
|
).RunTestWithBp(t, `
|
||||||
|
// These should be test-only
|
||||||
|
java_library {
|
||||||
|
name: "lib1-test-only",
|
||||||
|
srcs: ["a.java"],
|
||||||
|
test_only: true,
|
||||||
|
}
|
||||||
|
java_test {
|
||||||
|
name: "java-test",
|
||||||
|
}
|
||||||
|
java_test_host {
|
||||||
|
name: "java-test-host",
|
||||||
|
}
|
||||||
|
java_test_helper_library {
|
||||||
|
name: "helper-library",
|
||||||
|
}
|
||||||
|
java_binary {
|
||||||
|
name: "java-data-binary",
|
||||||
|
srcs: ["foo.java"],
|
||||||
|
main_class: "foo.bar.jb",
|
||||||
|
test_only: true,
|
||||||
|
}
|
||||||
|
|
||||||
|
// These are NOT
|
||||||
|
java_library {
|
||||||
|
name: "lib2-app",
|
||||||
|
srcs: ["b.java"],
|
||||||
|
}
|
||||||
|
java_import {
|
||||||
|
name: "bar",
|
||||||
|
jars: ["bar.jar"],
|
||||||
|
}
|
||||||
|
java_binary {
|
||||||
|
name: "java-binary",
|
||||||
|
srcs: ["foo.java"],
|
||||||
|
main_class: "foo.bar.jb",
|
||||||
|
}
|
||||||
|
`)
|
||||||
|
|
||||||
|
expectedTestOnlyModules := []string{
|
||||||
|
"lib1-test-only",
|
||||||
|
"java-test",
|
||||||
|
"java-test-host",
|
||||||
|
"helper-library",
|
||||||
|
"java-data-binary",
|
||||||
|
}
|
||||||
|
expectedTopLevelTests := []string{
|
||||||
|
"java-test",
|
||||||
|
"java-test-host",
|
||||||
|
}
|
||||||
|
assertTestOnlyAndTopLevel(t, ctx, expectedTestOnlyModules, expectedTopLevelTests)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Don't allow setting test-only on things that are always tests or never tests.
|
||||||
|
func TestInvalidTestOnlyTargets(t *testing.T) {
|
||||||
|
testCases := []string{
|
||||||
|
` java_test { name: "java-test", test_only: true, srcs: ["foo.java"], } `,
|
||||||
|
` java_test_host { name: "java-test-host", test_only: true, srcs: ["foo.java"], } `,
|
||||||
|
` java_test_import { name: "java-test-import", test_only: true, } `,
|
||||||
|
` java_api_library { name: "java-api-library", test_only: true, } `,
|
||||||
|
` java_test_helper_library { name: "test-help-lib", test_only: true, } `,
|
||||||
|
` java_defaults { name: "java-defaults", test_only: true, } `,
|
||||||
|
}
|
||||||
|
|
||||||
|
for i, bp := range testCases {
|
||||||
|
android.GroupFixturePreparers(prepareForJavaTest).
|
||||||
|
ExtendWithErrorHandler(
|
||||||
|
expectOneError("unrecognized property \"test_only\"",
|
||||||
|
fmt.Sprintf("testcase: %d", i))).
|
||||||
|
RunTestWithBp(t, bp)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Expect exactly one that matches 'expected'.
|
||||||
|
// Append 'msg' to the Errorf that printed.
|
||||||
|
func expectOneError(expected string, msg string) android.FixtureErrorHandler {
|
||||||
|
return android.FixtureCustomErrorHandler(func(t *testing.T, result *android.TestResult) {
|
||||||
|
t.Helper()
|
||||||
|
if len(result.Errs) != 1 {
|
||||||
|
t.Errorf("Expected exactly one error, but found: %d when setting test_only on: %s", len(result.Errs), msg)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
actualErrMsg := result.Errs[0].Error()
|
||||||
|
if !strings.Contains(actualErrMsg, expected) {
|
||||||
|
t.Errorf("Different error than expected. Received: [%v] on %s expected: %s", actualErrMsg, msg, expected)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
func TestJavaLibHostWithStem(t *testing.T) {
|
func TestJavaLibHostWithStem(t *testing.T) {
|
||||||
ctx, _ := testJava(t, `
|
ctx, _ := testJava(t, `
|
||||||
java_library_host {
|
java_library_host {
|
||||||
|
@ -2917,3 +3010,34 @@ func TestJavaLibraryOutputFilesRel(t *testing.T) {
|
||||||
android.AssertStringEquals(t, "baz relative output path",
|
android.AssertStringEquals(t, "baz relative output path",
|
||||||
"baz.jar", bazOutputPath.Rel())
|
"baz.jar", bazOutputPath.Rel())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func assertTestOnlyAndTopLevel(t *testing.T, ctx *android.TestResult, expectedTestOnly []string, expectedTopLevel []string) {
|
||||||
|
t.Helper()
|
||||||
|
actualTrueModules := []string{}
|
||||||
|
actualTopLevelTests := []string{}
|
||||||
|
addActuals := func(m blueprint.Module, key blueprint.ProviderKey[android.TestModuleInformation]) {
|
||||||
|
if provider, ok := android.OtherModuleProvider(ctx.TestContext.OtherModuleProviderAdaptor(), m, key); ok {
|
||||||
|
if provider.TestOnly {
|
||||||
|
actualTrueModules = append(actualTrueModules, m.Name())
|
||||||
|
}
|
||||||
|
if provider.TopLevelTarget {
|
||||||
|
actualTopLevelTests = append(actualTopLevelTests, m.Name())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx.VisitAllModules(func(m blueprint.Module) {
|
||||||
|
addActuals(m, android.TestOnlyProviderKey)
|
||||||
|
|
||||||
|
})
|
||||||
|
|
||||||
|
notEqual, left, right := android.ListSetDifference(expectedTestOnly, actualTrueModules)
|
||||||
|
if notEqual {
|
||||||
|
t.Errorf("test-only: Expected but not found: %v, Found but not expected: %v", left, right)
|
||||||
|
}
|
||||||
|
|
||||||
|
notEqual, left, right = android.ListSetDifference(expectedTopLevel, actualTopLevelTests)
|
||||||
|
if notEqual {
|
||||||
|
t.Errorf("top-level: Expected but not found: %v, Found but not expected: %v", left, right)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue