import Foundation import Testing @Suite("File System Operation Tests", .tags(.fileSystem)) struct FileSystemTests { // MARK: - Path Operations @Test("Path normalization and resolution") func pathNormalization() { // Test path normalization func normalizePath(_ path: String) -> String { (path as NSString).standardizingPath } #expect(normalizePath("/Users/test/./Documents") == "/Users/test/Documents") #expect(normalizePath("/Users/test/../test/Documents") == "/Users/test/Documents") #expect(normalizePath("~/Documents") != "~/Documents") // Should expand tilde #expect(normalizePath("/Users//test///Documents") == "/Users/test/Documents") } @Test("File extension handling") func fileExtensions() { struct FileInfo { let path: String var filename: String { (path as NSString).lastPathComponent } var `extension`: String { (path as NSString).pathExtension } var nameWithoutExtension: String { (filename as NSString).deletingPathExtension } func appendingExtension(_ ext: String) -> String { (path as NSString).appendingPathExtension(ext) ?? path } } let file = FileInfo(path: "/Users/test/document.txt") #expect(file.filename == "document.txt") #expect(file.extension == "txt") #expect(file.nameWithoutExtension == "document") let noExtFile = FileInfo(path: "/Users/test/README") #expect(noExtFile.extension == "") #expect(noExtFile.nameWithoutExtension == "README") } // MARK: - File Permissions @Test("File permission checks") func filePermissions() { struct FilePermissions { let isReadable: Bool let isWritable: Bool let isExecutable: Bool let isDeletable: Bool var octalRepresentation: String { var value = 0 if isReadable { value += 4 } if isWritable { value += 2 } if isExecutable { value += 1 } return String(value) } } let readOnly = FilePermissions( isReadable: true, isWritable: false, isExecutable: false, isDeletable: false ) #expect(readOnly.octalRepresentation == "4") let readWrite = FilePermissions( isReadable: true, isWritable: true, isExecutable: false, isDeletable: true ) #expect(readWrite.octalRepresentation == "6") let executable = FilePermissions( isReadable: true, isWritable: false, isExecutable: true, isDeletable: false ) #expect(executable.octalRepresentation == "5") } // MARK: - Directory Operations @Test("Directory traversal and listing") func directoryTraversal() { struct DirectoryEntry { let name: String let isDirectory: Bool let size: Int64? let modificationDate: Date? var type: String { isDirectory ? "directory" : "file" } } // Test directory entry creation let fileEntry = DirectoryEntry( name: "test.txt", isDirectory: false, size: 1_024, modificationDate: Date() ) #expect(fileEntry.type == "file") #expect(fileEntry.size == 1_024) let dirEntry = DirectoryEntry( name: "Documents", isDirectory: true, size: nil, modificationDate: Date() ) #expect(dirEntry.type == "directory") #expect(dirEntry.size == nil) } @Test("Recursive directory size calculation") func directorySizeCalculation() { // Simulate directory size calculation func calculateDirectorySize(files: [(name: String, size: Int64)]) -> Int64 { files.reduce(0) { $0 + $1.size } } let files = [ ("file1.txt", Int64(1_024)), ("file2.doc", Int64(2_048)), ("image.jpg", Int64(4_096)) ] let totalSize = calculateDirectorySize(files: files) #expect(totalSize == 7_168) // Test size formatting func formatFileSize(_ bytes: Int64) -> String { let formatter = ByteCountFormatter() formatter.countStyle = .file return formatter.string(fromByteCount: bytes) } #expect(!formatFileSize(1_024).isEmpty) #expect(!formatFileSize(1_048_576).isEmpty) // 1 MB } // MARK: - File Operations @Test("Safe file operations") func safeFileOperations() { enum FileOperation { case read case write case delete case move(to: String) case copy(to: String) var requiresWritePermission: Bool { switch self { case .read: false case .write, .delete, .move, .copy: true } } } #expect(FileOperation.read.requiresWritePermission == false) #expect(FileOperation.write.requiresWritePermission == true) #expect(FileOperation.delete.requiresWritePermission == true) #expect(FileOperation.move(to: "/tmp/file").requiresWritePermission == true) } @Test("Atomic file writing") func atomicFileWriting() { struct AtomicFileWriter { let destinationPath: String var temporaryPath: String { destinationPath + ".tmp" } func writeSteps() -> [String] { [ "Write to temporary file: \(temporaryPath)", "Verify temporary file integrity", "Atomically rename to: \(destinationPath)", "Clean up any failed attempts" ] } } let writer = AtomicFileWriter(destinationPath: "/Users/test/important.dat") let steps = writer.writeSteps() #expect(steps.count == 4) #expect(writer.temporaryPath == "/Users/test/important.dat.tmp") } // MARK: - File Watching @Test("File change detection") func fileChangeDetection() { struct FileSnapshot { let path: String let size: Int64 let modificationDate: Date let contentHash: String func hasChanged(comparedTo other: FileSnapshot) -> Bool { size != other.size || modificationDate != other.modificationDate || contentHash != other.contentHash } } let snapshot1 = FileSnapshot( path: "/test/file.txt", size: 1_024, modificationDate: Date(), contentHash: "abc123" ) let snapshot2 = FileSnapshot( path: "/test/file.txt", size: 1_024, modificationDate: Date().addingTimeInterval(10), contentHash: "abc123" ) let snapshot3 = FileSnapshot( path: "/test/file.txt", size: 2_048, modificationDate: Date().addingTimeInterval(20), contentHash: "def456" ) #expect(!snapshot1.hasChanged(comparedTo: snapshot1)) #expect(snapshot1.hasChanged(comparedTo: snapshot2)) // Different date #expect(snapshot1.hasChanged(comparedTo: snapshot3)) // Different size and hash } // MARK: - Sandbox and Security @Test("Sandbox path validation") func sandboxPaths() { struct SandboxValidator { let appGroupIdentifier = "group.com.vibetunnel" var documentsDirectory: String { "~/Documents" } var temporaryDirectory: String { NSTemporaryDirectory() } var appGroupDirectory: String { "~/Library/Group Containers/\(appGroupIdentifier)" } func isWithinSandbox(_ path: String) -> Bool { let normalizedPath = (path as NSString).standardizingPath let expandedDocs = (documentsDirectory as NSString).expandingTildeInPath let expandedAppGroup = (appGroupDirectory as NSString).expandingTildeInPath return normalizedPath.hasPrefix(expandedDocs) || normalizedPath.hasPrefix(temporaryDirectory) || normalizedPath.hasPrefix(expandedAppGroup) } } let validator = SandboxValidator() #expect(validator.isWithinSandbox("~/Documents/file.txt")) #expect(validator.isWithinSandbox(NSTemporaryDirectory() + "temp.dat")) #expect(!validator.isWithinSandbox("/System/Library/file.txt")) } // MARK: - File Type Detection @Test("MIME type detection") func mIMETypeDetection() { func mimeType(for fileExtension: String) -> String { let mimeTypes: [String: String] = [ "txt": "text/plain", "html": "text/html", "json": "application/json", "pdf": "application/pdf", "jpg": "image/jpeg", "png": "image/png", "mp4": "video/mp4", "zip": "application/zip" ] return mimeTypes[fileExtension.lowercased()] ?? "application/octet-stream" } #expect(mimeType(for: "txt") == "text/plain") #expect(mimeType(for: "JSON") == "application/json") #expect(mimeType(for: "unknown") == "application/octet-stream") } @Test("Text encoding detection") func textEncodingDetection() { // Test BOM (Byte Order Mark) detection func detectEncoding(from bom: [UInt8]) -> String.Encoding? { if bom.starts(with: [0xEF, 0xBB, 0xBF]) { return .utf8 } else if bom.starts(with: [0xFF, 0xFE]) { return .utf16LittleEndian } else if bom.starts(with: [0xFE, 0xFF]) { return .utf16BigEndian } else if bom.starts(with: [0xFF, 0xFE, 0x00, 0x00]) { return .utf32LittleEndian } else if bom.starts(with: [0x00, 0x00, 0xFE, 0xFF]) { return .utf32BigEndian } return nil } #expect(detectEncoding(from: [0xEF, 0xBB, 0xBF]) == .utf8) #expect(detectEncoding(from: [0xFF, 0xFE]) == .utf16LittleEndian) #expect(detectEncoding(from: [0x41, 0x42]) == nil) // No BOM } // MARK: - URL and Path Conversion @Test("URL to path conversion") func uRLPathConversion() { func filePathFromURL(_ urlString: String) -> String? { guard let url = URL(string: urlString), url.isFileURL else { return nil } return url.path } #expect(filePathFromURL("file:///Users/test/file.txt") == "/Users/test/file.txt") #expect(filePathFromURL("file://localhost/Users/test/file.txt") == "/Users/test/file.txt") #expect(filePathFromURL("https://example.com/file.txt") == nil) // Test path to URL conversion func fileURLFromPath(_ path: String) -> URL? { URL(fileURLWithPath: path) } let url = fileURLFromPath("/Users/test/file.txt") #expect(url?.isFileURL == true) #expect(url?.path == "/Users/test/file.txt") } }