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

Simplify handling of OS-sensitive test cases #810

Merged
merged 3 commits into from
Apr 15, 2021
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
1 change: 1 addition & 0 deletions src/agent/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion src/agent/coverage/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -37,5 +37,5 @@ procfs = "0.9"

[dev-dependencies]
env_logger = "0.8"
serde_json = "1.0"
serde_json = { version = "1.0", features = ["preserve_order"] }
structopt = "0.3"
148 changes: 75 additions & 73 deletions src/agent/coverage/src/block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,9 @@ mod array {

#[cfg(test)]
mod tests {
use anyhow::Result;
use serde_json::json;

use super::*;

// Builds a `ModuleCov` from a vec of `(offset, counts)` tuples.
Expand Down Expand Up @@ -251,37 +254,45 @@ mod tests {
);
}

fn module_path(path: &str) -> ModulePath {
ModulePath::new(std::path::PathBuf::from(path)).unwrap()
// Given a POSIX-style path as a string, construct a valid absolute path for
// the target OS and return it as a checked `ModulePath`.
macro_rules! module {
ranweiler marked this conversation as resolved.
Show resolved Hide resolved
($posix_path: expr) => {{
let mut p = std::path::PathBuf::default();

// Ensure that the new path is absolute.
if cfg!(target_os = "windows") {
p.push("c:\\");
} else {
p.push("/");
}

// Remove any affixed POSIX path separators, then split on any
// internal separators and add each component to our accumulator
// path in an OS-specific way.
for c in $posix_path.trim_matches('/').split('/') {
p.push(c);
}

ModulePath::new(p)
}};
}

fn cmd_cov_from_vec(data: Vec<(&'static str, Vec<(u64, u32)>)>) -> CommandBlockCov {
fn cmd_cov_from_vec(data: Vec<(&ModulePath, Vec<(u64, u32)>)>) -> CommandBlockCov {
let mut cov = CommandBlockCov::default();

for (path, module_data) in data {
let module_cov = from_vec(module_data);
cov.modules.insert(module_path(path), module_cov);
cov.modules.insert(path.clone(), module_cov);
}

cov
}

#[test]
fn test_cmd_cov_increment() {
#[cfg(target_os = "linux")]
const MAIN_EXE: &str = "/main.exe";

#[cfg(target_os = "linux")]
const SOME_DLL: &str = "/lib/some.dll";

#[cfg(target_os = "windows")]
const MAIN_EXE: &str = r"c:\main.exe";

#[cfg(target_os = "windows")]
const SOME_DLL: &str = r"c:\lib\some.dll";

let main_exe = module_path(MAIN_EXE);
let some_dll = module_path(SOME_DLL);
fn test_cmd_cov_increment() -> Result<()> {
let main_exe = module!("/onefuzz/main.exe")?;
let some_dll = module!("/common/some.dll")?;

let mut coverage = CommandBlockCov::default();

Expand All @@ -295,87 +306,69 @@ mod tests {
coverage.increment(&some_dll, 789);

let expected = cmd_cov_from_vec(vec![
(MAIN_EXE, vec![(1, 0), (20, 1), (300, 0)]),
(SOME_DLL, vec![(123, 1), (456, 1), (789, 1)]),
(&main_exe, vec![(1, 0), (20, 1), (300, 0)]),
(&some_dll, vec![(123, 1), (456, 1), (789, 1)]),
]);

assert_eq!(coverage, expected);

Ok(())
}

#[test]
fn test_cmd_cov_merge_max() {
#[cfg(target_os = "linux")]
const MAIN_EXE: &str = "/main.exe";

#[cfg(target_os = "linux")]
const KNOWN_DLL: &str = "/lib/known.dll";

#[cfg(target_os = "linux")]
const UNKNOWN_DLL: &str = "/usr/lib/unknown.dll";

#[cfg(target_os = "windows")]
const MAIN_EXE: &str = r"c:\main.exe";

#[cfg(target_os = "windows")]
const KNOWN_DLL: &str = r"c:\lib\known.dll";

#[cfg(target_os = "windows")]
const UNKNOWN_DLL: &str = r"c:\usr\lib\unknown.dll";
fn test_cmd_cov_merge_max() -> Result<()> {
let main_exe = module!("/onefuzz/main.exe")?;
let known_dll = module!("/common/known.dll")?;
let unknown_dll = module!("/other/unknown.dll")?;

let mut total = cmd_cov_from_vec(vec![
(MAIN_EXE, vec![(2, 0), (40, 1), (600, 0), (8000, 1)]),
(KNOWN_DLL, vec![(1, 1), (30, 1), (500, 0), (7000, 0)]),
(&main_exe, vec![(2, 0), (40, 1), (600, 0), (8000, 1)]),
(&known_dll, vec![(1, 1), (30, 1), (500, 0), (7000, 0)]),
]);

let new = cmd_cov_from_vec(vec![
(MAIN_EXE, vec![(2, 1), (40, 0), (600, 0), (8000, 0)]),
(KNOWN_DLL, vec![(1, 0), (30, 0), (500, 1), (7000, 1)]),
(UNKNOWN_DLL, vec![(123, 0), (456, 1)]),
(&main_exe, vec![(2, 1), (40, 0), (600, 0), (8000, 0)]),
(&known_dll, vec![(1, 0), (30, 0), (500, 1), (7000, 1)]),
(&unknown_dll, vec![(123, 0), (456, 1)]),
]);

total.merge_max(&new);

let expected = cmd_cov_from_vec(vec![
(MAIN_EXE, vec![(2, 1), (40, 1), (600, 0), (8000, 1)]),
(KNOWN_DLL, vec![(1, 1), (30, 1), (500, 1), (7000, 1)]),
(UNKNOWN_DLL, vec![(123, 0), (456, 1)]),
(&main_exe, vec![(2, 1), (40, 1), (600, 0), (8000, 1)]),
(&known_dll, vec![(1, 1), (30, 1), (500, 1), (7000, 1)]),
(&unknown_dll, vec![(123, 0), (456, 1)]),
]);

assert_eq!(total, expected);

Ok(())
}

#[test]
fn test_block_cov_serde() {
fn test_block_cov_serde() -> Result<()> {
let block = BlockCov {
offset: 123,
count: 456,
};

let ser = serde_json::to_string(&block).unwrap();
let ser = serde_json::to_string(&block)?;

let text = r#"{"offset":123,"count":456}"#;

assert_eq!(ser, text);

let de: BlockCov = serde_json::from_str(&ser).unwrap();
let de: BlockCov = serde_json::from_str(&ser)?;

assert_eq!(de, block);

Ok(())
}

#[test]
fn test_cmd_cov_serde() {
#[cfg(target_os = "linux")]
const MAIN_EXE: &str = "/main.exe";

#[cfg(target_os = "linux")]
const SOME_DLL: &str = "/lib/some.dll";

#[cfg(target_os = "windows")]
const MAIN_EXE: &str = r"c:\main.exe";

#[cfg(target_os = "windows")]
const SOME_DLL: &str = r"c:\lib\some.dll";

let main_exe = module_path(MAIN_EXE);
let some_dll = module_path(SOME_DLL);
fn test_cmd_cov_serde() -> Result<()> {
let main_exe = module!("/onefuzz/main.exe")?;
let some_dll = module!("/common/some.dll")?;

let cov = {
let mut cov = CommandBlockCov::default();
Expand All @@ -387,17 +380,26 @@ mod tests {
cov
};

let ser = serde_json::to_string(&cov).unwrap();

#[cfg(target_os = "linux")]
let text = r#"{"/lib/some.dll":[{"offset":2,"count":0},{"offset":30,"count":1},{"offset":400,"count":0}],"/main.exe":[{"offset":1,"count":1},{"offset":20,"count":0},{"offset":300,"count":1}]}"#;

#[cfg(target_os = "windows")]
let text = r#"{"c:\\lib\\some.dll":[{"offset":2,"count":0},{"offset":30,"count":1},{"offset":400,"count":0}],"c:\\main.exe":[{"offset":1,"count":1},{"offset":20,"count":0},{"offset":300,"count":1}]}"#;
let ser = serde_json::to_string(&cov)?;

let text = serde_json::to_string(&json!({
some_dll.to_string(): [
{"offset":2,"count":0},
{"offset":30,"count":1},
{"offset":400,"count":0},
],
main_exe.to_string(): [
{"offset":1,"count":1},
{"offset":20,"count":0},
{"offset":300,"count":1},
],
}))?;

assert_eq!(ser, text);

let de: CommandBlockCov = serde_json::from_str(&ser).unwrap();
let de: CommandBlockCov = serde_json::from_str(&ser)?;
assert_eq!(de, cov);

Ok(())
}
}