annotate tests/comm.rs @ 24:1941e9d9819c

Fix unsound manipulation of env vars Modifying env vars in multi-threaded process is unsound but this crate was neither checking the number of threads nor mark its functions as `unsafe`. This change fixes it by both adding a check and adding an `unsafe` function that can bypass that check if needed.
author Martin Habovstiak <martin.habovstiak@gmail.com>
date Fri, 28 Feb 2025 13:52:31 +0100
parents 08b37039504b
children cfef4593e207
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
1
ef8bf41097ac Added integration tests
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
1 use std::process::Child;
ef8bf41097ac Added integration tests
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
2 use std::ffi::OsStr;
ef8bf41097ac Added integration tests
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
3 use std::io::{self, Read, Write};
ef8bf41097ac Added integration tests
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
4
ef8bf41097ac Added integration tests
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
5 pub trait Test {
ef8bf41097ac Added integration tests
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
6 const SOCKET_ADDR: &'static str;
ef8bf41097ac Added integration tests
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
7
ef8bf41097ac Added integration tests
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
8 fn spawn_slave(program_name: &OsStr) -> io::Result<Child>;
ef8bf41097ac Added integration tests
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
9 }
ef8bf41097ac Added integration tests
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
10
ef8bf41097ac Added integration tests
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
11 const REQUEST: &[u8] = b"orange coin";
ef8bf41097ac Added integration tests
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
12 const RESPONSE: &[u8] = b"good";
ef8bf41097ac Added integration tests
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
13
ef8bf41097ac Added integration tests
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
14 fn main_master(slave: io::Result<Child>) {
15
08b37039504b Improved tests
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 8
diff changeset
15 let mut slave = slave.expect("failed to run a child");
1
ef8bf41097ac Added integration tests
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
16
ef8bf41097ac Added integration tests
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
17 // give slave some time to bind the socket just to be sure
8
372afb9a700f Prolong waiting for bind
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 1
diff changeset
18 std::thread::sleep(std::time::Duration::from_secs(5));
1
ef8bf41097ac Added integration tests
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
19
15
08b37039504b Improved tests
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 8
diff changeset
20 if let Some(exited) = slave.try_wait().expect("failed to check if the child exited") {
08b37039504b Improved tests
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 8
diff changeset
21 panic!("child exited unexpectedly: {}", exited);
08b37039504b Improved tests
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 8
diff changeset
22 }
08b37039504b Improved tests
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 8
diff changeset
23
08b37039504b Improved tests
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 8
diff changeset
24 let mut client_socket = std::net::TcpStream::connect("localhost:4242").expect("Failed to connect to 127.0.0.1:4242");
1
ef8bf41097ac Added integration tests
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
25 client_socket.write_all(REQUEST).expect("failed to send data");
ef8bf41097ac Added integration tests
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
26 let mut buf = [0u8; RESPONSE.len()];
ef8bf41097ac Added integration tests
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
27 client_socket.read_exact(&mut buf).expect("failed to read response");
ef8bf41097ac Added integration tests
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
28 assert_eq!(buf, RESPONSE);
ef8bf41097ac Added integration tests
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
29
ef8bf41097ac Added integration tests
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
30 let status = slave.wait().expect("faild to wait for slave");
ef8bf41097ac Added integration tests
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
31 if !status.success() {
ef8bf41097ac Added integration tests
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
32 panic!("slave did not exit with succcess, status: {}", status);
ef8bf41097ac Added integration tests
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
33 }
ef8bf41097ac Added integration tests
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
34 }
ef8bf41097ac Added integration tests
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
35
ef8bf41097ac Added integration tests
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
36 fn main_slave(addr: &str) {
ef8bf41097ac Added integration tests
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
37 use systemd_socket::SocketAddr;
ef8bf41097ac Added integration tests
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
38
24
1941e9d9819c Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 15
diff changeset
39 // SAFETY: this is the only thread that's going to mess with systemd sockets.
1941e9d9819c Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 15
diff changeset
40 unsafe {
1941e9d9819c Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 15
diff changeset
41 systemd_socket::init_unprotected().unwrap();
1941e9d9819c Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 15
diff changeset
42 }
1941e9d9819c Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 15
diff changeset
43
1
ef8bf41097ac Added integration tests
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
44 let socket = addr
ef8bf41097ac Added integration tests
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
45 .parse::<SocketAddr>()
ef8bf41097ac Added integration tests
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
46 .expect("failed to parse socket")
ef8bf41097ac Added integration tests
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
47 .bind()
ef8bf41097ac Added integration tests
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
48 .expect("failed to bind");
ef8bf41097ac Added integration tests
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
49
ef8bf41097ac Added integration tests
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
50 let (mut client_socket, _) = socket.accept().expect("failed to accept");
ef8bf41097ac Added integration tests
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
51 let mut buf = [0u8; REQUEST.len()];
ef8bf41097ac Added integration tests
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
52 client_socket.read_exact(&mut buf).expect("failed to read response");
ef8bf41097ac Added integration tests
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
53 assert_eq!(buf, REQUEST);
ef8bf41097ac Added integration tests
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
54 client_socket.write_all(RESPONSE).expect("failed to send data");
ef8bf41097ac Added integration tests
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
55 }
ef8bf41097ac Added integration tests
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
56
ef8bf41097ac Added integration tests
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
57 pub fn main<T: Test>() {
ef8bf41097ac Added integration tests
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
58 let mut args = std::env::args_os();
ef8bf41097ac Added integration tests
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
59 let program_name = args.next().expect("missing program name");
ef8bf41097ac Added integration tests
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
60
ef8bf41097ac Added integration tests
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
61 match std::env::var_os("SYSTEMD_SOCKET_INTEGRATION_TEST") {
ef8bf41097ac Added integration tests
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
62 None => main_master(T::spawn_slave(&program_name)),
ef8bf41097ac Added integration tests
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
63 Some(arg) if arg == "slave" => main_slave(T::SOCKET_ADDR),
ef8bf41097ac Added integration tests
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
64 Some(arg) => panic!("Unknown argument '{:?}'", arg),
ef8bf41097ac Added integration tests
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
65 }
ef8bf41097ac Added integration tests
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
66 }