661 lines
24 KiB
Swift
661 lines
24 KiB
Swift
@testable import Shared
|
|
import Version
|
|
import XCTest
|
|
|
|
class ServerManagerTests: XCTestCase {
|
|
private var encoder: JSONEncoder!
|
|
private var keychain: FakeServerManagerKeychain!
|
|
private var historicKeychain: FakeServerManagerKeychain!
|
|
private var servers: ServerManagerImpl!
|
|
|
|
override func setUp() {
|
|
super.setUp()
|
|
|
|
encoder = .init()
|
|
keychain = .init()
|
|
historicKeychain = .init()
|
|
|
|
Current.settingsStore.prefs.removeObject(forKey: "deletedServers")
|
|
}
|
|
|
|
private func setupRegular(
|
|
_ serverInfos: [String: ServerInfo] = [:]
|
|
) throws {
|
|
for (key, value) in serverInfos {
|
|
try keychain.set(encoder.encode(value), key: key)
|
|
}
|
|
|
|
servers = ServerManagerImpl(keychain: keychain, historicKeychain: historicKeychain)
|
|
servers.setup()
|
|
}
|
|
|
|
func testInitiallyEmptyAndGainingServersWithCaching() throws {
|
|
Current.isAppExtension = false
|
|
try base_testInitiallyEmptyAndGainingServers()
|
|
}
|
|
|
|
func testInitiallyEmptyAndGainingServersWithoutCaching() throws {
|
|
Current.isAppExtension = true
|
|
try base_testInitiallyEmptyAndGainingServers()
|
|
}
|
|
|
|
private func base_testInitiallyEmptyAndGainingServers() throws {
|
|
try setupRegular()
|
|
|
|
let observer = FakeObserver()
|
|
|
|
func expectingObserver(_ block: () -> Void) {
|
|
let expectation = observer.addExpectation(from: self)
|
|
block()
|
|
wait(for: [expectation], timeout: 10.0)
|
|
}
|
|
|
|
servers.add(observer: observer)
|
|
|
|
XCTAssertEqual(servers.all.count, 0)
|
|
|
|
XCTAssertNil(servers.server(for: "fake1"))
|
|
XCTAssertNil(servers.server(forServerIdentifier: "fake1"))
|
|
XCTAssertNil(servers.server(forWebhookID: "fake1"))
|
|
XCTAssertNil(servers.server(for: FakeServerIdentifierProviding(serverIdentifier: "fake1")))
|
|
XCTAssertNil(servers.server(for: FakeServerIdentifierProviding(serverIdentifier: "fake1"), fallback: false))
|
|
|
|
let state = servers.restorableState()
|
|
XCTAssertEqual(String(decoding: state, as: UTF8.self), "{}")
|
|
|
|
expectingObserver {
|
|
servers.restoreState(state)
|
|
}
|
|
XCTAssertEqual(servers.all.count, 0)
|
|
XCTAssertTrue(keychain.data.isEmpty)
|
|
|
|
let info1 = with(ServerInfo.fake()) {
|
|
$0.connection.webhookID = "webhook1"
|
|
}
|
|
|
|
let info2 = with(ServerInfo.fake()) {
|
|
$0.connection.webhookID = "webhook2"
|
|
}
|
|
|
|
let info3 = with(ServerInfo.fake()) {
|
|
$0.connection.webhookID = "webhook3"
|
|
}
|
|
|
|
expectingObserver {
|
|
servers.add(identifier: "fake1", serverInfo: info1)
|
|
}
|
|
|
|
let server1 = try XCTUnwrap(servers.server(for: "fake1"))
|
|
|
|
XCTAssertTrue(servers.server(forWebhookID: "webhook1") === server1)
|
|
XCTAssertTrue(servers.server(forServerIdentifier: "fake1") === server1)
|
|
XCTAssertTrue(servers.server(for: FakeServerIdentifierProviding(serverIdentifier: "fake1")) === server1)
|
|
XCTAssertTrue(
|
|
servers
|
|
.server(for: FakeServerIntentProviding(server: .init(identifier: "fake1", display: "fake1"))) ===
|
|
server1
|
|
)
|
|
XCTAssertEqual(server1.info, with(info1) {
|
|
$0.sortOrder = 0
|
|
})
|
|
|
|
XCTAssertEqual(servers.all, [server1])
|
|
|
|
expectingObserver {
|
|
servers.add(identifier: "fake2", serverInfo: info2)
|
|
}
|
|
let server2 = try XCTUnwrap(servers.server(for: "fake2"))
|
|
XCTAssertTrue(servers.server(forWebhookID: "webhook2") === server2)
|
|
XCTAssertTrue(servers.server(forServerIdentifier: "fake2") === server2)
|
|
XCTAssertTrue(servers.server(for: FakeServerIdentifierProviding(serverIdentifier: "fake2")) === server2)
|
|
XCTAssertTrue(
|
|
servers
|
|
.server(for: FakeServerIntentProviding(server: .init(identifier: "fake2", display: "fake1"))) ===
|
|
server2
|
|
)
|
|
XCTAssertEqual(server2.info, with(info2) {
|
|
$0.sortOrder = 1000
|
|
})
|
|
|
|
XCTAssertEqual(servers.all, [server1, server2])
|
|
|
|
try XCTAssertEqual(keychain.getData("fake1")?.count, encoder.encode(server1.info).count)
|
|
try XCTAssertEqual(keychain.getData("fake2")?.count, encoder.encode(server2.info).count)
|
|
XCTAssertEqual(keychain.data.count, 2)
|
|
|
|
let stateS1S2 = servers.restorableState()
|
|
|
|
expectingObserver {
|
|
server1.info.connection.webhookID = "webhook1_2"
|
|
}
|
|
XCTAssertEqual(server1.info.connection.webhookID, "webhook1_2")
|
|
try XCTAssertEqual(keychain.getData("fake1")?.count, encoder.encode(server1.info).count)
|
|
|
|
expectingObserver {
|
|
servers.remove(identifier: "fake1")
|
|
}
|
|
try XCTAssertNil(keychain.getData("fake1"))
|
|
|
|
// grab it, which may also side-effect insert into cache, if buggy
|
|
_ = server1.info
|
|
|
|
expectingObserver {
|
|
// we just deleted it, so we re-add it to make sure _that_ works
|
|
let tempFake1 = with(info1) {
|
|
$0.connection.webhookID = "deleted_and_reset"
|
|
}
|
|
servers.add(identifier: "fake1", serverInfo: tempFake1)
|
|
XCTAssertEqual(servers.server(for: "fake1")?.info.connection.webhookID, "deleted_and_reset")
|
|
}
|
|
|
|
expectingObserver {
|
|
servers.remove(identifier: "fake1")
|
|
}
|
|
|
|
XCTAssertNil(servers.server(for: "fake1"))
|
|
XCTAssertEqual(servers.all, [server2])
|
|
|
|
var server3: Server!
|
|
|
|
expectingObserver {
|
|
server3 = servers.add(identifier: "fake3", serverInfo: info3)
|
|
}
|
|
XCTAssertEqual(servers.all, [server2, server3])
|
|
try XCTAssertEqual(keychain.getData("fake3")?.count, encoder.encode(server3.info).count)
|
|
XCTAssertEqual(server3.info, with(info3) {
|
|
$0.sortOrder = 2000
|
|
})
|
|
|
|
let stateS2S3 = servers.restorableState()
|
|
|
|
expectingObserver {
|
|
servers.removeAll()
|
|
}
|
|
XCTAssertEqual(servers.all, [])
|
|
XCTAssertNil(servers.server(for: "fake1"))
|
|
XCTAssertNil(servers.server(for: "fake2"))
|
|
XCTAssertNil(servers.server(for: "fake3"))
|
|
XCTAssertTrue(keychain.data.isEmpty)
|
|
|
|
expectingObserver {
|
|
servers.restoreState(stateS2S3)
|
|
}
|
|
XCTAssertEqual(servers.all.map(\.identifier), ["fake2", "fake3"])
|
|
XCTAssertEqual(Set(keychain.data.keys), Set(["fake2", "fake3"]))
|
|
|
|
XCTAssertNil(servers.server(for: "fake1"))
|
|
XCTAssertEqual(servers.server(for: "fake2")?.info, with(info2) {
|
|
$0.sortOrder = 1000
|
|
})
|
|
XCTAssertEqual(servers.server(for: "fake3")?.info, with(info3) {
|
|
$0.sortOrder = 2000
|
|
})
|
|
|
|
let server2_afterRestore = try XCTUnwrap(servers.server(for: "fake2"))
|
|
expectingObserver {
|
|
server2_afterRestore.info.connection.webhookID = "webhook2_2"
|
|
}
|
|
|
|
if Current.isAppExtension {
|
|
// do it again to handle the restricted caching case - this should notify even with no change
|
|
expectingObserver {
|
|
server2_afterRestore.info.connection.webhookID = "webhook2_2"
|
|
}
|
|
} else {
|
|
// opposite - should not notify
|
|
server2_afterRestore.info.connection.webhookID = "webhook2_2"
|
|
}
|
|
|
|
XCTAssertEqual(servers.server(for: "fake2")?.info.connection.webhookID, "webhook2_2")
|
|
try XCTAssertEqual(keychain.getData("fake2")?.count, encoder.encode(server2_afterRestore.info).count)
|
|
|
|
let s2RestoreExpectation = expectation(description: "server2notify")
|
|
_ = server2_afterRestore.observe { info in
|
|
XCTAssertEqual(info.connection.webhookID, "webhook2")
|
|
s2RestoreExpectation.fulfill()
|
|
}
|
|
|
|
expectingObserver {
|
|
servers.restoreState(stateS1S2)
|
|
}
|
|
wait(for: [s2RestoreExpectation], timeout: 10.0)
|
|
XCTAssertEqual(servers.all.map(\.identifier), ["fake1", "fake2"])
|
|
XCTAssertEqual(Set(keychain.data.keys), Set(["fake1", "fake2"]))
|
|
|
|
XCTAssertEqual(servers.server(for: "fake1")?.info, with(info1) {
|
|
$0.sortOrder = 0
|
|
})
|
|
XCTAssertEqual(servers.server(for: "fake2")?.info, with(info2) {
|
|
$0.sortOrder = 1000
|
|
})
|
|
XCTAssertNil(servers.server(for: "fake3"))
|
|
|
|
servers.remove(observer: observer)
|
|
servers.removeAll()
|
|
XCTAssertTrue(servers.all.isEmpty)
|
|
XCTAssertTrue(keychain.data.isEmpty)
|
|
}
|
|
|
|
func testWithInitialServers() throws {
|
|
let info1 = with(ServerInfo.fake()) {
|
|
$0.connection.webhookID = "webhook1"
|
|
$0.sortOrder = 3
|
|
}
|
|
|
|
let info2 = with(ServerInfo.fake()) {
|
|
$0.connection.webhookID = "webhook2"
|
|
$0.sortOrder = 2
|
|
}
|
|
|
|
let info3 = with(ServerInfo.fake()) {
|
|
$0.connection.webhookID = "webhook3"
|
|
$0.sortOrder = 1
|
|
}
|
|
|
|
try setupRegular([
|
|
"fake1": info1,
|
|
"fake2": info2,
|
|
"fake3": info3,
|
|
])
|
|
|
|
let server1 = try XCTUnwrap(servers.server(for: "fake1"))
|
|
let server2 = try XCTUnwrap(servers.server(for: "fake2"))
|
|
let server3 = try XCTUnwrap(servers.server(for: "fake3"))
|
|
|
|
XCTAssertEqual(server1.info, info1)
|
|
XCTAssertEqual(server2.info, info2)
|
|
XCTAssertEqual(server3.info, info3)
|
|
XCTAssertEqual(servers.all, [server3, server2, server1])
|
|
}
|
|
|
|
func testSortOrder() throws {
|
|
try setupRegular([
|
|
"fake1": with(.fake()) {
|
|
$0.sortOrder = 1
|
|
},
|
|
"fake2": with(.fake()) {
|
|
$0.sortOrder = 2
|
|
},
|
|
"fake3": with(.fake()) {
|
|
$0.sortOrder = 3
|
|
},
|
|
])
|
|
|
|
XCTAssertEqual(servers.all.map(\.identifier), ["fake1", "fake2", "fake3"])
|
|
|
|
servers.server(for: "fake2")?.info.sortOrder = 10
|
|
XCTAssertEqual(servers.all.map(\.identifier), ["fake1", "fake3", "fake2"])
|
|
|
|
servers.server(for: "fake3")?.info.sortOrder = 0
|
|
XCTAssertEqual(servers.all.map(\.identifier), ["fake3", "fake1", "fake2"])
|
|
}
|
|
|
|
private func notificationContent(webhookID: String?) -> UNNotificationContent {
|
|
let content = UNMutableNotificationContent()
|
|
if let webhookID {
|
|
content.userInfo["webhook_id"] = webhookID
|
|
}
|
|
return content
|
|
}
|
|
|
|
func testServerGetterHelpersWith1Server() throws {
|
|
try setupRegular([
|
|
"fake1": with(.fake()) {
|
|
$0.sortOrder = 1
|
|
$0.connection.webhookID = "webhook1"
|
|
},
|
|
])
|
|
|
|
let server1 = servers.server(for: "fake1")
|
|
let intentServer1 = IntentServer(identifier: "fake1", display: "fake1")
|
|
let intentServer2 = IntentServer(identifier: "fake2", display: "fake2")
|
|
|
|
XCTAssertEqual(servers.server(forServerIdentifier: nil), nil)
|
|
XCTAssertEqual(servers.server(forServerIdentifier: "fake1"), server1)
|
|
XCTAssertEqual(servers.server(forServerIdentifier: "fake2"), nil)
|
|
|
|
XCTAssertEqual(servers.server(forWebhookID: "webhook1"), server1)
|
|
XCTAssertEqual(servers.server(forWebhookID: "webhook2"), nil)
|
|
|
|
XCTAssertEqual(servers.server(for: notificationContent(webhookID: "webhook1")), server1)
|
|
XCTAssertEqual(servers.server(for: notificationContent(webhookID: "webhook2")), nil)
|
|
XCTAssertEqual(servers.server(for: notificationContent(webhookID: nil)), server1)
|
|
|
|
XCTAssertEqual(servers.server(for: FakeServerIntentProviding(server: intentServer1)), server1)
|
|
XCTAssertEqual(servers.server(for: FakeServerIntentProviding(server: intentServer2)), server1)
|
|
XCTAssertEqual(servers.server(for: FakeServerIntentProviding(server: intentServer2), fallback: false), nil)
|
|
|
|
XCTAssertEqual(servers.server(for: FakeServerIdentifierProviding(serverIdentifier: "fake1")), server1)
|
|
XCTAssertEqual(servers.server(for: FakeServerIdentifierProviding(serverIdentifier: "fake2")), server1)
|
|
XCTAssertEqual(
|
|
servers.server(for: FakeServerIdentifierProviding(serverIdentifier: "fake2"), fallback: false),
|
|
nil
|
|
)
|
|
}
|
|
|
|
func testServerGetterHelpersWith2Server() throws {
|
|
try setupRegular([
|
|
"fake1": with(.fake()) {
|
|
$0.sortOrder = 1
|
|
$0.connection.webhookID = "webhook1"
|
|
},
|
|
"fake2": with(.fake()) {
|
|
$0.sortOrder = 2
|
|
$0.connection.webhookID = "webhook2"
|
|
},
|
|
])
|
|
|
|
let server1 = servers.server(for: "fake1")
|
|
let server2 = servers.server(for: "fake2")
|
|
let intentServer1 = IntentServer(identifier: "fake1", display: "fake1")
|
|
let intentServer2 = IntentServer(identifier: "fake2", display: "fake2")
|
|
let intentServer3 = IntentServer(identifier: "fake3", display: "fake3")
|
|
|
|
XCTAssertEqual(servers.server(forServerIdentifier: nil), nil)
|
|
XCTAssertEqual(servers.server(forServerIdentifier: "fake1"), server1)
|
|
XCTAssertEqual(servers.server(forServerIdentifier: "fake2"), server2)
|
|
XCTAssertEqual(servers.server(forServerIdentifier: "fake3"), nil)
|
|
|
|
XCTAssertEqual(servers.server(forWebhookID: "webhook1"), server1)
|
|
XCTAssertEqual(servers.server(forWebhookID: "webhook2"), server2)
|
|
XCTAssertEqual(servers.server(forWebhookID: "webhook3"), nil)
|
|
|
|
XCTAssertEqual(servers.server(for: notificationContent(webhookID: "webhook1")), server1)
|
|
XCTAssertEqual(servers.server(for: notificationContent(webhookID: "webhook2")), server2)
|
|
XCTAssertEqual(servers.server(for: notificationContent(webhookID: nil)), server1)
|
|
XCTAssertEqual(servers.server(for: notificationContent(webhookID: "webhook3")), nil)
|
|
|
|
XCTAssertEqual(servers.server(for: FakeServerIntentProviding(server: intentServer1)), server1)
|
|
XCTAssertEqual(servers.server(for: FakeServerIntentProviding(server: intentServer2)), server2)
|
|
XCTAssertEqual(servers.server(for: FakeServerIntentProviding(server: intentServer3)), nil)
|
|
XCTAssertEqual(servers.server(for: FakeServerIntentProviding(server: intentServer3), fallback: false), nil)
|
|
|
|
XCTAssertEqual(servers.server(for: FakeServerIdentifierProviding(serverIdentifier: "fake1")), server1)
|
|
XCTAssertEqual(servers.server(for: FakeServerIdentifierProviding(serverIdentifier: "fake2")), server2)
|
|
XCTAssertEqual(servers.server(for: FakeServerIdentifierProviding(serverIdentifier: "fake3")), nil)
|
|
XCTAssertEqual(
|
|
servers.server(for: FakeServerIdentifierProviding(serverIdentifier: "fake3"), fallback: false),
|
|
nil
|
|
)
|
|
}
|
|
|
|
func testServerUpdatePerField() throws {
|
|
try setupRegular([
|
|
"fake1": with(.fake()) {
|
|
$0.sortOrder = 1
|
|
$0.connection.webhookID = "webhook1"
|
|
},
|
|
])
|
|
|
|
var decoded: ServerInfo {
|
|
get throws {
|
|
try JSONDecoder().decode(ServerInfo.self, from: XCTUnwrap(keychain.data["fake1"]))
|
|
}
|
|
}
|
|
|
|
let server = try XCTUnwrap(servers.all.first)
|
|
server.info.remoteName = "updated_name"
|
|
XCTAssertEqual(server.info.remoteName, "updated_name")
|
|
XCTAssertEqual(try decoded.remoteName, "updated_name")
|
|
|
|
server.info.sortOrder = 3
|
|
XCTAssertEqual(server.info.sortOrder, 3)
|
|
XCTAssertEqual(try decoded.sortOrder, 3)
|
|
|
|
server.info.version = Version(major: 11)
|
|
XCTAssertEqual(server.info.version.major, 11)
|
|
XCTAssertEqual(try decoded.version.major, 11)
|
|
|
|
server.info.connection.webhookID = "webhook2"
|
|
XCTAssertEqual(server.info.connection.webhookID, "webhook2")
|
|
XCTAssertEqual(try decoded.connection.webhookID, "webhook2")
|
|
|
|
server.info.token.accessToken = "access2"
|
|
XCTAssertEqual(server.info.token.accessToken, "access2")
|
|
XCTAssertEqual(try decoded.token.accessToken, "access2")
|
|
}
|
|
|
|
func testUpdateAfterDeleteDoesntPersist() throws {
|
|
try setupRegular()
|
|
|
|
let oldServers = try XCTUnwrap(servers)
|
|
let oldServer1 = oldServers.add(identifier: "fake1", serverInfo: .fake())
|
|
|
|
try setupRegular()
|
|
|
|
let newServer1 = try XCTUnwrap(servers.server(for: oldServer1.identifier))
|
|
oldServers.remove(identifier: oldServer1.identifier)
|
|
|
|
newServer1.info.remoteName = "updated"
|
|
XCTAssertTrue(keychain.data.isEmpty)
|
|
|
|
let newInfo = with(newServer1.info) {
|
|
$0.remoteName = "new_name1"
|
|
}
|
|
servers.add(identifier: newServer1.identifier, serverInfo: newInfo)
|
|
XCTAssertEqual(keychain.data[newServer1.identifier.rawValue]?.count, try encoder.encode(newInfo).count)
|
|
}
|
|
|
|
func testUpdateAfterDeleteInAnotherProcessDoesntPersist() throws {
|
|
try setupRegular()
|
|
|
|
let server1 = servers.add(identifier: "fake1", serverInfo: .fake())
|
|
servers.remove(identifier: server1.identifier)
|
|
|
|
try setupRegular()
|
|
|
|
server1.info.remoteName = "updated"
|
|
XCTAssertTrue(keychain.data.isEmpty)
|
|
|
|
let newInfo = with(server1.info) {
|
|
$0.remoteName = "new_name1"
|
|
}
|
|
servers.add(identifier: server1.identifier, serverInfo: newInfo)
|
|
XCTAssertEqual(keychain.data[server1.identifier.rawValue]?.count, try encoder.encode(newInfo).count)
|
|
}
|
|
|
|
func testThreadsafeChangesWithoutCaching() throws {
|
|
Current.isAppExtension = true
|
|
try base_testThreadsafeChanges()
|
|
}
|
|
|
|
func testThreadsafeChangesWithCaching() throws {
|
|
Current.isAppExtension = false
|
|
try base_testThreadsafeChanges()
|
|
}
|
|
|
|
private func base_testThreadsafeChanges() throws {
|
|
try setupRegular()
|
|
|
|
enum ActionType {
|
|
case insertExisting(newValue: Bool)
|
|
case insertNew
|
|
case mutate
|
|
case delete
|
|
}
|
|
|
|
let cases: [ActionType] = [
|
|
// weight a little heavier the normal ones
|
|
.insertNew,
|
|
.insertNew,
|
|
.mutate,
|
|
.mutate,
|
|
.delete,
|
|
.delete,
|
|
// the rest
|
|
.insertExisting(newValue: false),
|
|
.insertExisting(newValue: true),
|
|
]
|
|
|
|
DispatchQueue.concurrentPerform(iterations: 1000) { _ in
|
|
let randomServerInfo: ServerInfo = with(.fake()) {
|
|
$0.connection.webhookID = UUID().uuidString
|
|
}
|
|
|
|
switch cases.randomElement()! {
|
|
case .insertNew:
|
|
let added = servers.add(identifier: .init(rawValue: UUID().uuidString), serverInfo: randomServerInfo)
|
|
_ = servers.server(for: added.identifier)
|
|
case let .insertExisting(newValue):
|
|
if let random = servers.all.randomElement() {
|
|
let used: ServerInfo = newValue ? randomServerInfo : .fake()
|
|
servers.add(identifier: random.identifier, serverInfo: used)
|
|
_ = servers.server(for: random.identifier)
|
|
}
|
|
case .mutate:
|
|
if let random = servers.all.randomElement() {
|
|
random.info = randomServerInfo
|
|
_ = servers.server(for: random.identifier)
|
|
}
|
|
case .delete:
|
|
if let random = servers.all.randomElement() {
|
|
servers.remove(identifier: random.identifier)
|
|
_ = servers.server(for: random.identifier)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
private struct HistoricInfo {
|
|
var connectionInfo: ConnectionInfo
|
|
var tokenInfo: TokenInfo
|
|
}
|
|
|
|
private func setupHistoric(
|
|
version: String?,
|
|
overrideDeviceName: String?,
|
|
locationName: String?
|
|
) throws -> HistoricInfo {
|
|
let connectionInfo = ConnectionInfo(
|
|
externalURL: URL(string: "http://external.local:8123")!,
|
|
internalURL: URL(string: "http://internal.local:8123")!,
|
|
cloudhookURL: nil,
|
|
remoteUIURL: nil,
|
|
webhookID: "webhook_id",
|
|
webhookSecret: "webhook_secret",
|
|
internalSSIDs: ["internal_ssid"],
|
|
internalHardwareAddresses: ["internal_hardware"],
|
|
isLocalPushEnabled: true,
|
|
securityExceptions: .init()
|
|
)
|
|
|
|
let tokenInfo = TokenInfo(
|
|
accessToken: "access_token",
|
|
refreshToken: "refresh_token",
|
|
expiration: Date(timeIntervalSinceNow: 1000)
|
|
)
|
|
|
|
try historicKeychain.set(encoder.encode(connectionInfo), key: "connectionInfo")
|
|
try historicKeychain.set(encoder.encode(tokenInfo), key: "tokenInfo")
|
|
Current.settingsStore.prefs.set(version, forKey: "version")
|
|
Current.settingsStore.prefs.set(overrideDeviceName, forKey: "override_device_name")
|
|
Current.settingsStore.prefs.set(locationName, forKey: "location_name")
|
|
|
|
servers = ServerManagerImpl(keychain: keychain, historicKeychain: historicKeychain)
|
|
servers.setup()
|
|
|
|
return .init(connectionInfo: connectionInfo, tokenInfo: tokenInfo)
|
|
}
|
|
|
|
func testEmptyMigrateWithFullData() throws {
|
|
let setupInfo = try setupHistoric(
|
|
version: "2021.96",
|
|
overrideDeviceName: "device_name_1",
|
|
locationName: "location_name_1"
|
|
)
|
|
|
|
XCTAssertEqual(servers.all.count, 1)
|
|
|
|
// added the server
|
|
let server = try XCTUnwrap(servers.server(for: Server.historicId))
|
|
XCTAssertEqual(server.info.connection, setupInfo.connectionInfo)
|
|
XCTAssertEqual(server.info.token, setupInfo.tokenInfo)
|
|
XCTAssertEqual(server.info.version, Version(major: 2021, minor: 96))
|
|
XCTAssertEqual(server.info.name, "location_name_1")
|
|
XCTAssertEqual(server.info.setting(for: .overrideDeviceName), "device_name_1")
|
|
|
|
// removed the old keychain
|
|
XCTAssertTrue(historicKeychain.data.isEmpty)
|
|
}
|
|
|
|
func testEmptyMigrateWithMinimalData() throws {
|
|
let setupInfo = try setupHistoric(
|
|
version: nil,
|
|
overrideDeviceName: nil,
|
|
locationName: nil
|
|
)
|
|
|
|
XCTAssertEqual(servers.all.count, 1)
|
|
|
|
// added the server
|
|
let server = try XCTUnwrap(servers.server(for: Server.historicId))
|
|
XCTAssertEqual(server.info.connection, setupInfo.connectionInfo)
|
|
XCTAssertEqual(server.info.token, setupInfo.tokenInfo)
|
|
XCTAssertEqual(server.info.version, Version(major: 2021, minor: 1))
|
|
XCTAssertEqual(server.info.name, ServerInfo.defaultName)
|
|
XCTAssertNil(server.info.setting(for: .overrideDeviceName))
|
|
|
|
// removed the old keychain
|
|
XCTAssertTrue(historicKeychain.data.isEmpty)
|
|
}
|
|
|
|
func testMigrateDoesntOccurWithExisting() throws {
|
|
try setupRegular(["existing": .fake()])
|
|
_ = try setupHistoric(version: nil, overrideDeviceName: nil, locationName: nil)
|
|
|
|
XCTAssertEqual(servers.all.count, 1)
|
|
XCTAssertNotNil(servers.server(for: "existing"))
|
|
XCTAssertNil(servers.server(for: Server.historicId))
|
|
}
|
|
}
|
|
|
|
class FakeServerManagerKeychain: ServerManagerKeychain {
|
|
var data = [String: Data]()
|
|
|
|
func removeAll() throws {
|
|
data.removeAll()
|
|
}
|
|
|
|
func allKeys() -> [String] {
|
|
Array(data.keys)
|
|
}
|
|
|
|
func getData(_ key: String) throws -> Data? {
|
|
data[key]
|
|
}
|
|
|
|
func set(_ value: Data, key: String) throws {
|
|
data[key] = value
|
|
}
|
|
|
|
func remove(_ key: String) throws {
|
|
data.removeValue(forKey: key)
|
|
}
|
|
}
|
|
|
|
private struct FakeServerIdentifierProviding: ServerIdentifierProviding {
|
|
var serverIdentifier: String
|
|
}
|
|
|
|
private struct FakeServerIntentProviding: ServerIntentProviding {
|
|
var server: IntentServer?
|
|
}
|
|
|
|
private class FakeObserver: ServerObserver {
|
|
var expectation: XCTestExpectation?
|
|
|
|
func addExpectation(from testCase: XCTestCase) -> XCTestExpectation {
|
|
let expectation = testCase.expectation(description: "server observer")
|
|
self.expectation = expectation
|
|
return expectation
|
|
}
|
|
|
|
func serversDidChange(_ serverManager: ServerManager) {
|
|
if let expectation {
|
|
expectation.fulfill()
|
|
} else {
|
|
XCTFail("observed without expectation")
|
|
}
|
|
}
|
|
}
|