commit 7f679fa8e0d4c43ed6828f718cd1cd01a2821e68
parent 6fc190f6e7bcbeb5b58a86fed6b31dd0f18225a8
Author: triesap <tyson@radroots.org>
Date: Tue, 8 Sep 2026 17:51:44 +0000
tera: capture current product equivalence
- exercise both calendar variants through the installed ffi
- preserve saved and queued fields across runtime reopen
- register the native test in the generated xcode project
- verify five-flow publication, donor round trips and native api checks
Diffstat:
3 files changed, 101 insertions(+), 0 deletions(-)
diff --git a/Radroots.xcodeproj/project.pbxproj b/Radroots.xcodeproj/project.pbxproj
@@ -14,6 +14,7 @@
3BCAFE2B1A96BBE5D741D8FC /* RadrootsSupportingStoreTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 41B94CEAFD958CE92D6B9265 /* RadrootsSupportingStoreTests.swift */; };
3FA27C59441DFE8F1B276642 /* RadrootsClockTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = CF79F087C35C4B0CFD5CAA68 /* RadrootsClockTests.swift */; };
51FE0A95B71A5D4EDCEB0748 /* RadrootsStateMigrationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = C26D512B6CBD1A9BE4780682 /* RadrootsStateMigrationTests.swift */; };
+ 5372708DA5127DFB175A3828 /* RadrootsCalendarFFICompatibilityTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 969358BEB12ED1EDAAF4F28B /* RadrootsCalendarFFICompatibilityTests.swift */; };
53C82BC2E86FCB582E8A8B32 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = FD3E502CA8ADE621038AEB47 /* Localizable.strings */; };
60B853393C8DF4FDF2C01CAF /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = 81E991EAE0A0EAB4853747C6 /* PrivacyInfo.xcprivacy */; };
75C044403AF08F7230DE9485 /* RadrootsRootShellUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = CF484F988B3D1D3D81880388 /* RadrootsRootShellUITests.swift */; };
@@ -62,6 +63,7 @@
81E991EAE0A0EAB4853747C6 /* PrivacyInfo.xcprivacy */ = {isa = PBXFileReference; path = PrivacyInfo.xcprivacy; sourceTree = "<group>"; };
8E51B7E9599732A711D60E1B /* RadrootsMediaStoreTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RadrootsMediaStoreTests.swift; sourceTree = "<group>"; };
93AA285819DD1269C3EAD80A /* Radroots.app */ = {isa = PBXFileReference; includeInIndex = 0; lastKnownFileType = wrapper.application; path = Radroots.app; sourceTree = BUILT_PRODUCTS_DIR; };
+ 969358BEB12ED1EDAAF4F28B /* RadrootsCalendarFFICompatibilityTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RadrootsCalendarFFICompatibilityTests.swift; sourceTree = "<group>"; };
9F54FC4930051FC4611B37D3 /* ios_app */ = {isa = PBXFileReference; lastKnownFileType = folder; name = ios_app; path = .; sourceTree = SOURCE_ROOT; };
B8F89E4B3A775E88F661B891 /* RadrootsRootShellTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RadrootsRootShellTests.swift; sourceTree = "<group>"; };
C26D512B6CBD1A9BE4780682 /* RadrootsStateMigrationTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RadrootsStateMigrationTests.swift; sourceTree = "<group>"; };
@@ -99,6 +101,7 @@
isa = PBXGroup;
children = (
42C296DF1E35100FE59C04D3 /* RadrootsAddStoreTests.swift */,
+ 969358BEB12ED1EDAAF4F28B /* RadrootsCalendarFFICompatibilityTests.swift */,
CF79F087C35C4B0CFD5CAA68 /* RadrootsClockTests.swift */,
D95CB1F4A964D87D2256DA9C /* RadrootsLifecycleTests.swift */,
8E51B7E9599732A711D60E1B /* RadrootsMediaStoreTests.swift */,
@@ -362,6 +365,7 @@
buildActionMask = 2147483647;
files = (
27B7FB991398E2BE7034C72E /* RadrootsAddStoreTests.swift in Sources */,
+ 5372708DA5127DFB175A3828 /* RadrootsCalendarFFICompatibilityTests.swift in Sources */,
3FA27C59441DFE8F1B276642 /* RadrootsClockTests.swift in Sources */,
CD88BB6222151E0B8242F84A /* RadrootsLifecycleTests.swift in Sources */,
AEEF096F40BCBC6D66A3BF32 /* RadrootsMediaStoreTests.swift in Sources */,
diff --git a/RadrootsTests/RadrootsCalendarFFICompatibilityTests.swift b/RadrootsTests/RadrootsCalendarFFICompatibilityTests.swift
@@ -0,0 +1,96 @@
+import Foundation
+import RadrootsKitBindings
+import XCTest
+
+final class RadrootsCalendarFFICompatibilityTests: XCTestCase {
+ private let publicKey = "79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798"
+
+ func testBothCalendarVariantsReopenThroughInstalledFFI() async throws {
+ let root = FileManager.default.temporaryDirectory
+ .appendingPathComponent("tera-calendar-ffi-\(UUID().uuidString.lowercased())")
+ try FileManager.default.createDirectory(
+ at: root.appendingPathComponent("radroots/users/\(publicKey)"),
+ withIntermediateDirectories: true
+ )
+ defer { try? FileManager.default.removeItem(at: root) }
+ let first = try await runtime(root)
+ var queued = [FfiDraftStatusRecord]()
+ for (index, timing) in [FfiEventTimingKind.allDay, .timed].enumerated() {
+ let input = calendar(timing)
+ let saved = try await first.phase1SaveDraft(
+ draftId: String(repeating: index == 0 ? "01" : "02", count: 16),
+ input: input,
+ authoredAtUnixS: 1_900_000_000,
+ expectedRevision: nil,
+ persistedAtUnixMs: 1_900_000_000_000
+ )
+ let form = try XCTUnwrap(saved.form)
+ XCTAssertEqual(form.commandType, .createEvent)
+ XCTAssertEqual(form.eventTiming, timing)
+ XCTAssertEqual(form.eventStartDate, input.eventStartDate)
+ XCTAssertEqual(form.eventEndDate, input.eventEndDate)
+ XCTAssertEqual(form.eventStartUnixS, input.eventStartUnixS)
+ XCTAssertEqual(form.eventEndUnixS, input.eventEndUnixS)
+ XCTAssertEqual(form.eventTimezone, input.eventTimezone)
+ let status = try await first.phase1QueueDraft(
+ draftId: saved.draftId,
+ expectedRevision: saved.revision,
+ policy: FfiQueuePolicyRecord(
+ schemaVersion: 1,
+ relayUrls: ["wss://relay.example"],
+ satisfaction: .allAccepted,
+ deliveryDeadlineUnixMs: 2_000_000_000_000,
+ cancellation: .localCooperative
+ ),
+ queuedAtUnixMs: 1_900_000_000_001
+ )
+ XCTAssertEqual(status.state, .queued)
+ XCTAssertNotNil(status.operationId)
+ XCTAssertEqual(status.form, saved.form)
+ queued.append(status)
+ }
+ _ = try await first.shutdown()
+ let reopened = try await runtime(root)
+ for expected in queued {
+ let restored = try await reopened.phase1DraftStatus(draftId: expected.draftId)
+ XCTAssertEqual(restored, expected)
+ }
+ _ = try await reopened.shutdown()
+ }
+
+ private func runtime(_ root: URL) async throws -> RadrootsRuntime {
+ try await RadrootsRuntime(
+ applicationSupportDirectory: root.path,
+ publicKeyHex: publicKey,
+ sourceGenerationHex: String(repeating: "04", count: 32),
+ sourceGenerationCreatedAtUnixMs: 1_800_000_000_000,
+ protectedData: .available
+ )
+ }
+
+ private func calendar(_ timing: FfiEventTimingKind) -> FfiAddDraftInput {
+ let allDay = timing == .allDay
+ return FfiAddDraftInput(
+ schemaVersion: 1,
+ commandType: .createEvent,
+ content: "Synthetic calendar boundary fixture",
+ identifier: allDay ? "all-day-fixture" : "timed-fixture",
+ title: "Synthetic calendar event",
+ summary: nil,
+ location: "Fixture location",
+ eventTiming: timing,
+ eventStartDate: allDay ? "2030-03-18" : nil,
+ eventEndDate: allDay ? "2030-03-19" : nil,
+ eventStartUnixS: allDay ? nil : 1_900_003_600,
+ eventEndUnixS: allDay ? nil : 1_900_007_200,
+ eventTimezone: allDay ? nil : "Etc/UTC",
+ priceAmount: nil,
+ currency: nil,
+ unit: nil,
+ quantity: nil,
+ foodPublishedAtUnixS: nil,
+ foodStatus: nil,
+ media: []
+ )
+ }
+}
diff --git a/project.yml b/project.yml
@@ -54,6 +54,7 @@ targets:
- path: RadrootsTests/RadrootsSupportingStoreTests.swift
- path: RadrootsTests/RadrootsLifecycleTests.swift
- path: RadrootsTests/RadrootsClockTests.swift
+ - path: RadrootsTests/RadrootsCalendarFFICompatibilityTests.swift
- path: RadrootsTests/RadrootsRemoteQualificationTests.swift
- path: RadrootsTests/RadrootsUserMessagesTests.swift
settings: