Add try / catch unit tests (#857)
parent
01ab173845
commit
042a99e638
@ -0,0 +1,11 @@ |
||||
pragma solidity >=0.8.0 <0.9.0; |
||||
|
||||
contract Test { |
||||
function op(bool y) external { |
||||
require(y); |
||||
} |
||||
|
||||
function a(bool x) external { |
||||
try this.op(x) { } catch { } |
||||
} |
||||
} |
@ -0,0 +1,16 @@ |
||||
pragma solidity >=0.8.0 <0.9.0; |
||||
|
||||
contract Test { |
||||
function op(bool y) external returns (uint){ |
||||
require(y, "sorry"); |
||||
return 1; |
||||
} |
||||
|
||||
function a(bool x) external returns (uint) { |
||||
try this.op(x) returns (uint v) { |
||||
return v; |
||||
} catch Error(string memory /*reason*/) { |
||||
return 0; |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,29 @@ |
||||
pragma solidity >=0.8.0 <0.9.0; |
||||
|
||||
contract Test { |
||||
function op(uint y) external returns (uint){ |
||||
uint a = 100; |
||||
uint b = 0; |
||||
|
||||
if (y == 0) |
||||
return 0; |
||||
if (y == 1) |
||||
require(false, 'sorry'); |
||||
if (y == 2) |
||||
uint x = (a / b); |
||||
if (y == 3) |
||||
revert(); |
||||
} |
||||
|
||||
function a(uint x) external returns (uint) { |
||||
try this.op(x) returns (uint v) { |
||||
return 0; |
||||
} catch Error(string memory /*reason*/) { |
||||
return 1; |
||||
} catch Panic(uint /*errorCode*/) { |
||||
return 2; |
||||
} catch (bytes memory /*lowLevelData*/) { |
||||
return 3; |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,16 @@ |
||||
pragma solidity >=0.8.0 <0.9.0; |
||||
|
||||
contract Test { |
||||
function op(bool y) external returns (uint){ |
||||
uint x = 100 / 0; |
||||
return x; |
||||
} |
||||
|
||||
function a(bool x) external pure returns (uint) { |
||||
try this.op(x) returns (uint v) { |
||||
return v; |
||||
} catch Panic(uint /*errorCode*/) { |
||||
return 0; |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,15 @@ |
||||
pragma solidity >=0.8.0 <0.9.0; |
||||
|
||||
contract Test { |
||||
function op(bool y) external returns (uint){ |
||||
if (y == false) revert(); |
||||
} |
||||
|
||||
function a(bool x) external pure returns (uint) { |
||||
try this.op(x) returns (uint v) { |
||||
return v; |
||||
} catch (bytes memory /*lowLevelData*/) { |
||||
return 0; |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,123 @@ |
||||
const assert = require('assert'); |
||||
const util = require('./../util/util.js'); |
||||
const Coverage = require('./../../lib/coverage'); |
||||
const Api = require('./../../lib/api') |
||||
|
||||
describe.only('try / catch branches', () => { |
||||
let coverage; |
||||
let api; |
||||
|
||||
before(async () => api = new Api({silent: true})); |
||||
beforeEach(() => coverage = new Coverage()); |
||||
after(async() => await api.finish()); |
||||
|
||||
it('should cover a try/catch statement with empty blocks (success branch only)', async function() { |
||||
const contract = await util.bootstrapCoverage('try/try-catch-empty-blocks', api, this.provider, ); |
||||
coverage.addContract(contract.instrumented, util.filePath); |
||||
await contract.instance.a(true, contract.gas); |
||||
const mapping = coverage.generate(contract.data, util.pathPrefix); |
||||
|
||||
assert.deepEqual(mapping[util.filePath].l, { |
||||
5:1,9:1 |
||||
}); |
||||
assert.deepEqual(mapping[util.filePath].b, { |
||||
1:[1,0] |
||||
}); |
||||
assert.deepEqual(mapping[util.filePath].s, { |
||||
1:1,2:1 |
||||
}); |
||||
assert.deepEqual(mapping[util.filePath].f, { |
||||
1:1,2:1 |
||||
}); |
||||
}); |
||||
|
||||
it('should cover a try/catch statement with empty blocks (both branches)', async function() { |
||||
const contract = await util.bootstrapCoverage('try/try-catch-empty-blocks', api, this.provider, ); |
||||
coverage.addContract(contract.instrumented, util.filePath); |
||||
await contract.instance.a(true, contract.gas); |
||||
|
||||
try { await contract.instance.a(false, contract.gas) } catch(err) { /* ignore */ } |
||||
|
||||
const mapping = coverage.generate(contract.data, util.pathPrefix); |
||||
|
||||
assert.deepEqual(mapping[util.filePath].l, { |
||||
5:2,9:2 |
||||
}); |
||||
assert.deepEqual(mapping[util.filePath].b, { |
||||
1:[1,1] |
||||
}); |
||||
assert.deepEqual(mapping[util.filePath].s, { |
||||
1:2,2:2 |
||||
}); |
||||
assert.deepEqual(mapping[util.filePath].f, { |
||||
1:2,2:2 |
||||
}); |
||||
}); |
||||
|
||||
it('should cover a try/catch statement with an Error block (success branch only)', async function() { |
||||
const contract = await util.bootstrapCoverage('try/try-error-block', api, this.provider, ); |
||||
coverage.addContract(contract.instrumented, util.filePath); |
||||
await contract.instance.a(true, contract.gas); |
||||
|
||||
const mapping = coverage.generate(contract.data, util.pathPrefix); |
||||
|
||||
assert.deepEqual(mapping[util.filePath].l, { |
||||
5:1,6:1,10:1,11:1,13:0 |
||||
}); |
||||
assert.deepEqual(mapping[util.filePath].b, { |
||||
1:[1,0] |
||||
}); |
||||
assert.deepEqual(mapping[util.filePath].s, { |
||||
1:1,2:1,3:1,4:1,5:0 |
||||
}); |
||||
assert.deepEqual(mapping[util.filePath].f, { |
||||
1:1,2:1 |
||||
}); |
||||
}); |
||||
|
||||
it('should cover a try/catch statement with an Error block (both branches)', async function() { |
||||
const contract = await util.bootstrapCoverage('try/try-error-block', api, this.provider, ); |
||||
coverage.addContract(contract.instrumented, util.filePath); |
||||
|
||||
await contract.instance.a(true, contract.gas); |
||||
try { await contract.instance.a(false, contract.gas) } catch(err) { /* ignore */ } |
||||
|
||||
const mapping = coverage.generate(contract.data, util.pathPrefix); |
||||
|
||||
assert.deepEqual(mapping[util.filePath].l, { |
||||
5:2,6:1,10:2,11:1,13:1 |
||||
}); |
||||
assert.deepEqual(mapping[util.filePath].b, { |
||||
1:[1,1] |
||||
}); |
||||
assert.deepEqual(mapping[util.filePath].s, { |
||||
1:2,2:1,3:2,4:1,5:1 |
||||
}); |
||||
assert.deepEqual(mapping[util.filePath].f, { |
||||
1:2,2:2 |
||||
}); |
||||
}); |
||||
|
||||
it('should cover a try/catch statement with multi-block catch clauses (middle-block)', async function() { |
||||
const contract = await util.bootstrapCoverage('try/try-multi-block', api, this.provider, ); |
||||
coverage.addContract(contract.instrumented, util.filePath); |
||||
|
||||
await contract.instance.a(0, contract.gas); |
||||
try { await contract.instance.a(2, contract.gas) } catch(err) { /* ignore */ } |
||||
|
||||
const mapping = coverage.generate(contract.data, util.pathPrefix); |
||||
|
||||
assert.deepEqual(mapping[util.filePath].l, { |
||||
5:2,6:2,8:2,9:1,10:1,11:0,12:1,13:1,14:0,15:0,19:2,20:1,22:0,24:1,26:0 |
||||
}); |
||||
assert.deepEqual(mapping[util.filePath].b, { |
||||
1:[1,1],2:[0,1],3:[0,0],4:[1,0],5:[0,0] |
||||
}); |
||||
assert.deepEqual(mapping[util.filePath].s, { |
||||
1:2,2:2,3:2,4:1,5:1,6:0,7:1,8:1,9:0,10:0,11:2,12:1,13:0,14:1,15:0 |
||||
}); |
||||
assert.deepEqual(mapping[util.filePath].f, { |
||||
1:2,2:2 |
||||
}); |
||||
}); |
||||
}); |
Loading…
Reference in new issue