120 lines
4.8 KiB
Swift
120 lines
4.8 KiB
Swift
//===----------------------------------------------------------------------===//
|
|
// Copyright © 2026 Apple Inc. and the Containerization project authors.
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// https://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
import ContainerizationError
|
|
import Crypto
|
|
import Foundation
|
|
import Testing
|
|
|
|
@testable import ContainerizationOCI
|
|
|
|
@Suite("ContentWriter Tests")
|
|
struct ContentWriterTests {
|
|
private func withTempDirectory(_ body: (URL) throws -> Void) throws {
|
|
let dir = FileManager.default.temporaryDirectory
|
|
.appendingPathComponent(UUID().uuidString)
|
|
try FileManager.default.createDirectory(at: dir, withIntermediateDirectories: true)
|
|
defer { try? FileManager.default.removeItem(at: dir) }
|
|
try body(dir)
|
|
}
|
|
|
|
private func makeTempFile(in dir: URL, data: Data) throws -> URL {
|
|
let url = dir.appendingPathComponent(UUID().uuidString)
|
|
try data.write(to: url)
|
|
return url
|
|
}
|
|
|
|
@Test func testWriteReturnsCorrectSizeAndDigest() throws {
|
|
try withTempDirectory { dir in
|
|
let writer = try ContentWriter(for: dir)
|
|
let data = Data("test content".utf8)
|
|
let (size, digest) = try writer.write(data)
|
|
let expected = SHA256.hash(data: data)
|
|
let destination = dir.appendingPathComponent(digest.encoded)
|
|
#expect(size == Int64(data.count))
|
|
#expect(digest == expected)
|
|
#expect(FileManager.default.fileExists(atPath: destination.path))
|
|
}
|
|
}
|
|
|
|
@Test func testWriteDuplicateData() throws {
|
|
try withTempDirectory { dir in
|
|
let writer = try ContentWriter(for: dir)
|
|
let data = Data("duplicate".utf8)
|
|
#expect(throws: Never.self) {
|
|
try writer.write(data)
|
|
try writer.write(data)
|
|
}
|
|
}
|
|
}
|
|
|
|
@Test func testCreateFromFileSmallFile() throws {
|
|
try withTempDirectory { base in
|
|
try withTempDirectory { src in
|
|
let data = Data("small file contents".utf8)
|
|
let sourceURL = try makeTempFile(in: src, data: data)
|
|
let writer = try ContentWriter(for: base)
|
|
let (size, digest) = try writer.create(from: sourceURL)
|
|
let destination = base.appendingPathComponent(digest.encoded)
|
|
let written = try Data(contentsOf: destination)
|
|
#expect(size == Int64(data.count))
|
|
#expect(digest == SHA256.hash(data: data))
|
|
#expect(FileManager.default.fileExists(atPath: destination.path))
|
|
#expect(written == data)
|
|
}
|
|
}
|
|
}
|
|
|
|
@Test func testCreateFromFileLargeFileDuplicates() throws {
|
|
try withTempDirectory { base in
|
|
try withTempDirectory { src in
|
|
let count = 3 * 1024 * 1024 + 100
|
|
var bytes = [UInt8](repeating: 0, count: count)
|
|
arc4random_buf(&bytes, count)
|
|
let data = Data(bytes)
|
|
let sourceURL = try makeTempFile(in: src, data: data)
|
|
let writer = try ContentWriter(for: base)
|
|
let (size, digest) = try writer.create(from: sourceURL)
|
|
let destination = base.appendingPathComponent(digest.encoded)
|
|
#expect(size == Int64(data.count))
|
|
#expect(digest == SHA256.hash(data: data))
|
|
#expect(throws: Never.self) {
|
|
try writer.create(from: sourceURL)
|
|
}
|
|
#expect(FileManager.default.fileExists(atPath: destination.path))
|
|
}
|
|
}
|
|
}
|
|
|
|
private struct SamplePayload: Codable, Equatable {
|
|
let name: String
|
|
let value: Int
|
|
}
|
|
|
|
@Test func testCreateFromEncodableReturnsCorrectDigest() throws {
|
|
try withTempDirectory { base in
|
|
let writer = try ContentWriter(for: base)
|
|
let payload = SamplePayload(name: "digest-check", value: 99)
|
|
let (size, digest) = try writer.create(from: payload)
|
|
let encoder = JSONEncoder()
|
|
encoder.outputFormatting = [.sortedKeys]
|
|
let expected = try encoder.encode(payload)
|
|
#expect(size == Int64(expected.count))
|
|
#expect(digest == SHA256.hash(data: expected))
|
|
}
|
|
}
|
|
}
|