289 lines
12 KiB
Swift
289 lines
12 KiB
Swift
import Foundation
|
|
import SourceKittenFramework
|
|
@testable import SwiftLintFramework
|
|
import XCTest
|
|
|
|
private let optInRules = masterRuleList.list.filter({ $0.1.init() is OptInRule }).map({ $0.0 })
|
|
|
|
private extension Configuration {
|
|
var disabledRules: [String] {
|
|
let configuredRuleIDs = rules.map({ type(of: $0).description.identifier })
|
|
let defaultRuleIDs = Set(masterRuleList.list.values.filter({
|
|
!($0.init() is OptInRule)
|
|
}).map({ $0.description.identifier }))
|
|
return defaultRuleIDs.subtracting(configuredRuleIDs).sorted(by: <)
|
|
}
|
|
}
|
|
|
|
class ConfigurationTests: XCTestCase {
|
|
|
|
func testInit() {
|
|
XCTAssert(Configuration(dict: [:]) != nil,
|
|
"initializing Configuration with empty Dictionary should succeed")
|
|
XCTAssert(Configuration(dict: ["a": 1, "b": 2]) != nil,
|
|
"initializing Configuration with valid Dictionary should succeed")
|
|
}
|
|
|
|
func testEmptyConfiguration() {
|
|
guard let config = Configuration(dict: [:]) else {
|
|
XCTFail("empty YAML string should yield non-nil Configuration")
|
|
return
|
|
}
|
|
XCTAssertEqual(config.disabledRules, [])
|
|
XCTAssertEqual(config.included, [])
|
|
XCTAssertEqual(config.excluded, [])
|
|
XCTAssertEqual(config.indentation, .spaces(count: 4))
|
|
XCTAssertEqual(config.reporter, "xcode")
|
|
XCTAssertEqual(reporterFrom(identifier: config.reporter).identifier, "xcode")
|
|
}
|
|
|
|
func testInitWithRelativePathAndRootPath() {
|
|
let previousWorkingDir = FileManager.default.currentDirectoryPath
|
|
let rootPath = projectMockSwift0
|
|
let expectedConfig = projectMockConfig0
|
|
FileManager.default.changeCurrentDirectoryPath(projectMockPathLevel0)
|
|
|
|
let config = Configuration(path: ".swiftlint.yml", rootPath: rootPath,
|
|
optional: false, quiet: true)
|
|
|
|
XCTAssertEqual(config.disabledRules, expectedConfig.disabledRules)
|
|
XCTAssertEqual(config.included, expectedConfig.included)
|
|
XCTAssertEqual(config.excluded, expectedConfig.excluded)
|
|
XCTAssertEqual(config.indentation, expectedConfig.indentation)
|
|
XCTAssertEqual(config.reporter, expectedConfig.reporter)
|
|
|
|
FileManager.default.changeCurrentDirectoryPath(previousWorkingDir)
|
|
}
|
|
|
|
func testEnableAllRulesConfiguration() {
|
|
let configuration = Configuration(dict: [:], ruleList: masterRuleList, enableAllRules: true, cachePath: nil)!
|
|
XCTAssertEqual(configuration.rules.count, masterRuleList.list.count)
|
|
}
|
|
|
|
func testWhitelistRules() {
|
|
let whitelist = ["nesting", "todo"]
|
|
let config = Configuration(dict: ["whitelist_rules": whitelist])!
|
|
let configuredIdentifiers = config.rules.map {
|
|
type(of: $0).description.identifier
|
|
}.sorted()
|
|
XCTAssertEqual(whitelist, configuredIdentifiers)
|
|
}
|
|
|
|
func testWarningThreshold_value() {
|
|
let config = Configuration(dict: ["warning_threshold": 5])!
|
|
XCTAssertEqual(config.warningThreshold, 5)
|
|
}
|
|
|
|
func testWarningThreshold_nil() {
|
|
let config = Configuration(dict: [:])!
|
|
XCTAssertEqual(config.warningThreshold, nil)
|
|
}
|
|
|
|
func testOtherRuleConfigurationsAlongsideWhitelistRules() {
|
|
let whitelist = ["nesting", "todo"]
|
|
let enabledRulesConfigDict = [
|
|
"opt_in_rules": ["line_length"],
|
|
"whitelist_rules": whitelist
|
|
]
|
|
let disabledRulesConfigDict = [
|
|
"disabled_rules": ["identifier_name"],
|
|
"whitelist_rules": whitelist
|
|
]
|
|
let combinedRulesConfigDict = enabledRulesConfigDict.reduce(into: disabledRulesConfigDict) { $0[$1.0] = $1.1 }
|
|
var configuration = Configuration(dict: enabledRulesConfigDict)
|
|
XCTAssertNil(configuration)
|
|
configuration = Configuration(dict: disabledRulesConfigDict)
|
|
XCTAssertNil(configuration)
|
|
configuration = Configuration(dict: combinedRulesConfigDict)
|
|
XCTAssertNil(configuration)
|
|
}
|
|
|
|
func testDisabledRules() {
|
|
let disabledConfig = Configuration(dict: ["disabled_rules": ["nesting", "todo"]])!
|
|
XCTAssertEqual(disabledConfig.disabledRules,
|
|
["nesting", "todo"],
|
|
"initializing Configuration with valid rules in Dictionary should succeed")
|
|
let expectedIdentifiers = Set(masterRuleList.list.keys
|
|
.filter({ !(["nesting", "todo"] + optInRules).contains($0) }))
|
|
let configuredIdentifiers = Set(disabledConfig.rules.map {
|
|
type(of: $0).description.identifier
|
|
})
|
|
XCTAssertEqual(expectedIdentifiers, configuredIdentifiers)
|
|
}
|
|
|
|
func testDisabledRulesWithUnknownRule() {
|
|
let validRule = "nesting"
|
|
let bogusRule = "no_sprites_with_elf_shoes"
|
|
let configuration = Configuration(dict: ["disabled_rules": [validRule, bogusRule]])!
|
|
|
|
XCTAssertEqual(configuration.disabledRules,
|
|
[validRule],
|
|
"initializing Configuration with valid rules in YAML string should succeed")
|
|
let expectedIdentifiers = Set(masterRuleList.list.keys
|
|
.filter({ !([validRule] + optInRules).contains($0) }))
|
|
let configuredIdentifiers = Set(configuration.rules.map {
|
|
type(of: $0).description.identifier
|
|
})
|
|
XCTAssertEqual(expectedIdentifiers, configuredIdentifiers)
|
|
}
|
|
|
|
func testDuplicatedRules() {
|
|
let duplicateConfig1 = Configuration(dict: ["whitelist_rules": ["todo", "todo"]])
|
|
XCTAssertNil(duplicateConfig1, "initializing Configuration with duplicate rules in " +
|
|
"Dictionary should fail")
|
|
|
|
let duplicateConfig2 = Configuration(dict: ["opt_in_rules": [optInRules.first!, optInRules.first!]])
|
|
XCTAssertNil(duplicateConfig2, "initializing Configuration with duplicate rules in " +
|
|
"Dictionary should fail")
|
|
|
|
let duplicateConfig3 = Configuration(dict: ["disabled_rules": ["todo", "todo"]])
|
|
XCTAssertNil(duplicateConfig3, "initializing Configuration with duplicate rules in " +
|
|
"Dictionary should fail")
|
|
}
|
|
|
|
private class TestFileManager: LintableFileManager {
|
|
func filesToLint(inPath path: String, rootDirectory: String? = nil) -> [String] {
|
|
switch path {
|
|
case "directory": return ["directory/File1.swift", "directory/File2.swift",
|
|
"directory/excluded/Excluded.swift",
|
|
"directory/ExcludedFile.swift"]
|
|
case "directory/excluded" : return ["directory/excluded/Excluded.swift"]
|
|
case "directory/ExcludedFile.swift" : return ["directory/ExcludedFile.swift"]
|
|
default: break
|
|
}
|
|
XCTFail("Should not be called with path \(path)")
|
|
return []
|
|
}
|
|
|
|
func modificationDate(forFileAtPath path: String) -> Date? {
|
|
return nil
|
|
}
|
|
}
|
|
|
|
func testExcludedPaths() {
|
|
let configuration = Configuration(included: ["directory"],
|
|
excluded: ["directory/excluded",
|
|
"directory/ExcludedFile.swift"])!
|
|
let paths = configuration.lintablePaths(inPath: "", forceExclude: false, fileManager: TestFileManager())
|
|
XCTAssertEqual(["directory/File1.swift", "directory/File2.swift"], paths)
|
|
}
|
|
|
|
func testForceExcludesFile() {
|
|
let configuration = Configuration(excluded: ["directory/ExcludedFile.swift"])!
|
|
let paths = configuration.lintablePaths(inPath: "directory/ExcludedFile.swift", forceExclude: true,
|
|
fileManager: TestFileManager())
|
|
XCTAssertEqual([], paths)
|
|
}
|
|
|
|
func testForceExcludesFileNotPresentInExcluded() {
|
|
let configuration = Configuration(included: ["directory"],
|
|
excluded: ["directory/ExcludedFile.swift", "directory/excluded"])!
|
|
let paths = configuration.lintablePaths(inPath: "", forceExclude: true, fileManager: TestFileManager())
|
|
XCTAssertEqual(["directory/File1.swift", "directory/File2.swift"], paths)
|
|
}
|
|
|
|
func testForceExcludesDirectory() {
|
|
let configuration = Configuration(excluded: ["directory/excluded", "directory/ExcludedFile.swift"])!
|
|
let paths = configuration.lintablePaths(inPath: "directory", forceExclude: true,
|
|
fileManager: TestFileManager())
|
|
XCTAssertEqual(["directory/File1.swift", "directory/File2.swift"], paths)
|
|
}
|
|
|
|
func testForceExcludesDirectoryThatIsNotInExcludedButHasChildrenThatAre() {
|
|
let configuration = Configuration(excluded: ["directory/excluded", "directory/ExcludedFile.swift"])!
|
|
let paths = configuration.lintablePaths(inPath: "directory", forceExclude: true,
|
|
fileManager: TestFileManager())
|
|
XCTAssertEqual(["directory/File1.swift", "directory/File2.swift"], paths)
|
|
}
|
|
|
|
func testLintablePaths() {
|
|
let paths = Configuration()!.lintablePaths(inPath: projectMockPathLevel0, forceExclude: false)
|
|
let filenames = paths.map { $0.bridge().lastPathComponent }.sorted()
|
|
let expectedFilenames = [
|
|
"DirectoryLevel1.swift",
|
|
"Level0.swift",
|
|
"Level1.swift",
|
|
"Level2.swift",
|
|
"Level3.swift"
|
|
]
|
|
|
|
XCTAssertEqual(expectedFilenames, filenames)
|
|
}
|
|
|
|
func testGlobExcludePaths() {
|
|
let configuration = Configuration(
|
|
included: [projectMockPathLevel3],
|
|
excluded: [projectMockPathLevel3.stringByAppendingPathComponent("*.swift")])!
|
|
|
|
XCTAssertEqual(configuration.lintablePaths(inPath: "", forceExclude: false), [])
|
|
}
|
|
|
|
// MARK: - Testing Configuration Equality
|
|
|
|
func testIsEqualTo() {
|
|
XCTAssertEqual(projectMockConfig0, projectMockConfig0)
|
|
}
|
|
|
|
func testIsNotEqualTo() {
|
|
XCTAssertNotEqual(projectMockConfig0, projectMockConfig2)
|
|
}
|
|
|
|
// MARK: - Testing Custom Configuration File
|
|
|
|
func testCustomConfiguration() {
|
|
let file = File(path: projectMockSwift0)!
|
|
XCTAssertNotEqual(projectMockConfig0.configuration(for: file),
|
|
projectMockConfig0CustomPath.configuration(for: file))
|
|
}
|
|
|
|
func testConfigurationWithSwiftFileAsRoot() {
|
|
let configuration = Configuration(path: projectMockYAML0,
|
|
rootPath: projectMockSwift0,
|
|
optional: false, quiet: true)
|
|
let file = File(path: projectMockSwift0)!
|
|
XCTAssertEqual(configuration.configuration(for: file), configuration)
|
|
}
|
|
|
|
func testConfigurationWithSwiftFileAsRootAndCustomConfiguration() {
|
|
let configuration = Configuration(path: projectMockYAML0CustomPath,
|
|
rootPath: projectMockSwift0,
|
|
optional: false, quiet: true)
|
|
let file = File(path: projectMockSwift0)!
|
|
XCTAssertEqual(configuration.configuration(for: file), configuration)
|
|
}
|
|
|
|
// MARK: - Testing custom indentation
|
|
|
|
func testIndentationTabs() {
|
|
let configuration = Configuration(dict: ["indentation": "tabs"])!
|
|
XCTAssertEqual(configuration.indentation, .tabs)
|
|
}
|
|
|
|
func testIndentationSpaces() {
|
|
let configuration = Configuration(dict: ["indentation": 2])!
|
|
XCTAssertEqual(configuration.indentation, .spaces(count: 2))
|
|
}
|
|
|
|
func testIndentationFallback() {
|
|
let configuration = Configuration(dict: ["indentation": "invalid"])!
|
|
XCTAssertEqual(configuration.indentation, .spaces(count: 4))
|
|
}
|
|
|
|
// MARK: - Testing Rules from config dictionary
|
|
|
|
let testRuleList = RuleList(rules: RuleWithLevelsMock.self)
|
|
|
|
func testConfiguresCorrectlyFromDict() throws {
|
|
let ruleConfiguration = [1, 2]
|
|
let config = [RuleWithLevelsMock.description.identifier: ruleConfiguration]
|
|
let rules = try testRuleList.configuredRules(with: config)
|
|
XCTAssertTrue(rules == [try RuleWithLevelsMock(configuration: ruleConfiguration)])
|
|
}
|
|
|
|
func testConfigureFallsBackCorrectly() throws {
|
|
let config = [RuleWithLevelsMock.description.identifier: ["a", "b"]]
|
|
let rules = try testRuleList.configuredRules(with: config)
|
|
XCTAssertTrue(rules == [RuleWithLevelsMock()])
|
|
}
|
|
}
|