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.
This commit is contained in:
emizzle 2018-07-31 14:54:28 +10:00
parent 12304eac16
commit 7cb9cd5622
3 changed files with 83 additions and 81 deletions

View File

@ -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);
});

View File

@ -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) {

View File

@ -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,15 +51,9 @@ describe('embark.DevFunds', function () {
config.rpcPort += constants.blockchain.servicePortOnProxy;
}
// TODO put default config
const test = new Test({ loglevel: 'trace' });
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({}));
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) {
@ -70,13 +63,13 @@ describe('embark.DevFunds', function () {
provider.injectResult('0x11f4d0a3c12e86b4b5f39b213f7e19d048276dae'); // createAccount #1
provider.injectResult('0x22f4d0a3c12e86b4b5f39b213f7e19d048276dab'); // createAccount #2
devFunds.createAccounts(config.account.numAccounts, 'test_password', (err) => {
assert.equal(err, null);
// TODO: make FakeIpcProvider smart enough to keep track of created accounts
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');
@ -87,38 +80,59 @@ describe('embark.DevFunds', function () {
});
});
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
try {
devFunds.fundAccounts(devFunds.balance, (err) => {
console.dir('accounts funded...');
assert.equal(err, null);
provider.injectResult(['0x47d33b27bb249a2dbab4c0612bf9caf4c1950855', '0x11f4d0a3c12e86b4b5f39b213f7e19d048276dae', '0x22f4d0a3c12e86b4b5f39b213f7e19d048276dab']);
web3.eth.getAccounts().then((accts) => {
console.log('got accts: ' + JSON.stringify(accts));
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(() => {
devFunds.unlockAccounts(devFunds.password, (errUnlock) => {
assert.equal(errUnlock, null);
done();
});
});
} catch (errFundAccts) {
throw errFundAccts;
}
it('should fund accounts', function (done) {
provider.injectResult('1234567890'); // account #1 balance
provider.injectResult('1234567890'); // account #2 balance
// provider.injectResult('0x11f4d0A3c12e86B4b5F39B213F7E19D048276DAe'); // send tx #1
// provider.injectResult('0x22F4d0A3C12E86b4b5F39B213f7e19D048276DAb'); // send tx #2
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((errGetAccts) => {
if (errGetAccts) throw errGetAccts;
done();
});
});
});
});