1b8a62b91Sopenharmony_ci/// Test that `Timespec` and `Secs` support a 64-bit number of seconds,
2b8a62b91Sopenharmony_ci/// avoiding the y2038 bug.
3b8a62b91Sopenharmony_ci///
4b8a62b91Sopenharmony_ci/// The Rust Musl target and libc crate are currently using Musl 1.1. It is
5b8a62b91Sopenharmony_ci/// expected to update to Musl 1.2 at some point, at which point it'll gain a
6b8a62b91Sopenharmony_ci/// 64-bit `time_t`.
7b8a62b91Sopenharmony_ci///
8b8a62b91Sopenharmony_ci/// 32-bit Android is [not y2038 compatible]. In theory we could use
9b8a62b91Sopenharmony_ci/// `libc::syscall` and call the new syscalls ourselves, however that doesn't
10b8a62b91Sopenharmony_ci/// seem worth the effort on a platform that will likely never support add
11b8a62b91Sopenharmony_ci/// such support itself.
12b8a62b91Sopenharmony_ci///
13b8a62b91Sopenharmony_ci/// [not y2038 compatible]: https://android.googlesource.com/platform/bionic/+/refs/heads/master/docs/32-bit-abi.md#is-32_bit-on-lp32-y2038
14b8a62b91Sopenharmony_ci#[cfg(not(all(target_env = "musl", target_pointer_width = "32")))]
15b8a62b91Sopenharmony_ci#[cfg(not(all(target_os = "android", target_pointer_width = "32")))]
16b8a62b91Sopenharmony_ci#[cfg(not(all(target_os = "emscripten", target_pointer_width = "32")))]
17b8a62b91Sopenharmony_ci#[cfg(not(all(target_os = "linux", target_arch = "sparc")))]
18b8a62b91Sopenharmony_ci#[test]
19b8a62b91Sopenharmony_cifn test_y2038() {
20b8a62b91Sopenharmony_ci    use rustix::time::{Secs, Timespec};
21b8a62b91Sopenharmony_ci
22b8a62b91Sopenharmony_ci    let tv_sec: i64 = 0;
23b8a62b91Sopenharmony_ci    let _ = Timespec { tv_sec, tv_nsec: 0 };
24b8a62b91Sopenharmony_ci    let _: Secs = tv_sec;
25b8a62b91Sopenharmony_ci
26b8a62b91Sopenharmony_ci    #[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))]
27b8a62b91Sopenharmony_ci    {
28b8a62b91Sopenharmony_ci        use rustix::time::Itimerspec;
29b8a62b91Sopenharmony_ci
30b8a62b91Sopenharmony_ci        let _ = Itimerspec {
31b8a62b91Sopenharmony_ci            it_interval: Timespec { tv_sec, tv_nsec: 0 },
32b8a62b91Sopenharmony_ci            it_value: Timespec { tv_sec, tv_nsec: 0 },
33b8a62b91Sopenharmony_ci        };
34b8a62b91Sopenharmony_ci    }
35b8a62b91Sopenharmony_ci}
36b8a62b91Sopenharmony_ci
37b8a62b91Sopenharmony_ci#[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))]
38b8a62b91Sopenharmony_ci#[test]
39b8a62b91Sopenharmony_cifn test_y2038_with_timerfd() {
40b8a62b91Sopenharmony_ci    use rustix::time::{
41b8a62b91Sopenharmony_ci        timerfd_create, timerfd_gettime, timerfd_settime, Itimerspec, TimerfdClockId, TimerfdFlags,
42b8a62b91Sopenharmony_ci        TimerfdTimerFlags, Timespec,
43b8a62b91Sopenharmony_ci    };
44b8a62b91Sopenharmony_ci
45b8a62b91Sopenharmony_ci    let fd = timerfd_create(TimerfdClockId::Monotonic, TimerfdFlags::CLOEXEC).unwrap();
46b8a62b91Sopenharmony_ci
47b8a62b91Sopenharmony_ci    let set = Itimerspec {
48b8a62b91Sopenharmony_ci        it_interval: Timespec {
49b8a62b91Sopenharmony_ci            tv_sec: (1_u64 << 32) as _,
50b8a62b91Sopenharmony_ci            tv_nsec: 20,
51b8a62b91Sopenharmony_ci        },
52b8a62b91Sopenharmony_ci        it_value: Timespec {
53b8a62b91Sopenharmony_ci            tv_sec: (1_u64 << 32) as _,
54b8a62b91Sopenharmony_ci            tv_nsec: 21,
55b8a62b91Sopenharmony_ci        },
56b8a62b91Sopenharmony_ci    };
57b8a62b91Sopenharmony_ci    let _old: Itimerspec = match timerfd_settime(&fd, TimerfdTimerFlags::ABSTIME, &set) {
58b8a62b91Sopenharmony_ci        Ok(i) => i,
59b8a62b91Sopenharmony_ci
60b8a62b91Sopenharmony_ci        // On 32-bit and mips64 platforms, accept `EOVERFLOW`, meaning that
61b8a62b91Sopenharmony_ci        // y2038 support in `timerfd` APIs is not available on this platform
62b8a62b91Sopenharmony_ci        // or this version of the platform.
63b8a62b91Sopenharmony_ci        #[cfg(any(target_pointer_width = "32", target_arch = "mips64"))]
64b8a62b91Sopenharmony_ci        Err(rustix::io::Errno::OVERFLOW) => return,
65b8a62b91Sopenharmony_ci
66b8a62b91Sopenharmony_ci        Err(err) => panic!("unexpected error: {:?}", err),
67b8a62b91Sopenharmony_ci    };
68b8a62b91Sopenharmony_ci
69b8a62b91Sopenharmony_ci    let new = timerfd_gettime(&fd).unwrap();
70b8a62b91Sopenharmony_ci
71b8a62b91Sopenharmony_ci    // The timer counts down.
72b8a62b91Sopenharmony_ci    assert_eq!(set.it_interval.tv_sec, new.it_interval.tv_sec);
73b8a62b91Sopenharmony_ci    assert_eq!(set.it_interval.tv_nsec, new.it_interval.tv_nsec);
74b8a62b91Sopenharmony_ci    assert!(new.it_value.tv_sec <= set.it_value.tv_sec);
75b8a62b91Sopenharmony_ci    assert!(
76b8a62b91Sopenharmony_ci        new.it_value.tv_nsec < set.it_value.tv_nsec || new.it_value.tv_sec < set.it_value.tv_sec
77b8a62b91Sopenharmony_ci    );
78b8a62b91Sopenharmony_ci}
79