]> git.ipfire.org Git - thirdparty/gcc.git/blame - libstdc++-v3/testsuite/experimental/filesystem/operations/last_write_time.cc
Update copyright years.
[thirdparty/gcc.git] / libstdc++-v3 / testsuite / experimental / filesystem / operations / last_write_time.cc
CommitLineData
83ffe9cd 1// Copyright (C) 2016-2023 Free Software Foundation, Inc.
fd5effb1
JW
2//
3// This file is part of the GNU ISO C++ Library. This library is free
4// software; you can redistribute it and/or modify it under the
5// terms of the GNU General Public License as published by the
6// Free Software Foundation; either version 3, or (at your option)
7// any later version.
8
9// This library is distributed in the hope that it will be useful,
10// but WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12// GNU General Public License for more details.
13
14// You should have received a copy of the GNU General Public License along
15// with this library; see the file COPYING3. If not see
16// <http://www.gnu.org/licenses/>.
17
ef0e80d2 18// { dg-options "-DUSE_FILESYSTEM_TS -lstdc++fs" }
fd5effb1
JW
19// { dg-do run { target c++11 } }
20// { dg-require-filesystem-ts "" }
f01cf5ea 21// { dg-require-target-fs-lwt "" }
fd5effb1
JW
22
23// 15.25 Permissions [fs.op.last_write_time]
24
25#include <experimental/filesystem>
a51a546c 26#include <limits>
fd5effb1
JW
27#include <testsuite_fs.h>
28#include <testsuite_hooks.h>
29
30#ifdef _GLIBCXX_HAVE_FCNTL_H
31# include <fcntl.h>
32#endif
33#if _GLIBCXX_HAVE_UTIME_H
34# include <utime.h>
35#endif
a51a546c 36#include <stdio.h>
fd5effb1 37
69af1c04
JW
38using time_type = std::experimental::filesystem::file_time_type;
39
a51a546c
JW
40namespace chrono = std::chrono;
41
fd5effb1
JW
42void
43test01()
44{
7195dfe9
JW
45 // read times
46
fd5effb1
JW
47 auto p = __gnu_test::nonexistent_path();
48 std::error_code ec;
49 time_type mtime = last_write_time(p, ec);
50 VERIFY( ec );
51 VERIFY( ec == std::make_error_code(std::errc::no_such_file_or_directory) );
52#if __cpp_exceptions
53 bool caught = false;
54 try {
55 mtime = last_write_time(p);
56 } catch (std::system_error const& e) {
57 caught = true;
58 ec = e.code();
59 }
60 VERIFY( caught );
61 VERIFY( ec );
62 VERIFY( ec == std::make_error_code(std::errc::no_such_file_or_directory) );
63#endif
64
65 __gnu_test::scoped_file file(p);
66 VERIFY( exists(p) );
67 mtime = last_write_time(p, ec);
68 VERIFY( !ec );
69 VERIFY( mtime <= time_type::clock::now() );
70 VERIFY( mtime == last_write_time(p) );
71
72 auto end_of_time = time_type::duration::max();
73 auto last_second
a51a546c 74 = chrono::duration_cast<chrono::seconds>(end_of_time).count();
fd5effb1 75 if (last_second > std::numeric_limits<std::time_t>::max())
a51a546c
JW
76 {
77 puts("Range of time_t is smaller than range of chrono::file_clock, "
78 "can't test for overflow on this target.");
79 return;
80 }
fd5effb1 81
a51a546c 82 // Set mtime to a date past the maximum possible file_time_type:
fd5effb1
JW
83#if _GLIBCXX_USE_UTIMENSAT
84 struct ::timespec ts[2];
85 ts[0].tv_sec = 0;
86 ts[0].tv_nsec = UTIME_NOW;
87 ts[1].tv_sec = std::numeric_limits<std::time_t>::max() - 1;
88 ts[1].tv_nsec = 0;
89 VERIFY( !::utimensat(AT_FDCWD, p.c_str(), ts, 0) );
90#elif _GLIBCXX_HAVE_UTIME_H
91 ::utimbuf times;
92 times.modtime = std::numeric_limits<std::time_t>::max() - 1;
93 times.actime = std::numeric_limits<std::time_t>::max() - 1;
9534a5e6 94 VERIFY( !::utime(p.string().c_str(), &times) );
fd5effb1 95#else
a51a546c 96 puts("No utimensat or utime, giving up.");
fd5effb1
JW
97 return;
98#endif
99
a51a546c 100 // Try to read back the impossibly-large mtime:
fd5effb1 101 mtime = last_write_time(p, ec);
a51a546c
JW
102 // Some filesystems (e.g. XFS) silently truncate distant times to
103 // the time_t epochalypse, Jan 19 2038, so we won't get an error when
104 // reading it back:
105 if (ec)
106 {
107 VERIFY( ec == std::make_error_code(std::errc::value_too_large) );
108 VERIFY( mtime == time_type::min() );
109 }
110 else
111 puts("No overflow error, filesystem may not support 64-bit time_t.");
fd5effb1
JW
112
113#if __cpp_exceptions
a51a546c 114 // Once more, with exceptions:
fd5effb1 115 try {
a51a546c
JW
116 auto mtime2 = last_write_time(p);
117 // If it didn't throw, expect to have read back the same value:
118 VERIFY( mtime2 == mtime );
119 } catch (std::experimental::filesystem::filesystem_error const& e) {
120 // If it did throw, expect the error_code to be the same:
121 VERIFY( e.code() == ec );
122 VERIFY( e.path1() == p );
fd5effb1 123 }
fd5effb1
JW
124#endif
125}
126
69af1c04
JW
127bool approx_equal(time_type file_time, time_type expected)
128{
129 auto delta = expected - file_time;
130 if (delta < delta.zero())
131 delta = -delta;
a51a546c 132 return delta < chrono::seconds(1);
69af1c04
JW
133}
134
7195dfe9
JW
135void
136test02()
137{
138 // write times
139
a51a546c 140 const std::error_code bad_ec = make_error_code(std::errc::invalid_argument);
7195dfe9
JW
141 __gnu_test::scoped_file f;
142 std::error_code ec;
143 time_type time;
144
a51a546c 145 ec = bad_ec;
7195dfe9
JW
146 time = last_write_time(f.path);
147 last_write_time(f.path, time, ec);
148 VERIFY( !ec );
69af1c04 149 VERIFY( approx_equal(last_write_time(f.path), time) );
7195dfe9 150
a51a546c
JW
151 ec = bad_ec;
152 time -= chrono::milliseconds(1000 * 60 * 10 + 15);
7195dfe9
JW
153 last_write_time(f.path, time, ec);
154 VERIFY( !ec );
69af1c04 155 VERIFY( approx_equal(last_write_time(f.path), time) );
7195dfe9 156
a51a546c
JW
157 ec = bad_ec;
158 time += chrono::milliseconds(1000 * 60 * 20 + 15);
7195dfe9
JW
159 last_write_time(f.path, time, ec);
160 VERIFY( !ec );
69af1c04 161 VERIFY( approx_equal(last_write_time(f.path), time) );
7195dfe9 162
a51a546c 163 ec = bad_ec;
7195dfe9
JW
164 time = time_type();
165 last_write_time(f.path, time, ec);
166 VERIFY( !ec );
69af1c04 167 VERIFY( approx_equal(last_write_time(f.path), time) );
7195dfe9 168
a51a546c
JW
169 ec = bad_ec;
170 time -= chrono::milliseconds(1000 * 60 * 10 + 15);
7195dfe9
JW
171 last_write_time(f.path, time, ec);
172 VERIFY( !ec );
69af1c04 173 VERIFY( approx_equal(last_write_time(f.path), time) );
7195dfe9
JW
174}
175
fd5effb1
JW
176int
177main()
178{
179 test01();
7195dfe9 180 test02();
fd5effb1 181}