Skip to content

test: region-coverage push (S6-S8 + post-merge restore)#188

Merged
singaraiona merged 7 commits intomasterfrom
tests/coverage-region-push
May 5, 2026
Merged

test: region-coverage push (S6-S8 + post-merge restore)#188
singaraiona merged 7 commits intomasterfrom
tests/coverage-region-push

Conversation

@ser-vasilich
Copy link
Copy Markdown
Collaborator

Summary

Multi-stage region-coverage push for src/. Five distinct stages of parallel-agent test work plus an after-merge restore of two files that regressed past 80%.

Files crossing 80% region coverage (over the whole branch):

Stage Files
S6 src/ops/group.c, src/ops/sort.c, src/store/journal.c, src/core/hash.c
S7 src/ops/compile.c, src/lang/format.c, src/store/splay.c, src/runtime/sort.c (+2 more)
S8 src/ops/index.c, src/runtime/embedding.c, src/runtime/graph_builtin.c, src/runtime/runtime.c, src/lang/parse.c
post-merge src/ops/query.c (restored after Anton's 924a335a perf hoist), src/core/ipc.c (restored after lazy IPC fixes)

Real bugs fixed (visible in src/):

  • src/ops/traverse.cuint8_t depth overflow at 255 in exec_shortest_path and var_expand causing infinite loops on deep/disconnected graphs (S8 commit). Promoted to int.
  • src/core/ipc.c (earlier S6) — auth realloc preserving cred_len byte; removed dead ipc_send_fn and ipc_on_data.
  • src/store/serde.c — F32 atom ser/de mismatch (was reading garbage from &obj->i32).
  • src/ops/internal.hpar_prepare_nullmap probed at idx=0 (never promoted to EXT); now probes at vec->len-1.

Surfaced uncoverable structural ceilings (deferred to design discussion):

  • src/core/block.c 65% — weak ray_alloc stub never linked
  • src/ops/traverse.c 76.6% — graph algorithm OOM-injection paths
  • src/lang/eval.c 78.5% — if (0 && ...) dead-code block at line 344 (came in with v2-engine import 4a3a0c724)

Test plan

  • Full suite passes locally on Linux (clang/gcc): 2332 of 2333 PASS, 1 SKIP, 0 FAIL — the skip is the explicit MUNIT_SKIP in runtime/create_with_sym_oversized_file.
  • Two origin/master merges integrated cleanly (no conflicts).
  • Portability check on new files (.portability-check.sh) — no Linux-only headers without macOS guard.
  • CI matrix (Linux + macOS, debug + release) on push — please verify before merge.

🤖 Generated with Claude Code

ser-vasilich and others added 7 commits May 4, 2026 16:58
| File              | Regions Before → After | Tests |
|-------------------|------------------------|-------|
| src/store/col.c   | 79.03% → 86.22%        | +12   |
| src/core/epoll.c  | 79.75% → 87.34%        | +3    |
| src/store/hnsw.c  | 79.63% → 83.14%        | +4    |
| src/ops/exec.c    | 86.99% → 88.38%        | +9    |

Region coverage measures branch paths (taken vs not-taken arms,
switch defaults, error guards) — typically the strictest of the
four metrics.  Files near 80% on regions usually reach there via
type-specific arms, error-path branches, and edge-case inputs.

No src/ changes.  No static-expose, no mocks.  Each agent ran in
an isolated worktree and used an exclusive test file (test_store.c,
test_pool.c, test_embedding.c, test_exec.c) to avoid merge conflicts.

Highlights:

  col.c — type-specific save/load arms (BOOL/U8/I16/DATE/TIME/
    TIMESTAMP), W32/W64 sym validation, 0-length / corrupt /
    truncated file paths, recursive atom serialization in lists.

  epoll.c — selector-array growth past initial cap, EPOLLHUP error
    branches with and without error_fn registered.  Remaining gaps
    are mmap/epoll_ctl/epoll_wait fault-injection paths.

  hnsw.c — public ray_hnsw_dim accessor, search_filter NULL accept
    branch, ray_hnsw_mmap (was entirely uncovered), maxheap_sift_down
    full-path via ef_construction=1 stress test.  prune_neighbors
    body remains uncovered — caller-side invariant (M_max_l == M_keep)
    makes it effectively dead code under current build logic.

  exec.c — FILTER+GROUP empty parted, HEAD/TAIL parted SYM esz
    mismatch, OP_SHORTEST_PATH src-error cleanup, streaming seg-mask
    mismatch, MAPCOMMON kv types (LIST/SEL) in build_segment_table
    and empty-build paths.

Tests 2067 → 2124 passing (1 pre-existing skip).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
| File              | Regions Before → After | Tests |
|-------------------|------------------------|-------|
| src/core/sock.c   | 75.95% → 82.28%        | +4    |
| src/ops/rerank.c  | 75.15% → 80.12%        | +10   |
| src/ops/string.c  | 75.55% → 82.64%        | +25   |
| src/ops/idxop.c   | 75.61% → 90.41%        | +23   |
| src/ops/opt.c     | 76.10% → 80.07%        | +28   |
| src/ops/collection.c | 77.04% → 82.03%     | +rfl (~100 asserts) |

TOTAL regions 82.13% → 83.13%.  Tests 2124 → 2215 passing.

No src/ changes.  No static-expose, no mocks.  Each agent ran in
an isolated worktree and used an exclusive test file.

Highlights:

  sock.c — 4 tests for socket close-on-invalid, listen-bind-failure
    (EADDRINUSE), connect bad host, connect zero-timeout branch.

  rerank.c — 10 tests covering rr_at_f64 type arms (I32/I64/F64),
    empty source, all-filter-rejected, identity-scan + filtered-scan
    bad-row paths, nullable col gather, heap right-child wins in
    percolate-down, cosine zero-query.

  string.c — 25 tests: like/ilike non-string fallback, SYM-column
    null propagation in upper/lower/trim/strlen/substr/replace,
    F64/I32/I64 atom and vector start/len for substr, >16-arg concat
    (scratch_calloc path), >8KB string scratch_alloc.

  idxop.c — 23 tests: numeric_elem_size and zone_scan arms for every
    type (BOOL/U8/I16/I32/F32/DATE/TIME/TIMESTAMP), all-null zone,
    NaN bucket, slice attach guard, direct ray_index_retain_payload
    + ray_index_release_saved + ray_index_retain_saved STR/SYM and
    NULLMAP_EXT branches (~94 regions reachable only via direct
    idxop.h API), bloom null-skip, GUID-unsupported error.

  opt.c — 28 tests for fold_binary_const F64/I64/I32 (DIV/MIN/MAX),
    atom_to_numeric -RAY_I16 arm, promote_type, partition pruning
    scalar EQ/NE/LT/LE/GT + AND-merge + I32 keys, factorize
    expand→group _src key detection, fold_filter_const_predicate.

  collection.c — new test/rfl/collection/collection_coverage.rfl
    (35 sections, ~100 asserts) covering boxed-list paths for
    distinct/union/sect/except, fold-left/-right aliases, binr
    scalar atom, range-take past-end on list/STR/dict, scan empty,
    map binary scalar, atom_eq timestamp, map-right scalar-vec swap.

Tests 2124 → 2215 passing (1 pre-existing skip).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
| File              | Regions Before → After | Tests |
|-------------------|------------------------|-------|
| src/ops/strop.c   | 74.17% → 87.71%        | +14   |
| src/ops/system.c  | 73.40% → 84.22%        | +14   |
| src/ops/graph_builtin.c | 78.80% → 85.28%   | +11   |
| src/ops/pivot.c   | 72.60% → 80.59%        | +12 rfl |
| src/ops/window.c  | 71.43% → 81.20%        | +25   |
| src/ops/traverse.c | 74.69% → 74.82%       | +rfl + critical fix |

TOTAL regions 83.21% → 83.74%.  Tests 2215 → 2277 passing.

## Bug fix surfaced by S8 traverse.c agent

Added a new `test/rfl/datalog/traverse_coverage.rfl` (403 lines)
covering edge cases for graph algorithms.  One assertion ---
`(.graph.shortest-path DISC 0 3) !- range` (path between two
disconnected components) --- caused the entire test suite to hang
indefinitely.

Root cause in `src/ops/traverse.c`:

    for (uint8_t depth = 1; depth <= max_depth && !found; depth++)

The default `max_depth` is 255 (set by the wrapper in graph_builtin.c).
When `depth` reaches 255 and the BFS queue is empty (target
unreachable), the post-increment `depth++` wraps the unsigned 8-bit
counter to 0, the condition `depth <= 255` is again true, and the
loop spins forever.  The implicit dependence on the inner-loop's
`!found` was the only thing terminating BFS in the connected case;
disconnected graphs simply never set `found` and never exit.

This is a CRITICAL bug --- a malicious or accidental
`shortest-path` query between disconnected components would DoS the
process.  The same pattern lives in `var_expand` (line 340), with
a `front_len > 0` guard that usually saves us but isn't airtight
for graphs whose BFS hasn't terminated by depth 255.

Fix: promote both loop counters to `int`, cast `max_depth` for the
comparison.  No behavioural change for normal inputs; disconnected
inputs now correctly bail with "range" error.

## Process notes

5 of 6 S8 agents cleared 80% regions on their target files.  The
traverse.c agent's rfl tests covered many *lines* but not enough
*regions* — rfl-driven tests tend to hit common branches well but
miss internal-arm coverage that C-level direct-API tests catch.
A follow-up C-level test pass for traverse.c is left for a later
session.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
| File              | Regions Before → After |
|-------------------|------------------------|
| src/ops/query.c   | 75.95% → 80.17% (+4.22pp) |
| src/ops/traverse.c | 74.82% → 76.53% (+1.71pp, ceiling) |

query.c — 12 new sections in test/rfl/ops/query_coverage.rfl:
  - I32/I16/U8/BOOL cast arms in compile_expr_dag
  - KEY_READ non-agg scatter for I32/F64/DATE/BOOL/I16 keys
  - window-join F64 OP_FIRST/OP_LAST + integer OP_VAR/OP_PROD/OP_STDDEV
  - Update no-WHERE: I64→F64 promote, STR broadcast, type errors,
    SYM→LIST broadcast
  - Update WHERE: non-BOOL mask, SYM→I64 type error, F64 promote
  - nearest+by: domain error
  - Eval-level group-by empty-groups + no-agg with STR/LIST cols
  - insert table row with STR column (lines 4795-4806)
  - nearest take: error paths (I32/F64/zero)
  - ANN with I32 query vector
  - knn unrecognized metric → domain error

traverse.c — 49 new tests in NEW test/test_traverse.c registered in
test/main.c, covering BFS buffer growth (var_expand out buffer,
next_front buffer, shortest_path queue), SIP direction==1 bitmap,
asymmetric CSR (different src/dst node counts), uf_union false
(MST cycle detection), exec_expand_factorized zero-degree nodes,
exec_wco_join unsupported plan, exec_var_expand out-of-range start,
exec_k_shortest range check, plus thorough algorithm-API coverage
(pagerank/topsort/louvain/betweenness/closeness/dijkstra/astar/
DFS/random_walk/MST/degree/clustering).

Why traverse.c stops at 76.53%: the remaining 729 missed regions
are overwhelmingly OOM error-handling paths (`if (!ptr || RAY_IS_ERR(ptr))`
cleanup blocks plus multi-condition `||` short-circuit arms).  Each
fires only when `ray_alloc`/`scratch_alloc`/`ray_vec_new` returns
NULL — the in-tree buddy allocator never does this absent fault
injection.  Pushing past 80% would require either a test-only
fault-injecting allocator (src/ change) or coverage-exclusion
markers on those branches.  Decision deferred to maintainer along
with the block.c weak-stub question.

Tests 2277 → 2326 passing (1 pre-existing skip).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Anton's master commits (lazy IPC fixes 0b243fa/7db74534/f207976d, perf
hoist 924a335) added src code without C-test coverage, dropping ipc.c
to 79.92% and query.c to 79.87%.

ipc/send_lazy_msg
  Sends lazy ray_t via ray_ipc_send / ray_ipc_send_verbose /
  ray_ipc_send_async, exercising the new lazy-materialise blocks in all
  three. ipc.c: 79.92% → 83.57%.

query_coverage.rfl additions
  Hit by-dict shape guards (>16 keys, duplicate key, alias shadows
  existing column, val not a vector / wrong length), nearest-clause
  shape guards (non-list, too-short list, non-symbol head), sort-take
  expression validation (eval failure, wrong type, F64 atom, vec len),
  and join key validation (empty list, non-symbol keys).
  query.c: 79.87% → 80.04%.

Tests: 2330 of 2331 PASS, 1 skipped, 0 failed.
@singaraiona singaraiona merged commit 7de2173 into master May 5, 2026
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants