aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/test/java/com/google
diff options
context:
space:
mode:
authorGravatar ajmichael <ajmichael@google.com>2017-04-10 21:24:21 +0000
committerGravatar Jakob Buchgraber <buchgr@google.com>2017-04-11 10:50:24 +0200
commit3334b253e8f0e59bbb3eb97a6de2a07dd4e64a25 (patch)
treea6b36951bc755a5c38f9701e620066d88d4b8795 /src/test/java/com/google
parent0e3381e92ec2060fb3d2fd16d113e065063ccc03 (diff)
Open source AndroidBinaryMultidexTest.
This includes tests for the feature in https://github.com/bazelbuild/bazel/issues/1936. RELNOTES: None PiperOrigin-RevId: 152734391
Diffstat (limited to 'src/test/java/com/google')
-rw-r--r--src/test/java/com/google/devtools/build/lib/rules/android/AndroidBinaryMultidexTest.java110
-rw-r--r--src/test/java/com/google/devtools/build/lib/rules/android/AndroidMultidexBaseTest.java149
-rw-r--r--src/test/java/com/google/devtools/build/lib/rules/android/BUILD20
3 files changed, 279 insertions, 0 deletions
diff --git a/src/test/java/com/google/devtools/build/lib/rules/android/AndroidBinaryMultidexTest.java b/src/test/java/com/google/devtools/build/lib/rules/android/AndroidBinaryMultidexTest.java
new file mode 100644
index 0000000000..9153f0dca5
--- /dev/null
+++ b/src/test/java/com/google/devtools/build/lib/rules/android/AndroidBinaryMultidexTest.java
@@ -0,0 +1,110 @@
+// Copyright 2017 The Bazel Authors. 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 com.google.devtools.build.lib.rules.android;
+
+import com.google.devtools.build.lib.rules.android.AndroidRuleClasses.MultidexMode;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+/**
+ * Tests the multidex code of {@link com.google.devtools.build.lib.rules.android.AndroidBinary}.
+ */
+@RunWith(JUnit4.class)
+public class AndroidBinaryMultidexTest extends AndroidMultidexBaseTest {
+
+ /**
+ * Tests that when multidex = "off", a classes.dex file is generated directly
+ * from the input jar.
+ */
+ @Test
+ public void testNonMultidexBuildStructure() throws Exception {
+ scratch.file("java/foo/BUILD",
+ "android_binary(",
+ " name = 'nomultidex',",
+ " srcs = ['a.java'],",
+ " manifest = 'AndroidManifest.xml',",
+ " resource_files = glob(['res/**']),",
+ " multidex = 'off')");
+ internalTestNonMultidexBuildStructure("//java/foo:nomultidex");
+ }
+
+ /**
+ * Tests that the default multidex setting is the same as when multidex = "off".
+ */
+ @Test
+ public void testDefaultBuildStructure() throws Exception {
+ scratch.file("java/foo/BUILD",
+ "android_binary(",
+ " name = 'default',",
+ " srcs = ['a.java'],",
+ " manifest = 'AndroidManifest.xml',",
+ " resource_files = glob(['res/**']))");
+ internalTestNonMultidexBuildStructure("//java/foo:default");
+ }
+
+ @Test
+ public void testManualMainDexMode() throws Exception {
+ scratch.file("java/foo/main_dex_list.txt",
+ "android/A.class");
+ scratch.file("java/foo/BUILD",
+ "android_binary(",
+ " name = 'manual_main_dex',",
+ " srcs = ['a.java'],",
+ " manifest = 'AndroidManifest.xml',",
+ " resource_files = glob(['res/**']),",
+ " multidex = 'manual_main_dex',",
+ " main_dex_list = 'main_dex_list.txt')");
+ internalTestMultidexBuildStructure(
+ "//java/foo:manual_main_dex", MultidexMode.MANUAL_MAIN_DEX);
+ }
+
+ /**
+ * Tests that when multidex = "legacy", a classes.dex.zip file is generated from
+ * an intermediate file with multidex mode specified and a "--main-dex-list" dx flag
+ * filled out with appropriate input, This file is then filtered through a zip
+ * action to remove non-.dex files to produce the final output.
+ */
+ @Test
+ public void testLegacyMultidexBuildStructure() throws Exception {
+ scratch.file("java/foo/BUILD",
+ "android_binary(",
+ " name = 'legacy',",
+ " srcs = ['a.java'],",
+ " manifest = 'AndroidManifest.xml',",
+ " resource_files = glob(['res/**']),",
+ " multidex = 'legacy')");
+ internalTestMultidexBuildStructure("//java/foo:legacy", MultidexMode.LEGACY);
+ }
+
+ /**
+ * Tests that when multidex = "native", a classes.dex.zip file is generated from
+ * an intermediate file with multidex mode specified. Unlike in "legacy" mode,
+ * no actions are required to set and fill the "--main-dex-list" dx flag. The
+ * intermediate file is then filtered through a zip action to remove non-.dex files
+ * to produce the final output.
+ */
+ @Test
+ public void testNativeMultidexBuildStructure() throws Exception {
+ scratch.file("java/foo/BUILD",
+ "android_binary(",
+ " name = 'native',",
+ " srcs = ['a.java'],",
+ " manifest = 'AndroidManifest.xml',",
+ " resource_files = glob(['res/**']),",
+ " multidex = 'native')");
+ internalTestMultidexBuildStructure("//java/foo:native", MultidexMode.NATIVE);
+ }
+}
+
diff --git a/src/test/java/com/google/devtools/build/lib/rules/android/AndroidMultidexBaseTest.java b/src/test/java/com/google/devtools/build/lib/rules/android/AndroidMultidexBaseTest.java
new file mode 100644
index 0000000000..272e4a90e1
--- /dev/null
+++ b/src/test/java/com/google/devtools/build/lib/rules/android/AndroidMultidexBaseTest.java
@@ -0,0 +1,149 @@
+// Copyright 2017 The Bazel Authors. 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 com.google.devtools.build.lib.rules.android;
+
+import static com.google.common.truth.Truth.assertThat;
+import static com.google.devtools.build.lib.actions.util.ActionsTestUtil.getFirstArtifactEndingWith;
+
+import com.google.common.collect.ImmutableList;
+import com.google.devtools.build.lib.actions.Artifact;
+import com.google.devtools.build.lib.analysis.ConfiguredTarget;
+import com.google.devtools.build.lib.analysis.actions.SpawnAction;
+import com.google.devtools.build.lib.analysis.util.BuildViewTestCase;
+import com.google.devtools.build.lib.rules.android.AndroidRuleClasses.MultidexMode;
+import java.util.Set;
+import org.junit.Before;
+
+/**
+ * Base class for testing the multidex code of android_binary and android_test.
+ */
+public class AndroidMultidexBaseTest extends BuildViewTestCase {
+
+ @Before
+ public final void createFiles() throws Exception {
+ scratch.file("java/android/BUILD",
+ "android_binary(name = 'app',",
+ " srcs = ['A.java'],",
+ " manifest = 'AndroidManifest.xml',",
+ " resource_files = glob(['res/**']),",
+ " )");
+ scratch.file("java/android/res/values/strings.xml",
+ "<resources><string name = 'hello'>Hello Android!</string></resources>");
+ scratch.file("java/android/A.java",
+ "package android; public class A {};");
+ }
+
+ /**
+ * Internal helper method: given an android_binary rule label, check that it builds in
+ * multidex mode. Three multidex variations are possible: "legacy", "manual_main_dex" and
+ * "native".
+ *
+ * @param ruleLabel the android_binary rule label to test against
+ * @param multidexMode the multidex mode used in the rule
+ */
+ protected void internalTestMultidexBuildStructure(
+ String ruleLabel, MultidexMode multidexMode) throws Exception {
+
+ ConfiguredTarget binary = getConfiguredTarget(ruleLabel);
+ Set<Artifact> artifacts = actionsTestUtil().artifactClosureOf(getFilesToBuild(binary));
+
+ // Always created:
+ Artifact intermediateDexOutput =
+ getFirstArtifactEndingWith(artifacts, "intermediate_classes.dex.zip");
+ assertThat(intermediateDexOutput).isNotNull();
+ Artifact finalDexOutput = getFirstArtifactEndingWith(artifacts, "/classes.dex.zip");
+ assertThat(finalDexOutput).isNotNull();
+
+ // Only created in legacy mode:
+ Artifact strippedJar = getFirstArtifactEndingWith(artifacts, "main_dex_intermediate.jar");
+ Artifact mainDexList = getFirstArtifactEndingWith(artifacts, "main_dex_list.txt");
+
+ if (multidexMode == MultidexMode.LEGACY) {
+ // First action: check that the stripped jar is generated through Proguard.
+ AndroidSdkProvider sdk = AndroidSdkProvider.fromRuleContext(getRuleContext(binary));
+ assertThat(strippedJar).isNotNull();
+ SpawnAction stripAction = (SpawnAction) getGeneratingAction(strippedJar);
+ assertThat(stripAction.getCommandFilename())
+ .isEqualTo(sdk.getProguard().getExecutable().getExecPathString());
+
+ // Second action: The dexer consumes the stripped jar to create the main dex class list.
+ assertThat(mainDexList).isNotNull();
+ SpawnAction mainDexAction = (SpawnAction) getGeneratingAction(mainDexList);
+ assertThat(mainDexAction.getArguments()).containsAllOf(
+ mainDexList.getExecPathString(),
+ strippedJar.getExecPathString()).inOrder();
+ } else if (multidexMode == MultidexMode.MANUAL_MAIN_DEX) {
+ // Manual main dex mode: strippedJar shouldn't exist and mainDexList should be provided.
+ assertThat(strippedJar).isNull();
+ assertThat(mainDexList).isNotNull();
+ } else {
+ // Native mode: these shouldn't exist.
+ assertThat(strippedJar).isNull();
+ assertThat(mainDexList).isNull();
+ }
+
+ // Third action: the dexer command consumes the main dex class list to generate the intermediate
+ // dex output.
+ SpawnAction dexAction = (SpawnAction) getGeneratingAction(intermediateDexOutput);
+ ImmutableList.Builder<String> argBuilder = ImmutableList.builder();
+ argBuilder.add("--dex");
+ if (multidexMode == MultidexMode.OFF) {
+ argBuilder.add("--num-threads=5");
+ } else {
+ argBuilder.add("--multi-dex");
+
+ if (multidexMode == MultidexMode.LEGACY || multidexMode == MultidexMode.MANUAL_MAIN_DEX) {
+ argBuilder.add("--main-dex-list=" + mainDexList.getExecPathString());
+ }
+ }
+
+ argBuilder.add("--output=" + intermediateDexOutput.getExecPathString());
+
+ assertThat(dexAction.getArguments()).containsAllIn(argBuilder.build()).inOrder();
+
+ // Final action: the SingleJar command that consumes the intermediate dex out to produce the
+ // final dex out.
+ SpawnAction singleJarAction = getGeneratingSpawnAction(finalDexOutput);
+ assertThat(singleJarAction.getArguments())
+ .containsAllOf(
+ "--exclude_build_data",
+ "--dont_change_compression",
+ "--sources",
+ intermediateDexOutput.getExecPathString(),
+ "--output",
+ finalDexOutput.getExecPathString(),
+ "--include_prefixes",
+ "classes")
+ .inOrder();
+ }
+
+ /**
+ * Internal helper method: given an android_binary rule label, check that it builds
+ * in non-multidex mode.
+ */
+ protected void internalTestNonMultidexBuildStructure(String ruleLabel) throws Exception {
+
+ ConfiguredTarget binary = getConfiguredTarget(ruleLabel);
+ Set<Artifact> artifacts = actionsTestUtil().artifactClosureOf(getFilesToBuild(binary));
+ Artifact dexOutput = getFirstArtifactEndingWith(artifacts, "classes.dex");
+ SpawnAction dexAction = (SpawnAction) getGeneratingAction(dexOutput);
+
+ assertThat(dexAction.getArguments()).doesNotContain("--multi-dex");
+ assertThat(dexAction.getArguments()).containsAllOf(
+ "--dex",
+ "--num-threads=5",
+ "--output=" + dexOutput.getExecPathString()).inOrder();
+ }
+}
+
diff --git a/src/test/java/com/google/devtools/build/lib/rules/android/BUILD b/src/test/java/com/google/devtools/build/lib/rules/android/BUILD
index b543ba853d..f7d7e1080e 100644
--- a/src/test/java/com/google/devtools/build/lib/rules/android/BUILD
+++ b/src/test/java/com/google/devtools/build/lib/rules/android/BUILD
@@ -129,3 +129,23 @@ java_test(
"//third_party:truth",
],
)
+
+java_test(
+ name = "AndroidBinaryMultidexTest",
+ srcs = [
+ "AndroidBinaryMultidexTest.java",
+ "AndroidMultidexBaseTest.java",
+ ],
+ deps = [
+ "//src/main/java/com/google/devtools/build/lib:android-rules",
+ "//src/main/java/com/google/devtools/build/lib:build-base",
+ "//src/main/java/com/google/devtools/build/lib:syntax",
+ "//src/main/java/com/google/devtools/build/lib/actions",
+ "//src/test/java/com/google/devtools/build/lib:actions_testutil",
+ "//src/test/java/com/google/devtools/build/lib:analysis_testutil",
+ "//src/test/java/com/google/devtools/build/lib:packages_testutil",
+ "//third_party:guava",
+ "//third_party:junit4",
+ "//third_party:truth",
+ ],
+)