Add test for generic signatures that should be pruned in fullmode
Bug: 184927364
Change-Id: Ic051d4d851e6501745455f9390a21051680f3bc2
diff --git a/src/test/java/com/android/tools/r8/graph/genericsignature/GenericSignatureKeepReferencesPruneTest.java b/src/test/java/com/android/tools/r8/graph/genericsignature/GenericSignatureKeepReferencesPruneTest.java
new file mode 100644
index 0000000..1c3ddbb
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/graph/genericsignature/GenericSignatureKeepReferencesPruneTest.java
@@ -0,0 +1,112 @@
+// Copyright (c) 2021, 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.graph.genericsignature;
+
+import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assume.assumeTrue;
+
+import com.android.tools.r8.TestBase;
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.graph.genericsignature.testclasses.Foo;
+import com.android.tools.r8.graph.genericsignature.testclasses.I;
+import com.android.tools.r8.graph.genericsignature.testclasses.J;
+import com.android.tools.r8.graph.genericsignature.testclasses.K;
+import com.android.tools.r8.graph.genericsignature.testclasses.L;
+import com.android.tools.r8.graph.genericsignature.testclasses.Main;
+import com.android.tools.r8.utils.BooleanUtils;
+import com.android.tools.r8.utils.codeinspector.ClassSubject;
+import com.android.tools.r8.utils.codeinspector.CodeInspector;
+import java.util.List;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameters;
+
+@RunWith(Parameterized.class)
+public class GenericSignatureKeepReferencesPruneTest extends TestBase {
+
+ private final String[] EXPECTED =
+ new String[] {
+ Foo.class.getTypeName() + "<java.lang.String>",
+ I.class.getTypeName()
+ + "<java.lang.Integer, "
+ + Foo.class.getTypeName()
+ + "<java.lang.Integer>>",
+ I.class.getTypeName()
+ + "<java.lang.String, "
+ + Foo.class.getTypeName()
+ + "<java.lang.String>>",
+ "Hello world"
+ };
+
+ private final TestParameters parameters;
+ private final boolean isCompat;
+
+ @Parameters(name = "{0}, isCompat: {1}")
+ public static List<Object[]> data() {
+ return buildParameters(
+ getTestParameters().withAllRuntimesAndApiLevels().build(), BooleanUtils.values());
+ }
+
+ public GenericSignatureKeepReferencesPruneTest(TestParameters parameters, boolean isCompat) {
+ this.parameters = parameters;
+ this.isCompat = isCompat;
+ }
+
+ @Test
+ public void testJvm() throws Exception {
+ assumeTrue(parameters.isCfRuntime());
+ testForJvm()
+ .addProgramClasses(I.class, Foo.class, J.class, K.class, L.class)
+ .addProgramClassesAndInnerClasses(Main.class)
+ .run(parameters.getRuntime(), Main.class)
+ .assertSuccessWithOutputLines(EXPECTED);
+ }
+
+ @Test
+ public void testR8() throws Exception {
+ (isCompat ? testForR8Compat(parameters.getBackend()) : testForR8(parameters.getBackend()))
+ .addProgramClasses(I.class, Foo.class, J.class, K.class, L.class)
+ .addProgramClassesAndInnerClasses(Main.class)
+ .addKeepClassAndMembersRules(Main.class)
+ .setMinApi(parameters.getApiLevel())
+ .addKeepAttributeSignature()
+ .addKeepAttributeInnerClassesAndEnclosingMethod()
+ .enableInliningAnnotations()
+ .enableNeverClassInliningAnnotations()
+ .noMinification()
+ .run(parameters.getRuntime(), Main.class)
+ // TODO(b/184927364): Should have different output due to pruning the inner class.
+ .assertSuccessWithOutputLines(EXPECTED)
+ .inspect(this::inspectSignatures);
+ }
+
+ private void inspectSignatures(CodeInspector inspector) {
+ ClassSubject fooClass = inspector.clazz(Foo.class);
+ assertThat(fooClass, isPresent());
+ // TODO(b/184927364): Fullmode should not keep the interface bound.
+ assertEquals(
+ "<T::Ljava/lang/Comparable<TT;>;>Ljava/lang/Object;",
+ fooClass.getFinalSignatureAttribute());
+ ClassSubject iClass = inspector.clazz(I.class);
+ assertThat(iClass, isPresent());
+ // TODO(b/184927364): Fullmode should not keep the interface and class bound.
+ assertEquals(
+ "<T::Ljava/lang/Comparable<TT;>;R:L" + binaryName(Foo.class) + "<TT;>;>Ljava/lang/Object;",
+ iClass.getFinalSignatureAttribute());
+ ClassSubject fooInnerClass = inspector.clazz(Main.class.getTypeName() + "$1");
+ assertThat(fooInnerClass, isPresent());
+ // TODO(b/184927364): Fullmode should completely remove this signature
+ assertEquals(
+ "Ljava/lang/Object;L"
+ + binaryName(I.class)
+ + "<Ljava/lang/String;L"
+ + binaryName(Foo.class)
+ + "<Ljava/lang/String;>;>;",
+ fooInnerClass.getFinalSignatureAttribute());
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/graph/genericsignature/testclasses/Foo.java b/src/test/java/com/android/tools/r8/graph/genericsignature/testclasses/Foo.java
new file mode 100644
index 0000000..81000d6
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/graph/genericsignature/testclasses/Foo.java
@@ -0,0 +1,19 @@
+// Copyright (c) 2021, 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.graph.genericsignature.testclasses;
+
+import com.android.tools.r8.NeverClassInline;
+import com.android.tools.r8.NeverInline;
+
+@NeverClassInline
+public class Foo<T extends Comparable<T>> implements J, K<T> {
+
+ @Override
+ @NeverInline
+ public String bar(String t) {
+ System.out.println("Foo::bar");
+ return t;
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/graph/genericsignature/testclasses/I.java b/src/test/java/com/android/tools/r8/graph/genericsignature/testclasses/I.java
new file mode 100644
index 0000000..089286d
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/graph/genericsignature/testclasses/I.java
@@ -0,0 +1,12 @@
+// Copyright (c) 2021, 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.graph.genericsignature.testclasses;
+
+import com.android.tools.r8.NeverInline;
+
+public interface I<T extends Comparable<T>, R extends Foo<T>> extends L<R> {
+ @NeverInline
+ T method(T t);
+}
diff --git a/src/test/java/com/android/tools/r8/graph/genericsignature/testclasses/J.java b/src/test/java/com/android/tools/r8/graph/genericsignature/testclasses/J.java
new file mode 100644
index 0000000..8deed10
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/graph/genericsignature/testclasses/J.java
@@ -0,0 +1,10 @@
+// Copyright (c) 2021, 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.graph.genericsignature.testclasses;
+
+public interface J {
+
+ String bar(String t);
+}
diff --git a/src/test/java/com/android/tools/r8/graph/genericsignature/testclasses/K.java b/src/test/java/com/android/tools/r8/graph/genericsignature/testclasses/K.java
new file mode 100644
index 0000000..608c12d
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/graph/genericsignature/testclasses/K.java
@@ -0,0 +1,7 @@
+// Copyright (c) 2021, 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.graph.genericsignature.testclasses;
+
+public interface K<T> {}
diff --git a/src/test/java/com/android/tools/r8/graph/genericsignature/testclasses/L.java b/src/test/java/com/android/tools/r8/graph/genericsignature/testclasses/L.java
new file mode 100644
index 0000000..bf3895b
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/graph/genericsignature/testclasses/L.java
@@ -0,0 +1,7 @@
+// Copyright (c) 2021, 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.graph.genericsignature.testclasses;
+
+public interface L<T> {}
diff --git a/src/test/java/com/android/tools/r8/graph/genericsignature/testclasses/Main.java b/src/test/java/com/android/tools/r8/graph/genericsignature/testclasses/Main.java
new file mode 100644
index 0000000..ccf9f04
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/graph/genericsignature/testclasses/Main.java
@@ -0,0 +1,39 @@
+// Copyright (c) 2021, 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.graph.genericsignature.testclasses;
+
+import java.lang.reflect.Type;
+
+public class Main extends Foo<String> implements I<Integer, Foo<Integer>> {
+
+ public static <T extends I<String, Foo<String>>> T test(T t) {
+ for (Type genericInterface : t.getClass().getGenericInterfaces()) {
+ System.out.println(genericInterface);
+ }
+ t.method("Hello world");
+ return t;
+ }
+
+ public static void main(String[] args) {
+ System.out.println(Main.class.getGenericSuperclass());
+ for (Type genericInterface : Main.class.getGenericInterfaces()) {
+ System.out.println(genericInterface);
+ }
+ test(
+ new I<String, Foo<String>>() {
+ @Override
+ public String method(String s) {
+ System.out.println(s);
+ return s;
+ }
+ });
+ }
+
+ @Override
+ public Integer method(Integer integer) {
+ System.out.println("Main::method");
+ return integer;
+ }
+}