Add coroutines-compat jar dependency to those tests that require it

#KT-36083
This commit is contained in:
Ilya Gorbunov
2020-01-20 23:44:38 +03:00
parent cef81e11b7
commit 9f8e3dad33
9 changed files with 63 additions and 19 deletions
@@ -1,4 +1,6 @@
// !LANGUAGE: -ExtendedMainConvention -ReleaseCoroutines // !LANGUAGE: -ExtendedMainConvention -ReleaseCoroutines
// WITH_RUNTIME // WITH_RUNTIME
// uses kotlin.coroutines.experimental classes under the hood
suspend fun main(args: Array<String>) {} suspend fun main(args: Array<String>) {}
@@ -109,13 +109,14 @@ abstract class AbstractDiagnosticsTest : BaseDiagnosticsTest() {
val oldModule = modules[testModule]!! val oldModule = modules[testModule]!!
val languageVersionSettings = val languageVersionSettings =
if (coroutinesPackage.isNotEmpty()) if (coroutinesPackage.isNotEmpty()) {
val isExperimental = coroutinesPackage == DescriptorUtils.COROUTINES_PACKAGE_FQ_NAME_EXPERIMENTAL.asString()
CompilerTestLanguageVersionSettings( CompilerTestLanguageVersionSettings(
DEFAULT_DIAGNOSTIC_TESTS_FEATURES, DEFAULT_DIAGNOSTIC_TESTS_FEATURES,
if (coroutinesPackage.contains("experimental")) ApiVersion.KOTLIN_1_2 else ApiVersion.KOTLIN_1_3, if (isExperimental) ApiVersion.KOTLIN_1_2 else ApiVersion.KOTLIN_1_3,
if (coroutinesPackage.contains("experimental")) LanguageVersion.KOTLIN_1_2 else LanguageVersion.KOTLIN_1_3 if (isExperimental) LanguageVersion.KOTLIN_1_2 else LanguageVersion.KOTLIN_1_3
) )
else loadLanguageVersionSettings(testFilesInModule) } else loadLanguageVersionSettings(testFilesInModule)
languageVersionSettingsByModule[testModule] = languageVersionSettings languageVersionSettingsByModule[testModule] = languageVersionSettings
@@ -16,6 +16,7 @@ import org.jetbrains.kotlin.codegen.forTestCompile.ForTestCompileRuntime;
import org.jetbrains.kotlin.config.CompilerConfiguration; import org.jetbrains.kotlin.config.CompilerConfiguration;
import org.jetbrains.kotlin.config.JVMConfigurationKeys; import org.jetbrains.kotlin.config.JVMConfigurationKeys;
import org.jetbrains.kotlin.parsing.KotlinParserDefinition; import org.jetbrains.kotlin.parsing.KotlinParserDefinition;
import org.jetbrains.kotlin.resolve.DescriptorUtils;
import org.jetbrains.kotlin.test.*; import org.jetbrains.kotlin.test.*;
import org.jetbrains.kotlin.test.testFramework.KtUsefulTestCase; import org.jetbrains.kotlin.test.testFramework.KtUsefulTestCase;
@@ -114,6 +115,11 @@ public abstract class KotlinMultiFileTestWithJava<M, F> extends KtUsefulTestCase
result.add(ForTestCompileRuntime.runtimeJarForTestsWithJdk8()); result.add(ForTestCompileRuntime.runtimeJarForTestsWithJdk8());
} }
if (DescriptorUtils.COROUTINES_PACKAGE_FQ_NAME_EXPERIMENTAL.asString().equals(coroutinesPackage) ||
fileText.contains(DescriptorUtils.COROUTINES_PACKAGE_FQ_NAME_EXPERIMENTAL.asString())) {
result.add(ForTestCompileRuntime.coroutinesCompatForTests());
}
return result; return result;
} }
@@ -14,6 +14,7 @@ import org.jetbrains.kotlin.backend.common.CodegenUtil;
import org.jetbrains.kotlin.codegen.ir.AbstractFirBlackBoxCodegenTest; import org.jetbrains.kotlin.codegen.ir.AbstractFirBlackBoxCodegenTest;
import org.jetbrains.kotlin.fileClasses.JvmFileClassUtil; import org.jetbrains.kotlin.fileClasses.JvmFileClassUtil;
import org.jetbrains.kotlin.psi.KtFile; import org.jetbrains.kotlin.psi.KtFile;
import org.jetbrains.kotlin.resolve.DescriptorUtils;
import org.jetbrains.kotlin.test.InTextDirectivesUtils; import org.jetbrains.kotlin.test.InTextDirectivesUtils;
import org.jetbrains.kotlin.utils.ExceptionUtilsKt; import org.jetbrains.kotlin.utils.ExceptionUtilsKt;
@@ -67,7 +68,7 @@ public abstract class AbstractBlackBoxCodegenTest extends CodegenTestCase {
if (!InTextDirectivesUtils.isDirectiveDefined(FileUtil.loadFile(wholeFile), "CHECK_BYTECODE_LISTING")) return; if (!InTextDirectivesUtils.isDirectiveDefined(FileUtil.loadFile(wholeFile), "CHECK_BYTECODE_LISTING")) return;
String suffix = String suffix =
(coroutinesPackage.contains("experimental") || coroutinesPackage.isEmpty()) (coroutinesPackage.equals(DescriptorUtils.COROUTINES_PACKAGE_FQ_NAME_EXPERIMENTAL.asString()) || coroutinesPackage.isEmpty())
&& InTextDirectivesUtils.isDirectiveDefined(FileUtil.loadFile(wholeFile), "COMMON_COROUTINES_TEST") && InTextDirectivesUtils.isDirectiveDefined(FileUtil.loadFile(wholeFile), "COMMON_COROUTINES_TEST")
? "_1_2" : ? "_1_2" :
getBackend().isIR() ? "_ir" : ""; getBackend().isIR() ? "_ir" : "";
@@ -86,7 +86,10 @@ public abstract class AbstractCompileKotlinAgainstKotlinTest extends CodegenTest
@NotNull @NotNull
private URLClassLoader createGeneratedClassLoader() throws Exception { private URLClassLoader createGeneratedClassLoader() throws Exception {
return new URLClassLoader( return new URLClassLoader(
new URL[]{ bDir.toURI().toURL(), aDir.toURI().toURL() }, new URL[]{
bDir.toURI().toURL(), aDir.toURI().toURL(),
ForTestCompileRuntime.coroutinesCompatForTests().toURI().toURL()
},
ForTestCompileRuntime.runtimeAndReflectJarClassLoader() ForTestCompileRuntime.runtimeAndReflectJarClassLoader()
); );
} }
@@ -28,12 +28,15 @@ import org.jetbrains.kotlin.cli.common.output.OutputUtilsKt;
import org.jetbrains.kotlin.cli.jvm.compiler.EnvironmentConfigFiles; import org.jetbrains.kotlin.cli.jvm.compiler.EnvironmentConfigFiles;
import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment; import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment;
import org.jetbrains.kotlin.cli.jvm.compiler.NoScopeRecordCliBindingTrace; import org.jetbrains.kotlin.cli.jvm.compiler.NoScopeRecordCliBindingTrace;
import org.jetbrains.kotlin.cli.jvm.config.JvmClasspathRoot;
import org.jetbrains.kotlin.cli.jvm.config.JvmContentRootsKt;
import org.jetbrains.kotlin.codegen.forTestCompile.ForTestCompileRuntime; import org.jetbrains.kotlin.codegen.forTestCompile.ForTestCompileRuntime;
import org.jetbrains.kotlin.codegen.state.GenerationState; import org.jetbrains.kotlin.codegen.state.GenerationState;
import org.jetbrains.kotlin.config.*; import org.jetbrains.kotlin.config.*;
import org.jetbrains.kotlin.fileClasses.JvmFileClassUtil; import org.jetbrains.kotlin.fileClasses.JvmFileClassUtil;
import org.jetbrains.kotlin.name.FqName; import org.jetbrains.kotlin.name.FqName;
import org.jetbrains.kotlin.psi.KtFile; import org.jetbrains.kotlin.psi.KtFile;
import org.jetbrains.kotlin.resolve.DescriptorUtils;
import org.jetbrains.kotlin.scripting.definitions.ScriptDependenciesProvider; import org.jetbrains.kotlin.scripting.definitions.ScriptDependenciesProvider;
import org.jetbrains.kotlin.scripting.resolve.ScriptCompilationConfigurationWrapper; import org.jetbrains.kotlin.scripting.resolve.ScriptCompilationConfigurationWrapper;
import org.jetbrains.kotlin.test.*; import org.jetbrains.kotlin.test.*;
@@ -59,10 +62,7 @@ import java.lang.reflect.Method;
import java.net.MalformedURLException; import java.net.MalformedURLException;
import java.net.URL; import java.net.URL;
import java.net.URLClassLoader; import java.net.URLClassLoader;
import java.util.ArrayList; import java.util.*;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher; import java.util.regex.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;
@@ -166,6 +166,7 @@ public abstract class CodegenTestCase extends KtUsefulTestCase {
) { ) {
LanguageVersionSettings explicitLanguageVersionSettings = null; LanguageVersionSettings explicitLanguageVersionSettings = null;
boolean disableReleaseCoroutines = false; boolean disableReleaseCoroutines = false;
boolean includeCompatExperimentalCoroutines = false;
List<String> kotlinConfigurationFlags = new ArrayList<>(0); List<String> kotlinConfigurationFlags = new ArrayList<>(0);
for (TestFile testFile : testFilesWithConfigurationDirectives) { for (TestFile testFile : testFilesWithConfigurationDirectives) {
@@ -191,11 +192,16 @@ public abstract class CodegenTestCase extends KtUsefulTestCase {
if (!InTextDirectivesUtils.findLinesWithPrefixesRemoved(testFile.content, "// COMMON_COROUTINES_TEST").isEmpty()) { if (!InTextDirectivesUtils.findLinesWithPrefixesRemoved(testFile.content, "// COMMON_COROUTINES_TEST").isEmpty()) {
assert !testFile.content.contains("COROUTINES_PACKAGE") : "Must replace COROUTINES_PACKAGE prior to tests compilation"; assert !testFile.content.contains("COROUTINES_PACKAGE") : "Must replace COROUTINES_PACKAGE prior to tests compilation";
if (coroutinesPackage.equals("kotlin.coroutines.experimental")) { if (DescriptorUtils.COROUTINES_PACKAGE_FQ_NAME_EXPERIMENTAL.asString().equals(coroutinesPackage)) {
disableReleaseCoroutines = true; disableReleaseCoroutines = true;
includeCompatExperimentalCoroutines = true;
} }
} }
if (testFile.content.contains(DescriptorUtils.COROUTINES_PACKAGE_FQ_NAME_EXPERIMENTAL.asString())) {
includeCompatExperimentalCoroutines = true;
}
Map<String, String> directives = KotlinTestUtils.parseDirectives(testFile.content); Map<String, String> directives = KotlinTestUtils.parseDirectives(testFile.content);
LanguageVersionSettings fileLanguageVersionSettings = parseLanguageVersionSettings(directives); LanguageVersionSettings fileLanguageVersionSettings = parseLanguageVersionSettings(directives);
@@ -213,6 +219,9 @@ public abstract class CodegenTestCase extends KtUsefulTestCase {
Collections.emptyMap() Collections.emptyMap()
); );
} }
if (includeCompatExperimentalCoroutines) {
JvmContentRootsKt.addJvmClasspathRoot(configuration, ForTestCompileRuntime.coroutinesCompatForTests());
}
if (explicitLanguageVersionSettings != null) { if (explicitLanguageVersionSettings != null) {
CommonConfigurationKeysKt.setLanguageVersionSettings(configuration, explicitLanguageVersionSettings); CommonConfigurationKeysKt.setLanguageVersionSettings(configuration, explicitLanguageVersionSettings);
@@ -425,6 +434,7 @@ public abstract class CodegenTestCase extends KtUsefulTestCase {
if (additionalDependencies != null) { if (additionalDependencies != null) {
files.addAll(additionalDependencies); files.addAll(additionalDependencies);
} }
files.addAll(getExtraDependenciesFromKotlinCompileClasspath());
ScriptDependenciesProvider externalImportsProvider = ScriptDependenciesProvider externalImportsProvider =
ScriptDependenciesProvider.Companion.getInstance(myEnvironment.getProject()); ScriptDependenciesProvider.Companion.getInstance(myEnvironment.getProject());
@@ -451,6 +461,20 @@ public abstract class CodegenTestCase extends KtUsefulTestCase {
} }
} }
private Set<File> getExtraDependenciesFromKotlinCompileClasspath() {
List<File> includeFromCompileClasspath = CollectionsKt.listOf(
ForTestCompileRuntime.coroutinesCompatForTests()
);
List<File> compileClasspath =
CollectionsKt.map(
CollectionsKt.filterIsInstance(
myEnvironment.getConfiguration().get(CLIConfigurationKeys.CONTENT_ROOTS),
JvmClasspathRoot.class),
JvmClasspathRoot::getFile);
return CollectionsKt.intersect(compileClasspath, includeFromCompileClasspath);
}
@NotNull @NotNull
protected String generateToText() { protected String generateToText() {
return generateToText(null); return generateToText(null);
@@ -699,6 +723,7 @@ public abstract class CodegenTestCase extends KtUsefulTestCase {
if (loadAndroidAnnotations) { if (loadAndroidAnnotations) {
javaClasspath.add(ForTestCompileRuntime.androidAnnotationsForTests().getPath()); javaClasspath.add(ForTestCompileRuntime.androidAnnotationsForTests().getPath());
} }
javaClasspath.addAll(CollectionsKt.map(getExtraDependenciesFromKotlinCompileClasspath(), File::getPath));
javaClassesOutputDirectory = getJavaClassesOutputDirectory(); javaClassesOutputDirectory = getJavaClassesOutputDirectory();
compileJava(findJavaSourcesInDirectory(javaSourceDir), javaClasspath, javacOptions, javaClassesOutputDirectory); compileJava(findJavaSourcesInDirectory(javaSourceDir), javaClasspath, javacOptions, javaClassesOutputDirectory);
@@ -100,6 +100,11 @@ public class ForTestCompileRuntime {
return assertExists(new File("dist/kotlinc/lib/kotlin-annotations-android.jar")); return assertExists(new File("dist/kotlinc/lib/kotlin-annotations-android.jar"));
} }
@NotNull
public static File coroutinesCompatForTests() {
return assertExists(new File("dist/kotlinc/lib/kotlin-coroutines-experimental-compat.jar"));
}
@NotNull @NotNull
private static File assertExists(@NotNull File file) { private static File assertExists(@NotNull File file) {
if (!file.exists()) { if (!file.exists()) {
@@ -59,7 +59,7 @@ abstract class AbstractKotlinCompilerIntegrationTest : TestCaseWithTmpdir() {
}, },
checkKotlinOutput: (String) -> Unit = { actual -> assertEquals(normalizeOutput("" to ExitCode.OK), actual) }, checkKotlinOutput: (String) -> Unit = { actual -> assertEquals(normalizeOutput("" to ExitCode.OK), actual) },
manifest: Manifest? = null, manifest: Manifest? = null,
vararg extraClassPath: File extraClassPath: List<File> = emptyList()
): File { ): File {
val sourceDir = File(testDataDirectory, libraryName) val sourceDir = File(testDataDirectory, libraryName)
val javaFiles = FileUtil.findFilesByMask(JAVA_FILES, sourceDir) val javaFiles = FileUtil.findFilesByMask(JAVA_FILES, sourceDir)
@@ -70,7 +70,7 @@ abstract class AbstractKotlinCompilerIntegrationTest : TestCaseWithTmpdir() {
val outputDir = if (isJar) File(tmpdir, "output-$libraryName") else destination val outputDir = if (isJar) File(tmpdir, "output-$libraryName") else destination
if (kotlinFiles.isNotEmpty()) { if (kotlinFiles.isNotEmpty()) {
val output = compileKotlin(libraryName, outputDir, extraClassPath.toList(), K2JVMCompiler(), additionalOptions, expectedFileName = null) val output = compileKotlin(libraryName, outputDir, extraClassPath, K2JVMCompiler(), additionalOptions, expectedFileName = null)
checkKotlinOutput(normalizeOutput(output)) checkKotlinOutput(normalizeOutput(output))
} }
@@ -438,7 +438,7 @@ class CompileKotlinAgainstCustomBinariesTest : AbstractKotlinCompilerIntegration
fun testReplaceAnnotationClassWithInterface() { fun testReplaceAnnotationClassWithInterface() {
val library1 = compileLibrary("library-1") val library1 = compileLibrary("library-1")
val usage = compileLibrary("usage", extraClassPath = *arrayOf(library1)) val usage = compileLibrary("usage", extraClassPath = listOf(library1))
val library2 = compileLibrary("library-2") val library2 = compileLibrary("library-2")
doTestWithTxt(usage, library2) doTestWithTxt(usage, library2)
} }
@@ -507,7 +507,7 @@ class CompileKotlinAgainstCustomBinariesTest : AbstractKotlinCompilerIntegration
val version = intArrayOf(1, 0, 1) // legacy coroutines metadata val version = intArrayOf(1, 0, 1) // legacy coroutines metadata
val options = listOf("-language-version", "1.2", "-Xcoroutines=enable") val options = listOf("-language-version", "1.2", "-Xcoroutines=enable")
val library = transformJar( val library = transformJar(
compileLibrary("library", additionalOptions = options), compileLibrary("library", additionalOptions = options, extraClassPath = listOf(ForTestCompileRuntime.coroutinesCompatForTests())),
{ _, bytes -> { _, bytes ->
val (resultBytes, removedCounter) = stripSuspensionMarksToImitateLegacyCompiler( val (resultBytes, removedCounter) = stripSuspensionMarksToImitateLegacyCompiler(
WrongBytecodeVersionTest.transformMetadataInClassFile(bytes) { name, _ -> WrongBytecodeVersionTest.transformMetadataInClassFile(bytes) { name, _ ->
@@ -518,11 +518,11 @@ class CompileKotlinAgainstCustomBinariesTest : AbstractKotlinCompilerIntegration
resultBytes resultBytes
}) })
compileKotlin( compileKotlin(
"source.kt", tmpdir, listOf(library), K2JVMCompiler(), "source.kt", tmpdir, listOf(library, ForTestCompileRuntime.coroutinesCompatForTests()), K2JVMCompiler(),
additionalOptions = options additionalOptions = options
) )
val classLoader = URLClassLoader( val classLoader = URLClassLoader(
arrayOf(library.toURI().toURL(), tmpdir.toURI().toURL()), arrayOf(library.toURI().toURL(), tmpdir.toURI().toURL(), ForTestCompileRuntime.coroutinesCompatForTests().toURI().toURL()),
ForTestCompileRuntime.runtimeJarClassLoader() ForTestCompileRuntime.runtimeJarClassLoader()
) )
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")
@@ -576,12 +576,13 @@ class CompileKotlinAgainstCustomBinariesTest : AbstractKotlinCompilerIntegration
val library = compileLibrary( val library = compileLibrary(
"library", "library",
additionalOptions = listOf("-language-version", "1.2"), additionalOptions = listOf("-language-version", "1.2"),
checkKotlinOutput = {} checkKotlinOutput = {},
extraClassPath = listOf(ForTestCompileRuntime.coroutinesCompatForTests())
) )
compileKotlin( compileKotlin(
"release.kt", "release.kt",
tmpdir, tmpdir,
listOf(library), listOf(library, ForTestCompileRuntime.coroutinesCompatForTests()),
additionalOptions = listOf("-language-version", "1.3", "-api-version", "1.3") additionalOptions = listOf("-language-version", "1.3", "-api-version", "1.3")
) )
} }