From d48f9479ddc0fa9775436535a86f45e3d5dc5dbf Mon Sep 17 00:00:00 2001 From: Nariman Abdullin Date: Wed, 8 Nov 2023 17:59:26 +0300 Subject: [PATCH] Remove `diktat-test-framework` (#1785) - removed `diktat-test-framework` - added `diktat-test-common` with common util methods for tests - removed usage of diff multiplatform tool --- .github/workflows/dependencies.yml | 2 +- CONTRIBUTING.md | 6 +- diktat-cli/build.gradle.kts | 2 +- .../diktat/smoke/DiktatSmokeTest.kt | 10 +- diktat-common-test/build.gradle.kts | 14 ++ .../framework/processing/ResourceReader.kt | 0 .../processing/TestComparatorUnit.kt | 49 +++---- .../framework/processing/TestFileContent.kt | 92 +++++++++++++ .../diktat/test/framework/util/TestUtils.kt | 22 ++++ diktat-rules/build.gradle.kts | 2 +- .../chapter2/CommentsFormattingFixTest.kt | 7 +- .../ClassLikeStructuresOrderRuleWarnTest.kt | 2 +- .../chapter3/spaces/IndentationRuleFixTest.kt | 21 +-- .../spaces/IndentationRuleTestUtils.kt | 20 --- .../junit/IndentationTestFixExtension.kt | 8 +- .../saveourtool/diktat/util/FixTestBase.kt | 23 +--- diktat-test-framework/build.gradle.kts | 19 --- .../diktat/test/framework/TestEntry.kt | 16 --- .../test/framework/common/ExecutionResult.kt | 9 -- .../framework/common/LocalCommandExecutor.kt | 67 ---------- .../diktat/test/framework/common/TestBase.kt | 32 ----- .../framework/config/TestArgumentsReader.kt | 96 -------------- .../test/framework/config/TestConfig.kt | 61 --------- .../test/framework/config/TestConfigReader.kt | 28 ---- .../config/TestFrameworkProperties.kt | 31 ----- .../framework/processing/FileComparator.kt | 124 ------------------ .../processing/FileComparisonResult.kt | 27 ---- .../framework/processing/TestCheckWarn.kt | 25 ---- .../test/framework/processing/TestCompare.kt | 96 -------------- .../test/framework/processing/TestMixed.kt | 29 ---- .../processing/TestProcessingFactory.kt | 99 -------------- .../diktat/test/framework/test_arguments.json | 23 ---- .../functional/1_3_a_package_naming.json | 8 -- .../functional/1_3_b_package_naming.json | 8 -- .../functional/1_9_a_special_space_cases.json | 8 -- .../test/framework/test_framework.properties | 12 -- .../src/main/resources/config.properties | 0 .../src/main/resources/log4j2.properties | 8 -- .../src/main/resources/options.json | 23 ---- gradle/libs.versions.toml | 2 - settings.gradle.kts | 2 +- 41 files changed, 172 insertions(+), 961 deletions(-) create mode 100644 diktat-common-test/build.gradle.kts rename {diktat-test-framework => diktat-common-test}/src/main/kotlin/com/saveourtool/diktat/test/framework/processing/ResourceReader.kt (100%) rename {diktat-test-framework => diktat-common-test}/src/main/kotlin/com/saveourtool/diktat/test/framework/processing/TestComparatorUnit.kt (77%) create mode 100644 diktat-common-test/src/main/kotlin/com/saveourtool/diktat/test/framework/processing/TestFileContent.kt rename {diktat-test-framework => diktat-common-test}/src/main/kotlin/com/saveourtool/diktat/test/framework/util/TestUtils.kt (95%) delete mode 100644 diktat-test-framework/build.gradle.kts delete mode 100644 diktat-test-framework/src/main/kotlin/com/saveourtool/diktat/test/framework/TestEntry.kt delete mode 100644 diktat-test-framework/src/main/kotlin/com/saveourtool/diktat/test/framework/common/ExecutionResult.kt delete mode 100644 diktat-test-framework/src/main/kotlin/com/saveourtool/diktat/test/framework/common/LocalCommandExecutor.kt delete mode 100644 diktat-test-framework/src/main/kotlin/com/saveourtool/diktat/test/framework/common/TestBase.kt delete mode 100644 diktat-test-framework/src/main/kotlin/com/saveourtool/diktat/test/framework/config/TestArgumentsReader.kt delete mode 100644 diktat-test-framework/src/main/kotlin/com/saveourtool/diktat/test/framework/config/TestConfig.kt delete mode 100644 diktat-test-framework/src/main/kotlin/com/saveourtool/diktat/test/framework/config/TestConfigReader.kt delete mode 100644 diktat-test-framework/src/main/kotlin/com/saveourtool/diktat/test/framework/config/TestFrameworkProperties.kt delete mode 100644 diktat-test-framework/src/main/kotlin/com/saveourtool/diktat/test/framework/processing/FileComparator.kt delete mode 100644 diktat-test-framework/src/main/kotlin/com/saveourtool/diktat/test/framework/processing/FileComparisonResult.kt delete mode 100644 diktat-test-framework/src/main/kotlin/com/saveourtool/diktat/test/framework/processing/TestCheckWarn.kt delete mode 100644 diktat-test-framework/src/main/kotlin/com/saveourtool/diktat/test/framework/processing/TestCompare.kt delete mode 100644 diktat-test-framework/src/main/kotlin/com/saveourtool/diktat/test/framework/processing/TestMixed.kt delete mode 100644 diktat-test-framework/src/main/kotlin/com/saveourtool/diktat/test/framework/processing/TestProcessingFactory.kt delete mode 100644 diktat-test-framework/src/main/resources/com/saveourtool/diktat/test/framework/test_arguments.json delete mode 100644 diktat-test-framework/src/main/resources/com/saveourtool/diktat/test/framework/test_configs/functional/1_3_a_package_naming.json delete mode 100644 diktat-test-framework/src/main/resources/com/saveourtool/diktat/test/framework/test_configs/functional/1_3_b_package_naming.json delete mode 100644 diktat-test-framework/src/main/resources/com/saveourtool/diktat/test/framework/test_configs/functional/1_9_a_special_space_cases.json delete mode 100644 diktat-test-framework/src/main/resources/com/saveourtool/diktat/test/framework/test_framework.properties delete mode 100644 diktat-test-framework/src/main/resources/config.properties delete mode 100644 diktat-test-framework/src/main/resources/log4j2.properties delete mode 100644 diktat-test-framework/src/main/resources/options.json diff --git a/.github/workflows/dependencies.yml b/.github/workflows/dependencies.yml index 24f8c24978..09cc5ebf06 100644 --- a/.github/workflows/dependencies.yml +++ b/.github/workflows/dependencies.yml @@ -39,12 +39,12 @@ jobs: gradle-build-module: |- :diktat-api :diktat-common + :diktat-common-test :diktat-ktlint-engine :diktat-gradle-plugin :diktat-maven-plugin :diktat-rules :diktat-ruleset - :diktat-test-framework :diktat-dev-ksp :diktat-cli gradle-build-configuration: |- diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 1e7f8f390f..6fe219df78 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -12,7 +12,7 @@ Rules are very simple: Main components are: 1) diktat-rules — number of rules that are supported by diKTat; -2) diktat-test-framework — functional/unit test framework that can be used for running your code fixer on the initial code and compare it with the expected result; +2) diktat-common-test — util methods for functional/unit tests that can be used for running your code fixer on the initial code and compare it with the expected result; 3) also see our demo: diktat-demo in a separate repository. Mainly we wanted to create a common configurable mechanism that @@ -31,7 +31,7 @@ Before you make a pull request, make sure the build is clean as we have lot of t $ mvn clean install ``` -# Hooks +# Hooks We have some hooks to a commit messages: 1) your commit message should have the following format: @@ -40,7 +40,7 @@ Brief Description ### What's done: 1) Long description -2) Long description +2) Long description ``` 2) Please also do not forget to update documentation on Wiki after the merge approval and before merge. diff --git a/diktat-cli/build.gradle.kts b/diktat-cli/build.gradle.kts index bd5ef27792..b7db4f5702 100644 --- a/diktat-cli/build.gradle.kts +++ b/diktat-cli/build.gradle.kts @@ -23,7 +23,7 @@ dependencies { implementation(libs.log4j2.core) implementation(libs.log4j2.slf4j2) - testImplementation(projects.diktatTestFramework) + testImplementation(projects.diktatCommonTest) testImplementation(libs.junit.jupiter) testImplementation(libs.junit.platform.suite) testImplementation(libs.assertj.core) diff --git a/diktat-cli/src/test/kotlin/com/saveourtool/diktat/smoke/DiktatSmokeTest.kt b/diktat-cli/src/test/kotlin/com/saveourtool/diktat/smoke/DiktatSmokeTest.kt index a327c1064d..12d44a280b 100644 --- a/diktat-cli/src/test/kotlin/com/saveourtool/diktat/smoke/DiktatSmokeTest.kt +++ b/diktat-cli/src/test/kotlin/com/saveourtool/diktat/smoke/DiktatSmokeTest.kt @@ -25,15 +25,7 @@ class DiktatSmokeTest : DiktatSmokeTestBase() { ) { val result = getTestComparatorUnit(config) .compareFilesFromResources(expected, test) - Assertions.assertAll( - { - Assertions.assertTrue(result.isSuccessful) - }, - { - Assertions.assertEquals(result.expectedContentWithoutWarns, result.actualContent) - } - ) - + result.assertSuccessful() } @BeforeEach diff --git a/diktat-common-test/build.gradle.kts b/diktat-common-test/build.gradle.kts new file mode 100644 index 0000000000..b464999d4c --- /dev/null +++ b/diktat-common-test/build.gradle.kts @@ -0,0 +1,14 @@ +plugins { + id("com.saveourtool.diktat.buildutils.kotlin-jvm-configuration") + id("com.saveourtool.diktat.buildutils.code-quality-convention") + id("com.saveourtool.diktat.buildutils.publishing-default-configuration") +} + +project.description = "Diktat common for tests" + +dependencies { + api(projects.diktatCommon) + implementation(libs.kotlin.logging) + implementation(libs.junit.jupiter.api) + implementation(libs.assertj.core) +} diff --git a/diktat-test-framework/src/main/kotlin/com/saveourtool/diktat/test/framework/processing/ResourceReader.kt b/diktat-common-test/src/main/kotlin/com/saveourtool/diktat/test/framework/processing/ResourceReader.kt similarity index 100% rename from diktat-test-framework/src/main/kotlin/com/saveourtool/diktat/test/framework/processing/ResourceReader.kt rename to diktat-common-test/src/main/kotlin/com/saveourtool/diktat/test/framework/processing/ResourceReader.kt diff --git a/diktat-test-framework/src/main/kotlin/com/saveourtool/diktat/test/framework/processing/TestComparatorUnit.kt b/diktat-common-test/src/main/kotlin/com/saveourtool/diktat/test/framework/processing/TestComparatorUnit.kt similarity index 77% rename from diktat-test-framework/src/main/kotlin/com/saveourtool/diktat/test/framework/processing/TestComparatorUnit.kt rename to diktat-common-test/src/main/kotlin/com/saveourtool/diktat/test/framework/processing/TestComparatorUnit.kt index a598538268..444bbe08c8 100644 --- a/diktat-test-framework/src/main/kotlin/com/saveourtool/diktat/test/framework/processing/TestComparatorUnit.kt +++ b/diktat-common-test/src/main/kotlin/com/saveourtool/diktat/test/framework/processing/TestComparatorUnit.kt @@ -1,12 +1,12 @@ package com.saveourtool.diktat.test.framework.processing import com.saveourtool.diktat.test.framework.processing.ResourceReader.Companion.withPrefix +import com.saveourtool.diktat.test.framework.util.NEWLINE import com.saveourtool.diktat.test.framework.util.readTextOrNull import com.saveourtool.diktat.test.framework.util.toUnixEndLines import io.github.oshai.kotlinlogging.KotlinLogging import java.nio.file.Path import kotlin.io.path.isRegularFile -import kotlin.io.path.name /** * Class that can apply transformation to an input file and then compare with expected result and output difference. @@ -45,17 +45,18 @@ class TestComparatorUnit( expectedResult: String, testFileStr: String, overrideResourceReader: (ResourceReader) -> ResourceReader = { it }, - ): FileComparisonResult { + ): TestFileContent { val overriddenResourceReader = overrideResourceReader(resourceReader) val expectedPath = overriddenResourceReader(expectedResult) val testPath = overriddenResourceReader(testFileStr) if (testPath == null || expectedPath == null) { log.error { "Not able to find files for running test: $expectedResult and $testFileStr" } - return FileComparisonResult( - isSuccessful = false, - delta = null, - actualContent = "// $expectedResult is found: ${testPath != null}", - expectedContent = "// $testFileStr is found: ${expectedPath != null}") + return NotFoundResourcesTestFileContent( + expectedResource = expectedResult, + expectedPath = expectedPath, + actualResource = testFileStr, + actualPath = testPath, + ) } return compareFilesFromFileSystem( @@ -78,35 +79,35 @@ class TestComparatorUnit( fun compareFilesFromFileSystem( expectedFile: Path, testFile: Path, - ): FileComparisonResult { + ): TestFileContent { if (!testFile.isRegularFile() || !expectedFile.isRegularFile()) { log.error { "Not able to find files for running test: $expectedFile and $testFile" } - return FileComparisonResult( - isSuccessful = false, - delta = null, - actualContent = "// $testFile is a regular file: ${testFile.isRegularFile()}", - expectedContent = "// $expectedFile is a regular file: ${expectedFile.isRegularFile()}") + return NotFoundFilesTestFileContent( + expectedPath = expectedFile, + actualPath = testFile, + ) } val actualFileContent = function(testFile).toUnixEndLines() val expectedFileContent = expectedFile.readTextOrNull().orEmpty() - val comparator = FileComparator( - expectedFile.name, - expectedFileContent, - actualFileContent, - ) - - return FileComparisonResult( - isSuccessful = comparator.compareFilesEqual(), - delta = comparator.delta, + return DefaultTestFileContent( actualContent = actualFileContent, - expectedContent = expectedFileContent, - expectedContentWithoutWarns = comparator.expectedResultWithoutWarns, + expectedContent = expectedFileContent.withoutWarns(), ) } private companion object { private val log = KotlinLogging.logger {} + private val warnRegex = (".*// ;warn:?(.*):(\\d*): (.+)").toRegex() + + /** + * @return Expected result without lines with warns + */ + private fun String.withoutWarns(): String = split(NEWLINE) + .filterNot { line -> + line.contains(warnRegex) + } + .joinToString(NEWLINE.toString()) } } diff --git a/diktat-common-test/src/main/kotlin/com/saveourtool/diktat/test/framework/processing/TestFileContent.kt b/diktat-common-test/src/main/kotlin/com/saveourtool/diktat/test/framework/processing/TestFileContent.kt new file mode 100644 index 0000000000..2766213b19 --- /dev/null +++ b/diktat-common-test/src/main/kotlin/com/saveourtool/diktat/test/framework/processing/TestFileContent.kt @@ -0,0 +1,92 @@ +/** + * It's a class container for test file content. + * Plus exception cases when resource or file is not found + */ + +package com.saveourtool.diktat.test.framework.processing + +import com.saveourtool.diktat.test.framework.util.describe + +import org.assertj.core.api.Assertions.assertThat +import org.assertj.core.api.SoftAssertions.assertSoftly +import org.intellij.lang.annotations.Language + +import java.nio.file.Path + +import kotlin.io.path.absolutePathString + +/** + * A base interface for content of test file + */ +sealed interface TestFileContent { + /** + * Asserts [TestFileContent] that content are equal + */ + fun assertSuccessful() +} + +/** + * Implementation of [TestFileContent] when resources are not found + * + * @param expectedResource + * @param expectedPath + * @param actualResource + * @param actualPath + */ +data class NotFoundResourcesTestFileContent( + private val expectedResource: String, + private val expectedPath: Path?, + private val actualResource: String, + private val actualPath: Path?, +) : TestFileContent { + override fun assertSuccessful() { + assertSoftly { softly -> + softly.assertThat(expectedPath) + .describedAs("Expected resource <%s>", expectedResource) + .isNotNull + softly.assertThat(actualPath) + .describedAs("Actual resource <%s>", actualResource) + .isNotNull + } + } +} + +/** + * Implementation of [TestFileContent] when files are not found + * + * @param expectedPath + * @param actualPath + */ +data class NotFoundFilesTestFileContent( + private val expectedPath: Path, + private val actualPath: Path, +) : TestFileContent { + override fun assertSuccessful() { + assertSoftly { softly -> + softly.assertThat(expectedPath) + .describedAs("Expected file <%s>", expectedPath.absolutePathString()) + .isRegularFile + softly.assertThat(actualPath) + .describedAs("Actual resource <%s>", actualPath.absolutePathString()) + .isRegularFile + } + } +} + +/** + * The result of files being compared by their content. + * + * @param actualContent the actual file content (possibly slightly different + * from the original after `diktat:check` is run). + * @param expectedContent the expected file content without warns. + */ +data class DefaultTestFileContent( + @Language("kotlin") private val actualContent: String, + @Language("kotlin") private val expectedContent: String, +) : TestFileContent { + override fun assertSuccessful() { + assertThat(actualContent) + .describedAs("lint result for ", actualContent.describe()) + .isEqualTo(expectedContent) + } +} diff --git a/diktat-test-framework/src/main/kotlin/com/saveourtool/diktat/test/framework/util/TestUtils.kt b/diktat-common-test/src/main/kotlin/com/saveourtool/diktat/test/framework/util/TestUtils.kt similarity index 95% rename from diktat-test-framework/src/main/kotlin/com/saveourtool/diktat/test/framework/util/TestUtils.kt rename to diktat-common-test/src/main/kotlin/com/saveourtool/diktat/test/framework/util/TestUtils.kt index 4191d521b1..7ed8769723 100644 --- a/diktat-test-framework/src/main/kotlin/com/saveourtool/diktat/test/framework/util/TestUtils.kt +++ b/diktat-common-test/src/main/kotlin/com/saveourtool/diktat/test/framework/util/TestUtils.kt @@ -32,6 +32,8 @@ import kotlin.io.path.isDirectory import kotlin.io.path.isSameFileAs import kotlin.io.path.readText +const val NEWLINE = '\n' + private val logger = KotlinLogging.logger {} /** @@ -291,6 +293,26 @@ fun Path.readTextOrNull(): String? = try { null } +/** + * @return a brief description of this code fragment. + */ +fun String.describe(): String { + val lines = splitToSequence(NEWLINE) + + var first: String? = null + + val count = lines.onEachIndexed { index, line -> + if (index == 0) { + first = line + } + }.count() + + return when (count) { + 1 -> "\"$this\"" + else -> "\"$first\u2026\" ($count line(s))" + } +} + /** * Retries the execution of the [block]. * diff --git a/diktat-rules/build.gradle.kts b/diktat-rules/build.gradle.kts index 9e03d01bb3..c736f90497 100644 --- a/diktat-rules/build.gradle.kts +++ b/diktat-rules/build.gradle.kts @@ -17,7 +17,7 @@ dependencies { // guava is used for string case utils implementation(libs.guava) implementation(libs.kotlin.logging) - testImplementation(projects.diktatTestFramework) + testImplementation(projects.diktatCommonTest) testImplementation(projects.diktatKtlintEngine) testImplementation(libs.log4j2.slf4j2) testImplementation(libs.junit.jupiter) diff --git a/diktat-rules/src/test/kotlin/com/saveourtool/diktat/ruleset/chapter2/CommentsFormattingFixTest.kt b/diktat-rules/src/test/kotlin/com/saveourtool/diktat/ruleset/chapter2/CommentsFormattingFixTest.kt index c299d74135..002e979532 100644 --- a/diktat-rules/src/test/kotlin/com/saveourtool/diktat/ruleset/chapter2/CommentsFormattingFixTest.kt +++ b/diktat-rules/src/test/kotlin/com/saveourtool/diktat/ruleset/chapter2/CommentsFormattingFixTest.kt @@ -1,7 +1,6 @@ package com.saveourtool.diktat.ruleset.chapter2 import com.saveourtool.diktat.ruleset.chapter2.CommentsFormattingTest.Companion.indentStyleComment -import com.saveourtool.diktat.ruleset.chapter3.spaces.describe import com.saveourtool.diktat.ruleset.rules.chapter2.kdoc.CommentsFormatting import com.saveourtool.diktat.util.FixTestBase @@ -9,8 +8,6 @@ import generated.WarningNames.COMMENT_WHITE_SPACE import generated.WarningNames.FIRST_COMMENT_NO_BLANK_LINE import generated.WarningNames.IF_ELSE_COMMENTS import generated.WarningNames.WRONG_NEWLINES_AROUND_KDOC -import org.assertj.core.api.Assertions.assertThat -import org.junit.jupiter.api.Disabled import org.junit.jupiter.api.Tag import org.junit.jupiter.api.Tags import org.junit.jupiter.api.Test @@ -55,8 +52,6 @@ class CommentsFormattingFixTest : FixTestBase("test/paragraph2/kdoc/", ::Comment @Tag(COMMENT_WHITE_SPACE) fun `indent-style header in a block comment should be preserved`(@TempDir tempDir: Path) { val lintResult = fixAndCompareContent(indentStyleComment, tempDir = tempDir) - assertThat(lintResult.actualContent) - .describedAs("lint result for ${indentStyleComment.describe()}") - .isEqualTo(lintResult.expectedContent) + lintResult.assertSuccessful() } } diff --git a/diktat-rules/src/test/kotlin/com/saveourtool/diktat/ruleset/chapter3/ClassLikeStructuresOrderRuleWarnTest.kt b/diktat-rules/src/test/kotlin/com/saveourtool/diktat/ruleset/chapter3/ClassLikeStructuresOrderRuleWarnTest.kt index 8aaed21cdf..8a34208d2f 100644 --- a/diktat-rules/src/test/kotlin/com/saveourtool/diktat/ruleset/chapter3/ClassLikeStructuresOrderRuleWarnTest.kt +++ b/diktat-rules/src/test/kotlin/com/saveourtool/diktat/ruleset/chapter3/ClassLikeStructuresOrderRuleWarnTest.kt @@ -1,13 +1,13 @@ package com.saveourtool.diktat.ruleset.chapter3 import com.saveourtool.diktat.common.config.rules.DIKTAT_RULE_SET_ID -import com.saveourtool.diktat.ruleset.chapter3.spaces.describe import com.saveourtool.diktat.ruleset.constants.Warnings.BLANK_LINE_BETWEEN_PROPERTIES import com.saveourtool.diktat.ruleset.constants.Warnings.WRONG_ORDER_IN_CLASS_LIKE_STRUCTURES import com.saveourtool.diktat.ruleset.rules.chapter3.ClassLikeStructuresOrderRule import com.saveourtool.diktat.util.LintTestBase import com.saveourtool.diktat.api.DiktatError +import com.saveourtool.diktat.test.framework.util.describe import generated.WarningNames import org.assertj.core.api.Assertions.assertThat import org.intellij.lang.annotations.Language diff --git a/diktat-rules/src/test/kotlin/com/saveourtool/diktat/ruleset/chapter3/spaces/IndentationRuleFixTest.kt b/diktat-rules/src/test/kotlin/com/saveourtool/diktat/ruleset/chapter3/spaces/IndentationRuleFixTest.kt index a5117a2a57..27b2090a2c 100644 --- a/diktat-rules/src/test/kotlin/com/saveourtool/diktat/ruleset/chapter3/spaces/IndentationRuleFixTest.kt +++ b/diktat-rules/src/test/kotlin/com/saveourtool/diktat/ruleset/chapter3/spaces/IndentationRuleFixTest.kt @@ -12,11 +12,10 @@ import com.saveourtool.diktat.ruleset.utils.indentation.IndentationConfig.Compan import com.saveourtool.diktat.ruleset.utils.indentation.IndentationConfig.Companion.EXTENDED_INDENT_FOR_EXPRESSION_BODIES import com.saveourtool.diktat.ruleset.utils.indentation.IndentationConfig.Companion.EXTENDED_INDENT_OF_PARAMETERS import com.saveourtool.diktat.ruleset.utils.indentation.IndentationConfig.Companion.NEWLINE_AT_END -import com.saveourtool.diktat.test.framework.processing.FileComparisonResult +import com.saveourtool.diktat.test.framework.processing.TestFileContent import com.saveourtool.diktat.util.FixTestBase import generated.WarningNames -import org.assertj.core.api.Assertions.assertThat import org.intellij.lang.annotations.Language import org.junit.jupiter.api.Nested import org.junit.jupiter.api.Tag @@ -110,9 +109,7 @@ class IndentationRuleFixTest : FixTestBase("test/paragraph3/indentation", """.trimMargin() val lintResult = fixAndCompareContent(actualCode, expectedCode, tempDir) - assertThat(lintResult.actualContent) - .describedAs("lint result for ${actualCode.describe()}") - .isEqualTo(lintResult.expectedContent) + lintResult.assertSuccessful() } /** @@ -148,9 +145,7 @@ class IndentationRuleFixTest : FixTestBase("test/paragraph3/indentation", """.trimMargin() val lintResult = fixAndCompareContent(actualCode, expectedCode, tempDir) - assertThat(lintResult.actualContent) - .describedAs("lint result for ${actualCode.describe()}") - .isEqualTo(lintResult.expectedContent) + lintResult.assertSuccessful() } /** @@ -186,9 +181,7 @@ class IndentationRuleFixTest : FixTestBase("test/paragraph3/indentation", """.trimMargin() val lintResult = fixAndCompareContent(actualCode, expectedCode, tempDir) - assertThat(lintResult.actualContent) - .describedAs("lint result for ${actualCode.describe()}") - .isEqualTo(lintResult.expectedContent) + lintResult.assertSuccessful() } /** @@ -224,15 +217,13 @@ class IndentationRuleFixTest : FixTestBase("test/paragraph3/indentation", """.trimMargin() val lintResult = fixAndCompareContent(actualCode, expectedCode, tempDir) - assertThat(lintResult.actualContent) - .describedAs("lint result for ${actualCode.describe()}") - .isEqualTo(lintResult.expectedContent) + lintResult.assertSuccessful() } private fun fixAndCompareContent(@Language("kotlin") actualCode: String, @Language("kotlin") expectedCode: String, tempDir: Path - ): FileComparisonResult { + ): TestFileContent { val config = IndentationConfig(NEWLINE_AT_END to false).withCustomParameters().asRulesConfigList() return fixAndCompareContent(actualCode, expectedCode, tempDir, overrideRulesConfigList = config) } diff --git a/diktat-rules/src/test/kotlin/com/saveourtool/diktat/ruleset/chapter3/spaces/IndentationRuleTestUtils.kt b/diktat-rules/src/test/kotlin/com/saveourtool/diktat/ruleset/chapter3/spaces/IndentationRuleTestUtils.kt index 19eb7c0eda..23e07b4163 100644 --- a/diktat-rules/src/test/kotlin/com/saveourtool/diktat/ruleset/chapter3/spaces/IndentationRuleTestUtils.kt +++ b/diktat-rules/src/test/kotlin/com/saveourtool/diktat/ruleset/chapter3/spaces/IndentationRuleTestUtils.kt @@ -63,23 +63,3 @@ internal fun Map.asRulesConfigList(): List = configuration = this ) ) - -/** - * @return a brief description of this code fragment. - */ -internal fun String.describe(): String { - val lines = splitToSequence(NEWLINE) - - var first: String? = null - - val count = lines.onEachIndexed { index, line -> - if (index == 0) { - first = line - } - }.count() - - return when (count) { - 1 -> "\"$this\"" - else -> "\"$first\u2026\" ($count line(s))" - } -} diff --git a/diktat-rules/src/test/kotlin/com/saveourtool/diktat/ruleset/chapter3/spaces/junit/IndentationTestFixExtension.kt b/diktat-rules/src/test/kotlin/com/saveourtool/diktat/ruleset/chapter3/spaces/junit/IndentationTestFixExtension.kt index 2d28b53041..1bffaa47d2 100644 --- a/diktat-rules/src/test/kotlin/com/saveourtool/diktat/ruleset/chapter3/spaces/junit/IndentationTestFixExtension.kt +++ b/diktat-rules/src/test/kotlin/com/saveourtool/diktat/ruleset/chapter3/spaces/junit/IndentationTestFixExtension.kt @@ -1,12 +1,10 @@ package com.saveourtool.diktat.ruleset.chapter3.spaces.junit import com.saveourtool.diktat.ruleset.chapter3.spaces.asRulesConfigList -import com.saveourtool.diktat.ruleset.chapter3.spaces.describe import com.saveourtool.diktat.ruleset.chapter3.spaces.withCustomParameters import com.saveourtool.diktat.ruleset.junit.CloseablePath import com.saveourtool.diktat.ruleset.rules.chapter3.files.IndentationRule import com.saveourtool.diktat.util.FixTestBase -import org.assertj.core.api.Assertions.assertThat import org.intellij.lang.annotations.Language import org.junit.jupiter.api.extension.BeforeEachCallback import org.junit.jupiter.api.extension.ExtensionContext @@ -48,11 +46,7 @@ class IndentationTestFixExtension( overrideRulesConfigList = defaultConfig.withCustomParameters(customConfig).asRulesConfigList(), ) - if (!lintResult.isSuccessful) { - assertThat(lintResult.actualContent) - .describedAs("lint result for ${actualCode.describe()}") - .isEqualTo(lintResult.expectedContent) - } + lintResult.assertSuccessful() } private companion object { diff --git a/diktat-rules/src/test/kotlin/com/saveourtool/diktat/util/FixTestBase.kt b/diktat-rules/src/test/kotlin/com/saveourtool/diktat/util/FixTestBase.kt index e29b96c527..7e813199c0 100644 --- a/diktat-rules/src/test/kotlin/com/saveourtool/diktat/util/FixTestBase.kt +++ b/diktat-rules/src/test/kotlin/com/saveourtool/diktat/util/FixTestBase.kt @@ -4,13 +4,12 @@ import com.saveourtool.diktat.api.DiktatCallback import com.saveourtool.diktat.common.config.rules.RulesConfig import com.saveourtool.diktat.ktlint.format import com.saveourtool.diktat.ruleset.rules.DiktatRule -import com.saveourtool.diktat.test.framework.processing.FileComparisonResult import com.saveourtool.diktat.test.framework.processing.ResourceReader import com.saveourtool.diktat.test.framework.processing.TestComparatorUnit +import com.saveourtool.diktat.test.framework.processing.TestFileContent import com.saveourtool.diktat.util.DiktatRuleSetFactoryImplTest.Companion.diktatRuleSetForTest import io.github.oshai.kotlinlogging.KotlinLogging 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.createDirectories @@ -80,7 +79,7 @@ open class FixTestBase( tempDir: Path, subFolder: String? = null, overrideRulesConfigList: List? = null - ): FileComparisonResult { + ): TestFileContent { val folder = subFolder?.let { tempDir / it }?.also { it.createDirectories() } ?: tempDir val actual = folder / "actual.kt" actual.bufferedWriter().use { out -> @@ -103,23 +102,5 @@ open class FixTestBase( private val defaultCallback = DiktatCallback { error, _ -> log.warn { "Received linting error: $error" } } - - /** - * Asserts [FileComparisonResult] as [this] that content are equal and status is successful - */ - internal fun FileComparisonResult.assertSuccessful() { - Assertions.assertAll( - { - Assertions.assertTrue(isSuccessful) { - "Detected delta: $delta" - } - }, - { - Assertions.assertEquals(expectedContentWithoutWarns, actualContent) { - "Content are different" - } - } - ) - } } } diff --git a/diktat-test-framework/build.gradle.kts b/diktat-test-framework/build.gradle.kts deleted file mode 100644 index 03a1157419..0000000000 --- a/diktat-test-framework/build.gradle.kts +++ /dev/null @@ -1,19 +0,0 @@ -plugins { - id("com.saveourtool.diktat.buildutils.kotlin-jvm-configuration") - id("com.saveourtool.diktat.buildutils.code-quality-convention") - id("com.saveourtool.diktat.buildutils.publishing-default-configuration") -} - -project.description = "Test framework for diktat" - -dependencies { - api(projects.diktatCommon) - implementation(libs.kotlin.stdlib.jdk8) - implementation(libs.apache.commons.cli) - implementation(libs.apache.commons.io) - implementation(libs.kotlin.logging) - implementation(libs.kotlinx.coroutines.core) - implementation(libs.kotlin.multiplatform.diff) - testImplementation(libs.junit.jupiter) - testImplementation(libs.assertj.core) -} diff --git a/diktat-test-framework/src/main/kotlin/com/saveourtool/diktat/test/framework/TestEntry.kt b/diktat-test-framework/src/main/kotlin/com/saveourtool/diktat/test/framework/TestEntry.kt deleted file mode 100644 index 3b6291ce63..0000000000 --- a/diktat-test-framework/src/main/kotlin/com/saveourtool/diktat/test/framework/TestEntry.kt +++ /dev/null @@ -1,16 +0,0 @@ -package com.saveourtool.diktat.test.framework - -import com.saveourtool.diktat.test.framework.config.TestArgumentsReader -import com.saveourtool.diktat.test.framework.config.TestFrameworkProperties -import com.saveourtool.diktat.test.framework.processing.TestProcessingFactory - -/** - * Main entry point for test executions - */ -object TestEntry { - @JvmStatic - fun main(args: Array) { - val properties = TestFrameworkProperties("com/saveourtool/diktat/test/framework/test_framework.properties") - TestProcessingFactory(TestArgumentsReader(args, properties, javaClass.classLoader)).processTests() - } -} diff --git a/diktat-test-framework/src/main/kotlin/com/saveourtool/diktat/test/framework/common/ExecutionResult.kt b/diktat-test-framework/src/main/kotlin/com/saveourtool/diktat/test/framework/common/ExecutionResult.kt deleted file mode 100644 index 3131d07746..0000000000 --- a/diktat-test-framework/src/main/kotlin/com/saveourtool/diktat/test/framework/common/ExecutionResult.kt +++ /dev/null @@ -1,9 +0,0 @@ -package com.saveourtool.diktat.test.framework.common - -/** - * Class that keeps the result of executed command - * - * @property stdOut content from stdout stream - * @property stdErr content from stderr stream - */ -data class ExecutionResult(val stdOut: List, val stdErr: List) diff --git a/diktat-test-framework/src/main/kotlin/com/saveourtool/diktat/test/framework/common/LocalCommandExecutor.kt b/diktat-test-framework/src/main/kotlin/com/saveourtool/diktat/test/framework/common/LocalCommandExecutor.kt deleted file mode 100644 index de4e611930..0000000000 --- a/diktat-test-framework/src/main/kotlin/com/saveourtool/diktat/test/framework/common/LocalCommandExecutor.kt +++ /dev/null @@ -1,67 +0,0 @@ -package com.saveourtool.diktat.test.framework.common - -import io.github.oshai.kotlinlogging.KotlinLogging -import java.io.IOException -import java.io.InputStream -import java.nio.charset.Charset -import kotlinx.coroutines.CoroutineDispatcher -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.flow.Flow -import kotlinx.coroutines.flow.flow -import kotlinx.coroutines.flow.flowOn -import kotlinx.coroutines.flow.toList -import kotlinx.coroutines.runBlocking - -/** - * Class that wraps shell [command] and can execute it - * - * @param command - * @param ioDispatcher - */ -class LocalCommandExecutor internal constructor( - private val command: String, - private val ioDispatcher: CoroutineDispatcher = Dispatchers.IO, -) { - /** - * Execute [command] - * - * @return [ExecutionResult] of command execution - */ - fun executeCommand(): ExecutionResult { - try { - log.info { "Executing command: $command" } - val process = Runtime.getRuntime().exec(command) - process.outputStream.close() - return runBlocking { - ExecutionResult( - process.inputStream.readLinesAsync("OUTPUT", ioDispatcher).toList(), - process.errorStream.readLinesAsync("ERROR", ioDispatcher).toList(), - ) - } - } catch (ex: IOException) { - log.error(ex) { "Execution of $command failed" } - } - return ExecutionResult(emptyList(), emptyList()) - } - - companion object { - private val log = KotlinLogging.logger {} - - /** - * @param streamType - * @param ioDispatcher - * @return [Flow] of strings from input stream - */ - fun InputStream.readLinesAsync(streamType: String, ioDispatcher: CoroutineDispatcher): Flow = flow { - try { - val bufferedReader = this@readLinesAsync.bufferedReader(Charset.defaultCharset()) - while (true) { - val line = bufferedReader.readLine() ?: break - emit(line) - } - } catch (ex: IOException) { - log.error(ex) { "Failed to consume and display the input stream of type $streamType." } - } - }.flowOn(ioDispatcher) - } -} diff --git a/diktat-test-framework/src/main/kotlin/com/saveourtool/diktat/test/framework/common/TestBase.kt b/diktat-test-framework/src/main/kotlin/com/saveourtool/diktat/test/framework/common/TestBase.kt deleted file mode 100644 index 46b9fe782d..0000000000 --- a/diktat-test-framework/src/main/kotlin/com/saveourtool/diktat/test/framework/common/TestBase.kt +++ /dev/null @@ -1,32 +0,0 @@ -package com.saveourtool.diktat.test.framework.common - -import com.saveourtool.diktat.test.framework.config.TestConfig -import com.saveourtool.diktat.test.framework.config.TestFrameworkProperties - -/** - * Base interface for different test runners - */ -interface TestBase { - /** - * simple test runner that depends on the test execution type - * - * @return if test failed or passed - */ - @Suppress("FUNCTION_BOOLEAN_PREFIX") - fun runTest(): Boolean - - /** - * injects test configuration that was read from .json config file - * - * @param testConfig json configuration - * @param properties config from properties - * @return test instance itself - */ - fun initTestProcessor(testConfig: TestConfig, properties: TestFrameworkProperties): TestBase - - /** - * @param command - command to execute in shell - * @return execution result - in default implementation returns inputStream - */ - fun executeCommand(command: String) = LocalCommandExecutor(command).executeCommand() -} diff --git a/diktat-test-framework/src/main/kotlin/com/saveourtool/diktat/test/framework/config/TestArgumentsReader.kt b/diktat-test-framework/src/main/kotlin/com/saveourtool/diktat/test/framework/config/TestArgumentsReader.kt deleted file mode 100644 index 11a7353d84..0000000000 --- a/diktat-test-framework/src/main/kotlin/com/saveourtool/diktat/test/framework/config/TestArgumentsReader.kt +++ /dev/null @@ -1,96 +0,0 @@ -package com.saveourtool.diktat.test.framework.config - -import com.saveourtool.diktat.common.cli.CliArgument -import com.saveourtool.diktat.common.config.reader.AbstractConfigReader -import io.github.oshai.kotlinlogging.KotlinLogging - -import org.apache.commons.cli.CommandLine -import org.apache.commons.cli.CommandLineParser -import org.apache.commons.cli.DefaultParser -import org.apache.commons.cli.HelpFormatter -import org.apache.commons.cli.Options -import org.apache.commons.cli.ParseException - -import java.io.IOException -import java.io.InputStream - -import kotlin.system.exitProcess -import kotlinx.serialization.ExperimentalSerializationApi -import kotlinx.serialization.json.Json -import kotlinx.serialization.json.decodeFromStream - -/** - * Class that gives access to properties of a test - * - * @param args CLI arguments - * @param classLoader [ClassLoader] which is used to load properties file - * @property properties properties from properties file - */ -class TestArgumentsReader( - private val args: Array, - val properties: TestFrameworkProperties, - classLoader: ClassLoader -) : AbstractConfigReader>() { - private val cliArguments: List? = classLoader.getResourceAsStream(properties.testFrameworkArgsRelativePath)?.let { read(it) } - private val cmd: CommandLine by lazy { parseArguments() } - - /** - * List of tests provided by user - */ - val tests: List by lazy { - val tests: String? = cmd.getOptionValue("t") - tests - ?.split(",") - ?.map { it.trim() } - ?: run { - log.error { - "Missing option --test or -t. Not able to run tests, please provide test names or use --all option to run all available tests" - } - exitProcess(2) - } - } - private val declaredOptions: Options by lazy { - val options = Options() - cliArguments - ?.map { it.convertToOption() } - ?.forEach { opt -> options.addOption(opt) } - ?: exitProcess(1) - options - } - - private fun parseArguments(): CommandLine { - val parser: CommandLineParser = DefaultParser() - val formatter = HelpFormatter() - val options = declaredOptions - val cmd: CommandLine - try { - cmd = parser.parse(options, args) - } catch (e: ParseException) { - log.error(e) { "Cannot parse command line arguments due to" } - formatter.printHelp("utility-name", options) - exitProcess(1) - } - return cmd - } - - /** - * Whether all tests should be run - * - * @return true if command has option "all" - */ - fun shouldRunAllTests() = cmd.hasOption("all") - - /** - * Parse JSON to a list of [CliArgument]s - * - * @param inputStream a [InputStream] representing input JSON - * @return list of [CliArgument]s - */ - @OptIn(ExperimentalSerializationApi::class) - @Throws(IOException::class) - override fun parse(inputStream: InputStream): List = Json.decodeFromStream(inputStream) - - companion object { - private val log = KotlinLogging.logger {} - } -} diff --git a/diktat-test-framework/src/main/kotlin/com/saveourtool/diktat/test/framework/config/TestConfig.kt b/diktat-test-framework/src/main/kotlin/com/saveourtool/diktat/test/framework/config/TestConfig.kt deleted file mode 100644 index 4afa88548c..0000000000 --- a/diktat-test-framework/src/main/kotlin/com/saveourtool/diktat/test/framework/config/TestConfig.kt +++ /dev/null @@ -1,61 +0,0 @@ -package com.saveourtool.diktat.test.framework.config - -import kotlinx.serialization.SerialName -import kotlinx.serialization.Serializable - -/** - * This class is used to serialize/deserialize json representation - * that is used to store command line arguments - * @property executionCommand command line execution command, use shell like "cmd", "bash" or other - * @property expectedResultFile expected result file can be a full path or a relative path to a resource - * @property testFile testFile can be a full path or a relative path to a resource - * @property executionType executionType that controls processing of the test (like COMPARE, MIXED, CHECK_WARN, e.t.c) - * @property testProfile - * @property inPlace option that controls if changes and automatic fix should be done directly in file - */ -@Serializable -@Suppress("ForbiddenComment") -class TestConfig internal constructor( - val executionCommand: String, - val expectedResultFile: String, - val testFile: String, - val executionType: ExecutionType, - @SerialName("profile") val testProfile: TestProfile, - val inPlace: Boolean = false -) { - /** - * test name - it is not included in config content, but is injected on runtime by setter - */ - var testName: String? = null - private set - - // FixMe: not used by for now, fix the description when the class will be ready - override fun toString() = - """(executionCommand: $executionCommand, expectedResultFile: $expectedResultFile, inPlace: $inPlace, - executionType: $executionCommand)""" - - /** - * @param testName - * @return [TestConfig] with updated [testName] - */ - fun setTestName(testName: String): TestConfig { - this.testName = testName - return this - } - - /** - * Different modes of tests execution - */ - enum class ExecutionType { - CHECK_WARN, COMPARE, MIXED - } - - /** - * different profiles that can be used to control common processing part for tests - * (processing differs for different programming languages) - */ - @Suppress("UNUSED") - enum class TestProfile { - CXX, JAVA, KT, PYTHON - } -} diff --git a/diktat-test-framework/src/main/kotlin/com/saveourtool/diktat/test/framework/config/TestConfigReader.kt b/diktat-test-framework/src/main/kotlin/com/saveourtool/diktat/test/framework/config/TestConfigReader.kt deleted file mode 100644 index d8351fd451..0000000000 --- a/diktat-test-framework/src/main/kotlin/com/saveourtool/diktat/test/framework/config/TestConfigReader.kt +++ /dev/null @@ -1,28 +0,0 @@ -package com.saveourtool.diktat.test.framework.config - -import com.saveourtool.diktat.common.config.reader.AbstractConfigReader - -import java.io.IOException -import java.io.InputStream - -import kotlinx.serialization.ExperimentalSerializationApi -import kotlinx.serialization.json.Json -import kotlinx.serialization.json.decodeFromStream - -/** - * A [AbstractConfigReader] to read tests configuration as [TestConfig] - */ -class TestConfigReader(configFilePath: String, classLoader: ClassLoader) : AbstractConfigReader() { - /** - * The [TestConfig] which is read from - */ - val config: TestConfig? = classLoader.getResourceAsStream(configFilePath)?.let { read(it) } - - /** - * @param inputStream input stream of data from config file - * @return [TestConfig] read from file - */ - @OptIn(ExperimentalSerializationApi::class) - @Throws(IOException::class) - override fun parse(inputStream: InputStream): TestConfig = Json.decodeFromStream(inputStream) -} diff --git a/diktat-test-framework/src/main/kotlin/com/saveourtool/diktat/test/framework/config/TestFrameworkProperties.kt b/diktat-test-framework/src/main/kotlin/com/saveourtool/diktat/test/framework/config/TestFrameworkProperties.kt deleted file mode 100644 index c29b4d2c13..0000000000 --- a/diktat-test-framework/src/main/kotlin/com/saveourtool/diktat/test/framework/config/TestFrameworkProperties.kt +++ /dev/null @@ -1,31 +0,0 @@ -package com.saveourtool.diktat.test.framework.config - -import com.saveourtool.diktat.common.config.reader.ApplicationProperties - -/** - * [ApplicationProperties] for running tests - */ -class TestFrameworkProperties(propertiesFileName: String) : ApplicationProperties(propertiesFileName) { - private val testFrameworkResourcePath: String by lazy { properties.getProperty("test.framework.dir") } - private val testFilesDir: String by lazy { properties.getProperty("test.files.dir") } - - /** - * Relative path to a file with arguments for tests runner - */ - val testFrameworkArgsRelativePath: String by lazy { testFrameworkResourcePath + "/" + properties.getProperty("test.framework.arguments") } - - /** - * Relative path to test files directory - */ - val testFilesRelativePath: String = "$testFrameworkResourcePath/$testFilesDir" - - /** - * Relative path to test configs directory - */ - val testConfigsRelativePath: String by lazy { testFrameworkResourcePath + "/" + properties.getProperty("test.configs.dir") } - - /** - * Whether tests should be run in parallel - */ - val isParallelMode: Boolean by lazy { java.lang.Boolean.getBoolean(properties.getProperty("parallel.mode")) } -} diff --git a/diktat-test-framework/src/main/kotlin/com/saveourtool/diktat/test/framework/processing/FileComparator.kt b/diktat-test-framework/src/main/kotlin/com/saveourtool/diktat/test/framework/processing/FileComparator.kt deleted file mode 100644 index adb05288ed..0000000000 --- a/diktat-test-framework/src/main/kotlin/com/saveourtool/diktat/test/framework/processing/FileComparator.kt +++ /dev/null @@ -1,124 +0,0 @@ -package com.saveourtool.diktat.test.framework.processing - -import com.saveourtool.diktat.test.framework.util.readTextOrNull - -import io.github.oshai.kotlinlogging.KotlinLogging -import io.github.petertrr.diffutils.diff -import io.github.petertrr.diffutils.patch.ChangeDelta -import io.github.petertrr.diffutils.text.DiffRowGenerator - -import java.io.File - -/** - * A class that is capable of comparing files content - * - * @param fileName - * @param expectedResult - * @param actualResult - */ -class FileComparator( - private val fileName: String, - private val expectedResult: String, - private val actualResult: String, -) { - private val diffGenerator = DiffRowGenerator( - columnWidth = Int.MAX_VALUE, - showInlineDiffs = true, - mergeOriginalRevised = false, - inlineDiffByWord = false, - oldTag = { _, start -> if (start) "[" else "]" }, - newTag = { _, start -> if (start) "<" else ">" }, - ) - - /** - * expected result without lines with warns - */ - val expectedResultWithoutWarns: String by lazy { - val regex = (".*// ;warn:?(.*):(\\d*): (.+)").toRegex() - expectedResult - .split("\n") - .filterNot { line -> - line.contains(regex) - } - .joinToString("\n") - } - - /** - * delta in files - */ - val delta: String? by lazy { - if (expectedResult.isEmpty()) { - return@lazy null - } - val patch = diff(expectedResultWithoutWarns, actualResult, null) - - if (patch.deltas.isEmpty()) { - return@lazy null - } - return@lazy patch.deltas.joinToString(System.lineSeparator()) { delta -> - when (delta) { - is ChangeDelta -> diffGenerator - .generateDiffRows(delta.source.lines, delta.target.lines) - .joinToString(prefix = "ChangeDelta, position ${delta.source.position}, lines:\n", separator = "\n\n") { - """ - |-${it.oldLine} - |+${it.newLine} - |""".trimMargin() - } - .let { "ChangeDelta, position ${delta.source.position}, lines:\n$it" } - else -> delta.toString() - } - } - } - - constructor( - expectedResultFile: File, - actualResult: String - ) : this( - fileName = expectedResultFile.name, - expectedResult = expectedResultFile.toPath().readTextOrNull().orEmpty(), - actualResult = actualResult, - ) - - constructor( - expectedResultFile: File, - actualResultFile: File - ) : this( - fileName = expectedResultFile.name, - expectedResult = expectedResultFile.toPath().readTextOrNull().orEmpty(), - actualResult = actualResultFile.toPath().readTextOrNull().orEmpty(), - ) - - /** - * @return true in case files are different - * false - in case they are equals - */ - @Suppress( - "ReturnCount", - "FUNCTION_BOOLEAN_PREFIX", - "TOO_LONG_FUNCTION" - ) - fun compareFilesEqual(): Boolean { - try { - if (expectedResult.isEmpty()) { - return false - } - val joinedDeltas = delta ?: return true - log.error { - """ - |Expected result for <$fileName> formatted are different. - |See difference below: - |$joinedDeltas - """.trimMargin() - } - return false - } catch (e: IllegalArgumentException) { - log.error(e) { "Not able to prepare diffs for <$fileName>" } - return false - } - } - - companion object { - private val log = KotlinLogging.logger {} - } -} diff --git a/diktat-test-framework/src/main/kotlin/com/saveourtool/diktat/test/framework/processing/FileComparisonResult.kt b/diktat-test-framework/src/main/kotlin/com/saveourtool/diktat/test/framework/processing/FileComparisonResult.kt deleted file mode 100644 index 8bcb108512..0000000000 --- a/diktat-test-framework/src/main/kotlin/com/saveourtool/diktat/test/framework/processing/FileComparisonResult.kt +++ /dev/null @@ -1,27 +0,0 @@ -package com.saveourtool.diktat.test.framework.processing - -import org.intellij.lang.annotations.Language - -/** - * The result of files being compared by their content. - * - * @property isSuccessful `true` if file content match (the comparison is - * successful), `false` otherwise. Even if [isSuccessful] is `true`, - * [actualContent] and [expectedContent] are not necessarily the same - * (theoretically, they may differ by the amount of trailing newlines). - * Similarly, if [isSuccessful] is `false`, [actualContent] and - * [expectedContent] are not necessarily different (consider the case when - * both files are missing). - * @property delta a delta between compared files. - * @property actualContent the actual file content (possibly slightly different - * from the original after `diktat:check` is run). - * @property expectedContent the expected file content. - * @property expectedContentWithoutWarns the expected file content without warns. - */ -data class FileComparisonResult( - val isSuccessful: Boolean, - val delta: String?, - @Language("kotlin") val actualContent: String, - @Language("kotlin") val expectedContent: String, - @Language("kotlin") val expectedContentWithoutWarns: String = expectedContent, -) diff --git a/diktat-test-framework/src/main/kotlin/com/saveourtool/diktat/test/framework/processing/TestCheckWarn.kt b/diktat-test-framework/src/main/kotlin/com/saveourtool/diktat/test/framework/processing/TestCheckWarn.kt deleted file mode 100644 index cba634a92d..0000000000 --- a/diktat-test-framework/src/main/kotlin/com/saveourtool/diktat/test/framework/processing/TestCheckWarn.kt +++ /dev/null @@ -1,25 +0,0 @@ -package com.saveourtool.diktat.test.framework.processing - -import com.saveourtool.diktat.test.framework.config.TestConfig -import io.github.oshai.kotlinlogging.KLogger -import io.github.oshai.kotlinlogging.KotlinLogging - -/** - * [TestCompare] that uses stderr as tests output stream - */ -class TestCheckWarn : TestCompare() { - @Suppress("MISSING_KDOC_CLASS_ELEMENTS") - override val log: KLogger = KotlinLogging.logger {} - - @Suppress( - "UnusedPrivateMember", - "UNUSED", - "VarCouldBeVal" - ) - private var testConfig: TestConfig? = null - - /** - * Get tests execution result - */ - override fun getExecutionResult() = testResult.stdErr -} diff --git a/diktat-test-framework/src/main/kotlin/com/saveourtool/diktat/test/framework/processing/TestCompare.kt b/diktat-test-framework/src/main/kotlin/com/saveourtool/diktat/test/framework/processing/TestCompare.kt deleted file mode 100644 index 84b5eaa083..0000000000 --- a/diktat-test-framework/src/main/kotlin/com/saveourtool/diktat/test/framework/processing/TestCompare.kt +++ /dev/null @@ -1,96 +0,0 @@ -package com.saveourtool.diktat.test.framework.processing - -import com.saveourtool.diktat.test.framework.common.ExecutionResult -import com.saveourtool.diktat.test.framework.common.TestBase -import com.saveourtool.diktat.test.framework.config.TestConfig -import com.saveourtool.diktat.test.framework.config.TestFrameworkProperties -import io.github.oshai.kotlinlogging.KLogger -import io.github.oshai.kotlinlogging.KotlinLogging - -import org.apache.commons.io.FileUtils - -import java.io.File - -/** - * A class that runs tests and compares output with expected result - */ -@Suppress("ForbiddenComment") -open class TestCompare : TestBase { - @Suppress("MISSING_KDOC_CLASS_ELEMENTS") - protected open val log: KLogger = KotlinLogging.logger {} - private lateinit var expectedResult: File - - // testResultFile will be used if and only if --in-place option will be used - private lateinit var testFile: File - private lateinit var testConfig: TestConfig - - /** Result of the test run */ - protected lateinit var testResult: ExecutionResult - - /** - * @return true if test has passed successfully, false otherwise - */ - @Suppress("FUNCTION_BOOLEAN_PREFIX") - override fun runTest(): Boolean { - // FixMe: this is an execution for Windows, should support other OS - val testPassed = if (testConfig.inPlace) processInPlace() else processToStdOut() - - if (testPassed) { - log.info { "Test <${testConfig.testName}> passed" } - } else { - log.error { "Test <${testConfig.testName}> failed" } - } - - return testPassed - } - - /** - * injects test configuration that was read from .json config file - * - * @param testConfig json configuration - * @param properties config from properties - * @return test instance itself - */ - override fun initTestProcessor(testConfig: TestConfig, properties: TestFrameworkProperties): TestCompare { - this.testConfig = testConfig - this.expectedResult = buildFullPathToResource( - testConfig.expectedResultFile, - properties.testFilesRelativePath - ) - this.testFile = buildFullPathToResource(testConfig.testFile, properties.testFilesRelativePath) - - return this - } - - @Suppress("FUNCTION_BOOLEAN_PREFIX") - private fun processInPlace(): Boolean { - val copyTestFile = File("${testFile}_copy") - FileUtils.copyFile(testFile, copyTestFile) - executeCommand("cmd /c ${testConfig.executionCommand} $copyTestFile") - - val testPassed = FileComparator(expectedResult, copyTestFile).compareFilesEqual() - FileUtils.forceDelete(copyTestFile) - - return testPassed - } - - @Suppress("FUNCTION_BOOLEAN_PREFIX") - private fun processToStdOut(): Boolean { - this.testResult = executeCommand("cmd /c ${testConfig.executionCommand} $testFile") - - return FileComparator(expectedResult, getExecutionResult().joinToString("\n")).compareFilesEqual() - } - - private fun buildFullPathToResource(resourceFile: String, resourceAbsolutePath: String): File { - val fileUrl = javaClass.classLoader.getResource("$resourceAbsolutePath/$resourceFile") - requireNotNull(fileUrl) { "Cannot read resource file $$resourceAbsolutePath/$resourceFile - it cannot be found in resources" } - return File(fileUrl.file) - } - - /** - * Get result of the test execution - * - * @return list stdOut - */ - protected open fun getExecutionResult() = testResult.stdOut -} diff --git a/diktat-test-framework/src/main/kotlin/com/saveourtool/diktat/test/framework/processing/TestMixed.kt b/diktat-test-framework/src/main/kotlin/com/saveourtool/diktat/test/framework/processing/TestMixed.kt deleted file mode 100644 index 3b1ddf3a96..0000000000 --- a/diktat-test-framework/src/main/kotlin/com/saveourtool/diktat/test/framework/processing/TestMixed.kt +++ /dev/null @@ -1,29 +0,0 @@ -package com.saveourtool.diktat.test.framework.processing - -import com.saveourtool.diktat.test.framework.common.TestBase -import com.saveourtool.diktat.test.framework.config.TestConfig -import com.saveourtool.diktat.test.framework.config.TestFrameworkProperties - -@Suppress( - "MISSING_KDOC_TOP_LEVEL", - "KDOC_NO_EMPTY_TAGS", - "UNUSED" -) // fixme: add documentation when implementation is done -class TestMixed : TestBase { - private lateinit var testConfig: TestConfig - - /** - * @return - */ - override fun runTest() = true - - /** - * @param testConfig - * @param properties - * @return - */ - override fun initTestProcessor(testConfig: TestConfig, properties: TestFrameworkProperties): TestMixed { - this.testConfig = testConfig - return this - } -} diff --git a/diktat-test-framework/src/main/kotlin/com/saveourtool/diktat/test/framework/processing/TestProcessingFactory.kt b/diktat-test-framework/src/main/kotlin/com/saveourtool/diktat/test/framework/processing/TestProcessingFactory.kt deleted file mode 100644 index 679771240e..0000000000 --- a/diktat-test-framework/src/main/kotlin/com/saveourtool/diktat/test/framework/processing/TestProcessingFactory.kt +++ /dev/null @@ -1,99 +0,0 @@ -package com.saveourtool.diktat.test.framework.processing - -import com.saveourtool.diktat.test.framework.common.TestBase -import com.saveourtool.diktat.test.framework.config.TestArgumentsReader -import com.saveourtool.diktat.test.framework.config.TestConfig -import com.saveourtool.diktat.test.framework.config.TestConfig.ExecutionType -import com.saveourtool.diktat.test.framework.config.TestConfigReader -import io.github.oshai.kotlinlogging.KotlinLogging - -import java.io.File -import java.io.IOException -import java.net.URL -import java.util.concurrent.atomic.AtomicInteger -import java.util.stream.Stream - -import kotlin.system.exitProcess - -/** - * A class that runs tests based on configuration - * - * @param argReader - */ -@Suppress("ForbiddenComment") -class TestProcessingFactory(private val argReader: TestArgumentsReader) { - private val allTestsFromResources: List by lazy { - val fileUrl: URL? = javaClass.getResource("/${argReader.properties.testConfigsRelativePath}") - val resource = fileUrl - ?.let { File(it.file) } - ?: run { - log.error { - "Not able to get directory with test configuration files: ${argReader.properties.testConfigsRelativePath}" - } - exitProcess(STATUS_FIVE) - } - try { - resource - .walk() - .filter { file -> file.isFile } - .map { file -> file.name.replace(".json", "") } - .toList() - } catch (e: IOException) { - log.error(e) { "Got -all option, but cannot read config files " } - exitProcess(STATUS_THREE) - } - } - - /** - * Run all tests specified in input parameters and log results - */ - fun processTests() { - val failedTests = AtomicInteger(0) - val passedTests = AtomicInteger(0) - val testList: List = if (argReader.shouldRunAllTests()) { - log.info { "Will run all available test cases" } - allTestsFromResources - } else { - log.info { "Will run specific tests: ${argReader.tests}" } - argReader.tests - } - - val testStream: Stream = - if (argReader.properties.isParallelMode) testList.parallelStream() else testList.stream() - - testStream - .map { test: String -> findTestInResources(test) } - .filter { it != null } - .map { it as TestConfig } - .forEach { test: TestConfig -> - if (processTest(test)) passedTests.incrementAndGet() else failedTests.incrementAndGet() - } - - log.info { "Test processing finished. Passed tests: [$passedTests]. Failed tests: [$failedTests]" } - } - - private fun findTestInResources(test: String): TestConfig? = - TestConfigReader("${argReader.properties.testConfigsRelativePath}/$test.json", javaClass.classLoader) - .config - ?.setTestName(test) - - @Suppress("FUNCTION_BOOLEAN_PREFIX") - private fun processTest(testConfig: TestConfig): Boolean { - val test: TestBase = when (testConfig.executionType) { - ExecutionType.MIXED -> - // FixMe: support Mixed type - TestCompare() - ExecutionType.COMPARE -> TestCompare() - ExecutionType.CHECK_WARN -> TestCheckWarn() - } - - return test.initTestProcessor(testConfig, argReader.properties) - .runTest() - } - - companion object { - private val log = KotlinLogging.logger {} - private const val STATUS_FIVE = 5 - private const val STATUS_THREE = 3 - } -} diff --git a/diktat-test-framework/src/main/resources/com/saveourtool/diktat/test/framework/test_arguments.json b/diktat-test-framework/src/main/resources/com/saveourtool/diktat/test/framework/test_arguments.json deleted file mode 100644 index f247db6d85..0000000000 --- a/diktat-test-framework/src/main/resources/com/saveourtool/diktat/test/framework/test_arguments.json +++ /dev/null @@ -1,23 +0,0 @@ -[ - { - "shortName": "help", - "longName": "help", - "helpDescr": "Help information", - "isRequired": false, - "hasArgs": false - }, - { - "shortName": "t", - "longName": "tests", - "helpDescr": "This option specifies the test that should be run. Tests can be listed separated with comma", - "isRequired": false, - "hasArgs": true - }, - { - "shortName": "all", - "longName": "all", - "helpDescr": "Run all tests that have configuration json-file", - "isRequired": false, - "hasArgs": false - } -] \ No newline at end of file diff --git a/diktat-test-framework/src/main/resources/com/saveourtool/diktat/test/framework/test_configs/functional/1_3_a_package_naming.json b/diktat-test-framework/src/main/resources/com/saveourtool/diktat/test/framework/test_configs/functional/1_3_a_package_naming.json deleted file mode 100644 index 017041533b..0000000000 --- a/diktat-test-framework/src/main/resources/com/saveourtool/diktat/test/framework/test_configs/functional/1_3_a_package_naming.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "profile": "KT", - "executionCommand": "dir", - "expectedResultFile": "1_3_a_package_naming_correct_.kt", - "inPlace": true, - "testFile": "1_3_a_package_naming_incorrect_.kt", - "executionType": "COMPARE" -} \ No newline at end of file diff --git a/diktat-test-framework/src/main/resources/com/saveourtool/diktat/test/framework/test_configs/functional/1_3_b_package_naming.json b/diktat-test-framework/src/main/resources/com/saveourtool/diktat/test/framework/test_configs/functional/1_3_b_package_naming.json deleted file mode 100644 index 1e62f5ed74..0000000000 --- a/diktat-test-framework/src/main/resources/com/saveourtool/diktat/test/framework/test_configs/functional/1_3_b_package_naming.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "profile": "KT", - "executionCommand": "didfgdr", - "expectedResultFile": "1_3_b_package_naming.warn", - "inPlace": false, - "testFile": "1_3_a_package_naming_correct_.kt", - "executionType": "CHECK_WARN" -} \ No newline at end of file diff --git a/diktat-test-framework/src/main/resources/com/saveourtool/diktat/test/framework/test_configs/functional/1_9_a_special_space_cases.json b/diktat-test-framework/src/main/resources/com/saveourtool/diktat/test/framework/test_configs/functional/1_9_a_special_space_cases.json deleted file mode 100644 index 5c8ec29834..0000000000 --- a/diktat-test-framework/src/main/resources/com/saveourtool/diktat/test/framework/test_configs/functional/1_9_a_special_space_cases.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "profile": "PYTHON", - "executionCommand": "dir", - "expectedResultFile": "1_9_a_special_space_cases_correct_.py", - "testFile": "1_9_a_special_space_cases_incorrect_.py", - "inPlace": false, - "executionType": "MIXED" -} \ No newline at end of file diff --git a/diktat-test-framework/src/main/resources/com/saveourtool/diktat/test/framework/test_framework.properties b/diktat-test-framework/src/main/resources/com/saveourtool/diktat/test/framework/test_framework.properties deleted file mode 100644 index 1752d60f00..0000000000 --- a/diktat-test-framework/src/main/resources/com/saveourtool/diktat/test/framework/test_framework.properties +++ /dev/null @@ -1,12 +0,0 @@ -# base directory of test framework (relative path in resources) -test.framework.dir=test_framework -# filename of a configuration file where argument description is stored -test.framework.arguments=test_arguments.json -# relative path (from base test.framework.dir) to a directory, where all test configurations are stored -test.configs.dir=test_configs/functional -# relative path (from base test.framework.dir) to a directory, where all test files (that should be run) are stored -test.files.dir=test_files/functional - - -# to setup test run in parallel mode - use this configuration -parallel.mode=false diff --git a/diktat-test-framework/src/main/resources/config.properties b/diktat-test-framework/src/main/resources/config.properties deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/diktat-test-framework/src/main/resources/log4j2.properties b/diktat-test-framework/src/main/resources/log4j2.properties deleted file mode 100644 index 20bfdb44d6..0000000000 --- a/diktat-test-framework/src/main/resources/log4j2.properties +++ /dev/null @@ -1,8 +0,0 @@ -rootLogger.level = info -rootLogger.appenderRef.stdout.ref = STDOUT - -appender.stdout.type = Console -appender.stdout.name = STDOUT -appender.stdout.target = SYSTEM_OUT -appender.stdout.layout.type = PatternLayout -appender.stdout.layout.pattern = [%-5p] %d{yyyy-MM-dd HH:mm:ss} %m%n \ No newline at end of file diff --git a/diktat-test-framework/src/main/resources/options.json b/diktat-test-framework/src/main/resources/options.json deleted file mode 100644 index dfa11b468e..0000000000 --- a/diktat-test-framework/src/main/resources/options.json +++ /dev/null @@ -1,23 +0,0 @@ -[ - { - "shortName": "help", - "longName": "help", - "helpDescr": "Help information", - "isRequired": false, - "hasArgs": false - }, - { - "shortName": "t", - "longName": "test", - "helpDescr": "This option specifies the test that should be run. Tests can be listed separated with comma", - "isRequired": false, - "hasArgs": true - }, - { - "shortName": "all", - "longName": "all", - "helpDescr": "Run all tests that have configuration json-file", - "isRequired": false, - "hasArgs": false - } -] diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 6063546da0..0a7026d407 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -22,7 +22,6 @@ jbool = "1.24" kotlin-logging = "5.1.0" log4j2 = "2.21.1" kaml = "0.55.0" -kotlin-multiplatform-diff = "0.4.0" sarif4k = "0.5.0" jupiter-itf-extension = "0.12.0" # FIXME: need to migrate to mockito @@ -83,7 +82,6 @@ kaml = { module = "com.charleskorn.kaml:kaml", version.ref = "kaml" } kotlinx-coroutines-core = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-core", version.ref = "kotlinx-coroutines" } #kotlin libs -kotlin-multiplatform-diff = { module = "io.github.petertrr:kotlin-multiplatform-diff", version.ref = "kotlin-multiplatform-diff" } # ktlint & detekt ktlint-rule-engine = { module = "com.pinterest.ktlint:ktlint-rule-engine", version.ref = "ktlint" } diff --git a/settings.gradle.kts b/settings.gradle.kts index ae97fc2aed..fb5ebee13c 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -48,12 +48,12 @@ plugins { includeBuild("gradle/plugins") include("diktat-api") include("diktat-common") +include("diktat-common-test") include("diktat-ktlint-engine") include("diktat-gradle-plugin") include("diktat-maven-plugin") include("diktat-rules") include("diktat-ruleset") -include("diktat-test-framework") include("diktat-dev-ksp") include("diktat-cli")