IOS-1545 rename NetworkService to ReplicationService IOS-1545
authorAlejandro Gelos <alejandro@pep-project.org>
Thu, 18 Apr 2019 11:56:49 +0200
branchIOS-1545
changeset 83150438a54b5094
parent 8314 84e386021641
child 8317 4dcaa1c257df
IOS-1545 rename NetworkService to ReplicationService
pEpForiOS.xcodeproj/project.pbxproj
pEpForiOS/AppDelegate.swift
pEpForiOSTests/NetworkServiceTests.swift
pEpForiOSTests/ReplicationServiceTests.swift
pEpForiOSTests/TestUtils/NetworkServiceObserver.swift
pEpForiOSTests/TestUtils/TestUtil.swift
     1.1 --- a/pEpForiOS.xcodeproj/project.pbxproj	Thu Apr 18 11:53:56 2019 +0200
     1.2 +++ b/pEpForiOS.xcodeproj/project.pbxproj	Thu Apr 18 11:56:49 2019 +0200
     1.3 @@ -411,7 +411,7 @@
     1.4  		49DCCD2621E8ABD300ABE487 /* nojavascript.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 49DCCD1F21E75BE300ABE487 /* nojavascript.pdf */; };
     1.5  		49DCCD2721E8ABD600ABE487 /* javascript.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 49079D9821E3867900D15A0D /* javascript.pdf */; };
     1.6  		49DCCD2821E8ABDF00ABE487 /* ScreenshotTestUtil.swift in Sources */ = {isa = PBXBuildFile; fileRef = 495F689921E6600500A10C63 /* ScreenshotTestUtil.swift */; };
     1.7 -		5DEBAA481DE59C3B00FAE12C /* NetworkServiceTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5DEBAA471DE59C3B00FAE12C /* NetworkServiceTests.swift */; };
     1.8 +		5DEBAA481DE59C3B00FAE12C /* ReplicationServiceTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5DEBAA471DE59C3B00FAE12C /* ReplicationServiceTests.swift */; };
     1.9  		8B69E3991E30F80E0022959E /* Appearance.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8B69E3981E30F80E0022959E /* Appearance.swift */; };
    1.10  		A1014DA71D1173CD00C472A8 /* UIHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 436C5A8D1CFEDF59006A195F /* UIHelper.swift */; };
    1.11  		A1B50A841CD26FF100B1A997 /* Constants.swift in Sources */ = {isa = PBXBuildFile; fileRef = A1B50A811CD26FF100B1A997 /* Constants.swift */; };
    1.12 @@ -929,7 +929,7 @@
    1.13  		49C34AF520E4F649009D11CC /* CellDetailTransition.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CellDetailTransition.swift; sourceTree = "<group>"; };
    1.14  		49D3BECB20F8F7330043E05D /* LoginViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoginViewController.swift; sourceTree = "<group>"; };
    1.15  		49DCCD1F21E75BE300ABE487 /* nojavascript.pdf */ = {isa = PBXFileReference; lastKnownFileType = image.pdf; path = nojavascript.pdf; sourceTree = "<group>"; };
    1.16 -		5DEBAA471DE59C3B00FAE12C /* NetworkServiceTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NetworkServiceTests.swift; sourceTree = "<group>"; };
    1.17 +		5DEBAA471DE59C3B00FAE12C /* ReplicationServiceTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ReplicationServiceTests.swift; sourceTree = "<group>"; };
    1.18  		8B69E3981E30F80E0022959E /* Appearance.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Appearance.swift; sourceTree = "<group>"; };
    1.19  		A1B50A811CD26FF100B1A997 /* Constants.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Constants.swift; sourceTree = "<group>"; };
    1.20  		B70A3A62220065F500EDCE61 /* String+pEp.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "String+pEp.swift"; sourceTree = "<group>"; };
    1.21 @@ -1830,7 +1830,7 @@
    1.22  				436F8E131D36706A007E9829 /* StringExtensionsTest.swift */,
    1.23  				43257C851F50659200DDC7F0 /* StringHTMLExtensionTests.swift */,
    1.24  				432A24D61DE714A200DAAC5C /* MessagePantomimeTests.swift */,
    1.25 -				5DEBAA471DE59C3B00FAE12C /* NetworkServiceTests.swift */,
    1.26 +				5DEBAA471DE59C3B00FAE12C /* ReplicationServiceTests.swift */,
    1.27  				43E74C731E38DE2200A2F7A6 /* ImapFlagsTests.swift */,
    1.28  				43EE994D1E4392530060EACE /* FlagImageTests.swift */,
    1.29  				438281821E891B7E00087343 /* DateTests.swift */,
    1.30 @@ -3090,7 +3090,7 @@
    1.31  				4356FFEC21356CB600804089 /* ReplyAllPossibleCheckerTest.swift in Sources */,
    1.32  				430C80E01D0EADC200CD4582 /* PepAdapterTests.swift in Sources */,
    1.33  				00DF2C3B2164C53F004EBA6C /* FolderViewModelTest.swift in Sources */,
    1.34 -				5DEBAA481DE59C3B00FAE12C /* NetworkServiceTests.swift in Sources */,
    1.35 +				5DEBAA481DE59C3B00FAE12C /* ReplicationServiceTests.swift in Sources */,
    1.36  				157C05482180756300E530DE /* DocumentAttachmentPickerViewModelTest.swift in Sources */,
    1.37  				49DCCD2521E8ABA900ABE487 /* SecurePDFScreenshotTest.swift in Sources */,
    1.38  				151F7200202A06760057C74D /* TestUtil.swift in Sources */,
     2.1 --- a/pEpForiOS/AppDelegate.swift	Thu Apr 18 11:53:56 2019 +0200
     2.2 +++ b/pEpForiOS/AppDelegate.swift	Thu Apr 18 11:56:49 2019 +0200
     2.3 @@ -80,7 +80,7 @@
     2.4      }
     2.5  
     2.6      /// Signals all PEPSession users to stop using a session as soon as possible.
     2.7 -    /// NetworkService will assure all local changes triggered by the user are synced to the server
     2.8 +    /// ReplicationService will assure all local changes triggered by the user are synced to the server
     2.9      /// and call it's delegate (me) after the last sync operation has finished.
    2.10      private func stopUsingPepSession() {
    2.11          syncUserActionsAndCleanupbackgroundTaskId =
    2.12 @@ -88,8 +88,8 @@
    2.13                  Logger.appDelegateLogger.errorAndCrash(
    2.14                      "syncUserActionsAndCleanupbackgroundTask with ID %{public}@ expired",
    2.15                      self.syncUserActionsAndCleanupbackgroundTaskId as CVarArg)
    2.16 -                // We migh want to call some (yet unexisting) emergency shutdown on NetworkService here
    2.17 -                // that brutally shuts down everything.
    2.18 +                // We migh want to call some (yet unexisting) emergency shutdown on
    2.19 +                // ReplicationService here that brutally shuts down everything.
    2.20                  self.application.endBackgroundTask(UIBackgroundTaskIdentifier(
    2.21                      rawValue: self.syncUserActionsAndCleanupbackgroundTaskId.rawValue))
    2.22              })
    2.23 @@ -105,8 +105,8 @@
    2.24      func kickOffMySelf() {
    2.25          mySelfTaskId = application.beginBackgroundTask(expirationHandler: { [unowned self] in
    2.26              Logger.appDelegateLogger.log("mySelfTaskId with ID expired.")
    2.27 -            // We migh want to call some (yet unexisting) emergency shutdown on NetworkService here
    2.28 -            // that brutally shuts down everything.
    2.29 +            // We migh want to call some (yet unexisting) emergency shutdown on
    2.30 +            // ReplicationService here here that brutally shuts down everything.
    2.31              self.application.endBackgroundTask(
    2.32                  UIBackgroundTaskIdentifier(rawValue:self.mySelfTaskId.rawValue))
    2.33          })
    2.34 @@ -194,7 +194,7 @@
    2.35      // Safely restarts all services
    2.36      private func shutdownAndPrepareServicesForRestart() {
    2.37          // We cancel the Network Service to make sure it is idle and ready for a clean restart.
    2.38 -        // The actual restart of the services happens in NetworkServiceDelegate callbacks.
    2.39 +        // The actual restart of the services happens in ReplicationServiceDelegate callbacks.
    2.40          messageModelService?.cancel()
    2.41      }
    2.42  
    2.43 @@ -298,7 +298,7 @@
    2.44          completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
    2.45          
    2.46          guard let messageModelService = messageModelService else {
    2.47 -            Logger.appDelegateLogger.error("no networkService")
    2.48 +            Logger.appDelegateLogger.error("no replicationService")
    2.49              return
    2.50          }
    2.51          
    2.52 @@ -351,7 +351,7 @@
    2.53      }
    2.54  }
    2.55  
    2.56 -// MARK: - NetworkServiceDelegate
    2.57 +// MARK: - ReplicationServiceDelegate
    2.58  
    2.59  extension AppDelegate: MessageModelServiceDelegate {
    2.60  
     3.1 --- a/pEpForiOSTests/NetworkServiceTests.swift	Thu Apr 18 11:53:56 2019 +0200
     3.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.3 @@ -1,279 +0,0 @@
     3.4 -//
     3.5 -//  NetworkServiceTests.swift
     3.6 -//  pEpForiOS
     3.7 -//
     3.8 -//  Created by hernani on 23/11/16.
     3.9 -//  Copyright © 2016 p≡p Security S.A. All rights reserved.
    3.10 -//
    3.11 -
    3.12 -import XCTest
    3.13 -
    3.14 -import MessageModel
    3.15 -@testable import pEpForiOS
    3.16 -
    3.17 -class NetworkServiceTests: XCTestCase {
    3.18 -    var persistenceSetup: PersistentSetup!
    3.19 -
    3.20 -    override func setUp() {
    3.21 -        super.setUp()
    3.22 -        persistenceSetup = PersistentSetup()
    3.23 -    }
    3.24 -
    3.25 -    override func tearDown() {
    3.26 -        persistenceSetup = nil
    3.27 -        super.tearDown()
    3.28 -    }
    3.29 -
    3.30 -    func testSyncOutgoing() {
    3.31 -        testSyncOutgoing(useCorrectSmtpAccount: true)
    3.32 -    }
    3.33 -
    3.34 -    func testSyncOutgoingWithWrongAccount() {
    3.35 -        testSyncOutgoing(useCorrectSmtpAccount: false)
    3.36 -    }
    3.37 -
    3.38 -    func testSyncOneTime() {
    3.39 -        XCTAssertNil(CdAccount.all())
    3.40 -        XCTAssertNil(CdFolder.all())
    3.41 -        XCTAssertNil(CdMessage.all())
    3.42 -
    3.43 -        let modelDelegate = MessageModelObserver()
    3.44 -        MessageModelConfig.messageFolderDelegate = modelDelegate
    3.45 -
    3.46 -        let networkService = NetworkService(parentName: #function)
    3.47 -
    3.48 -        let del = NetworkServiceObserver(
    3.49 -            expAccountsSynced: expectation(description: "expSingleAccountSynced"))
    3.50 -        networkService.unitTestDelegate = del
    3.51 -        networkService.delegate = del
    3.52 -
    3.53 -        _ = SecretTestData().createWorkingCdAccount()
    3.54 -        Record.saveAndWait()
    3.55 -
    3.56 -        networkService.start()
    3.57 -
    3.58 -        waitForExpectations(timeout: TestUtil.waitTime, handler: { error in
    3.59 -            XCTAssertNil(error)
    3.60 -        })
    3.61 -
    3.62 -        XCTAssertNotNil(del.accountInfo)
    3.63 -        XCTAssertNotNil(CdFolder.all())
    3.64 -
    3.65 -        guard let cdFolder = CdFolder.first(
    3.66 -            attributes: ["folderTypeRawValue": FolderType.inbox.rawValue]) else {
    3.67 -                XCTFail()
    3.68 -                return
    3.69 -        }
    3.70 -        XCTAssertGreaterThanOrEqual(cdFolder.messages?.count ?? 0, 0)
    3.71 -        let allCdMessages = cdFolder.messages?.sortedArray(
    3.72 -            using: [NSSortDescriptor(key: "uid", ascending: true)]) as? [CdMessage] ?? []
    3.73 -        XCTAssertGreaterThanOrEqual(allCdMessages.count, 0)
    3.74 -
    3.75 -        for cdMsg in allCdMessages {
    3.76 -            guard let parentF = cdMsg.parent else {
    3.77 -                XCTFail()
    3.78 -                continue
    3.79 -            }
    3.80 -            XCTAssertEqual(parentF.folderType, FolderType.inbox)
    3.81 -        }
    3.82 -
    3.83 -        let unifiedInbox = UnifiedInbox()
    3.84 -
    3.85 -        let unifiedMessageCount = unifiedInbox.messageCount()
    3.86 -        XCTAssertGreaterThanOrEqual(unifiedMessageCount, 0)
    3.87 -        for i in 0..<unifiedMessageCount {
    3.88 -            guard let msg = unifiedInbox.messageAt(index: i) else {
    3.89 -                XCTFail()
    3.90 -                continue
    3.91 -            }
    3.92 -
    3.93 -            XCTAssertTrue(msg.isValidMessage())
    3.94 -
    3.95 -            let pEpRating = Int16(msg.pEpRatingInt ?? -1)
    3.96 -            XCTAssertNotEqual(pEpRating, PEPUtil.pEpRatingNone)
    3.97 -            if !modelDelegate.contains(messageID: msg.messageID) {
    3.98 -                XCTFail()
    3.99 -            }
   3.100 -        }
   3.101 -
   3.102 -        let inbox = Folder.from(cdFolder: cdFolder)
   3.103 -        XCTAssertEqual(modelDelegate.messages.count, unifiedMessageCount)
   3.104 -
   3.105 -        for msg in modelDelegate.messages {
   3.106 -            let msgIsFlaggedDeleted = msg.imapFlags?.deleted ?? false
   3.107 -            XCTAssertTrue(!msgIsFlaggedDeleted)
   3.108 -            XCTAssertTrue(inbox.contains(message: msg))
   3.109 -            if !unifiedInbox.contains(message: msg) {
   3.110 -                XCTFail()
   3.111 -            }
   3.112 -        }
   3.113 -        XCTAssertFalse(modelDelegate.hasChangedMessages)
   3.114 -
   3.115 -        TestUtil.cancelNetworkServiceAndWait(networkService: networkService, testCase: self)
   3.116 -    }
   3.117 -
   3.118 -    func testCancelSyncImmediately() {
   3.119 -        XCTAssertNil(CdAccount.all())
   3.120 -        XCTAssertNil(CdFolder.all())
   3.121 -        XCTAssertNil(CdMessage.all())
   3.122 -
   3.123 -        let networkService = NetworkService(parentName: #function)
   3.124 -
   3.125 -        _ = SecretTestData().createWorkingCdAccount()
   3.126 -        Record.saveAndWait()
   3.127 -
   3.128 -        for _ in 0...10 {
   3.129 -            networkService.start()
   3.130 -            TestUtil.cancelNetworkServiceAndWait(networkService: networkService, testCase: self)
   3.131 -        }
   3.132 -
   3.133 -        XCTAssertNil(CdFolder.all())
   3.134 -        XCTAssertNil(CdMessage.all())
   3.135 -    }
   3.136 -
   3.137 -    class MySelfObserver: KickOffMySelfProtocol {
   3.138 -        let expMySelfed: XCTestExpectation?
   3.139 -        let queue = LimitedOperationQueue()
   3.140 -        let backgrounder: MockBackgrounder
   3.141 -
   3.142 -        init(expMySelfed: XCTestExpectation?,
   3.143 -             expBackgroundTaskFinishedAtLeastOnce: XCTestExpectation?) {
   3.144 -            self.expMySelfed = expMySelfed
   3.145 -            backgrounder = MockBackgrounder(
   3.146 -                expBackgroundTaskFinishedAtLeastOnce: expBackgroundTaskFinishedAtLeastOnce)
   3.147 -        }
   3.148 -
   3.149 -        func startMySelf() {
   3.150 -            let op = MySelfOperation(parentName: #function, backgrounder: backgrounder)
   3.151 -            op.completionBlock = {
   3.152 -                op.completionBlock = nil
   3.153 -                self.expMySelfed?.fulfill()
   3.154 -            }
   3.155 -            queue.addOperation(op)
   3.156 -        }
   3.157 -    }
   3.158 -
   3.159 -    //MARK: HELPER
   3.160 -
   3.161 -    func testSyncOutgoing(useCorrectSmtpAccount: Bool) {
   3.162 -        XCTAssertNil(CdAccount.all())
   3.163 -        XCTAssertNil(CdFolder.all())
   3.164 -        XCTAssertNil(CdMessage.all())
   3.165 -
   3.166 -        let modelDelegate = MessageModelObserver()
   3.167 -        MessageModelConfig.messageFolderDelegate = modelDelegate
   3.168 -
   3.169 -        let cdAccount = useCorrectSmtpAccount ? SecretTestData().createWorkingCdAccount() :
   3.170 -            SecretTestData().createSmtpTimeOutCdAccount()
   3.171 -        Record.saveAndWait()
   3.172 -
   3.173 -        TestUtil.syncAndWait(testCase: self)
   3.174 -
   3.175 -        let from = CdIdentity.create()
   3.176 -        from.userName = cdAccount.identity?.userName ?? "Unit 004"
   3.177 -        from.address = cdAccount.identity?.address ?? "unittest.ios.4@peptest.ch"
   3.178 -
   3.179 -        let to = CdIdentity.create()
   3.180 -        to.userName = "Unit 001"
   3.181 -        to.address = "unittest.ios.1@peptest.ch"
   3.182 -
   3.183 -        guard let sentFolder = CdFolder.by(folderType: .sent, account: cdAccount) else {
   3.184 -            XCTFail()
   3.185 -            return
   3.186 -        }
   3.187 -        XCTAssertEqual((sentFolder.messages ?? NSSet()).count, 0)
   3.188 -
   3.189 -        let numMails = 1
   3.190 -        let outgoingMails = try! TestUtil.createOutgoingMails(
   3.191 -            cdAccount: cdAccount,
   3.192 -            testCase: self, numberOfMails: numMails)
   3.193 -        let outgoingMessageIDs: [String] = outgoingMails
   3.194 -            .map() { $0.messageID ?? "" }
   3.195 -            .filter() { $0 != "" }
   3.196 -
   3.197 -        // Verify outgoing mails
   3.198 -        for m in outgoingMails {
   3.199 -            XCTAssertEqual(m.parent?.folderType, FolderType.outbox)
   3.200 -            XCTAssertEqual(m.uid, Int32(0))
   3.201 -        }
   3.202 -
   3.203 -        TestUtil.syncAndWait(testCase: self)
   3.204 -
   3.205 -        // Check that the sent mails have been deleted
   3.206 -        Record.refreshRegisteredObjects(mergeChanges: true)
   3.207 -        if useCorrectSmtpAccount {
   3.208 -            for m in outgoingMails {
   3.209 -                XCTAssertTrue(m.isDeleted)
   3.210 -            }
   3.211 -        }
   3.212 -
   3.213 -        // sync
   3.214 -        TestUtil.syncAndWait(testCase: self)
   3.215 -
   3.216 -        if useCorrectSmtpAccount {
   3.217 -            // those messages do not exist if we are using an incorrect account
   3.218 -            TestUtil.checkForExistanceAndUniqueness(uuids: outgoingMessageIDs)
   3.219 -        }
   3.220 -    }
   3.221 -
   3.222 -    class MessageModelObserver: MessageFolderDelegate {
   3.223 -        var messages: [Message] {
   3.224 -            var messages = [Message]()
   3.225 -            for ms in messagesByID.values {
   3.226 -                for m in ms {
   3.227 -                    messages.append(m)
   3.228 -                }
   3.229 -            }
   3.230 -            return messages.sorted { m1, m2 in
   3.231 -                if let d1 = m1.received, let d2 = m2.received {
   3.232 -                    return areInIncreasingOrder(d1: d1, d2: d2)
   3.233 -                } else if let d1 = m1.sent, let d2 = m2.sent {
   3.234 -                    return areInIncreasingOrder(d1: d1, d2: d2)
   3.235 -                }
   3.236 -                return false
   3.237 -            }
   3.238 -        }
   3.239 -        var messagesByID = [MessageID: [Message]]()
   3.240 -        var changedMessagesByID = [MessageID: Message]()
   3.241 -
   3.242 -        var hasChangedMessages: Bool {
   3.243 -            return !changedMessagesByID.isEmpty
   3.244 -        }
   3.245 -
   3.246 -        func contains(messageID: MessageID) -> Bool {
   3.247 -            return messagesByID[messageID] != nil
   3.248 -        }
   3.249 -
   3.250 -        func areInIncreasingOrder(d1: Date, d2: Date) -> Bool {
   3.251 -            switch d1.compare(d2 as Date) {
   3.252 -            case .orderedAscending: return true
   3.253 -            default: return false
   3.254 -            }
   3.255 -        }
   3.256 -
   3.257 -        func add(message: Message) {
   3.258 -            if let existing = messagesByID[message.uuid] {
   3.259 -                var news = existing
   3.260 -                news.append(message)
   3.261 -                messagesByID[message.uuid] = news
   3.262 -            } else {
   3.263 -                messagesByID[message.uuid] = [message]
   3.264 -            }
   3.265 -        }
   3.266 -
   3.267 -        func didUpdate(message: Message) {
   3.268 -            // messages has been changed during the test
   3.269 -            XCTAssertNotNil(messagesByID[message.messageID])
   3.270 -            add(message: message)
   3.271 -            changedMessagesByID[message.messageID] = message
   3.272 -        }
   3.273 -
   3.274 -        func didDelete(message: Message) {
   3.275 -            // this message has been deleted from the start, ignore
   3.276 -        }
   3.277 -
   3.278 -        func didCreate(message: Message) {
   3.279 -            add(message: message)
   3.280 -        }
   3.281 -    }
   3.282 -}
     4.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.2 +++ b/pEpForiOSTests/ReplicationServiceTests.swift	Thu Apr 18 11:56:49 2019 +0200
     4.3 @@ -0,0 +1,279 @@
     4.4 +//
     4.5 +//  ReplicationServiceTests.swift
     4.6 +//  pEpForiOS
     4.7 +//
     4.8 +//  Created by hernani on 23/11/16.
     4.9 +//  Copyright © 2016 p≡p Security S.A. All rights reserved.
    4.10 +//
    4.11 +
    4.12 +import XCTest
    4.13 +
    4.14 +import MessageModel
    4.15 +@testable import pEpForiOS
    4.16 +
    4.17 +class ReplicationServiceTests: XCTestCase {
    4.18 +    var persistenceSetup: PersistentSetup!
    4.19 +
    4.20 +    override func setUp() {
    4.21 +        super.setUp()
    4.22 +        persistenceSetup = PersistentSetup()
    4.23 +    }
    4.24 +
    4.25 +    override func tearDown() {
    4.26 +        persistenceSetup = nil
    4.27 +        super.tearDown()
    4.28 +    }
    4.29 +
    4.30 +    func testSyncOutgoing() {
    4.31 +        testSyncOutgoing(useCorrectSmtpAccount: true)
    4.32 +    }
    4.33 +
    4.34 +    func testSyncOutgoingWithWrongAccount() {
    4.35 +        testSyncOutgoing(useCorrectSmtpAccount: false)
    4.36 +    }
    4.37 +
    4.38 +    func testSyncOneTime() {
    4.39 +        XCTAssertNil(CdAccount.all())
    4.40 +        XCTAssertNil(CdFolder.all())
    4.41 +        XCTAssertNil(CdMessage.all())
    4.42 +
    4.43 +        let modelDelegate = MessageModelObserver()
    4.44 +        MessageModelConfig.messageFolderDelegate = modelDelegate
    4.45 +
    4.46 +        let replicationService = ReplicationService(parentName: #function)
    4.47 +
    4.48 +        let del = NetworkServiceObserver(
    4.49 +            expAccountsSynced: expectation(description: "expSingleAccountSynced"))
    4.50 +        replicationService.unitTestDelegate = del
    4.51 +        replicationService.delegate = del
    4.52 +
    4.53 +        _ = SecretTestData().createWorkingCdAccount()
    4.54 +        Record.saveAndWait()
    4.55 +
    4.56 +        replicationService.start()
    4.57 +
    4.58 +        waitForExpectations(timeout: TestUtil.waitTime, handler: { error in
    4.59 +            XCTAssertNil(error)
    4.60 +        })
    4.61 +
    4.62 +        XCTAssertNotNil(del.accountInfo)
    4.63 +        XCTAssertNotNil(CdFolder.all())
    4.64 +
    4.65 +        guard let cdFolder = CdFolder.first(
    4.66 +            attributes: ["folderTypeRawValue": FolderType.inbox.rawValue]) else {
    4.67 +                XCTFail()
    4.68 +                return
    4.69 +        }
    4.70 +        XCTAssertGreaterThanOrEqual(cdFolder.messages?.count ?? 0, 0)
    4.71 +        let allCdMessages = cdFolder.messages?.sortedArray(
    4.72 +            using: [NSSortDescriptor(key: "uid", ascending: true)]) as? [CdMessage] ?? []
    4.73 +        XCTAssertGreaterThanOrEqual(allCdMessages.count, 0)
    4.74 +
    4.75 +        for cdMsg in allCdMessages {
    4.76 +            guard let parentF = cdMsg.parent else {
    4.77 +                XCTFail()
    4.78 +                continue
    4.79 +            }
    4.80 +            XCTAssertEqual(parentF.folderType, FolderType.inbox)
    4.81 +        }
    4.82 +
    4.83 +        let unifiedInbox = UnifiedInbox()
    4.84 +
    4.85 +        let unifiedMessageCount = unifiedInbox.messageCount()
    4.86 +        XCTAssertGreaterThanOrEqual(unifiedMessageCount, 0)
    4.87 +        for i in 0..<unifiedMessageCount {
    4.88 +            guard let msg = unifiedInbox.messageAt(index: i) else {
    4.89 +                XCTFail()
    4.90 +                continue
    4.91 +            }
    4.92 +
    4.93 +            XCTAssertTrue(msg.isValidMessage())
    4.94 +
    4.95 +            let pEpRating = Int16(msg.pEpRatingInt ?? -1)
    4.96 +            XCTAssertNotEqual(pEpRating, PEPUtil.pEpRatingNone)
    4.97 +            if !modelDelegate.contains(messageID: msg.messageID) {
    4.98 +                XCTFail()
    4.99 +            }
   4.100 +        }
   4.101 +
   4.102 +        let inbox = Folder.from(cdFolder: cdFolder)
   4.103 +        XCTAssertEqual(modelDelegate.messages.count, unifiedMessageCount)
   4.104 +
   4.105 +        for msg in modelDelegate.messages {
   4.106 +            let msgIsFlaggedDeleted = msg.imapFlags?.deleted ?? false
   4.107 +            XCTAssertTrue(!msgIsFlaggedDeleted)
   4.108 +            XCTAssertTrue(inbox.contains(message: msg))
   4.109 +            if !unifiedInbox.contains(message: msg) {
   4.110 +                XCTFail()
   4.111 +            }
   4.112 +        }
   4.113 +        XCTAssertFalse(modelDelegate.hasChangedMessages)
   4.114 +
   4.115 +        TestUtil.cancelReplicationServiceAndWait(replicationService: replicationService, testCase: self)
   4.116 +    }
   4.117 +
   4.118 +    func testCancelSyncImmediately() {
   4.119 +        XCTAssertNil(CdAccount.all())
   4.120 +        XCTAssertNil(CdFolder.all())
   4.121 +        XCTAssertNil(CdMessage.all())
   4.122 +
   4.123 +        let replicationService = ReplicationService(parentName: #function)
   4.124 +
   4.125 +        _ = SecretTestData().createWorkingCdAccount()
   4.126 +        Record.saveAndWait()
   4.127 +
   4.128 +        for _ in 0...10 {
   4.129 +            replicationService.start()
   4.130 +            TestUtil.cancelReplicationServiceAndWait(replicationService: replicationService, testCase: self)
   4.131 +        }
   4.132 +
   4.133 +        XCTAssertNil(CdFolder.all())
   4.134 +        XCTAssertNil(CdMessage.all())
   4.135 +    }
   4.136 +
   4.137 +    class MySelfObserver: KickOffMySelfProtocol {
   4.138 +        let expMySelfed: XCTestExpectation?
   4.139 +        let queue = LimitedOperationQueue()
   4.140 +        let backgrounder: MockBackgrounder
   4.141 +
   4.142 +        init(expMySelfed: XCTestExpectation?,
   4.143 +             expBackgroundTaskFinishedAtLeastOnce: XCTestExpectation?) {
   4.144 +            self.expMySelfed = expMySelfed
   4.145 +            backgrounder = MockBackgrounder(
   4.146 +                expBackgroundTaskFinishedAtLeastOnce: expBackgroundTaskFinishedAtLeastOnce)
   4.147 +        }
   4.148 +
   4.149 +        func startMySelf() {
   4.150 +            let op = MySelfOperation(parentName: #function, backgrounder: backgrounder)
   4.151 +            op.completionBlock = {
   4.152 +                op.completionBlock = nil
   4.153 +                self.expMySelfed?.fulfill()
   4.154 +            }
   4.155 +            queue.addOperation(op)
   4.156 +        }
   4.157 +    }
   4.158 +
   4.159 +    //MARK: HELPER
   4.160 +
   4.161 +    func testSyncOutgoing(useCorrectSmtpAccount: Bool) {
   4.162 +        XCTAssertNil(CdAccount.all())
   4.163 +        XCTAssertNil(CdFolder.all())
   4.164 +        XCTAssertNil(CdMessage.all())
   4.165 +
   4.166 +        let modelDelegate = MessageModelObserver()
   4.167 +        MessageModelConfig.messageFolderDelegate = modelDelegate
   4.168 +
   4.169 +        let cdAccount = useCorrectSmtpAccount ? SecretTestData().createWorkingCdAccount() :
   4.170 +            SecretTestData().createSmtpTimeOutCdAccount()
   4.171 +        Record.saveAndWait()
   4.172 +
   4.173 +        TestUtil.syncAndWait(testCase: self)
   4.174 +
   4.175 +        let from = CdIdentity.create()
   4.176 +        from.userName = cdAccount.identity?.userName ?? "Unit 004"
   4.177 +        from.address = cdAccount.identity?.address ?? "unittest.ios.4@peptest.ch"
   4.178 +
   4.179 +        let to = CdIdentity.create()
   4.180 +        to.userName = "Unit 001"
   4.181 +        to.address = "unittest.ios.1@peptest.ch"
   4.182 +
   4.183 +        guard let sentFolder = CdFolder.by(folderType: .sent, account: cdAccount) else {
   4.184 +            XCTFail()
   4.185 +            return
   4.186 +        }
   4.187 +        XCTAssertEqual((sentFolder.messages ?? NSSet()).count, 0)
   4.188 +
   4.189 +        let numMails = 1
   4.190 +        let outgoingMails = try! TestUtil.createOutgoingMails(
   4.191 +            cdAccount: cdAccount,
   4.192 +            testCase: self, numberOfMails: numMails)
   4.193 +        let outgoingMessageIDs: [String] = outgoingMails
   4.194 +            .map() { $0.messageID ?? "" }
   4.195 +            .filter() { $0 != "" }
   4.196 +
   4.197 +        // Verify outgoing mails
   4.198 +        for m in outgoingMails {
   4.199 +            XCTAssertEqual(m.parent?.folderType, FolderType.outbox)
   4.200 +            XCTAssertEqual(m.uid, Int32(0))
   4.201 +        }
   4.202 +
   4.203 +        TestUtil.syncAndWait(testCase: self)
   4.204 +
   4.205 +        // Check that the sent mails have been deleted
   4.206 +        Record.refreshRegisteredObjects(mergeChanges: true)
   4.207 +        if useCorrectSmtpAccount {
   4.208 +            for m in outgoingMails {
   4.209 +                XCTAssertTrue(m.isDeleted)
   4.210 +            }
   4.211 +        }
   4.212 +
   4.213 +        // sync
   4.214 +        TestUtil.syncAndWait(testCase: self)
   4.215 +
   4.216 +        if useCorrectSmtpAccount {
   4.217 +            // those messages do not exist if we are using an incorrect account
   4.218 +            TestUtil.checkForExistanceAndUniqueness(uuids: outgoingMessageIDs)
   4.219 +        }
   4.220 +    }
   4.221 +
   4.222 +    class MessageModelObserver: MessageFolderDelegate {
   4.223 +        var messages: [Message] {
   4.224 +            var messages = [Message]()
   4.225 +            for ms in messagesByID.values {
   4.226 +                for m in ms {
   4.227 +                    messages.append(m)
   4.228 +                }
   4.229 +            }
   4.230 +            return messages.sorted { m1, m2 in
   4.231 +                if let d1 = m1.received, let d2 = m2.received {
   4.232 +                    return areInIncreasingOrder(d1: d1, d2: d2)
   4.233 +                } else if let d1 = m1.sent, let d2 = m2.sent {
   4.234 +                    return areInIncreasingOrder(d1: d1, d2: d2)
   4.235 +                }
   4.236 +                return false
   4.237 +            }
   4.238 +        }
   4.239 +        var messagesByID = [MessageID: [Message]]()
   4.240 +        var changedMessagesByID = [MessageID: Message]()
   4.241 +
   4.242 +        var hasChangedMessages: Bool {
   4.243 +            return !changedMessagesByID.isEmpty
   4.244 +        }
   4.245 +
   4.246 +        func contains(messageID: MessageID) -> Bool {
   4.247 +            return messagesByID[messageID] != nil
   4.248 +        }
   4.249 +
   4.250 +        func areInIncreasingOrder(d1: Date, d2: Date) -> Bool {
   4.251 +            switch d1.compare(d2 as Date) {
   4.252 +            case .orderedAscending: return true
   4.253 +            default: return false
   4.254 +            }
   4.255 +        }
   4.256 +
   4.257 +        func add(message: Message) {
   4.258 +            if let existing = messagesByID[message.uuid] {
   4.259 +                var news = existing
   4.260 +                news.append(message)
   4.261 +                messagesByID[message.uuid] = news
   4.262 +            } else {
   4.263 +                messagesByID[message.uuid] = [message]
   4.264 +            }
   4.265 +        }
   4.266 +
   4.267 +        func didUpdate(message: Message) {
   4.268 +            // messages has been changed during the test
   4.269 +            XCTAssertNotNil(messagesByID[message.messageID])
   4.270 +            add(message: message)
   4.271 +            changedMessagesByID[message.messageID] = message
   4.272 +        }
   4.273 +
   4.274 +        func didDelete(message: Message) {
   4.275 +            // this message has been deleted from the start, ignore
   4.276 +        }
   4.277 +
   4.278 +        func didCreate(message: Message) {
   4.279 +            add(message: message)
   4.280 +        }
   4.281 +    }
   4.282 +}
     5.1 --- a/pEpForiOSTests/TestUtils/NetworkServiceObserver.swift	Thu Apr 18 11:53:56 2019 +0200
     5.2 +++ b/pEpForiOSTests/TestUtils/NetworkServiceObserver.swift	Thu Apr 18 11:56:49 2019 +0200
     5.3 @@ -12,7 +12,7 @@
     5.4  @testable import MessageModel
     5.5  @testable import pEpForiOS
     5.6  
     5.7 -class NetworkServiceObserver: NetworkServiceUnitTestDelegate, NetworkServiceDelegate, CustomDebugStringConvertible {
     5.8 +class NetworkServiceObserver: CustomDebugStringConvertible {
     5.9      let expAllSynced: XCTestExpectation?
    5.10      var expCanceled: XCTestExpectation?
    5.11      var accountInfo: AccountConnectInfo?
    5.12 @@ -34,10 +34,12 @@
    5.13          self.expCanceled = expCanceled
    5.14          self.failOnError = failOnError
    5.15      }
    5.16 +}
    5.17  
    5.18 -    // MARK: - NetworkServiceUnitTestDelegate
    5.19 +// MARK: - ReplicationServiceUnitTestDelegate
    5.20  
    5.21 -    func networkServiceDidSync(service: NetworkService, accountInfo: AccountConnectInfo,
    5.22 +extension NetworkServiceObserver: ReplicationServiceUnitTestDelegate {
    5.23 +    func replicationServiceDidSync(service: ReplicationService, accountInfo: AccountConnectInfo,
    5.24                   errorProtocol: ServiceErrorProtocol) {
    5.25          if errorProtocol.hasErrors() && failOnError {
    5.26              XCTFail()
    5.27 @@ -50,14 +52,15 @@
    5.28              expAllSynced?.fulfill()
    5.29          }
    5.30      }
    5.31 +}
    5.32  
    5.33 -    // MARK: - NetworkServiceDelegate
    5.34 -    
    5.35 -    func networkServiceDidFinishLastSyncLoop(service: NetworkService) {
    5.36 +// MARK: - ReplicationServiceDelegate
    5.37 +extension NetworkServiceObserver: ReplicationServiceDelegate {
    5.38 +    func replicationServiceDidFinishLastSyncLoop(service: ReplicationService) {
    5.39          // ignore
    5.40      }
    5.41  
    5.42 -    func networkServiceDidCancel(service: NetworkService) {
    5.43 +    func replicationServiceDidCancel(service: ReplicationService) {
    5.44          expCanceled?.fulfill()
    5.45      }
    5.46  }
     6.1 --- a/pEpForiOSTests/TestUtils/TestUtil.swift	Thu Apr 18 11:53:56 2019 +0200
     6.2 +++ b/pEpForiOSTests/TestUtils/TestUtil.swift	Thu Apr 18 11:56:49 2019 +0200
     6.3 @@ -229,34 +229,34 @@
     6.4      // MARK: - Sync Loop
     6.5  
     6.6      static public func syncAndWait(numAccountsToSync: Int = 1, testCase: XCTestCase) {
     6.7 -        let networkService = NetworkService()
     6.8 -        networkService.sleepTimeInSeconds = 0.1
     6.9 +        let replicationService = ReplicationService()
    6.10 +        replicationService.sleepTimeInSeconds = 0.1
    6.11  
    6.12          let expAccountsSynced = testCase.expectation(description: "allAccountsSynced")
    6.13 -        // A temp variable is necassary, since the networkServiceUnitTestDelegate is weak
    6.14 +        // A temp variable is necassary, since the replicationServiceUnitTestDelegate is weak
    6.15          let del = NetworkServiceObserver(numAccountsToSync: numAccountsToSync,
    6.16                                           expAccountsSynced: expAccountsSynced,
    6.17                                           failOnError: true)
    6.18  
    6.19 -        networkService.unitTestDelegate = del
    6.20 -        networkService.delegate = del
    6.21 -        networkService.start()
    6.22 +        replicationService.unitTestDelegate = del
    6.23 +        replicationService.delegate = del
    6.24 +        replicationService.start()
    6.25  
    6.26          let canTakeSomeTimeFactor = 3.0
    6.27          testCase.waitForExpectations(timeout: TestUtil.waitTime * canTakeSomeTimeFactor) { error in
    6.28              XCTAssertNil(error)
    6.29          }
    6.30  
    6.31 -        TestUtil.cancelNetworkServiceAndWait(networkService: networkService, testCase: testCase)
    6.32 +        TestUtil.cancelReplicationServiceAndWait(replicationService: replicationService, testCase: testCase)
    6.33      }
    6.34  
    6.35 -    // MARK: - NetworkService
    6.36 -    static public func cancelNetworkServiceAndWait(networkService: NetworkService, testCase: XCTestCase) {
    6.37 +    // MARK: - ReplicationService
    6.38 +    static public func cancelReplicationServiceAndWait(replicationService: ReplicationService, testCase: XCTestCase) {
    6.39          let del = NetworkServiceObserver(
    6.40              expCanceled: testCase.expectation(description: "expCanceled"))
    6.41 -        networkService.unitTestDelegate = del
    6.42 -        networkService.delegate = del
    6.43 -        networkService.cancel()
    6.44 +        replicationService.unitTestDelegate = del
    6.45 +        replicationService.delegate = del
    6.46 +        replicationService.cancel()
    6.47  
    6.48          // Wait for cancellation
    6.49          testCase.waitForExpectations(timeout: TestUtil.waitTime, handler: { error in
    6.50 @@ -603,7 +603,7 @@
    6.51      static func determineInterestingFolders(in cdAccount: CdAccount)
    6.52          -> [NetworkServiceWorker.FolderInfo] {
    6.53          let accountInfo = AccountConnectInfo(accountID: cdAccount.objectID)
    6.54 -        let dummyConfig = NetworkService.ServiceConfig(sleepTimeInSeconds: 1,
    6.55 +        let dummyConfig = ReplicationService.ServiceConfig(sleepTimeInSeconds: 1,
    6.56                                                         parentName: #function,
    6.57                                                         mySelfer:
    6.58              DefaultMySelfer(parentName: #function,