Files
gemini-cli/packages/core/src/services/executionLifecycleService.test.ts

109 lines
3.4 KiB
TypeScript
Raw Normal View History

2026-03-08 17:32:16 -04:00
/**
* @license
* Copyright 2025 Google LLC
* SPDX-License-Identifier: Apache-2.0
*/
import { describe, expect, it, vi } from 'vitest';
import {
ShellExecutionService,
type ShellExecutionResult,
} from './shellExecutionService.js';
import {
ExecutionLifecycleService,
type ExecutionCompletionOptions,
} from './executionLifecycleService.js';
const createResult = (): ShellExecutionResult => ({
rawOutput: Buffer.from(''),
output: '',
exitCode: 0,
signal: null,
error: null,
aborted: false,
pid: 123,
executionMethod: 'none',
});
describe('ExecutionLifecycleService', () => {
it('creates executions through ShellExecutionService virtual execution API', () => {
const onKill = vi.fn();
const handle = {
pid: 123,
result: Promise.resolve(createResult()),
};
const createSpy = vi
.spyOn(ShellExecutionService, 'createVirtualExecution')
.mockReturnValue(handle);
const created = ExecutionLifecycleService.createExecution('seed', onKill);
expect(createSpy).toHaveBeenCalledWith('seed', onKill);
expect(created).toBe(handle);
});
it('delegates append and completion to ShellExecutionService virtual APIs', () => {
const appendSpy = vi.spyOn(ShellExecutionService, 'appendVirtualOutput');
const completeSpy = vi.spyOn(
ShellExecutionService,
'completeVirtualExecution',
);
const options: ExecutionCompletionOptions = {
exitCode: 0,
signal: null,
};
ExecutionLifecycleService.appendOutput(123, 'delta');
ExecutionLifecycleService.completeExecution(123, options);
expect(appendSpy).toHaveBeenCalledWith(123, 'delta');
expect(completeSpy).toHaveBeenCalledWith(123, options);
});
it('delegates backgrounding, subscriptions, exit callbacks, and kill', () => {
const unsubscribe = vi.fn();
const backgroundSpy = vi
.spyOn(ShellExecutionService, 'background')
.mockImplementation(() => {});
const subscribeSpy = vi
.spyOn(ShellExecutionService, 'subscribe')
.mockReturnValue(unsubscribe);
const onExitSpy = vi
.spyOn(ShellExecutionService, 'onExit')
.mockReturnValue(unsubscribe);
const killSpy = vi
.spyOn(ShellExecutionService, 'kill')
.mockImplementation(() => {});
const listener = vi.fn();
const onExit = vi.fn();
const returnedSub = ExecutionLifecycleService.subscribe(123, listener);
const returnedExit = ExecutionLifecycleService.onExit(123, onExit);
ExecutionLifecycleService.background(123);
ExecutionLifecycleService.kill(123);
expect(subscribeSpy).toHaveBeenCalledWith(123, listener);
expect(onExitSpy).toHaveBeenCalledWith(123, onExit);
expect(backgroundSpy).toHaveBeenCalledWith(123);
expect(killSpy).toHaveBeenCalledWith(123);
expect(returnedSub).toBe(unsubscribe);
expect(returnedExit).toBe(unsubscribe);
});
it('delegates active checks and input writes', () => {
const isActiveSpy = vi
.spyOn(ShellExecutionService, 'isPtyActive')
.mockReturnValue(true);
const writeSpy = vi
.spyOn(ShellExecutionService, 'writeToPty')
.mockImplementation(() => {});
const isActive = ExecutionLifecycleService.isActive(123);
ExecutionLifecycleService.writeInput(123, 'input');
expect(isActiveSpy).toHaveBeenCalledWith(123);
expect(writeSpy).toHaveBeenCalledWith(123, 'input');
expect(isActive).toBe(true);
});
});