
# Oracletests

Elke implementatiebeslissing in Phasis hangt af van één vraag: **levert V8 dezelfde uitvoer op?**

JavaScript heeft subtiele semantiek: `NaN !== NaN`, `-0 === 0`, `[1] + 1 === "11"`, de exacte volgorde waarin properties worden opgesomd en het moment waarop `Promise`-microtaken worden uitgevoerd. Deze opnieuw afleiden door de specificatie te lezen is traag en foutgevoelig. Phasis omzeilt dat door Node.js (V8) als oracle te behandelen: schrijf een JS-scenario, voer het uit via V8 en leg de uitvoer vast als waarheid; voer het daarna uit via Phasis, leg de uitvoer opnieuw vast en vergelijk.

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

## Twee testniveaus

### Niveau 1 — aangepaste scenario's

Elk scenario in `scenarios/` is een klein JS-programma met bekende uitvoer. Voer één scenario uit:

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

Voer ze allemaal, slechts één categorie of ze parallel uit:

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

Vernieuw de oracle (e.g, bijvoorbeeld na een versie-update van Node.js):

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

Scenario's zijn ingedeeld volgens de hoofdstukken van ECMAScript: literals, operators, variabelen, besturingsstroom, functies, objecten, arrays, classes, ingebouwde functies, fouten, interoperabiliteit en randgevallen.

### Niveau 2 — test262

De officiële conformiteitssuite van TC39 is uitgecheckt als git-submodule onder `test262/`. Elke test controleert zichzelf: hij slaagt als er geen fout wordt gegenereerd en faalt als dat wel gebeurt (of andersom voor `negative`-tests). De harness laadt `assert.js` en `sta.js` vóór elke 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
```

De snapshot van de volledige suite staat in [`COMPAT.md`](https://github.com/inline0/phasis/blob/main/COMPAT.md) en wordt opnieuw gegenereerd door `bin/compat-report`. In CI voert de workflow van `compat-matrix.yml` deze in shards uit en legt het resultaat vast; die workflow wordt handmatig gestart, niet bij elke push.

## Lokale controle vóór het pushen

`./bin/verify-all` voert de kwaliteitspoort uit die CI afdwingt:

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

Dat is op zichzelf **niet** voldoende: test262 moet ook worden getest op wijzigingen in de parser, interpreter of ingebouwde functies. Bij elke pull request voert CI PHPStan, PHPCS, de unit-suite en de oracle-regressietest uit. De WPT- en popular-package-suites worden uitgevoerd wanneer een pull request `src/` of de bijbehorende fixtures wijzigt. De volledige matrix van test262 maakt geen deel uit van pull-request-CI; test de geraakte categorieën daarom lokaal.

## Waarom dit werkt

Door V8 als bron van waarheid te behandelen, hoeft tijdens het ontwikkelproces bijna nooit meer de specificatie te worden gelezen. Verschillen met V8 duiden altijd op een Phasis-bug, nooit op een onduidelijkheid in de specificatie waarover gediscussieerd kan worden. Zodra een oplossing is toegevoegd, worden de bijbehorende test262-vermeldingen permanente regressietests.

Het passpercentage van 100 % is het resultaat van deze discipline: elke PR wordt beoordeeld aan de hand van V8, CI wijst regressies af in de oracle-, WPT- en popular-package-suites, en de matrix van test262 bevestigt het resultaat van de volledige suite wanneer die wordt uitgevoerd.
