feat: add datVerifier and tests
- Añade `datVerifier` con `parseDat` y `verifyHashesAgainstDat` - Añade tests y fixture XML para validar matching por CRC/MD5/SHA1/size - Añade `fast-xml-parser` en `backend/package.json` (devDependency)
This commit is contained in:
@@ -1,35 +1,73 @@
|
||||
import { describe, it, expect } from 'vitest';
|
||||
import path from 'path';
|
||||
import fs from 'fs';
|
||||
import { parseDat, verifyRomAgainstDat } from '../../src/services/datVerifier';
|
||||
import path from 'path';
|
||||
|
||||
const fixturesDir = path.join(__dirname, '..', 'fixtures');
|
||||
const datPath = path.join(fixturesDir, 'dats', 'sample-no-intro.dat.xml');
|
||||
const simpleRom = path.join(fixturesDir, 'simple-rom.bin');
|
||||
import { parseDat, verifyHashesAgainstDat, DatDatabase } from '../../src/services/datVerifier';
|
||||
|
||||
const FIXTURE = path.resolve('tests/fixtures/sample.dat.xml');
|
||||
|
||||
// Ejecutar siempre las pruebas de datVerifier. Dependencias externas (p.ej.
|
||||
// binarios para formatos específicos) deben estar instaladas en el entorno
|
||||
// donde se intente ejecutar las pruebas completas.
|
||||
describe('services/datVerifier', () => {
|
||||
it('parsea DAT xml', () => {
|
||||
const xml = fs.readFileSync(datPath, 'utf8');
|
||||
const parsed = parseDat(xml);
|
||||
expect(parsed).toBeDefined();
|
||||
it('parseDat parses simple DAT XML', () => {
|
||||
const xml = fs.readFileSync(FIXTURE, 'utf8');
|
||||
const dat: DatDatabase = parseDat(xml);
|
||||
|
||||
expect(dat).toBeTruthy();
|
||||
expect(Array.isArray(dat.games)).toBe(true);
|
||||
expect(dat.games.length).toBe(2);
|
||||
|
||||
const g0 = dat.games[0];
|
||||
expect(g0.name).toBe('Game Alpha');
|
||||
expect(g0.roms.length).toBeGreaterThan(0);
|
||||
expect(g0.roms[0].name).toBe('alpha1.bin');
|
||||
expect(g0.roms[0].crc).toBeDefined();
|
||||
expect(g0.roms[0].md5).toBeDefined();
|
||||
|
||||
const g1 = dat.games[1];
|
||||
expect(g1.name).toBe('Game Beta');
|
||||
expect(g1.roms.some((r) => r.name === 'beta2.rom')).toBe(true);
|
||||
});
|
||||
|
||||
it('verifica rom contra DAT', async () => {
|
||||
const stats = fs.statSync(simpleRom);
|
||||
const romMeta = {
|
||||
filename: 'simple-rom.bin',
|
||||
size: stats.size,
|
||||
md5: 'placeholder',
|
||||
sha1: 'placeholder',
|
||||
crc32: 'placeholder',
|
||||
} as any;
|
||||
it('verifyHashesAgainstDat finds match by CRC', () => {
|
||||
const xml = fs.readFileSync(FIXTURE, 'utf8');
|
||||
const dat = parseDat(xml);
|
||||
|
||||
const xml = fs.readFileSync(datPath, 'utf8');
|
||||
const parsed = parseDat(xml);
|
||||
const res = await verifyRomAgainstDat(romMeta, parsed);
|
||||
expect(res).toBeDefined();
|
||||
const match = verifyHashesAgainstDat(dat, { crc: 'DEADBEEF' });
|
||||
expect(match).not.toBeNull();
|
||||
expect(match?.gameName).toBe('Game Beta');
|
||||
expect(match?.romName).toBe('beta1.rom');
|
||||
expect(match?.matchedOn).toBe('crc');
|
||||
});
|
||||
|
||||
it('verifyHashesAgainstDat finds match by MD5, SHA1 and size', () => {
|
||||
const xml = fs.readFileSync(FIXTURE, 'utf8');
|
||||
const dat = parseDat(xml);
|
||||
|
||||
const md5match = verifyHashesAgainstDat(dat, { md5: '11111111111111111111111111111111' });
|
||||
expect(md5match).not.toBeNull();
|
||||
expect(md5match?.gameName).toBe('Game Alpha');
|
||||
expect(md5match?.romName).toBe('alpha1.bin');
|
||||
expect(md5match?.matchedOn).toBe('md5');
|
||||
|
||||
const sha1match = verifyHashesAgainstDat(dat, {
|
||||
sha1: 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb',
|
||||
});
|
||||
expect(sha1match).not.toBeNull();
|
||||
expect(sha1match?.gameName).toBe('Game Alpha');
|
||||
expect(sha1match?.romName).toBe('alpha2.bin');
|
||||
expect(sha1match?.matchedOn).toBe('sha1');
|
||||
|
||||
const sizematch = verifyHashesAgainstDat(dat, { size: 4000 });
|
||||
expect(sizematch).not.toBeNull();
|
||||
expect(sizematch?.gameName).toBe('Game Beta');
|
||||
expect(sizematch?.romName).toBe('beta2.rom');
|
||||
expect(sizematch?.matchedOn).toBe('size');
|
||||
});
|
||||
|
||||
it('verifyHashesAgainstDat returns null when no match', () => {
|
||||
const xml = fs.readFileSync(FIXTURE, 'utf8');
|
||||
const dat = parseDat(xml);
|
||||
|
||||
const noMatch = verifyHashesAgainstDat(dat, { md5: 'ffffffffffffffffffffffffffffffff' });
|
||||
expect(noMatch).toBeNull();
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user