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
// WITH_RUNTIME
// uses kotlin.coroutines.experimental classes under the hood
suspend fun main(args: Array<String>) {}
@@ -109,13 +109,14 @@ abstract class AbstractDiagnosticsTest : BaseDiagnosticsTest() {
val oldModule = modules[testModule]!!
val languageVersionSettings =
if (coroutinesPackage.isNotEmpty())
if (coroutinesPackage.isNotEmpty()) {
val isExperimental = coroutinesPackage == DescriptorUtils.COROUTINES_PACKAGE_FQ_NAME_EXPERIMENTAL.asString()
CompilerTestLanguageVersionSettings(
DEFAULT_DIAGNOSTIC_TESTS_FEATURES,
if (coroutinesPackage.contains("experimental")) ApiVersion.KOTLIN_1_2 else ApiVersion.KOTLIN_1_3,
if (coroutinesPackage.contains("experimental")) LanguageVersion.KOTLIN_1_2 else LanguageVersion.KOTLIN_1_3
if (isExperimental) ApiVersion.KOTLIN_1_2 else ApiVersion.KOTLIN_1_3,
if (isExperimental) LanguageVersion.KOTLIN_1_2 else LanguageVersion.KOTLIN_1_3
)
else loadLanguageVersionSettings(testFilesInModule)
} else loadLanguageVersionSettings(testFilesInModule)
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.JVMConfigurationKeys;
import org.jetbrains.kotlin.parsing.KotlinParserDefinition;
import org.jetbrains.kotlin.resolve.DescriptorUtils;
import org.jetbrains.kotlin.test.*;
import org.jetbrains.kotlin.test.testFramework.KtUsefulTestCase;
@@ -114,6 +115,11 @@ public abstract class KotlinMultiFileTestWithJava<M, F> extends KtUsefulTestCase
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;
}
@@ -14,6 +14,7 @@ import org.jetbrains.kotlin.backend.common.CodegenUtil;
import org.jetbrains.kotlin.codegen.ir.AbstractFirBlackBoxCodegenTest;
import org.jetbrains.kotlin.fileClasses.JvmFileClassUtil;
import org.jetbrains.kotlin.psi.KtFile;
import org.jetbrains.kotlin.resolve.DescriptorUtils;
import org.jetbrains.kotlin.test.InTextDirectivesUtils;
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;
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")
? "_1_2" :
getBackend().isIR() ? "_ir" : "";
@@ -86,7 +86,10 @@ public abstract class AbstractCompileKotlinAgainstKotlinTest extends CodegenTest
@NotNull
private URLClassLoader createGeneratedClassLoader() throws Exception {
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()
);
}
@@ -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.KotlinCoreEnvironment;
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.state.GenerationState;
import org.jetbrains.kotlin.config.*;
import org.jetbrains.kotlin.fileClasses.JvmFileClassUtil;
import org.jetbrains.kotlin.name.FqName;
import org.jetbrains.kotlin.psi.KtFile;
import org.jetbrains.kotlin.resolve.DescriptorUtils;
import org.jetbrains.kotlin.scripting.definitions.ScriptDependenciesProvider;
import org.jetbrains.kotlin.scripting.resolve.ScriptCompilationConfigurationWrapper;
import org.jetbrains.kotlin.test.*;
@@ -59,10 +62,7 @@ import java.lang.reflect.Method;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@@ -166,6 +166,7 @@ public abstract class CodegenTestCase extends KtUsefulTestCase {
) {
LanguageVersionSettings explicitLanguageVersionSettings = null;
boolean disableReleaseCoroutines = false;
boolean includeCompatExperimentalCoroutines = false;
List<String> kotlinConfigurationFlags = new ArrayList<>(0);
for (TestFile testFile : testFilesWithConfigurationDirectives) {
@@ -191,11 +192,16 @@ public abstract class CodegenTestCase extends KtUsefulTestCase {
if (!InTextDirectivesUtils.findLinesWithPrefixesRemoved(testFile.content, "// COMMON_COROUTINES_TEST").isEmpty()) {
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;
includeCompatExperimentalCoroutines = true;
}
}
if (testFile.content.contains(DescriptorUtils.COROUTINES_PACKAGE_FQ_NAME_EXPERIMENTAL.asString())) {
includeCompatExperimentalCoroutines = true;
}
Map<String, String> directives = KotlinTestUtils.parseDirectives(testFile.content);
LanguageVersionSettings fileLanguageVersionSettings = parseLanguageVersionSettings(directives);
@@ -213,6 +219,9 @@ public abstract class CodegenTestCase extends KtUsefulTestCase {
Collections.emptyMap()
);
}
if (includeCompatExperimentalCoroutines) {
JvmContentRootsKt.addJvmClasspathRoot(configuration, ForTestCompileRuntime.coroutinesCompatForTests());
}
if (explicitLanguageVersionSettings != null) {
CommonConfigurationKeysKt.setLanguageVersionSettings(configuration, explicitLanguageVersionSettings);
@@ -425,6 +434,7 @@ public abstract class CodegenTestCase extends KtUsefulTestCase {
if (additionalDependencies != null) {
files.addAll(additionalDependencies);
}
files.addAll(getExtraDependenciesFromKotlinCompileClasspath());
ScriptDependenciesProvider externalImportsProvider =
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
protected String generateToText() {
return generateToText(null);
@@ -699,6 +723,7 @@ public abstract class CodegenTestCase extends KtUsefulTestCase {
if (loadAndroidAnnotations) {
javaClasspath.add(ForTestCompileRuntime.androidAnnotationsForTests().getPath());
}
javaClasspath.addAll(CollectionsKt.map(getExtraDependenciesFromKotlinCompileClasspath(), File::getPath));
javaClassesOutputDirectory = getJavaClassesOutputDirectory();
compileJava(findJavaSourcesInDirectory(javaSourceDir), javaClasspath, javacOptions, javaClassesOutputDirectory);
@@ -100,6 +100,11 @@ public class ForTestCompileRuntime {
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
private static File assertExists(@NotNull File file) {
if (!file.exists()) {
@@ -59,7 +59,7 @@ abstract class AbstractKotlinCompilerIntegrationTest : TestCaseWithTmpdir() {
},
checkKotlinOutput: (String) -> Unit = { actual -> assertEquals(normalizeOutput("" to ExitCode.OK), actual) },
manifest: Manifest? = null,
vararg extraClassPath: File
extraClassPath: List<File> = emptyList()
): File {
val sourceDir = File(testDataDirectory, libraryName)
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
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))
}
@@ -438,7 +438,7 @@ class CompileKotlinAgainstCustomBinariesTest : AbstractKotlinCompilerIntegration
fun testReplaceAnnotationClassWithInterface() {
val library1 = compileLibrary("library-1")
val usage = compileLibrary("usage", extraClassPath = *arrayOf(library1))
val usage = compileLibrary("usage", extraClassPath = listOf(library1))
val library2 = compileLibrary("library-2")
doTestWithTxt(usage, library2)
}
@@ -507,7 +507,7 @@ class CompileKotlinAgainstCustomBinariesTest : AbstractKotlinCompilerIntegration
val version = intArrayOf(1, 0, 1) // legacy coroutines metadata
val options = listOf("-language-version", "1.2", "-Xcoroutines=enable")
val library = transformJar(
compileLibrary("library", additionalOptions = options),
compileLibrary("library", additionalOptions = options, extraClassPath = listOf(ForTestCompileRuntime.coroutinesCompatForTests())),
{ _, bytes ->
val (resultBytes, removedCounter) = stripSuspensionMarksToImitateLegacyCompiler(
WrongBytecodeVersionTest.transformMetadataInClassFile(bytes) { name, _ ->
@@ -518,11 +518,11 @@ class CompileKotlinAgainstCustomBinariesTest : AbstractKotlinCompilerIntegration
resultBytes
})
compileKotlin(
"source.kt", tmpdir, listOf(library), K2JVMCompiler(),
"source.kt", tmpdir, listOf(library, ForTestCompileRuntime.coroutinesCompatForTests()), K2JVMCompiler(),
additionalOptions = options
)
val classLoader = URLClassLoader(
arrayOf(library.toURI().toURL(), tmpdir.toURI().toURL()),
arrayOf(library.toURI().toURL(), tmpdir.toURI().toURL(), ForTestCompileRuntime.coroutinesCompatForTests().toURI().toURL()),
ForTestCompileRuntime.runtimeJarClassLoader()
)
@Suppress("UNCHECKED_CAST")
@@ -576,12 +576,13 @@ class CompileKotlinAgainstCustomBinariesTest : AbstractKotlinCompilerIntegration
val library = compileLibrary(
"library",
additionalOptions = listOf("-language-version", "1.2"),
checkKotlinOutput = {}
checkKotlinOutput = {},
extraClassPath = listOf(ForTestCompileRuntime.coroutinesCompatForTests())
)
compileKotlin(
"release.kt",
tmpdir,
listOf(library),
listOf(library, ForTestCompileRuntime.coroutinesCompatForTests()),
additionalOptions = listOf("-language-version", "1.3", "-api-version", "1.3")
)
}