Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
microsoft
GitHub Repository: microsoft/vscode
Path: blob/main/src/vs/base/test/common/assertHeap.ts
3296 views
1
/*---------------------------------------------------------------------------------------------
2
* Copyright (c) Microsoft Corporation. All rights reserved.
3
* Licensed under the MIT License. See License.txt in the project root for license information.
4
*--------------------------------------------------------------------------------------------*/
5
6
7
declare const __analyzeSnapshotInTests: (currentTest: string, classes: readonly string[]) => Promise<({ done: Promise<number[]>; file: string })>;
8
9
let currentTest: Mocha.Test | undefined;
10
11
const snapshotsToAssert: ({ counts: Promise<number[]>; file: string; test: string; opts: ISnapshotAssertOptions })[] = [];
12
13
setup(function () {
14
currentTest = this.currentTest;
15
});
16
17
suiteTeardown(async () => {
18
await Promise.all(snapshotsToAssert.map(async snap => {
19
const counts = await snap.counts;
20
21
const asserts = Object.entries(snap.opts.classes);
22
if (asserts.length !== counts.length) {
23
throw new Error(`expected class counts to equal assertions length for ${snap.test}`);
24
}
25
26
for (const [i, [name, doAssert]] of asserts.entries()) {
27
try {
28
doAssert(counts[i]);
29
} catch (e) {
30
throw new Error(`Unexpected number of ${name} instances (${counts[i]}) after "${snap.test}":\n\n${e.message}\n\nSnapshot saved at: ${snap.file}`);
31
}
32
}
33
}));
34
35
snapshotsToAssert.length = 0;
36
});
37
38
export interface ISnapshotAssertOptions {
39
classes: Record<string, (count: number) => void>;
40
}
41
42
const snapshotMinTime = 20_000;
43
44
/**
45
* Takes a heap snapshot, and asserts the state of classes in memory. This
46
* works in Node and the Electron sandbox, but is a no-op in the browser.
47
* Snapshots are process asynchronously and will report failures at the end of
48
* the suite.
49
*
50
* This method should be used sparingly (e.g. once at the end of a suite to
51
* ensure nothing leaked before), as gathering a heap snapshot is fairly
52
* slow, at least until V8 11.5.130 (https://v8.dev/blog/speeding-up-v8-heap-snapshots).
53
*
54
* Takes options containing a mapping of class names, and assertion functions
55
* to run on the number of retained instances of that class. For example:
56
*
57
* ```ts
58
* assertSnapshot({
59
* classes: {
60
* ShouldNeverLeak: count => assert.strictEqual(count, 0),
61
* SomeSingleton: count => assert(count <= 1),
62
* }
63
*});
64
* ```
65
*/
66
export async function assertHeap(opts: ISnapshotAssertOptions) {
67
if (!currentTest) {
68
throw new Error('assertSnapshot can only be used when a test is running');
69
}
70
71
// snapshotting can take a moment, ensure the test timeout is decently long
72
// so it doesn't immediately fail.
73
if (currentTest.timeout() < snapshotMinTime) {
74
currentTest.timeout(snapshotMinTime);
75
}
76
77
if (typeof __analyzeSnapshotInTests === 'undefined') {
78
return; // running in browser, no-op
79
}
80
81
const { done, file } = await __analyzeSnapshotInTests(currentTest.fullTitle(), Object.keys(opts.classes));
82
snapshotsToAssert.push({ counts: done, file, test: currentTest.fullTitle(), opts });
83
}
84
85
86