diff --git a/diktat-maven-plugin/pom.xml b/diktat-maven-plugin/pom.xml
index 1172a07260..8f296767d5 100644
--- a/diktat-maven-plugin/pom.xml
+++ b/diktat-maven-plugin/pom.xml
@@ -142,37 +142,10 @@
org.apache.maven.plugins
maven-surefire-plugin
-
-
- me.fabriciorby
- maven-surefire-junit5-tree-reporter
- ${junit-tree-reporter.version}
-
-
*IntegrationTest*
-
-
- true
- true
- true
- true
-
-
- plain
-
- true
-
-
-
- true
- true
-
- false
-
@@ -192,13 +165,6 @@
org.apache.maven.plugins
maven-failsafe-plugin
-
-
- me.fabriciorby
- maven-surefire-junit5-tree-reporter
- ${junit-tree-reporter.version}
-
-
${maven.version}
@@ -207,28 +173,6 @@
**/*IntegrationTest*
- ${project.build.testSourceDirectory}
- ${project.build.testOutputDirectory}
-
-
- true
- true
- true
- true
-
-
- plain
-
- true
-
-
-
- true
- true
-
- false
-
diff --git a/diktat-rules/pom.xml b/diktat-rules/pom.xml
index adf3254387..f9a42ec34e 100644
--- a/diktat-rules/pom.xml
+++ b/diktat-rules/pom.xml
@@ -12,11 +12,6 @@
1.2.4-SNAPSHOT
-
- 1.8
- 1.8
-
-
@@ -165,144 +160,6 @@
org.apache.maven.plugins
maven-surefire-plugin
-
-
- me.fabriciorby
- maven-surefire-junit5-tree-reporter
- ${junit-tree-reporter.version}
-
-
-
-
- **/DiktatSaveSmokeTest.*
-
-
-
- true
- true
- true
- true
-
-
- plain
-
- true
-
-
-
- true
- true
-
- false
-
-
-
-
-
- org.apache.maven.plugins
- maven-failsafe-plugin
-
-
- **/DiktatSaveSmokeTest.*
-
-
-
-
-
- integration-test
- verify
-
-
-
-
-
-
- org.jacoco
- jacoco-maven-plugin
-
-
-
- default-prepare-agent-integration
-
- prepare-agent-integration
-
-
-
- default-merge
- post-integration-test
-
- merge
-
-
-
-
- ${project.build.directory}
-
- jacoco.exec
- jacoco-it.exec
-
-
-
- ${project.build.directory}/jacoco-merged.exec
-
-
-
- default-report-merged
-
- report-integration
-
-
- ${project.reporting.outputDirectory}/jacoco
- ${project.build.directory}/jacoco-merged.exec
-
-
-
-
-
-
-
- org.apache.maven.plugins
- maven-shade-plugin
-
-
- false
-
- false
-
- ${project.name}-${project.version}-fat-jar-for-smoke-tests
-
-
- com.squareup:kotlinpoet
- net.java.dev.jna:jna
- org.jetbrains.intellij.deps:trove4j
- org.jetbrains.kotlin:kotlin-compiler-embeddable
- org.jetbrains.kotlin:kotlin-daemon-embeddable
- org.jetbrains.kotlin:kotlin-reflect
- org.jetbrains.kotlin:kotlin-script-runtime
- org.jetbrains.kotlin:kotlin-stdlib-common
- org.jetbrains.kotlin:kotlin-stdlib-jdk7
- org.jetbrains.kotlin:kotlin-stdlib-jdk8
- org.jetbrains.kotlin:kotlin-stdlib
- org.jetbrains:annotations
-
-
-
-
-
- fat-jar-for-smoke-tests
- package
-
- shade
-
-
-
diff --git a/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/utils/KtlintUtils.kt b/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/utils/KtlintUtils.kt
index 3c2fc353f4..6d773bd279 100644
--- a/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/utils/KtlintUtils.kt
+++ b/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/utils/KtlintUtils.kt
@@ -1,10 +1,27 @@
-@file:Suppress("HEADER_MISSING_IN_NON_SINGLE_CLASS_FILE")
+@file:Suppress(
+ "HEADER_MISSING_IN_NON_SINGLE_CLASS_FILE",
+ "Deprecation",
+)
package org.cqfn.diktat.ruleset.utils
+import org.cqfn.diktat.common.utils.loggerWithKtlintConfig
import com.pinterest.ktlint.core.KtLint
import com.pinterest.ktlint.core.KtLint.ExperimentalParams
import com.pinterest.ktlint.core.LintError
+import com.pinterest.ktlint.core.RuleSetProvider
+import mu.KotlinLogging
+import org.intellij.lang.annotations.Language
+
+@Suppress("EMPTY_BLOCK_STRUCTURE_ERROR")
+private val log = KotlinLogging.loggerWithKtlintConfig {}
+
+@Suppress("TYPE_ALIAS")
+val defaultCallback: (lintError: LintError, corrected: Boolean) -> Unit = { lintError, _ ->
+ log.warn("Received linting error: $lintError")
+}
+
+typealias LintErrorCallback = (LintError, Boolean) -> Unit
/**
* Enables ignoring autocorrected errors when in "fix" mode (i.e. when
@@ -27,3 +44,30 @@ fun ExperimentalParams.ignoreCorrectedErrors(): ExperimentalParams =
cb(error, false)
}
})
+
+/**
+ * @param ruleSetProviderRef
+ * @param text
+ * @param fileName
+ * @param cb callback to be called on unhandled [LintError]s
+ * @return formatted code
+ */
+@Suppress("LAMBDA_IS_NOT_LAST_PARAMETER")
+fun format(
+ ruleSetProviderRef: () -> RuleSetProvider,
+ @Language("kotlin") text: String,
+ fileName: String,
+ cb: LintErrorCallback = defaultCallback
+): String {
+ val ruleSets = listOf(ruleSetProviderRef().get())
+ return KtLint.format(
+ ExperimentalParams(
+ text = text,
+ ruleSets = ruleSets,
+ fileName = fileName.removeSuffix("_copy"),
+ script = fileName.removeSuffix("_copy").endsWith("kts"),
+ cb = cb,
+ debug = true,
+ ).ignoreCorrectedErrors()
+ )
+}
diff --git a/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/utils/indentation/IndentationConfig.kt b/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/utils/indentation/IndentationConfig.kt
index ac063c352d..fc416e69c5 100644
--- a/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/utils/indentation/IndentationConfig.kt
+++ b/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/utils/indentation/IndentationConfig.kt
@@ -5,7 +5,7 @@ import org.cqfn.diktat.common.config.rules.RuleConfiguration
/**
* [RuleConfiguration] for indentation logic
*/
-internal class IndentationConfig(config: Map) : RuleConfiguration(config) {
+class IndentationConfig(config: Map) : RuleConfiguration(config) {
/**
* Is newline at the end of a file needed
*/
@@ -87,7 +87,7 @@ internal class IndentationConfig(config: Map) : RuleConfiguratio
override fun toString(): String =
"${javaClass.simpleName}$configWithExplicitDefaults"
- internal companion object {
+ companion object {
internal const val ALIGNED_PARAMETERS = "alignedParameters"
/**
@@ -95,12 +95,12 @@ internal class IndentationConfig(config: Map) : RuleConfiguratio
* `indentationSize`.
*/
private const val DEFAULT_INDENTATION_SIZE = 4
- internal const val EXTENDED_INDENT_AFTER_OPERATORS = "extendedIndentAfterOperators"
- internal const val EXTENDED_INDENT_BEFORE_DOT = "extendedIndentBeforeDot"
- internal const val EXTENDED_INDENT_FOR_EXPRESSION_BODIES = "extendedIndentForExpressionBodies"
- internal const val EXTENDED_INDENT_OF_PARAMETERS = "extendedIndentOfParameters"
- internal const val INDENTATION_SIZE = "indentationSize"
- internal const val NEWLINE_AT_END = "newlineAtEnd"
+ const val EXTENDED_INDENT_AFTER_OPERATORS = "extendedIndentAfterOperators"
+ const val EXTENDED_INDENT_BEFORE_DOT = "extendedIndentBeforeDot"
+ const val EXTENDED_INDENT_FOR_EXPRESSION_BODIES = "extendedIndentForExpressionBodies"
+ const val EXTENDED_INDENT_OF_PARAMETERS = "extendedIndentOfParameters"
+ const val INDENTATION_SIZE = "indentationSize"
+ const val NEWLINE_AT_END = "newlineAtEnd"
@Suppress("CUSTOM_GETTERS_SETTERS")
private val IndentationConfig.configWithExplicitDefaults: Map
diff --git a/diktat-rules/src/test/kotlin/org/cqfn/diktat/ruleset/smoke/DiktatSmokeTest.kt b/diktat-rules/src/test/kotlin/org/cqfn/diktat/ruleset/smoke/DiktatSmokeTest.kt
deleted file mode 100644
index c69e6bb20b..0000000000
--- a/diktat-rules/src/test/kotlin/org/cqfn/diktat/ruleset/smoke/DiktatSmokeTest.kt
+++ /dev/null
@@ -1,123 +0,0 @@
-package org.cqfn.diktat.ruleset.smoke
-
-import org.cqfn.diktat.common.config.rules.DIKTAT_COMMON
-import org.cqfn.diktat.common.config.rules.DIKTAT_RULE_SET_ID
-import org.cqfn.diktat.ruleset.constants.Warnings.KDOC_NO_EMPTY_TAGS
-import org.cqfn.diktat.ruleset.constants.Warnings.MISSING_KDOC_CLASS_ELEMENTS
-import org.cqfn.diktat.ruleset.constants.Warnings.MISSING_KDOC_ON_FUNCTION
-import org.cqfn.diktat.ruleset.constants.Warnings.MISSING_KDOC_TOP_LEVEL
-import org.cqfn.diktat.ruleset.constants.Warnings.WRONG_INDENTATION
-import org.cqfn.diktat.ruleset.rules.DiktatRuleSetProvider
-import org.cqfn.diktat.ruleset.rules.chapter2.comments.CommentsRule
-import org.cqfn.diktat.ruleset.rules.chapter2.kdoc.KdocComments
-import org.cqfn.diktat.ruleset.rules.chapter2.kdoc.KdocFormatting
-import org.cqfn.diktat.ruleset.rules.chapter2.kdoc.KdocMethods
-import org.cqfn.diktat.ruleset.utils.indentation.IndentationConfig.Companion.NEWLINE_AT_END
-import org.cqfn.diktat.util.deleteIfExistsSilently
-
-import com.pinterest.ktlint.core.LintError
-import org.assertj.core.api.Assertions.assertThat
-import org.junit.jupiter.api.Assertions
-import org.junit.jupiter.api.Tag
-import org.junit.jupiter.api.Test
-
-import java.io.File
-
-/**
- * Test for [DiktatRuleSetProvider] in autocorrect mode as a whole. All rules are applied to a file.
- * Note: ktlint uses initial text from a file to calculate line and column from offset. Because of that line/col of unfixed errors
- * may change after some changes to text or other rules.
- */
-class DiktatSmokeTest : DiktatSmokeTestBase() {
- override val isLintErrors = true
- override fun fixAndCompare(
- config: String,
- expected: String,
- test: String,
- ) {
- fixAndCompareSmokeTest(expected, test)
- }
-
- @Test
- @Tag("DiktatRuleSetProvider")
- fun `smoke test with multiplatform project layout`() {
- fixAndCompareSmokeTest("../../jsMain/kotlin/org/cqfn/diktat/scripts/ScriptExpected.kt",
- "../../jsMain/kotlin/org/cqfn/diktat/scripts/ScriptTest.kt")
- }
-
- @Test
- @Tag("DiktatRuleSetProvider")
- fun `smoke test with kts files`() {
- overrideRulesConfig(
- emptyList(),
- mapOf(
- WRONG_INDENTATION.name to mapOf(
- NEWLINE_AT_END to "false",
- )
- )
- ) // so that trailing newline isn't checked, because it's incorrectly read in tests and we are comparing file with itself
- // file name is `gradle_` so that IDE doesn't suggest to import gradle project
- val tmpTestFile = javaClass.classLoader
- .getResource("$resourceFilePath/../../../build.gradle_.kts")!!
- .toURI()
- .let {
- val tmpTestFile = File(it).parentFile.resolve("build.gradle.kts")
- File(it).copyTo(tmpTestFile)
- tmpTestFile
- }
- try {
- val tmpFilePath = "../../../build.gradle.kts"
- fixAndCompare(tmpFilePath, tmpFilePath)
- Assertions.assertTrue(unfixedLintErrors.isEmpty())
- } finally {
- tmpTestFile.toPath().deleteIfExistsSilently()
- }
- }
-
- @Test
- @Tag("DiktatRuleSetProvider")
- fun `smoke test with gradle script plugin`() {
- fixAndCompareSmokeTest("kotlin-library-expected.gradle.kts", "kotlin-library.gradle.kts")
- assertThat(unfixedLintErrors).containsExactly(
- LintError(2, 1, "$DIKTAT_RULE_SET_ID:${CommentsRule.NAME_ID}", "[COMMENTED_OUT_CODE] you should not comment out code, " +
- "use VCS to save it in history and delete this block: import org.jetbrains.kotlin.gradle.dsl.jvm", false)
- )
- }
-
- @Test
- @Tag("DiktatRuleSetProvider")
- fun `disable chapters`() {
- overrideRulesConfig(
- emptyList(),
- mapOf(
- DIKTAT_COMMON to mapOf(
- "domainName" to "org.cqfn.diktat",
- "disabledChapters" to "Naming,3,4,5,Classes"
- )
- )
- )
- fixAndCompareSmokeTest("Example1-2Expected.kt", "Example1Test.kt")
- assertThat(unfixedLintErrors).containsExactlyInAnyOrder(
- LintError(1, 1, "$DIKTAT_RULE_SET_ID:${KdocFormatting.NAME_ID}", "${KDOC_NO_EMPTY_TAGS.warnText()} @return", false),
- LintError(3, 1, "$DIKTAT_RULE_SET_ID:${KdocComments.NAME_ID}", "${MISSING_KDOC_TOP_LEVEL.warnText()} example", false),
- LintError(3, 16, "$DIKTAT_RULE_SET_ID:${KdocComments.NAME_ID}", "${MISSING_KDOC_CLASS_ELEMENTS.warnText()} isValid", false),
- LintError(6, 5, "$DIKTAT_RULE_SET_ID:${KdocComments.NAME_ID}", "${MISSING_KDOC_CLASS_ELEMENTS.warnText()} foo", false),
- LintError(6, 5, "$DIKTAT_RULE_SET_ID:${KdocMethods.NAME_ID}", "${MISSING_KDOC_ON_FUNCTION.warnText()} foo", false),
- LintError(8, 5, "$DIKTAT_RULE_SET_ID:${KdocComments.NAME_ID}", "${MISSING_KDOC_CLASS_ELEMENTS.warnText()} foo", false),
- LintError(10, 4, "$DIKTAT_RULE_SET_ID:${KdocFormatting.NAME_ID}", "${KDOC_NO_EMPTY_TAGS.warnText()} @return", false),
- LintError(13, 9, "$DIKTAT_RULE_SET_ID:${KdocFormatting.NAME_ID}", "${KDOC_NO_EMPTY_TAGS.warnText()} @return", false),
- LintError(18, 40, "$DIKTAT_RULE_SET_ID:${KdocFormatting.NAME_ID}", "${KDOC_NO_EMPTY_TAGS.warnText()} @return", false)
- )
- }
-
- /**
- * @param expectedPath path to file with expected result, relative to [resourceFilePath]
- * @param testPath path to file with code that will be transformed by formatter, relative to [resourceFilePath]
- */
- private fun fixAndCompareSmokeTest(expectedPath: String, testPath: String) {
- Assertions.assertTrue(
- testComparatorUnit
- .compareFilesFromResources(expectedPath, testPath, true)
- )
- }
-}
diff --git a/diktat-rules/src/test/kotlin/org/cqfn/diktat/ruleset/smoke/RulesConfigValidationTest.kt b/diktat-rules/src/test/kotlin/org/cqfn/diktat/ruleset/smoke/RulesConfigValidationTest.kt
index 586eaf20d6..07e2135a97 100644
--- a/diktat-rules/src/test/kotlin/org/cqfn/diktat/ruleset/smoke/RulesConfigValidationTest.kt
+++ b/diktat-rules/src/test/kotlin/org/cqfn/diktat/ruleset/smoke/RulesConfigValidationTest.kt
@@ -1,7 +1,7 @@
package org.cqfn.diktat.ruleset.smoke
import org.cqfn.diktat.ruleset.rules.DiktatRuleSetProvider
-import org.cqfn.diktat.util.deleteIfExistsSilently
+import org.cqfn.diktat.test.framework.util.deleteIfExistsSilently
import com.charleskorn.kaml.InvalidPropertyValueException
import org.junit.jupiter.api.AfterEach
diff --git a/diktat-rules/src/test/kotlin/org/cqfn/diktat/util/FixTestBase.kt b/diktat-rules/src/test/kotlin/org/cqfn/diktat/util/FixTestBase.kt
index c30dcc8ad2..925c531ae8 100644
--- a/diktat-rules/src/test/kotlin/org/cqfn/diktat/util/FixTestBase.kt
+++ b/diktat-rules/src/test/kotlin/org/cqfn/diktat/util/FixTestBase.kt
@@ -5,94 +5,66 @@
package org.cqfn.diktat.util
import org.cqfn.diktat.common.config.rules.RulesConfig
+import org.cqfn.diktat.ruleset.utils.LintErrorCallback
+import org.cqfn.diktat.ruleset.utils.defaultCallback
+import org.cqfn.diktat.ruleset.utils.format
import org.cqfn.diktat.test.framework.processing.FileComparisonResult
import org.cqfn.diktat.test.framework.processing.TestComparatorUnit
import com.pinterest.ktlint.core.Rule
-import com.pinterest.ktlint.core.RuleSetProvider
import org.intellij.lang.annotations.Language
import org.junit.jupiter.api.Assertions
import java.nio.file.Path
import kotlin.io.path.bufferedWriter
import kotlin.io.path.div
-const val SAVE_VERSION: String = "0.3.2"
-
/**
- * @property resourceFilePath path to files which will be compared in tests
+ * Base class for FixTest
*/
open class FixTestBase(
- protected val resourceFilePath: String,
- private val ruleSetProviderRef: (rulesConfigList: List?) -> RuleSetProvider,
- private val cb: LintErrorCallback = defaultCallback,
- private val rulesConfigList: List? = null,
+ resourceFilePath: String,
+ ruleSupplier: (rulesConfigList: List) -> Rule,
+ defaultRulesConfigList: List? = null,
+ cb: LintErrorCallback = defaultCallback,
) {
/**
* testComparatorUnit
*/
- protected val testComparatorUnit = TestComparatorUnit(resourceFilePath) { text, fileName ->
- format(ruleSetProviderRef, text, fileName, rulesConfigList, cb = cb)
+ private val testComparatorUnitSupplier = { overrideRulesConfigList: List? ->
+ TestComparatorUnit(
+ resourceFilePath = resourceFilePath,
+ function = { expectedText, testFilePath ->
+ format(
+ ruleSetProviderRef = { DiktatRuleSetProvider4Test(ruleSupplier, overrideRulesConfigList ?: defaultRulesConfigList) },
+ text = expectedText,
+ fileName = testFilePath,
+ cb = cb,
+ )
+ },
+ )
}
- constructor(resourceFilePath: String,
- ruleSupplier: (rulesConfigList: List) -> Rule,
- rulesConfigList: List? = null,
- cb: LintErrorCallback = defaultCallback
- ) : this(
- resourceFilePath,
- { overrideRulesConfigList -> DiktatRuleSetProvider4Test(ruleSupplier, overrideRulesConfigList) },
- cb,
- rulesConfigList
- )
-
/**
* @param expectedPath path to file with expected result, relative to [resourceFilePath]
* @param testPath path to file with code that will be transformed by formatter, relative to [resourceFilePath]
- * @param overrideRulesConfigList optional override to [rulesConfigList]
+ * @param overrideRulesConfigList optional override to [defaultRulesConfigList]
+ * @param trimLastEmptyLine whether the last (empty) line should be
+ * discarded when reading the content of [testPath].
* @see fixAndCompareContent
*/
protected fun fixAndCompare(
expectedPath: String,
testPath: String,
- overrideRulesConfigList: List = emptyList()
+ overrideRulesConfigList: List? = null,
+ trimLastEmptyLine: Boolean = false,
) {
- val testComparatorUnit = if (overrideRulesConfigList.isNotEmpty()) {
- TestComparatorUnit(resourceFilePath) { text, fileName ->
- format(ruleSetProviderRef, text, fileName, overrideRulesConfigList)
- }
- } else {
- testComparatorUnit
- }
-
+ val testComparatorUnit = testComparatorUnitSupplier(overrideRulesConfigList)
Assertions.assertTrue(
testComparatorUnit
- .compareFilesFromResources(expectedPath, testPath)
+ .compareFilesFromResources(expectedPath, testPath, trimLastEmptyLine)
+ .isSuccessful
)
}
- private fun getSaveForCurrentOs() = when {
- System.getProperty("os.name").startsWith("Linux", ignoreCase = true) -> "save-$SAVE_VERSION-linuxX64.kexe"
- System.getProperty("os.name").startsWith("Mac", ignoreCase = true) -> "save-$SAVE_VERSION-macosX64.kexe"
- System.getProperty("os.name").startsWith("Windows", ignoreCase = true) -> "save-$SAVE_VERSION-mingwX64.exe"
- else -> ""
- }
-
- /**
- * @param testPath path to file with code that will be transformed by formatter, relative to [resourceFilePath]
- * @return ProcessBuilder
- */
- protected fun createProcessBuilderWithCmd(testPath: String): ProcessBuilder {
- val filesDir = "src/test/resources/test/smoke"
- val savePath = "$filesDir/${getSaveForCurrentOs()}"
-
- val systemName = System.getProperty("os.name")
- val result = when {
- systemName.startsWith("Linux", ignoreCase = true) || systemName.startsWith("Mac", ignoreCase = true) ->
- ProcessBuilder("sh", "-c", "chmod 777 $savePath ; ./$savePath $filesDir/src/main/kotlin $testPath --log all")
- else -> ProcessBuilder(savePath, "$filesDir/src/main/kotlin", testPath, "--log", "all")
- }
- return result
- }
-
/**
* Unlike [fixAndCompare], this method doesn't perform any assertions.
*
@@ -123,10 +95,8 @@ open class FixTestBase(
out.write(expectedContent)
}
- val testComparatorUnit = TestComparatorUnit(tempDir.toString()) { text, fileName ->
- format(ruleSetProviderRef, text, fileName, overrideRulesConfigList ?: rulesConfigList, cb)
- }
-
- return testComparatorUnit.compareFilesFromFileSystem(expected, actual)
+ val testComparatorUnit = testComparatorUnitSupplier(overrideRulesConfigList)
+ return testComparatorUnit
+ .compareFilesFromFileSystem(expected, actual, false)
}
}
diff --git a/diktat-rules/src/test/kotlin/org/cqfn/diktat/util/TestUtils.kt b/diktat-rules/src/test/kotlin/org/cqfn/diktat/util/TestUtils.kt
index bc9412e7a5..4f8eef4716 100644
--- a/diktat-rules/src/test/kotlin/org/cqfn/diktat/util/TestUtils.kt
+++ b/diktat-rules/src/test/kotlin/org/cqfn/diktat/util/TestUtils.kt
@@ -8,184 +8,19 @@
package org.cqfn.diktat.util
-import org.cqfn.diktat.common.config.rules.RulesConfig
-import org.cqfn.diktat.common.utils.loggerWithKtlintConfig
import org.cqfn.diktat.ruleset.constants.EmitType
-import org.cqfn.diktat.ruleset.utils.ignoreCorrectedErrors
import com.pinterest.ktlint.core.KtLint
-import com.pinterest.ktlint.core.LintError
import com.pinterest.ktlint.core.Rule
import com.pinterest.ktlint.core.RuleSet
-import com.pinterest.ktlint.core.RuleSetProvider
-import mu.KotlinLogging
import org.assertj.core.api.Assertions.assertThat
import org.assertj.core.api.Assertions.fail
-import org.intellij.lang.annotations.Language
import org.jetbrains.kotlin.com.intellij.lang.ASTNode
-import java.io.File
-import java.io.IOException
-import java.nio.file.FileVisitResult
-import java.nio.file.FileVisitResult.CONTINUE
-import java.nio.file.Files
-import java.nio.file.Files.walkFileTree
-import java.nio.file.NoSuchFileException
-import java.nio.file.Path
-import java.nio.file.SimpleFileVisitor
-import java.nio.file.attribute.BasicFileAttributes
import java.util.concurrent.atomic.AtomicInteger
-import kotlin.io.path.absolute
-import kotlin.io.path.deleteExisting
-import kotlin.io.path.deleteIfExists
-import kotlin.io.path.isDirectory
-import kotlin.io.path.isSameFileAs
internal const val TEST_FILE_NAME = "TestFileName.kt"
-@Suppress("EMPTY_BLOCK_STRUCTURE_ERROR")
-private val log = KotlinLogging.loggerWithKtlintConfig {}
-
-@Suppress("TYPE_ALIAS")
-internal val defaultCallback: (lintError: LintError, corrected: Boolean) -> Unit = { lintError, _ ->
- log.warn("Received linting error: $lintError")
-}
-
-typealias LintErrorCallback = (LintError, Boolean) -> Unit
-
-/**
- * Deletes the file if it exists, retrying as necessary if the file is
- * blocked by another process (on Windows).
- *
- * @receiver the file or empty directory.
- * @see Path.deleteIfExists
- */
-@Suppress(
- "EMPTY_BLOCK_STRUCTURE_ERROR",
- "MAGIC_NUMBER",
-)
-internal fun Path.deleteIfExistsSilently() {
- val attempts = 10
-
- val deleted = retry(attempts, delayMillis = 100L, lazyDefault = { false }) {
- deleteIfExists()
-
- /*
- * Ignore the return code of `deleteIfExists()` (will be `false`
- * if the file doesn't exist).
- */
- true
- }
-
- if (!deleted) {
- log.warn {
- "File \"${absolute()}\" not deleted after $attempts attempt(s)."
- }
- }
-}
-
-/**
- * Deletes this directory recursively.
- *
- * @see Path.deleteIfExistsRecursively
- */
-internal fun Path.deleteRecursively() {
- walkFileTree(this, object : SimpleFileVisitor() {
- override fun visitFile(file: Path, attrs: BasicFileAttributes): FileVisitResult {
- file.deleteIfExistsSilently()
- return CONTINUE
- }
-
- override fun postVisitDirectory(dir: Path, exc: IOException?): FileVisitResult {
- dir.deleteExisting()
- return CONTINUE
- }
- })
-}
-
-/**
- * Deletes this directory recursively if it exists.
- *
- * @return `true` if the existing directory was successfully deleted, `false` if
- * the directory doesn't exist.
- * @see Files.deleteIfExists
- * @see Path.deleteRecursively
- */
-@Suppress("FUNCTION_BOOLEAN_PREFIX")
-internal fun Path.deleteIfExistsRecursively(): Boolean =
- try {
- deleteRecursively()
- true
- } catch (_: NoSuchFileException) {
- false
- }
-
-/**
- * @receiver the 1st operand.
- * @param other the 2nd operand.
- * @return `true` if, and only if, the two paths locate the same `JAVA_HOME`.
- */
-internal fun Path.isSameJavaHomeAs(other: Path): Boolean =
- isDirectory() &&
- (isSameFileAsSafe(other) ||
- resolve("jre").isSameFileAsSafe(other) ||
- other.resolve("jre").isSameFileAsSafe(this))
-
-/**
- * The same as [Path.isSameFileAs], but doesn't throw any [NoSuchFileException]
- * if either of the operands doesn't exist.
- *
- * @receiver the 1st operand.
- * @param other the 2nd operand.
- * @return `true` if, and only if, the two paths locate the same file.
- * @see Path.isSameFileAs
- */
-internal fun Path.isSameFileAsSafe(other: Path): Boolean =
- try {
- isSameFileAs(other)
- } catch (_: NoSuchFileException) {
- false
- }
-
-/**
- * Prepends the `PATH` of this process builder with [pathEntry].
- *
- * @param pathEntry the entry to be prepended to the `PATH`.
- */
-internal fun ProcessBuilder.prependPath(pathEntry: Path) {
- require(pathEntry.isDirectory()) {
- "$pathEntry is not a directory"
- }
-
- val environment = environment()
-
- val defaultPathKey = "PATH"
- val defaultWindowsPathKey = "Path"
-
- val pathKey = when {
- /*-
- * Keys of the Windows environment are case-insensitive ("PATH" == "Path").
- * Keys of the Java interface to the environment are not ("PATH" != "Path").
- * This is an attempt to work around the inconsistency.
- */
- System.getProperty("os.name").startsWith("Windows") -> environment.keys.firstOrNull { key ->
- key.equals(defaultPathKey, ignoreCase = true)
- } ?: defaultWindowsPathKey
-
- else -> defaultPathKey
- }
-
- val pathSeparator = File.pathSeparatorChar
- val oldPath = environment[pathKey]
-
- val newPath = when {
- oldPath.isNullOrEmpty() -> pathEntry.toString()
- else -> "$pathEntry$pathSeparator$oldPath"
- }
-
- environment[pathKey] = newPath
-}
-
/**
* Casts a nullable value to a non-`null` one, similarly to the `!!`
* operator.
@@ -196,34 +31,6 @@ internal fun ProcessBuilder.prependPath(pathEntry: Path) {
internal fun T?.assertNotNull(lazyFailureMessage: () -> String = { "Expecting actual not to be null" }): T =
this ?: fail(lazyFailureMessage())
-/**
- * @param ruleSetProviderRef
- * @param text
- * @param fileName
- * @param rulesConfigList
- * @param cb callback to be called on unhandled [LintError]s
- * @return formatted code
- */
-@Suppress("LAMBDA_IS_NOT_LAST_PARAMETER")
-internal fun format(ruleSetProviderRef: (rulesConfigList: List?) -> RuleSetProvider,
- @Language("kotlin") text: String,
- fileName: String,
- rulesConfigList: List? = null,
- cb: LintErrorCallback = defaultCallback
-): String {
- val ruleSets = listOf(ruleSetProviderRef.invoke(rulesConfigList).get())
- return KtLint.format(
- KtLint.ExperimentalParams(
- text = text,
- ruleSets = ruleSets,
- fileName = fileName.removeSuffix("_copy"),
- script = fileName.removeSuffix("_copy").endsWith("kts"),
- cb = cb,
- debug = true,
- ).ignoreCorrectedErrors()
- )
-}
-
/**
* This utility function lets you run arbitrary code on every node of given [code].
* It also provides you with counter which can be incremented inside [applyToNode] and then will be compared to [expectedAsserts].
@@ -260,42 +67,3 @@ internal fun applyToCode(code: String,
.`as`("Number of expected asserts")
.isEqualTo(expectedAsserts)
}
-
-/**
- * Retries the execution of the [block].
- *
- * @param attempts the number of attempts (must be positive).
- * @param delayMillis the timeout (in milliseconds) between the consecutive
- * attempts. The default is 0. Ignored if [attempts] is 1.
- * @param lazyDefault allows to override the return value if none of the
- * attempts succeeds. By default, the last exception is thrown.
- * @param block the block to execute.
- * @return the result of the execution of the [block], or whatever [lazyDefault]
- * evaluates to if none of the attempts is successful.
- */
-internal fun retry(
- attempts: Int,
- delayMillis: Long = 0L,
- lazyDefault: (Throwable) -> T = { error -> throw error },
- block: () -> T
-): T {
- require(attempts > 0) {
- "The number of attempts should be positive: $attempts"
- }
-
- var lastError: Throwable? = null
-
- for (i in 1..attempts) {
- try {
- return block()
- } catch (error: Throwable) {
- lastError = error
- }
-
- if (delayMillis > 0L) {
- Thread.sleep(delayMillis)
- }
- }
-
- return lazyDefault(lastError ?: Exception("The block was never executed"))
-}
diff --git a/diktat-ruleset/pom.xml b/diktat-ruleset/pom.xml
index a7275178e1..9edd86b9b9 100644
--- a/diktat-ruleset/pom.xml
+++ b/diktat-ruleset/pom.xml
@@ -9,6 +9,7 @@
org.cqfn.diktat
diktat-parent
1.2.4-SNAPSHOT
+ ../pom.xml
@@ -36,10 +37,95 @@
+
+
+ org.cqfn.diktat
+ diktat-test-framework
+ ${project.version}
+ test
+
+
+ org.jetbrains.kotlin
+ kotlin-stdlib-common
+ test
+
+
+ org.jetbrains.kotlin
+ kotlin-stdlib-jdk7
+ test
+
+
+ org.jetbrains.kotlin
+ kotlin-stdlib-jdk8
+ test
+
+
+ org.jetbrains.kotlin
+ kotlin-stdlib
+ test
+
+
+ org.jetbrains.kotlin
+ kotlin-compiler-embeddable
+ test
+
+
+ org.apache.logging.log4j
+ log4j-core
+ test
+
+
+ org.apache.logging.log4j
+ log4j-slf4j-impl
+ test
+
+
+ org.junit.jupiter
+ junit-jupiter
+ test
+
+
+ org.junit.platform
+ junit-platform-suite-engine
+ test
+
+
+ org.assertj
+ assertj-core
+ test
+
+
+ org.mockito
+ mockito-all
+ test
+
+ ${project.basedir}/src/test/kotlin
+
+ org.jetbrains.kotlin
+ kotlin-maven-plugin
+
+
+ test-compile
+ process-test-sources
+
+ test-compile
+
+
+
+
+ src/main/kotlin
+ src/test/kotlin
+ ${project.basedir}/src/main/kotlin
+ ${project.basedir}/src/test/kotlin
+
+
+
+
+
maven-jar-plugin
@@ -76,6 +162,78 @@
+
+
+
+ org.apache.maven.plugins
+ maven-surefire-plugin
+
+
+ **/DiktatSaveSmokeTest.*
+
+
+
+
+ org.apache.maven.plugins
+ maven-failsafe-plugin
+
+
+ **/DiktatSaveSmokeTest.*
+
+
+
+
+
+ integration-test
+ verify
+
+ integration-test
+
+
+
+
+
+ org.jacoco
+ jacoco-maven-plugin
+
+
+
+ default-prepare-agent-integration
+
+ prepare-agent-integration
+
+
+
+ default-merge
+ post-integration-test
+
+ merge
+
+
+
+
+ ${project.build.directory}
+
+ jacoco.exec
+ jacoco-it.exec
+
+
+
+ ${project.build.directory}/jacoco-merged.exec
+
+
+
+ default-report-merged
+
+ report-integration
+
+
+ ${project.reporting.outputDirectory}/jacoco
+ ${project.build.directory}/jacoco-merged.exec
+
+
+
+
diff --git a/diktat-rules/src/test/kotlin/org/cqfn/diktat/ruleset/smoke/DiktatSaveSmokeTest.kt b/diktat-ruleset/src/test/kotlin/org/cqfn/diktat/ruleset/smoke/DiktatSaveSmokeTest.kt
similarity index 85%
rename from diktat-rules/src/test/kotlin/org/cqfn/diktat/ruleset/smoke/DiktatSaveSmokeTest.kt
rename to diktat-ruleset/src/test/kotlin/org/cqfn/diktat/ruleset/smoke/DiktatSaveSmokeTest.kt
index 85c6f19bfb..912e358621 100644
--- a/diktat-rules/src/test/kotlin/org/cqfn/diktat/ruleset/smoke/DiktatSaveSmokeTest.kt
+++ b/diktat-ruleset/src/test/kotlin/org/cqfn/diktat/ruleset/smoke/DiktatSaveSmokeTest.kt
@@ -1,12 +1,12 @@
package org.cqfn.diktat.ruleset.smoke
import org.cqfn.diktat.common.utils.loggerWithKtlintConfig
-import org.cqfn.diktat.util.SAVE_VERSION
-import org.cqfn.diktat.util.deleteIfExistsRecursively
-import org.cqfn.diktat.util.deleteIfExistsSilently
+import org.cqfn.diktat.test.framework.util.deleteIfExistsRecursively
+import org.cqfn.diktat.test.framework.util.deleteIfExistsSilently
+import org.cqfn.diktat.test.framework.util.retry
import org.cqfn.diktat.util.isSameJavaHomeAs
import org.cqfn.diktat.util.prependPath
-import org.cqfn.diktat.util.retry
+import com.pinterest.ktlint.core.LintError
import mu.KotlinLogging
import org.assertj.core.api.Assertions.assertThat
@@ -34,15 +34,18 @@ import kotlin.system.measureNanoTime
@DisabledOnOs(OS.MAC)
class DiktatSaveSmokeTest : DiktatSmokeTestBase() {
- override val isLintErrors = false
override fun fixAndCompare(
- config: String,
+ config: Path,
expected: String,
test: String,
+ trimLastEmptyLine: Boolean,
) {
- saveSmokeTest(Path(config), test)
+ saveSmokeTest(config, test)
}
+ // do nothing, we can't check unfixed lint errors here
+ override fun assertUnfixedLintErrors(lintErrorsConsumer: (List) -> Unit) = Unit
+
/**
* @param testPath path to file with code that will be transformed by formatter, relative to [resourceFilePath]
* @param configFilePath path of diktat-analysis file
@@ -113,12 +116,30 @@ class DiktatSaveSmokeTest : DiktatSmokeTestBase() {
}
}
+ /**
+ * @param testPath path to file with code that will be transformed by formatter, relative to [resourceFilePath]
+ * @return ProcessBuilder
+ */
+ private fun createProcessBuilderWithCmd(testPath: String): ProcessBuilder {
+ val filesDir = "src/test/resources/test/smoke"
+ val savePath = "$filesDir/${getSaveForCurrentOs()}"
+
+ val systemName = System.getProperty("os.name")
+ val result = when {
+ systemName.startsWith("Linux", ignoreCase = true) || systemName.startsWith("Mac", ignoreCase = true) ->
+ ProcessBuilder("sh", "-c", "chmod 777 $savePath ; ./$savePath $filesDir/src/main/kotlin $testPath --log all")
+ else -> ProcessBuilder(savePath, "$filesDir/src/main/kotlin", testPath, "--log", "all")
+ }
+ return result
+ }
+
companion object {
@Suppress("EMPTY_BLOCK_STRUCTURE_ERROR")
private val logger = KotlinLogging.loggerWithKtlintConfig { }
private const val BUILD_DIRECTORY = "target"
- private const val FAT_JAR_GLOB = "diktat-rules-*-fat-jar-for-smoke-tests.jar"
+ private const val FAT_JAR_GLOB = "diktat-*.jar"
private const val KTLINT_VERSION = "0.47.1"
+ private const val SAVE_VERSION: String = "0.3.4"
private val baseDirectory = Path("src/test/resources/test/smoke").absolute()
private fun getSaveForCurrentOs(): String {
diff --git a/diktat-ruleset/src/test/kotlin/org/cqfn/diktat/ruleset/smoke/DiktatSmokeTest.kt b/diktat-ruleset/src/test/kotlin/org/cqfn/diktat/ruleset/smoke/DiktatSmokeTest.kt
new file mode 100644
index 0000000000..46cf775a42
--- /dev/null
+++ b/diktat-ruleset/src/test/kotlin/org/cqfn/diktat/ruleset/smoke/DiktatSmokeTest.kt
@@ -0,0 +1,53 @@
+package org.cqfn.diktat.ruleset.smoke
+
+import org.cqfn.diktat.ruleset.rules.DiktatRuleSetProvider
+import org.cqfn.diktat.ruleset.utils.format
+import org.cqfn.diktat.test.framework.processing.TestComparatorUnit
+import com.pinterest.ktlint.core.LintError
+import org.junit.jupiter.api.Assertions
+import org.junit.jupiter.api.BeforeEach
+import java.nio.file.Path
+import kotlin.io.path.absolutePathString
+
+/**
+ * Test for [DiktatRuleSetProvider] in autocorrect mode as a whole. All rules are applied to a file.
+ * Note: ktlint uses initial text from a file to calculate line and column from offset. Because of that line/col of unfixed errors
+ * may change after some changes to text or other rules.
+ */
+class DiktatSmokeTest : DiktatSmokeTestBase() {
+ private val unfixedLintErrors: MutableList = mutableListOf()
+
+ override fun fixAndCompare(
+ config: Path,
+ expected: String,
+ test: String,
+ trimLastEmptyLine: Boolean,
+ ) {
+ Assertions.assertTrue(
+ getTestComparatorUnit(config)
+ .compareFilesFromResources(expected, test, trimLastEmptyLine)
+ .isSuccessful
+ )
+ }
+
+ @BeforeEach
+ internal fun setUp() {
+ unfixedLintErrors.clear()
+ }
+
+ override fun assertUnfixedLintErrors(lintErrorsConsumer: (List) -> Unit) {
+ lintErrorsConsumer(unfixedLintErrors)
+ }
+
+ private fun getTestComparatorUnit(config: Path) = TestComparatorUnit(
+ resourceFilePath = RESOURCE_FILE_PATH,
+ function = { expectedText, testFilePath ->
+ format(
+ ruleSetProviderRef = { DiktatRuleSetProvider(config.absolutePathString()) },
+ text = expectedText,
+ fileName = testFilePath,
+ cb = { lintError, _ -> unfixedLintErrors.add(lintError) },
+ )
+ },
+ )
+}
diff --git a/diktat-rules/src/test/kotlin/org/cqfn/diktat/ruleset/smoke/DiktatSmokeTestBase.kt b/diktat-ruleset/src/test/kotlin/org/cqfn/diktat/ruleset/smoke/DiktatSmokeTestBase.kt
similarity index 61%
rename from diktat-rules/src/test/kotlin/org/cqfn/diktat/ruleset/smoke/DiktatSmokeTestBase.kt
rename to diktat-ruleset/src/test/kotlin/org/cqfn/diktat/ruleset/smoke/DiktatSmokeTestBase.kt
index 9bd9f22892..e7199ae6f2 100644
--- a/diktat-rules/src/test/kotlin/org/cqfn/diktat/ruleset/smoke/DiktatSmokeTestBase.kt
+++ b/diktat-ruleset/src/test/kotlin/org/cqfn/diktat/ruleset/smoke/DiktatSmokeTestBase.kt
@@ -20,7 +20,6 @@ import org.cqfn.diktat.ruleset.constants.Warnings.MISSING_KDOC_CLASS_ELEMENTS
import org.cqfn.diktat.ruleset.constants.Warnings.MISSING_KDOC_ON_FUNCTION
import org.cqfn.diktat.ruleset.constants.Warnings.MISSING_KDOC_TOP_LEVEL
import org.cqfn.diktat.ruleset.constants.Warnings.WRONG_INDENTATION
-import org.cqfn.diktat.ruleset.rules.DiktatRuleSetProvider
import org.cqfn.diktat.ruleset.rules.chapter1.FileNaming
import org.cqfn.diktat.ruleset.rules.chapter2.comments.CommentsRule
import org.cqfn.diktat.ruleset.rules.chapter2.comments.HeaderCommentRule
@@ -29,24 +28,29 @@ import org.cqfn.diktat.ruleset.rules.chapter2.kdoc.KdocFormatting
import org.cqfn.diktat.ruleset.rules.chapter2.kdoc.KdocMethods
import org.cqfn.diktat.ruleset.rules.chapter3.EmptyBlock
import org.cqfn.diktat.ruleset.rules.chapter6.classes.InlineClassesRule
+import org.cqfn.diktat.ruleset.utils.indentation.IndentationConfig
import org.cqfn.diktat.ruleset.utils.indentation.IndentationConfig.Companion.EXTENDED_INDENT_AFTER_OPERATORS
import org.cqfn.diktat.ruleset.utils.indentation.IndentationConfig.Companion.EXTENDED_INDENT_BEFORE_DOT
import org.cqfn.diktat.ruleset.utils.indentation.IndentationConfig.Companion.EXTENDED_INDENT_FOR_EXPRESSION_BODIES
-import org.cqfn.diktat.util.FixTestBase
+import org.cqfn.diktat.test.framework.util.deleteIfExistsSilently
import com.charleskorn.kaml.Yaml
import com.charleskorn.kaml.YamlConfiguration
import com.pinterest.ktlint.core.LintError
import org.assertj.core.api.Assertions.assertThat
-import org.junit.jupiter.api.AfterEach
+import org.junit.jupiter.api.AfterAll
import org.junit.jupiter.api.Assertions
-import org.junit.jupiter.api.BeforeEach
+import org.junit.jupiter.api.BeforeAll
import org.junit.jupiter.api.Tag
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.Timeout
+import java.io.File
+import java.nio.file.Path
import java.time.LocalDate
import java.util.concurrent.TimeUnit.SECONDS
+import kotlin.io.path.createTempFile
+import kotlin.io.path.writeText
import kotlinx.serialization.builtins.ListSerializer
@@ -55,15 +59,7 @@ typealias RuleToConfig = Map>
/**
* Base class for smoke test classes
*/
-abstract class DiktatSmokeTestBase : FixTestBase("test/smoke/src/main/kotlin",
- { DiktatRuleSetProvider(configFilePath) },
- { lintError, _ -> unfixedLintErrors.add(lintError) },
-) {
- /**
- * Flag to check LintError in smoke tests
- */
- abstract val isLintErrors: Boolean
-
+abstract class DiktatSmokeTestBase {
/**
* Disable some of the rules.
*
@@ -71,7 +67,7 @@ abstract class DiktatSmokeTestBase : FixTestBase("test/smoke/src/main/kotlin",
* @param rulesToOverride
*/
@Suppress("UnsafeCallOnNullableType")
- open fun overrideRulesConfig(rulesToDisable: List, rulesToOverride: RuleToConfig = emptyMap()) {
+ private fun prepareOverriddenRulesConfig(rulesToDisable: List = emptyList(), rulesToOverride: RuleToConfig = emptyMap()): Path {
val rulesConfig = RulesConfigReader(javaClass.classLoader).readResource(DEFAULT_CONFIG_PATH)!!
.toMutableList()
.also { rulesConfig ->
@@ -85,32 +81,20 @@ abstract class DiktatSmokeTestBase : FixTestBase("test/smoke/src/main/kotlin",
}
}
.toList()
- kotlin.io.path.createTempFile()
- .toFile()
+ return createTempFile()
.also {
- configFilePath = it.absolutePath
+ it.writeText(
+ Yaml(configuration = YamlConfiguration(strictMode = true))
+ .encodeToString(ListSerializer(RulesConfig.serializer()), rulesConfig)
+ )
}
- .writeText(
- Yaml(configuration = YamlConfiguration(strictMode = true))
- .encodeToString(ListSerializer(RulesConfig.serializer()), rulesConfig)
- )
- }
-
- @BeforeEach
- fun setUp() {
- unfixedLintErrors.clear()
- }
-
- @AfterEach
- fun tearDown() {
- configFilePath = DEFAULT_CONFIG_PATH
}
@Test
@Tag("DiktatRuleSetProvider")
@Timeout(TEST_TIMEOUT_SECONDS, unit = SECONDS)
fun `regression - should not fail if package is not set`() {
- overrideRulesConfig(listOf(Warnings.PACKAGE_NAME_MISSING, Warnings.PACKAGE_NAME_INCORRECT_PATH,
+ val configFilePath = prepareOverriddenRulesConfig(listOf(Warnings.PACKAGE_NAME_MISSING, Warnings.PACKAGE_NAME_INCORRECT_PATH,
Warnings.PACKAGE_NAME_INCORRECT_PREFIX))
fixAndCompare(configFilePath, "DefaultPackageExpected.kt", "DefaultPackageTest.kt")
}
@@ -119,21 +103,21 @@ abstract class DiktatSmokeTestBase : FixTestBase("test/smoke/src/main/kotlin",
@Tag("DiktatRuleSetProvider")
@Timeout(TEST_TIMEOUT_SECONDS, unit = SECONDS)
fun `smoke test #8 - anonymous function`() {
- fixAndCompare(configFilePath, "Example8Expected.kt", "Example8Test.kt")
+ fixAndCompare(prepareOverriddenRulesConfig(), "Example8Expected.kt", "Example8Test.kt")
}
@Test
@Tag("DiktatRuleSetProvider")
@Timeout(TEST_TIMEOUT_SECONDS, unit = SECONDS)
fun `smoke test #7`() {
- fixAndCompare(configFilePath, "Example7Expected.kt", "Example7Test.kt")
+ fixAndCompare(prepareOverriddenRulesConfig(), "Example7Expected.kt", "Example7Test.kt")
}
@Test
@Tag("DiktatRuleSetProvider")
@Timeout(TEST_TIMEOUT_SECONDS, unit = SECONDS)
fun `smoke test #6`() {
- overrideRulesConfig(
+ val configFilePath = prepareOverriddenRulesConfig(
rulesToDisable = emptyList(),
rulesToOverride = mapOf(
WRONG_INDENTATION.name to mapOf(
@@ -150,7 +134,7 @@ abstract class DiktatSmokeTestBase : FixTestBase("test/smoke/src/main/kotlin",
@Tag("DiktatRuleSetProvider")
@Timeout(TEST_TIMEOUT_SECONDS, unit = SECONDS)
fun `smoke test #5`() {
- overrideRulesConfig(emptyList(),
+ val configFilePath = prepareOverriddenRulesConfig(emptyList(),
mapOf(
Warnings.HEADER_MISSING_OR_WRONG_COPYRIGHT.name to mapOf(
"isCopyrightMandatory" to "true",
@@ -170,7 +154,7 @@ abstract class DiktatSmokeTestBase : FixTestBase("test/smoke/src/main/kotlin",
)
fixAndCompare(configFilePath, "Example5Expected.kt", "Example5Test.kt")
- if (isLintErrors) {
+ assertUnfixedLintErrors { unfixedLintErrors ->
Assertions.assertFalse(
unfixedLintErrors.contains(LintError(line = 1, col = 1, ruleId = "diktat-ruleset:${CommentsRule.NAME_ID}", detail = "${Warnings.COMMENTED_OUT_CODE.warnText()} /*"))
)
@@ -185,28 +169,28 @@ abstract class DiktatSmokeTestBase : FixTestBase("test/smoke/src/main/kotlin",
@Tag("DiktatRuleSetProvider")
@Timeout(TEST_TIMEOUT_SECONDS, unit = SECONDS)
fun `smoke test #4`() {
- fixAndCompare(configFilePath, "Example4Expected.kt", "Example4Test.kt")
+ fixAndCompare(prepareOverriddenRulesConfig(), "Example4Expected.kt", "Example4Test.kt")
}
@Test
@Tag("DiktatRuleSetProvider")
@Timeout(TEST_TIMEOUT_SECONDS, unit = SECONDS)
fun `smoke test #3`() {
- fixAndCompare(configFilePath, "Example3Expected.kt", "Example3Test.kt")
+ fixAndCompare(prepareOverriddenRulesConfig(), "Example3Expected.kt", "Example3Test.kt")
}
@Test
@Tag("DiktatRuleSetProvider")
@Timeout(TEST_TIMEOUT_SECONDS, unit = SECONDS)
fun `regression - shouldn't throw exception in cases similar to #371`() {
- fixAndCompare(configFilePath, "Bug1Expected.kt", "Bug1Test.kt")
+ fixAndCompare(prepareOverriddenRulesConfig(), "Bug1Expected.kt", "Bug1Test.kt")
}
@Test
@Tag("DiktatRuleSetProvider")
@Timeout(TEST_TIMEOUT_SECONDS, unit = SECONDS)
fun `smoke test #2`() {
- overrideRulesConfig(
+ val configFilePath = prepareOverriddenRulesConfig(
rulesToDisable = emptyList(),
rulesToOverride = mapOf(
WRONG_INDENTATION.name to mapOf(
@@ -216,7 +200,7 @@ abstract class DiktatSmokeTestBase : FixTestBase("test/smoke/src/main/kotlin",
)
)
fixAndCompare(configFilePath, "Example2Expected.kt", "Example2Test.kt")
- if (isLintErrors) {
+ assertUnfixedLintErrors { unfixedLintErrors ->
assertThat(unfixedLintErrors).containsExactlyInAnyOrder(
LintError(1, 1, "$DIKTAT_RULE_SET_ID:${HeaderCommentRule.NAME_ID}",
"${HEADER_MISSING_IN_NON_SINGLE_CLASS_FILE.warnText()} there are 2 declared classes and/or objects", false),
@@ -232,7 +216,7 @@ abstract class DiktatSmokeTestBase : FixTestBase("test/smoke/src/main/kotlin",
@Tag("DiktatRuleSetProvider")
@Timeout(TEST_TIMEOUT_SECONDS, unit = SECONDS)
fun `smoke test #1`() {
- overrideRulesConfig(
+ val configFilePath = prepareOverriddenRulesConfig(
rulesToDisable = emptyList(),
rulesToOverride = mapOf(
WRONG_INDENTATION.name to mapOf(
@@ -242,7 +226,7 @@ abstract class DiktatSmokeTestBase : FixTestBase("test/smoke/src/main/kotlin",
)
)
fixAndCompare(configFilePath, "Example1Expected.kt", "Example1Test.kt")
- if (isLintErrors) {
+ assertUnfixedLintErrors { unfixedLintErrors ->
assertThat(unfixedLintErrors).containsExactlyInAnyOrder(
LintError(1, 1, "$DIKTAT_RULE_SET_ID:${FileNaming.NAME_ID}", "${FILE_NAME_MATCH_CLASS.warnText()} Example1Test.kt vs Example", true),
LintError(1, 1, "$DIKTAT_RULE_SET_ID:${KdocFormatting.NAME_ID}", "${KDOC_NO_EMPTY_TAGS.warnText()} @return", false),
@@ -269,35 +253,35 @@ abstract class DiktatSmokeTestBase : FixTestBase("test/smoke/src/main/kotlin",
@Tag("DiktatRuleSetProvider")
@Timeout(TEST_TIMEOUT_SECONDS, unit = SECONDS)
fun `smoke test with kts files #2`() {
- fixAndCompare(configFilePath, "script/SimpleRunInScriptExpected.kts", "script/SimpleRunInScriptTest.kts")
+ fixAndCompare(prepareOverriddenRulesConfig(), "script/SimpleRunInScriptExpected.kts", "script/SimpleRunInScriptTest.kts")
}
@Test
@Tag("DiktatRuleSetProvider")
@Timeout(TEST_TIMEOUT_SECONDS, unit = SECONDS)
fun `smoke test with kts files with package name`() {
- fixAndCompare(configFilePath, "script/PackageInScriptExpected.kts", "script/PackageInScriptTest.kts")
+ fixAndCompare(prepareOverriddenRulesConfig(), "script/PackageInScriptExpected.kts", "script/PackageInScriptTest.kts")
}
@Test
@Tag("DiktatRuleSetProvider")
@Timeout(TEST_TIMEOUT_SECONDS, unit = SECONDS)
fun `regression - should correctly handle tags with empty lines`() {
- fixAndCompare(configFilePath, "KdocFormattingMultilineTagsExpected.kt", "KdocFormattingMultilineTagsTest.kt")
+ fixAndCompare(prepareOverriddenRulesConfig(), "KdocFormattingMultilineTagsExpected.kt", "KdocFormattingMultilineTagsTest.kt")
}
@Test
@Tag("DiktatRuleSetProvider")
@Timeout(TEST_TIMEOUT_SECONDS, unit = SECONDS)
fun `regression - FP of local variables rule`() {
- fixAndCompare(configFilePath, "LocalVariableWithOffsetExpected.kt", "LocalVariableWithOffsetTest.kt")
+ fixAndCompare(prepareOverriddenRulesConfig(), "LocalVariableWithOffsetExpected.kt", "LocalVariableWithOffsetTest.kt")
}
@Test
@Tag("DiktatRuleSetProvider")
@Timeout(TEST_TIMEOUT_SECONDS, unit = SECONDS)
fun `fix can cause long line`() {
- overrideRulesConfig(
+ val configFilePath = prepareOverriddenRulesConfig(
rulesToDisable = emptyList(),
rulesToOverride = mapOf(
WRONG_INDENTATION.name to mapOf(
@@ -308,18 +292,119 @@ abstract class DiktatSmokeTestBase : FixTestBase("test/smoke/src/main/kotlin",
fixAndCompare(configFilePath, "ManyLineTransformInLongLineExpected.kt", "ManyLineTransformInLongLineTest.kt")
}
+ @Test
+ @Tag("DiktatRuleSetProvider")
+ fun `smoke test with multiplatform project layout`() {
+ fixAndCompare(
+ prepareOverriddenRulesConfig(),
+ "../../jsMain/kotlin/org/cqfn/diktat/scripts/ScriptExpected.kt",
+ "../../jsMain/kotlin/org/cqfn/diktat/scripts/ScriptTest.kt"
+ )
+ }
+
+ @Test
+ @Tag("DiktatRuleSetProvider")
+ fun `smoke test with kts files`() {
+ val configFilePath = prepareOverriddenRulesConfig(
+ emptyList(),
+ mapOf(
+ WRONG_INDENTATION.name to mapOf(
+ IndentationConfig.NEWLINE_AT_END to "false",
+ )
+ )
+ ) // so that trailing newline isn't checked, because it's incorrectly read in tests and we are comparing file with itself
+ // file name is `gradle_` so that IDE doesn't suggest to import gradle project
+ val tmpFilePath = "../../../build.gradle.kts"
+ fixAndCompare(configFilePath, tmpFilePath, tmpFilePath, false)
+ assertUnfixedLintErrors { unfixedLintErrors ->
+ Assertions.assertTrue(unfixedLintErrors.isEmpty())
+ }
+ }
+
+ @Test
+ @Tag("DiktatRuleSetProvider")
+ fun `smoke test with gradle script plugin`() {
+ fixAndCompare(prepareOverriddenRulesConfig(), "kotlin-library-expected.gradle.kts", "kotlin-library.gradle.kts")
+ assertUnfixedLintErrors { unfixedLintErrors ->
+ assertThat(unfixedLintErrors).containsExactly(
+ LintError(
+ 2, 1, "$DIKTAT_RULE_SET_ID:${CommentsRule.NAME_ID}", "[COMMENTED_OUT_CODE] you should not comment out code, " +
+ "use VCS to save it in history and delete this block: import org.jetbrains.kotlin.gradle.dsl.jvm", false
+ )
+ )
+ }
+ }
+
+ @Test
+ @Tag("DiktatRuleSetProvider")
+ fun `disable chapters`() {
+ val configFilePath = prepareOverriddenRulesConfig(
+ emptyList(),
+ mapOf(
+ DIKTAT_COMMON to mapOf(
+ "domainName" to "org.cqfn.diktat",
+ "disabledChapters" to "Naming,3,4,5,Classes"
+ )
+ )
+ )
+ fixAndCompare(configFilePath, "Example1-2Expected.kt", "Example1-2Test.kt")
+ assertUnfixedLintErrors { unfixedLintErrors ->
+ assertThat(unfixedLintErrors).containsExactlyInAnyOrder(
+ LintError(1, 1, "$DIKTAT_RULE_SET_ID:${KdocFormatting.NAME_ID}", "${KDOC_NO_EMPTY_TAGS.warnText()} @return", false),
+ LintError(3, 1, "$DIKTAT_RULE_SET_ID:${KdocComments.NAME_ID}", "${MISSING_KDOC_TOP_LEVEL.warnText()} example", false),
+ LintError(3, 16, "$DIKTAT_RULE_SET_ID:${KdocComments.NAME_ID}", "${MISSING_KDOC_CLASS_ELEMENTS.warnText()} isValid", false),
+ LintError(6, 5, "$DIKTAT_RULE_SET_ID:${KdocComments.NAME_ID}", "${MISSING_KDOC_CLASS_ELEMENTS.warnText()} foo", false),
+ LintError(6, 5, "$DIKTAT_RULE_SET_ID:${KdocMethods.NAME_ID}", "${MISSING_KDOC_ON_FUNCTION.warnText()} foo", false),
+ LintError(8, 5, "$DIKTAT_RULE_SET_ID:${KdocComments.NAME_ID}", "${MISSING_KDOC_CLASS_ELEMENTS.warnText()} foo", false),
+ LintError(10, 4, "$DIKTAT_RULE_SET_ID:${KdocFormatting.NAME_ID}", "${KDOC_NO_EMPTY_TAGS.warnText()} @return", false),
+ LintError(13, 9, "$DIKTAT_RULE_SET_ID:${KdocFormatting.NAME_ID}", "${KDOC_NO_EMPTY_TAGS.warnText()} @return", false),
+ LintError(18, 40, "$DIKTAT_RULE_SET_ID:${KdocFormatting.NAME_ID}", "${KDOC_NO_EMPTY_TAGS.warnText()} @return", false)
+ )
+ }
+ }
+
abstract fun fixAndCompare(
- config: String,
+ config: Path,
expected: String,
test: String,
+ trimLastEmptyLine: Boolean = true,
)
+ abstract fun assertUnfixedLintErrors(lintErrorsConsumer: (List) -> Unit)
+
companion object {
- const val DEFAULT_CONFIG_PATH = "../diktat-analysis.yml"
+ private const val DEFAULT_CONFIG_PATH = "../diktat-analysis.yml"
+ const val RESOURCE_FILE_PATH = "test/smoke/src/main/kotlin"
private const val TEST_TIMEOUT_SECONDS = 25L
- val unfixedLintErrors: MutableList = mutableListOf()
+ private val tmpFiles: MutableList = mutableListOf()
- // by default using same yml config as for diktat code style check, but allow to override
- var configFilePath = DEFAULT_CONFIG_PATH
+ @BeforeAll
+ @JvmStatic
+ @Suppress("AVOID_NULL_CHECKS")
+ internal fun createTmpFiles() {
+ listOf(
+ "$RESOURCE_FILE_PATH/../../../build.gradle_.kts" to "build.gradle.kts",
+ "$RESOURCE_FILE_PATH/Example1Test.kt" to "Example1-2Test.kt",
+ )
+ .map { (resource, targetFileName) ->
+ DiktatSmokeTestBase::class.java
+ .classLoader
+ .getResource(resource)!!
+ .toURI()
+ .let {
+ val tmpTestFile = File(it).parentFile.resolve(targetFileName)
+ File(it).copyTo(tmpTestFile, true)
+ }
+ .let { tmpFiles.add(it) }
+ }
+ }
+
+ @AfterAll
+ @JvmStatic
+ internal fun deleteTmpFiles() {
+ tmpFiles.forEach {
+ it.toPath().deleteIfExistsSilently()
+ }
+ }
}
}
diff --git a/diktat-ruleset/src/test/kotlin/org/cqfn/diktat/util/SmokeTestUtils.kt b/diktat-ruleset/src/test/kotlin/org/cqfn/diktat/util/SmokeTestUtils.kt
new file mode 100644
index 0000000000..8b69310762
--- /dev/null
+++ b/diktat-ruleset/src/test/kotlin/org/cqfn/diktat/util/SmokeTestUtils.kt
@@ -0,0 +1,77 @@
+/**
+ * Utility classes and methods for tests
+ */
+
+package org.cqfn.diktat.util
+
+import java.io.File
+import java.nio.file.NoSuchFileException
+import java.nio.file.Path
+import kotlin.io.path.isDirectory
+import kotlin.io.path.isSameFileAs
+
+/**
+ * @receiver the 1st operand.
+ * @param other the 2nd operand.
+ * @return `true` if, and only if, the two paths locate the same `JAVA_HOME`.
+ */
+internal fun Path.isSameJavaHomeAs(other: Path): Boolean =
+ isDirectory() &&
+ (isSameFileAsSafe(other) ||
+ resolve("jre").isSameFileAsSafe(other) ||
+ other.resolve("jre").isSameFileAsSafe(this))
+
+/**
+ * The same as [Path.isSameFileAs], but doesn't throw any [NoSuchFileException]
+ * if either of the operands doesn't exist.
+ *
+ * @receiver the 1st operand.
+ * @param other the 2nd operand.
+ * @return `true` if, and only if, the two paths locate the same file.
+ * @see Path.isSameFileAs
+ */
+internal fun Path.isSameFileAsSafe(other: Path): Boolean =
+ try {
+ isSameFileAs(other)
+ } catch (_: NoSuchFileException) {
+ false
+ }
+
+/**
+ * Prepends the `PATH` of this process builder with [pathEntry].
+ *
+ * @param pathEntry the entry to be prepended to the `PATH`.
+ */
+internal fun ProcessBuilder.prependPath(pathEntry: Path) {
+ require(pathEntry.isDirectory()) {
+ "$pathEntry is not a directory"
+ }
+
+ val environment = environment()
+
+ val defaultPathKey = "PATH"
+ val defaultWindowsPathKey = "Path"
+
+ val pathKey = when {
+ /*-
+ * Keys of the Windows environment are case-insensitive ("PATH" == "Path").
+ * Keys of the Java interface to the environment are not ("PATH" != "Path").
+ * This is an attempt to work around the inconsistency.
+ */
+ System.getProperty("os.name").startsWith("Windows") -> environment.keys.firstOrNull { key ->
+ key.equals(defaultPathKey, ignoreCase = true)
+ } ?: defaultWindowsPathKey
+
+ else -> defaultPathKey
+ }
+
+ val pathSeparator = File.pathSeparatorChar
+ val oldPath = environment[pathKey]
+
+ val newPath = when {
+ oldPath.isNullOrEmpty() -> pathEntry.toString()
+ else -> "$pathEntry$pathSeparator$oldPath"
+ }
+
+ environment[pathKey] = newPath
+}
diff --git a/diktat-rules/src/test/resources/test/smoke/.gitignore b/diktat-ruleset/src/test/resources/test/smoke/.gitignore
similarity index 100%
rename from diktat-rules/src/test/resources/test/smoke/.gitignore
rename to diktat-ruleset/src/test/resources/test/smoke/.gitignore
diff --git a/diktat-rules/src/test/resources/test/smoke/build.gradle_.kts b/diktat-ruleset/src/test/resources/test/smoke/build.gradle_.kts
similarity index 100%
rename from diktat-rules/src/test/resources/test/smoke/build.gradle_.kts
rename to diktat-ruleset/src/test/resources/test/smoke/build.gradle_.kts
diff --git a/diktat-rules/src/test/resources/test/smoke/save.toml b/diktat-ruleset/src/test/resources/test/smoke/save.toml
similarity index 96%
rename from diktat-rules/src/test/resources/test/smoke/save.toml
rename to diktat-ruleset/src/test/resources/test/smoke/save.toml
index 54611e9109..bebb752e9d 100644
--- a/diktat-rules/src/test/resources/test/smoke/save.toml
+++ b/diktat-ruleset/src/test/resources/test/smoke/save.toml
@@ -5,6 +5,7 @@ description = "SmokeTest"
suiteName = "SmokeTest"
language = "Kotlin"
expectedWarningsPattern = "// ;warn:?(.*):(\\d*): (.+)"
+timeOutMillis = 3600000
["fix and warn"]
["fix and warn".fix]
diff --git a/diktat-rules/src/test/resources/test/smoke/src/jsMain/kotlin/org/cqfn/diktat/scripts/ScriptExpected.kt b/diktat-ruleset/src/test/resources/test/smoke/src/jsMain/kotlin/org/cqfn/diktat/scripts/ScriptExpected.kt
similarity index 100%
rename from diktat-rules/src/test/resources/test/smoke/src/jsMain/kotlin/org/cqfn/diktat/scripts/ScriptExpected.kt
rename to diktat-ruleset/src/test/resources/test/smoke/src/jsMain/kotlin/org/cqfn/diktat/scripts/ScriptExpected.kt
diff --git a/diktat-rules/src/test/resources/test/smoke/src/jsMain/kotlin/org/cqfn/diktat/scripts/ScriptTest.kt b/diktat-ruleset/src/test/resources/test/smoke/src/jsMain/kotlin/org/cqfn/diktat/scripts/ScriptTest.kt
similarity index 100%
rename from diktat-rules/src/test/resources/test/smoke/src/jsMain/kotlin/org/cqfn/diktat/scripts/ScriptTest.kt
rename to diktat-ruleset/src/test/resources/test/smoke/src/jsMain/kotlin/org/cqfn/diktat/scripts/ScriptTest.kt
diff --git a/diktat-rules/src/test/resources/test/smoke/src/main/kotlin/Bug1Expected.kt b/diktat-ruleset/src/test/resources/test/smoke/src/main/kotlin/Bug1Expected.kt
similarity index 100%
rename from diktat-rules/src/test/resources/test/smoke/src/main/kotlin/Bug1Expected.kt
rename to diktat-ruleset/src/test/resources/test/smoke/src/main/kotlin/Bug1Expected.kt
diff --git a/diktat-rules/src/test/resources/test/smoke/src/main/kotlin/Bug1Test.kt b/diktat-ruleset/src/test/resources/test/smoke/src/main/kotlin/Bug1Test.kt
similarity index 100%
rename from diktat-rules/src/test/resources/test/smoke/src/main/kotlin/Bug1Test.kt
rename to diktat-ruleset/src/test/resources/test/smoke/src/main/kotlin/Bug1Test.kt
diff --git a/diktat-rules/src/test/resources/test/smoke/src/main/kotlin/DefaultPackageExpected.kt b/diktat-ruleset/src/test/resources/test/smoke/src/main/kotlin/DefaultPackageExpected.kt
similarity index 100%
rename from diktat-rules/src/test/resources/test/smoke/src/main/kotlin/DefaultPackageExpected.kt
rename to diktat-ruleset/src/test/resources/test/smoke/src/main/kotlin/DefaultPackageExpected.kt
diff --git a/diktat-rules/src/test/resources/test/smoke/src/main/kotlin/DefaultPackageTest.kt b/diktat-ruleset/src/test/resources/test/smoke/src/main/kotlin/DefaultPackageTest.kt
similarity index 100%
rename from diktat-rules/src/test/resources/test/smoke/src/main/kotlin/DefaultPackageTest.kt
rename to diktat-ruleset/src/test/resources/test/smoke/src/main/kotlin/DefaultPackageTest.kt
diff --git a/diktat-rules/src/test/resources/test/smoke/src/main/kotlin/Example1-2Expected.kt b/diktat-ruleset/src/test/resources/test/smoke/src/main/kotlin/Example1-2Expected.kt
similarity index 100%
rename from diktat-rules/src/test/resources/test/smoke/src/main/kotlin/Example1-2Expected.kt
rename to diktat-ruleset/src/test/resources/test/smoke/src/main/kotlin/Example1-2Expected.kt
diff --git a/diktat-rules/src/test/resources/test/smoke/src/main/kotlin/Example1Expected.kt b/diktat-ruleset/src/test/resources/test/smoke/src/main/kotlin/Example1Expected.kt
similarity index 100%
rename from diktat-rules/src/test/resources/test/smoke/src/main/kotlin/Example1Expected.kt
rename to diktat-ruleset/src/test/resources/test/smoke/src/main/kotlin/Example1Expected.kt
diff --git a/diktat-rules/src/test/resources/test/smoke/src/main/kotlin/Example1Test.kt b/diktat-ruleset/src/test/resources/test/smoke/src/main/kotlin/Example1Test.kt
similarity index 100%
rename from diktat-rules/src/test/resources/test/smoke/src/main/kotlin/Example1Test.kt
rename to diktat-ruleset/src/test/resources/test/smoke/src/main/kotlin/Example1Test.kt
diff --git a/diktat-rules/src/test/resources/test/smoke/src/main/kotlin/Example2Expected.kt b/diktat-ruleset/src/test/resources/test/smoke/src/main/kotlin/Example2Expected.kt
similarity index 100%
rename from diktat-rules/src/test/resources/test/smoke/src/main/kotlin/Example2Expected.kt
rename to diktat-ruleset/src/test/resources/test/smoke/src/main/kotlin/Example2Expected.kt
diff --git a/diktat-rules/src/test/resources/test/smoke/src/main/kotlin/Example2Test.kt b/diktat-ruleset/src/test/resources/test/smoke/src/main/kotlin/Example2Test.kt
similarity index 100%
rename from diktat-rules/src/test/resources/test/smoke/src/main/kotlin/Example2Test.kt
rename to diktat-ruleset/src/test/resources/test/smoke/src/main/kotlin/Example2Test.kt
diff --git a/diktat-rules/src/test/resources/test/smoke/src/main/kotlin/Example3Expected.kt b/diktat-ruleset/src/test/resources/test/smoke/src/main/kotlin/Example3Expected.kt
similarity index 100%
rename from diktat-rules/src/test/resources/test/smoke/src/main/kotlin/Example3Expected.kt
rename to diktat-ruleset/src/test/resources/test/smoke/src/main/kotlin/Example3Expected.kt
diff --git a/diktat-rules/src/test/resources/test/smoke/src/main/kotlin/Example3Test.kt b/diktat-ruleset/src/test/resources/test/smoke/src/main/kotlin/Example3Test.kt
similarity index 100%
rename from diktat-rules/src/test/resources/test/smoke/src/main/kotlin/Example3Test.kt
rename to diktat-ruleset/src/test/resources/test/smoke/src/main/kotlin/Example3Test.kt
diff --git a/diktat-rules/src/test/resources/test/smoke/src/main/kotlin/Example4Expected.kt b/diktat-ruleset/src/test/resources/test/smoke/src/main/kotlin/Example4Expected.kt
similarity index 100%
rename from diktat-rules/src/test/resources/test/smoke/src/main/kotlin/Example4Expected.kt
rename to diktat-ruleset/src/test/resources/test/smoke/src/main/kotlin/Example4Expected.kt
diff --git a/diktat-rules/src/test/resources/test/smoke/src/main/kotlin/Example4Test.kt b/diktat-ruleset/src/test/resources/test/smoke/src/main/kotlin/Example4Test.kt
similarity index 100%
rename from diktat-rules/src/test/resources/test/smoke/src/main/kotlin/Example4Test.kt
rename to diktat-ruleset/src/test/resources/test/smoke/src/main/kotlin/Example4Test.kt
diff --git a/diktat-rules/src/test/resources/test/smoke/src/main/kotlin/Example5Expected.kt b/diktat-ruleset/src/test/resources/test/smoke/src/main/kotlin/Example5Expected.kt
similarity index 100%
rename from diktat-rules/src/test/resources/test/smoke/src/main/kotlin/Example5Expected.kt
rename to diktat-ruleset/src/test/resources/test/smoke/src/main/kotlin/Example5Expected.kt
diff --git a/diktat-rules/src/test/resources/test/smoke/src/main/kotlin/Example5Test.kt b/diktat-ruleset/src/test/resources/test/smoke/src/main/kotlin/Example5Test.kt
similarity index 100%
rename from diktat-rules/src/test/resources/test/smoke/src/main/kotlin/Example5Test.kt
rename to diktat-ruleset/src/test/resources/test/smoke/src/main/kotlin/Example5Test.kt
diff --git a/diktat-rules/src/test/resources/test/smoke/src/main/kotlin/Example6Expected.kt b/diktat-ruleset/src/test/resources/test/smoke/src/main/kotlin/Example6Expected.kt
similarity index 100%
rename from diktat-rules/src/test/resources/test/smoke/src/main/kotlin/Example6Expected.kt
rename to diktat-ruleset/src/test/resources/test/smoke/src/main/kotlin/Example6Expected.kt
diff --git a/diktat-rules/src/test/resources/test/smoke/src/main/kotlin/Example6Test.kt b/diktat-ruleset/src/test/resources/test/smoke/src/main/kotlin/Example6Test.kt
similarity index 100%
rename from diktat-rules/src/test/resources/test/smoke/src/main/kotlin/Example6Test.kt
rename to diktat-ruleset/src/test/resources/test/smoke/src/main/kotlin/Example6Test.kt
diff --git a/diktat-rules/src/test/resources/test/smoke/src/main/kotlin/Example7Expected.kt b/diktat-ruleset/src/test/resources/test/smoke/src/main/kotlin/Example7Expected.kt
similarity index 100%
rename from diktat-rules/src/test/resources/test/smoke/src/main/kotlin/Example7Expected.kt
rename to diktat-ruleset/src/test/resources/test/smoke/src/main/kotlin/Example7Expected.kt
diff --git a/diktat-rules/src/test/resources/test/smoke/src/main/kotlin/Example7Test.kt b/diktat-ruleset/src/test/resources/test/smoke/src/main/kotlin/Example7Test.kt
similarity index 100%
rename from diktat-rules/src/test/resources/test/smoke/src/main/kotlin/Example7Test.kt
rename to diktat-ruleset/src/test/resources/test/smoke/src/main/kotlin/Example7Test.kt
diff --git a/diktat-rules/src/test/resources/test/smoke/src/main/kotlin/Example8Expected.kt b/diktat-ruleset/src/test/resources/test/smoke/src/main/kotlin/Example8Expected.kt
similarity index 100%
rename from diktat-rules/src/test/resources/test/smoke/src/main/kotlin/Example8Expected.kt
rename to diktat-ruleset/src/test/resources/test/smoke/src/main/kotlin/Example8Expected.kt
diff --git a/diktat-rules/src/test/resources/test/smoke/src/main/kotlin/Example8Test.kt b/diktat-ruleset/src/test/resources/test/smoke/src/main/kotlin/Example8Test.kt
similarity index 100%
rename from diktat-rules/src/test/resources/test/smoke/src/main/kotlin/Example8Test.kt
rename to diktat-ruleset/src/test/resources/test/smoke/src/main/kotlin/Example8Test.kt
diff --git a/diktat-rules/src/test/resources/test/smoke/src/main/kotlin/KdocFormattingMultilineTagsExpected.kt b/diktat-ruleset/src/test/resources/test/smoke/src/main/kotlin/KdocFormattingMultilineTagsExpected.kt
similarity index 100%
rename from diktat-rules/src/test/resources/test/smoke/src/main/kotlin/KdocFormattingMultilineTagsExpected.kt
rename to diktat-ruleset/src/test/resources/test/smoke/src/main/kotlin/KdocFormattingMultilineTagsExpected.kt
diff --git a/diktat-rules/src/test/resources/test/smoke/src/main/kotlin/KdocFormattingMultilineTagsTest.kt b/diktat-ruleset/src/test/resources/test/smoke/src/main/kotlin/KdocFormattingMultilineTagsTest.kt
similarity index 100%
rename from diktat-rules/src/test/resources/test/smoke/src/main/kotlin/KdocFormattingMultilineTagsTest.kt
rename to diktat-ruleset/src/test/resources/test/smoke/src/main/kotlin/KdocFormattingMultilineTagsTest.kt
diff --git a/diktat-rules/src/test/resources/test/smoke/src/main/kotlin/LocalVariableWithOffsetExpected.kt b/diktat-ruleset/src/test/resources/test/smoke/src/main/kotlin/LocalVariableWithOffsetExpected.kt
similarity index 100%
rename from diktat-rules/src/test/resources/test/smoke/src/main/kotlin/LocalVariableWithOffsetExpected.kt
rename to diktat-ruleset/src/test/resources/test/smoke/src/main/kotlin/LocalVariableWithOffsetExpected.kt
diff --git a/diktat-rules/src/test/resources/test/smoke/src/main/kotlin/LocalVariableWithOffsetTest.kt b/diktat-ruleset/src/test/resources/test/smoke/src/main/kotlin/LocalVariableWithOffsetTest.kt
similarity index 100%
rename from diktat-rules/src/test/resources/test/smoke/src/main/kotlin/LocalVariableWithOffsetTest.kt
rename to diktat-ruleset/src/test/resources/test/smoke/src/main/kotlin/LocalVariableWithOffsetTest.kt
diff --git a/diktat-rules/src/test/resources/test/smoke/src/main/kotlin/ManyLineTransformInLongLineExpected.kt b/diktat-ruleset/src/test/resources/test/smoke/src/main/kotlin/ManyLineTransformInLongLineExpected.kt
similarity index 100%
rename from diktat-rules/src/test/resources/test/smoke/src/main/kotlin/ManyLineTransformInLongLineExpected.kt
rename to diktat-ruleset/src/test/resources/test/smoke/src/main/kotlin/ManyLineTransformInLongLineExpected.kt
diff --git a/diktat-rules/src/test/resources/test/smoke/src/main/kotlin/ManyLineTransformInLongLineTest.kt b/diktat-ruleset/src/test/resources/test/smoke/src/main/kotlin/ManyLineTransformInLongLineTest.kt
similarity index 100%
rename from diktat-rules/src/test/resources/test/smoke/src/main/kotlin/ManyLineTransformInLongLineTest.kt
rename to diktat-ruleset/src/test/resources/test/smoke/src/main/kotlin/ManyLineTransformInLongLineTest.kt
diff --git a/diktat-rules/src/test/resources/test/smoke/src/main/kotlin/kotlin-library-expected.gradle.kts b/diktat-ruleset/src/test/resources/test/smoke/src/main/kotlin/kotlin-library-expected.gradle.kts
similarity index 100%
rename from diktat-rules/src/test/resources/test/smoke/src/main/kotlin/kotlin-library-expected.gradle.kts
rename to diktat-ruleset/src/test/resources/test/smoke/src/main/kotlin/kotlin-library-expected.gradle.kts
diff --git a/diktat-rules/src/test/resources/test/smoke/src/main/kotlin/kotlin-library.gradle.kts b/diktat-ruleset/src/test/resources/test/smoke/src/main/kotlin/kotlin-library.gradle.kts
similarity index 100%
rename from diktat-rules/src/test/resources/test/smoke/src/main/kotlin/kotlin-library.gradle.kts
rename to diktat-ruleset/src/test/resources/test/smoke/src/main/kotlin/kotlin-library.gradle.kts
diff --git a/diktat-rules/src/test/resources/test/smoke/src/main/kotlin/save.toml b/diktat-ruleset/src/test/resources/test/smoke/src/main/kotlin/save.toml
similarity index 100%
rename from diktat-rules/src/test/resources/test/smoke/src/main/kotlin/save.toml
rename to diktat-ruleset/src/test/resources/test/smoke/src/main/kotlin/save.toml
diff --git a/diktat-rules/src/test/resources/test/smoke/src/main/kotlin/script/PackageInScriptExpected.kts b/diktat-ruleset/src/test/resources/test/smoke/src/main/kotlin/script/PackageInScriptExpected.kts
similarity index 100%
rename from diktat-rules/src/test/resources/test/smoke/src/main/kotlin/script/PackageInScriptExpected.kts
rename to diktat-ruleset/src/test/resources/test/smoke/src/main/kotlin/script/PackageInScriptExpected.kts
diff --git a/diktat-rules/src/test/resources/test/smoke/src/main/kotlin/script/PackageInScriptTest.kts b/diktat-ruleset/src/test/resources/test/smoke/src/main/kotlin/script/PackageInScriptTest.kts
similarity index 100%
rename from diktat-rules/src/test/resources/test/smoke/src/main/kotlin/script/PackageInScriptTest.kts
rename to diktat-ruleset/src/test/resources/test/smoke/src/main/kotlin/script/PackageInScriptTest.kts
diff --git a/diktat-rules/src/test/resources/test/smoke/src/main/kotlin/script/SimpleRunInScriptExpected.kts b/diktat-ruleset/src/test/resources/test/smoke/src/main/kotlin/script/SimpleRunInScriptExpected.kts
similarity index 100%
rename from diktat-rules/src/test/resources/test/smoke/src/main/kotlin/script/SimpleRunInScriptExpected.kts
rename to diktat-ruleset/src/test/resources/test/smoke/src/main/kotlin/script/SimpleRunInScriptExpected.kts
diff --git a/diktat-rules/src/test/resources/test/smoke/src/main/kotlin/script/SimpleRunInScriptTest.kts b/diktat-ruleset/src/test/resources/test/smoke/src/main/kotlin/script/SimpleRunInScriptTest.kts
similarity index 100%
rename from diktat-rules/src/test/resources/test/smoke/src/main/kotlin/script/SimpleRunInScriptTest.kts
rename to diktat-ruleset/src/test/resources/test/smoke/src/main/kotlin/script/SimpleRunInScriptTest.kts
diff --git a/diktat-test-framework/src/main/kotlin/org/cqfn/diktat/test/framework/processing/TestComparatorUnit.kt b/diktat-test-framework/src/main/kotlin/org/cqfn/diktat/test/framework/processing/TestComparatorUnit.kt
index 36d592bcde..3d77f1419f 100644
--- a/diktat-test-framework/src/main/kotlin/org/cqfn/diktat/test/framework/processing/TestComparatorUnit.kt
+++ b/diktat-test-framework/src/main/kotlin/org/cqfn/diktat/test/framework/processing/TestComparatorUnit.kt
@@ -20,8 +20,10 @@ import kotlin.io.path.readLines
* @property function a transformation that will be applied to the file
*/
@Suppress("ForbiddenComment", "TYPE_ALIAS")
-class TestComparatorUnit(private val resourceFilePath: String,
- private val function: (expectedText: String, testFilePath: String) -> String) {
+class TestComparatorUnit(
+ private val resourceFilePath: String,
+ private val function: (expectedText: String, testFilePath: String) -> String,
+) {
/**
* @param expectedResult the name of the resource which has the expected
* content. The trailing newline, if any, **won't be read** as a separate
@@ -32,7 +34,7 @@ class TestComparatorUnit(private val resourceFilePath: String,
* @param testFileStr the name of the resource which has the original content.
* @param trimLastEmptyLine whether the last (empty) line should be
* discarded when reading the content of [testFileStr].
- * @return `true` if transformed file equals expected result, `false` otherwise.
+ * @return the result of file comparison by their content.
* @see compareFilesFromFileSystem
*/
@Suppress("FUNCTION_BOOLEAN_PREFIX")
@@ -40,18 +42,21 @@ class TestComparatorUnit(private val resourceFilePath: String,
expectedResult: String,
testFileStr: String,
trimLastEmptyLine: Boolean = false
- ): Boolean {
+ ): FileComparisonResult {
val expectedPath = javaClass.classLoader.getResource("$resourceFilePath/$expectedResult")
val testPath = javaClass.classLoader.getResource("$resourceFilePath/$testFileStr")
if (testPath == null || expectedPath == null) {
log.error("Not able to find files for running test: $expectedResult and $testFileStr")
- return false
+ return FileComparisonResult(
+ isSuccessful = false,
+ actualContent = "// $resourceFilePath/$expectedResult is found: ${testPath != null}",
+ expectedContent = "// $resourceFilePath/$testFileStr is found: ${expectedPath != null}")
}
return compareFilesFromFileSystem(
Paths.get(expectedPath.toURI()),
Paths.get(testPath.toURI()),
- trimLastEmptyLine).isSuccessful
+ trimLastEmptyLine)
}
/**
diff --git a/diktat-test-framework/src/main/kotlin/org/cqfn/diktat/test/framework/util/TestUtils.kt b/diktat-test-framework/src/main/kotlin/org/cqfn/diktat/test/framework/util/TestUtils.kt
new file mode 100644
index 0000000000..564297cf38
--- /dev/null
+++ b/diktat-test-framework/src/main/kotlin/org/cqfn/diktat/test/framework/util/TestUtils.kt
@@ -0,0 +1,131 @@
+/**
+ * Utility classes and methods for tests
+ */
+
+package org.cqfn.diktat.test.framework.util
+
+import org.cqfn.diktat.common.utils.loggerWithKtlintConfig
+
+import mu.KotlinLogging
+
+import java.io.IOException
+import java.nio.file.FileVisitResult
+import java.nio.file.FileVisitResult.CONTINUE
+import java.nio.file.Files.walkFileTree
+import java.nio.file.NoSuchFileException
+import java.nio.file.Path
+import java.nio.file.SimpleFileVisitor
+import java.nio.file.attribute.BasicFileAttributes
+
+import kotlin.io.path.absolute
+import kotlin.io.path.deleteExisting
+import kotlin.io.path.deleteIfExists
+
+@Suppress("EMPTY_BLOCK_STRUCTURE_ERROR")
+private val log = KotlinLogging.loggerWithKtlintConfig {}
+
+/**
+ * Deletes the file if it exists, retrying as necessary if the file is
+ * blocked by another process (on Windows).
+ *
+ * @receiver the file or empty directory.
+ * @see Path.deleteIfExists
+ */
+@Suppress(
+ "EMPTY_BLOCK_STRUCTURE_ERROR",
+ "MAGIC_NUMBER",
+)
+fun Path.deleteIfExistsSilently() {
+ val attempts = 10
+
+ val deleted = retry(attempts, delayMillis = 100L, lazyDefault = { false }) {
+ deleteIfExists()
+
+ /*
+ * Ignore the return code of `deleteIfExists()` (will be `false`
+ * if the file doesn't exist).
+ */
+ true
+ }
+
+ if (!deleted) {
+ log.warn {
+ "File \"${absolute()}\" not deleted after $attempts attempt(s)."
+ }
+ }
+}
+
+/**
+ * Deletes this directory recursively.
+ *
+ * @see Path.deleteIfExistsRecursively
+ */
+fun Path.deleteRecursively() {
+ walkFileTree(this, object : SimpleFileVisitor() {
+ override fun visitFile(file: Path, attrs: BasicFileAttributes): FileVisitResult {
+ file.deleteIfExistsSilently()
+ return CONTINUE
+ }
+
+ override fun postVisitDirectory(dir: Path, exc: IOException?): FileVisitResult {
+ dir.deleteExisting()
+ return CONTINUE
+ }
+ })
+}
+
+/**
+ * Deletes this directory recursively if it exists.
+ *
+ * @return `true` if the existing directory was successfully deleted, `false` if
+ * the directory doesn't exist.
+ * @see Files.deleteIfExists
+ * @see Path.deleteRecursively
+ */
+@Suppress("FUNCTION_BOOLEAN_PREFIX")
+fun Path.deleteIfExistsRecursively(): Boolean =
+ try {
+ deleteRecursively()
+ true
+ } catch (_: NoSuchFileException) {
+ false
+ }
+
+/**
+ * Retries the execution of the [block].
+ *
+ * @param attempts the number of attempts (must be positive).
+ * @param delayMillis the timeout (in milliseconds) between the consecutive
+ * attempts. The default is 0. Ignored if [attempts] is 1.
+ * @param lazyDefault allows to override the return value if none of the
+ * attempts succeeds. By default, the last exception is thrown.
+ * @param block the block to execute.
+ * @return the result of the execution of the [block], or whatever [lazyDefault]
+ * evaluates to if none of the attempts is successful.
+ */
+fun retry(
+ attempts: Int,
+ delayMillis: Long = 0L,
+ lazyDefault: (Throwable) -> T = { error -> throw error },
+ block: () -> T
+): T {
+ require(attempts > 0) {
+ "The number of attempts should be positive: $attempts"
+ }
+
+ var lastError: Throwable? = null
+
+ for (i in 1..attempts) {
+ try {
+ return block()
+ } catch (error: Throwable) {
+ lastError = error
+ }
+
+ if (delayMillis > 0L) {
+ Thread.sleep(delayMillis)
+ }
+ }
+
+ return lazyDefault(lastError ?: Exception("The block was never executed"))
+}
diff --git a/pom.xml b/pom.xml
index cfff28661b..fe5327fbbb 100644
--- a/pom.xml
+++ b/pom.xml
@@ -49,6 +49,7 @@
0.47.1
5.9.0
1.9.0
+ 1.1.0
31.1-jre
1.7.36
1.5.0
@@ -60,7 +61,6 @@
3.6.4
1.24
2.18.0
- 1.1.0
@@ -92,6 +92,11 @@
kotlin-stdlib
${kotlin.version}
+
+ org.jetbrains.kotlin
+ kotlin-stdlib-jdk7
+ ${kotlin.version}
+
org.jetbrains.kotlin
kotlin-stdlib-jdk8
@@ -268,6 +273,35 @@
org.apache.maven.plugins
maven-surefire-plugin
3.0.0-M7
+
+
+ me.fabriciorby
+ maven-surefire-junit5-tree-reporter
+ ${surefire.junit5.tree-reporter.version}
+
+
+
+
+
+ true
+ true
+ true
+ true
+
+
+ plain
+
+ true
+
+
+
+ true
+ true
+
+ false
+
+
org.apache.maven.plugins
@@ -278,11 +312,35 @@
org.apache.maven.plugins
maven-failsafe-plugin
3.0.0-M7
-
-
- org.apache.maven.plugins
- maven-shade-plugin
- 3.3.0
+
+
+ me.fabriciorby
+ maven-surefire-junit5-tree-reporter
+ ${surefire.junit5.tree-reporter.version}
+
+
+
+
+
+ true
+ true
+ true
+ true
+
+
+ plain
+
+ true
+
+
+
+ true
+ true
+
+ false
+
+
org.codehaus.mojo
@@ -544,5 +602,14 @@
+
+ jdk11
+
+ [11,
+
+
+ 8
+
+