@@ -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,59 @@ 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+ root. rm_rf ( ) ;
117+ SymlinkBuilder :: new_dir ( r, root) . mk ( ) ;
118+ }
96119 guard
97120}
98121
99122impl Drop for TestIdGuard {
100123 fn drop ( & mut self ) {
124+ #[ cfg( windows) ]
101125 TEST_ID . with ( |n| * n. borrow_mut ( ) = None ) ;
126+ #[ cfg( not( windows) ) ]
127+ TEST_NAME . with ( |n| * n. borrow_mut ( ) = None ) ;
102128 }
103129}
104130
105131/// Path to the test's filesystem scratchpad
106132///
107133/// ex: `$CARGO_TARGET_TMPDIR/cit/t0`
134+ #[ cfg( windows) ]
108135pub fn root ( ) -> PathBuf {
109136 let id = TEST_ID . with ( |n| {
110137 n. borrow ( ) . expect (
@@ -118,6 +145,23 @@ pub fn root() -> PathBuf {
118145 root
119146}
120147
148+ /// Path to the test's filesystem scratchpad
149+ ///
150+ /// ex: `$CARGO_TARGET_TMPDIR/cit/t0`
151+ #[ cfg( not( windows) ) ]
152+ pub fn root ( ) -> PathBuf {
153+ let test_name = TEST_NAME . with ( |n| {
154+ n. borrow ( ) . clone ( ) . expect (
155+ "Tests must use the `#[cargo_test]` attribute in \
156+ order to be able to use the crate root.",
157+ )
158+ } ) ;
159+
160+ let mut root = global_root ( ) ;
161+ root. push ( & test_name) ;
162+ root
163+ }
164+
121165/// Path to the current test's `$HOME`
122166///
123167/// ex: `$CARGO_TARGET_TMPDIR/cit/t0/home`
@@ -489,3 +533,26 @@ pub fn windows_reserved_names_are_allowed() -> bool {
489533 true
490534 }
491535}
536+
537+ /// This takes the test location (std::file!() should be passed) and the test name
538+ /// and outputs the location the test should be places in, inside of `target/tmp/cit`
539+ ///
540+ /// `path: tests/testsuite/workspaces.rs`
541+ /// `name: `workspace_in_git
542+ /// `output: "testsuite/workspaces/workspace_in_git`
543+ pub fn test_dir ( path : & str , name : & str ) -> std:: path:: PathBuf {
544+ let test_dir: std:: path:: PathBuf = std:: path:: PathBuf :: from ( path)
545+ . components ( )
546+ // Trim .rs from any files
547+ . map ( |c| c. as_os_str ( ) . to_str ( ) . unwrap ( ) . trim_end_matches ( ".rs" ) )
548+ // We only want to take once we have reached `tests` or `src`. This helps when in a
549+ // workspace: `workspace/more/src/...` would result in `src/...`
550+ . skip_while ( |c| c != & "tests" && c != & "src" )
551+ // We want to skip "tests" since it is taken in `skip_while`.
552+ // "src" is fine since you could have test in "src" named the same as one in "tests"
553+ // Skip "mod" since `snapbox` tests have a folder per test not a file and the files
554+ // are named "mod.rs"
555+ . filter ( |c| c != & "tests" && c != & "mod" )
556+ . collect ( ) ;
557+ test_dir. join ( name)
558+ }
0 commit comments