]> git.lizzy.rs Git - rust.git/blob - tests/run-pass/concurrency/libc_pthread_cond.rs
Add a custom ui test runner and move all tests to it
[rust.git] / tests / run-pass / concurrency / libc_pthread_cond.rs
1 // ignore-windows: No libc on Windows
2 // ignore-apple: pthread_condattr_setclock is not supported on MacOS.
3 // compile-flags: -Zmiri-disable-isolation -Zmiri-check-number-validity
4
5 #![feature(rustc_private)]
6
7 /// Test that conditional variable timeouts are working properly with both
8 /// monotonic and system clocks.
9 extern crate libc;
10
11 use std::mem::MaybeUninit;
12 use std::time::Instant;
13
14 fn test_timed_wait_timeout(clock_id: i32) {
15     unsafe {
16         let mut attr: MaybeUninit<libc::pthread_condattr_t> = MaybeUninit::uninit();
17         assert_eq!(libc::pthread_condattr_init(attr.as_mut_ptr()), 0);
18         assert_eq!(libc::pthread_condattr_setclock(attr.as_mut_ptr(), clock_id), 0);
19
20         let mut cond: MaybeUninit<libc::pthread_cond_t> = MaybeUninit::uninit();
21         assert_eq!(libc::pthread_cond_init(cond.as_mut_ptr(), attr.as_ptr()), 0);
22         assert_eq!(libc::pthread_condattr_destroy(attr.as_mut_ptr()), 0);
23
24         let mut mutex: libc::pthread_mutex_t = libc::PTHREAD_MUTEX_INITIALIZER;
25
26         let mut now_mu: MaybeUninit<libc::timespec> = MaybeUninit::uninit();
27         assert_eq!(libc::clock_gettime(clock_id, now_mu.as_mut_ptr()), 0);
28         let now = now_mu.assume_init();
29         // Waiting for a second... mostly because waiting less requires mich more tricky arithmetic.
30         // FIXME: wait less.
31         let timeout = libc::timespec { tv_sec: now.tv_sec + 1, tv_nsec: now.tv_nsec };
32
33         assert_eq!(libc::pthread_mutex_lock(&mut mutex as *mut _), 0);
34         let current_time = Instant::now();
35         assert_eq!(
36             libc::pthread_cond_timedwait(cond.as_mut_ptr(), &mut mutex as *mut _, &timeout),
37             libc::ETIMEDOUT
38         );
39         let elapsed_time = current_time.elapsed().as_millis();
40         assert!(900 <= elapsed_time && elapsed_time <= 1300);
41
42         // Test calling `pthread_cond_timedwait` again with an already elapsed timeout.
43         assert_eq!(
44             libc::pthread_cond_timedwait(cond.as_mut_ptr(), &mut mutex as *mut _, &timeout),
45             libc::ETIMEDOUT
46         );
47
48         // Test that invalid nanosecond values (above 10^9 or negative) are rejected with the
49         // correct error code.
50         let invalid_timeout_1 = libc::timespec { tv_sec: now.tv_sec + 1, tv_nsec: 1_000_000_000 };
51         assert_eq!(
52             libc::pthread_cond_timedwait(
53                 cond.as_mut_ptr(),
54                 &mut mutex as *mut _,
55                 &invalid_timeout_1
56             ),
57             libc::EINVAL
58         );
59         let invalid_timeout_2 = libc::timespec { tv_sec: now.tv_sec + 1, tv_nsec: -1 };
60         assert_eq!(
61             libc::pthread_cond_timedwait(
62                 cond.as_mut_ptr(),
63                 &mut mutex as *mut _,
64                 &invalid_timeout_2
65             ),
66             libc::EINVAL
67         );
68         // Test that invalid second values (negative) are rejected with the correct error code.
69         let invalid_timeout_3 = libc::timespec { tv_sec: -1, tv_nsec: 0 };
70         assert_eq!(
71             libc::pthread_cond_timedwait(
72                 cond.as_mut_ptr(),
73                 &mut mutex as *mut _,
74                 &invalid_timeout_3
75             ),
76             libc::EINVAL
77         );
78
79         assert_eq!(libc::pthread_mutex_unlock(&mut mutex as *mut _), 0);
80         assert_eq!(libc::pthread_mutex_destroy(&mut mutex as *mut _), 0);
81         assert_eq!(libc::pthread_cond_destroy(cond.as_mut_ptr()), 0);
82     }
83 }
84
85 fn main() {
86     test_timed_wait_timeout(libc::CLOCK_MONOTONIC);
87     test_timed_wait_timeout(libc::CLOCK_REALTIME);
88 }