blob: b6b26890fa3ae1bc2b228212e11d2f310af34407 [file] [log] [blame]
// 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.desugar.records;
import static com.android.tools.r8.TestRuntime.getCheckedInJdk8;
import static org.junit.Assert.assertTrue;
import com.android.tools.r8.JavaCompilerTool;
import com.android.tools.r8.ToolHelper;
import com.android.tools.r8.utils.StringUtils;
import com.android.tools.r8.utils.codeinspector.CodeInspector;
import com.android.tools.r8.utils.codeinspector.FoundClassSubject;
import com.google.common.io.ByteStreams;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import org.junit.Assume;
import org.junit.rules.TemporaryFolder;
/**
* Records are compiled using: third_party/openjdk/jdk-15/linux/bin/javac --release 15
* --enable-preview path/to/file.java
*/
public class RecordTestUtils {
private static final String EXAMPLE_FOLDER = "examplesJava17";
private static final String RECORD_FOLDER = "records";
public static Path jar() {
return Paths.get(ToolHelper.TESTS_BUILD_DIR, EXAMPLE_FOLDER, RECORD_FOLDER + ".jar");
}
// TODO(b/169645628): Consider if that keep rule should be required or not.
public static final String RECORD_KEEP_RULE =
"-keepattributes *\n" + "-keep class * extends java.lang.Record { private final <fields>; }";
public static Path[] getJdk15LibraryFiles(TemporaryFolder temp) throws IOException {
Assume.assumeFalse(ToolHelper.isWindows());
// TODO(b/169645628): Add JDK-15 runtime jar instead. As a temporary solution we use the jdk 8
// runtime with additional stubs.
// We use jdk-8 for compilation because in jdk-9 and higher we would need to deal with the
// module patching logic.
Path recordStubs =
JavaCompilerTool.create(getCheckedInJdk8(), temp)
.addSourceFiles(Paths.get("src", "test", "javaStubs", "Record.java"))
.addSourceFiles(Paths.get("src", "test", "javaStubs", "ObjectMethods.java"))
.addSourceFiles(Paths.get("src", "test", "javaStubs", "StringConcatFactory.java"))
.addSourceFiles(Paths.get("src", "test", "javaStubs", "TypeDescriptor.java"))
.addSourceFiles(Paths.get("src", "test", "javaStubs", "RecordComponent.java"))
.compile();
return new Path[] {recordStubs, ToolHelper.getJava8RuntimeJar()};
}
public static byte[][] getProgramData(String mainClassSimpleName) {
byte[][] bytes = classDataFromPrefix(RECORD_FOLDER + "/" + mainClassSimpleName);
assert bytes.length > 0 : "Did not find any program data for " + mainClassSimpleName;
return bytes;
}
public static String getMainType(String mainClassSimpleName) {
return RECORD_FOLDER + "." + mainClassSimpleName;
}
private static byte[][] classDataFromPrefix(String prefix) {
Path examplePath = jar();
if (!Files.exists(examplePath)) {
throw new RuntimeException(
"Could not find path "
+ examplePath
+ ". Build "
+ EXAMPLE_FOLDER
+ " by running tools/gradle.py build"
+ StringUtils.capitalize(EXAMPLE_FOLDER));
}
List<byte[]> result = new ArrayList<>();
try (ZipFile zipFile = new ZipFile(examplePath.toFile())) {
Enumeration<? extends ZipEntry> entries = zipFile.entries();
while (entries.hasMoreElements()) {
ZipEntry zipEntry = entries.nextElement();
if (zipEntry.getName().startsWith(prefix)) {
result.add(ByteStreams.toByteArray(zipFile.getInputStream(zipEntry)));
}
}
} catch (IOException e) {
throw new RuntimeException("Could not read zip-entry from " + examplePath.toString(), e);
}
if (result.isEmpty()) {
throw new RuntimeException("Did not find any class with prefix " + prefix);
}
return result.toArray(new byte[0][0]);
}
public static void assertRecordsAreRecords(Path output) throws IOException {
CodeInspector inspector =
new CodeInspector(output, opt -> opt.testing.enableExperimentalRecordDesugaring = true);
for (FoundClassSubject clazz : inspector.allClasses()) {
if (clazz.getDexProgramClass().superType.toString().equals("java.lang.Record")) {
assertTrue(clazz.getDexProgramClass().isRecord());
}
}
}
}