import Foundation import XCTest @testable import DocsKit final class CRDTSourceReuseTests: XCTestCase { func testAcknowledgedIdenticalSourceReuseBoundsClientsAndPreservesDivergence() async throws { let replica = CRDTReplica(guid: "source-reuse-test") _ = try await replica.open(update: Data()) _ = try await replica.command(["op": .string("insert_element"), "at": .number(0), "type": .string("paragraph")]) let initial = try await replica.presentation(source: 0, selection: NSRange(location: 0, length: 0)) var source = try XCTUnwrap(initial?.0) let original = source for index in 0..<100 { _ = try await replica.command(["op": .string("display_edit"), "generation": .number(Double(source)), "at": .number(Double(index)), "length": .number(0), "text": .string("a")]) await replica.retainGenerations([source]) let next = try await replica.presentation(source: source, selection: NSRange(location: index + 1, length: 0), allowReuse: true) source = try XCTUnwrap(next?.0) } XCTAssertEqual(source, original) let (clientData, typed) = try await replica.command(["op": .string("clients")]) XCTAssertEqual(try JSONDecoder().decode([UInt64].self, from: clientData).count, 2) XCTAssertEqual(typed.children.map(\.plainText).joined(), String(repeating: "a", count: 100)) // A candidate without explicit rendered acknowledgement must remain fresh. await replica.retainGenerations([source]) let unacknowledged = try await replica.presentation(source: source, selection: NSRange(location: 100, length: 0)) XCTAssertNotEqual(unacknowledged?.0, source) await replica.retainGenerations([source]) // A peer changes authority while displayed source stays at the old state. let (snapshot, _) = try await replica.command(["op": .string("snapshot")]) let peer = CRDTReplica(guid: "source-reuse-test") _ = try await peer.open(update: snapshot) let (peerUpdate, _) = try await peer.command(["op": .string("display_edit"), "at": .number(0), "length": .number(0), "text": .string("peer ")]) _ = try await replica.apply(peerUpdate) let divergent = try await replica.presentation(source: source, selection: NSRange(location: 100, length: 0), allowReuse: true) let changed = try XCTUnwrap(divergent?.0) XCTAssertNotEqual(changed, source) XCTAssertEqual(divergent?.1.children.map(\.plainText).joined(), "peer " + String(repeating: "a", count: 100)) XCTAssertEqual(divergent?.2.location, 105) // Reusing the newly acknowledged live source does not merge undo ownership. await replica.retainGenerations([changed]) _ = try await replica.command(["op": .string("display_edit"), "generation": .number(Double(changed)), "at": .number(105), "length": .number(0), "text": .string("!")]) let local = try await replica.presentation(source: changed, selection: NSRange(location: 106, length: 0), allowReuse: true) XCTAssertEqual(local?.0, changed) _ = try await replica.command(["op": .string("undo")]) let undone = try await replica.presentation(source: changed, selection: NSRange(location: 106, length: 0), allowReuse: true) XCTAssertNotEqual(undone?.0, changed) XCTAssertFalse(undone?.1.children.map(\.plainText).joined().hasSuffix("!") ?? true) XCTAssertTrue(undone?.1.children.map(\.plainText).joined().hasPrefix("peer ") ?? false) await peer.close(); await replica.close() } }