// 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.retrace.api;

import static org.hamcrest.CoreMatchers.containsString;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;

import com.android.tools.r8.Collectors;
import com.android.tools.r8.TestRuntime.CfRuntime;
import com.android.tools.r8.ToolHelper;
import com.android.tools.r8.ToolHelper.ProcessResult;
import com.android.tools.r8.transformers.ClassFileTransformer;
import com.android.tools.r8.transformers.ClassFileTransformer.InnerClassPredicate;
import com.android.tools.r8.utils.DescriptorUtils;
import com.android.tools.r8.utils.ZipUtils;
import com.android.tools.r8.utils.ZipUtils.ZipBuilder;
import com.google.common.collect.ImmutableList;
import java.io.File;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import org.junit.rules.TemporaryFolder;

public class RetraceApiTestHelper {

  private static final String JUNIT_JAR = "junit-4.13-beta-2.jar";
  private static final String HAMCREST = "hamcrest-core-1.3.jar";

  public static List<Class<? extends RetraceApiBinaryTest>> CLASSES_FOR_BINARY_COMPATIBILITY =
      ImmutableList.of(
          RetraceApiEmptyTest.RetraceTest.class,
          RetraceApiSourceFileTest.ApiTest.class,
          RetraceApiSourceFileNotFoundTest.ApiTest.class,
          RetraceApiInferSourceFileTest.ApiTest.class,
          RetraceApiSynthesizedClassTest.ApiTest.class,
          RetraceApiSynthesizedFieldTest.ApiTest.class,
          RetraceApiSynthesizedMethodTest.ApiTest.class,
          RetraceApiSynthesizedFrameTest.ApiTest.class,
          RetraceApiSynthesizedInnerFrameTest.ApiTest.class,
          RetraceApiUnknownJsonTest.ApiTest.class,
          RetraceApiRewriteFrameInlineNpeTest.ApiTest.class);
  public static List<Class<? extends RetraceApiBinaryTest>> CLASSES_PENDING_BINARY_COMPATIBILITY =
      ImmutableList.of();

  public static void runJunitOnTests(
      CfRuntime runtime,
      Path r8Jar,
      Class<? extends RetraceApiBinaryTest> clazz,
      TemporaryFolder temp)
      throws Exception {
    assertTrue(testIsSpecifiedAsBinaryOrPending(clazz));
    List<Class<? extends RetraceApiBinaryTest>> testClasses = ImmutableList.of(clazz);
    runJunitOnTests(
        runtime, r8Jar, generateJarForRetraceBinaryTests(temp, testClasses), testClasses);
  }

  public static void runJunitOnTests(
      CfRuntime runtime,
      Path r8Jar,
      Path testJar,
      Collection<Class<? extends RetraceApiBinaryTest>> tests)
      throws Exception {
    List<Path> classPaths = ImmutableList.of(getJunitDependency(), getHamcrest(), r8Jar, testJar);
    List<String> args = new ArrayList<>();
    args.add("org.junit.runner.JUnitCore");
    tests.forEach(test -> args.add(test.getTypeName()));
    ProcessResult processResult =
        ToolHelper.runJava(runtime, classPaths, args.toArray(new String[0]));
    assertEquals(processResult.toString(), 0, processResult.exitCode);
    assertThat(processResult.stdout, containsString("OK (" + tests.size() + " test"));
  }

  private static Path getJunitDependency() {
    String junitPath =
        Arrays.stream(System.getProperty("java.class.path").split(File.pathSeparator))
            .filter(cp -> cp.endsWith(JUNIT_JAR))
            .collect(Collectors.toSingle());
    return Paths.get(junitPath);
  }

  private static Path getHamcrest() {
    String junitPath =
        Arrays.stream(System.getProperty("java.class.path").split(File.pathSeparator))
            .filter(cp -> cp.endsWith(HAMCREST))
            .collect(Collectors.toSingle());
    return Paths.get(junitPath);
  }

  public static Path generateJarForRetraceBinaryTests(
      TemporaryFolder temp, Collection<Class<? extends RetraceApiBinaryTest>> classes)
      throws Exception {
    Path jar = File.createTempFile("retrace_api_tests", ".jar", temp.getRoot()).toPath();
    ZipBuilder zipBuilder = ZipBuilder.builder(jar);
    for (Class<? extends RetraceApiBinaryTest> retraceApiTest : classes) {
      zipBuilder.addFilesRelative(
          ToolHelper.getClassPathForTests(),
          ToolHelper.getClassFilesForInnerClasses(retraceApiTest));
      zipBuilder.addBytes(
          ZipUtils.zipEntryNameForClass(retraceApiTest),
          ClassFileTransformer.create(retraceApiTest)
              .removeInnerClasses(
                  InnerClassPredicate.onName(
                      DescriptorUtils.getBinaryNameFromJavaType(retraceApiTest.getTypeName())))
              .transform());
    }
    zipBuilder.addFilesRelative(
        ToolHelper.getClassPathForTests(),
        ToolHelper.getClassFileForTestClass(RetraceApiBinaryTest.class));
    return zipBuilder.build();
  }

  public static Collection<Class<? extends RetraceApiBinaryTest>> getBinaryCompatibilityTests() {
    return CLASSES_FOR_BINARY_COMPATIBILITY;
  }

  private static boolean testIsSpecifiedAsBinaryOrPending(Class<?> clazz) {
    return CLASSES_FOR_BINARY_COMPATIBILITY.contains(clazz)
        || CLASSES_PENDING_BINARY_COMPATIBILITY.contains(clazz);
  }
}
