diff --git a/test/node-spv-sync-test.js b/test/node-spv-sync-test.js index 62134b2ec..7d411cbbc 100644 --- a/test/node-spv-sync-test.js +++ b/test/node-spv-sync-test.js @@ -158,7 +158,7 @@ describe('SPV Node Sync', function() { }); it('should send a tx from chain 1 to SPV node', async () => { - const balanceEvent = forEvent(spvwallet, 'balance'); + const balanceEvent = forEvent(spvwallet, 'balance', 1, 9000); await wallet.send({ outputs: [{ value: 1012345678, diff --git a/test/util/common.js b/test/util/common.js index c2a6e3f06..57b738558 100644 --- a/test/util/common.js +++ b/test/util/common.js @@ -103,13 +103,14 @@ common.rimraf = async function(p) { return await fs.rimraf(p); }; -common.forValue = async function forValue(obj, key, val, timeout = 5000) { +common.forValue = async function forValue(obj, key, val, timeout = 2000) { assert(typeof obj === 'object'); assert(typeof key === 'string'); const ms = 10; let interval = null; let count = 0; + const stack = getStack(); return new Promise((resolve, reject) => { interval = setInterval(() => { @@ -118,14 +119,16 @@ common.forValue = async function forValue(obj, key, val, timeout = 5000) { resolve(); } else if (count * ms >= timeout) { clearInterval(interval); - reject(new Error('Timeout waiting for value.')); + const error = new Error('Timeout waiting for value.'); + error.stack = error.stack + '\n' + stack; + reject(error); } count += 1; }, ms); }); }; -common.forEvent = async function forEvent(obj, name, count = 1, timeout = 5000) { +common.forEvent = async function forEvent(obj, name, count = 1, timeout = 2000) { assert(typeof obj === 'object'); assert(typeof name === 'string'); assert(typeof count === 'number'); @@ -134,6 +137,8 @@ common.forEvent = async function forEvent(obj, name, count = 1, timeout = 5000) let countdown = count; const events = []; + const stack = getStack(); + return new Promise((resolve, reject) => { let timeoutHandler, listener; @@ -159,9 +164,11 @@ common.forEvent = async function forEvent(obj, name, count = 1, timeout = 5000) timeoutHandler = setTimeout(() => { cleanup(); const msg = `Timeout waiting for event ${name} ` - + `(received ${count - countdown}/${count})`; + + `(received ${count - countdown}/${count})\n${stack}`; - reject(new Error(msg)); + const error = new Error(msg); + error.stack = error.stack + '\n' + stack; + reject(error); return; }, timeout); @@ -169,12 +176,14 @@ common.forEvent = async function forEvent(obj, name, count = 1, timeout = 5000) }); }; -common.forEventCondition = async function forEventCondition(obj, name, fn, timeout = 5000) { +common.forEventCondition = async function forEventCondition(obj, name, fn, timeout = 2000) { assert(typeof obj === 'object'); assert(typeof name === 'string'); assert(typeof fn === 'function'); assert(typeof timeout === 'number'); + const stack = getStack(); + return new Promise((resolve, reject) => { let timeoutHandler, listener; @@ -190,6 +199,7 @@ common.forEventCondition = async function forEventCondition(obj, name, fn, timeo res = await fn(...args); } catch (e) { cleanup(); + e.stack = e.stack + '\n' + stack; reject(e); return; } @@ -203,7 +213,9 @@ common.forEventCondition = async function forEventCondition(obj, name, fn, timeo timeoutHandler = setTimeout(() => { cleanup(); const msg = `Timeout waiting for event ${name} with condition`; - reject(new Error(msg)); + const error = new Error(msg); + error.stack = error.stack + '\n' + stack; + reject(error); return; }, timeout); @@ -357,3 +369,7 @@ class TXContext { return [tx, view]; } } + +function getStack() { + return new Error().stack.split('\n').slice(2).join('\n'); +} diff --git a/test/util/nodes-context.js b/test/util/nodes-context.js index 221b88208..2989464df 100644 --- a/test/util/nodes-context.js +++ b/test/util/nodes-context.js @@ -19,12 +19,12 @@ class NodesContext { } addNode(options = {}) { - const index = this.nodeCtxs.length + 1; + const index = this.nodeCtxs.length; - let seedPort = this.network.port + index - 1; + let seedPort = getPort(this.network, index - 1); - if (seedPort < this.network.port) - seedPort = this.network.port; + if (options.seedNodeIndex != null) + seedPort = getPort(this.network, options.seedNodeIndex); const port = this.network.port + index; const brontidePort = this.network.brontidePort + index; @@ -33,6 +33,11 @@ class NodesContext { const nsPort = this.network.nsPort + index; const rsPort = this.network.rsPort + index + 100; + const seeds = []; + + if (options.seedNodeIndex != null || index > 0) + seeds.push(`127.0.0.1:${seedPort}`); + const nodeCtx = new NodeContext({ listen: true, @@ -47,9 +52,8 @@ class NodesContext { nsPort: nsPort, httpPort: httpPort, walletHttpPort: walletHttpPort, - seeds: [ - `127.0.0.1:${seedPort}` - ] + + seeds: seeds }); this.nodeCtxs.push(nodeCtx); @@ -191,4 +195,8 @@ class NodesContext { } } +function getPort(network, index) { + return Math.max(network.port + index, network.port); +} + module.exports = NodesContext; diff --git a/test/wallet-rescan-test.js b/test/wallet-rescan-test.js index b5b810b69..0048126e7 100644 --- a/test/wallet-rescan-test.js +++ b/test/wallet-rescan-test.js @@ -41,9 +41,9 @@ const noSPVcombinations = combinations.filter(c => !c.SPV); const regtest = Network.get('regtest'); describe('Wallet rescan/addBlock', function() { - // TODO: Add SPV tests. for (const {SPV, STANDALONE, name} of noSPVcombinations) { describe(`rescan/addBlock gapped addresses (${name} Integration)`, function() { + this.timeout(5000); const TEST_LOOKAHEAD = 20; const MAIN = 0; @@ -144,6 +144,7 @@ describe('Wallet rescan/addBlock', function() { // Prepare for the rescan and addBlock tests. it('should send gapped txs on each block', async () => { const expectedRescanBalance = await getBalance(main.client, ACCOUNT); + const height = nodes.height(MAIN); const blocks = 5; // 1 address per block, all of them gapped. @@ -154,9 +155,10 @@ describe('Wallet rescan/addBlock', function() { // give addBlock first address. await deriveAddresses(addBlock.client, addresses[0].depth - TEST_LOOKAHEAD); - const mainWalletBlocks = forEvent(main.wdb, 'block connect', blocks); - const addBlockWalletBlocks = forEvent(addBlock.wdb, 'block connect', blocks); - const rescanWalletBlocks = forEvent(rescan.wdb, 'block connect', blocks); + const condFn = entry => entry.height === blocks + height; + const mainWalletBlocks = forEventCondition(main.wdb, 'block connect', condFn); + const addBlockWalletBlocks = forEventCondition(addBlock.wdb, 'block connect', condFn); + const rescanWalletBlocks = forEventCondition(rescan.wdb, 'block connect', condFn); for (let i = 0; i < blocks; i++) { await minerWallet.send({ @@ -704,15 +706,17 @@ describe('Wallet rescan/addBlock', function() { const BLOCKS = 20; const chainBlocks = forEventCondition(node.chain, 'connect', (entry) => { return entry.height === BLOCKS; - }); + }, 5000); const wdbBlocks = forEventCondition(wdb, 'block connect', (entry) => { return entry.height === BLOCKS; - }); + }, 5000); await minerCtx.mineBlocks(BLOCKS, address); - await chainBlocks; - await wdbBlocks; + await Promise.all([ + chainBlocks, + wdbBlocks + ]); }); it('should rescan when receiving a block', async () => {