1255 lines
39 KiB
C++
1255 lines
39 KiB
C++
// 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("/"));
|
|
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();
|
|
}
|