Hash every validated server copy and register it as verified content
This commit is contained in:
@@ -10,6 +10,8 @@ const root = mkdtempSync(join(tmpdir(), 'ytp-media-test-'));
|
||||
process.env.DB_PATH = join(root, 'test.db');
|
||||
const dbmod = await import('./db.js');
|
||||
const { createMediaCache, validateMedia, MediaSkip, HIGH, LOW, OPT_REV } = await import('./media-cache.js');
|
||||
const { initP2pSchema } = await import('./p2p-db.js');
|
||||
const { sha256File } = await import('./hash.js');
|
||||
|
||||
const fx = (name) => join(root, name);
|
||||
const ff = (...args) => {
|
||||
@@ -26,6 +28,7 @@ async function until(fn, ms = 20000) {
|
||||
|
||||
beforeAll(async () => {
|
||||
await dbmod.initDb();
|
||||
await initP2pSchema(); // adds media_cache.sha256
|
||||
// 10 s 640x360 H.264 + AAC — the shape of a good cached copy.
|
||||
ff('-f', 'lavfi', '-i', 'testsrc=size=640x360:rate=30:duration=10', '-f', 'lavfi', '-i', 'sine=frequency=440:duration=10',
|
||||
'-c:v', 'libx264', '-preset', 'ultrafast', '-pix_fmt', 'yuv420p', '-c:a', 'aac', '-shortest', fx('good.mp4'));
|
||||
@@ -102,6 +105,7 @@ function makeCache({ fixture = 'good.mp4', duration = 10, ...opts } = {}) {
|
||||
download: async (id, out) => { calls.push(id); await sleep(30); copyFileSync(fx(state.fixture), out); return out; },
|
||||
transcode: { enabled: false },
|
||||
freeBytes: () => 100 * 1024 ** 3,
|
||||
backfillDelayMs: -1,
|
||||
...opts,
|
||||
});
|
||||
return { cache, dir, calls, state };
|
||||
@@ -110,6 +114,35 @@ async function clearDb() {
|
||||
for (const r of await dbmod.listMedia()) await dbmod.deleteMedia(r.video_id);
|
||||
}
|
||||
|
||||
describe('content hashes (P2P cids)', () => {
|
||||
test('a promoted copy stores the sha256 of its mp4 and reports it once', async () => {
|
||||
await clearDb();
|
||||
const seen = [];
|
||||
const { cache, dir } = makeCache({ onReady: (i) => { seen.push(i); } });
|
||||
await cache.init();
|
||||
const row = await cache.ensureCached('hashAAAAAA1', { priority: HIGH });
|
||||
const want = await sha256File(join(dir, `hashAAAAAA1.${row.gen}.mp4`));
|
||||
expect((await dbmod.getMedia('hashAAAAAA1')).sha256).toBe(want);
|
||||
expect(await until(() => seen.length === 1)).toBe(true);
|
||||
expect(seen[0]).toMatchObject({ id: 'hashAAAAAA1', gen: row.gen, sha256: want, vcodec: 'h264' });
|
||||
expect(seen[0].meta.title).toBe('T hashAAAAAA1');
|
||||
});
|
||||
|
||||
test('backfill hashes ready copies that have no sha256 yet', async () => {
|
||||
await clearDb();
|
||||
const seen = [];
|
||||
const { cache } = makeCache({ onReady: (i) => { seen.push(i); } });
|
||||
await cache.init();
|
||||
await cache.ensureCached('hashAAAAAA2', { priority: HIGH });
|
||||
await dbmod.upsertMedia('hashAAAAAA2', { sha256: null });
|
||||
seen.length = 0;
|
||||
expect(await cache.backfillHashes()).toBe(1);
|
||||
expect((await dbmod.getMedia('hashAAAAAA2')).sha256).toMatch(/^[0-9a-f]{64}$/);
|
||||
expect(await until(() => seen.length === 1)).toBe(true);
|
||||
expect(await cache.backfillHashes()).toBe(0); // nothing left
|
||||
});
|
||||
});
|
||||
|
||||
describe('media cache jobs', () => {
|
||||
test('fetches once, dedupes concurrent requests, then serves from disk', async () => {
|
||||
await clearDb();
|
||||
|
||||
Reference in New Issue
Block a user