AutoTest.swift 39 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825
  1. //
  2. // AutoTest.swift
  3. // KdanAuto
  4. //
  5. // Created by 朱东勇 on 2022/11/25.
  6. //
  7. import Foundation
  8. import AppKit
  9. var cacheObjects = NSMutableDictionary()
  10. let operateQueue = OperationQueue()
  11. class AutoTest : NSObject, AutoTestProtocal {
  12. var reportString : NSMutableAttributedString? = nil
  13. public var _status : AutoTestStatus = .Normal
  14. var _fileType : String = "RTF"
  15. var _type : String = "Others"
  16. var _extention : String = "rtf"
  17. var _name : String = "对照测试"
  18. var _params : NSDictionary = [:]
  19. class func autoTestFor(_ fileType:NSString ,type:NSString) -> AutoTest? {
  20. let key = String(fileType) + "." + String(type)
  21. if cacheObjects.value(forKey: key) != nil {
  22. let object = cacheObjects.value(forKey: key)
  23. return object as? AutoTest
  24. }
  25. // if let cacheObject as AutoTest {
  26. // return cacheObject
  27. // }
  28. let fileTypes = testTypeInfo[fileType] as! NSArray
  29. let clsname = "KdanAuto"//Bundle.main.infoDictionary! ["CFBundleExecutable"]
  30. for item in fileTypes {
  31. let cItem = item as! NSDictionary
  32. let cType = cItem["Type"] as! NSString
  33. let cExtention = cItem["Extention"] as! NSString
  34. let cName = cItem["Name"] as! NSString
  35. let cParams = cItem["Params"] as? NSDictionary
  36. if (cType.isEqual(to: type)) {
  37. let className = String((clsname )+"."+(cItem["Class"] as! String))
  38. let cl = NSClassFromString(className) as! AutoTest.Type
  39. let object = cl.shared()
  40. object?._fileType = fileType as String
  41. object?._type = String(cType)
  42. object?._extention = String(cExtention)
  43. object?._name = String(cName)
  44. if nil != cParams {
  45. object?._params = cParams ?? [:];
  46. }
  47. cacheObjects.setValue(object, forKey: key)
  48. return object
  49. }
  50. }
  51. let object = AutoTest.shared()
  52. object?._fileType = fileType as String
  53. object?._type = String(cType)
  54. object?._extention = ""
  55. object?._name = "对照测试"
  56. cacheObjects.setValue(object, forKey: key)
  57. return object
  58. }
  59. class func shared() -> AutoTest? {
  60. return AutoTest()
  61. }
  62. func fileType() -> String {
  63. return _fileType
  64. }
  65. func type() -> String {
  66. return _type
  67. }
  68. func name() -> String {
  69. return _name
  70. }
  71. func extention() -> String {
  72. return _extention
  73. }
  74. func params() -> NSDictionary {
  75. return _params
  76. }
  77. func keys() -> NSArray {
  78. return ["快照"]
  79. }
  80. func selectedKeys() -> NSArray {
  81. let userDefaults = UserDefaults.standard
  82. let key = self.fileType() + "." + self.type() + ".selectedKeys"
  83. if userDefaults.value(forKey: key) != nil {
  84. return userDefaults.value(forKey: key) as! NSArray
  85. }
  86. self.setSelectedKeys(self.keys())
  87. return self.keys()
  88. }
  89. func setSelectedKeys(_ keys: NSArray) {
  90. let userDefaults = UserDefaults.standard
  91. let key = self.fileType() + "." + self.type() + ".selectedKeys"
  92. userDefaults.setValue(keys, forKey: key)
  93. userDefaults.synchronize()
  94. }
  95. func needCompareTest() -> Bool {
  96. return self.selectedKeys().contains("快照")
  97. }
  98. func status() -> AutoTestStatus {
  99. return _status
  100. }
  101. func setStatus(_ status:AutoTestStatus) {
  102. _status = status
  103. }
  104. // Auto Test
  105. func autoTest(_ complention:@escaping (_ object:AutoTest, _ report:NSAttributedString?) -> ()) {
  106. clearCacheFiles()
  107. NSLog(String("转换\(self.type())"))
  108. let needCompare = self.selectedKeys().contains("快照")
  109. if !needCompare {
  110. // 未勾选 ”快照“ 选项
  111. self._status = .Finished
  112. complention(self, self.reportString)
  113. return
  114. }
  115. if hasOriginFile() {
  116. //目录中有需要执行对照的文件
  117. DispatchQueue.global().async {
  118. self._status = .Process
  119. self.reportString = NSMutableAttributedString.init(string: "\n【\(String(self.fileType())) - \(self.name())】快照比对开始!\n",
  120. attributes:[.foregroundColor : NSColor.blue])
  121. let files = DataModel.shared.originFilesFor(self.fileType(), type: self.type()) as [String]
  122. let checkDirectory = self.checkFileDirectory()
  123. let originDirectory = self.originFileDirectory()
  124. let resultDirectory = self.resultFileDirectory()
  125. if (files.count > 0) {
  126. try? FileManager.default.createDirectory(atPath: checkDirectory, withIntermediateDirectories: true);
  127. try? FileManager.default.createDirectory(atPath: resultDirectory, withIntermediateDirectories: true);
  128. }
  129. var tDegree = Double(0);
  130. var tCount = Int(0)
  131. var fileIndex = 0
  132. // 用 Block 递归调用形式,确保转档单任务执行
  133. var convertFileBlock = { (files:[String]) in }
  134. convertFileBlock = { (files:[String]) in
  135. if (fileIndex >= files.count) {
  136. //所有任务已经执行完成
  137. TestDegreeManager.shared().set(((tCount != 0) ? tDegree/Double(tCount) : 0.0),
  138. fileType: self.fileType(),
  139. type: self.type())
  140. self._status = .Finished
  141. DispatchQueue.main.async {
  142. complention(self, self.reportString);
  143. }
  144. return
  145. }
  146. //
  147. let fileName = files[fileIndex];
  148. autoreleasepool {
  149. let checkDirectory = self.checkFileDirectory()
  150. let originDirectory = self.originFileDirectory()
  151. let resultDirectory = self.resultFileDirectory()
  152. let fName = NSString(string: fileName).deletingPathExtension
  153. let originPath = NSString(string: originDirectory).appendingPathComponent(fName+".pdf")
  154. let resultPath = NSString(string: resultDirectory).appendingPathComponent(fName+"."+self.extention())
  155. // let checkPath = NSString(string: checkDirectory).appendingPathComponent(fName+"."+_extention)
  156. self.reportString?.append(NSMutableAttributedString.init(string: "【\(String(self.fileType())) - \(self.name())】开始转换文件 \"\(fName)\"\n",
  157. attributes:[.foregroundColor : NSColor.blue]))
  158. // ...
  159. // 执行异步转换过程
  160. self.process(originPath, resultPath: resultPath) { status in
  161. self.compareResult(fileName, resultPath: resultPath, status: status, needCompare: needCompare) { degree in
  162. autoreleasepool {
  163. fileIndex += 1;
  164. convertFileBlock(files)
  165. }
  166. };
  167. }
  168. }
  169. }
  170. // 启动第0号任务
  171. convertFileBlock(files);
  172. }
  173. }else {
  174. _status = .Normal
  175. DispatchQueue.main.async {
  176. complention(self, nil)
  177. }
  178. }
  179. }
  180. func process(_ originPath:String, resultPath:String, complention:@escaping (_ status:Int) -> ()) {
  181. return process(originPath, resultPath: resultPath, params: self.params(), complention: complention)
  182. }
  183. func process(_ originPath:String, resultPath:String, params:NSDictionary, complention:@escaping (_ status:Int) -> ()) {
  184. FileConverter.shared().converter(originPath, inDesPath: resultPath, params: params) { status in
  185. // 修复转 PNG 实际图片为 JPG 问题, 导致无法匹配问题
  186. if (NSArray(array: ["png", "PNG"]).contains(NSString(string: resultPath).pathExtension)) {
  187. let items = (FileManager.default.subpaths(atPath: resultPath) ?? []) as [String]
  188. for item in items {
  189. if NSArray(array: ["jpg", "JPG"]).contains(NSString(string:item).pathExtension) {
  190. let path = NSString(string: resultPath).appendingPathComponent(item);
  191. try? FileManager.default.moveItem(atPath: path,
  192. toPath: NSString(string: path).deletingPathExtension+".png");
  193. }
  194. }
  195. }
  196. complention(status)
  197. }
  198. }
  199. func compareResult(_ fileName:String, resultPath:String, status:Int, needCompare:Bool, complention:@escaping (_ degree:Double) -> ()) {
  200. let checkDirectory = self.checkFileDirectory()
  201. // let originDirectory = self.originFileDirectory()
  202. let resultDirectory = self.resultFileDirectory()
  203. let fName = NSString(string: fileName).deletingPathExtension
  204. var isDirectory = ObjCBool(false)
  205. if FileManager.default.fileExists(atPath: resultPath, isDirectory:&isDirectory) && status == 1 {
  206. // compare screenshoot between result file with check file
  207. if needCompare {
  208. let items = NSMutableArray()
  209. if (isDirectory.boolValue) {
  210. let searchItems = try! FileManager.default.contentsOfDirectory(atPath: resultPath)
  211. for item in NSArray(array: searchItems) {
  212. let ext = NSString(string: item as! String).pathExtension.lowercased()
  213. if (NSArray(array: [self.extention()]).contains(ext)) {
  214. let fileName = NSString(string: fName+"."+self.extention()+"/\(item as! String)").deletingPathExtension
  215. items.add(fileName)
  216. }
  217. }
  218. }else {
  219. items.add(fName)
  220. }
  221. var subDegree = Double(0);
  222. var subCount = Int(0)
  223. var itemIndex = 0;
  224. // let maxProcessCount = min(3, max(items.count, 1))
  225. var processItemBlock = {(items:NSMutableArray) in
  226. }
  227. processItemBlock = {(items:NSMutableArray) in
  228. if (itemIndex >= items.count) {
  229. // if (itemIndex >= (items.count + (maxProcessCount - 1))) {
  230. if subCount != 0 {
  231. subDegree = subDegree/Double(subCount)
  232. }else {
  233. subDegree = 0.0
  234. }
  235. TestDegreeManager.shared().set(subDegree,
  236. fileType: self.fileType(),
  237. type: self.type(),
  238. fileName: fileName)
  239. DispatchQueue.global().async {
  240. autoreleasepool {
  241. // 执行下一个文件转档
  242. complention(subDegree)
  243. }
  244. }
  245. // }
  246. return
  247. }
  248. DispatchQueue.global().async {
  249. autoreleasepool {
  250. let item = items[itemIndex]
  251. NSLog("\(itemIndex):\(item)")
  252. let subFileName = item as! String
  253. let subResultPath = NSString(string: resultDirectory).appendingPathComponent(subFileName+"."+self.extention())
  254. objc_sync_enter(self)
  255. self.reportString?.append(NSMutableAttributedString.init(string: "【\(String(self.fileType())) - \(self.name())】文件 \"\(subFileName+".\(self.extention())")\"快照生成中\n",
  256. attributes:[.foregroundColor : NSColor.black]))
  257. objc_sync_exit(self)
  258. let rComparePath = NSString(string: resultDirectory).appendingPathComponent(subFileName+".jpg")
  259. let cComparePath = NSString(string: checkDirectory).appendingPathComponent(subFileName+".jpg")
  260. ProcessThumbnal.process(subResultPath, desPath: rComparePath, outputSize: CGSize.init(width: 2048, height: 2048)) { processSuccess in
  261. autoreleasepool {
  262. if ( processSuccess &&
  263. FileManager.default.fileExists(atPath: rComparePath)) {
  264. var isDirectory = ObjCBool(false)
  265. if FileManager.default.fileExists(atPath: rComparePath, isDirectory: &isDirectory) && isDirectory.boolValue {
  266. // 单个文件生成批量快照目录情形
  267. let subImages = try! FileManager.default.contentsOfDirectory(atPath: rComparePath)
  268. var compareCount = 0;
  269. for sImageName in subImages {
  270. let subImageName = sImageName
  271. autoreleasepool {
  272. let pathCompotent = "/"+subImageName
  273. ImageProcess.compareJPEG(String(rComparePath+pathCompotent), checkPath: String(cComparePath+pathCompotent), processCover: true, complention: { degree in
  274. NSLog(String("文件夹,\(subFileName+".jpg"+pathCompotent)"))
  275. TestDegreeManager.shared().set(degree, fileType: self.fileType(), type: self.type(),
  276. fileName: fileName, refFilePath: subFileName+".jpg"+pathCompotent)
  277. if degree == -1 {
  278. objc_sync_enter(self)
  279. self.reportString?.append(NSMutableAttributedString.init(string: "【\(String(self.fileType())) - \(self.name())】文件 \"\(subResultPath+pathCompotent)\"快照对比失败,生成快照失败或无比对文件\n",
  280. attributes:[.foregroundColor : NSColor.red]))
  281. objc_sync_exit(self)
  282. }else {
  283. var color = NSColor.black
  284. if fabs(degree-100.0) >= 0.01 {
  285. color = NSColor.red
  286. }
  287. subDegree += degree
  288. subCount += 1
  289. objc_sync_enter(self)
  290. self.reportString?.append(NSMutableAttributedString.init(string: "【\(String(self.fileType())) - \(self.name())】文件 \"\(subResultPath+pathCompotent)\"快照对比完成,图像相似度 \(degree)%\n",
  291. attributes:[.foregroundColor : color]))
  292. objc_sync_exit(self)
  293. }
  294. compareCount += 1
  295. if (compareCount >= subImages.count) {
  296. DispatchQueue.global().async {
  297. itemIndex += 1
  298. processItemBlock(items)
  299. }
  300. }
  301. })
  302. }
  303. }
  304. if (subImages.count == 0) {
  305. // complention
  306. DispatchQueue.global().async {
  307. itemIndex += 1
  308. processItemBlock(items)
  309. }
  310. return
  311. }
  312. }else {
  313. // 单个文件生成单个快照文件情形
  314. ImageProcess.compareJPEG(rComparePath, checkPath: cComparePath, processCover: true, complention: { degree in
  315. NSLog(String("非文件夹,\(subFileName+".jpg")"))
  316. TestDegreeManager.shared().set(degree, fileType: self.fileType(), type: self.type(),
  317. fileName: fileName, refFilePath: subFileName+".jpg")
  318. if degree == -1 {
  319. self.reportString?.append(NSMutableAttributedString.init(string: "【\(String(self.fileType())) - \(self.name())】文件 \"\(subResultPath)\"快照对比失败,生成快照失败或无比对文件\n",
  320. attributes:[.foregroundColor : NSColor.red]))
  321. }else {
  322. var color = NSColor.black
  323. if fabs(degree-100.0) >= 0.01 {
  324. color = NSColor.red
  325. }
  326. subDegree += degree
  327. subCount += 1
  328. self.reportString?.append(NSMutableAttributedString.init(string: "【\(String(self.fileType())) - \(self.name())】文件 \"\(subResultPath)\"快照对比完成,图像相似度 \(degree)%\n",
  329. attributes:[.foregroundColor : color]))
  330. }
  331. // complention
  332. DispatchQueue.global().async {
  333. itemIndex += 1
  334. processItemBlock(items)
  335. }
  336. })
  337. }
  338. }else {
  339. self.reportString?.append(NSMutableAttributedString.init(string: "【\(String(self.fileType())) - \(self.name())】文件 \"\(subResultPath)\"快照生成失败\n",
  340. attributes:[.foregroundColor : NSColor.red]))
  341. // complention
  342. DispatchQueue.global().async {
  343. itemIndex += 1
  344. processItemBlock(items)
  345. }
  346. }
  347. }
  348. }
  349. }
  350. }
  351. }
  352. processItemBlock(items)
  353. // while (itemIndex < (maxProcessCount - 1)) {
  354. // itemIndex += 1;
  355. // processItemBlock(items)
  356. // }
  357. return
  358. }
  359. }else {
  360. if (status == 0) {
  361. self.reportString?.append(NSMutableAttributedString.init(string: "【\(String(self.fileType())) - \(self.name())】文件 \"\(fName)\"转档失败!\n",
  362. attributes:[.foregroundColor : NSColor.red]))
  363. }else if (status == -1 || status == -2) {
  364. self.reportString?.append(NSMutableAttributedString.init(string: "【\(String(self.fileType())) - \(self.name())】文件 \"\(fName)\"文档无法打开!\n",
  365. attributes:[.foregroundColor : NSColor.red]))
  366. }else if (status == -3) {
  367. self.reportString?.append(NSMutableAttributedString.init(string: "【\(String(self.fileType())) - \(self.name())】文件 \"\(fName)\"转档中 Crash!\n",
  368. attributes:[.foregroundColor : NSColor.red]))
  369. }
  370. }
  371. DispatchQueue.global().async {
  372. autoreleasepool {
  373. // 执行下一个文件转档
  374. complention(0)
  375. }
  376. }
  377. }
  378. ///
  379. func testReport() -> NSAttributedString? {
  380. return reportString
  381. }
  382. func degree() -> Double {
  383. return TestDegreeManager.shared().degreeFor(self.fileType(), type: self.type())
  384. }
  385. // func testReportOfFile(_ fileName:String) -> NSAttributedString? {
  386. //
  387. // }
  388. func degreeOfFile(_ fileName:String) -> Double {
  389. return TestDegreeManager.shared().degreeFor(self.fileType(), type: self.type(), fileName: fileName)
  390. }
  391. func degreeOfFile(_ fileName:String, refFilePath:String?) -> Double {
  392. if refFilePath != nil {
  393. return TestDegreeManager.shared().degreeFor(self.fileType(), type: self.type(), fileName: fileName, refFilePath: refFilePath)
  394. }else {
  395. return degreeOfFile(fileName)
  396. }
  397. }
  398. // Update Refrence image
  399. func canUpdateRefImage() -> Bool {
  400. let files = DataModel.shared.originFilesFor(_fileType, type: _type) as [String]
  401. let checkDirectory = self.checkFileDirectory()
  402. // let originDirectory = self.originFileDirectory()
  403. let resultDirectory = self.resultFileDirectory()
  404. for fileName in files {
  405. let fName = NSString(string: fileName).deletingPathExtension
  406. // let originPath = NSString(string: originDirectory).appendingPathComponent(fName+".pdf")
  407. let resultPath = NSString(string: resultDirectory).appendingPathComponent(fName+"."+_extention)
  408. // let checkPath = NSString(string: checkDirectory).appendingPathComponent(fName+"."+_extention)
  409. var isDirectory = ObjCBool(false)
  410. if FileManager.default.fileExists(atPath: resultPath, isDirectory:&isDirectory) {
  411. // compare screenshoot between result file with check file
  412. let items = NSMutableArray()
  413. if (isDirectory.boolValue) {
  414. let searchItems = try! FileManager.default.contentsOfDirectory(atPath: resultPath)
  415. for item in NSArray(array: searchItems) {
  416. let ext = NSString(string: item as! String).pathExtension.lowercased()
  417. if NSArray(array: [_extention]).contains(ext) {
  418. let fileName = NSString(string: fName+"."+_extention+"/\(item as! String)").deletingPathExtension
  419. items.add(fileName)
  420. }
  421. }
  422. }else {
  423. items.add(fName)
  424. }
  425. for item in items {
  426. let subFileName = item as! String
  427. let rComparePath = NSString(string: resultDirectory).appendingPathComponent(subFileName+".jpg")
  428. let cComparePath = NSString(string: checkDirectory).appendingPathComponent(subFileName+".jpg")
  429. if FileManager.default.fileExists(atPath: rComparePath) {
  430. if !FileManager.default.fileExists(atPath: cComparePath) {
  431. return true
  432. }
  433. let rfs = try! FileManager.default.attributesOfItem(atPath: rComparePath)[FileAttributeKey.size] as! NSNumber
  434. let cfs = try! FileManager.default.attributesOfItem(atPath: cComparePath)[FileAttributeKey.size] as! NSNumber
  435. if rfs.int64Value != cfs.int64Value {
  436. return true
  437. }
  438. }
  439. }
  440. }
  441. }
  442. return false
  443. }
  444. func updateRefImage() {
  445. let files = DataModel.shared.originFilesFor(_fileType, type: _type) as [String]
  446. for fileName in files {
  447. updateRefImage(fileName)
  448. }
  449. }
  450. func canUpdateRefImage(_ fileName:String) -> Bool {
  451. let checkDirectory = self.checkFileDirectory()
  452. // let originDirectory = self.originFileDirectory()
  453. let resultDirectory = self.resultFileDirectory()
  454. let fName = NSString(string: fileName).deletingPathExtension
  455. // let originPath = NSString(string: originDirectory).appendingPathComponent(fName+".pdf")
  456. let resultPath = NSString(string: resultDirectory).appendingPathComponent(fName+"."+_extention)
  457. // let checkPath = NSString(string: checkDirectory).appendingPathComponent(fName+"."+_extention)
  458. var isDirectory = ObjCBool(false)
  459. if FileManager.default.fileExists(atPath: resultPath, isDirectory:&isDirectory) {
  460. // compare screenshoot between result file with check file
  461. let items = NSMutableArray()
  462. if (isDirectory.boolValue) {
  463. let searchItems = try! FileManager.default.contentsOfDirectory(atPath: resultPath)
  464. for item in NSArray(array: searchItems) {
  465. let ext = NSString(string: item as! String).pathExtension.lowercased()
  466. if NSArray(array: [_extention]).contains(ext) {
  467. let fileName = NSString(string: fName+"."+_extention+"/\(item as! String)").deletingPathExtension
  468. items.add(fileName)
  469. }
  470. }
  471. }else {
  472. items.add(fName)
  473. }
  474. for item in items {
  475. let subFileName = item as! String
  476. let rComparePath = NSString(string: resultDirectory).appendingPathComponent(subFileName+".jpg")
  477. let cComparePath = NSString(string: checkDirectory).appendingPathComponent(subFileName+".jpg")
  478. if FileManager.default.fileExists(atPath: rComparePath) {
  479. if !FileManager.default.fileExists(atPath: cComparePath) {
  480. return true
  481. }
  482. let rfs = try! FileManager.default.attributesOfItem(atPath: rComparePath)[FileAttributeKey.size] as! NSNumber
  483. let cfs = try! FileManager.default.attributesOfItem(atPath: cComparePath)[FileAttributeKey.size] as! NSNumber
  484. if rfs.int64Value != cfs.int64Value {
  485. return true
  486. }
  487. }
  488. }
  489. }
  490. return false
  491. }
  492. func updateRefImage(_ fileName:String) {
  493. let checkDirectory = self.checkFileDirectory()
  494. // let originDirectory = self.originFileDirectory()
  495. let resultDirectory = self.resultFileDirectory()
  496. let fName = NSString(string: fileName).deletingPathExtension
  497. // let originPath = NSString(string: originDirectory).appendingPathComponent(fName+".pdf")
  498. let resultPath = NSString(string: resultDirectory).appendingPathComponent(fName+"."+_extention)
  499. // let checkPath = NSString(string: checkDirectory).appendingPathComponent(fName+"."+_extention)
  500. var isDirectory = ObjCBool(false)
  501. if FileManager.default.fileExists(atPath: resultPath, isDirectory:&isDirectory) {
  502. // compare screenshoot between result file with check file
  503. let items = NSMutableArray()
  504. if (isDirectory.boolValue) {
  505. let searchItems = try! FileManager.default.contentsOfDirectory(atPath: resultPath)
  506. for item in NSArray(array: searchItems) {
  507. let ext = NSString(string: item as! String).pathExtension.lowercased()
  508. if NSArray(array: [_extention]).contains(ext) {
  509. let fileName = NSString(string: fName+"."+_extention+"/\(item as! String)").deletingPathExtension
  510. items.add(fileName)
  511. }
  512. }
  513. }else {
  514. items.add(fName)
  515. }
  516. for item in items {
  517. let subFileName = item as! String
  518. let rComparePath = NSString(string: resultDirectory).appendingPathComponent(subFileName+".jpg")
  519. let cComparePath = NSString(string: checkDirectory).appendingPathComponent(subFileName+".jpg")
  520. if FileManager.default.fileExists(atPath: rComparePath) {
  521. if FileManager.default.fileExists(atPath: cComparePath) {
  522. try! FileManager.default.removeItem(atPath: cComparePath)
  523. }
  524. try! FileManager.default.createDirectory(atPath: NSString(string: cComparePath).deletingLastPathComponent,
  525. withIntermediateDirectories: true)
  526. try! FileManager.default.copyItem(atPath: rComparePath, toPath: cComparePath)
  527. }
  528. }
  529. }
  530. }
  531. func compareFiles() -> NSArray? {
  532. let items = NSMutableArray()
  533. let files = DataModel.shared.originFilesFor(_fileType, type: _type) as [String]
  534. for fileName in files {
  535. let sItems = compareFiles(fileName)
  536. if sItems != nil && sItems!.count != 0 {
  537. items.addObjects(from: sItems as! [Any])
  538. }
  539. }
  540. return items
  541. }
  542. func compareFiles(_ fileName: String) -> NSArray? {
  543. let files = NSMutableArray()
  544. let checkDirectory = self.checkFileDirectory()
  545. // let originDirectory = self.originFileDirectory()
  546. let resultDirectory = self.resultFileDirectory()
  547. let fName = NSString(string: fileName).deletingPathExtension
  548. // let originPath = NSString(string: originDirectory).appendingPathComponent(fName+".pdf")
  549. let resultPath = NSString(string: resultDirectory).appendingPathComponent(fName+"."+_extention)
  550. // let checkPath = NSString(string: checkDirectory).appendingPathComponent(fName+"."+_extention)
  551. var isDirectory = ObjCBool(false)
  552. if FileManager.default.fileExists(atPath: resultPath, isDirectory:&isDirectory) {
  553. // compare screenshoot between result file with check file
  554. let items = NSMutableArray()
  555. if (isDirectory.boolValue) {
  556. let searchItems = try! FileManager.default.contentsOfDirectory(atPath: resultPath)
  557. for item in NSArray(array: searchItems) {
  558. let ext = NSString(string: item as! String).pathExtension.lowercased()
  559. if (NSArray(array: [_extention]).contains(ext) &&
  560. !NSString(string: item as! String).contains("_cover.png")) {
  561. let fileName = NSString(string: fName+"."+_extention+"/\(item as! String)").deletingPathExtension
  562. items.add(fileName)
  563. }
  564. }
  565. }else {
  566. items.add(fName)
  567. }
  568. let nitems = items.sortedArray { str1, str2 in
  569. let s1 = NSString(string: str1 as! String).deletingPathExtension
  570. let s2 = NSString(string: str2 as! String).deletingPathExtension
  571. if (NSString(string: s1).length != NSString(string: s2).length) {
  572. if (NSString(string: s1).length > NSString(string: s2).length) {
  573. return .orderedDescending
  574. }else {
  575. return .orderedAscending
  576. }
  577. }
  578. return NSString(string: s1).compare(s2)
  579. }
  580. for item in nitems {
  581. let subFileName = item as! String
  582. let rComparePath = NSString(string: resultDirectory).appendingPathComponent(subFileName+".jpg")
  583. let cComparePath = NSString(string: checkDirectory).appendingPathComponent(subFileName+".jpg")
  584. let fileInfo = NSMutableDictionary.fileInfoWith(fileName,
  585. refFilePath: subFileName+".jpg",
  586. resultPath: rComparePath,
  587. comparePath: cComparePath,
  588. objc: self)
  589. files.add(fileInfo)
  590. }
  591. }
  592. return files
  593. }
  594. /// Path
  595. func originFileDirectory() -> String {
  596. return DataModel.shared.directoryPath().appendingFormat("/\(self.fileType())/\(self.type())/\(kOriginPathComponent)")
  597. }
  598. func resultFileDirectory() -> String {
  599. return DataModel.shared.directoryPath().appendingFormat("/\(self.fileType())/\(self.type())/\(kResultPathComponent)")
  600. }
  601. func checkFileDirectory() -> String {
  602. return DataModel.shared.directoryPath().appendingFormat("/\(self.fileType())/\(self.type())/\(kCheckPathComponent)")
  603. }
  604. // check File Exist
  605. func hasOriginFile() -> Bool {
  606. if FileManager.default.fileExists(atPath: self.originFileDirectory()) {
  607. let files = try? FileManager.default.subpathsOfDirectory(atPath: self.originFileDirectory())
  608. return (files ?? []).count > 0
  609. }
  610. return false
  611. }
  612. func hasResultFile() -> Bool {
  613. if FileManager.default.fileExists(atPath: self.resultFileDirectory()) {
  614. let files = try? FileManager.default.subpathsOfDirectory(atPath: self.resultFileDirectory())
  615. return (files ?? []).count > 0
  616. }
  617. return false
  618. }
  619. ///
  620. func clearCacheFiles() {
  621. reportString = NSMutableAttributedString.init();
  622. let resultDirectory = self.resultFileDirectory()
  623. var isDirectory = ObjCBool(false)
  624. if FileManager.default.fileExists(atPath: resultDirectory, isDirectory: &isDirectory) && isDirectory.boolValue {
  625. let searchItems = try! FileManager.default.contentsOfDirectory(atPath: resultDirectory)
  626. for item in NSArray(array: searchItems) {
  627. let path = NSString(string: resultDirectory).appendingPathComponent(item as! String)
  628. if FileManager.default.fileExists(atPath: path) {
  629. try! FileManager.default.removeItem(atPath: path)
  630. }
  631. }
  632. }
  633. }
  634. }
  635. extension AutoTest {
  636. func stringToImage(_ string:String) ->NSImage? {
  637. let length = Int(string.lengthOfBytes(using: .utf8)/2)
  638. let bytes = malloc(length)!
  639. for i in 0..<length {
  640. let index = i
  641. let subString = String(NSString(string: string).substring(with: NSMakeRange(Int(index * 2), 2)))
  642. bytes.storeBytes(of: UInt8(hexForString(subString)), as: UInt8.self)
  643. }
  644. let data = Data.init(bytes: bytes, count: length)
  645. let image = NSImage.init(data: data)
  646. return image
  647. }
  648. func hexForString(_ string:String) -> UInt8 {
  649. let chars = string.utf8CString
  650. if (string.lengthOfBytes(using: .utf8) >= 2) {
  651. return UInt8(intvalueForChar(chars[0]) * 16 + intvalueForChar(chars[1]))
  652. }
  653. return UInt8(0)
  654. }
  655. func intvalueForChar(_ char:CChar) -> UInt8 {
  656. let iValue = char
  657. // 0 ~ 9s
  658. if iValue >= 48 && iValue <= 57 {
  659. return UInt8(iValue - 48)
  660. }else if iValue >= 65 && iValue <= 70 {
  661. return UInt8(iValue - 65 + 10)
  662. }else if iValue >= 97 && iValue <= 102 {
  663. return UInt8(iValue - 97 + 10)
  664. }
  665. return UInt8(0)
  666. }
  667. }
  668. extension AutoTest {
  669. func isEqual(to object: AutoTest) -> Bool {
  670. return (NSString(string: self.className).isEqual(to: object.className) &&
  671. NSString(string: self.fileType()).isEqual(to: object.fileType()) &&
  672. NSString(string: self.type()).isEqual(to: object.type()) &&
  673. NSString(string: _extention).isEqual(to: object._extention))
  674. }
  675. }