Files
OSGKeyboard/OSGKeyboardTests/FlowPhysicalAudioStressTests.swift
T
Rocky 498f407585 feat(account): add managed credits and cloud gateway
Introduce optional Apple account-backed credits with scoped gateway access while preserving local and BYOK paths. Refresh assistant behavior, tests, privacy disclosures, docs, and the website for the 2.0 experience.
2026-08-20 11:43:21 +08:00

55 lines
2.0 KiB
Swift

// FlowPhysicalAudioStressTests.swift
// OSGKeyboardTests
//
// Physical-device release gate for the PiP playback ↔ capture transition.
// Excluded from PR presets because Simulator cannot model Bluetooth HFP.
import AVFoundation
@testable import OSGKeyboardHostSupport
@testable import OSGKeyboardShared
import XCTest
final class FlowPhysicalAudioStressTests: XCTestCase {
@MainActor
func testFiftyCapturePlaybackCyclesRemainStable() async throws {
#if targetEnvironment(simulator)
throw XCTSkip("Bluetooth HFP stress requires a physical iPhone")
#else
guard AVAudioApplication.shared.recordPermission == .granted else {
throw XCTSkip("Grant microphone permission to OSGKeyboard first")
}
let capture = FlowContinuousCapture()
let initialRSS = OSGDiag.memoryMB()
for iteration in 1...50 {
try await capture.start()
let receivedFrame = await capture.awaitAudioFlowing(timeout: 2)
XCTAssertTrue(receivedFrame, "No microphone frame in iteration \(iteration)")
XCTAssertTrue(capture.engineIsLive, "Engine not live in iteration \(iteration)")
capture.stop(releaseSession: false)
let playbackReady = await FlowAudioSessionCoordinator.shared.activatePlayback()
XCTAssertTrue(playbackReady, "PiP playback restore failed in iteration \(iteration)")
try? await Task.sleep(nanoseconds: 50_000_000)
}
try? await Task.sleep(nanoseconds: 500_000_000)
XCTAssertEqual(capture.engineActivationCount, 50)
XCTAssertEqual(
capture.routeRecoveryCount,
0,
"Stable routeConfigurationChange notifications must not rebuild the engine"
)
let growth = OSGDiag.memoryMB() - initialRSS
XCTAssertLessThan(
growth,
80,
"Fifty audio cycles retained \(String(format: "%.1f", growth)) MB"
)
FlowAudioSessionCoordinator.shared.deactivate()
#endif
}
}