Skip to content

Commit be11494

Browse files
authored
Stop reporting assert statements as branches (#556)
1 parent 19f1990 commit be11494

File tree

5 files changed

+26
-27
lines changed

5 files changed

+26
-27
lines changed

lib/coverage.js

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ class Coverage {
99

1010
constructor() {
1111
this.data = {};
12-
this.assertData = {};
12+
this.requireData = {};
1313
}
1414

1515
/**
@@ -30,7 +30,7 @@ class Coverage {
3030
statementMap: {},
3131
branchMap: {},
3232
};
33-
this.assertData[contractPath] = { };
33+
this.requireData[contractPath] = { };
3434

3535
info.runnableLines.forEach((item, idx) => {
3636
this.data[contractPath].l[info.runnableLines[idx]] = 0;
@@ -44,7 +44,7 @@ class Coverage {
4444
this.data[contractPath].branchMap = info.branchMap;
4545
for (let x = 1; x <= Object.keys(info.branchMap).length; x++) {
4646
this.data[contractPath].b[x] = [0, 0];
47-
this.assertData[contractPath][x] = {
47+
this.requireData[contractPath][x] = {
4848
preEvents: 0,
4949
postEvents: 0,
5050
};
@@ -76,19 +76,19 @@ class Coverage {
7676
case 'function': this.data[contractPath].f[id] = hits; break;
7777
case 'statement': this.data[contractPath].s[id] = hits; break;
7878
case 'branch': this.data[contractPath].b[id][data.locationIdx] = hits; break;
79-
case 'assertPre': this.assertData[contractPath][id].preEvents = hits; break;
80-
case 'assertPost': this.assertData[contractPath][id].postEvents = hits; break;
79+
case 'requirePre': this.requireData[contractPath][id].preEvents = hits; break;
80+
case 'requirePost': this.requireData[contractPath][id].postEvents = hits; break;
8181
}
8282
}
8383

8484
// Finally, interpret the assert pre/post events
85-
const contractPaths = Object.keys(this.assertData);
85+
const contractPaths = Object.keys(this.requireData);
8686

8787
for (let contractPath of contractPaths){
8888
const contract = this.data[contractPath];
8989

9090
for (let i = 1; i <= Object.keys(contract.b).length; i++) {
91-
const branch = this.assertData[contractPath][i];
91+
const branch = this.requireData[contractPath][i];
9292

9393
// Was it an assert branch?
9494
if (branch && branch.preEvents > 0){

lib/injector.js

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -158,8 +158,8 @@ class Injector {
158158
contract.instrumented = `${start}else { ${injectable}}${end}`;
159159
}
160160

161-
injectAssertPre(contract, fileName, injectionPoint, injection, instrumentation) {
162-
const type = 'assertPre';
161+
injectRequirePre(contract, fileName, injectionPoint, injection, instrumentation) {
162+
const type = 'requirePre';
163163
const id = `${fileName}:${injection.contractName}`;
164164

165165
const {
@@ -179,8 +179,8 @@ class Injector {
179179
contract.instrumented = `${start}${injectable}${end}`;
180180
}
181181

182-
injectAssertPost(contract, fileName, injectionPoint, injection, instrumentation) {
183-
const type = 'assertPost';
182+
injectRequirePost(contract, fileName, injectionPoint, injection, instrumentation) {
183+
const type = 'requirePost';
184184
const id = `${fileName}:${injection.contractName}`;
185185

186186
const {

lib/parse.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,8 @@ parse.FunctionCall = function(contract, expression) {
3939
// This makes sure we don't instrument a chain of expressions multiple times.
4040
if (expression.expression.type !== 'FunctionCall') {
4141
register.statement(contract, expression);
42-
if (expression.expression.name === 'assert' || expression.expression.name === 'require') {
43-
register.assertOrRequire(contract, expression);
42+
if (expression.expression.name === 'require') {
43+
register.requireBranch(contract, expression);
4444
}
4545
parse[expression.expression.type] &&
4646
parse[expression.expression.type](contract, expression.expression);

lib/registrar.js

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -152,7 +152,7 @@ class Registrar {
152152

153153
/**
154154
* Registers injections for branch measurements. This generic is consumed by
155-
* the `assert/require` and `if` registration methods.
155+
* the `require` and `if` registration methods.
156156
* @param {Object} contract instrumentation target
157157
* @param {Object} expression AST node
158158
*/
@@ -187,25 +187,25 @@ class Registrar {
187187
};
188188

189189
/**
190-
* Registers injections for assert/require statement measurements (branches)
190+
* Registers injections for require statement measurements (branches)
191191
* @param {Object} contract instrumentation target
192192
* @param {Object} expression AST node
193193
*/
194-
assertOrRequire(contract, expression) {
194+
requireBranch(contract, expression) {
195195
this.addNewBranch(contract, expression);
196196
this._createInjectionPoint(
197197
contract,
198198
expression.range[0],
199199
{
200-
type: 'injectAssertPre',
200+
type: 'injectRequirePre',
201201
branchId: contract.branchId,
202202
}
203203
);
204204
this._createInjectionPoint(
205205
contract,
206206
expression.range[1] + 2,
207207
{
208-
type: 'injectAssertPost',
208+
type: 'injectRequirePost',
209209
branchId: contract.branchId,
210210
}
211211
);

test/units/assert.js

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,10 @@ describe('asserts and requires', () => {
1616
beforeEach(() => coverage = new Coverage());
1717
after(async() => await api.finish());
1818

19-
it('should cover assert statements as `if` statements when they pass', async function() {
19+
// Assert was covered as a branch up to v0.7.11. But since those
20+
// conditions are never meant to be fullfilled (and assert is really for smt)
21+
// people disliked this...
22+
it('should *not* cover assert statements as branches (pass)', async function() {
2023
const contract = await util.bootstrapCoverage('assert/Assert', api);
2124
coverage.addContract(contract.instrumented, util.filePath);
2225
await contract.instance.a(true);
@@ -25,9 +28,7 @@ describe('asserts and requires', () => {
2528
assert.deepEqual(mapping[util.filePath].l, {
2629
5: 1,
2730
});
28-
assert.deepEqual(mapping[util.filePath].b, {
29-
1: [1, 0],
30-
});
31+
assert.deepEqual(mapping[util.filePath].b, {});
3132
assert.deepEqual(mapping[util.filePath].s, {
3233
1: 1,
3334
});
@@ -36,9 +37,9 @@ describe('asserts and requires', () => {
3637
});
3738
});
3839

39-
// NB: Truffle replays failing txs as .calls to obtain the revert reason from the return
40+
// NB: truffle/contract replays failing txs as .calls to obtain the revert reason from the return
4041
// data. Hence the 2X measurements.
41-
it('should cover assert statements as `if` statements when they fail', async function() {
42+
it('should *not* cover assert statements as branches (fail)', async function() {
4243
const contract = await util.bootstrapCoverage('assert/Assert', api);
4344
coverage.addContract(contract.instrumented, util.filePath);
4445

@@ -48,9 +49,7 @@ describe('asserts and requires', () => {
4849
assert.deepEqual(mapping[util.filePath].l, {
4950
5: 2,
5051
});
51-
assert.deepEqual(mapping[util.filePath].b, {
52-
1: [0, 2],
53-
});
52+
assert.deepEqual(mapping[util.filePath].b, {});
5453
assert.deepEqual(mapping[util.filePath].s, {
5554
1: 2,
5655
});

0 commit comments

Comments
 (0)