@@ -15,6 +15,7 @@ import arcs.core.data.Schema
15
15
import arcs.core.data.SchemaFields
16
16
import arcs.core.data.SchemaName
17
17
import arcs.core.data.util.toReferencable
18
+ import arcs.core.storage.Reference
18
19
import arcs.core.storage.StorageKey
19
20
import arcs.core.storage.driver.RamDisk
20
21
import arcs.core.storage.driver.RamDiskStorageKey
@@ -36,30 +37,33 @@ import org.junit.runner.RunWith
36
37
import org.mockito.Mockito.times
37
38
import org.mockito.Mockito.verify
38
39
39
-
40
40
@Suppress(" EXPERIMENTAL_API_USAGE" )
41
41
@RunWith(AndroidJUnit4 ::class )
42
42
class AndroidHandleManagerTest {
43
43
private lateinit var app: Application
44
44
45
+ private val backingKey = RamDiskStorageKey (" entities" )
46
+
45
47
val entity1 = RawEntity (
46
48
" entity1" ,
47
- singletons= mapOf (
49
+ singletons = mapOf (
48
50
" name" to " Jason" .toReferencable(),
49
51
" age" to 21 .toReferencable(),
50
- " is_cool" to false .toReferencable()
52
+ " is_cool" to false .toReferencable(),
53
+ " best_friend" to Reference (" entity2" , backingKey, null )
51
54
),
52
- collections= emptyMap()
55
+ collections = emptyMap()
53
56
)
54
57
55
58
val entity2 = RawEntity (
56
59
" entity2" ,
57
- singletons= mapOf (
60
+ singletons = mapOf (
58
61
" name" to " Jason" .toReferencable(),
59
62
" age" to 22 .toReferencable(),
60
- " is_cool" to true .toReferencable()
63
+ " is_cool" to true .toReferencable(),
64
+ " best_friend" to Reference (" entity1" , backingKey, null )
61
65
),
62
- collections= emptyMap()
66
+ collections = emptyMap()
63
67
)
64
68
65
69
private val schema = Schema (
@@ -68,20 +72,21 @@ class AndroidHandleManagerTest {
68
72
singletons = mapOf (
69
73
" name" to FieldType .Text ,
70
74
" age" to FieldType .Number ,
71
- " is_cool" to FieldType .Boolean
75
+ " is_cool" to FieldType .Boolean ,
76
+ " best_friend" to FieldType .EntityRef (" 1234acf" )
72
77
),
73
78
collections = emptyMap()
74
79
),
75
80
" 1234acf"
76
81
)
77
82
78
83
private val singletonKey = ReferenceModeStorageKey (
79
- backingKey = RamDiskStorageKey ( " single-back " ) ,
84
+ backingKey = backingKey ,
80
85
storageKey = RamDiskStorageKey (" single-ent" )
81
86
)
82
87
83
88
private val setKey = ReferenceModeStorageKey (
84
- backingKey = RamDiskStorageKey ( " set-back " ) ,
89
+ backingKey = backingKey ,
85
90
storageKey = RamDiskStorageKey (" set-ent" )
86
91
)
87
92
@@ -121,107 +126,144 @@ class AndroidHandleManagerTest {
121
126
}
122
127
123
128
@Test
124
- fun testCreateSingletonHandle () = runBlockingTest {
125
- handleManagerTest { hm ->
126
- val singletonHandle = hm.singletonHandle(singletonKey, schema)
127
- singletonHandle.store(entity1)
128
-
129
- // Now read back from a different handle
130
- val readbackHandle = hm.singletonHandle(singletonKey, schema)
131
- val readBack = readbackHandle.fetch()
132
- assertThat(readBack).isEqualTo(entity1)
133
- }
129
+ fun testCreateSingletonHandle () = handleManagerTest { hm ->
130
+ val singletonHandle = hm.singletonHandle(singletonKey, schema)
131
+ singletonHandle.store(entity1)
132
+
133
+ // Now read back from a different handle
134
+ val readbackHandle = hm.singletonHandle(singletonKey, schema)
135
+ val readBack = readbackHandle.fetch()
136
+ assertThat(readBack).isEqualTo(entity1)
137
+ }
138
+
139
+ @Test
140
+ fun testDereferencingFromSingletonEntity () = handleManagerTest { hm ->
141
+ val singleton1Handle = hm.singletonHandle(singletonKey, schema)
142
+ val singleton1Handle2 = hm.singletonHandle(singletonKey, schema)
143
+ singleton1Handle.store(entity1)
144
+
145
+ // Create a second handle for the second entity, so we can store it.
146
+ val singleton2Handle = hm.singletonHandle(
147
+ ReferenceModeStorageKey (backingKey, RamDiskStorageKey (" entity2" )),
148
+ schema
149
+ )
150
+ val singleton2Handle2 = hm.singletonHandle(
151
+ ReferenceModeStorageKey (backingKey, RamDiskStorageKey (" entity2" )),
152
+ schema
153
+ )
154
+ singleton2Handle.store(entity2)
155
+
156
+ // Now read back entity1, and dereference its best_friend.
157
+ val dereferencedEntity2 =
158
+ (singleton1Handle2.fetch()!! .singletons[" best_friend" ] as Reference )
159
+ .also {
160
+ // Check that it's alive
161
+ assertThat(it.isAlive(coroutineContext)).isTrue()
162
+ }
163
+ .dereference(coroutineContext)
164
+ assertThat(dereferencedEntity2).isEqualTo(entity2)
165
+
166
+ // Do the same for entity2's best_friend
167
+ val dereferencedEntity1 =
168
+ (singleton2Handle2.fetch()!! .singletons[" best_friend" ] as Reference )
169
+ .dereference(coroutineContext)
170
+ assertThat(dereferencedEntity1).isEqualTo(entity1)
134
171
}
135
172
136
173
@Test
137
- fun testCreateSetHandle () = runBlockingTest {
138
- handleManagerTest { hm ->
139
- val setHandle = hm.setHandle(setKey, schema)
140
- setHandle.store(entity1)
141
- setHandle.store(entity2)
142
-
143
- // Now read back from a different handle
144
- val secondHandle = hm.setHandle(setKey, schema)
145
- val readBack = secondHandle.fetchAll()
146
- assertThat(readBack).containsExactly(entity1, entity2)
174
+ fun testCreateSetHandle () = handleManagerTest { hm ->
175
+ val setHandle = hm.setHandle(setKey, schema)
176
+ setHandle.store(entity1)
177
+ setHandle.store(entity2)
178
+
179
+ // Now read back from a different handle
180
+ val secondHandle = hm.setHandle(setKey, schema)
181
+ val readBack = secondHandle.fetchAll()
182
+ assertThat(readBack).containsExactly(entity1, entity2)
183
+ }
184
+
185
+ @Test
186
+ fun testDereferencingFromSetHandleEntity () = handleManagerTest { hm ->
187
+ val setHandle = hm.setHandle(setKey, schema)
188
+ setHandle.store(entity1)
189
+ setHandle.store(entity2)
190
+
191
+ val secondHandle = hm.setHandle(setKey, schema)
192
+ secondHandle.fetchAll().also { assertThat(it).hasSize(2 ) }.forEach { entity ->
193
+ val expectedBestFriend = if (entity.id == " entity1" ) entity2 else entity1
194
+ val actualBestFriend = (entity.singletons[" best_friend" ] as Reference )
195
+ .dereference()
196
+ assertThat(actualBestFriend).isEqualTo(expectedBestFriend)
147
197
}
148
198
}
149
199
150
200
private fun testMapForKey (key : StorageKey ) = VersionMap (key.toKeyString() to 1 )
151
201
152
202
@Test
153
- fun testSetHandleOnUpdate () = runBlockingTest {
154
- handleManagerTest { hm ->
155
- val testCallback1 = mock<SetCallbacks <RawEntity >>()
156
- val testCallback2 = mock<SetCallbacks <RawEntity >>()
157
- val firstHandle = hm.setHandle(setKey, schema, testCallback1)
158
- val secondHandle = hm.setHandle(setKey, schema, testCallback2)
159
-
160
- val expectedAdd = CrdtSet .Operation .Add (
161
- setKey.toKeyString(),
162
- testMapForKey(setKey),
163
- entity1
164
- )
165
- secondHandle.store(entity1)
166
- verify(testCallback1, times(1 )).onUpdate(firstHandle, expectedAdd)
167
- verify(testCallback2, times(1 )).onUpdate(secondHandle, expectedAdd)
168
-
169
- firstHandle.remove(entity1)
170
- val expectedRemove = CrdtSet .Operation .Remove (
171
- setKey.toKeyString(),
172
- testMapForKey(setKey),
173
- entity1
174
- )
175
- verify(testCallback1, times(1 )).onUpdate(firstHandle, expectedRemove)
176
- verify(testCallback2, times(1 )).onUpdate(secondHandle, expectedRemove)
177
- }
203
+ fun testSetHandleOnUpdate () = handleManagerTest { hm ->
204
+ val testCallback1 = mock<SetCallbacks <RawEntity >>()
205
+ val testCallback2 = mock<SetCallbacks <RawEntity >>()
206
+ val firstHandle = hm.setHandle(setKey, schema, testCallback1)
207
+ val secondHandle = hm.setHandle(setKey, schema, testCallback2)
208
+
209
+ val expectedAdd = CrdtSet .Operation .Add (
210
+ setKey.toKeyString(),
211
+ testMapForKey(setKey),
212
+ entity1
213
+ )
214
+ secondHandle.store(entity1)
215
+ verify(testCallback1, times(1 )).onUpdate(firstHandle, expectedAdd)
216
+ verify(testCallback2, times(1 )).onUpdate(secondHandle, expectedAdd)
217
+
218
+ firstHandle.remove(entity1)
219
+ val expectedRemove = CrdtSet .Operation .Remove (
220
+ setKey.toKeyString(),
221
+ testMapForKey(setKey),
222
+ entity1
223
+ )
224
+ verify(testCallback1, times(1 )).onUpdate(firstHandle, expectedRemove)
225
+ verify(testCallback2, times(1 )).onUpdate(secondHandle, expectedRemove)
178
226
}
179
227
180
228
@Test
181
- fun testSingletonHandleOnUpdate () = runBlockingTest {
182
- handleManagerTest { hm ->
183
- val testCallback1 = mock<SingletonCallbacks <RawEntity >>()
184
- val testCallback2 = mock<SingletonCallbacks <RawEntity >>()
185
- val firstHandle = hm.singletonHandle(singletonKey, schema, testCallback1)
186
- val secondHandle = hm.singletonHandle(singletonKey, schema, testCallback2)
187
- secondHandle.store(entity1)
188
- val expectedAdd = CrdtSingleton .Operation .Update (
189
- singletonKey.toKeyString(),
190
- testMapForKey(singletonKey),
191
- entity1
192
- )
193
- verify(testCallback1, times(1 )).onUpdate(firstHandle, expectedAdd)
194
- verify(testCallback2, times(1 )).onUpdate(secondHandle, expectedAdd)
195
- firstHandle.clear()
196
-
197
- val expectedRemove = CrdtSingleton .Operation .Clear <RawEntity >(
198
- singletonKey.toKeyString(),
199
- testMapForKey(singletonKey)
200
- )
201
- verify(testCallback1, times(1 )).onUpdate(firstHandle, expectedRemove)
202
- verify(testCallback2, times(1 )).onUpdate(secondHandle, expectedRemove)
203
- }
229
+ fun testSingletonHandleOnUpdate () = handleManagerTest { hm ->
230
+ val testCallback1 = mock<SingletonCallbacks <RawEntity >>()
231
+ val testCallback2 = mock<SingletonCallbacks <RawEntity >>()
232
+ val firstHandle = hm.singletonHandle(singletonKey, schema, testCallback1)
233
+ val secondHandle = hm.singletonHandle(singletonKey, schema, testCallback2)
234
+ secondHandle.store(entity1)
235
+ val expectedAdd = CrdtSingleton .Operation .Update (
236
+ singletonKey.toKeyString(),
237
+ testMapForKey(singletonKey),
238
+ entity1
239
+ )
240
+ verify(testCallback1, times(1 )).onUpdate(firstHandle, expectedAdd)
241
+ verify(testCallback2, times(1 )).onUpdate(secondHandle, expectedAdd)
242
+ firstHandle.clear()
243
+
244
+ val expectedRemove = CrdtSingleton .Operation .Clear <RawEntity >(
245
+ singletonKey.toKeyString(),
246
+ testMapForKey(singletonKey)
247
+ )
248
+ verify(testCallback1, times(1 )).onUpdate(firstHandle, expectedRemove)
249
+ verify(testCallback2, times(1 )).onUpdate(secondHandle, expectedRemove)
204
250
}
205
251
206
252
@Test
207
- fun testSetSyncOnRegister () = runBlockingTest {
208
- handleManagerTest { hm ->
209
- val testCallback = mock<SetCallbacks <RawEntity >>()
210
- val firstHandle = hm.setHandle(setKey, schema, testCallback)
211
- verify(testCallback, times(1 )).onSync(firstHandle)
212
- firstHandle.fetchAll()
213
- verify(testCallback, times(1 )).onSync(firstHandle)
214
- }
253
+ fun testSetSyncOnRegister () = handleManagerTest { hm ->
254
+ val testCallback = mock<SetCallbacks <RawEntity >>()
255
+ val firstHandle = hm.setHandle(setKey, schema, testCallback)
256
+ verify(testCallback, times(1 )).onSync(firstHandle)
257
+ firstHandle.fetchAll()
258
+ verify(testCallback, times(1 )).onSync(firstHandle)
215
259
}
216
260
217
261
@Test
218
- fun testSingletonSyncOnRegister () = runBlockingTest {
219
- handleManagerTest { hm ->
220
- val testCallback = mock<SingletonCallbacks <RawEntity >>()
221
- val firstHandle = hm.singletonHandle(setKey, schema, testCallback)
222
- verify(testCallback, times(1 )).onSync(firstHandle)
223
- firstHandle.fetch()
224
- verify(testCallback, times(1 )).onSync(firstHandle)
225
- }
262
+ fun testSingletonSyncOnRegister () = handleManagerTest { hm ->
263
+ val testCallback = mock<SingletonCallbacks <RawEntity >>()
264
+ val firstHandle = hm.singletonHandle(setKey, schema, testCallback)
265
+ verify(testCallback, times(1 )).onSync(firstHandle)
266
+ firstHandle.fetch()
267
+ verify(testCallback, times(1 )).onSync(firstHandle)
226
268
}
227
269
}
0 commit comments