diff --git a/src/main/agent-hooks/server-opencode-binder.test.ts b/src/main/agent-hooks/server-opencode-binder.test.ts index 328dc98c04c..261de8888ac 100644 --- a/src/main/agent-hooks/server-opencode-binder.test.ts +++ b/src/main/agent-hooks/server-opencode-binder.test.ts @@ -3,13 +3,12 @@ import { tmpdir } from 'node:os' import { join } from 'node:path' import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest' import type { AgentHookSource } from '../../shared/agent-hook-relay' -import { createHookListenerState } from '../../shared/agent-hook-listener/listener-state' import { lookupOpenCodeSessionPane } from '../../shared/agent-hook-listener/opencode-session-registry' import { makePaneKey } from '../../shared/stable-pane-id' import SyncDatabase from '../sqlite/sync-database' import { AgentHookServer } from './server' import type { OpenCodeBinderLoopDeps } from './server/server-opencode-binder' -import { defaultOpenCodeDbPath, listOpenCodeDbSessions } from '../opencode/opencode-session-binder' +import { listOpenCodeDbSessions } from '../opencode/opencode-session-binder' const LEAF_A = 'aaaaaaaa-aaaa-4aaa-8aaa-aaaaaaaaaaaa' const LEAF_B = 'bbbbbbbb-bbbb-4bbb-8bbb-bbbbbbbbbbbb' @@ -237,15 +236,4 @@ describe('listOpenCodeDbSessions', () => { it('returns [] for a missing database instead of throwing', () => { expect(listOpenCodeDbSessions(join(dir, 'absent.db'), { ms: 0, id: '' })).toEqual([]) }) - - it('the default path points at the local opencode store', () => { - expect(defaultOpenCodeDbPath()).toMatch(/opencode\.db$/) - }) -}) - -describe('binder registry isolation', () => { - it('a fresh listener state starts unbound', () => { - const state = createHookListenerState() - expect(lookupOpenCodeSessionPane(state, 'ses_live')).toBeUndefined() - }) }) diff --git a/src/main/agent-hooks/server/server-row-ownership.test.ts b/src/main/agent-hooks/server/server-row-ownership.test.ts index e466ef879d2..3a63a0f2a75 100644 --- a/src/main/agent-hooks/server/server-row-ownership.test.ts +++ b/src/main/agent-hooks/server/server-row-ownership.test.ts @@ -44,14 +44,6 @@ function row( } describe('status-row change detection', () => { - it('treats the same row object on both sides as unchanged', () => { - const probe = new RowMutationProbe() - const same = row() - expect(probe.commit(same, same)).toBe(false) - expect(probe.commit(null, undefined)).toBe(false) - expect(probe.mutations).toEqual([]) - }) - it('ignores a rebuilt row whose published content is identical', () => { const probe = new RowMutationProbe() const before = row() diff --git a/src/main/daemon/daemon-spawner.test.ts b/src/main/daemon/daemon-spawner.test.ts index a2ad26130ff..a031ccd9e54 100644 --- a/src/main/daemon/daemon-spawner.test.ts +++ b/src/main/daemon/daemon-spawner.test.ts @@ -2,7 +2,6 @@ import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest' import { tmpdir } from 'node:os' import { basename, join } from 'node:path' import { chmodSync, mkdtempSync, readFileSync, rmSync, writeFileSync } from 'node:fs' -import { createServer, connect, type Server } from 'node:net' import { DaemonSpawner, getDaemonArtifactHoldClaimPath, @@ -14,12 +13,7 @@ import { replaceDaemonPidFile, restoreClaimedDaemonArtifact } from './daemon-spawner' -import { - getDaemonSocketBindPath, - publishDaemonEndpoint, - readDaemonSocketIdentity -} from './daemon-endpoint-ownership' -import { probeSocketConnect } from './daemon-endpoint-probe' +import { getDaemonSocketBindPath } from './daemon-endpoint-ownership' import { startDaemon, type DaemonHandle } from './daemon-main' import { DaemonClient } from './client' import type { SubprocessHandle } from './session-subprocess-handle' @@ -144,25 +138,6 @@ describe('DaemonSpawner', () => { expect(client.isConnected()).toBe(true) client.disconnect() }) - - it('daemon can create sessions', async () => { - const s = createSpawner() - const info = await s.ensureRunning() - - const client = new DaemonClient({ - socketPath: info.socketPath, - tokenPath: info.tokenPath - }) - await client.ensureConnected() - - const result = await client.request<{ isNew: boolean }>('createOrAttach', { - sessionId: 'test-session', - cols: 80, - rows: 24 - }) - expect(result.isNew).toBe(true) - client.disconnect() - }) }) describe('shutdown', () => { @@ -313,45 +288,6 @@ describe('daemon PID publication', () => { }) }) -function listenOnSocketPath(server: Server, socketPath: string): Promise { - return new Promise((resolve, reject) => { - server.once('error', reject) - server.listen(socketPath, () => { - server.off('error', reject) - resolve() - }) - }) -} - -function closeSocketServer(server: Server): Promise { - return new Promise((resolve) => { - if (!server.listening) { - resolve() - return - } - server.close(() => resolve()) - }) -} - -function connectsToSocketPath(socketPath: string): Promise { - return new Promise((resolve) => { - const socket = connect({ path: socketPath }) - const timer = setTimeout(() => { - socket.destroy() - resolve(false) - }, 500) - socket.on('connect', () => { - clearTimeout(timer) - socket.destroy() - resolve(true) - }) - socket.on('error', () => { - clearTimeout(timer) - resolve(false) - }) - }) -} - describe('daemon socket publication', () => { it('keeps every scratch namespace outside the released sweeper pattern', () => { // Why pinned, and why all three: builds already in the field sweep these names on age alone @@ -380,92 +316,4 @@ describe('daemon socket publication', () => { expect(getDaemonSocketBindPath(canonicalPath).length).toBeLessThan(canonicalPath.length) }) - - it.skipIf(process.platform === 'win32')( - 'keeps a live incumbent reachable when a second listener publishes', - async () => { - const dir = createTestDir() - const canonicalPath = getDaemonSocketPath(dir) - const incumbent = createServer((socket) => socket.end()) - const newcomer = createServer((socket) => socket.end()) - try { - const incumbentBind = getDaemonSocketBindPath(canonicalPath) - await listenOnSocketPath(incumbent, incumbentBind) - const incumbentOutcome = await publishDaemonEndpoint( - incumbentBind, - canonicalPath, - probeSocketConnect - ) - expect(incumbentOutcome.status).toBe('published') - const incumbentIdentity = readDaemonSocketIdentity(canonicalPath) - - const newcomerBind = getDaemonSocketBindPath(canonicalPath) - await listenOnSocketPath(newcomer, newcomerBind) - await expect( - publishDaemonEndpoint(newcomerBind, canonicalPath, probeSocketConnect) - ).resolves.toEqual({ status: 'occupied' }) - - expect(readDaemonSocketIdentity(canonicalPath)).toEqual(incumbentIdentity) - await expect(connectsToSocketPath(canonicalPath)).resolves.toBe(true) - } finally { - await closeSocketServer(incumbent) - await closeSocketServer(newcomer) - rmSync(dir, { recursive: true, force: true }) - } - } - ) - - it.skipIf(process.platform === 'win32')( - 'leaves an unclassifiable incumbent untouched', - async () => { - const dir = createTestDir() - const canonicalPath = getDaemonSocketPath(dir) - const newcomer = createServer((socket) => socket.end()) - try { - writeFileSync(canonicalPath, 'incumbent') - const newcomerBind = getDaemonSocketBindPath(canonicalPath) - await listenOnSocketPath(newcomer, newcomerBind) - - await expect( - publishDaemonEndpoint(newcomerBind, canonicalPath, async () => 'unknown') - ).resolves.toEqual({ status: 'inconclusive' }) - expect(readFileSync(canonicalPath, 'utf8')).toBe('incumbent') - } finally { - await closeSocketServer(newcomer) - rmSync(dir, { recursive: true, force: true }) - } - } - ) - - it.skipIf(process.platform === 'win32')( - 'replaces a dead incumbent with a reachable listener', - async () => { - const dir = createTestDir() - const canonicalPath = getDaemonSocketPath(dir) - const incumbent = createServer((socket) => socket.end()) - const replacement = createServer((socket) => socket.end()) - try { - const incumbentBind = getDaemonSocketBindPath(canonicalPath) - await listenOnSocketPath(incumbent, incumbentBind) - await publishDaemonEndpoint(incumbentBind, canonicalPath, probeSocketConnect) - await closeSocketServer(incumbent) - await expect(connectsToSocketPath(canonicalPath)).resolves.toBe(false) - - const replacementBind = getDaemonSocketBindPath(canonicalPath) - await listenOnSocketPath(replacement, replacementBind) - const outcome = await publishDaemonEndpoint( - replacementBind, - canonicalPath, - probeSocketConnect - ) - - expect(outcome.status).toBe('published') - await expect(connectsToSocketPath(canonicalPath)).resolves.toBe(true) - } finally { - await closeSocketServer(incumbent) - await closeSocketServer(replacement) - rmSync(dir, { recursive: true, force: true }) - } - } - ) }) diff --git a/src/main/daemon/issue-6814-daemon-failure-classification.test.ts b/src/main/daemon/issue-6814-daemon-failure-classification.test.ts index a7504a5e2a3..b1c36a2c7f5 100644 --- a/src/main/daemon/issue-6814-daemon-failure-classification.test.ts +++ b/src/main/daemon/issue-6814-daemon-failure-classification.test.ts @@ -56,44 +56,6 @@ describe('issue #6814 repro: daemon failure-mode classification', () => { rmSync(dir, { recursive: true, force: true }) }) - // The good case: daemon answers hello AND the PTY spawn probe succeeds. - it('HEALTHY: a daemon that can spawn PTYs classifies as healthy', async () => { - const server = new DaemonServer({ - socketPath, - tokenPath, - ptySpawnHealthCheck: vi.fn(async () => {}), - spawnSubprocess: () => createMockSubprocess() - }) - await server.start() - try { - await expect(checkDaemonHealth(socketPath, tokenPath)).resolves.toBe('healthy') - } finally { - await server.shutdown() - } - }) - - // Symptom B, degraded: this is the case #6830 RESCUES. The daemon answers - // protocol but its PTY spawn probe throws (deleted cwd / stale native PTY - // after an upgrade), so fresh terminals would open frozen with no cursor. - it('DEGRADED: protocol-alive daemon that cannot spawn PTYs classifies as pty-spawn-unhealthy', async () => { - const server = new DaemonServer({ - socketPath, - tokenPath, - ptySpawnHealthCheck: vi.fn(async () => { - throw new Error('chdir(2) failed.: No such file or directory') - }), - spawnSubprocess: () => createMockSubprocess() - }) - await server.start() - try { - // -> #6830 marks this daemon degraded and routes fresh spawns to the - // local provider instead of the no-cursor daemon pane. - await expect(checkDaemonHealth(socketPath, tokenPath)).resolves.toBe('pty-spawn-unhealthy') - } finally { - await server.shutdown() - } - }) - // The limit of #6830: a fully WEDGED daemon (event loop hung — health RPC // never returns) cannot be distinguished by a richer status. It times out // and classifies as 'unreachable', the SAME bucket as a dead daemon. @@ -137,9 +99,4 @@ describe('issue #6814 repro: daemon failure-mode classification', () => { await new Promise((resolve) => wedged.close(() => resolve())) } }, 15000) - - // No daemon at all (or token missing) -> unreachable. - it('UNREACHABLE: no daemon listening classifies as unreachable', async () => { - await expect(checkDaemonHealth(socketPath, tokenPath)).resolves.toBe('unreachable') - }) }) diff --git a/src/main/github/client-rate-limit-block.test.ts b/src/main/github/client-rate-limit-block.test.ts index a8c0a232ffa..969cc16af95 100644 --- a/src/main/github/client-rate-limit-block.test.ts +++ b/src/main/github/client-rate-limit-block.test.ts @@ -88,20 +88,6 @@ describe('getGitHubPRLookupRateLimitBlock', () => { }) }) - it('reports the later reset when graphql outlasts core', async () => { - // Retrying at the earlier reset would fail again on the bucket still blocked. - rateLimitGuardMock.mockImplementation(((bucket: string) => ({ - blocked: true, - remaining: 0, - limit: 5000, - resetAt: bucket === 'graphql' ? 1_800_000_600 : 1_800_000_000 - })) as () => RateLimitGuardResult) - - await expect(getGitHubPRLookupRateLimitBlock('/repo-root')).resolves.toEqual({ - resetAt: 1_800_000_600 - }) - }) - it('fails open when the exempt rate-limit probe itself fails', async () => { getRateLimitMock.mockRejectedValue(new Error('probe offline')) diff --git a/src/main/github/pr-refresh-coordinator-refresh-events.test.ts b/src/main/github/pr-refresh-coordinator-refresh-events.test.ts index 76745cf4789..fcaaff529ba 100644 --- a/src/main/github/pr-refresh-coordinator-refresh-events.test.ts +++ b/src/main/github/pr-refresh-coordinator-refresh-events.test.ts @@ -27,23 +27,6 @@ describe('pr-refresh-coordinator', () => { vi.useRealTimers() }) - it('preserves the coordinator public module API', async () => { - const coordinator = await import('./pr-refresh-coordinator') - - expect(Object.keys(coordinator).sort()).toEqual([ - '_getPRRefreshAliasCountForTests', - '_getPRRefreshErrorBackoffCountForTests', - '_getPRRefreshQueueSizeForTests', - '_getVisiblePRRefreshWindowCountForTests', - 'clearVisiblePRRefreshWindow', - 'enqueuePRRefresh', - 'pruneWorktreePRRefreshAliases', - 'refreshPRNow', - 'reportVisiblePRRefreshCandidates', - 'setPRRefreshOutcomeObserver' - ]) - }) - it('ignores a stale visibility generation before it can replace queued work', async () => { const { reportVisiblePRRefreshCandidates } = await import('./pr-refresh-coordinator') getPRForBranchOutcomeMock.mockResolvedValue({ kind: 'no-pr', fetchedAt: Date.now() }) diff --git a/src/main/native-chat/agent-session-journal/journal-item-identity.test.ts b/src/main/native-chat/agent-session-journal/journal-item-identity.test.ts index 0e05fc3fc93..58d6e58bda7 100644 --- a/src/main/native-chat/agent-session-journal/journal-item-identity.test.ts +++ b/src/main/native-chat/agent-session-journal/journal-item-identity.test.ts @@ -1,7 +1,6 @@ import { describe, expect, it } from 'vitest' import { agentJournalItemKey, - agentJournalSubmissionKey, boundJournalKeyComponent, MAX_JOURNAL_KEY_COMPONENT_CHARS, parseAgentJournalItemKey @@ -139,12 +138,6 @@ describe('key encoding', () => { }) expect(orca).not.toBe(legacy) }) - - it('derives the submission slot from the same function the reducer uses', () => { - expect(agentJournalSubmissionKey('cm_42')).toBe( - agentJournalItemKey({ provider: 'orca', clientMessageId: 'cm_42' }) - ) - }) }) describe('bounded component domain separation', () => { diff --git a/src/main/native-chat/agent-session-journal/journal-turn-scope.test.ts b/src/main/native-chat/agent-session-journal/journal-turn-scope.test.ts index 6842c119f73..2b8e4b80a76 100644 --- a/src/main/native-chat/agent-session-journal/journal-turn-scope.test.ts +++ b/src/main/native-chat/agent-session-journal/journal-turn-scope.test.ts @@ -124,14 +124,6 @@ function submissionScope(state: JournalReducerState, clientMessageId: string) { return state.items.get(agentJournalSubmissionKey(clientMessageId))?.turnScope } -function refold(built: readonly JournalRow[]) { - const state = createJournalReducerState('session-1', 'epoch-1') - for (const next of built) { - applyJournalRow(state, next) - } - return renderJournalState(state) -} - describe('stated turn scope', () => { it('keeps the scope of the write that created the row', () => { const { state, item } = rows() @@ -231,8 +223,8 @@ describe('scope derived for rows stored without one', () => { expect(scopeOf(state, row('crash-window'))).toEqual(inTurn(TURN_1)) }) - it('derives the same scopes on replay as live', () => { - const { state, built, item, submission, handover } = rows() + it('places a queued message handed over without a stated scope in the live turn', () => { + const { state, item, submission, handover } = rows() item(TURN_1, turn('t1', 'running')) item(row('inside'), prose('inside')) submission('steer') @@ -240,6 +232,5 @@ describe('scope derived for rows stored without one', () => { item(TURN_1, turn('t1', 'completed')) item(row('after'), prose('after')) expect(submissionScope(state, 'steer')).toEqual(inTurn(TURN_1)) - expect(refold(built)).toEqual(renderJournalState(state)) }) }) diff --git a/src/main/native-chat/agent-session-wire/provider-frame-disposition.test.ts b/src/main/native-chat/agent-session-wire/provider-frame-disposition.test.ts index cdee04cf2bf..55b338366f6 100644 --- a/src/main/native-chat/agent-session-wire/provider-frame-disposition.test.ts +++ b/src/main/native-chat/agent-session-wire/provider-frame-disposition.test.ts @@ -1,7 +1,5 @@ import { describe, expect, it } from 'vitest' import { DEFAULT_JOURNAL_PAYLOAD_LIMITS } from '../agent-session-journal/journal-payload-bounds' -import { CODEX_APP_SERVER_NOTIFICATION_METHODS } from '../../codex/codex-app-server-notification-schema' -import { CLAUDE_STREAM_JSON_FRAME_KINDS } from './claude-stream-json-frame-schema' import { classifyProviderFrame, isDeltaProviderFrameKind, @@ -10,18 +8,6 @@ import { import { unhandledProviderFrameJournalItem } from './unhandled-provider-frame' describe('provider frame classification catalog', () => { - it('classifies every pinned Codex app-server notification method', () => { - expect(Object.keys(PROVIDER_FRAME_CLASSIFICATIONS.codex)).toEqual([ - ...CODEX_APP_SERVER_NOTIFICATION_METHODS - ]) - }) - - it('classifies every pinned Claude stream-json frame kind', () => { - expect(Object.keys(PROVIDER_FRAME_CLASSIFICATIONS.claude)).toEqual([ - ...CLAUDE_STREAM_JSON_FRAME_KINDS - ]) - }) - it('classifies every pinned delta kind as stream-into-item', () => { const deltaKinds = [ ...Object.keys(PROVIDER_FRAME_CLASSIFICATIONS.codex), diff --git a/src/main/native-chat/claude-structured-managed-account-support.test.ts b/src/main/native-chat/claude-structured-managed-account-support.test.ts index f647579d03e..8d6aa55783f 100644 --- a/src/main/native-chat/claude-structured-managed-account-support.test.ts +++ b/src/main/native-chat/claude-structured-managed-account-support.test.ts @@ -90,24 +90,6 @@ describe('structuredClaudeMatchesActiveManagedAccount', () => { expect(structuredClaudeMatchesActiveManagedAccount(undefined)).toBe(false) }) - /** The four states this gate exists to tell apart, pinned together so a change to one is visible - * against the others. */ - it.each([ - ['no managed accounts', [], null, true], - ['accounts present, none active, no WSL account', [account('host-1', 'host')], null, true], - ['host account selected', [account('host-1', 'host')], 'host-1', true], - ['WSL-only, normalized to no host selection', [account('wsl-1', 'wsl')], null, false] - ] as const)('resolves %s', (_name, claudeManagedAccounts, activeId, expected) => { - expect( - structuredClaudeMatchesActiveManagedAccount( - settings({ - claudeManagedAccounts: [...claudeManagedAccounts], - activeClaudeManagedAccountIdsByRuntime: { host: activeId, wsl: {} } - }) - ) - ).toBe(expected) - }) - /** THE discriminator, and the whole of this rule. With nothing selected for the host runtime the * settings alone cannot distinguish honest deselection from the WSL-only steady state, because * `pruneInvalidClaudeRuntimeSelection` empties the host slot in the second case and persists it. diff --git a/src/main/persistence/profile-state/profile-state-database.test.ts b/src/main/persistence/profile-state/profile-state-database.test.ts index c3cb63fb114..245806b8ad0 100644 --- a/src/main/persistence/profile-state/profile-state-database.test.ts +++ b/src/main/persistence/profile-state/profile-state-database.test.ts @@ -330,10 +330,3 @@ describe('profile state database', () => { } }) }) - -describe('profile state database does not reuse orchestration state', () => { - it('uses a profile-local filename', () => { - const directory = createDirectory() - expect(profileStateDatabaseFile(directory)).not.toBe(join(directory, 'orchestration.db')) - }) -}) diff --git a/src/main/providers/local-pty-child-process-verdict.test.ts b/src/main/providers/local-pty-child-process-verdict.test.ts index 857017b6671..f934a7e7413 100644 --- a/src/main/providers/local-pty-child-process-verdict.test.ts +++ b/src/main/providers/local-pty-child-process-verdict.test.ts @@ -149,13 +149,6 @@ describeOnPosix('inspectLocalPtyChildProcesses on a retired master', () => { // Not `no-children`: the close guard reads that as "nothing is running here" and kills the pane. expect(await inspectLocalPtyChildProcesses('pty-retired')).toBe('unverifiable') }, 15000) - - it('preserves uncertainty conservatively in the boolean adapter', async () => { - await registerRetiredPane('pty-retired') - - // The adapter exists for `IPtyProvider.hasChildProcesses`, which has no third slot. - await expect(hasLocalPtyChildProcesses('pty-retired')).resolves.toBe(true) - }, 15000) }) describe('inspectPtyProviderProcess child-process evidence', () => { diff --git a/src/main/providers/macos-tcc-login-shell.test.ts b/src/main/providers/macos-tcc-login-shell.test.ts index ad29faf376e..585c9eb9d38 100644 --- a/src/main/providers/macos-tcc-login-shell.test.ts +++ b/src/main/providers/macos-tcc-login-shell.test.ts @@ -608,16 +608,6 @@ describe('probeMacosLoginSessionAlive', () => { expect(wrapShellSpawnForMacosTccAttribution('/bin/zsh', ['-l']).file).toBe('/bin/zsh') }) - it('does not overwrite the cached verdict on an inconclusive probe', async () => { - setPlatform('darwin') - await prepareMacosTccLoginShell() - runProcessMock.mockReturnValue(TIMED_OUT_RESULT) - ptyProbeMock.mockResolvedValue({ ok: false, conclusive: false, reason: 'timeout' }) - const outcome = await probeMacosLoginSessionAlive() - expect(outcome).toEqual({ ok: false, conclusive: false, reason: 'timeout' }) - expect(wrapShellSpawnForMacosTccAttribution('/bin/zsh', ['-l']).file).toBe('/usr/bin/login') - }) - it('does not trust a pipe rejection when its PTY confirmation is inconclusive', async () => { setPlatform('darwin') await prepareMacosTccLoginShell() diff --git a/src/main/providers/ssh-filesystem-provider.test.ts b/src/main/providers/ssh-filesystem-provider.test.ts index 0917c4cf81a..33b063ffa0c 100644 --- a/src/main/providers/ssh-filesystem-provider.test.ts +++ b/src/main/providers/ssh-filesystem-provider.test.ts @@ -59,10 +59,6 @@ describe('SshFilesystemProvider', () => { provider = new SshFilesystemProvider('conn-1', mux as never) }) - it('returns the connectionId', () => { - expect(provider.getConnectionId()).toBe('conn-1') - }) - describe('readDir', () => { it('sends fs.readDir request', async () => { const entries = [ diff --git a/src/main/providers/ssh-git-provider-api.test.ts b/src/main/providers/ssh-git-provider-api.test.ts deleted file mode 100644 index 3e6ebf76d74..00000000000 --- a/src/main/providers/ssh-git-provider-api.test.ts +++ /dev/null @@ -1,72 +0,0 @@ -import { describe, expect, it } from 'vitest' -import type { IGitProvider } from './types' -import { SshGitProvider } from './ssh-git-provider' -import { createMockMux } from './ssh-git-provider-test-harness' - -describe('SshGitProvider public API parity', () => { - it('retains every historical provider operation', () => { - const provider: IGitProvider & SshGitProvider = new SshGitProvider( - 'conn-1', - createMockMux() as never - ) - const methods = [ - 'getConnectionId', - 'getHostPlatform', - 'getStatus', - 'getSubmoduleStatus', - 'checkIgnoredPaths', - 'getHistory', - 'commit', - 'getStagedCommitContext', - 'executeCommitMessagePlan', - 'execNonInteractive', - 'cancelNonInteractiveExec', - 'cancelGenerateCommitMessage', - 'getDiff', - 'stageFile', - 'unstageFile', - 'bulkStageFiles', - 'bulkUnstageFiles', - 'discardChanges', - 'bulkDiscardChanges', - 'detectConflictOperation', - 'abortMerge', - 'abortRebase', - 'checkoutBranch', - 'listLocalBranches', - 'getBranchCompare', - 'getCommitCompare', - 'getUpstreamStatus', - 'pushBranch', - 'pullBranch', - 'fastForwardBranch', - 'rebaseFromBase', - 'fetchRemote', - 'syncForkDefaultBranch', - 'fetchRemoteTrackingRef', - 'fetchGitLabMergeRequestHead', - 'fetchGitHubPullRequestHead', - 'getBranchDiff', - 'getCommitDiff', - 'listWorktrees', - 'addWorktree', - 'removeWorktree', - 'worktreeIsClean', - 'refreshLocalBaseRefForWorktreeCreate', - 'renameCurrentBranch', - 'markRemoteOrcaCreated', - 'forceDeletePreservedBranch', - 'exec', - 'clone', - 'isGitRepoAsync', - 'isGitRepo', - 'getRemoteFileUrl', - 'getRemoteCommitUrl' - ] as const - - expect(methods).toHaveLength(52) - for (const method of methods) { - expect(provider[method], method).toBeTypeOf('function') - } - }) -}) diff --git a/src/main/providers/ssh-git-provider-status-lease.test.ts b/src/main/providers/ssh-git-provider-status-lease.test.ts index f7a8a09018b..9f436ba1a1a 100644 --- a/src/main/providers/ssh-git-provider-status-lease.test.ts +++ b/src/main/providers/ssh-git-provider-status-lease.test.ts @@ -29,122 +29,6 @@ describe('SshGitProvider status read leases', () => { provider = new SshGitProvider('conn-1', mux as never) }) - it('shares one status RPC across distinct caller signals', async () => { - const pending = deferredPromise<{ - entries: never[] - conflictOperation: 'unknown' - }>() - mux.request.mockReturnValue(pending.promise) - const controllers = Array.from({ length: 10 }, () => new AbortController()) - - const reads = controllers.map((controller) => - provider.getStatus('/home/user/repo', { signal: controller.signal }) - ) - await waitForRequestCount(mux.request, 1) - - expect(mux.request).toHaveBeenCalledTimes(1) - pending.resolve({ entries: [], conflictOperation: 'unknown' }) - await expect(Promise.all(reads)).resolves.toHaveLength(10) - }) - - it('isolates first and later caller cancellation while a status lease remains', async () => { - const pending = deferredPromise<{ - entries: never[] - conflictOperation: 'unknown' - }>() - mux.request.mockReturnValue(pending.promise) - const firstController = new AbortController() - const secondController = new AbortController() - const thirdController = new AbortController() - const firstError = new Error('first caller cancelled') - const thirdError = new Error('third caller cancelled') - - const first = provider.getStatus('/home/user/repo', { signal: firstController.signal }) - const second = provider.getStatus('/home/user/repo', { signal: secondController.signal }) - const third = provider.getStatus('/home/user/repo', { signal: thirdController.signal }) - await waitForRequestCount(mux.request, 1) - const sharedSignal = mux.request.mock.calls[0][2].signal as AbortSignal - - firstController.abort(firstError) - thirdController.abort(thirdError) - await expect(first).rejects.toBe(firstError) - await expect(third).rejects.toBe(thirdError) - expect(sharedSignal.aborted).toBe(false) - - pending.resolve({ entries: [], conflictOperation: 'unknown' }) - await expect(second).resolves.toEqual({ entries: [], conflictOperation: 'unknown' }) - }) - - it('cancels the underlying status RPC after its last live lease aborts', async () => { - const firstPending = deferredPromise<{ - entries: never[] - conflictOperation: 'unknown' - }>() - mux.request.mockReturnValueOnce(firstPending.promise) - const firstController = new AbortController() - const secondController = new AbortController() - const firstError = new Error('first caller cancelled') - const secondError = new Error('second caller cancelled') - const first = provider.getStatus('/home/user/repo', { signal: firstController.signal }) - const second = provider.getStatus('/home/user/repo', { signal: secondController.signal }) - await waitForRequestCount(mux.request, 1) - const sharedSignal = mux.request.mock.calls[0][2].signal as AbortSignal - sharedSignal.addEventListener('abort', () => firstPending.reject(sharedSignal.reason), { - once: true - }) - - firstController.abort(firstError) - await expect(first).rejects.toBe(firstError) - expect(sharedSignal.aborted).toBe(false) - secondController.abort(secondError) - await expect(second).rejects.toBe(secondError) - expect(sharedSignal.aborted).toBe(true) - - mux.request.mockResolvedValueOnce({ entries: [], conflictOperation: 'unknown' }) - await expect(provider.getStatus('/home/user/repo')).resolves.toMatchObject({ entries: [] }) - expect(mux.request).toHaveBeenCalledTimes(2) - }) - - it('rejects pre-aborted status callers without starting or joining an RPC', async () => { - const controller = new AbortController() - const abortError = new Error('already cancelled') - controller.abort(abortError) - - await expect(provider.getStatus('/home/user/repo', { signal: controller.signal })).rejects.toBe( - abortError - ) - expect(mux.request).not.toHaveBeenCalled() - - const pending = deferredPromise<{ - entries: never[] - conflictOperation: 'unknown' - }>() - mux.request.mockReturnValueOnce(pending.promise) - const active = provider.getStatus('/home/user/repo') - await waitForRequestCount(mux.request, 1) - await expect(provider.getStatus('/home/user/repo', { signal: controller.signal })).rejects.toBe( - abortError - ) - expect(mux.request).toHaveBeenCalledTimes(1) - - pending.resolve({ entries: [], conflictOperation: 'unknown' }) - await active - }) - - it('starts fresh status RPCs after result and error settlement', async () => { - const status = { entries: [], conflictOperation: 'unknown' as const } - mux.request.mockResolvedValueOnce(status) - - await expect(provider.getStatus('/home/user/repo')).resolves.toBe(status) - const failure = new Error('relay status failed') - mux.request.mockRejectedValueOnce(failure) - await expect(provider.getStatus('/home/user/repo')).rejects.toBe(failure) - mux.request.mockResolvedValueOnce(status) - await expect(provider.getStatus('/home/user/repo')).resolves.toBe(status) - - expect(mux.request).toHaveBeenCalledTimes(3) - }) - it('isolates status reads by worktree and output-affecting options', async () => { const pendingRequests = Array.from({ length: 8 }, () => deferredPromise<{ entries: never[]; conflictOperation: 'unknown' }>() diff --git a/src/main/providers/ssh-git-provider-status.test.ts b/src/main/providers/ssh-git-provider-status.test.ts index 1eb727eacfb..bb5d8adde2e 100644 --- a/src/main/providers/ssh-git-provider-status.test.ts +++ b/src/main/providers/ssh-git-provider-status.test.ts @@ -11,10 +11,6 @@ describe('SshGitProvider', () => { provider = new SshGitProvider('conn-1', mux as never) }) - it('returns the connectionId', () => { - expect(provider.getConnectionId()).toBe('conn-1') - }) - it('getStatus sends git.status request', async () => { const statusResult = { entries: [{ path: 'generated/a.ts', status: 'untracked', area: 'untracked' }], diff --git a/src/main/providers/ssh-git-provider-upstream-lease.test.ts b/src/main/providers/ssh-git-provider-upstream-lease.test.ts index d13c2d705bc..5717be064c4 100644 --- a/src/main/providers/ssh-git-provider-upstream-lease.test.ts +++ b/src/main/providers/ssh-git-provider-upstream-lease.test.ts @@ -29,23 +29,6 @@ describe('SshGitProvider upstream status read leases', () => { provider = new SshGitProvider('conn-1', mux as never) }) - it('shares one upstream-status RPC across ten identical callers', async () => { - const pending = deferredPromise<{ - hasUpstream: true - upstreamName: string - ahead: number - behind: number - }>() - mux.request.mockReturnValue(pending.promise) - - const reads = Array.from({ length: 10 }, () => provider.getUpstreamStatus('/home/user/repo')) - await waitForRequestCount(mux.request, 1) - - expect(mux.request).toHaveBeenCalledTimes(1) - pending.resolve({ hasUpstream: true, upstreamName: 'origin/main', ahead: 1, behind: 0 }) - await expect(Promise.all(reads)).resolves.toHaveLength(10) - }) - it('isolates upstream-status RPCs by worktree and every target field', async () => { mux.request.mockResolvedValue({ hasUpstream: true, @@ -89,32 +72,6 @@ describe('SshGitProvider upstream status read leases', () => { expect(mux.request).toHaveBeenCalledTimes(2) }) - it('runs a fresh upstream-status RPC after result and error settlement', async () => { - const failure = new Error('upstream RPC failed') - mux.request - .mockResolvedValueOnce({ - hasUpstream: true, - upstreamName: 'origin/main', - ahead: 0, - behind: 0 - }) - .mockRejectedValueOnce(failure) - .mockResolvedValueOnce({ - hasUpstream: false, - ahead: 0, - behind: 0 - }) - - await expect(provider.getUpstreamStatus('/home/user/repo')).resolves.toMatchObject({ - hasUpstream: true - }) - await expect(provider.getUpstreamStatus('/home/user/repo')).rejects.toBe(failure) - await expect(provider.getUpstreamStatus('/home/user/repo')).resolves.toMatchObject({ - hasUpstream: false - }) - expect(mux.request).toHaveBeenCalledTimes(3) - }) - it('fences upstream-status reads before, during, and after an SSH mutation', async () => { const upstreamRequests = Array.from({ length: 3 }, () => deferredPromise<{ hasUpstream: false; ahead: 0; behind: 0 }>() diff --git a/src/main/providers/ssh-pty-provider.test.ts b/src/main/providers/ssh-pty-provider.test.ts index 1555f01b0aa..8530691b159 100644 --- a/src/main/providers/ssh-pty-provider.test.ts +++ b/src/main/providers/ssh-pty-provider.test.ts @@ -17,10 +17,6 @@ describe('SshPtyProvider', () => { provider = new SshPtyProvider('conn-1', mux as never) }) - it('returns the connectionId', () => { - expect(provider.getConnectionId()).toBe('conn-1') - }) - it('reports that SSH panes cannot restore from authoritative provider snapshots', () => { expect(provider.canProvideAuthoritativeBufferSnapshot(scopedPty1)).toBe(false) }) diff --git a/src/main/ssh/ssh-channel-multiplexer.test.ts b/src/main/ssh/ssh-channel-multiplexer.test.ts index 7dc5ed8368d..5617745ed50 100644 --- a/src/main/ssh/ssh-channel-multiplexer.test.ts +++ b/src/main/ssh/ssh-channel-multiplexer.test.ts @@ -555,12 +555,6 @@ describe('SshChannelMultiplexer', () => { expect(disposeHandler).toHaveBeenCalledTimes(1) }) - it('ignores notify after dispose', () => { - mux.dispose() - mux.notify('pty.data', { id: 'pty-1', data: 'x' }) - // No writes should happen after the initial keepalive writes - }) - it('reports isDisposed correctly', () => { expect(mux.isDisposed()).toBe(false) mux.dispose() diff --git a/src/main/ssh/ssh-connection-manager-registry.test.ts b/src/main/ssh/ssh-connection-manager-registry.test.ts index 046c6f9f82c..e6a6bc24843 100644 --- a/src/main/ssh/ssh-connection-manager-registry.test.ts +++ b/src/main/ssh/ssh-connection-manager-registry.test.ts @@ -57,11 +57,6 @@ describe('SshConnectionManager', () => { expect(mgr.getConnection(target.id)).toBeUndefined() }) - it('disconnect is a no-op for unknown targets', async () => { - const mgr = new SshConnectionManager(createCallbacks()) - await mgr.disconnect('unknown') - }) - it('reuses existing connected connection for same target', async () => { const mgr = new SshConnectionManager(createCallbacks()) const target = createTarget() diff --git a/src/main/ssh/ssh-remote-platform.test.ts b/src/main/ssh/ssh-remote-platform.test.ts index 69c922dc64f..0f1f5b3cb67 100644 --- a/src/main/ssh/ssh-remote-platform.test.ts +++ b/src/main/ssh/ssh-remote-platform.test.ts @@ -1,27 +1,9 @@ -import { beforeEach, describe, expect, it, vi } from 'vitest' +import { describe, expect, it } from 'vitest' import { assertSafeRemotePathSegment, getRemoteHostPlatform, joinRemotePath } from './ssh-remote-platform' -import { detectRemoteHostPlatform } from './ssh-remote-platform-detection' -import { execCommand } from './ssh-relay-deploy-helpers' -import type { SshConnection } from './ssh-connection' - -vi.mock('./ssh-relay-deploy-helpers', () => ({ - execCommand: vi.fn() -})) - -const conn = {} as SshConnection - -function decodePowerShellCommand(command: string): string { - const match = command.match(/-EncodedCommand\s+([A-Za-z0-9+/=]+)/) - return match ? Buffer.from(match[1], 'base64').toString('utf16le') : '' -} - -beforeEach(() => { - vi.clearAllMocks() -}) describe('joinRemotePath', () => { it('joins POSIX remote paths', () => { @@ -77,33 +59,3 @@ describe('assertSafeRemotePathSegment', () => { ) }) }) - -describe('detectRemoteHostPlatform', () => { - it('uses uname when the remote is POSIX', async () => { - vi.mocked(execCommand).mockResolvedValueOnce('__ORCA_REMOTE_PLATFORM__ Darwin arm64') - - await expect(detectRemoteHostPlatform(conn)).resolves.toMatchObject({ - relayPlatform: 'darwin-arm64', - commandDialect: 'posix' - }) - }) - - it('falls back to PowerShell when uname is unavailable on Windows', async () => { - vi.mocked(execCommand) - .mockRejectedValueOnce(new Error('uname not recognized')) - .mockResolvedValueOnce('__ORCA_REMOTE_PLATFORM__ Windows AMD64') - - await expect(detectRemoteHostPlatform(conn)).resolves.toMatchObject({ - relayPlatform: 'win32-x64', - commandDialect: 'powershell', - pathFlavor: 'windows' - }) - - expect(vi.mocked(execCommand).mock.calls[1]?.[1]).toContain('powershell.exe') - const script = decodePowerShellCommand(vi.mocked(execCommand).mock.calls[1]?.[1] ?? '') - expect(script).toContain('$arch = $env:PROCESSOR_ARCHITECTURE') - expect(script).toContain('try { $runtimeArch =') - expect(script).toContain('catch {}') - expect(script).toContain('Write-Output ("`n__ORCA_REMOTE_PLATFORM__ Windows " + $arch)') - }) -}) diff --git a/src/main/ssh/ssh-system-fallback.test.ts b/src/main/ssh/ssh-system-fallback.test.ts index 3212a44b6fb..844f1dc847c 100644 --- a/src/main/ssh/ssh-system-fallback.test.ts +++ b/src/main/ssh/ssh-system-fallback.test.ts @@ -32,7 +32,6 @@ import { writeBufferViaSystemSsh, writeFileViaSystemSsh } from './ssh-system-fallback' -import { spawnSystemSshPortForward } from './system-ssh-forward-process' import { getRemoteHostPlatform } from './ssh-remote-platform' import type { SshTarget } from '../../shared/ssh-types' import type { SystemSshResolvedConfig } from './ssh-control-socket' @@ -506,36 +505,6 @@ describe('spawnSystemSsh', () => { ) }) - it('spawns port forwards before the ssh destination terminator', () => { - spawnSystemSshPortForward(createTarget({ configHost: 'fdpass-host' }), 5173, '127.0.0.1', 3000) - - const args = spawnMock.mock.calls[0][1] as string[] - const terminatorIdx = args.indexOf('--') - const forwardFlagIdx = args.indexOf('-N') - const localForwardIdx = args.indexOf('-L') - const exitOnForwardFailureIdx = args.indexOf('ExitOnForwardFailure=yes') - const standaloneControlIdx = args.indexOf('-S') - - expect(terminatorIdx).toBeGreaterThan(-1) - expect(forwardFlagIdx).toBeGreaterThan(-1) - expect(localForwardIdx).toBeGreaterThan(-1) - expect(exitOnForwardFailureIdx).toBeGreaterThan(-1) - // Why: -N and -L must appear before -- or OpenSSH treats them as remote command args. - expect(forwardFlagIdx).toBeLessThan(terminatorIdx) - expect(localForwardIdx).toBeLessThan(terminatorIdx) - expect(args[exitOnForwardFailureIdx - 1]).toBe('-o') - expect(exitOnForwardFailureIdx).toBeLessThan(terminatorIdx) - expect(standaloneControlIdx).toBe(-1) - expectNoOrcaControlMasterArgs(args) - expect(args).toContain('127.0.0.1:5173:127.0.0.1:3000') - expect(args[terminatorIdx + 1]).toBe('fdpass-host') - expect(spawnMock).toHaveBeenCalledWith( - SYSTEM_SSH_PATH, - expect.any(Array), - expect.objectContaining({ stdio: ['ignore', 'ignore', 'pipe'] }) - ) - }) - it('can spawn a native remote command without the POSIX shell wrapper', () => { spawnSystemSshCommand(createTarget({ configHost: 'fdpass-host' }), 'echo hello', { wrapCommand: false