From 099a88497969051aaad00cb1678ab8ec4556a96d Mon Sep 17 00:00:00 2001 From: Mykola Mokhnach Date: Mon, 16 Oct 2023 11:00:06 +0200 Subject: [PATCH] chore: Only use portscanner for port-related operations --- lib/commands/context.js | 34 +++++++++++++++++++++-------- package.json | 3 +-- test/unit/commands/context-specs.js | 6 ----- 3 files changed, 26 insertions(+), 17 deletions(-) diff --git a/lib/commands/context.js b/lib/commands/context.js index 2aefcc73..239cf606 100644 --- a/lib/commands/context.js +++ b/lib/commands/context.js @@ -3,9 +3,7 @@ import {util} from '@appium/support'; import Chromedriver from 'appium-chromedriver'; import {errors} from 'appium/driver'; -import B from 'bluebird'; import _ from 'lodash'; -import PortFinder from 'portfinder'; import { APP_STATE, CHROMIUM_WIN, @@ -16,9 +14,31 @@ import { WebviewHelpers, } from '../helpers'; import {mixin} from './mixins'; +import net from 'node:net'; +import {findAPortNotInUse} from 'portscanner'; const CHROMEDRIVER_AUTODOWNLOAD_FEATURE = 'chromedriver_autodownload'; +/** + * @returns {Promise} + */ +async function getFreePort() { + return await new Promise((resolve, reject) => { + const srv = net.createServer(); + srv.listen(0, () => { + const address = srv.address(); + let port; + if (_.has(address, 'port')) { + // @ts-ignore The above condition covers possible errors + port = address.port; + } else { + reject(new Error('Cannot determine any free port number')); + } + srv.close(() => resolve(port)); + }); + }); +} + /** * @type {import('./mixins').ContextMixin & ThisType} * @satisfies {import('@appium/types').ExternalDriver} @@ -362,14 +382,10 @@ const ContextMixin = { }, async getChromedriverPort(portSpec, log) { - const getPort = /** @type {(opts?: import('portfinder').PortFinderOptions) => B} */ ( - B.promisify(PortFinder.getPort, {context: PortFinder}) - ); - // if the user didn't give us any specific information about chromedriver // port ranges, just find any free port if (!portSpec) { - const port = await getPort(); + const port = await getFreePort(); log?.debug(`A port was not given, using random free port: ${port}`); return port; } @@ -388,9 +404,9 @@ const ContextMixin = { port = parseInt(String(potentialPort), 10); // ensure we have a number and not a string stopPort = port; } + log?.debug(`Checking port range ${port}:${stopPort}`); try { - log?.debug(`Checking port range ${port}:${stopPort}`); - foundPort = await getPort({port, stopPort}); + foundPort = await findAPortNotInUse(port, stopPort); break; } catch (e) { log?.debug(`Nothing in port range ${port}:${stopPort} was available`); diff --git a/package.json b/package.json index 95bfa598..566a2eaf 100644 --- a/package.json +++ b/package.json @@ -65,8 +65,7 @@ "lru-cache": "^10.0.1", "moment": "^2.24.0", "moment-timezone": "^0.5.26", - "portfinder": "^1.0.6", - "portscanner": "2.2.0", + "portscanner": "^2.2.0", "semver": "^7.0.0", "source-map-support": "^0.x", "teen_process": "^2.0.0", diff --git a/test/unit/commands/context-specs.js b/test/unit/commands/context-specs.js index 1d920302..252b1142 100644 --- a/test/unit/commands/context-specs.js +++ b/test/unit/commands/context-specs.js @@ -10,7 +10,6 @@ import { } from '../../../lib/helpers/webview'; import {AndroidDriver} from '../../../lib/driver'; import Chromedriver from 'appium-chromedriver'; -import PortFinder from 'portfinder'; import {errors} from 'appium/driver'; let driver; @@ -22,10 +21,6 @@ chai.use(chaiAsPromised); describe('Context', function () { beforeEach(function () { - sandbox.stub(PortFinder, 'getPort').callsFake(function (cb) { - // eslint-disable-line promise/prefer-await-to-callbacks - return cb(null, 4444); // eslint-disable-line promise/prefer-await-to-callbacks - }); driver = new AndroidDriver(); driver.adb = sandbox.stub(); driver.adb.curDeviceId = 'device_id'; @@ -173,7 +168,6 @@ describe('Context', function () { driver.chromedriver.start .getCall(0) .args[0].chromeOptions.androidDeviceSerial.should.be.equal('device_id'); - driver.chromedriver.proxyPort.should.be.equal('4444'); driver.chromedriver.proxyReq.bind.calledWithExactly(driver.chromedriver); driver.proxyReqRes.should.be.equal('proxy'); driver.jwpProxyActive.should.be.true;