Skip to content

Commit 4ac10f8

Browse files
committed
auto merge of #9185 : alexcrichton/rust/less-changing-directories, r=huonw
While usage of change_dir_locked is synchronized against itself, it's not synchronized against other relative path usage, so I'm of the opinion that it just really doesn't help in running tests. In order to prevent the problems that have been cropping up, this completely removes the function. All existing tests (except one) using it have been moved to run-pass tests where they get their own process and don't need to be synchronized with anyone else. There is one now-ignored rustpkg test because when I moved it to a run-pass test apparently run-pass isn't set up to have 'extern mod rustc' (it ends up having linkage failures).
2 parents 52b9688 + 0af2bd8 commit 4ac10f8

File tree

7 files changed

+119
-178
lines changed

7 files changed

+119
-178
lines changed

src/libextra/tempfile.rs

+3-94
Original file line numberDiff line numberDiff line change
@@ -28,97 +28,6 @@ pub fn mkdtemp(tmpdir: &Path, suffix: &str) -> Option<Path> {
2828
None
2929
}
3030

31-
#[cfg(test)]
32-
mod tests {
33-
34-
use tempfile::mkdtemp;
35-
36-
use std::os;
37-
38-
#[test]
39-
fn test_mkdtemp() {
40-
let p = mkdtemp(&Path("."), "foobar").unwrap();
41-
os::remove_dir(&p);
42-
assert!(p.to_str().ends_with("foobar"));
43-
}
44-
45-
// Ideally these would be in std::os but then core would need
46-
// to depend on std
47-
#[test]
48-
fn recursive_mkdir_rel() {
49-
use std::libc::consts::os::posix88::{S_IRUSR, S_IWUSR, S_IXUSR};
50-
use std::os;
51-
use std::unstable::change_dir_locked;
52-
53-
let root = mkdtemp(&os::tmpdir(), "recursive_mkdir_rel").
54-
expect("recursive_mkdir_rel");
55-
assert!(do change_dir_locked(&root) {
56-
let path = Path("frob");
57-
debug!("recursive_mkdir_rel: Making: %s in cwd %s [%?]", path.to_str(),
58-
os::getcwd().to_str(),
59-
os::path_exists(&path));
60-
assert!(os::mkdir_recursive(&path, (S_IRUSR | S_IWUSR | S_IXUSR) as i32));
61-
assert!(os::path_is_dir(&path));
62-
assert!(os::mkdir_recursive(&path, (S_IRUSR | S_IWUSR | S_IXUSR) as i32));
63-
assert!(os::path_is_dir(&path));
64-
});
65-
}
66-
67-
#[test]
68-
fn recursive_mkdir_dot() {
69-
use std::libc::consts::os::posix88::{S_IRUSR, S_IWUSR, S_IXUSR};
70-
use std::os;
71-
72-
let dot = Path(".");
73-
assert!(os::mkdir_recursive(&dot, (S_IRUSR | S_IWUSR | S_IXUSR) as i32));
74-
let dotdot = Path("..");
75-
assert!(os::mkdir_recursive(&dotdot, (S_IRUSR | S_IWUSR | S_IXUSR) as i32));
76-
}
77-
78-
#[test]
79-
fn recursive_mkdir_rel_2() {
80-
use std::libc::consts::os::posix88::{S_IRUSR, S_IWUSR, S_IXUSR};
81-
use std::os;
82-
use std::unstable::change_dir_locked;
83-
84-
let root = mkdtemp(&os::tmpdir(), "recursive_mkdir_rel_2").
85-
expect("recursive_mkdir_rel_2");
86-
assert!(do change_dir_locked(&root) {
87-
let path = Path("./frob/baz");
88-
debug!("recursive_mkdir_rel_2: Making: %s in cwd %s [%?]", path.to_str(),
89-
os::getcwd().to_str(), os::path_exists(&path));
90-
assert!(os::mkdir_recursive(&path, (S_IRUSR | S_IWUSR | S_IXUSR) as i32));
91-
assert!(os::path_is_dir(&path));
92-
assert!(os::path_is_dir(&path.pop()));
93-
let path2 = Path("quux/blat");
94-
debug!("recursive_mkdir_rel_2: Making: %s in cwd %s", path2.to_str(),
95-
os::getcwd().to_str());
96-
assert!(os::mkdir_recursive(&path2, (S_IRUSR | S_IWUSR | S_IXUSR) as i32));
97-
assert!(os::path_is_dir(&path2));
98-
assert!(os::path_is_dir(&path2.pop()));
99-
});
100-
}
101-
102-
// Ideally this would be in core, but needs mkdtemp
103-
#[test]
104-
pub fn test_rmdir_recursive_ok() {
105-
use std::libc::consts::os::posix88::{S_IRUSR, S_IWUSR, S_IXUSR};
106-
use std::os;
107-
108-
let rwx = (S_IRUSR | S_IWUSR | S_IXUSR) as i32;
109-
110-
let tmpdir = mkdtemp(&os::tmpdir(), "test").expect("test_rmdir_recursive_ok: \
111-
couldn't create temp dir");
112-
let root = tmpdir.push("foo");
113-
114-
debug!("making %s", root.to_str());
115-
assert!(os::make_dir(&root, rwx));
116-
assert!(os::make_dir(&root.push("foo"), rwx));
117-
assert!(os::make_dir(&root.push("foo").push("bar"), rwx));
118-
assert!(os::make_dir(&root.push("foo").push("bar").push("blat"), rwx));
119-
assert!(os::remove_dir_recursive(&root));
120-
assert!(!os::path_exists(&root));
121-
assert!(!os::path_exists(&root.push("bar")));
122-
assert!(!os::path_exists(&root.push("bar").push("blat")));
123-
}
124-
}
31+
// the tests for this module need to change the path using change_dir,
32+
// and this doesn't play nicely with other tests so these unit tests are located
33+
// in src/test/run-pass/tempfile.rs

src/librustpkg/tests.rs

+13-14
Original file line numberDiff line numberDiff line change
@@ -819,26 +819,25 @@ fn rust_path_test() {
819819
}
820820
821821
#[test]
822+
#[ignore] // FIXME(#9184) tests can't change the cwd (other tests are sad then)
822823
fn rust_path_contents() {
823-
use std::unstable::change_dir_locked;
824-
825824
let dir = mkdtemp(&os::tmpdir(), "rust_path").expect("rust_path_contents failed");
826825
let abc = &dir.push("A").push("B").push("C");
827826
assert!(os::mkdir_recursive(&abc.push(".rust"), U_RWX));
828827
assert!(os::mkdir_recursive(&abc.pop().push(".rust"), U_RWX));
829828
assert!(os::mkdir_recursive(&abc.pop().pop().push(".rust"), U_RWX));
830-
assert!(do change_dir_locked(&dir.push("A").push("B").push("C")) {
831-
let p = rust_path();
832-
let cwd = os::getcwd().push(".rust");
833-
let parent = cwd.pop().pop().push(".rust");
834-
let grandparent = cwd.pop().pop().pop().push(".rust");
835-
assert!(p.contains(&cwd));
836-
assert!(p.contains(&parent));
837-
assert!(p.contains(&grandparent));
838-
for a_path in p.iter() {
839-
assert!(!a_path.components.is_empty());
840-
}
841-
});
829+
assert!(os::change_dir(abc));
830+
831+
let p = rust_path();
832+
let cwd = os::getcwd().push(".rust");
833+
let parent = cwd.pop().pop().push(".rust");
834+
let grandparent = cwd.pop().pop().pop().push(".rust");
835+
assert!(p.contains(&cwd));
836+
assert!(p.contains(&parent));
837+
assert!(p.contains(&grandparent));
838+
for a_path in p.iter() {
839+
assert!(!a_path.components.is_empty());
840+
}
842841
}
843842
844843
#[test]

src/libstd/unstable/mod.rs

-53
Original file line numberDiff line numberDiff line change
@@ -68,59 +68,6 @@ fn test_run_in_bare_thread_exchange() {
6868
}
6969
}
7070

71-
72-
/// Changes the current working directory to the specified
73-
/// path while acquiring a global lock, then calls `action`.
74-
/// If the change is successful, releases the lock and restores the
75-
/// CWD to what it was before, returning true.
76-
/// Returns false if the directory doesn't exist or if the directory change
77-
/// is otherwise unsuccessful.
78-
///
79-
/// This is used by test cases to avoid cwd races.
80-
///
81-
/// # Safety Note
82-
///
83-
/// This uses a pthread mutex so descheduling in the action callback
84-
/// can lead to deadlock. Calling change_dir_locked recursively will
85-
/// also deadlock.
86-
pub fn change_dir_locked(p: &Path, action: &fn()) -> bool {
87-
#[fixed_stack_segment]; #[inline(never)];
88-
89-
use os;
90-
use os::change_dir;
91-
use unstable::sync::atomically;
92-
use unstable::finally::Finally;
93-
94-
unsafe {
95-
// This is really sketchy. Using a pthread mutex so descheduling
96-
// in the `action` callback can cause deadlock. Doing it in
97-
// `task::atomically` to try to avoid that, but ... I don't know
98-
// this is all bogus.
99-
return do atomically {
100-
rust_take_change_dir_lock();
101-
102-
do (||{
103-
let old_dir = os::getcwd();
104-
if change_dir(p) {
105-
action();
106-
change_dir(&old_dir)
107-
}
108-
else {
109-
false
110-
}
111-
}).finally {
112-
rust_drop_change_dir_lock();
113-
}
114-
}
115-
}
116-
117-
extern {
118-
fn rust_take_change_dir_lock();
119-
fn rust_drop_change_dir_lock();
120-
}
121-
}
122-
123-
12471
/// Dynamically inquire about whether we're running under V.
12572
/// You should usually not use this unless your test definitely
12673
/// can't run correctly un-altered. Valgrind is there to help

src/rt/rust_builtin.cpp

-12
Original file line numberDiff line numberDiff line change
@@ -603,18 +603,6 @@ rust_get_global_args_ptr() {
603603
return &global_args_ptr;
604604
}
605605

606-
static lock_and_signal change_dir_lock;
607-
608-
extern "C" CDECL void
609-
rust_take_change_dir_lock() {
610-
change_dir_lock.lock();
611-
}
612-
613-
extern "C" CDECL void
614-
rust_drop_change_dir_lock() {
615-
change_dir_lock.unlock();
616-
}
617-
618606
// Used by i386 __morestack
619607
extern "C" CDECL uintptr_t
620608
rust_get_task() {

src/rt/rustrt.def.in

-2
Original file line numberDiff line numberDiff line change
@@ -186,8 +186,6 @@ rust_get_num_cpus
186186
rust_get_global_args_ptr
187187
rust_take_global_args_lock
188188
rust_drop_global_args_lock
189-
rust_take_change_dir_lock
190-
rust_drop_change_dir_lock
191189
rust_take_linenoise_lock
192190
rust_drop_linenoise_lock
193191
rust_get_test_int

src/test/run-pass/glob-std.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,9 @@ use std::{io, os, unstable};
1919

2020
pub fn main() {
2121
fn change_then_remove(p: &Path, f: &fn()) {
22-
do (|| {
23-
unstable::change_dir_locked(p, || f());
24-
}).finally {
22+
assert!(os::change_dir(p));
23+
24+
do f.finally {
2525
os::remove_dir_recursive(p);
2626
}
2727
}

src/test/run-pass/tempfile.rs

+100
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// xfail-fast windows doesn't like 'extern mod extra'
12+
13+
// These tests are here to exercise the functionality of the `tempfile` module.
14+
// One might expect these tests to be located in that module, but sadly they
15+
// cannot. The tests need to invoke `os::change_dir` which cannot be done in the
16+
// normal test infrastructure. If the tests change the current working
17+
// directory, then *all* tests which require relative paths suddenly break b/c
18+
// they're in a different location than before. Hence, these tests are all run
19+
// serially here.
20+
21+
extern mod extra;
22+
23+
use extra::tempfile::mkdtemp;
24+
use std::os;
25+
use std::libc::consts::os::posix88::{S_IRUSR, S_IWUSR, S_IXUSR};
26+
27+
fn test_mkdtemp() {
28+
let p = mkdtemp(&Path("."), "foobar").unwrap();
29+
os::remove_dir(&p);
30+
assert!(p.to_str().ends_with("foobar"));
31+
}
32+
33+
// Ideally these would be in std::os but then core would need
34+
// to depend on std
35+
fn recursive_mkdir_rel() {
36+
let path = Path("frob");
37+
debug!("recursive_mkdir_rel: Making: %s in cwd %s [%?]", path.to_str(),
38+
os::getcwd().to_str(),
39+
os::path_exists(&path));
40+
assert!(os::mkdir_recursive(&path, (S_IRUSR | S_IWUSR | S_IXUSR) as i32));
41+
assert!(os::path_is_dir(&path));
42+
assert!(os::mkdir_recursive(&path, (S_IRUSR | S_IWUSR | S_IXUSR) as i32));
43+
assert!(os::path_is_dir(&path));
44+
}
45+
46+
fn recursive_mkdir_dot() {
47+
let dot = Path(".");
48+
assert!(os::mkdir_recursive(&dot, (S_IRUSR | S_IWUSR | S_IXUSR) as i32));
49+
let dotdot = Path("..");
50+
assert!(os::mkdir_recursive(&dotdot, (S_IRUSR | S_IWUSR | S_IXUSR) as i32));
51+
}
52+
53+
fn recursive_mkdir_rel_2() {
54+
let path = Path("./frob/baz");
55+
debug!("recursive_mkdir_rel_2: Making: %s in cwd %s [%?]", path.to_str(),
56+
os::getcwd().to_str(), os::path_exists(&path));
57+
assert!(os::mkdir_recursive(&path, (S_IRUSR | S_IWUSR | S_IXUSR) as i32));
58+
assert!(os::path_is_dir(&path));
59+
assert!(os::path_is_dir(&path.pop()));
60+
let path2 = Path("quux/blat");
61+
debug!("recursive_mkdir_rel_2: Making: %s in cwd %s", path2.to_str(),
62+
os::getcwd().to_str());
63+
assert!(os::mkdir_recursive(&path2, (S_IRUSR | S_IWUSR | S_IXUSR) as i32));
64+
assert!(os::path_is_dir(&path2));
65+
assert!(os::path_is_dir(&path2.pop()));
66+
}
67+
68+
// Ideally this would be in core, but needs mkdtemp
69+
pub fn test_rmdir_recursive_ok() {
70+
let rwx = (S_IRUSR | S_IWUSR | S_IXUSR) as i32;
71+
72+
let tmpdir = mkdtemp(&os::tmpdir(), "test").expect("test_rmdir_recursive_ok: \
73+
couldn't create temp dir");
74+
let root = tmpdir.push("foo");
75+
76+
debug!("making %s", root.to_str());
77+
assert!(os::make_dir(&root, rwx));
78+
assert!(os::make_dir(&root.push("foo"), rwx));
79+
assert!(os::make_dir(&root.push("foo").push("bar"), rwx));
80+
assert!(os::make_dir(&root.push("foo").push("bar").push("blat"), rwx));
81+
assert!(os::remove_dir_recursive(&root));
82+
assert!(!os::path_exists(&root));
83+
assert!(!os::path_exists(&root.push("bar")));
84+
assert!(!os::path_exists(&root.push("bar").push("blat")));
85+
}
86+
87+
fn in_tmpdir(f: &fn()) {
88+
let tmpdir = mkdtemp(&os::tmpdir(), "test").expect("can't make tmpdir");
89+
assert!(os::change_dir(&tmpdir));
90+
91+
f();
92+
}
93+
94+
fn main() {
95+
in_tmpdir(test_mkdtemp);
96+
in_tmpdir(recursive_mkdir_rel);
97+
in_tmpdir(recursive_mkdir_dot);
98+
in_tmpdir(recursive_mkdir_rel_2);
99+
in_tmpdir(test_rmdir_recursive_ok);
100+
}

0 commit comments

Comments
 (0)