Merge branch 'develop'

This commit is contained in:
Timofey Solomko
2021-09-21 13:29:10 +03:00
39 changed files with 547 additions and 402 deletions
+2 -2
View File
@@ -3,11 +3,11 @@ sourcekitten_sourcefile: docs.json
clean: false
author: Timofey Solomko
module: SWCompression
module_version: 4.6.0
module_version: 4.6.1
copyright: '© 2021 Timofey Solomko'
readme: README.md
github_url: https://github.com/tsolomko/SWCompression
github_file_prefix: https://github.com/tsolomko/SWCompression/tree/4.6.0
github_file_prefix: https://github.com/tsolomko/SWCompression/tree/4.6.1
theme: fullwidth
custom_categories:
-22
View File
@@ -1,22 +0,0 @@
# TODO: There is probably a way to simplify this very explicit build matrix.
git:
depth: 1
submodules: false
jobs:
include:
- stage: test
language: swift
os: osx
osx_image: xcode12.5 # Swift 5.4
env:
- HOMEBREW_NO_INSTALL_CLEANUP=1
- WATCHOS_ACTIONS='clean test'
- WATCHOS_SIMULATOR='Apple Watch Series 6 - 44mm'
before_install:
- brew update
install:
- ./utils.py ci install-macos
before_script:
- ./utils.py prepare-workspace macos --xcf
script:
- ./utils.py ci script-macos
+7
View File
@@ -1,5 +1,12 @@
# Changelog
## 4.6.1
- Fixed a crash in LZMA2 when trying to process an empty `Data`.
- swcomp changes:
- Added `benchmark create-tar` benchmarking command.
- Benchmarking results are now printed in the units of speed instead of time elapsed.
## 4.6.0
- Swift 4.2 is no longer supported.
-1
View File
@@ -2,7 +2,6 @@
[![Swift 5.X](https://img.shields.io/badge/Swift-5.X-blue.svg)](https://developer.apple.com/swift/)
[![GitHub license](https://img.shields.io/badge/license-MIT-lightgrey.svg)](https://raw.githubusercontent.com/tsolomko/SWCompression/master/LICENSE)
[![Build Status](https://travis-ci.com/tsolomko/SWCompression.svg?branch=develop)](https://travis-ci.com/tsolomko/SWCompression)
[![Build Status](https://dev.azure.com/tsolomko/SWCompression/_apis/build/status/tsolomko.SWCompression?branchName=develop)](https://dev.azure.com/tsolomko/SWCompression/_build/latest?definitionId=3&branchName=develop)
A framework with (de)compression algorithms and functions for working with various archives and containers.
+1 -1
View File
@@ -1,7 +1,7 @@
Pod::Spec.new do |s|
s.name = "SWCompression"
s.version = "4.6.0"
s.version = "4.6.1"
s.summary = "A framework with functions for working with compression, archives and containers."
s.description = "A framework with (de)compression algorithms and functions for processing various archives and containers."
+2 -2
View File
@@ -15,9 +15,9 @@
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>CFBundleShortVersionString</key>
<string>4.6.0</string>
<string>4.6.1</string>
<key>CFBundleVersion</key>
<string>80</string>
<string>81</string>
<key>NSHumanReadableCopyright</key>
<string>Copyright © 2021 Timofey Solomko</string>
</dict>
@@ -15,8 +15,8 @@
<key>CFBundlePackageType</key>
<string>BNDL</string>
<key>CFBundleShortVersionString</key>
<string>4.6.0</string>
<string>4.6.1</string>
<key>CFBundleVersion</key>
<string>80</string>
<string>81</string>
</dict>
</plist>
+17 -5
View File
@@ -220,6 +220,9 @@
E652D8F5263D678000FC229B /* test_nonstandard_runlength.answer in Resources */ = {isa = PBXBuildFile; fileRef = E652D8F4263D678000FC229B /* test_nonstandard_runlength.answer */; };
E66F36242538726E00076A6E /* test_empty.lzma in Resources */ = {isa = PBXBuildFile; fileRef = E66F36232538726E00076A6E /* test_empty.lzma */; };
E66F362C2538E2B700076A6E /* test_empty.zlib in Resources */ = {isa = PBXBuildFile; fileRef = E66F362B2538E2B700076A6E /* test_empty.zlib */; };
E6EDD6A826F7767F00884532 /* test_minor_version_3.7z in Resources */ = {isa = PBXBuildFile; fileRef = E6EDD6A626F7767E00884532 /* test_minor_version_3.7z */; };
E6EDD6A926F7767F00884532 /* test_minor_version_4.7z in Resources */ = {isa = PBXBuildFile; fileRef = E6EDD6A726F7767E00884532 /* test_minor_version_4.7z */; };
E6EDD6AC26F77C0E00884532 /* test_minor_version_2.7z in Resources */ = {isa = PBXBuildFile; fileRef = E6EDD6AB26F77C0E00884532 /* test_minor_version_2.7z */; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
@@ -447,6 +450,9 @@
E652D8F4263D678000FC229B /* test_nonstandard_runlength.answer */ = {isa = PBXFileReference; lastKnownFileType = file; path = test_nonstandard_runlength.answer; sourceTree = "<group>"; };
E66F36232538726E00076A6E /* test_empty.lzma */ = {isa = PBXFileReference; lastKnownFileType = file; path = test_empty.lzma; sourceTree = "<group>"; };
E66F362B2538E2B700076A6E /* test_empty.zlib */ = {isa = PBXFileReference; lastKnownFileType = file; path = test_empty.zlib; sourceTree = "<group>"; };
E6EDD6A626F7767E00884532 /* test_minor_version_3.7z */ = {isa = PBXFileReference; lastKnownFileType = file; path = test_minor_version_3.7z; sourceTree = "<group>"; };
E6EDD6A726F7767E00884532 /* test_minor_version_4.7z */ = {isa = PBXFileReference; lastKnownFileType = file; path = test_minor_version_4.7z; sourceTree = "<group>"; };
E6EDD6AB26F77C0E00884532 /* test_minor_version_2.7z */ = {isa = PBXFileReference; lastKnownFileType = file; path = test_minor_version_2.7z; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
@@ -883,6 +889,9 @@
06F066061FFB763300312A82 /* test_win.7z */,
0627A4D220FE521B0023987C /* test_unicode.7z */,
068D070321368617002A6C3B /* test_delta_filter.7z */,
E6EDD6AB26F77C0E00884532 /* test_minor_version_2.7z */,
E6EDD6A626F7767E00884532 /* test_minor_version_3.7z */,
E6EDD6A726F7767E00884532 /* test_minor_version_4.7z */,
06F066071FFB763300312A82 /* SWCompressionSourceCode.7z */,
);
path = 7z;
@@ -949,7 +958,7 @@
isa = PBXProject;
attributes = {
LastSwiftUpdateCheck = 0920;
LastUpgradeCheck = 1250;
LastUpgradeCheck = 1300;
ORGANIZATIONNAME = "Timofey Solomko";
TargetAttributes = {
06BE1AC71DB410F100EE0F59 = {
@@ -991,6 +1000,7 @@
06F066201FFB763300312A82 /* test1.answer in Resources */,
06F0664E1FFB763400312A82 /* test_v7.tar in Resources */,
06F0662E1FFB763400312A82 /* test2.gz in Resources */,
E6EDD6AC26F77C0E00884532 /* test_minor_version_2.7z in Resources */,
06F0665C1FFB763400312A82 /* test9.lzma in Resources */,
06F066661FFB763400312A82 /* test3.7z in Resources */,
06F0664B1FFB763400312A82 /* test.tar in Resources */,
@@ -1073,6 +1083,7 @@
06F066351FFB763400312A82 /* test5.xz in Resources */,
06F066631FFB763400312A82 /* test_complicated_coding_scheme.7z in Resources */,
06F066641FFB763400312A82 /* test_anti_file.7z in Resources */,
E6EDD6A826F7767F00884532 /* test_minor_version_3.7z in Resources */,
064D01AD20FD077D00CAE058 /* test_unicode_pax.tar in Resources */,
06F0665E1FFB763400312A82 /* test_empty_cont.7z in Resources */,
06F066731FFB763400312A82 /* test3.bz2 in Resources */,
@@ -1083,6 +1094,7 @@
06F066571FFB763400312A82 /* test_empty_file.tar in Resources */,
06F066441FFB763400312A82 /* test_data_descriptor.zip in Resources */,
06F066581FFB763400312A82 /* full_test.tar in Resources */,
E6EDD6A926F7767F00884532 /* test_minor_version_4.7z in Resources */,
06F0662B1FFB763400312A82 /* test3.gz in Resources */,
06F0664C1FFB763400312A82 /* test_pax.tar in Resources */,
06F0663A1FFB763400312A82 /* test_multi.xz in Resources */,
@@ -1270,7 +1282,7 @@
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
CURRENT_PROJECT_VERSION = 80;
CURRENT_PROJECT_VERSION = 81;
DEBUG_INFORMATION_FORMAT = dwarf;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = YES;
@@ -1351,7 +1363,7 @@
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
CURRENT_PROJECT_VERSION = 80;
CURRENT_PROJECT_VERSION = 81;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_STRICT_OBJC_MSGSEND = YES;
"FRAMEWORK_SEARCH_PATHS[sdk=appletvos*]" = (
@@ -1412,7 +1424,7 @@
APPLICATION_EXTENSION_API_ONLY = YES;
DEFINES_MODULE = YES;
DYLIB_COMPATIBILITY_VERSION = 1;
DYLIB_CURRENT_VERSION = 80;
DYLIB_CURRENT_VERSION = 81;
DYLIB_INSTALL_NAME_BASE = "@rpath";
INFOPLIST_FILE = SWCompression.xcodeproj/SWCompression.plist;
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
@@ -1439,7 +1451,7 @@
APPLICATION_EXTENSION_API_ONLY = YES;
DEFINES_MODULE = YES;
DYLIB_COMPATIBILITY_VERSION = 1;
DYLIB_CURRENT_VERSION = 80;
DYLIB_CURRENT_VERSION = 81;
DYLIB_INSTALL_NAME_BASE = "@rpath";
INFOPLIST_FILE = SWCompression.xcodeproj/SWCompression.plist;
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1250"
LastUpgradeVersion = "1300"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
+1 -1
View File
@@ -6,7 +6,7 @@
import Foundation
import BitByteData
class SevenZipProperty {
struct SevenZipProperty {
let type: UInt8
let size: Int
+2
View File
@@ -24,6 +24,8 @@ public class LZMA2: DecompressionAlgorithm {
*/
public static func decompress(data: Data) throws -> Data {
let byteReader = LittleEndianByteReader(data: data)
guard byteReader.bytesLeft >= 1
else { throw LZMAError.rangeDecoderInitError }
return try decompress(byteReader, byteReader.byte())
}
+3 -24
View File
@@ -6,10 +6,6 @@
import Foundation
import BitByteData
#if os(Linux)
import CoreFoundation
#endif
extension LittleEndianByteReader {
func zipString(_ length: Int, _ useUtf8: Bool) -> String? {
@@ -21,12 +17,7 @@ extension LittleEndianByteReader {
return String(data: stringData, encoding: .utf8)
}
if String.cp437Available && !stringData.needsUtf8() {
#if os(Windows)
return String(data: stringData, encoding: String.cp437Encoding)
#else
return String(data: stringData, encoding: String.Encoding(rawValue:
CFStringConvertEncodingToNSStringEncoding(String.cp437Encoding)))
#endif
} else {
return String(data: stringData, encoding: .utf8)
}
@@ -36,21 +27,9 @@ extension LittleEndianByteReader {
fileprivate extension String {
#if os(Linux)
#if compiler(>=5.3)
static let cp437Encoding: CFStringEncoding = CFStringEncoding(CFStringEncodings.dosLatinUS.rawValue)
#else
static let cp437Encoding: CFStringEncoding = UInt32(truncatingIfNeeded: UInt(kCFStringEncodingDOSLatinUS))
#endif
static let cp437Available: Bool = CFStringIsEncodingAvailable(cp437Encoding)
#elseif os(Windows)
// "Latin-US (DOS)" CP437-2147483120
static let cp437Encoding = String.Encoding(rawValue: 0x80000400)
static let cp437Available = String.availableStringEncodings.contains(cp437Encoding)
#else
static let cp437Encoding = CFStringEncoding(CFStringEncodings.dosLatinUS.rawValue)
static let cp437Available = CFStringIsEncodingAvailable(cp437Encoding)
#endif
// "Latin-US (DOS)" CP437-2147483120
static let cp437Encoding = String.Encoding(rawValue: 0x80000400)
static let cp437Available = String.availableStringEncodings.contains(cp437Encoding)
}
@@ -13,12 +13,28 @@ import SwiftCLI
protocol BenchmarkCommand: Command {
var files: CollectedParameter { get }
associatedtype InputType
var inputs: CollectedParameter { get }
var benchmarkName: String { get }
var benchmarkFunction: (Data) throws -> Any { get }
func loadInput(_ input: String) throws -> (InputType, Double)
var benchmarkFunction: (InputType) throws -> Any { get }
}
extension BenchmarkCommand where InputType == Data {
func loadInput(_ input: String) throws -> (Data, Double) {
let inputURL = URL(fileURLWithPath: input)
let inputData = try Data(contentsOf: inputURL, options: .mappedIfSafe)
let attr = try FileManager.default.attributesOfItem(atPath: input)
let inputSize = Double(attr[.size] as! UInt64)
return (inputData, inputSize)
}
}
extension BenchmarkCommand {
@@ -28,16 +44,15 @@ extension BenchmarkCommand {
print(String(repeating: "=", count: title.count))
print(title)
for file in self.files.value {
print("File: \(file)")
for input in self.inputs.value {
print("Input: \(input)")
let inputURL = URL(fileURLWithPath: file)
let fileData = try Data(contentsOf: inputURL, options: .mappedIfSafe)
let (loadedInput, inputSize) = try self.loadInput(input)
var totalTime: Double = 0
var totalSpeed: Double = 0
var maxTime = Double(Int.min)
var minTime = Double(Int.max)
var maxSpeed = Double(Int.min)
var minSpeed = Double(Int.max)
print("Iterations: ", terminator: "")
#if !os(Linux)
@@ -45,30 +60,35 @@ extension BenchmarkCommand {
#endif
// Zeroth (excluded) iteration.
let startTime = CFAbsoluteTimeGetCurrent()
_ = try benchmarkFunction(fileData)
_ = try benchmarkFunction(loadedInput)
let timeElapsed = CFAbsoluteTimeGetCurrent() - startTime
print(String(format: "(%.3f) ", timeElapsed), terminator: "")
let speed = inputSize / timeElapsed
print("(\(SpeedFormat(speed).format())), ", terminator: "")
#if !os(Linux)
fflush(__stdoutp)
#endif
for _ in 1...10 {
let startTime = CFAbsoluteTimeGetCurrent()
_ = try benchmarkFunction(fileData)
_ = try benchmarkFunction(loadedInput)
let timeElapsed = CFAbsoluteTimeGetCurrent() - startTime
print(String(format: "%.3f ", timeElapsed), terminator: "")
let speed = inputSize / timeElapsed
print(SpeedFormat(speed).format() + ", ", terminator: "")
#if !os(Linux)
fflush(__stdoutp)
#endif
totalTime += timeElapsed
if timeElapsed > maxTime {
maxTime = timeElapsed
totalSpeed += speed
if speed > maxSpeed {
maxSpeed = speed
}
if timeElapsed < minTime {
minTime = timeElapsed
if speed < minSpeed {
minSpeed = speed
}
}
print(String(format: "\nAverage: %.3f \u{B1} %.3f\n", totalTime / 10, (maxTime - minTime) / 2))
let avgSpeed = totalSpeed / 10
let avgSpeedFormat = SpeedFormat(avgSpeed)
let speedUncertainty = (maxSpeed - minSpeed) / 2
print("\nAverage: \(avgSpeedFormat.format().prefix { $0 != " " }) \u{B1} \(avgSpeedFormat.format(speedUncertainty))\n")
}
}
+98 -1
View File
@@ -4,6 +4,7 @@
// See LICENSE for license information
import Foundation
import SWCompression
import SwiftCLI
class BenchmarkGroup: CommandGroup {
@@ -11,6 +12,102 @@ class BenchmarkGroup: CommandGroup {
let name = "benchmark"
let shortDescription = "Run the specified benchmark using external files"
let children: [Routable] = [UnGzip(), UnXz(), UnBz2(), InfoTar(), InfoZip(), Info7z(), CompDeflate(), CompBz2()]
let children: [Routable] = [UnGzip(), UnXz(), UnBz2(), InfoTar(), InfoZip(), Info7z(), CompDeflate(), CompBz2(), CreateTar()]
}
class CompBz2: BenchmarkCommand {
let name = "comp-bz2"
let shortDescription = "BZip2 compression"
let inputs = CollectedParameter()
let benchmarkName = "BZip2 Compression"
let benchmarkFunction: (Data) throws -> Any = BZip2.compress
}
class CompDeflate: BenchmarkCommand {
let name = "comp-deflate"
let shortDescription = "Deflate compression"
let inputs = CollectedParameter()
let benchmarkName = "Deflate Compression"
let benchmarkFunction: (Data) throws -> Any = Deflate.compress
}
class Info7z: BenchmarkCommand {
let name = "info-7z"
let shortDescription = "7-Zip info function"
let inputs = CollectedParameter()
let benchmarkName = "7-Zip info function"
let benchmarkFunction: (Data) throws -> Any = SevenZipContainer.info
}
class InfoTar: BenchmarkCommand {
let name = "info-tar"
let shortDescription = "TAR info function"
let inputs = CollectedParameter()
let benchmarkName = "TAR info function"
let benchmarkFunction: (Data) throws -> Any = TarContainer.info
}
class InfoZip: BenchmarkCommand {
let name = "info-zip"
let shortDescription = "ZIP info function"
let inputs = CollectedParameter()
let benchmarkName = "ZIP info function"
let benchmarkFunction: (Data) throws -> Any = ZipContainer.info
}
class UnBz2: BenchmarkCommand {
let name = "un-bz2"
let shortDescription = "BZip2 unarchiving"
let inputs = CollectedParameter()
let benchmarkName = "BZip2 Unarchive"
let benchmarkFunction: (Data) throws -> Any = BZip2.decompress
}
class UnGzip: BenchmarkCommand {
let name = "un-gzip"
let shortDescription = "GZip unarchiving"
let inputs = CollectedParameter()
let benchmarkName = "GZip Unarchive"
let benchmarkFunction: (Data) throws -> Any = GzipArchive.unarchive
}
class UnXz: BenchmarkCommand {
let name = "un-xz"
let shortDescription = "XZ unarchiving"
let inputs = CollectedParameter()
let benchmarkName = "XZ Unarchive"
let benchmarkFunction: (Data) throws -> Any = XZArchive.unarchive
}
-20
View File
@@ -1,20 +0,0 @@
// Copyright (c) 2021 Timofey Solomko
// Licensed under MIT License
//
// See LICENSE for license information
import Foundation
import SWCompression
import SwiftCLI
class CompBz2: BenchmarkCommand {
let name = "comp-bz2"
let shortDescription = "BZip2 compression"
let files = CollectedParameter()
let benchmarkName = "BZip2 Compression"
let benchmarkFunction: (Data) throws -> Any = BZip2.compress
}
@@ -1,20 +0,0 @@
// Copyright (c) 2021 Timofey Solomko
// Licensed under MIT License
//
// See LICENSE for license information
import Foundation
import SWCompression
import SwiftCLI
class CompDeflate: BenchmarkCommand {
let name = "comp-deflate"
let shortDescription = "Deflate compression"
let files = CollectedParameter()
let benchmarkName = "Deflate Compression"
let benchmarkFunction: (Data) throws -> Any = Deflate.compress
}
+35
View File
@@ -0,0 +1,35 @@
// Copyright (c) 2021 Timofey Solomko
// Licensed under MIT License
//
// See LICENSE for license information
import Foundation
import SWCompression
import SwiftCLI
class CreateTar: BenchmarkCommand {
let name = "create-tar"
let shortDescription = "Tar container creation"
let inputs = CollectedParameter()
let benchmarkName = "TAR Create"
let benchmarkFunction: ([TarEntry]) throws -> Any = TarContainer.create
func loadInput(_ input: String) throws -> ([TarEntry], Double) {
return try (TarEntry.createEntries(input, false), Double(URL(fileURLWithPath: input).directorySize()))
}
}
fileprivate extension URL {
func directorySize() throws -> Int {
let urls = FileManager.default.enumerator(at: self, includingPropertiesForKeys: nil)?.allObjects as! [URL]
return try urls.lazy.reduce(0) {
(try $1.resourceValues(forKeys: [.totalFileAllocatedSizeKey]).totalFileAllocatedSize ?? 0) + $0
}
}
}
-20
View File
@@ -1,20 +0,0 @@
// Copyright (c) 2021 Timofey Solomko
// Licensed under MIT License
//
// See LICENSE for license information
import Foundation
import SWCompression
import SwiftCLI
class Info7z: BenchmarkCommand {
let name = "info-7z"
let shortDescription = "7-Zip info function"
let files = CollectedParameter()
let benchmarkName = "7-Zip info function"
let benchmarkFunction: (Data) throws -> Any = SevenZipContainer.info
}
-20
View File
@@ -1,20 +0,0 @@
// Copyright (c) 2021 Timofey Solomko
// Licensed under MIT License
//
// See LICENSE for license information
import Foundation
import SWCompression
import SwiftCLI
class InfoTar: BenchmarkCommand {
let name = "info-tar"
let shortDescription = "TAR info function"
let files = CollectedParameter()
let benchmarkName = "TAR info function"
let benchmarkFunction: (Data) throws -> Any = TarContainer.info
}
-20
View File
@@ -1,20 +0,0 @@
// Copyright (c) 2021 Timofey Solomko
// Licensed under MIT License
//
// See LICENSE for license information
import Foundation
import SWCompression
import SwiftCLI
class InfoZip: BenchmarkCommand {
let name = "info-zip"
let shortDescription = "ZIP info function"
let files = CollectedParameter()
let benchmarkName = "ZIP info function"
let benchmarkFunction: (Data) throws -> Any = ZipContainer.info
}
@@ -0,0 +1,60 @@
// Copyright (c) 2021 Timofey Solomko
// Licensed under MIT License
//
// See LICENSE for license information
import Foundation
enum SpeedFormat {
case bytes(Double)
case kilo(Double)
case mega(Double)
case giga(Double)
case tera(Double)
init(_ speed: Double) {
if speed > pow(1000, 4) {
self = .tera(speed)
} else if speed > pow(1000, 3) {
self = .giga(speed)
} else if speed > pow(1000, 2) {
self = .mega(speed)
} else if speed > 1000 {
self = .kilo(speed)
} else {
self = .bytes(speed)
}
}
func format() -> String {
switch self {
case .bytes(let speed):
return String(format: "%.3f B/s", speed)
case .kilo(let speed):
return String(format: "%.3f kB/s", speed / 1000)
case .mega(let speed):
return String(format: "%.3f MB/s", speed / 1000 / 1000)
case .giga(let speed):
return String(format: "%.3f GB/s", speed / 1000 / 1000 / 1000)
case .tera(let speed):
return String(format: "%.3f TB/s", speed / 1000 / 1000 / 1000 / 1000)
}
}
func format(_ speed: Double) -> String {
switch self {
case .bytes(_):
return String(format: "%.3f B/s", speed)
case .kilo(_):
return String(format: "%.3f kB/s", speed / 1000)
case .mega(_):
return String(format: "%.3f MB/s", speed / 1000 / 1000)
case .giga(_):
return String(format: "%.3f GB/s", speed / 1000 / 1000 / 1000)
case .tera(_):
return String(format: "%.3f TB/s", speed / 1000 / 1000 / 1000 / 1000)
}
}
}
-20
View File
@@ -1,20 +0,0 @@
// Copyright (c) 2021 Timofey Solomko
// Licensed under MIT License
//
// See LICENSE for license information
import Foundation
import SWCompression
import SwiftCLI
class UnBz2: BenchmarkCommand {
let name = "un-bz2"
let shortDescription = "BZip2 unarchiving"
let files = CollectedParameter()
let benchmarkName = "BZip2 Unarchive"
let benchmarkFunction: (Data) throws -> Any = BZip2.decompress
}
-20
View File
@@ -1,20 +0,0 @@
// Copyright (c) 2021 Timofey Solomko
// Licensed under MIT License
//
// See LICENSE for license information
import Foundation
import SWCompression
import SwiftCLI
class UnGzip: BenchmarkCommand {
let name = "un-gzip"
let shortDescription = "GZip unarchiving"
let files = CollectedParameter()
let benchmarkName = "GZip Unarchive"
let benchmarkFunction: (Data) throws -> Any = GzipArchive.unarchive
}
-20
View File
@@ -1,20 +0,0 @@
// Copyright (c) 2021 Timofey Solomko
// Licensed under MIT License
//
// See LICENSE for license information
import Foundation
import SWCompression
import SwiftCLI
class UnXz: BenchmarkCommand {
let name = "un-xz"
let shortDescription = "XZ unarchiving"
let files = CollectedParameter()
let benchmarkName = "XZ Unarchive"
let benchmarkFunction: (Data) throws -> Any = XZArchive.unarchive
}
+2 -3
View File
@@ -9,6 +9,8 @@ import SwiftCLI
class SevenZipCommand: ContainerCommand {
typealias ContainerType = SevenZipContainer
let name = "7z"
let shortDescription = "Extracts a 7-Zip container"
@@ -18,7 +20,4 @@ class SevenZipCommand: ContainerCommand {
let archive = Parameter()
let openFunction: (Data) throws -> [SevenZipEntry] = SevenZipContainer.open
let infoFunction: (Data) throws -> [SevenZipEntryInfo] = SevenZipContainer.info
}
@@ -9,7 +9,7 @@ import SwiftCLI
protocol ContainerCommand: Command {
associatedtype Entry: ContainerEntry
associatedtype ContainerType: Container
var info: Flag { get }
var extract: Key<String> { get }
@@ -17,9 +17,6 @@ protocol ContainerCommand: Command {
var archive: Parameter { get }
var openFunction: (Data) throws -> [Entry] { get }
var infoFunction: (Data) throws -> [Entry.Info] { get }
}
extension ContainerCommand {
@@ -33,7 +30,7 @@ extension ContainerCommand {
let fileData = try Data(contentsOf: URL(fileURLWithPath: self.archive.value),
options: .mappedIfSafe)
if info.value {
let entries = try infoFunction(fileData)
let entries = try ContainerType.info(container: fileData)
swcomp.printInfo(entries)
} else if let outputPath = self.extract.value {
if try !isValidOutputDirectory(outputPath, create: true) {
@@ -41,7 +38,7 @@ extension ContainerCommand {
exit(1)
}
let entries = try openFunction(fileData)
let entries = try ContainerType.open(container: fileData)
try swcomp.write(entries, outputPath, verbose.value)
}
}
+1 -85
View File
@@ -92,94 +92,10 @@ class TarCommand: Command {
print("Creating new container at \"\(self.archive.value)\" from \"\(inputPath)\"")
print("d = directory, f = file, l = symbolic link")
}
let entries = try self.createEntries(inputPath, verbose.value)
let entries = try TarEntry.createEntries(inputPath, verbose.value)
let containerData = TarContainer.create(from: entries)
try containerData.write(to: URL(fileURLWithPath: self.archive.value))
}
}
private func createEntries(_ inputPath: String, _ verbose: Bool) throws -> [TarEntry] {
let inputURL = URL(fileURLWithPath: inputPath)
let fileManager = FileManager.default
let fileAttributes = try fileManager.attributesOfItem(atPath: inputPath)
let name = inputURL.relativePath
let entryType: ContainerEntryType
if let typeFromAttributes = fileAttributes[.type] as? FileAttributeType {
switch typeFromAttributes {
case .typeBlockSpecial:
entryType = .blockSpecial
case .typeCharacterSpecial:
entryType = .characterSpecial
case .typeDirectory:
entryType = .directory
case .typeRegular:
entryType = .regular
case .typeSocket:
entryType = .socket
case .typeSymbolicLink:
entryType = .symbolicLink
case .typeUnknown:
entryType = .unknown
default:
entryType = .unknown
}
} else {
entryType = .unknown
}
var info = TarEntryInfo(name: name, type: entryType)
info.creationTime = fileAttributes[.creationDate] as? Date
info.groupID = (fileAttributes[.groupOwnerAccountID] as? NSNumber)?.intValue
info.ownerGroupName = fileAttributes[.groupOwnerAccountName] as? String
info.modificationTime = fileAttributes[.modificationDate] as? Date
info.ownerID = (fileAttributes[.ownerAccountID] as? NSNumber)?.intValue
info.ownerUserName = fileAttributes[.ownerAccountName] as? String
if let posixPermissions = (fileAttributes[.posixPermissions] as? NSNumber)?.intValue {
info.permissions = Permissions(rawValue: UInt32(truncatingIfNeeded: posixPermissions))
}
var entryData = Data()
if entryType == .symbolicLink {
info.linkName = try fileManager.destinationOfSymbolicLink(atPath: inputPath)
} else if entryType != .directory {
entryData = try Data(contentsOf: URL(fileURLWithPath: inputPath))
}
if verbose {
var log = ""
switch entryType {
case .regular:
log += "f: "
case .directory:
log += "d: "
case .symbolicLink:
log += "l:"
default:
log += "u: "
}
log += name
if entryType == .symbolicLink {
log += " -> " + info.linkName
}
print(log)
}
let entry = TarEntry(info: info, data: entryData)
var entries = [TarEntry]()
entries.append(entry)
if entryType == .directory {
for subPath in try fileManager.contentsOfDirectory(atPath: inputPath) {
entries.append(contentsOf: try self.createEntries(inputURL.appendingPathComponent(subPath).relativePath,
verbose))
}
}
return entries
}
}
+2 -3
View File
@@ -9,6 +9,8 @@ import SwiftCLI
class ZipCommand: ContainerCommand {
typealias ContainerType = ZipContainer
let name = "zip"
let shortDescription = "Extracts a ZIP container"
@@ -18,7 +20,4 @@ class ZipCommand: ContainerCommand {
let archive = Parameter()
let openFunction: (Data) throws -> [ZipEntry] = ZipContainer.open
let infoFunction: (Data) throws -> [ZipEntryInfo] = ZipContainer.info
}
@@ -0,0 +1,96 @@
// Copyright (c) 2021 Timofey Solomko
// Licensed under MIT License
//
// See LICENSE for license information
import Foundation
import SWCompression
import SwiftCLI
extension TarEntry {
static func createEntries(_ inputPath: String, _ verbose: Bool) throws -> [TarEntry] {
let inputURL = URL(fileURLWithPath: inputPath)
let fileManager = FileManager.default
let fileAttributes = try fileManager.attributesOfItem(atPath: inputPath)
let name = inputURL.relativePath
let entryType: ContainerEntryType
if let typeFromAttributes = fileAttributes[.type] as? FileAttributeType {
switch typeFromAttributes {
case .typeBlockSpecial:
entryType = .blockSpecial
case .typeCharacterSpecial:
entryType = .characterSpecial
case .typeDirectory:
entryType = .directory
case .typeRegular:
entryType = .regular
case .typeSocket:
entryType = .socket
case .typeSymbolicLink:
entryType = .symbolicLink
case .typeUnknown:
entryType = .unknown
default:
entryType = .unknown
}
} else {
entryType = .unknown
}
var info = TarEntryInfo(name: name, type: entryType)
info.creationTime = fileAttributes[.creationDate] as? Date
info.groupID = (fileAttributes[.groupOwnerAccountID] as? NSNumber)?.intValue
info.ownerGroupName = fileAttributes[.groupOwnerAccountName] as? String
info.modificationTime = fileAttributes[.modificationDate] as? Date
info.ownerID = (fileAttributes[.ownerAccountID] as? NSNumber)?.intValue
info.ownerUserName = fileAttributes[.ownerAccountName] as? String
if let posixPermissions = (fileAttributes[.posixPermissions] as? NSNumber)?.intValue {
info.permissions = Permissions(rawValue: UInt32(truncatingIfNeeded: posixPermissions))
}
var entryData = Data()
if entryType == .symbolicLink {
info.linkName = try fileManager.destinationOfSymbolicLink(atPath: inputPath)
} else if entryType != .directory {
entryData = try Data(contentsOf: URL(fileURLWithPath: inputPath))
}
if verbose {
var log = ""
switch entryType {
case .regular:
log += "f: "
case .directory:
log += "d: "
case .symbolicLink:
log += "l:"
default:
log += "u: "
}
log += name
if entryType == .symbolicLink {
log += " -> " + info.linkName
}
print(log)
}
let entry = TarEntry(info: info, data: entryData)
var entries = [TarEntry]()
entries.append(entry)
if entryType == .directory {
for subPath in try fileManager.contentsOfDirectory(atPath: inputPath) {
entries.append(contentsOf: try self.createEntries(inputURL.appendingPathComponent(subPath).relativePath,
verbose))
}
}
return entries
}
}
+1 -1
View File
@@ -7,7 +7,7 @@ import Foundation
import SWCompression
import SwiftCLI
let cli = CLI(name: "swcomp", version: "4.6.0",
let cli = CLI(name: "swcomp", version: "4.6.1",
description: """
swcomp - a small command-line client for SWCompression framework.
Serves as an example of SWCompression usage.
+4
View File
@@ -67,4 +67,8 @@ class BZip2Tests: XCTestCase {
XCTAssertThrowsError(try BZip2.decompress(data: testData))
}
func testEmptyData() throws {
XCTAssertThrowsError(try BZip2.decompress(data: Data()))
}
}
+4
View File
@@ -151,4 +151,8 @@ class GzipTests: XCTestCase {
XCTAssertThrowsError(try GzipArchive.multiUnarchive(archive: testData))
}
func testEmptyData() throws {
XCTAssertThrowsError(try GzipArchive.unarchive(archive: Data()))
}
}
+4
View File
@@ -51,5 +51,9 @@ class LzmaTests: XCTestCase {
XCTAssertThrowsError(try LZMA.decompress(data: testData))
}
func testEmptyData() throws {
XCTAssertThrowsError(try LZMA.decompress(data: Data()))
XCTAssertThrowsError(try LZMA2.decompress(data: Data()))
}
}
+64 -54
View File
@@ -1,18 +1,24 @@
# Test Results
In this document you can find the results of benchmarking which was performed on Macbook Pro, Late 2011. The main
purpose of these results is to track progress from version to version.
In this document you can find the results of benchmarking which was performed on Macbook Air, Retina, 13-inch, Early
2020 with 1,1 GHz Quad-Core Intel Core i5 CPU. The main purpose of these results is to track progress from version to
version.
__Note:__ Since 4.1.0 version of SWCompression internal functionality related to reading/writing bits and bytes
is published as a separate framework, [BitByteData](https://github.com/tsolomko/BitByteData).
The overall performance heavily depends on the speed of reading and writing, and thus BitByteData's version, which is
specified in a separate column in the tables below, becomes relevant to benchmarking, since newer versions can contain
performance improvements.
## Changelog
__Note:__ Since 4.3.0 version of SWCompression the first (zeroth, actually) iteration is excluded from averages
calculation since this iteration has abnormally longer execution time than any of the following iterations. This
exclusion led not only to (artificially) improved results, but also to the increased quality of the results by reducing
calculated uncertainty.
__September 2021.__ The results are now listed in terms of speed (e.g. MB/s); the benchmarks for Deflate, BZip2 compression and
TAR container creation have been added; all previous results have been removed since newer hardware is now used; added
results for the `-Ounchecked` compiler option; the macOS version is now listed for results.
__April 2018.__ The first (zeroth, actually) iteration is now excluded from averages calculation since this iteration
has abnormally longer execution time than any of the following iterations. This exclusion led not only to (artificially)
improved results, but also to the increased quality of the results by reducing calculated uncertainty. In addition, the
averages are now computed over 10 iterations instead of 6.
__January 2018.__ SWCompression internal functionality related to reading/writing bits and bytes is published as a
separate framework, [BitByteData](https://github.com/tsolomko/BitByteData). The overall performance heavily depends on
the speed of reading and writing, and thus BitByteData's version, which is specified in a separate column in the tables
below, becomes relevant to benchmarking, since newer versions can contain performance improvements.
## Tests description
@@ -29,64 +35,68 @@ using "Release" configuration.
__Note:__ External commands used to create compressed files were run using their default sets of options.
__Note:__ All results are averages over 10 iterations (6 iterations until 4.3.0 version).
__Note:__ All results are averages over 10 iterations. If the uncertainty is not listed it means that it is less than
10% in terms of the units listed.
## BZip2 Decompress
|SWCompression<br>version|BitByteData<br>version|Swift<br>version|Test 1|Test 2|Test 3|
|:---:|:---:|:---:|---|---|---|
|4.0.0|&mdash;|4.0.X|6.821 ± 0.042|54.214 ± 1.398|7.255 ± 0.117|
|4.0.1|&mdash;|4.0.X|6.797 ± 0.080|54.046 ± 1.070|7.177 ± 0.029|
|4.1.0|1.0.1|4.0.X|4.452 ± 0.125|36.768 ± 0.382|4.880 ± 0.094|
|4.3.0|1.2.0|4.1.0|3.481 ± 0.038|27.187 ± 0.152|3.914 ± 0.091|
|4.4.0|1.2.0|4.1.2|3.548 ± 0.037|27.950 ± 0.975|3.956 ± 0.063|
|SWCompression<br>version|BitByteData<br>version|macOS<br>version|Swift<br>version|Test 1|Test 2|Test 3|
|:---:|:---:|:---:|:---:|---|---|---|
|4.6.0|2.0.1|11.5.2|5.4.2|2.764 MB/s|2.973 MB/s|2.410 MB/s|
|4.6.0-unchecked|2.0.1|11.5.2|5.4.2|3.279 ± 0.429 MB/s|4.361 ± 0.306 MB/s|3.169 ± 0.180 MB/s|
## XZ Unarchive (LZMA/LZMA2 Decompress)
|SWCompression<br>version|BitByteData<br>version|Swift<br>version|Test 1|Test 2|Test 3|
|:---:|:---:|:---:|---|---|---|
|4.0.0|&mdash;|4.0.X|error|24.663 ± 2.349|2.904 ± 0.076|
|4.0.1|&mdash;|4.0.X|2.475 ± 0.067|23.507 ± 0.423|2.901 ± 0.049|
|4.1.0|1.0.1|4.0.X|2.480 ± 0.091|24.126 ± 1.239|2.892 ± 0.052|
|4.3.0|1.2.0|4.1.0|2.664 ± 0.031|26.030 ± 1.200|3.111 ± 0.053|
|4.4.0|1.2.0|4.1.2|2.494 ± 0.038|23.773 ± 0.563|2.912 ± 0.018|
|SWCompression<br>version|BitByteData<br>version|macOS<br>version|Swift<br>version|Test 1|Test 2|Test 3|
|:---:|:---:|:---:|:---:|---|---|---|
|4.6.0|2.0.1|11.5.2|5.4.2|5.246 ± 0.279 MB/s|5.543 ± 0.143 MB/s|5.322 ± 0.26 MB/s|
|4.6.0-unchecked|2.0.1|11.5.2|5.4.2|6.015 ± 0.319 MB/s|6.374 ± 0.143 MB/s|5.841 ± 0.212 MB/s|
## GZip Unarchive (Deflate Decompress)
|SWCompression<br>version|BitByteData<br>version|Swift<br>version|Test 1|Test 2|Test 3|
|:---:|:---:|:---:|---|---|---|
|4.0.0|&mdash;|4.0.X|4.007 ± 0.196|32.043 ± 0.581|4.303 ± 0.045|
|4.0.1|&mdash;|4.0.X|3.886 ± 0.100|32.390 ± 0.896|4.295 ± 0.040|
|4.1.0|1.0.1|4.0.X|2.886 ± 0.571|22.134 ± 1.473|2.700 ± 0.168|
|4.3.0|1.2.0|4.1.0|1.622 ± 0.016|13.641 ± 0.069|1.804 ± 0.028|
|4.4.0|1.2.0|4.1.2|1.665 ± 0.037|14.046 ± 0.093|1.858 ± 0.055|
|SWCompression<br>version|BitByteData<br>version|macOS<br>version|Swift<br>version|Test 1|Test 2|Test 3|
|:---:|:---:|:---:|:---:|---|---|---|
|4.6.0|2.0.1|11.5.2|5.4.2|5.946 ± 0.432 MB/s|6.034 ± 0.175 MB/s|6.071 ± 0.25 MB/s|
|4.6.0-unchecked|2.0.1|11.5.2|5.4.2|8.562 ± 0.388 MB/s|9.908 ± 0.204 MB/s|8.286 ± 0.250 MB/s|
## BZip2 Compress
|SWCompression<br>version|BitByteData<br>version|macOS<br>version|Swift<br>version|Test 1|Test 2|Test 3|
|:---:|:---:|:---:|:---:|---|---|---|
|4.6.0|2.0.1|11.5.2|5.4.2|3.540 MB/s|2.862 MB/s|4.253 MB/s|
|4.6.0-unchecked|2.0.1|11.5.2|5.4.2|3.816 MB/s|3.060 MB/s|4.647 MB/s|
## Deflate Compress
|SWCompression<br>version|BitByteData<br>version|macOS<br>version|Swift<br>version|Test 1|Test 2|Test 3|
|:---:|:---:|:---:|:---:|---|---|---|
|4.6.0|2.0.1|11.5.2|5.4.2|12.177 ± 0.259 MB/s|8.809 MB/s|13.594 ± 0.355 MB/s|
|4.6.0-unchecked|2.0.1|11.5.2|5.4.2|12.914 ± 0.355 MB/s|9.361 MB/s|15.020 ± 0.277 MB/s|
## 7-Zip Info Function
|SWCompression<br>version|BitByteData<br>version|Swift<br>version|Test 1|Test 2|Test 3|
|:---:|:---:|:---:|---|---|---|
|4.0.0|&mdash;|4.0.X|0.270 ± 0.010|crash|0.601 ± 0.057|
|4.0.1|&mdash;|4.0.X|0.258 ± 0.003|0.601 ± 0.010|0.473 ± 0.008|
|4.1.0|1.0.1|4.0.X|0.062 ± 0.008|0.208 ± 0.010|0.122 ± 0.003|
|4.3.0|1.2.0|4.1.0|0.060 ± 0.006|0.208 ± 0.008|0.123 ± 0.008|
|4.4.0|1.2.0|4.1.2|0.062 ± 0.005|0.212 ± 0.008|0.122 ± 0.007|
|SWCompression<br>version|BitByteData<br>version|macOS<br>version|Swift<br>version|Test 1|Test 2|Test 3|
|:---:|:---:|:---:|:---:|---|---|---|
|4.6.0|2.0.1|11.5.2|5.4.2|77.072 ± 6.625 MB/s|111.246 ± 4.855 MB/s|38.721 ± 2.681 MB/s|
|4.6.0-unchecked|2.0.1|11.5.2|5.4.2|82.367 ± 7.381 MB/s|116.923 ± 3.812 MB/s|38.519 ± 2.988 MB/s|
## TAR Info Function
|SWCompression<br>version|BitByteData<br>version|Swift<br>version|Test 1|Test 2|Test 3|
|:---:|:---:|:---:|---|---|---|
|4.0.0|&mdash;|4.0.X|0.248 ± 0.172|1.563 ± 0.442|1.254 ± 0.277|
|4.0.1|&mdash;|4.0.X|0.187 ± 0.177|1.257 ± 0.404|1.016 ± 0.325|
|4.1.0|1.0.1|4.0.X|0.194 ± 0.190|1.335 ± 0.475|1.062 ± 0.353|
|4.3.0|1.2.0|4.1.0|0.111 ± 0.008|1.014 ± 0.016|0.813 ± 0.015|
|4.4.0|1.2.0|4.1.2|0.095 ± 0.005|0.810 ± 0.025|0.680 ± 0.014|
|SWCompression<br>version|BitByteData<br>version|macOS<br>version|Swift<br>version|Test 1|Test 2|Test 3|
|:---:|:---:|:---:|:---:|---|---|---|
|4.6.0|2.0.1|11.5.2|5.4.2|967.792 ± 58.436 MB/s|1.006 GB/s|217.082 ± 19.783 MB/s|
|4.6.0-unchecked|2.0.1|11.5.2|5.4.2|1.073 ± 0.115 GB/s|1.053 GB/s|246.854 ± 6.763 MB/s|
## ZIP Info Function
|SWCompression<br>version|BitByteData<br>version|Swift<br>version|Test 1|Test 2|Test 3|
|:---:|:---:|:---:|---|---|---|
|4.0.0|&mdash;|4.0.X|0.072 ± 0.065|0.669 ± 0.147|0.120 ± 0.081|
|4.0.1|&mdash;|4.0.X|0.076 ± 0.064|0.670 ± 0.142|0.123 ± 0.080|
|4.1.0|1.0.1|4.0.X|0.063 ± 0.076|0.148 ± 0.107|0.105 ± 0.089|
|4.3.0|1.2.0|4.1.0|0.044 ± 0.007|0.122 ± 0.009|0.086 ± 0.008|
|4.4.0|1.2.0|4.1.2|0.048 ± 0.005|0.125 ± 0.005|0.091 ± 0.010|
|SWCompression<br>version|BitByteData<br>version|macOS<br>version|Swift<br>version|Test 1|Test 2|Test 3|
|:---:|:---:|:---:|:---:|---|---|---|
|4.6.0|2.0.1|11.5.2|5.4.2|597.002 ± 75.017 MB/s|1.941 ± 0.135 GB/s|389.626 ± 22.006 MB/s|
|4.6.0-unchecked|2.0.1|11.5.2|5.4.2|685.266 ± 53.895 MB/s|2.147 GB/s|420.461 ± 15.156 MB/s|
## TAR Create Function
|SWCompression<br>version|BitByteData<br>version|macOS<br>version|Swift<br>version|Test 1|Test 2|Test 3|
|:---:|:---:|:---:|:---:|---|---|---|
|4.6.0|2.0.1|11.5.2|5.4.2|139.649 ± 8.310 MB/s|446.101 ± 21.476 MB/s|215.556 ± 17.5 MB/s|
|4.6.0-unchecked|2.0.1|11.5.2|5.4.2|142.681 ± 5.664 MB/s|459.403 ± 17.862 MB/s|220.238 ± 3.476 MB/s|
+66
View File
@@ -19,6 +19,11 @@ class SevenZipTests: XCTestCase {
XCTAssertThrowsError(try SevenZipContainer.open(container: testData))
}
func testEmptyData() throws {
XCTAssertThrowsError(try SevenZipContainer.info(container: Data()))
XCTAssertThrowsError(try SevenZipContainer.open(container: Data()))
}
func test1() throws {
let testData = try Constants.data(forTest: "test1", withType: SevenZipTests.testType)
let entries = try SevenZipContainer.open(container: testData)
@@ -388,4 +393,65 @@ class SevenZipTests: XCTestCase {
XCTAssertEqual(entries[0].data, answerData)
}
func testFormatMinorVersions() throws {
let answerData = try Constants.data(forAnswer: "test2")
var testData = try Constants.data(forTest: "test_minor_version_2", withType: SevenZipTests.testType)
var entries = try SevenZipContainer.open(container: testData)
XCTAssertEqual(entries.count, 1)
XCTAssertEqual(entries[0].info.name, "test2.answer")
XCTAssertEqual(entries[0].info.type, .regular)
XCTAssertEqual(entries[0].info.size, answerData.count)
XCTAssertEqual(entries[0].info.permissions, Permissions(rawValue: 0))
XCTAssertEqual(entries[0].info.dosAttributes, DosAttributes(rawValue: 0x20))
// Checking times' values is a bit difficult since they are extremely precise.
XCTAssertNotNil(entries[0].info.modificationTime)
XCTAssertNil(entries[0].info.accessTime)
XCTAssertNil(entries[0].info.creationTime)
XCTAssertEqual(entries[0].info.hasStream, true)
XCTAssertEqual(entries[0].info.isEmpty, false)
XCTAssertEqual(entries[0].info.isAnti, false)
XCTAssertEqual(entries[0].info.crc, 4168830779)
XCTAssertEqual(entries[0].data, answerData)
testData = try Constants.data(forTest: "test_minor_version_3", withType: SevenZipTests.testType)
entries = try SevenZipContainer.open(container: testData)
XCTAssertEqual(entries.count, 1)
XCTAssertEqual(entries[0].info.name, "test2.answer")
XCTAssertEqual(entries[0].info.type, .regular)
XCTAssertEqual(entries[0].info.size, answerData.count)
XCTAssertEqual(entries[0].info.permissions, Permissions(rawValue: 420))
XCTAssertEqual(entries[0].info.dosAttributes, DosAttributes(rawValue: 0x20))
// Checking times' values is a bit difficult since they are extremely precise.
XCTAssertNotNil(entries[0].info.modificationTime)
XCTAssertNotNil(entries[0].info.accessTime)
XCTAssertNotNil(entries[0].info.creationTime)
XCTAssertEqual(entries[0].info.hasStream, true)
XCTAssertEqual(entries[0].info.isEmpty, false)
XCTAssertEqual(entries[0].info.isAnti, false)
XCTAssertEqual(entries[0].info.crc, 4168830779)
XCTAssertEqual(entries[0].data, answerData)
testData = try Constants.data(forTest: "test_minor_version_4", withType: SevenZipTests.testType)
entries = try SevenZipContainer.open(container: testData)
XCTAssertEqual(entries.count, 1)
XCTAssertEqual(entries[0].info.name, "test2.answer")
XCTAssertEqual(entries[0].info.type, .regular)
XCTAssertEqual(entries[0].info.size, answerData.count)
XCTAssertEqual(entries[0].info.permissions, Permissions(rawValue: 420))
XCTAssertEqual(entries[0].info.dosAttributes, DosAttributes(rawValue: 0x20))
// Checking times' values is a bit difficult since they are extremely precise.
XCTAssertNotNil(entries[0].info.modificationTime)
XCTAssertNotNil(entries[0].info.accessTime)
XCTAssertNotNil(entries[0].info.creationTime)
XCTAssertEqual(entries[0].info.hasStream, true)
XCTAssertEqual(entries[0].info.isEmpty, false)
XCTAssertEqual(entries[0].info.isAnti, false)
XCTAssertEqual(entries[0].info.crc, 4168830779)
XCTAssertEqual(entries[0].data, answerData)
}
}
+5
View File
@@ -18,6 +18,11 @@ class ZipTests: XCTestCase {
let testData = try Constants.data(forAnswer: "test6")
XCTAssertThrowsError(try ZipContainer.open(container: testData))
}
func testEmptyData() throws {
XCTAssertThrowsError(try ZipContainer.info(container: Data()))
XCTAssertThrowsError(try ZipContainer.open(container: Data()))
}
func testBigContainer() throws {
let testData = try Constants.data(forTest: "SWCompressionSourceCode", withType: ZipTests.testType)
+4
View File
@@ -52,4 +52,8 @@ class ZlibTests: XCTestCase {
XCTAssertThrowsError(try ZlibArchive.unarchive(archive: testData))
}
func testEmptyData() throws {
XCTAssertThrowsError(try ZlibArchive.unarchive(archive: Data()))
}
}
+20 -8
View File
@@ -37,12 +37,18 @@ stages:
WATCHOS_ACTIONS: 'clean build'
WATCHOS_SIMULATOR: 'Apple Watch Series 4 - 44mm'
UTILS_PW_XCF_FLAG: '--xcf'
# macosSwift54:
# imageName: 'macOS-11.3'
# DEVELOPER_DIR: '/Applications/Xcode_12.5.app'
# WATCHOS_ACTIONS: 'clean test'
# WATCHOS_SIMULATOR: 'Apple Watch Series 6 - 44mm'
# UTILS_PW_XCF_FLAG: '--xcf'
macosSwift54:
imageName: 'macOS-11'
DEVELOPER_DIR: '/Applications/Xcode_12.5.1.app'
WATCHOS_ACTIONS: 'clean test'
WATCHOS_SIMULATOR: 'Apple Watch Series 6 - 44mm'
UTILS_PW_XCF_FLAG: '--xcf'
macosSwift55:
imageName: 'macOS-11'
DEVELOPER_DIR: '/Applications/Xcode_13.0.app'
WATCHOS_ACTIONS: 'clean test'
WATCHOS_SIMULATOR: 'Apple Watch Series 6 - 44mm'
UTILS_PW_XCF_FLAG: '--xcf'
pool:
vmImage: $(imageName)
steps:
@@ -74,7 +80,10 @@ stages:
containerImage: 'swift:5.3.3-bionic'
linuxSwift54:
imageName: 'ubuntu-18.04'
containerImage: 'swift:5.4.2-bionic'
containerImage: 'swift:5.4.3-bionic'
linuxSwift55:
imageName: 'ubuntu-18.04'
containerImage: 'swift:5.5-bionic'
pool:
vmImage: $(imageName)
container: $[ variables['containerImage'] ]
@@ -90,7 +99,10 @@ stages:
matrix:
windowsSwift54:
imageName: 'windows-2019'
SWIFT_VERSION: '5.4.2'
SWIFT_VERSION: '5.4.3'
windowsSwift55:
imageName: 'windows-2019'
SWIFT_VERSION: '5.5'
pool:
vmImage: $(imageName)
variables: