-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
7 changed files
with
620 additions
and
5 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
node_modules/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
'use strict'; | ||
|
||
var clc = require('cli-color-tty')(true); | ||
var path = require('path'); | ||
var through = require('through2'); | ||
|
||
// Takes the output of the test and test_summarizer streams | ||
// and emits it to stdout and stderr (as appropriate) before | ||
// passing it on to the next stream in the pipeline. | ||
var first = true; | ||
module.exports = function () { | ||
var lastDirectory; | ||
|
||
return through.obj(function (file, enc, cb) { | ||
this.push(file); | ||
|
||
if (!/\.(stderr|stdout)$/.test(file.path)) { | ||
return cb(); | ||
} | ||
|
||
var out = console.log; | ||
|
||
if (/\.stderr$/.test(file.path)) { | ||
out = console.error; | ||
} | ||
|
||
if (first) { | ||
out(); | ||
first = false; | ||
} | ||
|
||
if (lastDirectory !== path.dirname(file.path)) { | ||
lastDirectory = path.dirname(file.path); | ||
out(clc.bold(lastDirectory)); | ||
} | ||
out(' ' + String(file.contents)); | ||
cb(); | ||
}); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,167 @@ | ||
'use strict'; | ||
|
||
var _ = require('lodash'); | ||
var BigNumber = require('bignumber.js'); | ||
var clc = require('cli-color-tty')(true); | ||
var Contract = require('../contract'); | ||
var deasync = require('deasync'); | ||
var File = require('vinyl'); | ||
var LogTranslator = require('../logtranslator'); | ||
var path = require('path'); | ||
var fs = require('fs'); | ||
var through = require('through2'); | ||
var VMTest = require('../vmtest'); | ||
|
||
// This stream takes the output of either the build stream or pipeline (they | ||
// produce the same output) and returns a stream of files containing the output | ||
// of running each `Test` contract. A special, non-standard `error` flag is set | ||
// on File objects representing failed tests. This allows the `cli_out` stream | ||
// to push the content of those files to `stderr` instead of `stdout`. | ||
|
||
function runTests (stream, className, vmTest, logTranslator) { | ||
var testCount = vmTest.testCount(); | ||
var remaining = testCount; | ||
var deployFailure = false; | ||
|
||
function testResultHandler (err, result) { | ||
if (deployFailure || stream.isPaused()) return; | ||
|
||
if (err) { | ||
stream.push(new File({ | ||
path: path.join(className, | ||
'Deployment failure.stderr'), | ||
contents: new Buffer(String(err)) | ||
})); | ||
deployFailure = true; | ||
return; | ||
} | ||
|
||
var color = clc.green; | ||
|
||
if (result.failed) { | ||
color = clc.red; | ||
} | ||
|
||
// TODO: Clean this up. We want it to be | ||
// easy to have special log formatting for | ||
// particular types of events, and this is | ||
// a discreet logical chunk that belongs in | ||
// its own function or class somewhere. | ||
var output = result.title + '\n'; | ||
var logPrefix = ' | '; | ||
var report = ''; | ||
for (let entry of result.logs) { | ||
if (entry.event === '__startBlockE') { | ||
report += '```{' + entry.args.what + '}\n'; | ||
} else if (entry.event === '__stopBlockE') { | ||
report += '```\n'; | ||
} else if (entry.event.indexOf('log_id_') > -1 && LogTranslator.logs[entry.event].type === 'doc') { | ||
report += LogTranslator.format(entry) + '\n'; | ||
} else if (entry.event.indexOf('_named_') > -1) { | ||
var key = toAscii(entry.args.key) + ': '; | ||
var val = entry.args.decimals | ||
? toDecimal(entry.args.val, entry.args.decimals) | ||
: entry.args.val; | ||
output += logPrefix + key + val + '\n'; | ||
} else if (entry.event.indexOf('log_id_') > -1) { | ||
output += ' ' + LogTranslator.format(entry) + '\n'; | ||
} else if (entry.event === 'log_bytes32') { | ||
output += logPrefix + toAscii(entry.args.val) + '\n'; | ||
} else { | ||
output += logPrefix + entry.event + '\n'; | ||
|
||
for (let arg of _.pairs(entry.args)) { | ||
output += logPrefix + ' ' + | ||
arg[0] + ': ' + arg[1] + '\n'; | ||
} | ||
} | ||
} | ||
output += ' ' + color(result.message) + '\n'; | ||
// TODO refactor to write report stream file | ||
if (result.reporterPath) { | ||
fs.appendFileSync(result.reporterPath, report); | ||
} | ||
|
||
var file = new File({ | ||
path: path.join( | ||
className, | ||
result.title + (result.failed ? '.stderr' : '.stdout')), | ||
contents: new Buffer(output) | ||
}); | ||
stream.push(file); | ||
|
||
remaining = remaining - 1; | ||
} | ||
|
||
// Run all the tests in parallel. | ||
for (var i = 0; i < testCount; i++) { | ||
vmTest.runTest(i, testResultHandler); | ||
} | ||
|
||
// Wait until all the tests have been run. | ||
deasync.loopWhile(() => remaining !== 0 && !deployFailure); | ||
} | ||
|
||
module.exports = function (opts) { | ||
return through.obj(function (file, enc, cb) { | ||
var classes = JSON.parse(String(file.contents)); | ||
|
||
// Skip if Test contract isn't found | ||
if (!('Test' in classes)) return cb(); | ||
|
||
// Load the Test contract | ||
try { | ||
var testContract = new Contract(classes['Test']); | ||
} catch (err) { | ||
return cb(err); | ||
} | ||
|
||
// TODO - export this to pipeline setup as different streams have to be able to communicate with the chain | ||
var web3 = opts.web3; | ||
|
||
// var libraryAddressMap = {}; | ||
// const DEFAULT_GAS = 900000000; // 900 million | ||
var className; | ||
|
||
for (className in classes) { | ||
// Filter classNames if a filter is present if a filter is present | ||
if (opts.nameFilter && !opts.nameFilter.test(className)) { | ||
continue; | ||
} | ||
|
||
try { | ||
var contract = new Contract(classes[className]); | ||
} catch (err) { | ||
return cb(err); | ||
} | ||
|
||
// way to determine if the class is a test, | ||
// iff it has implemented the Test interface | ||
if (_.intersection(contract.signatures, testContract.signatures) | ||
.length !== testContract.signatures.length) { | ||
continue; | ||
} | ||
let translator = opts.logTranslator || new LogTranslator(contract.abi); | ||
var vmTest = opts.vmTest || new VMTest(web3, contract, translator); | ||
let stream = opts.stream || this; | ||
runTests(stream, className, vmTest, translator); | ||
} | ||
vmTest.stop(); | ||
cb(); | ||
}); | ||
}; | ||
|
||
function toAscii (hex) { | ||
hex = hex.replace(/^0x/, ''); | ||
var result = ''; | ||
for (var i = 0; i < hex.length - 1; i += 2) { | ||
result += String.fromCharCode(parseInt(hex.substr(i, 2), 16)); | ||
} | ||
return result.replace(/\0/g, ''); | ||
} | ||
|
||
function toDecimal (value, decimals) { | ||
return new BigNumber(value) | ||
.div(new BigNumber(10).pow(decimals)) | ||
.toFixed(decimals); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
'use strict'; | ||
|
||
var clc = require('cli-color-tty')(true); | ||
var File = require('vinyl'); | ||
var path = require('path'); | ||
var through = require('through2'); | ||
|
||
// Takes the output of the test stream and summarizes the test results. | ||
// Outputs one file object if all the tests passed, and two if some | ||
// tests failed. One file object has a string describing the overall | ||
// test status, and the other has a list of all failing tests. | ||
module.exports = function () { | ||
var totalTests = 0; | ||
var failingTests = []; | ||
|
||
return through.obj(function (file, enc, cb) { | ||
if (/\.stderr$/.test(file.path)) { | ||
failingTests.push(file); | ||
} | ||
totalTests += 1; | ||
cb(); | ||
}, function (cb) { | ||
var ext = '.stdout'; | ||
var output = clc.green('Passed all ' + totalTests + ' tests!'); | ||
|
||
if (failingTests.length > 0) { | ||
ext = '.stderr'; | ||
output = clc.red( | ||
'Failed ' + failingTests.length + | ||
' out of ' + totalTests + ' tests.'); | ||
|
||
var failedOutput = ''; | ||
for (let failingTest of failingTests) { | ||
failedOutput += clc.red(path.dirname(failingTest.path) + | ||
': ' + path.basename(failingTest.path, ext)) + '\n '; | ||
} | ||
|
||
this.push(new File({ | ||
path: path.join('Failing Tests', 'summary' + ext), | ||
contents: new Buffer(failedOutput) | ||
})); | ||
} | ||
|
||
this.push(new File({ | ||
path: path.join('Summary', 'summary' + ext), | ||
contents: new Buffer(output) | ||
})); | ||
|
||
cb(); | ||
}); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.