From 797bb89035f45bb104d7273b72becf22a85b6f15 Mon Sep 17 00:00:00 2001 From: Huan-Cheng Chang Date: Tue, 26 Nov 2024 15:20:41 +0000 Subject: [PATCH] feat(jstzd): launch jstzd server with cli --- Cargo.toml | 2 +- crates/jstzd/src/lib.rs | 34 +++++++++++++++--- crates/jstzd/tests/main_test.rs | 61 +++++++++++++++++++++------------ 3 files changed, 71 insertions(+), 26 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 2a6b3199b..a06c118e9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -81,7 +81,7 @@ pretty_assertions = "1.4.1" proptest = "1.1" rand = "0.8" regex = "1" -reqwest = { version = "0.11.24", features = ["json"] } +reqwest = { version = "0.11.24", features = ["json", "blocking"] } reqwest-eventsource = "0.5.0" rust-embed = { version = "8.5.0", features = ["interpolate-folder-path"] } rustyline = "14.0.0" diff --git a/crates/jstzd/src/lib.rs b/crates/jstzd/src/lib.rs index 8f62b85e7..ae1f46b3b 100644 --- a/crates/jstzd/src/lib.rs +++ b/crates/jstzd/src/lib.rs @@ -2,6 +2,10 @@ mod config; pub mod docker; pub mod task; +use crate::task::{ + jstzd::{JstzdConfig, JstzdServer}, + utils::retry, +}; pub use config::BOOTSTRAP_CONTRACT_NAMES; use std::process::exit; @@ -12,10 +16,7 @@ pub const JSTZ_NATIVE_BRIDGE_ADDRESS: &str = "KT1GFiPkkTjd14oHe6MrBPiRh5djzRkVWc /// The `main` function for running jstzd pub async fn main(config_path: &Option) { match config::build_config(config_path).await { - Ok((_port, _config)) => { - // TODO: run JstzdServer here - println!("ready"); - } + Ok((port, config)) => run(port, config).await, Err(e) => { match config_path { Some(p) => eprintln!("failed to build config from {}: {:?}", p, e), @@ -25,3 +26,28 @@ pub async fn main(config_path: &Option) { } } } + +async fn run(port: u16, config: JstzdConfig) { + let mut server = JstzdServer::new(config, port); + if let Err(e) = server.run().await { + eprintln!("failed to run jstzd server: {:?}", e); + let _ = server.stop().await; + exit(1); + } + wait_for_server(&mut server).await; + + server.wait().await; + + println!("Shutting down"); + server.stop().await.unwrap(); +} + +async fn wait_for_server(server: &mut JstzdServer) { + let server_healthy = + retry(300, 100, || async { Ok(server.health_check().await) }).await; + if !server_healthy { + eprintln!("failed to run jstzd server: server never turned healthy"); + let _ = server.stop().await; + exit(1); + } +} diff --git a/crates/jstzd/tests/main_test.rs b/crates/jstzd/tests/main_test.rs index 33bde4bc5..a40cce282 100644 --- a/crates/jstzd/tests/main_test.rs +++ b/crates/jstzd/tests/main_test.rs @@ -1,7 +1,9 @@ -use assert_cmd::prelude::*; // Add methods on commands -use predicates::prelude::*; +use assert_cmd::prelude::{CommandCargoExt, OutputAssertExt}; +use octez::unused_port; +use predicates::prelude::predicate; +use std::thread; use std::{io::Write, process::Command}; -use tempfile::NamedTempFile; // Used for writing assertions // Run programs +use tempfile::NamedTempFile; #[test] fn unknown_command() -> Result<(), Box> { @@ -15,28 +17,45 @@ fn unknown_command() -> Result<(), Box> { Ok(()) } -#[test] -fn default_config() -> Result<(), Box> { - let mut cmd = Command::cargo_bin("jstzd")?; - - cmd.arg("run") - .assert() - .success() - .stdout(predicate::str::contains("ready")); - - Ok(()) -} - #[test] fn valid_config_file() -> Result<(), Box> { - let mut cmd = Command::cargo_bin("jstzd")?; + let port = unused_port(); let mut tmp_file = NamedTempFile::new().unwrap(); - tmp_file.write_all(r#"{"protocol":{"bootstrap_accounts":[["edpkuSLWfVU1Vq7Jg9FucPyKmma6otcMHac9zG4oU1KMHSTBpJuGQ2","6000000000"]]}}"#.as_bytes()).unwrap(); + tmp_file.write_all(format!(r#"{{"protocol":{{"bootstrap_accounts":[["edpkuSLWfVU1Vq7Jg9FucPyKmma6otcMHac9zG4oU1KMHSTBpJuGQ2","15000000000"]]}},"server_port":{}}}"#, port).as_bytes()).unwrap(); - cmd.args(["run", &tmp_file.path().to_string_lossy()]) - .assert() - .success() - .stdout(predicate::str::contains("ready")); + let handle = thread::spawn(move || { + Command::cargo_bin("jstzd") + .unwrap() + .args(["run", &tmp_file.path().to_string_lossy()]) + .assert() + .success() + // baker log writes to stderr + .stderr(predicate::str::contains( + "block ready for delegate: activator", + )); + }); + + let client = reqwest::blocking::Client::new(); + for _ in 0..30 { + thread::sleep(std::time::Duration::from_secs(1)); + if client + .get(&format!("http://localhost:{port}/health")) + .send() + .is_ok() + { + break; + } + } + + thread::sleep(std::time::Duration::from_secs(5)); + assert!(client + .put(&format!("http://localhost:{port}/shutdown")) + .send()? + .status() + .is_success()); + handle + .join() + .expect("jstzd should have been taken down without any error"); Ok(()) }