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 type { Config } from './types';
|
||||
import { Runner } from './runner';
|
||||
import { stopProfiling, startProfiling } from './profiler';
|
||||
|
||||
const defaultTimeout = 30000;
|
||||
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 }) {
|
||||
await startProfiling();
|
||||
|
||||
const browserOpt = opts.browser ? opts.browser.toLowerCase() : 'chromium';
|
||||
if (!['all', 'chromium', 'firefox', 'webkit'].includes(browserOpt))
|
||||
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);
|
||||
await stopProfiling(undefined);
|
||||
|
||||
if (result === 'sigint')
|
||||
process.exit(130);
|
||||
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 * as util from 'util';
|
||||
import { RunPayload, TestOutputPayload, WorkerInitParams } from './ipc';
|
||||
import { startProfiling, stopProfiling } from './profiler';
|
||||
import { serializeError } from './util';
|
||||
import { WorkerRunner } from './workerRunner';
|
||||
|
||||
|
|
@ -55,6 +56,7 @@ process.on('SIGINT',() => {});
|
|||
process.on('SIGTERM',() => {});
|
||||
|
||||
let workerRunner: WorkerRunner;
|
||||
let workerIndex: number | undefined;
|
||||
|
||||
process.on('unhandledRejection', (reason, promise) => {
|
||||
if (workerRunner)
|
||||
|
|
@ -69,6 +71,8 @@ process.on('uncaughtException', error => {
|
|||
process.on('message', async message => {
|
||||
if (message.method === 'init') {
|
||||
const initParams = message.params as WorkerInitParams;
|
||||
workerIndex = initParams.workerIndex;
|
||||
startProfiling();
|
||||
workerRunner = new WorkerRunner(initParams);
|
||||
for (const event of ['testBegin', 'testEnd', 'done'])
|
||||
workerRunner.on(event, sendMessageToParent.bind(null, event));
|
||||
|
|
@ -96,6 +100,8 @@ async function gracefullyCloseAndExit() {
|
|||
workerRunner.stop();
|
||||
await workerRunner.cleanup();
|
||||
}
|
||||
if (workerIndex !== undefined)
|
||||
await stopProfiling(workerIndex);
|
||||
} catch (e) {
|
||||
process.send!({ method: 'teardownError', params: { error: serializeError(e) } });
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue