OctagonDataPersistenceTests.swift [plain text]
import XCTest
#if OCTAGON
class OctagonAccountMetadataClassCPersistenceTests: CloudKitKeychainSyncingMockXCTest {
override static func setUp() {
super.setUp()
// Turn on NO_SERVER stuff
securityd_init_local_spi()
}
func testSaveAndLoad() throws {
XCTAssertThrowsError(try OTAccountMetadataClassC.loadFromKeychain(forContainer: OTCKContainerName, contextID: OTDefaultContext),
"Before doing anything, loading a non-existent account state should fail")
let state: OTAccountMetadataClassC! = OTAccountMetadataClassC()
state.peerID = "asdf"
state.icloudAccountState = .ACCOUNT_AVAILABLE
state.trustState = .TRUSTED
XCTAssertNoThrow(try state.saveToKeychain(forContainer: OTCKContainerName, contextID: OTDefaultContext), "saving to the keychain should work")
do {
let state2 = try OTAccountMetadataClassC.loadFromKeychain(forContainer: OTCKContainerName, contextID: OTDefaultContext)
XCTAssertNotNil(state2)
XCTAssertEqual(state2.peerID, state.peerID, "peer ID persists through keychain")
XCTAssertEqual(state2.icloudAccountState, state.icloudAccountState, "account state persists through keychain")
XCTAssertEqual(state2.trustState, state.trustState, "trust state persists through keychain")
} catch {
XCTFail("error loading from keychain: \(error)")
}
}
func testSilentOverwrite() throws {
XCTAssertThrowsError(try OTAccountMetadataClassC.loadFromKeychain(forContainer: OTCKContainerName, contextID: OTDefaultContext),
"Before doing anything, loading a non-existent account state should fail")
let state: OTAccountMetadataClassC! = OTAccountMetadataClassC()
state.peerID = "asdf"
state.icloudAccountState = .ACCOUNT_AVAILABLE
state.trustState = .TRUSTED
XCTAssertNoThrow(try state.saveToKeychain(forContainer: OTCKContainerName, contextID: OTDefaultContext), "saving to the keychain should work")
state.peerID = "no wait another peer id"
state.icloudAccountState = .ACCOUNT_AVAILABLE
state.trustState = .UNTRUSTED
XCTAssertNoThrow(try state.saveToKeychain(forContainer: OTCKContainerName, contextID: OTDefaultContext), "saving to the keychain should work")
do {
let state2 = try OTAccountMetadataClassC.loadFromKeychain(forContainer: OTCKContainerName, contextID: OTDefaultContext)
XCTAssertNotNil(state2)
XCTAssertEqual(state2.peerID, "no wait another peer id", "peer ID persists through keychain")
XCTAssertEqual(state2.icloudAccountState, .ACCOUNT_AVAILABLE, "account state persists through keychain")
XCTAssertEqual(state2.trustState, .UNTRUSTED, "trust state persists through keychain")
} catch {
XCTFail("error loading from keychain: \(error)")
}
}
func testContainerIndependence() throws {
let state1: OTAccountMetadataClassC! = OTAccountMetadataClassC()
state1.peerID = "asdf"
state1.icloudAccountState = .ACCOUNT_AVAILABLE
state1.trustState = .TRUSTED
let state2: OTAccountMetadataClassC! = OTAccountMetadataClassC()
state2.peerID = "anotherPeerID"
state2.icloudAccountState = .ACCOUNT_AVAILABLE
state2.trustState = .UNTRUSTED
XCTAssertNoThrow(try state1.saveToKeychain(forContainer: OTCKContainerName, contextID: OTDefaultContext), "saving to the keychain should work")
XCTAssertNoThrow(try state2.saveToKeychain(forContainer: "second_container", contextID: OTDefaultContext), "saving to the keychain should work")
do {
let state1reloaded = try OTAccountMetadataClassC.loadFromKeychain(forContainer: OTCKContainerName, contextID: OTDefaultContext)
XCTAssertNotNil(state1reloaded)
XCTAssertEqual(state1reloaded.peerID, state1.peerID, "peer ID persists through keychain")
XCTAssertEqual(state1reloaded.icloudAccountState, state1.icloudAccountState, "account state persists through keychain")
XCTAssertEqual(state1reloaded.trustState, state1.trustState, "trust state persists through keychain")
} catch {
XCTFail("error loading state1 from keychain: \(error)")
}
do {
let state2reloaded = try OTAccountMetadataClassC.loadFromKeychain(forContainer: "second_container", contextID: OTDefaultContext)
XCTAssertNotNil(state2reloaded)
XCTAssertEqual(state2reloaded.peerID, state2.peerID, "peer ID persists through keychain")
XCTAssertEqual(state2reloaded.icloudAccountState, state2.icloudAccountState, "account state persists through keychain")
XCTAssertEqual(state2reloaded.trustState, state2.trustState, "trust state persists through keychain")
} catch {
XCTFail("error loading state2 from keychain: \(error)")
}
}
func testContextIndependence() throws {
let state1: OTAccountMetadataClassC! = OTAccountMetadataClassC()
state1.peerID = "asdf"
state1.icloudAccountState = .ACCOUNT_AVAILABLE
state1.trustState = .TRUSTED
let state2: OTAccountMetadataClassC! = OTAccountMetadataClassC()
state2.peerID = "anotherPeerID"
state2.icloudAccountState = .ACCOUNT_AVAILABLE
state2.trustState = .UNTRUSTED
XCTAssertNoThrow(try state1.saveToKeychain(forContainer: OTCKContainerName, contextID: OTDefaultContext), "saving to the keychain should work")
XCTAssertNoThrow(try state2.saveToKeychain(forContainer: OTCKContainerName, contextID: "second_context"), "saving to the keychain should work")
do {
let state1reloaded = try OTAccountMetadataClassC.loadFromKeychain(forContainer: OTCKContainerName, contextID: OTDefaultContext)
XCTAssertNotNil(state1reloaded)
XCTAssertEqual(state1reloaded.peerID, state1.peerID, "peer ID persists through keychain")
XCTAssertEqual(state1reloaded.icloudAccountState, state1.icloudAccountState, "account state persists through keychain")
XCTAssertEqual(state1reloaded.trustState, state1.trustState, "trust state persists through keychain")
} catch {
XCTFail("error loading state1 from keychain: \(error)")
}
do {
let state2reloaded = try OTAccountMetadataClassC.loadFromKeychain(forContainer: OTCKContainerName, contextID: "second_context")
XCTAssertNotNil(state2reloaded)
XCTAssertEqual(state2reloaded.peerID, state2.peerID, "peer ID persists through keychain")
XCTAssertEqual(state2reloaded.icloudAccountState, state2.icloudAccountState, "account state persists through keychain")
XCTAssertEqual(state2reloaded.trustState, state2.trustState, "trust state persists through keychain")
} catch {
XCTFail("error loading state2 from keychain: \(error)")
}
}
func testLoadCorruptedAccountState() throws {
XCTAssertThrowsError(try OTAccountMetadataClassC.loadFromKeychain(forContainer: OTCKContainerName, contextID: OTDefaultContext),
"Before doing anything, loading a non-existent account state should fail")
let state: OTAccountMetadataClassC! = OTAccountMetadataClassC()
state.peerID = "asdf"
state.icloudAccountState = .ACCOUNT_AVAILABLE
state.trustState = .TRUSTED
XCTAssertNoThrow(try TestsObjectiveC.saveCoruptDataToKeychain(forContainer: OTCKContainerName, contextID: OTDefaultContext), "saving to the keychain should work")
do {
let state2 = try OTAccountMetadataClassC.loadFromKeychain(forContainer: OTCKContainerName, contextID: OTDefaultContext)
XCTAssertNotNil(state2)
XCTAssertEqual(state2.peerID, nil, "peerID should be nil")
XCTAssertEqual(state2.icloudAccountState, OTAccountMetadataClassC_AccountState.UNKNOWN, "account state should be OTAccountMetadataClassC_AccountState_UNKNOWN")
XCTAssertEqual(state2.trustState, OTAccountMetadataClassC_TrustState.UNKNOWN, "trust state should be OTAccountMetadataClassC_TrustState_UNKNOWN")
} catch {
XCTFail("error loading from keychain: \(error)")
}
}
func testDeleteFromKeychain() throws {
let state: OTAccountMetadataClassC! = OTAccountMetadataClassC()
state.peerID = "asdf"
state.icloudAccountState = .ACCOUNT_AVAILABLE
state.trustState = .TRUSTED
XCTAssertNoThrow(try state.saveToKeychain(forContainer: OTCKContainerName, contextID: OTDefaultContext), "saving to the keychain should work")
let deleted: Bool = try OTAccountMetadataClassC.deleteFromKeychain(forContainer: OTCKContainerName, contextID: OTDefaultContext)
XCTAssertTrue(deleted, "deleteFromKeychain should return true")
XCTAssertThrowsError(try OTAccountMetadataClassC.loadFromKeychain(forContainer: OTCKContainerName, contextID: OTDefaultContext))
}
}
#endif // OCTAGON