From a3788cdd3fb582e5b26ef3b017352176ec5ed1ad Mon Sep 17 00:00:00 2001 From: Glyn Normington Date: Mon, 7 Apr 2025 15:52:55 +0100 Subject: [PATCH 1/6] Test IpcReceiver behaviour --- src/test.rs | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/src/test.rs b/src/test.rs index e87840aa..bbf43cdd 100644 --- a/src/test.rs +++ b/src/test.rs @@ -163,6 +163,26 @@ fn embedded_receivers() { assert_eq!(received_person, person); } +#[test] +fn embedded_receivers_used_before_and_after_transmission() { + let person = ("Patrick Walton".to_owned(), 29); + let (sub_tx, sub_rx) = ipc::channel().unwrap(); + + sub_tx.send(person.clone()).unwrap(); + let received_person1 = sub_rx.recv().unwrap(); + assert_eq!(received_person1, person); + + let person_and_receiver = (person.clone(), sub_rx); + let (super_tx, super_rx) = ipc::channel().unwrap(); + super_tx.send(person_and_receiver).unwrap(); + let received_person_and_receiver = super_rx.recv().unwrap(); + assert_eq!(received_person_and_receiver.0, person); + + sub_tx.send(person.clone()).unwrap(); + let received_person2 = received_person_and_receiver.1.recv().unwrap(); + assert_eq!(received_person2, person); +} + #[test] fn select() { let (tx0, rx0) = ipc::channel().unwrap(); From 7d23b3181378d7c5d3f76fc641493eba1fbb6f62 Mon Sep 17 00:00:00 2001 From: Glyn Normington Date: Mon, 7 Apr 2025 15:53:46 +0100 Subject: [PATCH 2/6] Detect dead testcase --- src/test.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/test.rs b/src/test.rs index bbf43cdd..e2e1edbf 100644 --- a/src/test.rs +++ b/src/test.rs @@ -254,6 +254,8 @@ fn cross_process_embedded_senders_spawn() { unsafe { libc::exit(0); } + } else { + assert!(false, "dead testcase"); } } From 22f31c5e500d5a1354b755e07b6876b4a9d89882 Mon Sep 17 00:00:00 2001 From: Glyn Normington Date: Mon, 7 Apr 2025 15:54:46 +0100 Subject: [PATCH 3/6] Delete dead testcase See the previous commit for why this testcase is dead. --- src/test.rs | 23 ----------------------- 1 file changed, 23 deletions(-) diff --git a/src/test.rs b/src/test.rs index e2e1edbf..3458683a 100644 --- a/src/test.rs +++ b/src/test.rs @@ -236,29 +236,6 @@ fn select() { } } -#[cfg(not(any(feature = "force-inprocess", target_os = "android", target_os = "ios")))] -#[test] -fn cross_process_embedded_senders_spawn() { - let person = ("Patrick Walton".to_owned(), 29); - - let server0_name = get_channel_name_arg("server0"); - let server2_name = get_channel_name_arg("server2"); - if let (Some(server0_name), Some(server2_name)) = (server0_name, server2_name) { - let (tx1, rx1): (IpcSender, IpcReceiver) = ipc::channel().unwrap(); - let tx0 = IpcSender::connect(server0_name).unwrap(); - tx0.send(tx1).unwrap(); - rx1.recv().unwrap(); - let tx2: IpcSender = IpcSender::connect(server2_name).unwrap(); - tx2.send(person.clone()).unwrap(); - - unsafe { - libc::exit(0); - } - } else { - assert!(false, "dead testcase"); - } -} - #[cfg(not(any( feature = "force-inprocess", target_os = "windows", From 9a75c351f95131df537d0e4f7354385afcbc3f5a Mon Sep 17 00:00:00 2001 From: Glyn Normington Date: Mon, 7 Apr 2025 16:09:51 +0100 Subject: [PATCH 4/6] Integration test of IpcReceiver transmission --- src/bin/spawn_receiver_sender_client.rs | 27 ++++++++++++++++++++ tests/integration_test.rs | 33 ++++++++++++++++++++++++- 2 files changed, 59 insertions(+), 1 deletion(-) create mode 100644 src/bin/spawn_receiver_sender_client.rs diff --git a/src/bin/spawn_receiver_sender_client.rs b/src/bin/spawn_receiver_sender_client.rs new file mode 100644 index 00000000..39306cbb --- /dev/null +++ b/src/bin/spawn_receiver_sender_client.rs @@ -0,0 +1,27 @@ +// Copyright 2025 The Servo Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use ipc_channel::ipc::{self, IpcReceiver, IpcSender}; +use std::{env, process}; + +/// Test executable which connects to the one-shot server with name +/// passed in as an argument and then sends a receiver to the server +/// and then a test message to the receiver. +fn main() { + let args: Vec = env::args().collect(); + let token = args.get(1).expect("missing argument"); + + let (sub_tx, sub_rx) = ipc::channel().unwrap(); + + let tx: IpcSender> = IpcSender::connect(token.to_string()).expect("connect failed"); + tx.send(sub_rx).expect("send failed"); + sub_tx.send("test message".to_string()).expect("send failed"); + + process::exit(0); +} diff --git a/tests/integration_test.rs b/tests/integration_test.rs index 92d69e1c..9fba4ed4 100644 --- a/tests/integration_test.rs +++ b/tests/integration_test.rs @@ -8,7 +8,7 @@ // except according to those terms. #[cfg(not(any(feature = "force-inprocess", target_os = "android", target_os = "ios")))] -use ipc_channel::ipc::IpcOneShotServer; +use ipc_channel::ipc::{IpcOneShotServer, IpcReceiver}; #[cfg(not(any(feature = "force-inprocess", target_os = "android", target_os = "ios")))] use std::{env, process}; @@ -42,3 +42,34 @@ fn spawn_one_shot_server_client() { result.code().expect("exit status code not available") ); } + +/// Test spawing a process which then acts as a client to a +/// one-shot server in the parent process. The client sends a +/// receiver and then send a message to the receiver. +#[cfg(not(any(feature = "force-inprocess", target_os = "android", target_os = "ios")))] +#[test] +fn spawn_receiver_sender_client() { + let executable_path: String = env!("CARGO_BIN_EXE_spawn_receiver_sender_client").to_string(); + + let (server, token) = + IpcOneShotServer::>::new().expect("Failed to create IPC one-shot server."); + + let mut command = process::Command::new(executable_path); + let child_process = command.arg(token); + + let mut child = child_process + .spawn() + .expect("Failed to start child process"); + + let (_rx, sub_rx) = server.accept().expect("accept failed"); + + let msg = sub_rx.recv().unwrap(); + assert_eq!("test message", msg); + + let result = child.wait().expect("wait for child process failed"); + assert!( + result.success(), + "child process failed with exit status code {}", + result.code().expect("exit status code not available") + ); +} From 584a950a07ae322136b92e9768ce1b0b719b530e Mon Sep 17 00:00:00 2001 From: Glyn Normington Date: Mon, 7 Apr 2025 16:14:50 +0100 Subject: [PATCH 5/6] Integration test of used IpcReceiver transmission --- src/bin/spawn_used_receiver_sender_client.rs | 31 +++++++++++++++++++ tests/integration_test.rs | 32 ++++++++++++++++++++ 2 files changed, 63 insertions(+) create mode 100644 src/bin/spawn_used_receiver_sender_client.rs diff --git a/src/bin/spawn_used_receiver_sender_client.rs b/src/bin/spawn_used_receiver_sender_client.rs new file mode 100644 index 00000000..7c09fd1d --- /dev/null +++ b/src/bin/spawn_used_receiver_sender_client.rs @@ -0,0 +1,31 @@ +// Copyright 2025 The Servo Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use ipc_channel::ipc::{self, IpcReceiver, IpcSender}; +use std::{env, process}; + +/// Test executable which connects to the one-shot server with name +/// passed in as an argument and then sends a receiver which it has +/// already used to the server and then sends a test message to the +/// receiver. +fn main() { + let args: Vec = env::args().collect(); + let token = args.get(1).expect("missing argument"); + + let (sub_tx, sub_rx) = ipc::channel().unwrap(); + sub_tx.send("test message".to_string()).expect("send failed"); + let msg = sub_rx.recv().unwrap(); + assert_eq!("test message", msg); + + let tx: IpcSender> = IpcSender::connect(token.to_string()).expect("connect failed"); + tx.send(sub_rx).expect("send failed"); + sub_tx.send("test message".to_string()).expect("send failed"); + + process::exit(0); +} diff --git a/tests/integration_test.rs b/tests/integration_test.rs index 9fba4ed4..49f35565 100644 --- a/tests/integration_test.rs +++ b/tests/integration_test.rs @@ -73,3 +73,35 @@ fn spawn_receiver_sender_client() { result.code().expect("exit status code not available") ); } + +/// Test spawing a process which then acts as a client to a +/// one-shot server in the parent process. The client sends a +/// receiver, which it has already used, and then send a +/// message to the receiver. +#[cfg(not(any(feature = "force-inprocess", target_os = "android", target_os = "ios")))] +#[test] +fn spawn_used_receiver_sender_client() { + let executable_path: String = env!("CARGO_BIN_EXE_spawn_used_receiver_sender_client").to_string(); + + let (server, token) = + IpcOneShotServer::>::new().expect("Failed to create IPC one-shot server."); + + let mut command = process::Command::new(executable_path); + let child_process = command.arg(token); + + let mut child = child_process + .spawn() + .expect("Failed to start child process"); + + let (_rx, sub_rx) = server.accept().expect("accept failed"); + + let msg = sub_rx.recv().unwrap(); + assert_eq!("test message", msg); + + let result = child.wait().expect("wait for child process failed"); + assert!( + result.success(), + "child process failed with exit status code {}", + result.code().expect("exit status code not available") + ); +} From 642c8b32c4a9dd135866e0c43aaefa9e4db473ad Mon Sep 17 00:00:00 2001 From: Glyn Normington Date: Mon, 7 Apr 2025 16:33:21 +0100 Subject: [PATCH 6/6] cargo fmt --- src/bin/spawn_receiver_sender_client.rs | 7 +++++-- src/bin/spawn_used_receiver_sender_client.rs | 11 ++++++++--- src/test.rs | 2 +- tests/integration_test.rs | 11 ++++++----- 4 files changed, 20 insertions(+), 11 deletions(-) diff --git a/src/bin/spawn_receiver_sender_client.rs b/src/bin/spawn_receiver_sender_client.rs index 39306cbb..4fd15066 100644 --- a/src/bin/spawn_receiver_sender_client.rs +++ b/src/bin/spawn_receiver_sender_client.rs @@ -19,9 +19,12 @@ fn main() { let (sub_tx, sub_rx) = ipc::channel().unwrap(); - let tx: IpcSender> = IpcSender::connect(token.to_string()).expect("connect failed"); + let tx: IpcSender> = + IpcSender::connect(token.to_string()).expect("connect failed"); tx.send(sub_rx).expect("send failed"); - sub_tx.send("test message".to_string()).expect("send failed"); + sub_tx + .send("test message".to_string()) + .expect("send failed"); process::exit(0); } diff --git a/src/bin/spawn_used_receiver_sender_client.rs b/src/bin/spawn_used_receiver_sender_client.rs index 7c09fd1d..0743083a 100644 --- a/src/bin/spawn_used_receiver_sender_client.rs +++ b/src/bin/spawn_used_receiver_sender_client.rs @@ -19,13 +19,18 @@ fn main() { let token = args.get(1).expect("missing argument"); let (sub_tx, sub_rx) = ipc::channel().unwrap(); - sub_tx.send("test message".to_string()).expect("send failed"); + sub_tx + .send("test message".to_string()) + .expect("send failed"); let msg = sub_rx.recv().unwrap(); assert_eq!("test message", msg); - let tx: IpcSender> = IpcSender::connect(token.to_string()).expect("connect failed"); + let tx: IpcSender> = + IpcSender::connect(token.to_string()).expect("connect failed"); tx.send(sub_rx).expect("send failed"); - sub_tx.send("test message".to_string()).expect("send failed"); + sub_tx + .send("test message".to_string()) + .expect("send failed"); process::exit(0); } diff --git a/src/test.rs b/src/test.rs index 3458683a..1d483dda 100644 --- a/src/test.rs +++ b/src/test.rs @@ -177,7 +177,7 @@ fn embedded_receivers_used_before_and_after_transmission() { super_tx.send(person_and_receiver).unwrap(); let received_person_and_receiver = super_rx.recv().unwrap(); assert_eq!(received_person_and_receiver.0, person); - + sub_tx.send(person.clone()).unwrap(); let received_person2 = received_person_and_receiver.1.recv().unwrap(); assert_eq!(received_person2, person); diff --git a/tests/integration_test.rs b/tests/integration_test.rs index 49f35565..62b9eea5 100644 --- a/tests/integration_test.rs +++ b/tests/integration_test.rs @@ -51,8 +51,8 @@ fn spawn_one_shot_server_client() { fn spawn_receiver_sender_client() { let executable_path: String = env!("CARGO_BIN_EXE_spawn_receiver_sender_client").to_string(); - let (server, token) = - IpcOneShotServer::>::new().expect("Failed to create IPC one-shot server."); + let (server, token) = IpcOneShotServer::>::new() + .expect("Failed to create IPC one-shot server."); let mut command = process::Command::new(executable_path); let child_process = command.arg(token); @@ -81,10 +81,11 @@ fn spawn_receiver_sender_client() { #[cfg(not(any(feature = "force-inprocess", target_os = "android", target_os = "ios")))] #[test] fn spawn_used_receiver_sender_client() { - let executable_path: String = env!("CARGO_BIN_EXE_spawn_used_receiver_sender_client").to_string(); + let executable_path: String = + env!("CARGO_BIN_EXE_spawn_used_receiver_sender_client").to_string(); - let (server, token) = - IpcOneShotServer::>::new().expect("Failed to create IPC one-shot server."); + let (server, token) = IpcOneShotServer::>::new() + .expect("Failed to create IPC one-shot server."); let mut command = process::Command::new(executable_path); let child_process = command.arg(token);