Skip to content

Commit 9a29f98

Browse files
authoredJan 6, 2023
fix(coverage): flaky c8 coverage caused by parallel sourcemap constructing (#2591)
Co-authored-by: Vladimir <sleuths.slews0s@icloud.com> Fixes undefined
1 parent f8ac209 commit 9a29f98

File tree

4 files changed

+319
-36
lines changed

4 files changed

+319
-36
lines changed
 

‎packages/coverage-c8/src/provider.ts

+47-25
Original file line numberDiff line numberDiff line change
@@ -48,39 +48,61 @@ export class C8CoverageProvider implements CoverageProvider {
4848
takeCoverage()
4949
const report = createReport(this.ctx.config.coverage)
5050

51+
interface MapAndSource { map: RawSourceMap; source: string | undefined }
52+
type SourceMapMeta = { url: string; filepath: string } & MapAndSource
53+
5154
// add source maps
52-
const sourceMapMeta: Record<string, { map: RawSourceMap; source: string | undefined }> = {}
53-
await Promise.all(Array
55+
const sourceMapMeta: Record<SourceMapMeta['url'], MapAndSource> = {}
56+
57+
const entries = Array
5458
.from(this.ctx.vitenode.fetchCache.entries())
5559
.filter(i => !i[0].includes('/node_modules/'))
56-
.map(async ([file, { result }]) => {
57-
const map = result.map
58-
if (!map)
59-
return
60+
.map(([file, { result }]) => {
61+
if (!result.map)
62+
return null
6063

6164
const filepath = file.split('?')[0]
6265

63-
const url = _url.pathToFileURL(filepath).href
64-
65-
let code: string | undefined
66-
try {
67-
code = (await fs.readFile(filepath)).toString()
68-
}
69-
catch { }
70-
71-
// Vite does not report full path in sourcemap sources
72-
// so use an actual file path
73-
const sources = [url]
74-
75-
sourceMapMeta[url] = {
66+
return {
67+
filepath,
68+
url: _url.pathToFileURL(filepath).href,
69+
map: result.map,
7670
source: result.code,
77-
map: {
78-
sourcesContent: code ? [code] : undefined,
79-
...map,
80-
sources,
81-
},
8271
}
83-
}))
72+
})
73+
.filter((entry) => {
74+
if (!entry)
75+
return false
76+
77+
// Mappings and sourcesContent are needed for C8 to work
78+
return (
79+
entry.map.mappings.length > 0
80+
&& entry.map.sourcesContent
81+
&& entry.map.sourcesContent.length > 0
82+
&& entry.map.sourcesContent[0].length > 0
83+
)
84+
}) as SourceMapMeta[]
85+
86+
await Promise.all(entries.map(async ({ url, source, map, filepath }) => {
87+
let code: string | undefined
88+
try {
89+
code = (await fs.readFile(filepath)).toString()
90+
}
91+
catch { }
92+
93+
// Vite does not report full path in sourcemap sources
94+
// so use an actual file path
95+
const sources = [url]
96+
97+
sourceMapMeta[url] = {
98+
source,
99+
map: {
100+
sourcesContent: code ? [code] : undefined,
101+
...map,
102+
sources,
103+
},
104+
}
105+
}))
84106

85107
// This is a magic number. It corresponds to the amount of code
86108
// that we add in packages/vite-node/src/client.ts:114 (vm.runInThisContext)

‎test/coverage-test/coverage-report-tests/__snapshots__/c8.report.test.ts.snap

+182-8
Original file line numberDiff line numberDiff line change
@@ -809,19 +809,63 @@ exports[`c8 json report 1`] = `
809809
},
810810
"<process-cwd>/src/Defined.vue": {
811811
"all": false,
812-
"b": {},
813-
"branchMap": {},
812+
"b": {
813+
"0": [
814+
0,
815+
],
816+
},
817+
"branchMap": {
818+
"0": {
819+
"line": 6,
820+
"loc": {
821+
"end": {
822+
"column": 36,
823+
"line": 8,
824+
},
825+
"start": {
826+
"column": 33,
827+
"line": 6,
828+
},
829+
},
830+
"locations": [
831+
{
832+
"end": {
833+
"column": 36,
834+
"line": 8,
835+
},
836+
"start": {
837+
"column": 33,
838+
"line": 6,
839+
},
840+
},
841+
],
842+
"type": "branch",
843+
},
844+
},
814845
"f": {},
815846
"fnMap": {},
816847
"path": "<process-cwd>/src/Defined.vue",
817848
"s": {
818849
"0": 1,
819850
"1": 1,
851+
"10": 1,
852+
"11": 1,
853+
"12": 1,
854+
"13": 1,
855+
"14": 1,
856+
"15": 1,
857+
"16": 1,
858+
"17": 1,
859+
"18": 1,
860+
"19": 1,
820861
"2": 1,
821862
"3": 1,
822863
"4": 1,
823864
"5": 1,
824-
"6": 1,
865+
"6": 0,
866+
"7": 0,
867+
"8": 1,
868+
"9": 1,
825869
},
826870
"statementMap": {
827871
"0": {
@@ -844,9 +888,109 @@ exports[`c8 json report 1`] = `
844888
"line": 2,
845889
},
846890
},
891+
"10": {
892+
"end": {
893+
"column": 10,
894+
"line": 11,
895+
},
896+
"start": {
897+
"column": 0,
898+
"line": 11,
899+
},
900+
},
901+
"11": {
902+
"end": {
903+
"column": 15,
904+
"line": 12,
905+
},
906+
"start": {
907+
"column": 0,
908+
"line": 12,
909+
},
910+
},
911+
"12": {
912+
"end": {
913+
"column": 11,
914+
"line": 13,
915+
},
916+
"start": {
917+
"column": 0,
918+
"line": 13,
919+
},
920+
},
921+
"13": {
922+
"end": {
923+
"column": 0,
924+
"line": 14,
925+
},
926+
"start": {
927+
"column": 0,
928+
"line": 14,
929+
},
930+
},
931+
"14": {
932+
"end": {
933+
"column": 90,
934+
"line": 15,
935+
},
936+
"start": {
937+
"column": 0,
938+
"line": 15,
939+
},
940+
},
941+
"15": {
942+
"end": {
943+
"column": 25,
944+
"line": 16,
945+
},
946+
"start": {
947+
"column": 0,
948+
"line": 16,
949+
},
950+
},
951+
"16": {
952+
"end": {
953+
"column": 6,
954+
"line": 17,
955+
},
956+
"start": {
957+
"column": 0,
958+
"line": 17,
959+
},
960+
},
961+
"17": {
962+
"end": {
963+
"column": 25,
964+
"line": 18,
965+
},
966+
"start": {
967+
"column": 0,
968+
"line": 18,
969+
},
970+
},
971+
"18": {
972+
"end": {
973+
"column": 1,
974+
"line": 19,
975+
},
976+
"start": {
977+
"column": 0,
978+
"line": 19,
979+
},
980+
},
981+
"19": {
982+
"end": {
983+
"column": 8,
984+
"line": 20,
985+
},
986+
"start": {
987+
"column": 0,
988+
"line": 20,
989+
},
990+
},
847991
"2": {
848992
"end": {
849-
"column": 9,
993+
"column": 0,
850994
"line": 3,
851995
},
852996
"start": {
@@ -856,7 +1000,7 @@ exports[`c8 json report 1`] = `
8561000
},
8571001
"3": {
8581002
"end": {
859-
"column": 0,
1003+
"column": 31,
8601004
"line": 4,
8611005
},
8621006
"start": {
@@ -866,7 +1010,7 @@ exports[`c8 json report 1`] = `
8661010
},
8671011
"4": {
8681012
"end": {
869-
"column": 10,
1013+
"column": 12,
8701014
"line": 5,
8711015
},
8721016
"start": {
@@ -876,7 +1020,7 @@ exports[`c8 json report 1`] = `
8761020
},
8771021
"5": {
8781022
"end": {
879-
"column": 15,
1023+
"column": 34,
8801024
"line": 6,
8811025
},
8821026
"start": {
@@ -886,14 +1030,44 @@ exports[`c8 json report 1`] = `
8861030
},
8871031
"6": {
8881032
"end": {
889-
"column": 11,
1033+
"column": 4,
8901034
"line": 7,
8911035
},
8921036
"start": {
8931037
"column": 0,
8941038
"line": 7,
8951039
},
8961040
},
1041+
"7": {
1042+
"end": {
1043+
"column": 36,
1044+
"line": 8,
1045+
},
1046+
"start": {
1047+
"column": 0,
1048+
"line": 8,
1049+
},
1050+
},
1051+
"8": {
1052+
"end": {
1053+
"column": 9,
1054+
"line": 9,
1055+
},
1056+
"start": {
1057+
"column": 0,
1058+
"line": 9,
1059+
},
1060+
},
1061+
"9": {
1062+
"end": {
1063+
"column": 0,
1064+
"line": 10,
1065+
},
1066+
"start": {
1067+
"column": 0,
1068+
"line": 10,
1069+
},
1070+
},
8971071
},
8981072
},
8991073
"<process-cwd>/src/Hello.vue": {

‎test/coverage-test/coverage-report-tests/__snapshots__/istanbul.report.test.ts.snap

+77-3
Original file line numberDiff line numberDiff line change
@@ -256,14 +256,58 @@ exports[`istanbul json report 1`] = `
256256
},
257257
},
258258
"<process-cwd>/src/Defined.vue": {
259-
"b": {},
260-
"branchMap": {},
259+
"b": {
260+
"0": [
261+
1,
262+
0,
263+
],
264+
},
265+
"branchMap": {
266+
"0": {
267+
"loc": {
268+
"end": {
269+
"column": null,
270+
"line": 8,
271+
},
272+
"start": {
273+
"column": 0,
274+
"line": 5,
275+
},
276+
},
277+
"locations": [
278+
{
279+
"end": {
280+
"column": null,
281+
"line": 8,
282+
},
283+
"start": {
284+
"column": 0,
285+
"line": 5,
286+
},
287+
},
288+
{
289+
"end": {
290+
"column": null,
291+
"line": 8,
292+
},
293+
"start": {
294+
"column": 2,
295+
"line": 8,
296+
},
297+
},
298+
],
299+
"type": "if",
300+
},
301+
},
261302
"f": {},
262303
"fnMap": {},
263304
"path": "<process-cwd>/src/Defined.vue",
264305
"s": {
265306
"0": 1,
266307
"1": 1,
308+
"2": 1,
309+
"3": 0,
310+
"4": 1,
267311
},
268312
"statementMap": {
269313
"0": {
@@ -277,15 +321,45 @@ exports[`istanbul json report 1`] = `
277321
},
278322
},
279323
"1": {
324+
"end": {
325+
"column": null,
326+
"line": 8,
327+
},
328+
"start": {
329+
"column": 0,
330+
"line": 5,
331+
},
332+
},
333+
"2": {
280334
"end": {
281335
"column": null,
282336
"line": 6,
283337
},
284338
"start": {
285-
"column": 5,
339+
"column": 2,
286340
"line": 6,
287341
},
288342
},
343+
"3": {
344+
"end": {
345+
"column": null,
346+
"line": 8,
347+
},
348+
"start": {
349+
"column": 2,
350+
"line": 8,
351+
},
352+
},
353+
"4": {
354+
"end": {
355+
"column": null,
356+
"line": 12,
357+
},
358+
"start": {
359+
"column": 5,
360+
"line": 12,
361+
},
362+
},
289363
},
290364
},
291365
"<process-cwd>/src/Hello.vue": {

‎test/coverage-test/src/Defined.vue

+13
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,20 @@
11
<script setup lang="ts">
22
const defined = MY_CONSTANT
3+
4+
/* eslint-disable no-console */
5+
if (defined)
6+
console.log('Covered condition')
7+
else
8+
console.log('Uncovered condition')
39
</script>
410

511
<template>
612
{{ defined }}
713
</template>
14+
15+
<!-- Style block triggers a specific condition where sourcemaps used to break randomly -->
16+
<style lang="css" scoped>
17+
body {
18+
background-color: #FFF;
19+
}
20+
</style>

0 commit comments

Comments
 (0)
Please sign in to comment.