OverviewFilesCommitsIssuesDocsReleasesPeers

hyper-note / test / unit / media-gc.test.js

115 lines · javascript ref:
import test from 'brittle'
import Corestore from 'corestore'
import path from 'bare-path'
import fs from 'bare-fs'
import os from 'bare-os'
import { MediaStore } from '../../lib/media-store.js'

function tmpdir () {
  const dir = path.join(os.tmpdir(), 'hn-gc-test-' + Date.now() + '-' + Math.random().toString(36).slice(2))
  fs.mkdirSync(dir, { recursive: true })
  return dir
}

function rmrf (dir) {
  try { fs.rmSync(dir, { recursive: true, force: true }) } catch {}
}

test('GC - scheduleOrphan clears blob after grace period', async (t) => {
  const dir = tmpdir()
  try {
    const store = new Corestore(dir)
    const media = new MediaStore(store, {
      graceMs: 100,
      isReferencedAnywhere: async () => false
    })
    await media.ready()

    const buf = Buffer.from('orphan data')
    const hash = await media.put(buf, 'text/plain')
    t.is(await media.has(hash), true)

    media.scheduleOrphan(hash)

    // Wait for grace period + buffer
    await new Promise(r => setTimeout(r, 250))

    t.is(await media.has(hash), false)
  } finally {
    rmrf(dir)
  }
})

test('GC - cancelOrphan prevents deletion', async (t) => {
  const dir = tmpdir()
  try {
    const store = new Corestore(dir)
    const media = new MediaStore(store, {
      graceMs: 200,
      isReferencedAnywhere: async () => false
    })
    await media.ready()

    const buf = Buffer.from('rescued data')
    const hash = await media.put(buf, 'text/plain')

    media.scheduleOrphan(hash)

    // Cancel before grace period
    await new Promise(r => setTimeout(r, 50))
    media.cancelOrphan(hash)

    // Wait past original grace period
    await new Promise(r => setTimeout(r, 300))

    t.is(await media.has(hash), true)
  } finally {
    rmrf(dir)
  }
})

test('GC - scheduleOrphan skips if still referenced', async (t) => {
  const dir = tmpdir()
  try {
    const store = new Corestore(dir)
    const media = new MediaStore(store, {
      graceMs: 100,
      isReferencedAnywhere: async () => true
    })
    await media.ready()

    const buf = Buffer.from('still in use')
    const hash = await media.put(buf, 'text/plain')

    media.scheduleOrphan(hash)
    await new Promise(r => setTimeout(r, 250))

    t.is(await media.has(hash), true)
  } finally {
    rmrf(dir)
  }
})

test('GC - duplicate scheduleOrphan is idempotent', async (t) => {
  const dir = tmpdir()
  try {
    const store = new Corestore(dir)
    const media = new MediaStore(store, {
      graceMs: 100,
      isReferencedAnywhere: async () => false
    })
    await media.ready()

    const buf = Buffer.from('double schedule')
    const hash = await media.put(buf, 'text/plain')

    media.scheduleOrphan(hash)
    media.scheduleOrphan(hash)

    await new Promise(r => setTimeout(r, 250))
    t.is(await media.has(hash), false)
  } finally {
    rmrf(dir)
  }
})