Various fixes to KonanTest:
- Filter by language version - Coroutines helpers - Use experimental language flags - Exclude unsigned types
This commit is contained in:
committed by
Pavel Punegov
parent
6b6a0daf61
commit
e717f45da1
@@ -20,10 +20,9 @@ import groovy.json.JsonOutput
|
|||||||
import org.gradle.api.tasks.JavaExec
|
import org.gradle.api.tasks.JavaExec
|
||||||
import org.gradle.api.tasks.TaskAction
|
import org.gradle.api.tasks.TaskAction
|
||||||
import org.gradle.process.ExecResult
|
import org.gradle.process.ExecResult
|
||||||
import org.jetbrains.kotlin.konan.target.*
|
|
||||||
import org.jetbrains.kotlin.konan.properties.*
|
|
||||||
|
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
import java.nio.file.Paths
|
||||||
import java.util.regex.Pattern
|
import java.util.regex.Pattern
|
||||||
|
|
||||||
abstract class KonanTest extends JavaExec {
|
abstract class KonanTest extends JavaExec {
|
||||||
@@ -119,6 +118,7 @@ abstract class KonanTest extends JavaExec {
|
|||||||
if (enableKonanAssertions) {
|
if (enableKonanAssertions) {
|
||||||
args "-ea"
|
args "-ea"
|
||||||
}
|
}
|
||||||
|
println(args)
|
||||||
standardOutput = log
|
standardOutput = log
|
||||||
errorOutput = log
|
errorOutput = log
|
||||||
super.exec()
|
super.exec()
|
||||||
@@ -181,6 +181,57 @@ fun handleExceptionContinuation(x: (Throwable) -> Unit): Continuation<Any?> = ob
|
|||||||
createFile(file, text.toString())
|
createFile(file, text.toString())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
String createTextForHelpers() {
|
||||||
|
def coroutinesPackage = "kotlin.coroutines.experimental"
|
||||||
|
|
||||||
|
def emptyContinuationBody =
|
||||||
|
"""
|
||||||
|
|override fun resume(data: Any?) {}
|
||||||
|
|override fun resumeWithException(exception: Throwable) { throw exception }
|
||||||
|
""".stripMargin()
|
||||||
|
|
||||||
|
def handleResultContinuationBody = """
|
||||||
|
|override fun resumeWithException(exception: Throwable) {
|
||||||
|
| throw exception
|
||||||
|
|}
|
||||||
|
|
|
||||||
|
|override fun resume(data: T) = x(data)
|
||||||
|
""".stripMargin()
|
||||||
|
|
||||||
|
def handleExceptionContinuationBody = """
|
||||||
|
|override fun resumeWithException(exception: Throwable) {
|
||||||
|
| x(exception)
|
||||||
|
|}
|
||||||
|
|
|
||||||
|
|override fun resume(data: Any?) {}
|
||||||
|
""".stripMargin()
|
||||||
|
|
||||||
|
return """
|
||||||
|
|package helpers
|
||||||
|
|import $coroutinesPackage.*
|
||||||
|
|
|
||||||
|
|fun <T> handleResultContinuation(x: (T) -> Unit): Continuation<T> = object: Continuation<T> {
|
||||||
|
| override val context = EmptyCoroutineContext
|
||||||
|
| $handleResultContinuationBody
|
||||||
|
|}
|
||||||
|
|
|
||||||
|
|
|
||||||
|
|fun handleExceptionContinuation(x: (Throwable) -> Unit): Continuation<Any?> = object: Continuation<Any?> {
|
||||||
|
| override val context = EmptyCoroutineContext
|
||||||
|
| $handleExceptionContinuationBody
|
||||||
|
|}
|
||||||
|
|
|
||||||
|
|open class EmptyContinuation(override val context: CoroutineContext = EmptyCoroutineContext) : Continuation<Any?> {
|
||||||
|
| companion object : EmptyContinuation()
|
||||||
|
| $emptyContinuationBody
|
||||||
|
|}
|
||||||
|
|
|
||||||
|
|abstract class ContinuationAdapter<in T> : Continuation<T> {
|
||||||
|
| override val context: CoroutineContext = EmptyCoroutineContext
|
||||||
|
|}
|
||||||
|
""".stripMargin()
|
||||||
|
}
|
||||||
|
|
||||||
// TODO refactor
|
// TODO refactor
|
||||||
List<String> buildCompileList() {
|
List<String> buildCompileList() {
|
||||||
def result = []
|
def result = []
|
||||||
@@ -192,7 +243,12 @@ fun handleExceptionContinuation(x: (Throwable) -> Unit): Continuation<Any?> = ob
|
|||||||
if (srcText.contains('// WITH_COROUTINES')) {
|
if (srcText.contains('// WITH_COROUTINES')) {
|
||||||
def coroutineUtilFileName = "$outputDirectory/CoroutineUtil.kt"
|
def coroutineUtilFileName = "$outputDirectory/CoroutineUtil.kt"
|
||||||
createCoroutineUtil(coroutineUtilFileName)
|
createCoroutineUtil(coroutineUtilFileName)
|
||||||
|
|
||||||
|
def coroutineHelpersFileName = "$outputDirectory/helpers.kt"
|
||||||
|
createFile(coroutineHelpersFileName, createTextForHelpers())
|
||||||
|
|
||||||
result.add(coroutineUtilFileName)
|
result.add(coroutineUtilFileName)
|
||||||
|
result.add(coroutineHelpersFileName)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!matcher.find()) {
|
if (!matcher.find()) {
|
||||||
@@ -217,7 +273,12 @@ fun handleExceptionContinuation(x: (Throwable) -> Unit): Continuation<Any?> = ob
|
|||||||
}
|
}
|
||||||
|
|
||||||
void createFile(String file, String text) {
|
void createFile(String file, String text) {
|
||||||
project.file(file).write(text)
|
Paths.get(file).with {
|
||||||
|
getParent().toFile().with {
|
||||||
|
if (!exists()) { mkdirs() }
|
||||||
|
}
|
||||||
|
write(text)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@TaskAction
|
@TaskAction
|
||||||
@@ -631,6 +692,23 @@ class RunExternalTestGroup extends RunStandaloneKonanTest {
|
|||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void parseLanguageFlags() {
|
||||||
|
def text = project.file(source).text
|
||||||
|
def languageSettings = findLinesWithPrefixesRemoved(text, "// !LANGUAGE: ")
|
||||||
|
if (languageSettings.size() != 0) {
|
||||||
|
languageSettings.forEach { line ->
|
||||||
|
line.split(" ").toList().forEach { flags.add("-XXLanguage:$it") }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
def experimentalSettings = findLinesWithPrefixesRemoved(text, "// !USE_EXPERIMENTAL: ")
|
||||||
|
if (experimentalSettings.size() != 0) {
|
||||||
|
experimentalSettings.forEach { line ->
|
||||||
|
line.split(" ").toList().forEach { flags.add("-Xuse-experimental=$it") }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
List<String> createTestFiles() {
|
List<String> createTestFiles() {
|
||||||
def identifier = /[a-zA-Z_][a-zA-Z0-9_]/
|
def identifier = /[a-zA-Z_][a-zA-Z0-9_]/
|
||||||
def fullQualified = /[a-zA-Z_][a-zA-Z0-9_.]/
|
def fullQualified = /[a-zA-Z_][a-zA-Z0-9_.]/
|
||||||
@@ -641,14 +719,14 @@ class RunExternalTestGroup extends RunStandaloneKonanTest {
|
|||||||
def classPattern = ~/.*(class|object|enum)\s+(${identifier}*).*/
|
def classPattern = ~/.*(class|object|enum)\s+(${identifier}*).*/
|
||||||
|
|
||||||
def sourceName = "_" + normalize(project.file(source).name)
|
def sourceName = "_" + normalize(project.file(source).name)
|
||||||
def packages = new LinkedHashSet()
|
def packages = new LinkedHashSet<String>()
|
||||||
def imports = []
|
def imports = []
|
||||||
|
|
||||||
def result = super.buildCompileList()
|
def result = super.buildCompileList()
|
||||||
for (String filePath : result) {
|
for (String filePath : result) {
|
||||||
def text = project.file(filePath).text
|
def text = project.file(filePath).text
|
||||||
if (text.contains('COROUTINES_PACKAGE')) {
|
if (text.contains('COROUTINES_PACKAGE')) {
|
||||||
text.replaceAll('COROUTINES_PACKAGE', 'kotlin.coroutines.experimental')
|
text = text.replace('COROUTINES_PACKAGE', 'kotlin.coroutines.experimental')
|
||||||
}
|
}
|
||||||
def pkg = null
|
def pkg = null
|
||||||
if (text =~ packagePattern) {
|
if (text =~ packagePattern) {
|
||||||
@@ -704,11 +782,15 @@ class RunExternalTestGroup extends RunStandaloneKonanTest {
|
|||||||
text = (pkg ? "$pkg\n" : "") + "import $sourceName.*\n" + text
|
text = (pkg ? "$pkg\n" : "") + "import $sourceName.*\n" + text
|
||||||
}
|
}
|
||||||
// now replace all package usages in full qualified names
|
// now replace all package usages in full qualified names
|
||||||
def res = ""
|
def res = "" // result
|
||||||
text.eachLine {
|
def vars = new HashSet<String>() // variables that has the same name as a package
|
||||||
def line = it
|
text.eachLine { line ->
|
||||||
packages.each { String pkg ->
|
packages.each { pkg ->
|
||||||
if (line.contains("$pkg.") && ! (line =~ packagePattern || line =~ importRegex)) {
|
if (line =~ ~/va(l|r) *$pkg *\=/) {
|
||||||
|
vars.add(pkg)
|
||||||
|
}
|
||||||
|
if (line.contains("$pkg.") && ! (line =~ packagePattern || line =~ importRegex)
|
||||||
|
&& ! vars.contains(pkg)) {
|
||||||
def idx = line.indexOf("$pkg")
|
def idx = line.indexOf("$pkg")
|
||||||
if (! (idx > 0 && Character.isJavaIdentifierPart(line.charAt(idx - 1))) ) {
|
if (! (idx > 0 && Character.isJavaIdentifierPart(line.charAt(idx - 1))) ) {
|
||||||
line = line.substring(0, idx) + "$sourceName.$pkg" + line.substring(idx + pkg.length())
|
line = line.substring(0, idx) + "$sourceName.$pkg" + line.substring(idx + pkg.length())
|
||||||
@@ -768,6 +850,19 @@ fun runTest() {
|
|||||||
|
|
||||||
boolean isEnabledForNativeBackend(String fileName) {
|
boolean isEnabledForNativeBackend(String fileName) {
|
||||||
def text = project.file(fileName).text
|
def text = project.file(fileName).text
|
||||||
|
|
||||||
|
def unsigned = findLinesWithPrefixesRemoved(text, '// WITH_UNSIGNED')
|
||||||
|
if (unsigned.size() != 0) {
|
||||||
|
// Unsigned types are not yet supported
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
def version = findLinesWithPrefixesRemoved(text, '// LANGUAGE_VERSION: ')
|
||||||
|
if (version.size() != 0 && version.contains("1.3")) {
|
||||||
|
// 1.3 is not yet supported
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
def targetBackend = findLinesWithPrefixesRemoved(text, "// TARGET_BACKEND")
|
def targetBackend = findLinesWithPrefixesRemoved(text, "// TARGET_BACKEND")
|
||||||
if (targetBackend.size() != 0) {
|
if (targetBackend.size() != 0) {
|
||||||
// There is some target backend. Check if it is NATIVE or not.
|
// There is some target backend. Check if it is NATIVE or not.
|
||||||
@@ -834,6 +929,7 @@ fun runTest() {
|
|||||||
// Create separate output directory for each test in the group.
|
// Create separate output directory for each test in the group.
|
||||||
outputDirectory = outputRootDirectory + "/${it.name}"
|
outputDirectory = outputRootDirectory + "/${it.name}"
|
||||||
project.file(outputDirectory).mkdirs()
|
project.file(outputDirectory).mkdirs()
|
||||||
|
parseLanguageFlags()
|
||||||
compileList.addAll(createTestFiles())
|
compileList.addAll(createTestFiles())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -863,11 +959,13 @@ fun runTest() {
|
|||||||
testCase.start()
|
testCase.start()
|
||||||
if (isEnabledForNativeBackend(source)) {
|
if (isEnabledForNativeBackend(source)) {
|
||||||
try {
|
try {
|
||||||
|
println(source)
|
||||||
super.executeTest()
|
super.executeTest()
|
||||||
currentResult = testCase.pass()
|
currentResult = testCase.pass()
|
||||||
} catch (TestFailedException e) {
|
} catch (TestFailedException e) {
|
||||||
currentResult = testCase.fail(e)
|
currentResult = testCase.fail(e)
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
|
ex.printStackTrace()
|
||||||
currentResult = testCase.error(ex)
|
currentResult = testCase.error(ex)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
Reference in New Issue
Block a user