diff --git a/OptionsTable.md b/OptionsTable.md index d257f3802..b69af8126 100644 --- a/OptionsTable.md +++ b/OptionsTable.md @@ -12,8 +12,4 @@ 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 | -| - | 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 +| - | report-dir | Path to directory, where to store output (when `resultOutput` is set to `FILE`) | save-reports | \ 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 d6a98157e..ca30723f8 100644 --- a/buildSrc/src/main/resources/config-options.json +++ b/buildSrc/src/main/resources/config-options.json @@ -78,37 +78,5 @@ "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 661b9a1a7..da2ce78b0 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,7 +7,6 @@ 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 @@ -52,24 +51,6 @@ 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-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 7c1ac709e..cc6bcca48 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,6 +1,5 @@ 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 @@ -15,13 +14,17 @@ internal expect val fs: FileSystem * No-op implementation of [Plugin] that can be used to test reporters, which expect only a class name of the plugin. */ class MockPlugin(baseDir: Path, testFiles: List = emptyList()) : Plugin( - TestConfig((baseDir / "save.toml").also { fs.createFile(it) }, null, fs = fs), + TestConfig( + (baseDir / "save.toml").also { fs.createFile(it) }, + null, + overridesPluginConfigs = emptyList(), + fs = fs), testFiles, fs, useInternalRedirections = true, redirectTo = null ) { - override fun handleFiles(evaluatedToolConfig: EvaluatedToolConfig, files: Sequence): Sequence = emptySequence() + override fun handleFiles(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 deleted file mode 100644 index 9f4d56ffa..000000000 --- a/save-common/src/commonMain/kotlin/com/saveourtool/save/core/config/EvaluatedToolConfig.kt +++ /dev/null @@ -1,16 +0,0 @@ -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/config/TestConfig.kt b/save-common/src/commonMain/kotlin/com/saveourtool/save/core/config/TestConfig.kt index a0dc39538..c78a417a8 100644 --- a/save-common/src/commonMain/kotlin/com/saveourtool/save/core/config/TestConfig.kt +++ b/save-common/src/commonMain/kotlin/com/saveourtool/save/core/config/TestConfig.kt @@ -10,10 +10,14 @@ import com.saveourtool.save.core.logging.logTrace import com.saveourtool.save.core.plugin.GeneralConfig import com.saveourtool.save.core.plugin.Plugin import com.saveourtool.save.core.plugin.PluginConfig +import com.saveourtool.save.core.utils.mergeWith +import com.saveourtool.save.core.utils.overrideBy +import com.saveourtool.save.core.utils.singleIsInstanceOrNull import okio.FileSystem import okio.Path import okio.Path.Companion.toPath + import kotlin.js.JsName /** @@ -21,6 +25,7 @@ import kotlin.js.JsName * @property location [Path] denoting the location of this file * @property parentConfig parent config in the hierarchy of configs, `null` if this config is root. * @property pluginConfigs list of configurations for plugins that are active in this config + * @property overridesPluginConfigs list of configurations for plugins that overrides [pluginConfigs] * @property fs filesystem which can access test configs */ @Suppress("TYPE_ALIAS", "TooManyFunctions") @@ -28,6 +33,7 @@ data class TestConfig( val location: Path, val parentConfig: TestConfig?, val pluginConfigs: MutableList = mutableListOf(), + val overridesPluginConfigs: List, val fs: FileSystem, ) { /** @@ -78,7 +84,7 @@ data class TestConfig( * * @return [GeneralConfig] or `null` if not found */ - fun getGeneralConfig() = pluginConfigs.filterIsInstance().singleOrNull() + fun getGeneralConfig(): GeneralConfig? = pluginConfigs.singleIsInstanceOrNull() /** * @param withSelf if true, include this config as the first element of the sequence or start with parent config otherwise @@ -122,15 +128,17 @@ data class TestConfig( * @return an update this [TestConfig] */ fun processInPlace(createPluginConfigList: (TestConfig) -> List): TestConfig { - // need to process parent first - this.parentConfig?.processInPlace(createPluginConfigList) // discover plugins from the test configuration - createPluginConfigList(this).forEach { - logTrace("Discovered new pluginConfig: $it") - this.pluginConfigs.merge(it) + createPluginConfigList(this).forEach { pluginConfig -> + logTrace("Discovered new pluginConfig: $pluginConfig") + require(this.pluginConfigs.none { it.type == pluginConfig.type }) { + "Found duplicate for $pluginConfig" + } + this.pluginConfigs.add(pluginConfig) } // merge configurations with parents - this.mergeConfigWithParent() + mergeConfigWithParent() + overrideConfig() return this } @@ -161,27 +169,28 @@ data class TestConfig( * * @return all plugin configs without general config */ - fun pluginConfigsWithoutGeneralConfig() = pluginConfigs.filterNot { it is GeneralConfig } + private fun pluginConfigsWithoutGeneralConfig() = pluginConfigs.filterNot { it is GeneralConfig } /** * Merge parent list of plugins with the current list * * @return merged test config */ - fun mergeConfigWithParent(): TestConfig { - logDebug("Merging configs (with parental configs from higher directory level) for ${this.location}") + private fun mergeConfigWithParent(): TestConfig { + logDebug("Merging configs (with parental configs from higher directory level) for ${this.location}") - if (parentConfig != null) { + parentConfig?.let { logTrace("Using parental config ${parentConfig.location} to merge it with child config: ${this.location}") - // return from the function if we stay at the root element of the plugin tree - val parentalPlugins = parentConfig.pluginConfigs - parentalPlugins.forEach { parentalPluginConfig -> - this.pluginConfigs.merge(parentalPluginConfig) - } + this.pluginConfigs.mergeWith(parentConfig.pluginConfigs) } return this } + private fun overrideConfig() { + logDebug("Overriding configs for $location") + pluginConfigs.overrideBy(overridesPluginConfigs) + } + /** * Method, which validates all plugin configs and set default values, if possible */ @@ -192,23 +201,6 @@ data class TestConfig( logDebug("Validated plugin configuration for [$location] " + "(${pluginConfigs.map { it.type }.filterNot { it == TestConfigSections.GENERAL }})") } - - private fun MutableList.merge(parentalPluginConfig: PluginConfig) { - val childConfigs = this.filter { it.type == parentalPluginConfig.type } - if (childConfigs.isEmpty()) { - // if we haven't found a plugin from parent in a current list of plugins - we will simply copy it - this.add(parentalPluginConfig) - } else { - require(childConfigs.size == 1) { - "Duplicate config with type ${parentalPluginConfig.type} in $this" - } - val childConfig = childConfigs.single() - // else, we will merge plugin with a corresponding plugin from a parent config - // we expect that there is only one plugin of such type, otherwise we will throw an exception - logTrace("Merging process of ${parentalPluginConfig.type} from $parentalPluginConfig into $childConfig") - this[this.indexOf(childConfig)] = childConfig.mergeWith(parentalPluginConfig) - } - } } /** @@ -235,3 +227,8 @@ fun Path.isSaveTomlConfig() = name == "save.toml" * @return a file (save.toml) in current directory */ fun Path.resolveSaveTomlConfig() = this / "save.toml" + +/** + * @return a file (save-overrides.toml) in current directory + */ +fun Path.resolveSaveOverridesTomlConfig() = this / "save-overrides.toml" 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 233945dfe..83c22e45b 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,6 +1,5 @@ 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 @@ -12,6 +11,7 @@ import com.saveourtool.save.core.result.Ignored import com.saveourtool.save.core.result.TestResult import com.saveourtool.save.core.utils.PathSerializer import com.saveourtool.save.core.utils.ProcessBuilder +import com.saveourtool.save.core.utils.singleIsInstanceOrNull import okio.FileSystem import okio.Path @@ -44,17 +44,15 @@ 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(evaluatedToolConfig: EvaluatedToolConfig): Sequence { + fun execute(): Sequence { clean() val testFilesList = discoverTestFiles(testConfig.directory).toList() val excludedTests = testConfig .pluginConfigs - .filterIsInstance() - .singleOrNull() + .singleIsInstanceOrNull() ?.excludedTests if (!excludedTests.isNullOrEmpty()) { @@ -71,7 +69,7 @@ abstract class Plugin( val excludedTestResults = excludedTestFiles.map { TestResult(it, Ignored("Excluded by configuration")) } - handleFiles(evaluatedToolConfig, actualTestFiles.asSequence()) + excludedTestResults + handleFiles(actualTestFiles.asSequence()) + excludedTestResults } else { emptySequence() } @@ -80,11 +78,10 @@ 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(evaluatedToolConfig: EvaluatedToolConfig, files: Sequence): Sequence + abstract fun handleFiles(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 0fa865712..08bb43e24 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 @@ -8,6 +8,8 @@ package com.saveourtool.save.core.plugin import com.saveourtool.save.core.config.TestConfigSections import com.saveourtool.save.core.utils.RegexSerializer +import com.saveourtool.save.core.utils.requireNotNull +import com.saveourtool.save.core.utils.requirePositive import okio.Path import okio.Path.Companion.toPath @@ -17,7 +19,7 @@ import kotlinx.serialization.Transient import kotlinx.serialization.UseSerializers /** - * Core interface for plugin configuration (like warnPlugin/fixPluin/e.t.c) + * Core interface for plugin configuration (like warnPlugin/fixPlugin/e.t.c) */ interface PluginConfig { /** @@ -61,6 +63,8 @@ interface PluginConfig { * 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 + * @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) * @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 @@ -75,6 +79,8 @@ interface PluginConfig { @Serializable data class GeneralConfig( val execCmd: String? = null, + val batchSize: Long? = null, + val batchSeparator: String? = null, val tags: List? = null, val description: String? = null, val suiteName: String? = null, @@ -104,6 +110,8 @@ data class GeneralConfig( return GeneralConfig( this.execCmd ?: other.execCmd, + this.batchSize ?: other.batchSize, + this.batchSeparator ?: other.batchSeparator, mergedTag, this.description ?: other.description, this.suiteName ?: other.suiteName, @@ -119,23 +127,16 @@ data class GeneralConfig( @Suppress("MagicNumber") override fun validateAndSetDefaults(): GeneralConfig { - requireNotNull(execCmd) { - errorMsgForRequireCheck("execCmd") - } - requireNotNull(tags) { - errorMsgForRequireCheck("tags") - } - requireNotNull(description) { - errorMsgForRequireCheck("description") - } - requireNotNull(suiteName) { - errorMsgForRequireCheck("suiteName") + batchSize?.also { + requirePositive("batchSize", it) } return GeneralConfig( - execCmd, - tags, - description, - suiteName, + requireNotNull("execCmd", execCmd), + batchSize ?: 1, + batchSeparator ?: ", ", + requireNotNull("tags", tags), + requireNotNull("description", description), + requireNotNull("suiteName", suiteName), language, excludedTests ?: emptyList(), expectedWarningsPattern ?: defaultExpectedWarningPattern, @@ -146,13 +147,6 @@ data class GeneralConfig( ).also { it.configLocation = this.configLocation } } - private fun errorMsgForRequireCheck(field: String) = - """ - Error: Couldn't find `$field` in [general] section of `$configLocation` config. - Current configuration: ${this.toString().substringAfter("(").substringBefore(")")} - Please provide it in this, or at least in one of the parent configs. - """.trimIndent() - companion object { /** * Default regex for expected warnings in test resources, e.g. diff --git a/save-common/src/commonMain/kotlin/com/saveourtool/save/core/utils/PluginConfigUtils.kt b/save-common/src/commonMain/kotlin/com/saveourtool/save/core/utils/PluginConfigUtils.kt new file mode 100644 index 000000000..0b556a27d --- /dev/null +++ b/save-common/src/commonMain/kotlin/com/saveourtool/save/core/utils/PluginConfigUtils.kt @@ -0,0 +1,72 @@ +/** + * This file contains util methods for [PluginConfig] + */ + +package com.saveourtool.save.core.utils + +import com.saveourtool.save.core.logging.logTrace +import com.saveourtool.save.core.plugin.PluginConfig + +/** + * @return original list of configuration for plugins after validation and merged with default values + */ +fun MutableList.validateAndSetDefaults() { + forEachIndexed { index, config -> + this[index] = config.validateAndSetDefaults() + } +} + +/** + * @param otherPluginConfigs list of configurations for plugins that are merged to current list + * @return original list of configuration for plugins merged with [otherPluginConfigs] + */ +fun MutableList.mergeWith(otherPluginConfigs: List) { + otherPluginConfigs.forEach { otherPluginConfig -> + this.mergeOrOverride(otherPluginConfig) + } +} + +/** + * @param otherPluginConfigs list of configurations for plugins that overrides current list + * @return original list of configuration for plugins overridden by [otherPluginConfigs] + */ +fun MutableList.overrideBy(otherPluginConfigs: List) { + otherPluginConfigs.forEach { otherPluginConfig -> + this.mergeOrOverride(otherPluginConfig, merge = false) + } +} + +/** + * @return a single [PluginConfig] with type [P] from current list + */ +inline fun List.singleIsInstance(): P = requireNotNull(this.singleIsInstanceOrNull()) { + "Not found an element with type ${P::class}" +} + +/** + * @return a single [PluginConfig] with type [P] from current list or null + */ +inline fun List.singleIsInstanceOrNull(): P? = this.filterIsInstance

().singleOrNull() + +private fun MutableList.mergeOrOverride(otherPluginConfig: PluginConfig, merge: Boolean = true) { + val childConfigsWithIndex = this.withIndex().filter { (_, value) -> value.type == otherPluginConfig.type } + if (childConfigsWithIndex.isEmpty()) { + // if we haven't found a plugin from parent in a current list of plugins - we will simply copy it + this.add(otherPluginConfig) + } else { + require(childConfigsWithIndex.size == 1) { + "Duplicate config with type ${otherPluginConfig.type} in $this" + } + val (childIndex, childConfig) = childConfigsWithIndex.single() + // else, we will merge plugin with a corresponding plugin from a parent config + // we expect that there is only one plugin of such type, otherwise we will throw an exception + + this[childIndex] = if (merge) { + logTrace("Merging process of ${otherPluginConfig.type} from $otherPluginConfig into $childConfig") + childConfig.mergeWith(otherPluginConfig) + } else { + logTrace("Overriding process of ${otherPluginConfig.type} from $otherPluginConfig into $childConfig") + otherPluginConfig.mergeWith(childConfig) + } + } +} diff --git a/save-common/src/commonMain/kotlin/com/saveourtool/save/core/utils/ValidationUtils.kt b/save-common/src/commonMain/kotlin/com/saveourtool/save/core/utils/ValidationUtils.kt new file mode 100644 index 000000000..ffb6c00fa --- /dev/null +++ b/save-common/src/commonMain/kotlin/com/saveourtool/save/core/utils/ValidationUtils.kt @@ -0,0 +1,40 @@ +/** + * This file contains utils methods to validate PluginConfig + */ + +package com.saveourtool.save.core.utils + +import com.saveourtool.save.core.plugin.PluginConfig + +/** + * Validate [value] that [field] is not null + * + * @param field + * @param value + * @return [value] as not null + */ +fun T.requireNotNull(field: String, value: R?) = requireNotNull(value) { + """ + Error: Couldn't find `$field` in [${type.name.lowercase()}] section of `$configLocation` config. + Current configuration: ${this.currentConfiguration()} + Please provide it in this, or at least in one of the parent configs. + """.trimIndent() +} + +/** + * Validate [value] that [field] positive + * + * @param field + * @param value + * @return nothing + */ +fun T.requirePositive(field: String, value: Long) = require(value >= 0) { + """ + [Configuration Error]: `$field` in [${type.name.lowercase()}] section of `$configLocation` config should be positive! + Current configuration: ${this.currentConfiguration()} + """.trimIndent() +} + +private fun T.currentConfiguration() = toString() + .substringAfter("(") + .substringBefore(")") diff --git a/save-common/src/commonNonJsTest/kotlin/com/saveourtool/save/core/files/FileUtilsTest.kt b/save-common/src/commonNonJsTest/kotlin/com/saveourtool/save/core/files/FileUtilsTest.kt index e8a4765ba..98e8f0fae 100644 --- a/save-common/src/commonNonJsTest/kotlin/com/saveourtool/save/core/files/FileUtilsTest.kt +++ b/save-common/src/commonNonJsTest/kotlin/com/saveourtool/save/core/files/FileUtilsTest.kt @@ -10,7 +10,6 @@ import kotlin.test.assertEquals import kotlin.test.assertTrue class FileUtilsTest { - private val fs = FileSystem.SYSTEM private lateinit var tmpDir: Path @BeforeTest 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 f59ce8ea6..fd585574c 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,12 +1,12 @@ 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 import com.saveourtool.save.core.config.SaveProperties import com.saveourtool.save.core.config.TestConfig import com.saveourtool.save.core.config.isSaveTomlConfig +import com.saveourtool.save.core.config.resolveSaveOverridesTomlConfig import com.saveourtool.save.core.config.resolveSaveTomlConfig import com.saveourtool.save.core.files.ConfigDetector import com.saveourtool.save.core.files.StdStreamsSink @@ -25,7 +25,9 @@ import com.saveourtool.save.core.result.Ignored import com.saveourtool.save.core.result.Pass import com.saveourtool.save.core.result.TestResult import com.saveourtool.save.core.utils.buildActivePlugins +import com.saveourtool.save.core.utils.createPluginConfigListFromToml import com.saveourtool.save.core.utils.processInPlace +import com.saveourtool.save.core.utils.processWithParentsInPlace import com.saveourtool.save.plugin.warn.WarnPluginConfig import com.saveourtool.save.plugins.fix.FixPlugin import com.saveourtool.save.plugins.fix.FixPluginConfig @@ -74,16 +76,20 @@ 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, - ) + val saveOverridesPath = testRootPath.resolveSaveOverridesTomlConfig() + val pluginConfigOverrides = if (fs.exists(saveOverridesPath)) { + createPluginConfigListFromToml(saveOverridesPath, fs) + } else { + emptyList() + } // get all toml configs in file system - val testConfigs = ConfigDetector(fs) + val testConfigs = ConfigDetector(fs, pluginConfigOverrides) .configFromFile(rootTestConfigPath) + .also { testConfig -> + // need to process all parents (if there is a parent) + testConfig.parentConfig?.processWithParentsInPlace() + } .getAllTestConfigsForFiles(requestedConfigs) var atLeastOneExecutionProvided = false testConfigs.forEach { testConfig -> @@ -106,7 +112,7 @@ class Save( ?.forEach { atLeastOneExecutionProvided = true // execute created plugins - executePlugin(evaluatedToolConfig, it, reporter) + executePlugin(it, reporter) } ?.also { reporter.onSuiteEnd(testConfig.getGeneralConfig()?.suiteName!!) @@ -156,7 +162,6 @@ class Save( } private fun executePlugin( - evaluatedToolConfig: EvaluatedToolConfig, plugin: Plugin, reporter: Reporter ) { @@ -164,7 +169,7 @@ class Save( logDebug("=> Executing plugin: ${plugin::class.simpleName} for [${plugin.testConfig.location}]") reporter.onPluginExecutionStart(plugin) try { - plugin.execute(evaluatedToolConfig) + plugin.execute() .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/commonNonJsMain/kotlin/com/saveourtool/save/core/files/ConfigDetector.kt b/save-core/src/commonNonJsMain/kotlin/com/saveourtool/save/core/files/ConfigDetector.kt index bb3d119c0..55d21e3a4 100644 --- a/save-core/src/commonNonJsMain/kotlin/com/saveourtool/save/core/files/ConfigDetector.kt +++ b/save-core/src/commonNonJsMain/kotlin/com/saveourtool/save/core/files/ConfigDetector.kt @@ -5,6 +5,7 @@ import com.saveourtool.save.core.config.isSaveTomlConfig import com.saveourtool.save.core.logging.logDebug import com.saveourtool.save.core.logging.logError import com.saveourtool.save.core.logging.logTrace +import com.saveourtool.save.core.plugin.PluginConfig import okio.FileSystem import okio.Path @@ -12,9 +13,12 @@ import okio.Path /** * A class that is capable of discovering config files hierarchy. */ -class ConfigDetector(private val fs: FileSystem) { +class ConfigDetector( + private val fs: FileSystem, + private val overridesPluginConfigs: List, +) { /** - * Try to create SAVE config file from [file]. + * Try to create SAVE config file from [testConfig]. * * @param testConfig - testing configuration (save.toml) from which SAVE config file should be built * @return [TestConfig] or null if no suitable config file has been found. @@ -61,6 +65,7 @@ class ConfigDetector(private val fs: FileSystem) { TestConfig( path, parentConfig, + overridesPluginConfigs = overridesPluginConfigs, fs = fs, ) ) @@ -111,6 +116,7 @@ class ConfigDetector(private val fs: FileSystem) { return TestConfig( file, parentConfig, + overridesPluginConfigs = overridesPluginConfigs, fs = fs, ) } diff --git a/save-core/src/commonNonJsMain/kotlin/com/saveourtool/save/core/utils/TestConfigUtils.kt b/save-core/src/commonNonJsMain/kotlin/com/saveourtool/save/core/utils/TestConfigUtils.kt index 633a63abe..b60ee9d8c 100644 --- a/save-core/src/commonNonJsMain/kotlin/com/saveourtool/save/core/utils/TestConfigUtils.kt +++ b/save-core/src/commonNonJsMain/kotlin/com/saveourtool/save/core/utils/TestConfigUtils.kt @@ -20,6 +20,16 @@ fun TestConfig.processInPlace() = processInPlace { createPluginConfigListFromToml(it.location, fs) } +/** + * Process current and all parents of [this] config, reading individual plugin configurations from TOML file. + * + * @return [this] config with all descendants being evaluated (`pluginConfigs` are filled with data and merged with parents) + */ +fun TestConfig.processWithParentsInPlace(): TestConfig { + parentConfig?.processWithParentsInPlace() + return processInPlace() +} + /** * Creates a list of plugins according to [this] config, choosing plugin implementation from the list of available ones. * diff --git a/save-core/src/commonNonJsTest/kotlin/com/saveourtool/save/core/ConfigDetectorRegressionTest.kt b/save-core/src/commonNonJsTest/kotlin/com/saveourtool/save/core/ConfigDetectorRegressionTest.kt index 43d7206b2..1be5d9f4e 100644 --- a/save-core/src/commonNonJsTest/kotlin/com/saveourtool/save/core/ConfigDetectorRegressionTest.kt +++ b/save-core/src/commonNonJsTest/kotlin/com/saveourtool/save/core/ConfigDetectorRegressionTest.kt @@ -1,16 +1,14 @@ package com.saveourtool.save.core import com.saveourtool.save.core.files.ConfigDetector +import com.saveourtool.save.core.files.fs -import okio.FileSystem import okio.Path.Companion.toPath import kotlin.test.Test import kotlin.test.assertEquals class ConfigDetectorRegressionTest { - private val fs: FileSystem = FileSystem.SYSTEM - @Test fun `config detector regression test on directories`() { val baseDir = "../examples/discovery-test" @@ -20,14 +18,14 @@ class ConfigDetectorRegressionTest { "$baseDir/highlevel/suite2/inner/save.toml" ) - val actual1 = ConfigDetector(fs) + val actual1 = ConfigDetector(fs, emptyList()) .configFromFile(baseDir.toPath()) .getAllTestConfigs() .map { it.location.toString() } assertEquals(expected, actual1) - val actual2 = ConfigDetector(fs) + val actual2 = ConfigDetector(fs, emptyList()) .configFromFile("$baseDir/save.toml".toPath()) .getAllTestConfigs() .map { it.location.toString() } diff --git a/save-core/src/commonNonJsTest/kotlin/com/saveourtool/save/core/ConfigDetectorTest.kt b/save-core/src/commonNonJsTest/kotlin/com/saveourtool/save/core/ConfigDetectorTest.kt index 0e975e1d7..7290efc03 100644 --- a/save-core/src/commonNonJsTest/kotlin/com/saveourtool/save/core/ConfigDetectorTest.kt +++ b/save-core/src/commonNonJsTest/kotlin/com/saveourtool/save/core/ConfigDetectorTest.kt @@ -2,10 +2,9 @@ package com.saveourtool.save.core import com.saveourtool.save.core.files.ConfigDetector import com.saveourtool.save.core.files.createFile +import com.saveourtool.save.core.files.fs import com.saveourtool.save.createTempDir -import okio.FileSystem - import kotlin.test.AfterTest import kotlin.test.Test import kotlin.test.assertEquals @@ -14,9 +13,8 @@ import kotlin.test.assertNotNull import kotlin.test.assertTrue class ConfigDetectorTest { - private val fs = FileSystem.SYSTEM private val tmpDir = fs.createTempDir(ConfigDetectorTest::class.simpleName!!) - private val configDetector = ConfigDetector(fs) + private val configDetector = ConfigDetector(fs, emptyList()) @Test fun `should detect single file`() { diff --git a/save-core/src/commonNonJsTest/kotlin/com/saveourtool/save/core/MergeAndOverrideConfigsTest.kt b/save-core/src/commonNonJsTest/kotlin/com/saveourtool/save/core/MergeAndOverrideConfigsTest.kt new file mode 100644 index 000000000..a79a7703a --- /dev/null +++ b/save-core/src/commonNonJsTest/kotlin/com/saveourtool/save/core/MergeAndOverrideConfigsTest.kt @@ -0,0 +1,514 @@ +@file:Suppress( + "FILE_IS_TOO_LONG", + "TOO_LONG_FUNCTION", +) + +package com.saveourtool.save.core + +import com.saveourtool.save.core.config.TestConfig +import com.saveourtool.save.core.config.resolveSaveOverridesTomlConfig +import com.saveourtool.save.core.config.resolveSaveTomlConfig +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.plugin.PluginConfig +import com.saveourtool.save.core.utils.createPluginConfigListFromToml +import com.saveourtool.save.core.utils.mergeWith +import com.saveourtool.save.core.utils.overrideBy +import com.saveourtool.save.core.utils.processWithParentsInPlace +import com.saveourtool.save.core.utils.singleIsInstance +import com.saveourtool.save.createTempDir +import com.saveourtool.save.plugin.warn.WarnPluginConfig +import com.saveourtool.save.plugins.fix.FixPluginConfig + +import okio.Path.Companion.toPath + +import kotlin.test.Test +import kotlin.test.assertEquals + +class MergeAndOverrideConfigsTest { + private val extraFlagsPattern1 = Regex("// RUN: (.*)") + private val extraFlagsPattern2 = Regex("## RUN: (.*)") + private val generalConfig1 = GeneralConfig( + execCmd = "execCmd1", + batchSize = 1, + batchSeparator = ", ", + tags = listOf("Tag11", "Tag12"), + description = "Description1", + suiteName = "suiteName1", + language = "Kotlin", + excludedTests = listOf("excludedTests: test1"), + runConfigPattern = extraFlagsPattern2 + ) + private val generalConfig2 = GeneralConfig( + execCmd = "execCmd2", + batchSize = 2, + batchSeparator = "; ", + tags = listOf("Tag21"), + description = "Description2", + suiteName = "suiteName2", + language = "Kotlin", + excludedTests = listOf("excludedTests: test3"), + runConfigPattern = extraFlagsPattern1 + ) + private val generalConfig3 = GeneralConfig( + execCmd = "execCmd3", + batchSize = 3, + batchSeparator = " ", + tags = listOf("Tag21", "Tag31", "Tag32"), + description = "Description2", + suiteName = "suiteName3", + language = "Kotlin", + excludedTests = listOf("excludedTests: test5", "includedTests: test6"), + runConfigPattern = extraFlagsPattern2 + ) + private val generalConfig4 = GeneralConfig( + execCmd = null, + batchSize = null, + batchSeparator = null, + tags = listOf("Tag11", "Tag21"), + description = "Description2", + suiteName = "suiteName4", + language = "Kotlin", + excludedTests = listOf("excludedTests: test7"), + runConfigPattern = extraFlagsPattern2 + ) + private val warningsOutputPattern1 = Regex(".*") + private val warningsOutputPattern2 = Regex("\\w+ - (\\d+)/(\\d+) - (.*)$") + private val warnConfig1 = WarnPluginConfig( + execFlags = "warnExecFlags1", + actualWarningsPattern = warningsOutputPattern2, + warningTextHasLine = false, + warningTextHasColumn = false, + lineCaptureGroup = 1, + columnCaptureGroup = 1, + messageCaptureGroup = 1, + messageCaptureGroupMiddle = 1, + messageCaptureGroupEnd = 1, + fileNameCaptureGroupOut = 1, + lineCaptureGroupOut = 1, + columnCaptureGroupOut = 1, + messageCaptureGroupOut = 1, + exactWarningsMatch = false, + testNameRegex = null + ) + private val warnConfig2 = WarnPluginConfig( + execFlags = "warnExecFlags2", + actualWarningsPattern = warningsOutputPattern1, + warningTextHasLine = true, + warningTextHasColumn = true, + lineCaptureGroup = 2, + columnCaptureGroup = 2, + messageCaptureGroup = 2, + messageCaptureGroupMiddle = 1, + messageCaptureGroupEnd = 1, + fileNameCaptureGroupOut = 2, + lineCaptureGroupOut = 2, + columnCaptureGroupOut = 2, + messageCaptureGroupOut = 2, + exactWarningsMatch = true, + testNameRegex = null + ) + private val warnConfig3 = WarnPluginConfig( + execFlags = "warnExecFlags3", + actualWarningsPattern = warningsOutputPattern2, + warningTextHasColumn = false, + lineCaptureGroup = 3, + columnCaptureGroup = 3, + messageCaptureGroup = 3, + fileNameCaptureGroupOut = 3, + lineCaptureGroupOut = 3, + columnCaptureGroupOut = 3, + messageCaptureGroupOut = 3 + ) + private val warnConfig4 = WarnPluginConfig( + execFlags = "warnExecFlags4", + actualWarningsPattern = warningsOutputPattern2, + lineCaptureGroup = 4, + columnCaptureGroup = 4, + messageCaptureGroup = 4, + fileNameCaptureGroupOut = 4, + lineCaptureGroupOut = 4, + columnCaptureGroupOut = 4, + messageCaptureGroupOut = 4 + ) + private val fixConfig1 = FixPluginConfig(execFlags = "fixExecFlags1", resourceNameTestSuffix = "Suffix") + private val fixConfig2 = FixPluginConfig(execFlags = "fixExecFlags2") + private val fixConfig3 = FixPluginConfig(execFlags = "fixExecFlags3", resourceNameTestSuffix = null) + private val fixConfig4 = FixPluginConfig(execFlags = "fixExecFlags4") + + @Test + fun `merge and override general configs`() { + val config1 = listOf(generalConfig1) + + val config2ForMerge: MutableList = mutableListOf(generalConfig2) + config2ForMerge.mergeWith(config1) + assertEquals(1, config2ForMerge.size) + assertEquals( + GeneralConfig( + execCmd = "execCmd2", + batchSize = 2, + batchSeparator = "; ", + tags = listOf("Tag11", "Tag12", "Tag21"), + description = "Description2", + suiteName = "suiteName2", + language = "Kotlin", + excludedTests = listOf("excludedTests: test3"), + runConfigPattern = extraFlagsPattern1 + ), + config2ForMerge.singleIsInstance() + ) + + val config2ForOverride: MutableList = mutableListOf(generalConfig2) + config2ForOverride.overrideBy(config1) + assertEquals(1, config2ForOverride.size) + assertEquals( + GeneralConfig( + execCmd = "execCmd1", + batchSize = 1, + batchSeparator = ", ", + tags = listOf("Tag21", "Tag11", "Tag12"), + description = "Description1", + suiteName = "suiteName1", + language = "Kotlin", + excludedTests = listOf("excludedTests: test1"), + runConfigPattern = extraFlagsPattern2 + ), + config2ForOverride.singleIsInstance() + ) + } + + @Test + fun `merge and override two incomplete configs`() { + val config1 = listOf(generalConfig1, warnConfig1) + + val config2ForMerge: MutableList = mutableListOf(generalConfig2) + config2ForMerge.mergeWith(config1) + assertEquals(2, config2ForMerge.size) + assertEquals( + GeneralConfig( + execCmd = "execCmd2", + batchSize = 2, + batchSeparator = "; ", + tags = listOf("Tag11", "Tag12", "Tag21"), + description = "Description2", + suiteName = "suiteName2", + language = "Kotlin", + excludedTests = listOf("excludedTests: test3"), + runConfigPattern = extraFlagsPattern1 + ), + config2ForMerge.singleIsInstance() + ) + assertEquals(warnConfig1, config2ForMerge.singleIsInstance()) + + val config2ForOverride: MutableList = mutableListOf(generalConfig2) + config2ForOverride.overrideBy(config1) + assertEquals(2, config2ForOverride.size) + assertEquals( + GeneralConfig( + execCmd = "execCmd1", + batchSize = 1, + batchSeparator = ", ", + tags = listOf("Tag21", "Tag11", "Tag12"), + description = "Description1", + suiteName = "suiteName1", + language = "Kotlin", + excludedTests = listOf("excludedTests: test1"), + runConfigPattern = extraFlagsPattern2 + ), + config2ForOverride.singleIsInstance() + ) + assertEquals(warnConfig1, config2ForOverride.singleIsInstance()) + } + + @Test + fun `merge and override two incomplete configs 2`() { + val config1: List = emptyList() + + val config2ForMerge = mutableListOf(generalConfig2, warnConfig1) + config2ForMerge.mergeWith(config1) + assertEquals(2, config2ForMerge.size) + assertEquals(generalConfig2, config2ForMerge.singleIsInstance()) + assertEquals(warnConfig1, config2ForMerge.singleIsInstance()) + + val config2ForOverride = mutableListOf(generalConfig2, warnConfig1) + config2ForOverride.overrideBy(config1) + assertEquals(2, config2ForOverride.size) + assertEquals(generalConfig2, config2ForOverride.singleIsInstance()) + assertEquals(warnConfig1, config2ForOverride.singleIsInstance()) + } + + @Test + fun `merge and override two configs with different fields`() { + val config1 = listOf(generalConfig1, warnConfig2, fixConfig1) + + val config2ForMerge = mutableListOf(generalConfig2, warnConfig3, fixConfig2) + config2ForMerge.mergeWith(config1) + assertEquals(3, config2ForMerge.size) + assertEquals( + GeneralConfig( + execCmd = "execCmd2", + batchSize = 2, + batchSeparator = "; ", + tags = listOf("Tag11", "Tag12", "Tag21"), + description = "Description2", + suiteName = "suiteName2", + language = "Kotlin", + excludedTests = listOf("excludedTests: test3"), + runConfigPattern = extraFlagsPattern1 + ), + config2ForMerge.singleIsInstance() + ) + assertEquals( + WarnPluginConfig( + execFlags = "warnExecFlags3", + actualWarningsPattern = warningsOutputPattern2, + warningTextHasLine = true, + warningTextHasColumn = false, + lineCaptureGroup = 3, + columnCaptureGroup = 3, + messageCaptureGroup = 3, + messageCaptureGroupMiddle = 1, + messageCaptureGroupEnd = 1, + fileNameCaptureGroupOut = 3, + lineCaptureGroupOut = 3, + columnCaptureGroupOut = 3, + messageCaptureGroupOut = 3, + exactWarningsMatch = true, + testNameRegex = null + ), + config2ForMerge.singleIsInstance() + ) + assertEquals( + FixPluginConfig("fixExecFlags2", "Suffix"), + config2ForMerge.singleIsInstance()) + + val config2ForOverride = mutableListOf(generalConfig2, warnConfig3, fixConfig2) + config2ForOverride.overrideBy(config1) + assertEquals(3, config2ForOverride.size) + assertEquals( + GeneralConfig( + execCmd = "execCmd1", + batchSize = 1, + batchSeparator = ", ", + tags = listOf("Tag21", "Tag11", "Tag12"), + description = "Description1", + suiteName = "suiteName1", + language = "Kotlin", + excludedTests = listOf("excludedTests: test1"), + runConfigPattern = extraFlagsPattern2, + ), + config2ForOverride.singleIsInstance() + ) + assertEquals( + WarnPluginConfig( + execFlags = "warnExecFlags2", + actualWarningsPattern = warningsOutputPattern1, + warningTextHasLine = true, + warningTextHasColumn = true, + lineCaptureGroup = 2, + columnCaptureGroup = 2, + messageCaptureGroup = 2, + messageCaptureGroupMiddle = 1, + messageCaptureGroupEnd = 1, + fileNameCaptureGroupOut = 2, + lineCaptureGroupOut = 2, + columnCaptureGroupOut = 2, + messageCaptureGroupOut = 2, + exactWarningsMatch = true, + testNameRegex = null, + ), + config2ForOverride.singleIsInstance() + ) + assertEquals( + FixPluginConfig( + execFlags = "fixExecFlags1", + resourceNameTestSuffix = "Suffix", + ), + config2ForOverride.singleIsInstance()) + } + + @Test + fun `merge configs with many parents`() { + val config1 = mutableListOf(generalConfig1, warnConfig1, fixConfig1) + val config2 = mutableListOf(generalConfig2, warnConfig2, fixConfig2) + val config3 = mutableListOf(generalConfig3, warnConfig3, fixConfig3) + val config4 = mutableListOf(generalConfig4, warnConfig4, fixConfig4) + + config1.mergeWith(emptyList()) + config2.mergeWith(config1) + config3.mergeWith(config2) + config4.mergeWith(config3) + + assertEquals(3, config4.size) + val expectedGeneralConfig = + GeneralConfig( + execCmd = "execCmd3", + batchSize = 3, + batchSeparator = " ", + tags = listOf("Tag11", "Tag12", "Tag21", "Tag31", "Tag32"), + description = "Description2", + suiteName = "suiteName4", + language = "Kotlin", + excludedTests = listOf("excludedTests: test7"), + runConfigPattern = extraFlagsPattern2 + ) + val expectedWarnConfig = WarnPluginConfig( + execFlags = "warnExecFlags4", + actualWarningsPattern = warningsOutputPattern2, + warningTextHasLine = true, + warningTextHasColumn = false, + lineCaptureGroup = 4, + columnCaptureGroup = 4, + messageCaptureGroup = 4, + messageCaptureGroupMiddle = 1, + messageCaptureGroupEnd = 1, + fileNameCaptureGroupOut = 4, + lineCaptureGroupOut = 4, + columnCaptureGroupOut = 4, + messageCaptureGroupOut = 4, + exactWarningsMatch = true, + testNameRegex = null + ) + val expectedFixConfig = FixPluginConfig(execFlags = "fixExecFlags4", resourceNameTestSuffix = "Suffix") + + val actualGeneralConfig: GeneralConfig = config4.singleIsInstance() + val actualWarnConfig: WarnPluginConfig = config4.singleIsInstance() + val actualFixConfig: FixPluginConfig = config4.singleIsInstance() + + assertEquals(expectedGeneralConfig, actualGeneralConfig) + assertEquals(expectedWarnConfig, actualWarnConfig) + assertEquals(expectedFixConfig, actualFixConfig) + } + + @Test + fun `merge real toml configs with empty execFlag in child`() { + val toml1 = "src/commonNonJsTest/resources/merge_configs/save.toml" + val configList1 = createPluginConfigListFromToml(toml1.toPath(), fs) + + val parentGeneralConfig: GeneralConfig = configList1.singleIsInstance() + val parentWarnConfig: WarnPluginConfig = configList1.singleIsInstance() + assertEquals("echo hello world", parentGeneralConfig.execCmd) + assertEquals(listOf("Tag"), parentGeneralConfig.tags) + assertEquals(null, parentWarnConfig.execFlags) + + val toml2 = "src/commonNonJsTest/resources/merge_configs/inner/save.toml" + val configList2 = createPluginConfigListFromToml(toml2.toPath(), fs) + + val childGeneralConfig: GeneralConfig = configList2.singleIsInstance() + val childWarnConfig: WarnPluginConfig = configList2.singleIsInstance() + + assertEquals(listOf(""), childGeneralConfig.tags) + assertEquals(null, childWarnConfig.execFlags) + + val testConfig1 = TestConfig(toml1.toPath(), null, mutableListOf(), emptyList(), fs) + val testConfig2 = TestConfig(toml2.toPath(), testConfig1, mutableListOf(), emptyList(), fs) + + testConfig1.processInPlace { configList1 } + testConfig2.processInPlace { configList2 } + testConfig2.validateAndSetDefaults() + + val mergedGeneralConfig: GeneralConfig = testConfig2.pluginConfigs.singleIsInstance() + val mergedWarnConfig: WarnPluginConfig = testConfig2.pluginConfigs.singleIsInstance() + + assertEquals(listOf("Tag", ""), mergedGeneralConfig.tags) + // execFlags should be empty, not `"null"` + assertEquals("", mergedWarnConfig.execFlags) + } + + @Test + fun `override real toml configs`() { + val saveToml = "src/commonNonJsTest/resources/override_configs".toPath().resolveSaveTomlConfig() + val configs = createPluginConfigListFromToml(saveToml, fs) + + val saveOverridesToml = "src/commonNonJsTest/resources/override_configs".toPath().resolveSaveOverridesTomlConfig() + val overrides = createPluginConfigListFromToml(saveOverridesToml, fs) + + val testConfig = TestConfig( + location = saveToml, + parentConfig = null, + pluginConfigs = mutableListOf(), + overridesPluginConfigs = overrides, + fs = fs + ) + testConfig.processInPlace { + configs + } + val result = testConfig.pluginConfigs + assertEquals(3, result.size) + + assertEquals( + GeneralConfig( + execCmd = "java -jar tool.jar", + tags = listOf("Tag"), + description = "My description", + suiteName = "DocsCheck", + ), + result.singleIsInstance() + ) + assertEquals( + WarnPluginConfig( + execFlags = "--warn", + ), + result.singleIsInstance() + ) + assertEquals( + FixPluginConfig( + execFlags = "--fix", + ), + result.singleIsInstance()) + } + + @Test + fun `load save toml from middle hierarchy`() { + val tmpDir = fs.createTempDir() + val generalConfig1 = GeneralConfig( + execCmd = "execCmd" + ) + val testConfig1 = TestConfig( + location = tmpDir.resolveSaveTomlConfig() + .also { fs.createFile(it) }, + parentConfig = null, + pluginConfigs = mutableListOf( + generalConfig1 + ), + overridesPluginConfigs = emptyList(), + fs = fs + ) + val testConfig2 = TestConfig( + location = tmpDir.resolve("sub-folder") + .also { fs.createDirectories(it) } + .resolveSaveTomlConfig() + .also { fs.createFile(it) }, + parentConfig = testConfig1, + pluginConfigs = mutableListOf(), + overridesPluginConfigs = emptyList(), + fs = fs + ) + val testConfig3 = TestConfig( + location = tmpDir.resolve("sub-folder").resolve("sub-sub-folder") + .also { fs.createDirectories(it) } + .resolveSaveTomlConfig() + .also { fs.createFile(it) }, + parentConfig = testConfig2, + pluginConfigs = mutableListOf(), + overridesPluginConfigs = emptyList(), + fs = fs + ) + val testConfig4 = TestConfig( + location = tmpDir.resolve("sub-folder").resolve("sub-sub-folder").resolve("sub-sub-sub-folder") + .also { fs.createDirectories(it) } + .resolveSaveTomlConfig() + .also { fs.createFile(it) }, + parentConfig = testConfig3, + pluginConfigs = mutableListOf(), + overridesPluginConfigs = emptyList(), + fs = fs + ) + + testConfig4.processWithParentsInPlace() + + assertEquals(generalConfig1, testConfig4.getGeneralConfig()) + fs.deleteRecursively(tmpDir) + } +} 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 deleted file mode 100644 index 4831bc0d5..000000000 --- a/save-core/src/commonNonJsTest/kotlin/com/saveourtool/save/core/MergeConfigsTest.kt +++ /dev/null @@ -1,222 +0,0 @@ -package com.saveourtool.save.core - -import com.saveourtool.save.core.config.TestConfig -import com.saveourtool.save.core.files.createFile -import com.saveourtool.save.core.files.myDeleteRecursively -import com.saveourtool.save.core.plugin.GeneralConfig -import com.saveourtool.save.core.utils.createPluginConfigListFromToml -import com.saveourtool.save.plugin.warn.WarnPluginConfig -import com.saveourtool.save.plugins.fix.FixPluginConfig - -import okio.FileSystem -import okio.Path.Companion.toPath - -import kotlin.test.AfterTest -import kotlin.test.Test -import kotlin.test.assertEquals - -internal val fs = FileSystem.SYSTEM -internal val tmpDir = (FileSystem.SYSTEM_TEMPORARY_DIRECTORY / MergeConfigsTest::class.simpleName!!) - -internal val toml1 = tmpDir / "save.toml" -internal val nestedDir1 = tmpDir / "nestedDir1" -internal val toml2 = nestedDir1 / "save.toml" -internal val nestedDir2 = tmpDir / "nestedDir1" / "nestedDir2" -internal val toml3 = nestedDir2 / "save.toml" -internal val toml4 = nestedDir2 / "nestedDir3" / "nestedDir4" / "save.toml" - -@Suppress( - "TOO_LONG_FUNCTION", - "LOCAL_VARIABLE_EARLY_DECLARATION", - "LONG_LINE", -) -class MergeConfigsTest { - private val extraFlagsPattern1 = Regex("// RUN: (.*)") - private val extraFlagsPattern2 = Regex("## RUN: (.*)") - private val generalConfig1 = GeneralConfig("", listOf("Tag11", "Tag12"), "Description1", "suiteName1", "Kotlin", listOf("excludedTests: test1"), runConfigPattern = extraFlagsPattern2) - private val generalConfig2 = GeneralConfig("", listOf("Tag21"), "Description2", "suiteName2", "Kotlin", listOf("excludedTests: test3"), runConfigPattern = extraFlagsPattern1) - private val generalConfig3 = GeneralConfig("", listOf("Tag21", "Tag31", "Tag32"), "Description2", "suiteName3", "Kotlin", listOf("excludedTests: test5", "includedTests: test6"), runConfigPattern = extraFlagsPattern2) - private val generalConfig4 = GeneralConfig("", listOf("Tag11", "Tag21"), "Description2", "suiteName4", "Kotlin", listOf("excludedTests: test7"), runConfigPattern = extraFlagsPattern2) - 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, false, null) - private val warnConfig2 = WarnPluginConfig("execCmd2", warningsOutputPattern1, - true, true, 2, 2, 2, 1, 1, 2, 2, 2, 2, true, null) - private val warnConfig3 = WarnPluginConfig("execCmd3", warningsOutputPattern2, - warningTextHasColumn = false, lineCaptureGroup = 3, columnCaptureGroup = 3, messageCaptureGroup = 3, - fileNameCaptureGroupOut = 3, lineCaptureGroupOut = 3, columnCaptureGroupOut = 3, messageCaptureGroupOut = 3) - private val warnConfig4 = WarnPluginConfig("execCmd4", warningsOutputPattern2, - lineCaptureGroup = 4, columnCaptureGroup = 4, messageCaptureGroup = 4, - fileNameCaptureGroupOut = 4, lineCaptureGroupOut = 4, columnCaptureGroupOut = 4, messageCaptureGroupOut = 4) - private val fixConfig1 = FixPluginConfig("fixCmd1", "Suffix") - private val fixConfig2 = FixPluginConfig("fixCmd2") - private val fixConfig3 = FixPluginConfig("fixCmd3", null) - private val fixConfig4 = FixPluginConfig("fixCmd4") - - @Test - fun `merge general configs`() { - createTomlFiles() - val config1 = TestConfig(toml1, null, mutableListOf(generalConfig1), fs) - val config2 = TestConfig(toml2, config1, mutableListOf(generalConfig2), fs) - - config2.mergeConfigWithParent() - - assertEquals(1, config2.pluginConfigs.size) - - val expectedGeneralConfig = - GeneralConfig("", listOf("Tag11", "Tag12", "Tag21"), "Description2", "suiteName2", "Kotlin", listOf("excludedTests: test3"), runConfigPattern = extraFlagsPattern1) - - val actualGeneralConfig = config2.pluginConfigs.filterIsInstance().first() - - assertEquals(expectedGeneralConfig, actualGeneralConfig) - } - - @Test - fun `merge two incomplete configs`() { - createTomlFiles() - val config1 = TestConfig(toml1, null, mutableListOf(generalConfig1, warnConfig1), fs) - val config2 = TestConfig(toml2, config1, mutableListOf(generalConfig2), fs) - - config2.mergeConfigWithParent() - - assertEquals(2, config2.pluginConfigs.size) - - val expectedGeneralConfig = - GeneralConfig("", listOf("Tag11", "Tag12", "Tag21"), "Description2", "suiteName2", "Kotlin", listOf("excludedTests: test3"), runConfigPattern = extraFlagsPattern1) - - val actualGeneralConfig = config2.pluginConfigs.filterIsInstance().first() - val actualWarnConfig = config2.pluginConfigs.filterIsInstance().first() - - assertEquals(expectedGeneralConfig, actualGeneralConfig) - assertEquals(warnConfig1, actualWarnConfig) - } - - @Test - fun `merge two incomplete configs 2`() { - createTomlFiles() - val config1 = TestConfig(toml1, null, mutableListOf(), fs) - val config2 = TestConfig(toml2, config1, mutableListOf(generalConfig2, warnConfig1), fs) - - config2.mergeConfigWithParent() - - assertEquals(2, config2.pluginConfigs.size) - - val actualGeneralConfig = config2.pluginConfigs.filterIsInstance().first() - val actualWarnConfig = config2.pluginConfigs.filterIsInstance().first() - - assertEquals(generalConfig2, actualGeneralConfig) - assertEquals(warnConfig1, actualWarnConfig) - } - - @Test - fun `merge two configs with different fields`() { - createTomlFiles() - val config1 = TestConfig(toml1, null, mutableListOf(generalConfig1, warnConfig2, fixConfig1), fs) - val config2 = TestConfig(toml2, config1, mutableListOf(generalConfig2, warnConfig3, fixConfig2), fs) - - config2.mergeConfigWithParent() - - assertEquals(3, config2.pluginConfigs.size) - - val expectedGeneralConfig = - GeneralConfig("", listOf("Tag11", "Tag12", "Tag21"), "Description2", "suiteName2", "Kotlin", listOf("excludedTests: test3"), runConfigPattern = extraFlagsPattern1) - val expectedWarnConfig = WarnPluginConfig("execCmd3", warningsOutputPattern2, - 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() - val actualFixConfig = config2.pluginConfigs.filterIsInstance().first() - - assertEquals(expectedGeneralConfig, actualGeneralConfig) - assertEquals(expectedWarnConfig, actualWarnConfig) - assertEquals(expectedFixConfig, actualFixConfig) - } - - @Test - fun `merge configs with many parents`() { - createTomlFiles() - val config1 = TestConfig(toml1, null, mutableListOf(generalConfig1, warnConfig1, fixConfig1), fs) - val config2 = TestConfig(toml2, config1, mutableListOf(generalConfig2, warnConfig2, fixConfig2), fs) - val config3 = TestConfig(toml3, config2, mutableListOf(generalConfig3, warnConfig3, fixConfig3), fs) - val config4 = TestConfig(toml4, config3, mutableListOf(generalConfig4, warnConfig4, fixConfig4), fs) - - config1.mergeConfigWithParent() - config2.mergeConfigWithParent() - config3.mergeConfigWithParent() - config4.mergeConfigWithParent() - - assertEquals(3, config4.pluginConfigs.size) - val expectedGeneralConfig = - GeneralConfig("", listOf("Tag11", "Tag12", "Tag21", "Tag31", "Tag32"), "Description2", "suiteName4", "Kotlin", listOf("excludedTests: test7"), runConfigPattern = extraFlagsPattern2) - val expectedWarnConfig = WarnPluginConfig("execCmd4", warningsOutputPattern2, - 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() - val actualFixConfig = config4.pluginConfigs.filterIsInstance().first() - - assertEquals(expectedGeneralConfig, actualGeneralConfig) - assertEquals(expectedWarnConfig, actualWarnConfig) - assertEquals(expectedFixConfig, actualFixConfig) - } - - @Test - fun `merge real toml configs with empty execFlag in child`() { - // stub, since tearDown should delete it anyway - createTomlFiles() - - val toml1 = "src/commonNonJsTest/resources/merge_configs/save.toml" - val configList1 = createPluginConfigListFromToml(toml1.toPath(), fs) - - val parentGeneralConfig = configList1.filterIsInstance().first() - val parentWarnConfig = configList1.filterIsInstance().first() - assertEquals("echo hello world", parentGeneralConfig.execCmd) - assertEquals(listOf("Tag"), parentGeneralConfig.tags) - assertEquals(null, parentWarnConfig.execFlags) - - val toml2 = "src/commonNonJsTest/resources/merge_configs/inner/save.toml" - val configList2 = createPluginConfigListFromToml(toml2.toPath(), fs) - - val childGeneralConfig = configList2.filterIsInstance().first() - val childWarnConfig = configList2.filterIsInstance().first() - - assertEquals(listOf(""), childGeneralConfig.tags) - assertEquals(null, childWarnConfig.execFlags) - - val testConfig1 = TestConfig(toml1.toPath(), null, configList1.toMutableList(), fs) - val testConfig2 = TestConfig(toml2.toPath(), testConfig1, configList2.toMutableList(), fs) - - val mergedTestConfig = testConfig2.mergeConfigWithParent() - testConfig2.validateAndSetDefaults() - - val mergedGeneralConfig = mergedTestConfig.pluginConfigs.filterIsInstance().first() - val mergedWarnConfig = mergedTestConfig.pluginConfigs.filterIsInstance().first() - - assertEquals(listOf("Tag", ""), mergedGeneralConfig.tags) - // execFlags should be empty, not `"null"` - assertEquals("", mergedWarnConfig.execFlags) - } - - @AfterTest - fun tearDown() { - fs.deleteRecursively(tmpDir) - } -} - -internal fun createTomlFiles() { - if (fs.exists(tmpDir)) { - fs.myDeleteRecursively(tmpDir) - } - fs.createDirectory(tmpDir) - fs.createFile(toml1) - fs.createDirectory(nestedDir1) - fs.createFile(toml2) - fs.createDirectory(nestedDir2) - fs.createFile(toml3) - fs.createDirectory(nestedDir2 / "nestedDir3") - fs.createDirectory(nestedDir2 / "nestedDir3" / "nestedDir4") - fs.createFile(toml4) -} diff --git a/save-core/src/commonNonJsTest/kotlin/com/saveourtool/save/core/ValidationTest.kt b/save-core/src/commonNonJsTest/kotlin/com/saveourtool/save/core/ValidationTest.kt index 0fdf3f15e..b70b830cd 100644 --- a/save-core/src/commonNonJsTest/kotlin/com/saveourtool/save/core/ValidationTest.kt +++ b/save-core/src/commonNonJsTest/kotlin/com/saveourtool/save/core/ValidationTest.kt @@ -1,44 +1,40 @@ package com.saveourtool.save.core -import com.saveourtool.save.core.config.TestConfig import com.saveourtool.save.core.plugin.GeneralConfig +import com.saveourtool.save.core.plugin.PluginConfig +import com.saveourtool.save.core.utils.singleIsInstance +import com.saveourtool.save.core.utils.validateAndSetDefaults import com.saveourtool.save.plugin.warn.WarnPluginConfig import com.saveourtool.save.plugins.fix.FixPluginConfig -import okio.FileSystem - -import kotlin.test.AfterTest +import okio.Path.Companion.toPath import kotlin.test.Test import kotlin.test.assertEquals -import kotlin.test.assertTrue +import kotlin.test.fail -@Suppress("LONG_LINE") class ValidationTest { - private val fs: FileSystem = FileSystem.SYSTEM - @Test fun `set defaults to general section`() { - createTomlFiles() val generalConfig = GeneralConfig("exeCmd", tags = listOf("Tag11", "Tag12"), description = "Description1", suiteName = "suiteName1") - val config = TestConfig(toml1, null, mutableListOf(generalConfig), fs) + val config: MutableList = mutableListOf(generalConfig) config.validateAndSetDefaults() - assertEquals(1, config.pluginConfigs.size) + assertEquals(1, config.size) - val actualGeneralConfig1 = config.pluginConfigs.filterIsInstance().first() + val actualGeneralConfig1: GeneralConfig = config.singleIsInstance() assertEquals(emptyList(), actualGeneralConfig1.excludedTests) + assertEquals(1, actualGeneralConfig1.batchSize) + assertEquals(", ", actualGeneralConfig1.batchSeparator) } @Test fun `invalid general section`() { - createTomlFiles() - val generalConfig = GeneralConfig() - val config = TestConfig(toml1, null, mutableListOf(generalConfig), fs) - generalConfig.configLocation = config.location - try { - config.validateAndSetDefaults() - } catch (ex: IllegalArgumentException) { + val generalConfig = GeneralConfig().apply { + configLocation = "./some-path".toPath() + } + + assertException(generalConfig) { ex -> assertEquals( """ Error: Couldn't find `execCmd` in [general] section of `${generalConfig.configLocation}` config. @@ -48,19 +44,29 @@ class ValidationTest { ex.message ) } + + val generalConfigWithInvalidBatchSize = generalConfig.copy(execCmd = "execCmd", batchSize = -1) + assertException(generalConfigWithInvalidBatchSize) { ex -> + assertEquals( + """ + [Configuration Error]: `batchSize` in [general] section of `${generalConfigWithInvalidBatchSize.configLocation}` config should be positive! + Current configuration: ${generalConfigWithInvalidBatchSize.toString().substringAfter("(").substringBefore(")")} + """.trimIndent(), + ex.message + ) + } } @Test fun `set defaults to warn section`() { - createTomlFiles() val warnConfig = WarnPluginConfig(execFlags = "execFlags", messageCaptureGroup = 4) - val config = TestConfig(toml1, null, mutableListOf(warnConfig), fs) + val config: MutableList = mutableListOf(warnConfig) config.validateAndSetDefaults() - assertEquals(1, config.pluginConfigs.size) + assertEquals(1, config.size) - val actualWarnConfig = config.pluginConfigs.filterIsInstance().first() + val actualWarnConfig: WarnPluginConfig = config.singleIsInstance() assertEquals(Regex("(.+):(\\d*):(\\d*): (.+)").toString(), actualWarnConfig.actualWarningsPattern.toString()) assertEquals(true, actualWarnConfig.warningTextHasLine) assertEquals(true, actualWarnConfig.warningTextHasColumn) @@ -79,15 +85,14 @@ class ValidationTest { // `warningTextHasLine` `warningTextHasColumn` @Test fun `validate warn section`() { - createTomlFiles() val warnConfig = WarnPluginConfig(execFlags = "execFlags", warningTextHasLine = true, warningTextHasColumn = false) - val config = TestConfig(toml1, null, mutableListOf(warnConfig), fs) + val config: MutableList = mutableListOf(warnConfig) config.validateAndSetDefaults() - assertEquals(1, config.pluginConfigs.size) + assertEquals(1, config.size) - val actualWarnConfig = config.pluginConfigs.filterIsInstance().first() + val actualWarnConfig: WarnPluginConfig = config.singleIsInstance() assertEquals(true, actualWarnConfig.warningTextHasLine) assertEquals(false, actualWarnConfig.warningTextHasColumn) assertEquals(1, actualWarnConfig.lineCaptureGroup) @@ -97,15 +102,14 @@ class ValidationTest { // Provided incorrect values `warningTextHasLine = false` but `lineCaptureGroup = 2`; validate it @Test fun `validate warn section 2`() { - createTomlFiles() val warnConfig = WarnPluginConfig(execFlags = "execFlags", warningTextHasLine = false, lineCaptureGroup = 1) - val config = TestConfig(toml1, null, mutableListOf(warnConfig), fs) + val config: MutableList = mutableListOf(warnConfig) config.validateAndSetDefaults() - assertEquals(1, config.pluginConfigs.size) + assertEquals(1, config.size) - val actualWarnConfig = config.pluginConfigs.filterIsInstance().first() + val actualWarnConfig: WarnPluginConfig = config.singleIsInstance() assertEquals(false, actualWarnConfig.warningTextHasLine) assertEquals(true, actualWarnConfig.warningTextHasColumn) assertEquals(null, actualWarnConfig.lineCaptureGroup) @@ -115,15 +119,14 @@ class ValidationTest { // `lineCaptureGroup` provided, but `warningTextHasLine` is absent; validate it @Test fun `validate warn section 3`() { - createTomlFiles() val warnConfig = WarnPluginConfig(execFlags = "execFlags", lineCaptureGroup = 5) - val config = TestConfig(toml1, null, mutableListOf(warnConfig), fs) + val config: MutableList = mutableListOf(warnConfig) config.validateAndSetDefaults() - assertEquals(1, config.pluginConfigs.size) + assertEquals(1, config.size) - val actualWarnConfig = config.pluginConfigs.filterIsInstance().first() + val actualWarnConfig: WarnPluginConfig = config.singleIsInstance() assertEquals(true, actualWarnConfig.warningTextHasLine) assertEquals(true, actualWarnConfig.warningTextHasColumn) assertEquals(5, actualWarnConfig.lineCaptureGroup) @@ -133,39 +136,41 @@ class ValidationTest { // `lineCaptureGroup` provided, but incorrect -- error @Test fun `validate warn section 4`() { - createTomlFiles() - val warnConfig = WarnPluginConfig(execFlags = "execFlags", lineCaptureGroup = -127) - val config = TestConfig(toml1, null, mutableListOf(warnConfig), fs) - warnConfig.configLocation = config.location - try { - config.validateAndSetDefaults() - } catch (ex: IllegalArgumentException) { - assertTrue("Exception message content incorrect: ${ex.message}") { - ex.message!!.startsWith( - "[Configuration Error]: All integer values in [warn] section of `${warnConfig.configLocation}` config should be positive!" + - "\nCurrent configuration: " - ) - } + val warnConfig = WarnPluginConfig(execFlags = "execFlags", lineCaptureGroup = -127).apply { + configLocation = "./some-location".toPath() + } + assertException(warnConfig) { ex -> + assertEquals( + """ + [Configuration Error]: `lineCaptureGroup` in [warn] section of `${warnConfig.configLocation}` config should be positive! + Current configuration: ${warnConfig.toString().substringAfter("(").substringBefore(")")} + """.trimIndent(), + ex.message + ) } } @Test fun `set defaults to fix section`() { - createTomlFiles() val fixConfig = FixPluginConfig(execFlags = "execFlags") - val config = TestConfig(toml1, null, mutableListOf(fixConfig), fs) + val config: MutableList = mutableListOf(fixConfig) config.validateAndSetDefaults() - assertEquals(1, config.pluginConfigs.size) + assertEquals(1, config.size) - val actualFixConfig = config.pluginConfigs.filterIsInstance().first() + val actualFixConfig: FixPluginConfig = config.singleIsInstance() assertEquals("Test", actualFixConfig.resourceNameTest) assertEquals("Expected", actualFixConfig.resourceNameExpected) } - @AfterTest - fun tearDown() { - fs.deleteRecursively(tmpDir) + private fun assertException(pluginConfig: PluginConfig, validation: (IllegalArgumentException) -> Unit) { + try { + val config: MutableList = mutableListOf(pluginConfig) + config.validateAndSetDefaults() + fail("Expect exception with type ${IllegalArgumentException::class}") + } catch (ex: IllegalArgumentException) { + validation(ex) + } } } diff --git a/save-core/src/commonNonJsTest/resources/override_configs/save-overrides.toml b/save-core/src/commonNonJsTest/resources/override_configs/save-overrides.toml new file mode 100644 index 000000000..a301cbd44 --- /dev/null +++ b/save-core/src/commonNonJsTest/resources/override_configs/save-overrides.toml @@ -0,0 +1,8 @@ +[general] +execCmd = "java -jar tool.jar" + +[fix] +execFlags = "--fix" + +[warn] +execFlags = "--warn" \ No newline at end of file diff --git a/save-core/src/commonNonJsTest/resources/override_configs/save.toml b/save-core/src/commonNonJsTest/resources/override_configs/save.toml new file mode 100644 index 000000000..536c7280e --- /dev/null +++ b/save-core/src/commonNonJsTest/resources/override_configs/save.toml @@ -0,0 +1,8 @@ +[general] +execCmd = "echo hello world" +tags = ["Tag"] +description = "My description" +suiteName = "DocsCheck" + +[warn] + diff --git a/save-core/src/commonNonJsTest/resources/save-overrides.toml b/save-core/src/commonNonJsTest/resources/save-overrides.toml new file mode 100644 index 000000000..ffced3d1d --- /dev/null +++ b/save-core/src/commonNonJsTest/resources/save-overrides.toml @@ -0,0 +1,8 @@ +[general] +execCmd = "sh -c" + +[fix] +execFlags = "--encode" + +[warn] +execFlags = "--warn" \ No newline at end of file diff --git a/save-plugins/fix-and-warn-plugin/README.md b/save-plugins/fix-and-warn-plugin/README.md index d8bafacfa..c41d84de1 100644 --- a/save-plugins/fix-and-warn-plugin/README.md +++ b/save-plugins/fix-and-warn-plugin/README.md @@ -18,14 +18,14 @@ their configuration as a subsections of `[fix and warn]` plugin. ```toml [general] execCmd="./ktlint -R diktat-0.4.2.jar" +batchSize = 1 +batchSeparator = ", " description = "My suite description" suiteName = "DocsCheck" [fix and warn] [fix and warn.fix] execFlags="-F" - batchSize = 1 - batchSeparator = ", " resourceNameTestSuffix = "Test" resourceNameExpectedSuffix = "Expected" [fix and warn.warn] 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 ebd548518..da781d564 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,6 +1,5 @@ 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 @@ -8,6 +7,7 @@ import com.saveourtool.save.core.plugin.Plugin import com.saveourtool.save.core.plugin.PluginConfig import com.saveourtool.save.core.result.Pass import com.saveourtool.save.core.result.TestResult +import com.saveourtool.save.core.utils.singleIsInstance import com.saveourtool.save.plugin.warn.WarnPlugin import com.saveourtool.save.plugin.warn.WarnPluginConfig import com.saveourtool.save.plugins.fix.FixPlugin @@ -38,16 +38,14 @@ class FixAndWarnPlugin( ) { private val fixPluginConfig: FixPluginConfig = testConfig.pluginConfigs - .filterIsInstance() - .single() + .singleIsInstance() .fix private val warnPluginConfig: WarnPluginConfig = testConfig.pluginConfigs - .filterIsInstance() - .single() + .singleIsInstance() .warn private val generalConfig: GeneralConfig = - testConfig.pluginConfigs.filterIsInstance().single() + testConfig.pluginConfigs.singleIsInstance() @Suppress("MISSING_KDOC_CLASS_ELEMENTS") internal lateinit var fixPlugin: FixPlugin @@ -71,10 +69,11 @@ class FixAndWarnPlugin( generalConfig, pluginConfig ), + testConfig.overridesPluginConfigs, fs, ) - override fun handleFiles(evaluatedToolConfig: EvaluatedToolConfig, files: Sequence): Sequence { + override fun handleFiles(files: Sequence): Sequence { testConfig.validateAndSetDefaults() // Need to update private fields after validation initOrUpdateConfigs() @@ -84,7 +83,7 @@ class FixAndWarnPlugin( // fixme: should be performed on copies of files val filesAndTheirWarningsMap = removeWarningsFromExpectedFiles(expectedFiles) - val fixTestResults = fixPlugin.handleFiles(evaluatedToolConfig, files).toList() + val fixTestResults = fixPlugin.handleFiles(files).toList() val (fixTestResultsPassed, fixTestResultsFailed) = fixTestResults.partition { it.status is Pass } @@ -110,7 +109,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(evaluatedToolConfig, expectedFilesWithPass.map { Test(it) }) + val warnTestResults = warnPlugin.handleFiles(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/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 426b1055c..457960daf 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,8 +1,8 @@ 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.files.fs import com.saveourtool.save.core.plugin.GeneralConfig import com.saveourtool.save.core.result.Pass import com.saveourtool.save.core.utils.isCurrentOsWindows @@ -19,7 +19,6 @@ import kotlin.test.assertEquals import kotlin.test.assertTrue class FixAndWarnPluginTest { - private val fs = FileSystem.SYSTEM private val tmpDir = (FileSystem.SYSTEM_TEMPORARY_DIRECTORY / "${FixAndWarnPluginTest::class.simpleName!!}-${Random.nextInt()}") private val defaultExtraConfigPattern = Regex("(.+):(\\d+):(\\d+): (.+)") @@ -82,15 +81,16 @@ class FixAndWarnPluginTest { true, true, 1, 2, 3, 1, 1, 1, 2, 3, 4 ) ), - GeneralConfig("", listOf(""), "", "", expectedWarningsPattern = Regex("// ;warn:(\\d+):(\\d+): (.*)"), runConfigPattern = defaultExtraConfigPattern) + GeneralConfig("", 1, ", ", listOf(""), "", "", expectedWarningsPattern = Regex("// ;warn:(\\d+):(\\d+): (.*)"), runConfigPattern = defaultExtraConfigPattern) ), + emptyList(), fs, ), testFiles = emptyList(), fs, useInternalRedirections = false ) - val results = fixAndWarnPlugin.execute(EvaluatedToolConfig(null, null, 1, ", ")).toList() + val results = fixAndWarnPlugin.execute().toList() println("Results $results") assertEquals(1, results.count(), "Size of results should equal number of pairs") diff --git a/save-plugins/fix-plugin/README.md b/save-plugins/fix-plugin/README.md index 540c6d47b..9d2fb31f3 100644 --- a/save-plugins/fix-plugin/README.md +++ b/save-plugins/fix-plugin/README.md @@ -39,13 +39,13 @@ language=kotlin ```toml [general] execCmd="./ktlint -R diktat-0.4.2.jar" +batchSize = 1 # (default value) +batchSeparator = ", " # (default value) description = "My suite description" suiteName = "DocsCheck" [fix] execFlags="-F" -batchSize = 1 # (default value) -batchSeparator = ", " # (default value) resourceNameTestSuffix = "Test" # (default value) resourceNameExpectedSuffix = "Expected" #(default value) ``` 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 87cd36b86..b4daa5b54 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,6 +1,5 @@ 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 @@ -21,6 +20,7 @@ import com.saveourtool.save.core.result.TestResult import com.saveourtool.save.core.utils.PathSerializer import com.saveourtool.save.core.utils.ProcessExecutionException import com.saveourtool.save.core.utils.ProcessTimeoutException +import com.saveourtool.save.core.utils.singleIsInstance import io.github.petertrr.diffutils.diff import io.github.petertrr.diffutils.patch.ChangeDelta @@ -67,21 +67,27 @@ class FixPlugin( private var tmpDirectory: Path? = null private lateinit var extraFlagsExtractor: ExtraFlagsExtractor - @Suppress("TOO_LONG_FUNCTION") - override fun handleFiles(evaluatedToolConfig: EvaluatedToolConfig, files: Sequence): Sequence { + @Suppress("TOO_LONG_FUNCTION", "LongMethod") + override fun handleFiles(files: Sequence): Sequence { testConfig.validateAndSetDefaults() - val fixPluginConfig = testConfig.pluginConfigs.filterIsInstance().single() - val generalConfig = testConfig.pluginConfigs.filterIsInstance().single() + val fixPluginConfig: FixPluginConfig = testConfig.pluginConfigs.singleIsInstance() + val generalConfig: GeneralConfig = testConfig.pluginConfigs.singleIsInstance() + val batchSize = requireNotNull(generalConfig.batchSize) { + "`batchSize` is not set" + }.toInt() + val batchSeparator = requireNotNull(generalConfig.batchSeparator) { + "`batchSeparator` is not set" + } extraFlagsExtractor = ExtraFlagsExtractor(generalConfig, fs) return files.map { it as FixTestFiles } - .chunked(evaluatedToolConfig.batchSize) + .chunked(batchSize) .map { chunk -> val copyPaths = chunk.map { it.test } 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=${evaluatedToolConfig.batchSize}" + + "Extra flags for all files in a batch should be same, but you have batchSize=$batchSize" + " and there are ${extraFlagsList.size} different sets of flags inside it, namely $extraFlagsList" } val extraFlags = extraFlagsList.singleOrNull() ?: ExtraFlags("", "") @@ -91,11 +97,11 @@ class FixPlugin( createTestFile(test, generalConfig, fixPluginConfig) to expected } val testCopyNames = - pathCopyMap.joinToString(separator = evaluatedToolConfig.batchSeparator) { (testCopy, _) -> testCopy.toString() } + pathCopyMap.joinToString(separator = batchSeparator) { (testCopy, _) -> testCopy.toString() } - val execFlags = evaluatedToolConfig.execFlags ?: fixPluginConfig.execFlags + val execFlags = fixPluginConfig.execFlags val execFlagsAdjusted = resolvePlaceholdersFrom(execFlags, extraFlags, testCopyNames) - val execCmdWithoutFlags = evaluatedToolConfig.execCmd ?: generalConfig.execCmd + val execCmdWithoutFlags = generalConfig.execCmd val execCmd = "$execCmdWithoutFlags $execFlagsAdjusted" val time = generalConfig.timeOutMillis!!.times(pathMap.size) 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 a8df0e3f3..25850f52f 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,6 +1,5 @@ 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 @@ -77,17 +76,22 @@ class FixPluginTest { val diskWithTmpDir = if (isCurrentOsWindows()) "${tmpDir.toString().substringBefore("\\").lowercase()} && " else "" val executionCmd = "${diskWithTmpDir}cd $tmpDir && echo Expected file >" - val fixPlugin = FixPlugin(TestConfig(config, - null, - mutableListOf( - FixPluginConfig(executionCmd), - GeneralConfig("", listOf(""), "", "") - ), fs), + val fixPlugin = FixPlugin( + TestConfig( + config, + null, + mutableListOf( + FixPluginConfig(executionCmd), + GeneralConfig("", 1, ", ", listOf(""), "", "") + ), + emptyList(), + fs + ), testFiles = emptyList(), fs, useInternalRedirections = false ) - val results = fixPlugin.execute(EvaluatedToolConfig(null, null, 1, ", ")).toList() + val results = fixPlugin.execute().toList() assertEquals(1, results.size, "Size of results should equal number of pairs") val testResult = results.single() @@ -138,18 +142,23 @@ class FixPluginTest { val fixPluginConfig = FixPluginConfig(executionCmd) - val fixPlugin = FixPlugin(TestConfig(config, - null, - mutableListOf( - fixPluginConfig, - GeneralConfig("", listOf(""), "", "") - ), fs), + val batchSeparator = if (isCurrentOsWindows()) ", " else " " + val fixPlugin = FixPlugin( + TestConfig( + config, + null, + mutableListOf( + fixPluginConfig, + GeneralConfig("", 2, batchSeparator, listOf(""), "", "") + ), + emptyList(), + fs + ), testFiles = emptyList(), fs, useInternalRedirections = false ) - val batchSeparator = if (isCurrentOsWindows()) ", " else " " - val results = fixPlugin.execute(EvaluatedToolConfig(null, null, 2, batchSeparator)).toList() + val results = fixPlugin.execute().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) @@ -167,7 +176,13 @@ class FixPluginTest { } internal fun discoverFilePairs() = FixPlugin( - TestConfig(tmpDir / "save.toml", null, mutableListOf(FixPluginConfig("")), fs), + TestConfig( + tmpDir / "save.toml", + null, + mutableListOf(FixPluginConfig("")), + emptyList(), + fs + ), testFiles = emptyList(), fs, useInternalRedirections = false diff --git a/save-plugins/warn-plugin/README.md b/save-plugins/warn-plugin/README.md index 63c30b378..1489b739d 100644 --- a/save-plugins/warn-plugin/README.md +++ b/save-plugins/warn-plugin/README.md @@ -79,6 +79,8 @@ you will need the following SAVE configuration: ```toml [general] execCmd = "./detekt" +batchSize = 1 # (default value) +batchSeparator = ", " # (default value) description = "My suite description" suiteName = "DocsCheck" language = "Kotlin" @@ -123,8 +125,6 @@ messageCaptureGroupEnd = 1 # (default value) warningTextHasColumn = true # (default value) warningTextHasLine = true # (default value) testNameRegex = ".*Test.*" # (default value) -batchSize = 1 # (default value) -batchSeparator = ", " # (default value) linePlaceholder = "$line" # (default value) patternForRegexInWarning = ["{{", "}}"] # if true - the regex created from expected warning will be wrapped with '.*': .*warn.*. 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 8d3494b87..96ff1ee2f 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,7 +1,6 @@ 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 @@ -21,6 +20,7 @@ import com.saveourtool.save.core.utils.ExecutionResult import com.saveourtool.save.core.utils.ProcessExecutionException import com.saveourtool.save.core.utils.ProcessTimeoutException import com.saveourtool.save.core.utils.SarifParsingException +import com.saveourtool.save.core.utils.singleIsInstance import com.saveourtool.save.plugin.warn.sarif.toWarnings import com.saveourtool.save.plugin.warn.utils.CmdExecutorWarn import com.saveourtool.save.plugin.warn.utils.ResultsChecker @@ -62,10 +62,16 @@ class WarnPlugin( private lateinit var extraFlagsExtractor: ExtraFlagsExtractor private lateinit var tmpDirName: String - override fun handleFiles(evaluatedToolConfig: EvaluatedToolConfig, files: Sequence): Sequence { + override fun handleFiles(files: Sequence): Sequence { testConfig.validateAndSetDefaults() - val warnPluginConfig = testConfig.pluginConfigs.filterIsInstance().single() - val generalConfig = testConfig.pluginConfigs.filterIsInstance().single() + val warnPluginConfig: WarnPluginConfig = testConfig.pluginConfigs.singleIsInstance() + val generalConfig: GeneralConfig = testConfig.pluginConfigs.singleIsInstance() + val batchSize = requireNotNull(generalConfig.batchSize) { + "`batchSize` is not set" + }.toInt() + val batchSeparator = requireNotNull(generalConfig.batchSeparator) { + "`batchSeparator` is not set" + } extraFlagsExtractor = ExtraFlagsExtractor(generalConfig, fs) // Special trick to handle cases when tested tool is able to process directories. @@ -73,16 +79,16 @@ 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(), evaluatedToolConfig, warnPluginConfig, generalConfig).asSequence() + handleTestFile(files.map { it.test }.toList(), warnPluginConfig, generalConfig, batchSeparator).asSequence() } ?: run { - files.chunked(evaluatedToolConfig.batchSize).flatMap { chunk -> - handleTestFile(chunk.map { it.test }, evaluatedToolConfig, warnPluginConfig, generalConfig) + files.chunked(batchSize).flatMap { chunk -> + handleTestFile(chunk.map { it.test }, warnPluginConfig, generalConfig, batchSeparator) } } } override fun rawDiscoverTestFiles(resourceDirectories: Sequence): Sequence { - val warnPluginConfig = testConfig.pluginConfigs.filterIsInstance().single() + val warnPluginConfig: WarnPluginConfig = testConfig.pluginConfigs.singleIsInstance() val regex = warnPluginConfig.resourceNamePattern // returned sequence is a sequence of groups of size 1 return resourceDirectories.flatMap { directory -> @@ -109,9 +115,9 @@ class WarnPlugin( ) private fun handleTestFile( originalPaths: List, - evaluatedToolConfig: EvaluatedToolConfig, warnPluginConfig: WarnPluginConfig, - generalConfig: GeneralConfig + generalConfig: GeneralConfig, + batchSeparator: String, ): Sequence { // extracting all warnings from test resource files val copyPaths: List = createTestFiles(originalPaths, warnPluginConfig) @@ -126,9 +132,9 @@ class WarnPlugin( copyPaths, extraFlagsExtractor, pb, - evaluatedToolConfig.execCmd ?: generalConfig.execCmd, - evaluatedToolConfig.execFlags ?: warnPluginConfig.execFlags, - evaluatedToolConfig.batchSeparator, + generalConfig.execCmd, + warnPluginConfig.execFlags, + 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 d41d825ff..49181ce17 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 @@ -8,6 +8,7 @@ import com.saveourtool.save.core.config.ExpectedWarningsFormat import com.saveourtool.save.core.config.TestConfigSections import com.saveourtool.save.core.plugin.PluginConfig import com.saveourtool.save.core.utils.RegexSerializer +import com.saveourtool.save.core.utils.requirePositive import okio.Path import okio.Path.Companion.toPath @@ -150,13 +151,13 @@ data class WarnPluginConfig( "TOO_LONG_FUNCTION" ) override fun validateAndSetDefaults(): WarnPluginConfig { - requirePositiveIfNotNull(lineCaptureGroup) - requirePositiveIfNotNull(columnCaptureGroup) - requirePositiveIfNotNull(messageCaptureGroup) - requirePositiveIfNotNull(fileNameCaptureGroupOut) - requirePositiveIfNotNull(lineCaptureGroupOut) - requirePositiveIfNotNull(columnCaptureGroupOut) - requirePositiveIfNotNull(messageCaptureGroupOut) + lineCaptureGroup?.let { requirePositive("lineCaptureGroup", it) } + columnCaptureGroup?.let { requirePositive("columnCaptureGroup", it) } + messageCaptureGroup?.let { requirePositive("messageCaptureGroup", it) } + fileNameCaptureGroupOut?.let { requirePositive("fileNameCaptureGroupOut", it) } + lineCaptureGroupOut?.let { requirePositive("lineCaptureGroupOut", it) } + columnCaptureGroupOut?.let { requirePositive("columnCaptureGroupOut", it) } + messageCaptureGroupOut?.let { requirePositive("messageCaptureGroupOut", it) } requireValidPatternForRegexInWarning() val expectedWarningsFormat = expectedWarningsFormat ?: ExpectedWarningsFormat.IN_PLACE @@ -210,17 +211,6 @@ data class WarnPluginConfig( } } - private fun requirePositiveIfNotNull(value: Long?) { - value?.let { - require(value >= 0) { - """ - [Configuration Error]: All integer values in [warn] section of `$configLocation` config should be positive! - Current configuration: ${this.toString().substringAfter("(").substringBefore(")")} - """.trimIndent() - } - } - } - private fun requireValidPatternForRegexInWarning() { patternForRegexInWarning?.let { require(patternForRegexInWarning.size == 2) { diff --git a/save-plugins/warn-plugin/src/commonTest/kotlin/com/saveourtool/save/plugin/warn/WarnPluginTest.kt b/save-plugins/warn-plugin/src/commonNonJsTest/kotlin/com/saveourtool/save/plugin/warn/WarnPluginTest.kt similarity index 97% rename from save-plugins/warn-plugin/src/commonTest/kotlin/com/saveourtool/save/plugin/warn/WarnPluginTest.kt rename to save-plugins/warn-plugin/src/commonNonJsTest/kotlin/com/saveourtool/save/plugin/warn/WarnPluginTest.kt index b922994b6..77b112cb8 100644 --- a/save-plugins/warn-plugin/src/commonTest/kotlin/com/saveourtool/save/plugin/warn/WarnPluginTest.kt +++ b/save-plugins/warn-plugin/src/commonNonJsTest/kotlin/com/saveourtool/save/plugin/warn/WarnPluginTest.kt @@ -1,8 +1,8 @@ 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.files.fs import com.saveourtool.save.core.plugin.GeneralConfig import com.saveourtool.save.core.plugin.ResourceFormatException import com.saveourtool.save.core.result.Pass @@ -21,7 +21,6 @@ import kotlin.test.assertFailsWith import kotlin.test.assertTrue class WarnPluginTest { - private val fs = FileSystem.SYSTEM private val tmpDir = (FileSystem.SYSTEM_TEMPORARY_DIRECTORY / WarnPluginTest::class.simpleName!!) private val catCmd = if (isCurrentOsWindows()) "type" else "cat" private val mockScriptFile = tmpDir / "resource" @@ -412,7 +411,7 @@ class WarnPluginTest { texts: List, warnPluginConfig: WarnPluginConfig, generalConfig: GeneralConfig, - batchSize: Int = 1, + batchSize: Long = 1, assertion: (List) -> Unit, ) { val config = fs.createFile(tmpDir / "save.toml") @@ -424,11 +423,17 @@ class WarnPluginTest { } val results = WarnPlugin( - TestConfig(config, null, mutableListOf(warnPluginConfig, generalConfig), fs), + TestConfig( + config, + null, + mutableListOf(warnPluginConfig, generalConfig.copy(batchSize = batchSize)), + emptyList(), + fs + ), testFiles = emptyList(), fs ) - .execute(EvaluatedToolConfig(null, null, batchSize, ", ")) + .execute() .toList() assertion(results) } diff --git a/save-plugins/warn-plugin/src/commonTest/kotlin/com/saveourtool/save/plugin/warn/sarif/SarifWarningAdapterTest.kt b/save-plugins/warn-plugin/src/commonNonJsTest/kotlin/com/saveourtool/save/plugin/warn/sarif/SarifWarningAdapterTest.kt similarity index 100% rename from save-plugins/warn-plugin/src/commonTest/kotlin/com/saveourtool/save/plugin/warn/sarif/SarifWarningAdapterTest.kt rename to save-plugins/warn-plugin/src/commonNonJsTest/kotlin/com/saveourtool/save/plugin/warn/sarif/SarifWarningAdapterTest.kt