
# Testarea oracle

Fiecare decizie de implementare din Phasis depinde de un singur răspuns: **produce V8 același rezultat?**

JavaScript are semantică subtilă — `NaN !== NaN`, `-0 === 0`, `[1] + 1 === "11"`, ordinea exactă de enumerare a proprietăților și momentul executării microtask-urilor `Promise`. Rededucerea acestor detalii prin citirea specificației este lentă și predispusă la erori. Phasis evită această problemă folosind Node.js (V8) drept oracle: scrieți un scenariu JS, rulați-l prin V8 și înregistrați rezultatul drept adevăr; rulați-l prin Phasis, înregistrați din nou rezultatul și comparați-le.

```
1. SETUP    → a JavaScript source file or snippet
2. ORACLE   → Node.js executes it, output captured as truth
3. ACTUAL   → Phasis executes it, output captured
4. COMPARE  → oracle vs actual, diff measures the gap
```

## Două niveluri de testare

### Nivelul 1 — Scenarii personalizate

Fiecare scenariu din `scenarios/` este un mic program JS cu rezultat cunoscut. Rulați un singur scenariu:

```bash
./bin/test-scenario operators/arithmetic
```

Rulați-le pe toate, doar o categorie sau în paralel:

```bash
./bin/test-regression
./bin/test-regression --jobs 4
./bin/test-regression --category expressions
```

Reîmprospătați oracle-ul (e.g după o actualizare a versiunii Node.js):

```bash
./bin/oracle --refresh operators/arithmetic
```

Scenariile sunt organizate după capitolele ECMAScript: literali, operatori, variabile, flux de control, funcții, obiecte, tablouri, clase, funcționalități încorporate, erori, interoperabilitate și cazuri-limită.

### Nivelul 2 — test262

Suita oficială de conformitate TC39 este preluată ca submodul git în `test262/`. Fiecare test își verifică singur rezultatul: trece dacă nu aruncă o excepție și eșuează dacă o aruncă (sau invers, pentru testele `negative`). Harness-ul încarcă `assert.js` și `sta.js` înaintea fiecărui test.

```bash
./bin/test262                                    # full suite
./bin/test262 --category built-ins/Array         # subset
./bin/test262 --jobs 4                           # parallel
./bin/test262 --failures                         # one line per failing test
./bin/compat-report                              # full COMPAT.md + compat.json
```

Instantaneul suitei complete se află în [`COMPAT.md`](https://github.com/inline0/phasis/blob/main/COMPAT.md) și este regenerat de `bin/compat-report`. În CI, fluxul de lucru `compat-matrix.yml` îl rulează în fragmente și înregistrează rezultatul; fluxul este pornit manual, nu la fiecare trimitere.

## Verificare locală înainte de trimitere

`./bin/verify-all` rulează verificările de calitate impuse de CI:

```
=== PHPStan ===                  level 6, zero errors
=== Code Standards ===           PHPCS, zero warnings
=== PHPUnit ===                  unit suite passes
=== Oracle Regression ===        scenarios under `scenarios/` pass
```

Acest lucru **nu** este suficient de unul singur — trebuie testat și test262 pentru orice modificare care atinge parserul, interpretorul sau funcționalitățile încorporate. La fiecare pull request, CI rulează PHPStan, PHPCS, suita unitară și testul de regresie oracle; suitele WPT și popular rulează când pull request-ul modifică `src/` sau fixture-urile acestora. Matricea completă test262 nu face parte din CI pentru pull request-uri, așa că testați local categoriile afectate.

## De ce funcționează

Folosirea V8 ca sursă de adevăr elimină aproape complet citirea specificației din ciclul de dezvoltare. Orice dezacord cu V8 indică întotdeauna o eroare Phasis — niciodată o ambiguitate a specificației care poate fi dezbătută. După ce o remediere este integrată, intrările test262 corespunzătoare devin teste de regresie permanente.

Rata de promovare de 100% este rezultatul acestei discipline: fiecare PR este evaluat în raport cu V8, CI respinge regresiile din oracle și suitele WPT și popular, iar matricea test262 confirmă rezultatul suitei complete când este rulată.
