From 8014a6509e63c51ef4128f40fabcd236c6e3ea9e Mon Sep 17 00:00:00 2001 From: Nikolay Krasko Date: Fri, 20 Dec 2019 02:24:42 +0300 Subject: [PATCH] Allow to mute JUnit 4 tests with parameters --- .../jetbrains/kotlin/test/muteWithDatabase.kt | 80 +++++++++++++------ 1 file changed, 54 insertions(+), 26 deletions(-) diff --git a/compiler/tests-common/tests/org/jetbrains/kotlin/test/muteWithDatabase.kt b/compiler/tests-common/tests/org/jetbrains/kotlin/test/muteWithDatabase.kt index fff9f24ff19..242c51e083a 100644 --- a/compiler/tests-common/tests/org/jetbrains/kotlin/test/muteWithDatabase.kt +++ b/compiler/tests-common/tests/org/jetbrains/kotlin/test/muteWithDatabase.kt @@ -12,7 +12,6 @@ import org.junit.runners.parameterized.BlockJUnit4ClassRunnerWithParameters import org.junit.runners.parameterized.ParametersRunnerFactory import org.junit.runners.parameterized.TestWithParameters import java.io.File -import java.lang.reflect.Method private class AutoMute( val file: String, @@ -37,24 +36,44 @@ private class MutedTest( @Suppress("unused") val issue: String?, val hasFailFile: Boolean ) { - val methodName = key.substringAfterLast(".", "").replace("`", "").also { - if (it.isEmpty()) throw IllegalArgumentException("Can't get method name") + val methodKey: String + val classNameKey: String + val simpleClassName: String + + init { + val noQuoteKey = key.replace("`", "") + val beforeParamsKey = noQuoteKey.substringBefore("[") + val params = noQuoteKey.substringAfterWithDelimiter("[", "") + + methodKey = (beforeParamsKey.substringAfterLast(".", "") + params) + .also { + if (it.isEmpty()) throw IllegalArgumentException("Can't get method name") + } + + classNameKey = beforeParamsKey.substringBeforeLast(".", "").also { + if (it.isEmpty()) throw IllegalArgumentException("Can't get class name") + } + + simpleClassName = classNameKey.substringAfterLast(".") } - val classNameKey = key.substringBeforeLast(".", "").also { - if (it.isEmpty()) throw IllegalArgumentException("Can't get class name") + + companion object { + fun String.substringAfterWithDelimiter(delimiter: String, missingDelimiterValue: String = this): String { + val index = indexOf(delimiter) + return if (index == -1) missingDelimiterValue else (delimiter + substring(index + 1, length)) + } } - val simpleClassName = classNameKey.substringAfterLast(".") } private class MutedSet(muted: List) { - // Method name -> Simple class name -> List of muted tests + // Method key -> Simple class name -> List of muted tests private val cache: Map>> = muted - .groupBy { it.methodName } // Method name -> List of muted tests + .groupBy { it.methodKey } // Method key -> List of muted tests .mapValues { (_, tests) -> tests.groupBy { it.simpleClassName } } - fun mutedTest(testClass: Class<*>, methodName: String): MutedTest? { - val mutedTests = cache[methodName]?.get(testClass.simpleName) ?: return null + fun mutedTest(testClass: Class<*>, methodKey: String): MutedTest? { + val mutedTests = cache[methodKey]?.get(testClass.simpleName) ?: return null return mutedTests.firstOrNull { mutedTest -> testClass.canonicalName.endsWith(mutedTest.classNameKey) @@ -85,14 +104,21 @@ private fun loadMutedTests(file: File): List { } } +private val MUTE_LINE_PARSE_REGEXP = Regex("^([^,\\[]+)(\\[[^]]+])?(,\\s*)?([^,]+)?(,\\s*)?([^,]+)?$") + private fun parseMutedTest(str: String): MutedTest { - val components = str.splitToSequence(",").map { it.trim() }.toList() + val matchResult = MUTE_LINE_PARSE_REGEXP.matchEntire(str) ?: throw ParseError("Can't parse the line: $str") - val key = components.getOrNull(0) ?: throw ParseError("Test key is absent (1 column): $str") + val methodFull = matchResult.groups[1]?.value ?: throw ParseError("Test key is absent (1 column): $str") + val params = matchResult.groups[2]?.value ?: "" - val issue = components.getOrNull(1) + val key = methodFull + params - val hasFailFile = when (val stateStr = components.getOrNull(2)) { + val issue = matchResult.groups[4]?.value + + val stateStr = matchResult.groups[6]?.value + + val hasFailFile = when (stateStr) { "MUTE", "", null -> false "FAIL" -> true else -> throw ParseError("Invalid state (`$stateStr`), MUTE, FAIL or empty are expected: $str") @@ -115,12 +141,8 @@ internal fun isMutedInDatabase(testCase: TestCase): Boolean { return isMutedInDatabase(testCase.javaClass, testCase.name) } -fun isMutedInDatabase(method: Method): Boolean { - return isMutedInDatabase(method.declaringClass, method.name) -} - -fun isMutedInDatabase(testClass: Class<*>, methodName: String): Boolean { - val mutedTest = mutedSet.mutedTest(testClass, methodName) +fun isMutedInDatabase(testClass: Class<*>, methodKey: String): Boolean { + val mutedTest = mutedSet.mutedTest(testClass, methodKey) return mutedTest != null && !mutedTest.hasFailFile } @@ -152,22 +174,28 @@ internal fun wrapWithMuteInDatabase(testCase: TestCase, f: () -> Unit): (() -> U private fun mutedMessage(key: String) = "MUTED TEST: $key" -private fun testKey(testCase: TestCase) = "${testCase::class.java.canonicalName}.${testCase.name}" -private fun testKey(method: Method) = "${method.declaringClass.canonicalName}.${method.name}" +private fun testKey(klass: Class<*>, methodKey: String) = "${klass.canonicalName}.$methodKey" +private fun testKey(testCase: TestCase) = testKey(testCase::class.java, testCase.name) class RunnerFactoryWithMuteInDatabase: ParametersRunnerFactory { override fun createRunnerForTestWithParameters(test: TestWithParameters?): Runner { return object : BlockJUnit4ClassRunnerWithParameters(test) { override fun isIgnored(child: FrameworkMethod): Boolean { - return super.isIgnored(child) || isIgnoredInDatabaseWithLog(child) + return super.isIgnored(child) || isIgnoredInDatabaseWithLog(child, name) } } } } -fun isIgnoredInDatabaseWithLog(child: FrameworkMethod): Boolean { - if (isMutedInDatabase(child.method)) { - System.err.println(mutedMessage(testKey(child.method))) +fun isIgnoredInDatabaseWithLog(child: FrameworkMethod, parametersName: String): Boolean { + if (isMutedInDatabase(child.declaringClass, child.name)) { + System.err.println(mutedMessage(testKey(child.declaringClass, child.name))) + return true + } + + val methodWithParametersKey = child.method.name + parametersName + if (isMutedInDatabase(child.declaringClass, methodWithParametersKey)) { + System.err.println(mutedMessage(testKey(child.declaringClass, methodWithParametersKey))) return true }