Skip to content

Commit 9be722d

Browse files
committed
more
1 parent 94b2e25 commit 9be722d

File tree

3 files changed

+48
-22
lines changed

3 files changed

+48
-22
lines changed

lib/internal/test_runner/runner.js

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ const {
1111
ObjectAssign,
1212
PromisePrototypeThen,
1313
SafePromiseAll,
14+
SafeMap,
1415
SafeSet,
1516
} = primordials;
1617

@@ -115,6 +116,7 @@ function getRunArgs({ path, inspectPort }) {
115116
return argv;
116117
}
117118

119+
const runningProcesses = new SafeMap();
118120

119121
function runTestFile(path, root, inspectPort, filesWatcher) {
120122
const subtest = root.createSubtest(Test, path, async (t) => {
@@ -127,6 +129,7 @@ function runTestFile(path, root, inspectPort, filesWatcher) {
127129
}
128130

129131
const child = spawn(process.execPath, args, { signal: t.signal, encoding: 'utf8', env, stdio });
132+
runningProcesses.set(path, child);
130133
// TODO(cjihrig): Implement a TAP parser to read the child's stdout
131134
// instead of just displaying it all if the child fails.
132135
let err;
@@ -156,6 +159,7 @@ function runTestFile(path, root, inspectPort, filesWatcher) {
156159
child.stdout.toArray({ signal: t.signal }),
157160
]);
158161

162+
runningProcesses.delete(path);
159163
if (code !== 0 || signal !== null) {
160164
if (!err) {
161165
err = ObjectAssign(new ERR_TEST_FAILURE('test failed', kSubtestsFailed), {
@@ -194,17 +198,30 @@ function run(options) {
194198

195199
let postRun = () => root.postRun();
196200
let filesWatcher;
201+
const runningSubtests = new SafeMap();
197202
if (watch) {
198203
filesWatcher = new FilesWatcher({ throttle: 500, mode: 'filter' });
199204
filesWatcher.on('changed', ({ owners }) => {
200-
ArrayPrototypeForEach(ArrayPrototypeFilter(testFiles, (file) => owners.has(file)), (file) => {
201-
runTestFile(file, root, inspectPort, filesWatcher);
205+
filesWatcher.unfilterFilesOwnedBy(owners);
206+
const dependantTests = ArrayPrototypeFilter(testFiles, (file) => owners.has(file));
207+
ArrayPrototypeForEach(dependantTests, async (file) => {
208+
const runningProcess = runningProcesses.get(file);
209+
if (runningProcess) {
210+
runningProcess.kill();
211+
await once(runningProcess, 'exit');
212+
}
213+
await runningSubtests.get(file);
214+
runningSubtests.set(file, runTestFile(file, root, inspectPort, filesWatcher));
202215
});
203216
});
204217
postRun = undefined;
205218
}
206219

207-
PromisePrototypeThen(SafePromiseAll(testFiles, (path) => runTestFile(path, root, inspectPort, filesWatcher)),
220+
PromisePrototypeThen(SafePromiseAll(testFiles, (path) => {
221+
const subtest = runTestFile(path, root, inspectPort, filesWatcher);
222+
runningSubtests.set(path, subtest);
223+
return subtest;
224+
}),
208225
postRun);
209226

210227

lib/internal/watch_mode/files_watcher.js

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,8 @@ class FilesWatcher extends EventEmitter {
2424
#watchers = new SafeMap();
2525
#filteredFiles = new SafeSet();
2626
#throttling = new SafeSet();
27-
#depencencyMap = new SafeMap();
27+
#depencencyOwners = new SafeMap();
28+
#ownerDependencities = new SafeMap();
2829
#throttle;
2930
#mode;
3031

@@ -73,7 +74,8 @@ class FilesWatcher extends EventEmitter {
7374
return;
7475
}
7576
this.#throttling.add(trigger);
76-
this.emit('changed', { owners: this.#depencencyMap.get(trigger) });
77+
const owners = this.#depencencyOwners.get(trigger);
78+
this.emit('changed', { owners });
7779
setTimeout(() => this.#throttling.delete(trigger), this.#throttle).unref();
7880
}
7981

@@ -104,9 +106,12 @@ class FilesWatcher extends EventEmitter {
104106
}
105107
this.#filteredFiles.add(file);
106108
if (owner) {
107-
const owners = this.#depencencyMap.get(file) ?? new SafeSet();
109+
const owners = this.#depencencyOwners.get(file) ?? new SafeSet();
110+
const dependencies = this.#ownerDependencities.get(file) ?? new SafeSet();
108111
owners.add(owner);
109-
this.#depencencyMap.set(file, owners);
112+
dependencies.add(file);
113+
this.#depencencyOwners.set(file, owners);
114+
this.#ownerDependencities.set(owner, dependencies);
110115
}
111116
}
112117
watchChildProcessModules(child, key = null) {
@@ -126,14 +131,29 @@ class FilesWatcher extends EventEmitter {
126131
}
127132
});
128133
}
134+
unfilterFilesOwnedBy(owners) {
135+
owners.forEach((owner) => {
136+
const dependencies = this.#ownerDependencities.get(owner);
137+
if (dependencies) {
138+
dependencies.forEach((dependency) => {
139+
this.#filteredFiles.delete(dependency);
140+
this.#depencencyOwners.delete(dependency);
141+
});
142+
}
143+
this.#filteredFiles.delete(owner);
144+
this.#depencencyOwners.delete(owner);
145+
this.#ownerDependencities.delete(owner);
146+
});
147+
}
129148
clearFileFilters() {
130149
this.#filteredFiles.clear();
131150
}
132151
clear() {
133152
this.#watchers.forEach(this.#unwatch);
134153
this.#watchers.clear();
135154
this.#filteredFiles.clear();
136-
this.#depencencyMap.clear();
155+
this.#depencencyOwners.clear();
156+
this.#ownerDependencities.clear();
137157
}
138158
}
139159

Lines changed: 3 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,8 @@
1-
import * as common from '../common/index.mjs';
2-
import * as fixtures from '../common/fixtures.mjs';
3-
import { join } from 'node:path';
4-
import { describe, it, run } from 'node:test';
5-
import assert from 'node:assert';
6-
7-
const testFixtures = fixtures.path('test-runner');
1+
import '../common/index.mjs';
2+
import { describe, it } from 'node:test';
83

94
describe('test runner watch mode', { concurrency: true }, () => {
105

11-
it('should run a test repeatedly when its dependencies change', async () => {
12-
const stream = run({ files: [] });
13-
stream.setEncoding('utf8');
14-
stream.on('test:fail', common.mustNotCall());
15-
stream.on('test:pass', common.mustNotCall());
16-
// eslint-disable-next-line no-unused-vars
17-
for await (const _ of stream); // TODO(MoLow): assert.snapshot
6+
it('should run a test repeatedly when its dependencies change', { todo: true }, async () => {
187
});
198
});

0 commit comments

Comments
 (0)