Skip to content

Commit

Permalink
Add test for network listener (#411)
Browse files Browse the repository at this point in the history
  • Loading branch information
lucas34 authored Jun 29, 2022
1 parent c75282d commit 3fc7447
Show file tree
Hide file tree
Showing 2 changed files with 94 additions and 22 deletions.
74 changes: 52 additions & 22 deletions Sources/SwiftQueue/Constraint+Network.swift
Original file line number Diff line number Diff line change
Expand Up @@ -33,37 +33,28 @@ public enum NetworkType: Int, Codable {
case wifi = 2
}

internal final class NetworkConstraint: SimpleConstraint, CodableConstraint {
internal protocol NetworkMonitor {

/// Require a certain connectivity type
internal let networkType: NetworkType
func hasCorrectNetworkType(require: NetworkType) -> Bool

private var monitor: NWPathMonitor?
func startMonitoring(networkType: NetworkType, operation: SqOperation)

required init(networkType: NetworkType) {
assert(networkType != .any)
self.networkType = networkType
}
}

convenience init?(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: NetworkConstraintKey.self)
if container.contains(.requireNetwork) {
try self.init(networkType: container.decode(NetworkType.self, forKey: .requireNetwork))
} else { return nil }
}
internal class NWPathMonitorNetworkMonitor: NetworkMonitor {

override func willSchedule(queue: SqOperationQueue, operation: SqOperation) throws {
assert(operation.dispatchQueue != .main)
self.monitor = NWPathMonitor()
}

override func run(operation: SqOperation) -> Bool {
guard let monitor = monitor else { return true }
private let monitor = NWPathMonitor()

func hasCorrectNetworkType(require: NetworkType) -> Bool {
if monitor.currentPath.status == .satisfied {
monitor.pathUpdateHandler = nil
return true
} else {
return false
}
}

func startMonitoring(networkType: NetworkType, operation: SqOperation) {
monitor.pathUpdateHandler = { [monitor, operation, networkType] path in
guard path.status == .satisfied else {
operation.logger.log(.verbose, jobId: operation.name, message: "Unsatisfied network requirement")
Expand All @@ -81,8 +72,47 @@ internal final class NetworkConstraint: SimpleConstraint, CodableConstraint {
monitor.pathUpdateHandler = nil
operation.run()
}

monitor.start(queue: operation.dispatchQueue)
}


}


internal final class NetworkConstraint: SimpleConstraint, CodableConstraint {

/// Require a certain connectivity type
internal let networkType: NetworkType

private let monitor: NetworkMonitor

required init(networkType: NetworkType, monitor: NetworkMonitor) {
assert(networkType != .any)
self.networkType = networkType
self.monitor = monitor
}

convenience init(networkType: NetworkType) {
self.init(networkType: networkType, monitor: NWPathMonitorNetworkMonitor())
}

convenience init?(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: NetworkConstraintKey.self)
if container.contains(.requireNetwork) {
try self.init(networkType: container.decode(NetworkType.self, forKey: .requireNetwork))
} else { return nil }
}

override func willSchedule(queue: SqOperationQueue, operation: SqOperation) throws {
assert(operation.dispatchQueue != .main)
}

override func run(operation: SqOperation) -> Bool {
if monitor.hasCorrectNetworkType(require: networkType) {
return true
}

monitor.startMonitoring(networkType: networkType, operation: operation)
return false
}

Expand Down
42 changes: 42 additions & 0 deletions Tests/SwiftQueueTests/ConstraintTest+Network.swift
Original file line number Diff line number Diff line change
Expand Up @@ -54,4 +54,46 @@ class ConstraintTestNetwork: XCTestCase {
job.assertSingleCompletion()
}

func testNetworkWaitUntilAvailable() {
let (type, job) = (UUID().uuidString, TestJob())

let creator = TestCreator([type: job])
let semaphore = DispatchSemaphore(value: 0)

let manager = SwiftQueueManagerBuilder(creator: creator).set(persister: NoPersister.shared).build()
JobBuilder(type: type)
.add(constraint: NetworkConstraint(networkType: .wifi, monitor: TestNetworkMonitor(semaphore: semaphore)))
.schedule(manager: manager)

job.assertNoRun()

semaphore.signal()

job.awaitForRemoval()
job.assertSingleCompletion()
}

}

internal class TestNetworkMonitor: NetworkMonitor {

private let semaphore: DispatchSemaphore

private var hasNetworkChanged = false

required init(semaphore: DispatchSemaphore) {
self.semaphore = semaphore
}

func hasCorrectNetworkType(require: NetworkType) -> Bool {
hasNetworkChanged
}

func startMonitoring(networkType: NetworkType, operation: SqOperation) {
operation.dispatchQueue.async { [weak self] in
self?.semaphore.wait()
self?.hasNetworkChanged = true
operation.run()
}
}
}

0 comments on commit 3fc7447

Please sign in to comment.