FileKitTests.swift 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943
  1. //
  2. // FileKitTests.swift
  3. // FileKitTests
  4. //
  5. // The MIT License (MIT)
  6. //
  7. // Copyright (c) 2015-2017 Nikolai Vazquez
  8. //
  9. // Permission is hereby granted, free of charge, to any person obtaining a copy
  10. // of this software and associated documentation files (the "Software"), to deal
  11. // in the Software without restriction, including without limitation the rights
  12. // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  13. // copies of the Software, and to permit persons to whom the Software is
  14. // furnished to do so, subject to the following conditions:
  15. //
  16. // The above copyright notice and this permission notice shall be included in
  17. // all copies or substantial portions of the Software.
  18. //
  19. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  20. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  21. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  22. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  23. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  24. // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  25. // THE SOFTWARE.
  26. //
  27. // swiftlint:disable type_body_length
  28. // swiftlint:disable file_length
  29. //
  30. import XCTest
  31. import FileKit
  32. class FileKitTests: XCTestCase {
  33. // MARK: - Path
  34. class Delegate: NSObject, FileManagerDelegate {
  35. var expectedSourcePath: Path = ""
  36. var expectedDestinationPath: Path = ""
  37. func fileManager(
  38. _ fileManager: FileManager,
  39. shouldCopyItemAtPath srcPath: String,
  40. toPath dstPath: String
  41. ) -> Bool {
  42. XCTAssertEqual(srcPath, expectedSourcePath.rawValue)
  43. XCTAssertEqual(dstPath, expectedDestinationPath.rawValue)
  44. return true
  45. }
  46. }
  47. func testPathFileManagerDelegate() {
  48. do {
  49. var sourcePath = .userTemporary + "filekit_test_filemanager_delegate"
  50. let destinationPath = Path("\(sourcePath)1")
  51. try sourcePath.createFile()
  52. var delegate: Delegate {
  53. let delegate = Delegate()
  54. delegate.expectedSourcePath = sourcePath
  55. delegate.expectedDestinationPath = destinationPath
  56. return delegate
  57. }
  58. let d1 = delegate
  59. sourcePath.fileManagerDelegate = d1
  60. XCTAssertTrue(d1 === sourcePath.fileManagerDelegate)
  61. try sourcePath +>! destinationPath
  62. var secondSourcePath = sourcePath
  63. secondSourcePath.fileManagerDelegate = delegate
  64. XCTAssertFalse(sourcePath.fileManagerDelegate === secondSourcePath.fileManagerDelegate)
  65. try secondSourcePath +>! destinationPath
  66. } catch {
  67. XCTFail(String(describing: error))
  68. }
  69. }
  70. func testFindingPaths() {
  71. let homeFolders = Path.userHome.find(searchDepth: 0) { $0.isDirectory }
  72. XCTAssertFalse(homeFolders.isEmpty, "Home folder is not empty")
  73. let rootFiles = Path.root.find(searchDepth: 1) { !$0.isDirectory }
  74. XCTAssertFalse(rootFiles.isEmpty)
  75. }
  76. func testPathStringLiteralConvertible() {
  77. let a = "/Users" as Path
  78. let b: Path = "/Users"
  79. let c = Path("/Users")
  80. XCTAssertEqual(a, b)
  81. XCTAssertEqual(a, c)
  82. XCTAssertEqual(b, c)
  83. }
  84. func testPathStringInterpolationConvertible() {
  85. let path: Path = "\(Path.userTemporary)/testfile_\(10)"
  86. XCTAssertEqual(path.rawValue, Path.userTemporary.rawValue + "/testfile_10")
  87. }
  88. func testPathEquality() {
  89. let a: Path = "~"
  90. let b: Path = "~/"
  91. let c: Path = "~//"
  92. let d: Path = "~/./"
  93. XCTAssertEqual(a, b)
  94. XCTAssertEqual(a, c)
  95. XCTAssertEqual(a, d)
  96. }
  97. func testStandardizingPath() {
  98. let a: Path = "~/.."
  99. let b: Path = "/Users"
  100. XCTAssertEqual(a.standardized, b.standardized)
  101. }
  102. func testPathIsDirectory() {
  103. let d = Path.systemApplications
  104. XCTAssertTrue(d.isDirectory)
  105. }
  106. func testSequence() {
  107. var i = 0
  108. let parent = Path.userTemporary
  109. for _ in parent {
  110. i += 1
  111. }
  112. print("\(i) files under \(parent)")
  113. i = 0
  114. for (_, _) in Path.userTemporary.enumerated() {
  115. i += 1
  116. }
  117. }
  118. func testPathExtension() {
  119. var path = Path.userTemporary + "file.txt"
  120. XCTAssertEqual(path.pathExtension, "txt")
  121. path.pathExtension = "pdf"
  122. XCTAssertEqual(path.pathExtension, "pdf")
  123. }
  124. func testPathParent() {
  125. let a: Path = "/"
  126. let b: Path = a + "Users"
  127. XCTAssertEqual(a, b.parent)
  128. }
  129. func testPathChildren() {
  130. let p: Path = "/Users"
  131. XCTAssertNotEqual(p.children(), [])
  132. }
  133. func testPathRecursiveChildren() {
  134. let p: Path = Path.userTemporary
  135. let children = p.children(recursive: true)
  136. XCTAssertNotEqual(children, [])
  137. }
  138. func testRoot() {
  139. let root = Path.root
  140. XCTAssertTrue(root.isRoot)
  141. XCTAssertEqual(root.standardized, root)
  142. XCTAssertEqual(root.parent, root)
  143. var p: Path = Path.userTemporary
  144. XCTAssertFalse(p.isRoot)
  145. while !p.isRoot { p = p.parent }
  146. XCTAssertTrue(p.isRoot)
  147. let empty = Path("")
  148. XCTAssertFalse(empty.isRoot)
  149. XCTAssertEqual(empty.standardized, empty)
  150. XCTAssertTrue(Path("/.").isRoot)
  151. XCTAssertTrue(Path("//").isRoot)
  152. }
  153. func testFamily() {
  154. let p: Path = Path.userTemporary
  155. let children = p.children()
  156. guard let child = children.first else {
  157. XCTFail("No child into \(p)")
  158. return
  159. }
  160. XCTAssertTrue(child.isAncestorOfPath(p))
  161. XCTAssertTrue(p.isChildOfPath(child))
  162. XCTAssertFalse(p.isAncestorOfPath(child))
  163. XCTAssertFalse(p.isAncestorOfPath(p))
  164. XCTAssertFalse(p.isChildOfPath(p))
  165. let directories = children.filter { $0.isDirectory }
  166. if let directory = directories.first, directory.children().isEmpty {
  167. try? (directory + "childOfChild").createDirectory()
  168. }
  169. guard let directory = directories.first, let childOfChild = directory.children().first else {
  170. XCTFail("No child of child into \(p)")
  171. return
  172. }
  173. XCTAssertTrue(childOfChild.isAncestorOfPath(p))
  174. XCTAssertFalse(p.isChildOfPath(childOfChild, recursive: false))
  175. XCTAssertTrue(p.isChildOfPath(childOfChild, recursive: true))
  176. // common ancestor
  177. XCTAssertTrue(p.commonAncestor(Path.root).isRoot)
  178. XCTAssertEqual(.userDownloads <^> .userDocuments, Path.userHome)
  179. XCTAssertEqual(("~/Downloads" <^> "~/Documents").rawValue, "~")
  180. }
  181. func testPathAttributes() {
  182. let a = .userTemporary + "test.txt"
  183. let b = .userTemporary + "TestDir"
  184. do {
  185. try "Hello there, sir" |> TextFile(path: a)
  186. try b.createDirectory()
  187. } catch {
  188. XCTFail(String(describing: error))
  189. }
  190. for p in [a, b] {
  191. print(String(describing: p.creationDate))
  192. print(String(describing: p.modificationDate))
  193. print(String(describing: p.ownerName))
  194. print(String(describing: p.ownerID))
  195. print(String(describing: p.groupName))
  196. print(String(describing: p.groupID))
  197. print(String(describing: p.extensionIsHidden))
  198. print(String(describing: p.posixPermissions))
  199. print(String(describing: p.fileReferenceCount))
  200. print(String(describing: p.fileSize))
  201. print(String(describing: p.filesystemFileNumber))
  202. print(String(describing: p.fileType))
  203. print("")
  204. }
  205. }
  206. func testPathSubscript() {
  207. let path = "~/Library/Preferences" as Path
  208. let a = path[0]
  209. XCTAssertEqual(a, "~")
  210. let b = path[2]
  211. XCTAssertEqual(b, path)
  212. }
  213. func testAddingPaths() {
  214. let a: Path = "~/Desktop"
  215. let b: Path = "Files"
  216. XCTAssertEqual(a + b, "~/Desktop/Files")
  217. }
  218. func testPathPlusEquals() {
  219. var a: Path = "~/Desktop"
  220. a += "Files"
  221. XCTAssertEqual(a, "~/Desktop/Files")
  222. }
  223. func testPathSymlinking() {
  224. do {
  225. let testDir: Path = .userTemporary + "filekit_test_symlinking"
  226. if testDir.exists && !testDir.isDirectory {
  227. try testDir.deleteFile()
  228. XCTAssertFalse(testDir.exists)
  229. }
  230. try testDir.createDirectory()
  231. XCTAssertTrue(testDir.exists)
  232. let testFile = TextFile(path: testDir + "test_file.txt")
  233. try "FileKit test" |> testFile
  234. XCTAssertTrue(testFile.exists)
  235. let symDir = testDir + "sym_dir"
  236. if symDir.exists && !symDir.isDirectory {
  237. try symDir.deleteFile()
  238. }
  239. try symDir.createDirectory()
  240. // "/temporary/symDir/test_file.txt"
  241. try testFile =>! symDir
  242. let symPath = symDir + testFile.name
  243. XCTAssertTrue(symPath.isSymbolicLink)
  244. let symPathContents = try String(contentsOfPath: symPath)
  245. XCTAssertEqual(symPathContents, "FileKit test")
  246. let symLink = testDir + "test_file_link.txt"
  247. try testFile =>! symLink
  248. XCTAssertTrue(symLink.isSymbolicLink)
  249. let symLinkContents = try String(contentsOfPath: symLink)
  250. XCTAssertEqual(symLinkContents, "FileKit test")
  251. } catch {
  252. XCTFail(String(describing: error))
  253. }
  254. }
  255. func testPathOperators() {
  256. let p: Path = "~"
  257. let ps = p.standardized
  258. XCTAssertEqual(ps, p%)
  259. XCTAssertEqual(ps.parent, ps^)
  260. }
  261. func testCurrent() {
  262. let oldCurrent: Path = .current
  263. let newCurrent: Path = .userTemporary
  264. XCTAssertNotEqual(oldCurrent, newCurrent) // else there is no test
  265. Path.current = newCurrent
  266. XCTAssertEqual(Path.current, newCurrent)
  267. Path.current = oldCurrent
  268. XCTAssertEqual(Path.current, oldCurrent)
  269. }
  270. func testChangeDirectory() {
  271. Path.userTemporary.changeDirectory {
  272. XCTAssertEqual(Path.current, Path.userTemporary)
  273. }
  274. Path.userDesktop </> {
  275. XCTAssertEqual(Path.current, Path.userDesktop)
  276. }
  277. XCTAssertNotEqual(Path.current, Path.userTemporary)
  278. }
  279. func testVolumes() {
  280. var volumes = Path.volumes()
  281. XCTAssertFalse(volumes.isEmpty, "No volume")
  282. for volume in volumes {
  283. XCTAssertNotNil("\(volume)")
  284. }
  285. volumes = Path.volumes(.skipHiddenVolumes)
  286. XCTAssertFalse(volumes.isEmpty, "No visible volume")
  287. for volume in volumes {
  288. XCTAssertNotNil("\(volume)")
  289. }
  290. }
  291. func testURL() {
  292. let path: Path = .userTemporary
  293. let url = path.url
  294. if let pathFromURL = Path(url: url) {
  295. XCTAssertEqual(pathFromURL, path)
  296. let subPath = pathFromURL + "test"
  297. XCTAssertEqual(Path(url: url.appendingPathComponent("test")), subPath)
  298. } else {
  299. XCTFail("Not able to create Path from URL")
  300. }
  301. }
  302. func testBookmarkData() {
  303. let path: Path = .userTemporary
  304. XCTAssertNotNil(path.bookmarkData)
  305. if let bookmarkData = path.bookmarkData {
  306. if let pathFromBookmarkData = Path(bookmarkData: bookmarkData) {
  307. XCTAssertEqual(pathFromBookmarkData, path)
  308. } else {
  309. XCTFail("Not able to create Path from Bookmark Data")
  310. }
  311. }
  312. }
  313. func testGroupIdentifier() {
  314. let path = Path(groupIdentifier: "com.nikolaivazquez.FileKitTests")
  315. XCTAssertNotNil(path, "Not able to create Path from group identifier")
  316. }
  317. func testTouch() {
  318. let path: Path = .userTemporary + "filekit_test.touch"
  319. do {
  320. if path.exists { try path.deleteFile() }
  321. XCTAssertFalse(path.exists)
  322. try path.touch()
  323. XCTAssertTrue(path.exists)
  324. guard let modificationDate = path.modificationDate else {
  325. XCTFail("Failed to get modification date")
  326. return
  327. }
  328. sleep(1)
  329. try path.touch()
  330. guard let newModificationDate = path.modificationDate else {
  331. XCTFail("Failed to get modification date")
  332. return
  333. }
  334. XCTAssertTrue(modificationDate < newModificationDate)
  335. } catch {
  336. XCTFail(String(describing: error))
  337. }
  338. }
  339. func testCreateDirectory() {
  340. let dir: Path = .userTemporary + "filekit_testdir"
  341. do {
  342. if dir.exists { try dir.deleteFile() }
  343. } catch {
  344. XCTFail(String(describing: error))
  345. }
  346. defer {
  347. do {
  348. if dir.exists { try dir.deleteFile() }
  349. } catch {
  350. XCTFail(String(describing: error))
  351. }
  352. }
  353. do {
  354. XCTAssertFalse(dir.exists)
  355. try dir.createDirectory()
  356. XCTAssertTrue(dir.exists)
  357. } catch {
  358. XCTFail(String(describing: error))
  359. }
  360. do {
  361. XCTAssertTrue(dir.exists)
  362. try dir.createDirectory(withIntermediateDirectories: false)
  363. XCTFail("must throw exception")
  364. } catch FileKitError.createDirectoryFail {
  365. print("Create directory fail ok")
  366. } catch {
  367. XCTFail("Unknown error: " + String(describing: error))
  368. }
  369. do {
  370. XCTAssertTrue(dir.exists)
  371. try dir.createDirectory(withIntermediateDirectories: true)
  372. XCTAssertTrue(dir.exists)
  373. } catch {
  374. XCTFail("Unexpected error: " + String(describing: error))
  375. }
  376. }
  377. func testWellKnownDirectories() {
  378. var paths: [Path] = [
  379. .userHome, .userTemporary, .userCaches, .userDesktop, .userDocuments,
  380. .userAutosavedInformation, .userDownloads, .userLibrary, .userMovies,
  381. .userMusic, .userPictures, .userApplicationSupport, .userApplications,
  382. .userSharedPublic
  383. ]
  384. paths += [
  385. .systemApplications, .systemApplicationSupport, .systemLibrary,
  386. .systemCoreServices, .systemPreferencePanes /* .systemPrinterDescription,*/
  387. ]
  388. #if os(OSX)
  389. paths += [.userTrash] // .userApplicationScripts (not testable)
  390. #endif
  391. for path in paths {
  392. XCTAssertTrue(path.exists, path.rawValue)
  393. }
  394. // all
  395. XCTAssertTrue(Path.allLibraries.contains(.userLibrary))
  396. XCTAssertTrue(Path.allLibraries.contains(.systemLibrary))
  397. XCTAssertTrue(Path.allApplications.contains(.userApplications))
  398. XCTAssertTrue(Path.allApplications.contains(.systemApplications))
  399. // temporary
  400. XCTAssertFalse(Path.processTemporary.exists)
  401. XCTAssertFalse(Path.uniqueTemporary.exists)
  402. XCTAssertNotEqual(Path.uniqueTemporary, Path.uniqueTemporary)
  403. }
  404. // MARK: - TextFile
  405. let testFilePath: Path = .userTemporary + "filekit_test.txt"
  406. let textFile = TextFile(path: .userTemporary + "filekit_test.txt")
  407. let textFileWithoutExt = TextFile(path: .userTemporary + "filekit_test")
  408. func testFileName() {
  409. XCTAssertEqual(TextFile(path: "/Users/").name, "Users")
  410. }
  411. func testTextFileExtension() {
  412. XCTAssertEqual(textFile.pathExtension, "txt")
  413. }
  414. func testTextFileWihoutExtension() {
  415. XCTAssertEqual(textFile.nameWithoutExtension, "filekit_test")
  416. XCTAssertEqual(textFileWithoutExt.nameWithoutExtension, "filekit_test")
  417. }
  418. func testTextFileExists() {
  419. do {
  420. try textFile.create()
  421. XCTAssertTrue(textFile.exists)
  422. } catch {
  423. XCTFail(String(describing: error))
  424. }
  425. }
  426. func testWriteToTextFile() {
  427. do {
  428. try textFile.write("This is some test.")
  429. try textFile.write("This is another test.", atomically: false)
  430. } catch {
  431. XCTFail(String(describing: error))
  432. }
  433. }
  434. func testTextFileOperators() {
  435. do {
  436. let text = "FileKit Test"
  437. try text |> textFile
  438. var contents = try textFile.read()
  439. XCTAssertTrue(contents.hasSuffix(text))
  440. try text |>> textFile
  441. contents = try textFile.read()
  442. XCTAssertTrue(contents.hasSuffix("\(text)\n\(text)"))
  443. } catch {
  444. XCTFail(String(describing: error))
  445. }
  446. }
  447. func testTextFileStreamReader() {
  448. do {
  449. let expectedLines = [
  450. "Lorem ipsum dolor sit amet",
  451. "consectetur adipiscing elit",
  452. "Sed non risus"
  453. ]
  454. let separator = "\n"
  455. try expectedLines.joined(separator: separator) |> textFile
  456. let reader = try textFile.streamReader()
  457. defer {
  458. reader.close()
  459. }
  460. var lines = [String]()
  461. for line in reader {
  462. lines.append(line)
  463. }
  464. XCTAssertEqual(expectedLines, lines)
  465. } catch {
  466. XCTFail(String(describing: error))
  467. }
  468. }
  469. func testTextFileGrep() {
  470. do {
  471. let expectedLines = [
  472. "Lorem ipsum dolor sit amet",
  473. "consectetur adipiscing elit",
  474. "Sed non risus"
  475. ]
  476. let separator = "\n"
  477. try expectedLines.joined(separator: separator) |> textFile
  478. // all
  479. var result = textFile | "e"
  480. XCTAssertEqual(result, expectedLines)
  481. // not all
  482. result = textFile |- "e"
  483. XCTAssertTrue(result.isEmpty)
  484. // specific line
  485. result = textFile | "eli"
  486. XCTAssertEqual(result, [expectedLines[1]])
  487. // the other line
  488. result = textFile |- "eli"
  489. XCTAssertEqual(result, [expectedLines[0], expectedLines[2]])
  490. // regex
  491. result = textFile |~ "e.*i.*e.*"
  492. XCTAssertEqual(result, [expectedLines[0], expectedLines[1]])
  493. // this not a regex
  494. result = textFile | "e.*i.*e.*"
  495. XCTAssertTrue(result.isEmpty)
  496. } catch {
  497. XCTFail(String(describing: error))
  498. }
  499. }
  500. func testTextFileStreamWritter() {
  501. if testFilePath.exists {
  502. try? testFilePath.deleteFile()
  503. }
  504. do {
  505. let lines = [
  506. "Lorem ipsum dolor sit amet",
  507. "consectetur adipiscing elit",
  508. "Sed non risus"
  509. ]
  510. let separator = "\n"
  511. let writer = try textFile.streamWriter(separator)
  512. defer {
  513. writer.close()
  514. }
  515. for line in lines {
  516. let delim = line != lines.last
  517. writer.write(line: line, delim: delim)
  518. }
  519. let expected = try textFile.read()
  520. let expectedLines = expected.components(separatedBy: separator)
  521. XCTAssertEqual(expectedLines, lines)
  522. } catch {
  523. XCTFail(String(describing: error))
  524. }
  525. }
  526. // MARK: - FileType
  527. func testFileTypeComparable() {
  528. let textFile1 = TextFile(path: .userTemporary + "filekit_test_comparable1.txt")
  529. let textFile2 = TextFile(path: .userTemporary + "filekit_test_comparable2.txt")
  530. do {
  531. try "1234567890" |> textFile1
  532. try "12345" |> textFile2
  533. XCTAssert(textFile1 > textFile2)
  534. } catch {
  535. XCTFail(String(describing: error))
  536. }
  537. }
  538. // MARK: - FilePermissions
  539. func testFilePermissions() {
  540. let swift: Path = "/usr/bin/swift"
  541. if swift.exists {
  542. XCTAssertTrue(swift.filePermissions.contains([.read, .execute]))
  543. }
  544. let file: Path = .userTemporary + "filekit_test_filepermissions"
  545. do {
  546. try file.createFile()
  547. XCTAssertTrue(file.filePermissions.contains([.read, .write]))
  548. } catch {
  549. XCTFail(String(describing: error))
  550. }
  551. }
  552. // MARK: - DictionaryFile
  553. let nsDictionaryFile = NSDictionaryFile(path: .userTemporary + "filekit_test_nsdictionary.plist")
  554. func testWriteToNSDictionaryFile() {
  555. do {
  556. let dict = NSMutableDictionary()
  557. dict["FileKit" as NSString] = true
  558. dict["Hello" as NSString] = "World"
  559. try nsDictionaryFile.write(dict)
  560. let contents = try nsDictionaryFile.read()
  561. XCTAssertEqual(contents, dict)
  562. } catch {
  563. XCTFail(String(describing: error))
  564. }
  565. }
  566. // MARK: - DictionaryFile
  567. let dictionaryFile = DictionaryFile<String, Any>(path: .userTemporary + "filekit_test_dictionary.plist")
  568. func testWriteToDictionaryFile() {
  569. do {
  570. var dict: [String: Any] = [:]
  571. dict["FileKit"] = true
  572. dict["Hello"] = "World"
  573. try dictionaryFile.write(dict)
  574. let contents = try dictionaryFile.read()
  575. XCTAssertEqual(contents.count, dict.count)
  576. for (kc, vc) in contents {
  577. let v = dict[kc]
  578. if let vb = v as? Bool , let vcb = vc as? Bool {
  579. XCTAssertEqual(vb, vcb)
  580. }
  581. else if let vb = v as? String , let vcb = vc as? String {
  582. XCTAssertEqual(vb, vcb)
  583. }
  584. else {
  585. XCTFail("unknow type")
  586. }
  587. }
  588. } catch {
  589. XCTFail(String(describing: error))
  590. }
  591. }
  592. // MARK: - ArrayFile
  593. let nsArrayFile = NSArrayFile(path: .userTemporary + "filekit_test_nsarray.plist")
  594. func testWriteToNSArrayFile() {
  595. do {
  596. let array: NSArray = ["ABCD", "WXYZ"]
  597. try nsArrayFile.write(array)
  598. let contents = try nsArrayFile.read()
  599. XCTAssertEqual(contents, array)
  600. } catch {
  601. XCTFail(String(describing: error))
  602. }
  603. }
  604. // MARK: - ArrayFile
  605. let arrayFile = ArrayFile<String>(path: .userTemporary + "filekit_test_array.plist")
  606. func testWriteToArrayFile() {
  607. do {
  608. let array = ["ABCD", "WXYZ"]
  609. try arrayFile.write(array)
  610. let contents = try arrayFile.read()
  611. XCTAssertEqual(contents, array)
  612. } catch {
  613. XCTFail(String(describing: error))
  614. }
  615. }
  616. // MARK: - NSDataFile
  617. let nsDataFile = NSDataFile(path: .userTemporary + "filekit_test_nsdata")
  618. func testWriteToNSDataFile() {
  619. do {
  620. let data = ("FileKit test" as NSString).data(using: String.Encoding.utf8.rawValue)! as NSData
  621. try nsDataFile.write(data)
  622. let contents = try nsDataFile.read()
  623. XCTAssertEqual(contents, data)
  624. } catch {
  625. XCTFail(String(describing: error))
  626. }
  627. }
  628. // MARK: - DataFile
  629. let dataFile = DataFile(path: .userTemporary + "filekit_test_data")
  630. func testWriteToDataFile() {
  631. do {
  632. let data = "FileKit test".data(using: String.Encoding.utf8)!
  633. try dataFile.write(data)
  634. let contents = try dataFile.read()
  635. XCTAssertEqual(contents, data)
  636. } catch {
  637. XCTFail(String(describing: error))
  638. }
  639. }
  640. // MARK: - String+FileKit
  641. let stringFile = File<String>(path: .userTemporary + "filekit_stringtest.txt")
  642. func testStringInitializationFromPath() {
  643. do {
  644. let message = "Testing string init..."
  645. try stringFile.write(message)
  646. let contents = try String(contentsOfPath: stringFile.path)
  647. XCTAssertEqual(contents, message)
  648. } catch {
  649. XCTFail(String(describing: error))
  650. }
  651. }
  652. func testStringWriting() {
  653. do {
  654. let message = "Testing string writing..."
  655. try message.write(to: stringFile.path)
  656. let contents = try String(contentsOfPath: stringFile.path)
  657. XCTAssertEqual(contents, message)
  658. } catch {
  659. XCTFail(String(describing: error))
  660. }
  661. }
  662. // MARK: - Image
  663. func testImageWriting() {
  664. let url = URL(string: "https://raw.githubusercontent.com/nvzqz/FileKit/assets/logo.png")!
  665. let img = Image(contentsOf: url) ?? Image()
  666. do {
  667. let path: Path = .userTemporary + "filekit_imagetest.png"
  668. try img.write(to: path)
  669. } catch {
  670. XCTFail(String(describing: error))
  671. }
  672. }
  673. // MARK: - Watch
  674. func testWatch() {
  675. let pathToWatch = .userTemporary + "filekit_test_watch"
  676. let expectation = "event"
  677. let operation = {
  678. do {
  679. let message = "Testing file system event when writing..."
  680. try message.write(to: pathToWatch, atomically: false)
  681. } catch {
  682. XCTFail(String(describing: error))
  683. }
  684. }
  685. // Do watch test
  686. let expt = self.expectation(description: expectation)
  687. let watcher = pathToWatch.watch { event in
  688. print(event)
  689. // XXX here could check expected event type according to operation
  690. expt.fulfill()
  691. }
  692. defer {
  693. watcher.close()
  694. }
  695. operation()
  696. self.waitForExpectations(timeout: 10, handler: nil)
  697. }
  698. // MARK: - Codable
  699. func testJSONCodable() {
  700. let encodable = TestJSONCodable(string: "test", integer: 9)
  701. let path: Path = .userTemporary + "testcodable.json"
  702. let codableFile = File<TestJSONCodable>(path: path)
  703. do {
  704. try codableFile.write(encodable)
  705. let decodable: TestJSONCodable = try codableFile.read()
  706. XCTAssertEqual(decodable, encodable)
  707. } catch {
  708. XCTFail(String(describing: error))
  709. }
  710. }
  711. func testCodable() {
  712. let encodable = TestCodable(string: "test", integer: 9)
  713. let path: Path = .userTemporary + "testcodable.plist"
  714. do {
  715. try FileKit.write(encodable, to: path)
  716. let decodable: TestCodable = try FileKit.read(from: path)
  717. XCTAssertEqual(decodable, encodable)
  718. } catch {
  719. XCTFail(String(describing: error))
  720. }
  721. }
  722. func testCodableArray() {
  723. let encodable = [TestCodable(string: "test", integer: 9), TestCodable(string: "test3", integer: 8)]
  724. let path: Path = .userTemporary + "testcodablearray.plist"
  725. do {
  726. try FileKit.write(encodable, to: path)
  727. let decodable: [TestCodable] = try FileKit.read(from: path)
  728. XCTAssertEqual(decodable, encodable)
  729. } catch {
  730. XCTFail(String(describing: error))
  731. }
  732. }
  733. }
  734. // MARK: Test objects
  735. struct TestCodable: Codable {
  736. let string: String
  737. let integer: Int
  738. }
  739. extension TestCodable: Equatable {
  740. static func == (l: TestCodable, r: TestCodable) -> Bool {
  741. return l.string == r.string && l.integer == r.integer
  742. }
  743. }
  744. struct TestJSONCodable: Codable {
  745. let string: String
  746. let integer: Int
  747. }
  748. extension TestJSONCodable: JSONWritable, JSONReadable {}
  749. extension TestJSONCodable: Equatable {
  750. static func == (l: TestJSONCodable, r: TestJSONCodable) -> Bool {
  751. return l.string == r.string && l.integer == r.integer
  752. }
  753. }
  754. struct TestPropertyListCodable: Codable {
  755. let string: String
  756. let integer: Int
  757. }
  758. extension TestPropertyListCodable: PropertyListWritable, PropertyListReadable {}
  759. extension TestPropertyListCodable: Equatable {
  760. static func == (l: TestPropertyListCodable, r: TestPropertyListCodable) -> Bool {
  761. return l.string == r.string && l.integer == r.integer
  762. }
  763. }