Skip to content

Commit 44d60ce

Browse files
committed
[ECO-5426] Added few more tests to ObjectsPool
1 parent 57cf42b commit 44d60ce

2 files changed

Lines changed: 97 additions & 0 deletions

File tree

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ class DefaultLiveObjectsTest {
5252
val rootObject = defaultLiveObjects.objectsPool.get(ROOT_OBJECT_ID) as DefaultLiveMap
5353
rootObject.data["key1"] = LiveMapEntry(data = ObjectData("testValue1"))
5454
defaultLiveObjects.objectsPool.set("dummyObjectId", DefaultLiveCounter("dummyObjectId", mockk(relaxed = true)))
55+
assertEquals(2, defaultLiveObjects.objectsPool.size(), "RTO4b - Should have 2 objects before state change")
5556

5657
// RTO4b - If the HAS_OBJECTS flag is 0, the sync sequence must be considered complete immediately
5758
defaultLiveObjects.handleStateChange(ChannelState.attached, false)

live-objects/src/test/kotlin/io/ably/lib/objects/unit/objects/ObjectsPoolTest.kt

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,18 @@
11
package io.ably.lib.objects.unit.objects
22

33
import io.ably.lib.objects.DefaultLiveObjects
4+
import io.ably.lib.objects.ObjectData
45
import io.ably.lib.objects.ROOT_OBJECT_ID
56
import io.ably.lib.objects.type.livecounter.DefaultLiveCounter
67
import io.ably.lib.objects.type.livemap.DefaultLiveMap
8+
import io.ably.lib.objects.type.livemap.LiveMapEntry
9+
import io.ably.lib.objects.unit.*
710
import io.mockk.mockk
11+
import io.mockk.spyk
812
import org.junit.Test
913
import kotlin.test.assertEquals
1014
import kotlin.test.assertNotNull
15+
import kotlin.test.assertNull
1116
import kotlin.test.assertTrue
1217

1318
class ObjectsPoolTest {
@@ -23,6 +28,8 @@ class ObjectsPoolTest {
2328
assertNotNull(rootLiveMap)
2429
assertTrue(rootLiveMap is DefaultLiveMap)
2530
assertTrue(rootLiveMap.data.isEmpty())
31+
assertEquals(ROOT_OBJECT_ID, rootLiveMap.objectId)
32+
assertEquals(1, objectsPool.size(), "RTO3 - Should only contain the root object initially")
2633

2734
// RTO3a - ObjectsPool is a Dict, a map of LiveObjects keyed by objectId string
2835
val testLiveMap = DefaultLiveMap("testObjectId", mockk(relaxed = true), objectsPool)
@@ -32,5 +39,94 @@ class ObjectsPoolTest {
3239
// Assert that the objects are stored in the pool
3340
assertEquals(testLiveMap, objectsPool.get("testObjectId"))
3441
assertEquals(testLiveCounter, objectsPool.get("testCounterId"))
42+
assertEquals(3, objectsPool.size(), "RTO3 - Should have 3 objects in pool (root + testLiveMap + testLiveCounter)")
43+
}
44+
45+
@Test
46+
fun `(RTO6) ObjectsPool should create zero-value objects if not exists`() {
47+
val defaultLiveObjects = DefaultLiveObjects("dummyChannel", mockk(relaxed = true))
48+
val objectsPool = spyk(defaultLiveObjects.objectsPool)
49+
assertEquals(1, objectsPool.size(), "RTO3 - Should only contain the root object initially")
50+
51+
// Test creating zero-value map
52+
// RTO6b1, RTO6b2 - Type is parsed from the objectId format (map:hash@timestamp)
53+
val mapId = "map:xyz789@67890"
54+
val map = objectsPool.createZeroValueObjectIfNotExists(mapId)
55+
assertNotNull(map, "Should create a map object")
56+
assertTrue(map is DefaultLiveMap, "RTO6b2 - Should create a LiveMap for map type")
57+
assertEquals(mapId, map.objectId)
58+
assertTrue(map.data.isEmpty(), "RTO6b2 - Should create an empty map")
59+
assertEquals(2, objectsPool.size(), "RTO6 - root + map should be in pool after creation")
60+
61+
// Test creating zero-value counter
62+
// RTO6b1, RTO6b3 - Type is parsed from the objectId format (counter:hash@timestamp)
63+
val counterId = "counter:abc123@12345"
64+
val counter = objectsPool.createZeroValueObjectIfNotExists(counterId)
65+
assertNotNull(counter, "Should create a counter object")
66+
assertTrue(counter is DefaultLiveCounter, "RTO6b3 - Should create a LiveCounter for counter type")
67+
assertEquals(counterId, counter.objectId)
68+
assertEquals(0L, counter.data, "RTO6b3 - Should create a zero-value counter")
69+
assertEquals(3, objectsPool.size(), "RTO6 - root + map + counter should be in pool after creation")
70+
71+
// RTO6a - If object exists in pool, do not create a new one
72+
val existingMap = objectsPool.createZeroValueObjectIfNotExists(mapId)
73+
assertEquals(map, existingMap, "RTO6a - Should return existing object, not create a new one")
74+
val existingCounter = objectsPool.createZeroValueObjectIfNotExists(counterId)
75+
assertEquals(counter, existingCounter, "RTO6a - Should return existing object, not create a new one")
76+
assertEquals(3, objectsPool.size(), "RTO6 - Should still have 3 objects in pool after re-creation attempt")
77+
}
78+
79+
@Test
80+
fun `(RTO4b1, RTO4b2) ObjectsPool should reset to initial pool retaining original root map`() {
81+
val defaultLiveObjects = DefaultLiveObjects("dummyChannel", mockk(relaxed = true))
82+
val objectsPool = defaultLiveObjects.objectsPool
83+
assertEquals(1, objectsPool.size())
84+
val rootMap = objectsPool.get(ROOT_OBJECT_ID) as DefaultLiveMap
85+
// add some data to the root map
86+
rootMap.data["initialKey1"] = LiveMapEntry(data = ObjectData("testValue1"))
87+
rootMap.data["initialKey2"] = LiveMapEntry(data = ObjectData("testValue2"))
88+
assertEquals(2, rootMap.data.size, "RTO3 - Root map should have initial data")
89+
90+
// Add some objects
91+
objectsPool.set("testObjectId", DefaultLiveCounter("testObjectId", mockk(relaxed = true)))
92+
assertEquals(2, objectsPool.size()) // root + testObject
93+
objectsPool.set("anotherObjectId", DefaultLiveCounter("anotherObjectId", mockk(relaxed = true)))
94+
assertEquals(3, objectsPool.size()) // root + testObject + anotherObject
95+
objectsPool.set("testMapId", DefaultLiveMap("testMapId", mockk(relaxed = true), objectsPool))
96+
assertEquals(4, objectsPool.size()) // root + testObject + anotherObject + testMap
97+
98+
// Reset to initial pool
99+
objectsPool.resetToInitialPool(true)
100+
101+
// RTO4b1 - Should only contain root object
102+
assertEquals(1, objectsPool.size())
103+
assertEquals(rootMap, objectsPool.get(ROOT_OBJECT_ID))
104+
// RTO4b2 - RootMap should be empty after reset
105+
assertTrue(rootMap.data.isEmpty(), "RTO3 - Root map should be empty after reset")
106+
}
107+
108+
@Test
109+
fun `(RTO5c2, RTO5c2a) ObjectsPool should delete extra object IDs`() {
110+
val defaultLiveObjects = DefaultLiveObjects("dummyChannel", mockk(relaxed = true))
111+
val objectsPool = defaultLiveObjects.objectsPool
112+
113+
// Add some objects
114+
objectsPool.set("object1", DefaultLiveCounter("object1", mockk(relaxed = true)))
115+
objectsPool.set("object2", DefaultLiveCounter("object2", mockk(relaxed = true)))
116+
objectsPool.set("object3", DefaultLiveCounter("object3", mockk(relaxed = true)))
117+
assertEquals(4, objectsPool.size()) // root + 3 objects
118+
119+
// Delete extra object IDs (keep only object1 and object2)
120+
val receivedObjectIds = mutableSetOf("object1", "object2")
121+
objectsPool.deleteExtraObjectIds(receivedObjectIds)
122+
123+
// Should only contain root, object1, and object2
124+
assertEquals(3, objectsPool.size())
125+
// RTO5c2a - Should keep the root object
126+
assertNotNull(objectsPool.get(ROOT_OBJECT_ID))
127+
// RTO5c2 - Should delete object3 and keep object1 and object2
128+
assertNotNull(objectsPool.get("object1"))
129+
assertNotNull(objectsPool.get("object2"))
130+
assertNull(objectsPool.get("object3")) // Should be deleted
35131
}
36132
}

0 commit comments

Comments
 (0)