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

import static com.android.tools.r8.references.Reference.classFromClass;
import static com.android.tools.r8.references.Reference.methodFromMethod;
import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.core.IsNot.not;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;

import com.android.tools.r8.DataEntryResource;
import com.android.tools.r8.R8TestRunResult;
import com.android.tools.r8.TestBase;
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.graph.AppServices;
import com.android.tools.r8.naming.AdaptResourceFileContentsTest.DataResourceConsumerForTesting;
import com.android.tools.r8.origin.Origin;
import com.android.tools.r8.references.ClassReference;
import com.android.tools.r8.references.MethodReference;
import com.android.tools.r8.utils.BooleanUtils;
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.graphinspector.GraphInspector;
import com.android.tools.r8.utils.graphinspector.GraphInspector.QueryNode;
import com.google.common.collect.Lists;
import java.util.List;
import java.util.ServiceLoader;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;

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

  private final boolean includeWorldGreeter;
  private final TestParameters parameters;

  private DataResourceConsumerForTesting dataResourceConsumer;
  private static final String LINE_COMMENT = "# This is a comment.";
  private static final String POSTFIX_COMMENT = "# POSTFIX_COMMENT";

  @Parameters(name = "{1}, include WorldGreeter: {0}")
  public static List<Object[]> data() {
    return buildParameters(BooleanUtils.values(), getTestParameters().withAllRuntimes().build());
  }

  public ServiceLoaderTest(boolean includeWorldGreeter, TestParameters parameters) {
    this.includeWorldGreeter = includeWorldGreeter;
    this.parameters = parameters;
  }

  @Test
  public void test() throws Exception {
    String expectedOutput = includeWorldGreeter ? "Hello world!" : "Hello";

    List<String> serviceImplementations = Lists.newArrayList();

    // Add a comment to the service implementations file.
    serviceImplementations.add(LINE_COMMENT);

    // Postfix a valid line with a comment.
    serviceImplementations.add(HelloGreeter.class.getTypeName() + POSTFIX_COMMENT);

    if (includeWorldGreeter) {
      serviceImplementations.add(WorldGreeter.class.getTypeName());
    }

    R8TestRunResult result =
        testForR8(parameters.getBackend())
            .addInnerClasses(ServiceLoaderTest.class)
            .addKeepMainRule(TestClass.class)
            .addDataEntryResources(
                DataEntryResource.fromBytes(
                    StringUtils.lines(serviceImplementations).getBytes(),
                    "META-INF/services/" + Greeter.class.getTypeName(),
                    Origin.unknown()))
            .addOptionsModification(
                options -> {
                  dataResourceConsumer =
                      new DataResourceConsumerForTesting(options.dataResourceConsumer);
                  options.dataResourceConsumer = dataResourceConsumer;
                  options.enableInliningOfInvokesWithNullableReceivers = false;
                })
            .enableGraphInspector()
            .setMinApi(parameters.getRuntime())
            .run(parameters.getRuntime(), TestClass.class)
            .assertSuccessWithOutput(expectedOutput);

    CodeInspector inspector = result.inspector();

    ClassSubject greeterSubject = inspector.clazz(Greeter.class);
    assertEquals(includeWorldGreeter, greeterSubject.isPresent());

    ClassSubject helloGreeterSubject = inspector.clazz(HelloGreeter.class);
    assertThat(helloGreeterSubject, isPresent());

    ClassSubject worldGreeterSubject = inspector.clazz(WorldGreeter.class);
    assertEquals(includeWorldGreeter, worldGreeterSubject.isPresent());

    String serviceFileName =
        includeWorldGreeter ? greeterSubject.getFinalName() : helloGreeterSubject.getFinalName();
    List<String> lines =
        dataResourceConsumer.get(AppServices.SERVICE_DIRECTORY_NAME + serviceFileName);
    assertEquals(includeWorldGreeter ? 2 : 1, lines.size() - 1);
    assertEquals(LINE_COMMENT, lines.get(0));
    assertEquals(helloGreeterSubject.getFinalName() + POSTFIX_COMMENT, lines.get(1));
    if (includeWorldGreeter) {
      assertEquals(worldGreeterSubject.getFinalName(), lines.get(2));
    }

    verifyGraphInformation(result.graphInspector());
  }

  private void verifyGraphInformation(GraphInspector graphInspector) throws Exception {
    assertEquals(1, graphInspector.getRoots().size());
    QueryNode keepMain = graphInspector.rule(Origin.unknown(), 1, 1).assertRoot();

    MethodReference mainMethod =
        methodFromMethod(TestClass.class.getDeclaredMethod("main", String[].class));
    graphInspector.method(mainMethod).assertKeptBy(keepMain);

    ClassReference helloGreeterClass = classFromClass(HelloGreeter.class);
    MethodReference helloGreeterInitMethod = methodFromMethod(HelloGreeter.class.getConstructor());
    MethodReference helloGreeterGreetingMethod =
        methodFromMethod(HelloGreeter.class.getDeclaredMethod("greeting"));

    graphInspector.clazz(helloGreeterClass).assertKeptBy(graphInspector.method(mainMethod));
    graphInspector.clazz(helloGreeterClass).assertReflectedFrom(mainMethod);
    graphInspector.method(helloGreeterInitMethod).assertReflectedFrom(mainMethod);

    // TODO(b/121313747): greeting() is called from main(), so this should be strengthened to
    //  `assertInvokedFrom(mainMethod)`.
    graphInspector.method(helloGreeterGreetingMethod).assertPresent();

    if (includeWorldGreeter) {
      ClassReference worldGreeterClass = classFromClass(WorldGreeter.class);
      MethodReference worldGreeterInitMethod =
          methodFromMethod(WorldGreeter.class.getConstructor());
      MethodReference worldGreeterGreetingMethod =
          methodFromMethod(WorldGreeter.class.getDeclaredMethod("greeting"));

      graphInspector.clazz(worldGreeterClass).assertKeptBy(graphInspector.method(mainMethod));
      graphInspector.clazz(worldGreeterClass).assertReflectedFrom(mainMethod);
      graphInspector.method(worldGreeterInitMethod).assertReflectedFrom(mainMethod);

      // TODO(b/121313747): greeting() is called from main(), so this should be strengthened to
      //  `assertInvokedFrom(mainMethod)`.
      graphInspector.method(worldGreeterGreetingMethod).assertPresent();
    }
  }

  @Test
  public void testResourceElimination() throws Exception {
    String expectedOutput = "Hello world!";

    List<String> serviceImplementations = Lists.newArrayList(HelloGreeter.class.getTypeName());
    if (includeWorldGreeter) {
      serviceImplementations.add(WorldGreeter.class.getTypeName());
    }

    CodeInspector inspector =
        testForR8(parameters.getBackend())
            .addInnerClasses(ServiceLoaderTest.class)
            .addKeepMainRule(OtherTestClass.class)
            .addDataEntryResources(
                DataEntryResource.fromBytes(
                    StringUtils.lines(serviceImplementations).getBytes(),
                    "META-INF/services/" + Greeter.class.getTypeName(),
                    Origin.unknown()))
            .addOptionsModification(
                options -> {
                  dataResourceConsumer =
                      new DataResourceConsumerForTesting(options.dataResourceConsumer);
                  options.dataResourceConsumer = dataResourceConsumer;
                })
            .setMinApi(parameters.getRuntime())
            .run(parameters.getRuntime(), OtherTestClass.class)
            .assertSuccessWithOutput(expectedOutput)
            .inspector();

    ClassSubject greeterSubject = inspector.clazz(Greeter.class);
    assertThat(greeterSubject, not(isPresent()));

    ClassSubject helloGreeterSubject = inspector.clazz(HelloGreeter.class);
    assertThat(helloGreeterSubject, not(isPresent()));

    ClassSubject worldGreeterSubject = inspector.clazz(WorldGreeter.class);
    assertThat(worldGreeterSubject, not(isPresent()));

    assertTrue(dataResourceConsumer.isEmpty());
  }

  static class TestClass {

    public static void main(String[] args) {
      for (Greeter greeter : ServiceLoader.load(Greeter.class)) {
        System.out.print(greeter.greeting());
      }
    }
  }

  static class OtherTestClass {

    public static void main(String[] args) {
      System.out.print("Hello world!");
    }
  }

  public interface Greeter {

    String greeting();
  }

  public static class HelloGreeter implements Greeter {

    @Override
    public String greeting() {
      return "Hello";
    }
  }

  public static class WorldGreeter implements Greeter {

    @Override
    public String greeting() {
      return " world!";
    }
  }
}
