From c3ab5089e8dcaf725d9cabbf1d56dd1a82275ea4 Mon Sep 17 00:00:00 2001 From: Joe Ranweiler Date: Fri, 7 Jan 2022 14:58:37 -0800 Subject: [PATCH] Generate source-line coverage in task (#1535) --- .../src/tasks/coverage/generic.rs | 22 +++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/src/agent/onefuzz-agent/src/tasks/coverage/generic.rs b/src/agent/onefuzz-agent/src/tasks/coverage/generic.rs index 234d60615..7f546e4c1 100644 --- a/src/agent/onefuzz-agent/src/tasks/coverage/generic.rs +++ b/src/agent/onefuzz-agent/src/tasks/coverage/generic.rs @@ -12,6 +12,7 @@ use async_trait::async_trait; use coverage::block::CommandBlockCov; use coverage::cache::ModuleCache; use coverage::code::{CmdFilter, CmdFilterDef}; +use coverage::debuginfo::DebugInfo; use onefuzz::expand::{Expand, PlaceHolder}; use onefuzz::syncdir::SyncedDir; use onefuzz_telemetry::{warn, Event::coverage_data, EventData}; @@ -28,6 +29,7 @@ use crate::tasks::heartbeat::{HeartbeatSender, TaskHeartbeatClient}; const MAX_COVERAGE_RECORDING_ATTEMPTS: usize = 2; const COVERAGE_FILE: &str = "coverage.json"; +const SOURCE_COVERAGE_FILE: &str = "source-coverage.json"; const MODULE_CACHE_FILE: &str = "module-cache.json"; const DEFAULT_TARGET_TIMEOUT: Duration = Duration::from_secs(5); @@ -168,6 +170,7 @@ struct TaskContext<'a> { cache: Arc>, config: &'a Config, coverage: CommandBlockCov, + debuginfo: Mutex, filter: CmdFilter, heartbeat: Option, } @@ -181,11 +184,13 @@ impl<'a> TaskContext<'a> { heartbeat: Option, ) -> Self { let cache = Arc::new(Mutex::new(cache)); + let debuginfo = Mutex::new(DebugInfo::default()); Self { cache, config, coverage, + debuginfo, filter, heartbeat, } @@ -339,11 +344,24 @@ impl<'a> TaskContext<'a> { pub async fn save_and_sync_coverage(&self) -> Result<()> { let path = self.config.coverage.local_path.join(COVERAGE_FILE); - let text = serde_json::to_string(&self.coverage).context("serializing coverage to JSON")?; - + let text = serde_json::to_string(&self.coverage).context("serializing block coverage")?; fs::write(&path, &text) .await .with_context(|| format!("writing coverage to {}", path.display()))?; + + let path = self.config.coverage.local_path.join(SOURCE_COVERAGE_FILE); + let src_coverage = { + let mut debuginfo = self + .debuginfo + .lock() + .map_err(|e| anyhow::format_err!("{}", e))?; + self.coverage.source_coverage(&mut *debuginfo)? + }; + let text = serde_json::to_string(&src_coverage).context("serializing source coverage")?; + fs::write(&path, &text) + .await + .with_context(|| format!("writing source coverage to {}", path.display()))?; + self.config.coverage.sync_push().await?; Ok(())