blob: 67e62e852aeae63ecb97659138c70c7eb085fedf [file] [log] [blame]
// Copyright (c) 2017, 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.debug;
import com.android.tools.r8.CompilationMode;
import com.android.tools.r8.OutputMode;
import com.android.tools.r8.R8Command;
import com.android.tools.r8.ToolHelper;
import com.android.tools.r8.ToolHelper.DexVm.Version;
import com.android.tools.r8.debug.DebugTestBase.JUnit3Wrapper.DebuggeeState;
import com.android.tools.r8.origin.Origin;
import com.android.tools.r8.utils.FileUtils;
import com.google.common.collect.ImmutableList;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.stream.Stream;
import org.junit.Assume;
import org.junit.Ignore;
import org.junit.Test;
public class ExamplesDebugTest extends DebugTestBase {
private String clazzName;
private Path inputJar;
private Stream<DebuggeeState> input() throws Exception {
return streamDebugTest(new CfDebugTestConfig(inputJar), clazzName, ANDROID_FILTER);
}
private Stream<DebuggeeState> d8() throws Exception {
D8DebugTestConfig config = new D8DebugTestConfig().compileAndAdd(temp, inputJar);
return streamDebugTest(config, clazzName, ANDROID_FILTER);
}
private Stream<DebuggeeState> r8cf() throws Exception {
return streamDebugTest(getCfConfig("r8cf.jar"), clazzName, ANDROID_FILTER);
}
private DebugTestConfig getCfConfig(String outputName) throws Exception {
Path input = inputJar;
Path output = temp.newFolder().toPath().resolve(outputName);
ToolHelper.runR8(
R8Command.builder()
.addProgramFiles(input)
.addLibraryFiles(ToolHelper.getJava8RuntimeJar())
.setMode(CompilationMode.DEBUG)
.setOutput(output, OutputMode.ClassFile)
.setDisableTreeShaking(true)
.setDisableMinification(true)
.addProguardConfiguration(ImmutableList.of("-keepattributes *"), Origin.unknown())
.build());
return new CfDebugTestConfig(output);
}
@Test
public void testArithmetic() throws Throwable {
testDebugging("arithmetic", "Arithmetic");
}
@Test
public void testArrayAccess() throws Exception {
testDebugging("arrayaccess", "ArrayAccess");
}
@Test
public void testBArray() throws Exception {
testDebugging("barray", "BArray");
}
@Test
public void testBridgeMethod() throws Exception {
testDebugging("bridge", "BridgeMethod");
}
@Test
public void testCommonSubexpressionElimination() throws Exception {
testDebugging("cse", "CommonSubexpressionElimination");
}
@Test
public void testConstants() throws Exception {
testDebugging("constants", "Constants");
}
@Test
public void testControlFlow() throws Exception {
testDebugging("controlflow", "ControlFlow");
}
@Test
public void testConversions() throws Exception {
testDebugging("conversions", "Conversions");
}
@Test
public void testFloatingPointValuedAnnotation() throws Exception {
testDebugging("floating_point_annotations", "FloatingPointValuedAnnotationTest");
}
@Test
public void testFilledArray() throws Exception {
testDebugging("filledarray", "FilledArray");
}
@Test
public void testHello() throws Exception {
testDebugging("hello", "Hello");
}
@Test
public void testIfStatements() throws Exception {
testDebugging("ifstatements", "IfStatements");
}
@Test
public void testInstanceVariable() throws Exception {
testDebugging("instancevariable", "InstanceVariable");
}
@Test
public void testInstanceofString() throws Exception {
testDebugging("instanceofstring", "InstanceofString");
}
@Test
public void testInvoke() throws Exception {
testDebugging("invoke", "Invoke");
}
@Test
public void testJumboString() throws Exception {
testDebugging("jumbostring", "JumboString");
}
@Test
public void testLoadConst() throws Exception {
testDebugging("loadconst", "LoadConst");
}
@Test
public void testUdpServer() throws Exception {
// TODO(b/79671093): We don't match JVM's behavior on this example.
testDebuggingJvmOutputOnly("loop", "UdpServer");
}
@Test
public void testRegAlloc() throws Exception {
testDebugging("regalloc", "RegAlloc");
}
@Test
public void testReturns() throws Exception {
testDebugging("returns", "Returns");
}
@Test
public void testStaticField() throws Exception {
// TODO(b/79671093): D8 has different line number info during stepping.
testDebuggingJvmOnly("staticfield", "StaticField");
}
@Test
public void testStringBuilding() throws Exception {
testDebugging("stringbuilding", "StringBuilding");
}
@Test
public void testSwitches() throws Exception {
testDebugging("switches", "Switches");
}
@Test
public void testSync() throws Exception {
// TODO(b/79671093): Line number mismatch in D8.
testDebuggingJvmOnly("sync", "Sync");
}
@Test
public void testThrowing() throws Exception {
// TODO(b/79671093): D8 has unexpected variables (this in throwing.c <init>).
testDebuggingJvmOnly("throwing", "Throwing");
}
@Test
public void testTrivial() throws Exception {
testDebugging("trivial", "Trivial");
}
@Test
public void testTryCatch() throws Exception {
testDebugging("trycatch", "TryCatch");
}
@Test
public void testNestedTryCatches() throws Exception {
testDebugging("nestedtrycatches", "NestedTryCatches");
}
@Test
public void testTryCatchMany() throws Exception {
testDebugging("trycatchmany", "TryCatchMany");
}
@Test
public void testInvokeEmpty() throws Exception {
testDebugging("invokeempty", "InvokeEmpty");
}
@Test
public void testRegress() throws Exception {
testDebugging("regress", "Regress");
}
@Test
public void testRegress2() throws Exception {
testDebugging("regress2", "Regress2");
}
@Test
public void testRegress37726195() throws Exception {
testDebugging("regress_37726195", "Regress");
}
@Test
public void testRegress37658666() throws Exception {
testDebugging("regress_37658666", "Regress");
}
@Test
public void testRegress37875803() throws Exception {
testDebugging("regress_37875803", "Regress");
}
@Test
public void testRegress37955340() throws Exception {
testDebugging("regress_37955340", "Regress");
}
@Test
public void testRegress62300145() throws Exception {
// TODO(b/67936230): Executes differently for Java 8 and 9, so don't compare to DEX output.
testDebuggingJvmOnly("regress_62300145", "Regress");
}
@Test
public void testRegress64881691() throws Exception {
testDebugging("regress_64881691", "Regress");
}
@Test
public void testRegress65104300() throws Exception {
testDebugging("regress_65104300", "Regress");
}
@Ignore("TODO(b/79671093): This test seems to take forever")
@Test
public void testRegress70703087() throws Exception {
testDebugging("regress_70703087", "Test");
}
@Test
public void testRegress70736958() throws Exception {
testDebugging("regress_70736958", "Test");
}
@Test
public void testRegress70737019() throws Exception {
testDebugging("regress_70737019", "Test");
}
@Test
public void testRegress72361252() throws Exception {
testDebugging("regress_72361252", "Test");
}
@Test
public void testMemberrebinding2() throws Exception {
testDebugging("memberrebinding2", "Memberrebinding");
}
@Test
public void testMemberrebinding3() throws Exception {
testDebugging("memberrebinding3", "Memberrebinding");
}
@Test
public void testMinification() throws Exception {
testDebugging("minification", "Minification");
}
@Test
public void testEnclosingmethod() throws Exception {
testDebugging("enclosingmethod", "Main");
}
@Test
public void testEnclosingmethod_proguarded() throws Exception {
// TODO(b/79671093): We don't match JVM's behavior on this example.
testDebuggingJvmOutputOnly("enclosingmethod_proguarded", "Main");
}
@Test
public void testInterfaceinlining() throws Exception {
testDebugging("interfaceinlining", "Main");
}
@Test
public void testSwitchmaps() throws Exception {
// TODO(b/79671093): D8 has different line number info during stepping.
testDebuggingJvmOnly("switchmaps", "Switches");
}
private void testDebugging(String pkg, String clazz) throws Exception {
init(pkg, clazz)
.add("Input", input())
.add("R8/CfSourceCode", r8cf())
.add("D8", d8())
// When running on CF and DEX runtimes, filter down to states within the test package.
.setFilter(state -> state.getClassName().startsWith(pkg))
.compare();
}
private void testDebuggingJvmOnly(String pkg, String clazz) throws Exception {
init(pkg, clazz)
.add("Input", input())
.add("R8/CfSourceCode", r8cf())
.compare();
}
private void testDebuggingJvmOutputOnly(String pkg, String clazz) throws Exception {
init(pkg, clazz)
.add("R8/CfSourceCode", r8cf())
.run();
}
private DebugStreamComparator init(String pkg, String clazz) throws Exception {
// See verifyStateLocation in DebugTestBase.
Assume.assumeTrue(
"Streaming on Dalvik DEX runtimes has some unknown interference issue",
ToolHelper.getDexVm().getVersion().isAtLeast(Version.V6_0_1));
Assume.assumeTrue(
"Skipping test "
+ testName.getMethodName()
+ " because debug tests are not yet supported on Windows",
!ToolHelper.isWindows());
clazzName = pkg + "." + clazz;
inputJar =
Paths.get(ToolHelper.EXAMPLES_BUILD_DIR, pkg + "_debuginfo_all" + FileUtils.JAR_EXTENSION);
return new DebugStreamComparator();
}
}