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

import static com.android.tools.r8.ToolHelper.isLocalDevelopment;
import static com.android.tools.r8.ToolHelper.shouldRunSlowTests;
import static com.android.tools.r8.internal.proto.ProtoShrinkingTestBase.assertRewrittenProtoSchemasMatch;
import static com.android.tools.r8.internal.proto.ProtoShrinkingTestBase.keepAllProtosRule;
import static com.android.tools.r8.internal.proto.ProtoShrinkingTestBase.keepDynamicMethodSignatureRule;
import static com.android.tools.r8.internal.proto.ProtoShrinkingTestBase.keepNewMessageInfoSignatureRule;
import static org.hamcrest.CoreMatchers.anyOf;
import static org.hamcrest.CoreMatchers.containsString;
import static org.junit.Assert.assertTrue;
import static org.junit.Assume.assumeTrue;

import com.android.tools.r8.CompilationFailedException;
import com.android.tools.r8.D8TestCompileResult;
import com.android.tools.r8.L8TestCompileResult;
import com.android.tools.r8.LibraryDesugaringTestConfiguration;
import com.android.tools.r8.R8FullTestBuilder;
import com.android.tools.r8.R8TestCompileResult;
import com.android.tools.r8.ResourceException;
import com.android.tools.r8.StringConsumer.FileConsumer;
import com.android.tools.r8.StringResource;
import com.android.tools.r8.TestCompileResult;
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.TestParametersCollection;
import com.android.tools.r8.ThrowableConsumer;
import com.android.tools.r8.startup.StartupProfileProvider;
import com.android.tools.r8.tracereferences.TraceReferences;
import com.android.tools.r8.tracereferences.TraceReferencesCommand;
import com.android.tools.r8.tracereferences.TraceReferencesKeepRules;
import com.android.tools.r8.utils.AndroidApiLevel;
import com.android.tools.r8.utils.Reporter;
import com.android.tools.r8.utils.codeinspector.CodeInspector;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.concurrent.ExecutionException;
import org.junit.After;
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 YouTubeV1719Test extends YouTubeCompilationTestBase {

  private static final int MAX_APPLICATION_SIZE = 29750000;
  private static final int MAX_DESUGARED_LIBRARY_SIZE = 425000;

  private final TestParameters parameters;

  // Location where test artifacts will be dumped when `local_development` is set.
  private final Path dumpDirectory = Paths.get("YouTubeV1719-" + System.currentTimeMillis());

  // By setting this to an actual startup list, YouTube will be build with layout optimizations
  // enabled.
  private final StartupProfileProvider startupProfileProvider = null;
  private final boolean enableMinimalStartupDex = true;
  private final boolean enableStartupBoundaryOptimizations = false;

  private final Reporter reporter = new Reporter();

  @Parameters(name = "{0}")
  public static TestParametersCollection data() {
    return getTestParameters().withDefaultDexRuntime().withApiLevel(AndroidApiLevel.M).build();
  }

  public YouTubeV1719Test(TestParameters parameters) {
    super(17, 19, parameters.getApiLevel());
    this.parameters = parameters;
  }

  /**
   * Running this test will dump an instrumented version of YouTube in the {@link #dumpDirectory}.
   */
  @Test
  public void testStartupInstrumentation() throws Exception {
    assumeTrue(isLocalDevelopment());
    assumeTrue(shouldRunSlowTests());

    // Compile the app with instrumentation and core library desugaring enabled.
    D8TestCompileResult d8CompileResult =
        testForD8()
            .addProgramFiles(getProgramFiles())
            .addLibraryFiles(getLibraryFileWithoutDesugaredLibrary())
            .addOptionsModification(
                options ->
                    options
                        .getStartupInstrumentationOptions()
                        .setEnableStartupInstrumentation()
                        .setStartupInstrumentationTag("r8"))
            .enableCoreLibraryDesugaring(
                LibraryDesugaringTestConfiguration.builder()
                    .addDesugaredLibraryConfiguration(
                        StringResource.fromFile(getDesugaredLibraryConfiguration()))
                    .build())
            .release()
            .setMinApi(parameters.getApiLevel())
            .compile();

    // Compile desugared library using cf backend (without keep rules).
    L8TestCompileResult l8CompileResult = compileDesugaredLibraryWithL8();

    // Generate keep rules for desugared library using trace references.
    Path generatedKeepRules = temp.newFile().toPath();
    TraceReferences.run(
        TraceReferencesCommand.builder()
            .addLibraryFiles(getLibraryFileWithoutDesugaredLibrary())
            .addSourceFiles(d8CompileResult.writeToZip())
            .addTargetFiles(l8CompileResult.writeToZip())
            .setConsumer(
                TraceReferencesKeepRules.builder()
                    .setAllowObfuscation(false)
                    .setOutputConsumer(new FileConsumer(generatedKeepRules))
                    .build())
            .build());

    // Compile desugared library using the generated keep rules.
    R8TestCompileResult l8R8CompileResult =
        compileDesugaredLibraryWithR8(l8CompileResult, generatedKeepRules);

    if (isLocalDevelopment()) {
      dump(d8CompileResult, l8R8CompileResult);
    }
  }

  /**
   * Running this test will dump an R8 build of YouTube in the {@link #dumpDirectory}, where the
   * desugared library keep rules are generated using trace references.
   *
   * <p>If {@link #startupProfileProvider} is set to a concrete startup list, YouTube will be build
   * with layout optimizations enabled.
   */
  @Test
  public void testR8() throws Exception {
    assumeTrue(isLocalDevelopment());
    assumeTrue(shouldRunSlowTests());

    // Compile app using R8, passing the startup list.
    R8TestCompileResult r8CompileResult =
        compileApplicationWithR8(
            testBuilder ->
                testBuilder.addOptionsModification(
                    options -> {
                      if (startupProfileProvider != null) {
                        options
                            .getStartupOptions()
                            .setStartupProfileProvider(startupProfileProvider)
                            .setEnableMinimalStartupDex(enableMinimalStartupDex)
                            .setEnableStartupBoundaryOptimizations(
                                enableStartupBoundaryOptimizations);
                      }
                    }));

    // Compile desugared library using cf backend (without keep rules).
    L8TestCompileResult l8CompileResult = compileDesugaredLibraryWithL8();

    // Generate keep rules for desugared library using trace references.
    Path generatedKeepRules = temp.newFile().toPath();
    TraceReferences.run(
        TraceReferencesCommand.builder()
            .addLibraryFiles(getLibraryFileWithoutDesugaredLibrary())
            .addSourceFiles(r8CompileResult.writeToZip())
            .addTargetFiles(l8CompileResult.writeToZip())
            .setConsumer(
                TraceReferencesKeepRules.builder()
                    .setAllowObfuscation(false)
                    .setOutputConsumer(new FileConsumer(generatedKeepRules))
                    .build())
            .build());

    // Compile desugared library using the generated keep rules.
    R8TestCompileResult l8R8CompileResult =
        compileDesugaredLibraryWithR8(l8CompileResult, generatedKeepRules);

    if (isLocalDevelopment()) {
      dump(r8CompileResult, l8R8CompileResult);
    }

    inspect(r8CompileResult, l8CompileResult);
  }

  /**
   * Validates that when all protos are kept and the proto optmization is enabled, the generated
   * proto schemas are identical to the proto schemas in the input.
   */
  @Test
  public void testProtoRewriting() throws Exception {
    assumeTrue(shouldRunSlowTests());

    R8TestCompileResult r8CompileResult =
        compileApplicationWithR8(
            builder ->
                builder
                    .addKeepRules(
                        keepAllProtosRule(),
                        keepDynamicMethodSignatureRule(),
                        keepNewMessageInfoSignatureRule())
                    .allowCheckDiscardedErrors(true));
    assertRewrittenProtoSchemasMatch(
        new CodeInspector(getProgramFiles()), r8CompileResult.inspector());
  }

  @After
  public void teardown() {
    reporter.failIfPendingErrors();
  }

  private R8TestCompileResult compileApplicationWithR8(
      ThrowableConsumer<R8FullTestBuilder> configuration)
      throws IOException, CompilationFailedException {
    return testForR8(parameters.getBackend())
        .addProgramFiles(getProgramFiles())
        .addLibraryFiles(getLibraryFileWithoutDesugaredLibrary())
        .addKeepRuleFiles(getKeepRuleFiles())
        .addDontWarn("android.app.Activity$TranslucentConversionListener")
        .apply(configuration)
        .apply(this::disableR8StrictMode)
        .apply(this::disableR8TestingDefaults)
        .setMinApi(getApiLevel())
        .enableCoreLibraryDesugaring(
            LibraryDesugaringTestConfiguration.builder()
                .addDesugaredLibraryConfiguration(
                    StringResource.fromFile(getDesugaredLibraryConfiguration()))
                .build())
        .compile()
        .assertAllInfoMessagesMatch(
            anyOf(
                containsString("Ignoring option: -optimizations"),
                containsString("Proguard configuration rule does not match anything"),
                containsString("Invalid signature")))
        .apply(this::printProtoStats);
  }

  private L8TestCompileResult compileDesugaredLibraryWithL8()
      throws CompilationFailedException, IOException, ExecutionException {
    return testForL8(getApiLevel(), Backend.CF)
        .setDesugaredLibrarySpecification(getDesugaredLibraryConfiguration())
        .addProgramFiles(getDesugaredLibraryJDKLibs())
        .addLibraryFiles(getLibraryFileWithoutDesugaredLibrary())
        .compile();
  }

  private R8TestCompileResult compileDesugaredLibraryWithR8(
      L8TestCompileResult l8CompileResult, Path generatedKeepRules)
      throws IOException, CompilationFailedException {
    return testForR8(parameters.getBackend())
        .addProgramFiles(l8CompileResult.writeToZip())
        .addLibraryFiles(getLibraryFileWithoutDesugaredLibrary())
        .addKeepRuleFiles(getDesugaredLibraryKeepRuleFiles(generatedKeepRules))
        .apply(this::disableR8StrictMode)
        .apply(this::disableR8TestingDefaults)
        .setMinApi(parameters.getApiLevel())
        .compile();
  }

  private void inspect(R8TestCompileResult r8CompileResult, L8TestCompileResult l8CompileResult)
      throws IOException, ResourceException {
    r8CompileResult.runDex2Oat(parameters.getRuntime()).assertNoVerificationErrors();
    l8CompileResult.runDex2Oat(parameters.getRuntime()).assertNoVerificationErrors();

    int applicationSize = r8CompileResult.getApp().applicationSize();
    if (applicationSize > MAX_APPLICATION_SIZE) {
      reporter.error(
          "Expected application size to be <="
              + MAX_APPLICATION_SIZE
              + ", but was "
              + applicationSize);
    }

    int desugaredLibrarySize = l8CompileResult.getApp().applicationSize();
    if (desugaredLibrarySize > MAX_DESUGARED_LIBRARY_SIZE) {
      reporter.error(
          "Expected desugared library size to be <="
              + MAX_DESUGARED_LIBRARY_SIZE
              + ", but was "
              + desugaredLibrarySize);
    }

    if (isLocalDevelopment()) {
      System.out.println("Dex size (application, excluding desugared library): " + applicationSize);
      System.out.println("Dex size (desugared library): " + desugaredLibrarySize);
      System.out.println("Dex size (total): " + (applicationSize + desugaredLibrarySize));
    }
  }

  private void dump(TestCompileResult<?, ?> compileResult, R8TestCompileResult l8R8CompileResult)
      throws IOException {
    assertTrue(isLocalDevelopment());
    Files.createDirectories(dumpDirectory);

    // Dump dex.
    compileResult.writeToDirectory(dumpDirectory);

    // Dump mapping.
    if (compileResult instanceof R8TestCompileResult) {
      R8TestCompileResult r8TestCompileResult = (R8TestCompileResult) compileResult;
      r8TestCompileResult.writeProguardMap(dumpDirectory.resolve("mapping.txt"));
    }

    // Dump desugared library dex.
    int i = 2;
    while (true) {
      Path desugaredLibraryDexFile = dumpDirectory.resolve("classes" + i + ".dex");
      if (!desugaredLibraryDexFile.toFile().exists()) {
        l8R8CompileResult.writeSingleDexOutputToFile(desugaredLibraryDexFile);
        break;
      }
      i++;
    }

    // Dump desugared library mapping.
    l8R8CompileResult.writeProguardMap(dumpDirectory.resolve("mapping-desugared-library.txt"));
  }

  private void disableR8StrictMode(R8FullTestBuilder testBuilder) {
    testBuilder
        .allowDiagnosticMessages()
        .allowUnusedDontWarnPatterns()
        .allowUnusedProguardConfigurationRules();
  }

  private void disableR8TestingDefaults(R8FullTestBuilder testBuilder) {
    testBuilder.addOptionsModification(
        options -> options.horizontalClassMergerOptions().setEnableInterfaceMerging(false));
  }
}
