TeraCalendarTimingTests.swift (5237B)
1 import Foundation 2 @testable import TeraApp 3 import TeraKitBindings 4 import XCTest 5 6 final class TeraCalendarTimingTests: XCTestCase { 7 func testGeneratedNativeBuffersPreserveCivilDatesAndExclusiveEnds() throws { 8 let values: [FfiCalendarTiming] = [ 9 .dateBased(start: FfiCivilDate(year: 1, month: 1, day: 1), endExclusive: nil), 10 .dateBased(start: FfiCivilDate(year: 2024, month: 2, day: 29), endExclusive: FfiCivilDate(year: 2024, month: 3, day: 1)), 11 .dateBased(start: FfiCivilDate(year: 2026, month: 9, day: 5), endExclusive: FfiCivilDate(year: 2026, month: 9, day: 7)), 12 .dateBased(start: FfiCivilDate(year: 9999, month: 12, day: 31), endExclusive: nil), 13 ] 14 for value in values { 15 let restored = try FfiConverterTypeFfiCalendarTiming_lift(FfiConverterTypeFfiCalendarTiming_lower(value)) 16 XCTAssertEqual(restored, value) 17 guard case let .dateBased(start, end) = restored, 18 case let .dateBased(nativeStart, nativeEnd) = try restored.appValue() 19 else { return XCTFail("The generated boundary must retain civil timing.") } 20 XCTAssertEqual(nativeStart.year, start.year) 21 XCTAssertEqual(nativeStart.month, start.month) 22 XCTAssertEqual(nativeStart.day, start.day) 23 XCTAssertEqual(nativeEnd?.year, end?.year) 24 XCTAssertEqual(nativeEnd?.month, end?.month) 25 XCTAssertEqual(nativeEnd?.day, end?.day) 26 } 27 } 28 29 func testGeneratedNativeBuffersKeepUnsignedInstantsAndBothZonesWithoutRounding() throws { 30 for start: UInt64 in [0, (1 << 53) + 1, .max - 1, .max] { 31 let end = start == .max ? nil : start + 1 32 for zones in [false, true] { 33 let value = FfiCalendarTiming.timeBased( 34 startUnixS: start, endExclusiveUnixS: end, 35 startTzid: zones ? "America/Vancouver" : nil, endTzid: zones ? "Europe/Paris" : nil 36 ) 37 let restored = try FfiConverterTypeFfiCalendarTiming_lift(FfiConverterTypeFfiCalendarTiming_lower(value)) 38 XCTAssertEqual(restored, value) 39 guard case let .timeBased(actualStart, actualEnd, startZone, endZone) = try restored.appValue() else { 40 return XCTFail("The generated boundary must retain timed values.") 41 } 42 XCTAssertEqual(actualStart, start) 43 XCTAssertEqual(actualEnd, end) 44 XCTAssertEqual(startZone, zones ? "America/Vancouver" : nil) 45 XCTAssertEqual(endZone, zones ? "Europe/Paris" : nil) 46 } 47 } 48 XCTAssertNotNil(TeraCalendarTiming.presentationInstant(0)) 49 XCTAssertNotNil(TeraCalendarTiming.presentationInstant(253_402_300_799)) 50 XCTAssertNil(TeraCalendarTiming.presentationInstant(253_402_300_800)) 51 XCTAssertNil(TeraCalendarTiming.presentationInstant(.max)) 52 } 53 54 func testUnsupportedGeneratedDiscriminantsAndTruncatedPayloadsThrow() { 55 for bytes: [UInt8] in [[0, 0, 0, 99], [0, 0, 0, 1], []] { 56 var input = (data: Data(bytes), offset: 0) 57 XCTAssertThrowsError(try FfiConverterTypeFfiCalendarTiming.read(from: &input)) 58 } 59 } 60 61 func testMalformedNativeTimingAndUnsupportedCardSchemasFailThroughTypedRecovery() throws { 62 let date = FfiCivilDate(year: 2026, month: 9, day: 5) 63 let invalid: [FfiCalendarTiming] = [ 64 .dateBased(start: FfiCivilDate(year: 0, month: 1, day: 1), endExclusive: nil), 65 .dateBased(start: FfiCivilDate(year: 2023, month: 2, day: 29), endExclusive: nil), 66 .dateBased(start: FfiCivilDate(year: 2024, month: 13, day: 1), endExclusive: nil), 67 .dateBased(start: date, endExclusive: date), 68 .timeBased(startUnixS: 2, endExclusiveUnixS: 1, startTzid: nil, endTzid: nil), 69 .timeBased(startUnixS: 1, endExclusiveUnixS: nil, startTzid: "Mars/Olympus", endTzid: nil), 70 ] 71 for timing in invalid { 72 XCTAssertThrowsError(try timing.appValue()) { error in 73 XCTAssertEqual(error as? TeraRuntimeFailure, TeraCalendarTiming.unsupported) 74 } 75 } 76 let timing = FfiCalendarTiming.dateBased(start: date, endExclusive: nil) 77 for version: UInt16 in [0, 1, .max] { 78 XCTAssertThrowsError(try card(schema: version, timing: timing).appValue()) 79 } 80 XCTAssertThrowsError(try card(schema: 2, timing: nil).appValue()) 81 let valid = card(schema: 2, timing: timing) 82 let restored = try FfiConverterTypeFfiTodayCardRecord_lift(FfiConverterTypeFfiTodayCardRecord_lower(valid)) 83 XCTAssertEqual(restored, valid) 84 XCTAssertEqual(try restored.appValue().calendarTiming, try timing.appValue()) 85 } 86 87 private func card(schema: UInt16, timing: FfiCalendarTiming?) -> FfiTodayCardRecord { 88 FfiTodayCardRecord( 89 schemaVersion: schema, cardId: "synthetic-card", cardType: .event, sourceEventId: "synthetic-event", 90 sourceAddress: nil, authorPublicKey: "synthetic-author", contractId: "synthetic-calendar", 91 title: "Harvest day", content: "Synthetic calendar", authoredAtUnixS: 1, effectiveAtUnixS: 1, 92 calendarTiming: timing, location: nil, priceAmount: nil, priceCurrency: nil, priceUnit: nil, 93 quantity: nil, foodSummary: nil, foodPublishedAtUnixS: nil, foodStatus: nil, contextRank: 1, 94 inclusionReason: "local", media: [], lifecycle: .active, rankDigest: nil, authorProfile: nil, 95 thread: [], localSourceDraftId: nil, localOperationId: nil, localOperationState: nil 96 ) 97 } 98 }