mirror of
https://github.com/github/codeql-action.git
synced 2025-12-26 17:20:10 +08:00
263 lines
5.5 KiB
JavaScript
263 lines
5.5 KiB
JavaScript
import v8 from 'node:v8';
|
|
|
|
import Emittery from 'emittery';
|
|
|
|
const copyStats = stats => v8.deserialize(v8.serialize(stats));
|
|
|
|
export default class RunStatus extends Emittery {
|
|
constructor(files, parallelRuns, selectionInsights) {
|
|
super();
|
|
|
|
this.pendingTests = new Map();
|
|
this.pendingTestsLogs = new Map();
|
|
|
|
this.emptyParallelRun = parallelRuns
|
|
&& parallelRuns.currentFileCount === 0
|
|
&& parallelRuns.totalRuns > 1
|
|
&& files > 0;
|
|
|
|
this.selectionInsights = selectionInsights;
|
|
|
|
this.stats = {
|
|
byFile: new Map(),
|
|
declaredTests: 0,
|
|
failedHooks: 0,
|
|
failedTests: 0,
|
|
failedWorkers: 0,
|
|
files,
|
|
parallelRuns,
|
|
finishedWorkers: 0,
|
|
internalErrors: 0,
|
|
remainingTests: 0,
|
|
passedKnownFailingTests: 0,
|
|
passedTests: 0,
|
|
selectedTests: 0,
|
|
sharedWorkerErrors: 0,
|
|
skippedTests: 0,
|
|
timedOutTests: 0,
|
|
timeouts: 0,
|
|
todoTests: 0,
|
|
uncaughtExceptions: 0,
|
|
unhandledRejections: 0,
|
|
};
|
|
}
|
|
|
|
observeWorker(worker, testFile, stats) {
|
|
this.stats.byFile.set(testFile, {
|
|
declaredTests: 0,
|
|
failedHooks: 0,
|
|
failedTests: 0,
|
|
internalErrors: 0,
|
|
remainingTests: 0,
|
|
passedKnownFailingTests: 0,
|
|
passedTests: 0,
|
|
selectedTests: 0,
|
|
selectingLines: false,
|
|
skippedTests: 0,
|
|
todoTests: 0,
|
|
uncaughtExceptions: 0,
|
|
unhandledRejections: 0,
|
|
...stats,
|
|
});
|
|
|
|
this.pendingTests.set(testFile, new Set());
|
|
this.pendingTestsLogs.set(testFile, new Map());
|
|
worker.onStateChange(data => this.emitStateChange(data));
|
|
}
|
|
|
|
// eslint-disable-next-line complexity
|
|
emitStateChange(event) {
|
|
const {stats} = this;
|
|
const fileStats = stats.byFile.get(event.testFile);
|
|
|
|
let changedStats = true;
|
|
switch (event.type) {
|
|
case 'declared-test': {
|
|
stats.declaredTests++;
|
|
fileStats.declaredTests++;
|
|
break;
|
|
}
|
|
|
|
case 'hook-failed': {
|
|
stats.failedHooks++;
|
|
fileStats.failedHooks++;
|
|
break;
|
|
}
|
|
|
|
case 'internal-error': {
|
|
stats.internalErrors++;
|
|
if (event.testFile) {
|
|
fileStats.internalErrors++;
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
case 'selected-test': {
|
|
stats.selectedTests++;
|
|
fileStats.selectedTests++;
|
|
if (event.skip) {
|
|
stats.skippedTests++;
|
|
fileStats.skippedTests++;
|
|
} else if (event.todo) {
|
|
stats.todoTests++;
|
|
fileStats.todoTests++;
|
|
} else {
|
|
stats.remainingTests++;
|
|
fileStats.remainingTests++;
|
|
this.addPendingTest(event);
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
case 'shared-worker-error': {
|
|
stats.sharedWorkerErrors++;
|
|
break;
|
|
}
|
|
|
|
case 'test-failed': {
|
|
stats.failedTests++;
|
|
fileStats.failedTests++;
|
|
stats.remainingTests--;
|
|
fileStats.remainingTests--;
|
|
this.removePendingTest(event);
|
|
break;
|
|
}
|
|
|
|
case 'test-passed': {
|
|
if (event.knownFailing) {
|
|
stats.passedKnownFailingTests++;
|
|
fileStats.passedKnownFailingTests++;
|
|
} else {
|
|
stats.passedTests++;
|
|
fileStats.passedTests++;
|
|
}
|
|
|
|
stats.remainingTests--;
|
|
fileStats.remainingTests--;
|
|
this.removePendingTest(event);
|
|
break;
|
|
}
|
|
|
|
case 'test-register-log-reference': {
|
|
this.addPendingTestLogs(event);
|
|
break;
|
|
}
|
|
|
|
case 'timeout': {
|
|
stats.timeouts++;
|
|
event.pendingTests = this.pendingTests;
|
|
event.pendingTestsLogs = this.pendingTestsLogs;
|
|
this.pendingTests = new Map();
|
|
this.pendingTestsLogs = new Map();
|
|
for (const testsInFile of event.pendingTests.values()) {
|
|
stats.timedOutTests += testsInFile.size;
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
case 'interrupt': {
|
|
event.pendingTests = this.pendingTests;
|
|
event.pendingTestsLogs = this.pendingTestsLogs;
|
|
this.pendingTests = new Map();
|
|
this.pendingTestsLogs = new Map();
|
|
break;
|
|
}
|
|
|
|
case 'process-exit': {
|
|
event.pendingTests = this.pendingTests;
|
|
event.pendingTestsLogs = this.pendingTestsLogs;
|
|
this.pendingTests = new Map();
|
|
this.pendingTestsLogs = new Map();
|
|
break;
|
|
}
|
|
|
|
case 'uncaught-exception': {
|
|
stats.uncaughtExceptions++;
|
|
fileStats.uncaughtExceptions++;
|
|
break;
|
|
}
|
|
|
|
case 'unhandled-rejection': {
|
|
stats.unhandledRejections++;
|
|
fileStats.unhandledRejections++;
|
|
break;
|
|
}
|
|
|
|
case 'worker-failed': {
|
|
stats.failedWorkers++;
|
|
break;
|
|
}
|
|
|
|
case 'worker-finished': {
|
|
stats.finishedWorkers++;
|
|
break;
|
|
}
|
|
|
|
default: {
|
|
changedStats = false;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (changedStats) {
|
|
this.emit('stateChange', {type: 'stats', stats: copyStats(stats)});
|
|
}
|
|
|
|
this.emit('stateChange', event);
|
|
}
|
|
|
|
suggestExitCode(circumstances) {
|
|
if (this.emptyParallelRun) {
|
|
return 0;
|
|
}
|
|
|
|
if (circumstances.matching && this.stats.selectedTests === 0) {
|
|
return 1;
|
|
}
|
|
|
|
if (
|
|
this.stats.declaredTests === 0
|
|
|| this.stats.internalErrors > 0
|
|
|| this.stats.failedHooks > 0
|
|
|| this.stats.failedTests > 0
|
|
|| this.stats.failedWorkers > 0
|
|
|| this.stats.remainingTests > 0
|
|
|| this.stats.sharedWorkerErrors > 0
|
|
|| this.stats.timeouts > 0
|
|
|| this.stats.uncaughtExceptions > 0
|
|
|| this.stats.unhandledRejections > 0
|
|
) {
|
|
return 1;
|
|
}
|
|
|
|
if ([...this.stats.byFile.values()].some(stats => stats.selectingLines && stats.selectedTests === 0)) {
|
|
return 1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
addPendingTestLogs(event) {
|
|
this.pendingTestsLogs.get(event.testFile)?.set(event.title, event.logs);
|
|
}
|
|
|
|
addPendingTest(event) {
|
|
if (this.pendingTests.has(event.testFile)) {
|
|
this.pendingTests.get(event.testFile).add(event.title);
|
|
}
|
|
}
|
|
|
|
removePendingTest(event) {
|
|
if (this.pendingTests.has(event.testFile)) {
|
|
this.pendingTests.get(event.testFile).delete(event.title);
|
|
}
|
|
}
|
|
|
|
getFailedTestFiles() {
|
|
return [...this.stats.byFile].filter(statByFile => statByFile[1].failedTests).map(statByFile => statByFile[0]);
|
|
}
|
|
}
|