]>
git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/filesystem/test/path_unit_test.cpp
1 // filesystem path_unit_test.cpp --------------------------------------------------- //
3 // Copyright Beman Dawes 2008, 2009
5 // Distributed under the Boost Software License, Version 1.0.
6 // See http://www.boost.org/LICENSE_1_0.txt
8 // Library home page: http://www.boost.org/libs/filesystem
10 // ---------------------------------------------------------------------------------- //
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.
17 // For full functionality tests, including probes with many different argument
18 // values, see path_test.cpp and other test programs.
20 // ---------------------------------------------------------------------------------- //
22 #include <boost/config/warning_disable.hpp>
24 // See deprecated_test for tests of deprecated features
25 #ifndef BOOST_FILESYSTEM_NO_DEPRECATED
26 # define BOOST_FILESYSTEM_NO_DEPRECATED
28 #ifndef BOOST_SYSTEM_NO_DEPRECATED
29 # define BOOST_SYSTEM_NO_DEPRECATED
32 #include <boost/filesystem/path.hpp>
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>
49 namespace fs
= boost::filesystem
;
50 namespace bs
= boost::system
;
51 using boost::filesystem::path
;
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__)
63 # pragma warning(push) // Save warning settings.
64 # pragma warning(disable : 4428) // Disable universal-character-name encountered in source warning.
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());
74 std::string
platform(BOOST_PLATFORM
);
76 void check_path(const path
& source
,
77 const wstring
& expected
, const char* file
, int line
)
79 if (source
== expected
) return;
81 ++::boost::detail::test_errors();
84 std::wcout
<< L
'(' << line
<< L
"): source.wstring(): \""
86 << L
"\" != expected: \"" << expected
90 # ifdef BOOST_WINDOWS_API
91 void check_native(const path
& p
,
92 const string
&, const wstring
& expected
, const char* file
, int line
)
94 void check_native(const path
& p
,
95 const string
& expected
, const wstring
&, const char* file
, int line
)
98 if (p
.native() == expected
) return;
100 ++::boost::detail::test_errors();
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
;
113 template< class T1
, class T2
>
114 void check_equal(const T1
& value
,
115 const T2
& expected
, const char* file
, int line
)
117 if (value
== expected
) return;
119 ++::boost::detail::test_errors();
123 std::wcout
<< L
'(' << line
<< L
"): value: \"" << value
124 << L
"\" != expected: \"" << expected
128 void check(bool ok_
, const char* file
, int line
)
132 ++::boost::detail::test_errors();
134 std::cout
<< file
<< '(' << line
<< "): test failed\n";
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
145 class Derived
: public Base
{};
146 void fun(const boost::shared_ptr
< Base
>&) {}
148 // test_constructors ---------------------------------------------------------------//
150 void test_constructors()
152 std::cout
<< "testing constructors..." << std::endl
;
154 path x0
; // default constructor
156 BOOST_TEST_EQ(x0
.native().size(), 0U);
158 path
x1(l
.begin(), l
.end()); // iterator range char
159 PATH_IS(x1
, L
"string");
160 BOOST_TEST_EQ(x1
.native().size(), 6U);
162 path
x2(x1
); // copy constructor
163 PATH_IS(x2
, L
"string");
164 BOOST_TEST_EQ(x2
.native().size(), 6U);
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);
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);
175 path
x5(wstring(L
"std::wstring")); // std::wstring
176 PATH_IS(x5
, L
"std::wstring");
177 BOOST_TEST_EQ(x5
.native().size(), 12U);
179 path
x4v(v
); // std::vector<char>
180 PATH_IS(x4v
, L
"fuz");
181 BOOST_TEST_EQ(x4v
.native().size(), 3U);
183 path
x5v(wv
); // std::vector<wchar_t>
184 PATH_IS(x5v
, L
"wfuz");
185 BOOST_TEST_EQ(x5v
.native().size(), 4U);
187 path
x6("array char"); // array char
188 PATH_IS(x6
, L
"array char");
189 BOOST_TEST_EQ(x6
.native().size(), 10U);
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);
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);
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);
207 path
x8(s
.c_str()); // const char* null terminated
208 PATH_IS(x8
, L
"string");
209 BOOST_TEST_EQ(x8
.native().size(), 6U);
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);
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);
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);
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);
228 path
xll(wl
); // std::list<wchar_t>
229 PATH_IS(xll
, L
"wstring");
230 BOOST_TEST_EQ(xll
.native().size(), 7U);
232 // easy-to-make coding errors
233 // path e1(x0, path::codecvt()); // fails to compile, and that is OK
235 boost::shared_ptr
< Derived
> pDerived( new Derived() );
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
243 // test_assignments ----------------------------------------------------------------//
245 void test_assignments()
247 std::cout
<< "testing assignments..." << std::endl
;
249 x
= path("yet another path"); // another path
250 PATH_IS(x
, L
"yet another path");
251 BOOST_TEST_EQ(x
.native().size(), 16U);
253 x
= x
; // self-assignment
254 PATH_IS(x
, L
"yet another path");
255 BOOST_TEST_EQ(x
.native().size(), 16U);
257 x
.assign(l
.begin(), l
.end()); // iterator range char
258 PATH_IS(x
, L
"string");
260 x
.assign(wl
.begin(), wl
.end()); // iterator range wchar_t
261 PATH_IS(x
, L
"wstring");
263 x
= string("std::string"); // container char
264 PATH_IS(x
, L
"std::string");
266 x
= wstring(L
"std::wstring"); // container wchar_t
267 PATH_IS(x
, L
"std::wstring");
269 x
= "array char"; // array char
270 PATH_IS(x
, L
"array char");
272 x
= L
"array wchar"; // array wchar_t
273 PATH_IS(x
, L
"array wchar");
275 x
= s
.c_str(); // const char* null terminated
276 PATH_IS(x
, L
"string");
278 x
= ws
.c_str(); // const wchar_t* null terminated
279 PATH_IS(x
, L
"wstring");
282 // test_move_construction_and_assignment -------------------------------------------//
284 void test_move_construction_and_assignment()
286 std::cout
<< "testing move_construction_and_assignment..." << std::endl
;
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");
293 cout
<< "Note: move construction did not result in empty source path" << endl
;
295 path
from2("long enough to avoid small object optimization");
297 to2
= std::move(from2
);
298 BOOST_TEST(to2
== "long enough to avoid small object optimization");
300 cout
<< "Note: move assignment did not result in empty rhs path" << endl
;
303 "Test skipped because compiler does not support move semantics" << std::endl
;
308 // test_appends --------------------------------------------------------------------//
312 std::cout
<< "testing appends..." << std::endl
;
314 # ifdef BOOST_WINDOWS_API
315 # define BOOST_FS_FOO L"/foo\\"
316 # else // POSIX paths
317 # define BOOST_FS_FOO L"/foo/"
321 x
/= path(""); // empty path
325 x
/= path("/"); // slash path
326 PATH_IS(x
, L
"/foo/");
329 x
/= path("/boo"); // slash path
330 PATH_IS(x
, L
"/foo/boo");
333 x
/= x
; // self-append
334 PATH_IS(x
, L
"/foo/foo");
337 x
/= path("yet another path"); // another path
338 PATH_IS(x
, BOOST_FS_FOO L
"yet another path");
341 x
.append(l
.begin(), l
.end()); // iterator range char
342 PATH_IS(x
, BOOST_FS_FOO L
"string");
345 x
.append(wl
.begin(), wl
.end()); // iterator range wchar_t
346 PATH_IS(x
, BOOST_FS_FOO L
"wstring");
349 x
/= string("std::string"); // container char
350 PATH_IS(x
, BOOST_FS_FOO L
"std::string");
353 x
/= wstring(L
"std::wstring"); // container wchar_t
354 PATH_IS(x
, BOOST_FS_FOO L
"std::wstring");
357 x
/= "array char"; // array char
358 PATH_IS(x
, BOOST_FS_FOO L
"array char");
361 x
/= L
"array wchar"; // array wchar_t
362 PATH_IS(x
, BOOST_FS_FOO L
"array wchar");
365 x
/= s
.c_str(); // const char* null terminated
366 PATH_IS(x
, BOOST_FS_FOO L
"string");
369 x
/= ws
.c_str(); // const wchar_t* null terminated
370 PATH_IS(x
, BOOST_FS_FOO L
"wstring");
373 // test_concats --------------------------------------------------------------------//
377 std::cout
<< "testing concats..." << std::endl
;
380 x
+= path(""); // empty path
384 x
+= path("/"); // slash path
385 PATH_IS(x
, L
"/foo/");
388 x
+= path("boo"); // slash path
389 PATH_IS(x
, L
"/fooboo");
392 x
+= x
; // self-append
393 PATH_IS(x
, L
"foofoo");
396 x
+= path("yet another path"); // another path
397 PATH_IS(x
, L
"foo-yet another path");
400 x
.concat(l
.begin(), l
.end()); // iterator range char
401 PATH_IS(x
, L
"foo-string");
404 x
.concat(wl
.begin(), wl
.end()); // iterator range wchar_t
405 PATH_IS(x
, L
"foo-wstring");
408 x
+= string("std::string"); // container char
409 PATH_IS(x
, L
"foo-std::string");
412 x
+= wstring(L
"std::wstring"); // container wchar_t
413 PATH_IS(x
, L
"foo-std::wstring");
416 x
+= "array char"; // array char
417 PATH_IS(x
, L
"foo-array char");
420 x
+= L
"array wchar"; // array wchar_t
421 PATH_IS(x
, L
"foo-array wchar");
424 x
+= s
.c_str(); // const char* null terminated
425 PATH_IS(x
, L
"foo-string");
428 x
+= ws
.c_str(); // const wchar_t* null terminated
429 PATH_IS(x
, L
"foo-wstring");
433 PATH_IS(x
, L
"foo-x");
437 PATH_IS(x
, L
"foo-x");
440 // test_observers ------------------------------------------------------------------//
442 void test_observers()
444 std::cout
<< "testing observers..." << std::endl
;
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);
456 CHECK(p0
.native().size() == 0);
457 CHECK(p0
.size() == 0);
459 # ifdef BOOST_WINDOWS_API
461 path
p("abc\\def/ghi");
463 CHECK(std::wstring(p
.c_str()) == L
"abc\\def/ghi");
465 CHECK(p
.string() == "abc\\def/ghi");
466 CHECK(p
.wstring() == L
"abc\\def/ghi");
468 CHECK(p
.generic().string() == "abc/def/ghi");
469 CHECK(p
.generic_string() == "abc/def/ghi");
470 CHECK(p
.generic_wstring() == L
"abc/def/ghi");
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");
476 # else // BOOST_POSIX_API
478 path
p("abc\\def/ghi");
480 CHECK(string(p
.c_str()) == "abc\\def/ghi");
482 CHECK(p
.string() == "abc\\def/ghi");
483 CHECK(p
.wstring() == L
"abc\\def/ghi");
485 CHECK(p
.generic().string() == "abc\\def/ghi");
486 CHECK(p
.generic_string() == "abc\\def/ghi");
487 CHECK(p
.generic_wstring() == L
"abc\\def/ghi");
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");
496 // test_relationals ----------------------------------------------------------------//
498 void test_relationals()
500 std::cout
<< "testing relationals..." << std::endl
;
502 boost::hash
<path
> hash
;
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")));
511 const path
p2("baz");
517 CHECK(p
< string("baz"));
519 CHECK(p
< wstring(L
"baz"));
521 CHECK(!(string("baz") < p
));
522 CHECK(!(L
"baz" < p
));
523 CHECK(!(wstring(L
"baz") < p
));
529 CHECK(p2
== string("baz"));
531 CHECK(p2
== wstring(L
"baz"));
533 CHECK(string("baz") == p2
);
535 CHECK(wstring(L
"baz") == p2
);
537 CHECK(hash(p
) == hash(p
));
538 CHECK(hash(p
) != hash(p2
)); // Not strictly required, but desirable
557 // test_inserter_and_extractor -----------------------------------------------------//
559 void test_inserter_and_extractor()
561 std::cout
<< "testing inserter and extractor..." << std::endl
;
563 path
p1("foo bar"); // verify space in path roundtrips per ticket #3863
566 std::stringstream ss
;
573 path
wp1(L
"foo bar");
576 std::wstringstream wss
;
584 // test_other_non_members ----------------------------------------------------------//
586 void test_other_non_members()
588 std::cout
<< "testing other_non_members..." << std::endl
;
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());
611 // // test_modifiers ------------------------------------------------------------------//
613 // void test_modifiers()
615 // std::cout << "testing modifiers..." << std::endl;
619 // test_iterators ------------------------------------------------------------------//
621 void test_iterators()
623 std::cout
<< "testing iterators..." << std::endl
;
626 CHECK(p1
.begin() == p1
.end());
629 CHECK(p2
.begin() != p2
.end());
630 CHECK(*p2
.begin() == "/");
631 CHECK(++p2
.begin() == p2
.end());
633 path
p3("foo/bar/baz");
635 path::iterator
it(p3
.begin());
636 CHECK(p3
.begin() != p3
.end());
638 CHECK(*++it
== "bar");
639 CHECK(*++it
== "baz");
640 CHECK(*--it
== "bar");
641 CHECK(*--it
== "foo");
642 CHECK(*++it
== "bar");
643 CHECK(*++it
== "baz");
644 CHECK(++it
== p3
.end());
647 // test_reverse_iterators ----------------------------------------------------------//
649 void test_reverse_iterators()
651 std::cout
<< "testing reverse_iterators..." << std::endl
;
654 CHECK(p1
.rbegin() == p1
.rend());
657 CHECK(p2
.rbegin() != p2
.rend());
658 CHECK(*p2
.rbegin() == "/");
659 CHECK(++p2
.rbegin() == p2
.rend());
661 path
p3("foo/bar/baz");
663 path::reverse_iterator
it(p3
.rbegin());
664 CHECK(p3
.rbegin() != p3
.rend());
666 CHECK(*++it
== "bar");
667 CHECK(*++it
== "foo");
668 CHECK(*--it
== "bar");
669 CHECK(*--it
== "baz");
670 CHECK(*++it
== "bar");
671 CHECK(*++it
== "foo");
672 CHECK(++it
== p3
.rend());
675 // test_modifiers ------------------------------------------------------------------//
677 void test_modifiers()
679 std::cout
<< "testing modifiers..." << std::endl
;
681 CHECK(path("").remove_filename() == "");
682 CHECK(path("foo").remove_filename() == "");
683 CHECK(path("/foo").remove_filename() == "/");
684 CHECK(path("foo/bar").remove_filename() == "foo");
685 BOOST_TEST_EQ(path("foo/bar/").remove_filename(), path("foo/bar"));
686 BOOST_TEST_EQ(path(".").remove_filename(), path(""));
687 BOOST_TEST_EQ(path("./.").remove_filename(), path("."));
688 BOOST_TEST_EQ(path("/.").remove_filename(), path("/"));
689 BOOST_TEST_EQ(path("..").remove_filename(), path(""));
690 BOOST_TEST_EQ(path("../..").remove_filename(), path(".."));
691 BOOST_TEST_EQ(path("/..").remove_filename(), path("/"));
695 // test_decompositions -------------------------------------------------------------//
697 void test_decompositions()
699 std::cout
<< "testing decompositions..." << std::endl
;
701 CHECK(path("").root_name().string() == "");
702 CHECK(path("foo").root_name().string() == "");
703 CHECK(path("/").root_name().string() == "");
704 CHECK(path("/foo").root_name().string() == "");
705 CHECK(path("//netname").root_name().string() == "//netname");
706 CHECK(path("//netname/foo").root_name().string() == "//netname");
708 CHECK(path("").root_directory().string() == "");
709 CHECK(path("foo").root_directory().string() == "");
710 CHECK(path("/").root_directory().string() == "/");
711 CHECK(path("/foo").root_directory().string() == "/");
712 CHECK(path("//netname").root_directory().string() == "");
713 CHECK(path("//netname/foo").root_directory().string() == "/");
715 CHECK(path("").root_path().string() == "");
716 CHECK(path("/").root_path().string() == "/");
717 CHECK(path("/foo").root_path().string() == "/");
718 CHECK(path("//netname").root_path().string() == "//netname");
719 CHECK(path("//netname/foo").root_path().string() == "//netname/");
721 # ifdef BOOST_WINDOWS_API
722 CHECK(path("c:/foo").root_path().string() == "c:/");
725 CHECK(path("").relative_path().string() == "");
726 CHECK(path("/").relative_path().string() == "");
727 CHECK(path("/foo").relative_path().string() == "foo");
729 CHECK(path("").parent_path().string() == "");
730 CHECK(path("/").parent_path().string() == "");
731 CHECK(path("/foo").parent_path().string() == "/");
732 CHECK(path("/foo/bar").parent_path().string() == "/foo");
734 CHECK(path("/foo/bar/baz.zoo").filename().string() == "baz.zoo");
736 CHECK(path("/foo/bar/baz.zoo").stem().string() == "baz");
737 CHECK(path("/foo/bar.woo/baz").stem().string() == "baz");
739 CHECK(path("foo.bar.baz.tar.bz2").extension().string() == ".bz2");
740 CHECK(path("/foo/bar/baz.zoo").extension().string() == ".zoo");
741 CHECK(path("/foo/bar.woo/baz").extension().string() == "");
744 // test_queries --------------------------------------------------------------------//
748 std::cout
<< "testing queries..." << std::endl
;
751 path
p2("//netname/foo.doo");
754 CHECK(!p1
.has_root_path());
755 CHECK(!p1
.has_root_name());
756 CHECK(!p1
.has_root_directory());
757 CHECK(!p1
.has_relative_path());
758 CHECK(!p1
.has_parent_path());
759 CHECK(!p1
.has_filename());
760 CHECK(!p1
.has_stem());
761 CHECK(!p1
.has_extension());
762 CHECK(!p1
.is_absolute());
763 CHECK(p1
.is_relative());
766 CHECK(p2
.has_root_path());
767 CHECK(p2
.has_root_name());
768 CHECK(p2
.has_root_directory());
769 CHECK(p2
.has_relative_path());
770 CHECK(p2
.has_parent_path());
771 CHECK(p2
.has_filename());
772 CHECK(p2
.has_stem());
773 CHECK(p2
.has_extension());
774 CHECK(p2
.is_absolute());
775 CHECK(!p2
.is_relative());
779 // test_imbue_locale ---------------------------------------------------------------//
781 void test_imbue_locale()
783 std::cout
<< "testing imbue locale..." << std::endl
;
785 // weak test case for before/after states since we don't know what characters the
786 // default locale accepts.
789 // So that tests are run with known encoding, use Boost UTF-8 codecvt
790 // \u2722 and \xE2\x9C\xA2 are UTF-16 and UTF-8 FOUR TEARDROP-SPOKED ASTERISK
792 std::locale global_loc
= std::locale();
793 std::locale
loc(global_loc
, new fs::detail::utf8_codecvt_facet
);
794 std::cout
<< " imbuing locale ..." << std::endl
;
795 std::locale old_loc
= path::imbue(loc
);
797 std::cout
<< " testing with the imbued locale ..." << std::endl
;
798 path
p2("\xE2\x9C\xA2");
799 CHECK(p2
.wstring().size() == 1);
800 CHECK(p2
.wstring()[0] == 0x2722);
802 std::cout
<< " imbuing the original locale ..." << std::endl
;
803 path::imbue(old_loc
);
805 std::cout
<< " testing with the original locale ..." << std::endl
;
807 CHECK(before
== after
);
809 std::cout
<< " locale testing complete" << std::endl
;
812 // test_codecvt_argument -----------------------------------------------------------//
814 void test_codecvt_argument()
816 std::cout
<< "testing codecvt arguments..." << std::endl
;
818 const char * c1
= "a1";
819 const std::string
s1(c1
);
820 const std::wstring
ws1(L
"b2"); // off-by-one mimics test_codecvt
821 const std::string
s2("y8");
822 const std::wstring
ws2(L
"z9");
824 test_codecvt cvt
; // produces off-by-one values that will always differ from
825 // the system's default locale codecvt facet
830 std::cout
<< " constructors test " << ++t
<< std::endl
;
832 NATIVE_IS(p
, s1
, ws1
);
834 std::cout
<< " test " << ++t
<< std::endl
;
835 path
p1(s1
.begin(), s1
.end(), cvt
);
836 NATIVE_IS(p1
, s1
, ws1
);
838 std::cout
<< " test " << ++t
<< std::endl
;
840 NATIVE_IS(p2
, s2
, ws2
);
842 std::cout
<< " test " << ++t
<< std::endl
;
843 path
p3(ws2
.begin(), ws2
.end(), cvt
);
844 NATIVE_IS(p3
, s2
, ws2
);
846 // path p2(p1, cvt); // fails to compile, and that is OK
850 std::cout
<< " assigns test " << ++t
<< std::endl
;
852 NATIVE_IS(p1
, s1
, ws1
);
854 std::cout
<< " test " << ++t
<< std::endl
;
855 p1
.assign(s1
.begin(), s1
.end(), cvt
);
856 NATIVE_IS(p1
, s1
, ws1
);
857 // p1.assign(p, cvt); // fails to compile, and that is OK
861 std::cout
<< " appends test " << ++t
<< std::endl
;
863 NATIVE_IS(p1
, s1
, ws1
);
865 std::cout
<< " test " << ++t
<< std::endl
;
866 p1
.append(s1
.begin(), s1
.end(), cvt
);
867 NATIVE_IS(p1
, s1
, ws1
);
868 // p1.append(p, cvt); // fails to compile, and that is OK
871 std::cout
<< " native observers test " << ++t
<< std::endl
;
872 CHECK(p
.string
<std::string
>(cvt
) == s1
);
873 std::cout
<< " test " << ++t
<< std::endl
;
874 CHECK(p
.string(cvt
) == s1
);
875 std::cout
<< " test " << ++t
<< std::endl
;
876 CHECK(p
.string
<std::wstring
>(cvt
) == ws1
);
877 std::cout
<< " test " << ++t
<< std::endl
;
878 CHECK(p
.wstring(cvt
) == ws1
);
881 std::cout
<< " generic observers test " << ++t
<< std::endl
;
882 CHECK(p
.generic_string
<std::string
>(cvt
) == s1
);
883 std::cout
<< " test " << ++t
<< std::endl
;
884 CHECK(p
.generic_string(cvt
) == s1
);
885 std::cout
<< " test " << ++t
<< std::endl
;
886 CHECK(p
.generic_string
<std::wstring
>(cvt
) == ws1
);
887 std::cout
<< " test " << ++t
<< std::endl
;
888 CHECK(p
.generic_wstring(cvt
) == ws1
);
890 std::cout
<< " codecvt arguments testing complete" << std::endl
;
893 // test_overloads ------------------------------------------------------------------//
895 void test_overloads()
897 std::cout
<< "testing overloads..." << std::endl
;
898 std::string
sto("hello");
899 const char a
[] = "goodbye";
901 path
p2(sto
.c_str());
905 std::wstring
wsto(L
"hello");
906 const wchar_t wa
[] = L
"goodbye";
908 path
wp2(wsto
.c_str());
913 // test_error_handling -------------------------------------------------------------//
916 : public std::codecvt
< wchar_t, char, std::mbstate_t >
919 explicit error_codecvt()
920 : std::codecvt
<wchar_t, char, std::mbstate_t>() {}
923 virtual bool do_always_noconv() const throw() { return false; }
924 virtual int do_encoding() const throw() { return 0; }
926 virtual std::codecvt_base::result
do_in(std::mbstate_t&,
927 const char*, const char*, const char*&,
928 wchar_t*, wchar_t*, wchar_t*&) const
930 static std::codecvt_base::result r
= std::codecvt_base::noconv
;
931 if (r
== std::codecvt_base::partial
) r
= std::codecvt_base::error
;
932 else if (r
== std::codecvt_base::error
) r
= std::codecvt_base::noconv
;
933 else r
= std::codecvt_base::partial
;
937 virtual std::codecvt_base::result
do_out(std::mbstate_t &,
938 const wchar_t*, const wchar_t*, const wchar_t*&,
939 char*, char*, char*&) const
941 static std::codecvt_base::result r
= std::codecvt_base::noconv
;
942 if (r
== std::codecvt_base::partial
) r
= std::codecvt_base::error
;
943 else if (r
== std::codecvt_base::error
) r
= std::codecvt_base::noconv
;
944 else r
= std::codecvt_base::partial
;
948 virtual std::codecvt_base::result
do_unshift(std::mbstate_t&,
949 char*, char*, char* &) const { return ok
; }
950 virtual int do_length(std::mbstate_t &,
951 const char*, const char*, std::size_t) const { return 0; }
952 virtual int do_max_length() const throw () { return 0; }
955 void test_error_handling()
957 std::cout
<< "testing error handling..." << std::endl
;
959 std::locale global_loc
= std::locale();
960 std::locale
loc(global_loc
, new error_codecvt
);
961 std::cout
<< " imbuing error locale ..." << std::endl
;
962 std::locale old_loc
= path::imbue(loc
);
964 // These tests rely on a path constructor that fails in the locale conversion.
965 // Thus construction has to call codecvt. Force that by using a narrow string
966 // for Windows, and a wide string for POSIX.
967 # ifdef BOOST_WINDOWS_API
968 # define STRING_FOO_ "foo"
970 # define STRING_FOO_ L"foo"
974 std::cout
<< " testing std::codecvt_base::partial error..." << std::endl
;
975 bool exception_thrown (false);
976 try { path(STRING_FOO_
); }
977 catch (const bs::system_error
& ex
)
979 exception_thrown
= true;
980 BOOST_TEST_EQ(ex
.code(), bs::error_code(std::codecvt_base::partial
,
981 fs::codecvt_error_category()));
983 catch (...) { std::cout
<< "***** unexpected exception type *****" << std::endl
; }
984 BOOST_TEST(exception_thrown
);
988 std::cout
<< " testing std::codecvt_base::error error..." << std::endl
;
989 bool exception_thrown (false);
990 try { path(STRING_FOO_
); }
991 catch (const bs::system_error
& ex
)
993 exception_thrown
= true;
994 BOOST_TEST_EQ(ex
.code(), bs::error_code(std::codecvt_base::error
,
995 fs::codecvt_error_category()));
997 catch (...) { std::cout
<< "***** unexpected exception type *****" << std::endl
; }
998 BOOST_TEST(exception_thrown
);
1002 std::cout
<< " testing std::codecvt_base::noconv error..." << std::endl
;
1003 bool exception_thrown (false);
1004 try { path(STRING_FOO_
); }
1005 catch (const bs::system_error
& ex
)
1007 exception_thrown
= true;
1008 BOOST_TEST_EQ(ex
.code(), bs::error_code(std::codecvt_base::noconv
,
1009 fs::codecvt_error_category()));
1011 catch (...) { std::cout
<< "***** unexpected exception type *****" << std::endl
; }
1012 BOOST_TEST(exception_thrown
);
1015 std::cout
<< " restoring original locale ..." << std::endl
;
1016 path::imbue(old_loc
);
1017 std::cout
<< " testing error handling complete" << std::endl
;
1022 // // test_locales --------------------------------------------------------------------//
1024 // void test_locales()
1026 // std::cout << "testing locales..." << std::endl;
1030 // test_user_supplied_type ---------------------------------------------------------//
1032 typedef std::basic_string
<int> user_string
;
1034 } // unnamed namespace
1038 namespace filesystem
1040 namespace path_traits
1042 template<> struct is_iterator
<const user_string::value_type
*> { static const bool value
= true; };
1043 template<> struct is_iterator
<user_string::value_type
*> { static const bool value
= true; };
1044 template<> struct is_iterator
<user_string::iterator
> { static const bool value
= true; };
1045 template<> struct is_iterator
<user_string::const_iterator
> { static const bool value
= true; };
1046 template<> struct is_container
<user_string
> { static const bool value
= true; };
1049 void append
<user_string::value_type
>(const user_string::value_type
* begin
,
1050 const user_string::value_type
* end
, string_type
& target
, system::error_code
& ec
)
1052 for (; begin
!= end
&& *begin
; ++begin
)
1053 target
+= *begin
+ 1; // change so that results distinguishable from char cvts
1057 // This specialization shouldn't be needed, and VC++, Intel, and others work
1058 // fine without it. But gcc 4.3.2, and presumably other versions, need it.
1060 void append
<user_string::value_type
>(const user_string::value_type
* begin
,
1061 string_type
& target
, system::error_code
& ec
)
1063 path_traits::append
<user_string::value_type
>(begin
,
1064 static_cast<const user_string::value_type
*>(0), target
, ec
);
1069 user_string convert
<user_string
>(const string_type
& source
,
1070 system::error_code
& ec
)
1073 for (string_type::const_iterator it
= source
.begin();
1074 it
!= source
.end(); ++it
)
1078 } // namespace path_traits
1079 } // namespace filesystem
1080 } // namespace boost
1085 void test_user_supplied_type()
1087 std::cout
<< "testing user supplied type..." << std::endl
;
1089 user_string::value_type usr_c_str
[] = { 'a', 'b', 'c', 0 };
1090 user_string
usr(usr_c_str
);
1092 path
p1(usr
.c_str());
1093 CHECK(p1
== path("bcd"));
1095 user_string
s1(p1
.string
<user_string
>());
1101 } // unnamed namespace
1103 //--------------------------------------------------------------------------------------//
1107 //--------------------------------------------------------------------------------------//
1109 int test_main(int, char*[])
1111 // document state of critical macros
1112 #ifdef BOOST_POSIX_API
1113 cout
<< "BOOST_POSIX_API" << endl
;
1114 BOOST_TEST(path::preferred_separator
== '/');
1116 #ifdef BOOST_WINDOWS_API
1117 cout
<< "BOOST_WINDOWS_API" << endl
;
1118 BOOST_TEST(path::preferred_separator
== '\\');
1146 test_constructors();
1148 test_move_construction_and_assignment();
1154 test_inserter_and_extractor();
1155 test_other_non_members();
1157 test_reverse_iterators();
1158 test_decompositions();
1160 test_imbue_locale();
1161 test_codecvt_argument();
1162 test_error_handling();
1166 test_user_supplied_type();
1170 std::string
foo("\\abc");
1171 const char* bar
= "/abc";
1174 cout
<< "unintended consequence\n";
1176 return ::boost::report_errors();