Add DebugInfoTest

Bug: 77522100
Change-Id: I3da8bceffc4bfe3eb6c4a16be64e263ccb209cde
diff --git a/src/main/java/com/android/tools/r8/utils/InternalOptions.java b/src/main/java/com/android/tools/r8/utils/InternalOptions.java
index dc0cd0f..42775d2 100644
--- a/src/main/java/com/android/tools/r8/utils/InternalOptions.java
+++ b/src/main/java/com/android/tools/r8/utils/InternalOptions.java
@@ -9,6 +9,7 @@
 import com.android.tools.r8.ProgramConsumer;
 import com.android.tools.r8.StringConsumer;
 import com.android.tools.r8.dex.Marker;
+import com.android.tools.r8.errors.CompilationError;
 import com.android.tools.r8.errors.InvalidDebugInfoException;
 import com.android.tools.r8.graph.DexEncodedMethod;
 import com.android.tools.r8.graph.DexItemFactory;
@@ -100,6 +101,8 @@
   public boolean verbose = false;
   // Silencing output.
   public boolean quiet = false;
+  // Throw exception if there is a warning about invalid debug info.
+  public boolean invalidDebugInfoFatal = false;
 
   // Hidden marker for classes.dex
   private boolean hasMarker = false;
@@ -268,6 +271,9 @@
 
   public void warningInvalidDebugInfo(
       DexEncodedMethod method, Origin origin, InvalidDebugInfoException e) {
+    if (invalidDebugInfoFatal) {
+      throw new CompilationError("Fatal warning: Invalid debug info", e);
+    }
     synchronized (warningInvalidDebugInfo) {
       warningInvalidDebugInfo.computeIfAbsent(
           origin, k -> new ArrayList<>()).add(new Pair<>(method, e.getMessage()));
diff --git a/src/test/java/com/android/tools/r8/cf/DebugInfoTest.java b/src/test/java/com/android/tools/r8/cf/DebugInfoTest.java
new file mode 100644
index 0000000..6e009e8
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/cf/DebugInfoTest.java
@@ -0,0 +1,27 @@
+// 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.
+package com.android.tools.r8.cf;
+
+public class DebugInfoTest {
+
+  public static void main(String[] args) {
+    if (args.length > 0) {
+      arg = args.length % 2 == 0;
+      DebugInfoTest.method();
+    }
+  }
+
+  private static boolean arg;
+
+  private static void method() {
+    int intVar;
+    if (arg) {
+      float floatVar1 = 0f;
+      intVar = (int) floatVar1;
+    } else {
+      float floatVar2 = 0f;
+      intVar = (int) floatVar2;
+    }
+  }
+}
diff --git a/src/test/java/com/android/tools/r8/cf/DebugInfoTestRunner.java b/src/test/java/com/android/tools/r8/cf/DebugInfoTestRunner.java
new file mode 100644
index 0000000..fed7637
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/cf/DebugInfoTestRunner.java
@@ -0,0 +1,68 @@
+// 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.
+package com.android.tools.r8.cf;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import com.android.tools.r8.ClassFileConsumer;
+import com.android.tools.r8.CompilationMode;
+import com.android.tools.r8.ProgramConsumer;
+import com.android.tools.r8.R8Command;
+import com.android.tools.r8.R8Command.Builder;
+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;
+import org.junit.Test;
+
+public class DebugInfoTestRunner extends TestBase {
+  static final Class CLASS = DebugInfoTest.class;
+
+  @Test
+  public void test() throws Exception {
+    ProcessResult runInput =
+        ToolHelper.runJava(ToolHelper.getClassPathForTests(), CLASS.getCanonicalName());
+    assertEquals(0, runInput.exitCode);
+    Path out1 = temp.getRoot().toPath().resolve("out1.zip");
+    build(
+        builder -> builder.addClassProgramData(ToolHelper.getClassAsBytes(CLASS), Origin.unknown()),
+        new ClassFileConsumer.ArchiveConsumer(out1));
+    ProcessResult run1 = ToolHelper.runJava(out1, CLASS.getCanonicalName());
+    assertEquals(runInput.toString(), run1.toString());
+    Path out2 = temp.getRoot().toPath().resolve("out2.zip");
+    boolean invalidDebugInfo = false;
+    try {
+      build(builder -> builder.addProgramFiles(out1), new ClassFileConsumer.ArchiveConsumer(out2));
+    } catch (CompilationError e) {
+      invalidDebugInfo = e.getCause() instanceof InvalidDebugInfoException;
+    }
+    // TODO(b/77522100): Change to assertFalse when fixed.
+    assertTrue(invalidDebugInfo);
+    if (!invalidDebugInfo) {
+      ProcessResult run2 = ToolHelper.runJava(out2, CLASS.getCanonicalName());
+      assertEquals(runInput.toString(), run2.toString());
+    }
+  }
+
+  private void build(ThrowingConsumer<Builder, Exception> input, ProgramConsumer consumer)
+      throws Exception {
+    Builder builder =
+        R8Command.builder()
+            .setMode(CompilationMode.DEBUG)
+            .addLibraryFiles(ToolHelper.getAndroidJar(ToolHelper.getMinApiLevelForDexVm()))
+            .setProgramConsumer(consumer);
+    input.accept(builder);
+    ToolHelper.runR8(
+        builder.build(),
+        o -> {
+          o.invalidDebugInfoFatal = true;
+          o.enableInlining = false;
+        });
+  }
+}