summaryrefslogtreecommitdiffstats
path: root/src/boost/libs/filesystem/test/path_unit_test.cpp
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 18:45:59 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 18:45:59 +0000
commit19fcec84d8d7d21e796c7624e521b60d28ee21ed (patch)
tree42d26aa27d1e3f7c0b8bd3fd14e7d7082f5008dc /src/boost/libs/filesystem/test/path_unit_test.cpp
parentInitial commit. (diff)
downloadceph-upstream.tar.xz
ceph-upstream.zip
Adding upstream version 16.2.11+ds.upstream/16.2.11+dsupstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/boost/libs/filesystem/test/path_unit_test.cpp')
-rw-r--r--src/boost/libs/filesystem/test/path_unit_test.cpp1253
1 files changed, 1253 insertions, 0 deletions
diff --git a/src/boost/libs/filesystem/test/path_unit_test.cpp b/src/boost/libs/filesystem/test/path_unit_test.cpp
new file mode 100644
index 000000000..7ec707363
--- /dev/null
+++ b/src/boost/libs/filesystem/test/path_unit_test.cpp
@@ -0,0 +1,1253 @@
+// filesystem path_unit_test.cpp --------------------------------------------------- //
+
+// Copyright Beman Dawes 2008, 2009
+
+// Distributed under the Boost Software License, Version 1.0.
+// See http://www.boost.org/LICENSE_1_0.txt
+
+// Library home page: http://www.boost.org/libs/filesystem
+
+// ---------------------------------------------------------------------------------- //
+//
+// The purpose of this test is to ensure that each function in the public
+// interface can be called with arguments of the appropriate types. It does
+// not attempt to verify that the full range of values for each argument
+// are processed correctly.
+//
+// For full functionality tests, including probes with many different argument
+// values, see path_test.cpp and other test programs.
+//
+// ---------------------------------------------------------------------------------- //
+
+#include <boost/config/warning_disable.hpp>
+
+// See deprecated_test for tests of deprecated features
+#ifndef BOOST_FILESYSTEM_NO_DEPRECATED
+# define BOOST_FILESYSTEM_NO_DEPRECATED
+#endif
+#ifndef BOOST_SYSTEM_NO_DEPRECATED
+# define BOOST_SYSTEM_NO_DEPRECATED
+#endif
+
+#include <boost/filesystem/path.hpp>
+
+#include <boost/filesystem/detail/utf8_codecvt_facet.hpp> // for imbue tests
+#include "test_codecvt.hpp" // for codecvt arg tests
+#include <boost/detail/lightweight_test_report.hpp>
+#include <boost/smart_ptr.hpp> // used constructor tests
+#include <boost/functional/hash.hpp>
+
+#include <iostream>
+#include <iomanip>
+#include <sstream>
+#include <string>
+#include <cstring>
+#include <cwchar>
+#include <locale>
+#include <list>
+
+namespace fs = boost::filesystem;
+namespace bs = boost::system;
+using boost::filesystem::path;
+using std::cout;
+using std::endl;
+using std::string;
+using std::wstring;
+
+#define CHECK(x) check(x, __FILE__, __LINE__)
+#define PATH_IS(a, b) check_path(a, b, __FILE__, __LINE__)
+#define NATIVE_IS(p, s, ws) check_native(p, s, ws, __FILE__, __LINE__)
+#define IS(a,b) check_equal(a, b, __FILE__, __LINE__)
+
+#if defined(_MSC_VER)
+# pragma warning(push) // Save warning settings.
+# pragma warning(disable : 4428) // Disable universal-character-name encountered in source warning.
+#endif
+
+namespace
+{
+
+ boost::system::error_code ec;
+ const boost::system::error_code ok;
+ const boost::system::error_code ng(-1, boost::system::system_category());
+
+ std::string platform(BOOST_PLATFORM);
+
+ void check_path(const path& source,
+ const wstring& expected, const char* file, int line)
+ {
+ if (source == expected) return;
+
+ ++::boost::detail::test_errors();
+
+ std::cout << file;
+ std::wcout << L'(' << line << L"): source.wstring(): \""
+ << source.wstring()
+ << L"\" != expected: \"" << expected
+ << L"\"\n" ;
+ }
+
+# ifdef BOOST_WINDOWS_API
+ void check_native(const path& p,
+ const string&, const wstring& expected, const char* file, int line)
+# else
+ void check_native(const path& p,
+ const string& expected, const wstring&, const char* file, int line)
+# endif
+ {
+ if (p.native() == expected) return;
+
+ ++::boost::detail::test_errors();
+
+ std::cout << file << '(' << line << "): native() is not equal expected\n"
+ " native---: " << std::hex;
+ path::string_type nat(p.native());
+ for (path::string_type::const_iterator it = nat.begin(); it != nat.end(); ++it)
+ std::cout << long(*it) << ' ';
+ std::cout << "\n expected-: ";
+ for (path::string_type::const_iterator it = expected.begin(); it != expected.end(); ++it)
+ std::cout << long(*it) << ' ';
+ std::cout << std::dec << std::endl;
+ }
+
+ template< class T1, class T2 >
+ void check_equal(const T1& value,
+ const T2& expected, const char* file, int line)
+ {
+ if (value == expected) return;
+
+ ++::boost::detail::test_errors();
+
+ std::cout << file;
+
+ std::wcout << L'(' << line << L"): value: \"" << value
+ << L"\" != expected: \"" << expected
+ << L"\"\n" ;
+ }
+
+ void check(bool ok_, const char* file, int line)
+ {
+ if (ok_) return;
+
+ ++::boost::detail::test_errors();
+
+ std::cout << file << '(' << line << "): test failed\n";
+ }
+
+ string s("string");
+ wstring ws(L"wstring");
+ std::list<char> l; // see main() for initialization to s, t, r, i, n, g
+ std::list<wchar_t> wl; // see main() for initialization to w, s, t, r, i, n, g
+ std::vector<char> v; // see main() for initialization to f, u, z
+ std::vector<wchar_t> wv; // see main() for initialization to w, f, u, z
+
+ class Base {};
+ class Derived : public Base {};
+ void fun(const boost::shared_ptr< Base >&) {}
+
+ // test_constructors ---------------------------------------------------------------//
+
+ void test_constructors()
+ {
+ std::cout << "testing constructors..." << std::endl;
+
+ path x0; // default constructor
+ PATH_IS(x0, L"");
+ BOOST_TEST_EQ(x0.native().size(), 0U);
+
+ path x1(l.begin(), l.end()); // iterator range char
+ PATH_IS(x1, L"string");
+ BOOST_TEST_EQ(x1.native().size(), 6U);
+
+ path x2(x1); // copy constructor
+ PATH_IS(x2, L"string");
+ BOOST_TEST_EQ(x2.native().size(), 6U);
+
+ path x3(wl.begin(), wl.end()); // iterator range wchar_t
+ PATH_IS(x3, L"wstring");
+ BOOST_TEST_EQ(x3.native().size(), 7U);
+
+ // contiguous containers
+ path x4(string("std::string")); // std::string
+ PATH_IS(x4, L"std::string");
+ BOOST_TEST_EQ(x4.native().size(), 11U);
+
+ path x5(wstring(L"std::wstring")); // std::wstring
+ PATH_IS(x5, L"std::wstring");
+ BOOST_TEST_EQ(x5.native().size(), 12U);
+
+ path x4v(v); // std::vector<char>
+ PATH_IS(x4v, L"fuz");
+ BOOST_TEST_EQ(x4v.native().size(), 3U);
+
+ path x5v(wv); // std::vector<wchar_t>
+ PATH_IS(x5v, L"wfuz");
+ BOOST_TEST_EQ(x5v.native().size(), 4U);
+
+ path x6("array char"); // array char
+ PATH_IS(x6, L"array char");
+ BOOST_TEST_EQ(x6.native().size(), 10U);
+
+ path x7(L"array wchar_t"); // array wchar_t
+ PATH_IS(x7, L"array wchar_t");
+ BOOST_TEST_EQ(x7.native().size(), 13U);
+
+ char char_array[100];
+ std::strcpy(char_array, "big array char");
+ path x6o(char_array); // array char, only partially full
+ PATH_IS(x6o, L"big array char");
+ BOOST_TEST_EQ(x6o.native().size(), 14U);
+
+ wchar_t wchar_array[100];
+ std::wcscpy(wchar_array, L"big array wchar_t");
+ path x7o(wchar_array); // array char, only partially full
+ PATH_IS(x7o, L"big array wchar_t");
+ BOOST_TEST_EQ(x7o.native().size(), 17U);
+
+ path x8(s.c_str()); // const char* null terminated
+ PATH_IS(x8, L"string");
+ BOOST_TEST_EQ(x8.native().size(), 6U);
+
+ path x9(ws.c_str()); // const wchar_t* null terminated
+ PATH_IS(x9, L"wstring");
+ BOOST_TEST_EQ(x9.native().size(), 7U);
+
+ path x8nc(const_cast<char*>(s.c_str())); // char* null terminated
+ PATH_IS(x8nc, L"string");
+ BOOST_TEST_EQ(x8nc.native().size(), 6U);
+
+ path x9nc(const_cast<wchar_t*>(ws.c_str())); // wchar_t* null terminated
+ PATH_IS(x9nc, L"wstring");
+ BOOST_TEST_EQ(x9nc.native().size(), 7U);
+
+ // non-contiguous containers
+ path x10(l); // std::list<char>
+ PATH_IS(x10, L"string");
+ BOOST_TEST_EQ(x10.native().size(), 6U);
+
+ path xll(wl); // std::list<wchar_t>
+ PATH_IS(xll, L"wstring");
+ BOOST_TEST_EQ(xll.native().size(), 7U);
+
+ // easy-to-make coding errors
+ // path e1(x0, path::codecvt()); // fails to compile, and that is OK
+
+ boost::shared_ptr< Derived > pDerived( new Derived() );
+ fun( pDerived ); // tests constructor member template enable_if working correctly;
+ // will fail to compile if enable_if not taking path off the table
+ }
+
+ path x;
+ path y;
+
+ // test_assignments ----------------------------------------------------------------//
+
+ void test_assignments()
+ {
+ std::cout << "testing assignments..." << std::endl;
+
+ x = path("yet another path"); // another path
+ PATH_IS(x, L"yet another path");
+ BOOST_TEST_EQ(x.native().size(), 16U);
+
+ x = x; // self-assignment
+ PATH_IS(x, L"yet another path");
+ BOOST_TEST_EQ(x.native().size(), 16U);
+
+ x.assign(l.begin(), l.end()); // iterator range char
+ PATH_IS(x, L"string");
+
+ x.assign(wl.begin(), wl.end()); // iterator range wchar_t
+ PATH_IS(x, L"wstring");
+
+ x = string("std::string"); // container char
+ PATH_IS(x, L"std::string");
+
+ x = wstring(L"std::wstring"); // container wchar_t
+ PATH_IS(x, L"std::wstring");
+
+ x = "array char"; // array char
+ PATH_IS(x, L"array char");
+
+ x = L"array wchar"; // array wchar_t
+ PATH_IS(x, L"array wchar");
+
+ x = s.c_str(); // const char* null terminated
+ PATH_IS(x, L"string");
+
+ x = ws.c_str(); // const wchar_t* null terminated
+ PATH_IS(x, L"wstring");
+ }
+
+ // test_move_construction_and_assignment -------------------------------------------//
+
+ void test_move_construction_and_assignment()
+ {
+ std::cout << "testing move_construction_and_assignment..." << std::endl;
+
+# if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
+ path from("long enough to avoid small object optimization");
+ path to(std::move(from));
+ BOOST_TEST(to == "long enough to avoid small object optimization");
+ if (!from.empty())
+ cout << "Note: move construction did not result in empty source path" << endl;
+
+ path from2("long enough to avoid small object optimization");
+ path to2;
+ to2 = std::move(from2);
+ BOOST_TEST(to2 == "long enough to avoid small object optimization");
+ if (!from2.empty())
+ cout << "Note: move assignment did not result in empty rhs path" << endl;
+# else
+ std::cout <<
+ "Test skipped because compiler does not support move semantics" << std::endl;
+# endif
+
+ }
+
+ // test_appends --------------------------------------------------------------------//
+
+ void test_appends()
+ {
+ std::cout << "testing appends..." << std::endl;
+
+# ifdef BOOST_WINDOWS_API
+# define BOOST_FS_FOO L"/foo\\"
+# else // POSIX paths
+# define BOOST_FS_FOO L"/foo/"
+# endif
+
+ x = "/foo";
+ x /= path(""); // empty path
+ PATH_IS(x, L"/foo");
+
+ x = "/foo";
+ x /= path("/"); // slash path
+ PATH_IS(x, L"/foo/");
+
+ x = "/foo";
+ x /= path("/boo"); // slash path
+ PATH_IS(x, L"/foo/boo");
+
+ x = "/foo";
+ x /= x; // self-append
+ PATH_IS(x, L"/foo/foo");
+
+ x = "/foo";
+ x /= path("yet another path"); // another path
+ PATH_IS(x, BOOST_FS_FOO L"yet another path");
+
+ x = "/foo";
+ x.append(l.begin(), l.end()); // iterator range char
+ PATH_IS(x, BOOST_FS_FOO L"string");
+
+ x = "/foo";
+ x.append(wl.begin(), wl.end()); // iterator range wchar_t
+ PATH_IS(x, BOOST_FS_FOO L"wstring");
+
+ x = "/foo";
+ x /= string("std::string"); // container char
+ PATH_IS(x, BOOST_FS_FOO L"std::string");
+
+ x = "/foo";
+ x /= wstring(L"std::wstring"); // container wchar_t
+ PATH_IS(x, BOOST_FS_FOO L"std::wstring");
+
+ x = "/foo";
+ x /= "array char"; // array char
+ PATH_IS(x, BOOST_FS_FOO L"array char");
+
+ x = "/foo";
+ x /= L"array wchar"; // array wchar_t
+ PATH_IS(x, BOOST_FS_FOO L"array wchar");
+
+ x = "/foo";
+ x /= s.c_str(); // const char* null terminated
+ PATH_IS(x, BOOST_FS_FOO L"string");
+
+ x = "/foo";
+ x /= ws.c_str(); // const wchar_t* null terminated
+ PATH_IS(x, BOOST_FS_FOO L"wstring");
+ }
+
+ // test_concats --------------------------------------------------------------------//
+
+ void test_concats()
+ {
+ std::cout << "testing concats..." << std::endl;
+
+ x = "/foo";
+ x += path(""); // empty path
+ PATH_IS(x, L"/foo");
+
+ x = "/foo";
+ x += path("/"); // slash path
+ PATH_IS(x, L"/foo/");
+
+ x = "/foo";
+ x += path("boo"); // slash path
+ PATH_IS(x, L"/fooboo");
+
+ x = "foo";
+ x += x; // self-append
+ PATH_IS(x, L"foofoo");
+
+ x = "foo-";
+ x += path("yet another path"); // another path
+ PATH_IS(x, L"foo-yet another path");
+
+ x = "foo-";
+ x.concat(l.begin(), l.end()); // iterator range char
+ PATH_IS(x, L"foo-string");
+
+ x = "foo-";
+ x.concat(wl.begin(), wl.end()); // iterator range wchar_t
+ PATH_IS(x, L"foo-wstring");
+
+ x = "foo-";
+ x += string("std::string"); // container char
+ PATH_IS(x, L"foo-std::string");
+
+ x = "foo-";
+ x += wstring(L"std::wstring"); // container wchar_t
+ PATH_IS(x, L"foo-std::wstring");
+
+ x = "foo-";
+ x += "array char"; // array char
+ PATH_IS(x, L"foo-array char");
+
+ x = "foo-";
+ x += L"array wchar"; // array wchar_t
+ PATH_IS(x, L"foo-array wchar");
+
+ x = "foo-";
+ x += s.c_str(); // const char* null terminated
+ PATH_IS(x, L"foo-string");
+
+ x = "foo-";
+ x += ws.c_str(); // const wchar_t* null terminated
+ PATH_IS(x, L"foo-wstring");
+
+ x = "foo-";
+ x += 'x'; // char
+ PATH_IS(x, L"foo-x");
+
+ x = "foo-";
+ x += L'x'; // wchar
+ PATH_IS(x, L"foo-x");
+ }
+
+ // test_observers ------------------------------------------------------------------//
+
+ void test_observers()
+ {
+ std::cout << "testing observers..." << std::endl;
+
+ path p0("abc");
+
+ CHECK(p0.native().size() == 3);
+ CHECK(p0.size() == 3);
+ CHECK(p0.string() == "abc");
+ CHECK(p0.string().size() == 3);
+ CHECK(p0.wstring() == L"abc");
+ CHECK(p0.wstring().size() == 3);
+
+ p0 = "";
+ CHECK(p0.native().size() == 0);
+ CHECK(p0.size() == 0);
+
+# ifdef BOOST_WINDOWS_API
+
+ path p("abc\\def/ghi");
+
+ CHECK(std::wstring(p.c_str()) == L"abc\\def/ghi");
+
+ CHECK(p.string() == "abc\\def/ghi");
+ CHECK(p.wstring() == L"abc\\def/ghi");
+
+ CHECK(p.generic_path().string() == "abc/def/ghi");
+ CHECK(p.generic_string() == "abc/def/ghi");
+ CHECK(p.generic_wstring() == L"abc/def/ghi");
+
+ CHECK(p.generic_string<string>() == "abc/def/ghi");
+ CHECK(p.generic_string<wstring>() == L"abc/def/ghi");
+ CHECK(p.generic_string<path::string_type>() == L"abc/def/ghi");
+
+# else // BOOST_POSIX_API
+
+ path p("abc\\def/ghi");
+
+ CHECK(string(p.c_str()) == "abc\\def/ghi");
+
+ CHECK(p.string() == "abc\\def/ghi");
+ CHECK(p.wstring() == L"abc\\def/ghi");
+
+ CHECK(p.generic_path().string() == "abc\\def/ghi");
+ CHECK(p.generic_string() == "abc\\def/ghi");
+ CHECK(p.generic_wstring() == L"abc\\def/ghi");
+
+ CHECK(p.generic_string<string>() == "abc\\def/ghi");
+ CHECK(p.generic_string<wstring>() == L"abc\\def/ghi");
+ CHECK(p.generic_string<path::string_type>() == "abc\\def/ghi");
+
+# endif
+ }
+
+ // test_relationals ----------------------------------------------------------------//
+
+ void test_relationals()
+ {
+ std::cout << "testing relationals..." << std::endl;
+
+ boost::hash<path> hash;
+
+# ifdef BOOST_WINDOWS_API
+ // this is a critical use case to meet user expectations
+ CHECK(path("c:\\abc") == path("c:/abc"));
+ CHECK(hash(path("c:\\abc")) == hash(path("c:/abc")));
+# endif
+
+ const path p("bar");
+ const path p2("baz");
+
+ CHECK(!(p < p));
+ CHECK(p < p2);
+ CHECK(!(p2 < p));
+ CHECK(p < "baz");
+ CHECK(p < string("baz"));
+ CHECK(p < L"baz");
+ CHECK(p < wstring(L"baz"));
+ CHECK(!("baz" < p));
+ CHECK(!(string("baz") < p));
+ CHECK(!(L"baz" < p));
+ CHECK(!(wstring(L"baz") < p));
+
+ CHECK(p == p);
+ CHECK(!(p == p2));
+ CHECK(!(p2 == p));
+ CHECK(p2 == "baz");
+ CHECK(p2 == string("baz"));
+ CHECK(p2 == L"baz");
+ CHECK(p2 == wstring(L"baz"));
+ CHECK("baz" == p2);
+ CHECK(string("baz") == p2);
+ CHECK(L"baz" == p2);
+ CHECK(wstring(L"baz") == p2);
+
+ CHECK(hash(p) == hash(p));
+ CHECK(hash(p) != hash(p2)); // Not strictly required, but desirable
+
+ CHECK(!(p != p));
+ CHECK(p != p2);
+ CHECK(p2 != p);
+
+ CHECK(p <= p);
+ CHECK(p <= p2);
+ CHECK(!(p2 <= p));
+
+ CHECK(!(p > p));
+ CHECK(!(p > p2));
+ CHECK(p2 > p);
+
+ CHECK(p >= p);
+ CHECK(!(p >= p2));
+ CHECK(p2 >= p);
+}
+
+ // test_inserter_and_extractor -----------------------------------------------------//
+
+ void test_inserter_and_extractor()
+ {
+ std::cout << "testing inserter and extractor..." << std::endl;
+
+ path p1("foo bar"); // verify space in path roundtrips per ticket #3863
+ path p2;
+
+ std::stringstream ss;
+
+ CHECK(p1 != p2);
+ ss << p1;
+ ss >> p2;
+ CHECK(p1 == p2);
+
+ path wp1(L"foo bar");
+ path wp2;
+
+ std::wstringstream wss;
+
+ CHECK(wp1 != wp2);
+ wss << wp1;
+ wss >> wp2;
+ CHECK(wp1 == wp2);
+ }
+
+ // test_other_non_members ----------------------------------------------------------//
+
+ void test_other_non_members()
+ {
+ std::cout << "testing other_non_members..." << std::endl;
+
+ path p1("foo");
+ path p2("bar");
+
+ // operator /
+
+ CHECK(p1 / p2 == path("foo/bar").make_preferred());
+ CHECK("foo" / p2 == path("foo/bar").make_preferred());
+ CHECK(L"foo" / p2 == path("foo/bar").make_preferred());
+ CHECK(string("foo") / p2 == path("foo/bar").make_preferred());
+ CHECK(wstring(L"foo") / p2 == path("foo/bar").make_preferred());
+ CHECK(p1 / "bar" == path("foo/bar").make_preferred());
+ CHECK(p1 / L"bar" == path("foo/bar").make_preferred());
+ CHECK(p1 / string("bar") == path("foo/bar").make_preferred());
+ CHECK(p1 / wstring(L"bar") == path("foo/bar").make_preferred());
+
+ swap(p1, p2);
+
+ CHECK(p1 == "bar");
+ CHECK(p2 == "foo");
+
+ CHECK(!path("").filename_is_dot());
+ CHECK(!path("").filename_is_dot_dot());
+ CHECK(!path("..").filename_is_dot());
+ CHECK(!path(".").filename_is_dot_dot());
+ CHECK(!path("...").filename_is_dot_dot());
+ CHECK(path(".").filename_is_dot());
+ CHECK(path("..").filename_is_dot_dot());
+ CHECK(path("/.").filename_is_dot());
+ CHECK(path("/..").filename_is_dot_dot());
+ CHECK(!path("a.").filename_is_dot());
+ CHECK(!path("a..").filename_is_dot_dot());
+
+ // edge cases
+ CHECK(path("foo/").filename() == path("."));
+ CHECK(path("foo/").filename_is_dot());
+ CHECK(path("/").filename() == path("/"));
+ CHECK(!path("/").filename_is_dot());
+# ifdef BOOST_WINDOWS_API
+ CHECK(path("c:.").filename() == path("."));
+ CHECK(path("c:.").filename_is_dot());
+ CHECK(path("c:/").filename() == path("/"));
+ CHECK(!path("c:\\").filename_is_dot());
+# else
+ CHECK(path("c:.").filename() == path("c:."));
+ CHECK(!path("c:.").filename_is_dot());
+ CHECK(path("c:/").filename() == path("."));
+ CHECK(path("c:/").filename_is_dot());
+# endif
+
+ // check that the implementation code to make the edge cases above work right
+ // doesn't cause some non-edge cases to fail
+ CHECK(path("c:").filename() != path("."));
+ CHECK(!path("c:").filename_is_dot());
+
+ // examples from reference.html
+ std::cout << path(".").filename_is_dot(); // outputs 1
+ std::cout << path("/.").filename_is_dot(); // outputs 1
+ std::cout << path("foo/.").filename_is_dot(); // outputs 1
+ std::cout << path("foo/").filename_is_dot(); // outputs 1
+ std::cout << path("/").filename_is_dot(); // outputs 0
+ std::cout << path("/foo").filename_is_dot(); // outputs 0
+ std::cout << path("/foo.").filename_is_dot(); // outputs 0
+ std::cout << path("..").filename_is_dot(); // outputs 0
+ cout << std::endl;
+ }
+
+// // test_modifiers ------------------------------------------------------------------//
+//
+// void test_modifiers()
+// {
+// std::cout << "testing modifiers..." << std::endl;
+//
+// }
+
+ // test_iterators ------------------------------------------------------------------//
+
+ void test_iterators()
+ {
+ std::cout << "testing iterators..." << std::endl;
+
+ path p1;
+ CHECK(p1.begin() == p1.end());
+
+ path p2("/");
+ CHECK(p2.begin() != p2.end());
+ CHECK(*p2.begin() == "/");
+ CHECK(++p2.begin() == p2.end());
+
+ path p3("foo/bar/baz");
+
+ path::iterator it(p3.begin());
+ CHECK(p3.begin() != p3.end());
+ CHECK(*it == "foo");
+ CHECK(*++it == "bar");
+ CHECK(*++it == "baz");
+ CHECK(*--it == "bar");
+ CHECK(*--it == "foo");
+ CHECK(*++it == "bar");
+ CHECK(*++it == "baz");
+ CHECK(++it == p3.end());
+ }
+
+ // test_reverse_iterators ----------------------------------------------------------//
+
+ void test_reverse_iterators()
+ {
+ std::cout << "testing reverse_iterators..." << std::endl;
+
+ path p1;
+ CHECK(p1.rbegin() == p1.rend());
+
+ path p2("/");
+ CHECK(p2.rbegin() != p2.rend());
+ CHECK(*p2.rbegin() == "/");
+ CHECK(++p2.rbegin() == p2.rend());
+
+ path p3("foo/bar/baz");
+
+ path::reverse_iterator it(p3.rbegin());
+ CHECK(p3.rbegin() != p3.rend());
+ CHECK(*it == "baz");
+ CHECK(*++it == "bar");
+ CHECK(*++it == "foo");
+ CHECK(*--it == "bar");
+ CHECK(*--it == "baz");
+ CHECK(*++it == "bar");
+ CHECK(*++it == "foo");
+ CHECK(++it == p3.rend());
+ }
+
+ // test_modifiers ------------------------------------------------------------------//
+
+ void test_modifiers()
+ {
+ std::cout << "testing modifiers..." << std::endl;
+
+ CHECK(path("").remove_filename() == "");
+ CHECK(path("foo").remove_filename() == "");
+ CHECK(path("/foo").remove_filename() == "/");
+ CHECK(path("foo/bar").remove_filename() == "foo");
+ BOOST_TEST_EQ(path("foo/bar/").remove_filename(), path("foo/bar"));
+ BOOST_TEST_EQ(path(".").remove_filename(), path(""));
+ BOOST_TEST_EQ(path("./.").remove_filename(), path("."));
+ BOOST_TEST_EQ(path("/.").remove_filename(), path("/"));
+ BOOST_TEST_EQ(path("..").remove_filename(), path(""));
+ BOOST_TEST_EQ(path("../..").remove_filename(), path(".."));
+ BOOST_TEST_EQ(path("/..").remove_filename(), path("/"));
+
+ }
+
+ // test_decompositions -------------------------------------------------------------//
+
+ void test_decompositions()
+ {
+ std::cout << "testing decompositions..." << std::endl;
+
+ CHECK(path("").root_name().string() == "");
+ CHECK(path("foo").root_name().string() == "");
+ CHECK(path("/").root_name().string() == "");
+ CHECK(path("/foo").root_name().string() == "");
+ CHECK(path("//netname").root_name().string() == "//netname");
+ CHECK(path("//netname/foo").root_name().string() == "//netname");
+
+ CHECK(path("").root_directory().string() == "");
+ CHECK(path("foo").root_directory().string() == "");
+ CHECK(path("/").root_directory().string() == "/");
+ CHECK(path("/foo").root_directory().string() == "/");
+ CHECK(path("//netname").root_directory().string() == "");
+ CHECK(path("//netname/foo").root_directory().string() == "/");
+
+ CHECK(path("").root_path().string() == "");
+ CHECK(path("/").root_path().string() == "/");
+ CHECK(path("/foo").root_path().string() == "/");
+ CHECK(path("//netname").root_path().string() == "//netname");
+ CHECK(path("//netname/foo").root_path().string() == "//netname/");
+
+# ifdef BOOST_WINDOWS_API
+ CHECK(path("c:/foo").root_path().string() == "c:/");
+# endif
+
+ CHECK(path("").relative_path().string() == "");
+ CHECK(path("/").relative_path().string() == "");
+ CHECK(path("/foo").relative_path().string() == "foo");
+
+ CHECK(path("").parent_path().string() == "");
+ CHECK(path("/").parent_path().string() == "");
+ CHECK(path("/foo").parent_path().string() == "/");
+ CHECK(path("/foo/bar").parent_path().string() == "/foo");
+
+ CHECK(path("/foo/bar/baz.zoo").filename().string() == "baz.zoo");
+
+ CHECK(path("/foo/bar/baz.zoo").stem().string() == "baz");
+ CHECK(path("/foo/bar.woo/baz").stem().string() == "baz");
+
+ CHECK(path("foo.bar.baz.tar.bz2").extension().string() == ".bz2");
+ CHECK(path("/foo/bar/baz.zoo").extension().string() == ".zoo");
+ CHECK(path("/foo/bar.woo/baz").extension().string() == "");
+ }
+
+ // test_queries --------------------------------------------------------------------//
+
+ void test_queries()
+ {
+ std::cout << "testing queries..." << std::endl;
+
+ path p1("");
+ path p2("//netname/foo.doo");
+
+ CHECK(p1.empty());
+ CHECK(!p1.has_root_path());
+ CHECK(!p1.has_root_name());
+ CHECK(!p1.has_root_directory());
+ CHECK(!p1.has_relative_path());
+ CHECK(!p1.has_parent_path());
+ CHECK(!p1.has_filename());
+ CHECK(!p1.has_stem());
+ CHECK(!p1.has_extension());
+ CHECK(!p1.is_absolute());
+ CHECK(p1.is_relative());
+
+ CHECK(!p2.empty());
+ CHECK(p2.has_root_path());
+ CHECK(p2.has_root_name());
+ CHECK(p2.has_root_directory());
+ CHECK(p2.has_relative_path());
+ CHECK(p2.has_parent_path());
+ CHECK(p2.has_filename());
+ CHECK(p2.has_stem());
+ CHECK(p2.has_extension());
+ CHECK(p2.is_absolute());
+ CHECK(!p2.is_relative());
+
+ }
+
+ // test_imbue_locale ---------------------------------------------------------------//
+
+ void test_imbue_locale()
+ {
+ std::cout << "testing imbue locale..." << std::endl;
+
+ // weak test case for before/after states since we don't know what characters the
+ // default locale accepts.
+ path before("abc");
+
+ // So that tests are run with known encoding, use Boost UTF-8 codecvt
+ // \u2722 and \xE2\x9C\xA2 are UTF-16 and UTF-8 FOUR TEARDROP-SPOKED ASTERISK
+
+ std::locale global_loc = std::locale();
+ std::locale loc(global_loc, new fs::detail::utf8_codecvt_facet);
+ std::cout << " imbuing locale ..." << std::endl;
+ std::locale old_loc = path::imbue(loc);
+
+ std::cout << " testing with the imbued locale ..." << std::endl;
+ path p2("\xE2\x9C\xA2");
+ CHECK(p2.wstring().size() == 1);
+ CHECK(p2.wstring()[0] == 0x2722);
+
+ std::cout << " imbuing the original locale ..." << std::endl;
+ path::imbue(old_loc);
+
+ std::cout << " testing with the original locale ..." << std::endl;
+ path after("abc");
+ CHECK(before == after);
+
+ std::cout << " locale testing complete" << std::endl;
+ }
+
+ // test_codecvt_argument -----------------------------------------------------------//
+
+ void test_codecvt_argument()
+ {
+ std::cout << "testing codecvt arguments..." << std::endl;
+
+ const char * c1 = "a1";
+ const std::string s1(c1);
+ const std::wstring ws1(L"b2"); // off-by-one mimics test_codecvt
+ const std::string s2("y8");
+ const std::wstring ws2(L"z9");
+
+ test_codecvt cvt; // produces off-by-one values that will always differ from
+ // the system's default locale codecvt facet
+
+ int t = 0;
+
+ // constructors
+ std::cout << " constructors test " << ++t << std::endl;
+ path p(c1, cvt);
+ NATIVE_IS(p, s1, ws1);
+
+ std::cout << " test " << ++t << std::endl;
+ path p1(s1.begin(), s1.end(), cvt);
+ NATIVE_IS(p1, s1, ws1);
+
+ std::cout << " test " << ++t << std::endl;
+ path p2(ws2, cvt);
+ NATIVE_IS(p2, s2, ws2);
+
+ std::cout << " test " << ++t << std::endl;
+ path p3(ws2.begin(), ws2.end(), cvt);
+ NATIVE_IS(p3, s2, ws2);
+
+ // path p2(p1, cvt); // fails to compile, and that is OK
+
+ // assigns
+ p1.clear();
+ std::cout << " assigns test " << ++t << std::endl;
+ p1.assign(s1,cvt);
+ NATIVE_IS(p1, s1, ws1);
+ p1.clear();
+ std::cout << " test " << ++t << std::endl;
+ p1.assign(s1.begin(), s1.end(), cvt);
+ NATIVE_IS(p1, s1, ws1);
+ // p1.assign(p, cvt); // fails to compile, and that is OK
+
+ // appends
+ p1.clear();
+ std::cout << " appends test " << ++t << std::endl;
+ p1.append(s1,cvt);
+ NATIVE_IS(p1, s1, ws1);
+ p1.clear();
+ std::cout << " test " << ++t << std::endl;
+ p1.append(s1.begin(), s1.end(), cvt);
+ NATIVE_IS(p1, s1, ws1);
+ // p1.append(p, cvt); // fails to compile, and that is OK
+
+ // native observers
+ std::cout << " native observers test " << ++t << std::endl;
+ CHECK(p.string<std::string>(cvt) == s1);
+ std::cout << " test " << ++t << std::endl;
+ CHECK(p.string(cvt) == s1);
+ std::cout << " test " << ++t << std::endl;
+ CHECK(p.string<std::wstring>(cvt) == ws1);
+ std::cout << " test " << ++t << std::endl;
+ CHECK(p.wstring(cvt) == ws1);
+
+ // generic observers
+ std::cout << " generic observers test " << ++t << std::endl;
+ CHECK(p.generic_string<std::string>(cvt) == s1);
+ std::cout << " test " << ++t << std::endl;
+ CHECK(p.generic_string(cvt) == s1);
+ std::cout << " test " << ++t << std::endl;
+ CHECK(p.generic_string<std::wstring>(cvt) == ws1);
+ std::cout << " test " << ++t << std::endl;
+ CHECK(p.generic_wstring(cvt) == ws1);
+
+ std::cout << " codecvt arguments testing complete" << std::endl;
+ }
+
+ // test_overloads ------------------------------------------------------------------//
+
+ void test_overloads()
+ {
+ std::cout << "testing overloads..." << std::endl;
+ std::string sto("hello");
+ const char a[] = "goodbye";
+ path p1(sto);
+ path p2(sto.c_str());
+ path p3(a);
+ path p4("foo");
+
+ std::wstring wsto(L"hello");
+ const wchar_t wa[] = L"goodbye";
+ path wp1(wsto);
+ path wp2(wsto.c_str());
+ path wp3(wa);
+ path wp4(L"foo");
+ }
+
+ // test_error_handling -------------------------------------------------------------//
+
+ class error_codecvt
+ : public std::codecvt< wchar_t, char, std::mbstate_t >
+ {
+ public:
+ explicit error_codecvt()
+ : std::codecvt<wchar_t, char, std::mbstate_t>() {}
+ protected:
+
+ virtual bool do_always_noconv() const throw() { return false; }
+ virtual int do_encoding() const throw() { return 0; }
+
+ virtual std::codecvt_base::result do_in(std::mbstate_t&,
+ const char*, const char*, const char*&,
+ wchar_t*, wchar_t*, wchar_t*&) const
+ {
+ static std::codecvt_base::result r = std::codecvt_base::noconv;
+ if (r == std::codecvt_base::partial) r = std::codecvt_base::error;
+ else if (r == std::codecvt_base::error) r = std::codecvt_base::noconv;
+ else r = std::codecvt_base::partial;
+ return r;
+ }
+
+ virtual std::codecvt_base::result do_out(std::mbstate_t &,
+ const wchar_t*, const wchar_t*, const wchar_t*&,
+ char*, char*, char*&) const
+ {
+ static std::codecvt_base::result r = std::codecvt_base::noconv;
+ if (r == std::codecvt_base::partial) r = std::codecvt_base::error;
+ else if (r == std::codecvt_base::error) r = std::codecvt_base::noconv;
+ else r = std::codecvt_base::partial;
+ return r;
+ }
+
+ virtual std::codecvt_base::result do_unshift(std::mbstate_t&,
+ char*, char*, char* &) const { return ok; }
+ virtual int do_length(std::mbstate_t &,
+ const char*, const char*, std::size_t) const { return 0; }
+ virtual int do_max_length() const throw () { return 0; }
+ };
+
+ void test_error_handling()
+ {
+ std::cout << "testing error handling..." << std::endl;
+
+ std::locale global_loc = std::locale();
+ std::locale loc(global_loc, new error_codecvt);
+ std::cout << " imbuing error locale ..." << std::endl;
+ std::locale old_loc = path::imbue(loc);
+
+ // These tests rely on a path constructor that fails in the locale conversion.
+ // Thus construction has to call codecvt. Force that by using a narrow string
+ // for Windows, and a wide string for POSIX.
+# ifdef BOOST_WINDOWS_API
+# define STRING_FOO_ "foo"
+# else
+# define STRING_FOO_ L"foo"
+# endif
+
+ {
+ std::cout << " testing std::codecvt_base::partial error..." << std::endl;
+ bool exception_thrown (false);
+ try { path(STRING_FOO_); }
+ catch (const bs::system_error & ex)
+ {
+ exception_thrown = true;
+ BOOST_TEST_EQ(ex.code(), bs::error_code(std::codecvt_base::partial,
+ fs::codecvt_error_category()));
+ }
+ catch (...) { std::cout << "***** unexpected exception type *****" << std::endl; }
+ BOOST_TEST(exception_thrown);
+ }
+
+ {
+ std::cout << " testing std::codecvt_base::error error..." << std::endl;
+ bool exception_thrown (false);
+ try { path(STRING_FOO_); }
+ catch (const bs::system_error & ex)
+ {
+ exception_thrown = true;
+ BOOST_TEST_EQ(ex.code(), bs::error_code(std::codecvt_base::error,
+ fs::codecvt_error_category()));
+ }
+ catch (...) { std::cout << "***** unexpected exception type *****" << std::endl; }
+ BOOST_TEST(exception_thrown);
+ }
+
+ {
+ std::cout << " testing std::codecvt_base::noconv error..." << std::endl;
+ bool exception_thrown (false);
+ try { path(STRING_FOO_); }
+ catch (const bs::system_error & ex)
+ {
+ exception_thrown = true;
+ BOOST_TEST_EQ(ex.code(), bs::error_code(std::codecvt_base::noconv,
+ fs::codecvt_error_category()));
+ }
+ catch (...) { std::cout << "***** unexpected exception type *****" << std::endl; }
+ BOOST_TEST(exception_thrown);
+ }
+
+ std::cout << " restoring original locale ..." << std::endl;
+ path::imbue(old_loc);
+ std::cout << " testing error handling complete" << std::endl;
+ }
+
+# if 0
+
+// // test_locales --------------------------------------------------------------------//
+//
+// void test_locales()
+// {
+// std::cout << "testing locales..." << std::endl;
+//
+// }
+
+ // test_user_supplied_type ---------------------------------------------------------//
+
+ typedef std::basic_string<int> user_string;
+
+} // unnamed namespace
+
+namespace boost
+{
+namespace filesystem
+{
+ namespace path_traits
+ {
+ template<> struct is_iterator<const user_string::value_type *> { static const bool value = true; };
+ template<> struct is_iterator<user_string::value_type *> { static const bool value = true; };
+ template<> struct is_iterator<user_string::iterator> { static const bool value = true; };
+ template<> struct is_iterator<user_string::const_iterator> { static const bool value = true; };
+ template<> struct is_container<user_string> { static const bool value = true; };
+
+ template<>
+ void append<user_string::value_type>(const user_string::value_type * begin,
+ const user_string::value_type * end, string_type & target, system::error_code & ec)
+ {
+ for (; begin != end && *begin; ++begin)
+ target += *begin + 1; // change so that results distinguishable from char cvts
+ }
+
+# ifdef __GNUC__
+ // This specialization shouldn't be needed, and VC++, Intel, and others work
+ // fine without it. But gcc 4.3.2, and presumably other versions, need it.
+ template<>
+ void append<user_string::value_type>(const user_string::value_type * begin,
+ string_type & target, system::error_code & ec)
+ {
+ path_traits::append<user_string::value_type>(begin,
+ static_cast<const user_string::value_type *>(0), target, ec);
+ }
+# endif
+
+ template<>
+ user_string convert<user_string>(const string_type & source,
+ system::error_code & ec)
+ {
+ user_string temp;
+ for (string_type::const_iterator it = source.begin();
+ it != source.end(); ++it)
+ temp += *it - 1;
+ return temp;
+ }
+ } // namespace path_traits
+} // namespace filesystem
+} // namespace boost
+
+namespace
+{
+
+ void test_user_supplied_type()
+ {
+ std::cout << "testing user supplied type..." << std::endl;
+
+ user_string::value_type usr_c_str[] = { 'a', 'b', 'c', 0 };
+ user_string usr(usr_c_str);
+
+ path p1(usr.c_str());
+ CHECK(p1 == path("bcd"));
+ CHECK(p1 == "bcd");
+ user_string s1(p1.string<user_string>());
+ CHECK(s1 == usr);
+ }
+
+# endif
+
+ inline const char* macro_value(const char* name, const char* value)
+ {
+ static const char* no_value = "[no value]";
+ static const char* not_defined = "[not defined]";
+
+ //if (0 != strcmp(name, value + 1)) // macro is defined
+ //{
+ // if (value[1])
+ // return value;
+ // else
+ // return no_value;
+ //}
+ //return not_defined;
+
+ return 0 == strcmp(name, value + 1)
+ ? not_defined
+ : (value[1] ? value : no_value);
+ }
+
+#define BOOST_MACRO_VALUE(X) macro_value(#X, BOOST_STRINGIZE(=X))
+
+} // unnamed namespace
+
+//--------------------------------------------------------------------------------------//
+// //
+// main //
+// //
+//--------------------------------------------------------------------------------------//
+
+int test_main(int, char*[])
+{
+// document state of critical macros
+#ifdef BOOST_POSIX_API
+ cout << "BOOST_POSIX_API" << endl;
+ BOOST_TEST(path::preferred_separator == '/');
+#endif
+#ifdef BOOST_WINDOWS_API
+ cout << "BOOST_WINDOWS_API" << endl;
+ BOOST_TEST(path::preferred_separator == '\\');
+#endif
+
+ cout << "BOOST_FILESYSTEM_DECL "
+ << BOOST_MACRO_VALUE(BOOST_FILESYSTEM_DECL) << endl;
+
+//#ifdef BOOST_FILESYSTEM_DECL
+// cout << "BOOST_FILESYSTEM_DECL is defined as "
+// << BOOST_STRINGIZE(BOOST_FILESYSTEM_DECL) << endl;
+//#else
+// cout << "BOOST_FILESYSTEM_DECL is not defined" << endl;
+//#endif
+
+ l.push_back('s');
+ l.push_back('t');
+ l.push_back('r');
+ l.push_back('i');
+ l.push_back('n');
+ l.push_back('g');
+
+ wl.push_back(L'w');
+ wl.push_back(L's');
+ wl.push_back(L't');
+ wl.push_back(L'r');
+ wl.push_back(L'i');
+ wl.push_back(L'n');
+ wl.push_back(L'g');
+
+ v.push_back('f');
+ v.push_back('u');
+ v.push_back('z');
+
+ wv.push_back(L'w');
+ wv.push_back(L'f');
+ wv.push_back(L'u');
+ wv.push_back(L'z');
+
+ test_overloads();
+ test_constructors();
+ test_assignments();
+ test_move_construction_and_assignment();
+ test_appends();
+ test_concats();
+ test_modifiers();
+ test_observers();
+ test_relationals();
+ test_inserter_and_extractor();
+ test_other_non_members();
+ test_iterators();
+ test_reverse_iterators();
+ test_decompositions();
+ test_queries();
+ test_imbue_locale();
+ test_codecvt_argument();
+ test_error_handling();
+
+#if 0
+
+ test_user_supplied_type();
+
+#endif
+
+ std::string foo("\\abc");
+ const char* bar = "/abc";
+
+ if (foo == bar)
+ cout << "unintended consequence\n";
+
+ return ::boost::report_errors();
+}