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

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.fail;
import static org.junit.Assume.assumeFalse;
import static org.junit.Assume.assumeTrue;

import com.android.tools.r8.CompilationFailedException;
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.jasmin.JasminBuilder;
import com.android.tools.r8.utils.codeinspector.CodeInspector;
import java.util.List;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;

// This test used to test R8 errors/warnings when library class extends program class. Before
// the change fixing b/120884788, that could easily happen as lookup would lookup in program
// classes before library classes, and the Android library included parts of JUnit, which could
// also easily end up as program classes when JUnit was used by a program.
//
// Now that library classes are looked up before program classes these JUnit classes will be
// found in the library and the ones in program will be ignored and not end up in the output.
//
// For a D8 compilation any class passed as input will end up in the output.
@RunWith(Parameterized.class)
public class LibraryClassExtendsProgramClassTest extends TestBase {

  private static List<byte[]> junitClasses;

  @BeforeClass
  public static void setUp() throws Exception {
    JasminBuilder builder = new JasminBuilder();
    builder.addClass("junit.framework.TestCase");
    junitClasses = builder.buildClasses();
  }

  private final TestParameters parameters;

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

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

  private void checkClassesInResult(CodeInspector inspector) {
    if (parameters.isDexRuntime()) {
      noClassesInResult(inspector);
    } else {
      testCaseClassInResult(inspector);
    }
  }

  private void noClassesInResult(CodeInspector inspector) {
    assertEquals(1, inspector.allClasses().size());
    assertThat(inspector.clazz(TestClass.class), isPresent());
  }

  private void testCaseClassInResult(CodeInspector inspector) {
    assertEquals(2, inspector.allClasses().size());
    assertThat(inspector.clazz("junit.framework.TestCase"), isPresent());
    assertThat(inspector.clazz(TestClass.class), isPresent());
  }

  @Test
  public void testFullMode() throws Exception {
    assumeFalse(parameters.getApiLevel().getLevel() == 28);
    testForR8(parameters.getBackend())
        .setMinApi(parameters.getApiLevel())
        .addProgramClasses(TestClass.class)
        .addProgramClassFileData(junitClasses)
        .addKeepAllClassesRule()
        // TODO(120884788): Remove when this is the default.
        .addOptionsModification(options -> options.lookupLibraryBeforeProgram = true)
        .compile()
        .inspect(this::checkClassesInResult)
        .assertNoMessages();
  }

  @Test
  public void testCompatibilityMode() throws Exception {
    assumeFalse(parameters.getApiLevel().getLevel() == 28);
    testForR8Compat(parameters.getBackend())
        .setMinApi(parameters.getApiLevel())
        .addProgramClasses(TestClass.class)
        .addProgramClassFileData(junitClasses)
        .addKeepAllClassesRule()
        // TODO(120884788): Remove when this is the default.
        .addOptionsModification(options -> options.lookupLibraryBeforeProgram = true)
        .compile()
        .inspect(this::checkClassesInResult)
        .assertNoMessages();
  }

  @Test
  public void testD8() throws Exception {
    assumeTrue("Only run D8 for Dex backend", parameters.isDexRuntime());
    testForD8()
        .setMinApi(parameters.getApiLevel())
        .addProgramClasses(TestClass.class)
        .addProgramClassFileData(junitClasses)
        .compile()
        .inspect(this::testCaseClassInResult)
        .assertNoMessages();
  }

  @Test
  public void testFullModeError() {
    assumeFalse(parameters.getApiLevel().getLevel() == 28);
    assumeTrue("Only run for Dex backend", parameters.isDexRuntime());
    try {
      testForR8(parameters.getBackend())
          .setMinApi(parameters.getApiLevel())
          .addProgramClasses(TestClass.class)
          .addProgramClassFileData(junitClasses)
          .addKeepAllClassesRule()
          .addOptionsModification(options -> options.lookupLibraryBeforeProgram = false)
          .compile();
      fail("Succeeded in full mode");
    } catch (CompilationFailedException e) {
      // Ignore.
    }
  }

  @Test
  public void testCompatibilityModeWarning() throws Exception {
    assumeFalse(parameters.getApiLevel().getLevel() == 28);
    assumeTrue("Only run for Dex backend", parameters.isDexRuntime());
    R8TestCompileResult result =
        testForR8Compat(parameters.getBackend())
            .setMinApi(parameters.getApiLevel())
            .addProgramClasses(TestClass.class)
            .addProgramClassFileData(junitClasses)
            .addKeepAllClassesRule()
            .addOptionsModification(options -> options.lookupLibraryBeforeProgram = false)
            .compile()
            .assertOnlyWarnings();

    String[] libraryClassesExtendingTestCase = new String[]{
        "android.test.InstrumentationTestCase",
        "android.test.AndroidTestCase",
        "android.test.suitebuilder.TestSuiteBuilder$FailedToCreateTests"
    };

    result.getDiagnosticMessages().assertWarningsCount(libraryClassesExtendingTestCase.length);

    for (String name : libraryClassesExtendingTestCase) {
      result
          .assertWarningMessageThatMatches(
              containsString(
                  "Library class " + name + " extends program class junit.framework.TestCase"));
    }
  }

  @Test
  public void testWithDontWarn() throws Exception {
    assumeTrue("Only run for Dex backend", parameters.isDexRuntime());
    testForR8(parameters.getBackend())
        .setMinApi(parameters.getApiLevel())
        .addProgramClassFileData(junitClasses)
        .addKeepAllClassesRule()
        .addKeepRules("-dontwarn android.test.**")
        .addOptionsModification(options -> options.lookupLibraryBeforeProgram = false)
        .compile()
        .assertNoMessages();
  }

  static class TestClass {

    public static void main(String[] args) throws Exception {
      // Ensure that the problematic library types are actually live.
      Class.forName("android.test.InstrumentationTestCase").getDeclaredConstructor().newInstance();
      Class.forName("android.test.AndroidTestCase").getDeclaredConstructor().newInstance();
      Class.forName("android.test.suitebuilder.TestSuiteBuilder$FailedToCreateTests")
          .getDeclaredConstructor()
          .newInstance();
    }
  }
}
