@@ -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