@@ -7,6 +7,34 @@ import XCTest
77@testable import IterableSDK
88
99class TaskRunnerTests : XCTestCase {
10+ private final class WeakBox < T: AnyObject > {
11+ weak var value : T ?
12+
13+ init ( _ value: T ? ) {
14+ self . value = value
15+ }
16+ }
17+
18+ private final class LifecycleNetworkMonitor : NetworkMonitorProtocol {
19+ var statusUpdatedCallback : ( ( ) -> Void ) ?
20+ private( set) var startCount = 0
21+ private( set) var stopCount = 0
22+
23+ func start( ) {
24+ startCount += 1
25+ }
26+
27+ func stop( ) {
28+ stopCount += 1
29+ }
30+ }
31+
32+ private final class ImmediatePersistenceContext : MockPersistenceContext {
33+ override func perform( _ block: @escaping ( ) -> Void ) {
34+ block ( )
35+ }
36+ }
37+
1038 override func setUpWithError( ) throws {
1139 try super. setUpWithError ( )
1240
@@ -271,6 +299,58 @@ class TaskRunnerTests: XCTestCase {
271299 verifyTaskIsExecuted ( notificationCenter, withinInterval: 10.0 )
272300 taskRunner. stop ( )
273301 }
302+
303+ func testForegroundBackgroundCyclingDoesNotLeakConnectivityLifecycle( ) throws {
304+ let weakMonitor = WeakBox < LifecycleNetworkMonitor > ( nil )
305+ let weakManager = WeakBox < NetworkConnectivityManager > ( nil )
306+ let weakTaskRunner = WeakBox < IterableTaskRunner > ( nil )
307+
308+ autoreleasepool {
309+ let networkSession = MockNetworkSession ( )
310+ let checker = NetworkConnectivityChecker ( networkSession: networkSession)
311+ let monitor = LifecycleNetworkMonitor ( )
312+ weakMonitor. value = monitor
313+ let notificationCenter = MockNotificationCenter ( )
314+ let persistenceContextProvider = MockPersistenceContextProvider ( context: ImmediatePersistenceContext ( ) )
315+ let manager = NetworkConnectivityManager ( networkMonitor: monitor,
316+ connectivityChecker: checker,
317+ notificationCenter: notificationCenter,
318+ offlineModePollingInterval: 600 ,
319+ onlineModePollingInterval: 600 )
320+ weakManager. value = manager
321+
322+ let healthMonitor = HealthMonitor ( dataProvider: HealthMonitorDataProvider ( maxTasks: 1000 ,
323+ persistenceContextProvider: persistenceContextProvider) ,
324+ dateProvider: SystemDateProvider ( ) ,
325+ networkSession: networkSession)
326+ let taskRunner = IterableTaskRunner ( networkSession: networkSession,
327+ persistenceContextProvider: persistenceContextProvider,
328+ healthMonitor: healthMonitor,
329+ notificationCenter: notificationCenter,
330+ timeInterval: 600 ,
331+ connectivityManager: manager)
332+ weakTaskRunner. value = taskRunner
333+
334+ taskRunner. start ( )
335+ XCTAssertEqual ( monitor. startCount, 1 )
336+
337+ for cycleIndex in 1 ... 3 {
338+ notificationCenter. post ( name: UIApplication . didEnterBackgroundNotification, object: nil , userInfo: nil )
339+ XCTAssertEqual ( monitor. stopCount, cycleIndex)
340+
341+ notificationCenter. post ( name: UIApplication . willEnterForegroundNotification, object: nil , userInfo: nil )
342+ XCTAssertEqual ( monitor. startCount, cycleIndex + 1 )
343+ }
344+
345+ taskRunner. stop ( )
346+ XCTAssertEqual ( monitor. stopCount, 4 )
347+ XCTAssertNil ( monitor. statusUpdatedCallback)
348+ }
349+
350+ XCTAssertNil ( weakTaskRunner. value)
351+ XCTAssertNil ( weakManager. value)
352+ XCTAssertNil ( weakMonitor. value)
353+ }
274354
275355 func testSentAtInHeader( ) throws {
276356 let date = Date ( )
0 commit comments