|
| 1 | +import Foundation |
| 2 | +@testable import MongoSwift |
| 3 | +import XCTest |
| 4 | + |
| 5 | +extension MongoSwiftTestCase { |
| 6 | + /// Gets the path of the directory containing spec files, depending on whether |
| 7 | + /// we're running from XCode or the command line |
| 8 | + static var specsPath: String { |
| 9 | + // if we can access the "/Tests" directory, assume we're running from command line |
| 10 | + if FileManager.default.fileExists(atPath: "./Tests") { |
| 11 | + return "./Tests/Specs" |
| 12 | + } |
| 13 | + // otherwise we're in Xcode, get the bundle's resource path |
| 14 | + guard let path = Bundle(for: self).resourcePath else { |
| 15 | + XCTFail("Missing resource path") |
| 16 | + return "" |
| 17 | + } |
| 18 | + return path |
| 19 | + } |
| 20 | +} |
| 21 | + |
| 22 | +extension Document { |
| 23 | + init(fromJSONFile file: URL) throws { |
| 24 | + let jsonString = try String(contentsOf: file, encoding: .utf8) |
| 25 | + try self.init(fromJSON: jsonString) |
| 26 | + } |
| 27 | +} |
| 28 | + |
| 29 | +/// Given a spec folder name (e.g. "crud") and optionally a subdirectory name for a folder (e.g. "read") retrieves an |
| 30 | +/// array of [(filename, file decoded to type T)]. |
| 31 | +internal func retrieveSpecTestFiles<T: Decodable>(specName: String, |
| 32 | + subdirectory: String? = nil, |
| 33 | + asType: T.Type) throws -> [(String, T)] { |
| 34 | + var path = "\(MongoSwiftTestCase.specsPath)/\(specName)/tests" |
| 35 | + if let sd = subdirectory { |
| 36 | + path += "/\(sd)" |
| 37 | + } |
| 38 | + return try FileManager.default |
| 39 | + .contentsOfDirectory(atPath: path) |
| 40 | + .filter { $0.hasSuffix(".json") } |
| 41 | + .map { ($0, URL(fileURLWithPath: "\(path)/\($0)")) } |
| 42 | + .map { ($0.0, try Document(fromJSONFile: $0.1)) } |
| 43 | + .map { ($0.0, try BSONDecoder().decode(T.self, from: $0.1)) } |
| 44 | +} |
| 45 | + |
| 46 | +/// Given two documents, returns a copy of the input document with all keys that *don't* |
| 47 | +/// exist in `standard` removed, and with all matching keys put in the same order they |
| 48 | +/// appear in `standard`. |
| 49 | +internal func rearrangeDoc(_ input: Document, toLookLike standard: Document) -> Document { |
| 50 | + var output = Document() |
| 51 | + for (k, v) in standard { |
| 52 | + // if it's a document, recursively rearrange to look like corresponding sub-document |
| 53 | + if let sDoc = v as? Document, let iDoc = input[k] as? Document { |
| 54 | + output[k] = rearrangeDoc(iDoc, toLookLike: sDoc) |
| 55 | + |
| 56 | + // if it's an array, recursively rearrange to look like corresponding sub-array |
| 57 | + } else if let sArr = v as? [Document], let iArr = input[k] as? [Document] { |
| 58 | + var newArr = [Document]() |
| 59 | + for (i, el) in iArr.enumerated() { |
| 60 | + newArr.append(rearrangeDoc(el, toLookLike: sArr[i])) |
| 61 | + } |
| 62 | + output[k] = newArr |
| 63 | + // just copy the value over as is |
| 64 | + } else { |
| 65 | + output[k] = input[k] |
| 66 | + } |
| 67 | + } |
| 68 | + return output |
| 69 | +} |
0 commit comments