Add tests and support for data resources to the dump file.
Change-Id: I48638f47cd93157a77d6e89fbbad2cca841ccfce
diff --git a/src/main/java/com/android/tools/r8/utils/AndroidApp.java b/src/main/java/com/android/tools/r8/utils/AndroidApp.java
index 110308d..3f57203 100644
--- a/src/main/java/com/android/tools/r8/utils/AndroidApp.java
+++ b/src/main/java/com/android/tools/r8/utils/AndroidApp.java
@@ -443,7 +443,7 @@
String entryName = dataResource.getName();
try (InputStream dataStream = dataResource.getByteStream()) {
byte[] bytes = ByteStreams.toByteArray(dataStream);
- writeToZipStream(out, entryName, bytes, ZipEntry.DEFLATED);
+ writeToZipStream(archiveOutputStream, entryName, bytes, ZipEntry.DEFLATED);
}
}
for (ProgramResourceProvider provider : programResourceProviders) {
@@ -616,6 +616,8 @@
readClassFileDump(origin, input, this::addClasspathResourceProvider, "classpath");
} else if (name.equals(dumpLibraryFileName)) {
readClassFileDump(origin, input, this::addLibraryResourceProvider, "library");
+ } else {
+ System.out.println("WARNING: Unexpected dump file entry: " + entry.getName());
}
});
return this;
@@ -667,6 +669,8 @@
}
private void readProgramDump(Origin origin, InputStream input) throws IOException {
+ List<ProgramResource> programResources = new ArrayList<>();
+ List<DataEntryResource> dataResources = new ArrayList<>();
try (ZipInputStream stream = new ZipInputStream(input)) {
ZipEntry entry;
while (null != (entry = stream.getNextEntry())) {
@@ -680,18 +684,44 @@
entryOrigin,
ByteStreams.toByteArray(stream),
Collections.singleton(descriptor));
- addProgramResources(resource);
+ programResources.add(resource);
} else if (ZipUtils.isDexFile(name)) {
Origin entryOrigin = new ArchiveEntryOrigin(name, origin);
ProgramResource resource =
OneShotByteResource.create(
Kind.DEX, entryOrigin, ByteStreams.toByteArray(stream), null);
- addProgramResources(resource);
+ programResources.add(resource);
} else if (name.endsWith(".dup")) {
System.out.println("WARNING: Duplicate program resource: " + name);
+ } else {
+ dataResources.add(
+ DataEntryResource.fromBytes(ByteStreams.toByteArray(stream), name, origin));
}
}
}
+ if (!programResources.isEmpty() || !dataResources.isEmpty()) {
+ addProgramResourceProvider(
+ new ProgramResourceProvider() {
+ @Override
+ public Collection<ProgramResource> getProgramResources() throws ResourceException {
+ return programResources;
+ }
+
+ @Override
+ public DataResourceProvider getDataResourceProvider() {
+ return dataResources.isEmpty()
+ ? null
+ : new DataResourceProvider() {
+ @Override
+ public void accept(Visitor visitor) throws ResourceException {
+ for (DataEntryResource dataResource : dataResources) {
+ visitor.visit(dataResource);
+ }
+ }
+ };
+ }
+ });
+ }
}
/** Add program file resources. */
diff --git a/src/test/java/com/android/tools/r8/AndroidAppDumpsTest.java b/src/test/java/com/android/tools/r8/AndroidAppDumpsTest.java
index 2579acb..04c4bf2 100644
--- a/src/test/java/com/android/tools/r8/AndroidAppDumpsTest.java
+++ b/src/test/java/com/android/tools/r8/AndroidAppDumpsTest.java
@@ -4,15 +4,21 @@
package com.android.tools.r8;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import com.android.tools.r8.DataResourceProvider.Visitor;
import com.android.tools.r8.ProgramResource.Kind;
import com.android.tools.r8.origin.Origin;
import com.android.tools.r8.utils.AndroidApiLevel;
import com.android.tools.r8.utils.AndroidApp;
+import com.android.tools.r8.utils.Box;
import com.android.tools.r8.utils.DescriptorUtils;
import com.android.tools.r8.utils.Reporter;
+import java.io.ByteArrayInputStream;
import java.io.IOException;
+import java.io.InputStream;
import java.nio.file.Path;
+import java.util.Collection;
import java.util.Collections;
import java.util.Set;
import org.junit.Test;
@@ -35,10 +41,14 @@
@Test
public void test() throws Exception {
+ Reporter reporter = new Reporter();
+
+ String dataResourceName = "my-resource.bin";
+ byte[] dataResourceData = new byte[] {1, 2, 3};
+
Path dexForB =
testForD8().addProgramClasses(B.class).setMinApi(AndroidApiLevel.B).compile().writeToZip();
- Reporter reporter = new Reporter();
AndroidApp appIn =
AndroidApp.builder(reporter)
.addClassProgramData(ToolHelper.getClassAsBytes(A.class), origin("A"))
@@ -51,6 +61,9 @@
.addLibraryResourceProvider(provider(C.class))
.addLibraryResourceProvider(provider(C.class))
.addLibraryResourceProvider(provider(C.class))
+ .addProgramResourceProvider(
+ createDataResourceProvider(
+ dataResourceName, dataResourceData, origin(dataResourceName)))
.build();
Path dumpFile = temp.newFolder().toPath().resolve("dump.zip");
@@ -73,6 +86,62 @@
assertEquals(
DescriptorUtils.javaTypeToDescriptor(C.class.getTypeName()),
appOut.getLibraryResourceProviders().get(0).getClassDescriptors().iterator().next());
+
+ Box<Boolean> foundData = new Box<>(false);
+ for (ProgramResourceProvider provider : appOut.getProgramResourceProviders()) {
+ DataResourceProvider dataProvider = provider.getDataResourceProvider();
+ if (dataProvider != null) {
+ dataProvider.accept(
+ new Visitor() {
+ @Override
+ public void visit(DataDirectoryResource directory) {}
+
+ @Override
+ public void visit(DataEntryResource file) {
+ if (file.getName().equals(dataResourceName)) {
+ foundData.set(true);
+ }
+ }
+ });
+ }
+ }
+ assertTrue(foundData.get());
+ }
+
+ private ProgramResourceProvider createDataResourceProvider(
+ String name, byte[] content, Origin origin) {
+ return new ProgramResourceProvider() {
+ @Override
+ public Collection<ProgramResource> getProgramResources() throws ResourceException {
+ return Collections.emptyList();
+ }
+
+ @Override
+ public DataResourceProvider getDataResourceProvider() {
+ return new DataResourceProvider() {
+ @Override
+ public void accept(Visitor visitor) throws ResourceException {
+ visitor.visit(
+ new DataEntryResource() {
+ @Override
+ public InputStream getByteStream() throws ResourceException {
+ return new ByteArrayInputStream(content);
+ }
+
+ @Override
+ public String getName() {
+ return name;
+ }
+
+ @Override
+ public Origin getOrigin() {
+ return origin;
+ }
+ });
+ }
+ };
+ }
+ };
}
private Origin origin(String name) {