c8
c8 copied to clipboard
bug: finally block in async function indicates incorrect missing block coverage
Observed Behavior
The following code:
async function abc() {
try {
return 'abc';
} finally {
console.log('in finally');
} // this is a covered line but uncovered branch
}
abc()
Ends up having the following coverage output:
{
"functionName": "abc",
"ranges": [
{
"startOffset": 0,
"endOffset": 146,
"count": 1
},
{
"startOffset": 97,
"endOffset": 145,
"count": 0
}
],
"isBlockCoverage": true
}
}
This indicates that the following characters were tracked as an uncovered block:
// this is a covered line but uncovered branch\n
Expected behavior
Coverage should be 100% in the above example.
I have created a tracking issue on v8 here:
https://bugs.chromium.org/p/v8/issues/detail?id=10628
I'm not sure if it's related, but I think I hit this? I happened to be on c8 v7.4.0 when I encountered the failure in CI, but it reproduces in v7.5.0 when run on node v12.20.1.
The tests pass, it's just the mysterious coverage gap on an async function that fails in node v12. v14 is fine.
https://github.com/dendrochronologist/cli/commit/edd0aaf93026f85df1aef64cd51d48bb3d6c700f "fixes" it by ignoring the missed line. Not ideal, long-term.
However, if I avoid using the async
keyword, it passes again:
diff --git a/src/api.ts b/src/api.ts
index 99472c5..69c22ef 100644
--- a/src/api.ts
+++ b/src/api.ts
@@ -9,7 +9,7 @@ interface RunOptions extends Partial<ParsedConfig> {
logger?: MinimalLogger;
}
-export async function run({
+export function run({
logger = processLogger(),
...options
}: RunOptions): Promise<Node> {
@@ -22,8 +22,5 @@ export async function run({
const arb = new Arborist({
path: cwd,
});
- const tree = await arb.loadVirtual().catch(() => arb.loadActual());
-
- return tree;
- /* c8 ignore next */
+ return arb.loadVirtual().catch(() => arb.loadActual());
}
I validated this locally with
volta run --node 12 npm test
To be clear, the node v14 I was passing with is v14.15.4. Which tracks, given the release of the linked back-porting. I have literally no idea if it could (or should?) be back-ported to v12, though it seems like a good candidate if someone has bandwidth?
@evocateur there are some v8 bug fixes that have landed in v14/v15, that I don't think got backported to v12 unfortunately -- I'm pretty sure that v12 might be closed to extension at this point unfortunately.
@bcoe Perfectly fair! Especially considering it's going into maintenance mode in like, 2 months? So I'll probably drop v12 before I even finish this wee babby of a tool, lol.
Just ran into this one as well. Rough one to debug. Any update regarding a fix?
I'm encountering something similar. My finally
block has a coverage of 26, while the keyword finally
has no coverage.
I'm using 5 finally
statements in the entire solution, 4 of them are working as expected, only this one has no coverage. I have no idea how this is possible.
I can send you a link to the code so you can see the problem yourself.
Update
Noticed that if you remove the throw
statement in the catch
block, that the finally
is hit. However the amount of hits seems wrong.
I'm also getting the same issue with a finally
block. But this is not an async function.
Everything is 100% covered but the branch reports a 96.15% coverage
I just added an ignore comment for now
@xolott would you be able to provide a minimal breaking example, this would help in investigating the underlying cause.
@bcoe I have run into a similar issue as reported by @xolott, where the generated output is showing the finally block as uncovered. If you are still interested in troubleshooting, here is a minimum example repro
EDIT: Just noticed that if you change the handler to finish without returning then the finally block is marked as covered:
await orchestrator.activate()