Browse Source

Add tests

Kishikawa Katsumi 5 years ago
parent
commit
046b2c7e95
2 changed files with 101 additions and 38 deletions
  1. 18 38
      Lib/KeychainAccess/Keychain.swift
  2. 83 0
      Lib/KeychainAccessTests/KeychainAccessTests.swift

+ 18 - 38
Lib/KeychainAccess/Keychain.swift

@@ -511,24 +511,12 @@ public final class Keychain {
 
 
     // MARK:
     // MARK:
 
 
-    public func get(_ key: String) throws -> String? {
-        return try getString(key, exactly: false)
+    public func get(_ key: String, ignoringAttributeSynchronizable: Bool = true) throws -> String? {
+        return try getString(key, ignoringAttributeSynchronizable: ignoringAttributeSynchronizable)
     }
     }
 
 
-    public func get(exactly key: String) throws -> String? {
-        return try getString(key, exactly: true)
-    }
-
-    public func getString(_ key: String) throws -> String? {
-        return try getString(key, exactly: false)
-    }
-
-    public func getString(exactly key: String) throws -> String? {
-        return try getString(key, exactly: true)
-    }
-
-    private func getString(_ key: String, exactly: Bool = false) throws -> String? {
-        guard let data = try getData(key, exactly: exactly) else  {
+    public func getString(_ key: String, ignoringAttributeSynchronizable: Bool = true) throws -> String? {
+        guard let data = try getData(key, ignoringAttributeSynchronizable: ignoringAttributeSynchronizable) else  {
             return nil
             return nil
         }
         }
         guard let string = String(data: data, encoding: .utf8) else {
         guard let string = String(data: data, encoding: .utf8) else {
@@ -538,16 +526,8 @@ public final class Keychain {
         return string
         return string
     }
     }
 
 
-    public func getData(_ key: String) throws -> Data? {
-        return try getData(key, exactly: false)
-    }
-
-    public func getData(exactly key: String) throws -> Data? {
-        return try getData(key, exactly: true)
-    }
-
-    private func getData(_ key: String, exactly: Bool = false) throws -> Data? {
-        var query = options.query(exactly: exactly)
+    public func getData(_ key: String, ignoringAttributeSynchronizable: Bool = true) throws -> Data? {
+        var query = options.query(ignoringAttributeSynchronizable: ignoringAttributeSynchronizable)
 
 
         query[MatchLimit] = MatchLimitOne
         query[MatchLimit] = MatchLimitOne
         query[ReturnData] = kCFBooleanTrue
         query[ReturnData] = kCFBooleanTrue
@@ -570,8 +550,8 @@ public final class Keychain {
         }
         }
     }
     }
 
 
-    public func get<T>(_ key: String, handler: (Attributes?) -> T) throws -> T {
-        var query = options.query()
+    public func get<T>(_ key: String, ignoringAttributeSynchronizable: Bool = true, handler: (Attributes?) -> T) throws -> T {
+        var query = options.query(ignoringAttributeSynchronizable: ignoringAttributeSynchronizable)
 
 
         query[MatchLimit] = MatchLimitOne
         query[MatchLimit] = MatchLimitOne
 
 
@@ -600,16 +580,16 @@ public final class Keychain {
 
 
     // MARK:
     // MARK:
 
 
-    public func set(_ value: String, key: String) throws {
+    public func set(_ value: String, key: String, ignoringAttributeSynchronizable: Bool = true) throws {
         guard let data = value.data(using: .utf8, allowLossyConversion: false) else {
         guard let data = value.data(using: .utf8, allowLossyConversion: false) else {
             print("failed to convert string to data")
             print("failed to convert string to data")
             throw Status.conversionError
             throw Status.conversionError
         }
         }
-        try set(data, key: key)
+        try set(data, key: key, ignoringAttributeSynchronizable: ignoringAttributeSynchronizable)
     }
     }
 
 
-    public func set(_ value: Data, key: String) throws {
-        var query = options.query()
+    public func set(_ value: Data, key: String, ignoringAttributeSynchronizable: Bool = true) throws {
+        var query = options.query(ignoringAttributeSynchronizable: ignoringAttributeSynchronizable)
         query[AttributeAccount] = key
         query[AttributeAccount] = key
         #if os(iOS)
         #if os(iOS)
         if #available(iOS 9.0, *) {
         if #available(iOS 9.0, *) {
@@ -738,8 +718,8 @@ public final class Keychain {
 
 
     // MARK:
     // MARK:
 
 
-    public func remove(_ key: String) throws {
-        var query = options.query()
+    public func remove(_ key: String, ignoringAttributeSynchronizable: Bool = true) throws {
+        var query = options.query(ignoringAttributeSynchronizable: ignoringAttributeSynchronizable)
         query[AttributeAccount] = key
         query[AttributeAccount] = key
 
 
         let status = SecItemDelete(query as CFDictionary)
         let status = SecItemDelete(query as CFDictionary)
@@ -1219,17 +1199,17 @@ extension Keychain: CustomStringConvertible, CustomDebugStringConvertible {
 
 
 extension Options {
 extension Options {
 
 
-    func query(exactly: Bool = false) -> [String: Any] {
+    func query(ignoringAttributeSynchronizable: Bool = true) -> [String: Any] {
         var query = [String: Any]()
         var query = [String: Any]()
 
 
         query[Class] = itemClass.rawValue
         query[Class] = itemClass.rawValue
         if let accessGroup = self.accessGroup {
         if let accessGroup = self.accessGroup {
             query[AttributeAccessGroup] = accessGroup
             query[AttributeAccessGroup] = accessGroup
         }
         }
-        if exactly {
-            query[AttributeSynchronizable] = attributes[AttributeSynchronizable] ?? SynchronizableAny
-        } else {
+        if ignoringAttributeSynchronizable {
             query[AttributeSynchronizable] = SynchronizableAny
             query[AttributeSynchronizable] = SynchronizableAny
+        } else {
+            query[AttributeSynchronizable] = synchronizable ? kCFBooleanTrue : kCFBooleanFalse
         }
         }
 
 
         switch itemClass {
         switch itemClass {

+ 83 - 0
Lib/KeychainAccessTests/KeychainAccessTests.swift

@@ -1618,4 +1618,87 @@ class KeychainAccessTests: XCTestCase {
         }
         }
         #endif
         #endif
     }
     }
+
+    func testIgnoringAttributeSynchronizable() {
+        let keychain = Keychain(service: "Twitter").synchronizable(false)
+        let keychainSynchronizable = Keychain(service: "Twitter").synchronizable(true)
+
+        XCTAssertNil(try! keychain.get("username", ignoringAttributeSynchronizable: false), "not stored username")
+        XCTAssertNil(try! keychain.get("password", ignoringAttributeSynchronizable: false), "not stored password")
+        XCTAssertNil(try! keychainSynchronizable.get("username", ignoringAttributeSynchronizable: false), "not stored username")
+        XCTAssertNil(try! keychainSynchronizable.get("password", ignoringAttributeSynchronizable: false), "not stored password")
+
+        do { try keychain.set("kishikawakatsumi", key: "username", ignoringAttributeSynchronizable: false) } catch {}
+        do { try keychainSynchronizable.set("kishikawakatsumi_synchronizable", key: "username", ignoringAttributeSynchronizable: false) } catch {}
+        XCTAssertEqual(try! keychain.get("username", ignoringAttributeSynchronizable: false), "kishikawakatsumi", "stored username")
+        XCTAssertEqual(try! keychainSynchronizable.get("username", ignoringAttributeSynchronizable: false), "kishikawakatsumi_synchronizable", "stored username")
+        XCTAssertNil(try! keychain.get("password", ignoringAttributeSynchronizable: false), "not stored password")
+        XCTAssertNil(try! keychainSynchronizable.get("password", ignoringAttributeSynchronizable: false), "not stored password")
+
+        do { try keychain.set("password1234", key: "password", ignoringAttributeSynchronizable: false) } catch {}
+        do { try keychainSynchronizable.set("password1234_synchronizable", key: "password", ignoringAttributeSynchronizable: false) } catch {}
+        XCTAssertEqual(try! keychain.get("username", ignoringAttributeSynchronizable: false), "kishikawakatsumi", "stored username")
+        XCTAssertEqual(try! keychainSynchronizable.get("username", ignoringAttributeSynchronizable: false), "kishikawakatsumi_synchronizable", "stored username")
+        XCTAssertEqual(try! keychain.get("password", ignoringAttributeSynchronizable: false), "password1234", "stored password")
+        XCTAssertEqual(try! keychainSynchronizable.get("password", ignoringAttributeSynchronizable: false), "password1234_synchronizable", "stored password")
+
+        do { try keychain.remove("username", ignoringAttributeSynchronizable: false) } catch {}
+        XCTAssertNil(try! keychain.get("username", ignoringAttributeSynchronizable: false), "not stored username")
+        XCTAssertEqual(try! keychainSynchronizable.get("username", ignoringAttributeSynchronizable: false), "kishikawakatsumi_synchronizable", "stored username")
+
+        do { try keychainSynchronizable.remove("username", ignoringAttributeSynchronizable: false) } catch {}
+        XCTAssertNil(try! keychain.get("username", ignoringAttributeSynchronizable: false), "not stored username")
+        XCTAssertNil(try! keychainSynchronizable.get("username", ignoringAttributeSynchronizable: false), "not stored username")
+        
+        XCTAssertEqual(try! keychain.get("password", ignoringAttributeSynchronizable: false), "password1234", "stored password")
+        XCTAssertEqual(try! keychainSynchronizable.get("password", ignoringAttributeSynchronizable: false), "password1234_synchronizable", "stored password")
+
+        do { try keychain.removeAll() } catch {}
+        XCTAssertNil(try! keychain.get("username", ignoringAttributeSynchronizable: false), "not stored username")
+        XCTAssertNil(try! keychainSynchronizable.get("username", ignoringAttributeSynchronizable: false), "not stored username")
+        XCTAssertNil(try! keychain.get("password", ignoringAttributeSynchronizable: false), "not stored password")
+        XCTAssertNil(try! keychainSynchronizable.get("password", ignoringAttributeSynchronizable: false), "not stored password")
+    }
+
+    func testIgnoringAttributeSynchronizableBackwardCompatibility() {
+        let keychain = Keychain(service: "Twitter").synchronizable(false)
+        let keychainSynchronizable = Keychain(service: "Twitter").synchronizable(true)
+
+        XCTAssertNil(try! keychain.get("username"), "not stored username")
+        XCTAssertNil(try! keychain.get("password"), "not stored password")
+        XCTAssertNil(try! keychainSynchronizable.get("username"), "not stored username")
+        XCTAssertNil(try! keychainSynchronizable.get("password"), "not stored password")
+
+        do { try keychain.set("kishikawakatsumi", key: "username") } catch {}
+        XCTAssertEqual(try! keychain.get("username"), "kishikawakatsumi", "stored username")
+        XCTAssertEqual(try! keychainSynchronizable.get("username"), "kishikawakatsumi", "stored username")
+
+        do { try keychainSynchronizable.set("kishikawakatsumi_synchronizable", key: "username") } catch {}
+        XCTAssertEqual(try! keychain.get("username"), "kishikawakatsumi_synchronizable", "stored username")
+        XCTAssertEqual(try! keychainSynchronizable.get("username"), "kishikawakatsumi_synchronizable", "stored username")
+        XCTAssertNil(try! keychain.get("password"), "not stored password")
+        XCTAssertNil(try! keychainSynchronizable.get("password"), "not stored password")
+
+        do { try keychain.set("password1234", key: "password") } catch {}
+        XCTAssertEqual(try! keychain.get("password"), "password1234", "stored password")
+        XCTAssertEqual(try! keychainSynchronizable.get("password"), "password1234", "stored password")
+
+        do { try keychainSynchronizable.set("password1234_synchronizable", key: "password") } catch {}
+        XCTAssertEqual(try! keychain.get("username"), "kishikawakatsumi_synchronizable", "stored username")
+        XCTAssertEqual(try! keychainSynchronizable.get("username"), "kishikawakatsumi_synchronizable", "stored username")
+        XCTAssertEqual(try! keychain.get("password"), "password1234_synchronizable", "stored password")
+        XCTAssertEqual(try! keychainSynchronizable.get("password"), "password1234_synchronizable", "stored password")
+
+        do { try keychain.remove("username") } catch {}
+        XCTAssertNil(try! keychain.get("username"), "not stored username")
+        XCTAssertNil(try! keychainSynchronizable.get("username"), "not stored username")
+        XCTAssertEqual(try! keychain.get("password"), "password1234_synchronizable", "stored password")
+        XCTAssertEqual(try! keychainSynchronizable.get("password"), "password1234_synchronizable", "stored password")
+
+        do { try keychain.removeAll() } catch {}
+        XCTAssertNil(try! keychain.get("username"), "not stored username")
+        XCTAssertNil(try! keychainSynchronizable.get("username"), "not stored username")
+        XCTAssertNil(try! keychain.get("password"), "not stored password")
+        XCTAssertNil(try! keychainSynchronizable.get("password"), "not stored password")
+    }
 }
 }