// Copyright (c) 2020, 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.cf;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;

import com.android.tools.r8.NeverClassInline;
import com.android.tools.r8.NeverInline;
import com.android.tools.r8.R8TestRunResult;
import com.android.tools.r8.TestBase;
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.utils.StringUtils;
import com.android.tools.r8.utils.codeinspector.CodeInspector;
import java.io.IOException;
import java.util.List;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;

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

  static final String EXPECTED = StringUtils.lines(Runner.class.getName());

  private final TestParameters parameters;
  private final CfVersion version;

  @Parameterized.Parameters(name = "{0}, cf:{1}")
  public static List<Object[]> data() {
    return buildParameters(
        getTestParameters().withAllRuntimesAndApiLevels().build(),
        new CfVersion[] {CfVersion.V1_1, CfVersion.V1_4, CfVersion.V1_5});
  }

  public GetClassLdcClassTest(TestParameters parameters, CfVersion version) {
    this.parameters = parameters;
    this.version = version;
  }

  @Test
  public void testReference() throws Exception {
    // Check the program works with the code as-is and the version downgraded.
    testForRuntime(parameters)
        .addProgramClassFileData(getDowngradedClass(Runner.class))
        .addProgramClassFileData(getDowngradedClass(TestClass.class))
        .run(parameters.getRuntime(), TestClass.class)
        .assertSuccessWithOutput(EXPECTED)
        .inspect(
            inspector -> {
              if (parameters.isCfRuntime()) {
                checkVersion(inspector, TestClass.class, version);
                checkVersion(inspector, Runner.class, version);
              }
            });
  }

  @Test
  public void testNoVersionUpgrade() throws Exception {
    testForR8(parameters.getBackend())
        .addProgramClassFileData(getDowngradedClass(Runner.class))
        .addProgramClassFileData(getDowngradedClass(TestClass.class))
        .setMinApi(parameters.getApiLevel())
        .addKeepMainRule(TestClass.class)
        // We cannot keep class Runner, as that prohibits getClass optimization.
        // Instead disable minification and inlining of the Runner class and method.
        .addDontObfuscate()
        .enableInliningAnnotations()
        .enableNeverClassInliningAnnotations()
        .run(parameters.getRuntime(), TestClass.class)
        .assertSuccessWithOutput(EXPECTED)
        .inspect(
            inspector -> {
              if (parameters.isCfRuntime()) {
                checkVersion(inspector, TestClass.class, version);
                checkVersion(inspector, Runner.class, version);
              }
            });
  }

  @Test
  public void testWithVersionUpgrade() throws Exception {
    R8TestRunResult run =
        testForR8(parameters.getBackend())
            .addProgramClassFileData(getDowngradedClass(Runner.class))
            // Here the main class is not downgraded, thus the output may upgrade to that version.
            .addProgramClasses(TestClass.class)
            .setMinApi(parameters.getApiLevel())
            .addKeepMainRule(TestClass.class)
            // We cannot keep class Runner, as that prohibits getClass optimization.
            // Instead disable minification and inlining of the Runner class and method.
            .addDontObfuscate()
            .enableInliningAnnotations()
            .enableNeverClassInliningAnnotations()
            .run(parameters.getRuntime(), TestClass.class);
    run.assertSuccessWithOutput(EXPECTED)
        .inspect(
            inspector -> {
              if (parameters.isCfRuntime()) {
                // We are assuming the runtimes we are testing are post CF SE 1.4 (version 48).
                CfVersion cfVersionForRuntime = getVersion(inspector, TestClass.class);
                assertTrue(CfVersion.V1_4.isLessThan(cfVersionForRuntime));
                // Check that the downgraded class has been bumped to at least SE 1.5 (version 49).
                CfVersion cfVersionAfterUpgrade = getVersion(inspector, Runner.class);
                boolean lessThan = CfVersion.V1_4.isLessThan(cfVersionAfterUpgrade);
                if (!lessThan) {
                  run.disassemble();
                }
                assertTrue("Got version: " + cfVersionAfterUpgrade, lessThan);
              }
              // Check that the method uses a const class instruction.
              assertTrue(
                  inspector
                      .clazz(Runner.class)
                      .uniqueMethodWithName("run")
                      .streamInstructions()
                      .anyMatch(i -> i.isConstClass(Runner.class.getTypeName())));
            });
  }

  private static CfVersion getVersion(CodeInspector inspector, Class<?> clazz) {
    return inspector.clazz(clazz).getDexProgramClass().getInitialClassFileVersion();
  }

  private static void checkVersion(CodeInspector inspector, Class<?> clazz, CfVersion version) {
    assertEquals(version, getVersion(inspector, clazz));
  }

  private byte[] getDowngradedClass(Class<?> clazz) throws IOException {
    return transformer(clazz).setVersion(version).transform();
  }

  @NeverClassInline
  static class Runner {

    @NeverInline
    public void run() {
      System.out.println(getClass().getName());
    }
  }

  static class TestClass {

    public static void main(String[] args) {
      new Runner().run();
    }
  }
}
