Skip to content

Commit 332ac0a

Browse files
committed
[ECO-5447] Replaced partial testObjectRemovalFromRoot with well simulated
testObjectDelete test
1 parent f700c58 commit 332ac0a

2 files changed

Lines changed: 61 additions & 8 deletions

File tree

live-objects/src/test/kotlin/io/ably/lib/objects/integration/DefaultLiveObjectsTest.kt

Lines changed: 34 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,15 @@ import io.ably.lib.objects.*
66
import io.ably.lib.objects.Binary
77
import io.ably.lib.objects.integration.helpers.State
88
import io.ably.lib.objects.integration.helpers.fixtures.initializeRootMap
9+
import io.ably.lib.objects.integration.helpers.simulateObjectDelete
910
import io.ably.lib.objects.integration.setup.IntegrationTest
1011
import io.ably.lib.objects.size
1112
import io.ably.lib.objects.state.ObjectsStateEvent
1213
import io.ably.lib.objects.type.counter.LiveCounter
14+
import io.ably.lib.objects.type.livecounter.DefaultLiveCounter
15+
import io.ably.lib.objects.type.livemap.DefaultLiveMap
1316
import io.ably.lib.objects.type.map.LiveMap
17+
import io.ably.lib.objects.type.map.LiveMapUpdate
1418
import kotlinx.coroutines.test.runTest
1519
import org.junit.Test
1620
import kotlin.test.assertEquals
@@ -155,13 +159,14 @@ class DefaultLiveObjectsTest : IntegrationTest() {
155159
}
156160

157161
/**
158-
* Spec: RTLO4e - Tests the removal of objects from the root map.
159162
* Server runs periodic garbage collection (GC) to remove orphaned objects and will send
160163
* OBJECT_DELETE events for objects that are no longer referenced.
161-
* `OBJECT_DELETE` event is not covered in the test and we only check if map entries are removed
164+
* So, we simulate the deletion of an object by sending an object delete ProtocolMessage.
165+
* This does not actually delete the object from the server, only simulates the deletion locally.
166+
* Spec: RTLO4e
162167
*/
163168
@Test
164-
fun testObjectRemovalFromRoot() = runTest {
169+
fun testObjectDelete() = runTest {
165170
val channelName = generateChannelName()
166171
// Initialize the root map on the channel with initial data
167172
restObjects.initializeRootMap(channelName)
@@ -171,19 +176,41 @@ class DefaultLiveObjectsTest : IntegrationTest() {
171176
assertEquals(6L, rootMap.size()) // Should have 6 entries initially
172177

173178
// Remove the "referencedCounter" from the root map
174-
assertNotNull(rootMap.get("referencedCounter")) // Access to ensure it exists before removal
179+
val refCounter = rootMap.get("referencedCounter") as LiveCounter
180+
assertNotNull(refCounter)
181+
// Subscribe to counter updates to verify removal
182+
val counterUpdates = mutableListOf<Double>()
183+
refCounter.subscribe { event ->
184+
counterUpdates.add(event.update.amount)
185+
}
175186

176-
restObjects.removeMapValue(channelName, "root", "referencedCounter")
187+
// Simulate the deletion of the referencedCounter object
188+
channel.objects.simulateObjectDelete(channelName, refCounter as DefaultLiveCounter)
177189

178190
assertWaiter { rootMap.size() == 5L } // Wait for the removal to complete
179191
assertNull(rootMap.get("referencedCounter")) // Should be null after removal
192+
assertEquals(1, counterUpdates.size) // Should have received one update for deletion
193+
assertEquals(20.0, counterUpdates[0]) // The update should indicate the counter was removed
180194

181195
// Remove the "referencedMap" from the root map
182-
assertNotNull(rootMap.get("referencedMap")) // Access to ensure it exists before removal
196+
val referencedMap = rootMap.get("referencedMap") as LiveMap
197+
assertNotNull(referencedMap)
198+
// Subscribe to map updates to verify removal
199+
val mapUpdates = mutableListOf<Map<String, LiveMapUpdate.Change>>()
200+
referencedMap.subscribe { event ->
201+
mapUpdates.add(event.update)
202+
}
183203

184-
restObjects.removeMapValue(channelName, "root", "referencedMap")
204+
// Simulate the deletion of the referencedMap object
205+
channel.objects.simulateObjectDelete(channelName, referencedMap as DefaultLiveMap)
185206

186207
assertWaiter { rootMap.size() == 4L } // Wait for the removal to complete
187208
assertNull(rootMap.get("referencedMap")) // Should be null after removal
209+
assertEquals(1, mapUpdates.size) // Should have received one update for deletion
210+
211+
val updatedMap = mapUpdates.first()
212+
assertEquals(1, updatedMap.size) // Should have one change
213+
assertEquals("counterKey", updatedMap.keys.first()) // The change should be for the "counterKey"
214+
assertEquals(LiveMapUpdate.Change.REMOVED, updatedMap.values.first()) // Should indicate removal
188215
}
189216
}
Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,40 @@
11
package io.ably.lib.objects.integration.helpers
22

3+
import io.ably.lib.objects.*
34
import io.ably.lib.objects.DefaultLiveObjects
5+
import io.ably.lib.objects.ObjectMessage
6+
import io.ably.lib.objects.ObjectOperation
7+
import io.ably.lib.objects.type.BaseLiveObject
48
import io.ably.lib.objects.type.counter.LiveCounter
59
import io.ably.lib.objects.type.map.LiveMap
6-
import io.ably.lib.objects.LiveObjects
710
import io.ably.lib.objects.type.livecounter.DefaultLiveCounter
811
import io.ably.lib.objects.type.livemap.DefaultLiveMap
12+
import io.ably.lib.types.ProtocolMessage
913

1014
internal val LiveMap.ObjectId get() = (this as DefaultLiveMap).objectId
1115

1216
internal val LiveCounter.ObjectId get() = (this as DefaultLiveCounter).objectId
1317

1418
internal val LiveObjects.State get() = (this as DefaultLiveObjects).state
19+
20+
/**
21+
* Server runs periodic garbage collection (GC) to remove orphaned objects and will send
22+
* OBJECT_DELETE events for objects that are no longer referenced.
23+
* So, we simulate the deletion of an object by sending a ProtocolMessage.
24+
*/
25+
internal fun LiveObjects.simulateObjectDelete(channelName: String, baseObject: BaseLiveObject) {
26+
val defaultLiveObjects = this as DefaultLiveObjects
27+
val existingSiteCode = baseObject.siteTimeserials.keys.first()
28+
val existingSiteSerial = baseObject.siteTimeserials[existingSiteCode]!!
29+
30+
val deleteObjectProtoMsg = ProtocolMessage(ProtocolMessage.Action.`object`, channelName)
31+
deleteObjectProtoMsg.state = arrayOf(ObjectMessage(
32+
siteCode = existingSiteCode,
33+
serial = existingSiteSerial + "1", // Increment serial to accept new operation
34+
operation = ObjectOperation(
35+
action = ObjectOperationAction.ObjectDelete,
36+
objectId = baseObject.objectId,
37+
)
38+
))
39+
defaultLiveObjects.handle(deleteObjectProtoMsg)
40+
}

0 commit comments

Comments
 (0)