apple_kit

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

RadrootsInactiveExecutionTests.swift (8551B)


      1 import Foundation
      2 @testable import RadrootsKit
      3 import RadrootsKitTesting
      4 import Testing
      5 
      6 @Test func inactiveExecutionRefusesActiveTerminalSnapshots() async throws {
      7     let request = try appleUploadRequest(identifier: "renewal.active")
      8     for state: RadrootsBackgroundTransferState in [.failed, .expired, .cancelled, .interrupted] {
      9         let snapshot = try RadrootsBackgroundTransferSnapshot(request: request, state: state, executionID: UUID())
     10         let store = RadrootsInMemoryBackgroundTransferStore(snapshots: [snapshot])
     11         let probe = RadrootsAppleBackgroundTransferProbe(activeIdentifiers: [request.identifier])
     12         let transfer = RadrootsAppleBackgroundTransfer(store: store, adapters: probe.adapters())
     13         let called = RadrootsCompletionProbe()
     14         await #expect(throws: RadrootsBackgroundTransferError.transferFailure) {
     15             try await transfer.withInactiveExecution(for: request.identifier) { _ in called.markCompleted() }
     16         }
     17         #expect(!called.completed)
     18         #expect(try await store.loadSnapshots() == [snapshot])
     19         #expect(await probe.enqueuedRequests.isEmpty)
     20         #expect(await probe.cancelledIdentifiers.isEmpty)
     21         #expect(try await !store.admissionIsActive(for: request.identifier))
     22     }
     23 }
     24 
     25 @Test func inactiveExecutionRefusesUnreconciledOrReceiptedSnapshots() async throws {
     26     let request = try appleUploadRequest(identifier: "renewal.receipt")
     27     for state: RadrootsBackgroundTransferState in [.queued, .running, .awaitingVerification, .completed] {
     28         let snapshot = try RadrootsBackgroundTransferSnapshot(request: request, state: state)
     29         let store = RadrootsInMemoryBackgroundTransferStore(snapshots: [snapshot])
     30         let transfer = RadrootsAppleBackgroundTransfer(store: store, adapters: RadrootsAppleBackgroundTransferProbe().adapters())
     31         let called = RadrootsCompletionProbe()
     32         await #expect(throws: RadrootsBackgroundTransferError.transferFailure) {
     33             try await transfer.withInactiveExecution(for: request.identifier) { _ in called.markCompleted() }
     34         }
     35         #expect(!called.completed)
     36         #expect(try await store.loadSnapshots() == [snapshot])
     37     }
     38 }
     39 
     40 @Test func inactiveExecutionUnknownInventoryPreservesEvidence() async throws {
     41     let request = try appleUploadRequest(identifier: "renewal.unknown")
     42     let snapshot = try RadrootsBackgroundTransferSnapshot(request: request, state: .expired)
     43     let store = RadrootsInMemoryBackgroundTransferStore(snapshots: [snapshot])
     44     let called = RadrootsCompletionProbe()
     45     let transfer = RadrootsAppleBackgroundTransfer(store: store, adapters: .unavailable)
     46     await #expect(throws: RadrootsBackgroundTransferError.unavailable) {
     47         try await transfer.withInactiveExecution(for: request.identifier) { _ in called.markCompleted() }
     48     }
     49     #expect(!called.completed)
     50     #expect(try await store.loadSnapshots() == [snapshot])
     51     #expect(try await !store.admissionIsActive(for: request.identifier))
     52 }
     53 
     54 @Test func inactiveExecutionSuppliesExactRedactedSnapshotOrAbsenceThroughExistential() async throws {
     55     let request = try appleUploadRequest(identifier: "renewal.inactive")
     56     let snapshot = try RadrootsBackgroundTransferSnapshot(request: request, state: .expired, executionID: UUID())
     57     for snapshots in [[], [snapshot]] {
     58         let store = RadrootsInMemoryBackgroundTransferStore(snapshots: snapshots)
     59         let probe = RadrootsAppleBackgroundTransferProbe()
     60         let transfer: any RadrootsBackgroundTransfer = RadrootsAppleBackgroundTransfer(store: store, adapters: probe.adapters())
     61         let result = try await transfer.withInactiveExecution(for: request.identifier) { observed in
     62             #expect(observed == snapshots.first)
     63             let reserved = try await store.admissionIsActive(for: request.identifier)
     64             #expect(reserved)
     65             return "caller-result"
     66         }
     67         #expect(result == "caller-result")
     68         #expect(try await store.loadSnapshots() == snapshots)
     69         #expect(await probe.enqueuedRequests.isEmpty)
     70         #expect(await probe.cancelledIdentifiers.isEmpty)
     71         #expect(try await !store.admissionIsActive(for: request.identifier))
     72     }
     73 }
     74 
     75 @Test func inactiveExecutionFencesIndependentOwnersAndRetainsLateReceipt() async throws {
     76     let roots = try appleTransferRoots()
     77     defer { try? FileManager.default.removeItem(at: roots.dataRoot.deletingLastPathComponent()) }
     78     let request = try appleUploadRequest(identifier: "renewal.exclusive")
     79     let snapshot = try RadrootsBackgroundTransferSnapshot(request: request, state: .interrupted, executionID: UUID())
     80     let late = try snapshot.transitioned(to: .awaitingVerification, at: Date())
     81     let firstStore = RadrootsAppleBackgroundTransferStore(roots: roots)
     82     let otherStore = RadrootsAppleBackgroundTransferStore(roots: roots)
     83     try await firstStore.saveSnapshot(snapshot)
     84     let probe = RadrootsAppleBackgroundTransferProbe()
     85     let first = RadrootsAppleBackgroundTransfer(store: firstStore, adapters: probe.adapters())
     86     let other = RadrootsAppleBackgroundTransfer(store: otherStore, adapters: probe.adapters())
     87     let result = try await first.withInactiveExecution(for: request.identifier) { observed in
     88         #expect(observed == snapshot)
     89         await #expect(throws: RadrootsBackgroundTransferError.invalidRequest) { _ = try await other.retry(request) }
     90         await #expect(throws: RadrootsBackgroundTransferError.invalidRequest) {
     91             try await other.withInactiveExecution(for: request.identifier) { _ in Issue.record("Competing renewal admitted") }
     92         }
     93         await #expect(throws: RadrootsBackgroundTransferError.invalidRequest) { _ = try await first.retry(request) }
     94         // Delegate persistence remains available during the long reservation.
     95         let retained = try await otherStore.compareExchangeSnapshot(expected: snapshot, desired: late)
     96         #expect(retained)
     97         return 42
     98     }
     99     #expect(result == 42)
    100     #expect(try await otherStore.loadSnapshots() == [late])
    101     #expect(try await !otherStore.admissionIsActive(for: request.identifier))
    102     #expect(await probe.enqueuedRequests.isEmpty)
    103     await #expect(throws: RadrootsBackgroundTransferError.transferFailure) {
    104         try await other.withInactiveExecution(for: request.identifier) { _ in Issue.record("Receipt discarded") }
    105     }
    106 }
    107 
    108 @Test func inactiveExecutionCallerDenialReleasesAdmissionAndPreservesError() async throws {
    109     let request = try appleUploadRequest(identifier: "renewal.denied")
    110     let snapshot = try RadrootsBackgroundTransferSnapshot(request: request, state: .expired)
    111     let store = RadrootsInMemoryBackgroundTransferStore(snapshots: [snapshot])
    112     let probe = RadrootsAppleBackgroundTransferProbe()
    113     let transfer = RadrootsAppleBackgroundTransfer(store: store, adapters: probe.adapters())
    114     await #expect(throws: RenewalTestDenial.denied) {
    115         try await transfer.withInactiveExecution(for: request.identifier) { _ in throw RenewalTestDenial.denied }
    116     }
    117     #expect(try await store.loadSnapshots() == [snapshot])
    118     #expect(try await !store.admissionIsActive(for: request.identifier))
    119     _ = try await transfer.retry(request)
    120     #expect(await probe.enqueuedRequests == [request])
    121 }
    122 
    123 @Test func inactiveExecutionCancellationDuringQueryNeverCallsBody() async throws {
    124     let request = try appleUploadRequest(identifier: "renewal.cancelled-query")
    125     let store = RadrootsInMemoryBackgroundTransferStore()
    126     let called = RadrootsCompletionProbe()
    127     let (entered, signal) = AsyncStream<Void>.makeStream()
    128     let transfer = RadrootsAppleBackgroundTransfer(store: store, adapters: RadrootsAppleBackgroundTransferAdapters(
    129         enqueue: { _, _ in Issue.record("Unexpected enqueue") }, cancel: { _ in Issue.record("Unexpected cancel") },
    130         activeTransferIdentifiers: {
    131             try await RadrootsBackgroundTaskQuery.read { _ in signal.yield(); signal.finish() }
    132         }, handleBackgroundEvents: { _, completion in completion() }
    133     ))
    134     let task = Task { try await transfer.withInactiveExecution(for: request.identifier) { _ in called.markCompleted() } }
    135     for await _ in entered {
    136         break
    137     }
    138     task.cancel()
    139     await #expect(throws: RadrootsBackgroundTransferError.transferFailure) { try await task.value }
    140     #expect(!called.completed)
    141     #expect(try await !store.admissionIsActive(for: request.identifier))
    142     #expect(try await store.loadSnapshots().isEmpty)
    143 }
    144 
    145 private enum RenewalTestDenial: Error, Equatable { case denied }