Skip to content

Commit 6f0168d

Browse files
committed
enhanced tests adn CI
1 parent 86c05e3 commit 6f0168d

5 files changed

Lines changed: 115 additions & 5 deletions

File tree

.github/clippy-wasm/clippy.toml

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
# WASM-only clippy configuration.
2+
#
3+
# Loaded by the `test-wasm` job in flutter-ci.yml via CLIPPY_CONF_DIR. Bans
4+
# stdlib time APIs that compile cleanly on wasm32-unknown-unknown but panic at
5+
# runtime with "time not implemented on this platform". Native clippy never
6+
# loads this file, so heartbeat/WAL/retry-backoff code that's
7+
# `#[cfg(not(target_arch = "wasm32"))]`-gated remains free to use SystemTime.
8+
disallowed-methods = [
9+
{ path = "std::time::Instant::now", reason = "panics on wasm32; use web_time::Instant::now()" },
10+
{ path = "std::time::SystemTime::now", reason = "panics on wasm32; use fula_crypto::time::now_timestamp() or web_time" },
11+
]

.github/workflows/flutter-ci.yml

Lines changed: 48 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -41,11 +41,14 @@ jobs:
4141
shared-key: rust-ci
4242

4343
- name: Run Rust tests
44-
run: |
45-
cargo test -p fula-flutter --lib
46-
cargo test -p fula-js --lib
47-
cargo test -p fula-client --lib
48-
cargo test -p fula-crypto --lib
44+
# `--workspace --all-targets` covers lib + integration tests under each
45+
# crate's tests/ AND the workspace-root tests/. The previous
46+
# `-p X --lib` form silently excluded tests/migration_tests.rs and the
47+
# rest of the integration suite, so bugs that integration tests would
48+
# have caught (including v1→v7 migration correctness on native) never
49+
# gated PRs. `--no-fail-fast` lets every failure report on the first
50+
# run with the broader scope.
51+
run: cargo test --workspace --all-targets --no-fail-fast
4952

5053
# Test WASM compilation (fula-js npm package)
5154
test-wasm:
@@ -79,6 +82,46 @@ jobs:
7982
grep -q "deriveKey" crates/fula-js/pkg/fula_js.d.ts
8083
echo "All expected exports found!"
8184
85+
# Layer 1: ban panic-on-wasm stdlib time APIs at compile time.
86+
# The disallowed-methods config lives at `.github/clippy-wasm/clippy.toml`
87+
# and is loaded only here via `CLIPPY_CONF_DIR`, so native clippy never
88+
# sees the bans (cfg(not(target_arch = "wasm32"))-gated heartbeat / WAL /
89+
# retry-backoff code in encryption.rs is free to keep using SystemTime).
90+
# Two clippy invocations are needed because fula-crypto's default features
91+
# include `tokio-runtime`, which doesn't compile on wasm32. The other
92+
# crates pull fula-crypto with `default-features = false, features = ["wasm"]`
93+
# via target-conditional deps, but a direct `-p fula-crypto` would use its
94+
# own defaults. We use `-D clippy::disallowed_methods` (not `-D warnings`)
95+
# to scope the failure mode to the panic-on-wasm bug class only — pre-existing
96+
# style/idiom warnings in the workspace shouldn't gate this PR.
97+
#
98+
# `--lib` only: integration tests under `tests/` pull in tokio with full
99+
# features and don't compile on wasm32. The lint applies to library code,
100+
# which is what actually ships into the browser bundle.
101+
- name: WASM clippy — fula-client / fula-flutter / fula-js
102+
env:
103+
CLIPPY_CONF_DIR: ${{ github.workspace }}/.github/clippy-wasm
104+
run: |
105+
cargo clippy --target wasm32-unknown-unknown \
106+
-p fula-client -p fula-flutter -p fula-js \
107+
--lib -- -D clippy::disallowed_methods
108+
109+
- name: WASM clippy — fula-crypto (forced wasm features)
110+
env:
111+
CLIPPY_CONF_DIR: ${{ github.workspace }}/.github/clippy-wasm
112+
run: |
113+
cargo clippy --target wasm32-unknown-unknown \
114+
-p fula-crypto --no-default-features --features wasm \
115+
--lib -- -D clippy::disallowed_methods
116+
117+
# Layer 2: actually exercise the time wiring at runtime in a browser.
118+
# Catches dependency-config regressions clippy can't see (e.g. someone
119+
# later sets default-features = false on chrono and drops `wasmbind`).
120+
- name: Install Firefox + geckodriver for wasm-pack test
121+
uses: browser-actions/setup-firefox@v1
122+
- name: WASM runtime smoke tests
123+
run: wasm-pack test --headless --firefox crates/fula-flutter
124+
82125
# Generate and validate Dart bindings
83126
generate-bindings:
84127
runs-on: ubuntu-latest

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/fula-flutter/Cargo.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,9 @@ async-lock = "3.4"
5353
[dev-dependencies]
5454
# For WASM tests
5555
wasm-bindgen-test = "0.3"
56+
# Used by tests/wasm_time_smoke.rs to assert that the wasm-incompat stdlib
57+
# time APIs aren't re-introduced into the migration path.
58+
web-time = "1"
5659

5760
[features]
5861
default = []
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
//! WASM regression tests for the v1→v7 forest migration time-API panic.
2+
//!
3+
//! Background: `std::time::Instant::now()` and `std::time::SystemTime::now()`
4+
//! compile cleanly on `wasm32-unknown-unknown` but panic at runtime with
5+
//! "time not implemented on this platform". The migration code path used both
6+
//! at module level (un-gated by `cfg(not(target_arch = "wasm32"))`), so any
7+
//! browser user listing a v1-format bucket panicked the WASM module.
8+
//!
9+
//! These tests exercise the public surface of the time wiring so a regression
10+
//! that drops `web-time` from `fula-client`'s deps, removes the `wasmbind`
11+
//! feature on chrono, or re-introduces a raw stdlib time call inside an
12+
//! ungated code path will fail CI's `wasm-pack test` step instead of
13+
//! reaching production.
14+
//!
15+
//! Run with: `wasm-pack test --headless --firefox crates/fula-flutter`
16+
17+
#![cfg(target_arch = "wasm32")]
18+
19+
use wasm_bindgen_test::*;
20+
21+
wasm_bindgen_test_configure!(run_in_browser);
22+
23+
/// Validates that `web_time::Instant::now()` — the replacement for
24+
/// `std::time::Instant::now()` at `fula-client/src/encryption.rs:3600` — wires
25+
/// through to `performance.now()` without panicking.
26+
#[wasm_bindgen_test]
27+
fn web_time_instant_now_does_not_panic() {
28+
let _ = web_time::Instant::now();
29+
}
30+
31+
/// Validates that `fula_crypto::time::now_timestamp()` — the wrapper used at
32+
/// `fula-crypto/src/private_forest.rs:292, 368, 1125, 1350` — returns a
33+
/// plausible Unix timestamp from the JS Date API on WASM.
34+
#[wasm_bindgen_test]
35+
fn fula_crypto_now_timestamp_returns_current_seconds() {
36+
let ts = fula_crypto::time::now_timestamp();
37+
assert!(
38+
ts > 1_700_000_000,
39+
"expected a post-2023 Unix timestamp, got {ts}",
40+
);
41+
}
42+
43+
/// Constructs a `PrivateForest` via the public `with_format` constructor
44+
/// (`fula-crypto/src/private_forest.rs:287`). Before the fix, that constructor
45+
/// called `std::time::SystemTime::now().duration_since(...)` at line 292 and
46+
/// panicked under WASM. The fix routes through `crate::time::now_timestamp()`;
47+
/// this test catches a regression that re-introduces the raw stdlib call.
48+
#[wasm_bindgen_test]
49+
fn private_forest_with_format_does_not_panic_on_wasm() {
50+
use fula_crypto::{ForestFormat, PrivateForest};
51+
let _ = PrivateForest::with_format(ForestFormat::FlatMapV1);
52+
}

0 commit comments

Comments
 (0)