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 // REQUIRES: can-create-symlinks
10 // UNSUPPORTED: c++03, c++11, c++14
11 // UNSUPPORTED: no-filesystem
12 // UNSUPPORTED: availability-filesystem-missing
13
14 // This test requires the dylib support introduced in D92769.
15 // XFAIL: stdlib=apple-libc++ && target={{.+}}-apple-macosx{{10.15|11.0}}
16
17 // <filesystem>
18
19 // bool create_directories(const path& p);
20 // bool create_directories(const path& p, error_code& ec) noexcept;
21
22 #include <filesystem>
23 #include <type_traits>
24 #include <cassert>
25
26 #include "assert_macros.h"
27 #include "test_macros.h"
28 #include "filesystem_test_helper.h"
29 namespace fs = std::filesystem;
30 using namespace fs;
31
test_signatures()32 static void test_signatures()
33 {
34 const path p; ((void)p);
35 std::error_code ec; ((void)ec);
36 ASSERT_SAME_TYPE(decltype(fs::create_directories(p)), bool);
37 ASSERT_SAME_TYPE(decltype(fs::create_directories(p, ec)), bool);
38 ASSERT_NOT_NOEXCEPT(fs::create_directories(p));
39 ASSERT_NOT_NOEXCEPT(fs::create_directories(p, ec));
40 }
41
create_existing_directory()42 static void create_existing_directory()
43 {
44 scoped_test_env env;
45 const path dir = env.create_dir("dir1");
46 std::error_code ec;
47 assert(fs::create_directories(dir, ec) == false);
48 assert(!ec);
49 assert(is_directory(dir));
50 }
51
create_directory_one_level()52 static void create_directory_one_level()
53 {
54 scoped_test_env env;
55 const path dir = env.make_env_path("dir1");
56 std::error_code ec;
57 assert(fs::create_directories(dir, ec) == true);
58 assert(!ec);
59 assert(is_directory(dir));
60 }
61
create_directories_multi_level()62 static void create_directories_multi_level()
63 {
64 scoped_test_env env;
65 const path dir = env.make_env_path("dir1/dir2/dir3");
66 std::error_code ec;
67 assert(fs::create_directories(dir, ec) == true);
68 assert(!ec);
69 assert(is_directory(dir));
70 }
71
create_directory_symlinks()72 static void create_directory_symlinks() {
73 scoped_test_env env;
74 const path root = env.create_dir("dir");
75 const path sym_dest_dead = env.make_env_path("dead");
76 const path dead_sym = env.create_directory_symlink(sym_dest_dead, "dir/sym_dir");
77 const path target = env.make_env_path("dir/sym_dir/foo");
78 {
79 std::error_code ec = GetTestEC();
80 assert(create_directories(target, ec) == false);
81 assert(ec);
82 assert(ErrorIs(ec, std::errc::file_exists));
83 assert(!exists(sym_dest_dead));
84 assert(!exists(dead_sym));
85 }
86 }
87
create_directory_through_symlinks()88 static void create_directory_through_symlinks() {
89 scoped_test_env env;
90 const path root = env.create_dir("dir");
91 const path sym_dir = env.create_directory_symlink(root, "sym_dir");
92 const path target = env.make_env_path("sym_dir/foo");
93 const path resolved_target = env.make_env_path("dir/foo");
94 assert(is_directory(sym_dir));
95 {
96 std::error_code ec = GetTestEC();
97 assert(create_directories(target, ec) == true);
98 assert(!ec);
99 assert(is_directory(target));
100 assert(is_directory(resolved_target));
101 }
102 }
103
dest_is_file()104 static void dest_is_file()
105 {
106 scoped_test_env env;
107 const path file = env.create_file("file", 42);
108 std::error_code ec = GetTestEC();
109 assert(fs::create_directories(file, ec) == false);
110 assert(ec);
111 assert(ErrorIs(ec, std::errc::file_exists));
112 assert(is_regular_file(file));
113 }
114
dest_part_is_file()115 static void dest_part_is_file()
116 {
117 scoped_test_env env;
118 const path file = env.create_file("file");
119 const path dir = env.make_env_path("file/dir1");
120 std::error_code ec = GetTestEC();
121 assert(fs::create_directories(dir, ec) == false);
122 assert(ec);
123 assert(ErrorIs(ec, std::errc::not_a_directory));
124 assert(is_regular_file(file));
125 assert(!exists(dir));
126 }
127
dest_final_part_is_file()128 static void dest_final_part_is_file()
129 {
130 scoped_test_env env;
131 env.create_dir("dir");
132 const path file = env.create_file("dir/file");
133 const path dir = env.make_env_path("dir/file/dir1");
134 std::error_code ec = GetTestEC();
135 assert(fs::create_directories(dir, ec) == false);
136 assert(ec);
137 assert(ErrorIs(ec, std::errc::not_a_directory));
138 assert(is_regular_file(file));
139 assert(!exists(dir));
140 }
141
dest_is_empty_path()142 static void dest_is_empty_path()
143 {
144 std::error_code ec = GetTestEC();
145 assert(fs::create_directories(fs::path{}, ec) == false);
146 assert(ec);
147 assert(ErrorIs(ec, std::errc::no_such_file_or_directory));
148 ExceptionChecker Checker(path{}, std::errc::no_such_file_or_directory,
149 "create_directories");
150 TEST_VALIDATE_EXCEPTION(filesystem_error, Checker,
151 fs::create_directories(path{}));
152 }
153
154 #ifdef _WIN32
nonexistent_root()155 static void nonexistent_root()
156 {
157 std::error_code ec = GetTestEC();
158 // If Q:\ doesn't exist, create_directories would try to recurse upwards
159 // to parent_path() until it finds a directory that does exist. As the
160 // whole path is the root name, parent_path() returns itself, and it
161 // would recurse indefinitely, unless the recursion is broken.
162 if (!exists("Q:\\"))
163 assert(fs::create_directories("Q:\\", ec) == false);
164 assert(fs::create_directories("\\\\nonexistentserver", ec) == false);
165 }
166 #endif // _WIN32
167
main(int,char **)168 int main(int, char**) {
169 test_signatures();
170 create_existing_directory();
171 create_directory_one_level();
172 create_directories_multi_level();
173 create_directory_symlinks();
174 create_directory_through_symlinks();
175 dest_is_file();
176 dest_part_is_file();
177 dest_final_part_is_file();
178 dest_is_empty_path();
179 #ifdef _WIN32
180 nonexistent_root();
181 #endif
182
183 return 0;
184 }
185