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