aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar ajmichael <ajmichael@google.com>2017-08-29 00:41:40 +0200
committerGravatar Vladimir Moskva <vladmos@google.com>2017-08-29 13:33:04 +0200
commit69ef625b464093aaefd3d8af9e947832d4385211 (patch)
treecbc8f4c3a8cfce9adc0f89e9269720076a5e7921
parenta4c0e1a84029b2bad2310f7259ba6757fe706ac2 (diff)
aar_import creates res/values/empty.xml if it contains no resources.
To do this, add a new tool that is used instead of zipper to get the resources out of the AAR. This tool creates res/values/empty.xml if there are no resources in the AAR. Also, some general cleaning of the code. RELNOTES: None PiperOrigin-RevId: 166768607
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/android/AarImport.java60
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/android/AarImportBaseRule.java32
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/android/ApplicationManifest.java13
-rw-r--r--src/test/java/com/google/devtools/build/lib/analysis/mock/BazelAnalysisMock.java2
-rw-r--r--src/test/java/com/google/devtools/build/lib/rules/android/AarImportTest.java27
-rw-r--r--tools/android/BUILD29
-rw-r--r--tools/android/BUILD.tools12
-rw-r--r--tools/android/aar_resources_extractor.py58
-rw-r--r--tools/android/aar_resources_extractor_test.py64
9 files changed, 207 insertions, 90 deletions
diff --git a/src/main/java/com/google/devtools/build/lib/rules/android/AarImport.java b/src/main/java/com/google/devtools/build/lib/rules/android/AarImport.java
index 19ff508e3f..61295fc8e6 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/android/AarImport.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/android/AarImport.java
@@ -83,13 +83,9 @@ public class AarImport implements RuleConfiguredTargetFactory {
ruleContext.registerAction(createSingleFileExtractorActions(
ruleContext, aar, ANDROID_MANIFEST, androidManifestArtifact));
- Artifact resourcesManifest = createAarArtifact(ruleContext, "resource_manifest");
- ruleContext.registerAction(
- createManifestExtractorActions(ruleContext, aar, "res/.*", resourcesManifest));
-
Artifact resources = createAarTreeArtifact(ruleContext, "resources");
ruleContext.registerAction(
- createManifestFileEntriesExtractorActions(ruleContext, aar, resourcesManifest, resources));
+ createAarResourcesExtractorActions(ruleContext, aar, resources));
ApplicationManifest androidManifest =
ApplicationManifest.fromExplicitManifest(ruleContext, androidManifestArtifact);
@@ -110,8 +106,7 @@ public class AarImport implements RuleConfiguredTargetFactory {
ruleContext.getImplicitOutputArtifact(AndroidRuleClasses.ANDROID_R_TXT),
ruleContext.getImplicitOutputArtifact(AndroidRuleClasses.ANDROID_LOCAL_SYMBOLS),
ruleContext.getImplicitOutputArtifact(AndroidRuleClasses.ANDROID_PROCESSED_MANIFEST),
- resourcesZip,
- /* alwaysExportManifest = */ true);
+ resourcesZip);
// There isn't really any use case for building an aar_import target on its own, so the files to
// build could be empty. The resources zip and merged jars are added here as a sanity check for
@@ -123,8 +118,8 @@ public class AarImport implements RuleConfiguredTargetFactory {
Artifact nativeLibs = createAarArtifact(ruleContext, "native_libs.zip");
ruleContext.registerAction(createAarNativeLibsFilterActions(ruleContext, aar, nativeLibs));
- JavaRuleOutputJarsProvider.Builder jarProviderBuilder = new JavaRuleOutputJarsProvider.Builder()
- .addOutputJar(mergedJar, null, ImmutableList.<Artifact>of());
+ JavaRuleOutputJarsProvider.Builder jarProviderBuilder =
+ new JavaRuleOutputJarsProvider.Builder().addOutputJar(mergedJar, null, ImmutableList.of());
for (TransitiveInfoCollection export : ruleContext.getPrerequisites("exports", Mode.TARGET)) {
for (OutputJar jar :
JavaInfo.getProvider(JavaRuleOutputJarsProvider.class, export).getOutputJars()) {
@@ -134,13 +129,12 @@ public class AarImport implements RuleConfiguredTargetFactory {
}
ImmutableList<TransitiveInfoCollection> targets =
- ImmutableList.<TransitiveInfoCollection>copyOf(
- ruleContext.getPrerequisites("exports", Mode.TARGET));
+ ImmutableList.copyOf(ruleContext.getPrerequisites("exports", Mode.TARGET));
JavaCommon common =
new JavaCommon(
ruleContext,
javaSemantics,
- /* sources = */ ImmutableList.<Artifact>of(),
+ /* sources = */ ImmutableList.of(),
/* compileDeps = */ targets,
/* runtimeDeps = */ targets,
/* bothDeps = */ targets);
@@ -182,7 +176,7 @@ public class AarImport implements RuleConfiguredTargetFactory {
private static Action[] createSingleFileExtractorActions(RuleContext ruleContext, Artifact aar,
String filename, Artifact outputArtifact) {
return new SpawnAction.Builder()
- .setExecutable(ruleContext.getExecutablePrerequisite("$zipper", Mode.HOST))
+ .setExecutable(ruleContext.getExecutablePrerequisite(AarImportBaseRule.ZIPPER, Mode.HOST))
.setMnemonic("AarFileExtractor")
.setProgressMessage("Extracting %s from %s", filename, aar.getFilename())
.addInput(aar)
@@ -196,20 +190,20 @@ public class AarImport implements RuleConfiguredTargetFactory {
.build(ruleContext);
}
- private static Action[] createManifestFileEntriesExtractorActions(RuleContext ruleContext,
- Artifact aar, Artifact manifest, Artifact outputTree) {
+ private static Action[] createAarResourcesExtractorActions(
+ RuleContext ruleContext, Artifact aar, Artifact outputTree) {
return new SpawnAction.Builder()
- .setExecutable(ruleContext.getExecutablePrerequisite("$zipper", Mode.HOST))
- .setMnemonic("AarManifestFileEntriesExtractor")
+ .setExecutable(
+ ruleContext.getExecutablePrerequisite(
+ AarImportBaseRule.AAR_RESOURCES_EXTRACTOR, Mode.HOST))
+ .setMnemonic("AarResourcesExtractor")
.addInput(aar)
.addOutput(outputTree)
.setCommandLine(
CustomCommandLine.builder()
- .addExecPath("x", aar)
- .addExecPath("-d", outputTree)
- .addPrefixedExecPath("@", manifest)
+ .addExecPath("--input_aar", aar)
+ .addExecPath("--output_res_dir", outputTree)
.build())
- .addInput(manifest)
.build(ruleContext);
}
@@ -217,7 +211,8 @@ public class AarImport implements RuleConfiguredTargetFactory {
Artifact aar, Artifact jarsTreeArtifact, Artifact singleJarParamFile) {
return new SpawnAction.Builder()
.setExecutable(
- ruleContext.getExecutablePrerequisite("$aar_embedded_jars_extractor", Mode.HOST))
+ ruleContext.getExecutablePrerequisite(
+ AarImportBaseRule.AAR_EMBEDDED_JARS_EXTACTOR, Mode.HOST))
.setMnemonic("AarEmbeddedJarsExtractor")
.setProgressMessage("Extracting classes.jar and libs/*.jar from %s", aar.getFilename())
.addInput(aar)
@@ -249,30 +244,13 @@ public class AarImport implements RuleConfiguredTargetFactory {
.build(ruleContext);
}
- private static Action[] createManifestExtractorActions(RuleContext ruleContext, Artifact aar,
- String filenameRegexp, Artifact manifest) {
- return new SpawnAction.Builder()
- .setExecutable(ruleContext.getExecutablePrerequisite("$zip_manifest_creator", Mode.HOST))
- .setMnemonic("ZipManifestCreator")
- .setProgressMessage(
- "Creating manifest for %s matching %s", aar.getFilename(), filenameRegexp)
- .addInput(aar)
- .addOutput(manifest)
- .setCommandLine(
- CustomCommandLine.builder()
- .addDynamicString(filenameRegexp)
- .addExecPath(aar)
- .addExecPath(manifest)
- .build())
- .build(ruleContext);
- }
-
private static Action[] createAarNativeLibsFilterActions(RuleContext ruleContext, Artifact aar,
Artifact outputZip) {
SpawnAction.Builder actionBuilder =
new SpawnAction.Builder()
.setExecutable(
- ruleContext.getExecutablePrerequisite("$aar_native_libs_zip_creator", Mode.HOST))
+ ruleContext.getExecutablePrerequisite(
+ AarImportBaseRule.AAR_NATIVE_LIBS_ZIP_CREATOR, Mode.HOST))
.setMnemonic("AarNativeLibsFilter")
.setProgressMessage("Filtering AAR native libs by architecture")
.addInput(aar)
diff --git a/src/main/java/com/google/devtools/build/lib/rules/android/AarImportBaseRule.java b/src/main/java/com/google/devtools/build/lib/rules/android/AarImportBaseRule.java
index 530a04cc7d..52262de62a 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/android/AarImportBaseRule.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/android/AarImportBaseRule.java
@@ -21,7 +21,6 @@ import static com.google.devtools.build.lib.packages.BuildType.LABEL_LIST;
import com.google.devtools.build.lib.analysis.RuleDefinition;
import com.google.devtools.build.lib.analysis.RuleDefinitionEnvironment;
-import com.google.devtools.build.lib.cmdline.Label;
import com.google.devtools.build.lib.packages.RuleClass;
import com.google.devtools.build.lib.packages.RuleClass.Builder;
import com.google.devtools.build.lib.packages.RuleClass.Builder.RuleClassType;
@@ -32,15 +31,18 @@ import com.google.devtools.build.lib.util.FileType;
/** Rule definition for the aar_import rule. */
public class AarImportBaseRule implements RuleDefinition {
+ static final String AAR_EMBEDDED_JARS_EXTACTOR = "$aar_embedded_jars_extractor";
+ static final String AAR_NATIVE_LIBS_ZIP_CREATOR = "$aar_native_libs_zip_creator";
+ static final String AAR_RESOURCES_EXTRACTOR = "$aar_resources_extractor";
+ static final String ZIPPER = "$zipper";
+
@Override
- public RuleClass build(Builder builder, RuleDefinitionEnvironment environment) {
+ public RuleClass build(Builder builder, RuleDefinitionEnvironment env) {
return builder
/* <!-- #BLAZE_RULE($aar_import_base).ATTRIBUTE(aar) -->
The <code>.aar</code> file to provide to the Android targets that depend on this target.
<!-- #END_BLAZE_RULE.ATTRIBUTE --> */
- .add(attr("aar", LABEL)
- .mandatory()
- .allowedFileTypes(FileType.of(".aar")))
+ .add(attr("aar", LABEL).mandatory().allowedFileTypes(FileType.of(".aar")))
/* <!-- #BLAZE_RULE(aar_import).ATTRIBUTE(exports) -->
Targets to export to rules that depend on this rule.
See <a href="${link java_library.exports}">java_library.exports.
@@ -49,26 +51,22 @@ public class AarImportBaseRule implements RuleDefinition {
.allowedRuleClasses("aar_import", "java_import")
.allowedFileTypes()
.validityPredicate(ANY_EDGE))
- .add(attr("$aar_embedded_jars_extractor", LABEL)
+ .add(attr(AAR_EMBEDDED_JARS_EXTACTOR, LABEL)
.cfg(HOST)
.exec()
- .value(Label.parseAbsoluteUnchecked(
- environment.getToolsRepository() + "//tools/android:aar_embedded_jars_extractor")))
- .add(attr("$aar_native_libs_zip_creator", LABEL)
+ .value(env.getToolsLabel("//tools/android:aar_embedded_jars_extractor")))
+ .add(attr(AAR_NATIVE_LIBS_ZIP_CREATOR, LABEL)
.cfg(HOST)
.exec()
- .value(Label.parseAbsoluteUnchecked(
- environment.getToolsRepository() + "//tools/android:aar_native_libs_zip_creator")))
- .add(attr("$zip_manifest_creator", LABEL)
+ .value(env.getToolsLabel("//tools/android:aar_native_libs_zip_creator")))
+ .add(attr(AAR_RESOURCES_EXTRACTOR, LABEL)
.cfg(HOST)
.exec()
- .value(Label.parseAbsoluteUnchecked(
- environment.getToolsRepository() + "//tools/android:zip_manifest_creator")))
- .add(attr("$zipper", LABEL)
+ .value(env.getToolsLabel("//tools/android:aar_resources_extractor")))
+ .add(attr(ZIPPER, LABEL)
.cfg(HOST)
.exec()
- .value(Label.parseAbsoluteUnchecked(
- environment.getToolsRepository() + "//tools/zip:zipper")))
+ .value(env.getToolsLabel("//tools/zip:zipper")))
.advertiseProvider(JavaCompilationArgsProvider.class)
.build();
}
diff --git a/src/main/java/com/google/devtools/build/lib/rules/android/ApplicationManifest.java b/src/main/java/com/google/devtools/build/lib/rules/android/ApplicationManifest.java
index f15eba6697..f291995260 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/android/ApplicationManifest.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/android/ApplicationManifest.java
@@ -360,8 +360,7 @@ public final class ApplicationManifest {
Artifact rTxt,
Artifact symbols,
Artifact manifestOut,
- Artifact mergedResources,
- boolean alwaysExportManifest) throws InterruptedException, RuleErrorException {
+ Artifact mergedResources) throws InterruptedException, RuleErrorException {
if (ruleContext.hasErrors()) {
return null;
}
@@ -369,16 +368,14 @@ public final class ApplicationManifest {
ResourceContainer.builderFromRule(ruleContext)
.setRTxt(rTxt)
.setSymbols(symbols)
- .setJavaPackageFrom(JavaPackageSource.MANIFEST);
- if (alwaysExportManifest) {
- builder.setManifestExported(true);
- }
+ .setJavaPackageFrom(JavaPackageSource.MANIFEST)
+ .setManifestExported(true);
return createApk(
ruleContext,
true, /* isLibrary */
resourceDeps,
- ImmutableList.<String>of(), /* List<String> uncompressedExtensions */
+ ImmutableList.of(), /* List<String> uncompressedExtensions */
false, /* crunchPng */
false, /* incremental */
builder,
@@ -788,7 +785,7 @@ public final class ApplicationManifest {
List<String> uncompressedExtensions =
ruleContext.getTokenizedStringListAttr("nocompress_extensions");
- ImmutableList.Builder<String> additionalAaptOpts = ImmutableList.<String>builder();
+ ImmutableList.Builder<String> additionalAaptOpts = ImmutableList.builder();
for (String extension : uncompressedExtensions) {
additionalAaptOpts.add("-0").add(extension);
diff --git a/src/test/java/com/google/devtools/build/lib/analysis/mock/BazelAnalysisMock.java b/src/test/java/com/google/devtools/build/lib/analysis/mock/BazelAnalysisMock.java
index bd6ce313a4..f3525b3e4c 100644
--- a/src/test/java/com/google/devtools/build/lib/analysis/mock/BazelAnalysisMock.java
+++ b/src/test/java/com/google/devtools/build/lib/analysis/mock/BazelAnalysisMock.java
@@ -247,7 +247,7 @@ public final class BazelAnalysisMock extends AnalysisMock {
.add("java_binary(name = 'IdlClass',")
.add(" runtime_deps = [ ':idlclass_import' ],")
.add(" main_class = 'com.google.devtools.build.android.idlclass.IdlClass')")
- .add("sh_binary(name = 'zip_manifest_creator', srcs = ['empty.sh'])")
+ .add("sh_binary(name = 'aar_resources_extractor', srcs = ['empty.sh'])")
.add("sh_binary(name = 'aar_embedded_jars_extractor', srcs = ['empty.sh'])")
.add("java_import(name = 'idlclass_import',")
.add(" jars = [ 'idlclass.jar' ])")
diff --git a/src/test/java/com/google/devtools/build/lib/rules/android/AarImportTest.java b/src/test/java/com/google/devtools/build/lib/rules/android/AarImportTest.java
index 245698d347..bb52347a22 100644
--- a/src/test/java/com/google/devtools/build/lib/rules/android/AarImportTest.java
+++ b/src/test/java/com/google/devtools/build/lib/rules/android/AarImportTest.java
@@ -13,6 +13,7 @@
// limitations under the License.
package com.google.devtools.build.lib.rules.android;
+import static com.google.common.collect.Streams.stream;
import static com.google.common.truth.Truth.assertThat;
import com.google.common.base.Predicates;
@@ -21,6 +22,7 @@ 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.FileConfiguredTarget;
+import com.google.devtools.build.lib.analysis.FilesToRunProvider;
import com.google.devtools.build.lib.analysis.actions.SpawnAction;
import com.google.devtools.build.lib.analysis.util.BuildViewTestCase;
import com.google.devtools.build.lib.collect.nestedset.NestedSet;
@@ -86,6 +88,31 @@ public class AarImportTest extends BuildViewTestCase {
}
@Test
+ public void testResourcesExtractor() throws Exception {
+ AndroidResourcesProvider resourcesProvider =
+ getConfiguredTarget("//a:foo").getProvider(AndroidResourcesProvider.class);
+
+ Artifact resourceTreeArtifact =
+ stream(resourcesProvider.getDirectAndroidResources())
+ .flatMap(resourceContainer -> resourceContainer.getResources().stream())
+ .findFirst()
+ .get();
+ Artifact aarResourcesExtractor =
+ getHostConfiguredTarget(
+ ruleClassProvider.getToolsRepository() + "//tools/android:aar_resources_extractor")
+ .getProvider(FilesToRunProvider.class)
+ .getExecutable();
+
+ assertThat(getGeneratingSpawnAction(resourceTreeArtifact).getArguments())
+ .containsExactly(
+ aarResourcesExtractor.getExecPathString(),
+ "--input_aar",
+ "a/foo.aar",
+ "--output_res_dir",
+ resourceTreeArtifact.getExecPathString());
+ }
+
+ @Test
public void testNativeLibsProvided() throws Exception {
ConfiguredTarget androidLibraryTarget = getConfiguredTarget("//java:lib");
diff --git a/tools/android/BUILD b/tools/android/BUILD
index 19155c29f5..75a9956e67 100644
--- a/tools/android/BUILD
+++ b/tools/android/BUILD
@@ -120,23 +120,6 @@ py_test(
],
)
-sh_binary(
- name = "zip_manifest_creator",
- srcs = ["zip_manifest_creator.sh"],
- data = ["//tools/zip:zipper"],
-)
-
-sh_test(
- name = "zip_manifest_creator_test",
- size = "small",
- srcs = ["zip_manifest_creator_test.sh"],
- args = ["$(location //tools/zip:zipper)"],
- data = [
- ":zip_manifest_creator",
- "//tools/zip:zipper",
- ],
-)
-
py_binary(
name = "aar_embedded_jars_extractor",
srcs = ["aar_embedded_jars_extractor.py"],
@@ -150,6 +133,18 @@ py_test(
)
py_binary(
+ name = "aar_resources_extractor",
+ srcs = ["aar_resources_extractor.py"],
+ deps = ["//third_party/py/gflags"],
+)
+
+py_test(
+ name = "aar_resources_extractor_test",
+ srcs = ["aar_resources_extractor_test.py"],
+ deps = [":aar_resources_extractor"],
+)
+
+py_binary(
name = "resource_extractor",
srcs = ["resource_extractor.py"],
)
diff --git a/tools/android/BUILD.tools b/tools/android/BUILD.tools
index 866d6afcee..bc43e41509 100644
--- a/tools/android/BUILD.tools
+++ b/tools/android/BUILD.tools
@@ -151,12 +151,6 @@ sh_binary(
srcs = ["fail.sh"],
)
-sh_binary(
- name = "zip_manifest_creator",
- srcs = ["zip_manifest_creator.sh"],
- data = ["//tools/zip:zipper"],
-)
-
py_binary(
name = "aar_embedded_jars_extractor",
srcs = ["aar_embedded_jars_extractor.py"],
@@ -164,6 +158,12 @@ py_binary(
)
py_binary(
+ name = "aar_resources_extractor",
+ srcs = ["aar_resources_extractor.py"],
+ deps = ["//third_party/py/gflags"],
+)
+
+py_binary(
name = "resource_extractor",
srcs = ["resource_extractor.py"],
)
diff --git a/tools/android/aar_resources_extractor.py b/tools/android/aar_resources_extractor.py
new file mode 100644
index 0000000000..0e259b8028
--- /dev/null
+++ b/tools/android/aar_resources_extractor.py
@@ -0,0 +1,58 @@
+# pylint: disable=g-direct-third-party-import
+# 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.
+
+"""A tool for extracting resource files from an AAR.
+
+An AAR may contain resources under the /res directory. This tool extracts all
+of the resources into a directory. If no resources exist, it creates an
+empty.xml file that defines no resources.
+
+In the future, this script may be extended to also extract assets.
+"""
+
+import os
+import sys
+import zipfile
+
+from third_party.py import gflags
+
+FLAGS = gflags.FLAGS
+
+gflags.DEFINE_string("input_aar", None, "Input AAR")
+gflags.MarkFlagAsRequired("input_aar")
+gflags.DEFINE_string("output_res_dir", None, "Output resources directory")
+gflags.MarkFlagAsRequired("output_res_dir")
+
+
+def ExtractResources(aar, output_res_dir):
+ aar_contains_no_resources = True
+ for name in aar.namelist():
+ if name.startswith("res/"):
+ aar.extract(name, output_res_dir)
+ aar_contains_no_resources = False
+ if aar_contains_no_resources:
+ empty_xml_filename = output_res_dir + "/res/values/empty.xml"
+ os.makedirs(os.path.dirname(empty_xml_filename))
+ with open(empty_xml_filename, "wb") as empty_xml:
+ empty_xml.write("<resources/>")
+
+
+def main():
+ with zipfile.ZipFile(FLAGS.input_aar, "r") as aar:
+ ExtractResources(aar, FLAGS.output_res_dir)
+
+if __name__ == "__main__":
+ FLAGS(sys.argv)
+ main()
diff --git a/tools/android/aar_resources_extractor_test.py b/tools/android/aar_resources_extractor_test.py
new file mode 100644
index 0000000000..b59e4160cb
--- /dev/null
+++ b/tools/android/aar_resources_extractor_test.py
@@ -0,0 +1,64 @@
+# 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.
+
+"""Tests for aar_resources_extractor."""
+
+import os
+import shutil
+import StringIO
+import unittest
+import zipfile
+
+from tools.android import aar_resources_extractor
+
+
+class AarResourcesExtractorTest(unittest.TestCase):
+ """Unit tests for aar_resources_extractor.py."""
+
+ def setUp(self):
+ os.chdir(os.environ["TEST_TMPDIR"])
+
+ def tearDown(self):
+ shutil.rmtree("out_dir")
+
+ def DirContents(self, d):
+ return [path + "/" + f for (path, _, files) in os.walk(d)
+ for f in files]
+
+ def testNoResources(self):
+ aar = zipfile.ZipFile(StringIO.StringIO(), "w")
+ os.makedirs("out_dir")
+ aar_resources_extractor.ExtractResources(aar, "out_dir")
+ self.assertEqual(["out_dir/res/values/empty.xml"],
+ self.DirContents("out_dir"))
+ with open("out_dir/res/values/empty.xml", "r") as empty_xml:
+ self.assertEqual("<resources/>", empty_xml.read())
+
+ def testContainsResources(self):
+ aar = zipfile.ZipFile(StringIO.StringIO(), "w")
+ aar.writestr("res/values/values.xml", "some values")
+ aar.writestr("res/layouts/layout.xml", "some layout")
+ os.makedirs("out_dir")
+ aar_resources_extractor.ExtractResources(aar, "out_dir")
+ expected_resources = ["out_dir/res/values/values.xml",
+ "out_dir/res/layouts/layout.xml"]
+ self.assertItemsEqual(expected_resources, self.DirContents("out_dir"))
+ with open("out_dir/res/values/values.xml", "r") as values_xml:
+ self.assertEqual("some values", values_xml.read())
+ with open("out_dir/res/layouts/layout.xml", "r") as layout_xml:
+ self.assertEqual("some layout", layout_xml.read())
+
+
+if __name__ == "__main__":
+ unittest.main()