185 lines
5.9 KiB
Swift
185 lines
5.9 KiB
Swift
import PromiseKit
|
|
@testable import Shared
|
|
import XCTest
|
|
|
|
struct TestObject1: Codable, Equatable {
|
|
var uuid1 = UUID()
|
|
}
|
|
|
|
struct TestObject2: Codable, Equatable {
|
|
var uuid2 = UUID()
|
|
}
|
|
|
|
struct DoubleObject1: Codable, Equatable {
|
|
var value: Double
|
|
}
|
|
|
|
class DiskCacheTests: XCTestCase {
|
|
var cache: DiskCacheImpl!
|
|
|
|
override func setUp() {
|
|
super.setUp()
|
|
cache = DiskCacheImpl(containerName: "UnitTests_\(UUID().uuidString)")
|
|
}
|
|
|
|
func testReadNothing() {
|
|
XCTAssertThrowsError(try hang(cache.value(for: "missing_value")) as TestObject1)
|
|
XCTAssertThrowsError(try hang(cache.value(for: "missing_value2")) as TestObject2)
|
|
XCTAssertThrowsError(try hang(cache.value(for: "missing_value2")) as TestObject1)
|
|
}
|
|
|
|
func testReadAfterWrite() {
|
|
let obj1 = TestObject1()
|
|
let obj2 = TestObject1()
|
|
let obj3 = TestObject1()
|
|
|
|
let cache: DiskCache = cache
|
|
let key = "key"
|
|
|
|
let write1 = cache.set(obj1, for: key)
|
|
let read1 = write1.then { cache.value(for: key) as Promise<TestObject1> }
|
|
let write2 = read1.then { _ in cache.set(obj2, for: key) }
|
|
let read2 = write2.then { cache.value(for: key) as Promise<TestObject1> }
|
|
let write3 = read2.then { _ in cache.set(obj3, for: key) }
|
|
let read3 = write3.then { cache.value(for: key) as Promise<TestObject1> }
|
|
|
|
XCTAssertNoThrow(try hang(write1))
|
|
XCTAssertEqual(try hang(read1), obj1)
|
|
|
|
XCTAssertNoThrow(try hang(write2))
|
|
XCTAssertEqual(try hang(read2), obj2)
|
|
|
|
XCTAssertNoThrow(try hang(write3))
|
|
XCTAssertEqual(try hang(read3), obj3)
|
|
}
|
|
|
|
func testInterleaveObjectType() {
|
|
let obj1 = TestObject1()
|
|
let obj2 = TestObject2()
|
|
let obj3 = TestObject1()
|
|
|
|
let cache: DiskCache = cache
|
|
let key = "key"
|
|
|
|
let write1 = cache.set(obj1, for: key)
|
|
let read1 = write1.then { cache.value(for: key) as Promise<TestObject1> }
|
|
let write2 = read1.then { _ in cache.set(obj2, for: key) }
|
|
let read2a = write2.then { cache.value(for: key) as Promise<TestObject1> }
|
|
let read2b = when(resolved: read2a).then { _ in cache.value(for: key) as Promise<TestObject2> }
|
|
let write3 = read2b.then { _ in cache.set(obj3, for: key) }
|
|
let read3 = write3.then { cache.value(for: key) as Promise<TestObject1> }
|
|
|
|
XCTAssertNoThrow(try hang(write1))
|
|
XCTAssertEqual(try hang(read1), obj1)
|
|
|
|
XCTAssertNoThrow(try hang(write2))
|
|
XCTAssertThrowsError(try hang(read2a))
|
|
XCTAssertEqual(try hang(read2b), obj2)
|
|
|
|
XCTAssertNoThrow(try hang(write3))
|
|
XCTAssertEqual(try hang(read3), obj3)
|
|
}
|
|
|
|
func testMultipleKeys() {
|
|
let obj1 = TestObject1()
|
|
let obj2 = TestObject2()
|
|
let obj3 = TestObject1()
|
|
let obj4 = TestObject2()
|
|
|
|
let cache: DiskCache = cache
|
|
|
|
let write1 = cache.set(obj1, for: "obj1")
|
|
let write2 = cache.set(obj2, for: "obj2")
|
|
let write3 = cache.set(obj3, for: "obj3")
|
|
let write4 = cache.set(obj4, for: "obj4")
|
|
|
|
let read1 = write1.then { cache.value(for: "obj1") as Promise<TestObject1> }
|
|
let read2 = write2.then { cache.value(for: "obj2") as Promise<TestObject2> }
|
|
let read3 = write3.then { cache.value(for: "obj3") as Promise<TestObject1> }
|
|
let read4 = write4.then { cache.value(for: "obj4") as Promise<TestObject2> }
|
|
|
|
XCTAssertEqual(try hang(read1), obj1)
|
|
XCTAssertEqual(try hang(read2), obj2)
|
|
XCTAssertEqual(try hang(read3), obj3)
|
|
XCTAssertEqual(try hang(read4), obj4)
|
|
}
|
|
|
|
func testJsonEncoderFail() {
|
|
let obj1 = DoubleObject1(value: 3)
|
|
let obj2 = DoubleObject1(value: .infinity)
|
|
|
|
let cache: DiskCache = cache
|
|
|
|
let write1 = cache.set(obj1, for: "obj1/")
|
|
let read1 = write1.then { cache.value(for: "obj1/") as Promise<DoubleObject1> }
|
|
|
|
let write2 = cache.set(obj2, for: "obj2")
|
|
let read2 = when(resolved: write2).then { _ in cache.value(for: "obj2") as Promise<DoubleObject1> }
|
|
|
|
XCTAssertEqual(try hang(read1), obj1)
|
|
XCTAssertThrowsError(try hang(write2))
|
|
XCTAssertThrowsError(try hang(read2))
|
|
}
|
|
|
|
func testInvalidFileNameKey() {
|
|
let obj1 = TestObject1()
|
|
let cache: DiskCache = cache
|
|
|
|
let write1 = cache.set(obj1, for: "a//")
|
|
let read1 = write1.then { cache.value(for: "a//") as Promise<TestObject1> }
|
|
XCTAssertEqual(try hang(read1), obj1)
|
|
}
|
|
|
|
func testWriteFailure() {
|
|
let obj1 = TestObject1()
|
|
|
|
cache.container = URL(fileURLWithPath: "/dev/null")
|
|
|
|
let write1 = cache.set(obj1, for: "key")
|
|
XCTAssertThrowsError(try hang(write1))
|
|
}
|
|
|
|
func testCoordinatorError() {
|
|
let obj1 = TestObject1()
|
|
|
|
let cache: DiskCacheImpl = cache
|
|
|
|
// uses a fake coordinator because presenters do not work in the simulator
|
|
cache.coordinator = FailingNSFileCoordinator()
|
|
|
|
let write1 = cache.set(obj1, for: "key")
|
|
let read1 = when(resolved: write1).then { _ in cache.value(for: "key") as Promise<TestObject1> }
|
|
|
|
XCTAssertThrowsError(try hang(write1))
|
|
XCTAssertThrowsError(try hang(read1))
|
|
}
|
|
}
|
|
|
|
class FailingNSFileCoordinator: NSFileCoordinator {
|
|
enum TestError: Error {
|
|
case any
|
|
}
|
|
|
|
init() {
|
|
super.init(filePresenter: nil)
|
|
}
|
|
|
|
override func coordinate(
|
|
readingItemAt url: URL,
|
|
options: NSFileCoordinator.ReadingOptions = [],
|
|
error outError: NSErrorPointer,
|
|
byAccessor reader: (URL) -> Void
|
|
) {
|
|
outError?.pointee = TestError.any as NSError
|
|
}
|
|
|
|
override func coordinate(
|
|
writingItemAt url: URL,
|
|
options: NSFileCoordinator.WritingOptions = [],
|
|
error outError: NSErrorPointer,
|
|
byAccessor writer: (URL) -> Void
|
|
) {
|
|
outError?.pointee = TestError.any as NSError
|
|
}
|
|
}
|