Skip to content

Commit

Permalink
[Tests] Add many tests that check that checksum errors are thrown cor…
Browse files Browse the repository at this point in the history
…rectly
  • Loading branch information
tsolomko committed Oct 29, 2021
1 parent 20e8db7 commit a333236
Show file tree
Hide file tree
Showing 8 changed files with 177 additions and 10 deletions.
2 changes: 1 addition & 1 deletion Sources/XZ/XZArchive.swift
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ public class XZArchive: Archive {
var indexSize = -1
while true {
let blockHeaderSize = byteReader.byte()
if blockHeaderSize == 0 { /// Zero value of blockHeaderSize means that we've encountered INDEX.
if blockHeaderSize == 0 { // Zero value of blockHeaderSize means that we've encountered the index.
indexSize = try processIndex(blockInfos, byteReader)
break
} else {
Expand Down
8 changes: 4 additions & 4 deletions Sources/ZIP/ZipContainer.swift
Original file line number Diff line number Diff line change
Expand Up @@ -70,17 +70,17 @@ public class ZipContainer: Container {
case .deflate:
let bitReader = LsbBitReader(byteReader)
fileData = try Deflate.decompress(bitReader)
// Sometimes `bitReader` has misaligned state after Deflate decompression,
// so we need to align before getting end index back.
// Sometimes bitReader is misaligned after Deflate decompression, so we need to align before getting end
// index back.
bitReader.align()
byteReader.offset = bitReader.offset
case .bzip2:
#if (!SWCOMPRESSION_POD_ZIP) || (SWCOMPRESSION_POD_ZIP && SWCOMPRESSION_POD_BZ2)
// BZip2 algorithm uses different bit numbering scheme.
let bitReader = MsbBitReader(byteReader)
fileData = try BZip2.decompress(bitReader)
// Sometimes `bitReader` has misaligned state after BZip2 decompression,
// so we need to align before getting the end index back.
// Sometimes bitReader is misaligned after BZip2 decompression, so we need to align before getting end
// index back.
bitReader.align()
byteReader.offset = bitReader.offset
#else
Expand Down
18 changes: 18 additions & 0 deletions Tests/BZip2Tests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -71,4 +71,22 @@ class BZip2Tests: XCTestCase {
XCTAssertThrowsError(try BZip2.decompress(data: Data()))
}

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

}
40 changes: 40 additions & 0 deletions Tests/GzipTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -155,4 +155,44 @@ class GzipTests: XCTestCase {
XCTAssertThrowsError(try GzipArchive.unarchive(archive: Data()))
}

func testChecksumMismatch() throws {
// Here we test that an error for checksum mismatch is thrown correctly and its associated value contains
// expected data. We do this by programmatically adjusting the input: we change one of the bytes for the checkum,
// which makes it incorrect.
var testData = try Constants.data(forTest: "test1", withType: GzipTests.testType)
// Here we modify the stored value of crc32.
testData[41] &+= 1
var thrownError: Error? = nil
XCTAssertThrowsError(try GzipArchive.unarchive(archive: testData)) { thrownError = $0 }
XCTAssertTrue(thrownError is GzipError, "Unexpected error type: \(type(of: thrownError))")
if case let .some(.wrongCRC(members)) = thrownError as? GzipError {
XCTAssertEqual(members.count, 1)
let answerData = try Constants.data(forAnswer: "test1")
XCTAssertEqual(members.first?.data, answerData)
} else {
XCTFail("Unexpected error: \(String(describing: thrownError))")
}
}

func testMultiUnarchiveChecksumMismatch() throws {
// Here we test that an error for checksum mismatch is thrown correctly and its associated value contains
// expected data. We do this by programmatically adjusting the input: we change one of the bytes for the checkum,
// which makes it incorrect.
var testData = try Constants.data(forTest: "test_multi", withType: GzipTests.testType)
// Here we modify the stored value of crc32.
testData[2289] &+= 1
var thrownError: Error? = nil
XCTAssertThrowsError(try GzipArchive.multiUnarchive(archive: testData)) { thrownError = $0 }
XCTAssertTrue(thrownError is GzipError, "Unexpected error type: \(type(of: thrownError))")
if case let .some(.wrongCRC(members)) = thrownError as? GzipError {
XCTAssertEqual(members.count, 2)
var answerData = try Constants.data(forAnswer: "test1")
XCTAssertEqual(members[0].data, answerData)
answerData = try Constants.data(forAnswer: "test2")
XCTAssertEqual(members[1].data, answerData)
} else {
XCTFail("Unexpected error: \(String(describing: thrownError))")
}
}

}
19 changes: 19 additions & 0 deletions Tests/LZ4Tests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -183,4 +183,23 @@ class LZ4Tests: XCTestCase {
XCTAssertEqual(result[1], try Constants.data(forAnswer: "test4"))
}

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

}
48 changes: 43 additions & 5 deletions Tests/XzTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -58,9 +58,8 @@ class XZTests: XCTestCase {
func testMultiStreamNoPadding() throws {
// Doesn't contain any padding.
let testData = try Constants.data(forTest: "test_multi", withType: XZTests.testType)

let decompressedData = try XZArchive.unarchive(archive: testData)
let splitDecompressedData = try XZArchive.splitUnarchive(archive: testData)
XCTAssertEqual(splitDecompressedData.count, 4)

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

let decompressedData = try XZArchive.unarchive(archive: testData)
XCTAssertEqual(decompressedData, answerData)
}

Expand All @@ -77,11 +77,9 @@ class XZTests: XCTestCase {
// After second - 4 bytes of padding.
// Third - 8 bytes.
// At the end - 4 bytes.

let testData = try Constants.data(forTest: "test_multi_pad", withType: XZTests.testType)

let decompressedData = try XZArchive.unarchive(archive: testData)
let splitDecompressedData = try XZArchive.splitUnarchive(archive: testData)
XCTAssertEqual(splitDecompressedData.count, 4)

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

let decompressedData = try XZArchive.unarchive(archive: testData)
XCTAssertEqual(decompressedData, answerData)
}

Expand Down Expand Up @@ -120,4 +119,43 @@ class XZTests: XCTestCase {
XCTAssertThrowsError(try XZArchive.unarchive(archive: testData))
}

func testChecksumMismatch() throws {
// Here we test that an error for checksum mismatch is thrown correctly and its associated value contains
// expected data. We do this by programmatically adjusting the input: we change one of the bytes for the checkum,
// which makes it incorrect.
var testData = try Constants.data(forTest: "test1", withType: XZTests.testType)
// Here we modify the stored value of crc64.
testData[46] &+= 1
var thrownError: Error? = nil
XCTAssertThrowsError(try XZArchive.unarchive(archive: testData)) { thrownError = $0 }
XCTAssertTrue(thrownError is XZError, "Unexpected error type: \(type(of: thrownError))")
if case let .some(.wrongCheck(decompressedData)) = thrownError as? XZError {
XCTAssertEqual(decompressedData.count, 1)
let answerData = try Constants.data(forAnswer: "test1")
XCTAssertEqual(decompressedData.first, answerData)
} else {
XCTFail("Unexpected error: \(String(describing: thrownError))")
}
}

func testMultiStreamChecksumMismatch() throws {
// Here we test that an error for checksum mismatch is thrown correctly and its associated value contains
// expected data. We do this by programmatically adjusting the input: we change one of the bytes for the checkum,
// which makes it incorrect.
var testData = try Constants.data(forTest: "test_multi", withType: XZTests.testType)
// Here we modify the stored value of crc64.
testData[2346] &+= 1
var thrownError: Error? = nil
XCTAssertThrowsError(try XZArchive.splitUnarchive(archive: testData)) { thrownError = $0 }
XCTAssertTrue(thrownError is XZError, "Unexpected error type: \(type(of: thrownError))")
if case let .some(.wrongCheck(decompressedData)) = thrownError as? XZError {
XCTAssertEqual(decompressedData.count, 2)
var answerData = [try Constants.data(forAnswer: "test1")]
answerData.append(try Constants.data(forAnswer: "test2"))
XCTAssertEqual(decompressedData, answerData)
} else {
XCTFail("Unexpected error: \(String(describing: thrownError))")
}
}

}
34 changes: 34 additions & 0 deletions Tests/ZipTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -316,4 +316,38 @@ class ZipTests: XCTestCase {
XCTAssertEqual(entries[0].data, answerData)
}

func testChecksumMismatch() throws {
// Here we test that an error for checksum mismatch is thrown correctly and its associated value contains
// expected data. We do this by programmatically adjusting the input: we change one of the bytes for the checkum,
// which makes it incorrect.
var testData = try Constants.data(forTest: "test_unicode", withType: ZipTests.testType)
// Here we modify the stored value of crc32.
testData[16] &+= 1
var thrownError: Error? = nil
XCTAssertThrowsError(try ZipContainer.open(container: testData)) { thrownError = $0 }
XCTAssertTrue(thrownError is ZipError, "Unexpected error type: \(type(of: thrownError))")
if case let .some(.wrongCRC(entries)) = thrownError as? ZipError {
XCTAssertEqual(entries.count, 1)
XCTAssertEqual(entries[0].info.name, "текстовый файл")
XCTAssertEqual(entries[0].info.type, .regular)
XCTAssertEqual(entries[0].info.fileSystemType, .unix)
XCTAssertEqual(entries[0].info.compressionMethod, .deflate)
XCTAssertTrue(entries[0].info.isTextFile)
XCTAssertEqual(entries[0].info.ownerID, 501)
XCTAssertEqual(entries[0].info.groupID, 20)
XCTAssertEqual(entries[0].info.permissions, Permissions(rawValue: 420))
XCTAssertEqual(entries[0].info.dosAttributes, DosAttributes(rawValue: 0))
XCTAssertEqual(entries[0].info.comment, "")
// Checking times' values is a bit difficult since they are extremely precise.
XCTAssertNotNil(entries[0].info.modificationTime)
XCTAssertNotNil(entries[0].info.accessTime)
XCTAssertNil(entries[0].info.creationTime)

let answerData = try Constants.data(forAnswer: "текстовый файл")
XCTAssertEqual(entries[0].data, answerData)
} else {
XCTFail("Unexpected error: \(String(describing: thrownError))")
}
}

}
18 changes: 18 additions & 0 deletions Tests/ZlibTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -56,4 +56,22 @@ class ZlibTests: XCTestCase {
XCTAssertThrowsError(try ZlibArchive.unarchive(archive: Data()))
}

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

}

0 comments on commit a333236

Please sign in to comment.