More java8 debug tests
Adds new cases for lambda (using method reference) and default/static
method in interface.
Bug: 38218137
Bug: 37731140
Bug: 62290295
Change-Id: I5e387c6194cef313fbbd4b66e1d78db6ff5cbdf8
diff --git a/src/test/debugTestResourcesJava8/DebugDefaultMethod.java b/src/test/debugTestResourcesJava8/DebugInterfaceMethod.java
similarity index 77%
rename from src/test/debugTestResourcesJava8/DebugDefaultMethod.java
rename to src/test/debugTestResourcesJava8/DebugInterfaceMethod.java
index db216b3..b407698 100644
--- a/src/test/debugTestResourcesJava8/DebugDefaultMethod.java
+++ b/src/test/debugTestResourcesJava8/DebugInterfaceMethod.java
@@ -2,13 +2,17 @@
// 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.
-public class DebugDefaultMethod {
+public class DebugInterfaceMethod {
interface I {
default void doSomething(String msg) {
String name = getClass().getName();
System.out.println(name + ": " + msg);
}
+
+ static void printString(String msg) {
+ System.out.println(msg);
+ }
}
static class DefaultImpl implements I {
@@ -27,9 +31,14 @@
i.doSomething("Test");
}
+ private static void testStaticMethod() {
+ I.printString("I'm a static method in interface");
+ }
+
public static void main(String[] args) {
testDefaultMethod(new DefaultImpl());
testDefaultMethod(new OverrideImpl());
+ testStaticMethod();
}
}
diff --git a/src/test/debugTestResourcesJava8/DebugLambda.java b/src/test/debugTestResourcesJava8/DebugLambda.java
index c3b8695..007cd0c 100644
--- a/src/test/debugTestResourcesJava8/DebugLambda.java
+++ b/src/test/debugTestResourcesJava8/DebugLambda.java
@@ -16,8 +16,52 @@
printInt(() -> i + j);
}
- public static void main(String[] args) {
- DebugLambda.testLambda(5, 10);
+ private static void printInt2(I i) {
+ System.out.println(i.getInt());
}
+ public static void testLambdaWithMethodReference() {
+ printInt2(DebugLambda::returnOne);
+ }
+
+ private static int returnOne() {
+ return 1;
+ }
+
+ private static void printInt3(BinaryOpInterface i, int a, int b) {
+ System.out.println(i.binaryOp(a, b));
+ }
+
+ public static void testLambdaWithArguments(int i, int j) {
+ printInt3((a, b) -> {
+ return a + b;
+ }, i, j);
+ }
+
+ interface ObjectProvider {
+ Object foo(String a, String b, String c);
+ }
+
+ private static void testLambdaWithMethodReferenceAndConversion(ObjectProvider objectProvider) {
+ System.out.println(objectProvider.foo("A", "B", "C"));
+ }
+
+ public static void main(String[] args) {
+ DebugLambda.testLambda(5, 10);
+ DebugLambda.testLambdaWithArguments(5, 10);
+ DebugLambda.testLambdaWithMethodReference();
+ DebugLambda.testLambdaWithMethodReferenceAndConversion(DebugLambda::concatObjects);
+ }
+
+ private static Object concatObjects(Object... objects) {
+ StringBuilder sb = new StringBuilder();
+ for (Object o : objects) {
+ sb.append(o.toString());
+ }
+ return sb.toString();
+ }
+
+ interface BinaryOpInterface {
+ int binaryOp(int a, int b);
+ }
}
diff --git a/src/test/java/com/android/tools/r8/debug/DebugTestBase.java b/src/test/java/com/android/tools/r8/debug/DebugTestBase.java
index 9cffe15..4cef632 100644
--- a/src/test/java/com/android/tools/r8/debug/DebugTestBase.java
+++ b/src/test/java/com/android/tools/r8/debug/DebugTestBase.java
@@ -20,6 +20,7 @@
import java.util.Collections;
import java.util.List;
import java.util.Map;
+import java.util.Optional;
import java.util.Queue;
import java.util.TreeMap;
import java.util.function.Consumer;
@@ -245,7 +246,10 @@
}
protected final JUnit3Wrapper.Command checkNoLocal() {
- return inspect(t -> Assert.assertTrue(t.getLocalNames().isEmpty()));
+ return inspect(t -> {
+ List<String> localNames = t.getLocalNames();
+ Assert.assertTrue("Local variables: " + String.join(",", localNames), localNames.isEmpty());
+ });
}
protected final JUnit3Wrapper.Command checkLine(String sourceFile, int line) {
@@ -475,11 +479,13 @@
}
public void checkLocal(String localName) {
- getVariableAt(getLocation(), localName);
+ Optional<Variable> localVar = getVariableAt(getLocation(), localName);
+ Assert.assertTrue("No local '" + localName + "'", localVar.isPresent());
}
public void checkLocal(String localName, Value expectedValue) {
- Variable localVar = getVariableAt(getLocation(), localName);
+ Optional<Variable> localVar = getVariableAt(getLocation(), localName);
+ Assert.assertTrue("No local '" + localName + "'", localVar.isPresent());
// Get value
CommandPacket commandPacket = new CommandPacket(
@@ -488,8 +494,8 @@
commandPacket.setNextValueAsThreadID(getThreadId());
commandPacket.setNextValueAsFrameID(getFrameId());
commandPacket.setNextValueAsInt(1);
- commandPacket.setNextValueAsInt(localVar.getSlot());
- commandPacket.setNextValueAsByte(localVar.getTag());
+ commandPacket.setNextValueAsInt(localVar.get().getSlot());
+ commandPacket.setNextValueAsByte(localVar.get().getTag());
ReplyPacket replyPacket = getMirror().performCommand(commandPacket);
checkReplyPacket(replyPacket, "StackFrame.GetValues command");
int valuesCount = replyPacket.getNextValueAsInt();
@@ -594,11 +600,10 @@
return index >= varStart && index < varEnd;
}
- private Variable getVariableAt(Location location, String localName) {
+ private Optional<Variable> getVariableAt(Location location, String localName) {
return getVariablesAt(location).stream()
.filter(v -> localName.equals(v.getName()))
- .findFirst()
- .get();
+ .findFirst();
}
private List<Variable> getVariablesAt(Location location) {
@@ -858,13 +863,16 @@
@Override
public void perform(JUnit3Wrapper testBase) {
- Variable v = testBase.getVariableAt(testBase.debuggeeState.location, localName);
+ Optional<Variable> localVar = testBase
+ .getVariableAt(testBase.debuggeeState.location, localName);
+ Assert.assertTrue("No local '" + localName + "'", localVar.isPresent());
+
CommandPacket setValues = new CommandPacket(StackFrameCommandSet.CommandSetID,
StackFrameCommandSet.SetValuesCommand);
setValues.setNextValueAsThreadID(testBase.getDebuggeeState().getThreadId());
setValues.setNextValueAsFrameID(testBase.getDebuggeeState().getFrameId());
setValues.setNextValueAsInt(1);
- setValues.setNextValueAsInt(v.getSlot());
+ setValues.setNextValueAsInt(localVar.get().getSlot());
setValues.setNextValueAsValue(newValue);
ReplyPacket replyPacket = testBase.getMirror().performCommand(setValues);
testBase.checkReplyPacket(replyPacket, "StackFrame.SetValues");
diff --git a/src/test/java/com/android/tools/r8/debug/DefaultMethodTest.java b/src/test/java/com/android/tools/r8/debug/InterfaceMethodTest.java
similarity index 61%
rename from src/test/java/com/android/tools/r8/debug/DefaultMethodTest.java
rename to src/test/java/com/android/tools/r8/debug/InterfaceMethodTest.java
index e0eb5ea..a7dcb60 100644
--- a/src/test/java/com/android/tools/r8/debug/DefaultMethodTest.java
+++ b/src/test/java/com/android/tools/r8/debug/InterfaceMethodTest.java
@@ -9,13 +9,13 @@
import java.util.List;
import org.junit.Test;
-public class DefaultMethodTest extends DebugTestBase {
+public class InterfaceMethodTest extends DebugTestBase {
- private static final String SOURCE_FILE = "DebugDefaultMethod.java";
+ private static final String SOURCE_FILE = "DebugInterfaceMethod.java";
@Test
public void testDefaultMethod() throws Throwable {
- String debuggeeClass = "DebugDefaultMethod";
+ String debuggeeClass = "DebugInterfaceMethod";
String parameterName = "msg";
String localVariableName = "name";
@@ -23,13 +23,17 @@
commands.add(breakpoint(debuggeeClass, "testDefaultMethod"));
commands.add(run());
commands.add(checkMethod(debuggeeClass, "testDefaultMethod"));
- commands.add(checkLine(SOURCE_FILE, 27));
+ commands.add(checkLine(SOURCE_FILE, 31));
if (!supportsDefaultMethod()) {
// We desugared default method. This means we're going to step through an extra (forward)
// method first.
commands.add(stepInto());
}
commands.add(stepInto());
+ // TODO(shertz) we should see the local variable this even when desugaring.
+ if (supportsDefaultMethod()) {
+ commands.add(checkLocal("this"));
+ }
commands.add(checkLocal(parameterName));
commands.add(stepOver());
commands.add(checkLocal(parameterName));
@@ -43,7 +47,7 @@
@Test
public void testOverrideDefaultMethod() throws Throwable {
- String debuggeeClass = "DebugDefaultMethod";
+ String debuggeeClass = "DebugInterfaceMethod";
String parameterName = "msg";
String localVariableName = "newMsg";
@@ -52,13 +56,34 @@
commands.add(run());
commands.add(run() /* resume after 1st breakpoint */);
commands.add(checkMethod(debuggeeClass, "testDefaultMethod"));
- commands.add(checkLine(SOURCE_FILE, 27));
+ commands.add(checkLine(SOURCE_FILE, 31));
commands.add(stepInto());
- commands.add(checkMethod("DebugDefaultMethod$OverrideImpl", "doSomething"));
+ commands.add(checkMethod("DebugInterfaceMethod$OverrideImpl", "doSomething"));
+ commands.add(checkLocal("this"));
+ commands.add(checkLocal(parameterName));
+ commands.add(stepOver());
+ commands.add(checkLocal("this"));
+ commands.add(checkLocal(parameterName));
+ commands.add(checkLocal(localVariableName));
+ commands.add(run());
+
+ runDebugTestJava8(debuggeeClass, commands);
+ }
+
+ @Test
+ public void testStaticMethod() throws Throwable {
+ String debuggeeClass = "DebugInterfaceMethod";
+ String parameterName = "msg";
+
+ List<Command> commands = new ArrayList<>();
+ commands.add(breakpoint(debuggeeClass, "testStaticMethod"));
+ commands.add(run());
+ commands.add(checkMethod(debuggeeClass, "testStaticMethod"));
+ commands.add(checkLine(SOURCE_FILE, 35));
+ commands.add(stepInto());
commands.add(checkLocal(parameterName));
commands.add(stepOver());
commands.add(checkLocal(parameterName));
- commands.add(checkLocal(localVariableName));
commands.add(run());
runDebugTestJava8(debuggeeClass, commands);
diff --git a/src/test/java/com/android/tools/r8/debug/LambdaTest.java b/src/test/java/com/android/tools/r8/debug/LambdaTest.java
index 52d9c70..6bdbb90 100644
--- a/src/test/java/com/android/tools/r8/debug/LambdaTest.java
+++ b/src/test/java/com/android/tools/r8/debug/LambdaTest.java
@@ -4,17 +4,18 @@
package com.android.tools.r8.debug;
+import org.junit.Assert;
import org.junit.Test;
+// TODO(shertz) test local variables
public class LambdaTest extends DebugTestBase {
public static final String SOURCE_FILE = "DebugLambda.java";
@Test
- public void testLambdaDebugging() throws Throwable {
+ public void testLambda_ExpressionOnSameLine() throws Throwable {
String debuggeeClass = "DebugLambda";
String initialMethodName = "printInt";
- // TODO(shertz) test local variables
runDebugTestJava8(debuggeeClass,
breakpoint(debuggeeClass, initialMethodName),
run(),
@@ -24,4 +25,56 @@
checkLine(SOURCE_FILE, 16),
run());
}
+
+ @Test
+ public void testLambda_StatementOnNewLine() throws Throwable {
+ String debuggeeClass = "DebugLambda";
+ String initialMethodName = "printInt3";
+ runDebugTestJava8(debuggeeClass,
+ breakpoint(debuggeeClass, initialMethodName),
+ run(),
+ checkMethod(debuggeeClass, initialMethodName),
+ checkLine(SOURCE_FILE, 32),
+ stepInto(INTELLIJ_FILTER),
+ checkLine(SOURCE_FILE, 37),
+ run());
+ }
+
+ @Test
+ public void testLambda_StaticMethodReference_Trivial() throws Throwable {
+ String debuggeeClass = "DebugLambda";
+ String initialMethodName = "printInt2";
+ runDebugTestJava8(debuggeeClass,
+ breakpoint(debuggeeClass, initialMethodName),
+ run(),
+ checkMethod(debuggeeClass, initialMethodName),
+ checkLine(SOURCE_FILE, 20),
+ stepInto(INTELLIJ_FILTER),
+ isRunningJava() ? LambdaTest::doNothing : stepInto(INTELLIJ_FILTER),
+ checkMethod(debuggeeClass, "returnOne"),
+ checkLine(SOURCE_FILE, 28),
+ checkNoLocal(),
+ run());
+ }
+
+ @Test
+ public void testLambda_StaticMethodReference_NonTrivial() throws Throwable {
+ String debuggeeClass = "DebugLambda";
+ String initialMethodName = "testLambdaWithMethodReferenceAndConversion";
+ runDebugTestJava8(debuggeeClass,
+ breakpoint(debuggeeClass, initialMethodName),
+ run(),
+ checkMethod(debuggeeClass, initialMethodName),
+ checkLine(SOURCE_FILE, 46),
+ stepInto(INTELLIJ_FILTER),
+ inspect(t -> Assert.assertTrue(t.getCurrentMethodName().startsWith("lambda$"))),
+ stepInto(INTELLIJ_FILTER),
+ checkMethod(debuggeeClass, "concatObjects"),
+ checkLine(SOURCE_FILE, 57),
+ checkLocal("objects"),
+ run());
+ }
+
+ private static void doNothing(JUnit3Wrapper jUnit3Wrapper) {
+ }
}