Skip to content

Commit a18d54d

Browse files
vvukantrik
authored andcommitted
Add inception channel-in-channel multi-process transfer test
1 parent 41d7986 commit a18d54d

File tree

1 file changed

+94
-0
lines changed

1 file changed

+94
-0
lines changed

src/platform/test.rs

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -970,3 +970,97 @@ mod sync_test {
970970
platform::OsIpcSender::test_not_sync();
971971
}
972972
}
973+
974+
// Note! This test is actually used by the
975+
// cross_process_two_step_transfer_spawn() test below. Running it by
976+
// itself is meaningless, but it passes if run this way.
977+
#[cfg(not(any(feature = "force-inprocess", target_os = "windows", target_os = "android")))]
978+
#[test]
979+
#[ignore]
980+
fn cross_process_two_step_transfer_server()
981+
{
982+
let cookie: &[u8] = b"cookie";
983+
let channel_name = get_channel_name_arg();
984+
if channel_name.is_none() {
985+
return;
986+
}
987+
988+
// connect by name to our other process
989+
let super_tx = OsIpcSender::connect(channel_name.unwrap()).unwrap();
990+
991+
// create a channel for real communication between the two processes
992+
let (sub_tx, sub_rx) = platform::channel().unwrap();
993+
994+
// send the other process the tx side, so it can send us the channels
995+
super_tx.send(&[], vec![OsIpcChannel::Sender(sub_tx)], vec![]).unwrap();
996+
997+
// get two_rx from the other process
998+
let (_, mut received_channels, _) = sub_rx.recv().unwrap();
999+
assert_eq!(received_channels.len(), 1);
1000+
let two_rx = received_channels[0].to_receiver();
1001+
1002+
// get one_rx from two_rx's buffer
1003+
let (_, mut received_channels, _) = two_rx.recv().unwrap();
1004+
assert_eq!(received_channels.len(), 1);
1005+
let one_rx = received_channels[0].to_receiver();
1006+
1007+
// get a cookie from one_rx
1008+
let (mut data, _, _) = one_rx.recv().unwrap();
1009+
data.truncate(cookie.len());
1010+
assert_eq!(&data[..], cookie);
1011+
1012+
// finally, send a cookie back
1013+
super_tx.send(&data, vec![], vec![]).unwrap();
1014+
1015+
// terminate
1016+
unsafe { libc::exit(0); }
1017+
}
1018+
1019+
// TODO -- this fails on OSX with a MACH_SEND_INVALID_RIGHT!
1020+
// Needs investigation.
1021+
#[cfg(not(any(feature = "force-inprocess", target_os = "windows", target_os = "android")))]
1022+
#[cfg_attr(target_os = "macos", ignore)]
1023+
#[test]
1024+
fn cross_process_two_step_transfer_spawn() {
1025+
let cookie: &[u8] = b"cookie";
1026+
1027+
// create channel 1
1028+
let (one_tx, one_rx) = platform::channel().unwrap();
1029+
// put data in channel 1's pipe
1030+
one_tx.send(cookie, vec![], vec![]).unwrap();
1031+
1032+
// create channel 2
1033+
let (two_tx, two_rx) = platform::channel().unwrap();
1034+
// put channel 1's rx end in channel 2's pipe
1035+
two_tx.send(&[], vec![OsIpcChannel::Receiver(one_rx)], vec![]).unwrap();
1036+
1037+
// create a one-shot server, and spawn another process
1038+
let (server, name) = OsIpcOneShotServer::new().unwrap();
1039+
let mut child_pid = Command::new(env::current_exe().unwrap())
1040+
.arg("--ignored")
1041+
.arg("cross_process_two_step_transfer_server")
1042+
.arg(format!("channel_name:{}", name))
1043+
.stdin(Stdio::null())
1044+
.stdout(Stdio::null())
1045+
.stderr(Stdio::null())
1046+
.spawn()
1047+
.expect("failed to execute server process");
1048+
1049+
// The other process will have sent us a transmit channel in received channels
1050+
let (super_rx, _, mut received_channels, _) = server.accept().unwrap();
1051+
assert_eq!(received_channels.len(), 1);
1052+
let sub_tx = received_channels[0].to_sender();
1053+
1054+
// Send the outer payload channel, so the server can use it to
1055+
// retrive the inner payload and the cookie
1056+
sub_tx.send(&[], vec![OsIpcChannel::Receiver(two_rx)], vec![]).unwrap();
1057+
1058+
// Then we wait for the cookie to make its way back to us
1059+
let (mut received_data, received_channels, received_shared_memory_regions) =
1060+
super_rx.recv().unwrap();
1061+
let child_exit_code = child_pid.wait().expect("failed to wait on child");
1062+
assert!(child_exit_code.success());
1063+
received_data.truncate(cookie.len());
1064+
assert_eq!((&received_data[..], received_channels, received_shared_memory_regions),
1065+
(cookie, vec![], vec![]));
1066+
}

0 commit comments

Comments
 (0)