about summary refs log tree commit diff
path: root/src/test
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2013-05-06 20:12:37 -0700
committerbors <bors@rust-lang.org>2013-05-06 20:12:37 -0700
commitd2f0235a2c887e425b2c06b8df359b1400b8dd4d (patch)
tree5781e7cd43a381a03eddd91c11b0e78037513acd /src/test
parent4b6864f2195250d34cbedf92ffaf23a400c71b9e (diff)
parentde8071234f66b984bf5a2ce33ec9100cb3204ea2 (diff)
auto merge of #6228 : brson/rust/run-destroy, r=brson
These cause valgrind errors in subprocesses. I don't *think* these errors
lead to actual test failures but they are very confusing.
Diffstat (limited to 'src/test')
-rw-r--r--src/test/run-pass/core-run-destroy.rs89
1 files changed, 89 insertions, 0 deletions
diff --git a/src/test/run-pass/core-run-destroy.rs b/src/test/run-pass/core-run-destroy.rs
new file mode 100644
index 00000000000..a4f3f59f46b
--- /dev/null
+++ b/src/test/run-pass/core-run-destroy.rs
@@ -0,0 +1,89 @@
+// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// xfail-fast
+// compile-flags:--test
+
+// NB: These tests kill child processes. Valgrind sees these children as leaking
+// memory, which makes for some *confusing* logs. That's why these are here
+// instead of in core.
+
+use core::run;
+use core::run::*;
+
+#[test]
+fn test_destroy_once() {
+    let mut p = run::start_program("echo", []);
+    p.destroy(); // this shouldn't crash (and nor should the destructor)
+}
+
+#[test]
+fn test_destroy_twice() {
+    let mut p = run::start_program("echo", []);
+    p.destroy(); // this shouldnt crash...
+    p.destroy(); // ...and nor should this (and nor should the destructor)
+}
+
+fn test_destroy_actually_kills(force: bool) {
+
+    #[cfg(unix)]
+    static BLOCK_COMMAND: &'static str = "cat";
+
+    #[cfg(windows)]
+    static BLOCK_COMMAND: &'static str = "cmd";
+
+    #[cfg(unix)]
+    fn process_exists(pid: libc::pid_t) -> bool {
+        run::program_output("ps", [~"-p", pid.to_str()]).out.contains(pid.to_str())
+    }
+
+    #[cfg(windows)]
+    fn process_exists(pid: libc::pid_t) -> bool {
+
+        use core::libc::types::os::arch::extra::DWORD;
+        use core::libc::funcs::extra::kernel32::{CloseHandle, GetExitCodeProcess, OpenProcess};
+        use core::libc::consts::os::extra::{FALSE, PROCESS_QUERY_INFORMATION, STILL_ACTIVE };
+
+        unsafe {
+            let proc = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, pid as DWORD);
+            if proc.is_null() {
+                return false;
+            }
+            // proc will be non-null if the process is alive, or if it died recently
+            let mut status = 0;
+            GetExitCodeProcess(proc, &mut status);
+            CloseHandle(proc);
+            return status == STILL_ACTIVE;
+        }
+    }
+
+    // this program will stay alive indefinitely trying to read from stdin
+    let mut p = run::start_program(BLOCK_COMMAND, []);
+
+    assert!(process_exists(p.get_id()));
+
+    if force {
+        p.force_destroy();
+    } else {
+        p.destroy();
+    }
+
+    assert!(!process_exists(p.get_id()));
+}
+
+#[test]
+fn test_unforced_destroy_actually_kills() {
+    test_destroy_actually_kills(false);
+}
+
+#[test]
+fn test_forced_destroy_actually_kills() {
+    test_destroy_actually_kills(true);
+}