From 0c02722fdccc065c2e61a8f8555ab1bb517ff8c7 Mon Sep 17 00:00:00 2001 From: cjihrig Date: Tue, 2 Apr 2024 11:16:35 -0400 Subject: [PATCH] test_runner: make end of work check stricter This commit updates the logic that checks for the end of the test run. Prior to this change, it was possible for root.run() to be called multiple times because of the way pending subtests were tracked. The extra calls to root.run() were harmless, but could trigger an EventEmitter leak warning due to 'abort' listeners being created. --- lib/internal/test_runner/test.js | 9 +++++++++ test/parallel/test-runner-filter-warning.js | 11 +++++++++++ 2 files changed, 20 insertions(+) create mode 100644 test/parallel/test-runner-filter-warning.js diff --git a/lib/internal/test_runner/test.js b/lib/internal/test_runner/test.js index 5c003ca6106f87..8258d368f2727a 100644 --- a/lib/internal/test_runner/test.js +++ b/lib/internal/test_runner/test.js @@ -822,11 +822,20 @@ class Test extends AsyncResource { this.parent.activeSubtests--; } + // The call to processPendingSubtests() below can change the number of + // pending subtests. When detecting if we are done running tests, we want + // to check if there are no pending subtests both before and after + // calling processPendingSubtests(). Otherwise, it is possible to call + // root.run() multiple times (which is harmless but can trigger an + // EventEmitter leak warning). + const pendingSiblingCount = this.parent.pendingSubtests.length; + this.parent.addReadySubtest(this); this.parent.processReadySubtestRange(false); this.parent.processPendingSubtests(); if (this.parent === this.root && + pendingSiblingCount === 0 && this.root.activeSubtests === 0 && this.root.pendingSubtests.length === 0 && this.root.readySubtests.size === 0) { diff --git a/test/parallel/test-runner-filter-warning.js b/test/parallel/test-runner-filter-warning.js new file mode 100644 index 00000000000000..0f98f796d9f1c7 --- /dev/null +++ b/test/parallel/test-runner-filter-warning.js @@ -0,0 +1,11 @@ +// Flags: --test-only +'use strict'; +const common = require('../common'); +const { test } = require('node:test'); +const { defaultMaxListeners } = require('node:events'); + +process.on('warning', common.mustNotCall()); + +for (let i = 0; i < defaultMaxListeners + 1; ++i) { + test(`test ${i + 1}`); +}