field_ios

In-the-field app for Radroots on iOS
git clone https://radroots.dev/git/field_ios.git
Log | Files | Refs | README | LICENSE

TeraAddMediaHarness.swift (3263B)


      1 import Foundation
      2 @testable import TeraApp
      3 
      4 actor AddMediaHarness: TeraAddMediaHandling {
      5   /// Metadata-only fake backend tests; real file durability has separate fixtures.
      6   func confirmDurableComposerMedia(_: [TeraComposerMedia]) {}
      7 
      8   private let delayFirstUpload: Bool
      9   private let delaySettlement: Bool
     10   private let openPause: ResourceTestPause?
     11   private let failOpen: Bool
     12   private let foreground: Bool
     13   private var uploadAttempts = 0
     14   private var settlementStarted = false
     15   private var settlements: [Bool] = []
     16   private var reconciliations = 0
     17   private(set) var openCount = 0
     18   private(set) var submissionReconciliations = 0
     19   private let item = TeraPreparedMedia(
     20     opaqueReference: "media:\(String(repeating: "0", count: 64))",
     21     remoteURL: nil,
     22     sha256: String(repeating: "0", count: 64),
     23     mediaType: "image/png",
     24     byteSize: 4,
     25     width: 2,
     26     height: 2,
     27     alt: "Carrots",
     28     preparedAtUnixSeconds: 1_800_000_000
     29   )
     30 
     31   init(delayFirstUpload: Bool = false, delaySettlement: Bool = false,
     32        openPause: ResourceTestPause? = nil, failOpen: Bool = false, foreground: Bool = false)
     33   {
     34     self.delayFirstUpload = delayFirstUpload
     35     self.delaySettlement = delaySettlement
     36     self.openPause = openPause
     37     self.failOpen = failOpen
     38     self.foreground = foreground
     39   }
     40 
     41   func prefersSharedForegroundUpload(ownerID _: String) -> Bool {
     42     foreground
     43   }
     44 
     45   func support() -> TeraAddMediaSupport {
     46     .init(library: true, camera: true)
     47   }
     48 
     49   func importImages(limit _: Int) -> [TeraPreparedMedia] {
     50     [item]
     51   }
     52 
     53   func captureImage() -> TeraPreparedMedia {
     54     item
     55   }
     56 
     57   func open(_ media: [TeraPreparedMedia]) async throws -> TeraOpenedMedia {
     58     openCount += 1
     59     await openPause?.wait()
     60     if failOpen {
     61       throw TeraComposerAcknowledgment.unconfirmed
     62     }
     63     return try TeraMediaFileFixture.open(media, bytes: Data(repeating: 0, count: 4))
     64   }
     65 
     66   func uploadInBackground(
     67     transfer job: TeraNativeTransferJob,
     68     media _: TeraPreparedMedia
     69   ) async throws -> TeraAddBackgroundUploadReceipt {
     70     uploadAttempts += 1
     71     if delayFirstUpload, uploadAttempts == 1 {
     72       try await Task.sleep(nanoseconds: 50_000_000)
     73     }
     74     return TeraAddBackgroundUploadReceipt(
     75       identifier: "radroots.add.\(job.ownerID).\(job.expectedRevision).\(job.operationID)",
     76       draftID: job.ownerID,
     77       expectedRevision: job.expectedRevision,
     78       statusCode: 200,
     79       mediaType: "application/json",
     80       contentEncoding: nil,
     81       body: Data("{}".utf8)
     82     )
     83   }
     84 
     85   func settleBackgroundUpload(identifier _: String, accepted: Bool) async throws {
     86     settlementStarted = true
     87     if delaySettlement {
     88       try await Task.sleep(nanoseconds: 50_000_000)
     89     }
     90     settlements.append(accepted)
     91   }
     92 
     93   func recoverNativeUploads(client _: TeraRuntimeClient) -> TeraNativeRecoveryProgress {
     94     reconciliations += 1
     95     return .init(visited: 0, remaining: 0, needsAttention: false)
     96   }
     97 
     98   func reconcileBackgroundSubmissions(_: [TeraSubmissionStatus], client _: TeraRuntimeClient) {
     99     submissionReconciliations += 1
    100   }
    101 
    102   func didBeginSettlement() -> Bool {
    103     settlementStarted
    104   }
    105 
    106   func settlementValues() -> [Bool] {
    107     settlements
    108   }
    109 
    110   func reconciliationCount() -> Int {
    111     reconciliations
    112   }
    113 }