]>
Commit | Line | Data |
---|---|---|
6cda876d | 1 | // { dg-do run { target c++17 } } |
6cda876d | 2 | |
99dee823 | 3 | // Copyright (C) 2018-2021 Free Software Foundation, Inc. |
6cda876d JW |
4 | // |
5 | // This file is part of the GNU ISO C++ Library. This library is free | |
6 | // software; you can redistribute it and/or modify it under the | |
7 | // terms of the GNU General Public License as published by the | |
8 | // Free Software Foundation; either version 3, or (at your option) | |
9 | // any later version. | |
10 | ||
11 | // This library is distributed in the hope that it will be useful, | |
12 | // but WITHOUT ANY WARRANTY; without even the implied warranty of | |
13 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
14 | // GNU General Public License for more details. | |
15 | ||
16 | // You should have received a copy of the GNU General Public License along | |
17 | // with this library; see the file COPYING3. If not see | |
18 | // <http://www.gnu.org/licenses/>. | |
19 | ||
20 | // C++17 30.10.8.4.3 path appends [fs.path.append] | |
21 | ||
22 | #include <filesystem> | |
23 | #include <string_view> | |
24 | #include <testsuite_fs.h> | |
25 | #include <testsuite_iterators.h> | |
26 | ||
27 | using std::filesystem::path; | |
28 | using __gnu_test::compare_paths; | |
29 | ||
30 | // path::operator/=(const Source& source) | |
31 | // path::append(const Source& source) | |
32 | // Equivalent to: return operator/=(path(source)); | |
33 | ||
34 | // path::append(InputIterator first, InputIterator last) | |
35 | // Equivalent to: return operator/=(path(first, last)); | |
36 | ||
49d729ea JW |
37 | template<typename Char> |
38 | void test(const path& p, const Char* s) | |
6cda876d JW |
39 | { |
40 | path expected = p; | |
41 | expected /= path(s); | |
42 | ||
43 | path oper = p; | |
44 | oper /= s; | |
45 | ||
46 | path func = p; | |
47 | func.append(s); | |
48 | ||
49d729ea JW |
49 | __gnu_test::test_container<const Char, __gnu_test::input_iterator_wrapper> |
50 | input_range(s, s + std::char_traits<Char>::length(s)); | |
6cda876d JW |
51 | path range = p; |
52 | range.append(input_range.begin(), input_range.end()); | |
53 | ||
54 | compare_paths( oper, expected ); | |
55 | compare_paths( func, expected ); | |
56 | compare_paths( range, expected ); | |
57 | } | |
58 | ||
59 | void | |
60 | test01() | |
61 | { | |
62 | test( "/foo/bar", "/foo/" ); | |
63 | ||
64 | test( "baz", "baz" ); | |
65 | test( "baz/", "baz" ); | |
66 | test( "baz", "/foo/bar" ); | |
67 | test( "baz/", "/foo/bar" ); | |
68 | ||
69 | test( "", "" ); | |
70 | test( "", "rel" ); | |
71 | ||
72 | test( "dir/", "/file" ); | |
73 | test( "dir/", "file" ); | |
74 | } | |
75 | ||
76 | void | |
77 | test02() | |
78 | { | |
79 | // C++17 [fs.path.append] p4 | |
80 | test( "//host", "foo" ); | |
81 | test( "//host/", "foo" ); | |
82 | test( "foo", "" ); | |
83 | test( "foo", "/bar" ); | |
84 | test( "foo", "c:/bar" ); | |
85 | test( "foo", "c:" ); | |
86 | test( "c:", "" ); | |
87 | test( "c:foo", "/bar" ); | |
88 | test( "foo", "c:\\bar" ); | |
89 | } | |
90 | ||
91 | void | |
92 | test03() | |
93 | { | |
4a7c7999 JW |
94 | for (const path p : __gnu_test::test_paths) |
95 | for (const path q : __gnu_test::test_paths) | |
49d729ea JW |
96 | { |
97 | test(p, q.c_str()); | |
98 | if constexpr (!std::is_same_v<path::value_type, char>) | |
99 | test(p, q.string().c_str()); | |
100 | } | |
101 | } | |
102 | ||
103 | void | |
104 | test04() | |
105 | { | |
106 | #ifdef _GLIBCXX_USE_WCHAR_T | |
107 | test( "foo", L"/bar" ); | |
108 | test( L"foo", "/bar" ); | |
109 | test( L"foo", L"/bar" ); | |
110 | #endif | |
6cda876d JW |
111 | } |
112 | ||
4f87bb8d JW |
113 | void |
114 | test05() | |
115 | { | |
116 | std::basic_string_view<path::value_type> s; | |
117 | ||
118 | path p = "0/1/2/3/4/5/6"; | |
119 | // The string_view aliases the path's internal string: | |
120 | s = p.native(); | |
080cec7f JW |
121 | path::string_type expected(s); |
122 | expected += path::preferred_separator; | |
123 | expected += s; | |
4f87bb8d JW |
124 | // Append that string_view, which must work correctly even though the |
125 | // internal string will be reallocated during the operation: | |
126 | p /= s; | |
080cec7f | 127 | compare_paths(p, expected); |
4f87bb8d JW |
128 | |
129 | // Same again with a trailing slash: | |
130 | path p2 = "0/1/2/3/4/5/"; | |
131 | s = p2.native(); | |
080cec7f JW |
132 | expected = s; |
133 | expected += s; | |
4f87bb8d | 134 | p2 /= s; |
080cec7f | 135 | compare_paths(p2, expected); |
4f87bb8d JW |
136 | |
137 | // And aliasing one of the components of the path: | |
138 | path p3 = "0/123456789/a"; | |
139 | path::iterator second = std::next(p3.begin()); | |
140 | s = second->native(); | |
080cec7f JW |
141 | expected = p3.native() + path::preferred_separator; |
142 | expected += s; | |
4f87bb8d | 143 | p3 /= s; |
080cec7f JW |
144 | compare_paths(p3, expected); |
145 | } | |
2017595d JW |
146 | |
147 | void | |
148 | test06() | |
149 | { | |
150 | const std::string s0 = "a/b/c"; | |
151 | path p = s0; | |
152 | std::string s; | |
153 | for (int i = 0; i < 10; ++i) | |
154 | s += "0/1/2/3/4/5/6/7/8/9/"; | |
155 | // append a long string with many components | |
156 | test(p, s.c_str()); | |
157 | ||
158 | // Same again but with a trailing slash on the left operand: | |
159 | path p2 = s0 + '/'; | |
160 | test(p2, s.c_str()); | |
4f87bb8d JW |
161 | } |
162 | ||
49ff88bd JW |
163 | void |
164 | test07() | |
165 | { | |
166 | path p, p0; | |
167 | std::string_view s; | |
168 | p /= s; // PR libstdc++/97167 | |
169 | compare_paths(p, p0); | |
170 | } | |
171 | ||
6cda876d JW |
172 | int |
173 | main() | |
174 | { | |
175 | test01(); | |
176 | test02(); | |
177 | test03(); | |
49d729ea | 178 | test04(); |
4f87bb8d | 179 | test05(); |
2017595d | 180 | test06(); |
49ff88bd | 181 | test07(); |
6cda876d | 182 | } |