Add codegen box spec tests support
This commit is contained in:
@@ -0,0 +1,119 @@
|
|||||||
|
// WITH_RUNTIME
|
||||||
|
// WITH_REFLECT
|
||||||
|
// FULL_JDK
|
||||||
|
|
||||||
|
<!PACKAGE!>
|
||||||
|
|
||||||
|
import kotlin.reflect.*
|
||||||
|
import kotlin.reflect.full.*
|
||||||
|
|
||||||
|
fun checkAnnotation(className: String, annotationName: String) =
|
||||||
|
Class.forName(className).annotations.find { it.annotationClass.qualifiedName == annotationName } != null
|
||||||
|
|
||||||
|
fun checkSuperClass(classRef: KClass<*>, superClassName: String) =
|
||||||
|
classRef.superclasses.find { it.qualifiedName == superClassName } != null
|
||||||
|
|
||||||
|
private fun getClassTypeParameter(classRef: KClass<*>, typeParameter: String) =
|
||||||
|
classRef.typeParameters.find { it.name == typeParameter }
|
||||||
|
|
||||||
|
private fun getCallableTypeParameter(callableRef: KCallable<*>, typeParameter: String) =
|
||||||
|
callableRef.typeParameters.find { it.name == typeParameter }
|
||||||
|
|
||||||
|
private fun getParameter(functionRef: KFunction<*>, parameterName: String) =
|
||||||
|
functionRef.parameters.find { it.name == parameterName }
|
||||||
|
|
||||||
|
fun checkClassTypeParameter(classRef: KClass<*>, typeParameter: String) = getClassTypeParameter(classRef, typeParameter) != null
|
||||||
|
|
||||||
|
fun checkClassTypeParameters(classRef: KClass<*>, typeParameters: List<String>) =
|
||||||
|
typeParameters.all { checkClassTypeParameter(classRef, it) }
|
||||||
|
|
||||||
|
fun checkCallableTypeParameter(callableRef: KCallable<*>, typeParameter: String) =
|
||||||
|
getCallableTypeParameter(callableRef, typeParameter) != null
|
||||||
|
|
||||||
|
fun checkCallableTypeParameters(callableRef: KCallable<*>, typeParameters: List<String>) =
|
||||||
|
typeParameters.all { checkCallableTypeParameter(callableRef, it) }
|
||||||
|
|
||||||
|
fun checkTypeUpperBounds(typeParameter: KTypeParameter, typeParameters: List<String>) =
|
||||||
|
typeParameters.all { typeParameterName: String ->
|
||||||
|
typeParameter.upperBounds.find { it.toString() == typeParameterName } != null
|
||||||
|
}
|
||||||
|
|
||||||
|
fun checkClassTypeParametersWithUpperBounds(classRef: KClass<*>, typeParameters: List<Pair<String, List<String>>>) =
|
||||||
|
typeParameters.all { (parameterName, parameterUpperBounds) ->
|
||||||
|
getClassTypeParameter(classRef, parameterName).let { typeParameter: KTypeParameter? ->
|
||||||
|
typeParameter != null && checkTypeUpperBounds(typeParameter, parameterUpperBounds)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun checkCallableTypeParametersWithUpperBounds(callableRef: KCallable<*>, typeParameters: List<Pair<String, List<String>>>) =
|
||||||
|
typeParameters.all { (parameterName, parameterUpperBounds) ->
|
||||||
|
getCallableTypeParameter(callableRef, parameterName).let { typeParameter: KTypeParameter? ->
|
||||||
|
typeParameter != null && checkTypeUpperBounds(typeParameter, parameterUpperBounds)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun checkSuperTypeAnnotation(classRef: KClass<*>, superClassName: String, annotationName: String): Boolean {
|
||||||
|
val superType = classRef.supertypes.find { it.classifier.toString() == superClassName }
|
||||||
|
|
||||||
|
return superType?.annotations?.find { it.annotationClass.qualifiedName == annotationName } != null ?: false
|
||||||
|
}
|
||||||
|
|
||||||
|
fun checkClassName(ref: KClass<*>, expectedQualifiedName: String) = ref.qualifiedName == expectedQualifiedName
|
||||||
|
|
||||||
|
fun checkPackageName(fileClass: String, expectedName: String) =
|
||||||
|
Class.forName(fileClass).`package`.name == expectedName
|
||||||
|
|
||||||
|
fun checkFileAnnotation(fileClass: String, expectedName: String) =
|
||||||
|
Class.forName(fileClass)?.annotations?.find { it.annotationClass.qualifiedName == expectedName } != null ?: false
|
||||||
|
|
||||||
|
fun checkFileAnnotations(fileClass: String, expectedNames: List<String>) =
|
||||||
|
expectedNames.all { checkFileAnnotation(fileClass, it) }
|
||||||
|
|
||||||
|
fun checkProperties(classRef: KClass<*>, properties: List<String>) =
|
||||||
|
properties.all { property: String ->
|
||||||
|
classRef.members.find { it.name == property } != null
|
||||||
|
}
|
||||||
|
|
||||||
|
fun checkTypeProperties(classRef: KClass<*>, properties: List<Pair<String, String>>) =
|
||||||
|
properties.all { (propertyName, propertyType) ->
|
||||||
|
classRef.members.find { it.name == propertyName }?.returnType?.toString() == propertyType
|
||||||
|
}
|
||||||
|
|
||||||
|
fun checkPropertiesWithAnnotation(classRef: KClass<*>, properties: List<Pair<String, List<String>>>) =
|
||||||
|
properties.all { (propertyName, propertyAnnotations) ->
|
||||||
|
val foundProperty = classRef.members.find { it.name == propertyName }
|
||||||
|
|
||||||
|
foundProperty.let {
|
||||||
|
it != null && propertyAnnotations.all { expectedAnnotationName: String ->
|
||||||
|
it.annotations.find { it.annotationClass.qualifiedName == expectedAnnotationName } != null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun checkPropertyAnnotation(propertyRef: KProperty<*>, expectedQualifiedName: String) =
|
||||||
|
propertyRef.annotations.find { it.annotationClass.qualifiedName == expectedQualifiedName } != null
|
||||||
|
|
||||||
|
fun checkPropertyType(propertyRef: KProperty<*>, expectedType: String) =
|
||||||
|
propertyRef.returnType.toString() == expectedType
|
||||||
|
|
||||||
|
fun checkFunctionAnnotation(functionRef: KFunction<*>, expectedQualifiedName: String) =
|
||||||
|
functionRef.annotations.find { it.annotationClass.qualifiedName == expectedQualifiedName } != null
|
||||||
|
|
||||||
|
fun checkCompanionObjectName(classRef: KClass<*>, expectedQualifiedName: String) =
|
||||||
|
classRef.companionObject?.qualifiedName == expectedQualifiedName
|
||||||
|
|
||||||
|
fun checkFunctionName(functionRef: KFunction<*>, expectedQualifiedName: String) = functionRef.name == expectedQualifiedName
|
||||||
|
|
||||||
|
fun checkSetterParameterName(propertyRef: KMutableProperty<*>, expectedName: String) =
|
||||||
|
propertyRef.setter.parameters.find { it.name == expectedName } != null
|
||||||
|
|
||||||
|
fun checkParameterType(functionRef: KFunction<*>, parameterName: String, expectedType: String) =
|
||||||
|
getParameter(functionRef, parameterName)?.type.toString() == expectedType ?: false
|
||||||
|
|
||||||
|
fun checkParameter(functionRef: KFunction<*>, parameterName: String) =
|
||||||
|
getParameter(functionRef, parameterName) != null
|
||||||
|
|
||||||
|
fun checkParameters(functionRef: KFunction<*>, parameterNames: List<String>) =
|
||||||
|
parameterNames.all { checkParameter(functionRef, it) }
|
||||||
|
|
||||||
|
fun checkCallableName(property: KCallable<*>, propertyName: String) = property.name == propertyName
|
||||||
+65
@@ -0,0 +1,65 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||||
|
* that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.codegen
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.spec.utils.GeneralConfiguration.TESTDATA_PATH
|
||||||
|
import java.io.File
|
||||||
|
import org.jetbrains.kotlin.spec.validators.AbstractSpecTestValidator
|
||||||
|
import org.jetbrains.kotlin.spec.validators.SpecTestValidationException
|
||||||
|
import org.jetbrains.kotlin.test.InTextDirectivesUtils
|
||||||
|
import org.junit.Assert
|
||||||
|
import java.util.regex.Pattern
|
||||||
|
|
||||||
|
abstract class AbstractBlackBoxCodegenTestSpec : AbstractBlackBoxCodegenTest() {
|
||||||
|
companion object {
|
||||||
|
private const val CODEGEN_BOX_TESTDATA_PATH = "$TESTDATA_PATH/codegen/box"
|
||||||
|
private const val HELPERS_PATH = "$CODEGEN_BOX_TESTDATA_PATH/helpers"
|
||||||
|
private const val HELPERS_PACKAGE_VARIABLE = "<!PACKAGE!>"
|
||||||
|
private const val HELPERS_DIRECTIVE = "// HELPERS:"
|
||||||
|
|
||||||
|
// map of pairs: source helper filename - target helper filename
|
||||||
|
private val helperDirectives = mapOf(
|
||||||
|
"REFLECT" to "reflect.kt"
|
||||||
|
)
|
||||||
|
private val packagePattern = Pattern.compile("""(?:^|\n)package (?<packageName>.*?)(?:;|\n)""")
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun addPackageDirectiveToHelperFile(helperContent: String, packageName: String?) =
|
||||||
|
helperContent.replace(HELPERS_PACKAGE_VARIABLE, if (packageName == null) "" else "package $packageName")
|
||||||
|
|
||||||
|
private fun includeHelpers(wholeFile: File, files: MutableList<TestFile>) {
|
||||||
|
val fileContent = wholeFile.readText()
|
||||||
|
val helpersSpecified = InTextDirectivesUtils.findListWithPrefixes(fileContent, HELPERS_DIRECTIVE)
|
||||||
|
val packageName = packagePattern.matcher(fileContent).let {
|
||||||
|
if (it.find()) it.group("packageName") else null
|
||||||
|
}
|
||||||
|
|
||||||
|
helpersSpecified.forEach {
|
||||||
|
if (helperDirectives.contains(it)) {
|
||||||
|
val helperContent = File("$HELPERS_PATH/${helperDirectives[it]}").readText()
|
||||||
|
files.add(
|
||||||
|
TestFile(helperDirectives[it]!!, addPackageDirectiveToHelperFile(helperContent, packageName))
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun doMultiFileTest(wholeFile: File, files: MutableList<TestFile>, javaFilesDir: File?) {
|
||||||
|
val testValidator = AbstractSpecTestValidator.getInstanceByType(wholeFile)
|
||||||
|
|
||||||
|
try {
|
||||||
|
testValidator.parseTestInfo()
|
||||||
|
} catch (e: SpecTestValidationException) {
|
||||||
|
Assert.fail(e.description)
|
||||||
|
}
|
||||||
|
|
||||||
|
testValidator.printTestInfo()
|
||||||
|
|
||||||
|
includeHelpers(wholeFile, files)
|
||||||
|
|
||||||
|
super.doMultiFileTest(wholeFile, files, javaFilesDir)
|
||||||
|
}
|
||||||
|
}
|
||||||
+10
-13
@@ -19,15 +19,15 @@ enum class TestType(val type: String) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
enum class TestArea {
|
enum class TestArea(val testDataPath: String) {
|
||||||
PSI,
|
PSI("psi"),
|
||||||
DIAGNOSTICS,
|
DIAGNOSTICS("diagnostics"),
|
||||||
CODEGEN
|
CODEGEN_BOX("codegen/box")
|
||||||
}
|
}
|
||||||
|
|
||||||
enum class SpecTestLinkedType {
|
enum class SpecTestLinkedType(val testDataPath: String) {
|
||||||
LINKED,
|
LINKED("linked"),
|
||||||
NOT_LINKED
|
NOT_LINKED("notLinked")
|
||||||
}
|
}
|
||||||
|
|
||||||
interface SpecTestInfoElementType {
|
interface SpecTestInfoElementType {
|
||||||
@@ -108,15 +108,12 @@ abstract class AbstractSpecTestValidator<T : AbstractSpecTest>(private val testD
|
|||||||
|
|
||||||
val pathSeparator: String = Pattern.quote(File.separator)
|
val pathSeparator: String = Pattern.quote(File.separator)
|
||||||
val lineSeparator: String = System.lineSeparator()
|
val lineSeparator: String = System.lineSeparator()
|
||||||
val testAreaRegex = """(?<testArea>${TestArea.values().joinToString("|")})"""
|
val testAreaRegex = """(?<testArea>${TestArea.values().joinToString("|").replace("_", " ")})"""
|
||||||
val testTypeRegex = """(?<testType>${TestType.values().joinToString("|")})"""
|
val testTypeRegex = """(?<testType>${TestType.values().joinToString("|")})"""
|
||||||
val dirsByLinkedType = mapOf(
|
|
||||||
SpecTestLinkedType.LINKED to "linked",
|
|
||||||
SpecTestLinkedType.NOT_LINKED to "notLinked"
|
|
||||||
)
|
|
||||||
private val testInfoElementPattern: Pattern = Pattern.compile("""\s*(?<name>[A-Z ]+?)(?::\s*(?<value>.*?))?$lineSeparator""")
|
private val testInfoElementPattern: Pattern = Pattern.compile("""\s*(?<name>[A-Z ]+?)(?::\s*(?<value>.*?))?$lineSeparator""")
|
||||||
private val testCaseInfoRegex = """(?<infoElements>CASE DESCRIPTION:[\s\S]*?$lineSeparator)$lineSeparator*"""
|
private val testCaseInfoRegex = """(?<infoElements>CASE DESCRIPTION:[\s\S]*?$lineSeparator)$lineSeparator*"""
|
||||||
private val testPathBaseRegexTemplate = """^.*?$pathSeparator(?<testArea>diagnostics|psi|codegen)$pathSeparator%s"""
|
private val testPathBaseRegexTemplate =
|
||||||
|
"""^.*?$pathSeparator(?<testArea>diagnostics|psi|(?:codegen${pathSeparator}box))$pathSeparator%s"""
|
||||||
val testPathRegexTemplate = """$testPathBaseRegexTemplate$pathSeparator(?<testType>pos|neg)/%s$"""
|
val testPathRegexTemplate = """$testPathBaseRegexTemplate$pathSeparator(?<testType>pos|neg)/%s$"""
|
||||||
val testCaseInfoSingleLinePattern: Pattern = Pattern.compile(SINGLELINE_COMMENT_REGEX.format(testCaseInfoRegex))
|
val testCaseInfoSingleLinePattern: Pattern = Pattern.compile(SINGLELINE_COMMENT_REGEX.format(testCaseInfoRegex))
|
||||||
val testCaseInfoMultilinePattern: Pattern = Pattern.compile(MULTILINE_COMMENT_REGEX.format(testCaseInfoRegex))
|
val testCaseInfoMultilinePattern: Pattern = Pattern.compile(MULTILINE_COMMENT_REGEX.format(testCaseInfoRegex))
|
||||||
|
|||||||
Reference in New Issue
Block a user