OverviewFilesCommitsIssuesDocsReleasesPeers

hyper-proto-peer / test / upload-blob-path-uds.test.mjs

71 lines · javascript ref:
// upload-blob over the UDS accepts a PATH as well as hex bytes.
//
// favela-bridge (lib/bsky.js uploadBlob) hands hpp a picture BY PATH — both ends share one machine, and
// hex-encoding it doubles the transfer and needs a buffer library the client may not have. Until this
// handler took `path`, every such upload failed with "bytes (hex) required" and the bridge logged
// blob-upload-failed and posted without the image.
//
// The socket is 0775 fleeky:fleeky: only the daemon's own user can connect, so reading a path grants no
// access that caller does not already have.
//
// Run: bare test/upload-blob-path-uds.test.mjs
import { serveDeviceUds } from '../lib/serve-device-uds.js'
import { Client } from 'hyper-svc'
import b4a from 'b4a'
import fs from 'bare-fs'
import process from 'bare-process'
import { join } from 'bare-path'

const assert = (cond, msg) => { if (!cond) { console.error('FAIL:', msg); process.exit(1) } console.log('  ok -', msg) }
const tmp = join(process.env.TMPDIR || '/tmp', 'hpp-upload-path-' + process.pid)
fs.mkdirSync(tmp, { recursive: true })

// The handler is only registered when a blob store is passed; a stub records exactly what it was given.
const stored = []
const blobs = {
  async put (buf, mimeType) { stored.push({ buf, mimeType }); return { cid: 'bafystub' + stored.length, size: buf.length } }
}
const device = { state: () => ({ ok: true }), membersDiag: async () => ({}), did: 'did:plc:test' }

const sock = join(tmp, 'u.sock')
const served = await serveDeviceUds(device, { uds: sock, blobs })
const c = await Client.connectUds(sock)
const rejects = async (params) => { try { await c.call('upload-blob', params); return null } catch (e) { return e.message } }

console.log('# a path uploads the file\'s exact bytes')
{
  const file = join(tmp, 'pic.png')
  const bytes = b4a.from('not really a png, but exact bytes are the point')
  fs.writeFileSync(file, bytes)
  const r = await c.call('upload-blob', { path: file, mimeType: 'image/png' })
  assert(r && r.cid === 'bafystub1', 'upload-blob by path returns the store\'s CID')
  assert(r.size === bytes.length && r.mimeType === 'image/png', 'size and mimeType are what was stored')
  assert(b4a.equals(stored[0].buf, bytes), 'the store received the file\'s bytes, unchanged')
}

console.log('\n# hex bytes still work — a remote client has no path to offer')
{
  const bytes = b4a.from('bytes over the wire')
  const r = await c.call('upload-blob', { bytes: b4a.toString(bytes, 'hex'), mimeType: 'image/jpeg' })
  assert(r && r.size === bytes.length, 'upload-blob by bytes still stores them')
  assert(b4a.equals(stored[1].buf, bytes), 'and they decode exactly')
}

console.log('\n# failures say what is wrong, and store nothing')
{
  const before = stored.length
  const missing = await rejects({ path: join(tmp, 'nope.png') })
  assert(missing && /no file at/.test(missing), `a missing path is named (${missing})`)
  const empty = join(tmp, 'empty.png'); fs.writeFileSync(empty, b4a.alloc(0))
  const e2 = await rejects({ path: empty })
  assert(e2 && /empty/.test(e2), `an empty file is refused (${e2})`)
  const e3 = await rejects({})
  assert(e3 && /bytes \(hex\) or path required/.test(e3), `neither bytes nor path is refused (${e3})`)
  assert(stored.length === before, 'no failed call reached the store')
}

try { await c.close() } catch {}
try { await served.close() } catch {}
fs.rmSync(tmp, { recursive: true, force: true })
console.log('\nupload-blob path: all assertions passed')