Rewrite RemoveAssertionsTest to use bytecode dumps and new test setup
The test was relying on a bytecode generated by javac, which will not
work when using applymapping.
Change-Id: I14a335c2aa8bbd0ae85cba02cde5311621e8026d
diff --git a/src/test/java/com/android/tools/r8/TestCompileResult.java b/src/test/java/com/android/tools/r8/TestCompileResult.java
index 1c4d7e1..c03c10e 100644
--- a/src/test/java/com/android/tools/r8/TestCompileResult.java
+++ b/src/test/java/com/android/tools/r8/TestCompileResult.java
@@ -20,6 +20,7 @@
import com.android.tools.r8.utils.codeinspector.ClassSubject;
import com.android.tools.r8.utils.codeinspector.CodeInspector;
import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ObjectArrays;
import java.io.IOException;
import java.io.PrintStream;
import java.nio.file.Path;
@@ -38,6 +39,7 @@
public final AndroidApp app;
final List<Path> additionalRunClassPath = new ArrayList<>();
+ final List<String> vmArguments = new ArrayList<>();
TestCompileResult(TestState state, AndroidApp app) {
super(state);
@@ -74,15 +76,23 @@
}
public RR run(TestRuntime runtime, String mainClass) throws ExecutionException, IOException {
+ return run(runtime, mainClass, new String[] {});
+ }
+
+ public RR run(TestRuntime runtime, String mainClass, String... args)
+ throws ExecutionException, IOException {
assert getBackend() == runtime.getBackend();
ClassSubject mainClassSubject = inspector().clazz(mainClass);
assertThat(mainClassSubject, isPresent());
if (runtime.isDex()) {
return runArt(
- runtime.asDex().getVm(), additionalRunClassPath, mainClassSubject.getFinalName());
+ runtime.asDex().getVm(), additionalRunClassPath, mainClassSubject.getFinalName(), args);
}
assert runtime.isCf();
- return runJava(runtime, additionalRunClassPath, mainClassSubject.getFinalName());
+ return runJava(
+ runtime,
+ additionalRunClassPath,
+ ObjectArrays.concat(mainClassSubject.getFinalName(), args));
}
public CR addRunClasspathFiles(Path... classpath) {
@@ -116,6 +126,14 @@
}
}
+ public CR enableRuntimeAssertions() {
+ assert getBackend() == Backend.CF;
+ if (!this.vmArguments.contains("-ea")) {
+ this.vmArguments.add("-ea");
+ }
+ return self();
+ }
+
public Path writeToZip() throws IOException {
Path file = state.getNewTempFolder().resolve("out.zip");
writeToZip(file);
@@ -194,7 +212,7 @@
}
}
- private RR runJava(TestRuntime runtime, List<Path> additionalClassPath, String mainClass)
+ private RR runJava(TestRuntime runtime, List<Path> additionalClassPath, String... arguments)
throws IOException {
// TODO(b/127785410): Always assume a non-null runtime.
assert runtime == null || TestParametersBuilder.isSystemJdk(runtime.asCf().getVm());
@@ -204,11 +222,12 @@
.addAll(additionalClassPath)
.add(out)
.build();
- ProcessResult result = ToolHelper.runJava(classPath, mainClass);
+ ProcessResult result = ToolHelper.runJava(vmArguments, classPath, arguments);
return createRunResult(result);
}
- private RR runArt(DexVm vm, List<Path> additionalClassPath, String mainClass) throws IOException {
+ private RR runArt(DexVm vm, List<Path> additionalClassPath, String mainClass, String... arguments)
+ throws IOException {
// TODO(b/127785410): Always assume a non-null runtime.
Path out = state.getNewTempFolder().resolve("out.zip");
app.writeToZip(out, OutputMode.DexIndexed);
@@ -216,7 +235,7 @@
.addAll(additionalClassPath.stream().map(Path::toString).collect(Collectors.toList()))
.add(out.toString())
.build();
- ProcessResult result = ToolHelper.runArtRaw(classPath, mainClass, dummy -> {}, vm);
+ ProcessResult result = ToolHelper.runArtRaw(classPath, mainClass, dummy -> {}, vm, arguments);
return createRunResult(result);
}
diff --git a/src/test/java/com/android/tools/r8/ToolHelper.java b/src/test/java/com/android/tools/r8/ToolHelper.java
index 97e0d09..e8b0202 100644
--- a/src/test/java/com/android/tools/r8/ToolHelper.java
+++ b/src/test/java/com/android/tools/r8/ToolHelper.java
@@ -1111,6 +1111,19 @@
return runProcess(builder);
}
+ public static ProcessResult runJava(List<String> vmArgs, List<Path> classpath, String... args)
+ throws IOException {
+ String cp =
+ classpath.stream().map(Path::toString).collect(Collectors.joining(CLASSPATH_SEPARATOR));
+ List<String> cmdline = new ArrayList<String>(Arrays.asList(getJavaExecutable()));
+ cmdline.addAll(vmArgs);
+ cmdline.add("-cp");
+ cmdline.add(cp);
+ cmdline.addAll(Arrays.asList(args));
+ ProcessBuilder builder = new ProcessBuilder(cmdline);
+ return runProcess(builder);
+ }
+
public static ProcessResult runJavaNoVerify(
Path classpath, String mainClass, String... args) throws IOException {
return runJavaNoVerify(
@@ -1217,53 +1230,59 @@
// multiple calls within the same test.
private static int testOutputPathIndex = 0;
- public static ProcessResult runArtRaw(List<String> files, String mainClass,
- Consumer<ArtCommandBuilder> extras, DexVm version)
+ public static ProcessResult runArtRaw(
+ List<String> files,
+ String mainClass,
+ Consumer<ArtCommandBuilder> extras,
+ DexVm version,
+ String... args)
throws IOException {
+ ArtCommandBuilder builder =
+ version != null ? new ArtCommandBuilder(version) : new ArtCommandBuilder();
+ files.forEach(builder::appendClasspath);
+ builder.setMainClass(mainClass);
+ if (extras != null) {
+ extras.accept(builder);
+ }
+ for (String arg : args) {
+ builder.appendProgramArgument(arg);
+ }
+ ProcessResult processResult = null;
- ArtCommandBuilder builder =
- version != null ? new ArtCommandBuilder(version) : new ArtCommandBuilder();
- files.forEach(builder::appendClasspath);
- builder.setMainClass(mainClass);
- if (extras != null) {
- extras.accept(builder);
+ // Whenever we start a new test method we reset the index count.
+ String reset_output_index = System.getProperty("reset_output_index");
+ if (reset_output_index != null) {
+ System.clearProperty("reset_output_index");
+ testOutputPathIndex = 0;
+ } else {
+ assert testOutputPathIndex >= 0;
+ testOutputPathIndex++;
+ }
+
+ String goldenFilesDirInProp = System.getProperty("use_golden_files_in");
+ if (goldenFilesDirInProp != null) {
+ File goldenFileDir = new File(goldenFilesDirInProp);
+ assert goldenFileDir.isDirectory();
+ processResult =
+ compareAgainstGoldenFiles(
+ files.stream().map(f -> new File(f)).collect(Collectors.toList()), goldenFileDir);
+ if (processResult.exitCode == 0) {
+ processResult = readProcessResult(goldenFileDir);
}
+ } else {
+ processResult = runArtProcessRaw(builder);
+ }
- ProcessResult processResult = null;
+ String goldenFilesDirToProp = System.getProperty("generate_golden_files_to");
+ if (goldenFilesDirToProp != null) {
+ File goldenFileDir = new File(goldenFilesDirToProp);
+ assert goldenFileDir.isDirectory();
+ storeAsGoldenFiles(
+ files.stream().map(f -> new File(f)).collect(Collectors.toList()), goldenFileDir);
+ storeProcessResult(processResult, goldenFileDir);
+ }
- // Whenever we start a new test method we reset the index count.
- String reset_output_index = System.getProperty("reset_output_index");
- if (reset_output_index != null) {
- System.clearProperty("reset_output_index");
- testOutputPathIndex = 0;
- } else {
- assert testOutputPathIndex >= 0;
- testOutputPathIndex++;
- }
-
- String goldenFilesDirInProp = System.getProperty("use_golden_files_in");
- if (goldenFilesDirInProp != null) {
- File goldenFileDir = new File(goldenFilesDirInProp);
- assert goldenFileDir.isDirectory();
- processResult = compareAgainstGoldenFiles(
- files.stream().map(f -> new File(f)).collect(Collectors.toList()), goldenFileDir);
- if (processResult.exitCode == 0) {
- processResult = readProcessResult(goldenFileDir);
- }
- } else {
- processResult = runArtProcessRaw(builder);
- }
-
- String goldenFilesDirToProp = System.getProperty("generate_golden_files_to");
- if (goldenFilesDirToProp != null) {
- File goldenFileDir = new File(goldenFilesDirToProp);
- assert goldenFileDir.isDirectory();
- storeAsGoldenFiles(files.stream().map(f -> new File(f)).collect(Collectors.toList()),
- goldenFileDir);
- storeProcessResult(processResult, goldenFileDir);
- }
-
- return processResult;
+ return processResult;
}
private static Path findNonConflictingDestinationFilePath(Path testOutputPath) {
diff --git a/src/test/java/com/android/tools/r8/rewrite/assertions/ChromuimAssertionHookMock.java b/src/test/java/com/android/tools/r8/rewrite/assertions/ChromuimAssertionHookMock.java
index 772ef09..466d57a 100644
--- a/src/test/java/com/android/tools/r8/rewrite/assertions/ChromuimAssertionHookMock.java
+++ b/src/test/java/com/android/tools/r8/rewrite/assertions/ChromuimAssertionHookMock.java
@@ -4,8 +4,105 @@
package com.android.tools.r8.rewrite.assertions;
+import org.objectweb.asm.ClassWriter;
+import org.objectweb.asm.Label;
+import org.objectweb.asm.MethodVisitor;
+import org.objectweb.asm.Opcodes;
+
public class ChromuimAssertionHookMock {
public static void assertFailureHandler(AssertionError assertion) {
System.out.println("Got AssertionError " + assertion);
}
}
+
+/* Below is an asmified dump of the above class */
+
+class ChromuimAssertionHookMockDump implements Opcodes {
+
+ public static byte[] dump() {
+
+ ClassWriter classWriter = new ClassWriter(0);
+ MethodVisitor methodVisitor;
+
+ classWriter.visit(
+ V1_8,
+ ACC_PUBLIC | ACC_SUPER,
+ "com/android/tools/r8/rewrite/assertions/ChromuimAssertionHookMock",
+ null,
+ "java/lang/Object",
+ null);
+
+ classWriter.visitSource("ChromuimAssertionHookMock.java", null);
+
+ {
+ methodVisitor = classWriter.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null);
+ methodVisitor.visitCode();
+ Label label0 = new Label();
+ methodVisitor.visitLabel(label0);
+ methodVisitor.visitLineNumber(7, label0);
+ methodVisitor.visitVarInsn(ALOAD, 0);
+ methodVisitor.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V", false);
+ methodVisitor.visitInsn(RETURN);
+ Label label1 = new Label();
+ methodVisitor.visitLabel(label1);
+ methodVisitor.visitLocalVariable(
+ "this",
+ "Lcom/android/tools/r8/rewrite/assertions/ChromuimAssertionHookMock;",
+ null,
+ label0,
+ label1,
+ 0);
+ methodVisitor.visitMaxs(1, 1);
+ methodVisitor.visitEnd();
+ }
+ {
+ methodVisitor =
+ classWriter.visitMethod(
+ ACC_PUBLIC | ACC_STATIC,
+ "assertFailureHandler",
+ "(Ljava/lang/AssertionError;)V",
+ null,
+ null);
+ methodVisitor.visitCode();
+ Label label0 = new Label();
+ methodVisitor.visitLabel(label0);
+ methodVisitor.visitLineNumber(9, label0);
+ methodVisitor.visitFieldInsn(GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;");
+ methodVisitor.visitTypeInsn(NEW, "java/lang/StringBuilder");
+ methodVisitor.visitInsn(DUP);
+ methodVisitor.visitMethodInsn(
+ INVOKESPECIAL, "java/lang/StringBuilder", "<init>", "()V", false);
+ methodVisitor.visitLdcInsn("Got AssertionError ");
+ methodVisitor.visitMethodInsn(
+ INVOKEVIRTUAL,
+ "java/lang/StringBuilder",
+ "append",
+ "(Ljava/lang/String;)Ljava/lang/StringBuilder;",
+ false);
+ methodVisitor.visitVarInsn(ALOAD, 0);
+ methodVisitor.visitMethodInsn(
+ INVOKEVIRTUAL,
+ "java/lang/StringBuilder",
+ "append",
+ "(Ljava/lang/Object;)Ljava/lang/StringBuilder;",
+ false);
+ methodVisitor.visitMethodInsn(
+ INVOKEVIRTUAL, "java/lang/StringBuilder", "toString", "()Ljava/lang/String;", false);
+ methodVisitor.visitMethodInsn(
+ INVOKEVIRTUAL, "java/io/PrintStream", "println", "(Ljava/lang/String;)V", false);
+ Label label1 = new Label();
+ methodVisitor.visitLabel(label1);
+ methodVisitor.visitLineNumber(10, label1);
+ methodVisitor.visitInsn(RETURN);
+ Label label2 = new Label();
+ methodVisitor.visitLabel(label2);
+ methodVisitor.visitLocalVariable(
+ "assertion", "Ljava/lang/AssertionError;", null, label0, label2, 0);
+ methodVisitor.visitMaxs(3, 1);
+ methodVisitor.visitEnd();
+ }
+ classWriter.visitEnd();
+
+ return classWriter.toByteArray();
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/rewrite/assertions/ClassWithAssertions.java b/src/test/java/com/android/tools/r8/rewrite/assertions/ClassWithAssertions.java
index 49fe85e..17139be 100644
--- a/src/test/java/com/android/tools/r8/rewrite/assertions/ClassWithAssertions.java
+++ b/src/test/java/com/android/tools/r8/rewrite/assertions/ClassWithAssertions.java
@@ -4,6 +4,13 @@
package com.android.tools.r8.rewrite.assertions;
+import org.objectweb.asm.ClassWriter;
+import org.objectweb.asm.FieldVisitor;
+import org.objectweb.asm.Label;
+import org.objectweb.asm.MethodVisitor;
+import org.objectweb.asm.Opcodes;
+import org.objectweb.asm.Type;
+
public class ClassWithAssertions {
int x = 0;
@@ -26,3 +33,238 @@
new ClassWithAssertions(Integer.parseInt(args[0])).getX();
}
}
+
+/* Below is an asmified dump of the above class */
+
+class ClassWithAssertionsDump implements Opcodes {
+
+ public static byte[] dump() {
+
+ ClassWriter classWriter = new ClassWriter(0);
+ FieldVisitor fieldVisitor;
+ MethodVisitor methodVisitor;
+
+ classWriter.visit(
+ V1_8,
+ ACC_PUBLIC | ACC_SUPER,
+ "com/android/tools/r8/rewrite/assertions/ClassWithAssertions",
+ null,
+ "java/lang/Object",
+ null);
+
+ classWriter.visitSource("ClassWithAssertions.java", null);
+
+ {
+ fieldVisitor = classWriter.visitField(0, "x", "I", null, null);
+ fieldVisitor.visitEnd();
+ }
+ {
+ fieldVisitor =
+ classWriter.visitField(
+ ACC_FINAL | ACC_STATIC | ACC_SYNTHETIC, "$assertionsDisabled", "Z", null, null);
+ fieldVisitor.visitEnd();
+ }
+ {
+ methodVisitor = classWriter.visitMethod(0, "<init>", "(I)V", null, null);
+ methodVisitor.visitCode();
+ Label label0 = new Label();
+ methodVisitor.visitLabel(label0);
+ methodVisitor.visitLineNumber(10, label0);
+ methodVisitor.visitVarInsn(ALOAD, 0);
+ methodVisitor.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V", false);
+ Label label1 = new Label();
+ methodVisitor.visitLabel(label1);
+ methodVisitor.visitLineNumber(8, label1);
+ methodVisitor.visitVarInsn(ALOAD, 0);
+ methodVisitor.visitInsn(ICONST_0);
+ methodVisitor.visitFieldInsn(
+ PUTFIELD, "com/android/tools/r8/rewrite/assertions/ClassWithAssertions", "x", "I");
+ Label label2 = new Label();
+ methodVisitor.visitLabel(label2);
+ methodVisitor.visitLineNumber(11, label2);
+ methodVisitor.visitVarInsn(ALOAD, 0);
+ methodVisitor.visitVarInsn(ILOAD, 1);
+ methodVisitor.visitFieldInsn(
+ PUTFIELD, "com/android/tools/r8/rewrite/assertions/ClassWithAssertions", "x", "I");
+ Label label3 = new Label();
+ methodVisitor.visitLabel(label3);
+ methodVisitor.visitLineNumber(12, label3);
+ methodVisitor.visitInsn(RETURN);
+ Label label4 = new Label();
+ methodVisitor.visitLabel(label4);
+ methodVisitor.visitLocalVariable(
+ "this",
+ "Lcom/android/tools/r8/rewrite/assertions/ClassWithAssertions;",
+ null,
+ label0,
+ label4,
+ 0);
+ methodVisitor.visitLocalVariable("x", "I", null, label0, label4, 1);
+ methodVisitor.visitMaxs(2, 2);
+ methodVisitor.visitEnd();
+ }
+ {
+ methodVisitor = classWriter.visitMethod(0, "condition", "()Z", null, null);
+ methodVisitor.visitCode();
+ Label label0 = new Label();
+ methodVisitor.visitLabel(label0);
+ methodVisitor.visitLineNumber(15, label0);
+ methodVisitor.visitVarInsn(ALOAD, 0);
+ methodVisitor.visitFieldInsn(
+ GETFIELD, "com/android/tools/r8/rewrite/assertions/ClassWithAssertions", "x", "I");
+ methodVisitor.visitInsn(ICONST_1);
+ Label label1 = new Label();
+ methodVisitor.visitJumpInsn(IF_ICMPNE, label1);
+ methodVisitor.visitInsn(ICONST_1);
+ Label label2 = new Label();
+ methodVisitor.visitJumpInsn(GOTO, label2);
+ methodVisitor.visitLabel(label1);
+ methodVisitor.visitFrame(Opcodes.F_SAME, 0, null, 0, null);
+ methodVisitor.visitInsn(ICONST_0);
+ methodVisitor.visitLabel(label2);
+ methodVisitor.visitFrame(Opcodes.F_SAME1, 0, null, 1, new Object[] {Opcodes.INTEGER});
+ methodVisitor.visitInsn(IRETURN);
+ Label label3 = new Label();
+ methodVisitor.visitLabel(label3);
+ methodVisitor.visitLocalVariable(
+ "this",
+ "Lcom/android/tools/r8/rewrite/assertions/ClassWithAssertions;",
+ null,
+ label0,
+ label3,
+ 0);
+ methodVisitor.visitMaxs(2, 1);
+ methodVisitor.visitEnd();
+ }
+ {
+ methodVisitor = classWriter.visitMethod(0, "getX", "()I", null, null);
+ methodVisitor.visitCode();
+ Label label0 = new Label();
+ methodVisitor.visitLabel(label0);
+ methodVisitor.visitLineNumber(19, label0);
+ methodVisitor.visitFieldInsn(GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;");
+ methodVisitor.visitLdcInsn("1");
+ methodVisitor.visitMethodInsn(
+ INVOKEVIRTUAL, "java/io/PrintStream", "println", "(Ljava/lang/String;)V", false);
+ Label label1 = new Label();
+ methodVisitor.visitLabel(label1);
+ methodVisitor.visitLineNumber(20, label1);
+ methodVisitor.visitFieldInsn(
+ GETSTATIC,
+ "com/android/tools/r8/rewrite/assertions/ClassWithAssertions",
+ "$assertionsDisabled",
+ "Z");
+ Label label2 = new Label();
+ methodVisitor.visitJumpInsn(IFNE, label2);
+ methodVisitor.visitVarInsn(ALOAD, 0);
+ methodVisitor.visitMethodInsn(
+ INVOKEVIRTUAL,
+ "com/android/tools/r8/rewrite/assertions/ClassWithAssertions",
+ "condition",
+ "()Z",
+ false);
+ methodVisitor.visitJumpInsn(IFNE, label2);
+ methodVisitor.visitTypeInsn(NEW, "java/lang/AssertionError");
+ methodVisitor.visitInsn(DUP);
+ methodVisitor.visitMethodInsn(
+ INVOKESPECIAL, "java/lang/AssertionError", "<init>", "()V", false);
+ methodVisitor.visitInsn(ATHROW);
+ methodVisitor.visitLabel(label2);
+ methodVisitor.visitLineNumber(21, label2);
+ methodVisitor.visitFrame(Opcodes.F_SAME, 0, null, 0, null);
+ methodVisitor.visitFieldInsn(GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;");
+ methodVisitor.visitLdcInsn("2");
+ methodVisitor.visitMethodInsn(
+ INVOKEVIRTUAL, "java/io/PrintStream", "println", "(Ljava/lang/String;)V", false);
+ Label label3 = new Label();
+ methodVisitor.visitLabel(label3);
+ methodVisitor.visitLineNumber(22, label3);
+ methodVisitor.visitVarInsn(ALOAD, 0);
+ methodVisitor.visitFieldInsn(
+ GETFIELD, "com/android/tools/r8/rewrite/assertions/ClassWithAssertions", "x", "I");
+ methodVisitor.visitInsn(IRETURN);
+ Label label4 = new Label();
+ methodVisitor.visitLabel(label4);
+ methodVisitor.visitLocalVariable(
+ "this",
+ "Lcom/android/tools/r8/rewrite/assertions/ClassWithAssertions;",
+ null,
+ label0,
+ label4,
+ 0);
+ methodVisitor.visitMaxs(2, 1);
+ methodVisitor.visitEnd();
+ }
+ {
+ methodVisitor =
+ classWriter.visitMethod(
+ ACC_PUBLIC | ACC_STATIC, "main", "([Ljava/lang/String;)V", null, null);
+ methodVisitor.visitCode();
+ Label label0 = new Label();
+ methodVisitor.visitLabel(label0);
+ methodVisitor.visitLineNumber(26, label0);
+ methodVisitor.visitTypeInsn(
+ NEW, "com/android/tools/r8/rewrite/assertions/ClassWithAssertions");
+ methodVisitor.visitInsn(DUP);
+ methodVisitor.visitVarInsn(ALOAD, 0);
+ methodVisitor.visitInsn(ICONST_0);
+ methodVisitor.visitInsn(AALOAD);
+ methodVisitor.visitMethodInsn(
+ INVOKESTATIC, "java/lang/Integer", "parseInt", "(Ljava/lang/String;)I", false);
+ methodVisitor.visitMethodInsn(
+ INVOKESPECIAL,
+ "com/android/tools/r8/rewrite/assertions/ClassWithAssertions",
+ "<init>",
+ "(I)V",
+ false);
+ methodVisitor.visitMethodInsn(
+ INVOKEVIRTUAL,
+ "com/android/tools/r8/rewrite/assertions/ClassWithAssertions",
+ "getX",
+ "()I",
+ false);
+ methodVisitor.visitInsn(POP);
+ Label label1 = new Label();
+ methodVisitor.visitLabel(label1);
+ methodVisitor.visitLineNumber(27, label1);
+ methodVisitor.visitInsn(RETURN);
+ Label label2 = new Label();
+ methodVisitor.visitLabel(label2);
+ methodVisitor.visitLocalVariable("args", "[Ljava/lang/String;", null, label0, label2, 0);
+ methodVisitor.visitMaxs(4, 1);
+ methodVisitor.visitEnd();
+ }
+ {
+ methodVisitor = classWriter.visitMethod(ACC_STATIC, "<clinit>", "()V", null, null);
+ methodVisitor.visitCode();
+ Label label0 = new Label();
+ methodVisitor.visitLabel(label0);
+ methodVisitor.visitLineNumber(7, label0);
+ methodVisitor.visitLdcInsn(
+ Type.getType("Lcom/android/tools/r8/rewrite/assertions/ClassWithAssertions;"));
+ methodVisitor.visitMethodInsn(
+ INVOKEVIRTUAL, "java/lang/Class", "desiredAssertionStatus", "()Z", false);
+ Label label1 = new Label();
+ methodVisitor.visitJumpInsn(IFNE, label1);
+ methodVisitor.visitInsn(ICONST_1);
+ Label label2 = new Label();
+ methodVisitor.visitJumpInsn(GOTO, label2);
+ methodVisitor.visitLabel(label1);
+ methodVisitor.visitFrame(Opcodes.F_SAME, 0, null, 0, null);
+ methodVisitor.visitInsn(ICONST_0);
+ methodVisitor.visitLabel(label2);
+ methodVisitor.visitFrame(Opcodes.F_SAME1, 0, null, 1, new Object[] {Opcodes.INTEGER});
+ methodVisitor.visitFieldInsn(
+ PUTSTATIC,
+ "com/android/tools/r8/rewrite/assertions/ClassWithAssertions",
+ "$assertionsDisabled",
+ "Z");
+ methodVisitor.visitInsn(RETURN);
+ methodVisitor.visitMaxs(1, 0);
+ methodVisitor.visitEnd();
+ }
+ classWriter.visitEnd();
+
+ return classWriter.toByteArray();
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/rewrite/assertions/RemoveAssertionsTest.java b/src/test/java/com/android/tools/r8/rewrite/assertions/RemoveAssertionsTest.java
index 4b88194..fac04f0 100644
--- a/src/test/java/com/android/tools/r8/rewrite/assertions/RemoveAssertionsTest.java
+++ b/src/test/java/com/android/tools/r8/rewrite/assertions/RemoveAssertionsTest.java
@@ -4,29 +4,29 @@
package com.android.tools.r8.rewrite.assertions;
-import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
+import static org.junit.Assume.assumeTrue;
-import com.android.tools.r8.CompilationMode;
-import com.android.tools.r8.DexIndexedConsumer;
-import com.android.tools.r8.OutputMode;
-import com.android.tools.r8.R8Command;
+import com.android.tools.r8.CompilationFailedException;
+import com.android.tools.r8.R8TestCompileResult;
import com.android.tools.r8.TestBase;
+import com.android.tools.r8.TestParameters;
import com.android.tools.r8.ToolHelper;
-import com.android.tools.r8.ToolHelper.ProcessResult;
import com.android.tools.r8.dex.Constants;
import com.android.tools.r8.naming.MemberNaming.MethodSignature;
-import com.android.tools.r8.origin.Origin;
-import com.android.tools.r8.utils.AndroidApp;
-import com.android.tools.r8.utils.InternalOptions;
+import com.android.tools.r8.utils.AndroidApiLevel;
+import com.android.tools.r8.utils.StringUtils;
import com.android.tools.r8.utils.codeinspector.ClassSubject;
import com.android.tools.r8.utils.codeinspector.CodeInspector;
import com.android.tools.r8.utils.codeinspector.MethodSubject;
-import com.google.common.collect.ImmutableList;
-import java.nio.file.Path;
-import java.util.function.Consumer;
+import java.util.Collection;
import java.util.function.Function;
+import org.junit.ClassRule;
import org.junit.Test;
+import org.junit.rules.TemporaryFolder;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.BeforeParam;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.ClassWriter;
@@ -138,20 +138,109 @@
}
}
+class CompilationResults {
+
+ final R8TestCompileResult allowAccess;
+ final R8TestCompileResult withAssertions;
+ final R8TestCompileResult withoutAssertions;
+
+ CompilationResults(
+ R8TestCompileResult allowAccess,
+ R8TestCompileResult withAssertions,
+ R8TestCompileResult withoutAssertions) {
+ this.allowAccess = allowAccess;
+ this.withAssertions = withAssertions;
+ this.withoutAssertions = withoutAssertions;
+ }
+}
+
+@RunWith(Parameterized.class)
public class RemoveAssertionsTest extends TestBase {
+ private final TestParameters parameters;
+
+ @Parameterized.Parameters(name = "{0}")
+ public static Collection<Object[]> data() {
+ return buildParameters(getTestParameters().withAllRuntimes().build());
+ }
+
+ public RemoveAssertionsTest(TestParameters parameters) {
+ this.parameters = parameters;
+ }
+
+ @ClassRule public static TemporaryFolder staticTemp = ToolHelper.getTemporaryFolderForTest();
+
+ @BeforeParam
+ public static void forceCompilation(TestParameters parameters) {
+ compilationResults.apply(parameters.getBackend());
+ }
+
+ private static Function<Backend, CompilationResults> compilationResults =
+ memoizeFunction(RemoveAssertionsTest::compileAll);
+
+ private static R8TestCompileResult compileWithAccessModification(Backend backend)
+ throws CompilationFailedException {
+ return testForR8(staticTemp, backend)
+ .addProgramClassFileData(ClassWithAssertionsDump.dump())
+ .addKeepMainRule(ClassWithAssertions.class)
+ .addKeepRules("-allowaccessmodification", "-dontobfuscate")
+ .addOptionsModification(o -> o.enableInlining = false)
+ .compile();
+ }
+
+ private static R8TestCompileResult compileCf(boolean disableAssertions)
+ throws CompilationFailedException {
+ return testForR8(staticTemp, Backend.CF)
+ .addProgramClassFileData(ClassWithAssertionsDump.dump())
+ .debug()
+ .noTreeShaking()
+ .noMinification()
+ .addOptionsModification(o -> o.disableAssertions = disableAssertions)
+ .compile();
+ }
+
+ private static byte[] identity(byte[] classBytes) {
+ return classBytes;
+ }
+
+ private static byte[] chromiumAssertionEnabler(byte[] classBytes) {
+ ClassWriter writer = new ClassWriter(0);
+ new ClassReader(classBytes).accept(new AssertionEnablerClassAdapter(writer), 0);
+ return writer.toByteArray();
+ }
+
+ private static R8TestCompileResult compileRegress110887293(Function<byte[], byte[]> rewriter)
+ throws CompilationFailedException {
+ return testForR8(staticTemp, Backend.DEX)
+ .addProgramClassFileData(
+ rewriter.apply(ClassWithAssertionsDump.dump()), ChromuimAssertionHookMockDump.dump())
+ .setMinApi(AndroidApiLevel.B)
+ .debug()
+ .noTreeShaking()
+ .noMinification()
+ .compile();
+ }
+
+ private static CompilationResults compileAll(Backend backend) throws CompilationFailedException {
+ R8TestCompileResult withAccess = compileWithAccessModification(backend);
+ if (backend == Backend.CF) {
+ return new CompilationResults(withAccess, compileCf(false), compileCf(true));
+ }
+ return new CompilationResults(
+ withAccess,
+ compileRegress110887293(RemoveAssertionsTest::chromiumAssertionEnabler),
+ compileRegress110887293(RemoveAssertionsTest::identity));
+ }
+
@Test
public void test() throws Exception {
+ // TODO(mkroghj) Why does this fail on JDK?
+ assumeTrue(parameters.isDexRuntime());
// Run with R8, but avoid inlining to really validate that the methods "condition"
// and "<clinit>" are gone.
- Class testClass = ClassWithAssertions.class;
- AndroidApp app = compileWithR8(
- ImmutableList.of(testClass),
- keepMainProguardConfiguration(testClass, true, false),
- options -> options.enableInlining = false);
- CodeInspector x = new CodeInspector(app);
-
- ClassSubject clazz = x.clazz(ClassWithAssertions.class);
+ CompilationResults results = compilationResults.apply(parameters.getBackend());
+ CodeInspector inspector = results.allowAccess.inspector();
+ ClassSubject clazz = inspector.clazz(ClassWithAssertions.class);
assertTrue(clazz.isPresent());
MethodSubject conditionMethod =
clazz.method(new MethodSignature("condition", "boolean", new String[]{}));
@@ -161,79 +250,54 @@
assertTrue(!clinit.isPresent());
}
- private Path buildTestToCf(Consumer<InternalOptions> consumer) throws Exception {
- Path outputJar = temp.getRoot().toPath().resolve("output.jar");
- R8Command command =
- ToolHelper.prepareR8CommandBuilder(readClasses(ClassWithAssertions.class))
- .setMode(CompilationMode.DEBUG)
- .setDisableTreeShaking(true)
- .setDisableMinification(true)
- .addLibraryFiles(ToolHelper.getJava8RuntimeJar())
- .setOutput(outputJar, OutputMode.ClassFile)
- .build();
- ToolHelper.runR8(command, consumer);
- return outputJar;
- }
-
@Test
public void testCfOutput() throws Exception {
+ assumeTrue(parameters.isCfRuntime());
String main = ClassWithAssertions.class.getCanonicalName();
- ProcessResult result;
+ CompilationResults results = compilationResults.apply(parameters.getBackend());
// Assertion is hit.
- result = ToolHelper.runJava(buildTestToCf(options -> {}), "-ea", main, "0");
- assertEquals(1, result.exitCode);
- assertEquals("1\n".replace("\n", System.lineSeparator()), result.stdout);
+ results
+ .withAssertions
+ .enableRuntimeAssertions()
+ .run(parameters.getRuntime(), main, "0")
+ .assertFailureWithOutput(StringUtils.lines("1"));
// Assertion is not hit.
- result = ToolHelper.runJava(buildTestToCf(options -> {}), "-ea", main, "1");
- assertEquals(0, result.exitCode);
- assertEquals("1\n2\n".replace("\n", System.lineSeparator()), result.stdout);
+ results
+ .withAssertions
+ .enableRuntimeAssertions()
+ .run(parameters.getRuntime(), main, "1")
+ .assertSuccessWithOutput(StringUtils.lines("1", "2"));
// Assertion is hit, but removed.
- result = ToolHelper.runJava(
- buildTestToCf(
- options -> options.disableAssertions = true), "-ea", main, "0");
- assertEquals(0, result.exitCode);
- assertEquals("1\n2\n".replace("\n", System.lineSeparator()), result.stdout);
- }
-
- private byte[] identity(byte[] classBytes) {
- return classBytes;
- }
-
- private byte[] chromiumAssertionEnabler(byte[] classBytes) {
- ClassWriter writer = new ClassWriter(0);
- new ClassReader(classBytes).accept(new AssertionEnablerClassAdapter(writer), 0);
- return writer.toByteArray();
- }
-
- private AndroidApp runRegress110887293(Function<byte[], byte[]> rewriter) throws Exception {
- return ToolHelper.runR8(
- R8Command.builder()
- .addClassProgramData(
- rewriter.apply(ToolHelper.getClassAsBytes(ClassWithAssertions.class)),
- Origin.unknown())
- .addClassProgramData(
- ToolHelper.getClassAsBytes(ChromuimAssertionHookMock.class), Origin.unknown())
- .setProgramConsumer(DexIndexedConsumer.emptyConsumer())
- .setMode(CompilationMode.DEBUG)
- .setDisableTreeShaking(true)
- .setDisableMinification(true)
- .build());
+ results
+ .withoutAssertions
+ .enableRuntimeAssertions()
+ .run(parameters.getRuntime(), main, "0")
+ .assertSuccessWithOutput(StringUtils.lines("1", "2"));
}
@Test
public void regress110887293() throws Exception {
- AndroidApp app;
+ assumeTrue(parameters.isDexRuntime());
+ String main = ClassWithAssertions.class.getCanonicalName();
+ CompilationResults results = compilationResults.apply(parameters.getBackend());
// Assertions removed for default assertion code.
- app = runRegress110887293(this::identity);
- assertEquals("1\n2\n", runOnArt(app, ClassWithAssertions.class.getCanonicalName(), "0"));
- assertEquals("1\n2\n", runOnArt(app, ClassWithAssertions.class.getCanonicalName(), "1"));
+ results
+ .withoutAssertions
+ .run(parameters.getRuntime(), main, "0")
+ .assertSuccessWithOutput(StringUtils.lines("1", "2"));
+ results
+ .withoutAssertions
+ .run(parameters.getRuntime(), main, "1")
+ .assertSuccessWithOutput(StringUtils.lines("1", "2"));
// Assertions not removed when default assertion code is not present.
- app = runRegress110887293(this::chromiumAssertionEnabler);
- assertEquals(
- "1\nGot AssertionError java.lang.AssertionError\n2\n".replace("\n", System.lineSeparator()),
- runOnArt(app, ClassWithAssertions.class.getCanonicalName(), "0"));
- assertEquals(
- "1\n2\n".replace("\n", System.lineSeparator()),
- runOnArt(app, ClassWithAssertions.class.getCanonicalName(), "1"));
+ results
+ .withAssertions
+ .run(parameters.getRuntime(), main, "0")
+ .assertSuccessWithOutput(
+ StringUtils.lines("1", "Got AssertionError java.lang.AssertionError", "2"));
+ results
+ .withAssertions
+ .run(parameters.getRuntime(), main, "1")
+ .assertSuccessWithOutput(StringUtils.lines("1", "2"));
}
}