diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml
index 2903dbbd..7699e3e6 100644
--- a/.github/workflows/test.yml
+++ b/.github/workflows/test.yml
@@ -23,26 +23,22 @@ jobs:
fail-fast: false
matrix:
swift-version:
- - 5.10
- 6.0
- 6.1
+ - 6.2
include:
- - { swift-version: 5.10, swift-branch: swift-5.10.1-release, swift-tag: 5.10.1-RELEASE }
- { swift-version: 6.0, swift-branch: swift-6.0.3-release, swift-tag: 6.0.3-RELEASE }
- - { swift-version: 6.1, swift-branch: swift-6.1-release, swift-tag: 6.1-RELEASE }
+ - { swift-version: 6.1, swift-branch: swift-6.1.3-release, swift-tag: 6.1.3-RELEASE }
+ - { swift-version: 6.2, swift-branch: swift-6.2-release, swift-tag: 6.2-RELEASE }
runs-on: windows-latest
timeout-minutes: 60
steps:
- - name: Configure dev environment
- uses: compnerd/gha-setup-vsdevenv@main
- with:
- toolset_version: 14.29
- winsdk: 10.0.22621.0
- name: Install Windows Swift toolchain
uses: compnerd/gha-setup-swift@main
with:
- branch: ${{ matrix.swift-branch }}
- tag: ${{ matrix.swift-tag }}
+ swift-version: ${{ matrix.swift-branch }}
+ swift-build: ${{ matrix.swift-tag }}
+ update-sdk-modules: true
- name: Download zlib
run: |
curl -L -o zlib.zip https://www.zlib.net/zlib131.zip
@@ -57,7 +53,8 @@ jobs:
cmake --build . --config Release
cmake --install . --prefix ../install
- name: Check out code
- uses: actions/checkout@v4
+ uses: actions/checkout@v5
- name: Run unit tests
run: |
- swift test -Xcc -I'C:/Program Files (x86)/zlib/include' -Xcc -D_INTSAFE_H_INCLUDED_ -Xlinker -L'C:/Program Files (x86)/zlib/lib' -Xbuild-tools-swiftc -windows-sdk-root -Xbuild-tools-swiftc "${env:WindowsSdkDir}" -Xbuild-tools-swiftc -windows-sdk-version -Xbuild-tools-swiftc ${env:UCRTVersion} -Xswiftc -windows-sdk-root -Xswiftc "${env:WindowsSdkDir}" -Xswiftc -windows-sdk-version -Xswiftc ${env:UCRTVersion}
+ swift test -Xcc -I'C:/Program Files (x86)/zlib/include' -Xcc -D_INTSAFE_H_INCLUDED_ -Xlinker -L'C:/Program Files (x86)/zlib/lib'
+ #-Xbuild-tools-swiftc -windows-sdk-root -Xbuild-tools-swiftc "${env:WindowsSdkDir}" -Xbuild-tools-swiftc -windows-sdk-version -Xbuild-tools-swiftc ${env:UCRTVersion} -Xswiftc -windows-sdk-root -Xswiftc "${env:WindowsSdkDir}" -Xswiftc -windows-sdk-version -Xswiftc ${env:UCRTVersion}
diff --git a/.swift-format b/.swift-format
index dea65687..1268f53b 100644
--- a/.swift-format
+++ b/.swift-format
@@ -5,7 +5,7 @@
"indentation": {
"spaces": 4
},
- "indentConditionalCompilationBlocks": true,
+ "indentConditionalCompilationBlocks": false,
"indentSwitchCaseLabels": false,
"lineBreakAroundMultilineExpressionChainComponents": false,
"lineBreakBeforeControlFlowKeywords": false,
diff --git a/Package.swift b/Package.swift
index 6ef4951f..72614189 100644
--- a/Package.swift
+++ b/Package.swift
@@ -1,12 +1,6 @@
-// swift-tools-version:5.10
+// swift-tools-version:6.0
import PackageDescription
-#if canImport(Darwin) || compiler(<6.0)
- import Foundation
-#else
- import FoundationEssentials
-#endif
-
let package = Package(
name: "Zip",
products: [
@@ -45,25 +39,19 @@ let package = Package(
var swiftSettings: [SwiftSetting] {
[
- .enableUpcomingFeature("ExistentialAny"),
- .enableUpcomingFeature("ConciseMagicFile"),
- .enableUpcomingFeature("ForwardTrailingClosures"),
- .enableUpcomingFeature("DisableOutwardActorInference"),
- .enableUpcomingFeature("StrictConcurrency"),
- .enableExperimentalFeature("StrictConcurrency=complete"),
- .enableExperimentalFeature("AccessLevelOnImport"),
+ .enableUpcomingFeature("ExistentialAny")
]
}
-if let target = package.targets.filter({ $0.name == "CMinizip" }).first {
+if let target = package.targets.first(where: { $0.name == "CMinizip" }) {
#if os(Windows)
- if ProcessInfo.processInfo.environment["ZIP_USE_DYNAMIC_ZLIB"] == nil {
- target.cSettings?.append(contentsOf: [.define("ZLIB_STATIC")])
- target.linkerSettings = [.linkedLibrary("zlibstatic")]
- } else {
- target.linkerSettings = [.linkedLibrary("zlib")]
- }
+ if Context.environment["ZIP_USE_DYNAMIC_ZLIB"] == nil {
+ target.cSettings?.append(contentsOf: [.define("ZLIB_STATIC")])
+ target.linkerSettings = [.linkedLibrary("zlibstatic")]
+ } else {
+ target.linkerSettings = [.linkedLibrary("zlib")]
+ }
#else
- target.linkerSettings = [.linkedLibrary("z")]
+ target.linkerSettings = [.linkedLibrary("z")]
#endif
}
diff --git a/README.md b/README.md
index 57df6a85..ec6eff1e 100644
--- a/README.md
+++ b/README.md
@@ -9,10 +9,10 @@
-
+
-
+
@@ -40,7 +40,7 @@ and add it to your target's dependencies:
### Supported Platforms
-Zip supports all platforms supported by Swift 5.10 and later.
+Zip supports all platforms supported by Swift 6.0 and later.
To use Zip on Windows, you need to pass an available build of `zlib` to the build via extended flags. For example:
diff --git a/Sources/Zip/Date+dosDate.swift b/Sources/Zip/Date+dosDate.swift
index d4834282..aea5d5aa 100644
--- a/Sources/Zip/Date+dosDate.swift
+++ b/Sources/Zip/Date+dosDate.swift
@@ -1,7 +1,7 @@
-#if canImport(Darwin) || compiler(<6.0)
- import Foundation
+#if canImport(FoundationEssentials)
+import FoundationEssentials
#else
- import FoundationEssentials
+import Foundation
#endif
extension Date {
diff --git a/Sources/Zip/QuickZip.swift b/Sources/Zip/QuickZip.swift
index 5d7fdc00..a89b29bd 100644
--- a/Sources/Zip/QuickZip.swift
+++ b/Sources/Zip/QuickZip.swift
@@ -6,10 +6,10 @@
// Copyright © 2016 Roy Marmelstein. All rights reserved.
//
-#if canImport(Darwin) || compiler(<6.0)
- import Foundation
+#if canImport(FoundationEssentials)
+import FoundationEssentials
#else
- import FoundationEssentials
+import Foundation
#endif
extension Zip {
@@ -23,7 +23,7 @@ extension Zip {
///
/// - Returns: `URL` of the destination folder.
public class func quickUnzipFile(_ path: URL) throws -> URL {
- return try quickUnzipFile(path, progress: nil)
+ try quickUnzipFile(path, progress: nil)
}
/// Unzips a file with less configuration.
@@ -57,7 +57,7 @@ extension Zip {
///
/// - Returns: `URL` of the destination folder.
public class func quickZipFiles(_ paths: [URL], fileName: String) throws -> URL {
- return try quickZipFiles(paths, fileName: fileName, progress: nil)
+ try quickZipFiles(paths, fileName: fileName, progress: nil)
}
/// Zips files with less configuration.
diff --git a/Sources/Zip/URL+nativePath.swift b/Sources/Zip/URL+nativePath.swift
index f15e2a5d..6d6227e5 100644
--- a/Sources/Zip/URL+nativePath.swift
+++ b/Sources/Zip/URL+nativePath.swift
@@ -1,11 +1,11 @@
-#if canImport(Darwin) || compiler(<6.0)
- import Foundation
+#if canImport(FoundationEssentials)
+import FoundationEssentials
#else
- import FoundationEssentials
+import Foundation
#endif
extension URL {
var nativePath: String {
- return withUnsafeFileSystemRepresentation { String(cString: $0!) }
+ withUnsafeFileSystemRepresentation { String(cString: $0!) }
}
}
diff --git a/Sources/Zip/Zip.docc/Documentation.md b/Sources/Zip/Zip.docc/Documentation.md
index 5c875293..0c7959b8 100644
--- a/Sources/Zip/Zip.docc/Documentation.md
+++ b/Sources/Zip/Zip.docc/Documentation.md
@@ -31,7 +31,7 @@ and add it to your target's dependencies:
### Supported Platforms
-Zip supports all platforms supported by Swift 5.10 and later.
+Zip supports all platforms supported by Swift 6.0 and later.
To use Zip on Windows, you need to pass an available build of `zlib` to the build via extended flags. For example:
diff --git a/Sources/Zip/Zip.swift b/Sources/Zip/Zip.swift
index 75d44475..c4d5a3ca 100644
--- a/Sources/Zip/Zip.swift
+++ b/Sources/Zip/Zip.swift
@@ -66,7 +66,7 @@ public class Zip {
}
#if os(Windows)
- var fileNames = Set()
+ var fileNames = Set()
#endif
var buffer = [CUnsignedChar](repeating: 0, count: 4096)
@@ -101,23 +101,23 @@ public class Zip {
var pathString = String(cString: fileName)
#if os(Windows)
- // Windows Reserved Characters
- let reservedCharacters: CharacterSet = ["<", ">", ":", "\"", "|", "?", "*"]
-
- if pathString.rangeOfCharacter(from: reservedCharacters) != nil {
- pathString = pathString.components(separatedBy: reservedCharacters).joined(separator: "_")
-
- let pathExtension = (pathString as NSString).pathExtension
- let pathWithoutExtension = (pathString as NSString).deletingPathExtension
- var counter = 1
- while fileNames.contains(pathString) {
- let newFileName = "\(pathWithoutExtension) (\(counter))"
- pathString = pathExtension.isEmpty ? newFileName : newFileName.appendingPathExtension(pathExtension) ?? newFileName
- counter += 1
- }
+ // Windows Reserved Characters
+ let reservedCharacters: CharacterSet = ["<", ">", ":", "\"", "|", "?", "*"]
+
+ if pathString.rangeOfCharacter(from: reservedCharacters) != nil {
+ pathString = pathString.components(separatedBy: reservedCharacters).joined(separator: "_")
+
+ let pathExtension = (pathString as NSString).pathExtension
+ let pathWithoutExtension = (pathString as NSString).deletingPathExtension
+ var counter = 1
+ while fileNames.contains(pathString) {
+ let newFileName = "\(pathWithoutExtension) (\(counter))"
+ pathString = pathExtension.isEmpty ? newFileName : newFileName.appendingPathExtension(pathExtension) ?? newFileName
+ counter += 1
}
+ }
- fileNames.insert(pathString)
+ fileNames.insert(pathString)
#endif
guard !pathString.isEmpty else {
@@ -136,16 +136,11 @@ public class Zip {
throw ZipError.unzipFail
}
- let directoryAttributes: [FileAttributeKey: Any]?
- #if (os(Linux) || os(Windows)) && compiler(<6.0)
- directoryAttributes = nil
- #else
- let creationDate = Date()
- directoryAttributes = [
- .creationDate: creationDate,
- .modificationDate: creationDate,
- ]
- #endif
+ let creationDate = Date()
+ let directoryAttributes: [FileAttributeKey: Any]? = [
+ .creationDate: creationDate,
+ .modificationDate: creationDate,
+ ]
let isDirectory =
fileName[Int(fileInfo.size_filename - 1)] == "/".cString(using: String.Encoding.utf8)?.first
diff --git a/Sources/Zip/ZipCompression.swift b/Sources/Zip/ZipCompression.swift
index cd4269ba..cdd196b9 100644
--- a/Sources/Zip/ZipCompression.swift
+++ b/Sources/Zip/ZipCompression.swift
@@ -9,14 +9,10 @@ public enum ZipCompression: Int {
internal var minizipCompression: Int32 {
switch self {
- case .NoCompression:
- return Z_NO_COMPRESSION
- case .BestSpeed:
- return Z_BEST_SPEED
- case .DefaultCompression:
- return Z_DEFAULT_COMPRESSION
- case .BestCompression:
- return Z_BEST_COMPRESSION
+ case .NoCompression: Z_NO_COMPRESSION
+ case .BestSpeed: Z_BEST_SPEED
+ case .DefaultCompression: Z_DEFAULT_COMPRESSION
+ case .BestCompression: Z_BEST_COMPRESSION
}
}
}
diff --git a/Sources/Zip/ZipError.swift b/Sources/Zip/ZipError.swift
index 5bbf0eae..5504e347 100644
--- a/Sources/Zip/ZipError.swift
+++ b/Sources/Zip/ZipError.swift
@@ -1,7 +1,7 @@
-#if canImport(Darwin) || compiler(<6.0)
- import Foundation
+#if canImport(FoundationEssentials)
+import FoundationEssentials
#else
- import FoundationEssentials
+import Foundation
#endif
/// Errors that can be thrown by Zip.
diff --git a/Tests/ZipTests/ZipTests.swift b/Tests/ZipTests/ZipTests.swift
index d94ecced..57122b52 100644
--- a/Tests/ZipTests/ZipTests.swift
+++ b/Tests/ZipTests/ZipTests.swift
@@ -6,196 +6,222 @@
// Copyright © 2015 Roy Marmelstein. All rights reserved.
//
-import XCTest
+import Foundation
+import Testing
@testable import Zip
-final class ZipTests: XCTestCase {
+@Suite("Zip Tests", .serialized)
+struct ZipTests {
private func url(forResource resource: String, withExtension ext: String? = nil) -> URL? {
Bundle.module.url(forResource: "TestResources/\(resource)", withExtension: ext)
}
- private func autoRemovingSandbox() throws -> URL {
+ private func withSandbox(_ block: (URL) throws -> Void) throws {
let sandbox = FileManager.default.temporaryDirectory.appendingPathComponent("ZipTests_" + UUID().uuidString, isDirectory: true)
// We can always create it. UUID should be unique.
try FileManager.default.createDirectory(at: sandbox, withIntermediateDirectories: true, attributes: nil)
- // Schedule the teardown block _after_ the directory has been created (so that if it fails, no teardown block is registered).
- addTeardownBlock {
- do {
- try FileManager.default.removeItem(at: sandbox)
- } catch {
- print("Could not remove test sandbox at '\(sandbox.path)': \(error)")
- }
+
+ try block(sandbox)
+
+ do {
+ try FileManager.default.removeItem(at: sandbox)
+ } catch {
+ print("Could not remove test sandbox at '\(sandbox.path)': \(error)")
}
- return sandbox
}
- func testQuickUnzip() throws {
+ @Test("Quick Unzip")
+ func quickUnzip() throws {
let filePath = url(forResource: "bb8", withExtension: "zip")!
let destinationURL = try Zip.quickUnzipFile(filePath)
- addTeardownBlock {
+ defer {
try? FileManager.default.removeItem(at: destinationURL)
}
- XCTAssertTrue(FileManager.default.fileExists(atPath: destinationURL.path))
- try XCTAssertGreaterThan(Data(contentsOf: destinationURL.appendingPathComponent("3crBXeO.gif")).count, 0)
- try XCTAssertGreaterThan(Data(contentsOf: destinationURL.appendingPathComponent("kYkLkPf.gif")).count, 0)
+ #expect(FileManager.default.fileExists(atPath: destinationURL.path))
+ #expect(try !Data(contentsOf: destinationURL.appendingPathComponent("3crBXeO.gif")).isEmpty)
+ #expect(try !Data(contentsOf: destinationURL.appendingPathComponent("kYkLkPf.gif")).isEmpty)
}
- func testQuickUnzipNonExistingPath() {
+ @Test("Quick Unzip with Non-Existing Path")
+ func quickUnzipNonExistingPath() {
let filePath = URL(fileURLWithPath: "/some/path/to/nowhere/bb9.zip")
- XCTAssertThrowsError(try Zip.quickUnzipFile(filePath))
+ #expect(throws: (any Error).self) { try Zip.quickUnzipFile(filePath) }
}
- func testQuickUnzipNonZipPath() {
+ @Test("Quick Unzip with Non-Zip Path")
+ func quickUnzipNonZipPath() {
let filePath = url(forResource: "3crBXeO", withExtension: "gif")!
- XCTAssertThrowsError(try Zip.quickUnzipFile(filePath))
+ #expect(throws: (any Error).self) { try Zip.quickUnzipFile(filePath) }
}
- func testQuickUnzipProgress() throws {
+ @Test("Quick Unzip with Progress")
+ func quickUnzipProgress() throws {
let filePath = url(forResource: "bb8", withExtension: "zip")!
let destinationURL = try Zip.quickUnzipFile(filePath) { progress in
- XCTAssertFalse(progress.isNaN)
+ #expect(!progress.isNaN)
}
- addTeardownBlock {
+ defer {
try? FileManager.default.removeItem(at: destinationURL)
}
- XCTAssertTrue(FileManager.default.fileExists(atPath: destinationURL.path))
- try XCTAssertGreaterThan(Data(contentsOf: destinationURL.appendingPathComponent("3crBXeO.gif")).count, 0)
- try XCTAssertGreaterThan(Data(contentsOf: destinationURL.appendingPathComponent("kYkLkPf.gif")).count, 0)
+ #expect(FileManager.default.fileExists(atPath: destinationURL.path))
+ #expect(try !Data(contentsOf: destinationURL.appendingPathComponent("3crBXeO.gif")).isEmpty)
+ #expect(try !Data(contentsOf: destinationURL.appendingPathComponent("kYkLkPf.gif")).isEmpty)
}
- func testQuickUnzipOnlineURL() {
+ @Test("Quick Unzip with Online URL")
+ func quickUnzipOnlineURL() {
let filePath = URL(string: "http://www.google.com/google.zip")!
- XCTAssertThrowsError(try Zip.quickUnzipFile(filePath))
+ #expect(throws: (any Error).self) { try Zip.quickUnzipFile(filePath) }
}
- func testUnzip() throws {
+ @Test("Unzip")
+ func unzip() throws {
let filePath = url(forResource: "bb8", withExtension: "zip")!
- let destinationPath = try autoRemovingSandbox()
- XCTAssertNoThrow(try Zip.unzipFile(filePath, destination: destinationPath, overwrite: true, password: "password", progress: nil))
+ try withSandbox { destinationPath in
+ #expect(throws: Never.self) {
+ try Zip.unzipFile(filePath, destination: destinationPath, overwrite: true, password: "password", progress: nil)
+ }
- XCTAssertTrue(FileManager.default.fileExists(atPath: destinationPath.path))
- try XCTAssertGreaterThan(Data(contentsOf: destinationPath.appendingPathComponent("3crBXeO.gif")).count, 0)
- try XCTAssertGreaterThan(Data(contentsOf: destinationPath.appendingPathComponent("kYkLkPf.gif")).count, 0)
+ #expect(FileManager.default.fileExists(atPath: destinationPath.path))
+ try #expect(!Data(contentsOf: destinationPath.appendingPathComponent("3crBXeO.gif")).isEmpty)
+ try #expect(!Data(contentsOf: destinationPath.appendingPathComponent("kYkLkPf.gif")).isEmpty)
+ }
}
- func testImplicitProgressUnzip() throws {
+ @Test("Implicit Progress Unzip")
+ func implicitProgressUnzip() throws {
let progress = Progress(totalUnitCount: 1)
let filePath = url(forResource: "bb8", withExtension: "zip")!
- let destinationPath = try autoRemovingSandbox()
- progress.becomeCurrent(withPendingUnitCount: 1)
- try Zip.unzipFile(filePath, destination: destinationPath, overwrite: true, password: "password", progress: nil)
- progress.resignCurrent()
+ try withSandbox { destinationPath in
+ progress.becomeCurrent(withPendingUnitCount: 1)
+ try Zip.unzipFile(filePath, destination: destinationPath, overwrite: true, password: "password", progress: nil)
+ progress.resignCurrent()
- XCTAssertTrue(progress.totalUnitCount == progress.completedUnitCount)
+ #expect(progress.totalUnitCount == progress.completedUnitCount)
+ }
}
- func testImplicitProgressZip() throws {
+ @Test("Implicit Progress Zip")
+ func implicitProgressZip() throws {
let progress = Progress(totalUnitCount: 1)
let imageURL1 = url(forResource: "3crBXeO", withExtension: "gif")!
let imageURL2 = url(forResource: "kYkLkPf", withExtension: "gif")!
- let sandboxFolder = try autoRemovingSandbox()
- let zipFilePath = sandboxFolder.appendingPathComponent("archive.zip")
+ try withSandbox { sandboxFolder in
+ let zipFilePath = sandboxFolder.appendingPathComponent("archive.zip")
- progress.becomeCurrent(withPendingUnitCount: 1)
- try Zip.zipFiles(paths: [imageURL1, imageURL2], zipFilePath: zipFilePath, password: nil, progress: nil)
- progress.resignCurrent()
+ progress.becomeCurrent(withPendingUnitCount: 1)
+ try Zip.zipFiles(paths: [imageURL1, imageURL2], zipFilePath: zipFilePath, password: nil, progress: nil)
+ progress.resignCurrent()
- XCTAssertTrue(progress.totalUnitCount == progress.completedUnitCount)
+ #expect(progress.totalUnitCount == progress.completedUnitCount)
+ }
}
- func testQuickZip() throws {
+ @Test("Quick Zip")
+ func quickZip() throws {
let imageURL1 = url(forResource: "3crBXeO", withExtension: "gif")!
let imageURL2 = url(forResource: "kYkLkPf", withExtension: "gif")!
let destinationURL = try Zip.quickZipFiles([imageURL1, imageURL2], fileName: "archive.zip")
- XCTAssertTrue(FileManager.default.fileExists(atPath: destinationURL.path))
- try XCTAssertGreaterThan(Data(contentsOf: destinationURL).count, 0)
- addTeardownBlock {
+ defer {
try? FileManager.default.removeItem(at: destinationURL)
}
+ #expect(FileManager.default.fileExists(atPath: destinationURL.path))
+ #expect(try !Data(contentsOf: destinationURL).isEmpty)
}
- func testQuickZipProgress() throws {
+ @Test("Quick Zip with Progress")
+ func quickZipProgress() throws {
let imageURL1 = url(forResource: "3crBXeO", withExtension: "gif")!
let imageURL2 = url(forResource: "kYkLkPf", withExtension: "gif")!
let destinationURL = try Zip.quickZipFiles([imageURL1, imageURL2], fileName: "archive") { progress in
- XCTAssertFalse(progress.isNaN)
+ #expect(!progress.isNaN)
}
- XCTAssertTrue(FileManager.default.fileExists(atPath: destinationURL.path))
- try XCTAssertGreaterThan(Data(contentsOf: destinationURL).count, 0)
- addTeardownBlock {
+ defer {
try? FileManager.default.removeItem(at: destinationURL)
}
+ #expect(FileManager.default.fileExists(atPath: destinationURL.path))
+ #expect(try !Data(contentsOf: destinationURL).isEmpty)
}
- func testQuickZipFolder() throws {
+ @Test("Quick Zip Folder")
+ func quickZipFolder() throws {
let fileManager = FileManager.default
let imageURL1 = url(forResource: "3crBXeO", withExtension: "gif")!
let imageURL2 = url(forResource: "kYkLkPf", withExtension: "gif")!
- let folderURL = try autoRemovingSandbox()
- let targetImageURL1 = folderURL.appendingPathComponent("3crBXeO.gif")
- let targetImageURL2 = folderURL.appendingPathComponent("kYkLkPf.gif")
- try fileManager.copyItem(at: imageURL1, to: targetImageURL1)
- try fileManager.copyItem(at: imageURL2, to: targetImageURL2)
- let destinationURL = try Zip.quickZipFiles([folderURL], fileName: "directory")
- XCTAssertTrue(fileManager.fileExists(atPath: destinationURL.path))
- addTeardownBlock {
- try? FileManager.default.removeItem(at: destinationURL)
+ try withSandbox { folderURL in
+ let targetImageURL1 = folderURL.appendingPathComponent("3crBXeO.gif")
+ let targetImageURL2 = folderURL.appendingPathComponent("kYkLkPf.gif")
+ try fileManager.copyItem(at: imageURL1, to: targetImageURL1)
+ try fileManager.copyItem(at: imageURL2, to: targetImageURL2)
+ let destinationURL = try Zip.quickZipFiles([folderURL], fileName: "directory")
+ defer {
+ try? FileManager.default.removeItem(at: destinationURL)
+ }
+ #expect(fileManager.fileExists(atPath: destinationURL.path))
}
}
- func testZip() throws {
+ @Test("Zip")
+ func zip() throws {
let imageURL1 = url(forResource: "3crBXeO", withExtension: "gif")!
let imageURL2 = url(forResource: "kYkLkPf", withExtension: "gif")!
- let sandboxFolder = try autoRemovingSandbox()
- let zipFilePath = sandboxFolder.appendingPathComponent("archive.zip")
- XCTAssertNoThrow(try Zip.zipFiles(paths: [imageURL1, imageURL2], zipFilePath: zipFilePath, password: nil, progress: nil))
- XCTAssertTrue(FileManager.default.fileExists(atPath: zipFilePath.path))
+ try withSandbox { sandboxFolder in
+ let zipFilePath = sandboxFolder.appendingPathComponent("archive.zip")
+ #expect(throws: Never.self) {
+ try Zip.zipFiles(paths: [imageURL1, imageURL2], zipFilePath: zipFilePath, password: nil, progress: nil)
+ }
+ #expect(FileManager.default.fileExists(atPath: zipFilePath.path))
+ }
}
- func testZipUnzipPassword() throws {
+ @Test("Zip and Unzip with Password")
+ func zipUnzipPassword() throws {
let imageURL1 = url(forResource: "3crBXeO", withExtension: "gif")!
let imageURL2 = url(forResource: "kYkLkPf", withExtension: "gif")!
- let zipFilePath = try autoRemovingSandbox().appendingPathComponent("archive.zip")
- try Zip.zipFiles(paths: [imageURL1, imageURL2], zipFilePath: zipFilePath, password: "password", progress: nil)
- let fileManager = FileManager.default
- XCTAssertTrue(fileManager.fileExists(atPath: zipFilePath.path))
- let directoryName = zipFilePath.lastPathComponent.replacingOccurrences(of: ".\(zipFilePath.pathExtension)", with: "")
- let destinationUrl = try autoRemovingSandbox().appendingPathComponent(directoryName, isDirectory: true)
- try Zip.unzipFile(zipFilePath, destination: destinationUrl, overwrite: true, password: "password", progress: nil)
- XCTAssertTrue(fileManager.fileExists(atPath: destinationUrl.path))
+ try withSandbox { firstSandbox in
+ let zipFilePath = firstSandbox.appendingPathComponent("archive.zip")
+ try Zip.zipFiles(paths: [imageURL1, imageURL2], zipFilePath: zipFilePath, password: "password", progress: nil)
+ let fileManager = FileManager.default
+ #expect(fileManager.fileExists(atPath: zipFilePath.path))
+ let directoryName = zipFilePath.lastPathComponent.replacingOccurrences(of: ".\(zipFilePath.pathExtension)", with: "")
+ try withSandbox { secondSandbox in
+ let destinationUrl = secondSandbox.appendingPathComponent(directoryName, isDirectory: true)
+ try Zip.unzipFile(zipFilePath, destination: destinationUrl, overwrite: true, password: "password", progress: nil)
+ #expect(fileManager.fileExists(atPath: destinationUrl.path))
+ }
+ }
}
- func testUnzipWithUnsupportedPermissions() throws {
+ @Test("Unzip with Unsupported Permissions")
+ func unzipWithUnsupportedPermissions() throws {
let permissionsURL = url(forResource: "unsupported_permissions", withExtension: "zip")!
let unzipDestination = try Zip.quickUnzipFile(permissionsURL)
let permission644 = unzipDestination.appendingPathComponent("unsupported_permission").appendingPathExtension("txt")
let foundPermissions = try FileManager.default.attributesOfItem(atPath: permission644.path)[.posixPermissions] as? Int
- #if os(Windows) && compiler(<6.0)
- let expectedPermissions = 0o700
- #elseif os(Windows) && compiler(>=6.0)
- let expectedPermissions = 0o600
+ #if os(Windows)
+ let expectedPermissions = 0o600
#elseif os(Android)
- let expectedPermissions = 0o666
+ let expectedPermissions = 0o666
#else
- let expectedPermissions = 0o644
+ let expectedPermissions = 0o644
#endif
- XCTAssertNotNil(foundPermissions)
- XCTAssertEqual(
- foundPermissions,
- expectedPermissions,
+ try #require(foundPermissions != nil)
+ #expect(
+ foundPermissions == expectedPermissions,
"\(foundPermissions.map { String($0, radix: 8) } ?? "nil") is not equal to \(String(expectedPermissions, radix: 8))"
)
}
- func testUnzipPermissions() throws {
+ @Test("Unzip with Permissions")
+ func unzipPermissions() throws {
let permissionsURL = url(forResource: "permissions", withExtension: "zip")!
let unzipDestination = try Zip.quickUnzipFile(permissionsURL)
- addTeardownBlock {
+ defer {
try? FileManager.default.removeItem(at: unzipDestination)
}
let fileManager = FileManager.default
@@ -206,82 +232,81 @@ final class ZipTests: XCTestCase {
let attributes777 = try fileManager.attributesOfItem(atPath: permission777.path)
let attributes600 = try fileManager.attributesOfItem(atPath: permission600.path)
let attributes604 = try fileManager.attributesOfItem(atPath: permission604.path)
- #if os(Windows) && compiler(<6.0)
- XCTAssertEqual(attributes777[.posixPermissions] as? Int, 0o700)
- XCTAssertEqual(attributes600[.posixPermissions] as? Int, 0o700)
- XCTAssertEqual(attributes604[.posixPermissions] as? Int, 0o700)
- #elseif os(Windows) && compiler(>=6.0)
- XCTAssertEqual(attributes777[.posixPermissions] as? Int, 0o600)
- XCTAssertEqual(attributes600[.posixPermissions] as? Int, 0o600)
- XCTAssertEqual(attributes604[.posixPermissions] as? Int, 0o600)
+ #if os(Windows)
+ #expect(attributes777[.posixPermissions] as? Int == 0o600)
+ #expect(attributes600[.posixPermissions] as? Int == 0o600)
+ #expect(attributes604[.posixPermissions] as? Int == 0o600)
#else
- XCTAssertEqual(attributes777[.posixPermissions] as? Int, 0o777)
- XCTAssertEqual(attributes600[.posixPermissions] as? Int, 0o600)
- XCTAssertEqual(attributes604[.posixPermissions] as? Int, 0o604)
+ #expect(attributes777[.posixPermissions] as? Int == 0o777)
+ #expect(attributes600[.posixPermissions] as? Int == 0o600)
+ #expect(attributes604[.posixPermissions] as? Int == 0o604)
#endif
}
- // Tests if https://github.com/marmelroy/Zip/issues/245 does not uccor anymore.
- func testUnzipProtectsAgainstPathTraversal() throws {
+ @Test("Unzip protects against Path Traversal", .bug("https://github.com/marmelroy/Zip/issues/245"))
+ func unzipProtectsAgainstPathTraversal() throws {
let filePath = url(forResource: "pathTraversal", withExtension: "zip")!
- let destinationPath = try autoRemovingSandbox()
-
- do {
- try Zip.unzipFile(filePath, destination: destinationPath, overwrite: true, password: "password", progress: nil)
- XCTFail("ZipError.unzipFail expected.")
- } catch {}
-
- XCTAssertFalse(
- FileManager.default.fileExists(
- atPath: destinationPath.appendingPathComponent("../naughtyFile.txt").path
+ try withSandbox { destinationPath in
+ do {
+ try Zip.unzipFile(filePath, destination: destinationPath, overwrite: true, password: "password", progress: nil)
+ Issue.record("ZipError.unzipFail expected.")
+ } catch {}
+
+ #expect(
+ !FileManager.default.fileExists(
+ atPath: destinationPath.appendingPathComponent("../naughtyFile.txt").path
+ )
)
- )
+ }
}
- func testQuickUnzipSubDir() throws {
+ @Test("Quick Unzip Subdirectory")
+ func quickUnzipSubDir() throws {
let bookURL = url(forResource: "bb8", withExtension: "zip")!
let unzipDestination = try Zip.quickUnzipFile(bookURL)
- addTeardownBlock {
+ defer {
try? FileManager.default.removeItem(at: unzipDestination)
}
let fileManager = FileManager.default
let subDir = unzipDestination.appendingPathComponent("subDir")
let imageURL = subDir.appendingPathComponent("r2W9yu9").appendingPathExtension("gif")
- XCTAssertTrue(fileManager.fileExists(atPath: unzipDestination.path))
- XCTAssertTrue(fileManager.fileExists(atPath: subDir.path))
- XCTAssertTrue(fileManager.fileExists(atPath: imageURL.path))
+ #expect(fileManager.fileExists(atPath: unzipDestination.path))
+ #expect(fileManager.fileExists(atPath: subDir.path))
+ #expect(fileManager.fileExists(atPath: imageURL.path))
}
- func testAddedCustomFileExtensionIsValid() {
+ @Test("Added Custom File Extension Is Valid")
+ func addedCustomFileExtensionIsValid() {
let fileExtension = "cstm"
Zip.addCustomFileExtension(fileExtension)
let result = Zip.isValidFileExtension(fileExtension)
- XCTAssertTrue(result)
+ #expect(result)
Zip.removeCustomFileExtension(fileExtension)
}
- func testRemovedCustomFileExtensionIsInvalid() {
+ @Test("Removed Custom File Extension Is Invalid")
+ func removedCustomFileExtensionIsInvalid() {
let fileExtension = "cstm"
Zip.addCustomFileExtension(fileExtension)
Zip.removeCustomFileExtension(fileExtension)
let result = Zip.isValidFileExtension(fileExtension)
- XCTAssertFalse(result)
+ #expect(!result)
}
- func testDefaultFileExtensionsIsValid() {
- XCTAssertTrue(Zip.isValidFileExtension("zip"))
- XCTAssertTrue(Zip.isValidFileExtension("cbz"))
+ @Test("Default File Extensions Are Valid", arguments: ["zip", "cbz"])
+ func defaultFileExtensionsIsValid(fileExtension: String) {
+ #expect(Zip.isValidFileExtension(fileExtension))
}
- func testDefaultFileExtensionsIsNotRemoved() {
- Zip.removeCustomFileExtension("zip")
- Zip.removeCustomFileExtension("cbz")
- XCTAssertTrue(Zip.isValidFileExtension("zip"))
- XCTAssertTrue(Zip.isValidFileExtension("cbz"))
+ @Test("Default File Extensions Are Not Removed", arguments: ["zip", "cbz"])
+ func defaultFileExtensionsAreNotRemoved(fileExtension: String) {
+ Zip.removeCustomFileExtension(fileExtension)
+ #expect(Zip.isValidFileExtension(fileExtension))
}
- func testZipData() throws {
+ @Test("Zip Data")
+ func zipData() throws {
let archiveFile1 = ArchiveFile(filename: "file1.txt", data: "Hello, World!".data(using: .utf8)!)
let archiveFile2 = ArchiveFile(
filename: "file2.txt",
@@ -289,13 +314,15 @@ final class ZipTests: XCTestCase {
modifiedTime: Date()
)
let emptyArchiveFile = ArchiveFile(filename: "empty.txt", data: Data())
- let sandboxFolder = try autoRemovingSandbox()
- let zipFilePath = sandboxFolder.appendingPathComponent("archive.zip")
- try Zip.zipData(archiveFiles: [archiveFile1, archiveFile2, emptyArchiveFile], zipFilePath: zipFilePath)
- XCTAssertTrue(FileManager.default.fileExists(atPath: zipFilePath.path))
+ try withSandbox { sandboxFolder in
+ let zipFilePath = sandboxFolder.appendingPathComponent("archive.zip")
+ try Zip.zipData(archiveFiles: [archiveFile1, archiveFile2, emptyArchiveFile], zipFilePath: zipFilePath)
+ #expect(FileManager.default.fileExists(atPath: zipFilePath.path))
+ }
}
- func testZipDataProgress() throws {
+ @Test("Zip Data with Progress")
+ func zipDataProgress() throws {
let archiveFile1 = ArchiveFile(filename: "file1.txt", data: "Hello, World!".data(using: .utf8)!)
let archiveFile2 = ArchiveFile(
filename: "file2.txt",
@@ -303,74 +330,87 @@ final class ZipTests: XCTestCase {
modifiedTime: Date()
)
let emptyArchiveFile = ArchiveFile(filename: "empty.txt", data: Data())
- let sandboxFolder = try autoRemovingSandbox()
- let zipFilePath = sandboxFolder.appendingPathComponent("archive.zip")
- try Zip.zipData(archiveFiles: [archiveFile1, archiveFile2, emptyArchiveFile], zipFilePath: zipFilePath) { progress in
- XCTAssertFalse(progress.isNaN)
+ try withSandbox { sandboxFolder in
+ let zipFilePath = sandboxFolder.appendingPathComponent("archive.zip")
+ try Zip.zipData(archiveFiles: [archiveFile1, archiveFile2, emptyArchiveFile], zipFilePath: zipFilePath) { progress in
+ #expect(!progress.isNaN)
+ }
+ #expect(FileManager.default.fileExists(atPath: zipFilePath.path))
}
- XCTAssertTrue(FileManager.default.fileExists(atPath: zipFilePath.path))
}
- func testZipError() {
- XCTAssertEqual(ZipError.fileNotFound.description, "File not found.")
- XCTAssertEqual(ZipError.unzipFail.description, "Failed to unzip file.")
- XCTAssertEqual(ZipError.zipFail.description, "Failed to zip file.")
+ @Test("Zip Error")
+ func zipError() {
+ #expect(ZipError.fileNotFound.description == "File not found.")
+ #expect(ZipError.unzipFail.description == "Failed to unzip file.")
+ #expect(ZipError.zipFail.description == "Failed to zip file.")
}
- func testZipCompression() {
- XCTAssertEqual(ZipCompression.NoCompression.minizipCompression, 0)
- XCTAssertEqual(ZipCompression.BestSpeed.minizipCompression, 1)
- XCTAssertEqual(ZipCompression.DefaultCompression.minizipCompression, -1)
- XCTAssertEqual(ZipCompression.BestCompression.minizipCompression, 9)
+ @Test("Zip Compression")
+ func zipCompression() {
+ #expect(ZipCompression.NoCompression.minizipCompression == 0)
+ #expect(ZipCompression.BestSpeed.minizipCompression == 1)
+ #expect(ZipCompression.DefaultCompression.minizipCompression == -1)
+ #expect(ZipCompression.BestCompression.minizipCompression == 9)
}
- func testDosDate() {
+ @Test("DOS Date")
+ func dosDate() {
NSTimeZone.default = NSTimeZone(forSecondsFromGMT: 0) as TimeZone
- XCTAssertEqual(0b10000011_00110001_10001100_00110001, Date(timeIntervalSince1970: 2_389_282_415).dosDate)
- XCTAssertEqual(0b00000001_00110001_10001100_00110001, Date(timeIntervalSince1970: 338_060_015).dosDate)
- XCTAssertEqual(0b00000000_00100001_00000000_00000000, Date(timeIntervalSince1970: 315_532_800).dosDate)
+ #expect(0b10000011_00110001_10001100_00110001 == Date(timeIntervalSince1970: 2_389_282_415).dosDate)
+ #expect(0b00000001_00110001_10001100_00110001 == Date(timeIntervalSince1970: 338_060_015).dosDate)
+ #expect(0b00000000_00100001_00000000_00000000 == Date(timeIntervalSince1970: 315_532_800).dosDate)
}
- func testInit() {
+ @Test("Zip Init")
+ func zipInit() {
var zip: Zip? = Zip()
- XCTAssertNotNil(zip)
+ #expect(zip != nil)
zip = nil
- XCTAssertNil(zip)
+ #expect(zip == nil)
}
- func testUnzipWithoutPassword() throws {
+ @Test("Unzip Without Password")
+ func unzipWithoutPassword() throws {
let imageURL1 = url(forResource: "3crBXeO", withExtension: "gif")!
let imageURL2 = url(forResource: "kYkLkPf", withExtension: "gif")!
- let zipFilePath = try autoRemovingSandbox().appendingPathComponent("archive.zip")
- try Zip.zipFiles(paths: [imageURL1, imageURL2], zipFilePath: zipFilePath, password: "password")
- XCTAssertTrue(FileManager.default.fileExists(atPath: zipFilePath.path))
- let directoryName = zipFilePath.lastPathComponent.replacingOccurrences(of: ".\(zipFilePath.pathExtension)", with: "")
- let destinationUrl = try autoRemovingSandbox().appendingPathComponent(directoryName, isDirectory: true)
- XCTAssertThrowsError(try Zip.unzipFile(zipFilePath, destination: destinationUrl))
+ try withSandbox { firstSandbox in
+ let zipFilePath = firstSandbox.appendingPathComponent("archive.zip")
+ try Zip.zipFiles(paths: [imageURL1, imageURL2], zipFilePath: zipFilePath, password: "password")
+ #expect(FileManager.default.fileExists(atPath: zipFilePath.path))
+ let directoryName = zipFilePath.lastPathComponent.replacingOccurrences(of: ".\(zipFilePath.pathExtension)", with: "")
+ try withSandbox { secondSandbox in
+ let destinationUrl = secondSandbox.appendingPathComponent(directoryName, isDirectory: true)
+ #expect(throws: (any Error).self) { try Zip.unzipFile(zipFilePath, destination: destinationUrl) }
+ }
+ }
}
- func testFileHandler() throws {
+ @Test("File Handler")
+ func fileHandler() throws {
let filePath = url(forResource: "bb8", withExtension: "zip")!
- let destinationPath = try autoRemovingSandbox()
- XCTAssertNoThrow(
- try Zip.unzipFile(
- filePath, destination: destinationPath, password: "password",
- fileOutputHandler: { fileURL in
- XCTAssertTrue(FileManager.default.fileExists(atPath: fileURL.path))
- }
- )
- )
- XCTAssertTrue(FileManager.default.fileExists(atPath: destinationPath.path))
- try XCTAssertGreaterThan(Data(contentsOf: destinationPath.appendingPathComponent("3crBXeO.gif")).count, 0)
- try XCTAssertGreaterThan(Data(contentsOf: destinationPath.appendingPathComponent("kYkLkPf.gif")).count, 0)
+ try withSandbox { destinationPath in
+ #expect(throws: Never.self) {
+ try Zip.unzipFile(
+ filePath, destination: destinationPath, password: "password",
+ fileOutputHandler: { fileURL in
+ #expect(FileManager.default.fileExists(atPath: fileURL.path))
+ }
+ )
+ }
+ #expect(FileManager.default.fileExists(atPath: destinationPath.path))
+ try #expect(!Data(contentsOf: destinationPath.appendingPathComponent("3crBXeO.gif")).isEmpty)
+ try #expect(!Data(contentsOf: destinationPath.appendingPathComponent("kYkLkPf.gif")).isEmpty)
+ }
}
- // Tests if https://github.com/vapor-community/Zip/issues/4 does not occur anymore.
- func testRoundTripping() throws {
+ @Test("Round Tripping", .bug("https://github.com/vapor-community/Zip/issues/4"))
+ func roundTripping() throws {
// "prod-apple-swift-metrics-main-e6a00d36.zip" is the original zip file from the issue.
let zipFilePath = url(forResource: "prod-apple-swift-metrics-main-e6a00d36", withExtension: "zip")!
- let failDestinationPath = try autoRemovingSandbox()
- XCTAssertThrowsError(try Zip.unzipFile(zipFilePath, destination: failDestinationPath, overwrite: true))
+ try withSandbox { failDestinationPath in
+ #expect(throws: (any Error).self) { try Zip.unzipFile(zipFilePath, destination: failDestinationPath, overwrite: true) }
+ }
// "prod-apple-swift-metrics-main-e6a00d36-finder.zip" is a zip file
// that was created by unzipping the original zip file with Finder on macOS 14.6.1
@@ -380,50 +420,57 @@ final class ZipTests: XCTestCase {
// that was created by unzipping the original zip file with Finder on macOS 14.6.1
// and then zipping it again using vapor-community/Zip v2.2.0.
let testZipFilePath = url(forResource: "prod-apple-swift-metrics-main-e6a00d36-test", withExtension: "zip")!
- let destinationPath = try autoRemovingSandbox()
- XCTAssertNoThrow(try Zip.unzipFile(testZipFilePath, destination: destinationPath, overwrite: true))
-
- let destinationFolder = destinationPath.appendingPathComponent("prod-apple-swift-metrics-main-e6a00d36")
- XCTAssert(FileManager.default.fileExists(atPath: destinationFolder.appendingPathComponent("metadata.json").path))
- XCTAssert(FileManager.default.fileExists(atPath: destinationFolder.appendingPathComponent("main/index.html").path))
- XCTAssert(FileManager.default.fileExists(atPath: destinationFolder.appendingPathComponent("main/index/index.json").path))
- try XCTAssertGreaterThan(Data(contentsOf: destinationFolder.appendingPathComponent("metadata.json")).count, 0)
-
- let unzippedFiles = try FileManager.default.contentsOfDirectory(atPath: destinationFolder.path)
-
- let newZipFilePath = try autoRemovingSandbox().appendingPathComponent("new-archive.zip")
- try Zip.zipFiles(paths: [destinationFolder], zipFilePath: newZipFilePath)
-
- let newDestinationPath = try autoRemovingSandbox()
- try Zip.unzipFile(newZipFilePath, destination: newDestinationPath, overwrite: true)
-
- let newDestinationFolder = newDestinationPath.appendingPathComponent("prod-apple-swift-metrics-main-e6a00d36")
- XCTAssert(FileManager.default.fileExists(atPath: newDestinationFolder.appendingPathComponent("metadata.json").path))
- XCTAssert(FileManager.default.fileExists(atPath: newDestinationFolder.appendingPathComponent("main/index.html").path))
- XCTAssert(FileManager.default.fileExists(atPath: newDestinationFolder.appendingPathComponent("main/index/index.json").path))
- try XCTAssertGreaterThan(Data(contentsOf: newDestinationFolder.appendingPathComponent("metadata.json")).count, 0)
-
- let newUnzippedFiles = try FileManager.default.contentsOfDirectory(atPath: newDestinationFolder.path)
- XCTAssertEqual(unzippedFiles, newUnzippedFiles)
+ try withSandbox { destinationPath in
+ #expect(throws: Never.self) { try Zip.unzipFile(testZipFilePath, destination: destinationPath, overwrite: true) }
+
+ let destinationFolder = destinationPath.appendingPathComponent("prod-apple-swift-metrics-main-e6a00d36")
+ #expect(FileManager.default.fileExists(atPath: destinationFolder.appendingPathComponent("metadata.json").path))
+ #expect(FileManager.default.fileExists(atPath: destinationFolder.appendingPathComponent("main/index.html").path))
+ #expect(FileManager.default.fileExists(atPath: destinationFolder.appendingPathComponent("main/index/index.json").path))
+ #expect(try !Data(contentsOf: destinationFolder.appendingPathComponent("metadata.json")).isEmpty)
+
+ let unzippedFiles = try FileManager.default.contentsOfDirectory(atPath: destinationFolder.path)
+
+ try withSandbox { sandbox in
+ let newZipFilePath = sandbox.appendingPathComponent("new-archive.zip")
+ try Zip.zipFiles(paths: [destinationFolder], zipFilePath: newZipFilePath)
+
+ try withSandbox { newDestinationPath in
+ try Zip.unzipFile(newZipFilePath, destination: newDestinationPath, overwrite: true)
+
+ let newDestinationFolder = newDestinationPath.appendingPathComponent("prod-apple-swift-metrics-main-e6a00d36")
+ #expect(FileManager.default.fileExists(atPath: newDestinationFolder.appendingPathComponent("metadata.json").path))
+ #expect(FileManager.default.fileExists(atPath: newDestinationFolder.appendingPathComponent("main/index.html").path))
+ #expect(
+ FileManager.default.fileExists(atPath: newDestinationFolder.appendingPathComponent("main/index/index.json").path)
+ )
+ #expect(try !Data(contentsOf: newDestinationFolder.appendingPathComponent("metadata.json")).isEmpty)
+
+ let newUnzippedFiles = try FileManager.default.contentsOfDirectory(atPath: newDestinationFolder.path)
+ #expect(unzippedFiles == newUnzippedFiles)
+ }
+ }
+ }
}
#if os(Windows)
- func testWindowsReservedChars() throws {
- let txtFile = ArchiveFile(filename: "a_b.txt", data: "Hi Mom!".data(using: .utf8)!)
- let txtFile1 = ArchiveFile(filename: "ab.txt", data: "Hello, Swift!".data(using: .utf8)!)
- let txtFile3 = ArchiveFile(filename: "a:b.txt", data: "Hello, World!".data(using: .utf8)!)
- let txtFile4 = ArchiveFile(filename: "a\"b.txt", data: "Hi Windows!".data(using: .utf8)!)
- let txtFile5 = ArchiveFile(filename: "a|b.txt", data: "Hi Barbie!".data(using: .utf8)!)
- let txtFile6 = ArchiveFile(filename: "a?b.txt", data: "Hi, Ken!".data(using: .utf8)!)
- let txtFile7 = ArchiveFile(filename: "a*b.txt", data: "Hello Everyone!".data(using: .utf8)!)
-
- let file = ArchiveFile(filename: "a_b", data: "Hello, World!".data(using: .utf8)!)
- let file1 = ArchiveFile(filename: "ab", data: "Hello, Swift!".data(using: .utf8)!)
- let file3 = ArchiveFile(filename: "a:b", data: "Hello, World!".data(using: .utf8)!)
-
- let sandboxFolder = try autoRemovingSandbox()
+ @Test("Windows Reserved Characters")
+ func windowsReservedChars() throws {
+ let txtFile = ArchiveFile(filename: "a_b.txt", data: "Hi Mom!".data(using: .utf8)!)
+ let txtFile1 = ArchiveFile(filename: "ab.txt", data: "Hello, Swift!".data(using: .utf8)!)
+ let txtFile3 = ArchiveFile(filename: "a:b.txt", data: "Hello, World!".data(using: .utf8)!)
+ let txtFile4 = ArchiveFile(filename: "a\"b.txt", data: "Hi Windows!".data(using: .utf8)!)
+ let txtFile5 = ArchiveFile(filename: "a|b.txt", data: "Hi Barbie!".data(using: .utf8)!)
+ let txtFile6 = ArchiveFile(filename: "a?b.txt", data: "Hi, Ken!".data(using: .utf8)!)
+ let txtFile7 = ArchiveFile(filename: "a*b.txt", data: "Hello Everyone!".data(using: .utf8)!)
+
+ let file = ArchiveFile(filename: "a_b", data: "Hello, World!".data(using: .utf8)!)
+ let file1 = ArchiveFile(filename: "ab", data: "Hello, Swift!".data(using: .utf8)!)
+ let file3 = ArchiveFile(filename: "a:b", data: "Hello, World!".data(using: .utf8)!)
+
+ try withSandbox { sandboxFolder in
let zipFilePath = sandboxFolder.appendingPathComponent("archive.zip")
try Zip.zipData(
archiveFiles: [
@@ -433,57 +480,62 @@ final class ZipTests: XCTestCase {
zipFilePath: zipFilePath
)
- let destinationPath = try autoRemovingSandbox()
- try Zip.unzipFile(zipFilePath, destination: destinationPath)
-
- let txtFileURL = destinationPath.appendingPathComponent("a_b.txt")
- let txtFile1URL = destinationPath.appendingPathComponent("a_b (1).txt")
- let txtFile2URL = destinationPath.appendingPathComponent("a_b (2).txt")
- let txtFile3URL = destinationPath.appendingPathComponent("a_b (3).txt")
- let txtFile4URL = destinationPath.appendingPathComponent("a_b (4).txt")
- let txtFile5URL = destinationPath.appendingPathComponent("a_b (5).txt")
- let txtFile6URL = destinationPath.appendingPathComponent("a_b (6).txt")
- let txtFile7URL = destinationPath.appendingPathComponent("a_b (7).txt")
-
- let fileURL = destinationPath.appendingPathComponent("a_b")
- let file1URL = destinationPath.appendingPathComponent("a_b (1)")
- let file2URL = destinationPath.appendingPathComponent("a_b (2)")
- let file3URL = destinationPath.appendingPathComponent("a_b (3)")
-
- XCTAssertTrue(FileManager.default.fileExists(atPath: txtFileURL.path))
- XCTAssertTrue(FileManager.default.fileExists(atPath: txtFile1URL.path))
- XCTAssertTrue(FileManager.default.fileExists(atPath: txtFile2URL.path))
- XCTAssertTrue(FileManager.default.fileExists(atPath: txtFile3URL.path))
- XCTAssertTrue(FileManager.default.fileExists(atPath: txtFile4URL.path))
- XCTAssertTrue(FileManager.default.fileExists(atPath: txtFile5URL.path))
- XCTAssertTrue(FileManager.default.fileExists(atPath: txtFile6URL.path))
- XCTAssertTrue(FileManager.default.fileExists(atPath: txtFile7URL.path))
-
- XCTAssertTrue(FileManager.default.fileExists(atPath: fileURL.path))
- XCTAssertTrue(FileManager.default.fileExists(atPath: file1URL.path))
- XCTAssertTrue(FileManager.default.fileExists(atPath: file2URL.path))
- XCTAssertTrue(FileManager.default.fileExists(atPath: file3URL.path))
+ try withSandbox { destinationPath in
+ try Zip.unzipFile(zipFilePath, destination: destinationPath)
+
+ let txtFileURL = destinationPath.appendingPathComponent("a_b.txt")
+ let txtFile1URL = destinationPath.appendingPathComponent("a_b (1).txt")
+ let txtFile2URL = destinationPath.appendingPathComponent("a_b (2).txt")
+ let txtFile3URL = destinationPath.appendingPathComponent("a_b (3).txt")
+ let txtFile4URL = destinationPath.appendingPathComponent("a_b (4).txt")
+ let txtFile5URL = destinationPath.appendingPathComponent("a_b (5).txt")
+ let txtFile6URL = destinationPath.appendingPathComponent("a_b (6).txt")
+ let txtFile7URL = destinationPath.appendingPathComponent("a_b (7).txt")
+
+ let fileURL = destinationPath.appendingPathComponent("a_b")
+ let file1URL = destinationPath.appendingPathComponent("a_b (1)")
+ let file2URL = destinationPath.appendingPathComponent("a_b (2)")
+ let file3URL = destinationPath.appendingPathComponent("a_b (3)")
+
+ #expect(FileManager.default.fileExists(atPath: txtFileURL.path))
+ #expect(FileManager.default.fileExists(atPath: txtFile1URL.path))
+ #expect(FileManager.default.fileExists(atPath: txtFile2URL.path))
+ #expect(FileManager.default.fileExists(atPath: txtFile3URL.path))
+ #expect(FileManager.default.fileExists(atPath: txtFile4URL.path))
+ #expect(FileManager.default.fileExists(atPath: txtFile5URL.path))
+ #expect(FileManager.default.fileExists(atPath: txtFile6URL.path))
+ #expect(FileManager.default.fileExists(atPath: txtFile7URL.path))
+
+ #expect(FileManager.default.fileExists(atPath: fileURL.path))
+ #expect(FileManager.default.fileExists(atPath: file1URL.path))
+ #expect(FileManager.default.fileExists(atPath: file2URL.path))
+ #expect(FileManager.default.fileExists(atPath: file3URL.path))
+ }
}
+ }
#endif
- func testPassKitExtensions() throws {
+ @Test("PassKit Extensions")
+ func passKitExtensions() throws {
let pkpassURL = url(forResource: "PassKitTest", withExtension: "pkpass")!
- let pkpassDestination = try autoRemovingSandbox()
- Zip.addCustomFileExtension("pkpass")
- XCTAssertNoThrow(try Zip.unzipFile(pkpassURL, destination: pkpassDestination))
- XCTAssert(FileManager.default.fileExists(atPath: pkpassDestination.appendingPathComponent("pass.json").path))
- XCTAssert(FileManager.default.fileExists(atPath: pkpassDestination.appendingPathComponent("manifest.json").path))
- XCTAssert(FileManager.default.fileExists(atPath: pkpassDestination.appendingPathComponent("signature").path))
- XCTAssert(FileManager.default.fileExists(atPath: pkpassDestination.appendingPathComponent("icon.png").path))
- XCTAssert(FileManager.default.fileExists(atPath: pkpassDestination.appendingPathComponent("logo.png").path))
+ try withSandbox { pkpassDestination in
+ Zip.addCustomFileExtension("pkpass")
+ #expect(throws: Never.self) { try Zip.unzipFile(pkpassURL, destination: pkpassDestination) }
+ #expect(FileManager.default.fileExists(atPath: pkpassDestination.appendingPathComponent("pass.json").path))
+ #expect(FileManager.default.fileExists(atPath: pkpassDestination.appendingPathComponent("manifest.json").path))
+ #expect(FileManager.default.fileExists(atPath: pkpassDestination.appendingPathComponent("signature").path))
+ #expect(FileManager.default.fileExists(atPath: pkpassDestination.appendingPathComponent("icon.png").path))
+ #expect(FileManager.default.fileExists(atPath: pkpassDestination.appendingPathComponent("logo.png").path))
+ }
let orderURL = url(forResource: "PassKitTest", withExtension: "order")!
- let orderDestination = try autoRemovingSandbox()
- Zip.addCustomFileExtension("order")
- XCTAssertNoThrow(try Zip.unzipFile(orderURL, destination: orderDestination))
- XCTAssert(FileManager.default.fileExists(atPath: orderDestination.appendingPathComponent("order.json").path))
- XCTAssert(FileManager.default.fileExists(atPath: orderDestination.appendingPathComponent("manifest.json").path))
- XCTAssert(FileManager.default.fileExists(atPath: orderDestination.appendingPathComponent("signature").path))
- XCTAssert(FileManager.default.fileExists(atPath: orderDestination.appendingPathComponent("icon.png").path))
+ try withSandbox { orderDestination in
+ Zip.addCustomFileExtension("order")
+ #expect(throws: Never.self) { try Zip.unzipFile(orderURL, destination: orderDestination) }
+ #expect(FileManager.default.fileExists(atPath: orderDestination.appendingPathComponent("order.json").path))
+ #expect(FileManager.default.fileExists(atPath: orderDestination.appendingPathComponent("manifest.json").path))
+ #expect(FileManager.default.fileExists(atPath: orderDestination.appendingPathComponent("signature").path))
+ #expect(FileManager.default.fileExists(atPath: orderDestination.appendingPathComponent("icon.png").path))
+ }
}
}