Skip to content

Commit

Permalink
fix: merge branch/statement/functionMap's together when merging two c…
Browse files Browse the repository at this point in the history
…overage reports (#617)
  • Loading branch information
JustinChristensen committed Sep 13, 2021
1 parent 0b6e022 commit ff1b5e9
Show file tree
Hide file tree
Showing 2 changed files with 92 additions and 38 deletions.
90 changes: 72 additions & 18 deletions packages/istanbul-lib-coverage/lib/file-coverage.js
Expand Up @@ -40,6 +40,47 @@ function assertValidObject(obj) {
}
}

const keyFromLoc = ({ start, end }) =>
`${start.line}|${start.column}|${end.line}|${end.column}`;

const mergeProp = (aHits, aMap, bHits, bMap, itemKey = keyFromLoc) => {
const aItems = Object.values(aHits).reduce((items, itemHits, i) => {
const item = aMap[i];
items[itemKey(item)] = [itemHits, item];
return items;
}, {});

Object.values(bHits).forEach((bItemHits, i) => {
const bItem = bMap[i];
const k = itemKey(bItem);

if (aItems[k]) {
const aPair = aItems[k];
if (bItemHits.forEach) {
// should this throw an exception if aPair[0] is not an array?
bItemHits.forEach((hits, h) => {
if (aPair[0][h] !== undefined) aPair[0][h] += hits;
else aPair[0][h] = hits;
});
} else {
aPair[0] += bItemHits;
}
} else {
aItems[k] = [bItemHits, bItem];
}
});

const hits = {};
const map = {};

Object.values(aItems).forEach(([itemHits, item], i) => {
hits[i] = itemHits;
map[i] = item;
});

return [hits, map];
};

/**
* provides a read-only view of coverage for a single file.
* The deep structure of this object is documented elsewhere. It has the following
Expand Down Expand Up @@ -166,24 +207,37 @@ class FileCoverage {
return;
}

Object.entries(other.s).forEach(([k, v]) => {
this.data.s[k] += v;
});
Object.entries(other.f).forEach(([k, v]) => {
this.data.f[k] += v;
});
Object.entries(other.b).forEach(([k, v]) => {
let i;
const retArray = this.data.b[k];
/* istanbul ignore if: is this even possible? */
if (!retArray) {
this.data.b[k] = v;
return;
}
for (i = 0; i < retArray.length; i += 1) {
retArray[i] += v[i];
}
});
let [hits, map] = mergeProp(
this.s,
this.statementMap,
other.s,
other.statementMap
);
this.data.s = hits;
this.data.statementMap = map;

const keyFromLocProp = x => keyFromLoc(x.loc);
const keyFromLocationsProp = x => keyFromLoc(x.locations[0]);

[hits, map] = mergeProp(
this.f,
this.fnMap,
other.f,
other.fnMap,
keyFromLocProp
);
this.data.f = hits;
this.data.fnMap = map;

[hits, map] = mergeProp(
this.b,
this.branchMap,
other.b,
other.branchMap,
keyFromLocationsProp
);
this.data.b = hits;
this.data.branchMap = map;
}

computeSimpleTotals(property) {
Expand Down
40 changes: 20 additions & 20 deletions packages/istanbul-lib-coverage/test/file.test.js
Expand Up @@ -153,36 +153,36 @@ describe('base coverage', () => {
const template = new FileCoverage({
path: '/path/to/file',
statementMap: {
1: loc(1, 1, 1, 100),
2: loc(2, 1, 2, 50),
3: loc(2, 51, 2, 100),
4: loc(2, 101, 3, 100)
0: loc(1, 1, 1, 100),
1: loc(2, 1, 2, 50),
2: loc(2, 51, 2, 100),
3: loc(2, 101, 3, 100)
},
fnMap: {
1: {
0: {
name: 'foobar',
line: 1,
loc: loc(1, 1, 1, 50)
}
},
branchMap: {
1: {
0: {
type: 'if',
line: 2,
locations: [loc(2, 1, 2, 20), loc(2, 50, 2, 100)]
}
},
s: {
0: 0,
1: 0,
2: 0,
3: 0,
4: 0
3: 0
},
f: {
1: 0
0: 0
},
b: {
1: [0, 0]
0: [0, 0]
}
});
const clone = function(obj) {
Expand All @@ -192,13 +192,13 @@ describe('base coverage', () => {
const c2 = new FileCoverage(clone(template));
let summary;

c1.s[1] = 1;
c1.f[1] = 1;
c1.b[1][0] = 1;
c1.s[0] = 1;
c1.f[0] = 1;
c1.b[0][0] = 1;

c2.s[2] = 1;
c2.f[1] = 1;
c2.b[1][1] = 2;
c2.s[1] = 1;
c2.f[0] = 1;
c2.b[0][1] = 2;
summary = c1.toSummary();
assert.ok(summary instanceof CoverageSummary);
assert.deepEqual(summary.statements, {
Expand Down Expand Up @@ -253,11 +253,11 @@ describe('base coverage', () => {
pct: 100
});

assert.equal(c1.s[0], 1);
assert.equal(c1.s[1], 1);
assert.equal(c1.s[2], 1);
assert.equal(c1.f[1], 2);
assert.equal(c1.b[1][0], 1);
assert.equal(c1.b[1][1], 2);
assert.equal(c1.f[0], 2);
assert.equal(c1.b[0][0], 1);
assert.equal(c1.b[0][1], 2);
});

it('drops all data during merges', () => {
Expand Down

0 comments on commit ff1b5e9

Please sign in to comment.