mirror of
https://github.com/microsoft/onefuzz.git
synced 2025-06-18 04:38:09 +00:00
allow for more coverage data in total
(#519)
This commit is contained in:
@ -43,7 +43,7 @@ use onefuzz::{fs::list_files, libfuzzer::LibFuzzer, syncdir::SyncedDir};
|
|||||||
use onefuzz_telemetry::{Event::coverage_data, EventData};
|
use onefuzz_telemetry::{Event::coverage_data, EventData};
|
||||||
use reqwest::Url;
|
use reqwest::Url;
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
use std::collections::HashMap;
|
use std::collections::{BTreeMap, HashMap};
|
||||||
use std::{
|
use std::{
|
||||||
ffi::OsString,
|
ffi::OsString,
|
||||||
path::{Path, PathBuf},
|
path::{Path, PathBuf},
|
||||||
@ -197,7 +197,7 @@ pub struct CoverageProcessor {
|
|||||||
config: Arc<Config>,
|
config: Arc<Config>,
|
||||||
pub recorder: CoverageRecorder,
|
pub recorder: CoverageRecorder,
|
||||||
pub total: TotalCoverage,
|
pub total: TotalCoverage,
|
||||||
pub module_totals: HashMap<OsString, TotalCoverage>,
|
pub module_totals: BTreeMap<OsString, TotalCoverage>,
|
||||||
heartbeat_client: Option<TaskHeartbeatClient>,
|
heartbeat_client: Option<TaskHeartbeatClient>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -206,7 +206,7 @@ impl CoverageProcessor {
|
|||||||
let heartbeat_client = config.common.init_heartbeat().await?;
|
let heartbeat_client = config.common.init_heartbeat().await?;
|
||||||
let total = TotalCoverage::new(config.coverage.path.join(TOTAL_COVERAGE));
|
let total = TotalCoverage::new(config.coverage.path.join(TOTAL_COVERAGE));
|
||||||
let recorder = CoverageRecorder::new(config.clone());
|
let recorder = CoverageRecorder::new(config.clone());
|
||||||
let module_totals = HashMap::default();
|
let module_totals = BTreeMap::default();
|
||||||
|
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
config,
|
config,
|
||||||
@ -244,8 +244,9 @@ impl CoverageProcessor {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn collect_by_module(&mut self, path: &Path) -> Result<PathBuf> {
|
async fn collect_by_module(&mut self, path: &Path) -> Result<()> {
|
||||||
let files = list_files(&path).await?;
|
let mut files = list_files(&path).await?;
|
||||||
|
files.sort();
|
||||||
let mut sum = Vec::new();
|
let mut sum = Vec::new();
|
||||||
|
|
||||||
for file in &files {
|
for file in &files {
|
||||||
@ -264,14 +265,25 @@ impl CoverageProcessor {
|
|||||||
.await
|
.await
|
||||||
.with_context(|| format!("unable to write combined coverage file: {:?}", combined))?;
|
.with_context(|| format!("unable to write combined coverage file: {:?}", combined))?;
|
||||||
|
|
||||||
Ok(combined.into())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn test_input(&mut self, input: &Path) -> Result<()> {
|
pub async fn test_input(&mut self, input: &Path) -> Result<()> {
|
||||||
info!("processing input {:?}", input);
|
info!("processing input {:?}", input);
|
||||||
let new_coverage = self.recorder.record(input).await?;
|
let new_coverage = self.recorder.record(input).await?;
|
||||||
let combined = self.collect_by_module(&new_coverage).await?;
|
self.collect_by_module(&new_coverage).await?;
|
||||||
self.total.update(&combined).await?;
|
self.update_total().await?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn update_total(&mut self) -> Result<()> {
|
||||||
|
let mut total = Vec::new();
|
||||||
|
for module_total in self.module_totals.values() {
|
||||||
|
if let Some(mut module_data) = module_total.data().await? {
|
||||||
|
total.append(&mut module_data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
self.total.write(&total).await?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -43,22 +43,29 @@ impl TotalCoverage {
|
|||||||
&self.path
|
&self.path
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub async fn write(&self, data: &[u8]) -> Result<()> {
|
||||||
|
fs::write(self.path(), data).await?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
pub async fn update_bytes(&self, new_data: &[u8]) -> Result<()> {
|
pub async fn update_bytes(&self, new_data: &[u8]) -> Result<()> {
|
||||||
match self.data().await {
|
match self.data().await {
|
||||||
Ok(Some(mut total_data)) => {
|
Ok(Some(mut total_data)) => {
|
||||||
|
if total_data.len() < new_data.len() {
|
||||||
|
total_data.resize_with(new_data.len(), || 0);
|
||||||
|
}
|
||||||
for (i, b) in new_data.iter().enumerate() {
|
for (i, b) in new_data.iter().enumerate() {
|
||||||
if *b > 0 {
|
if *b > 0 {
|
||||||
total_data[i] = 1;
|
total_data[i] = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
self.write(&total_data).await?;
|
||||||
fs::write(self.path(), total_data).await?;
|
|
||||||
}
|
}
|
||||||
Ok(None) => {
|
Ok(None) => {
|
||||||
// Base case: we don't yet have any total coverage. Promote the
|
// Base case: we don't yet have any total coverage. Promote the
|
||||||
// new coverage to being our total coverage.
|
// new coverage to being our total coverage.
|
||||||
info!("initializing total coverage map {}", self.path().display());
|
info!("initializing total coverage map {}", self.path().display());
|
||||||
fs::write(self.path(), new_data).await?;
|
self.write(new_data).await?;
|
||||||
}
|
}
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
// Couldn't read total for some other reason, so this is a real error.
|
// Couldn't read total for some other reason, so this is a real error.
|
||||||
@ -69,11 +76,6 @@ impl TotalCoverage {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn update(&self, new: impl AsRef<Path>) -> Result<()> {
|
|
||||||
let new_data = fs::read(new).await?;
|
|
||||||
self.update_bytes(&new_data).await
|
|
||||||
}
|
|
||||||
|
|
||||||
pub async fn info(&self) -> Result<Info> {
|
pub async fn info(&self) -> Result<Info> {
|
||||||
let data = self
|
let data = self
|
||||||
.data()
|
.data()
|
||||||
|
Reference in New Issue
Block a user