diff --git a/OptionsTable.md b/OptionsTable.md index b69af8126..d257f3802 100644 --- a/OptionsTable.md +++ b/OptionsTable.md @@ -12,4 +12,8 @@ Most (except for `-h` and `-prop`) of the options below can be passed to a SAVE | i | include-suites | Test suites, only which ones will be checked | - | | l | language | Language that you are developing analyzer for | UNDEFINED | | out | result-output | Data output stream | STDOUT | -| - | report-dir | Path to directory, where to store output (when `resultOutput` is set to `FILE`) | save-reports | \ No newline at end of file +| - | report-dir | Path to directory, where to store output (when `resultOutput` is set to `FILE`) | save-reports | +| - | override-exec-cmd | A temporary workaround for save-cloud to override `execCmd` in `save.toml` | - | +| - | override-exec-flags | A temporary workaround for save-cloud to override `execFlags` in `save.toml` | - | +| - | batch-size | Number of files execCmd will process at a time | 1 | +| - | batch-separator | A separator to join test files to string if the tested tool supports processing of file batches (`batch-size` > 1) | , | \ No newline at end of file diff --git a/buildSrc/src/main/resources/config-options.json b/buildSrc/src/main/resources/config-options.json index ca30723f8..d6a98157e 100644 --- a/buildSrc/src/main/resources/config-options.json +++ b/buildSrc/src/main/resources/config-options.json @@ -78,5 +78,37 @@ "shortName" : "", "description" : "Path to directory, where to store output (when `resultOutput` is set to `FILE`)", "default" : "save-reports" + }, + "overrideExecCmd" : { + "argType": "ArgType.String", + "kotlinType": "kotlin.String", + "fullName": "override-exec-cmd", + "shortName" : "", + "description" : "A temporary workaround for save-cloud to override `execCmd` in `save.toml`", + "default" : null + }, + "overrideExecFlags" : { + "argType": "ArgType.String", + "kotlinType": "kotlin.String", + "fullName": "override-exec-flags", + "shortName" : "", + "description" : "A temporary workaround for save-cloud to override `execFlags` in `save.toml`", + "default" : null + }, + "batchSize" : { + "argType" : "ArgType.Int", + "kotlinType": "kotlin.Int", + "fullName" : "batch-size", + "shortName" : "", + "description" : "Number of files execCmd will process at a time", + "default" : "1" + }, + "batchSeparator" : { + "argType": "ArgType.String", + "kotlinType": "kotlin.String", + "fullName": "batch-separator", + "shortName" : "", + "description" : "A separator to join test files to string if the tested tool supports processing of file batches (`batch-size` > 1)", + "default" : ", " } } \ No newline at end of file diff --git a/save-cli/src/commonNonJsMain/kotlin/com/saveourtool/save/cli/config/SavePropertiesExt.kt b/save-cli/src/commonNonJsMain/kotlin/com/saveourtool/save/cli/config/SavePropertiesExt.kt index c731a8ad4..661b9a1a7 100644 --- a/save-cli/src/commonNonJsMain/kotlin/com/saveourtool/save/cli/config/SavePropertiesExt.kt +++ b/save-cli/src/commonNonJsMain/kotlin/com/saveourtool/save/cli/config/SavePropertiesExt.kt @@ -7,6 +7,7 @@ package com.saveourtool.save.cli.config import com.saveourtool.save.cli.ExitCodes import com.saveourtool.save.cli.fs import com.saveourtool.save.cli.logging.logErrorAndExit +import com.saveourtool.save.cli.logging.logWarn import com.saveourtool.save.core.config.SaveProperties import com.saveourtool.save.core.config.resolveSaveTomlConfig import com.saveourtool.save.core.logging.logDebug @@ -51,6 +52,23 @@ private fun SaveProperties.validate(): SaveProperties { " Please provide a valid path to the test config via command-line or using the file with properties." ) } + if (batchSize < 1) { + return logErrorAndExit( + ExitCodes.INVALID_CONFIGURATION, "Property `batch-size` should be more or equal to 1." + ) + } + overrideExecCmd?.also { + logWarn { + "Property `override-exec-cmd` is a temporary workaround for `save-cloud`, " + + "please be aware this property can be removed in future versions" + } + } + overrideExecFlags?.also { + logWarn { + "Property `override-exec-flags` is a temporary workaround for `save-cloud`, " + + "please be aware this property can be removed in future versions" + } + } return this } diff --git a/save-cli/src/commonNonJsMain/kotlin/com/saveourtool/save/cli/logging/Logger.kt b/save-cli/src/commonNonJsMain/kotlin/com/saveourtool/save/cli/logging/Logger.kt index 477218325..ff7dffc85 100644 --- a/save-cli/src/commonNonJsMain/kotlin/com/saveourtool/save/cli/logging/Logger.kt +++ b/save-cli/src/commonNonJsMain/kotlin/com/saveourtool/save/cli/logging/Logger.kt @@ -15,3 +15,10 @@ import com.saveourtool.save.cli.ExitCodes */ @Deprecated("never use this method in save-core as it can lead to a break of save-cloud application") expect fun logErrorAndExit(exitCode: ExitCodes, message: String): Nothing + +/** + * Log result of [messageSupplier] with level WARN + * + * @param messageSupplier supplier for message to log + */ +expect fun logWarn(messageSupplier: () -> String): Unit diff --git a/save-cli/src/jvmMain/kotlin/com/saveourtool/save/cli/logging/Logger.kt b/save-cli/src/jvmMain/kotlin/com/saveourtool/save/cli/logging/Logger.kt index bb1ba8872..54adcf7a7 100644 --- a/save-cli/src/jvmMain/kotlin/com/saveourtool/save/cli/logging/Logger.kt +++ b/save-cli/src/jvmMain/kotlin/com/saveourtool/save/cli/logging/Logger.kt @@ -6,9 +6,14 @@ package com.saveourtool.save.cli.logging import com.saveourtool.save.cli.ExitCodes import com.saveourtool.save.core.logging.logError +import com.saveourtool.save.core.logging.logWarn import kotlin.system.exitProcess actual fun logErrorAndExit(exitCode: ExitCodes, message: String): Nothing { logError(message) exitProcess(exitCode.code) } + +actual fun logWarn(messageSupplier: () -> String) { + logWarn(messageSupplier()) +} diff --git a/save-cli/src/nativeMain/kotlin/com/saveourtool/save/cli/logging/Logger.kt b/save-cli/src/nativeMain/kotlin/com/saveourtool/save/cli/logging/Logger.kt index bb1ba8872..54adcf7a7 100644 --- a/save-cli/src/nativeMain/kotlin/com/saveourtool/save/cli/logging/Logger.kt +++ b/save-cli/src/nativeMain/kotlin/com/saveourtool/save/cli/logging/Logger.kt @@ -6,9 +6,14 @@ package com.saveourtool.save.cli.logging import com.saveourtool.save.cli.ExitCodes import com.saveourtool.save.core.logging.logError +import com.saveourtool.save.core.logging.logWarn import kotlin.system.exitProcess actual fun logErrorAndExit(exitCode: ExitCodes, message: String): Nothing { logError(message) exitProcess(exitCode.code) } + +actual fun logWarn(messageSupplier: () -> String) { + logWarn(messageSupplier()) +} diff --git a/save-common-test/src/commonNonJsMain/kotlin/com/saveourtool/save/plugin/MockPlugin.kt b/save-common-test/src/commonNonJsMain/kotlin/com/saveourtool/save/plugin/MockPlugin.kt index 9f9024235..7c1ac709e 100644 --- a/save-common-test/src/commonNonJsMain/kotlin/com/saveourtool/save/plugin/MockPlugin.kt +++ b/save-common-test/src/commonNonJsMain/kotlin/com/saveourtool/save/plugin/MockPlugin.kt @@ -1,5 +1,6 @@ package com.saveourtool.save.plugin +import com.saveourtool.save.core.config.EvaluatedToolConfig import com.saveourtool.save.core.config.TestConfig import com.saveourtool.save.core.files.createFile import com.saveourtool.save.core.plugin.Plugin @@ -20,7 +21,7 @@ class MockPlugin(baseDir: Path, testFiles: List = emptyList()) : Plugin( useInternalRedirections = true, redirectTo = null ) { - override fun handleFiles(files: Sequence): Sequence = emptySequence() + override fun handleFiles(evaluatedToolConfig: EvaluatedToolConfig, files: Sequence): Sequence = emptySequence() override fun rawDiscoverTestFiles(resourceDirectories: Sequence): Sequence = emptySequence() diff --git a/save-common/src/commonMain/kotlin/com/saveourtool/save/core/config/EvaluatedToolConfig.kt b/save-common/src/commonMain/kotlin/com/saveourtool/save/core/config/EvaluatedToolConfig.kt new file mode 100644 index 000000000..9f4d56ffa --- /dev/null +++ b/save-common/src/commonMain/kotlin/com/saveourtool/save/core/config/EvaluatedToolConfig.kt @@ -0,0 +1,16 @@ +package com.saveourtool.save.core.config + +/** + * Configuration for an evaluated tool, that is read from test suite configuration file (toml config) or cli + * + * @property execCmd + * @property execFlags + * @property batchSize it controls how many files execCmd will process at a time + * @property batchSeparator A separator to join test files to string if the tested tool supports processing of file batches (`batch-size` > 1) + */ +data class EvaluatedToolConfig( + val execCmd: String?, + val execFlags: String?, + val batchSize: Int, + val batchSeparator: String, +) diff --git a/save-common/src/commonMain/kotlin/com/saveourtool/save/core/plugin/Plugin.kt b/save-common/src/commonMain/kotlin/com/saveourtool/save/core/plugin/Plugin.kt index d0ac9f123..233945dfe 100644 --- a/save-common/src/commonMain/kotlin/com/saveourtool/save/core/plugin/Plugin.kt +++ b/save-common/src/commonMain/kotlin/com/saveourtool/save/core/plugin/Plugin.kt @@ -1,5 +1,6 @@ package com.saveourtool.save.core.plugin +import com.saveourtool.save.core.config.EvaluatedToolConfig import com.saveourtool.save.core.config.TestConfig import com.saveourtool.save.core.config.isSaveTomlConfig import com.saveourtool.save.core.files.createRelativePathToTheRoot @@ -20,6 +21,7 @@ import kotlinx.serialization.Serializable /** * Plugin that can be injected into SAVE during execution. Plugins accept contents of configuration file and then perform some work. + * * @property testConfig * @property testFiles a list of files (test resources or save.toml configs) * @property fs describes the current file system @@ -42,9 +44,10 @@ abstract class Plugin( /** * Perform plugin's work. * + * @param evaluatedToolConfig a configuration for evaluated tool * @return a sequence of [TestResult]s for each group of test resources */ - fun execute(): Sequence { + fun execute(evaluatedToolConfig: EvaluatedToolConfig): Sequence { clean() val testFilesList = discoverTestFiles(testConfig.directory).toList() @@ -68,7 +71,7 @@ abstract class Plugin( val excludedTestResults = excludedTestFiles.map { TestResult(it, Ignored("Excluded by configuration")) } - handleFiles(actualTestFiles.asSequence()) + excludedTestResults + handleFiles(evaluatedToolConfig, actualTestFiles.asSequence()) + excludedTestResults } else { emptySequence() } @@ -77,10 +80,11 @@ abstract class Plugin( /** * Perform plugin's work on a set of files. * + * @param evaluatedToolConfig a configuration for evaluated tool * @param files a sequence of file groups, corresponding to tests. * @return a sequence of [TestResult]s for each group of test resources */ - abstract fun handleFiles(files: Sequence): Sequence + abstract fun handleFiles(evaluatedToolConfig: EvaluatedToolConfig, files: Sequence): Sequence /** * Discover groups of resource files which will be used to run tests, applying additional filtering diff --git a/save-common/src/commonMain/kotlin/com/saveourtool/save/core/plugin/PluginConfig.kt b/save-common/src/commonMain/kotlin/com/saveourtool/save/core/plugin/PluginConfig.kt index a4b4da26a..0fa865712 100644 --- a/save-common/src/commonMain/kotlin/com/saveourtool/save/core/plugin/PluginConfig.kt +++ b/save-common/src/commonMain/kotlin/com/saveourtool/save/core/plugin/PluginConfig.kt @@ -41,7 +41,7 @@ interface PluginConfig { val resourceNamePatternStr: String /** - * @param otherConfig - 'this' will be merged with 'other' + * @param otherConfig 'this' will be merged with 'other' * @return merged config */ fun mergeWith(otherConfig: PluginConfig): PluginConfig @@ -60,13 +60,13 @@ interface PluginConfig { * of nested configs, we can't detect whether the value are passed by user, or taken from default. * The logic of the default value processing will be provided in stage of validation * - * @property execCmd a command that will be executed to check resources and emit warnings + * @property execCmd a command that will be executed to check resources * @property tags special labels that can be used for splitting tests into groups * @property description free text with a description * @property suiteName name of test suite that can be visible from save-cloud * @property language to tests * @property excludedTests excluded tests from the run - * @property expectedWarningsPattern - pattern with warnings that are expected from the test file + * @property expectedWarningsPattern pattern with warnings that are expected from the test file * @property runConfigPattern everything from the capture group will be split by comma and then by `=` * @property timeOutMillis command execution time for one test * @property expectedWarningsMiddlePattern diff --git a/save-common/src/commonNonJsTest/kotlin/com/saveourtool/save/core/ProcessBuilderTest.kt b/save-common/src/commonNonJsTest/kotlin/com/saveourtool/save/core/ProcessBuilderTest.kt index d2a0bd10b..35cfc92d3 100644 --- a/save-common/src/commonNonJsTest/kotlin/com/saveourtool/save/core/ProcessBuilderTest.kt +++ b/save-common/src/commonNonJsTest/kotlin/com/saveourtool/save/core/ProcessBuilderTest.kt @@ -4,19 +4,18 @@ package com.saveourtool.save.core +import com.saveourtool.save.core.files.fs import com.saveourtool.save.core.utils.ProcessBuilder import com.saveourtool.save.core.utils.ProcessBuilder.Companion.processCommandWithEcho import com.saveourtool.save.core.utils.ProcessExecutionException import com.saveourtool.save.core.utils.isCurrentOsWindows -import okio.FileSystem - import kotlin.test.Test import kotlin.test.assertEquals @Suppress("INLINE_CLASS_CAN_BE_USED") class ProcessBuilderTest { - private val processBuilder = ProcessBuilder(useInternalRedirections = true, FileSystem.SYSTEM) + private val processBuilder = ProcessBuilder(useInternalRedirections = true, fs) @Test fun `empty command`() { diff --git a/save-core/src/commonNonJsMain/kotlin/com/saveourtool/save/core/Save.kt b/save-core/src/commonNonJsMain/kotlin/com/saveourtool/save/core/Save.kt index 50096c10f..f59ce8ea6 100644 --- a/save-core/src/commonNonJsMain/kotlin/com/saveourtool/save/core/Save.kt +++ b/save-core/src/commonNonJsMain/kotlin/com/saveourtool/save/core/Save.kt @@ -1,5 +1,6 @@ package com.saveourtool.save.core +import com.saveourtool.save.core.config.EvaluatedToolConfig import com.saveourtool.save.core.config.OutputStreamType import com.saveourtool.save.core.config.ReportType import com.saveourtool.save.core.config.SAVE_VERSION @@ -72,6 +73,14 @@ class Save( reporter.beforeAll() + // create config for evaluated tool from cli args + val evaluatedToolConfig = EvaluatedToolConfig( + execCmd = saveProperties.overrideExecCmd, + execFlags = saveProperties.overrideExecFlags, + batchSize = saveProperties.batchSize, + batchSeparator = saveProperties.batchSeparator, + ) + // get all toml configs in file system val testConfigs = ConfigDetector(fs) .configFromFile(rootTestConfigPath) @@ -97,7 +106,7 @@ class Save( ?.forEach { atLeastOneExecutionProvided = true // execute created plugins - executePlugin(it, reporter) + executePlugin(evaluatedToolConfig, it, reporter) } ?.also { reporter.onSuiteEnd(testConfig.getGeneralConfig()?.suiteName!!) @@ -146,12 +155,16 @@ class Save( (excludeSuites.isEmpty() || !excludeSuites.contains(suiteName)) } - private fun executePlugin(plugin: Plugin, reporter: Reporter) { + private fun executePlugin( + evaluatedToolConfig: EvaluatedToolConfig, + plugin: Plugin, + reporter: Reporter + ) { reporter.onPluginInitialization(plugin) logDebug("=> Executing plugin: ${plugin::class.simpleName} for [${plugin.testConfig.location}]") reporter.onPluginExecutionStart(plugin) try { - plugin.execute() + plugin.execute(evaluatedToolConfig) .onEach { event -> // calculate relative paths, because reporters don't need paths higher than root dir val resourcesRelative = event.resources.withRelativePaths(testRootPath) diff --git a/save-core/src/commonNonJsTest/kotlin/com/saveourtool/save/core/MergeConfigsTest.kt b/save-core/src/commonNonJsTest/kotlin/com/saveourtool/save/core/MergeConfigsTest.kt index ea3cf5322..4831bc0d5 100644 --- a/save-core/src/commonNonJsTest/kotlin/com/saveourtool/save/core/MergeConfigsTest.kt +++ b/save-core/src/commonNonJsTest/kotlin/com/saveourtool/save/core/MergeConfigsTest.kt @@ -40,16 +40,16 @@ class MergeConfigsTest { private val warningsOutputPattern1 = Regex(".*") private val warningsOutputPattern2 = Regex("\\w+ - (\\d+)/(\\d+) - (.*)$") private val warnConfig1 = WarnPluginConfig("execCmd1", warningsOutputPattern2, - false, false, 1, ", ", 1, 1, 1, 1, 1, 1, 1, 1, 1, false, null) + false, false, 1, 1, 1, 1, 1, 1, 1, 1, 1, false, null) private val warnConfig2 = WarnPluginConfig("execCmd2", warningsOutputPattern1, - true, true, 1, ", ", 2, 2, 2, 1, 1, 2, 2, 2, 2, true, null) + true, true, 2, 2, 2, 1, 1, 2, 2, 2, 2, true, null) private val warnConfig3 = WarnPluginConfig("execCmd3", warningsOutputPattern2, - warningTextHasColumn = false, batchSize = 1, lineCaptureGroup = 3, columnCaptureGroup = 3, messageCaptureGroup = 3, + warningTextHasColumn = false, lineCaptureGroup = 3, columnCaptureGroup = 3, messageCaptureGroup = 3, fileNameCaptureGroupOut = 3, lineCaptureGroupOut = 3, columnCaptureGroupOut = 3, messageCaptureGroupOut = 3) private val warnConfig4 = WarnPluginConfig("execCmd4", warningsOutputPattern2, - batchSize = 1, lineCaptureGroup = 4, columnCaptureGroup = 4, messageCaptureGroup = 4, + lineCaptureGroup = 4, columnCaptureGroup = 4, messageCaptureGroup = 4, fileNameCaptureGroupOut = 4, lineCaptureGroupOut = 4, columnCaptureGroupOut = 4, messageCaptureGroupOut = 4) - private val fixConfig1 = FixPluginConfig("fixCmd1", 1, "Suffix") + private val fixConfig1 = FixPluginConfig("fixCmd1", "Suffix") private val fixConfig2 = FixPluginConfig("fixCmd2") private val fixConfig3 = FixPluginConfig("fixCmd3", null) private val fixConfig4 = FixPluginConfig("fixCmd4") @@ -122,8 +122,8 @@ class MergeConfigsTest { val expectedGeneralConfig = GeneralConfig("", listOf("Tag11", "Tag12", "Tag21"), "Description2", "suiteName2", "Kotlin", listOf("excludedTests: test3"), runConfigPattern = extraFlagsPattern1) val expectedWarnConfig = WarnPluginConfig("execCmd3", warningsOutputPattern2, - true, false, 1, ", ", 3, 3, 3, 1, 1, 3, 3, 3, 3, true, null) - val expectedFixConfig = FixPluginConfig("fixCmd2", 1, "Suffix") + true, false, 3, 3, 3, 1, 1, 3, 3, 3, 3, true, null) + val expectedFixConfig = FixPluginConfig("fixCmd2", "Suffix") val actualGeneralConfig = config2.pluginConfigs.filterIsInstance().first() val actualWarnConfig = config2.pluginConfigs.filterIsInstance().first() @@ -151,8 +151,8 @@ class MergeConfigsTest { val expectedGeneralConfig = GeneralConfig("", listOf("Tag11", "Tag12", "Tag21", "Tag31", "Tag32"), "Description2", "suiteName4", "Kotlin", listOf("excludedTests: test7"), runConfigPattern = extraFlagsPattern2) val expectedWarnConfig = WarnPluginConfig("execCmd4", warningsOutputPattern2, - true, false, 1, ", ", 4, 4, 4, 1, 1, 4, 4, 4, 4, true, null) - val expectedFixConfig = FixPluginConfig("fixCmd4", 1, "Suffix") + true, false, 4, 4, 4, 1, 1, 4, 4, 4, 4, true, null) + val expectedFixConfig = FixPluginConfig("fixCmd4", "Suffix") val actualGeneralConfig = config4.pluginConfigs.filterIsInstance().first() val actualWarnConfig = config4.pluginConfigs.filterIsInstance().first() diff --git a/save-core/src/commonNonJsTest/kotlin/com/saveourtool/save/core/test/utils/TestUtilsCommon.kt b/save-core/src/commonNonJsTest/kotlin/com/saveourtool/save/core/test/utils/TestUtilsCommon.kt index 15c7303d2..db916abb4 100644 --- a/save-core/src/commonNonJsTest/kotlin/com/saveourtool/save/core/test/utils/TestUtilsCommon.kt +++ b/save-core/src/commonNonJsTest/kotlin/com/saveourtool/save/core/test/utils/TestUtilsCommon.kt @@ -11,13 +11,13 @@ import com.saveourtool.save.core.config.LogType import com.saveourtool.save.core.config.OutputStreamType import com.saveourtool.save.core.config.ReportType import com.saveourtool.save.core.config.SaveProperties +import com.saveourtool.save.core.files.fs import com.saveourtool.save.core.logging.logType import com.saveourtool.save.core.result.Fail import com.saveourtool.save.core.result.Ignored import com.saveourtool.save.core.result.Pass import com.saveourtool.save.reporter.test.TestReporter -import okio.FileSystem import okio.Path import kotlin.test.assertEquals @@ -55,7 +55,7 @@ fun runTestsWithDiktat( logType.set(LogType.ALL) // In this test we need to merge with emulated empty save.properties file in aim to use default values, // since initially all fields are null - val save = Save(saveProperties, FileSystem.SYSTEM) + val save = Save(saveProperties, fs) val testReporter = save.performAnalysis() as TestReporter assertEquals(numberOfTests, testReporter.results.size) diff --git a/save-plugins/fix-and-warn-plugin/src/commonMain/kotlin/com/saveourtool/save/plugins/fixandwarn/FixAndWarnPlugin.kt b/save-plugins/fix-and-warn-plugin/src/commonMain/kotlin/com/saveourtool/save/plugins/fixandwarn/FixAndWarnPlugin.kt index 95a9d75c8..ebd548518 100644 --- a/save-plugins/fix-and-warn-plugin/src/commonMain/kotlin/com/saveourtool/save/plugins/fixandwarn/FixAndWarnPlugin.kt +++ b/save-plugins/fix-and-warn-plugin/src/commonMain/kotlin/com/saveourtool/save/plugins/fixandwarn/FixAndWarnPlugin.kt @@ -1,5 +1,6 @@ package com.saveourtool.save.plugins.fixandwarn +import com.saveourtool.save.core.config.EvaluatedToolConfig import com.saveourtool.save.core.config.TestConfig import com.saveourtool.save.core.files.readLines import com.saveourtool.save.core.plugin.GeneralConfig @@ -73,7 +74,7 @@ class FixAndWarnPlugin( fs, ) - override fun handleFiles(files: Sequence): Sequence { + override fun handleFiles(evaluatedToolConfig: EvaluatedToolConfig, files: Sequence): Sequence { testConfig.validateAndSetDefaults() // Need to update private fields after validation initOrUpdateConfigs() @@ -83,7 +84,7 @@ class FixAndWarnPlugin( // fixme: should be performed on copies of files val filesAndTheirWarningsMap = removeWarningsFromExpectedFiles(expectedFiles) - val fixTestResults = fixPlugin.handleFiles(files).toList() + val fixTestResults = fixPlugin.handleFiles(evaluatedToolConfig, files).toList() val (fixTestResultsPassed, fixTestResultsFailed) = fixTestResults.partition { it.status is Pass } @@ -109,7 +110,7 @@ class FixAndWarnPlugin( // TODO: then warn plugin should look at the fix plugin output for actual warnings, and not execute command one more time. // TODO: However it's required changes in warn plugin logic (it's should be able to compare expected and actual warnings from different places), // TODO: this probably could be obtained after https://github.com/saveourtool/save/issues/164, - val warnTestResults = warnPlugin.handleFiles(expectedFilesWithPass.map { Test(it) }) + val warnTestResults = warnPlugin.handleFiles(evaluatedToolConfig, expectedFilesWithPass.map { Test(it) }) val fixAndWarnTestResults = fixTestResultsFailed.asSequence() + warnTestResults.map { testResult -> files.map { it as FixPlugin.FixTestFiles } diff --git a/save-plugins/fix-and-warn-plugin/src/commonMain/kotlin/com/saveourtool/save/plugins/fixandwarn/FixAndWarnPluginConfig.kt b/save-plugins/fix-and-warn-plugin/src/commonMain/kotlin/com/saveourtool/save/plugins/fixandwarn/FixAndWarnPluginConfig.kt index 8485bac70..37587d197 100644 --- a/save-plugins/fix-and-warn-plugin/src/commonMain/kotlin/com/saveourtool/save/plugins/fixandwarn/FixAndWarnPluginConfig.kt +++ b/save-plugins/fix-and-warn-plugin/src/commonMain/kotlin/com/saveourtool/save/plugins/fixandwarn/FixAndWarnPluginConfig.kt @@ -42,13 +42,11 @@ data class FixAndWarnPluginConfig( } override fun validateAndSetDefaults(): PluginConfig { - require(warn.resourceNamePattern.matches(fix.resourceNameTest) && - fix.batchSize == warn.batchSize - ) { + require(warn.resourceNamePattern.matches(fix.resourceNameTest)) { """ - Test files batch sizes should be identical for [fix] and [warn] plugins and [fix] files should match [warn] regex . - But found [fix]: {${fix.resourceNameTest}, ${fix.batchSize}}, - [warn]: {${warn.resourceNamePatternStr}, ${warn.batchSize}} + Pattern of [fix] files should match [warn] resource files. + But found [fix]: {${fix.resourceNameTest}, + [warn]: {${warn.resourceNamePatternStr} """ } return FixAndWarnPluginConfig( diff --git a/save-plugins/fix-and-warn-plugin/src/commonNonJsTest/kotlin/com/saveourtool/save/plugins/fixandwarn/FixAndWarnPluginTest.kt b/save-plugins/fix-and-warn-plugin/src/commonNonJsTest/kotlin/com/saveourtool/save/plugins/fixandwarn/FixAndWarnPluginTest.kt index 0193da881..426b1055c 100644 --- a/save-plugins/fix-and-warn-plugin/src/commonNonJsTest/kotlin/com/saveourtool/save/plugins/fixandwarn/FixAndWarnPluginTest.kt +++ b/save-plugins/fix-and-warn-plugin/src/commonNonJsTest/kotlin/com/saveourtool/save/plugins/fixandwarn/FixAndWarnPluginTest.kt @@ -1,5 +1,6 @@ package com.saveourtool.save.plugins.fixandwarn +import com.saveourtool.save.core.config.EvaluatedToolConfig import com.saveourtool.save.core.config.TestConfig import com.saveourtool.save.core.files.createFile import com.saveourtool.save.core.plugin.GeneralConfig @@ -75,10 +76,10 @@ class FixAndWarnPluginTest { null, mutableListOf( FixAndWarnPluginConfig( - FixPluginConfig(fixExecutionCmd, batchSize = 1), + FixPluginConfig(fixExecutionCmd), WarnPluginConfig(warnExecutionCmd, Regex("(.+):(\\d+):(\\d+): (.+)"), - true, true, 1, ", ", 1, 2, 3, 1, 1, 1, 2, 3, 4 + true, true, 1, 2, 3, 1, 1, 1, 2, 3, 4 ) ), GeneralConfig("", listOf(""), "", "", expectedWarningsPattern = Regex("// ;warn:(\\d+):(\\d+): (.*)"), runConfigPattern = defaultExtraConfigPattern) @@ -89,7 +90,7 @@ class FixAndWarnPluginTest { fs, useInternalRedirections = false ) - val results = fixAndWarnPlugin.execute().toList() + val results = fixAndWarnPlugin.execute(EvaluatedToolConfig(null, null, 1, ", ")).toList() println("Results $results") assertEquals(1, results.count(), "Size of results should equal number of pairs") diff --git a/save-plugins/fix-plugin/src/commonMain/kotlin/com/saveourtool/save/plugins/fix/FixPlugin.kt b/save-plugins/fix-plugin/src/commonMain/kotlin/com/saveourtool/save/plugins/fix/FixPlugin.kt index e4c7de0ce..9a2f7e51d 100644 --- a/save-plugins/fix-plugin/src/commonMain/kotlin/com/saveourtool/save/plugins/fix/FixPlugin.kt +++ b/save-plugins/fix-plugin/src/commonMain/kotlin/com/saveourtool/save/plugins/fix/FixPlugin.kt @@ -1,5 +1,6 @@ package com.saveourtool.save.plugins.fix +import com.saveourtool.save.core.config.EvaluatedToolConfig import com.saveourtool.save.core.config.TestConfig import com.saveourtool.save.core.files.createFile import com.saveourtool.save.core.files.createRelativePathToTheRoot @@ -66,22 +67,20 @@ class FixPlugin( private lateinit var extraFlagsExtractor: ExtraFlagsExtractor @Suppress("TOO_LONG_FUNCTION") - override fun handleFiles(files: Sequence): Sequence { + override fun handleFiles(evaluatedToolConfig: EvaluatedToolConfig, files: Sequence): Sequence { testConfig.validateAndSetDefaults() val fixPluginConfig = testConfig.pluginConfigs.filterIsInstance().single() val generalConfig = testConfig.pluginConfigs.filterIsInstance().single() extraFlagsExtractor = ExtraFlagsExtractor(generalConfig, fs) return files.map { it as FixTestFiles } - .chunked(fixPluginConfig.batchSize!!.toInt()) + .chunked(evaluatedToolConfig.batchSize) .map { chunk -> + val copyPaths = chunk.map { it.test } - val extraFlagsList = chunk.map { it.test }.mapNotNull { path -> - extraFlagsExtractor.extractExtraFlagsFrom(path) - } - .distinct() + val extraFlagsList = copyPaths.mapNotNull { path -> extraFlagsExtractor.extractExtraFlagsFrom(path) }.distinct() require(extraFlagsList.size <= 1) { - "Extra flags for all files in a batch should be same, but you have batchSize=${fixPluginConfig.batchSize}" + + "Extra flags for all files in a batch should be same, but you have batchSize=${evaluatedToolConfig.batchSize}" + " and there are ${extraFlagsList.size} different sets of flags inside it, namely $extraFlagsList" } val extraFlags = extraFlagsList.singleOrNull() ?: ExtraFlags("", "") @@ -91,10 +90,12 @@ class FixPlugin( createTestFile(test, generalConfig, fixPluginConfig) to expected } val testCopyNames = - pathCopyMap.joinToString(separator = fixPluginConfig.batchSeparator!!) { (testCopy, _) -> testCopy.toString() } + pathCopyMap.joinToString(separator = evaluatedToolConfig.batchSeparator) { (testCopy, _) -> testCopy.toString() } - val execFlagsAdjusted = resolvePlaceholdersFrom(fixPluginConfig.execFlags, extraFlags, testCopyNames) - val execCmd = "${generalConfig.execCmd} $execFlagsAdjusted" + val execFlags = evaluatedToolConfig.execFlags ?: fixPluginConfig.execFlags + val execFlagsAdjusted = resolvePlaceholdersFrom(execFlags, extraFlags, testCopyNames) + val execCmdWithoutFlags = evaluatedToolConfig.execCmd ?: generalConfig.execCmd + val execCmd = "$execCmdWithoutFlags $execFlagsAdjusted" val time = generalConfig.timeOutMillis!!.times(pathMap.size) val executionResult = try { diff --git a/save-plugins/fix-plugin/src/commonMain/kotlin/com/saveourtool/save/plugins/fix/FixPluginConfig.kt b/save-plugins/fix-plugin/src/commonMain/kotlin/com/saveourtool/save/plugins/fix/FixPluginConfig.kt index 5e746bc6d..cf6d281e7 100644 --- a/save-plugins/fix-plugin/src/commonMain/kotlin/com/saveourtool/save/plugins/fix/FixPluginConfig.kt +++ b/save-plugins/fix-plugin/src/commonMain/kotlin/com/saveourtool/save/plugins/fix/FixPluginConfig.kt @@ -18,18 +18,14 @@ import kotlinx.serialization.UseSerializers * of nested configs, we can't detect whether the value are passed by user, or taken from default. * The logic of the default value processing will be provided in stage of validation * - * @property execFlags a command that will be executed to mutate test file contents - * @property batchSize it controls how many files execCmd will process at a time. + * @property execFlags a flags that will be applied to execCmd * @property resourceNameTestSuffix suffix name of the test file. * @property resourceNameExpectedSuffix suffix name of the expected file. - * @property batchSeparator * @property ignoreLines mutable list of patterns that later will be used to filter lines in test file */ @Serializable data class FixPluginConfig( val execFlags: String? = null, - val batchSize: Long? = null, - val batchSeparator: String? = null, val resourceNameTestSuffix: String? = null, val resourceNameExpectedSuffix: String? = null, val ignoreLines: MutableList? = null @@ -62,8 +58,6 @@ data class FixPluginConfig( val other = otherConfig as FixPluginConfig return FixPluginConfig( this.execFlags ?: other.execFlags, - this.batchSize ?: other.batchSize, - this.batchSeparator ?: other.batchSeparator, this.resourceNameTestSuffix ?: other.resourceNameTestSuffix, this.resourceNameExpectedSuffix ?: other.resourceNameExpectedSuffix, other.ignoreLines?.let { @@ -75,10 +69,8 @@ data class FixPluginConfig( } // due to probable bug in ktoml, ignoreLines = [] and no ignoreLines is ktoml are parsed to be mutableListOf("null") - override fun validateAndSetDefaults() = FixPluginConfig( + override fun validateAndSetDefaults(): FixPluginConfig = FixPluginConfig( execFlags ?: "", - batchSize ?: 1, - batchSeparator ?: ", ", resourceNameTest, resourceNameExpected, ignoreLines diff --git a/save-plugins/fix-plugin/src/commonNonJsTest/kotlin/com/saveourtool/save/plugins/fix/FixPluginTest.kt b/save-plugins/fix-plugin/src/commonNonJsTest/kotlin/com/saveourtool/save/plugins/fix/FixPluginTest.kt index 4bdefa3a6..d297bedcb 100644 --- a/save-plugins/fix-plugin/src/commonNonJsTest/kotlin/com/saveourtool/save/plugins/fix/FixPluginTest.kt +++ b/save-plugins/fix-plugin/src/commonNonJsTest/kotlin/com/saveourtool/save/plugins/fix/FixPluginTest.kt @@ -1,7 +1,9 @@ package com.saveourtool.save.plugins.fix +import com.saveourtool.save.core.config.EvaluatedToolConfig import com.saveourtool.save.core.config.TestConfig import com.saveourtool.save.core.files.createFile +import com.saveourtool.save.core.files.fs import com.saveourtool.save.core.plugin.GeneralConfig import com.saveourtool.save.core.result.DebugInfo import com.saveourtool.save.core.result.Pass @@ -23,7 +25,6 @@ import kotlin.test.assertTrue * - running tool */ class FixPluginTest { - private val fs = FileSystem.SYSTEM private val tmpDir = (FileSystem.SYSTEM_TEMPORARY_DIRECTORY / "${FixPluginTest::class.simpleName!!}-${Random.nextInt()}").also { fs.createDirectory(it) } @@ -84,7 +85,7 @@ class FixPluginTest { fs, useInternalRedirections = false ) - val results = fixPlugin.execute().toList() + val results = fixPlugin.execute(EvaluatedToolConfig(null, null, 1, ", ")).toList() assertEquals(1, results.size, "Size of results should equal number of pairs") val testResult = results.single() @@ -127,7 +128,7 @@ class FixPluginTest { "${diskWithTmpDir}cd $tmpDir && echo Expected file | tee" } - val fixPluginConfig = if (isCurrentOsWindows()) FixPluginConfig(executionCmd, 2) else FixPluginConfig(executionCmd, 2, " ") + val fixPluginConfig = FixPluginConfig(executionCmd) val fixPlugin = FixPlugin(TestConfig(config, null, @@ -139,7 +140,8 @@ class FixPluginTest { fs, useInternalRedirections = false ) - val results = fixPlugin.execute().toList() + val batchSeparator = if (isCurrentOsWindows()) ", " else " " + val results = fixPlugin.execute(EvaluatedToolConfig(null, null, 2, batchSeparator)).toList() // We call ProcessBuilder ourselves, because the command ">" does not work for the list of files ProcessBuilder(false, fs).exec("echo Expected file > $testFile2", "", null, 10_000L) diff --git a/save-plugins/warn-plugin/src/commonMain/kotlin/com/saveourtool/save/plugin/warn/WarnPlugin.kt b/save-plugins/warn-plugin/src/commonMain/kotlin/com/saveourtool/save/plugin/warn/WarnPlugin.kt index d18ef8ed5..8d3494b87 100644 --- a/save-plugins/warn-plugin/src/commonMain/kotlin/com/saveourtool/save/plugin/warn/WarnPlugin.kt +++ b/save-plugins/warn-plugin/src/commonMain/kotlin/com/saveourtool/save/plugin/warn/WarnPlugin.kt @@ -1,6 +1,7 @@ package com.saveourtool.save.plugin.warn import com.saveourtool.save.core.config.ActualWarningsFormat +import com.saveourtool.save.core.config.EvaluatedToolConfig import com.saveourtool.save.core.config.ExpectedWarningsFormat import com.saveourtool.save.core.config.TestConfig import com.saveourtool.save.core.files.createFile @@ -61,7 +62,7 @@ class WarnPlugin( private lateinit var extraFlagsExtractor: ExtraFlagsExtractor private lateinit var tmpDirName: String - override fun handleFiles(files: Sequence): Sequence { + override fun handleFiles(evaluatedToolConfig: EvaluatedToolConfig, files: Sequence): Sequence { testConfig.validateAndSetDefaults() val warnPluginConfig = testConfig.pluginConfigs.filterIsInstance().single() val generalConfig = testConfig.pluginConfigs.filterIsInstance().single() @@ -72,10 +73,10 @@ class WarnPlugin( // // In case, when user doesn't want to use directory mode, he needs simply not to pass [wildCardInDirectoryMode] and it will be null return warnPluginConfig.wildCardInDirectoryMode?.let { - handleTestFile(files.map { it.test }.toList(), warnPluginConfig, generalConfig).asSequence() + handleTestFile(files.map { it.test }.toList(), evaluatedToolConfig, warnPluginConfig, generalConfig).asSequence() } ?: run { - files.chunked(warnPluginConfig.batchSize!!.toInt()).flatMap { chunk -> - handleTestFile(chunk.map { it.test }, warnPluginConfig, generalConfig) + files.chunked(evaluatedToolConfig.batchSize).flatMap { chunk -> + handleTestFile(chunk.map { it.test }, evaluatedToolConfig, warnPluginConfig, generalConfig) } } } @@ -108,6 +109,7 @@ class WarnPlugin( ) private fun handleTestFile( originalPaths: List, + evaluatedToolConfig: EvaluatedToolConfig, warnPluginConfig: WarnPluginConfig, generalConfig: GeneralConfig ): Sequence { @@ -124,6 +126,9 @@ class WarnPlugin( copyPaths, extraFlagsExtractor, pb, + evaluatedToolConfig.execCmd ?: generalConfig.execCmd, + evaluatedToolConfig.execFlags ?: warnPluginConfig.execFlags, + evaluatedToolConfig.batchSeparator, warnPluginConfig, testConfig, fs, diff --git a/save-plugins/warn-plugin/src/commonMain/kotlin/com/saveourtool/save/plugin/warn/WarnPluginConfig.kt b/save-plugins/warn-plugin/src/commonMain/kotlin/com/saveourtool/save/plugin/warn/WarnPluginConfig.kt index 7d2531482..d41d825ff 100644 --- a/save-plugins/warn-plugin/src/commonMain/kotlin/com/saveourtool/save/plugin/warn/WarnPluginConfig.kt +++ b/save-plugins/warn-plugin/src/commonMain/kotlin/com/saveourtool/save/plugin/warn/WarnPluginConfig.kt @@ -21,7 +21,7 @@ import kotlinx.serialization.UseSerializers * of nested configs, we can't detect whether the value are passed by user, or taken from default. * The logic of the default value processing will be provided in stage of validation * - * @property execFlags a command that will be executed to check resources and emit warnings + * @property execFlags a flags that will be applied to execCmd * @property actualWarningsPattern a regular expression by which warnings will be discovered in the process output * @property warningTextHasLine whether line number is included in [actualWarningsPattern] * @property warningTextHasColumn whether column number is included in [actualWarningsPattern] @@ -41,8 +41,6 @@ import kotlinx.serialization.UseSerializers * corresponding to the whole string. * @property exactWarningsMatch exact match of errors * @property testNameRegex regular expression, which defines a test-file's name. - * @property batchSize it controls how many files execCmd will process at a time. - * @property batchSeparator separator for batch mode * @property linePlaceholder placeholder for line number, which resolved as current line and support addition and subtraction * @property wildCardInDirectoryMode mode that controls that we are targeting our tested tools on directories (not on files) * This prefix will be added to the name of the directory, if you would like to use directory mode without any prefix simply use "" @@ -66,8 +64,6 @@ data class WarnPluginConfig( val actualWarningsPattern: Regex? = null, val warningTextHasLine: Boolean? = null, val warningTextHasColumn: Boolean? = null, - val batchSize: Long? = null, - val batchSeparator: String? = null, val lineCaptureGroup: Long? = null, val columnCaptureGroup: Long? = null, val messageCaptureGroup: Long? = null, @@ -118,8 +114,6 @@ data class WarnPluginConfig( this.actualWarningsPattern ?: other.actualWarningsPattern, this.warningTextHasLine ?: other.warningTextHasLine, this.warningTextHasColumn ?: other.warningTextHasColumn, - this.batchSize ?: other.batchSize, - this.batchSeparator ?: other.batchSeparator, this.lineCaptureGroup ?: other.lineCaptureGroup, this.columnCaptureGroup ?: other.columnCaptureGroup, this.messageCaptureGroup ?: other.messageCaptureGroup, @@ -163,7 +157,6 @@ data class WarnPluginConfig( requirePositiveIfNotNull(lineCaptureGroupOut) requirePositiveIfNotNull(columnCaptureGroupOut) requirePositiveIfNotNull(messageCaptureGroupOut) - requirePositiveIfNotNull(batchSize) requireValidPatternForRegexInWarning() val expectedWarningsFormat = expectedWarningsFormat ?: ExpectedWarningsFormat.IN_PLACE @@ -190,8 +183,6 @@ data class WarnPluginConfig( actualWarningsPattern ?: defaultOutputPattern, newWarningTextHasLine, newWarningTextHasColumn, - batchSize ?: 1, - batchSeparator ?: ", ", newLineCaptureGroup, newColumnCaptureGroup, newMessageCaptureGroup, diff --git a/save-plugins/warn-plugin/src/commonMain/kotlin/com/saveourtool/save/plugin/warn/utils/CmdExecutorWarn.kt b/save-plugins/warn-plugin/src/commonMain/kotlin/com/saveourtool/save/plugin/warn/utils/CmdExecutorWarn.kt index 582901683..3d7b7280b 100644 --- a/save-plugins/warn-plugin/src/commonMain/kotlin/com/saveourtool/save/plugin/warn/utils/CmdExecutorWarn.kt +++ b/save-plugins/warn-plugin/src/commonMain/kotlin/com/saveourtool/save/plugin/warn/utils/CmdExecutorWarn.kt @@ -23,11 +23,14 @@ class CmdExecutorWarn( copyPaths: List, extraFlagsExtractor: ExtraFlagsExtractor, pb: ProcessBuilder, + execCmd: String?, + private val execFlags: String?, + private val batchSeparator: String, private val warnPluginConfig: WarnPluginConfig, private val testConfig: TestConfig, private val fs: FileSystem, ) : CmdExecutorBase( - generalConfig.execCmd!!, + execCmd!!, generalConfig.timeOutMillis!!, copyPaths, extraFlagsExtractor, @@ -36,7 +39,7 @@ class CmdExecutorWarn( ) { override fun getWildCardInDirectoryMode(): String? = warnPluginConfig.wildCardInDirectoryMode - override fun getExecFlags(): String? = warnPluginConfig.execFlags + override fun getExecFlags(): String? = execFlags @Suppress("SwallowedException") override fun ExecutionResult.getStdout(): List = warnPluginConfig.testToolResFileOutput?.let { @@ -55,5 +58,5 @@ class CmdExecutorWarn( } ?: this.stdout - override fun getBatchSeparator(): String = warnPluginConfig.batchSeparator!! + override fun getBatchSeparator(): String = batchSeparator } diff --git a/save-plugins/warn-plugin/src/commonTest/kotlin/com/saveourtool/save/plugin/warn/WarnPluginTest.kt b/save-plugins/warn-plugin/src/commonTest/kotlin/com/saveourtool/save/plugin/warn/WarnPluginTest.kt index a3eb75f77..b922994b6 100644 --- a/save-plugins/warn-plugin/src/commonTest/kotlin/com/saveourtool/save/plugin/warn/WarnPluginTest.kt +++ b/save-plugins/warn-plugin/src/commonTest/kotlin/com/saveourtool/save/plugin/warn/WarnPluginTest.kt @@ -1,5 +1,6 @@ package com.saveourtool.save.plugin.warn +import com.saveourtool.save.core.config.EvaluatedToolConfig import com.saveourtool.save.core.config.TestConfig import com.saveourtool.save.core.files.createFile import com.saveourtool.save.core.plugin.GeneralConfig @@ -36,8 +37,6 @@ class WarnPluginTest { execFlags = "$catCmd $mockScriptFile && set stub=", warningTextHasLine = true, warningTextHasColumn = true, - batchSize = 1, - batchSeparator = ", ", lineCaptureGroup = 1, columnCaptureGroup = 2, messageCaptureGroup = 3, @@ -362,10 +361,9 @@ class WarnPluginTest { } """.trimIndent() ), - defaultWarnConfig.copy( - batchSize = 2 - ), - defaultGeneralConfig + defaultWarnConfig, + defaultGeneralConfig, + 2 ) { results -> assertEquals(2, results.size) assertTrue(results.all { it.status is Pass }) @@ -387,10 +385,9 @@ class WarnPluginTest { fs.createFile(tmpDir / "inner" / "Test4Test.java") performTest( emptyList(), // files will be discovered in tmpDir, because they are already created - defaultWarnConfig.copy( - batchSize = 2, - ), - defaultGeneralConfig + defaultWarnConfig, + defaultGeneralConfig, + 2 ) { results -> assertEquals(4, results.size) assertTrue(results.all { it.status is Pass }) @@ -415,7 +412,8 @@ class WarnPluginTest { texts: List, warnPluginConfig: WarnPluginConfig, generalConfig: GeneralConfig, - assertion: (List) -> Unit + batchSize: Int = 1, + assertion: (List) -> Unit, ) { val config = fs.createFile(tmpDir / "save.toml") texts.forEachIndexed { idx, text -> @@ -430,7 +428,7 @@ class WarnPluginTest { testFiles = emptyList(), fs ) - .execute() + .execute(EvaluatedToolConfig(null, null, batchSize, ", ")) .toList() assertion(results) }