mirror of
https://github.com/keymanapp/keyman.git
synced 2026-08-06 00:45:32 +00:00
360 lines
15 KiB
Swift
360 lines
15 KiB
Swift
//
|
|
// ResourceDownloadManagerTests.swift
|
|
// KeymanEngineTests
|
|
//
|
|
// Created by Joshua Horton on 6/29/20.
|
|
// Copyright © 2020 SIL International. All rights reserved.
|
|
//
|
|
|
|
import XCTest
|
|
@testable import KeymanEngine
|
|
|
|
class ResourceDownloadManagerTests: XCTestCase {
|
|
var mockedURLSession: TestUtils.Downloading.URLSessionMock?
|
|
var downloadManager: ResourceDownloadManager?
|
|
|
|
override func setUp() {
|
|
mockedURLSession = TestUtils.Downloading.URLSessionMock()
|
|
downloadManager = ResourceDownloadManager(session: mockedURLSession!, autoExecute: false)
|
|
}
|
|
|
|
override func tearDownWithError() throws {
|
|
// Resets resource directories for a clean slate.
|
|
TestUtils.standardTearDown()
|
|
|
|
let queueWasCleared = mockedURLSession!.queueIsEmpty
|
|
mockedURLSession = nil
|
|
|
|
if !queueWasCleared {
|
|
throw NSError(domain: "Keyman",
|
|
code: 4,
|
|
userInfo: [NSLocalizedDescriptionKey: "A test did not fully utilize its queued mock results!"])
|
|
}
|
|
}
|
|
|
|
func testDefaultKeyboardDownloadURL() {
|
|
let tier = Version.currentTagged.tier ?? .stable
|
|
let root = "/go/package/download"
|
|
|
|
let basic_khmer_angkor_components = URLComponents(string: downloadManager!.defaultDownloadURL(forPackage: TestUtils.Packages.Keys.khmer_angkor).absoluteString)!
|
|
|
|
XCTAssertEqual(basic_khmer_angkor_components.path, "\(root)/khmer_angkor")
|
|
XCTAssertTrue(basic_khmer_angkor_components.queryItems!.contains { item in
|
|
return item.name == "platform" && item.value == "ios"
|
|
})
|
|
XCTAssertTrue(basic_khmer_angkor_components.queryItems!.contains { item in
|
|
return item.name == "tier" && item.value == tier.rawValue
|
|
})
|
|
XCTAssertTrue(basic_khmer_angkor_components.queryItems!.contains { item in
|
|
return item.name == "type" && item.value == "keyboard"
|
|
})
|
|
|
|
let adv_khmer_angkor_url = downloadManager!.defaultDownloadURL(forPackage: TestUtils.Packages.Keys.khmer_angkor, andResource: TestUtils.Keyboards.khmer_angkor.fullID, withVersion: Version("1.0.6"), asUpdate: true)
|
|
let adv_khmer_angkor_components = URLComponents(string: adv_khmer_angkor_url.absoluteString)!
|
|
XCTAssertEqual(adv_khmer_angkor_components.path, "\(root)/khmer_angkor")
|
|
XCTAssertTrue(adv_khmer_angkor_components.queryItems!.contains { item in
|
|
return item.name == "platform" && item.value == "ios"
|
|
})
|
|
XCTAssertTrue(adv_khmer_angkor_components.queryItems!.contains { item in
|
|
return item.name == "tier" && item.value == tier.rawValue
|
|
})
|
|
XCTAssertTrue(adv_khmer_angkor_components.queryItems!.contains { item in
|
|
return item.name == "type" && item.value == "keyboard"
|
|
})
|
|
XCTAssertTrue(adv_khmer_angkor_components.queryItems!.contains { item in
|
|
return item.name == "update" && item.value == "1"
|
|
})
|
|
XCTAssertTrue(adv_khmer_angkor_components.queryItems!.contains { item in
|
|
return item.name == "version" && item.value == "1.0.6"
|
|
})
|
|
XCTAssertTrue(adv_khmer_angkor_components.queryItems!.contains { item in
|
|
return item.name == "bcp47" && item.value == "km"
|
|
})
|
|
}
|
|
|
|
func testDefaultLexicalModelDownloadURL() {
|
|
let tier = Version.currentTagged.tier ?? .stable
|
|
let root = "/go/package/download"
|
|
|
|
let basic_mtnt_components = URLComponents(string: downloadManager!.defaultDownloadURL(forPackage: TestUtils.Packages.Keys.nrc_en_mtnt).absoluteString)!
|
|
|
|
XCTAssertEqual(basic_mtnt_components.path, "\(root)/nrc.en.mtnt")
|
|
XCTAssertTrue(basic_mtnt_components.queryItems!.contains { item in
|
|
return item.name == "platform" && item.value == "ios"
|
|
})
|
|
XCTAssertTrue(basic_mtnt_components.queryItems!.contains { item in
|
|
return item.name == "tier" && item.value == tier.rawValue
|
|
})
|
|
XCTAssertTrue(basic_mtnt_components.queryItems!.contains { item in
|
|
return item.name == "type" && item.value == "model"
|
|
})
|
|
|
|
let adv_mtnt_url = downloadManager!.defaultDownloadURL(forPackage: TestUtils.Packages.Keys.nrc_en_mtnt, andResource: TestUtils.LexicalModels.mtnt.fullID, withVersion: Version(TestUtils.LexicalModels.mtnt.version), asUpdate: true)
|
|
let adv_mtnt_components = URLComponents(string: adv_mtnt_url.absoluteString)!
|
|
XCTAssertEqual(adv_mtnt_components.path, "\(root)/nrc.en.mtnt")
|
|
XCTAssertTrue(adv_mtnt_components.queryItems!.contains { item in
|
|
return item.name == "platform" && item.value == "ios"
|
|
})
|
|
XCTAssertTrue(adv_mtnt_components.queryItems!.contains { item in
|
|
return item.name == "tier" && item.value == tier.rawValue
|
|
})
|
|
XCTAssertTrue(adv_mtnt_components.queryItems!.contains { item in
|
|
return item.name == "type" && item.value == "model"
|
|
})
|
|
XCTAssertTrue(adv_mtnt_components.queryItems!.contains { item in
|
|
return item.name == "update" && item.value == "1"
|
|
})
|
|
XCTAssertTrue(adv_mtnt_components.queryItems!.contains { item in
|
|
return item.name == "version" && item.value == TestUtils.LexicalModels.mtnt.version
|
|
})
|
|
XCTAssertTrue(adv_mtnt_components.queryItems!.contains { item in
|
|
return item.name == "bcp47" && item.value == "en"
|
|
})
|
|
}
|
|
|
|
func testDownloadPackageForKeyboard() throws {
|
|
let expectation = XCTestExpectation(description: "Mocked \"download\" should complete successfully.")
|
|
let packageKey = TestUtils.Keyboards.khmer_angkor.packageKey
|
|
|
|
let mockedResult = TestUtils.Downloading.MockResult(location: TestUtils.Keyboards.khmerAngkorKMP, error: nil)
|
|
mockedURLSession?.queueMockResult(.download(mockedResult))
|
|
|
|
downloadManager?.downloadPackage(withKey: packageKey, from: TestUtils.Keyboards.khmerAngkorKMP, withNotifications: false) { (package: KeyboardKeymanPackage?, error: Error?) in
|
|
|
|
let tempDownloadKMP = ResourceFileManager.shared.packageDownloadTempPath(forKey: packageKey)
|
|
XCTAssertFalse(FileManager.default.fileExists(atPath: tempDownloadKMP.path))
|
|
|
|
// Assertions: a copy of the KMP file exists in the documents directory, facilitating user sharing.
|
|
let cachedDocumentsKMP = ResourceFileManager.shared.cachedPackagePath(forKey: packageKey)
|
|
|
|
XCTAssertTrue(FileManager.default.fileExists(atPath: cachedDocumentsKMP.path))
|
|
|
|
XCTAssertNil(error)
|
|
XCTAssertNotNil(package)
|
|
|
|
// Basic verification that it really is the khmer_angkor keyboard package.
|
|
if let package = package {
|
|
XCTAssertEqual(package.id, TestUtils.Keyboards.khmer_angkor.id)
|
|
XCTAssertNotNil(package.findResource(withID: TestUtils.Keyboards.khmer_angkor.fullID))
|
|
}
|
|
|
|
expectation.fulfill()
|
|
}
|
|
|
|
let downloadQueue = downloadManager!.downloader
|
|
downloadQueue.step()
|
|
|
|
wait(for: [expectation], timeout: 5)
|
|
}
|
|
|
|
func testDownloadPackageForLexicalModel() throws {
|
|
let expectation = XCTestExpectation(description: "Mocked \"download\" should complete successfully.")
|
|
let packageKey = TestUtils.LexicalModels.mtnt.packageKey
|
|
|
|
let mockedResult = TestUtils.Downloading.MockResult(location: TestUtils.LexicalModels.mtntKMP, error: nil)
|
|
mockedURLSession?.queueMockResult(.download(mockedResult))
|
|
|
|
downloadManager?.downloadPackage(withKey: packageKey, from: TestUtils.LexicalModels.mtntKMP, withNotifications: false) { (package: LexicalModelKeymanPackage?, error: Error?) in
|
|
let tempDownloadKMP = ResourceFileManager.shared.packageDownloadTempPath(forKey: packageKey)
|
|
XCTAssertFalse(FileManager.default.fileExists(atPath: tempDownloadKMP.path))
|
|
|
|
// Assertion: a copy of the KMP file exists in the documents directory, facilitating user sharing.
|
|
let cachedDocumentsKMP = ResourceFileManager.shared.cachedPackagePath(forKey: packageKey)
|
|
|
|
XCTAssertTrue(FileManager.default.fileExists(atPath: cachedDocumentsKMP.path))
|
|
|
|
XCTAssertNil(error)
|
|
XCTAssertNotNil(package)
|
|
|
|
// Basic verification that it really is the khmer_angkor keyboard package.
|
|
if let package = package {
|
|
XCTAssertEqual(package.id, TestUtils.LexicalModels.mtnt.id)
|
|
XCTAssertNotNil(package.findResource(withID: TestUtils.LexicalModels.mtnt.fullID))
|
|
}
|
|
|
|
expectation.fulfill()
|
|
}
|
|
|
|
let downloadQueue = downloadManager!.downloader
|
|
downloadQueue.step()
|
|
|
|
wait(for: [expectation], timeout: 5)
|
|
}
|
|
|
|
func testDownloadPackageFailure() throws {
|
|
let expectation = XCTestExpectation(description: "Mocked \"download\" should complete, though with an error.")
|
|
let packageKey = TestUtils.Keyboards.khmer_angkor.packageKey
|
|
|
|
let mockedResult = TestUtils.Downloading.MockResult(location: TestUtils.Keyboards.khmerAngkorKMP, error: TestUtils.mockedError)
|
|
mockedURLSession?.queueMockResult(.download(mockedResult))
|
|
|
|
downloadManager?.downloadPackage(withKey: packageKey, from: TestUtils.Keyboards.khmerAngkorKMP, withNotifications: false) { package, error in
|
|
|
|
let tempDownloadKMP = ResourceFileManager.shared.packageDownloadTempPath(forKey: packageKey)
|
|
XCTAssertFalse(FileManager.default.fileExists(atPath: tempDownloadKMP.path))
|
|
|
|
// Assertion: a copy of the KMP file exists in the documents directory, facilitating user sharing.
|
|
let cachedDocumentsKMP = ResourceFileManager.shared.cachedPackagePath(forKey: packageKey)
|
|
|
|
// On download failure, we shouldn't be producing a file here.
|
|
XCTAssertFalse(FileManager.default.fileExists(atPath: cachedDocumentsKMP.path))
|
|
|
|
XCTAssertNotNil(error)
|
|
XCTAssertNil(package)
|
|
|
|
expectation.fulfill()
|
|
}
|
|
|
|
let downloadQueue = downloadManager!.downloader
|
|
downloadQueue.step()
|
|
|
|
wait(for: [expectation], timeout: 5)
|
|
}
|
|
|
|
func testLegacyDownloadKeyboard() throws {
|
|
let expectation = XCTestExpectation(description: "Mocked package \"download\" should complete successfully.")
|
|
|
|
// For this test, we actually want the downloader to run automatically. It's... a bit tricky to
|
|
// run this integration test otherwise.
|
|
downloadManager = ResourceDownloadManager(session: mockedURLSession!, autoExecute: true)
|
|
|
|
let mockedDownload = TestUtils.Downloading.MockResult(location: TestUtils.Keyboards.khmerAngkorKMP, error: nil)
|
|
|
|
mockedURLSession?.queueMockResult(.download(mockedDownload))
|
|
|
|
let khmer_angkor_id = TestUtils.Keyboards.khmer_angkor.fullID
|
|
|
|
downloadManager?.downloadKeyboard(withID: khmer_angkor_id.id, languageID: khmer_angkor_id.languageID, isUpdate: false, fetchRepositoryIfNeeded: false) { package, error in
|
|
if let error = error {
|
|
XCTFail("Mocked query and download should both succeed; reported error: \(error.localizedDescription)")
|
|
} else if let package = package {
|
|
// Double-check it!
|
|
XCTAssertEqual(package.id, "khmer_angkor")
|
|
XCTAssertNotNil(package.findResource(withID: khmer_angkor_id))
|
|
}
|
|
|
|
expectation.fulfill()
|
|
}
|
|
|
|
wait(for: [expectation], timeout: 5)
|
|
}
|
|
|
|
func testLegacyDownloadLexicalModel() throws {
|
|
let expectation = XCTestExpectation(description: "Mocked package \"download\" should complete successfully.")
|
|
|
|
// For this test, we actually want the downloader to run automatically. It's... a bit tricky to
|
|
// run this integration test otherwise.
|
|
downloadManager = ResourceDownloadManager(session: mockedURLSession!, autoExecute: true)
|
|
|
|
let mockedDownload = TestUtils.Downloading.MockResult(location: TestUtils.LexicalModels.mtntKMP, error: nil)
|
|
|
|
mockedURLSession?.queueMockResult(.download(mockedDownload))
|
|
|
|
let mtnt_id = TestUtils.LexicalModels.mtnt.fullID
|
|
|
|
downloadManager?.downloadLexicalModel(withID: mtnt_id.id, languageID: mtnt_id.languageID, isUpdate: false, fetchRepositoryIfNeeded: false) { package, error in
|
|
if let error = error {
|
|
XCTFail("Mocked query and download should both succeed; reported error: \(error.localizedDescription)")
|
|
} else if let package = package {
|
|
// Double-check it!
|
|
XCTAssertEqual(package.id, "nrc.en.mtnt")
|
|
XCTAssertNotNil(package.findResource(withID: mtnt_id))
|
|
}
|
|
|
|
expectation.fulfill()
|
|
}
|
|
|
|
wait(for: [expectation], timeout: 5)
|
|
}
|
|
|
|
// This annotation prevents local deprecation warnings for what it tests.
|
|
@available(*, deprecated, message: "This method tests the deprecated ResourceDownloadManager.stateForKeyboard.")
|
|
func testStateForKeyboard() {
|
|
let baseInstallation = XCTestExpectation(description: "Mocked \"download\" should complete successfully.")
|
|
let khmer_angkor_id = TestUtils.Keyboards.khmer_angkor.fullID
|
|
let packageKey = TestUtils.Keyboards.khmer_angkor.packageKey
|
|
|
|
let mockedResult = TestUtils.Downloading.MockResult(location: TestUtils.Keyboards.khmerAngkorKMP, error: nil)
|
|
mockedURLSession?.queueMockResult(.download(mockedResult))
|
|
|
|
XCTAssertEqual(downloadManager!.stateForKeyboard(withID: khmer_angkor_id.id), .needsDownload)
|
|
|
|
downloadManager!.downloadPackage(withKey: packageKey,
|
|
from: TestUtils.Keyboards.khmerAngkorKMP,
|
|
withNotifications: false) { (package: KeyboardKeymanPackage?, error) in
|
|
if let _ = error {
|
|
XCTFail()
|
|
baseInstallation.fulfill()
|
|
return
|
|
} else if let package = package {
|
|
do {
|
|
try ResourceFileManager.shared.install(resourceWithID: khmer_angkor_id, from: package)
|
|
baseInstallation.fulfill()
|
|
} catch {
|
|
XCTFail()
|
|
baseInstallation.fulfill()
|
|
}
|
|
}
|
|
}
|
|
|
|
XCTAssertEqual(downloadManager!.stateForKeyboard(withID: khmer_angkor_id.id), .downloading)
|
|
|
|
downloadManager!.downloader.step()
|
|
|
|
wait(for: [baseInstallation], timeout: 5)
|
|
|
|
XCTAssertEqual(downloadManager!.stateForKeyboard(withID: khmer_angkor_id.id), .upToDate)
|
|
|
|
// Now, to test the update-check part of the function...
|
|
// This fixture was hand-altered. At the time of this test's creation, this version did not exist.
|
|
let mockedQuery = TestUtils.Downloading.MockResult(location: TestUtils.Queries.package_version_km_updated, error: nil)
|
|
mockedURLSession?.queueMockResult(.data(mockedQuery))
|
|
|
|
let versionQuery = XCTestExpectation()
|
|
|
|
// Now to do a package-version check.
|
|
KeymanPackage.queryCurrentVersions(for: [KeymanPackage.Key(id: khmer_angkor_id.id, type: .keyboard)], withSession: downloadManager!.session) { result, _ in
|
|
XCTAssertEqual(self.downloadManager!.stateForKeyboard(withID: khmer_angkor_id.id), .needsUpdate)
|
|
versionQuery.fulfill()
|
|
}
|
|
|
|
wait(for: [versionQuery], timeout: 5)
|
|
}
|
|
|
|
public func testDefaultLexicalModelForLanguage() {
|
|
let mockedQueryWithModel = TestUtils.Downloading.MockResult(location: TestUtils.Queries.model_case_en, error: nil)
|
|
let mockedModelDownload = TestUtils.Downloading.MockResult(location: TestUtils.LexicalModels.mtntKMP, error: nil)
|
|
let mockedQueryWithoutModel = TestUtils.Downloading.MockResult(location: TestUtils.Queries.model_case_km, error: nil)
|
|
mockedURLSession?.queueMockResult(.data(mockedQueryWithModel))
|
|
mockedURLSession?.queueMockResult(.download(mockedModelDownload))
|
|
mockedURLSession?.queueMockResult(.data(mockedQueryWithoutModel))
|
|
|
|
let foundExpectation = XCTestExpectation()
|
|
let noneExpectation = XCTestExpectation()
|
|
|
|
downloadManager?.downloader.autoExecute = true
|
|
downloadManager?.downloadLexicalModelsForLanguageIfExists(languageID: "en") { package, error in
|
|
if error != nil {
|
|
XCTFail()
|
|
}
|
|
|
|
XCTAssertNotNil(package)
|
|
|
|
foundExpectation.fulfill()
|
|
}
|
|
|
|
wait(for: [foundExpectation], timeout: 5)
|
|
|
|
downloadManager?.downloadLexicalModelsForLanguageIfExists(languageID: "km") { package, error in
|
|
if error != nil {
|
|
XCTFail()
|
|
}
|
|
|
|
XCTAssertNil(package)
|
|
|
|
noneExpectation.fulfill()
|
|
}
|
|
|
|
wait(for: [noneExpectation], timeout: 5)
|
|
}
|
|
}
|