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 {
|
||||
PSI,
|
||||
DIAGNOSTICS,
|
||||
CODEGEN
|
||||
enum class TestArea(val testDataPath: String) {
|
||||
PSI("psi"),
|
||||
DIAGNOSTICS("diagnostics"),
|
||||
CODEGEN_BOX("codegen/box")
|
||||
}
|
||||
|
||||
enum class SpecTestLinkedType {
|
||||
LINKED,
|
||||
NOT_LINKED
|
||||
enum class SpecTestLinkedType(val testDataPath: String) {
|
||||
LINKED("linked"),
|
||||
NOT_LINKED("notLinked")
|
||||
}
|
||||
|
||||
interface SpecTestInfoElementType {
|
||||
@@ -108,15 +108,12 @@ abstract class AbstractSpecTestValidator<T : AbstractSpecTest>(private val testD
|
||||
|
||||
val pathSeparator: String = Pattern.quote(File.separator)
|
||||
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 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 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 testCaseInfoSingleLinePattern: Pattern = Pattern.compile(SINGLELINE_COMMENT_REGEX.format(testCaseInfoRegex))
|
||||
val testCaseInfoMultilinePattern: Pattern = Pattern.compile(MULTILINE_COMMENT_REGEX.format(testCaseInfoRegex))
|
||||
|
||||
Reference in New Issue
Block a user