Skip to content

Commit 2a99320

Browse files
committed
Add tests for KillHandle
1 parent afc199b commit 2a99320

File tree

1 file changed

+140
-0
lines changed

1 file changed

+140
-0
lines changed

src/libstd/rt/kill.rs

Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -193,3 +193,143 @@ impl Death {
193193
};
194194
}
195195
}
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

Comments
 (0)