1010use platform:: { self , OsIpcChannel , OsIpcReceiverSet } ;
1111use platform:: { OsIpcSharedMemory } ;
1212use std:: collections:: HashMap ;
13+ #[ cfg( not( any( feature = "force-inprocess" , target_os = "windows" , target_os = "android" ) ) ) ]
14+ use std:: process:: { Command , Stdio } ;
1315use std:: sync:: Arc ;
1416use std:: time:: { Duration , Instant } ;
1517use 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;
1723use platform:: { OsIpcSender , OsIpcOneShotServer } ;
1824#[ cfg( not( any( feature = "force-inprocess" , target_os = "windows" , target_os = "android" ) ) ) ]
1925use libc:: { kill, SIGSTOP , SIGCONT } ;
2026#[ cfg( not( any( feature = "force-inprocess" , target_os = "windows" , target_os = "android" ) ) ) ]
2127use 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]
2443fn 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