// Copyright 2016 The Bazel Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//    http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package com.google.devtools.build.android.desugar;

import static com.google.common.truth.Truth.assertThat;
import static java.lang.reflect.Modifier.isFinal;
import static java.nio.charset.StandardCharsets.UTF_8;
import static org.junit.Assert.fail;

import com.google.common.collect.ImmutableList;
import com.google.common.io.ByteStreams;
import com.google.devtools.build.android.desugar.testdata.CaptureLambda;
import com.google.devtools.build.android.desugar.testdata.ConcreteFunction;
import com.google.devtools.build.android.desugar.testdata.ConstructorReference;
import com.google.devtools.build.android.desugar.testdata.GuavaLambda;
import com.google.devtools.build.android.desugar.testdata.InnerClassLambda;
import com.google.devtools.build.android.desugar.testdata.InterfaceWithLambda;
import com.google.devtools.build.android.desugar.testdata.Lambda;
import com.google.devtools.build.android.desugar.testdata.LambdaInOverride;
import com.google.devtools.build.android.desugar.testdata.MethodReference;
import com.google.devtools.build.android.desugar.testdata.MethodReferenceInSubclass;
import com.google.devtools.build.android.desugar.testdata.MethodReferenceSuperclass;
import com.google.devtools.build.android.desugar.testdata.OuterReferenceLambda;
import com.google.devtools.build.android.desugar.testdata.SpecializedFunction;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.concurrent.Callable;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;

/**
 * Test that exercises classes in the {@code testdata} package.  This is meant to be run against a
 * desugared version of those classes, which in turn exercise various desugaring features.
 */
@RunWith(JUnit4.class)
public class DesugarFunctionalTest {

  private final int expectedBridgesFromSameTarget;
  private final int expectedBridgesFromSeparateTarget;
  private final boolean expectLambdaMethodsInInterfaces;

  public DesugarFunctionalTest() {
    this(3, 1, false);
  }

  /** Constructor for testing desugar while allowing default and static interface methods. */
  protected DesugarFunctionalTest(
      boolean expectBridgesFromSeparateTarget, boolean expectDefaultMethods) {
    this(
        expectDefaultMethods ? 0 : 3,
        expectBridgesFromSeparateTarget ? 1 : 0,
        expectDefaultMethods);
  }

  private DesugarFunctionalTest(int bridgesFromSameTarget, int bridgesFromSeparateTarget,
      boolean lambdaMethodsInInterfaces) {
    this.expectedBridgesFromSameTarget = bridgesFromSameTarget;
    this.expectedBridgesFromSeparateTarget = bridgesFromSeparateTarget;
    this.expectLambdaMethodsInInterfaces = lambdaMethodsInInterfaces;
  }

  @Test
  public void testGuavaLambda() {
    GuavaLambda lambdaUse = new GuavaLambda(ImmutableList.of("Sergey", "Larry", "Alex"));
    assertThat(lambdaUse.as()).containsExactly("Alex");
  }

  @Test
  public void testJavaLambda() {
    Lambda lambdaUse = new Lambda(ImmutableList.of("Sergey", "Larry", "Alex"));
    assertThat(lambdaUse.as()).containsExactly("Alex");
  }

  @Test
  public void testLambdaForIntersectionType() throws Exception {
    assertThat(Lambda.hello().call()).isEqualTo("hello");
  }

  @Test
  public void testCapturingLambda() {
    CaptureLambda lambdaUse = new CaptureLambda(ImmutableList.of("Sergey", "Larry", "Alex"));
    assertThat(lambdaUse.prefixed("L")).containsExactly("Larry");
  }

  @Test
  public void testOuterReferenceLambda() throws Exception {
    OuterReferenceLambda lambdaUse = new OuterReferenceLambda(ImmutableList.of("Sergey", "Larry"));
    assertThat(lambdaUse.filter(ImmutableList.of("Larry", "Alex"))).containsExactly("Larry");
    assertThat(
        isFinal(
            OuterReferenceLambda.class
                .getDeclaredMethod("lambda$filter$0$OuterReferenceLambda", String.class)
                .getModifiers()))
        .isTrue();
  }

  /**
   * Tests a lambda in a subclass whose generated lambda$ method has the same name and signature
   * as a lambda$ method generated by Javac in a superclass and both of these methods are used
   * in the implementation of the subclass (by calling super).  Naively this leads to wrong
   * behavior (in this case, return a non-empty list) because the lambda$ in the superclass is never
   * used once its made non-private during desugaring.
   */
  @Test
  public void testOuterReferenceLambdaInOverride() throws Exception {
    OuterReferenceLambda lambdaUse = new LambdaInOverride(ImmutableList.of("Sergey", "Larry"));
    assertThat(lambdaUse.filter(ImmutableList.of("Larry", "Alex"))).isEmpty();
    assertThat(
        isFinal(
            LambdaInOverride.class
                .getDeclaredMethod("lambda$filter$0$LambdaInOverride", String.class)
                .getModifiers()))
        .isTrue();
  }

  @Test
  public void testLambdaInAnonymousClassReferencesSurroundingMethodParameter() throws Exception {
    assertThat(Lambda.mult(21).apply(2).call()).isEqualTo(42);
  }

  /** Tests a lambda that accesses a method parameter across 2 nested anonymous classes. */
  @Test
  public void testLambdaInNestedAnonymousClass() throws Exception {
    InnerClassLambda lambdaUse = new InnerClassLambda(ImmutableList.of("Sergey", "Larry"));
    assertThat(lambdaUse.prefixFilter("L").apply(ImmutableList.of("Lois", "Larry")).call())
        .containsExactly("Larry");
  }

  @Test
  public void testClassMethodReference() {
    MethodReference methodrefUse = new MethodReference(ImmutableList.of("Sergey", "Larry", "Alex"));
    StringBuilder dest = new StringBuilder();
    methodrefUse.appendAll(dest);
    assertThat(dest.toString()).isEqualTo("SergeyLarryAlex");
  }

  // Regression test for b/33378312
  @Test
  public void testHiddenMethodReference() {
    MethodReference methodrefUse = new MethodReference(ImmutableList.of("Sergey", "Larry", "Alex"));
    assertThat(methodrefUse.intersect(ImmutableList.of("Alex", "Sundar"))).containsExactly("Alex");
  }

  // Regression test for b/33378312
  @Test
  public void testHiddenStaticMethodReference() {
    MethodReference methodrefUse =
        new MethodReference(ImmutableList.of("Sergey", "Larry", "Sundar"));
    assertThat(methodrefUse.some()).containsExactly("Sergey", "Sundar");
  }

  @Test
  public void testDuplicateHiddenMethodReference() {
    MethodReference methodrefUse = new MethodReference(ImmutableList.of("Sergey", "Larry", "Alex"));
    assertThat(methodrefUse.onlyIn(ImmutableList.of("Alex", "Sundar"))).containsExactly("Sundar");
  }

  // Regression test for b/36201257
  @Test
  public void testMethodReferenceThatNeedsBridgeInSubclass() {
    MethodReferenceInSubclass methodrefUse =
        new MethodReferenceInSubclass(ImmutableList.of("Sergey", "Larry", "Alex"));
    assertThat(methodrefUse.containsE()).containsExactly("Sergey", "Alex");
    assertThat(methodrefUse.startsWithL()).containsExactly("Larry");
    // Test sanity: make sure sub- and superclass have bridge methods with matching descriptors but
    // different names
    Method superclassBridge = findOnlyBridge(MethodReferenceSuperclass.class);
    Method subclassBridge = findOnlyBridge(MethodReferenceInSubclass.class);
    assertThat(superclassBridge.getName()).isNotEqualTo(subclassBridge.getName());
    assertThat(superclassBridge.getParameterTypes()).isEqualTo(subclassBridge.getParameterTypes());
  }

  private Method findOnlyBridge(Class<?> clazz) {
    Method result = null;
    for (Method m : clazz.getDeclaredMethods()) {
      if (m.getName().startsWith("bridge$")) {
        assertThat(result).named(m.getName()).isNull();
        result = m;
      }
    }
    assertThat(result).named(clazz.getSimpleName()).isNotNull();
    return result;
  }

  // Regression test for b/33378312
  @Test
  public void testThrowingPrivateMethodReference() throws Exception {
    MethodReference methodrefUse = new MethodReference(ImmutableList.of("Sergey", "Larry"));
    Callable<?> stringer = methodrefUse.stringer();
    try {
      stringer.call();
      fail("IOException expected");
    } catch (IOException expected) {
      assertThat(expected).hasMessageThat().isEqualTo("SergeyLarry");
    } catch (Exception e) {
      throw e;
    }
  }

  // Regression test for b/33304582
  @Test
  public void testInterfaceMethodReference() {
    MethodReference methodrefUse = new MethodReference(ImmutableList.of("Sergey", "Larry", "Alex"));
    MethodReference.Transformer<String> transform = new MethodReference.Transformer<String>() {
      @Override
      public String transform(String input) {
        return input.substring(1);
      }
    };
    assertThat(methodrefUse.transform(transform)).containsExactly("ergey", "arry", "lex");
  }

  @Test
  public void testConstructorReference() {
    ConstructorReference initRefUse = new ConstructorReference(ImmutableList.of("1", "2", "42"));
    assertThat(initRefUse.toInt()).containsExactly(1, 2, 42);
  }

  // Regression test for b/33304582
  @Test
  public void testPrivateConstructorReference() {
    ConstructorReference initRefUse = ConstructorReference.singleton().apply("17");
    assertThat(initRefUse.toInt()).containsExactly(17);
  }

  // This test is similar to testPrivateConstructorReference but the private constructor of an inner
  // class is used as a method reference.  That causes Javac to generate a bridge constructor and
  // a lambda body method that calls it, so the desugaring step doesn't need to do anything to make
  // the private constructor visible.  This is mostly to double-check that we don't interfere with
  // this "already-working" scenario.
  @Test
  public void testPrivateConstructorAccessedThroughJavacGeneratedBridge() {
    try {
      @SuppressWarnings("unused") // local is needed to make ErrorProne happy
      ConstructorReference unused = ConstructorReference.emptyThroughJavacGeneratedBridge().get();
      fail("RuntimeException expected");
    } catch (RuntimeException expected) {
      assertThat(expected).hasMessageThat().isEqualTo("got it!");
    }
  }

  @Test
  public void testExpressionMethodReference() {
    assertThat(
            MethodReference.stringChars(new StringBuilder().append("Larry").append("Sergey"))
                .apply(5))
        .isEqualTo('S');
  }

  @Test
  public void testFieldMethodReference() {
    MethodReference methodrefUse = new MethodReference(ImmutableList.of("Sergey", "Larry", "Alex"));
    assertThat(methodrefUse.toPredicate().test("Larry")).isTrue();
    assertThat(methodrefUse.toPredicate().test("Sundar")).isFalse();
  }

  @Test
  public void testConcreteFunctionWithInheritedBridgeMethods() {
    assertThat(new ConcreteFunction().apply("1234567890987654321")).isEqualTo(1234567890987654321L);
    assertThat(ConcreteFunction.parseAll(ImmutableList.of("5", "17"), new ConcreteFunction()))
        .containsExactly(5L, 17L);
  }

  @Test
  public void testLambdaWithInheritedBridgeMethods() throws Exception {
    assertThat(ConcreteFunction.toInt().apply("123456789")).isEqualTo(123456789);
    assertThat(ConcreteFunction.parseAll(ImmutableList.of("5", "17"), ConcreteFunction.toInt()))
        .containsExactly(5, 17);
    // Expect String apply(Number) and any expected bridges
    assertThat(ConcreteFunction.toInt().getClass().getDeclaredMethods())
        .hasLength(expectedBridgesFromSameTarget + 1);
    // Sanity check that we only copied over methods, no fields, from the functional interface
    try {
      ConcreteFunction.toInt().getClass().getDeclaredField("DO_NOT_COPY_INTO_LAMBDA_CLASSES");
      fail("NoSuchFieldException expected");
    } catch (NoSuchFieldException expected) {}
    assertThat(SpecializedFunction.class.getDeclaredField("DO_NOT_COPY_INTO_LAMBDA_CLASSES"))
        .isNotNull(); // test sanity
  }

  /** Tests lambdas with bridge methods when the implemented interface is in a separate target.*/
  @Test
  public void testLambdaWithBridgeMethodsForInterfaceInSeparateTarget() {
    assertThat(ConcreteFunction.isInt().test(123456789L)).isTrue();
    assertThat(
        ConcreteFunction.doFilter(
            ImmutableList.of(123456789L, 1234567890987654321L),
            ConcreteFunction.isInt()))
        .containsExactly(123456789L);
    // Expect test(Number) and any expected bridges
    assertThat(ConcreteFunction.isInt().getClass().getDeclaredMethods())
        .hasLength(expectedBridgesFromSeparateTarget + 1);
  }

  @Test
  public void testLambdaInInterfaceStaticInitializer() {
    assertThat(InterfaceWithLambda.DIGITS).containsExactly("0", "1").inOrder();
    // <clinit> doesn't count but if there's a lambda method then Jacoco adds more methods
    assertThat(InterfaceWithLambda.class.getDeclaredMethods().length != 0)
        .isEqualTo(expectLambdaMethodsInInterfaces);
  }

  /**
   * Sanity-checks that the resource file included in the original Jar is still there unchanged.
   */
  @Test
  public void testResourcePreserved() throws Exception {
    try (InputStream content = Lambda.class.getResource("testresource.txt").openStream()) {
      assertThat(new String(ByteStreams.toByteArray(content), UTF_8)).isEqualTo("test");
    }
  }

  /**
   * Test for b/62456849. After desugar, the method {@code lambda$mult$0} should still be in the
   * class.
   */
  @Test
  public void testCallMethodWithLambdaNamingConvention()
      throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
    Method method = Lambda.class.getDeclaredMethod("lambda$mult$0");
    Object value = method.invoke(null);
    assertThat(value).isInstanceOf(Integer.class);
    assertThat((Integer) value).isEqualTo(0);
  }
}
