[Spec tests] Make main link nullable for case if implementation tests don't have this one
This commit is contained in:
+4
-3
@@ -15,7 +15,6 @@ import org.jetbrains.kotlin.spec.utils.spec.SpecSentencesStorage
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import java.io.File
|
||||
import kotlin.io.walkTopDown
|
||||
|
||||
@TestDataPath("\$PROJECT_ROOT/compiler/tests-spec/testData/")
|
||||
@RunWith(com.intellij.testFramework.Parameterized::class)
|
||||
@@ -55,8 +54,9 @@ class SpecTestsConsistencyTest : TestCase() {
|
||||
val file = File("${GeneralConfiguration.SPEC_TESTDATA_PATH}/${testFilePath.replace("$", "/")}")
|
||||
val specSentences = specSentencesStorage.getLatest() ?: return
|
||||
val test = parseLinkedSpecTest(file.canonicalPath, mapOf("main" to file.readText()))
|
||||
val sectionsPath = setOf(*test.place.sections.toTypedArray(), test.place.paragraphNumber).joinToString()
|
||||
val sentenceNumber = test.place.sentenceNumber
|
||||
if (test.mainLink == null) return //todo add check for relevant links also
|
||||
val sectionsPath = setOf(*test.mainLink.sections.toTypedArray(), test.mainLink.paragraphNumber).joinToString()
|
||||
val sentenceNumber = test.mainLink.sentenceNumber
|
||||
val paragraphSentences = specSentences[sectionsPath]
|
||||
|
||||
if (paragraphSentences != null && paragraphSentences.size >= sentenceNumber) {
|
||||
@@ -76,5 +76,6 @@ class SpecTestsConsistencyTest : TestCase() {
|
||||
|
||||
assertEquals(expectedSentence, actualSentence)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
+40
-34
@@ -35,7 +35,7 @@ object TestsJsonMapGenerator {
|
||||
return testsByType.getOrCreate(specPlace.sentenceNumber.toString())
|
||||
}
|
||||
|
||||
enum class LinkType{
|
||||
enum class LinkType {
|
||||
MAIN,
|
||||
PRIMARY,
|
||||
SECONDARY;
|
||||
@@ -44,6 +44,7 @@ object TestsJsonMapGenerator {
|
||||
return name.toLowerCase()
|
||||
}
|
||||
}
|
||||
|
||||
private fun getTestInfo(test: LinkedSpecTest, testFile: File? = null, linkType: LinkType = LinkType.MAIN) =
|
||||
JsonObject().apply {
|
||||
addProperty("specVersion", test.specVersion)
|
||||
@@ -57,6 +58,29 @@ object TestsJsonMapGenerator {
|
||||
addProperty("linkType", linkType.toString())
|
||||
}
|
||||
|
||||
|
||||
private fun collectInfoFromTests(
|
||||
testsMap: JsonObject,
|
||||
testDataPath: String,
|
||||
linkedTestsPath: String = ""
|
||||
) {
|
||||
TestArea.values().forEach { testArea ->
|
||||
val filePath = buildString {
|
||||
append("${testDataPath}/${testArea.testDataPath}")
|
||||
if (linkedTestsPath.isNotEmpty())
|
||||
append("/${linkedTestsPath}")
|
||||
}
|
||||
File(filePath).walkTopDown()
|
||||
.forEach testFiles@{ file ->
|
||||
if (!file.isFile || file.extension != "kt" || file.name.endsWith(".fir.kt")) return@testFiles
|
||||
val (specTest, _) = CommonParser.parseSpecTest(file.canonicalPath, mapOf("main.kt" to file.readText()))
|
||||
if (specTest is LinkedSpecTest) {
|
||||
collectInfoFromTests(testsMap = testsMap, specTest = specTest, file = file)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun collectInfoFromSpecTests(testsMap: JsonObject) {
|
||||
TestArea.values().forEach { testArea ->
|
||||
File("${GeneralConfiguration.SPEC_TESTDATA_PATH}/${testArea.testDataPath}/$LINKED_TESTS_PATH").walkTopDown()
|
||||
@@ -64,13 +88,7 @@ object TestsJsonMapGenerator {
|
||||
if (!file.isFile || file.extension != "kt" || file.name.endsWith(".fir.kt")) return@testFiles
|
||||
val (specTest, _) = CommonParser.parseSpecTest(file.canonicalPath, mapOf("main.kt" to file.readText()))
|
||||
if (specTest is LinkedSpecTest) {
|
||||
collectInfoFromTestsTemp(
|
||||
testsMap = testsMap,
|
||||
specTest = specTest,
|
||||
testInfoForMainLink = getTestInfo(specTest, file, LinkType.MAIN),
|
||||
testInfoForPrimaryLink = getTestInfo(specTest, file, LinkType.PRIMARY),
|
||||
testInfoForSecondaryLink = getTestInfo(specTest, file, LinkType.SECONDARY)
|
||||
)
|
||||
collectInfoFromTests(testsMap = testsMap, specTest = specTest, file = file)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -83,46 +101,34 @@ object TestsJsonMapGenerator {
|
||||
if (!file.isFile || file.extension != "kt") return@testFiles
|
||||
if (!LinkedSpecTestPatterns.testInfoPattern.matcher(file.readText()).find())
|
||||
return@testFiles
|
||||
val (specTest, _) = CommonParser.parseImplTest(file.canonicalPath, mapOf("main.kt" to file.readText()))
|
||||
collectInfoFromTests(testsMap, specTest, getTestInfo(specTest, file))
|
||||
val (specTest, _) = CommonParser.parseSpecTest(file.canonicalPath, mapOf("main.kt" to file.readText()), true)
|
||||
if (specTest is LinkedSpecTest) {
|
||||
collectInfoFromTests(testsMap = testsMap, specTest = specTest, file = file)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun collectInfoFromTests(
|
||||
testsMap: JsonObject,
|
||||
specTest: LinkedSpecTest,
|
||||
testInfoForMainLink: JsonObject,
|
||||
testInfoForRelevantLink: JsonObject = testInfoForMainLink
|
||||
) {
|
||||
testsMap.getOrCreateSpecTestObject(specTest.place, specTest.testArea, specTest.testType).add(testInfoForMainLink)
|
||||
specTest.primaryLinks?.forEach {
|
||||
testsMap.getOrCreateSpecTestObject(it, specTest.testArea, specTest.testType).add(testInfoForRelevantLink)
|
||||
}
|
||||
specTest.secondaryLinks?.forEach {
|
||||
testsMap.getOrCreateSpecTestObject(it, specTest.testArea, specTest.testType).add(testInfoForRelevantLink)
|
||||
}
|
||||
}
|
||||
|
||||
private fun collectInfoFromTestsTemp( //todo add same for implementation tests
|
||||
testsMap: JsonObject,
|
||||
specTest: LinkedSpecTest,
|
||||
testInfoForMainLink: JsonObject,
|
||||
testInfoForPrimaryLink: JsonObject = testInfoForMainLink,
|
||||
testInfoForSecondaryLink: JsonObject = testInfoForMainLink
|
||||
private fun collectInfoFromTests(
|
||||
testsMap: JsonObject, specTest: LinkedSpecTest, file: File
|
||||
) {
|
||||
testsMap.getOrCreateSpecTestObject(specTest.place, specTest.testArea, specTest.testType).add(testInfoForMainLink)
|
||||
|
||||
if (specTest.mainLink != null)
|
||||
testsMap.getOrCreateSpecTestObject(specTest.mainLink, specTest.testArea, specTest.testType)
|
||||
.add(getTestInfo(specTest, file, LinkType.MAIN))
|
||||
specTest.primaryLinks?.forEach {
|
||||
testsMap.getOrCreateSpecTestObject(it, specTest.testArea, specTest.testType).add(testInfoForPrimaryLink)
|
||||
testsMap.getOrCreateSpecTestObject(it, specTest.testArea, specTest.testType).add(getTestInfo(specTest, file, LinkType.PRIMARY))
|
||||
}
|
||||
specTest.secondaryLinks?.forEach {
|
||||
testsMap.getOrCreateSpecTestObject(it, specTest.testArea, specTest.testType).add(testInfoForSecondaryLink)
|
||||
testsMap.getOrCreateSpecTestObject(it, specTest.testArea, specTest.testType)
|
||||
.add(getTestInfo(specTest, file, LinkType.SECONDARY))
|
||||
}
|
||||
}
|
||||
|
||||
fun buildTestsMapPerSection() {
|
||||
val testsMap = JsonObject().apply {
|
||||
collectInfoFromSpecTests(this)
|
||||
collectInfoFromTests(this, GeneralConfiguration.SPEC_TESTDATA_PATH, LINKED_TESTS_PATH)
|
||||
collectInfoFromImplementationTests(this)
|
||||
}
|
||||
|
||||
|
||||
+28
-10
@@ -10,12 +10,12 @@ import org.jetbrains.kotlin.spec.utils.SpecTestCasesSet
|
||||
import org.jetbrains.kotlin.spec.utils.SpecTestInfoElementType
|
||||
import org.jetbrains.kotlin.spec.utils.TestArea
|
||||
import org.jetbrains.kotlin.spec.utils.TestType
|
||||
import org.jetbrains.kotlin.spec.utils.parsers.LinkedSpecTestPatterns.mainLinkPattern
|
||||
import org.jetbrains.kotlin.spec.utils.parsers.LinkedSpecTestPatterns.relevantLinksPattern
|
||||
import org.jetbrains.kotlin.spec.utils.parsers.CommonParser.splitByPathSeparator
|
||||
import org.jetbrains.kotlin.spec.utils.parsers.CommonParser.withSpaces
|
||||
import org.jetbrains.kotlin.spec.utils.parsers.CommonParser.withUnderscores
|
||||
import org.jetbrains.kotlin.spec.utils.parsers.CommonParser.splitByPathSeparator
|
||||
import org.jetbrains.kotlin.spec.utils.parsers.CommonPatterns.ls
|
||||
import org.jetbrains.kotlin.spec.utils.parsers.LinkedSpecTestPatterns.mainLinkPattern
|
||||
import org.jetbrains.kotlin.spec.utils.parsers.LinkedSpecTestPatterns.relevantLinksPattern
|
||||
import java.util.regex.Matcher
|
||||
import java.util.regex.Pattern
|
||||
|
||||
@@ -40,7 +40,7 @@ class LinkedSpecTest(
|
||||
val specVersion: String,
|
||||
testArea: TestArea,
|
||||
testType: TestType,
|
||||
val place: SpecPlace,
|
||||
val mainLink: SpecPlace?,
|
||||
val primaryLinks: Set<SpecPlace>?,
|
||||
val secondaryLinks: Set<SpecPlace>?,
|
||||
testNumber: Int,
|
||||
@@ -51,14 +51,25 @@ class LinkedSpecTest(
|
||||
issues: Set<String>,
|
||||
helpers: Set<String>?,
|
||||
exception: TestsExceptionType?
|
||||
) : AbstractSpecTest(testArea, testType, place.sections, testNumber, description, cases, unexpectedBehavior, issues, helpers, exception) {
|
||||
) : AbstractSpecTest(
|
||||
testArea,
|
||||
testType,
|
||||
mainLink?.sections ?: listOf(),
|
||||
testNumber,
|
||||
description,
|
||||
cases,
|
||||
unexpectedBehavior,
|
||||
issues,
|
||||
helpers,
|
||||
exception
|
||||
) {
|
||||
|
||||
override fun checkPathConsistency(pathMatcher: Matcher) =
|
||||
testArea == TestArea.valueOf(pathMatcher.group("testArea").withUnderscores())
|
||||
&& testType == TestType.fromValue(pathMatcher.group("testType"))!!
|
||||
&& sections == pathMatcher.group("sections").splitByPathSeparator()
|
||||
&& place.paragraphNumber == pathMatcher.group("paragraphNumber").toInt()
|
||||
&& place.sentenceNumber == pathMatcher.group("sentenceNumber").toInt()
|
||||
&& mainLink?.paragraphNumber == pathMatcher.group("paragraphNumber").toInt()
|
||||
&& mainLink.sentenceNumber == pathMatcher.group("sentenceNumber").toInt()
|
||||
&& testNumber == pathMatcher.group("testNumber").toInt()
|
||||
|
||||
private fun getUnspecifiedBehaviourText(): String? {
|
||||
@@ -80,12 +91,19 @@ class LinkedSpecTest(
|
||||
super.getUnexpectedBehaviourText()?.let { append(it + ls) }
|
||||
append("${testArea.name.withSpaces()} $testType SPEC TEST (${testType.toString().withSpaces()})$ls")
|
||||
append("SPEC VERSION: $specVersion$ls")
|
||||
append("SPEC PLACE: ${sections.joinToString()} -> paragraph: ${place.paragraphNumber} -> sentence: ${place.sentenceNumber}$ls")
|
||||
primaryLinks?.let { append("PRIMARY LINKS:${it.joinToString { "$ls\t${sections.joinToString()} -> paragraph: ${place.paragraphNumber} -> sentence: ${place.sentenceNumber}" }}$ls") }
|
||||
secondaryLinks?.let { append("SECONDARY LINKS:${it.joinToString { "$ls\t${sections.joinToString()} -> paragraph: ${place.paragraphNumber} -> sentence: ${place.sentenceNumber}" }}$ls") }
|
||||
mainLink?.let { append("MAIN LINK: ${sections.joinToString()} -> paragraph: ${mainLink.paragraphNumber} -> sentence: ${mainLink.sentenceNumber}$ls") }
|
||||
primaryLinks?.let { append("PRIMARY LINKS: ${primaryLinks.buildToString()}$ls") }
|
||||
secondaryLinks?.let { append("SECONDARY LINKS: ${secondaryLinks.buildToString()}$ls") }
|
||||
append("NUMBER: $testNumber$ls")
|
||||
append("TEST CASES: ${cases.byNumbers.size.coerceAtLeast(1)}$ls")
|
||||
append("DESCRIPTION: $description$ls")
|
||||
super.getIssuesText()?.let { append(it + ls) }
|
||||
}
|
||||
|
||||
private fun Set<SpecPlace>.buildToString(): String = buildString {
|
||||
this@buildToString.forEach {
|
||||
append("${sections.joinToString()} -> paragraph: ${it.paragraphNumber} -> sentence: ${it.sentenceNumber}$ls")
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -35,14 +35,13 @@ object CommonParser {
|
||||
private fun parseBasePath(pathPartRegex: String, testFilePath: String) =
|
||||
Pattern.compile(testPathBaseRegexTemplate.format(pathPartRegex)).matcher(testFilePath)
|
||||
|
||||
fun parseImplTest(testFilePath: String, files: TestFiles): Pair<LinkedSpecTest, SpecTestLinkedType> =
|
||||
Pair(parseLinkedSpecTest(testFilePath, files, isImplementationTest = true), SpecTestLinkedType.LINKED)
|
||||
|
||||
fun parseSpecTest(testFilePath: String, files: TestFiles) = when {
|
||||
fun parseSpecTest(testFilePath: String, files: TestFiles, isImplementationTest: Boolean = false) = when {
|
||||
isPathMatched(LinkedSpecTestPatterns.pathPartRegex, testFilePath) ->
|
||||
Pair(parseLinkedSpecTest(testFilePath, files), SpecTestLinkedType.LINKED)
|
||||
isPathMatched(NotLinkedSpecTestPatterns.pathPartRegex, testFilePath) ->
|
||||
Pair(parseNotLinkedSpecTest(testFilePath, files), SpecTestLinkedType.NOT_LINKED)
|
||||
isImplementationTest ->
|
||||
Pair(parseLinkedSpecTest(testFilePath, files, true), SpecTestLinkedType.LINKED)
|
||||
else ->
|
||||
throw SpecTestValidationException(SpecTestValidationFailedReason.FILENAME_NOT_VALID)
|
||||
}
|
||||
@@ -54,51 +53,38 @@ object CommonParser {
|
||||
placeMatcher.group("sentenceNumber").toInt()
|
||||
)
|
||||
|
||||
private fun parseRelevantPlaces(
|
||||
placesMatcher: Matcher?,
|
||||
relevantPlaces: MutableSet<SpecPlace>
|
||||
) {
|
||||
if (placesMatcher == null)
|
||||
return
|
||||
placesMatcher?.let {
|
||||
relevantPlaces.add(createSpecPlace(it, placesMatcher))
|
||||
while (it.find()) {
|
||||
relevantPlaces.add(createSpecPlace(it, placesMatcher))
|
||||
class RelevantLinks(linksMatcher: Matcher?) {
|
||||
val linksSet: MutableSet<SpecPlace> = mutableSetOf()
|
||||
|
||||
init {
|
||||
if (linksMatcher != null) {
|
||||
linksSet.add(createSpecPlace(linksMatcher))
|
||||
while (linksMatcher.find()) {
|
||||
linksSet.add(createSpecPlace(linksMatcher))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fun parseLinkedSpecTest(testFilePath: String, testFiles: TestFiles, isImplementationTest: Boolean = false): LinkedSpecTest {
|
||||
val primaryLinks = mutableSetOf<SpecPlace>()
|
||||
val secondaryLinks = mutableSetOf<SpecPlace>()
|
||||
|
||||
val parsedTestFile = tryParseTestInfo(testFilePath, testFiles, SpecTestLinkedType.LINKED, isImplementationTest)
|
||||
|
||||
val testInfoElements = parsedTestFile.testInfoElements
|
||||
|
||||
parseRelevantPlaces(
|
||||
testInfoElements[LinkedSpecTestFileInfoElementType.PRIMARY_LINKS]?.additionalMatcher,
|
||||
primaryLinks
|
||||
)
|
||||
|
||||
parseRelevantPlaces(
|
||||
testInfoElements[LinkedSpecTestFileInfoElementType.SECONDARY_LINKS]?.additionalMatcher,
|
||||
secondaryLinks
|
||||
)
|
||||
val primaryLinks =
|
||||
RelevantLinks(testInfoElements[LinkedSpecTestFileInfoElementType.PRIMARY_LINKS]?.additionalMatcher).linksSet
|
||||
val secondaryLinks =
|
||||
RelevantLinks(testInfoElements[LinkedSpecTestFileInfoElementType.SECONDARY_LINKS]?.additionalMatcher).linksSet
|
||||
|
||||
val placeMatcher = testInfoElements[LinkedSpecTestFileInfoElementType.MAIN_LINK]?.additionalMatcher
|
||||
|
||||
val mainPlace: SpecPlace
|
||||
if (placeMatcher != null) {
|
||||
mainPlace = createSpecPlace(placeMatcher)
|
||||
} else {
|
||||
mainPlace = primaryLinks.first()
|
||||
primaryLinks.remove(mainPlace)
|
||||
}
|
||||
return LinkedSpecTest(
|
||||
testInfoElements[LinkedSpecTestFileInfoElementType.SPEC_VERSION]!!.content,
|
||||
parsedTestFile.testArea,
|
||||
parsedTestFile.testType,
|
||||
mainPlace,
|
||||
placeMatcher?.let { createSpecPlace(placeMatcher) },
|
||||
primaryLinks,
|
||||
secondaryLinks,
|
||||
parsedTestFile.testNumber,
|
||||
@@ -157,9 +143,9 @@ object CommonParser {
|
||||
rawElements: String,
|
||||
) = when (testInfoOriginalElementName) {
|
||||
LinkedSpecTestPatterns.PRIMARY_LINKS ->
|
||||
groupRelevantAndAlternativePlaces(LinkedSpecTestPatterns.primaryLinks, rawElements, testInfoOriginalElementName)
|
||||
groupRelevantLinks(LinkedSpecTestPatterns.primaryLinks, rawElements, testInfoOriginalElementName)
|
||||
LinkedSpecTestPatterns.SECONDARY_LINKS ->
|
||||
groupRelevantAndAlternativePlaces(LinkedSpecTestPatterns.secondaryLinks, rawElements, testInfoOriginalElementName)
|
||||
groupRelevantLinks(LinkedSpecTestPatterns.secondaryLinks, rawElements, testInfoOriginalElementName)
|
||||
else ->
|
||||
testInfoElementMatcher.group("value")
|
||||
}
|
||||
@@ -204,14 +190,14 @@ object CommonParser {
|
||||
}
|
||||
|
||||
|
||||
private fun groupRelevantAndAlternativePlaces(placesPattern: Pattern, rawElements: String, linkType: String): String {
|
||||
val placesMatcher = placesPattern.matcher(rawElements)
|
||||
private fun groupRelevantLinks(linksPattern: Pattern, rawElements: String, linkType: String): String {
|
||||
val placesMatcher = linksPattern.matcher(rawElements)
|
||||
if (placesMatcher.find()) {
|
||||
return placesMatcher.group("places")
|
||||
} else throw Exception("$linkType link is incorrect")
|
||||
}
|
||||
|
||||
fun testInfoFilter(fileContent: String) =
|
||||
fun testInfoFilter(fileContent: String): String =
|
||||
testInfoPattern.matcher(fileContent).replaceAll("").let {
|
||||
testCaseInfoPattern.matcher(it).replaceAll("")
|
||||
}
|
||||
|
||||
@@ -21,7 +21,6 @@ import org.jetbrains.kotlin.spec.utils.parsers.CommonPatterns.sectionsInPathRege
|
||||
import org.jetbrains.kotlin.spec.utils.parsers.CommonPatterns.testAreaRegex
|
||||
import org.jetbrains.kotlin.spec.utils.parsers.CommonPatterns.testPathRegexTemplate
|
||||
import org.jetbrains.kotlin.spec.utils.parsers.CommonPatterns.testTypeRegex
|
||||
import org.jetbrains.kotlin.spec.utils.parsers.CommonPatterns.ws
|
||||
import java.io.File
|
||||
import java.util.regex.Pattern
|
||||
|
||||
@@ -35,7 +34,6 @@ object CommonPatterns {
|
||||
|
||||
val ls: String = System.lineSeparator()
|
||||
val ps: String = Pattern.quote(File.separator)
|
||||
val ws = """\s*"""
|
||||
|
||||
val directiveRegex =
|
||||
"""${SINGLE_LINE_COMMENT_REGEX.format("""[\w\s]+:""")}|${MULTILINE_COMMENT_REGEX.format(""" $ASTERISK_REGEX [\w\s]+:[\s\S]*?""")}"""
|
||||
@@ -88,8 +86,8 @@ object LinkedSpecTestPatterns : BasePatterns {
|
||||
private val linkRegex =
|
||||
Regex("""(( $ASTERISK_REGEX )?\s*($SECTIONS_IN_FILE_REGEX -> )?(paragraph $INTEGER_REGEX -> )?sentence $INTEGER_REGEX)""")
|
||||
|
||||
val primaryLinks: Pattern = Pattern.compile("""$PRIMARY_LINKS$ws:$ws(?<places>(${linkRegex}(\s)*\n)+)""")
|
||||
val secondaryLinks: Pattern = Pattern.compile("""$SECONDARY_LINKS$ws:$ws(?<places>(${linkRegex}(\s)*\n)+)""")
|
||||
val primaryLinks: Pattern = Pattern.compile("""$PRIMARY_LINKS\s*:\s*(?<places>(${linkRegex}(\s)*\n)+)""")
|
||||
val secondaryLinks: Pattern = Pattern.compile("""$SECONDARY_LINKS\s*:\s*(?<places>(${linkRegex}(\s)*\n)+)""")
|
||||
}
|
||||
|
||||
object TestCasePatterns {
|
||||
|
||||
Reference in New Issue
Block a user