@@ -1119,9 +1119,7 @@ private struct ObjectsIntegrationTests {
11191119
11201120 let clearTimeserial = lexicoTimeserial ( seriesId: " aaa " , timestamp: 5 , counter: 0 )
11211121
1122- // the server would have already tombstoned entries that predate the clear,
1123- // so the sync state reflects the materialised result. this test checks that
1124- // even with clearTimeserial set, the entries from materialised entries are
1122+ // check that even with clearTimeserial set, the entries from materialised entries are
11251123 // processed correctly.
11261124 await objectsHelper. processObjectStateMessageOnChannel (
11271125 channel: channel,
@@ -1136,11 +1134,6 @@ private struct ObjectsIntegrationTests {
11361134 " timeserial " : . string( lexicoTimeserial ( seriesId: " aaa " , timestamp: 8 , counter: 0 ) ) ,
11371135 " data " : . object( [ " string " : . string( " late " ) ] ) ,
11381136 ] ) ,
1139- // entry tombstoned by the clear - should not be visible
1140- " clearedKey " : . object( [
1141- " timeserial " : . string( clearTimeserial) ,
1142- " tombstone " : . bool( true ) ,
1143- ] ) ,
11441137 ] ,
11451138 clearTimeserial: clearTimeserial,
11461139 ) ,
@@ -1149,8 +1142,6 @@ private struct ObjectsIntegrationTests {
11491142
11501143 let lateKeyValue = try #require( root. get ( key: " lateKey " ) ? . stringValue)
11511144 #expect( lateKeyValue == " late " , " Check lateKey is visible (postdates clear) " )
1152- let clearedKeyValue = try root. get ( key: " clearedKey " )
1153- #expect( clearedKeyValue == nil , " Check clearedKey is not visible (tombstoned by clear) " )
11541145 #expect( try root. size == 1 , " Check root has 1 visible key " )
11551146 } ,
11561147 ) ,
@@ -2343,36 +2334,10 @@ private struct ObjectsIntegrationTests {
23432334 let root = ctx. root
23442335 let objects = ctx. objects
23452336 let objectsHelper = ctx. objectsHelper
2346- let channelName = ctx. channelName
23472337
23482338 // set some keys on root
2349- let fooUpdatedPromiseUpdates = try root. updates ( )
2350- let bazUpdatedPromiseUpdates = try root. updates ( )
2351- async let keysUpdatedPromise : Void = withTaskGroup ( of: Void . self) { group in
2352- group. addTask {
2353- await waitForMapKeyUpdate ( fooUpdatedPromiseUpdates, " foo " )
2354- }
2355- group. addTask {
2356- await waitForMapKeyUpdate ( bazUpdatedPromiseUpdates, " baz " )
2357- }
2358- await group. waitForAll ( )
2359- }
2360- try await withThrowingTaskGroup ( of: ObjectsHelper . OperationResult. self) { group in
2361- group. addTask {
2362- try await objectsHelper. operationRequest (
2363- channelName: channelName,
2364- opBody: objectsHelper. mapSetRestOp ( objectId: " root " , key: " foo " , value: [ " string " : . string( " bar " ) ] ) ,
2365- )
2366- }
2367- group. addTask {
2368- try await objectsHelper. operationRequest (
2369- channelName: channelName,
2370- opBody: objectsHelper. mapSetRestOp ( objectId: " root " , key: " baz " , value: [ " number " : . number( 42 ) ] ) ,
2371- )
2372- }
2373- while try await group. next ( ) != nil { }
2374- }
2375- await keysUpdatedPromise
2339+ try await root. set ( key: " foo " , value: " bar " )
2340+ try await root. set ( key: " baz " , value: 42 )
23762341
23772342 // verify keys exist before clear
23782343 let fooValue = try #require( root. get ( key: " foo " ) ? . stringValue)
@@ -2403,20 +2368,12 @@ private struct ObjectsIntegrationTests {
24032368 description: " can apply MAP_CLEAR object operation messages on non-root map objects " ,
24042369 action: { ctx in
24052370 let root = ctx. root
2371+ let objects = ctx. objects
24062372 let objectsHelper = ctx. objectsHelper
2407- let channelName = ctx. channelName
24082373 let channel = ctx. channel
24092374
24102375 // create a non-root map with entries
2411- let mapCreatedPromiseUpdates = try root. updates ( )
2412- async let mapCreatedPromise : Void = waitForMapKeyUpdate ( mapCreatedPromiseUpdates, " map " )
2413- let mapResult = try await objectsHelper. createAndSetOnMap (
2414- channelName: channelName,
2415- mapObjectId: " root " ,
2416- key: " map " ,
2417- createOp: objectsHelper. mapCreateRestOp ( data: [ " foo " : [ " string " : . string( " bar " ) ] , " baz " : [ " number " : . number( 42 ) ] ] ) ,
2418- )
2419- await mapCreatedPromise
2376+ try await root. set ( key: " map " , value: . liveMap( try await objects. createMap ( entries: [ " foo " : " bar " , " baz " : 42 ] ) ) )
24202377
24212378 let map = try #require( try root. get ( key: " map " ) ? . liveMapValue)
24222379 #expect( try map. size == 2 , " Check map has 2 keys before MAP_CLEAR " )
@@ -2427,11 +2384,12 @@ private struct ObjectsIntegrationTests {
24272384
24282385 // apply MAP_CLEAR on non-root map via internal API call,
24292386 // as the server won't accept MAP_CLEAR for non-root object ids.
2387+ let internalMap = try #require( map as? PublicDefaultLiveMap )
24302388 await objectsHelper. processObjectOperationMessageOnChannel (
24312389 channel: channel,
24322390 serial: lexicoTimeserial ( seriesId: " zzz " , timestamp: 99_999_999_999_999 , counter: 0 ) ,
24332391 siteCode: " zzz " ,
2434- state: [ objectsHelper. mapClearOp ( objectId: mapResult . objectId ) ] ,
2392+ state: [ objectsHelper. mapClearOp ( objectId: internalMap . proxied . testsOnly_objectID ) ] ,
24352393 )
24362394
24372395 // verify all keys are cleared
@@ -2572,19 +2530,25 @@ private struct ObjectsIntegrationTests {
25722530
25732531 for (i, mapId) in mapIds. enumerated ( ) {
25742532 // for each map, send two operations:
2575- // 1. set a key so the map has visible data that can be verified after MAP_CLEAR
2533+ // 1. create a map with visible data that can be verified after MAP_CLEAR.
2534+ // use earliest possible timeserial to ensure entries can be cleared by MAP_CLEAR ops
25762535 await objectsHelper. processObjectOperationMessageOnChannel (
25772536 channel: channel,
25782537 serial: lexicoTimeserial ( seriesId: " aaa " , timestamp: 0 , counter: 0 ) ,
25792538 siteCode: " aaa " ,
2580- state: [ objectsHelper. mapSetOp ( objectId: mapId, key: " foo " , data: . object( [ " string " : . string( " bar " ) ] ) ) ] ,
2539+ state: [
2540+ objectsHelper. mapCreateOp (
2541+ objectId: mapId,
2542+ entries: [ " foo " : . object( [ " timeserial " : . string( lexicoTimeserial ( seriesId: " aaa " , timestamp: 0 , counter: 0 ) ) , " data " : . object( [ " string " : . string( " bar " ) ] ) ] ) ] ,
2543+ ) ,
2544+ ] ,
25812545 )
2582- // 2. send a no-op remove to establish site 'bbb ' in the map's siteTimeserials at a known serial,
2546+ // 2. send a no-op remove to establish site 'ccc ' in the map's siteTimeserials at a known serial,
25832547 // which the MAP_CLEAR ops below will be compared against
25842548 await objectsHelper. processObjectOperationMessageOnChannel (
25852549 channel: channel,
2586- serial: lexicoTimeserial ( seriesId: " bbb " , timestamp: 5 , counter: 0 ) ,
2587- siteCode: " bbb " ,
2550+ serial: lexicoTimeserial ( seriesId: " ccc " , timestamp: 5 , counter: 0 ) ,
2551+ siteCode: " ccc " ,
25882552 state: [ objectsHelper. mapRemoveOp ( objectId: mapId, key: " baz " ) ] ,
25892553 )
25902554
@@ -2598,12 +2562,13 @@ private struct ObjectsIntegrationTests {
25982562 }
25992563
26002564 // inject MAP_CLEAR operations with various timeserial values
2565+ // relative to the lexicoTimeserial('ccc', 5, 0) from the remove op above
26012566 let ops : [ ( serial: String , siteCode: String , cleared: Bool ) ] = [
2602- ( serial: lexicoTimeserial ( seriesId: " bbb " , timestamp: 4 , counter: 0 ) , siteCode: " bbb " , cleared: false ) , // existing site, earlier CGO, not applied
2603- ( serial: lexicoTimeserial ( seriesId: " bbb " , timestamp: 5 , counter: 0 ) , siteCode: " bbb " , cleared: false ) , // existing site, same CGO, not applied
2604- ( serial: lexicoTimeserial ( seriesId: " bbb " , timestamp: 6 , counter: 0 ) , siteCode: " bbb " , cleared: true ) , // existing site, later CGO, applied
2605- ( serial: lexicoTimeserial ( seriesId: " aaa " , timestamp: 1 , counter: 0 ) , siteCode: " aaa " , cleared: true ) , // different site, earlier CGO, applied
2606- ( serial: lexicoTimeserial ( seriesId: " ccc " , timestamp: 9 , counter: 0 ) , siteCode: " ccc " , cleared: true ) , // different site, later CGO, applied
2567+ ( serial: lexicoTimeserial ( seriesId: " ccc " , timestamp: 4 , counter: 0 ) , siteCode: " ccc " , cleared: false ) , // existing site, earlier CGO, not applied
2568+ ( serial: lexicoTimeserial ( seriesId: " ccc " , timestamp: 5 , counter: 0 ) , siteCode: " ccc " , cleared: false ) , // existing site, same CGO, not applied
2569+ ( serial: lexicoTimeserial ( seriesId: " ccc " , timestamp: 6 , counter: 0 ) , siteCode: " ccc " , cleared: true ) , // existing site, later CGO, applied
2570+ ( serial: lexicoTimeserial ( seriesId: " bbb " , timestamp: 1 , counter: 0 ) , siteCode: " bbb " , cleared: true ) , // different site, earlier CGO, applied
2571+ ( serial: lexicoTimeserial ( seriesId: " ddd " , timestamp: 9 , counter: 0 ) , siteCode: " ddd " , cleared: true ) , // different site, later CGO, applied
26072572 ]
26082573
26092574 for (i, op) in ops. enumerated ( ) {
@@ -2731,6 +2696,7 @@ private struct ObjectsIntegrationTests {
27312696 siteCode: " aaa " ,
27322697 state: [ objectsHelper. mapSetOp ( objectId: " root " , key: " foo " , data: . object( [ " string " : . string( " bar " ) ] ) ) ] ,
27332698 )
2699+ #expect( try root. get ( key: " foo " ) != nil , " Check \" foo \" exists before clear " )
27342700
27352701 await objectsHelper. processObjectOperationMessageOnChannel (
27362702 channel: channel,
0 commit comments