Run JDK-11 Test for ConcurrentLinkedQueue
Enable the test without VarHandle desugaring.
It only succeeds on Android 13 which has the required VarHandle and
MethodHandles support and an implementation where the white-box test
can find the expected internal behaviour.
Bug: b/246860430
Bug: b/247076137
Change-Id: I521f42349e14af3000ea1ac063a56297e94b3b06
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/jdktests/Jdk11ConcurrentLinkedQueueTests.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/jdktests/Jdk11ConcurrentLinkedQueueTests.java
new file mode 100644
index 0000000..6a8398c
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/jdktests/Jdk11ConcurrentLinkedQueueTests.java
@@ -0,0 +1,152 @@
+// Copyright (c) 2023, 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.desugar.desugaredlibrary.jdktests;
+
+import static com.android.tools.r8.ToolHelper.JDK_TESTS_BUILD_DIR;
+import static com.android.tools.r8.desugar.desugaredlibrary.jdktests.Jdk11SupportFiles.testNGSupportProgramFiles;
+import static com.android.tools.r8.desugar.desugaredlibrary.test.CompilationSpecification.D8_L8DEBUG;
+import static com.android.tools.r8.desugar.desugaredlibrary.test.CompilationSpecification.D8_L8SHRINK;
+import static com.android.tools.r8.desugar.desugaredlibrary.test.LibraryDesugaringSpecification.JDK11;
+import static com.android.tools.r8.desugar.desugaredlibrary.test.LibraryDesugaringSpecification.JDK11_MINIMAL;
+import static com.android.tools.r8.desugar.desugaredlibrary.test.LibraryDesugaringSpecification.JDK11_PATH;
+import static com.android.tools.r8.utils.FileUtils.CLASS_EXTENSION;
+import static com.android.tools.r8.utils.FileUtils.JAVA_EXTENSION;
+import static org.junit.Assert.assertTrue;
+
+import com.android.tools.r8.SingleTestRunResult;
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.TestRuntime;
+import com.android.tools.r8.ToolHelper;
+import com.android.tools.r8.ToolHelper.DexVm.Version;
+import com.android.tools.r8.desugar.desugaredlibrary.DesugaredLibraryTestBase;
+import com.android.tools.r8.desugar.desugaredlibrary.test.CompilationSpecification;
+import com.android.tools.r8.desugar.desugaredlibrary.test.DesugaredLibraryTestCompileResult;
+import com.android.tools.r8.desugar.desugaredlibrary.test.LibraryDesugaringSpecification;
+import com.android.tools.r8.utils.AndroidApiLevel;
+import com.android.tools.r8.utils.StringUtils;
+import com.google.common.collect.ImmutableList;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.Collections;
+import java.util.List;
+import org.junit.BeforeClass;
+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 Jdk11ConcurrentLinkedQueueTests extends DesugaredLibraryTestBase {
+
+ private static final String WHITEBOX = "WhiteBox";
+
+ private static Path[] JDK_11_CONCURRENT_LINKED_QUEUE_TEST_CLASS_FILES;
+
+ // JDK 11 test constants.
+ private static final Path JDK_11_CONCURRENT_LINKED_QUEUE_JAVA_DIR =
+ Paths.get(ToolHelper.JDK_11_TESTS_DIR + "java/util/concurrent/ConcurrentLinkedQueue");
+ private static final Path[] JDK_11_CONCURRENT_LINKED_QUEUE_JAVA_FILES =
+ new Path[] {JDK_11_CONCURRENT_LINKED_QUEUE_JAVA_DIR.resolve(WHITEBOX + JAVA_EXTENSION)};
+
+ @Parameter(0)
+ public static TestParameters parameters;
+
+ @Parameter(1)
+ public static LibraryDesugaringSpecification libraryDesugaringSpecification;
+
+ @Parameter(2)
+ public static CompilationSpecification compilationSpecification;
+
+ @Parameters(name = "{0}, spec: {1}, {2}")
+ public static List<Object[]> data() {
+ return buildParameters(
+ // TODO(134732760): Support Dalvik VMs, currently fails because libjavacrypto is required
+ // and present only in ART runtimes.
+ getTestParameters()
+ .withDexRuntimesStartingFromIncluding(Version.V5_1_1)
+ .withAllApiLevels()
+ .withApiLevel(AndroidApiLevel.N)
+ .build(),
+ ImmutableList.of(JDK11_MINIMAL, JDK11, JDK11_PATH),
+ ImmutableList.of(D8_L8DEBUG, D8_L8SHRINK));
+ }
+
+ @BeforeClass
+ public static void compileConcurrentLinkedQueueClasses() throws Exception {
+ // Build test constants.
+ Path jdk11MathTestsDir = getStaticTemp().newFolder("ConcurrentLinkedQueue").toPath();
+ javac(TestRuntime.getCheckedInJdk11(), getStaticTemp())
+ .addClasspathFiles(
+ Collections.singletonList(Paths.get(JDK_TESTS_BUILD_DIR + "testng-6.10.jar")))
+ .addSourceFiles(JDK_11_CONCURRENT_LINKED_QUEUE_JAVA_FILES)
+ .setOutputPath(jdk11MathTestsDir)
+ .compile();
+ JDK_11_CONCURRENT_LINKED_QUEUE_TEST_CLASS_FILES =
+ new Path[] {jdk11MathTestsDir.resolve(WHITEBOX + CLASS_EXTENSION)};
+ }
+
+ void runTest(List<String> toRun) throws Exception {
+ String verbosity = "2";
+ DesugaredLibraryTestCompileResult<?> compileResult =
+ testForDesugaredLibrary(
+ parameters, libraryDesugaringSpecification, compilationSpecification)
+ .addProgramFiles(JDK_11_CONCURRENT_LINKED_QUEUE_TEST_CLASS_FILES)
+ .addProgramFiles(testNGSupportProgramFiles())
+ .compile()
+ .withArt6Plus64BitsLib();
+ for (String success : toRun) {
+ SingleTestRunResult<?> result =
+ compileResult.run(parameters.getRuntime(), "TestNGMainRunner", verbosity, success);
+ // The WhiteBox test is using VarHandle and MethodHandles.privateLookupIn to inspect the
+ // internal state of the implementation so running it fails for various reasons on all VMs
+ // before T.
+ if (parameters.asDexRuntime().getVersion().equals(Version.V5_1_1)
+ || parameters.asDexRuntime().getVersion().equals(Version.V6_0_1)) {
+ assertTrue(
+ result
+ .getStdErr()
+ .contains(
+ "java.lang.ClassNotFoundException: Didn't find class"
+ + " \"java.lang.invoke.MethodHandles\""));
+ } else if (parameters.asDexRuntime().getVersion().equals(Version.V7_0_0)) {
+ assertTrue(
+ result
+ .getStdErr()
+ .contains(
+ "java.lang.NoClassDefFoundError: Failed resolution of:"
+ + " Ljava/lang/invoke/MethodHandles;"));
+ } else if (parameters.asDexRuntime().getVersion().isOlderThanOrEqual(Version.V12_0_0)) {
+ if (parameters.getApiLevel() == AndroidApiLevel.O
+ || parameters.getApiLevel() == AndroidApiLevel.O_MR1) {
+ assertTrue(result.getStdErr().contains("Verification error"));
+ } else {
+ assertTrue(
+ result
+ .getStdErr()
+ .contains(
+ "java.lang.NoSuchMethodError: No static method"
+ + " privateLookupIn(Ljava/lang/Class;Ljava/lang/invoke/MethodHandles$Lookup;)Ljava/lang/invoke/MethodHandles$Lookup;"
+ + " in class Ljava/lang/invoke/MethodHandles;"));
+ }
+ } else {
+ assertTrue(parameters.asDexRuntime().getVersion().isNewerThanOrEqual(Version.V13_0_0));
+ if (parameters.getApiLevel() == AndroidApiLevel.B
+ || parameters.getApiLevel() == AndroidApiLevel.N) {
+ assertTrue(result.getStdOut().contains("Instruction is unrepresentable in DEX"));
+ } else {
+ assertTrue(
+ "Failure in " + success + "\n" + result,
+ result.getStdOut().contains(StringUtils.lines(success + ": SUCCESS")));
+ }
+ }
+ }
+ }
+
+ @Test
+ public void testWhiteBox() throws Exception {
+ runTest(ImmutableList.of("WhiteBox"));
+ }
+}