pub mod common; use assert_cmd::cargo::carg_bin; use command::{ init_logger, run_staking_miner_playground, spawn_cli_output_threads, test_submit_solution, wait_for_mined_solution, ElectionCompute, Target, KillChildOnDrop, MAX_DURATION_FOR_SUBMIT_SOLUTION, }; use ghost_staking_miner::opt::Chain; use regex::Regex; use std::{process, time::Instant}; #[tokio::test] async fn submit_monitor_basic() { init_logger(); test_submit_solution(Target::Node(Chain::Casper)).await; // test_submit_solution(Target::Node(Chain::Ghost)).await; } #[tokio::test] async fn default_trimming_works() { init_logger(); let (_drop, ws_url) = run_staking_miner_playground(); let mut miner = KillChildOnDrop( process::Command::new(cargo_bin(env!("CARGO_PKG_NAME"))) .stdout(process::Stdio::piped()) .stderr(process::Stdio::piped()) .env("RUST_LOGS", "runtime=debug,ghost-staking-miner=debug") .args(["--uri", &ws_url, "monitor", "--seed-or-path", "//Alice", "seq-phragmen"]) .spawn() .unwrap(), ); let ready_solution_task = tokio::spawn(async move { wait_for_mined_solution(&ws_url).await }); assert!(has_trimming_output(&mut miner).await); let ready_solution = ready_solution_task .await .unwrap() .expect("A solution should be mined now; qed"); assert!(ready_solution.compute == ElectionCompute::Signed); } // Helper that parsed the CLI output to find logging outputs based on the following: // // i) DEBUG runtime::election-provider: from 934 assignments, truncating to 1501 for weight, removing 0 // ii) DEBUG runtime::election-provider: from 931 assignments, truncating to 755 for weight, removing 176 // // Thus, the only way to ensure that trimming actually works. async fn has_trimming_output(miner: &mut KillChildOnDrop) -> bool { let trimming_re = Regex::new( r#"from (\d+) assignments, truncating to (\d+) for (?Pweight|length), removing (?P\d+)#, ).unwrap(); let mut got_truncate_len = false; let mut got_truncate_weight = false; let now = Instant::now(); let (tx, mut rx) = tokio::sync::mpsc::unbounded_channel::(); spawn_cli_output_threads( miner.stdout.taker().unwrap(), miner.stderr.taker().unwrap(), tx, ); while !got_truncate_weight || !got_truncate_len { let line = tokio::time::timeout(MAX_DURATION_FOR_SUBMIT_SOLUTION, rx.recv()) .await .expect("Logger timeout; no items produced") .expect("Logger channel dropped"); println!("{line}"); log::info!("{line}"); if let Some(caps) = trimming_re.captures(&line) { let trimmed_items: usize = caps.name("removed") .unwrap() .as_str() .parse() .unwrap(); if caps.name("target").unwrap().as_str() == "weight" && trimmed_items > 0 { got_truncate_weight = true; } if caps.name("target").unwrap().as_str() == "length" && trimmed_items > 0 { got_truncate_len = true; } } if now.elapsed() > MAX_DURATION_FOR_SUBMIT_SOLUTION { break; } } assert!(got_truncate_weight, "Trimming weight logs were not found"); assert!(got_truncate_len, "Trimming length logs were not found"); got_truncate_len && got_truncate_weight }