Files
OSGKeyboard/OSGKeyboardTests/CloudASRTests.swift
T
Rocky bf844caa7f feat(dictionary): add iCloud KVS sync, cloud ASR, and lexicon expansion
Mirror the personal dictionary through iCloud Key-Value Store with
deterministic merge rules, main-app-only sync UI, and App Group as the
keyboard runtime cache. Add cloud-engine ASR with dictionary bias and
expand the bundled custom language model lexicon.
2026-07-06 22:44:14 +08:00

79 lines
3.5 KiB
Swift

// CloudASRTests.swift
// OSGKeyboardTests
import XCTest
@testable import OSGKeyboardShared
final class CloudASRTests: XCTestCase {
func testCloudASRStrategyRouting() {
XCTAssertEqual(CloudASRModelCatalog.strategy(for: "zhipu"), .zhipuHotwords)
XCTAssertEqual(CloudASRModelCatalog.strategy(for: "qwen"), .alibabaVocabulary)
XCTAssertEqual(CloudASRModelCatalog.strategy(for: "openai"), .prompt)
XCTAssertEqual(CloudASRModelCatalog.strategy(for: "mimo"), .prompt)
XCTAssertEqual(CloudASRModelCatalog.strategy(for: "moonshot"), .localFallback)
}
func testCloudASRModelDefaults() {
XCTAssertEqual(CloudASRModelCatalog.defaultModel(for: "qwen"), "fun-asr-flash-2026-06-15")
XCTAssertEqual(CloudASRModelCatalog.defaultModel(for: "zhipu"), "glm-asr-2512")
XCTAssertEqual(CloudASRModelCatalog.defaultModel(for: "mimo"), "mimo-v2.5-asr")
XCTAssertEqual(CloudASRModelCatalog.defaultModel(for: "openai"), "gpt-4o-mini-transcribe")
}
func testPersonalDictionaryCloudASRBadgeProviders() {
XCTAssertTrue(LLMProvider.provider(id: "zhipu").supportsPersonalDictionaryCloudASR)
XCTAssertTrue(LLMProvider.provider(id: "qwen").supportsPersonalDictionaryCloudASR)
XCTAssertFalse(LLMProvider.provider(id: "openai").supportsPersonalDictionaryCloudASR)
XCTAssertFalse(LLMProvider.provider(id: "moonshot").supportsPersonalDictionaryCloudASR)
}
func testPersonalDictionaryASRHotwordsDedupesTerms() {
let dict = PersonalDictionary(entries: [
PersonalDictionary.Entry(term: "Kubernetes", category: .technical, source: .manual),
PersonalDictionary.Entry(term: "kubernetes", category: .technical, source: .manual),
PersonalDictionary.Entry(term: "OSGKeyboard", category: .productName, source: .manual),
])
let hotwords = dict.asrHotwords()
XCTAssertEqual(hotwords.count, 2)
XCTAssertTrue(hotwords.contains("Kubernetes"))
XCTAssertTrue(hotwords.contains("OSGKeyboard"))
}
func testPersonalDictionaryASRPromptIncludesAliases() {
var dict = PersonalDictionary.empty
_ = dict.upsertManual(term: "Kubernetes")
dict.updateAliases(
for: dict.entries[0].id,
aliases: ["k8s", "库伯内特斯"]
)
let prompt = dict.asrPromptBias()
XCTAssertTrue(prompt.contains("Kubernetes"))
XCTAssertTrue(prompt.contains("k8s"))
}
func testPersonalDictionaryAlibabaHotwordEntries() {
let dict = PersonalDictionary(entries: [
PersonalDictionary.Entry(term: "Cursor", category: .productName, source: .manual),
])
let entries = dict.alibabaHotwordEntries()
XCTAssertEqual(entries.count, 1)
XCTAssertEqual(entries[0].text, "Cursor")
XCTAssertEqual(entries[0].weight, 4)
}
func testPCMSampleWavEncoderProducesHeader() {
let wav = PCMSampleWavEncoder.encode(samples: [0.0, 0.5, -0.5], sampleRate: 16_000)
XCTAssertGreaterThan(wav.count, 44)
XCTAssertEqual(String(data: wav.prefix(4), encoding: .ascii), "RIFF")
XCTAssertEqual(String(data: wav.dropFirst(8).prefix(4), encoding: .ascii), "WAVE")
}
func testVocabularyFingerprintChangesWhenDictionaryChanges() {
var dict = PersonalDictionary.empty
let emptyFP = dict.vocabularySyncFingerprint()
_ = dict.upsertManual(term: "OSGKeyboard")
XCTAssertNotEqual(emptyFP, dict.vocabularySyncFingerprint())
}
}