eth-gas-reporter
Advanced tools
Comparing version 0.1.10 to 0.1.11
## Changelog: eth-gas-reporter | ||
0.1.10 / 2018-07-18 | ||
=================== | ||
* Update mocha from 3.5.3 to 4.10.0 (contribution ldub) | ||
* Update truffle to truffle@next to fix mocha issues (contribution ldub) | ||
* Modify binary checking to allow very long bytecodes / large contracts (contribution ben-kaufman) | ||
0.1.9 / 2018-06-27 | ||
@@ -4,0 +10,0 @@ ================== |
@@ -63,4 +63,4 @@ /** | ||
*/ | ||
function getMethodID (code) { | ||
return code.slice(2, 10) | ||
function getMethodID (contractName, code) { | ||
return contractName + '_' +code.slice(2, 10) | ||
} | ||
@@ -91,8 +91,14 @@ | ||
*/ | ||
function generateGasStatsReport (methodMap, deployMap) { | ||
function generateGasStatsReport (methodMap, deployMap, addressContractNameMap) { | ||
const methodRows = [] | ||
const deployedContracts = {}; | ||
for(const key of Object.keys(addressContractNameMap)) { | ||
deployedContracts[addressContractNameMap[key]] = true; | ||
} | ||
_.forEach(methodMap, (data, methodId) => { | ||
if (!data) return | ||
if(!deployedContracts[data.contract]) return // skip contract that were not deployed | ||
let stats = {} | ||
@@ -270,3 +276,3 @@ | ||
gasPrice = config.gasPrice || null | ||
onlyCalledMethods = config.onlyCalledMethods || false | ||
onlyCalledMethods = (config.onlyCalledMethods === false) ? false : true; | ||
outputFile = config.outputFile || null | ||
@@ -349,5 +355,6 @@ rst = config.rst || false | ||
*/ | ||
function mapMethodsToContracts (truffleArtifacts) { | ||
function mapMethodsToContracts (truffleArtifacts, srcPath) { | ||
const methodMap = {} | ||
const deployMap = [] | ||
const addressContractNameMap = {} | ||
const abis = [] | ||
@@ -358,4 +365,6 @@ | ||
const files = shell.ls('./contracts/**/*.sol') | ||
const networkId = sync.getNetworkId(); | ||
const files = shell.ls('./' + srcPath + '/**/*.sol') | ||
// For each file | ||
@@ -379,2 +388,11 @@ files.forEach(file => { | ||
deployMap.push(contractInfo) | ||
// report the gas used during initial truffle migration too : | ||
const networkDeployment = contract.networks[networkId] | ||
if (networkDeployment) { | ||
addressContractNameMap[networkDeployment.address] = name; | ||
const receipt = sync.getTransactionReceipt(networkDeployment.transactionHash); | ||
contractInfo.gasData.push(parseInt(receipt.gasUsed, 16)); | ||
} | ||
abis.push(contract._json.abi) | ||
@@ -394,3 +412,3 @@ | ||
if (hasName && !isConstant && !isEvent && !isInterface) { | ||
methodMap[key] = { | ||
methodMap[name + '_' + key] = { | ||
contract: name, | ||
@@ -410,3 +428,4 @@ method: methodIDs[key].name, | ||
methodMap: methodMap, | ||
deployMap: deployMap | ||
deployMap: deployMap, | ||
addressContractNameMap: addressContractNameMap | ||
} | ||
@@ -413,0 +432,0 @@ } |
38
index.js
@@ -6,2 +6,3 @@ const mocha = require('mocha') | ||
const reqCwd = require('req-cwd') | ||
const sha1 = require('sha1') | ||
const Base = mocha.reporters.Base | ||
@@ -14,3 +15,8 @@ const color = Base.color | ||
Base.call(this, runner) | ||
if (!(web3.currentProvider.connection || web3.currentProvider.host)) { | ||
console.log('the provider use for the test does not support synchronous call but eth-gas-reporter requires it \n falling back on the Spec reporter'); | ||
mocha.reporters.Spec.call(this, runner); | ||
return; | ||
} | ||
Base.call(this, runner); | ||
@@ -25,2 +31,3 @@ const self = this | ||
let deployMap | ||
let addressContractNameMap; | ||
@@ -35,2 +42,5 @@ // Load config / keep .ethgas.js for backward compatibility | ||
config.src = config.src || 'contracts'; // default contracts folder | ||
// TODO grab the contract srcpath from truffle / truffle config ? | ||
// Start getting this data when the reporter loads. | ||
@@ -57,5 +67,8 @@ stats.getGasAndPriceRates(config); | ||
const receipt = sync.getTransactionReceipt(tx); | ||
const id = stats.getMethodID(transaction.input) | ||
const code = sync.getCode(transaction.to); | ||
const hash = sha1(code); | ||
const contractName = addressContractNameMap[hash]; | ||
const id = stats.getMethodID(contractName, transaction.input) | ||
let threw = parseInt(receipt.status) === 0; | ||
let threw = parseInt(receipt.status) === 0 || receipt.status === false; | ||
@@ -81,3 +94,3 @@ if (methodMap[id] && !threw) { | ||
const receipt = sync.getTransactionReceipt(tx); | ||
const threw = parseInt(receipt.status) === 0; | ||
const threw = parseInt(receipt.status) === 0 || receipt.status === false; | ||
@@ -93,3 +106,12 @@ if (receipt.contractAddress && !threw) { | ||
const match = matches.find(item => item.binary !== '0x'); | ||
match && match.gasData.push(parseInt(receipt.gasUsed, 16)) | ||
if (match) { | ||
// We have to get code that might be linked here in | ||
// in order to match correctly at the method ids | ||
const code = sync.getCode(receipt.contractAddress); | ||
const hash = sha1(code); | ||
match.gasData.push(parseInt(receipt.gasUsed, 16)); | ||
addressContractNameMap[hash] = match.name; | ||
} | ||
} | ||
@@ -104,3 +126,3 @@ } | ||
runner.on('start', () => { | ||
({ methodMap, deployMap } = stats.mapMethodsToContracts(artifacts)) | ||
({ methodMap, deployMap, addressContractNameMap } = stats.mapMethodsToContracts(artifacts, config.src)) | ||
}) | ||
@@ -148,3 +170,3 @@ | ||
} | ||
fmt = indent() + | ||
@@ -179,3 +201,3 @@ color('checkmark', ' ' + Base.symbols.ok) + | ||
runner.on('end', () => { | ||
stats.generateGasStatsReport(methodMap, deployMap) | ||
stats.generateGasStatsReport(methodMap, deployMap, addressContractNameMap) | ||
self.epilogue() | ||
@@ -182,0 +204,0 @@ }); |
@@ -15,3 +15,3 @@ module.exports = { | ||
gasPrice: 21, | ||
onlyCalledMethods: true, | ||
onlyCalledMethods: false, | ||
noColors: true, | ||
@@ -18,0 +18,0 @@ rst: true, |
{ | ||
"name": "eth-gas-reporter", | ||
"version": "0.1.9", | ||
"version": "0.1.10", | ||
"description": "Mocha reporter which shows gas used per unit test.", | ||
@@ -36,2 +36,3 @@ "main": "index.js", | ||
"request-promise-native": "^1.0.5", | ||
"sha1": "^1.1.1", | ||
"shelljs": "^0.7.8", | ||
@@ -38,0 +39,0 @@ "solidity-parser-antlr": "^0.2.10", |
const VariableCosts = artifacts.require('./VariableCosts.sol') | ||
const Wallet = artifacts.require('./Wallet.sol') | ||
@@ -8,4 +9,8 @@ contract('VariableCosts', accounts => { | ||
let instance | ||
let walletB | ||
beforeEach(async () => instance = await VariableCosts.new()) | ||
beforeEach(async () => { | ||
instance = await VariableCosts.new() | ||
walletB = await Wallet.new(); | ||
}) | ||
@@ -49,5 +54,26 @@ it('should add one', async () => { | ||
it('methods that call methods in other contracts', async() => { | ||
await instance.otherContractMethod(); | ||
}) | ||
it('prints a table at end of test suites with failures', async() => { | ||
assert(false); | ||
}) | ||
// VariableCosts is Wallet. We also have Wallet tests. So we should see | ||
// separate entries for `sendPayment` / `transferPayment` under VariableCosts | ||
// and Wallet in the report | ||
it('should allow contracts to have identically named methods', async () => { | ||
await instance.sendTransaction({ | ||
value: 100, from: accounts[0] | ||
}) | ||
await instance.sendPayment(50, walletB.address, { | ||
from: accounts[0] | ||
}) | ||
await instance.transferPayment(50, walletB.address, { | ||
from: accounts[0] | ||
}) | ||
const balance = await walletB.getBalance() | ||
assert.equal(parseInt(balance.toString()), 100) | ||
}) | ||
}) |
{ | ||
"name": "eth-gas-reporter", | ||
"version": "0.1.10", | ||
"version": "0.1.11", | ||
"description": "Mocha reporter which shows gas used per unit test.", | ||
@@ -36,2 +36,3 @@ "main": "index.js", | ||
"request-promise-native": "^1.0.5", | ||
"sha1": "^1.1.1", | ||
"shelljs": "^0.7.8", | ||
@@ -38,0 +39,0 @@ "solidity-parser-antlr": "^0.2.10", |
@@ -12,3 +12,4 @@ # eth-gas-reporter | ||
![screen shot 2017-10-28 at 1 29 52 pm](https://user-images.githubusercontent.com/7332026/32138588-db1d56e0-bbe9-11e7-820e-511d6e36c846.png) | ||
![screen shot 2018-08-01 at 10 13 56 am](https://user-images.githubusercontent.com/7332026/43537357-f64f031e-9573-11e8-9348-315d9d4a8476.png) | ||
![screen shot 2018-08-01 at 10 13 34 am](https://user-images.githubusercontent.com/7332026/43537353-f1889f70-9573-11e8-82c3-f93d3901db64.png) | ||
@@ -45,6 +46,7 @@ | ||
| noColors | *Boolean* | false | Suppress report color. Useful if you are printing to file b/c terminal colorization corrupts the text. | | ||
| onlyCalledMethods | *Boolean* | false | Omit methods that are never called from report. | | ||
| onlyCalledMethods | *Boolean* | true | Omit methods that are never called from report. | | ||
| rst | *Boolean* | false | Output with a reStructured text code-block directive. Useful if you want to include report in RTD | | ||
| rstTitle | *String* | "" | Title for reStructured text header (See Travis for example output) | | ||
| showTimeSpent | *Boolean* | false | Show the amount of time spent as well as the gas consumed | | ||
| src | *String* | "contracts" | Folder in root directory to begin search for `.sol` files. This can also be a path to a subfolder relative to the root, e.g. "planets/annares/contracts" | | ||
@@ -59,13 +61,7 @@ | ||
+ Method calls that throw are filtered from the stats. | ||
+ Not currently shown in the `deployments` table: | ||
+ Contracts that never get instantiated within the tests (e.g: only deployed in migrations) | ||
+ Contracts that are only ever created by other contracts within Solidity. | ||
+ Your ethereum client has to be run in separate process (e.g. reporter will not work if you connect | ||
to `ganache` through a `provider` in your `truffle.js`). This because mocha's reporter is sync | ||
and we have to collect gas data synchronously from the client as your tests run. Sync requests | ||
fail with an in memory provider because they block the thread and prevent a | ||
response. (Pro-tip courtesy of [@fosgate29](https://github.com/fosgate29)). | ||
+ Contracts that are only ever created by other contracts within Solidity are not shown in the deployments table. | ||
### Contributions | ||
Please feel free to open a PR (or an issue) for anything. The units are an integration test and one of them is expected to fail, verifying that the table prints at the end of a suite even when there are errors. If you're adding an option, you can vaildate it in CI by adding it to the mock options config located [here](https://github.com/cgewecke/eth-gas-reporter/blob/master/mock/config-template.js#L13-L19). | ||
Please feel free to open a PR (or an issue) for anything. The units are an integration test and one of them is expected to fail, verifying that the table prints at the end of a suite even when there are errors. If you're adding an option, you can vaildate it in CI by adding it to the mock options config located [here](https://github.com/cgewecke/eth-gas-reporter/blob/master/mock/config-template.js#L13-L19). | ||
@@ -83,1 +79,3 @@ ### Credits | ||
+ [@ldub](https://github.com/ldub) | ||
+ [@ben-kaufman](https://github.com/ben-kaufman) | ||
+ [@wighawag](https://github.com/wighawag) |
@@ -12,2 +12,10 @@ /** | ||
const sync = { | ||
getNetworkId: () => { | ||
return sync.request('net_version', []); | ||
}, | ||
getCode: (address) => { | ||
return sync.request('eth_getCode', [address, 'latest']) | ||
}, | ||
getLatestBlock: () => { | ||
@@ -14,0 +22,0 @@ return sync.request('eth_getBlockByNumber', ['latest', false]); |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
47165
851
12
78
+ Addedsha1@^1.1.1
+ Addedcharenc@0.0.2(transitive)
+ Addedcrypt@0.0.2(transitive)
+ Addedsha1@1.1.1(transitive)