SwiftLint/Tests/SwiftLintFrameworkTests/CustomRulesTests.swift

291 lines
11 KiB
Swift

import SourceKittenFramework
@testable import SwiftLintFramework
import XCTest
class CustomRulesTests: XCTestCase {
func testCustomRuleConfigurationSetsCorrectlyWithMatchKinds() {
let configDict = [
"my_custom_rule": [
"name": "MyCustomRule",
"message": "Message",
"regex": "regex",
"match_kinds": "comment",
"severity": "error"
]
]
var comp = RegexConfiguration(identifier: "my_custom_rule")
comp.name = "MyCustomRule"
comp.message = "Message"
comp.regex = regex("regex")
comp.severityConfiguration = SeverityConfiguration(.error)
comp.excludedMatchKinds = SyntaxKind.allKinds.subtracting([.comment])
var compRules = CustomRulesConfiguration()
compRules.customRuleConfigurations = [comp]
do {
var configuration = CustomRulesConfiguration()
try configuration.apply(configuration: configDict)
XCTAssertEqual(configuration, compRules)
} catch {
XCTFail("Did not configure correctly")
}
}
func testCustomRuleConfigurationSetsCorrectlyWithExcludedMatchKinds() {
let configDict = [
"my_custom_rule": [
"name": "MyCustomRule",
"message": "Message",
"regex": "regex",
"excluded_match_kinds": "comment",
"severity": "error"
]
]
var comp = RegexConfiguration(identifier: "my_custom_rule")
comp.name = "MyCustomRule"
comp.message = "Message"
comp.regex = regex("regex")
comp.severityConfiguration = SeverityConfiguration(.error)
comp.excludedMatchKinds = Set<SyntaxKind>([.comment])
var compRules = CustomRulesConfiguration()
compRules.customRuleConfigurations = [comp]
do {
var configuration = CustomRulesConfiguration()
try configuration.apply(configuration: configDict)
XCTAssertEqual(configuration, compRules)
} catch {
XCTFail("Did not configure correctly")
}
}
func testCustomRuleConfigurationThrows() {
let config = 17
var customRulesConfig = CustomRulesConfiguration()
checkError(ConfigurationError.unknownConfiguration) {
try customRulesConfig.apply(configuration: config)
}
}
func testCustomRuleConfigurationMatchKindAmbiguity() {
let configDict = [
"name": "MyCustomRule",
"message": "Message",
"regex": "regex",
"match_kinds": "comment",
"excluded_match_kinds": "argument",
"severity": "error"
]
var configuration = RegexConfiguration(identifier: "my_custom_rule")
checkError(ConfigurationError.ambiguousMatchKindParameters) {
try configuration.apply(configuration: configDict)
}
}
func testCustomRuleConfigurationIgnoreInvalidRules() throws {
let configDict = [
"my_custom_rule": ["name": "MyCustomRule",
"message": "Message",
"regex": "regex",
"match_kinds": "comment",
"severity": "error"],
"invalid_rule": ["name": "InvalidRule"] // missing `regex`
]
var customRulesConfig = CustomRulesConfiguration()
try customRulesConfig.apply(configuration: configDict)
XCTAssertEqual(customRulesConfig.customRuleConfigurations.count, 1)
let identifier = customRulesConfig.customRuleConfigurations.first?.description.identifier
XCTAssertEqual(identifier, "my_custom_rule")
}
func testCustomRules() {
let (regexConfig, customRules) = getCustomRules()
let file = SwiftLintFile(contents: "// My file with\n// a pattern")
XCTAssertEqual(customRules.validate(file: file),
[StyleViolation(ruleDescription: regexConfig.description,
severity: .warning,
location: Location(file: nil, line: 2, character: 6),
reason: regexConfig.message)])
}
func testLocalDisableCustomRule() {
let (_, customRules) = getCustomRules()
let file = SwiftLintFile(contents: "//swiftlint:disable custom \n// file with a pattern")
XCTAssertEqual(customRules.validate(file: file), [])
}
func testLocalDisableCustomRuleWithMultipleRules() {
let (configs, customRules) = getCustomRulesWithTwoRules()
let file = SwiftLintFile(contents: "//swiftlint:disable \(configs.1.identifier) \n// file with a pattern")
XCTAssertEqual(customRules.validate(file: file),
[StyleViolation(ruleDescription: configs.0.description,
severity: .warning,
location: Location(file: nil, line: 2, character: 16),
reason: configs.0.message)])
}
func testCustomRulesIncludedDefault() {
// Violation detected when included is omitted.
let (_, customRules) = getCustomRules()
let violations = customRules.validate(file: getTestTextFile())
XCTAssertEqual(violations.count, 1)
}
func testCustomRulesIncludedExcludesFile() {
var (regexConfig, customRules) = getCustomRules(["included": "\\.yml$"])
var customRuleConfiguration = CustomRulesConfiguration()
customRuleConfiguration.customRuleConfigurations = [regexConfig]
customRules.configuration = customRuleConfiguration
let violations = customRules.validate(file: getTestTextFile())
XCTAssertEqual(violations.count, 0)
}
func testCustomRulesExcludedExcludesFile() {
var (regexConfig, customRules) = getCustomRules(["excluded": "\\.txt$"])
var customRuleConfiguration = CustomRulesConfiguration()
customRuleConfiguration.customRuleConfigurations = [regexConfig]
customRules.configuration = customRuleConfiguration
let violations = customRules.validate(file: getTestTextFile())
XCTAssertEqual(violations.count, 0)
}
func testCustomRulesExcludedArrayExcludesFile() {
var (regexConfig, customRules) = getCustomRules(["excluded": ["\\.pdf$", "\\.txt$"]])
var customRuleConfiguration = CustomRulesConfiguration()
customRuleConfiguration.customRuleConfigurations = [regexConfig]
customRules.configuration = customRuleConfiguration
let violations = customRules.validate(file: getTestTextFile())
XCTAssertEqual(violations.count, 0)
}
func testCustomRulesCaptureGroup() {
let (_, customRules) = getCustomRules(["regex": #"\ba\s+(\w+)"#,
"capture_group": 1])
let violations = customRules.validate(file: getTestTextFile())
XCTAssertEqual(violations.count, 1)
XCTAssertEqual(violations[0].location.line, 2)
XCTAssertEqual(violations[0].location.character, 6)
}
func testSuperfluousDisableCommandWithCustomRules() throws {
let customRulesConfiguration: [String: Any] = [
"custom1": [
"regex": "pattern",
"match_kinds": "comment"
]
]
let example = Example(
"// swiftlint:disable custom1\n",
configuration: customRulesConfiguration
).skipWrappingInCommentTest()
let configuration = try Configuration(dict: ["custom_rules": customRulesConfiguration])
let violations = violations(example, config: configuration)
XCTAssertEqual(violations.count, 1)
XCTAssertTrue(violations.allSatisfy { $0.ruleIdentifier == "superfluous_disable_command" })
XCTAssertTrue(violations.contains { violation in
violation.description.contains("SwiftLint rule 'custom1' did not trigger a violation")
})
}
func testSuperfluousDisableCommandWithMultipleCustomRules() throws {
let customRulesConfiguration: [String: Any] = [
"custom1": [
"regex": "pattern",
"match_kinds": "comment"
],
"custom2": [
"regex": "10",
"match_kinds": "number"
],
"custom3": [
"regex": "100",
"match_kinds": "number"
]
]
let example = Example(
"""
// swiftlint:disable custom1 custom3
return 10
""",
configuration: customRulesConfiguration
).skipWrappingInCommentTest()
let configuration = try Configuration(dict: ["custom_rules": customRulesConfiguration])
let violations = violations(example, config: configuration)
XCTAssertEqual(violations.count, 3)
XCTAssertEqual(violations.filter { $0.ruleIdentifier == "superfluous_disable_command" }.count, 2)
XCTAssertEqual(violations.filter { $0.ruleIdentifier == "custom2" }.count, 1)
XCTAssertTrue(violations.contains { violation in
violation.description.contains("SwiftLint rule 'custom1' did not trigger a violation")
})
XCTAssertTrue(violations.contains { violation in
violation.description.contains("SwiftLint rule 'custom3' did not trigger a violation")
})
}
private func getCustomRules(_ extraConfig: [String: Any] = [:]) -> (RegexConfiguration, CustomRules) {
var config: [String: Any] = ["regex": "pattern",
"match_kinds": "comment"]
extraConfig.forEach { config[$0] = $1 }
var regexConfig = RegexConfiguration(identifier: "custom")
do {
try regexConfig.apply(configuration: config)
} catch {
XCTFail("Failed regex config")
}
var customRuleConfiguration = CustomRulesConfiguration()
customRuleConfiguration.customRuleConfigurations = [regexConfig]
var customRules = CustomRules()
customRules.configuration = customRuleConfiguration
return (regexConfig, customRules)
}
private func getCustomRulesWithTwoRules() -> ((RegexConfiguration, RegexConfiguration), CustomRules) {
let config1 = ["regex": "pattern",
"match_kinds": "comment"]
var regexConfig1 = RegexConfiguration(identifier: "custom1")
do {
try regexConfig1.apply(configuration: config1)
} catch {
XCTFail("Failed regex config")
}
let config2 = ["regex": "something",
"match_kinds": "comment"]
var regexConfig2 = RegexConfiguration(identifier: "custom2")
do {
try regexConfig2.apply(configuration: config2)
} catch {
XCTFail("Failed regex config")
}
var customRuleConfiguration = CustomRulesConfiguration()
customRuleConfiguration.customRuleConfigurations = [regexConfig1, regexConfig2]
var customRules = CustomRules()
customRules.configuration = customRuleConfiguration
return ((regexConfig1, regexConfig2), customRules)
}
private func getTestTextFile() -> SwiftLintFile {
return SwiftLintFile(path: "\(testResourcesPath)/test.txt")!
}
}