Merge "Make all private fields public."
diff --git a/build.gradle b/build.gradle
index 4caf5fa..7d13d0c 100644
--- a/build.gradle
+++ b/build.gradle
@@ -29,6 +29,12 @@
         }
         output.resourcesDir = 'build/classes/debugTestResources'
     }
+    debugTestResourcesJava8 {
+        java {
+            srcDirs = ['src/test/debugTestResourcesJava8']
+        }
+        output.resourcesDir = 'build/classes/debugTestResourcesJava8'
+    }
     examples {
         java {
             srcDirs = ['src/test/examples']
@@ -295,13 +301,12 @@
 
 task createArtTests(type: Exec) {
     def outputDir = "build/generated/test/java/com/android/tools/r8/art"
-    def createArtTestsScript = "scripts/create-art-tests.sh"
+    def createArtTestsScript = "tools/create_art_tests.py"
     inputs.file "tests/art.tar.gz"
     inputs.file createArtTestsScript
     outputs.dir outputDir
     dependsOn downloadDeps
-    executable "bash"
-    args "${projectDir}/${createArtTestsScript}"
+    commandLine "python", createArtTestsScript
     workingDir = projectDir
 }
 
@@ -352,7 +357,6 @@
 }
 
 task buildDebugTestResourcesJars {
-    dependsOn downloadDeps
     def resourcesDir = file("src/test/debugTestResources")
     def hostJar = "debug_test_resources.jar"
     task "compile_debugTestResources"(type: JavaCompile) {
@@ -369,7 +373,25 @@
         from "build/test/debugTestResources/classes"
         include "**/*.class"
     }
+    def java8ResourcesDir = file("src/test/debugTestResourcesJava8")
+    def java8HostJar = "debug_test_resources_java8.jar"
+    task "compile_debugTestResourcesJava8"(type: JavaCompile) {
+        source = fileTree(dir: java8ResourcesDir, include: '**/*.java')
+        destinationDir = file("build/test/debugTestResourcesJava8/classes")
+        classpath = sourceSets.main.compileClasspath
+        sourceCompatibility = JavaVersion.VERSION_1_8
+        targetCompatibility = JavaVersion.VERSION_1_8
+        options.compilerArgs += ["-g", "-Xlint:-options"]
+    }
+    task "jar_debugTestResourcesJava8"(type: Jar, dependsOn: "compile_debugTestResourcesJava8") {
+        archiveName = java8HostJar
+        destinationDir = file("build/test/")
+        from "build/test/debugTestResourcesJava8/classes"
+        include "**/*.class"
+    }
+    dependsOn downloadDeps
     dependsOn jar_debugTestResources
+    dependsOn jar_debugTestResourcesJava8
 }
 
 task buildExampleJars {
diff --git a/scripts/create-art-tests.sh b/scripts/create-art-tests.sh
deleted file mode 100755
index dc6d6d2..0000000
--- a/scripts/create-art-tests.sh
+++ /dev/null
@@ -1,75 +0,0 @@
-#!/bin/bash
-#
-# Copyright (c) 2016, 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.
-
-function generate_test() {
-  local name=$1
-  local testClassName=$2
-  local testGeneratingToolchain=$3
-  # The bash uppercase substitution ^^ is not supported on the bash version on Mac OS.
-  local testGeneratingToolchainEnum=$(echo $testGeneratingToolchain | tr /a-z/ /A-Z/)
-  local fileName=$4
-  local compilerUnderTest=$5
-  local compilerUnderTestEnum=$(echo ${compilerUnderTest} | tr /a-z/ /A-Z/)
-
-  cat <<EOF > $fileName
-// Copyright (c) 2016, 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.art.${testGeneratingToolchain}.${compilerUnderTest};
-
-import static com.android.tools.r8.R8RunArtTestsTest.DexTool.${testGeneratingToolchainEnum};
-
-import com.android.tools.r8.R8RunArtTestsTest;
-import org.junit.Test;
-
-/**
- * Auto-generated test for the art ${name} test using the ${testGeneratingToolchain} toolchain.
- *
- * DO NOT EDIT THIS FILE. EDIT THE HERE DOCUMENT TEMPLATE IN scripts/create-art-tests.sh INSTEAD!
- */
-public class ${testClassName} extends R8RunArtTestsTest {
-
-    public ${testClassName}() {
-      super("${name}", ${testGeneratingToolchainEnum});
-    }
-
-    @Test
-    public void run${testClassName}() throws Throwable {
-      // For testing with other Art VMs than the default pass the VM version as a argument to
-      // runArtTest, e.g. runArtTest(ToolHelper.ART_4_4_4).
-      runArtTest(CompilerUnderTest.${compilerUnderTestEnum});
-    }
-}
-EOF
-}
-
-TESTDIR="tests/art"
-TOOLCHAINS=("dx" "jack" "none")
-DESTINATIONDIR="build/generated/test/java/com/android/tools/r8/art"
-
-if [ ! -e $TESTDIR ]; then
-  echo "Missing art tests in $TESTDIR."
-  exit
-fi
-
-for TOOLCHAIN in ${TOOLCHAINS[@]}; do
-  for d in $DESTINATIONDIR/$TOOLCHAIN/r8 $DESTINATIONDIR/$TOOLCHAIN/d8; do
-    rm -rf $d
-    mkdir -p $d
-  done
-  # class files are found in the dx directory.
-  if [ "$TOOLCHAIN" == "none" ]; then
-    SOURCEDIR=${TESTDIR}/dx
-  else
-    SOURCEDIR=${TESTDIR}/${TOOLCHAIN}
-  fi
-  for TEST in ${SOURCEDIR}/*; do
-    TESTNAME=$(basename $TEST)
-    TESTCLASSNAME="Art${TESTNAME//-/_}Test"
-    generate_test $TESTNAME $TESTCLASSNAME ${TOOLCHAIN} $DESTINATIONDIR/$TOOLCHAIN/r8/$TESTCLASSNAME.java r8
-    generate_test $TESTNAME $TESTCLASSNAME ${TOOLCHAIN} $DESTINATIONDIR/$TOOLCHAIN/d8/$TESTCLASSNAME.java d8
-  done
-done
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/ClassProcessor.java b/src/main/java/com/android/tools/r8/ir/desugar/ClassProcessor.java
index ba15c9d..ecda01e 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/ClassProcessor.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/ClassProcessor.java
@@ -115,7 +115,7 @@
     // by this class as well as its superclasses.
     DexClass current = clazz;
     while (true) {
-      for (DexType type : clazz.interfaces.values) {
+      for (DexType type : current.interfaces.values) {
         helper.merge(getOrCreateInterfaceInfo(type));
       }
 
@@ -139,7 +139,7 @@
     current = clazz;
     while (true) {
       // Hide candidates by virtual method of the class.
-      hideCandidates(clazz.virtualMethods, candidates, toBeImplemented);
+      hideCandidates(current.virtualMethods, candidates, toBeImplemented);
       if (candidates.isEmpty()) {
         return toBeImplemented;
       }
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/Inliner.java b/src/main/java/com/android/tools/r8/ir/optimize/Inliner.java
index 11548bc..bc9b95e 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/Inliner.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/Inliner.java
@@ -138,8 +138,13 @@
         assert target.getCode().isDexCode();
         return target.buildIR(generator, options);
       } else {
-        assert target.getCode().isJarCode();
-        IRCode code = target.getCode().asJarCode().buildIR(target, generator, options);
+        // Build the IR for a yet not processed method, and perform minimal IR processing.
+        IRCode code;
+        if (target.getCode().isJarCode()) {
+          code = target.getCode().asJarCode().buildIR(target, generator, options);
+        } else {
+          code = target.getCode().asDexCode().buildIR(target, generator, options);
+        }
         new LensCodeRewriter(graphLense, appInfo).rewrite(code, target);
         return code;
       }
diff --git a/src/main/java/com/android/tools/r8/ir/regalloc/LinearScanRegisterAllocator.java b/src/main/java/com/android/tools/r8/ir/regalloc/LinearScanRegisterAllocator.java
index f2d039d..f621c67 100644
--- a/src/main/java/com/android/tools/r8/ir/regalloc/LinearScanRegisterAllocator.java
+++ b/src/main/java/com/android/tools/r8/ir/regalloc/LinearScanRegisterAllocator.java
@@ -429,9 +429,48 @@
   private boolean performAllocation(ArgumentReuseMode mode) {
     boolean result = performAllocationWithoutMoveInsertion(mode);
     insertMoves();
+    if (mode == ArgumentReuseMode.DISALLOW_ARGUMENT_REUSE) {
+      // Now that we know the max register number we can compute whether it is safe to use
+      // argument registers in place. If it is, we redo move insertion to get rid of the moves
+      // caused by splitting of the argument registers.
+      if (unsplitArguments()) {
+        removeSpillAndPhiMoves();
+        insertMoves();
+      }
+    }
     return result;
   }
 
+  // When argument register reuse is disallowed, we split argument values to make sure that
+  // we can get the argument into low enough registers at uses that require low numbers. After
+  // register allocation we can check if it is safe to just use the argument register itself
+  // for all uses and thereby avoid moving argument values around.
+  private boolean unsplitArguments() {
+    boolean argumentRegisterUnsplit = false;
+    Value current = preArgumentSentinelValue;
+    while (current != null) {
+      LiveIntervals intervals = current.getLiveIntervals();
+      assert intervals.getRegisterLimit() == Constants.U16BIT_MAX;
+      boolean canUseArgumentRegister = true;
+      for (LiveIntervals child : intervals.getSplitChildren()) {
+        if (child.getRegisterLimit() < registersUsed()) {
+          canUseArgumentRegister = false;
+          break;
+        }
+      }
+      if (canUseArgumentRegister) {
+        argumentRegisterUnsplit = true;
+        for (LiveIntervals child : intervals.getSplitChildren()) {
+          child.clearRegisterAssignment();
+          child.setRegister(intervals.getRegister());
+          child.setSpilled(false);
+        }
+      }
+      current = current.getNextConsecutive();
+    }
+    return argumentRegisterUnsplit;
+  }
+
   private void removeSpillAndPhiMoves() {
     for (BasicBlock block : code.blocks) {
       InstructionListIterator it = block.listIterator();
diff --git a/src/test/debugTestResourcesJava8/DebugDefaultMethod.java b/src/test/debugTestResourcesJava8/DebugDefaultMethod.java
new file mode 100644
index 0000000..db216b3
--- /dev/null
+++ b/src/test/debugTestResourcesJava8/DebugDefaultMethod.java
@@ -0,0 +1,35 @@
+// 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.
+
+public class DebugDefaultMethod {
+
+  interface I {
+    default void doSomething(String msg) {
+      String name = getClass().getName();
+      System.out.println(name + ": " + msg);
+    }
+  }
+
+  static class DefaultImpl implements I {
+  }
+
+  static class OverrideImpl implements I {
+
+    @Override
+    public void doSomething(String msg) {
+      String newMsg = "OVERRIDE" + msg;
+      System.out.println(newMsg);
+    }
+  }
+
+  private static void testDefaultMethod(I i) {
+    i.doSomething("Test");
+  }
+
+  public static void main(String[] args) {
+    testDefaultMethod(new DefaultImpl());
+    testDefaultMethod(new OverrideImpl());
+  }
+
+}
diff --git a/src/test/debugTestResourcesJava8/DebugLambda.java b/src/test/debugTestResourcesJava8/DebugLambda.java
new file mode 100644
index 0000000..c3b8695
--- /dev/null
+++ b/src/test/debugTestResourcesJava8/DebugLambda.java
@@ -0,0 +1,23 @@
+// 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.
+
+public class DebugLambda {
+
+  interface I {
+    int getInt();
+  }
+
+  private static void printInt(I i) {
+    System.out.println(i.getInt());
+  }
+
+  public static void testLambda(int i, int j) {
+    printInt(() -> i + j);
+  }
+
+  public static void main(String[] args) {
+    DebugLambda.testLambda(5, 10);
+  }
+
+}
diff --git a/src/test/examplesAndroidN/interfacemethods/DefaultMethods.java b/src/test/examplesAndroidN/interfacemethods/DefaultMethods.java
index 49e792c..ef49f4e 100644
--- a/src/test/examplesAndroidN/interfacemethods/DefaultMethods.java
+++ b/src/test/examplesAndroidN/interfacemethods/DefaultMethods.java
@@ -6,7 +6,24 @@
 
 public class DefaultMethods {
 
+  interface I3 {
+    default int getValue() {
+      return 1;
+    }
+
+  }
+
+  static class C3 {
+    public int getValue() {
+      return 2;
+    }
+  }
+
+  static class C4 extends C3 implements I3 {
+  }
+
   public static void main(String[] args) {
     new C2().d1();
+    System.out.println(new C4().getValue());
   }
 }
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 0b042a9..5f9a95c 100644
--- a/src/test/java/com/android/tools/r8/debug/DebugTestBase.java
+++ b/src/test/java/com/android/tools/r8/debug/DebugTestBase.java
@@ -4,11 +4,12 @@
 package com.android.tools.r8.debug;
 
 import com.android.tools.r8.CompilationMode;
-import com.android.tools.r8.D8;
 import com.android.tools.r8.D8Command;
 import com.android.tools.r8.ToolHelper;
 import com.android.tools.r8.ToolHelper.ArtCommandBuilder;
 import com.android.tools.r8.ToolHelper.DexVm;
+import com.android.tools.r8.dex.Constants;
+import com.android.tools.r8.utils.OffOrAuto;
 import com.google.common.collect.ImmutableList;
 import java.io.File;
 import java.nio.file.Path;
@@ -78,11 +79,14 @@
 
   private static final Path DEBUGGEE_JAR = Paths
       .get(ToolHelper.BUILD_DIR, "test", "debug_test_resources.jar");
+  private static final Path DEBUGGEE_JAVA8_JAR = Paths
+      .get(ToolHelper.BUILD_DIR, "test", "debug_test_resources_java8.jar");
 
   @ClassRule
   public static TemporaryFolder temp = new TemporaryFolder();
   private static Path jdwpDexD8 = null;
   private static Path debuggeeDexD8 = null;
+  private static Path debuggeeJava8DexD8 = null;
 
   @Rule
   public TestName testName = new TestName();
@@ -95,7 +99,7 @@
       Path jdwpJar = ToolHelper.getJdwpTestsJarPath(minSdk);
       Path dexOutputDir = temp.newFolder("d8-jdwp-jar").toPath();
       jdwpDexD8 = dexOutputDir.resolve("classes.dex");
-      D8.run(
+      ToolHelper.runD8(
           D8Command.builder()
               .addProgramFiles(jdwpJar)
               .setOutputPath(dexOutputDir)
@@ -106,7 +110,7 @@
     {
       Path dexOutputDir = temp.newFolder("d8-debuggee-jar").toPath();
       debuggeeDexD8 = dexOutputDir.resolve("classes.dex");
-      D8.run(
+      ToolHelper.runD8(
           D8Command.builder()
               .addProgramFiles(DEBUGGEE_JAR)
               .setOutputPath(dexOutputDir)
@@ -114,6 +118,25 @@
               .setMode(CompilationMode.DEBUG)
               .build());
     }
+    {
+      Path dexOutputDir = temp.newFolder("d8-debuggee-java8-jar").toPath();
+      debuggeeJava8DexD8 = dexOutputDir.resolve("classes.dex");
+      ToolHelper.runD8(
+          D8Command.builder()
+              .addProgramFiles(DEBUGGEE_JAVA8_JAR)
+              .setOutputPath(dexOutputDir)
+              .setMinApiLevel(minSdk)
+              .setMode(CompilationMode.DEBUG)
+              .build(),
+          options -> {
+            // Enable desugaring for preN runtimes
+            options.interfaceMethodDesugaring = OffOrAuto.Auto;
+          });
+    }
+  }
+
+  protected final boolean supportsDefaultMethod() {
+    return ToolHelper.getMinApiLevelForDexVm(ToolHelper.getDexVm()) >= Constants.ANDROID_N_API;
   }
 
   protected final void runDebugTest(String debuggeeClass, JUnit3Wrapper.Command... commands)
@@ -123,6 +146,22 @@
 
   protected final void runDebugTest(String debuggeeClass, List<JUnit3Wrapper.Command> commands)
       throws Throwable {
+    runDebugTest(debuggeeDexD8, debuggeeClass, commands);
+  }
+
+  protected final void runDebugTestJava8(String debuggeeClass, JUnit3Wrapper.Command... commands)
+      throws Throwable {
+    runDebugTestJava8(debuggeeClass, Arrays.asList(commands));
+  }
+
+  protected final void runDebugTestJava8(String debuggeeClass, List<JUnit3Wrapper.Command> commands)
+      throws Throwable {
+    runDebugTest(debuggeeJava8DexD8, debuggeeClass, commands);
+  }
+
+  private void runDebugTest(Path debuggeeExec, String debuggeeClass,
+      List<JUnit3Wrapper.Command> commands)
+      throws Throwable {
     // Skip test due to unsupported runtime.
     Assume.assumeTrue("Skipping test " + testName.getMethodName() + " because ART is not supported",
         ToolHelper.artSupported());
@@ -131,7 +170,7 @@
             .getDexVm(), UNSUPPORTED_ART_VERSIONS.contains(ToolHelper.getDexVm()));
 
     // Run with ART.
-    String[] paths = new String[]{jdwpDexD8.toString(), debuggeeDexD8.toString()};
+    String[] paths = new String[]{jdwpDexD8.toString(), debuggeeExec.toString()};
     new JUnit3Wrapper(debuggeeClass, paths, commands).runBare();
   }
 
@@ -172,6 +211,10 @@
     return new JUnit3Wrapper.Command.StepCommand(stepDepth, stepFilter);
   }
 
+  protected final JUnit3Wrapper.Command checkLocal(String localName) {
+    return inspect(t -> t.checkLocal(localName));
+  }
+
   protected final JUnit3Wrapper.Command checkLocal(String localName, Value expectedValue) {
     return inspect(t -> t.checkLocal(localName, expectedValue));
   }
@@ -308,6 +351,18 @@
         // Capture the context of the event suspension.
         updateEventContext((EventThread) parsedEvent);
 
+        if (DEBUG_TESTS && debuggeeState.location != null) {
+          // Dump location
+          String classSig = getMirror().getClassSignature(debuggeeState.location.classID);
+          String methodName = getMirror()
+              .getMethodName(debuggeeState.location.classID, debuggeeState.location.methodID);
+          String methodSig = getMirror()
+              .getMethodSignature(debuggeeState.location.classID, debuggeeState.location.methodID);
+          System.out.println(String
+              .format("Suspended in %s#%s%s@%x", classSig, methodName, methodSig,
+                  Long.valueOf(debuggeeState.location.index)));
+        }
+
         // Handle event.
         EventHandler eh = events.get(requestID);
         assert eh != null;
@@ -346,6 +401,10 @@
         return this.location;
       }
 
+      public void checkLocal(String localName) {
+        getVariableAt(getLocation(), localName);
+      }
+
       public void checkLocal(String localName, Value expectedValue) {
         Variable localVar = getVariableAt(getLocation(), localName);
 
@@ -767,7 +826,27 @@
       public boolean skipLocation(VmMirror mirror, Location location) {
         // TODO(shertz) we also need to skip class loaders to act like IntelliJ.
         // Skip synthetic methods.
-        return isSyntheticMethod(mirror, location);
+        if (isLambdaMethod(mirror, location)) {
+          // Lambda methods are synthetic but we do want to stop there.
+          if (DEBUG_TESTS) {
+            System.out.println("NOT skipping lambda implementation method");
+          }
+          return false;
+        }
+        if (isInLambdaClass(mirror, location)) {
+          // Lambda classes must be skipped since they are only wrappers around lambda code.
+          if (DEBUG_TESTS) {
+            System.out.println("Skipping lambda class wrapper method");
+          }
+          return true;
+        }
+        if (isSyntheticMethod(mirror, location)) {
+          if (DEBUG_TESTS) {
+            System.out.println("Skipping synthetic method");
+          }
+          return true;
+        }
+        return false;
       }
 
       private static boolean isSyntheticMethod(VmMirror mirror, Location location) {
@@ -787,6 +866,16 @@
         }
         return false;
       }
+
+      private static boolean isInLambdaClass(VmMirror mirror, Location location) {
+        String classSig = mirror.getClassSignature(location.classID);
+        return classSig.contains("$$Lambda$");
+      }
+
+      private boolean isLambdaMethod(VmMirror mirror, Location location) {
+        String methodName = mirror.getMethodName(location.classID, location.methodID);
+        return methodName.startsWith("lambda$");
+      }
     }
   }
 
diff --git a/src/test/java/com/android/tools/r8/debug/DefaultMethodTest.java b/src/test/java/com/android/tools/r8/debug/DefaultMethodTest.java
new file mode 100644
index 0000000..ea116a7
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/debug/DefaultMethodTest.java
@@ -0,0 +1,65 @@
+// 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.debug.DebugTestBase.JUnit3Wrapper.Command;
+import java.util.ArrayList;
+import java.util.List;
+import org.junit.Test;
+
+public class DefaultMethodTest extends DebugTestBase {
+
+  @Test
+  public void testDefaultMethod() throws Throwable {
+    String debuggeeClass = "DebugDefaultMethod";
+    String parameterName = "msg";
+    String localVariableName = "name";
+
+    List<Command> commands = new ArrayList<>();
+    commands.add(breakpoint(debuggeeClass, "testDefaultMethod"));
+    commands.add(run());
+    commands.add(checkMethod(debuggeeClass, "testDefaultMethod"));
+    commands.add(checkLine(27));
+    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());
+    commands.add(checkLocal(parameterName));
+    commands.add(stepOver());
+    commands.add(checkLocal(parameterName));
+    commands.add(checkLocal(localVariableName));
+    // TODO(shertz) check current method name ?
+    commands.add(run());
+    commands.add(run()  /* resume after 2nd breakpoint */);
+
+    runDebugTestJava8(debuggeeClass, commands);
+  }
+
+  @Test
+  public void testOverrideDefaultMethod() throws Throwable {
+    String debuggeeClass = "DebugDefaultMethod";
+    String parameterName = "msg";
+    String localVariableName = "newMsg";
+
+    List<Command> commands = new ArrayList<>();
+    commands.add(breakpoint(debuggeeClass, "testDefaultMethod"));
+    commands.add(run());
+    commands.add(run() /* resume after 1st breakpoint */);
+    commands.add(checkMethod(debuggeeClass, "testDefaultMethod"));
+    commands.add(checkLine(27));
+    commands.add(stepInto());
+    commands.add(checkMethod("DebugDefaultMethod$OverrideImpl", "doSomething"));
+    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
new file mode 100644
index 0000000..467ae09
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/debug/LambdaTest.java
@@ -0,0 +1,25 @@
+// 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 org.junit.Test;
+
+public class LambdaTest extends DebugTestBase {
+
+  @Test
+  public void testLambdaDebugging() throws Throwable {
+    String debuggeeClass = "DebugLambda";
+    String initialMethodName = "printInt";
+    // TODO(shertz) test local variables
+    runDebugTestJava8(debuggeeClass,
+        breakpoint(debuggeeClass, initialMethodName),
+        run(),
+        checkMethod(debuggeeClass, initialMethodName),
+        checkLine(12),
+        stepInto(INTELLIJ_FILTER),
+        checkLine(16),
+        run());
+  }
+}
diff --git a/src/test/java/com/android/tools/r8/internal/CompilationTestBase.java b/src/test/java/com/android/tools/r8/internal/CompilationTestBase.java
index 5902a6e..4b2ece0 100644
--- a/src/test/java/com/android/tools/r8/internal/CompilationTestBase.java
+++ b/src/test/java/com/android/tools/r8/internal/CompilationTestBase.java
@@ -36,17 +36,19 @@
 
   public AndroidApp runAndCheckVerification(
       CompilerUnderTest compiler,
+      CompilationMode mode,
       String referenceApk,
       String pgMap,
       String pgConf,
       String... inputs)
       throws ExecutionException, IOException, ProguardRuleParserException, CompilationException {
     return runAndCheckVerification(
-        compiler, referenceApk, pgMap, pgConf, Arrays.asList(inputs));
+        compiler, mode, referenceApk, pgMap, pgConf, Arrays.asList(inputs));
   }
 
   public AndroidApp runAndCheckVerification(
       CompilerUnderTest compiler,
+      CompilationMode mode,
       String referenceApk,
       String pgMap,
       String pgConf,
@@ -63,6 +65,7 @@
       if (pgConf != null) {
         builder.addProguardConfigurationFiles(Paths.get(pgConf));
       }
+      builder.setMode(mode);
       outputApp = ToolHelper.runR8(builder.build());
     } else {
       assert compiler == CompilerUnderTest.D8;
@@ -70,7 +73,7 @@
           ToolHelper.runD8(
               D8Command.builder()
                   .addProgramFiles(ListUtils.map(inputs, Paths::get))
-                  .setMode(CompilationMode.DEBUG)
+                  .setMode(mode)
                   .build());
     }
     Path out = temp.getRoot().toPath().resolve("all.zip");
diff --git a/src/test/java/com/android/tools/r8/internal/D8GMSCoreV10DeployJarVerificationTest.java b/src/test/java/com/android/tools/r8/internal/D8GMSCoreV10DeployJarVerificationTest.java
new file mode 100644
index 0000000..04c1d2e
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/internal/D8GMSCoreV10DeployJarVerificationTest.java
@@ -0,0 +1,31 @@
+// 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.internal;
+
+import com.android.tools.r8.CompilationException;
+import com.android.tools.r8.CompilationMode;
+import com.android.tools.r8.R8RunArtTestsTest.CompilerUnderTest;
+import com.android.tools.r8.shaking.ProguardRuleParserException;
+import java.io.IOException;
+import java.util.concurrent.ExecutionException;
+import org.junit.Test;
+
+public class D8GMSCoreV10DeployJarVerificationTest extends GMSCoreDeployJarVerificationTest {
+
+  @Test
+  public void buildDebugFromDeployJar()
+      throws ExecutionException, IOException, ProguardRuleParserException, CompilationException {
+    buildFromDeployJar(
+        CompilerUnderTest.D8, CompilationMode.DEBUG,
+        GMSCoreCompilationTestBase.GMSCORE_V10_DIR, false);
+  }
+
+  @Test
+  public void buildReleaseFromDeployJar()
+      throws ExecutionException, IOException, ProguardRuleParserException, CompilationException {
+    buildFromDeployJar(
+        CompilerUnderTest.D8, CompilationMode.RELEASE,
+        GMSCoreCompilationTestBase.GMSCORE_V10_DIR, false);
+  }
+}
diff --git a/src/test/java/com/android/tools/r8/internal/D8GMSCoreV9DeployJarVerificationTest.java b/src/test/java/com/android/tools/r8/internal/D8GMSCoreV9DeployJarVerificationTest.java
index d5f23d0..2e076d5 100644
--- a/src/test/java/com/android/tools/r8/internal/D8GMSCoreV9DeployJarVerificationTest.java
+++ b/src/test/java/com/android/tools/r8/internal/D8GMSCoreV9DeployJarVerificationTest.java
@@ -4,6 +4,7 @@
 package com.android.tools.r8.internal;
 
 import com.android.tools.r8.CompilationException;
+import com.android.tools.r8.CompilationMode;
 import com.android.tools.r8.R8RunArtTestsTest.CompilerUnderTest;
 import com.android.tools.r8.shaking.ProguardRuleParserException;
 import java.io.IOException;
@@ -13,8 +14,18 @@
 public class D8GMSCoreV9DeployJarVerificationTest extends GMSCoreDeployJarVerificationTest {
 
   @Test
-  public void buildFromDeployJar()
+  public void buildDebugFromDeployJar()
       throws ExecutionException, IOException, ProguardRuleParserException, CompilationException {
-    buildFromDeployJar(CompilerUnderTest.D8, GMSCoreCompilationTestBase.GMSCORE_V9_DIR, true);
+    buildFromDeployJar(
+        CompilerUnderTest.D8, CompilationMode.DEBUG,
+        GMSCoreCompilationTestBase.GMSCORE_V9_DIR, true);
+  }
+
+  @Test
+  public void buildReleaseFromDeployJar()
+      throws ExecutionException, IOException, ProguardRuleParserException, CompilationException {
+    buildFromDeployJar(
+        CompilerUnderTest.D8, CompilationMode.RELEASE,
+        GMSCoreCompilationTestBase.GMSCORE_V9_DIR, true);
   }
 }
diff --git a/src/test/java/com/android/tools/r8/internal/D8YouTubeDeployJarVerificationTest.java b/src/test/java/com/android/tools/r8/internal/D8YouTubeDeployJarVerificationTest.java
new file mode 100644
index 0000000..5e226bb
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/internal/D8YouTubeDeployJarVerificationTest.java
@@ -0,0 +1,29 @@
+// Copyright (c) 2016, 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.internal;
+
+import com.android.tools.r8.CompilationException;
+import com.android.tools.r8.CompilationMode;
+import com.android.tools.r8.R8RunArtTestsTest.CompilerUnderTest;
+import com.android.tools.r8.shaking.ProguardRuleParserException;
+import java.io.IOException;
+import java.util.concurrent.ExecutionException;
+import org.junit.Test;
+
+public class D8YouTubeDeployJarVerificationTest extends YouTubeCompilationBase {
+
+  @Test
+  public void buildDebugFromDeployJar()
+      throws ExecutionException, IOException, ProguardRuleParserException, CompilationException {
+    runAndCheckVerification(
+        CompilerUnderTest.D8, CompilationMode.DEBUG, BASE + APK, null, null, BASE + DEPLOY_JAR);
+  }
+
+  @Test
+  public void buildReleaseFromDeployJar()
+      throws ExecutionException, IOException, ProguardRuleParserException, CompilationException {
+    runAndCheckVerification(
+        CompilerUnderTest.D8, CompilationMode.RELEASE, BASE + APK, null, null, BASE + DEPLOY_JAR);
+  }
+}
diff --git a/src/test/java/com/android/tools/r8/internal/GMSCoreCompilationTestBase.java b/src/test/java/com/android/tools/r8/internal/GMSCoreCompilationTestBase.java
index ca8d019..1e91e0d 100644
--- a/src/test/java/com/android/tools/r8/internal/GMSCoreCompilationTestBase.java
+++ b/src/test/java/com/android/tools/r8/internal/GMSCoreCompilationTestBase.java
@@ -4,6 +4,7 @@
 package com.android.tools.r8.internal;
 
 import com.android.tools.r8.CompilationException;
+import com.android.tools.r8.CompilationMode;
 import com.android.tools.r8.R8RunArtTestsTest.CompilerUnderTest;
 import com.android.tools.r8.shaking.ProguardRuleParserException;
 import java.io.IOException;
@@ -30,14 +31,16 @@
   static final String DEPLOY_JAR = "GmsCore_prod_alldpi_release_all_locales_deploy.jar";
   static final String REFERENCE_APK = "noshrink_x86_GmsCore_prod_alldpi_release_unsigned.apk";
 
-  public void runR8AndCheckVerification(String version)
+  public void runR8AndCheckVerification(CompilationMode mode, String version)
       throws ProguardRuleParserException, ExecutionException, IOException, CompilationException {
-    runAndCheckVerification(CompilerUnderTest.R8, version);
+    runAndCheckVerification(CompilerUnderTest.R8, mode, version);
   }
 
-  public void runAndCheckVerification(CompilerUnderTest compiler, String version)
+  public void runAndCheckVerification(
+      CompilerUnderTest compiler, CompilationMode mode, String version)
       throws ExecutionException, IOException, ProguardRuleParserException, CompilationException {
     runAndCheckVerification(
-        compiler, version + GMSCORE_APK, null, null, Paths.get(version, GMSCORE_APK).toString());
+        compiler, mode, version + GMSCORE_APK, null, null,
+        Paths.get(version, GMSCORE_APK).toString());
   }
 }
diff --git a/src/test/java/com/android/tools/r8/internal/GMSCoreDeployJarVerificationTest.java b/src/test/java/com/android/tools/r8/internal/GMSCoreDeployJarVerificationTest.java
index ecc7451..0a2cdae 100644
--- a/src/test/java/com/android/tools/r8/internal/GMSCoreDeployJarVerificationTest.java
+++ b/src/test/java/com/android/tools/r8/internal/GMSCoreDeployJarVerificationTest.java
@@ -4,6 +4,7 @@
 package com.android.tools.r8.internal;
 
 import com.android.tools.r8.CompilationException;
+import com.android.tools.r8.CompilationMode;
 import com.android.tools.r8.R8RunArtTestsTest.CompilerUnderTest;
 import com.android.tools.r8.shaking.ProguardRuleParserException;
 import java.io.IOException;
@@ -11,9 +12,10 @@
 
 public class GMSCoreDeployJarVerificationTest extends GMSCoreCompilationTestBase {
 
-  public void buildFromDeployJar(CompilerUnderTest compiler, String base, boolean hasReference)
+  public void buildFromDeployJar(
+      CompilerUnderTest compiler, CompilationMode mode, String base, boolean hasReference)
       throws ExecutionException, IOException, ProguardRuleParserException, CompilationException {
     runAndCheckVerification(
-        compiler, hasReference ? base + REFERENCE_APK : null, null, null, base + DEPLOY_JAR);
+        compiler, mode, hasReference ? base + REFERENCE_APK : null, null, null, base + DEPLOY_JAR);
   }
 }
diff --git a/src/test/java/com/android/tools/r8/internal/R8GMSCoreTreeShakeJarVerificationTest.java b/src/test/java/com/android/tools/r8/internal/R8GMSCoreTreeShakeJarVerificationTest.java
index 2571490..fecc360 100644
--- a/src/test/java/com/android/tools/r8/internal/R8GMSCoreTreeShakeJarVerificationTest.java
+++ b/src/test/java/com/android/tools/r8/internal/R8GMSCoreTreeShakeJarVerificationTest.java
@@ -6,6 +6,7 @@
 import static junit.framework.TestCase.assertTrue;
 
 import com.android.tools.r8.CompilationException;
+import com.android.tools.r8.CompilationMode;
 import com.android.tools.r8.R8RunArtTestsTest.CompilerUnderTest;
 import com.android.tools.r8.shaking.ProguardRuleParserException;
 import com.android.tools.r8.utils.AndroidApp;
@@ -18,10 +19,12 @@
 
 public class R8GMSCoreTreeShakeJarVerificationTest extends GMSCoreCompilationTestBase {
 
-  public void buildAndTreeShakeFromDeployJar(String base, boolean hasReference, int maxSize)
+  public void buildAndTreeShakeFromDeployJar(
+      CompilationMode mode, String base, boolean hasReference, int maxSize)
       throws ExecutionException, IOException, ProguardRuleParserException, CompilationException {
     AndroidApp app = runAndCheckVerification(
         CompilerUnderTest.R8,
+        mode,
         hasReference ? base + REFERENCE_APK : null,
         null,
         base + PG_CONF,
diff --git a/src/test/java/com/android/tools/r8/internal/R8GMSCoreV10DeployJarVerificationTest.java b/src/test/java/com/android/tools/r8/internal/R8GMSCoreV10DeployJarVerificationTest.java
index 5894981..6118b3d 100644
--- a/src/test/java/com/android/tools/r8/internal/R8GMSCoreV10DeployJarVerificationTest.java
+++ b/src/test/java/com/android/tools/r8/internal/R8GMSCoreV10DeployJarVerificationTest.java
@@ -5,6 +5,7 @@
 package com.android.tools.r8.internal;
 
 import com.android.tools.r8.CompilationException;
+import com.android.tools.r8.CompilationMode;
 import com.android.tools.r8.R8RunArtTestsTest.CompilerUnderTest;
 import com.android.tools.r8.shaking.ProguardRuleParserException;
 import java.io.IOException;
@@ -17,6 +18,8 @@
   public void buildFromDeployJar()
       // TODO(tamaskenez): set hasReference = true when we have the noshrink file for V10
       throws ExecutionException, IOException, ProguardRuleParserException, CompilationException {
-    buildFromDeployJar(CompilerUnderTest.R8, GMSCoreCompilationTestBase.GMSCORE_V10_DIR, false);
+    buildFromDeployJar(
+        CompilerUnderTest.R8, CompilationMode.RELEASE,
+        GMSCoreCompilationTestBase.GMSCORE_V10_DIR, false);
   }
 }
diff --git a/src/test/java/com/android/tools/r8/internal/R8GMSCoreV10TreeShakeJarVerificationTest.java b/src/test/java/com/android/tools/r8/internal/R8GMSCoreV10TreeShakeJarVerificationTest.java
index 5253ac2..9572825 100644
--- a/src/test/java/com/android/tools/r8/internal/R8GMSCoreV10TreeShakeJarVerificationTest.java
+++ b/src/test/java/com/android/tools/r8/internal/R8GMSCoreV10TreeShakeJarVerificationTest.java
@@ -4,6 +4,7 @@
 package com.android.tools.r8.internal;
 
 import com.android.tools.r8.CompilationException;
+import com.android.tools.r8.CompilationMode;
 import com.android.tools.r8.shaking.ProguardRuleParserException;
 import java.io.IOException;
 import java.util.concurrent.ExecutionException;
@@ -16,6 +17,7 @@
   public void buildAndTreeShakeFromDeployJar()
       throws ExecutionException, IOException, ProguardRuleParserException, CompilationException {
     // TODO(tamaskenez): set hasReference = true when we have the noshrink file for V10
-    buildAndTreeShakeFromDeployJar(GMSCORE_V10_DIR, false, GMSCORE_V10_MAX_SIZE);
+    buildAndTreeShakeFromDeployJar(
+        CompilationMode.RELEASE, GMSCORE_V10_DIR, false, GMSCORE_V10_MAX_SIZE);
   }
 }
diff --git a/src/test/java/com/android/tools/r8/internal/R8GMSCoreV4VerificationTest.java b/src/test/java/com/android/tools/r8/internal/R8GMSCoreV4VerificationTest.java
index d7de82e..0405587 100644
--- a/src/test/java/com/android/tools/r8/internal/R8GMSCoreV4VerificationTest.java
+++ b/src/test/java/com/android/tools/r8/internal/R8GMSCoreV4VerificationTest.java
@@ -4,6 +4,7 @@
 package com.android.tools.r8.internal;
 
 import com.android.tools.r8.CompilationException;
+import com.android.tools.r8.CompilationMode;
 import com.android.tools.r8.shaking.ProguardRuleParserException;
 import java.io.IOException;
 import java.util.concurrent.ExecutionException;
@@ -13,6 +14,6 @@
   @Test
   public void verify()
       throws ExecutionException, IOException, ProguardRuleParserException, CompilationException {
-    runR8AndCheckVerification(GMSCORE_V4_DIR);
+    runR8AndCheckVerification(CompilationMode.RELEASE, GMSCORE_V4_DIR);
   }
 }
diff --git a/src/test/java/com/android/tools/r8/internal/R8GMSCoreV5VerificationTest.java b/src/test/java/com/android/tools/r8/internal/R8GMSCoreV5VerificationTest.java
index 6a098a8..17aab5e 100644
--- a/src/test/java/com/android/tools/r8/internal/R8GMSCoreV5VerificationTest.java
+++ b/src/test/java/com/android/tools/r8/internal/R8GMSCoreV5VerificationTest.java
@@ -4,6 +4,7 @@
 package com.android.tools.r8.internal;
 
 import com.android.tools.r8.CompilationException;
+import com.android.tools.r8.CompilationMode;
 import com.android.tools.r8.shaking.ProguardRuleParserException;
 import java.io.IOException;
 import java.util.concurrent.ExecutionException;
@@ -13,6 +14,6 @@
   @Test
   public void verify()
       throws ExecutionException, IOException, ProguardRuleParserException, CompilationException {
-    runR8AndCheckVerification(GMSCORE_V5_DIR);
+    runR8AndCheckVerification(CompilationMode.RELEASE, GMSCORE_V5_DIR);
   }
 }
diff --git a/src/test/java/com/android/tools/r8/internal/R8GMSCoreV6VerificationTest.java b/src/test/java/com/android/tools/r8/internal/R8GMSCoreV6VerificationTest.java
index b7ca295..d34ad90 100644
--- a/src/test/java/com/android/tools/r8/internal/R8GMSCoreV6VerificationTest.java
+++ b/src/test/java/com/android/tools/r8/internal/R8GMSCoreV6VerificationTest.java
@@ -4,6 +4,7 @@
 package com.android.tools.r8.internal;
 
 import com.android.tools.r8.CompilationException;
+import com.android.tools.r8.CompilationMode;
 import com.android.tools.r8.shaking.ProguardRuleParserException;
 import java.io.IOException;
 import java.util.concurrent.ExecutionException;
@@ -13,6 +14,6 @@
   @Test
   public void verify()
       throws ExecutionException, IOException, ProguardRuleParserException, CompilationException {
-    runR8AndCheckVerification(GMSCORE_V6_DIR);
+    runR8AndCheckVerification(CompilationMode.RELEASE, GMSCORE_V6_DIR);
   }
 }
diff --git a/src/test/java/com/android/tools/r8/internal/R8GMSCoreV7VerificationTest.java b/src/test/java/com/android/tools/r8/internal/R8GMSCoreV7VerificationTest.java
index f65a8e1..2f530f4 100644
--- a/src/test/java/com/android/tools/r8/internal/R8GMSCoreV7VerificationTest.java
+++ b/src/test/java/com/android/tools/r8/internal/R8GMSCoreV7VerificationTest.java
@@ -4,6 +4,7 @@
 package com.android.tools.r8.internal;
 
 import com.android.tools.r8.CompilationException;
+import com.android.tools.r8.CompilationMode;
 import com.android.tools.r8.shaking.ProguardRuleParserException;
 import java.io.IOException;
 import java.util.concurrent.ExecutionException;
@@ -14,6 +15,6 @@
   @Test
   public void verify()
       throws ExecutionException, IOException, ProguardRuleParserException, CompilationException {
-    runR8AndCheckVerification(GMSCORE_V7_DIR);
+    runR8AndCheckVerification(CompilationMode.RELEASE, GMSCORE_V7_DIR);
   }
 }
diff --git a/src/test/java/com/android/tools/r8/internal/R8GMSCoreV8VerificationTest.java b/src/test/java/com/android/tools/r8/internal/R8GMSCoreV8VerificationTest.java
index bc0dbe8..128bd17 100644
--- a/src/test/java/com/android/tools/r8/internal/R8GMSCoreV8VerificationTest.java
+++ b/src/test/java/com/android/tools/r8/internal/R8GMSCoreV8VerificationTest.java
@@ -4,6 +4,7 @@
 package com.android.tools.r8.internal;
 
 import com.android.tools.r8.CompilationException;
+import com.android.tools.r8.CompilationMode;
 import com.android.tools.r8.shaking.ProguardRuleParserException;
 import java.io.IOException;
 import java.util.concurrent.ExecutionException;
@@ -14,6 +15,6 @@
   @Test
   public void verify()
       throws ExecutionException, IOException, ProguardRuleParserException, CompilationException {
-    runR8AndCheckVerification(GMSCORE_V8_DIR);
+    runR8AndCheckVerification(CompilationMode.RELEASE, GMSCORE_V8_DIR);
   }
 }
diff --git a/src/test/java/com/android/tools/r8/internal/R8GMSCoreV9DeployJarVerificationTest.java b/src/test/java/com/android/tools/r8/internal/R8GMSCoreV9DeployJarVerificationTest.java
index d1e6844..bc8c2b6 100644
--- a/src/test/java/com/android/tools/r8/internal/R8GMSCoreV9DeployJarVerificationTest.java
+++ b/src/test/java/com/android/tools/r8/internal/R8GMSCoreV9DeployJarVerificationTest.java
@@ -5,6 +5,7 @@
 package com.android.tools.r8.internal;
 
 import com.android.tools.r8.CompilationException;
+import com.android.tools.r8.CompilationMode;
 import com.android.tools.r8.R8RunArtTestsTest.CompilerUnderTest;
 import com.android.tools.r8.shaking.ProguardRuleParserException;
 import java.io.IOException;
@@ -16,6 +17,8 @@
   @Test
   public void buildFromDeployJar()
       throws ExecutionException, IOException, ProguardRuleParserException, CompilationException {
-    buildFromDeployJar(CompilerUnderTest.R8, GMSCoreCompilationTestBase.GMSCORE_V9_DIR, true);
+    buildFromDeployJar(
+        CompilerUnderTest.R8, CompilationMode.RELEASE,
+        GMSCoreCompilationTestBase.GMSCORE_V9_DIR, true);
   }
 }
diff --git a/src/test/java/com/android/tools/r8/internal/R8GMSCoreV9TreeShakeJarVerificationTest.java b/src/test/java/com/android/tools/r8/internal/R8GMSCoreV9TreeShakeJarVerificationTest.java
index 2f5ed63..78aa1a3 100644
--- a/src/test/java/com/android/tools/r8/internal/R8GMSCoreV9TreeShakeJarVerificationTest.java
+++ b/src/test/java/com/android/tools/r8/internal/R8GMSCoreV9TreeShakeJarVerificationTest.java
@@ -4,6 +4,7 @@
 package com.android.tools.r8.internal;
 
 import com.android.tools.r8.CompilationException;
+import com.android.tools.r8.CompilationMode;
 import com.android.tools.r8.shaking.ProguardRuleParserException;
 import java.io.IOException;
 import java.util.concurrent.ExecutionException;
@@ -14,6 +15,7 @@
   @Test
   public void buildAndTreeShakeFromDeployJar()
       throws ExecutionException, IOException, ProguardRuleParserException, CompilationException {
-    buildAndTreeShakeFromDeployJar(GMSCORE_V9_DIR, true, GMSCORE_V9_MAX_SIZE);
+    buildAndTreeShakeFromDeployJar(
+        CompilationMode.RELEASE, GMSCORE_V9_DIR, true, GMSCORE_V9_MAX_SIZE);
   }
 }
diff --git a/src/test/java/com/android/tools/r8/internal/YouTubeCompilationBase.java b/src/test/java/com/android/tools/r8/internal/YouTubeCompilationBase.java
index 08b3892..3e46590 100644
--- a/src/test/java/com/android/tools/r8/internal/YouTubeCompilationBase.java
+++ b/src/test/java/com/android/tools/r8/internal/YouTubeCompilationBase.java
@@ -4,7 +4,7 @@
 package com.android.tools.r8.internal;
 
 public abstract class YouTubeCompilationBase extends CompilationTestBase {
-  static final String BASE = "third_party/youtube/youtube.android_11.47/";
+  static final String BASE = "third_party/youtube/youtube.android_12.17/";
   static final String APK = "YouTubeRelease_unsigned.apk";
   static final String DEPLOY_JAR = "YouTubeRelease_deploy.jar";
   static final String PG_JAR = "YouTubeRelease_proguard.jar";
diff --git a/src/test/java/com/android/tools/r8/internal/YouTubeDeployJarVerificationTest.java b/src/test/java/com/android/tools/r8/internal/YouTubeDeployJarVerificationTest.java
index b40ba07..7fbfb2e 100644
--- a/src/test/java/com/android/tools/r8/internal/YouTubeDeployJarVerificationTest.java
+++ b/src/test/java/com/android/tools/r8/internal/YouTubeDeployJarVerificationTest.java
@@ -4,6 +4,7 @@
 package com.android.tools.r8.internal;
 
 import com.android.tools.r8.CompilationException;
+import com.android.tools.r8.CompilationMode;
 import com.android.tools.r8.R8RunArtTestsTest.CompilerUnderTest;
 import com.android.tools.r8.shaking.ProguardRuleParserException;
 import java.io.IOException;
@@ -13,8 +14,16 @@
 public class YouTubeDeployJarVerificationTest extends YouTubeCompilationBase {
 
   @Test
-  public void buildFromDeployJar()
+  public void buildDebugFromDeployJar()
       throws ExecutionException, IOException, ProguardRuleParserException, CompilationException {
-    runAndCheckVerification(CompilerUnderTest.R8, BASE + APK, null, null, BASE + DEPLOY_JAR);
+    runAndCheckVerification(
+        CompilerUnderTest.R8, CompilationMode.DEBUG, BASE + APK, null, null, BASE + DEPLOY_JAR);
+  }
+
+  @Test
+  public void buildReleaseFromDeployJar()
+      throws ExecutionException, IOException, ProguardRuleParserException, CompilationException {
+    runAndCheckVerification(
+        CompilerUnderTest.R8, CompilationMode.RELEASE, BASE + APK, null, null, BASE + DEPLOY_JAR);
   }
 }
diff --git a/src/test/java/com/android/tools/r8/internal/YouTubeDexVerificationTest.java b/src/test/java/com/android/tools/r8/internal/YouTubeDexVerificationTest.java
index 19bfe25..ba816f1 100644
--- a/src/test/java/com/android/tools/r8/internal/YouTubeDexVerificationTest.java
+++ b/src/test/java/com/android/tools/r8/internal/YouTubeDexVerificationTest.java
@@ -4,6 +4,7 @@
 package com.android.tools.r8.internal;
 
 import com.android.tools.r8.CompilationException;
+import com.android.tools.r8.CompilationMode;
 import com.android.tools.r8.R8RunArtTestsTest.CompilerUnderTest;
 import com.android.tools.r8.shaking.ProguardRuleParserException;
 import java.io.IOException;
@@ -13,8 +14,16 @@
 public class YouTubeDexVerificationTest extends YouTubeCompilationBase {
 
   @Test
-  public void buildFromDex()
+  public void buildDebugFromDex()
       throws ExecutionException, IOException, ProguardRuleParserException, CompilationException {
-    runAndCheckVerification(CompilerUnderTest.R8, BASE + APK, BASE + PG_MAP, null, BASE + APK);
+    runAndCheckVerification(
+        CompilerUnderTest.R8, CompilationMode.DEBUG, BASE + APK, BASE + PG_MAP, null, BASE + APK);
+  }
+
+  @Test
+  public void buildReleaseFromDex()
+      throws ExecutionException, IOException, ProguardRuleParserException, CompilationException {
+    runAndCheckVerification(
+        CompilerUnderTest.R8, CompilationMode.RELEASE, BASE + APK, BASE + PG_MAP, null, BASE + APK);
   }
 }
diff --git a/src/test/java/com/android/tools/r8/internal/YouTubeProguardJarVerificationTest.java b/src/test/java/com/android/tools/r8/internal/YouTubeProguardJarVerificationTest.java
index 0b1e553..4bbceeb 100644
--- a/src/test/java/com/android/tools/r8/internal/YouTubeProguardJarVerificationTest.java
+++ b/src/test/java/com/android/tools/r8/internal/YouTubeProguardJarVerificationTest.java
@@ -4,6 +4,7 @@
 package com.android.tools.r8.internal;
 
 import com.android.tools.r8.CompilationException;
+import com.android.tools.r8.CompilationMode;
 import com.android.tools.r8.R8RunArtTestsTest.CompilerUnderTest;
 import com.android.tools.r8.shaking.ProguardRuleParserException;
 import java.io.IOException;
@@ -13,8 +14,17 @@
 public class YouTubeProguardJarVerificationTest extends YouTubeCompilationBase {
 
   @Test
-  public void buildFromProguardJar()
+  public void buildDebugFromProguardJar()
       throws ExecutionException, IOException, ProguardRuleParserException, CompilationException {
-    runAndCheckVerification(CompilerUnderTest.R8, BASE + APK, BASE + PG_MAP, null, BASE + PG_JAR);
+    runAndCheckVerification(
+        CompilerUnderTest.R8, CompilationMode.DEBUG, BASE + APK, BASE + PG_MAP, null, BASE + PG_JAR);
+  }
+
+  @Test
+  public void buildReleaseFromProguardJar()
+      throws ExecutionException, IOException, ProguardRuleParserException, CompilationException {
+    runAndCheckVerification(
+        CompilerUnderTest.R8, CompilationMode.RELEASE,
+        BASE + APK, BASE + PG_MAP, null, BASE + PG_JAR);
   }
 }
diff --git a/src/test/java/com/android/tools/r8/internal/YouTubeTreeShakeJarVerificationTest.java b/src/test/java/com/android/tools/r8/internal/YouTubeTreeShakeJarVerificationTest.java
index c51129c..229a6fb 100644
--- a/src/test/java/com/android/tools/r8/internal/YouTubeTreeShakeJarVerificationTest.java
+++ b/src/test/java/com/android/tools/r8/internal/YouTubeTreeShakeJarVerificationTest.java
@@ -6,6 +6,7 @@
 import static org.junit.Assert.assertTrue;
 
 import com.android.tools.r8.CompilationException;
+import com.android.tools.r8.CompilationMode;
 import com.android.tools.r8.R8RunArtTestsTest.CompilerUnderTest;
 import com.android.tools.r8.shaking.ProguardRuleParserException;
 import com.android.tools.r8.utils.AndroidApp;
@@ -25,7 +26,8 @@
       throws ExecutionException, IOException, ProguardRuleParserException, CompilationException {
     int maxSize = 16000000;
     AndroidApp app = runAndCheckVerification(
-        CompilerUnderTest.R8, BASE + APK, null, BASE + PG_CONF, BASE + DEPLOY_JAR);
+        CompilerUnderTest.R8, CompilationMode.RELEASE,
+        BASE + APK, null, BASE + PG_CONF, BASE + DEPLOY_JAR);
     int bytes = 0;
     try (Closer closer = Closer.create()) {
       for (InternalResource dex : app.getDexProgramResources()) {
diff --git a/tools/create_art_tests.py b/tools/create_art_tests.py
new file mode 100755
index 0000000..3a83cbc
--- /dev/null
+++ b/tools/create_art_tests.py
@@ -0,0 +1,82 @@
+#!/usr/bin/env python
+# 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.
+
+from os import makedirs, listdir
+from os.path import join, exists, isdir
+from string import Template, upper
+from sys import exit
+from shutil import rmtree
+
+OUTPUT_DIR = "build/generated/test/java/com/android/tools/r8/art"
+TEST_DIR = "tests/art"
+TOOLCHAINS = ["dx", "jack", "none"]
+TOOLS = ["r8", "d8"]
+TEMPLATE = Template(
+"""// Copyright (c) 2016, 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.art.$testGeneratingToolchain.$compilerUnderTest;
+
+import static com.android.tools.r8.R8RunArtTestsTest.DexTool.$testGeneratingToolchainEnum;
+
+import com.android.tools.r8.R8RunArtTestsTest;
+import org.junit.Test;
+
+/**
+ * Auto-generated test for the art $name test using the $testGeneratingToolchain toolchain.
+ *
+ * DO NOT EDIT THIS FILE. EDIT THE HERE DOCUMENT TEMPLATE IN tools/create_art_tests.py INSTEAD!
+ */
+public class $testClassName extends R8RunArtTestsTest {
+
+    public $testClassName() {
+      super("$name", $testGeneratingToolchainEnum);
+    }
+
+    @Test
+    public void run$testClassName() throws Throwable {
+      // For testing with other Art VMs than the default pass the VM version as a argument to
+      // runArtTest, e.g. runArtTest(ToolHelper.ART_4_4_4).
+      runArtTest(CompilerUnderTest.$compilerUnderTestEnum);
+    }
+}
+""")
+
+def create_toolchain_dirs(toolchain):
+  toolchain_dir = join(OUTPUT_DIR, toolchain)
+  if exists(toolchain_dir):
+    rmtree(toolchain_dir)
+  makedirs(join(toolchain_dir, "d8"))
+  makedirs(join(toolchain_dir, "r8"))
+
+def write_file(toolchain, tool, class_name, contents):
+  file_name = join(OUTPUT_DIR, toolchain, tool, class_name + ".java")
+  with open(file_name, "w") as file:
+    file.write(contents)
+
+def create_tests(toolchain):
+  source_dir = join(TEST_DIR, "dx" if toolchain == "none" else toolchain)
+  dirs = [d for d in listdir(source_dir)
+          if isdir(join(source_dir, d))]
+  for dir in dirs:
+    class_name = "Art" + dir.replace("-", "_") + "Test"
+    for tool in TOOLS:
+      contents = TEMPLATE.substitute(
+          name=dir,
+          compilerUnderTestEnum=upper(tool),
+          compilerUnderTest=tool,
+          testGeneratingToolchain=toolchain,
+          testGeneratingToolchainEnum=upper(toolchain),
+          testClassName=class_name)
+      write_file(toolchain, tool, class_name, contents)
+
+
+def main():
+  for toolchain in TOOLCHAINS:
+    create_toolchain_dirs(toolchain)
+    create_tests(toolchain)
+
+if __name__ == "__main__":
+  exit(main())
diff --git a/tools/linux/dx.tar.gz.sha1 b/tools/linux/dx.tar.gz.sha1
index f13e394..92e67ce 100644
--- a/tools/linux/dx.tar.gz.sha1
+++ b/tools/linux/dx.tar.gz.sha1
@@ -1 +1 @@
-6976e6a1768527b2388b1fdda5868dfa6b80d844
\ No newline at end of file
+da8789846188590e69dbac06f4d387762e71a616
\ No newline at end of file