RadrootsAppleFileRootsTests.swift (3867B)
1 import Foundation 2 import Testing 3 @testable import RadrootsKit 4 5 @Test func fileRootsDeriveDefaultLogsAndStagedBlobRoots() throws { 6 let root = FileManager.default.temporaryDirectory 7 .appendingPathComponent("radroots-file-roots-\(UUID().uuidString)", isDirectory: true) 8 let roots = try RadrootsAppleFileRoots( 9 appIdentifier: " org.radroots.tests ", 10 dataRoot: root.appendingPathComponent("data", isDirectory: true), 11 cacheRoot: root.appendingPathComponent("cache", isDirectory: true), 12 temporaryRoot: root.appendingPathComponent("tmp", isDirectory: true) 13 ) 14 15 #expect(roots.appIdentifier == "org.radroots.tests") 16 #expect(roots.logsRoot == roots.cacheRoot.appendingPathComponent("Logs", isDirectory: true).standardizedFileURL) 17 #expect(roots.stagedBlobsRoot == roots.temporaryRoot.appendingPathComponent("staged_blobs", isDirectory: true).standardizedFileURL) 18 } 19 20 @Test func fileRootsRejectBlankAppIdentifier() throws { 21 let root = FileManager.default.temporaryDirectory 22 #expect(throws: RadrootsAppleFileError.self) { 23 _ = try RadrootsAppleFileRoots( 24 appIdentifier: " ", 25 dataRoot: root, 26 cacheRoot: root, 27 temporaryRoot: root 28 ) 29 } 30 } 31 32 @Test func fileRootsRejectNonFileURLs() throws { 33 let root = FileManager.default.temporaryDirectory 34 #expect(throws: RadrootsAppleFileError.self) { 35 _ = try RadrootsAppleFileRoots( 36 appIdentifier: "org.radroots.tests", 37 dataRoot: URL(string: "https://radroots.org/data")!, 38 cacheRoot: root, 39 temporaryRoot: root 40 ) 41 } 42 } 43 44 @Test func fileReferenceResolvesInsideSelectedScope() throws { 45 let root = FileManager.default.temporaryDirectory 46 .appendingPathComponent("radroots-file-roots-\(UUID().uuidString)", isDirectory: true) 47 let roots = try RadrootsAppleFileRoots( 48 appIdentifier: "org.radroots.tests", 49 dataRoot: root.appendingPathComponent("data", isDirectory: true), 50 cacheRoot: root.appendingPathComponent("cache", isDirectory: true), 51 temporaryRoot: root.appendingPathComponent("tmp", isDirectory: true) 52 ) 53 let file = RadrootsFileReference(scope: .data, relativePath: "identity/public.json") 54 55 #expect(try roots.resolvedURL(for: file) == roots.dataRoot.appendingPathComponent("identity/public.json").standardizedFileURL) 56 } 57 58 @Test func fileReferenceRejectsAbsolutePath() throws { 59 let roots = try testFileRoots() 60 let file = RadrootsFileReference(scope: .cache, relativePath: "/tmp/escape") 61 62 #expect(throws: RadrootsAppleFileError.self) { 63 _ = try roots.resolvedURL(for: file) 64 } 65 } 66 67 @Test func fileReferenceRejectsPathTraversal() throws { 68 let roots = try testFileRoots() 69 let file = RadrootsFileReference(scope: .data, relativePath: "../escape") 70 71 #expect(throws: RadrootsAppleFileError.self) { 72 _ = try roots.resolvedURL(for: file) 73 } 74 } 75 76 @Test func fileReferenceAllowsRootOnlyWhenRequested() throws { 77 let roots = try testFileRoots() 78 let rootFile = RadrootsFileReference(scope: .logs, relativePath: " ") 79 80 #expect(try roots.resolvedURL(for: rootFile, allowRootDirectory: true) == roots.logsRoot) 81 #expect(throws: RadrootsAppleFileError.self) { 82 _ = try roots.resolvedURL(for: rootFile) 83 } 84 } 85 86 private func testFileRoots() throws -> RadrootsAppleFileRoots { 87 let root = FileManager.default.temporaryDirectory 88 .appendingPathComponent("radroots-file-roots-\(UUID().uuidString)", isDirectory: true) 89 return try RadrootsAppleFileRoots( 90 appIdentifier: "org.radroots.tests", 91 dataRoot: root.appendingPathComponent("data", isDirectory: true), 92 cacheRoot: root.appendingPathComponent("cache", isDirectory: true), 93 temporaryRoot: root.appendingPathComponent("tmp", isDirectory: true) 94 ) 95 }