// 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.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;

import com.android.tools.r8.D8TestRunResult;
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.ToolHelper.DexVm.Version;
import com.android.tools.r8.utils.AndroidApiLevel;
import com.android.tools.r8.utils.StringUtils;
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 is overridden by a class method
 * also in the library, then that class method remains the target of resolution and dispatch.
 *
 * <p>Concretely, List (and Collection) define a default spliterator() method which is overridden in
 * the ArrayList class. Thus, any class deriving ArrayList for which spliterator is not overridden
 * should end up targeting that of ArrayList and not other potential non-library default interface
 * methods.
 */
@RunWith(Parameterized.class)
public class DefaultMethodOverrideInLibraryTest extends DesugaredLibraryTestBase {

  static final String EXPECTED = StringUtils.lines("0", "42", "0", "0", "42", "42");

  private final TestParameters parameters;

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

  public DefaultMethodOverrideInLibraryTest(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 an ArrayList class with a declared spliterator.
      // For that reason, resolution will find that definition prior to a default interface method.
      Method spliterator = ArrayList.class.getDeclaredMethod("spliterator");
      assertNotNull(spliterator);
      assertFalse(spliterator.isDefault());
    }
    if (parameters.isCfRuntime()) {
      testForJvm()
          .addInnerClasses(DefaultMethodOverrideInLibraryTest.class)
          .run(parameters.getRuntime(), Main.class)
          .assertSuccessWithOutput(EXPECTED);
    } else {
      testForD8()
          .addLibraryFiles(ToolHelper.getAndroidJar(AndroidApiLevel.P))
          .setMinApi(parameters.getApiLevel())
          .addInnerClasses(DefaultMethodOverrideInLibraryTest.class)
          .enableCoreLibraryDesugaring(
              LibraryDesugaringTestConfiguration.forApiLevel(parameters.getApiLevel()))
          .compile()
          .run(parameters.getRuntime(), Main.class)
          .apply(this::checkResult);
    }
  }

  private void checkResult(D8TestRunResult result) {
    // TODO(b/145504401): Execution on Art 7.0.0 has the wrong runtime behavior (non-desugared).
    if (parameters.isDexRuntime()
        && parameters.getApiLevel().isGreaterThanOrEqualTo(AndroidApiLevel.N)
        && parameters.getRuntime().asDex().getVm().getVersion().equals(Version.V7_0_0)) {
      result.assertSuccessWithOutputLines("42", "42", "0", "0", "42", "42");
      return;
    }
    result.assertSuccessWithOutput(EXPECTED);
  }

  // Custom spliterator, just returns 42 in estimateSize, otherwise unused.
  static class MySpliterator implements Spliterator<Integer> {

    @Override
    public boolean tryAdvance(Consumer<? super Integer> action) {
      return false;
    }

    @Override
    public Spliterator<Integer> trySplit() {
      return null;
    }

    @Override
    public long estimateSize() {
      return 42; // Overridden to differ from the default.
    }

    @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 no override of spliterator. The call will thus go to the super class, not
  // the default method!
  static class MyIntegerArrayListWithoutOverride extends ArrayList<Integer>
      implements MyIntegerList {
    // No override of spliterator.

    public Spliterator<Integer> superSpliteratorItf() {
      return MyIntegerList.super.spliterator();
    }

    public Spliterator<Integer> superSpliterator() {
      return super.spliterator();
    }
  }

  // Derived list with an override of spliterator. The call must hit the classes override and 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();
    }

    public Spliterator<Integer> superSpliteratorItf() {
      return MyIntegerList.super.spliterator();
    }

    public Spliterator<Integer> superSpliterator() {
      return super.spliterator();
    }
  }

  static class Main {

    public static void main(String[] args) {
      System.out.println(new MyIntegerArrayListWithoutOverride().spliterator().estimateSize());
      System.out.println(new MyIntegerArrayListWithOverride().spliterator().estimateSize());
      System.out.println(new MyIntegerArrayListWithoutOverride().superSpliterator().estimateSize());
      System.out.println(new MyIntegerArrayListWithOverride().superSpliterator().estimateSize());
      System.out.println(
          new MyIntegerArrayListWithoutOverride().superSpliteratorItf().estimateSize());
      System.out.println(new MyIntegerArrayListWithOverride().superSpliteratorItf().estimateSize());
    }
  }
}
