Refactoring of muteWithDatabase
- remove unused function RunNotifier.withMuteFailureListener - inline some functions (isIgnoredInDatabaseWithLog, etc.) - change declaration of mutedMessage - change naming of AutoMute related functions - extract to separate function isPresentedInDatabaseWithoutFailMarker
This commit is contained in:
committed by
Yunir Salimzyanov
parent
fb9b3f96de
commit
63ba883a77
@@ -0,0 +1,79 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||||
|
* 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.test
|
||||||
|
|
||||||
|
import org.junit.runner.notification.Failure
|
||||||
|
import org.junit.runner.notification.RunListener
|
||||||
|
import org.junit.runner.notification.RunNotifier
|
||||||
|
import java.io.File
|
||||||
|
|
||||||
|
class AutoMute(
|
||||||
|
val file: String,
|
||||||
|
val issue: String
|
||||||
|
)
|
||||||
|
|
||||||
|
val DO_AUTO_MUTE: AutoMute? by lazy {
|
||||||
|
val autoMuteFile = File("tests/automute")
|
||||||
|
if (autoMuteFile.exists()) {
|
||||||
|
val lines = autoMuteFile.readLines().filter { it.isNotBlank() }.map { it.trim() }
|
||||||
|
AutoMute(
|
||||||
|
lines.getOrNull(0) ?: error("A file path is expected in tne first line"),
|
||||||
|
lines.getOrNull(1) ?: error("An issue description is the second line")
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun AutoMute.muteTest(testKey: String) {
|
||||||
|
val file = File(file)
|
||||||
|
val lines = file.readLines()
|
||||||
|
val firstLine = lines[0] // Drop file header
|
||||||
|
val muted = lines.drop(1).toMutableList()
|
||||||
|
muted.add("$testKey, $issue")
|
||||||
|
val newMuted: List<String> = mutableListOf<String>() + firstLine + muted.sorted()
|
||||||
|
file.writeText(newMuted.joinToString("\n"))
|
||||||
|
}
|
||||||
|
|
||||||
|
internal fun wrapWithAutoMute(f: () -> Unit, testKey: String): (() -> Unit)? {
|
||||||
|
val doAutoMute = DO_AUTO_MUTE
|
||||||
|
if (doAutoMute != null) {
|
||||||
|
return {
|
||||||
|
try {
|
||||||
|
f()
|
||||||
|
} catch (e: Throwable) {
|
||||||
|
doAutoMute.muteTest(testKey)
|
||||||
|
throw e
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal inline fun RunNotifier.withAutoMuteListener(
|
||||||
|
testKey: String,
|
||||||
|
crossinline run: () -> Unit,
|
||||||
|
) {
|
||||||
|
val doAutoMute = DO_AUTO_MUTE
|
||||||
|
if (doAutoMute != null) {
|
||||||
|
val autoMuteListener = object : RunListener() {
|
||||||
|
override fun testFailure(failure: Failure) {
|
||||||
|
doAutoMute.muteTest(testKey)
|
||||||
|
super.testFailure(failure)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
addListener(autoMuteListener)
|
||||||
|
run()
|
||||||
|
} finally {
|
||||||
|
removeListener(autoMuteListener)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
run()
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -9,8 +9,6 @@ import junit.framework.TestCase
|
|||||||
import org.jetbrains.kotlin.test.mutes.*
|
import org.jetbrains.kotlin.test.mutes.*
|
||||||
import org.junit.internal.runners.statements.InvokeMethod
|
import org.junit.internal.runners.statements.InvokeMethod
|
||||||
import org.junit.runner.Runner
|
import org.junit.runner.Runner
|
||||||
import org.junit.runner.notification.Failure
|
|
||||||
import org.junit.runner.notification.RunListener
|
|
||||||
import org.junit.runner.notification.RunNotifier
|
import org.junit.runner.notification.RunNotifier
|
||||||
import org.junit.runners.model.FrameworkMethod
|
import org.junit.runners.model.FrameworkMethod
|
||||||
import org.junit.runners.model.Statement
|
import org.junit.runners.model.Statement
|
||||||
@@ -20,61 +18,63 @@ import org.junit.runners.parameterized.TestWithParameters
|
|||||||
|
|
||||||
private val SKIP_MUTED_TESTS = java.lang.Boolean.getBoolean("org.jetbrains.kotlin.skip.muted.tests")
|
private val SKIP_MUTED_TESTS = java.lang.Boolean.getBoolean("org.jetbrains.kotlin.skip.muted.tests")
|
||||||
|
|
||||||
private fun isMutedInDatabase(testCase: TestCase): Boolean {
|
|
||||||
return isMutedInDatabase(testCase.javaClass, testCase.name)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun isMutedInDatabase(testClass: Class<*>, methodKey: String): Boolean {
|
private fun isMutedInDatabase(testClass: Class<*>, methodKey: String): Boolean {
|
||||||
val mutedTest = mutedSet.mutedTest(testClass, methodKey)
|
val mutedTest = mutedSet.mutedTest(testClass, methodKey)
|
||||||
return mutedTest != null && (if (SKIP_MUTED_TESTS) !mutedTest.hasFailFile else mutedTest.isFlaky)
|
return mutedTest != null && (if (SKIP_MUTED_TESTS) !mutedTest.hasFailFile else mutedTest.isFlaky)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getMutedTest(testCase: TestCase): MutedTest? {
|
private fun isMutedInDatabaseWithLog(testClass: Class<*>, methodKey: String): Boolean {
|
||||||
return getMutedTest(testCase.javaClass, testCase.name)
|
val mutedInDatabase = isMutedInDatabase(testClass, methodKey)
|
||||||
|
|
||||||
|
if (mutedInDatabase) {
|
||||||
|
System.err.println(mutedMessage(testClass, methodKey))
|
||||||
|
}
|
||||||
|
|
||||||
|
return mutedInDatabase
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun isPresentedInDatabaseWithoutFailMarker(mutedTest: MutedTest?): Boolean {
|
||||||
|
return mutedTest != null && !mutedTest.hasFailFile
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun wrapWithMuteInDatabase(testCase: TestCase, f: () -> Unit): (() -> Unit)? {
|
internal fun wrapWithMuteInDatabase(testCase: TestCase, f: () -> Unit): (() -> Unit)? {
|
||||||
if (isMutedInDatabase(testCase)) {
|
val testClass = testCase.javaClass
|
||||||
return {
|
val methodKey = testCase.name
|
||||||
System.err.println(mutedMessage(testKey(testCase)))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
val mutedTest = getMutedTest(testCase)
|
val mutedTest = getMutedTest(testClass, methodKey)
|
||||||
if (mutedTest != null && !mutedTest.hasFailFile) {
|
val testKey = testKey(testClass, methodKey)
|
||||||
|
|
||||||
|
if (isMutedInDatabase(testClass, methodKey)) {
|
||||||
|
return {
|
||||||
|
System.err.println(mutedMessage(testClass, methodKey))
|
||||||
|
}
|
||||||
|
} else if (isPresentedInDatabaseWithoutFailMarker(mutedTest)) {
|
||||||
return {
|
return {
|
||||||
val testKey = testKey(testCase)
|
|
||||||
invertMutedTestResultWithLog(f, testKey)
|
invertMutedTestResultWithLog(f, testKey)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
val doAutoMute = DO_AUTO_MUTE ?: return null
|
return wrapWithAutoMute(f, testKey)
|
||||||
return {
|
|
||||||
try {
|
|
||||||
f()
|
|
||||||
} catch (e: Throwable) {
|
|
||||||
doAutoMute.muteTest(testKey(testCase))
|
|
||||||
throw e
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun mutedMessage(key: String) = "MUTED TEST: $key"
|
private fun mutedMessage(klass: Class<*>, methodKey: String) = "MUTED TEST: ${testKey(klass, methodKey)}"
|
||||||
|
|
||||||
private fun testKey(klass: Class<*>, methodKey: String) = "${klass.canonicalName}.$methodKey"
|
private fun testKey(klass: Class<*>, methodKey: String) = "${klass.canonicalName}.$methodKey"
|
||||||
private fun testKey(testCase: TestCase) = testKey(testCase::class.java, testCase.name)
|
|
||||||
|
|
||||||
class RunnerFactoryWithMuteInDatabase : ParametersRunnerFactory {
|
class RunnerFactoryWithMuteInDatabase : ParametersRunnerFactory {
|
||||||
override fun createRunnerForTestWithParameters(testWithParameters: TestWithParameters?): Runner {
|
override fun createRunnerForTestWithParameters(testWithParameters: TestWithParameters?): Runner {
|
||||||
return object : BlockJUnit4ClassRunnerWithParameters(testWithParameters) {
|
return object : BlockJUnit4ClassRunnerWithParameters(testWithParameters) {
|
||||||
override fun isIgnored(child: FrameworkMethod): Boolean {
|
override fun isIgnored(child: FrameworkMethod): Boolean {
|
||||||
return super.isIgnored(child) || isIgnoredInDatabaseWithLog(child, name)
|
val methodWithParametersKey = parametrizedMethodKey(child, name)
|
||||||
|
|
||||||
|
return super.isIgnored(child)
|
||||||
|
|| isMutedInDatabaseWithLog(child.declaringClass, child.name)
|
||||||
|
|| isMutedInDatabaseWithLog(child.declaringClass, methodWithParametersKey)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun runChild(method: FrameworkMethod, notifier: RunNotifier) {
|
override fun runChild(method: FrameworkMethod, notifier: RunNotifier) {
|
||||||
notifier.withMuteFailureListener(method.declaringClass, parametrizedMethodKey(method, name)) {
|
val testKey = testKey(method.declaringClass, parametrizedMethodKey(method, name))
|
||||||
|
notifier.withAutoMuteListener(testKey) {
|
||||||
super.runChild(method, notifier)
|
super.runChild(method, notifier)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -85,7 +85,7 @@ class RunnerFactoryWithMuteInDatabase : ParametersRunnerFactory {
|
|||||||
val methodClass = method.declaringClass
|
val methodClass = method.declaringClass
|
||||||
val methodKey = parametrizedMethodKey(method, name)
|
val methodKey = parametrizedMethodKey(method, name)
|
||||||
val mutedTest = getMutedTest(methodClass, methodKey) ?: getMutedTest(methodClass, method.method.name)
|
val mutedTest = getMutedTest(methodClass, methodKey) ?: getMutedTest(methodClass, method.method.name)
|
||||||
if (mutedTest != null && !mutedTest.hasFailFile) {
|
if (isPresentedInDatabaseWithoutFailMarker(mutedTest)) {
|
||||||
val testKey = testKey(methodClass, methodKey)
|
val testKey = testKey(methodClass, methodKey)
|
||||||
invertMutedTestResultWithLog({ super.evaluate() }, testKey)
|
invertMutedTestResultWithLog({ super.evaluate() }, testKey)
|
||||||
return
|
return
|
||||||
@@ -96,6 +96,8 @@ class RunnerFactoryWithMuteInDatabase : ParametersRunnerFactory {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun parametrizedMethodKey(child: FrameworkMethod, parametersName: String) = "${child.method.name}$parametersName"
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun invertMutedTestResultWithLog(f: () -> Unit, testKey: String) {
|
private fun invertMutedTestResultWithLog(f: () -> Unit, testKey: String) {
|
||||||
@@ -106,73 +108,13 @@ private fun invertMutedTestResultWithLog(f: () -> Unit, testKey: String) {
|
|||||||
println("MUTED TEST STILL FAILS: $testKey")
|
println("MUTED TEST STILL FAILS: $testKey")
|
||||||
isTestGreen = false
|
isTestGreen = false
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isTestGreen) {
|
if (isTestGreen) {
|
||||||
System.err.println("SUCCESS RESULT OF MUTED TEST: $testKey")
|
System.err.println("SUCCESS RESULT OF MUTED TEST: $testKey")
|
||||||
throw Exception("Muted non-flaky test $testKey finished successfully. Please remove it from csv file")
|
throw Exception("Muted non-flaky test $testKey finished successfully. Please remove it from csv file")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun parametrizedMethodKey(child: FrameworkMethod, parametersName: String): String {
|
|
||||||
return child.method.name + parametersName
|
|
||||||
}
|
|
||||||
|
|
||||||
private inline fun RunNotifier.withMuteFailureListener(
|
|
||||||
declaredClass: Class<*>,
|
|
||||||
methodKey: String,
|
|
||||||
crossinline run: () -> Unit,
|
|
||||||
) {
|
|
||||||
val doAutoMute = DO_AUTO_MUTE
|
|
||||||
if (doAutoMute == null) {
|
|
||||||
run()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
val muteFailureListener = object : RunListener() {
|
|
||||||
override fun testFailure(failure: Failure) {
|
|
||||||
doAutoMute.muteTest(testKey(declaredClass, methodKey))
|
|
||||||
super.testFailure(failure)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
addListener(muteFailureListener)
|
|
||||||
run()
|
|
||||||
} finally {
|
|
||||||
removeListener(muteFailureListener)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun isIgnoredInDatabaseWithLog(child: FrameworkMethod): Boolean {
|
|
||||||
if (isMutedInDatabase(child.declaringClass, child.name)) {
|
|
||||||
System.err.println(mutedMessage(testKey(child.declaringClass, child.name)))
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
fun isIgnoredInDatabaseWithLog(child: FrameworkMethod, parametersName: String): Boolean {
|
|
||||||
if (isIgnoredInDatabaseWithLog(child)) {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
val methodWithParametersKey = parametrizedMethodKey(child, parametersName)
|
|
||||||
if (isMutedInDatabase(child.declaringClass, methodWithParametersKey)) {
|
|
||||||
System.err.println(mutedMessage(testKey(child.declaringClass, methodWithParametersKey)))
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
fun isIgnoredInDatabaseWithLog(testCase: TestCase): Boolean {
|
|
||||||
if (isMutedInDatabase(testCase)) {
|
|
||||||
System.err.println(mutedMessage(testKey(testCase)))
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
fun TestCase.runTest(test: () -> Unit) {
|
fun TestCase.runTest(test: () -> Unit) {
|
||||||
(wrapWithMuteInDatabase(this, test) ?: test).invoke()
|
(wrapWithMuteInDatabase(this, test) ?: test).invoke()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,36 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
|
||||||
* 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.test.mutes
|
|
||||||
|
|
||||||
import java.io.File
|
|
||||||
|
|
||||||
class AutoMute(
|
|
||||||
val file: String,
|
|
||||||
val issue: String
|
|
||||||
)
|
|
||||||
|
|
||||||
val DO_AUTO_MUTE: AutoMute? by lazy {
|
|
||||||
val autoMuteFile = File("tests/automute")
|
|
||||||
if (autoMuteFile.exists()) {
|
|
||||||
val lines = autoMuteFile.readLines().filter { it.isNotBlank() }.map { it.trim() }
|
|
||||||
AutoMute(
|
|
||||||
lines.getOrNull(0) ?: error("A file path is expected in tne first line"),
|
|
||||||
lines.getOrNull(1) ?: error("An issue description is the second line")
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun AutoMute.muteTest(testKey: String) {
|
|
||||||
val file = File(file)
|
|
||||||
val lines = file.readLines()
|
|
||||||
val firstLine = lines[0] // Drop file header
|
|
||||||
val muted = lines.drop(1).toMutableList()
|
|
||||||
muted.add("$testKey, $issue")
|
|
||||||
val newMuted: List<String> = mutableListOf<String>() + firstLine + muted.sorted()
|
|
||||||
file.writeText(newMuted.joinToString("\n"))
|
|
||||||
}
|
|
||||||
-4
@@ -18,13 +18,9 @@ package org.jetbrains.kotlin.idea.test;
|
|||||||
|
|
||||||
import com.intellij.codeInsight.CodeInsightTestCase;
|
import com.intellij.codeInsight.CodeInsightTestCase;
|
||||||
import com.intellij.openapi.vfs.newvfs.impl.VfsRootAccess;
|
import com.intellij.openapi.vfs.newvfs.impl.VfsRootAccess;
|
||||||
import kotlin.Unit;
|
|
||||||
import org.jetbrains.kotlin.test.KotlinTestUtils;
|
import org.jetbrains.kotlin.test.KotlinTestUtils;
|
||||||
import org.jetbrains.kotlin.test.MuteWithDatabaseKt;
|
|
||||||
import org.jetbrains.kotlin.test.WithMutedInDatabaseRunTest;
|
import org.jetbrains.kotlin.test.WithMutedInDatabaseRunTest;
|
||||||
|
|
||||||
import static org.jetbrains.kotlin.test.MuteWithDatabaseKt.isIgnoredInDatabaseWithLog;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Please use KotlinLightCodeInsightFixtureTestCase as the base class for all new tests.
|
* Please use KotlinLightCodeInsightFixtureTestCase as the base class for all new tests.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -20,12 +20,9 @@ import com.intellij.testFramework.UsefulTestCase
|
|||||||
import junit.framework.TestCase
|
import junit.framework.TestCase
|
||||||
import org.jetbrains.kotlin.idea.configuration.KotlinWithLibraryConfigurator.FileState
|
import org.jetbrains.kotlin.idea.configuration.KotlinWithLibraryConfigurator.FileState
|
||||||
import org.jetbrains.kotlin.idea.framework.KotlinSdkType
|
import org.jetbrains.kotlin.idea.framework.KotlinSdkType
|
||||||
import org.jetbrains.kotlin.idea.test.PluginTestCaseBase
|
|
||||||
import org.jetbrains.kotlin.idea.test.PluginTestCaseBase.*
|
import org.jetbrains.kotlin.idea.test.PluginTestCaseBase.*
|
||||||
import org.jetbrains.kotlin.idea.util.getProjectJdkTableSafe
|
|
||||||
import org.jetbrains.kotlin.test.KotlinTestUtils
|
import org.jetbrains.kotlin.test.KotlinTestUtils
|
||||||
import org.jetbrains.kotlin.test.WithMutedInDatabaseRunTest
|
import org.jetbrains.kotlin.test.WithMutedInDatabaseRunTest
|
||||||
import org.jetbrains.kotlin.test.isIgnoredInDatabaseWithLog
|
|
||||||
import org.jetbrains.kotlin.test.runTest
|
import org.jetbrains.kotlin.test.runTest
|
||||||
import org.jetbrains.kotlin.utils.PathUtil
|
import org.jetbrains.kotlin.utils.PathUtil
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
|||||||
Reference in New Issue
Block a user