Files
SwiftLint/Tests/FrameworkTests/RuleConfigurationTests.swift
Danny Mösch ac2eda6732 Adopt Swift Testing
# Conflicts:
#	Tests/BuiltInRulesTests/FileHeaderRuleTests.swift
#	Tests/BuiltInRulesTests/FileNameNoSpaceRuleTests.swift
#	Tests/BuiltInRulesTests/IndentationWidthRuleTests.swift
#	Tests/CoreTests/RegexConfigurationTests.swift
#	Tests/CoreTests/SwiftLintFileTests.swift
#	Tests/FileSystemAccessTests/BaselineTests.swift
#	Tests/FileSystemAccessTests/ConfigurationTests+Mock.swift
#	Tests/FileSystemAccessTests/ConfigurationTests.swift
#	Tests/FileSystemAccessTests/GlobTests.swift
#	Tests/FileSystemAccessTests/MultipleConfigurationsTests.swift
#	Tests/FileSystemAccessTests/ReporterTests.swift
#	Tests/FileSystemAccessTests/SourceKitCrashTests.swift
#	Tests/FrameworkTests/CustomRulesTests.swift
#	Tests/FrameworkTests/LinterCacheTests.swift
#	Tests/FrameworkTests/RuleConfigurationTests.swift
#	Tests/FrameworkTests/SwiftVersionTests.swift
#	Tests/GeneratedTests/GeneratedTests_02.swift
#	Tests/GeneratedTests/GeneratedTests_03.swift
#	Tests/GeneratedTests/GeneratedTests_04.swift
#	Tests/GeneratedTests/GeneratedTests_05.swift
#	Tests/GeneratedTests/GeneratedTests_06.swift
#	Tests/GeneratedTests/GeneratedTests_07.swift
#	Tests/GeneratedTests/GeneratedTests_08.swift
#	Tests/GeneratedTests/GeneratedTests_09.swift
#	Tests/GeneratedTests/GeneratedTests_10.swift
#	Tests/IntegrationTests/ConfigPathResolutionTests.swift
#	Tests/IntegrationTests/IntegrationTests.swift
#	Tests/TestHelpers/TestHelpers.swift
2026-06-06 11:07:04 +02:00

399 lines
14 KiB
Swift

import SourceKittenFramework
import TestHelpers
import Testing
@testable import SwiftLintBuiltInRules
@testable import SwiftLintCore
@Suite
struct RuleConfigurationTests {
private let defaultNestingConfiguration = NestingConfiguration(
typeLevel: SeverityLevelsConfiguration(warning: 0),
functionLevel: SeverityLevelsConfiguration(warning: 0)
)
@Test
func nestingConfigurationSetsCorrectly() {
let config =
[
"type_level": [
"warning": 7, "error": 17,
],
"function_level": [
"warning": 8, "error": 18,
],
"check_nesting_in_closures_and_statements": false,
"always_allow_one_type_in_functions": true,
] as [String: any Sendable]
var nestingConfig = defaultNestingConfiguration
do {
try nestingConfig.apply(configuration: config)
#expect(nestingConfig.typeLevel.warning == 7)
#expect(nestingConfig.functionLevel.warning == 8)
#expect(nestingConfig.typeLevel.error == 17)
#expect(nestingConfig.functionLevel.error == 18)
#expect(nestingConfig.alwaysAllowOneTypeInFunctions)
#expect(!nestingConfig.checkNestingInClosuresAndStatements)
} catch {
Issue.record("Failed to configure nested configurations")
}
}
@Test
func nestingConfigurationThrowsOnBadConfig() {
let config = 17
var nestingConfig = defaultNestingConfiguration
#expect(throws: Issue.invalidConfiguration(ruleID: NestingRule.identifier)) {
try nestingConfig.apply(configuration: config)
}
}
@Test
func severityWorksAsOnlyParameter() throws {
var config = AttributesConfiguration()
#expect(config.severity == .warning)
try config.apply(configuration: "error")
#expect(config.severity == .error)
}
@Test
func severityConfigurationFromString() {
let config = "Warning"
let comp = SeverityConfiguration<MockRule>(.warning)
var severityConfig = SeverityConfiguration<MockRule>(.error)
#expect(throws: Never.self) {
try severityConfig.apply(configuration: config)
}
#expect(severityConfig == comp)
}
@Test
func severityConfigurationFromDictionary() {
let config = ["severity": "warning"]
let comp = SeverityConfiguration<MockRule>(.warning)
var severityConfig = SeverityConfiguration<MockRule>(.error)
do {
try severityConfig.apply(configuration: config)
#expect(severityConfig == comp)
} catch {
Issue.record("Failed to configure severity from dictionary")
}
}
@Test
func severityConfigurationThrowsNothingApplied() {
let config = 17
var severityConfig = SeverityConfiguration<MockRule>(.error)
#expect(throws: Issue.nothingApplied(ruleID: MockRule.identifier)) {
try severityConfig.apply(configuration: config)
}
}
@Test
func severityConfigurationThrowsInvalidConfiguration() {
let config = "foo"
var severityConfig = SeverityConfiguration<MockRule>(.warning)
#expect(throws: Issue.invalidConfiguration(ruleID: MockRule.identifier)) {
try severityConfig.apply(configuration: config)
}
}
@Test
func severityLevelConfigParams() {
let severityConfig = SeverityLevelsConfiguration<MockRule>(warning: 17, error: 7)
#expect(
severityConfig.params == [
RuleParameter(severity: .error, value: 7),
RuleParameter(severity: .warning, value: 17),
]
)
}
@Test
func severityLevelConfigPartialParams() {
let severityConfig = SeverityLevelsConfiguration<MockRule>(warning: 17, error: nil)
#expect(severityConfig.params == [RuleParameter(severity: .warning, value: 17)])
}
@Test
func severityLevelConfigApplyNilErrorValue() throws {
var severityConfig = SeverityLevelsConfiguration<MockRule>(warning: 17, error: 20)
try severityConfig.apply(configuration: ["error": nil, "warning": 18])
#expect(severityConfig.params == [RuleParameter(severity: .warning, value: 18)])
}
@Test
func severityLevelConfigApplyMissingErrorValue() throws {
var severityConfig = SeverityLevelsConfiguration<MockRule>(warning: 17, error: 20)
try severityConfig.apply(configuration: ["warning": 18])
#expect(severityConfig.params == [RuleParameter(severity: .warning, value: 18)])
}
@Test
func regexConfigurationThrows() {
let config = 17
var regexConfig = RegexConfiguration<MockRule>(identifier: "")
#expect(throws: Issue.invalidConfiguration(ruleID: MockRule.identifier)) {
try regexConfig.apply(configuration: config)
}
}
@Test
func regexRuleDescription() {
var regexConfig = RegexConfiguration<MockRule>(identifier: "regex")
#expect(
regexConfig.description
== RuleDescription(
identifier: "regex",
name: "regex",
description: "", kind: .style))
regexConfig.name = "name"
#expect(
regexConfig.description
== RuleDescription(
identifier: "regex",
name: "name",
description: "", kind: .style))
}
@Test
func trailingWhitespaceConfigurationThrowsOnBadConfig() {
let config = "unknown"
var configuration = TrailingWhitespaceConfiguration(
ignoresEmptyLines: false,
ignoresComments: true)
#expect(throws: Issue.invalidConfiguration(ruleID: TrailingWhitespaceRule.identifier)) {
try configuration.apply(configuration: config)
}
}
@Test
func trailingWhitespaceConfigurationInitializerSetsIgnoresEmptyLines() {
let configuration1 = TrailingWhitespaceConfiguration(
ignoresEmptyLines: false,
ignoresComments: true)
#expect(!configuration1.ignoresEmptyLines)
let configuration2 = TrailingWhitespaceConfiguration(
ignoresEmptyLines: true,
ignoresComments: true)
#expect(configuration2.ignoresEmptyLines)
}
@Test
func trailingWhitespaceConfigurationInitializerSetsIgnoresComments() {
let configuration1 = TrailingWhitespaceConfiguration(
ignoresEmptyLines: false,
ignoresComments: true)
#expect(configuration1.ignoresComments)
let configuration2 = TrailingWhitespaceConfiguration(
ignoresEmptyLines: false,
ignoresComments: false)
#expect(!configuration2.ignoresComments)
}
@Test
func trailingWhitespaceConfigurationApplyConfigurationSetsIgnoresEmptyLines() {
var configuration = TrailingWhitespaceConfiguration(
ignoresEmptyLines: false,
ignoresComments: true
)
let config1 = ["ignores_empty_lines": true]
#expect(throws: Never.self) {
try configuration.apply(configuration: config1)
}
#expect(configuration.ignoresEmptyLines)
let config2 = ["ignores_empty_lines": false]
#expect(throws: Never.self) {
try configuration.apply(configuration: config2)
}
#expect(!configuration.ignoresEmptyLines)
}
@Test
func trailingWhitespaceConfigurationApplyConfigurationSetsIgnoresComments() {
var configuration = TrailingWhitespaceConfiguration(
ignoresEmptyLines: false,
ignoresComments: true
)
let config1 = ["ignores_comments": true]
#expect(throws: Never.self) {
try configuration.apply(configuration: config1)
}
#expect(configuration.ignoresComments)
let config2 = ["ignores_comments": false]
#expect(throws: Never.self) {
try configuration.apply(configuration: config2)
}
#expect(!configuration.ignoresComments)
}
@Test
func trailingWhitespaceConfigurationCompares() {
let configuration1 = TrailingWhitespaceConfiguration(
ignoresEmptyLines: false,
ignoresComments: true)
let configuration2 = TrailingWhitespaceConfiguration(
ignoresEmptyLines: true,
ignoresComments: true)
#expect(configuration1 != configuration2)
let configuration3 = TrailingWhitespaceConfiguration(
ignoresEmptyLines: true,
ignoresComments: true)
#expect(configuration2 == configuration3)
let configuration4 = TrailingWhitespaceConfiguration(
ignoresEmptyLines: false,
ignoresComments: false)
#expect(configuration1 != configuration4)
let configuration5 = TrailingWhitespaceConfiguration(
ignoresEmptyLines: true,
ignoresComments: false)
#expect(configuration1 != configuration5)
}
@Test
func trailingWhitespaceConfigurationApplyConfigurationUpdatesSeverityConfiguration() {
var configuration = TrailingWhitespaceConfiguration(
severityConfiguration: .warning,
ignoresEmptyLines: false,
ignoresComments: true
)
#expect(throws: Never.self) {
try configuration.apply(configuration: ["severity": "error"])
}
#expect(configuration.severityConfiguration.severity == .error)
}
@Test
func overriddenSuperCallConfigurationFromDictionary() {
var configuration = OverriddenSuperCallConfiguration()
#expect(configuration.resolvedMethodNames.contains("viewWillAppear(_:)"))
let conf1 = ["severity": "error", "excluded": "viewWillAppear(_:)"]
#expect(throws: Never.self) {
try configuration.apply(configuration: conf1)
}
#expect(configuration.severityConfiguration.severity == .error)
#expect(!configuration.resolvedMethodNames.contains("*"))
#expect(!configuration.resolvedMethodNames.contains("viewWillAppear(_:)"))
#expect(configuration.resolvedMethodNames.contains("viewWillDisappear(_:)"))
let conf2 = [
"severity": "error",
"excluded": "viewWillAppear(_:)",
"included": ["*", "testMethod1()", "testMethod2(_:)"],
] as [String: any Sendable]
#expect(throws: Never.self) {
try configuration.apply(configuration: conf2)
}
#expect(configuration.severityConfiguration.severity == .error)
#expect(!configuration.resolvedMethodNames.contains("*"))
#expect(!configuration.resolvedMethodNames.contains("viewWillAppear(_:)"))
#expect(configuration.resolvedMethodNames.contains("viewWillDisappear(_:)"))
#expect(configuration.resolvedMethodNames.contains("testMethod1()"))
#expect(configuration.resolvedMethodNames.contains("testMethod2(_:)"))
let conf3 = [
"severity": "warning",
"excluded": "*",
"included": ["testMethod1()", "testMethod2(_:)"],
] as [String: any Sendable]
#expect(throws: Never.self) {
try configuration.apply(configuration: conf3)
}
#expect(configuration.severityConfiguration.severity == .warning)
#expect(configuration.resolvedMethodNames.count == 2)
#expect(!configuration.resolvedMethodNames.contains("*"))
#expect(configuration.resolvedMethodNames.contains("testMethod1()"))
#expect(configuration.resolvedMethodNames.contains("testMethod2(_:)"))
}
@Test
func modifierOrderConfigurationFromDictionary() throws {
var configuration = ModifierOrderConfiguration()
let config: [String: Any] = [
"severity": "warning",
"preferred_modifier_order": [
"override",
"acl",
"setterACL",
"owned",
"mutators",
"final",
"typeMethods",
"required",
"convenience",
"lazy",
"dynamic",
],
]
try configuration.apply(configuration: config)
let expected: [SwiftDeclarationAttributeKind.ModifierGroup] = [
.override,
.acl,
.setterACL,
.owned,
.mutators,
.final,
.typeMethods,
.required,
.convenience,
.lazy,
.dynamic,
]
#expect(configuration.severityConfiguration.severity == .warning)
#expect(configuration.preferredModifierOrder == expected)
}
@Test
func modifierOrderConfigurationThrowsOnUnrecognizedModifierGroup() {
var configuration = ModifierOrderConfiguration()
let config =
["severity": "warning", "preferred_modifier_order": ["specialize"]]
as [String: any Sendable]
#expect(throws: Issue.invalidConfiguration(ruleID: ModifierOrderRule.identifier)) {
try configuration.apply(configuration: config)
}
}
@Test
func modifierOrderConfigurationThrowsOnNonModifiableGroup() {
var configuration = ModifierOrderConfiguration()
let config = ["severity": "warning", "preferred_modifier_order": ["atPrefixed"]] as [String: any Sendable]
#expect(throws: Issue.invalidConfiguration(ruleID: ModifierOrderRule.identifier)) {
try configuration.apply(configuration: config)
}
}
@Test
func unusedParameterConfigurationFromDictionary() throws {
var configuration = UnusedParameterConfiguration()
try configuration.apply(configuration: ["severity": "error", "allow_underscore_prefixed_names": true])
#expect(configuration.severity == .error)
#expect(configuration.allowUnderscorePrefixedNames)
}
@Test
func computedAccessorsOrderRuleConfiguration() throws {
var configuration = ComputedAccessorsOrderConfiguration()
let config = ["severity": "error", "order": "set_get"]
try configuration.apply(configuration: config)
#expect(configuration.severityConfiguration.severity == .error)
#expect(configuration.order == .setGet)
#expect(
RuleConfigurationDescription.from(configuration: configuration).oneLiner()
== "severity: error; order: set_get")
}
}