// 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.naming.overloadaggressively;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assume.assumeTrue;

import com.android.tools.r8.R8Command;
import com.android.tools.r8.TestBase;
import com.android.tools.r8.ToolHelper;
import com.android.tools.r8.ToolHelper.ProcessResult;
import com.android.tools.r8.graph.DexEncodedField;
import com.android.tools.r8.graph.DexEncodedMethod;
import com.android.tools.r8.origin.Origin;
import com.android.tools.r8.utils.AndroidApp;
import com.android.tools.r8.utils.StringUtils;
import com.android.tools.r8.utils.codeinspector.ClassSubject;
import com.android.tools.r8.utils.codeinspector.CodeInspector;
import com.google.common.collect.ImmutableList;
import java.io.IOException;
import java.nio.file.Path;
import java.util.Collections;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;

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

  private Backend backend;

  @Parameterized.Parameters(name = "Backend: {0}")
  public static Backend[] data() {
    return ToolHelper.getBackends();
  }

  public OverloadAggressivelyTest(Backend backend) {
    this.backend = backend;
  }

  private AndroidApp runR8(AndroidApp app, Class<?> main, Path out, boolean overloadaggressively)
      throws Exception {
    R8Command command =
        ToolHelper.addProguardConfigurationConsumer(
                ToolHelper.prepareR8CommandBuilder(app),
                pgConfig -> {
                  pgConfig.setPrintMapping(true);
                  pgConfig.setPrintMappingFile(out.resolve(ToolHelper.DEFAULT_PROGUARD_MAP_FILE));
                })
            .addProguardConfiguration(
                ImmutableList.of(
                    keepMainProguardConfiguration(main),
                    overloadaggressively ? "-overloadaggressively" : ""),
                Origin.unknown())
            .setOutput(out, outputMode(backend))
            .addLibraryFiles(TestBase.runtimeJar(backend))
            .build();
    return ToolHelper.runR8(
        command,
        o -> {
          o.inlinerOptions().enableInlining = false;
          o.forceProguardCompatibility = true;
        });
  }

  private ProcessResult runRaw(AndroidApp app, String main) throws IOException {
    if (backend == Backend.DEX) {
      return runOnArtRaw(app, main);
    } else {
      assert backend == Backend.CF;
      return runOnJavaRaw(app, main, Collections.emptyList());
    }
  }

  private void fieldUpdater(boolean overloadaggressively) throws Exception {
    byte[][] classes = {
        ToolHelper.getClassAsBytes(FieldUpdater.class),
        ToolHelper.getClassAsBytes(A.class),
        ToolHelper.getClassAsBytes(B.class)
    };
    AndroidApp originalApp = buildAndroidApp(classes);
    Path out = temp.getRoot().toPath();
    AndroidApp processedApp = runR8(originalApp, FieldUpdater.class, out, overloadaggressively);

    CodeInspector codeInspector = new CodeInspector(processedApp);
    ClassSubject a = codeInspector.clazz(A.class.getCanonicalName());
    DexEncodedField f1 = a.field("int", "f1").getField();
    assertNotNull(f1);
    DexEncodedField f2 = a.field("java.lang.Object", "f2").getField();
    assertNotNull(f2);
    // TODO(b/72858955): due to the potential reflective access, they should have different names
    //   by R8's improved reflective access detection or via keep rules.
    assertEquals(overloadaggressively, f1.getReference().name == f2.getReference().name);
    DexEncodedField f3 = a.field(B.class.getCanonicalName(), "f3").getField();
    assertNotNull(f3);
    // TODO(b/72858955): ditto
    assertEquals(overloadaggressively, f1.getReference().name == f3.getReference().name);
    // TODO(b/72858955): ditto
    assertEquals(overloadaggressively, f2.getReference().name == f3.getReference().name);

    String main = FieldUpdater.class.getCanonicalName();
    ProcessResult javaOutput = runOnJavaRaw(main, classes);
    assertEquals(0, javaOutput.exitCode);
    ProcessResult output = runRaw(processedApp, main);
    // TODO(b/72858955): eventually, R8 should avoid this field resolution conflict.
    if (overloadaggressively) {
      assertNotEquals(0, output.exitCode);
      assertTrue(output.stderr.contains("ClassCastException"));
    } else {
      assertEquals(0, output.exitCode);
      assertEquals(javaOutput.stdout.trim(), output.stdout.trim());
      // ART may dump its own debugging info through stderr.
      // assertEquals(javaOutput.stderr.trim(), artOutput.stderr.trim());
    }
  }

  @Test
  public void testFieldUpdater_aggressively() throws Exception {
    fieldUpdater(true);
  }

  @Test
  public void testFieldUpdater_not_aggressively() throws Exception {
    fieldUpdater(false);
  }

  private void fieldResolution(boolean overloadaggressively) throws Exception {
    byte[][] classes = {
        ToolHelper.getClassAsBytes(FieldResolution.class),
        ToolHelper.getClassAsBytes(A.class),
        ToolHelper.getClassAsBytes(B.class)
    };
    AndroidApp originalApp = buildAndroidApp(classes);
    Path out = temp.getRoot().toPath();
    AndroidApp processedApp = runR8(originalApp, FieldResolution.class, out, overloadaggressively);

    CodeInspector codeInspector = new CodeInspector(processedApp);
    ClassSubject a = codeInspector.clazz(A.class.getCanonicalName());
    DexEncodedField f1 = a.field("int", "f1").getField();
    assertNotNull(f1);
    DexEncodedField f3 = a.field(B.class.getCanonicalName(), "f3").getField();
    assertNotNull(f3);
    // TODO(b/72858955): due to the potential reflective access, they should have different names
    //   by R8's improved reflective access detection or via keep rules.
    assertEquals(overloadaggressively, f1.getReference().name == f3.getReference().name);

    String main = FieldResolution.class.getCanonicalName();
    ProcessResult javaOutput = runOnJavaRaw(main, classes);
    assertEquals(0, javaOutput.exitCode);
    ProcessResult output = runRaw(processedApp, main);
    // TODO(b/72858955): R8 should avoid field resolution conflict even w/ -overloadaggressively.
    if (overloadaggressively) {
      assertNotEquals(0, output.exitCode);
      assertTrue(output.stderr.contains("IllegalArgumentException"));
    } else {
      assertEquals(0, output.exitCode);
      assertEquals(javaOutput.stdout.trim(), output.stdout.trim());
      // ART may dump its own debugging info through stderr.
      // assertEquals(javaOutput.stderr.trim(), artOutput.stderr.trim());
    }
  }

  @Test
  public void testFieldResolution_aggressively() throws Exception {
    fieldResolution(true);
  }

  @Test
  public void testFieldResolution_not_aggressively() throws Exception {
    fieldResolution(false);
  }

  private void methodResolution(boolean overloadaggressively) throws Exception {
    String expected = StringUtils.lines("diff: 0", "d8 v.s. d8", "r8 v.s. r8");
    String expectedOverloadAggressively = StringUtils.lines("diff: 0", "d8 v.s. 8", "r8 v.s. 8");

    if (backend.isCf()) {
      testForJvm().addTestClasspath().run(MethodResolution.class).assertSuccessWithOutput(expected);
    }

    testForR8Compat(backend)
        .addProgramClasses(MethodResolution.class, B.class)
        .addKeepMainRule(MethodResolution.class)
        .addOptionsModification(options -> options.inlinerOptions().enableInlining = false)
        .applyIf(overloadaggressively, builder -> builder.addKeepRules("-overloadaggressively"))
        .enableMemberValuePropagationAnnotations()
        .compile()
        .inspect(inspector -> inspect(inspector, overloadaggressively))
        .run(MethodResolution.class)
        .applyIf(
            overloadaggressively,
            runResult -> runResult.assertSuccessWithOutput(expectedOverloadAggressively),
            runResult -> runResult.assertSuccessWithOutput(expected));
  }

  private void inspect(CodeInspector codeInspector, boolean overloadaggressively) {
    ClassSubject b = codeInspector.clazz(B.class.getCanonicalName());
    DexEncodedMethod m1 =
        b.method("int", "getF1", ImmutableList.of()).getMethod();
    assertNotNull(m1);
    DexEncodedMethod m2 =
        b.method("java.lang.Object", "getF2", ImmutableList.of()).getMethod();
    assertNotNull(m2);
    // TODO(b/72858955): due to the potential reflective access, they should have different names.
    assertEquals(overloadaggressively, m1.getReference().name == m2.getReference().name);
    DexEncodedMethod m3 =
        b.method("java.lang.String", "getF3", ImmutableList.of()).getMethod();
    assertNotNull(m3);
    // TODO(b/72858955): ditto
    assertEquals(overloadaggressively, m1.getReference().name == m3.getReference().name);
    // TODO(b/72858955): ditto
    assertEquals(overloadaggressively, m2.getReference().name == m3.getReference().name);
  }

  @Test
  public void testMethodResolution_aggressively() throws Exception {
    assumeTrue(backend == Backend.CF);
    methodResolution(true);
  }

  @Test
  public void testMethodResolution_not_aggressively() throws Exception {
    methodResolution(false);
  }
}
