spiegel-keyman/ios/engine/KMEI/KeymanEngineTests/FileManagementTests.swift

204 lines
9.2 KiB
Swift

//
// KeymanEngineTests.swift
// KeymanEngineTests
//
// Created by Joshua Horton on 2020-02-19.
// Copyright © 2020 SIL International. All rights reserved.
//
import XCTest
@testable import KeymanEngine
import DeviceKit
class FileManagementTests: XCTestCase {
override func setUp() {
TestUtils.setupAndDeinitManager()
}
override func tearDown() {
TestUtils.standardTearDown()
}
func testKeyboardInstallation() throws {
let kmp = try ResourceFileManager.shared.prepareKMPInstall(from: TestUtils.Keyboards.khmerAngkorKMP)
XCTAssertNotNil(kmp, "Failed to prepare KMP for installation")
XCTAssertNotNil(kmp as? KeyboardKeymanPackage, "KMP resource type improperly recognized - expected a keyboard package!")
try ResourceFileManager.shared.finalizePackageInstall(kmp, isCustom: true)
let installURL = Storage.active.keyboardURL(for: TestUtils.Keyboards.khmer_angkor)
XCTAssertTrue(FileManager.default.fileExists(atPath: installURL.path),
"Could not find installed keyboard file")
let keyboards = Storage.active.userDefaults.userKeyboards!
XCTAssertEqual(keyboards.count, 1, "Unexpected number of keyboards were installed")
XCTAssertEqual(keyboards[0].id, "khmer_angkor", "Installed keyboard ID mismatch")
let fontURL = Storage.active.fontURL(forResource: TestUtils.Keyboards.khmer_angkor, filename: "Mondulkiri-R.ttf")!
XCTAssertTrue(FileManager.default.fileExists(atPath: fontURL.path))
}
func testLexicalModelInstallation() throws {
let kmp = try ResourceFileManager.shared.prepareKMPInstall(from: TestUtils.LexicalModels.mtntKMP)
XCTAssertNotNil(kmp, "Failed to prepare KMP for installation")
XCTAssertNotNil(kmp as? LexicalModelKeymanPackage, "KMP resource type improperly recognized - expected a lexical model package!")
try ResourceFileManager.shared.finalizePackageInstall(kmp, isCustom: true)
let installURL = Storage.active.lexicalModelURL(for: TestUtils.LexicalModels.mtnt)
XCTAssertTrue(FileManager.default.fileExists(atPath: installURL.path),
"Could not find installed lexical model file")
let models = Storage.active.userDefaults.userLexicalModels!
// Yep, the model auto-installs for all language ids, even when there's no matching keyboard.
// That's the current state of affairs in Keyman Engine for iOS.
XCTAssertEqual(models.count, 3, "Unexpected number of models were installed")
XCTAssertEqual(models[0].id, "nrc.en.mtnt", "Installed lexical model ID mismatch")
}
func testInstallKeyboardFromPackage() throws {
// Standard installation
let rawKMP = try ResourceFileManager.shared.prepareKMPInstall(from: TestUtils.Keyboards.khmerAngkorKMP)
XCTAssertNotNil(rawKMP, "Failed to prepare KMP for installation")
guard let kmp = rawKMP as? KeyboardKeymanPackage else {
XCTFail("KMP resource type improperly recognized - expected a keyboard package!")
return
}
do {
try ResourceFileManager.shared.install(resourceWithID: TestUtils.Keyboards.khmer_angkor.fullID, from: kmp)
} catch {
XCTFail("Unexpected error during KeyboardPackage install")
}
let installURL = Storage.active.keyboardURL(for: TestUtils.Keyboards.khmer_angkor)
XCTAssertTrue(FileManager.default.fileExists(atPath: installURL.path),
"Could not find installed keyboard file")
let keyboards = Storage.active.userDefaults.userKeyboards!
XCTAssertEqual(keyboards.count, 1, "Unexpected number of keyboards were installed")
XCTAssertEqual(keyboards[0].id, "khmer_angkor", "Installed keyboard ID mismatch")
// While the LanguageResource definition we provided lacks font definitions, the
// KMP's definition has that data. By default, the KMP's definition takes precedence.
let fontURL = Storage.active.fontURL(forResource: TestUtils.Keyboards.khmer_angkor, filename: "Mondulkiri-R.ttf")!
XCTAssertTrue(FileManager.default.fileExists(atPath: fontURL.path))
}
func testInstallLexicalModelFromPackage() throws {
let rawKMP = try ResourceFileManager.shared.prepareKMPInstall(from: TestUtils.LexicalModels.mtntKMP)
XCTAssertNotNil(rawKMP, "Failed to prepare KMP for installation")
guard let kmp = rawKMP as? LexicalModelKeymanPackage else {
XCTFail("KMP resource type improperly recognized - expected a lexical model package!")
return
}
do {
try ResourceFileManager.shared.install(resourceWithID: TestUtils.LexicalModels.mtnt.fullID, from: kmp)
} catch {
XCTFail("Unexpected error during LexicalModelPackage install")
}
let installURL = Storage.active.lexicalModelURL(for: TestUtils.LexicalModels.mtnt)
XCTAssertTrue(FileManager.default.fileExists(atPath: installURL.path),
"Could not find installed lexical model file")
let models = Storage.active.userDefaults.userLexicalModels!
// This variant is selective - only a single pairing should be installed for the model.
XCTAssertEqual(models.count, 1, "Unexpected number of models were installed")
XCTAssertEqual(models[0].id, "nrc.en.mtnt", "Installed lexical model ID mismatch")
}
func testInstallUpdateCheck() throws {
// Has a resource in need of updates (sil_euro_latin)
TestUtils.Migrations.applyBundleToFileSystem(TestUtils.Migrations.cloud_to_kmp_13)
let package = try ResourceFileManager.shared.prepareKMPInstall(from: TestUtils.Keyboards.silEuroLatinKMP) as! KeyboardKeymanPackage
let updatables = ResourceFileManager.shared.findPotentialUpdates(in: package)
XCTAssertEqual(updatables.count, 2)
XCTAssertTrue(updatables.contains(where: { $0.languageID == "en" }))
XCTAssertTrue(updatables.contains(where: { $0.languageID == "fr" }))
}
func testGetInstalledPackageFor() throws {
// Standard installation
let rawKMP = try ResourceFileManager.shared.prepareKMPInstall(from: TestUtils.Keyboards.khmerAngkorKMP)
XCTAssertNotNil(rawKMP, "Failed to prepare KMP for installation")
guard let kmp = rawKMP as? KeyboardKeymanPackage else {
XCTFail("KMP resource type improperly recognized - expected a keyboard package!")
return
}
do {
try ResourceFileManager.shared.install(resourceWithID: TestUtils.Keyboards.khmer_angkor.fullID, from: kmp)
} catch {
XCTFail("Unexpected error during KeyboardPackage install")
}
// We did not install sil_euro_latin.
XCTAssertNil(ResourceFileManager.shared.getInstalledPackage(for: TestUtils.Keyboards.sil_euro_latin))
// We've installed khmer_angkor for 'km'. Now to look up the resource from its InstallableKeyboard def.
let km_package = ResourceFileManager.shared.getInstalledPackage(for: TestUtils.Keyboards.khmer_angkor)
XCTAssertNotNil(km_package)
if let package = km_package {
XCTAssertFalse(package.metadata.isAutogeneratedWrapper)
XCTAssertFalse(package.isTemp)
let kbdMetadata: KMPKeyboard? = package.findMetadataMatchFor(resource: TestUtils.Keyboards.khmer_angkor, ignoreLanguage: false, ignoreVersion: false)
XCTAssertNotNil(kbdMetadata)
}
}
func testInstallStateForPackage() throws {
// State 1: Not installed, no download or install pending.
let khmer_angkor_key = TestUtils.Keyboards.khmer_angkor.packageKey
// No downloads have even started.
XCTAssertEqual(ResourceFileManager.shared.installState(forPackage: khmer_angkor_key), .none)
// State 2: Download requested.
// Note - we don't need to actually run the queue.
let downloadManager = ResourceDownloadManager(session: TestUtils.Downloading.URLSessionMock(), autoExecute: false)
downloadManager.downloadPackage(withKey: khmer_angkor_key,
from: TestUtils.Keyboards.khmerAngkorKMP,
completionBlock: { _, _ in })
XCTAssertEqual(ResourceFileManager.shared.installState(forPackage: khmer_angkor_key, withManager: downloadManager), .downloading)
// State 3: During install process.
// If it was just downloaded, that means it should exist within the Documents directory.
let documentsKMPURL = ResourceFileManager.shared.importFile(TestUtils.Keyboards.khmerAngkorKMP)!
guard let installPackage = try ResourceFileManager.shared.prepareKMPInstall(from: documentsKMPURL) as? KeyboardKeymanPackage else {
XCTFail("Could not load keyboard KMP for test")
return
}
XCTAssertEqual(installPackage.installState, .pending)
XCTAssertEqual(ResourceFileManager.shared.installState(forPackage: khmer_angkor_key), .pending)
// State 4: package is fully installed.
try ResourceFileManager.shared.install(resourceWithID: TestUtils.Keyboards.khmer_angkor.fullID, from: installPackage)
// Retrieve an instance for the installation. We're currently using the temp version.
guard let package = ResourceFileManager.shared.getInstalledPackage(withKey: installPackage.key) else {
XCTFail("Could not load installed form of keyboard KMP for test")
return
}
XCTAssertEqual(installPackage.installState, .pending) // Reflects that the instance is a temporary extraction.
XCTAssertEqual(package.installState, .installed) // Reflects the actually-installed package
XCTAssertEqual(ResourceFileManager.shared.installState(forPackage: khmer_angkor_key), .installed)
}
}