// 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.compilerapi;

import static org.junit.Assert.assertEquals;

import com.android.tools.r8.compilerapi.mockdata.MockClass;
import com.android.tools.r8.compilerapi.mockdata.MockClassWithAssertion;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Collections;
import java.util.List;
import org.junit.Rule;
import org.junit.rules.TemporaryFolder;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;

/**
 * Base class for any actual API test.
 *
 * <p>Subclasses of this must only use the public API and the otherwise linked libraries (junit,
 * etc).
 */
@RunWith(Parameterized.class)
public abstract class CompilerApiTest {

  public static final Object PARAMETERS = "none";

  public static final String API_TEST_MODE_KEY = "API_TEST_MODE";
  public static final String API_TEST_MODE_EXTERNAL = "external";

  public static final String API_TEST_LIB_KEY = "API_TEST_LIB";
  public static final String API_TEST_LIB_YES = "yes";
  public static final String API_TEST_LIB_NO = "no";

  @Parameters(name = "{0}")
  public static List<Object> data() {
    // Simulate only running the API tests directly on the "none" runtime configuration.
    String runtimes = System.getProperty("runtimes");
    if (runtimes != null && !runtimes.contains("none")) {
      return Collections.emptyList();
    }
    return Collections.singletonList(PARAMETERS);
  }

  @Rule public final TemporaryFolder temp = new TemporaryFolder();

  public CompilerApiTest(Object none) {
    assertEquals(PARAMETERS, none);
  }

  /** Predicate to determine if the test is being run externally. */
  public boolean isRunningExternal() {
    return API_TEST_MODE_EXTERNAL.equals(System.getProperty(API_TEST_MODE_KEY));
  }

  /** Predicate to determine if the test is being run for an R8 lib compilation. */
  public boolean isRunningR8Lib() {
    return API_TEST_LIB_YES.equals(System.getProperty(API_TEST_LIB_KEY));
  }

  public Path getNewTempFolder() throws IOException {
    return temp.newFolder().toPath();
  }

  public Class<?> getMockClass() {
    return MockClass.class;
  }

  public Class<?> getMockClassWithAssertion() {
    return MockClassWithAssertion.class;
  }

  public Path getJava8RuntimeJar() {
    return Paths.get("third_party", "openjdk", "openjdk-rt-1.8", "rt.jar");
  }

  public List<String> getKeepMainRules(Class<?> clazz) {
    return Collections.singletonList(
        "-keep class " + clazz.getName() + " { public static void main(java.lang.String[]); }");
  }

  public Path getPathForClass(Class<?> clazz) {
    String file = clazz.getName().replace('.', '/') + ".class";
    return Paths.get("build", "classes", "java", "test", file);
  }

  public byte[] getBytesForClass(Class<?> clazz) throws IOException {
    return Files.readAllBytes(getPathForClass(clazz));
  }
}
