# v0.49.0 — Test Infrastructure Hardening > **Theme:** Replace false-confidence tests with provably-correct synchronization; > fill the unit-test and fuzz coverage gaps identified in the v10 overall > assessment; decompose the scheduler monolith. ## Why This Release The v10 overall assessment found that pg_trickle's core algorithms are mathematically sound — all P0 correctness issues are closed. The remaining risk is concentrated in **coverage confidence**: tests that look correct but cannot actually detect the failures they were written to catch, and source modules that can only be validated through expensive E2E runs because they have zero unit test coverage. This release fixes the test foundation so that every subsequent hardening investment lands on solid ground. ## Deliverables ### TEST-10-01 — Concurrency Test Synchronization Overhaul All tests in `tests/e2e_concurrent_tests.rs` currently use `tokio::time::sleep(Duration::from_millis(50))` to simulate overlap between concurrent operations. This is unreliable: on a loaded CI runner the 50ms window may not be enough, and there is no guarantee the spawned tasks are actually executing concurrently. Replace with `pg_locks`-polling loops that wait until the target transaction is actually visible in `pg_locks` before proceeding. Add a timeout with a clear failure message so flakiness becomes a named error rather than a silent pass. Affected tests: - `test_pb1_concurrent_refresh_skip_locked_no_corruption` - `test_concurrent_inserts_during_refresh` - `test_concurrent_refresh_and_drop` - `test_concurrent_refresh_multiple_sts_same_source` ### TEST-10-02 — 10-Module Unit Test Sweep Add `#[cfg(test)]` modules with focused unit tests for pure-logic functions in every module that currently has zero test coverage: | Module | Key logic to test | |--------|-------------------| | `src/catalog.rs` | ST lookup, OID resolution, metadata serialization | | `src/template_cache.rs` | Cache hit/miss/eviction logic, hash key derivation | | `src/ivm.rs` | Lock mode selection for given operator trees | | `src/cdc/polling.rs` | LSN range splitting, synthetic slot naming | | `src/cdc/rebuild.rs` | Trigger body SQL generation, reserved column mapping | | `src/diagnostics.rs` | Status field population, staleness calculation | | `src/logging.rs` | Log-level routing, message formatting | | `src/metrics_server.rs` | Metric serialization format | | `src/otel.rs` | Span creation, attribute propagation | ### TEST-10-03 — Fuzz Targets for Merge Codegen and Row Identity Add two new `libFuzzer` fuzz targets: 1. **`fuzz/merge_sql_fuzz.rs`** — generates random change streams (random insert/update/delete counts, random column types, random key cardinalities) and feeds them into the full merge SQL construction pipeline (`src/refresh/merge/`). Validates that the generated SQL is valid UTF-8, does not contain unresolved placeholders, and round-trips through a PostgreSQL parse-only check. 2. **`fuzz/row_id_fuzz.rs`** — generates random operator trees with random source schemas and feeds them into the row identity tracking logic (`src/dvm/row_id.rs`). Validates that the keyed/keyless classification is deterministic and that generated row-id expressions are syntactically valid. Both targets are added to the nightly fuzz workflow. ### TEST-10-04 — DDL During Concurrent Refresh E2E Test Add `test_ddl_during_concurrent_refresh` to `tests/e2e_concurrent_tests.rs`. This test: 1. Creates a stream table and populates it. 2. Starts a long-running refresh in a background task. 3. Concurrently issues `ALTER STREAM TABLE ... SET query = '...'`. 4. Verifies that either: - The DDL completes and the next refresh uses the new query, or - The DDL is blocked until the refresh completes (no torn state). 5. Runs three refresh cycles to confirm the stream table remains correct. ### CI-10-02 — Expand e2e-Smoke Filter The current PR smoke test filter matches only 4 test name patterns (`smoke`, `basic`, `create_stream_table`, `health_check`). An operator-level regression in JOIN or AGG handling would pass this gate undetected. Expand the filter to also match: - `test_.*join.*` — inner/left/full join correctness - `test_.*aggregate.*` — aggregate differential correctness - `test_.*window.*` — window function correctness - `test_.*subquery.*` — correlated subquery correctness ### CI-10-03 — Consolidated Fuzz Recipe Add `just fuzz-all` to the `justfile` that runs all fuzz targets in sequence with a configurable corpus duration (default 60s each). Document the available fuzz targets and their corpus locations in `CONTRIBUTING.md`. ### CQ-10-01 — Scheduler Module Decomposition `src/scheduler/mod.rs` is 6,700+ lines — the largest single file in the codebase and a source of high merge-conflict risk. Extract into focused submodules: | New file | Content | |----------|---------| | `src/scheduler/loop.rs` | Main scheduling loop, tick logic, SIGTERM handling | | `src/scheduler/dispatch.rs` | Parallel dispatch state, worker claiming, orphan reaping | | `src/scheduler/cost.rs` | (already exists — ensure complete) | | `src/scheduler/watermark.rs` | Tick watermark computation, xmin holdback, frontier advance | `mod.rs` becomes a thin re-export facade. All existing public API is preserved with no behaviour change. ## Testing - `just test-unit` — all new unit tests pass - `just test-integration` — concurrency tests pass with `pg_locks`-polling sync - `just test-light-e2e` — smoke filter expansion catches more regressions - `cargo fuzz run merge_sql_fuzz -- -max_total_time=60` — no crashes - `cargo fuzz run row_id_fuzz -- -max_total_time=60` — no crashes