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

import static com.android.tools.r8.utils.DescriptorUtils.getDescriptorFromClassBinaryName;

import com.android.tools.r8.D8TestCompileResult;
import com.android.tools.r8.Dex2OatTestRunResult;
import com.android.tools.r8.TestBase;
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.TestParametersCollection;
import com.android.tools.r8.ToolHelper;
import com.android.tools.r8.ToolHelper.DexVm.Version;
import com.android.tools.r8.softverification.TestRunner.Measure;
import com.android.tools.r8.transformers.ClassFileTransformer;
import com.android.tools.r8.transformers.ClassFileTransformer.FieldPredicate;
import com.android.tools.r8.transformers.ClassFileTransformer.MethodPredicate;
import com.android.tools.r8.transformers.MethodTransformer;
import com.android.tools.r8.utils.AndroidApiLevel;
import com.android.tools.r8.utils.ListUtils;
import com.android.tools.r8.utils.ZipUtils.ZipBuilder;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import java.io.IOException;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Collection;
import java.util.List;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameter;
import org.junit.runners.Parameterized.Parameters;

/**
 * This runner produces a benchmark jar that can be used to investigate the time penalty that soft-
 * verification errors have on the runtime of an app. It will build a set of different tests:
 *
 * <pre>
 * - CheckCast
 * - InstanceOf
 * - TypeReference
 * - NewInstance
 * - StaticField
 * - StaticMethod
 * - InstanceField
 * - InstanceMethod
 * </pre>
 *
 * where for each test, there is a reference to either a missing class, existing class with missing
 * members or a full class with all definitions. Each test column can be run by invoking the
 * corresponding test runner:
 *
 * <p>TestRunner_MissingClass, TestRunner_MissingMember, TestRunner_FoundClass
 *
 * <p>To test in a setting with a studio project, modify ANDROID_STUDIO_LIB_PATH to point to an
 * android project. A reference android project can be found at:
 * /google/data/ro/teams/r8/deps/DexVerificationSample.tar.gz
 */
@RunWith(Parameterized.class)
public class TestRunnerBuilder extends TestBase {

  @Parameter() public TestParameters parameters;

  @Parameters(name = "{0}")
  public static TestParametersCollection data() {
    return getTestParameters()
        .withDexRuntime(Version.V9_0_0)
        .withApiLevel(AndroidApiLevel.M)
        .build();
  }

  private static final Path ANDROID_STUDIO_LIB_PATH = Paths.get("PATH_TO_PROJECT/libs/library.jar");

  private static final int COUNT = 800;

  private static final List<Class<?>> referenceClasses =
      ImmutableList.of(
          MissingClass.class, MissingMember.class, FoundClass.class, MissingSuperType.class);
  private static final List<Class<?>> testClasses =
      ImmutableList.of(
          TestCheckCast.class,
          TestInstanceOf.class,
          TestTypeReference.class,
          TestNewInstance.class,
          TestStaticField.class,
          TestStaticMethod.class,
          TestInstanceField.class,
          TestInstanceMethod.class,
          TestHashCode.class,
          TestTryCatch.class);
  private static final Collection<String> testClassBinaryNames =
      ImmutableSet.copyOf(ListUtils.map(testClasses, TestBase::binaryName));

  private static void buildJar(Path path) throws Exception {
    ZipBuilder builder = ZipBuilder.builder(path);
    builder.addFilesRelative(
        ToolHelper.getClassPathForTests(), ToolHelper.getClassFileForTestClass(Measure.class));
    for (Class<?> clazz : referenceClasses) {
      String postFix = clazz.getSimpleName();
      int classCounter = 0;
      for (int i = 0; i < COUNT; i++) {
        for (Class<?> testClass : testClasses) {
          addClass(builder, testClass, clazz, postFix, i, classCounter++);
        }
      }
      if (clazz != MissingClass.class) {
        for (int i = 0; i < classCounter; i++) {
          String binaryName = binaryName(clazz) + "_" + i;
          ClassFileTransformer transformer =
              transformer(clazz).setClassDescriptor(getDescriptorFromClassBinaryName(binaryName));
          if (clazz == MissingMember.class) {
            transformer.removeMethods(MethodPredicate.all()).removeFields(FieldPredicate.all());
          }
          builder.addBytes(binaryName + ".class", transformer.transform());
        }
      }
      String runnerClass = binaryName(TestRunner.class) + "_" + postFix;
      builder.addBytes(
          runnerClass + ".class",
          transformer(TestRunner.class)
              .setClassDescriptor(getDescriptorFromClassBinaryName(runnerClass))
              .addMethodTransformer(
                  new MethodTransformer() {

                    @Override
                    public void visitMaxs(int maxStack, int maxLocals) {
                      super.visitMaxs(-1, maxLocals);
                    }

                    @Override
                    public void visitMethodInsn(
                        int opcode,
                        String owner,
                        String name,
                        String descriptor,
                        boolean isInterface) {
                      if (!testClassBinaryNames.contains(owner)) {
                        super.visitMethodInsn(opcode, owner, name, descriptor, isInterface);
                        return;
                      }
                      for (int i = 0; i < COUNT; i++) {
                        super.visitMethodInsn(
                            opcode, owner + "_" + postFix + "_" + i, name, descriptor, isInterface);
                      }
                    }
                  })
              .transform());
    }
    builder.build();
  }

  private static void addClass(
      ZipBuilder builder,
      Class<?> clazz,
      Class<?> classReference,
      String postFix,
      int index,
      int referenceIndex)
      throws IOException {
    String binaryName = binaryName(clazz) + "_" + postFix + "_" + index;
    String referenceBinaryName = binaryName(classReference) + "_" + referenceIndex;
    builder.addBytes(
        binaryName + ".class",
        transformer(clazz)
            .setClassDescriptor(getDescriptorFromClassBinaryName(binaryName))
            .replaceClassDescriptorInMembers(
                descriptor(MissingClass.class),
                getDescriptorFromClassBinaryName(referenceBinaryName))
            .replaceClassDescriptorInMethodInstructions(
                descriptor(MissingClass.class),
                getDescriptorFromClassBinaryName(referenceBinaryName))
            .transformTryCatchBlock(
                "run",
                (start, end, handler, type, visitor) -> {
                  visitor.visitTryCatchBlock(start, end, handler, referenceBinaryName);
                })
            .transform());
  }

  @Test
  public void buildTest() throws Exception {
    Path benchmarkJar = temp.newFile("library.jar").toPath();
    buildJar(benchmarkJar);
    D8TestCompileResult compileResult =
        testForD8(parameters.getBackend())
            .setMinApi(parameters.getApiLevel())
            .addProgramFiles(benchmarkJar)
            .compile();
    Dex2OatTestRunResult dex2OatTestRunResult = compileResult.runDex2Oat(parameters.getRuntime());
    dex2OatTestRunResult.assertSoftVerificationErrors();
  }

  public static void main(String[] args) throws Exception {
    System.out.println("Building jar and placing in " + ANDROID_STUDIO_LIB_PATH);
    buildJar(ANDROID_STUDIO_LIB_PATH);
  }
}
