You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

105 lines
3.9 KiB

import XCTest
@testable import DropTwoCore
final class JobQueueTests: XCTestCase {
private var tempDirectory: URL!
private var outputDirectory: URL!
override func setUpWithError() throws {
tempDirectory = FileManager.default.temporaryDirectory.appendingPathComponent(UUID().uuidString)
outputDirectory = tempDirectory.appendingPathComponent("output")
try FileManager.default.createDirectory(at: outputDirectory, withIntermediateDirectories: true)
}
override func tearDownWithError() throws {
try? FileManager.default.removeItem(at: tempDirectory)
}
func testProcessesAllJobsAndReportsEachOutcome() async throws {
let validClip = try TestVideoFactory.makeNineBySixteenClip(fileName: "SOMOS-9x16-v3-DE.mov", in: tempDirectory)
let skippedURL = tempDirectory.appendingPathComponent("SOMOS-4x5-v3-DE.mov")
let rejectedURL = tempDirectory.appendingPathComponent("SOMOS-v3-DE.mov")
let jobs = [
JobQueue.Job(sourceURL: validClip.url),
JobQueue.Job(sourceURL: skippedURL),
JobQueue.Job(sourceURL: rejectedURL)
]
var results: [JobQueue.JobResult] = []
for await result in JobQueue.run(jobs: jobs, outputRootDirectory: outputDirectory) {
results.append(result)
}
XCTAssertEqual(results.count, 3)
func outcome(for job: JobQueue.Job) -> ConversionPipeline.Outcome? {
results.first { $0.job.id == job.id }?.outcome
}
guard case .succeeded = outcome(for: jobs[0]) else {
return XCTFail("Erwartete .succeeded für die valide Datei")
}
guard case .skipped(_, .alreadyTargetFormat) = outcome(for: jobs[1]) else {
return XCTFail("Erwartete .skipped für die bereits-4:5-Datei")
}
guard case .rejected(_, .formatSegmentMissing) = outcome(for: jobs[2]) else {
return XCTFail("Erwartete .rejected für die Datei ohne Format-Segment")
}
}
func testWorksWithMaxConcurrentOne() async throws {
let clipA = try TestVideoFactory.makeNineBySixteenClip(fileName: "SOMOS-9x16-v3-DE.mov", in: tempDirectory)
let clipB = try TestVideoFactory.makeNineBySixteenClip(fileName: "Somos-Pendant-9x16-v3-DE.mov", in: tempDirectory)
let jobs = [JobQueue.Job(sourceURL: clipA.url), JobQueue.Job(sourceURL: clipB.url)]
var successCount = 0
for await result in JobQueue.run(jobs: jobs, outputRootDirectory: outputDirectory, maxConcurrent: 1) {
if case .succeeded = result.outcome {
successCount += 1
}
}
XCTAssertEqual(successCount, 2)
}
func testReportsProgressForJobs() async throws {
let clip = try TestVideoFactory.makeNineBySixteenClip(fileName: "SOMOS-9x16-v3-DE.mov", in: tempDirectory)
let job = JobQueue.Job(sourceURL: clip.url)
let progressBox = ProgressBox()
var results: [JobQueue.JobResult] = []
for await result in JobQueue.run(
jobs: [job],
outputRootDirectory: outputDirectory,
progress: { _, value in progressBox.record(value) }
) {
results.append(result)
}
XCTAssertEqual(results.count, 1)
XCTAssertFalse(progressBox.values.isEmpty)
}
/// Sammelt Fortschrittswerte thread-sicher (synchron per Lock statt
/// Actor-Hop), da `progress` von einer Hintergrund-Queue innerhalb von
/// CropEngine aufgerufen wird und wir sofort nach dem Batch lesen.
private final class ProgressBox: @unchecked Sendable {
private let lock = NSLock()
private var _values: [Double] = []
func record(_ value: Double) {
lock.lock()
_values.append(value)
lock.unlock()
}
var values: [Double] {
lock.lock()
defer { lock.unlock() }
return _values
}
}
}

Powered by TurnKey Linux.