From 7cb9cd56222dc4aaf8f34b322f35b4294c2fc889 Mon Sep 17 00:00:00 2001 From: emizzle Date: Tue, 31 Jul 2018 14:54:28 +1000 Subject: [PATCH] Basic unit tests complete for dev funds Finished added unit tests for dev_funds. These are weak tests as the FakeIpcProvider does not provide enough support for keeping track of accounts and balances and instead we are injecting the provider responses in the tests, which kind of defeats the purposes of the tests. Instead, the FakeIpcProvider should be a little smarter and do more of what a real node would do. --- lib/cmds/blockchain/blockchain.js | 5 +- lib/cmds/blockchain/dev_funds.js | 37 ++++----- test/devFunds.js | 122 +++++++++++++++++------------- 3 files changed, 83 insertions(+), 81 deletions(-) diff --git a/lib/cmds/blockchain/blockchain.js b/lib/cmds/blockchain/blockchain.js index 9be5a974..6cf02ab4 100644 --- a/lib/cmds/blockchain/blockchain.js +++ b/lib/cmds/blockchain/blockchain.js @@ -170,9 +170,8 @@ Blockchain.prototype.run = function() { if (self.onReadyCallback && !self.readyCalled && data.indexOf('WebSocket endpoint opened') > -1) { if (self.isDev) { self.createFundAndUnlockAccounts((err) => { + // TODO: this is never called! if(err) console.error('Error creating, unlocking, and funding accounts', err); - //self.readyCalled = true; - //self.onReadyCallback(); }); } self.readyCalled = true; @@ -189,7 +188,7 @@ Blockchain.prototype.run = function() { }; Blockchain.prototype.createFundAndUnlockAccounts = function(cb) { - let devFunds = new DevFunds(this.config); + let devFunds = new DevFunds({blockchainConfig: this.config}); devFunds.createFundAndUnlockAccounts((err) => { cb(err); }); diff --git a/lib/cmds/blockchain/dev_funds.js b/lib/cmds/blockchain/dev_funds.js index ae8a524d..6b86533f 100644 --- a/lib/cmds/blockchain/dev_funds.js +++ b/lib/cmds/blockchain/dev_funds.js @@ -1,29 +1,29 @@ const async = require('async'); const Web3 = require('web3'); -const { getWeiBalanceFromString, buildUrl } = require('../../utils/utils.js'); -const { readFileSync, dappPath } = require('../../core/fs'); +const {getWeiBalanceFromString, buildUrl} = require('../../utils/utils.js'); +const {readFileSync, dappPath} = require('../../core/fs'); class DevFunds { - constructor(blockchainConfig, provider, logger) { - this.blockchainConfig = blockchainConfig; + constructor(options) { + this.blockchainConfig = options.blockchainConfig; this.accounts = []; this.numAccounts = this.blockchainConfig.account.numAccounts || 0; - this.password = blockchainConfig.account.password ? readFileSync(dappPath(blockchainConfig.account.password), 'utf8').replace('\n', '') : 'dev_password'; + this.password = this.blockchainConfig.account.password ? readFileSync(dappPath(this.blockchainConfig.account.password), 'utf8').replace('\n', '') : 'dev_password'; this.networkId = null; this.balance = Web3.utils.toWei("1", "ether"); - this.provider = provider || new Web3.providers.WebsocketProvider(buildUrl('ws', this.blockchainConfig.wsHost, this.blockchainConfig.wsPort), { headers: { Origin: "http://localhost:8000" } }); - this.web3 = new Web3(provider); + this.provider = options.provider || new Web3.providers.WebsocketProvider(buildUrl('ws', this.blockchainConfig.wsHost, this.blockchainConfig.wsPort), {headers: {Origin: "http://localhost:8000"}}); + this.web3 = new Web3(this.provider); if (this.blockchainConfig.account.balance) { this.balance = getWeiBalanceFromString(this.blockchainConfig.account.balance, this.web3); } - this.logger = logger || console; + this.logger = options.logger || console; } _sendTx() { if (this.networkId !== 1337) { return; } - this.web3.eth.sendTransaction({ value: "1000000000000000", to: "0xA2817254cb8E7b6269D1689c3E0eBadbB78889d1", from: this.web3.eth.defaultAccount }); + this.web3.eth.sendTransaction({value: "1000000000000000", to: "0xA2817254cb8E7b6269D1689c3E0eBadbB78889d1", from: this.web3.eth.defaultAccount}); } // trigger regular txs due to a bug in geth and stuck transactions in --dev mode @@ -48,7 +48,6 @@ class DevFunds { } getCurrentAccounts(cb) { - this.web3.eth.getAccounts().then((accounts) => { this.web3.eth.defaultAccount = accounts[0]; if (accounts.length > 1) { @@ -80,25 +79,15 @@ class DevFunds { } fundAccounts(balance, cb) { - this.logger.info('[dev_funds]: funding accounts'); async.each(this.accounts, (account, next) => { - this.logger.info('[dev_funds]: funding acct ' + account); this.web3.eth.getBalance(account).then(currBalance => { - this.logger.info('[dev_funds]: acct ' + account + ' current balance ' + currBalance); const remainingBalance = balance - currBalance; if (remainingBalance <= 0) return next(); - this.logger.info('[dev_funds]: funding acct ' + account + ' with ' + remainingBalance); - - this.web3.eth.sendTransaction({ to: account, value: remainingBalance }).then((_result) => { - this.logger.info('[dev_funds]: funding result ' + JSON.stringify(_result)); - next(); - }).catch(next); - }, (err) => { - this.logger.info('[dev_funds]: done funding'); - cb(err); - }); - }); + this.web3.eth.sendTransaction({to: account, value: remainingBalance}).catch(next); + next(); // don't wait for the tx receipt as it never comes! + }).catch(cb); + }, cb); } createFundAndUnlockAccounts(cb) { diff --git a/test/devFunds.js b/test/devFunds.js index f960ea31..1994c00d 100644 --- a/test/devFunds.js +++ b/test/devFunds.js @@ -4,7 +4,6 @@ let TestLogger = require('../lib/tests/test_logger.js'); const Web3 = require('web3'); const i18n = require('../lib/i18n/i18n.js'); const constants = require('../lib/constants.json'); -const Test = require('../lib/tests/test'); const DevFunds = require('../lib/cmds/blockchain/dev_funds'); const async = require('async'); const FakeIpcProvider = require('./helpers/fakeIpcProvider'); @@ -52,73 +51,88 @@ describe('embark.DevFunds', function () { config.rpcPort += constants.blockchain.servicePortOnProxy; } - // TODO put default config - const test = new Test({ loglevel: 'trace' }); + describe('#create, fund, and unlock accounts', function () { + let provider = new FakeIpcProvider(); + let devFunds = new DevFunds({blockchainConfig: config, provider: provider, logger: new TestLogger({})}); + const web3 = new Web3(provider); + it('should create correct number of accounts', function (done) { + provider.injectResult(['0x47d33b27bb249a2dbab4c0612bf9caf4c1950855']); // getAccounts - return --dev account + devFunds.getCurrentAccounts(() => { - test.initWeb3Provider((err) => { - if (err) throw err; - describe('#create, fund, and unlock accounts', function () { - let provider = new FakeIpcProvider(); - let devFunds = new DevFunds(config, provider, new TestLogger({})); - const web3 = new Web3(provider); + provider.injectResult('0x11f4d0a3c12e86b4b5f39b213f7e19d048276dae'); // createAccount #1 + provider.injectResult('0x22f4d0a3c12e86b4b5f39b213f7e19d048276dab'); // createAccount #2 - it('should create correct number of accounts', function (done) { - provider.injectResult(['0x47d33b27bb249a2dbab4c0612bf9caf4c1950855']); // getAccounts - return --dev account - devFunds.getCurrentAccounts(() => { + devFunds.createAccounts(config.account.numAccounts, 'test_password', (err) => { + assert.equal(err, null); - provider.injectResult('0x11f4d0a3c12e86b4b5f39b213f7e19d048276dae'); // createAccount #1 - provider.injectResult('0x22f4d0a3c12e86b4b5f39b213f7e19d048276dab'); // createAccount #2 + // TODO: make FakeIpcProvider smart enough to keep track of created accounts + provider.injectResult(['0x47d33b27bb249a2dbab4c0612bf9caf4c1950855', '0x11f4d0a3c12e86b4b5f39b213f7e19d048276dae', '0x22f4d0a3c12e86b4b5f39b213f7e19d048276dab']); - - devFunds.createAccounts(config.account.numAccounts, 'test_password', (err) => { - assert.equal(err, null); - - provider.injectResult(['0x47d33b27bb249a2dbab4c0612bf9caf4c1950855', '0x11f4d0a3c12e86b4b5f39b213f7e19d048276dae', '0x22f4d0a3c12e86b4b5f39b213f7e19d048276dab']); - web3.eth.getAccounts().then((accts) => { - console.log('got accts: ' + JSON.stringify(accts)); - assert.equal(accts.length, config.account.numAccounts); - assert.strictEqual(accts[0], '0x47D33b27Bb249a2DBab4C0612BF9CaF4C1950855'); - assert.strictEqual(accts[1], '0x11f4d0A3c12e86B4b5F39B213F7E19D048276DAe'); - assert.strictEqual(accts[2], '0x22F4d0A3C12E86b4b5F39B213f7e19D048276DAb'); - done(); - }); + web3.eth.getAccounts().then((accts) => { + assert.equal(accts.length, config.account.numAccounts); + assert.strictEqual(accts[0], '0x47D33b27Bb249a2DBab4C0612BF9CaF4C1950855'); + assert.strictEqual(accts[1], '0x11f4d0A3c12e86B4b5F39B213F7E19D048276DAe'); + assert.strictEqual(accts[2], '0x22F4d0A3C12E86b4b5F39B213f7e19D048276DAb'); + done(); }); }); }); + }); - it('should fund accounts', function (done) { - console.dir('funding accounts...'); + it('should unlock accounts', function (done) { + provider.injectResult(true); // account #1 unlock result + provider.injectResult(true); // account #2 unlock result - provider.injectResult('1234567890'); // account #1 balance - provider.injectResult('1234567890'); // account #2 balance - provider.injectResult('0xfff12345678976543213456786543212345675432'); // send tx #1 - provider.injectResult('0xfff12345678976543213456786543212345675433'); // send tx #2 + devFunds.unlockAccounts(devFunds.password, (errUnlock) => { + assert.equal(errUnlock, null); + done(); + }); + }); - try { - devFunds.fundAccounts(devFunds.balance, (err) => { - console.dir('accounts funded...'); - assert.equal(err, null); + it('should fund accounts', function (done) { - provider.injectResult(['0x47d33b27bb249a2dbab4c0612bf9caf4c1950855', '0x11f4d0a3c12e86b4b5f39b213f7e19d048276dae', '0x22f4d0a3c12e86b4b5f39b213f7e19d048276dab']); - web3.eth.getAccounts().then((accts) => { - console.log('got accts: ' + JSON.stringify(accts)); + provider.injectResult('1234567890'); // account #1 balance + provider.injectResult('1234567890'); // account #2 balance + // provider.injectResult('0x11f4d0A3c12e86B4b5F39B213F7E19D048276DAe'); // send tx #1 + // provider.injectResult('0x22F4d0A3C12E86b4b5F39B213f7e19D048276DAb'); // send tx #2 - const weiFromConfig = utils.getWeiBalanceFromString(config.account.balance); - async.each(accts, (acct, cb) => { - provider.injectResult(web3.utils.numberToHex(weiFromConfig)); - devFunds.web3.eth.getBalance(acct).then((wei) => { - assert.equal(wei, weiFromConfig); - cb(); - }).catch(cb); - }, function(err) { done(); }); - }).catch(() => { - done(); - }); + devFunds.fundAccounts(devFunds.balance, (errFundAccounts) => { + + assert.equal(errFundAccounts, null); + + // inject response for web3.eth.getAccounts + // TODO: make FakeIpcProvider smart enough to keep track of created accounts + provider.injectResult(['0x47d33b27bb249a2dbab4c0612bf9caf4c1950855', '0x11f4d0a3c12e86b4b5f39b213f7e19d048276dae', '0x22f4d0a3c12e86b4b5f39b213f7e19d048276dab']); + + web3.eth.getAccounts().then((accts) => { + + const weiFromConfig = utils.getWeiBalanceFromString(config.account.balance, web3); + + async.each(accts, (acct, cb) => { + + // inject response for web3.eth.getBalance. + // essentially, this will always return the amount we specified + // in the config. + // this is dodgy. really, we should be letting the FakeIpcProvider + // at this point tell us how many wei we have per account (as it would + // in a real node), but the FakeIpcProvider is not smart enough... yet. + // TODO: make FakeIpcProvider smart enough to keep track of balances + provider.injectResult(web3.utils.numberToHex(weiFromConfig)); + + web3.eth.getBalance(acct).then((wei) => { + assert.equal(wei, weiFromConfig); + cb(); + }).catch(cb); + + }, function (errAcctsBalance) { + if (errAcctsBalance) throw errAcctsBalance; + done(); }); - } catch (errFundAccts) { - throw errFundAccts; - } + }).catch((errGetAccts) => { + if (errGetAccts) throw errGetAccts; + done(); + }); }); }); });