mirror of
https://github.com/QwenLM/qwen-code.git
synced 2025-12-19 09:33:53 +00:00
Co-authored-by: Taylor Mullen <ntaylormullen@google.com> Co-authored-by: Arya Gummadi <aryagummadi@google.com>
This commit is contained in:
@@ -83,7 +83,7 @@ vi.mock('@google/gemini-cli-core', async () => {
|
||||
return {
|
||||
...actualServer,
|
||||
IdeClient: {
|
||||
getInstance: vi.fn().mockReturnValue({
|
||||
getInstance: vi.fn().mockResolvedValue({
|
||||
getConnectionStatus: vi.fn(),
|
||||
initialize: vi.fn(),
|
||||
shutdown: vi.fn(),
|
||||
|
||||
@@ -100,6 +100,16 @@ vi.mock('../services/gitService.js', () => {
|
||||
return { GitService: GitServiceMock };
|
||||
});
|
||||
|
||||
vi.mock('../ide/ide-client.js', () => ({
|
||||
IdeClient: {
|
||||
getInstance: vi.fn().mockResolvedValue({
|
||||
getConnectionStatus: vi.fn(),
|
||||
initialize: vi.fn(),
|
||||
shutdown: vi.fn(),
|
||||
}),
|
||||
},
|
||||
}));
|
||||
|
||||
describe('Server Config (config.ts)', () => {
|
||||
const MODEL = 'gemini-pro';
|
||||
const SANDBOX: SandboxConfig = {
|
||||
|
||||
@@ -66,13 +66,34 @@ describe('getIdeProcessInfo', () => {
|
||||
it('should traverse up and find the great-grandchild of the root process', async () => {
|
||||
(os.platform as Mock).mockReturnValue('win32');
|
||||
const processInfoMap = new Map([
|
||||
[1000, { stdout: 'ParentProcessId=900\r\nCommandLine=node.exe\r\n' }],
|
||||
[
|
||||
1000,
|
||||
{
|
||||
stdout:
|
||||
'{"Name":"node.exe","ParentProcessId":900,"CommandLine":"node.exe"}',
|
||||
},
|
||||
],
|
||||
[
|
||||
900,
|
||||
{ stdout: 'ParentProcessId=800\r\nCommandLine=powershell.exe\r\n' },
|
||||
{
|
||||
stdout:
|
||||
'{"Name":"powershell.exe","ParentProcessId":800,"CommandLine":"powershell.exe"}',
|
||||
},
|
||||
],
|
||||
[
|
||||
800,
|
||||
{
|
||||
stdout:
|
||||
'{"Name":"code.exe","ParentProcessId":700,"CommandLine":"code.exe"}',
|
||||
},
|
||||
],
|
||||
[
|
||||
700,
|
||||
{
|
||||
stdout:
|
||||
'{"Name":"wininit.exe","ParentProcessId":0,"CommandLine":"wininit.exe"}',
|
||||
},
|
||||
],
|
||||
[800, { stdout: 'ParentProcessId=700\r\nCommandLine=code.exe\r\n' }],
|
||||
[700, { stdout: 'ParentProcessId=0\r\nCommandLine=wininit.exe\r\n' }],
|
||||
]);
|
||||
mockedExec.mockImplementation((command: string) => {
|
||||
const pidMatch = command.match(/ProcessId=(\d+)/);
|
||||
@@ -86,5 +107,90 @@ describe('getIdeProcessInfo', () => {
|
||||
const result = await getIdeProcessInfo();
|
||||
expect(result).toEqual({ pid: 900, command: 'powershell.exe' });
|
||||
});
|
||||
|
||||
it('should handle non-existent process gracefully', async () => {
|
||||
(os.platform as Mock).mockReturnValue('win32');
|
||||
mockedExec
|
||||
.mockResolvedValueOnce({ stdout: '' }) // Non-existent PID returns empty due to -ErrorAction SilentlyContinue
|
||||
.mockResolvedValueOnce({
|
||||
stdout:
|
||||
'{"Name":"fallback.exe","ParentProcessId":0,"CommandLine":"fallback.exe"}',
|
||||
}); // Fallback call
|
||||
|
||||
const result = await getIdeProcessInfo();
|
||||
expect(result).toEqual({ pid: 1000, command: 'fallback.exe' });
|
||||
});
|
||||
|
||||
it('should handle malformed JSON output gracefully', async () => {
|
||||
(os.platform as Mock).mockReturnValue('win32');
|
||||
mockedExec
|
||||
.mockResolvedValueOnce({ stdout: '{"invalid":json}' }) // Malformed JSON
|
||||
.mockResolvedValueOnce({
|
||||
stdout:
|
||||
'{"Name":"fallback.exe","ParentProcessId":0,"CommandLine":"fallback.exe"}',
|
||||
}); // Fallback call
|
||||
|
||||
const result = await getIdeProcessInfo();
|
||||
expect(result).toEqual({ pid: 1000, command: 'fallback.exe' });
|
||||
});
|
||||
|
||||
it('should handle PowerShell errors without crashing the process chain', async () => {
|
||||
(os.platform as Mock).mockReturnValue('win32');
|
||||
const processInfoMap = new Map([
|
||||
[1000, { stdout: '' }], // First process doesn't exist (empty due to -ErrorAction)
|
||||
[
|
||||
1001,
|
||||
{
|
||||
stdout:
|
||||
'{"Name":"parent.exe","ParentProcessId":800,"CommandLine":"parent.exe"}',
|
||||
},
|
||||
],
|
||||
[
|
||||
800,
|
||||
{
|
||||
stdout:
|
||||
'{"Name":"ide.exe","ParentProcessId":0,"CommandLine":"ide.exe"}',
|
||||
},
|
||||
],
|
||||
]);
|
||||
|
||||
// Mock the process.pid to test traversal with missing processes
|
||||
Object.defineProperty(process, 'pid', {
|
||||
value: 1001,
|
||||
configurable: true,
|
||||
});
|
||||
|
||||
mockedExec.mockImplementation((command: string) => {
|
||||
const pidMatch = command.match(/ProcessId=(\d+)/);
|
||||
if (pidMatch) {
|
||||
const pid = parseInt(pidMatch[1], 10);
|
||||
return Promise.resolve(processInfoMap.get(pid) || { stdout: '' });
|
||||
}
|
||||
return Promise.reject(new Error('Invalid command for mock'));
|
||||
});
|
||||
|
||||
const result = await getIdeProcessInfo();
|
||||
// Should return the current process command since traversal continues despite missing processes
|
||||
expect(result).toEqual({ pid: 1001, command: 'parent.exe' });
|
||||
|
||||
// Reset process.pid
|
||||
Object.defineProperty(process, 'pid', {
|
||||
value: 1000,
|
||||
configurable: true,
|
||||
});
|
||||
});
|
||||
|
||||
it('should handle partial JSON data with defaults', async () => {
|
||||
(os.platform as Mock).mockReturnValue('win32');
|
||||
mockedExec
|
||||
.mockResolvedValueOnce({ stdout: '{"Name":"partial.exe"}' }) // Missing ParentProcessId, defaults to 0
|
||||
.mockResolvedValueOnce({
|
||||
stdout:
|
||||
'{"Name":"root.exe","ParentProcessId":0,"CommandLine":"root.exe"}',
|
||||
}); // Get grandparent info
|
||||
|
||||
const result = await getIdeProcessInfo();
|
||||
expect(result).toEqual({ pid: 1000, command: 'root.exe' });
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -26,15 +26,24 @@ async function getProcessInfo(pid: number): Promise<{
|
||||
}> {
|
||||
const platform = os.platform();
|
||||
if (platform === 'win32') {
|
||||
const command = `wmic process where "ProcessId=${pid}" get Name,ParentProcessId,CommandLine /value`;
|
||||
const { stdout } = await execAsync(command);
|
||||
const nameMatch = stdout.match(/Name=([^\n]*)/);
|
||||
const processName = nameMatch ? nameMatch[1].trim() : '';
|
||||
const ppidMatch = stdout.match(/ParentProcessId=(\d+)/);
|
||||
const parentPid = ppidMatch ? parseInt(ppidMatch[1], 10) : 0;
|
||||
const commandLineMatch = stdout.match(/CommandLine=([^\n]*)/);
|
||||
const commandLine = commandLineMatch ? commandLineMatch[1].trim() : '';
|
||||
return { parentPid, name: processName, command: commandLine };
|
||||
const powershellCommand = [
|
||||
'$p = Get-CimInstance Win32_Process',
|
||||
`-Filter 'ProcessId=${pid}'`,
|
||||
'-ErrorAction SilentlyContinue;',
|
||||
'if ($p) {',
|
||||
'@{Name=$p.Name;ParentProcessId=$p.ParentProcessId;CommandLine=$p.CommandLine}',
|
||||
'| ConvertTo-Json',
|
||||
'}',
|
||||
].join(' ');
|
||||
const { stdout } = await execAsync(`powershell "${powershellCommand}"`);
|
||||
const output = stdout.trim();
|
||||
if (!output) return { parentPid: 0, name: '', command: '' };
|
||||
const {
|
||||
Name = '',
|
||||
ParentProcessId = 0,
|
||||
CommandLine = '',
|
||||
} = JSON.parse(output);
|
||||
return { parentPid: ParentProcessId, name: Name, command: CommandLine };
|
||||
} else {
|
||||
const command = `ps -o ppid=,command= -p ${pid}`;
|
||||
const { stdout } = await execAsync(command);
|
||||
|
||||
Reference in New Issue
Block a user