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 34 kB image not shown  

Quelle  app_import_test.go   Sprache: unbekannt

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

// 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 java

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

 "github.com/google/blueprint/proptools"

 "android/soong/android"
)

func TestAndroidAppImport(t *testing.T) {
 t.Parallel()
 ctx, _ := testJava(t, `
  android_app_import {
   name: "foo",
   apk: "prebuilts/apk/app.apk",
   certificate: "platform",
   dex_preopt: {
    enabled: true,
   },
  }
  `)

 variant := ctx.ModuleForTests(t, "foo", "android_common")

 // Check dexpreopt outputs.
 if variant.MaybeOutput("dexpreopt/foo/oat/arm64/package.vdex").Rule == nil ||
  variant.MaybeOutput("dexpreopt/foo/oat/arm64/package.odex").Rule == nil {
  t.Errorf("can't find dexpreopt outputs")
 }

 // Check cert signing flag.
 signedApk := variant.Output("signed/foo.apk")
 signingFlag := signedApk.Args["certificates"]
 expected := "build/make/target/product/security/platform.x509.pem build/make/target/product/security/platform.pk8"
 if expected != signingFlag {
  t.Errorf("Incorrect signing flags, expected: %q, got: %q", expected, signingFlag)
 }
 rule := variant.Rule("genProvenanceMetaData")
 android.AssertStringEquals(t, "Invalid input", "prebuilts/apk/app.apk", rule.Inputs[0].String())
 android.AssertStringEquals(t, "Invalid output", "out/soong/.intermediates/provenance_metadata/foo/provenance_metadata.textproto", rule.Output.String())
 android.AssertStringEquals(t, "Invalid args", "foo", rule.Args["module_name"])
 android.AssertStringEquals(t, "Invalid args", "/system/app/foo/foo.apk", rule.Args["install_path"])
}

func TestAndroidAppImportWithDefaults(t *testing.T) {
 t.Parallel()
 ctx, _ := testJava(t, `
  android_app_import {
   name: "foo",
   defaults: ["foo_defaults"],
  }

  java_defaults {
   name: "foo_defaults",
   apk: "prebuilts/apk/app.apk",
   certificate: "platform",
   dex_preopt: {
    enabled: true,
   },
  }
  `)

 variant := ctx.ModuleForTests(t, "foo", "android_common")

 // Check dexpreopt outputs.
 if variant.MaybeOutput("dexpreopt/foo/oat/arm64/package.vdex").Rule == nil ||
  variant.MaybeOutput("dexpreopt/foo/oat/arm64/package.odex").Rule == nil {
  t.Errorf("can't find dexpreopt outputs")
 }

 // Check cert signing flag.
 signedApk := variant.Output("signed/foo.apk")
 signingFlag := signedApk.Args["certificates"]
 expected := "build/make/target/product/security/platform.x509.pem build/make/target/product/security/platform.pk8"
 if expected != signingFlag {
  t.Errorf("Incorrect signing flags, expected: %q, got: %q", expected, signingFlag)
 }
 rule := variant.Rule("genProvenanceMetaData")
 android.AssertStringEquals(t, "Invalid input", "prebuilts/apk/app.apk", rule.Inputs[0].String())
 android.AssertStringEquals(t, "Invalid output", "out/soong/.intermediates/provenance_metadata/foo/provenance_metadata.textproto", rule.Output.String())
 android.AssertStringEquals(t, "Invalid args", "foo", rule.Args["module_name"])
 android.AssertStringEquals(t, "Invalid args", "/system/app/foo/foo.apk", rule.Args["install_path"])
}

func TestAndroidAppImport_NoDexPreopt(t *testing.T) {
 t.Parallel()
 ctx, _ := testJava(t, `
  android_app_import {
   name: "foo",
   apk: "prebuilts/apk/app.apk",
   certificate: "platform",
   dex_preopt: {
    enabled: false,
   },
  }
  `)

 variant := ctx.ModuleForTests(t, "foo", "android_common")

 // Check dexpreopt outputs. They shouldn't exist.
 if variant.MaybeOutput("dexpreopt/foo/oat/arm64/package.vdex").Rule != nil ||
  variant.MaybeOutput("dexpreopt/foo/oat/arm64/package.odex").Rule != nil {
  t.Errorf("dexpreopt shouldn't have run.")
 }

 rule := variant.Rule("genProvenanceMetaData")
 android.AssertStringEquals(t, "Invalid input", "prebuilts/apk/app.apk", rule.Inputs[0].String())
 android.AssertStringEquals(t, "Invalid output", "out/soong/.intermediates/provenance_metadata/foo/provenance_metadata.textproto", rule.Output.String())
 android.AssertStringEquals(t, "Invalid args", "foo", rule.Args["module_name"])
 android.AssertStringEquals(t, "Invalid args", "/system/app/foo/foo.apk", rule.Args["install_path"])
}

func TestAndroidAppImport_Presigned(t *testing.T) {
 t.Parallel()
 ctx, _ := testJava(t, `
  android_app_import {
   name: "foo",
   apk: "prebuilts/apk/app.apk",
   presigned: true,
   dex_preopt: {
    enabled: true,
   },
  }
  `)

 variant := ctx.ModuleForTests(t, "foo", "android_common")

 // Check dexpreopt outputs.
 if variant.MaybeOutput("dexpreopt/foo/oat/arm64/package.vdex").Rule == nil ||
  variant.MaybeOutput("dexpreopt/foo/oat/arm64/package.odex").Rule == nil {
  t.Errorf("can't find dexpreopt outputs")
 }
 // Make sure signing was skipped and aligning was done.
 if variant.MaybeOutput("signed/foo.apk").Rule != nil {
  t.Errorf("signing rule shouldn't be included.")
 }
 if variant.MaybeOutput("zip-aligned/foo.apk").Rule == nil {
  t.Errorf("can't find aligning rule")
 }

 rule := variant.Rule("genProvenanceMetaData")
 android.AssertStringEquals(t, "Invalid input", "prebuilts/apk/app.apk", rule.Inputs[0].String())
 android.AssertStringEquals(t, "Invalid output", "out/soong/.intermediates/provenance_metadata/foo/provenance_metadata.textproto", rule.Output.String())
 android.AssertStringEquals(t, "Invalid args", "foo", rule.Args["module_name"])
 android.AssertStringEquals(t, "Invalid args", "/system/app/foo/foo.apk", rule.Args["install_path"])
}

func TestAndroidAppImport_SigningLineage(t *testing.T) {
 t.Parallel()
 ctx, _ := testJava(t, `
   android_app_import {
   name: "foo",
   apk: "prebuilts/apk/app.apk",
   certificate: "platform",
   additional_certificates: [":additional_certificate"],
   lineage: "lineage.bin",
   rotationMinSdkVersion: "32",
  }

  android_app_certificate {
   name: "additional_certificate",
   certificate: "cert/additional_cert",
  }
 `)

 variant := ctx.ModuleForTests(t, "foo", "android_common")

 signedApk := variant.Output("signed/foo.apk")
 // Check certificates
 certificatesFlag := signedApk.Args["certificates"]
 expected := "build/make/target/product/security/platform.x509.pem " +
  "build/make/target/product/security/platform.pk8 " +
  "cert/additional_cert.x509.pem cert/additional_cert.pk8"
 if expected != certificatesFlag {
  t.Errorf("Incorrect certificates flags, expected: %q, got: %q", expected, certificatesFlag)
 }

 // Check cert signing flags.
 actualCertSigningFlags := signedApk.Args["flags"]
 expectedCertSigningFlags := "--lineage lineage.bin --rotation-min-sdk-version 32 --disable-v1"
 if expectedCertSigningFlags != actualCertSigningFlags {
  t.Errorf("Incorrect signing flags, expected: %q, got: %q", expectedCertSigningFlags, actualCertSigningFlags)
 }

 rule := variant.Rule("genProvenanceMetaData")
 android.AssertStringEquals(t, "Invalid input", "prebuilts/apk/app.apk", rule.Inputs[0].String())
 android.AssertStringEquals(t, "Invalid output", "out/soong/.intermediates/provenance_metadata/foo/provenance_metadata.textproto", rule.Output.String())
 android.AssertStringEquals(t, "Invalid args", "foo", rule.Args["module_name"])
 android.AssertStringEquals(t, "Invalid args", "/system/app/foo/foo.apk", rule.Args["install_path"])
}

func TestAndroidAppImport_SigningLineageFilegroup(t *testing.T) {
 t.Parallel()
 ctx, _ := testJava(t, `
   android_app_import {
   name: "foo",
   apk: "prebuilts/apk/app.apk",
   certificate: "platform",
   lineage: ":lineage_bin",
  }

  filegroup {
   name: "lineage_bin",
   srcs: ["lineage.bin"],
  }
 `)

 variant := ctx.ModuleForTests(t, "foo", "android_common")

 signedApk := variant.Output("signed/foo.apk")
 // Check cert signing lineage flag.
 signingFlag := signedApk.Args["flags"]
 expected := "--lineage lineage.bin --disable-v1"
 if expected != signingFlag {
  t.Errorf("Incorrect signing flags, expected: %q, got: %q", expected, signingFlag)
 }

 rule := variant.Rule("genProvenanceMetaData")
 android.AssertStringEquals(t, "Invalid input", "prebuilts/apk/app.apk", rule.Inputs[0].String())
 android.AssertStringEquals(t, "Invalid output", "out/soong/.intermediates/provenance_metadata/foo/provenance_metadata.textproto", rule.Output.String())
 android.AssertStringEquals(t, "Invalid args", "foo", rule.Args["module_name"])
 android.AssertStringEquals(t, "Invalid args", "/system/app/foo/foo.apk", rule.Args["install_path"])
}

func TestAndroidAppImport_DefaultDevCert(t *testing.T) {
 t.Parallel()
 ctx, _ := testJava(t, `
  android_app_import {
   name: "foo",
   apk: "prebuilts/apk/app.apk",
   default_dev_cert: true,
   dex_preopt: {
    enabled: true,
   },
  }
  `)

 variant := ctx.ModuleForTests(t, "foo", "android_common")

 // Check dexpreopt outputs.
 if variant.MaybeOutput("dexpreopt/foo/oat/arm64/package.vdex").Rule == nil ||
  variant.MaybeOutput("dexpreopt/foo/oat/arm64/package.odex").Rule == nil {
  t.Errorf("can't find dexpreopt outputs")
 }

 // Check cert signing flag.
 signedApk := variant.Output("signed/foo.apk")
 signingFlag := signedApk.Args["certificates"]
 expected := "build/make/target/product/security/testkey.x509.pem build/make/target/product/security/testkey.pk8"
 if expected != signingFlag {
  t.Errorf("Incorrect signing flags, expected: %q, got: %q", expected, signingFlag)
 }

 rule := variant.Rule("genProvenanceMetaData")
 android.AssertStringEquals(t, "Invalid input", "prebuilts/apk/app.apk", rule.Inputs[0].String())
 android.AssertStringEquals(t, "Invalid output", "out/soong/.intermediates/provenance_metadata/foo/provenance_metadata.textproto", rule.Output.String())
 android.AssertStringEquals(t, "Invalid args", "foo", rule.Args["module_name"])
 android.AssertStringEquals(t, "Invalid args", "/system/app/foo/foo.apk", rule.Args["install_path"])
}

func TestAndroidAppImport_DpiVariants(t *testing.T) {
 t.Parallel()
 bp := `
  android_app_import {
   name: "foo",
   apk: "prebuilts/apk/app.apk",
   dpi_variants: {
    xhdpi: {
     apk: "prebuilts/apk/app_xhdpi.apk",
    },
    xxhdpi: {
     apk: "prebuilts/apk/app_xxhdpi.apk",
    },
   },
   presigned: true,
   dex_preopt: {
    enabled: true,
   },
  }
  `
 testCases := []struct {
  name                                   string
  aaptPreferredConfig                    *string
  aaptPrebuiltDPI                        []string
  expected                               string
  expectedProvenanceMetaDataArtifactPath string
 }{
  {
   name:                                   "no preferred",
   aaptPreferredConfig:                    nil,
   aaptPrebuiltDPI:                        []string{},
   expected:                               "verify_uses_libraries/apk/app.apk",
   expectedProvenanceMetaDataArtifactPath: "prebuilts/apk/app.apk",
  },
  {
   name:                                   "AAPTPreferredConfig matches",
   aaptPreferredConfig:                    proptools.StringPtr("xhdpi"),
   aaptPrebuiltDPI:                        []string{"xxhdpi", "ldpi"},
   expected:                               "verify_uses_libraries/apk/app_xhdpi.apk",
   expectedProvenanceMetaDataArtifactPath: "prebuilts/apk/app_xhdpi.apk",
  },
  {
   name:                                   "AAPTPrebuiltDPI matches",
   aaptPreferredConfig:                    proptools.StringPtr("mdpi"),
   aaptPrebuiltDPI:                        []string{"xxhdpi", "xhdpi"},
   expected:                               "verify_uses_libraries/apk/app_xxhdpi.apk",
   expectedProvenanceMetaDataArtifactPath: "prebuilts/apk/app_xxhdpi.apk",
  },
  {
   name:                                   "non-first AAPTPrebuiltDPI matches",
   aaptPreferredConfig:                    proptools.StringPtr("mdpi"),
   aaptPrebuiltDPI:                        []string{"ldpi", "xhdpi"},
   expected:                               "verify_uses_libraries/apk/app_xhdpi.apk",
   expectedProvenanceMetaDataArtifactPath: "prebuilts/apk/app_xhdpi.apk",
  },
  {
   name:                                   "no matches",
   aaptPreferredConfig:                    proptools.StringPtr("mdpi"),
   aaptPrebuiltDPI:                        []string{"ldpi", "xxxhdpi"},
   expected:                               "verify_uses_libraries/apk/app.apk",
   expectedProvenanceMetaDataArtifactPath: "prebuilts/apk/app.apk",
  },
 }

 for _, test := range testCases {
  result := android.GroupFixturePreparers(
   PrepareForTestWithJavaDefaultModules,
   android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
    variables.AAPTPreferredConfig = test.aaptPreferredConfig
    variables.AAPTPrebuiltDPI = test.aaptPrebuiltDPI
   }),
  ).RunTestWithBp(t, bp)

  variant := result.ModuleForTests(t, "foo", "android_common")
  input := variant.Output("jnis-uncompressed/foo.apk").Input.String()
  if strings.HasSuffix(input, test.expected) {
   t.Errorf("wrong src apk, expected: %q got: %q", test.expected, input)
  }

  provenanceMetaDataRule := variant.Rule("genProvenanceMetaData")
  android.AssertStringEquals(t, "Invalid input", test.expectedProvenanceMetaDataArtifactPath, provenanceMetaDataRule.Inputs[0].String())
  android.AssertStringEquals(t, "Invalid output", "out/soong/.intermediates/provenance_metadata/foo/provenance_metadata.textproto", provenanceMetaDataRule.Output.String())
  android.AssertStringEquals(t, "Invalid args", "foo", provenanceMetaDataRule.Args["module_name"])
  android.AssertStringEquals(t, "Invalid args", "/system/app/foo/foo.apk", provenanceMetaDataRule.Args["install_path"])
 }
}

func TestAndroidAppImport_Filename(t *testing.T) {
 t.Parallel()
 bp := `
  android_app_import {
   name: "foo",
   apk: "prebuilts/apk/app.apk",
   presigned: true,
  }

  android_app_import {
   name: "foo_compressed",
   apk: "prebuilts/apk/app.apk",
   presigned: true,
   compress_apk: true,
  }

  android_app_import {
   name: "bar",
   apk: "prebuilts/apk/app.apk",
   presigned: true,
   filename: "bar_sample.apk",
  }

  android_app_import {
   name: "compressed_bar",
   apk: "prebuilts/apk/app.apk",
   presigned: true,
   filename: "bar_sample.apk",
   compress_apk: true,
  }
  `

 testCases := []struct {
  name                 string
  expected             string
  onDevice             string
  expectedArtifactPath string
  expectedMetaDataPath string
 }{
  {
   name:                 "foo",
   expected:             "foo.apk",
   onDevice:             "/system/app/foo/foo.apk",
   expectedArtifactPath: "prebuilts/apk/app.apk",
   expectedMetaDataPath: "out/soong/.intermediates/provenance_metadata/foo/provenance_metadata.textproto",
  },
  {
   name:                 "foo_compressed",
   expected:             "foo_compressed.apk.gz",
   onDevice:             "/system/app/foo_compressed/foo_compressed.apk.gz",
   expectedArtifactPath: "prebuilts/apk/app.apk",
   expectedMetaDataPath: "out/soong/.intermediates/provenance_metadata/foo_compressed/provenance_metadata.textproto",
  },
  {
   name:                 "bar",
   expected:             "bar_sample.apk",
   onDevice:             "/system/app/bar/bar_sample.apk",
   expectedArtifactPath: "prebuilts/apk/app.apk",
   expectedMetaDataPath: "out/soong/.intermediates/provenance_metadata/bar/provenance_metadata.textproto",
  },
  {
   name:                 "compressed_bar",
   expected:             "bar_sample.apk",
   onDevice:             "/system/app/compressed_bar/bar_sample.apk",
   expectedArtifactPath: "prebuilts/apk/app.apk",
   expectedMetaDataPath: "out/soong/.intermediates/provenance_metadata/compressed_bar/provenance_metadata.textproto",
  },
 }

 t.Run("soong_only", func(t *testing.T) {
  ctx := prepareForJavaTest.RunTestWithBp(t, bp)
  for _, test := range testCases {
   variant := ctx.ModuleForTests(t, test.name, "android_common")
   if variant.MaybeOutput(test.expected).Rule == nil {
    t.Errorf("can't find output named %q - all outputs: %v", test.expected, variant.AllOutputs())
   }

   rule := variant.Rule("genProvenanceMetaData")
   android.AssertStringEquals(t, "Invalid input", test.expectedArtifactPath, rule.Inputs[0].String())
   android.AssertStringEquals(t, "Invalid output", test.expectedMetaDataPath, rule.Output.String())
   android.AssertStringEquals(t, "Invalid args", test.name, rule.Args["module_name"])
   android.AssertStringEquals(t, "Invalid args", test.onDevice, rule.Args["install_path"])
  }
 })
 t.Run("androidmk", func(t *testing.T) {
  ctx := prepareForJavaAndroidMkTest.RunTestWithBp(t, bp)
  for _, test := range testCases {
   variant := ctx.ModuleForTests(t, test.name, "android_common")
   expectedValues := []string{test.expected}
   info := android.AndroidMkInfoForTest(t, ctx.TestContext, variant.Module())
   actualValues := info.PrimaryInfo.EntryMap["LOCAL_INSTALLED_MODULE_STEM"]
   if !reflect.DeepEqual(actualValues, expectedValues) {
    t.Errorf("Incorrect LOCAL_INSTALLED_MODULE_STEM value '%s', expected '%s'",
     actualValues, expectedValues)
   }
   android.AssertStringEquals(t, "unexpected LOCAL_SOONG_MODULE_TYPE", "android_app_import",
    info.PrimaryInfo.EntryMap["LOCAL_SOONG_MODULE_TYPE"][0])
  }
 })

}

func TestAndroidAppImport_ArchVariants(t *testing.T) {
 t.Parallel()
 // The test config's target arch is ARM64.
 testCases := []struct {
  name         string
  bp           string
  expected     string
  artifactPath string
  metaDataPath string
  installPath  string
 }{
  {
   name: "matching arch",
   bp: `
    android_app_import {
     name: "foo",
     apk: "prebuilts/apk/app.apk",
     arch: {
      arm64: {
       apk: "prebuilts/apk/app_arm64.apk",
      },
     },
     presigned: true,
     dex_preopt: {
      enabled: true,
     },
    }
   `,
   expected:     "verify_uses_libraries/apk/app_arm64.apk",
   artifactPath: "prebuilts/apk/app_arm64.apk",
   installPath:  "/system/app/foo/foo.apk",
  },
  {
   name: "matching arch without default",
   bp: `
    android_app_import {
     name: "foo",
     apk: "prebuilts/apk/app.apk",
     arch: {
      arm64: {
       apk: "prebuilts/apk/app_arm64.apk",
      },
     },
     presigned: true,
     dex_preopt: {
      enabled: true,
     },
    }
   `,
   expected:     "verify_uses_libraries/apk/app_arm64.apk",
   artifactPath: "prebuilts/apk/app_arm64.apk",
   installPath:  "/system/app/foo/foo.apk",
  },
  {
   name: "no matching arch",
   bp: `
    android_app_import {
     name: "foo",
     apk: "prebuilts/apk/app.apk",
     arch: {
      arm: {
       apk: "prebuilts/apk/app_arm.apk",
      },
     },
     presigned: true,
     dex_preopt: {
      enabled: true,
     },
    }
   `,
   expected:     "verify_uses_libraries/apk/app.apk",
   artifactPath: "prebuilts/apk/app.apk",
   installPath:  "/system/app/foo/foo.apk",
  },
  {
   name: "no matching arch without default",
   bp: `
    android_app_import {
     name: "foo",
     arch: {
      arm: {
       apk: "prebuilts/apk/app_arm.apk",
      },
     },
     presigned: true,
     dex_preopt: {
      enabled: true,
     },
    }
   `,
   expected:     "",
   artifactPath: "prebuilts/apk/app_arm.apk",
   installPath:  "/system/app/foo/foo.apk",
  },
  {
   name: "matching arch and dpi_variants",
   bp: `
    android_app_import {
     name: "foo",
     apk: "prebuilts/apk/app.apk",
     arch: {
      arm64: {
       apk: "prebuilts/apk/app_arm64.apk",
       dpi_variants: {
        mdpi: {
         apk: "prebuilts/apk/app_arm64_mdpi.apk",
        },
        xhdpi: {
         apk: "prebuilts/apk/app_arm64_xhdpi.apk",
        },
       },
      },
     },
     presigned: true,
     dex_preopt: {
      enabled: true,
     },
    }
   `,
   expected:     "verify_uses_libraries/apk/app_arm64_xhdpi.apk",
   artifactPath: "prebuilts/apk/app_arm64_xhdpi.apk",
   installPath:  "/system/app/foo/foo.apk",
  },
 }

 for _, test := range testCases {
  t.Run(test.name, func(t *testing.T) {
   t.Parallel()
   ctx, _ := testJava(t, test.bp)

   variant := ctx.ModuleForTests(t, "foo", "android_common")
   if test.expected == "" {
    if variant.Module().Enabled(android.PanickingConfigAndErrorContext(ctx)) {
     t.Error("module should have been disabled, but wasn't")
    }
    rule := variant.MaybeRule("genProvenanceMetaData")
    android.AssertDeepEquals(t, "Provenance metadata is not empty", android.TestingBuildParams{}, rule)
    return
   }
   input := variant.Output("jnis-uncompressed/foo.apk").Input.String()
   if strings.HasSuffix(input, test.expected) {
    t.Errorf("wrong src apk, expected: %q got: %q", test.expected, input)
   }
   rule := variant.Rule("genProvenanceMetaData")
   android.AssertStringEquals(t, "Invalid input", test.artifactPath, rule.Inputs[0].String())
   android.AssertStringEquals(t, "Invalid output", "out/soong/.intermediates/provenance_metadata/foo/provenance_metadata.textproto", rule.Output.String())
   android.AssertStringEquals(t, "Invalid args", "foo", rule.Args["module_name"])
   android.AssertStringEquals(t, "Invalid args", test.installPath, rule.Args["install_path"])
  })
 }
}

func TestAndroidAppImport_SoongConfigVariables(t *testing.T) {
 t.Parallel()
 testCases := []struct {
  name         string
  bp           string
  expected     string
  artifactPath string
  metaDataPath string
  installPath  string
 }{
  {
   name: "matching arch",
   bp: `
    soong_config_module_type {
     name: "my_android_app_import",
     module_type: "android_app_import",
     config_namespace: "my_namespace",
     value_variables: ["my_apk_var"],
     properties: ["apk"],
    }
    soong_config_value_variable {
     name: "my_apk_var",
    }
    my_android_app_import {
     name: "foo",
     soong_config_variables: {
      my_apk_var: {
       apk: "prebuilts/apk/%s.apk",
      },
     },
     presigned: true,
     dex_preopt: {
      enabled: true,
     },
    }
   `,
   expected:     "verify_uses_libraries/apk/name_from_soong_config.apk",
   artifactPath: "prebuilts/apk/name_from_soong_config.apk",
   installPath:  "/system/app/foo/foo.apk",
  },
 }

 for _, test := range testCases {
  t.Run(test.name, func(t *testing.T) {
   t.Parallel()
   ctx := android.GroupFixturePreparers(
    prepareForJavaTest,
    android.PrepareForTestWithSoongConfigModuleBuildComponents,
    android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
     variables.VendorVars = map[string]map[string]string{
      "my_namespace": {
       "my_apk_var": "name_from_soong_config",
      },
     }
    }),
   ).RunTestWithBp(t, test.bp).TestContext

   variant := ctx.ModuleForTests(t, "foo", "android_common")
   if test.expected == "" {
    if variant.Module().Enabled(android.PanickingConfigAndErrorContext(ctx)) {
     t.Error("module should have been disabled, but wasn't")
    }
    rule := variant.MaybeRule("genProvenanceMetaData")
    android.AssertDeepEquals(t, "Provenance metadata is not empty", android.TestingBuildParams{}, rule)
    return
   }
   input := variant.Output("jnis-uncompressed/foo.apk").Input.String()
   if strings.HasSuffix(input, test.expected) {
    t.Errorf("wrong src apk, expected: %q got: %q", test.expected, input)
   }
   rule := variant.Rule("genProvenanceMetaData")
   android.AssertStringEquals(t, "Invalid input", test.artifactPath, rule.Inputs[0].String())
   android.AssertStringEquals(t, "Invalid output", "out/soong/.intermediates/provenance_metadata/foo/provenance_metadata.textproto", rule.Output.String())
   android.AssertStringEquals(t, "Invalid args", "foo", rule.Args["module_name"])
   android.AssertStringEquals(t, "Invalid args", test.installPath, rule.Args["install_path"])
  })
 }
}

func TestAndroidAppImport_overridesDisabledAndroidApp(t *testing.T) {
 t.Parallel()
 ctx, _ := testJava(t, `
  android_app {
   name: "foo",
   srcs: ["a.java"],
   enabled: false,
  }

   android_app_import {
   name: "foo",
   apk: "prebuilts/apk/app.apk",
   certificate: "platform",
   prefer: true,
  }
  `)

 variant := ctx.ModuleForTests(t, "prebuilt_foo", "android_common")
 a := variant.Module().(*AndroidAppImport)
 // The prebuilt module should still be enabled and active even if the source-based counterpart
 // is disabled.
 if !a.prebuilt.UsePrebuilt() {
  t.Errorf("prebuilt foo module is not active")
 }
 if !a.Enabled(android.PanickingConfigAndErrorContext(ctx)) {
  t.Errorf("prebuilt foo module is disabled")
 }
}

func TestAndroidAppImport_relativeInstallPath(t *testing.T) {
 t.Parallel()
 bp := `
  android_app_import {
   name: "no_relative_install_path",
   apk: "prebuilts/apk/app.apk",
   presigned: true,
  }

  android_app_import {
   name: "relative_install_path",
   apk: "prebuilts/apk/app.apk",
   presigned: true,
   relative_install_path: "my/path",
  }

  android_app_import {
   name: "privileged_relative_install_path",
   apk: "prebuilts/apk/app.apk",
   presigned: true,
   privileged: true,
   relative_install_path: "my/path"
  }
  `
 testCases := []struct {
  name                string
  expectedInstallPath string
  errorMessage        string
 }{
  {
   name:                "no_relative_install_path",
   expectedInstallPath: "out/target/product/test_device/system/app/no_relative_install_path/no_relative_install_path.apk",
   errorMessage:        "Install path is not correct when relative_install_path is missing",
  },
  {
   name:                "relative_install_path",
   expectedInstallPath: "out/target/product/test_device/system/app/my/path/relative_install_path/relative_install_path.apk",
   errorMessage:        "Install path is not correct for app when relative_install_path is present",
  },
  {
   name:                "privileged_relative_install_path",
   expectedInstallPath: "out/target/product/test_device/system/priv-app/my/path/privileged_relative_install_path/privileged_relative_install_path.apk",
   errorMessage:        "Install path is not correct for privileged app when relative_install_path is present",
  },
 }
 for _, testCase := range testCases {
  t.Run(testCase.name, func(t *testing.T) {
   t.Parallel()
   ctx, _ := testJava(t, bp)
   mod := ctx.ModuleForTests(t, testCase.name, "android_common").Module().(*AndroidAppImport)
   android.AssertPathRelativeToTopEquals(t, testCase.errorMessage, testCase.expectedInstallPath, mod.installPath)
  })
 }
}

func TestAndroidAppImport_ExtractApk(t *testing.T) {
 t.Parallel()
 ctx, _ := testJava(t, `
  android_app_import {
   name: "foo",
   apk: "prebuilts/apk/app.apk",
   certificate: "platform",
   extract_apk: "extract_path/sub_app.apk"
  }
  `)

 variant := ctx.ModuleForTests(t, "foo", "android_common")
 extractRuleArgs := variant.Output("extract-apk/foo.apk").BuildParams.Args
 if extractRuleArgs["extract_apk"] != "extract_path/sub_app.apk" {
  t.Errorf("Unexpected extract apk args: %s", extractRuleArgs["extract_apk"])
 }
}
func TestAndroidTestImport(t *testing.T) {
 t.Parallel()
 ctx := prepareForJavaAndroidMkTest.RunTestWithBp(t, `
  android_test_import {
   name: "foo",
   apk: "prebuilts/apk/app.apk",
   presigned: true,
   data: [
    "testdata/data",
   ],
  }
  `)

 test := ctx.ModuleForTests(t, "foo", "android_common").Module().(*AndroidTestImport)

 // Check android mks.
 info := android.AndroidMkInfoForTest(t, ctx.TestContext, test)
 expected := []string{"tests"}
 actual := info.PrimaryInfo.EntryMap["LOCAL_MODULE_TAGS"]
 if !reflect.DeepEqual(expected, actual) {
  t.Errorf("Unexpected module tags - expected: %q, actual: %q", expected, actual)
 }
 expected = []string{"testdata/data:testdata/data"}
 actual = info.PrimaryInfo.EntryMap["LOCAL_COMPATIBILITY_SUPPORT_FILES"]
 if !reflect.DeepEqual(expected, actual) {
  t.Errorf("Unexpected test data - expected: %q, actual: %q", expected, actual)
 }
}

func TestAndroidTestImport_NoJinUncompressForPresigned(t *testing.T) {
 t.Parallel()
 ctx, _ := testJava(t, `
  android_test_import {
   name: "foo",
   apk: "prebuilts/apk/app.apk",
   certificate: "cert/new_cert",
   data: [
    "testdata/data",
   ],
  }

  android_test_import {
   name: "foo_presigned",
   apk: "prebuilts/apk/app.apk",
   presigned: true,
   data: [
    "testdata/data",
   ],
  }
  `)

 variant := ctx.ModuleForTests(t, "foo", "android_common")
 jniRule := variant.Output("jnis-uncompressed/foo.apk").BuildParams.Rule.String()
 if jniRule == android.CpRule.String() {
  t.Errorf("Unexpected JNI uncompress rule command: %s", jniRule)
 }

 variant = ctx.ModuleForTests(t, "foo_presigned", "android_common")
 jniRule = variant.Output("jnis-uncompressed/foo_presigned.apk").BuildParams.Rule.String()
 if jniRule != android.CpRule.String() {
  t.Errorf("Unexpected JNI uncompress rule: %s", jniRule)
 }
 if variant.MaybeOutput("zip-aligned/foo_presigned.apk").Rule == nil {
  t.Errorf("Presigned test apk should be aligned")
 }
}

func TestAndroidTestImport_Preprocessed(t *testing.T) {
 t.Parallel()
 ctx, _ := testJava(t, `
  android_test_import {
   name: "foo",
   apk: "prebuilts/apk/app.apk",
   presigned: true,
   preprocessed: true,
  }
  `)

 apkName := "foo.apk"
 variant := ctx.ModuleForTests(t, "foo", "android_common")
 jniRule := variant.Output("jnis-uncompressed/" + apkName).BuildParams.Rule.String()
 if jniRule != android.CpRule.String() {
  t.Errorf("Unexpected JNI uncompress rule: %s", jniRule)
 }

 // Make sure signing and aligning were skipped.
 if variant.MaybeOutput("signed/"+apkName).Rule != nil {
  t.Errorf("signing rule shouldn't be included for preprocessed.")
 }
 if variant.MaybeOutput("zip-aligned/"+apkName).Rule != nil {
  t.Errorf("aligning rule shouldn't be for preprocessed")
 }
}

func TestAndroidAppImport_Preprocessed(t *testing.T) {
 t.Parallel()
 for _, dontUncompressPrivAppDexs := range []bool{false, true} {
  name := fmt.Sprintf("dontUncompressPrivAppDexs:%t", dontUncompressPrivAppDexs)
  t.Run(name, func(t *testing.T) {
   t.Parallel()
   result := android.GroupFixturePreparers(
    PrepareForTestWithJavaDefaultModules,
    android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
     variables.UncompressPrivAppDex = proptools.BoolPtr(!dontUncompressPrivAppDexs)
    }),
   ).RunTestWithBp(t, `
    android_app_import {
     name: "foo",
     apk: "prebuilts/apk/app.apk",
     presigned: true,
     preprocessed: true,
    }

    android_app_import {
     name: "bar",
     apk: "prebuilts/apk/app.apk",
     presigned: true,
     privileged: true,
     preprocessed: true,
    }
   `)

   // non-privileged app
   apkName := "foo.apk"
   variant := result.ModuleForTests(t, "foo", "android_common")
   outputBuildParams := variant.Output(apkName).BuildParams
   if outputBuildParams.Rule.String() != android.CpRule.String() {
    t.Errorf("Unexpected prebuilt android_app_import rule: %s", outputBuildParams.Rule.String())
   }

   // Make sure compression and aligning were validated.
   if outputBuildParams.Validation == nil {
    t.Errorf("Expected validation rule, but was not found")
   }

   validationBuildParams := variant.Output("validated-prebuilt/check.stamp").BuildParams
   if validationBuildParams.Rule.String() != checkPresignedApkRule.String() {
    t.Errorf("Unexpected validation rule: %s", validationBuildParams.Rule.String())
   }

   expectedScriptArgs := "--preprocessed"
   actualScriptArgs := validationBuildParams.Args["extraArgs"]
   android.AssertStringEquals(t, "check script extraArgs", expectedScriptArgs, actualScriptArgs)

   // privileged app
   apkName = "bar.apk"
   variant = result.ModuleForTests(t, "bar", "android_common")
   outputBuildParams = variant.Output(apkName).BuildParams
   if outputBuildParams.Rule.String() != android.CpRule.String() {
    t.Errorf("Unexpected prebuilt android_app_import rule: %s", outputBuildParams.Rule.String())
   }

   // Make sure compression and aligning were validated.
   if outputBuildParams.Validation == nil {
    t.Errorf("Expected validation rule, but was not found")
   }

   validationBuildParams = variant.Output("validated-prebuilt/check.stamp").BuildParams
   if validationBuildParams.Rule.String() != checkPresignedApkRule.String() {
    t.Errorf("Unexpected validation rule: %s", validationBuildParams.Rule.String())
   }

   expectedScriptArgs = "--privileged"
   if !dontUncompressPrivAppDexs {
    expectedScriptArgs += " --uncompress-priv-app-dex"
   }
   expectedScriptArgs += " --preprocessed"
   actualScriptArgs = validationBuildParams.Args["extraArgs"]
   android.AssertStringEquals(t, "check script extraArgs", expectedScriptArgs, actualScriptArgs)
  })
 }
}

func TestAndroidTestImport_UncompressDex(t *testing.T) {
 t.Parallel()
 testCases := []struct {
  name string
  bp   string
 }{
  {
   name: "normal",
   bp: `
    android_app_import {
     name: "foo",
     presigned: true,
     apk: "prebuilts/apk/app.apk",
    }
   `,
  },
  {
   name: "privileged",
   bp: `
    android_app_import {
     name: "foo",
     presigned: true,
     privileged: true,
     apk: "prebuilts/apk/app.apk",
    }
   `,
  },
 }

 test := func(t *testing.T, bp string, unbundled bool, dontUncompressPrivAppDexs bool) {
  t.Helper()

  result := android.GroupFixturePreparers(
   prepareForJavaTest,
   android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
    if unbundled {
     variables.Unbundled_build = proptools.BoolPtr(true)
    }
    variables.UncompressPrivAppDex = proptools.BoolPtr(!dontUncompressPrivAppDexs)
   }),
  ).RunTestWithBp(t, bp)

  foo := result.ModuleForTests(t, "foo", "android_common")
  actual := foo.MaybeRule("uncompress-dex").Rule != nil

  expect := !unbundled
  if strings.Contains(bp, "privileged: true") {
   if dontUncompressPrivAppDexs {
    expect = false
   } else {
    // TODO(b/194504107): shouldn't priv-apps be always uncompressed unless
    // DONT_UNCOMPRESS_PRIV_APPS_DEXS is true (regardless of unbundling)?
    // expect = true
   }
  }

  android.AssertBoolEquals(t, "uncompress dex", expect, actual)
 }

 for _, unbundled := range []bool{false, true} {
  for _, dontUncompressPrivAppDexs := range []bool{false, true} {
   for _, tt := range testCases {
    name := fmt.Sprintf("%s,unbundled:%t,dontUncompressPrivAppDexs:%t",
     tt.name, unbundled, dontUncompressPrivAppDexs)
    t.Run(name, func(t *testing.T) {
     t.Parallel()
     test(t, tt.bp, unbundled, dontUncompressPrivAppDexs)
    })
   }
  }
 }
}

func TestAppImportMissingCertificateAllowMissingDependencies(t *testing.T) {
 t.Parallel()
 result := android.GroupFixturePreparers(
  PrepareForTestWithJavaDefaultModules,
  android.PrepareForTestWithAllowMissingDependencies,
  android.PrepareForTestWithAndroidMk,
 ).RunTestWithBp(t, `
  android_app_import {
   name: "foo",
   apk: "a.apk",
   certificate: ":missing_certificate",
  }`)

 foo := result.ModuleForTests(t, "foo", "android_common")
 fooApk := foo.Output("signed/foo.apk")
 if !android.IsErrorRule(fooApk.Rule) {
  t.Fatalf("expected ErrorRule for foo.apk, got %s", fooApk.Rule.String())
 }
 android.AssertStringDoesContain(t, "expected error rule message", fooApk.Args["error"], "missing dependencies: missing_certificate\n")
}

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