Unverified Commit ade3463a authored by yann300's avatar yann300 Committed by GitHub

Merge branch 'master' into origin/compileRenaming

parents d89010ff 365fbd9f
...@@ -11,3 +11,4 @@ package-lock.json ...@@ -11,3 +11,4 @@ package-lock.json
.tern-port .tern-port
TODO TODO
soljson.js soljson.js
lerna-debug.log
[submodule "remixd"]
path = remixd
url = https://github.com/ethereum/remixd
language: node_js
node_js:
- stable
env:
- TEST_DIR=remix-lib
- TEST_DIR=remix-solidity
- TEST_DIR=remix-debug
- TEST_DIR=remix-tests
- TEST_DIR=remix-simulator
script:
- cd $TEST_DIR && npm install && npm test
deploy:
provider: script
script: remix-debugger/ci/deploy_from_travis.sh
skip_cleanup: true
on:
branch: master
condition: $TEST_DIR = remix-debugger
cache: false
# Remix # Remix
[![Join the chat at https://gitter.im/ethereum/remix](https://badges.gitter.im/ethereum/remix.svg)](https://gitter.im/ethereum/remix?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) [![Join the chat at https://gitter.im/ethereum/remix](https://badges.gitter.im/ethereum/remix.svg)](https://gitter.im/ethereum/remix?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
[![CircleCI](https://circleci.com/gh/ethereum/remix.svg?style=svg)](https://circleci.com/gh/ethereum/remix) [![CircleCI](https://circleci.com/gh/ethereum/remix/tree/master.svg?style=svg)](https://circleci.com/gh/ethereum/remix/tree/master)
[![Documentation Status](https://readthedocs.org/projects/docs/badge/?version=latest)](https://remix.readthedocs.io/en/latest/) [![Documentation Status](https://readthedocs.org/projects/docs/badge/?version=latest)](https://remix.readthedocs.io/en/latest/)
Ethereum tools for the web. Ethereum tools for the web.
...@@ -50,6 +50,7 @@ Remix is built out of several different modules: ...@@ -50,6 +50,7 @@ Remix is built out of several different modules:
+ [`remix-lib`](remix-lib/README.md) + [`remix-lib`](remix-lib/README.md)
+ [`remix-debug`](remix-debugger/README.md) is now *deprecated*. It contains the debugger. + [`remix-debug`](remix-debugger/README.md) is now *deprecated*. It contains the debugger.
+ [`remix-tests`](remix-tests/README.md) contains our tests. + [`remix-tests`](remix-tests/README.md) contains our tests.
+ [`remixd`](https://github.com/ethereum/remixd/tree/master) CLI which allow accessing local element from Remix IDE (see https://remix.readthedocs.io/en/latest/tutorial_remixd_filesystem.html)
Each generally has their own npm package and test suite, as well as basic documentation. Each generally has their own npm package and test suite, as well as basic documentation.
......
...@@ -24,8 +24,12 @@ This execute tests. The execution is run in a separate environment and the resul ...@@ -24,8 +24,12 @@ This execute tests. The execution is run in a separate environment and the resul
| `Assert.greaterThan()` | `uint`, `int` | | `Assert.greaterThan()` | `uint`, `int` |
| `Assert.lesserThan()` | `uint`, `int` | | `Assert.lesserThan()` | `uint`, `int` |
see [https://github.com/ethereum/remix/blob/master/remix-tests/tests/examples_4/SafeMath_test.sol](https://github.com/ethereum/remix/blob/master/remix-tests/tests/examples_4/SafeMath_test.sol) for some code sample
Continuous integration Continuous integration
---------------------- ----------------------
remix-tests is also a CLI, it can be used in a continuous integration environement which support node.js. remix-tests is also a CLI, it can be used in a continuous integration environement which support node.js.
Please find more information in the [remix-test repository](https://github.com/ethereum/remix/tree/master/remix-tests) Please find more information in the [remix-test repository](https://github.com/ethereum/remix/tree/master/remix-tests)
See also: example [Su Squares contract](https://github.com/su-squares/ethereum-contract/tree/e542f37d4f8f6c7b07d90a6554424268384a4186) and [https://travis-ci.org/su-squares/ethereum-contract/builds/446186067](Travis build) that uses remix-tests for continuous integration testing.
...@@ -10,5 +10,5 @@ This tutorial was used in workshops at ethCC, Edcon, and DappCon. ...@@ -10,5 +10,5 @@ This tutorial was used in workshops at ethCC, Edcon, and DappCon.
You can [watch the Edcon presentation talk](https://www.youtube.com/watch?v=nAI_Cr5Y8JY) and here are the [workshop slides](https://slides.com/ninabreznik/deck-11-13#/). You can [watch the Edcon presentation talk](https://www.youtube.com/watch?v=nAI_Cr5Y8JY) and here are the [workshop slides](https://slides.com/ninabreznik/deck-11-13#/).
(May 3, 2018) (May 3, 2018)
Here are the [DappCon slides (hosted on swarm)](https://30400.swarm-gateways.net/bzz:/2271229d214f8aef9b1176bc22dbc09e384cd8c577a87c60ebece68aebc59d3a/) and here are the [DappCon slides (not on swarm)](https://www.updig.is/pdf/remix-at-dappcon.pdf). Here are the [latest slides (hosted on swarm)](http://30400.swarm-gateways.net/bzz:/49277e2a16baf5576c9f54204c70dc403a425c3df85424864fe04ad6dfc609bc/) and here are the [latest slides (not on swarm)](https://www.updig.is/pdf/remix-chez-coinhouse.pdf).
(July 19, 2018) (Oct 16, 2018)
\ No newline at end of file \ No newline at end of file
#!/usr/bin/env node
'use strict';
var gulp = require('gulp');
var exec = require('child_process').exec;
var packageJSON = require('./package.json');
gulp.task('publishTag', function () {
exec("git tag v"+ packageJSON.version +"; git push --tags");
});
...@@ -8,5 +8,14 @@ ...@@ -8,5 +8,14 @@
"remix-tests", "remix-tests",
"remix-simulator" "remix-simulator"
], ],
"command": {
"init": {
"exact": true
},
"publish": {
"exact": true,
"skipGit": true
}
},
"version": "independent" "version": "independent"
} }
{ {
"version": "0.1.2",
"devDependencies": { "devDependencies": {
"gulp": "^3.9.1",
"lerna": "^2.10.2" "lerna": "^2.10.2"
}, },
"scripts": { "scripts": {
"diff": "lerna diff",
"updated": "lerna updated",
"bootstrap": "lerna bootstrap", "bootstrap": "lerna bootstrap",
"publish": "lerna publish" "publish": "lerna publish",
"release": "lerna bootstrap; lerna publish;",
"tag": "gulp; gulp publishTag;"
} }
} }
# Release process
This document details steps for publishing packages and tag the code base accordingly:
- checkout a new branch
- npm run publish
- commit
- increment root package.json version
- commit
- merge the branch
- fetch origin/master
- checkout origin/master
- npm run tag
- github-changes -o ethereum -r remix -a --only-pulls --use-commit-body --only-merges --between-tags <previous>...<next>
- create a new release out of the changelog.md
- in changelog put list of published packages with version
{ {
"name": "remix-analyzer", "name": "remix-analyzer",
"version": "0.2.8", "version": "0.2.11",
"description": "Remix Analyzer", "description": "Remix Analyzer",
"main": "./index.js", "main": "./index.js",
"contributors": [ "contributors": [
...@@ -21,7 +21,7 @@ ...@@ -21,7 +21,7 @@
"babel-eslint": "^7.1.1", "babel-eslint": "^7.1.1",
"babel-plugin-transform-object-assign": "^6.22.0", "babel-plugin-transform-object-assign": "^6.22.0",
"babel-preset-es2015": "^6.24.0", "babel-preset-es2015": "^6.24.0",
"remix-lib": "^0.3.8", "remix-lib": "0.3.11",
"solc": "^0.4.24", "solc": "^0.4.24",
"standard": "^7.0.1", "standard": "^7.0.1",
"tape": "^4.6.0" "tape": "^4.6.0"
......
{ {
"name": "remix-debug", "name": "remix-debug",
"version": "0.2.9", "version": "0.2.12",
"description": "Ethereum IDE and tools for the web", "description": "Ethereum IDE and tools for the web",
"contributors": [ "contributors": [
{ {
...@@ -23,7 +23,7 @@ ...@@ -23,7 +23,7 @@
"fast-async": "^6.1.2", "fast-async": "^6.1.2",
"notify-error": "^1.2.0", "notify-error": "^1.2.0",
"npm-run-all": "^4.1.2", "npm-run-all": "^4.1.2",
"remix-lib": "^0.3.8", "remix-lib": "0.3.11",
"solc": "^0.4.24" "solc": "^0.4.24"
}, },
"devDependencies": { "devDependencies": {
......
{ {
"name": "remix-lib", "name": "remix-lib",
"version": "0.3.8", "version": "0.3.11",
"description": "Ethereum IDE and tools for the web", "description": "Ethereum IDE and tools for the web",
"contributors": [ "contributors": [
{ {
......
...@@ -85,6 +85,7 @@ function ExecutionContext () { ...@@ -85,6 +85,7 @@ function ExecutionContext () {
this.blockGasLimitDefault = 4300000 this.blockGasLimitDefault = 4300000
this.blockGasLimit = this.blockGasLimitDefault this.blockGasLimit = this.blockGasLimitDefault
this.customNetWorks = {}
this.init = function (config) { this.init = function (config) {
if (config.get('settings/always-use-vm')) { if (config.get('settings/always-use-vm')) {
...@@ -134,6 +135,20 @@ function ExecutionContext () { ...@@ -134,6 +135,20 @@ function ExecutionContext () {
} }
} }
this.removeProvider = function (name) {
if (name && this.customNetWorks[name]) {
delete this.customNetWorks[name]
self.event.trigger('removeProvider', [name])
}
}
this.addProvider = function (network) {
if (network && network.name && network.url) {
this.customNetWorks[network.name] = network
self.event.trigger('addProvider', [network])
}
}
this.internalWeb3 = function () { this.internalWeb3 = function () {
return web3 return web3
} }
...@@ -182,6 +197,11 @@ function ExecutionContext () { ...@@ -182,6 +197,11 @@ function ExecutionContext () {
if (context === 'web3') { if (context === 'web3') {
confirmCb(cb) confirmCb(cb)
} }
if (this.customNetWorks[context]) {
var provider = this.customNetWorks[context]
setProviderFromEndpoint(provider.url, provider.name, () => { cb() })
}
} }
this.currentblockGasLimit = function () { this.currentblockGasLimit = function () {
......
...@@ -122,6 +122,7 @@ web3VmProvider.prototype.txProcessed = function (self, data) { ...@@ -122,6 +122,7 @@ web3VmProvider.prototype.txProcessed = function (self, data) {
} }
self.txsReceipt[self.processingHash].logs = logs self.txsReceipt[self.processingHash].logs = logs
self.txsReceipt[self.processingHash].transactionHash = self.processingHash self.txsReceipt[self.processingHash].transactionHash = self.processingHash
self.txsReceipt[self.processingHash].status = '0x' + data.vm.exception.toString(16)
if (data.createdAddress) { if (data.createdAddress) {
var address = util.hexConvert(data.createdAddress) var address = util.hexConvert(data.createdAddress)
......
{ {
"name": "remix-simulator", "name": "remix-simulator",
"version": "0.0.4", "version": "0.0.6",
"description": "Ethereum IDE and tools for the web", "description": "Ethereum IDE and tools for the web",
"contributors": [ "contributors": [
{ {
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
"main": "./index.js", "main": "./index.js",
"dependencies": { "dependencies": {
"ansi-gray": "^0.1.1", "ansi-gray": "^0.1.1",
"babel-eslint": "^7.1.1",
"babel-plugin-transform-object-assign": "^6.22.0", "babel-plugin-transform-object-assign": "^6.22.0",
"babel-preset-es2017": "^6.24.1", "babel-preset-es2017": "^6.24.1",
"babelify": "^7.3.0", "babelify": "^7.3.0",
...@@ -23,7 +24,7 @@ ...@@ -23,7 +24,7 @@
"express": "^4.16.3", "express": "^4.16.3",
"fast-async": "^6.3.7", "fast-async": "^6.3.7",
"merge": "^1.2.0", "merge": "^1.2.0",
"remix-lib": "^0.2.5", "remix-lib": "0.3.11",
"standard": "^10.0.3", "standard": "^10.0.3",
"time-stamp": "^2.0.0", "time-stamp": "^2.0.0",
"web3": "1.0.0-beta.27" "web3": "1.0.0-beta.27"
......
...@@ -3,10 +3,15 @@ var Web3 = require('web3') ...@@ -3,10 +3,15 @@ var Web3 = require('web3')
var Accounts = function () { var Accounts = function () {
this.web3 = new Web3() this.web3 = new Web3()
// TODO: make it random and/or use remix-libs // TODO: make it random and/or use remix-libs
this.accounts = [this.web3.eth.accounts.create(['abcd'])] this.accounts = [this.web3.eth.accounts.create(['abcd']), this.web3.eth.accounts.create(['ef12']), this.web3.eth.accounts.create(['ef34'])]
this.accounts[this.accounts[0].address.toLowerCase()] = this.accounts[0] this.accounts[this.accounts[0].address.toLowerCase()] = this.accounts[0]
this.accounts[this.accounts[1].address.toLowerCase()] = this.accounts[1]
this.accounts[this.accounts[2].address.toLowerCase()] = this.accounts[2]
this.accounts[this.accounts[0].address.toLowerCase()].privateKey = Buffer.from(this.accounts[this.accounts[0].address.toLowerCase()].privateKey.slice(2), 'hex') this.accounts[this.accounts[0].address.toLowerCase()].privateKey = Buffer.from(this.accounts[this.accounts[0].address.toLowerCase()].privateKey.slice(2), 'hex')
this.accounts[this.accounts[1].address.toLowerCase()].privateKey = Buffer.from(this.accounts[this.accounts[1].address.toLowerCase()].privateKey.slice(2), 'hex')
this.accounts[this.accounts[2].address.toLowerCase()].privateKey = Buffer.from(this.accounts[this.accounts[2].address.toLowerCase()].privateKey.slice(2), 'hex')
} }
Accounts.prototype.methods = function () { Accounts.prototype.methods = function () {
......
...@@ -39,7 +39,7 @@ Transactions.prototype.eth_getTransactionReceipt = function (payload, cb) { ...@@ -39,7 +39,7 @@ Transactions.prototype.eth_getTransactionReceipt = function (payload, cb) {
'cumulativeGasUsed': '0x06345f', 'cumulativeGasUsed': '0x06345f',
'contractAddress': receipt.contractAddress, 'contractAddress': receipt.contractAddress,
'logs': receipt.logs, 'logs': receipt.logs,
'status': 1 'status': receipt.status
} }
cb(null, r) cb(null, r)
......
{ {
"name": "remix-solidity", "name": "remix-solidity",
"version": "0.2.8", "version": "0.2.12",
"description": "Ethereum IDE and tools for the web", "description": "Ethereum IDE and tools for the web",
"contributors": [ "contributors": [
{ {
...@@ -22,7 +22,7 @@ ...@@ -22,7 +22,7 @@
"ethereumjs-vm": "^2.3.3", "ethereumjs-vm": "^2.3.3",
"fast-async": "^6.1.2", "fast-async": "^6.1.2",
"npm-run-all": "^4.0.2", "npm-run-all": "^4.0.2",
"remix-lib": "^0.3.8", "remix-lib": "0.3.11",
"solc": "^0.5.0", "solc": "^0.5.0",
"standard": "^7.0.1", "standard": "^7.0.1",
"tape": "^4.6.0", "tape": "^4.6.0",
......
...@@ -313,7 +313,7 @@ function Compiler (handleImportCall) { ...@@ -313,7 +313,7 @@ function Compiler (handleImportCall) {
while ((match = importRegex.exec(files[fileName].content))) { while ((match = importRegex.exec(files[fileName].content))) {
var importFilePath = match[1] var importFilePath = match[1]
if (importFilePath.startsWith('./')) { if (importFilePath.startsWith('./')) {
var path = /(.*\/).*/.exec(target) var path = /(.*\/).*/.exec(fileName)
if (path !== null) { if (path !== null) {
importFilePath = importFilePath.replace('./', path[1]) importFilePath = importFilePath.replace('./', path[1])
} else { } else {
......
[![Build Status](https://travis-ci.org/ethereum/remix-tests.svg?branch=master)](https://travis-ci.org/ethereum/remix-tests)
Remix-Tests Remix-Tests
--- ---
...@@ -43,6 +41,8 @@ contract MyTest { ...@@ -43,6 +41,8 @@ contract MyTest {
} }
``` ```
See also: example [Su Squares contract](https://github.com/su-squares/ethereum-contract/tree/e542f37d4f8f6c7b07d90a6554424268384a4186) and [https://travis-ci.org/su-squares/ethereum-contract/builds/446186067](Travis build) that uses remix-tests for continuous integration testing.
Available special functions: Available special functions:
* `beforeEach()` - runs before each test * `beforeEach()` - runs before each test
* `beforeAll()` - runs before all tests * `beforeAll()` - runs before all tests
......
{ {
"name": "remix-tests", "name": "remix-tests",
"version": "0.0.13", "version": "0.0.18",
"description": "Tests for the Ethereum tool suite Remix", "description": "Tests for the Ethereum tool suite Remix",
"main": "./src/index.js", "main": "./src/index.js",
"contributors": [ "contributors": [
...@@ -41,13 +41,13 @@ ...@@ -41,13 +41,13 @@
"change-case": "^3.0.1", "change-case": "^3.0.1",
"colors": "^1.1.2", "colors": "^1.1.2",
"commander": "^2.13.0", "commander": "^2.13.0",
"remix-lib": "^0.3.8", "remix-lib": "0.3.11",
"remix-simulator": "^0.0.4", "remix-simulator": "0.0.6",
"remix-solidity": "^0.2.8", "remix-solidity": "0.2.12",
"signale": "^1.2.1", "signale": "^1.2.1",
"solc": "^0.4.24", "solc": "^0.4.24",
"standard": "^10.0.3", "standard": "^10.0.3",
"web3": "1.0.0-beta.34", "web3": "1.0.0-beta.36",
"winston": "^3.0.0" "winston": "^3.0.0"
}, },
"peerDependencies": { "peerDependencies": {
......
module.exports = `pragma solidity ^0.4.7;
library TestsAccounts {
function getAccount(uint index) returns (address) {
>accounts<
return accounts[index];
}
}
`
...@@ -9,18 +9,28 @@ String.prototype.regexIndexOf = function (regex, startpos) { ...@@ -9,18 +9,28 @@ String.prototype.regexIndexOf = function (regex, startpos) {
return (indexOf >= 0) ? (indexOf + (startpos || 0)) : indexOf return (indexOf >= 0) ? (indexOf + (startpos || 0)) : indexOf
} }
function writeTestAccountsContract (accounts) {
var testAccountContract = require('../sol/tests_accounts.sol.js')
var body = 'address[' + accounts.length + '] memory accounts'
if (!accounts.length) body += ';'
else {
body += '= [' + accounts.map((value) => { return `address(${value})` }).join(',') + '];'
}
return testAccountContract.replace('>accounts<', body)
}
var userAgent = (typeof (navigator) !== 'undefined') && navigator.userAgent ? navigator.userAgent.toLowerCase() : '-' var userAgent = (typeof (navigator) !== 'undefined') && navigator.userAgent ? navigator.userAgent.toLowerCase() : '-'
var isBrowser = !(typeof (window) === 'undefined' || userAgent.indexOf(' electron/') > -1) var isBrowser = !(typeof (window) === 'undefined' || userAgent.indexOf(' electron/') > -1)
// TODO: replace this with remix's own compiler code // TODO: replace this with remix's own compiler code
function compileFileOrFiles (filename, isDirectory, cb) { function compileFileOrFiles (filename, isDirectory, opts, cb) {
let compiler, filepath let compiler, filepath
let accounts = opts.accounts || []
const sources = { const sources = {
'tests.sol': { content: require('../sol/tests.sol.js') }, 'tests.sol': { content: require('../sol/tests.sol.js') },
'remix_tests.sol': { content: require('../sol/tests.sol.js') } 'remix_tests.sol': { content: require('../sol/tests.sol.js') },
'remix_accounts.sol': { content: writeTestAccountsContract(accounts) }
} }
// TODO: for now assumes filepath dir contains all tests, later all this // TODO: for now assumes filepath dir contains all tests, later all this
// should be replaced with remix's & browser solidity compiler code // should be replaced with remix's & browser solidity compiler code
filepath = (isDirectory ? filename : path.dirname(filename)) filepath = (isDirectory ? filename : path.dirname(filename))
...@@ -31,7 +41,7 @@ function compileFileOrFiles (filename, isDirectory, cb) { ...@@ -31,7 +41,7 @@ function compileFileOrFiles (filename, isDirectory, cb) {
let c = fs.readFileSync(path.join(filepath, file)).toString() let c = fs.readFileSync(path.join(filepath, file)).toString()
const s = /^(import)\s['"](remix_tests.sol|tests.sol)['"];/gm const s = /^(import)\s['"](remix_tests.sol|tests.sol)['"];/gm
if (file.indexOf('_test.sol') > 0 && c.regexIndexOf(s) < 0) { if (file.indexOf('_test.sol') > 0 && c.regexIndexOf(s) < 0) {
c = c.replace(/(pragma solidity \^\d+\.\d+\.\d+;)/, '$1\nimport \'remix_tests.sol\';') c = c.replace(/(pragma solidity \^?\d+\.\d+\.\d+;)/, '$1\nimport \'remix_tests.sol\';')
} }
sources[file] = { content: c } sources[file] = { content: c }
} }
...@@ -61,12 +71,13 @@ function compileFileOrFiles (filename, isDirectory, cb) { ...@@ -61,12 +71,13 @@ function compileFileOrFiles (filename, isDirectory, cb) {
}) })
} }
function compileContractSources (sources, importFileCb, cb) { function compileContractSources (sources, importFileCb, opts, cb) {
let compiler, filepath let compiler, filepath
let accounts = opts.accounts || []
// Iterate over sources keys. Inject test libraries. Inject test library import statements. // Iterate over sources keys. Inject test libraries. Inject test library import statements.
if (!('remix_tests.sol' in sources) && !('tests.sol' in sources)) { if (!('remix_tests.sol' in sources) && !('tests.sol' in sources)) {
sources['remix_tests.sol'] = { content: require('../sol/tests.sol.js') } sources['remix_tests.sol'] = { content: require('../sol/tests.sol.js') }
sources['remix_accounts.sol'] = { content: writeTestAccountsContract(accounts) }
} }
const s = /^(import)\s['"](remix_tests.sol|tests.sol)['"];/gm const s = /^(import)\s['"](remix_tests.sol|tests.sol)['"];/gm
for (let file in sources) { for (let file in sources) {
......
...@@ -16,13 +16,22 @@ var createWeb3Provider = function () { ...@@ -16,13 +16,22 @@ var createWeb3Provider = function () {
return web3 return web3
} }
var runTestSources = function (contractSources, testCallback, resultCallback, finalCallback, importFileCb) { var runTestSources = function (contractSources, testCallback, resultCallback, finalCallback, importFileCb, opts) {
opts = opts || {}
let web3 = opts.web3 || createWeb3Provider()
let accounts = opts.accounts || null
async.waterfall([ async.waterfall([
function getAccountList (next) {
if (accounts) return next()
web3.eth.getAccounts((_err, _accounts) => {
accounts = _accounts
next()
})
},
function compile (next) { function compile (next) {
Compiler.compileContractSources(contractSources, importFileCb, next) Compiler.compileContractSources(contractSources, importFileCb, { accounts }, next)
}, },
function deployAllContracts (compilationResult, next) { function deployAllContracts (compilationResult, next) {
let web3 = createWeb3Provider()
Deployer.deployAll(compilationResult, web3, function (err, contracts) { Deployer.deployAll(compilationResult, web3, function (err, contracts) {
if (err) { if (err) {
next(err) next(err)
...@@ -33,19 +42,21 @@ var runTestSources = function (contractSources, testCallback, resultCallback, fi ...@@ -33,19 +42,21 @@ var runTestSources = function (contractSources, testCallback, resultCallback, fi
}, },
function determineTestContractsToRun (compilationResult, contracts, next) { function determineTestContractsToRun (compilationResult, contracts, next) {
let contractsToTest = [] let contractsToTest = []
let contractsToTestDetails = []
for (let filename in compilationResult) { for (let filename in compilationResult) {
if (filename.indexOf('_test.sol') < 0) { if (filename.indexOf('_test.sol') < 0) {
continue continue
} }
Object.keys(compilationResult[filename]).forEach(contractName => { Object.keys(compilationResult[filename]).forEach(contractName => {
contractsToTestDetails.push(compilationResult[filename][contractName])
contractsToTest.push(contractName) contractsToTest.push(contractName)
}) })
} }
next(null, contractsToTest, contracts) next(null, contractsToTest, contractsToTestDetails, contracts)
}, },
function runTests (contractsToTest, contracts, next) { function runTests (contractsToTest, contractsToTestDetails, contracts, next) {
let totalPassing = 0 let totalPassing = 0
let totalFailing = 0 let totalFailing = 0
let totalTime = 0 let totalTime = 0
...@@ -67,7 +78,7 @@ var runTestSources = function (contractSources, testCallback, resultCallback, fi ...@@ -67,7 +78,7 @@ var runTestSources = function (contractSources, testCallback, resultCallback, fi
} }
async.eachOfLimit(contractsToTest, 1, (contractName, index, cb) => { async.eachOfLimit(contractsToTest, 1, (contractName, index, cb) => {
TestRunner.runTest(contractName, contracts[contractName], _testCallback, (err, result) => { TestRunner.runTest(contractName, contracts[contractName], contractsToTestDetails[index], { accounts }, _testCallback, (err, result) => {
if (err) { if (err) {
return cb(err) return cb(err)
} }
...@@ -95,7 +106,8 @@ var runTestSources = function (contractSources, testCallback, resultCallback, fi ...@@ -95,7 +106,8 @@ var runTestSources = function (contractSources, testCallback, resultCallback, fi
], finalCallback) ], finalCallback)
} }
var runTestFiles = function (filepath, isDirectory, web3) { var runTestFiles = function (filepath, isDirectory, web3, opts) {
opts = opts || {}
const { Signale } = require('signale') const { Signale } = require('signale')
// signale configuration // signale configuration
const options = { const options = {
...@@ -118,37 +130,49 @@ var runTestFiles = function (filepath, isDirectory, web3) { ...@@ -118,37 +130,49 @@ var runTestFiles = function (filepath, isDirectory, web3) {
} }
} }
const signale = new Signale(options) const signale = new Signale(options)
let accounts = opts.accounts || null
async.waterfall([ async.waterfall([
function getAccountList (next) {
if (accounts) return next(null)
web3.eth.getAccounts((_err, _accounts) => {
accounts = _accounts
next(null)
})
},
function compile (next) { function compile (next) {
Compiler.compileFileOrFiles(filepath, isDirectory, next) Compiler.compileFileOrFiles(filepath, isDirectory, { accounts }, next)
}, },
function deployAllContracts (compilationResult, next) { function deployAllContracts (compilationResult, next) {
Deployer.deployAll(compilationResult, web3, function (err, contracts) { Deployer.deployAll(compilationResult, web3, function (err, contracts) {
if (err) { if (err) {
next(err) next(err)
} }
next(null, compilationResult, contracts) next(null, compilationResult, contracts)
}) })
}, },
function determineTestContractsToRun (compilationResult, contracts, next) { function determineTestContractsToRun (compilationResult, contracts, next) {
let contractsToTest = [] let contractsToTest = []
if (isDirectory) { let contractsToTestDetails = []
fs.readdirSync(filepath).forEach(filename => { var gatherContractsFrom = (filename) => {
if (filename.indexOf('_test.sol') < 0) { if (filename.indexOf('_test.sol') < 0) {
return return
} }
Object.keys(compilationResult[path.basename(filename)]).forEach(contractName => { Object.keys(compilationResult[path.basename(filename)]).forEach(contractName => {
contractsToTest.push(contractName) contractsToTest.push(contractName)
contractsToTestDetails.push(compilationResult[path.basename(filename)][contractName])
}) })
}
if (isDirectory) {
fs.readdirSync(filepath).forEach(filename => {
gatherContractsFrom(filename)
}) })
} else { } else {
contractsToTest = Object.keys(compilationResult[path.basename(filepath)]) gatherContractsFrom(filepath)
} }
next(null, contractsToTest, contractsToTestDetails, contracts)
next(null, contractsToTest, contracts)
}, },
function runTests (contractsToTest, contracts, next) { function runTests (contractsToTest, contractsToTestDetails, contracts, next) {
let totalPassing = 0 let totalPassing = 0
let totalFailing = 0 let totalFailing = 0
let totalTime = 0 let totalTime = 0
...@@ -172,7 +196,7 @@ var runTestFiles = function (filepath, isDirectory, web3) { ...@@ -172,7 +196,7 @@ var runTestFiles = function (filepath, isDirectory, web3) {
} }
async.eachOfLimit(contractsToTest, 1, (contractName, index, cb) => { async.eachOfLimit(contractsToTest, 1, (contractName, index, cb) => {
TestRunner.runTest(contractName, contracts[contractName], testCallback, (err, result) => { TestRunner.runTest(contractName, contracts[contractName], contractsToTestDetails[index], { accounts }, testCallback, (err, result) => {
if (err) { if (err) {
return cb(err) return cb(err)
} }
......
...@@ -2,6 +2,20 @@ var async = require('async') ...@@ -2,6 +2,20 @@ var async = require('async')
var changeCase = require('change-case') var changeCase = require('change-case')
var Web3 = require('web3') var Web3 = require('web3')
function getFunctionFullName (signature, methodIdentifiers) {
for (var method in methodIdentifiers) {
if (signature.replace('0x', '') === methodIdentifiers[method].replace('0x', '')) {
return method
}
}
return null
}
function getOverridedSender (userdoc, signature, methodIdentifiers) {
let fullName = getFunctionFullName(signature, methodIdentifiers)
return fullName && userdoc.methods[fullName] ? userdoc.methods[fullName].notice : null
}
function getAvailableFunctions (jsonInterface) { function getAvailableFunctions (jsonInterface) {
return jsonInterface.reverse().filter((x) => x.type === 'function').map((x) => x.name) return jsonInterface.reverse().filter((x) => x.type === 'function').map((x) => x.name)
} }
...@@ -24,7 +38,7 @@ function createRunList (jsonInterface) { ...@@ -24,7 +38,7 @@ function createRunList (jsonInterface) {
if (availableFunctions.indexOf('beforeEach') >= 0) { if (availableFunctions.indexOf('beforeEach') >= 0) {
runList.push({name: 'beforeEach', type: 'internal', constant: false}) runList.push({name: 'beforeEach', type: 'internal', constant: false})
} }
runList.push({name: func.name, type: 'test', constant: func.constant}) runList.push({name: func.name, signature: func.signature, type: 'test', constant: func.constant})
if (availableFunctions.indexOf('afterEach') >= 0) { if (availableFunctions.indexOf('afterEach') >= 0) {
runList.push({name: 'afterEach', type: 'internal', constant: false}) runList.push({name: 'afterEach', type: 'internal', constant: false})
} }
...@@ -37,7 +51,7 @@ function createRunList (jsonInterface) { ...@@ -37,7 +51,7 @@ function createRunList (jsonInterface) {
return runList return runList
} }
function runTest (testName, testObject, testCallback, resultsCallback) { function runTest (testName, testObject, contractDetails, opts, testCallback, resultsCallback) {
let runList = createRunList(testObject._jsonInterface) let runList = createRunList(testObject._jsonInterface)
let passingNum = 0 let passingNum = 0
...@@ -45,12 +59,32 @@ function runTest (testName, testObject, testCallback, resultsCallback) { ...@@ -45,12 +59,32 @@ function runTest (testName, testObject, testCallback, resultsCallback) {
let timePassed = 0 let timePassed = 0
let web3 = new Web3() let web3 = new Web3()
var userAgent = (typeof (navigator) !== 'undefined') && navigator.userAgent ? navigator.userAgent.toLowerCase() : '-'
var isBrowser = !(typeof (window) === 'undefined' || userAgent.indexOf(' electron/') > -1)
if (!isBrowser) {
let signale = require('signale')
signale.warn('DO NOT TRY TO ACCESS (IN YOUR SOLIDITY TEST) AN ACCOUNT GREATER THAN THE LENGTH OF THE FOLLOWING ARRAY (' + opts.accounts.length + ') :')
signale.warn(opts.accounts)
signale.warn('e.g: the following code won\'t work in the current context:')
signale.warn('TestsAccounts.getAccount(' + opts.accounts.length + ')')
}
testCallback({type: 'contract', value: testName, filename: testObject.filename}) testCallback({type: 'contract', value: testName, filename: testObject.filename})
async.eachOfLimit(runList, 1, function (func, index, next) { async.eachOfLimit(runList, 1, function (func, index, next) {
let sender
if (func.signature) {
sender = getOverridedSender(contractDetails.userdoc, func.signature, contractDetails.evm.methodIdentifiers)
if (opts.accounts) {
sender = opts.accounts[sender]
}
}
let sendParams
if (sender) sendParams = { from: sender }
let method = testObject.methods[func.name].apply(testObject.methods[func.name], []) let method = testObject.methods[func.name].apply(testObject.methods[func.name], [])
let startTime = Date.now() let startTime = Date.now()
if (func.constant) { if (func.constant) {
method.call().then((result) => { method.call(sendParams).then((result) => {
let time = Math.ceil((Date.now() - startTime) / 1000.0) let time = Math.ceil((Date.now() - startTime) / 1000.0)
if (result) { if (result) {
testCallback({type: 'testPass', value: changeCase.sentenceCase(func.name), time: time, context: testName}) testCallback({type: 'testPass', value: changeCase.sentenceCase(func.name), time: time, context: testName})
...@@ -63,7 +97,7 @@ function runTest (testName, testObject, testCallback, resultsCallback) { ...@@ -63,7 +97,7 @@ function runTest (testName, testObject, testCallback, resultsCallback) {
next() next()
}) })
} else { } else {
method.send().on('receipt', function (receipt) { method.send(sendParams).on('receipt', function (receipt) {
try { try {
let time = Math.ceil((Date.now() - startTime) / 1000.0) let time = Math.ceil((Date.now() - startTime) / 1000.0)
let topic = Web3.utils.sha3('AssertionEvent(bool,string)') let topic = Web3.utils.sha3('AssertionEvent(bool,string)')
...@@ -95,11 +129,12 @@ function runTest (testName, testObject, testCallback, resultsCallback) { ...@@ -95,11 +129,12 @@ function runTest (testName, testObject, testCallback, resultsCallback) {
return next(err) return next(err)
} }
}).on('error', function (err) { }).on('error', function (err) {
console.error(err)
next(err) next(err)
}) })
} }
}, function () { }, function (error) {
resultsCallback(null, { resultsCallback(error, {
passingNum: passingNum, passingNum: passingNum,
failureNum: failureNum, failureNum: failureNum,
timePassed: timePassed timePassed: timePassed
......
...@@ -10,19 +10,28 @@ const Provider = require('remix-simulator').Provider ...@@ -10,19 +10,28 @@ const Provider = require('remix-simulator').Provider
function compileAndDeploy (filename, callback) { function compileAndDeploy (filename, callback) {
let web3 = new Web3() let web3 = new Web3()
web3.setProvider(new Provider()) web3.setProvider(new Provider())
let compilationData
let accounts
async.waterfall([ async.waterfall([
function getAccountList (next) {
web3.eth.getAccounts((_err, _accounts) => {
accounts = _accounts
next(_err)
})
},
function compile (next) { function compile (next) {
Compiler.compileFileOrFiles(filename, false, next) Compiler.compileFileOrFiles(filename, false, {accounts}, next)
}, },
function deployAllContracts (compilationResult, next) { function deployAllContracts (compilationResult, next) {
compilationData = compilationResult
Deployer.deployAll(compilationResult, web3, next) Deployer.deployAll(compilationResult, web3, next)
} }
], function (_err, contracts) { ], function (_err, contracts) {
callback(null, contracts) callback(null, compilationData, contracts, accounts)
}) })
} }
describe('testRunner', function () { describe('testRunner', function () {
describe('#runTest', function() { describe('#runTest', function() {
describe('test with beforeAll', function () { describe('test with beforeAll', function () {
...@@ -30,7 +39,7 @@ describe('testRunner', function () { ...@@ -30,7 +39,7 @@ describe('testRunner', function () {
let tests = [], results = {} let tests = [], results = {}
before(function (done) { before(function (done) {
compileAndDeploy(filename, function (_err, contracts) { compileAndDeploy(filename, function (_err, compilationData, contracts, accounts) {
var testCallback = function (test) { var testCallback = function (test) {
tests.push(test) tests.push(test)
} }
...@@ -38,7 +47,7 @@ describe('testRunner', function () { ...@@ -38,7 +47,7 @@ describe('testRunner', function () {
results = _results results = _results
done() done()
} }
TestRunner.runTest('MyTest', contracts.MyTest, testCallback, resultsCallback) TestRunner.runTest('MyTest', contracts.MyTest, compilationData['simple_storage_test.sol']['MyTest'], { accounts }, testCallback, resultsCallback)
}) })
}) })
...@@ -66,7 +75,7 @@ describe('testRunner', function () { ...@@ -66,7 +75,7 @@ describe('testRunner', function () {
let tests = [], results = {} let tests = [], results = {}
before(function (done) { before(function (done) {
compileAndDeploy(filename, function (_err, contracts) { compileAndDeploy(filename, function (_err, compilationData, contracts, accounts) {
var testCallback = function (test) { var testCallback = function (test) {
tests.push(test) tests.push(test)
} }
...@@ -74,7 +83,7 @@ describe('testRunner', function () { ...@@ -74,7 +83,7 @@ describe('testRunner', function () {
results = _results results = _results
done() done()
} }
TestRunner.runTest('MyTest', contracts.MyTest, testCallback, resultsCallback) TestRunner.runTest('MyTest', contracts.MyTest, compilationData['simple_storage_test.sol']['MyTest'], { accounts }, testCallback, resultsCallback)
}) })
}) })
...@@ -101,7 +110,7 @@ describe('testRunner', function () { ...@@ -101,7 +110,7 @@ describe('testRunner', function () {
let tests = [], results = {} let tests = [], results = {}
before(function (done) { before(function (done) {
compileAndDeploy(filename, function (_err, contracts) { compileAndDeploy(filename, function (_err, compilationData, contracts, accounts) {
var testCallback = function (test) { var testCallback = function (test) {
tests.push(test) tests.push(test)
} }
...@@ -109,8 +118,8 @@ describe('testRunner', function () { ...@@ -109,8 +118,8 @@ describe('testRunner', function () {
results = _results results = _results
done() done()
} }
TestRunner.runTest('StringTest', contracts.StringTest, testCallback, resultsCallback) TestRunner.runTest('StringTest', contracts.StringTest, compilationData['simple_string_test.sol']['StringTest'], { accounts }, testCallback, resultsCallback)
TestRunner.runTest('StringTest2', contracts.StringTest2, testCallback, resultsCallback) TestRunner.runTest('StringTest2', contracts.StringTest2, compilationData['simple_string_test.sol']['StringTest2'], { accounts }, testCallback, resultsCallback)
}) })
}) })
...@@ -138,7 +147,7 @@ describe('testRunner', function () { ...@@ -138,7 +147,7 @@ describe('testRunner', function () {
let tests = [], results = {} let tests = [], results = {}
before(function (done) { before(function (done) {
compileAndDeploy(filename, function (_err, contracts) { compileAndDeploy(filename, function (_err, compilationData, contracts, accounts) {
var testCallback = function (test) { var testCallback = function (test) {
tests.push(test) tests.push(test)
} }
...@@ -146,7 +155,7 @@ describe('testRunner', function () { ...@@ -146,7 +155,7 @@ describe('testRunner', function () {
results = _results results = _results
done() done()
} }
TestRunner.runTest('IntegerTest', contracts.IntegerTest, testCallback, resultsCallback) TestRunner.runTest('IntegerTest', contracts.IntegerTest, compilationData['number_test.sol']['IntegerTest'], { accounts }, testCallback, resultsCallback)
}) })
}) })
...@@ -157,5 +166,33 @@ describe('testRunner', function () { ...@@ -157,5 +166,33 @@ describe('testRunner', function () {
assert.equal(results.failureNum, 2) assert.equal(results.failureNum, 2)
}) })
}) })
// Test Transaction with different sender
describe('various sender', function () {
let filename = 'tests/various_sender/sender_test.sol'
let tests = [], results = {}
before(function (done) {
compileAndDeploy(filename, function (_err, compilationData, contracts, accounts) {
var testCallback = function (test) {
tests.push(test)
}
var resultsCallback = function (_err, _results) {
results = _results
done()
}
TestRunner.runTest('SenderTest', contracts.SenderTest, compilationData['sender_test.sol']['SenderTest'], { accounts }, testCallback, resultsCallback)
})
})
it('should have 4 passing tests', function () {
assert.equal(results.passingNum, 4)
})
it('should have 1 failing tests', function () {
assert.equal(results.failureNum, 0)
})
})
}) })
}) })
pragma solidity ^0.4.7;
import "remix_tests.sol"; // this import is automatically injected by Remix.
import "remix_accounts.sol";
contract SenderTest {
function beforeAll () {}
/// 1
function checkSenderIs1 () public {
Assert.equal(msg.sender, TestsAccounts.getAccount(1), "wrong sender in checkSenderIs1");
}
/// 0
function checkSenderIs0 () public {
Assert.equal(msg.sender, TestsAccounts.getAccount(0), "wrong sender in checkSenderIs0");
}
/// 1
function checkSenderIsNt0 () public {
Assert.notEqual(msg.sender, TestsAccounts.getAccount(0), "wrong sender in checkSenderIsNot0");
}
/// 2
function checkSenderIsnt2 () public {
Assert.notEqual(msg.sender, TestsAccounts.getAccount(1), "wrong sender in checkSenderIsnt2");
}
}
Subproject commit 1a9ec3230e7a3c278ddc6344e5c89d488a316910
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment