From df0304d8f436e674267d33377918b059ae0ad31e Mon Sep 17 00:00:00 2001 From: Aleksandar Janicijevic Date: Sun, 18 Apr 2021 16:36:43 -0400 Subject: [PATCH] touch: added unit test for test -m -t fail (#2089) --- tests/by-util/test_touch.rs | 55 +++++++++++++++++++++++++++++++++++-- 1 file changed, 53 insertions(+), 2 deletions(-) diff --git a/tests/by-util/test_touch.rs b/tests/by-util/test_touch.rs index 9f2c079b0..40fbb8aa9 100644 --- a/tests/by-util/test_touch.rs +++ b/tests/by-util/test_touch.rs @@ -367,7 +367,58 @@ fn test_touch_mtime_dst_succeeds() { let target_time = str_to_filetime("%Y%m%d%H%M", "202103140300"); let (_, mtime) = get_file_times(&at, file); - eprintln!("target_time: {:?}", target_time); - eprintln!("mtime: {:?}", mtime); assert!(target_time == mtime); } + +// is_dst_switch_hour returns true if timespec ts is just before the switch +// to Daylight Saving Time. +// For example, in EST (UTC-5), Timespec { sec: 1583647200, nsec: 0 } +// for March 8 2020 01:00:00 AM +// is just before the switch because on that day clock jumps by 1 hour, +// so 1 minute after 01:59:00 is 03:00:00. +fn is_dst_switch_hour(ts: time::Timespec) -> bool { + let ts_after = ts + time::Duration::hours(1); + let tm = time::at(ts); + let tm_after = time::at(ts_after); + tm_after.tm_hour == tm.tm_hour + 2 +} + +// get_dstswitch_hour returns date string for which touch -m -t fails. +// For example, in EST (UTC-5), that will be "202003080200" so +// touch -m -t 202003080200 somefile +// fails (that date/time does not exist). +// In other locales it will be a different date/time, and in some locales +// it doesn't exist at all, in which case this function will return None. +fn get_dstswitch_hour() -> Option { + let now = time::now(); + // Start from January 1, 2020, 00:00. + let mut tm = time::strptime("20200101-0000", "%Y%m%d-%H%M").unwrap(); + tm.tm_isdst = -1; + tm.tm_utcoff = now.tm_utcoff; + let mut ts = tm.to_timespec(); + // Loop through all hours in year 2020 until we find the hour just + // before the switch to DST. + for _i in 0..(366 * 24) { + if is_dst_switch_hour(ts) { + let mut tm = time::at(ts); + tm.tm_hour = tm.tm_hour + 1; + let s = time::strftime("%Y%m%d%H%M", &tm).unwrap().to_string(); + return Some(s); + } + ts = ts + time::Duration::hours(1); + } + None +} + +#[test] +fn test_touch_mtime_dst_fails() { + let (_at, mut ucmd) = at_and_ucmd!(); + let file = "test_touch_set_mtime_dst_fails"; + + match get_dstswitch_hour() { + Some(s) => { + ucmd.args(&["-m", "-t", &s, file]).fails(); + } + None => (), + } +}