From 6a796e3d9fd10e38a846b21453bb0a130b1c32c0 Mon Sep 17 00:00:00 2001 From: TheHypnoo Date: Wed, 13 May 2026 18:39:44 +0200 Subject: [PATCH] =?UTF-8?q?test:=20#698=20=E2=80=94=20behavioral=20parity?= =?UTF-8?q?=20tests=20for=20argon2=20+=20ethers=20integrations?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Converts deterministic entries from `test_ffi_surface_stdlib_integrations.ts` into focused behavioral parity fixtures, per the follow-up to #694. - `test_parity_argon2.ts` + expected output: round-trip `argon2.hash` / `argon2.verify` (async path — the only one wired in the dispatch table) with random-salt shape assertions. - `test_parity_ethers.ts` + expected output: deterministic helpers `getAddress`, `parseEther`/`formatEther`, `parseUnits`/`formatUnits`. - Adds `@covers` block to `test_parity_crypto.ts` for the crypto/webcrypto/crypto_e2e FFI surface it already exercises (digest, hash, hmac-via-pbkdf2/hkdf, subtle.sign/verify). Both new fixtures use the `test-parity/expected/` mechanism: Perry routes the npm-style imports to its bundled `perry-ext-*` wrappers, but Node can't load the same names without `node_modules`, so they fall through to the stored expected-output comparison. After `./test-coverage/regen_ts_surface_inventory.py`: - stdlib integrations inventory: 156 → 138 unique FFI names. - `./test-coverage/audit.sh --markdown` still reports 100% TS FFI coverage. --- CHANGELOG.md | 2 + CLAUDE.md | 2 +- Cargo.lock | 136 +++++++++--------- Cargo.toml | 2 +- test-coverage/COVERAGE.md | 2 +- .../test_ffi_surface_stdlib_integrations.ts | 21 +-- test-files/test_parity_argon2.ts | 40 ++++++ test-files/test_parity_crypto.ts | 15 ++ test-files/test_parity_ethers.ts | 36 +++++ test-parity/expected/test_parity_argon2.txt | 7 + test-parity/expected/test_parity_ethers.txt | 9 ++ 11 files changed, 181 insertions(+), 91 deletions(-) create mode 100644 test-files/test_parity_argon2.ts create mode 100644 test-files/test_parity_ethers.ts create mode 100644 test-parity/expected/test_parity_argon2.txt create mode 100644 test-parity/expected/test_parity_ethers.txt diff --git a/CHANGELOG.md b/CHANGELOG.md index 8c2eb54c95..3930edd423 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,8 @@ Detailed changelog for Perry. See CLAUDE.md for concise summaries. +## v0.5.908 — test: #698 — behavioral parity tests for argon2 + ethers integrations (#760). Follow-up to #694, addressing #698. Adds two new parity fixtures and a `@covers` block on `test_parity_crypto.ts`, moving 18 FFI entries out of `test_ffi_surface_stdlib_integrations.ts` (156 → 138 unique names) into behavioral coverage. **`test_parity_argon2.ts`** — round-trips `argon2.hash` / `argon2.verify` against the `perry-ext-argon2` wrapper; non-deterministic salt is handled by shape-checking the `$argon2id$` prefix and asserting verify round-trips against a freshly produced hash. Only the async path is in `NativeModSig`, so this covers the two FFI entries (`js_argon2_hash`, `js_argon2_verify`) reachable end-to-end. **`test_parity_ethers.ts`** — pure deterministic helpers from `perry-ext-ethers`: `getAddress` (EIP-55 checksum on lower- and upper-case input), `parseEther`/`formatEther` round-trip on 1.5 ETH, `parseUnits`/`formatUnits` at 6- (USDC) and 9-decimal (gwei) positions. Covers the five `js_ethers_*` helpers. Both new fixtures use the `test-parity/expected/` mechanism — Perry routes the npm-style imports to the bundled `perry-ext-*` wrappers, but Node can't resolve the same names without `node_modules`, so they fall through to stored expected-output comparison. **`test_parity_crypto.ts`** — adds a `@covers` block declaring the crypto/webcrypto/crypto_e2e FFI surface it already exercises via `node:crypto` and `crypto.subtle` (digest, hash, pbkdf2/hkdf, subtle.sign/verify); no behavioral change. **Out of scope (each gets its own follow-up).** `jsonwebtoken.sign` — `NativeModSig` passes `payload`/`secret` as `NA_F64` (NaN-boxed) but `js_jwt_sign` reads them as `*const StringHeader`, producing garbage tokens (calling-convention mismatch, same shape as the #591 argon2 fix). `bcrypt.hash` — return value reports `typeof === "object"` in user code; `compare` round-trips correctly but `.startsWith(...)` on the hash fails. `cheerio` — `$.select(...)` returns a bare-number handle, so `.length()` / `.first()` etc. fail with `(number).method is not a function` at the prototype check. Service-backed integrations (MongoDB, MySQL, PG, ioredis, Nodemailer, Sharp) also remain in the inventory pending the local-container / opt-in test setup described in #698. **Audit.** `./test-coverage/audit.sh --markdown` keeps TS-side and combined FFI coverage at **1791/1791 (100.0%)**. `test_ffi_surface_stdlib_integrations.ts` re-regenerated via `regen_ts_surface_inventory.py` to fold in the new `@covers` blocks. Comment-only changes; no behavioral or runtime impact. Contributor: @TheHypnoo. + ## v0.5.907 — test(stdlib): #697 — move stdlib_io FFI coverage into behavioral tests (#758). Follow-up to #694: relocates the 155 inventory entries from `test_ffi_surface_stdlib_io.ts` into `@covers` annotations attached to the existing behavioral fixtures for each surface — `fetch.rs` (43 names) → `test_gap_fetch_response.ts`; `streams.rs` (37) → `test_parity_stream_web.ts`; `http.rs` (13) → `test_parity_http.ts`; `net/mod.rs` (10) → `test_net_socket.ts`; `readline.rs` (5) → `test_parity_readline.ts`; `worker_threads.rs` (6) → `test_parity_worker_threads.ts`; `ws.rs` (11) → `test_node_http_ws_upgrade.ts`; `framework/{multipart,request,response,server}.rs` (28) → `test_fastify_integration.ts`. Each receiving fixture already exercises real behavior on its surface (local loopback servers / deterministic in-memory probes / Headers + Blob + Response API roundtrips) — no external services added. **Mechanism.** `regen_ts_surface_inventory.py` excludes the six `test_ffi_surface_*.ts` inventory files when scanning for `@covers` references, so any FFI name that appears in a non-inventory fixture's `@covers` block is dropped from its inventory file on the next regen. After this PR, `test_ffi_surface_stdlib_io.ts` shrinks from **155 → 0** unique FFI names. **Audit.** `./test-coverage/audit.sh --markdown` keeps TypeScript and combined FFI coverage at **1791/1791 (100.0%)**. `test_ffi_surface_runtime_core.ts` re-regenerated against current `main` post-rebase — the inventory drift visible in the diff (added `js_array_flat_depth`, `js_template_raw`, `js_path_matches_glob`, `js_async_first_call`, the 7 new `webassembly.rs` exports; removed `js_mul`, `js_net_socket_destroy/end/write`, the 9 `js_ws_*` stubs from `stdlib_stubs.rs`) reflects upstream Rust refactors, not hand edits. Comment-only changes; no behavioral or runtime impact. Contributor: @TheHypnoo. ## v0.5.906 — test(stdlib): #696 — behavioral parity fixtures for stdlib core utilities (#757). Converts the stdlib-core FFI inventory entries called out in #696 into focused parity fixtures: 13 new `test_parity_*.ts` files (`lodash`, `dotenv`, `validator`, `uuid`, `nanoid`, `decimal`, `dayjs`, `moment`, `date_fns`, `lru_cache`, `commander`, `cron`, `async_local_storage`) plus `@covers` blocks appended to the existing `test_parity_events.ts` and `test_parity_zlib.ts`. Non-deterministic surfaces (uuid v4/v7, nanoid, dayjs.now / fromNow) use shape checks (length, alphabet, `validate()` round-trip) so output stays byte-stable; everything else uses fixed inputs and anchored UTC timestamps (e.g. dayjs anchored to `1709209096789` / 2024-02-29). `test_parity_async_local_storage.ts` is the one fixture that runs end-to-end in Node today (built-in `node:async_hooks`); the other 12 import npm packages not installed in the parity worker and will record as `NODE_FAIL`/`SKIP` until those land, acting as `@covers`-driven coverage anchors in the meantime. After `./test-coverage/regen_ts_surface_inventory.py`, `test_ffi_surface_stdlib_core.ts` drops from **313 → 84** unique FFI names; `./test-coverage/audit.sh --markdown` keeps TS-side coverage at **1791/1791 (100.0%)**. CI workflow tweak: `decimal`, `dotenv`, `lodash`, `moment`, `validator` added to the compile-smoke `SKIP_TESTS` list (no native stdlib path); the other 7 npm-package fixtures compile under perry-stdlib's native dispatch so they're left to the standard runner. `test_ffi_surface_runtime_core.ts` re-regenerated against current `main` (post-#756) — pure regen artifact, not a behavioral change. Contributor: @TheHypnoo. diff --git a/CLAUDE.md b/CLAUDE.md index 8a39d235e7..9d2bcdbe5c 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -8,7 +8,7 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co Perry is a native TypeScript compiler written in Rust that compiles TypeScript source code directly to native executables. It uses SWC for TypeScript parsing and LLVM for code generation. -**Current Version:** 0.5.907 +**Current Version:** 0.5.908 ## TypeScript Parity Status diff --git a/Cargo.lock b/Cargo.lock index e1b41efdb4..9ed2bdbd3e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4790,7 +4790,7 @@ checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" [[package]] name = "perry" -version = "0.5.907" +version = "0.5.908" dependencies = [ "anyhow", "base64", @@ -4845,14 +4845,14 @@ dependencies = [ [[package]] name = "perry-api-manifest" -version = "0.5.907" +version = "0.5.908" dependencies = [ "serde", ] [[package]] name = "perry-codegen" -version = "0.5.907" +version = "0.5.908" dependencies = [ "anyhow", "log", @@ -4865,7 +4865,7 @@ dependencies = [ [[package]] name = "perry-codegen-arkts" -version = "0.5.907" +version = "0.5.908" dependencies = [ "anyhow", "perry-hir", @@ -4874,7 +4874,7 @@ dependencies = [ [[package]] name = "perry-codegen-glance" -version = "0.5.907" +version = "0.5.908" dependencies = [ "anyhow", "perry-hir", @@ -4882,7 +4882,7 @@ dependencies = [ [[package]] name = "perry-codegen-js" -version = "0.5.907" +version = "0.5.908" dependencies = [ "anyhow", "perry-dispatch", @@ -4892,7 +4892,7 @@ dependencies = [ [[package]] name = "perry-codegen-swiftui" -version = "0.5.907" +version = "0.5.908" dependencies = [ "anyhow", "perry-hir", @@ -4901,7 +4901,7 @@ dependencies = [ [[package]] name = "perry-codegen-wasm" -version = "0.5.907" +version = "0.5.908" dependencies = [ "anyhow", "base64", @@ -4914,7 +4914,7 @@ dependencies = [ [[package]] name = "perry-codegen-wear-tiles" -version = "0.5.907" +version = "0.5.908" dependencies = [ "anyhow", "perry-hir", @@ -4922,7 +4922,7 @@ dependencies = [ [[package]] name = "perry-diagnostics" -version = "0.5.907" +version = "0.5.908" dependencies = [ "serde", "serde_json", @@ -4930,7 +4930,7 @@ dependencies = [ [[package]] name = "perry-dispatch" -version = "0.5.907" +version = "0.5.908" [[package]] name = "perry-doc-fixture-my-bindings" @@ -4941,7 +4941,7 @@ dependencies = [ [[package]] name = "perry-doc-tests" -version = "0.5.907" +version = "0.5.908" dependencies = [ "anyhow", "clap", @@ -4956,7 +4956,7 @@ dependencies = [ [[package]] name = "perry-ext-argon2" -version = "0.5.907" +version = "0.5.908" dependencies = [ "argon2", "perry-ffi", @@ -4964,7 +4964,7 @@ dependencies = [ [[package]] name = "perry-ext-axios" -version = "0.5.907" +version = "0.5.908" dependencies = [ "perry-ffi", "reqwest", @@ -4973,7 +4973,7 @@ dependencies = [ [[package]] name = "perry-ext-bcrypt" -version = "0.5.907" +version = "0.5.908" dependencies = [ "bcrypt", "perry-ffi", @@ -4981,7 +4981,7 @@ dependencies = [ [[package]] name = "perry-ext-better-sqlite3" -version = "0.5.907" +version = "0.5.908" dependencies = [ "perry-ffi", "rusqlite", @@ -4989,7 +4989,7 @@ dependencies = [ [[package]] name = "perry-ext-cheerio" -version = "0.5.907" +version = "0.5.908" dependencies = [ "perry-ffi", "scraper", @@ -4997,14 +4997,14 @@ dependencies = [ [[package]] name = "perry-ext-commander" -version = "0.5.907" +version = "0.5.908" dependencies = [ "perry-ffi", ] [[package]] name = "perry-ext-cron" -version = "0.5.907" +version = "0.5.908" dependencies = [ "chrono", "cron", @@ -5013,7 +5013,7 @@ dependencies = [ [[package]] name = "perry-ext-dayjs" -version = "0.5.907" +version = "0.5.908" dependencies = [ "chrono", "perry-ffi", @@ -5021,7 +5021,7 @@ dependencies = [ [[package]] name = "perry-ext-decimal" -version = "0.5.907" +version = "0.5.908" dependencies = [ "perry-ffi", "rust_decimal", @@ -5029,7 +5029,7 @@ dependencies = [ [[package]] name = "perry-ext-dotenv" -version = "0.5.907" +version = "0.5.908" dependencies = [ "perry-ffi", "serde_json", @@ -5037,7 +5037,7 @@ dependencies = [ [[package]] name = "perry-ext-ethers" -version = "0.5.907" +version = "0.5.908" dependencies = [ "perry-ffi", "rand 0.8.6", @@ -5045,21 +5045,21 @@ dependencies = [ [[package]] name = "perry-ext-events" -version = "0.5.907" +version = "0.5.908" dependencies = [ "perry-ffi", ] [[package]] name = "perry-ext-exponential-backoff" -version = "0.5.907" +version = "0.5.908" dependencies = [ "perry-ffi", ] [[package]] name = "perry-ext-fastify" -version = "0.5.907" +version = "0.5.908" dependencies = [ "bytes", "http-body-util", @@ -5073,7 +5073,7 @@ dependencies = [ [[package]] name = "perry-ext-fetch" -version = "0.5.907" +version = "0.5.908" dependencies = [ "lazy_static", "perry-ffi", @@ -5084,7 +5084,7 @@ dependencies = [ [[package]] name = "perry-ext-http" -version = "0.5.907" +version = "0.5.908" dependencies = [ "lazy_static", "perry-ext-http-server", @@ -5096,7 +5096,7 @@ dependencies = [ [[package]] name = "perry-ext-http-server" -version = "0.5.907" +version = "0.5.908" dependencies = [ "bytes", "http-body-util", @@ -5115,7 +5115,7 @@ dependencies = [ [[package]] name = "perry-ext-ioredis" -version = "0.5.907" +version = "0.5.908" dependencies = [ "lazy_static", "perry-ffi", @@ -5125,7 +5125,7 @@ dependencies = [ [[package]] name = "perry-ext-jsonwebtoken" -version = "0.5.907" +version = "0.5.908" dependencies = [ "base64", "jsonwebtoken", @@ -5136,7 +5136,7 @@ dependencies = [ [[package]] name = "perry-ext-lru-cache" -version = "0.5.907" +version = "0.5.908" dependencies = [ "lru", "perry-ffi", @@ -5144,7 +5144,7 @@ dependencies = [ [[package]] name = "perry-ext-moment" -version = "0.5.907" +version = "0.5.908" dependencies = [ "chrono", "perry-ffi", @@ -5152,7 +5152,7 @@ dependencies = [ [[package]] name = "perry-ext-mongodb" -version = "0.5.907" +version = "0.5.908" dependencies = [ "bson", "futures-util", @@ -5164,7 +5164,7 @@ dependencies = [ [[package]] name = "perry-ext-mysql2" -version = "0.5.907" +version = "0.5.908" dependencies = [ "chrono", "perry-ffi", @@ -5174,7 +5174,7 @@ dependencies = [ [[package]] name = "perry-ext-nanoid" -version = "0.5.907" +version = "0.5.908" dependencies = [ "nanoid", "perry-ffi", @@ -5183,7 +5183,7 @@ dependencies = [ [[package]] name = "perry-ext-net" -version = "0.5.907" +version = "0.5.908" dependencies = [ "perry-ffi", "rustls", @@ -5194,7 +5194,7 @@ dependencies = [ [[package]] name = "perry-ext-nodemailer" -version = "0.5.907" +version = "0.5.908" dependencies = [ "lettre", "perry-ffi", @@ -5204,7 +5204,7 @@ dependencies = [ [[package]] name = "perry-ext-pg" -version = "0.5.907" +version = "0.5.908" dependencies = [ "perry-ffi", "sqlx", @@ -5213,7 +5213,7 @@ dependencies = [ [[package]] name = "perry-ext-ratelimit" -version = "0.5.907" +version = "0.5.908" dependencies = [ "governor", "perry-ffi", @@ -5221,7 +5221,7 @@ dependencies = [ [[package]] name = "perry-ext-sharp" -version = "0.5.907" +version = "0.5.908" dependencies = [ "base64", "image", @@ -5230,14 +5230,14 @@ dependencies = [ [[package]] name = "perry-ext-slugify" -version = "0.5.907" +version = "0.5.908" dependencies = [ "perry-ffi", ] [[package]] name = "perry-ext-streams" -version = "0.5.907" +version = "0.5.908" dependencies = [ "lazy_static", "perry-ffi", @@ -5245,7 +5245,7 @@ dependencies = [ [[package]] name = "perry-ext-uuid" -version = "0.5.907" +version = "0.5.908" dependencies = [ "perry-ffi", "uuid", @@ -5253,7 +5253,7 @@ dependencies = [ [[package]] name = "perry-ext-validator" -version = "0.5.907" +version = "0.5.908" dependencies = [ "perry-ffi", "regex", @@ -5263,7 +5263,7 @@ dependencies = [ [[package]] name = "perry-ext-ws" -version = "0.5.907" +version = "0.5.908" dependencies = [ "futures-util", "lazy_static", @@ -5274,7 +5274,7 @@ dependencies = [ [[package]] name = "perry-ext-zlib" -version = "0.5.907" +version = "0.5.908" dependencies = [ "flate2", "perry-ffi", @@ -5282,7 +5282,7 @@ dependencies = [ [[package]] name = "perry-ffi" -version = "0.5.907" +version = "0.5.908" dependencies = [ "dashmap 6.1.0", "once_cell", @@ -5291,7 +5291,7 @@ dependencies = [ [[package]] name = "perry-hir" -version = "0.5.907" +version = "0.5.908" dependencies = [ "anyhow", "perry-api-manifest", @@ -5305,7 +5305,7 @@ dependencies = [ [[package]] name = "perry-jsruntime" -version = "0.5.907" +version = "0.5.908" dependencies = [ "anyhow", "deno_core", @@ -5325,7 +5325,7 @@ dependencies = [ [[package]] name = "perry-parser" -version = "0.5.907" +version = "0.5.908" dependencies = [ "anyhow", "perry-diagnostics", @@ -5337,7 +5337,7 @@ dependencies = [ [[package]] name = "perry-runtime" -version = "0.5.907" +version = "0.5.908" dependencies = [ "anyhow", "base64", @@ -5361,7 +5361,7 @@ dependencies = [ [[package]] name = "perry-stdlib" -version = "0.5.907" +version = "0.5.908" dependencies = [ "aes", "aes-gcm", @@ -5429,7 +5429,7 @@ dependencies = [ [[package]] name = "perry-transform" -version = "0.5.907" +version = "0.5.908" dependencies = [ "anyhow", "perry-hir", @@ -5439,7 +5439,7 @@ dependencies = [ [[package]] name = "perry-types" -version = "0.5.907" +version = "0.5.908" dependencies = [ "anyhow", "thiserror 1.0.69", @@ -5447,11 +5447,11 @@ dependencies = [ [[package]] name = "perry-ui" -version = "0.5.907" +version = "0.5.908" [[package]] name = "perry-ui-android" -version = "0.5.907" +version = "0.5.908" dependencies = [ "itoa", "jni", @@ -5466,7 +5466,7 @@ dependencies = [ [[package]] name = "perry-ui-geisterhand" -version = "0.5.907" +version = "0.5.908" dependencies = [ "rand 0.8.6", "serde", @@ -5476,7 +5476,7 @@ dependencies = [ [[package]] name = "perry-ui-gtk4" -version = "0.5.907" +version = "0.5.908" dependencies = [ "cairo-rs", "dirs 5.0.1", @@ -5495,7 +5495,7 @@ dependencies = [ [[package]] name = "perry-ui-ios" -version = "0.5.907" +version = "0.5.908" dependencies = [ "block2", "libc", @@ -5510,7 +5510,7 @@ dependencies = [ [[package]] name = "perry-ui-macos" -version = "0.5.907" +version = "0.5.908" dependencies = [ "block2", "libc", @@ -5528,11 +5528,11 @@ version = "0.1.0" [[package]] name = "perry-ui-testkit" -version = "0.5.907" +version = "0.5.908" [[package]] name = "perry-ui-tvos" -version = "0.5.907" +version = "0.5.908" dependencies = [ "block2", "libc", @@ -5547,7 +5547,7 @@ dependencies = [ [[package]] name = "perry-ui-visionos" -version = "0.5.907" +version = "0.5.908" dependencies = [ "block2", "libc", @@ -5562,7 +5562,7 @@ dependencies = [ [[package]] name = "perry-ui-watchos" -version = "0.5.907" +version = "0.5.908" dependencies = [ "block2", "libc", @@ -5575,7 +5575,7 @@ dependencies = [ [[package]] name = "perry-ui-windows" -version = "0.5.907" +version = "0.5.908" dependencies = [ "libc", "perry-runtime", @@ -5589,7 +5589,7 @@ dependencies = [ [[package]] name = "perry-updater" -version = "0.5.907" +version = "0.5.908" dependencies = [ "base64", "ed25519-dalek", @@ -5603,7 +5603,7 @@ dependencies = [ [[package]] name = "perry-wasm-host" -version = "0.5.907" +version = "0.5.908" dependencies = [ "wasmi", ] diff --git a/Cargo.toml b/Cargo.toml index 6164c74dd1..eddb8a1c5f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -190,7 +190,7 @@ opt-level = "s" # Optimize for size in stdlib opt-level = 3 [workspace.package] -version = "0.5.907" +version = "0.5.908" edition = "2021" license = "MIT" repository = "https://github.com/PerryTS/perry" diff --git a/test-coverage/COVERAGE.md b/test-coverage/COVERAGE.md index 86a36f7f5d..a11671b852 100644 --- a/test-coverage/COVERAGE.md +++ b/test-coverage/COVERAGE.md @@ -1,6 +1,6 @@ # Perry FFI Test Coverage -Generated: 2026-05-14T05:30:25Z +Generated: 2026-05-14T05:37:01Z ## Summary diff --git a/test-files/test_ffi_surface_stdlib_integrations.ts b/test-files/test_ffi_surface_stdlib_integrations.ts index b27cd589b4..df27cae358 100644 --- a/test-files/test_ffi_surface_stdlib_integrations.ts +++ b/test-files/test_ffi_surface_stdlib_integrations.ts @@ -6,7 +6,7 @@ // inventory into behavioral tests as each area gets deeper compatibility // coverage. // -// Inventory entries: 156 unique FFI names, 156 declarations. +// Inventory entries: 138 unique FFI names, 138 declarations. const testFfiSurfaceStdlibIntegrationsVersion = 1; if (testFfiSurfaceStdlibIntegrationsVersion !== 1) { @@ -17,10 +17,8 @@ console.log("test_ffi_surface_stdlib_integrations: ok"); /* @covers crates/perry-stdlib/src/argon2.rs: - - js_argon2_hash - js_argon2_hash_sync - js_argon2_needs_rehash - - js_argon2_verify - js_argon2_verify_sync crates/perry-stdlib/src/bcrypt.rs: - js_bcrypt_compare @@ -50,33 +48,21 @@ crates/perry-stdlib/src/cheerio.rs: crates/perry-stdlib/src/crypto.rs: - js_crypto_aes256_decrypt - js_crypto_aes256_encrypt - - js_crypto_create_hash - js_crypto_ed25519_verify - js_crypto_hmac_sha256 - js_crypto_hmac_sha256_bytes - - js_crypto_md5 - - js_crypto_pbkdf2 - - js_crypto_pbkdf2_bytes - js_crypto_random_bytes_buffer - js_crypto_random_bytes_hex - js_crypto_random_uuid - js_crypto_scrypt - js_crypto_scrypt_custom - - js_crypto_sha256 - - js_crypto_sha256_bytes crates/perry-stdlib/src/crypto_e2e.rs: - js_crypto_aes256_gcm_decrypt - js_crypto_aes256_gcm_encrypt - - js_crypto_hkdf_sha256 - js_crypto_random_nonce - js_crypto_x25519_keypair - js_crypto_x25519_shared_secret crates/perry-stdlib/src/ethers.rs: - - js_ethers_format_ether - - js_ethers_format_units - - js_ethers_get_address - - js_ethers_parse_ether - - js_ethers_parse_units - js_ethers_wallet_create_random - js_keccak256_native - js_keccak256_native_bytes @@ -183,9 +169,4 @@ crates/perry-stdlib/src/sharp.rs: - js_sharp_to_file - js_sharp_webp - js_sharp_width -crates/perry-stdlib/src/webcrypto.rs: - - js_webcrypto_digest - - js_webcrypto_import_key - - js_webcrypto_sign - - js_webcrypto_verify */ diff --git a/test-files/test_parity_argon2.ts b/test-files/test_parity_argon2.ts new file mode 100644 index 0000000000..e8af531457 --- /dev/null +++ b/test-files/test_parity_argon2.ts @@ -0,0 +1,40 @@ +// Behavioral parity test for the `argon2` npm wrapper. +// +// Perry routes `import argon2 from "argon2"` to perry-ext-argon2. Node +// would need the npm package installed; we use the expected-output +// mechanism instead. +// +// argon2.hash() embeds a random salt, so the literal hash output is +// non-deterministic. We assert by shape (`$argon2id$` prefix) and by +// round-trip argon2.verify against a freshly-produced hash. Only the +// async path is wired in Perry's dispatch +// (see crates/perry-codegen/src/lower_call.rs: `argon2.hash` / `verify`). +// +// @covers +// crates/perry-stdlib/src/argon2.rs: +// - js_argon2_hash +// - js_argon2_verify + +import argon2 from "argon2"; + +async function main() { + const hash = await argon2.hash("perry-parity"); + console.log("hash starts $argon2id$:", hash.startsWith("$argon2id$")); + console.log("hash typeof:", typeof hash); + + const ok = await argon2.verify(hash, "perry-parity"); + console.log("verify correct:", ok); + + const bad = await argon2.verify(hash, "wrong-password"); + console.log("verify wrong:", bad); + + // A second hash of the same password produces a different hash (salt + // changes) but still verifies. This confirms verify isn't just a + // string-equality check. + const hash2 = await argon2.hash("perry-parity"); + console.log("two hashes differ:", hash !== hash2); + console.log("verify second:", await argon2.verify(hash2, "perry-parity")); +} + +await main(); +console.log("argon2 parity: ok"); diff --git a/test-files/test_parity_crypto.ts b/test-files/test_parity_crypto.ts index 0755d5458b..7f8a1bac15 100644 --- a/test-files/test_parity_crypto.ts +++ b/test-files/test_parity_crypto.ts @@ -3,6 +3,21 @@ // This file is a byte-for-byte parity test against `node --experimental-strip-types`. // Edit the TODO lines below to exercise each API; rerun // `./run_parity_tests.sh --filter test_parity_crypto` to verify. +// +// @covers +// crates/perry-stdlib/src/crypto.rs: +// - js_crypto_create_hash +// - js_crypto_md5 +// - js_crypto_pbkdf2_bytes +// - js_crypto_sha256 +// - js_crypto_sha256_bytes +// crates/perry-stdlib/src/crypto_e2e.rs: +// - js_crypto_hkdf_sha256 +// crates/perry-stdlib/src/webcrypto.rs: +// - js_webcrypto_digest +// - js_webcrypto_import_key +// - js_webcrypto_sign +// - js_webcrypto_verify import * as crypto from "node:crypto"; diff --git a/test-files/test_parity_ethers.ts b/test-files/test_parity_ethers.ts new file mode 100644 index 0000000000..594cbdaeea --- /dev/null +++ b/test-files/test_parity_ethers.ts @@ -0,0 +1,36 @@ +// Behavioral parity test for the `ethers` npm utility surface. +// +// Perry routes `import ... from "ethers"` to perry-ext-ethers. The +// numeric/address helpers are pure functions of their inputs, so the +// output is byte-for-byte deterministic. Node would need the npm package +// installed; we use the expected-output mechanism instead. +// +// @covers +// crates/perry-stdlib/src/ethers.rs: +// - js_ethers_format_ether +// - js_ethers_format_units +// - js_ethers_get_address +// - js_ethers_parse_ether +// - js_ethers_parse_units + +import { formatEther, formatUnits, getAddress, parseEther, parseUnits } from "ethers"; + +// EIP-55 checksum. +console.log("getAddress lower:", getAddress("0x5aaeb6053f3e94c9b9a09f33669435e7ef1beaed")); +console.log("getAddress upper:", getAddress("0X5AAEB6053F3E94C9B9A09F33669435E7EF1BEAED")); + +// parseEther / formatEther round-trip — 1.5 ETH → 1500000000000000000 wei. +const oneAndHalf = parseEther("1.5"); +console.log("parseEther 1.5:", oneAndHalf.toString()); +console.log("formatEther round-trip:", formatEther(oneAndHalf)); + +// parseUnits / formatUnits at common decimal positions. +const usdc = parseUnits("123.456789", 6); +console.log("parseUnits 6dec:", usdc.toString()); +console.log("formatUnits 6dec:", formatUnits(usdc, 6)); + +const gwei = parseUnits("25", 9); +console.log("parseUnits gwei:", gwei.toString()); +console.log("formatUnits gwei:", formatUnits(gwei, 9)); + +console.log("ethers parity: ok"); diff --git a/test-parity/expected/test_parity_argon2.txt b/test-parity/expected/test_parity_argon2.txt new file mode 100644 index 0000000000..b82f524648 --- /dev/null +++ b/test-parity/expected/test_parity_argon2.txt @@ -0,0 +1,7 @@ +hash starts $argon2id$: true +hash typeof: string +verify correct: true +verify wrong: false +two hashes differ: true +verify second: true +argon2 parity: ok diff --git a/test-parity/expected/test_parity_ethers.txt b/test-parity/expected/test_parity_ethers.txt new file mode 100644 index 0000000000..ac17db9e5a --- /dev/null +++ b/test-parity/expected/test_parity_ethers.txt @@ -0,0 +1,9 @@ +getAddress lower: 0x5aAeb6053F3E94C9b9A09f33669435E7Ef1BeAed +getAddress upper: 0x5aAeb6053F3E94C9b9A09f33669435E7Ef1BeAed +parseEther 1.5: 1500000000000000000 +formatEther round-trip: 1.500000000000000000 +parseUnits 6dec: 123456789 +formatUnits 6dec: 123.456789 +parseUnits gwei: 25000000000 +formatUnits gwei: 25.000000000 +ethers parity: ok