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

Add key for block coverage, tests #2715

Merged
merged 3 commits into from
Dec 20, 2022
Merged
Show file tree
Hide file tree
Changes from all 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
7 changes: 4 additions & 3 deletions src/agent/coverage/src/binary.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,19 @@
use std::collections::{BTreeMap, BTreeSet};

use anyhow::{bail, Result};
use debuggable_module::{block, path::FilePath, Module, Offset};
use debuggable_module::Module;
pub use debuggable_module::{block, path::FilePath, Offset};
use symbolic::debuginfo::Object;
use symbolic::symcache::{SymCache, SymCacheConverter};

use crate::allowlist::TargetAllowList;

#[derive(Clone, Debug, Default)]
#[derive(Clone, Debug, Default, Eq, PartialEq)]
pub struct BinaryCoverage {
pub modules: BTreeMap<FilePath, ModuleBinaryCoverage>,
}

#[derive(Clone, Debug, Default)]
#[derive(Clone, Debug, Default, Eq, PartialEq)]
pub struct ModuleBinaryCoverage {
pub offsets: BTreeMap<Offset, Count>,
}
Expand Down
25 changes: 16 additions & 9 deletions src/agent/onefuzz-file-format/src/coverage/binary/v1.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,22 +13,29 @@ use crate::hex::Hex;
#[derive(Deserialize, Serialize)]
pub struct BinaryCoverageJson {
#[serde(flatten)]
pub modules: BTreeMap<String, BTreeMap<Hex, u32>>,
pub modules: BTreeMap<String, ModuleCoverageJson>,
}

#[derive(Deserialize, Serialize)]
pub struct ModuleCoverageJson {
pub blocks: BTreeMap<Hex, u32>,
}

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

for (module, offsets) in &binary.modules {
let mut map: BTreeMap<Hex, u32> = BTreeMap::new();
for (path, offsets) in &binary.modules {
let mut blocks: BTreeMap<Hex, u32> = BTreeMap::new();

for (offset, count) in offsets.as_ref() {
map.insert(Hex(offset.0), count.0);
blocks.insert(Hex(offset.0), count.0);
}

let path = module.as_str().to_owned();
modules.insert(path, map);
let path = path.as_str().to_owned();
let module = ModuleCoverageJson { blocks };

modules.insert(path, module);
}

Self { modules }
Expand All @@ -41,15 +48,15 @@ impl TryFrom<BinaryCoverageJson> for BinaryCoverage {
fn try_from(json: BinaryCoverageJson) -> Result<Self> {
let mut process = BinaryCoverage::default();

for (module, offsets) in json.modules {
for (path, module) in json.modules {
let mut coverage = ModuleBinaryCoverage::default();

for (hex, count) in offsets {
for (hex, count) in module.blocks {
let offset = Offset(hex.0);
coverage.offsets.insert(offset, Count(count));
}

let path = FilePath::new(module)?;
let path = FilePath::new(path)?;
process.modules.insert(path, coverage);
}

Expand Down
32 changes: 32 additions & 0 deletions src/agent/onefuzz-file-format/tests/files/binary-coverage.v0.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
[
{
"module": "/setup/main.exe",
"blocks": [
{
"offset": 1,
"count": 0
},
{
"offset": 300,
"count": 1
},
{
"offset": 5000,
"count": 0
}
]
},
{
"module": "/setup/lib/some.dll",
"blocks": [
{
"offset": 123,
"count": 0
},
{
"offset": 456,
"count": 10
}
]
}
]
15 changes: 15 additions & 0 deletions src/agent/onefuzz-file-format/tests/files/binary-coverage.v1.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"/setup/main.exe": {
"blocks": {
"1": 0,
"12c": 1,
"1388": 0
}
},
"/setup/lib/some.dll": {
"blocks": {
"7b": 0,
"1c8": 10
}
}
}
45 changes: 45 additions & 0 deletions src/agent/onefuzz-file-format/tests/integration.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

use pretty_assertions::assert_eq;

use anyhow::Result;
use coverage::binary::{BinaryCoverage, Count, FilePath, ModuleBinaryCoverage, Offset};
use onefuzz_file_format::coverage::binary::{v0, v1};

fn expected_binary_coverage() -> Result<BinaryCoverage> {
let main_exe_path = FilePath::new("/setup/main.exe")?;
let some_dll_path = FilePath::new("/setup/lib/some.dll")?;

let mut main_exe = ModuleBinaryCoverage::default();
main_exe.offsets.insert(Offset(1), Count(0));
main_exe.offsets.insert(Offset(300), Count(1));
main_exe.offsets.insert(Offset(5000), Count(0));

let mut some_dll = ModuleBinaryCoverage::default();
some_dll.offsets.insert(Offset(123), Count(0));
some_dll.offsets.insert(Offset(456), Count(10));

let mut binary = BinaryCoverage::default();
binary.modules.insert(some_dll_path, some_dll);
binary.modules.insert(main_exe_path, main_exe);

Ok(binary)
}

#[test]
fn test_binary_coverage_formats() -> Result<()> {
ranweiler marked this conversation as resolved.
Show resolved Hide resolved
let expected = expected_binary_coverage()?;

let v0_text = include_str!("files/binary-coverage.v0.json");
let v0_json: v0::BinaryCoverageJson = serde_json::from_str(v0_text)?;
let from_v0 = BinaryCoverage::try_from(v0_json)?;
assert_eq!(from_v0, expected);

let v1_text = include_str!("files/binary-coverage.v1.json");
let v1_json: v1::BinaryCoverageJson = serde_json::from_str(v1_text)?;
let from_v1 = BinaryCoverage::try_from(v1_json)?;
assert_eq!(from_v1, expected);

Ok(())
}