// 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 static org.junit.Assert.fail;

import com.android.tools.r8.LibraryDesugaringTestConfiguration;
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.TestParametersCollection;
import com.android.tools.r8.TestRuntime;
import com.android.tools.r8.TestRuntime.CfVm;
import com.android.tools.r8.ToolHelper;
import com.android.tools.r8.utils.AndroidApiLevel;
import com.google.common.collect.ImmutableList;
import java.io.IOException;
import java.lang.reflect.Method;
import java.util.Collection;
import java.util.LinkedList;
import java.util.List;
import java.util.function.Predicate;
import org.hamcrest.Matcher;
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 is not overridden by a class
 * method in the library, then multiple maximally specific method lead to ICCE.
 *
 * <p>Concretely, Collection defines a default removeIf() method which is not overridden in either
 * the List interface or the LinkedList class. Thus, a class that has an unrelated default method
 * for removeIf will cause a conflict throwing ICCE.
 */
@RunWith(Parameterized.class)
public class DefaultMethodOverrideConflictWithLibraryTest extends DesugaredLibraryTestBase {

  private static List<Class<?>> CLASSES = ImmutableList.of(Main.class, MyRemoveIf.class);

  private static List<byte[]> getTransforms() throws IOException {
    return ImmutableList.of(
        transformer(ConflictingClass.class).setImplements(MyRemoveIf.class).transform());
  }

  private final TestParameters parameters;

  @Parameterized.Parameters(name = "{0}")
  public static TestParametersCollection data() {
    return getTestParameters().withAllRuntimes().withAllApiLevels().build();
  }

  public DefaultMethodOverrideConflictWithLibraryTest(TestParameters parameters) {
    this.parameters = parameters;
  }

  @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 a Collection class with a default removeIf.
      Method removeIf = Collection.class.getDeclaredMethod("removeIf", Predicate.class);
      assertNotNull(removeIf);
      assertTrue(removeIf.isDefault());
      // Also, the LinkedList implementation does *not* define an override of removeIf.
      try {
        LinkedList.class.getDeclaredMethod("removeIf", Predicate.class);
        fail("Unexpected defintion of removeIf on LinkedList");
      } catch (NoSuchMethodException e) {
        // Expected.
      }
    }
    if (parameters.isCfRuntime()) {
      testForJvm()
          .addProgramClasses(CLASSES)
          .addProgramClassFileData(getTransforms())
          .run(parameters.getRuntime(), Main.class)
          .assertFailureWithErrorThatMatches(getExpectedError());
    } else {
      testForD8()
          .addLibraryFiles(ToolHelper.getAndroidJar(AndroidApiLevel.P))
          .setMinApi(parameters.getApiLevel())
          .addProgramClasses(CLASSES)
          .addProgramClassFileData(getTransforms())
          .enableCoreLibraryDesugaring(
              LibraryDesugaringTestConfiguration.forApiLevel(parameters.getApiLevel()))
          .compile()
          .run(parameters.getRuntime(), Main.class)
          .assertFailureWithErrorThatMatches(getExpectedError());
    }
  }

  private Matcher<String> getExpectedError() {
    return containsString(IncompatibleClassChangeError.class.getName());
  }

  // Interface with a default method that can lead to a conflict.
  interface MyRemoveIf {

    default boolean removeIf(Predicate<? super Integer> filter) {
      System.out.println("MyRemoveIf::removeIf");
      return false;
    }
  }

  // Derived list with no override of removeIf but with a default method in MyRemoveIf.
  // The two maximally specific methods Collection::removeIf and MyRemoveIf must cause ICCE.
  static class ConflictingClass extends LinkedList<Integer> /* implements MyRemoveIf via ASM */ {
    // Intentionally empty.
  }

  static class Main {

    public static void main(String[] args) {
      System.out.println(new ConflictingClass().removeIf(e -> false));
    }
  }
}
