import XCTest @testable import Rosetta final class VoiceRecordingParityMathTests: XCTestCase { func testParityConstants() { XCTAssertEqual(VoiceRecordingParityConstants.holdThreshold, 0.19, accuracy: 0.0001) XCTAssertEqual(VoiceRecordingParityConstants.cancelDistanceThreshold, -150) XCTAssertEqual(VoiceRecordingParityConstants.cancelHapticThreshold, -100) XCTAssertEqual(VoiceRecordingParityConstants.lockDistanceThreshold, -110) XCTAssertEqual(VoiceRecordingParityConstants.lockHapticThreshold, -60) XCTAssertEqual(VoiceRecordingParityConstants.velocityGate, -400) XCTAssertEqual(VoiceRecordingParityConstants.preHoldCancelDistance, 10) XCTAssertEqual(VoiceRecordingParityConstants.micHitInsetX, -10) XCTAssertEqual(VoiceRecordingParityConstants.locknessDivisor, 105) XCTAssertEqual(VoiceRecordingParityConstants.dragNormalizeDivisor, 300) XCTAssertEqual(VoiceRecordingParityConstants.cancelTransformThreshold, 8) XCTAssertEqual(VoiceRecordingParityConstants.sendAccessibilityHitSize, 120) XCTAssertEqual(VoiceRecordingParityConstants.minVoiceDuration, 0.5) XCTAssertEqual(VoiceRecordingParityConstants.minFreeDiskBytes, 8 * 1024 * 1024) } func testReleaseDecisionVelocityGate() { let cancel = VoiceRecordingParityMath.releaseDecision( velocityX: -500, velocityY: 0, distanceX: -10, distanceY: 0 ) XCTAssertEqual(cancel, .cancel) let lock = VoiceRecordingParityMath.releaseDecision( velocityX: 0, velocityY: -500, distanceX: 0, distanceY: -10 ) XCTAssertEqual(lock, .lock) } func testReleaseDecisionDistanceFallback() { let cancel = VoiceRecordingParityMath.releaseDecision( velocityX: 0, velocityY: 0, distanceX: -120, distanceY: 0 ) XCTAssertEqual(cancel, .cancel) let lock = VoiceRecordingParityMath.releaseDecision( velocityX: 0, velocityY: 0, distanceX: 0, distanceY: -80 ) XCTAssertEqual(lock, .lock) let finish = VoiceRecordingParityMath.releaseDecision( velocityX: 0, velocityY: 0, distanceX: -20, distanceY: -20 ) XCTAssertEqual(finish, .finish) } func testDominantAxis() { XCTAssertEqual( VoiceRecordingParityMath.dominantAxisDistances(distanceX: -110, distanceY: -40).0, -110 ) XCTAssertEqual( VoiceRecordingParityMath.dominantAxisDistances(distanceX: -110, distanceY: -40).1, 0 ) XCTAssertEqual( VoiceRecordingParityMath.dominantAxisDistances(distanceX: -20, distanceY: -80).0, 0 ) XCTAssertEqual( VoiceRecordingParityMath.dominantAxisDistances(distanceX: -20, distanceY: -80).1, -80 ) } func testLocknessNormalization() { XCTAssertEqual(VoiceRecordingParityMath.lockness(distanceY: 0), 0) XCTAssertEqual(VoiceRecordingParityMath.lockness(distanceY: -52.5), 0.5, accuracy: 0.0001) XCTAssertEqual(VoiceRecordingParityMath.lockness(distanceY: -500), 1) } func testNormalizedDrag() { XCTAssertEqual(VoiceRecordingParityMath.normalizedDrag(distance: 0), 0, accuracy: 0.0001) XCTAssertEqual(VoiceRecordingParityMath.normalizedDrag(distance: 150), 0.5, accuracy: 0.0001) XCTAssertEqual(VoiceRecordingParityMath.normalizedDrag(distance: -450), 1, accuracy: 0.0001) } func testCancelTransformThreshold() { XCTAssertFalse(VoiceRecordingParityMath.shouldApplyCancelTransform(-8)) XCTAssertTrue(VoiceRecordingParityMath.shouldApplyCancelTransform(-8.1)) } func testShortRecordingDiscardGuard() { XCTAssertTrue(VoiceRecordingParityMath.shouldDiscard(duration: 0.49)) XCTAssertFalse(VoiceRecordingParityMath.shouldDiscard(duration: 0.5)) XCTAssertFalse(VoiceRecordingParityMath.shouldDiscard(duration: 1.2)) } func testMinTrimDurationFormula() { let minDuration = VoiceRecordingParityConstants.minTrimDuration(duration: 10, waveformWidth: 280) XCTAssertEqual(minDuration, 2.0, accuracy: 0.0001) let clamped = VoiceRecordingParityConstants.minTrimDuration(duration: 1, waveformWidth: 600) XCTAssertEqual(clamped, 1.0, accuracy: 0.0001) } func testClampTrimRange() { let range = VoiceRecordingParityMath.clampTrimRange((-3)...(12), duration: 8) XCTAssertEqual(range.lowerBound, 0) XCTAssertEqual(range.upperBound, 8) } func testWaveformSliceRange() { let range = VoiceRecordingParityMath.waveformSliceRange( sampleCount: 100, totalDuration: 10, trimRange: 2...7 ) XCTAssertEqual(range, 20..<70) } func testWaveformSliceRangeInvalidInputs() { XCTAssertNil( VoiceRecordingParityMath.waveformSliceRange( sampleCount: 0, totalDuration: 10, trimRange: 2...7 ) ) XCTAssertNil( VoiceRecordingParityMath.waveformSliceRange( sampleCount: 100, totalDuration: 0, trimRange: 2...7 ) ) } }