mirror of
https://github.com/tsolomko/SWCompression.git
synced 2026-06-23 14:56:41 +00:00
333 lines
15 KiB
Swift
333 lines
15 KiB
Swift
// Copyright (c) 2026 Timofey Solomko
|
|
// Licensed under MIT License
|
|
//
|
|
// See LICENSE for license information
|
|
|
|
import XCTest
|
|
import SWCompression
|
|
|
|
class TarReaderTests: XCTestCase {
|
|
|
|
private static let testType: String = "tar"
|
|
|
|
func testBadFile_invalid() throws {
|
|
// This is potentially a misleading test, since there is no way to guarantee that a file is not a TAR container.
|
|
// We use randomly generated data, since the 0-filled data is processed as an empty container.
|
|
let testHandle = try Constants.handle(forTest: "test7", withType: "answer")
|
|
var reader = TarReader(fileHandle: testHandle)
|
|
XCTAssertThrowsError(try reader.read())
|
|
try testHandle.close()
|
|
}
|
|
|
|
func test() throws {
|
|
let testHandle = try Constants.handle(forTest: "test", withType: TarReaderTests.testType)
|
|
var reader = TarReader(fileHandle: testHandle)
|
|
var isFinished = false
|
|
var entriesCount = 0
|
|
while !isFinished {
|
|
isFinished = try reader.process { (entry: TarEntry?) -> Bool in
|
|
if entry == nil {
|
|
return true
|
|
}
|
|
XCTAssertEqual(entry!.info.name, "test5.answer")
|
|
XCTAssertEqual(entry!.info.size, 0)
|
|
XCTAssertEqual(entry!.info.type, .regular)
|
|
XCTAssertEqual(entry!.info.ownerID, 501)
|
|
XCTAssertEqual(entry!.info.groupID, 20)
|
|
XCTAssertEqual(entry!.info.ownerUserName, "timofeysolomko")
|
|
XCTAssertEqual(entry!.info.ownerGroupName, "staff")
|
|
XCTAssertEqual(entry!.info.permissions, Permissions(rawValue: 420))
|
|
XCTAssertNil(entry!.info.comment)
|
|
XCTAssertEqual(entry!.data, Data())
|
|
entriesCount += 1
|
|
return false
|
|
}
|
|
}
|
|
XCTAssertEqual(entriesCount, 1)
|
|
try testHandle.close()
|
|
}
|
|
|
|
|
|
func testPax() throws {
|
|
let testHandle = try Constants.handle(forTest: "full_test", withType: TarReaderTests.testType)
|
|
var reader = TarReader(fileHandle: testHandle)
|
|
var isFinished = false
|
|
var entriesCount = 0
|
|
while !isFinished {
|
|
isFinished = try reader.process { (entry: TarEntry?) -> Bool in
|
|
if entry == nil {
|
|
return true
|
|
}
|
|
let name = entry!.info.name.components(separatedBy: ".")[0]
|
|
let answerData = try Constants.data(forAnswer: name)
|
|
XCTAssertEqual(entry!.data, answerData)
|
|
XCTAssertEqual(entry!.info.type, .regular)
|
|
XCTAssertEqual(entry!.info.ownerUserName, "tsolomko")
|
|
XCTAssertEqual(entry!.info.ownerGroupName, "tsolomko")
|
|
XCTAssertEqual(entry!.info.ownerID, 1001)
|
|
XCTAssertEqual(entry!.info.groupID, 1001)
|
|
XCTAssertEqual(entry!.info.permissions, Permissions(rawValue: 436))
|
|
XCTAssertNil(entry!.info.comment)
|
|
// Checking times' values is a bit difficult since they are extremely precise.
|
|
XCTAssertNotNil(entry!.info.modificationTime)
|
|
XCTAssertNotNil(entry!.info.accessTime)
|
|
XCTAssertNotNil(entry!.info.creationTime)
|
|
entriesCount += 1
|
|
return false
|
|
}
|
|
}
|
|
XCTAssertEqual(entriesCount, 5)
|
|
try testHandle.close()
|
|
}
|
|
|
|
func testFormats() throws {
|
|
let formatTestNames = ["test_gnu", "test_oldgnu", "test_pax", "test_ustar", "test_v7"]
|
|
let answerData = try Constants.data(forAnswer: "test1")
|
|
|
|
for testName in formatTestNames {
|
|
let testHandle = try Constants.handle(forTest: testName, withType: TarReaderTests.testType)
|
|
var reader = TarReader(fileHandle: testHandle)
|
|
var isFinished = false
|
|
var entriesCount = 0
|
|
while !isFinished {
|
|
isFinished = try reader.process { (entry: TarEntry?) -> Bool in
|
|
if entry == nil {
|
|
return true
|
|
}
|
|
XCTAssertEqual(entry!.info.name, "test1.answer")
|
|
XCTAssertEqual(entry!.info.size, 14)
|
|
XCTAssertEqual(entry!.info.type, .regular)
|
|
XCTAssertEqual(entry!.data, answerData)
|
|
entriesCount += 1
|
|
return false
|
|
}
|
|
}
|
|
XCTAssertEqual(entriesCount, 1)
|
|
XCTAssertNil(try reader.read())
|
|
try testHandle.close()
|
|
}
|
|
}
|
|
|
|
func testLongNames() throws {
|
|
let formatTestNames = ["long_test_gnu", "long_test_oldgnu", "long_test_pax"]
|
|
for testName in formatTestNames {
|
|
let testHandle = try Constants.handle(forTest: testName, withType: TarReaderTests.testType)
|
|
var reader = TarReader(fileHandle: testHandle)
|
|
var isFinished = false
|
|
var entriesCount = 0
|
|
while !isFinished {
|
|
isFinished = try reader.process { (entry: TarEntry?) -> Bool in
|
|
if entry == nil {
|
|
return true
|
|
}
|
|
entriesCount += 1
|
|
return false
|
|
}
|
|
}
|
|
XCTAssertEqual(entriesCount, 6)
|
|
XCTAssertNil(try reader.read())
|
|
try testHandle.close()
|
|
}
|
|
}
|
|
|
|
func testWinContainer() throws {
|
|
let testHandle = try Constants.handle(forTest: "test_win", withType: TarReaderTests.testType)
|
|
var reader = TarReader(fileHandle: testHandle)
|
|
try reader.process { (entry: TarEntry?) in
|
|
XCTAssertNotNil(entry)
|
|
XCTAssertEqual(entry!.info.name, "dir/")
|
|
XCTAssertEqual(entry!.info.type, .directory)
|
|
XCTAssertEqual(entry!.info.size, 0)
|
|
XCTAssertEqual(entry!.info.ownerUserName, "")
|
|
XCTAssertEqual(entry!.info.ownerGroupName, "")
|
|
XCTAssertEqual(entry!.info.ownerID, 0)
|
|
XCTAssertEqual(entry!.info.groupID, 0)
|
|
XCTAssertEqual(entry!.info.permissions, Permissions(rawValue: 511))
|
|
XCTAssertNil(entry!.info.comment)
|
|
XCTAssertEqual(entry!.data, nil)
|
|
}
|
|
try reader.process { (entry: TarEntry?) in
|
|
XCTAssertNotNil(entry)
|
|
XCTAssertEqual(entry!.info.name, "text_win.txt")
|
|
XCTAssertEqual(entry!.info.type, .regular)
|
|
XCTAssertEqual(entry!.info.size, 15)
|
|
XCTAssertEqual(entry!.info.ownerUserName, "")
|
|
XCTAssertEqual(entry!.info.ownerGroupName, "")
|
|
XCTAssertEqual(entry!.info.ownerID, 0)
|
|
XCTAssertEqual(entry!.info.groupID, 0)
|
|
XCTAssertEqual(entry!.info.permissions, Permissions(rawValue: 511))
|
|
XCTAssertNil(entry!.info.comment)
|
|
XCTAssertEqual(entry!.data, "Hello, Windows!".data(using: .utf8))
|
|
}
|
|
XCTAssertNil(try reader.read())
|
|
try testHandle.close()
|
|
}
|
|
|
|
func testEmptyFile() throws {
|
|
let testHandle = try Constants.handle(forTest: "test_empty_file", withType: TarReaderTests.testType)
|
|
var reader = TarReader(fileHandle: testHandle)
|
|
try reader.process { (entry: TarEntry?) in
|
|
XCTAssertNotNil(entry)
|
|
XCTAssertEqual(entry!.info.name, "empty_file")
|
|
XCTAssertEqual(entry!.info.type, .regular)
|
|
XCTAssertEqual(entry!.info.size, 0)
|
|
XCTAssertEqual(entry!.info.ownerID, 501)
|
|
XCTAssertEqual(entry!.info.groupID, 20)
|
|
XCTAssertEqual(entry!.info.ownerUserName, "timofeysolomko")
|
|
XCTAssertEqual(entry!.info.ownerGroupName, "staff")
|
|
XCTAssertEqual(entry!.info.permissions, Permissions(rawValue: 420))
|
|
XCTAssertNil(entry!.info.comment)
|
|
XCTAssertEqual(entry!.data, Data())
|
|
|
|
}
|
|
XCTAssertNil(try reader.read())
|
|
try testHandle.close()
|
|
}
|
|
|
|
func testEmptyDirectory() throws {
|
|
let testHandle = try Constants.handle(forTest: "test_empty_dir", withType: TarReaderTests.testType)
|
|
var reader = TarReader(fileHandle: testHandle)
|
|
try reader.process { (entry: TarEntry?) in
|
|
XCTAssertNotNil(entry)
|
|
XCTAssertEqual(entry!.info.name, "empty_dir/")
|
|
XCTAssertEqual(entry!.info.type, .directory)
|
|
XCTAssertEqual(entry!.info.size, 0)
|
|
XCTAssertEqual(entry!.info.ownerID, 501)
|
|
XCTAssertEqual(entry!.info.groupID, 20)
|
|
XCTAssertEqual(entry!.info.ownerUserName, "timofeysolomko")
|
|
XCTAssertEqual(entry!.info.ownerGroupName, "staff")
|
|
XCTAssertEqual(entry!.info.permissions, Permissions(rawValue: 493))
|
|
XCTAssertNil(entry!.info.comment)
|
|
XCTAssertNil(entry!.data)
|
|
}
|
|
XCTAssertNil(try reader.read())
|
|
try testHandle.close()
|
|
}
|
|
|
|
func testOnlyDirectoryHeader() throws {
|
|
// This tests the correct handling of the situation when there is nothing in the container but one basic header,
|
|
// even no EOF marker (two blocks of zeros).
|
|
let testHandle = try Constants.handle(forTest: "test_only_dir_header", withType: TarReaderTests.testType)
|
|
var reader = TarReader(fileHandle: testHandle)
|
|
try reader.process { (entry: TarEntry?) in
|
|
XCTAssertNotNil(entry)
|
|
XCTAssertEqual(entry!.info.name, "empty_dir/")
|
|
XCTAssertEqual(entry!.info.type, .directory)
|
|
XCTAssertEqual(entry!.info.size, 0)
|
|
XCTAssertEqual(entry!.info.ownerID, 501)
|
|
XCTAssertEqual(entry!.info.groupID, 20)
|
|
XCTAssertEqual(entry!.info.ownerUserName, "timofeysolomko")
|
|
XCTAssertEqual(entry!.info.ownerGroupName, "staff")
|
|
XCTAssertEqual(entry!.info.permissions, Permissions(rawValue: 493))
|
|
XCTAssertNil(entry!.info.comment)
|
|
XCTAssertNil(entry!.data)
|
|
}
|
|
XCTAssertNil(try reader.read())
|
|
try testHandle.close()
|
|
}
|
|
|
|
func testEmptyContainer() throws {
|
|
let testHandle = try Constants.handle(forTest: "test_empty_cont", withType: TarReaderTests.testType)
|
|
var reader = TarReader(fileHandle: testHandle)
|
|
XCTAssertNil(try reader.read())
|
|
try testHandle.close()
|
|
}
|
|
|
|
func testBigContainer() throws {
|
|
let testHandle = try Constants.handle(forTest: "SWCompressionSourceCode", withType: TarReaderTests.testType)
|
|
var reader = TarReader(fileHandle: testHandle)
|
|
while try reader.read() != nil { }
|
|
try testHandle.close()
|
|
}
|
|
|
|
func testUnicodeUstar() throws {
|
|
let testHandle = try Constants.handle(forTest: "test_unicode_ustar", withType: TarReaderTests.testType)
|
|
var reader = TarReader(fileHandle: testHandle)
|
|
try reader.process { (entry: TarEntry?) in
|
|
XCTAssertNotNil(entry)
|
|
XCTAssertEqual(entry!.info.name, "текстовый файл.answer")
|
|
XCTAssertEqual(entry!.info.type, .regular)
|
|
XCTAssertEqual(entry!.info.ownerID, 501)
|
|
XCTAssertEqual(entry!.info.groupID, 20)
|
|
XCTAssertEqual(entry!.info.ownerUserName, "timofeysolomko")
|
|
XCTAssertEqual(entry!.info.ownerGroupName, "staff")
|
|
XCTAssertEqual(entry!.info.permissions, Permissions(rawValue: 420))
|
|
XCTAssertNil(entry!.info.comment)
|
|
XCTAssertEqual(entry!.data, Constants.текстовыйФайлData)
|
|
|
|
}
|
|
XCTAssertNil(try reader.read())
|
|
try testHandle.close()
|
|
}
|
|
|
|
func testUnicodePax() throws {
|
|
let testHandle = try Constants.handle(forTest: "test_unicode_pax", withType: TarReaderTests.testType)
|
|
var reader = TarReader(fileHandle: testHandle)
|
|
try reader.process { (entry: TarEntry?) in
|
|
XCTAssertNotNil(entry)
|
|
XCTAssertEqual(entry!.info.name, "текстовый файл.answer")
|
|
XCTAssertEqual(entry!.info.type, .regular)
|
|
XCTAssertEqual(entry!.info.ownerID, 501)
|
|
XCTAssertEqual(entry!.info.groupID, 20)
|
|
XCTAssertEqual(entry!.info.ownerUserName, "timofeysolomko")
|
|
XCTAssertEqual(entry!.info.ownerGroupName, "staff")
|
|
XCTAssertEqual(entry!.info.permissions, Permissions(rawValue: 420))
|
|
XCTAssertNil(entry!.info.comment)
|
|
XCTAssertEqual(entry!.data, Constants.текстовыйФайлData)
|
|
|
|
}
|
|
XCTAssertNil(try reader.read())
|
|
try testHandle.close()
|
|
}
|
|
|
|
func testGnuIncrementalFormat() throws {
|
|
let testHandle = try Constants.handle(forTest: "test_gnu_inc_format", withType: TarReaderTests.testType)
|
|
var reader = TarReader(fileHandle: testHandle)
|
|
var isFinished = false
|
|
var entriesCount = 0
|
|
while !isFinished {
|
|
isFinished = try reader.process { (entry: TarEntry?) -> Bool in
|
|
if entry == nil {
|
|
return true
|
|
}
|
|
XCTAssertEqual(entry!.info.ownerID, 501)
|
|
XCTAssertEqual(entry!.info.groupID, 20)
|
|
XCTAssertEqual(entry!.info.ownerUserName, "timofeysolomko")
|
|
XCTAssertEqual(entry!.info.ownerGroupName, "staff")
|
|
XCTAssertNotNil(entry!.info.accessTime)
|
|
XCTAssertNotNil(entry!.info.creationTime)
|
|
entriesCount += 1
|
|
return false
|
|
}
|
|
}
|
|
XCTAssertEqual(entriesCount, 3)
|
|
XCTAssertNil(try reader.read())
|
|
try testHandle.close()
|
|
}
|
|
|
|
// This test is impossible to implement using TarReader since the test file doesn't contain actual entry data.
|
|
// func testBigNumField() throws { }
|
|
|
|
func testNegativeMtime() throws {
|
|
let testHandle = try Constants.handle(forTest: "test_negative_mtime", withType: TarReaderTests.testType)
|
|
var reader = TarReader(fileHandle: testHandle)
|
|
try reader.process { (entry: TarEntry?) in
|
|
XCTAssertEqual(entry!.info.name, "file")
|
|
XCTAssertEqual(entry!.info.type, .regular)
|
|
XCTAssertEqual(entry!.info.size, 27)
|
|
XCTAssertEqual(entry!.info.ownerID, 501)
|
|
XCTAssertEqual(entry!.info.groupID, 20)
|
|
XCTAssertEqual(entry!.info.ownerUserName, "timofeysolomko")
|
|
XCTAssertEqual(entry!.info.ownerGroupName, "staff")
|
|
XCTAssertEqual(entry!.info.permissions, Permissions(rawValue: 420))
|
|
XCTAssertEqual(entry!.info.modificationTime, Date(timeIntervalSince1970: -313006414))
|
|
XCTAssertNil(entry!.info.comment)
|
|
XCTAssertEqual(entry!.data, "File with negative mtime.\n\n".data(using: .utf8))
|
|
}
|
|
// Test that reading after reaching EOF returns nil.
|
|
XCTAssertNil(try reader.read())
|
|
try testHandle.close()
|
|
}
|
|
|
|
}
|