field_ios

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

TeraSubmissionAdmissionTests.swift (4048B)


      1 import Foundation
      2 @testable import TeraApp
      3 import XCTest
      4 
      5 final class TeraSubmissionAdmissionTests: XCTestCase {
      6   func testTimeoutOrCancellationReturnsPromptlyButKeepsAdmissionUntilActualCallback() async throws {
      7     for cancel in [false, true] {
      8       let backend = AddBackend()
      9       let client = TeraRuntimeClient(factory: { _ in
     10         await TeraRuntimeBackendStart(backend: backend, snapshot: backend.snapshot())
     11       }, deadlines: TeraRuntimeDeadlinePolicy(operationNanoseconds: 100_000_000))
     12       _ = try await client.start(configuration: TeraAddStoreTests.configuration())
     13       let scope = TeraComposerScope(authorPublicKey: String(repeating: "ab", count: 32), localNetworkID: "nearby")
     14       var form = TeraComposerForm(commandType: .createUpdate)
     15       form.content = "original"
     16       let saved = try await client.saveComposer(request: TeraComposerSaveRequest(
     17         scope: scope, id: client.reserveComposerID(), expectedRevision: nil, editSequence: 1, form: form
     18       ))
     19       let request = try await TeraSubmissionRequest(commandID: client.reserveSubmissionID(), scope: scope,
     20                                                     composerID: saved.draft.id, expectedRevision: saved.draft.revision)
     21       let pause = ResourceTestPause()
     22       await backend.submissionBackend.pausePrepare(pause)
     23       let first = Task { try await client.prepareSubmission(request: request, media: []) }
     24       let entered = expectation(description: "Reached the original submission call")
     25       let observer = Task { await pause.entered.wait(); entered.fulfill() }
     26       await fulfillment(of: [entered], timeout: 3)
     27       await pause.entered.open()
     28       await observer.value
     29       if cancel {
     30         first.cancel()
     31       }
     32       await assertBoundedReturn(first, cancelled: cancel)
     33       await assertHeldAdmission(client, request: request)
     34       let calls = await backend.submissionBackend.prepareCount
     35       XCTAssertEqual(calls, 1)
     36       await pause.resume.open()
     37       var recovered: TeraSubmissionStatus?
     38       let deadline = ContinuousClock.now.advanced(by: .seconds(3))
     39       while recovered == nil, ContinuousClock.now < deadline {
     40         recovered = try? await client.recoverSubmission(request: request)
     41         if recovered == nil {
     42           try await Task.sleep(for: .milliseconds(1))
     43         }
     44       }
     45       let original = try XCTUnwrap(recovered)
     46       let replay = try await client.prepareSubmission(request: request, media: [])
     47       XCTAssertEqual(replay, original)
     48       XCTAssertEqual(replay.request, request)
     49       XCTAssertEqual(replay.captured, saved.draft)
     50       let operations = await backend.submissionBackend.operationCount
     51       XCTAssertEqual(operations, 1)
     52       _ = try await client.stop()
     53     }
     54   }
     55 
     56   private func assertHeldAdmission(_ client: TeraRuntimeClient, request: TeraSubmissionRequest) async {
     57       for _ in 0 ..< 100 {
     58         do {
     59           _ = try await client.prepareSubmission(request: request, media: [])
     60           XCTFail("A late original callback must retain admission")
     61         } catch { XCTAssertEqual(TeraAddPresentation.failure(for: error)?.code, "operation_in_progress") }
     62       }
     63       do {
     64         _ = try await client.recoverSubmission(request: request)
     65         XCTFail("Recovery cannot infer absence while the original call is unfinished")
     66       } catch { XCTAssertEqual(TeraAddPresentation.failure(for: error)?.code, "operation_in_progress") }
     67   }
     68 
     69   private func assertBoundedReturn(_ first: Task<TeraSubmissionStatus, Error>, cancelled cancel: Bool) async {
     70       let returned = expectation(description: "Native waiter keeps its original deadline")
     71       let waiter = Task {
     72         do {
     73           _ = try await first.value
     74           XCTFail("Expected bounded wait to end")
     75         } catch {
     76           XCTAssertEqual(TeraAddPresentation.failure(for: error)?.code,
     77                          cancel ? "ios.runtime.cancelled" : "ios.runtime.deadline_exceeded")
     78         }
     79         returned.fulfill()
     80       }
     81       await fulfillment(of: [returned], timeout: 2)
     82       await waiter.value
     83   }
     84 }