103 lines
3.3 KiB
TypeScript
103 lines
3.3 KiB
TypeScript
import assert from 'node:assert/strict';
|
|
import fs from 'node:fs';
|
|
import os from 'node:os';
|
|
import path from 'node:path';
|
|
import test from 'node:test';
|
|
|
|
import UploadSessionManager from '../src/services/file/UploadSessionManager.ts';
|
|
|
|
function makeSessionManager(ttlMs = 60_000): {
|
|
manager: UploadSessionManager;
|
|
rootDir: string;
|
|
} {
|
|
const rootDir = fs.mkdtempSync(path.join(os.tmpdir(), 'upload-sessions-'));
|
|
return {
|
|
manager: new UploadSessionManager({ sessionDir: rootDir, ttlMs }),
|
|
rootDir,
|
|
};
|
|
}
|
|
|
|
void test('UploadSessionManager creates metadata and tracks uploaded chunks', async () => {
|
|
const { manager, rootDir } = makeSessionManager();
|
|
try {
|
|
const sessionId = manager.createSession({
|
|
filename: 'tour.mp4',
|
|
folder: 'assets',
|
|
totalChunks: 2,
|
|
totalSize: 11,
|
|
userId: 'user-1',
|
|
contentType: 'video/mp4',
|
|
});
|
|
|
|
let meta = manager.readMeta(sessionId);
|
|
assert.equal(meta?.filename, 'tour.mp4');
|
|
assert.equal(meta?.uploadedChunks !== undefined, true);
|
|
assert.equal(manager.isComplete(sessionId), false);
|
|
|
|
await manager.saveChunk(sessionId, 0, Buffer.from('hello '));
|
|
await manager.saveChunk(sessionId, 1, Buffer.from('world'));
|
|
|
|
meta = manager.readMeta(sessionId);
|
|
assert.equal(meta?.uploadedChunks[0]?.size, 6);
|
|
assert.equal(meta?.uploadedChunks[1]?.size, 5);
|
|
assert.equal(manager.chunkExists(sessionId, 0), true);
|
|
assert.equal(manager.isComplete(sessionId), true);
|
|
} finally {
|
|
fs.rmSync(rootDir, { recursive: true, force: true });
|
|
}
|
|
});
|
|
|
|
void test('UploadSessionManager assembles chunks in index order', async () => {
|
|
const { manager, rootDir } = makeSessionManager();
|
|
try {
|
|
const sessionId = manager.createSession({
|
|
filename: 'image.bin',
|
|
folder: 'assets',
|
|
totalChunks: 3,
|
|
totalSize: 9,
|
|
});
|
|
await manager.saveChunk(sessionId, 2, Buffer.from('ghi'));
|
|
await manager.saveChunk(sessionId, 0, Buffer.from('abc'));
|
|
await manager.saveChunk(sessionId, 1, Buffer.from('def'));
|
|
|
|
const targetPath = path.join(rootDir, 'assembled', 'image.bin');
|
|
await manager.assembleChunks(sessionId, targetPath);
|
|
|
|
assert.equal(fs.readFileSync(targetPath, 'utf8'), 'abcdefghi');
|
|
} finally {
|
|
fs.rmSync(rootDir, { recursive: true, force: true });
|
|
}
|
|
});
|
|
|
|
void test('UploadSessionManager removes expired and invalid sessions during cleanup', () => {
|
|
const { manager, rootDir } = makeSessionManager(1);
|
|
try {
|
|
const expiredSessionId = manager.createSession({
|
|
filename: 'expired.txt',
|
|
folder: 'assets',
|
|
totalChunks: 1,
|
|
totalSize: 1,
|
|
});
|
|
const meta = manager.readMeta(expiredSessionId);
|
|
assert.ok(meta);
|
|
meta.updatedAt = new Date(Date.now() - 10_000).toISOString();
|
|
manager.writeMeta(expiredSessionId, meta);
|
|
|
|
const invalidSessionId = 'invalid-session';
|
|
const invalidSessionDir = manager.getSessionDir(invalidSessionId);
|
|
fs.mkdirSync(invalidSessionDir, { recursive: true });
|
|
fs.writeFileSync(
|
|
manager.getMetaPath(invalidSessionId),
|
|
JSON.stringify({ sessionId: invalidSessionId }),
|
|
'utf8',
|
|
);
|
|
|
|
manager.cleanupExpiredSessions();
|
|
|
|
assert.equal(fs.existsSync(manager.getSessionDir(expiredSessionId)), false);
|
|
assert.equal(fs.existsSync(invalidSessionDir), false);
|
|
} finally {
|
|
fs.rmSync(rootDir, { recursive: true, force: true });
|
|
}
|
|
});
|