Another test for ICCE in library default interface methods.

Bug: 145566657
Change-Id: Ifbe4511a870733f93c90f78a406c628ec0fc5c4e
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/DefaultMethodOverrideConflictWithLibrary2Test.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/DefaultMethodOverrideConflictWithLibrary2Test.java
new file mode 100644
index 0000000..f3c3f18
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/DefaultMethodOverrideConflictWithLibrary2Test.java
@@ -0,0 +1,159 @@
+// Copyright (c) 2019, 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.desugar.desugaredlibrary;
+
+import static org.hamcrest.CoreMatchers.containsString;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.TestParametersCollection;
+import com.android.tools.r8.TestRunResult;
+import com.android.tools.r8.TestRuntime;
+import com.android.tools.r8.TestRuntime.CfVm;
+import com.google.common.collect.ImmutableList;
+import java.io.IOException;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Spliterator;
+import java.util.function.Consumer;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+/**
+ * This test checks that if a default interface method in a library interface conflicts with a
+ * default method in a program interface, then deriving both leads to a ICCE.
+ *
+ * <p>In contrast to DefaultMethodOverrideConflictWithLibraryTest, in this test, the conflict is in
+ * a class with the two conflicting interfaces as the immediate interfaces.
+ */
+@RunWith(Parameterized.class)
+public class DefaultMethodOverrideConflictWithLibrary2Test extends CoreLibDesugarTestBase {
+
+  private final TestParameters parameters;
+
+  @Parameterized.Parameters(name = "{0}")
+  public static TestParametersCollection data() {
+    return getTestParameters().withAllRuntimes().withAllApiLevels().build();
+  }
+
+  public DefaultMethodOverrideConflictWithLibrary2Test(TestParameters parameters) {
+    this.parameters = parameters;
+  }
+
+  private List<Class<?>> getClasses() {
+    return ImmutableList.of(
+        Main.class,
+        MyIntegerList.class,
+        MyIntegerArrayListWithOverride.class,
+        MyHasCharacteristics.class);
+  }
+
+  private List<byte[]> getTransforms() throws IOException {
+    return ImmutableList.of(
+        transformer(MySpliterator.class)
+            .setImplements(Spliterator.class, MyHasCharacteristics.class)
+            .transform());
+  }
+
+  @Test
+  public void test() throws Exception {
+    TestRuntime systemRuntime = TestRuntime.getSystemRuntime();
+    if (systemRuntime.isCf() && systemRuntime.asCf().isNewerThanOrEqual(CfVm.JDK8)) {
+      // This test assumes that the library defines default method Spliterator::hasCharacteristics.
+      Method method = Spliterator.class.getDeclaredMethod("hasCharacteristics", int.class);
+      assertNotNull(method);
+      assertTrue(method.isDefault());
+    }
+    if (parameters.isCfRuntime()) {
+      testForJvm()
+          .addProgramClasses(getClasses())
+          .addProgramClassFileData(getTransforms())
+          .run(parameters.getRuntime(), Main.class)
+          .apply(this::checkResult);
+    } else {
+      testForD8()
+          .addProgramClasses(getClasses())
+          .addProgramClassFileData(getTransforms())
+          .setMinApi(parameters.getApiLevel())
+          .enableCoreLibraryDesugaring(parameters.getApiLevel())
+          .compile()
+          .disassemble()
+          .addDesugaredCoreLibraryRunClassPath(
+              this::buildDesugaredLibrary, parameters.getApiLevel())
+          .run(parameters.getRuntime(), Main.class)
+          .apply(this::checkResult);
+    }
+  }
+
+  private void checkResult(TestRunResult<?> result) {
+    if (parameters.isCfRuntime() && parameters.getRuntime().asCf().getVm().equals(CfVm.JDK11)) {
+      // TODO(b/145566657): For some reason JDK11 throws AbstractMethodError.
+      result.assertFailureWithErrorThatMatches(containsString(AbstractMethodError.class.getName()));
+    } else {
+      result.assertFailureWithErrorThatMatches(
+          containsString(IncompatibleClassChangeError.class.getName()));
+    }
+  }
+
+  // Interface that will lead to a conflicting default method with Spliterator::hasCharacteristics.
+  interface MyHasCharacteristics {
+
+    default boolean hasCharacteristics(int characteristics) {
+      System.out.println("MyHasCharacteristics::hasCharacteristics");
+      return false;
+    }
+  }
+
+  // Class deriving the default methods. The resolution of which will throw ICCE.
+  static class MySpliterator implements Spliterator<Integer> /*, MyHasCharacteristics via ASM */ {
+
+    @Override
+    public boolean tryAdvance(Consumer<? super Integer> action) {
+      return false;
+    }
+
+    @Override
+    public Spliterator<Integer> trySplit() {
+      return null;
+    }
+
+    @Override
+    public long estimateSize() {
+      return 0;
+    }
+
+    @Override
+    public int characteristics() {
+      return 0;
+    }
+  }
+
+  // Custom list interface with a default method for spliterator.
+  interface MyIntegerList extends List<Integer> {
+
+    @Override
+    default Spliterator<Integer> spliterator() {
+      return new MySpliterator();
+    }
+  }
+
+  // Derived list with override of spliterator that will explicitly call the custom default method.
+  static class MyIntegerArrayListWithOverride extends ArrayList<Integer> implements MyIntegerList {
+
+    @Override
+    public Spliterator<Integer> spliterator() {
+      return MyIntegerList.super.spliterator();
+    }
+  }
+
+  static class Main {
+
+    public static void main(String[] args) {
+      System.out.println(new MyIntegerArrayListWithOverride().spliterator().hasCharacteristics(0));
+    }
+  }
+}