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

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;

import com.android.tools.r8.desugar.desugaredlibrary.test.LibraryDesugaringSpecification;
import com.android.tools.r8.profile.art.ArtProfile;
import com.android.tools.r8.profile.art.ArtProfileConsumer;
import com.android.tools.r8.profile.art.ArtProfileForRewriting;
import com.android.tools.r8.profile.art.ArtProfileProvider;
import com.android.tools.r8.profile.startup.profile.StartupProfile;
import com.android.tools.r8.profile.startup.profile.StartupProfileRule;
import com.android.tools.r8.startup.StartupProfileProvider;
import com.android.tools.r8.startup.diagnostic.MissingStartupProfileItemsDiagnostic;
import com.android.tools.r8.utils.AndroidApiLevel;
import com.android.tools.r8.utils.InternalOptions;
import com.android.tools.r8.utils.internal.FileUtils;
import com.android.tools.r8.utils.internal.IntBox;
import com.android.tools.r8.utils.internal.ListUtils;
import com.android.tools.r8.utils.timing.Timing;
import com.google.common.collect.ImmutableList;
import java.io.IOException;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import org.junit.Test;

public abstract class CommandTestBase<C extends BaseCompilerCommand> extends TestBase {

  public boolean isL8() {
    return false;
  }

  private void mapDiagnosticsMissingArguments(String... args) {
    try {
      // TODO(jonathanlist): Make this more precise once all CLI uses CliParser.
      DiagnosticsChecker.checkErrorsContains(
          "for --map-diagnostics", handler -> parse(handler, args));
      fail("Expected failure");
    } catch (CompilationFailedException e) {
      // Expected.
    }
  }

  @Test
  public void mapDiagnosticsMissingArguments() throws Exception {
    mapDiagnosticsMissingArguments("--map-diagnostics");
    mapDiagnosticsMissingArguments("--map-diagnostics", "error");
    mapDiagnosticsMissingArguments("--map-diagnostics", "warning");
    mapDiagnosticsMissingArguments("--map-diagnostics", "info");
    mapDiagnosticsMissingArguments("--map-diagnostics", "xxx");
  }

  private void mapDiagnosticsInvalidArguments(String... args) {
    try {
      DiagnosticsChecker.checkErrorsContains(
          "Invalid diagnostics level 'xxx'", handler -> parse(handler, args));
      fail("Expected failure");
    } catch (CompilationFailedException e) {
      // Expected.
    }
  }

  @Test
  public void mapDiagnosticsInvalidArguments() throws Exception {
    mapDiagnosticsInvalidArguments("--map-diagnostics", "error", "xxx");
    mapDiagnosticsInvalidArguments("--map-diagnostics", "warning", "xxx");
    mapDiagnosticsInvalidArguments("--map-diagnostics", "info", "xxx");
    mapDiagnosticsInvalidArguments("--map-diagnostics", "xxx", "xxx");
    mapDiagnosticsInvalidArguments("--map-diagnostics", "xxx", "error");
    mapDiagnosticsInvalidArguments("--map-diagnostics", "xxx", "warning");
    mapDiagnosticsInvalidArguments("--map-diagnostics", "xxx", "info");
    mapDiagnosticsInvalidArguments("--debug", "--map-diagnostics", "error", "xxx", "--debug");
  }

  @Test
  public void mapDiagnosticsInvalidArgumentsMoreErrors() {
    try {
      DiagnosticsChecker.checkErrorsContains(
          ImmutableList.of("Invalid diagnostics level 'xxx'", "Unknown option: --xxx"),
          handler -> parse(handler, "--debug", "--map-diagnostics", "error", "xxx", "--xxx"));
      fail("Expected failure");
    } catch (CompilationFailedException e) {
      // Expected.
    }
  }

  @Test
  public void mapDiagnosticsFromLevelNone() {
    try {
      DiagnosticsChecker.checkErrorsContains(
          "Cannot map from diagnostics level 'none'",
          handler -> parse(handler, "--map-diagnostics", "none", "warning"));
      fail("Expected failure");
    } catch (CompilationFailedException e) {
      // Expected.
    }
  }

  @Test
  public void errorsToWarnings() throws Exception {
    DiagnosticsChecker.checkWarningsContains(
        "Error",
        handler -> {
          C command = parseWithRequiredArgs(handler, "--map-diagnostics", "error", "warning");
          command.getReporter().error("Error");
        });

    try {
      DiagnosticsChecker.checkErrorsContains(
          "Test diagnostic",
          handler -> {
            C command =
                parseWithRequiredArgs(handler, "--map-diagnostics:a.b.C", "error", "warning");
            command.getReporter().error(new TestDiagnostic());
            try {
              command.getReporter().failIfPendingErrors();
            } catch (RuntimeException e) {
              throw InternalCompilationFailedExceptionUtils.createForTesting();
            }
          });
      fail("Failure expected");
    } catch (CompilationFailedException e) {
      // Expected.
    }

    DiagnosticsChecker.checkWarningsContains(
        "Test diagnostic",
        handler -> {
          C command =
              parseWithRequiredArgs(
                  handler,
                  "--map-diagnostics:com.android.tools.r8.TestDiagnostic",
                  "error",
                  "warning");
          command.getReporter().error(new TestDiagnostic());
        });

    DiagnosticsChecker.checkWarningsContains(
        "Test diagnostic",
        handler -> {
          C command =
              parseWithRequiredArgs(
                  handler, "--map-diagnostics:TestDiagnostic", "error", "warning");
          command.getReporter().error(new TestDiagnostic());
        });
  }

  @Test
  public void errorsToInfo() throws Exception {
    DiagnosticsChecker.checkInfosContains(
        "Error",
        handler -> {
          C command = parseWithRequiredArgs(handler, "--map-diagnostics", "error", "info");
          command.getReporter().error("Error");
        });

    try {
      DiagnosticsChecker.checkErrorsContains(
          "Test diagnostic",
          handler -> {
            C command = parseWithRequiredArgs(handler, "--map-diagnostics:a.b.C", "error", "info");
            command.getReporter().error(new TestDiagnostic());
            try {
              command.getReporter().failIfPendingErrors();
            } catch (RuntimeException e) {
              throw InternalCompilationFailedExceptionUtils.createForTesting();
            }
          });
      fail("Failure expected");
    } catch (CompilationFailedException e) {
      // Expected.
    }

    DiagnosticsChecker.checkInfosContains(
        "Test diagnostic",
        handler -> {
          C command =
              parseWithRequiredArgs(handler, "--map-diagnostics:TestDiagnostic", "error", "info");
          command.getReporter().error(new TestDiagnostic());
        });
  }

  @Test
  public void warningsToInfo() throws Exception {
    DiagnosticsChecker.checkInfosContains(
        "Warning",
        handler -> {
          C command = parseWithRequiredArgs(handler, "--map-diagnostics", "warning", "info");
          command.getReporter().warning("Warning");
        });

    DiagnosticsChecker.checkInfosContains(
        "Test diagnostic",
        handler -> {
          C command =
              parseWithRequiredArgs(handler, "--map-diagnostics:TestDiagnostic", "warning", "info");
          command.getReporter().warning(new TestDiagnostic());
        });
  }

  @Test
  public void warningsToError() {
    try {
      DiagnosticsChecker.checkErrorsContains(
          "Warning",
          handler -> {
            C command = parseWithRequiredArgs(handler, "--map-diagnostics", "warning", "error");
            command.getReporter().warning("Warning");
            try {
              command.getReporter().failIfPendingErrors();
            } catch (RuntimeException e) {
              throw InternalCompilationFailedExceptionUtils.createForTesting();
            }
          });
      fail("Expected failure");
    } catch (CompilationFailedException e) {
      // Expected.
    }

    try {
      DiagnosticsChecker.checkErrorsContains(
          "Test diagnostic",
          handler -> {
            C command =
                parseWithRequiredArgs(
                    handler, "--map-diagnostics:TestDiagnostic", "warning", "error");
            command.getReporter().warning(new TestDiagnostic());
            try {
              command.getReporter().failIfPendingErrors();
            } catch (RuntimeException e) {
              throw InternalCompilationFailedExceptionUtils.createForTesting();
            }
          });
      fail("Expected failure");
    } catch (CompilationFailedException e) {
      // Expected.
    }
  }

  @Test
  public void errorsToWarningsWarningsToInfos() throws Exception {
    DiagnosticsChecker.checkInfosContains(
        "Error",
        handler -> {
          C command =
              parseWithRequiredArgs(
                  handler,
                  "--map-diagnostics",
                  "error",
                  "warning",
                  "--map-diagnostics",
                  "warning",
                  "info");
          command.getReporter().error("Error");
        });

    DiagnosticsChecker.checkInfosContains(
        "Test diagnostic",
        handler -> {
          C command =
              parseWithRequiredArgs(
                  handler,
                  "--map-diagnostics:TestDiagnostic",
                  "error",
                  "warning",
                  "--map-diagnostics",
                  "warning",
                  "info");
          command.getReporter().error(new TestDiagnostic());
        });
  }

  @Test
  public void warningsToInfosErrorsToWarnings() throws Exception {
    DiagnosticsChecker.checkDiagnostics(
        diagnostics -> {
          assertEquals(0, diagnostics.errors.size());
          diagnostics.checkWarningsContains("Error");
          diagnostics.checkInfosContains("Warning");
        },
        handler -> {
          C command =
              parseWithRequiredArgs(
                  handler,
                  "--map-diagnostics",
                  "warning",
                  "info",
                  "--map-diagnostics",
                  "error",
                  "warning");
          command.getReporter().error("Error");
          command.getReporter().warning("Warning");
        });

    DiagnosticsChecker.checkDiagnostics(
        diagnostics -> {
          assertEquals(0, diagnostics.errors.size());
          diagnostics.checkWarningsContains("Test diagnostic");
          diagnostics.checkInfosContains("Test diagnostic");
        },
        handler -> {
          C command =
              parseWithRequiredArgs(
                  handler,
                  "--map-diagnostics:TestDiagnostic",
                  "warning",
                  "info",
                  "--map-diagnostics:TestDiagnostic",
                  "error",
                  "warning");
          command.getReporter().error(new TestDiagnostic());
          command.getReporter().warning(new TestDiagnostic());
        });
  }

  @Test
  public void artProfileFlagAbsentTest() throws Exception {
    assertTrue(parseWithRequiredArgs().getArtProfilesForRewriting().isEmpty());
  }

  @Test
  public void artProfileFlagPresentTest() throws Exception {
    // Create a simple profile.
    Path profile = temp.newFile("profile.txt").toPath();
    Path residualProfile = temp.newFile("profile-out.txt").toPath();
    String profileRuleFlags = "HSP";
    String profileRuleDescriptor = "Lfoo/bar/Baz;->qux()V";
    FileUtils.writeTextFile(profile, profileRuleFlags + profileRuleDescriptor);

    // Pass the profile on the command line.
    List<String> args =
        new ArrayList<>(
            ImmutableList.of("--art-profile", profile.toString(), residualProfile.toString()));
    // L8 only accepts an art profile when shrinking.
    if (this instanceof L8CommandTest) {
      Path path = temp.newFile("proguard-rules.pro").toPath();
      FileUtils.writeTextFile(path, "-dontshrink");
      args.addAll(ImmutableList.of("--pg-conf", path.toString()));
    }
    List<ArtProfileForRewriting> artProfilesForRewriting =
        parseWithRequiredArgs(args.toArray(new String[0])).getArtProfilesForRewriting();
    assertEquals(1, artProfilesForRewriting.size());

    // Extract inputs.
    ArtProfileForRewriting artProfileForRewriting = artProfilesForRewriting.get(0);
    ArtProfileProvider artProfileProvider = artProfileForRewriting.getArtProfileProvider();
    ArtProfileConsumer residualArtProfileConsumer =
        artProfileForRewriting.getResidualArtProfileConsumer();
    InternalOptions options = new InternalOptions();

    // Build provided ART profile.
    ArtProfile.Builder artProfileBuilder =
        ArtProfile.builderForInitialArtProfile(artProfileProvider, options);
    artProfileProvider.getArtProfile(artProfileBuilder);
    ArtProfile artProfile = artProfileBuilder.build();

    // Verify we found the same rule.
    assertEquals(1, artProfile.size());
    IntBox count = new IntBox();
    artProfile.forEachRule(
        classRule -> fail(),
        methodRule -> {
          assertEquals(profileRuleDescriptor, methodRule.getMethod().toSmaliString());
          assertTrue(methodRule.getMethodRuleInfo().isHot());
          assertTrue(methodRule.getMethodRuleInfo().isStartup());
          assertTrue(methodRule.getMethodRuleInfo().isPostStartup());
          count.increment();
        });
    assertEquals(1, count.get());

    // Supply the rule back to the consumer.
    artProfile.supplyConsumer(residualArtProfileConsumer, options.reporter);
    assertEquals(
        ImmutableList.of(profileRuleFlags + profileRuleDescriptor),
        FileUtils.readAllLines(residualProfile));
  }

  @Test
  public void artProfileFlagMissingInputOutputParameterTest() {
    // TODO(jonathanlist): Make this more precise once all CLI uses CliParser.
    String expectedErrorContains = "for --art-profile";
    try {
      DiagnosticsChecker.checkErrorsContains(
          expectedErrorContains, handler -> parseWithRequiredArgs(handler, "--art-profile"));
      fail("Expected failure");
    } catch (CompilationFailedException e) {
      // Expected.
    }
  }

  @Test
  public void artProfileFlagMissingOutputParameterTest() throws Exception {
    // TODO(jonathanlist): Make this more precise once all CLI uses CliParser.
    String expectedErrorContains = "for --art-profile";
    Path profile = temp.newFile("profile.txt").toPath();
    FileUtils.writeTextFile(profile, "");
    try {
      DiagnosticsChecker.checkErrorsContains(
          expectedErrorContains,
          handler -> parseWithRequiredArgs(handler, "--art-profile", profile.toString()));
      fail("Expected failure");
    } catch (CompilationFailedException e) {
      // Expected.
    }
  }

  @Test
  public void startupProfileFlagAbsentTest() throws Exception {
    assertTrue(parseWithRequiredArgs().getStartupProfileProviders().isEmpty());
  }

  @Test
  public void startupProfileFlagPresentTest() throws Exception {
    // Create a simple profile.
    Path profile = temp.newFile("profile.txt").toPath();
    String profileRule = "Lfoo/bar/Baz;->qux()V";
    FileUtils.writeTextFile(profile, profileRule);

    // Pass the profile on the command line.
    List<StartupProfileProvider> startupProfileProviders;
    try {
      startupProfileProviders =
          parseWithRequiredArgs(
                  "--min-api",
                  Integer.toString(AndroidApiLevel.L.getMajor()),
                  "--startup-profile",
                  profile.toString())
              .getStartupProfileProviders();
    } catch (CompilationFailedException e) {
      assertTrue(isL8());
      return;
    }

    assertEquals(1, startupProfileProviders.size());

    // Construct the internal profile representation using the provider.
    InternalOptions options = new InternalOptions();
    MissingStartupProfileItemsDiagnostic.Builder missingStartupProfileItemsDiagnosticBuilder =
        MissingStartupProfileItemsDiagnostic.Builder.nop();
    StartupProfileProvider startupProfileProvider = startupProfileProviders.get(0);
    StartupProfile.Builder startupProfileBuilder =
        StartupProfile.builder(
            options, missingStartupProfileItemsDiagnosticBuilder, startupProfileProvider);
    startupProfileProvider.getStartupProfile(startupProfileBuilder);

    // Verify we found the same rule.
    StartupProfile startupProfile = startupProfileBuilder.build();
    Collection<StartupProfileRule> startupItems =
        ListUtils.newArrayList(consumer -> startupProfile.forEachRule(consumer::accept));
    assertEquals(1, startupItems.size());
    StartupProfileRule startupItem = startupItems.iterator().next();
    startupItem.accept(
        startupClass -> fail(),
        startupMethod -> assertEquals(profileRule, startupMethod.getReference().toSmaliString()));
  }

  @Test
  public void startupProfileFlagMissingParameterTest() {
    // TODO(jonathanlist): Make this more precise once all CLI uses CliParser.
    String expectedErrorContains =
        isL8() ? "Unknown option: --startup-profile" : "for --startup-profile.";
    try {
      DiagnosticsChecker.checkErrorsContains(
          expectedErrorContains, handler -> parseWithRequiredArgs(handler, "--startup-profile"));
      fail("Expected failure");
    } catch (CompilationFailedException e) {
      // Expected.
    }
  }

  private String[] prepareArgs(String[] args) {
    String[] actualTestArgs;
    String[] additionalTestArgs = requiredArgsForTest();
    if (additionalTestArgs.length > 0) {
      actualTestArgs = new String[args.length + additionalTestArgs.length];
      System.arraycopy(additionalTestArgs, 0, actualTestArgs, 0, additionalTestArgs.length);
      System.arraycopy(args, 0, actualTestArgs, additionalTestArgs.length, args.length);
    } else {
      actualTestArgs = args;
    }
    return actualTestArgs;
  }

  private C parseWithRequiredArgs(String... args) throws CompilationFailedException {
    return parse(prepareArgs(args));
  }

  private C parseWithRequiredArgs(DiagnosticsHandler handler, String... args)
      throws CompilationFailedException {
    return parse(handler, prepareArgs(args));
  }

  protected InternalOptions getOptionsWithLoadedDesugaredLibraryConfiguration(
      C command, boolean libraryCompilation) throws IOException {
    InternalOptions options = command.getInternalOptions();
    LibraryDesugaringSpecification spec = LibraryDesugaringSpecification.JDK11;
    options
        .getLibraryDesugaringOptions()
        .loadMachineDesugaredLibrarySpecification(
            Timing.empty(), spec.getAppForTesting(options, libraryCompilation));
    return options;
  }

  /**
   * Tests in this class are executed for all of D8, R8 and L8. When testing arguments this can add
   * additional required arguments to all tests
   */
  abstract String[] requiredArgsForTest();

  abstract C parse(String... args) throws CompilationFailedException;

  abstract C parse(DiagnosticsHandler handler, String... args) throws CompilationFailedException;
}
