
# Tests de l'oracle

Chaque décision d'implémentation dans Phasis dépend d'une seule question : **V8 produit-il le même résultat ?**

JavaScript a une sémantique subtile — `NaN !== NaN`, `-0 === 0`, `[1] + 1 === "11"`, l'ordre exact d'énumération des propriétés et le moment d'exécution des microtâches `Promise`. Reconstituer ces détails en lisant la spécification est lent et source d'erreurs. Phasis évite cela en traitant Node.js (V8) comme un oracle : écrivez un scénario JS, exécutez-le avec V8 et capturez le résultat de référence ; exécutez-le ensuite avec Phasis, capturez à nouveau le résultat, puis comparez-les.

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

## Deux niveaux de test

### Niveau 1 — Scénarios personnalisés

Chaque scénario de `scenarios/` est un petit programme JS dont le résultat est connu. Exécutez un scénario seul :

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

Exécutez-les tous, une seule catégorie, ou en parallèle :

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

Actualisez l'oracle (e.g après une mise à jour de version Node.js) :

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

Les scénarios sont organisés par chapitre ECMAScript : littéraux, opérateurs, variables, flux de contrôle, fonctions, objets, tableaux, classes, éléments intégrés, erreurs, interopérabilité et cas limites.

### Niveau 2 — test262

La suite officielle de conformité TC39 est récupérée comme sous-module git sous `test262/`. Chaque test se vérifie lui-même : il réussit s'il ne déclenche pas d'exception et échoue dans le cas contraire (ou l'inverse pour les tests `negative`). Le harnais charge `assert.js` et `sta.js` avant chaque 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
```

L'instantané de la suite complète se trouve dans [`COMPAT.md`](https://github.com/inline0/phasis/blob/main/COMPAT.md) et est régénéré par `bin/compat-report`. Dans la CI, le workflow `compat-matrix.yml` l'exécute en lots et valide le résultat ; ce workflow est lancé manuellement, pas à chaque push.

## Vérification locale avant le push

`./bin/verify-all` exécute les contrôles qualité imposés par la CI :

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

Cela ne suffit **pas** à lui seul : il faut aussi échantillonner test262 pour toute modification touchant l'analyseur, l'interpréteur ou les éléments intégrés. Pour chaque pull request, la CI exécute PHPStan, PHPCS, la suite unitaire et la régression de l'oracle ; les suites WPT et de paquets populaires s'exécutent si la pull request modifie `src/` ou leurs fixtures. La matrice test262 complète ne fait pas partie de la CI des pull requests : échantillonnez donc localement les catégories concernées.

## Pourquoi cela fonctionne

Prendre V8 comme référence élimine presque toute lecture de la spécification pendant le développement. Tout désaccord avec V8 révèle un bogue Phasis — jamais une ambiguïté de la spécification qui pourrait se discuter. Une fois le correctif intégré, les tests test262 correspondants deviennent des tests de régression permanents.

Le taux de réussite de 100 % découle de cette méthode : chaque PR est évaluée par rapport à V8, la CI rejette les régressions dans l'oracle, WPT et les suites de paquets populaires, et la matrice test262 confirme le résultat complet lorsqu'elle est exécutée.
