From ce5ca7ddab6e0fd579deddcd02094b3f798bbe6a Mon Sep 17 00:00:00 2001 From: Armani Ferrante Date: Wed, 10 Feb 2021 01:04:18 +0800 Subject: [PATCH] cli: Stream program logs to file when testing --- CHANGELOG.md | 1 + cli/src/main.rs | 38 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 39 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index d3f18c30..7ba87e57 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,7 @@ incremented for features. ## [Unreleased] * cli: Embed workspace programs into local validator genesis when testing. +* cli: Stream program logs to `.anchor/program-logs` directory when testing. ## [0.2.0] - 2021-02-08 diff --git a/cli/src/main.rs b/cli/src/main.rs index 4bfea264..48f97838 100644 --- a/cli/src/main.rs +++ b/cli/src/main.rs @@ -603,6 +603,8 @@ fn test(skip_deploy: bool) -> Result<()> { } }; + let log_streams = stream_logs(&cfg.cluster.url())?; + // Run the tests. if let Err(e) = std::process::Command::new("mocha") .arg("-t") @@ -622,6 +624,10 @@ fn test(skip_deploy: bool) -> Result<()> { validator_handle.kill()?; } + for mut stream in log_streams { + stream.kill()?; + } + Ok(()) }) } @@ -652,6 +658,38 @@ fn genesis_flags() -> Result> { Ok(flags) } +fn stream_logs(url: &str) -> Result> { + let program_logs_dir = ".anchor/program-logs"; + if Path::new(program_logs_dir).exists() { + std::fs::remove_dir_all(program_logs_dir)?; + } + fs::create_dir_all(program_logs_dir)?; + let mut handles = vec![]; + for program in read_all_programs()? { + let mut file = File::open(&format!("target/idl/{}.json", program.lib_name))?; + let mut contents = vec![]; + file.read_to_end(&mut contents)?; + let idl: Idl = serde_json::from_slice(&contents)?; + let metadata = idl.metadata.ok_or(anyhow!("Program address not found."))?; + let metadata: IdlTestMetadata = serde_json::from_value(metadata)?; + + let log_file = File::create(format!( + "{}/{}.{}.log", + program_logs_dir, metadata.address, program.idl.name + ))?; + let stdio = std::process::Stdio::from(log_file); + let child = std::process::Command::new("solana") + .arg("logs") + .arg(metadata.address) + .arg("--url") + .arg(url) + .stdout(stdio) + .spawn()?; + handles.push(child); + } + Ok(handles) +} + #[derive(Debug, Serialize, Deserialize)] pub struct IdlTestMetadata { address: String,