From 65fa3d54f77ab526f9b7f4fa7269fb23d420907b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Ro=CC=88nnqvist?= Date: Wed, 17 Nov 2021 17:11:37 -0800 Subject: [PATCH 01/16] Add utility to create temp directories in unit tests --- .../Utility/DataStructures/File.swift | 4 +- .../Benchmark/OutputSizeTests.swift | 6 +- .../Indexing/NavigatorIndexTests.swift | 58 ++----- .../Infrastructure/BundleDiscoveryTests.swift | 29 +--- .../DocumentationContext+RootPageTests.swift | 4 +- .../DocumentationContextTests.swift | 160 +++--------------- .../DocumentationCuratorTests.swift | 5 +- .../ExternalReferenceResolverTests.swift | 3 +- .../InheritIntroducedAvailabilityTests.swift | 15 +- .../Infrastructure/NodeTagsTests.swift | 3 +- .../SymbolGraph/SymbolGraphLoaderTests.swift | 20 +-- .../Infrastructure/SymbolReferenceTests.swift | 5 +- .../LinkDestinationSummaryTests.swift | 19 --- .../Model/LineHighlighterTests.swift | 34 +--- .../Model/SemaToRenderNodeTests.swift | 2 +- .../Rendering/PlistSymbolTests.swift | 4 +- .../Semantics/SymbolTests.swift | 4 +- Tests/SwiftDocCTests/Utility/LMDBTests.swift | 20 +-- .../XCTestCase+LoadingTestData.swift | 77 +++++++++ .../XCTestCase+TemporaryDirectory.swift | 56 ++++++ .../ConvertSubcommandTests.swift | 14 +- .../ArgumentParsing/ErrorMessageTests.swift | 12 +- .../PreviewSubcommandTests.swift | 22 +-- .../ConvertActionIndexerTests.swift | 4 +- .../ConvertActionTests.swift | 17 +- .../DirectoryMonitorTests.swift | 24 +-- .../FolderStructureTests.swift | 19 --- .../IndexActionTests.swift | 10 +- .../OutOfProcessReferenceResolverTests.swift | 36 +--- .../PreviewActionIntegrationTests.swift | 35 +--- .../PreviewHTTPHandlerTests.swift | 6 +- .../PreviewServer/PreviewServerTests.swift | 19 ++- .../DefaultRequestHandlerTests.swift | 6 +- .../FileRequestHandlerTests.swift | 15 +- .../SemanticAnalyzerTests.swift | 6 - .../TempFolderTests.swift | 17 +- .../Utility/TestFileSystem.swift | 1 - .../Utility/TestFileSystemTests.swift | 8 +- 38 files changed, 288 insertions(+), 511 deletions(-) create mode 100644 Tests/SwiftDocCTests/XCTestCase+LoadingTestData.swift create mode 100644 Tests/SwiftDocCTests/XCTestCase+TemporaryDirectory.swift diff --git a/Sources/SwiftDocC/Utility/DataStructures/File.swift b/Sources/SwiftDocC/Utility/DataStructures/File.swift index a4a67dee08..5feb4c15ac 100644 --- a/Sources/SwiftDocC/Utility/DataStructures/File.swift +++ b/Sources/SwiftDocC/Utility/DataStructures/File.swift @@ -247,10 +247,10 @@ class TempFolder: File { } } - init(content: [File]) throws { + init(content: [File], atRoot root: URL) throws { self.content = content - url = URL(fileURLWithPath: NSTemporaryDirectory()).appendingPathComponent(UUID().uuidString) + url = root name = url.absoluteString try write(to: url) diff --git a/Tests/SwiftDocCTests/Benchmark/OutputSizeTests.swift b/Tests/SwiftDocCTests/Benchmark/OutputSizeTests.swift index c513b3c452..e6e7e60f49 100644 --- a/Tests/SwiftDocCTests/Benchmark/OutputSizeTests.swift +++ b/Tests/SwiftDocCTests/Benchmark/OutputSizeTests.swift @@ -14,11 +14,7 @@ import XCTest class OutputSizeTests: XCTestCase { func testOutputSize() throws { // Create a faux output folder - let tempURL = URL(fileURLWithPath: NSTemporaryDirectory()).appendingPathComponent(UUID().uuidString) - let writeURL = tempURL.appendingPathComponent(NodeURLGenerator.Path.dataFolderName) - - try FileManager.default.createDirectory(at: writeURL, withIntermediateDirectories: true, attributes: nil) - defer { try? FileManager.default.removeItem(at: tempURL) } + let writeURL = try createTemporaryDirectory(pathComponents: "data") // Write a 2MB file let data = Data(repeating: 1, count: 2 * 1024 * 1024) diff --git a/Tests/SwiftDocCTests/Indexing/NavigatorIndexTests.swift b/Tests/SwiftDocCTests/Indexing/NavigatorIndexTests.swift index fdfd8d6800..7495480ece 100644 --- a/Tests/SwiftDocCTests/Indexing/NavigatorIndexTests.swift +++ b/Tests/SwiftDocCTests/Indexing/NavigatorIndexTests.swift @@ -165,11 +165,7 @@ Root } func testNavigationTreeDumpAndRead() throws { - let targetURL = URL(fileURLWithPath: NSTemporaryDirectory()).appendingPathComponent(UUID().uuidString) - try FileManager.default.createDirectory(at: targetURL, withIntermediateDirectories: true, attributes: nil) - defer { - try? FileManager.default.removeItem(at: targetURL) - } + let targetURL = try createTemporaryDirectory() let indexURL = targetURL.appendingPathComponent("nav.index") let root = generateSmallTree() @@ -219,11 +215,7 @@ Root func testNavigationTreeLargeDumpAndRead() throws { #if os(OSX) - let targetURL = URL(fileURLWithPath: NSTemporaryDirectory()).appendingPathComponent(UUID().uuidString) - try FileManager.default.createDirectory(at: targetURL, withIntermediateDirectories: true, attributes: nil) - defer { - try? FileManager.default.removeItem(at: targetURL) - } + let targetURL = try createTemporaryDirectory() let indexURL = targetURL.appendingPathComponent("nav.index") let root = generateLargeTree() let original = NavigatorTree(root: root) @@ -239,11 +231,7 @@ Root // // rdar://85055022 tracks updating this test to remove any flakiness. func disabled_testNavigationTreeLargeDumpAndReadAsync() throws { - let targetURL = URL(fileURLWithPath: NSTemporaryDirectory()).appendingPathComponent(UUID().uuidString) - try FileManager.default.createDirectory(at: targetURL, withIntermediateDirectories: true, attributes: nil) - defer { - try? FileManager.default.removeItem(at: targetURL) - } + let targetURL = try createTemporaryDirectory() let indexURL = targetURL.appendingPathComponent("nav.index") let root = generateLargeTree() @@ -284,11 +272,7 @@ Root } func testNavigatorIndexGenerationEmpty() throws { - let targetURL = URL(fileURLWithPath: NSTemporaryDirectory()).appendingPathComponent(UUID().uuidString) - try FileManager.default.createDirectory(at: targetURL, withIntermediateDirectories: true, attributes: nil) - defer { - try? FileManager.default.removeItem(at: targetURL) - } + let targetURL = try createTemporaryDirectory() let builder = NavigatorIndex.Builder(outputURL: targetURL, bundleIdentifier: testBundleIdentifier) builder.setup() @@ -303,11 +287,7 @@ Root } func testNavigatorIndexGenerationOneNode() throws { - let targetURL = URL(fileURLWithPath: NSTemporaryDirectory()).appendingPathComponent(UUID().uuidString) - try FileManager.default.createDirectory(at: targetURL, withIntermediateDirectories: true, attributes: nil) - defer { - try? FileManager.default.removeItem(at: targetURL) - } + let targetURL = try createTemporaryDirectory() let indexURL = targetURL.appendingPathComponent("nav.index") let original = NavigatorTree(root: NavigatorTree.rootNode(bundleIdentifier: NavigatorIndex.UnknownBundleIdentifier)) @@ -337,11 +317,7 @@ Root let renderNode = try RenderNode.decode(fromJSON: Data(contentsOf: operatorURL)) - let targetURL = URL(fileURLWithPath: NSTemporaryDirectory()).appendingPathComponent(UUID().uuidString) - try FileManager.default.createDirectory(at: targetURL, withIntermediateDirectories: true, attributes: nil) - defer { - try? FileManager.default.removeItem(at: targetURL) - } + let targetURL = try createTemporaryDirectory() let builder = NavigatorIndex.Builder(outputURL: targetURL, bundleIdentifier: testBundleIdentifier) builder.setup() @@ -359,7 +335,7 @@ Root // Create an index 10 times to ensure we have not undeterministic behavior across builds for _ in 0..<10 { - let targetURL = URL(fileURLWithPath: NSTemporaryDirectory()).appendingPathComponent(UUID().uuidString) + let targetURL = try createTemporaryDirectory() let builder = NavigatorIndex.Builder(outputURL: targetURL, bundleIdentifier: testBundleIdentifier, sortRootChildrenByName: true) builder.setup() @@ -405,7 +381,7 @@ Root let jsonFile = Bundle.module.url(forResource: "Variant-render-node", withExtension: "json", subdirectory: "Test Resources")! let jsonData = try Data(contentsOf: jsonFile) - let targetURL = URL(fileURLWithPath: NSTemporaryDirectory()).appendingPathComponent(UUID().uuidString) + let targetURL = try createTemporaryDirectory() let builder = NavigatorIndex.Builder(outputURL: targetURL, bundleIdentifier: testBundleIdentifier, sortRootChildrenByName: true, groupByLanguage: true) builder.setup() @@ -441,7 +417,7 @@ Root // Create an index 10 times to ensure we have not undeterministic behavior across builds for _ in 0..<10 { - let targetURL = URL(fileURLWithPath: NSTemporaryDirectory()).appendingPathComponent(UUID().uuidString) + let targetURL = try createTemporaryDirectory() let builder = NavigatorIndex.Builder(outputURL: targetURL, bundleIdentifier: testBundleIdentifier, sortRootChildrenByName: true, usePageTitle: true) builder.setup() @@ -490,7 +466,7 @@ Root // Create an index 10 times to ensure we have not undeterministic behavior across builds for _ in 0..<10 { - let targetURL = URL(fileURLWithPath: NSTemporaryDirectory()).appendingPathComponent(UUID().uuidString) + let targetURL = try createTemporaryDirectory() let builder = NavigatorIndex.Builder(outputURL: targetURL, bundleIdentifier: testBundleIdentifier, sortRootChildrenByName: true, writePathsOnDisk: false) builder.setup() @@ -532,7 +508,6 @@ Root assertUniqueIDs(node: navigatorIndex.navigatorTree.root) results.insert(navigatorIndex.navigatorTree.root.dumpTree()) - try FileManager.default.removeItem(at: targetURL) } XCTAssertEqual(results.count, 1) @@ -544,7 +519,7 @@ Root let renderContext = RenderContext(documentationContext: context, bundle: bundle) let converter = DocumentationContextConverter(bundle: bundle, context: context, renderContext: renderContext) - let targetURL = URL(fileURLWithPath: NSTemporaryDirectory()).appendingPathComponent(UUID().uuidString) + let targetURL = try createTemporaryDirectory() let builder = NavigatorIndex.Builder(outputURL: targetURL, bundleIdentifier: testBundleIdentifier, sortRootChildrenByName: true, groupByLanguage: true) builder.setup() @@ -594,7 +569,7 @@ Root // Create an index 10 times to ensure we have no undeterministic behavior across builds for _ in 0..<10 { - let targetURL = URL(fileURLWithPath: NSTemporaryDirectory()).appendingPathComponent(UUID().uuidString) + let targetURL = try createTemporaryDirectory() let builder = NavigatorIndex.Builder(outputURL: targetURL, bundleIdentifier: testBundleIdentifier, sortRootChildrenByName: true) builder.setup() @@ -654,7 +629,7 @@ Root let renderContext = RenderContext(documentationContext: context, bundle: bundle) let converter = DocumentationContextConverter(bundle: bundle, context: context, renderContext: renderContext) - let targetURL = URL(fileURLWithPath: NSTemporaryDirectory()).appendingPathComponent(UUID().uuidString) + let targetURL = try createTemporaryDirectory() let builder = NavigatorIndex.Builder(outputURL: targetURL, bundleIdentifier: testBundleIdentifier, sortRootChildrenByName: true) builder.setup() @@ -751,7 +726,7 @@ Root let renderContext = RenderContext(documentationContext: context, bundle: bundle) let converter = DocumentationContextConverter(bundle: bundle, context: context, renderContext: renderContext) - let targetURL = URL(fileURLWithPath: NSTemporaryDirectory()).appendingPathComponent(UUID().uuidString) + let targetURL = try createTemporaryDirectory() let builder = NavigatorIndex.Builder(outputURL: targetURL, bundleIdentifier: testBundleIdentifier, sortRootChildrenByName: true) builder.setup() @@ -1007,8 +982,7 @@ Root XCTAssertEqual(availabilityIndex.versions(for: .iOS)?.count, 4) XCTAssertEqual(availabilityIndex.versions(for: .macOS)?.count, 1) - let targetFolder = URL(fileURLWithPath: NSTemporaryDirectory()).appendingPathComponent(UUID().uuidString) - try FileManager.default.createDirectory(at: targetFolder, withIntermediateDirectories: true) + let targetFolder = try createTemporaryDirectory() let targetURL = targetFolder.appendingPathComponent("availability.index") let jsonEncoder = JSONEncoder() let data = try jsonEncoder.encode(availabilityIndex) @@ -1161,7 +1135,7 @@ Root let (bundle, context) = try testBundleAndContext(named: "TestBundle") let converter = DocumentationNodeConverter(bundle: bundle, context: context) - let targetURL = URL(fileURLWithPath: NSTemporaryDirectory()).appendingPathComponent(UUID().uuidString) + let targetURL = try createTemporaryDirectory() let builder = NavigatorIndex.Builder(outputURL: targetURL, bundleIdentifier: "org.swift.docc.test", sortRootChildrenByName: true) builder.setup() diff --git a/Tests/SwiftDocCTests/Infrastructure/BundleDiscoveryTests.swift b/Tests/SwiftDocCTests/Infrastructure/BundleDiscoveryTests.swift index 09cb0e8ced..7187c2b204 100644 --- a/Tests/SwiftDocCTests/Infrastructure/BundleDiscoveryTests.swift +++ b/Tests/SwiftDocCTests/Infrastructure/BundleDiscoveryTests.swift @@ -20,8 +20,7 @@ class BundleDiscoveryTests: XCTestCase { .filter { !$0.pathComponents.dropFirst(testBundleLocation.pathComponents.count).contains(where: { $0.hasPrefix(".") }) } func testFirstBundle() throws { - let url = URL(fileURLWithPath: NSTemporaryDirectory().appending(UUID().uuidString)) - try FileManager.default.createDirectory(at: url, withIntermediateDirectories: true, attributes: nil) + let url = try createTemporaryDirectory() // Create 3 minimal doc bundles for i in 1 ... 3 { let nestedBundle = Folder(name: "TestBundle\(i).docc", content: [ @@ -38,8 +37,6 @@ class BundleDiscoveryTests: XCTestCase { ]) _ = try nestedBundle.write(inside: url) } - - defer { try? FileManager.default.removeItem(at: url) } let workspace = DocumentationWorkspace() let context = try DocumentationContext(dataProvider: workspace) @@ -74,9 +71,7 @@ class BundleDiscoveryTests: XCTestCase { ]), ]) - let tempURL = Foundation.URL(fileURLWithPath: NSTemporaryDirectory()).appendingPathComponent(ProcessInfo.processInfo.globallyUniqueString) - try FileManager.default.createDirectory(at: tempURL, withIntermediateDirectories: true, attributes: nil) - defer { try? FileManager.default.removeItem(at: tempURL) } + let tempURL = try createTemporaryDirectory() let workspaceURL = try workspace.write(inside: tempURL) @@ -111,9 +106,7 @@ class BundleDiscoveryTests: XCTestCase { func testBundleFormat() throws { func parsedBundle(from folder: File) throws -> DocumentationBundle? { - let tempURL = Foundation.URL(fileURLWithPath: NSTemporaryDirectory()).appendingPathComponent(ProcessInfo.processInfo.globallyUniqueString) - try FileManager.default.createDirectory(at: tempURL, withIntermediateDirectories: true, attributes: nil) - defer { try? FileManager.default.removeItem(at: tempURL) } + let tempURL = try createTemporaryDirectory() let workspaceURL = try folder.write(inside: tempURL) let dataProvider = try LocalFileSystemDataProvider(rootURL: workspaceURL) @@ -209,9 +202,7 @@ class BundleDiscoveryTests: XCTestCase { CopyOfFolder(original: testBundleLocation, newName: "Not a doc bundle", filter: { DocumentationBundleFileTypes.isSymbolGraphFile($0) }), ]) - let tempURL = Foundation.URL(fileURLWithPath: NSTemporaryDirectory()).appendingPathComponent(ProcessInfo.processInfo.globallyUniqueString) - try FileManager.default.createDirectory(at: tempURL, withIntermediateDirectories: true, attributes: nil) - defer { try? FileManager.default.removeItem(at: tempURL) } + let tempURL = try createTemporaryDirectory() let workspaceURL = try workspace.write(inside: tempURL) let dataProvider = try LocalFileSystemDataProvider(rootURL: workspaceURL) @@ -255,9 +246,7 @@ class BundleDiscoveryTests: XCTestCase { XCTAssertFalse(workspace.recursiveContent.contains(where: { $0.name == "Info.plist" }), "This bundle shouldn't contain an Info.plist file") - let tempURL = Foundation.URL(fileURLWithPath: NSTemporaryDirectory()).appendingPathComponent(ProcessInfo.processInfo.globallyUniqueString) - try FileManager.default.createDirectory(at: tempURL, withIntermediateDirectories: true, attributes: nil) - defer { try? FileManager.default.removeItem(at: tempURL) } + let tempURL = try createTemporaryDirectory() let workspaceURL = try workspace.write(inside: tempURL) let dataProvider = try LocalFileSystemDataProvider(rootURL: workspaceURL) @@ -287,9 +276,7 @@ class BundleDiscoveryTests: XCTestCase { CopyOfFolder(original: testBundleLocation), ]) - let tempURL = Foundation.URL(fileURLWithPath: NSTemporaryDirectory()).appendingPathComponent(ProcessInfo.processInfo.globallyUniqueString) - try FileManager.default.createDirectory(at: tempURL, withIntermediateDirectories: true, attributes: nil) - defer { try? FileManager.default.removeItem(at: tempURL) } + let tempURL = try createTemporaryDirectory() let workspaceURL = try workspace.write(inside: tempURL) let dataProvider = try LocalFileSystemDataProvider(rootURL: workspaceURL) @@ -319,9 +306,7 @@ class BundleDiscoveryTests: XCTestCase { ] ) - let tempURL = Foundation.URL(fileURLWithPath: NSTemporaryDirectory()).appendingPathComponent(ProcessInfo.processInfo.globallyUniqueString) - try FileManager.default.createDirectory(at: tempURL, withIntermediateDirectories: true, attributes: nil) - defer { try? FileManager.default.removeItem(at: tempURL) } + let tempURL = try createTemporaryDirectory() let workspaceURL = try workspace.write(inside: tempURL) let dataProvider = try LocalFileSystemDataProvider(rootURL: workspaceURL) diff --git a/Tests/SwiftDocCTests/Infrastructure/DocumentationContext+RootPageTests.swift b/Tests/SwiftDocCTests/Infrastructure/DocumentationContext+RootPageTests.swift index 47b739658c..c446301b0c 100644 --- a/Tests/SwiftDocCTests/Infrastructure/DocumentationContext+RootPageTests.swift +++ b/Tests/SwiftDocCTests/Infrastructure/DocumentationContext+RootPageTests.swift @@ -36,7 +36,7 @@ class DocumentationContext_RootPageTests: XCTestCase { """), InfoPlist(displayName: "TestBundle", identifier: "com.test.example"), ]), - ]) + ], atRoot: createTemporaryDirectory(createDirectoryForLastPathComponent: false)) // Parse this test content let workspace = DocumentationWorkspace() @@ -78,7 +78,7 @@ class DocumentationContext_RootPageTests: XCTestCase { """), InfoPlist(displayName: "TestBundle", identifier: "com.test.example"), ]), - ]) + ], atRoot: createTemporaryDirectory(createDirectoryForLastPathComponent: false)) // Parse this test content let workspace = DocumentationWorkspace() diff --git a/Tests/SwiftDocCTests/Infrastructure/DocumentationContextTests.swift b/Tests/SwiftDocCTests/Infrastructure/DocumentationContextTests.swift index 45af8d983a..82615c0b1e 100644 --- a/Tests/SwiftDocCTests/Infrastructure/DocumentationContextTests.swift +++ b/Tests/SwiftDocCTests/Infrastructure/DocumentationContextTests.swift @@ -34,67 +34,6 @@ extension CollectionDifference { } } -/// Loads a documentation bundle from the given source URL and creates a documentation context. -func loadBundle(from bundleURL: URL, codeListings: [String : AttributedCodeListing] = [:], externalResolvers: [String: ExternalReferenceResolver] = [:], externalSymbolResolver: ExternalSymbolResolver? = nil, diagnosticFilterLevel: DiagnosticSeverity = .hint, configureContext: ((DocumentationContext) throws -> Void)? = nil) throws -> (URL, DocumentationBundle, DocumentationContext) { - let workspace = DocumentationWorkspace() - let context = try DocumentationContext(dataProvider: workspace, diagnosticEngine: DiagnosticEngine(filterLevel: diagnosticFilterLevel)) - context.externalReferenceResolvers = externalResolvers - context.externalSymbolResolver = externalSymbolResolver - context.externalMetadata.diagnosticLevel = diagnosticFilterLevel - try configureContext?(context) - // Load the bundle using automatic discovery - let automaticDataProvider = try LocalFileSystemDataProvider(rootURL: bundleURL) - // Mutate the bundle to include the code listings, then apply to the workspace using a manual provider. - var bundle = try automaticDataProvider.bundles().first! - bundle.attributedCodeListings = codeListings - let dataProvider = PrebuiltLocalFileSystemDataProvider(bundles: [bundle]) - try workspace.registerProvider(dataProvider) - return (bundleURL, bundle, context) -} - -func testBundleAndContext(copying name: String, excludingPaths excludedPaths: [String] = [], codeListings: [String : AttributedCodeListing] = [:], externalResolvers: [BundleIdentifier : ExternalReferenceResolver] = [:], externalSymbolResolver: ExternalSymbolResolver? = nil, configureBundle: ((URL) throws -> Void)? = nil) throws -> (URL, DocumentationBundle, DocumentationContext) { - let sourceURL = Bundle.module.url( - forResource: name, withExtension: "docc", subdirectory: "Test Bundles")! - let bundleURL = URL(fileURLWithPath: NSTemporaryDirectory().appending(UUID().uuidString.appending(".docc"))) - - if FileManager.default.fileExists(atPath: sourceURL.path) { - try FileManager.default.copyItem(at: sourceURL, to: bundleURL) - } else { - try FileManager.default.createDirectory(at: bundleURL, withIntermediateDirectories: true, attributes: nil) - } - - for path in excludedPaths { - try FileManager.default.removeItem(at: bundleURL.appendingPathComponent(path)) - } - - // Do any additional setup to the custom bundle - adding, modifying files, etc - try configureBundle?(bundleURL) - - return try loadBundle(from: bundleURL, codeListings: codeListings, externalResolvers: externalResolvers, externalSymbolResolver: externalSymbolResolver) -} - - -func testBundleAndContext(named name: String, codeListings: [String : AttributedCodeListing] = [:], externalResolvers: [String: ExternalReferenceResolver] = [:]) throws -> (DocumentationBundle, DocumentationContext) { - let bundleURL = Bundle.module.url( - forResource: name, withExtension: "docc", subdirectory: "Test Bundles")! - let (_, bundle, context) = try loadBundle(from: bundleURL, codeListings: codeListings, externalResolvers: externalResolvers) - return (bundle, context) -} - -func testBundle(named name: String) -> DocumentationBundle { - let (bundle, _) = try! testBundleAndContext(named: name) - return bundle -} - -func testBundleFromRootURL(named name: String) throws -> DocumentationBundle { - let bundleURL = Bundle.module.url( - forResource: name, withExtension: "docc", subdirectory: "Test Bundles")! - let dataProvider = try LocalFileSystemDataProvider(rootURL: bundleURL) - - let bundles = try dataProvider.bundles() - return bundles[0] -} - class DocumentationContextTests: XCTestCase { func testResolve() throws { let workspace = DocumentationWorkspace() @@ -517,9 +456,7 @@ class DocumentationContextTests: XCTestCase { ]), InfoPlist(displayName: "TestBundle", identifier: "com.test.example"), ]) - let tempURL = Foundation.URL(fileURLWithPath: NSTemporaryDirectory()).appendingPathComponent(ProcessInfo.processInfo.globallyUniqueString) - try FileManager.default.createDirectory(at: tempURL, withIntermediateDirectories: true, attributes: nil) - defer { try? FileManager.default.removeItem(at: tempURL) } + let tempURL = try createTemporaryDirectory() let bundleURL = try exampleDocumentation.write(inside: tempURL) @@ -632,9 +569,7 @@ class DocumentationContextTests: XCTestCase { ]) ]) - let tempURL = Foundation.URL(fileURLWithPath: NSTemporaryDirectory()).appendingPathComponent(ProcessInfo.processInfo.globallyUniqueString) - try FileManager.default.createDirectory(at: tempURL, withIntermediateDirectories: true, attributes: nil) - defer { try? FileManager.default.removeItem(at: tempURL) } + let tempURL = try createTemporaryDirectory() let workspaceURL = try workspaceContent.write(inside: tempURL) let dataProvider = try LocalFileSystemDataProvider(rootURL: workspaceURL) @@ -700,10 +635,7 @@ class DocumentationContextTests: XCTestCase { ]) ]) - let tempURL = Foundation.URL(fileURLWithPath: NSTemporaryDirectory()).appendingPathComponent(ProcessInfo.processInfo.globallyUniqueString) - try FileManager.default.createDirectory(at: tempURL, withIntermediateDirectories: true, attributes: nil) - defer { try? FileManager.default.removeItem(at: tempURL) } - + let tempURL = try createTemporaryDirectory() let bundleURL = try testBundle.write(inside: tempURL) let workspace = DocumentationWorkspace() @@ -731,10 +663,7 @@ class DocumentationContextTests: XCTestCase { ]) ]) - let tempURL = Foundation.URL(fileURLWithPath: NSTemporaryDirectory()).appendingPathComponent(ProcessInfo.processInfo.globallyUniqueString) - try FileManager.default.createDirectory(at: tempURL, withIntermediateDirectories: true, attributes: nil) - defer { try? FileManager.default.removeItem(at: tempURL) } - + let tempURL = try createTemporaryDirectory() let bundleURL = try testBundle.write(inside: tempURL) let workspace = DocumentationWorkspace() @@ -972,10 +901,7 @@ class DocumentationContextTests: XCTestCase { ]), ]) - let tempURL = Foundation.URL(fileURLWithPath: NSTemporaryDirectory()).appendingPathComponent(ProcessInfo.processInfo.globallyUniqueString) - try FileManager.default.createDirectory(at: tempURL, withIntermediateDirectories: true, attributes: nil) - defer { try? FileManager.default.removeItem(at: tempURL) } - + let tempURL = try createTemporaryDirectory() let bundleURL = try testBundle.write(inside: tempURL) let workspace = DocumentationWorkspace() @@ -1038,10 +964,7 @@ class DocumentationContextTests: XCTestCase { ]) ]) - let tempURL = Foundation.URL(fileURLWithPath: NSTemporaryDirectory()).appendingPathComponent(ProcessInfo.processInfo.globallyUniqueString) - try FileManager.default.createDirectory(at: tempURL, withIntermediateDirectories: true, attributes: nil) - defer { try? FileManager.default.removeItem(at: tempURL) } - + let tempURL = try createTemporaryDirectory() let bundleURL = try testBundle.write(inside: tempURL) let workspace = DocumentationWorkspace() @@ -1075,10 +998,7 @@ class DocumentationContextTests: XCTestCase { ]) ]) - let tempURL = Foundation.URL(fileURLWithPath: NSTemporaryDirectory()).appendingPathComponent(ProcessInfo.processInfo.globallyUniqueString) - try FileManager.default.createDirectory(at: tempURL, withIntermediateDirectories: true, attributes: nil) - defer { try? FileManager.default.removeItem(at: tempURL) } - + let tempURL = try createTemporaryDirectory() let bundleURL = try testBundle.write(inside: tempURL) let workspace = DocumentationWorkspace() @@ -1115,10 +1035,7 @@ class DocumentationContextTests: XCTestCase { ]) ]) - let tempURL = Foundation.URL(fileURLWithPath: NSTemporaryDirectory()).appendingPathComponent(ProcessInfo.processInfo.globallyUniqueString) - try FileManager.default.createDirectory(at: tempURL, withIntermediateDirectories: true, attributes: nil) - defer { try? FileManager.default.removeItem(at: tempURL) } - + let tempURL = try createTemporaryDirectory() let bundleURL = try testBundle.write(inside: tempURL) let workspace = DocumentationWorkspace() @@ -1159,10 +1076,7 @@ class DocumentationContextTests: XCTestCase { ]) ]) - let tempURL = Foundation.URL(fileURLWithPath: NSTemporaryDirectory()).appendingPathComponent(ProcessInfo.processInfo.globallyUniqueString) - try FileManager.default.createDirectory(at: tempURL, withIntermediateDirectories: true, attributes: nil) - defer { try? FileManager.default.removeItem(at: tempURL) } - + let tempURL = try createTemporaryDirectory() let bundleURL = try testBundle.write(inside: tempURL) let workspace = DocumentationWorkspace() @@ -1910,11 +1824,7 @@ let expected = """ ("file:///path with spaces/to/file.swift", "file:///path%20with%20spaces/to/file.swift"), ] { // Create an empty bundle - let targetURL = Foundation.URL(fileURLWithPath: NSTemporaryDirectory()).appendingPathComponent(UUID().uuidString.appending(".docc")) - try FileManager.default.createDirectory(at: targetURL, withIntermediateDirectories: true, attributes: nil) - defer { - try? FileManager.default.removeItem(at: targetURL) - } + let targetURL = try createTemporaryDirectory(pathComponents: "test.docc") // Copy test Info.plist try FileManager.default.copyItem(at: Bundle.module.url( @@ -2070,9 +1980,7 @@ let expected = """ func testCrossSymbolGraphPathCollisions() throws { // Create temp folder - let tempURL = URL(fileURLWithPath: NSTemporaryDirectory().appending(UUID().uuidString)) - try FileManager.default.createDirectory(atPath: tempURL.path, withIntermediateDirectories: false, attributes: nil) - defer { try? FileManager.default.removeItem(at: tempURL) } + let tempURL = try createTemporaryDirectory() // Create test bundle let bundleURL = try Folder(name: "collisions.docc", content: [ @@ -2162,9 +2070,7 @@ let expected = """ /// rdar://69242313 func testLinkResolutionDoesNotSkipSymbolGraph() throws { - let tempURL = URL(fileURLWithPath: NSTemporaryDirectory().appending(UUID().uuidString)) - try FileManager.default.createDirectory(atPath: tempURL.path, withIntermediateDirectories: false, attributes: nil) - defer { try? FileManager.default.removeItem(at: tempURL) } + let tempURL = try createTemporaryDirectory() let bundleURL = try Folder(name: "Missing.docc", content: [ InfoPlist(displayName: "MissingDocs", identifier: "com.test.missing-docs"), @@ -2278,9 +2184,7 @@ let expected = """ } func testLinkResolutionDiagnosticsEmittedForTechnologyPages() throws { - let tempURL = URL(fileURLWithPath: NSTemporaryDirectory().appending(UUID().uuidString)) - try FileManager.default.createDirectory(atPath: tempURL.path, withIntermediateDirectories: false, attributes: nil) - defer { try? FileManager.default.removeItem(at: tempURL) } + let tempURL = try createTemporaryDirectory() let bundleURL = try Folder(name: "module-links.docc", content: [ InfoPlist(displayName: "Test", identifier: "com.test.docc"), @@ -2343,10 +2247,7 @@ let expected = """ """), InfoPlist(displayName: "MyKit", identifier: "com.test.MyKit"), ]) - let tempURL = Foundation.URL(fileURLWithPath: NSTemporaryDirectory()).appendingPathComponent(ProcessInfo.processInfo.globallyUniqueString) - try FileManager.default.createDirectory(at: tempURL, withIntermediateDirectories: true, attributes: nil) - defer { try? FileManager.default.removeItem(at: tempURL) } - + let tempURL = try createTemporaryDirectory() let bundleURL = try exampleDocumentation.write(inside: tempURL) // Parse this test content @@ -2438,9 +2339,7 @@ let expected = """ """) do { - let tempURL = URL(fileURLWithPath: NSTemporaryDirectory().appending(UUID().uuidString)) - try FileManager.default.createDirectory(atPath: tempURL.path, withIntermediateDirectories: false, attributes: nil) - defer { try? FileManager.default.removeItem(at: tempURL) } + let tempURL = try createTemporaryDirectory() let bundleURL = try Folder(name: "Module.docc", content: [ InfoPlist(displayName: "Module", identifier: "org.swift.docc.example"), @@ -2476,9 +2375,7 @@ let expected = """ } do { - let tempURL = URL(fileURLWithPath: NSTemporaryDirectory().appending(UUID().uuidString)) - try FileManager.default.createDirectory(atPath: tempURL.path, withIntermediateDirectories: false, attributes: nil) - defer { try? FileManager.default.removeItem(at: tempURL) } + let tempURL = try createTemporaryDirectory() let bundleURL = try Folder(name: "Module.docc", content: [ InfoPlist(displayName: "Module", identifier: "org.swift.docc.example"), @@ -2509,9 +2406,7 @@ let expected = """ } func testAutomaticTaskGroupsPlacedAfterManualCuration() throws { - let tempURL = URL(fileURLWithPath: NSTemporaryDirectory().appending(UUID().uuidString)) - try FileManager.default.createDirectory(atPath: tempURL.path, withIntermediateDirectories: false, attributes: nil) - defer { try? FileManager.default.removeItem(at: tempURL) } + let tempURL = try createTemporaryDirectory() let bundleURL = try Folder(name: "Module.docc", content: [ InfoPlist(displayName: "Module", identifier: "org.swift.docc.example"), @@ -2722,9 +2617,8 @@ let expected = """ TextFile(name: "TestTechnology.tutorial", utf8Content: testTechnologySource), TextFile(name: "Test.tutorial", utf8Content: testTutorialSource), ]) - let tempFolderURL = URL(fileURLWithPath: NSTemporaryDirectory().appending(UUID().uuidString.appending(".docc"))) + let tempFolderURL = try createTemporaryDirectory(pathComponents: "test.docc", createDirectoryForLastPathComponent: false) try testBundle.write(to: tempFolderURL) - defer { try? FileManager.default.removeItem(at: tempFolderURL) } // Load the bundle let (_, bundle, context) = try loadBundle(from: tempFolderURL) @@ -2760,9 +2654,8 @@ let expected = """ TextFile(name: "TestTechnology.tutorial", utf8Content: testTechnologySource), TextFile(name: "Test.tutorial", utf8Content: testTutorialSource), ]) - let tempFolderURL = URL(fileURLWithPath: NSTemporaryDirectory().appending(UUID().uuidString.appending(".docc"))) + let tempFolderURL = try createTemporaryDirectory(pathComponents: "test.docc", createDirectoryForLastPathComponent: false) try testBundle.write(to: tempFolderURL) - defer { try? FileManager.default.removeItem(at: tempFolderURL) } // Load the bundle let (_, bundle, context) = try loadBundle(from: tempFolderURL) @@ -2821,9 +2714,8 @@ let expected = """ TextFile(name: "TestTechnology.tutorial", utf8Content: testTechnologySource), TextFile(name: "Test.tutorial", utf8Content: testTutorialSource), ]) - let tempFolderURL = URL(fileURLWithPath: NSTemporaryDirectory().appending(UUID().uuidString.appending(".docc"))) + let tempFolderURL = try createTemporaryDirectory(pathComponents: "test.docc", createDirectoryForLastPathComponent: false) try testBundle.write(to: tempFolderURL) - defer { try? FileManager.default.removeItem(at: tempFolderURL) } // Load the bundle let (_, bundle, context) = try loadBundle(from: tempFolderURL) @@ -2892,9 +2784,8 @@ let expected = """ CopyOfFile(original: infoPlistURL, newName: "Info.plist"), TextFile(name: "TestFramework.symbols.json", utf8Content: symbolGraphFixture), ]) - let tempFolderURL = URL(fileURLWithPath: NSTemporaryDirectory().appending(UUID().uuidString.appending(".docc"))) + let tempFolderURL = try createTemporaryDirectory(pathComponents: "test.docc", createDirectoryForLastPathComponent: false) try testBundle.write(to: tempFolderURL) - defer { try? FileManager.default.removeItem(at: tempFolderURL) } // Load the bundle let (_, bundle, context) = try loadBundle(from: tempFolderURL) @@ -2931,9 +2822,7 @@ let expected = """ /// ``` func testWarningForUnresolvableLinksInInheritedDocs() throws { // Create temp folder - let tempURL = URL(fileURLWithPath: NSTemporaryDirectory().appending(UUID().uuidString)) - try FileManager.default.createDirectory(atPath: tempURL.path, withIntermediateDirectories: false, attributes: nil) - defer { try? FileManager.default.removeItem(at: tempURL) } + let tempURL = try createTemporaryDirectory() // Create test bundle let bundleURL = try Folder(name: "InheritedDocs.docc", content: [ @@ -3015,10 +2904,7 @@ let expected = """ InfoPlist(displayName: "TestBundle", identifier: "com.test.example") ]) - let tempURL = Foundation.URL(fileURLWithPath: NSTemporaryDirectory()).appendingPathComponent(ProcessInfo.processInfo.globallyUniqueString) - try FileManager.default.createDirectory(at: tempURL, withIntermediateDirectories: true, attributes: nil) - defer { try? FileManager.default.removeItem(at: tempURL) } - + let tempURL = try createTemporaryDirectory() let bundleURL = try exampleDocumentation.write(inside: tempURL) let workspace = DocumentationWorkspace() diff --git a/Tests/SwiftDocCTests/Infrastructure/DocumentationCuratorTests.swift b/Tests/SwiftDocCTests/Infrastructure/DocumentationCuratorTests.swift index c52d861eaf..38bfe1a3f4 100644 --- a/Tests/SwiftDocCTests/Infrastructure/DocumentationCuratorTests.swift +++ b/Tests/SwiftDocCTests/Infrastructure/DocumentationCuratorTests.swift @@ -81,14 +81,11 @@ class DocumentationCuratorTests: XCTestCase { let workspace = DocumentationWorkspace() let context = try DocumentationContext(dataProvider: workspace) - let tempURL = URL(fileURLWithPath: NSTemporaryDirectory()).appendingPathComponent(ProcessInfo.processInfo.globallyUniqueString).appendingPathComponent("unit-test.docc") + let tempURL = try createTemporaryDirectory(pathComponents: "unit-test.docc", createDirectoryForLastPathComponent: false) let testBundleURL = Bundle.module.url( forResource: "TestBundle", withExtension: "docc", subdirectory: "Test Bundles")! XCTAssert(FileManager.default.fileExists(atPath: testBundleURL.path)) - - try FileManager.default.createDirectory(at: tempURL.deletingLastPathComponent(), withIntermediateDirectories: true, attributes: nil) - defer { try? FileManager.default.removeItem(at: tempURL.deletingLastPathComponent()) } try FileManager.default.copyItem(at: testBundleURL, to: tempURL) let sidecarFile = tempURL.appendingPathComponent("documentation/myfunction.md") diff --git a/Tests/SwiftDocCTests/Infrastructure/ExternalReferenceResolverTests.swift b/Tests/SwiftDocCTests/Infrastructure/ExternalReferenceResolverTests.swift index abb47c3308..40f44e5c15 100644 --- a/Tests/SwiftDocCTests/Infrastructure/ExternalReferenceResolverTests.swift +++ b/Tests/SwiftDocCTests/Infrastructure/ExternalReferenceResolverTests.swift @@ -101,9 +101,8 @@ class ExternalReferenceResolverTests: XCTestCase { forResource: "TestBundle", withExtension: "docc", subdirectory: "Test Bundles")! // Create a copy of the test bundle - let bundleURL = URL(fileURLWithPath: NSTemporaryDirectory()).appendingPathComponent(ProcessInfo.processInfo.globallyUniqueString.appending(".docc")) + let bundleURL = try createTemporaryDirectory(pathComponents: "test.docc", createDirectoryForLastPathComponent: false) try FileManager.default.copyItem(at: sourceURL, to: bundleURL) - defer { try? FileManager.default.removeItem(at: bundleURL) } // Add external link let myClassMDURL = bundleURL.appendingPathComponent("documentation").appendingPathComponent("myclass.md") diff --git a/Tests/SwiftDocCTests/Infrastructure/InheritIntroducedAvailabilityTests.swift b/Tests/SwiftDocCTests/Infrastructure/InheritIntroducedAvailabilityTests.swift index c00d76215f..50d24b91fe 100644 --- a/Tests/SwiftDocCTests/Infrastructure/InheritIntroducedAvailabilityTests.swift +++ b/Tests/SwiftDocCTests/Infrastructure/InheritIntroducedAvailabilityTests.swift @@ -33,7 +33,20 @@ fileprivate extension SymbolGraph.Symbol { class InheritIntroducedAvailabilityTests: XCTestCase { typealias Domain = SymbolGraph.Symbol.Availability.Domain typealias Version = SymbolGraph.SemanticVersion - let (testBundle, context) = try! testBundleAndContext(named: "TestBundle") + + var testBundle: DocumentationBundle! + var context: DocumentationContext! + + override func setUpWithError() throws { + try super.setUpWithError() + (testBundle, context) = try testBundleAndContext(named: "TestBundle") + } + + override func tearDown() { + testBundle = nil + context = nil + super.tearDown() + } /// Tests that the `introduced` availability version comes from /// the macOS version in the Info.plist diff --git a/Tests/SwiftDocCTests/Infrastructure/NodeTagsTests.swift b/Tests/SwiftDocCTests/Infrastructure/NodeTagsTests.swift index 617a8bb47d..a359495e0d 100644 --- a/Tests/SwiftDocCTests/Infrastructure/NodeTagsTests.swift +++ b/Tests/SwiftDocCTests/Infrastructure/NodeTagsTests.swift @@ -20,9 +20,8 @@ class NodeTagsTests: XCTestCase { InfoPlist(displayName: "spi", identifier: "com.tests.spi"), CopyOfFile(original: spiSGURL), ]) - let tempURL = URL(fileURLWithPath: NSTemporaryDirectory()).appendingPathComponent(UUID().uuidString.appending("unit-tests.docc")) + let tempURL = try createTemporaryDirectory(pathComponents: "unit-tests.docc", createDirectoryForLastPathComponent: false) try bundleFolder.write(to: tempURL) - defer { try? FileManager.default.removeItem(at: tempURL) } let (_, bundle, context) = try loadBundle(from: tempURL) diff --git a/Tests/SwiftDocCTests/Infrastructure/SymbolGraph/SymbolGraphLoaderTests.swift b/Tests/SwiftDocCTests/Infrastructure/SymbolGraph/SymbolGraphLoaderTests.swift index d9b1faf16f..355368ab50 100644 --- a/Tests/SwiftDocCTests/Infrastructure/SymbolGraph/SymbolGraphLoaderTests.swift +++ b/Tests/SwiftDocCTests/Infrastructure/SymbolGraph/SymbolGraphLoaderTests.swift @@ -16,10 +16,7 @@ import XCTest class SymbolGraphLoaderTests: XCTestCase { func testLoadingDifferentModules() throws { - let tempURL = URL(fileURLWithPath: NSTemporaryDirectory()).appendingPathComponent(ProcessInfo.processInfo.globallyUniqueString) - - try FileManager.default.createDirectory(at: tempURL, withIntermediateDirectories: true, attributes: nil) - defer { try? FileManager.default.removeItem(at: tempURL) } + let tempURL = try createTemporaryDirectory() var symbolGraphURLs = [URL]() for moduleNames in ["One", "Two", "Three"] { @@ -59,10 +56,7 @@ class SymbolGraphLoaderTests: XCTestCase { } func testLoadingDifferentModuleExtensions() throws { - let tempURL = URL(fileURLWithPath: NSTemporaryDirectory()).appendingPathComponent(ProcessInfo.processInfo.globallyUniqueString) - - try FileManager.default.createDirectory(at: tempURL, withIntermediateDirectories: true, attributes: nil) - defer { try? FileManager.default.removeItem(at: tempURL) } + let tempURL = try createTemporaryDirectory() var symbolGraphURLs = [URL]() for moduleName in ["One", "Two", "Three"] { @@ -89,10 +83,7 @@ class SymbolGraphLoaderTests: XCTestCase { } func testNotGroupingExtensionsWithWithTheModuleThatExtends() throws { - let tempURL = URL(fileURLWithPath: NSTemporaryDirectory()).appendingPathComponent(ProcessInfo.processInfo.globallyUniqueString) - - try FileManager.default.createDirectory(at: tempURL, withIntermediateDirectories: true, attributes: nil) - defer { try? FileManager.default.removeItem(at: tempURL) } + let tempURL = try createTemporaryDirectory() var symbolGraphURLs = [URL]() @@ -130,10 +121,7 @@ class SymbolGraphLoaderTests: XCTestCase { } func testLoadingHighNumberOfModulesConcurrently() throws { - let tempURL = URL(fileURLWithPath: NSTemporaryDirectory()).appendingPathComponent(ProcessInfo.processInfo.globallyUniqueString) - - try FileManager.default.createDirectory(at: tempURL, withIntermediateDirectories: true, attributes: nil) - defer { try? FileManager.default.removeItem(at: tempURL) } + let tempURL = try createTemporaryDirectory() let symbolGraphSourceURL = Bundle.module.url( forResource: "TestBundle", withExtension: "docc", subdirectory: "Test Bundles")! diff --git a/Tests/SwiftDocCTests/Infrastructure/SymbolReferenceTests.swift b/Tests/SwiftDocCTests/Infrastructure/SymbolReferenceTests.swift index 64efe1f311..b4106c481e 100644 --- a/Tests/SwiftDocCTests/Infrastructure/SymbolReferenceTests.swift +++ b/Tests/SwiftDocCTests/Infrastructure/SymbolReferenceTests.swift @@ -197,10 +197,7 @@ class SymbolReferenceTests: XCTestCase { ]), ]) - let tempURL = Foundation.URL(fileURLWithPath: NSTemporaryDirectory()).appendingPathComponent(ProcessInfo.processInfo.globallyUniqueString) - try FileManager.default.createDirectory(at: tempURL, withIntermediateDirectories: true, attributes: nil) - defer { try? FileManager.default.removeItem(at: tempURL) } - + let tempURL = try createTemporaryDirectory() let bundleURL = try testBundle.write(inside: tempURL) let workspace = DocumentationWorkspace() diff --git a/Tests/SwiftDocCTests/LinkTargets/LinkDestinationSummaryTests.swift b/Tests/SwiftDocCTests/LinkTargets/LinkDestinationSummaryTests.swift index 864297211d..1aba5e7a89 100644 --- a/Tests/SwiftDocCTests/LinkTargets/LinkDestinationSummaryTests.swift +++ b/Tests/SwiftDocCTests/LinkTargets/LinkDestinationSummaryTests.swift @@ -270,23 +270,4 @@ class ExternalLinkableTests: XCTestCase { ]) } } - - // Workaround that addTeardownBlock doesn't exist in swift-corelibs-xctest - - private var tempFilesToRemove: [URL] = [] - - override func tearDown() { - for url in tempFilesToRemove { - try? FileManager.default.removeItem(at: url) - } - tempFilesToRemove.removeAll() - super.tearDown() - } - - func createTemporaryDirectory() throws -> URL { - let url = Foundation.URL(fileURLWithPath: NSTemporaryDirectory()).appendingPathComponent(ProcessInfo.processInfo.globallyUniqueString) - try FileManager.default.createDirectory(at: url, withIntermediateDirectories: true, attributes: nil) - tempFilesToRemove.append(url) - return url - } } diff --git a/Tests/SwiftDocCTests/Model/LineHighlighterTests.swift b/Tests/SwiftDocCTests/Model/LineHighlighterTests.swift index 91ff565101..b44a37bc89 100644 --- a/Tests/SwiftDocCTests/Model/LineHighlighterTests.swift +++ b/Tests/SwiftDocCTests/Model/LineHighlighterTests.swift @@ -13,7 +13,6 @@ import XCTest import Markdown class LineHighlighterTests: XCTestCase { - static var tempFilesToRemove = [URL]() static let bundleIdentifier = "org.swift.docc.LineHighlighterTests" static let defaultOverview = TextFile(name: "TechnologyX.tutorial", utf8Content: """ @Technology(name: "TechnologyX") { @@ -49,14 +48,7 @@ class LineHighlighterTests: XCTestCase { ]) } - static func createTemporaryDirectory() throws -> URL { - let url = Foundation.URL(fileURLWithPath: NSTemporaryDirectory()).appendingPathComponent(ProcessInfo.processInfo.globallyUniqueString) - try FileManager.default.createDirectory(at: url, withIntermediateDirectories: true, attributes: nil) - LineHighlighterTests.tempFilesToRemove.append(url) - return url - } - - static func testBundleAndContext(bundleRoot: Folder, bundleIdentifier: BundleIdentifier) throws -> (DocumentationBundle, DocumentationContext) { + func testBundleAndContext(bundleRoot: Folder, bundleIdentifier: BundleIdentifier) throws -> (DocumentationBundle, DocumentationContext) { let workspace = DocumentationWorkspace() let context = try! DocumentationContext(dataProvider: workspace) @@ -68,7 +60,7 @@ class LineHighlighterTests: XCTestCase { return (bundle, context) } - static func highlights(tutorialFile: TextFile, codeFiles: [TextFile]) throws -> [LineHighlighter.Result] { + func highlights(tutorialFile: TextFile, codeFiles: [TextFile]) throws -> [LineHighlighter.Result] { let bundleFolder = LineHighlighterTests.bundleFolder(tutorial: tutorialFile, codeFiles: codeFiles) let (bundle, context) = try testBundleAndContext(bundleRoot: bundleFolder, bundleIdentifier: LineHighlighterTests.bundleIdentifier) @@ -91,7 +83,7 @@ class LineHighlighterTests: XCTestCase { @Assessments } """) - XCTAssertTrue(try LineHighlighterTests.highlights(tutorialFile: tutorialFile, codeFiles: []).isEmpty) + XCTAssertTrue(try highlights(tutorialFile: tutorialFile, codeFiles: []).isEmpty) } func testOneStep() throws { @@ -113,7 +105,7 @@ class LineHighlighterTests: XCTestCase { @Assessments """) let code1 = TextFile(name: "code1.swift", utf8Content: "func foo() {}") - let results = try LineHighlighterTests.highlights(tutorialFile: tutorialFile, codeFiles: [code1]) + let results = try highlights(tutorialFile: tutorialFile, codeFiles: [code1]) XCTAssertEqual(1, results.count) results.first.map { result in XCTAssertEqual(ResourceReference(bundleIdentifier: LineHighlighterTests.bundleIdentifier, path: code1.name), result.file) @@ -142,7 +134,7 @@ class LineHighlighterTests: XCTestCase { """) let code0 = TextFile(name: "code0.swift", utf8Content: "func foo() {}") let code1 = TextFile(name: "code1.swift", utf8Content: "func foo() {}\nfunc bar() {}") - let results = try LineHighlighterTests.highlights(tutorialFile: tutorialFile, codeFiles: [code0, code1]) + let results = try highlights(tutorialFile: tutorialFile, codeFiles: [code0, code1]) XCTAssertEqual(1, results.count) results.first.map { result in XCTAssertEqual(ResourceReference(bundleIdentifier: LineHighlighterTests.bundleIdentifier, path: code1.name), result.file) @@ -181,7 +173,7 @@ class LineHighlighterTests: XCTestCase { let code1 = TextFile(name: "code1.swift", utf8Content: "func foo() {}") let code2 = TextFile(name: "code2.swift", utf8Content: "func foo() {}\nfunc bar() {}") - let results = try LineHighlighterTests.highlights(tutorialFile: tutorialFile, codeFiles: [code1, code2]) + let results = try highlights(tutorialFile: tutorialFile, codeFiles: [code1, code2]) XCTAssertEqual(2, results.count) XCTAssertEqual(ResourceReference(bundleIdentifier: LineHighlighterTests.bundleIdentifier, path: code1.name), results[0].file) @@ -211,7 +203,7 @@ class LineHighlighterTests: XCTestCase { """) let code0 = TextFile(name: "code0.swift", utf8Content: "func foo() {}") let code1 = TextFile(name: "code1.swift", utf8Content: "func foo() {}\nfunc bar() {}") - let results = try LineHighlighterTests.highlights(tutorialFile: tutorialFile, codeFiles: [code0, code1]) + let results = try highlights(tutorialFile: tutorialFile, codeFiles: [code0, code1]) XCTAssertEqual(1, results.count) results.first.map { result in XCTAssertEqual(ResourceReference(bundleIdentifier: LineHighlighterTests.bundleIdentifier, path: code1.name), result.file) @@ -243,7 +235,7 @@ class LineHighlighterTests: XCTestCase { """) let code1 = TextFile(name: "code1.swift", utf8Content: "func foo() {}") let code2 = TextFile(name: "code2.swift", utf8Content: "func foo() {}\nfunc bar() {}") - let results = try LineHighlighterTests.highlights(tutorialFile: tutorialFile, codeFiles: [code1, code2]) + let results = try highlights(tutorialFile: tutorialFile, codeFiles: [code1, code2]) XCTAssertEqual(2, results.count) @@ -282,7 +274,7 @@ class LineHighlighterTests: XCTestCase { let code0 = TextFile(name: "code0.swift", utf8Content: "") let code1 = TextFile(name: "code1.swift", utf8Content: "func foo() {}") let code2 = TextFile(name: "code2.swift", utf8Content: "func foo() {}\nfunc bar() {}") - let results = try LineHighlighterTests.highlights(tutorialFile: tutorialFile, codeFiles: [code0, code1, code2]) + let results = try highlights(tutorialFile: tutorialFile, codeFiles: [code0, code1, code2]) XCTAssertEqual(2, results.count) @@ -297,12 +289,4 @@ class LineHighlighterTests: XCTestCase { XCTAssertNil(highlight.length) } } - - override func tearDown() { - for url in LineHighlighterTests.tempFilesToRemove { - try? FileManager.default.removeItem(at: url) - } - LineHighlighterTests.tempFilesToRemove.removeAll() - super.tearDown() - } } diff --git a/Tests/SwiftDocCTests/Model/SemaToRenderNodeTests.swift b/Tests/SwiftDocCTests/Model/SemaToRenderNodeTests.swift index b28d3aa0d3..7b188658cc 100644 --- a/Tests/SwiftDocCTests/Model/SemaToRenderNodeTests.swift +++ b/Tests/SwiftDocCTests/Model/SemaToRenderNodeTests.swift @@ -1796,7 +1796,7 @@ Document @1:1-11:19 // Overwrite the article so we can test the article eyebrow for articles without task groups let sourceURL = Bundle.module.url( forResource: "TestBundle", withExtension: "docc", subdirectory: "Test Bundles")! - let targetURL = URL(fileURLWithPath: NSTemporaryDirectory()).appendingPathComponent(UUID().uuidString).appendingPathExtension("docc") + let targetURL = try createTemporaryDirectory(pathComponents: "test.docc", createDirectoryForLastPathComponent: false) try FileManager.default.copyItem(at: sourceURL, to: targetURL) diff --git a/Tests/SwiftDocCTests/Rendering/PlistSymbolTests.swift b/Tests/SwiftDocCTests/Rendering/PlistSymbolTests.swift index dcdf7a2145..8e289e07e5 100644 --- a/Tests/SwiftDocCTests/Rendering/PlistSymbolTests.swift +++ b/Tests/SwiftDocCTests/Rendering/PlistSymbolTests.swift @@ -128,7 +128,7 @@ class PlistSymbolTests: XCTestCase { let tempDir = try TempFolder(content: [ TextFile(name: "missingIdeTitle.json", utf8Content: modifiedJSON), - ]) + ], atRoot: createTemporaryDirectory(createDirectoryForLastPathComponent: false)) let symbol = try RenderNode.decode(fromJSON: try Data(contentsOf: tempDir.url.appendingPathComponent("missingIdeTitle.json"))) // @@ -154,7 +154,7 @@ class PlistSymbolTests: XCTestCase { let tempDir = try TempFolder(content: [ TextFile(name: "missingPossibleValuesTitle.json", utf8Content: modifiedJSON), - ]) + ], atRoot: createTemporaryDirectory(createDirectoryForLastPathComponent: false)) let symbol = try RenderNode.decode(fromJSON: try Data(contentsOf: tempDir.url.appendingPathComponent("missingPossibleValuesTitle.json"))) // diff --git a/Tests/SwiftDocCTests/Semantics/SymbolTests.swift b/Tests/SwiftDocCTests/Semantics/SymbolTests.swift index 62e64573e4..8888ceca2d 100644 --- a/Tests/SwiftDocCTests/Semantics/SymbolTests.swift +++ b/Tests/SwiftDocCTests/Semantics/SymbolTests.swift @@ -499,9 +499,7 @@ class SymbolTests: XCTestCase { } func testWarningWhenDocCommentContainsDirectiveInSubclass() throws { - let tempURL = URL(fileURLWithPath: NSTemporaryDirectory().appending(UUID().uuidString)) - try FileManager.default.createDirectory(atPath: tempURL.path, withIntermediateDirectories: false, attributes: nil) - defer { try? FileManager.default.removeItem(at: tempURL) } + let tempURL = try createTemporaryDirectory() let bundleURL = try Folder(name: "Inheritance.docc", content: [ InfoPlist(displayName: "Inheritance", identifier: "com.test.inheritance"), diff --git a/Tests/SwiftDocCTests/Utility/LMDBTests.swift b/Tests/SwiftDocCTests/Utility/LMDBTests.swift index 5ce1a5dc33..a6de1731dc 100644 --- a/Tests/SwiftDocCTests/Utility/LMDBTests.swift +++ b/Tests/SwiftDocCTests/Utility/LMDBTests.swift @@ -13,29 +13,15 @@ import XCTest @testable import SwiftDocC final class SwiftLMDBTests: XCTestCase { - - let temporaryDirectoryURL = URL(fileURLWithPath: NSTemporaryDirectory(), isDirectory: true).appendingPathComponent(ProcessInfo.processInfo.globallyUniqueString) - - /// Convenience var for path. - var tmpPath: String { - return temporaryDirectoryURL.path - } - var environment: LMDB.Environment! - override func setUp() { - if !FileManager.default.fileExists(atPath: temporaryDirectoryURL.path) { - try? FileManager.default.createDirectory(at: temporaryDirectoryURL, withIntermediateDirectories: false, attributes: nil) - } else { - try? FileManager.default.removeItem(at: temporaryDirectoryURL) - try? FileManager.default.createDirectory(at: temporaryDirectoryURL, withIntermediateDirectories: false, attributes: nil) - } + override func setUpWithError() throws { + let tempURL = try createTemporaryDirectory() - environment = try! LMDB.Environment(path: tmpPath, maxDBs: 4, mapSize: 1024 * 1024 * 1024) // 1GB of mapSize + environment = try! LMDB.Environment(path: tempURL.path, maxDBs: 4, mapSize: 1024 * 1024 * 1024) // 1GB of mapSize } override func tearDown() { - try? FileManager.default.removeItem(at: temporaryDirectoryURL) environment = nil } diff --git a/Tests/SwiftDocCTests/XCTestCase+LoadingTestData.swift b/Tests/SwiftDocCTests/XCTestCase+LoadingTestData.swift new file mode 100644 index 0000000000..84ebf6fd4f --- /dev/null +++ b/Tests/SwiftDocCTests/XCTestCase+LoadingTestData.swift @@ -0,0 +1,77 @@ +/* + This source file is part of the Swift.org open source project + + Copyright (c) 2021 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 +*/ + +import Foundation +import XCTest +@testable import SwiftDocC + +extension XCTestCase { + + /// Loads a documentation bundle from the given source URL and creates a documentation context. + func loadBundle(from bundleURL: URL, codeListings: [String : AttributedCodeListing] = [:], externalResolvers: [String: ExternalReferenceResolver] = [:], externalSymbolResolver: ExternalSymbolResolver? = nil, diagnosticFilterLevel: DiagnosticSeverity = .hint, configureContext: ((DocumentationContext) throws -> Void)? = nil) throws -> (URL, DocumentationBundle, DocumentationContext) { + let workspace = DocumentationWorkspace() + let context = try DocumentationContext(dataProvider: workspace, diagnosticEngine: DiagnosticEngine(filterLevel: diagnosticFilterLevel)) + context.externalReferenceResolvers = externalResolvers + context.externalSymbolResolver = externalSymbolResolver + context.externalMetadata.diagnosticLevel = diagnosticFilterLevel + try configureContext?(context) + // Load the bundle using automatic discovery + let automaticDataProvider = try LocalFileSystemDataProvider(rootURL: bundleURL) + // Mutate the bundle to include the code listings, then apply to the workspace using a manual provider. + var bundle = try automaticDataProvider.bundles().first! + bundle.attributedCodeListings = codeListings + let dataProvider = PrebuiltLocalFileSystemDataProvider(bundles: [bundle]) + try workspace.registerProvider(dataProvider) + return (bundleURL, bundle, context) + } + + func testBundleAndContext(copying name: String, excludingPaths excludedPaths: [String] = [], codeListings: [String : AttributedCodeListing] = [:], externalResolvers: [BundleIdentifier : ExternalReferenceResolver] = [:], externalSymbolResolver: ExternalSymbolResolver? = nil, configureBundle: ((URL) throws -> Void)? = nil) throws -> (URL, DocumentationBundle, DocumentationContext) { + let sourceURL = Bundle.module.url( + forResource: name, withExtension: "docc", subdirectory: "Test Bundles")! + + let sourceExists = FileManager.default.fileExists(atPath: sourceURL.path) + let bundleURL = try createTemporaryDirectory(pathComponents: "\(name).docc", createDirectoryForLastPathComponent: !sourceExists) + + if sourceExists { + try FileManager.default.copyItem(at: sourceURL, to: bundleURL) + } + + for path in excludedPaths { + try FileManager.default.removeItem(at: bundleURL.appendingPathComponent(path)) + } + + // Do any additional setup to the custom bundle - adding, modifying files, etc + try configureBundle?(bundleURL) + + return try loadBundle(from: bundleURL, codeListings: codeListings, externalResolvers: externalResolvers, externalSymbolResolver: externalSymbolResolver) + } + + func testBundleAndContext(named name: String, codeListings: [String : AttributedCodeListing] = [:], externalResolvers: [String: ExternalReferenceResolver] = [:]) throws -> (DocumentationBundle, DocumentationContext) { + let bundleURL = Bundle.module.url( + forResource: name, withExtension: "docc", subdirectory: "Test Bundles")! + let (_, bundle, context) = try loadBundle(from: bundleURL, codeListings: codeListings, externalResolvers: externalResolvers) + return (bundle, context) + } + + func testBundle(named name: String) -> DocumentationBundle { + let (bundle, _) = try! testBundleAndContext(named: name) + return bundle + } + + func testBundleFromRootURL(named name: String) throws -> DocumentationBundle { + let bundleURL = Bundle.module.url( + forResource: name, withExtension: "docc", subdirectory: "Test Bundles")! + let dataProvider = try LocalFileSystemDataProvider(rootURL: bundleURL) + + let bundles = try dataProvider.bundles() + return bundles[0] + } + +} diff --git a/Tests/SwiftDocCTests/XCTestCase+TemporaryDirectory.swift b/Tests/SwiftDocCTests/XCTestCase+TemporaryDirectory.swift new file mode 100644 index 0000000000..99993e6727 --- /dev/null +++ b/Tests/SwiftDocCTests/XCTestCase+TemporaryDirectory.swift @@ -0,0 +1,56 @@ +/* + This source file is part of the Swift.org open source project + + Copyright (c) 2021 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 +*/ + +import Foundation +import XCTest +@testable import SwiftDocC + +// These helpers methods exist to put temp files for different test executions in different locations when running in Swift CI. + +extension XCTestCase { + + @available(*, deprecated, message: "Use `createTemporaryDirectory` instead in unit tests to avoid referencing a shared location in Swift CI.") + func NSTemporaryDirectory() -> String { + return Foundation.NSTemporaryDirectory() + } + + /// Creates a new temporary directory and returns the URL of that directory. + /// + /// At the end of the test the temporary directory is automatically removed. + /// + /// - Parameters: + /// - pathComponents: Additional path components to add to the temporary URL. + /// - createDirectoryForLastPathComponent: If the file manager should create a directory for the last path component or not. Defaults to `true`. + /// - fileManager: The file manager that will create the directory. + /// - Returns: The URL of the newly created directory. + func createTemporaryDirectory( + pathComponents: String..., + createDirectoryForLastPathComponent: Bool = true, + fileManager: FileManager = .default + ) throws -> URL { + let bundleParentDir = Bundle(for: Self.self).bundleURL.deletingLastPathComponent() + let baseURL = bundleParentDir.appendingPathComponent(name.replacingWhitespaceAndPunctuation(with: "-")) + + var tempURL = baseURL.appendingPathComponent(ProcessInfo.processInfo.globallyUniqueString) + for component in pathComponents { + tempURL.appendPathComponent(component) + } + tempURL.standardize() + + addTeardownBlock { + try? fileManager.removeItem(at: baseURL) + } + + let urlToCreate = createDirectoryForLastPathComponent ? tempURL : tempURL.deletingLastPathComponent() + try fileManager.createDirectory(at: urlToCreate, withIntermediateDirectories: true, attributes: nil) + + return tempURL + } +} diff --git a/Tests/SwiftDocCUtilitiesTests/ArgumentParsing/ConvertSubcommandTests.swift b/Tests/SwiftDocCUtilitiesTests/ArgumentParsing/ConvertSubcommandTests.swift index 92437213d8..d606aa4ce9 100644 --- a/Tests/SwiftDocCUtilitiesTests/ArgumentParsing/ConvertSubcommandTests.swift +++ b/Tests/SwiftDocCUtilitiesTests/ArgumentParsing/ConvertSubcommandTests.swift @@ -21,19 +21,11 @@ class ConvertSubcommandTests: XCTestCase { func testOptionsValidation() throws { // create source bundle directory - let sourceURL = Foundation.URL(fileURLWithPath: NSTemporaryDirectory()).appendingPathComponent(UUID().uuidString).appendingPathExtension("documentation") - try FileManager.default.createDirectory(at: sourceURL, withIntermediateDirectories: true, attributes: nil) - defer { - try? FileManager.default.removeItem(at: sourceURL) - } + let sourceURL = try createTemporaryDirectory(pathComponents: "documentation") try "".write(to: sourceURL.appendingPathComponent("Info.plist"), atomically: true, encoding: .utf8) // create template dir - let rendererTemplateDirectory = Foundation.URL(fileURLWithPath: NSTemporaryDirectory()).appendingPathComponent(UUID().uuidString) - try FileManager.default.createDirectory(at: rendererTemplateDirectory, withIntermediateDirectories: true, attributes: nil) - defer { - try? FileManager.default.removeItem(at: rendererTemplateDirectory) - } + let rendererTemplateDirectory = try createTemporaryDirectory() try "".write(to: rendererTemplateDirectory.appendingPathComponent("index.html"), atomically: true, encoding: .utf8) // Tests a single input. @@ -84,7 +76,7 @@ class ConvertSubcommandTests: XCTestCase { // Test default template do { unsetenv(TemplateOption.environmentVariableKey) - let tempDir = URL(fileURLWithPath: NSTemporaryDirectory()).appendingPathComponent(UUID().uuidString) + let tempDir = try createTemporaryDirectory() let doccExecutableLocation = tempDir .appendingPathComponent("bin") .appendingPathComponent("docc-executable-name") diff --git a/Tests/SwiftDocCUtilitiesTests/ArgumentParsing/ErrorMessageTests.swift b/Tests/SwiftDocCUtilitiesTests/ArgumentParsing/ErrorMessageTests.swift index 98e64c00ee..98b9022ab2 100644 --- a/Tests/SwiftDocCUtilitiesTests/ArgumentParsing/ErrorMessageTests.swift +++ b/Tests/SwiftDocCUtilitiesTests/ArgumentParsing/ErrorMessageTests.swift @@ -16,19 +16,11 @@ class ErrorMessageTests: XCTestCase { func testInvalidParameterMessageError() throws { // create source bundle directory - let sourceURL = Foundation.URL(fileURLWithPath: NSTemporaryDirectory()).appendingPathComponent(UUID().uuidString).appendingPathExtension("documentation") - try FileManager.default.createDirectory(at: sourceURL, withIntermediateDirectories: true, attributes: nil) - defer { - try? FileManager.default.removeItem(at: sourceURL) - } + let sourceURL = try createTemporaryDirectory(pathComponents: "documentation") try "".write(to: sourceURL.appendingPathComponent("Info.plist"), atomically: true, encoding: .utf8) // create renderer template directory - let rendererDirectory = Foundation.URL(fileURLWithPath: NSTemporaryDirectory()).appendingPathComponent(UUID().uuidString) - try FileManager.default.createDirectory(at: rendererDirectory, withIntermediateDirectories: true, attributes: nil) - defer { - try? FileManager.default.removeItem(at: rendererDirectory) - } + let rendererDirectory = try createTemporaryDirectory() try "".write(to: rendererDirectory.appendingPathComponent("index.html"), atomically: true, encoding: .utf8) do { diff --git a/Tests/SwiftDocCUtilitiesTests/ArgumentParsing/PreviewSubcommandTests.swift b/Tests/SwiftDocCUtilitiesTests/ArgumentParsing/PreviewSubcommandTests.swift index faed8227a5..f11f60ebfc 100644 --- a/Tests/SwiftDocCUtilitiesTests/ArgumentParsing/PreviewSubcommandTests.swift +++ b/Tests/SwiftDocCUtilitiesTests/ArgumentParsing/PreviewSubcommandTests.swift @@ -17,25 +17,16 @@ class PreviewSubcommandTests: XCTestCase { forResource: "TestBundle", withExtension: "docc", subdirectory: "Test Bundles")! // Create HTML template dir. - let templateDir = Foundation.URL(fileURLWithPath: NSTemporaryDirectory()).appendingPathComponent(UUID().uuidString) - try FileManager.default.createDirectory(at: templateDir, withIntermediateDirectories: true, attributes: nil) - defer { - try? FileManager.default.removeItem(at: templateDir) - } + let templateDir = try createTemporaryDirectory() try "".write(to: templateDir.appendingPathComponent("index.html"), atomically: true, encoding: .utf8) + let tempURL = try createTemporaryDirectory() // Create Test TLS Certificate File - let testTLSCertificate = Foundation.URL(fileURLWithPath: NSTemporaryDirectory()).appendingPathComponent("testCert.pem") - defer { - try? FileManager.default.removeItem(at: testTLSCertificate) - } + let testTLSCertificate = tempURL.appendingPathComponent("testCert.pem") try "".write(to: testTLSCertificate, atomically: true, encoding: .utf8) // Create Test TLS Key File - let testTLSKey = Foundation.URL(fileURLWithPath: NSTemporaryDirectory()).appendingPathComponent("testCert.pem") - defer { - try? FileManager.default.removeItem(at: testTLSKey) - } + let testTLSKey = tempURL.appendingPathComponent("testCert.pem") try "".write(to: testTLSKey, atomically: true, encoding: .utf8) // Tests a single input. @@ -57,7 +48,7 @@ class PreviewSubcommandTests: XCTestCase { // Test default template do { unsetenv(TemplateOption.environmentVariableKey) - let tempDir = URL(fileURLWithPath: NSTemporaryDirectory()).appendingPathComponent(UUID().uuidString) + let tempDir = try createTemporaryDirectory() let doccExecutableLocation = tempDir .appendingPathComponent("bin") .appendingPathComponent("docc-executable-name") @@ -72,9 +63,6 @@ class PreviewSubcommandTests: XCTestCase { TemplateOption.doccExecutableLocation = originalDoccExecutableLocation } try FileManager.default.createDirectory(at: defaultTemplateDir, withIntermediateDirectories: true, attributes: nil) - defer { - try? FileManager.default.removeItem(at: defaultTemplateDir) - } try "".write(to: defaultTemplateDir.appendingPathComponent("index.html"), atomically: true, encoding: .utf8) let preview = try Docc.Preview.parse([ diff --git a/Tests/SwiftDocCUtilitiesTests/ConvertActionIndexerTests.swift b/Tests/SwiftDocCUtilitiesTests/ConvertActionIndexerTests.swift index 151c9ecadb..be9a224214 100644 --- a/Tests/SwiftDocCUtilitiesTests/ConvertActionIndexerTests.swift +++ b/Tests/SwiftDocCUtilitiesTests/ConvertActionIndexerTests.swift @@ -21,9 +21,7 @@ class ConvertActionIndexerTests: XCTestCase { forResource: "TestBundle", withExtension: "docc", subdirectory: "Test Bundles")! // Create temo folder. - let url = URL(fileURLWithPath: NSTemporaryDirectory().appending(UUID().uuidString)) - try FileManager.default.createDirectory(at: url, withIntermediateDirectories: true, attributes: nil) - defer { try? FileManager.default.removeItem(at: url) } + let url = try createTemporaryDirectory() // Copy TestBundle into a temp folder let testBundleURL = url.appendingPathComponent("TestBundle.docc") diff --git a/Tests/SwiftDocCUtilitiesTests/ConvertActionTests.swift b/Tests/SwiftDocCUtilitiesTests/ConvertActionTests.swift index 36d5a68b7e..fa09b6ef9b 100644 --- a/Tests/SwiftDocCUtilitiesTests/ConvertActionTests.swift +++ b/Tests/SwiftDocCUtilitiesTests/ConvertActionTests.swift @@ -1759,15 +1759,9 @@ class ConvertActionTests: XCTestCase { // The navigator index needs to test with the real file manager let bundleURL = Bundle.module.url(forResource: "TestBundle", withExtension: "docc", subdirectory: "Test Bundles")! - let targetURL = URL(fileURLWithPath: NSTemporaryDirectory()).appendingPathComponent(UUID().uuidString) - - let fileManager = FileManager.default - try fileManager.createDirectory(at: targetURL, withIntermediateDirectories: true, attributes: nil) - defer { try? fileManager.removeItem(at: targetURL) } - - let templateURL = URL(fileURLWithPath: NSTemporaryDirectory()).appendingPathComponent(UUID().uuidString) + let targetURL = try createTemporaryDirectory() + let templateURL = try createTemporaryDirectory(createDirectoryForLastPathComponent: false) try Folder.emptyHTMLTemplateDirectory.write(to: templateURL) - defer { try? fileManager.removeItem(at: templateURL) } // Convert the documentation and create an index @@ -1788,7 +1782,7 @@ class ConvertActionTests: XCTestCase { let indexFromConvertAction = try NavigatorIndex(url: indexURL) XCTAssertEqual(indexFromConvertAction.count, 37) - try fileManager.removeItem(at: indexURL) + try FileManager.default.removeItem(at: indexURL) // Run just the index command over the built documentation @@ -2316,10 +2310,7 @@ class ConvertActionTests: XCTestCase { footer, ]) - let tempURL = URL(fileURLWithPath: NSTemporaryDirectory()) - .appendingPathComponent(ProcessInfo.processInfo.globallyUniqueString) - try FileManager.default.createDirectory(at: tempURL, withIntermediateDirectories: true, attributes: nil) - defer { try? FileManager.default.removeItem(at: tempURL) } + let tempURL = try createTemporaryDirectory() let targetURL = tempURL.appendingPathComponent("target", isDirectory: true) let bundleURL = try bundle.write(inside: tempURL) diff --git a/Tests/SwiftDocCUtilitiesTests/DirectoryMonitorTests.swift b/Tests/SwiftDocCUtilitiesTests/DirectoryMonitorTests.swift index 004c51879d..7d2d163864 100644 --- a/Tests/SwiftDocCUtilitiesTests/DirectoryMonitorTests.swift +++ b/Tests/SwiftDocCUtilitiesTests/DirectoryMonitorTests.swift @@ -121,12 +121,8 @@ class DirectoryMonitorTests: XCTestCase { #if !os(Linux) && !os(Android) // Create temp folder & sub-folder. - let tempFolderURL = Foundation.URL(fileURLWithPath: NSTemporaryDirectory()).appendingPathComponent(UUID().uuidString) - let tempSubfolderURL = tempFolderURL.appendingPathComponent("subfolder") - try FileManager.default.createDirectory(at: tempSubfolderURL, withIntermediateDirectories: true, attributes: nil) - defer { - try? FileManager.default.removeItem(at: tempFolderURL) - } + let tempSubfolderURL = try createTemporaryDirectory(pathComponents: "subfolder") + let tempFolderURL = tempSubfolderURL.deletingLastPathComponent() // A file URL to update. let updateURL = tempSubfolderURL.appendingPathComponent("test.txt") @@ -174,12 +170,8 @@ class DirectoryMonitorTests: XCTestCase { #if !os(Linux) && !os(Android) // Create temp folder & sub-folder. - let tempFolderURL = Foundation.URL(fileURLWithPath: NSTemporaryDirectory()).appendingPathComponent(UUID().uuidString) - let tempSubfolderURL = tempFolderURL.appendingPathComponent("subfolder") - try FileManager.default.createDirectory(at: tempSubfolderURL, withIntermediateDirectories: true, attributes: nil) - defer { - try? FileManager.default.removeItem(at: tempFolderURL) - } + let tempSubfolderURL = try createTemporaryDirectory(pathComponents: "subfolder") + let tempFolderURL = tempSubfolderURL.deletingLastPathComponent() // 1) Test that creating a hidden file inside the tree will not trigger an update. try monitorNoUpdates(url: tempFolderURL, testBlock: { @@ -211,12 +203,8 @@ class DirectoryMonitorTests: XCTestCase { #if !os(Linux) && !os(Android) // Create temp folder & sub-folder. - let tempFolderURL = Foundation.URL(fileURLWithPath: NSTemporaryDirectory()).appendingPathComponent(UUID().uuidString) - let tempSubfolderURL = tempFolderURL.appendingPathComponent("subfolder") - try FileManager.default.createDirectory(at: tempSubfolderURL, withIntermediateDirectories: true, attributes: nil) - defer { - try? FileManager.default.removeItem(at: tempFolderURL) - } + let tempSubfolderURL = try createTemporaryDirectory(pathComponents: "subfolder") + let tempFolderURL = tempSubfolderURL.deletingLastPathComponent() // A file URL to update. let updateURL = tempSubfolderURL.appendingPathComponent("test.txt") diff --git a/Tests/SwiftDocCUtilitiesTests/FolderStructureTests.swift b/Tests/SwiftDocCUtilitiesTests/FolderStructureTests.swift index 43136c334e..04d61b32e0 100644 --- a/Tests/SwiftDocCUtilitiesTests/FolderStructureTests.swift +++ b/Tests/SwiftDocCUtilitiesTests/FolderStructureTests.swift @@ -105,23 +105,4 @@ class FolderStructureTests: XCTestCase { XCTAssertEqual(try FileManager.default.contentsOfDirectory(atPath: lowercaseCopyURL.path), ["lower"]) } - - // Workaround that addTeardownBlock doesn't exist in swift-corelibs-xctest - - private var tempFilesToRemove: [URL] = [] - - override func tearDown() { - for url in tempFilesToRemove { - try? FileManager.default.removeItem(at: url) - } - tempFilesToRemove.removeAll() - super.tearDown() - } - - func createTemporaryDirectory() throws -> URL { - let url = Foundation.URL(fileURLWithPath: NSTemporaryDirectory()).appendingPathComponent(ProcessInfo.processInfo.globallyUniqueString) - try FileManager.default.createDirectory(at: url, withIntermediateDirectories: true, attributes: nil) - tempFilesToRemove.append(url) - return url - } } diff --git a/Tests/SwiftDocCUtilitiesTests/IndexActionTests.swift b/Tests/SwiftDocCUtilitiesTests/IndexActionTests.swift index 1e707ba3f4..764e198c51 100644 --- a/Tests/SwiftDocCUtilitiesTests/IndexActionTests.swift +++ b/Tests/SwiftDocCUtilitiesTests/IndexActionTests.swift @@ -20,15 +20,9 @@ class IndexActionTests: XCTestCase { // Convert a test bundle as input for the IndexAction let bundleURL = Bundle.module.url(forResource: "TestBundle", withExtension: "docc", subdirectory: "Test Bundles")! - let targetURL = URL(fileURLWithPath: NSTemporaryDirectory()).appendingPathComponent(UUID().uuidString) - - let fileManager = FileManager.default - try fileManager.createDirectory(at: targetURL, withIntermediateDirectories: true, attributes: nil) - defer { try? fileManager.removeItem(at: targetURL) } - - let templateURL = URL(fileURLWithPath: NSTemporaryDirectory()).appendingPathComponent(UUID().uuidString) + let targetURL = try createTemporaryDirectory() + let templateURL = try createTemporaryDirectory(createDirectoryForLastPathComponent: false) try Folder.emptyHTMLTemplateDirectory.write(to: templateURL) - defer { try? fileManager.removeItem(at: templateURL) } let targetBundleURL = targetURL.appendingPathComponent("Result.builtdocs") diff --git a/Tests/SwiftDocCUtilitiesTests/OutOfProcessReferenceResolverTests.swift b/Tests/SwiftDocCUtilitiesTests/OutOfProcessReferenceResolverTests.swift index fdebd58ba7..d0d90ad06f 100644 --- a/Tests/SwiftDocCUtilitiesTests/OutOfProcessReferenceResolverTests.swift +++ b/Tests/SwiftDocCUtilitiesTests/OutOfProcessReferenceResolverTests.swift @@ -18,11 +18,7 @@ class OutOfProcessReferenceResolverTests: XCTestCase { func testInitializationProcess() throws { #if os(macOS) - let temporaryFolder = Foundation.URL(fileURLWithPath: NSTemporaryDirectory()).appendingPathComponent(ProcessInfo.processInfo.globallyUniqueString) - try FileManager.default.createDirectory(at: temporaryFolder, withIntermediateDirectories: true, attributes: nil) - defer { - try? FileManager.default.removeItem(at: temporaryFolder) - } + let temporaryFolder = try createTemporaryDirectory() let executableLocation = temporaryFolder.appendingPathComponent("link-resolver-executable") // When the executable file doesn't exist @@ -120,11 +116,7 @@ class OutOfProcessReferenceResolverTests: XCTestCase { func testResolvingTopicLinkProcess() throws { #if os(macOS) try assertResolvesTopicLink(makeResolver: { testMetadata in - let temporaryFolder = Foundation.URL(fileURLWithPath: NSTemporaryDirectory()).appendingPathComponent(ProcessInfo.processInfo.globallyUniqueString) - try FileManager.default.createDirectory(at: temporaryFolder, withIntermediateDirectories: true, attributes: nil) - defer { - try? FileManager.default.removeItem(at: temporaryFolder) - } + let temporaryFolder = try createTemporaryDirectory() let executableLocation = temporaryFolder.appendingPathComponent("link-resolver-executable") let encodedMetadata = try String(data: JSONEncoder().encode(testMetadata), encoding: .utf8)! @@ -256,11 +248,7 @@ class OutOfProcessReferenceResolverTests: XCTestCase { func testResolvingSymbolProcess() throws { #if os(macOS) try assertResolvesSymbol(makeResolver: { testMetadata in - let temporaryFolder = Foundation.URL(fileURLWithPath: NSTemporaryDirectory()).appendingPathComponent(ProcessInfo.processInfo.globallyUniqueString) - try FileManager.default.createDirectory(at: temporaryFolder, withIntermediateDirectories: true, attributes: nil) - defer { - try? FileManager.default.removeItem(at: temporaryFolder) - } + let temporaryFolder = try createTemporaryDirectory() let executableLocation = temporaryFolder.appendingPathComponent("link-resolver-executable") let encodedMetadata = try String(data: JSONEncoder().encode(testMetadata), encoding: .utf8)! @@ -327,11 +315,7 @@ class OutOfProcessReferenceResolverTests: XCTestCase { func testForwardsErrorOutputProcess() throws { #if os(macOS) - let temporaryFolder = Foundation.URL(fileURLWithPath: NSTemporaryDirectory()).appendingPathComponent(ProcessInfo.processInfo.globallyUniqueString) - try FileManager.default.createDirectory(at: temporaryFolder, withIntermediateDirectories: true, attributes: nil) - defer { - try? FileManager.default.removeItem(at: temporaryFolder) - } + let temporaryFolder = try createTemporaryDirectory() let executableLocation = temporaryFolder.appendingPathComponent("link-resolver-executable") try """ @@ -370,11 +354,7 @@ class OutOfProcessReferenceResolverTests: XCTestCase { func testForwardsResolverErrorsProcess() throws { #if os(macOS) - let temporaryFolder = Foundation.URL(fileURLWithPath: NSTemporaryDirectory()).appendingPathComponent(ProcessInfo.processInfo.globallyUniqueString) - try FileManager.default.createDirectory(at: temporaryFolder, withIntermediateDirectories: true, attributes: nil) - defer { - try? FileManager.default.removeItem(at: temporaryFolder) - } + let temporaryFolder = try createTemporaryDirectory() let executableLocation = temporaryFolder.appendingPathComponent("link-resolver-executable") try """ @@ -504,11 +484,7 @@ class OutOfProcessReferenceResolverTests: XCTestCase { func testErrorWhenReceivingBundleIdentifierTwiceProcess() throws { #if os(macOS) - let temporaryFolder = Foundation.URL(fileURLWithPath: NSTemporaryDirectory()).appendingPathComponent(ProcessInfo.processInfo.globallyUniqueString) - try FileManager.default.createDirectory(at: temporaryFolder, withIntermediateDirectories: true, attributes: nil) - defer { - try? FileManager.default.removeItem(at: temporaryFolder) - } + let temporaryFolder = try createTemporaryDirectory() let executableLocation = temporaryFolder.appendingPathComponent("link-resolver-executable") try """ diff --git a/Tests/SwiftDocCUtilitiesTests/PreviewActionIntegrationTests.swift b/Tests/SwiftDocCUtilitiesTests/PreviewActionIntegrationTests.swift index 4e14896bb7..15f30515bc 100644 --- a/Tests/SwiftDocCUtilitiesTests/PreviewActionIntegrationTests.swift +++ b/Tests/SwiftDocCUtilitiesTests/PreviewActionIntegrationTests.swift @@ -70,11 +70,10 @@ class PreviewActionIntegrationTests: XCTestCase { return (sourceURL: sourceURL, outputURL: outputURL, templateURL: templateURL) } -/* - FIXME: This test can fail when run in parallel so it is temporarily disabled (rdar://81524725). - + // FIXME: This test can fail when run in parallel so it is temporarily disabled (rdar://81524725). + /// Test the fix for . - func testWatchRecoversAfterConversionErrors() throws { + func skip_testWatchRecoversAfterConversionErrors() throws { #if os(macOS) // Source files. let source = createMinimalDocsBundle() @@ -109,7 +108,7 @@ class PreviewActionIntegrationTests: XCTestCase { return } - let socketURL = URL(fileURLWithPath: NSTemporaryDirectory()).appendingPathComponent(UUID().uuidString).appendingPathExtension("sock") + let socketURL = try createTemporaryDirectory(pathComponents: "sock", createDirectoryForLastPathComponent: false) preview.bindServerToSocketPath = socketURL.path // The technology output file URL @@ -223,7 +222,6 @@ class PreviewActionIntegrationTests: XCTestCase { try FileManager.default.removeItem(at: templateURL) #endif } -*/ class MemoryOutputChecker { init(storage: LogHandle.LogStorage, expectation: XCTestExpectation, condition: @escaping (String)->Bool) { @@ -237,7 +235,7 @@ class PreviewActionIntegrationTests: XCTestCase { let condition: (String)->Bool } - /// Helper class to fulfill an expecation when given condition is met. + /// Helper class to fulfill an expectation when given condition is met. class OutputChecker { init(fileURL: URL, expectation: XCTestExpectation, condition: @escaping (String)->Bool) { self.url = fileURL @@ -250,7 +248,7 @@ class PreviewActionIntegrationTests: XCTestCase { let condition: (String)->Bool } - /// Check the contents of the log file for the expectatation. + /// Check the contents of the log file for the expectation. func checkOutput(timer: Timer) { if let checker = timer.userInfo as? OutputChecker { if let data = try? Data(contentsOf: checker.url), @@ -460,7 +458,7 @@ class PreviewActionIntegrationTests: XCTestCase { return } - let socketURL = URL(fileURLWithPath: NSTemporaryDirectory()).appendingPathComponent(UUID().uuidString).appendingPathExtension("sock") + let socketURL = try createTemporaryDirectory(pathComponents: "sock", createDirectoryForLastPathComponent: false) preview.bindServerToSocketPath = socketURL.path // Start watching the source and get the initial (successful) state. @@ -540,10 +538,6 @@ class PreviewActionIntegrationTests: XCTestCase { // MARK: - - // Workaround that addTeardownBlock doesn't exist in swift-corelibs-xctest - - private static var tempFilesToRemove: [URL] = [] - override static func setUp() { super.setUp() PreviewAction.allowConcurrentPreviews = true @@ -551,21 +545,6 @@ class PreviewActionIntegrationTests: XCTestCase { override static func tearDown() { PreviewAction.allowConcurrentPreviews = false - for url in tempFilesToRemove { - try? FileManager.default.removeItem(at: url) - } - tempFilesToRemove.removeAll() super.tearDown() } - - func createTemporaryDirectory() throws -> URL { - // We append "-test" here because the convert action uses the same logic - // to create its temporary directory and we don't want to rely on - // this folder already existing - let url = Foundation.URL(fileURLWithPath: NSTemporaryDirectory()) - .appendingPathComponent("\(ProcessInfo.processInfo.globallyUniqueString)-test") - try FileManager.default.createDirectory(at: url, withIntermediateDirectories: true, attributes: nil) - Self.tempFilesToRemove.append(url) - return url - } } diff --git a/Tests/SwiftDocCUtilitiesTests/PreviewServer/PreviewHTTPHandlerTests.swift b/Tests/SwiftDocCUtilitiesTests/PreviewServer/PreviewHTTPHandlerTests.swift index 8c05689ad2..edda259ad5 100644 --- a/Tests/SwiftDocCUtilitiesTests/PreviewServer/PreviewHTTPHandlerTests.swift +++ b/Tests/SwiftDocCUtilitiesTests/PreviewServer/PreviewHTTPHandlerTests.swift @@ -26,8 +26,7 @@ class PreviewHTTPHandlerTests: XCTestCase { Folder(name: "css", content: [ TextFile(name: "test.css", utf8Content: "css"), ]) - ]) - try tempDir.write(to: URL(fileURLWithPath: NSTemporaryDirectory().appending(UUID().uuidString))) + ], atRoot: createTemporaryDirectory(createDirectoryForLastPathComponent: false)) let channel = EmbeddedChannel() let channelHandler = PreviewHTTPHandler(fileIO: fileIO, rootURL: tempDir.url) @@ -88,8 +87,7 @@ class PreviewHTTPHandlerTests: XCTestCase { Folder(name: "css", content: [ TextFile(name: "test.css", utf8Content: "css"), ]) - ]) - try tempDir.write(to: URL(fileURLWithPath: NSTemporaryDirectory().appending(UUID().uuidString))) + ], atRoot: createTemporaryDirectory(createDirectoryForLastPathComponent: false)) let channel = EmbeddedChannel() defer { diff --git a/Tests/SwiftDocCUtilitiesTests/PreviewServer/PreviewServerTests.swift b/Tests/SwiftDocCUtilitiesTests/PreviewServer/PreviewServerTests.swift index ed7a982e33..9b51df2781 100644 --- a/Tests/SwiftDocCUtilitiesTests/PreviewServer/PreviewServerTests.swift +++ b/Tests/SwiftDocCUtilitiesTests/PreviewServer/PreviewServerTests.swift @@ -25,14 +25,21 @@ import Foundation // class PreviewServerTests: XCTestCase { class PreviewServerTests { + func createTemporaryDirectory( + pathComponents: String..., + createDirectoryForLastPathComponent: Bool = true, + fileManager: FileManager = .default + ) throws -> URL { + fatalError("This test is disabled by not conforming to XCTestCase. This helper is added here to make the code compile. This should never be called.") + } + func testPreviewServerBeforeStarted() throws { // Create test content let tempFolder = try TempFolder(content: [ TextFile(name: "index.html", utf8Content: "index"), - ]) - try tempFolder.write(to: URL(fileURLWithPath: NSTemporaryDirectory().appending(UUID().uuidString))) + ], atRoot: createTemporaryDirectory(createDirectoryForLastPathComponent: false)) - let socketURL = URL(fileURLWithPath: FileManager.default.temporaryDirectory.path).appendingPathComponent(UUID().uuidString).appendingPathExtension("sock") + let socketURL = try createTemporaryDirectory(pathComponents: "sock", createDirectoryForLastPathComponent: false) // Run test server var log = LogHandle.none @@ -105,14 +112,14 @@ class PreviewServerTests { Folder(name: "downloads", content: [ TextFile(name: "test.zip", utf8Content: "downloads content"), ]) - ]) + ], atRoot: createTemporaryDirectory(createDirectoryForLastPathComponent: false)) } func testPreviewServerPaths() throws { let tempFolder = try makeTempFolder() // Socket URL - let socketURL = URL(fileURLWithPath: FileManager.default.temporaryDirectory.path).appendingPathComponent(UUID().uuidString).appendingPathExtension("sock") + let socketURL = try createTemporaryDirectory(pathComponents: "sock", createDirectoryForLastPathComponent: false) // Create the server var log = LogHandle.none @@ -159,7 +166,7 @@ class PreviewServerTests { let tempFolder = try makeTempFolder() // Socket URL - let socketURL = URL(fileURLWithPath: FileManager.default.temporaryDirectory.path).appendingPathComponent(UUID().uuidString).appendingPathExtension("sock") + let socketURL = try createTemporaryDirectory(pathComponents: "sock", createDirectoryForLastPathComponent: false) // Create the server var log = LogHandle.none diff --git a/Tests/SwiftDocCUtilitiesTests/PreviewServer/RequestHandler/DefaultRequestHandlerTests.swift b/Tests/SwiftDocCUtilitiesTests/PreviewServer/RequestHandler/DefaultRequestHandlerTests.swift index 7633da4e2c..bbae20b71d 100644 --- a/Tests/SwiftDocCUtilitiesTests/PreviewServer/RequestHandler/DefaultRequestHandlerTests.swift +++ b/Tests/SwiftDocCUtilitiesTests/PreviewServer/RequestHandler/DefaultRequestHandlerTests.swift @@ -21,8 +21,7 @@ class DefaultRequestHandlerTests: XCTestCase { func testDefaultHandler() throws { let tempDir = try TempFolder(content: [ TextFile(name: "index.html", utf8Content: "Hello!"), - ]) - try tempDir.write(to: URL(fileURLWithPath: NSTemporaryDirectory().appending(UUID().uuidString))) + ], atRoot: createTemporaryDirectory(createDirectoryForLastPathComponent: false)) // Default handler should be invoked for any non-asset path let request = makeRequestHead(path: "/random-path") @@ -45,8 +44,7 @@ class DefaultRequestHandlerTests: XCTestCase { let tempDir = try TempFolder(content: [ TextFile(name: "index.html", utf8Content: "Hello!"), TextFile(name: "existing.html", utf8Content: "Existing!"), - ]) - try tempDir.write(to: URL(fileURLWithPath: NSTemporaryDirectory().appending(UUID().uuidString))) + ], atRoot: createTemporaryDirectory(createDirectoryForLastPathComponent: false)) // Default handler should handle even paths that do exist on disc let request = makeRequestHead(path: "/existing.html") diff --git a/Tests/SwiftDocCUtilitiesTests/PreviewServer/RequestHandler/FileRequestHandlerTests.swift b/Tests/SwiftDocCUtilitiesTests/PreviewServer/RequestHandler/FileRequestHandlerTests.swift index 5bbf359dfd..1a5904e6e1 100644 --- a/Tests/SwiftDocCUtilitiesTests/PreviewServer/RequestHandler/FileRequestHandlerTests.swift +++ b/Tests/SwiftDocCUtilitiesTests/PreviewServer/RequestHandler/FileRequestHandlerTests.swift @@ -63,8 +63,7 @@ class FileRequestHandlerTests: XCTestCase { Folder(name: "downloads", content: [ TextFile(name: "project.zip", utf8Content: "zip"), ]) - ]) - try tempDir.write(to: URL(fileURLWithPath: NSTemporaryDirectory().appending(UUID().uuidString))) + ], atRoot: createTemporaryDirectory(createDirectoryForLastPathComponent: false)) try verifyAsset(root: tempDir.url, path: "/data/test.json", body: "data", type: "application/json") try verifyAsset(root: tempDir.url, path: "/css/test.css", body: "css", type: "text/css") @@ -87,8 +86,7 @@ class FileRequestHandlerTests: XCTestCase { } func testFileHandlerAssetsMissing() throws { - let tempDir = try TempFolder(content: []) - try tempDir.write(to: URL(fileURLWithPath: NSTemporaryDirectory().appending(UUID().uuidString))) + let tempDir = try TempFolder(content: [], atRoot: createTemporaryDirectory(createDirectoryForLastPathComponent: false)) let request = makeRequestHead(path: "/css/b00011100.css") let factory = FileRequestHandler(rootURL: tempDir.url, fileIO: fileIO) @@ -102,8 +100,7 @@ class FileRequestHandlerTests: XCTestCase { Folder(name: "videos", content: [ TextFile(name: "video.mov", utf8Content: "Hello!"), ]) - ]) - try tempDir.write(to: URL(fileURLWithPath: NSTemporaryDirectory().appending(UUID().uuidString))) + ], atRoot: createTemporaryDirectory(createDirectoryForLastPathComponent: false)) let request = makeRequestHead(path: "/videos/video.mov", headers: [("Range", "bytes=0-1")]) let factory = FileRequestHandler(rootURL: tempDir.url, fileIO: fileIO) @@ -122,8 +119,7 @@ class FileRequestHandlerTests: XCTestCase { Folder(name: "videos", content: [ TextFile(name: "video.mov", utf8Content: "Hello!"), ]) - ]) - try tempDir.write(to: URL(fileURLWithPath: NSTemporaryDirectory().appending(UUID().uuidString))) + ], atRoot: createTemporaryDirectory(createDirectoryForLastPathComponent: false)) let request = makeRequestHead(path: "/videos/../video.mov", headers: [("Range", "bytes=0-1")]) let factory = FileRequestHandler(rootURL: tempDir.url, fileIO: fileIO) @@ -138,8 +134,7 @@ class FileRequestHandlerTests: XCTestCase { Folder(name: "videos", content: [ TextFile(name: "video.mov", utf8Content: "Hello!"), ]) - ]) - try tempDir.write(to: URL(fileURLWithPath: NSTemporaryDirectory().appending(UUID().uuidString))) + ], atRoot: createTemporaryDirectory(createDirectoryForLastPathComponent: false)) let request = makeRequestHead(path: "/videos/. ? ? ? ./video.mov", headers: [("Range", "bytes=0-1")]) let factory = FileRequestHandler(rootURL: tempDir.url, fileIO: fileIO) diff --git a/Tests/SwiftDocCUtilitiesTests/SemanticAnalyzerTests.swift b/Tests/SwiftDocCUtilitiesTests/SemanticAnalyzerTests.swift index 10d48f98c3..3b2dfeed5a 100644 --- a/Tests/SwiftDocCUtilitiesTests/SemanticAnalyzerTests.swift +++ b/Tests/SwiftDocCUtilitiesTests/SemanticAnalyzerTests.swift @@ -14,12 +14,6 @@ import Markdown @testable import SwiftDocCUtilities class SemanticAnalyzerTests: XCTestCase { - func createTemporaryDirectory() throws -> URL { - let url = Foundation.URL(fileURLWithPath: NSTemporaryDirectory()).appendingPathComponent(ProcessInfo.processInfo.globallyUniqueString) - try FileManager.default.createDirectory(at: url, withIntermediateDirectories: true, attributes: nil) - return url - } - let bundleFolderHierarchy = Folder(name: "SemanticAnalyzerTests.docc", content: [ Folder(name: "Symbols", content: []), Folder(name: "Resources", content: [ diff --git a/Tests/SwiftDocCUtilitiesTests/TempFolderTests.swift b/Tests/SwiftDocCUtilitiesTests/TempFolderTests.swift index a80e5cddca..a374524a7b 100644 --- a/Tests/SwiftDocCUtilitiesTests/TempFolderTests.swift +++ b/Tests/SwiftDocCUtilitiesTests/TempFolderTests.swift @@ -14,22 +14,19 @@ import XCTest class TempFolderTests: XCTestCase { func testCreatesAndDeletesTempFolder() throws { - var tempFolder: TempFolder? = try TempFolder(content: [ + var tempFolder: TempFolder! = try TempFolder(content: [ TextFile(name: "index.html", utf8Content: "index"), - ]) - - // Below is safe to unwrap tempFolder because the initializer does not return an optional. + ], atRoot: createTemporaryDirectory(createDirectoryForLastPathComponent: false)) // Check the folder is created and the file inside exists. - XCTAssertTrue(FileManager.default.directoryExists(atPath: tempFolder!.url.path)) + XCTAssertTrue(FileManager.default.directoryExists(atPath: tempFolder.url.path)) XCTAssertTrue(FileManager.default.fileExists(atPath: tempFolder!.url.appendingPathComponent("index.html").path)) - let rootTempFolderPath = NSTemporaryDirectory() - + let rootTempFolderPath = tempFolder!.url.path // Check the temp folder is inside the system temporary folder. XCTAssertTrue(tempFolder!.url.path.contains(rootTempFolderPath)) - let tempFolderURL = tempFolder!.url + let tempFolderURL = tempFolder.url tempFolder = nil @@ -38,8 +35,8 @@ class TempFolderTests: XCTestCase { } func testCreatesRandomPaths() throws { - let tempFolder1 = try TempFolder(content: []) - let tempFolder2 = try TempFolder(content: []) + let tempFolder1 = try TempFolder(content: [], atRoot: createTemporaryDirectory(createDirectoryForLastPathComponent: false)) + let tempFolder2 = try TempFolder(content: [], atRoot: createTemporaryDirectory(createDirectoryForLastPathComponent: false)) XCTAssertNotEqual(tempFolder1.url, tempFolder2.url) } diff --git a/Tests/SwiftDocCUtilitiesTests/Utility/TestFileSystem.swift b/Tests/SwiftDocCUtilitiesTests/Utility/TestFileSystem.swift index fcc7138b8d..5419b5c965 100644 --- a/Tests/SwiftDocCUtilitiesTests/Utility/TestFileSystem.swift +++ b/Tests/SwiftDocCUtilitiesTests/Utility/TestFileSystem.swift @@ -70,7 +70,6 @@ class TestFileSystem: FileManagerProtocol, DocumentationWorkspaceDataProvider { // Default system paths files["/"] = Self.folderFixtureData - files[NSTemporaryDirectory()] = Self.folderFixtureData // Import given folders try updateDocumentationBundles(withFolders: folders) diff --git a/Tests/SwiftDocCUtilitiesTests/Utility/TestFileSystemTests.swift b/Tests/SwiftDocCUtilitiesTests/Utility/TestFileSystemTests.swift index 469751f652..df0cece3cb 100644 --- a/Tests/SwiftDocCUtilitiesTests/Utility/TestFileSystemTests.swift +++ b/Tests/SwiftDocCUtilitiesTests/Utility/TestFileSystemTests.swift @@ -21,8 +21,7 @@ class TestFileSystemTests: XCTestCase { XCTAssertTrue(try fs.bundles().isEmpty) var isDirectory = ObjCBool(false) XCTAssertTrue(fs.fileExists(atPath: "/", isDirectory: &isDirectory)) - XCTAssertTrue(isDirectory.boolValue) - XCTAssertTrue(fs.fileExists(atPath: NSTemporaryDirectory(), isDirectory: &isDirectory)) + XCTAssertEqual(fs.files.keys.sorted(), ["/"], "The root (/) should be the only existing path.") XCTAssertTrue(isDirectory.boolValue) XCTAssertFalse(fs.disableWriting) } @@ -36,7 +35,6 @@ class TestFileSystemTests: XCTestCase { let folder2 = Folder(name: "additional", content: []) let fs = try TestFileSystem(folders: [folder1, folder2]) - try fs.removeItem(at: URL(string: NSTemporaryDirectory())!) // Verify correct folders & files var isDirectory = ObjCBool(false) @@ -68,9 +66,6 @@ class TestFileSystemTests: XCTestCase { ]) let fs = try TestFileSystem(folders: [folder]) - - // Remove temp folder since the path is random on macOS and we can't do efficient comparisson of the dump - try fs.removeItem(at: URL(string: NSTemporaryDirectory())!) XCTAssertEqual(fs.dump(), """ / @@ -214,7 +209,6 @@ class TestFileSystemTests: XCTestCase { func testCreateDeeplyNestedDirectory() throws { let fs = try TestFileSystem(folders: []) - try fs.removeItem(at: URL(string: NSTemporaryDirectory())!) // Test if creates deeply nested directory structure try fs.createDirectory(at: URL(string: "/one/two/three/four/five/six")!, withIntermediateDirectories: true) From fb6fa6ea83b114301c4849369c572cbce63527b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Ro=CC=88nnqvist?= Date: Thu, 18 Nov 2021 12:59:25 -0800 Subject: [PATCH 02/16] Create new target for test utilities --- Package.swift | 11 ++++++++++- .../XCTestCase+TemporaryDirectory.swift | 10 ++++++++-- .../SymbolGraph/SymbolGraphLoaderTests.swift | 1 + .../Infrastructure/SymbolReferenceTests.swift | 1 + Tests/SwiftDocCTests/Model/LineHighlighterTests.swift | 1 + Tests/SwiftDocCTests/Rendering/PlistSymbolTests.swift | 1 + Tests/SwiftDocCTests/Utility/LMDBTests.swift | 3 ++- .../ArgumentParsing/ConvertSubcommandTests.swift | 1 + .../OutOfProcessReferenceResolverTests.swift | 1 + .../RequestHandler/FileRequestHandlerTests.swift | 1 + Tests/SwiftDocCUtilitiesTests/TempFolderTests.swift | 1 + 11 files changed, 28 insertions(+), 4 deletions(-) rename {Tests/SwiftDocCTests => Sources/SwiftDocCTestUtilities}/XCTestCase+TemporaryDirectory.swift (87%) diff --git a/Package.swift b/Package.swift index 5f944e1150..770d4c8f9c 100644 --- a/Package.swift +++ b/Package.swift @@ -44,7 +44,10 @@ let package = Package( ]), .testTarget( name: "SwiftDocCTests", - dependencies: ["SwiftDocC"], + dependencies: [ + "SwiftDocC", + "SwiftDocCTestUtilities", + ], resources: [ .copy("Test Resources"), .copy("Test Bundles"), @@ -66,11 +69,17 @@ let package = Package( dependencies: [ "SwiftDocCUtilities", "SwiftDocC", + "SwiftDocCTestUtilities", ], resources: [ .copy("Test Resources"), .copy("Test Bundles"), ]), + + // Test utility library + .target( + name: "SwiftDocCTestUtilities", + dependencies: []), // Command-line tool .executableTarget( diff --git a/Tests/SwiftDocCTests/XCTestCase+TemporaryDirectory.swift b/Sources/SwiftDocCTestUtilities/XCTestCase+TemporaryDirectory.swift similarity index 87% rename from Tests/SwiftDocCTests/XCTestCase+TemporaryDirectory.swift rename to Sources/SwiftDocCTestUtilities/XCTestCase+TemporaryDirectory.swift index 99993e6727..81856db7c1 100644 --- a/Tests/SwiftDocCTests/XCTestCase+TemporaryDirectory.swift +++ b/Sources/SwiftDocCTestUtilities/XCTestCase+TemporaryDirectory.swift @@ -10,11 +10,10 @@ import Foundation import XCTest -@testable import SwiftDocC // These helpers methods exist to put temp files for different test executions in different locations when running in Swift CI. -extension XCTestCase { +public extension XCTestCase { @available(*, deprecated, message: "Use `createTemporaryDirectory` instead in unit tests to avoid referencing a shared location in Swift CI.") func NSTemporaryDirectory() -> String { @@ -54,3 +53,10 @@ extension XCTestCase { return tempURL } } + +private extension String { + func replacingWhitespaceAndPunctuation(with separator: String) -> String { + let charactersToStrip = CharacterSet.whitespaces.union(.punctuationCharacters) + return components(separatedBy: charactersToStrip).filter({ !$0.isEmpty }).joined(separator: separator) + } +} diff --git a/Tests/SwiftDocCTests/Infrastructure/SymbolGraph/SymbolGraphLoaderTests.swift b/Tests/SwiftDocCTests/Infrastructure/SymbolGraph/SymbolGraphLoaderTests.swift index 355368ab50..1706e65c9e 100644 --- a/Tests/SwiftDocCTests/Infrastructure/SymbolGraph/SymbolGraphLoaderTests.swift +++ b/Tests/SwiftDocCTests/Infrastructure/SymbolGraph/SymbolGraphLoaderTests.swift @@ -12,6 +12,7 @@ import Foundation import XCTest @testable import SymbolKit @testable import SwiftDocC +import SwiftDocCTestUtilities class SymbolGraphLoaderTests: XCTestCase { diff --git a/Tests/SwiftDocCTests/Infrastructure/SymbolReferenceTests.swift b/Tests/SwiftDocCTests/Infrastructure/SymbolReferenceTests.swift index b4106c481e..95549eb053 100644 --- a/Tests/SwiftDocCTests/Infrastructure/SymbolReferenceTests.swift +++ b/Tests/SwiftDocCTests/Infrastructure/SymbolReferenceTests.swift @@ -11,6 +11,7 @@ import XCTest @testable import SymbolKit @testable import SwiftDocC +import SwiftDocCTestUtilities class SymbolReferenceTests: XCTestCase { func testUsesIdentifierForUnresolvedSymbols() { diff --git a/Tests/SwiftDocCTests/Model/LineHighlighterTests.swift b/Tests/SwiftDocCTests/Model/LineHighlighterTests.swift index b44a37bc89..ae76be6cba 100644 --- a/Tests/SwiftDocCTests/Model/LineHighlighterTests.swift +++ b/Tests/SwiftDocCTests/Model/LineHighlighterTests.swift @@ -11,6 +11,7 @@ import XCTest @testable import SwiftDocC import Markdown +import SwiftDocCTestUtilities class LineHighlighterTests: XCTestCase { static let bundleIdentifier = "org.swift.docc.LineHighlighterTests" diff --git a/Tests/SwiftDocCTests/Rendering/PlistSymbolTests.swift b/Tests/SwiftDocCTests/Rendering/PlistSymbolTests.swift index 8e289e07e5..a96e279d2e 100644 --- a/Tests/SwiftDocCTests/Rendering/PlistSymbolTests.swift +++ b/Tests/SwiftDocCTests/Rendering/PlistSymbolTests.swift @@ -11,6 +11,7 @@ import Foundation import XCTest @testable import SwiftDocC +import SwiftDocCTestUtilities class PlistSymbolTests: XCTestCase { private let plistSymbolURL = Bundle.module.url( diff --git a/Tests/SwiftDocCTests/Utility/LMDBTests.swift b/Tests/SwiftDocCTests/Utility/LMDBTests.swift index a6de1731dc..2050311d82 100644 --- a/Tests/SwiftDocCTests/Utility/LMDBTests.swift +++ b/Tests/SwiftDocCTests/Utility/LMDBTests.swift @@ -11,6 +11,7 @@ import XCTest @testable import SwiftDocC +import SwiftDocCTestUtilities final class SwiftLMDBTests: XCTestCase { var environment: LMDB.Environment! @@ -30,7 +31,7 @@ final class SwiftLMDBTests: XCTestCase { func testVersion() { let version = LMDB.default.version - // Ensure the LMDB library version is the exptected one: 0.9.70 + // Ensure the LMDB library version is the expected one: 0.9.70 XCTAssertEqual(version.description, "0.9.70") } diff --git a/Tests/SwiftDocCUtilitiesTests/ArgumentParsing/ConvertSubcommandTests.swift b/Tests/SwiftDocCUtilitiesTests/ArgumentParsing/ConvertSubcommandTests.swift index d606aa4ce9..6c143dfdb8 100644 --- a/Tests/SwiftDocCUtilitiesTests/ArgumentParsing/ConvertSubcommandTests.swift +++ b/Tests/SwiftDocCUtilitiesTests/ArgumentParsing/ConvertSubcommandTests.swift @@ -11,6 +11,7 @@ import XCTest @testable import SwiftDocCUtilities @testable import SwiftDocC +import SwiftDocCTestUtilities class ConvertSubcommandTests: XCTestCase { private let testBundleURL = Bundle.module.url( diff --git a/Tests/SwiftDocCUtilitiesTests/OutOfProcessReferenceResolverTests.swift b/Tests/SwiftDocCUtilitiesTests/OutOfProcessReferenceResolverTests.swift index d0d90ad06f..7f03037ba7 100644 --- a/Tests/SwiftDocCUtilitiesTests/OutOfProcessReferenceResolverTests.swift +++ b/Tests/SwiftDocCUtilitiesTests/OutOfProcessReferenceResolverTests.swift @@ -13,6 +13,7 @@ import Foundation import SymbolKit @testable import SwiftDocC @testable import SwiftDocCUtilities +import SwiftDocCTestUtilities class OutOfProcessReferenceResolverTests: XCTestCase { diff --git a/Tests/SwiftDocCUtilitiesTests/PreviewServer/RequestHandler/FileRequestHandlerTests.swift b/Tests/SwiftDocCUtilitiesTests/PreviewServer/RequestHandler/FileRequestHandlerTests.swift index 1a5904e6e1..0c826823e2 100644 --- a/Tests/SwiftDocCUtilitiesTests/PreviewServer/RequestHandler/FileRequestHandlerTests.swift +++ b/Tests/SwiftDocCUtilitiesTests/PreviewServer/RequestHandler/FileRequestHandlerTests.swift @@ -12,6 +12,7 @@ import Foundation import XCTest @testable import SwiftDocC @testable import SwiftDocCUtilities +import SwiftDocCTestUtilities import NIO import NIOHTTP1 diff --git a/Tests/SwiftDocCUtilitiesTests/TempFolderTests.swift b/Tests/SwiftDocCUtilitiesTests/TempFolderTests.swift index a374524a7b..8d671c7d09 100644 --- a/Tests/SwiftDocCUtilitiesTests/TempFolderTests.swift +++ b/Tests/SwiftDocCUtilitiesTests/TempFolderTests.swift @@ -11,6 +11,7 @@ import Foundation import XCTest @testable import SwiftDocC +import SwiftDocCTestUtilities class TempFolderTests: XCTestCase { func testCreatesAndDeletesTempFolder() throws { From b6452987f75d26ec945b13f3e394cad3670a6634 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Ro=CC=88nnqvist?= Date: Thu, 18 Nov 2021 13:03:39 -0800 Subject: [PATCH 03/16] Pass the temporary directory to ConvertAction --- .../Actions/Convert/ConvertAction.swift | 11 ++- .../ConvertAction+CommandInitialization.swift | 1 + .../ConvertActionTests.swift | 95 +++++++++++++------ .../IndexActionTests.swift | 4 +- .../PreviewActionIntegrationTests.swift | 14 ++- 5 files changed, 90 insertions(+), 35 deletions(-) diff --git a/Sources/SwiftDocCUtilities/Action/Actions/Convert/ConvertAction.swift b/Sources/SwiftDocCUtilities/Action/Actions/Convert/ConvertAction.swift index 72f973b3a0..730d1fe502 100644 --- a/Sources/SwiftDocCUtilities/Action/Actions/Convert/ConvertAction.swift +++ b/Sources/SwiftDocCUtilities/Action/Actions/Convert/ConvertAction.swift @@ -59,6 +59,7 @@ public struct ConvertAction: Action, RecreatingContext { private var currentDataProvider: DocumentationWorkspaceDataProvider? private var injectedDataProvider: DocumentationWorkspaceDataProvider? private var fileManager: FileManagerProtocol + private let temporaryDirectory: URL public var setupContext: ((inout DocumentationContext) -> Void)? { didSet { @@ -86,6 +87,7 @@ public struct ConvertAction: Action, RecreatingContext { context: DocumentationContext? = nil, dataProvider: DocumentationWorkspaceDataProvider? = nil, fileManager: FileManagerProtocol = FileManager.default, + temporaryDirectory: URL, documentationCoverageOptions: DocumentationCoverageOptions = .noCoverage, bundleDiscoveryOptions: BundleDiscoveryOptions = .init(), diagnosticLevel: String? = nil, @@ -107,6 +109,7 @@ public struct ConvertAction: Action, RecreatingContext { self.workspace = workspace self.injectedDataProvider = dataProvider self.fileManager = fileManager + self.temporaryDirectory = temporaryDirectory self.documentationCoverageOptions = documentationCoverageOptions self.transformForStaticHosting = transformForStaticHosting self.hostingBasePath = hostingBasePath @@ -200,7 +203,8 @@ public struct ConvertAction: Action, RecreatingContext { inheritDocs: Bool = false, experimentalEnableCustomTemplates: Bool = false, transformForStaticHosting: Bool, - hostingBasePath: String? + hostingBasePath: String?, + temporaryDirectory: URL ) throws { // Note: This public initializer exists separately from the above internal one // because the FileManagerProtocol type we use to enable mocking in tests @@ -222,6 +226,7 @@ public struct ConvertAction: Action, RecreatingContext { context: context, dataProvider: dataProvider, fileManager: FileManager.default, + temporaryDirectory: temporaryDirectory, documentationCoverageOptions: documentationCoverageOptions, bundleDiscoveryOptions: bundleDiscoveryOptions, diagnosticLevel: diagnosticLevel, @@ -409,9 +414,7 @@ public struct ConvertAction: Action, RecreatingContext { } func createTempFolder(with templateURL: URL?) throws -> URL { - - let targetURL = URL(fileURLWithPath: NSTemporaryDirectory()) - .appendingPathComponent(ProcessInfo.processInfo.globallyUniqueString) + let targetURL = temporaryDirectory.appendingPathComponent(ProcessInfo.processInfo.globallyUniqueString) if let templateURL = templateURL { // If a template directory has been provided, create the temporary build folder with diff --git a/Sources/SwiftDocCUtilities/ArgumentParsing/ActionExtensions/ConvertAction+CommandInitialization.swift b/Sources/SwiftDocCUtilities/ArgumentParsing/ActionExtensions/ConvertAction+CommandInitialization.swift index 1d3357a485..c6024d64d6 100644 --- a/Sources/SwiftDocCUtilities/ArgumentParsing/ActionExtensions/ConvertAction+CommandInitialization.swift +++ b/Sources/SwiftDocCUtilities/ArgumentParsing/ActionExtensions/ConvertAction+CommandInitialization.swift @@ -72,6 +72,7 @@ extension ConvertAction { emitDigest: convert.emitDigest, currentPlatforms: parsedPlatforms, buildIndex: convert.index, + temporaryDirectory: URL(fileURLWithPath: NSTemporaryDirectory()), documentationCoverageOptions: DocumentationCoverageOptions( from: convert.experimentalDocumentationCoverageOptions ), diff --git a/Tests/SwiftDocCUtilitiesTests/ConvertActionTests.swift b/Tests/SwiftDocCUtilitiesTests/ConvertActionTests.swift index fa09b6ef9b..cf0d892ace 100644 --- a/Tests/SwiftDocCUtilitiesTests/ConvertActionTests.swift +++ b/Tests/SwiftDocCUtilitiesTests/ConvertActionTests.swift @@ -13,6 +13,7 @@ import Foundation @testable import SwiftDocC @testable import SwiftDocCUtilities import Markdown +import SwiftDocCTestUtilities class ConvertActionTests: XCTestCase { #if !os(iOS) @@ -89,7 +90,8 @@ class ConvertActionTests: XCTestCase { emitDigest: false, currentPlatforms: nil, dataProvider: testDataProvider, - fileManager: testDataProvider) + fileManager: testDataProvider, + temporaryDirectory: createTemporaryDirectory()) let result = try action.perform(logHandle: .standardOutput) // Verify that the following files and folder exist at the output location @@ -135,7 +137,8 @@ class ConvertActionTests: XCTestCase { emitDigest: false, currentPlatforms: nil, dataProvider: testDataProvider, - fileManager: testDataProvider) + fileManager: testDataProvider, + temporaryDirectory: createTemporaryDirectory()) let result = try action.perform(logHandle: .standardOutput) // Verify that the following files and folder exist at the output location @@ -193,7 +196,8 @@ class ConvertActionTests: XCTestCase { emitDigest: false, currentPlatforms: nil, dataProvider: testDataProvider, - fileManager: testDataProvider) + fileManager: testDataProvider, + temporaryDirectory: createTemporaryDirectory()) let result = try action.perform(logHandle: .standardOutput) // Verify that the following files and folder exist at the output location @@ -226,7 +230,8 @@ class ConvertActionTests: XCTestCase { emitDigest: false, currentPlatforms: nil, dataProvider: testDataProvider, - fileManager: testDataProvider) + fileManager: testDataProvider, + temporaryDirectory: createTemporaryDirectory()) let result = try action.perform(logHandle: .standardOutput) // Verify that the following files and folder exist at the output location @@ -258,7 +263,8 @@ class ConvertActionTests: XCTestCase { emitDigest: false, currentPlatforms: nil, dataProvider: testDataProvider, - fileManager: testDataProvider) + fileManager: testDataProvider, + temporaryDirectory: createTemporaryDirectory()) let result = try action.perform(logHandle: .standardOutput) XCTAssertEqual(result.problems.count, 0) } @@ -291,6 +297,7 @@ class ConvertActionTests: XCTestCase { emitDigest: false, currentPlatforms: nil, fileManager: testDataProvider, + temporaryDirectory: createTemporaryDirectory(), bundleDiscoveryOptions: BundleDiscoveryOptions( infoPlistFallbacks: infoPlistFallbacks, additionalSymbolGraphFiles: [URL(fileURLWithPath: "/Not-a-doc-bundle/MyKit.symbols.json")] @@ -354,6 +361,7 @@ class ConvertActionTests: XCTestCase { emitDigest: false, currentPlatforms: nil, fileManager: testDataProvider, + temporaryDirectory: createTemporaryDirectory(), bundleDiscoveryOptions: BundleDiscoveryOptions( infoPlistFallbacks: infoPlistFallbacks, additionalSymbolGraphFiles: [URL(fileURLWithPath: "/Not-a-doc-bundle/MyKit.symbols.json")] @@ -396,7 +404,8 @@ class ConvertActionTests: XCTestCase { emitDigest: false, currentPlatforms: nil, dataProvider: testDataProvider, - fileManager: testDataProvider) + fileManager: testDataProvider, + temporaryDirectory: createTemporaryDirectory()) let targetURL = target.absoluteURL.appendingPathComponent("output") @@ -432,7 +441,8 @@ class ConvertActionTests: XCTestCase { emitDigest: false, currentPlatforms: nil, dataProvider: testDataProvider, - fileManager: testDataProvider) + fileManager: testDataProvider, + temporaryDirectory: createTemporaryDirectory()) let targetURL = target.absoluteURL.appendingPathComponent("target").appendingPathComponent("output") @@ -460,7 +470,8 @@ class ConvertActionTests: XCTestCase { emitDigest: false, currentPlatforms: nil, dataProvider: testDataProvider, - fileManager: testDataProvider) + fileManager: testDataProvider, + temporaryDirectory: createTemporaryDirectory()) let result = try action.perform(logHandle: .standardOutput) // Verify that the following files and folder exist at the output location @@ -498,7 +509,8 @@ class ConvertActionTests: XCTestCase { emitDigest: false, currentPlatforms: nil, dataProvider: testDataProvider, - fileManager: testDataProvider) + fileManager: testDataProvider, + temporaryDirectory: createTemporaryDirectory()) let result = try action.perform(logHandle: .none) // Construct the URLs for the produced render json: @@ -567,7 +579,8 @@ class ConvertActionTests: XCTestCase { emitDigest: false, currentPlatforms: nil, dataProvider: testDataProvider, - fileManager: testDataProvider) + fileManager: testDataProvider, + temporaryDirectory: createTemporaryDirectory()) let result = try action.perform(logHandle: .none) // Construct the URLs for the produced render json: @@ -654,7 +667,8 @@ class ConvertActionTests: XCTestCase { emitDigest: true, currentPlatforms: nil, dataProvider: testDataProvider, - fileManager: testDataProvider) + fileManager: testDataProvider, + temporaryDirectory: createTemporaryDirectory()) let result = try action.perform(logHandle: .standardOutput) // Verify that the following files and folder exist at the output location @@ -711,6 +725,7 @@ class ConvertActionTests: XCTestCase { currentPlatforms: nil, dataProvider: testDataProvider, fileManager: testDataProvider, + temporaryDirectory: createTemporaryDirectory(), diagnosticLevel: "hint") // report all errors during the test let result = try action.perform(logHandle: .standardOutput) @@ -791,6 +806,7 @@ class ConvertActionTests: XCTestCase { currentPlatforms: nil, dataProvider: testDataProvider, fileManager: testDataProvider, + temporaryDirectory: createTemporaryDirectory(), diagnosticLevel: "hint") // report all errors during the test let result = try action.perform(logHandle: .standardOutput) @@ -875,7 +891,8 @@ class ConvertActionTests: XCTestCase { emitDigest: false, currentPlatforms: nil, dataProvider: testDataProvider, - fileManager: testDataProvider) + fileManager: testDataProvider, + temporaryDirectory: createTemporaryDirectory()) let result = try action.perform(logHandle: .standardOutput) XCTAssertFalse( @@ -904,7 +921,8 @@ class ConvertActionTests: XCTestCase { emitDigest: false, currentPlatforms: nil, dataProvider: testDataProvider, - fileManager: testDataProvider) + fileManager: testDataProvider, + temporaryDirectory: createTemporaryDirectory()) let result = try action.perform(logHandle: .standardOutput) XCTAssert( @@ -942,7 +960,8 @@ class ConvertActionTests: XCTestCase { emitDigest: true, currentPlatforms: nil, dataProvider: testDataProvider, - fileManager: testDataProvider) + fileManager: testDataProvider, + temporaryDirectory: createTemporaryDirectory()) let result = try action.perform(logHandle: .standardOutput) // Verify that the following files and folder exist at the output location @@ -1031,7 +1050,8 @@ class ConvertActionTests: XCTestCase { emitDigest: true, currentPlatforms: nil, dataProvider: testDataProvider, - fileManager: testDataProvider) + fileManager: testDataProvider, + temporaryDirectory: createTemporaryDirectory()) let result = try action.perform(logHandle: .standardOutput) // Because the page order isn't deterministic, we create the indexing records and linkable entities in the same order as the pages. @@ -1236,7 +1256,8 @@ class ConvertActionTests: XCTestCase { emitDigest: true, currentPlatforms: nil, dataProvider: testDataProvider, - fileManager: testDataProvider) + fileManager: testDataProvider, + temporaryDirectory: createTemporaryDirectory()) let result = try action.perform(logHandle: .standardOutput) // Because the page order isn't deterministic, we create the indexing records and linkable entities in the same order as the pages. @@ -1391,7 +1412,8 @@ class ConvertActionTests: XCTestCase { emitDigest: true, // emit digest files currentPlatforms: nil, dataProvider: testDataProvider, - fileManager: testDataProvider) + fileManager: testDataProvider, + temporaryDirectory: createTemporaryDirectory()) let result = try action.perform(logHandle: .standardOutput) XCTAssertTrue(testDataProvider.fileExists(atPath: result.outputs[0].appendingPathComponent("assets.json").path)) @@ -1415,7 +1437,8 @@ class ConvertActionTests: XCTestCase { emitDigest: false, // don't emit digest files currentPlatforms: nil, dataProvider: testDataProvider, - fileManager: testDataProvider) + fileManager: testDataProvider, + temporaryDirectory: createTemporaryDirectory()) let result = try action.perform(logHandle: .standardOutput) XCTAssertFalse(testDataProvider.fileExists(atPath: result.outputs[0].appendingPathComponent("assets.json").path)) @@ -1448,6 +1471,7 @@ class ConvertActionTests: XCTestCase { currentPlatforms: nil, dataProvider: testDataProvider, fileManager: testDataProvider, + temporaryDirectory: createTemporaryDirectory(), documentationCoverageOptions: .noCoverage) let result = try action.perform(logHandle: .standardOutput) @@ -1470,6 +1494,7 @@ class ConvertActionTests: XCTestCase { currentPlatforms: nil, dataProvider: testDataProvider, fileManager: testDataProvider, + temporaryDirectory: createTemporaryDirectory(), documentationCoverageOptions: DocumentationCoverageOptions(level: .brief)) let result = try action.perform(logHandle: .standardOutput) @@ -1492,6 +1517,7 @@ class ConvertActionTests: XCTestCase { currentPlatforms: nil, dataProvider: testDataProvider, fileManager: testDataProvider, + temporaryDirectory: createTemporaryDirectory(), documentationCoverageOptions: DocumentationCoverageOptions(level: .detailed)) let result = try action.perform(logHandle: .standardOutput) @@ -1526,7 +1552,8 @@ class ConvertActionTests: XCTestCase { "platform2": PlatformVersion(.init(11, 12, 13), beta: false), ], dataProvider: testDataProvider, - fileManager: testDataProvider) + fileManager: testDataProvider, + temporaryDirectory: createTemporaryDirectory()) XCTAssertEqual(action.context.externalMetadata.currentPlatforms, [ "platform1" : PlatformVersion(.init(10, 11, 12), beta: false), @@ -1556,6 +1583,7 @@ class ConvertActionTests: XCTestCase { currentPlatforms: nil, dataProvider: testDataProvider, fileManager: testDataProvider, + temporaryDirectory: createTemporaryDirectory(), diagnosticEngine: engine) let result = try action.perform(logHandle: .standardOutput) XCTAssertFalse(result.didEncounterError) @@ -1620,7 +1648,8 @@ class ConvertActionTests: XCTestCase { emitDigest: emitDigest, currentPlatforms: nil, dataProvider: testDataProvider, - fileManager: testDataProvider) + fileManager: testDataProvider, + temporaryDirectory: createTemporaryDirectory()) action.converter.batchNodeCount = batchSize @@ -1699,7 +1728,8 @@ class ConvertActionTests: XCTestCase { emitDigest: false, currentPlatforms: nil, dataProvider: testFileSystem, - fileManager: testFileSystem + fileManager: testFileSystem, + temporaryDirectory: createTemporaryDirectory() ) _ = try action.perform(logHandle: .none) @@ -1773,7 +1803,8 @@ class ConvertActionTests: XCTestCase { htmlTemplateDirectory: templateURL, emitDigest: false, currentPlatforms: nil, - buildIndex: true // Create an index + buildIndex: true, + temporaryDirectory: createTemporaryDirectory() // Create an index ) _ = try action.perform(logHandle: .standardOutput) @@ -1840,7 +1871,8 @@ class ConvertActionTests: XCTestCase { htmlTemplateDirectory: nil, emitDigest: false, currentPlatforms: nil, - buildIndex: true + buildIndex: true, + temporaryDirectory: createTemporaryDirectory() ) enableFeatureFlag(\.isExperimentalObjectiveCSupportEnabled) @@ -2055,6 +2087,7 @@ class ConvertActionTests: XCTestCase { currentPlatforms: nil, dataProvider: testDataProvider, fileManager: testDataProvider, + temporaryDirectory: createTemporaryDirectory(), diagnosticLevel: "error", diagnosticEngine: engine ) @@ -2092,6 +2125,7 @@ class ConvertActionTests: XCTestCase { currentPlatforms: nil, dataProvider: testDataProvider, fileManager: testDataProvider, + temporaryDirectory: createTemporaryDirectory(), diagnosticLevel: "error", diagnosticEngine: engine ) @@ -2130,6 +2164,7 @@ class ConvertActionTests: XCTestCase { currentPlatforms: nil, dataProvider: testDataProvider, fileManager: testDataProvider, + temporaryDirectory: createTemporaryDirectory(), diagnosticLevel: "error" ) XCTAssertThrowsError(try action.performAndHandleResult()) { error in @@ -2160,6 +2195,7 @@ class ConvertActionTests: XCTestCase { currentPlatforms: nil, dataProvider: testDataProvider, fileManager: testDataProvider, + temporaryDirectory: createTemporaryDirectory(), inheritDocs: flag) XCTAssertEqual(action.context.externalMetadata.inheritDocs, flag) } @@ -2174,7 +2210,8 @@ class ConvertActionTests: XCTestCase { emitDigest: false, currentPlatforms: nil, dataProvider: testDataProvider, - fileManager: testDataProvider) + fileManager: testDataProvider, + temporaryDirectory: createTemporaryDirectory()) XCTAssertEqual(action.context.externalMetadata.inheritDocs, false) } @@ -2200,7 +2237,8 @@ class ConvertActionTests: XCTestCase { emitDigest: true, currentPlatforms: nil, dataProvider: testDataProvider, - fileManager: testDataProvider + fileManager: testDataProvider, + temporaryDirectory: createTemporaryDirectory() ) XCTAssertThrowsError(try action.performAndHandleResult(), "The test bundle should have thrown an error about an incomplete symbol graph file") @@ -2230,7 +2268,8 @@ class ConvertActionTests: XCTestCase { emitDigest: true, currentPlatforms: nil, dataProvider: testDataProvider, - fileManager: testDataProvider + fileManager: testDataProvider, + temporaryDirectory: createTemporaryDirectory() ) try action.performAndHandleResult() @@ -2266,7 +2305,8 @@ class ConvertActionTests: XCTestCase { emitDigest: false, currentPlatforms: nil, dataProvider: testDataProvider, - fileManager: testDataProvider + fileManager: testDataProvider, + temporaryDirectory: createTemporaryDirectory() ) let result = try action.perform(logHandle: .standardOutput) @@ -2328,6 +2368,7 @@ class ConvertActionTests: XCTestCase { currentPlatforms: nil, dataProvider: dataProvider, fileManager: FileManager.default, + temporaryDirectory: createTemporaryDirectory(), experimentalEnableCustomTemplates: true ) let result = try action.perform(logHandle: .standardOutput) diff --git a/Tests/SwiftDocCUtilitiesTests/IndexActionTests.swift b/Tests/SwiftDocCUtilitiesTests/IndexActionTests.swift index 764e198c51..bb5d9e2529 100644 --- a/Tests/SwiftDocCUtilitiesTests/IndexActionTests.swift +++ b/Tests/SwiftDocCUtilitiesTests/IndexActionTests.swift @@ -13,6 +13,7 @@ import Foundation @testable import SwiftDocC @testable import SwiftDocCUtilities import Markdown +import SwiftDocCTestUtilities class IndexActionTests: XCTestCase { #if !os(iOS) @@ -33,7 +34,8 @@ class IndexActionTests: XCTestCase { targetDirectory: targetBundleURL, htmlTemplateDirectory: templateURL, emitDigest: false, - currentPlatforms: nil + currentPlatforms: nil, + temporaryDirectory: createTemporaryDirectory() ) _ = try action.perform(logHandle: .standardOutput) diff --git a/Tests/SwiftDocCUtilitiesTests/PreviewActionIntegrationTests.swift b/Tests/SwiftDocCUtilitiesTests/PreviewActionIntegrationTests.swift index 15f30515bc..8385279cc1 100644 --- a/Tests/SwiftDocCUtilitiesTests/PreviewActionIntegrationTests.swift +++ b/Tests/SwiftDocCUtilitiesTests/PreviewActionIntegrationTests.swift @@ -85,6 +85,7 @@ class PreviewActionIntegrationTests: XCTestCase { let logStorage = LogHandle.LogStorage() var logHandle = LogHandle.memory(logStorage) + let convertActionTempDirectory = try createTemporaryDirectory() let createConvertAction = { try ConvertAction( documentationBundleURL: sourceURL, @@ -94,7 +95,8 @@ class PreviewActionIntegrationTests: XCTestCase { htmlTemplateDirectory: templateURL, emitDigest: false, currentPlatforms: nil, - fileManager: FileManager.default) + fileManager: FileManager.default, + temporaryDirectory: convertActionTempDirectory) } guard let preview = try? PreviewAction( @@ -289,6 +291,7 @@ class PreviewActionIntegrationTests: XCTestCase { let engine = DiagnosticEngine() + let convertActionTempDirectory = try createTemporaryDirectory() let createConvertAction = { try ConvertAction( documentationBundleURL: sourceURL, @@ -299,6 +302,7 @@ class PreviewActionIntegrationTests: XCTestCase { emitDigest: false, currentPlatforms: nil, fileManager: FileManager.default, + temporaryDirectory: convertActionTempDirectory, diagnosticEngine: engine) } @@ -359,6 +363,7 @@ class PreviewActionIntegrationTests: XCTestCase { let logStorage = LogHandle.LogStorage() let logHandle = LogHandle.memory(logStorage) + let convertActionTempDirectory = try createTemporaryDirectory() let createConvertAction = { try ConvertAction( documentationBundleURL: sourceURL, @@ -368,7 +373,8 @@ class PreviewActionIntegrationTests: XCTestCase { htmlTemplateDirectory: templateURL, emitDigest: false, currentPlatforms: nil, - fileManager: FileManager.default) + fileManager: FileManager.default, + temporaryDirectory: convertActionTempDirectory) } guard let preview = try? PreviewAction( @@ -429,6 +435,7 @@ class PreviewActionIntegrationTests: XCTestCase { var convertFuture: () -> Void = {} + let convertActionTempDirectory = try createTemporaryDirectory() /// Create the convert action and store it let createConvertAction = { () -> ConvertAction in var convertAction = try ConvertAction( @@ -439,7 +446,8 @@ class PreviewActionIntegrationTests: XCTestCase { htmlTemplateDirectory: templateURL, emitDigest: false, currentPlatforms: nil, - fileManager: FileManager.default) + fileManager: FileManager.default, + temporaryDirectory: convertActionTempDirectory) // Inject a future to control how long the conversion takes convertAction.willPerformFuture = convertFuture From b7e969b6ca3b9404df87d062c29b9f3e357b2cc8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Ro=CC=88nnqvist?= Date: Thu, 18 Nov 2021 13:03:58 -0800 Subject: [PATCH 04/16] Re-enable one skipped test --- Tests/SwiftDocCTests/Indexing/NavigatorIndexTests.swift | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/Tests/SwiftDocCTests/Indexing/NavigatorIndexTests.swift b/Tests/SwiftDocCTests/Indexing/NavigatorIndexTests.swift index 7495480ece..994c3c2f62 100644 --- a/Tests/SwiftDocCTests/Indexing/NavigatorIndexTests.swift +++ b/Tests/SwiftDocCTests/Indexing/NavigatorIndexTests.swift @@ -227,10 +227,7 @@ Root #endif } - // This test has been disabled because of frequent failures in Swift CI. - // - // rdar://85055022 tracks updating this test to remove any flakiness. - func disabled_testNavigationTreeLargeDumpAndReadAsync() throws { + func testNavigationTreeLargeDumpAndReadAsync() throws { let targetURL = try createTemporaryDirectory() let indexURL = targetURL.appendingPathComponent("nav.index") From 777319f77c7a8aea4ceebad5c958a2cb55974344 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Ro=CC=88nnqvist?= Date: Mon, 13 Dec 2021 11:59:11 -0800 Subject: [PATCH 05/16] Update new tests to use `createTemporaryDirectory` helper --- .../SemaToRenderNodeMultiLanguageTests.swift | 12 +++-- .../ConvertActionStaticHostableTests.swift | 15 ++---- .../ConvertActionTests.swift | 3 +- .../StaticHostableTransformerTests.swift | 47 ++++++------------- ...TransformForStaticHostingActionTests.swift | 34 +++++--------- 5 files changed, 39 insertions(+), 72 deletions(-) diff --git a/Tests/SwiftDocCTests/Model/SemaToRenderNodeMultiLanguageTests.swift b/Tests/SwiftDocCTests/Model/SemaToRenderNodeMultiLanguageTests.swift index 529c526f0b..a9bffec963 100644 --- a/Tests/SwiftDocCTests/Model/SemaToRenderNodeMultiLanguageTests.swift +++ b/Tests/SwiftDocCTests/Model/SemaToRenderNodeMultiLanguageTests.swift @@ -64,7 +64,7 @@ class SemaToRenderNodeMixedLanguageTests: ExperimentalObjectiveCTestCase { } func testOutputsMultiLanguageRenderNodes() throws { - let outputConsumer = try TestRenderNodeOutputConsumer.mixedLanguageFrameworkConsumer() + let outputConsumer = try mixedLanguageFrameworkConsumer() XCTAssertEqual( Set( @@ -119,7 +119,7 @@ class SemaToRenderNodeMixedLanguageTests: ExperimentalObjectiveCTestCase { } func testFrameworkRenderNodeHasExpectedContentAcrossLanguages() throws { - let outputConsumer = try TestRenderNodeOutputConsumer.mixedLanguageFrameworkConsumer() + let outputConsumer = try mixedLanguageFrameworkConsumer() let mixedLanguageFrameworkRenderNode = try outputConsumer.renderNode( withIdentifier: "MixedLanguageFramework" ) @@ -204,7 +204,7 @@ class SemaToRenderNodeMixedLanguageTests: ExperimentalObjectiveCTestCase { } func testObjectiveCAuthoredRenderNodeHasExpectedContentAcrossLanguages() throws { - let outputConsumer = try TestRenderNodeOutputConsumer.mixedLanguageFrameworkConsumer() + let outputConsumer = try mixedLanguageFrameworkConsumer() let fooRenderNode = try outputConsumer.renderNode(withIdentifier: "c:@E@Foo") assertExpectedContent( @@ -455,8 +455,10 @@ extension TestRenderNodeOutputConsumer { return try XCTUnwrap(renderNode) } - - static func mixedLanguageFrameworkConsumer() throws -> TestRenderNodeOutputConsumer { +} + +fileprivate extension SemaToRenderNodeMixedLanguageTests { + func mixedLanguageFrameworkConsumer() throws -> TestRenderNodeOutputConsumer { let (bundleURL, _, context) = try testBundleAndContext(copying: "MixedLanguageFramework") var converter = DocumentationConverter( diff --git a/Tests/SwiftDocCUtilitiesTests/ConvertActionStaticHostableTests.swift b/Tests/SwiftDocCUtilitiesTests/ConvertActionStaticHostableTests.swift index 05f75401f8..ffc8bf0474 100644 --- a/Tests/SwiftDocCUtilitiesTests/ConvertActionStaticHostableTests.swift +++ b/Tests/SwiftDocCUtilitiesTests/ConvertActionStaticHostableTests.swift @@ -18,22 +18,15 @@ class ConvertActionStaticHostableTests: StaticHostingBaseTests { func testConvertActionStaticHostableTestOutput() throws { let bundleURL = Bundle.module.url(forResource: "TestBundle", withExtension: "docc", subdirectory: "Test Bundles")! - let targetURL = URL(fileURLWithPath: NSTemporaryDirectory()).appendingPathComponent(UUID().uuidString) + let targetURL = try createTemporaryDirectory() let fileManager = FileManager.default - try fileManager.createDirectory(at: targetURL, withIntermediateDirectories: true, attributes: nil) - defer { try? fileManager.removeItem(at: targetURL) } - let targetBundleURL = targetURL.appendingPathComponent("Result.doccarchive") - defer { try? fileManager.removeItem(at: targetBundleURL) } - - let testTemplateURL = URL(fileURLWithPath: NSTemporaryDirectory()).appendingPathComponent(UUID().uuidString) + let testTemplateURL = try createTemporaryDirectory().appendingPathComponent("testTemplate") let templateFolder = Folder.testHTMLTemplateDirectory try templateFolder.write(to: testTemplateURL) - defer { try? fileManager.removeItem(at: testTemplateURL) } - let basePath = "test/folder" let indexHTML = Folder.testHTMLTemplate(basePath: "test/folder") @@ -47,12 +40,12 @@ class ConvertActionStaticHostableTests: StaticHostingBaseTests { emitDigest: false, currentPlatforms: nil, transformForStaticHosting: true, - hostingBasePath: basePath + hostingBasePath: basePath, + temporaryDirectory: try createTemporaryDirectory() ) _ = try action.perform(logHandle: .standardOutput) - // Test the content of the output folder. var expectedContent = ["data", "documentation", "tutorials", "downloads", "images", "metadata.json" ,"videos", "index.html"] expectedContent += templateFolder.content.filter { $0 is Folder }.map{ $0.name } diff --git a/Tests/SwiftDocCUtilitiesTests/ConvertActionTests.swift b/Tests/SwiftDocCUtilitiesTests/ConvertActionTests.swift index cf0d892ace..7734feadde 100644 --- a/Tests/SwiftDocCUtilitiesTests/ConvertActionTests.swift +++ b/Tests/SwiftDocCUtilitiesTests/ConvertActionTests.swift @@ -1937,7 +1937,8 @@ class ConvertActionTests: XCTestCase { htmlTemplateDirectory: nil, emitDigest: false, currentPlatforms: nil, - buildIndex: true + buildIndex: true, + temporaryDirectory: createTemporaryDirectory() ) _ = try action.perform(logHandle: .none) diff --git a/Tests/SwiftDocCUtilitiesTests/StaticHostableTransformerTests.swift b/Tests/SwiftDocCUtilitiesTests/StaticHostableTransformerTests.swift index 6038bbd349..9d58acd653 100644 --- a/Tests/SwiftDocCUtilitiesTests/StaticHostableTransformerTests.swift +++ b/Tests/SwiftDocCUtilitiesTests/StaticHostableTransformerTests.swift @@ -20,14 +20,11 @@ class StaticHostableTransformerTests: StaticHostingBaseTests { // Convert a test bundle as input for the StaticHostableTransformer let bundleURL = Bundle.module.url(forResource: "TestBundle", withExtension: "docc", subdirectory: "Test Bundles")! - let targetURL = URL(fileURLWithPath: NSTemporaryDirectory()).appendingPathComponent(UUID().uuidString) + let targetURL = try createTemporaryDirectory() let fileManager = FileManager.default - try fileManager.createDirectory(at: targetURL, withIntermediateDirectories: true, attributes: nil) - defer { try? fileManager.removeItem(at: targetURL) } - - let templateURL = URL(fileURLWithPath: NSTemporaryDirectory()).appendingPathComponent(UUID().uuidString) + let templateURL = try createTemporaryDirectory().appendingPathComponent("template") try Folder.emptyHTMLTemplateDirectory.write(to: templateURL) defer { try? fileManager.removeItem(at: templateURL) } @@ -41,17 +38,16 @@ class StaticHostableTransformerTests: StaticHostingBaseTests { targetDirectory: targetBundleURL, htmlTemplateDirectory: templateURL, emitDigest: false, - currentPlatforms: nil + currentPlatforms: nil, + temporaryDirectory: createTemporaryDirectory() ) _ = try action.perform(logHandle: .standardOutput) - let outputURL = URL(fileURLWithPath: NSTemporaryDirectory()).appendingPathComponent(UUID().uuidString) - defer { try? fileManager.removeItem(at: outputURL) } + let outputURL = try createTemporaryDirectory().appendingPathComponent("output") - let testTemplateURL = URL(fileURLWithPath: NSTemporaryDirectory()).appendingPathComponent(UUID().uuidString) + let testTemplateURL = try createTemporaryDirectory().appendingPathComponent("testTemplate") try Folder.testHTMLTemplateDirectory.write(to: testTemplateURL) - defer { try? fileManager.removeItem(at: testTemplateURL) } let basePath = "test/folder" let indexHTML = Folder.testHTMLTemplate(basePath: basePath) @@ -103,10 +99,8 @@ class StaticHostableTransformerTests: StaticHostingBaseTests { /// Creates a DocC archive and then archive then executes and TransformForStaticHostingAction on it to produce static content which is then validated. func testStaticHostableTransformerBasePaths() throws { - - let testTemplateURL = URL(fileURLWithPath: NSTemporaryDirectory()).appendingPathComponent(UUID().uuidString) + let testTemplateURL = try createTemporaryDirectory().appendingPathComponent("testTemplate") try Folder.testHTMLTemplateDirectory.write(to: testTemplateURL) - defer { try? FileManager.default.removeItem(at: testTemplateURL) } let basePaths = ["test": "test", "/test": "test", @@ -126,27 +120,16 @@ class StaticHostableTransformerTests: StaticHostingBaseTests { XCTAssertEqual(indexHTML, testIndexHTML, "Template HTML not transformed as expected") } } - - func testStaticHostableTransformerIndexHTMLOutput() throws { - // Convert a test bundle as input for the StaticHostableTransformer let bundleURL = Bundle.module.url(forResource: "TestBundle", withExtension: "docc", subdirectory: "Test Bundles")! - let targetURL = URL(fileURLWithPath: NSTemporaryDirectory()).appendingPathComponent(UUID().uuidString) - - let fileManager = FileManager.default - try fileManager.createDirectory(at: targetURL, withIntermediateDirectories: true, attributes: nil) - - defer { try? fileManager.removeItem(at: targetURL) } - - let templateURL = URL(fileURLWithPath: NSTemporaryDirectory()).appendingPathComponent(UUID().uuidString) + let targetURL = try createTemporaryDirectory() + let templateURL = try createTemporaryDirectory().appendingPathComponent("template") try Folder.emptyHTMLTemplateDirectory.write(to: templateURL) - defer { try? fileManager.removeItem(at: templateURL) } let targetBundleURL = targetURL.appendingPathComponent("Result.doccarchive") - defer { try? fileManager.removeItem(at: targetBundleURL) } var action = try ConvertAction( documentationBundleURL: bundleURL, @@ -155,7 +138,8 @@ class StaticHostableTransformerTests: StaticHostingBaseTests { targetDirectory: targetBundleURL, htmlTemplateDirectory: templateURL, emitDigest: false, - currentPlatforms: nil + currentPlatforms: nil, + temporaryDirectory: createTemporaryDirectory() ) _ = try action.perform(logHandle: .standardOutput) @@ -163,9 +147,8 @@ class StaticHostableTransformerTests: StaticHostingBaseTests { let dataURL = targetBundleURL.appendingPathComponent(NodeURLGenerator.Path.dataFolderName) let dataProvider = try LocalFileSystemDataProvider(rootURL: dataURL) - let testTemplateURL = URL(fileURLWithPath: NSTemporaryDirectory()).appendingPathComponent(UUID().uuidString) + let testTemplateURL = try createTemporaryDirectory().appendingPathComponent("testTemplate") try Folder.testHTMLTemplateDirectory.write(to: testTemplateURL) - defer { try? fileManager.removeItem(at: testTemplateURL) } let basePaths = ["test": "test", "/test": "test", @@ -176,11 +159,9 @@ class StaticHostableTransformerTests: StaticHostingBaseTests { "test/test/": "test/test", "/test/test/": "test/test"] + let fileManager = FileManager.default for (basePath, testValue) in basePaths { - - let outputURL = URL(fileURLWithPath: NSTemporaryDirectory()).appendingPathComponent(UUID().uuidString) - defer { try? fileManager.removeItem(at: outputURL) } - + let outputURL = try createTemporaryDirectory().appendingPathComponent("output") let indexHTMLData = try StaticHostableTransformer.transformHTMLTemplate(htmlTemplate: testTemplateURL, hostingBasePath: basePath) let transformer = StaticHostableTransformer(dataProvider: dataProvider, fileManager: fileManager, outputURL: outputURL, indexHTMLData: indexHTMLData) diff --git a/Tests/SwiftDocCUtilitiesTests/TransformForStaticHostingActionTests.swift b/Tests/SwiftDocCUtilitiesTests/TransformForStaticHostingActionTests.swift index 6409388bfb..f1a1bb1fed 100644 --- a/Tests/SwiftDocCUtilitiesTests/TransformForStaticHostingActionTests.swift +++ b/Tests/SwiftDocCUtilitiesTests/TransformForStaticHostingActionTests.swift @@ -20,19 +20,12 @@ class TransformForStaticHostingActionTests: StaticHostingBaseTests { // Convert a test bundle as input for the TransformForStaticHostingAction let bundleURL = Bundle.module.url(forResource: "TestBundle", withExtension: "docc", subdirectory: "Test Bundles")! - let targetURL = URL(fileURLWithPath: NSTemporaryDirectory()).appendingPathComponent(UUID().uuidString) - - let fileManager = FileManager.default - try fileManager.createDirectory(at: targetURL, withIntermediateDirectories: true, attributes: nil) - - defer { try? fileManager.removeItem(at: targetURL) } + let targetURL = try createTemporaryDirectory() - let templateURL = URL(fileURLWithPath: NSTemporaryDirectory()).appendingPathComponent(UUID().uuidString) + let templateURL = try createTemporaryDirectory().appendingPathComponent("template") try Folder.emptyHTMLTemplateDirectory.write(to: templateURL) - defer { try? fileManager.removeItem(at: templateURL) } let targetBundleURL = targetURL.appendingPathComponent("Result.doccarchive") - defer { try? fileManager.removeItem(at: targetBundleURL) } var action = try ConvertAction( documentationBundleURL: bundleURL, @@ -41,28 +34,27 @@ class TransformForStaticHostingActionTests: StaticHostingBaseTests { targetDirectory: targetBundleURL, htmlTemplateDirectory: templateURL, emitDigest: false, - currentPlatforms: nil + currentPlatforms: nil, + temporaryDirectory: try createTemporaryDirectory() ) _ = try action.perform(logHandle: .standardOutput) - let outputURL = URL(fileURLWithPath: NSTemporaryDirectory()).appendingPathComponent(UUID().uuidString) - defer { try? fileManager.removeItem(at: outputURL) } + let outputURL = try createTemporaryDirectory()//.appendingPathComponent("output") let basePath = "test/folder" - let testTemplateURL = URL(fileURLWithPath: NSTemporaryDirectory()).appendingPathComponent(UUID().uuidString) + let testTemplateURL = try createTemporaryDirectory().appendingPathComponent("testTemplate") let templateFolder = Folder.testHTMLTemplateDirectory try templateFolder.write(to: testTemplateURL) let indexHTML = Folder.testHTMLTemplate(basePath: basePath) - defer { try? fileManager.removeItem(at: testTemplateURL) } - var transformAction = try TransformForStaticHostingAction(documentationBundleURL: targetBundleURL, outputURL: outputURL, hostingBasePath: basePath, htmlTemplateDirectory: testTemplateURL) _ = try transformAction.perform(logHandle: .standardOutput) + let fileManager = FileManager.default var isDirectory: ObjCBool = false // Test an output folder exists @@ -109,15 +101,14 @@ class TransformForStaticHostingActionTests: StaticHostingBaseTests { // Convert a test bundle as input for the TransformForStaticHostingAction let bundleURL = Bundle.module.url(forResource: "TestBundle", withExtension: "docc", subdirectory: "Test Bundles")! - let targetURL = URL(fileURLWithPath: NSTemporaryDirectory()).appendingPathComponent(UUID().uuidString) + let targetURL = try createTemporaryDirectory() let fileManager = FileManager.default try fileManager.createDirectory(at: targetURL, withIntermediateDirectories: true, attributes: nil) defer { try? fileManager.removeItem(at: targetURL) } - let templateURL = URL(fileURLWithPath: NSTemporaryDirectory()).appendingPathComponent(UUID().uuidString) + let templateURL = try createTemporaryDirectory().appendingPathComponent("template") try Folder.emptyHTMLTemplateDirectory.write(to: templateURL) - defer { try? fileManager.removeItem(at: templateURL) } let targetBundleURL = targetURL.appendingPathComponent("Result.doccarchive") @@ -128,21 +119,20 @@ class TransformForStaticHostingActionTests: StaticHostingBaseTests { targetDirectory: targetBundleURL, htmlTemplateDirectory: templateURL, emitDigest: false, - currentPlatforms: nil + currentPlatforms: nil, + temporaryDirectory: try createTemporaryDirectory() ) _ = try action.perform(logHandle: .standardOutput) let basePath = "test/folder" - let testTemplateURL = URL(fileURLWithPath: NSTemporaryDirectory()).appendingPathComponent(UUID().uuidString) + let testTemplateURL = try createTemporaryDirectory().appendingPathComponent("testTemplate") let templateFolder = Folder.testHTMLTemplateDirectory try templateFolder.write(to: testTemplateURL) let indexHTML = Folder.testHTMLTemplate(basePath: basePath) var expectedContent = try fileManager.contentsOfDirectory(atPath: targetBundleURL.path) - - defer { try? fileManager.removeItem(at: testTemplateURL) } var transformAction = try TransformForStaticHostingAction(documentationBundleURL: targetBundleURL, outputURL: nil, hostingBasePath: basePath, htmlTemplateDirectory: testTemplateURL) From 0240e3930b13b415638523989bd4091a763b6214 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Ro=CC=88nnqvist?= Date: Mon, 13 Dec 2021 12:18:33 -0800 Subject: [PATCH 06/16] Remove `createDirectoryForLastPathComponent` argument in test helper --- .../XCTestCase+TemporaryDirectory.swift | 11 ++--------- .../DocumentationContext+RootPageTests.swift | 4 ++-- .../Infrastructure/DocumentationContextTests.swift | 8 ++++---- .../Infrastructure/DocumentationCuratorTests.swift | 2 +- .../ExternalReferenceResolverTests.swift | 2 +- .../SwiftDocCTests/Infrastructure/NodeTagsTests.swift | 2 +- .../SwiftDocCTests/Model/SemaToRenderNodeTests.swift | 2 +- Tests/SwiftDocCTests/Rendering/PlistSymbolTests.swift | 4 ++-- Tests/SwiftDocCTests/XCTestCase+LoadingTestData.swift | 4 +++- .../SwiftDocCUtilitiesTests/ConvertActionTests.swift | 2 +- Tests/SwiftDocCUtilitiesTests/IndexActionTests.swift | 2 +- .../PreviewActionIntegrationTests.swift | 4 ++-- .../PreviewServer/PreviewHTTPHandlerTests.swift | 4 ++-- .../PreviewServer/PreviewServerTests.swift | 4 ++-- .../RequestHandler/DefaultRequestHandlerTests.swift | 4 ++-- .../RequestHandler/FileRequestHandlerTests.swift | 10 +++++----- Tests/SwiftDocCUtilitiesTests/TempFolderTests.swift | 6 +++--- 17 files changed, 35 insertions(+), 40 deletions(-) diff --git a/Sources/SwiftDocCTestUtilities/XCTestCase+TemporaryDirectory.swift b/Sources/SwiftDocCTestUtilities/XCTestCase+TemporaryDirectory.swift index 81856db7c1..e2072c6d3d 100644 --- a/Sources/SwiftDocCTestUtilities/XCTestCase+TemporaryDirectory.swift +++ b/Sources/SwiftDocCTestUtilities/XCTestCase+TemporaryDirectory.swift @@ -26,14 +26,9 @@ public extension XCTestCase { /// /// - Parameters: /// - pathComponents: Additional path components to add to the temporary URL. - /// - createDirectoryForLastPathComponent: If the file manager should create a directory for the last path component or not. Defaults to `true`. /// - fileManager: The file manager that will create the directory. /// - Returns: The URL of the newly created directory. - func createTemporaryDirectory( - pathComponents: String..., - createDirectoryForLastPathComponent: Bool = true, - fileManager: FileManager = .default - ) throws -> URL { + func createTemporaryDirectory(pathComponents: String..., fileManager: FileManager = .default) throws -> URL { let bundleParentDir = Bundle(for: Self.self).bundleURL.deletingLastPathComponent() let baseURL = bundleParentDir.appendingPathComponent(name.replacingWhitespaceAndPunctuation(with: "-")) @@ -46,9 +41,7 @@ public extension XCTestCase { addTeardownBlock { try? fileManager.removeItem(at: baseURL) } - - let urlToCreate = createDirectoryForLastPathComponent ? tempURL : tempURL.deletingLastPathComponent() - try fileManager.createDirectory(at: urlToCreate, withIntermediateDirectories: true, attributes: nil) + try fileManager.createDirectory(at: tempURL, withIntermediateDirectories: true, attributes: nil) return tempURL } diff --git a/Tests/SwiftDocCTests/Infrastructure/DocumentationContext+RootPageTests.swift b/Tests/SwiftDocCTests/Infrastructure/DocumentationContext+RootPageTests.swift index c446301b0c..f0ce030f58 100644 --- a/Tests/SwiftDocCTests/Infrastructure/DocumentationContext+RootPageTests.swift +++ b/Tests/SwiftDocCTests/Infrastructure/DocumentationContext+RootPageTests.swift @@ -36,7 +36,7 @@ class DocumentationContext_RootPageTests: XCTestCase { """), InfoPlist(displayName: "TestBundle", identifier: "com.test.example"), ]), - ], atRoot: createTemporaryDirectory(createDirectoryForLastPathComponent: false)) + ], atRoot: createTemporaryDirectory().appendingPathComponent("tempFolder")) // Parse this test content let workspace = DocumentationWorkspace() @@ -78,7 +78,7 @@ class DocumentationContext_RootPageTests: XCTestCase { """), InfoPlist(displayName: "TestBundle", identifier: "com.test.example"), ]), - ], atRoot: createTemporaryDirectory(createDirectoryForLastPathComponent: false)) + ], atRoot: createTemporaryDirectory().appendingPathComponent("tempFolder")) // Parse this test content let workspace = DocumentationWorkspace() diff --git a/Tests/SwiftDocCTests/Infrastructure/DocumentationContextTests.swift b/Tests/SwiftDocCTests/Infrastructure/DocumentationContextTests.swift index 82615c0b1e..18c626b198 100644 --- a/Tests/SwiftDocCTests/Infrastructure/DocumentationContextTests.swift +++ b/Tests/SwiftDocCTests/Infrastructure/DocumentationContextTests.swift @@ -2617,7 +2617,7 @@ let expected = """ TextFile(name: "TestTechnology.tutorial", utf8Content: testTechnologySource), TextFile(name: "Test.tutorial", utf8Content: testTutorialSource), ]) - let tempFolderURL = try createTemporaryDirectory(pathComponents: "test.docc", createDirectoryForLastPathComponent: false) + let tempFolderURL = try createTemporaryDirectory().appendingPathComponent("test.docc") try testBundle.write(to: tempFolderURL) // Load the bundle @@ -2654,7 +2654,7 @@ let expected = """ TextFile(name: "TestTechnology.tutorial", utf8Content: testTechnologySource), TextFile(name: "Test.tutorial", utf8Content: testTutorialSource), ]) - let tempFolderURL = try createTemporaryDirectory(pathComponents: "test.docc", createDirectoryForLastPathComponent: false) + let tempFolderURL = try createTemporaryDirectory().appendingPathComponent("test.docc") try testBundle.write(to: tempFolderURL) // Load the bundle @@ -2714,7 +2714,7 @@ let expected = """ TextFile(name: "TestTechnology.tutorial", utf8Content: testTechnologySource), TextFile(name: "Test.tutorial", utf8Content: testTutorialSource), ]) - let tempFolderURL = try createTemporaryDirectory(pathComponents: "test.docc", createDirectoryForLastPathComponent: false) + let tempFolderURL = try createTemporaryDirectory().appendingPathComponent("test.docc") try testBundle.write(to: tempFolderURL) // Load the bundle @@ -2784,7 +2784,7 @@ let expected = """ CopyOfFile(original: infoPlistURL, newName: "Info.plist"), TextFile(name: "TestFramework.symbols.json", utf8Content: symbolGraphFixture), ]) - let tempFolderURL = try createTemporaryDirectory(pathComponents: "test.docc", createDirectoryForLastPathComponent: false) + let tempFolderURL = try createTemporaryDirectory().appendingPathComponent("test.docc") try testBundle.write(to: tempFolderURL) // Load the bundle diff --git a/Tests/SwiftDocCTests/Infrastructure/DocumentationCuratorTests.swift b/Tests/SwiftDocCTests/Infrastructure/DocumentationCuratorTests.swift index 38bfe1a3f4..05b4da68bd 100644 --- a/Tests/SwiftDocCTests/Infrastructure/DocumentationCuratorTests.swift +++ b/Tests/SwiftDocCTests/Infrastructure/DocumentationCuratorTests.swift @@ -81,7 +81,7 @@ class DocumentationCuratorTests: XCTestCase { let workspace = DocumentationWorkspace() let context = try DocumentationContext(dataProvider: workspace) - let tempURL = try createTemporaryDirectory(pathComponents: "unit-test.docc", createDirectoryForLastPathComponent: false) + let tempURL = try createTemporaryDirectory().appendingPathComponent("unit-test.docc") let testBundleURL = Bundle.module.url( forResource: "TestBundle", withExtension: "docc", subdirectory: "Test Bundles")! diff --git a/Tests/SwiftDocCTests/Infrastructure/ExternalReferenceResolverTests.swift b/Tests/SwiftDocCTests/Infrastructure/ExternalReferenceResolverTests.swift index 40f44e5c15..554c224176 100644 --- a/Tests/SwiftDocCTests/Infrastructure/ExternalReferenceResolverTests.swift +++ b/Tests/SwiftDocCTests/Infrastructure/ExternalReferenceResolverTests.swift @@ -101,7 +101,7 @@ class ExternalReferenceResolverTests: XCTestCase { forResource: "TestBundle", withExtension: "docc", subdirectory: "Test Bundles")! // Create a copy of the test bundle - let bundleURL = try createTemporaryDirectory(pathComponents: "test.docc", createDirectoryForLastPathComponent: false) + let bundleURL = try createTemporaryDirectory().appendingPathComponent("test.docc") try FileManager.default.copyItem(at: sourceURL, to: bundleURL) // Add external link diff --git a/Tests/SwiftDocCTests/Infrastructure/NodeTagsTests.swift b/Tests/SwiftDocCTests/Infrastructure/NodeTagsTests.swift index a359495e0d..9dbece26a5 100644 --- a/Tests/SwiftDocCTests/Infrastructure/NodeTagsTests.swift +++ b/Tests/SwiftDocCTests/Infrastructure/NodeTagsTests.swift @@ -20,7 +20,7 @@ class NodeTagsTests: XCTestCase { InfoPlist(displayName: "spi", identifier: "com.tests.spi"), CopyOfFile(original: spiSGURL), ]) - let tempURL = try createTemporaryDirectory(pathComponents: "unit-tests.docc", createDirectoryForLastPathComponent: false) + let tempURL = try createTemporaryDirectory().appendingPathComponent("unit-tests.docc") try bundleFolder.write(to: tempURL) let (_, bundle, context) = try loadBundle(from: tempURL) diff --git a/Tests/SwiftDocCTests/Model/SemaToRenderNodeTests.swift b/Tests/SwiftDocCTests/Model/SemaToRenderNodeTests.swift index 7b188658cc..ce9ad2561f 100644 --- a/Tests/SwiftDocCTests/Model/SemaToRenderNodeTests.swift +++ b/Tests/SwiftDocCTests/Model/SemaToRenderNodeTests.swift @@ -1796,7 +1796,7 @@ Document @1:1-11:19 // Overwrite the article so we can test the article eyebrow for articles without task groups let sourceURL = Bundle.module.url( forResource: "TestBundle", withExtension: "docc", subdirectory: "Test Bundles")! - let targetURL = try createTemporaryDirectory(pathComponents: "test.docc", createDirectoryForLastPathComponent: false) + let targetURL = try createTemporaryDirectory().appendingPathComponent("test.docc") try FileManager.default.copyItem(at: sourceURL, to: targetURL) diff --git a/Tests/SwiftDocCTests/Rendering/PlistSymbolTests.swift b/Tests/SwiftDocCTests/Rendering/PlistSymbolTests.swift index a96e279d2e..963e55e25e 100644 --- a/Tests/SwiftDocCTests/Rendering/PlistSymbolTests.swift +++ b/Tests/SwiftDocCTests/Rendering/PlistSymbolTests.swift @@ -129,7 +129,7 @@ class PlistSymbolTests: XCTestCase { let tempDir = try TempFolder(content: [ TextFile(name: "missingIdeTitle.json", utf8Content: modifiedJSON), - ], atRoot: createTemporaryDirectory(createDirectoryForLastPathComponent: false)) + ], atRoot: createTemporaryDirectory().appendingPathComponent("tempFolder")) let symbol = try RenderNode.decode(fromJSON: try Data(contentsOf: tempDir.url.appendingPathComponent("missingIdeTitle.json"))) // @@ -155,7 +155,7 @@ class PlistSymbolTests: XCTestCase { let tempDir = try TempFolder(content: [ TextFile(name: "missingPossibleValuesTitle.json", utf8Content: modifiedJSON), - ], atRoot: createTemporaryDirectory(createDirectoryForLastPathComponent: false)) + ], atRoot: createTemporaryDirectory().appendingPathComponent("tempFolder")) let symbol = try RenderNode.decode(fromJSON: try Data(contentsOf: tempDir.url.appendingPathComponent("missingPossibleValuesTitle.json"))) // diff --git a/Tests/SwiftDocCTests/XCTestCase+LoadingTestData.swift b/Tests/SwiftDocCTests/XCTestCase+LoadingTestData.swift index 84ebf6fd4f..737d7b4f5d 100644 --- a/Tests/SwiftDocCTests/XCTestCase+LoadingTestData.swift +++ b/Tests/SwiftDocCTests/XCTestCase+LoadingTestData.swift @@ -37,7 +37,9 @@ extension XCTestCase { forResource: name, withExtension: "docc", subdirectory: "Test Bundles")! let sourceExists = FileManager.default.fileExists(atPath: sourceURL.path) - let bundleURL = try createTemporaryDirectory(pathComponents: "\(name).docc", createDirectoryForLastPathComponent: !sourceExists) + let bundleURL = sourceExists + ? try createTemporaryDirectory().appendingPathComponent("\(name).docc") + : try createTemporaryDirectory(pathComponents: "\(name).docc") if sourceExists { try FileManager.default.copyItem(at: sourceURL, to: bundleURL) diff --git a/Tests/SwiftDocCUtilitiesTests/ConvertActionTests.swift b/Tests/SwiftDocCUtilitiesTests/ConvertActionTests.swift index 7734feadde..72e6553f7a 100644 --- a/Tests/SwiftDocCUtilitiesTests/ConvertActionTests.swift +++ b/Tests/SwiftDocCUtilitiesTests/ConvertActionTests.swift @@ -1790,7 +1790,7 @@ class ConvertActionTests: XCTestCase { let bundleURL = Bundle.module.url(forResource: "TestBundle", withExtension: "docc", subdirectory: "Test Bundles")! let targetURL = try createTemporaryDirectory() - let templateURL = try createTemporaryDirectory(createDirectoryForLastPathComponent: false) + let templateURL = try createTemporaryDirectory().appendingPathComponent("template") try Folder.emptyHTMLTemplateDirectory.write(to: templateURL) // Convert the documentation and create an index diff --git a/Tests/SwiftDocCUtilitiesTests/IndexActionTests.swift b/Tests/SwiftDocCUtilitiesTests/IndexActionTests.swift index bb5d9e2529..5af4d7c07f 100644 --- a/Tests/SwiftDocCUtilitiesTests/IndexActionTests.swift +++ b/Tests/SwiftDocCUtilitiesTests/IndexActionTests.swift @@ -22,7 +22,7 @@ class IndexActionTests: XCTestCase { let bundleURL = Bundle.module.url(forResource: "TestBundle", withExtension: "docc", subdirectory: "Test Bundles")! let targetURL = try createTemporaryDirectory() - let templateURL = try createTemporaryDirectory(createDirectoryForLastPathComponent: false) + let templateURL = try createTemporaryDirectory().appendingPathComponent("template") try Folder.emptyHTMLTemplateDirectory.write(to: templateURL) let targetBundleURL = targetURL.appendingPathComponent("Result.builtdocs") diff --git a/Tests/SwiftDocCUtilitiesTests/PreviewActionIntegrationTests.swift b/Tests/SwiftDocCUtilitiesTests/PreviewActionIntegrationTests.swift index 8385279cc1..0fd299faac 100644 --- a/Tests/SwiftDocCUtilitiesTests/PreviewActionIntegrationTests.swift +++ b/Tests/SwiftDocCUtilitiesTests/PreviewActionIntegrationTests.swift @@ -110,7 +110,7 @@ class PreviewActionIntegrationTests: XCTestCase { return } - let socketURL = try createTemporaryDirectory(pathComponents: "sock", createDirectoryForLastPathComponent: false) + let socketURL = try createTemporaryDirectory().appendingPathComponent("sock") preview.bindServerToSocketPath = socketURL.path // The technology output file URL @@ -466,7 +466,7 @@ class PreviewActionIntegrationTests: XCTestCase { return } - let socketURL = try createTemporaryDirectory(pathComponents: "sock", createDirectoryForLastPathComponent: false) + let socketURL = try createTemporaryDirectory().appendingPathComponent("sock") preview.bindServerToSocketPath = socketURL.path // Start watching the source and get the initial (successful) state. diff --git a/Tests/SwiftDocCUtilitiesTests/PreviewServer/PreviewHTTPHandlerTests.swift b/Tests/SwiftDocCUtilitiesTests/PreviewServer/PreviewHTTPHandlerTests.swift index edda259ad5..fe58bed7a1 100644 --- a/Tests/SwiftDocCUtilitiesTests/PreviewServer/PreviewHTTPHandlerTests.swift +++ b/Tests/SwiftDocCUtilitiesTests/PreviewServer/PreviewHTTPHandlerTests.swift @@ -26,7 +26,7 @@ class PreviewHTTPHandlerTests: XCTestCase { Folder(name: "css", content: [ TextFile(name: "test.css", utf8Content: "css"), ]) - ], atRoot: createTemporaryDirectory(createDirectoryForLastPathComponent: false)) + ], atRoot: createTemporaryDirectory().appendingPathComponent("tempFolder")) let channel = EmbeddedChannel() let channelHandler = PreviewHTTPHandler(fileIO: fileIO, rootURL: tempDir.url) @@ -87,7 +87,7 @@ class PreviewHTTPHandlerTests: XCTestCase { Folder(name: "css", content: [ TextFile(name: "test.css", utf8Content: "css"), ]) - ], atRoot: createTemporaryDirectory(createDirectoryForLastPathComponent: false)) + ], atRoot: createTemporaryDirectory().appendingPathComponent("tempFolder")) let channel = EmbeddedChannel() defer { diff --git a/Tests/SwiftDocCUtilitiesTests/PreviewServer/PreviewServerTests.swift b/Tests/SwiftDocCUtilitiesTests/PreviewServer/PreviewServerTests.swift index 9b51df2781..3295a1076a 100644 --- a/Tests/SwiftDocCUtilitiesTests/PreviewServer/PreviewServerTests.swift +++ b/Tests/SwiftDocCUtilitiesTests/PreviewServer/PreviewServerTests.swift @@ -37,7 +37,7 @@ class PreviewServerTests { // Create test content let tempFolder = try TempFolder(content: [ TextFile(name: "index.html", utf8Content: "index"), - ], atRoot: createTemporaryDirectory(createDirectoryForLastPathComponent: false)) + ], atRoot: createTemporaryDirectory().appendingPathComponent("tempFolder")) let socketURL = try createTemporaryDirectory(pathComponents: "sock", createDirectoryForLastPathComponent: false) @@ -112,7 +112,7 @@ class PreviewServerTests { Folder(name: "downloads", content: [ TextFile(name: "test.zip", utf8Content: "downloads content"), ]) - ], atRoot: createTemporaryDirectory(createDirectoryForLastPathComponent: false)) + ], atRoot: createTemporaryDirectory().appendingPathComponent("tempFolder")) } func testPreviewServerPaths() throws { diff --git a/Tests/SwiftDocCUtilitiesTests/PreviewServer/RequestHandler/DefaultRequestHandlerTests.swift b/Tests/SwiftDocCUtilitiesTests/PreviewServer/RequestHandler/DefaultRequestHandlerTests.swift index bbae20b71d..e7bf839a3c 100644 --- a/Tests/SwiftDocCUtilitiesTests/PreviewServer/RequestHandler/DefaultRequestHandlerTests.swift +++ b/Tests/SwiftDocCUtilitiesTests/PreviewServer/RequestHandler/DefaultRequestHandlerTests.swift @@ -21,7 +21,7 @@ class DefaultRequestHandlerTests: XCTestCase { func testDefaultHandler() throws { let tempDir = try TempFolder(content: [ TextFile(name: "index.html", utf8Content: "Hello!"), - ], atRoot: createTemporaryDirectory(createDirectoryForLastPathComponent: false)) + ], atRoot: createTemporaryDirectory().appendingPathComponent("tempFolder")) // Default handler should be invoked for any non-asset path let request = makeRequestHead(path: "/random-path") @@ -44,7 +44,7 @@ class DefaultRequestHandlerTests: XCTestCase { let tempDir = try TempFolder(content: [ TextFile(name: "index.html", utf8Content: "Hello!"), TextFile(name: "existing.html", utf8Content: "Existing!"), - ], atRoot: createTemporaryDirectory(createDirectoryForLastPathComponent: false)) + ], atRoot: createTemporaryDirectory().appendingPathComponent("tempFolder")) // Default handler should handle even paths that do exist on disc let request = makeRequestHead(path: "/existing.html") diff --git a/Tests/SwiftDocCUtilitiesTests/PreviewServer/RequestHandler/FileRequestHandlerTests.swift b/Tests/SwiftDocCUtilitiesTests/PreviewServer/RequestHandler/FileRequestHandlerTests.swift index 0c826823e2..cb89daff6d 100644 --- a/Tests/SwiftDocCUtilitiesTests/PreviewServer/RequestHandler/FileRequestHandlerTests.swift +++ b/Tests/SwiftDocCUtilitiesTests/PreviewServer/RequestHandler/FileRequestHandlerTests.swift @@ -64,7 +64,7 @@ class FileRequestHandlerTests: XCTestCase { Folder(name: "downloads", content: [ TextFile(name: "project.zip", utf8Content: "zip"), ]) - ], atRoot: createTemporaryDirectory(createDirectoryForLastPathComponent: false)) + ], atRoot: createTemporaryDirectory().appendingPathComponent("tempFolder")) try verifyAsset(root: tempDir.url, path: "/data/test.json", body: "data", type: "application/json") try verifyAsset(root: tempDir.url, path: "/css/test.css", body: "css", type: "text/css") @@ -87,7 +87,7 @@ class FileRequestHandlerTests: XCTestCase { } func testFileHandlerAssetsMissing() throws { - let tempDir = try TempFolder(content: [], atRoot: createTemporaryDirectory(createDirectoryForLastPathComponent: false)) + let tempDir = try TempFolder(content: [], atRoot: createTemporaryDirectory().appendingPathComponent("tempFolder")) let request = makeRequestHead(path: "/css/b00011100.css") let factory = FileRequestHandler(rootURL: tempDir.url, fileIO: fileIO) @@ -101,7 +101,7 @@ class FileRequestHandlerTests: XCTestCase { Folder(name: "videos", content: [ TextFile(name: "video.mov", utf8Content: "Hello!"), ]) - ], atRoot: createTemporaryDirectory(createDirectoryForLastPathComponent: false)) + ], atRoot: createTemporaryDirectory().appendingPathComponent("tempFolder")) let request = makeRequestHead(path: "/videos/video.mov", headers: [("Range", "bytes=0-1")]) let factory = FileRequestHandler(rootURL: tempDir.url, fileIO: fileIO) @@ -120,7 +120,7 @@ class FileRequestHandlerTests: XCTestCase { Folder(name: "videos", content: [ TextFile(name: "video.mov", utf8Content: "Hello!"), ]) - ], atRoot: createTemporaryDirectory(createDirectoryForLastPathComponent: false)) + ], atRoot: createTemporaryDirectory().appendingPathComponent("tempFolder")) let request = makeRequestHead(path: "/videos/../video.mov", headers: [("Range", "bytes=0-1")]) let factory = FileRequestHandler(rootURL: tempDir.url, fileIO: fileIO) @@ -135,7 +135,7 @@ class FileRequestHandlerTests: XCTestCase { Folder(name: "videos", content: [ TextFile(name: "video.mov", utf8Content: "Hello!"), ]) - ], atRoot: createTemporaryDirectory(createDirectoryForLastPathComponent: false)) + ], atRoot: createTemporaryDirectory().appendingPathComponent("tempFolder")) let request = makeRequestHead(path: "/videos/. ? ? ? ./video.mov", headers: [("Range", "bytes=0-1")]) let factory = FileRequestHandler(rootURL: tempDir.url, fileIO: fileIO) diff --git a/Tests/SwiftDocCUtilitiesTests/TempFolderTests.swift b/Tests/SwiftDocCUtilitiesTests/TempFolderTests.swift index 8d671c7d09..c22d5aa262 100644 --- a/Tests/SwiftDocCUtilitiesTests/TempFolderTests.swift +++ b/Tests/SwiftDocCUtilitiesTests/TempFolderTests.swift @@ -17,7 +17,7 @@ class TempFolderTests: XCTestCase { func testCreatesAndDeletesTempFolder() throws { var tempFolder: TempFolder! = try TempFolder(content: [ TextFile(name: "index.html", utf8Content: "index"), - ], atRoot: createTemporaryDirectory(createDirectoryForLastPathComponent: false)) + ], atRoot: createTemporaryDirectory().appendingPathComponent("tempFolder")) // Check the folder is created and the file inside exists. XCTAssertTrue(FileManager.default.directoryExists(atPath: tempFolder.url.path)) @@ -36,8 +36,8 @@ class TempFolderTests: XCTestCase { } func testCreatesRandomPaths() throws { - let tempFolder1 = try TempFolder(content: [], atRoot: createTemporaryDirectory(createDirectoryForLastPathComponent: false)) - let tempFolder2 = try TempFolder(content: [], atRoot: createTemporaryDirectory(createDirectoryForLastPathComponent: false)) + let tempFolder1 = try TempFolder(content: [], atRoot: createTemporaryDirectory().appendingPathComponent("tempFolder")) + let tempFolder2 = try TempFolder(content: [], atRoot: createTemporaryDirectory().appendingPathComponent("tempFolder")) XCTAssertNotEqual(tempFolder1.url, tempFolder2.url) } From af38caac29891839796f087427f3217d470e7ef2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Ro=CC=88nnqvist?= Date: Mon, 13 Dec 2021 12:25:48 -0800 Subject: [PATCH 07/16] Update test helper documentation --- .../SwiftDocCTestUtilities/XCTestCase+TemporaryDirectory.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Sources/SwiftDocCTestUtilities/XCTestCase+TemporaryDirectory.swift b/Sources/SwiftDocCTestUtilities/XCTestCase+TemporaryDirectory.swift index e2072c6d3d..f35604136a 100644 --- a/Sources/SwiftDocCTestUtilities/XCTestCase+TemporaryDirectory.swift +++ b/Sources/SwiftDocCTestUtilities/XCTestCase+TemporaryDirectory.swift @@ -22,7 +22,7 @@ public extension XCTestCase { /// Creates a new temporary directory and returns the URL of that directory. /// - /// At the end of the test the temporary directory is automatically removed. + /// After the current test method has returned the temporary directory is automatically removed. /// /// - Parameters: /// - pathComponents: Additional path components to add to the temporary URL. From 8c614df91223b0493318e96c46f7d99fe13c3064 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Ro=CC=88nnqvist?= Date: Mon, 13 Dec 2021 12:26:12 -0800 Subject: [PATCH 08/16] Prefer `FileManager.temporaryDirectory` property in ConvertAction --- .../ActionExtensions/ConvertAction+CommandInitialization.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Sources/SwiftDocCUtilities/ArgumentParsing/ActionExtensions/ConvertAction+CommandInitialization.swift b/Sources/SwiftDocCUtilities/ArgumentParsing/ActionExtensions/ConvertAction+CommandInitialization.swift index c6024d64d6..4b918e0089 100644 --- a/Sources/SwiftDocCUtilities/ArgumentParsing/ActionExtensions/ConvertAction+CommandInitialization.swift +++ b/Sources/SwiftDocCUtilities/ArgumentParsing/ActionExtensions/ConvertAction+CommandInitialization.swift @@ -72,7 +72,7 @@ extension ConvertAction { emitDigest: convert.emitDigest, currentPlatforms: parsedPlatforms, buildIndex: convert.index, - temporaryDirectory: URL(fileURLWithPath: NSTemporaryDirectory()), + temporaryDirectory: FileManager.default.temporaryDirectory, documentationCoverageOptions: DocumentationCoverageOptions( from: convert.experimentalDocumentationCoverageOptions ), From 5d4ce3e41fe1a5dae63dcf1e02e163297b72e15f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Ro=CC=88nnqvist?= Date: Tue, 21 Dec 2021 15:29:52 -0800 Subject: [PATCH 09/16] Move `Files` and `Folder` types into test utility target --- .../FilesAndFolders.swift} | 116 ++++++++++-------- .../Infrastructure/BundleDiscoveryTests.swift | 1 + .../DocumentationContext+RootPageTests.swift | 1 + .../DocumentationContextTests.swift | 1 + .../Infrastructure/NodeTagsTests.swift | 1 + .../LinkDestinationSummaryTests.swift | 1 + .../Semantics/SymbolTests.swift | 1 + .../ConvertActionStaticHostableTests.swift | 1 + .../ConvertActionTests.swift | 4 +- .../FolderStructure.swift | 9 +- .../FolderStructureTests.swift | 1 + .../HTMLTemplateDirectory.swift | 1 + .../PreviewActionIntegrationTests.swift | 1 + .../PreviewHTTPHandlerTests.swift | 1 + .../PreviewServer/PreviewServerTests.swift | 1 + .../DefaultRequestHandlerTests.swift | 1 + .../SemanticAnalyzerTests.swift | 1 + .../StaticHostableTransformerTests.swift | 1 + ...TransformForStaticHostingActionTests.swift | 1 + .../Utility/FileTests.swift | 1 + .../Utility/TestFileSystem.swift | 1 + .../Utility/TestFileSystemTests.swift | 1 + 22 files changed, 92 insertions(+), 56 deletions(-) rename Sources/{SwiftDocC/Utility/DataStructures/File.swift => SwiftDocCTestUtilities/FilesAndFolders.swift} (70%) diff --git a/Sources/SwiftDocC/Utility/DataStructures/File.swift b/Sources/SwiftDocCTestUtilities/FilesAndFolders.swift similarity index 70% rename from Sources/SwiftDocC/Utility/DataStructures/File.swift rename to Sources/SwiftDocCTestUtilities/FilesAndFolders.swift index 5feb4c15ac..ccc780e307 100644 --- a/Sources/SwiftDocC/Utility/DataStructures/File.swift +++ b/Sources/SwiftDocCTestUtilities/FilesAndFolders.swift @@ -16,7 +16,7 @@ import Foundation */ /// An abstract representation of a file (or folder). -protocol File { +public protocol File { /// The name of the file. var name: String { get } @@ -24,7 +24,7 @@ protocol File { func write(to url: URL) throws } -extension File { +public extension File { /// Writes the file inside of a folder and returns the URL that it was written to. @discardableResult func write(inside url: URL) throws -> URL { @@ -35,12 +35,12 @@ extension File { } /// An item which provides data. -protocol DataRepresentable { +public protocol DataRepresentable { func data() throws -> Data } /// `DataRepresentable` can automatically write itself to disk via `Data.write(to:)` -extension DataRepresentable { +public extension DataRepresentable { func write(to url: URL) throws { try data().write(to: url) } @@ -49,17 +49,22 @@ extension DataRepresentable { // MARK: - /// An abstract representation of a folder, containing some files or folders. -struct Folder: File { - let name: String +public struct Folder: File { + public init(name: String, content: [File]) { + self.name = name + self.content = content + } + + public let name: String /// The files and sub folders that this folder contains. - let content: [File] + public let content: [File] - func appendingFile(_ newFile: File) -> Folder { + public func appendingFile(_ newFile: File) -> Folder { return Folder(name: name, content: content + [newFile]) } - func write(to url: URL) throws { + public func write(to url: URL) throws { try FileManager.default.createDirectory(at: url, withIntermediateDirectories: false, attributes: nil) for file in content { try file.write(inside: url) @@ -69,7 +74,7 @@ struct Folder: File { extension Folder { /// Returns a flat list of a folder's recursive listing for testing purposes. - var recursiveContent: [File] { + public var recursiveContent: [File] { var result = content for file in content { if let content = (file as? Folder)?.recursiveContent { @@ -81,13 +86,13 @@ extension Folder { } /// A representation of an Info.plist file. -struct InfoPlist: File, DataRepresentable { - let name = "Info.plist" +public struct InfoPlist: File, DataRepresentable { + public let name = "Info.plist" /// The information that the Into.plist file contains. - let content: Content + public let content: Content - init(displayName: String, identifier: String, versionString: String = "1.0", developmentRegion: String = "en") { + public init(displayName: String, identifier: String, versionString: String = "1.0", developmentRegion: String = "en") { self.content = Content( displayName: displayName, identifier: identifier, @@ -96,11 +101,11 @@ struct InfoPlist: File, DataRepresentable { ) } - struct Content: Codable, Equatable { - let displayName: String - let identifier: String - let versionString: String - let developmentRegion: String + public struct Content: Codable, Equatable { + public let displayName: String + public let identifier: String + public let versionString: String + public let developmentRegion: String fileprivate init(displayName: String, identifier: String, versionString: String, developmentRegion: String) { self.displayName = displayName @@ -117,7 +122,7 @@ struct InfoPlist: File, DataRepresentable { } } - func data() throws -> Data { + public func data() throws -> Data { // TODO: Replace this with PropertListEncoder (see below) when it's available in swift-corelibs-foundation // https://github.com/apple/swift-corelibs-foundation/commit/d2d72f88d93f7645b94c21af88a7c9f69c979e4f let infoPlist = [ @@ -136,74 +141,85 @@ struct InfoPlist: File, DataRepresentable { } /// A representation of a text file with some UTF-8 content. -struct TextFile: File, DataRepresentable { - let name: String +public struct TextFile: File, DataRepresentable { + public init(name: String, utf8Content: String) { + self.name = name + self.utf8Content = utf8Content + } + + public let name: String /// The UTF8 content of the file. - let utf8Content: String + public let utf8Content: String - func data() throws -> Data { + public func data() throws -> Data { return utf8Content.data(using: .utf8)! } } /// A representation of a text file with some UTF-8 content. -struct JSONFile: File, DataRepresentable { - let name: String +public struct JSONFile: File, DataRepresentable { + public init(name: String, content: Content) { + self.name = name + self.content = content + } + + public let name: String /// The UTF8 content of the file. - let content: Content + public let content: Content - func data() throws -> Data { + public func data() throws -> Data { return try JSONEncoder().encode(content) } } /// A copy of another file on disk somewhere. -struct CopyOfFile: File, DataRepresentable { - enum Error: DescribedError { +public struct CopyOfFile: File, DataRepresentable { + enum Error: LocalizedError { case notAFile(URL) var errorDescription: String { switch self { - case .notAFile(let url): return "Original url is not a file: \(url.path.singleQuoted)" + case .notAFile(let url): return "Original url is not a file: '\(url.path)'" } } } /// The original file. - let original: URL - let name: String + public let original: URL + public let name: String - init(original: URL, newName: String? = nil) { + public init(original: URL, newName: String? = nil) { self.original = original self.name = newName ?? original.lastPathComponent } - func data() throws -> Data { + public func data() throws -> Data { // Note that `CopyOfFile` always reads a file from disk and so it's okay // to use `FileManager.default` directly here instead of `FileManagerProtocol`. - guard !FileManager.default.directoryExists(atPath: original.path) else { throw Error.notAFile(original) } + var isDirectory: ObjCBool = false + guard FileManager.default.fileExists(atPath: original.path, isDirectory: &isDirectory), !isDirectory.boolValue else { throw Error.notAFile(original) } return try Data(contentsOf: original) } - func write(to url: URL) throws { + public func write(to url: URL) throws { try FileManager.default.copyItem(at: original, to: url) } } -struct CopyOfFolder: File { +public struct CopyOfFolder: File { /// The original file. let original: URL - let name: String + public let name: String let shouldCopyFile: (URL) -> Bool - init(original: URL, newName: String? = nil, filter shouldCopyFile: @escaping (URL) -> Bool = { _ in true }) { + public init(original: URL, newName: String? = nil, filter shouldCopyFile: @escaping (URL) -> Bool = { _ in true }) { self.original = original self.name = newName ?? original.lastPathComponent self.shouldCopyFile = shouldCopyFile } - func write(to url: URL) throws { + public func write(to url: URL) throws { try FileManager.default.createDirectory(at: url, withIntermediateDirectories: false, attributes: nil) for filePath in try FileManager.default.contentsOfDirectory(atPath: original.path) { // `contentsOfDirectory(atPath)` includes hidden files, skipHiddenFiles option doesn't help on Linux. @@ -217,37 +233,37 @@ struct CopyOfFolder: File { } /// A file backed by `Data`. -struct DataFile: File, DataRepresentable { - var name: String +public struct DataFile: File, DataRepresentable { + public var name: String var _data: Data - init(name: String, data: Data) { + public init(name: String, data: Data) { self.name = name self._data = data } - func data() throws -> Data { + public func data() throws -> Data { return _data } } /// A temporary folder which can write files to a temporary location on disk and /// will delete itself when its instance is released from memory. -class TempFolder: File { - let name: String - let url: URL +public class TempFolder: File { + public let name: String + public let url: URL /// The files and sub folders that this folder contains. let content: [File] - func write(to url: URL) throws { + public func write(to url: URL) throws { try FileManager.default.createDirectory(at: url, withIntermediateDirectories: false, attributes: nil) for file in content { try file.write(inside: url) } } - init(content: [File], atRoot root: URL) throws { + public init(content: [File], atRoot root: URL) throws { self.content = content url = root diff --git a/Tests/SwiftDocCTests/Infrastructure/BundleDiscoveryTests.swift b/Tests/SwiftDocCTests/Infrastructure/BundleDiscoveryTests.swift index 7187c2b204..9520c59775 100644 --- a/Tests/SwiftDocCTests/Infrastructure/BundleDiscoveryTests.swift +++ b/Tests/SwiftDocCTests/Infrastructure/BundleDiscoveryTests.swift @@ -10,6 +10,7 @@ import XCTest @testable import SwiftDocC +import SwiftDocCTestUtilities class BundleDiscoveryTests: XCTestCase { diff --git a/Tests/SwiftDocCTests/Infrastructure/DocumentationContext+RootPageTests.swift b/Tests/SwiftDocCTests/Infrastructure/DocumentationContext+RootPageTests.swift index f0ce030f58..cd56809f43 100644 --- a/Tests/SwiftDocCTests/Infrastructure/DocumentationContext+RootPageTests.swift +++ b/Tests/SwiftDocCTests/Infrastructure/DocumentationContext+RootPageTests.swift @@ -11,6 +11,7 @@ import XCTest import SymbolKit @testable import SwiftDocC +import SwiftDocCTestUtilities class DocumentationContext_RootPageTests: XCTestCase { func testNoSGFBundle() throws { diff --git a/Tests/SwiftDocCTests/Infrastructure/DocumentationContextTests.swift b/Tests/SwiftDocCTests/Infrastructure/DocumentationContextTests.swift index 18c626b198..7db8eef0a0 100644 --- a/Tests/SwiftDocCTests/Infrastructure/DocumentationContextTests.swift +++ b/Tests/SwiftDocCTests/Infrastructure/DocumentationContextTests.swift @@ -12,6 +12,7 @@ import XCTest import SymbolKit @testable import SwiftDocC import Markdown +import SwiftDocCTestUtilities func diffDescription(lhs: String, rhs: String) -> String { let leftLines = lhs.components(separatedBy: .newlines) diff --git a/Tests/SwiftDocCTests/Infrastructure/NodeTagsTests.swift b/Tests/SwiftDocCTests/Infrastructure/NodeTagsTests.swift index 9dbece26a5..f2dcc9470a 100644 --- a/Tests/SwiftDocCTests/Infrastructure/NodeTagsTests.swift +++ b/Tests/SwiftDocCTests/Infrastructure/NodeTagsTests.swift @@ -10,6 +10,7 @@ import XCTest @testable import SwiftDocC +import SwiftDocCTestUtilities class NodeTagsTests: XCTestCase { func testSPIMetadata() throws { diff --git a/Tests/SwiftDocCTests/LinkTargets/LinkDestinationSummaryTests.swift b/Tests/SwiftDocCTests/LinkTargets/LinkDestinationSummaryTests.swift index 2f233cf257..d1158e8f50 100644 --- a/Tests/SwiftDocCTests/LinkTargets/LinkDestinationSummaryTests.swift +++ b/Tests/SwiftDocCTests/LinkTargets/LinkDestinationSummaryTests.swift @@ -10,6 +10,7 @@ import XCTest @testable import SwiftDocC +import SwiftDocCTestUtilities class ExternalLinkableTests: XCTestCase { diff --git a/Tests/SwiftDocCTests/Semantics/SymbolTests.swift b/Tests/SwiftDocCTests/Semantics/SymbolTests.swift index 8888ceca2d..95932d41a4 100644 --- a/Tests/SwiftDocCTests/Semantics/SymbolTests.swift +++ b/Tests/SwiftDocCTests/Semantics/SymbolTests.swift @@ -12,6 +12,7 @@ import XCTest @testable import SymbolKit @testable import SwiftDocC import Markdown +import SwiftDocCTestUtilities class SymbolTests: XCTestCase { diff --git a/Tests/SwiftDocCUtilitiesTests/ConvertActionStaticHostableTests.swift b/Tests/SwiftDocCUtilitiesTests/ConvertActionStaticHostableTests.swift index ffc8bf0474..96e0b4d48e 100644 --- a/Tests/SwiftDocCUtilitiesTests/ConvertActionStaticHostableTests.swift +++ b/Tests/SwiftDocCUtilitiesTests/ConvertActionStaticHostableTests.swift @@ -12,6 +12,7 @@ import XCTest import Foundation @testable import SwiftDocC @testable import SwiftDocCUtilities +import SwiftDocCTestUtilities class ConvertActionStaticHostableTests: StaticHostingBaseTests { /// Creates a DocC archive and then archives it with options to produce static content which is then validated. diff --git a/Tests/SwiftDocCUtilitiesTests/ConvertActionTests.swift b/Tests/SwiftDocCUtilitiesTests/ConvertActionTests.swift index 39fbdc02b2..a57a5e5133 100644 --- a/Tests/SwiftDocCUtilitiesTests/ConvertActionTests.swift +++ b/Tests/SwiftDocCUtilitiesTests/ConvertActionTests.swift @@ -2467,8 +2467,8 @@ extension Folder { if fileURL.lastPathComponent == "Info.plist", let infoPlistData = FileManager.default.contents(atPath: fileURL.path), let infoPlist = try? PropertyListSerialization.propertyList(from: infoPlistData, options: [], format: nil) as? [String: Any], - let displayName = infoPlist[InfoPlist.Content.CodingKeys.displayName.rawValue] as? String, - let identifier = infoPlist[InfoPlist.Content.CodingKeys.identifier.rawValue] as? String { + let displayName = infoPlist["CFBundleDisplayName"] as? String, + let identifier = infoPlist["CFBundleIdentifier"] as? String { content.append(InfoPlist(displayName: displayName, identifier: identifier)) } else { content.append(CopyOfFile(original: fileURL, newName: fileURL.lastPathComponent)) diff --git a/Tests/SwiftDocCUtilitiesTests/FolderStructure.swift b/Tests/SwiftDocCUtilitiesTests/FolderStructure.swift index e08b9dcab8..c408fbf751 100644 --- a/Tests/SwiftDocCUtilitiesTests/FolderStructure.swift +++ b/Tests/SwiftDocCUtilitiesTests/FolderStructure.swift @@ -11,6 +11,7 @@ @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: @@ -69,10 +70,10 @@ extension InfoPlist: AssertableFile { } let infoPlist = try PropertyListSerialization.propertyList(from: infoPlistData, options: [], format: nil) as? [String: String] - let displayName = infoPlist?[Content.CodingKeys.displayName.rawValue] - let identifier = infoPlist?[Content.CodingKeys.identifier.rawValue] - let versionString = infoPlist?[Content.CodingKeys.versionString.rawValue] - let developmentRegion = infoPlist?[Content.CodingKeys.developmentRegion.rawValue] + let displayName = infoPlist?["CFBundleIdentifier"] + let identifier = infoPlist?["CFBundleVersion"] + let versionString = infoPlist?["CFBundleDevelopmentRegion"] + let developmentRegion = infoPlist?["CFBundleDisplayName"] XCTAssert(displayName == content.displayName && identifier == content.identifier && versionString == content.versionString && developmentRegion == content.developmentRegion, "File '\(name)' should contain the correct information.", file: (file), line: line) diff --git a/Tests/SwiftDocCUtilitiesTests/FolderStructureTests.swift b/Tests/SwiftDocCUtilitiesTests/FolderStructureTests.swift index 04d61b32e0..8a9c6ad396 100644 --- a/Tests/SwiftDocCUtilitiesTests/FolderStructureTests.swift +++ b/Tests/SwiftDocCUtilitiesTests/FolderStructureTests.swift @@ -10,6 +10,7 @@ import XCTest @testable import SwiftDocC +import SwiftDocCTestUtilities class FolderStructureTests: XCTestCase { diff --git a/Tests/SwiftDocCUtilitiesTests/HTMLTemplateDirectory.swift b/Tests/SwiftDocCUtilitiesTests/HTMLTemplateDirectory.swift index 118eb13476..09ee4a1797 100644 --- a/Tests/SwiftDocCUtilitiesTests/HTMLTemplateDirectory.swift +++ b/Tests/SwiftDocCUtilitiesTests/HTMLTemplateDirectory.swift @@ -10,6 +10,7 @@ import Foundation @testable import SwiftDocC +import SwiftDocCTestUtilities /// A folder that represents a fake html-build directory for testing. extension Folder { diff --git a/Tests/SwiftDocCUtilitiesTests/PreviewActionIntegrationTests.swift b/Tests/SwiftDocCUtilitiesTests/PreviewActionIntegrationTests.swift index 0fd299faac..296b7a9c85 100644 --- a/Tests/SwiftDocCUtilitiesTests/PreviewActionIntegrationTests.swift +++ b/Tests/SwiftDocCUtilitiesTests/PreviewActionIntegrationTests.swift @@ -11,6 +11,7 @@ import XCTest @testable import SwiftDocC @testable import SwiftDocCUtilities +import SwiftDocCTestUtilities class PreviewActionIntegrationTests: XCTestCase { func json(contentsOf url: URL) throws -> [String: Any] { diff --git a/Tests/SwiftDocCUtilitiesTests/PreviewServer/PreviewHTTPHandlerTests.swift b/Tests/SwiftDocCUtilitiesTests/PreviewServer/PreviewHTTPHandlerTests.swift index fe58bed7a1..3347f0e217 100644 --- a/Tests/SwiftDocCUtilitiesTests/PreviewServer/PreviewHTTPHandlerTests.swift +++ b/Tests/SwiftDocCUtilitiesTests/PreviewServer/PreviewHTTPHandlerTests.swift @@ -12,6 +12,7 @@ import Foundation import XCTest @testable import SwiftDocC @testable import SwiftDocCUtilities +import SwiftDocCTestUtilities import NIO import NIOHTTP1 diff --git a/Tests/SwiftDocCUtilitiesTests/PreviewServer/PreviewServerTests.swift b/Tests/SwiftDocCUtilitiesTests/PreviewServer/PreviewServerTests.swift index 3295a1076a..f88758c0a0 100644 --- a/Tests/SwiftDocCUtilitiesTests/PreviewServer/PreviewServerTests.swift +++ b/Tests/SwiftDocCUtilitiesTests/PreviewServer/PreviewServerTests.swift @@ -13,6 +13,7 @@ import Foundation @testable import SwiftDocCUtilities @testable import SwiftDocC +import SwiftDocCTestUtilities @testable import NIO @testable import NIOHTTP1 diff --git a/Tests/SwiftDocCUtilitiesTests/PreviewServer/RequestHandler/DefaultRequestHandlerTests.swift b/Tests/SwiftDocCUtilitiesTests/PreviewServer/RequestHandler/DefaultRequestHandlerTests.swift index e7bf839a3c..cfaafba07b 100644 --- a/Tests/SwiftDocCUtilitiesTests/PreviewServer/RequestHandler/DefaultRequestHandlerTests.swift +++ b/Tests/SwiftDocCUtilitiesTests/PreviewServer/RequestHandler/DefaultRequestHandlerTests.swift @@ -12,6 +12,7 @@ import Foundation import XCTest @testable import SwiftDocC @testable import SwiftDocCUtilities +import SwiftDocCTestUtilities import NIO import NIOHTTP1 diff --git a/Tests/SwiftDocCUtilitiesTests/SemanticAnalyzerTests.swift b/Tests/SwiftDocCUtilitiesTests/SemanticAnalyzerTests.swift index 3b2dfeed5a..59af3ff9e7 100644 --- a/Tests/SwiftDocCUtilitiesTests/SemanticAnalyzerTests.swift +++ b/Tests/SwiftDocCUtilitiesTests/SemanticAnalyzerTests.swift @@ -12,6 +12,7 @@ import XCTest import Markdown @testable import SwiftDocC @testable import SwiftDocCUtilities +import SwiftDocCTestUtilities class SemanticAnalyzerTests: XCTestCase { let bundleFolderHierarchy = Folder(name: "SemanticAnalyzerTests.docc", content: [ diff --git a/Tests/SwiftDocCUtilitiesTests/StaticHostableTransformerTests.swift b/Tests/SwiftDocCUtilitiesTests/StaticHostableTransformerTests.swift index 9d58acd653..b31a7e8bf6 100644 --- a/Tests/SwiftDocCUtilitiesTests/StaticHostableTransformerTests.swift +++ b/Tests/SwiftDocCUtilitiesTests/StaticHostableTransformerTests.swift @@ -12,6 +12,7 @@ import XCTest import Foundation @testable import SwiftDocC @testable import SwiftDocCUtilities +import SwiftDocCTestUtilities class StaticHostableTransformerTests: StaticHostingBaseTests { diff --git a/Tests/SwiftDocCUtilitiesTests/TransformForStaticHostingActionTests.swift b/Tests/SwiftDocCUtilitiesTests/TransformForStaticHostingActionTests.swift index f1a1bb1fed..7d5ca49f71 100644 --- a/Tests/SwiftDocCUtilitiesTests/TransformForStaticHostingActionTests.swift +++ b/Tests/SwiftDocCUtilitiesTests/TransformForStaticHostingActionTests.swift @@ -12,6 +12,7 @@ import XCTest import Foundation @testable import SwiftDocC @testable import SwiftDocCUtilities +import SwiftDocCTestUtilities class TransformForStaticHostingActionTests: StaticHostingBaseTests { diff --git a/Tests/SwiftDocCUtilitiesTests/Utility/FileTests.swift b/Tests/SwiftDocCUtilitiesTests/Utility/FileTests.swift index 96336e15d3..e1286a33fc 100644 --- a/Tests/SwiftDocCUtilitiesTests/Utility/FileTests.swift +++ b/Tests/SwiftDocCUtilitiesTests/Utility/FileTests.swift @@ -11,6 +11,7 @@ import XCTest @testable import SwiftDocC @testable import SwiftDocCUtilities +import SwiftDocCTestUtilities class FileTests: XCTestCase { func testAbsoluteURL() { diff --git a/Tests/SwiftDocCUtilitiesTests/Utility/TestFileSystem.swift b/Tests/SwiftDocCUtilitiesTests/Utility/TestFileSystem.swift index 5419b5c965..dc79be4c8c 100644 --- a/Tests/SwiftDocCUtilitiesTests/Utility/TestFileSystem.swift +++ b/Tests/SwiftDocCUtilitiesTests/Utility/TestFileSystem.swift @@ -12,6 +12,7 @@ import Foundation import XCTest @testable import SwiftDocCUtilities @testable import SwiftDocC +import SwiftDocCTestUtilities /// A Data provider and file manager that accepts pre-built documentation bundles with files on the local filesystem. /// diff --git a/Tests/SwiftDocCUtilitiesTests/Utility/TestFileSystemTests.swift b/Tests/SwiftDocCUtilitiesTests/Utility/TestFileSystemTests.swift index df0cece3cb..ae041e2c61 100644 --- a/Tests/SwiftDocCUtilitiesTests/Utility/TestFileSystemTests.swift +++ b/Tests/SwiftDocCUtilitiesTests/Utility/TestFileSystemTests.swift @@ -11,6 +11,7 @@ import XCTest @testable import SwiftDocC @testable import SwiftDocCUtilities +import SwiftDocCTestUtilities class TestFileSystemTests: XCTestCase { From db26074346fab521b3bc8401bf8ddfd62afa863c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Ro=CC=88nnqvist?= Date: Tue, 21 Dec 2021 16:31:24 -0800 Subject: [PATCH 10/16] Add additional safety checks when creating and removing temporary directories --- .../XCTestCase+TemporaryDirectory.swift | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/Sources/SwiftDocCTestUtilities/XCTestCase+TemporaryDirectory.swift b/Sources/SwiftDocCTestUtilities/XCTestCase+TemporaryDirectory.swift index f35604136a..eedfe2345a 100644 --- a/Sources/SwiftDocCTestUtilities/XCTestCase+TemporaryDirectory.swift +++ b/Sources/SwiftDocCTestUtilities/XCTestCase+TemporaryDirectory.swift @@ -39,8 +39,20 @@ public extension XCTestCase { tempURL.standardize() addTeardownBlock { - try? fileManager.removeItem(at: baseURL) + do { + if fileManager.fileExists(atPath: baseURL.path) { + try fileManager.removeItem(at: baseURL) + } + } catch { + XCTFail("Failed to remove temporary directory: '\(error)'") + } } + + if !fileManager.fileExists(atPath: bundleParentDir.path) { + // Create the base URL directory without intermediate directories so that an error is raised if the parent directory doesn't exist. + try fileManager.createDirectory(at: baseURL, withIntermediateDirectories: false, attributes: nil) + } + try fileManager.createDirectory(at: tempURL, withIntermediateDirectories: true, attributes: nil) return tempURL From a3035e233458300aa28703569e031b4aae364470 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Ro=CC=88nnqvist?= Date: Tue, 21 Dec 2021 17:01:25 -0800 Subject: [PATCH 11/16] Replace `TempFolder` test class with `createTempFolder` test function --- .../FilesAndFolders.swift | 39 ++++--------- .../DocumentationContext+RootPageTests.swift | 12 ++-- .../Rendering/PlistSymbolTests.swift | 12 ++-- .../ConvertSubcommandTests.swift | 6 +- .../PreviewSubcommandTests.swift | 6 +- .../PreviewHTTPHandlerTests.swift | 12 ++-- .../PreviewServer/PreviewServerTests.swift | 24 ++++---- .../DefaultRequestHandlerTests.swift | 12 ++-- .../FileRequestHandlerTests.swift | 56 +++++++++---------- .../TempFolderTests.swift | 44 --------------- 10 files changed, 84 insertions(+), 139 deletions(-) delete mode 100644 Tests/SwiftDocCUtilitiesTests/TempFolderTests.swift diff --git a/Sources/SwiftDocCTestUtilities/FilesAndFolders.swift b/Sources/SwiftDocCTestUtilities/FilesAndFolders.swift index ccc780e307..7656975393 100644 --- a/Sources/SwiftDocCTestUtilities/FilesAndFolders.swift +++ b/Sources/SwiftDocCTestUtilities/FilesAndFolders.swift @@ -9,6 +9,7 @@ */ import Foundation +import XCTest /* This file contains API for working with folder hierarchies, and is extensible to allow for testing @@ -247,32 +248,16 @@ public struct DataFile: File, DataRepresentable { } } -/// A temporary folder which can write files to a temporary location on disk and -/// will delete itself when its instance is released from memory. -public class TempFolder: File { - public let name: String - public let url: URL - - /// The files and sub folders that this folder contains. - let content: [File] - - public func write(to url: URL) throws { - try FileManager.default.createDirectory(at: url, withIntermediateDirectories: false, attributes: nil) - for file in content { - try file.write(inside: url) - } - } - - public init(content: [File], atRoot root: URL) throws { - self.content = content - - url = root - name = url.absoluteString - - try write(to: url) - } - - deinit { - try? FileManager.default.removeItem(at: url) +extension XCTestCase { + /// Creates a ``Folder`` and writes its content to a temporary location on disk. + /// + /// - Parameters: + /// - content: The files and subfolders to write to a temporary location + /// - Returns: The temporary location where the temporary folder was written. + public func createTempFolder(content: [File]) throws -> URL { + let temporaryDirectory = try createTemporaryDirectory().appendingPathComponent("TempDirectory-\(ProcessInfo.processInfo.globallyUniqueString)") + let folder = Folder(name: temporaryDirectory.lastPathComponent, content: content) + try folder.write(to: temporaryDirectory) + return temporaryDirectory } } diff --git a/Tests/SwiftDocCTests/Infrastructure/DocumentationContext+RootPageTests.swift b/Tests/SwiftDocCTests/Infrastructure/DocumentationContext+RootPageTests.swift index cd56809f43..71961a724d 100644 --- a/Tests/SwiftDocCTests/Infrastructure/DocumentationContext+RootPageTests.swift +++ b/Tests/SwiftDocCTests/Infrastructure/DocumentationContext+RootPageTests.swift @@ -15,7 +15,7 @@ import SwiftDocCTestUtilities class DocumentationContext_RootPageTests: XCTestCase { func testNoSGFBundle() throws { - let tempFolder = try TempFolder(content: [ + let tempFolderURL = try createTempFolder(content: [ Folder(name: "no-sgf-test.docc", content: [ // Root page for the collection TextFile(name: "ReleaseNotes.md", utf8Content: """ @@ -37,12 +37,12 @@ class DocumentationContext_RootPageTests: XCTestCase { """), InfoPlist(displayName: "TestBundle", identifier: "com.test.example"), ]), - ], atRoot: createTemporaryDirectory().appendingPathComponent("tempFolder")) + ]) // Parse this test content let workspace = DocumentationWorkspace() let context = try DocumentationContext(dataProvider: workspace) - let dataProvider = try LocalFileSystemDataProvider(rootURL: tempFolder.url.appendingPathComponent("no-sgf-test.docc")) + let dataProvider = try LocalFileSystemDataProvider(rootURL: tempFolderURL.appendingPathComponent("no-sgf-test.docc")) try workspace.registerProvider(dataProvider) // Verify all articles were loaded in the context @@ -57,7 +57,7 @@ class DocumentationContext_RootPageTests: XCTestCase { } func testWarnForSidecarRootPage() throws { - let tempFolder = try TempFolder(content: [ + let tempFolderURL = try createTempFolder(content: [ Folder(name: "no-sgf-test.docc", content: [ // Root page for the collection TextFile(name: "ReleaseNotes.md", utf8Content: """ @@ -79,12 +79,12 @@ class DocumentationContext_RootPageTests: XCTestCase { """), InfoPlist(displayName: "TestBundle", identifier: "com.test.example"), ]), - ], atRoot: createTemporaryDirectory().appendingPathComponent("tempFolder")) + ]) // Parse this test content let workspace = DocumentationWorkspace() let context = try DocumentationContext(dataProvider: workspace) - let dataProvider = try LocalFileSystemDataProvider(rootURL: tempFolder.url.appendingPathComponent("no-sgf-test.docc")) + let dataProvider = try LocalFileSystemDataProvider(rootURL: tempFolderURL.appendingPathComponent("no-sgf-test.docc")) try workspace.registerProvider(dataProvider) // Verify that we emit a warning when trying to make a symbol a root page diff --git a/Tests/SwiftDocCTests/Rendering/PlistSymbolTests.swift b/Tests/SwiftDocCTests/Rendering/PlistSymbolTests.swift index 963e55e25e..0ef19b21e6 100644 --- a/Tests/SwiftDocCTests/Rendering/PlistSymbolTests.swift +++ b/Tests/SwiftDocCTests/Rendering/PlistSymbolTests.swift @@ -127,10 +127,10 @@ class PlistSymbolTests: XCTestCase { let modifiedJSON = try String(contentsOf: plistSymbolURL) .replacingOccurrences(of: "\"ideTitle\": \"WiFi access\",", with: "") - let tempDir = try TempFolder(content: [ + let tempFolderURL = try createTempFolder(content: [ TextFile(name: "missingIdeTitle.json", utf8Content: modifiedJSON), - ], atRoot: createTemporaryDirectory().appendingPathComponent("tempFolder")) - let symbol = try RenderNode.decode(fromJSON: try Data(contentsOf: tempDir.url.appendingPathComponent("missingIdeTitle.json"))) + ]) + let symbol = try RenderNode.decode(fromJSON: try Data(contentsOf: tempFolderURL.appendingPathComponent("missingIdeTitle.json"))) // // Plist Details @@ -153,10 +153,10 @@ class PlistSymbolTests: XCTestCase { let modifiedJSON = try String(contentsOf: plistSymbolURL) .replacingOccurrences(of: "\"title\": \"Possible Values\",", with: "") - let tempDir = try TempFolder(content: [ + let tempFolderURL = try createTempFolder(content: [ TextFile(name: "missingPossibleValuesTitle.json", utf8Content: modifiedJSON), - ], atRoot: createTemporaryDirectory().appendingPathComponent("tempFolder")) - let symbol = try RenderNode.decode(fromJSON: try Data(contentsOf: tempDir.url.appendingPathComponent("missingPossibleValuesTitle.json"))) + ]) + let symbol = try RenderNode.decode(fromJSON: try Data(contentsOf: tempFolderURL.appendingPathComponent("missingPossibleValuesTitle.json"))) // // Plist Details diff --git a/Tests/SwiftDocCUtilitiesTests/ArgumentParsing/ConvertSubcommandTests.swift b/Tests/SwiftDocCUtilitiesTests/ArgumentParsing/ConvertSubcommandTests.swift index 6c143dfdb8..49b1b9e19a 100644 --- a/Tests/SwiftDocCUtilitiesTests/ArgumentParsing/ConvertSubcommandTests.swift +++ b/Tests/SwiftDocCUtilitiesTests/ArgumentParsing/ConvertSubcommandTests.swift @@ -77,11 +77,11 @@ class ConvertSubcommandTests: XCTestCase { // Test default template do { unsetenv(TemplateOption.environmentVariableKey) - let tempDir = try createTemporaryDirectory() - let doccExecutableLocation = tempDir + let tempFolder = try createTemporaryDirectory() + let doccExecutableLocation = tempFolder .appendingPathComponent("bin") .appendingPathComponent("docc-executable-name") - let defaultTemplateDir = tempDir + let defaultTemplateDir = tempFolder .appendingPathComponent("share") .appendingPathComponent("docc") .appendingPathComponent("render", isDirectory: true) diff --git a/Tests/SwiftDocCUtilitiesTests/ArgumentParsing/PreviewSubcommandTests.swift b/Tests/SwiftDocCUtilitiesTests/ArgumentParsing/PreviewSubcommandTests.swift index f11f60ebfc..051a369d0d 100644 --- a/Tests/SwiftDocCUtilitiesTests/ArgumentParsing/PreviewSubcommandTests.swift +++ b/Tests/SwiftDocCUtilitiesTests/ArgumentParsing/PreviewSubcommandTests.swift @@ -48,11 +48,11 @@ class PreviewSubcommandTests: XCTestCase { // Test default template do { unsetenv(TemplateOption.environmentVariableKey) - let tempDir = try createTemporaryDirectory() - let doccExecutableLocation = tempDir + let tempFolder = try createTemporaryDirectory() + let doccExecutableLocation = tempFolder .appendingPathComponent("bin") .appendingPathComponent("docc-executable-name") - let defaultTemplateDir = tempDir + let defaultTemplateDir = tempFolder .appendingPathComponent("share") .appendingPathComponent("docc") .appendingPathComponent("render", isDirectory: true) diff --git a/Tests/SwiftDocCUtilitiesTests/PreviewServer/PreviewHTTPHandlerTests.swift b/Tests/SwiftDocCUtilitiesTests/PreviewServer/PreviewHTTPHandlerTests.swift index 3347f0e217..8f3d478128 100644 --- a/Tests/SwiftDocCUtilitiesTests/PreviewServer/PreviewHTTPHandlerTests.swift +++ b/Tests/SwiftDocCUtilitiesTests/PreviewServer/PreviewHTTPHandlerTests.swift @@ -22,15 +22,15 @@ class PreviewHTTPHandlerTests: XCTestCase { /// Tests the three different responses we offer: static file, default, and error. func testPreviewHandler() throws { - let tempDir = try TempFolder(content: [ + let tempFolderURL = try createTempFolder(content: [ TextFile(name: "index.html", utf8Content: "index"), Folder(name: "css", content: [ TextFile(name: "test.css", utf8Content: "css"), ]) - ], atRoot: createTemporaryDirectory().appendingPathComponent("tempFolder")) + ]) let channel = EmbeddedChannel() - let channelHandler = PreviewHTTPHandler(fileIO: fileIO, rootURL: tempDir.url) + let channelHandler = PreviewHTTPHandler(fileIO: fileIO, rootURL: tempFolderURL) let response = Response() @@ -83,12 +83,12 @@ class PreviewHTTPHandlerTests: XCTestCase { } func testPreviewAuthHandler() throws { - let tempDir = try TempFolder(content: [ + let tempFolderURL = try createTempFolder(content: [ TextFile(name: "index.html", utf8Content: "index"), Folder(name: "css", content: [ TextFile(name: "test.css", utf8Content: "css"), ]) - ], atRoot: createTemporaryDirectory().appendingPathComponent("tempFolder")) + ]) let channel = EmbeddedChannel() defer { @@ -96,7 +96,7 @@ class PreviewHTTPHandlerTests: XCTestCase { _ = try? channel.finish() } - let channelHandler = PreviewHTTPHandler(fileIO: fileIO, rootURL: tempDir.url, credentials: (user: "user", pass: "pass")) + let channelHandler = PreviewHTTPHandler(fileIO: fileIO, rootURL: tempFolderURL, credentials: (user: "user", pass: "pass")) let response = Response() diff --git a/Tests/SwiftDocCUtilitiesTests/PreviewServer/PreviewServerTests.swift b/Tests/SwiftDocCUtilitiesTests/PreviewServer/PreviewServerTests.swift index f88758c0a0..50db38374d 100644 --- a/Tests/SwiftDocCUtilitiesTests/PreviewServer/PreviewServerTests.swift +++ b/Tests/SwiftDocCUtilitiesTests/PreviewServer/PreviewServerTests.swift @@ -34,17 +34,21 @@ class PreviewServerTests { fatalError("This test is disabled by not conforming to XCTestCase. This helper is added here to make the code compile. This should never be called.") } + public func createTempFolder(content: [File]) throws -> URL { + fatalError("This test is disabled by not conforming to XCTestCase. This helper is added here to make the code compile. This should never be called.") + } + func testPreviewServerBeforeStarted() throws { // Create test content - let tempFolder = try TempFolder(content: [ + let tempFolderURL = try createTempFolder(content: [ TextFile(name: "index.html", utf8Content: "index"), - ], atRoot: createTemporaryDirectory().appendingPathComponent("tempFolder")) + ]) let socketURL = try createTemporaryDirectory(pathComponents: "sock", createDirectoryForLastPathComponent: false) // Run test server var log = LogHandle.none - let server = try PreviewServer(contentURL: tempFolder.url, bindTo: .socket(path: socketURL.path), username: "username", password: "password", logHandle: &log) + let server = try PreviewServer(contentURL: tempFolderURL, bindTo: .socket(path: socketURL.path), username: "username", password: "password", logHandle: &log) // Assert server starts let expectationStarted = AsyncronousExpectation(description: "Server before start") @@ -81,9 +85,9 @@ class PreviewServerTests { XCTAssertEqual(client.handler.statusCode, errorStatusCode, file: (file), line: line) } - private func makeTempFolder() throws -> TempFolder { + private func makeTempFolder() throws -> URL { // Create test content - try TempFolder(content: [ + try createTempFolder(content: [ TextFile(name: "index.html", utf8Content: "index"), TextFile(name: "theme-settings.js", utf8Content: "java script content"), TextFile(name: "theme-settings.json", utf8Content: "JSON content"), @@ -113,18 +117,18 @@ class PreviewServerTests { Folder(name: "downloads", content: [ TextFile(name: "test.zip", utf8Content: "downloads content"), ]) - ], atRoot: createTemporaryDirectory().appendingPathComponent("tempFolder")) + ]) } func testPreviewServerPaths() throws { - let tempFolder = try makeTempFolder() + let tempFolderURL = try makeTempFolder() // Socket URL let socketURL = try createTemporaryDirectory(pathComponents: "sock", createDirectoryForLastPathComponent: false) // Create the server var log = LogHandle.none - let server = try PreviewServer(contentURL: tempFolder.url, bindTo: .socket(path: socketURL.path), username: "username", password: "password", logHandle: &log) + let server = try PreviewServer(contentURL: tempFolderURL, bindTo: .socket(path: socketURL.path), username: "username", password: "password", logHandle: &log) // Start the server let expectationStarted = AsyncronousExpectation(description: "Server before start") @@ -164,14 +168,14 @@ class PreviewServerTests { } func testConcurrentRequests() throws { - let tempFolder = try makeTempFolder() + let tempFolderURL = try makeTempFolder() // Socket URL let socketURL = try createTemporaryDirectory(pathComponents: "sock", createDirectoryForLastPathComponent: false) // Create the server var log = LogHandle.none - let server = try PreviewServer(contentURL: tempFolder.url, bindTo: .socket(path: socketURL.path), username: "username", password: "password", logHandle: &log) + let server = try PreviewServer(contentURL: tempFolderURL, bindTo: .socket(path: socketURL.path), username: "username", password: "password", logHandle: &log) // Start the server let expectationStarted = AsyncronousExpectation(description: "Server before start") diff --git a/Tests/SwiftDocCUtilitiesTests/PreviewServer/RequestHandler/DefaultRequestHandlerTests.swift b/Tests/SwiftDocCUtilitiesTests/PreviewServer/RequestHandler/DefaultRequestHandlerTests.swift index cfaafba07b..e6c6ff70b4 100644 --- a/Tests/SwiftDocCUtilitiesTests/PreviewServer/RequestHandler/DefaultRequestHandlerTests.swift +++ b/Tests/SwiftDocCUtilitiesTests/PreviewServer/RequestHandler/DefaultRequestHandlerTests.swift @@ -20,13 +20,13 @@ import NIOHTTP1 class DefaultRequestHandlerTests: XCTestCase { func testDefaultHandler() throws { - let tempDir = try TempFolder(content: [ + let tempFolderURL = try createTempFolder(content: [ TextFile(name: "index.html", utf8Content: "Hello!"), - ], atRoot: createTemporaryDirectory().appendingPathComponent("tempFolder")) + ]) // Default handler should be invoked for any non-asset path let request = makeRequestHead(path: "/random-path") - let factory = DefaultRequestHandler(rootURL: tempDir.url) + let factory = DefaultRequestHandler(rootURL: tempFolderURL) let response = try responseWithPipeline(request: request, handler: factory) // Expected content @@ -42,14 +42,14 @@ class DefaultRequestHandlerTests: XCTestCase { } func testDefaultHandlerForExistingPath() throws { - let tempDir = try TempFolder(content: [ + let tempFolderURL = try createTempFolder(content: [ TextFile(name: "index.html", utf8Content: "Hello!"), TextFile(name: "existing.html", utf8Content: "Existing!"), - ], atRoot: createTemporaryDirectory().appendingPathComponent("tempFolder")) + ]) // Default handler should handle even paths that do exist on disc let request = makeRequestHead(path: "/existing.html") - let factory = DefaultRequestHandler(rootURL: tempDir.url) + let factory = DefaultRequestHandler(rootURL: tempFolderURL) let response = try responseWithPipeline(request: request, handler: factory) // Expected content diff --git a/Tests/SwiftDocCUtilitiesTests/PreviewServer/RequestHandler/FileRequestHandlerTests.swift b/Tests/SwiftDocCUtilitiesTests/PreviewServer/RequestHandler/FileRequestHandlerTests.swift index cb89daff6d..84774c6bdb 100644 --- a/Tests/SwiftDocCUtilitiesTests/PreviewServer/RequestHandler/FileRequestHandlerTests.swift +++ b/Tests/SwiftDocCUtilitiesTests/PreviewServer/RequestHandler/FileRequestHandlerTests.swift @@ -32,7 +32,7 @@ class FileRequestHandlerTests: XCTestCase { } func testFileHandlerAssets() throws { - let tempDir = try TempFolder(content: [ + let tempFolderURL = try createTempFolder(content: [ Folder(name: "data", content: [ TextFile(name: "test.json", utf8Content: "data"), ]), @@ -64,47 +64,47 @@ class FileRequestHandlerTests: XCTestCase { Folder(name: "downloads", content: [ TextFile(name: "project.zip", utf8Content: "zip"), ]) - ], atRoot: createTemporaryDirectory().appendingPathComponent("tempFolder")) + ]) - try verifyAsset(root: tempDir.url, path: "/data/test.json", body: "data", type: "application/json") - try verifyAsset(root: tempDir.url, path: "/css/test.css", body: "css", type: "text/css") - try verifyAsset(root: tempDir.url, path: "/js/test.js", body: "js", type: "text/javascript") - try verifyAsset(root: tempDir.url, path: "/fonts/test.otf", body: "font", type: "font/otf") + try verifyAsset(root: tempFolderURL, path: "/data/test.json", body: "data", type: "application/json") + try verifyAsset(root: tempFolderURL, path: "/css/test.css", body: "css", type: "text/css") + try verifyAsset(root: tempFolderURL, path: "/js/test.js", body: "js", type: "text/javascript") + try verifyAsset(root: tempFolderURL, path: "/fonts/test.otf", body: "font", type: "font/otf") // default font type - try verifyAsset(root: tempDir.url, path: "/fonts/test.ttf", body: "ttf", type: "application/octet-stream") - try verifyAsset(root: tempDir.url, path: "/images/image.png", body: "png", type: "image/png") - try verifyAsset(root: tempDir.url, path: "/images/image.gif", body: "gif", type: "image/gif") + try verifyAsset(root: tempFolderURL, path: "/fonts/test.ttf", body: "ttf", type: "application/octet-stream") + try verifyAsset(root: tempFolderURL, path: "/images/image.png", body: "png", type: "image/png") + try verifyAsset(root: tempFolderURL, path: "/images/image.gif", body: "gif", type: "image/gif") // default image type - try verifyAsset(root: tempDir.url, path: "/images/image.jpg", body: "jpg", type: "image/jpeg") - try verifyAsset(root: tempDir.url, path: "/images/logo.svg", body: "svg", type: "image/svg+xml") - try verifyAsset(root: tempDir.url, path: "/img/image.png", body: "png", type: "image/png") - try verifyAsset(root: tempDir.url, path: "/img/image.gif", body: "gif", type: "image/gif") + try verifyAsset(root: tempFolderURL, path: "/images/image.jpg", body: "jpg", type: "image/jpeg") + try verifyAsset(root: tempFolderURL, path: "/images/logo.svg", body: "svg", type: "image/svg+xml") + try verifyAsset(root: tempFolderURL, path: "/img/image.png", body: "png", type: "image/png") + try verifyAsset(root: tempFolderURL, path: "/img/image.gif", body: "gif", type: "image/gif") // default image type - try verifyAsset(root: tempDir.url, path: "/img/image.jpg", body: "jpg", type: "image/jpeg") - try verifyAsset(root: tempDir.url, path: "/videos/video.mov", body: "mov", type: "video/quicktime") - try verifyAsset(root: tempDir.url, path: "/videos/video.avi", body: "avi", type: "video/x-msvideo") - try verifyAsset(root: tempDir.url, path: "/downloads/project.zip", body: "zip", type: "application/zip") + try verifyAsset(root: tempFolderURL, path: "/img/image.jpg", body: "jpg", type: "image/jpeg") + try verifyAsset(root: tempFolderURL, path: "/videos/video.mov", body: "mov", type: "video/quicktime") + try verifyAsset(root: tempFolderURL, path: "/videos/video.avi", body: "avi", type: "video/x-msvideo") + try verifyAsset(root: tempFolderURL, path: "/downloads/project.zip", body: "zip", type: "application/zip") } func testFileHandlerAssetsMissing() throws { - let tempDir = try TempFolder(content: [], atRoot: createTemporaryDirectory().appendingPathComponent("tempFolder")) + let tempFolderURL = try createTempFolder(content: []) let request = makeRequestHead(path: "/css/b00011100.css") - let factory = FileRequestHandler(rootURL: tempDir.url, fileIO: fileIO) + let factory = FileRequestHandler(rootURL: tempFolderURL, fileIO: fileIO) let response = try responseWithPipeline(request: request, handler: factory) XCTAssertEqual(response.requestError?.status, .notFound) } func testFileHandlerWithRange() throws { - let tempDir = try TempFolder(content: [ + let tempFolderURL = try createTempFolder(content: [ Folder(name: "videos", content: [ TextFile(name: "video.mov", utf8Content: "Hello!"), ]) - ], atRoot: createTemporaryDirectory().appendingPathComponent("tempFolder")) + ]) let request = makeRequestHead(path: "/videos/video.mov", headers: [("Range", "bytes=0-1")]) - let factory = FileRequestHandler(rootURL: tempDir.url, fileIO: fileIO) + let factory = FileRequestHandler(rootURL: tempFolderURL, fileIO: fileIO) let response = try responseWithPipeline(request: request, handler: factory) XCTAssertEqual(response.body, "He") @@ -116,14 +116,14 @@ class FileRequestHandlerTests: XCTestCase { } func testFileInUpperDirectory() throws { - let tempDir = try TempFolder(content: [ + let tempFolderURL = try createTempFolder(content: [ Folder(name: "videos", content: [ TextFile(name: "video.mov", utf8Content: "Hello!"), ]) - ], atRoot: createTemporaryDirectory().appendingPathComponent("tempFolder")) + ]) let request = makeRequestHead(path: "/videos/../video.mov", headers: [("Range", "bytes=0-1")]) - let factory = FileRequestHandler(rootURL: tempDir.url, fileIO: fileIO) + let factory = FileRequestHandler(rootURL: tempFolderURL, fileIO: fileIO) let response = try responseWithPipeline(request: request, handler: factory) XCTAssertNil(response.body, "He") @@ -131,14 +131,14 @@ class FileRequestHandlerTests: XCTestCase { } func testMalformedPath() throws { - let tempDir = try TempFolder(content: [ + let tempFolderURL = try createTempFolder(content: [ Folder(name: "videos", content: [ TextFile(name: "video.mov", utf8Content: "Hello!"), ]) - ], atRoot: createTemporaryDirectory().appendingPathComponent("tempFolder")) + ]) let request = makeRequestHead(path: "/videos/. ? ? ? ./video.mov", headers: [("Range", "bytes=0-1")]) - let factory = FileRequestHandler(rootURL: tempDir.url, fileIO: fileIO) + let factory = FileRequestHandler(rootURL: tempFolderURL, fileIO: fileIO) let response = try responseWithPipeline(request: request, handler: factory) XCTAssertNil(response.body, "He") diff --git a/Tests/SwiftDocCUtilitiesTests/TempFolderTests.swift b/Tests/SwiftDocCUtilitiesTests/TempFolderTests.swift deleted file mode 100644 index c22d5aa262..0000000000 --- a/Tests/SwiftDocCUtilitiesTests/TempFolderTests.swift +++ /dev/null @@ -1,44 +0,0 @@ -/* - This source file is part of the Swift.org open source project - - Copyright (c) 2021 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 -*/ - -import Foundation -import XCTest -@testable import SwiftDocC -import SwiftDocCTestUtilities - -class TempFolderTests: XCTestCase { - func testCreatesAndDeletesTempFolder() throws { - var tempFolder: TempFolder! = try TempFolder(content: [ - TextFile(name: "index.html", utf8Content: "index"), - ], atRoot: createTemporaryDirectory().appendingPathComponent("tempFolder")) - - // Check the folder is created and the file inside exists. - XCTAssertTrue(FileManager.default.directoryExists(atPath: tempFolder.url.path)) - XCTAssertTrue(FileManager.default.fileExists(atPath: tempFolder!.url.appendingPathComponent("index.html").path)) - - let rootTempFolderPath = tempFolder!.url.path - // Check the temp folder is inside the system temporary folder. - XCTAssertTrue(tempFolder!.url.path.contains(rootTempFolderPath)) - - let tempFolderURL = tempFolder.url - - tempFolder = nil - - // Check the temp folder and contents are deleted immediately. - XCTAssertFalse(FileManager.default.fileExists(atPath: tempFolderURL.path)) - } - - func testCreatesRandomPaths() throws { - let tempFolder1 = try TempFolder(content: [], atRoot: createTemporaryDirectory().appendingPathComponent("tempFolder")) - let tempFolder2 = try TempFolder(content: [], atRoot: createTemporaryDirectory().appendingPathComponent("tempFolder")) - - XCTAssertNotEqual(tempFolder1.url, tempFolder2.url) - } -} From cc3d57db484b729aa400fd029282279adba43c10 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Ro=CC=88nnqvist?= Date: Tue, 21 Dec 2021 17:30:25 -0800 Subject: [PATCH 12/16] Use XCTUnwrap instead of force unwrap in test helper --- .../DocumentationContextTests.swift | 12 ++++++------ .../DocumentationCuratorTests.swift | 6 +++--- .../ExternalReferenceResolverTests.swift | 6 +++--- .../SymbolGraphRelationshipsBuilderTests.swift | 6 +++--- .../Rendering/DefaultAvailabilityTests.swift | 4 ++-- .../XCTestCase+LoadingTestData.swift | 18 +++++++++--------- 6 files changed, 26 insertions(+), 26 deletions(-) diff --git a/Tests/SwiftDocCTests/Infrastructure/DocumentationContextTests.swift b/Tests/SwiftDocCTests/Infrastructure/DocumentationContextTests.swift index 7db8eef0a0..94dddffc91 100644 --- a/Tests/SwiftDocCTests/Infrastructure/DocumentationContextTests.swift +++ b/Tests/SwiftDocCTests/Infrastructure/DocumentationContextTests.swift @@ -39,7 +39,7 @@ class DocumentationContextTests: XCTestCase { func testResolve() throws { let workspace = DocumentationWorkspace() let context = try DocumentationContext(dataProvider: workspace) - let bundle = testBundle(named: "TestBundle") + let bundle = try testBundle(named: "TestBundle") let dataProvider = PrebuiltLocalFileSystemDataProvider(bundles: [bundle]) try workspace.registerProvider(dataProvider) @@ -482,7 +482,7 @@ class DocumentationContextTests: XCTestCase { func testRegisteredImages() throws { let workspace = DocumentationWorkspace() let context = try DocumentationContext(dataProvider: workspace) - let bundle = testBundle(named: "TestBundle") + let bundle = try testBundle(named: "TestBundle") let dataProvider = PrebuiltLocalFileSystemDataProvider(bundles: [bundle]) try workspace.registerProvider(dataProvider) @@ -513,7 +513,7 @@ class DocumentationContextTests: XCTestCase { func testDownloadAssets() throws { let workspace = DocumentationWorkspace() let context = try DocumentationContext(dataProvider: workspace) - let bundle = testBundle(named: "TestBundle") + let bundle = try testBundle(named: "TestBundle") let dataProvider = PrebuiltLocalFileSystemDataProvider(bundles: [bundle]) try workspace.registerProvider(dataProvider) @@ -601,7 +601,7 @@ class DocumentationContextTests: XCTestCase { context.addGlobalChecks([{ (context, reference) -> [Problem] in return [Problem(diagnostic: Diagnostic(source: reference.url, severity: DiagnosticSeverity.error, range: nil, identifier: "com.tests.testGraphChecks", summary: "test error"), possibleSolutions: [])] }]) - let bundle = testBundle(named: "TestBundle") + let bundle = try testBundle(named: "TestBundle") let dataProvider = PrebuiltLocalFileSystemDataProvider(bundles: [bundle]) try workspace.registerProvider(dataProvider) @@ -1265,7 +1265,7 @@ let expected = """ func testLanguageForNode() throws { let workspace = DocumentationWorkspace() let context = try DocumentationContext(dataProvider: workspace) - let bundle = testBundle(named: "TestBundle") + let bundle = try testBundle(named: "TestBundle") let dataProvider = PrebuiltLocalFileSystemDataProvider(bundles: [bundle]) try workspace.registerProvider(dataProvider) let articleReference = ResolvedTopicReference(bundleIdentifier: bundle.identifier, path: "/documentation/Test-Bundle/article", sourceLanguage: .swift) @@ -1938,7 +1938,7 @@ let expected = """ func renderNodeForPath(path: String) throws -> (DocumentationNode, RenderNode) { let workspace = DocumentationWorkspace() let context = try DocumentationContext(dataProvider: workspace) - let bundle = testBundle(named: "TestBundle") + let bundle = try testBundle(named: "TestBundle") let dataProvider = PrebuiltLocalFileSystemDataProvider(bundles: [bundle]) try workspace.registerProvider(dataProvider) diff --git a/Tests/SwiftDocCTests/Infrastructure/DocumentationCuratorTests.swift b/Tests/SwiftDocCTests/Infrastructure/DocumentationCuratorTests.swift index 05b4da68bd..7f6e7a4c27 100644 --- a/Tests/SwiftDocCTests/Infrastructure/DocumentationCuratorTests.swift +++ b/Tests/SwiftDocCTests/Infrastructure/DocumentationCuratorTests.swift @@ -29,7 +29,7 @@ class DocumentationCuratorTests: XCTestCase { func testCrawl() throws { let workspace = DocumentationWorkspace() let context = try DocumentationContext(dataProvider: workspace) - let bundle = testBundle(named: "TestBundle") + let bundle = try testBundle(named: "TestBundle") let dataProvider = PrebuiltLocalFileSystemDataProvider(bundles: [bundle]) try workspace.registerProvider(dataProvider) @@ -148,7 +148,7 @@ class DocumentationCuratorTests: XCTestCase { func testSymbolLinkResolving() throws { let workspace = DocumentationWorkspace() let context = try DocumentationContext(dataProvider: workspace) - let bundle = testBundle(named: "TestBundle") + let bundle = try testBundle(named: "TestBundle") let dataProvider = PrebuiltLocalFileSystemDataProvider(bundles: [bundle]) try workspace.registerProvider(dataProvider) @@ -205,7 +205,7 @@ class DocumentationCuratorTests: XCTestCase { func testLinkResolving() throws { let workspace = DocumentationWorkspace() let context = try DocumentationContext(dataProvider: workspace) - let bundle = testBundle(named: "TestBundle") + let bundle = try testBundle(named: "TestBundle") let sourceRoot = Bundle.module.url( forResource: "TestBundle", withExtension: "docc", subdirectory: "Test Bundles")! let dataProvider = PrebuiltLocalFileSystemDataProvider(bundles: [bundle]) diff --git a/Tests/SwiftDocCTests/Infrastructure/ExternalReferenceResolverTests.swift b/Tests/SwiftDocCTests/Infrastructure/ExternalReferenceResolverTests.swift index 554c224176..8f65edcde8 100644 --- a/Tests/SwiftDocCTests/Infrastructure/ExternalReferenceResolverTests.swift +++ b/Tests/SwiftDocCTests/Infrastructure/ExternalReferenceResolverTests.swift @@ -145,7 +145,7 @@ class ExternalReferenceResolverTests: XCTestCase { func testResolvesReferencesExternallyOnlyWhenFallbackResolversAreSet() throws { let workspace = DocumentationWorkspace() - let bundle = testBundle(named: "TestBundle") + let bundle = try testBundle(named: "TestBundle") let dataProvider = PrebuiltLocalFileSystemDataProvider(bundles: [bundle]) try workspace.registerProvider(dataProvider) let context = try DocumentationContext(dataProvider: workspace) @@ -189,7 +189,7 @@ class ExternalReferenceResolverTests: XCTestCase { func testLoadEntityForExternalReference() throws { let workspace = DocumentationWorkspace() - let bundle = testBundle(named: "TestBundle") + let bundle = try testBundle(named: "TestBundle") let dataProvider = PrebuiltLocalFileSystemDataProvider(bundles: [bundle]) try workspace.registerProvider(dataProvider) let context = try DocumentationContext(dataProvider: workspace) @@ -237,7 +237,7 @@ Document @1:1-1:35 externalResolver.resolvedEntityKind = resolvedEntityKind context.externalReferenceResolvers = [externalResolver.bundleIdentifier: externalResolver] - let bundle = testBundle(named: "TestBundle") + let bundle = try testBundle(named: "TestBundle") let dataProvider = PrebuiltLocalFileSystemDataProvider(bundles: [bundle]) try workspace.registerProvider(dataProvider) diff --git a/Tests/SwiftDocCTests/Infrastructure/SymbolGraph/SymbolGraphRelationshipsBuilderTests.swift b/Tests/SwiftDocCTests/Infrastructure/SymbolGraph/SymbolGraphRelationshipsBuilderTests.swift index 4b6bc6ae5f..392b5e27bf 100644 --- a/Tests/SwiftDocCTests/Infrastructure/SymbolGraph/SymbolGraphRelationshipsBuilderTests.swift +++ b/Tests/SwiftDocCTests/Infrastructure/SymbolGraph/SymbolGraphRelationshipsBuilderTests.swift @@ -48,7 +48,7 @@ class SymbolGraphRelationshipsBuilderTests: XCTestCase { } func testConformsRelationship() throws { - let bundle = testBundle(named: "TestBundle") + let bundle = try testBundle(named: "TestBundle") var symbolIndex = [String: DocumentationNode]() let engine = DiagnosticEngine() @@ -77,7 +77,7 @@ class SymbolGraphRelationshipsBuilderTests: XCTestCase { } func testInheritanceRelationship() throws { - let bundle = testBundle(named: "TestBundle") + let bundle = try testBundle(named: "TestBundle") var symbolIndex = [String: DocumentationNode]() let engine = DiagnosticEngine() @@ -106,7 +106,7 @@ class SymbolGraphRelationshipsBuilderTests: XCTestCase { } func testRequirementRelationship() throws { - let bundle = testBundle(named: "TestBundle") + let bundle = try testBundle(named: "TestBundle") var symbolIndex = [String: DocumentationNode]() let engine = DiagnosticEngine() diff --git a/Tests/SwiftDocCTests/Rendering/DefaultAvailabilityTests.swift b/Tests/SwiftDocCTests/Rendering/DefaultAvailabilityTests.swift index 6a5902a550..417167b056 100644 --- a/Tests/SwiftDocCTests/Rendering/DefaultAvailabilityTests.swift +++ b/Tests/SwiftDocCTests/Rendering/DefaultAvailabilityTests.swift @@ -16,8 +16,8 @@ import SymbolKit class DefaultAvailabilityTests: XCTestCase { // Test whether missing default availability key correctly produces nil availability - func testBundleWithoutDefaultAvailability() { - let bundle = testBundle(named: "BundleWithoutAvailability") + func testBundleWithoutDefaultAvailability() throws { + let bundle = try testBundle(named: "BundleWithoutAvailability") XCTAssertNil(bundle.info.defaultAvailability) } diff --git a/Tests/SwiftDocCTests/XCTestCase+LoadingTestData.swift b/Tests/SwiftDocCTests/XCTestCase+LoadingTestData.swift index 737d7b4f5d..ad00b7271b 100644 --- a/Tests/SwiftDocCTests/XCTestCase+LoadingTestData.swift +++ b/Tests/SwiftDocCTests/XCTestCase+LoadingTestData.swift @@ -25,7 +25,7 @@ extension XCTestCase { // Load the bundle using automatic discovery let automaticDataProvider = try LocalFileSystemDataProvider(rootURL: bundleURL) // Mutate the bundle to include the code listings, then apply to the workspace using a manual provider. - var bundle = try automaticDataProvider.bundles().first! + var bundle = try XCTUnwrap(automaticDataProvider.bundles().first) bundle.attributedCodeListings = codeListings let dataProvider = PrebuiltLocalFileSystemDataProvider(bundles: [bundle]) try workspace.registerProvider(dataProvider) @@ -33,8 +33,8 @@ extension XCTestCase { } func testBundleAndContext(copying name: String, excludingPaths excludedPaths: [String] = [], codeListings: [String : AttributedCodeListing] = [:], externalResolvers: [BundleIdentifier : ExternalReferenceResolver] = [:], externalSymbolResolver: ExternalSymbolResolver? = nil, configureBundle: ((URL) throws -> Void)? = nil) throws -> (URL, DocumentationBundle, DocumentationContext) { - let sourceURL = Bundle.module.url( - forResource: name, withExtension: "docc", subdirectory: "Test Bundles")! + let sourceURL = try XCTUnwrap(Bundle.module.url( + forResource: name, withExtension: "docc", subdirectory: "Test Bundles")) let sourceExists = FileManager.default.fileExists(atPath: sourceURL.path) let bundleURL = sourceExists @@ -56,20 +56,20 @@ extension XCTestCase { } func testBundleAndContext(named name: String, codeListings: [String : AttributedCodeListing] = [:], externalResolvers: [String: ExternalReferenceResolver] = [:]) throws -> (DocumentationBundle, DocumentationContext) { - let bundleURL = Bundle.module.url( - forResource: name, withExtension: "docc", subdirectory: "Test Bundles")! + let bundleURL = try XCTUnwrap(Bundle.module.url( + forResource: name, withExtension: "docc", subdirectory: "Test Bundles")) let (_, bundle, context) = try loadBundle(from: bundleURL, codeListings: codeListings, externalResolvers: externalResolvers) return (bundle, context) } - func testBundle(named name: String) -> DocumentationBundle { - let (bundle, _) = try! testBundleAndContext(named: name) + func testBundle(named name: String) throws -> DocumentationBundle { + let (bundle, _) = try testBundleAndContext(named: name) return bundle } func testBundleFromRootURL(named name: String) throws -> DocumentationBundle { - let bundleURL = Bundle.module.url( - forResource: name, withExtension: "docc", subdirectory: "Test Bundles")! + let bundleURL = try XCTUnwrap(Bundle.module.url( + forResource: name, withExtension: "docc", subdirectory: "Test Bundles")) let dataProvider = try LocalFileSystemDataProvider(rootURL: bundleURL) let bundles = try dataProvider.bundles() From 0436ad58f438c3acd944bbac27dc22c456777be6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Ro=CC=88nnqvist?= Date: Wed, 22 Dec 2021 13:21:43 -0800 Subject: [PATCH 13/16] Also shadow `FileManager.temporaryDirectory` in tests --- .../XCTestCase+TemporaryDirectory.swift | 10 ++++++++ .../DocumentationConverterTests.swift | 4 +-- .../ShadowFileManagerTemporaryDirectory.swift | 23 +++++++++++++++++ .../ConvertActionTests.swift | 25 ++----------------- .../ShadowFileManagerTemporaryDirectory.swift | 23 +++++++++++++++++ 5 files changed, 59 insertions(+), 26 deletions(-) create mode 100644 Tests/SwiftDocCTests/ShadowFileManagerTemporaryDirectory.swift create mode 100644 Tests/SwiftDocCUtilitiesTests/ShadowFileManagerTemporaryDirectory.swift diff --git a/Sources/SwiftDocCTestUtilities/XCTestCase+TemporaryDirectory.swift b/Sources/SwiftDocCTestUtilities/XCTestCase+TemporaryDirectory.swift index eedfe2345a..0af918bc9c 100644 --- a/Sources/SwiftDocCTestUtilities/XCTestCase+TemporaryDirectory.swift +++ b/Sources/SwiftDocCTestUtilities/XCTestCase+TemporaryDirectory.swift @@ -13,10 +13,20 @@ import XCTest // These helpers methods exist to put temp files for different test executions in different locations when running in Swift CI. +extension FileManager { + + @available(*, deprecated, message: "Use `createTemporaryDirectory` instead in unit tests to avoid referencing a shared location in Swift CI.") + var temporaryDirectory: URL { + XCTFail("Use `createTemporaryDirectory` instead in unit tests to avoid referencing a shared location in Swift CI.") + return URL(fileURLWithPath: Foundation.NSTemporaryDirectory()) + } +} + public extension XCTestCase { @available(*, deprecated, message: "Use `createTemporaryDirectory` instead in unit tests to avoid referencing a shared location in Swift CI.") func NSTemporaryDirectory() -> String { + XCTFail("Use `createTemporaryDirectory` instead in unit tests to avoid referencing a shared location in Swift CI.") return Foundation.NSTemporaryDirectory() } diff --git a/Tests/SwiftDocCTests/Converter/DocumentationConverterTests.swift b/Tests/SwiftDocCTests/Converter/DocumentationConverterTests.swift index 7669f6985a..e68fead2fe 100644 --- a/Tests/SwiftDocCTests/Converter/DocumentationConverterTests.swift +++ b/Tests/SwiftDocCTests/Converter/DocumentationConverterTests.swift @@ -26,9 +26,7 @@ class DocumentationConverterTests: XCTestCase { } func testThrowsErrorOnConvertingNoBundles() throws { - let rootURL = FileManager.default.temporaryDirectory.appendingPathComponent(#function, isDirectory: true) - try FileManager.default.createDirectory(at: rootURL, withIntermediateDirectories: false) - defer { try? FileManager.default.removeItem(at: rootURL) } + let rootURL = try createTemporaryDirectory() let dataProvider = try LocalFileSystemDataProvider(rootURL: rootURL) let workspace = DocumentationWorkspace() diff --git a/Tests/SwiftDocCTests/ShadowFileManagerTemporaryDirectory.swift b/Tests/SwiftDocCTests/ShadowFileManagerTemporaryDirectory.swift new file mode 100644 index 0000000000..c7602c156f --- /dev/null +++ b/Tests/SwiftDocCTests/ShadowFileManagerTemporaryDirectory.swift @@ -0,0 +1,23 @@ +/* + This source file is part of the Swift.org open source project + + Copyright (c) 2021 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 +*/ + +import Foundation +import XCTest + +// This file exists to shadow `FileManager.temporaryDirectory` in unit tests to warn about potentially referencing a shared location if multiple checkouts run tests at the same time in Swift CI. + +extension FileManager { + + @available(*, deprecated, message: "Use `createTemporaryDirectory` instead in unit tests to avoid referencing a shared location in Swift CI.") + var temporaryDirectory: URL { + XCTFail("Use `createTemporaryDirectory` instead in unit tests to avoid referencing a shared location in Swift CI.") + return URL(fileURLWithPath: Foundation.NSTemporaryDirectory()) + } +} diff --git a/Tests/SwiftDocCUtilitiesTests/ConvertActionTests.swift b/Tests/SwiftDocCUtilitiesTests/ConvertActionTests.swift index a57a5e5133..5be793cd08 100644 --- a/Tests/SwiftDocCUtilitiesTests/ConvertActionTests.swift +++ b/Tests/SwiftDocCUtilitiesTests/ConvertActionTests.swift @@ -1840,17 +1840,7 @@ class ConvertActionTests: XCTestCase { ]) // The navigator index needs to test with the real File Manager - let testTemporaryDirectory = FileManager.default.temporaryDirectory.appendingPathComponent( - "\(#function)-\(UUID())" - ) - try FileManager.default.createDirectory( - at: testTemporaryDirectory, - withIntermediateDirectories: true, - attributes: nil - ) - defer { - try? FileManager.default.removeItem(at: testTemporaryDirectory) - } + let testTemporaryDirectory = try createTemporaryDirectory() let bundleDirectory = testTemporaryDirectory.appendingPathComponent( bundle.name, @@ -1907,18 +1897,7 @@ class ConvertActionTests: XCTestCase { enableFeatureFlag(\.isExperimentalObjectiveCSupportEnabled) // The navigator index needs to test with the real File Manager - let temporaryTestOutputDirectory = FileManager.default.temporaryDirectory.appendingPathComponent( - "\(#function)-\(UUID())" - ) - try FileManager.default.createDirectory( - at: temporaryTestOutputDirectory, - withIntermediateDirectories: true, - attributes: nil - ) - - defer { - try? FileManager.default.removeItem(at: temporaryTestOutputDirectory) - } + let temporaryTestOutputDirectory = try createTemporaryDirectory() let bundleDirectory = try XCTUnwrap( Bundle.module.url( diff --git a/Tests/SwiftDocCUtilitiesTests/ShadowFileManagerTemporaryDirectory.swift b/Tests/SwiftDocCUtilitiesTests/ShadowFileManagerTemporaryDirectory.swift new file mode 100644 index 0000000000..c7602c156f --- /dev/null +++ b/Tests/SwiftDocCUtilitiesTests/ShadowFileManagerTemporaryDirectory.swift @@ -0,0 +1,23 @@ +/* + This source file is part of the Swift.org open source project + + Copyright (c) 2021 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 +*/ + +import Foundation +import XCTest + +// This file exists to shadow `FileManager.temporaryDirectory` in unit tests to warn about potentially referencing a shared location if multiple checkouts run tests at the same time in Swift CI. + +extension FileManager { + + @available(*, deprecated, message: "Use `createTemporaryDirectory` instead in unit tests to avoid referencing a shared location in Swift CI.") + var temporaryDirectory: URL { + XCTFail("Use `createTemporaryDirectory` instead in unit tests to avoid referencing a shared location in Swift CI.") + return URL(fileURLWithPath: Foundation.NSTemporaryDirectory()) + } +} From d71cc3805bf62d725181f19fee9bb0a4f1debb49 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Ro=CC=88nnqvist?= Date: Wed, 22 Dec 2021 13:32:04 -0800 Subject: [PATCH 14/16] Add temp directory test helper variant with "named" argument This is clearer at the call site when only a single path component is specified. --- .../XCTestCase+TemporaryDirectory.swift | 12 ++++++++++++ Tests/SwiftDocCTests/Benchmark/OutputSizeTests.swift | 2 +- .../Infrastructure/DocumentationContextTests.swift | 2 +- .../SwiftDocCTests/XCTestCase+LoadingTestData.swift | 2 +- .../ArgumentParsing/ConvertSubcommandTests.swift | 2 +- .../ArgumentParsing/ErrorMessageTests.swift | 2 +- .../DirectoryMonitorTests.swift | 6 +++--- 7 files changed, 20 insertions(+), 8 deletions(-) diff --git a/Sources/SwiftDocCTestUtilities/XCTestCase+TemporaryDirectory.swift b/Sources/SwiftDocCTestUtilities/XCTestCase+TemporaryDirectory.swift index 0af918bc9c..2389e18798 100644 --- a/Sources/SwiftDocCTestUtilities/XCTestCase+TemporaryDirectory.swift +++ b/Sources/SwiftDocCTestUtilities/XCTestCase+TemporaryDirectory.swift @@ -30,6 +30,18 @@ public extension XCTestCase { return Foundation.NSTemporaryDirectory() } + /// Creates a new temporary directory and returns the URL of that directory. + /// + /// After the current test method has returned the temporary directory is automatically removed. + /// + /// - Parameters: + /// - pathComponents: The name of the temporary directory. + /// - fileManager: The file manager that will create the directory. + /// - Returns: The URL of the newly created directory. + func createTemporaryDirectory(named: String, fileManager: FileManager = .default) throws -> URL { + try createTemporaryDirectory(pathComponents: named) + } + /// Creates a new temporary directory and returns the URL of that directory. /// /// After the current test method has returned the temporary directory is automatically removed. diff --git a/Tests/SwiftDocCTests/Benchmark/OutputSizeTests.swift b/Tests/SwiftDocCTests/Benchmark/OutputSizeTests.swift index e6e7e60f49..bc2a8d94a8 100644 --- a/Tests/SwiftDocCTests/Benchmark/OutputSizeTests.swift +++ b/Tests/SwiftDocCTests/Benchmark/OutputSizeTests.swift @@ -14,7 +14,7 @@ import XCTest class OutputSizeTests: XCTestCase { func testOutputSize() throws { // Create a faux output folder - let writeURL = try createTemporaryDirectory(pathComponents: "data") + let writeURL = try createTemporaryDirectory(named: "data") // Write a 2MB file let data = Data(repeating: 1, count: 2 * 1024 * 1024) diff --git a/Tests/SwiftDocCTests/Infrastructure/DocumentationContextTests.swift b/Tests/SwiftDocCTests/Infrastructure/DocumentationContextTests.swift index 94dddffc91..4f5d366c7b 100644 --- a/Tests/SwiftDocCTests/Infrastructure/DocumentationContextTests.swift +++ b/Tests/SwiftDocCTests/Infrastructure/DocumentationContextTests.swift @@ -1825,7 +1825,7 @@ let expected = """ ("file:///path with spaces/to/file.swift", "file:///path%20with%20spaces/to/file.swift"), ] { // Create an empty bundle - let targetURL = try createTemporaryDirectory(pathComponents: "test.docc") + let targetURL = try createTemporaryDirectory(named: "test.docc") // Copy test Info.plist try FileManager.default.copyItem(at: Bundle.module.url( diff --git a/Tests/SwiftDocCTests/XCTestCase+LoadingTestData.swift b/Tests/SwiftDocCTests/XCTestCase+LoadingTestData.swift index ad00b7271b..945c73cd81 100644 --- a/Tests/SwiftDocCTests/XCTestCase+LoadingTestData.swift +++ b/Tests/SwiftDocCTests/XCTestCase+LoadingTestData.swift @@ -39,7 +39,7 @@ extension XCTestCase { let sourceExists = FileManager.default.fileExists(atPath: sourceURL.path) let bundleURL = sourceExists ? try createTemporaryDirectory().appendingPathComponent("\(name).docc") - : try createTemporaryDirectory(pathComponents: "\(name).docc") + : try createTemporaryDirectory(named: "\(name).docc") if sourceExists { try FileManager.default.copyItem(at: sourceURL, to: bundleURL) diff --git a/Tests/SwiftDocCUtilitiesTests/ArgumentParsing/ConvertSubcommandTests.swift b/Tests/SwiftDocCUtilitiesTests/ArgumentParsing/ConvertSubcommandTests.swift index 49b1b9e19a..3be34ed636 100644 --- a/Tests/SwiftDocCUtilitiesTests/ArgumentParsing/ConvertSubcommandTests.swift +++ b/Tests/SwiftDocCUtilitiesTests/ArgumentParsing/ConvertSubcommandTests.swift @@ -22,7 +22,7 @@ class ConvertSubcommandTests: XCTestCase { func testOptionsValidation() throws { // create source bundle directory - let sourceURL = try createTemporaryDirectory(pathComponents: "documentation") + let sourceURL = try createTemporaryDirectory(named: "documentation") try "".write(to: sourceURL.appendingPathComponent("Info.plist"), atomically: true, encoding: .utf8) // create template dir diff --git a/Tests/SwiftDocCUtilitiesTests/ArgumentParsing/ErrorMessageTests.swift b/Tests/SwiftDocCUtilitiesTests/ArgumentParsing/ErrorMessageTests.swift index 98b9022ab2..e5ea02cb8e 100644 --- a/Tests/SwiftDocCUtilitiesTests/ArgumentParsing/ErrorMessageTests.swift +++ b/Tests/SwiftDocCUtilitiesTests/ArgumentParsing/ErrorMessageTests.swift @@ -16,7 +16,7 @@ class ErrorMessageTests: XCTestCase { func testInvalidParameterMessageError() throws { // create source bundle directory - let sourceURL = try createTemporaryDirectory(pathComponents: "documentation") + let sourceURL = try createTemporaryDirectory(named: "documentation") try "".write(to: sourceURL.appendingPathComponent("Info.plist"), atomically: true, encoding: .utf8) // create renderer template directory diff --git a/Tests/SwiftDocCUtilitiesTests/DirectoryMonitorTests.swift b/Tests/SwiftDocCUtilitiesTests/DirectoryMonitorTests.swift index 7d2d163864..07a9f9c96d 100644 --- a/Tests/SwiftDocCUtilitiesTests/DirectoryMonitorTests.swift +++ b/Tests/SwiftDocCUtilitiesTests/DirectoryMonitorTests.swift @@ -121,7 +121,7 @@ class DirectoryMonitorTests: XCTestCase { #if !os(Linux) && !os(Android) // Create temp folder & sub-folder. - let tempSubfolderURL = try createTemporaryDirectory(pathComponents: "subfolder") + let tempSubfolderURL = try createTemporaryDirectory(named: "subfolder") let tempFolderURL = tempSubfolderURL.deletingLastPathComponent() // A file URL to update. @@ -170,7 +170,7 @@ class DirectoryMonitorTests: XCTestCase { #if !os(Linux) && !os(Android) // Create temp folder & sub-folder. - let tempSubfolderURL = try createTemporaryDirectory(pathComponents: "subfolder") + let tempSubfolderURL = try createTemporaryDirectory(named: "subfolder") let tempFolderURL = tempSubfolderURL.deletingLastPathComponent() // 1) Test that creating a hidden file inside the tree will not trigger an update. @@ -203,7 +203,7 @@ class DirectoryMonitorTests: XCTestCase { #if !os(Linux) && !os(Android) // Create temp folder & sub-folder. - let tempSubfolderURL = try createTemporaryDirectory(pathComponents: "subfolder") + let tempSubfolderURL = try createTemporaryDirectory(named: "subfolder") let tempFolderURL = tempSubfolderURL.deletingLastPathComponent() // A file URL to update. From 1e5de9f8a992739db5e6e09416fa186ca6f307e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Ro=CC=88nnqvist?= Date: Wed, 22 Dec 2021 13:32:46 -0800 Subject: [PATCH 15/16] Fix test helper syntax in disabled preview server test --- .../PreviewServer/PreviewServerTests.swift | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/Tests/SwiftDocCUtilitiesTests/PreviewServer/PreviewServerTests.swift b/Tests/SwiftDocCUtilitiesTests/PreviewServer/PreviewServerTests.swift index 50db38374d..b4c4b4050a 100644 --- a/Tests/SwiftDocCUtilitiesTests/PreviewServer/PreviewServerTests.swift +++ b/Tests/SwiftDocCUtilitiesTests/PreviewServer/PreviewServerTests.swift @@ -27,8 +27,6 @@ import SwiftDocCTestUtilities class PreviewServerTests { func createTemporaryDirectory( - pathComponents: String..., - createDirectoryForLastPathComponent: Bool = true, fileManager: FileManager = .default ) throws -> URL { fatalError("This test is disabled by not conforming to XCTestCase. This helper is added here to make the code compile. This should never be called.") @@ -44,7 +42,7 @@ class PreviewServerTests { TextFile(name: "index.html", utf8Content: "index"), ]) - let socketURL = try createTemporaryDirectory(pathComponents: "sock", createDirectoryForLastPathComponent: false) + let socketURL = try createTemporaryDirectory().appendingPathComponent("sock") // Run test server var log = LogHandle.none @@ -124,7 +122,7 @@ class PreviewServerTests { let tempFolderURL = try makeTempFolder() // Socket URL - let socketURL = try createTemporaryDirectory(pathComponents: "sock", createDirectoryForLastPathComponent: false) + let socketURL = try createTemporaryDirectory().appendingPathComponent("sock") // Create the server var log = LogHandle.none @@ -171,7 +169,7 @@ class PreviewServerTests { let tempFolderURL = try makeTempFolder() // Socket URL - let socketURL = try createTemporaryDirectory(pathComponents: "sock", createDirectoryForLastPathComponent: false) + let socketURL = try createTemporaryDirectory().appendingPathComponent("sock") // Create the server var log = LogHandle.none From 4dac6a46abe3b39141d3301556cd9677ad461d34 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Ro=CC=88nnqvist?= Date: Wed, 22 Dec 2021 13:35:46 -0800 Subject: [PATCH 16/16] Re-enable one file monitoring test --- .../PreviewActionIntegrationTests.swift | 19 ++++++------------- 1 file changed, 6 insertions(+), 13 deletions(-) diff --git a/Tests/SwiftDocCUtilitiesTests/PreviewActionIntegrationTests.swift b/Tests/SwiftDocCUtilitiesTests/PreviewActionIntegrationTests.swift index 296b7a9c85..731446b391 100644 --- a/Tests/SwiftDocCUtilitiesTests/PreviewActionIntegrationTests.swift +++ b/Tests/SwiftDocCUtilitiesTests/PreviewActionIntegrationTests.swift @@ -71,18 +71,13 @@ class PreviewActionIntegrationTests: XCTestCase { return (sourceURL: sourceURL, outputURL: outputURL, templateURL: templateURL) } - // FIXME: This test can fail when run in parallel so it is temporarily disabled (rdar://81524725). - /// Test the fix for . - func skip_testWatchRecoversAfterConversionErrors() throws { + func testWatchRecoversAfterConversionErrors() throws { #if os(macOS) // Source files. let source = createMinimalDocsBundle() let (sourceURL, outputURL, templateURL) = try createPreviewSetup(source: source) - let sourceOverviewURL = sourceURL.appendingPathComponent("Resources") - .appendingPathComponent("Overview.tutorial") - let logStorage = LogHandle.LogStorage() var logHandle = LogHandle.memory(logStorage) @@ -182,14 +177,14 @@ class PreviewActionIntegrationTests: XCTestCase { XCTAssertEqual(initialIntroTitle, "Technology X") + let invalidJSONSymbolGraphURL = sourceURL.appendingPathComponent("invalid-incomplete-data.symbols.json") + // Start watching the source and detect failed conversion. do { let outputExpectation = asyncLogExpectation(log: logStorage, description: "Did produce output") { $0.contains("Compilation failed") } - // Triger a watch update. - try String(contentsOf: sourceOverviewURL) - .replacingOccurrences(of: "title: \"Technology X\"", with: "ti!!!!!!tle: \"Technology X\"") - .write(to: sourceOverviewURL, atomically: true, encoding: .utf8) + // this is invalid JSON and will result in an error + try "{".write(to: invalidJSONSymbolGraphURL, atomically: true, encoding: .utf8) // Wait for watch to produce output. wait(for: [outputExpectation], timeout: 20.0) @@ -199,9 +194,7 @@ class PreviewActionIntegrationTests: XCTestCase { do { let outputExpectation = asyncLogExpectation(log: logStorage, description: "Did finish conversion") { $0.contains("Done") } - try String(contentsOf: sourceOverviewURL) - .replacingOccurrences(of: "ti!!!!!!tle: \"Technology X\"", with: "title: \"Technology X\"") - .write(to: sourceOverviewURL, atomically: true, encoding: .utf8) + try FileManager.default.removeItem(at: invalidJSONSymbolGraphURL) // Wait for watch to produce output. wait(for: [outputExpectation], timeout: 20.0)