KeychainAccessTests.swift 37 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866
  1. //
  2. // KeychainAccessTests.swift
  3. // KeychainAccessTests
  4. //
  5. // Created by kishikawa katsumi on 2014/12/24.
  6. // Copyright (c) 2014 kishikawa katsumi. All rights reserved.
  7. //
  8. import Foundation
  9. import XCTest
  10. import KeychainAccess
  11. class KeychainAccessTests: XCTestCase {
  12. override func setUp() {
  13. super.setUp()
  14. do { try Keychain(service: "Twitter", accessGroup: "12ABCD3E4F.shared").removeAll() } catch {}
  15. do { try Keychain(service: "Twitter").removeAll() } catch {}
  16. do { try Keychain(server: NSURL(string: "https://example.com")!, protocolType: .HTTPS).removeAll() } catch {}
  17. do { try Keychain().removeAll() } catch {}
  18. }
  19. override func tearDown() {
  20. super.tearDown()
  21. }
  22. // MARK:
  23. func testGenericPassword() {
  24. do {
  25. // Add Keychain items
  26. let keychain = Keychain(service: "Twitter")
  27. do { try keychain.set("kishikawa_katsumi", key: "username") } catch {}
  28. do { try keychain.set("password_1234", key: "password") } catch {}
  29. let username = try! keychain.get("username")
  30. XCTAssertEqual(username!, "kishikawa_katsumi")
  31. let password = try! keychain.get("password")
  32. XCTAssertEqual(password!, "password_1234")
  33. }
  34. do {
  35. // Update Keychain items
  36. let keychain = Keychain(service: "Twitter")
  37. do { try keychain.set("katsumi_kishikawa", key: "username") } catch {}
  38. do { try keychain.set("1234_password", key: "password") } catch {}
  39. let username = try! keychain.get("username")
  40. XCTAssertEqual(username!, "katsumi_kishikawa")
  41. let password = try! keychain.get("password")
  42. XCTAssertEqual(password!, "1234_password")
  43. }
  44. do {
  45. // Remove Keychain items
  46. let keychain = Keychain(service: "Twitter")
  47. do { try keychain.remove("username") } catch {}
  48. do { try keychain.remove("password") } catch {}
  49. XCTAssertNil(try! keychain.get("username"))
  50. XCTAssertNil(try! keychain.get("password"))
  51. }
  52. }
  53. func testGenericPasswordSubscripting() {
  54. do {
  55. // Add Keychain items
  56. let keychain = Keychain(service: "Twitter", accessGroup: "12ABCD3E4F.shared")
  57. keychain["username"] = "kishikawa_katsumi"
  58. keychain["password"] = "password_1234"
  59. let username = keychain["username"]
  60. XCTAssertEqual(username!, "kishikawa_katsumi")
  61. let password = keychain["password"]
  62. XCTAssertEqual(password!, "password_1234")
  63. }
  64. do {
  65. // Update Keychain items
  66. let keychain = Keychain(service: "Twitter", accessGroup: "12ABCD3E4F.shared")
  67. keychain["username"] = "katsumi_kishikawa"
  68. keychain["password"] = "1234_password"
  69. let username = keychain["username"]
  70. XCTAssertEqual(username!, "katsumi_kishikawa")
  71. let password = keychain["password"]
  72. XCTAssertEqual(password!, "1234_password")
  73. }
  74. do {
  75. // Remove Keychain items
  76. let keychain = Keychain(service: "Twitter", accessGroup: "12ABCD3E4F.shared")
  77. keychain["username"] = nil
  78. keychain["password"] = nil
  79. XCTAssertNil(keychain["username"])
  80. XCTAssertNil(keychain["password"])
  81. }
  82. }
  83. // MARK:
  84. func testInternetPassword() {
  85. do {
  86. // Add Keychain items
  87. let keychain = Keychain(server: NSURL(string: "https://kishikawakatsumi.com")!, protocolType: .HTTPS)
  88. do { try keychain.set("kishikawa_katsumi", key: "username") } catch {}
  89. do { try keychain.set("password_1234", key: "password") } catch {}
  90. let username = try! keychain.get("username")
  91. XCTAssertEqual(username!, "kishikawa_katsumi")
  92. let password = try! keychain.get("password")
  93. XCTAssertEqual(password!, "password_1234")
  94. }
  95. do {
  96. // Update Keychain items
  97. let keychain = Keychain(server: NSURL(string: "https://kishikawakatsumi.com")!, protocolType: .HTTPS)
  98. do { try keychain.set("katsumi_kishikawa", key: "username") } catch {}
  99. do { try keychain.set("1234_password", key: "password") } catch {}
  100. let username = try! keychain.get("username")
  101. XCTAssertEqual(username!, "katsumi_kishikawa")
  102. let password = try! keychain.get("password")
  103. XCTAssertEqual(password!, "1234_password")
  104. }
  105. do {
  106. // Remove Keychain items
  107. let keychain = Keychain(server: NSURL(string: "https://kishikawakatsumi.com")!, protocolType: .HTTPS)
  108. do { try keychain.remove("username") } catch {}
  109. do { try keychain.remove("password") } catch {}
  110. XCTAssertNil(try! keychain.get("username"))
  111. XCTAssertNil(try! keychain.get("password"))
  112. }
  113. }
  114. func testInternetPasswordSubscripting() {
  115. do {
  116. // Add Keychain items
  117. let keychain = Keychain(server: NSURL(string: "https://kishikawakatsumi.com")!, protocolType: .HTTPS)
  118. keychain["username"] = "kishikawa_katsumi"
  119. keychain["password"] = "password_1234"
  120. let username = keychain["username"]
  121. XCTAssertEqual(username!, "kishikawa_katsumi")
  122. let password = keychain["password"]
  123. XCTAssertEqual(password!, "password_1234")
  124. }
  125. do {
  126. // Update Keychain items
  127. let keychain = Keychain(server: NSURL(string: "https://kishikawakatsumi.com")!, protocolType: .HTTPS)
  128. keychain["username"] = "katsumi_kishikawa"
  129. keychain["password"] = "1234_password"
  130. let username = keychain["username"]
  131. XCTAssertEqual(username!, "katsumi_kishikawa")
  132. let password = keychain["password"]
  133. XCTAssertEqual(password!, "1234_password")
  134. }
  135. do {
  136. // Remove Keychain items
  137. let keychain = Keychain(server: NSURL(string: "https://kishikawakatsumi.com")!, protocolType: .HTTPS)
  138. keychain["username"] = nil
  139. keychain["password"] = nil
  140. XCTAssertNil(keychain["username"])
  141. XCTAssertNil(keychain["password"])
  142. }
  143. }
  144. // MARK:
  145. func testDefaultInitializer() {
  146. let keychain = Keychain()
  147. XCTAssertEqual(keychain.service, "")
  148. XCTAssertNil(keychain.accessGroup)
  149. }
  150. func testInitializerWithService() {
  151. let keychain = Keychain(service: "com.example.github-token")
  152. XCTAssertEqual(keychain.service, "com.example.github-token")
  153. XCTAssertNil(keychain.accessGroup)
  154. }
  155. func testInitializerWithAccessGroup() {
  156. let keychain = Keychain(accessGroup: "12ABCD3E4F.shared")
  157. XCTAssertEqual(keychain.service, "")
  158. XCTAssertEqual(keychain.accessGroup!, "12ABCD3E4F.shared")
  159. }
  160. func testInitializerWithServiceAndAccessGroup() {
  161. let keychain = Keychain(service: "com.example.github-token", accessGroup: "12ABCD3E4F.shared")
  162. XCTAssertEqual(keychain.service, "com.example.github-token")
  163. XCTAssertEqual(keychain.accessGroup!, "12ABCD3E4F.shared")
  164. }
  165. func testInitializerWithServer() {
  166. let server = "https://kishikawakatsumi.com"
  167. let URL = NSURL(string: server)!
  168. do {
  169. let keychain = Keychain(server: server, protocolType: .HTTPS)
  170. XCTAssertEqual(keychain.server, URL)
  171. XCTAssertEqual(keychain.protocolType, ProtocolType.HTTPS)
  172. XCTAssertEqual(keychain.authenticationType, AuthenticationType.Default)
  173. }
  174. do {
  175. let keychain = Keychain(server: URL, protocolType: .HTTPS)
  176. XCTAssertEqual(keychain.server, URL)
  177. XCTAssertEqual(keychain.protocolType, ProtocolType.HTTPS)
  178. XCTAssertEqual(keychain.authenticationType, AuthenticationType.Default)
  179. }
  180. }
  181. func testInitializerWithServerAndAuthenticationType() {
  182. let server = "https://kishikawakatsumi.com"
  183. let URL = NSURL(string: server)!
  184. do {
  185. let keychain = Keychain(server: server, protocolType: .HTTPS, authenticationType: .HTMLForm)
  186. XCTAssertEqual(keychain.server, URL)
  187. XCTAssertEqual(keychain.protocolType, ProtocolType.HTTPS)
  188. XCTAssertEqual(keychain.authenticationType, AuthenticationType.HTMLForm)
  189. }
  190. do {
  191. let keychain = Keychain(server: URL, protocolType: .HTTPS, authenticationType: .HTMLForm)
  192. XCTAssertEqual(keychain.server, URL)
  193. XCTAssertEqual(keychain.protocolType, ProtocolType.HTTPS)
  194. XCTAssertEqual(keychain.authenticationType, AuthenticationType.HTMLForm)
  195. }
  196. }
  197. // MARK:
  198. func testContains() {
  199. let keychain = Keychain(service: "Twitter")
  200. XCTAssertFalse(try! keychain.contains("username"), "not stored username")
  201. XCTAssertFalse(try! keychain.contains("password"), "not stored password")
  202. do { try keychain.set("kishikawakatsumi", key: "username") } catch {}
  203. XCTAssertTrue(try! keychain.contains("username"), "stored username")
  204. XCTAssertFalse(try! keychain.contains("password"), "not stored password")
  205. do { try keychain.set("password1234", key: "password") } catch {}
  206. XCTAssertTrue(try! keychain.contains("username"), "stored username")
  207. XCTAssertTrue(try! keychain.contains("password"), "stored password")
  208. }
  209. // MARK:
  210. func testSetString() {
  211. let keychain = Keychain(service: "Twitter")
  212. XCTAssertNil(try! keychain.get("username"), "not stored username")
  213. XCTAssertNil(try! keychain.get("password"), "not stored password")
  214. do { try keychain.set("kishikawakatsumi", key: "username") } catch {}
  215. XCTAssertEqual(try! keychain.get("username")!, "kishikawakatsumi", "stored username")
  216. XCTAssertNil(try! keychain.get("password"), "not stored password")
  217. do { try keychain.set("password1234", key: "password") } catch {}
  218. XCTAssertEqual(try! keychain.get("username")!, "kishikawakatsumi", "stored username")
  219. XCTAssertEqual(try! keychain.get("password")!, "password1234", "stored password")
  220. }
  221. func testSetData() {
  222. let JSONObject = ["username": "kishikawakatsumi", "password": "password1234"]
  223. let JSONData = try! NSJSONSerialization.dataWithJSONObject(JSONObject, options: [])
  224. let keychain = Keychain(service: "Twitter")
  225. XCTAssertNil(try! keychain.getData("JSONData"), "not stored JSON data")
  226. do { try keychain.set(JSONData, key: "JSONData") } catch {}
  227. XCTAssertEqual(try! keychain.getData("JSONData")!, JSONData, "stored JSON data")
  228. }
  229. func testStringConversionError() {
  230. let keychain = Keychain(service: "Twitter")
  231. let length = 256
  232. let data = NSMutableData(length: length)!
  233. SecRandomCopyBytes(kSecRandomDefault, length, UnsafeMutablePointer<UInt8>(data.mutableBytes))
  234. do {
  235. try keychain.set(data, key: "RandomData")
  236. let _ = try keychain.getString("RandomData")
  237. } catch let error as NSError {
  238. XCTAssertEqual(error.domain, KeychainAccessErrorDomain)
  239. XCTAssertEqual(error.code, Int(Status.ConversionError.rawValue))
  240. }
  241. }
  242. func testRemoveString() {
  243. let keychain = Keychain(service: "Twitter")
  244. XCTAssertNil(try! keychain.get("username"), "not stored username")
  245. XCTAssertNil(try! keychain.get("password"), "not stored password")
  246. do { try keychain.set("kishikawakatsumi", key: "username") } catch {}
  247. XCTAssertEqual(try! keychain.get("username")!, "kishikawakatsumi", "stored username")
  248. do { try keychain.set("password1234", key: "password") } catch {}
  249. XCTAssertEqual(try! keychain.get("password")!, "password1234", "stored password")
  250. do { try keychain.remove("username") } catch {}
  251. XCTAssertNil(try! keychain.get("username"), "removed username")
  252. XCTAssertEqual(try! keychain.get("password")!, "password1234", "left password")
  253. do { try keychain.remove("password") } catch {}
  254. XCTAssertNil(try! keychain.get("username"), "removed username")
  255. XCTAssertNil(try! keychain.get("password"), "removed password")
  256. }
  257. func testRemoveData() {
  258. let JSONObject = ["username": "kishikawakatsumi", "password": "password1234"]
  259. let JSONData = try! NSJSONSerialization.dataWithJSONObject(JSONObject, options: [])
  260. let keychain = Keychain(service: "Twitter")
  261. XCTAssertNil(try! keychain.getData("JSONData"), "not stored JSON data")
  262. do { try keychain.set(JSONData, key: "JSONData") } catch {}
  263. XCTAssertEqual(try! keychain.getData("JSONData")!, JSONData, "stored JSON data")
  264. do { try keychain.remove("JSONData") } catch {}
  265. XCTAssertNil(try! keychain.getData("JSONData"), "removed JSON data")
  266. }
  267. // MARK:
  268. func testSubscripting() {
  269. let keychain = Keychain(service: "Twitter")
  270. XCTAssertNil(keychain["username"], "not stored username")
  271. XCTAssertNil(keychain["password"], "not stored password")
  272. XCTAssertNil(keychain[string: "username"], "not stored username")
  273. XCTAssertNil(keychain[string: "password"], "not stored password")
  274. keychain["username"] = "kishikawakatsumi"
  275. XCTAssertEqual(keychain["username"]!, "kishikawakatsumi", "stored username")
  276. XCTAssertEqual(keychain[string: "username"]!, "kishikawakatsumi", "stored username")
  277. keychain["password"] = "password1234"
  278. XCTAssertEqual(keychain["password"]!, "password1234", "stored password")
  279. XCTAssertEqual(keychain[string: "password"]!, "password1234", "stored password")
  280. keychain[string: "username"] = nil
  281. XCTAssertNil(keychain["username"], "removed username")
  282. XCTAssertEqual(keychain["password"]!, "password1234", "left password")
  283. XCTAssertNil(keychain[string: "username"], "removed username")
  284. XCTAssertEqual(keychain[string: "password"]!, "password1234", "left password")
  285. keychain[string: "password"] = nil
  286. XCTAssertNil(keychain["username"], "removed username")
  287. XCTAssertNil(keychain["password"], "removed password")
  288. XCTAssertNil(keychain[string: "username"], "removed username")
  289. XCTAssertNil(keychain[string: "password"], "removed password")
  290. let JSONObject = ["username": "kishikawakatsumi", "password": "password1234"]
  291. let JSONData = try! NSJSONSerialization.dataWithJSONObject(JSONObject, options: [])
  292. XCTAssertNil(keychain[data:"JSONData"], "not stored JSON data")
  293. keychain[data: "JSONData"] = JSONData
  294. XCTAssertEqual(keychain[data: "JSONData"]!, JSONData, "stored JSON data")
  295. keychain[data: "JSONData"] = nil
  296. XCTAssertNil(keychain[data:"JSONData"], "removed JSON data")
  297. }
  298. // MARK:
  299. #if os(iOS)
  300. func testErrorHandling() {
  301. do {
  302. let keychain = Keychain(service: "Twitter", accessGroup: "12ABCD3E4F.shared")
  303. try keychain.removeAll()
  304. XCTAssertTrue(true, "no error occurred")
  305. } catch {
  306. XCTFail("error occurred")
  307. }
  308. do {
  309. let keychain = Keychain(service: "Twitter")
  310. try keychain.removeAll()
  311. XCTAssertTrue(true, "no error occurred")
  312. } catch {
  313. XCTFail("error occurred")
  314. }
  315. do {
  316. let keychain = Keychain(server: NSURL(string: "https://kishikawakatsumi.com")!, protocolType: .HTTPS)
  317. try keychain.removeAll()
  318. XCTAssertTrue(true, "no error occurred")
  319. } catch {
  320. XCTFail("error occurred")
  321. }
  322. do {
  323. let keychain = Keychain()
  324. try keychain.removeAll()
  325. XCTAssertTrue(true, "no error occurred")
  326. } catch {
  327. XCTFail("error occurred")
  328. }
  329. do {
  330. // Add Keychain items
  331. let keychain = Keychain(service: "Twitter")
  332. do {
  333. try keychain.set("kishikawa_katsumi", key: "username")
  334. XCTAssertTrue(true, "no error occurred")
  335. } catch {
  336. XCTFail("error occurred")
  337. }
  338. do {
  339. try keychain.set("password_1234", key: "password")
  340. XCTAssertTrue(true, "no error occurred")
  341. } catch {
  342. XCTFail("error occurred")
  343. }
  344. do {
  345. let username = try keychain.get("username")
  346. XCTAssertEqual(username, "kishikawa_katsumi")
  347. } catch {
  348. XCTFail("error occurred")
  349. }
  350. do {
  351. let password = try keychain.get("password")
  352. XCTAssertEqual(password, "password_1234")
  353. } catch {
  354. XCTFail("error occurred")
  355. }
  356. }
  357. do {
  358. // Update Keychain items
  359. let keychain = Keychain(service: "Twitter")
  360. do {
  361. try keychain.set("katsumi_kishikawa", key: "username")
  362. XCTAssertTrue(true, "no error occurred")
  363. } catch {
  364. XCTFail("error occurred")
  365. }
  366. do {
  367. try keychain.set("1234_password", key: "password")
  368. XCTAssertTrue(true, "no error occurred")
  369. } catch {
  370. XCTFail("error occurred")
  371. }
  372. do {
  373. let username = try keychain.get("username")
  374. XCTAssertEqual(username, "katsumi_kishikawa")
  375. } catch {
  376. XCTFail("error occurred")
  377. }
  378. do {
  379. let password = try keychain.get("password")
  380. XCTAssertEqual(password, "1234_password")
  381. } catch {
  382. XCTFail("error occurred")
  383. }
  384. }
  385. do {
  386. // Remove Keychain items
  387. let keychain = Keychain(service: "Twitter")
  388. do {
  389. try keychain.remove("username")
  390. XCTAssertNil(try! keychain.get("username"))
  391. } catch {
  392. XCTFail("error occurred")
  393. }
  394. do {
  395. try keychain.remove("password")
  396. XCTAssertNil(try! keychain.get("username"))
  397. } catch {
  398. XCTFail("error occurred")
  399. }
  400. }
  401. }
  402. #endif
  403. // MARK:
  404. func testSetStringWithCustomService() {
  405. let username_1 = "kishikawakatsumi"
  406. let password_1 = "password1234"
  407. let username_2 = "kishikawa_katsumi"
  408. let password_2 = "password_1234"
  409. let username_3 = "k_katsumi"
  410. let password_3 = "12341234"
  411. let service_1 = ""
  412. let service_2 = "com.kishikawakatsumi.KeychainAccess"
  413. let service_3 = "example.com"
  414. do { try Keychain().removeAll() } catch {}
  415. do { try Keychain(service: service_1).removeAll() } catch {}
  416. do { try Keychain(service: service_2).removeAll() } catch {}
  417. do { try Keychain(service: service_3).removeAll() } catch {}
  418. XCTAssertNil(try! Keychain().get("username"), "not stored username")
  419. XCTAssertNil(try! Keychain().get("password"), "not stored password")
  420. XCTAssertNil(try! Keychain(service: service_1).get("username"), "not stored username")
  421. XCTAssertNil(try! Keychain(service: service_1).get("password"), "not stored password")
  422. XCTAssertNil(try! Keychain(service: service_2).get("username"), "not stored username")
  423. XCTAssertNil(try! Keychain(service: service_2).get("password"), "not stored password")
  424. XCTAssertNil(try! Keychain(service: service_3).get("username"), "not stored username")
  425. XCTAssertNil(try! Keychain(service: service_3).get("password"), "not stored password")
  426. do { try Keychain().set(username_1, key: "username") } catch {}
  427. XCTAssertEqual(try! Keychain().get("username")!, username_1, "stored username")
  428. XCTAssertEqual(try! Keychain(service: service_1).get("username")!, username_1, "stored username")
  429. XCTAssertNil(try! Keychain(service: service_2).get("username"), "not stored username")
  430. XCTAssertNil(try! Keychain(service: service_3).get("username"), "not stored username")
  431. do { try Keychain(service: service_1).set(username_1, key: "username") } catch {}
  432. XCTAssertEqual(try! Keychain().get("username")!, username_1, "stored username")
  433. XCTAssertEqual(try! Keychain(service: service_1).get("username")!, username_1, "stored username")
  434. XCTAssertNil(try! Keychain(service: service_2).get("username"), "not stored username")
  435. XCTAssertNil(try! Keychain(service: service_3).get("username"), "not stored username")
  436. do { try Keychain(service: service_2).set(username_2, key: "username") } catch {}
  437. XCTAssertEqual(try! Keychain().get("username")!, username_1, "stored username")
  438. XCTAssertEqual(try! Keychain(service: service_1).get("username")!, username_1, "stored username")
  439. XCTAssertEqual(try! Keychain(service: service_2).get("username")!, username_2, "stored username")
  440. XCTAssertNil(try! Keychain(service: service_3).get("username"), "not stored username")
  441. do { try Keychain(service: service_3).set(username_3, key: "username") } catch {}
  442. XCTAssertEqual(try! Keychain().get("username")!, username_1, "stored username")
  443. XCTAssertEqual(try! Keychain(service: service_1).get("username")!, username_1, "stored username")
  444. XCTAssertEqual(try! Keychain(service: service_2).get("username")!, username_2, "stored username")
  445. XCTAssertEqual(try! Keychain(service: service_3).get("username")!, username_3, "stored username")
  446. do { try Keychain().set(password_1, key: "password") } catch {}
  447. XCTAssertEqual(try! Keychain().get("password")!, password_1, "stored password")
  448. XCTAssertEqual(try! Keychain(service: service_1).get("password")!, password_1, "stored password")
  449. XCTAssertNil(try! Keychain(service: service_2).get("password"), "not stored password")
  450. XCTAssertNil(try! Keychain(service: service_3).get("password"), "not stored password")
  451. do { try Keychain(service: service_1).set(password_1, key: "password") } catch {}
  452. XCTAssertEqual(try! Keychain().get("password")!, password_1, "stored password")
  453. XCTAssertEqual(try! Keychain(service: service_1).get("password")!, password_1, "stored password")
  454. XCTAssertNil(try! Keychain(service: service_2).get("password"), "not stored password")
  455. XCTAssertNil(try! Keychain(service: service_3).get("password"), "not stored password")
  456. do { try Keychain(service: service_2).set(password_2, key: "password") } catch {}
  457. XCTAssertEqual(try! Keychain().get("password")!, password_1, "stored password")
  458. XCTAssertEqual(try! Keychain(service: service_1).get("password")!, password_1, "stored password")
  459. XCTAssertEqual(try! Keychain(service: service_2).get("password")!, password_2, "stored password")
  460. XCTAssertNil(try! Keychain(service: service_3).get("password"), "not stored password")
  461. do { try Keychain(service: service_3).set(password_3, key: "password") } catch {}
  462. XCTAssertEqual(try! Keychain().get("password")!, password_1, "stored password")
  463. XCTAssertEqual(try! Keychain(service: service_1).get("password")!, password_1, "stored password")
  464. XCTAssertEqual(try! Keychain(service: service_2).get("password")!, password_2, "stored password")
  465. XCTAssertEqual(try! Keychain(service: service_3).get("password")!, password_3, "stored password")
  466. do { try Keychain().remove("username") } catch {}
  467. XCTAssertNil(try! Keychain().get("username"), "removed username")
  468. XCTAssertNil(try! Keychain(service: service_1).get("username"), "removed username")
  469. XCTAssertEqual(try! Keychain(service: service_2).get("username")!, username_2, "left username")
  470. XCTAssertEqual(try! Keychain(service: service_3).get("username")!, username_3, "left username")
  471. do { try Keychain(service: service_1).remove("username") } catch {}
  472. XCTAssertNil(try! Keychain().get("username"), "removed username")
  473. XCTAssertNil(try! Keychain(service: service_1).get("username"), "removed username")
  474. XCTAssertEqual(try! Keychain(service: service_2).get("username")!, username_2, "left username")
  475. XCTAssertEqual(try! Keychain(service: service_3).get("username")!, username_3, "left username")
  476. do { try Keychain(service: service_2).remove("username") } catch {}
  477. XCTAssertNil(try! Keychain().get("username"), "removed username")
  478. XCTAssertNil(try! Keychain(service: service_1).get("username"), "removed username")
  479. XCTAssertNil(try! Keychain(service: service_2).get("username"), "removed username")
  480. XCTAssertEqual(try! Keychain(service: service_3).get("username")!, username_3, "left username")
  481. do { try Keychain(service: service_3).remove("username") } catch {}
  482. XCTAssertNil(try! Keychain().get("username"), "removed username")
  483. XCTAssertNil(try! Keychain(service: service_1).get("username"), "removed username")
  484. XCTAssertNil(try! Keychain(service: service_2).get("username"), "removed username")
  485. XCTAssertNil(try! Keychain(service: service_3).get("username"), "removed username")
  486. do { try Keychain().remove("password") } catch {}
  487. XCTAssertNil(try! Keychain().get("password"), "removed password")
  488. XCTAssertNil(try! Keychain(service: service_1).get("password"), "removed password")
  489. XCTAssertEqual(try! Keychain(service: service_2).get("password")!, password_2, "left password")
  490. XCTAssertEqual(try! Keychain(service: service_3).get("password")!, password_3, "left password")
  491. do { try Keychain(service: service_1).remove("password") } catch {}
  492. XCTAssertNil(try! Keychain().get("password"), "removed password")
  493. XCTAssertNil(try! Keychain(service: service_1).get("password"), "removed password")
  494. XCTAssertEqual(try! Keychain(service: service_2).get("password")!, password_2, "left password")
  495. XCTAssertEqual(try! Keychain(service: service_3).get("password")!, password_3, "left password")
  496. do { try Keychain(service: service_2).remove("password") } catch {}
  497. XCTAssertNil(try! Keychain().get("password"), "removed password")
  498. XCTAssertNil(try! Keychain(service: service_1).get("password"), "removed password")
  499. XCTAssertNil(try! Keychain(service: service_2).get("password"), "removed password")
  500. XCTAssertEqual(try! Keychain(service: service_3).get("password")!, password_3, "left password")
  501. do { try Keychain(service: service_3).remove("password") } catch {}
  502. XCTAssertNil(try! Keychain().get("password"), "removed password")
  503. XCTAssertNil(try! Keychain(service: service_2).get("password"), "removed password")
  504. XCTAssertNil(try! Keychain(service: service_2).get("password"), "removed password")
  505. XCTAssertNil(try! Keychain(service: service_2).get("password"), "removed password")
  506. }
  507. // MARK:
  508. func testProperties() {
  509. guard #available(OSX 10.10, *) else {
  510. return
  511. }
  512. let keychain = Keychain()
  513. XCTAssertEqual(keychain.synchronizable, false)
  514. XCTAssertEqual(keychain.synchronizable(true).synchronizable, true)
  515. XCTAssertEqual(keychain.synchronizable(false).synchronizable, false)
  516. XCTAssertEqual(keychain.accessibility(.AfterFirstUnlock).accessibility, Accessibility.AfterFirstUnlock)
  517. XCTAssertEqual(keychain.accessibility(.WhenPasscodeSetThisDeviceOnly, authenticationPolicy: .UserPresence).accessibility, Accessibility.WhenPasscodeSetThisDeviceOnly)
  518. XCTAssertEqual(keychain.accessibility(.WhenPasscodeSetThisDeviceOnly, authenticationPolicy: .UserPresence).authenticationPolicy, AuthenticationPolicy.UserPresence)
  519. XCTAssertNil(keychain.label)
  520. XCTAssertEqual(keychain.label("Label").label, "Label")
  521. XCTAssertNil(keychain.comment)
  522. XCTAssertEqual(keychain.comment("Comment").comment, "Comment")
  523. XCTAssertEqual(keychain.authenticationPrompt("Prompt").authenticationPrompt, "Prompt")
  524. }
  525. // MARK:
  526. func testAuthenticationPolicy() {
  527. guard #available(iOS 9.0, OSX 10.11, *) else {
  528. return
  529. }
  530. do {
  531. let accessibility: Accessibility = .WhenPasscodeSetThisDeviceOnly
  532. let policy: AuthenticationPolicy = [.UserPresence]
  533. let flags = SecAccessControlCreateFlags(rawValue: policy.rawValue)
  534. var error: Unmanaged<CFError>?
  535. let accessControl = SecAccessControlCreateWithFlags(kCFAllocatorDefault, accessibility.rawValue, flags, &error)
  536. XCTAssertNil(error)
  537. XCTAssertNotNil(accessControl)
  538. }
  539. do {
  540. let accessibility: Accessibility = .WhenPasscodeSetThisDeviceOnly
  541. let policy: AuthenticationPolicy = [.UserPresence, .ApplicationPassword]
  542. let flags = SecAccessControlCreateFlags(rawValue: policy.rawValue)
  543. var error: Unmanaged<CFError>?
  544. let accessControl = SecAccessControlCreateWithFlags(kCFAllocatorDefault, accessibility.rawValue, flags, &error)
  545. XCTAssertNil(error)
  546. XCTAssertNotNil(accessControl)
  547. }
  548. do {
  549. let accessibility: Accessibility = .WhenPasscodeSetThisDeviceOnly
  550. let policy: AuthenticationPolicy = [.UserPresence, .ApplicationPassword, .PrivateKeyUsage]
  551. let flags = SecAccessControlCreateFlags(rawValue: policy.rawValue)
  552. var error: Unmanaged<CFError>?
  553. let accessControl = SecAccessControlCreateWithFlags(kCFAllocatorDefault, accessibility.rawValue, flags, &error)
  554. XCTAssertNil(error)
  555. XCTAssertNotNil(accessControl)
  556. }
  557. do {
  558. let accessibility: Accessibility = .WhenPasscodeSetThisDeviceOnly
  559. let policy: AuthenticationPolicy = [.ApplicationPassword]
  560. let flags = SecAccessControlCreateFlags(rawValue: policy.rawValue)
  561. var error: Unmanaged<CFError>?
  562. let accessControl = SecAccessControlCreateWithFlags(kCFAllocatorDefault, accessibility.rawValue, flags, &error)
  563. XCTAssertNil(error)
  564. XCTAssertNotNil(accessControl)
  565. }
  566. do {
  567. let accessibility: Accessibility = .WhenPasscodeSetThisDeviceOnly
  568. let policy: AuthenticationPolicy = [.ApplicationPassword, .PrivateKeyUsage]
  569. let flags = SecAccessControlCreateFlags(rawValue: policy.rawValue)
  570. var error: Unmanaged<CFError>?
  571. let accessControl = SecAccessControlCreateWithFlags(kCFAllocatorDefault, accessibility.rawValue, flags, &error)
  572. XCTAssertNil(error)
  573. XCTAssertNotNil(accessControl)
  574. }
  575. do {
  576. let accessibility: Accessibility = .WhenPasscodeSetThisDeviceOnly
  577. let policy: AuthenticationPolicy = [.PrivateKeyUsage]
  578. let flags = SecAccessControlCreateFlags(rawValue: policy.rawValue)
  579. var error: Unmanaged<CFError>?
  580. let accessControl = SecAccessControlCreateWithFlags(kCFAllocatorDefault, accessibility.rawValue, flags, &error)
  581. XCTAssertNil(error)
  582. XCTAssertNotNil(accessControl)
  583. }
  584. do {
  585. let accessibility: Accessibility = .WhenPasscodeSetThisDeviceOnly
  586. let policy: AuthenticationPolicy = [.TouchIDAny]
  587. let flags = SecAccessControlCreateFlags(rawValue: policy.rawValue)
  588. var error: Unmanaged<CFError>?
  589. let accessControl = SecAccessControlCreateWithFlags(kCFAllocatorDefault, accessibility.rawValue, flags, &error)
  590. XCTAssertNil(error)
  591. XCTAssertNotNil(accessControl)
  592. }
  593. do {
  594. let accessibility: Accessibility = .WhenPasscodeSetThisDeviceOnly
  595. let policy: AuthenticationPolicy = [.TouchIDAny, .DevicePasscode]
  596. let flags = SecAccessControlCreateFlags(rawValue: policy.rawValue)
  597. var error: Unmanaged<CFError>?
  598. let accessControl = SecAccessControlCreateWithFlags(kCFAllocatorDefault, accessibility.rawValue, flags, &error)
  599. XCTAssertNil(error)
  600. XCTAssertNotNil(accessControl)
  601. }
  602. do {
  603. let accessibility: Accessibility = .WhenPasscodeSetThisDeviceOnly
  604. let policy: AuthenticationPolicy = [.TouchIDAny, .ApplicationPassword]
  605. let flags = SecAccessControlCreateFlags(rawValue: policy.rawValue)
  606. var error: Unmanaged<CFError>?
  607. let accessControl = SecAccessControlCreateWithFlags(kCFAllocatorDefault, accessibility.rawValue, flags, &error)
  608. XCTAssertNil(error)
  609. XCTAssertNotNil(accessControl)
  610. }
  611. do {
  612. let accessibility: Accessibility = .WhenPasscodeSetThisDeviceOnly
  613. let policy: AuthenticationPolicy = [.TouchIDAny, .ApplicationPassword, .PrivateKeyUsage]
  614. let flags = SecAccessControlCreateFlags(rawValue: policy.rawValue)
  615. var error: Unmanaged<CFError>?
  616. let accessControl = SecAccessControlCreateWithFlags(kCFAllocatorDefault, accessibility.rawValue, flags, &error)
  617. XCTAssertNil(error)
  618. XCTAssertNotNil(accessControl)
  619. }
  620. do {
  621. let accessibility: Accessibility = .WhenPasscodeSetThisDeviceOnly
  622. let policy: AuthenticationPolicy = [.TouchIDCurrentSet]
  623. let flags = SecAccessControlCreateFlags(rawValue: policy.rawValue)
  624. var error: Unmanaged<CFError>?
  625. let accessControl = SecAccessControlCreateWithFlags(kCFAllocatorDefault, accessibility.rawValue, flags, &error)
  626. XCTAssertNil(error)
  627. XCTAssertNotNil(accessControl)
  628. }
  629. do {
  630. let accessibility: Accessibility = .WhenPasscodeSetThisDeviceOnly
  631. let policy: AuthenticationPolicy = [.TouchIDCurrentSet, .DevicePasscode]
  632. let flags = SecAccessControlCreateFlags(rawValue: policy.rawValue)
  633. var error: Unmanaged<CFError>?
  634. let accessControl = SecAccessControlCreateWithFlags(kCFAllocatorDefault, accessibility.rawValue, flags, &error)
  635. XCTAssertNil(error)
  636. XCTAssertNotNil(accessControl)
  637. }
  638. do {
  639. let accessibility: Accessibility = .WhenPasscodeSetThisDeviceOnly
  640. let policy: AuthenticationPolicy = [.TouchIDCurrentSet, .ApplicationPassword]
  641. let flags = SecAccessControlCreateFlags(rawValue: policy.rawValue)
  642. var error: Unmanaged<CFError>?
  643. let accessControl = SecAccessControlCreateWithFlags(kCFAllocatorDefault, accessibility.rawValue, flags, &error)
  644. XCTAssertNil(error)
  645. XCTAssertNotNil(accessControl)
  646. }
  647. do {
  648. let accessibility: Accessibility = .WhenPasscodeSetThisDeviceOnly
  649. let policy: AuthenticationPolicy = [.TouchIDCurrentSet, .ApplicationPassword, .PrivateKeyUsage]
  650. let flags = SecAccessControlCreateFlags(rawValue: policy.rawValue)
  651. var error: Unmanaged<CFError>?
  652. let accessControl = SecAccessControlCreateWithFlags(kCFAllocatorDefault, accessibility.rawValue, flags, &error)
  653. XCTAssertNil(error)
  654. XCTAssertNotNil(accessControl)
  655. }
  656. do {
  657. let accessibility: Accessibility = .WhenPasscodeSetThisDeviceOnly
  658. let policy: AuthenticationPolicy = [.TouchIDAny, .Or, .DevicePasscode]
  659. let flags = SecAccessControlCreateFlags(rawValue: policy.rawValue)
  660. var error: Unmanaged<CFError>?
  661. let accessControl = SecAccessControlCreateWithFlags(kCFAllocatorDefault, accessibility.rawValue, flags, &error)
  662. XCTAssertNil(error)
  663. XCTAssertNotNil(accessControl)
  664. }
  665. do {
  666. let accessibility: Accessibility = .WhenPasscodeSetThisDeviceOnly
  667. let policy: AuthenticationPolicy = [.TouchIDAny, .And, .DevicePasscode]
  668. let flags = SecAccessControlCreateFlags(rawValue: policy.rawValue)
  669. var error: Unmanaged<CFError>?
  670. let accessControl = SecAccessControlCreateWithFlags(kCFAllocatorDefault, accessibility.rawValue, flags, &error)
  671. XCTAssertNil(error)
  672. XCTAssertNotNil(accessControl)
  673. }
  674. }
  675. }