mirror of
https://github.com/keymanapp/keyman.git
synced 2026-08-12 11:55:32 +00:00
221 lines
10 KiB
Swift
221 lines
10 KiB
Swift
//
|
|
// MigrationTests.swift
|
|
// KeymanEngineTests
|
|
//
|
|
// Created by Joshua Horton on 2/20/20.
|
|
// Copyright © 2020 SIL International. All rights reserved.
|
|
//
|
|
|
|
import Foundation
|
|
@testable import KeymanEngine
|
|
import XCTest
|
|
|
|
class MigrationTests: XCTestCase {
|
|
override func tearDown() {
|
|
TestUtils.standardTearDown()
|
|
}
|
|
|
|
func testComplexVersion13Migration() {
|
|
TestUtils.Migrations.applyBundleToFileSystem(TestUtils.Migrations.cloud_to_kmp_13)
|
|
Migrations.migrate(storage: Storage.active)
|
|
Migrations.updateResources(storage: Storage.active)
|
|
|
|
let userDefaults = Storage.active.userDefaults
|
|
let userKeyboards = userDefaults.userKeyboards
|
|
|
|
// The fun thing to test here - sil_euro_latin is first wrapped with an auto-generated
|
|
// kmp.json, THEN updated with the actual KMP.
|
|
|
|
let sil_euro_latin_kbds = userKeyboards!.filter { return $0.id == "sil_euro_latin" }
|
|
|
|
sil_euro_latin_kbds.forEach {
|
|
XCTAssertEqual($0.packageID, "sil_euro_latin")
|
|
XCTAssertEqual($0.version, TestUtils.Keyboards.sil_euro_latin.version)
|
|
}
|
|
|
|
let sil_euro_latin_package = ResourceFileManager.shared.installedPackages.first(where: { $0.id == "sil_euro_latin" }) as! KeyboardKeymanPackage
|
|
|
|
XCTAssertFalse(sil_euro_latin_package.metadata.isAutogeneratedWrapper)
|
|
|
|
// As it's installing a true package, there will be files existing here that won't exist
|
|
// for the others.
|
|
let validationFilenames = ["kmp.inf", "readme.htm", "welcome.htm", "sil_euro_latin.kmx", "DejaVuSans.ttf", "currency.png", "usage.htm"]
|
|
validationFilenames.forEach {
|
|
let file = sil_euro_latin_package.sourceFolder.appendingPathComponent($0)
|
|
XCTAssertTrue(FileManager.default.fileExists(atPath: file.path), "Expected file \(file.path) missing")
|
|
}
|
|
}
|
|
|
|
func testVersion13ResourceMigration() {
|
|
TestUtils.Migrations.applyBundleToFileSystem(TestUtils.Migrations.simple_13)
|
|
Migrations.updateResources(storage: Storage.active)
|
|
|
|
let userDefaults = Storage.active.userDefaults
|
|
|
|
// SIL EuroLatin should be updated to 1.9.1. The lexical model version should be unchanged.
|
|
|
|
let defaultKbd = userDefaults.userKeyboards![0]
|
|
XCTAssertEqual(defaultKbd.id, Defaults.keyboard.id)
|
|
XCTAssertEqual(defaultKbd.version, Defaults.keyboard.version)
|
|
let keyboardURL = Storage.active.resourceURL(for: Defaults.keyboard)!
|
|
XCTAssert(FileManager.default.fileExists(atPath: keyboardURL.path))
|
|
}
|
|
|
|
func testVersion13CloudToKMPMigration() throws {
|
|
TestUtils.Migrations.applyBundleToFileSystem(TestUtils.Migrations.cloud_to_kmp_13)
|
|
|
|
let initialUserKeyboards = Storage.active.userDefaults.userKeyboards!
|
|
let initialUserModels = Storage.active.userDefaults.userLexicalModels!
|
|
|
|
// A baseline load-check; confirms we have the correct resource count at the start.
|
|
XCTAssertEqual(initialUserKeyboards.count, 7)
|
|
XCTAssertEqual(initialUserModels.count, 6)
|
|
|
|
try Migrations.migrateCloudResourcesToKMPFormat()
|
|
|
|
// Now that migration has completed, it's time to check the results.
|
|
|
|
let userKeyboards = Storage.active.userDefaults.userKeyboards!
|
|
let userModels = Storage.active.userDefaults.userLexicalModels!
|
|
|
|
// Pass 1: do we have a matching set of resources after the migration?
|
|
XCTAssertEqual(userKeyboards.count, 7)
|
|
XCTAssertEqual(userModels.count, 6)
|
|
|
|
userKeyboards.forEach{ kbd in
|
|
XCTAssertTrue(initialUserKeyboards.contains(where: { $0.fullID == kbd.fullID }))
|
|
XCTAssertEqual(kbd.packageID, kbd.id)
|
|
}
|
|
|
|
userModels.forEach{ lm in
|
|
XCTAssertTrue(initialUserModels.contains(where: { $0.fullID == lm.fullID }))
|
|
XCTAssertEqual(lm.packageID, lm.id)
|
|
}
|
|
|
|
// Pass 2: do we get the expected package metadata and file structure?
|
|
let installedPackages = ResourceFileManager.shared.installedPackages
|
|
installedPackages.forEach { package in
|
|
// A bit lazy, but at least we'll know which package(s) the error occurs for.
|
|
let generalMessage = "Unexpected value for package \(package.id)"
|
|
|
|
XCTAssertEqual(package.resources.count, 1, generalMessage)
|
|
let metadataFile = package.sourceFolder.appendingPathComponent("kmp.json")
|
|
XCTAssertTrue(FileManager.default.fileExists(atPath: metadataFile.path), generalMessage)
|
|
|
|
// "sil_sahu" has a version-matched locally-cached KMP, so it should be migrated based on
|
|
// that local KMP.
|
|
if package.id == "sil_sahu" {
|
|
XCTAssertFalse(package.metadata.isAutogeneratedWrapper, generalMessage)
|
|
XCTAssertNotEqual(package.version, Version(KMPInfo.AUTOGEN_VERSION.description), generalMessage)
|
|
XCTAssertEqual(package.version, Version("1.0")) // The version of the stored sil_sahu package.
|
|
|
|
// As it's installing a true package, there will be files existing here that won't exist
|
|
// for the others.
|
|
let validationFilenames = ["kmp.inf", "readme.htm", "welcome.htm", "sil_sahu.kmx"]
|
|
validationFilenames.forEach {
|
|
let file = package.sourceFolder.appendingPathComponent($0)
|
|
XCTAssertTrue(FileManager.default.fileExists(atPath: file.path), "Expected file \(file.path) missing for package \(package.id)")
|
|
}
|
|
// The others get autogenerated version wrappers.
|
|
// Even sil_cameroon_qwerty, which has a locally-cached KMP... but the version's out of date.
|
|
} else {
|
|
XCTAssertTrue(package.metadata.isAutogeneratedWrapper, generalMessage)
|
|
XCTAssertEqual(package.version, Version(KMPInfo.AUTOGEN_VERSION.description), generalMessage)
|
|
}
|
|
|
|
// .installableResourceSets[0] -> the set of LanguageResources represented by the
|
|
// one expected script-file-resource in each 'package'.
|
|
switch package.id {
|
|
case "sil_euro_latin":
|
|
XCTAssertEqual(package.installableResourceSets[0].count, 2, generalMessage)
|
|
case "nrc.en.mtnt":
|
|
XCTAssertEqual(package.installableResourceSets[0].count, 3, generalMessage)
|
|
case "nrc.str.sencoten":
|
|
XCTAssertEqual(package.installableResourceSets[0].count, 2, generalMessage)
|
|
default:
|
|
XCTAssertEqual(package.installableResourceSets[0].count, 1, generalMessage)
|
|
}
|
|
}
|
|
}
|
|
|
|
func testVersion12ResourceMigration() {
|
|
TestUtils.Migrations.applyBundleToFileSystem(TestUtils.Migrations.simple_12)
|
|
Migrations.updateResources(storage: Storage.active)
|
|
|
|
let userDefaults = Storage.active.userDefaults
|
|
|
|
// The two keyboards should remain in the same location, while the lexical model should be upgraded.
|
|
// v 0.1.2 -> 0.1.4.
|
|
// Minor surprise (as of 13.0) is that 0.1.2's file actually remains!
|
|
|
|
let defaultModel = userDefaults.userLexicalModels![0]
|
|
XCTAssertEqual(defaultModel.id, Defaults.lexicalModel.id)
|
|
XCTAssertEqual(defaultModel.version, Defaults.lexicalModel.version)
|
|
let modelURL = Storage.active.lexicalModelURL(for: TestUtils.LexicalModels.mtnt) // The bundled, 0.1.4 version.
|
|
XCTAssert(FileManager.default.fileExists(atPath: modelURL.path))
|
|
}
|
|
|
|
func testVersion12AdhocMigration() throws {
|
|
TestUtils.Migrations.applyBundleToFileSystem(TestUtils.Migrations.adhoc_12)
|
|
Storage.active.userDefaults.lastEngineVersion = Version.firstTracked
|
|
Migrations.migrate(storage: Storage.active)
|
|
|
|
// The files in the .documents directory should be erased after this method is run.
|
|
|
|
let documentsDirectory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0]
|
|
let documentsContents = try FileManager.default.contentsOfDirectory(atPath: documentsDirectory.path)
|
|
XCTAssertEqual(documentsContents.count, 1, "Documents directory was not purged of installation by-products during ad-hoc resource migration!")
|
|
|
|
// The .kmp.zip is converted back into its original .kmp file, which remains in the Documents directory
|
|
// so that it may be used for sharing.
|
|
let kmpURL = URL(fileURLWithPath: documentsContents[0])
|
|
XCTAssertEqual(kmpURL.lastPathComponent, "khmer10.kmp")
|
|
}
|
|
|
|
func testVersion10ResourceMigration() {
|
|
TestUtils.Migrations.applyBundleToFileSystem(TestUtils.Migrations.simple_10)
|
|
Storage.active.userDefaults.lastEngineVersion = nil
|
|
Migrations.updateResources(storage: Storage.active)
|
|
|
|
let userDefaults = Storage.active.userDefaults
|
|
|
|
// The old keyboard should be gone entirely, replaced by the current version's default resources.
|
|
// There should only be one default resource per type (at least, as of 13.0.)
|
|
XCTAssertEqual(userDefaults.userKeyboards!.count, 1, "Unexpected keyboard count after migration!")
|
|
// 3, b/c all language-code variants are counted.
|
|
XCTAssertEqual(userDefaults.userLexicalModels!.count, 3, "Unexpected lexical model count after migration!")
|
|
|
|
let defaultKeyboard = userDefaults.userKeyboards![0]
|
|
XCTAssertNotEqual(TestUtils.Migrations.european2.id, defaultKeyboard.id) // Double-ensure that the ID is new.
|
|
XCTAssertEqual(defaultKeyboard.id, Defaults.keyboard.id)
|
|
XCTAssertEqual(defaultKeyboard.version, Defaults.keyboard.version)
|
|
|
|
let defaultModel = userDefaults.userLexicalModels![0]
|
|
XCTAssertEqual(defaultModel.id, Defaults.lexicalModel.id)
|
|
XCTAssertEqual(defaultModel.version, Defaults.lexicalModel.version)
|
|
|
|
let keyboardURL = Storage.active.keyboardURL(for: Defaults.keyboard)
|
|
let modelURL = Storage.active.lexicalModelURL(for: Defaults.lexicalModel)
|
|
XCTAssert(FileManager.default.fileExists(atPath: keyboardURL.path))
|
|
XCTAssert(FileManager.default.fileExists(atPath: modelURL.path))
|
|
}
|
|
|
|
func testNoDefaultVersion10ResourceMigration() {
|
|
TestUtils.Migrations.applyBundleToFileSystem(TestUtils.Migrations.noDefault_10)
|
|
Migrations.updateResources(storage: Storage.active)
|
|
|
|
Storage.active.userDefaults.lastEngineVersion = nil
|
|
let userDefaults = Storage.active.userDefaults
|
|
|
|
// No new resources should be installed - only what was originally present should be there.
|
|
XCTAssertEqual(userDefaults.userKeyboards!.count, 1, "Unexpected keyboard count after migration!")
|
|
// There was no prior lexical model installed, so the installation still proceeds. The user just won't see it.
|
|
XCTAssertNil(userDefaults.userLexicalModels, "Unexpected lexical model(s) installed after migration!")
|
|
|
|
let keyboard = userDefaults.userKeyboards![0]
|
|
XCTAssertEqual(keyboard.id, TestUtils.Keyboards.khmer_angkor.id, "Unexpected keyboard was installed after migration!")
|
|
XCTAssertEqual(keyboard.version, TestUtils.Keyboards.khmer_angkor.version)
|
|
|
|
// If successful, confirms that the current default resources are not installed - as expected.
|
|
}
|
|
}
|