AutoTest.swift 40 KB

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