Change license to AGPL
This commit:
- Updates the `LICENSE` file
- Start every file with something like:
// Copyright YEAR_FIRST_PUBLISHED Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
---
First, I removed existing license headers with this Ruby 3.1.2 script:
require 'set'
EXTENSIONS_TO_CHECK = Set['.h', '.hpp', '.cpp', '.m', '.mm', '.pch', '.swift']
same = 0
different = 0
all_files = `git ls-files`.lines.map { |line| line.strip }
all_files.each do |relative_path|
if relative_path == 'Pods'
next
end
unless EXTENSIONS_TO_CHECK.include? File.extname(relative_path)
next
end
path = File.expand_path(relative_path)
contents = File.read(path)
new_contents = contents.sub(/\/\/\n\/\/ Copyright .*\n\/\/\n\n/, '')
if contents == new_contents
same += 1
else
different += 1
end
File.write(path, new_contents)
end
puts "updated #{different} file(s), left #{same} untouched"
I'm sure this script could be improved, but it worked well enough.
Then, I created `Scripts/lint/lint-license-headers` and ran it to auto-
fix a lot of files. This changed the mode of some files, but I think
that's actually desirable. For example,
`SignalServiceKit/src/Util/AppContext.m` previously had a mode of
`0755/-rwxr-xr-x`, and it's now `0644/-rw-r--r--`.
Then I fixed some stragglers and updated the precommit script.
See [a similar change in the Desktop app][0].
[0]: 8bfaf598af
188 lines
6.6 KiB
Swift
188 lines
6.6 KiB
Swift
//
|
|
// Copyright 2022 Signal Messenger, LLC
|
|
// SPDX-License-Identifier: AGPL-3.0-only
|
|
//
|
|
|
|
import XCTest
|
|
@testable import SignalServiceKit
|
|
|
|
class PngChunkerTest: XCTestCase {
|
|
func testPngSignature() {
|
|
let expected = Data([137, 80, 78, 71, 13, 10, 26, 10])
|
|
XCTAssertEqual(PngChunker.pngSignature, expected)
|
|
}
|
|
|
|
func testTotallyInvalidPngs() {
|
|
let tooSmall: [Data] = [
|
|
Data(),
|
|
Data(count: 8),
|
|
PngChunker.pngSignature
|
|
]
|
|
for data in tooSmall {
|
|
XCTAssertThrowsError(try PngChunker(data: data)) { error in
|
|
XCTAssertEqual(
|
|
error as? PngChunker.PngChunkerError,
|
|
PngChunker.PngChunkerError.tooSmall
|
|
)
|
|
}
|
|
}
|
|
|
|
let wrongPrefix: [Data] = [
|
|
// PNG with no signature
|
|
fixture(filename: "test-png").dropFirst(8),
|
|
// PNG with invalid signature
|
|
Data([137, 2, 3, 4, 5, 6, 7, 8] + fixture(filename: "test-png").dropFirst(8)),
|
|
// Garbage
|
|
Randomness.generateRandomBytes(123)
|
|
]
|
|
for data in wrongPrefix {
|
|
XCTAssertThrowsError(try PngChunker(data: data)) { error in
|
|
XCTAssertEqual(
|
|
error as? PngChunker.PngChunkerError,
|
|
PngChunker.PngChunkerError.fileDoesNotStartWithPngSignature
|
|
)
|
|
}
|
|
}
|
|
}
|
|
|
|
func testBarebonesPng() throws {
|
|
let data = fixture(filename: "test-png")
|
|
|
|
let chunker = try XCTUnwrap(PngChunker(data: data), "test-png chunker")
|
|
let chunks = try XCTUnwrap(allChunks(from: chunker), "test-png chunks")
|
|
|
|
XCTAssertEqual(reconstruct(from: chunks), data)
|
|
|
|
let types = chunks.map { $0.type.asString(.ascii) }
|
|
XCTAssertEqual(types, ["IHDR", "IDAT", "IEND"])
|
|
}
|
|
|
|
func testApng() throws {
|
|
let data = fixture(filename: "test-apng")
|
|
|
|
let chunker = try XCTUnwrap(PngChunker(data: data), "test-apng chunker")
|
|
let chunks = try XCTUnwrap(allChunks(from: chunker), "test-apng chunks")
|
|
|
|
XCTAssertEqual(reconstruct(from: chunks), data)
|
|
|
|
let types = chunks.map { $0.type.asString(.ascii) }
|
|
XCTAssert(types.starts(with: ["IHDR", "acTL", "fcTL", "IDAT", "fcTL", "fdAT"]))
|
|
}
|
|
|
|
func testNextAfterFinished() throws {
|
|
let data = fixture(filename: "test-png")
|
|
let chunker = try XCTUnwrap(PngChunker(data: data), "test-png chunker")
|
|
while try chunker.next() != nil {}
|
|
|
|
XCTAssertNil(try chunker.next())
|
|
XCTAssertNil(try chunker.next())
|
|
XCTAssertNil(try chunker.next())
|
|
}
|
|
|
|
func testNextAfterError() throws {
|
|
let data = PngChunker.pngSignature + Data(count: 100)
|
|
let chunker = try XCTUnwrap(PngChunker(data: data), "test-png chunker")
|
|
|
|
XCTAssertThrowsError(try chunker.next())
|
|
|
|
XCTAssertNil(try chunker.next())
|
|
XCTAssertNil(try chunker.next())
|
|
XCTAssertNil(try chunker.next())
|
|
}
|
|
|
|
func testInvalidType() throws {
|
|
let invalidData: Data = try {
|
|
var result = PngChunker.pngSignature
|
|
let validData = fixture(filename: "test-png")
|
|
let chunker = try XCTUnwrap(PngChunker(data: validData), "Test not set up correctly")
|
|
while let chunk = try chunker.next() {
|
|
let allBytes = chunk.allBytes()
|
|
if chunk.type.asString(.ascii) == "IDAT" {
|
|
let bogusType = Data([9, 8, 7, 6])
|
|
result += chunk.lengthBytes + bogusType + chunk.data + chunk.crcBytes
|
|
} else {
|
|
result += allBytes
|
|
}
|
|
}
|
|
return result
|
|
}()
|
|
let chunker = try XCTUnwrap(PngChunker(data: invalidData), "Chunker for invalid data")
|
|
|
|
XCTAssertEqual((try XCTUnwrap(chunker.next())).type.asString(.ascii), "IHDR")
|
|
XCTAssertThrowsError(try chunker.next()) { error in
|
|
XCTAssertEqual(
|
|
error as? PngChunker.PngChunkerError,
|
|
PngChunker.PngChunkerError.invalidChunkType
|
|
)
|
|
}
|
|
}
|
|
|
|
func testInvalidChecksum() throws {
|
|
let invalidData: Data = try {
|
|
var result = PngChunker.pngSignature
|
|
let validData = fixture(filename: "test-png")
|
|
let chunker = try XCTUnwrap(PngChunker(data: validData), "Test not set up correctly")
|
|
while let chunk = try chunker.next() {
|
|
let allBytes = chunk.allBytes()
|
|
if chunk.type.asString(.ascii) == "IDAT" {
|
|
let bogusCrc = Data([9, 8, 7, 6])
|
|
result += allBytes.dropLast(4) + bogusCrc
|
|
} else {
|
|
result += allBytes
|
|
}
|
|
}
|
|
return result
|
|
}()
|
|
let chunker = try XCTUnwrap(PngChunker(data: invalidData), "Chunker for invalid data")
|
|
|
|
XCTAssertEqual((try XCTUnwrap(chunker.next())).type.asString(.ascii), "IHDR")
|
|
XCTAssertThrowsError(try chunker.next()) { error in
|
|
XCTAssertEqual(
|
|
error as? PngChunker.PngChunkerError,
|
|
PngChunker.PngChunkerError.invalidChunkChecksum
|
|
)
|
|
}
|
|
}
|
|
|
|
func testEndedUnexpectedly() throws {
|
|
let invalidData = fixture(filename: "test-png").dropLast(8)
|
|
let chunker = try XCTUnwrap(PngChunker(data: invalidData), "Invalid data chunker")
|
|
|
|
XCTAssertEqual((try XCTUnwrap(chunker.next())).type.asString(.ascii), "IHDR")
|
|
XCTAssertEqual((try XCTUnwrap(chunker.next())).type.asString(.ascii), "IDAT")
|
|
XCTAssertThrowsError(try chunker.next()) { error in
|
|
XCTAssertEqual(error as? PngChunker.PngChunkerError, PngChunker.PngChunkerError.endedUnexpectedly)
|
|
}
|
|
}
|
|
|
|
// MARK: - Utilities
|
|
|
|
private func fixture(filename: String, withExtension ext: String = "png") -> Data {
|
|
let testBundle = Bundle(for: Self.self)
|
|
let url = testBundle.url(forResource: filename, withExtension: ext)!
|
|
return try! Data(contentsOf: url)
|
|
}
|
|
|
|
private func allChunks(from chunker: PngChunker) throws -> [PngChunker.Chunk] {
|
|
var result = [PngChunker.Chunk]()
|
|
while let chunk = try chunker.next() {
|
|
result.append(chunk)
|
|
}
|
|
return result
|
|
}
|
|
|
|
private func reconstruct(from chunks: [PngChunker.Chunk]) -> Data {
|
|
PngChunker.pngSignature + chunks.reduce(Data()) { result, chunk in
|
|
result + chunk.allBytes()
|
|
}
|
|
}
|
|
}
|
|
|
|
// MARK: - Convert data to strings
|
|
|
|
extension Data {
|
|
func asString(_ encoding: String.Encoding) -> String? {
|
|
String(data: self, encoding: encoding)
|
|
}
|
|
}
|