Skip to content
This repository has been archived by the owner on Nov 1, 2023. It is now read-only.

Deserialize the coverage files directly into the output files #3410

Merged
merged 8 commits into from
Aug 15, 2023
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
71 changes: 38 additions & 33 deletions src/agent/cobertura/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,25 +12,30 @@ impl CoberturaCoverage {

let mut writer = Writer::new_with_indent(cursor, b' ', 2);

self.write_xml(&mut writer)?;
self._write_xml(&mut writer)?;

let text = String::from_utf8(data)?;
Ok(text)
}
}

trait WriteXml {
fn write_xml<W: Write>(&self, writer: &mut Writer<W>) -> Result<()>;
pub trait WriteXml {
fn _write_xml<W: Write>(&self, writer: &mut Writer<W>) -> Result<()>;

fn write_xml<W: Write>(&self, writer: W) -> Result<()> {
let mut writer = Writer::new(writer);
self._write_xml(&mut writer)
}
}

// Only write optional fields if present.
impl<T> WriteXml for Option<T>
where
T: WriteXml,
{
fn write_xml<W: Write>(&self, writer: &mut Writer<W>) -> Result<()> {
fn _write_xml<W: Write>(&self, writer: &mut Writer<W>) -> Result<()> {
if let Some(value) = self {
value.write_xml(writer)?;
value._write_xml(writer)?;
}

Ok(())
Expand All @@ -41,9 +46,9 @@ impl<T> WriteXml for Vec<T>
where
T: WriteXml,
{
fn write_xml<W: Write>(&self, writer: &mut Writer<W>) -> Result<()> {
fn _write_xml<W: Write>(&self, writer: &mut Writer<W>) -> Result<()> {
for value in self {
value.write_xml(writer)?;
value._write_xml(writer)?;
}

Ok(())
Expand Down Expand Up @@ -101,7 +106,7 @@ pub struct CoberturaCoverage {
}

impl WriteXml for CoberturaCoverage {
fn write_xml<W: Write>(&self, writer: &mut Writer<W>) -> Result<()> {
fn _write_xml<W: Write>(&self, writer: &mut Writer<W>) -> Result<()> {
writer
.create_element("coverage")
.with_attributes([
Expand All @@ -116,8 +121,8 @@ impl WriteXml for CoberturaCoverage {
("timestamp", uint!(self.timestamp)),
])
.write_inner_content(|w| {
self.sources.write_xml(w)?;
self.packages.write_xml(w)?;
self.sources._write_xml(w)?;
self.packages._write_xml(w)?;

Ok(())
})?;
Expand All @@ -133,10 +138,10 @@ pub struct Sources {
}

impl WriteXml for Sources {
fn write_xml<W: Write>(&self, writer: &mut Writer<W>) -> Result<()> {
fn _write_xml<W: Write>(&self, writer: &mut Writer<W>) -> Result<()> {
writer
.create_element("sources")
.write_inner_content(|w| self.sources.write_xml(w))?;
.write_inner_content(|w| self.sources._write_xml(w))?;

Ok(())
}
Expand All @@ -149,7 +154,7 @@ pub struct Source {
}

impl WriteXml for Source {
fn write_xml<W: Write>(&self, writer: &mut Writer<W>) -> Result<()> {
fn _write_xml<W: Write>(&self, writer: &mut Writer<W>) -> Result<()> {
writer
.create_element("source")
.with_attributes([("path", string!(self.path))])
Expand All @@ -166,10 +171,10 @@ pub struct Packages {
}

impl WriteXml for Packages {
fn write_xml<W: Write>(&self, writer: &mut Writer<W>) -> Result<()> {
fn _write_xml<W: Write>(&self, writer: &mut Writer<W>) -> Result<()> {
writer
.create_element("packages")
.write_inner_content(|w| self.packages.write_xml(w))?;
.write_inner_content(|w| self.packages._write_xml(w))?;

Ok(())
}
Expand All @@ -191,7 +196,7 @@ pub struct Package {
}

impl WriteXml for Package {
fn write_xml<W: Write>(&self, writer: &mut Writer<W>) -> Result<()> {
fn _write_xml<W: Write>(&self, writer: &mut Writer<W>) -> Result<()> {
writer
.create_element("package")
.with_attributes([
Expand All @@ -200,7 +205,7 @@ impl WriteXml for Package {
("branch-rate", float!(self.branch_rate)),
("complexity", uint!(self.complexity)),
])
.write_inner_content(|w| self.classes.write_xml(w))?;
.write_inner_content(|w| self.classes._write_xml(w))?;

Ok(())
}
Expand All @@ -213,10 +218,10 @@ pub struct Classes {
}

impl WriteXml for Classes {
fn write_xml<W: Write>(&self, writer: &mut Writer<W>) -> Result<()> {
fn _write_xml<W: Write>(&self, writer: &mut Writer<W>) -> Result<()> {
writer
.create_element("classes")
.write_inner_content(|w| self.classes.write_xml(w))?;
.write_inner_content(|w| self.classes._write_xml(w))?;

Ok(())
}
Expand All @@ -241,7 +246,7 @@ pub struct Class {
}

impl WriteXml for Class {
fn write_xml<W: Write>(&self, writer: &mut Writer<W>) -> Result<()> {
fn _write_xml<W: Write>(&self, writer: &mut Writer<W>) -> Result<()> {
writer
.create_element("class")
.with_attributes([
Expand All @@ -252,8 +257,8 @@ impl WriteXml for Class {
("complexity", uint!(self.complexity)),
])
.write_inner_content(|w| {
self.methods.write_xml(w)?;
self.lines.write_xml(w)?;
self.methods._write_xml(w)?;
self.lines._write_xml(w)?;
Ok(())
})?;

Expand All @@ -268,10 +273,10 @@ pub struct Methods {
}

impl WriteXml for Methods {
fn write_xml<W: Write>(&self, writer: &mut Writer<W>) -> Result<()> {
fn _write_xml<W: Write>(&self, writer: &mut Writer<W>) -> Result<()> {
writer
.create_element("methods")
.write_inner_content(|w| self.methods.write_xml(w))?;
.write_inner_content(|w| self.methods._write_xml(w))?;

Ok(())
}
Expand All @@ -293,7 +298,7 @@ pub struct Method {
}

impl WriteXml for Method {
fn write_xml<W: Write>(&self, writer: &mut Writer<W>) -> Result<()> {
fn _write_xml<W: Write>(&self, writer: &mut Writer<W>) -> Result<()> {
writer
.create_element("method")
.with_attributes([
Expand All @@ -302,7 +307,7 @@ impl WriteXml for Method {
("line-rate", float!(self.line_rate)),
("branch-rate", float!(self.branch_rate)),
])
.write_inner_content(|w| self.lines.write_xml(w))?;
.write_inner_content(|w| self.lines._write_xml(w))?;

Ok(())
}
Expand All @@ -315,10 +320,10 @@ pub struct Lines {
}

impl WriteXml for Lines {
fn write_xml<W: Write>(&self, writer: &mut Writer<W>) -> Result<()> {
fn _write_xml<W: Write>(&self, writer: &mut Writer<W>) -> Result<()> {
writer
.create_element("lines")
.write_inner_content(|w| self.lines.write_xml(w))?;
.write_inner_content(|w| self.lines._write_xml(w))?;

Ok(())
}
Expand All @@ -340,7 +345,7 @@ pub struct Line {
}

impl WriteXml for Line {
fn write_xml<W: Write>(&self, writer: &mut Writer<W>) -> Result<()> {
fn _write_xml<W: Write>(&self, writer: &mut Writer<W>) -> Result<()> {
let condition_coverage = if let Some(s) = &self.condition_coverage {
s.as_str()
} else {
Expand All @@ -355,7 +360,7 @@ impl WriteXml for Line {
("branch", boolean!(self.branch.unwrap_or_default())),
("condition-coverage", condition_coverage),
])
.write_inner_content(|w| self.conditions.write_xml(w))?;
.write_inner_content(|w| self.conditions._write_xml(w))?;

Ok(())
}
Expand All @@ -368,10 +373,10 @@ pub struct Conditions {
}

impl WriteXml for Conditions {
fn write_xml<W: Write>(&self, writer: &mut Writer<W>) -> Result<()> {
fn _write_xml<W: Write>(&self, writer: &mut Writer<W>) -> Result<()> {
writer
.create_element("conditions")
.write_inner_content(|w| self.conditions.write_xml(w))?;
.write_inner_content(|w| self.conditions._write_xml(w))?;

Ok(())
}
Expand All @@ -389,7 +394,7 @@ pub struct Condition {
}

impl WriteXml for Condition {
fn write_xml<W: Write>(&self, writer: &mut Writer<W>) -> Result<()> {
fn _write_xml<W: Write>(&self, writer: &mut Writer<W>) -> Result<()> {
writer
.create_element("condition")
.with_attributes([
Expand Down
2 changes: 1 addition & 1 deletion src/agent/coverage/examples/cobertura.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ fn generate_output() -> Result<String> {
coverage.files.insert(file_path, file);
}

CoberturaCoverage::from(coverage).to_string()
CoberturaCoverage::from(&coverage).to_string()
}

#[cfg(test)]
Expand Down
2 changes: 1 addition & 1 deletion src/agent/coverage/examples/record.rs
Original file line number Diff line number Diff line change
Expand Up @@ -203,7 +203,7 @@ fn dump_source_line(binary: &BinaryCoverage, allowlist: AllowList) -> Result<()>

fn dump_cobertura(binary: &BinaryCoverage, allowlist: AllowList) -> Result<()> {
let source = coverage::source::binary_to_source_coverage(binary, allowlist)?;
let cobertura: CoberturaCoverage = source.into();
let cobertura: CoberturaCoverage = (&source).into();

println!("{}", cobertura.to_string()?);

Expand Down
6 changes: 3 additions & 3 deletions src/agent/coverage/src/cobertura.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ use crate::source::SourceCoverage;
// Dir -> Set<FilePath>
type FileMap<'a> = BTreeMap<&'a str, BTreeSet<&'a FilePath>>;

impl From<SourceCoverage> for CoberturaCoverage {
fn from(source: SourceCoverage) -> Self {
impl From<&SourceCoverage> for CoberturaCoverage {
fn from(source: &SourceCoverage) -> Self {
// The Cobertura data model is organized around `classes` and `methods` contained
// in `packages`. Our source coverage has no language-level assumptions.
//
Expand Down Expand Up @@ -51,7 +51,7 @@ impl From<SourceCoverage> for CoberturaCoverage {
// Iterate through the grouped files, accumulating `<package>` elements.
let (packages, hit_counts): (Vec<Package>, Vec<HitCounts>) = file_map
.into_iter()
.map(|(directory, files)| directory_to_package(&source, directory, files))
.map(|(directory, files)| directory_to_package(source, directory, files))
.unzip();

let hit_count: HitCounts = hit_counts.into_iter().sum();
Expand Down
3 changes: 1 addition & 2 deletions src/agent/coverage/src/source.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,14 +51,13 @@ impl From<Line> for u32 {

pub fn binary_to_source_coverage(
binary: &BinaryCoverage,
source_allowlist: impl Into<Option<AllowList>>,
source_allowlist: AllowList,
) -> Result<SourceCoverage> {
use std::collections::btree_map::Entry;

use symbolic::debuginfo::Object;
use symbolic::symcache::{SymCache, SymCacheConverter};

let source_allowlist = source_allowlist.into().unwrap_or_default();
let loader = Loader::new();

let mut source = SourceCoverage::default();
Expand Down
4 changes: 2 additions & 2 deletions src/agent/onefuzz-file-format/src/coverage/binary.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,8 @@ impl BinaryCoverageJson {
}

// Convert into the latest format.
impl From<BinaryCoverage> for BinaryCoverageJson {
fn from(source: BinaryCoverage) -> Self {
impl From<&BinaryCoverage> for BinaryCoverageJson {
fn from(source: &BinaryCoverage) -> Self {
v1::BinaryCoverageJson::from(source).into()
}
}
Expand Down
4 changes: 2 additions & 2 deletions src/agent/onefuzz-file-format/src/coverage/binary/v1.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@ pub struct ModuleCoverageJson {
pub blocks: BTreeMap<Hex, u32>,
}

impl From<BinaryCoverage> for BinaryCoverageJson {
fn from(binary: BinaryCoverage) -> Self {
impl From<&BinaryCoverage> for BinaryCoverageJson {
fn from(binary: &BinaryCoverage) -> Self {
let mut modules = BTreeMap::new();

for (path, offsets) in &binary.modules {
Expand Down
4 changes: 2 additions & 2 deletions src/agent/onefuzz-file-format/src/coverage/source.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,8 @@ impl SourceCoverageJson {
}

// Convert into the latest format.
impl From<SourceCoverage> for SourceCoverageJson {
fn from(source: SourceCoverage) -> Self {
impl From<&SourceCoverage> for SourceCoverageJson {
fn from(source: &SourceCoverage) -> Self {
v1::SourceCoverageJson::from(source).into()
}
}
Expand Down
8 changes: 4 additions & 4 deletions src/agent/onefuzz-file-format/src/coverage/source/v1.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,14 @@ pub struct FileCoverageJson {
pub lines: BTreeMap<LineNumber, HitCount>,
}

impl From<SourceCoverage> for SourceCoverageJson {
fn from(source: SourceCoverage) -> Self {
impl From<&SourceCoverage> for SourceCoverageJson {
fn from(source: &SourceCoverage) -> Self {
let mut json = SourceCoverageJson::default();

for (path, file) in source.files {
for (path, file) in &source.files {
let mut file_json = FileCoverageJson::default();

for (line, count) in file.lines {
for (line, count) in &file.lines {
let line_number = LineNumber(line.number());
let hit_count = count.0;
file_json.lines.insert(line_number, hit_count);
Expand Down
Loading
Loading