blob: adc0928a35b523426487ad5054d733fddf868f8e [file] [log] [blame]
// 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.desugaredlibrary.desugaredlibraryjdktests;
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.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[]{
// Disabled because explicit cast done on a wrapped value.
//"org/openjdk/tests/java/util/SplittableRandomTest.java",
// Working tests
"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",
// Disabled because time to run > 1 min.
// "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;
}
@Test
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()
.addDesugaredCoreLibraryRunClassPath(
this::buildDesugaredLibraryWithJavaBaseExtension, parameters.getApiLevel())
.withArtFrameworks()
.withArt6Plus64BitsLib();
int numSuccesses = 0;
int numHardFailures = 0;
for (String path : runnableTests.keySet()) {
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++;
} else {
String errorMessage = "STDOUT:\n" + result.getStdOut() + "STDERR:\n" + result.getStdErr();
fail(errorMessage);
}
}
}
assertTrue(numSuccesses > 20);
assertTrue(numHardFailures <= 6);
}
}