Move dump utilities into AndroidApp.
This CL also adds handling of duplicates and prepares for allowing compilation to continue after dumping inputs.
Change-Id: If1458c00aa1ac4ce3505109a4d78168705c8f536
diff --git a/src/main/java/com/android/tools/r8/dex/ApplicationReader.java b/src/main/java/com/android/tools/r8/dex/ApplicationReader.java
index 6e95cac..4549d8e 100644
--- a/src/main/java/com/android/tools/r8/dex/ApplicationReader.java
+++ b/src/main/java/com/android/tools/r8/dex/ApplicationReader.java
@@ -7,17 +7,14 @@
import static com.android.tools.r8.graph.ClassKind.LIBRARY;
import static com.android.tools.r8.graph.ClassKind.PROGRAM;
import static com.android.tools.r8.utils.ExceptionUtils.unwrapExecutionException;
-import static com.android.tools.r8.utils.InternalOptions.ASM_VERSION;
import com.android.tools.r8.ClassFileResourceProvider;
-import com.android.tools.r8.DataEntryResource;
import com.android.tools.r8.DataResourceProvider;
import com.android.tools.r8.ProgramResource;
import com.android.tools.r8.ProgramResource.Kind;
import com.android.tools.r8.ProgramResourceProvider;
import com.android.tools.r8.ResourceException;
import com.android.tools.r8.StringResource;
-import com.android.tools.r8.Version;
import com.android.tools.r8.errors.CompilationError;
import com.android.tools.r8.graph.ClassKind;
import com.android.tools.r8.graph.DexApplication;
@@ -43,38 +40,26 @@
import com.android.tools.r8.utils.StringDiagnostic;
import com.android.tools.r8.utils.ThreadUtils;
import com.android.tools.r8.utils.Timing;
-import com.android.tools.r8.utils.ZipUtils;
-import com.google.common.collect.ImmutableSet;
-import com.google.common.io.ByteStreams;
-import com.google.common.io.Closer;
-import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
-import java.nio.file.Files;
-import java.nio.file.OpenOption;
import java.nio.file.Paths;
-import java.nio.file.StandardOpenOption;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Queue;
-import java.util.Set;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.stream.Collectors;
-import java.util.zip.ZipEntry;
-import java.util.zip.ZipOutputStream;
-import org.objectweb.asm.ClassVisitor;
public class ApplicationReader {
private final InternalOptions options;
private final DexItemFactory itemFactory;
private final Timing timing;
- private final AndroidApp inputApp;
+ private AndroidApp inputApp;
public interface ProgramClassConflictResolver {
DexProgramClass resolveClassConflict(DexProgramClass a, DexProgramClass b);
@@ -123,7 +108,7 @@
throws IOException, ExecutionException {
assert verifyMainDexOptionsCompatible(inputApp, options);
if (options.dumpInputToFile != null) {
- dumpInputToFile();
+ inputApp = dumpInputToFile(inputApp, options);
throw options.reporter.fatalError("Dumped compilation inputs to: " + options.dumpInputToFile);
}
timing.begin("DexApplication.read");
@@ -160,141 +145,9 @@
return builder.build();
}
- private void dumpInputToFile() throws IOException {
- try {
- List<ProgramResourceProvider> programResourceProviders =
- inputApp.getProgramResourceProviders();
- Set<DataEntryResource> dataEntryResources = inputApp.getDataEntryResourcesForTesting();
- List<ProgramResource> programResourcesWithDescriptors = new ArrayList<>();
- for (ProgramResourceProvider programResourceProvider : programResourceProviders) {
- addProgramResourcesWithDescriptor(
- programResourcesWithDescriptors, programResourceProvider.getProgramResources());
- }
-
- List<ProgramResource> libraryProgramResourcesWithDescriptors =
- getProgramResourcesWithDescriptors(inputApp.getLibraryResourceProviders());
-
- List<ProgramResource> classpathProgramResourcesWithDescriptors =
- getProgramResourcesWithDescriptors(inputApp.getClasspathResourceProviders());
-
- OpenOption[] openOptions =
- new OpenOption[] {StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING};
- try (Closer closer = Closer.create()) {
- try (ZipOutputStream out =
- new ZipOutputStream(
- Files.newOutputStream(Paths.get(options.dumpInputToFile), openOptions))) {
- writeToZip(
- dataEntryResources, programResourcesWithDescriptors, closer, out, "program.jar");
- writeToZip(
- ImmutableSet.of(),
- libraryProgramResourcesWithDescriptors,
- closer,
- out,
- "library.jar");
- writeToZip(
- ImmutableSet.of(),
- classpathProgramResourcesWithDescriptors,
- closer,
- out,
- "classpath.jar");
- if (options.hasProguardConfiguration()) {
- String proguardConfig = options.getProguardConfiguration().getParsedConfiguration();
- ZipUtils.writeToZipStream(
- out, "proguard.config", proguardConfig.getBytes(), ZipEntry.DEFLATED);
- }
-
- ZipUtils.writeToZipStream(
- out, "r8-version", Version.getVersionString().getBytes(), ZipEntry.DEFLATED);
- }
- }
- } catch (ResourceException e) {
- options.reporter.fatalError("Failed to write input:" + e.getMessage());
- }
- }
-
- private static void writeToZip(
- Set<DataEntryResource> dataEntryResources,
- List<ProgramResource> programResourcesWithDescriptors,
- Closer closer,
- ZipOutputStream out,
- String entry)
- throws IOException, ResourceException {
- try (ByteArrayOutputStream programByteStream = new ByteArrayOutputStream()) {
- try (ZipOutputStream archiveOutputStream = new ZipOutputStream(programByteStream)) {
- ZipUtils.writeResourcesToZip(
- programResourcesWithDescriptors, dataEntryResources, closer, archiveOutputStream);
- }
- ZipUtils.writeToZipStream(out, entry, programByteStream.toByteArray(), ZipEntry.DEFLATED);
- }
- }
-
- private static List<ProgramResource> getProgramResourcesWithDescriptors(
- List<ClassFileResourceProvider> classFileResourceProviders)
- throws IOException, ResourceException {
- ArrayList<ProgramResource> programResourcesWithDescriptors = new ArrayList<>();
- for (ClassFileResourceProvider libraryResourceProvider : classFileResourceProviders) {
- List<ProgramResource> programResources = new ArrayList<>();
- for (String classDescriptor : libraryResourceProvider.getClassDescriptors()) {
- programResources.add(libraryResourceProvider.getProgramResource(classDescriptor));
- }
- addProgramResourcesWithDescriptor(programResourcesWithDescriptors, programResources);
- }
- return programResourcesWithDescriptors;
- }
-
- private static void addProgramResourcesWithDescriptor(
- List<ProgramResource> programResourcesWithDescriptors,
- Collection<ProgramResource> programResources)
- throws IOException, ResourceException {
- for (ProgramResource programResource : programResources) {
- if (programResource.getKind() != Kind.CF) {
- continue;
- }
- try (InputStream inputStream = programResource.getByteStream()) {
- byte[] bytes = ByteStreams.toByteArray(inputStream);
- String descriptor = extractClassInternalType(bytes);
- programResourcesWithDescriptors.add(
- ProgramResource.fromBytes(
- programResource.getOrigin(),
- programResource.getKind(),
- bytes,
- ImmutableSet.of(descriptor)));
- }
- }
- }
-
- private static String extractClassInternalType(byte[] bytes) throws IOException {
- class ClassNameExtractor extends ClassVisitor {
- private String className;
-
- private ClassNameExtractor() {
- super(ASM_VERSION);
- }
-
- @Override
- public void visit(
- int version,
- int access,
- String name,
- String signature,
- String superName,
- String[] interfaces) {
- className = name;
- }
-
- String getDescriptor() {
- return "L" + className + ";";
- }
- }
-
- org.objectweb.asm.ClassReader reader = new org.objectweb.asm.ClassReader(bytes);
- ClassNameExtractor extractor = new ClassNameExtractor();
- reader.accept(
- extractor,
- org.objectweb.asm.ClassReader.SKIP_CODE
- | org.objectweb.asm.ClassReader.SKIP_DEBUG
- | org.objectweb.asm.ClassReader.SKIP_FRAMES);
- return extractor.getDescriptor();
+ private static AndroidApp dumpInputToFile(AndroidApp app, InternalOptions options) {
+ return app.dump(
+ Paths.get(options.dumpInputToFile), options.getProguardConfiguration(), options.reporter);
}
private static boolean verifyMainDexOptionsCompatible(
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 1c3af7a..14f705e 100644
--- a/src/main/java/com/android/tools/r8/utils/AndroidApp.java
+++ b/src/main/java/com/android/tools/r8/utils/AndroidApp.java
@@ -7,6 +7,8 @@
import static com.android.tools.r8.utils.FileUtils.isArchive;
import static com.android.tools.r8.utils.FileUtils.isClassFile;
import static com.android.tools.r8.utils.FileUtils.isDexFile;
+import static com.android.tools.r8.utils.InternalOptions.ASM_VERSION;
+import static com.android.tools.r8.utils.ZipUtils.writeToZipStream;
import com.android.tools.r8.ClassFileConsumer;
import com.android.tools.r8.ClassFileResourceProvider;
@@ -25,28 +27,39 @@
import com.android.tools.r8.Resource;
import com.android.tools.r8.ResourceException;
import com.android.tools.r8.StringResource;
+import com.android.tools.r8.Version;
import com.android.tools.r8.errors.CompilationError;
import com.android.tools.r8.errors.InternalCompilerError;
import com.android.tools.r8.errors.Unreachable;
import com.android.tools.r8.origin.Origin;
import com.android.tools.r8.origin.PathOrigin;
import com.android.tools.r8.shaking.FilteredClassPath;
+import com.android.tools.r8.shaking.ProguardConfiguration;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.io.ByteStreams;
+import java.io.ByteArrayOutputStream;
import java.io.IOException;
+import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.NoSuchFileException;
+import java.nio.file.OpenOption;
import java.nio.file.Path;
+import java.nio.file.StandardOpenOption;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
+import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
+import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipOutputStream;
+import org.objectweb.asm.ClassVisitor;
/**
* Collection of program files needed for processing.
@@ -382,6 +395,154 @@
return programResourcesMainDescriptor.get(resource);
}
+ public AndroidApp dump(Path output, ProguardConfiguration configuration, Reporter reporter) {
+ int nextDexIndex = 0;
+ Builder builder = AndroidApp.builder(reporter);
+ OpenOption[] openOptions =
+ new OpenOption[] {StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING};
+ try (ZipOutputStream out = new ZipOutputStream(Files.newOutputStream(output, openOptions))) {
+ writeToZipStream(out, "r8-version", Version.getVersionString().getBytes(), ZipEntry.DEFLATED);
+ if (configuration != null) {
+ String proguardConfig = configuration.getParsedConfiguration();
+ writeToZipStream(out, "proguard.config", proguardConfig.getBytes(), ZipEntry.DEFLATED);
+ }
+ nextDexIndex = dumpProgramResources("program.jar", nextDexIndex, out, builder);
+ nextDexIndex =
+ dumpClassFileResources(
+ "classpath.jar", nextDexIndex, out, builder, classpathResourceProviders);
+ nextDexIndex =
+ dumpClassFileResources(
+ "library.jar", nextDexIndex, out, builder, libraryResourceProviders);
+ } catch (IOException | ResourceException e) {
+ reporter.fatalError(new StringDiagnostic("Failed to dump inputs"), e);
+ }
+ return builder.build();
+ }
+
+ private int dumpProgramResources(
+ String archiveName, int nextDexIndex, ZipOutputStream out, Builder builder)
+ throws IOException, ResourceException {
+ try (ByteArrayOutputStream archiveByteStream = new ByteArrayOutputStream()) {
+ try (ZipOutputStream archiveOutputStream = new ZipOutputStream(archiveByteStream)) {
+ Set<String> seen = new HashSet<>();
+ Set<DataEntryResource> dataEntries = getDataEntryResourcesForTesting();
+ for (DataEntryResource dataResource : dataEntries) {
+ builder.addDataResources(dataResource);
+ String entryName = dataResource.getName();
+ try (InputStream dataStream = dataResource.getByteStream()) {
+ byte[] bytes = ByteStreams.toByteArray(dataStream);
+ writeToZipStream(out, entryName, bytes, ZipEntry.DEFLATED);
+ }
+ }
+ for (ProgramResourceProvider provider : programResourceProviders) {
+ for (ProgramResource programResource : provider.getProgramResources()) {
+ nextDexIndex =
+ dumpProgramResource(
+ builder, seen, nextDexIndex, archiveOutputStream, programResource);
+ }
+ }
+ }
+ writeToZipStream(out, archiveName, archiveByteStream.toByteArray(), ZipEntry.DEFLATED);
+ }
+ return nextDexIndex;
+ }
+
+ private static int dumpClassFileResources(
+ String archiveName,
+ int nextDexIndex,
+ ZipOutputStream out,
+ Builder builder,
+ ImmutableList<ClassFileResourceProvider> classpathResourceProviders)
+ throws IOException, ResourceException {
+ try (ByteArrayOutputStream archiveByteStream = new ByteArrayOutputStream()) {
+ try (ZipOutputStream archiveOutputStream = new ZipOutputStream(archiveByteStream)) {
+ Set<String> seen = new HashSet<>();
+ for (ClassFileResourceProvider provider : classpathResourceProviders) {
+ for (String descriptor : provider.getClassDescriptors()) {
+ ProgramResource programResource = provider.getProgramResource(descriptor);
+ int oldDexIndex = nextDexIndex;
+ nextDexIndex =
+ dumpProgramResource(
+ builder, seen, nextDexIndex, archiveOutputStream, programResource);
+ assert nextDexIndex == oldDexIndex;
+ }
+ }
+ }
+ writeToZipStream(out, archiveName, archiveByteStream.toByteArray(), ZipEntry.DEFLATED);
+ }
+ return nextDexIndex;
+ }
+
+ private static int dumpProgramResource(
+ Builder builder,
+ Set<String> seen,
+ int nextDexIndex,
+ ZipOutputStream archiveOutputStream,
+ ProgramResource programResource)
+ throws ResourceException, IOException {
+ byte[] bytes = ByteStreams.toByteArray(programResource.getByteStream());
+ Set<String> classDescriptors = programResource.getClassDescriptors();
+ if (classDescriptors.size() != 1 && programResource.getKind() == Kind.CF) {
+ classDescriptors = Collections.singleton(extractClassDescriptor(bytes));
+ }
+ if (programResource instanceof OneShotByteResource) {
+ builder.addProgramResources(
+ OneShotByteResource.create(
+ programResource.getKind(), programResource.getOrigin(), bytes, classDescriptors));
+
+ } else {
+ builder.addProgramResources(programResource);
+ }
+ String entryName;
+ if (programResource.getKind() == Kind.CF) {
+ String classDescriptor =
+ classDescriptors.size() == 1
+ ? classDescriptors.iterator().next()
+ : extractClassDescriptor(bytes);
+ String classFileName = DescriptorUtils.getClassFileName(classDescriptor);
+ entryName = seen.add(classDescriptor) ? classFileName : (classFileName + ".dup");
+ } else {
+ assert programResource.getKind() == Kind.DEX;
+ entryName = "classes" + nextDexIndex++ + ".dex";
+ }
+ writeToZipStream(archiveOutputStream, entryName, bytes, ZipEntry.DEFLATED);
+ return nextDexIndex;
+ }
+
+ private static String extractClassDescriptor(byte[] bytes) {
+ class ClassNameExtractor extends ClassVisitor {
+ private String className;
+
+ private ClassNameExtractor() {
+ super(ASM_VERSION);
+ }
+
+ @Override
+ public void visit(
+ int version,
+ int access,
+ String name,
+ String signature,
+ String superName,
+ String[] interfaces) {
+ className = name;
+ }
+
+ String getDescriptor() {
+ return "L" + className + ";";
+ }
+ }
+
+ org.objectweb.asm.ClassReader reader = new org.objectweb.asm.ClassReader(bytes);
+ ClassNameExtractor extractor = new ClassNameExtractor();
+ reader.accept(
+ extractor,
+ org.objectweb.asm.ClassReader.SKIP_CODE
+ | org.objectweb.asm.ClassReader.SKIP_DEBUG
+ | org.objectweb.asm.ClassReader.SKIP_FRAMES);
+ return extractor.getDescriptor();
+ }
+
/**
* Builder interface for constructing an AndroidApp.
*/
diff --git a/src/main/java/com/android/tools/r8/utils/OneShotByteResource.java b/src/main/java/com/android/tools/r8/utils/OneShotByteResource.java
index da958c3..1dfbc64 100644
--- a/src/main/java/com/android/tools/r8/utils/OneShotByteResource.java
+++ b/src/main/java/com/android/tools/r8/utils/OneShotByteResource.java
@@ -17,7 +17,7 @@
private byte[] bytes;
private final Set<String> classDescriptors;
- static ProgramResource create(
+ public static OneShotByteResource create(
Kind kind, Origin origin, byte[] bytes, Set<String> classDescriptors) {
return new OneShotByteResource(origin, kind, bytes, classDescriptors);
}
diff --git a/src/test/java/com/android/tools/r8/DumpInputsTest.java b/src/test/java/com/android/tools/r8/DumpInputsTest.java
new file mode 100644
index 0000000..3c2d9b3
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/DumpInputsTest.java
@@ -0,0 +1,72 @@
+// Copyright (c) 2019, the R8 project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+package com.android.tools.r8;
+
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import com.android.tools.r8.TestRuntime.CfVm;
+import com.android.tools.r8.utils.DescriptorUtils;
+import com.android.tools.r8.utils.StringUtils;
+import com.android.tools.r8.utils.ZipUtils;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.HashSet;
+import java.util.Set;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+@RunWith(Parameterized.class)
+public class DumpInputsTest extends TestBase {
+
+ static final String EXPECTED = StringUtils.lines("Hello, world");
+
+ private final TestParameters parameters;
+
+ @Parameterized.Parameters(name = "{0}")
+ public static TestParametersCollection data() {
+ return getTestParameters().withCfRuntime(CfVm.JDK9).build();
+ }
+
+ public DumpInputsTest(TestParameters parameters) {
+ this.parameters = parameters;
+ }
+
+ @Test
+ public void test() throws Exception {
+ Path dump = temp.newFolder().toPath().resolve("dump.zip");
+ try {
+ testForExternalR8(parameters.getBackend())
+ .useExternalJDK(parameters.getRuntime().asCf().getVm())
+ .addJvmFlag("-Dcom.android.tools.r8.dumpinputtofile=" + dump)
+ .addProgramClasses(TestClass.class)
+ .compile();
+ } catch (AssertionError e) {
+ assertTrue(Files.exists(dump));
+ Path unzipped = temp.newFolder().toPath();
+ ZipUtils.unzip(dump.toString(), unzipped.toFile());
+ assertTrue(Files.exists(unzipped.resolve("program.jar")));
+ assertTrue(Files.exists(unzipped.resolve("classpath.jar")));
+ assertTrue(Files.exists(unzipped.resolve("proguard.config")));
+ assertTrue(Files.exists(unzipped.resolve("r8-version")));
+ Set<String> entries = new HashSet<>();
+ ZipUtils.iter(
+ unzipped.resolve("program.jar").toString(),
+ (entry, input) -> entries.add(entry.getName()));
+ assertTrue(
+ entries.contains(
+ DescriptorUtils.getClassFileName(
+ DescriptorUtils.javaTypeToDescriptor(TestClass.class.getTypeName()))));
+ return;
+ }
+ fail("Expected external compilation to exit");
+ }
+
+ static class TestClass {
+ public static void main(String[] args) {
+ System.out.println("Hello, world");
+ }
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/ExternalR8TestBuilder.java b/src/test/java/com/android/tools/r8/ExternalR8TestBuilder.java
index 0328184..ae4a36c 100644
--- a/src/test/java/com/android/tools/r8/ExternalR8TestBuilder.java
+++ b/src/test/java/com/android/tools/r8/ExternalR8TestBuilder.java
@@ -57,6 +57,8 @@
private boolean addR8ExternalDeps = false;
+ private List<String> jvmFlags = new ArrayList<>();
+
private ExternalR8TestBuilder(TestState state, Builder builder, Backend backend) {
super(state, builder, backend);
}
@@ -72,7 +74,7 @@
public ExternalR8TestBuilder useExternalJDK(CfVm externalJDK) {
this.externalJDK = externalJDK;
- return this;
+ return self();
}
private String getJDKToRun() {
@@ -82,6 +84,11 @@
return getJavaExecutable(externalJDK);
}
+ public ExternalR8TestBuilder addJvmFlag(String flag) {
+ jvmFlags.add(flag);
+ return self();
+ }
+
@Override
ExternalR8TestCompileResult internalCompile(
Builder builder, Consumer<InternalOptions> optionsConsumer, Supplier<AndroidApp> app)
@@ -99,9 +106,12 @@
: r8jar.toAbsolutePath().toString();
List<String> command = new ArrayList<>();
+ Collections.addAll(command, getJDKToRun());
+
+ command.addAll(jvmFlags);
+
Collections.addAll(
command,
- getJDKToRun(),
"-ea",
"-cp",
classPath,
diff --git a/src/test/java/com/android/tools/r8/R8EntryPointTests.java b/src/test/java/com/android/tools/r8/R8EntryPointTests.java
index 553ff0e..0bbc7bc 100644
--- a/src/test/java/com/android/tools/r8/R8EntryPointTests.java
+++ b/src/test/java/com/android/tools/r8/R8EntryPointTests.java
@@ -9,20 +9,13 @@
import com.android.tools.r8.ToolHelper.ProcessResult;
import com.android.tools.r8.utils.FileUtils;
-import com.android.tools.r8.utils.ZipUtils;
-import com.android.tools.r8.utils.ZipUtils.OnEntryHandler;
import com.google.common.collect.ImmutableList;
import java.io.IOException;
-import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
-import java.util.zip.ZipEntry;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
@@ -180,53 +173,6 @@
}
@Test
- public void testDumpInputs() throws IOException {
- Path out = temp.newFile("dex.zip").toPath();
- Path dump = temp.newFile("dump.zip").toPath();
- ProcessResult r8 =
- ToolHelper.forkR8WithJavaOptions(
- Paths.get("."),
- ImmutableList.of("-Dcom.android.tools.r8.dumpinputtofile=" + dump.toString()),
- "--lib",
- ToolHelper.getDefaultAndroidJar().toString(),
- "--dex",
- "--output",
- out.toString(),
- "--pg-conf",
- PROGUARD_FLAGS.toString(),
- "--pg-conf",
- testFlags.toString(),
- INPUT_JAR.toString());
-
- List<ZipEntry> entries = new ArrayList<>();
- ZipUtils.iter(
- dump.toString(),
- new OnEntryHandler() {
- @Override
- public void onEntry(ZipEntry entry, InputStream input) throws IOException {
- entries.add(entry);
- }
- });
- Assert.assertTrue(hasEntry(entries, "program.jar"));
- Assert.assertTrue(hasEntry(entries, "library.jar"));
- Assert.assertTrue(hasEntry(entries, "classpath.jar"));
- Assert.assertTrue(hasEntry(entries, "proguard.config"));
- Assert.assertTrue(hasEntry(entries, "r8-version"));
- // When dumping the inputs we throw an error in the program to exit early.
- Assert.assertNotEquals(0, r8.exitCode);
- }
-
- private boolean hasEntry(Collection<ZipEntry> entries, String name) {
- for (ZipEntry entry : entries) {
- if (entry.getName().equals(name)) {
- return true;
- }
- }
-
- return false;
- }
-
- @Test
public void testSpecifyDexAndClassfileNotAllowed() throws IOException, InterruptedException {
Path out = temp.newFile("dex.zip").toPath();
ProcessResult r8 =