Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Android/build/build/soong/java/   (Android Betriebssystem Version 17©)  Datei vom 26.5.2026 mit Größe 31 kB image not shown  

Quelle  testing.go   Sprache: unbekannt

 
Spracherkennung für: .go vermutete Sprache: Unknown {[0] [0] [0]} [Methode: Schwerpunktbildung, einfache Gewichte, sechs Dimensionen]

// Copyright 2019 Google Inc. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package java

import (
 "fmt"
 "reflect"
 "regexp"
 "strings"
 "testing"

 "android/soong/android"
 "android/soong/cc"
 "android/soong/dexpreopt"

 "github.com/google/blueprint"
)

const defaultJavaDir = "default/java"
const testDefaultUpdatableModuleVersion = "340090000"

// 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.GroupFixturePreparers(
 // Make sure that mutators and module types, e.g. prebuilt mutators available.
 android.PrepareForTestWithAndroidBuildComponents,
 // Make java build components available to the test.
 android.FixtureRegisterWithContext(registerRequiredBuildComponentsForTest),
 android.FixtureRegisterWithContext(registerJavaPluginBuildComponents),
 android.PrepareForTestWithHostTools("cp_if_changed", "rm", "touch", "grep"),
 // Additional files needed in tests that disallow non-existent source files.
 // This includes files that are needed by all, or at least most, instances of a java module type.
 android.MockFS{
  // Needed for linter used by java_library.
  "build/soong/java/lint_defaults.txt": nil,
  // Needed for java components that invoke Metalava.
  "build/soong/java/metalava/default-unsafe-ignore-missing-latest-api.txt": nil,
  "build/soong/java/metalava/Android.bp": []byte(`
    filegroup {name: "metalava-config-files"}
    filegroup {
            name: "default-unsafe-ignore-missing-latest-api",
            srcs: ["default-unsafe-ignore-missing-latest-api.txt"],
        }
   `),
  // Needed for apps that do not provide their own.
  "build/make/target/product/security/default_testkey.x509.pem": nil,
  "external/error_prone/Android.bp": []byte(`
   java_plugin {
    name: "error_prone_plugin",
    errorprone: {
     enabled: false,
    },
   }
   `),
  // Needed for the global lint checks provided from tools/lint_checks
  "tools/lint_checks/global/Android.bp": []byte(`
   java_library_host {
    name: "AndroidGlobalLintChecker",
   }
   `),
 }.AddToFixture(),
 android.PrepareForTestWithBuildFlag("RELEASE_DEFAULT_UPDATABLE_MODULE_VERSION", testDefaultUpdatableModuleVersion),
)

var prepareForTestWithFrameworkDeps = android.GroupFixturePreparers(
 // The java default module definitions.
 android.FixtureAddTextFile(defaultJavaDir+"/Android.bp", gatherRequiredDepsForTest()),
 // Additional files needed when test disallows non-existent source.
 android.MockFS{
  // Needed for framework-res
  defaultJavaDir + "/AndroidManifest.xml": nil,
  // Needed for framework
  defaultJavaDir + "/framework/aidl": nil,
  // Needed for various deps defined in GatherRequiredDepsForTest()
  defaultJavaDir + "/a.java":                        nil,
  defaultJavaDir + "/api/current.txt":               nil,
  defaultJavaDir + "/api/removed.txt":               nil,
  defaultJavaDir + "/api/system-current.txt":        nil,
  defaultJavaDir + "/api/system-removed.txt":        nil,
  defaultJavaDir + "/api/test-current.txt":          nil,
  defaultJavaDir + "/api/test-removed.txt":          nil,
  defaultJavaDir + "/api/module-lib-current.txt":    nil,
  defaultJavaDir + "/api/module-lib-removed.txt":    nil,
  defaultJavaDir + "/api/system-server-current.txt": nil,
  defaultJavaDir + "/api/system-server-removed.txt": nil,

  // Needed for R8 rules on apps
  "build/make/core/proguard.flags":             nil,
  "build/make/core/proguard_basic_keeps.flags": nil,
  "build/make/core/proguard/enumvalues.flags":  nil,
  "build/make/core/proguard/kotlin.flags":      nil,
  "prebuilts/cmdline-tools/shrinker.xml":       nil,
  defaultJavaDir + "/framework-private.flags":  nil,
 }.AddToFixture(),
)

var prepareForTestWithJavaDefaultModulesBase = android.GroupFixturePreparers(
 // Make sure that all the module types used in the defaults are registered.
 PrepareForTestWithJavaBuildComponents,
 prepareForTestWithFrameworkDeps,
 // Add dexpreopt compat libs (android.test.base, etc.) and a fake dex2oatd module.
 dexpreopt.PrepareForTestWithDexpreoptCompatLibs,
 android.PrepareForTestWithHostTools(
  "dexdeps",
  "gen_apex_symbols",
 ),
)

// Test fixture preparer that will define default java modules, e.g. standard prebuilt modules.
var PrepareForTestWithJavaDefaultModules = android.GroupFixturePreparers(
 prepareForTestWithJavaDefaultModulesBase,
 dexpreopt.FixtureDisableDexpreoptBootImages(true),
 dexpreopt.FixtureDisableDexpreopt(true),
)

// Provides everything needed by dexpreopt.
var PrepareForTestWithDexpreopt = android.GroupFixturePreparers(
 prepareForTestWithJavaDefaultModulesBase,
 dexpreopt.PrepareForTestWithFakeDex2oatd,
 dexpreopt.PrepareForTestByEnablingDexpreopt,
)

// Provides everything needed by dexpreopt except the fake_tool_binary for dex2oatd.
var PrepareForTestWithDexpreoptWithoutFakeDex2oatd = android.GroupFixturePreparers(
 prepareForTestWithJavaDefaultModulesBase,
 dexpreopt.PrepareForTestByEnablingDexpreopt,
)

// 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,
)

// Prepare a fixture with the standard files required by a java_sdk_library module.
var PrepareForTestWithJavaSdkLibraryFiles = android.FixtureMergeMockFs(android.MockFS{
 "api/current.txt":               nil,
 "api/removed.txt":               nil,
 "api/system-current.txt":        nil,
 "api/system-removed.txt":        nil,
 "api/test-current.txt":          nil,
 "api/test-removed.txt":          nil,
 "api/module-lib-current.txt":    nil,
 "api/module-lib-removed.txt":    nil,
 "api/system-server-current.txt": nil,
 "api/system-server-removed.txt": nil,
})

// FixtureWithLastReleaseApis creates a preparer that creates prebuilt versions of the specified
// modules for the `last` API release. By `last` it just means last in the list of supplied versions
// and as this only provides one version it can be any value.
//
// This uses FixtureWithPrebuiltApis under the covers so the limitations of that apply to this.
func FixtureWithLastReleaseApis(moduleNames ...string) android.FixturePreparer {
 return FixtureWithPrebuiltApis(map[string][]string{
  "30": moduleNames,
 })
}

// PrepareForTestWithPrebuiltsOfCurrentApi is a preparer that creates prebuilt versions of the
// standard modules for the current version.
//
// This uses FixtureWithPrebuiltApis under the covers so the limitations of that apply to this.
var PrepareForTestWithPrebuiltsOfCurrentApi = FixtureWithPrebuiltApis(map[string][]string{
 "current": {},
 // Can't have current on its own as it adds a prebuilt_apis module but doesn't add any
 // .txt files which causes the prebuilt_apis module to fail.
 "30": {},
})

var prepareForTestWithFrameworkJacocoInstrumentation = android.GroupFixturePreparers(
 android.FixtureMergeEnv(map[string]string{
  "EMMA_INSTRUMENT_FRAMEWORK": "true",
 }),
 PrepareForTestWithJacocoInstrumentation,
)

// PrepareForTestWithJacocoInstrumentation creates a mock jacocoagent library that can be
// depended on as part of the build process for instrumented Java modules.
var PrepareForTestWithJacocoInstrumentation = android.GroupFixturePreparers(
 android.FixtureMergeEnv(map[string]string{
  "EMMA_INSTRUMENT": "true",
 }),
 android.FixtureAddFile("jacocoagent/Test.java", nil),
 android.FixtureAddFile("jacocoagent/Android.bp", []byte(`
  java_library {
   name: "jacocoagent",
   host_supported: true,
   srcs: ["Test.java"],
   sdk_version: "current",
   apex_available: [
    "//apex_available:anyapex",
    "//apex_available:platform",
   ],
   compile_dex: true,
   optimize: {
    force_disabled_with_source_stubs: true,
   },
  }
 `)),
)

// FixtureWithPrebuiltApis creates a preparer that will define prebuilt api modules for the
// specified releases and modules.
//
// The supplied map keys are the releases, e.g. current, 2930, etc. The values are a list of
// modules for that release. Due to limitations in the prebuilt_apis module which this preparer
// uses the set of releases must include at least one numbered release, i.e. it cannot just include
// "current".
//
// This defines a file in the mock file system in a predefined location (prebuilts/sdk/Android.bp)
// and so only one instance of this can be used in each fixture.
func FixtureWithPrebuiltApis(release2Modules map[string][]string) android.FixturePreparer {
 return FixtureWithPrebuiltApisAndExtensions(release2Modules, nil)
}

func FixtureWithPrebuiltApisAndExtensions(apiLevel2Modules map[string][]string, extensionLevel2Modules map[string][]string) android.FixturePreparer {
 mockFS := android.MockFS{}
 path := "prebuilts/sdk/Android.bp"

 bp := fmt.Sprintf(`
   prebuilt_apis {
    name: "sdk",
    api_dirs: ["%s"],
    extensions_dir: "extensions",
    imports_sdk_version: "none",
    imports_compile_dex: true,
   }
  `, strings.Join(android.SortedKeys(apiLevel2Modules), `", "`))

 for release, modules := range apiLevel2Modules {
  mockFS.Merge(prebuiltApisFilesForModules([]string{release}, modules))
 }
 if extensionLevel2Modules != nil {
  for release, modules := range extensionLevel2Modules {
   mockFS.Merge(prebuiltExtensionApiFiles([]string{release}, modules))
  }
 }
 return android.GroupFixturePreparers(
  android.FixtureAddTextFile(path, bp),
  android.FixtureMergeMockFs(mockFS),
 )
}

func prebuiltApisFilesForModules(apiLevels []string, modules []string) map[string][]byte {
 libs := append([]string{"android"}, modules...)

 fs := make(map[string][]byte)
 for _, level := range apiLevels {
  apiLevel := android.ApiLevelForTest(level)
  for _, sdkKind := range []android.SdkKind{android.SdkPublic, android.SdkSystem, android.SdkModule, android.SdkSystemServer, android.SdkTest} {
   // A core-for-system-modules file must only be created for the sdk kind that supports it.
   if sdkKind == systemModuleKind(sdkKind, apiLevel) {
    fs[fmt.Sprintf("prebuilts/sdk/%s/%s/core-for-system-modules.jar", level, sdkKind)] = nil
   }

   for _, lib := range libs {
    // Create a jar file for every library.
    fs[fmt.Sprintf("prebuilts/sdk/%s/%s/%s.jar", level, sdkKind, lib)] = nil

    // No finalized API files for "current"
    if level != "current" {
     fs[fmt.Sprintf("prebuilts/sdk/%s/%s/api/%s.txt", level, sdkKind, lib)] = nil
     fs[fmt.Sprintf("prebuilts/sdk/%s/%s/api/%s-removed.txt", level, sdkKind, lib)] = nil
    }
   }
  }
  if level == "current" {
   fs["prebuilts/sdk/current/core/android.jar"] = nil
  }
  fs[fmt.Sprintf("prebuilts/sdk/%s/public/framework.aidl", level)] = nil
 }
 return fs
}

func prebuiltExtensionApiFiles(extensionLevels []string, modules []string) map[string][]byte {
 fs := make(map[string][]byte)
 for _, level := range extensionLevels {
  for _, sdkKind := range []android.SdkKind{android.SdkPublic, android.SdkSystem, android.SdkModule, android.SdkSystemServer} {
   for _, lib := range modules {
    fs[fmt.Sprintf("prebuilts/sdk/extensions/%s/%s/api/%s.txt", level, sdkKind, lib)] = nil
    fs[fmt.Sprintf("prebuilts/sdk/extensions/%s/%s/api/%s-removed.txt", level, sdkKind, lib)] = nil
   }
  }
 }
 return fs
}

// FixtureConfigureBootJars configures the boot jars in both the dexpreopt.GlobalConfig and
// Config.productVariables structs. As a side effect that enables dexpreopt.
func FixtureConfigureBootJars(bootJars ...string) android.FixturePreparer {
 artBootJars := []string{}
 for _, j := range bootJars {
  artApex := false
  for _, artApexName := range artApexNames {
   if strings.HasPrefix(j, artApexName+":") {
    artApex = true
    break
   }
  }
  if artApex {
   artBootJars = append(artBootJars, j)
  }
 }
 return android.GroupFixturePreparers(
  android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
   variables.BootJars = android.CreateTestConfiguredJarList(bootJars)
  }),
  dexpreopt.FixtureSetBootJars(bootJars...),
  dexpreopt.FixtureSetArtBootJars(artBootJars...),

  // Add a fake dex2oatd module.
  dexpreopt.PrepareForTestWithFakeDex2oatd,
 )
}

// FixtureConfigureApexBootJars configures the apex boot jars in both the
// dexpreopt.GlobalConfig and Config.productVariables structs. As a side effect that enables
// dexpreopt.
func FixtureConfigureApexBootJars(bootJars ...string) android.FixturePreparer {
 return android.GroupFixturePreparers(
  android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
   variables.ApexBootJars = android.CreateTestConfiguredJarList(bootJars)
  }),
  dexpreopt.FixtureSetApexBootJars(bootJars...),

  // Add a fake dex2oatd module.
  dexpreopt.PrepareForTestWithFakeDex2oatd,
 )
}

// FixtureUseLegacyCorePlatformApi prepares the fixture by setting the exception list of those
// modules that are allowed to use the legacy core platform API to be the ones supplied.
func FixtureUseLegacyCorePlatformApi(moduleNames ...string) android.FixturePreparer {
 lookup := make(map[string]struct{})
 for _, moduleName := range moduleNames {
  lookup[moduleName] = struct{}{}
 }
 return android.FixtureModifyConfig(func(config android.Config) {
  // Try and set the legacyCorePlatformApiLookup in the config, the returned value will be the
  // actual value that is set.
  cached := config.Once(legacyCorePlatformApiLookupKey, func() interface{} {
   return lookup
  })
  // Make sure that the cached value is the one we need.
  if !reflect.DeepEqual(cached, lookup) {
   panic(fmt.Errorf("attempting to set legacyCorePlatformApiLookupKey to %q but it has already been set to %q", lookup, cached))
  }
 })
}

// registerRequiredBuildComponentsForTest registers the build components used by
// PrepareForTestWithJavaDefaultModules.
//
// As functionality is moved out of here into separate FixturePreparer instances they should also
// be moved into GatherRequiredDepsForTest for use by tests that have not yet switched to use test
// fixtures.
func registerRequiredBuildComponentsForTest(ctx android.RegistrationContext) {
 RegisterAARBuildComponents(ctx)
 RegisterAppBuildComponents(ctx)
 RegisterAppImportBuildComponents(ctx)
 RegisterAppSetBuildComponents(ctx)
 registerBootclasspathFragmentBuildComponents(ctx)
 RegisterDexpreoptBootJarsComponents(ctx)
 RegisterDocsBuildComponents(ctx)
 RegisterGenRuleBuildComponents(ctx)
 registerJavaBuildComponents(ctx)
 registerPlatformBootclasspathBuildComponents(ctx)
 RegisterPrebuiltApisBuildComponents(ctx)
 RegisterRuntimeResourceOverlayBuildComponents(ctx)
 RegisterSdkLibraryBuildComponents(ctx)
 RegisterStubsBuildComponents(ctx)
 RegisterSystemModulesBuildComponents(ctx)
 registerSystemserverClasspathBuildComponents(ctx)
 android.RegisterApexContributionsBuildComponents(ctx)
}

// gatherRequiredDepsForTest gathers the module definitions used by
// PrepareForTestWithJavaDefaultModules.
//
// As functionality is moved out of here into separate FixturePreparer instances they should also
// be moved into GatherRequiredDepsForTest for use by tests that have not yet switched to use test
// fixtures.
func gatherRequiredDepsForTest() string {
 var bp string

 extraModules := []string{
  "core-lambda-stubs",
  "ext",
  "android_stubs_current",
  "android_system_stubs_current",
  "android_test_stubs_current",
  "android_module_lib_stubs_current",
  "android_system_server_stubs_current",
  "core.current.stubs",
  "legacy.core.platform.api.stubs",
  "stable.core.platform.api.stubs",
  "android_stubs_current_exportable",
  "android_system_stubs_current_exportable",
  "android_test_stubs_current_exportable",
  "android_module_lib_stubs_current_exportable",
  "android_system_server_stubs_current_exportable",
  "core.current.stubs.exportable",
  "legacy.core.platform.api.stubs.exportable",
  "kotlin-stdlib",
  "kotlin-stdlib-jdk7",
  "kotlin-stdlib-jdk8",
  "kotlin-annotations",
  "stub-annotations",
  "aconfig-annotations-lib",
  "aconfig_storage_stub",
  "unsupportedappusage",
 }

 for _, extra := range extraModules {
  bp += fmt.Sprintf(`
   java_library {
    name: "%s",
    srcs: ["a.java"],
    sdk_version: "none",
    system_modules: "stable-core-platform-api-stubs-system-modules",
    compile_dex: true,
    is_stubs_module: true,
   }
  `, extra)
 }

 type droidstubsStruct struct {
  name        string
  apiSurface  string
  apiFile     string
  removedFile string
 }

 var publicDroidstubs = droidstubsStruct{
  name:        "api-stubs-docs-non-updatable",
  apiSurface:  "public",
  apiFile:     "api/current.txt",
  removedFile: "api/removed.txt",
 }
 var systemDroidstubs = droidstubsStruct{
  name:        "system-api-stubs-docs-non-updatable",
  apiSurface:  "system",
  apiFile:     "api/system-current.txt",
  removedFile: "api/system-removed.txt",
 }
 var testDroidstubs = droidstubsStruct{
  name:        "test-api-stubs-docs-non-updatable",
  apiSurface:  "test",
  apiFile:     "api/test-current.txt",
  removedFile: "api/test-removed.txt",
 }
 var moduleLibDroidstubs = droidstubsStruct{
  name:        "module-lib-api-stubs-docs-non-updatable",
  apiSurface:  "module-lib",
  apiFile:     "api/module-lib-current.txt",
  removedFile: "api/module-lib-removed.txt",
 }
 var systemServerDroidstubs = droidstubsStruct{
  // This module does not exist but is named this way for consistency
  name:        "system-server-api-stubs-docs-non-updatable",
  apiSurface:  "system-server",
  apiFile:     "api/system-server-current.txt",
  removedFile: "api/system-server-removed.txt",
 }
 var droidstubsStructs = []droidstubsStruct{
  publicDroidstubs,
  systemDroidstubs,
  testDroidstubs,
  moduleLibDroidstubs,
  systemServerDroidstubs,
 }

 extraApiLibraryModules := map[string]droidstubsStruct{
  "android_stubs_current.from-text":                 publicDroidstubs,
  "android_system_stubs_current.from-text":          systemDroidstubs,
  "android_test_stubs_current.from-text":            testDroidstubs,
  "android_module_lib_stubs_current.from-text":      moduleLibDroidstubs,
  "android_module_lib_stubs_current_full.from-text": moduleLibDroidstubs,
  "android_system_server_stubs_current.from-text":   systemServerDroidstubs,
  "core.current.stubs.from-text":                    publicDroidstubs,
  "legacy.core.platform.api.stubs.from-text":        publicDroidstubs,
  "stable.core.platform.api.stubs.from-text":        publicDroidstubs,
  "core-lambda-stubs.from-text":                     publicDroidstubs,
  "android-non-updatable.stubs.test_module_lib":     moduleLibDroidstubs,
 }

 for _, droidstubs := range droidstubsStructs {
  bp += fmt.Sprintf(`
   droidstubs {
    name: "%s",
    api_surface: "%s",
    check_api: {
     current: {
      api_file: "%s",
      removed_api_file: "%s",
     }
    }
   }
  `,
   droidstubs.name,
   droidstubs.apiSurface,
   droidstubs.apiFile,
   droidstubs.removedFile,
  )
 }

 for libName, droidstubs := range extraApiLibraryModules {
  bp += fmt.Sprintf(`
  java_api_library {
   name: "%s",
   api_contributions: ["%s"],
   stubs_type: "everything",
   sdk_version: "none",
   system_modules: "none",
  }
        `, libName, droidstubs.name+".api.contribution")
 }

 bp += `
  java_library {
   name: "framework",
   srcs: ["a.java"],
   sdk_version: "none",
   system_modules: "stable-core-platform-api-stubs-system-modules",
   aidl: {
    export_include_dirs: ["framework/aidl"],
   },
   compile_dex: true,
   optimize: {
    force_disabled_with_source_stubs: true,
   },
  }
  java_library {
   name: "framework-minus-apex",
   srcs: ["a.java"],
   sdk_version: "none",
   system_modules: "stable-core-platform-api-stubs-system-modules",
   aidl: {
    export_include_dirs: ["framework/aidl"],
   },
   compile_dex: true,
   optimize: {
    force_disabled_with_source_stubs: true,
   },
  }

  android_app {
   name: "framework-res",
   sdk_version: "core_platform",
  }

  filegroup {
   name: "framework-private-proguard",
   srcs: ["framework-private.flags"],
  }
  `

 systemModules := []string{
  "core-public-stubs-system-modules",
  "core-module-lib-stubs-system-modules",
  "legacy-core-platform-api-stubs-system-modules",
  "stable-core-platform-api-stubs-system-modules",
  "core-public-stubs-system-modules.from-text",
  "core-module-lib-stubs-system-modules.from-text",
  "legacy-core-platform-api-stubs-system-modules.from-text",
  "stable-core-platform-api-stubs-system-modules.from-text",
 }

 for _, extra := range systemModules {
  bp += fmt.Sprintf(`
   java_system_modules {
    name: "%[1]s",
    libs: ["%[1]s-lib"],
   }
   java_library {
    name: "%[1]s-lib",
    sdk_version: "none",
    system_modules: "none",
    srcs: ["a.java"],
   }
  `, extra)
 }

 // Make sure that the dex_bootjars singleton module is instantiated for the tests.
 bp += `
  dex_bootjars {
   name: "dex_bootjars",
  }
`

 bp += `
  all_apex_contributions {
   name: "all_apex_contributions",
  }
`
 return bp
}

func getModuleDependencies(t *testing.T, ctx *android.TestContext, name, variant string) []string {
 t.Helper()
 module := ctx.ModuleForTests(t, name, variant).Module()
 deps := []string{}
 ctx.VisitDirectDepsProxiesWithTags(module, func(m blueprint.ModuleProxy, tag blueprint.DependencyTag) {
  if _, ok := tag.(android.HostToolDepTagType); ok {
   // ignore host tools
   return
  }
  deps = append(deps, m.Name())
 })
 return android.SortedUniqueStrings(deps)
}

// CheckModuleDependencies checks if the expected dependencies of the module are
// identical to the actual dependencies.
func CheckModuleDependencies(t *testing.T, ctx *android.TestContext, name, variant string, expected []string) {
 t.Helper()
 deps := getModuleDependencies(t, ctx, name, variant)

 if actual := deps; !reflect.DeepEqual(expected, actual) {
  t.Errorf("expected %#q, found %#q", expected, actual)
 }
}

// CheckModuleHasDependency returns true if the module depends on the expected dependency.
func CheckModuleHasDependency(t *testing.T, ctx *android.TestContext, name, variant string, expected string) bool {
 for _, dep := range getModuleDependencies(t, ctx, name, variant) {
  if dep == expected {
   return true
  }
 }
 return false
}

// CheckModuleHasDependency returns true if the module depends on the expected dependency.
func CheckModuleHasDependencyWithTag(t *testing.T, ctx *android.TestContext, name, variant string, desiredTag blueprint.DependencyTag, expected string) bool {
 module := ctx.ModuleForTests(t, name, variant).Module()
 found := false
 ctx.VisitDirectDepsProxiesWithTags(module, func(m blueprint.ModuleProxy, tag blueprint.DependencyTag) {
  if tag == desiredTag && m.Name() == expected {
   found = true
  }
 })
 return found
}

// CheckPlatformBootclasspathModules returns the apex:module pair for the modules depended upon by
// the platform-bootclasspath module.
func CheckPlatformBootclasspathModules(t *testing.T, result *android.TestResult, name string, expected []string) {
 t.Helper()
 platformBootclasspath := result.Module(name, "android_common").(*platformBootclasspathModule)
 pairs := apexNamePairsFromModules(result.TestContext, platformBootclasspath.configuredModules, platformBootclasspath.libraryToApex)
 android.AssertDeepEquals(t, fmt.Sprintf("%s modules", "platform-bootclasspath"), expected, pairs)
}

func CheckClasspathFragmentProtoContentInfoProvider(t *testing.T, result *android.TestResult, generated bool, contents, outputFilename, installDir string) {
 t.Helper()
 p := result.Module("platform-bootclasspath", "android_common").(*platformBootclasspathModule)
 info, _ := android.OtherModuleProvider(result, p, ClasspathFragmentProtoContentInfoProvider)

 android.AssertBoolEquals(t, "classpath proto generated", generated, info.ClasspathFragmentProtoGenerated)
 android.AssertStringEquals(t, "classpath proto contents", contents, info.ClasspathFragmentProtoContents.String())
 android.AssertStringEquals(t, "output filepath", outputFilename, info.ClasspathFragmentProtoOutput.Base())
 android.AssertPathRelativeToTopEquals(t, "install filepath", installDir, info.ClasspathFragmentProtoInstallDir)
}

// CheckPlatformBootclasspathDependencies checks the dependencies of the selected module against the expected list.
//
// The expected list must be a list of strings of the form "<apex>:<module>", where <apex> is the
// name of the apex, or platform is it is not part of an apex and <module> is the module name.
func CheckPlatformBootclasspathDependencies(t *testing.T, ctx *android.TestContext, name, variant string, expected []string) {
 t.Helper()
 platformBootclasspath := ctx.ModuleForTests(t, name, variant).Module().(*platformBootclasspathModule)
 modules := []android.ModuleProxy{}
 ctx.VisitDirectDepsProxies(platformBootclasspath, func(m android.ModuleProxy) {
  modules = append(modules, m)
 })

 pairs := apexNamePairsFromModules(ctx, modules, platformBootclasspath.libraryToApex)
 android.AssertDeepEquals(t, "module dependencies", expected, pairs)
}

// apexNamePairsFromModules returns the apex:module pair for the supplied modules.
func apexNamePairsFromModules(ctx *android.TestContext, modules []android.ModuleProxy, modulesToApex map[android.ModuleProxy]string) []string {
 pairs := []string{}
 for _, module := range modules {
  pairs = append(pairs, apexNamePairFromModule(ctx, module, modulesToApex))
 }
 return pairs
}

// ApexFragmentPairsFromModules returns the apex:fragment pair for the supplied fragments.
func ApexFragmentPairsFromModules(ctx *android.TestContext, fragments []android.ModuleProxy, apexNameToFragment map[string]android.ModuleProxy) []string {
 pairs := []string{}
 for _, fragment := range fragments {
  found := false
  for apex, apexFragment := range apexNameToFragment {
   if apexFragment == fragment {
    pairs = append(pairs, apex+":"+ctx.ModuleName(fragment))
    found = true
   }
  }
  if !found {
   pairs = append(pairs, "platform:"+ctx.ModuleName(fragment))
  }
 }
 return pairs
}

func apexNamePairFromModule(ctx *android.TestContext, module android.ModuleProxy, modulesToApex map[android.ModuleProxy]string) string {
 name := module.Name()
 apex := modulesToApex[module]
 if apex == "" {
  apex = "platform"
 }

 return fmt.Sprintf("%s:%s", apex, name)
}

// CheckPlatformBootclasspathFragments returns the apex:module pair for the fragments depended upon
// by the platform-bootclasspath module.
func CheckPlatformBootclasspathFragments(t *testing.T, result *android.TestResult, name string, expected []string) {
 t.Helper()
 platformBootclasspath := result.Module(name, "android_common").(*platformBootclasspathModule)
 pairs := ApexFragmentPairsFromModules(result.TestContext, platformBootclasspath.fragments, platformBootclasspath.apexNameToFragment)
 android.AssertDeepEquals(t, fmt.Sprintf("%s fragments", "platform-bootclasspath"), expected, pairs)
}

func CheckHiddenAPIRuleInputs(t *testing.T, message string, expected string, hiddenAPIRule android.TestingBuildParams) {
 t.Helper()
 inputs := android.Paths{}
 if hiddenAPIRule.Input != nil {
  inputs = append(inputs, hiddenAPIRule.Input)
 }
 inputs = append(inputs, hiddenAPIRule.Inputs...)
 inputs = append(inputs, hiddenAPIRule.Implicits...)
 inputs = android.SortedUniquePaths(inputs)
 actual := strings.TrimSpace(strings.Join(inputs.RelativeToTop().Strings(), "\n"))
 re := regexp.MustCompile(`\n\s+`)
 expected = strings.TrimSpace(re.ReplaceAllString(expected, "\n"))
 if actual != expected {
  t.Errorf("Expected hiddenapi rule inputs - %s:\n%s\nactual inputs:\n%s", message, expected, actual)
 }
}

// Check that the merged file create by platform_compat_config_singleton has the correct inputs.
func CheckMergedCompatConfigInputs(t *testing.T, result *android.TestResult, message string, expectedPaths ...string) {
 sourceGlobalCompatConfig := result.SingletonForTests(t, "platform_compat_config_singleton")
 allOutputs := sourceGlobalCompatConfig.AllOutputs()
 android.AssertIntEquals(t, message+": output len", 1, len(allOutputs))
 output := sourceGlobalCompatConfig.Output(allOutputs[0])
 android.AssertPathsRelativeToTopEquals(t, message+": inputs", expectedPaths, output.Implicits)
}

// Register the fake APEX mutator to `android.InitRegistrationContext` as if the real mutator exists
// at runtime. This must be called in `init()` of a test if the test is going to use the fake APEX
// mutator. Otherwise, we will be missing the runtime mutator because "soong-apex" is not a
// dependency, which will cause an inconsistency between testing and runtime mutators.
func RegisterFakeRuntimeApexMutator() {
 registerFakeApexMutator(android.InitRegistrationContext)
}

var PrepareForTestWithFakeApexMutator = android.GroupFixturePreparers(
 android.FixtureRegisterWithContext(registerFakeApexMutator),
)

func registerFakeApexMutator(ctx android.RegistrationContext) {
 ctx.PostDepsMutators(func(ctx android.RegisterMutatorsContext) {
  ctx.Transition("apex", &fakeApexMutator{})
 })
}

type apexModuleBase interface {
 ApexAvailable() []string
}

var _ apexModuleBase = (*Library)(nil)
var _ apexModuleBase = (*SdkLibrary)(nil)

// A fake APEX mutator that creates a platform variant and an APEX variant for modules with
// `apex_available`. It helps us avoid a dependency on the real mutator defined in "soong-apex",
// which will cause a cyclic dependency, and it provides an easy way to create an APEX variant for
// testing without dealing with all the complexities in the real mutator.
type fakeApexMutator struct{}

func (f *fakeApexMutator) Split(ctx android.BaseModuleContext) []string {
 switch ctx.Module().(type) {
 case *Library, *SdkLibrary:
  return []string{"", "apex1000"}
 }
 return []string{""}
}

func (f *fakeApexMutator) SplitOnDemand(ctx android.BaseModuleContext) []string {
 return nil
}

func (f *fakeApexMutator) OutgoingTransition(ctx android.OutgoingTransitionContext, sourceVariation string) string {
 return sourceVariation
}

func (f *fakeApexMutator) IncomingTransition(ctx android.IncomingTransitionContext, incomingVariation string) string {
 return incomingVariation
}

func (f *fakeApexMutator) Mutate(ctx android.BottomUpMutatorContext, variation string) {
 if variation != "" {
  apexInfo := android.ApexInfo{
   ApexVariationName: "apex1000",
  }
  android.SetProvider(ctx, android.ApexInfoProvider, apexInfo)
 }
}

// Applies the given modifier on the boot image config with the given name.
func FixtureModifyBootImageConfig(name string, configModifier func(*bootImageConfig)) android.FixturePreparer {
 return android.FixtureModifyConfig(func(androidConfig android.Config) {
  pathCtx := android.PathContextForTesting(androidConfig)
  config := genBootImageConfigRaw(pathCtx)
  configModifier(config[name])
 })
}

// Sets the value of `installDir` of the boot image config with the given name.
func FixtureSetBootImageInstallDirOnDevice(name string, installDir string) android.FixturePreparer {
 return FixtureModifyBootImageConfig(name, func(config *bootImageConfig) {
  config.installDir = installDir
 })
}

[Dauer der Verarbeitung: 0.25 Sekunden, vorverarbeitet 2026-06-28]