// 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.assertTrue;
import static org.junit.Assert.fail;

import com.android.tools.r8.BaseCommand;
import com.android.tools.r8.CompatProguardCommandBuilder;
import com.android.tools.r8.CompilationFailedException;
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.R8;
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.DexInspector;
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 {
  // 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.getLevel()))
        .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);
    assertTrue(mainDexList.contains("junit/framework/TestCase.class"));
    diagnostics.assertEmpty();
  }

  private static class StringBox {
    String content;
  }

  @Test
  public void testR8ForceProguardCompatibility() throws Exception {
    StringBox mainDexList = new StringBox();
    // 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(
            (string, handler) -> mainDexList.content = string)
        .build();
    DexInspector inspector = new DexInspector(ToolHelper.runR8(command));
    assertTrue(inspector.clazz("instrumentationtest.InstrumentationTest").isPresent());
    assertTrue(mainDexList.content.contains("junit/framework/TestCase.class"));
    // TODO(72794301): Two copies of this message is a bit over the top.
    assertEquals(2,
        diagnostics.countLibraryClassExtensdProgramClassWarnings(
            "android.test.InstrumentationTestCase", "junit.framework.TestCase"));
  }

  @Test
  public void testR8() throws Exception {
    CollectingDiagnosticHandler diagnostics = new CollectingDiagnosticHandler();
    R8Command.Builder builder = R8Command.builder(diagnostics);
    buildInstrumentationTestCaseApplication(builder);
    R8Command command = builder
        .addMainDexRules(keepInstrumentationTestCaseRules, Origin.unknown())
        .setProgramConsumer(DexIndexedConsumer.emptyConsumer())
        .build();
    try {
      R8.run(command);
      fail();
    } catch (CompilationFailedException e) {
      // Expected, as library class extending program class is an error for R8.
    }
  }

  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 isLibraryClassExtensdProgramClassWarnings(
        String libraryClass, String programClass, Diagnostic diagnostic) {
      return diagnostic.getDiagnosticMessage().equals(
          "Library class "+ libraryClass + " extends program class " + programClass);
    }

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