Skip to content

Commit 99ff8fc

Browse files
committed
Warm up AVFoundation encoder once before tests
The first AVAssetWriter/H.264 use on the CI simulator pays a large, variable cold-start cost (30s+ observed), which landed inside the first video test's timed expectation and could trip its timeout. Pay that cost once in setUp, outside any XCTest expectation, so each test only measures steady-state latency.
1 parent cae246d commit 99ff8fc

1 file changed

Lines changed: 34 additions & 0 deletions

File tree

TimeLapseBuilder-Common/TimeLapseBuilderTests.swift

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,40 @@ import XCTest
1111
@testable import TimeLapseBuilder
1212

1313
class TimeLapseBuilderTests: XCTestCase {
14+
private static var didWarmUpEncoder = false
15+
16+
override func setUp() {
17+
super.setUp()
18+
Self.warmUpEncoderIfNeeded()
19+
}
20+
21+
// The first use of AVAssetWriter's H.264 encoder on the CI simulator pays a
22+
// large and highly variable cold-start cost (30s+ has been observed). Pay it
23+
// once here, before any test's timed expectation, so individual tests only
24+
// measure steady-state encoding latency. This wait is not bounded by an
25+
// XCTest expectation, so the cold start can't trip a test timeout.
26+
private static func warmUpEncoderIfNeeded() {
27+
guard !didWarmUpEncoder else { return }
28+
didWarmUpEncoder = true
29+
30+
guard let warmUpAsset = Bundle(for: TimeLapseBuilderTests.self).url(forResource: "red", withExtension: "jpg")?.absoluteString else {
31+
return
32+
}
33+
34+
let semaphore = DispatchSemaphore(value: 0)
35+
let delegate = TestDelegate(progress: { _ in }, finished: { _ in
36+
semaphore.signal()
37+
}, failed: { _ in
38+
semaphore.signal()
39+
})
40+
let documentsPath = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0] as NSString
41+
let outputPath = documentsPath.appendingPathComponent("WarmUp.mov")
42+
43+
let builder = TimeLapseBuilder(delegate: delegate)
44+
builder.build(with: [warmUpAsset], atFrameRate: 30, type: .mov, toOutputPath: outputPath)
45+
_ = semaphore.wait(timeout: .now() + 120)
46+
}
47+
1448
func testWhenGivenASeriesOfImages_producesAnOutputFile() {
1549
let expectation = self.expectation(description: "Build timelapse")
1650
let testDelegate = TestDelegate(progress: { (progress: Progress) in

0 commit comments

Comments
 (0)