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
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
|
|
}
|
|
}
|
|
}
|