Add source file checking in debug tests

Since a line number is related to a source file, let's check the
source file too.

Also fixes computation of the current line number.

Change-Id: I5bddde93f3bcbab7c14ce17b26c367d4d8db2956
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 8f2e9ce..b6ec466 100644
--- a/src/test/java/com/android/tools/r8/debug/DebugTestBase.java
+++ b/src/test/java/com/android/tools/r8/debug/DebugTestBase.java
@@ -244,8 +244,11 @@
     return inspect(t -> Assert.assertTrue(t.getLocalNames().isEmpty()));
   }
 
-  protected final JUnit3Wrapper.Command checkLine(int line) {
-    return inspect(t -> t.checkLine(line));
+  protected final JUnit3Wrapper.Command checkLine(String sourceFile, int line) {
+    return inspect(t -> {
+      Assert.assertEquals(sourceFile, t.getCurrentSourceFile());
+      Assert.assertEquals(line, t.getCurrentLineNumber());
+    });
   }
 
   protected final JUnit3Wrapper.Command checkMethod(String className, String methodName) {
@@ -477,11 +480,48 @@
         Assert.assertEquals(expectedValue, localValue);
       }
 
-      public void checkLine(int line) {
-        Location location = getLocation();
-        int currentLine = getMirror()
-            .getLineNumber(location.classID, location.methodID, location.index);
-        Assert.assertEquals(line, currentLine);
+      public int getCurrentLineNumber() {
+        ReplyPacket reply = getMirror().getLineTable(location.classID, location.methodID);
+        if (reply.getErrorCode() != 0) {
+          return -1;
+        }
+
+        long startCodeIndex = reply.getNextValueAsLong();
+        long endCodeIndex = reply.getNextValueAsLong();
+        int lines = reply.getNextValueAsInt();
+        int line = -1;
+        long previousLineCodeIndex = -1;
+        for (int i = 0; i < lines; ++i) {
+          long currentLineCodeIndex = reply.getNextValueAsLong();
+          int currentLineNumber = reply.getNextValueAsInt();
+
+          // Code indices are in ascending order.
+          assert currentLineCodeIndex >= startCodeIndex;
+          assert currentLineCodeIndex <= endCodeIndex;
+          assert currentLineCodeIndex > previousLineCodeIndex;
+          previousLineCodeIndex = currentLineCodeIndex;
+
+          if (location.index >= currentLineCodeIndex) {
+            line = currentLineNumber;
+          } else {
+            break;
+          }
+        }
+
+        return line;
+      }
+
+      public String getCurrentSourceFile() {
+        CommandPacket sourceFileCommand = new CommandPacket(
+            JDWPCommands.ReferenceTypeCommandSet.CommandSetID,
+            JDWPCommands.ReferenceTypeCommandSet.SourceFileCommand);
+        sourceFileCommand.setNextValueAsReferenceTypeID(location.classID);
+        ReplyPacket replyPacket = getMirror().performCommand(sourceFileCommand);
+        if (replyPacket.getErrorCode() != 0) {
+          return null;
+        } else {
+          return replyPacket.getNextValueAsString();
+        }
       }
 
       public List<String> getLocalNames() {
diff --git a/src/test/java/com/android/tools/r8/debug/DefaultMethodTest.java b/src/test/java/com/android/tools/r8/debug/DefaultMethodTest.java
index ea116a7..e0eb5ea 100644
--- a/src/test/java/com/android/tools/r8/debug/DefaultMethodTest.java
+++ b/src/test/java/com/android/tools/r8/debug/DefaultMethodTest.java
@@ -11,6 +11,8 @@
 
 public class DefaultMethodTest extends DebugTestBase {
 
+  private static final String SOURCE_FILE = "DebugDefaultMethod.java";
+
   @Test
   public void testDefaultMethod() throws Throwable {
     String debuggeeClass = "DebugDefaultMethod";
@@ -21,7 +23,7 @@
     commands.add(breakpoint(debuggeeClass, "testDefaultMethod"));
     commands.add(run());
     commands.add(checkMethod(debuggeeClass, "testDefaultMethod"));
-    commands.add(checkLine(27));
+    commands.add(checkLine(SOURCE_FILE, 27));
     if (!supportsDefaultMethod()) {
       // We desugared default method. This means we're going to step through an extra (forward)
       // method first.
@@ -50,7 +52,7 @@
     commands.add(run());
     commands.add(run() /* resume after 1st breakpoint */);
     commands.add(checkMethod(debuggeeClass, "testDefaultMethod"));
-    commands.add(checkLine(27));
+    commands.add(checkLine(SOURCE_FILE, 27));
     commands.add(stepInto());
     commands.add(checkMethod("DebugDefaultMethod$OverrideImpl", "doSomething"));
     commands.add(checkLocal(parameterName));
@@ -61,5 +63,4 @@
 
     runDebugTestJava8(debuggeeClass, commands);
   }
-
 }
diff --git a/src/test/java/com/android/tools/r8/debug/ExceptionTest.java b/src/test/java/com/android/tools/r8/debug/ExceptionTest.java
index 5f15f8f..3d4202b 100644
--- a/src/test/java/com/android/tools/r8/debug/ExceptionTest.java
+++ b/src/test/java/com/android/tools/r8/debug/ExceptionTest.java
@@ -10,6 +10,8 @@
  */
 public class ExceptionTest extends DebugTestBase {
 
+  public static final String SOURCE_FILE = "Exceptions.java";
+
   @Test
   public void testStepOnCatch() throws Throwable {
     int catchLine;
@@ -24,9 +26,9 @@
     runDebugTest("Exceptions",
         breakpoint("Exceptions", "catchException"),
         run(),
-        checkLine(9), // line of the method call throwing the exception
+        checkLine(SOURCE_FILE, 9), // line of the method call throwing the exception
         stepOver(),
-        checkLine(catchLine), // line of the catch declaration
+        checkLine(SOURCE_FILE, catchLine), // line of the catch declaration
         run());
   }
 
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 467ae09..52d9c70 100644
--- a/src/test/java/com/android/tools/r8/debug/LambdaTest.java
+++ b/src/test/java/com/android/tools/r8/debug/LambdaTest.java
@@ -8,6 +8,8 @@
 
 public class LambdaTest extends DebugTestBase {
 
+  public static final String SOURCE_FILE = "DebugLambda.java";
+
   @Test
   public void testLambdaDebugging() throws Throwable {
     String debuggeeClass = "DebugLambda";
@@ -17,9 +19,9 @@
         breakpoint(debuggeeClass, initialMethodName),
         run(),
         checkMethod(debuggeeClass, initialMethodName),
-        checkLine(12),
+        checkLine(SOURCE_FILE, 12),
         stepInto(INTELLIJ_FILTER),
-        checkLine(16),
+        checkLine(SOURCE_FILE, 16),
         run());
   }
 }
diff --git a/src/test/java/com/android/tools/r8/debug/LocalsTest.java b/src/test/java/com/android/tools/r8/debug/LocalsTest.java
index 0d72ab9..6132ace 100644
--- a/src/test/java/com/android/tools/r8/debug/LocalsTest.java
+++ b/src/test/java/com/android/tools/r8/debug/LocalsTest.java
@@ -3,7 +3,6 @@
 // BSD-style license that can be found in the LICENSE file.
 package com.android.tools.r8.debug;
 
-import com.android.tools.r8.debug.DebugTestBase;
 import org.apache.harmony.jpda.tests.framework.jdwp.Value;
 import org.junit.Test;
 
@@ -12,6 +11,8 @@
  */
 public class LocalsTest extends DebugTestBase {
 
+  public static final String SOURCE_FILE = "Locals.java";
+
   @Test
   public void testNoLocal() throws Throwable {
     final String className = "Locals";
@@ -20,11 +21,11 @@
         breakpoint(className, methodName),
         run(),
         checkMethod(className, methodName),
-        checkLine(8),
+        checkLine(SOURCE_FILE, 8),
         checkNoLocal(),
         stepOver(),
         checkMethod(className, methodName),
-        checkLine(9),
+        checkLine(SOURCE_FILE, 9),
         checkNoLocal(),
         run());
   }
@@ -37,10 +38,10 @@
         breakpoint(className, methodName),
         run(),
         checkMethod(className, methodName),
-        checkLine(12),
+        checkLine(SOURCE_FILE, 12),
         checkNoLocal(),
         stepOver(),
-        checkLine(13),
+        checkLine(SOURCE_FILE, 13),
         checkLocal("i", Value.createInt(Integer.MAX_VALUE)),
         run());
   }
@@ -57,14 +58,14 @@
         breakpoint(className, methodName),
         run(),
         checkMethod(className, methodName),
-        checkLine(17),
+        checkLine(SOURCE_FILE, 17),
         checkLocal("p", pValue),
         stepOver(),
-        checkLine(18),
+        checkLine(SOURCE_FILE, 18),
         checkLocal("p", pValue),
         checkLocal("c", cValue),
         stepOver(),
-        checkLine(19),
+        checkLine(SOURCE_FILE, 19),
         checkLocal("p", pValue),
         checkLocal("c", cValue),
         checkLocal("v", vValue),
@@ -84,16 +85,16 @@
         breakpoint(className, methodName),
         run(),
         checkMethod(className, methodName),
-        checkLine(17),
+        checkLine(SOURCE_FILE, 17),
         checkLocal("p", pValue),
         stepOver(),
-        checkLine(18),
+        checkLine(SOURCE_FILE, 18),
         checkLocal("p", pValue),
         checkLocal("c", cValue),
         setLocal("c", newValue),
         checkLocal("c", newValue),  // we should see the updated value
         stepOver(),
-        checkLine(19),
+        checkLine(SOURCE_FILE, 19),
         checkLocal("p", pValue),
         checkLocal("c", newValue),
         checkLocal("v", vValue),
@@ -109,15 +110,15 @@
         breakpoint(className, methodName),
         run(),
         checkMethod(className, methodName),
-        checkLine(23),
+        checkLine(SOURCE_FILE, 23),
         checkNoLocal(),
         stepOver(),
         checkMethod(className, methodName),
-        checkLine(24),
+        checkLine(SOURCE_FILE, 24),
         checkLocal("i", Value.createInt(0)),
         setLocal("i", newValueForI),
         stepOver(),
-        checkLine(25),
+        checkLine(SOURCE_FILE, 25),
         checkLocal("i", newValueForI),
         checkLocal("f", Value.createFloat(0)),
         run());
@@ -133,15 +134,15 @@
         breakpoint(className, methodName),
         run(),
         checkMethod(className, methodName),
-        checkLine(29),
+        checkLine(SOURCE_FILE, 29),
         checkNoLocal(),
         stepOver(),
         checkMethod(className, methodName),
-        checkLine(30),
+        checkLine(SOURCE_FILE, 30),
         checkLocal("i", oldValueForI),
         setLocal("i", newValueForI),
         stepOver(),
-        checkLine(33),
+        checkLine(SOURCE_FILE, 33),
         checkLocal("i", newValueForI),
         run());
   }
diff --git a/src/test/java/com/android/tools/r8/debug/MultipleReturnsTest.java b/src/test/java/com/android/tools/r8/debug/MultipleReturnsTest.java
index 0b7973e..1d708cf 100644
--- a/src/test/java/com/android/tools/r8/debug/MultipleReturnsTest.java
+++ b/src/test/java/com/android/tools/r8/debug/MultipleReturnsTest.java
@@ -10,16 +10,18 @@
  */
 public class MultipleReturnsTest extends DebugTestBase {
 
+  public static final String SOURCE_FILE = "MultipleReturns.java";
+
   @Test
   public void testMultipleReturns() throws Throwable {
     runDebugTest("MultipleReturns",
         breakpoint("MultipleReturns", "multipleReturns"),
         run(),
         stepOver(),
-        checkLine(16), // this should be the 1st return statement
+        checkLine(SOURCE_FILE, 16), // this should be the 1st return statement
         run(),
         stepOver(),
-        checkLine(18), // this should be the 2nd return statement
+        checkLine(SOURCE_FILE, 18), // this should be the 2nd return statement
         run());
   }
 }
diff --git a/src/test/java/com/android/tools/r8/debug/SyntheticMethodTest.java b/src/test/java/com/android/tools/r8/debug/SyntheticMethodTest.java
index a5b7d4e..8184c0c 100644
--- a/src/test/java/com/android/tools/r8/debug/SyntheticMethodTest.java
+++ b/src/test/java/com/android/tools/r8/debug/SyntheticMethodTest.java
@@ -11,18 +11,20 @@
 
 public class SyntheticMethodTest extends DebugTestBase {
 
+  public static final String SOURCE_FILE = "InnerAccessors.java";
+
   private void debugInnerAccessors(StepFilter stepFilter) throws Throwable {
     String debuggeeClass = "InnerAccessors";
     List<Command> commands = new ArrayList<>();
     commands.add(breakpoint("InnerAccessors$Inner", "callPrivateMethodInOuterClass"));
     commands.add(run());
-    commands.add(checkLine(13));
+    commands.add(checkLine(SOURCE_FILE, 13));
     commands.add(stepInto(stepFilter));  // skip synthetic accessor
     if (stepFilter == NO_FILTER) {
       commands.add(stepInto(stepFilter));
     }
     commands.add(checkMethod(debuggeeClass, "privateMethod"));
-    commands.add(checkLine(8));
+    commands.add(checkLine(SOURCE_FILE, 8));
     commands.add(run());
     runDebugTest(debuggeeClass, commands);
   }