1
0
Fork 0
mirror of https://github.com/denoland/deno.git synced 2024-11-26 16:09:27 -05:00

fix(coverage): merge duplicate reports (#8942)

Merging multiple runs isn't quite right because we 
rely on a 0 count to signal that a block hasn't been called.

Other tools like c8 expect this to be true as-well so we 
need to do our best to merge coverage files rather 
than duplicating them.
This commit is contained in:
Casper Beyer 2021-01-05 00:01:21 +08:00 committed by GitHub
parent 3e5a3daf59
commit 4ca77ad84c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 85 additions and 27 deletions

View file

@ -3330,6 +3330,12 @@ itest!(deno_test_run_run_coverage {
exit_code: 0, exit_code: 0,
}); });
itest!(deno_test_run_combined_coverage {
args: "test --allow-all --coverage --unstable test_run_run_coverage.ts test_run_test_coverage.ts",
output: "test_run_combined_coverage.out",
exit_code: 0,
});
itest!(deno_lint { itest!(deno_lint {
args: "lint --unstable lint/file1.js lint/file2.ts lint/ignored_file.ts", args: "lint --unstable lint/file1.js lint/file2.ts lint/ignored_file.ts",
output: "lint/expected.out", output: "lint/expected.out",

View file

@ -1,3 +1,3 @@
import { returnsFoo2 } from "./subdir/mod1.ts"; import { returnsHi } from "./subdir/mod1.ts";
returnsFoo2(); returnsHi();

View file

@ -0,0 +1,31 @@
Check [WILDCARD]/tests/$deno$test.ts
running 2 tests
test spawn test ... Check [WILDCARD]/tests/run_coverage.ts
ok ([WILDCARD])
test spawn test ... Check [WILDCARD]/tests/$deno$test.ts
running 1 tests
test returnsFooSuccess ... ok ([WILDCARD])
test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out ([WILDCARD])
ok ([WILDCARD])
test result: ok. 2 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out ([WILDCARD])
cover [WILDCARD]/tests/run_coverage.ts ... 100.000% (3/3)
cover [WILDCARD]/tests/subdir/mod1.ts ... 57.143% (8/14)
8 | export function printHello3() {
9 | printHello2();
10 | }
11 | export function throwsError() {
12 | throw Error("exception from mod1");
13 | }
cover [WILDCARD]/tests/subdir/print_hello.ts ... 25.000% (1/4)
1 | export function printHello() {
2 | console.log("Hello");
3 | }
cover [WILDCARD]/tests/subdir/subdir2/mod2.ts ... 62.500% (5/8)
5 | export function printHello2() {
6 | printHello();
7 | }
cover [WILDCARD]/tests/test_coverage.ts ... 100.000% (5/5)

View file

@ -1,16 +1,15 @@
Check [WILDCARD]/$deno$test.ts Check [WILDCARD]/tests/$deno$test.ts
running 1 tests running 1 tests
test spawn test ... Check [WILDCARD]/run_coverage.ts test spawn test ... Check [WILDCARD]/tests/run_coverage.ts
ok ([WILDCARD]) ok ([WILDCARD])
test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out ([WILDCARD]) test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out ([WILDCARD])
cover [WILDCARD]/tests/run_coverage.ts ... 100.000% (3/3) cover [WILDCARD]/tests/run_coverage.ts ... 100.000% (3/3)
cover [WILDCARD]/tests/subdir/mod1.ts ... 35.714% (5/14) cover [WILDCARD]/tests/subdir/mod1.ts ... 35.714% (5/14)
2 | export function returnsHi() { 5 | export function returnsFoo2() {
3 | return "Hi"; 6 | return returnsFoo();
4 | } 7 | }
-----|-----
8 | export function printHello3() { 8 | export function printHello3() {
9 | printHello2(); 9 | printHello2();
10 | } 10 | }
@ -21,7 +20,10 @@ cover [WILDCARD]/tests/subdir/print_hello.ts ... 25.000% (1/4)
1 | export function printHello() { 1 | export function printHello() {
2 | console.log("Hello"); 2 | console.log("Hello");
3 | } 3 | }
cover [WILDCARD]/tests/subdir/subdir2/mod2.ts ... 62.500% (5/8) cover [WILDCARD]/tests/subdir/subdir2/mod2.ts ... 25.000% (2/8)
2 | export function returnsFoo() {
3 | return "Foo";
4 | }
5 | export function printHello2() { 5 | export function printHello2() {
6 | printHello(); 6 | printHello();
7 | } 7 | }

View file

@ -93,7 +93,7 @@ impl CoverageCollector {
// TODO(caspervonb) all of these structs can and should be made private, possibly moved to // TODO(caspervonb) all of these structs can and should be made private, possibly moved to
// inspector::protocol. // inspector::protocol.
#[derive(Debug, Serialize, Deserialize)] #[derive(Debug, Serialize, Deserialize, Clone)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
pub struct CoverageRange { pub struct CoverageRange {
pub start_offset: usize, pub start_offset: usize,
@ -101,7 +101,7 @@ pub struct CoverageRange {
pub count: usize, pub count: usize,
} }
#[derive(Debug, Serialize, Deserialize)] #[derive(Debug, Serialize, Deserialize, Clone)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
pub struct FunctionCoverage { pub struct FunctionCoverage {
pub function_name: String, pub function_name: String,
@ -109,7 +109,7 @@ pub struct FunctionCoverage {
pub is_block_coverage: bool, pub is_block_coverage: bool,
} }
#[derive(Debug, Serialize, Deserialize)] #[derive(Debug, Serialize, Deserialize, Clone)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
pub struct ScriptCoverage { pub struct ScriptCoverage {
pub script_id: String, pub script_id: String,
@ -117,7 +117,7 @@ pub struct ScriptCoverage {
pub functions: Vec<FunctionCoverage>, pub functions: Vec<FunctionCoverage>,
} }
#[derive(Debug, Serialize, Deserialize)] #[derive(Debug, Serialize, Deserialize, Clone)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
pub struct Coverage { pub struct Coverage {
pub script_coverage: ScriptCoverage, pub script_coverage: ScriptCoverage,
@ -237,29 +237,48 @@ fn collect_coverages(dir: &PathBuf) -> Result<Vec<Coverage>, AnyError> {
let entries = fs::read_dir(dir)?; let entries = fs::read_dir(dir)?;
for entry in entries { for entry in entries {
let json = fs::read_to_string(entry.unwrap().path())?; let json = fs::read_to_string(entry.unwrap().path())?;
let coverage: Coverage = serde_json::from_str(&json)?; let new_coverage: Coverage = serde_json::from_str(&json)?;
coverages.push(coverage); let existing_coverage = coverages
} .iter_mut()
.find(|x| x.script_coverage.url == new_coverage.script_coverage.url);
// TODO(caspervonb) drain_filter would make this cleaner, its nightly at the moment. if let Some(existing_coverage) = existing_coverage {
if coverages.len() > 1 { for new_function in new_coverage.script_coverage.functions {
coverages.sort_by_key(|k| k.script_coverage.url.clone()); let existing_function = existing_coverage
.script_coverage
.functions
.iter_mut()
.find(|x| x.function_name == new_function.function_name);
for i in (1..coverages.len() - 1).rev() { if let Some(existing_function) = existing_function {
if coverages[i].script_coverage.url for new_range in new_function.ranges {
== coverages[i - 1].script_coverage.url let existing_range =
{ existing_function.ranges.iter_mut().find(|x| {
let current = coverages.remove(i); x.start_offset == new_range.start_offset
let previous = &mut coverages[i - 1]; && x.end_offset == new_range.end_offset
});
for function in current.script_coverage.functions { if let Some(existing_range) = existing_range {
previous.script_coverage.functions.push(function); existing_range.count += new_range.count;
} else {
existing_function.ranges.push(new_range);
}
}
} else {
existing_coverage
.script_coverage
.functions
.push(new_function);
} }
} }
} else {
coverages.push(new_coverage);
} }
} }
coverages.sort_by_key(|k| k.script_coverage.url.clone());
Ok(coverages) Ok(coverages)
} }