92 lines
3.8 KiB
Swift
92 lines
3.8 KiB
Swift
|
|
import XCTest
|
||
|
|
import Foundation
|
||
|
|
import ForgeCamera
|
||
|
|
import ForgeCameraARRI
|
||
|
|
import ForgeColor
|
||
|
|
import ForgeGrade
|
||
|
|
import ForgeLibrary
|
||
|
|
import ForgeExport
|
||
|
|
import ForgeSim
|
||
|
|
@testable import ForgeLogger
|
||
|
|
|
||
|
|
/// Full pipeline: ARRI sim -> driver poll -> ClipLogger -> LibraryStore -> exports.
|
||
|
|
final class EndToEndExportTests: XCTestCase {
|
||
|
|
|
||
|
|
func testSimSessionToExports() async throws {
|
||
|
|
// Infra.
|
||
|
|
let sim = ArriSimulator()
|
||
|
|
try await sim.start(port: 0)
|
||
|
|
defer { Task { try? await sim.stop() } }
|
||
|
|
let port = await sim.boundPort!
|
||
|
|
|
||
|
|
let dbPath = NSTemporaryDirectory() + "forge-e2e-\(UUID().uuidString).db"
|
||
|
|
defer { try? FileManager.default.removeItem(atPath: dbPath) }
|
||
|
|
let store = try LibraryStore(path: dbPath)
|
||
|
|
let project = try store.createProject(name: "E2E")
|
||
|
|
let day = try store.createDay(projectID: project.id, label: "Day 01", date: "2026-07-10")
|
||
|
|
|
||
|
|
let driver = ArriDriver(host: "127.0.0.1", port: port, pollInterval: .milliseconds(15))
|
||
|
|
let logger = ClipLogger(store: store, dayID: day.id)
|
||
|
|
|
||
|
|
let grade = GradeStack(nodes: [GradeNode(kind: .cdl(CDL(
|
||
|
|
slope: SIMD3(1.15, 1.0, 0.92), offset: SIMD3(0.01, 0, -0.01),
|
||
|
|
power: .one, saturation: 1.1)))])
|
||
|
|
let snapshotForProvider = grade
|
||
|
|
|
||
|
|
await logger.attach(slotName: "A-Cam", driver: driver) { snapshotForProvider }
|
||
|
|
try await driver.connect()
|
||
|
|
|
||
|
|
// Three takes.
|
||
|
|
let takes: [(clip: String, tcIn: String, tcOut: String)] = [
|
||
|
|
("A001C001_260710", "10:00:00:00", "10:00:30:00"),
|
||
|
|
("A001C002_260710", "10:05:00:00", "10:05:45:00"),
|
||
|
|
("A001C003_260710", "10:12:00:00", "10:13:00:00"),
|
||
|
|
]
|
||
|
|
for take in takes {
|
||
|
|
await sim.setMetadata(ei: 800, wb: 5600, tint: 0, fps: 24, timecode: take.tcIn)
|
||
|
|
try await Task.sleep(for: .milliseconds(60))
|
||
|
|
await sim.setRecording(true, clipName: take.clip)
|
||
|
|
try await Task.sleep(for: .milliseconds(80))
|
||
|
|
await sim.setMetadata(ei: 800, wb: 5600, tint: 0, fps: 24, timecode: take.tcOut)
|
||
|
|
try await Task.sleep(for: .milliseconds(60))
|
||
|
|
await sim.setRecording(false)
|
||
|
|
try await Task.sleep(for: .milliseconds(80))
|
||
|
|
}
|
||
|
|
|
||
|
|
await driver.disconnect()
|
||
|
|
await logger.stop()
|
||
|
|
|
||
|
|
// Three shots logged with TCs + snapshots.
|
||
|
|
let shots = try store.listShots(dayID: day.id)
|
||
|
|
XCTAssertEqual(shots.count, 3)
|
||
|
|
XCTAssertEqual(shots.map(\.clipName), takes.map(\.clip))
|
||
|
|
for (shot, take) in zip(shots, takes) {
|
||
|
|
XCTAssertEqual(shot.timecodeIn, take.tcIn)
|
||
|
|
XCTAssertEqual(shot.timecodeOut, take.tcOut)
|
||
|
|
XCTAssertNotNil(shot.gradeSnapshot)
|
||
|
|
}
|
||
|
|
|
||
|
|
// All export formats produce sane output.
|
||
|
|
let ale = PostExport.writeALE(shots: shots, fps: 24)
|
||
|
|
XCTAssertEqual(ale.components(separatedBy: "A001C").count - 1, 3)
|
||
|
|
|
||
|
|
let csv = PostExport.writeCSV(shots: shots)
|
||
|
|
XCTAssertEqual(csv.split(separator: "\n").count, 4) // header + 3
|
||
|
|
|
||
|
|
let edl = PostExport.writeEDL(shots: shots, title: "DAY01", fps: 24)
|
||
|
|
XCTAssertTrue(edl.contains("003 A001C003_260710"))
|
||
|
|
XCTAssertEqual(edl.components(separatedBy: "* ASC_SOP").count - 1, 3)
|
||
|
|
|
||
|
|
let ccc = CDLExport.writeCCC(shots.compactMap { s in
|
||
|
|
guard let data = s.gradeSnapshot,
|
||
|
|
let stack = try? GradeSnapshot.decode(data),
|
||
|
|
case .cdl(let c)? = stack.nodes.first?.kind else { return nil }
|
||
|
|
return (s.clipName, c)
|
||
|
|
})
|
||
|
|
XCTAssertEqual(ccc.components(separatedBy: "<ColorCorrection id=").count - 1, 3)
|
||
|
|
|
||
|
|
let cube = try CubeExport.fromSnapshot(shots[0].gradeSnapshot!, latticeSize: 17, title: shots[0].clipName)
|
||
|
|
XCTAssertTrue(cube.contains("LUT_3D_SIZE 17"))
|
||
|
|
}
|
||
|
|
}
|