@@ -46,16 +46,13 @@ pub fn global_root() -> PathBuf {
4646 }
4747}
4848
49- // We need to give each test a unique id. The test name could serve this
50- // purpose, but the `test` crate doesn't have a way to obtain the current test
51- // name.[*] Instead, we used the `cargo-test-macro` crate to automatically
52- // insert an init function for each test that sets the test name in a thread
53- // local variable.
54- //
55- // [*] It does set the thread name, but only when running concurrently. If not
56- // running concurrently, all tests are run on the main thread.
49+ // We need to give each test a unique id. The test name serve this
50+ // purpose. We are able to get the test name by having the `cargo-test-macro`
51+ // crate automatically insert an init function for each test that sets the
52+ // test name in a thread local variable.
5753thread_local ! {
5854 static TEST_ID : RefCell <Option <usize >> = const { RefCell :: new( None ) } ;
55+ static TEST_DIR : RefCell <Option <PathBuf >> = const { RefCell :: new( None ) } ;
5956}
6057
6158/// See [`init_root`]
@@ -64,44 +61,56 @@ pub struct TestIdGuard {
6461}
6562
6663/// For test harnesses like [`crate::cargo_test`]
67- pub fn init_root ( tmp_dir : & ' static str ) -> TestIdGuard {
64+ pub fn init_root ( tmp_dir : & ' static str , test_dir : PathBuf ) -> TestIdGuard {
6865 static NEXT_ID : AtomicUsize = AtomicUsize :: new ( 0 ) ;
69-
7066 let id = NEXT_ID . fetch_add ( 1 , Ordering :: SeqCst ) ;
7167 TEST_ID . with ( |n| * n. borrow_mut ( ) = Some ( id) ) ;
72-
68+ if cfg ! ( windows) {
69+ // Due to path-length limits, Windows doesn't use the full test name.
70+ TEST_DIR . with ( |n| * n. borrow_mut ( ) = Some ( PathBuf :: from ( format ! ( "t{id}" ) ) ) ) ;
71+ } else {
72+ TEST_DIR . with ( |n| * n. borrow_mut ( ) = Some ( test_dir) ) ;
73+ }
7374 let guard = TestIdGuard { _private : ( ) } ;
74-
7575 set_global_root ( tmp_dir) ;
7676 let r = root ( ) ;
7777 r. rm_rf ( ) ;
7878 r. mkdir_p ( ) ;
79-
79+ #[ cfg( not( windows) ) ]
80+ if id == 0 {
81+ // Create a symlink from `t0` to the first test to make it easier to
82+ // find and reuse when running a single test.
83+ use crate :: SymlinkBuilder ;
84+ let mut alias = global_root ( ) ;
85+ alias. push ( "t0" ) ;
86+ alias. rm_rf ( ) ;
87+ SymlinkBuilder :: new_dir ( r, alias) . mk ( ) ;
88+ }
8089 guard
8190}
8291
8392impl Drop for TestIdGuard {
8493 fn drop ( & mut self ) {
8594 TEST_ID . with ( |n| * n. borrow_mut ( ) = None ) ;
95+ TEST_DIR . with ( |n| * n. borrow_mut ( ) = None ) ;
8696 }
8797}
8898
8999/// Path to the test's filesystem scratchpad
90100///
91- /// ex: `$CARGO_TARGET_TMPDIR/cit/t0`
101+ /// ex: `$CARGO_TARGET_TMPDIR/cit/<integration test>/<module>/<fn name>/`
102+ /// or `$CARGO_TARGET_TMPDIR/cit/t0` on Windows
92103pub fn root ( ) -> PathBuf {
93- let id = TEST_ID . with ( |n| {
94- n. borrow ( ) . expect (
104+ let test_dir = TEST_DIR . with ( |n| {
105+ n. borrow ( ) . clone ( ) . expect (
95106 "Tests must use the `#[cargo_test]` attribute in \
96107 order to be able to use the crate root.",
97108 )
98109 } ) ;
99-
100110 let mut root = global_root ( ) ;
101- root. push ( & format ! ( "t{}" , id ) ) ;
111+ root. push ( & test_dir ) ;
102112 root
103113}
104-
105114/// Path to the current test's `$HOME`
106115///
107116/// ex: `$CARGO_TARGET_TMPDIR/cit/t0/home`
@@ -473,3 +482,26 @@ pub fn windows_reserved_names_are_allowed() -> bool {
473482 true
474483 }
475484}
485+
486+ /// This takes the test location (std::file!() should be passed) and the test name
487+ /// and outputs the location the test should be places in, inside of `target/tmp/cit`
488+ ///
489+ /// `path: tests/testsuite/workspaces.rs`
490+ /// `name: `workspace_in_git
491+ /// `output: "testsuite/workspaces/workspace_in_git`
492+ pub fn test_dir ( path : & str , name : & str ) -> std:: path:: PathBuf {
493+ let test_dir: std:: path:: PathBuf = std:: path:: PathBuf :: from ( path)
494+ . components ( )
495+ // Trim .rs from any files
496+ . map ( |c| c. as_os_str ( ) . to_str ( ) . unwrap ( ) . trim_end_matches ( ".rs" ) )
497+ // We only want to take once we have reached `tests` or `src`. This helps when in a
498+ // workspace: `workspace/more/src/...` would result in `src/...`
499+ . skip_while ( |c| c != & "tests" && c != & "src" )
500+ // We want to skip "tests" since it is taken in `skip_while`.
501+ // "src" is fine since you could have test in "src" named the same as one in "tests"
502+ // Skip "mod" since `snapbox` tests have a folder per test not a file and the files
503+ // are named "mod.rs"
504+ . filter ( |c| c != & "tests" && c != & "mod" )
505+ . collect ( ) ;
506+ test_dir. join ( name)
507+ }
0 commit comments