mirror of
https://github.com/stablyai/orca.git
synced 2026-10-22 08:03:37 +00:00
test(ssh): keep relay liveness coverage within limits
This commit is contained in:
@@ -24,8 +24,7 @@ export function isSshPtyExitedEvidenceError(error: unknown): boolean {
|
||||
const message = error instanceof Error ? error.message : String(error)
|
||||
return (
|
||||
!isSshPtyIdentityMismatchError(error) &&
|
||||
(message.includes(SSH_SESSION_EXPIRED_ERROR) ||
|
||||
message === 'agent_session_exited_during_start')
|
||||
(message.includes(SSH_SESSION_EXPIRED_ERROR) || message === 'agent_session_exited_during_start')
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -84,12 +84,25 @@ vi.mock('../providers/ssh-pty-provider', () => ({
|
||||
isSshPtyNotFoundError: (error: unknown) => String(error).includes('not found'),
|
||||
isSshPtyIdentityMismatchError: (error: unknown) => String(error).includes('identity mismatch'),
|
||||
SshPtyProvider: class MockSshPtyProvider {
|
||||
readonly initialUnverifiablePtyIds: Set<string>
|
||||
onData = vi.fn().mockReturnValue(() => {})
|
||||
onReplay = vi.fn().mockReturnValue(() => {})
|
||||
onExit = vi.fn().mockReturnValue(() => {})
|
||||
attach = vi.fn().mockResolvedValue(undefined)
|
||||
attachForReconnect = vi.fn().mockResolvedValue({})
|
||||
acceptUnverifiablePty = vi.fn()
|
||||
acceptExitedPty = vi.fn()
|
||||
dispose = vi.fn()
|
||||
|
||||
constructor(
|
||||
_connectionId: string,
|
||||
_mux: unknown,
|
||||
_remoteCliBridgeEnv: unknown,
|
||||
_providerGeneration: number,
|
||||
initialUnverifiablePtyIds: Iterable<string> = []
|
||||
) {
|
||||
this.initialUnverifiablePtyIds = new Set(initialUnverifiablePtyIds)
|
||||
}
|
||||
}
|
||||
}))
|
||||
vi.mock('../providers/ssh-filesystem-provider', () => ({
|
||||
@@ -181,6 +194,42 @@ describe('SshRelaySession reconnect incarnation ordering', () => {
|
||||
vi.mocked(getPtyIdsForConnection).mockReturnValue([])
|
||||
})
|
||||
|
||||
it('keeps a transiently unreattached PTY unverifiable after the relay becomes ready', async () => {
|
||||
const { mockConn, mockStore, mockPortForward, getMainWindow } = createMockDeps()
|
||||
vi.mocked(getPtyIdsForConnection).mockReturnValue(['pty-unverifiable'])
|
||||
vi.mocked(getSshPtyProvider).mockImplementationOnce(() => {
|
||||
const provider = vi.mocked(registerSshPtyProvider).mock.calls.at(-1)?.[1] as unknown as {
|
||||
attachForReconnect: ReturnType<typeof vi.fn>
|
||||
}
|
||||
provider.attachForReconnect.mockRejectedValue(new Error('transport interrupted'))
|
||||
return provider as never
|
||||
})
|
||||
const warn = vi.spyOn(console, 'warn').mockImplementation(() => {})
|
||||
const session = new SshRelaySession('target-1', getMainWindow, mockStore, mockPortForward)
|
||||
|
||||
try {
|
||||
await session.establish(mockConn)
|
||||
const provider = vi.mocked(registerSshPtyProvider).mock.calls.at(-1)?.[1] as unknown as {
|
||||
initialUnverifiablePtyIds: Set<string>
|
||||
acceptUnverifiablePty: ReturnType<typeof vi.fn>
|
||||
acceptExitedPty: ReturnType<typeof vi.fn>
|
||||
}
|
||||
const appPtyId = 'ssh:target-1@@pty-unverifiable'
|
||||
|
||||
expect(session.getState()).toBe('ready')
|
||||
expect(provider.initialUnverifiablePtyIds).toContain(appPtyId)
|
||||
expect(provider.acceptUnverifiablePty).toHaveBeenCalledWith(appPtyId)
|
||||
expect(provider.acceptExitedPty).not.toHaveBeenCalled()
|
||||
expect(mockStore.markSshRemotePtyLease).not.toHaveBeenCalledWith(
|
||||
'target-1',
|
||||
'pty-unverifiable',
|
||||
'expired'
|
||||
)
|
||||
} finally {
|
||||
warn.mockRestore()
|
||||
}
|
||||
})
|
||||
|
||||
it('bounds fifty reattaches to eight workers without slow or failed sibling head-of-line delay', async () => {
|
||||
const { mockConn, mockStore, mockPortForward, getMainWindow } = createMockDeps()
|
||||
const session = new SshRelaySession('target-1', getMainWindow, mockStore, mockPortForward)
|
||||
|
||||
@@ -66,9 +66,6 @@ vi.mock('../providers/ssh-pty-provider', () => ({
|
||||
isSshPtyIdentityMismatchError: (err: unknown) =>
|
||||
(err instanceof Error ? err.message : String(err)).includes('identity mismatch'),
|
||||
SshPtyProvider: class MockSshPtyProvider {
|
||||
private livePtyIds = new Set<string>()
|
||||
private unverifiablePtyIds = new Set<string>()
|
||||
private exitedPtyIds = new Set<string>()
|
||||
onData = vi.fn().mockReturnValue(() => {})
|
||||
onReplay = vi.fn().mockReturnValue(() => {})
|
||||
onExit = vi.fn().mockReturnValue(() => {})
|
||||
@@ -76,32 +73,6 @@ vi.mock('../providers/ssh-pty-provider', () => ({
|
||||
attachForReconnect = vi.fn().mockResolvedValue({})
|
||||
setPtyDeliveryPauseAdapter = pauseAdapterMock
|
||||
dispose = vi.fn()
|
||||
|
||||
constructor(
|
||||
_connectionId: string,
|
||||
_mux: unknown,
|
||||
_remoteCliBridgeEnv: unknown,
|
||||
_providerGeneration: number,
|
||||
initialUnverifiablePtyIds: Iterable<string> = []
|
||||
) {
|
||||
this.unverifiablePtyIds = new Set(initialUnverifiablePtyIds)
|
||||
}
|
||||
|
||||
hasPty = (id: string): boolean => this.livePtyIds.has(id) || this.unverifiablePtyIds.has(id)
|
||||
probePtyLiveness = vi.fn(
|
||||
async (id: string): Promise<boolean | null> =>
|
||||
this.livePtyIds.has(id) ? true : this.exitedPtyIds.has(id) ? false : null
|
||||
)
|
||||
acceptUnverifiablePty = vi.fn((id: string) => {
|
||||
this.livePtyIds.delete(id)
|
||||
this.exitedPtyIds.delete(id)
|
||||
this.unverifiablePtyIds.add(id)
|
||||
})
|
||||
acceptExitedPty = vi.fn((id: string) => {
|
||||
this.livePtyIds.delete(id)
|
||||
this.unverifiablePtyIds.delete(id)
|
||||
this.exitedPtyIds.add(id)
|
||||
})
|
||||
}
|
||||
}))
|
||||
|
||||
@@ -235,41 +206,6 @@ describe('SshRelaySession', () => {
|
||||
expect(registerSshGitProvider).toHaveBeenCalledWith('target-1', expect.anything())
|
||||
})
|
||||
|
||||
it('keeps a transiently unreattached PTY unverifiable after the relay becomes ready', async () => {
|
||||
const { mockConn, mockStore, mockPortForward, getMainWindow } = createMockDeps()
|
||||
const { getSshPtyProvider } = await import('../ipc/pty')
|
||||
vi.mocked(getPtyIdsForConnection).mockReturnValue(['pty-unverifiable'])
|
||||
vi.mocked(getSshPtyProvider).mockImplementationOnce(() => {
|
||||
const provider = vi.mocked(registerSshPtyProvider).mock.calls.at(-1)?.[1] as {
|
||||
attachForReconnect: ReturnType<typeof vi.fn>
|
||||
}
|
||||
provider.attachForReconnect.mockRejectedValue(new Error('transport interrupted'))
|
||||
return provider as never
|
||||
})
|
||||
const warn = vi.spyOn(console, 'warn').mockImplementation(() => {})
|
||||
const session = new SshRelaySession('target-1', getMainWindow, mockStore, mockPortForward)
|
||||
|
||||
try {
|
||||
await session.establish(mockConn)
|
||||
const provider = vi.mocked(registerSshPtyProvider).mock.calls.at(-1)?.[1] as {
|
||||
hasPty: (id: string) => boolean
|
||||
probePtyLiveness: (id: string) => Promise<boolean | null>
|
||||
}
|
||||
const appPtyId = 'ssh:target-1@@pty-unverifiable'
|
||||
|
||||
expect(session.getState()).toBe('ready')
|
||||
expect(provider.hasPty(appPtyId)).toBe(true)
|
||||
await expect(provider.probePtyLiveness(appPtyId)).resolves.toBeNull()
|
||||
expect(mockStore.markSshRemotePtyLease).not.toHaveBeenCalledWith(
|
||||
'target-1',
|
||||
'pty-unverifiable',
|
||||
'expired'
|
||||
)
|
||||
} finally {
|
||||
warn.mockRestore()
|
||||
}
|
||||
})
|
||||
|
||||
it('continues provider registration when the relay managed-hook request fails', async () => {
|
||||
process.env.ORCA_FEATURE_REMOTE_AGENT_HOOKS = '1'
|
||||
muxRequestMock.mockImplementation(async (method: string) => {
|
||||
|
||||
Reference in New Issue
Block a user