]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | // filesystem path_unit_test.cpp --------------------------------------------------- // |
2 | ||
3 | // Copyright Beman Dawes 2008, 2009 | |
4 | ||
5 | // Distributed under the Boost Software License, Version 1.0. | |
6 | // See http://www.boost.org/LICENSE_1_0.txt | |
7 | ||
8 | // Library home page: http://www.boost.org/libs/filesystem | |
9 | ||
10 | // ---------------------------------------------------------------------------------- // | |
11 | // | |
12 | // The purpose of this test is to ensure that each function in the public | |
13 | // interface can be called with arguments of the appropriate types. It does | |
14 | // not attempt to verify that the full range of values for each argument | |
15 | // are processed correctly. | |
16 | // | |
17 | // For full functionality tests, including probes with many different argument | |
18 | // values, see path_test.cpp and other test programs. | |
19 | // | |
20 | // ---------------------------------------------------------------------------------- // | |
21 | ||
22 | #include <boost/config/warning_disable.hpp> | |
23 | ||
24 | // See deprecated_test for tests of deprecated features | |
92f5a8d4 | 25 | #ifndef BOOST_FILESYSTEM_NO_DEPRECATED |
7c673cae FG |
26 | # define BOOST_FILESYSTEM_NO_DEPRECATED |
27 | #endif | |
92f5a8d4 | 28 | #ifndef BOOST_SYSTEM_NO_DEPRECATED |
7c673cae FG |
29 | # define BOOST_SYSTEM_NO_DEPRECATED |
30 | #endif | |
31 | ||
32 | #include <boost/filesystem/path.hpp> | |
33 | ||
34 | #include <boost/filesystem/detail/utf8_codecvt_facet.hpp> // for imbue tests | |
35 | #include "test_codecvt.hpp" // for codecvt arg tests | |
36 | #include <boost/detail/lightweight_test_report.hpp> | |
37 | #include <boost/smart_ptr.hpp> // used constructor tests | |
38 | #include <boost/functional/hash.hpp> | |
39 | ||
40 | #include <iostream> | |
41 | #include <iomanip> | |
42 | #include <sstream> | |
43 | #include <string> | |
44 | #include <cstring> | |
45 | #include <cwchar> | |
46 | #include <locale> | |
47 | #include <list> | |
48 | ||
49 | namespace fs = boost::filesystem; | |
50 | namespace bs = boost::system; | |
51 | using boost::filesystem::path; | |
52 | using std::cout; | |
53 | using std::endl; | |
54 | using std::string; | |
55 | using std::wstring; | |
56 | ||
57 | #define CHECK(x) check(x, __FILE__, __LINE__) | |
58 | #define PATH_IS(a, b) check_path(a, b, __FILE__, __LINE__) | |
59 | #define NATIVE_IS(p, s, ws) check_native(p, s, ws, __FILE__, __LINE__) | |
60 | #define IS(a,b) check_equal(a, b, __FILE__, __LINE__) | |
61 | ||
62 | #if defined(_MSC_VER) | |
63 | # pragma warning(push) // Save warning settings. | |
64 | # pragma warning(disable : 4428) // Disable universal-character-name encountered in source warning. | |
65 | #endif | |
66 | ||
67 | namespace | |
68 | { | |
69 | ||
70 | boost::system::error_code ec; | |
71 | const boost::system::error_code ok; | |
72 | const boost::system::error_code ng(-1, boost::system::system_category()); | |
73 | ||
74 | std::string platform(BOOST_PLATFORM); | |
75 | ||
76 | void check_path(const path& source, | |
77 | const wstring& expected, const char* file, int line) | |
78 | { | |
79 | if (source == expected) return; | |
80 | ||
81 | ++::boost::detail::test_errors(); | |
82 | ||
83 | std::cout << file; | |
84 | std::wcout << L'(' << line << L"): source.wstring(): \"" | |
85 | << source.wstring() | |
86 | << L"\" != expected: \"" << expected | |
87 | << L"\"\n" ; | |
88 | } | |
89 | ||
90 | # ifdef BOOST_WINDOWS_API | |
91 | void check_native(const path& p, | |
92 | const string&, const wstring& expected, const char* file, int line) | |
93 | # else | |
94 | void check_native(const path& p, | |
95 | const string& expected, const wstring&, const char* file, int line) | |
96 | # endif | |
97 | { | |
98 | if (p.native() == expected) return; | |
99 | ||
100 | ++::boost::detail::test_errors(); | |
101 | ||
102 | std::cout << file << '(' << line << "): native() is not equal expected\n" | |
103 | " native---: " << std::hex; | |
104 | path::string_type nat(p.native()); | |
105 | for (path::string_type::const_iterator it = nat.begin(); it != nat.end(); ++it) | |
106 | std::cout << long(*it) << ' '; | |
107 | std::cout << "\n expected-: "; | |
108 | for (path::string_type::const_iterator it = expected.begin(); it != expected.end(); ++it) | |
109 | std::cout << long(*it) << ' '; | |
110 | std::cout << std::dec << std::endl; | |
111 | } | |
112 | ||
113 | template< class T1, class T2 > | |
114 | void check_equal(const T1& value, | |
115 | const T2& expected, const char* file, int line) | |
116 | { | |
117 | if (value == expected) return; | |
118 | ||
119 | ++::boost::detail::test_errors(); | |
120 | ||
121 | std::cout << file; | |
122 | ||
123 | std::wcout << L'(' << line << L"): value: \"" << value | |
124 | << L"\" != expected: \"" << expected | |
125 | << L"\"\n" ; | |
126 | } | |
127 | ||
128 | void check(bool ok_, const char* file, int line) | |
129 | { | |
130 | if (ok_) return; | |
131 | ||
132 | ++::boost::detail::test_errors(); | |
133 | ||
134 | std::cout << file << '(' << line << "): test failed\n"; | |
135 | } | |
136 | ||
137 | string s("string"); | |
138 | wstring ws(L"wstring"); | |
139 | std::list<char> l; // see main() for initialization to s, t, r, i, n, g | |
140 | std::list<wchar_t> wl; // see main() for initialization to w, s, t, r, i, n, g | |
141 | std::vector<char> v; // see main() for initialization to f, u, z | |
142 | std::vector<wchar_t> wv; // see main() for initialization to w, f, u, z | |
143 | ||
144 | class Base {}; | |
145 | class Derived : public Base {}; | |
146 | void fun(const boost::shared_ptr< Base >&) {} | |
147 | ||
148 | // test_constructors ---------------------------------------------------------------// | |
149 | ||
150 | void test_constructors() | |
151 | { | |
152 | std::cout << "testing constructors..." << std::endl; | |
153 | ||
154 | path x0; // default constructor | |
155 | PATH_IS(x0, L""); | |
156 | BOOST_TEST_EQ(x0.native().size(), 0U); | |
157 | ||
158 | path x1(l.begin(), l.end()); // iterator range char | |
159 | PATH_IS(x1, L"string"); | |
160 | BOOST_TEST_EQ(x1.native().size(), 6U); | |
161 | ||
162 | path x2(x1); // copy constructor | |
163 | PATH_IS(x2, L"string"); | |
164 | BOOST_TEST_EQ(x2.native().size(), 6U); | |
165 | ||
166 | path x3(wl.begin(), wl.end()); // iterator range wchar_t | |
167 | PATH_IS(x3, L"wstring"); | |
168 | BOOST_TEST_EQ(x3.native().size(), 7U); | |
169 | ||
170 | // contiguous containers | |
171 | path x4(string("std::string")); // std::string | |
172 | PATH_IS(x4, L"std::string"); | |
173 | BOOST_TEST_EQ(x4.native().size(), 11U); | |
174 | ||
175 | path x5(wstring(L"std::wstring")); // std::wstring | |
176 | PATH_IS(x5, L"std::wstring"); | |
177 | BOOST_TEST_EQ(x5.native().size(), 12U); | |
178 | ||
179 | path x4v(v); // std::vector<char> | |
180 | PATH_IS(x4v, L"fuz"); | |
181 | BOOST_TEST_EQ(x4v.native().size(), 3U); | |
182 | ||
183 | path x5v(wv); // std::vector<wchar_t> | |
184 | PATH_IS(x5v, L"wfuz"); | |
185 | BOOST_TEST_EQ(x5v.native().size(), 4U); | |
186 | ||
187 | path x6("array char"); // array char | |
188 | PATH_IS(x6, L"array char"); | |
189 | BOOST_TEST_EQ(x6.native().size(), 10U); | |
190 | ||
191 | path x7(L"array wchar_t"); // array wchar_t | |
192 | PATH_IS(x7, L"array wchar_t"); | |
193 | BOOST_TEST_EQ(x7.native().size(), 13U); | |
194 | ||
195 | char char_array[100]; | |
196 | std::strcpy(char_array, "big array char"); | |
197 | path x6o(char_array); // array char, only partially full | |
198 | PATH_IS(x6o, L"big array char"); | |
199 | BOOST_TEST_EQ(x6o.native().size(), 14U); | |
200 | ||
201 | wchar_t wchar_array[100]; | |
202 | std::wcscpy(wchar_array, L"big array wchar_t"); | |
203 | path x7o(wchar_array); // array char, only partially full | |
204 | PATH_IS(x7o, L"big array wchar_t"); | |
205 | BOOST_TEST_EQ(x7o.native().size(), 17U); | |
206 | ||
207 | path x8(s.c_str()); // const char* null terminated | |
208 | PATH_IS(x8, L"string"); | |
209 | BOOST_TEST_EQ(x8.native().size(), 6U); | |
210 | ||
211 | path x9(ws.c_str()); // const wchar_t* null terminated | |
212 | PATH_IS(x9, L"wstring"); | |
213 | BOOST_TEST_EQ(x9.native().size(), 7U); | |
214 | ||
215 | path x8nc(const_cast<char*>(s.c_str())); // char* null terminated | |
216 | PATH_IS(x8nc, L"string"); | |
217 | BOOST_TEST_EQ(x8nc.native().size(), 6U); | |
218 | ||
219 | path x9nc(const_cast<wchar_t*>(ws.c_str())); // wchar_t* null terminated | |
220 | PATH_IS(x9nc, L"wstring"); | |
221 | BOOST_TEST_EQ(x9nc.native().size(), 7U); | |
222 | ||
223 | // non-contiguous containers | |
224 | path x10(l); // std::list<char> | |
225 | PATH_IS(x10, L"string"); | |
226 | BOOST_TEST_EQ(x10.native().size(), 6U); | |
227 | ||
228 | path xll(wl); // std::list<wchar_t> | |
229 | PATH_IS(xll, L"wstring"); | |
230 | BOOST_TEST_EQ(xll.native().size(), 7U); | |
231 | ||
232 | // easy-to-make coding errors | |
233 | // path e1(x0, path::codecvt()); // fails to compile, and that is OK | |
234 | ||
92f5a8d4 | 235 | boost::shared_ptr< Derived > pDerived( new Derived() ); |
7c673cae FG |
236 | fun( pDerived ); // tests constructor member template enable_if working correctly; |
237 | // will fail to compile if enable_if not taking path off the table | |
238 | } | |
239 | ||
240 | path x; | |
241 | path y; | |
242 | ||
243 | // test_assignments ----------------------------------------------------------------// | |
244 | ||
245 | void test_assignments() | |
246 | { | |
247 | std::cout << "testing assignments..." << std::endl; | |
248 | ||
249 | x = path("yet another path"); // another path | |
250 | PATH_IS(x, L"yet another path"); | |
251 | BOOST_TEST_EQ(x.native().size(), 16U); | |
252 | ||
253 | x = x; // self-assignment | |
254 | PATH_IS(x, L"yet another path"); | |
255 | BOOST_TEST_EQ(x.native().size(), 16U); | |
256 | ||
257 | x.assign(l.begin(), l.end()); // iterator range char | |
258 | PATH_IS(x, L"string"); | |
259 | ||
260 | x.assign(wl.begin(), wl.end()); // iterator range wchar_t | |
261 | PATH_IS(x, L"wstring"); | |
262 | ||
263 | x = string("std::string"); // container char | |
264 | PATH_IS(x, L"std::string"); | |
265 | ||
266 | x = wstring(L"std::wstring"); // container wchar_t | |
267 | PATH_IS(x, L"std::wstring"); | |
268 | ||
269 | x = "array char"; // array char | |
270 | PATH_IS(x, L"array char"); | |
271 | ||
272 | x = L"array wchar"; // array wchar_t | |
273 | PATH_IS(x, L"array wchar"); | |
274 | ||
275 | x = s.c_str(); // const char* null terminated | |
276 | PATH_IS(x, L"string"); | |
277 | ||
278 | x = ws.c_str(); // const wchar_t* null terminated | |
279 | PATH_IS(x, L"wstring"); | |
280 | } | |
281 | ||
282 | // test_move_construction_and_assignment -------------------------------------------// | |
283 | ||
284 | void test_move_construction_and_assignment() | |
285 | { | |
286 | std::cout << "testing move_construction_and_assignment..." << std::endl; | |
287 | ||
288 | # if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) | |
289 | path from("long enough to avoid small object optimization"); | |
290 | path to(std::move(from)); | |
291 | BOOST_TEST(to == "long enough to avoid small object optimization"); | |
292 | if (!from.empty()) | |
293 | cout << "Note: move construction did not result in empty source path" << endl; | |
294 | ||
295 | path from2("long enough to avoid small object optimization"); | |
296 | path to2; | |
297 | to2 = std::move(from2); | |
298 | BOOST_TEST(to2 == "long enough to avoid small object optimization"); | |
299 | if (!from2.empty()) | |
300 | cout << "Note: move assignment did not result in empty rhs path" << endl; | |
301 | # else | |
92f5a8d4 | 302 | std::cout << |
7c673cae FG |
303 | "Test skipped because compiler does not support move semantics" << std::endl; |
304 | # endif | |
305 | ||
306 | } | |
307 | ||
308 | // test_appends --------------------------------------------------------------------// | |
309 | ||
310 | void test_appends() | |
311 | { | |
312 | std::cout << "testing appends..." << std::endl; | |
313 | ||
314 | # ifdef BOOST_WINDOWS_API | |
315 | # define BOOST_FS_FOO L"/foo\\" | |
316 | # else // POSIX paths | |
317 | # define BOOST_FS_FOO L"/foo/" | |
318 | # endif | |
319 | ||
320 | x = "/foo"; | |
321 | x /= path(""); // empty path | |
322 | PATH_IS(x, L"/foo"); | |
323 | ||
324 | x = "/foo"; | |
325 | x /= path("/"); // slash path | |
326 | PATH_IS(x, L"/foo/"); | |
327 | ||
328 | x = "/foo"; | |
329 | x /= path("/boo"); // slash path | |
330 | PATH_IS(x, L"/foo/boo"); | |
331 | ||
332 | x = "/foo"; | |
333 | x /= x; // self-append | |
334 | PATH_IS(x, L"/foo/foo"); | |
335 | ||
336 | x = "/foo"; | |
337 | x /= path("yet another path"); // another path | |
338 | PATH_IS(x, BOOST_FS_FOO L"yet another path"); | |
339 | ||
340 | x = "/foo"; | |
341 | x.append(l.begin(), l.end()); // iterator range char | |
342 | PATH_IS(x, BOOST_FS_FOO L"string"); | |
343 | ||
344 | x = "/foo"; | |
345 | x.append(wl.begin(), wl.end()); // iterator range wchar_t | |
346 | PATH_IS(x, BOOST_FS_FOO L"wstring"); | |
347 | ||
348 | x = "/foo"; | |
349 | x /= string("std::string"); // container char | |
350 | PATH_IS(x, BOOST_FS_FOO L"std::string"); | |
351 | ||
352 | x = "/foo"; | |
353 | x /= wstring(L"std::wstring"); // container wchar_t | |
354 | PATH_IS(x, BOOST_FS_FOO L"std::wstring"); | |
355 | ||
356 | x = "/foo"; | |
357 | x /= "array char"; // array char | |
358 | PATH_IS(x, BOOST_FS_FOO L"array char"); | |
359 | ||
360 | x = "/foo"; | |
361 | x /= L"array wchar"; // array wchar_t | |
362 | PATH_IS(x, BOOST_FS_FOO L"array wchar"); | |
363 | ||
364 | x = "/foo"; | |
365 | x /= s.c_str(); // const char* null terminated | |
366 | PATH_IS(x, BOOST_FS_FOO L"string"); | |
367 | ||
368 | x = "/foo"; | |
369 | x /= ws.c_str(); // const wchar_t* null terminated | |
370 | PATH_IS(x, BOOST_FS_FOO L"wstring"); | |
371 | } | |
372 | ||
373 | // test_concats --------------------------------------------------------------------// | |
374 | ||
375 | void test_concats() | |
376 | { | |
377 | std::cout << "testing concats..." << std::endl; | |
378 | ||
379 | x = "/foo"; | |
380 | x += path(""); // empty path | |
381 | PATH_IS(x, L"/foo"); | |
382 | ||
383 | x = "/foo"; | |
384 | x += path("/"); // slash path | |
385 | PATH_IS(x, L"/foo/"); | |
386 | ||
387 | x = "/foo"; | |
388 | x += path("boo"); // slash path | |
389 | PATH_IS(x, L"/fooboo"); | |
390 | ||
391 | x = "foo"; | |
392 | x += x; // self-append | |
393 | PATH_IS(x, L"foofoo"); | |
394 | ||
395 | x = "foo-"; | |
396 | x += path("yet another path"); // another path | |
397 | PATH_IS(x, L"foo-yet another path"); | |
398 | ||
399 | x = "foo-"; | |
400 | x.concat(l.begin(), l.end()); // iterator range char | |
401 | PATH_IS(x, L"foo-string"); | |
402 | ||
403 | x = "foo-"; | |
404 | x.concat(wl.begin(), wl.end()); // iterator range wchar_t | |
405 | PATH_IS(x, L"foo-wstring"); | |
406 | ||
407 | x = "foo-"; | |
408 | x += string("std::string"); // container char | |
409 | PATH_IS(x, L"foo-std::string"); | |
410 | ||
411 | x = "foo-"; | |
412 | x += wstring(L"std::wstring"); // container wchar_t | |
413 | PATH_IS(x, L"foo-std::wstring"); | |
414 | ||
415 | x = "foo-"; | |
416 | x += "array char"; // array char | |
417 | PATH_IS(x, L"foo-array char"); | |
418 | ||
419 | x = "foo-"; | |
420 | x += L"array wchar"; // array wchar_t | |
421 | PATH_IS(x, L"foo-array wchar"); | |
422 | ||
423 | x = "foo-"; | |
424 | x += s.c_str(); // const char* null terminated | |
425 | PATH_IS(x, L"foo-string"); | |
426 | ||
427 | x = "foo-"; | |
428 | x += ws.c_str(); // const wchar_t* null terminated | |
429 | PATH_IS(x, L"foo-wstring"); | |
430 | ||
431 | x = "foo-"; | |
432 | x += 'x'; // char | |
433 | PATH_IS(x, L"foo-x"); | |
434 | ||
435 | x = "foo-"; | |
436 | x += L'x'; // wchar | |
437 | PATH_IS(x, L"foo-x"); | |
438 | } | |
439 | ||
440 | // test_observers ------------------------------------------------------------------// | |
441 | ||
442 | void test_observers() | |
443 | { | |
444 | std::cout << "testing observers..." << std::endl; | |
445 | ||
446 | path p0("abc"); | |
447 | ||
448 | CHECK(p0.native().size() == 3); | |
449 | CHECK(p0.size() == 3); | |
450 | CHECK(p0.string() == "abc"); | |
451 | CHECK(p0.string().size() == 3); | |
452 | CHECK(p0.wstring() == L"abc"); | |
453 | CHECK(p0.wstring().size() == 3); | |
454 | ||
455 | p0 = ""; | |
456 | CHECK(p0.native().size() == 0); | |
457 | CHECK(p0.size() == 0); | |
458 | ||
459 | # ifdef BOOST_WINDOWS_API | |
460 | ||
461 | path p("abc\\def/ghi"); | |
462 | ||
463 | CHECK(std::wstring(p.c_str()) == L"abc\\def/ghi"); | |
464 | ||
465 | CHECK(p.string() == "abc\\def/ghi"); | |
466 | CHECK(p.wstring() == L"abc\\def/ghi"); | |
467 | ||
b32b8144 | 468 | CHECK(p.generic_path().string() == "abc/def/ghi"); |
7c673cae FG |
469 | CHECK(p.generic_string() == "abc/def/ghi"); |
470 | CHECK(p.generic_wstring() == L"abc/def/ghi"); | |
471 | ||
472 | CHECK(p.generic_string<string>() == "abc/def/ghi"); | |
473 | CHECK(p.generic_string<wstring>() == L"abc/def/ghi"); | |
474 | CHECK(p.generic_string<path::string_type>() == L"abc/def/ghi"); | |
475 | ||
476 | # else // BOOST_POSIX_API | |
477 | ||
478 | path p("abc\\def/ghi"); | |
479 | ||
480 | CHECK(string(p.c_str()) == "abc\\def/ghi"); | |
481 | ||
482 | CHECK(p.string() == "abc\\def/ghi"); | |
483 | CHECK(p.wstring() == L"abc\\def/ghi"); | |
484 | ||
b32b8144 | 485 | CHECK(p.generic_path().string() == "abc\\def/ghi"); |
7c673cae FG |
486 | CHECK(p.generic_string() == "abc\\def/ghi"); |
487 | CHECK(p.generic_wstring() == L"abc\\def/ghi"); | |
488 | ||
489 | CHECK(p.generic_string<string>() == "abc\\def/ghi"); | |
490 | CHECK(p.generic_string<wstring>() == L"abc\\def/ghi"); | |
491 | CHECK(p.generic_string<path::string_type>() == "abc\\def/ghi"); | |
492 | ||
493 | # endif | |
494 | } | |
495 | ||
496 | // test_relationals ----------------------------------------------------------------// | |
497 | ||
498 | void test_relationals() | |
499 | { | |
500 | std::cout << "testing relationals..." << std::endl; | |
501 | ||
502 | boost::hash<path> hash; | |
503 | ||
504 | # ifdef BOOST_WINDOWS_API | |
505 | // this is a critical use case to meet user expectations | |
506 | CHECK(path("c:\\abc") == path("c:/abc")); | |
507 | CHECK(hash(path("c:\\abc")) == hash(path("c:/abc"))); | |
508 | # endif | |
509 | ||
510 | const path p("bar"); | |
511 | const path p2("baz"); | |
512 | ||
513 | CHECK(!(p < p)); | |
514 | CHECK(p < p2); | |
515 | CHECK(!(p2 < p)); | |
516 | CHECK(p < "baz"); | |
517 | CHECK(p < string("baz")); | |
518 | CHECK(p < L"baz"); | |
519 | CHECK(p < wstring(L"baz")); | |
520 | CHECK(!("baz" < p)); | |
521 | CHECK(!(string("baz") < p)); | |
522 | CHECK(!(L"baz" < p)); | |
523 | CHECK(!(wstring(L"baz") < p)); | |
524 | ||
525 | CHECK(p == p); | |
526 | CHECK(!(p == p2)); | |
527 | CHECK(!(p2 == p)); | |
528 | CHECK(p2 == "baz"); | |
529 | CHECK(p2 == string("baz")); | |
530 | CHECK(p2 == L"baz"); | |
531 | CHECK(p2 == wstring(L"baz")); | |
532 | CHECK("baz" == p2); | |
533 | CHECK(string("baz") == p2); | |
534 | CHECK(L"baz" == p2); | |
535 | CHECK(wstring(L"baz") == p2); | |
536 | ||
537 | CHECK(hash(p) == hash(p)); | |
538 | CHECK(hash(p) != hash(p2)); // Not strictly required, but desirable | |
539 | ||
540 | CHECK(!(p != p)); | |
541 | CHECK(p != p2); | |
542 | CHECK(p2 != p); | |
543 | ||
544 | CHECK(p <= p); | |
545 | CHECK(p <= p2); | |
546 | CHECK(!(p2 <= p)); | |
547 | ||
548 | CHECK(!(p > p)); | |
549 | CHECK(!(p > p2)); | |
550 | CHECK(p2 > p); | |
551 | ||
552 | CHECK(p >= p); | |
553 | CHECK(!(p >= p2)); | |
554 | CHECK(p2 >= p); | |
555 | } | |
556 | ||
557 | // test_inserter_and_extractor -----------------------------------------------------// | |
558 | ||
559 | void test_inserter_and_extractor() | |
560 | { | |
561 | std::cout << "testing inserter and extractor..." << std::endl; | |
562 | ||
563 | path p1("foo bar"); // verify space in path roundtrips per ticket #3863 | |
564 | path p2; | |
565 | ||
566 | std::stringstream ss; | |
567 | ||
568 | CHECK(p1 != p2); | |
569 | ss << p1; | |
570 | ss >> p2; | |
571 | CHECK(p1 == p2); | |
572 | ||
573 | path wp1(L"foo bar"); | |
574 | path wp2; | |
575 | ||
576 | std::wstringstream wss; | |
577 | ||
578 | CHECK(wp1 != wp2); | |
579 | wss << wp1; | |
580 | wss >> wp2; | |
581 | CHECK(wp1 == wp2); | |
582 | } | |
583 | ||
584 | // test_other_non_members ----------------------------------------------------------// | |
585 | ||
586 | void test_other_non_members() | |
587 | { | |
588 | std::cout << "testing other_non_members..." << std::endl; | |
589 | ||
590 | path p1("foo"); | |
591 | path p2("bar"); | |
592 | ||
593 | // operator / | |
594 | ||
595 | CHECK(p1 / p2 == path("foo/bar").make_preferred()); | |
596 | CHECK("foo" / p2 == path("foo/bar").make_preferred()); | |
597 | CHECK(L"foo" / p2 == path("foo/bar").make_preferred()); | |
598 | CHECK(string("foo") / p2 == path("foo/bar").make_preferred()); | |
599 | CHECK(wstring(L"foo") / p2 == path("foo/bar").make_preferred()); | |
600 | CHECK(p1 / "bar" == path("foo/bar").make_preferred()); | |
601 | CHECK(p1 / L"bar" == path("foo/bar").make_preferred()); | |
602 | CHECK(p1 / string("bar") == path("foo/bar").make_preferred()); | |
603 | CHECK(p1 / wstring(L"bar") == path("foo/bar").make_preferred()); | |
604 | ||
605 | swap(p1, p2); | |
606 | ||
607 | CHECK(p1 == "bar"); | |
608 | CHECK(p2 == "foo"); | |
b32b8144 FG |
609 | |
610 | CHECK(!path("").filename_is_dot()); | |
611 | CHECK(!path("").filename_is_dot_dot()); | |
612 | CHECK(!path("..").filename_is_dot()); | |
613 | CHECK(!path(".").filename_is_dot_dot()); | |
614 | CHECK(!path("...").filename_is_dot_dot()); | |
615 | CHECK(path(".").filename_is_dot()); | |
616 | CHECK(path("..").filename_is_dot_dot()); | |
617 | CHECK(path("/.").filename_is_dot()); | |
618 | CHECK(path("/..").filename_is_dot_dot()); | |
619 | CHECK(!path("a.").filename_is_dot()); | |
620 | CHECK(!path("a..").filename_is_dot_dot()); | |
621 | ||
622 | // edge cases | |
623 | CHECK(path("foo/").filename() == path(".")); | |
624 | CHECK(path("foo/").filename_is_dot()); | |
625 | CHECK(path("/").filename() == path("/")); | |
626 | CHECK(!path("/").filename_is_dot()); | |
627 | # ifdef BOOST_WINDOWS_API | |
628 | CHECK(path("c:.").filename() == path(".")); | |
629 | CHECK(path("c:.").filename_is_dot()); | |
630 | CHECK(path("c:/").filename() == path("/")); | |
631 | CHECK(!path("c:\\").filename_is_dot()); | |
632 | # else | |
633 | CHECK(path("c:.").filename() == path("c:.")); | |
634 | CHECK(!path("c:.").filename_is_dot()); | |
635 | CHECK(path("c:/").filename() == path(".")); | |
636 | CHECK(path("c:/").filename_is_dot()); | |
637 | # endif | |
638 | ||
639 | // check that the implementation code to make the edge cases above work right | |
640 | // doesn't cause some non-edge cases to fail | |
641 | CHECK(path("c:").filename() != path(".")); | |
642 | CHECK(!path("c:").filename_is_dot()); | |
643 | ||
644 | // examples from reference.html | |
645 | std::cout << path(".").filename_is_dot(); // outputs 1 | |
646 | std::cout << path("/.").filename_is_dot(); // outputs 1 | |
647 | std::cout << path("foo/.").filename_is_dot(); // outputs 1 | |
648 | std::cout << path("foo/").filename_is_dot(); // outputs 1 | |
649 | std::cout << path("/").filename_is_dot(); // outputs 0 | |
650 | std::cout << path("/foo").filename_is_dot(); // outputs 0 | |
651 | std::cout << path("/foo.").filename_is_dot(); // outputs 0 | |
652 | std::cout << path("..").filename_is_dot(); // outputs 0 | |
653 | cout << std::endl; | |
7c673cae FG |
654 | } |
655 | ||
656 | // // test_modifiers ------------------------------------------------------------------// | |
657 | // | |
658 | // void test_modifiers() | |
659 | // { | |
660 | // std::cout << "testing modifiers..." << std::endl; | |
661 | // | |
662 | // } | |
663 | ||
664 | // test_iterators ------------------------------------------------------------------// | |
665 | ||
666 | void test_iterators() | |
667 | { | |
668 | std::cout << "testing iterators..." << std::endl; | |
669 | ||
670 | path p1; | |
671 | CHECK(p1.begin() == p1.end()); | |
672 | ||
673 | path p2("/"); | |
674 | CHECK(p2.begin() != p2.end()); | |
675 | CHECK(*p2.begin() == "/"); | |
676 | CHECK(++p2.begin() == p2.end()); | |
677 | ||
678 | path p3("foo/bar/baz"); | |
679 | ||
680 | path::iterator it(p3.begin()); | |
681 | CHECK(p3.begin() != p3.end()); | |
682 | CHECK(*it == "foo"); | |
683 | CHECK(*++it == "bar"); | |
684 | CHECK(*++it == "baz"); | |
685 | CHECK(*--it == "bar"); | |
686 | CHECK(*--it == "foo"); | |
687 | CHECK(*++it == "bar"); | |
688 | CHECK(*++it == "baz"); | |
689 | CHECK(++it == p3.end()); | |
690 | } | |
691 | ||
692 | // test_reverse_iterators ----------------------------------------------------------// | |
693 | ||
694 | void test_reverse_iterators() | |
695 | { | |
696 | std::cout << "testing reverse_iterators..." << std::endl; | |
697 | ||
698 | path p1; | |
699 | CHECK(p1.rbegin() == p1.rend()); | |
700 | ||
701 | path p2("/"); | |
702 | CHECK(p2.rbegin() != p2.rend()); | |
703 | CHECK(*p2.rbegin() == "/"); | |
704 | CHECK(++p2.rbegin() == p2.rend()); | |
705 | ||
706 | path p3("foo/bar/baz"); | |
707 | ||
708 | path::reverse_iterator it(p3.rbegin()); | |
709 | CHECK(p3.rbegin() != p3.rend()); | |
710 | CHECK(*it == "baz"); | |
711 | CHECK(*++it == "bar"); | |
712 | CHECK(*++it == "foo"); | |
713 | CHECK(*--it == "bar"); | |
714 | CHECK(*--it == "baz"); | |
715 | CHECK(*++it == "bar"); | |
716 | CHECK(*++it == "foo"); | |
717 | CHECK(++it == p3.rend()); | |
718 | } | |
719 | ||
720 | // test_modifiers ------------------------------------------------------------------// | |
721 | ||
722 | void test_modifiers() | |
723 | { | |
724 | std::cout << "testing modifiers..." << std::endl; | |
725 | ||
726 | CHECK(path("").remove_filename() == ""); | |
727 | CHECK(path("foo").remove_filename() == ""); | |
728 | CHECK(path("/foo").remove_filename() == "/"); | |
729 | CHECK(path("foo/bar").remove_filename() == "foo"); | |
730 | BOOST_TEST_EQ(path("foo/bar/").remove_filename(), path("foo/bar")); | |
731 | BOOST_TEST_EQ(path(".").remove_filename(), path("")); | |
732 | BOOST_TEST_EQ(path("./.").remove_filename(), path(".")); | |
733 | BOOST_TEST_EQ(path("/.").remove_filename(), path("/")); | |
734 | BOOST_TEST_EQ(path("..").remove_filename(), path("")); | |
735 | BOOST_TEST_EQ(path("../..").remove_filename(), path("..")); | |
736 | BOOST_TEST_EQ(path("/..").remove_filename(), path("/")); | |
737 | ||
738 | } | |
739 | ||
740 | // test_decompositions -------------------------------------------------------------// | |
741 | ||
742 | void test_decompositions() | |
743 | { | |
744 | std::cout << "testing decompositions..." << std::endl; | |
745 | ||
746 | CHECK(path("").root_name().string() == ""); | |
747 | CHECK(path("foo").root_name().string() == ""); | |
748 | CHECK(path("/").root_name().string() == ""); | |
749 | CHECK(path("/foo").root_name().string() == ""); | |
750 | CHECK(path("//netname").root_name().string() == "//netname"); | |
751 | CHECK(path("//netname/foo").root_name().string() == "//netname"); | |
752 | ||
753 | CHECK(path("").root_directory().string() == ""); | |
754 | CHECK(path("foo").root_directory().string() == ""); | |
755 | CHECK(path("/").root_directory().string() == "/"); | |
756 | CHECK(path("/foo").root_directory().string() == "/"); | |
757 | CHECK(path("//netname").root_directory().string() == ""); | |
758 | CHECK(path("//netname/foo").root_directory().string() == "/"); | |
759 | ||
760 | CHECK(path("").root_path().string() == ""); | |
761 | CHECK(path("/").root_path().string() == "/"); | |
762 | CHECK(path("/foo").root_path().string() == "/"); | |
763 | CHECK(path("//netname").root_path().string() == "//netname"); | |
764 | CHECK(path("//netname/foo").root_path().string() == "//netname/"); | |
765 | ||
766 | # ifdef BOOST_WINDOWS_API | |
767 | CHECK(path("c:/foo").root_path().string() == "c:/"); | |
768 | # endif | |
769 | ||
770 | CHECK(path("").relative_path().string() == ""); | |
771 | CHECK(path("/").relative_path().string() == ""); | |
772 | CHECK(path("/foo").relative_path().string() == "foo"); | |
773 | ||
774 | CHECK(path("").parent_path().string() == ""); | |
775 | CHECK(path("/").parent_path().string() == ""); | |
776 | CHECK(path("/foo").parent_path().string() == "/"); | |
777 | CHECK(path("/foo/bar").parent_path().string() == "/foo"); | |
778 | ||
779 | CHECK(path("/foo/bar/baz.zoo").filename().string() == "baz.zoo"); | |
780 | ||
781 | CHECK(path("/foo/bar/baz.zoo").stem().string() == "baz"); | |
782 | CHECK(path("/foo/bar.woo/baz").stem().string() == "baz"); | |
783 | ||
784 | CHECK(path("foo.bar.baz.tar.bz2").extension().string() == ".bz2"); | |
785 | CHECK(path("/foo/bar/baz.zoo").extension().string() == ".zoo"); | |
786 | CHECK(path("/foo/bar.woo/baz").extension().string() == ""); | |
787 | } | |
788 | ||
789 | // test_queries --------------------------------------------------------------------// | |
790 | ||
791 | void test_queries() | |
792 | { | |
793 | std::cout << "testing queries..." << std::endl; | |
794 | ||
795 | path p1(""); | |
796 | path p2("//netname/foo.doo"); | |
797 | ||
798 | CHECK(p1.empty()); | |
799 | CHECK(!p1.has_root_path()); | |
800 | CHECK(!p1.has_root_name()); | |
801 | CHECK(!p1.has_root_directory()); | |
802 | CHECK(!p1.has_relative_path()); | |
803 | CHECK(!p1.has_parent_path()); | |
804 | CHECK(!p1.has_filename()); | |
805 | CHECK(!p1.has_stem()); | |
806 | CHECK(!p1.has_extension()); | |
807 | CHECK(!p1.is_absolute()); | |
808 | CHECK(p1.is_relative()); | |
809 | ||
810 | CHECK(!p2.empty()); | |
811 | CHECK(p2.has_root_path()); | |
812 | CHECK(p2.has_root_name()); | |
813 | CHECK(p2.has_root_directory()); | |
814 | CHECK(p2.has_relative_path()); | |
815 | CHECK(p2.has_parent_path()); | |
816 | CHECK(p2.has_filename()); | |
817 | CHECK(p2.has_stem()); | |
818 | CHECK(p2.has_extension()); | |
819 | CHECK(p2.is_absolute()); | |
820 | CHECK(!p2.is_relative()); | |
821 | ||
822 | } | |
823 | ||
824 | // test_imbue_locale ---------------------------------------------------------------// | |
825 | ||
826 | void test_imbue_locale() | |
827 | { | |
828 | std::cout << "testing imbue locale..." << std::endl; | |
829 | ||
830 | // weak test case for before/after states since we don't know what characters the | |
92f5a8d4 | 831 | // default locale accepts. |
7c673cae FG |
832 | path before("abc"); |
833 | ||
834 | // So that tests are run with known encoding, use Boost UTF-8 codecvt | |
835 | // \u2722 and \xE2\x9C\xA2 are UTF-16 and UTF-8 FOUR TEARDROP-SPOKED ASTERISK | |
836 | ||
837 | std::locale global_loc = std::locale(); | |
838 | std::locale loc(global_loc, new fs::detail::utf8_codecvt_facet); | |
839 | std::cout << " imbuing locale ..." << std::endl; | |
840 | std::locale old_loc = path::imbue(loc); | |
841 | ||
842 | std::cout << " testing with the imbued locale ..." << std::endl; | |
843 | path p2("\xE2\x9C\xA2"); | |
844 | CHECK(p2.wstring().size() == 1); | |
845 | CHECK(p2.wstring()[0] == 0x2722); | |
846 | ||
847 | std::cout << " imbuing the original locale ..." << std::endl; | |
848 | path::imbue(old_loc); | |
849 | ||
850 | std::cout << " testing with the original locale ..." << std::endl; | |
851 | path after("abc"); | |
852 | CHECK(before == after); | |
853 | ||
854 | std::cout << " locale testing complete" << std::endl; | |
855 | } | |
856 | ||
857 | // test_codecvt_argument -----------------------------------------------------------// | |
858 | ||
859 | void test_codecvt_argument() | |
860 | { | |
861 | std::cout << "testing codecvt arguments..." << std::endl; | |
862 | ||
863 | const char * c1 = "a1"; | |
864 | const std::string s1(c1); | |
865 | const std::wstring ws1(L"b2"); // off-by-one mimics test_codecvt | |
866 | const std::string s2("y8"); | |
867 | const std::wstring ws2(L"z9"); | |
868 | ||
869 | test_codecvt cvt; // produces off-by-one values that will always differ from | |
870 | // the system's default locale codecvt facet | |
871 | ||
872 | int t = 0; | |
873 | ||
874 | // constructors | |
875 | std::cout << " constructors test " << ++t << std::endl; | |
876 | path p(c1, cvt); | |
877 | NATIVE_IS(p, s1, ws1); | |
878 | ||
879 | std::cout << " test " << ++t << std::endl; | |
880 | path p1(s1.begin(), s1.end(), cvt); | |
881 | NATIVE_IS(p1, s1, ws1); | |
882 | ||
883 | std::cout << " test " << ++t << std::endl; | |
884 | path p2(ws2, cvt); | |
885 | NATIVE_IS(p2, s2, ws2); | |
886 | ||
887 | std::cout << " test " << ++t << std::endl; | |
888 | path p3(ws2.begin(), ws2.end(), cvt); | |
889 | NATIVE_IS(p3, s2, ws2); | |
890 | ||
891 | // path p2(p1, cvt); // fails to compile, and that is OK | |
892 | ||
893 | // assigns | |
894 | p1.clear(); | |
895 | std::cout << " assigns test " << ++t << std::endl; | |
896 | p1.assign(s1,cvt); | |
897 | NATIVE_IS(p1, s1, ws1); | |
898 | p1.clear(); | |
899 | std::cout << " test " << ++t << std::endl; | |
900 | p1.assign(s1.begin(), s1.end(), cvt); | |
901 | NATIVE_IS(p1, s1, ws1); | |
902 | // p1.assign(p, cvt); // fails to compile, and that is OK | |
903 | ||
904 | // appends | |
905 | p1.clear(); | |
906 | std::cout << " appends test " << ++t << std::endl; | |
907 | p1.append(s1,cvt); | |
908 | NATIVE_IS(p1, s1, ws1); | |
909 | p1.clear(); | |
910 | std::cout << " test " << ++t << std::endl; | |
911 | p1.append(s1.begin(), s1.end(), cvt); | |
912 | NATIVE_IS(p1, s1, ws1); | |
913 | // p1.append(p, cvt); // fails to compile, and that is OK | |
914 | ||
915 | // native observers | |
916 | std::cout << " native observers test " << ++t << std::endl; | |
917 | CHECK(p.string<std::string>(cvt) == s1); | |
918 | std::cout << " test " << ++t << std::endl; | |
919 | CHECK(p.string(cvt) == s1); | |
920 | std::cout << " test " << ++t << std::endl; | |
921 | CHECK(p.string<std::wstring>(cvt) == ws1); | |
922 | std::cout << " test " << ++t << std::endl; | |
923 | CHECK(p.wstring(cvt) == ws1); | |
924 | ||
925 | // generic observers | |
926 | std::cout << " generic observers test " << ++t << std::endl; | |
927 | CHECK(p.generic_string<std::string>(cvt) == s1); | |
928 | std::cout << " test " << ++t << std::endl; | |
929 | CHECK(p.generic_string(cvt) == s1); | |
930 | std::cout << " test " << ++t << std::endl; | |
931 | CHECK(p.generic_string<std::wstring>(cvt) == ws1); | |
932 | std::cout << " test " << ++t << std::endl; | |
933 | CHECK(p.generic_wstring(cvt) == ws1); | |
934 | ||
935 | std::cout << " codecvt arguments testing complete" << std::endl; | |
936 | } | |
937 | ||
938 | // test_overloads ------------------------------------------------------------------// | |
939 | ||
940 | void test_overloads() | |
941 | { | |
942 | std::cout << "testing overloads..." << std::endl; | |
943 | std::string sto("hello"); | |
944 | const char a[] = "goodbye"; | |
945 | path p1(sto); | |
946 | path p2(sto.c_str()); | |
947 | path p3(a); | |
948 | path p4("foo"); | |
949 | ||
950 | std::wstring wsto(L"hello"); | |
951 | const wchar_t wa[] = L"goodbye"; | |
952 | path wp1(wsto); | |
953 | path wp2(wsto.c_str()); | |
954 | path wp3(wa); | |
955 | path wp4(L"foo"); | |
956 | } | |
957 | ||
958 | // test_error_handling -------------------------------------------------------------// | |
959 | ||
960 | class error_codecvt | |
961 | : public std::codecvt< wchar_t, char, std::mbstate_t > | |
962 | { | |
963 | public: | |
964 | explicit error_codecvt() | |
965 | : std::codecvt<wchar_t, char, std::mbstate_t>() {} | |
966 | protected: | |
967 | ||
968 | virtual bool do_always_noconv() const throw() { return false; } | |
969 | virtual int do_encoding() const throw() { return 0; } | |
970 | ||
971 | virtual std::codecvt_base::result do_in(std::mbstate_t&, | |
972 | const char*, const char*, const char*&, | |
973 | wchar_t*, wchar_t*, wchar_t*&) const | |
974 | { | |
975 | static std::codecvt_base::result r = std::codecvt_base::noconv; | |
976 | if (r == std::codecvt_base::partial) r = std::codecvt_base::error; | |
977 | else if (r == std::codecvt_base::error) r = std::codecvt_base::noconv; | |
978 | else r = std::codecvt_base::partial; | |
979 | return r; | |
980 | } | |
981 | ||
982 | virtual std::codecvt_base::result do_out(std::mbstate_t &, | |
983 | const wchar_t*, const wchar_t*, const wchar_t*&, | |
984 | char*, char*, char*&) const | |
985 | { | |
986 | static std::codecvt_base::result r = std::codecvt_base::noconv; | |
987 | if (r == std::codecvt_base::partial) r = std::codecvt_base::error; | |
988 | else if (r == std::codecvt_base::error) r = std::codecvt_base::noconv; | |
989 | else r = std::codecvt_base::partial; | |
990 | return r; | |
991 | } | |
992 | ||
993 | virtual std::codecvt_base::result do_unshift(std::mbstate_t&, | |
994 | char*, char*, char* &) const { return ok; } | |
995 | virtual int do_length(std::mbstate_t &, | |
996 | const char*, const char*, std::size_t) const { return 0; } | |
997 | virtual int do_max_length() const throw () { return 0; } | |
998 | }; | |
999 | ||
1000 | void test_error_handling() | |
1001 | { | |
1002 | std::cout << "testing error handling..." << std::endl; | |
1003 | ||
1004 | std::locale global_loc = std::locale(); | |
1005 | std::locale loc(global_loc, new error_codecvt); | |
1006 | std::cout << " imbuing error locale ..." << std::endl; | |
1007 | std::locale old_loc = path::imbue(loc); | |
1008 | ||
1009 | // These tests rely on a path constructor that fails in the locale conversion. | |
1010 | // Thus construction has to call codecvt. Force that by using a narrow string | |
1011 | // for Windows, and a wide string for POSIX. | |
1012 | # ifdef BOOST_WINDOWS_API | |
1013 | # define STRING_FOO_ "foo" | |
1014 | # else | |
1015 | # define STRING_FOO_ L"foo" | |
1016 | # endif | |
1017 | ||
1018 | { | |
1019 | std::cout << " testing std::codecvt_base::partial error..." << std::endl; | |
1020 | bool exception_thrown (false); | |
1021 | try { path(STRING_FOO_); } | |
1022 | catch (const bs::system_error & ex) | |
1023 | { | |
1024 | exception_thrown = true; | |
1025 | BOOST_TEST_EQ(ex.code(), bs::error_code(std::codecvt_base::partial, | |
1026 | fs::codecvt_error_category())); | |
1027 | } | |
1028 | catch (...) { std::cout << "***** unexpected exception type *****" << std::endl; } | |
1029 | BOOST_TEST(exception_thrown); | |
1030 | } | |
1031 | ||
1032 | { | |
1033 | std::cout << " testing std::codecvt_base::error error..." << std::endl; | |
1034 | bool exception_thrown (false); | |
1035 | try { path(STRING_FOO_); } | |
1036 | catch (const bs::system_error & ex) | |
1037 | { | |
1038 | exception_thrown = true; | |
1039 | BOOST_TEST_EQ(ex.code(), bs::error_code(std::codecvt_base::error, | |
1040 | fs::codecvt_error_category())); | |
1041 | } | |
1042 | catch (...) { std::cout << "***** unexpected exception type *****" << std::endl; } | |
1043 | BOOST_TEST(exception_thrown); | |
1044 | } | |
1045 | ||
1046 | { | |
1047 | std::cout << " testing std::codecvt_base::noconv error..." << std::endl; | |
1048 | bool exception_thrown (false); | |
1049 | try { path(STRING_FOO_); } | |
1050 | catch (const bs::system_error & ex) | |
1051 | { | |
1052 | exception_thrown = true; | |
1053 | BOOST_TEST_EQ(ex.code(), bs::error_code(std::codecvt_base::noconv, | |
1054 | fs::codecvt_error_category())); | |
1055 | } | |
1056 | catch (...) { std::cout << "***** unexpected exception type *****" << std::endl; } | |
1057 | BOOST_TEST(exception_thrown); | |
1058 | } | |
1059 | ||
1060 | std::cout << " restoring original locale ..." << std::endl; | |
1061 | path::imbue(old_loc); | |
1062 | std::cout << " testing error handling complete" << std::endl; | |
1063 | } | |
1064 | ||
1065 | # if 0 | |
1066 | ||
1067 | // // test_locales --------------------------------------------------------------------// | |
1068 | // | |
1069 | // void test_locales() | |
1070 | // { | |
1071 | // std::cout << "testing locales..." << std::endl; | |
1072 | // | |
1073 | // } | |
1074 | ||
1075 | // test_user_supplied_type ---------------------------------------------------------// | |
1076 | ||
1077 | typedef std::basic_string<int> user_string; | |
1078 | ||
1079 | } // unnamed namespace | |
1080 | ||
1081 | namespace boost | |
1082 | { | |
1083 | namespace filesystem | |
1084 | { | |
1085 | namespace path_traits | |
1086 | { | |
1087 | template<> struct is_iterator<const user_string::value_type *> { static const bool value = true; }; | |
1088 | template<> struct is_iterator<user_string::value_type *> { static const bool value = true; }; | |
1089 | template<> struct is_iterator<user_string::iterator> { static const bool value = true; }; | |
1090 | template<> struct is_iterator<user_string::const_iterator> { static const bool value = true; }; | |
1091 | template<> struct is_container<user_string> { static const bool value = true; }; | |
1092 | ||
1093 | template<> | |
1094 | void append<user_string::value_type>(const user_string::value_type * begin, | |
1095 | const user_string::value_type * end, string_type & target, system::error_code & ec) | |
1096 | { | |
1097 | for (; begin != end && *begin; ++begin) | |
1098 | target += *begin + 1; // change so that results distinguishable from char cvts | |
1099 | } | |
1100 | ||
1101 | # ifdef __GNUC__ | |
1102 | // This specialization shouldn't be needed, and VC++, Intel, and others work | |
1103 | // fine without it. But gcc 4.3.2, and presumably other versions, need it. | |
1104 | template<> | |
1105 | void append<user_string::value_type>(const user_string::value_type * begin, | |
1106 | string_type & target, system::error_code & ec) | |
1107 | { | |
1108 | path_traits::append<user_string::value_type>(begin, | |
1109 | static_cast<const user_string::value_type *>(0), target, ec); | |
1110 | } | |
1111 | # endif | |
1112 | ||
1113 | template<> | |
1114 | user_string convert<user_string>(const string_type & source, | |
1115 | system::error_code & ec) | |
1116 | { | |
1117 | user_string temp; | |
1118 | for (string_type::const_iterator it = source.begin(); | |
1119 | it != source.end(); ++it) | |
1120 | temp += *it - 1; | |
1121 | return temp; | |
1122 | } | |
1123 | } // namespace path_traits | |
1124 | } // namespace filesystem | |
1125 | } // namespace boost | |
1126 | ||
1127 | namespace | |
1128 | { | |
1129 | ||
1130 | void test_user_supplied_type() | |
1131 | { | |
1132 | std::cout << "testing user supplied type..." << std::endl; | |
1133 | ||
1134 | user_string::value_type usr_c_str[] = { 'a', 'b', 'c', 0 }; | |
1135 | user_string usr(usr_c_str); | |
1136 | ||
1137 | path p1(usr.c_str()); | |
1138 | CHECK(p1 == path("bcd")); | |
1139 | CHECK(p1 == "bcd"); | |
1140 | user_string s1(p1.string<user_string>()); | |
1141 | CHECK(s1 == usr); | |
1142 | } | |
1143 | ||
1144 | # endif | |
1145 | ||
b32b8144 FG |
1146 | inline const char* macro_value(const char* name, const char* value) |
1147 | { | |
1148 | static const char* no_value = "[no value]"; | |
1149 | static const char* not_defined = "[not defined]"; | |
1150 | ||
1151 | //if (0 != strcmp(name, value + 1)) // macro is defined | |
1152 | //{ | |
1153 | // if (value[1]) | |
1154 | // return value; | |
1155 | // else | |
1156 | // return no_value; | |
1157 | //} | |
1158 | //return not_defined; | |
1159 | ||
1160 | return 0 == strcmp(name, value + 1) | |
92f5a8d4 | 1161 | ? not_defined |
b32b8144 FG |
1162 | : (value[1] ? value : no_value); |
1163 | } | |
1164 | ||
1165 | #define BOOST_MACRO_VALUE(X) macro_value(#X, BOOST_STRINGIZE(=X)) | |
1166 | ||
7c673cae FG |
1167 | } // unnamed namespace |
1168 | ||
1169 | //--------------------------------------------------------------------------------------// | |
1170 | // // | |
1171 | // main // | |
1172 | // // | |
1173 | //--------------------------------------------------------------------------------------// | |
1174 | ||
1175 | int test_main(int, char*[]) | |
1176 | { | |
1177 | // document state of critical macros | |
1178 | #ifdef BOOST_POSIX_API | |
1179 | cout << "BOOST_POSIX_API" << endl; | |
1180 | BOOST_TEST(path::preferred_separator == '/'); | |
1181 | #endif | |
1182 | #ifdef BOOST_WINDOWS_API | |
1183 | cout << "BOOST_WINDOWS_API" << endl; | |
1184 | BOOST_TEST(path::preferred_separator == '\\'); | |
1185 | #endif | |
1186 | ||
b32b8144 FG |
1187 | cout << "BOOST_FILESYSTEM_DECL " |
1188 | << BOOST_MACRO_VALUE(BOOST_FILESYSTEM_DECL) << endl; | |
1189 | ||
1190 | //#ifdef BOOST_FILESYSTEM_DECL | |
1191 | // cout << "BOOST_FILESYSTEM_DECL is defined as " | |
1192 | // << BOOST_STRINGIZE(BOOST_FILESYSTEM_DECL) << endl; | |
1193 | //#else | |
1194 | // cout << "BOOST_FILESYSTEM_DECL is not defined" << endl; | |
1195 | //#endif | |
1196 | ||
7c673cae FG |
1197 | l.push_back('s'); |
1198 | l.push_back('t'); | |
1199 | l.push_back('r'); | |
1200 | l.push_back('i'); | |
1201 | l.push_back('n'); | |
1202 | l.push_back('g'); | |
1203 | ||
1204 | wl.push_back(L'w'); | |
1205 | wl.push_back(L's'); | |
1206 | wl.push_back(L't'); | |
1207 | wl.push_back(L'r'); | |
1208 | wl.push_back(L'i'); | |
1209 | wl.push_back(L'n'); | |
1210 | wl.push_back(L'g'); | |
1211 | ||
1212 | v.push_back('f'); | |
1213 | v.push_back('u'); | |
1214 | v.push_back('z'); | |
1215 | ||
1216 | wv.push_back(L'w'); | |
1217 | wv.push_back(L'f'); | |
1218 | wv.push_back(L'u'); | |
1219 | wv.push_back(L'z'); | |
1220 | ||
1221 | test_overloads(); | |
1222 | test_constructors(); | |
1223 | test_assignments(); | |
1224 | test_move_construction_and_assignment(); | |
1225 | test_appends(); | |
1226 | test_concats(); | |
1227 | test_modifiers(); | |
1228 | test_observers(); | |
1229 | test_relationals(); | |
1230 | test_inserter_and_extractor(); | |
1231 | test_other_non_members(); | |
1232 | test_iterators(); | |
1233 | test_reverse_iterators(); | |
1234 | test_decompositions(); | |
1235 | test_queries(); | |
1236 | test_imbue_locale(); | |
1237 | test_codecvt_argument(); | |
1238 | test_error_handling(); | |
1239 | ||
1240 | #if 0 | |
1241 | ||
1242 | test_user_supplied_type(); | |
1243 | ||
1244 | #endif | |
1245 | ||
1246 | std::string foo("\\abc"); | |
1247 | const char* bar = "/abc"; | |
1248 | ||
1249 | if (foo == bar) | |
1250 | cout << "unintended consequence\n"; | |
1251 | ||
1252 | return ::boost::report_errors(); | |
1253 | } |