- Añade `computeHashesFromStream` para hashing desde streams - Añade `streamArchiveEntry` e integra en `importDirectory` (path codificado con ::) - Extiende `scanDirectory` para exponer entradas internas, normaliza rutas POSIX y evita traversal; `ARCHIVE_MAX_ENTRIES` configurable - Limpia listeners en hashing y mejora robustez/logging - Añade tests unitarios e integración; actualiza mocks a `Mock` types - CI: instala `unzip` junto a `p7zip` para soportar tests de integración
55 lines
1.8 KiB
TypeScript
55 lines
1.8 KiB
TypeScript
import { test, expect } from 'vitest';
|
|
import { promises as fs } from 'fs';
|
|
import path from 'path';
|
|
import { execSync } from 'child_process';
|
|
import { computeHashesFromStream } from '../../src/services/checksumService';
|
|
import { streamArchiveEntry } from '../../src/services/archiveReader';
|
|
import { createHash } from 'crypto';
|
|
|
|
function hasBinary(bin: string): boolean {
|
|
try {
|
|
execSync(`which ${bin}`, { stdio: 'ignore' });
|
|
return true;
|
|
} catch (e) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
const wantIntegration = process.env.INTEGRATION === '1';
|
|
const canCreate = hasBinary('7z') || hasBinary('zip');
|
|
|
|
if (!wantIntegration) {
|
|
test.skip('archiveReader integration tests require INTEGRATION=1', () => {});
|
|
} else if (!canCreate) {
|
|
test.skip('archiveReader integration tests skipped: no archive creation tool (7z or zip) available', () => {});
|
|
} else {
|
|
test('reads entry from zip using system tools', async () => {
|
|
const tmpDir = await fs.mkdtemp(path.join(process.cwd(), 'tmp-arc-'));
|
|
const inner = path.join(tmpDir, 'game.rom');
|
|
const content = 'QUASAR-INTEGRATION-TEST';
|
|
await fs.writeFile(inner, content);
|
|
|
|
const archivePath = path.join(tmpDir, 'simple.zip');
|
|
|
|
// create zip using available tool
|
|
if (hasBinary('7z')) {
|
|
execSync(`7z a -tzip ${JSON.stringify(archivePath)} ${JSON.stringify(inner)}`, {
|
|
stdio: 'ignore',
|
|
});
|
|
} else {
|
|
execSync(`zip -j ${JSON.stringify(archivePath)} ${JSON.stringify(inner)}`, {
|
|
stdio: 'ignore',
|
|
});
|
|
}
|
|
|
|
const stream = await streamArchiveEntry(archivePath, path.basename(inner));
|
|
expect(stream).not.toBeNull();
|
|
const hashes = await computeHashesFromStream(stream as any);
|
|
|
|
const expectedMd5 = createHash('md5').update(content).digest('hex');
|
|
expect(hashes.md5).toBe(expectedMd5);
|
|
|
|
await fs.rm(tmpDir, { recursive: true, force: true });
|
|
});
|
|
}
|