@@ -193,3 +193,143 @@ impl Death {
193
193
} ;
194
194
}
195
195
}
196
+
197
+ #[ cfg( test) ]
198
+ mod test {
199
+ #[ allow( unused_mut) ] ;
200
+ use rt:: test:: * ;
201
+ use super :: * ;
202
+ use util;
203
+
204
+ #[ test]
205
+ fn no_tombstone_success ( ) {
206
+ do run_in_newsched_task {
207
+ // Tests case 4 of the 4-way match in reparent_children.
208
+ let mut parent = KillHandle :: new ( ) ;
209
+ let mut child = KillHandle :: new ( ) ;
210
+
211
+ // Without another handle to child, the try unwrap should succeed.
212
+ child. reparent_children_to ( & mut parent) ;
213
+ let mut parent_inner = unsafe { parent. unwrap ( ) } ;
214
+ assert ! ( parent_inner. child_tombstones. is_none( ) ) ;
215
+ assert ! ( parent_inner. any_child_failed == false ) ;
216
+ }
217
+ }
218
+ #[ test]
219
+ fn no_tombstone_failure ( ) {
220
+ do run_in_newsched_task {
221
+ // Tests case 2 of the 4-way match in reparent_children.
222
+ let mut parent = KillHandle :: new ( ) ;
223
+ let mut child = KillHandle :: new ( ) ;
224
+
225
+ child. notify_immediate_failure ( ) ;
226
+ // Without another handle to child, the try unwrap should succeed.
227
+ child. reparent_children_to ( & mut parent) ;
228
+ let mut parent_inner = unsafe { parent. unwrap ( ) } ;
229
+ assert ! ( parent_inner. child_tombstones. is_none( ) ) ;
230
+ // Immediate failure should have been propagated.
231
+ assert ! ( parent_inner. any_child_failed) ;
232
+ }
233
+ }
234
+ #[ test]
235
+ fn no_tombstone_because_sibling_already_failed ( ) {
236
+ do run_in_newsched_task {
237
+ // Tests "case 0, the optimistic path in reparent_children.
238
+ let mut parent = KillHandle :: new ( ) ;
239
+ let mut child1 = KillHandle :: new ( ) ;
240
+ let mut child2 = KillHandle :: new ( ) ;
241
+ let mut link = child2. clone ( ) ;
242
+
243
+ // Should set parent's child_failed flag
244
+ child1. notify_immediate_failure ( ) ;
245
+ child1. reparent_children_to ( & mut parent) ;
246
+ // Should bypass trying to unwrap child2 entirely.
247
+ // Otherwise, due to 'link', it would try to tombstone.
248
+ child2. reparent_children_to ( & mut parent) ;
249
+ // Should successfully unwrap even though 'link' is still alive.
250
+ let mut parent_inner = unsafe { parent. unwrap ( ) } ;
251
+ assert ! ( parent_inner. child_tombstones. is_none( ) ) ;
252
+ // Immediate failure should have been propagated by first child.
253
+ assert ! ( parent_inner. any_child_failed) ;
254
+ util:: ignore ( link) ;
255
+ }
256
+ }
257
+ #[ test]
258
+ fn one_tombstone_success ( ) {
259
+ do run_in_newsched_task {
260
+ let mut parent = KillHandle :: new ( ) ;
261
+ let mut child = KillHandle :: new ( ) ;
262
+ let mut link = child. clone ( ) ;
263
+
264
+ // Creates 1 tombstone. Existence of 'link' makes try-unwrap fail.
265
+ child. reparent_children_to ( & mut parent) ;
266
+ // Let parent collect tombstones.
267
+ util:: ignore ( link) ;
268
+ // Must have created a tombstone
269
+ let mut parent_inner = unsafe { parent. unwrap ( ) } ;
270
+ assert ! ( parent_inner. child_tombstones. take_unwrap( ) ( ) ) ;
271
+ assert ! ( parent_inner. any_child_failed == false ) ;
272
+ }
273
+ }
274
+ #[ test]
275
+ fn one_tombstone_failure ( ) {
276
+ do run_in_newsched_task {
277
+ let mut parent = KillHandle :: new ( ) ;
278
+ let mut child = KillHandle :: new ( ) ;
279
+ let mut link = child. clone ( ) ;
280
+
281
+ // Creates 1 tombstone. Existence of 'link' makes try-unwrap fail.
282
+ child. reparent_children_to ( & mut parent) ;
283
+ // Must happen after tombstone to not be immediately propagated.
284
+ link. notify_immediate_failure ( ) ;
285
+ // Let parent collect tombstones.
286
+ util:: ignore ( link) ;
287
+ // Must have created a tombstone
288
+ let mut parent_inner = unsafe { parent. unwrap ( ) } ;
289
+ // Failure must be seen in the tombstone.
290
+ assert ! ( parent_inner. child_tombstones. take_unwrap( ) ( ) == false ) ;
291
+ assert ! ( parent_inner. any_child_failed == false ) ;
292
+ }
293
+ }
294
+ #[ test]
295
+ fn two_tombstones_success ( ) {
296
+ do run_in_newsched_task {
297
+ let mut parent = KillHandle :: new ( ) ;
298
+ let mut middle = KillHandle :: new ( ) ;
299
+ let mut child = KillHandle :: new ( ) ;
300
+ let mut link = child. clone ( ) ;
301
+
302
+ child. reparent_children_to ( & mut middle) ; // case 1 tombstone
303
+ // 'middle' should try-unwrap okay, but still have to reparent.
304
+ middle. reparent_children_to ( & mut parent) ; // case 3 tombston
305
+ // Let parent collect tombstones.
306
+ util:: ignore ( link) ;
307
+ // Must have created a tombstone
308
+ let mut parent_inner = unsafe { parent. unwrap ( ) } ;
309
+ assert ! ( parent_inner. child_tombstones. take_unwrap( ) ( ) ) ;
310
+ assert ! ( parent_inner. any_child_failed == false ) ;
311
+ }
312
+ }
313
+ #[ test]
314
+ fn two_tombstones_failure ( ) {
315
+ do run_in_newsched_task {
316
+ let mut parent = KillHandle :: new ( ) ;
317
+ let mut middle = KillHandle :: new ( ) ;
318
+ let mut child = KillHandle :: new ( ) ;
319
+ let mut link = child. clone ( ) ;
320
+
321
+ child. reparent_children_to ( & mut middle) ; // case 1 tombstone
322
+ // Must happen after tombstone to not be immediately propagated.
323
+ link. notify_immediate_failure ( ) ;
324
+ // 'middle' should try-unwrap okay, but still have to reparent.
325
+ middle. reparent_children_to ( & mut parent) ; // case 3 tombstone
326
+ // Let parent collect tombstones.
327
+ util:: ignore ( link) ;
328
+ // Must have created a tombstone
329
+ let mut parent_inner = unsafe { parent. unwrap ( ) } ;
330
+ // Failure must be seen in the tombstone.
331
+ assert ! ( parent_inner. child_tombstones. take_unwrap( ) ( ) == false ) ;
332
+ assert ! ( parent_inner. any_child_failed == false ) ;
333
+ }
334
+ }
335
+ }
0 commit comments