// Copyright (c) 2019, 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.proguard.configuration;

import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
import static org.hamcrest.CoreMatchers.containsString;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.fail;

import com.android.tools.r8.CompilationFailedException;
import com.android.tools.r8.TestBase;
import com.android.tools.r8.TestShrinkerBuilder;
import com.android.tools.r8.utils.codeinspector.CodeInspector;
import com.google.common.collect.ImmutableList;
import java.util.List;
import java.util.function.Consumer;
import org.junit.Ignore;
import org.junit.Test;

public class InheritanceClauseWithDisjunctionTest extends TestBase {

  @Ignore("b/128503974")
  @Test
  public void testExtendsClauseWithR8() throws Exception {
    runTest(
        testForR8(Backend.DEX),
        getKeepRulesForExtendsClauseTests(),
        InheritanceClauseWithDisjunctionTest::inspectExtendsClauseTests);
  }

  @Test
  public void testExtendsClauseWithProguard() throws Exception {
    runTest(
        testForProguard(),
        getKeepRulesForExtendsClauseTests(),
        InheritanceClauseWithDisjunctionTest::inspectExtendsClauseTests);
  }

  private static List<String> getKeepRulesForExtendsClauseTests() {
    return ImmutableList.of(
        "-keep class * extends "
            + InheritanceClauseWithDisjunctionTestClassA.class.getTypeName()
            + ", "
            + InheritanceClauseWithDisjunctionTestClassB.class.getTypeName()
            + ", "
            + InheritanceClauseWithDisjunctionTestClassC.class.getTypeName());
  }

  private static void inspectExtendsClauseTests(CodeInspector inspector) {
    // ASub extends A and BSub extends B. A and B are kept because Proguard presumably does not
    // merge them into ASub and BSub, respectively.
    assertEquals(4, inspector.allClasses().size());
    assertThat(inspector.clazz(InheritanceClauseWithDisjunctionTestClassA.class), isPresent());
    assertThat(inspector.clazz(InheritanceClauseWithDisjunctionTestClassASub.class), isPresent());
    assertThat(inspector.clazz(InheritanceClauseWithDisjunctionTestClassB.class), isPresent());
    assertThat(inspector.clazz(InheritanceClauseWithDisjunctionTestClassBSub.class), isPresent());
  }

  @Ignore("b/128503974")
  @Test
  public void testExtendsClauseWithNegation1WithR8() throws Exception {
    runTest(
        testForR8(Backend.DEX),
        getKeepRulesForExtendsClauseWithNegation1Tests(),
        InheritanceClauseWithDisjunctionTest::inspectExtendsClauseWithNegation1Tests);
  }

  @Test
  public void testExtendsClauseWithNegation1WithProguard() throws Exception {
    runTest(
        testForProguard(),
        getKeepRulesForExtendsClauseWithNegation1Tests(),
        InheritanceClauseWithDisjunctionTest::inspectExtendsClauseWithNegation1Tests);
  }

  private static List<String> getKeepRulesForExtendsClauseWithNegation1Tests() {
    return ImmutableList.of(
        "-keep class * extends "
            + InheritanceClauseWithDisjunctionTestClassA.class.getTypeName()
            + ", !"
            + InheritanceClauseWithDisjunctionTestClassB.class.getTypeName());
  }

  private static void inspectExtendsClauseWithNegation1Tests(CodeInspector inspector) {
    // Strangely, BSub is kept, although it does not extend A and it extends B.
    assertEquals(11, inspector.allClasses().size());
  }

  @Ignore("b/128503974")
  @Test
  public void testExtendsClauseWithNegation2WithR8() throws Exception {
    runTest(
        testForR8(Backend.DEX),
        getKeepRulesForExtendsClauseWithNegation2Tests(),
        InheritanceClauseWithDisjunctionTest::inspectExtendsClauseWithNegation2Tests);
  }

  @Test
  public void testExtendsClauseWithNegation2WithProguard() throws Exception {
    runTest(
        testForProguard(),
        getKeepRulesForExtendsClauseWithNegation2Tests(),
        InheritanceClauseWithDisjunctionTest::inspectExtendsClauseWithNegation2Tests);
  }

  private static List<String> getKeepRulesForExtendsClauseWithNegation2Tests() {
    return ImmutableList.of(
        "-keep class * extends !"
            + InheritanceClauseWithDisjunctionTestClassB.class.getTypeName()
            + ", "
            + InheritanceClauseWithDisjunctionTestClassA.class.getTypeName());
  }

  private static void inspectExtendsClauseWithNegation2Tests(CodeInspector inspector) {
    // Strangely, all the types that do not extend A have not kept.
    assertEquals(2, inspector.allClasses().size());
    assertThat(inspector.clazz(InheritanceClauseWithDisjunctionTestClassA.class), isPresent());
    assertThat(inspector.clazz(InheritanceClauseWithDisjunctionTestClassASub.class), isPresent());
  }

  @Ignore("b/128503974")
  @Test
  public void testExtendsClauseWithMatchAllNegationWithR8() throws Exception {
    runTest(
        testForR8(Backend.DEX),
        getKeepRulesForExtendsClauseWithMatchAllNegationTests(),
        InheritanceClauseWithDisjunctionTest::inspectExtendsClauseWithMatchAllNegationTests);
  }

  @Test
  public void testExtendsClauseWithMatchAllNegationWithProguard() throws Exception {
    runTest(
        testForProguard(),
        getKeepRulesForExtendsClauseWithMatchAllNegationTests(),
        InheritanceClauseWithDisjunctionTest::inspectExtendsClauseWithMatchAllNegationTests);
  }

  private static List<String> getKeepRulesForExtendsClauseWithMatchAllNegationTests() {
    return ImmutableList.of(
        "-keep class * extends "
            + InheritanceClauseWithDisjunctionTestClassA.class.getTypeName()
            + ", !"
            + InheritanceClauseWithDisjunctionTestClassA.class.getTypeName());
  }

  private static void inspectExtendsClauseWithMatchAllNegationTests(CodeInspector inspector) {
    // Every type extends A or does not extend A.
    assertEquals(11, inspector.allClasses().size());
  }

  @Ignore("b/128503974")
  @Test
  public void testImplementsClauseWithR8() throws Exception {
    runTest(
        testForR8(Backend.DEX),
        getKeepRulesForImplementsClauseTests(),
        InheritanceClauseWithDisjunctionTest::inspectImplementsClauseTests);
  }

  @Test
  public void testImplementsClauseWithProguard() throws Exception {
    try {
      runTest(
          testForProguard(),
          getKeepRulesForImplementsClauseTests(),
          InheritanceClauseWithDisjunctionTest::inspectImplementsClauseTests);
      fail();
    } catch (CompilationFailedException e) {
      // Strangely, nothing matches implements I or J (not even InheritanceClauseWithDisjunction-
      // TestClassIJSub, which implements both I and J!).
      assertThat(e.getMessage(), containsString("The output jar is empty"));
    }
  }

  private static List<String> getKeepRulesForImplementsClauseTests() {
    return ImmutableList.of(
        "-keep class * implements "
            + InheritanceClauseWithDisjunctionTestInterfaceI.class.getTypeName()
            + ", "
            + InheritanceClauseWithDisjunctionTestInterfaceJ.class.getTypeName()
            + ", "
            + InheritanceClauseWithDisjunctionTestInterfaceK.class.getTypeName());
  }

  private static void inspectImplementsClauseTests(CodeInspector inspector) {
    // Strangely, nothing matches implements I or J (not even InheritanceClauseWithDisjunctionTest-
    // ClassIJSub, which implements both I and J!).
    assertEquals(0, inspector.allClasses().size());
  }

  @Ignore("b/128503974")
  @Test
  public void testImplementsClauseWithNegationWithR8() throws Exception {
    runTest(
        testForR8(Backend.DEX),
        getKeepRulesForImplementsClauseTests(),
        InheritanceClauseWithDisjunctionTest::inspectImplementsClauseWithNegationTests);
  }

  @Test
  public void testImplementsClauseWithNegationWithProguard() throws Exception {
    runTest(
        testForProguard(),
        getKeepRulesForImplementsClauseWithNegationTests(),
        InheritanceClauseWithDisjunctionTest::inspectImplementsClauseWithNegationTests);
  }

  private static List<String> getKeepRulesForImplementsClauseWithNegationTests() {
    return ImmutableList.of(
        "-keep class * implements "
            + InheritanceClauseWithDisjunctionTestInterfaceI.class.getTypeName()
            + ", !"
            + InheritanceClauseWithDisjunctionTestInterfaceI.class.getTypeName());
  }

  private static void inspectImplementsClauseWithNegationTests(CodeInspector inspector) {
    // Every type implements I or does not implement I.
    assertEquals(11, inspector.allClasses().size());
  }

  private static void runTest(
      TestShrinkerBuilder<?, ?, ?, ?, ?> builder,
      List<String> keepRules,
      Consumer<CodeInspector> consumer)
      throws Exception {
    builder
        .addProgramClasses(
            InheritanceClauseWithDisjunctionTestClassA.class,
            InheritanceClauseWithDisjunctionTestClassASub.class,
            InheritanceClauseWithDisjunctionTestClassB.class,
            InheritanceClauseWithDisjunctionTestClassBSub.class,
            InheritanceClauseWithDisjunctionTestClassC.class,
            InheritanceClauseWithDisjunctionTestInterfaceI.class,
            InheritanceClauseWithDisjunctionTestClassISub.class,
            InheritanceClauseWithDisjunctionTestInterfaceJ.class,
            InheritanceClauseWithDisjunctionTestClassJSub.class,
            InheritanceClauseWithDisjunctionTestInterfaceK.class,
            InheritanceClauseWithDisjunctionTestClassIJKSub.class)
        .addKeepRules(keepRules)
        .compile()
        .inspect(consumer);
  }
}

class InheritanceClauseWithDisjunctionTestClassA {}

class InheritanceClauseWithDisjunctionTestClassASub
    extends InheritanceClauseWithDisjunctionTestClassA {}

class InheritanceClauseWithDisjunctionTestClassB {}

class InheritanceClauseWithDisjunctionTestClassBSub
    extends InheritanceClauseWithDisjunctionTestClassB {}

class InheritanceClauseWithDisjunctionTestClassC {}

interface InheritanceClauseWithDisjunctionTestInterfaceI {}

class InheritanceClauseWithDisjunctionTestClassISub
    implements InheritanceClauseWithDisjunctionTestInterfaceI {}

interface InheritanceClauseWithDisjunctionTestInterfaceJ {}

class InheritanceClauseWithDisjunctionTestClassJSub
    implements InheritanceClauseWithDisjunctionTestInterfaceJ {}

interface InheritanceClauseWithDisjunctionTestInterfaceK {}

class InheritanceClauseWithDisjunctionTestClassIJKSub
    implements InheritanceClauseWithDisjunctionTestInterfaceI,
        InheritanceClauseWithDisjunctionTestInterfaceJ,
        InheritanceClauseWithDisjunctionTestInterfaceK {}
