aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/test/java/com/google/devtools
diff options
context:
space:
mode:
authorGravatar ajmichael <ajmichael@google.com>2017-10-05 23:06:41 +0200
committerGravatar Klaus Aehlig <aehlig@google.com>2017-10-06 19:48:18 +0200
commit7569bd0cab3a7eec863f48caee69d47f6260211a (patch)
treebd9d8a6a802e05e7be84f6fd23154f30822f1fde /src/test/java/com/google/devtools
parent104eb04bc709859a31079e77b397d3efa786968f (diff)
Open-source unit tests for proguard actions.
RELNOTES: None PiperOrigin-RevId: 171205009
Diffstat (limited to 'src/test/java/com/google/devtools')
-rw-r--r--src/test/java/com/google/devtools/build/lib/rules/android/AndroidBinaryTest.java421
-rw-r--r--src/test/java/com/google/devtools/build/lib/rules/android/AndroidBuildViewTestCase.java120
-rw-r--r--src/test/java/com/google/devtools/build/lib/rules/android/AndroidLibraryTest.java65
3 files changed, 602 insertions, 4 deletions
diff --git a/src/test/java/com/google/devtools/build/lib/rules/android/AndroidBinaryTest.java b/src/test/java/com/google/devtools/build/lib/rules/android/AndroidBinaryTest.java
index b97b27aadd..c50042c52c 100644
--- a/src/test/java/com/google/devtools/build/lib/rules/android/AndroidBinaryTest.java
+++ b/src/test/java/com/google/devtools/build/lib/rules/android/AndroidBinaryTest.java
@@ -17,11 +17,13 @@ import static com.google.common.collect.Iterables.getOnlyElement;
import static com.google.common.truth.Truth.assertThat;
import static com.google.common.truth.Truth.assertWithMessage;
import static com.google.devtools.build.lib.actions.util.ActionsTestUtil.getFirstArtifactEndingWith;
+import static com.google.devtools.build.lib.actions.util.ActionsTestUtil.prettyArtifactNames;
import static com.google.devtools.build.lib.testutil.MoreAsserts.expectThrows;
import com.google.common.base.Joiner;
import com.google.common.base.Predicate;
import com.google.common.base.Predicates;
+import com.google.common.collect.Collections2;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
@@ -2760,8 +2762,7 @@ public class AndroidBinaryTest extends AndroidBuildViewTestCase {
")");
ConfiguredTarget binary = getConfiguredTarget("//java/com/foo");
List<String> inputs =
- actionsTestUtil()
- .prettyArtifactNames(actionsTestUtil().artifactClosureOf(getFinalUnsignedApk(binary)));
+ prettyArtifactNames(actionsTestUtil().artifactClosureOf(getFinalUnsignedApk(binary)));
assertThat(inputs).containsAllOf("java/com/foo/Flag1On.java", "java/com/foo/Flag2Off.java");
assertThat(inputs).containsNoneOf("java/com/foo/Flag1Off.java", "java/com/foo/Flag2On.java");
@@ -2806,8 +2807,7 @@ public class AndroidBinaryTest extends AndroidBuildViewTestCase {
")");
ConfiguredTarget binary = getConfiguredTarget("//java/com/foo");
List<String> inputs =
- actionsTestUtil()
- .prettyArtifactNames(actionsTestUtil().artifactClosureOf(getFinalUnsignedApk(binary)));
+ prettyArtifactNames(actionsTestUtil().artifactClosureOf(getFinalUnsignedApk(binary)));
assertThat(inputs).containsAllOf("java/com/foo/Flag1On.java", "java/com/foo/Flag2Off.java");
assertThat(inputs).containsNoneOf("java/com/foo/Flag1Off.java", "java/com/foo/Flag2On.java");
@@ -3344,4 +3344,417 @@ public class AndroidBinaryTest extends AndroidBuildViewTestCase {
" manifest = 'AndroidManifest.xml')");
checkDebugKey(debugKeyTarget, false);
}
+
+ @Test
+ public void testOnlyProguardSpecs() throws Exception {
+ scratch.file("java/com/google/android/hello/BUILD",
+ "android_library(name = 'l2',",
+ " srcs = ['MoreMaps.java'],",
+ " neverlink = 1)",
+ "android_library(name = 'l3',",
+ " idl_srcs = ['A.aidl'],",
+ " deps = [':l2'])",
+ "android_library(name = 'l4',",
+ " srcs = ['SubMoreMaps.java'],",
+ " neverlink = 1)",
+ "android_binary(name = 'b',",
+ " srcs = ['HelloApp.java'],",
+ " deps = [':l3', ':l4'],",
+ " manifest = 'AndroidManifest.xml',",
+ " proguard_specs = ['proguard-spec.pro', 'proguard-spec1.pro',",
+ " 'proguard-spec2.pro'])");
+ checkProguardUse(
+ "//java/com/google/android/hello:b", "b_proguard.jar", false, null,
+ targetConfig.getBinFragment()
+ + "/java/com/google/android/hello/proguard/b/legacy_b_combined_library_jars.jar");
+ }
+
+ @Test
+ public void testOnlyProguardSpecsProguardJar() throws Exception {
+ scratch.file("java/com/google/android/hello/BUILD",
+ "android_library(name = 'l2',",
+ " srcs = ['MoreMaps.java'],",
+ " neverlink = 1)",
+ "android_library(name = 'l3',",
+ " idl_srcs = ['A.aidl'],",
+ " deps = [':l2'])",
+ "android_library(name = 'l4',",
+ " srcs = ['SubMoreMaps.java'],",
+ " neverlink = 1)",
+ "android_binary(name = 'b',",
+ " srcs = ['HelloApp.java'],",
+ " deps = [':l3', ':l4'],",
+ " manifest = 'AndroidManifest.xml',",
+ " proguard_generate_mapping = 1,",
+ " proguard_specs = ['proguard-spec.pro', 'proguard-spec1.pro',",
+ " 'proguard-spec2.pro'])");
+
+ ConfiguredTarget output = getConfiguredTarget("//java/com/google/android/hello:b_proguard.jar");
+ assertProguardUsed(output);
+
+ output = getConfiguredTarget("//java/com/google/android/hello:b_proguard.map");
+ assertWithMessage("proguard.map is not in the rule output")
+ .that(
+ actionsTestUtil()
+ .getActionForArtifactEndingWith(getFilesToBuild(output), "_proguard.map"))
+ .isNotNull();
+ }
+
+ @Test
+ public void testCommandLineForMultipleProguardSpecs() throws Exception {
+ scratch.file("java/com/google/android/hello/BUILD",
+ "android_library(name = 'l1',",
+ " srcs = ['Maps.java'],",
+ " neverlink = 1)",
+ "android_binary(name = 'b',",
+ " srcs = ['HelloApp.java'],",
+ " deps = [':l1'],",
+ " manifest = 'AndroidManifest.xml',",
+ " proguard_specs = ['proguard-spec.pro', 'proguard-spec1.pro',",
+ " 'proguard-spec2.pro'])");
+ ConfiguredTarget binary = getConfiguredTarget("//java/com/google/android/hello:b");
+ SpawnAction action = (SpawnAction) actionsTestUtil().getActionForArtifactEndingWith(
+ getFilesToBuild(binary), "_proguard.jar");
+
+ assertWithMessage("Proguard action does not contain expected inputs.")
+ .that(ActionsTestUtil.prettyArtifactNames(action.getInputs()))
+ .containsAllOf(
+ "java/com/google/android/hello/proguard-spec.pro",
+ "java/com/google/android/hello/proguard-spec1.pro",
+ "java/com/google/android/hello/proguard-spec2.pro");
+
+ assertThat(action.getArguments())
+ .containsExactly(
+ getProguardBinary().getExecPathString(),
+ "-forceprocessing",
+ "-injars",
+ execPathEndingWith(action.getInputs(), "b_deploy.jar"),
+ "-outjars",
+ execPathEndingWith(action.getOutputs(), "b_proguard.jar"),
+ // Only one combined library jar
+ "-libraryjars",
+ execPathEndingWith(action.getInputs(), "legacy_b_combined_library_jars.jar"),
+ "@" + execPathEndingWith(action.getInputs(), "b_proguard.cfg"),
+ "@java/com/google/android/hello/proguard-spec.pro",
+ "@java/com/google/android/hello/proguard-spec1.pro",
+ "@java/com/google/android/hello/proguard-spec2.pro",
+ "-printseeds",
+ execPathEndingWith(action.getOutputs(), "_proguard.seeds"),
+ "-printusage",
+ execPathEndingWith(action.getOutputs(), "_proguard.usage"),
+ "-printconfiguration",
+ execPathEndingWith(action.getOutputs(), "_proguard.config"))
+ .inOrder();
+ }
+
+ /** Regression test for b/17790639 */
+ @Test
+ public void testNoDuplicatesInProguardCommand() throws Exception {
+ scratch.file("java/com/google/android/hello/BUILD",
+ "android_library(name = 'l1',",
+ " srcs = ['Maps.java'],",
+ " neverlink = 1)",
+ "android_binary(name = 'b',",
+ " srcs = ['HelloApp.java'],",
+ " deps = [':l1'],",
+ " manifest = 'AndroidManifest.xml',",
+ " proguard_specs = ['proguard-spec.pro', 'proguard-spec1.pro',",
+ " 'proguard-spec2.pro'])");
+ ConfiguredTarget binary = getConfiguredTarget("//java/com/google/android/hello:b");
+ SpawnAction action = (SpawnAction) actionsTestUtil().getActionForArtifactEndingWith(
+ getFilesToBuild(binary), "_proguard.jar");
+ assertThat(action.getArguments())
+ .containsExactly(
+ getProguardBinary().getExecPathString(),
+ "-forceprocessing",
+ "-injars",
+ execPathEndingWith(action.getInputs(), "b_deploy.jar"),
+ "-outjars",
+ execPathEndingWith(action.getOutputs(), "b_proguard.jar"),
+ // Only one combined library jar
+ "-libraryjars",
+ execPathEndingWith(action.getInputs(), "legacy_b_combined_library_jars.jar"),
+ "@" + execPathEndingWith(action.getInputs(), "b_proguard.cfg"),
+ "@java/com/google/android/hello/proguard-spec.pro",
+ "@java/com/google/android/hello/proguard-spec1.pro",
+ "@java/com/google/android/hello/proguard-spec2.pro",
+ "-printseeds",
+ execPathEndingWith(action.getOutputs(), "_proguard.seeds"),
+ "-printusage",
+ execPathEndingWith(action.getOutputs(), "_proguard.usage"),
+ "-printconfiguration",
+ execPathEndingWith(action.getOutputs(), "_proguard.config"))
+ .inOrder();
+ }
+
+ @Test
+ public void testProguardMapping() throws Exception {
+ scratch.file("java/com/google/android/hello/BUILD",
+ "android_binary(name = 'b',",
+ " srcs = ['HelloApp.java'],",
+ " manifest = 'AndroidManifest.xml',",
+ " proguard_specs = ['proguard-spec.pro'],",
+ " proguard_generate_mapping = 1)");
+ checkProguardUse(
+ "//java/com/google/android/hello:b", "b_proguard.jar", true, null, getAndroidJarPath());
+ }
+
+ @Test
+ public void testProguardMappingProvider() throws Exception {
+ scratch.file("java/com/google/android/hello/BUILD",
+ "android_library(name = 'l2',",
+ " srcs = ['MoreMaps.java'],",
+ " neverlink = 1)",
+ "android_library(name = 'l3',",
+ " idl_srcs = ['A.aidl'],",
+ " deps = [':l2'])",
+ "android_library(name = 'l4',",
+ " srcs = ['SubMoreMaps.java'],",
+ " neverlink = 1)",
+ "android_binary(name = 'b1',",
+ " srcs = ['HelloApp.java'],",
+ " deps = [':l3', ':l4'],",
+ " manifest = 'AndroidManifest.xml',",
+ " proguard_generate_mapping = 1,",
+ " proguard_specs = ['proguard-spec.pro', 'proguard-spec1.pro',",
+ " 'proguard-spec2.pro'])",
+ "android_binary(name = 'b2',",
+ " srcs = ['HelloApp.java'],",
+ " deps = [':l3', ':l4'],",
+ " manifest = 'AndroidManifest.xml',",
+ " proguard_specs = ['proguard-spec.pro', 'proguard-spec1.pro',",
+ " 'proguard-spec2.pro'])");
+
+ ConfiguredTarget output = getConfiguredTarget("//java/com/google/android/hello:b1");
+ assertProguardUsed(output);
+ Artifact mappingArtifact = getBinArtifact("b1_proguard.map", output);
+ ProguardMappingProvider mappingProvider = output.getProvider(ProguardMappingProvider.class);
+ assertThat(mappingProvider.getProguardMapping()).isEqualTo(mappingArtifact);
+
+ output = getConfiguredTarget("//java/com/google/android/hello:b2");
+ assertProguardUsed(output);
+ assertThat(output.getProvider(ProguardMappingProvider.class)).isNull();
+ }
+
+ @Test
+ public void testLegacyOptimizationModeUsesExtraProguardSpecs() throws Exception {
+ useConfiguration("--extra_proguard_specs=java/com/google/android/hello:extra.pro");
+ scratch.file("java/com/google/android/hello/BUILD",
+ "exports_files(['extra.pro'])",
+ "android_binary(name = 'b',",
+ " srcs = ['HelloApp.java'],",
+ " manifest = 'AndroidManifest.xml',",
+ " proguard_specs = ['proguard-spec.pro'])");
+ checkProguardUse(
+ "//java/com/google/android/hello:b", "b_proguard.jar", false, null, getAndroidJarPath());
+
+ SpawnAction action = (SpawnAction) actionsTestUtil().getActionForArtifactEndingWith(
+ getFilesToBuild(getConfiguredTarget("//java/com/google/android/hello:b")), "_proguard.jar");
+ assertThat(ActionsTestUtil.prettyArtifactNames(action.getInputs())).containsNoDuplicates();
+ assertThat(Collections2.filter(action.getArguments(), arg -> arg.startsWith("@")))
+ .containsExactly(
+ "@" + execPathEndingWith(action.getInputs(), "/proguard-spec.pro"),
+ "@" + execPathEndingWith(action.getInputs(), "/_b_proguard.cfg"),
+ "@java/com/google/android/hello/extra.pro");
+ }
+
+ @Test
+ public void testExtraProguardSpecsDontDuplicateProguardInputFiles() throws Exception {
+ useConfiguration("--extra_proguard_specs=java/com/google/android/hello:proguard-spec.pro");
+ scratch.file("java/com/google/android/hello/BUILD",
+ "android_binary(name = 'b',",
+ " srcs = ['HelloApp.java'],",
+ " manifest = 'AndroidManifest.xml',",
+ " proguard_specs = ['proguard-spec.pro'])");
+ checkProguardUse(
+ "//java/com/google/android/hello:b", "b_proguard.jar", false, null, getAndroidJarPath());
+
+ SpawnAction action = (SpawnAction) actionsTestUtil().getActionForArtifactEndingWith(
+ getFilesToBuild(getConfiguredTarget("//java/com/google/android/hello:b")), "_proguard.jar");
+ assertThat(ActionsTestUtil.prettyArtifactNames(action.getInputs())).containsNoDuplicates();
+ assertThat(Collections2.filter(action.getArguments(), arg -> arg.startsWith("@")))
+ .containsExactly(
+ "@java/com/google/android/hello/proguard-spec.pro",
+ "@" + execPathEndingWith(action.getInputs(), "/_b_proguard.cfg"));
+ }
+
+ @Test
+ public void testLegacyLinkingProguardNotUsedWithoutSpecOnBinary() throws Exception {
+ useConfiguration(
+ "--java_optimization_mode=legacy",
+ "--extra_proguard_specs=//java/com/google/android/hello:ignored.pro");
+ scratch.file("java/com/google/android/hello/BUILD",
+ "exports_files(['ignored.pro'])",
+ "android_library(name = 'l2',",
+ " srcs = ['MoreMaps.java'],",
+ " neverlink = 1)",
+ "android_library(name = 'l3',",
+ " idl_srcs = ['A.aidl'],",
+ // Having a library spec should not trigger proguard on the binary target.
+ " proguard_specs = ['library_spec.cfg'],",
+ " deps = [':l2'])",
+ "android_library(name = 'l4',",
+ " srcs = ['SubMoreMaps.java'],",
+ " neverlink = 1)",
+ "android_binary(name = 'b',",
+ " srcs = ['HelloApp.java'],",
+ " deps = [':l3', ':l4'],",
+ " manifest = 'AndroidManifest.xml',)");
+ assertProguardNotUsed(getConfiguredTarget("//java/com/google/android/hello:b"));
+ }
+
+ @Test
+ public void testFullOptimizationModeForcesProguard() throws Exception {
+ useConfiguration("--java_optimization_mode=optimize_minify");
+ SpawnAction action = testProguardOptimizationMode();
+ // Expect spec generated from resources as well as library's (validated) spec as usual
+ assertThat(Collections2.filter(action.getArguments(), arg -> arg.startsWith("@")))
+ .containsExactly(
+ "@" + execPathEndingWith(action.getInputs(), "/_b_proguard.cfg"),
+ "@" + execPathEndingWith(action.getInputs(), "library_spec.cfg_valid"));
+ }
+
+ @Test
+ public void testOptimizingModesIncludeExtraProguardSpecs() throws Exception {
+ useConfiguration(
+ "--java_optimization_mode=fast_minify",
+ "--extra_proguard_specs=//java/com/google/android/hello:extra.pro");
+ SpawnAction action = testProguardOptimizationMode();
+ assertThat(action.getArguments()).contains("@java/com/google/android/hello/extra.pro");
+ }
+
+ @Test
+ public void testRenameModeForcesProguardWithSpecForMode() throws Exception {
+ testProguardPartialOptimizationMode("rename", "-dontshrink\n-dontoptimize\n");
+ }
+
+ @Test
+ public void testMinimizingModeForcesProguardWithSpecForMode() throws Exception {
+ testProguardPartialOptimizationMode("fast_minify", "-dontoptimize\n");
+ }
+
+ public void testProguardPartialOptimizationMode(String mode, String expectedSpecForMode)
+ throws Exception {
+ useConfiguration("--java_optimization_mode=" + mode);
+ SpawnAction action = testProguardOptimizationMode();
+ // Expect spec generated from resources, library's (validated) spec, and spec for mode
+ String modeSpecFileSuffix = "/" + mode + "_b_proguard.cfg";
+ assertThat(Collections2.filter(action.getArguments(), arg -> arg.startsWith("@")))
+ .containsExactly(
+ "@" + execPathEndingWith(action.getInputs(), modeSpecFileSuffix),
+ "@" + execPathEndingWith(action.getInputs(), "/_b_proguard.cfg"),
+ "@" + execPathEndingWith(action.getInputs(), "library_spec.cfg_valid"));
+
+ FileWriteAction modeSpec = (FileWriteAction) actionsTestUtil().getActionForArtifactEndingWith(
+ action.getInputs(), modeSpecFileSuffix);
+ assertThat(modeSpec.getFileContents()).isEqualTo(expectedSpecForMode);
+ }
+
+ public SpawnAction testProguardOptimizationMode() throws Exception {
+ scratch.file("java/com/google/android/hello/BUILD",
+ "exports_files(['extra.pro'])",
+ "android_library(name = 'l',",
+ " idl_srcs = ['A.aidl'],",
+ " proguard_specs = ['library_spec.cfg'])",
+ "android_binary(name = 'b',",
+ " srcs = ['HelloApp.java'],",
+ " deps = [':l'],",
+ " manifest = 'AndroidManifest.xml',)");
+ checkProguardUse(
+ "//java/com/google/android/hello:b",
+ "b_proguard.jar",
+ /*expectMapping*/ true,
+ /*passes*/ null,
+ getAndroidJarPath());
+
+ SpawnAction action = (SpawnAction) actionsTestUtil().getActionForArtifactEndingWith(
+ getFilesToBuild(getConfiguredTarget("//java/com/google/android/hello:b")), "_proguard.jar");
+ assertThat(ActionsTestUtil.prettyArtifactNames(action.getInputs())).containsNoDuplicates();
+ return action;
+ }
+
+ @Test
+ public void testProguardSpecFromLibraryUsedInBinary() throws Exception {
+ scratch.file("java/com/google/android/hello/BUILD",
+ "android_library(name = 'l2',",
+ " srcs = ['MoreMaps.java'],",
+ " proguard_specs = ['library_spec.cfg'])",
+ "android_library(name = 'l3',",
+ " idl_srcs = ['A.aidl'],",
+ " proguard_specs = ['library_spec.cfg'],",
+ " deps = [':l2'])",
+ "android_library(name = 'l4',",
+ " srcs = ['SubMoreMaps.java'],",
+ " neverlink = 1)",
+ "android_binary(name = 'b',",
+ " srcs = ['HelloApp.java'],",
+ " deps = [':l3', ':l4'],",
+ " proguard_specs = ['proguard-spec.pro'],",
+ " manifest = 'AndroidManifest.xml',)");
+ assertProguardUsed(getConfiguredTarget("//java/com/google/android/hello:b"));
+ assertProguardGenerated(getConfiguredTarget("//java/com/google/android/hello:b"));
+ SpawnAction action = (SpawnAction) actionsTestUtil().getActionForArtifactEndingWith(
+ getFilesToBuild(getConfiguredTarget("//java/com/google/android/hello:b")), "_proguard.jar");
+ assertThat(prettyArtifactNames(action.getInputs())).contains(
+ "java/com/google/android/hello/proguard-spec.pro");
+ assertThat(prettyArtifactNames(action.getInputs())).contains(
+ "java/com/google/android/hello/validated_proguard/l2/java/com/google/android/hello/library_spec.cfg_valid");
+ assertThat(ActionsTestUtil.prettyArtifactNames(action.getInputs())).containsNoDuplicates();
+ }
+
+ @Test
+ public void testResourcesUsedInProguardGenerate() throws Exception {
+ scratch.file("java/com/google/android/hello/BUILD",
+ "android_binary(name = 'b',",
+ " srcs = ['HelloApp.java'],",
+ " manifest = 'AndroidManifest.xml',",
+ " resource_files = ['res/values/strings.xml'],",
+ " proguard_specs = ['proguard-spec.pro', 'proguard-spec1.pro',",
+ " 'proguard-spec2.pro'])");
+ scratch.file("java/com/google/android/hello/res/values/strings.xml",
+ "<resources><string name = 'hello'>Hello Android!</string></resources>");
+ ConfiguredTarget binary = getConfiguredTarget("//java/com/google/android/hello:b");
+ SpawnAction action = (SpawnAction) actionsTestUtil().getActionForArtifactEndingWith(
+ actionsTestUtil().artifactClosureOf(getFilesToBuild(binary)), "_proguard.cfg");
+
+ assertProguardGenerated(binary);
+ assertWithMessage("Generate proguard action does not contain expected input.")
+ .that(ActionsTestUtil.prettyArtifactNames(action.getInputs()))
+ .contains("java/com/google/android/hello/res/values/strings.xml");
+ }
+
+ @Test
+ public void testUseSingleJarForLibraryJars() throws Exception {
+ scratch.file("java/com/google/android/hello/BUILD",
+ "android_library(name = 'l1',",
+ " srcs = ['Maps.java'],",
+ " neverlink = 1)",
+ "android_binary(name = 'b',",
+ " srcs = ['HelloApp.java'],",
+ " deps = [':l1'],",
+ " manifest = 'AndroidManifest.xml',",
+ " proguard_specs = ['proguard-spec.pro', 'proguard-spec1.pro',",
+ " 'proguard-spec2.pro'])");
+ ConfiguredTarget binary = getConfiguredTarget("//java/com/google/android/hello:b");
+ SpawnAction action = (SpawnAction) actionsTestUtil().getActionForArtifactEndingWith(
+ getFilesToBuild(binary), "_proguard.jar");
+
+ checkProguardLibJars(action, targetConfig.getBinFragment()
+ + "/java/com/google/android/hello/proguard/b/legacy_b_combined_library_jars.jar");
+ }
+
+ @Test
+ public void testOnlyOneLibraryJar() throws Exception {
+ scratch.file("java/com/google/android/hello/BUILD",
+ "android_binary(name = 'b',",
+ " srcs = ['HelloApp.java'],",
+ " manifest = 'AndroidManifest.xml',",
+ " proguard_specs = ['proguard-spec.pro'],",
+ " proguard_generate_mapping = 1)");
+ ConfiguredTarget binary = getConfiguredTarget("//java/com/google/android/hello:b");
+ SpawnAction action = (SpawnAction) actionsTestUtil().getActionForArtifactEndingWith(
+ getFilesToBuild(binary), "_proguard.jar");
+
+ checkProguardLibJars(action, getAndroidJarPath());
+ }
}
diff --git a/src/test/java/com/google/devtools/build/lib/rules/android/AndroidBuildViewTestCase.java b/src/test/java/com/google/devtools/build/lib/rules/android/AndroidBuildViewTestCase.java
index f6f6bd44c4..5ae85d5c54 100644
--- a/src/test/java/com/google/devtools/build/lib/rules/android/AndroidBuildViewTestCase.java
+++ b/src/test/java/com/google/devtools/build/lib/rules/android/AndroidBuildViewTestCase.java
@@ -26,6 +26,7 @@ import com.google.common.collect.Sets;
import com.google.devtools.build.lib.actions.Action;
import com.google.devtools.build.lib.actions.Artifact;
import com.google.devtools.build.lib.actions.CommandLineExpansionException;
+import com.google.devtools.build.lib.actions.util.ActionsTestUtil;
import com.google.devtools.build.lib.analysis.ConfiguredRuleClassProvider;
import com.google.devtools.build.lib.analysis.ConfiguredTarget;
import com.google.devtools.build.lib.analysis.FileProvider;
@@ -39,7 +40,10 @@ import com.google.devtools.build.lib.rules.java.JavaRuleOutputJarsProvider;
import com.google.devtools.build.lib.testutil.TestRuleClassProvider;
import com.google.devtools.build.lib.util.Preconditions;
import java.io.IOException;
+import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Collection;
+import java.util.Iterator;
import java.util.List;
import java.util.Set;
import javax.annotation.Nullable;
@@ -274,4 +278,120 @@ public abstract class AndroidBuildViewTestCase extends BuildViewTestCase {
return hasKey && !doesNotHaveKey;
}
+
+ protected String getAndroidJarPath() throws Exception {
+ return getAndroidSdk().getAndroidJar().getRootRelativePathString();
+ }
+
+ protected Artifact getProguardBinary() throws Exception {
+ return getAndroidSdk().getProguard().getExecutable();
+ }
+
+ private AndroidSdkProvider getAndroidSdk() {
+ Label sdk = targetConfig.getFragment(AndroidConfiguration.class).getSdk();
+ return getConfiguredTarget(sdk, targetConfig).getProvider(AndroidSdkProvider.class);
+ }
+
+ protected void checkProguardUse(String target, String artifact, boolean expectMapping,
+ @Nullable Integer passes,
+ String... expectedlibraryJars) throws Exception {
+ ConfiguredTarget binary = getConfiguredTarget(target);
+ assertProguardUsed(binary);
+ assertProguardGenerated(binary);
+
+ Action dexAction = actionsTestUtil().getActionForArtifactEndingWith(
+ actionsTestUtil().artifactClosureOf(getFilesToBuild(binary)), "classes.dex");
+ Artifact trimmedJar =
+ getFirstArtifactEndingWith(dexAction.getInputs(), artifact);
+ assertWithMessage("Dex should be built from jar trimmed with Proguard.")
+ .that(trimmedJar)
+ .isNotNull();
+ SpawnAction proguardAction = getGeneratingSpawnAction(trimmedJar);
+
+ if (passes == null) {
+ // Verify proguard as a single action.
+ Action proguardMap = actionsTestUtil().getActionForArtifactEndingWith(getFilesToBuild(binary),
+ "_proguard.map");
+ if (expectMapping) {
+ assertWithMessage("proguard.map is not in the rule output").that(proguardMap).isNotNull();
+ } else {
+ assertWithMessage("proguard.map is in the rule output").that(proguardMap).isNull();
+ }
+ checkProguardLibJars(proguardAction, expectedlibraryJars);
+ } else {
+ // Verify the multi-stage system generated the correct number of stages.
+ Artifact proguardMap = ActionsTestUtil.getFirstArtifactEndingWith(
+ proguardAction.getOutputs(), "_proguard.map");
+ if (expectMapping) {
+ assertWithMessage("proguard.map is not in the rule output").that(proguardMap).isNotNull();
+ } else {
+ assertWithMessage("proguard.map is in the rule output").that(proguardMap).isNull();
+ }
+
+ assertThat(proguardAction.getArguments()).contains("-runtype FINAL");
+ checkProguardLibJars(proguardAction, expectedlibraryJars);
+
+ SpawnAction lastStageAction = proguardAction;
+ // Verify Obfuscation config.
+ for (int pass = passes; pass > 0; pass--) {
+ Artifact lastStageOutput = ActionsTestUtil.getFirstArtifactEndingWith(
+ lastStageAction.getInputs(),
+ "Proguard_optimization_" + pass + ".jar");
+ assertWithMessage("Proguard_optimization_" + pass + ".jar is not in rule output")
+ .that(lastStageOutput)
+ .isNotNull();
+ lastStageAction = getGeneratingSpawnAction(lastStageOutput);
+
+ // Verify Optimization pass config.
+ assertThat(lastStageAction.getArguments()).contains("-runtype OPTIMIZATION");
+ checkProguardLibJars(lastStageAction, expectedlibraryJars);
+ }
+
+ Artifact preoptimizationOutput = ActionsTestUtil.getFirstArtifactEndingWith(
+ lastStageAction.getInputs(), "proguard_preoptimization.jar");
+ assertWithMessage("proguard_preoptimization.jar is not in rule output")
+ .that(preoptimizationOutput)
+ .isNotNull();
+ SpawnAction proOptimization = getGeneratingSpawnAction(preoptimizationOutput);
+
+ // Verify intitial step.
+ assertThat(proOptimization.getArguments()).contains("-runtype INITIAL");
+ checkProguardLibJars(proOptimization, expectedlibraryJars);
+ }
+ }
+
+ void checkProguardLibJars(SpawnAction proguardAction, String... expectedlibraryJars)
+ throws Exception {
+ Collection<String> libraryJars = new ArrayList<>();
+ Iterator<String> argsIterator = proguardAction.getArguments().iterator();
+ for (String argument = argsIterator.next(); argsIterator.hasNext();
+ argument = argsIterator.next()) {
+ if (argument.equals("-libraryjars")) {
+ libraryJars.add(argsIterator.next());
+ }
+ }
+ assertThat(libraryJars).containsExactly((Object[]) expectedlibraryJars);
+ }
+
+ protected void assertProguardGenerated(ConfiguredTarget binary) {
+ Action generateProguardAction = actionsTestUtil().getActionForArtifactEndingWith(
+ actionsTestUtil().artifactClosureOf(getFilesToBuild(binary)), "_proguard.cfg");
+ assertWithMessage("proguard generating action not spawned")
+ .that(generateProguardAction)
+ .isNotNull();
+ Action proguardAction =
+ actionsTestUtil().getActionForArtifactEndingWith(getFilesToBuild(binary), "_proguard.jar");
+ actionsTestUtil();
+ assertWithMessage("Generated config not in inputs to proguard action")
+ .that(proguardAction.getInputs()).contains(ActionsTestUtil.getFirstArtifactEndingWith(
+ generateProguardAction.getOutputs(), "_proguard.cfg"));
+ }
+
+ protected void assertProguardNotUsed(ConfiguredTarget binary) {
+ assertWithMessage("proguard.jar is in the rule output")
+ .that(
+ actionsTestUtil()
+ .getActionForArtifactEndingWith(getFilesToBuild(binary), "_proguard.jar"))
+ .isNull();
+ }
}
diff --git a/src/test/java/com/google/devtools/build/lib/rules/android/AndroidLibraryTest.java b/src/test/java/com/google/devtools/build/lib/rules/android/AndroidLibraryTest.java
index 7c7d821479..0f76cd20d1 100644
--- a/src/test/java/com/google/devtools/build/lib/rules/android/AndroidLibraryTest.java
+++ b/src/test/java/com/google/devtools/build/lib/rules/android/AndroidLibraryTest.java
@@ -15,6 +15,7 @@ package com.google.devtools.build.lib.rules.android;
import static com.google.common.collect.Iterables.getOnlyElement;
import static com.google.common.truth.Truth.assertThat;
+import static com.google.common.truth.Truth.assertWithMessage;
import com.google.common.base.Function;
import com.google.common.base.Joiner;
@@ -26,6 +27,7 @@ import com.google.devtools.build.lib.actions.Action;
import com.google.devtools.build.lib.actions.Artifact;
import com.google.devtools.build.lib.actions.util.ActionsTestUtil;
import com.google.devtools.build.lib.analysis.ConfiguredTarget;
+import com.google.devtools.build.lib.analysis.OutputGroupProvider;
import com.google.devtools.build.lib.analysis.actions.FileWriteAction;
import com.google.devtools.build.lib.analysis.actions.SpawnAction;
import com.google.devtools.build.lib.analysis.config.BuildConfiguration;
@@ -1588,4 +1590,67 @@ public class AndroidLibraryTest extends AndroidBuildViewTestCase {
.allowSrcsLessAndroidLibraryDeps())
.isTrue();
}
+
+ @Test
+ public void testAndroidLibraryValidatesProguardSpec() throws Exception {
+ scratch.file("java/com/google/android/hello/BUILD",
+ "android_library(name = 'l2',",
+ " srcs = ['MoreMaps.java'],",
+ " proguard_specs = ['library_spec.cfg'])",
+ "android_binary(name = 'b',",
+ " srcs = ['HelloApp.java'],",
+ " manifest = 'AndroidManifest.xml',",
+ " deps = [':l2'],",
+ " proguard_specs = ['proguard-spec.pro'])");
+ Set<Artifact> transitiveArtifacts =
+ actionsTestUtil()
+ .artifactClosureOf(
+ getFilesToBuild(getConfiguredTarget("//java/com/google/android/hello:b")));
+ Action action =
+ actionsTestUtil()
+ .getActionForArtifactEndingWith(transitiveArtifacts, "library_spec.cfg_valid");
+ assertWithMessage("proguard validate action was spawned for binary target.")
+ .that(
+ actionsTestUtil()
+ .getActionForArtifactEndingWith(transitiveArtifacts, "proguard-spec.pro_valid"))
+ .isNull();
+ assertWithMessage("Proguard validate action was not spawned.")
+ .that(ActionsTestUtil.prettyArtifactNames(action.getInputs()))
+ .contains("java/com/google/android/hello/library_spec.cfg");
+ }
+
+ @Test
+ public void testAndroidLibraryValidatesProguardSpecWithoutBinary() throws Exception {
+ scratch.file("java/com/google/android/hello/BUILD",
+ "android_library(name = 'l2',",
+ " srcs = ['MoreMaps.java'],",
+ " proguard_specs = ['library_spec.cfg'])",
+ "android_library(name = 'l3',",
+ " srcs = ['MoreMaps.java'],",
+ " deps = [':l2'])");
+ Action action =
+ actionsTestUtil()
+ .getActionForArtifactEndingWith(
+ getOutputGroup(
+ getConfiguredTarget("//java/com/google/android/hello:l2"),
+ OutputGroupProvider.HIDDEN_TOP_LEVEL),
+ "library_spec.cfg_valid");
+ assertWithMessage("Proguard validate action was not spawned.").that(action).isNotNull();
+ assertWithMessage("Proguard validate action was spawned without correct input.")
+ .that(ActionsTestUtil.prettyArtifactNames(action.getInputs()))
+ .contains("java/com/google/android/hello/library_spec.cfg");
+ Action transitiveAction =
+ actionsTestUtil()
+ .getActionForArtifactEndingWith(
+ getOutputGroup(
+ getConfiguredTarget("//java/com/google/android/hello:l3"),
+ OutputGroupProvider.HIDDEN_TOP_LEVEL),
+ "library_spec.cfg_valid");
+ assertWithMessage("Proguard validate action was not spawned.")
+ .that(transitiveAction)
+ .isNotNull();
+ assertWithMessage("Proguard validate action was spawned without correct input.")
+ .that(ActionsTestUtil.prettyArtifactNames(transitiveAction.getInputs()))
+ .contains("java/com/google/android/hello/library_spec.cfg");
+ }
}