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 e4ed349c7658.
15// XFAIL: using-built-library-before-llvm-12
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"
29namespace fs = std::filesystem;
30using namespace fs;
31
32static 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: p));
39 ASSERT_NOT_NOEXCEPT(fs::create_directories(p: p, ec&: ec));
40}
41
42static 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
52static 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
62static 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
72static 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
88static 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
104static 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
115static 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
128static 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
142static 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
155static 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
168int 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

source code of libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.create_directories/create_directories.pass.cpp