@memlab/api 1.0.0 → 1.0.3
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/README.md +5 -9
- package/dist/API.d.ts +139 -18
- package/dist/API.js +146 -17
- package/dist/__tests__/API/E2EDetachedDOMAnalysis.test.js +5 -6
- package/dist/__tests__/API/E2EDuplicateObjectAnalysis.test.js +5 -6
- package/dist/__tests__/API/E2EFindLeaks.example.d.ts +11 -0
- package/dist/__tests__/API/E2EFindLeaks.example.js +50 -0
- package/dist/__tests__/API/E2EFindMemoryLeaks.test.d.ts +11 -0
- package/dist/__tests__/API/E2EFindMemoryLeaks.test.js +72 -0
- package/dist/__tests__/API/E2EResultReader.test.d.ts +11 -0
- package/dist/__tests__/API/E2EResultReader.test.js +72 -0
- package/dist/__tests__/API/E2ERunSingleSnapshot.example.js +11 -12
- package/dist/__tests__/API/E2EShapeUnboundGrowthAnalysis.test.js +8 -17
- package/dist/__tests__/API/E2EStringAnalysis.test.js +19 -15
- package/dist/__tests__/packages/heap-analysis.test.d.ts +11 -0
- package/dist/__tests__/packages/heap-analysis.test.js +82 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.js +11 -2
- package/dist/result-reader/BaseResultReader.d.ts +70 -0
- package/dist/result-reader/BaseResultReader.js +96 -0
- package/dist/result-reader/BrowserInteractionResultReader.d.ts +105 -0
- package/dist/result-reader/BrowserInteractionResultReader.js +136 -0
- package/package.json +15 -6
- package/dist/API.d.ts.map +0 -1
- package/dist/__tests__/API/E2EBasicAnalysis.test.d.ts.map +0 -1
- package/dist/__tests__/API/E2EDetachedDOMAnalysis.test.d.ts.map +0 -1
- package/dist/__tests__/API/E2EDuplicateObjectAnalysis.test.d.ts.map +0 -1
- package/dist/__tests__/API/E2ERunMultipleSnapshots.example.d.ts.map +0 -1
- package/dist/__tests__/API/E2ERunSingleSnapshot.example.d.ts.map +0 -1
- package/dist/__tests__/API/E2EShapeUnboundGrowthAnalysis.test.d.ts.map +0 -1
- package/dist/__tests__/API/E2EStringAnalysis.test.d.ts.map +0 -1
- package/dist/__tests__/API/lib/E2ETestSettings.d.ts.map +0 -1
- package/dist/__tests__/heap/E2EHeapParser.test.d.ts.map +0 -1
- package/dist/__tests__/heap/lib/HeapParserTestUtils.d.ts.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/lib/APIUtils.d.ts.map +0 -1
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
4
|
+
*
|
|
5
|
+
* This source code is licensed under the MIT license found in the
|
|
6
|
+
* LICENSE file in the root directory of this source tree.
|
|
7
|
+
*
|
|
8
|
+
* @emails oncall+ws_labs
|
|
9
|
+
* @format
|
|
10
|
+
*/
|
|
11
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
12
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
13
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
14
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
15
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
16
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
17
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
18
|
+
});
|
|
19
|
+
};
|
|
20
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
21
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
22
|
+
};
|
|
23
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
24
|
+
/* eslint-disable @typescript-eslint/ban-ts-comment */
|
|
25
|
+
const fs_1 = __importDefault(require("fs"));
|
|
26
|
+
const BrowserInteractionResultReader_1 = __importDefault(require("../../result-reader/BrowserInteractionResultReader"));
|
|
27
|
+
const index_1 = require("../../index");
|
|
28
|
+
const E2ETestSettings_1 = require("./lib/E2ETestSettings");
|
|
29
|
+
beforeEach(E2ETestSettings_1.testSetup);
|
|
30
|
+
function inject() {
|
|
31
|
+
// @ts-ignore
|
|
32
|
+
window.injectHookForLink4 = () => {
|
|
33
|
+
const arr = [];
|
|
34
|
+
for (let i = 0; i < 10000; ++i) {
|
|
35
|
+
arr.push('duplicated string value' + (i % 1));
|
|
36
|
+
}
|
|
37
|
+
// @ts-ignore
|
|
38
|
+
window.__injectedValue = arr;
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
function checkResultReader(result) {
|
|
42
|
+
const workDir = result.getRootDirectory();
|
|
43
|
+
expect(fs_1.default.existsSync(workDir)).toBe(true);
|
|
44
|
+
const snapshotDir = result.getSnapshotFileDir();
|
|
45
|
+
expect(fs_1.default.existsSync(snapshotDir)).toBe(true);
|
|
46
|
+
const snapshotFiles = result.getSnapshotFiles();
|
|
47
|
+
expect(snapshotFiles.length > 0).toBe(true);
|
|
48
|
+
const steps = result.getInteractionSteps();
|
|
49
|
+
expect(steps.length > 0).toBe(true);
|
|
50
|
+
expect(steps[0].name).toBe('page-load');
|
|
51
|
+
const runMeta = result.getRunMetaInfo();
|
|
52
|
+
expect(runMeta.app).toBe('test-spa');
|
|
53
|
+
result.cleanup();
|
|
54
|
+
expect(fs_1.default.existsSync(workDir)).toBe(false);
|
|
55
|
+
expect(() => result.getRootDirectory()).toThrowError();
|
|
56
|
+
expect(() => result.getSnapshotFileDir()).toThrowError();
|
|
57
|
+
expect(() => result.getSnapshotFiles()).toThrowError();
|
|
58
|
+
}
|
|
59
|
+
test('result data/file reader is working as expected', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
60
|
+
const result = yield (0, index_1.warmupAndTakeSnapshots)({
|
|
61
|
+
scenario: E2ETestSettings_1.scenario,
|
|
62
|
+
evalInBrowserAfterInitLoad: inject,
|
|
63
|
+
});
|
|
64
|
+
checkResultReader(result);
|
|
65
|
+
}), E2ETestSettings_1.testTimeout);
|
|
66
|
+
test('ResultReader.from is working as expected', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
67
|
+
const result = yield (0, index_1.warmupAndTakeSnapshots)({
|
|
68
|
+
scenario: E2ETestSettings_1.scenario,
|
|
69
|
+
evalInBrowserAfterInitLoad: inject,
|
|
70
|
+
});
|
|
71
|
+
checkResultReader(BrowserInteractionResultReader_1.default.from(result.getRootDirectory()));
|
|
72
|
+
}), E2ETestSettings_1.testTimeout);
|
|
@@ -17,22 +17,21 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
17
17
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
18
18
|
});
|
|
19
19
|
};
|
|
20
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
21
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
22
|
-
};
|
|
23
20
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
24
|
-
const path_1 = __importDefault(require("path"));
|
|
25
21
|
const index_1 = require("../../index");
|
|
26
22
|
const scenario = {
|
|
27
23
|
app: () => 'test-spa',
|
|
28
24
|
url: () => '',
|
|
29
25
|
action: (page) => __awaiter(void 0, void 0, void 0, function* () { return yield page.click('[data-testid="link-4"]'); }),
|
|
30
26
|
};
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
27
|
+
function test() {
|
|
28
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
29
|
+
const result = yield (0, index_1.warmupAndTakeSnapshots)({
|
|
30
|
+
scenario,
|
|
31
|
+
});
|
|
32
|
+
const analysis = new index_1.StringAnalysis();
|
|
33
|
+
const snapshotFile = result.getSnapshotFiles().pop();
|
|
34
|
+
analysis.analyzeSnapshotFromFile(snapshotFile);
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
test();
|
|
@@ -17,12 +17,8 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
17
17
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
18
18
|
});
|
|
19
19
|
};
|
|
20
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
21
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
22
|
-
};
|
|
23
20
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
24
21
|
/* eslint-disable @typescript-eslint/ban-ts-comment */
|
|
25
|
-
const path_1 = __importDefault(require("path"));
|
|
26
22
|
const index_1 = require("../../index");
|
|
27
23
|
const E2ETestSettings_1 = require("./lib/E2ETestSettings");
|
|
28
24
|
beforeEach(E2ETestSettings_1.testSetup);
|
|
@@ -44,29 +40,24 @@ function inject() {
|
|
|
44
40
|
test('Shape unbound analysis works as expected', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
45
41
|
const repeatScenario = Object.assign({ repeat: () => 2 }, E2ETestSettings_1.scenario);
|
|
46
42
|
// test analysis from auto loading
|
|
47
|
-
const result = yield (0, index_1.
|
|
43
|
+
const result = yield (0, index_1.warmupAndTakeSnapshots)({
|
|
48
44
|
scenario: repeatScenario,
|
|
49
45
|
evalInBrowserAfterInitLoad: inject,
|
|
50
46
|
snapshotForEachStep: true,
|
|
51
47
|
});
|
|
52
48
|
// test analysis from auto loading
|
|
53
49
|
let analysis = new index_1.ShapeUnboundGrowthAnalysis();
|
|
54
|
-
|
|
50
|
+
yield analysis.run();
|
|
51
|
+
let shapeSummary = analysis.getShapesWithUnboundGrowth();
|
|
55
52
|
expect(shapeSummary.reduce((acc, summary) => acc || summary.shape.includes('LeakObject'), false)).toBe(true);
|
|
56
53
|
// test analysis from file
|
|
57
|
-
const snapshotDir =
|
|
54
|
+
const snapshotDir = result.getSnapshotFileDir();
|
|
58
55
|
analysis = new index_1.ShapeUnboundGrowthAnalysis();
|
|
59
|
-
|
|
56
|
+
yield analysis.analyzeSnapshotsInDirectory(snapshotDir);
|
|
57
|
+
shapeSummary = analysis.getShapesWithUnboundGrowth();
|
|
60
58
|
expect(shapeSummary.some((summary) => summary.shape.includes('LeakObject'))).toBe(true);
|
|
61
59
|
// expect incorrect use of heap analysis to throw
|
|
62
|
-
const snapshotFile =
|
|
60
|
+
const snapshotFile = result.getSnapshotFiles().pop();
|
|
63
61
|
analysis = new index_1.ShapeUnboundGrowthAnalysis();
|
|
64
|
-
|
|
65
|
-
try {
|
|
66
|
-
yield analysis.analyzeSnapshotFromFile(snapshotFile);
|
|
67
|
-
}
|
|
68
|
-
catch (ex) {
|
|
69
|
-
isThrow = true;
|
|
70
|
-
}
|
|
71
|
-
expect(isThrow).toBe(true);
|
|
62
|
+
expect(() => __awaiter(void 0, void 0, void 0, function* () { return yield analysis.analyzeSnapshotFromFile(snapshotFile); })).rejects.toThrowError();
|
|
72
63
|
}), E2ETestSettings_1.testTimeout);
|
|
@@ -17,12 +17,8 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
17
17
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
18
18
|
});
|
|
19
19
|
};
|
|
20
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
21
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
22
|
-
};
|
|
23
20
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
24
21
|
/* eslint-disable @typescript-eslint/ban-ts-comment */
|
|
25
|
-
const path_1 = __importDefault(require("path"));
|
|
26
22
|
const index_1 = require("../../index");
|
|
27
23
|
const E2ETestSettings_1 = require("./lib/E2ETestSettings");
|
|
28
24
|
beforeEach(E2ETestSettings_1.testSetup);
|
|
@@ -38,7 +34,10 @@ function inject() {
|
|
|
38
34
|
};
|
|
39
35
|
}
|
|
40
36
|
test('String analysis works as expected', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
41
|
-
const result = yield (0, index_1.
|
|
37
|
+
const result = yield (0, index_1.warmupAndTakeSnapshots)({
|
|
38
|
+
scenario: E2ETestSettings_1.scenario,
|
|
39
|
+
evalInBrowserAfterInitLoad: inject,
|
|
40
|
+
});
|
|
42
41
|
// test analysis from auto loading
|
|
43
42
|
let analysis = new index_1.StringAnalysis();
|
|
44
43
|
yield analysis.run();
|
|
@@ -46,21 +45,26 @@ test('String analysis works as expected', () => __awaiter(void 0, void 0, void 0
|
|
|
46
45
|
expect(dupStrings[0].n).toBe(10000);
|
|
47
46
|
expect(dupStrings[0].str).toBe('duplicated string value0');
|
|
48
47
|
// test analysis from file
|
|
49
|
-
const snapshotFile =
|
|
48
|
+
const snapshotFile = result.getSnapshotFiles().pop();
|
|
50
49
|
analysis = new index_1.StringAnalysis();
|
|
51
50
|
yield analysis.analyzeSnapshotFromFile(snapshotFile);
|
|
52
51
|
dupStrings = analysis.getTopDuplicatedStringsInCount();
|
|
53
52
|
expect(dupStrings[0].n).toBe(10000);
|
|
54
53
|
expect(dupStrings[0].str).toBe('duplicated string value0');
|
|
55
54
|
// expect incorrect use of heap analysis to throw
|
|
56
|
-
const snapshotDir = result.
|
|
55
|
+
const snapshotDir = result.getSnapshotFileDir();
|
|
57
56
|
analysis = new index_1.StringAnalysis();
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
}
|
|
65
|
-
|
|
57
|
+
expect(() => __awaiter(void 0, void 0, void 0, function* () { return yield analysis.analyzeSnapshotsInDirectory(snapshotDir); })).rejects.toThrowError();
|
|
58
|
+
}), E2ETestSettings_1.testTimeout);
|
|
59
|
+
test('analyze function works as expected', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
60
|
+
const result = yield (0, index_1.warmupAndTakeSnapshots)({
|
|
61
|
+
scenario: E2ETestSettings_1.scenario,
|
|
62
|
+
evalInBrowserAfterInitLoad: inject,
|
|
63
|
+
});
|
|
64
|
+
// test analysis from auto loading
|
|
65
|
+
const analysis = new index_1.StringAnalysis();
|
|
66
|
+
yield (0, index_1.analyze)(result, analysis);
|
|
67
|
+
const dupStrings = analysis.getTopDuplicatedStringsInCount();
|
|
68
|
+
expect(dupStrings[0].n).toBe(10000);
|
|
69
|
+
expect(dupStrings[0].str).toBe('duplicated string value0');
|
|
66
70
|
}), E2ETestSettings_1.testTimeout);
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the MIT license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
*
|
|
7
|
+
* @emails oncall+ws_labs
|
|
8
|
+
* @format
|
|
9
|
+
*/
|
|
10
|
+
export {};
|
|
11
|
+
//# sourceMappingURL=heap-analysis.test.d.ts.map
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
4
|
+
*
|
|
5
|
+
* This source code is licensed under the MIT license found in the
|
|
6
|
+
* LICENSE file in the root directory of this source tree.
|
|
7
|
+
*
|
|
8
|
+
* @emails oncall+ws_labs
|
|
9
|
+
* @format
|
|
10
|
+
*/
|
|
11
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
12
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
13
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
14
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
15
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
16
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
17
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
18
|
+
});
|
|
19
|
+
};
|
|
20
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
21
|
+
const heap_analysis_1 = require("@memlab/heap-analysis");
|
|
22
|
+
const index_1 = require("../../index");
|
|
23
|
+
const E2ETestSettings_1 = require("../API/lib/E2ETestSettings");
|
|
24
|
+
const API_1 = require("../../API");
|
|
25
|
+
beforeEach(E2ETestSettings_1.testSetup);
|
|
26
|
+
function injectTestObject() {
|
|
27
|
+
class TestObject {
|
|
28
|
+
}
|
|
29
|
+
// @ts-ignore
|
|
30
|
+
window.injectHookForLink4 = () => {
|
|
31
|
+
// @ts-ignore
|
|
32
|
+
const arr = (window.__injectedValue = window.__injectedValue || []);
|
|
33
|
+
arr.push(new TestObject());
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
const selfDefinedScenario = {
|
|
37
|
+
app: () => 'test-spa',
|
|
38
|
+
url: () => '',
|
|
39
|
+
action: (page) => __awaiter(void 0, void 0, void 0, function* () { return yield page.click('[data-testid="link-4"]'); }),
|
|
40
|
+
repeat: () => 3,
|
|
41
|
+
};
|
|
42
|
+
class ExampleAnalysis extends heap_analysis_1.BaseAnalysis {
|
|
43
|
+
constructor() {
|
|
44
|
+
super(...arguments);
|
|
45
|
+
this.isMonotonicIncreasing = false;
|
|
46
|
+
}
|
|
47
|
+
getCommandName() {
|
|
48
|
+
return 'example-analysis';
|
|
49
|
+
}
|
|
50
|
+
getDescription() {
|
|
51
|
+
return 'an example analysis for demo';
|
|
52
|
+
}
|
|
53
|
+
process(options) {
|
|
54
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
55
|
+
// check if the number of TestObject keeps growing overtime
|
|
56
|
+
this.isMonotonicIncreasing = yield (0, heap_analysis_1.snapshotMapReduce)(heap => {
|
|
57
|
+
let cnt = 0;
|
|
58
|
+
heap.nodes.forEach(node => {
|
|
59
|
+
if (node.name === 'TestObject' && node.type === 'object') {
|
|
60
|
+
++cnt;
|
|
61
|
+
}
|
|
62
|
+
});
|
|
63
|
+
return cnt;
|
|
64
|
+
}, nodeCounts => nodeCounts[0] === 0 &&
|
|
65
|
+
nodeCounts[nodeCounts.length - 1] === 4 &&
|
|
66
|
+
nodeCounts.every((count, i) => i === 0 || count >= nodeCounts[i - 1]), options);
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
test('snapshotMapReduce works as expected', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
71
|
+
const results = yield (0, API_1.takeSnapshots)({
|
|
72
|
+
scenario: selfDefinedScenario,
|
|
73
|
+
evalInBrowserAfterInitLoad: injectTestObject,
|
|
74
|
+
snapshotForEachStep: true,
|
|
75
|
+
});
|
|
76
|
+
let analysis = new ExampleAnalysis();
|
|
77
|
+
yield (0, index_1.analyze)(results, analysis);
|
|
78
|
+
expect(analysis.isMonotonicIncreasing).toBe(true);
|
|
79
|
+
analysis = new ExampleAnalysis();
|
|
80
|
+
yield analysis.analyzeSnapshotsInDirectory(results.getSnapshotFileDir());
|
|
81
|
+
expect(analysis.isMonotonicIncreasing).toBe(true);
|
|
82
|
+
}), E2ETestSettings_1.testTimeout);
|
package/dist/index.d.ts
CHANGED
|
@@ -9,5 +9,8 @@
|
|
|
9
9
|
*/
|
|
10
10
|
export * from './API';
|
|
11
11
|
export * from '@memlab/heap-analysis';
|
|
12
|
+
export { default as BrowserInteractionResultReader } from './result-reader/BrowserInteractionResultReader';
|
|
13
|
+
export { dumpNodeHeapSnapshot, getCurrentNodeHeap } from '@memlab/core';
|
|
14
|
+
/** @internal */
|
|
12
15
|
export { config } from '@memlab/core';
|
|
13
16
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.js
CHANGED
|
@@ -22,9 +22,18 @@ var __createBinding = (this && this.__createBinding) || (Object.create ? (functi
|
|
|
22
22
|
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
23
23
|
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
24
24
|
};
|
|
25
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
26
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
27
|
+
};
|
|
25
28
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
26
|
-
exports.config = void 0;
|
|
29
|
+
exports.config = exports.getCurrentNodeHeap = exports.dumpNodeHeapSnapshot = exports.BrowserInteractionResultReader = void 0;
|
|
27
30
|
__exportStar(require("./API"), exports);
|
|
28
31
|
__exportStar(require("@memlab/heap-analysis"), exports);
|
|
32
|
+
var BrowserInteractionResultReader_1 = require("./result-reader/BrowserInteractionResultReader");
|
|
33
|
+
Object.defineProperty(exports, "BrowserInteractionResultReader", { enumerable: true, get: function () { return __importDefault(BrowserInteractionResultReader_1).default; } });
|
|
29
34
|
var core_1 = require("@memlab/core");
|
|
30
|
-
Object.defineProperty(exports, "
|
|
35
|
+
Object.defineProperty(exports, "dumpNodeHeapSnapshot", { enumerable: true, get: function () { return core_1.dumpNodeHeapSnapshot; } });
|
|
36
|
+
Object.defineProperty(exports, "getCurrentNodeHeap", { enumerable: true, get: function () { return core_1.getCurrentNodeHeap; } });
|
|
37
|
+
/** @internal */
|
|
38
|
+
var core_2 = require("@memlab/core");
|
|
39
|
+
Object.defineProperty(exports, "config", { enumerable: true, get: function () { return core_2.config; } });
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the MIT license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
*
|
|
7
|
+
* @emails oncall+ws_labs
|
|
8
|
+
* @format
|
|
9
|
+
*/
|
|
10
|
+
import { FileManager } from '@memlab/core';
|
|
11
|
+
/**
|
|
12
|
+
* A utility entity to read all generated files from
|
|
13
|
+
* the directory holding the data and results from
|
|
14
|
+
* a memlab run
|
|
15
|
+
*/
|
|
16
|
+
export default class BaseResultReader {
|
|
17
|
+
protected workDir: string;
|
|
18
|
+
protected fileManager: FileManager;
|
|
19
|
+
private isValid;
|
|
20
|
+
/**
|
|
21
|
+
* build a result reader
|
|
22
|
+
* @param workDir absolute path of the directory where the data
|
|
23
|
+
* and generated files of the memlab run were stored
|
|
24
|
+
*/
|
|
25
|
+
protected constructor(workDir?: string);
|
|
26
|
+
protected check(): void;
|
|
27
|
+
/**
|
|
28
|
+
* internal
|
|
29
|
+
* @param workDir
|
|
30
|
+
* @returns
|
|
31
|
+
*/
|
|
32
|
+
static from(workDir?: string): BaseResultReader;
|
|
33
|
+
/**
|
|
34
|
+
* get the directory where the data and generated files of
|
|
35
|
+
* the memlab run were stored
|
|
36
|
+
* @returns absolute path of the directory
|
|
37
|
+
* * **Examples**:
|
|
38
|
+
* ```javascript
|
|
39
|
+
* const {takeSnapshots} = require('@memlab/api');
|
|
40
|
+
*
|
|
41
|
+
* (async function () {
|
|
42
|
+
* const scenario = { url: () => 'https://www.npmjs.com'};
|
|
43
|
+
* const result = await takeSnapshots({scenario});
|
|
44
|
+
*
|
|
45
|
+
* // get the directory that stores all the files
|
|
46
|
+
* // generated from the takeSnapshots call
|
|
47
|
+
* const dataDir = result.getRootDirectory();
|
|
48
|
+
* })();
|
|
49
|
+
* ```
|
|
50
|
+
*/
|
|
51
|
+
getRootDirectory(): string;
|
|
52
|
+
/**
|
|
53
|
+
* clean up data/files generated from the memlab browser interaction run
|
|
54
|
+
* @returns no return value
|
|
55
|
+
* * **Examples**:
|
|
56
|
+
* ```javascript
|
|
57
|
+
* const {takeSnapshots} = require('@memlab/api');
|
|
58
|
+
*
|
|
59
|
+
* (async function () {
|
|
60
|
+
* const scenario = { url: () => 'https://www.npmjs.com'};
|
|
61
|
+
* const result = await takeSnapshots({scenario});
|
|
62
|
+
*
|
|
63
|
+
* // delete all data/files generated by takeSnapshots
|
|
64
|
+
* result.cleanup();
|
|
65
|
+
* })();
|
|
66
|
+
* ```
|
|
67
|
+
*/
|
|
68
|
+
cleanup(): void;
|
|
69
|
+
}
|
|
70
|
+
//# sourceMappingURL=BaseResultReader.d.ts.map
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
4
|
+
*
|
|
5
|
+
* This source code is licensed under the MIT license found in the
|
|
6
|
+
* LICENSE file in the root directory of this source tree.
|
|
7
|
+
*
|
|
8
|
+
* @emails oncall+ws_labs
|
|
9
|
+
* @format
|
|
10
|
+
*/
|
|
11
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
12
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
13
|
+
};
|
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
const core_1 = require("@memlab/core");
|
|
16
|
+
const fs_extra_1 = __importDefault(require("fs-extra"));
|
|
17
|
+
/**
|
|
18
|
+
* A utility entity to read all generated files from
|
|
19
|
+
* the directory holding the data and results from
|
|
20
|
+
* a memlab run
|
|
21
|
+
*/
|
|
22
|
+
class BaseResultReader {
|
|
23
|
+
/**
|
|
24
|
+
* build a result reader
|
|
25
|
+
* @param workDir absolute path of the directory where the data
|
|
26
|
+
* and generated files of the memlab run were stored
|
|
27
|
+
*/
|
|
28
|
+
constructor(workDir = '') {
|
|
29
|
+
this.fileManager = new core_1.FileManager();
|
|
30
|
+
if (workDir === '') {
|
|
31
|
+
workDir = this.fileManager.getWorkDir();
|
|
32
|
+
}
|
|
33
|
+
this.workDir = workDir;
|
|
34
|
+
this.check();
|
|
35
|
+
}
|
|
36
|
+
check() {
|
|
37
|
+
this.isValid = fs_extra_1.default.existsSync(this.workDir);
|
|
38
|
+
if (!this.isValid) {
|
|
39
|
+
core_1.utils.haltOrThrow(`invalid/removed data directory: ${this.workDir}`);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* internal
|
|
44
|
+
* @param workDir
|
|
45
|
+
* @returns
|
|
46
|
+
*/
|
|
47
|
+
static from(workDir = '') {
|
|
48
|
+
return new BaseResultReader(workDir);
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* get the directory where the data and generated files of
|
|
52
|
+
* the memlab run were stored
|
|
53
|
+
* @returns absolute path of the directory
|
|
54
|
+
* * **Examples**:
|
|
55
|
+
* ```javascript
|
|
56
|
+
* const {takeSnapshots} = require('@memlab/api');
|
|
57
|
+
*
|
|
58
|
+
* (async function () {
|
|
59
|
+
* const scenario = { url: () => 'https://www.npmjs.com'};
|
|
60
|
+
* const result = await takeSnapshots({scenario});
|
|
61
|
+
*
|
|
62
|
+
* // get the directory that stores all the files
|
|
63
|
+
* // generated from the takeSnapshots call
|
|
64
|
+
* const dataDir = result.getRootDirectory();
|
|
65
|
+
* })();
|
|
66
|
+
* ```
|
|
67
|
+
*/
|
|
68
|
+
getRootDirectory() {
|
|
69
|
+
this.check();
|
|
70
|
+
return this.workDir;
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* clean up data/files generated from the memlab browser interaction run
|
|
74
|
+
* @returns no return value
|
|
75
|
+
* * **Examples**:
|
|
76
|
+
* ```javascript
|
|
77
|
+
* const {takeSnapshots} = require('@memlab/api');
|
|
78
|
+
*
|
|
79
|
+
* (async function () {
|
|
80
|
+
* const scenario = { url: () => 'https://www.npmjs.com'};
|
|
81
|
+
* const result = await takeSnapshots({scenario});
|
|
82
|
+
*
|
|
83
|
+
* // delete all data/files generated by takeSnapshots
|
|
84
|
+
* result.cleanup();
|
|
85
|
+
* })();
|
|
86
|
+
* ```
|
|
87
|
+
*/
|
|
88
|
+
cleanup() {
|
|
89
|
+
if (!this.isValid) {
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
fs_extra_1.default.removeSync(this.workDir);
|
|
93
|
+
this.isValid = false;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
exports.default = BaseResultReader;
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the MIT license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
*
|
|
7
|
+
* @emails oncall+ws_labs
|
|
8
|
+
* @format
|
|
9
|
+
*/
|
|
10
|
+
import type { E2EStepInfo, RunMetaInfo } from '@memlab/core';
|
|
11
|
+
import BaseResultReader from './BaseResultReader';
|
|
12
|
+
/**
|
|
13
|
+
* A utility entity to read all generated files from
|
|
14
|
+
* the directory holding the data and results from the
|
|
15
|
+
* last browser interaction run
|
|
16
|
+
*/
|
|
17
|
+
export default class BrowserInteractionResultReader extends BaseResultReader {
|
|
18
|
+
/**
|
|
19
|
+
* build a result reader from a data directory where the data
|
|
20
|
+
* and generated files of a memlab run were stored
|
|
21
|
+
* @param workDir absolute path of the data directory
|
|
22
|
+
* @returns the ResultReader instance
|
|
23
|
+
*
|
|
24
|
+
* * **Examples**:
|
|
25
|
+
* ```javascript
|
|
26
|
+
* const {BrowserInteractionResultReader} = require('@memlab/api');
|
|
27
|
+
*
|
|
28
|
+
* const dataDir = '/tmp/memlab'; // where the last memlab run stores results
|
|
29
|
+
* const reader = BrowserInteractionResultReader.from(dataDir);
|
|
30
|
+
* reader.cleanup(); // clean up the results
|
|
31
|
+
* ```
|
|
32
|
+
*/
|
|
33
|
+
static from(workDir?: string): BrowserInteractionResultReader;
|
|
34
|
+
/**
|
|
35
|
+
* get all snapshot files generated from last memlab browser interaction
|
|
36
|
+
* @returns an array of snapshot file's absolute path
|
|
37
|
+
* * **Examples**:
|
|
38
|
+
* ```javascript
|
|
39
|
+
* const {takeSnapshots} = require('@memlab/api');
|
|
40
|
+
*
|
|
41
|
+
* (async function () {
|
|
42
|
+
* const scenario = { url: () => 'https://www.npmjs.com'};
|
|
43
|
+
* const result = await takeSnapshots({scenario});
|
|
44
|
+
*
|
|
45
|
+
* // get absolute paths of all snapshot files
|
|
46
|
+
* const files = result.getSnapshotFiles();
|
|
47
|
+
* })();
|
|
48
|
+
* ```
|
|
49
|
+
*/
|
|
50
|
+
getSnapshotFiles(): string[];
|
|
51
|
+
/**
|
|
52
|
+
* get the directory holding all snapshot files
|
|
53
|
+
* @returns the absolute path of the directory
|
|
54
|
+
* * **Examples**:
|
|
55
|
+
* ```javascript
|
|
56
|
+
* const {takeSnapshots} = require('@memlab/api');
|
|
57
|
+
*
|
|
58
|
+
* (async function () {
|
|
59
|
+
* const scenario = { url: () => 'https://www.npmjs.com'};
|
|
60
|
+
* const result = await takeSnapshots({scenario});
|
|
61
|
+
*
|
|
62
|
+
* // get the absolute path the directory holding all snapshot files
|
|
63
|
+
* const files = result.getSnapshotFileDir();
|
|
64
|
+
* })();
|
|
65
|
+
* ```
|
|
66
|
+
*/
|
|
67
|
+
getSnapshotFileDir(): string;
|
|
68
|
+
/**
|
|
69
|
+
* browser interaction step sequence
|
|
70
|
+
* @returns an array of browser interaction step information
|
|
71
|
+
* * **Examples**:
|
|
72
|
+
* ```javascript
|
|
73
|
+
* const {takeSnapshots} = require('@memlab/api');
|
|
74
|
+
*
|
|
75
|
+
* (async function () {
|
|
76
|
+
* const scenario = { url: () => 'https://www.npmjs.com'};
|
|
77
|
+
* const result = await takeSnapshots({scenario});
|
|
78
|
+
*
|
|
79
|
+
* const steps = result.getInteractionSteps();
|
|
80
|
+
* // print each browser interaction's name and JavaScript heap size (in bytes)
|
|
81
|
+
* steps.forEach(step => console.log(step.name, step.JSHeapUsedSize))
|
|
82
|
+
* })();
|
|
83
|
+
* ```
|
|
84
|
+
*/
|
|
85
|
+
getInteractionSteps(): E2EStepInfo[];
|
|
86
|
+
/**
|
|
87
|
+
* general meta data of the browser interaction run
|
|
88
|
+
* @returns meta data about the entire browser interaction
|
|
89
|
+
* * **Examples**:
|
|
90
|
+
* ```javascript
|
|
91
|
+
* const {takeSnapshots} = require('@memlab/api');
|
|
92
|
+
*
|
|
93
|
+
* (async function () {
|
|
94
|
+
* const scenario = { url: () => 'https://www.npmjs.com'};
|
|
95
|
+
* const result = await takeSnapshots({scenario});
|
|
96
|
+
*
|
|
97
|
+
* const metaInfo = result.getRunMetaInfo();
|
|
98
|
+
* // print all browser web console output
|
|
99
|
+
* console.log(metaInfo.browserInfo._consoleMessages.join('\n'));
|
|
100
|
+
* })();
|
|
101
|
+
* ```
|
|
102
|
+
*/
|
|
103
|
+
getRunMetaInfo(): RunMetaInfo;
|
|
104
|
+
}
|
|
105
|
+
//# sourceMappingURL=BrowserInteractionResultReader.d.ts.map
|