// Copyright (c) 2020, 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.lambdas;

import static org.junit.Assume.assumeTrue;

import com.android.tools.r8.TestBase;
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.TestParametersCollection;
import com.android.tools.r8.references.Reference;
import com.android.tools.r8.utils.StringUtils;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;

/**
 * These tests document the behavior of lambdas w.r.t identity and equality.
 *
 * <p>The D8 and R8 compilers take the stance that a program should not rely on either identity or
 * equality of any lambda metafactory allocated lambda. Thus the status of these tests differ
 * between JVM, D8/CF, D8/DEX and R8 runs as the compilers may or may not share classes and
 * allocations as seen fit.
 */
@RunWith(Parameterized.class)
public class LambdaEqualityTest extends TestBase {

  static final String EXPECTED_JAVAC =
      StringUtils.lines(
          "Same method refs",
          "true",
          "true",
          "true",
          "Different method refs",
          "false",
          "false",
          "false",
          "Empty lambda",
          "false",
          "false",
          "false");

  static final String EXPECTED_D8 =
      StringUtils.lines(
          "Same method refs",
          "true",
          "true",
          "true",
          "Different method refs",
          "true", // D8 will share the class for the method references.
          "false",
          "false",
          "Empty lambda",
          "false",
          "false",
          "false");

  static final String EXPECTED_R8 =
      StringUtils.lines(
          "Same method refs",
          "true",
          "true",
          "true",
          "Different method refs",
          "true", // R8 will share the class for the method references.
          "false",
          "false",
          "Empty lambda",
          "true", // R8 will eliminate the call to the impl method thus making lambdas equal.
          "true",
          "true");

  private final TestParameters parameters;

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

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

  @Test
  public void testJvm() throws Exception {
    assumeTrue(parameters.isCfRuntime());
    testForRuntime(parameters)
        .addInnerClasses(LambdaEqualityTest.class)
        .run(parameters.getRuntime(), TestClass.class)
        .assertSuccessWithOutput(EXPECTED_JAVAC);
  }

  @Test
  public void testD8() throws Exception {
    testForD8(parameters.getBackend())
        .addInnerClasses(LambdaEqualityTest.class)
        .setMinApi(parameters.getApiLevel())
        .run(parameters.getRuntime(), TestClass.class)
        .assertSuccessWithOutput(EXPECTED_D8);
  }

  @Test
  public void testR8() throws Exception {
    testForR8(parameters.getBackend())
        .addInnerClasses(LambdaEqualityTest.class)
        .setMinApi(parameters.getApiLevel())
        .addKeepMainRule(TestClass.class)
        .addKeepMethodRules(
            Reference.methodFromMethod(
                TestClass.class.getDeclaredMethod(
                    "compare", String.class, MyInterface.class, MyInterface.class)))
        .run(parameters.getRuntime(), TestClass.class)
        // The use of invoke dynamics prohibits the optimization and sharing of lambdas in R8.
        .assertSuccessWithOutput(parameters.isCfRuntime() ? EXPECTED_JAVAC : EXPECTED_R8);
  }

  interface MyInterface {
    void foo();
  }

  static class TestClass {

    public static void compare(String msg, MyInterface i1, MyInterface i2) {
      System.out.println(msg);
      System.out.println(i1.getClass() == i2.getClass());
      System.out.println(i1 == i2);
      System.out.println(i1.equals(i2));
    }

    public static void main(String[] args) {
      MyInterface println = System.out::println;
      // These lambdas are physically the same and should remain so in all cases.
      compare("Same method refs", println, println);
      // These lambdas can be shared as they reference the same actual function.
      compare("Different method refs", println, System.out::println);
      // These lambdas cannot be shared (by D8) as javac will generate a lambda$main$X for each.
      compare("Empty lambda", () -> {}, () -> {});
    }
  }
}
