-
Notifications
You must be signed in to change notification settings - Fork 0
/
applyCoverageMap.js
120 lines (107 loc) · 3.85 KB
/
applyCoverageMap.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
/**
* @fileoverview
* This is a simple script that changes the coverage data generated by Deno
* so that it matches the coverage of the real files.
* It essentially performs two actions:
* - Replaces blob: urls with the path of the real files.
* - Offsets the values of coverage function ranges.
* If the contents of an imported file is changed, which is usually the case
* because import urls get replaced with blob: urls, the function ranges will
* be incorrect.
* Most of the work for fixing these things have already been done when
* generating the coverage map. This script only applies the data from the
* coverage map.
*/
import { join } from "https://deno.land/[email protected]/path/mod.ts";
import { mapIndex } from "./src/mapDiffOffsetsIndex.js";
/**
* @typedef DenoCoverageData
* @property {string} [url]
* @property {DenoCoverageFunctionData[]} [functions]
*/
/**
* @typedef DenoCoverageFunctionData
* @property {string} [functionName]
* @property {boolean} [isBlockCoverage]
* @property {DenoCoverageRangeData[]} [ranges]
*/
/**
* @typedef DenoCoverageRangeData
* @property {number} [startOffset]
* @property {number} [endOffset]
* @property {number} [count]
*/
/**
* @param {string} path
*/
async function assertIsDir(path) {
const fileInfo = await Deno.stat(path);
if (!fileInfo.isDirectory) {
throw new Error(`${path} is not a directory.`);
}
}
/**
* @param {string} coverageMapPath The absolute path to the directory containing the coverage map data generated fake-imports.
* @param {string} denoCoveragePath The absolute path to the directory containing the coverage data generated by Deno.
*/
export async function applyCoverageMap(coverageMapPath, denoCoveragePath) {
await assertIsDir(coverageMapPath);
await assertIsDir(denoCoveragePath);
// Collect all the entries in the coverage map directory.
/** @type {Map<string, import("./mod.js").CoverageMapEntry>} */
const collectedMapEntries = new Map();
const covMapPromises = [];
for await (const file of Deno.readDir(coverageMapPath)) {
const filePath = join(coverageMapPath, file.name);
const promise = (async () => {
const fileContent = await Deno.readTextFile(filePath);
const fileJson = JSON.parse(fileContent);
const castFileJson = /** @type {import("./mod.js").CoverageMapEntry} */ (fileJson);
collectedMapEntries.set(castFileJson.replacedUrl, castFileJson);
})();
covMapPromises.push(promise);
}
await Promise.all(covMapPromises);
// Apply the collected entries to the deno coverage directory.
const denoCoveragePromises = [];
for await (const file of Deno.readDir(denoCoveragePath)) {
const filePath = join(denoCoveragePath, file.name);
const promise = (async () => {
const oldContent = await Deno.readTextFile(filePath);
const coverageJson = /** @type {DenoCoverageData} */ (JSON.parse(oldContent));
if (!coverageJson.url) return;
const mappedEntry = collectedMapEntries.get(coverageJson.url);
if (!mappedEntry) return;
coverageJson.url = mappedEntry.originalUrl;
if (coverageJson.functions) {
for (const fn of coverageJson.functions) {
if (fn.ranges) {
for (const range of fn.ranges) {
if (range.startOffset != undefined) {
range.startOffset = mapIndex(
range.startOffset,
mappedEntry.diffOffsets,
);
}
if (range.endOffset != undefined) {
range.endOffset = mapIndex(
range.endOffset,
mappedEntry.diffOffsets,
);
}
}
}
}
}
const newContent = JSON.stringify(coverageJson, null, 2);
await Deno.writeTextFile(filePath, newContent);
})();
denoCoveragePromises.push(promise);
}
await Promise.all(denoCoveragePromises);
}
if (import.meta.main) {
const coverageMapPath = join(Deno.cwd(), Deno.args[0]);
const denoCoveragePath = join(Deno.cwd(), Deno.args[1]);
applyCoverageMap(coverageMapPath, denoCoveragePath);
}