Files
Termind/TFITests/MobileSystemSoundPlayerTests.swift

66 lines
2.4 KiB
Swift

// SPDX-FileCopyrightText: 2026 Kaede Akino
// SPDX-License-Identifier: GPL-3.0-only
import AudioToolbox
import Foundation
import Synchronization
import Testing
@testable import TermindIOS
@MainActor
struct MobileSystemSoundPlayerTests {
@Test func sharedBellResourceIsBundledAsWaveAudio() throws {
let url = try #require(TerminalNotificationPlatform.soundURL)
#expect(url.lastPathComponent == "bell.wav")
let data = try Data(contentsOf: url)
#expect(String(data: data.prefix(4), encoding: .ascii) == "RIFF")
#expect(String(data: data.dropFirst(8).prefix(4), encoding: .ascii) == "WAVE")
}
@Test func completionCanDisposeOnTheAudioQueueWithoutReenteringTheMainActor() async throws {
let completions = Mutex<[@Sendable () -> Void]>([])
let started = Mutex<[SystemSoundID]>([])
let disposed = Mutex<[SystemSoundID]>([])
let nextSound = Mutex<SystemSoundID>(40)
let player = MobileSystemSoundPlayer(
create: { _ in
nextSound.withLock {
$0 += 1
return $0
}
},
start: { sound, completion in
started.withLock { $0.append(sound) }
completions.withLock { $0.append(completion) }
},
dispose: { sound in
#expect(!Thread.isMainThread)
disposed.withLock { $0.append(sound) }
})
let url = URL(fileURLWithPath: "/unused.wav")
player.play(url: url)
player.play(url: url)
#expect(started.withLock { $0 } == [41, 42])
#expect(disposed.withLock { $0.isEmpty })
let callbacks = completions.withLock { $0 }
#expect(callbacks.count == 2)
await withCheckedContinuation { continuation in
DispatchQueue(label: "test.audio-completion").async {
for callback in callbacks.reversed() { callback() }
continuation.resume()
}
}
#expect(disposed.withLock { $0 } == [42, 41])
}
@Test func failedSoundCreationDoesNotPlayOrDisposeAnInvalidIdentifier() {
let player = MobileSystemSoundPlayer(
create: { _ in nil },
start: { _, _ in Issue.record("Failed creation must not start playback") },
dispose: { _ in Issue.record("Failed creation has no sound to dispose") })
player.play(url: URL(fileURLWithPath: "/missing.wav"))
}
}