Lewati ke konten

Pengujian oracle

Setiap keputusan implementasi di Phasis bergantung pada satu pertanyaan: apakah V8 menghasilkan keluaran yang sama?

JavaScript memiliki semantik yang rumit — NaN !== NaN, -0 === 0, [1] + 1 === "11", urutan enumerasi properti yang tepat, dan waktu eksekusi microtask Promise. Menurunkannya kembali dengan membaca spesifikasi lambat dan rawan kesalahan. Phasis mengatasi hal ini dengan memperlakukan Node.js (V8) sebagai oracle: tulis skenario JS, jalankan melalui V8, simpan keluarannya sebagai kebenaran; jalankan melalui Phasis, simpan keluarannya lagi; bandingkan.

Kode
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

Dua tingkat pengujian

Tingkat 1 — Skenario khusus

Setiap skenario di scenarios/ adalah program JS kecil dengan keluaran yang diketahui. Jalankan satu skenario:

Shell
./bin/test-scenario operators/arithmetic

Jalankan semuanya, hanya satu kategori, atau secara paralel:

Shell
./bin/test-regression
./bin/test-regression --jobs 4
./bin/test-regression --category expressions

Perbarui oracle (e.g, misalnya setelah pembaruan versi Node.js):

Shell
./bin/oracle --refresh operators/arithmetic

Skenario diatur berdasarkan bab ECMAScript: literal, operator, variabel, alur kontrol, fungsi, objek, array, kelas, built-in, error, interop, kasus tepi.

Tingkat 2 — test262

Rangkaian pengujian kesesuaian resmi TC39 di-checkout sebagai submodul git di bawah test262/. Setiap pengujian memverifikasi dirinya sendiri: berhasil jika tidak melempar error, gagal jika sebaliknya (atau kebalikannya untuk pengujian negative). Harness memuat assert.js dan sta.js sebelum setiap pengujian.

Shell
./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

Snapshot rangkaian lengkap berada di COMPAT.md, dibuat ulang oleh bin/compat-report. Di CI, workflow compat-matrix.yml menjalankannya dalam beberapa shard dan melakukan commit atas hasilnya; workflow itu dijalankan secara manual, bukan pada setiap push.

Pemeriksaan lokal sebelum push

./bin/verify-all menjalankan gerbang kualitas yang diterapkan CI:

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

Itu saja tidak cukup — test262 juga harus dijalankan pada sampel untuk setiap perubahan yang menyentuh parser, interpreter, atau built-in. Pada setiap pull request, CI menjalankan PHPStan, PHPCS, rangkaian unit, dan regresi oracle; rangkaian WPT dan paket populer dijalankan jika pull request mengubah src/ atau fixture-nya. Matriks test262 lengkap tidak termasuk dalam CI pull request, jadi lakukan sampling kategori terdampak secara lokal.

Mengapa cara ini berhasil

Memperlakukan V8 sebagai sumber kebenaran menghilangkan hampir semua kegiatan membaca spesifikasi dari siklus pengembangan. Ketidaksesuaian dengan V8 selalu menunjukkan bug Phasis — tidak pernah ambiguitas spesifikasi yang dapat diperdebatkan. Setelah perbaikan diterapkan, entri test262 yang sesuai menjadi pengujian regresi permanen.

Tingkat kelulusan 100 sebesar % merupakan hasil dari disiplin ini: setiap PR dinilai berdasarkan V8, CI menolak regresi pada rangkaian oracle, WPT, dan paket populer, serta matriks test262 mengonfirmasi hasil rangkaian lengkap saat dijalankan.