Merge "Add a test for stale method def in outliner."
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/outliner/b111893131/B111893131.java b/src/test/java/com/android/tools/r8/ir/optimize/outliner/b111893131/B111893131.java
new file mode 100644
index 0000000..ea64746
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/ir/optimize/outliner/b111893131/B111893131.java
@@ -0,0 +1,116 @@
+// 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.ir.optimize.outliner.b111893131;
+
+import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.assertTrue;
+
+import com.android.tools.r8.DexIndexedConsumer;
+import com.android.tools.r8.R8Command;
+import com.android.tools.r8.TestBase;
+import com.android.tools.r8.ToolHelper;
+import com.android.tools.r8.ToolHelper.ProcessResult;
+import com.android.tools.r8.VmTestRunner;
+import com.android.tools.r8.code.Instruction;
+import com.android.tools.r8.code.InvokeVirtual;
+import com.android.tools.r8.graph.Code;
+import com.android.tools.r8.graph.DexClass;
+import com.android.tools.r8.graph.DexCode;
+import com.android.tools.r8.graph.DexMethod;
+import com.android.tools.r8.origin.Origin;
+import com.android.tools.r8.utils.AndroidApp;
+import com.android.tools.r8.utils.codeinspector.ClassSubject;
+import com.android.tools.r8.utils.codeinspector.CodeInspector;
+import com.google.common.collect.ImmutableList;
+import org.junit.Ignore;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+class TestClass {
+  public interface Act {
+    // Need both builder and arg to create code snippets for outline candidates.
+    String get(StringBuilder builder, String arg);
+  }
+
+  public static void main(String[] args) {
+    System.out.println(test(new TestClass("OK").toAct(), new StringBuilder(), "1"));
+  }
+
+  // Need to pass Act and call #get to create private instance lambda$
+  private static String test(Act act, StringBuilder builder, String arg) {
+    // Outline candidate
+    builder.append(arg).append(arg).append(arg);
+    act.get(builder, "#");
+    return builder.toString();
+  }
+
+  private final String foo;
+
+  TestClass(String foo) {
+    this.foo = foo;
+  }
+
+  private Act toAct() {
+    return (builder, arg) -> {
+      // Outline candidate
+      builder.append(arg).append(arg).append(arg);
+      return foo;
+    };
+  }
+}
+
+@RunWith(VmTestRunner.class)
+public class B111893131 extends TestBase {
+
+  @Ignore("b/111893131")
+  @Test
+  public void test() throws Exception {
+    String javaResult = runOnJava(TestClass.class);
+
+    R8Command.Builder builder = R8Command.builder();
+    builder.addProgramFiles(ToolHelper.getClassFileForTestClass(TestClass.class));
+    builder.addProgramFiles(ToolHelper.getClassFileForTestClass(TestClass.Act.class));
+    builder.setProgramConsumer(DexIndexedConsumer.emptyConsumer());
+    builder.setMinApiLevel(ToolHelper.getMinApiLevelForDexVm().getLevel());
+    String config = keepMainProguardConfiguration(TestClass.class);
+    builder.addProguardConfiguration(ImmutableList.of(config), Origin.unknown());
+    AndroidApp app = ToolHelper.runR8(builder.build(), options -> {
+      // To trigger outliner, set # of expected outline candidate as threshold.
+      options.outline.threshold = 2;
+      options.enableInlining = false;
+      options.enableMinification = false;
+    });
+    ProcessResult result = runOnArtRaw(app, TestClass.class);
+    assertEquals(0, result.exitCode);
+    assertEquals(javaResult, result.stdout);
+
+    CodeInspector inspector = new CodeInspector(app);
+    ClassSubject classSubject = inspector.clazz(TestClass.class);
+    assertThat(classSubject, isPresent());
+    DexClass clazz = classSubject.getDexClass();
+    clazz.forEachMethod(encodedMethod -> {
+      Code code = encodedMethod.getCode();
+      assertTrue(code.isDexCode());
+      DexCode dexCode = code.asDexCode();
+      // TODO(b/111893131): all outline candidate should be replaced with a call to outlined code.
+      verifyAbsenceOfStringBuilderAppend(dexCode.instructions);
+    });
+  }
+
+  private void verifyAbsenceOfStringBuilderAppend(Instruction[] instructions) {
+    for (Instruction instr : instructions) {
+      if (instr instanceof InvokeVirtual) {
+        InvokeVirtual invokeVirtual = (InvokeVirtual) instr;
+        DexMethod invokedMethod = invokeVirtual.getMethod();
+        if (invokedMethod.getHolder().getName().endsWith("StringBuilder")) {
+          assertNotEquals("append", invokedMethod.name.toString());
+        }
+      }
+    }
+  }
+
+}