Skip to content

Commit a333236

Browse files
committed
[Tests] Add many tests that check that checksum errors are thrown correctly
1 parent 20e8db7 commit a333236

8 files changed

Lines changed: 177 additions & 10 deletions

File tree

Sources/XZ/XZArchive.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ public class XZArchive: Archive {
9797
var indexSize = -1
9898
while true {
9999
let blockHeaderSize = byteReader.byte()
100-
if blockHeaderSize == 0 { /// Zero value of blockHeaderSize means that we've encountered INDEX.
100+
if blockHeaderSize == 0 { // Zero value of blockHeaderSize means that we've encountered the index.
101101
indexSize = try processIndex(blockInfos, byteReader)
102102
break
103103
} else {

Sources/ZIP/ZipContainer.swift

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -70,17 +70,17 @@ public class ZipContainer: Container {
7070
case .deflate:
7171
let bitReader = LsbBitReader(byteReader)
7272
fileData = try Deflate.decompress(bitReader)
73-
// Sometimes `bitReader` has misaligned state after Deflate decompression,
74-
// so we need to align before getting end index back.
73+
// Sometimes bitReader is misaligned after Deflate decompression, so we need to align before getting end
74+
// index back.
7575
bitReader.align()
7676
byteReader.offset = bitReader.offset
7777
case .bzip2:
7878
#if (!SWCOMPRESSION_POD_ZIP) || (SWCOMPRESSION_POD_ZIP && SWCOMPRESSION_POD_BZ2)
7979
// BZip2 algorithm uses different bit numbering scheme.
8080
let bitReader = MsbBitReader(byteReader)
8181
fileData = try BZip2.decompress(bitReader)
82-
// Sometimes `bitReader` has misaligned state after BZip2 decompression,
83-
// so we need to align before getting the end index back.
82+
// Sometimes bitReader is misaligned after BZip2 decompression, so we need to align before getting end
83+
// index back.
8484
bitReader.align()
8585
byteReader.offset = bitReader.offset
8686
#else

Tests/BZip2Tests.swift

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,4 +71,22 @@ class BZip2Tests: XCTestCase {
7171
XCTAssertThrowsError(try BZip2.decompress(data: Data()))
7272
}
7373

74+
func testChecksumMismatch() throws {
75+
// Here we test that an error for checksum mismatch is thrown correctly and its associated value contains
76+
// expected data. We do this by programmatically adjusting the input: we change one of the bytes for the checkum,
77+
// which makes it incorrect.
78+
var testData = try Constants.data(forTest: "test1", withType: BZip2Tests.testType)
79+
// The checksum is the last 4 bytes.
80+
testData[testData.endIndex - 2] &+= 1
81+
var thrownError: Error? = nil
82+
XCTAssertThrowsError(try BZip2.decompress(data: testData)) { thrownError = $0 }
83+
XCTAssertTrue(thrownError is BZip2Error, "Unexpected error type: \(type(of: thrownError))")
84+
if case let .some(.wrongCRC(decompressedData)) = thrownError as? BZip2Error {
85+
let answerData = try Constants.data(forAnswer: "test1")
86+
XCTAssertEqual(decompressedData, answerData)
87+
} else {
88+
XCTFail("Unexpected error: \(String(describing: thrownError))")
89+
}
90+
}
91+
7492
}

Tests/GzipTests.swift

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,4 +155,44 @@ class GzipTests: XCTestCase {
155155
XCTAssertThrowsError(try GzipArchive.unarchive(archive: Data()))
156156
}
157157

158+
func testChecksumMismatch() throws {
159+
// Here we test that an error for checksum mismatch is thrown correctly and its associated value contains
160+
// expected data. We do this by programmatically adjusting the input: we change one of the bytes for the checkum,
161+
// which makes it incorrect.
162+
var testData = try Constants.data(forTest: "test1", withType: GzipTests.testType)
163+
// Here we modify the stored value of crc32.
164+
testData[41] &+= 1
165+
var thrownError: Error? = nil
166+
XCTAssertThrowsError(try GzipArchive.unarchive(archive: testData)) { thrownError = $0 }
167+
XCTAssertTrue(thrownError is GzipError, "Unexpected error type: \(type(of: thrownError))")
168+
if case let .some(.wrongCRC(members)) = thrownError as? GzipError {
169+
XCTAssertEqual(members.count, 1)
170+
let answerData = try Constants.data(forAnswer: "test1")
171+
XCTAssertEqual(members.first?.data, answerData)
172+
} else {
173+
XCTFail("Unexpected error: \(String(describing: thrownError))")
174+
}
175+
}
176+
177+
func testMultiUnarchiveChecksumMismatch() throws {
178+
// Here we test that an error for checksum mismatch is thrown correctly and its associated value contains
179+
// expected data. We do this by programmatically adjusting the input: we change one of the bytes for the checkum,
180+
// which makes it incorrect.
181+
var testData = try Constants.data(forTest: "test_multi", withType: GzipTests.testType)
182+
// Here we modify the stored value of crc32.
183+
testData[2289] &+= 1
184+
var thrownError: Error? = nil
185+
XCTAssertThrowsError(try GzipArchive.multiUnarchive(archive: testData)) { thrownError = $0 }
186+
XCTAssertTrue(thrownError is GzipError, "Unexpected error type: \(type(of: thrownError))")
187+
if case let .some(.wrongCRC(members)) = thrownError as? GzipError {
188+
XCTAssertEqual(members.count, 2)
189+
var answerData = try Constants.data(forAnswer: "test1")
190+
XCTAssertEqual(members[0].data, answerData)
191+
answerData = try Constants.data(forAnswer: "test2")
192+
XCTAssertEqual(members[1].data, answerData)
193+
} else {
194+
XCTFail("Unexpected error: \(String(describing: thrownError))")
195+
}
196+
}
197+
158198
}

Tests/LZ4Tests.swift

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -183,4 +183,23 @@ class LZ4Tests: XCTestCase {
183183
XCTAssertEqual(result[1], try Constants.data(forAnswer: "test4"))
184184
}
185185

186+
func testChecksumMismatch() throws {
187+
// Here we test that an error for checksum mismatch is thrown correctly and its associated value contains
188+
// expected data. We do this by programmatically adjusting the input: we change one of the bytes for the checkum,
189+
// which makes it incorrect.
190+
var testData = try Constants.data(forTest: "test1", withType: LZ4Tests.testType)
191+
// The content checksum is the last 4 bytes.
192+
testData[testData.endIndex - 2] &+= 1
193+
var thrownError: Error? = nil
194+
XCTAssertThrowsError(try LZ4.decompress(data: testData)) { thrownError = $0 }
195+
XCTAssertTrue(thrownError is DataError, "Unexpected error type: \(type(of: thrownError))")
196+
if case let .some(.checksumMismatch(decompressedData)) = thrownError as? DataError {
197+
XCTAssertEqual(decompressedData.count, 1)
198+
let answerData = try Constants.data(forAnswer: "test1")
199+
XCTAssertEqual(decompressedData.first, answerData)
200+
} else {
201+
XCTFail("Unexpected error: \(String(describing: thrownError))")
202+
}
203+
}
204+
186205
}

Tests/XzTests.swift

Lines changed: 43 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -58,9 +58,8 @@ class XZTests: XCTestCase {
5858
func testMultiStreamNoPadding() throws {
5959
// Doesn't contain any padding.
6060
let testData = try Constants.data(forTest: "test_multi", withType: XZTests.testType)
61-
62-
let decompressedData = try XZArchive.unarchive(archive: testData)
6361
let splitDecompressedData = try XZArchive.splitUnarchive(archive: testData)
62+
XCTAssertEqual(splitDecompressedData.count, 4)
6463

6564
var answerData = Data()
6665
for i in 1...4 {
@@ -69,6 +68,7 @@ class XZTests: XCTestCase {
6968
XCTAssertEqual(splitDecompressedData[i - 1], currentAnswerData)
7069
}
7170

71+
let decompressedData = try XZArchive.unarchive(archive: testData)
7272
XCTAssertEqual(decompressedData, answerData)
7373
}
7474

@@ -77,11 +77,9 @@ class XZTests: XCTestCase {
7777
// After second - 4 bytes of padding.
7878
// Third - 8 bytes.
7979
// At the end - 4 bytes.
80-
8180
let testData = try Constants.data(forTest: "test_multi_pad", withType: XZTests.testType)
82-
83-
let decompressedData = try XZArchive.unarchive(archive: testData)
8481
let splitDecompressedData = try XZArchive.splitUnarchive(archive: testData)
82+
XCTAssertEqual(splitDecompressedData.count, 4)
8583

8684
var answerData = Data()
8785
for i in 1...4 {
@@ -91,6 +89,7 @@ class XZTests: XCTestCase {
9189
XCTAssertEqual(splitDecompressedData[i - 1], currentAnswerData)
9290
}
9391

92+
let decompressedData = try XZArchive.unarchive(archive: testData)
9493
XCTAssertEqual(decompressedData, answerData)
9594
}
9695

@@ -120,4 +119,43 @@ class XZTests: XCTestCase {
120119
XCTAssertThrowsError(try XZArchive.unarchive(archive: testData))
121120
}
122121

122+
func testChecksumMismatch() throws {
123+
// Here we test that an error for checksum mismatch is thrown correctly and its associated value contains
124+
// expected data. We do this by programmatically adjusting the input: we change one of the bytes for the checkum,
125+
// which makes it incorrect.
126+
var testData = try Constants.data(forTest: "test1", withType: XZTests.testType)
127+
// Here we modify the stored value of crc64.
128+
testData[46] &+= 1
129+
var thrownError: Error? = nil
130+
XCTAssertThrowsError(try XZArchive.unarchive(archive: testData)) { thrownError = $0 }
131+
XCTAssertTrue(thrownError is XZError, "Unexpected error type: \(type(of: thrownError))")
132+
if case let .some(.wrongCheck(decompressedData)) = thrownError as? XZError {
133+
XCTAssertEqual(decompressedData.count, 1)
134+
let answerData = try Constants.data(forAnswer: "test1")
135+
XCTAssertEqual(decompressedData.first, answerData)
136+
} else {
137+
XCTFail("Unexpected error: \(String(describing: thrownError))")
138+
}
139+
}
140+
141+
func testMultiStreamChecksumMismatch() throws {
142+
// Here we test that an error for checksum mismatch is thrown correctly and its associated value contains
143+
// expected data. We do this by programmatically adjusting the input: we change one of the bytes for the checkum,
144+
// which makes it incorrect.
145+
var testData = try Constants.data(forTest: "test_multi", withType: XZTests.testType)
146+
// Here we modify the stored value of crc64.
147+
testData[2346] &+= 1
148+
var thrownError: Error? = nil
149+
XCTAssertThrowsError(try XZArchive.splitUnarchive(archive: testData)) { thrownError = $0 }
150+
XCTAssertTrue(thrownError is XZError, "Unexpected error type: \(type(of: thrownError))")
151+
if case let .some(.wrongCheck(decompressedData)) = thrownError as? XZError {
152+
XCTAssertEqual(decompressedData.count, 2)
153+
var answerData = [try Constants.data(forAnswer: "test1")]
154+
answerData.append(try Constants.data(forAnswer: "test2"))
155+
XCTAssertEqual(decompressedData, answerData)
156+
} else {
157+
XCTFail("Unexpected error: \(String(describing: thrownError))")
158+
}
159+
}
160+
123161
}

Tests/ZipTests.swift

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -316,4 +316,38 @@ class ZipTests: XCTestCase {
316316
XCTAssertEqual(entries[0].data, answerData)
317317
}
318318

319+
func testChecksumMismatch() throws {
320+
// Here we test that an error for checksum mismatch is thrown correctly and its associated value contains
321+
// expected data. We do this by programmatically adjusting the input: we change one of the bytes for the checkum,
322+
// which makes it incorrect.
323+
var testData = try Constants.data(forTest: "test_unicode", withType: ZipTests.testType)
324+
// Here we modify the stored value of crc32.
325+
testData[16] &+= 1
326+
var thrownError: Error? = nil
327+
XCTAssertThrowsError(try ZipContainer.open(container: testData)) { thrownError = $0 }
328+
XCTAssertTrue(thrownError is ZipError, "Unexpected error type: \(type(of: thrownError))")
329+
if case let .some(.wrongCRC(entries)) = thrownError as? ZipError {
330+
XCTAssertEqual(entries.count, 1)
331+
XCTAssertEqual(entries[0].info.name, "текстовый файл")
332+
XCTAssertEqual(entries[0].info.type, .regular)
333+
XCTAssertEqual(entries[0].info.fileSystemType, .unix)
334+
XCTAssertEqual(entries[0].info.compressionMethod, .deflate)
335+
XCTAssertTrue(entries[0].info.isTextFile)
336+
XCTAssertEqual(entries[0].info.ownerID, 501)
337+
XCTAssertEqual(entries[0].info.groupID, 20)
338+
XCTAssertEqual(entries[0].info.permissions, Permissions(rawValue: 420))
339+
XCTAssertEqual(entries[0].info.dosAttributes, DosAttributes(rawValue: 0))
340+
XCTAssertEqual(entries[0].info.comment, "")
341+
// Checking times' values is a bit difficult since they are extremely precise.
342+
XCTAssertNotNil(entries[0].info.modificationTime)
343+
XCTAssertNotNil(entries[0].info.accessTime)
344+
XCTAssertNil(entries[0].info.creationTime)
345+
346+
let answerData = try Constants.data(forAnswer: "текстовый файл")
347+
XCTAssertEqual(entries[0].data, answerData)
348+
} else {
349+
XCTFail("Unexpected error: \(String(describing: thrownError))")
350+
}
351+
}
352+
319353
}

Tests/ZlibTests.swift

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,4 +56,22 @@ class ZlibTests: XCTestCase {
5656
XCTAssertThrowsError(try ZlibArchive.unarchive(archive: Data()))
5757
}
5858

59+
func testChecksumMismatch() throws {
60+
// Here we test that an error for checksum mismatch is thrown correctly and its associated value contains
61+
// expected data. We do this by programmatically adjusting the input: we change one of the bytes for the checkum,
62+
// which makes it incorrect.
63+
var testData = try Constants.data(forTest: "random_file", withType: ZlibTests.testType)
64+
// Here we modify the stored value of adler32.
65+
testData[10249] &+= 1
66+
var thrownError: Error? = nil
67+
XCTAssertThrowsError(try ZlibArchive.unarchive(archive: testData)) { thrownError = $0 }
68+
XCTAssertTrue(thrownError is ZlibError, "Unexpected error type: \(type(of: thrownError))")
69+
if case let .some(.wrongAdler32(decompressedData)) = thrownError as? ZlibError {
70+
let answerData = try Constants.data(forAnswer: "test9")
71+
XCTAssertEqual(decompressedData, answerData)
72+
} else {
73+
XCTFail("Unexpected error: \(String(describing: thrownError))")
74+
}
75+
}
76+
5977
}

0 commit comments

Comments
 (0)