Skip to content

Commit 0ab3b77

Browse files
Jonas HahnfeldJonas Hahnfeld
Jonas Hahnfeld
authored and
Jonas Hahnfeld
committedJan 14, 2017
Fix last_write_time tests for filesystems that don't support negative and very large times
Seems to be the case for NFS. Original patch by Eric Fiselier! Differential Revision: https://reviews.llvm.org/D22452 llvm-svn: 292013
1 parent 117c4af commit 0ab3b77

File tree

1 file changed

+63
-29
lines changed

1 file changed

+63
-29
lines changed
 

‎libcxx/test/std/experimental/filesystem/fs.op.funcs/fs.op.last_write_time/last_write_time.pass.cpp

+63-29
Original file line numberDiff line numberDiff line change
@@ -72,13 +72,60 @@ std::pair<std::time_t, std::time_t> GetSymlinkTimes(path const& p) {
7272
return {st.st_atime, st.st_mtime};
7373
}
7474

75-
inline bool TimeIsRepresentableAsTimeT(file_time_type tp) {
75+
namespace {
76+
bool TestSupportsNegativeTimes() {
77+
using namespace std::chrono;
78+
std::error_code ec;
79+
std::time_t old_write_time, new_write_time;
80+
{ // WARNING: Do not assert in this scope.
81+
scoped_test_env env;
82+
const path file = env.create_file("file", 42);
83+
old_write_time = LastWriteTime(file);
84+
file_time_type tp(seconds(-5));
85+
fs::last_write_time(file, tp, ec);
86+
new_write_time = LastWriteTime(file);
87+
}
88+
return !ec && new_write_time <= -5;
89+
}
90+
91+
bool TestSupportsMaxTime() {
7692
using namespace std::chrono;
7793
using Lim = std::numeric_limits<std::time_t>;
78-
auto sec = duration_cast<seconds>(tp.time_since_epoch()).count();
79-
return (sec >= Lim::min() && sec <= Lim::max());
94+
auto max_sec = duration_cast<seconds>(file_time_type::max().time_since_epoch()).count();
95+
if (max_sec > Lim::max()) return false;
96+
std::error_code ec;
97+
std::time_t old_write_time, new_write_time;
98+
{ // WARNING: Do not assert in this scope.
99+
scoped_test_env env;
100+
const path file = env.create_file("file", 42);
101+
old_write_time = LastWriteTime(file);
102+
file_time_type tp = file_time_type::max();
103+
fs::last_write_time(file, tp, ec);
104+
new_write_time = LastWriteTime(file);
105+
}
106+
return !ec && new_write_time > max_sec - 1;
80107
}
81108

109+
static const bool SupportsNegativeTimes = TestSupportsNegativeTimes();
110+
static const bool SupportsMaxTime = TestSupportsMaxTime();
111+
112+
} // end namespace
113+
114+
// Check if a time point is representable on a given filesystem. Check that:
115+
// (A) 'tp' is representable as a time_t
116+
// (B) 'tp' is non-negative or the filesystem supports negative times.
117+
// (C) 'tp' is not 'file_time_type::max()' or the filesystem supports the max
118+
// value.
119+
inline bool TimeIsRepresentableByFilesystem(file_time_type tp) {
120+
using namespace std::chrono;
121+
using Lim = std::numeric_limits<std::time_t>;
122+
auto sec = duration_cast<seconds>(tp.time_since_epoch()).count();
123+
auto microsec = duration_cast<microseconds>(tp.time_since_epoch()).count();
124+
if (sec < Lim::min() || sec > Lim::max()) return false;
125+
else if (microsec < 0 && !SupportsNegativeTimes) return false;
126+
else if (tp == file_time_type::max() && !SupportsMaxTime) return false;
127+
return true;
128+
}
82129

83130
TEST_SUITE(exists_test_suite)
84131

@@ -214,15 +261,17 @@ TEST_CASE(set_last_write_time_dynamic_env_test)
214261

215262
file_time_type got_time = last_write_time(TC.p);
216263

217-
TEST_CHECK(got_time != old_time);
218-
if (TC.new_time < epoch_time) {
219-
TEST_CHECK(got_time <= TC.new_time);
220-
TEST_CHECK(got_time > TC.new_time - Sec(1));
221-
} else {
222-
TEST_CHECK(got_time <= TC.new_time + Sec(1));
223-
TEST_CHECK(got_time >= TC.new_time - Sec(1));
264+
if (TimeIsRepresentableByFilesystem(TC.new_time)) {
265+
TEST_CHECK(got_time != old_time);
266+
if (TC.new_time < epoch_time) {
267+
TEST_CHECK(got_time <= TC.new_time);
268+
TEST_CHECK(got_time > TC.new_time - Sec(1));
269+
} else {
270+
TEST_CHECK(got_time <= TC.new_time + Sec(1));
271+
TEST_CHECK(got_time >= TC.new_time - Sec(1));
272+
}
273+
TEST_CHECK(LastAccessTime(TC.p) == old_times.first);
224274
}
225-
TEST_CHECK(LastAccessTime(TC.p) == old_times.first);
226275
}
227276
}
228277

@@ -269,36 +318,26 @@ TEST_CASE(test_write_min_time)
269318
const path p = env.create_file("file", 42);
270319

271320
std::error_code ec = GetTestEC();
272-
file_time_type last_time = last_write_time(p);
273321
file_time_type new_time = file_time_type::min();
274322

275323
last_write_time(p, new_time, ec);
276324
file_time_type tt = last_write_time(p);
277325

278-
if (!TimeIsRepresentableAsTimeT(new_time)) {
279-
TEST_CHECK(ec);
280-
TEST_CHECK(ec != GetTestEC());
281-
TEST_CHECK(tt == last_time);
282-
} else {
326+
if (TimeIsRepresentableByFilesystem(new_time)) {
283327
TEST_CHECK(!ec);
284328
TEST_CHECK(tt >= new_time);
285329
TEST_CHECK(tt < new_time + Sec(1));
286330
}
287331

288332
ec = GetTestEC();
289333
last_write_time(p, Clock::now());
290-
last_time = last_write_time(p);
291334

292335
new_time = file_time_type::min() + MicroSec(1);
293336

294337
last_write_time(p, new_time, ec);
295338
tt = last_write_time(p);
296339

297-
if (!TimeIsRepresentableAsTimeT(new_time)) {
298-
TEST_CHECK(ec);
299-
TEST_CHECK(ec != GetTestEC());
300-
TEST_CHECK(tt == last_time);
301-
} else {
340+
if (TimeIsRepresentableByFilesystem(new_time)) {
302341
TEST_CHECK(!ec);
303342
TEST_CHECK(tt >= new_time);
304343
TEST_CHECK(tt < new_time + Sec(1));
@@ -317,18 +356,13 @@ TEST_CASE(test_write_min_max_time)
317356
const path p = env.create_file("file", 42);
318357

319358
std::error_code ec = GetTestEC();
320-
file_time_type last_time = last_write_time(p);
321359
file_time_type new_time = file_time_type::max();
322360

323361
ec = GetTestEC();
324362
last_write_time(p, new_time, ec);
325363
file_time_type tt = last_write_time(p);
326364

327-
if (!TimeIsRepresentableAsTimeT(new_time)) {
328-
TEST_CHECK(ec);
329-
TEST_CHECK(ec != GetTestEC());
330-
TEST_CHECK(tt == last_time);
331-
} else {
365+
if (TimeIsRepresentableByFilesystem(new_time)) {
332366
TEST_CHECK(!ec);
333367
TEST_CHECK(tt > new_time - Sec(1));
334368
TEST_CHECK(tt <= new_time);

0 commit comments

Comments
 (0)
Please sign in to comment.