
# Testiranje oracle

Vsaka odločitev pri implementaciji v Phasis temelji na enem vprašanju: **ali V8 ustvari enak rezultat?**

JavaScript ima subtilno semantiko — `NaN !== NaN`, `-0 === 0`, `[1] + 1 === "11"`, natančen vrstni red naštevanja lastnosti in čas izvajanja mikroopravil `Promise`. Ponovno izpeljevanje teh podrobnosti z branjem specifikacije je počasno in nagnjeno k napakam. Phasis to poenostavi tako, da Node.js (V8) obravnava kot oracle: napišite scenarij JS, ga zaženite prek V8 in zajemite rezultat kot resnico; nato ga zaženite prek Phasis, znova zajemite rezultat in primerjajte razlike.

```
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
```

## Dve ravni testiranja

### Raven 1 — Scenariji po meri

Vsak scenarij v `scenarios/` je majhen program JS z znanim rezultatom. Zaženite en sam scenarij:

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

Zaženite vse scenarije, samo eno kategorijo ali pa jih zaženite vzporedno:

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

Osvežite oracle (e.g po posodobitvi različice Node.js):

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

Scenariji so razvrščeni po poglavjih ECMAScripta: literali, operatorji, spremenljivke, nadzorni tok, funkcije, objekti, polja, razredi, vgrajene funkcije, napake, interoperabilnost in robni primeri.

### Raven 2 — test262

Uradna zbirka testov skladnosti TC39 je vključena kot podmodul git v `test262/`. Vsak test preveri samega sebe: uspe, če ne sproži izjeme, in ne uspe, če jo (pri testih `negative` velja obratno). Pred vsakim testom testno okolje naloži `assert.js` in `sta.js`.

```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
```

Posnetek celotne zbirke je shranjen v [`COMPAT.md`](https://github.com/inline0/phasis/blob/main/COMPAT.md), ponovno pa ga ustvari `bin/compat-report`. V CI ga potek dela `compat-matrix.yml` izvede v delih in potrdi rezultat; ta potek dela se zažene ročno, ne ob vsakem potisku kode.

## Lokalni pregled pred pošiljanjem

`./bin/verify-all` zažene preverjanja kakovosti, ki jih uveljavlja CI:

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

Sam po sebi **ne** zadostuje — pri vsaki spremembi razčlenjevalnika, tolmača ali vgrajenih funkcij je treba vzorčno preizkusiti tudi test262. Ob vsakem zahtevku za združitev CI zažene PHPStan, PHPCS, zbirko testov enot in regresijski test oracle; zbirki WPT in popular se zaženeta, ko zahtevek spremeni `src/` ali njune testne primere. Celotna matrika test262 ni del CI za zahtevke za združitev, zato lokalno vzorčno preizkusite prizadete kategorije.

## Zakaj to deluje

Če V8 obravnavamo kot vir resnice, v razvojnem procesu skoraj ni več treba brati specifikacije. Vsako odstopanje od V8 kaže na napako v Phasis — nikoli na dvoumnost specifikacije, o kateri bi se bilo mogoče prepirati. Ko je popravek vključen, ustrezni vnosi test262 postanejo trajni regresijski testi.

Stopnja uspešnosti 100 % je posledica te doslednosti: vsak zahtevek za združitev se preveri glede na V8, CI zavrne regresije v zbirkah oracle, WPT in popular, matrika test262 pa ob zagonu potrdi rezultat celotne zbirke.
