Index: test/std/experimental/filesystem/fs.op.funcs/fs.op.last_write_time/last_write_time.pass.cpp =================================================================== --- test/std/experimental/filesystem/fs.op.funcs/fs.op.last_write_time/last_write_time.pass.cpp +++ test/std/experimental/filesystem/fs.op.funcs/fs.op.last_write_time/last_write_time.pass.cpp @@ -72,13 +72,72 @@ return {st.st_atime, st.st_mtime}; } -inline bool TimeIsRepresentableAsTimeT(file_time_type tp) { +namespace { +bool TestSupportsNegativeTimes() { + using namespace std::chrono; + std::error_code ec; + std::time_t old_write_time, new_write_time; + { // WARNING: Do not assert in this scope. + scoped_test_env env; + const path file = env.create_file("file", 42); + old_write_time = LastWriteTime(file); + std::error_code ec; + file_time_type tp(seconds(-5)); + fs::last_write_time(file, tp, ec); + new_write_time = LastWriteTime(file); + } + if (ec) { + assert(old_write_time == new_write_time); + return false; + } else { + assert(new_write_time <= -5); + return true; + } +} + +bool TestSupportsMaxTime() { using namespace std::chrono; using Lim = std::numeric_limits; - auto sec = duration_cast(tp.time_since_epoch()).count(); - return (sec >= Lim::min() && sec <= Lim::max()); + auto max_sec = duration_cast(file_time_type::max().time_since_epoch()).count(); + if (max_sec > Lim::max()) return false; + std::error_code ec; + std::time_t old_write_time, new_write_time; + { // WARNING: Do not assert in this scope. + scoped_test_env env; + const path file = env.create_file("file", 42); + old_write_time = LastWriteTime(file); + file_time_type tp = file_time_type::max(); + fs::last_write_time(file, tp, ec); + new_write_time = LastWriteTime(file); + } + if (ec) { + assert(new_write_time == old_write_time); + return false; + } else { + assert(new_write_time > old_write_time); + return true; + } } +static const bool SupportsNegativeTimes = TestSupportsNegativeTimes(); +static const bool SupportsMaxTime = TestSupportsMaxTime(); + +} // end namespace + +// Check if a time point is representable on a given filesystem. Check that: +// (A) 'tp' is representable as a time_t +// (B) 'tp' is non-negative or the filesystem supports negative times. +// (C) 'tp' is not 'file_time_type::max()' or the filesystem supports the max +// value. +inline bool TimeIsRepresentableByFilesystem(file_time_type tp) { + using namespace std::chrono; + using Lim = std::numeric_limits; + auto sec = duration_cast(tp.time_since_epoch()).count(); + if (sec < Lim::min() || sec > Lim::max()) return false; + else if (sec < 0 && !SupportsNegativeTimes) return false; + else if (tp == file_time_type::max() && !SupportsMaxTime) return false; + return true; +} TEST_SUITE(exists_test_suite) @@ -274,7 +333,7 @@ last_write_time(p, new_time, ec); file_time_type tt = last_write_time(p); - if (!TimeIsRepresentableAsTimeT(new_time)) { + if (!TimeIsRepresentableByFilesystem(new_time)) { TEST_CHECK(ec); TEST_CHECK(ec != GetTestEC()); TEST_CHECK(tt == last_time); @@ -293,7 +352,7 @@ last_write_time(p, new_time, ec); tt = last_write_time(p); - if (!TimeIsRepresentableAsTimeT(new_time)) { + if (!TimeIsRepresentableByFilesystem(new_time)) { TEST_CHECK(ec); TEST_CHECK(ec != GetTestEC()); TEST_CHECK(tt == last_time); @@ -323,7 +382,7 @@ last_write_time(p, new_time, ec); file_time_type tt = last_write_time(p); - if (!TimeIsRepresentableAsTimeT(new_time)) { + if (!TimeIsRepresentableByFilesystem(new_time)) { TEST_CHECK(ec); TEST_CHECK(ec != GetTestEC()); TEST_CHECK(tt == last_time);