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

import static junit.framework.Assert.assertNotNull;
import static junit.framework.TestCase.assertEquals;
import static junit.framework.TestCase.assertNull;
import static junit.framework.TestCase.assertTrue;
import static org.junit.Assume.assumeTrue;

import com.android.tools.r8.CompilationFailedException;
import com.android.tools.r8.DataEntryResource;
import com.android.tools.r8.NeverInline;
import com.android.tools.r8.TestBase;
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.TestParametersCollection;
import com.android.tools.r8.ToolHelper.DexVm.Version;
import com.android.tools.r8.origin.Origin;
import com.android.tools.r8.utils.StringUtils;
import com.android.tools.r8.utils.codeinspector.ClassSubject;
import com.android.tools.r8.utils.codeinspector.CodeInspector;
import com.android.tools.r8.utils.codeinspector.InstructionSubject;
import com.android.tools.r8.utils.codeinspector.MethodSubject;
import java.io.IOException;
import java.nio.file.Path;
import java.util.ServiceLoader;
import java.util.concurrent.ExecutionException;
import java.util.zip.ZipFile;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;

@RunWith(Parameterized.class)
public class ServiceLoaderRewritingTest extends TestBase {

  private final TestParameters parameters;
  private final String EXPECTED_OUTPUT =
      StringUtils.lines("Hello World!", "Hello World!", "Hello World!");

  public interface Service {

    void print();
  }

  public static class ServiceImpl implements Service {

    @Override
    public void print() {
      System.out.println("Hello World!");
    }
  }

  public static class MainRunner {

    public static void main(String[] args) {
      ServiceLoader.load(Service.class, Service.class.getClassLoader()).iterator().next().print();
      ServiceLoader.load(Service.class, null).iterator().next().print();
      for (Service x : ServiceLoader.load(Service.class, Service.class.getClassLoader())) {
        x.print();
      }
      // TODO(b/120436373) The stream API for ServiceLoader was added in Java 9. When we can model
      //   streams correctly, uncomment the lines below and adjust EXPECTED_OUTPUT.
      // ServiceLoader.load(Service.class, Service.class.getClassLoader())
      //   .stream().forEach(x -> x.get().print());
    }
  }

  public static class OtherRunner {

    public static void main(String[] args) {
      ServiceLoader.load(Service.class).iterator().next().print();
      ServiceLoader.load(Service.class, Thread.currentThread().getContextClassLoader())
          .iterator()
          .next()
          .print();
      ServiceLoader.load(Service.class, OtherRunner.class.getClassLoader())
          .iterator()
          .next()
          .print();
    }
  }

  public static class EscapingRunner {

    public ServiceLoader<Service> serviceImplementations;

    @NeverInline
    public ServiceLoader<Service> getServices() {
      return ServiceLoader.load(Service.class, Thread.currentThread().getContextClassLoader());
    }

    @NeverInline
    public void printServices() {
      print(ServiceLoader.load(Service.class, Thread.currentThread().getContextClassLoader()));
    }

    @NeverInline
    public void print(ServiceLoader<Service> loader) {
      loader.iterator().next().print();
    }

    @NeverInline
    public void assignServicesField() {
      serviceImplementations =
          ServiceLoader.load(Service.class, Thread.currentThread().getContextClassLoader());
    }

    public static void main(String[] args) {
      EscapingRunner escapingRunner = new EscapingRunner();
      escapingRunner.getServices().iterator().next().print();
      escapingRunner.printServices();
      escapingRunner.assignServicesField();
      escapingRunner.print(escapingRunner.serviceImplementations);
    }
  }

  @Parameterized.Parameters(name = "{0}")
  public static TestParametersCollection data() {
    return getTestParameters().withAllRuntimes().build();
  }

  public ServiceLoaderRewritingTest(TestParameters parameters) {
    this.parameters = parameters;
  }

  @Test
  public void testRewritings() throws IOException, CompilationFailedException, ExecutionException {
    Path path = temp.newFile("out.zip").toPath();
    testForR8(parameters.getBackend())
        .addInnerClasses(ServiceLoaderRewritingTest.class)
        .addKeepMainRule(MainRunner.class)
        .setMinApi(parameters.getRuntime())
        .addDataEntryResources(
            DataEntryResource.fromBytes(
                StringUtils.lines(ServiceImpl.class.getTypeName()).getBytes(),
                "META-INF/services/" + Service.class.getTypeName(),
                Origin.unknown()))
        .compile()
        .writeToZip(path)
        .run(parameters.getRuntime(), MainRunner.class)
        .assertSuccessWithOutput(EXPECTED_OUTPUT)
        .inspect(
            inspector -> {
              // Check that we have actually rewritten the calls to ServiceLoader.load.
              ClassSubject clazz = inspector.clazz(MainRunner.class);
              assertTrue(clazz.isPresent());
              MethodSubject main = clazz.uniqueMethodWithName("main");
              assertTrue(main.isPresent());
              assertTrue(
                  main.streamInstructions()
                      .noneMatch(ServiceLoaderRewritingTest::isServiceLoaderLoad));
            });

    // Check that we have removed the service configuration from META-INF/services.
    ZipFile zip = new ZipFile(path.toFile());
    assertNull(zip.getEntry("META-INF/services"));
  }

  @Test
  public void testDoNoRewrite() throws IOException, CompilationFailedException, ExecutionException {
    Path path = temp.newFile("out.zip").toPath();
    CodeInspector inspector =
        testForR8(parameters.getBackend())
            .addInnerClasses(ServiceLoaderRewritingTest.class)
            .addKeepMainRule(OtherRunner.class)
            .setMinApi(parameters.getRuntime())
            .addDataEntryResources(
                DataEntryResource.fromBytes(
                    StringUtils.lines(ServiceImpl.class.getTypeName()).getBytes(),
                    "META-INF/services/" + Service.class.getTypeName(),
                    Origin.unknown()))
            .compile()
            .writeToZip(path)
            .run(parameters.getRuntime(), OtherRunner.class)
            .assertSuccessWithOutput(EXPECTED_OUTPUT)
            .inspector();

    // Check that we have not rewritten the calls to ServiceLoader.load.
    ClassSubject clazz = inspector.clazz(OtherRunner.class);
    assertTrue(clazz.isPresent());
    MethodSubject main = clazz.uniqueMethodWithName("main");
    assertTrue(main.isPresent());
    assertEquals(
        3,
        main.streamInstructions().filter(ServiceLoaderRewritingTest::isServiceLoaderLoad).count());

    // Check that we have not removed the service configuration from META-INF/services.
    ZipFile zip = new ZipFile(path.toFile());
    ClassSubject serviceImpl = inspector.clazz(ServiceImpl.class);
    assertTrue(serviceImpl.isPresent());
    assertNotNull(zip.getEntry("META-INF/services/" + serviceImpl.getFinalName()));
  }

  @Test
  public void testDoNoRewriteWhenEscaping()
      throws IOException, CompilationFailedException, ExecutionException {
    Path path = temp.newFile("out.zip").toPath();
    CodeInspector inspector =
        testForR8(parameters.getBackend())
            .addInnerClasses(ServiceLoaderRewritingTest.class)
            .addKeepMainRule(EscapingRunner.class)
            .enableInliningAnnotations()
            .setMinApi(parameters.getRuntime())
            .noMinification()
            .addDataEntryResources(
                DataEntryResource.fromBytes(
                    StringUtils.lines(ServiceImpl.class.getTypeName()).getBytes(),
                    "META-INF/services/" + Service.class.getTypeName(),
                    Origin.unknown()))
            .compile()
            .writeToZip(path)
            .run(parameters.getRuntime(), EscapingRunner.class)
            .assertSuccessWithOutput(EXPECTED_OUTPUT)
            .inspector();

    // Check that we have not rewritten the calls to ServiceLoader.load.
    ClassSubject clazz = inspector.clazz(EscapingRunner.class);
    assertTrue(clazz.isPresent());
    int allServiceLoaders =
        clazz.allMethods().stream()
            .mapToInt(
                method ->
                    (int)
                        method
                            .streamInstructions()
                            .filter(ServiceLoaderRewritingTest::isServiceLoaderLoad)
                            .count())
            .sum();
    assertEquals(3, allServiceLoaders);
    // Check that we have not removed the service configuration from META-INF/services.
    ZipFile zip = new ZipFile(path.toFile());
    ClassSubject serviceImpl = inspector.clazz(ServiceImpl.class);
    assertTrue(serviceImpl.isPresent());
    assertNotNull(zip.getEntry("META-INF/services/" + serviceImpl.getFinalName()));
  }

  @Test
  public void testKeepAsOriginal()
      throws IOException, CompilationFailedException, ExecutionException {
    // The CL that changed behaviour after Nougat is:
    // https://android-review.googlesource.com/c/platform/libcore/+/273135
    assumeTrue(
        parameters.getRuntime().isCf()
            || !parameters.getRuntime().asDex().getVm().getVersion().equals(Version.V7_0_0));
    Path path = temp.newFile("out.zip").toPath();
    CodeInspector inspector =
        testForR8(parameters.getBackend())
            .addInnerClasses(ServiceLoaderRewritingTest.class)
            .addKeepMainRule(MainRunner.class)
            .addKeepClassRules(Service.class)
            .setMinApi(parameters.getRuntime())
            .addDataEntryResources(
                DataEntryResource.fromBytes(
                    StringUtils.lines(ServiceImpl.class.getTypeName()).getBytes(),
                    "META-INF/services/" + Service.class.getTypeName(),
                    Origin.unknown()))
            .compile()
            .writeToZip(path)
            .run(parameters.getRuntime(), MainRunner.class)
            .assertSuccessWithOutput(EXPECTED_OUTPUT)
            .inspector();

    // Check that we have not rewritten the calls to ServiceLoader.load.
    ClassSubject clazz = inspector.clazz(MainRunner.class);
    assertTrue(clazz.isPresent());
    MethodSubject main = clazz.uniqueMethodWithName("main");
    assertTrue(main.isPresent());
    assertEquals(
        3,
        main.streamInstructions().filter(ServiceLoaderRewritingTest::isServiceLoaderLoad).count());

    // Check that we have not removed the service configuration from META-INF/services.
    ZipFile zip = new ZipFile(path.toFile());
    ClassSubject service = inspector.clazz(Service.class);
    assertTrue(service.isPresent());
    assertNotNull(zip.getEntry("META-INF/services/" + service.getFinalName()));
  }

  private static boolean isServiceLoaderLoad(InstructionSubject instruction) {
    return instruction.isInvokeStatic()
        && instruction.getMethod().qualifiedName().contains("ServiceLoader.load");
  }
}
