Skip to content

Commit d380750

Browse files
hulxvRalfJung
authored andcommitted
Refactor libc pipe tests to use utility functions for error handling and data operations
1 parent dc1ede0 commit d380750

File tree

2 files changed

+72
-83
lines changed

2 files changed

+72
-83
lines changed

tests/pass-dep/libc/libc-pipe.rs

Lines changed: 54 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ use std::thread;
55

66
#[path = "../../utils/libc.rs"]
77
mod libc_utils;
8+
use libc_utils::*;
89

910
fn main() {
1011
test_pipe();
@@ -25,69 +26,46 @@ fn main() {
2526

2627
fn test_pipe() {
2728
let mut fds = [-1, -1];
28-
let res = unsafe { libc::pipe(fds.as_mut_ptr()) };
29-
assert_eq!(res, 0);
29+
errno_check(unsafe { libc::pipe(fds.as_mut_ptr()) });
3030

3131
// Read size == data available in buffer.
32-
let data = "12345".as_bytes().as_ptr();
33-
let res = unsafe { libc_utils::write_all(fds[1], data as *const libc::c_void, 5) };
34-
assert_eq!(res, 5);
35-
let mut buf3: [u8; 5] = [0; 5];
36-
let res = unsafe {
37-
libc_utils::read_all(fds[0], buf3.as_mut_ptr().cast(), buf3.len() as libc::size_t)
38-
};
39-
assert_eq!(res, 5);
40-
assert_eq!(buf3, "12345".as_bytes());
32+
let data = b"12345";
33+
write_all_from_slice(fds[1], data).unwrap();
34+
let buf3 = read_all_into_array::<5>(fds[0]).unwrap();
35+
assert_eq!(&buf3, data);
4136

4237
// Read size > data available in buffer.
43-
let data = "123".as_bytes();
44-
let res = unsafe { libc_utils::write_all(fds[1], data.as_ptr() as *const libc::c_void, 3) };
45-
assert_eq!(res, 3);
38+
let data = b"123";
39+
write_all_from_slice(fds[1], data).unwrap();
4640
let mut buf4: [u8; 5] = [0; 5];
47-
let res = unsafe { libc::read(fds[0], buf4.as_mut_ptr().cast(), buf4.len() as libc::size_t) };
48-
assert!(res > 0 && res <= 3);
49-
let res = res as usize;
41+
let res = read_into_slice(fds[0], &mut buf4).unwrap().0.len();
5042
assert_eq!(buf4[..res], data[..res]);
5143
if res < 3 {
5244
// Drain the rest from the read end.
53-
let res = unsafe { libc_utils::read_all(fds[0], buf4[res..].as_mut_ptr().cast(), 3 - res) };
45+
let res = read_into_slice(fds[0], &mut buf4[res..]).unwrap().0.len();
5446
assert!(res > 0);
5547
}
5648
}
5749

5850
fn test_pipe_threaded() {
5951
let mut fds = [-1, -1];
60-
let res = unsafe { libc::pipe(fds.as_mut_ptr()) };
61-
assert_eq!(res, 0);
52+
errno_check(unsafe { libc::pipe(fds.as_mut_ptr()) });
6253

6354
let thread1 = thread::spawn(move || {
64-
let mut buf: [u8; 5] = [0; 5];
65-
let res: i64 = unsafe {
66-
libc_utils::read_all(fds[0], buf.as_mut_ptr().cast(), buf.len() as libc::size_t)
67-
.try_into()
68-
.unwrap()
69-
};
70-
assert_eq!(res, 5);
71-
assert_eq!(buf, "abcde".as_bytes());
55+
let buf = read_all_into_array::<5>(fds[0]).unwrap();
56+
assert_eq!(&buf, b"abcde");
7257
});
7358
thread::yield_now();
74-
let data = "abcde".as_bytes().as_ptr();
75-
let res = unsafe { libc_utils::write_all(fds[1], data as *const libc::c_void, 5) };
76-
assert_eq!(res, 5);
59+
write_all_from_slice(fds[1], b"abcde").unwrap();
7760
thread1.join().unwrap();
7861

7962
// Read and write from different direction
8063
let thread2 = thread::spawn(move || {
8164
thread::yield_now();
82-
let data = "12345".as_bytes().as_ptr();
83-
let res = unsafe { libc_utils::write_all(fds[1], data as *const libc::c_void, 5) };
84-
assert_eq!(res, 5);
65+
write_all_from_slice(fds[1], b"12345").unwrap();
8566
});
86-
let mut buf: [u8; 5] = [0; 5];
87-
let res =
88-
unsafe { libc_utils::read_all(fds[0], buf.as_mut_ptr().cast(), buf.len() as libc::size_t) };
89-
assert_eq!(res, 5);
90-
assert_eq!(buf, "12345".as_bytes());
67+
let buf = read_all_into_array::<5>(fds[0]).unwrap();
68+
assert_eq!(&buf, b"12345");
9169
thread2.join().unwrap();
9270
}
9371

@@ -96,26 +74,17 @@ fn test_pipe_threaded() {
9674
fn test_race() {
9775
static mut VAL: u8 = 0;
9876
let mut fds = [-1, -1];
99-
let res = unsafe { libc::pipe(fds.as_mut_ptr()) };
100-
assert_eq!(res, 0);
77+
errno_check(unsafe { libc::pipe(fds.as_mut_ptr()) });
10178
let thread1 = thread::spawn(move || {
102-
let mut buf: [u8; 1] = [0; 1];
10379
// write() from the main thread will occur before the read() here
10480
// because preemption is disabled and the main thread yields after write().
105-
let res: i32 = unsafe {
106-
libc_utils::read_all(fds[0], buf.as_mut_ptr().cast(), buf.len() as libc::size_t)
107-
.try_into()
108-
.unwrap()
109-
};
110-
assert_eq!(res, 1);
111-
assert_eq!(buf, "a".as_bytes());
81+
let buf = read_all_into_array::<1>(fds[0]).unwrap();
82+
assert_eq!(&buf, b"a");
11283
// The read above establishes a happens-before so it is now safe to access this global variable.
11384
unsafe { assert_eq!(VAL, 1) };
11485
});
11586
unsafe { VAL = 1 };
116-
let data = "a".as_bytes().as_ptr();
117-
let res = unsafe { libc_utils::write_all(fds[1], data as *const libc::c_void, 1) };
118-
assert_eq!(res, 1);
87+
write_all_from_slice(fds[1], b"a").unwrap();
11988
thread::yield_now();
12089
thread1.join().unwrap();
12190
}
@@ -139,40 +108,46 @@ fn test_pipe_array() {
139108
))]
140109
fn test_pipe2() {
141110
let mut fds = [-1, -1];
142-
let res = unsafe { libc::pipe2(fds.as_mut_ptr(), libc::O_NONBLOCK) };
143-
assert_eq!(res, 0);
111+
errno_check(unsafe { libc::pipe2(fds.as_mut_ptr(), libc::O_NONBLOCK) });
144112
}
145113

146114
/// Basic test for pipe fcntl's F_SETFL and F_GETFL flag.
147115
fn test_pipe_setfl_getfl() {
148116
// Initialise pipe fds.
149117
let mut fds = [-1, -1];
150-
let res = unsafe { libc::pipe(fds.as_mut_ptr()) };
151-
assert_eq!(res, 0);
118+
errno_check(unsafe { libc::pipe(fds.as_mut_ptr()) });
152119

153120
// Both sides should either have O_RONLY or O_WRONLY.
154-
let res = unsafe { libc::fcntl(fds[0], libc::F_GETFL) };
155-
assert_eq!(res, libc::O_RDONLY);
156-
let res = unsafe { libc::fcntl(fds[1], libc::F_GETFL) };
157-
assert_eq!(res, libc::O_WRONLY);
121+
assert_eq!(
122+
errno_result(unsafe { libc::fcntl(fds[0], libc::F_GETFL) }).unwrap(),
123+
libc::O_RDONLY
124+
);
125+
assert_eq!(
126+
errno_result(unsafe { libc::fcntl(fds[1], libc::F_GETFL) }).unwrap(),
127+
libc::O_WRONLY
128+
);
158129

159130
// Add the O_NONBLOCK flag with F_SETFL.
160-
let res = unsafe { libc::fcntl(fds[0], libc::F_SETFL, libc::O_NONBLOCK) };
161-
assert_eq!(res, 0);
131+
errno_check(unsafe { libc::fcntl(fds[0], libc::F_SETFL, libc::O_NONBLOCK) });
162132

163133
// Test if the O_NONBLOCK flag is successfully added.
164-
let res = unsafe { libc::fcntl(fds[0], libc::F_GETFL) };
165-
assert_eq!(res, libc::O_RDONLY | libc::O_NONBLOCK);
134+
assert_eq!(
135+
errno_result(unsafe { libc::fcntl(fds[0], libc::F_GETFL) }).unwrap(),
136+
libc::O_RDONLY | libc::O_NONBLOCK
137+
);
166138

167139
// The other side remains unchanged.
168-
let res = unsafe { libc::fcntl(fds[1], libc::F_GETFL) };
169-
assert_eq!(res, libc::O_WRONLY);
140+
assert_eq!(
141+
errno_result(unsafe { libc::fcntl(fds[1], libc::F_GETFL) }).unwrap(),
142+
libc::O_WRONLY
143+
);
170144

171145
// Test if O_NONBLOCK flag can be unset.
172-
let res = unsafe { libc::fcntl(fds[0], libc::F_SETFL, 0) };
173-
assert_eq!(res, 0);
174-
let res = unsafe { libc::fcntl(fds[0], libc::F_GETFL) };
175-
assert_eq!(res, libc::O_RDONLY);
146+
errno_check(unsafe { libc::fcntl(fds[0], libc::F_SETFL, 0) });
147+
assert_eq!(
148+
errno_result(unsafe { libc::fcntl(fds[0], libc::F_GETFL) }).unwrap(),
149+
libc::O_RDONLY
150+
);
176151
}
177152

178153
/// Test the behaviour of F_SETFL/F_GETFL when a fd is blocking.
@@ -183,28 +158,24 @@ fn test_pipe_setfl_getfl() {
183158
/// then writes to fds[1] to unblock main thread's `read`.
184159
fn test_pipe_fcntl_threaded() {
185160
let mut fds = [-1, -1];
186-
let res = unsafe { libc::pipe(fds.as_mut_ptr()) };
187-
assert_eq!(res, 0);
188-
let mut buf: [u8; 5] = [0; 5];
161+
errno_check(unsafe { libc::pipe(fds.as_mut_ptr()) });
189162
let thread1 = thread::spawn(move || {
190163
// Add O_NONBLOCK flag while pipe is still blocked on read.
191-
let res = unsafe { libc::fcntl(fds[0], libc::F_SETFL, libc::O_NONBLOCK) };
192-
assert_eq!(res, 0);
164+
errno_check(unsafe { libc::fcntl(fds[0], libc::F_SETFL, libc::O_NONBLOCK) });
193165

194166
// Check the new flag value while the main thread is still blocked on fds[0].
195-
let res = unsafe { libc::fcntl(fds[0], libc::F_GETFL) };
196-
assert_eq!(res, libc::O_NONBLOCK);
167+
assert_eq!(
168+
errno_result(unsafe { libc::fcntl(fds[0], libc::F_GETFL) }).unwrap(),
169+
libc::O_NONBLOCK
170+
);
197171

198172
// The write below will unblock the `read` in main thread: even though
199173
// the socket is now "non-blocking", the shim needs to deal correctly
200174
// with threads that were blocked before the socket was made non-blocking.
201-
let data = "abcde".as_bytes().as_ptr();
202-
let res = unsafe { libc_utils::write_all(fds[1], data as *const libc::c_void, 5) };
203-
assert_eq!(res, 5);
175+
write_all_from_slice(fds[1], b"abcde").unwrap();
204176
});
205177
// The `read` below will block.
206-
let res =
207-
unsafe { libc_utils::read_all(fds[0], buf.as_mut_ptr().cast(), buf.len() as libc::size_t) };
178+
let buf = read_all_into_array::<5>(fds[0]).unwrap();
208179
thread1.join().unwrap();
209-
assert_eq!(res, 5);
180+
assert_eq!(&buf, b"abcde");
210181
}

tests/utils/libc.rs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,24 @@ pub fn read_all_into_array<const N: usize>(fd: libc::c_int) -> Result<[u8; N], l
5353
}
5454
}
5555

56+
pub fn read_all_into_slice(fd: libc::c_int, buf: &mut [u8]) -> Result<(), libc::ssize_t> {
57+
let res = unsafe { read_all(fd, buf.as_mut_ptr().cast(), buf.len()) };
58+
if res >= 0 {
59+
assert_eq!(res as usize, buf.len());
60+
Ok(())
61+
} else {
62+
Err(res)
63+
}
64+
}
65+
66+
pub fn read_into_slice(
67+
fd: libc::c_int,
68+
buf: &mut [u8],
69+
) -> Result<(&mut [u8], &mut [u8]), libc::ssize_t> {
70+
let res = unsafe { libc::read(fd, buf.as_mut_ptr().cast(), buf.len()) };
71+
if res >= 0 { Ok(buf.split_at_mut(res as usize)) } else { Err(res) }
72+
}
73+
5674
pub unsafe fn write_all(
5775
fd: libc::c_int,
5876
buf: *const libc::c_void,

0 commit comments

Comments
 (0)