| 
 | 1 | +use super::*;  | 
 | 2 | + | 
 | 3 | +type ChronoUtcDateTime = chrono::DateTime<chrono::Utc>;  | 
 | 4 | + | 
 | 5 | +#[test]  | 
 | 6 | +fn timestamp_constructors() {  | 
 | 7 | +    assert!(TimestampUs::now() > TimestampUs::UNIX_EPOCH);  | 
 | 8 | +    assert!(TimestampUs::now() < TimestampUs::MAX);  | 
 | 9 | + | 
 | 10 | +    assert_eq!(TimestampUs::from_micros(12345).as_micros(), 12345);  | 
 | 11 | +    assert_eq!(TimestampUs::from_micros(12345).as_nanos(), 12345000);  | 
 | 12 | +    assert_eq!(TimestampUs::from_micros(12345).as_millis(), 12);  | 
 | 13 | +    assert_eq!(TimestampUs::from_micros(12345).as_secs(), 0);  | 
 | 14 | + | 
 | 15 | +    assert_eq!(TimestampUs::from_micros(123456789).as_millis(), 123456);  | 
 | 16 | +    assert_eq!(TimestampUs::from_micros(123456789).as_secs(), 123);  | 
 | 17 | + | 
 | 18 | +    assert_eq!(  | 
 | 19 | +        TimestampUs::from_nanos(1234567890).unwrap().as_nanos(),  | 
 | 20 | +        1234567000  | 
 | 21 | +    );  | 
 | 22 | +    assert_eq!(  | 
 | 23 | +        TimestampUs::from_nanos(1234567890).unwrap().as_nanos_i128(),  | 
 | 24 | +        1234567000  | 
 | 25 | +    );  | 
 | 26 | + | 
 | 27 | +    assert_eq!(TimestampUs::from_millis(25).unwrap().as_millis(), 25);  | 
 | 28 | +    assert_eq!(TimestampUs::from_millis(25).unwrap().as_micros(), 25000);  | 
 | 29 | + | 
 | 30 | +    assert_eq!(TimestampUs::from_secs(25).unwrap().as_secs(), 25);  | 
 | 31 | +    assert_eq!(TimestampUs::from_secs(25).unwrap().as_millis(), 25000);  | 
 | 32 | +    assert_eq!(TimestampUs::from_secs(25).unwrap().as_micros(), 25000000);  | 
 | 33 | + | 
 | 34 | +    TimestampUs::from_nanos(u128::from(u64::MAX) * 1000 + 5000).unwrap_err();  | 
 | 35 | +    TimestampUs::from_millis(5_000_000_000_000_000_000).unwrap_err();  | 
 | 36 | +    TimestampUs::from_secs(5_000_000_000_000_000).unwrap_err();  | 
 | 37 | +}  | 
 | 38 | + | 
 | 39 | +#[test]  | 
 | 40 | +fn duration_constructors() {  | 
 | 41 | +    assert_eq!(DurationUs::from_micros(12345).as_micros(), 12345);  | 
 | 42 | +    assert_eq!(DurationUs::from_micros(12345).as_nanos(), 12345000);  | 
 | 43 | +    assert_eq!(DurationUs::from_micros(12345).as_millis(), 12);  | 
 | 44 | +    assert_eq!(DurationUs::from_micros(12345).as_secs(), 0);  | 
 | 45 | + | 
 | 46 | +    assert_eq!(DurationUs::from_micros(123456789).as_millis(), 123456);  | 
 | 47 | +    assert_eq!(DurationUs::from_micros(123456789).as_secs(), 123);  | 
 | 48 | + | 
 | 49 | +    assert_eq!(  | 
 | 50 | +        DurationUs::from_nanos(1234567890).unwrap().as_nanos(),  | 
 | 51 | +        1234567000  | 
 | 52 | +    );  | 
 | 53 | +    assert_eq!(  | 
 | 54 | +        DurationUs::from_nanos(1234567890).unwrap().as_nanos_i128(),  | 
 | 55 | +        1234567000  | 
 | 56 | +    );  | 
 | 57 | + | 
 | 58 | +    assert_eq!(DurationUs::from_millis(25).unwrap().as_millis(), 25);  | 
 | 59 | +    assert_eq!(DurationUs::from_millis(25).unwrap().as_micros(), 25000);  | 
 | 60 | + | 
 | 61 | +    assert_eq!(DurationUs::from_secs(25).unwrap().as_secs(), 25);  | 
 | 62 | +    assert_eq!(DurationUs::from_secs(25).unwrap().as_millis(), 25000);  | 
 | 63 | +    assert_eq!(DurationUs::from_secs(25).unwrap().as_micros(), 25000000);  | 
 | 64 | + | 
 | 65 | +    DurationUs::from_nanos(u128::from(u64::MAX) * 1000 + 5000).unwrap_err();  | 
 | 66 | +    DurationUs::from_millis(5_000_000_000_000_000_000).unwrap_err();  | 
 | 67 | +    DurationUs::from_secs(5_000_000_000_000_000).unwrap_err();  | 
 | 68 | + | 
 | 69 | +    assert_eq!(DurationUs::from_millis_u32(42).as_micros(), 42_000);  | 
 | 70 | +    assert_eq!(DurationUs::from_secs_u32(42).as_micros(), 42_000_000);  | 
 | 71 | +    assert_eq!(DurationUs::from_days_u16(42).as_micros(), 3_628_800_000_000);  | 
 | 72 | + | 
 | 73 | +    assert_eq!(  | 
 | 74 | +        DurationUs::from_millis_u32(u32::MAX).as_micros(),  | 
 | 75 | +        4_294_967_295_000  | 
 | 76 | +    );  | 
 | 77 | +    assert_eq!(  | 
 | 78 | +        DurationUs::from_secs_u32(u32::MAX).as_micros(),  | 
 | 79 | +        4_294_967_295_000_000  | 
 | 80 | +    );  | 
 | 81 | +    assert_eq!(  | 
 | 82 | +        DurationUs::from_days_u16(u16::MAX).as_micros(),  | 
 | 83 | +        5_662_224_000_000_000  | 
 | 84 | +    );  | 
 | 85 | +}  | 
 | 86 | + | 
 | 87 | +#[test]  | 
 | 88 | +#[allow(clippy::bool_assert_comparison)]  | 
 | 89 | +fn timestamp_ops() {  | 
 | 90 | +    assert_eq!(  | 
 | 91 | +        TimestampUs::from_micros(123)  | 
 | 92 | +            .checked_sub(DurationUs::from_micros(23))  | 
 | 93 | +            .unwrap(),  | 
 | 94 | +        TimestampUs::from_micros(100)  | 
 | 95 | +    );  | 
 | 96 | +    TimestampUs::from_micros(123)  | 
 | 97 | +        .checked_sub(DurationUs::from_micros(223))  | 
 | 98 | +        .unwrap_err();  | 
 | 99 | + | 
 | 100 | +    assert_eq!(  | 
 | 101 | +        TimestampUs::from_micros(123)  | 
 | 102 | +            .checked_add(DurationUs::from_micros(23))  | 
 | 103 | +            .unwrap(),  | 
 | 104 | +        TimestampUs::from_micros(146)  | 
 | 105 | +    );  | 
 | 106 | +    TimestampUs::from_micros(u64::MAX - 5)  | 
 | 107 | +        .checked_add(DurationUs::from_micros(223))  | 
 | 108 | +        .unwrap_err();  | 
 | 109 | + | 
 | 110 | +    assert_eq!(  | 
 | 111 | +        TimestampUs::from_micros(123)  | 
 | 112 | +            .duration_since(TimestampUs::from_micros(23))  | 
 | 113 | +            .unwrap(),  | 
 | 114 | +        DurationUs::from_micros(100)  | 
 | 115 | +    );  | 
 | 116 | +    TimestampUs::from_micros(123)  | 
 | 117 | +        .duration_since(TimestampUs::from_micros(223))  | 
 | 118 | +        .unwrap_err();  | 
 | 119 | + | 
 | 120 | +    assert_eq!(  | 
 | 121 | +        TimestampUs::from_micros(123).saturating_duration_since(TimestampUs::from_micros(23)),  | 
 | 122 | +        DurationUs::from_micros(100)  | 
 | 123 | +    );  | 
 | 124 | +    assert_eq!(  | 
 | 125 | +        TimestampUs::from_micros(123).saturating_duration_since(TimestampUs::from_micros(223)),  | 
 | 126 | +        DurationUs::ZERO  | 
 | 127 | +    );  | 
 | 128 | + | 
 | 129 | +    assert_eq!(  | 
 | 130 | +        TimestampUs::from_micros(123).saturating_add(DurationUs::from_micros(100)),  | 
 | 131 | +        TimestampUs::from_micros(223)  | 
 | 132 | +    );  | 
 | 133 | +    assert_eq!(  | 
 | 134 | +        TimestampUs::from_micros(u64::MAX - 100).saturating_add(DurationUs::from_micros(200)),  | 
 | 135 | +        TimestampUs::from_micros(u64::MAX)  | 
 | 136 | +    );  | 
 | 137 | +    assert_eq!(  | 
 | 138 | +        TimestampUs::from_micros(123).saturating_sub(DurationUs::from_micros(100)),  | 
 | 139 | +        TimestampUs::from_micros(23)  | 
 | 140 | +    );  | 
 | 141 | +    assert_eq!(  | 
 | 142 | +        TimestampUs::from_micros(123).saturating_sub(DurationUs::from_micros(200)),  | 
 | 143 | +        TimestampUs::from_micros(0)  | 
 | 144 | +    );  | 
 | 145 | +    assert_eq!(  | 
 | 146 | +        TimestampUs::from_micros(123).is_multiple_of(DurationUs::from_micros(200)),  | 
 | 147 | +        false  | 
 | 148 | +    );  | 
 | 149 | +    assert_eq!(  | 
 | 150 | +        TimestampUs::from_micros(400).is_multiple_of(DurationUs::from_micros(200)),  | 
 | 151 | +        true  | 
 | 152 | +    );  | 
 | 153 | +    assert_eq!(  | 
 | 154 | +        TimestampUs::from_micros(400).is_multiple_of(DurationUs::from_micros(0)),  | 
 | 155 | +        false  | 
 | 156 | +    );  | 
 | 157 | +    assert_eq!(  | 
 | 158 | +        TimestampUs::from_micros(400)  | 
 | 159 | +            .next_multiple_of(DurationUs::from_micros(200))  | 
 | 160 | +            .unwrap(),  | 
 | 161 | +        TimestampUs::from_micros(400)  | 
 | 162 | +    );  | 
 | 163 | +    assert_eq!(  | 
 | 164 | +        TimestampUs::from_micros(400)  | 
 | 165 | +            .previous_multiple_of(DurationUs::from_micros(200))  | 
 | 166 | +            .unwrap(),  | 
 | 167 | +        TimestampUs::from_micros(400)  | 
 | 168 | +    );  | 
 | 169 | +    assert_eq!(  | 
 | 170 | +        TimestampUs::from_micros(678)  | 
 | 171 | +            .next_multiple_of(DurationUs::from_micros(200))  | 
 | 172 | +            .unwrap(),  | 
 | 173 | +        TimestampUs::from_micros(800)  | 
 | 174 | +    );  | 
 | 175 | +    assert_eq!(  | 
 | 176 | +        TimestampUs::from_micros(678)  | 
 | 177 | +            .previous_multiple_of(DurationUs::from_micros(200))  | 
 | 178 | +            .unwrap(),  | 
 | 179 | +        TimestampUs::from_micros(600)  | 
 | 180 | +    );  | 
 | 181 | +    TimestampUs::from_micros(678)  | 
 | 182 | +        .previous_multiple_of(DurationUs::from_micros(0))  | 
 | 183 | +        .unwrap_err();  | 
 | 184 | +    TimestampUs::from_micros(678)  | 
 | 185 | +        .next_multiple_of(DurationUs::from_micros(0))  | 
 | 186 | +        .unwrap_err();  | 
 | 187 | +    TimestampUs::from_micros(u64::MAX - 5)  | 
 | 188 | +        .next_multiple_of(DurationUs::from_micros(1000))  | 
 | 189 | +        .unwrap_err();  | 
 | 190 | +}  | 
 | 191 | + | 
 | 192 | +#[test]  | 
 | 193 | +#[allow(clippy::bool_assert_comparison)]  | 
 | 194 | +fn duration_ops() {  | 
 | 195 | +    assert_eq!(  | 
 | 196 | +        DurationUs::from_micros(400).is_multiple_of(DurationUs::from_micros(200)),  | 
 | 197 | +        true  | 
 | 198 | +    );  | 
 | 199 | +    assert_eq!(  | 
 | 200 | +        DurationUs::from_micros(400).is_multiple_of(DurationUs::from_micros(300)),  | 
 | 201 | +        false  | 
 | 202 | +    );  | 
 | 203 | +    assert_eq!(  | 
 | 204 | +        DurationUs::from_micros(400).is_multiple_of(DurationUs::from_micros(0)),  | 
 | 205 | +        false  | 
 | 206 | +    );  | 
 | 207 | + | 
 | 208 | +    assert_eq!(  | 
 | 209 | +        DurationUs::from_micros(123)  | 
 | 210 | +            .checked_add(DurationUs::from_micros(100))  | 
 | 211 | +            .unwrap(),  | 
 | 212 | +        DurationUs::from_micros(223)  | 
 | 213 | +    );  | 
 | 214 | +    DurationUs::from_micros(u64::MAX - 5)  | 
 | 215 | +        .checked_add(DurationUs::from_micros(100))  | 
 | 216 | +        .unwrap_err();  | 
 | 217 | + | 
 | 218 | +    assert_eq!(  | 
 | 219 | +        DurationUs::from_micros(123)  | 
 | 220 | +            .checked_sub(DurationUs::from_micros(100))  | 
 | 221 | +            .unwrap(),  | 
 | 222 | +        DurationUs::from_micros(23)  | 
 | 223 | +    );  | 
 | 224 | +    DurationUs::from_micros(123)  | 
 | 225 | +        .checked_sub(DurationUs::from_micros(200))  | 
 | 226 | +        .unwrap_err();  | 
 | 227 | + | 
 | 228 | +    assert_eq!(  | 
 | 229 | +        DurationUs::from_micros(123).checked_mul(100).unwrap(),  | 
 | 230 | +        DurationUs::from_micros(12300)  | 
 | 231 | +    );  | 
 | 232 | +    DurationUs::from_micros(u64::MAX - 5)  | 
 | 233 | +        .checked_mul(100)  | 
 | 234 | +        .unwrap_err();  | 
 | 235 | +    assert_eq!(  | 
 | 236 | +        DurationUs::from_micros(123).checked_div(100).unwrap(),  | 
 | 237 | +        DurationUs::from_micros(1)  | 
 | 238 | +    );  | 
 | 239 | +    assert_eq!(  | 
 | 240 | +        DurationUs::from_micros(12300).checked_div(100).unwrap(),  | 
 | 241 | +        DurationUs::from_micros(123)  | 
 | 242 | +    );  | 
 | 243 | +    DurationUs::from_micros(123).checked_div(0).unwrap_err();  | 
 | 244 | + | 
 | 245 | +    assert!(DurationUs::ZERO.is_zero());  | 
 | 246 | +    assert!(!DurationUs::ZERO.is_positive());  | 
 | 247 | + | 
 | 248 | +    assert!(DurationUs::from_micros(5).is_positive());  | 
 | 249 | +    assert!(!DurationUs::from_micros(5).is_zero());  | 
 | 250 | +}  | 
 | 251 | + | 
 | 252 | +#[test]  | 
 | 253 | +fn timestamp_conversions() {  | 
 | 254 | +    let system_time = SystemTime::UNIX_EPOCH + Duration::from_micros(3_456_789_123_456_789);  | 
 | 255 | +    let ts = TimestampUs::try_from(system_time).unwrap();  | 
 | 256 | +    assert_eq!(ts, TimestampUs::from_micros(3_456_789_123_456_789));  | 
 | 257 | +    assert_eq!(SystemTime::try_from(ts).unwrap(), system_time);  | 
 | 258 | + | 
 | 259 | +    let proto_ts = ProtobufTimestamp::from(ts);  | 
 | 260 | +    assert_eq!(proto_ts.seconds, 3_456_789_123);  | 
 | 261 | +    assert_eq!(proto_ts.nanos, 456_789_000);  | 
 | 262 | +    assert_eq!(TimestampUs::try_from(&proto_ts).unwrap(), ts);  | 
 | 263 | +    assert_eq!(TimestampUs::try_from(proto_ts).unwrap(), ts);  | 
 | 264 | + | 
 | 265 | +    let chrono_dt: ChronoUtcDateTime = "2079-07-17T03:12:03.456789Z".parse().unwrap();  | 
 | 266 | +    assert_eq!(ChronoUtcDateTime::try_from(ts).unwrap(), chrono_dt);  | 
 | 267 | +    assert_eq!(TimestampUs::try_from(chrono_dt).unwrap(), ts);  | 
 | 268 | +}  | 
 | 269 | + | 
 | 270 | +#[test]  | 
 | 271 | +fn duration_conversions() {  | 
 | 272 | +    let duration = DurationUs::from_micros(123_456_789);  | 
 | 273 | +    let std_duration = Duration::from(duration);  | 
 | 274 | +    assert_eq!(format!("{std_duration:?}"), "123.456789s");  | 
 | 275 | +    assert_eq!(DurationUs::try_from(std_duration).unwrap(), duration);  | 
 | 276 | + | 
 | 277 | +    let proto_duration = ProtobufDuration::from(duration);  | 
 | 278 | +    assert_eq!(proto_duration.seconds, 123);  | 
 | 279 | +    assert_eq!(proto_duration.nanos, 456_789_000);  | 
 | 280 | +    assert_eq!(DurationUs::try_from(proto_duration).unwrap(), duration);  | 
 | 281 | +}  | 
 | 282 | + | 
 | 283 | +#[derive(Debug, PartialEq, Deserialize, Serialize)]  | 
 | 284 | +struct Test1 {  | 
 | 285 | +    t1: TimestampUs,  | 
 | 286 | +    d1: DurationUs,  | 
 | 287 | +    #[serde(with = "super::duration_us_serde_humantime")]  | 
 | 288 | +    d2: DurationUs,  | 
 | 289 | +}  | 
 | 290 | + | 
 | 291 | +#[test]  | 
 | 292 | +fn time_serde() {  | 
 | 293 | +    let test1 = Test1 {  | 
 | 294 | +        t1: TimestampUs::from_micros(123456789),  | 
 | 295 | +        d1: DurationUs::from_micros(123456789),  | 
 | 296 | +        d2: DurationUs::from_micros(123456789),  | 
 | 297 | +    };  | 
 | 298 | + | 
 | 299 | +    let json = serde_json::to_string(&test1).unwrap();  | 
 | 300 | +    assert_eq!(  | 
 | 301 | +        json,  | 
 | 302 | +        r#"{"t1":123456789,"d1":123456789,"d2":"2m 3s 456ms 789us"}"#  | 
 | 303 | +    );  | 
 | 304 | +    assert_eq!(serde_json::from_str::<Test1>(&json).unwrap(), test1);  | 
 | 305 | +}  | 
 | 306 | + | 
 | 307 | +#[cfg(feature = "mry")]  | 
 | 308 | +#[test]  | 
 | 309 | +#[mry::lock(TimestampUs::now)]  | 
 | 310 | +fn now_tests() {  | 
 | 311 | +    use std::sync::atomic::{AtomicU64, Ordering};  | 
 | 312 | +    use std::sync::Arc;  | 
 | 313 | + | 
 | 314 | +    let now = Arc::new(AtomicU64::new(42));  | 
 | 315 | +    let now2 = Arc::clone(&now);  | 
 | 316 | +    TimestampUs::mock_now()  | 
 | 317 | +        .returns_with(move || TimestampUs::from_micros(now2.load(Ordering::Relaxed)));  | 
 | 318 | + | 
 | 319 | +    assert_eq!(TimestampUs::now().as_micros(), 42);  | 
 | 320 | + | 
 | 321 | +    now.store(45, Ordering::Relaxed);  | 
 | 322 | +    let s = TimestampUs::now();  | 
 | 323 | +    now.store(95, Ordering::Relaxed);  | 
 | 324 | +    assert_eq!(s.elapsed().unwrap(), DurationUs::from_micros(50));  | 
 | 325 | +    assert_eq!(s.saturating_elapsed(), DurationUs::from_micros(50));  | 
 | 326 | + | 
 | 327 | +    now.store(35, Ordering::Relaxed);  | 
 | 328 | +    s.elapsed().unwrap_err();  | 
 | 329 | +    assert_eq!(s.saturating_elapsed(), DurationUs::ZERO);  | 
 | 330 | +}  | 
0 commit comments