feat(keyboard): improve typing, voice flow, and polish reliability
Reduce extension memory pressure and delivery races while adding richer candidates, tactile feedback, and safer two-level creative polishing.
This commit is contained in:
@@ -0,0 +1,54 @@
|
||||
// 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
|
||||
import XCTest
|
||||
@testable import OSGKeyboardHostSupport
|
||||
@testable import OSGKeyboardShared
|
||||
|
||||
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
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user