blob: ec33236f1de22187c61ff109cfcd8bf0f8c153b4 [file] [log] [blame]
// Boost operations_test.cpp ---------------------------------------------------------//
// Copyright Beman Dawes 2002, 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
#define BOOST_FILESYSTEM_VERSION 3
#include <boost/config.hpp>
# if defined( BOOST_NO_STD_WSTRING )
# error Configuration not supported: Boost.Filesystem V3 and later requires std::wstring support
# endif
#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/operations.hpp>
#include <boost/cerrno.hpp>
namespace fs = boost::filesystem;
#include <boost/detail/lightweight_test.hpp>
using boost::system::error_code;
using boost::system::system_category;
using boost::system::system_error;
#include <fstream>
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include <cstring> // for strncmp, etc.
#include <ctime>
#include <cstdlib> // for system(), getenv(), etc.
#ifdef BOOST_WINDOWS_API
# include <windows.h>
#endif
// on Windows, except for standard libaries known to have wchar_t overloads for
// file stream I/O, use path::string() to get a narrow character c_str()
#if defined(BOOST_WINDOWS_API) \
&& !(defined(_CPPLIB_VER) && _CPPLIB_VER >= 405) // not (Dinkumware with overloads)
# define BOOST_FILESYSTEM_C_STR string().c_str() // use narrow, since wide not available
#else // use the native c_str, which will be narrow on POSIX, wide on Windows
# define BOOST_FILESYSTEM_C_STR c_str()
#endif
#define CHECK_EXCEPTION(Functor,Expect) throws_fs_error(Functor,Expect,__LINE__)
namespace
{
typedef int errno_t;
std::string platform(BOOST_PLATFORM);
bool report_throws;
bool cleanup = true;
fs::path init_path(fs::current_path());
fs::directory_iterator end_itr;
fs::path dir;
fs::path d1;
fs::path d2;
fs::path f0;
fs::path f1;
fs::path d1f1;
bool create_symlink_ok(true);
fs::path ng(" no-way, Jose");
unsigned short language_id; // 0 except for Windows
const char* temp_dir_name = "temp_fs_test_dir";
void create_file(const fs::path & ph, const std::string & contents)
{
std::ofstream f(ph.BOOST_FILESYSTEM_C_STR);
if (!f)
throw fs::filesystem_error("operations_test create_file",
ph, error_code(errno, system_category()));
if (!contents.empty()) f << contents;
}
void verify_file(const fs::path & ph, const std::string & expected)
{
std::ifstream f(ph.BOOST_FILESYSTEM_C_STR);
if (!f)
throw fs::filesystem_error("operations_test verify_file",
ph, error_code(errno, system_category()));
std::string contents;
f >> contents;
if (contents != expected)
throw fs::filesystem_error("operations_test verify_file contents \""
+ contents + "\" != \"" + expected + "\"", ph, error_code());
}
template< typename F >
bool throws_fs_error(F func, errno_t en, int line)
{
try { func(); }
catch (const fs::filesystem_error & ex)
{
if (report_throws)
{
// use the what() convenience function to display exceptions
std::cout << "\n" << ex.what() << "\n";
}
if (en == 0
|| en == ex.code().default_error_condition().value()) return true;
std::cout
<< "\nWarning: line " << line
<< " exception reports default_error_condition().value() "
<< ex.code().default_error_condition().value()
<< ", should be " << en
<< "\n value() is " << ex.code().value()
<< std::endl;
return true;
}
return false;
}
boost::system::error_category* poison_category_aux() { return 0; }
boost::system::error_category& poison_category() { return *poison_category_aux(); }
// compile-only two argument "do-the-right-thing" tests
// verifies that all overload combinations compile without error
void do_not_call()
{
fs::path p;
std::string s;
const char* a = 0;
fs::copy_file(p, p);
fs::copy_file(s, p);
fs::copy_file(a, p);
fs::copy_file(p, s);
fs::copy_file(p, a);
fs::copy_file(s, s);
fs::copy_file(a, s);
fs::copy_file(s, a);
fs::copy_file(a, a);
}
void bad_file_size()
{
fs::file_size(" No way, Jose");
}
void bad_directory_size()
{
fs::file_size(fs::current_path());
}
fs::path bad_create_directory_path;
void bad_create_directory()
{
fs::create_directory(bad_create_directory_path);
}
void bad_equivalent()
{
fs::equivalent("no-such-path", "another-not-present-path");
}
fs::path bad_remove_dir;
void bad_remove()
{
fs::remove(bad_remove_dir);
}
class renamer
{
public:
renamer(const fs::path & p1, const fs::path & p2)
: from(p1), to(p2) {}
void operator()()
{
fs::rename(from, to);
}
private:
fs::path from;
fs::path to;
};
// exception_tests() ---------------------------------------------------------------//
void exception_tests()
{
std::cout << "exception_tests..." << std::endl;
bool exception_thrown;
// catch runtime_error by value
std::cout << " catch runtime_error by value" << std::endl;
exception_thrown = false;
try
{
fs::create_directory("no-such-dir/foo/bar");
}
catch (std::runtime_error x)
{
exception_thrown = true;
if (report_throws) std::cout << x.what() << std::endl;
if (platform == "Windows" && language_id == 0x0409) // English (United States)
// the stdcxx standard library apparently appends additional info
// to what(), so check only the initial portion:
BOOST_TEST(std::strncmp(x.what(),
"boost::filesystem::create_directory",
sizeof("boost::filesystem::create_directory")-1) == 0);
}
BOOST_TEST(exception_thrown);
// catch system_error by value
std::cout << " catch system_error by value" << std::endl;
exception_thrown = false;
try
{
fs::create_directory("no-such-dir/foo/bar");
}
catch (system_error x)
{
exception_thrown = true;
if (report_throws) std::cout << x.what() << std::endl;
if (platform == "Windows" && language_id == 0x0409) // English (United States)
BOOST_TEST(std::strcmp(x.what(),
"boost::filesystem::create_directory: The system cannot find the path specified") == 0);
}
BOOST_TEST(exception_thrown);
// catch filesystem_error by value
std::cout << " catch filesystem_error by value" << std::endl;
exception_thrown = false;
try
{
fs::create_directory("no-such-dir/foo/bar");
}
catch (fs::filesystem_error x)
{
exception_thrown = true;
if (report_throws) std::cout << x.what() << std::endl;
if (platform == "Windows" && language_id == 0x0409) // English (United States)
{
bool ok (std::strcmp(x.what(),
"boost::filesystem::create_directory: The system cannot find the path specified: \"no-such-dir/foo/bar\"") == 0);
BOOST_TEST(ok);
if (!ok)
{
std::cout << "what returns \"" << x.what() << "\"" << std::endl;
}
}
}
BOOST_TEST(exception_thrown);
// catch filesystem_error by const reference
std::cout << " catch filesystem_error by const reference" << std::endl;
exception_thrown = false;
try
{
fs::create_directory("no-such-dir/foo/bar");
}
catch (const fs::filesystem_error & x)
{
exception_thrown = true;
if (report_throws) std::cout << x.what() << std::endl;
if (platform == "Windows" && language_id == 0x0409) // English (United States)
{
bool ok (std::strcmp(x.what(),
"boost::filesystem::create_directory: The system cannot find the path specified: \"no-such-dir/foo/bar\"") == 0);
BOOST_TEST(ok);
if (!ok)
{
std::cout << "what returns \"" << x.what() << "\"" << std::endl;
}
}
}
BOOST_TEST(exception_thrown);
// the bound functions should throw, so CHECK_EXCEPTION() should return true
BOOST_TEST(CHECK_EXCEPTION(bad_file_size, ENOENT));
if (platform == "Windows")
BOOST_TEST(CHECK_EXCEPTION(bad_directory_size, ENOENT));
else
BOOST_TEST(CHECK_EXCEPTION(bad_directory_size, 0));
// test path::exception members
try { fs::file_size(ng); } // will throw
catch (const fs::filesystem_error & ex)
{
BOOST_TEST(ex.path1().string() == " no-way, Jose");
}
std::cout << " exception_tests complete" << std::endl;
}
// create a directory tree that can be used by subsequent tests ---------------------//
//
// dir
// d1
// d1f1 // an empty file
// f0 // an empty file
// f1 // a file containing "file-f1"
void create_tree()
{
// create directory d1
BOOST_TEST(!fs::create_directory(dir));
BOOST_TEST(!fs::is_symlink(dir));
BOOST_TEST(!fs::is_symlink("nosuchfileordirectory"));
d1 = dir / "d1";
BOOST_TEST(fs::create_directory(d1));
BOOST_TEST(fs::exists(d1));
BOOST_TEST(fs::is_directory(d1));
BOOST_TEST(fs::is_empty(d1));
// create an empty file named "d1f1"
d1f1 = d1 / "d1f1";
create_file(d1f1, "");
BOOST_TEST(fs::exists(d1f1));
BOOST_TEST(!fs::is_directory(d1f1));
BOOST_TEST(fs::is_regular_file(d1f1));
BOOST_TEST(fs::is_empty(d1f1));
BOOST_TEST(fs::file_size(d1f1) == 0);
BOOST_TEST(fs::hard_link_count(d1f1) == 1);
// create an empty file named "f0"
f0 = dir / "f0";
create_file(f0, "");
BOOST_TEST(fs::exists(f0));
BOOST_TEST(!fs::is_directory(f0));
BOOST_TEST(fs::is_regular_file(f0));
BOOST_TEST(fs::is_empty(f0));
BOOST_TEST(fs::file_size(f0) == 0);
BOOST_TEST(fs::hard_link_count(f0) == 1);
// create a file named "f1"
f1 = dir / "f1";
create_file(f1, "file-f1");
BOOST_TEST(fs::exists(f1));
BOOST_TEST(!fs::is_directory(f1));
BOOST_TEST(fs::is_regular_file(f1));
BOOST_TEST(fs::file_size(f1) == 7);
verify_file(f1, "file-f1");
}
// directory_iterator_tests --------------------------------------------------------//
void directory_iterator_tests()
{
std::cout << "directory_iterator_tests..." << std::endl;
bool dir_itr_exception(false);
try { fs::directory_iterator it(""); }
catch (const fs::filesystem_error &) { dir_itr_exception = true; }
BOOST_TEST(dir_itr_exception);
error_code ec;
BOOST_TEST(!ec);
fs::directory_iterator it("", ec);
BOOST_TEST(ec);
dir_itr_exception = false;
try { fs::directory_iterator it("nosuchdirectory"); }
catch (const fs::filesystem_error &) { dir_itr_exception = true; }
BOOST_TEST(dir_itr_exception);
ec.clear();
fs::directory_iterator it2("nosuchdirectory", ec);
BOOST_TEST(ec);
dir_itr_exception = false;
try
{
error_code ec;
fs::directory_iterator it("nosuchdirectory", ec);
BOOST_TEST(ec);
BOOST_TEST(ec == boost::system::errc::no_such_file_or_directory);
}
catch (const fs::filesystem_error &) { dir_itr_exception = true; }
BOOST_TEST(!dir_itr_exception);
{
// probe query function overloads
fs::directory_iterator dir_itr(dir);
// BOOST_TEST(fs::is_directory(*dir_itr));
BOOST_TEST(fs::is_directory(dir_itr->status())
|| fs::is_regular_file(dir_itr->status()));
// BOOST_TEST(fs::is_directory(fs::symlink_status(*dir_itr)));
BOOST_TEST(fs::is_directory(dir_itr->symlink_status())
|| fs::is_regular_file(dir_itr->symlink_status()));
BOOST_TEST(dir_itr->path().filename() == "d1"
|| dir_itr->path().filename() == "d2" || dir_itr->path().filename() == "f0"
|| dir_itr->path().filename() == "f1");
}
// create a second directory named d2
d2 = dir / "d2";
fs::create_directory(d2);
BOOST_TEST(fs::exists(d2));
BOOST_TEST(fs::is_directory(d2));
// test the basic operation of directory_iterators, and test that
// stepping one iterator doesn't affect a different iterator.
{
typedef std::vector<fs::directory_entry> vec_type;
vec_type vec;
fs::directory_iterator it1(dir);
BOOST_TEST(it1 != fs::directory_iterator());
BOOST_TEST(fs::exists(it1->status()));
vec.push_back(*it1);
BOOST_TEST(*it1 == vec[0]);
fs::directory_iterator it2(dir);
BOOST_TEST(it2 != fs::directory_iterator());
BOOST_TEST(*it1 == *it2);
++it1;
BOOST_TEST(it1 != fs::directory_iterator());
BOOST_TEST(fs::exists(it1->status()));
BOOST_TEST(it1 != it2);
BOOST_TEST(*it1 != vec[0]);
BOOST_TEST(*it2 == vec[0]);
vec.push_back(*it1);
++it1;
BOOST_TEST(it1 != fs::directory_iterator());
BOOST_TEST(fs::exists(it1->status()));
BOOST_TEST(it1 != it2);
BOOST_TEST(*it2 == vec[0]);
vec.push_back(*it1);
++it1;
BOOST_TEST(it1 != fs::directory_iterator());
BOOST_TEST(fs::exists(it1->status()));
BOOST_TEST(it1 != it2);
BOOST_TEST(*it2 == vec[0]);
vec.push_back(*it1);
++it1;
BOOST_TEST(it1 == fs::directory_iterator());
BOOST_TEST(*it2 == vec[0]);
ec.clear();
it2.increment(ec);
BOOST_TEST(!ec);
BOOST_TEST(it2 != fs::directory_iterator());
BOOST_TEST(it1 == fs::directory_iterator());
BOOST_TEST(*it2 == vec[1]);
++it2;
BOOST_TEST(*it2 == vec[2]);
BOOST_TEST(it1 == fs::directory_iterator());
++it2;
BOOST_TEST(*it2 == vec[3]);
++it2;
BOOST_TEST(it1 == fs::directory_iterator());
BOOST_TEST(it2 == fs::directory_iterator());
// sort vec and check that the right directory entries were found
std::sort(vec.begin(), vec.end());
BOOST_TEST_EQ(vec[0].path().filename().string(), std::string("d1"));
BOOST_TEST_EQ(vec[1].path().filename().string(), std::string("d2"));
BOOST_TEST_EQ(vec[2].path().filename().string(), std::string("f0"));
BOOST_TEST_EQ(vec[3].path().filename().string(), std::string("f1"));
}
{ // *i++ must meet the standard's InputIterator requirements
fs::directory_iterator dir_itr(dir);
BOOST_TEST(dir_itr != fs::directory_iterator());
fs::path p = dir_itr->path();
BOOST_TEST((*dir_itr++).path() == p);
BOOST_TEST(dir_itr != fs::directory_iterator());
BOOST_TEST(dir_itr->path() != p);
// test case reported in comment to SourceForge bug tracker [937606]
fs::directory_iterator it(dir);
const fs::path p1 = (*it++).path();
BOOST_TEST(it != fs::directory_iterator());
const fs::path p2 = (*it++).path();
BOOST_TEST(p1 != p2);
++it;
++it;
BOOST_TEST(it == fs::directory_iterator());
}
// Windows has a tricky special case when just the root-name is given,
// causing the rest of the path to default to the current directory.
// Reported as S/F bug [ 1259176 ]
if (platform == "Windows")
{
fs::path root_name_path(fs::current_path().root_name());
fs::directory_iterator it(root_name_path);
BOOST_TEST(it != fs::directory_iterator());
// BOOST_TEST(fs::exists((*it).path()));
BOOST_TEST(fs::exists(it->path()));
BOOST_TEST(it->path().parent_path() == root_name_path);
bool found(false);
do
{
if (it->path().filename() == temp_dir_name) found = true;
} while (++it != fs::directory_iterator());
BOOST_TEST(found);
}
// there was an inital bug in directory_iterator that caused premature
// close of an OS handle. This block will detect regression.
{
fs::directory_iterator di;
{
di = fs::directory_iterator(dir);
}
BOOST_TEST(++di != fs::directory_iterator());
}
std::cout << " directory_iterator_tests complete" << std::endl;
}
// create_hard_link_tests ----------------------------------------------------------//
void create_hard_link_tests()
{
std::cout << "create_hard_link_tests..." << std::endl;
fs::path from_ph(dir / "f3");
fs::path f1(dir / "f1");
BOOST_TEST(!fs::exists(from_ph));
BOOST_TEST(fs::exists(f1));
bool create_hard_link_ok(true);
try { fs::create_hard_link(f1, from_ph); }
catch (const fs::filesystem_error & ex)
{
create_hard_link_ok = false;
std::cout
<< " *** For information only ***\n"
" create_hard_link() attempt failed\n"
" filesystem_error.what() reports: " << ex.what() << "\n"
" create_hard_link() may not be supported on this file system\n";
}
if (create_hard_link_ok)
{
std::cout
<< " *** For information only ***\n"
" create_hard_link() succeeded\n";
BOOST_TEST(fs::exists(from_ph));
BOOST_TEST(fs::exists(f1));
BOOST_TEST(fs::equivalent(from_ph, f1));
BOOST_TEST(fs::hard_link_count(from_ph) == 2);
BOOST_TEST(fs::hard_link_count(f1) == 2);
}
// Although tests may be running on a FAT or other file system that does
// not support hard links, that is unusual enough that it is considered
// a test failure.
BOOST_TEST(create_hard_link_ok);
error_code ec;
fs::create_hard_link(fs::path("doesnotexist"),
fs::path("shouldnotwork"), ec);
BOOST_TEST(ec);
}
// create_symlink_tests ------------------------------------------------------------//
void create_symlink_tests()
{
std::cout << "create_symlink_tests..." << std::endl;
fs::path from_ph(dir / "f4");
fs::path f1(dir / "f1");
BOOST_TEST(!fs::exists(from_ph));
BOOST_TEST(fs::exists(f1));
try { fs::create_symlink(f1, from_ph); }
catch (const fs::filesystem_error & ex)
{
create_symlink_ok = false;
std::cout
<< " *** For information only ***\n"
" create_symlink() attempt failed\n"
" filesystem_error.what() reports: " << ex.what() << "\n"
" create_symlink() may not be supported on this operating system or file system\n";
}
if (create_symlink_ok)
{
std::cout
<< " *** For information only ***\n"
" create_symlink() succeeded\n";
BOOST_TEST(fs::exists(from_ph));
BOOST_TEST(fs::is_symlink(from_ph));
BOOST_TEST(fs::exists(f1));
BOOST_TEST(fs::equivalent(from_ph, f1));
BOOST_TEST(fs::read_symlink(from_ph) == f1);
fs::file_status stat = fs::symlink_status(from_ph);
BOOST_TEST(fs::exists(stat));
BOOST_TEST(!fs::is_directory(stat));
BOOST_TEST(!fs::is_regular_file(stat));
BOOST_TEST(!fs::is_other(stat));
BOOST_TEST(fs::is_symlink(stat));
stat = fs::status(from_ph);
BOOST_TEST(fs::exists(stat));
BOOST_TEST(!fs::is_directory(stat));
BOOST_TEST(fs::is_regular_file(stat));
BOOST_TEST(!fs::is_other(stat));
BOOST_TEST(!fs::is_symlink(stat));
// since create_symlink worked, copy_symlink should also work
fs::path symlink2_ph(dir / "symlink2");
fs::copy_symlink(from_ph, symlink2_ph);
stat = fs::symlink_status(symlink2_ph);
BOOST_TEST(fs::is_symlink(stat));
BOOST_TEST(fs::exists(stat));
BOOST_TEST(!fs::is_directory(stat));
BOOST_TEST(!fs::is_regular_file(stat));
BOOST_TEST(!fs::is_other(stat));
}
error_code ec = error_code();
fs::create_symlink("doesnotexist", "", ec);
BOOST_TEST(ec);
}
// rename_tests --------------------------------------------------------------------//
void rename_tests()
{
std::cout << "rename_tests..." << std::endl;
fs::path f1(dir / "f1");
BOOST_TEST(fs::exists(f1));
// error: rename a non-existent old file
BOOST_TEST(!fs::exists(d1 / "f99"));
BOOST_TEST(!fs::exists(d1 / "f98"));
renamer n1a(d1 / "f99", d1 / "f98");
BOOST_TEST(CHECK_EXCEPTION(n1a, ENOENT));
renamer n1b(fs::path(""), d1 / "f98");
BOOST_TEST(CHECK_EXCEPTION(n1b, ENOENT));
// error: rename an existing file to ""
renamer n2(f1, "");
BOOST_TEST(CHECK_EXCEPTION(n2, ENOENT));
// rename an existing file to an existent file
create_file(dir / "ff1", "ff1");
create_file(dir / "ff2", "ff2");
fs::rename(dir / "ff2", dir / "ff1");
BOOST_TEST(fs::exists(dir / "ff1"));
verify_file(dir / "ff1", "ff2");
BOOST_TEST(!fs::exists(dir / "ff2"));
// rename an existing file to itself
BOOST_TEST(fs::exists(dir / "f1"));
fs::rename(dir / "f1", dir / "f1");
BOOST_TEST(fs::exists(dir / "f1"));
// error: rename an existing directory to an existing non-empty directory
BOOST_TEST(fs::exists(dir / "f1"));
BOOST_TEST(fs::exists(d1 / "f2"));
// several POSIX implementations (cygwin, openBSD) report ENOENT instead of EEXIST,
// so we don't verify error type on the following test.
renamer n3b(dir, d1);
BOOST_TEST(CHECK_EXCEPTION(n3b, 0));
// error: move existing file to a nonexistent parent directory
BOOST_TEST(!fs::is_directory(dir / "f1"));
BOOST_TEST(!fs::exists(dir / "d3/f3"));
renamer n4a(dir / "f1", dir / "d3/f3");
BOOST_TEST(CHECK_EXCEPTION(n4a, ENOENT));
// rename existing file in same directory
BOOST_TEST(fs::exists(d1 / "f2"));
BOOST_TEST(!fs::exists(d1 / "f50"));
fs::rename(d1 / "f2", d1 / "f50");
BOOST_TEST(!fs::exists(d1 / "f2"));
BOOST_TEST(fs::exists(d1 / "f50"));
fs::rename(d1 / "f50", d1 / "f2");
BOOST_TEST(fs::exists(d1 / "f2"));
BOOST_TEST(!fs::exists(d1 / "f50"));
// move and rename an existing file to a different directory
fs::rename(d1 / "f2", d2 / "f3");
BOOST_TEST(!fs::exists(d1 / "f2"));
BOOST_TEST(!fs::exists(d2 / "f2"));
BOOST_TEST(fs::exists(d2 / "f3"));
BOOST_TEST(!fs::is_directory(d2 / "f3"));
verify_file(d2 / "f3", "file-f1");
fs::rename(d2 / "f3", d1 / "f2");
BOOST_TEST(fs::exists(d1 / "f2"));
// error: move existing directory to nonexistent parent directory
BOOST_TEST(fs::exists(d1));
BOOST_TEST(!fs::exists(dir / "d3/d5"));
BOOST_TEST(!fs::exists(dir / "d3"));
renamer n5a(d1, dir / "d3/d5");
BOOST_TEST(CHECK_EXCEPTION(n5a, ENOENT));
// rename existing directory
fs::path d3(dir / "d3");
BOOST_TEST(fs::exists(d1));
BOOST_TEST(fs::exists(d1 / "f2"));
BOOST_TEST(!fs::exists(d3));
fs::rename(d1, d3);
BOOST_TEST(!fs::exists(d1));
BOOST_TEST(fs::exists(d3));
BOOST_TEST(fs::is_directory(d3));
BOOST_TEST(!fs::exists(d1 / "f2"));
BOOST_TEST(fs::exists(d3 / "f2"));
fs::rename(d3, d1);
BOOST_TEST(fs::exists(d1));
BOOST_TEST(fs::exists(d1 / "f2"));
BOOST_TEST(!fs::exists(d3));
// rename and move d1 to d2 / "d20"
BOOST_TEST(fs::exists(d1));
BOOST_TEST(!fs::exists(d2 / "d20"));
BOOST_TEST(fs::exists(d1 / "f2"));
fs::rename(d1, d2 / "d20");
BOOST_TEST(!fs::exists(d1));
BOOST_TEST(fs::exists(d2 / "d20"));
BOOST_TEST(fs::exists(d2 / "d20" / "f2"));
fs::rename(d2 / "d20", d1);
BOOST_TEST(fs::exists(d1));
BOOST_TEST(!fs::exists(d2 / "d20"));
BOOST_TEST(fs::exists(d1 / "f2"));
}
// predicate_and_status_tests ------------------------------------------------------//
void predicate_and_status_tests()
{
std::cout << "predicate_and_status_tests..." << std::endl;
BOOST_TEST(!fs::exists(ng));
BOOST_TEST(!fs::is_directory(ng));
BOOST_TEST(!fs::is_regular_file(ng));
BOOST_TEST(!fs::is_symlink(ng));
fs::file_status stat(fs::status(ng));
BOOST_TEST(fs::status_known(stat));
BOOST_TEST(!fs::exists(stat));
BOOST_TEST(!fs::is_directory(stat));
BOOST_TEST(!fs::is_regular_file(stat));
BOOST_TEST(!fs::is_other(stat));
BOOST_TEST(!fs::is_symlink(stat));
stat = fs::status("");
BOOST_TEST(fs::status_known(stat));
BOOST_TEST(!fs::exists(stat));
BOOST_TEST(!fs::is_directory(stat));
BOOST_TEST(!fs::is_regular_file(stat));
BOOST_TEST(!fs::is_other(stat));
BOOST_TEST(!fs::is_symlink(stat));
}
// create_directory_tests ----------------------------------------------------------//
void create_directory_tests()
{
std::cout << "create_directory_tests..." << std::endl;
// create a directory, then check it for consistency
// take extra care to report problems, since if this fails
// many subsequent tests will fail
try
{
fs::create_directory(dir);
}
catch (const fs::filesystem_error & x)
{
std::cout << x.what() << "\n\n"
"***** Creating directory " << dir << " failed. *****\n"
"***** This is a serious error that will prevent further tests *****\n"
"***** from returning useful results. Further testing is aborted. *****\n\n";
std::exit(1);
}
catch (...)
{
std::cout << "\n\n"
"***** Creating directory " << dir << " failed. *****\n"
"***** This is a serious error that will prevent further tests *****\n"
"***** from returning useful results. Further testing is aborted. *****\n\n";
std::exit(1);
}
BOOST_TEST(fs::exists(dir));
BOOST_TEST(fs::is_empty(dir));
BOOST_TEST(fs::is_directory(dir));
BOOST_TEST(!fs::is_regular_file(dir));
BOOST_TEST(!fs::is_other(dir));
BOOST_TEST(!fs::is_symlink(dir));
fs::file_status stat = fs::status(dir);
BOOST_TEST(fs::exists(stat));
BOOST_TEST(fs::is_directory(stat));
BOOST_TEST(!fs::is_regular_file(stat));
BOOST_TEST(!fs::is_other(stat));
BOOST_TEST(!fs::is_symlink(stat));
std::cout << " create_directory_tests complete" << std::endl;
}
// current_directory_tests ---------------------------------------------------------//
void current_directory_tests()
{
std::cout << "current_directory_tests..." << std::endl;
// set the current directory, then check it for consistency
fs::path original_dir = fs::current_path();
BOOST_TEST(dir != original_dir);
fs::current_path(dir);
BOOST_TEST(fs::current_path() == dir);
BOOST_TEST(fs::current_path() != original_dir);
fs::current_path(original_dir);
BOOST_TEST(fs::current_path() == original_dir);
BOOST_TEST(fs::current_path() != dir);
// make sure the overloads work
fs::current_path(dir.c_str());
BOOST_TEST(fs::current_path() == dir);
BOOST_TEST(fs::current_path() != original_dir);
fs::current_path(original_dir.string());
BOOST_TEST(fs::current_path() == original_dir);
BOOST_TEST(fs::current_path() != dir);
}
// create_directories_tests --------------------------------------------------------//
void create_directories_tests()
{
std::cout << "create_directories_tests..." << std::endl;
fs::path p = dir / "level1" / "level2";
BOOST_TEST(!fs::exists(p));
BOOST_TEST(fs::create_directories(p));
BOOST_TEST(fs::exists(p));
BOOST_TEST(fs::is_directory(p));
}
// resize_file_tests ---------------------------------------------------------------//
void resize_file_tests()
{
std::cout << "resize_file_tests..." << std::endl;
fs::path p(dir / "resize_file_test.txt");
fs::remove(p);
create_file(p, "1234567890");
BOOST_TEST(fs::exists(p));
BOOST_TEST_EQ(fs::file_size(p), 10U);
fs::resize_file(p, 5);
BOOST_TEST(fs::exists(p));
BOOST_TEST_EQ(fs::file_size(p), 5U);
fs::resize_file(p, 15);
BOOST_TEST(fs::exists(p));
BOOST_TEST_EQ(fs::file_size(p), 15U);
error_code ec;
fs::resize_file("no such file", 15, ec);
BOOST_TEST(ec);
}
// status_of_nonexistent_tests -----------------------------------------------------//
void status_of_nonexistent_tests()
{
std::cout << "status_of_nonexistent_tests..." << std::endl;
fs::path p ("nosuch");
BOOST_TEST(!fs::exists(p));
BOOST_TEST(!fs::is_regular_file(p));
BOOST_TEST(!fs::is_directory(p));
BOOST_TEST(!fs::is_symlink(p));
BOOST_TEST(!fs::is_other(p));
fs::file_status s = fs::status(p);
BOOST_TEST(!fs::exists(s));
BOOST_TEST_EQ(s.type(), fs::file_not_found);
BOOST_TEST(fs::status_known(s));
BOOST_TEST(!fs::is_regular_file(s));
BOOST_TEST(!fs::is_directory(s));
BOOST_TEST(!fs::is_symlink(s));
BOOST_TEST(!fs::is_other(s));
}
// status_error_reporting_tests ----------------------------------------------------//
void status_error_reporting_tests()
{
std::cout << "status_error_reporting_tests..." << std::endl;
error_code ec;
// test status, ec, for existing file
ec.assign(-1,poison_category());
BOOST_TEST(ec.value() == -1);
BOOST_TEST(&ec.category() == &poison_category());
fs::file_status s = fs::status(".",ec);
BOOST_TEST(ec.value() == 0);
BOOST_TEST(ec.category() == system_category());
BOOST_TEST(fs::exists(s));
BOOST_TEST(fs::is_directory(s));
// test status, ec, for non-existing file
fs::path p ("nosuch");
ec.assign(-1,poison_category());
s = fs::status(p,ec);
BOOST_TEST(ec.value() != 0);
BOOST_TEST(ec.category() == system_category());
BOOST_TEST(!fs::exists(s));
BOOST_TEST_EQ(s.type(), fs::file_not_found);
BOOST_TEST(fs::status_known(s));
BOOST_TEST(!fs::is_regular_file(s));
BOOST_TEST(!fs::is_directory(s));
BOOST_TEST(!fs::is_symlink(s));
BOOST_TEST(!fs::is_other(s));
// test queries, ec, for existing file
ec.assign(-1,poison_category());
BOOST_TEST(fs::exists(".", ec));
BOOST_TEST(ec.value() == 0);
BOOST_TEST(ec.category() == system_category());
ec.assign(-1,poison_category());
BOOST_TEST(!fs::is_regular_file(".", ec));
BOOST_TEST(ec.value() == 0);
BOOST_TEST(ec.category() == system_category());
ec.assign(-1,poison_category());
BOOST_TEST(fs::is_directory(".", ec));
BOOST_TEST(ec.value() == 0);
BOOST_TEST(ec.category() == system_category());
// test queries, ec, for non-existing file
ec.assign(-1,poison_category());
BOOST_TEST(!fs::exists(p, ec));
BOOST_TEST(ec.value() != 0);
BOOST_TEST(ec.category() == system_category());
ec.assign(-1,poison_category());
BOOST_TEST(!fs::is_regular_file(p, ec));
BOOST_TEST(ec.value() != 0);
BOOST_TEST(ec.category() == system_category());
ec.assign(-1,poison_category());
BOOST_TEST(!fs::is_directory(p, ec));
BOOST_TEST(ec.value() != 0);
BOOST_TEST(ec.category() == system_category());
}
// remove_tests --------------------------------------------------------------------//
void remove_tests(const fs::path& dir)
{
std::cout << "remove_tests..." << std::endl;
// remove() file
fs::path f1 = dir / "shortlife";
BOOST_TEST(!fs::exists(f1));
create_file(f1, "");
BOOST_TEST(fs::exists(f1));
BOOST_TEST(!fs::is_directory(f1));
BOOST_TEST(fs::remove(f1));
BOOST_TEST(!fs::exists(f1));
BOOST_TEST(!fs::remove("no-such-file"));
BOOST_TEST(!fs::remove("no-such-directory/no-such-file"));
// remove() directory
fs::path d1 = dir / "shortlife_dir";
BOOST_TEST(!fs::exists(d1));
fs::create_directory(d1);
BOOST_TEST(fs::exists(d1));
BOOST_TEST(fs::is_directory(d1));
BOOST_TEST(fs::is_empty(d1));
bad_remove_dir = dir;
BOOST_TEST(CHECK_EXCEPTION(bad_remove, ENOTEMPTY));
BOOST_TEST(fs::remove(d1));
BOOST_TEST(!fs::exists(d1));
}
// remove_symlink_tests ------------------------------------------------------------//
void remove_symlink_tests()
{
std::cout << "remove_symlink_tests..." << std::endl;
// remove() dangling symbolic link
fs::path link("dangling_link");
fs::remove(link); // remove any residue from past tests
BOOST_TEST(!fs::is_symlink(link));
BOOST_TEST(!fs::exists(link));
fs::create_symlink("nowhere", link);
BOOST_TEST(!fs::exists(link));
BOOST_TEST(fs::is_symlink(link));
BOOST_TEST(fs::remove(link));
BOOST_TEST(!fs::is_symlink(link));
// remove() self-refering symbolic link
link = "link_to_self";
fs::remove(link); // remove any residue from past tests
BOOST_TEST(!fs::is_symlink(link));
BOOST_TEST(!fs::exists(link));
fs::create_symlink(link, link);
BOOST_TEST(fs::remove(link));
BOOST_TEST(!fs::exists(link));
BOOST_TEST(!fs::is_symlink(link));
// remove() cyclic symbolic link
link = "link_to_a";
fs::path link2("link_to_b");
fs::remove(link); // remove any residue from past tests
fs::remove(link2); // remove any residue from past tests
BOOST_TEST(!fs::is_symlink(link));
BOOST_TEST(!fs::exists(link));
fs::create_symlink(link, link2);
fs::create_symlink(link2, link);
BOOST_TEST(fs::remove(link));
BOOST_TEST(fs::remove(link2));
BOOST_TEST(!fs::exists(link));
BOOST_TEST(!fs::exists(link2));
BOOST_TEST(!fs::is_symlink(link));
// remove() symbolic link to file
fs::path f1 = "link_target";
fs::remove(f1); // remove any residue from past tests
BOOST_TEST(!fs::exists(f1));
create_file(f1, "");
BOOST_TEST(fs::exists(f1));
BOOST_TEST(!fs::is_directory(f1));
BOOST_TEST(fs::is_regular_file(f1));
link = "non_dangling_link";
fs::create_symlink(f1, link);
BOOST_TEST(fs::exists(link));
BOOST_TEST(!fs::is_directory(link));
BOOST_TEST(fs::is_regular_file(link));
BOOST_TEST(fs::is_symlink(link));
BOOST_TEST(fs::remove(link));
BOOST_TEST(fs::exists(f1));
BOOST_TEST(!fs::exists(link));
BOOST_TEST(!fs::is_symlink(link));
BOOST_TEST(fs::remove(f1));
BOOST_TEST(!fs::exists(f1));
}
// absolute_tests -----------------------------------------------------------------//
void absolute_tests()
{
std::cout << "absolute_tests..." << std::endl;
BOOST_TEST_EQ(fs::absolute(""), fs::current_path() );
BOOST_TEST_EQ(fs::absolute(fs::current_path() / "foo/bar"), fs::current_path() / "foo/bar");
BOOST_TEST_EQ(fs::absolute("foo"), fs::current_path() / "foo");
BOOST_TEST_EQ(fs::absolute("foo", fs::current_path()), fs::current_path() / "foo");
BOOST_TEST_EQ(fs::absolute("bar", "foo"), fs::current_path() / "foo" / "bar");
BOOST_TEST_EQ(fs::absolute("/foo"), fs::current_path().root_name().string() + "/foo");
# ifdef BOOST_WINDOWS_API
BOOST_TEST_EQ(fs::absolute("a:foo", "b:/bar"), "a:/bar/foo");
# endif
// these tests were moved from elsewhere, so may duplicate some of the above tests
// p.empty()
BOOST_TEST_EQ(fs::absolute(fs::path(), "//foo/bar"), "//foo/bar");
if (platform == "Windows")
{
BOOST_TEST_EQ(fs::absolute(fs::path(), "a:/bar"), "a:/bar");
}
// p.has_root_name()
// p.has_root_directory()
BOOST_TEST_EQ(fs::absolute(fs::path("//foo/bar"), "//uvw/xyz"), "//foo/bar");
if (platform == "Windows")
{
BOOST_TEST_EQ(fs::absolute(fs::path("a:/bar"), "b:/xyz"), "a:/bar");
}
// !p.has_root_directory()
BOOST_TEST_EQ(fs::absolute(fs::path("//net"), "//xyz/"), "//net/");
BOOST_TEST_EQ(fs::absolute(fs::path("//net"), "//xyz/abc"), "//net/abc");
BOOST_TEST_EQ(fs::absolute(fs::path("//net"), "//xyz/abc/def"), "//net/abc/def");
if (platform == "Windows")
{
BOOST_TEST_EQ(fs::absolute(fs::path("a:"), "b:/"), "a:/");
BOOST_TEST_EQ(fs::absolute(fs::path("a:"),"b:/abc"), "a:/abc");
BOOST_TEST_EQ(fs::absolute(fs::path("a:"),"b:/abc/def"), "a:/abc/def");
BOOST_TEST_EQ(fs::absolute(fs::path("a:foo"), "b:/"), "a:/foo");
BOOST_TEST_EQ(fs::absolute(fs::path("a:foo"), "b:/abc"), "a:/abc/foo");
BOOST_TEST_EQ(fs::absolute(fs::path("a:foo"), "b:/abc/def"), "a:/abc/def/foo");
BOOST_TEST_EQ(fs::absolute(fs::path("a:foo/bar"), "b:/"), "a:/foo/bar");
BOOST_TEST_EQ(fs::absolute(fs::path("a:foo/bar"), "b:/abc"), "a:/abc/foo/bar");
BOOST_TEST_EQ(fs::absolute(fs::path("a:foo/bar"), "b:/abc/def"), "a:/abc/def/foo/bar");
}
// !p.has_root_name()
// p.has_root_directory()
BOOST_TEST_EQ(fs::absolute(fs::path("/"), "//xyz/"), "//xyz/");
BOOST_TEST_EQ(fs::absolute(fs::path("/"), "//xyz/abc"), "//xyz/");
BOOST_TEST_EQ(fs::absolute(fs::path("/foo"), "//xyz/"), "//xyz/foo");
BOOST_TEST_EQ(fs::absolute(fs::path("/foo"), "//xyz/abc"), "//xyz/foo");
// !p.has_root_directory()
BOOST_TEST_EQ(fs::absolute(fs::path("foo"), "//xyz/abc"), "//xyz/abc/foo");
BOOST_TEST_EQ(fs::absolute(fs::path("foo/bar"), "//xyz/abc"), "//xyz/abc/foo/bar");
BOOST_TEST_EQ(fs::absolute(fs::path("."), "//xyz/abc"), "//xyz/abc/.");
BOOST_TEST_EQ(fs::absolute(fs::path(".."), "//xyz/abc"), "//xyz/abc/..");
BOOST_TEST_EQ(fs::absolute(fs::path("./foo"), "//xyz/abc"), "//xyz/abc/./foo");
BOOST_TEST_EQ(fs::absolute(fs::path("../foo"), "//xyz/abc"), "//xyz/abc/../foo");
if (platform == "POSIX")
{
BOOST_TEST_EQ(fs::absolute(fs::path("foo"), "/abc"), "/abc/foo");
BOOST_TEST_EQ(fs::absolute(fs::path("foo/bar"), "/abc"), "/abc/foo/bar");
BOOST_TEST_EQ(fs::absolute(fs::path("."), "/abc"), "/abc/.");
BOOST_TEST_EQ(fs::absolute(fs::path(".."), "/abc"), "/abc/..");
BOOST_TEST_EQ(fs::absolute(fs::path("./foo"), "/abc"), "/abc/./foo");
BOOST_TEST_EQ(fs::absolute(fs::path("../foo"), "/abc"), "/abc/../foo");
}
}
// copy_file_tests -----------------------------------------------------------------//
void copy_file_tests(const fs::path& f1, const fs::path& d1)
{
std::cout << "copy_file_tests..." << std::endl;
BOOST_TEST(fs::exists(f1));
fs::remove(d1 / "f2"); // remove possible residue from prior testing
BOOST_TEST(fs::exists(d1));
BOOST_TEST(!fs::exists(d1 / "f2"));
std::cout << " copy " << f1 << " to " << d1 / "f2" << std::endl;
fs::copy_file(f1, d1 / "f2");
std::cout << " copy complete" << std::endl;
BOOST_TEST(fs::exists(f1));
BOOST_TEST(fs::exists(d1 / "f2"));
BOOST_TEST(!fs::is_directory(d1 / "f2"));
verify_file(d1 / "f2", "file-f1");
bool copy_ex_ok = false;
try { fs::copy_file(f1, d1 / "f2"); }
catch (const fs::filesystem_error &) { copy_ex_ok = true; }
BOOST_TEST(copy_ex_ok);
copy_ex_ok = false;
try { fs::copy_file(f1, d1 / "f2", fs::copy_option::fail_if_exists); }
catch (const fs::filesystem_error &) { copy_ex_ok = true; }
BOOST_TEST(copy_ex_ok);
copy_ex_ok = true;
try { fs::copy_file(f1, d1 / "f2", fs::copy_option::overwrite_if_exists); }
catch (const fs::filesystem_error &) { copy_ex_ok = false; }
BOOST_TEST(copy_ex_ok);
}
// symlink_status_tests -------------------------------------------------------------//
void symlink_status_tests()
{
std::cout << "symlink_status_tests..." << std::endl;
boost::system::error_code ec;
fs::path dangling_sym(dir / "dangling-sym");
fs::path dangling_directory_sym(dir / "dangling-directory-sym");
fs::path sym_d1(dir / "sym-d1");
fs::path symsym_d1(dir / "symsym-d1");
fs::path sym_f1(dir / "sym-f1");
fs::path symsym_f1(dir / "symsym-f1");
fs::create_symlink("does not exist", dangling_sym);
fs::create_directory_symlink("does not exist", dangling_directory_sym);
fs::create_directory_symlink(d1, sym_d1);
fs::create_directory_symlink(sym_d1, symsym_d1);
fs::create_symlink(f1, sym_f1);
fs::create_symlink(sym_f1, symsym_f1);
// verify all cases detected as symlinks
BOOST_TEST_EQ(fs::symlink_status(dangling_sym, ec).type(), fs::symlink_file);
BOOST_TEST_EQ(fs::symlink_status(dangling_directory_sym, ec).type(), fs::symlink_file);
BOOST_TEST_EQ(fs::symlink_status(sym_d1, ec).type(), fs::symlink_file);
BOOST_TEST_EQ(fs::symlink_status(symsym_d1, ec).type(), fs::symlink_file);
BOOST_TEST_EQ(fs::symlink_status(sym_f1, ec).type(), fs::symlink_file);
BOOST_TEST_EQ(fs::symlink_status(symsym_f1, ec).type(), fs::symlink_file);
// verify all cases resolve to the (possibly recursive) symlink target
BOOST_TEST_EQ(fs::status(dangling_sym, ec).type(), fs::file_not_found);
BOOST_TEST_EQ(fs::status(dangling_directory_sym, ec).type(), fs::file_not_found);
BOOST_TEST_EQ(fs::status(sym_d1, ec).type(), fs::directory_file);
BOOST_TEST_EQ(fs::status(sym_d1 / "d1f1", ec).type(), fs::regular_file);
BOOST_TEST_EQ(fs::status(symsym_d1, ec).type(), fs::directory_file);
BOOST_TEST_EQ(fs::status(symsym_d1 / "d1f1", ec).type(), fs::regular_file);
BOOST_TEST_EQ(fs::status(sym_f1, ec).type(), fs::regular_file);
BOOST_TEST_EQ(fs::status(symsym_f1, ec).type(), fs::regular_file);
#ifdef BOOST_WINDOWS_API
// On Windows, telling if a filesystem entry is a symlink, rather than some other
// kind of reparse point such as a junction, requires some truely baroque code.
// See ticket #4663, filesystem objects falsely identified as symlinks.
// This test checks two directory entries created by Windows itself to verify
// is_symlink() works correctly. Try "dir /A %HOMEPATH%\.." from the command line to
// verify this test is valid on your version of Windows. It only works on Vista and
// later.
fs::path users(getenv("HOMEDRIVE"));
BOOST_TEST(!users.empty());
users /= "\\Users";
BOOST_TEST(fs::exists(users));
BOOST_TEST(fs::exists(users/"All Users"));
BOOST_TEST(fs::exists(users/"Default User"));
BOOST_TEST(fs::is_symlink(users/"All Users")); // dir /A reports <SYMLINKD>
BOOST_TEST(!fs::is_symlink(users/"Default User")); // dir /A reports <JUNCTION> <JUNCTION>
#endif
}
// copy_symlink_tests ---------------------------------------------------------------//
void copy_symlink_tests(const fs::path& f1, const fs::path& d1)
{
std::cout << "copy_symlink_tests..." << std::endl;
BOOST_TEST(fs::exists(f1));
BOOST_TEST(fs::exists(d1));
fs::path sym1(d1 / "symlink1");
fs::remove(sym1); // remove possible residue from prior testing
fs::create_symlink(f1, sym1);
BOOST_TEST(fs::exists(sym1));
BOOST_TEST(fs::is_symlink(sym1));
fs::path sym2(d1 / "symlink2");
fs::copy_symlink(sym1, sym2);
BOOST_TEST(fs::exists(sym2));
BOOST_TEST(fs::is_symlink(sym2));
//fs::path sym3(d1 / "symlink3");
//fs::copy(sym1, sym3);
//BOOST_TEST(fs::exists(sym3));
//BOOST_TEST(fs::is_symlink(sym3));
bool copy_ex_ok = false;
try { fs::copy_symlink("no-such-file", "new-symlink1"); }
catch (const fs::filesystem_error &) { copy_ex_ok = true; }
BOOST_TEST(copy_ex_ok);
copy_ex_ok = false;
try { fs::copy_symlink(f1, "new-symlink2"); } // should fail; f1 not symlink
catch (const fs::filesystem_error &) { copy_ex_ok = true; }
BOOST_TEST(copy_ex_ok);
}
// write_time_tests ----------------------------------------------------------------//
void write_time_tests(const fs::path& dir)
{
std::cout << "write_time_tests..." << std::endl;
fs::path f1 = dir / "foobar2";
create_file(f1, "foobar2");
BOOST_TEST(fs::exists(f1));
BOOST_TEST(!fs::is_directory(f1));
BOOST_TEST(fs::is_regular_file(f1));
BOOST_TEST(fs::file_size(f1) == 7);
verify_file(f1, "foobar2");
// Some file system report last write time as local (FAT), while
// others (NTFS) report it as UTC. The C standard does not specify
// if time_t is local or UTC.
std::time_t ft = fs::last_write_time(f1);
std::cout << "\n UTC last_write_time() for a file just created is "
<< std::asctime(std::gmtime(&ft)) << std::endl;
std::tm * tmp = std::localtime(&ft);
std::cout << "\n Year is " << tmp->tm_year << std::endl;
--tmp->tm_year;
std::cout << " Change year to " << tmp->tm_year << std::endl;
fs::last_write_time(f1, std::mktime(tmp));
std::time_t ft2 = fs::last_write_time(f1);
std::cout << " last_write_time() for the file is now "
<< std::asctime(std::gmtime(&ft2)) << std::endl;
BOOST_TEST(ft != fs::last_write_time(f1));
std::cout << "\n Reset to current time" << std::endl;
fs::last_write_time(f1, ft);
double time_diff = std::difftime(ft, fs::last_write_time(f1));
std::cout
<< " original last_write_time() - current last_write_time() is "
<< time_diff << " seconds" << std::endl;
BOOST_TEST(time_diff >= -60.0 && time_diff <= 60.0);
}
// platform_specific_tests ---------------------------------------------------------//
void platform_specific_tests()
{
// Windows only tests
if (platform == "Windows")
{
std::cout << "Window specific tests..."
"\n (may take several seconds)" << std::endl;
BOOST_TEST(!fs::exists(fs::path("//share-not")));
BOOST_TEST(!fs::exists(fs::path("//share-not/")));
BOOST_TEST(!fs::exists(fs::path("//share-not/foo")));
BOOST_TEST(!fs::exists("tools/jam/src/:sys:stat.h")); // !exists() if ERROR_INVALID_NAME
BOOST_TEST(!fs::exists(":sys:stat.h")); // !exists() if ERROR_INVALID_PARAMETER
BOOST_TEST(dir.string().size() > 1
&& dir.string()[1] == ':'); // verify path includes drive
BOOST_TEST(fs::system_complete("").empty());
BOOST_TEST(fs::system_complete("/") == init_path.root_path());
BOOST_TEST(fs::system_complete("foo")
== init_path / "foo");
fs::path p1(fs::system_complete("/foo"));
BOOST_TEST_EQ(p1.string().size(), 6U); // this failed during v3 development due to bug
std::string s1(p1.string() );
std::string s2(init_path.root_path().string()+"foo");
BOOST_TEST_EQ(s1, s2);
BOOST_TEST(fs::system_complete(fs::path(init_path.root_name()))
== init_path);
BOOST_TEST(fs::system_complete(fs::path(init_path.root_name().string()
+ "foo")).string() == init_path / "foo");
BOOST_TEST(fs::system_complete(fs::path("c:/")).generic_string()
== "c:/");
BOOST_TEST(fs::system_complete(fs::path("c:/foo")).generic_string()
== "c:/foo");
BOOST_TEST(fs::system_complete(fs::path("//share")).generic_string()
== "//share");
} // Windows
else if (platform == "POSIX")
{
std::cout << "POSIX specific tests..." << std::endl;
BOOST_TEST(fs::system_complete("").empty());
BOOST_TEST(init_path.root_path().string() == "/");
BOOST_TEST(fs::system_complete("/").string() == "/");
BOOST_TEST(fs::system_complete("foo").string()
== init_path.string()+"/foo");
BOOST_TEST(fs::system_complete("/foo").string()
== init_path.root_path().string()+"foo");
} // POSIX
}
// initial_tests -------------------------------------------------------------------//
void initial_tests()
{
std::cout << "initial_tests..." << std::endl;
std::cout << " current_path().string() is\n \""
<< init_path.string()
<< "\"\n\n";
BOOST_TEST(init_path.is_absolute());
BOOST_TEST(fs::current_path().is_absolute());
BOOST_TEST(init_path.string()
== fs::current_path().string());
}
// space_tests ---------------------------------------------------------------------//
void space_tests()
{
std::cout << "space_tests..." << std::endl;
// make some reasonable assuptions for testing purposes
fs::space_info spi(fs::space(dir));
BOOST_TEST(spi.capacity > 1000000);
BOOST_TEST(spi.free > 1000);
BOOST_TEST(spi.capacity > spi.free);
BOOST_TEST(spi.free >= spi.available);
// it is convenient to display space, but older VC++ versions choke
# if !defined(BOOST_MSVC) || _MSC_VER >= 1300 // 1300 == VC++ 7.0
std::cout << " capacity = " << spi.capacity << '\n';
std::cout << " free = " << spi.free << '\n';
std::cout << " available = " << spi.available << '\n';
# endif
}
// equivalent_tests ----------------------------------------------------------------//
void equivalent_tests(const fs::path& f1)
{
std::cout << "equivalent_tests..." << std::endl;
BOOST_TEST(CHECK_EXCEPTION(bad_equivalent, ENOENT));
BOOST_TEST(fs::equivalent(f1, dir / "f1"));
BOOST_TEST(fs::equivalent(dir, d1 / ".."));
BOOST_TEST(!fs::equivalent(f1, dir));
BOOST_TEST(!fs::equivalent(dir, f1));
BOOST_TEST(!fs::equivalent(d1, d2));
BOOST_TEST(!fs::equivalent(dir, ng));
BOOST_TEST(!fs::equivalent(ng, dir));
BOOST_TEST(!fs::equivalent(f1, ng));
BOOST_TEST(!fs::equivalent(ng, f1));
}
// _tests --------------------------------------------------------------------------//
void _tests()
{
std::cout << "_tests..." << std::endl;
}
} // unnamed namespace
//------------------------------------------------------------------------------------//
// //
// main //
// //
//------------------------------------------------------------------------------------//
int main(int argc, char* argv[])
{
// document state of critical macros
#ifdef BOOST_POSIX_API
std::cout << "BOOST_POSIX_API is defined\n";
#endif
#ifdef BOOST_WINDOWS_API
std::cout << "BOOST_WINDOWS_API is defined\n";
#endif
if (argc > 1 && *argv[1]=='-' && *(argv[1]+1)=='t') report_throws = true;
if (argc > 1 && *argv[1]=='-' && *(argv[1]+1)=='x') cleanup = false;
// The choice of platform to test is make at runtime rather than compile-time
// so that compile errors for all platforms will be detected even though
// only the current platform is runtime tested.
# if defined(BOOST_POSIX_API)
platform = "POSIX";
# elif defined(BOOST_WINDOWS_API)
platform = "Windows";
# if !defined(__MINGW32__) && !defined(__CYGWIN__)
language_id = ::GetUserDefaultUILanguage();
# else
language_id = 0x0409; // Assume US English
# endif
# else
# error neither BOOST_POSIX_API nor BOOST_WINDOWS_API is defined. See boost/system/api_config.hpp
# endif
std::cout << "API is " << platform << std::endl;
dir = init_path / temp_dir_name;
if (fs::exists(dir))
{
std::cout << "remove residue from prior failed tests..." << std::endl;
fs::remove_all(dir);
}
BOOST_TEST(!fs::exists(dir));
// several functions give unreasonable results if uintmax_t isn't 64-bits
std::cout << "sizeof(boost::uintmax_t) = " << sizeof(boost::uintmax_t) << '\n';
BOOST_TEST(sizeof(boost::uintmax_t) >= 8);
initial_tests();
predicate_and_status_tests();
exception_tests();
platform_specific_tests();
create_directory_tests();
current_directory_tests();
space_tests();
// create a directory tree that can be used by subsequent tests
//
// dir
// d1
// d1f1 // an empty file
// f0 // an empty file
// f1 // a file containing "file f1"
//
create_tree();
status_of_nonexistent_tests();
status_error_reporting_tests();
directory_iterator_tests();
create_directories_tests(); // must run AFTER directory_iterator_tests
bad_create_directory_path = f1;
BOOST_TEST(CHECK_EXCEPTION(bad_create_directory, EEXIST));
fs::file_status stat = fs::status(f1);
BOOST_TEST(fs::status_known(stat));
BOOST_TEST(fs::exists(stat));
BOOST_TEST(!fs::is_directory(stat));
BOOST_TEST(fs::is_regular_file(stat));
BOOST_TEST(!fs::is_other(stat));
BOOST_TEST(!fs::is_symlink(stat));
equivalent_tests(f1);
create_hard_link_tests();
create_symlink_tests();
resize_file_tests();
absolute_tests();
copy_file_tests(f1, d1);
if (create_symlink_ok) // only if symlinks supported
{
symlink_status_tests();
copy_symlink_tests(f1, d1);
}
rename_tests();
remove_tests(dir);
if (create_symlink_ok) // only if symlinks supported
remove_symlink_tests();
write_time_tests(dir);
std::cout << "testing complete" << std::endl;
// post-test cleanup
if (cleanup)
{
std::cout << "post-test removal of " << dir << std::endl;
BOOST_TEST(fs::remove_all(dir) != 0);
// above was added just to simplify testing, but it ended up detecting
// a bug (failure to close an internal search handle).
std::cout << "post-test removal complete" << std::endl;
BOOST_TEST(!fs::exists(dir));
BOOST_TEST(fs::remove_all(dir) == 0);
}
std::cout << "returning from main()" << std::endl;
return ::boost::report_errors();
} // main