]> git.lizzy.rs Git - rust.git/blob - tests/run-pass/libc.rs
14d12de0d186d279938c7e4bb322c2ac0ca85ac2
[rust.git] / tests / run-pass / libc.rs
1 // ignore-windows: No libc on Windows
2 // compile-flags: -Zmiri-disable-isolation
3
4 #![feature(rustc_private)]
5
6 extern crate libc;
7
8 #[cfg(target_os = "linux")]
9 fn tmp() -> std::path::PathBuf {
10     std::env::var("MIRI_TEMP").map(std::path::PathBuf::from).unwrap_or_else(|_| std::env::temp_dir())
11 }
12
13 #[cfg(target_os = "linux")]
14 fn test_posix_fadvise() {
15     use std::convert::TryInto;
16     use std::fs::{remove_file, File};
17     use std::io::Write;
18     use std::os::unix::io::AsRawFd;
19
20     let path = tmp().join("miri_test_libc.txt");
21     // Cleanup before test
22     remove_file(&path).ok();
23
24     // Set up an open file
25     let mut file = File::create(&path).unwrap();
26     let bytes = b"Hello, World!\n";
27     file.write(bytes).unwrap();
28
29     // Test calling posix_fadvise on a file.
30     let result = unsafe {
31         libc::posix_fadvise(
32             file.as_raw_fd(),
33             0,
34             bytes.len().try_into().unwrap(),
35             libc::POSIX_FADV_DONTNEED,
36         )
37     };
38     drop(file);
39     remove_file(&path).unwrap();
40     assert_eq!(result, 0);
41 }
42
43 fn test_mutex_libc_init_recursive() {
44     unsafe {
45         let mut attr: libc::pthread_mutexattr_t = std::mem::zeroed();
46         assert_eq!(libc::pthread_mutexattr_init(&mut attr as *mut _), 0);
47         assert_eq!(libc::pthread_mutexattr_settype(&mut attr as *mut _, libc::PTHREAD_MUTEX_RECURSIVE), 0);
48         let mut mutex: libc::pthread_mutex_t = std::mem::zeroed();
49         assert_eq!(libc::pthread_mutex_init(&mut mutex as *mut _, &mut attr as *mut _), 0);
50         assert_eq!(libc::pthread_mutex_lock(&mut mutex as *mut _), 0);
51         assert_eq!(libc::pthread_mutex_trylock(&mut mutex as *mut _), 0);
52         assert_eq!(libc::pthread_mutex_unlock(&mut mutex as *mut _), 0);
53         assert_eq!(libc::pthread_mutex_unlock(&mut mutex as *mut _), 0);
54         assert_eq!(libc::pthread_mutex_trylock(&mut mutex as *mut _), 0);
55         assert_eq!(libc::pthread_mutex_lock(&mut mutex as *mut _), 0);
56         assert_eq!(libc::pthread_mutex_unlock(&mut mutex as *mut _), 0);
57         assert_eq!(libc::pthread_mutex_unlock(&mut mutex as *mut _), 0);
58         assert_eq!(libc::pthread_mutex_unlock(&mut mutex as *mut _), libc::EPERM);
59         assert_eq!(libc::pthread_mutex_destroy(&mut mutex as *mut _), 0);
60         assert_eq!(libc::pthread_mutexattr_destroy(&mut attr as *mut _), 0);
61     }
62 }
63
64 fn test_mutex_libc_init_normal() {
65     unsafe {
66         let mut mutexattr: libc::pthread_mutexattr_t = std::mem::zeroed();
67         assert_eq!(libc::pthread_mutexattr_settype(&mut mutexattr as *mut _, 0x12345678), libc::EINVAL);
68         assert_eq!(libc::pthread_mutexattr_settype(&mut mutexattr as *mut _, libc::PTHREAD_MUTEX_NORMAL), 0);
69         let mut mutex: libc::pthread_mutex_t = std::mem::zeroed();
70         assert_eq!(libc::pthread_mutex_init(&mut mutex as *mut _, &mutexattr as *const _), 0);
71         assert_eq!(libc::pthread_mutex_lock(&mut mutex as *mut _), 0);
72         assert_eq!(libc::pthread_mutex_trylock(&mut mutex as *mut _), libc::EBUSY);
73         assert_eq!(libc::pthread_mutex_unlock(&mut mutex as *mut _), 0);
74         assert_eq!(libc::pthread_mutex_trylock(&mut mutex as *mut _), 0);
75         assert_eq!(libc::pthread_mutex_unlock(&mut mutex as *mut _), 0);
76         assert_eq!(libc::pthread_mutex_destroy(&mut mutex as *mut _), 0);
77     }
78 }
79
80 fn test_mutex_libc_init_errorcheck() {
81     unsafe {
82         let mut mutexattr: libc::pthread_mutexattr_t = std::mem::zeroed();
83         assert_eq!(libc::pthread_mutexattr_settype(&mut mutexattr as *mut _, libc::PTHREAD_MUTEX_ERRORCHECK), 0);
84         let mut mutex: libc::pthread_mutex_t = std::mem::zeroed();
85         assert_eq!(libc::pthread_mutex_init(&mut mutex as *mut _, &mutexattr as *const _), 0);
86         assert_eq!(libc::pthread_mutex_lock(&mut mutex as *mut _), 0);
87         assert_eq!(libc::pthread_mutex_trylock(&mut mutex as *mut _), libc::EBUSY);
88         assert_eq!(libc::pthread_mutex_lock(&mut mutex as *mut _), libc::EDEADLK);
89         assert_eq!(libc::pthread_mutex_unlock(&mut mutex as *mut _), 0);
90         assert_eq!(libc::pthread_mutex_trylock(&mut mutex as *mut _), 0);
91         assert_eq!(libc::pthread_mutex_unlock(&mut mutex as *mut _), 0);
92         assert_eq!(libc::pthread_mutex_unlock(&mut mutex as *mut _), libc::EPERM);
93         assert_eq!(libc::pthread_mutex_destroy(&mut mutex as *mut _), 0);
94     }
95 }
96
97 // Only linux provides PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP,
98 // libc for macOS just has the default PTHREAD_MUTEX_INITIALIZER.
99 #[cfg(target_os = "linux")]
100 fn test_mutex_libc_static_initializer_recursive() {
101     let mutex = std::cell::UnsafeCell::new(libc::PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP);
102     unsafe {
103         assert_eq!(libc::pthread_mutex_lock(mutex.get()), 0);
104         assert_eq!(libc::pthread_mutex_trylock(mutex.get()), 0);
105         assert_eq!(libc::pthread_mutex_unlock(mutex.get()), 0);
106         assert_eq!(libc::pthread_mutex_unlock(mutex.get()), 0);
107         assert_eq!(libc::pthread_mutex_trylock(mutex.get()), 0);
108         assert_eq!(libc::pthread_mutex_lock(mutex.get()), 0);
109         assert_eq!(libc::pthread_mutex_unlock(mutex.get()), 0);
110         assert_eq!(libc::pthread_mutex_unlock(mutex.get()), 0);
111         assert_eq!(libc::pthread_mutex_unlock(mutex.get()), libc::EPERM);
112         assert_eq!(libc::pthread_mutex_destroy(mutex.get()), 0);
113     }
114 }
115
116 // Testing the behavior of std::sync::RwLock does not fully exercise the pthread rwlock shims, we
117 // need to go a layer deeper and test the behavior of the libc functions, because
118 // std::sys::unix::rwlock::RWLock itself keeps track of write_locked and num_readers.
119 fn test_rwlock_libc_static_initializer() {
120     let rw = std::cell::UnsafeCell::new(libc::PTHREAD_RWLOCK_INITIALIZER);
121     unsafe {
122         assert_eq!(libc::pthread_rwlock_rdlock(rw.get()), 0);
123         assert_eq!(libc::pthread_rwlock_rdlock(rw.get()), 0);
124         assert_eq!(libc::pthread_rwlock_unlock(rw.get()), 0);
125         assert_eq!(libc::pthread_rwlock_tryrdlock(rw.get()), 0);
126         assert_eq!(libc::pthread_rwlock_unlock(rw.get()), 0);
127         assert_eq!(libc::pthread_rwlock_trywrlock(rw.get()), libc::EBUSY);
128         assert_eq!(libc::pthread_rwlock_unlock(rw.get()), 0);
129
130         assert_eq!(libc::pthread_rwlock_wrlock(rw.get()), 0);
131         assert_eq!(libc::pthread_rwlock_tryrdlock(rw.get()), libc::EBUSY);
132         assert_eq!(libc::pthread_rwlock_trywrlock(rw.get()), libc::EBUSY);
133         assert_eq!(libc::pthread_rwlock_unlock(rw.get()), 0);
134
135         assert_eq!(libc::pthread_rwlock_trywrlock(rw.get()), 0);
136         assert_eq!(libc::pthread_rwlock_tryrdlock(rw.get()), libc::EBUSY);
137         assert_eq!(libc::pthread_rwlock_trywrlock(rw.get()), libc::EBUSY);
138         assert_eq!(libc::pthread_rwlock_unlock(rw.get()), 0);
139
140         assert_eq!(libc::pthread_rwlock_destroy(rw.get()), 0);
141     }
142 }
143
144 fn main() {
145     #[cfg(target_os = "linux")]
146     test_posix_fadvise();
147
148     test_mutex_libc_init_recursive();
149     test_mutex_libc_init_normal();
150     test_mutex_libc_init_errorcheck();
151     test_rwlock_libc_static_initializer();
152
153     #[cfg(target_os = "linux")]
154     test_mutex_libc_static_initializer_recursive();
155 }