field_ios

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

TeraPublicationRetryTests.swift (3837B)


      1 import Foundation
      2 @testable import TeraApp
      3 import TeraKitBindings
      4 import XCTest
      5 
      6 @MainActor
      7 final class TeraPublicationRetryTests: XCTestCase {
      8   func testTypedDecisionsRetainSpecificActionAndWaitingReasons() throws {
      9     let cases: [(FfiPublicationActionReason, TeraPublicationActionReason)] = [
     10       (.deadlineExceeded, .deadlineExceeded), (.attemptLimit, .attemptLimit),
     11       (.authenticationRequired, .authenticationRequired), (.quotaExceeded, .quotaExceeded),
     12       (.invalidPayload, .invalidPayload), (.deliveryRefused, .deliveryRefused),
     13       (.coordinateChanged, .coordinateChanged),
     14     ]
     15     for (wire, expected) in cases {
     16       let decoded = try TeraPublicationRetry.decode(.needsAction(reason: wire))
     17       XCTAssertEqual(decoded, .needsAction(expected))
     18       XCTAssertFalse(decoded.mayStart)
     19       XCTAssertTrue(decoded.explanation?.contains("retain") == true)
     20     }
     21     XCTAssertTrue(try TeraPublicationRetry.decode(.ready).mayStart)
     22     XCTAssertFalse(try TeraPublicationRetry.decode(.complete).mayStart)
     23     XCTAssertFalse(try TeraPublicationRetry.decode(.stopped).mayStart)
     24     XCTAssertEqual(try TeraPublicationRetry.decode(.deferredUntil(unixMs: 100)), .deferredUntil(100))
     25     XCTAssertEqual(try TeraPublicationRetry.decode(.inFlightUntil(unixMs: 100)), .inFlightUntil(100))
     26     // A native clock cannot substitute for a fresh Rust scheduling decision.
     27     XCTAssertFalse(TeraPublicationRetry.deferredUntil(1).mayStart)
     28     XCTAssertFalse(TeraPublicationRetry.inFlightUntil(1).mayStart)
     29   }
     30 
     31   func testMalformedWaitingBoundsFailClosed() {
     32     for value in [UInt64(0), UInt64.max] {
     33       XCTAssertThrowsError(try TeraPublicationRetry.decode(.deferredUntil(unixMs: value)))
     34       XCTAssertThrowsError(try TeraPublicationRetry.decode(.inFlightUntil(unixMs: value)))
     35     }
     36   }
     37 
     38   func testNeedsActionAndWaitDoNotAdvanceAStillQueuedSubmission() async throws {
     39     let backend = AddBackend(advanceOffline: true)
     40     let client = try await TeraAddStoreTests.startedClient(backend)
     41     let store = TeraAddStore(runtimeClient: client)
     42     await store.configure(snapshot: backend.snapshot())
     43     await store.start()
     44     store.updateForm(\.content, "Saved original")
     45     await store.submit()
     46     let original = try XCTUnwrap(store.submissions.status)
     47     XCTAssertEqual(original.state, .queued)
     48     let before = await backend.submissionBackend.advanceCount
     49     let decisions: [TeraPublicationRetry] = [
     50       .deferredUntil(1), .inFlightUntil(1), .needsAction(.deadlineExceeded), .needsAction(.attemptLimit),
     51       .needsAction(.authenticationRequired), .needsAction(.quotaExceeded),
     52       .needsAction(.invalidPayload), .needsAction(.deliveryRefused),
     53       .needsAction(.coordinateChanged),
     54     ]
     55     for decision in decisions {
     56       let status = TeraSubmissionStatus(
     57         request: original.request, intentID: original.intentID, operationID: original.operationID,
     58         revision: original.revision, captured: original.captured, state: original.state,
     59         committedAtUnixMilliseconds: original.committedAtUnixMilliseconds,
     60         updatedAtUnixMilliseconds: original.updatedAtUnixMilliseconds,
     61         media: original.media, settlement: original.settlement, delivery: original.delivery,
     62         targetDetails: original.targetDetails, retry: decision
     63       )
     64       XCTAssertFalse(status.canOfferContinuation)
     65       let effects = TeraSubmissionEffects(client: client, media: nil, ensure: {},
     66                                           accept: { _ in XCTFail("Blocked work cannot advance") })
     67       try await effects.advance(status)
     68       XCTAssertEqual(status.captured, original.captured)
     69       XCTAssertEqual(status.targetDetails, original.targetDetails)
     70     }
     71     let after = await backend.submissionBackend.advanceCount
     72     XCTAssertEqual(after, before)
     73     store.stop()
     74     _ = try await client.stop()
     75   }
     76 }