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

Commit

Permalink
Simplify handling of OS-sensitive test cases (#810)
Browse files Browse the repository at this point in the history
- Add `module!` test helper to let us always define tests paths using POSIX-style paths
- Use `serde_json::json!` macro for maintainable definitions of expected test results
  • Loading branch information
ranweiler authored Apr 15, 2021
1 parent d9eda00 commit 4d86765
Show file tree
Hide file tree
Showing 3 changed files with 75 additions and 74 deletions.
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"
146 changes: 73 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,43 @@ 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`.
fn module_path(posix_path: &str) -> Result<ModulePath> {
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_path("/onefuzz/main.exe")?;
let some_dll = module_path("/common/some.dll")?;

let mut coverage = CommandBlockCov::default();

Expand All @@ -295,87 +304,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_path("/onefuzz/main.exe")?;
let known_dll = module_path("/common/known.dll")?;
let unknown_dll = module_path("/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_path("/onefuzz/main.exe")?;
let some_dll = module_path("/common/some.dll")?;

let cov = {
let mut cov = CommandBlockCov::default();
Expand All @@ -387,17 +378,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(())
}
}

0 comments on commit 4d86765

Please sign in to comment.