// Copyright (c) 2018, 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.ir.optimize.reflection;

import static org.hamcrest.CoreMatchers.containsString;
import static org.junit.Assume.assumeTrue;

import com.android.tools.r8.D8TestCompileResult;
import com.android.tools.r8.D8TestRunResult;
import com.android.tools.r8.JvmTestRunResult;
import com.android.tools.r8.R8TestCompileResult;
import com.android.tools.r8.R8TestRunResult;
import com.android.tools.r8.TestBase;
import com.android.tools.r8.TestCompileResult;
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.TestRuntime.CfVm;
import com.android.tools.r8.ToolHelper.DexVm;
import com.android.tools.r8.errors.Unreachable;
import com.android.tools.r8.utils.BooleanUtils;
import com.android.tools.r8.utils.DescriptorUtils;
import com.android.tools.r8.utils.StringUtils;
import com.android.tools.r8.utils.codeinspector.CodeInspector;
import java.util.Collection;
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 InnerClassNameTestRunner extends TestBase {

  private static final Class<?> MAIN_CLASS = InnerClassNameTest.class;
  private static final String PACKAGE = "com/android/tools/r8/ir/optimize/reflection/";
  private static final String REPACKAGE =
      "com/android/some/other/repackage/tools/r8/ir/optimize/reflection/";

  public enum TestNamingConfig {
    DEFAULT,
    DOLLAR2_SEPARATOR,
    EMTPY_SEPARATOR,
    UNDERBAR_SEPARATOR,
    NON_NESTED_INNER,
    WRONG_REPACKAGE,
    OUTER_ENDS_WITH_DOLLAR,
    $_$_$;

    public String getOuterTypeRaw() {
      switch (this) {
        case DEFAULT:
        case DOLLAR2_SEPARATOR:
        case EMTPY_SEPARATOR:
        case UNDERBAR_SEPARATOR:
        case NON_NESTED_INNER:
        case WRONG_REPACKAGE:
          return "OuterClass";
        case OUTER_ENDS_WITH_DOLLAR:
          return "OuterClass$";
        case $_$_$:
          return "$";
      }
      throw new Unreachable();
    }

    public String getSeparator() {
      switch (this) {
        case DEFAULT:
        case WRONG_REPACKAGE:
        case OUTER_ENDS_WITH_DOLLAR:
        case $_$_$:
          return "$";
        case DOLLAR2_SEPARATOR:
          return "$$";
        case UNDERBAR_SEPARATOR:
          return "_";
        case NON_NESTED_INNER:
        case EMTPY_SEPARATOR:
          return "";
      }
      throw new Unreachable();
    }

    public String getMinifiedSeparator() {
      switch (this) {
        case DEFAULT:
        case OUTER_ENDS_WITH_DOLLAR:
        case $_$_$:
        case UNDERBAR_SEPARATOR:
        case NON_NESTED_INNER:
        case WRONG_REPACKAGE:
        case EMTPY_SEPARATOR:
          return "$";
        case DOLLAR2_SEPARATOR:
          return "$$";
      }
      throw new Unreachable();
    }

    public String getInnerClassName() {
      return this == $_$_$ ? "$" : "InnerClass";
    }

    public String getInnerTypeRaw() {
      switch (this) {
        case DEFAULT:
        case DOLLAR2_SEPARATOR:
        case EMTPY_SEPARATOR:
        case UNDERBAR_SEPARATOR:
        case WRONG_REPACKAGE:
        case OUTER_ENDS_WITH_DOLLAR:
        case $_$_$:
          return getOuterTypeRaw() + getSeparator() + getInnerClassName();
        case NON_NESTED_INNER:
          return getInnerClassName();
      }
      throw new Unreachable();
    }

    public String getInnerInternalType() {
      // b/130706685: Intentionally repackage inner type only.
      return (this == WRONG_REPACKAGE ? REPACKAGE : PACKAGE) + getInnerTypeRaw();
    }

    public String getOuterInternalType() {
      return PACKAGE + getOuterTypeRaw();
    }

    public String getInnerDescriptor() {
      return "L" + getInnerInternalType() + ";";
    }

    public String getOuterDescriptor() {
      return "L" + getOuterInternalType() + ";";
    }

    public static boolean isGetTypeNameSupported(TestParameters parameters) {
      return parameters.getRuntime().isCf()
          || parameters.getRuntime().asDex().getVm().isNewerThan(DexVm.ART_7_0_0_HOST);
    }
  }

  @Parameters(name = "{0} minify:{1} {2}")
  public static Collection<Object[]> parameters() {
    return buildParameters(
        getTestParameters().withAllRuntimes().build(),
        BooleanUtils.values(),
        TestNamingConfig.values());
  }

  private final TestParameters parameters;
  private final boolean minify;
  private final TestNamingConfig config;

  public InnerClassNameTestRunner(
      TestParameters parameters, boolean minify, TestNamingConfig config) {
    this.parameters = parameters;
    this.minify = minify;
    this.config = config;
  }

  private void checkWarningsAboutMalformedAttribute(TestCompileResult<?, ?> result) {
    switch (config) {
      case DEFAULT:
      case OUTER_ENDS_WITH_DOLLAR:
      case $_$_$:
      case DOLLAR2_SEPARATOR:
        result.assertNoMessages();
        break;
      case EMTPY_SEPARATOR:
      case UNDERBAR_SEPARATOR:
      case NON_NESTED_INNER:
      case WRONG_REPACKAGE:
        result
            .assertInfoMessageThatMatches(containsString("Malformed inner-class attribute"))
            .assertInfoMessageThatMatches(containsString(config.getOuterTypeRaw()))
            .assertInfoMessageThatMatches(containsString(config.getInnerTypeRaw()));
        break;
      default:
        throw new Unreachable("Unexpected test configuration: " + config);
    }
  }

  @Test
  public void testD8() throws Exception {
    assumeTrue("Only run D8 for Dex backend", parameters.isDexRuntime() && !minify);
    D8TestCompileResult d8CompileResult =
        testForD8()
            .addProgramClassFileData(InnerClassNameTestDump.dump(config, parameters))
            .setMinApi(parameters.getRuntime())
            .compile();
    checkWarningsAboutMalformedAttribute(d8CompileResult);
    D8TestRunResult d8RunResult = d8CompileResult.run(parameters.getRuntime(), MAIN_CLASS);
    d8RunResult.assertSuccessWithOutput(getExpectedNonMinified(config.getInnerClassName()));
  }

  @Test
  public void testR8() throws Exception {
    JvmTestRunResult runResult = null;
    if (parameters.isCfRuntime()) {
      runResult =
          testForJvm()
              .addProgramClassFileData(InnerClassNameTestDump.dump(config, parameters))
              .run(parameters.getRuntime(), MAIN_CLASS);
    }

    R8TestCompileResult r8CompileResult =
        testForR8(parameters.getBackend())
            .addKeepMainRule(MAIN_CLASS)
            .addKeepRules("-keep,allowobfuscation class * { *; }")
            .addKeepRules("-keepattributes InnerClasses,EnclosingMethod")
            .addProgramClassFileData(InnerClassNameTestDump.dump(config, parameters))
            .minification(minify)
            .setMinApi(parameters.getRuntime())
            .compile();
    checkWarningsAboutMalformedAttribute(r8CompileResult);
    CodeInspector inspector = r8CompileResult.inspector();
    R8TestRunResult r8RunResult = r8CompileResult.run(parameters.getRuntime(), MAIN_CLASS);
    switch (config) {
      case DEFAULT:
      case OUTER_ENDS_WITH_DOLLAR:
      case $_$_$:
        if (parameters.isCfRuntime()) {
          runResult.assertSuccessWithOutput(getExpectedNonMinified(config.getInnerClassName()));
        }
        r8RunResult.assertSuccessWithOutput(getExpectedMinified(inspector));
        break;
      case DOLLAR2_SEPARATOR:
        if (parameters.isCfRuntime()
            && parameters.getRuntime().asCf().getVm().lessThanOrEqual(CfVm.JDK8)) {
          // $$ as separator and InnerClass as name, results in $InnerClass from getSimpleName...
          String expectedWithDollarOnInnerName =
              getExpectedNonMinified("$" + config.getInnerClassName());
          runResult.assertSuccessWithOutput(expectedWithDollarOnInnerName);
          // R8 map the inner name to 'a' while keeping $$ as a separator, whose inner name will be
          // "$a" in JDK under 8.
          r8RunResult.assertSuccessWithOutput(
              minify ? getExpectedMinified(inspector, true) : expectedWithDollarOnInnerName);
        } else {
          // $$ in DEX or JDK 9+ will not change the InnerName/getSimpleName.
          r8RunResult.assertSuccessWithOutput(getExpectedMinified(inspector));
        }
        break;
      case EMTPY_SEPARATOR:
      case UNDERBAR_SEPARATOR:
      case NON_NESTED_INNER:
      case WRONG_REPACKAGE:
        if (!minify
            && parameters.isCfRuntime()
            && parameters.getRuntime().asCf().getVm().lessThanOrEqual(CfVm.JDK8)) {
          // Any non-$ separator results in a runtime exception in getCanonicalName.
          r8RunResult.assertFailureWithErrorThatMatches(containsString("Malformed class name"));
        } else {
          assert minify
              || parameters.isDexRuntime()
              || !parameters.getRuntime().asCf().getVm().lessThanOrEqual(CfVm.JDK8);
          r8RunResult.assertSuccessWithOutput(getExpectedMinified(inspector));
        }
        break;
      default:
        throw new Unreachable("Unexpected test configuration: " + config);
    }
  }

  private String getExpected(String typeName, String canonicalName, String simpleName) {
    if (TestNamingConfig.isGetTypeNameSupported(parameters)) {
      return StringUtils.lines(
          "getName: " + typeName,
          "getTypeName: " + typeName,
          "getCanonicalName: " + canonicalName,
          "getSimpleName: " + simpleName);
    } else {
      return StringUtils.lines(
          "getName: " + typeName,
          "getCanonicalName: " + canonicalName,
          "getSimpleName: " + simpleName);
    }
  }

  private String getExpectedNonMinified(String innerName) {
    String outerClassType = DescriptorUtils.descriptorToJavaType(config.getOuterDescriptor());
    String innerClassType = DescriptorUtils.descriptorToJavaType(config.getInnerDescriptor());
    return getExpected(innerClassType, outerClassType + "." + innerName, innerName);
  }

  private String getExpectedMinified(CodeInspector inspector) {
    return getExpectedMinified(inspector, false);
  }

  private String getExpectedMinified(CodeInspector inspector, boolean withDollarOnInnerName) {
    String outerClassType = DescriptorUtils.descriptorToJavaType(config.getOuterDescriptor());
    String innerClassType = DescriptorUtils.descriptorToJavaType(config.getInnerDescriptor());
    String outerClassTypeFinal = inspector.clazz(outerClassType).getFinalName();
    String innerClassTypeFinal = inspector.clazz(innerClassType).getFinalName();
    String innerNameFinal =
        !minify
            ? config.getInnerClassName()
            : innerClassTypeFinal.substring(
                outerClassTypeFinal.length() + config.getMinifiedSeparator().length());
    innerNameFinal = withDollarOnInnerName ? "$" + innerNameFinal : innerNameFinal;
    return getExpected(
        innerClassTypeFinal, outerClassTypeFinal + "." + innerNameFinal, innerNameFinal);
  }
}
