89 lines
6.9 KiB
JavaScript
89 lines
6.9 KiB
JavaScript
#!/usr/bin/env node
|
|
// Controlul negativ al probelor clientului Java (1.5.0; 1.6.1 adauga redirectarea si poarta --release 8): fiecare paznic se strica intr-o COPIE a clasei (sursa din depozit nu se
|
|
// atinge), probele se ruleaza pe copie si proba tinta TREBUIE sa pice; o plantare care nu se aplica sau nu compileaza e un ESEC al
|
|
// controlului (STRICAT), nu un rosu. La urma, clasa neatinsa trebuie sa treaca intreaga.
|
|
// node aerenew/sdk/java/control-negativ.mjs
|
|
import fs from 'node:fs';
|
|
import os from 'node:os';
|
|
import path from 'node:path';
|
|
import { execFileSync } from 'node:child_process';
|
|
import { fileURLToPath } from 'node:url';
|
|
|
|
const AICI = path.dirname(fileURLToPath(import.meta.url));
|
|
const SRC = path.join(AICI, 'src', 'main', 'java', 'network', 'aere', 'cloud', 'AereCloud.java');
|
|
const TEST = path.join(AICI, 'src', 'test', 'java', 'network', 'aere', 'cloud', 'TestAereCloud.java');
|
|
const original = fs.readFileSync(SRC, 'utf8');
|
|
|
|
const PLANTARI = [
|
|
['piatra zilei sterse acceptata fara comparatie', 'return new KeptCheck(day, "expired", dig, local, local.equals(dig), cand);',
|
|
'return new KeptCheck(day, "expired", dig, local, true, cand);', 'auditVerifyKept'],
|
|
['ziua tinuta acceptata fara comparatie', 'return new KeptCheck(day, "held", dig, local, local.equals(dig), null);',
|
|
'return new KeptCheck(day, "held", dig, local, true, null);', 'auditVerifyKept'],
|
|
['exportul jsonl declarat verificat fara hash', 'Boolean ok = "jsonl".equals(f) ? (digest != null && digest.equals(sha256Hex(r.octeti))) : null;',
|
|
'Boolean ok = "jsonl".equals(f) ? Boolean.TRUE : null;', 'auditExport'],
|
|
['cheia trimisa si fara attest', 'return req("POST", "/pq/readiness", json(m), attest);',
|
|
'return req("POST", "/pq/readiness", json(m), true);', 'readiness fara attest'],
|
|
['un 429 intors ca nepotrivire', 'if (r.status < 200 || r.status >= 300) throw new AereCloudException(r.status, r.text(), "/account/audit");\n String dig = sha256Hex(r.octeti);',
|
|
'if (r.status < 200 || r.status >= 300) return new KeptCheck(day, "held", null, local, false, null);\n String dig = sha256Hex(r.octeti);', 'auditVerifyKept'],
|
|
// 1.6.1: HttpURLConnection urmeaza redirectarile implicit; fara oprire, cheia pleaca spre gazda din Location
|
|
['redirectarea urmata (cheia pleaca spre alta gazda)', 'c.setInstanceFollowRedirects(false);', 'c.setInstanceFollowRedirects(true);', '302'],
|
|
// 1.7.0: conformitatea trimisa pe ruta identitatii; identitatea fara cheie
|
|
['complianceCheck pe ruta identitatii', 'return req("POST", "/compliance/check", requestJson, true);', 'return req("POST", "/identity/verify", requestJson, true);', '1.7.0'],
|
|
['identityVerify fara cheie', 'return req("POST", "/identity/verify", requestJson, true);', 'return req("POST", "/identity/verify", requestJson, false);', '1.7.0'],
|
|
// 1.8.0: chitanta pe ruta riscului; verificarea fara cheie
|
|
['paymentsReceipt pe ruta riscului', 'return req("POST", "/payments/receipt", requestJson, true);', 'return req("POST", "/payments/risk", requestJson, true);', '1.8.0'],
|
|
['paymentsVerify fara cheie', 'return req("POST", "/payments/verify", requestJson, true);', 'return req("POST", "/payments/verify", requestJson, false);', '1.8.0'],
|
|
];
|
|
// 1.6.1: poarta Android = clasa compileaza cu `javac --release 8`. Un API de dupa Java 8 trece probele pe JDK 21 si trebuie prins
|
|
// numai de poarta; plantarea NU e o proba, e o compilare care TREBUIE sa cada.
|
|
const PLANTARI_JAVA8 = [
|
|
['InputStream.readAllBytes (Java 9)', 'while ((n = in.read(buf)) != -1) b.write(buf, 0, n);\n return b.toByteArray();', 'return in.readAllBytes();'],
|
|
['URLEncoder.encode cu Charset (Java 10)', 'try { return URLEncoder.encode(s, "UTF-8"); }', 'try { if (s == null) throw new java.io.UnsupportedEncodingException(); return URLEncoder.encode(s, StandardCharsets.UTF_8); }'],
|
|
];
|
|
function compileazaJava8(sursa) {
|
|
const d = fs.mkdtempSync(path.join(os.tmpdir(), 'aere-java8-'));
|
|
try {
|
|
fs.writeFileSync(path.join(d, 'AereCloud.java'), sursa);
|
|
execFileSync('javac', ['--release', '8', '-Xlint:-options', '-d', path.join(d, 'out'), path.join(d, 'AereCloud.java')], { stdio: 'pipe' });
|
|
return { ok: true };
|
|
} catch (e) { return { ok: false, err: String(e.stderr || e.message).split('\n').find((l) => /error/.test(l)) || 'eroare' }; }
|
|
finally { fs.rmSync(d, { recursive: true, force: true }); }
|
|
}
|
|
|
|
function ruleaza(sursa) {
|
|
const d = fs.mkdtempSync(path.join(os.tmpdir(), 'aere-java-cn-'));
|
|
try {
|
|
fs.writeFileSync(path.join(d, 'AereCloud.java'), sursa);
|
|
try { execFileSync('javac', ['-d', path.join(d, 'out'), path.join(d, 'AereCloud.java'), TEST], { stdio: 'pipe' }); }
|
|
catch (e) { return { stricat: 'nu compileaza: ' + String(e.stderr || e.message).split('\n')[0] }; }
|
|
let out;
|
|
try { out = execFileSync('java', ['-cp', path.join(d, 'out'), 'network.aere.cloud.TestAereCloud'], { encoding: 'utf8' }); }
|
|
catch (e) { out = String(e.stdout || ''); }
|
|
const m = /(\d+) treceri, (\d+) esecuri/.exec(out);
|
|
if (!m) return { stricat: 'probele nu au terminat' };
|
|
return { treceri: +m[1], esecuri: +m[2], picate: out.split('\n').filter((l) => l.startsWith(' PICA')) };
|
|
} finally { fs.rmSync(d, { recursive: true, force: true }); }
|
|
}
|
|
|
|
let rele = 0;
|
|
for (const [nume, vechi, nou, tinta] of PLANTARI) {
|
|
if (original.split(vechi).length !== 2) { console.log(` STRICAT ${nume}: ancora apare de ${original.split(vechi).length - 1} ori`); rele++; continue; }
|
|
const r = ruleaza(original.replace(vechi, nou));
|
|
if (r.stricat) { console.log(` STRICAT ${nume}: ${r.stricat}`); rele++; continue; }
|
|
if (r.picate.some((l) => l.includes(tinta))) console.log(` ROSU cum trebuia ${nume} (${r.esecuri} esec, intre ele proba '${tinta}')`);
|
|
else { console.log(` CONTROL CAZUT ${nume}: proba '${tinta}' a ramas verde`); rele++; }
|
|
}
|
|
for (const [nume, vechi, nou] of PLANTARI_JAVA8) {
|
|
if (original.split(vechi).length !== 2) { console.log(` STRICAT ${nume}: ancora apare de ${original.split(vechi).length - 1} ori`); rele++; continue; }
|
|
const r = compileazaJava8(original.replace(vechi, nou));
|
|
if (!r.ok) console.log(` ROSU cum trebuia ${nume}: --release 8 refuza (${r.err.trim().slice(0, 90)})`);
|
|
else { console.log(` CONTROL CAZUT ${nume}: --release 8 a compilat`); rele++; }
|
|
}
|
|
const j8 = compileazaJava8(original);
|
|
if (!j8.ok) { console.log(' MARTORUL nu compileaza cu --release 8: ' + j8.err); rele++; } else console.log(' martor: sursa neatinsa compileaza cu --release 8 (API Java 8, deci si Android)');
|
|
const martor = ruleaza(original);
|
|
if (martor.stricat || martor.esecuri !== 0) { console.log(' MARTORUL nu e verde: ' + JSON.stringify(martor)); rele++; }
|
|
else console.log(` martor: sursa neatinsa ${martor.treceri}/${martor.treceri} verde`);
|
|
console.log(rele ? `CONTROL NEGATIV: ${rele} probleme` : `CONTROL NEGATIV TRECUT (${PLANTARI.length + PLANTARI_JAVA8.length} din ${PLANTARI.length + PLANTARI_JAVA8.length} rosii, martorul verde si pe --release 8)`);
|
|
process.exitCode = rele ? 1 : 0;
|