// Copyright (c) 2018, 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.maindexlist.b72312389;

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

import com.android.tools.r8.BaseCommand;
import com.android.tools.r8.CompatProguardCommandBuilder;
import com.android.tools.r8.DexIndexedConsumer;
import com.android.tools.r8.Diagnostic;
import com.android.tools.r8.DiagnosticsHandler;
import com.android.tools.r8.GenerateMainDexList;
import com.android.tools.r8.GenerateMainDexListCommand;
import com.android.tools.r8.R8Command;
import com.android.tools.r8.TestBase;
import com.android.tools.r8.ToolHelper;
import com.android.tools.r8.ToolHelper.DexVm;
import com.android.tools.r8.VmTestRunner;
import com.android.tools.r8.origin.Origin;
import com.android.tools.r8.utils.AndroidApiLevel;
import com.android.tools.r8.utils.Box;
import com.android.tools.r8.utils.codeinspector.CodeInspector;
import com.google.common.collect.ImmutableList;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;
import org.junit.Test;
import org.junit.runner.RunWith;

@RunWith(VmTestRunner.class)
public class B72312389 extends TestBase {
  // TODO(120884788): Remove this when default is true.
  private static boolean lookupLibraryBeforeProgram = false;

  // Build a app with a class extending InstrumentationTestCase and including both the junit
  // and the Android library.
  private void buildInstrumentationTestCaseApplication(BaseCommand.Builder builder) {
    builder
        .addLibraryFiles(ToolHelper.getAndroidJar(AndroidApiLevel.O))
        .addProgramFiles(
            Paths.get("build", "test", "examplesAndroidApi",
                "classes", "instrumentationtest", "InstrumentationTest.class"))
        .addProgramFiles(ToolHelper.getFrameworkJunitJarPath(DexVm.ART_7_0_0_HOST));
  }

  private List<String> keepInstrumentationTestCaseRules = ImmutableList.of(
      "-keep class instrumentationtest.InstrumentationTest {",
      "  *;",
      "}");

  @Test
  public void testGenerateMainDexList() throws Exception {
    CollectingDiagnosticHandler diagnostics = new CollectingDiagnosticHandler();
    GenerateMainDexListCommand.Builder builder = GenerateMainDexListCommand.builder(diagnostics);
    buildInstrumentationTestCaseApplication(builder);
    GenerateMainDexListCommand command = builder
        .addMainDexRules(keepInstrumentationTestCaseRules, Origin.unknown())
        .build();
    List<String> mainDexList = GenerateMainDexList.run(command);
    if (lookupLibraryBeforeProgram) {
      assertFalse(mainDexList.contains("junit/framework/TestCase.class"));
    } else {
      assertTrue(mainDexList.contains("junit/framework/TestCase.class"));
    }
    diagnostics.assertEmpty();
  }

  @Test
  public void testR8ForceProguardCompatibility() throws Exception {
    Box<String> mainDexList = new Box<>();
    // Build a app with a class extending InstrumentationTestCase and including both the junit
    // and the Android library.
    CollectingDiagnosticHandler diagnostics = new CollectingDiagnosticHandler();
    R8Command.Builder builder = new CompatProguardCommandBuilder(true, diagnostics);
    buildInstrumentationTestCaseApplication(builder);
    R8Command command =
        builder
            .setMinApiLevel(AndroidApiLevel.K.getLevel())
            // TODO(72793900): This should not be required.
            .addProguardConfiguration(ImmutableList.of("-keep class ** { *; }"), Origin.unknown())
            .addProguardConfiguration(ImmutableList.of("-dontobfuscate"), Origin.unknown())
            .addMainDexRules(keepInstrumentationTestCaseRules, Origin.unknown())
            .setProgramConsumer(DexIndexedConsumer.emptyConsumer())
            .setMainDexListConsumer(ToolHelper.consumeString(mainDexList::set))
            .build();
    CodeInspector inspector = new CodeInspector(ToolHelper.runR8(command));
    assertTrue(inspector.clazz("instrumentationtest.InstrumentationTest").isPresent());
    assertEquals(
        !lookupLibraryBeforeProgram, mainDexList.get().contains("junit/framework/TestCase.class"));
    assertEquals(
        lookupLibraryBeforeProgram ? 0 : 1,
        diagnostics.countLibraryClassExtendsProgramClassWarnings(
            "android.test.InstrumentationTestCase", "junit.framework.TestCase"));
  }

  @Test
  public void testR8() throws Exception {
    testForR8(Backend.DEX)
        .apply(b -> buildInstrumentationTestCaseApplication(b.getBuilder()))
        .setMinApi(AndroidApiLevel.B)
        .addMainDexRules(keepInstrumentationTestCaseRules)
        .compile()
        // Library types and method overrides are lazily enqueued, thus no longer causing failures.
        .assertNoMessages();
  }

  private static class CollectingDiagnosticHandler implements DiagnosticsHandler {
    private final List<Diagnostic> infos = new ArrayList<>();
    private final List<Diagnostic> warnings = new ArrayList<>();
    private final List<Diagnostic> errors = new ArrayList<>();

    @Override
    public void info(Diagnostic info) {
      infos.add(info);
    }

    @Override
    public void warning(Diagnostic warning) {
      warnings.add(warning);
    }

    @Override
    public void error(Diagnostic error) {
      errors.add(error);
    }

    public void assertEmpty() {
      assertEquals(0, errors.size());
      assertEquals(0, warnings.size());
      assertEquals(0, infos.size());
    }

    private boolean isLibraryClassExtendsProgramClassWarning(
        String libraryClass, String programClass, Diagnostic diagnostic) {
      return diagnostic.getDiagnosticMessage().equals(
          "Library class "+ libraryClass + " extends program class " + programClass);
    }

    public long countLibraryClassExtendsProgramClassWarnings(
        String libraryClass, String programClass) {
      return warnings.stream()
          .filter(
              diagnostics ->
                  isLibraryClassExtendsProgramClassWarning(libraryClass, programClass, diagnostics))
          .count();
    }
  }
}
