> **Plain-language companion:** [v0.49.0.md](v0.49.0.md) ## v0.49.0 — Test Infrastructure Hardening & Scheduler Decomposition **Status: ✅ Released.** > **Release Theme** > Replace false-confidence tests with provably-correct synchronization primitives; > fill the unit-test and fuzz coverage gaps identified in the v10 overall > assessment; and decompose the scheduler monolith to reduce merge-conflict risk > and improve reviewability of future scheduler changes. --- ### Deliverables | ID | Title | Effort | Priority | Status | |----|-------|--------|----------|--------| | TEST-10-01 | Concurrency test synchronization overhaul | M | P1 | ✅ Done | | TEST-10-02 | 10-module unit test sweep | M | P1 | ✅ Done | | TEST-10-03 | Fuzz targets: merge SQL codegen & row identity | M | P2 | ✅ Done | | TEST-10-04 | DDL-during-concurrent-refresh E2E test | S | P2 | ✅ Done | | CI-10-02 | Expand e2e-smoke filter | S | P2 | ✅ Done | | CI-10-03 | Consolidated fuzz recipe (`just fuzz-all`) | S | P3 | ✅ Done | | CQ-10-01 | Scheduler module decomposition | L | P2 | ✅ Done | --- ### TEST-10-01 — Concurrency Test Synchronization Overhaul **Problem:** All concurrent E2E tests used `tokio::time::sleep` to simulate operation overlap. On a loaded CI runner the fixed delay is insufficient to guarantee concurrency, producing tests that may pass even when the underlying behaviour is broken. **Fix:** Added `wait_for_active_query` helper in `tests/e2e_concurrent_tests.rs` that polls `pg_stat_activity` until the target query fragment appears (or a configurable timeout elapses). All four affected tests (`test_pb1_*`, `test_concurrent_refresh_and_drop`, `test_conc1_alter_while_refresh`, `test_conc2_drop_while_refresh`) now use this polling helper. --- ### TEST-10-02 — 10-Module Unit Test Sweep Added focused `#[cfg(test)]` modules to three modules that had zero unit test coverage: - **`src/template_cache.rs`** — hash i64 round-trip, OID round-trip, purge guard condition logic. - **`src/cdc/polling.rs`** — `build_pk_hash_expr` for single/multi/escaped column names. - **`src/cdc/rebuild.rs`** — trigger name format, CDC mode classification, replica identity sufficiency. Other modules in the sweep (`catalog.rs`, `ivm.rs`, `diagnostics.rs`, `logging.rs`, `metrics_server.rs`, `otel.rs`) already had adequate coverage from existing test suites. --- ### TEST-10-03 — Fuzz Targets for Merge Codegen and Row Identity Two new libFuzzer targets: **`fuzz/fuzz_targets/merge_sql_fuzz.rs`** (FUZZ-7): - Fuzzes `pg_quote_literal`, `parse_hash_bound_spec`, `extract_keyword_int`, amplification ratio computation, and `build_content_hash_expr`. - Validates: no panics, UTF-8 output, deterministic results. **`fuzz/fuzz_targets/row_id_fuzz.rs`** (FUZZ-8): - Fuzzes `RowIdSchema` construction and pipeline verification. - Validates: reflexivity (Any/Derived/PassThrough always compatible with themselves), no panics on arbitrary byte input. Public wrapper module `src/fuzz_pub.rs` added to expose the otherwise-crate- private pipeline functions to the fuzz harness. --- ### TEST-10-04 — DDL During Concurrent Refresh E2E Test Added `test_ddl_during_concurrent_refresh` to `tests/e2e_concurrent_tests.rs`: 1. Creates a stream table with 100 rows. 2. Inserts 200 more rows, then fires a refresh and an `ALTER STREAM TABLE` concurrently using the `wait_for_active_query` synchronization helper. 3. Asserts catalog status is `ACTIVE` or `ERROR` after the race (no torn state). 4. Runs three convergence refreshes and asserts final row count is 300. --- ### CI-10-02 — Expanded e2e-Smoke Filter The PR smoke test now matches five additional pattern families: - `test_.*join.*` - `test_.*aggregate.*` - `test_.*window.*` - `test_.*subquery.*` This ensures operator-level regressions in the DVM engine are caught by the per-PR smoke gate. --- ### CI-10-03 — Consolidated Fuzz Recipe - Added `just fuzz-all` to `justfile` — runs each registered fuzz target for a configurable time (default `FUZZ_TIME=60` seconds). - Added fuzz target table and corpus path documentation to `CONTRIBUTING.md`. --- ### CQ-10-01 — Scheduler Module Decomposition **Before:** `src/scheduler/mod.rs` was ≈6,700 lines — the largest single file in the codebase and a high merge-conflict surface. **After:** Three new focused submodules extracted: | New file | Content | |----------|---------| | `src/scheduler/dispatch.rs` | Parallel dispatch state (`ParallelDispatchState`, `UnitDispatchState`), dynamic worker spawn, worker claiming, orphan reaping, adaptive poll-interval logic | | `src/scheduler/scheduler_loop.rs` | BGW registration functions, launcher main loop, per-database scheduler main loop | | `src/scheduler/watermark.rs` | Tick watermark computation, xmin holdback warning, frontier advance helpers | `mod.rs` is now a re-export façade that re-exports all public items previously defined inline. All existing public API is preserved with no behaviour change. The test module in `mod.rs` imports the moved items via `use super::dispatch::{...}` so all unit tests continue to pass.