TeraUploadRenewalLifecycleTests.swift (2643B)
1 import Foundation 2 import RadrootsKit 3 @testable import TeraApp 4 import XCTest 5 6 final class TeraUploadRenewalLifecycleTests: XCTestCase { 7 func testCallerDeadlineKeepsNativeReservationUntilLateWorkerReturns() async throws { 8 let fixture = try BackgroundUploadFixture() 9 defer { fixture.remove() } 10 let configuration = TeraRuntimeClientTests().makeConfiguration(generation: "35") 11 let backend = ResourceTestBackend(publicKeyHex: configuration.publicKeyHex) 12 let client = TeraRuntimeClient(factory: { _ in await backend.start() }, 13 deadlines: TeraRuntimeDeadlinePolicy(operationNanoseconds: 20_000_000)) 14 _ = try await client.start(configuration: configuration) 15 let request = try fixture.request(job: fixture.job(revision: 2, operation: String(repeating: "a", count: 32))) 16 let store = fixture.nativeStore 17 try await store.saveSnapshot(RadrootsBackgroundTransferSnapshot(request: request, state: .expired)) 18 let adapters = RadrootsAppleBackgroundTransferAdapters(enqueue: { _, _ in XCTFail("Unexpected enqueue") }, 19 cancel: { _ in XCTFail("Unexpected cancel") }, activeTransferIdentifiers: { [] }, handleBackgroundEvents: { _, done in done() }) 20 let transfer = RadrootsAppleBackgroundTransfer(store: store, adapters: adapters) 21 let other = RadrootsAppleBackgroundTransfer(store: fixture.nativeStore, adapters: adapters) 22 let pause = ResourceTestPause() 23 let task = Task { 24 try await client.withUploadRenewal { _ in 25 try await transfer.withInactiveExecution(for: request.identifier) { _ in 26 await pause.wait() 27 throw TeraComposerAcknowledgment.unconfirmed 28 } 29 } 30 } 31 await pause.entered.wait() 32 do { _ = try await task.value; XCTFail("Deadline must return to caller") } catch {} 33 do { _ = try await other.retry(request); XCTFail("Late worker must retain the old identifier") } catch {} 34 do { 35 _ = try await client.withUploadRenewal { _ in XCTFail("Duplicate worker admitted"); throw TeraComposerAcknowledgment.unconfirmed } 36 XCTFail("Submission admission must remain held") 37 } catch {} 38 await pause.resume.open() 39 _ = try await client.stop() 40 // Shutdown drains the actual worker before this new owner can acquire it. 41 let reopened = try await other.withInactiveExecution(for: request.identifier) { snapshot in snapshot?.identifier } 42 XCTAssertEqual(reopened, request.identifier) 43 let snapshot = try await store.loadSnapshots().first { $0.identifier == request.identifier } 44 XCTAssertEqual(snapshot?.state, .expired) 45 } 46 }