// 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,
          RetraceApiInferSourceFileTest.ApiTest.class,
          RetraceApiSynthesizedClassTest.ApiTest.class,
          RetraceApiSynthesizedFieldTest.ApiTest.class,
          RetraceApiSynthesizedMethodTest.ApiTest.class,
          RetraceApiSynthesizedFrameTest.ApiTest.class,
          RetraceApiSynthesizedInnerFrameTest.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);
  }
}
