]>
git.ipfire.org Git - thirdparty/gcc.git/blob - libstdc++-v3/testsuite/util/testsuite_fs.h
2 // Filesystem utils for the C++ library testsuite.
4 // Copyright (C) 2014-2021 Free Software Foundation, Inc.
6 // This file is part of the GNU ISO C++ Library. This library is free
7 // software; you can redistribute it and/or modify it under the
8 // terms of the GNU General Public License as published by the
9 // Free Software Foundation; either version 3, or (at your option)
12 // This library is distributed in the hope that it will be useful,
13 // but WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 // GNU General Public License for more details.
17 // You should have received a copy of the GNU General Public License along
18 // with this library; see the file COPYING3. If not see
19 // <http://www.gnu.org/licenses/>.
22 #ifndef _TESTSUITE_FS_H
23 #define _TESTSUITE_FS_H 1
25 // Assume we want std::filesystem in C++17, unless USE_FILESYSTEM_TS defined:
26 #if __cplusplus >= 201703L && ! defined USE_FILESYSTEM_TS
28 namespace test_fs
= std::filesystem
;
30 #include <experimental/filesystem>
31 namespace test_fs
= std::experimental::filesystem
;
38 #if defined(_GNU_SOURCE) || _XOPEN_SOURCE >= 500 || _POSIX_C_SOURCE >= 200112L
39 #include <stdlib.h> // mkstemp
40 #include <unistd.h> // unlink, close
42 #include <random> // std::random_device
47 #define PATH_CHK(p1, p2, fn) \
48 if ( p1.fn() != p2.fn() ) \
49 throw test_fs::filesystem_error("comparing '" #fn "' failed", p1, p2, \
50 std::make_error_code(std::errc::invalid_argument) )
53 compare_paths(const test_fs::path
& p1
,
54 const test_fs::path
& p2
)
56 PATH_CHK( p1
, p2
, native
);
57 PATH_CHK( p1
, p2
, string
);
58 PATH_CHK( p1
, p2
, empty
);
59 PATH_CHK( p1
, p2
, has_root_path
);
60 PATH_CHK( p1
, p2
, has_root_name
);
61 PATH_CHK( p1
, p2
, has_root_directory
);
62 PATH_CHK( p1
, p2
, has_relative_path
);
63 PATH_CHK( p1
, p2
, has_parent_path
);
64 PATH_CHK( p1
, p2
, has_filename
);
65 PATH_CHK( p1
, p2
, has_stem
);
66 PATH_CHK( p1
, p2
, has_extension
);
67 PATH_CHK( p1
, p2
, is_absolute
);
68 PATH_CHK( p1
, p2
, is_relative
);
69 auto d1
= std::distance(p1
.begin(), p1
.end());
70 auto d2
= std::distance(p2
.begin(), p2
.end());
72 throw test_fs::filesystem_error(
73 "distance(begin1, end1) != distance(begin2, end2)", p1
, p2
,
74 std::make_error_code(std::errc::invalid_argument
) );
75 if (!std::equal(p1
.begin(), p1
.end(), p2
.begin()))
76 throw test_fs::filesystem_error(
77 "!equal(begin1, end1, begin2)", p1
, p2
,
78 std::make_error_code(std::errc::invalid_argument
) );
82 const std::string test_paths
[] = {
83 "", "/", "//", "/.", "/./", "/a", "/a/", "/a//", "/a/b/c/d", "/a//b",
84 "a", "a/b", "a/b/", "a/b/c", "a/b/c.d", "a/b/..", "a/b/c.", "a/b/.c"
90 #if defined(__MINGW32__) || defined(__MINGW64__)
97 // This is NOT supposed to be a secure way to get a unique name!
98 // We just need a path that doesn't exist for testing purposes.
100 nonexistent_path(std::string file
= __builtin_FILE())
102 // Include the caller's filename to help identify tests that fail to
103 // clean up the files they create.
104 // Remove .cc extension:
105 if (file
.length() > 3 && file
.compare(file
.length() - 3, 3, ".cc") == 0)
106 file
.resize(file
.length() - 3);
108 auto pos
= file
.find_last_of("/\\");
109 if (pos
!= file
.npos
)
110 file
.erase(0, pos
+1);
113 #if defined(_GNU_SOURCE) || _XOPEN_SOURCE >= 500 || _POSIX_C_SOURCE >= 200112L
114 char tmp
[] = "filesystem-test.XXXXXX";
115 int fd
= ::mkstemp(tmp
);
117 throw test_fs::filesystem_error("mkstemp failed",
118 std::error_code(errno
, std::generic_category()));
122 file
.insert(0, 1, '-');
126 if (file
.length() > 64)
129 static unsigned counter
= std::random_device
{}();
130 #if _GLIBCXX_USE_C99_STDIO
131 std::snprintf(buf
, 128,
135 "filesystem-test.%u.%lu-%s", counter
++, (unsigned long) ::getpid(),
142 // RAII helper to remove a file on scope exit.
145 using path_type
= test_fs::path
;
147 enum adopt_file_t
{ adopt_file
};
150 scoped_file(const path_type
& p
= nonexistent_path()) : path(p
)
151 { std::ofstream
{p
.c_str()}; }
153 scoped_file(path_type p
, adopt_file_t
) : path(p
) { }
155 ~scoped_file() { if (!path
.empty()) remove(path
); }
157 scoped_file(scoped_file
&&) = default;
158 scoped_file
& operator=(scoped_file
&&) = default;
163 } // namespace __gnu_test