| // 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.desugar.corelib.corelibjdktests; |
| |
| import static com.android.tools.r8.ToolHelper.JDK_TESTS_BUILD_DIR; |
| 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 static org.junit.Assert.fail; |
| |
| import com.android.tools.r8.D8TestCompileResult; |
| import com.android.tools.r8.D8TestRunResult; |
| import com.android.tools.r8.TestParameters; |
| import com.android.tools.r8.TestParametersCollection; |
| import com.android.tools.r8.TestRuntime.CfVm; |
| import com.android.tools.r8.ToolHelper; |
| import com.android.tools.r8.ToolHelper.DexVm.Version; |
| import com.android.tools.r8.utils.AndroidApiLevel; |
| import com.android.tools.r8.utils.StringUtils; |
| import java.io.File; |
| import java.nio.file.Path; |
| import java.nio.file.Paths; |
| import java.util.Arrays; |
| import java.util.Collections; |
| import java.util.IdentityHashMap; |
| import java.util.List; |
| import java.util.Map; |
| import java.util.stream.Collectors; |
| import org.junit.Assume; |
| import org.junit.BeforeClass; |
| import org.junit.Ignore; |
| import org.junit.Test; |
| import org.junit.runner.RunWith; |
| import org.junit.runners.Parameterized; |
| |
| @RunWith(Parameterized.class) |
| public class Jdk11StreamTests extends Jdk11CoreLibTestBase { |
| |
| private final TestParameters parameters; |
| |
| @Parameterized.Parameters(name = "{0}") |
| public static TestParametersCollection data() { |
| // TODO(134732760): Support Dalvik VMs, currently fails because libjavacrypto is required and |
| // present only in ART runtimes. |
| return getTestParameters() |
| .withDexRuntimesStartingFromIncluding(Version.V5_1_1) |
| .withAllApiLevels() |
| .build(); |
| } |
| |
| public Jdk11StreamTests(TestParameters parameters) { |
| this.parameters = parameters; |
| } |
| |
| private static final Path JDK_11_STREAM_TEST_CLASSES_DIR = |
| Paths.get(ToolHelper.JDK_11_TESTS_CLASSES_DIR + "Stream"); |
| private static final Path JDK_11_STREAM_TEST_FILES_DIR = |
| Paths.get("third_party/openjdk/jdk-11-test/java/util/stream/test"); |
| private static Path[] JDK_11_STREAM_TEST_COMPILED_FILES; |
| |
| private static Path[] getJdk11StreamTestFiles() throws Exception { |
| Path[] files = getAllFilesWithSuffixInDirectory(JDK_11_STREAM_TEST_FILES_DIR, JAVA_EXTENSION); |
| assert files.length > 0; |
| return files; |
| } |
| |
| private static String[] RUNNABLE_TESTS = |
| new String[] { |
| |
| // Working tests |
| "org/openjdk/tests/java/util/SplittableRandomTest.java", |
| "org/openjdk/tests/java/util/MapTest.java", |
| "org/openjdk/tests/java/util/FillableStringTest.java", |
| "org/openjdk/tests/java/util/stream/ForEachOpTest.java", |
| "org/openjdk/tests/java/util/stream/CollectionAndMapModifyStreamTest.java", |
| "org/openjdk/tests/java/util/stream/GroupByOpTest.java", |
| "org/openjdk/tests/java/util/stream/InfiniteStreamWithLimitOpTest.java", |
| "org/openjdk/tests/java/util/stream/PrimitiveAverageOpTest.java", |
| "org/openjdk/tests/java/util/stream/TeeOpTest.java", |
| "org/openjdk/tests/java/util/stream/MinMaxTest.java", |
| "org/openjdk/tests/java/util/stream/ConcatTest.java", |
| // Disabled because time to run > 1 min. |
| // "org/openjdk/tests/java/util/stream/CountLargeTest.java", |
| "org/openjdk/tests/java/util/stream/StreamParSeqTest.java", |
| "org/openjdk/tests/java/util/stream/ReduceByOpTest.java", |
| "org/openjdk/tests/java/util/stream/ConcatOpTest.java", |
| "org/openjdk/tests/java/util/stream/IntReduceTest.java", |
| "org/openjdk/tests/java/util/stream/SortedOpTest.java", |
| "org/openjdk/tests/java/util/stream/MatchOpTest.java", |
| // Disabled because time to run > 1 min. |
| // "org/openjdk/tests/java/util/stream/RangeTest.java", |
| "org/openjdk/tests/java/util/stream/IntSliceOpTest.java", |
| "org/openjdk/tests/java/util/stream/SequentialOpTest.java", |
| "org/openjdk/tests/java/util/stream/PrimitiveSumTest.java", |
| "org/openjdk/tests/java/util/stream/IterateTest.java", |
| "org/openjdk/tests/java/util/stream/ReduceTest.java", |
| "org/openjdk/tests/java/util/stream/IntUniqOpTest.java", |
| |
| // J9 failure |
| "org/openjdk/tests/java/util/stream/SpliteratorTest.java", |
| // Disabled because time to run > 1 min. |
| // "org/openjdk/tests/java/util/stream/CollectorsTest.java", |
| "org/openjdk/tests/java/util/stream/WhileOpStatefulTest.java", |
| "org/openjdk/tests/java/util/stream/WhileOpTest.java", |
| |
| // J9 security |
| "org/openjdk/tests/java/util/stream/CountTest.java", |
| // Disabled because time to run > 1 min. |
| // "org/openjdk/tests/java/util/stream/FlatMapOpTest.java", |
| "org/openjdk/tests/java/util/stream/StreamCloseTest.java", |
| "org/openjdk/tests/java/util/stream/DoublePrimitiveOpsTests.java", |
| // Disabled because time to run > 1 min. |
| // "org/openjdk/tests/java/util/stream/StreamSpliteratorTest.java", |
| "org/openjdk/tests/java/util/stream/CollectAndSummaryStatisticsTest.java", |
| |
| // Foreach problem |
| // Disabled because time to run > 1 min. |
| // "org/openjdk/tests/java/util/stream/StreamLinkTest.java", |
| "org/openjdk/tests/java/util/stream/FindFirstOpTest.java", |
| "org/openjdk/tests/java/util/stream/FindAnyOpTest.java", |
| // Disabled because time to run > 1 min. |
| // "org/openjdk/tests/java/util/stream/StreamBuilderTest.java", |
| // Disabled because time to run > 1 min. |
| // "org/openjdk/tests/java/util/stream/SliceOpTest.java", |
| "org/openjdk/tests/java/util/stream/DistinctOpTest.java", |
| "org/openjdk/tests/java/util/stream/MapOpTest.java", |
| // Disabled because time to run > 1 min. |
| // "org/openjdk/tests/java/util/stream/ToArrayOpTest.java", |
| |
| // J9 Random problem |
| "org/openjdk/tests/java/util/stream/LongPrimitiveOpsTests.java", |
| "org/openjdk/tests/java/util/stream/IntPrimitiveOpsTests.java" |
| }; |
| |
| private static Map<String, String> getRunnableTests() { |
| IdentityHashMap<String, String> pathToName = new IdentityHashMap<>(); |
| int javaExtSize = JAVA_EXTENSION.length(); |
| for (String runnableTest : RUNNABLE_TESTS) { |
| String nameWithoutJavaExt = runnableTest.substring(0, runnableTest.length() - javaExtSize); |
| pathToName.put( |
| JDK_11_STREAM_TEST_CLASSES_DIR + "/" + nameWithoutJavaExt + CLASS_EXTENSION, |
| nameWithoutJavaExt.replace("/", ".")); |
| } |
| return pathToName; |
| } |
| |
| private static String[] missingDesugaredMethods() { |
| // These methods are from Java 9 and not supported in the current desugared libraries. |
| return new String[] { |
| // Stream |
| "takeWhile(", |
| "dropWhile(", |
| "iterate(", |
| "ofNullable(", |
| "range(", |
| "doubles(", |
| // Collectors |
| "filtering(", |
| "flatMapping(", |
| }; |
| } |
| |
| @BeforeClass |
| public static void compileJdk11StreamTests() throws Exception { |
| if (!new File(JDK_11_STREAM_TEST_CLASSES_DIR.toString()).exists()) { |
| List<String> options = |
| Arrays.asList( |
| "--add-reads", |
| "java.base=ALL-UNNAMED", |
| "--patch-module", |
| "java.base=" + JDK_11_JAVA_BASE_EXTENSION_CLASSES_DIR); |
| ToolHelper.runJavac( |
| CfVm.JDK11, |
| Collections.singletonList(Paths.get(JDK_TESTS_BUILD_DIR + "testng-6.10.jar")), |
| JDK_11_STREAM_TEST_CLASSES_DIR, |
| options, |
| getJdk11StreamTestFiles()); |
| } |
| JDK_11_STREAM_TEST_COMPILED_FILES = |
| getAllFilesWithSuffixInDirectory(JDK_11_STREAM_TEST_CLASSES_DIR, CLASS_EXTENSION); |
| assert JDK_11_STREAM_TEST_COMPILED_FILES.length > 0; |
| } |
| |
| |
| // TODO(b/137876068): Temporarily ignored to move forward with Desugared API conversion. |
| @Test |
| @Ignore |
| public void testStream() throws Exception { |
| Assume.assumeTrue( |
| "Requires Java base extensions, should add it when not desugaring", |
| parameters.getApiLevel().getLevel() < AndroidApiLevel.N.getLevel()); |
| // TODO(b/137876068): It seems to fail on windows because the method. |
| // getAllFilesWithSuffixInDirectory() finds different files on Windows (To be confirmed), so |
| // compilation is then different and raises an error. |
| Assume.assumeFalse(ToolHelper.isWindows()); |
| Map<String, String> runnableTests = getRunnableTests(); |
| String verbosity = "2"; |
| List<Path> filesToCompile = |
| Arrays.stream(JDK_11_STREAM_TEST_COMPILED_FILES) |
| .filter(file -> !file.toString().contains("lang/invoke")) |
| .collect(Collectors.toList()); |
| D8TestCompileResult compileResult = |
| testForD8() |
| .addProgramFiles(filesToCompile) |
| .addProgramFiles(getPathsFiles()) |
| .addProgramFiles(getSafeVarArgsFile()) |
| .addProgramFiles(testNGSupportProgramFiles()) |
| .addLibraryFiles(ToolHelper.getAndroidJar(AndroidApiLevel.P)) |
| .setMinApi(parameters.getApiLevel()) |
| .enableCoreLibraryDesugaring(parameters.getApiLevel()) |
| .compile() |
| .inspect( |
| i -> { |
| System.out.println("x"); |
| }) |
| .addDesugaredCoreLibraryRunClassPath( |
| this::buildDesugaredLibraryWithJavaBaseExtension, parameters.getApiLevel()) |
| .withArtFrameworks() |
| .withArt6Plus64BitsLib(); |
| int numSuccesses = 0; |
| int numHardFailures = 0; |
| for (String path : runnableTests.keySet()) { |
| // System.out.println(path); |
| // System.out.println(LocalDateTime.now()); |
| assert runnableTests.get(path) != null; |
| D8TestRunResult result = |
| compileResult.run( |
| parameters.getRuntime(), "TestNGMainRunner", verbosity, runnableTests.get(path)); |
| if (result.getStdOut().endsWith(StringUtils.lines("SUCCESS"))) { |
| assertTrue( |
| result |
| .getStdOut() |
| .endsWith( |
| StringUtils.lines("Tests result in " + runnableTests.get(path) + ": SUCCESS"))); |
| numSuccesses++; |
| } else { |
| if (result.getStdOut().contains("java.lang.NoSuchMethodError") |
| && Arrays.stream(missingDesugaredMethods()) |
| .anyMatch(method -> result.getStdOut().contains(method))) { |
| // TODO(b/134732760): support Java 9 APIs. |
| } else if (result |
| .getStdOut() |
| .contains("java.lang.NoSuchMethodError: No interface method forEach")) { |
| // TODO(b/134732760): fix tests no to use Iterable#forEach |
| } else if (result.getStdOut().contains("in class Ljava/util/Random") |
| && result.getStdOut().contains("java.lang.NoSuchMethodError")) { |
| // TODO(b/134732760): Random Java 9 Apis, support or do not use them. |
| } else if (result.getStdOut().contains("java.lang.AssertionError")) { |
| // TODO(b/134732760): Investigate and fix these issues. |
| numHardFailures++; |
| System.out.println("HARD FAIL" + path); |
| } else { |
| String errorMessage = "STDOUT:\n" + result.getStdOut() + "STDERR:\n" + result.getStdErr(); |
| fail(errorMessage); |
| } |
| } |
| } |
| assertTrue(numSuccesses > 20); |
| assertTrue(numHardFailures < 6); |
| } |
| } |