@@ -62,16 +62,15 @@ pub fn global_root() -> PathBuf {
6262 }
6363}
6464
65- // We need to give each test a unique id. The test name could serve this
66- // purpose, but the `test` crate doesn't have a way to obtain the current test
67- // name.[*] Instead, we used the `cargo-test-macro` crate to automatically
68- // insert an init function for each test that sets the test name in a thread
69- // local variable.
70- //
71- // [*] It does set the thread name, but only when running concurrently. If not
72- // running concurrently, all tests are run on the main thread.
65+ // We need to give each test a unique id. The test name serve this
66+ // purpose. We are able to get the test name by having the `cargo-test-macro`
67+ // crate automatically insert an init function for each test that sets the
68+ // test name in a thread local variable.
7369thread_local ! {
70+ #[ cfg( windows) ]
7471 static TEST_ID : RefCell <Option <usize >> = const { RefCell :: new( None ) } ;
72+ #[ cfg( not( windows) ) ]
73+ static TEST_NAME : RefCell <Option <PathBuf >> = const { RefCell :: new( None ) } ;
7574}
7675
7776/// See [`init_root`]
@@ -80,31 +79,58 @@ pub struct TestIdGuard {
8079}
8180
8281/// For test harnesses like [`crate::cargo_test`]
82+ #[ cfg( windows) ]
8383pub fn init_root ( tmp_dir : Option < & ' static str > ) -> TestIdGuard {
8484 static NEXT_ID : AtomicUsize = AtomicUsize :: new ( 0 ) ;
8585
8686 let id = NEXT_ID . fetch_add ( 1 , Ordering :: SeqCst ) ;
8787 TEST_ID . with ( |n| * n. borrow_mut ( ) = Some ( id) ) ;
88+ let guard = TestIdGuard { _private : ( ) } ;
89+
90+ set_global_root ( tmp_dir) ;
91+ let r = root ( ) ;
92+ r. rm_rf ( ) ;
93+ r. mkdir_p ( ) ;
94+
95+ guard
96+ }
97+
98+ /// For test harnesses like [`crate::cargo_test`]
99+ #[ cfg( not( windows) ) ]
100+ pub fn init_root ( tmp_dir : Option < & ' static str > , test_name : PathBuf ) -> TestIdGuard {
101+ static NEXT_ID : AtomicUsize = AtomicUsize :: new ( 0 ) ;
102+ let id = NEXT_ID . fetch_add ( 1 , Ordering :: SeqCst ) ;
88103
104+ TEST_NAME . with ( |n| * n. borrow_mut ( ) = Some ( test_name) ) ;
89105 let guard = TestIdGuard { _private : ( ) } ;
90106
91107 set_global_root ( tmp_dir) ;
92108 let r = root ( ) ;
93109 r. rm_rf ( ) ;
94110 r. mkdir_p ( ) ;
111+ if id == 0 {
112+ use crate :: SymlinkBuilder ;
95113
114+ let mut root = global_root ( ) ;
115+ root. push ( & format ! ( "t{}" , id) ) ;
116+ SymlinkBuilder :: new_dir ( r, root) . mk ( ) ;
117+ }
96118 guard
97119}
98120
99121impl Drop for TestIdGuard {
100122 fn drop ( & mut self ) {
123+ #[ cfg( windows) ]
101124 TEST_ID . with ( |n| * n. borrow_mut ( ) = None ) ;
125+ #[ cfg( not( windows) ) ]
126+ TEST_NAME . with ( |n| * n. borrow_mut ( ) = None ) ;
102127 }
103128}
104129
105130/// Path to the test's filesystem scratchpad
106131///
107132/// ex: `$CARGO_TARGET_TMPDIR/cit/t0`
133+ #[ cfg( windows) ]
108134pub fn root ( ) -> PathBuf {
109135 let id = TEST_ID . with ( |n| {
110136 n. borrow ( ) . expect (
@@ -118,6 +144,23 @@ pub fn root() -> PathBuf {
118144 root
119145}
120146
147+ /// Path to the test's filesystem scratchpad
148+ ///
149+ /// ex: `$CARGO_TARGET_TMPDIR/cit/t0`
150+ #[ cfg( not( windows) ) ]
151+ pub fn root ( ) -> PathBuf {
152+ let test_name = TEST_NAME . with ( |n| {
153+ n. borrow ( ) . clone ( ) . expect (
154+ "Tests must use the `#[cargo_test]` attribute in \
155+ order to be able to use the crate root.",
156+ )
157+ } ) ;
158+
159+ let mut root = global_root ( ) ;
160+ root. push ( & test_name) ;
161+ root
162+ }
163+
121164/// Path to the current test's `$HOME`
122165///
123166/// ex: `$CARGO_TARGET_TMPDIR/cit/t0/home`
@@ -489,3 +532,26 @@ pub fn windows_reserved_names_are_allowed() -> bool {
489532 true
490533 }
491534}
535+
536+ /// This takes the test location (std::file!() should be passed) and the test name
537+ /// and outputs the location the test should be places in, inside of `target/tmp/cit`
538+ ///
539+ /// `path: tests/testsuite/workspaces.rs`
540+ /// `name: `workspace_in_git
541+ /// `output: "testsuite/workspaces/workspace_in_git`
542+ pub fn test_dir ( path : & str , name : & str ) -> std:: path:: PathBuf {
543+ let test_dir: std:: path:: PathBuf = std:: path:: PathBuf :: from ( path)
544+ . components ( )
545+ // Trim .rs from any files
546+ . map ( |c| c. as_os_str ( ) . to_str ( ) . unwrap ( ) . trim_end_matches ( ".rs" ) )
547+ // We only want to take once we have reached `tests` or `src`. This helps when in a
548+ // workspace: `workspace/more/src/...` would result in `src/...`
549+ . skip_while ( |c| c != & "tests" && c != & "src" )
550+ // We want to skip "tests" since it is taken in `skip_while`.
551+ // "src" is fine since you could have test in "src" named the same as one in "tests"
552+ // Skip "mod" since `snapbox` tests have a folder per test not a file and the files
553+ // are named "mod.rs"
554+ . filter ( |c| c != & "tests" && c != & "mod" )
555+ . collect ( ) ;
556+ test_dir. join ( name)
557+ }
0 commit comments