
# Oracle-testning

Hver implementeringsbeslutning i Phasis afhænger af ét spørgsmål: **giver V8 det samme resultat?**

JavaScript har subtil semantik — `NaN !== NaN`, `-0 === 0`, `[1] + 1 === "11"`, den nøjagtige rækkefølge for egenskabsopregning og tidspunktet for `Promise`-mikrotasks. Det er langsomt og fejlbehæftet at udlede dette ved at læse specifikationen. Phasis undgår det ved at behandle Node.js (V8) som et oracle: Skriv et JS-scenarie, kør det gennem V8, og gem resultatet som facit; kør det gennem Phasis, gem resultatet igen, og sammenlign dem.

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

## To testniveauer

### Niveau 1 — Tilpassede scenarier

Hvert scenarie i `scenarios/` er et lille JS-program med kendt resultat. Kør et enkelt scenarie:

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

Kør dem alle, en enkelt kategori eller flere parallelt:

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

Opdater oracle (e.g, efter en versionsopdatering af Node.js):

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

Scenarierne er organiseret efter ECMAScript-kapitler: literaler, operatorer, variabler, kontrolflow, funktioner, objekter, arrays, klasser, indbyggede funktioner, fejl, interop og kanttilfælde.

### Niveau 2 — test262

Den officielle TC39-overensstemmelsessuite er hentet som et git-submodul under `test262/`. Hver test kontrollerer selv sit resultat: Den består, hvis den ikke udløser en fejl, og fejler, hvis den gør det (eller omvendt for `negative`-tests). Testrammen indlæser `assert.js` og `sta.js` før hver 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
```

Øjebliksbilledet af den fulde suite ligger i [`COMPAT.md`](https://github.com/inline0/phasis/blob/main/COMPAT.md) og gendannes af `bin/compat-report`. I CI kører workflowen `compat-matrix.yml` den i shards og gemmer resultatet; workflowen startes manuelt, ikke ved hver push.

## Lokal kontrol før push

`./bin/verify-all` kører den kvalitetskontrol, som CI håndhæver:

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

Det er **ikke** tilstrækkeligt i sig selv — test262 skal også køres i udvalg for enhver ændring, der berører parseren, fortolkeren eller indbyggede funktioner. Ved hver pull request kører CI PHPStan, PHPCS, unit-suiten og oracle-regressionstesten; WPT- og populærpakke-suiterne køres, når en pull request ændrer `src/` eller deres fixtures. Den fulde test262-matrix er ikke en del af CI for pull requests, så kør lokalt de berørte kategorier.

## Hvorfor det virker

Når V8 behandles som facit, fjernes næsten al læsning af specifikationen fra udviklingsforløbet. Uenighed med V8 betyder altid en fejl i Phasis — aldrig en tvetydighed i specifikationen, der kan diskuteres. Når en rettelse er landet, bliver de tilsvarende test262-elementer permanente regressionstests.

100 % beståelsesgrad er resultatet af denne praksis: Hver PR vurderes mod V8, CI afviser regressioner i oracle-, WPT- og populærpakke-suiterne, og test262-matricen bekræfter resultatet for hele suiten, når den køres.
