Add test case for disjunction in extends clause of keep rule
Bug: 128503974
Change-Id: I89d7d67431da2b17d3dc80de62849ca44734504d
diff --git a/src/test/java/com/android/tools/r8/proguard/configuration/InheritanceClauseWithDisjunctionTest.java b/src/test/java/com/android/tools/r8/proguard/configuration/InheritanceClauseWithDisjunctionTest.java
new file mode 100644
index 0000000..6a26c3b
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/proguard/configuration/InheritanceClauseWithDisjunctionTest.java
@@ -0,0 +1,275 @@
+// 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 {}