Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added save-overrides.toml #438

Merged
merged 19 commits into from
Aug 29, 2022
Merged
Show file tree
Hide file tree
Changes from 18 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 1 addition & 5 deletions OptionsTable.md
Original file line number Diff line number Diff line change
Expand Up @@ -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) | , |
| - | report-dir | Path to directory, where to store output (when `resultOutput` is set to `FILE`) | save-reports |
32 changes: 0 additions & 32 deletions buildSrc/src/main/resources/config-options.json
Original file line number Diff line number Diff line change
Expand Up @@ -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" : ", "
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
}

Expand Down
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -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<String> = 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<TestFiles>): Sequence<TestResult> = emptySequence()
override fun handleFiles(files: Sequence<TestFiles>): Sequence<TestResult> = emptySequence()

override fun rawDiscoverTestFiles(resourceDirectories: Sequence<Path>): Sequence<TestFiles> = emptySequence()

Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -10,24 +10,30 @@ 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

/**
* Configuration for a test suite, that is read from test suite configuration file (toml config)
* @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")
data class TestConfig(
val location: Path,
val parentConfig: TestConfig?,
val pluginConfigs: MutableList<PluginConfig> = mutableListOf(),
val overridesPluginConfigs: List<PluginConfig>,
val fs: FileSystem,
) {
/**
Expand Down Expand Up @@ -78,7 +84,7 @@ data class TestConfig(
*
* @return [GeneralConfig] or `null` if not found
*/
fun getGeneralConfig() = pluginConfigs.filterIsInstance<GeneralConfig>().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
Expand Down Expand Up @@ -122,15 +128,17 @@ data class TestConfig(
* @return an update this [TestConfig]
*/
fun processInPlace(createPluginConfigList: (TestConfig) -> List<PluginConfig>): TestConfig {
// need to process parent first
this.parentConfig?.processInPlace(createPluginConfigList)
petertrr marked this conversation as resolved.
Show resolved Hide resolved
// 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
}

Expand Down Expand Up @@ -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
*/
Expand All @@ -192,23 +201,6 @@ data class TestConfig(
logDebug("Validated plugin configuration for [$location] " +
"(${pluginConfigs.map { it.type }.filterNot { it == TestConfigSections.GENERAL }})")
}

private fun MutableList<PluginConfig>.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)
}
}
}

/**
Expand All @@ -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"
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -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
Expand Down Expand Up @@ -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<TestResult> {
fun execute(): Sequence<TestResult> {
clean()
val testFilesList = discoverTestFiles(testConfig.directory).toList()

val excludedTests = testConfig
.pluginConfigs
.filterIsInstance<GeneralConfig>()
.singleOrNull()
.singleIsInstanceOrNull<GeneralConfig>()
?.excludedTests

if (!excludedTests.isNullOrEmpty()) {
Expand All @@ -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()
}
Expand All @@ -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<TestFiles>): Sequence<TestResult>
abstract fun handleFiles(files: Sequence<TestFiles>): Sequence<TestResult>

/**
* Discover groups of resource files which will be used to run tests, applying additional filtering
Expand Down
Loading