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

144 lines
6 KiB
Swift

//
// HTTPDownloaderTests.swift
// KeymanEngineTests
//
// Created by Joshua Horton on 5/27/20.
// Copyright © 2020 SIL International. All rights reserved.
//
import XCTest
@testable import KeymanEngine
class HTTPDownloaderTests: XCTestCase {
var downloader: HTTPDownloader?
var mockedURLSession: TestUtils.Downloading.URLSessionMock?
override func setUp() {
mockedURLSession = TestUtils.Downloading.URLSessionMock()
downloader = HTTPDownloader(nil, session: mockedURLSession!)
}
override func tearDownWithError() throws {
let queueWasCleared = mockedURLSession!.queueIsEmpty
mockedURLSession = nil
downloader = nil
if !queueWasCleared {
throw NSError(domain: "Keyman",
code: 4,
userInfo: [NSLocalizedDescriptionKey: "A test did not fully utilize its queued mock results!"])
}
}
func testSingleRequestSuccess() throws {
// Simple, easy case: our local testing copy of the Khmer Angkor KMP file.
let mockedResult = TestUtils.Downloading.MockResult(location: TestUtils.Keyboards.khmerAngkorKMP, error: nil)
mockedURLSession?.queueMockResult(.download(mockedResult))
let testDelegate = TestUtils.Downloading.ExpectationDownloaderDelegate()
downloader!.handler = testDelegate
let request = HTTPDownloadRequest(url: TestUtils.Keyboards.khmerAngkorKMP)
downloader!.addRequest(request)
testDelegate.expect(method: .RequestStarted, request: request)
testDelegate.expect(method: .RequestFinished, request: request)
testDelegate.expect(method: .QueueFinished, queue: downloader!)
XCTAssertEqual(downloader!.requestsCount, 1)
downloader!.run()
testDelegate.sequentialWait(testCase: self, timeout: 10)
}
func testSingleRequestFailure() throws {
// A twist on the previous version - the 'download' fails.
let mockedResult = TestUtils.Downloading.MockResult(location: TestUtils.Keyboards.khmerAngkorKMP, error: TestUtils.mockedError)
mockedURLSession?.queueMockResult(.download(mockedResult))
let testDelegate = TestUtils.Downloading.ExpectationDownloaderDelegate()
downloader!.handler = testDelegate
let request = HTTPDownloadRequest(url: TestUtils.Keyboards.khmerAngkorKMP)
downloader!.addRequest(request)
testDelegate.expect(method: .RequestStarted, request: request)
testDelegate.expect(method: .RequestFailed, request: request)
testDelegate.expect(method: .QueueFinished, queue: downloader!)
XCTAssertEqual(downloader!.requestsCount, 1)
downloader!.run()
testDelegate.sequentialWait(testCase: self, timeout: 10)
}
func testSequentialRequests() {
let mockedResult1 = TestUtils.Downloading.MockResult(location: TestUtils.Keyboards.khmerAngkorKMP, error: nil)
mockedURLSession?.queueMockResult(.download(mockedResult1))
let mockedResult2 = TestUtils.Downloading.MockResult(location:
TestUtils.LexicalModels.mtntKMP, error: nil)
mockedURLSession?.queueMockResult(.download(mockedResult2))
let testDelegate = TestUtils.Downloading.ExpectationDownloaderDelegate()
downloader!.handler = testDelegate
let request1 = HTTPDownloadRequest(url: TestUtils.Keyboards.khmerAngkorKMP)
downloader!.addRequest(request1)
testDelegate.expect(method: .RequestStarted, request: request1)
testDelegate.expect(method: .RequestFinished, request: request1)
let request2 = HTTPDownloadRequest(url: TestUtils.LexicalModels.mtntKMP)
downloader!.addRequest(request2)
testDelegate.expect(method: .RequestStarted, request: request2)
testDelegate.expect(method: .RequestFinished, request: request2)
testDelegate.expect(method: .QueueFinished, queue: downloader!)
XCTAssertEqual(downloader!.requestsCount, 2)
downloader!.run()
// This is currently safe, as all downloads are sequential. If we ever
// enable parallel downloads, this will obviously need to change
testDelegate.sequentialWait(testCase: self, timeout: 10)
}
func testRequestCancellation() {
let mockedResult1 = TestUtils.Downloading.MockResult(location: TestUtils.Keyboards.khmerAngkorKMP, error: nil)
mockedURLSession?.queueMockResult(.download(mockedResult1))
// No second mocked result - its call should be cancelled.
let testDelegate = TestUtils.Downloading.ExpectationDownloaderDelegate()
downloader!.handler = testDelegate
let request1 = HTTPDownloadRequest(url: TestUtils.Keyboards.khmerAngkorKMP)
downloader!.addRequest(request1)
testDelegate.expect(method: .RequestStarted, request: request1)
let request2 = HTTPDownloadRequest(url: TestUtils.LexicalModels.mtntKMP)
downloader!.addRequest(request2)
testDelegate.expectAbsence(method: .RequestStarted, request: request2)
testDelegate.expectAbsence(method: .RequestFinished, request: request2)
testDelegate.expect(method: .QueueCancelled, queue: downloader!)
testDelegate.expectAbsence(method: .QueueFinished, queue: downloader!)
// Placed here for chronological ordering. We expect the request to finish because of
// our mocking structure, but want to delay its completion long enough for the
// `cancelAllOperations` call below to complete.
testDelegate.expect(method: .RequestFinished, request: request1, completion: { response in
// Force a delay so that our `cancelAllOperations` call has a chance to execute;
// our mocking structure is otherwise synchronous!
sleep(1) // in seconds.
response.expectation.fulfill()
return false
})
// Ideally, we could add this... but because of how things are currently mocked,
// it actually does trigger - we have a .RequestFinished processing after .QueueCancelled,
// which then notes the empty queue.
//
// testDelegate.expectAbsence(method: .QueueFinished, queue: downloader!)
XCTAssertEqual(downloader!.requestsCount, 2)
downloader!.run()
downloader!.cancelAllOperations()
// This is currently safe, as all downloads are sequential. If we ever
// enable parallel downloads, this will obviously need to change
testDelegate.sequentialWait(testCase: self, timeout: 5)
}
}