1 //===----------------------------------------------------------------------===//
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
7 //===----------------------------------------------------------------------===//
9 // REQUIRES: can-create-symlinks
10 // UNSUPPORTED: c++03, c++11, c++14
11 // UNSUPPORTED: no-filesystem
12 // UNSUPPORTED: availability-filesystem-missing
16 // void rename(const path& old_p, const path& new_p);
17 // void rename(const path& old_p, const path& new_p, error_code& ec) noexcept;
21 #include "test_macros.h"
22 #include "filesystem_test_helper.h"
23 namespace fs
= std::filesystem
;
26 static void test_signatures()
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);
33 ASSERT_NOT_NOEXCEPT(fs::rename(p
, p
));
34 ASSERT_NOEXCEPT(fs::rename(p
, p
, ec
));
37 static void test_error_reporting()
39 auto checkThrow
= [](path
const& f
, path
const& t
, const std::error_code
& ec
)
41 #ifndef TEST_HAS_NO_EXCEPTIONS
45 } catch (filesystem_error
const& err
) {
46 return err
.path1() == f
51 ((void)f
); ((void)t
); ((void)ec
);
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");
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.
73 for (auto& TC
: cases
) {
74 auto from_before
= status(TC
.from
);
75 auto to_before
= status(TC
.to
);
77 rename(TC
.from
, TC
.to
, ec
);
79 assert(from_before
.type() == status(TC
.from
).type());
80 assert(to_before
.type() == status(TC
.to
).type());
81 assert(checkThrow(TC
.from
, TC
.to
, ec
));
85 static void basic_rename_test()
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);
92 std::error_code ec
= set_ec
;
93 rename(file
, file
, ec
);
95 assert(is_regular_file(file
));
96 assert(file_size(file
) == 42);
98 const path sym
= env
.create_symlink(file
, "sym");
100 std::error_code ec
= set_ec
;
101 rename(file
, sym
, ec
);
103 assert(!exists(file
));
104 assert(is_regular_file(symlink_status(sym
)));
105 assert(file_size(sym
) == 42);
107 const path file2
= env
.create_file("file2", 42);
108 const path file3
= env
.create_file("file3", 100);
110 std::error_code ec
= set_ec
;
111 rename(file2
, file3
, ec
);
113 assert(!exists(file2
));
114 assert(is_regular_file(file3
));
115 assert(file_size(file3
) == 42);
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");
121 std::error_code ec
= set_ec
;
122 rename(bad_sym
, bad_sym_dest
, ec
);
124 assert(!exists(symlink_status(bad_sym
)));
125 assert(is_symlink(bad_sym_dest
));
126 assert(read_symlink(bad_sym_dest
) == dne
);
130 static void basic_rename_dir_test()
133 const std::error_code set_ec
= std::make_error_code(std::errc::address_in_use
);
134 const path new_dir
= env
.makePath("new_dir");
135 { // dir -> dir (with contents)
136 std::error_code ec
= set_ec
;
137 rename(env
.Dir
, new_dir
, ec
);
139 assert(!exists(env
.Dir
));
140 assert(is_directory(new_dir
));
141 assert(exists(new_dir
/ "file1"));
144 // On Windows, renaming a directory over a file isn't an error (this
145 // case is skipped in test_error_reporting above).
147 std::error_code ec
= set_ec
;
148 rename(new_dir
, env
.NonEmptyFile
, ec
);
150 assert(!exists(new_dir
));
151 assert(is_directory(env
.NonEmptyFile
));
152 assert(exists(env
.NonEmptyFile
/ "file1"));
157 int main(int, char**) {
159 test_error_reporting();
161 basic_rename_dir_test();