Skip to content

Commit 8b6f64f

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

2 files changed

Lines changed: 60 additions & 8 deletions

File tree

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

Lines changed: 33 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,13 @@ 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+
* Spec: RTLO4e
162166
*/
163167
@Test
164-
fun testObjectRemovalFromRoot() = runTest {
168+
fun testObjectDelete() = runTest {
165169
val channelName = generateChannelName()
166170
// Initialize the root map on the channel with initial data
167171
restObjects.initializeRootMap(channelName)
@@ -171,19 +175,41 @@ class DefaultLiveObjectsTest : IntegrationTest() {
171175
assertEquals(6L, rootMap.size()) // Should have 6 entries initially
172176

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

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

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

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

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

186206
assertWaiter { rootMap.size() == 4L } // Wait for the removal to complete
187207
assertNull(rootMap.get("referencedMap")) // Should be null after removal
208+
assertEquals(1, mapUpdates.size) // Should have received one update for deletion
209+
210+
val updatedMap = mapUpdates.first()
211+
assertEquals(1, updatedMap.size) // Should have one change
212+
assertEquals("counterKey", updatedMap.keys.first()) // The change should be for the "counterKey"
213+
assertEquals(LiveMapUpdate.Change.REMOVED, updatedMap.values.first()) // Should indicate removal
188214
}
189215
}
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)