From 140265e211eb8e3871da5fb5ac7a8dcb43bab3a6 Mon Sep 17 00:00:00 2001 From: Nodari Chkuaselidze Date: Tue, 31 Oct 2023 14:05:03 +0400 Subject: [PATCH] test: add test case for the issue in the bcoin-org/bsock#11. If the client closes before the socket.call, next call would never resolve nor reject and locker would never unlock. --- package-lock.json | 10 +++++----- package.json | 2 +- test/node-http-test.js | 2 -- test/node-rescan-test.js | 37 ++++++++++++++++++++++++++++++++++++- test/util/node.js | 21 ++++++++++++++++++++- 5 files changed, 62 insertions(+), 10 deletions(-) diff --git a/package-lock.json b/package-lock.json index ac938796b..a592c1191 100644 --- a/package-lock.json +++ b/package-lock.json @@ -25,7 +25,7 @@ "bmutex": "~0.1.6", "bns": "~0.15.0", "bsert": "~0.0.12", - "bsock": "~0.1.9", + "bsock": "~0.1.11", "bsocks": "~0.2.6", "btcp": "~0.1.5", "buffer-map": "~0.0.7", @@ -310,11 +310,11 @@ } }, "node_modules/bsock": { - "version": "0.1.9", - "resolved": "https://registry.npmjs.org/bsock/-/bsock-0.1.9.tgz", - "integrity": "sha512-/l9Kg/c5o+n/0AqreMxh2jpzDMl1ikl4gUxT7RFNe3A3YRIyZkiREhwcjmqxiymJSRI/Qhew357xGn1SLw/xEw==", + "version": "0.1.11", + "resolved": "https://registry.npmjs.org/bsock/-/bsock-0.1.11.tgz", + "integrity": "sha512-4COhlKKBfOQOomNvz1hjoPtN5ytpqbxkuCPvIPbYMvaZwNBKpo8dZa1LJjcN3wuAkjIIJLF/fc4o3e1DYiceQw==", "dependencies": { - "bsert": "~0.0.10" + "bsert": "~0.0.12" }, "engines": { "node": ">=8.0.0" diff --git a/package.json b/package.json index 0d4e0de30..aae0c4761 100644 --- a/package.json +++ b/package.json @@ -36,7 +36,7 @@ "bmutex": "~0.1.6", "bns": "~0.15.0", "bsert": "~0.0.12", - "bsock": "~0.1.9", + "bsock": "~0.1.11", "bsocks": "~0.2.6", "btcp": "~0.1.5", "buffer-map": "~0.0.7", diff --git a/test/node-http-test.js b/test/node-http-test.js index 60b16e5fd..eedb06c13 100644 --- a/test/node-http-test.js +++ b/test/node-http-test.js @@ -3,8 +3,6 @@ const assert = require('bsert'); const bio = require('bufio'); const Network = require('../lib/protocol/network'); -const FullNode = require('../lib/node/fullnode'); -const SPVNode = require('../lib/node/spvnode'); const Address = require('../lib/primitives/address'); const Mnemonic = require('../lib/hd/mnemonic'); const Witness = require('../lib/script/witness'); diff --git a/test/node-rescan-test.js b/test/node-rescan-test.js index dc0654308..75783b523 100644 --- a/test/node-rescan-test.js +++ b/test/node-rescan-test.js @@ -7,7 +7,7 @@ const TX = require('../lib/primitives/tx'); const nodeCommon = require('../lib/blockchain/common'); const {scanActions} = nodeCommon; const NodeContext = require('./util/node'); -const {forEvent} = require('./util/common'); +const {forEvent, sleep} = require('./util/common'); const MemWallet = require('./util/memwallet'); const rules = require('../lib/covenants/rules'); @@ -771,6 +771,41 @@ describe('Node Rescan Interactive API', function() { i++; } }); + + // Make sure the client closing does not cause the chain locker to get + // indefinitely locked. (https://github.com/bcoin-org/bsock/pull/11) + it('should stop rescan when client closes', async () => { + const client2 = nodeCtx.nodeClient(); + + const addr = funderWallet.getAddress().toString(nodeCtx.network); + + // Client does not need rescan hooks, because we make + // sure that the rescan hooks are never actually called. + // Client closes before they are called. + // We simulate this by acquiring chain lock before we + // call rescan and then closing the client. + const unlock = await nodeCtx.chain.locker.lock(); + const rescan = client.rescanInteractive(0); + let err = null; + rescan.catch(e => err = e); + + // make sure call reaches the server. + await sleep(50); + await client.close(); + try { + await rescan; + } catch (e) { + err = e; + } + + assert(err); + assert(err.message, 'Job timed out.'); + unlock(); + + // Make sure lock was unlocked. + // w/o bsock update this will fail with timeout. + await client2.execute('generatetoaddress', [1, addr]); + }); }); }); diff --git a/test/util/node.js b/test/util/node.js index e98faa2b1..fd11010cd 100644 --- a/test/util/node.js +++ b/test/util/node.js @@ -8,6 +8,7 @@ const FullNode = require('../../lib/node/fullnode'); const plugin = require('../../lib/wallet/plugin'); const Network = require('../../lib/protocol/network'); const {NodeClient, WalletClient} = require('../../lib/client'); +const Logger = require('blgr'); class NodeContext { constructor(options = {}) { @@ -15,6 +16,11 @@ class NodeContext { this.options = {}; this.node = null; this.opened = false; + this.logger = new Logger({ + console: true, + filename: null, + level: 'none' + }); this.nclient = null; this.wclient = null; @@ -32,7 +38,8 @@ class NodeContext { network: 'regtest', listen: false, wallet: false, - spv: false + spv: false, + logger: this.logger }; if (options.network != null) @@ -226,6 +233,18 @@ class NodeContext { await fs.rimraf(this.prefix); } + /* + * Helpers + */ + + enableLogging() { + this.logger.setLevel('debug'); + } + + disableLogging() { + this.logger.setLevel('none'); + } + /** * Execute an RPC using the node client. * @param {String} method - RPC method