Files
2026-06-13 16:22:23 +08:00

174 lines
8.4 KiB
Swift

// Copyright (c) 2026 Timofey Solomko
// Licensed under MIT License
//
// See LICENSE for license information
import XCTest
import SWCompression
class LZ4CompressionTests: XCTestCase {
func answerTest(_ testName: String) throws {
let answerData = try Constants.data(forAnswer: testName)
let compressedData = LZ4.compress(data: answerData)
let redecompressedData = try LZ4.decompress(data: compressedData)
XCTAssertEqual(redecompressedData, answerData)
if answerData.count > 0 { // Compression ratio is always bad for empty file.
let compressionRatio = Double(answerData.count) / Double(compressedData.count)
print(String(format: "LZ4.\(testName).compressionRatio = %.3f", compressionRatio))
}
}
func stringTest(_ string: String) throws {
let answerData = Data(string.utf8)
let compressedData = LZ4.compress(data: answerData)
let redecompressedData = try LZ4.decompress(data: compressedData)
XCTAssertEqual(redecompressedData, answerData)
}
func testLZ4CompressStrings() throws {
try stringTest("ban")
try stringTest("banana")
try stringTest("abaaba")
try stringTest("abracadabra")
try stringTest("cabbage")
try stringTest("baabaabac")
try stringTest("AAAAAAABBBBCCCD")
try stringTest("AAAAAAA")
try stringTest("qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM1234567890")
}
func testLZ4CompressBytes() throws {
var bytes = ""
for i: UInt8 in 0...255 {
bytes += String(format: "%c", i)
}
try stringTest(bytes)
}
func testWithAnswer1LZ4Compress() throws {
try answerTest("test1")
}
func testWithAnswer2LZ4Compress() throws {
try answerTest("test2")
}
func testWithAnswer3LZ4Compress() throws {
try answerTest("test3")
}
func testWithAnswer4LZ4Compress() throws {
try answerTest("test4")
}
func testWithAnswer5LZ4Compress() throws {
try answerTest("test5")
}
func testWithAnswer6LZ4Compress() throws {
try answerTest("test6")
}
func testWithAnswer7LZ4Compress() throws {
try answerTest("test7")
}
func testWithAnswer8LZ4Compress() throws {
try answerTest("test8")
}
func testWithAnswer9LZ4Compress() throws {
try answerTest("test9")
}
func testWithRandomOptions() throws {
for i in 1...9 {
let independentBlocks = Bool.random()
let blockChecksums = Bool.random()
let contentChecksum = Bool.random()
let contentSize = Bool.random()
let blockSize = Int.random(in: 1024...4 * 1024 * 1024)
let answerData = try Constants.data(forAnswer: "test\(i)")
let compressedData = LZ4.compress(data: answerData, independentBlocks: independentBlocks,
blockChecksums: blockChecksums, contentChecksum: contentChecksum,
contentSize: contentSize, blockSize: blockSize)
do {
let redecompressedData = try LZ4.decompress(data: compressedData)
XCTAssertEqual(redecompressedData, answerData, "Test #\(i) failed (result mismatch) with the following " +
"options: independent blocks = \(independentBlocks), block checksums = \(blockChecksums), " +
"content checksum = \(contentChecksum), content size = \(contentSize), " +
"block size = \(blockSize) bytes")
} catch let error {
XCTFail("Test #\(i) failed (DataError.\(error) caught) with the following options: " +
"independent blocks = \(independentBlocks), block checksums = \(blockChecksums), " +
"content checksum = \(contentChecksum), content size = \(contentSize), " +
"block size = \(blockSize) bytes")
}
}
}
func testDictionary() throws {
let answerData = try Constants.data(forTest: "SWCompressionSourceCode", withType: "tar")
let dictData = try Constants.data(forTest: "lz4_dict", withType: "")
var compressedData = LZ4.compress(data: answerData, independentBlocks: true, blockChecksums: Bool.random(),
contentChecksum: Bool.random(), contentSize: Bool.random(),
blockSize: 256 * 1024, dictionary: dictData, dictionaryID: nil)
var redecompressedData = try LZ4.decompress(data: compressedData, dictionary: dictData)
XCTAssertEqual(redecompressedData, answerData)
var compressionRatio = Double(answerData.count) / Double(compressedData.count)
print(String(format: "LZ4.dict.compressionRatio = %.3f", compressionRatio))
compressedData = LZ4.compress(data: answerData, independentBlocks: false, blockChecksums: Bool.random(),
contentChecksum: Bool.random(), contentSize: Bool.random(),
blockSize: 256 * 1024, dictionary: dictData, dictionaryID: nil)
redecompressedData = try LZ4.decompress(data: compressedData, dictionary: dictData)
XCTAssertEqual(redecompressedData, answerData)
compressionRatio = Double(answerData.count) / Double(compressedData.count)
print(String(format: "LZ4.dict_BD.compressionRatio = %.3f", compressionRatio))
compressedData = LZ4.compress(data: answerData, independentBlocks: true, blockChecksums: Bool.random(),
contentChecksum: Bool.random(), contentSize: Bool.random(),
blockSize: 256 * 1024, dictionary: dictData, dictionaryID: 20000)
redecompressedData = try LZ4.decompress(data: compressedData, dictionary: dictData, dictionaryID: 20000)
XCTAssertEqual(redecompressedData, answerData)
// If the wrong dictionary ID is specified the decompression should fail.
XCTAssertThrowsError(try LZ4.decompress(data: compressedData, dictionary: dictData, dictionaryID: 12345))
}
func testSmallDictionary() throws {
let answerData = try Constants.data(forTest: "SWCompressionSourceCode", withType: "tar")
let dictData = try Constants.data(forTest: "lz4_small_dict", withType: "")
var compressedData = LZ4.compress(data: answerData, independentBlocks: true, blockChecksums: Bool.random(),
contentChecksum: Bool.random(), contentSize: Bool.random(),
blockSize: 256 * 1024, dictionary: dictData, dictionaryID: nil)
var redecompressedData = try LZ4.decompress(data: compressedData, dictionary: dictData)
XCTAssertEqual(redecompressedData, answerData)
var compressionRatio = Double(answerData.count) / Double(compressedData.count)
print(String(format: "LZ4.small_dict.compressionRatio = %.3f", compressionRatio))
compressedData = LZ4.compress(data: answerData, independentBlocks: false, blockChecksums: Bool.random(),
contentChecksum: Bool.random(), contentSize: Bool.random(),
blockSize: 256 * 1024, dictionary: dictData, dictionaryID: nil)
redecompressedData = try LZ4.decompress(data: compressedData, dictionary: dictData)
XCTAssertEqual(redecompressedData, answerData)
compressionRatio = Double(answerData.count) / Double(compressedData.count)
print(String(format: "LZ4.small_dict_BD.compressionRatio = %.3f", compressionRatio))
}
func testTrickySequence() throws {
// This test helped us find an issue with implementation (match index was wrongly used as cyclical index).
// The last 10 bytes (0x01 - 0x00) are only here to allow creation of a sequence with a match.
let answerData = Data([0x61, 0x6C, 0x20, 0x2D, 0x43, 0x20, 0x2D, 0x43, 0x20, 0x2D, 0x2D, 0x01, 0x02, 0x03, 0x04,
0x05, 0x06, 0x07, 0x08, 0x09, 0x00])
let compressedData = LZ4.compress(data: answerData, independentBlocks: false, blockChecksums: true,
contentChecksum: true, contentSize: true)
let redecompressedData = try LZ4.decompress(data: compressedData)
XCTAssertEqual(redecompressedData, answerData)
}
}