Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Run separate CLI server for test discovery #3201

Draft
wants to merge 2 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
24 changes: 23 additions & 1 deletion extensions/ql-vscode/src/codeql-cli/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -246,6 +246,7 @@ export class CodeQLCliServer implements Disposable {
private distributionProvider: DistributionProvider,
private cliConfig: CliConfig,
public readonly logger: Logger,
private readonly name = "CodeQL Cli Server",
) {
this.commandQueue = [];
this.commandInProcess = false;
Expand All @@ -262,6 +263,27 @@ export class CodeQLCliServer implements Disposable {
}
}

/**
* Creates a clone of this CLI server with the same configuration. This is useful
* for creating a separate CLI server for running some commands in a different
* process to avoid blocking the main CLI server.
*
* To ensure that the CLI server is only used for its intended purpose, the
* generic `AvailableMethods` parameter should be set to the union of the
* methods that the CLI server will be used for.
*/
public createClone<AvailableMethods extends keyof CodeQLCliServer>(
name: string,
): Pick<CodeQLCliServer, AvailableMethods> & Disposable {
return new CodeQLCliServer(
this.app,
this.distributionProvider,
this.cliConfig,
this.logger,
name,
);
}

dispose(): void {
this.killProcessIfRunning();
}
Expand Down Expand Up @@ -340,7 +362,7 @@ export class CodeQLCliServer implements Disposable {

return spawnServer(
codeQlPath,
"CodeQL CLI Server",
this.name,
["execute", "cli-server"],
args,
this.logger,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ export class QLTestDiscovery extends Discovery {

constructor(
private readonly workspaceFolder: WorkspaceFolder,
private readonly cliServer: CodeQLCliServer,
private readonly cliServer: Pick<CodeQLCliServer, "resolveTests">,
) {
super("QL Test Discovery", extLogger);

Expand Down
12 changes: 10 additions & 2 deletions extensions/ql-vscode/src/query-testing/test-manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ class WorkspaceFolderHandler extends DisposableObject {
public constructor(
private readonly workspaceFolder: WorkspaceFolder,
private readonly testUI: TestManager,
cliServer: CodeQLCliServer,
cliServer: Pick<CodeQLCliServer, "resolveTests">,
) {
super();

Expand Down Expand Up @@ -119,10 +119,12 @@ export class TestManager extends TestManagerBase {
WorkspaceFolderHandler
>();

private readonly cliServer: Pick<CodeQLCliServer, "resolveTests">;

public constructor(
app: App,
private readonly testRunner: TestRunner,
private readonly cliServer: CodeQLCliServer,
extensionCliServer: CodeQLCliServer,
// Having this as a parameter with a default value makes passing in a mock easier.
private readonly testController: TestController = tests.createTestController(
"codeql",
Expand All @@ -131,6 +133,12 @@ export class TestManager extends TestManagerBase {
) {
super(app);

// The resolve tests command can be very slow for large workspaces and we don't want to block
// other CLI commands from running, so we'll create a separate CLI server just for this.
this.cliServer = this.push(
extensionCliServer.createClone("CodeQL Test Discovery CLI Server"),
);

this.testController.createRunProfile(
"Run",
TestRunProfileKind.Run,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,10 @@ export function createMockCliServerForTestRun() {
cliServer: mockedObject<CodeQLCliServer>({
runTests: runTestsSpy,
resolveQlpacks: resolveQlpacksSpy,
resolveTests: resolveTestsSpy,
createClone: () =>
mockedObject<CodeQLCliServer>({
resolveTests: resolveTestsSpy,
}),
}),
runTestsSpy,
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,6 @@ describe("test-runner", () => {
const renameDatabaseItemSpy = jest.fn();
const setCurrentDatabaseItemSpy = jest.fn();
let runTestsSpy: jest.Mock<any, any>;
const resolveTestsSpy = jest.fn();
const resolveQlpacksSpy = jest.fn();

const preTestDatabaseItem = new DatabaseItemImpl(
Uri.file("/path/to/test/dir/dir.testproj"),
Expand All @@ -58,8 +56,6 @@ describe("test-runner", () => {
removeDatabaseItemSpy.mockResolvedValue(undefined);
renameDatabaseItemSpy.mockResolvedValue(undefined);
setCurrentDatabaseItemSpy.mockResolvedValue(undefined);
resolveQlpacksSpy.mockResolvedValue({});
resolveTestsSpy.mockResolvedValue([]);
fakeDatabaseManager = mockedObject<DatabaseManager>(
{
openDatabase: openDatabaseSpy,
Expand Down