OverviewFilesCommitsIssuesDocsReleasesPeers

P2P-Hiverelay / packages / blind-ipc / test / framing-vectors.test.js

130 lines · javascript ref:
import test from 'brittle'
import fs from 'node:fs/promises'
import path from 'node:path'
import { fileURLToPath } from 'node:url'
import b4a from 'b4a'
import { decodeVectorManifest } from '@hiverelay/blind-protocol'
import {
  PRIVATE_IPC_VECTOR_OUTCOME,
  PRIVATE_IPC_VECTOR_PARSER,
  LocalStreamSequenceGuard,
  decodeLocalRequest,
  decodeLocalResponse,
  decodeLocalStreamFrame,
  decodeLocalStreamOpen,
  decodePrivateIpcFramingVector,
  encodePrivateIpcFramingVector,
  localRequestFrameLength,
  localResponseFrameLength,
  localStreamFrameLength,
  localStreamOpenFrameLength
} from '../index.js'

const packageRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..')

function append (left, right) {
  return left.byteLength === 0 ? b4a.from(right) : b4a.concat([left, right])
}

function runSingleItemScenario (scenario, frameLength, decode) {
  let buffer = b4a.alloc(0)
  let itemCount = 0
  let complete = false
  for (const chunk of scenario.chunks) {
    if (complete) throw new Error('single-item private IPC connection received another chunk')
    buffer = append(buffer, chunk)
    const expected = frameLength(buffer)
    if (expected == null || buffer.byteLength < expected) continue
    if (buffer.byteLength !== expected) throw new Error('single-item private IPC connection has trailing bytes')
    decode(buffer)
    itemCount++
    complete = true
    buffer = b4a.alloc(0)
  }
  if (!complete || buffer.byteLength !== 0) throw new Error('single-item private IPC connection ended truncated')
  return itemCount
}

function runStreamFrameScenario (scenario) {
  let buffer = b4a.alloc(0)
  let itemCount = 0
  const guard = new LocalStreamSequenceGuard()
  for (const chunk of scenario.chunks) {
    buffer = append(buffer, chunk)
    for (;;) {
      const expected = localStreamFrameLength(buffer)
      if (expected == null || buffer.byteLength < expected) break
      const frame = decodeLocalStreamFrame(buffer.subarray(0, expected))
      buffer = b4a.from(buffer.subarray(expected))
      guard.accept(frame)
      itemCount++
    }
  }
  if (buffer.byteLength !== 0) throw new Error('private IPC stream ended with a truncated frame')
  return itemCount
}

function runScenario (scenario) {
  if (scenario.parser === PRIVATE_IPC_VECTOR_PARSER.LOCAL_REQUEST) {
    return runSingleItemScenario(scenario, localRequestFrameLength, decodeLocalRequest)
  }
  if (scenario.parser === PRIVATE_IPC_VECTOR_PARSER.LOCAL_RESPONSE) {
    return runSingleItemScenario(scenario, localResponseFrameLength, decodeLocalResponse)
  }
  if (scenario.parser === PRIVATE_IPC_VECTOR_PARSER.LOCAL_STREAM_OPEN) {
    return runSingleItemScenario(scenario, localStreamOpenFrameLength, decodeLocalStreamOpen)
  }
  return runStreamFrameScenario(scenario)
}

test('manifest-bound private IPC framing vectors execute their exact accept/reject outcomes', async t => {
  const manifest = decodeVectorManifest(await fs.readFile(path.join(packageRoot, 'vector-manifest-v1.cenc')))
  const entries = manifest.filter(entry => entry.path.startsWith('framing/'))
  t.is(entries.length, 44)
  let accepted = 0
  let rejected = 0
  for (const entry of entries) {
    const bytes = await fs.readFile(path.join(packageRoot, 'vectors', ...entry.path.split('/')))
    const scenario = decodePrivateIpcFramingVector(bytes)
    let result = null
    let error = null
    try {
      result = runScenario(scenario)
    } catch (cause) {
      error = cause
    }
    if (scenario.outcome === PRIVATE_IPC_VECTOR_OUTCOME.ACCEPT) {
      t.is(error, null, `${entry.path} accepts`)
      t.is(result, scenario.expectedItemCount, `${entry.path} item count`)
      accepted++
    } else {
      t.ok(error, `${entry.path} rejects`)
      rejected++
    }
  }
  t.is(accepted, 11)
  t.is(rejected, 33)
})

test('private IPC framing-vector container is canonical, bounded and snapshots input', t => {
  const encoded = encodePrivateIpcFramingVector({
    parser: PRIVATE_IPC_VECTOR_PARSER.LOCAL_STREAM_FRAMES,
    outcome: PRIVATE_IPC_VECTOR_OUTCOME.ACCEPT,
    expectedItemCount: 1,
    chunks: [b4a.from([1, 2, 3])]
  })
  const source = b4a.from(encoded)
  const decoded = decodePrivateIpcFramingVector(source)
  source.fill(0)
  t.alike([...decoded.chunks[0]], [1, 2, 3])
  t.ok(b4a.equals(encodePrivateIpcFramingVector(decoded), encoded))
  t.exception(() => decodePrivateIpcFramingVector(encoded.subarray(0, encoded.byteLength - 1)))
  t.exception(() => decodePrivateIpcFramingVector(b4a.concat([encoded, b4a.from([0])])), /trailing/)
  t.exception(() => encodePrivateIpcFramingVector({
    parser: PRIVATE_IPC_VECTOR_PARSER.LOCAL_REQUEST,
    outcome: PRIVATE_IPC_VECTOR_OUTCOME.REJECT,
    expectedItemCount: 1,
    chunks: [b4a.from([1])]
  }), /reject vectors require zero/)
})