TeraComposerSaveLatencyTests.swift (3943B)
1 import Foundation 2 @testable import TeraApp 3 import XCTest 4 5 @MainActor 6 final class TeraComposerSaveLatencyTests: XCTestCase { 7 func testTextOnlyExplicitSaveMeasuresActualDurableReceiptsAndReopen() async throws { 8 let fixture = try MediaOwnershipFixture() 9 defer { fixture.remove() } 10 let signer = ComposerForbiddenSigner() 11 let configuration = configuration(fixture, signer: signer) 12 let client = TeraRuntimeClient.production() 13 let snapshot = try await client.start(configuration: configuration) 14 let store = TeraAddStore(runtimeClient: client) 15 store.configure(snapshot: snapshot) 16 await store.start() 17 store.updateForm(\.content, "warm text-only save") 18 await store.save() 19 var previous = try XCTUnwrap(store.savedComposer) 20 var samples: [Double] = [] 21 let clock = ContinuousClock() 22 for index in 0 ..< 24 { 23 let content = "bounded text-only sample \(index)" 24 store.updateForm(\.content, content) 25 let started = clock.now 26 await store.save() 27 let duration = started.duration(to: clock.now).components 28 samples.append(Double(duration.seconds) * 1000 + Double(duration.attoseconds) / 1e15) 29 let saved = try XCTUnwrap(store.savedComposer) 30 XCTAssertEqual(store.composerState, .saved) 31 XCTAssertEqual(saved.form.content, content) 32 XCTAssertTrue(saved.form.media.isEmpty) 33 XCTAssertEqual(saved.id, previous.id) 34 XCTAssertEqual(saved.revision, previous.revision + 1) 35 previous = saved 36 } 37 store.stop() 38 _ = try await client.stop() 39 _ = try await client.start(configuration: configuration) 40 let reopened = try await client.loadComposer(scope: previous.scope, id: previous.id) 41 XCTAssertEqual(reopened, previous) 42 _ = try await client.stop() 43 let signingRequests = await signer.requests 44 XCTAssertEqual(signingRequests, 0) 45 try record(samples) 46 } 47 48 private func record(_ samples: [Double]) throws { 49 XCTAssertEqual(samples.count, 24) 50 XCTAssertTrue(samples.allSatisfy { $0.isFinite && $0 >= 0 }) 51 let ordered = samples.sorted() 52 #if targetEnvironment(simulator) 53 let platform = "ios_simulator" 54 #else 55 let platform = "ios_physical_device" 56 #endif 57 let value: [String: Any] = try [ 58 "schema": "tera.explicit-save-latency.v1", 59 "platform": platform, 60 "os": ProcessInfo.processInfo.operatingSystemVersionString, 61 "sample_count": samples.count, 62 "warmup_count": 1, 63 "samples_ms": samples, 64 "p50_ms": ordered[ordered.count / 2], 65 "p95_ms": ordered[Int(ceil(Double(ordered.count) * 0.95)) - 1], 66 "max_ms": XCTUnwrap(ordered.last), 67 "measurement": "Explicit Add Save through production FFI to its acknowledged receipt; final revision reopened.", 68 ] 69 let data = try JSONSerialization.data(withJSONObject: value, options: [.sortedKeys]) 70 let attachment = XCTAttachment(data: data, uniformTypeIdentifier: "public.json") 71 attachment.name = "tera-explicit-save-latency.json" 72 attachment.lifetime = .keepAlways 73 add(attachment) 74 try print("TERA_EXPLICIT_SAVE_LATENCY \(XCTUnwrap(String(data: data, encoding: .utf8)))") 75 } 76 77 private func configuration(_ fixture: MediaOwnershipFixture, signer: ComposerForbiddenSigner) -> TeraRuntimeLaunchConfiguration { 78 TeraRuntimeLaunchConfiguration( 79 applicationSupportDirectory: fixture.root.path, 80 publicKeyHex: "79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798", 81 sourceGenerationHex: String(repeating: "04", count: 32), 82 sourceGenerationCreatedAtUnixMilliseconds: 1_800_000_000_000, 83 protectedData: .available, networkProfile: .publicNetwork, 84 writableRelays: ["wss://relay.example"], blossom: nil, 85 app: TeraRuntimeAppMetadata(bundleIdentifier: "test.composer-latency", version: "1", buildNumber: "1", buildSHA: nil), 86 signerGeneration: "composer-latency", signer: signer, adoptBootstrapSettings: false 87 ) 88 } 89 }