From 8c131950d103bed6a7c5cd7754ce160276fd459f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=A1s=20Venturo?= Date: Thu, 16 May 2019 21:42:22 -0300 Subject: [PATCH] Rename shouldFail to expectRevert (#39) * Rename shouldFail to expectFailure. * Fix exports. * Refactor expectRevert and change API. * Update src/expectRevert.js Co-Authored-By: Francisco Giordano * Update CHANGELOG.md Co-Authored-By: Francisco Giordano * Update CHANGELOG.md Co-Authored-By: Francisco Giordano * Update src/expectRevert.js Co-Authored-By: Francisco Giordano * Update src/expectRevert.js Co-Authored-By: Francisco Giordano * Fix output message. * Add assertFailure helper. * Update tests and integration tests to use the new API. * update documentation for expectRevert * Update README.md --- .eslintrc | 1 + CHANGELOG.md | 12 +- README.md | 30 ++-- contracts/Failer.sol | 34 ---- contracts/Reverter.sol | 38 ++++ index.js | 2 +- src/expectRevert.js | 52 ++++++ src/shouldFail.js | 71 -------- .../ganache-core-2.1.x/test/Tested.test.js | 6 +- .../test/Tested.test.js | 6 +- test/helpers/assertFailure.js | 12 ++ test/src/expectEvent.test.js | 28 +-- test/src/expectRevert.test.js | 162 ++++++++++++++++++ test/src/send.test.js | 10 +- test/src/shouldFail.test.js | 125 -------------- test/src/time.test.js | 6 +- 16 files changed, 318 insertions(+), 277 deletions(-) delete mode 100644 contracts/Failer.sol create mode 100644 contracts/Reverter.sol create mode 100644 src/expectRevert.js delete mode 100644 src/shouldFail.js create mode 100644 test/helpers/assertFailure.js create mode 100644 test/src/expectRevert.test.js delete mode 100644 test/src/shouldFail.test.js diff --git a/.eslintrc b/.eslintrc index e4cc9f2..3d44292 100644 --- a/.eslintrc +++ b/.eslintrc @@ -33,6 +33,7 @@ "no-dupe-args": "error", "no-dupe-keys": "error", "no-mixed-spaces-and-tabs": ["error", "smart-tabs"], + "no-multi-str": "off", "no-redeclare": ["error", {"builtinGlobals": true}], "no-trailing-spaces": ["error", { "skipBlankLines": false }], "no-undef": "error", diff --git a/CHANGELOG.md b/CHANGELOG.md index d44aa7c..32add2a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,10 +6,18 @@ * `shouldFail.reverting.withMessage` fails if no error string is provided. ([#28](https://github.com/OpenZeppelin/openzeppelin-test-helpers/pull/28) * Rename `makeInterfaceId` to `makeInterfaceId.ERC165`, and add `makeInterfaceId.ERC1820`. ([#21](https://github.com/OpenZeppelin/openzeppelin-test-helpers/pull/21) * Add possibility to configure a custom web3 instance. ([#38](https://github.com/OpenZeppelin/openzeppelin-test-helpers/pull/38)) - + * Replace `shouldFail` with `expectRevert`, with an improved API. ([#39](https://github.com/OpenZeppelin/openzeppelin-test-helpers/pull/39)) + #### How to upgrade from 0.3 - Change all occurences of `makeInterfaceId` to `makeInterfaceId.ERC165`. -- Some uses of `shouldFail.reverting.withMessage` may fail now. This means it was being used incorrectly and an error string to match against should be added. Alternatively, if the error message is unknown, use `shouldFail.reverting` instead. +- The `shouldFail` module has been renamed to `expectRevert`, and `reverting.withMessage` is now the main module export. + +| 0.3 | 0.4 | +| ---------------------------------- | ---------------------------- | +| `shouldFail.reverting.withMessage` | `expectRevert` | +| `shouldFail.reverting` | `expectRevert.unspecified` | +| `shouldFail.throwing` | `expectRevert.invalidOpcode` | +| `shouldFail.outOfGas` | `expectRevert.outOfGas` | ## 0.3.2 (2019-04-10) * Update ERC1820Registry address. ([#26](https://github.com/OpenZeppelin/openzeppelin-test-helpers/pull/26)) diff --git a/README.md b/README.md index 0a99937..eba9fcd 100644 --- a/README.md +++ b/README.md @@ -15,7 +15,7 @@ npm install --save-dev openzeppelin-test-helpers ```javascript // Import all required modules from openzeppelin-test-helpers -const { BN, constants, expectEvent, shouldFail } = require('openzeppelin-test-helpers'); +const { BN, constants, expectEvent, expectRevert } = require('openzeppelin-test-helpers'); // Import preferred chai flavor: both expect and should are supported const { expect } = require('chai'); @@ -30,7 +30,7 @@ contract('ERC20', ([sender, receiver]) => { it('reverts when transferring tokens to the zero address', async function () { // Edge cases that trigger a require statement can be tested for, optionally checking the revert reason as well - await shouldFail.reverting(this.erc20.transfer(constants.ZERO_ADDRESS, this.value, { from: sender })); + await expectRevert.unspecified(this.erc20.transfer(constants.ZERO_ADDRESS, this.value, { from: sender })); }); it('emits a Transfer event on successful transfers', async function () { @@ -177,14 +177,11 @@ A chai [should](https://www.chaijs.com/api/bdd/) instance, containing the `bignu --- -### shouldFail -Collection of assertions for failures (similar to [chai's `throw`](https://www.chaijs.com/api/bdd/#method_throw)). `shouldFail` will accept any exception type, but more specific functions exist and their usage is encouraged. +### expectRevert +Collection of assertions for transaction errors (similar to [chai's `throw`](https://www.chaijs.com/api/bdd/#method_throw)). -#### async shouldFail.reverting (promise) -Only accepts failures caused due to an EVM revert (e.g. a failed `require`). - -#### async shouldFail.reverting.withMessage (promise, message) -Like `shouldFail.reverting`, this helper only accepts failures caused due to an EVM revert (e.g. a failed `require`). Furthermore, it checks whether revert reason string includes passed `message`. For example: +#### async expectRevert (promise, message) +This helper asserts that `promise` was rejected due to a reverted transaction, and it will check that the revert reason includes `message`. Use `expectRevert.unspecified` when the revert reason is unknown. For example: ```solidity contract Owned { @@ -203,7 +200,7 @@ contract Owned { Can be tested as follows: ```javascript -const { shouldFail } = require('openzeppelin-test-helpers'); +const { expectRevert } = require('openzeppelin-test-helpers'); const Owned = artifacts.require('Owned'); @@ -214,19 +211,20 @@ contract('Owned', ([owner, other]) => { describe('doOwnerOperation', function() { it('Fails when called by a non-owner account', async function () { - await shouldFail.reverting.withMessage(this.owned.doOwnerOperation({ from: other }), "Unauthorized"); + await expectRevert(this.owned.doOwnerOperation({ from: other }), "Unauthorized"); }); }); ... ``` -Use this helper to specify the expected error message, when you're testing a function that can revert for multiple reasons. +#### async expectRevert.unspecified (promise) +This helper asserts that `promise` was rejected due to a reverted transaction caused by a `require` or `revert` statement. -#### async shouldFail.throwing (promise) -Only accepts failures due to a failed `assert` (which executes an invalid opcode). +#### async expectRevert.assertion (promise) +This helper asserts that `promise` was rejected due to a reverted transaction caused by an `assert` statement or an invalid opcode. -#### async shouldFail.outOfGas (promise) -Only accepts failures due to the transaction running out of gas. +#### async expectRevert.outOfGas (promise) +This helper asserts that `promise` was rejected due to a transaction running out of gas. --- diff --git a/contracts/Failer.sol b/contracts/Failer.sol deleted file mode 100644 index 543ac2c..0000000 --- a/contracts/Failer.sol +++ /dev/null @@ -1,34 +0,0 @@ -pragma solidity ^0.4.24; - -contract Failer { - uint256[] private array; - - function dontFail() public pure { - } - - function failWithRevert() public pure { - revert(); - } - - function failWithThrow() public pure { - assert(false); - } - - function failWithRevertReason() public pure { - revert("Doomed to fail"); - } - - function failWithOutOfGas() public { - for (uint256 i = 0; i < 2**200; ++i) { - array.push(i); - } - } - - function failRequirement() public pure { - require(false); - } - - function failRequirementWithReason() public pure { - require(false, "Unsatisfied"); - } -} diff --git a/contracts/Reverter.sol b/contracts/Reverter.sol new file mode 100644 index 0000000..7d4acad --- /dev/null +++ b/contracts/Reverter.sol @@ -0,0 +1,38 @@ +pragma solidity ^0.4.24; + +contract Reverter { + uint256[] private array; + + function dontRevert() public pure { + } + + function revertFromRevert() public pure { + revert(); + } + + function revertFromRevertWithReason() public pure { + revert("Call to revert"); + } + + function revertFromRequire() public pure { + require(false); + } + + function revertFromRequireWithReason() public pure { + require(false, "Failed requirement"); + } + + function revertFromThrow() public pure { + throw; + } + + function revertFromAssert() public pure { + assert(false); + } + + function revertFromOutOfGas() public { + for (uint256 i = 0; i < 2**200; ++i) { + array.push(i); + } + } +} diff --git a/index.js b/index.js index c74f970..1f7c751 100644 --- a/index.js +++ b/index.js @@ -8,7 +8,7 @@ module.exports = { get expectEvent () { return require('./src/expectEvent'); }, get makeInterfaceId () { return require('./src/makeInterfaceId'); }, get send () { return require('./src/send'); }, - get shouldFail () { return require('./src/shouldFail'); }, + get expectRevert () { return require('./src/expectRevert'); }, get singletons () { return require('./src/singletons'); }, get time () { return require('./src/time'); }, }; diff --git a/src/expectRevert.js b/src/expectRevert.js new file mode 100644 index 0000000..69d1813 --- /dev/null +++ b/src/expectRevert.js @@ -0,0 +1,52 @@ +const { web3 } = require('./setup'); + +const { expect } = require('chai'); +const colors = require('ansi-colors'); +const semver = require('semver'); + +async function expectException (promise, expectedError) { + try { + await promise; + } catch (error) { + expect(error.message).to.include(expectedError, `Wrong failure type, expected '${expectedError}'`); + return; + } + + throw Error('Expected failure not received'); +} + +const expectRevert = async function (promise, expectedError) { + if (!expectedError) { + promise.catch(() => { }); + throw Error('No revert reason specified: call expectRevert with the reason string, or use expectRevert.unspecified \ +if your \'require\' statement doesn\'t have one.'); + } + + // Find out if current version of ganache-core supports revert reason i.e >= 2.2.0. + // https://github.com/trufflesuite/ganache-core/releases/tag/v2.2.0 + const nodeInfo = await web3.eth.getNodeInfo(); + const matches = /TestRPC\/v([0-9.]+)\/ethereum-js/.exec(nodeInfo); + + const warn = function (msg) { + console.log(`${colors.white.bgBlack('openzeppelin-test-helpers')} ${colors.black.bgYellow('WARN')} \ + expectRevert: ` + msg); + }; + + if (matches === null || !(1 in matches)) { + // warn users and skip reason check. + warn('revert reason checking only supported on Ganache v2.2.0 or newer.'); + expectedError = 'revert'; + } else if (!semver.gte(matches[1], '2.2.0')) { + // warn users and skip reason check. + warn(`current version of Ganache (v${matches[1]}) doesn't return revert reason. Use v2.2.0 or newer.`); + expectedError = 'revert'; + } + + await expectException(promise, expectedError); +}; + +expectRevert.assertion = (promise) => expectException(promise, 'invalid opcode'); +expectRevert.outOfGas = (promise) => expectException(promise, 'out of gas'); +expectRevert.unspecified = (promise) => expectException(promise, 'revert'); + +module.exports = expectRevert; diff --git a/src/shouldFail.js b/src/shouldFail.js deleted file mode 100644 index 467e8b4..0000000 --- a/src/shouldFail.js +++ /dev/null @@ -1,71 +0,0 @@ -const { web3 } = require('./setup'); - -const { expect } = require('chai'); -const colors = require('ansi-colors'); -const semver = require('semver'); - -async function shouldFailWithMessage (promise, message) { - try { - await promise; - } catch (error) { - if (message) { - expect(error.message).to.include(message, `Wrong failure type, expected '${message}'`); - } else { - expect.fail('Message not provided'); - } - return; - } - - expect.fail('Expected failure not received'); -} - -async function reverting (promise) { - await shouldFailWithMessage(promise, 'revert'); -} - -async function throwing (promise) { - await shouldFailWithMessage(promise, 'invalid opcode'); -} - -async function outOfGas (promise) { - await shouldFailWithMessage(promise, 'out of gas'); -} - -async function shouldFail (promise) { - try { - await promise; - } catch (error) { - return; - } - expect.fail('Failure not received'); -} - -async function withMessage (promise, message) { - // Find out if current version of ganache-core supports revert reason i.e >= 2.2.0. - // https://github.com/trufflesuite/ganache-core/releases/tag/v2.2.0 - const nodeInfo = await web3.eth.getNodeInfo(); - const matches = /TestRPC\/v([0-9.]+)\/ethereum-js/.exec(nodeInfo); - const warn = function (msg) { - console.log(`${colors.white.bgBlack('openzeppelin-test-helpers')} ${colors.black.bgYellow('WARN')} \ -shouldFail.reverting.withMessage: ` + msg); - }; - if (matches === null || !(1 in matches)) { - // warn users and skip reason check. - warn('revert reason checking only supported on Ganache>=2.2.0'); - return shouldFail(promise); - } else if (!semver.satisfies(matches[1], '>=2.2.0')) { - // warn users and skip reason check. - warn(`current version of Ganache (${matches[1]}) doesn't return revert reason.`); - return shouldFail(promise); - } else { - // actually perform revert reason check. - return shouldFailWithMessage(promise, message); - } -} - -shouldFail.reverting = reverting; -shouldFail.reverting.withMessage = withMessage; -shouldFail.throwing = throwing; -shouldFail.outOfGas = outOfGas; - -module.exports = shouldFail; diff --git a/test-integration/ganache-core-2.1.x/test/Tested.test.js b/test-integration/ganache-core-2.1.x/test/Tested.test.js index f245f88..108f2ed 100644 --- a/test-integration/ganache-core-2.1.x/test/Tested.test.js +++ b/test-integration/ganache-core-2.1.x/test/Tested.test.js @@ -1,10 +1,10 @@ -const { shouldFail } = require('openzeppelin-test-helpers'); +const { expectRevert } = require('openzeppelin-test-helpers'); const { expect } = require('chai'); const Tested = artifacts.require('Tested'); contract('Tested', function (accounts) { - context('shouldFail.reverting.withMessage', async function () { + context('expectRevert', async function () { beforeEach(async function () { this.contract = await Tested.new(); }) @@ -25,7 +25,7 @@ contract('Tested', function (accounts) { } // With that said, following revert should be accepted without regard to the specified // reason message. - await shouldFail.reverting.withMessage(this.contract.failWithRevertReason(), expectedMessage); + await expectRevert(this.contract.failWithRevertReason(), expectedMessage); }) }) }) diff --git a/test-integration/simple-project-truffle-5.x/test/Tested.test.js b/test-integration/simple-project-truffle-5.x/test/Tested.test.js index b81aae5..410f25b 100644 --- a/test-integration/simple-project-truffle-5.x/test/Tested.test.js +++ b/test-integration/simple-project-truffle-5.x/test/Tested.test.js @@ -1,4 +1,4 @@ -const { BN, constants, expectEvent, shouldFail } = require('openzeppelin-test-helpers'); +const { BN, constants, expectEvent, expectRevert } = require('openzeppelin-test-helpers'); const Tested = artifacts.require('Tested'); @@ -13,7 +13,7 @@ contract('Tested', function (accounts) { }) it('detect reverts', async function () { - await shouldFail.reverting(this.contract.reverts()); + await expectRevert.unspecified(this.contract.reverts()); }); it('accepts calls with non-zero address', async function () { @@ -22,7 +22,7 @@ contract('Tested', function (accounts) { }); it('reverts with calls with non-zero address', async function () { - await shouldFail.reverting(this.contract.nonZeroAddress(constants.ZERO_ADDRESS)); + await expectRevert.unspecified(this.contract.nonZeroAddress(constants.ZERO_ADDRESS)); }); }); }); diff --git a/test/helpers/assertFailure.js b/test/helpers/assertFailure.js new file mode 100644 index 0000000..f5a63c4 --- /dev/null +++ b/test/helpers/assertFailure.js @@ -0,0 +1,12 @@ +const { expect } = require('chai'); + +async function assertFailure (promise) { + try { + await promise; + } catch (error) { + return; + } + expect.fail(); +} + +module.exports = assertFailure; diff --git a/test/src/expectEvent.test.js b/test/src/expectEvent.test.js index aa67cf6..e80eb7a 100644 --- a/test/src/expectEvent.test.js +++ b/test/src/expectEvent.test.js @@ -1,7 +1,7 @@ const { BN } = require('../../src/setup'); const { expect } = require('chai'); +const assertFailure = require('../helpers/assertFailure'); const expectEvent = require('../../src/expectEvent'); -const shouldFail = require('../../src/shouldFail'); const EventEmitter = artifacts.require('EventEmitter'); const IndirectEventEmitter = artifacts.require('IndirectEventEmitter'); @@ -30,13 +30,13 @@ describe('expectEvent', function () { }); it('throws if a correct JavaScript number is passed', async function () { - await shouldFail( + await assertFailure( expectEvent.inConstruction(this.emitter, 'ShortUint', { value: this.constructionValues.uint }) ); }); it('throws if an incorrect value is passed', async function () { - await shouldFail(expectEvent.inConstruction(this.emitter, 'ShortUint', { value: 23 })); + await assertFailure(expectEvent.inConstruction(this.emitter, 'ShortUint', { value: 23 })); }); }); @@ -46,7 +46,7 @@ describe('expectEvent', function () { }); it('throws if an incorrect value is passed', async function () { - await shouldFail(expectEvent.inConstruction(this.emitter, 'Boolean', + await assertFailure(expectEvent.inConstruction(this.emitter, 'Boolean', { value: !this.constructionValues.boolean } )); }); @@ -58,12 +58,12 @@ describe('expectEvent', function () { }); it('throws if an incorrect string is passed', async function () { - await shouldFail(expectEvent.inConstruction(this.emitter, 'String', { value: 'ClosedZeppelin' })); + await assertFailure(expectEvent.inConstruction(this.emitter, 'String', { value: 'ClosedZeppelin' })); }); }); it('throws if an unemitted event is requested', async function () { - await shouldFail(expectEvent.inConstruction(this.emitter, 'UnemittedEvent')); + await assertFailure(expectEvent.inConstruction(this.emitter, 'UnemittedEvent')); }); }); @@ -386,25 +386,25 @@ describe('expectEvent', function () { }); it('throws if an unemitted event is requested', async function () { - await shouldFail(expectEvent.inTransaction(this.txHash, EventEmitter, 'UnemittedEvent', + await assertFailure(expectEvent.inTransaction(this.txHash, EventEmitter, 'UnemittedEvent', { value: this.value } )); }); it('throws if an incorrect string is passed', async function () { - await shouldFail(expectEvent.inTransaction(this.txHash, EventEmitter, 'String', + await assertFailure(expectEvent.inTransaction(this.txHash, EventEmitter, 'String', { value: 'ClosedZeppelin' } )); }); it('throws if an event emitted from other contract is passed', async function () { - await shouldFail(expectEvent.inTransaction(this.txHash, EventEmitter, 'IndirectString', + await assertFailure(expectEvent.inTransaction(this.txHash, EventEmitter, 'IndirectString', { value: this.value } )); }); it('throws if an incorrect emitter is passed', async function () { - await shouldFail(expectEvent.inTransaction(this.txHash, IndirectEventEmitter, 'String', + await assertFailure(expectEvent.inTransaction(this.txHash, IndirectEventEmitter, 'String', { value: this.value } )); }); @@ -418,25 +418,25 @@ describe('expectEvent', function () { }); it('throws if an unemitted event is requested', async function () { - await shouldFail(expectEvent.inTransaction(this.txHash, IndirectEventEmitter, 'UnemittedEvent', + await assertFailure(expectEvent.inTransaction(this.txHash, IndirectEventEmitter, 'UnemittedEvent', { value: this.value } )); }); it('throws if an incorrect string is passed', async function () { - await shouldFail(expectEvent.inTransaction(this.txHash, IndirectEventEmitter, 'IndirectString', + await assertFailure(expectEvent.inTransaction(this.txHash, IndirectEventEmitter, 'IndirectString', { value: 'ClosedZeppelin' } )); }); it('throws if an event emitted from other contract is passed', async function () { - await shouldFail(expectEvent.inTransaction(this.txHash, IndirectEventEmitter, 'String', + await assertFailure(expectEvent.inTransaction(this.txHash, IndirectEventEmitter, 'String', { value: this.value } )); }); it('throws if an incorrect emitter is passed', async function () { - await shouldFail(expectEvent.inTransaction(this.txHash, EventEmitter, 'IndirectString', + await assertFailure(expectEvent.inTransaction(this.txHash, EventEmitter, 'IndirectString', { value: this.value } )); }); diff --git a/test/src/expectRevert.test.js b/test/src/expectRevert.test.js new file mode 100644 index 0000000..2a5547b --- /dev/null +++ b/test/src/expectRevert.test.js @@ -0,0 +1,162 @@ +const assertFailure = require('../helpers/assertFailure'); +const expectRevert = require('../../src/expectRevert'); + +const Reverter = artifacts.require('Reverter'); + +describe('expectRevert', function () { + beforeEach(async function () { + this.reverter = await Reverter.new(); + }); + + describe('expectRevert', function () { + it('rejects if no revert occurs', async function () { + await assertFailure(expectRevert(this.reverter.dontRevert())); + }); + + it('rejects a revert', async function () { + await assertFailure(expectRevert(this.reverter.revertFromRevert())); + }); + + it('rejects a revert with reason and none expected', async function () { + await assertFailure(expectRevert(this.reverter.revertFromRevertWithReason())); + }); + + it('rejects a revert with incorrect expected reason', async function () { + await assertFailure(expectRevert(this.reverter.revertFromRevertWithReason(), 'Wrong reason')); + }); + + it('accepts a revert with correct expected reason', async function () { + await expectRevert(this.reverter.revertFromRevertWithReason(), 'Call to revert'); + }); + + it('rejects a failed requirement', async function () { + await assertFailure(expectRevert(this.reverter.revertFromRequire())); + }); + + it('rejects a failed requirement with reason and none expected', async function () { + await assertFailure(expectRevert(this.reverter.revertFromRequireWithReason())); + }); + + it('rejects a failed requirement with incorrect expected reason', async function () { + await assertFailure(expectRevert(this.reverter.revertFromRequireWithReason(), 'Wrong reason')); + }); + + it('accepts a failed requirement with correct expected reason', async function () { + await expectRevert(this.reverter.revertFromRequireWithReason(), 'Failed requirement'); + }); + + it('rejects a throw', async function () { + await assertFailure(expectRevert(this.reverter.revertFromThrow())); + }); + + it('rejects a failed assertion', async function () { + await assertFailure(expectRevert(this.reverter.revertFromAssert())); + }); + + it('rejects an outOfGas', async function () { + await assertFailure(expectRevert(this.reverter.revertFromOutOfGas({ gas: 2000000 }))); + }); + }); + + describe('unspecified', function () { + it('rejects if no revert occurs', async function () { + await assertFailure(expectRevert.unspecified(this.reverter.dontRevert())); + }); + + it('accepts a revert', async function () { + await expectRevert.unspecified(this.reverter.revertFromRevert()); + }); + + it('accepts a revert with reason', async function () { + await expectRevert.unspecified(this.reverter.revertFromRevertWithReason()); + }); + + it('accepts a failed requirement', async function () { + await expectRevert.unspecified(this.reverter.revertFromRequire()); + }); + + it('accepts a failed requirement with reason', async function () { + await expectRevert.unspecified(this.reverter.revertFromRequireWithReason()); + }); + + it('accepts a throw', async function () { + await expectRevert.unspecified(this.reverter.revertFromThrow()); + }); + + it('rejects a failed assertion', async function () { + await assertFailure(expectRevert.unspecified(this.reverter.revertFromAssert())); + }); + + it('rejects an outOfGas', async function () { + await assertFailure(expectRevert.unspecified(this.reverter.revertFromOutOfGas({ gas: 2000000 }))); + }); + }); + + describe('assertion', function () { + it('rejects if no revert occurs', async function () { + await assertFailure(expectRevert.assertion(this.reverter.dontRevert())); + }); + + it('rejects a revert', async function () { + await assertFailure(expectRevert.assertion(this.reverter.revertFromRevert())); + }); + + it('rejects a revert with reason', async function () { + await assertFailure(expectRevert.assertion(this.reverter.revertFromRevertWithReason())); + }); + + it('rejects a failed requirement', async function () { + await assertFailure(expectRevert.assertion(this.reverter.revertFromRequire())); + }); + + it('rejects a failed requirement with reason', async function () { + await assertFailure(expectRevert.assertion(this.reverter.revertFromRequireWithReason())); + }); + + it('rejects a throw', async function () { + await assertFailure(expectRevert.assertion(this.reverter.revertFromThrow())); + }); + + it('accepts a failed assertion', async function () { + await expectRevert.assertion(this.reverter.revertFromAssert()); + }); + + it('rejects an outOfGas', async function () { + await assertFailure(expectRevert.assertion(this.reverter.revertFromOutOfGas({ gas: 2000000 }))); + }); + }); + + describe('outOfGas', function () { + it('rejects if no revert occurs', async function () { + await assertFailure(expectRevert.outOfGas(this.reverter.dontRevert())); + }); + + it('rejects a revert', async function () { + await assertFailure(expectRevert.outOfGas(this.reverter.revertFromRevert())); + }); + + it('rejects a revert with reason', async function () { + await assertFailure(expectRevert.outOfGas(this.reverter.revertFromRevertWithReason())); + }); + + it('rejects a failed requirement', async function () { + await assertFailure(expectRevert.outOfGas(this.reverter.revertFromRequire())); + }); + + it('rejects a failed requirement with reason', async function () { + await assertFailure(expectRevert.outOfGas(this.reverter.revertFromRequireWithReason())); + }); + + it('rejects a throw', async function () { + await assertFailure(expectRevert.outOfGas(this.reverter.revertFromThrow())); + }); + + it('accepts a failed assertion', async function () { + await assertFailure(expectRevert.outOfGas(this.reverter.revertFromAssert())); + }); + + it('accets an outOfGas', async function () { + await expectRevert.outOfGas(this.reverter.revertFromOutOfGas({ gas: 2000000 })); + }); + }); +}); diff --git a/test/src/send.test.js b/test/src/send.test.js index 56b8380..91fc327 100644 --- a/test/src/send.test.js +++ b/test/src/send.test.js @@ -1,7 +1,7 @@ const { BN } = require('../../src/setup'); const { expect } = require('chai'); +const assertFailure = require('../helpers/assertFailure'); const send = require('../../src/send'); -const shouldFail = require('../../src/shouldFail'); const expectEvent = require('../../src/expectEvent'); const ether = require('../../src/ether'); @@ -27,7 +27,7 @@ contract('send', function ([sender, receiver]) { it('throws if the sender balance is insufficient', async function () { const value = new BN(await web3.eth.getBalance(sender)).add(new BN(1)); - await shouldFail(send.ether(sender, receiver, value)); + await assertFailure(send.ether(sender, receiver, value)); }); it('calls fallback function', async function () { @@ -71,15 +71,15 @@ contract('send', function ([sender, receiver]) { }); it('throws if the number of arguments does not match', async function () { - await shouldFail(send.transaction(this.acknowledger, 'foo', 'uint256, uint256', [3, 5]), opts); + await assertFailure(send.transaction(this.acknowledger, 'foo', 'uint256, uint256', [3, 5]), opts); }); it('throws if the method does not exist', async function () { - await shouldFail(send.transaction(this.acknowledger, 'baz', 'uint256', [3]), opts); + await assertFailure(send.transaction(this.acknowledger, 'baz', 'uint256', [3]), opts); }); it('throws if there is a mismatch in the number of types and values', async function () { - await shouldFail(send.transaction(this.acknowledger, 'foo', 'uint256', [3, 3]), opts); + await assertFailure(send.transaction(this.acknowledger, 'foo', 'uint256', [3, 3]), opts); }); } }); diff --git a/test/src/shouldFail.test.js b/test/src/shouldFail.test.js deleted file mode 100644 index 250c96c..0000000 --- a/test/src/shouldFail.test.js +++ /dev/null @@ -1,125 +0,0 @@ -const { expect } = require('chai'); -const shouldFail = require('../../src/shouldFail'); - -const Failer = artifacts.require('Failer'); - -async function assertFailure (promise) { - try { - await promise; - } catch (error) { - return; - } - expect.fail(); -} - -describe('shouldFail', function () { - beforeEach(async function () { - this.failer = await Failer.new(); - }); - - describe('shouldFail', function () { - it('rejects if no failure occurs', async function () { - await assertFailure(shouldFail(this.failer.dontFail())); - }); - - it('accepts a revert', async function () { - await shouldFail(this.failer.failWithRevert()); - }); - - it('accepts a require() revert', async function () { - await shouldFail(this.failer.failRequirement()); - }); - - it('accepts a throw', async function () { - await shouldFail(this.failer.failWithThrow()); - }); - - it('accepts an out of gas', async function () { - await shouldFail(this.failer.failWithOutOfGas({ gas: 2000000 })); - }); - }); - - describe('reverting', function () { - it('rejects if no failure occurs', async function () { - await assertFailure(shouldFail.reverting(this.failer.dontFail())); - }); - - it('accepts a revert', async function () { - await shouldFail.reverting(this.failer.failWithRevert()); - }); - - it('accepts a require() revert', async function () { - await shouldFail.reverting(this.failer.failRequirement()); - }); - - it('rejects a throw', async function () { - await assertFailure(shouldFail.reverting(this.failer.failWithThrow())); - }); - - it('rejects an outOfGas', async function () { - await assertFailure(shouldFail.reverting(this.failer.failWithOutOfGas({ gas: 2000000 }))); - }); - - describe('reverting.withMessage', function () { - it('rejects if no failure occurs', async function () { - await assertFailure(shouldFail.reverting.withMessage(this.failer.dontFail())); - }); - - it('accepts a revert with an expected reason', async function () { - await shouldFail.reverting.withMessage(this.failer.failWithRevertReason(), 'Doomed to fail'); - }); - - it('rejects a revert with an unexpected reason', async function () { - await assertFailure(shouldFail.reverting.withMessage(this.failer.failWithRevertReason(), 'Wrong reason')); - }); - - it('rejects if no reason string passed', async function () { - await assertFailure(shouldFail.reverting.withMessage(this.failer.failWithRevertReason())); - }); - - it('accepts require() revert with an expected reason', async function () { - await shouldFail.reverting.withMessage(this.failer.failRequirementWithReason(), 'Unsatisfied'); - }); - - it('rejects a require() revert with an unexpected reason', async function () { - await assertFailure(shouldFail.reverting.withMessage(this.failer.failRequirementWithReason(), 'Wrong reason')); - }); - }); - }); - - describe('throwing', function () { - it('rejects if no failure occurs', async function () { - await assertFailure(shouldFail.throwing(this.failer.dontFail())); - }); - - it('accepts a throw', async function () { - await shouldFail.throwing(this.failer.failWithThrow()); - }); - - it('rejects a throw', async function () { - await assertFailure(shouldFail.throwing(this.failer.failWithRevert())); - }); - - it('rejects an outOfGas', async function () { - await assertFailure(shouldFail.throwing(this.failer.failWithOutOfGas({ gas: 2000000 }))); - }); - }); - - describe('outOfGas', function () { - it('rejects if no failure occurs', async function () { - await assertFailure(shouldFail.outOfGas(this.failer.dontFail())); - }); - - it('accepts an out of gas', async function () { - await shouldFail.outOfGas(this.failer.failWithOutOfGas({ gas: 2000000 })); - }); - - it('rejects a revert', async function () { - await assertFailure(shouldFail.outOfGas(this.failer.failWithRevert())); - }); - - it('rejects a throw', async function () { - await assertFailure(shouldFail.outOfGas(this.failer.failWithThrow())); - }); - }); -}); diff --git a/test/src/time.test.js b/test/src/time.test.js index 605e062..971d24a 100644 --- a/test/src/time.test.js +++ b/test/src/time.test.js @@ -1,7 +1,7 @@ const { BN } = require('../../src/setup'); const { expect } = require('chai'); +const assertFailure = require('../helpers/assertFailure'); const time = require('../../src/time'); -const shouldFail = require('../../src/shouldFail'); describe('time', function () { const TOLERANCE_SECONDS = new BN(1); @@ -69,7 +69,7 @@ describe('time', function () { }); it('throws with negative durations', async function () { - await shouldFail(time.increase(-1)); + await assertFailure(time.increase(-1)); }); }); @@ -83,7 +83,7 @@ describe('time', function () { }); it('throws with a time in the past', async function () { - await shouldFail(time.increaseTo(this.start.sub(new BN(30)))); + await assertFailure(time.increaseTo(this.start.sub(new BN(30)))); }); }); });