Merge "Add a test for b/114554345"
diff --git a/src/main/java/com/android/tools/r8/BaseCommand.java b/src/main/java/com/android/tools/r8/BaseCommand.java
index 8828248..a537d7f 100644
--- a/src/main/java/com/android/tools/r8/BaseCommand.java
+++ b/src/main/java/com/android/tools/r8/BaseCommand.java
@@ -172,7 +172,7 @@
try {
app.addProgramFile(path);
programFiles.add(path);
- } catch (IOException | CompilationError e) {
+ } catch (CompilationError e) {
error(new ProgramInputOrigin(path), e);
}
});
diff --git a/src/main/java/com/android/tools/r8/CompatDxHelper.java b/src/main/java/com/android/tools/r8/CompatDxHelper.java
index f540ed0..a84bab5 100644
--- a/src/main/java/com/android/tools/r8/CompatDxHelper.java
+++ b/src/main/java/com/android/tools/r8/CompatDxHelper.java
@@ -6,10 +6,10 @@
import com.android.tools.r8.utils.AndroidApp;
import com.android.tools.r8.utils.InternalOptions;
-import java.io.IOException;
public class CompatDxHelper {
- public static void run(D8Command command, Boolean minimalMainDex) throws IOException {
+ public static void run(D8Command command, Boolean minimalMainDex)
+ throws CompilationFailedException {
AndroidApp app = command.getInputApp();
InternalOptions options = command.getInternalOptions();
// DX does not desugar.
diff --git a/src/main/java/com/android/tools/r8/D8.java b/src/main/java/com/android/tools/r8/D8.java
index 76e7277..68d9095 100644
--- a/src/main/java/com/android/tools/r8/D8.java
+++ b/src/main/java/com/android/tools/r8/D8.java
@@ -110,7 +110,7 @@
}
InternalOptions options = command.getInternalOptions();
AndroidApp app = command.getInputApp();
- ExceptionUtils.withD8CompilationHandler(options.reporter, () -> runForTesting(app, options));
+ runForTesting(app, options);
}
/**
@@ -126,13 +126,18 @@
ExceptionUtils.withMainProgramHandler(() -> run(args));
}
- static void runForTesting(AndroidApp inputApp, InternalOptions options) throws IOException {
+ static void runForTesting(AndroidApp inputApp, InternalOptions options)
+ throws CompilationFailedException {
ExecutorService executor = ThreadUtils.getExecutorService(options);
- try {
- run(inputApp, options, executor);
- } finally {
- executor.shutdown();
- }
+ ExceptionUtils.withD8CompilationHandler(
+ options.reporter,
+ () -> {
+ try {
+ run(inputApp, options, executor);
+ } finally {
+ executor.shutdown();
+ }
+ });
}
// Compute the marker to be placed in the main dex file.
diff --git a/src/main/java/com/android/tools/r8/DexFileMergerHelper.java b/src/main/java/com/android/tools/r8/DexFileMergerHelper.java
index d7183c8..b6bb4e0 100644
--- a/src/main/java/com/android/tools/r8/DexFileMergerHelper.java
+++ b/src/main/java/com/android/tools/r8/DexFileMergerHelper.java
@@ -115,7 +115,7 @@
}
public static void runD8ForTesting(D8Command command, boolean dontCreateMarkerInD8)
- throws IOException {
+ throws CompilationFailedException {
InternalOptions options = command.getInternalOptions();
options.testing.dontCreateMarkerInD8 = dontCreateMarkerInD8;
D8.runForTesting(command.getInputApp(), options);
diff --git a/src/main/java/com/android/tools/r8/DexRoundTrip.java b/src/main/java/com/android/tools/r8/DexRoundTrip.java
index b6bebbb..fcf308b 100644
--- a/src/main/java/com/android/tools/r8/DexRoundTrip.java
+++ b/src/main/java/com/android/tools/r8/DexRoundTrip.java
@@ -5,10 +5,8 @@
import com.android.tools.r8.utils.AndroidApp;
import com.android.tools.r8.utils.AndroidAppConsumers;
-import com.android.tools.r8.utils.ExceptionUtils;
import com.android.tools.r8.utils.FileUtils;
import com.android.tools.r8.utils.InternalOptions;
-import java.io.IOException;
import java.nio.file.Path;
import java.nio.file.Paths;
@@ -20,11 +18,10 @@
InternalOptions options = command.getInternalOptions();
AndroidApp app = command.getInputApp();
options.passthroughDexCode = false;
- ExceptionUtils.withD8CompilationHandler(options.reporter, () -> D8.runForTesting(app, options));
+ D8.runForTesting(app, options);
}
- public static void main(String[] args)
- throws CompilationFailedException, IOException, ResourceException {
+ public static void main(String[] args) throws CompilationFailedException {
D8Command.Builder builder = D8Command.builder();
for (String arg : args) {
Path file = Paths.get(arg);
diff --git a/src/main/java/com/android/tools/r8/DexSplitterHelper.java b/src/main/java/com/android/tools/r8/DexSplitterHelper.java
index 163c46f..51424d5 100644
--- a/src/main/java/com/android/tools/r8/DexSplitterHelper.java
+++ b/src/main/java/com/android/tools/r8/DexSplitterHelper.java
@@ -136,7 +136,7 @@
}
public static void runD8ForTesting(D8Command command, boolean dontCreateMarkerInD8)
- throws IOException {
+ throws CompilationFailedException {
InternalOptions options = command.getInternalOptions();
options.testing.dontCreateMarkerInD8 = dontCreateMarkerInD8;
D8.runForTesting(command.getInputApp(), options);
diff --git a/src/main/java/com/android/tools/r8/R8.java b/src/main/java/com/android/tools/r8/R8.java
index 6de196e..5d3f795 100644
--- a/src/main/java/com/android/tools/r8/R8.java
+++ b/src/main/java/com/android/tools/r8/R8.java
@@ -126,16 +126,7 @@
public static void run(R8Command command) throws CompilationFailedException {
AndroidApp app = command.getInputApp();
InternalOptions options = command.getInternalOptions();
- ExecutorService executor = ThreadUtils.getExecutorService(options);
- ExceptionUtils.withR8CompilationHandler(
- command.getReporter(),
- () -> {
- try {
- run(app, options, executor);
- } finally {
- executor.shutdown();
- }
- });
+ runForTesting(app, options);
}
/**
@@ -218,13 +209,18 @@
return result;
}
- static void runForTesting(AndroidApp app, InternalOptions options) throws IOException {
+ static void runForTesting(AndroidApp app, InternalOptions options)
+ throws CompilationFailedException {
ExecutorService executor = ThreadUtils.getExecutorService(options);
- try {
- run(app, options, executor);
- } finally {
- executor.shutdown();
- }
+ ExceptionUtils.withR8CompilationHandler(
+ options.reporter,
+ () -> {
+ try {
+ run(app, options, executor);
+ } finally {
+ executor.shutdown();
+ }
+ });
}
private static void run(AndroidApp app, InternalOptions options, ExecutorService executor)
diff --git a/src/main/java/com/android/tools/r8/shaking/ReasonPrinter.java b/src/main/java/com/android/tools/r8/shaking/ReasonPrinter.java
index 3b3063d..1eb43f5 100644
--- a/src/main/java/com/android/tools/r8/shaking/ReasonPrinter.java
+++ b/src/main/java/com/android/tools/r8/shaking/ReasonPrinter.java
@@ -11,6 +11,7 @@
import com.android.tools.r8.graph.DexItem;
import com.android.tools.r8.graph.DexType;
import com.google.common.collect.Sets;
+import java.io.PrintStream;
import java.util.ArrayDeque;
import java.util.Arrays;
import java.util.Collections;
@@ -136,6 +137,8 @@
private int indentation = -1;
+ private PrintStream output = System.out;
+
void pushIsLivePrefix() {
prefixes.push("is live because ");
}
@@ -159,27 +162,27 @@
void startItem(DexItem item) {
indentation++;
indent();
- System.out.println(item.toSourceString());
+ output.println(item.toSourceString());
}
private void indent() {
for (int i = 0; i < indentation; i++) {
- System.out.print(" ");
+ output.print(" ");
}
}
void addReason(String thing) {
indent();
- System.out.print("|- ");
+ output.print("|- ");
String prefix = prefixes.peek();
- System.out.print(prefix);
- System.out.println(thing);
+ output.print(prefix);
+ output.println(thing);
}
void addMessage(String thing) {
indent();
- System.out.print("| ");
- System.out.println(thing);
+ output.print("| ");
+ output.println(thing);
}
void endItem() {
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 4dff93c..383b9c3 100644
--- a/src/main/java/com/android/tools/r8/utils/AndroidApp.java
+++ b/src/main/java/com/android/tools/r8/utils/AndroidApp.java
@@ -12,7 +12,6 @@
import com.android.tools.r8.ClassFileResourceProvider;
import com.android.tools.r8.DataEntryResource;
import com.android.tools.r8.DataResourceProvider;
-import com.android.tools.r8.DataResourceProvider.Visitor;
import com.android.tools.r8.DexFilePerClassFileConsumer;
import com.android.tools.r8.DexIndexedConsumer;
import com.android.tools.r8.DirectoryClassFileProvider;
@@ -303,12 +302,12 @@
}
/** Add program file resources. */
- public Builder addProgramFiles(Path... files) throws NoSuchFileException {
+ public Builder addProgramFiles(Path... files) {
return addProgramFiles(Arrays.asList(files));
}
/** Add program file resources. */
- public Builder addProgramFiles(Collection<Path> files) throws NoSuchFileException {
+ public Builder addProgramFiles(Collection<Path> files) {
for (Path file : files) {
addProgramFile(file);
}
@@ -366,12 +365,12 @@
}
/** Add library file resources. */
- public Builder addLibraryFiles(Path... files) throws IOException {
+ public Builder addLibraryFiles(Path... files) {
return addLibraryFiles(Arrays.asList(files));
}
/** Add library file resources. */
- public Builder addLibraryFiles(Collection<Path> files) throws IOException {
+ public Builder addLibraryFiles(Collection<Path> files) {
for (Path file : files) {
addClasspathOrLibraryProvider(file, libraryResourceProviders);
}
@@ -578,9 +577,11 @@
mainDexListClasses);
}
- public void addProgramFile(Path file) throws NoSuchFileException {
+ public void addProgramFile(Path file) {
if (!Files.exists(file)) {
- throw new NoSuchFileException(file.toString());
+ PathOrigin pathOrigin = new PathOrigin(file);
+ NoSuchFileException noSuchFileException = new NoSuchFileException(file.toString());
+ reporter.error(new ExceptionDiagnostic(noSuchFileException, pathOrigin));
}
if (isDexFile(file)) {
addProgramResources(ProgramResource.fromFile(Kind.DEX, file));
@@ -610,12 +611,18 @@
}
private void addClasspathOrLibraryProvider(
- Path file, List<ClassFileResourceProvider> providerList) throws IOException {
+ Path file, List<ClassFileResourceProvider> providerList) {
if (!Files.exists(file)) {
- throw new NoSuchFileException(file.toString());
+ reporter.error(
+ new ExceptionDiagnostic(
+ new NoSuchFileException(file.toString()), new PathOrigin(file)));
}
if (isArchive(file)) {
- providerList.add(new ArchiveClassFileProvider(file));
+ try {
+ providerList.add(new ArchiveClassFileProvider(file));
+ } catch (IOException e) {
+ reporter.error(new ExceptionDiagnostic(e, new PathOrigin(file)));
+ }
} else if (Files.isDirectory(file) ) {
providerList.add(DirectoryClassFileProvider.fromDirectory(file));
} else {
diff --git a/src/test/java/com/android/tools/r8/AsmTestBase.java b/src/test/java/com/android/tools/r8/AsmTestBase.java
index 35767fb..2c4cb6b 100644
--- a/src/test/java/com/android/tools/r8/AsmTestBase.java
+++ b/src/test/java/com/android/tools/r8/AsmTestBase.java
@@ -8,9 +8,7 @@
import com.android.tools.r8.ToolHelper.ArtCommandBuilder;
import com.android.tools.r8.ToolHelper.ProcessResult;
-import com.android.tools.r8.errors.CompilationError;
import com.android.tools.r8.origin.Origin;
-import com.android.tools.r8.shaking.ProguardRuleParserException;
import com.android.tools.r8.utils.AndroidApiLevel;
import com.android.tools.r8.utils.AndroidApp;
import com.android.tools.r8.utils.InternalOptions;
@@ -94,17 +92,17 @@
throws Exception {
// TODO(zerny): Port this to use diagnostics handler.
AndroidApp app = buildAndroidApp(classes);
- CompilationError r8Error = null;
- CompilationError r8ShakenError = null;
+ CompilationFailedException r8Error = null;
+ CompilationFailedException r8ShakenError = null;
try {
runOnArtRaw(compileWithR8(app), main);
- } catch (CompilationError e) {
+ } catch (CompilationFailedException e) {
r8Error = e;
}
try {
runOnArtRaw(compileWithR8(app, keepMainProguardConfiguration(main) + "-dontobfuscate\n"),
main);
- } catch (CompilationError e) {
+ } catch (CompilationFailedException e) {
r8ShakenError = e;
}
Assert.assertNotNull(r8Error);
@@ -112,7 +110,7 @@
}
protected void ensureSameOutputAfterMerging(String main, byte[]... classes)
- throws IOException, CompilationFailedException, ProguardRuleParserException {
+ throws IOException, CompilationFailedException {
AndroidApp app = buildAndroidApp(classes);
// Compile to dex files with D8.
AndroidApp dexApp = compileWithD8(app);
diff --git a/src/test/java/com/android/tools/r8/D8RunExamplesAndroidOTest.java b/src/test/java/com/android/tools/r8/D8RunExamplesAndroidOTest.java
index e01373c..6ccf086 100644
--- a/src/test/java/com/android/tools/r8/D8RunExamplesAndroidOTest.java
+++ b/src/test/java/com/android/tools/r8/D8RunExamplesAndroidOTest.java
@@ -4,20 +4,15 @@
package com.android.tools.r8;
-import com.android.tools.r8.errors.CompilationError;
-import com.android.tools.r8.errors.InternalCompilerError;
-import com.android.tools.r8.errors.Unimplemented;
+import static org.junit.Assert.assertTrue;
+
import com.android.tools.r8.utils.AndroidApiLevel;
import com.android.tools.r8.utils.OffOrAuto;
import java.nio.file.Path;
import java.util.function.UnaryOperator;
-import org.hamcrest.core.CombinableMatcher;
-import org.hamcrest.core.IsInstanceOf;
-import org.hamcrest.core.StringContains;
import org.junit.Assert;
import org.junit.Assume;
import org.junit.Test;
-import org.junit.internal.matchers.ThrowableMessageMatcher;
public class D8RunExamplesAndroidOTest extends RunExamplesAndroidOTest<D8Command.Builder> {
@@ -37,7 +32,7 @@
}
@Override
- void build(Path inputFile, Path out, OutputMode mode) throws Throwable {
+ void build(Path inputFile, Path out, OutputMode mode) throws CompilationFailedException {
D8Command.Builder builder = D8Command.builder().setOutput(out, mode);
for (UnaryOperator<D8Command.Builder> transformation : builderTransformations) {
builder = transformation.apply(builder);
@@ -46,13 +41,7 @@
ToolHelper.getAndroidJar(
androidJarVersion == null ? builder.getMinApiLevel() : androidJarVersion.getLevel()));
builder.addProgramFiles(inputFile);
- try {
- ToolHelper.runD8(builder, this::combinedOptionConsumer);
- } catch (Unimplemented | CompilationError | InternalCompilerError re) {
- throw re;
- } catch (RuntimeException re) {
- throw re.getCause() == null ? re : re.getCause();
- }
+ ToolHelper.runD8(builder, this::combinedOptionConsumer);
}
D8TestRunner withIntermediate(boolean intermediate) {
@@ -77,7 +66,7 @@
// compilation should have failed on CompilationError since A is declaring a default method.
Assert.fail();
- } catch (CompilationError e) {
+ } catch (CompilationFailedException e) {
// Expected.
}
}
@@ -363,13 +352,14 @@
.withClasspath(lib1.getInputJar())
.withClasspath(lib2.getInputJar())
.withMinApiLevel(minApi);
- thrown.expect(
- new CombinableMatcher<CompilationError>(new IsInstanceOf(CompilationError.class))
- .and(new ThrowableMessageMatcher<CompilationError>(
- new StringContains("desugaringwithmissingclasstest2.ImplementMethodsWithDefault")))
- .and(new ThrowableMessageMatcher<CompilationError>(
- new StringContains("desugaringwithmissingclasslib3.C"))));
- test.build();
+ try {
+ test.build();
+ Assert.fail("Expected build to fail with CompilationFailedException");
+ } catch (CompilationFailedException e) {
+ String message = e.getCause().getMessage();
+ assertTrue(message.contains("desugaringwithmissingclasstest2.ImplementMethodsWithDefault"));
+ assertTrue(message.contains("desugaringwithmissingclasslib3.C"));
+ }
}
@Test
diff --git a/src/test/java/com/android/tools/r8/R8RunArtTestsTest.java b/src/test/java/com/android/tools/r8/R8RunArtTestsTest.java
index 37515d2..3ef4037 100644
--- a/src/test/java/com/android/tools/r8/R8RunArtTestsTest.java
+++ b/src/test/java/com/android/tools/r8/R8RunArtTestsTest.java
@@ -1408,8 +1408,7 @@
boolean disableInlining,
boolean disableClassInlining,
boolean hasMissingClasses)
- throws IOException, ProguardRuleParserException, ExecutionException,
- CompilationFailedException {
+ throws CompilationFailedException {
executeCompilerUnderTest(compilerUnderTest, fileNames, resultPath, compilationMode, null,
disableInlining, disableClassInlining, hasMissingClasses);
}
@@ -1423,8 +1422,7 @@
boolean disableInlining,
boolean disableClassInlining,
boolean hasMissingClasses)
- throws IOException, ProguardRuleParserException, ExecutionException,
- CompilationFailedException {
+ throws CompilationFailedException {
assert mode != null;
switch (compilerUnderTest) {
case D8_AFTER_R8CF:
@@ -1956,8 +1954,6 @@
specification.hasMissingClasses);
} catch (CompilationFailedException e) {
throw new CompilationError(e.getMessage(), e);
- } catch (ExecutionException e) {
- throw e.getCause();
}
System.err.println("Should have failed R8/D8 compilation with a CompilationError.");
return;
diff --git a/src/test/java/com/android/tools/r8/R8RunExamplesCommon.java b/src/test/java/com/android/tools/r8/R8RunExamplesCommon.java
index 008c6b9..428c611 100644
--- a/src/test/java/com/android/tools/r8/R8RunExamplesCommon.java
+++ b/src/test/java/com/android/tools/r8/R8RunExamplesCommon.java
@@ -12,7 +12,6 @@
import com.android.tools.r8.R8RunArtTestsTest.DexTool;
import com.android.tools.r8.ToolHelper.DexVm;
import com.android.tools.r8.errors.Unreachable;
-import com.android.tools.r8.utils.ExceptionUtils;
import com.android.tools.r8.utils.InternalOptions.LineNumberOptimization;
import com.android.tools.r8.utils.TestDescriptionWatcher;
import java.io.IOException;
@@ -170,19 +169,16 @@
.setOutput(getOutputFile(), outputMode)
.setMode(mode)
.build();
- ExceptionUtils.withR8CompilationHandler(
- command.getReporter(),
- () ->
- ToolHelper.runR8(
- command,
- options -> {
- options.lineNumberOptimization = LineNumberOptimization.OFF;
- options.enableCfFrontend = frontend == Frontend.CF;
- if (output == Output.CF) {
- // Class inliner is not supported with CF backend yet.
- options.enableClassInlining = false;
- }
- }));
+ ToolHelper.runR8(
+ command,
+ options -> {
+ options.lineNumberOptimization = LineNumberOptimization.OFF;
+ options.enableCfFrontend = frontend == Frontend.CF;
+ if (output == Output.CF) {
+ // Class inliner is not supported with CF backend yet.
+ options.enableClassInlining = false;
+ }
+ });
break;
}
default:
diff --git a/src/test/java/com/android/tools/r8/RunExamplesAndroidNTest.java b/src/test/java/com/android/tools/r8/RunExamplesAndroidNTest.java
index 83df845..5b4482e 100644
--- a/src/test/java/com/android/tools/r8/RunExamplesAndroidNTest.java
+++ b/src/test/java/com/android/tools/r8/RunExamplesAndroidNTest.java
@@ -129,9 +129,8 @@
.run();
}
- @Test
+ @Test(expected = CompilationFailedException.class)
public void staticInterfaceMethodsErrorDueToMinSdk() throws Throwable {
- thrown.expect(ApiLevelException.class);
test("staticinterfacemethods-error-due-to-min-sdk", "interfacemethods",
"StaticInterfaceMethods")
.withInterfaceMethodDesugaring(OffOrAuto.Off)
@@ -146,9 +145,8 @@
.run();
}
- @Test
+ @Test(expected = CompilationFailedException.class)
public void defaultMethodsErrorDueToMinSdk() throws Throwable {
- thrown.expect(ApiLevelException.class);
test("defaultmethods-error-due-to-min-sdk", "interfacemethods",
"DefaultMethods")
.withInterfaceMethodDesugaring(OffOrAuto.Off)
diff --git a/src/test/java/com/android/tools/r8/RunExamplesAndroidOTest.java b/src/test/java/com/android/tools/r8/RunExamplesAndroidOTest.java
index 1f0c464..68aec3f 100644
--- a/src/test/java/com/android/tools/r8/RunExamplesAndroidOTest.java
+++ b/src/test/java/com/android/tools/r8/RunExamplesAndroidOTest.java
@@ -149,7 +149,7 @@
void run() throws Throwable {
if (minSdkErrorExpected(testName)) {
- thrown.expect(ApiLevelException.class);
+ thrown.expect(CompilationFailedException.class);
}
String qualifiedMainClass = packageName + "." + mainClass;
diff --git a/src/test/java/com/android/tools/r8/RunExamplesAndroidPTest.java b/src/test/java/com/android/tools/r8/RunExamplesAndroidPTest.java
index 7f15eca..177fe89 100644
--- a/src/test/java/com/android/tools/r8/RunExamplesAndroidPTest.java
+++ b/src/test/java/com/android/tools/r8/RunExamplesAndroidPTest.java
@@ -136,7 +136,7 @@
void run() throws Throwable {
if (minSdkErrorExpected(testName)) {
- thrown.expect(ApiLevelException.class);
+ thrown.expect(CompilationFailedException.class);
}
String qualifiedMainClass = packageName + "." + mainClass;
diff --git a/src/test/java/com/android/tools/r8/RunExamplesJava9Test.java b/src/test/java/com/android/tools/r8/RunExamplesJava9Test.java
index 48a14f3..99ac1f7 100644
--- a/src/test/java/com/android/tools/r8/RunExamplesJava9Test.java
+++ b/src/test/java/com/android/tools/r8/RunExamplesJava9Test.java
@@ -139,7 +139,7 @@
void run() throws Throwable {
if (minSdkErrorExpected(testName)) {
- thrown.expect(ApiLevelException.class);
+ thrown.expect(CompilationFailedException.class);
}
String qualifiedMainClass = packageName + "." + mainClass;
diff --git a/src/test/java/com/android/tools/r8/TestBase.java b/src/test/java/com/android/tools/r8/TestBase.java
index 80d856d..22bb5e5 100644
--- a/src/test/java/com/android/tools/r8/TestBase.java
+++ b/src/test/java/com/android/tools/r8/TestBase.java
@@ -107,10 +107,8 @@
return file;
}
- /**
- * Build an AndroidApp with the specified test classes as byte array.
- */
- protected AndroidApp buildAndroidApp(byte[]... classes) throws IOException {
+ /** Build an AndroidApp with the specified test classes as byte array. */
+ protected AndroidApp buildAndroidApp(byte[]... classes) {
AndroidApp.Builder builder = AndroidApp.builder();
for (byte[] clazz : classes) {
builder.addClassProgramData(clazz, Origin.unknown());
@@ -343,7 +341,8 @@
}
/** Compile an application with R8. */
- protected AndroidApp compileWithR8(Class... classes) throws IOException {
+ protected AndroidApp compileWithR8(Class... classes)
+ throws IOException, CompilationFailedException {
return ToolHelper.runR8(readClasses(classes));
}
diff --git a/src/test/java/com/android/tools/r8/ToolHelper.java b/src/test/java/com/android/tools/r8/ToolHelper.java
index 8739216..e34282d 100644
--- a/src/test/java/com/android/tools/r8/ToolHelper.java
+++ b/src/test/java/com/android/tools/r8/ToolHelper.java
@@ -840,39 +840,32 @@
.setProguardMapConsumer(StringConsumer.emptyConsumer());
}
- public static AndroidApp runR8(AndroidApp app) throws IOException {
+ public static AndroidApp runR8(AndroidApp app) throws CompilationFailedException {
return runR8WithProgramConsumer(app, DexIndexedConsumer.emptyConsumer());
}
public static AndroidApp runR8WithProgramConsumer(AndroidApp app, ProgramConsumer programConsumer)
- throws IOException {
- try {
- return runR8(prepareR8CommandBuilder(app, programConsumer).build());
- } catch (CompilationFailedException e) {
- throw new RuntimeException(e);
- }
+ throws CompilationFailedException {
+ return runR8(prepareR8CommandBuilder(app, programConsumer).build());
}
public static AndroidApp runR8(AndroidApp app, Consumer<InternalOptions> optionsConsumer)
- throws IOException {
- try {
- return runR8(prepareR8CommandBuilder(app).build(), optionsConsumer);
- } catch (CompilationFailedException e) {
- throw new RuntimeException(e);
- }
+ throws CompilationFailedException {
+ return runR8(prepareR8CommandBuilder(app).build(), optionsConsumer);
}
- public static AndroidApp runR8(R8Command command) throws IOException {
+ public static AndroidApp runR8(R8Command command) throws CompilationFailedException {
return runR8(command, null);
}
public static AndroidApp runR8(R8Command command, Consumer<InternalOptions> optionsConsumer)
- throws IOException {
+ throws CompilationFailedException {
return runR8WithFullResult(command, optionsConsumer);
}
public static AndroidApp runR8WithFullResult(
- R8Command command, Consumer<InternalOptions> optionsConsumer) throws IOException {
+ R8Command command, Consumer<InternalOptions> optionsConsumer)
+ throws CompilationFailedException {
// TODO(zerny): Should we really be adding the android library in ToolHelper?
AndroidApp app = command.getInputApp();
if (app.getLibraryResourceProviders().isEmpty()) {
@@ -891,39 +884,32 @@
return compatSink.build();
}
- public static void addFilteredAndroidJar(BaseCommand.Builder builder, AndroidApiLevel apiLevel)
- throws IOException {
+ public static void addFilteredAndroidJar(BaseCommand.Builder builder, AndroidApiLevel apiLevel) {
addFilteredAndroidJar(getAppBuilder(builder), apiLevel);
}
- public static void addFilteredAndroidJar(AndroidApp.Builder builder, AndroidApiLevel apiLevel)
- throws IOException {
+ public static void addFilteredAndroidJar(AndroidApp.Builder builder, AndroidApiLevel apiLevel) {
builder.addFilteredLibraryArchives(Collections.singletonList(
new FilteredClassPath(getAndroidJar(apiLevel),
ImmutableList.of("!junit/**", "!android/test/**"))));
}
- public static AndroidApp runD8(AndroidApp app) throws IOException {
+ public static AndroidApp runD8(AndroidApp app) throws CompilationFailedException {
return runD8(app, null);
}
public static AndroidApp runD8(AndroidApp app, Consumer<InternalOptions> optionsConsumer)
- throws IOException {
- try {
- return runD8(D8Command.builder(app), optionsConsumer);
- } catch (CompilationFailedException e) {
- throw new RuntimeException(e);
- }
+ throws CompilationFailedException {
+ return runD8(D8Command.builder(app), optionsConsumer);
}
- public static AndroidApp runD8(D8Command.Builder builder)
- throws IOException, CompilationFailedException {
+ public static AndroidApp runD8(D8Command.Builder builder) throws CompilationFailedException {
return runD8(builder, null);
}
public static AndroidApp runD8(
D8Command.Builder builder, Consumer<InternalOptions> optionsConsumer)
- throws IOException, CompilationFailedException {
+ throws CompilationFailedException {
AndroidAppConsumers compatSink = new AndroidAppConsumers(builder);
D8Command command = builder.build();
InternalOptions options = command.getInternalOptions();
diff --git a/src/test/java/com/android/tools/r8/cf/DebugInfoTestRunner.java b/src/test/java/com/android/tools/r8/cf/DebugInfoTestRunner.java
index ad6a72b..3514a00 100644
--- a/src/test/java/com/android/tools/r8/cf/DebugInfoTestRunner.java
+++ b/src/test/java/com/android/tools/r8/cf/DebugInfoTestRunner.java
@@ -7,6 +7,7 @@
import static org.junit.Assert.assertTrue;
import com.android.tools.r8.ClassFileConsumer;
+import com.android.tools.r8.CompilationFailedException;
import com.android.tools.r8.CompilationMode;
import com.android.tools.r8.ProgramConsumer;
import com.android.tools.r8.R8Command;
@@ -14,8 +15,6 @@
import com.android.tools.r8.TestBase;
import com.android.tools.r8.ToolHelper;
import com.android.tools.r8.ToolHelper.ProcessResult;
-import com.android.tools.r8.errors.CompilationError;
-import com.android.tools.r8.errors.InvalidDebugInfoException;
import com.android.tools.r8.origin.Origin;
import com.android.tools.r8.utils.ThrowingConsumer;
import java.nio.file.Path;
@@ -39,8 +38,8 @@
boolean invalidDebugInfo = false;
try {
build(builder -> builder.addProgramFiles(out1), new ClassFileConsumer.ArchiveConsumer(out2));
- } catch (CompilationError e) {
- invalidDebugInfo = e.getCause() instanceof InvalidDebugInfoException;
+ } catch (CompilationFailedException e) {
+ invalidDebugInfo = e.getCause().getMessage().contains("Invalid debug info");
}
// TODO(b/77522100): Change to assertFalse when fixed.
assertTrue(invalidDebugInfo);
diff --git a/src/test/java/com/android/tools/r8/checkdiscarded/CheckDiscardedTest.java b/src/test/java/com/android/tools/r8/checkdiscarded/CheckDiscardedTest.java
index 1938c46..a1042b8 100644
--- a/src/test/java/com/android/tools/r8/checkdiscarded/CheckDiscardedTest.java
+++ b/src/test/java/com/android/tools/r8/checkdiscarded/CheckDiscardedTest.java
@@ -3,13 +3,13 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.checkdiscarded;
+import com.android.tools.r8.CompilationFailedException;
import com.android.tools.r8.TestBase;
import com.android.tools.r8.checkdiscarded.testclasses.Main;
import com.android.tools.r8.checkdiscarded.testclasses.UnusedClass;
import com.android.tools.r8.checkdiscarded.testclasses.UsedClass;
import com.android.tools.r8.checkdiscarded.testclasses.WillBeGone;
import com.android.tools.r8.checkdiscarded.testclasses.WillStay;
-import com.android.tools.r8.errors.CompilationError;
import com.android.tools.r8.utils.InternalOptions;
import com.google.common.collect.ImmutableList;
import java.util.List;
@@ -28,7 +28,7 @@
+ checkDiscardRule(checkMembers, annotation);
try {
compileWithR8(classes, proguardConfig, this::noInlining);
- } catch (CompilationError e) {
+ } catch (CompilationFailedException e) {
Assert.assertTrue(shouldFail);
return;
}
diff --git a/src/test/java/com/android/tools/r8/desugaring/interfacemethods/InterfaceMethodDesugaringTests.java b/src/test/java/com/android/tools/r8/desugaring/interfacemethods/InterfaceMethodDesugaringTests.java
index 2b73eaa..3674108 100644
--- a/src/test/java/com/android/tools/r8/desugaring/interfacemethods/InterfaceMethodDesugaringTests.java
+++ b/src/test/java/com/android/tools/r8/desugaring/interfacemethods/InterfaceMethodDesugaringTests.java
@@ -7,6 +7,7 @@
import static org.junit.Assert.assertEquals;
import com.android.tools.r8.AsmTestBase;
+import com.android.tools.r8.CompilationFailedException;
import com.android.tools.r8.ToolHelper;
import com.android.tools.r8.ToolHelper.DexVm.Version;
import com.android.tools.r8.VmTestRunner;
@@ -20,7 +21,6 @@
import com.android.tools.r8.desugaring.interfacemethods.default2.TestMainDefault2;
import com.android.tools.r8.desugaring.interfacemethods.static0.TestMainStatic0;
import com.android.tools.r8.desugaring.interfacemethods.static1.TestMainStatic1;
-import com.android.tools.r8.errors.CompilationError;
import com.android.tools.r8.utils.AndroidApiLevel;
import java.io.ByteArrayInputStream;
import java.io.IOException;
@@ -139,7 +139,7 @@
ToolHelper.getClassAsBytes(TestMainDefault0.class));
}
- @Test(expected = CompilationError.class)
+ @Test(expected = CompilationFailedException.class)
@IgnoreForRangeOfVmVersions(from = Version.V7_0_0, to = Version.DEFAULT) // No desugaring
public void testInvokeDefault1() throws Exception {
ensureSameOutput(
diff --git a/src/test/java/com/android/tools/r8/graph/TargetLookupTest.java b/src/test/java/com/android/tools/r8/graph/TargetLookupTest.java
index 39b5ff8..7e0bfec 100644
--- a/src/test/java/com/android/tools/r8/graph/TargetLookupTest.java
+++ b/src/test/java/com/android/tools/r8/graph/TargetLookupTest.java
@@ -8,6 +8,7 @@
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
+import com.android.tools.r8.CompilationFailedException;
import com.android.tools.r8.ToolHelper;
import com.android.tools.r8.ToolHelper.DexVm;
import com.android.tools.r8.ToolHelper.ProcessResult;
@@ -175,7 +176,7 @@
}
@Test
- public void lookupFieldWithDefaultInInterface() {
+ public void lookupFieldWithDefaultInInterface() throws CompilationFailedException {
SmaliBuilder builder = new SmaliBuilder();
builder.addInterface("Interface");
diff --git a/src/test/java/com/android/tools/r8/jasmin/MemberResolutionTest.java b/src/test/java/com/android/tools/r8/jasmin/MemberResolutionTest.java
index 49516d7..3d0aaff 100644
--- a/src/test/java/com/android/tools/r8/jasmin/MemberResolutionTest.java
+++ b/src/test/java/com/android/tools/r8/jasmin/MemberResolutionTest.java
@@ -5,12 +5,12 @@
import static java.util.Collections.emptyList;
+import com.android.tools.r8.CompilationFailedException;
import com.android.tools.r8.R8RunArtTestsTest.CompilerUnderTest;
import com.android.tools.r8.ToolHelper.DexVm.Version;
import com.android.tools.r8.ToolHelper.ProcessResult;
import com.android.tools.r8.VmTestRunner;
import com.android.tools.r8.VmTestRunner.IgnoreForRangeOfVmVersions;
-import com.android.tools.r8.errors.CompilationError;
import com.android.tools.r8.jasmin.JasminBuilder.ClassBuilder;
import com.android.tools.r8.jasmin.JasminBuilder.ClassFileVersion;
import com.android.tools.r8.utils.ThrowingBiFunction;
@@ -572,7 +572,7 @@
ProcessResult result = process.get();
Assert.assertFalse(compiler != null && predicate.test(compiler));
Assert.assertTrue(result.stderr.contains(name));
- } catch (CompilationError e) {
+ } catch (CompilationFailedException e) {
Assert.assertTrue(compiler == null || predicate.test(compiler));
} catch (Exception e) {
Assert.fail();
diff --git a/src/test/java/com/android/tools/r8/jasmin/NameTestBase.java b/src/test/java/com/android/tools/r8/jasmin/NameTestBase.java
index 1104e54..6589e06 100644
--- a/src/test/java/com/android/tools/r8/jasmin/NameTestBase.java
+++ b/src/test/java/com/android/tools/r8/jasmin/NameTestBase.java
@@ -7,8 +7,8 @@
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
+import com.android.tools.r8.CompilationFailedException;
import com.android.tools.r8.ToolHelper;
-import com.android.tools.r8.errors.CompilationError;
import com.android.tools.r8.utils.StringUtils;
import java.nio.file.InvalidPathException;
import java.util.Arrays;
@@ -112,8 +112,8 @@
try {
runOnArtD8(jasminBuilder, mainClassName);
fail("D8 should have rejected this case.");
- } catch (CompilationError t) {
- assertTrue(t.getMessage().contains(expectedNameInFailingD8Message));
+ } catch (CompilationFailedException t) {
+ assertTrue(t.getCause().getMessage().contains(expectedNameInFailingD8Message));
}
// Make sure ART also fail, if D8 rejects it.
diff --git a/src/test/java/com/android/tools/r8/maindexlist/MainDexListTests.java b/src/test/java/com/android/tools/r8/maindexlist/MainDexListTests.java
index e608a20..4a76bde 100644
--- a/src/test/java/com/android/tools/r8/maindexlist/MainDexListTests.java
+++ b/src/test/java/com/android/tools/r8/maindexlist/MainDexListTests.java
@@ -185,7 +185,7 @@
try {
verifyMainDexContains(TWO_LARGE_CLASSES, getTwoLargeClassesAppPath(), false);
fail("Expect to fail, for there are too many classes for the main-dex list.");
- } catch (AbortException e) {
+ } catch (CompilationFailedException e) {
assertEquals(1, errors.size());
String message = errors.get(0).getDiagnosticMessage();
// Make sure {@link MonoDexDistributor} was _not_ used.
@@ -229,7 +229,7 @@
try {
verifyMainDexContains(MANY_CLASSES, getManyClassesMultiDexAppPath(), false);
fail("Expect to fail, for there are too many classes for the main-dex list.");
- } catch (AbortException e) {
+ } catch (CompilationFailedException e) {
assertEquals(1, errors.size());
String message = errors.get(0).getDiagnosticMessage();
// Make sure {@link MonoDexDistributor} was _not_ used.
diff --git a/src/test/java/com/android/tools/r8/naming/ApplyMappingTest.java b/src/test/java/com/android/tools/r8/naming/ApplyMappingTest.java
index 1e2e46e..7ce8a05 100644
--- a/src/test/java/com/android/tools/r8/naming/ApplyMappingTest.java
+++ b/src/test/java/com/android/tools/r8/naming/ApplyMappingTest.java
@@ -10,6 +10,7 @@
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
+import com.android.tools.r8.CompilationFailedException;
import com.android.tools.r8.DiagnosticsHandler;
import com.android.tools.r8.R8Command;
import com.android.tools.r8.StringConsumer;
@@ -17,7 +18,6 @@
import com.android.tools.r8.ToolHelper;
import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.DexType;
-import com.android.tools.r8.shaking.ProguardRuleParserException;
import com.android.tools.r8.utils.AndroidApp;
import com.android.tools.r8.utils.FileUtils;
import com.android.tools.r8.utils.codeinspector.CodeInspector;
@@ -287,8 +287,8 @@
try {
runR8(getCommandForApps(out, flag, MINIFICATION_JAR).build());
fail("Expect to detect renaming conflict");
- } catch (ProguardMapError e) {
- assertTrue(e.getMessage().contains("functionFromIntToInt"));
+ } catch (CompilationFailedException e) {
+ assertTrue(e.getCause().getMessage().contains("functionFromIntToInt"));
}
}
@@ -310,8 +310,7 @@
.addProguardConfigurationFiles(flag);
}
- private static AndroidApp runR8(R8Command command)
- throws ProguardRuleParserException, ExecutionException, IOException {
+ private static AndroidApp runR8(R8Command command) throws CompilationFailedException {
return ToolHelper.runR8(
command,
options -> {
diff --git a/src/test/java/com/android/tools/r8/rewrite/switches/SwitchRewritingTest.java b/src/test/java/com/android/tools/r8/rewrite/switches/SwitchRewritingTest.java
index 2073ab9..354f3c2 100644
--- a/src/test/java/com/android/tools/r8/rewrite/switches/SwitchRewritingTest.java
+++ b/src/test/java/com/android/tools/r8/rewrite/switches/SwitchRewritingTest.java
@@ -7,6 +7,7 @@
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
+import com.android.tools.r8.CompilationFailedException;
import com.android.tools.r8.code.Const;
import com.android.tools.r8.code.Const4;
import com.android.tools.r8.code.ConstHigh16;
@@ -39,7 +40,8 @@
|| instruction instanceof ConstHigh16
|| instruction instanceof Const;
}
- private void runSingleCaseDexTest(boolean packed, int key) {
+
+ private void runSingleCaseDexTest(boolean packed, int key) throws CompilationFailedException {
SmaliBuilder builder = new SmaliBuilder(DEFAULT_CLASS_NAME);
String switchInstruction;
String switchData;
@@ -100,7 +102,7 @@
}
@Test
- public void singleCaseDex() {
+ public void singleCaseDex() throws CompilationFailedException {
for (boolean packed : new boolean[]{true, false}) {
runSingleCaseDexTest(packed, Integer.MIN_VALUE);
runSingleCaseDexTest(packed, -1);
@@ -110,7 +112,8 @@
}
}
- private void runTwoCaseSparseToPackedOrIfsDexTest(int key1, int key2) {
+ private void runTwoCaseSparseToPackedOrIfsDexTest(int key1, int key2)
+ throws CompilationFailedException {
SmaliBuilder builder = new SmaliBuilder(DEFAULT_CLASS_NAME);
MethodSignature signature = builder.addStaticMethod(
@@ -162,7 +165,7 @@
}
@Test
- public void twoCaseSparseToPackedOrIfsDex() {
+ public void twoCaseSparseToPackedOrIfsDex() throws CompilationFailedException {
for (int delta = 1; delta <= 3; delta++) {
runTwoCaseSparseToPackedOrIfsDexTest(0, delta);
runTwoCaseSparseToPackedOrIfsDexTest(-delta, 0);
diff --git a/src/test/java/com/android/tools/r8/shaking/LibraryExtendsProgramTest.java b/src/test/java/com/android/tools/r8/shaking/LibraryExtendsProgramTest.java
index 09faa8b..834a486 100644
--- a/src/test/java/com/android/tools/r8/shaking/LibraryExtendsProgramTest.java
+++ b/src/test/java/com/android/tools/r8/shaking/LibraryExtendsProgramTest.java
@@ -3,40 +3,29 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.shaking;
+import com.android.tools.r8.CompilationFailedException;
import com.android.tools.r8.TestBase;
import com.android.tools.r8.shaking.libraryextendsprogram.Interface;
import com.android.tools.r8.shaking.libraryextendsprogram.Main;
import com.android.tools.r8.shaking.libraryextendsprogram.SubClass;
import com.android.tools.r8.shaking.libraryextendsprogram.SuperClass;
-import com.android.tools.r8.utils.AbortException;
import com.android.tools.r8.utils.AndroidApp;
import com.google.common.collect.ImmutableList;
-import org.junit.Assert;
import org.junit.Test;
public class LibraryExtendsProgramTest extends TestBase {
- @Test
+ @Test(expected = CompilationFailedException.class)
public void libraryClassExtendsProgramClass() throws Exception {
AndroidApp theApp = readClasses(ImmutableList.of(Main.class, SuperClass.class),
ImmutableList.of(SubClass.class, Interface.class));
- try {
- compileWithR8(theApp, o -> o.ignoreMissingClasses = true);
- } catch (AbortException e) {
- return;
- }
- Assert.fail();
+ compileWithR8(theApp, o -> o.ignoreMissingClasses = true);
}
- @Test
+ @Test(expected = CompilationFailedException.class)
public void libraryClassImplementsProgramInterface() throws Exception {
AndroidApp theApp = readClasses(ImmutableList.of(Main.class, Interface.class),
ImmutableList.of(SubClass.class, SuperClass.class));
- try {
- compileWithR8(theApp, o -> o.ignoreMissingClasses = true);
- } catch (AbortException e) {
- return;
- }
- Assert.fail();
+ compileWithR8(theApp, o -> o.ignoreMissingClasses = true);
}
}
diff --git a/src/test/java/com/android/tools/r8/shaking/forceproguardcompatibility/ForceProguardCompatibilityTest.java b/src/test/java/com/android/tools/r8/shaking/forceproguardcompatibility/ForceProguardCompatibilityTest.java
index ff762b7..30de112 100644
--- a/src/test/java/com/android/tools/r8/shaking/forceproguardcompatibility/ForceProguardCompatibilityTest.java
+++ b/src/test/java/com/android/tools/r8/shaking/forceproguardcompatibility/ForceProguardCompatibilityTest.java
@@ -9,10 +9,10 @@
import static org.junit.Assert.assertTrue;
import com.android.tools.r8.CompatProguardCommandBuilder;
+import com.android.tools.r8.CompilationFailedException;
import com.android.tools.r8.R8Command;
import com.android.tools.r8.TestBase;
import com.android.tools.r8.ToolHelper;
-import com.android.tools.r8.errors.CompilationError;
import com.android.tools.r8.graph.DexItemFactory;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.graph.invokesuper.Consumer;
@@ -588,7 +588,7 @@
builder.setProgramConsumer(emptyConsumer(backend)).addLibraryFiles(runtimeJar(backend));
try {
app = ToolHelper.runR8(builder.build(), o -> o.enableClassInlining = false);
- } catch (CompilationError e) {
+ } catch (CompilationFailedException e) {
assertTrue(!forceProguardCompatibility && (!innerClasses || !enclosingMethod));
return;
}
diff --git a/src/test/java/com/android/tools/r8/smali/ComputeBlockTryRangeTest.java b/src/test/java/com/android/tools/r8/smali/ComputeBlockTryRangeTest.java
index de8b832..9cfd7fa 100644
--- a/src/test/java/com/android/tools/r8/smali/ComputeBlockTryRangeTest.java
+++ b/src/test/java/com/android/tools/r8/smali/ComputeBlockTryRangeTest.java
@@ -3,6 +3,7 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.smali;
+import com.android.tools.r8.CompilationFailedException;
import com.android.tools.r8.graph.DexEncodedMethod;
import com.android.tools.r8.smali.SmaliBuilder.MethodSignature;
import com.android.tools.r8.utils.AndroidApp;
@@ -13,7 +14,7 @@
public class ComputeBlockTryRangeTest extends SmaliTestBase {
@Test
- public void jumpIntoTryRange() {
+ public void jumpIntoTryRange() throws CompilationFailedException {
SmaliBuilder builder = new SmaliBuilder("Test");
diff --git a/src/test/java/com/android/tools/r8/smali/SmaliBuildTest.java b/src/test/java/com/android/tools/r8/smali/SmaliBuildTest.java
index 8d780b4..912915b 100644
--- a/src/test/java/com/android/tools/r8/smali/SmaliBuildTest.java
+++ b/src/test/java/com/android/tools/r8/smali/SmaliBuildTest.java
@@ -6,6 +6,7 @@
import static org.junit.Assert.assertEquals;
+import com.android.tools.r8.CompilationFailedException;
import com.android.tools.r8.ToolHelper;
import com.android.tools.r8.origin.EmbeddedOrigin;
import com.android.tools.r8.utils.AndroidApp;
@@ -28,7 +29,7 @@
}
@Test
- public void buildWithoutLibrary() {
+ public void buildWithoutLibrary() throws CompilationFailedException {
// Build simple "Hello, world!" application.
SmaliBuilder builder = new SmaliBuilder(DEFAULT_CLASS_NAME);
builder.addMainMethod(
diff --git a/src/test/java/com/android/tools/r8/smali/SmaliTestBase.java b/src/test/java/com/android/tools/r8/smali/SmaliTestBase.java
index b12c0b9..0aa8cae 100644
--- a/src/test/java/com/android/tools/r8/smali/SmaliTestBase.java
+++ b/src/test/java/com/android/tools/r8/smali/SmaliTestBase.java
@@ -69,17 +69,15 @@
}
}
- protected AndroidApp processApplication(AndroidApp application) {
+ protected AndroidApp processApplication(AndroidApp application)
+ throws CompilationFailedException {
return processApplication(application, null);
}
- protected AndroidApp processApplication(AndroidApp application,
- Consumer<InternalOptions> optionsConsumer) {
- try {
- return ToolHelper.runR8(application, optionsConsumer);
- } catch (IOException e) {
- throw new RuntimeException(e);
- }
+ protected AndroidApp processApplication(
+ AndroidApp application, Consumer<InternalOptions> optionsConsumer)
+ throws CompilationFailedException {
+ return ToolHelper.runR8(application, optionsConsumer);
}
protected Path runR8(SmaliBuilder builder, List<String> proguardConfigurations) {
@@ -224,7 +222,12 @@
returnType, parameters, locals, instructions);
// Process the application with R8.
- AndroidApp processdApplication = processApplication(application);
+ AndroidApp processdApplication = null;
+ try {
+ processdApplication = processApplication(application);
+ } catch (CompilationFailedException e) {
+ throw new RuntimeException(e);
+ }
assertEquals(1, getNumberOfProgramClasses(processdApplication));
// Return the processed method for inspection.
diff --git a/tools/compare_apk_sizes.py b/tools/compare_apk_sizes.py
new file mode 100755
index 0000000..e477320
--- /dev/null
+++ b/tools/compare_apk_sizes.py
@@ -0,0 +1,143 @@
+#!/usr/bin/env python
+# Copyright (c) 2018, 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.
+
+# Script for checking impact of a change by comparing the sizes of generated
+# classes in an apk.
+
+import glob
+import optparse
+import os
+import shutil
+import sys
+import toolhelper
+import utils
+import zipfile
+import StringIO
+
+USAGE = """%prog [options] app1 app2
+ NOTE: This only makes sense if minification is disabled"""
+
+def parse_options():
+ result = optparse.OptionParser(usage=USAGE)
+ result.add_option('--temp',
+ help='Temporary directory to store extracted classes in')
+ result.add_option('--report',
+ help='Print comparison to this location instead of stdout')
+ return result.parse_args()
+
+def extract_apk(apk, output):
+ if os.path.exists(output):
+ shutil.rmtree(output)
+ zipfile.ZipFile(apk).extractall(output)
+ with utils.ChangedWorkingDirectory(output):
+ dex = glob.glob('*.dex')
+ return [os.path.join(output, dexfile) for dexfile in dex]
+
+def ensure_exists(files):
+ for f in files:
+ if not os.path.exists(f):
+ raise Exception('%s does not exist')
+
+def extract_classes(input, output):
+ if os.path.exists(output):
+ shutil.rmtree(output)
+ os.makedirs(output)
+ args = ['--file-per-class',
+ '--output', output]
+ args.extend(input)
+ if toolhelper.run('d8', args) is not 0:
+ raise Exception('Failed running d8')
+
+class FileInfo:
+ def __init__(self, path, root):
+ self.path = path
+ self.full_path = os.path.join(root, path)
+ self.size = os.path.getsize(self.full_path)
+
+def generate_file_info(path):
+ file_info_map = {}
+ with utils.ChangedWorkingDirectory(path):
+ for root, dirs, files in os.walk('.'):
+ for f in files:
+ assert f.endswith('dex')
+ file_path = os.path.join(root, f)
+ entry = FileInfo(file_path, path)
+ file_info_map[file_path] = entry
+ return file_info_map
+
+def print_info(app, app_files, only_in_app, bigger_in_app, output):
+ output.write('Only in %s\n' % app)
+ only_app_sorted = sorted(only_in_app,
+ key=lambda a: app_files[a].size,
+ reverse=True)
+ output.write('\n'.join([' %s %s bytes' %
+ (x, app_files[x].size) for x in only_app_sorted]))
+ output.write('\n\n')
+ output.write('Bigger in %s\n' % app)
+ # Sort by the percentage diff compared to size
+ percent = lambda a: (0.0 + bigger_in_app.get(a))/app_files.get(a).size * 100
+ for bigger in sorted(bigger_in_app, key=percent, reverse=True):
+ output.write(' {0:.3f}% {1} bytes {2}\n'.format(percent(bigger),
+ bigger_in_app[bigger],
+ bigger))
+ output.write('\n\n')
+
+
+def compare(app1_classes_dir, app2_classes_dir, app1, app2, report):
+ app1_files = generate_file_info(app1_classes_dir)
+ app2_files = generate_file_info(app2_classes_dir)
+ only_in_app1 = [k for k in app1_files if k not in app2_files]
+ only_in_app2 = [k for k in app2_files if k not in app1_files]
+ in_both = [k for k in app2_files if k in app1_files]
+ assert len(app1_files) == len(only_in_app1) + len(in_both)
+ assert len(app2_files) == len(only_in_app2) + len(in_both)
+ bigger_in_app1 = {}
+ bigger_in_app2 = {}
+ same_size = []
+ for f in in_both:
+ app1_entry = app1_files[f]
+ app2_entry = app2_files[f]
+ if app1_entry.size > app2_entry.size:
+ bigger_in_app1[f] = app1_entry.size - app2_entry.size
+ elif app2_entry.size > app1_entry.size:
+ bigger_in_app2[f] = app2_entry.size - app1_entry.size
+ else:
+ same_size.append(f)
+ output = open(report, 'w') if report else sys.stdout
+ print_info(app1, app1_files, only_in_app1, bigger_in_app1, output)
+ print_info(app2, app2_files, only_in_app2, bigger_in_app2, output)
+ output.write('Same size\n')
+ output.write('\n'.join([' %s' % x for x in same_size]))
+ if report:
+ output.close()
+
+def Main():
+ (options, args) = parse_options()
+ if len(args) is not 2:
+ print args
+ print('Takes exactly two arguments, the two apps to compare')
+ return 1
+ app1 = args[0]
+ app2 = args[1]
+ ensure_exists([app1, app2])
+ with utils.TempDir() as temporary:
+ # If a temp dir is passed in, use that instead of the generated temporary
+ output = options.temp if options.temp else temporary
+ ensure_exists([output])
+ app1_input = [app1]
+ app2_input = [app2]
+ if app1.endswith('apk'):
+ app1_input = extract_apk(app1, os.path.join(output, 'app1'))
+ if app2.endswith('apk'):
+ app2_input = extract_apk(app2, os.path.join(output, 'app2'))
+ app1_classes_dir = os.path.join(output, 'app1_classes')
+ app2_classes_dir = os.path.join(output, 'app2_classes')
+
+ extract_classes(app1_input, app1_classes_dir)
+ extract_classes(app2_input, app2_classes_dir)
+ compare(app1_classes_dir, app2_classes_dir, app1, app2, options.report)
+
+if __name__ == '__main__':
+ sys.exit(Main())