Skip to content

Commit

Permalink
Add unit tests for the config.
Browse files Browse the repository at this point in the history
  • Loading branch information
temochka committed Apr 6, 2021
1 parent 6b7703b commit 3a2ba8c
Show file tree
Hide file tree
Showing 16 changed files with 2,224 additions and 14 deletions.
141 changes: 141 additions & 0 deletions Anykey.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
objects = {

/* Begin PBXBuildFile section */
C0274BC1261ABDAC00D67214 /* HotkeyConfigTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = C0274BC0261ABDAC00D67214 /* HotkeyConfigTests.swift */; };
C0274BDC261C068100D67214 /* TestConfigs in Resources */ = {isa = PBXBuildFile; fileRef = C0274BDB261C068100D67214 /* TestConfigs */; };
C05B608225DDBC1200B0CECC /* Notifications.swift in Sources */ = {isa = PBXBuildFile; fileRef = C05B608125DDBC1200B0CECC /* Notifications.swift */; };
C05B608725DF28F100B0CECC /* UserDefaults+AnykeySettings.swift in Sources */ = {isa = PBXBuildFile; fileRef = C05B608625DF28F100B0CECC /* UserDefaults+AnykeySettings.swift */; };
C05B609025E5B21200B0CECC /* README.md in Resources */ = {isa = PBXBuildFile; fileRef = C05B608F25E5B21200B0CECC /* README.md */; };
Expand All @@ -23,7 +25,21 @@
C0E386B925D60D3D006D9B7D /* FileWatcher in Frameworks */ = {isa = PBXBuildFile; productRef = C0E386B825D60D3D006D9B7D /* FileWatcher */; };
/* End PBXBuildFile section */

/* Begin PBXContainerItemProxy section */
C0274BB7261ABD6A00D67214 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = C0E3866525D1E60F006D9B7D /* Project object */;
proxyType = 1;
remoteGlobalIDString = C0E3866C25D1E60F006D9B7D;
remoteInfo = Anykey;
};
/* End PBXContainerItemProxy section */

/* Begin PBXFileReference section */
C0274BB2261ABD6A00D67214 /* AnykeyUnitTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = AnykeyUnitTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
C0274BB6261ABD6A00D67214 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
C0274BC0261ABDAC00D67214 /* HotkeyConfigTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HotkeyConfigTests.swift; sourceTree = "<group>"; };
C0274BDB261C068100D67214 /* TestConfigs */ = {isa = PBXFileReference; lastKnownFileType = folder; path = TestConfigs; sourceTree = "<group>"; };
C05B608125DDBC1200B0CECC /* Notifications.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Notifications.swift; sourceTree = "<group>"; };
C05B608625DF28F100B0CECC /* UserDefaults+AnykeySettings.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UserDefaults+AnykeySettings.swift"; sourceTree = "<group>"; };
C05B608F25E5B21200B0CECC /* README.md */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = SOURCE_ROOT; };
Expand All @@ -42,6 +58,13 @@
/* End PBXFileReference section */

/* Begin PBXFrameworksBuildPhase section */
C0274BAF261ABD6A00D67214 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
C0E3866A25D1E60F006D9B7D /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
Expand All @@ -54,10 +77,21 @@
/* End PBXFrameworksBuildPhase section */

/* Begin PBXGroup section */
C0274BB3261ABD6A00D67214 /* AnykeyUnitTests */ = {
isa = PBXGroup;
children = (
C0274BDB261C068100D67214 /* TestConfigs */,
C0274BB6261ABD6A00D67214 /* Info.plist */,
C0274BC0261ABDAC00D67214 /* HotkeyConfigTests.swift */,
);
path = AnykeyUnitTests;
sourceTree = "<group>";
};
C0E3866425D1E60F006D9B7D = {
isa = PBXGroup;
children = (
C0E3866F25D1E60F006D9B7D /* Anykey */,
C0274BB3261ABD6A00D67214 /* AnykeyUnitTests */,
C0E3866E25D1E60F006D9B7D /* Products */,
);
sourceTree = "<group>";
Expand All @@ -66,6 +100,7 @@
isa = PBXGroup;
children = (
C0E3866D25D1E60F006D9B7D /* Anykey.app */,
C0274BB2261ABD6A00D67214 /* AnykeyUnitTests.xctest */,
);
name = Products;
sourceTree = "<group>";
Expand Down Expand Up @@ -102,6 +137,24 @@
/* End PBXGroup section */

/* Begin PBXNativeTarget section */
C0274BB1261ABD6A00D67214 /* AnykeyUnitTests */ = {
isa = PBXNativeTarget;
buildConfigurationList = C0274BBB261ABD6A00D67214 /* Build configuration list for PBXNativeTarget "AnykeyUnitTests" */;
buildPhases = (
C0274BAE261ABD6A00D67214 /* Sources */,
C0274BAF261ABD6A00D67214 /* Frameworks */,
C0274BB0261ABD6A00D67214 /* Resources */,
);
buildRules = (
);
dependencies = (
C0274BB8261ABD6A00D67214 /* PBXTargetDependency */,
);
name = AnykeyUnitTests;
productName = AnykeyUnitTests;
productReference = C0274BB2261ABD6A00D67214 /* AnykeyUnitTests.xctest */;
productType = "com.apple.product-type.bundle.unit-test";
};
C0E3866C25D1E60F006D9B7D /* Anykey */ = {
isa = PBXNativeTarget;
buildConfigurationList = C0E3868025D1E611006D9B7D /* Build configuration list for PBXNativeTarget "Anykey" */;
Expand Down Expand Up @@ -132,6 +185,11 @@
LastSwiftUpdateCheck = 1240;
LastUpgradeCheck = 1240;
TargetAttributes = {
C0274BB1261ABD6A00D67214 = {
CreatedOnToolsVersion = 12.4;
LastSwiftMigration = 1240;
TestTargetID = C0E3866C25D1E60F006D9B7D;
};
C0E3866C25D1E60F006D9B7D = {
CreatedOnToolsVersion = 12.4;
};
Expand All @@ -155,11 +213,20 @@
projectRoot = "";
targets = (
C0E3866C25D1E60F006D9B7D /* Anykey */,
C0274BB1261ABD6A00D67214 /* AnykeyUnitTests */,
);
};
/* End PBXProject section */

/* Begin PBXResourcesBuildPhase section */
C0274BB0261ABD6A00D67214 /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
C0274BDC261C068100D67214 /* TestConfigs in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
C0E3866B25D1E60F006D9B7D /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
Expand All @@ -175,6 +242,14 @@
/* End PBXResourcesBuildPhase section */

/* Begin PBXSourcesBuildPhase section */
C0274BAE261ABD6A00D67214 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
C0274BC1261ABDAC00D67214 /* HotkeyConfigTests.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
C0E3866925D1E60F006D9B7D /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
Expand All @@ -191,7 +266,64 @@
};
/* End PBXSourcesBuildPhase section */

/* Begin PBXTargetDependency section */
C0274BB8261ABD6A00D67214 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = C0E3866C25D1E60F006D9B7D /* Anykey */;
targetProxy = C0274BB7261ABD6A00D67214 /* PBXContainerItemProxy */;
};
/* End PBXTargetDependency section */

/* Begin XCBuildConfiguration section */
C0274BB9261ABD6A00D67214 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
BUNDLE_LOADER = "$(TEST_HOST)";
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_IDENTITY = "-";
CODE_SIGN_INJECT_BASE_ENTITLEMENTS = YES;
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
INFOPLIST_FILE = AnykeyUnitTests/Info.plist;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/../Frameworks",
"@loader_path/../Frameworks",
);
MACOSX_DEPLOYMENT_TARGET = 11.1;
OTHER_CODE_SIGN_FLAGS = "";
PRODUCT_BUNDLE_IDENTIFIER = com.temochka.AnykeyUnitTests;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_VERSION = 5.0;
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Anykey.app/Contents/MacOS/Anykey";
};
name = Debug;
};
C0274BBA261ABD6A00D67214 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
BUNDLE_LOADER = "$(TEST_HOST)";
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_IDENTITY = "-";
CODE_SIGN_INJECT_BASE_ENTITLEMENTS = YES;
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
INFOPLIST_FILE = AnykeyUnitTests/Info.plist;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/../Frameworks",
"@loader_path/../Frameworks",
);
MACOSX_DEPLOYMENT_TARGET = 11.1;
OTHER_CODE_SIGN_FLAGS = "";
PRODUCT_BUNDLE_IDENTIFIER = com.temochka.AnykeyUnitTests;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_VERSION = 5.0;
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Anykey.app/Contents/MacOS/Anykey";
};
name = Release;
};
C0E3867E25D1E611006D9B7D /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
Expand Down Expand Up @@ -358,6 +490,15 @@
/* End XCBuildConfiguration section */

/* Begin XCConfigurationList section */
C0274BBB261ABD6A00D67214 /* Build configuration list for PBXNativeTarget "AnykeyUnitTests" */ = {
isa = XCConfigurationList;
buildConfigurations = (
C0274BB9261ABD6A00D67214 /* Debug */,
C0274BBA261ABD6A00D67214 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
C0E3866825D1E60F006D9B7D /* Build configuration list for PBXProject "Anykey" */ = {
isa = XCConfigurationList;
buildConfigurations = (
Expand Down
10 changes: 10 additions & 0 deletions Anykey.xcodeproj/xcshareddata/xcschemes/Anykey.xcscheme
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,16 @@
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
<TestableReference
skipped = "NO">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "C0274BB1261ABD6A00D67214"
BuildableName = "AnykeyUnitTests.xctest"
BlueprintName = "AnykeyUnitTests"
ReferencedContainer = "container:Anykey.xcodeproj">
</BuildableReference>
</TestableReference>
</Testables>
</TestAction>
<LaunchAction
Expand Down
2 changes: 1 addition & 1 deletion Anykey/AppDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ class AppDelegate: NSObject, NSApplicationDelegate {
private func loadConfig() {
do {
os_log("Reloading hotkey config at %s", log: OSLog.default, type: .debug, self.configPath())
config = try HotkeyConfig(filePath: configPath())
config = try HotkeyConfig(url: URL(fileURLWithPath: configPath()))
} catch let error as ConfigError {
os_log("Error when loading the config at %s", log: OSLog.default, type: .error, self.configPath())
notifications.configError(error: error)
Expand Down
19 changes: 9 additions & 10 deletions Anykey/HotkeyConfig.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import Cocoa
import Foundation
import OSLog

enum ConfigError : Error {
enum ConfigError : Error, Equatable {
case access(String)
case invalid(String)
case unknown(String)
Expand All @@ -20,7 +20,7 @@ extension NSEvent.ModifierFlags : Decodable {
let jsonModifiers = try decoder.singleValueContainer().decode([String].self)

guard !jsonModifiers.isEmpty else {
throw DecodingError.typeMismatch(Self.self, DecodingError.Context(codingPath: decoder.codingPath, debugDescription: "Found an empty array of modifiers"))
throw DecodingError.typeMismatch(Self.self, DecodingError.Context(codingPath: decoder.codingPath, debugDescription: "Found an empty array of modifiers."))
}

self = NSEvent.ModifierFlags(try jsonModifiers.map { mod in
Expand All @@ -36,7 +36,7 @@ extension NSEvent.ModifierFlags : Decodable {
case "fn", "function":
return .function
default:
throw DecodingError.typeMismatch(Self.self, DecodingError.Context(codingPath: decoder.codingPath, debugDescription: "Unknown modifier \(mod)"))
throw DecodingError.typeMismatch(Self.self, DecodingError.Context(codingPath: decoder.codingPath, debugDescription: "Unknown modifier \(mod)."))
}
})
}
Expand All @@ -46,7 +46,7 @@ extension Key : Decodable {
public init(from decoder: Decoder) throws {
let jsonKey = try decoder.singleValueContainer().decode(String.self)
guard let knownKey = Key(string: jsonKey) else {
throw DecodingError.typeMismatch(Self.self, DecodingError.Context(codingPath: decoder.codingPath, debugDescription: "Unknown key \(jsonKey)"))
throw DecodingError.typeMismatch(Self.self, DecodingError.Context(codingPath: decoder.codingPath, debugDescription: "Unknown key \(jsonKey)."))
}
self = knownKey
}
Expand Down Expand Up @@ -81,27 +81,26 @@ struct HotkeyConfig : Decodable {
let workingDirectory: String?
var isEmpty: Bool { hotkeys.isEmpty }

init(filePath: String) throws {
let url = URL(fileURLWithPath: filePath)
init(url: URL) throws {
do {
let data = try Data(contentsOf: url)
let decoder = JSONDecoder()
self = try decoder.decode(HotkeyConfig.self, from: data)
} catch CocoaError.fileNoSuchFile, CocoaError.fileReadNoSuchFile {
throw ConfigError.access("configuration file is missing")
throw ConfigError.access("The specified configuration file is missing.")
} catch CocoaError.fileLocking, CocoaError.fileReadCorruptFile, CocoaError.fileReadNoPermission, CocoaError.fileReadTooLarge {
throw ConfigError.access("couldn’t read from the configuration file")
throw ConfigError.access("Couldn’t read from the configuration file.")
} catch let error as ConfigError {
os_log("Error when loading the config: %s", log: OSLog.default, type: .error, error.localizedDescription)
throw error
} catch DecodingError.keyNotFound(let key, let context) {
os_log("Config parse error: %s", context.debugDescription)
throw ConfigError.invalid("Missing required key \(key.stringValue)")
throw ConfigError.invalid("Missing required key \(key.stringValue).")
} catch DecodingError.valueNotFound(_, let context),
DecodingError.typeMismatch(_, let context),
DecodingError.dataCorrupted(let context) {
os_log("Config parse error: %s", context.debugDescription)
throw ConfigError.invalid("Invalid value for key \(context.codingPath.last?.stringValue ?? ""). \(context.debugDescription)")
throw ConfigError.invalid("Invalid value for \(context.codingPath.last?.stringValue ?? "config root"). \(context.debugDescription)")
} catch {
os_log("Unexpected error %s when loading the config", log: OSLog.default, type: .error, error.localizedDescription)
throw ConfigError.unknown("Unknown error when reading from the configuration file. Please check the log.")
Expand Down
4 changes: 2 additions & 2 deletions Anykey/Key.swift
Original file line number Diff line number Diff line change
Expand Up @@ -199,10 +199,10 @@ public enum Key {
case "minus", "-": self = .minus
case "eight", "8": self = .eight
case "zero", "0": self = .zero
case "rightBracket", "]": self = .rightBracket
case "rightbracket", "]": self = .rightBracket
case "o": self = .o
case "u": self = .u
case "leftBracket", "[": self = .leftBracket
case "leftbracket", "[": self = .leftBracket
case "i": self = .i
case "p": self = .p
case "l": self = .l
Expand Down
2 changes: 1 addition & 1 deletion Anykey/PreferencesView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ struct PreferencesView: View {

dynamic var configStatus: ConfigStatus {
do {
_ = try HotkeyConfig(filePath: NSString(string: self.configPathText).expandingTildeInPath)
_ = try HotkeyConfig(url: URL(fileURLWithPath: NSString(string: self.configPathText).expandingTildeInPath))
return .valid
} catch let error as ConfigError {
switch error {
Expand Down
Loading

0 comments on commit 3a2ba8c

Please sign in to comment.