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