// 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.InternalOptions;
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().withAllRuntimesAndApiLevels().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;
  }

  public boolean hasMalformedInnerClassAttribute() {
    switch (config) {
      case DEFAULT:
      case OUTER_ENDS_WITH_DOLLAR:
      case $_$_$:
      case DOLLAR2_SEPARATOR:
        return false;
      case EMTPY_SEPARATOR:
      case UNDERBAR_SEPARATOR:
      case NON_NESTED_INNER:
      case WRONG_REPACKAGE:
        return true;
      default:
        throw new Unreachable("Unexpected test configuration: " + 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))
            .addOptionsModification(InternalOptions::disableNameReflectionOptimization)
            .setMinApi(parameters.getApiLevel())
            .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))
            .allowDiagnosticInfoMessages(hasMalformedInnerClassAttribute())
            .minification(minify)
            .addOptionsModification(InternalOptions::disableNameReflectionOptimization)
            .setMinApi(parameters.getApiLevel())
            .compile()
            .apply(this::checkWarningsAboutMalformedAttribute);

    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);
  }
}
