// Controlul negativ al probei de cost (test/proba-timp.mjs): proba trebuie sa iasa ROSIE pe cazul numit cand forma patratica e // pusa inapoi. Trei stari pe caz: PRINS (proba a masurat si cazul tinta e ROSU), SCAPAT (a ramas VERDE), STRICAT (copia nu s-a // putut face, ancora nu apare exact o data, sau proba nu a masurat). // V0 inventarul de dinainte de reparatie, din git (sarit si spus daca revizia nu e in istoricul depozitului) // -> rosii: pem, py-triplu, js-regex, js-linie, java-linie, java-kpg // P1 rezolvarea variabilelor fara memorie (fiecare apel reciteste fisierul) -> js-linie rosu // P2 esecurile literalului regex JS netinute minte -> js-regex rosu // P3 cautarea PEM fara pozitiile tinute minte (sfarsitul cautat de la fiecare antet) -> pem rosu // node test/control-negativ-timp.mjs -> 0 toate prinse, 1 unul scapat, 2 STRICAT import { mkdtempSync, cpSync, readFileSync, writeFileSync, readdirSync, rmSync, mkdirSync } from 'node:fs'; import { join, dirname } from 'node:path'; import { fileURLToPath } from 'node:url'; import { spawnSync } from 'node:child_process'; import { tmpdir } from 'node:os'; const AICI = dirname(fileURLToPath(import.meta.url)); const RADACINA = join(AICI, '..'); const PROBA = join(AICI, 'proba-timp.mjs'); const REV = process.env.AERE_INV_REV_VECHE || 'db9d9543'; let prinse = 0, stricate = 0, total = 0; const copiaza = () => { const d = mkdtempSync(join(tmpdir(), 'ci-timp-control-')); cpSync(join(RADACINA, 'inventar.mjs'), join(d, 'inventar.mjs')); cpSync(join(RADACINA, 'lib'), join(d, 'lib'), { recursive: true }); return d; }; function ruleaza(id, d, tinte, doar) { const r = spawnSync(process.execPath, [PROBA, ...(doar ? ['--doar', doar.join(',')] : [])], { encoding: 'utf8', timeout: 600000, env: { ...process.env, CRYPTO_INVENTORY_MODULE: join(d, 'inventar.mjs') } }); const out = r.stdout || ''; if (!out.includes(`(modul: ${join(d, 'inventar.mjs')})`) || /^STRICAT/m.test(out)) { stricate++; console.log(` STRICAT ${id}: proba nu a masurat copia (cod ${r.status}) ${out.split('\n').filter((l) => /^STRICAT/.test(l)).join(' | ').slice(0, 160)}`); return; } const rosii = out.split('\n').filter((l) => /^ROSU/.test(l)).map((l) => l.split(/\s+/)[1].replace(/:$/, '')); const lipsa = tinte.filter((t) => !rosii.includes(t)); if (r.status === 1 && !lipsa.length) { prinse++; console.log(` PRINS ${id}: rosii ${rosii.join(', ')}`); } else console.log(` SCAPAT ${id}: cod ${r.status}, au ramas verzi: ${lipsa.join(', ')}`); } // V0: codul de dinainte, din git, in forma comisa (fara conversia capetelor de rand) total++; const git = (...a) => spawnSync('git', ['-c', 'core.autocrlf=false', ...a], { cwd: RADACINA, encoding: 'buffer', maxBuffer: 64 << 20 }); const ls = git('ls-tree', '-r', '--name-only', '--full-tree', REV, 'tools/crypto-inventory/inventar.mjs', 'tools/crypto-inventory/lib'); const fisiere = ls.status === 0 ? ls.stdout.toString().split('\n').filter(Boolean) : []; if (!fisiere.length) { total--; console.log(` SARIT V0: revizia ${REV} nu e in istoricul acestui depozit; NEMASURAT aici`); } else { const d = mkdtempSync(join(tmpdir(), 'ci-timp-v0-')); try { let ok = true; for (const f of fisiere) { const b = git('show', `${REV}:${f}`); if (b.status !== 0) { ok = false; break; } const t = join(d, f.slice('tools/crypto-inventory/'.length)); mkdirSync(dirname(t), { recursive: true }); writeFileSync(t, b.stdout); } if (!ok || readFileSync(join(d, 'lib', 'pem.mjs'), 'utf8').includes('blocuriPem')) { stricate++; console.log(' STRICAT V0: revizia veche nu se citeste sau are deja reparatia'); } else ruleaza('V0', d, ['pem.txt', 'py-triplu.py', 'js-regex.js', 'js-linie.js', 'java-linie.java', 'java-kpg.java']); } finally { rmSync(d, { recursive: true, force: true }); } } const P = [ ['P1', 'lib/context.mjs', 'if (ctx.rezolvari.has(nume)) return ctx.rezolvari.get(nume);', "if (ctx.rezolvari.has(nume) && process.env.AERE_PLANTA_NICIODATA === 'da') return ctx.rezolvari.get(nume);", ['js-linie.js']], ['P2', 'lib/lexer.mjs', 'if (esecRegex && esecRegex[j] & (inClasa ? 2 : 1)) break;', "if (esecRegex && esecRegex[j] & (inClasa ? 2 : 1) && process.env.AERE_PLANTA_NICIODATA === 'da') break;", ['js-regex.js']], ['P3', 'lib/pem.mjs', 'const valabil = (c, de) => c && c.la <= de && (c.poz < 0 || c.poz >= de);', "const valabil = (c, de) => process.env.AERE_PLANTA_NICIODATA === 'da' && c && c.la <= de && (c.poz < 0 || c.poz >= de);", ['pem.txt']], ]; for (const [id, fisier, ancora, cu, tinte] of P) { total++; const d = copiaza(); try { const cale = join(d, fisier); const text = readFileSync(cale, 'utf8'); if (text.split(ancora).length !== 2) { stricate++; console.log(` STRICAT ${id}: ancora nu apare exact o data in ${fisier}`); continue; } writeFileSync(cale, text.replace(ancora, cu)); const dif = ['inventar.mjs', ...readdirSync(join(d, 'lib')).map((f) => `lib/${f}`)].filter((f) => readFileSync(join(d, f), 'utf8') !== readFileSync(join(RADACINA, f), 'utf8')); if (dif.length !== 1 || dif[0] !== fisier) { stricate++; console.log(` STRICAT ${id}: copia difera in ${dif.join(', ') || 'nimic'}`); continue; } ruleaza(id, d, tinte, tinte); } finally { rmSync(d, { recursive: true, force: true }); } } console.log(`\ncontrolul negativ al probei de cost: prinse ${prinse}/${total}, stricate ${stricate}`); process.exitCode = stricate ? 2 : prinse === total ? 0 : 1;