// Copyright (c) 2021, 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.graph.genericsignature;

import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.junit.Assert.assertEquals;
import static org.junit.Assume.assumeTrue;

import com.android.tools.r8.TestBase;
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.graph.genericsignature.testclasses.Foo;
import com.android.tools.r8.graph.genericsignature.testclasses.I;
import com.android.tools.r8.graph.genericsignature.testclasses.J;
import com.android.tools.r8.graph.genericsignature.testclasses.K;
import com.android.tools.r8.graph.genericsignature.testclasses.L;
import com.android.tools.r8.graph.genericsignature.testclasses.Main;
import com.android.tools.r8.utils.BooleanUtils;
import com.android.tools.r8.utils.codeinspector.ClassSubject;
import com.android.tools.r8.utils.codeinspector.CodeInspector;
import java.util.List;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;

@RunWith(Parameterized.class)
public class GenericSignatureKeepReferencesPruneTest extends TestBase {

  private final String[] EXPECTED =
      new String[] {
        Foo.class.getTypeName() + "<java.lang.String>",
        I.class.getTypeName()
            + "<java.lang.Integer, "
            + Foo.class.getTypeName()
            + "<java.lang.Integer>>",
        I.class.getTypeName()
            + "<java.lang.String, "
            + Foo.class.getTypeName()
            + "<java.lang.String>>",
        "Hello world"
      };

  private final String[] EXPECTED_FULL_MODE =
      new String[] {
        "class " + Foo.class.getTypeName(),
        "interface " + I.class.getTypeName(),
        "interface " + I.class.getTypeName(),
        "Hello world"
      };

  private final TestParameters parameters;
  private final boolean isCompat;

  @Parameters(name = "{0}, isCompat: {1}")
  public static List<Object[]> data() {
    return buildParameters(
        getTestParameters().withAllRuntimesAndApiLevels().build(), BooleanUtils.values());
  }

  public GenericSignatureKeepReferencesPruneTest(TestParameters parameters, boolean isCompat) {
    this.parameters = parameters;
    this.isCompat = isCompat;
  }

  @Test
  public void testJvm() throws Exception {
    assumeTrue(parameters.isCfRuntime());
    testForJvm()
        .addProgramClasses(I.class, Foo.class, J.class, K.class, L.class)
        .addProgramClassesAndInnerClasses(Main.class)
        .run(parameters.getRuntime(), Main.class)
        .assertSuccessWithOutputLines(EXPECTED);
  }

  @Test
  public void testR8() throws Exception {
    (isCompat ? testForR8Compat(parameters.getBackend()) : testForR8(parameters.getBackend()))
        .addProgramClasses(I.class, Foo.class, J.class, K.class, L.class)
        .addProgramClassesAndInnerClasses(Main.class)
        .addKeepClassAndMembersRules(Main.class)
        .setMinApi(parameters.getApiLevel())
        .addKeepAttributeSignature()
        .addKeepAttributeInnerClassesAndEnclosingMethod()
        .enableInliningAnnotations()
        .enableNeverClassInliningAnnotations()
        .noMinification()
        .compile()
        .inspect(this::inspectSignatures)
        .run(parameters.getRuntime(), Main.class)
        .assertSuccessWithOutputLines(isCompat ? EXPECTED : EXPECTED_FULL_MODE);
  }

  private void inspectSignatures(CodeInspector inspector) {
    ClassSubject fooClass = inspector.clazz(Foo.class);
    assertThat(fooClass, isPresent());
    assertEquals(
        isCompat ? "<T::Ljava/lang/Comparable<TT;>;>Ljava/lang/Object;" : null,
        fooClass.getFinalSignatureAttribute());
    ClassSubject iClass = inspector.clazz(I.class);
    assertThat(iClass, isPresent());
    assertEquals(
        isCompat
            ? "<T::Ljava/lang/Comparable<TT;>;R:L"
                + binaryName(Foo.class)
                + "<TT;>;>Ljava/lang/Object;"
            : null,
        iClass.getFinalSignatureAttribute());
    ClassSubject fooInnerClass = inspector.clazz(Main.class.getTypeName() + "$1");
    assertThat(fooInnerClass, isPresent());
    assertEquals(
        isCompat
            ? "Ljava/lang/Object;L"
                + binaryName(I.class)
                + "<Ljava/lang/String;L"
                + binaryName(Foo.class)
                + "<Ljava/lang/String;>;>;"
            : null,
        fooInnerClass.getFinalSignatureAttribute());
  }
}
