Add tests for unused arrays of built in types
Fixes: b/320454647
Change-Id: I3c2a292ea3e2a0c910416000946f152f9dd2bf5d
diff --git a/src/test/java/com/android/tools/r8/rewrite/arrays/UnusedNewArrayOfApiDependentLibraryTypeTest.java b/src/test/java/com/android/tools/r8/rewrite/arrays/UnusedNewArrayOfApiDependentLibraryTypeTest.java
new file mode 100644
index 0000000..1f49507
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/rewrite/arrays/UnusedNewArrayOfApiDependentLibraryTypeTest.java
@@ -0,0 +1,104 @@
+// Copyright (c) 2024, 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.rewrite.arrays;
+
+import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.junit.Assert.assertEquals;
+
+import com.android.tools.r8.TestBase;
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.TestParametersCollection;
+import com.android.tools.r8.TestRunResult;
+import com.android.tools.r8.ToolHelper.DexVm.Version;
+import com.android.tools.r8.utils.AndroidApiLevel;
+import com.android.tools.r8.utils.codeinspector.CodeInspector;
+import com.android.tools.r8.utils.codeinspector.MethodSubject;
+import java.util.function.Function;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameter;
+import org.junit.runners.Parameterized.Parameters;
+
+@RunWith(Parameterized.class)
+public class UnusedNewArrayOfApiDependentLibraryTypeTest extends TestBase {
+
+ @Parameter(0)
+ public TestParameters parameters;
+
+ @Parameters(name = "{0}")
+ public static TestParametersCollection data() {
+ return getTestParameters().withAllRuntimesAndApiLevels().build();
+ }
+
+ @Test
+ public void testJvm() throws Exception {
+ parameters.assumeCfRuntime();
+ testForJvm(parameters)
+ .addInnerClasses(getClass())
+ .run(parameters.getRuntime(), Main.class)
+ .assertSuccessWithEmptyOutput();
+ }
+
+ @Test
+ public void testD8Release() throws Exception {
+ parameters.assumeDexRuntime();
+ testForD8()
+ .addInnerClasses(getClass())
+ .release()
+ .setMinApi(parameters)
+ .compile()
+ .inspect(this::inspect)
+ .run(parameters.getRuntime(), Main.class)
+ .applyIf(
+ hasFunctionAsRunTime(),
+ TestRunResult::assertSuccessWithEmptyOutput,
+ runResult -> runResult.assertFailureWithErrorThatThrows(NoClassDefFoundError.class));
+ }
+
+ @Test
+ public void testR8() throws Exception {
+ testForR8(parameters.getBackend())
+ .addInnerClasses(getClass())
+ .addKeepMainRule(Main.class)
+ .applyIf(
+ !hasFunctionAtCompileTime(), testBuilder -> testBuilder.addDontWarn(Function.class))
+ .setMinApi(parameters)
+ .compile()
+ .inspect(this::inspect)
+ .run(parameters.getRuntime(), Main.class)
+ .applyIf(
+ hasFunctionAsRunTime(),
+ TestRunResult::assertSuccessWithEmptyOutput,
+ runResult -> runResult.assertFailureWithErrorThatThrows(NoClassDefFoundError.class));
+ }
+
+ private void inspect(CodeInspector inspector) {
+ MethodSubject mainMethodSubject = inspector.clazz(Main.class).mainMethod();
+ assertThat(mainMethodSubject, isPresent());
+ assertEquals(canOptimize(), mainMethodSubject.getMethod().getCode().isEmptyVoidMethod());
+ }
+
+ private boolean canOptimize() {
+ return hasFunctionAtCompileTime() && parameters.isDexRuntime();
+ }
+
+ private boolean hasFunctionAtCompileTime() {
+ return parameters.isCfRuntime()
+ || parameters.getApiLevel().isGreaterThanOrEqualTo(AndroidApiLevel.N);
+ }
+
+ private boolean hasFunctionAsRunTime() {
+ return parameters.isCfRuntime()
+ || parameters.getDexRuntimeVersion().isNewerThanOrEqual(Version.V7_0_0);
+ }
+
+ public static class Main {
+
+ public static void main(String[] args) {
+ Function[] functions = new Function[0];
+ }
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/rewrite/arrays/UnusedNewArrayOfKnownLibraryTypeTest.java b/src/test/java/com/android/tools/r8/rewrite/arrays/UnusedNewArrayOfKnownLibraryTypeTest.java
new file mode 100644
index 0000000..a013ceb
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/rewrite/arrays/UnusedNewArrayOfKnownLibraryTypeTest.java
@@ -0,0 +1,102 @@
+// Copyright (c) 2024, 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.rewrite.arrays;
+
+import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.junit.Assert.assertTrue;
+
+import com.android.tools.r8.TestBase;
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.TestParametersCollection;
+import com.android.tools.r8.utils.codeinspector.CodeInspector;
+import com.android.tools.r8.utils.codeinspector.MethodSubject;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameter;
+import org.junit.runners.Parameterized.Parameters;
+
+@RunWith(Parameterized.class)
+public class UnusedNewArrayOfKnownLibraryTypeTest extends TestBase {
+
+ @Parameter(0)
+ public TestParameters parameters;
+
+ @Parameters(name = "{0}")
+ public static TestParametersCollection data() {
+ return getTestParameters().withAllRuntimesAndApiLevels().build();
+ }
+
+ @Test
+ public void testJvm() throws Exception {
+ parameters.assumeCfRuntime();
+ testForJvm(parameters)
+ .addInnerClasses(getClass())
+ .run(parameters.getRuntime(), Main.class)
+ .assertSuccessWithEmptyOutput();
+ }
+
+ @Test
+ public void testD8Release() throws Exception {
+ parameters.assumeDexRuntime();
+ testForD8()
+ .addInnerClasses(getClass())
+ .release()
+ .setMinApi(parameters)
+ .compile()
+ .inspect(this::inspect)
+ .run(parameters.getRuntime(), Main.class)
+ .assertSuccessWithEmptyOutput();
+ }
+
+ @Test
+ public void testR8() throws Exception {
+ testForR8(parameters.getBackend())
+ .addInnerClasses(getClass())
+ .addKeepMainRule(Main.class)
+ .setMinApi(parameters)
+ .compile()
+ .inspect(this::inspect)
+ .run(parameters.getRuntime(), Main.class)
+ .assertSuccessWithEmptyOutput();
+ }
+
+ private void inspect(CodeInspector inspector) {
+ MethodSubject mainMethodSubject = inspector.clazz(Main.class).mainMethod();
+ assertThat(mainMethodSubject, isPresent());
+ assertTrue(mainMethodSubject.getMethod().getCode().isEmptyVoidMethod());
+ }
+
+ public static class Main {
+
+ public static void main(String[] args) {
+ // Primitives.
+ boolean[] booleans = new boolean[0];
+ byte[] bytes = new byte[0];
+ char[] chars = new char[0];
+ double[] doubles = new double[0];
+ float[] floats = new float[0];
+ int[] ints = new int[0];
+ long[] longs = new long[0];
+ short[] shorts = new short[0];
+
+ // Boxed primitives.
+ Boolean[] boxedBooleans = new Boolean[0];
+ Byte[] boxedBytes = new Byte[0];
+ Character[] boxedChars = new Character[0];
+ Double[] boxedDoubles = new Double[0];
+ Float[] boxedFloats = new Float[0];
+ Integer[] boxedInts = new Integer[0];
+ Long[] boxedLongs = new Long[0];
+ Short[] boxedShorts = new Short[0];
+
+ // Common classes.
+ Enum<?>[] enums = new Enum<?>[0];
+ Object[] objects = new Object[0];
+ String[] strings = new String[0];
+ StringBuilder[] stringBuilders = new StringBuilder[0];
+ }
+ }
+}