#![allow(clippy::unwrap_used, clippy::expect_used)]
use std::process::Command;
fn oracle_available() -> bool {
Command::new("time-decode")
.arg("--version")
.output()
.is_ok_and(|o| o.status.success())
}
fn oracle(flag: &str, value: &str) -> Option<String> {
let out = Command::new("time-decode")
.arg(flag)
.arg(value)
.output()
.ok()?;
let text = String::from_utf8_lossy(&out.stdout);
let line = text.lines().find(|l| l.contains(": "))?;
let after = line.split_once(": ")?.1.trim();
if after.len() < 19 {
return None;
}
Some(after[..19].to_string())
}
fn civil(rfc3339: &str) -> String {
rfc3339.replacen('T', " ", 1).chars().take(19).collect()
}
fn agree(label: &str, tg_rfc3339: &str, flag: &str, value: &str) {
let want = civil(tg_rfc3339);
let got = oracle(flag, value).unwrap_or_else(|| panic!("{label}: no oracle output"));
assert_eq!(got, want, "{label}: oracle {got:?} vs timeglyph {want:?}");
}
fn agree_float(label: &str, id: &str, flag: &str, value: &str) {
let v: f64 = value.parse().unwrap();
agree(label, &render_float(id, v), flag, value);
}
fn render_int(id: &str, value: i64) -> String {
timeglyph::format(id)
.unwrap()
.decode_int(value)
.unwrap()
.to_rfc3339()
.unwrap()
}
fn render_float(id: &str, value: f64) -> String {
timeglyph::format(id)
.unwrap()
.decode_float(value)
.unwrap()
.to_rfc3339()
.unwrap()
}
#[test]
fn differential_battery_posix_family() {
if !oracle_available() {
eprintln!("skipping: time-decode oracle not on PATH (see docs/validation.md)");
return;
}
agree(
"unix",
&render_int("unix", 1_746_371_930),
"--unixsec",
"1746371930",
);
agree(
"unix_ms",
&render_int("unix_ms", 1_746_371_930_064),
"--unixmilli",
"1746371930064",
);
agree(
"unix_us",
&render_int("unix_us", 1_746_371_930_064_939),
"--prtime",
"1746371930064939",
);
agree(
"filetime",
&render_int("filetime", 133_908_455_300_649_390),
"--active",
"133908455300649390",
);
agree(
"webkit",
&render_int("webkit", 13_390_845_530_064_940),
"--chrome",
"13390845530064940",
);
agree(
"hfsplus",
&render_int("hfsplus", 3_829_216_730),
"--hfsdec",
"3829216730",
);
agree(
"hfsplus-max",
&render_int("hfsplus", 4_294_967_295),
"--hfsdec",
"4294967295",
);
agree(
"dotnet_ticks",
&render_int("dotnet_ticks", 638_819_687_300_649_472),
"--dotnet",
"638819687300649472",
);
agree_float("cocoa_float", "cocoa_float", "--mac", "768064730.064939");
agree_float(
"sqlite_julian",
"sqlite_julian",
"--juliandec",
"2460800.1380787035",
);
agree_float("ole", "ole", "--oleauto", "45781.638079455312");
agree(
"discord",
&render_int("discord", 1_102_608_904_745_127_937),
"--discord",
"1102608904745127937",
);
agree(
"snowflake",
&render_int("snowflake", 1_189_581_422_684_274_688),
"--twitter",
"1189581422684274688",
);
agree("fat", &render_int("fat", 0x5AA4_7A59), "--fat", "a45a597a");
}
#[cfg(feature = "leap")]
#[test]
fn differential_battery_leap_family() {
use timeglyph::leap;
if !oracle_available() {
eprintln!("skipping: time-decode oracle not on PATH (see docs/validation.md)");
return;
}
agree(
"gps",
&leap::from_gps_seconds(1_430_407_111.0).utc_rfc3339,
"--gps",
"1430407111",
);
agree(
"ntp",
&leap::from_ntp_seconds(3_981_841_662).unwrap().utc_rfc3339,
"--ntp",
"3981841662.020607",
);
let tai_seconds: u64 = 1_599_755_800;
agree(
"tai64",
&leap::from_tai64((1u64 << 62) + tai_seconds)
.unwrap()
.utc_rfc3339,
"--tai",
"1599755800",
);
}