Skip to content

Commit

Permalink
Merge pull request #56 from matepek/development
Browse files Browse the repository at this point in the history
Development
  • Loading branch information
matepek authored Jan 18, 2019
2 parents b4734fd + 79677b5 commit ebf6fa8
Show file tree
Hide file tree
Showing 16 changed files with 260 additions and 229 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

## [2.3.14]

### Fixed

- a bug related to Google Test framework's test list loading. ([Issue](https://github.com/matepek/vscode-catch2-test-adapter/issues/55))

## [2.3.13] - 2019-01-16

Sorting has been change to alphabetic order.
Expand Down
16 changes: 16 additions & 0 deletions src/AbstractTestInfo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,22 @@ export abstract class AbstractTestInfo implements TestInfo {
return { type: 'test', test: this, state: 'skipped' };
}

getTimeoutEvent(milisec: number): TestEvent {
const ev = this.getFailedEventBase();
ev.message += '⌛️ Timed out: "catch2TestExplorer.defaultRunningTimeoutSec": ' + milisec / 1000 + ' second(s).\n';
return ev;
}

getFailedEventBase(): TestEvent {
return {
type: 'test',
test: this,
state: 'failed',
message: '', //TODO: complicated because of tests: '🧪 Executable: ' + this.execPath + '\n',
decorations: []
};
}

findRouteToTestById(id: string): AbstractTestInfo[] | undefined {
return this.id === id ? [this] : undefined;
}
Expand Down
33 changes: 12 additions & 21 deletions src/AbstractTestSuiteInfo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,12 @@ import { ChildProcess, spawn, SpawnOptions } from 'child_process';
import * as path from 'path';
import * as vscode from 'vscode';

import { AbstractTestInfo } from './AbstractTestInfo';
import * as c2fs from './FsWrapper';
import { AbstractTestInfo } from './AbstractTestInfo';
import { AbstractTestSuiteInfoBase } from './AbstractTestSuiteInfoBase';
import { TaskPool } from './TaskPool';
import { SharedVariables } from './SharedVariables';
import { AbstractTestSuiteInfoBase } from './AbstractTestSuiteInfoBase';
import { RunningTestExecutableInfo } from './RunningTestExecutableInfo';

export abstract class AbstractTestSuiteInfo extends AbstractTestSuiteInfoBase {

Expand All @@ -30,7 +31,7 @@ export abstract class AbstractTestSuiteInfo extends AbstractTestSuiteInfoBase {

protected abstract _getRunParams(childrenToRun: Set<AbstractTestInfo>): string[];

protected abstract _handleProcess(runInfo: AbstractTestSuiteInfoRunInfo): Promise<void>;
protected abstract _handleProcess(runInfo: RunningTestExecutableInfo): Promise<void>;

cancel(): void {
this._shared.log.info('canceled:', this.id, this.label, this._process != undefined);
Expand Down Expand Up @@ -77,7 +78,10 @@ export abstract class AbstractTestSuiteInfo extends AbstractTestSuiteInfoBase {
* @param childrenToRun If it is empty, it means run all.
*/
private _runInner(childrenToRun: Set<AbstractTestInfo>): Promise<void> {
if (this._killed) return Promise.reject(Error('Test was killed.'));
if (this._killed) {
this._shared.log.info('test was canceled:', this);
return Promise.resolve();
}

const execParams = this._getRunParams(childrenToRun);

Expand All @@ -91,17 +95,16 @@ export abstract class AbstractTestSuiteInfo extends AbstractTestSuiteInfoBase {

this._process = spawn(this.execPath, execParams, this.execOptions);

const runInfo: AbstractTestSuiteInfoRunInfo = {
const runInfo: RunningTestExecutableInfo = {
process: this._process,
childrenToRun: childrenToRun,
timeout: undefined,
timeoutWatcherTrigger: () => { },
startTime: Date.now(),
};

this._shared.log.info('proc started');
{
const startTime = Date.now();

const killIfTimeouts = (): Promise<void> => {
return new Promise<vscode.Disposable>(resolve => {
const conn = this._shared.onDidChangeExecRunningTimeout(() => {
Expand All @@ -111,7 +114,7 @@ export abstract class AbstractTestSuiteInfo extends AbstractTestSuiteInfoBase {
runInfo.timeoutWatcherTrigger = () => { resolve(conn); };

if (this._shared.execRunningTimeout !== null) {
const elapsed = Date.now() - startTime;
const elapsed = Date.now() - runInfo.startTime;
const left = this._shared.execRunningTimeout - elapsed;
if (left <= 0) resolve(conn);
else setTimeout(resolve, left, conn);
Expand All @@ -121,7 +124,7 @@ export abstract class AbstractTestSuiteInfo extends AbstractTestSuiteInfoBase {
if (runInfo.process === undefined) {
return Promise.resolve();
} else if (this._shared.execRunningTimeout !== null
&& Date.now() - startTime > this._shared.execRunningTimeout) {
&& Date.now() - runInfo.startTime > this._shared.execRunningTimeout) {
runInfo.process.kill();
runInfo.timeout = this._shared.execRunningTimeout;
return Promise.resolve();
Expand Down Expand Up @@ -172,16 +175,4 @@ export abstract class AbstractTestSuiteInfo extends AbstractTestSuiteInfoBase {
}
return filePath;
}

protected _getTimeoutMessage(milisec: number): string {
return 'Timed out: "catch2TestExplorer.defaultRunningTimeoutSec": '
+ milisec / 1000 + ' second(s).\n';
}
}

export interface AbstractTestSuiteInfoRunInfo {
process: ChildProcess | undefined;
childrenToRun: Set<AbstractTestInfo>;
timeout: number | undefined;
timeoutWatcherTrigger: () => void;
}
4 changes: 2 additions & 2 deletions src/AbstractTestSuiteInfoBase.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ export abstract class AbstractTestSuiteInfoBase implements TestSuiteInfo {
findRouteToTestById(id: string): (AbstractTestSuiteInfoBase | AbstractTestInfo)[] | undefined {
for (let i = 0; i < this.children.length; ++i) {
const res = this.children[i].findRouteToTestById(id);
if (res) return [this, ...res];
if (res !== undefined) return [this, ...res];
}
return undefined;
}
Expand Down Expand Up @@ -101,7 +101,7 @@ export abstract class AbstractTestSuiteInfoBase implements TestSuiteInfo {
findTestInfoInArray(array: (AbstractTestSuiteInfoBase | AbstractTestInfo)[], pred: (v: AbstractTestInfo) => boolean) {
for (let i = 0; i < array.length; i++) {
const res = array[i].findTestInfo(pred);
if (res) return res;
if (res !== undefined) return res;
}
return undefined;
}
Expand Down
73 changes: 30 additions & 43 deletions src/Catch2TestInfo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { SpawnOptions } from 'child_process';
import { AbstractTestInfo } from './AbstractTestInfo';
import { inspect } from 'util';
import { SharedVariables } from './SharedVariables';
import { RunningTestExecutableInfo } from './RunningTestExecutableInfo';

export class Catch2TestInfo extends AbstractTestInfo {
constructor(
Expand Down Expand Up @@ -50,8 +51,12 @@ export class Catch2TestInfo extends AbstractTestInfo {
return debugParams;
}

parseAndProcessTestCase(xmlStr: string, rngSeed: number | undefined):
parseAndProcessTestCase(xmlStr: string, rngSeed: number | undefined, runInfo: RunningTestExecutableInfo):
TestEvent {
if (runInfo.timeout !== undefined) {
return this.getTimeoutEvent(runInfo.timeout);
}

let res: any = undefined;
new xml2js.Parser({ explicitArray: true })
.parseString(xmlStr, (err: any, result: any) => {
Expand All @@ -62,41 +67,23 @@ export class Catch2TestInfo extends AbstractTestInfo {
}
});

return this._processXmlTagTestCase(res.TestCase, rngSeed);
}

private _processXmlTagTestCase(testCase: any, rngSeed: number | undefined):
TestEvent {
try {
const testEvent: TestEvent = {
type: 'test',
test: this,
state: 'failed',
message: '',
decorations: []
};

if (rngSeed) {
testEvent.message += 'Randomness seeded to: ' + rngSeed.toString() + '.\n';
}
const testEvent = this.getFailedEventBase();

this._processXmlTagTestCaseInner(testCase, testEvent);
if (rngSeed) {
testEvent.message += '🔀 Randomness seeded to: ' + rngSeed.toString() + '.\n';
}

if (testEvent.message === '') testEvent.message = '';
if (testEvent.decorations!.length == 0) testEvent.decorations = undefined;
this._processXmlTagTestCaseInner(res.TestCase, testEvent);

return testEvent;
} catch (e) {
throw e;
}
return testEvent;
}

private _processXmlTagTestCaseInner(testCase: any, testEvent: TestEvent):
void {
const title = '>>> "' + testCase.$.name + '" at line ' + testCase.$.line;
const title = '⬇️⬇️⬇️ "' + testCase.$.name + '" at line ' + testCase.$.line;

if (testCase.OverallResult[0].$.hasOwnProperty('durationInSeconds')) {
testEvent.message += 'Duration: ' + testCase.OverallResult[0].$.durationInSeconds + ' second(s).\n';
testEvent.message += 'Duration: ' + testCase.OverallResult[0].$.durationInSeconds + ' second(s).\n';
}

this._processInfoWarningAndFailureTags(testCase, title, testEvent);
Expand All @@ -109,21 +96,21 @@ export class Catch2TestInfo extends AbstractTestInfo {


if (testCase.OverallResult[0].hasOwnProperty('StdOut')) {
testEvent.message += '>>> std::cout:';
testEvent.message += '⬇️⬇️⬇️ std::cout:';
for (let i = 0; i < testCase.OverallResult[0].StdOut.length; i++) {
const element = testCase.OverallResult[0].StdOut[i];
testEvent.message += element.trimRight();
}
testEvent.message += '\n<<< std::cout\n';
testEvent.message += '\n⬆️⬆️⬆️ std::cout\n';
}

if (testCase.OverallResult[0].hasOwnProperty('StdErr')) {
testEvent.message += '>>> std::err:';
testEvent.message += '⬇️⬇️⬇️ std::err:';
for (let i = 0; i < testCase.OverallResult[0].StdErr.length; i++) {
const element = testCase.OverallResult[0].StdErr[i];
testEvent.message += element.trimRight();
}
testEvent.message += '\n<<< std::err\n';
testEvent.message += '\n⬆️⬆️⬆️ std::err\n';
}

if (testCase.OverallResult[0].$.success === 'true') {
Expand All @@ -135,22 +122,22 @@ export class Catch2TestInfo extends AbstractTestInfo {
if (xml.hasOwnProperty('Info')) {
for (let j = 0; j < xml.Info.length; ++j) {
const info = xml.Info[j];
testEvent.message += '>>> Info: ' + info.trim() + ' <<<\n';
testEvent.message += '⬇️⬇️⬇️ Info: ' + info.trim() + ' ⬆️⬆️⬆️\n';
}
}
if (xml.hasOwnProperty('Warning')) {
for (let j = 0; j < xml.Warning.length; ++j) {
const warning = xml.Warning[j];
testEvent.message += '>>> Warning: ' + warning.trim() + ' <<<\n';
testEvent.message += '⬇️⬇️⬇️ Warning: ' + warning.trim() + ' ⬆️⬆️⬆️\n';
}
}
if (xml.hasOwnProperty('Failure')) {
for (let j = 0; j < xml.Failure.length; ++j) {
const failure = xml.Failure[j];
testEvent.message += '>>> Failure: ' + failure._.trim() + ' <<<\n';
testEvent.message += '⬇️⬇️⬇️ Failure: ' + failure._.trim() + ' ⬆️⬆️⬆️\n';
testEvent.decorations!.push({
line: Number(failure.$.line) - 1 /*It looks vscode works like this.*/,
message: '-> ' + failure._.split(EOL)
message: '⬅️ ' + failure._.split(EOL)
.map((l: string) => l.trim())
.filter((l: string) => l.length > 0)
.join('; ')
Expand All @@ -164,18 +151,18 @@ export class Catch2TestInfo extends AbstractTestInfo {
for (let j = 0; j < xml.Expression.length; ++j) {
const expr = xml.Expression[j];
try {
testEvent.message += title + ' -> '
testEvent.message += title + ' ➡️ '
+ (expr.$.type ? expr.$.type : '<unknown>')
+ ' at line ' + expr.$.line + ':\n'
+ ' Original:\n '
+ expr.Original.map((x: string) => x.trim()).join('; ') + '\n'
+ ' Expanded:\n '
+ expr.Expanded.map((x: string) => x.trim()).join('; ') + '\n'
+ '<<<\n\n';
+ '⬆️⬆️⬆️\n\n';
testEvent.decorations!.push({
line: Number(expr.$.line) - 1 /*It looks vscode works like this.*/,
message:
'-> ' + expr.Expanded.map((x: string) => x.trim()).join('; ')
'⬅️ ' + expr.Expanded.map((x: string) => x.trim()).join('; ')
});
} catch (error) {
this._shared.log.error(error);
Expand All @@ -191,7 +178,7 @@ export class Catch2TestInfo extends AbstractTestInfo {
for (let j = 0; j < xml.Section.length; ++j) {
const section = xml.Section[j];
try {
title += ' -> "' + section.$.name + '" at line ' + section.$.line;
title += ' ➡️ "' + section.$.name + '" at line ' + section.$.line;

this._processInfoWarningAndFailureTags(xml, title, testEvent);

Expand All @@ -212,13 +199,13 @@ export class Catch2TestInfo extends AbstractTestInfo {
for (let j = 0; j < expr.FatalErrorCondition.length; ++j) {
const fatal = expr.FatalErrorCondition[j];

testEvent.message += title + ' -> at line ' + expr.$.line + ':\n';
testEvent.message += title + ' ➡️ Fatal Error at line ' + expr.$.line + ':\n';
if (fatal.hasOwnProperty('_')) {
testEvent.message += ' Fatal error: ' + fatal._.trim() + '\n';
testEvent.message += ' Error: ' + fatal._.trim() + '\n';
} else {
testEvent.message += ' Unknown fatal error: ' + inspect(fatal) + '\n';
testEvent.message += ' Error: unknown: ' + inspect(fatal) + '\n';
}
testEvent.message += '<<<\n\n';
testEvent.message += '⬆️⬆️⬆️\n\n';
}
}
catch (error) {
Expand Down
27 changes: 11 additions & 16 deletions src/Catch2TestSuiteInfo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,10 @@ import * as xml2js from 'xml2js';

import { Catch2TestInfo } from './Catch2TestInfo';
import * as c2fs from './FsWrapper';
import { AbstractTestSuiteInfo, AbstractTestSuiteInfoRunInfo } from './AbstractTestSuiteInfo';
import { AbstractTestSuiteInfo } from './AbstractTestSuiteInfo';
import { SharedVariables } from './SharedVariables';
import { TestSuiteInfoFactory } from './TestSuiteInfoFactory';
import { RunningTestExecutableInfo } from './RunningTestExecutableInfo';

export class Catch2TestSuiteInfo extends AbstractTestSuiteInfo {
children: Catch2TestInfo[] = [];
Expand Down Expand Up @@ -142,7 +143,7 @@ export class Catch2TestSuiteInfo extends AbstractTestSuiteInfo {
return execParams;
}

protected _handleProcess(runInfo: AbstractTestSuiteInfoRunInfo): Promise<void> {
protected _handleProcess(runInfo: RunningTestExecutableInfo): Promise<void> {
const data = new class {
buffer: string = '';
inTestCase: boolean = false;
Expand Down Expand Up @@ -196,8 +197,7 @@ export class Catch2TestSuiteInfo extends AbstractTestSuiteInfo {

if (data.currentChild !== undefined) {
this._shared.log.info('Test', data.currentChild.testNameFull, 'has started.');
const ev = data.currentChild.getStartEvent();
this._shared.testStatesEmitter.fire(ev);
this._shared.testStatesEmitter.fire(data.currentChild.getStartEvent());
} else {
this._shared.log.error('TestCase not found in children: ' + name);
}
Expand All @@ -214,11 +214,9 @@ export class Catch2TestSuiteInfo extends AbstractTestSuiteInfo {
this._shared.log.info('Test ', data.currentChild.testNameFull, 'has finished.');
try {
const ev: TestEvent = data.currentChild.parseAndProcessTestCase(
testCaseXml, data.rngSeed);
testCaseXml, data.rngSeed, runInfo);
if (!this._shared.isEnabledSourceDecoration)
ev.decorations = undefined;
if (runInfo.timeout)
ev.message = this._getTimeoutMessage(runInfo.timeout);
ev.decorations = [];
this._shared.testStatesEmitter.fire(ev);
data.processedTestCases.push(data.currentChild);
} catch (e) {
Expand Down Expand Up @@ -269,15 +267,12 @@ export class Catch2TestSuiteInfo extends AbstractTestSuiteInfo {
if (data.inTestCase) {
if (data.currentChild !== undefined) {
this._shared.log.warn('data.currentChild !== undefined: ', data);
const ev: TestEvent = {
type: 'test',
test: data.currentChild!,
state: 'failed',
};
let ev: TestEvent;
if (runInfo.timeout !== undefined) {
ev.message = this._getTimeoutMessage(runInfo.timeout);
ev = data.currentChild.getTimeoutEvent(runInfo.timeout);
} else {
ev.message = 'Fatal error: (Wrong Catch2 xml output.)\nError: ' + inspect(codeOrReason) + '\n';
ev = data.currentChild.getFailedEventBase();
ev.message = '😱 Fatal error: (Wrong Catch2 xml output.)\nError: ' + inspect(codeOrReason) + '\n';
}
this._shared.testStatesEmitter.fire(ev);
} else {
Expand Down Expand Up @@ -325,7 +320,7 @@ export class Catch2TestSuiteInfo extends AbstractTestSuiteInfo {
if (currentChild === undefined) break;

try {
const ev = currentChild.parseAndProcessTestCase(testCaseXml, data.rngSeed);
const ev = currentChild.parseAndProcessTestCase(testCaseXml, data.rngSeed, runInfo);
events.push(ev);
} catch (e) {
this._shared.log.error('parsing and processing test: ' + testCaseXml);
Expand Down
Loading

0 comments on commit ebf6fa8

Please sign in to comment.