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

import static com.android.tools.r8.DiagnosticsMatcher.diagnosticMessage;
import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
import static org.hamcrest.CoreMatchers.containsString;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;

import com.android.tools.r8.DataEntryResource;
import com.android.tools.r8.NeverInline;
import com.android.tools.r8.R8TestCompileResult;
import com.android.tools.r8.TestBase;
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.TestParametersCollection;
import com.android.tools.r8.graph.AppServices;
import com.android.tools.r8.origin.Origin;
import com.android.tools.r8.utils.Box;
import com.android.tools.r8.utils.DataResourceConsumerForTesting;
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.google.common.io.ByteStreams;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.List;
import java.util.ServiceConfigurationError;
import java.util.ServiceLoader;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import java.util.zip.ZipOutputStream;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;

// Test where a service implementation class is missing.
@RunWith(Parameterized.class)
public class MissingServiceImplementationClassTest extends TestBase {

  private final TestParameters parameters;

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

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

  @Test
  public void testR8() throws Exception {
    Box<DataResourceConsumerForTesting> dataResourceConsumer = new Box<>();
    R8TestCompileResult compileResult =
        testForR8(parameters.getBackend())
            .addProgramClasses(TestClass.class, Service.class)
            .addKeepMainRule(TestClass.class)
            .addKeepClassAndMembersRulesWithAllowObfuscation(Service.class)
            .addDataEntryResources(
                DataEntryResource.fromBytes(
                    StringUtils.lines(ServiceImpl.class.getTypeName()).getBytes(),
                    AppServices.SERVICE_DIRECTORY_NAME + Service.class.getTypeName(),
                    Origin.unknown()))
            .addOptionsModification(
                options -> {
                  dataResourceConsumer.set(
                      new DataResourceConsumerForTesting(options.dataResourceConsumer));
                  options.dataResourceConsumer = dataResourceConsumer.get();
                })
            .allowDiagnosticWarningMessages()
            .setMinApi(parameters.getApiLevel())
            .compile()
            .inspectDiagnosticMessages(
                inspector -> {
                  inspector.assertWarningsCount(1);
                  inspector.assertAllWarningsMatch(
                      diagnosticMessage(
                          containsString(
                              "Unexpected reference to missing service implementation class in "
                                  + AppServices.SERVICE_DIRECTORY_NAME
                                  + Service.class.getTypeName()
                                  + ": "
                                  + ServiceImpl.class.getTypeName()
                                  + ".")));
                });

    CodeInspector inspector = compileResult.inspector();
    ClassSubject serviceClassSubject = inspector.clazz(Service.class);
    assertThat(serviceClassSubject, isPresent());

    // Verify that ServiceImpl was not removed from META-INF/services/[...]Service.
    inspectResource(
        dataResourceConsumer.get().get("META-INF/services/" + serviceClassSubject.getFinalName()));

    // Execution fails since META-INF/services/[...]Service is referring to a missing class.
    compileResult
        .run(parameters.getRuntime(), TestClass.class)
        .assertFailureWithErrorThatThrows(ServiceConfigurationError.class);

    // Verify that it is still possible to inject a new implementation of Service after the
    // compilation.
    testForR8(parameters.getBackend())
        .addProgramClasses(ServiceImpl.class)
        .addClasspathClasses(Service.class)
        .addKeepAllClassesRule()
        .addApplyMapping(compileResult.getProguardMap())
        .setMinApi(parameters.getApiLevel())
        .compile()
        .addRunClasspathFiles(
            transformServiceDeclarationInProgram(
                compileResult.writeToZip(),
                AppServices.SERVICE_DIRECTORY_NAME + serviceClassSubject.getFinalName(),
                ServiceImpl.class.getTypeName()))
        .run(parameters.getRuntime(), TestClass.class)
        .assertSuccessWithOutputLines("Hello world!");
  }

  private void inspectResource(List<String> contents) {
    assertNotNull(contents);
    assertEquals(1, contents.size());
    assertEquals(ServiceImpl.class.getTypeName(), contents.get(0));
  }

  private Path transformServiceDeclarationInProgram(Path program, String fileName, String contents)
      throws Exception {
    Path newProgram = temp.newFolder().toPath().resolve("program.jar");
    try (ZipOutputStream outputStream = new ZipOutputStream(Files.newOutputStream(newProgram))) {
      try (ZipInputStream inputStream = new ZipInputStream(Files.newInputStream(program))) {
        ZipEntry next = inputStream.getNextEntry();
        while (next != null) {
          outputStream.putNextEntry(new ZipEntry(next.getName()));
          if (next.getName().equals(fileName)) {
            outputStream.write(contents.getBytes());
          } else {
            outputStream.write(ByteStreams.toByteArray(inputStream));
          }
          outputStream.closeEntry();
          next = inputStream.getNextEntry();
        }
      }
    }
    return newProgram;
  }

  static class TestClass {

    public static void main(String[] args) {
      for (Object object : ServiceLoader.load(getServiceClass())) {
        if (object instanceof Service) {
          Service service = (Service) object;
          service.greet();
        }
      }
    }

    static Class<?> getServiceClass() {
      return System.currentTimeMillis() >= 0 ? Service.class : Object.class;
    }
  }

  public interface Service {

    void greet();
  }

  public static class ServiceImpl implements Service {

    @Override
    @NeverInline
    public void greet() {
      System.out.println("Hello world!");
    }
  }
}
