1 //===----------------------------------------------------------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 // UNSUPPORTED: c++03 10 11 // <filesystem> 12 13 // void rename(const path& old_p, const path& new_p); 14 // void rename(const path& old_p, const path& new_p, error_code& ec) noexcept; 15 16 #include "filesystem_include.h" 17 18 #include "test_macros.h" 19 #include "rapid-cxx-test.h" 20 #include "filesystem_test_helper.h" 21 22 using namespace fs; 23 24 TEST_SUITE(filesystem_rename_test_suite) 25 26 TEST_CASE(test_signatures) 27 { 28 const path p; ((void)p); 29 std::error_code ec; ((void)ec); 30 ASSERT_SAME_TYPE(decltype(fs::rename(p, p)), void); 31 ASSERT_SAME_TYPE(decltype(fs::rename(p, p, ec)), void); 32 33 ASSERT_NOT_NOEXCEPT(fs::rename(p, p)); 34 ASSERT_NOEXCEPT(fs::rename(p, p, ec)); 35 } 36 37 TEST_CASE(test_error_reporting) 38 { 39 auto checkThrow = [](path const& f, path const& t, const std::error_code& ec) 40 { 41 #ifndef TEST_HAS_NO_EXCEPTIONS 42 try { 43 fs::rename(f, t); 44 return false; 45 } catch (filesystem_error const& err) { 46 return err.path1() == f 47 && err.path2() == t 48 && err.code() == ec; 49 } 50 #else 51 ((void)f); ((void)t); ((void)ec); 52 return true; 53 #endif 54 }; 55 scoped_test_env env; 56 const path dne = env.make_env_path("dne"); 57 const path file = env.create_file("file1", 42); 58 const path dir = env.create_dir("dir1"); 59 struct TestCase { 60 path from; 61 path to; 62 } cases[] = { 63 {dne, dne}, 64 {file, dir}, 65 #ifndef _WIN32 66 // The spec doesn't say that this case must be an error; fs.op.rename 67 // note 1.2.1 says that a file may be overwritten by a rename. 68 // On Windows, with rename() implemented with MoveFileExW, overwriting 69 // a file with a directory is not an error. 70 {dir, file}, 71 #endif 72 }; 73 for (auto& TC : cases) { 74 auto from_before = status(TC.from); 75 auto to_before = status(TC.to); 76 std::error_code ec; 77 rename(TC.from, TC.to, ec); 78 TEST_REQUIRE(ec); 79 TEST_CHECK(from_before.type() == status(TC.from).type()); 80 TEST_CHECK(to_before.type() == status(TC.to).type()); 81 TEST_CHECK(checkThrow(TC.from, TC.to, ec)); 82 } 83 } 84 85 TEST_CASE(basic_rename_test) 86 { 87 scoped_test_env env; 88 89 const std::error_code set_ec = std::make_error_code(std::errc::address_in_use); 90 const path file = env.create_file("file1", 42); 91 { // same file 92 std::error_code ec = set_ec; 93 rename(file, file, ec); 94 TEST_CHECK(!ec); 95 TEST_CHECK(is_regular_file(file)); 96 TEST_CHECK(file_size(file) == 42); 97 } 98 const path sym = env.create_symlink(file, "sym"); 99 { // file -> symlink 100 std::error_code ec = set_ec; 101 rename(file, sym, ec); 102 TEST_CHECK(!ec); 103 TEST_CHECK(!exists(file)); 104 TEST_CHECK(is_regular_file(symlink_status(sym))); 105 TEST_CHECK(file_size(sym) == 42); 106 } 107 const path file2 = env.create_file("file2", 42); 108 const path file3 = env.create_file("file3", 100); 109 { // file -> file 110 std::error_code ec = set_ec; 111 rename(file2, file3, ec); 112 TEST_CHECK(!ec); 113 TEST_CHECK(!exists(file2)); 114 TEST_CHECK(is_regular_file(file3)); 115 TEST_CHECK(file_size(file3) == 42); 116 } 117 const path dne = env.make_env_path("dne"); 118 const path bad_sym = env.create_symlink(dne, "bad_sym"); 119 const path bad_sym_dest = env.make_env_path("bad_sym2"); 120 { // bad-symlink 121 std::error_code ec = set_ec; 122 rename(bad_sym, bad_sym_dest, ec); 123 TEST_CHECK(!ec); 124 TEST_CHECK(!exists(symlink_status(bad_sym))); 125 TEST_CHECK(is_symlink(bad_sym_dest)); 126 TEST_CHECK(read_symlink(bad_sym_dest) == dne); 127 } 128 } 129 130 TEST_SUITE_END() 131