about summary refs log tree commit diff
path: root/src/libstd/rt
diff options
context:
space:
mode:
authorBen Blum <bblum@andrew.cmu.edu>2013-07-11 19:43:02 -0400
committerBen Blum <bblum@andrew.cmu.edu>2013-07-20 05:08:57 -0400
commite283c4ddffad0ac4e2ebace590849ff46336ca0e (patch)
treef2733fcb9237af9d7b840204641b6d5753527278 /src/libstd/rt
parenta093b5434a7110967d8597fb602588b299f9859e (diff)
downloadrust-e283c4ddffad0ac4e2ebace590849ff46336ca0e.tar.gz
rust-e283c4ddffad0ac4e2ebace590849ff46336ca0e.zip
Add tests for task killing and blocking.
Diffstat (limited to 'src/libstd/rt')
-rw-r--r--src/libstd/rt/kill.rs140
1 files changed, 140 insertions, 0 deletions
diff --git a/src/libstd/rt/kill.rs b/src/libstd/rt/kill.rs
index a3ee40f395f..94173b14f80 100644
--- a/src/libstd/rt/kill.rs
+++ b/src/libstd/rt/kill.rs
@@ -464,6 +464,7 @@ impl Drop for Death {
 #[cfg(test)]
 mod test {
     #[allow(unused_mut)];
+    use cell::Cell;
     use rt::test::*;
     use super::*;
     use util;
@@ -599,4 +600,143 @@ mod test {
             assert!(parent_inner.any_child_failed == false);
         }
     }
+
+    // Task killing tests
+
+    #[test]
+    fn kill_basic() {
+        do run_in_newsched_task {
+            let mut handle = KillHandle::new();
+            assert!(!handle.killed());
+            assert!(handle.kill().is_none());
+            assert!(handle.killed());
+        }
+    }
+
+    #[test]
+    fn double_kill() {
+        do run_in_newsched_task {
+            let mut handle = KillHandle::new();
+            assert!(!handle.killed());
+            assert!(handle.kill().is_none());
+            assert!(handle.killed());
+            assert!(handle.kill().is_none());
+            assert!(handle.killed());
+        }
+    }
+
+    #[test]
+    fn unkillable_after_kill() {
+        do run_in_newsched_task {
+            let mut handle = KillHandle::new();
+            assert!(handle.kill().is_none());
+            assert!(handle.killed());
+            let handle_cell = Cell::new(handle);
+            let result = do spawntask_try {
+                handle_cell.take().inhibit_kill(false);
+            };
+            assert!(result.is_err());
+        }
+    }
+
+    #[test]
+    fn unkillable_during_kill() {
+        do run_in_newsched_task {
+            let mut handle = KillHandle::new();
+            handle.inhibit_kill(false);
+            assert!(handle.kill().is_none());
+            assert!(!handle.killed());
+            let handle_cell = Cell::new(handle);
+            let result = do spawntask_try {
+                handle_cell.take().allow_kill(false);
+            };
+            assert!(result.is_err());
+        }
+    }
+
+    #[test]
+    fn unkillable_before_kill() {
+        do run_in_newsched_task {
+            let mut handle = KillHandle::new();
+            handle.inhibit_kill(false);
+            handle.allow_kill(false);
+            assert!(handle.kill().is_none());
+            assert!(handle.killed());
+        }
+    }
+
+    // Task blocking tests
+
+    #[test]
+    fn block_and_wake() {
+        do with_test_task |mut task| {
+            BlockedTask::try_block(task).unwrap_right().wake().unwrap()
+        }
+    }
+
+    #[test]
+    fn block_and_get_killed() {
+        do with_test_task |mut task| {
+            let mut handle = task.death.kill_handle.get_ref().clone();
+            let result = BlockedTask::try_block(task).unwrap_right();
+            let task = handle.kill().unwrap();
+            assert!(result.wake().is_none());
+            task
+        }
+    }
+
+    #[test]
+    fn block_already_killed() {
+        do with_test_task |mut task| {
+            let mut handle = task.death.kill_handle.get_ref().clone();
+            assert!(handle.kill().is_none());
+            BlockedTask::try_block(task).unwrap_left()
+        }
+    }
+
+    #[test]
+    fn block_unkillably_and_get_killed() {
+        do with_test_task |mut task| {
+            let mut handle = task.death.kill_handle.get_ref().clone();
+            task.death.inhibit_kill(false);
+            let result = BlockedTask::try_block(task).unwrap_right();
+            assert!(handle.kill().is_none());
+            let mut task = result.wake().unwrap();
+            // This call wants to fail, but we can't have that happen since
+            // we're not running in a newsched task, so we can't even use
+            // spawntask_try. But the failing behaviour is already tested
+            // above, in unkillable_during_kill(), so we punt on it here.
+            task.death.allow_kill(true);
+            task
+        }
+    }
+
+    #[test]
+    fn block_on_pipe() {
+        // Tests the "killable" path of casting to/from uint.
+        do run_in_newsched_task {
+            do with_test_task |mut task| {
+                let result = BlockedTask::try_block(task).unwrap_right();
+                let result = unsafe { result.cast_to_uint() };
+                let result = unsafe { BlockedTask::cast_from_uint(result) };
+                result.wake().unwrap()
+            }
+        }
+    }
+
+    #[test]
+    fn block_unkillably_on_pipe() {
+        // Tests the "indestructible" path of casting to/from uint.
+        do run_in_newsched_task {
+            do with_test_task |mut task| {
+                task.death.inhibit_kill(false);
+                let result = BlockedTask::try_block(task).unwrap_right();
+                let result = unsafe { result.cast_to_uint() };
+                let result = unsafe { BlockedTask::cast_from_uint(result) };
+                let mut task = result.wake().unwrap();
+                task.death.allow_kill(false);
+                task
+            }
+        }
+    }
 }