@@ -199,3 +199,136 @@ impl EntityRcSource {
199199 }
200200 }
201201}
202+
203+ #[ cfg( test) ]
204+ mod tests {
205+ use crate :: {
206+ entity_rc:: { EntityRc , EntityRcSource } ,
207+ world:: World ,
208+ } ;
209+
210+ /// Handles any dropped entities, and flushes the world.
211+ fn handle_drops ( world : & mut World , source : & EntityRcSource ) {
212+ source. handle_dropped_rcs ( & mut world. commands ( ) ) ;
213+ world. flush ( ) ;
214+ }
215+
216+ #[ test]
217+ fn simple_counting ( ) {
218+ let mut world = World :: new ( ) ;
219+ let source = EntityRcSource :: new ( ) ;
220+
221+ let entity_1 = world. spawn_empty ( ) . id ( ) ;
222+ let rc_1_1 = source. create_rc ( entity_1, ( ) ) ;
223+
224+ let entity_2 = world. spawn_empty ( ) . id ( ) ;
225+ let rc_2_1 = source. create_rc ( entity_2, ( ) ) ;
226+
227+ let entity_3 = world. spawn_empty ( ) . id ( ) ;
228+ let rc_3_1 = source. create_rc ( entity_3, ( ) ) ;
229+
230+ handle_drops ( & mut world, & source) ;
231+
232+ assert ! ( world. get_entity( entity_1) . is_ok( ) ) ;
233+ assert ! ( world. get_entity( entity_2) . is_ok( ) ) ;
234+ assert ! ( world. get_entity( entity_3) . is_ok( ) ) ;
235+
236+ drop ( rc_2_1) ;
237+
238+ // Dropping the rc doesn't do anything until we handle the drops.
239+ assert ! ( world. get_entity( entity_1) . is_ok( ) ) ;
240+ assert ! ( world. get_entity( entity_2) . is_ok( ) ) ;
241+ assert ! ( world. get_entity( entity_3) . is_ok( ) ) ;
242+
243+ handle_drops ( & mut world, & source) ;
244+
245+ // entity_2 is despawned.
246+ assert ! ( world. get_entity( entity_1) . is_ok( ) ) ;
247+ assert ! ( world. get_entity( entity_2) . is_err( ) ) ;
248+ assert ! ( world. get_entity( entity_3) . is_ok( ) ) ;
249+
250+ // Cloning the rc and then dropping the original doesn't drop the entity.
251+ let rc_1_2 = rc_1_1. clone ( ) ;
252+ drop ( rc_1_1) ;
253+ handle_drops ( & mut world, & source) ;
254+
255+ assert ! ( world. get_entity( entity_1) . is_ok( ) ) ;
256+ assert ! ( world. get_entity( entity_3) . is_ok( ) ) ;
257+
258+ // Dropping all handles will.
259+ drop ( rc_1_2) ;
260+ handle_drops ( & mut world, & source) ;
261+
262+ assert ! ( world. get_entity( entity_1) . is_err( ) ) ;
263+ assert ! ( world. get_entity( entity_3) . is_ok( ) ) ;
264+
265+ // Cloning the handle many times doesn't do anything.
266+ let rc_3_2 = rc_3_1. clone ( ) ;
267+ let rc_3_3 = rc_3_1. clone ( ) ;
268+ let rc_3_4 = rc_3_1. clone ( ) ;
269+ let rc_3_5 = rc_3_1. clone ( ) ;
270+ handle_drops ( & mut world, & source) ;
271+
272+ assert ! ( world. get_entity( entity_3) . is_ok( ) ) ;
273+
274+ // Dropping the rc fewer times than clones still does nothing.
275+ for rc in [ rc_3_1, rc_3_2, rc_3_3, rc_3_4] {
276+ drop ( rc) ;
277+ handle_drops ( & mut world, & source) ;
278+ assert ! ( world. get_entity( entity_3) . is_ok( ) ) ;
279+ }
280+
281+ // Dropping the last rc finally drops the entity.
282+ drop ( rc_3_5) ;
283+ handle_drops ( & mut world, & source) ;
284+ assert ! ( world. get_entity( entity_3) . is_err( ) ) ;
285+ }
286+
287+ #[ test]
288+ fn weak_handles_dont_keep_entity_alive ( ) {
289+ let mut world = World :: new ( ) ;
290+ let source = EntityRcSource :: new ( ) ;
291+
292+ let entity = world. spawn_empty ( ) . id ( ) ;
293+ let rc = source. create_rc ( entity, ( ) ) ;
294+
295+ let weak_1 = EntityRc :: downgrade ( & rc) ;
296+ let _weak_2 = EntityRc :: downgrade ( & rc) ;
297+ let _weak_3 = EntityRc :: downgrade ( & rc) ;
298+ handle_drops ( & mut world, & source) ;
299+ assert ! ( world. get_entity( entity) . is_ok( ) ) ;
300+
301+ // Dropping the one rc is enough to despawn the entity.
302+ drop ( rc) ;
303+
304+ // Bonus: trying to get an rc out of an expired weak doesn't work.
305+ assert ! ( weak_1. upgrade( ) . is_none( ) ) ;
306+
307+ handle_drops ( & mut world, & source) ;
308+ assert ! ( world. get_entity( entity) . is_err( ) ) ;
309+ }
310+
311+ #[ test]
312+ fn weak_handles_can_upgrade ( ) {
313+ let mut world = World :: new ( ) ;
314+ let source = EntityRcSource :: new ( ) ;
315+
316+ let entity = world. spawn_empty ( ) . id ( ) ;
317+ let rc = source. create_rc ( entity, ( ) ) ;
318+
319+ let weak = EntityRc :: downgrade ( & rc) ;
320+
321+ let upgraded_weak = weak. upgrade ( ) ;
322+ assert ! ( upgraded_weak. is_some( ) ) ;
323+
324+ // Dropping the original rc does nothing, since we upgraded the weak.
325+ drop ( rc) ;
326+ handle_drops ( & mut world, & source) ;
327+ assert ! ( world. get_entity( entity) . is_ok( ) ) ;
328+
329+ // Also dropping the upgraded weak (now just an rc) will drop the entity.
330+ drop ( upgraded_weak) ;
331+ handle_drops ( & mut world, & source) ;
332+ assert ! ( world. get_entity( entity) . is_err( ) ) ;
333+ }
334+ }
0 commit comments