143 lines
6.4 KiB
Rust
143 lines
6.4 KiB
Rust
use std::process::{Command, Child, Stdio};
|
|
use std::time::Duration;
|
|
use std::path::PathBuf;
|
|
use tokio::time::sleep;
|
|
// tokio_tungstenite and direct futures_util for ws stream are no longer needed here
|
|
// use tokio_tungstenite::{connect_async, tungstenite::protocol::Message as WsMessage};
|
|
// use futures_util::{StreamExt, SinkExt};
|
|
// use serde_json::Value; // No longer needed as CircleWsClient::play takes String
|
|
// Uuid is handled by CircleWsClient internally for requests.
|
|
// use uuid::Uuid;
|
|
use circle_client_ws::CircleWsClient;
|
|
// PlayResultClient and CircleWsClientError will be resolved via the client methods if needed,
|
|
// or this indicates they were not actually needed in the scope of this file directly.
|
|
// The compiler warning suggests they are unused from this specific import.
|
|
|
|
const TEST_CIRCLE_NAME: &str = "e2e_test_circle";
|
|
const TEST_SERVER_PORT: u16 = 9876; // Choose a unique port for the test
|
|
const RHAI_WORKER_BIN_NAME: &str = "rhai_worker";
|
|
const CIRCLE_SERVER_WS_BIN_NAME: &str = "circle_server_ws";
|
|
|
|
// RAII guard for cleaning up child processes
|
|
struct ChildProcessGuard {
|
|
child: Child,
|
|
name: String,
|
|
}
|
|
|
|
impl ChildProcessGuard {
|
|
fn new(child: Child, name: String) -> Self {
|
|
Self { child, name }
|
|
}
|
|
}
|
|
|
|
impl Drop for ChildProcessGuard {
|
|
fn drop(&mut self) {
|
|
log::info!("Cleaning up {} process (PID: {})...", self.name, self.child.id());
|
|
match self.child.kill() {
|
|
Ok(_) => {
|
|
log::info!("Successfully sent kill signal to {} (PID: {}).", self.name, self.child.id());
|
|
// Optionally wait for a short period or check status
|
|
match self.child.wait() {
|
|
Ok(status) => log::info!("{} (PID: {}) exited with status: {}", self.name, self.child.id(), status),
|
|
Err(e) => log::warn!("Error waiting for {} (PID: {}): {}", self.name, self.child.id(), e),
|
|
}
|
|
}
|
|
Err(e) => log::error!("Failed to kill {} (PID: {}): {}", self.name, self.child.id(), e),
|
|
}
|
|
}
|
|
}
|
|
|
|
fn find_target_dir() -> Result<PathBuf, String> {
|
|
// Try to find the cargo target directory relative to current exe or manifest
|
|
let mut current_exe = std::env::current_exe().map_err(|e| format!("Failed to get current exe path: {}", e))?;
|
|
// current_exe is target/debug/examples/e2e_rhai_flow
|
|
// want target/debug/
|
|
if current_exe.ends_with("examples/e2e_rhai_flow") { // Adjust if example name changes
|
|
current_exe.pop(); // remove e2e_rhai_flow
|
|
current_exe.pop(); // remove examples
|
|
Ok(current_exe)
|
|
} else {
|
|
// Fallback: Assume 'target/debug' relative to workspace root if CARGO_MANIFEST_DIR is set
|
|
let manifest_dir = std::env::var("CARGO_MANIFEST_DIR").map_err(|_| "CARGO_MANIFEST_DIR not set".to_string())?;
|
|
let workspace_root = PathBuf::from(manifest_dir).parent().ok_or("Failed to get workspace root")?.to_path_buf();
|
|
Ok(workspace_root.join("target").join("debug"))
|
|
}
|
|
}
|
|
|
|
|
|
#[tokio::main]
|
|
async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|
env_logger::Builder::from_env(env_logger::Env::default().default_filter_or("info")).init();
|
|
|
|
let target_dir = find_target_dir().map_err(|e| {
|
|
log::error!("Could not determine target directory: {}", e);
|
|
e
|
|
})?;
|
|
|
|
let rhai_worker_path = target_dir.join(RHAI_WORKER_BIN_NAME);
|
|
let circle_server_ws_path = target_dir.join(CIRCLE_SERVER_WS_BIN_NAME);
|
|
|
|
if !rhai_worker_path.exists() {
|
|
return Err(format!("Rhai worker binary not found at {:?}. Ensure it's built (e.g., cargo build --package rhai_worker)", rhai_worker_path).into());
|
|
}
|
|
if !circle_server_ws_path.exists() {
|
|
return Err(format!("Circle server WS binary not found at {:?}. Ensure it's built (e.g., cargo build --package circle_server_ws)", circle_server_ws_path).into());
|
|
}
|
|
|
|
log::info!("Starting {}...", RHAI_WORKER_BIN_NAME);
|
|
let rhai_worker_process = Command::new(&rhai_worker_path)
|
|
.args(["--circles", TEST_CIRCLE_NAME])
|
|
.stdout(Stdio::piped()) // Capture stdout
|
|
.stderr(Stdio::piped()) // Capture stderr
|
|
.spawn()?;
|
|
let _rhai_worker_guard = ChildProcessGuard::new(rhai_worker_process, RHAI_WORKER_BIN_NAME.to_string());
|
|
log::info!("{} started with PID {}", RHAI_WORKER_BIN_NAME, _rhai_worker_guard.child.id());
|
|
|
|
log::info!("Starting {} for circle '{}' on port {}...", CIRCLE_SERVER_WS_BIN_NAME, TEST_CIRCLE_NAME, TEST_SERVER_PORT);
|
|
let circle_server_process = Command::new(&circle_server_ws_path)
|
|
.args(["--port", &TEST_SERVER_PORT.to_string(), "--circle-name", TEST_CIRCLE_NAME])
|
|
.stdout(Stdio::piped())
|
|
.stderr(Stdio::piped())
|
|
.spawn()?;
|
|
let _circle_server_guard = ChildProcessGuard::new(circle_server_process, CIRCLE_SERVER_WS_BIN_NAME.to_string());
|
|
log::info!("{} started with PID {}", CIRCLE_SERVER_WS_BIN_NAME, _circle_server_guard.child.id());
|
|
|
|
// Give servers a moment to start
|
|
sleep(Duration::from_secs(3)).await; // Increased sleep
|
|
|
|
let ws_url_str = format!("ws://127.0.0.1:{}/ws", TEST_SERVER_PORT);
|
|
|
|
log::info!("Creating CircleWsClient for {}...", ws_url_str);
|
|
let mut client = CircleWsClient::new(ws_url_str.clone());
|
|
|
|
log::info!("Connecting CircleWsClient...");
|
|
client.connect().await.map_err(|e| {
|
|
log::error!("CircleWsClient connection failed: {}", e);
|
|
format!("CircleWsClient connection failed: {}", e)
|
|
})?;
|
|
log::info!("CircleWsClient connected successfully.");
|
|
|
|
let script_to_run = "let a = 5; let b = 10; print(\"E2E Rhai: \" + (a+b)); a + b";
|
|
|
|
log::info!("Sending 'play' request via CircleWsClient for script: '{}'", script_to_run);
|
|
|
|
match client.play(script_to_run.to_string()).await {
|
|
Ok(play_result) => {
|
|
log::info!("Received play result: {:?}", play_result);
|
|
assert_eq!(play_result.output, "15");
|
|
log::info!("E2E Test Passed! Correct output '15' received via CircleWsClient.");
|
|
}
|
|
Err(e) => {
|
|
log::error!("CircleWsClient play request failed: {}", e);
|
|
return Err(format!("CircleWsClient play request failed: {}", e).into());
|
|
}
|
|
}
|
|
|
|
log::info!("Disconnecting CircleWsClient...");
|
|
client.disconnect().await;
|
|
log::info!("CircleWsClient disconnected.");
|
|
|
|
log::info!("E2E Rhai flow example completed successfully.");
|
|
// Guards will automatically clean up child processes when they go out of scope here
|
|
Ok(())
|
|
} |