UNPKG

2.83 kBPlain TextView Raw
1import { URL } from 'url';
2
3import { FileDescriptions, StrykerOptions } from '@stryker-mutator/api/core';
4import { Logger } from '@stryker-mutator/api/logging';
5import { TestRunner, DryRunOptions, MutantRunOptions, MutantRunResult, DryRunResult, TestRunnerCapabilities } from '@stryker-mutator/api/test-runner';
6import { ExpirableTask } from '@stryker-mutator/util';
7
8import { ChildProcessCrashedError } from '../child-proxy/child-process-crashed-error.js';
9import { ChildProcessProxy } from '../child-proxy/child-process-proxy.js';
10import { LoggingClientContext } from '../logging/index.js';
11
12import { IdGenerator } from '../child-proxy/id-generator.js';
13
14import { ChildProcessTestRunnerWorker } from './child-process-test-runner-worker.js';
15
16const MAX_WAIT_FOR_DISPOSE = 2000;
17
18/**
19 * Runs the given test runner in a child process and forwards reports about test results
20 */
21export class ChildProcessTestRunnerProxy implements TestRunner {
22 private readonly worker: ChildProcessProxy<ChildProcessTestRunnerWorker>;
23
24 constructor(
25 options: StrykerOptions,
26 fileDescriptions: FileDescriptions,
27 sandboxWorkingDirectory: string,
28 loggingContext: LoggingClientContext,
29 pluginModulePaths: readonly string[],
30 private readonly log: Logger,
31 idGenerator: IdGenerator
32 ) {
33 this.worker = ChildProcessProxy.create(
34 new URL('./child-process-test-runner-worker.js', import.meta.url).toString(),
35 loggingContext,
36 options,
37 fileDescriptions,
38 pluginModulePaths,
39 sandboxWorkingDirectory,
40 ChildProcessTestRunnerWorker,
41 options.testRunnerNodeArgs,
42 idGenerator
43 );
44 }
45
46 public capabilities(): Promise<TestRunnerCapabilities> {
47 return this.worker.proxy.capabilities();
48 }
49
50 public init(): Promise<void> {
51 return this.worker.proxy.init();
52 }
53
54 public dryRun(options: DryRunOptions): Promise<DryRunResult> {
55 return this.worker.proxy.dryRun(options);
56 }
57 public mutantRun(options: MutantRunOptions): Promise<MutantRunResult> {
58 return this.worker.proxy.mutantRun(options);
59 }
60
61 public async dispose(): Promise<void> {
62 await ExpirableTask.timeout(
63 // First let the inner test runner dispose
64 this.worker.proxy.dispose().catch((error) => {
65 // It's OK if the child process is already down.
66 if (!(error instanceof ChildProcessCrashedError)) {
67 // Handle error by logging it. We still want to kill the child process.
68 this.log.warn(
69 'An unexpected error occurred during test runner disposal. This might be worth looking into. Stryker will ignore this error.',
70 error
71 );
72 }
73 }),
74
75 // ... but don't wait forever on that
76 MAX_WAIT_FOR_DISPOSE
77 );
78
79 // After that, dispose the child process itself
80 await this.worker.dispose();
81 }
82}