apple_kit

Apple-native services for Radroots iOS and macOS apps
git clone https://radroots.dev/git/apple_kit.git
Log | Files | Refs | README

RadrootsBackgroundTransferTesting.swift (5533B)


      1 import Foundation
      2 import RadrootsKit
      3 
      4 public actor RadrootsInMemoryBackgroundTransferStore: RadrootsBackgroundTransferStore {
      5     private var snapshotsByIdentifier: [RadrootsBackgroundTransferIdentifier: RadrootsBackgroundTransferSnapshot]
      6 
      7     public init(snapshots: [RadrootsBackgroundTransferSnapshot] = []) {
      8         self.snapshotsByIdentifier = Dictionary(uniqueKeysWithValues: snapshots.map { ($0.identifier, $0) })
      9     }
     10 
     11     public func loadSnapshots() async throws -> [RadrootsBackgroundTransferSnapshot] {
     12         snapshotsByIdentifier.values.sorted { left, right in
     13             left.identifier < right.identifier
     14         }
     15     }
     16 
     17     public func saveSnapshot(_ snapshot: RadrootsBackgroundTransferSnapshot) async throws {
     18         snapshotsByIdentifier[snapshot.identifier] = snapshot
     19     }
     20 
     21     public func removeSnapshot(for identifier: RadrootsBackgroundTransferIdentifier) async throws {
     22         snapshotsByIdentifier.removeValue(forKey: identifier)
     23     }
     24 
     25     public func removeAllSnapshots() async throws {
     26         snapshotsByIdentifier.removeAll()
     27     }
     28 }
     29 
     30 public actor RadrootsFakeBackgroundTransfer: RadrootsBackgroundTransfer {
     31     private let store: any RadrootsBackgroundTransferStore
     32     private var enqueueOutcome: Result<Void, RadrootsBackgroundTransferError>
     33     private var enqueuedRequestsValue: [RadrootsBackgroundTransferRequest]
     34     private var cancelledIdentifiersValue: [RadrootsBackgroundTransferIdentifier]
     35     private var handledBackgroundEventIdentifiersValue: [String]
     36     private let updatedAt: Date
     37 
     38     public init(
     39         store: any RadrootsBackgroundTransferStore = RadrootsInMemoryBackgroundTransferStore(),
     40         enqueueOutcome: Result<Void, RadrootsBackgroundTransferError> = .success(()),
     41         updatedAt: Date = Date(timeIntervalSince1970: 0)
     42     ) {
     43         self.store = store
     44         self.enqueueOutcome = enqueueOutcome
     45         self.enqueuedRequestsValue = []
     46         self.cancelledIdentifiersValue = []
     47         self.handledBackgroundEventIdentifiersValue = []
     48         self.updatedAt = updatedAt
     49     }
     50 
     51     public func setEnqueueOutcome(_ outcome: Result<Void, RadrootsBackgroundTransferError>) {
     52         enqueueOutcome = outcome
     53     }
     54 
     55     public func enqueue(_ request: RadrootsBackgroundTransferRequest) async throws -> RadrootsBackgroundTransferHandle {
     56         enqueuedRequestsValue.append(request)
     57         switch enqueueOutcome {
     58         case .success:
     59             let snapshot = try RadrootsBackgroundTransferSnapshot(
     60                 request: request,
     61                 state: .queued,
     62                 updatedAt: updatedAt
     63             )
     64             try await store.saveSnapshot(snapshot)
     65             return RadrootsBackgroundTransferHandle(request: request)
     66         case .failure(let error):
     67             throw error
     68         }
     69     }
     70 
     71     public func cancel(_ identifier: RadrootsBackgroundTransferIdentifier) async throws {
     72         cancelledIdentifiersValue.append(identifier)
     73         if let existing = try await store.loadSnapshots().first(where: { $0.identifier == identifier }) {
     74             let snapshot = try RadrootsBackgroundTransferSnapshot(
     75                 request: existing.request,
     76                 state: .cancelled,
     77                 progress: existing.progress,
     78                 updatedAt: updatedAt
     79             )
     80             try await store.saveSnapshot(snapshot)
     81         }
     82     }
     83 
     84     public func complete(_ identifier: RadrootsBackgroundTransferIdentifier) async throws {
     85         guard let existing = try await store.loadSnapshots().first(where: { $0.identifier == identifier }) else {
     86             throw RadrootsBackgroundTransferError.transferFailure("background transfer snapshot not found")
     87         }
     88         let snapshot = try RadrootsBackgroundTransferSnapshot(
     89             request: existing.request,
     90             state: .completed,
     91             progress: existing.progress,
     92             updatedAt: updatedAt
     93         )
     94         try await store.saveSnapshot(snapshot)
     95     }
     96 
     97     public func fail(_ identifier: RadrootsBackgroundTransferIdentifier, message: String) async throws {
     98         guard let existing = try await store.loadSnapshots().first(where: { $0.identifier == identifier }) else {
     99             throw RadrootsBackgroundTransferError.transferFailure("background transfer snapshot not found")
    100         }
    101         let snapshot = try RadrootsBackgroundTransferSnapshot(
    102             request: existing.request,
    103             state: .failed,
    104             progress: existing.progress,
    105             errorMessage: message,
    106             updatedAt: updatedAt
    107         )
    108         try await store.saveSnapshot(snapshot)
    109     }
    110 
    111     public func snapshot(for identifier: RadrootsBackgroundTransferIdentifier) async throws -> RadrootsBackgroundTransferSnapshot? {
    112         try await store.loadSnapshots().first { $0.identifier == identifier }
    113     }
    114 
    115     public func snapshots() async throws -> [RadrootsBackgroundTransferSnapshot] {
    116         try await store.loadSnapshots()
    117     }
    118 
    119     public func handleEventsForBackgroundURLSession(
    120         identifier: String,
    121         completionHandler: @escaping @Sendable () -> Void
    122     ) async {
    123         handledBackgroundEventIdentifiersValue.append(identifier)
    124         completionHandler()
    125     }
    126 
    127     public var enqueuedRequests: [RadrootsBackgroundTransferRequest] {
    128         enqueuedRequestsValue
    129     }
    130 
    131     public var cancelledIdentifiers: [RadrootsBackgroundTransferIdentifier] {
    132         cancelledIdentifiersValue
    133     }
    134 
    135     public var handledBackgroundEventIdentifiers: [String] {
    136         handledBackgroundEventIdentifiersValue
    137     }
    138 }