Skip to content

Commit 41d7986

Browse files
vvukantrik
authored andcommitted
tests: Add variants of cross-process test, using spawn()
Since `fork()` isn't available on Windows, we need to do the tests using `spawn()` instead. The `spawn()` variants work both on Windows and on Unix platforms (including MacOS), making the `fork()` variants pretty redundant. However, it doesn't really hurt to keep them around, just in case. (It might help narrowing down any problems coming up, for example; or we might need support in the future for some platform that only works with `fork()`...)
1 parent 5070132 commit 41d7986

File tree

1 file changed

+117
-2
lines changed

1 file changed

+117
-2
lines changed

src/platform/test.rs

Lines changed: 117 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,16 +10,35 @@
1010
use platform::{self, OsIpcChannel, OsIpcReceiverSet};
1111
use platform::{OsIpcSharedMemory};
1212
use std::collections::HashMap;
13+
#[cfg(not(any(feature = "force-inprocess", target_os = "windows", target_os = "android")))]
14+
use std::process::{Command, Stdio};
1315
use std::sync::Arc;
1416
use std::time::{Duration, Instant};
1517
use std::thread;
18+
#[cfg(not(any(feature = "force-inprocess", target_os = "windows", target_os = "android")))]
19+
use std::env;
1620

21+
#[cfg(not(any(feature = "force-inprocess", target_os = "windows", target_os = "android")))]
22+
use libc;
1723
use platform::{OsIpcSender, OsIpcOneShotServer};
1824
#[cfg(not(any(feature = "force-inprocess", target_os = "windows", target_os = "android")))]
1925
use libc::{kill, SIGSTOP, SIGCONT};
2026
#[cfg(not(any(feature = "force-inprocess", target_os = "windows", target_os = "android")))]
2127
use test::{fork, Wait};
2228

29+
// Helper to get a channel_name argument passed in; used for the
30+
// cross-process spawn server tests.
31+
#[cfg(not(any(feature = "force-inprocess", target_os = "android")))]
32+
fn get_channel_name_arg() -> Option<String> {
33+
for arg in env::args() {
34+
let arg_str = "channel_name:";
35+
if arg.starts_with(arg_str) {
36+
return Some(arg[arg_str.len()..].to_owned());
37+
}
38+
}
39+
None
40+
}
41+
2342
#[test]
2443
fn simple() {
2544
let (tx, rx) = platform::channel().unwrap();
@@ -644,9 +663,52 @@ fn server_connect_first() {
644663
(data, vec![], vec![]));
645664
}
646665

666+
// Note! This test is actually used by the cross_process_spawn() test
667+
// below as a second process. Running it by itself is meaningless, but
668+
// passes.
669+
#[cfg(not(any(feature = "force-inprocess", target_os = "windows", target_os = "android")))]
670+
#[test]
671+
#[ignore]
672+
fn cross_process_server()
673+
{
674+
let data: &[u8] = b"1234567";
675+
let channel_name = get_channel_name_arg();
676+
if channel_name.is_none() {
677+
return;
678+
}
679+
680+
let tx = OsIpcSender::connect(channel_name.unwrap()).unwrap();
681+
tx.send(data, vec![], vec![]).unwrap();
682+
unsafe { libc::exit(0); }
683+
}
684+
685+
#[cfg(not(any(feature = "force-inprocess", target_os = "windows", target_os = "android")))]
686+
#[test]
687+
fn cross_process_spawn() {
688+
let (server, name) = OsIpcOneShotServer::new().unwrap();
689+
let data: &[u8] = b"1234567";
690+
691+
let mut child_pid = Command::new(env::current_exe().unwrap())
692+
.arg("--ignored")
693+
.arg("cross_process_server")
694+
.arg(format!("channel_name:{}", name))
695+
.stdin(Stdio::null())
696+
.stdout(Stdio::null())
697+
.stderr(Stdio::null())
698+
.spawn()
699+
.expect("failed to execute server process");
700+
701+
let (_, mut received_data, received_channels, received_shared_memory_regions) =
702+
server.accept().unwrap();
703+
child_pid.wait().expect("failed to wait on child");
704+
received_data.truncate(7);
705+
assert_eq!((&received_data[..], received_channels, received_shared_memory_regions),
706+
(data, vec![], vec![]));
707+
}
708+
647709
#[cfg(not(any(feature = "force-inprocess", target_os = "windows", target_os = "android")))]
648710
#[test]
649-
fn cross_process() {
711+
fn cross_process_fork() {
650712
let (server, name) = OsIpcOneShotServer::new().unwrap();
651713
let data: &[u8] = b"1234567";
652714

@@ -662,9 +724,62 @@ fn cross_process() {
662724
(data, vec![], vec![]));
663725
}
664726

727+
// Note! This test is actually used by the cross_process_sender_transfer_spawn() test
728+
// below as a second process. Running it by itself is meaningless, but
729+
// passes.
730+
#[cfg(not(any(feature = "force-inprocess", target_os = "windows", target_os = "android")))]
731+
#[test]
732+
#[ignore]
733+
fn cross_process_sender_transfer_server()
734+
{
735+
let channel_name = get_channel_name_arg();
736+
if channel_name.is_none() {
737+
return;
738+
}
739+
740+
let super_tx = OsIpcSender::connect(channel_name.unwrap()).unwrap();
741+
let (sub_tx, sub_rx) = platform::channel().unwrap();
742+
let data: &[u8] = b"foo";
743+
super_tx.send(data, vec![OsIpcChannel::Sender(sub_tx)], vec![]).unwrap();
744+
sub_rx.recv().unwrap();
745+
let data: &[u8] = b"bar";
746+
super_tx.send(data, vec![], vec![]).unwrap();
747+
unsafe { libc::exit(0); }
748+
}
749+
750+
#[cfg(not(any(feature = "force-inprocess", target_os = "windows", target_os = "android")))]
751+
#[test]
752+
fn cross_process_sender_transfer_spawn() {
753+
let (server, name) = OsIpcOneShotServer::new().unwrap();
754+
755+
let mut child_pid = Command::new(env::current_exe().unwrap())
756+
.arg("--ignored")
757+
.arg("cross_process_sender_transfer_server")
758+
.arg(format!("channel_name:{}", name))
759+
.stdin(Stdio::null())
760+
.stdout(Stdio::null())
761+
.stderr(Stdio::null())
762+
.spawn()
763+
.expect("failed to execute server process");
764+
765+
let (super_rx, _, mut received_channels, _) = server.accept().unwrap();
766+
assert_eq!(received_channels.len(), 1);
767+
let sub_tx = received_channels[0].to_sender();
768+
let data: &[u8] = b"baz";
769+
sub_tx.send(data, vec![], vec![]).unwrap();
770+
771+
let data: &[u8] = b"bar";
772+
let (mut received_data, received_channels, received_shared_memory_regions) =
773+
super_rx.recv().unwrap();
774+
child_pid.wait().expect("failed to wait on child");
775+
received_data.truncate(3);
776+
assert_eq!((&received_data[..], received_channels, received_shared_memory_regions),
777+
(data, vec![], vec![]));
778+
}
779+
665780
#[cfg(not(any(feature = "force-inprocess", target_os = "windows", target_os = "android")))]
666781
#[test]
667-
fn cross_process_sender_transfer() {
782+
fn cross_process_sender_transfer_fork() {
668783
let (server, name) = OsIpcOneShotServer::new().unwrap();
669784

670785
let child_pid = unsafe { fork(|| {

0 commit comments

Comments
 (0)