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