2018-08-04 15:13:01 +00:00
|
|
|
import { ChildProcess } from 'child_process';
|
2023-07-13 01:19:11 +00:00
|
|
|
import { coloredString as cs } from '@push.rocks/consolecolor';
|
2018-08-03 17:18:42 +00:00
|
|
|
|
|
|
|
// ============
|
|
|
|
// combines different tap test files to an overall result
|
|
|
|
// ============
|
2022-03-12 23:30:32 +00:00
|
|
|
import * as plugins from './tstest.plugins.js';
|
|
|
|
import { TapTestResult } from './tstest.classes.tap.testresult.js';
|
|
|
|
import * as logPrefixes from './tstest.logprefixes.js';
|
2018-08-03 17:18:42 +00:00
|
|
|
|
|
|
|
export class TapParser {
|
2018-08-05 20:58:52 +00:00
|
|
|
testStore: TapTestResult[] = [];
|
2018-08-04 12:23:07 +00:00
|
|
|
|
2018-08-13 21:58:50 +00:00
|
|
|
expectedTestsRegex = /([0-9]*)\.\.([0-9]*)$/;
|
2018-08-03 17:18:42 +00:00
|
|
|
expectedTests: number;
|
2018-08-05 20:58:52 +00:00
|
|
|
receivedTests: number;
|
2018-08-03 17:18:42 +00:00
|
|
|
|
2018-08-04 17:23:17 +00:00
|
|
|
testStatusRegex = /(ok|not\sok)\s([0-9]+)\s-\s(.*)\s#\stime=(.*)ms$/;
|
2018-08-04 12:23:07 +00:00
|
|
|
activeTapTestResult: TapTestResult;
|
|
|
|
|
2023-11-09 20:06:06 +00:00
|
|
|
pretaskRegex = /^::__PRETASK:(.*)$/;
|
|
|
|
|
2018-08-05 20:58:52 +00:00
|
|
|
/**
|
|
|
|
* the constructor for TapParser
|
|
|
|
*/
|
|
|
|
constructor(public fileName: string) {}
|
|
|
|
|
2018-08-04 15:13:01 +00:00
|
|
|
private _getNewTapTestResult() {
|
2018-08-05 20:58:52 +00:00
|
|
|
this.activeTapTestResult = new TapTestResult(this.testStore.length + 1);
|
2018-08-04 12:23:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
private _processLog(logChunk: Buffer | string) {
|
|
|
|
if (Buffer.isBuffer(logChunk)) {
|
2018-08-03 17:18:42 +00:00
|
|
|
logChunk = logChunk.toString();
|
|
|
|
}
|
2018-08-04 15:13:01 +00:00
|
|
|
const logLineArray = logChunk.split('\n');
|
|
|
|
if (logLineArray[logLineArray.length - 1] === '') {
|
2018-08-04 12:23:07 +00:00
|
|
|
logLineArray.pop();
|
|
|
|
}
|
|
|
|
|
|
|
|
// lets parse the log information
|
|
|
|
for (const logLine of logLineArray) {
|
|
|
|
let logLineIsTapProtocol = false;
|
|
|
|
if (!this.expectedTests && this.expectedTestsRegex.test(logLine)) {
|
|
|
|
logLineIsTapProtocol = true;
|
|
|
|
const regexResult = this.expectedTestsRegex.exec(logLine);
|
|
|
|
this.expectedTests = parseInt(regexResult[2]);
|
2018-08-05 20:58:52 +00:00
|
|
|
console.log(
|
2018-12-06 00:03:48 +00:00
|
|
|
`${logPrefixes.TapPrefix} ${cs(`Expecting ${this.expectedTests} tests!`, 'blue')}`
|
2018-08-05 20:58:52 +00:00
|
|
|
);
|
2018-08-04 12:23:07 +00:00
|
|
|
|
|
|
|
// initiating first TapResult
|
|
|
|
this._getNewTapTestResult();
|
2023-11-09 20:06:06 +00:00
|
|
|
} else if (this.pretaskRegex.test(logLine)) {
|
|
|
|
logLineIsTapProtocol = true;
|
|
|
|
const pretaskContentMatch = this.pretaskRegex.exec(logLine);
|
|
|
|
if (pretaskContentMatch && pretaskContentMatch[1]) {
|
|
|
|
console.log(`${logPrefixes.TapPretaskPrefix} Pretask ->${pretaskContentMatch[1]}: Success.`);
|
|
|
|
}
|
2018-08-04 12:23:07 +00:00
|
|
|
} else if (this.testStatusRegex.test(logLine)) {
|
|
|
|
logLineIsTapProtocol = true;
|
|
|
|
const regexResult = this.testStatusRegex.exec(logLine);
|
|
|
|
const testId = parseInt(regexResult[2]);
|
|
|
|
const testOk = (() => {
|
2018-08-04 15:13:01 +00:00
|
|
|
if (regexResult[1] === 'ok') {
|
2018-08-04 12:23:07 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
})();
|
|
|
|
|
2018-08-04 17:23:17 +00:00
|
|
|
const testSubject = regexResult[3];
|
|
|
|
const testDuration = parseInt(regexResult[4]);
|
|
|
|
|
2018-08-04 12:23:07 +00:00
|
|
|
// test for protocol error
|
2018-08-04 15:13:01 +00:00
|
|
|
if (testId !== this.activeTapTestResult.id) {
|
2018-08-05 20:58:52 +00:00
|
|
|
console.log(
|
2018-12-06 00:03:48 +00:00
|
|
|
`${logPrefixes.TapErrorPrefix} Something is strange! Test Ids are not equal!`
|
2018-08-05 20:58:52 +00:00
|
|
|
);
|
2018-08-04 12:23:07 +00:00
|
|
|
}
|
|
|
|
this.activeTapTestResult.setTestResult(testOk);
|
|
|
|
|
2018-08-04 15:13:01 +00:00
|
|
|
if (testOk) {
|
2018-08-04 17:23:17 +00:00
|
|
|
console.log(
|
|
|
|
logPrefixes.TapPrefix,
|
2018-08-13 21:58:50 +00:00
|
|
|
`${cs(`T${testId} ${plugins.figures.tick}`, 'green')} ${plugins.figures.arrowRight} ` +
|
2018-08-05 20:58:52 +00:00
|
|
|
cs(testSubject, 'blue') +
|
|
|
|
` | ${cs(`${testDuration} ms`, 'orange')}`
|
2018-08-04 17:23:17 +00:00
|
|
|
);
|
2018-08-04 12:23:07 +00:00
|
|
|
} else {
|
2018-08-04 17:23:17 +00:00
|
|
|
console.log(
|
|
|
|
logPrefixes.TapPrefix,
|
2018-08-13 21:58:50 +00:00
|
|
|
`${cs(`T${testId} ${plugins.figures.cross}`, 'red')} ${plugins.figures.arrowRight} ` +
|
2018-08-05 20:58:52 +00:00
|
|
|
cs(testSubject, 'blue') +
|
|
|
|
` | ${cs(`${testDuration} ms`, 'orange')}`
|
2018-08-04 17:23:17 +00:00
|
|
|
);
|
2018-08-04 12:23:07 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!logLineIsTapProtocol) {
|
|
|
|
if (this.activeTapTestResult) {
|
|
|
|
this.activeTapTestResult.addLogLine(logLine);
|
|
|
|
}
|
|
|
|
console.log(logLine);
|
|
|
|
}
|
|
|
|
|
2018-08-04 15:13:01 +00:00
|
|
|
if (this.activeTapTestResult && this.activeTapTestResult.testSettled) {
|
2018-08-05 20:58:52 +00:00
|
|
|
this.testStore.push(this.activeTapTestResult);
|
2018-08-04 12:23:07 +00:00
|
|
|
this._getNewTapTestResult();
|
|
|
|
}
|
|
|
|
}
|
2018-08-03 17:18:42 +00:00
|
|
|
}
|
|
|
|
|
2018-08-05 20:58:52 +00:00
|
|
|
/**
|
|
|
|
* returns all tests that are not completed
|
|
|
|
*/
|
2020-07-07 20:50:29 +00:00
|
|
|
public getUncompletedTests() {
|
2018-08-05 20:58:52 +00:00
|
|
|
// TODO:
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* returns all tests that threw an error
|
|
|
|
*/
|
2020-07-07 20:50:29 +00:00
|
|
|
public getErrorTests() {
|
2020-07-07 23:09:17 +00:00
|
|
|
return this.testStore.filter((tapTestArg) => {
|
2018-08-05 20:58:52 +00:00
|
|
|
return !tapTestArg.testOk;
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2018-08-13 21:58:50 +00:00
|
|
|
/**
|
|
|
|
* returns a test overview as string
|
|
|
|
*/
|
|
|
|
getTestOverviewAsString() {
|
2018-12-06 00:03:48 +00:00
|
|
|
let overviewString = '';
|
2020-07-07 20:50:29 +00:00
|
|
|
for (const test of this.testStore) {
|
2018-12-06 00:03:48 +00:00
|
|
|
if (overviewString !== '') {
|
2018-08-13 21:58:50 +00:00
|
|
|
overviewString += ' | ';
|
|
|
|
}
|
|
|
|
if (test.testOk) {
|
|
|
|
overviewString += cs(`T${test.id} ${plugins.figures.tick}`, 'green');
|
|
|
|
} else {
|
|
|
|
overviewString += cs(`T${test.id} ${plugins.figures.cross}`, 'red');
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return overviewString;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* handles a tap process
|
|
|
|
* @param childProcessArg
|
|
|
|
*/
|
2020-07-07 23:09:17 +00:00
|
|
|
public async handleTapProcess(childProcessArg: ChildProcess) {
|
2018-08-03 17:18:42 +00:00
|
|
|
const done = plugins.smartpromise.defer();
|
2020-07-07 23:09:17 +00:00
|
|
|
childProcessArg.stdout.on('data', (data) => {
|
2018-08-04 12:23:07 +00:00
|
|
|
this._processLog(data);
|
|
|
|
});
|
2020-07-07 23:09:17 +00:00
|
|
|
childProcessArg.stderr.on('data', (data) => {
|
2018-08-04 12:23:07 +00:00
|
|
|
this._processLog(data);
|
|
|
|
});
|
2020-07-07 23:09:17 +00:00
|
|
|
childProcessArg.on('exit', async () => {
|
2023-11-09 20:06:06 +00:00
|
|
|
await this.evaluateFinalResult();
|
2018-08-04 12:23:07 +00:00
|
|
|
done.resolve();
|
|
|
|
});
|
2018-08-03 17:18:42 +00:00
|
|
|
await done.promise;
|
|
|
|
}
|
2020-07-07 20:50:29 +00:00
|
|
|
|
2020-07-07 23:09:17 +00:00
|
|
|
public async handleTapLog(tapLog: string) {
|
2020-07-07 20:50:29 +00:00
|
|
|
this._processLog(tapLog);
|
2020-07-07 23:09:17 +00:00
|
|
|
}
|
|
|
|
|
2023-11-09 20:06:06 +00:00
|
|
|
public async evaluateFinalResult() {
|
2020-07-07 23:09:17 +00:00
|
|
|
this.receivedTests = this.testStore.length;
|
|
|
|
|
|
|
|
// check wether all tests ran
|
|
|
|
if (this.expectedTests === this.receivedTests) {
|
|
|
|
console.log(
|
|
|
|
`${logPrefixes.TapPrefix} ${cs(
|
|
|
|
`${this.receivedTests} out of ${this.expectedTests} Tests completed!`,
|
|
|
|
'green'
|
|
|
|
)}`
|
|
|
|
);
|
|
|
|
} else {
|
|
|
|
console.log(
|
|
|
|
`${logPrefixes.TapErrorPrefix} ${cs(
|
|
|
|
`Only ${this.receivedTests} out of ${this.expectedTests} completed!`,
|
|
|
|
'red'
|
|
|
|
)}`
|
|
|
|
);
|
|
|
|
}
|
2020-07-11 15:52:31 +00:00
|
|
|
if (!this.expectedTests) {
|
|
|
|
console.log(cs('Error: No tests were defined. Therefore the testfile failed!', 'red'));
|
|
|
|
} else if (this.expectedTests !== this.receivedTests) {
|
2020-07-12 00:47:41 +00:00
|
|
|
console.log(
|
|
|
|
cs(
|
|
|
|
'Error: The amount of received tests and expectedTests is unequal! Therefore the testfile failed',
|
|
|
|
'red'
|
|
|
|
)
|
|
|
|
);
|
2020-07-11 15:52:31 +00:00
|
|
|
} else if (this.getErrorTests().length === 0) {
|
2020-07-07 23:09:17 +00:00
|
|
|
console.log(`${logPrefixes.TapPrefix} ${cs(`All tests are successfull!!!`, 'green')}`);
|
|
|
|
} else {
|
|
|
|
console.log(
|
|
|
|
`${logPrefixes.TapPrefix} ${cs(
|
|
|
|
`${this.getErrorTests().length} tests threw an error!!!`,
|
|
|
|
'red'
|
|
|
|
)}`
|
|
|
|
);
|
|
|
|
}
|
2020-07-07 20:50:29 +00:00
|
|
|
}
|
2018-08-03 17:18:42 +00:00
|
|
|
}
|