110 lines
4.1 KiB
Swift
110 lines
4.1 KiB
Swift
//
|
|
// Copyright 2021 Signal Messenger, LLC
|
|
// SPDX-License-Identifier: AGPL-3.0-only
|
|
//
|
|
|
|
import XCTest
|
|
import CoreServices
|
|
import SignalServiceKit
|
|
import UniformTypeIdentifiers
|
|
|
|
class SignalAttachmentTest: SignalBaseTest {
|
|
// MARK: - Utilities
|
|
|
|
func testMetadataStrippingDoesNotChangeOrientation(url: URL) throws {
|
|
let size = Data.imageSize(forFilePath: url.path, mimeType: "image/jpeg")
|
|
|
|
let dataSource = try DataSourcePath(fileUrl: url, shouldDeleteOnDeallocation: false)
|
|
let attachment = SignalAttachment.attachment(
|
|
dataSource: dataSource,
|
|
dataUTI: UTType.jpeg.identifier
|
|
)
|
|
let newSize = attachment.data.imageMetadata(withPath: nil, mimeType: "image/jpeg").pixelSize
|
|
|
|
XCTAssertEqual(newSize, size, "image dimensions changed for \(url.lastPathComponent)")
|
|
}
|
|
|
|
private func pngChunks(data: Data) throws -> [PngChunker.Chunk] {
|
|
let chunker = try PngChunker(source: data)
|
|
var result = [PngChunker.Chunk]()
|
|
while let chunk = try chunker.next() {
|
|
result.append(chunk)
|
|
}
|
|
return result
|
|
}
|
|
|
|
private func pngChunkTypes(data: Data) throws -> [String] {
|
|
(try pngChunks(data: data)).compactMap { chunk in
|
|
String(data: chunk.type, encoding: .ascii)
|
|
}
|
|
}
|
|
|
|
// MARK: - Tests
|
|
|
|
func testMetadataStrippingDoesNotChangeOrientation() throws {
|
|
let testBundle = Bundle(for: Self.self)
|
|
try testMetadataStrippingDoesNotChangeOrientation(url: testBundle.url(forResource: "test-jpg",
|
|
withExtension: "jpg")!)
|
|
try testMetadataStrippingDoesNotChangeOrientation(url: testBundle.url(forResource: "test-jpg-rotated",
|
|
withExtension: "jpg")!)
|
|
}
|
|
|
|
func testRemoveMetadataFromPng() throws {
|
|
let testBundle = Bundle(for: Self.self)
|
|
let url = testBundle.url(forResource: "test-png-with-metadata", withExtension: "png")!
|
|
let dataSource = try DataSourcePath(fileUrl: url, shouldDeleteOnDeallocation: false)
|
|
XCTAssertEqual(
|
|
try pngChunkTypes(data: dataSource.data),
|
|
["IHDR", "PLTE", "sRGB", "tIME", "tEXt", "IDAT", "IEND"],
|
|
"Test is not set up correctly. Fixture doesn't have the expected chunks"
|
|
)
|
|
|
|
let attachment = SignalAttachment.attachment(
|
|
dataSource: dataSource,
|
|
dataUTI: UTType.png.identifier
|
|
)
|
|
|
|
XCTAssertEqual(
|
|
try pngChunkTypes(data: attachment.data),
|
|
["IHDR", "PLTE", "sRGB", "IDAT", "IEND"]
|
|
)
|
|
}
|
|
|
|
func testRemoveMetadataFromAPng() throws {
|
|
let pngData: Data = {
|
|
let testBundle = Bundle(for: Self.self)
|
|
let apngUrl = testBundle.url(forResource: "test-apng", withExtension: "png")!
|
|
let apngData = try! Data(contentsOf: apngUrl)
|
|
let apngChunks = try! pngChunks(data: apngData)
|
|
|
|
// This is a `tEXt` chunk with some sample data.
|
|
let newChunkData = Data([
|
|
0x00, 0x00, 0x00, 0x14, 0x74, 0x45, 0x58, 0x74,
|
|
0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x00,
|
|
0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x20, 0x77, 0x6f,
|
|
0x72, 0x6c, 0x64, 0x21, 0xab, 0x32, 0xb0, 0x28
|
|
])
|
|
let newChunks: [Data] = (
|
|
apngChunks.dropLast(1).map { $0.allBytes() } +
|
|
[newChunkData, apngChunks.last!.allBytes()]
|
|
)
|
|
|
|
return PngChunker.pngSignature + newChunks.reduce(Data()) { $0 + $1 }
|
|
}()
|
|
XCTAssert(
|
|
(try pngChunkTypes(data: pngData)).contains("tEXt"),
|
|
"Test is not set up correctly. Fixture doesn't have the expected chunks"
|
|
)
|
|
let dataSource = DataSourceValue(pngData, fileExtension: "png")
|
|
|
|
let attachment = SignalAttachment.attachment(
|
|
dataSource: dataSource,
|
|
dataUTI: UTType.png.identifier
|
|
)
|
|
|
|
XCTAssert(
|
|
!(try pngChunkTypes(data: attachment.data)).contains("tEXt"),
|
|
"Result contained unexpected chunk"
|
|
)
|
|
}
|
|
}
|