Press n or j to go to the next uncovered block, b, p or k for the previous block.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 | 1x 154x 154x 138x 138x 138x 400x 138x 138x 267x 138x 138x 158x 158x 138x 138x 278x 111x 111x 1233x 1233x 1233x 1233x 1233x 390x 257x 270x 76x 90x 18x 66x 66x 111x 111x 132x 132x 158x 158x 62x 111x 1x | /** * Converts instrumentation data accumulated a the vm steps to an instanbul spec coverage object. * @type {Coverage} */ const util = require('util'); class Coverage { constructor() { this.data = {}; this.requireData = {}; } /** * Initializes an entry in the coverage map for an instrumented contract. Tracks by * its canonical contract path, e.g. *not* by its location in the temp folder. * @param {Object} info 'info = instrumenter.instrument(contract, fileName, true)' * @param {String} contractPath canonical path to contract file */ addContract(info, contractPath) { this.data[contractPath] = { l: {}, path: contractPath, s: {}, b: {}, f: {}, fnMap: {}, statementMap: {}, branchMap: {}, }; this.requireData[contractPath] = { }; info.runnableLines.forEach((item, idx) => { this.data[contractPath].l[info.runnableLines[idx]] = 0; }); this.data[contractPath].fnMap = info.fnMap; for (let x = 1; x <= Object.keys(info.fnMap).length; x++) { this.data[contractPath].f[x] = 0; } this.data[contractPath].branchMap = info.branchMap; for (let x = 1; x <= Object.keys(info.branchMap).length; x++) { this.data[contractPath].b[x] = [0, 0]; this.requireData[contractPath][x] = { preEvents: 0, postEvents: 0, }; } this.data[contractPath].statementMap = info.statementMap; for (let x = 1; x <= Object.keys(info.statementMap).length; x++) { this.data[contractPath].s[x] = 0; } } /** * Populates an empty coverage map with values derived from a hash map of * data collected as the instrumented contracts are tested * @param {Object} map of collected instrumentation data * @return {Object} coverage map. */ generate(collectedData) { const hashes = Object.keys(collectedData); for (let hash of hashes){ const data = collectedData[hash]; const contractPath = collectedData[hash].contractPath; const id = collectedData[hash].id; // NB: Any branch using the injected fn which returns boolean will have artificially // doubled hits (because of something internal to Solidity about how the stack is managed) const hits = collectedData[hash].hits; switch(collectedData[hash].type){ case 'line': this.data[contractPath].l[id] = hits; break; case 'function': this.data[contractPath].f[id] = hits; break; case 'statement': this.data[contractPath].s[id] = hits; break; case 'branch': this.data[contractPath].b[id][data.locationIdx] = hits; break; case 'and-true': this.data[contractPath].b[id][data.locationIdx] = hits; break; case 'or-false': this.data[contractPath].b[id][data.locationIdx] = hits; break; case 'requirePre': this.requireData[contractPath][id].preEvents = hits; break; case 'requirePost': this.requireData[contractPath][id].postEvents = hits; break; } } // Finally, interpret the assert pre/post events const contractPaths = Object.keys(this.requireData); for (let contractPath of contractPaths){ const contract = this.data[contractPath]; for (let i = 1; i <= Object.keys(contract.b).length; i++) { const branch = this.requireData[contractPath][i]; // Was it an assert branch? if (branch && branch.preEvents > 0){ this.data[contractPath].b[i] = [ branch.postEvents, branch.preEvents - branch.postEvents ] } } } return Object.assign({}, this.data); } }; module.exports = Coverage; |