Δοκιμές oracle
Κάθε απόφαση υλοποίησης στο Phasis εξαρτάται από ένα ερώτημα: παράγει το V8 την ίδια έξοδο;
Το JavaScript έχει λεπτές σημασιολογικές διαφορές — NaN !== NaN, -0 === 0, [1] + 1 === "11", την ακριβή σειρά απαρίθμησης ιδιοτήτων και τον χρονισμό των microtask Promise. Η αναπαραγωγή αυτών διαβάζοντας την προδιαγραφή είναι αργή και επιρρεπής σε σφάλματα. Το Phasis το παρακάμπτει, αντιμετωπίζοντας το Node.js (V8) ως oracle: γράψτε ένα σενάριο JS, εκτελέστε το μέσω του V8 και καταγράψτε την έξοδο ως αληθή· εκτελέστε το μέσω του Phasis, καταγράψτε ξανά την έξοδο και συγκρίνετέ τες.
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
Δύο επίπεδα δοκιμών
Επίπεδο 1 — Προσαρμοσμένα σενάρια
Κάθε σενάριο στο scenarios/ είναι ένα μικρό πρόγραμμα JS με γνωστή έξοδο. Εκτελέστε ένα σενάριο:
./bin/test-scenario operators/arithmetic
Εκτελέστε όλα τα σενάρια, μόνο μία κατηγορία ή παράλληλα:
./bin/test-regression
./bin/test-regression --jobs 4
./bin/test-regression --category expressions
Ανανεώστε το oracle (e.g. μετά από ενημέρωση έκδοσης του Node.js):
./bin/oracle --refresh operators/arithmetic
Τα σενάρια οργανώνονται ανά κεφάλαιο ECMAScript: κυριολεκτικές τιμές, τελεστές, μεταβλητές, ροή ελέγχου, συναρτήσεις, αντικείμενα, πίνακες, κλάσεις, ενσωματωμένα στοιχεία, σφάλματα, διαλειτουργικότητα και οριακές περιπτώσεις.
Επίπεδο 2 — test262
Η επίσημη σουίτα συμμόρφωσης TC39 έχει ληφθεί ως υπομονάδα git στο test262/. Κάθε δοκιμή επαληθεύει μόνη της το αποτέλεσμα: περνά αν δεν προκληθεί εξαίρεση και αποτυγχάνει αν προκληθεί (ή το αντίστροφο για δοκιμές negative). Ο μηχανισμός δοκιμών φορτώνει τα assert.js και sta.js πριν από κάθε δοκιμή.
./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
Το πλήρες στιγμιότυπο της σουίτας βρίσκεται στο COMPAT.md και αναδημιουργείται από το bin/compat-report. Στο CI, η ροή εργασίας compat-matrix.yml το εκτελεί σε τμήματα και υποβάλλει το αποτέλεσμα· η ροή εργασίας ξεκινά χειροκίνητα, όχι σε κάθε push.
Τοπικός έλεγχος πριν από το push
Το ./bin/verify-all εκτελεί την πύλη ποιότητας που επιβάλλει το CI:
=== PHPStan === level 6, zero errors
=== Code Standards === PHPCS, zero warnings
=== PHPUnit === unit suite passes
=== Oracle Regression === scenarios under `scenarios/` pass
Από μόνο του δεν αρκεί — πρέπει επίσης να δειγματοληπτείται το test262 για κάθε αλλαγή που αγγίζει τον parser, τον interpreter ή τα ενσωματωμένα στοιχεία. Σε κάθε pull request, το CI εκτελεί τα PHPStan, PHPCS, τη σουίτα μονάδων και την παλινδρόμηση oracle· οι σουίτες WPT και δημοφιλών πακέτων εκτελούνται όταν ένα pull request αλλάζει το src/ ή τα fixtures τους. Η πλήρης μήτρα test262 δεν αποτελεί μέρος του CI των pull request, επομένως δοκιμάστε τοπικά τις κατηγορίες που επηρεάζονται.
Γιατί λειτουργεί
Αν θεωρείτε το V8 ως την έγκυρη πηγή, σχεδόν όλη η ανάγνωση προδιαγραφών αφαιρείται από τον κύκλο ανάπτυξης. Η διαφωνία με το V8 υποδεικνύει πάντα σφάλμα Phasis — ποτέ ασάφεια στις προδιαγραφές που επιδέχεται συζήτηση. Μόλις ενσωματωθεί μια διόρθωση, οι αντίστοιχες εγγραφές test262 γίνονται μόνιμες δοκιμές παλινδρόμησης.
Το ποσοστό επιτυχίας 100% είναι αποτέλεσμα αυτής της πειθαρχίας: κάθε PR αξιολογείται με βάση το V8, το CI απορρίπτει παλινδρομήσεις στις σουίτες oracle, WPT και δημοφιλών πακέτων, ενώ η μήτρα test262 επιβεβαιώνει το αποτέλεσμα της πλήρους σουίτας όταν εκτελείται.