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