@matter/testing 0.14.0-alpha.0-20250528-ad0054c84 → 0.14.0-alpha.0-20250530-5730c9bd1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/chip/chip.d.ts +0 -6
- package/dist/cjs/chip/chip.d.ts.map +1 -1
- package/dist/cjs/chip/chip.js +5 -14
- package/dist/cjs/chip/chip.js.map +2 -2
- package/dist/cjs/chip/state.d.ts +0 -3
- package/dist/cjs/chip/state.d.ts.map +1 -1
- package/dist/cjs/chip/state.js +4 -25
- package/dist/cjs/chip/state.js.map +1 -1
- package/dist/cjs/index.d.ts +2 -0
- package/dist/cjs/index.d.ts.map +1 -1
- package/dist/cjs/index.js +9 -0
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/mocha.d.ts.map +1 -1
- package/dist/cjs/mocha.js +1 -1
- package/dist/cjs/mocha.js.map +1 -1
- package/dist/cjs/nodejs.d.ts +1 -0
- package/dist/cjs/nodejs.d.ts.map +1 -1
- package/dist/cjs/nodejs.js +9 -2
- package/dist/cjs/nodejs.js.map +1 -1
- package/dist/cjs/runner.d.ts +1 -0
- package/dist/cjs/runner.d.ts.map +1 -1
- package/dist/cjs/runner.js +8 -2
- package/dist/cjs/runner.js.map +1 -1
- package/dist/cjs/test-descriptor.js +1 -1
- package/dist/cjs/test-descriptor.js.map +1 -1
- package/dist/cjs/util/heap.d.ts +18 -0
- package/dist/cjs/util/heap.d.ts.map +1 -0
- package/dist/cjs/util/heap.js +124 -0
- package/dist/cjs/util/heap.js.map +6 -0
- package/dist/esm/chip/chip.d.ts +0 -6
- package/dist/esm/chip/chip.d.ts.map +1 -1
- package/dist/esm/chip/chip.js +2 -11
- package/dist/esm/chip/chip.js.map +1 -1
- package/dist/esm/chip/state.d.ts +0 -3
- package/dist/esm/chip/state.d.ts.map +1 -1
- package/dist/esm/chip/state.js +4 -25
- package/dist/esm/chip/state.js.map +1 -1
- package/dist/esm/index.d.ts +2 -0
- package/dist/esm/index.d.ts.map +1 -1
- package/dist/esm/index.js +5 -0
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/mocha.d.ts.map +1 -1
- package/dist/esm/mocha.js +1 -1
- package/dist/esm/mocha.js.map +1 -1
- package/dist/esm/nodejs.d.ts +1 -0
- package/dist/esm/nodejs.d.ts.map +1 -1
- package/dist/esm/nodejs.js +9 -2
- package/dist/esm/nodejs.js.map +1 -1
- package/dist/esm/runner.d.ts +1 -0
- package/dist/esm/runner.d.ts.map +1 -1
- package/dist/esm/runner.js +8 -2
- package/dist/esm/runner.js.map +1 -1
- package/dist/esm/test-descriptor.js +1 -1
- package/dist/esm/test-descriptor.js.map +1 -1
- package/dist/esm/util/heap.d.ts +18 -0
- package/dist/esm/util/heap.d.ts.map +1 -0
- package/dist/esm/util/heap.js +94 -0
- package/dist/esm/util/heap.js.map +6 -0
- package/package.json +2 -2
- package/src/chip/chip.ts +2 -20
- package/src/chip/state.ts +4 -34
- package/src/cli.ts +1 -1
- package/src/index.ts +2 -0
- package/src/mocha.ts +2 -1
- package/src/nodejs.ts +10 -2
- package/src/runner.ts +11 -2
- package/src/test-descriptor.ts +1 -1
- package/src/util/heap.ts +119 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/test-descriptor.ts"],
|
|
4
|
-
"mappings": "AAAA;AAAA;AAAA;AAAA;AAAA;AAOA,SAAS,UAAU,iBAAiB;AACpC,SAAS,sBAAsB;AAqCxB,IAAU;AAAA,CAAV,CAAUA,oBAAV;AAII,EAAMA,gBAAA,iBAAiB;AAIvB,EAAMA,gBAAA,mBAAmB;AAsBzB,WAAS,OAAO,YAA4B,UAAgD;AAC/F,UAAM,EAAE,cAAc,OAAO,MAAM,UAAU,IAAI;AAIjD,QAAI;AACJ,QAAI,cAAc;AACd,oBAAc,CAAC;AACf,iBAAW,QAAQ,cAAc;AAC7B,YAAI,OAAO;AACX,cAAM,WAAW,KAAK,MAAM,GAAG;AAC/B,YAAI,SAAS,CAAC,MAAM,IAAI;AACpB,mBAAS,CAAC,IAAI,WAAW;AAAA,QAC7B;AACA,mBAAW,WAAW,UAAU;AAC5B,iBAAQ,KAAK,OAAO,MAAmB,CAAC;AAAA,QAC5C;AAAA,MACJ;AAAA,IACJ;AAEA,WAAOC,QAAO,YAAY,WAAW;AAErC,aAASA,QAAOC,aAA4B,OAA8C;AAEtF,YAAMC,eAAc,QAAQD,YAAW,IAAI;AAC3C,UAAI,SAAS,CAACC,cAAa;AACvB;AAAA,MACJ;AAGA,UAAI,QAAQD,YAAW,SAAS,QAAW;AACvC,QAAAA,YAAW,aAAa;AACxB,cAAM,OAAO,IAAI,eAAeA,YAAW,IAAI;AAC/C,YAAI,CAAC,KAAK,SAAS,IAAI,GAAG;AACtB;AAAA,QACJ;AAAA,MACJ;AAGA,UAAIA,YAAW,SAAS,SAAS;AAC7B,cAAM,EAAE,QAAQ,IAAIA;AACpB,YAAI,CAAC,SAAS,QAAQ;AAClB;AAAA,QACJ;AAEA,YAAI;AACJ,mBAAW,UAAU,SAAS;AAC1B,gBAAM,iBAAiBD,QAAO,QAAQE,YAAW;AACjD,cAAI,CAAC,gBAAgB;AACjB;AAAA,UACJ;AACA,cAAI,aAAa,CAAC,UAAU,cAAc,GAAG;AACzC;AAAA,UACJ;AACA,cAAI,iBAAiB;AACjB,4BAAgB,KAAK,cAAc;AAAA,UACvC,OAAO;AACH,8BAAkB,CAAC,cAAc;AAAA,UACrC;AAAA,QACJ;AAGA,YAAI,iBAAiB;AACjB,iBAAO,EAAE,GAAGD,aAAY,SAAS,gBAAgB;AAAA,QACrD;AAGA;AAAA,MACJ;AAGA,UAAI,SAAS,CAAC,MAAM,SAASA,YAAW,IAAI,GAAG;AAC3C;AAAA,MACJ;AAEA,aAAOA;AAAA,IACX;AAAA,EACJ;AA7EO,EAAAF,gBAAS;AAkFT,WAAS,MAAM,YAA4B,IAA0D;AACxG,QAAI,GAAG,UAAU,MAAM,OAAO;AAC1B;AAAA,IACJ;AAEA,QAAI,CAAC,WAAW,SAAS;AACrB;AAAA,IACJ;AAEA,eAAW,UAAU,WAAW,SAAS;AACrC,YAAM,QAAQ,EAAE;AAAA,IACpB;AAAA,EACJ;AAZO,EAAAA,gBAAS;AAiBhB,iBAAsB,KAAK,MAA4C;AACnE,QAAI,aAAkC;AAAA,MAClC,MAAM;AAAA,MACN,MAAM;AAAA,MACN,SAAS,CAAC;AAAA,IACd;AAEA,QAAI;AACA,YAAM,OAAO,MAAM,SAAS,MAAM,OAAO;AACzC,mBAAa,KAAK,MAAM,MAAM,CAAC,GAAG,MAAO,MAAM,eAAe,SAAY,CAAE;AAC5E,UACI,OAAO,YAAY,SAAS,YAC5B,WAAW,SAAS,WACpB,CAAC,MAAM,QAAQ,WAAW,OAAO,GACnC;AACE,cAAM,IAAI,MAAM,4BAA4B,IAAI,GAAG;AAAA,MACvD;AAAA,IACJ,SAAS,GAAG;AACR,
|
|
4
|
+
"mappings": "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",
|
|
5
5
|
"names": ["TestDescriptor", "filter", "descriptor", "memberNames"]
|
|
6
6
|
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2022-2025 Project CHIP Authors
|
|
4
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
5
|
+
*/
|
|
6
|
+
import memlabCore from "@memlab/core";
|
|
7
|
+
/**
|
|
8
|
+
* Heap analysis utility class.
|
|
9
|
+
*
|
|
10
|
+
* This provides convenient methods for producing heap snapshots along with analysis using memlab.
|
|
11
|
+
*/
|
|
12
|
+
export declare class HeapDumpSet {
|
|
13
|
+
#private;
|
|
14
|
+
constructor(name: string);
|
|
15
|
+
create(name?: string): Promise<void>;
|
|
16
|
+
findLeaks(): Promise<memlabCore.ISerializedInfo[]>;
|
|
17
|
+
}
|
|
18
|
+
//# sourceMappingURL=heap.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"heap.d.ts","sourceRoot":"","sources":["../../../src/util/heap.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH,OAAO,UAAU,MAAM,cAAc,CAAC;AAkEtC;;;;GAIG;AACH,qBAAa,WAAW;;gBAMR,IAAI,EAAE,MAAM;IAIlB,MAAM,CAAC,IAAI,SAAS;IAcpB,SAAS;CAelB"}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2022-2025 Project CHIP Authors
|
|
4
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
5
|
+
*/
|
|
6
|
+
import { isDirectory } from "@matter/tools";
|
|
7
|
+
import { config, findLeaks } from "@memlab/api";
|
|
8
|
+
import memlabCore from "@memlab/core";
|
|
9
|
+
import memlab from "memlab";
|
|
10
|
+
import { mkdir } from "node:fs/promises";
|
|
11
|
+
import { join } from "node:path";
|
|
12
|
+
import { writeHeapSnapshot } from "node:v8";
|
|
13
|
+
import { TestRunner } from "../runner.js";
|
|
14
|
+
config.externalLeakFilter = {
|
|
15
|
+
leakFilter(_node) {
|
|
16
|
+
return true;
|
|
17
|
+
},
|
|
18
|
+
retainerReferenceFilter(edge, _snapshot, isReferenceUsedByDefault) {
|
|
19
|
+
switch (edge.name_or_index) {
|
|
20
|
+
case "MatterHooks":
|
|
21
|
+
case "MockLogger":
|
|
22
|
+
case "MockTime":
|
|
23
|
+
case "MochaReporter":
|
|
24
|
+
case "mocha":
|
|
25
|
+
case "#wrapPrefix":
|
|
26
|
+
case "#dumps":
|
|
27
|
+
case "_playwrightInstance":
|
|
28
|
+
return false;
|
|
29
|
+
}
|
|
30
|
+
return isReferenceUsedByDefault;
|
|
31
|
+
}
|
|
32
|
+
};
|
|
33
|
+
let skipNextConsoleNewline = false;
|
|
34
|
+
Object.defineProperties(memlabCore.info, {
|
|
35
|
+
outStream: {
|
|
36
|
+
value: {
|
|
37
|
+
write(payload) {
|
|
38
|
+
payload = payload.toString();
|
|
39
|
+
if (payload === "\x1B[K" || payload === "\x1B[F") {
|
|
40
|
+
skipNextConsoleNewline = true;
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
payload = payload.trimEnd();
|
|
44
|
+
for (const line of payload.toString().split("\n")) {
|
|
45
|
+
if (skipNextConsoleNewline) {
|
|
46
|
+
skipNextConsoleNewline = false;
|
|
47
|
+
if (line === "") {
|
|
48
|
+
continue;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
MockLogger.injectExternalMessage("MEMLAB", line);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
});
|
|
57
|
+
class HeapDumpSet {
|
|
58
|
+
#dir;
|
|
59
|
+
#startedAt = /* @__PURE__ */ new Date();
|
|
60
|
+
#dumps = {};
|
|
61
|
+
#nextId = 1;
|
|
62
|
+
constructor(name) {
|
|
63
|
+
this.#dir = TestRunner.current.pkg.resolve(`build/heaps/${name}-${this.#startedAt.toISOString()}`);
|
|
64
|
+
}
|
|
65
|
+
async create(name = "dump") {
|
|
66
|
+
await TestRunner.current.progress.subtask(`heap dump ${name}`, async () => {
|
|
67
|
+
if (!isDirectory(this.#dir)) {
|
|
68
|
+
await mkdir(this.#dir, { recursive: true });
|
|
69
|
+
}
|
|
70
|
+
const path = join(
|
|
71
|
+
this.#dir,
|
|
72
|
+
`${(this.#nextId++).toString().padStart(2, "0")}-${name}-${Date.now() - this.#startedAt.getTime()}.heapsnapshot`
|
|
73
|
+
);
|
|
74
|
+
writeHeapSnapshot(path);
|
|
75
|
+
this.#dumps[name] = path;
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
async findLeaks() {
|
|
79
|
+
const paths = Object.values(this.#dumps);
|
|
80
|
+
if (paths.length !== 3) {
|
|
81
|
+
throw new Error("Leak analysis requires three heap dumps: baseline, target and final");
|
|
82
|
+
}
|
|
83
|
+
let result = [];
|
|
84
|
+
await TestRunner.current.progress.subtask("analyzing leaks", async () => {
|
|
85
|
+
const snapshots = memlab.SnapshotResultReader.fromSnapshots(paths[0], paths[1], paths[2]);
|
|
86
|
+
result = await findLeaks(snapshots);
|
|
87
|
+
});
|
|
88
|
+
return result;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
export {
|
|
92
|
+
HeapDumpSet
|
|
93
|
+
};
|
|
94
|
+
//# sourceMappingURL=heap.js.map
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../src/util/heap.ts"],
|
|
4
|
+
"mappings": "AAAA;AAAA;AAAA;AAAA;AAAA;AAMA,SAAS,mBAAmB;AAC5B,SAAS,QAAQ,iBAAiB;AAClC,OAAO,gBAAgB;AACvB,OAAO,YAAY;AACnB,SAAS,aAAa;AACtB,SAAS,YAAY;AACrB,SAAS,yBAAyB;AAClC,SAAS,kBAAkB;AAI3B,OAAO,qBAAqB;AAAA,EACxB,WAAW,OAAO;AACd,WAAO;AAAA,EACX;AAAA,EAEA,wBAAwB,MAAM,WAAW,0BAA0B;AAC/D,YAAQ,KAAK,eAAe;AAAA,MACxB,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AAED,eAAO;AAAA,IACf;AACA,WAAO;AAAA,EACX;AACJ;AAEA,IAAI,yBAAyB;AAE7B,OAAO,iBAAiB,WAAW,MAAM;AAAA,EACrC,WAAW;AAAA,IACP,OAAO;AAAA,MACH,MAAM,SAA8B;AAChC,kBAAU,QAAQ,SAAS;AAI3B,YAAI,YAAY,YAAY,YAAY,UAAU;AAE9C,mCAAyB;AACzB;AAAA,QACJ;AAEA,kBAAU,QAAQ,QAAQ;AAE1B,mBAAW,QAAQ,QAAQ,SAAS,EAAE,MAAM,IAAI,GAAG;AAC/C,cAAI,wBAAwB;AACxB,qCAAyB;AACzB,gBAAI,SAAS,IAAI;AACb;AAAA,YACJ;AAAA,UACJ;AAEA,qBAAW,sBAAsB,UAAU,IAAI;AAAA,QACnD;AAAA,MACJ;AAAA,IACJ;AAAA,EACJ;AACJ,CAAC;AASM,MAAM,YAAY;AAAA,EACrB;AAAA,EACA,aAAa,oBAAI,KAAK;AAAA,EACtB,SAAS,CAAC;AAAA,EACV,UAAU;AAAA,EAEV,YAAY,MAAc;AACtB,SAAK,OAAO,WAAW,QAAQ,IAAI,QAAQ,eAAe,IAAI,IAAI,KAAK,WAAW,YAAY,CAAC,EAAE;AAAA,EACrG;AAAA,EAEA,MAAM,OAAO,OAAO,QAAQ;AACxB,UAAM,WAAW,QAAQ,SAAS,QAAQ,aAAa,IAAI,IAAI,YAAY;AACvE,UAAI,CAAC,YAAY,KAAK,IAAI,GAAG;AACzB,cAAM,MAAM,KAAK,MAAM,EAAE,WAAW,KAAK,CAAC;AAAA,MAC9C;AACA,YAAM,OAAO;AAAA,QACT,KAAK;AAAA,QACL,IAAI,KAAK,WAAW,SAAS,EAAE,SAAS,GAAG,GAAG,CAAC,IAAI,IAAI,IAAI,KAAK,IAAI,IAAI,KAAK,WAAW,QAAQ,CAAC;AAAA,MACrG;AACA,wBAAkB,IAAI;AACtB,WAAK,OAAO,IAAI,IAAI;AAAA,IACxB,CAAC;AAAA,EACL;AAAA,EAEA,MAAM,YAAY;AACd,UAAM,QAAQ,OAAO,OAAO,KAAK,MAAM;AACvC,QAAI,MAAM,WAAW,GAAG;AACpB,YAAM,IAAI,MAAM,qEAAqE;AAAA,IACzF;AAEA,QAAI,SAAuC,CAAC;AAE5C,UAAM,WAAW,QAAQ,SAAS,QAAQ,mBAAmB,YAAY;AACrE,YAAM,YAAY,OAAO,qBAAqB,cAAc,MAAM,CAAC,GAAG,MAAM,CAAC,GAAG,MAAM,CAAC,CAAC;AACxF,eAAS,MAAM,UAAU,SAAS;AAAA,IACtC,CAAC;AAED,WAAO;AAAA,EACX;AACJ;",
|
|
5
|
+
"names": []
|
|
6
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@matter/testing",
|
|
3
|
-
"version": "0.14.0-alpha.0-
|
|
3
|
+
"version": "0.14.0-alpha.0-20250530-5730c9bd1",
|
|
4
4
|
"description": "Test harness for running JavaScript and Matter certification tests",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"scripts": {
|
|
@@ -45,7 +45,7 @@
|
|
|
45
45
|
"#tools/ansi-text": "@matter/tools/ansi-text"
|
|
46
46
|
},
|
|
47
47
|
"dependencies": {
|
|
48
|
-
"@matter/tools": "0.14.0-alpha.0-
|
|
48
|
+
"@matter/tools": "0.14.0-alpha.0-20250530-5730c9bd1",
|
|
49
49
|
"@types/express": "^5.0.2",
|
|
50
50
|
"ansi-colors": "^4.1.3",
|
|
51
51
|
"chai": "^4.5.0",
|
package/src/chip/chip.ts
CHANGED
|
@@ -5,12 +5,11 @@
|
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
7
|
import { globSync } from "#tools";
|
|
8
|
-
import Mocha from "mocha";
|
|
9
8
|
import { Subject } from "../device/subject.js";
|
|
10
9
|
import { Test } from "../device/test.js";
|
|
11
10
|
import type { Container } from "../docker/container.js";
|
|
12
11
|
import { afterOne, beforeOne } from "../mocha.js";
|
|
13
|
-
import
|
|
12
|
+
import { getCurrentNodejsMocha } from "../nodejs.js";
|
|
14
13
|
import { TestDescriptor } from "../test-descriptor.js";
|
|
15
14
|
import { PicsFile } from "./pics/file.js";
|
|
16
15
|
import { State } from "./state.js";
|
|
@@ -31,11 +30,6 @@ export interface Chip {
|
|
|
31
30
|
(subject: Subject): chip.Builder;
|
|
32
31
|
(...include: string[]): chip.Builder;
|
|
33
32
|
|
|
34
|
-
/**
|
|
35
|
-
* Testing controller. Must be set prior to use of other methods.
|
|
36
|
-
*/
|
|
37
|
-
runner: undefined | TestRunner;
|
|
38
|
-
|
|
39
33
|
/**
|
|
40
34
|
* Mocha instance. Must be set prior to use of other methods.
|
|
41
35
|
*/
|
|
@@ -250,7 +244,7 @@ function createBuilder(initial: {
|
|
|
250
244
|
}
|
|
251
245
|
|
|
252
246
|
function defineSuite(descriptor: TestDescriptor) {
|
|
253
|
-
const mocha =
|
|
247
|
+
const mocha = getCurrentNodejsMocha();
|
|
254
248
|
|
|
255
249
|
const { name, members } = descriptor;
|
|
256
250
|
if (!members?.length) {
|
|
@@ -326,18 +320,6 @@ function chipFn(subjectOrFirstInclusion: Subject.Factory | string | undefined, .
|
|
|
326
320
|
}
|
|
327
321
|
|
|
328
322
|
Object.defineProperties(chipFn, {
|
|
329
|
-
runner: {
|
|
330
|
-
set(runner: TestRunner) {
|
|
331
|
-
State.runner = runner;
|
|
332
|
-
},
|
|
333
|
-
},
|
|
334
|
-
|
|
335
|
-
mocha: {
|
|
336
|
-
set(mocha: Mocha) {
|
|
337
|
-
State.mocha = mocha;
|
|
338
|
-
},
|
|
339
|
-
},
|
|
340
|
-
|
|
341
323
|
defaultSubject: {
|
|
342
324
|
set(subject: Subject.Factory) {
|
|
343
325
|
State.subject = subject;
|
package/src/chip/state.ts
CHANGED
|
@@ -14,7 +14,7 @@ import { edit } from "../docker/edit.js";
|
|
|
14
14
|
import { Image } from "../docker/image.js";
|
|
15
15
|
import { Volume } from "../docker/volume.js";
|
|
16
16
|
import { afterRun, beforeRun } from "../mocha.js";
|
|
17
|
-
import
|
|
17
|
+
import { TestRunner } from "../runner.js";
|
|
18
18
|
import { RootTestDescriptor, TestDescriptor, TestFileDescriptor } from "../test-descriptor.js";
|
|
19
19
|
import { AccessoryServer } from "./accessory-server.js";
|
|
20
20
|
import type { chip } from "./chip.js";
|
|
@@ -30,8 +30,6 @@ import { YamlTest } from "./yaml-test.js";
|
|
|
30
30
|
*/
|
|
31
31
|
const Values = {
|
|
32
32
|
isInitialized: false,
|
|
33
|
-
runner: undefined as TestRunner | undefined,
|
|
34
|
-
mocha: undefined as Mocha | undefined,
|
|
35
33
|
subject: undefined as Subject.Factory | undefined,
|
|
36
34
|
test: undefined as Test | undefined,
|
|
37
35
|
mainContainer: undefined as Container | undefined,
|
|
@@ -65,34 +63,6 @@ export const State = {
|
|
|
65
63
|
return container;
|
|
66
64
|
},
|
|
67
65
|
|
|
68
|
-
set runner(runner: TestRunner) {
|
|
69
|
-
Values.runner = runner;
|
|
70
|
-
},
|
|
71
|
-
|
|
72
|
-
get runner() {
|
|
73
|
-
const runner = Values.runner;
|
|
74
|
-
|
|
75
|
-
if (runner === undefined) {
|
|
76
|
-
throw new Error("No test runner configured");
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
return runner;
|
|
80
|
-
},
|
|
81
|
-
|
|
82
|
-
set mocha(mocha: Mocha) {
|
|
83
|
-
Values.mocha = mocha;
|
|
84
|
-
},
|
|
85
|
-
|
|
86
|
-
get mocha() {
|
|
87
|
-
const mocha = Values.mocha;
|
|
88
|
-
|
|
89
|
-
if (mocha === undefined) {
|
|
90
|
-
throw new Error("No mocha instance configured");
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
return mocha;
|
|
94
|
-
},
|
|
95
|
-
|
|
96
66
|
set subject(subject: Subject.Factory) {
|
|
97
67
|
Values.subject = subject;
|
|
98
68
|
},
|
|
@@ -158,7 +128,7 @@ export const State = {
|
|
|
158
128
|
return;
|
|
159
129
|
}
|
|
160
130
|
|
|
161
|
-
const { progress } =
|
|
131
|
+
const { progress } = TestRunner.current;
|
|
162
132
|
|
|
163
133
|
progress.update("Initializing containers");
|
|
164
134
|
try {
|
|
@@ -220,7 +190,7 @@ export const State = {
|
|
|
220
190
|
* Run a CHIP test.
|
|
221
191
|
*/
|
|
222
192
|
async run(test: Test, args: string[], beforeTest: (subject: Subject, test: Test) => void | Promise<void>) {
|
|
223
|
-
const { reporter } =
|
|
193
|
+
const { reporter } = TestRunner.current;
|
|
224
194
|
|
|
225
195
|
const subject = Values.activeSubject!;
|
|
226
196
|
|
|
@@ -306,7 +276,7 @@ export const State = {
|
|
|
306
276
|
return;
|
|
307
277
|
}
|
|
308
278
|
|
|
309
|
-
const { progress } =
|
|
279
|
+
const { progress } = TestRunner.current;
|
|
310
280
|
|
|
311
281
|
await progress.subtask("activating subject", async () => {
|
|
312
282
|
// Avahi restarts too slowly currently to do this for every test
|
package/src/cli.ts
CHANGED
|
@@ -18,7 +18,7 @@ import { defaultDescriptor, printReport } from "./print-report.js";
|
|
|
18
18
|
import { TestRunner } from "./runner.js";
|
|
19
19
|
import { TestDescriptor } from "./test-descriptor.js";
|
|
20
20
|
|
|
21
|
-
const SHUTDOWN_TIMEOUT_MS =
|
|
21
|
+
const SHUTDOWN_TIMEOUT_MS = 5_000;
|
|
22
22
|
|
|
23
23
|
enum TestType {
|
|
24
24
|
esm = "esm",
|
package/src/index.ts
CHANGED
|
@@ -8,5 +8,7 @@ import "./global-declarations.js";
|
|
|
8
8
|
export * from "./chip/index.js";
|
|
9
9
|
export * from "./device/index.js";
|
|
10
10
|
export * from "./docker/index.js";
|
|
11
|
+
export { afterRun } from "./mocha.js";
|
|
11
12
|
export * from "./mocharc.cjs";
|
|
13
|
+
export * from "./util/heap.js";
|
|
12
14
|
export * from "./util/wtf.js";
|
package/src/mocha.ts
CHANGED
|
@@ -184,6 +184,8 @@ export async function runMocha(mocha: Mocha) {
|
|
|
184
184
|
await hook();
|
|
185
185
|
}
|
|
186
186
|
});
|
|
187
|
+
|
|
188
|
+
wtf.dump();
|
|
187
189
|
}
|
|
188
190
|
|
|
189
191
|
// Reset mocks before each file. Suites could conceivably have callbacks that occur across tests. If individual tests
|
|
@@ -255,7 +257,6 @@ export function adaptReporter(
|
|
|
255
257
|
}
|
|
256
258
|
MatterHooks.loggerSink = undefined;
|
|
257
259
|
reporter.endRun(this.translatedStats);
|
|
258
|
-
wtf.dump();
|
|
259
260
|
});
|
|
260
261
|
}
|
|
261
262
|
|
package/src/nodejs.ts
CHANGED
|
@@ -13,7 +13,6 @@ import { TestOptions } from "./options.js";
|
|
|
13
13
|
import type { TestRunner } from "./runner.js";
|
|
14
14
|
|
|
15
15
|
// Load globals so settings get applied
|
|
16
|
-
import { chip } from "./chip/chip.js";
|
|
17
16
|
import { FailureDetail } from "./failure-detail.js";
|
|
18
17
|
import "./global-definitions.js";
|
|
19
18
|
import { TestDescriptor } from "./test-descriptor.js";
|
|
@@ -70,6 +69,8 @@ export async function testNodejs(runner: TestRunner, format: "cjs" | "esm") {
|
|
|
70
69
|
}
|
|
71
70
|
}
|
|
72
71
|
|
|
72
|
+
let currentMocha: Mocha | undefined;
|
|
73
|
+
|
|
73
74
|
export async function createNodejsMocha(runner: TestRunner, format: "esm" | "cjs") {
|
|
74
75
|
const updateStats = runner.pkg.supportsEsm ? format === "esm" : true;
|
|
75
76
|
|
|
@@ -78,7 +79,7 @@ export async function createNodejsMocha(runner: TestRunner, format: "esm" | "cjs
|
|
|
78
79
|
reporter: adaptReporter(Mocha, format.toUpperCase(), runner.reporter, updateStats),
|
|
79
80
|
});
|
|
80
81
|
|
|
81
|
-
|
|
82
|
+
currentMocha = mocha;
|
|
82
83
|
|
|
83
84
|
generalSetup(mocha);
|
|
84
85
|
|
|
@@ -98,6 +99,13 @@ export async function createNodejsMocha(runner: TestRunner, format: "esm" | "cjs
|
|
|
98
99
|
return mocha;
|
|
99
100
|
}
|
|
100
101
|
|
|
102
|
+
export function getCurrentNodejsMocha() {
|
|
103
|
+
if (currentMocha === undefined) {
|
|
104
|
+
throw new Error("No mocha instance active");
|
|
105
|
+
}
|
|
106
|
+
return currentMocha;
|
|
107
|
+
}
|
|
108
|
+
|
|
101
109
|
class Profiler {
|
|
102
110
|
#session?: Session;
|
|
103
111
|
|
package/src/runner.ts
CHANGED
|
@@ -8,7 +8,6 @@ import { ansi, Package, Progress, std } from "#tools";
|
|
|
8
8
|
import debug from "debug";
|
|
9
9
|
import { readFile } from "node:fs/promises";
|
|
10
10
|
import { dirname, relative, resolve } from "node:path";
|
|
11
|
-
import { chip } from "./chip/chip.js";
|
|
12
11
|
import { FailureDetail } from "./failure-detail.js";
|
|
13
12
|
import { FailureReporter } from "./failure-reporter.js";
|
|
14
13
|
import { NodejsReporter } from "./nodejs-reporter.js";
|
|
@@ -19,6 +18,16 @@ import { listSupportFiles } from "./util/files.js";
|
|
|
19
18
|
import { testWeb } from "./web.js";
|
|
20
19
|
|
|
21
20
|
export class TestRunner {
|
|
21
|
+
static #current?: TestRunner;
|
|
22
|
+
|
|
23
|
+
static get current() {
|
|
24
|
+
if (this.#current === undefined) {
|
|
25
|
+
throw new Error("No test active test runner");
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
return this.#current;
|
|
29
|
+
}
|
|
30
|
+
|
|
22
31
|
readonly reporter: Reporter;
|
|
23
32
|
private spec = Array<string>();
|
|
24
33
|
|
|
@@ -27,7 +36,7 @@ export class TestRunner {
|
|
|
27
36
|
readonly progress: Progress,
|
|
28
37
|
readonly options: TestOptions,
|
|
29
38
|
) {
|
|
30
|
-
|
|
39
|
+
TestRunner.#current = this;
|
|
31
40
|
|
|
32
41
|
this.reporter = new (class extends NodejsReporter {
|
|
33
42
|
constructor() {
|
package/src/test-descriptor.ts
CHANGED
|
@@ -190,7 +190,7 @@ export namespace TestDescriptor {
|
|
|
190
190
|
throw new Error(`Invalid test descriptor "${path}"`);
|
|
191
191
|
}
|
|
192
192
|
} catch (e) {
|
|
193
|
-
if ((e as undefined | { code?: string })?.code !== "ENOENT") {
|
|
193
|
+
if (!(e instanceof SyntaxError) && (e as undefined | { code?: string })?.code !== "ENOENT") {
|
|
194
194
|
throw e;
|
|
195
195
|
}
|
|
196
196
|
}
|
package/src/util/heap.ts
ADDED
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2022-2025 Project CHIP Authors
|
|
4
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { isDirectory } from "@matter/tools";
|
|
8
|
+
import { config, findLeaks } from "@memlab/api";
|
|
9
|
+
import memlabCore from "@memlab/core";
|
|
10
|
+
import memlab from "memlab";
|
|
11
|
+
import { mkdir } from "node:fs/promises";
|
|
12
|
+
import { join } from "node:path";
|
|
13
|
+
import { writeHeapSnapshot } from "node:v8";
|
|
14
|
+
import { TestRunner } from "../runner.js";
|
|
15
|
+
|
|
16
|
+
// TODO - we filter some "non-leaks" but not all. Need to put more time into filtering stuff that's not really a leak
|
|
17
|
+
// if we're going to use this for actual automated leak detection
|
|
18
|
+
config.externalLeakFilter = {
|
|
19
|
+
leakFilter(_node) {
|
|
20
|
+
return true;
|
|
21
|
+
},
|
|
22
|
+
|
|
23
|
+
retainerReferenceFilter(edge, _snapshot, isReferenceUsedByDefault) {
|
|
24
|
+
switch (edge.name_or_index) {
|
|
25
|
+
case "MatterHooks":
|
|
26
|
+
case "MockLogger":
|
|
27
|
+
case "MockTime":
|
|
28
|
+
case "MochaReporter":
|
|
29
|
+
case "mocha":
|
|
30
|
+
case "#wrapPrefix":
|
|
31
|
+
case "#dumps":
|
|
32
|
+
case "_playwrightInstance":
|
|
33
|
+
// Skip stashed log messages, etc. from testing infrastructure
|
|
34
|
+
return false;
|
|
35
|
+
}
|
|
36
|
+
return isReferenceUsedByDefault;
|
|
37
|
+
},
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
let skipNextConsoleNewline = false;
|
|
41
|
+
|
|
42
|
+
Object.defineProperties(memlabCore.info, {
|
|
43
|
+
outStream: {
|
|
44
|
+
value: {
|
|
45
|
+
write(payload: Uint8Array | string) {
|
|
46
|
+
payload = payload.toString();
|
|
47
|
+
|
|
48
|
+
// If we set config.isContinuousText we lose color, so don't do that. But then we need to prevent
|
|
49
|
+
// ANSI codes that clear output. These codes are defined in @memlab/core Console.ts
|
|
50
|
+
if (payload === "\x1b[K" || payload === "\x1b[F") {
|
|
51
|
+
// Next line would be an "overwrite" so ignore newline that would push us to next line
|
|
52
|
+
skipNextConsoleNewline = true;
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
payload = payload.trimEnd();
|
|
57
|
+
|
|
58
|
+
for (const line of payload.toString().split("\n")) {
|
|
59
|
+
if (skipNextConsoleNewline) {
|
|
60
|
+
skipNextConsoleNewline = false;
|
|
61
|
+
if (line === "") {
|
|
62
|
+
continue;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
MockLogger.injectExternalMessage("MEMLAB", line);
|
|
67
|
+
}
|
|
68
|
+
},
|
|
69
|
+
},
|
|
70
|
+
},
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
//config.isContinuousTest = true;
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Heap analysis utility class.
|
|
77
|
+
*
|
|
78
|
+
* This provides convenient methods for producing heap snapshots along with analysis using memlab.
|
|
79
|
+
*/
|
|
80
|
+
export class HeapDumpSet {
|
|
81
|
+
#dir: string;
|
|
82
|
+
#startedAt = new Date();
|
|
83
|
+
#dumps = {} as Record<string, string>;
|
|
84
|
+
#nextId = 1;
|
|
85
|
+
|
|
86
|
+
constructor(name: string) {
|
|
87
|
+
this.#dir = TestRunner.current.pkg.resolve(`build/heaps/${name}-${this.#startedAt.toISOString()}`);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
async create(name = "dump") {
|
|
91
|
+
await TestRunner.current.progress.subtask(`heap dump ${name}`, async () => {
|
|
92
|
+
if (!isDirectory(this.#dir)) {
|
|
93
|
+
await mkdir(this.#dir, { recursive: true });
|
|
94
|
+
}
|
|
95
|
+
const path = join(
|
|
96
|
+
this.#dir,
|
|
97
|
+
`${(this.#nextId++).toString().padStart(2, "0")}-${name}-${Date.now() - this.#startedAt.getTime()}.heapsnapshot`,
|
|
98
|
+
);
|
|
99
|
+
writeHeapSnapshot(path);
|
|
100
|
+
this.#dumps[name] = path;
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
async findLeaks() {
|
|
105
|
+
const paths = Object.values(this.#dumps);
|
|
106
|
+
if (paths.length !== 3) {
|
|
107
|
+
throw new Error("Leak analysis requires three heap dumps: baseline, target and final");
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
let result: memlabCore.ISerializedInfo[] = [];
|
|
111
|
+
|
|
112
|
+
await TestRunner.current.progress.subtask("analyzing leaks", async () => {
|
|
113
|
+
const snapshots = memlab.SnapshotResultReader.fromSnapshots(paths[0], paths[1], paths[2]);
|
|
114
|
+
result = await findLeaks(snapshots);
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
return result;
|
|
118
|
+
}
|
|
119
|
+
}
|