diff options
author | 2017-12-19 09:30:45 -0800 | |
---|---|---|
committer | 2017-12-19 09:32:20 -0800 | |
commit | 741dbc081e2479fd8b0b9c289802b8a0e4af7c06 (patch) | |
tree | 45430c4303439099540e77619f3c1b949e2416be /src/main/java/com/google/devtools/build | |
parent | 691bd158149602aeb6bbcc46fd4b22367d0157b4 (diff) |
Ensure that the target package in the <instrumentation> tag of the instrumentation android_binary's AndroidManifest.xml references the correct package name of the instrumented android_binary.
During an instrumentation test, ART will use the targetPackage specified in the instrumentation APK's AndroidManifest to determine the application to be instrumented. We can perform this check in Bazel at execution time, before the apps are loaded onto the device.
See android_instrumentation_test_integration_test.sh for the e2e example.
GITHUB: https://github.com/bazelbuild/bazel/issues/903
RELNOTES: None.
PiperOrigin-RevId: 179564246
Diffstat (limited to 'src/main/java/com/google/devtools/build')
3 files changed, 52 insertions, 7 deletions
diff --git a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidBinary.java b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidBinary.java index 3b1933cf3d..694c5d7dab 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidBinary.java +++ b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidBinary.java @@ -43,6 +43,7 @@ import com.google.devtools.build.lib.analysis.actions.CustomCommandLine.VectorAr import com.google.devtools.build.lib.analysis.actions.ParamFileInfo; import com.google.devtools.build.lib.analysis.actions.ParameterFileWriteAction; import com.google.devtools.build.lib.analysis.actions.SpawnAction; +import com.google.devtools.build.lib.analysis.actions.SpawnAction.Builder; import com.google.devtools.build.lib.analysis.actions.SpawnActionTemplate; import com.google.devtools.build.lib.analysis.configuredtargets.RuleConfiguredTarget.Mode; import com.google.devtools.build.lib.collect.nestedset.NestedSet; @@ -562,17 +563,46 @@ public abstract class AndroidBinary implements RuleConfiguredTargetFactory { // If this is an instrumentation APK, create the provider for android_instrumentation_test. if (isInstrumentation(ruleContext)) { - Artifact targetApk = - ruleContext - .getPrerequisite("instruments", Mode.TARGET) - .getProvider(ApkProvider.class) - .getApk(); + ApkProvider targetApkProvider = + ruleContext.getPrerequisite("instruments", Mode.TARGET, ApkProvider.class); + + Artifact targetApk = targetApkProvider.getApk(); Artifact instrumentationApk = zipAlignedApk; AndroidInstrumentationInfo instrumentationProvider = new AndroidInstrumentationInfo(targetApk, instrumentationApk); builder.addNativeDeclaredProvider(instrumentationProvider); + + // At this point, the Android manifests of both target and instrumentation APKs are finalized. + FilesToRunProvider checker = + ruleContext.getExecutablePrerequisite("$instrumentation_test_check", Mode.HOST); + Artifact targetManifest = targetApkProvider.getMergedManifest(); + Artifact instrumentationManifest = applicationManifest.getManifest(); + Artifact checkOutput = + ruleContext.getImplicitOutputArtifact( + AndroidRuleClasses.INSTRUMENTATION_TEST_CHECK_RESULTS); + + SpawnAction.Builder checkAction = + new Builder() + .setExecutable(checker) + .addInput(targetManifest) + .addInput(instrumentationManifest) + .addOutput(checkOutput) + .setProgressMessage( + "Validating the merged manifests of the target and instrumentation APKs") + .setMnemonic("AndroidManifestInstrumentationCheck"); + + CustomCommandLine commandLine = + CustomCommandLine.builder() + .addExecPath("--instrumentation_manifest", instrumentationManifest) + .addExecPath("--target_manifest", targetManifest) + .addExecPath("--output", checkOutput) + .build(); + + builder.addOutputGroup(OutputGroupInfo.HIDDEN_TOP_LEVEL, checkOutput); + checkAction.addCommandLine(commandLine); + ruleContext.registerAction(checkAction.build(ruleContext)); } androidCommon.addTransitiveInfoProviders( diff --git a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidInstrumentationTest.java b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidInstrumentationTest.java index 30e26d1803..cc3d44e9fc 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidInstrumentationTest.java +++ b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidInstrumentationTest.java @@ -56,8 +56,8 @@ public class AndroidInstrumentationTest implements RuleConfiguredTargetFactory { ruleContext.throwWithAttributeError( "instrumentation", String.format( - "The android_binary target at %s is missing an 'instruments' attribute. Please set " - + "it as the label of the android_binary under test.", + "The android_binary target %s is missing an 'instruments' attribute. Please set " + + "it to the label of the android_binary under test.", ruleContext.attributes().get("instrumentation", BuildType.LABEL))); } } diff --git a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidRuleClasses.java b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidRuleClasses.java index e13978ce6c..faa903ecb6 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidRuleClasses.java +++ b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidRuleClasses.java @@ -164,6 +164,8 @@ public final class AndroidRuleClasses { fromTemplates("%{name}_files/deploy_info_split.deployinfo.pb"); public static final SafeImplicitOutputsFunction REX_OUTPUT_PACKAGE_MAP = fromTemplates("%{name}_rex/rex_output_package.map"); + public static final SafeImplicitOutputsFunction INSTRUMENTATION_TEST_CHECK_RESULTS = + fromTemplates("%{name}_files/instrumentation_test_check_results.txt"); // This needs to be in its own directory because ApkBuilder only has a function (-rf) for source // folders but not source files, and it's easiest to guarantee that nothing gets put beside this @@ -992,6 +994,19 @@ public final class AndroidRuleClasses { .allowedRuleClasses("android_binary") .allowedFileTypes(NO_FILE)) .add( + attr("$instrumentation_test_check", LABEL) + .cfg(HOST) + .value( + new Attribute.ComputedDefault() { + @Override + public Object getDefault(AttributeMap rule) { + return rule.isAttributeValueExplicitlySpecified("instruments") + ? env.getToolsLabel("//tools/android:instrumentation_test_check") + : null; + } + }) + .exec()) + .add( attr("$zip_filter", LABEL) .cfg(HOST) .exec() |