1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135
|
/*
This source file is part of the Swift.org open source project
Copyright (c) 2021-2024 Apple Inc. and the Swift project authors
Licensed under Apache License v2.0 with Runtime Library Exception
See https://swift.org/LICENSE.txt for license information
See https://swift.org/CONTRIBUTORS.txt for Swift project authors
*/
@testable import SwiftDocC
@testable import SwiftDocCUtilities
import XCTest
import SwiftDocCTestUtilities
/*
This file contains a test helper API for working with folder hierarchies, with the ability to:
1. write a hierarchy of folders and files to disk
2. verify that a hierarchy of folders and files exist on disk
*/
protocol AssertableFile: File {
/// Asserts that a file exist a given URL.
func __assertExist(at location: URL, fileManager: FileManagerProtocol, file: StaticString, line: UInt) // Implement this since protocol methods can't have default arguments.
}
extension AssertableFile {
/// Asserts that a file exist a given URL.
func assertExist(at location: URL, fileManager: FileManagerProtocol = FileManager.default, file: StaticString = #file, line: UInt = #line) {
__assertExist(at: location, fileManager: fileManager, file: (file), line: line)
}
}
extension AssertableFile {
/// Writes the file inside of a folder and returns the URL that it was written to.
func write(inside url: URL) throws -> URL {
let outputURL = url.appendingPathComponent(name)
try write(to: outputURL)
return outputURL
}
}
// MARK: -
extension Folder: AssertableFile {
func __assertExist(at location: URL, fileManager: FileManagerProtocol, file: StaticString = #file, line: UInt = #line) {
var isFolder: ObjCBool = false
XCTAssert(fileManager.fileExists(atPath: location.path, isDirectory: &isFolder),
"Folder '\(name)' should exist at '\(location.path)'", file: (file), line: line)
XCTAssert(isFolder.boolValue,
"Folder '\(name)' should be a folder", file: (file), line: line)
for fileOrFolder in content as! [AssertableFile] {
fileOrFolder.assertExist(at: location.appendingPathComponent(fileOrFolder.name), fileManager: fileManager, file: (file), line: line)
}
}
}
extension InfoPlist: AssertableFile {
func __assertExist(at location: URL, fileManager: FileManagerProtocol, file: StaticString, line: UInt) {
XCTAssert(fileManager.fileExists(atPath: location.path),
"File '\(name)' should exist at '\(location.path)'", file: (file), line: line)
// TODO: Replace this with PropertListDecoder (see below) when it's available in swift-corelibs-foundation
// https://github.com/apple/swift-corelibs-foundation/commit/d2d72f88d93f7645b94c21af88a7c9f69c979e4f
do {
guard let infoPlistData = fileManager.contents(atPath: location.path) else {
XCTFail("File '\(name)' does not exist at path \(location.path.singleQuoted)", file: (file), line: line)
return
}
let infoPlist = try PropertyListSerialization.propertyList(from: infoPlistData, options: [], format: nil) as? [String: String]
let displayName = infoPlist?["CFBundleIdentifier"]
let identifier = infoPlist?["CFBundleVersion"]
let versionString = infoPlist?["CFBundleDevelopmentRegion"]
XCTAssert(displayName == content.displayName && identifier == content.identifier && versionString == content.versionString,
"File '\(name)' should contain the correct information.", file: (file), line: line)
} catch {
XCTFail("File '\(name)' should contain the correct information.", file: (file), line: line)
}
}
}
extension TextFile: AssertableFile {
func __assertExist(at location: URL, fileManager: FileManagerProtocol, file: StaticString, line: UInt) {
XCTAssert(fileManager.fileExists(atPath: location.path),
"File '\(name)' should exist at '\(location.path)'", file: (file), line: line)
XCTAssertEqual(fileManager.contents(atPath: location.path).map({ String(data: $0, encoding: .utf8)}), utf8Content,
"File '\(name)' should contain '\(utf8Content)'", file: (file), line: line)
}
}
extension JSONFile: AssertableFile {
func __assertExist(at location: URL, fileManager: FileManagerProtocol, file: StaticString, line: UInt) {
XCTAssert(fileManager.fileExists(atPath: location.path),
"File '\(name)' should exist at '\(location.path)'", file: (file), line: line)
guard let fileData = fileManager.contents(atPath: location.path),
let other = try? JSONDecoder().decode(Content.self, from: fileData) else {
XCTFail("File '\(name)' should contain '\(Content.self)' data at '\(location.path)'", file: (file), line: line)
return
}
let encoder = JSONEncoder()
guard let data = try? encoder.encode(content), let json = try? JSONSerialization.jsonObject(with: data),
let otherData = try? encoder.encode(other), let otherJSON = try? JSONSerialization.jsonObject(with: otherData)
else {
XCTFail("The decoded data in '\(name)' should be encodable as '\(Content.self)'", file: (file), line: line)
return
}
switch (json, otherJSON) {
case let (array as NSArray, otherArray as NSArray):
XCTAssertEqual(array, otherArray,
"File '\(name)' should contain JSON data that is equal to:\n\(array)", file: (file), line: line)
case let (dictionary as NSDictionary, otherDictionary as NSDictionary):
XCTAssertEqual(dictionary, otherDictionary,
"File '\(name)' should contain JSON data that is equal to:\n\(dictionary)", file: (file), line: line)
default:
XCTFail("The decoded data in '\(name)' should be encodable as '\(Content.self)'", file: (file), line: line)
}
}
}
extension CopyOfFile: AssertableFile {
func __assertExist(at location: URL, fileManager: FileManagerProtocol, file: StaticString, line: UInt) {
XCTAssert(fileManager.fileExists(atPath: location.path),
"File '\(name)' should exist at '\(location.path)'", file: (file), line: line)
XCTAssert(fileManager.contentsEqual(atPath: original.path, andPath: location.path),
"File '\(name)' should contain the same content as '\(original.path)'", file: (file), line: line)
}
}
|