Skip to content

Commit 72681fd

Browse files
committed
simplify and expand test suite
1 parent 8975c33 commit 72681fd

File tree

3 files changed

+35
-23
lines changed

3 files changed

+35
-23
lines changed

packages/core/src/shared/utilities/pollingSet.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,4 +49,9 @@ export class PollingSet<T> extends Set<T> {
4949
this.add(id)
5050
this.pollTimer = this.pollTimer ?? globals.clock.setInterval(() => this.poll(), this.interval)
5151
}
52+
53+
public override clear(): void {
54+
this.pollTimer = undefined
55+
super.clear()
56+
}
5257
}

packages/core/src/shared/utilities/processUtils.ts

Lines changed: 18 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -62,13 +62,14 @@ export interface ChildProcessResult {
6262
signal?: string
6363
}
6464

65-
interface Tracker<T> {
65+
interface Tracker<P, T> {
6666
add(item: T): void
67-
delete(item: T): void
67+
delete(id: P): void
6868
has(item: T): boolean
6969
size(): number
7070
cleanUp(): void
7171
monitor(): void | Promise<void>
72+
clear(): void
7273
}
7374

7475
export const eof = Symbol('EOF')
@@ -78,9 +79,9 @@ export interface ProcessStats {
7879
cpu: number
7980
elapsed: number
8081
}
81-
export class ChildProcessTracker implements Tracker<ChildProcess> {
82-
static pollingInterval: number = 10000
83-
static thresholds: ProcessStats = {
82+
export class ChildProcessTracker implements Tracker<number, ChildProcess> {
83+
static readonly pollingInterval: number = 10000
84+
static readonly thresholds: ProcessStats = {
8485
memory: 100 * 1024 * 1024, // 100 MB
8586
cpu: 50,
8687
elapsed: 30 * 1000, // 30 seconds
@@ -94,10 +95,10 @@ export class ChildProcessTracker implements Tracker<ChildProcess> {
9495

9596
public cleanUp() {
9697
const terminatedProcesses = Array.from(this.#pids.values()).filter(
97-
(pid: number) => !this.#pids.has(pid) || this.#processByPid.get(pid)?.stopped
98+
(pid: number) => this.#processByPid.get(pid)?.stopped
9899
)
99100
for (const pid of terminatedProcesses) {
100-
this.#pids.delete(pid)
101+
this.delete(pid)
101102
}
102103
}
103104

@@ -134,10 +135,9 @@ export class ChildProcessTracker implements Tracker<ChildProcess> {
134135
this.#pids.start(pid)
135136
}
136137

137-
public delete(childProcess: ChildProcess) {
138-
const pid = childProcess.pid()
139-
this.#processByPid.delete(pid)
140-
this.#pids.delete(pid)
138+
public delete(childProcessId: number) {
139+
this.#processByPid.delete(childProcessId)
140+
this.#pids.delete(childProcessId)
141141
}
142142

143143
public size() {
@@ -156,6 +156,11 @@ export class ChildProcessTracker implements Tracker<ChildProcess> {
156156
elapsed: stats.elapsed,
157157
}
158158
}
159+
160+
public clear() {
161+
this.#pids.clear()
162+
this.#processByPid.clear()
163+
}
159164
}
160165

161166
/**
@@ -165,7 +170,7 @@ export class ChildProcessTracker implements Tracker<ChildProcess> {
165170
* - call and await run to get the results (pass or fail)
166171
*/
167172
export class ChildProcess {
168-
static #runningProcesses: Tracker<ChildProcess> = new ChildProcessTracker()
173+
static #runningProcesses: Tracker<number, ChildProcess> = new ChildProcessTracker()
169174
#childProcess: proc.ChildProcess | undefined
170175
#processErrors: Error[] = []
171176
#processResult: ChildProcessResult | undefined
@@ -416,7 +421,7 @@ export class ChildProcess {
416421

417422
const dispose = () => {
418423
timeoutListener?.dispose()
419-
ChildProcess.#runningProcesses.delete(this)
424+
ChildProcess.#runningProcesses.delete(this.pid())
420425
}
421426

422427
process.on('exit', dispose)

packages/core/src/test/shared/utilities/processUtils.test.ts

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import assert from 'assert'
77
import * as os from 'os'
88
import * as path from 'path'
9+
import * as sinon from 'sinon'
910
import { makeTemporaryToolkitFolder, tryRemoveFolder } from '../../../shared/filesystemUtilities'
1011
import { ChildProcess, ChildProcessTracker, eof, ProcessStats } from '../../../shared/utilities/processUtils'
1112
import { sleep } from '../../../shared/utilities/timeoutUtils'
@@ -14,7 +15,6 @@ import { fs } from '../../../shared'
1415
import * as FakeTimers from '@sinonjs/fake-timers'
1516
import { installFakeClock } from '../../testUtil'
1617
import { isWin } from '../../../shared/vscode/env'
17-
import Sinon from 'sinon'
1818
import { assertLogsContain } from '../../globalSetup.test'
1919

2020
describe('ChildProcess', async function () {
@@ -368,6 +368,14 @@ describe('ChildProcessTracker', function () {
368368
tracker = new ChildProcessTracker()
369369
})
370370

371+
afterEach(function () {
372+
tracker.clear()
373+
})
374+
375+
after(function () {
376+
clock.uninstall()
377+
})
378+
371379
it(`removes stopped processes every ${ChildProcessTracker.pollingInterval / 1000} seconds`, async function () {
372380
// Start a 'sleep' command, check it only removes after we stop it.
373381
const childProcess = new ChildProcess(getSleepCmd(), ['90'])
@@ -388,30 +396,24 @@ describe('ChildProcessTracker', function () {
388396
const childProcess2 = new ChildProcess(getSleepCmd(), ['90'])
389397
childProcess1.run().catch(() => assert.fail('sleep command threw an error'))
390398
childProcess2.run().catch(() => assert.fail('sleep command threw an error'))
391-
392399
tracker.add(childProcess1)
393400
tracker.add(childProcess2)
394401

395402
assert.strictEqual(tracker.has(childProcess1), true, 'Missing first process')
396403
assert.strictEqual(tracker.has(childProcess2), true, 'Missing second process')
397-
assert.strictEqual(tracker.size(), 2)
398404

399405
childProcess1.stop()
400-
await clock.tickAsync(ChildProcessTracker.pollingInterval + 1)
406+
await clock.tickAsync(ChildProcessTracker.pollingInterval)
401407
assert.strictEqual(tracker.has(childProcess2), true, 'first process was not removed after stopping it')
402408
assert.strictEqual(tracker.size(), 1)
403-
404-
childProcess2.stop()
405-
await clock.tickAsync(ChildProcessTracker.pollingInterval + 1)
406-
assert.strictEqual(tracker.size(), 0, 'second process was not removed after stopping it')
407409
})
408410

409411
it('logs a warning message when system usage exceeds threshold', async function () {
410412
const childProcess = new ChildProcess(getSleepCmd(), ['90'])
411413
childProcess.run().catch(() => assert.fail('sleep command threw an error'))
412414
tracker.add(childProcess)
413415

414-
const usageMock = Sinon.stub(ChildProcessTracker.prototype, 'getUsage')
416+
const usageMock = sinon.stub(ChildProcessTracker.prototype, 'getUsage')
415417
const highCpu: ProcessStats = {
416418
cpu: ChildProcessTracker.thresholds.cpu + 1,
417419
memory: 0,
@@ -442,6 +444,6 @@ describe('ChildProcessTracker', function () {
442444
await clock.tickAsync(ChildProcessTracker.pollingInterval)
443445
assertLogsContain('exceeded time threshold', false, 'warn')
444446

445-
usageMock.restore()
447+
sinon.restore()
446448
})
447449
})

0 commit comments

Comments
 (0)