@@ -53,10 +53,10 @@ template <typename Elem, typename Traits>
5353 return str.size () >= prefix.size () && Traits::compare (str.data (), prefix.data (), prefix.size ()) == 0 ;
5454}
5555
56- struct test_temp_directory {
57- error_code ec;
56+ struct [[nodiscard]] test_temp_directory {
5857 path directoryPath;
59- explicit test_temp_directory (const string_view testName) : directoryPath(get_new_test_directory(testName)) {
58+ explicit test_temp_directory (const string_view testName) : directoryPath (get_test_directory (testName)) {
59+ error_code ec;
6060 remove_all (directoryPath, ec);
6161 if (ec) {
6262 wcerr << L" Warning, couldn't clean up " << directoryPath << L" before test.\n " ;
@@ -68,7 +68,11 @@ struct test_temp_directory {
6868 }
6969 }
7070
71+ test_temp_directory (const test_temp_directory&) = delete ;
72+ test_temp_directory& operator =(const test_temp_directory&) = delete ;
73+
7174 ~test_temp_directory () noexcept {
75+ error_code ec;
7276 remove_all (directoryPath, ec);
7377 if (ec) {
7478 wcerr << L" Warning, couldn't clean up " << directoryPath << L" after test.\n " ;
@@ -1420,8 +1424,8 @@ void test_recursive_directory_iterator() {
14201424 test_directory_iterator_common_parts<recursive_directory_iterator>(" recursive_directory_iterator" sv);
14211425
14221426 {
1423- const test_temp_directory recursiveTests (" recursive_directory_iterator specific" sv);
1424- create_file_containing (recursiveTests .directoryPath / L" a.txt" sv, L" hello" );
1427+ const test_temp_directory tempDir (" recursive_directory_iterator- specific" sv);
1428+ create_file_containing (tempDir .directoryPath / L" a.txt" sv, L" hello" );
14251429
14261430 // _NODISCARD directory_options options() const;
14271431 // _NODISCARD int depth() const;
@@ -1430,19 +1434,19 @@ void test_recursive_directory_iterator() {
14301434 // void disable_recursion_pending();
14311435 {
14321436 error_code ec;
1433- recursive_directory_iterator good_dir (recursiveTests .directoryPath , directory_options::none, ec);
1437+ recursive_directory_iterator good_dir (tempDir .directoryPath , directory_options::none, ec);
14341438 if (!EXPECT (good (ec))) {
14351439 return ;
14361440 }
14371441
14381442 EXPECT (good_dir.options () == directory_options::none);
14391443
14401444 recursive_directory_iterator good_dir2 (
1441- recursiveTests .directoryPath , directory_options::skip_permission_denied, ec);
1445+ tempDir .directoryPath , directory_options::skip_permission_denied, ec);
14421446 EXPECT (good_dir2.options () == directory_options::skip_permission_denied);
14431447
14441448 recursive_directory_iterator good_dir3 (
1445- recursiveTests .directoryPath , directory_options::follow_directory_symlink, ec);
1449+ tempDir .directoryPath , directory_options::follow_directory_symlink, ec);
14461450 EXPECT (good_dir3.options () == directory_options::follow_directory_symlink);
14471451
14481452 EXPECT (good_dir.depth () == 0 );
@@ -1461,7 +1465,7 @@ void test_recursive_directory_iterator() {
14611465
14621466 // void pop();
14631467 {
1464- recursive_directory_iterator good_dir (recursiveTests .directoryPath , directory_options::none);
1468+ recursive_directory_iterator good_dir (tempDir .directoryPath , directory_options::none);
14651469 good_dir.pop ();
14661470 EXPECT (good_dir == recursive_directory_iterator{});
14671471 }
@@ -1481,10 +1485,10 @@ void test_recursive_directory_iterator() {
14811485
14821486 // Also test VSO-649431 <filesystem> follow_directory_symlinks with a broken symlink causes iteration to break
14831487 {
1484- const test_temp_directory followSymlinkTests ( " recursive_directory_iterator_VSO -649431" sv);
1485- const path aaa = followSymlinkTests .directoryPath / L" aaa" sv;
1486- const path bbb = followSymlinkTests .directoryPath / L" bbb" sv;
1487- const path ccc = followSymlinkTests .directoryPath / L" ccc" sv;
1488+ const test_temp_directory tempDir ( " recursive_directory_iterator-VSO -649431" sv);
1489+ const path aaa = tempDir .directoryPath / L" aaa" sv;
1490+ const path bbb = tempDir .directoryPath / L" bbb" sv;
1491+ const path ccc = tempDir .directoryPath / L" ccc" sv;
14881492 error_code ec;
14891493 create_directory_symlink (nonexistentPaths[0 ], bbb, ec);
14901494 if (ec) {
@@ -1496,7 +1500,7 @@ void test_recursive_directory_iterator() {
14961500 directory_options::follow_directory_symlink, directory_options::skip_permission_denied,
14971501 directory_options::follow_directory_symlink | directory_options::skip_permission_denied};
14981502 for (const auto & option : options) {
1499- recursive_directory_iterator first (followSymlinkTests .directoryPath , option);
1503+ recursive_directory_iterator first (tempDir .directoryPath , option);
15001504 assert (first != recursive_directory_iterator{});
15011505 EXPECT (first->is_directory ());
15021506 EXPECT (!first->is_symlink ());
@@ -2883,7 +2887,7 @@ void test_invalid_conversions() {
28832887}
28842888
28852889void test_status () {
2886- const test_temp_directory tempDir (" test_status " sv);
2890+ const test_temp_directory tempDir (" status " sv);
28872891 const path& testDir = tempDir.directoryPath ;
28882892 const path testFile (testDir / L" test_file" sv);
28892893 const path testLink (testDir / L" test_link" sv);
@@ -3328,9 +3332,9 @@ void test_rename() {
33283332 const path fileA (tempDir.directoryPath / L" filea.txt" sv);
33293333 const path fileB (tempDir.directoryPath / L" fileb.txt" sv);
33303334
3331- create_directories (dir. native () , ec);
3335+ create_directories (dir, ec);
33323336 EXPECT (good (ec));
3333- create_directory (otherDir. native () , ec);
3337+ create_directory (otherDir, ec);
33343338 EXPECT (good (ec));
33353339 create_file_containing (fileA, L" hello" );
33363340 create_file_containing (fileB, L" world" );
@@ -3342,15 +3346,26 @@ void test_rename() {
33423346 EXPECT (good (ec));
33433347 EXPECT (read_file_contents (fileA) == L" hello" );
33443348
3349+ #ifndef _MSVC_INTERNAL_TESTING // TRANSITION, skip this for all MSVC-internal test runs.
3350+ // As of 2024-05-09, these rename() tests sporadically fail in MSVC-internal private test runs with
3351+ // "Access is denied" error codes. We've never observed such failures in MSVC-internal PR/CI checks,
3352+ // MSVC-internal local test runs, GitHub PR/CI checks, or GitHub local test runs. There's no significant
3353+ // compiler interaction here, so we can live with GitHub-only test coverage. Although we don't know the
3354+ // root cause, we suspect that this is related to the physical machines that are used for MSVC-internal
3355+ // private test runs, so we should check whether they've been replaced in a year or two.
3356+
33453357 // If new_p resolves to an existing non-directory file, new_p is removed
33463358 rename (fileA, fileB, ec);
33473359 EXPECT (good (ec));
3348- EXPECT (!exists (fileA. native () ));
3360+ EXPECT (!exists (fileA));
33493361 EXPECT (read_file_contents (fileB) == L" hello" );
33503362
33513363 // Standard rename where target doesn't exist
3352- rename (fileB, fileA);
3364+ rename (fileB, fileA, ec);
3365+ EXPECT (good (ec));
3366+ EXPECT (!exists (fileB));
33533367 EXPECT (read_file_contents (fileA) == L" hello" );
3368+ #endif // ^^^ no workaround ^^^
33543369
33553370 // Bad cases
33563371 EXPECT (throws_filesystem_error ([&] { rename (dir, otherDir); }, " rename" , dir, otherDir));
@@ -3364,7 +3379,7 @@ void test_space() {
33643379 const path file (dir / L" test_space_file.txt" sv);
33653380
33663381 error_code ec;
3367- create_directory (dir. native () , ec);
3382+ create_directory (dir, ec);
33683383 EXPECT (good (ec));
33693384 create_file_containing (file, L" hello" );
33703385
@@ -3643,7 +3658,7 @@ void test_create_directory() {
36433658}
36443659
36453660void test_create_dirs_and_remove_all () {
3646- const test_temp_directory tempDir (" create_dirs_and_remove_all " sv);
3661+ const test_temp_directory tempDir (" create_directories-and-remove_all " sv);
36473662 const path& r = tempDir.directoryPath ;
36483663
36493664 // test long path support
0 commit comments