chore(test runner): self profile under PWTEST_PROFILE_DIR (#7252)
`PWTEST_CLI_ALLOW_TEST_COMMAND=1 PWTEST_PROFILE_DIR=./profile node lib/cli/cli.js test -c <dir/config>`
This commit is contained in:
parent
143689e34f
commit
73a43fce60
|
|
@ -21,6 +21,7 @@ import * as fs from 'fs';
|
||||||
import * as path from 'path';
|
import * as path from 'path';
|
||||||
import type { Config } from './types';
|
import type { Config } from './types';
|
||||||
import { Runner } from './runner';
|
import { Runner } from './runner';
|
||||||
|
import { stopProfiling, startProfiling } from './profiler';
|
||||||
|
|
||||||
const defaultTimeout = 30000;
|
const defaultTimeout = 30000;
|
||||||
const defaultReporter = process.env.CI ? 'dot' : 'list';
|
const defaultReporter = process.env.CI ? 'dot' : 'list';
|
||||||
|
|
@ -80,6 +81,8 @@ export function addTestCommand(program: commander.CommanderStatic) {
|
||||||
}
|
}
|
||||||
|
|
||||||
async function runTests(args: string[], opts: { [key: string]: any }) {
|
async function runTests(args: string[], opts: { [key: string]: any }) {
|
||||||
|
await startProfiling();
|
||||||
|
|
||||||
const browserOpt = opts.browser ? opts.browser.toLowerCase() : 'chromium';
|
const browserOpt = opts.browser ? opts.browser.toLowerCase() : 'chromium';
|
||||||
if (!['all', 'chromium', 'firefox', 'webkit'].includes(browserOpt))
|
if (!['all', 'chromium', 'firefox', 'webkit'].includes(browserOpt))
|
||||||
throw new Error(`Unsupported browser "${opts.browser}", must be one of "all", "chromium", "firefox" or "webkit"`);
|
throw new Error(`Unsupported browser "${opts.browser}", must be one of "all", "chromium", "firefox" or "webkit"`);
|
||||||
|
|
@ -129,6 +132,8 @@ async function runTests(args: string[], opts: { [key: string]: any }) {
|
||||||
}
|
}
|
||||||
|
|
||||||
const result = await runner.run(!!opts.list, args.map(forceRegExp), opts.project || undefined);
|
const result = await runner.run(!!opts.list, args.map(forceRegExp), opts.project || undefined);
|
||||||
|
await stopProfiling(undefined);
|
||||||
|
|
||||||
if (result === 'sigint')
|
if (result === 'sigint')
|
||||||
process.exit(130);
|
process.exit(130);
|
||||||
process.exit(result === 'passed' ? 0 : 1);
|
process.exit(result === 'passed' ? 0 : 1);
|
||||||
|
|
|
||||||
48
src/test/profiler.ts
Normal file
48
src/test/profiler.ts
Normal file
|
|
@ -0,0 +1,48 @@
|
||||||
|
/**
|
||||||
|
* Copyright Microsoft Corporation. All rights reserved.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import * as fs from 'fs';
|
||||||
|
import * as path from 'path';
|
||||||
|
|
||||||
|
const profileDir = process.env.PWTEST_PROFILE_DIR || '';
|
||||||
|
|
||||||
|
let session: import('inspector').Session;
|
||||||
|
|
||||||
|
export async function startProfiling() {
|
||||||
|
if (!profileDir)
|
||||||
|
return;
|
||||||
|
|
||||||
|
session = new (require('inspector').Session)();
|
||||||
|
session.connect();
|
||||||
|
await new Promise<void>(f => {
|
||||||
|
session.post('Profiler.enable', () => {
|
||||||
|
session.post('Profiler.start', f);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function stopProfiling(workerIndex: number | undefined) {
|
||||||
|
if (!profileDir)
|
||||||
|
return;
|
||||||
|
|
||||||
|
await new Promise<void>(f => session.post('Profiler.stop', async (err, { profile }) => {
|
||||||
|
if (!err) {
|
||||||
|
await fs.promises.mkdir(profileDir, { recursive: true });
|
||||||
|
await fs.promises.writeFile(path.join(profileDir, workerIndex === undefined ? 'runner.json' : 'worker' + workerIndex + '.json'), JSON.stringify(profile));
|
||||||
|
}
|
||||||
|
f();
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
@ -17,6 +17,7 @@
|
||||||
import { Console } from 'console';
|
import { Console } from 'console';
|
||||||
import * as util from 'util';
|
import * as util from 'util';
|
||||||
import { RunPayload, TestOutputPayload, WorkerInitParams } from './ipc';
|
import { RunPayload, TestOutputPayload, WorkerInitParams } from './ipc';
|
||||||
|
import { startProfiling, stopProfiling } from './profiler';
|
||||||
import { serializeError } from './util';
|
import { serializeError } from './util';
|
||||||
import { WorkerRunner } from './workerRunner';
|
import { WorkerRunner } from './workerRunner';
|
||||||
|
|
||||||
|
|
@ -55,6 +56,7 @@ process.on('SIGINT',() => {});
|
||||||
process.on('SIGTERM',() => {});
|
process.on('SIGTERM',() => {});
|
||||||
|
|
||||||
let workerRunner: WorkerRunner;
|
let workerRunner: WorkerRunner;
|
||||||
|
let workerIndex: number | undefined;
|
||||||
|
|
||||||
process.on('unhandledRejection', (reason, promise) => {
|
process.on('unhandledRejection', (reason, promise) => {
|
||||||
if (workerRunner)
|
if (workerRunner)
|
||||||
|
|
@ -69,6 +71,8 @@ process.on('uncaughtException', error => {
|
||||||
process.on('message', async message => {
|
process.on('message', async message => {
|
||||||
if (message.method === 'init') {
|
if (message.method === 'init') {
|
||||||
const initParams = message.params as WorkerInitParams;
|
const initParams = message.params as WorkerInitParams;
|
||||||
|
workerIndex = initParams.workerIndex;
|
||||||
|
startProfiling();
|
||||||
workerRunner = new WorkerRunner(initParams);
|
workerRunner = new WorkerRunner(initParams);
|
||||||
for (const event of ['testBegin', 'testEnd', 'done'])
|
for (const event of ['testBegin', 'testEnd', 'done'])
|
||||||
workerRunner.on(event, sendMessageToParent.bind(null, event));
|
workerRunner.on(event, sendMessageToParent.bind(null, event));
|
||||||
|
|
@ -96,6 +100,8 @@ async function gracefullyCloseAndExit() {
|
||||||
workerRunner.stop();
|
workerRunner.stop();
|
||||||
await workerRunner.cleanup();
|
await workerRunner.cleanup();
|
||||||
}
|
}
|
||||||
|
if (workerIndex !== undefined)
|
||||||
|
await stopProfiling(workerIndex);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
process.send!({ method: 'teardownError', params: { error: serializeError(e) } });
|
process.send!({ method: 'teardownError', params: { error: serializeError(e) } });
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue