Skip to content

Commit

Permalink
executableSuffixToInclude
Browse files Browse the repository at this point in the history
  • Loading branch information
matepek committed Feb 7, 2024
1 parent d71789a commit 089ce6f
Show file tree
Hide file tree
Showing 8 changed files with 123 additions and 85 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,12 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).

## [Unreleased]

## [4.8.3]

### Added

- `testMate.test.advancedExecutables` - `executableSuffixToInclude` for [custom filtering](https://github.com/matepek/vscode-catch2-test-adapter/issues/415).

## [4.8.2] - 2024-02-07

### Fixed
Expand Down
43 changes: 22 additions & 21 deletions documents/configuration/test.advancedExecutables.md

Large diffs are not rendered by default.

9 changes: 8 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -345,10 +345,17 @@
"default": false
},
"executableCloning": {
"markdownDescription": "(experimental) If enabled it creates a copy of the test executable before listing or running the tests. NOTE: discovery (`--help`) still uses the original file.",
"markdownDescription": "If enabled it creates a copy of the test executable before listing or running the tests. NOTE: discovery (`--help`) still uses the original file.",
"type": "boolean",
"default": false
},
"executableSuffixToInclude": {
"markdownDescription": "Filter files based on suffix for faster discovery.",
"type": "array",
"items": {
"type": "string"
}
},
"waitForBuildProcess": {
"markdownDescription": "Prevents the extension of auto-reloading. With this linking failure might can be avoided. Can be true to use a default pattern that works for most cases, or a string to pass your own search pattern (regex) for processes.",
"type": [
Expand Down
1 change: 1 addition & 0 deletions src/AdvancedExecutableInterface.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ export type AdvancedExecutableConfig = {
strictPattern?: boolean;
markAsSkipped?: boolean;
executableCloning?: boolean;
executableSuffixToInclude?: string[];
waitForBuildProcess?: boolean | string;
catch2?: FrameworkSpecificConfig;
gtest?: FrameworkSpecificConfig;
Expand Down
70 changes: 60 additions & 10 deletions src/ConfigOfExecGroup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,12 +41,56 @@ export class ConfigOfExecGroup implements vscode.Disposable {
private readonly _strictPattern: boolean | undefined,
private readonly _markAsSkipped: boolean | undefined,
private readonly _executableCloning: boolean | undefined,
executableSuffixToInclude: string[] | undefined,
private readonly _waitForBuildProcess: boolean | string | undefined,
private readonly _executionWrapper: ExecutionWrapperConfig | undefined,
private readonly _sourceFileMap: Record<string, string>,
private readonly _frameworkSpecific: Record<FrameworkType, FrameworkSpecificConfig>,
) {}
) {
this._executableSuffixToInclude =
process.platform === 'win32' ? new Set(executableSuffixToInclude ?? ['.exe', '.cmd', '.bat']) : undefined;
// https://askubuntu.com/questions/156392/what-is-the-equivalent-of-an-exe-file
this._executableSuffixToExclude =
process.platform !== 'win32'
? new Set([
'.a',
'.bat',
'.c',
'.cc',
'.cmake',
'.cpp',
'.cxx',
'.deb',
'.dir',
'.gz',
'.h',
'.hpp',
'.hxx',
'.in',
'.input',
'.ko',
'.log',
'.md',
'.mm',
'.ninja',
'.o',
'.obj',
'.pc',
'.php',
'.pyc',
'.rpm',
'.so',
'.stamp',
'.tar',
'.txt',
'.vcxproj.user',
'.xml',
])
: undefined;
}

private readonly _executableSuffixToInclude: Set<string> | undefined;
private readonly _executableSuffixToExclude: Set<string> | undefined;
private _disposables: vscode.Disposable[] = [];

dispose(): void {
Expand Down Expand Up @@ -132,7 +176,7 @@ export class ConfigOfExecGroup implements vscode.Disposable {
suiteCreationAndLoadingTasks.push(
(async (): Promise<void> => {
try {
await c2fs.isNativeExecutableAsync(file);
await c2fs.isNativeExecutableAsync(file, this._executableSuffixToInclude, this._executableSuffixToExclude);
try {
const factory = await this._createSuiteByUri(file);
const suite = await factory.create(false);
Expand Down Expand Up @@ -373,6 +417,8 @@ export class ConfigOfExecGroup implements vscode.Disposable {
this._parallelizationLimit,
this._markAsSkipped === true,
this._executableCloning === true,
this._executableSuffixToInclude,
this._executableSuffixToExclude,
this._runTask,
spawner,
resolvedSourceFileMap,
Expand Down Expand Up @@ -434,10 +480,12 @@ export class ConfigOfExecGroup implements vscode.Disposable {
return;
}

const isExec = await c2fs.isNativeExecutableAsync(filePath).then(
() => true,
() => false,
);
const isExec = await c2fs
.isNativeExecutableAsync(filePath, this._executableSuffixToInclude, this._executableSuffixToExclude)
.then(
() => true,
() => false,
);

if (isExec) {
try {
Expand Down Expand Up @@ -511,10 +559,12 @@ export class ConfigOfExecGroup implements vscode.Disposable {
} else {
await promisify(setTimeout)(delay);

const isExec = await c2fs.isNativeExecutableAsync(filePath).then(
() => true,
() => false,
);
const isExec = await c2fs
.isNativeExecutableAsync(filePath, this._executableSuffixToInclude, this._executableSuffixToExclude)
.then(
() => true,
() => false,
);

return this._recursiveHandleRunnable(executable, isExec, Math.min(delay * 2, 2000));
}
Expand Down
4 changes: 4 additions & 0 deletions src/Configurations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -464,6 +464,7 @@ export class Configurations {
undefined,
undefined,
undefined,
undefined,
{},
{
catch2: {},
Expand Down Expand Up @@ -569,6 +570,8 @@ export class Configurations {

const executableCloning: boolean | undefined = obj.executableCloning;

const executableSuffixToInclude: string[] | undefined = obj.executableSuffixToInclude;

const waitForBuildProcess: boolean | string | undefined = obj.waitForBuildProcess;

const defaultTestGrouping = obj.testGrouping;
Expand Down Expand Up @@ -601,6 +604,7 @@ export class Configurations {
strictPattern,
markAsSkipped,
executableCloning,
executableSuffixToInclude,
waitForBuildProcess,
spawnerConfig,
sourceFileMap,
Expand Down
9 changes: 8 additions & 1 deletion src/framework/ExecutableFactory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ export class ExecutableFactory {
private readonly _parallelizationLimit: number,
private readonly _markAsSkipped: boolean,
private readonly _executableCloning: boolean,
private readonly _executableSuffixToInclude: Set<string> | undefined,
private readonly _executableSuffixToExclude: Set<string> | undefined,
private readonly _runTask: RunTaskConfig,
private readonly _spawner: Spawner,
private readonly _resolvedSourceFileMap: Record<string, string>,
Expand All @@ -31,7 +33,12 @@ export class ExecutableFactory {

async create(checkIsNativeExecutable: boolean): Promise<AbstractExecutable | undefined> {
const runWithHelpRes = await this._shared.taskPool.scheduleTask(async () => {
if (checkIsNativeExecutable) await c2fs.isNativeExecutableAsync(this._execPath);
if (checkIsNativeExecutable)
await c2fs.isNativeExecutableAsync(
this._execPath,
this._executableSuffixToInclude,
this._executableSuffixToExclude,
);

return this._spawner.spawnAsync(this._execPath, ['--help'], this._execOptions, this._shared.execParsingTimeout);
});
Expand Down
66 changes: 14 additions & 52 deletions src/util/FSWrapper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,60 +42,22 @@ function accessAsync(filePath: string, flag: number): Promise<void> {
});
}

// https://askubuntu.com/questions/156392/what-is-the-equivalent-of-an-exe-file
const nativeExecutableExtensionFilter = new Set([
'.a',
'.bat',
'.c',
'.cc',
'.cmake',
'.cpp',
'.cxx',
'.deb',
'.dir',
'.gz',
'.h',
'.hpp',
'.hxx',
'.in',
'.input',
'.ko',
'.log',
'.md',
'.mm',
'.ninja',
'.o',
'.obj',
'.pc',
'.php',
'.pyc',
'.rpm',
'.so',
'.stamp',
'.tar',
'.txt',
'.vcxproj.user',
'.xml',
]);

const win32NativeExecutableExtensionFilter = new Set(['.exe', '.cmd', '.bat']);

export function isNativeExecutableAsync(filePath: string): Promise<void> {
export function isNativeExecutableAsync(
filePath: string,
extensionIncludeFilter: Set<string> | undefined,
extensionExcludeFilter: Set<string> | undefined,
): Promise<void> {
const ext = path.extname(filePath);
if (process.platform === 'win32') {
if (win32NativeExecutableExtensionFilter.has(ext)) return accessAsync(filePath, ExecutableFlag);
else return Promise.reject(new Error('Not a native executable extension on win32: ' + filePath));
} else {
if (filePath.endsWith('/')) {
// noted that we got ".../CMakeFiles/" a lot. I assume the slash means directory.
return Promise.reject(new Error('It is a directory, not a native executable: ' + filePath));
}
if (nativeExecutableExtensionFilter.has(ext)) {
return Promise.reject(new Error('Not a native executable (filtered because of its extension): ' + filePath));
} else {
return accessAsync(filePath, ExecutableFlag);
}
if (extensionIncludeFilter) {
if (!extensionIncludeFilter.has(ext)) return Promise.reject(new Error('Not included by filter: ' + filePath));
} else if (extensionExcludeFilter) {
if (extensionExcludeFilter.has(ext)) return Promise.reject(new Error('Excluded by fitler: ' + filePath));
}
if (process.platform !== 'win32' && filePath.endsWith('/')) {
// noted that we got ".../CMakeFiles/" a lot. I assume the slash means directory.
return Promise.reject(new Error('It is a directory, not a native executable: ' + filePath));
}
return accessAsync(filePath, ExecutableFlag);
}

export function existsSync(filePath: string): boolean {
Expand Down

0 comments on commit 089ce6f

Please sign in to comment.