Files
orca/src/shared/terminal-stream-protocol.test.ts
T
NeilandOrca 879aad7dd6 oom(foundation): bound shared readers/limits + add BoundedMap primitive (#10299)
* oom(01): A1-shared-readers — reintroduce #10179 subset

Files: 18 applied, 0 deleted (from 6eb70d8370)

Co-authored-by: Orca <help@stably.ai>

* oom(02): A2-shared-image-media — reintroduce #10179 subset

Files: 7 applied, 0 deleted (from 6eb70d8370)

Co-authored-by: Orca <help@stably.ai>

* oom(03): A3-shared-fs-listing — reintroduce #10179 subset

Files: 21 applied, 0 deleted (from 6eb70d8370)

Co-authored-by: Orca <help@stably.ai>

* oom(04): A4-shared-remote-relay — reintroduce #10179 subset

Files: 8 applied, 0 deleted (from 6eb70d8370)

Co-authored-by: Orca <help@stably.ai>

* oom(05): A5-shared-misc — reintroduce #10179 subset

Files: 28 applied, 0 deleted (from 6eb70d8370)

Co-authored-by: Orca <help@stably.ai>

* oom(06): B-shared-wiring — reintroduce #10179 subset

Files: 81 applied, 0 deleted (from 6eb70d8370)

Co-authored-by: Orca <help@stably.ai>

---------

Co-authored-by: Orca <help@stably.ai>
2026-07-24 21:36:57 -07:00

172 lines
5.3 KiB
TypeScript

import { describe, expect, it, vi } from 'vitest'
import {
TerminalStreamOpcode,
decodeTerminalStreamFrame,
decodeTerminalStreamJson,
decodeTerminalStreamText,
encodeTerminalStreamFrame,
encodeTerminalStreamJson,
encodeTerminalStreamText,
TERMINAL_STREAM_JSON_STRUCTURE_LIMITS
} from './terminal-stream-protocol'
describe('terminal-stream-protocol', () => {
it('round-trips fixed-width binary frame headers and payloads', () => {
const payload = encodeTerminalStreamText('hello terminal')
const encoded = encodeTerminalStreamFrame({
opcode: TerminalStreamOpcode.Output,
streamId: 42,
seq: 9,
payload
})
const decoded = decodeTerminalStreamFrame(encoded)
expect(decoded?.opcode).toBe(TerminalStreamOpcode.Output)
expect(decoded?.streamId).toBe(42)
expect(decoded?.seq).toBe(9)
expect(decoded ? decodeTerminalStreamText(decoded.payload) : '').toBe('hello terminal')
})
it('round-trips snapshot metadata JSON payloads', () => {
const encoded = encodeTerminalStreamFrame({
opcode: TerminalStreamOpcode.SnapshotStart,
streamId: 7,
seq: 1,
payload: encodeTerminalStreamJson({ kind: 'scrollback', cols: 49, rows: 28 })
})
const decoded = decodeTerminalStreamFrame(encoded)
expect(decoded && decodeTerminalStreamJson(decoded.payload)).toEqual({
kind: 'scrollback',
cols: 49,
rows: 28
})
})
it('round-trips terminal input and resize frames', () => {
const input = decodeTerminalStreamFrame(
encodeTerminalStreamFrame({
opcode: TerminalStreamOpcode.Input,
streamId: 11,
seq: 1,
payload: encodeTerminalStreamText('a')
})
)
const resize = decodeTerminalStreamFrame(
encodeTerminalStreamFrame({
opcode: TerminalStreamOpcode.Resize,
streamId: 11,
seq: 2,
payload: encodeTerminalStreamJson({ cols: 120, rows: 40 })
})
)
expect(input?.opcode).toBe(TerminalStreamOpcode.Input)
expect(input ? decodeTerminalStreamText(input.payload) : '').toBe('a')
expect(resize?.opcode).toBe(TerminalStreamOpcode.Resize)
expect(resize && decodeTerminalStreamJson(resize.payload)).toEqual({ cols: 120, rows: 40 })
})
it('round-trips terminal metadata frames', () => {
const metadata = decodeTerminalStreamFrame(
encodeTerminalStreamFrame({
opcode: TerminalStreamOpcode.Metadata,
streamId: 11,
seq: 4,
payload: encodeTerminalStreamJson({ cwd: '/repo/src' })
})
)
expect(metadata?.opcode).toBe(TerminalStreamOpcode.Metadata)
expect(metadata && decodeTerminalStreamJson(metadata.payload)).toEqual({ cwd: '/repo/src' })
})
it('round-trips multiplex subscribe, snapshot request, and unsubscribe frames', () => {
const subscribe = decodeTerminalStreamFrame(
encodeTerminalStreamFrame({
opcode: TerminalStreamOpcode.Subscribe,
streamId: 0,
seq: 1,
payload: encodeTerminalStreamJson({
streamId: 12,
terminal: 'terminal-1',
viewport: { cols: 120, rows: 40 }
})
})
)
const unsubscribe = decodeTerminalStreamFrame(
encodeTerminalStreamFrame({
opcode: TerminalStreamOpcode.Unsubscribe,
streamId: 12,
seq: 2,
payload: new Uint8Array()
})
)
const snapshotRequest = decodeTerminalStreamFrame(
encodeTerminalStreamFrame({
opcode: TerminalStreamOpcode.SnapshotRequest,
streamId: 12,
seq: 3,
payload: new Uint8Array()
})
)
expect(subscribe?.opcode).toBe(TerminalStreamOpcode.Subscribe)
expect(subscribe && decodeTerminalStreamJson(subscribe.payload)).toMatchObject({
streamId: 12,
terminal: 'terminal-1'
})
expect(snapshotRequest?.opcode).toBe(TerminalStreamOpcode.SnapshotRequest)
expect(snapshotRequest?.streamId).toBe(12)
expect(unsubscribe?.opcode).toBe(TerminalStreamOpcode.Unsubscribe)
expect(unsubscribe?.streamId).toBe(12)
})
it('round-trips output acknowledgement frames', () => {
const ack = decodeTerminalStreamFrame(
encodeTerminalStreamFrame({
opcode: TerminalStreamOpcode.Ack,
streamId: 12,
seq: 4,
payload: encodeTerminalStreamJson({ bytes: 4096 })
})
)
expect(ack?.opcode).toBe(TerminalStreamOpcode.Ack)
expect(ack?.streamId).toBe(12)
expect(ack && decodeTerminalStreamJson(ack.payload)).toEqual({ bytes: 4096 })
})
it('rejects excessive JSON nesting before JSON.parse', () => {
const parseSpy = vi.spyOn(JSON, 'parse')
try {
const depth = TERMINAL_STREAM_JSON_STRUCTURE_LIMITS.nestingDepth + 1
const payload = new TextEncoder().encode(`${'['.repeat(depth)}0${']'.repeat(depth)}`)
expect(decodeTerminalStreamJson(payload)).toBeNull()
expect(parseSpy).not.toHaveBeenCalled()
} finally {
parseSpy.mockRestore()
}
})
it('rejects unknown frame versions and opcodes', () => {
const encoded = encodeTerminalStreamFrame({
opcode: TerminalStreamOpcode.Output,
streamId: 1,
seq: 1,
payload: new Uint8Array()
})
const badVersion = encoded.slice()
badVersion[1] = 99
expect(decodeTerminalStreamFrame(badVersion)).toBeNull()
const badOpcode = encoded.slice()
badOpcode[2] = 99
expect(decodeTerminalStreamFrame(badOpcode)).toBeNull()
})
})