import XCTest @testable import MacSyncShared private struct FakeItem: Sendable, Equatable { let id: String let body: String } private actor FakeTransportState { var pending: [FakeItem] var reportedSent: [String] = [] var reportedFailed: [(id: String, error: String?)] = [] var fetchCalls: Int = 0 init(pending: [FakeItem]) { self.pending = pending } func popAll() -> [FakeItem] { fetchCalls += 1 let items = pending pending = [] return items } func recordSent(_ id: String) { reportedSent.append(id) } func recordFailed(_ id: String, _ error: String?) { reportedFailed.append((id, error)) } } private struct FakeTransport: SendQueueTransport { typealias PendingItem = FakeItem let state: FakeTransportState func id(of item: FakeItem) -> String { item.id } func fetchPending() async throws -> [FakeItem] { await state.popAll() } func reportResult(id: String, status: String, error: String?) async throws { if status == "sent" { await state.recordSent(id) } else { await state.recordFailed(id, error) } } } final class SendQueueClientTests: XCTestCase { @MainActor func test_drainOnce_appliesAndAcksEachItem() async { let state = FakeTransportState(pending: [ FakeItem(id: "a", body: "hello"), FakeItem(id: "b", body: "world"), ]) let transport = FakeTransport(state: state) let client = SendQueueClient( label: "test", transport: transport, interval: 60 ) { item in item.body == "world" ? .failed(reason: "bad world") : .sent } await client.drainOnce() let sent = await state.reportedSent let failed = await state.reportedFailed XCTAssertEqual(sent, ["a"]) XCTAssertEqual(failed.count, 1) XCTAssertEqual(failed.first?.id, "b") XCTAssertEqual(failed.first?.error, "bad world") } @MainActor func test_drainOnce_isReentrantSafe() async { let state = FakeTransportState(pending: (0..<5).map { FakeItem(id: "\($0)", body: "x") }) let transport = FakeTransport(state: state) let client = SendQueueClient( label: "test", transport: transport, interval: 60 ) { _ in try? await Task.sleep(nanoseconds: 20_000_000) return .sent } async let a: Void = client.drainOnce() async let b: Void = client.drainOnce() async let c: Void = client.drainOnce() _ = await (a, b, c) let calls = await state.fetchCalls XCTAssertEqual(calls, 1, "concurrent drains must coalesce") let sent = await state.reportedSent XCTAssertEqual(sent.count, 5) } @MainActor func test_drainOnce_emptyQueueIsNoop() async { let state = FakeTransportState(pending: []) let transport = FakeTransport(state: state) let client = SendQueueClient( label: "test", transport: transport, interval: 60 ) { _ in .sent } await client.drainOnce() let sent = await state.reportedSent let failed = await state.reportedFailed XCTAssertTrue(sent.isEmpty) XCTAssertTrue(failed.isEmpty) } }