Skip to content

Commit

Permalink
Add rule parsing tests and make split better
Browse files Browse the repository at this point in the history
  • Loading branch information
grgar committed Oct 20, 2023
1 parent fca40d6 commit e01e109
Show file tree
Hide file tree
Showing 5 changed files with 167 additions and 4 deletions.
117 changes: 117 additions & 0 deletions Passwords Inspector.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
17618B7C2AC200C600B31C28 /* PasswordRules.swift in Sources */ = {isa = PBXBuildFile; fileRef = 17618B7B2AC200C600B31C28 /* PasswordRules.swift */; };
1776885F2AD9D65400F68E88 /* HomeSidebar.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1776885E2AD9D65400F68E88 /* HomeSidebar.swift */; };
17882AC52AC84AAD0037E3A6 /* PasswordRuleDetail.swift in Sources */ = {isa = PBXBuildFile; fileRef = 17882AC42AC84AAD0037E3A6 /* PasswordRuleDetail.swift */; };
17A3A7662ADC8A3E00CF82FD /* Tests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 17A3A7652ADC8A3E00CF82FD /* Tests.swift */; };
17BFF7002ABCDDC2004047AD /* SharedCredentials.swift in Sources */ = {isa = PBXBuildFile; fileRef = 17BFF6FF2ABCDDC2004047AD /* SharedCredentials.swift */; };
17BFF7022ABF217D004047AD /* Favicon.swift in Sources */ = {isa = PBXBuildFile; fileRef = 17BFF7012ABF217D004047AD /* Favicon.swift */; };
17BFF7042ABF7D50004047AD /* Appended2FA.swift in Sources */ = {isa = PBXBuildFile; fileRef = 17BFF7032ABF7D50004047AD /* Appended2FA.swift */; };
Expand Down Expand Up @@ -50,6 +51,13 @@
remoteGlobalIDString = 171459ED2ADB3FCF00E6C111;
remoteInfo = "Passwords Inspector (Watch) Watch App";
};
17A3A7672ADC8A3E00CF82FD /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 1717C4922ABA44EC00AD991A /* Project object */;
proxyType = 1;
remoteGlobalIDString = 1717C4992ABA44EC00AD991A;
remoteInfo = "Passwords Inspector";
};
/* End PBXContainerItemProxy section */

/* Begin PBXCopyFilesBuildPhase section */
Expand Down Expand Up @@ -82,6 +90,8 @@
17618B7B2AC200C600B31C28 /* PasswordRules.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PasswordRules.swift; sourceTree = "<group>"; };
1776885E2AD9D65400F68E88 /* HomeSidebar.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomeSidebar.swift; sourceTree = "<group>"; };
17882AC42AC84AAD0037E3A6 /* PasswordRuleDetail.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PasswordRuleDetail.swift; sourceTree = "<group>"; };
17A3A7632ADC8A3E00CF82FD /* Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = Tests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
17A3A7652ADC8A3E00CF82FD /* Tests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Tests.swift; sourceTree = "<group>"; };
17BFF6FF2ABCDDC2004047AD /* SharedCredentials.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SharedCredentials.swift; sourceTree = "<group>"; };
17BFF7012ABF217D004047AD /* Favicon.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Favicon.swift; sourceTree = "<group>"; };
17BFF7032ABF7D50004047AD /* Appended2FA.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Appended2FA.swift; sourceTree = "<group>"; };
Expand All @@ -105,6 +115,13 @@
);
runOnlyForDeploymentPostprocessing = 0;
};
17A3A7602ADC8A3E00CF82FD /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */

/* Begin PBXGroup section */
Expand All @@ -121,6 +138,7 @@
1717C4A32ABA44ED00AD991A /* PI.entitlements */,
1748409A2AD4A73C00EB9592 /* Info.plist */,
174840982AD49A3E00EB9592 /* Settings.bundle */,
17A3A7642ADC8A3E00CF82FD /* Tests */,
1717C49B2ABA44EC00AD991A /* Products */,
);
sourceTree = "<group>";
Expand All @@ -130,6 +148,7 @@
children = (
1717C49A2ABA44EC00AD991A /* Passwords Inspector.app */,
171459EE2ADB3FCF00E6C111 /* Passwords Inspector.app */,
17A3A7632ADC8A3E00CF82FD /* Tests.xctest */,
);
name = Products;
sourceTree = "<group>";
Expand Down Expand Up @@ -167,6 +186,14 @@
path = Domains;
sourceTree = "<group>";
};
17A3A7642ADC8A3E00CF82FD /* Tests */ = {
isa = PBXGroup;
children = (
17A3A7652ADC8A3E00CF82FD /* Tests.swift */,
);
path = Tests;
sourceTree = "<group>";
};
/* End PBXGroup section */

/* Begin PBXNativeTarget section */
Expand Down Expand Up @@ -206,6 +233,24 @@
productReference = 1717C49A2ABA44EC00AD991A /* Passwords Inspector.app */;
productType = "com.apple.product-type.application";
};
17A3A7622ADC8A3E00CF82FD /* Tests */ = {
isa = PBXNativeTarget;
buildConfigurationList = 17A3A76B2ADC8A3E00CF82FD /* Build configuration list for PBXNativeTarget "Tests" */;
buildPhases = (
17A3A75F2ADC8A3E00CF82FD /* Sources */,
17A3A7602ADC8A3E00CF82FD /* Frameworks */,
17A3A7612ADC8A3E00CF82FD /* Resources */,
);
buildRules = (
);
dependencies = (
17A3A7682ADC8A3E00CF82FD /* PBXTargetDependency */,
);
name = Tests;
productName = Tests;
productReference = 17A3A7632ADC8A3E00CF82FD /* Tests.xctest */;
productType = "com.apple.product-type.bundle.unit-test";
};
/* End PBXNativeTarget section */

/* Begin PBXProject section */
Expand All @@ -222,6 +267,10 @@
1717C4992ABA44EC00AD991A = {
CreatedOnToolsVersion = 15.0;
};
17A3A7622ADC8A3E00CF82FD = {
CreatedOnToolsVersion = 15.0.1;
TestTargetID = 1717C4992ABA44EC00AD991A;
};
};
};
buildConfigurationList = 1717C4952ABA44EC00AD991A /* Build configuration list for PBXProject "Passwords Inspector" */;
Expand All @@ -239,6 +288,7 @@
targets = (
1717C4992ABA44EC00AD991A /* Passwords Inspector */,
171459ED2ADB3FCF00E6C111 /* Watch App */,
17A3A7622ADC8A3E00CF82FD /* Tests */,
);
};
/* End PBXProject section */
Expand All @@ -261,6 +311,13 @@
);
runOnlyForDeploymentPostprocessing = 0;
};
17A3A7612ADC8A3E00CF82FD /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXResourcesBuildPhase section */

/* Begin PBXSourcesBuildPhase section */
Expand Down Expand Up @@ -307,6 +364,14 @@
);
runOnlyForDeploymentPostprocessing = 0;
};
17A3A75F2ADC8A3E00CF82FD /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
17A3A7662ADC8A3E00CF82FD /* Tests.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */

/* Begin PBXTargetDependency section */
Expand All @@ -316,6 +381,11 @@
target = 171459ED2ADB3FCF00E6C111 /* Watch App */;
targetProxy = 171459F92ADB3FD000E6C111 /* PBXContainerItemProxy */;
};
17A3A7682ADC8A3E00CF82FD /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = 1717C4992ABA44EC00AD991A /* Passwords Inspector */;
targetProxy = 17A3A7672ADC8A3E00CF82FD /* PBXContainerItemProxy */;
};
/* End PBXTargetDependency section */

/* Begin XCBuildConfiguration section */
Expand Down Expand Up @@ -580,6 +650,44 @@
};
name = Release;
};
17A3A7692ADC8A3E00CF82FD /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
BUNDLE_LOADER = "$(TEST_HOST)";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
DEVELOPMENT_TEAM = 5TFUK958NL;
GENERATE_INFOPLIST_FILE = YES;
MACOSX_DEPLOYMENT_TARGET = 14.0;
MARKETING_VERSION = 1.0;
PRODUCT_BUNDLE_IDENTIFIER = com.georgegarside.passwordsinspector.tests;
PRODUCT_NAME = "$(TARGET_NAME)";
SDKROOT = macosx;
SWIFT_EMIT_LOC_STRINGS = NO;
SWIFT_VERSION = 5.0;
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Passwords Inspector.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Passwords Inspector";
};
name = Debug;
};
17A3A76A2ADC8A3E00CF82FD /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
BUNDLE_LOADER = "$(TEST_HOST)";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
DEVELOPMENT_TEAM = 5TFUK958NL;
GENERATE_INFOPLIST_FILE = YES;
MACOSX_DEPLOYMENT_TARGET = 14.0;
MARKETING_VERSION = 1.0;
PRODUCT_BUNDLE_IDENTIFIER = com.georgegarside.passwordsinspector.tests;
PRODUCT_NAME = "$(TARGET_NAME)";
SDKROOT = macosx;
SWIFT_EMIT_LOC_STRINGS = NO;
SWIFT_VERSION = 5.0;
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Passwords Inspector.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Passwords Inspector";
};
name = Release;
};
/* End XCBuildConfiguration section */

/* Begin XCConfigurationList section */
Expand Down Expand Up @@ -610,6 +718,15 @@
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
17A3A76B2ADC8A3E00CF82FD /* Build configuration list for PBXNativeTarget "Tests" */ = {
isa = XCConfigurationList;
buildConfigurations = (
17A3A7692ADC8A3E00CF82FD /* Debug */,
17A3A76A2ADC8A3E00CF82FD /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
};
rootObject = 1717C4922ABA44EC00AD991A /* Project object */;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,19 @@
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES"
shouldAutocreateTestPlan = "YES">
<Testables>
<TestableReference
skipped = "NO"
parallelizable = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "17A3A7622ADC8A3E00CF82FD"
BuildableName = "Tests.xctest"
BlueprintName = "Tests"
ReferencedContainer = "container:Passwords Inspector.xcodeproj">
</BuildableReference>
</TestableReference>
</Testables>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,19 @@
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES"
shouldAutocreateTestPlan = "YES">
<Testables>
<TestableReference
skipped = "NO"
parallelizable = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "17A3A7622ADC8A3E00CF82FD"
BuildableName = "Tests.xctest"
BlueprintName = "Tests"
ReferencedContainer = "container:Passwords Inspector.xcodeproj">
</BuildableReference>
</TestableReference>
</Testables>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
Expand Down
9 changes: 5 additions & 4 deletions Rule/Rule.swift
Original file line number Diff line number Diff line change
Expand Up @@ -87,22 +87,23 @@ struct Rule: Identifiable, Hashable {
extension Rule {
init(domain: String, rule originalRule: String) {
self = Self(id: domain, originalRule: originalRule)
for split in originalRule.split(separator: /;(?: |$)/, omittingEmptySubsequences: true) {
let split = String(split).split(separator: /: ?/, maxSplits: 1)
// TODO: Fix regex if character set contains one bracket without the other
for split in originalRule.split(separator: /; ?(?=(?:[^\[\]]*[\[\]][^\[\]]*[\[\]])*[^\[\]]*$)/, omittingEmptySubsequences: true) {
let split = String(split).split(separator: /: ?(?=(?:[^\[\]]*[\[\]][^\[\]]*[\[\]])*[^\[\]]*$)/, maxSplits: 1)
if split.count != 2 { continue }
switch split[0] {
case "minlength":
self.minLength = Int(split[1].trimmingCharacters(in: .punctuationCharacters))
case "maxlength":
self.maxLength = Int(split[1].trimmingCharacters(in: .punctuationCharacters))
case "required":
for set in String(split[1]).split(separator: /, ?(?![^\[]*\])/) {
for set in String(split[1]).split(separator: /, ?(?=(?:[^\[\]]*[\[\]][^\[\]]*[\[\]])*[^\[\]]*$)/) {
if let set = PasswordCharacter(String(set)) {
self.required.insert(set)
}
}
case "allowed":
for set in String(split[1]).split(separator: /, ?(?![^\[]*\])/) {
for set in String(split[1]).split(separator: /, ?(?=(?:[^\[\]]*[\[\]][^\[\]]*[\[\]])*[^\[\]]*$)/) {
if let set = PasswordCharacter(String(set)) {
self.allowed.insert(set)
}
Expand Down
19 changes: 19 additions & 0 deletions Tests/Tests.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
@testable import Passwords_Inspector
import XCTest

final class Tests: XCTestCase {
func testRuleParse1() throws {
let rule = Rule(domain: "admiral.com", rule: "minlength: 8; required: digit; required: [- !\"#$&'()*+,.:;<=>?@[^_`{|}~]]; allowed: lower, upper;")
XCTAssertEqual(rule.minLength, .some(8), "minLength")
XCTAssertEqual(rule.maxLength, nil, "maxLength")
XCTAssertEqual(rule.required, Set<Rule.PasswordCharacter>(arrayLiteral: .digit, .other(.init("- !\"#$&'()*+,.:;<=>?@[^_`{|}~]"))))
XCTAssertEqual(rule.allowed, Set<Rule.PasswordCharacter>(arrayLiteral: .lower, .upper))
}
func testRuleParse2() throws {
let rule = Rule(domain: "hotels.com", rule: "minlength: 6; maxlength: 20; required: digit; allowed: lower, upper, [@$!#()&^*%];")
XCTAssertEqual(rule.minLength, .some(6), "minLength")
XCTAssertEqual(rule.maxLength, .some(20), "maxLength")
XCTAssertEqual(rule.required, Set<Rule.PasswordCharacter>(arrayLiteral: .digit))
XCTAssertEqual(rule.allowed, Set<Rule.PasswordCharacter>(arrayLiteral: .lower, .upper, .other(.init("@$!#()&^*%"))))
}
}

0 comments on commit e01e109

Please sign in to comment.