Skip to content

Reorganize test files - #174

Merged
mstdokumaci merged 8 commits into
mainfrom
organize-tests
Aug 2, 2026
Merged

mstdokumaci merged 8 commits into
mainfrom
organize-tests

Conversation

@mstdokumaci

@mstdokumaci mstdokumaci commented Aug 1, 2026 •

Copy link
Copy Markdown
Owner

Summary by CodeRabbit

  • Tests

    • Expanded coverage for configuration, storage, migrations, messaging, checkpointing, logging, WebSocket callbacks, server initialization, and MessagePack handling.
    • Added randomized, concurrent, boundary, persistence, and error-handling scenarios to strengthen reliability and data-integrity validation.
    • Consolidated coverage into standard suites for more consistent execution.
    • Improved storage-engine performance validation across build modes.
  • Chores

    • Improved test discovery and rebuild checks to recognize relevant test sources consistently.
    • Added validation for test filename detection to reduce false positives.

@coderabbitai

coderabbitai Bot commented Aug 1, 2026 •

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 342b54a6-6569-4573-86a8-bae64ab73e18

📥 Commits

Reviewing files that changed from the base of the PR and between a110f0d and d68f85d.

📒 Files selected for processing (1)
  • src/config/loader_test.zig
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/config/loader_test.zig

📝 Walkthrough

Walkthrough

The pull request moves property-style coverage into standard Zig test files. It adds focused tests for configuration, logging, protocol handling, migrations, MessagePack, storage, checkpointing, server lifecycle, and WebSocket callbacks.

Changes

Test suite consolidation

Layer / File(s) Summary
Test registration and detection
scripts/unused_pub_detector.js, src/test_all.zig
The test aggregator imports standard suites. Test detection uses boundary-aware filename matching and self-tests.
Checkpoint and configuration coverage
src/checkpoint_worker_test.zig, src/config/loader_test.zig
Tests cover checkpoint integrity, WAL handling, thresholds, metrics, failure state, escalation, environment substitution, validation, file loading, and configuration round trips.
Protocol and runtime component coverage
src/logging_test.zig, src/message_handler_test.zig, src/server_init_test.zig, src/uwebsockets_wrapper_test.zig
Tests cover logging paths, message routing, response correlation, allocation cleanup, server lifecycle, and WebSocket callback contracts.
Migration and MessagePack coverage
src/migration_detector_test.zig, src/migration_executor_test.zig, src/msgpack_utils_test.zig
Tests cover migration detection and execution, data preservation, destructive-migration checks, version handling, MessagePack limits, round trips, and boundary behavior.
Storage operation and lifecycle coverage
src/storage_engine_test.zig, src/storage_engine_error_test.zig, src/storage_engine_stability_test.zig, src/storage_engine/read_worker_perf_test.zig
Tests cover storage initialization, concurrency, persistence, batching, flushing, schema evolution, randomized operations, error handling, stability, and performance thresholds.

Estimated code review effort: 4 (Complex) | ~60 minutes

Possibly related PRs

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main change: reorganizing and consolidating test files.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 11

🧹 Nitpick comments (22)
src/checkpoint_worker_test.zig (2)

357-381: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Conditional assertion can silently skip the property check.

The WAL-size property is only checked if (result.success). If performCheckpoint(.truncate) ever returns success == false, the test passes without verifying the stated invariant. The all-modes test (Line 126-143) asserts result.success unconditionally for the same kind of manager, so .truncate succeeds reliably in this context. Assert result.success directly and drop the conditional, so the test fails loudly instead of silently passing.

♻️ Proposed fix
     const result = try manager.performCheckpoint(.truncate);

-    if (result.success) {
-        // WAL size after should be <= WAL size before
-        try testing.expect(result.wal_size_after <= result.wal_size_before);
-        try testing.expect(result.wal_size_before == initial_wal_size);
-    }
+    try testing.expect(result.success);
+    try testing.expect(result.wal_size_after <= result.wal_size_before);
+    try testing.expect(result.wal_size_before == initial_wal_size);
 }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/checkpoint_worker_test.zig` around lines 357 - 381, Update the
“checkpoint: WAL size management - size decreases or stays same after success”
test to assert result.success unconditionally after performCheckpoint(.truncate)
and remove the surrounding conditional; retain both WAL-size invariant
assertions so failures are reported instead of skipped.

487-514: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Duplicate tests introduced by the property-to-standard-test consolidation. Merging property-style tests into these standard test files left several new tests that repeat the exact scenario and assertions of tests already present in the same file. The shared root cause is that the consolidation did not deduplicate against pre-existing coverage.

  • src/checkpoint_worker_test.zig#L487-L514: remove or merge "checkpoint: Prometheus formatting - output contains all required metrics" with "CheckpointWorker: Prometheus metrics format" (Line 190-221); both use identical CheckpointMetrics values and check the same metric names/values.
  • src/checkpoint_worker_test.zig#L431-L460: remove or merge "checkpoint: metrics accuracy - metrics reflect operations accurately" with "CheckpointWorker: performCheckpoint - metrics update" (Line 145-165); keep the extra last_checkpoint_duration_ms >= 0 check in the surviving test if it adds value.
  • src/config/loader_test.zig#L608-L872: remove or merge "config: round-trip - auth config" (644-684), "config: round-trip - security config" (686-725), and "config: round-trip - performance config" (760-795) with the earlier "ConfigLoader parses auth config" (121-149), "ConfigLoader parses security config" (151-179), and the performance section of "ConfigLoader parses valid JSON config" (24-56); keep "config: round-trip - complete config" (797-872) since it verifies all sections together in one load.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/checkpoint_worker_test.zig` around lines 487 - 514, Deduplicate the
consolidated tests: in src/checkpoint_worker_test.zig lines 487-514, remove or
merge the Prometheus formatting test into “CheckpointWorker: Prometheus metrics
format”; in lines 431-460, remove or merge the metrics accuracy test into
“CheckpointWorker: performCheckpoint - metrics update” while preserving the
duration nonnegative assertion if useful; in src/config/loader_test.zig lines
608-872, merge or remove the auth, security, and performance round-trip tests in
favor of the earlier equivalent tests, while retaining the complete-config
round-trip test.
src/uwebsockets_wrapper_test.zig (2)

589-598: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Give CallbackContext field defaults.

Four tests write all nine fields by hand at lines 311-320, 419-428, 481-490, and 527-536. Defaults reduce that to var ctx: CallbackContext = .{}; and stop a new field from silently breaking every initializer.

♻️ Proposed change
 const CallbackContext = struct {
-    open_called: u32,
-    message_called: u32,
-    close_called: u32,
-    last_message: ?[]const u8,
-    last_message_type: ?MessageType,
-    last_close_code: ?i32,
-    last_close_message: ?[]const u8,
-    received_user_data: ?*anyopaque,
+    open_called: u32 = 0,
+    message_called: u32 = 0,
+    close_called: u32 = 0,
+    last_message: ?[]const u8 = null,
+    last_message_type: ?MessageType = null,
+    last_close_code: ?i32 = null,
+    last_close_message: ?[]const u8 = null,
+    received_user_data: ?*anyopaque = null,
 };
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/uwebsockets_wrapper_test.zig` around lines 589 - 598, Update the
CallbackContext struct to provide defaults for all fields, using zero or null
values matching each field type, so tests can initialize it with .{} and future
fields do not require manual initialization.

322-379: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

These tests do not exercise the wrapper dispatch.

The test creates a WebSocketServer, registers handlers, and then calls the handler function pointers directly at lines 351, 361, and 371. The registered handlers are never dispatched by the wrapper, so the server instance has no effect on any assertion. The assertions confirm that the local test callbacks increment their own counters.

The header comment at line 252 also claims that unregistered callbacks are not invoked. The code only calls a handler inside if (tc.register_open), so the "no callbacks registered" case verifies the test's own branch, not wrapper behavior.

Either drop the unused server setup and describe these as callback-contract tests, or drive the events through WebSocketServer so the wrapper dispatch is actually covered. As per coding guidelines, "After Zig protocol-level changes, run npm run test:e2e to verify server-client communication" — the end-to-end suite is the right place for real dispatch coverage.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/uwebsockets_wrapper_test.zig` around lines 322 - 379, Update the property
test around WebSocketServer initialization and handler invocation so it does not
claim wrapper-dispatch coverage: either remove the unused server setup and
relabel the test as direct callback-contract coverage, or route simulated events
through WebSocketServer’s dispatch API instead of invoking handlers.on_open,
handlers.on_message, and handlers.on_close directly. Keep the
unregistered-callback case aligned with the chosen scope, and rely on the
end-to-end suite for real server-client dispatch coverage.

Source: Coding guidelines

src/logging_test.zig (3)

27-68: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

No test in src/logging_test.zig observes log output. LogCapture is never constructed and has no method to record a message, so the file falls back to placeholder assertions where a log assertion belongs. The shared root cause is the missing logFn hook.

  • src/logging_test.zig#L27-L68: install a custom logFn through pub const std_options that appends to a LogCapture instance, or delete LogCapture.
  • src/logging_test.zig#L396-L400: replace try testing.expect(true) with a LogCapture.contains assertion on the expected message, or delete the block. Apply the same change at lines 488-492.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/logging_test.zig` around lines 27 - 68, In src/logging_test.zig lines
27-68, either wire LogCapture into a pub const std_options.logFn that records
emitted messages or remove the unused LogCapture helper. In lines 396-400 and
488-492, replace the placeholder testing.expect(true) assertions with
LogCapture.contains checks for the expected log messages, or remove those blocks
if no log output is intended.

154-168: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Test 4 duplicates Test 2.

The block opens a connection, calls manager.onClose, and expects error.ConnectionNotFound. Test 2 at lines 111-125 performs the same steps and the same assertion. The comment at line 162 also describes an error-handling log path, but the code calls onClose.

Either exercise a real failure path here, for example an onOpen rejection with a missing or empty session as in src/connection/manager.zig lines 101-112, or delete the block.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/logging_test.zig` around lines 154 - 168, The Test 4 block in the logging
test duplicates Test 2 and incorrectly labels an onClose flow as error handling.
Replace it with a genuine failure-path test, such as an onOpen rejection for a
missing or empty session using the manager’s existing behavior, or remove the
block entirely; preserve assertions that match the selected path.

321-389: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Replace the manual service stacks with AppTestContext.

This block builds MemoryStrategy, ViolationTracker, TestContext, schema, SubscriptionEngine, StorageEngine, auth config, StoreService, PresenceService, MessageHandler, and ConnectionManager by hand. Lines 416-486 and 495-565 repeat the same sequence, and only the local names (sm2, sm3, sm4, empty_claims, empty_claims2, empty_claims3) and the directory label differ.

Tests at lines 81 and 220 in this same file already use AppTestContext for the same stack. Use AppTestContext.init in all three blocks. That removes about 200 duplicated lines and keeps the setup in one place when a component signature changes.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/logging_test.zig` around lines 321 - 389, Replace the manual service
initialization in this block and the corresponding repeated blocks with
AppTestContext.init, using each block’s existing directory label and local
context references as needed. Remove the duplicated MemoryStrategy,
ViolationTracker, schema, service, handler, and ConnectionManager setup and rely
on AppTestContext’s lifecycle cleanup, matching the established usage in the
earlier tests.
src/server_init_test.zig (1)

58-65: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

These pointer assertions cannot fail.

&server.memory_strategy is the address of a field inside an allocated struct. It is never null, so each @intFromPtr(...) != 0 check always passes and verifies nothing about initialization.

Assert observable initialized state instead, for example a non-zero schema table count, a configured storage path, or a registered handler count. If no such state is reachable from the test, delete these seven lines and keep the shutdown_requested check at line 68.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/server_init_test.zig` around lines 58 - 65, Remove the seven always-true
pointer assertions in the server initialization test. Replace them with
assertions on observable initialized state such as schema table count,
configured storage path, or registered handler count; if none is accessible,
delete these assertions and retain the shutdown_requested check.
src/message_handler_test.zig (1)

513-538: 🩺 Stability & Availability | 🔵 Trivial | 💤 Low value

Check the payload tag before you read .str.

expectResponseType and expectErrorCode read value.str.value() after only a presence check. If the field is not a string, the union access panics and the test reports a crash instead of a failed assertion. expectResponseId at line 526 already guards with value == .uint.

♻️ Proposed guard
     const value = (try msgpack_helpers.getMapValue(parsed, "type")) orelse return error.TestExpectedError;
+    try testing.expect(value == .str);
     try testing.expectEqualStrings(expected, value.str.value());

Apply the same guard to resp_type and code in expectErrorCode.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/message_handler_test.zig` around lines 513 - 538, Validate the
MessagePack union tag before accessing string payloads in expectResponseType and
expectErrorCode. Add the equivalent .str assertions used by expectResponseId for
value, resp_type, and code, preserving the existing expected-string comparisons
after validation.
src/storage_engine_test.zig (4)

1103-1150: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Move the alias to the top and split the combined test.

Two points on this block:

  1. Line 1103 declares const StorageEngine = sth.StorageEngine; at line 1103, while all other aliases sit at Lines 1-17. Move it up with the rest.
  2. The test bundles three independent scenarios and shares one MemoryStrategy across two failed inits and one successful init. If the first assertion fails, the later scenarios never run. Split into three tests, each with its own MemoryStrategy.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/storage_engine_test.zig` around lines 1103 - 1150, Move the StorageEngine
alias from the test block to the existing alias declarations at the top of the
file. Split “storage: engine initialization errors” into three independent tests
for invalid directory, file-as-directory, and successful initialization, giving
each test its own MemoryStrategy setup and teardown so every scenario runs
independently.

1158-1158: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Update the stale prop- test directory prefixes.

The prefixes do not match the tests. "prop-multi-table" names a thread-safety test. "prop-many-ns" names a connection-pool test. "prop-burst" names a persistence round-trip test. These prefixes appear in temporary directory names and in failure output, so they make triage harder after the property files were merged into this file.

♻️ Proposed rename
-    try sth.setupEngine(&ctx, allocator, "prop-multi-table", table);
+    try sth.setupEngine(&ctx, allocator, "storage-thread-safety", table);
-    try sth.setupEngine(&ctx, allocator, "prop-many-ns", table);
+    try sth.setupEngine(&ctx, allocator, "storage-pool-reuse", table);
-    try sth.setupEngine(&ctx, allocator, "prop-burst", table);
+    try sth.setupEngine(&ctx, allocator, "storage-persistence-types", table);

Also applies to: 1225-1225, 1254-1254

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/storage_engine_test.zig` at line 1158, Update the temporary directory
name arguments in the affected setupEngine calls in storage_engine_test.zig:
rename "prop-multi-table" to reflect the thread-safety test, "prop-many-ns" to
reflect the connection-pool test, and "prop-burst" to reflect the persistence
round-trip test. Keep the test logic unchanged and ensure each identifier is
used consistently in failure output and temporary-directory creation.

1279-1283: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

These tests verify existence, not stored content. Each site knows the exact expected value, but asserts only record != null. A wrong value, a truncated Unicode or escaped string, or an update that never applied still passes. expectFieldString and expectFieldInt are already used elsewhere in this file (Lines 169-170).

  • src/storage_engine_test.zig#L1279-L1283: compare the read value against tc.value for every case, so the Unicode and escaped-character cases actually verify the round trip.
  • src/storage_engine_test.zig#L1357-L1368: assert "updated1", "updated2", and "new3" instead of non-null, so a dropped batched update is detected.
  • src/storage_engine_test.zig#L1505-L1507: assert that val1 still equals "value1" after the field is added, so the schema-evolution property is verified rather than row presence.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/storage_engine_test.zig` around lines 1279 - 1283, Strengthen the
read-back assertions in src/storage_engine_test.zig at lines 1279-1283,
1357-1368, and 1505-1507: use the existing expectFieldString/expectFieldInt
helpers to compare each record’s stored value with tc.value, assert "updated1",
"updated2", and "new3" for the batched updates, and verify val1 remains "value1"
after schema evolution instead of checking only record presence.

1168-1204: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Capture and assert errors from every worker. std.Thread.spawn catches errors from !void entry points, prints them, and does not return them through join(). A worker can stop at its first try while the test still passes when write thread 0 created document 1. Store each worker's error and assert all results after the joins.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/storage_engine_test.zig` around lines 1168 - 1204, Capture each worker’s
error from WriteThread.run and ReadThread.run instead of allowing
std.Thread.spawn to discard it, using per-thread error storage passed through
the worker context or arguments. Ensure each worker records failures before
exiting, then join all write and read threads and assert that every stored
result is successful, so any worker error fails the test.
src/storage_engine_stability_test.zig (1)

9-19: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Trim the header comment to the coverage that exists.

The comment lists error recovery, retry logic, rapid error conditions, and resource cleanup after errors. The file contains one test that runs concurrent insert, read, and delete operations. The comment also calls this a "property test", but the file now holds standard Zig tests. Reduce the list to the concurrent-operation property, or add the missing tests.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/storage_engine_stability_test.zig` around lines 9 - 19, Trim the header
comment in the storage stability test to describe only the coverage implemented:
concurrent insert, read, and delete operations during database errors. Remove
claims about property-test status, recovery or retry logic, rapid errors,
resource cleanup, and other unimplemented scenarios.
src/storage_engine_error_test.zig (2)

88-116: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

The concurrent read test cannot fail.

runRead discards every error with catch return, and the test asserts nothing after join. If readDoc starts to fail under concurrency, or returns null, the test still passes. Only a hard crash is detected.

Collect the per-thread outcome and assert it after the joins.

🧪 Proposed assertion
     const ThreadContext = struct {
         storage: *StorageEngine,
         allocator: std.mem.Allocator,
+        found: *std.atomic.Value(usize),
     };
     const runRead = struct {
         fn run(t_ctx: ThreadContext, table_index: usize) void {
             const record = sth.readDoc(t_ctx.allocator, t_ctx.storage, table_index, 1, 1) catch return; // zwanzig-disable-line: swallowed-error
             defer if (record) |r| r.deinit(t_ctx.allocator);
+            if (record != null) _ = t_ctx.found.fetchAdd(1, .monotonic);
         }
     }.run;
     var threads: [4]std.Thread = undefined;
+    var found = std.atomic.Value(usize).init(0);
     const tbl_md = ctx.schema.table("data_table") orelse return error.UnknownTable;
     for (&threads) |*t| {
-        t.* = try std.Thread.spawn(.{}, runRead, .{ ThreadContext{ .storage = storage, .allocator = allocator }, tbl_md.index });
+        t.* = try std.Thread.spawn(.{}, runRead, .{ ThreadContext{ .storage = storage, .allocator = allocator, .found = &found }, tbl_md.index });
     }
     for (threads) |t| t.join();
+    try testing.expectEqual(`@as`(usize, 4), found.load(.acquire));
 }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/storage_engine_error_test.zig` around lines 88 - 116, Update the
concurrent test around runRead to record each thread’s read result, including
errors and null records, in shared per-thread outcome storage. After joining all
threads, assert every outcome represents a successful non-null read, while
preserving proper record cleanup and avoiding data races.

41-61: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Rename these tests to match what they verify.

The test named "error handling read-only filesystem" does not create a read-only filesystem. It writes a value, flushes, and reads it back on a normal temporary directory. The test named "error handling empty paths" at Lines 117-133 has the same problem; it uses a normal directory and a non-empty value. The names promise error coverage that does not exist, so a future reader can assume the paths are tested.

Either rename both tests to describe the write/read round trip, or add the missing setup (mark the directory read-only, pass an empty field value).

♻️ Rename option
-test "storage: error handling read-only filesystem" {
+test "storage: write and read back on filesystem-backed engine" {
-test "storage: error handling empty paths" {
+test "storage: write and read back with default path setup" {
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/storage_engine_error_test.zig` around lines 41 - 61, Rename the tests
currently labeled “storage: error handling read-only filesystem” and “storage:
error handling empty paths” to describe the write/flush/read round-trip behavior
they actually exercise. Keep the existing normal-directory setup and non-empty
value unchanged; do not retain error-oriented names unless the tests are
expanded with the corresponding read-only and empty-value setup.
src/migration_detector_test.zig (1)

263-268: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Remove the debug print block.

std.testing.expectEqual at line 269 already reports the mismatch. The std.debug.print block writes to stderr on every failing iteration and is a debug artifact.

♻️ Proposed cleanup
-        if (plan.changes.len != 0) {
-            std.debug.print("iter {d}: expected 0 changes, got {d}\n", .{ iter, plan.changes.len });
-            for (plan.changes) |c| {
-                std.debug.print("  change: kind={s} table={s}\n", .{ `@tagName`(c.kind), c.table.name });
-            }
-        }
         try std.testing.expectEqual(`@as`(usize, 0), plan.changes.len);
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/migration_detector_test.zig` around lines 263 - 268, Remove the
conditional std.debug.print block that checks plan.changes.len in the relevant
test, including the per-change diagnostic loop, while preserving the existing
std.testing.expectEqual assertion and surrounding test logic.
src/msgpack_utils_test.zig (3)

236-248: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Drop the toOwnedSlice step.

The reader at line 246 only needs a read-only view of the encoded bytes. list.items provides that. toOwnedSlice adds a second ownership transfer and a second defer free for no benefit.

♻️ Proposed simplification
         var list: std.ArrayListUnmanaged(u8) = .empty;
         defer list.deinit(allocator);
         try msgpack_utils.encode(payload, list.writer(allocator));
 
-        // Get the encoded bytes
-        const encoded = try list.toOwnedSlice(allocator);
-        defer allocator.free(encoded);
-
         // Decode using the project's standard fixed reader
-        var reader: std.Io.Reader = .fixed(encoded);
+        var reader: std.Io.Reader = .fixed(list.items);
         const decoded = try msgpack_utils.decode(allocator, &reader);
         defer decoded.free(allocator);
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/msgpack_utils_test.zig` around lines 236 - 248, Remove the toOwnedSlice
call and its associated allocator.free defer in the test around list and reader;
initialize std.Io.Reader.fixed directly from list.items, while preserving the
existing ArrayList lifetime through decoding.

255-260: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Add boundary coverage for max_map_size, max_bin_length, and max_ext_length.

wire_limits in src/msgpack_utils.zig lines 5-16 defines six limits. The boundary tests cover only max_depth, max_array_length, and max_string_length. The one-over test at lines 322-391 covers the same three.

max_map_size appears only in the bomb test at lines 138-161, and max_bin_length and max_ext_length are not tested at all. Add exact-limit and one-over cases for these three limits so a change to any wire_limits field is caught.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/msgpack_utils_test.zig` around lines 255 - 260, Add exact-boundary and
one-over test cases in the boundary success and boundary rejection tests,
covering wire_limits.max_map_size, wire_limits.max_bin_length, and
wire_limits.max_ext_length alongside the existing depth, array, and string
cases. Ensure exact-limit payloads decode successfully while payloads exceeding
each limit are rejected, using the existing test patterns and payload helpers.

88-189: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Extract the repeated bomb-construction and assertion code.

Add helpers for the shared big-endian header construction and decode/error assertion. testing.expectEqual accepts these error values in Zig 0.15.2; retain explicit branching to free an unexpected payload.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/msgpack_utils_test.zig` around lines 88 - 189, Extract the repeated
MessagePack bomb setup in the test into helpers for writing big-endian length
headers and decoding input while asserting the expected error. Update the depth,
array, map, and string bomb cases to use these helpers, retaining explicit
successful-payload cleanup before reporting an unexpected result; use
testing.expectEqual for the expected error values.
src/migration_executor_test.zig (2)

236-241: 🚀 Performance & Scalability | 🔵 Trivial | ⚡ Quick win

Fixed 100-iteration loops over a small input space repeat work without adding coverage. Every consolidated property test runs exactly 100 iterations, but each iteration draws from at most five table names and a handful of field types, and it opens a fresh in-memory database plus DDL each time. Most iterations are exact duplicates of an earlier one, so the loops raise zig build test runtime without raising coverage.

  • src/migration_executor_test.zig#L236-L241: replace the while (iter < 100) loop with iteration over table_names, or vary column count, column types, and row values per iteration. Apply the same change to the loops at lines 336, 427, and 488.
  • src/migration_detector_test.zig#L52-L54: the loop draws tname from five names and scenario from four values, so at most 20 distinct cases exist. Iterate over the table_names × scenario product instead of sampling 100 times.
  • src/migration_detector_test.zig#L219-L226: n_tables is 1 to 3 and table names are chosen by ti % table_names.len, so table identity never varies. Vary the table-name offset and the field names per iteration, or reduce the iteration count.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/migration_executor_test.zig` around lines 236 - 241, Replace the fixed
100-iteration sampling loops with bounded, distinct case coverage: in
src/migration_executor_test.zig lines 236-241, 336, 427, and 488, iterate over
table_names or vary column counts, types, and row values; in
src/migration_detector_test.zig lines 52-54, iterate over every table_names ×
scenario combination; and in src/migration_detector_test.zig lines 219-226, vary
table-name offsets and field names or reduce the iteration count. Use the
existing test-loop symbols and preserve each test’s assertions and setup.

391-409: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Assert the schema is unchanged, not only the row.

The property states that execute must not modify the database. The check verifies only that the row still exists. It does not verify that col_a still has its original TEXT type after the refused change_type plan.

Add a PRAGMA table_info check like the one at lines 546-577, and assert col_a type is still TEXT.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/migration_executor_test.zig` around lines 391 - 409, Extend the
post-execution validation near the existing row check to verify the schema as
well: query PRAGMA table_info for the migrated table, following the established
pattern around the later table-info check, and assert that col_a still has type
TEXT. Preserve the existing row-identity assertions and ensure the schema check
confirms the refused change_type plan did not alter the column definition.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@scripts/unused_pub_detector.js`:
- Line 6: Replace the broad TEST_RE match in unused_pub_detector.js with
boundary-aware patterns covering _test.zig, test-helper, and test_all.zig paths
without matching ordinary production names such as latest.zig. Add regression
cases for these classifications, rely on canonical()’s relative paths without
absolute-parent handling, then run bunx biome check --write and bun run lint via
zwanzig.

In `@src/checkpoint_worker_test.zig`:
- Around line 462-485: The test “checkpoint: escalation logic - works correctly
when needed” does not verify escalation occurred. After calling
manager.performCheckpointWithEscalation(), assert that result.mode indicates a
mode beyond .passive, while preserving the existing success and duration
assertions.
- Around line 410-429: The test does not exercise a failed checkpoint despite
claiming to verify failure-count increments. Either rename the test to describe
its actual initial-counter assertion, or add failure injection through the
checkpoint manager so a failed checkpoint is executed and
manager.failed_checkpoint_count is verified to increase.

In `@src/message_handler_test.zig`:
- Around line 566-575: Replace the optional-response handling in the StoreQuery
test block with an explicit assertion: use routeBytes when a response is
guaranteed, or assert the expected null outcome when it is valid. Preserve the
existing response type and ID checks for non-null responses, and apply the same
fix to the matching block around the StoreQuery coverage at lines 612-619.

In `@src/migration_detector_test.zig`:
- Around line 227-253: Update the cleanup around the table-construction loop to
track the number of successfully initialized tables and iterate only over those
entries, preventing access to undefined allocations when construction fails.
Also add partial cleanup for the fields slice in the loop so names already
allocated are freed if makeFieldAlloc fails before the table is created.

In `@src/msgpack_utils_test.zig`:
- Around line 74-80: Update the comments in the MessagePack utility tests to
match the existing implementation and test data: remove the stale “must fail,”
fix-name, “Bug confirmed,” and “Counterexample” claims, including the inaccurate
payload-size notes in the blocks around the oversized payload cases, and delete
the outdated line describing a 64KB+1 string near the 1MB+1 test. Preserve the
test logic unchanged.
- Around line 406-416: Update verifyPayloadEquality’s .map branch to iterate
through expected.map, retrieve each corresponding entry with
actual.mapGetGeneric(...), require the key to exist, and recursively compare its
value. Replace the catch-all else => {} branch with a failing assertion so
unsupported payload variants cannot pass silently.

In `@src/server_init_test.zig`:
- Around line 44-48: Update num_cycles in the init/deinit cycle test to a value
of at least 2 so it exercises repeated initialization and cleanup as described
by the test name and documentation, and remove the temporary single-cycle
debugging comment.
- Around line 52-71: Move the data-directory cleanup out of the scope where
server is still alive: wrap server initialization, assertions, and the existing
defer-based server.deinit() in an inner block, then call deleteTree(data_dir)
after that block completes. Preserve the current cleanup behavior while ensuring
deinit finishes before removing files.

In `@src/storage_engine_test.zig`:
- Around line 1547-1550: Update the delete branch in the fuzz operation dispatch
to derive the table index through the existing ctx.tableIndex helper for
"items", matching the other operation branches, and pass that resolved index
into the delete request instead of hardcoding 0.

In `@src/uwebsockets_wrapper_test.zig`:
- Around line 557-584: In the test covering the WebSocket callback counts,
rename the test to reflect that it expects one open, three message, and one
close invocation, and defer destroyMockWebSocket immediately after
createMockWebSocket so cleanup runs on assertion failures. Remove the duplicated
final assertions while preserving the existing count checks.

---

Nitpick comments:
In `@src/checkpoint_worker_test.zig`:
- Around line 357-381: Update the “checkpoint: WAL size management - size
decreases or stays same after success” test to assert result.success
unconditionally after performCheckpoint(.truncate) and remove the surrounding
conditional; retain both WAL-size invariant assertions so failures are reported
instead of skipped.
- Around line 487-514: Deduplicate the consolidated tests: in
src/checkpoint_worker_test.zig lines 487-514, remove or merge the Prometheus
formatting test into “CheckpointWorker: Prometheus metrics format”; in lines
431-460, remove or merge the metrics accuracy test into “CheckpointWorker:
performCheckpoint - metrics update” while preserving the duration nonnegative
assertion if useful; in src/config/loader_test.zig lines 608-872, merge or
remove the auth, security, and performance round-trip tests in favor of the
earlier equivalent tests, while retaining the complete-config round-trip test.

In `@src/logging_test.zig`:
- Around line 27-68: In src/logging_test.zig lines 27-68, either wire LogCapture
into a pub const std_options.logFn that records emitted messages or remove the
unused LogCapture helper. In lines 396-400 and 488-492, replace the placeholder
testing.expect(true) assertions with LogCapture.contains checks for the expected
log messages, or remove those blocks if no log output is intended.
- Around line 154-168: The Test 4 block in the logging test duplicates Test 2
and incorrectly labels an onClose flow as error handling. Replace it with a
genuine failure-path test, such as an onOpen rejection for a missing or empty
session using the manager’s existing behavior, or remove the block entirely;
preserve assertions that match the selected path.
- Around line 321-389: Replace the manual service initialization in this block
and the corresponding repeated blocks with AppTestContext.init, using each
block’s existing directory label and local context references as needed. Remove
the duplicated MemoryStrategy, ViolationTracker, schema, service, handler, and
ConnectionManager setup and rely on AppTestContext’s lifecycle cleanup, matching
the established usage in the earlier tests.

In `@src/message_handler_test.zig`:
- Around line 513-538: Validate the MessagePack union tag before accessing
string payloads in expectResponseType and expectErrorCode. Add the equivalent
.str assertions used by expectResponseId for value, resp_type, and code,
preserving the existing expected-string comparisons after validation.

In `@src/migration_detector_test.zig`:
- Around line 263-268: Remove the conditional std.debug.print block that checks
plan.changes.len in the relevant test, including the per-change diagnostic loop,
while preserving the existing std.testing.expectEqual assertion and surrounding
test logic.

In `@src/migration_executor_test.zig`:
- Around line 236-241: Replace the fixed 100-iteration sampling loops with
bounded, distinct case coverage: in src/migration_executor_test.zig lines
236-241, 336, 427, and 488, iterate over table_names or vary column counts,
types, and row values; in src/migration_detector_test.zig lines 52-54, iterate
over every table_names × scenario combination; and in
src/migration_detector_test.zig lines 219-226, vary table-name offsets and field
names or reduce the iteration count. Use the existing test-loop symbols and
preserve each test’s assertions and setup.
- Around line 391-409: Extend the post-execution validation near the existing
row check to verify the schema as well: query PRAGMA table_info for the migrated
table, following the established pattern around the later table-info check, and
assert that col_a still has type TEXT. Preserve the existing row-identity
assertions and ensure the schema check confirms the refused change_type plan did
not alter the column definition.

In `@src/msgpack_utils_test.zig`:
- Around line 236-248: Remove the toOwnedSlice call and its associated
allocator.free defer in the test around list and reader; initialize
std.Io.Reader.fixed directly from list.items, while preserving the existing
ArrayList lifetime through decoding.
- Around line 255-260: Add exact-boundary and one-over test cases in the
boundary success and boundary rejection tests, covering
wire_limits.max_map_size, wire_limits.max_bin_length, and
wire_limits.max_ext_length alongside the existing depth, array, and string
cases. Ensure exact-limit payloads decode successfully while payloads exceeding
each limit are rejected, using the existing test patterns and payload helpers.
- Around line 88-189: Extract the repeated MessagePack bomb setup in the test
into helpers for writing big-endian length headers and decoding input while
asserting the expected error. Update the depth, array, map, and string bomb
cases to use these helpers, retaining explicit successful-payload cleanup before
reporting an unexpected result; use testing.expectEqual for the expected error
values.

In `@src/server_init_test.zig`:
- Around line 58-65: Remove the seven always-true pointer assertions in the
server initialization test. Replace them with assertions on observable
initialized state such as schema table count, configured storage path, or
registered handler count; if none is accessible, delete these assertions and
retain the shutdown_requested check.

In `@src/storage_engine_error_test.zig`:
- Around line 88-116: Update the concurrent test around runRead to record each
thread’s read result, including errors and null records, in shared per-thread
outcome storage. After joining all threads, assert every outcome represents a
successful non-null read, while preserving proper record cleanup and avoiding
data races.
- Around line 41-61: Rename the tests currently labeled “storage: error handling
read-only filesystem” and “storage: error handling empty paths” to describe the
write/flush/read round-trip behavior they actually exercise. Keep the existing
normal-directory setup and non-empty value unchanged; do not retain
error-oriented names unless the tests are expanded with the corresponding
read-only and empty-value setup.

In `@src/storage_engine_stability_test.zig`:
- Around line 9-19: Trim the header comment in the storage stability test to
describe only the coverage implemented: concurrent insert, read, and delete
operations during database errors. Remove claims about property-test status,
recovery or retry logic, rapid errors, resource cleanup, and other unimplemented
scenarios.

In `@src/storage_engine_test.zig`:
- Around line 1103-1150: Move the StorageEngine alias from the test block to the
existing alias declarations at the top of the file. Split “storage: engine
initialization errors” into three independent tests for invalid directory,
file-as-directory, and successful initialization, giving each test its own
MemoryStrategy setup and teardown so every scenario runs independently.
- Line 1158: Update the temporary directory name arguments in the affected
setupEngine calls in storage_engine_test.zig: rename "prop-multi-table" to
reflect the thread-safety test, "prop-many-ns" to reflect the connection-pool
test, and "prop-burst" to reflect the persistence round-trip test. Keep the test
logic unchanged and ensure each identifier is used consistently in failure
output and temporary-directory creation.
- Around line 1279-1283: Strengthen the read-back assertions in
src/storage_engine_test.zig at lines 1279-1283, 1357-1368, and 1505-1507: use
the existing expectFieldString/expectFieldInt helpers to compare each record’s
stored value with tc.value, assert "updated1", "updated2", and "new3" for the
batched updates, and verify val1 remains "value1" after schema evolution instead
of checking only record presence.
- Around line 1168-1204: Capture each worker’s error from WriteThread.run and
ReadThread.run instead of allowing std.Thread.spawn to discard it, using
per-thread error storage passed through the worker context or arguments. Ensure
each worker records failures before exiting, then join all write and read
threads and assert that every stored result is successful, so any worker error
fails the test.

In `@src/uwebsockets_wrapper_test.zig`:
- Around line 589-598: Update the CallbackContext struct to provide defaults for
all fields, using zero or null values matching each field type, so tests can
initialize it with .{} and future fields do not require manual initialization.
- Around line 322-379: Update the property test around WebSocketServer
initialization and handler invocation so it does not claim wrapper-dispatch
coverage: either remove the unused server setup and relabel the test as direct
callback-contract coverage, or route simulated events through WebSocketServer’s
dispatch API instead of invoking handlers.on_open, handlers.on_message, and
handlers.on_close directly. Keep the unregistered-callback case aligned with the
chosen scope, and rely on the end-to-end suite for real server-client dispatch
coverage.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: daaf7410-bb6f-464b-84e5-6b454c93890c

📥 Commits

Reviewing files that changed from the base of the PR and between 92b6613 and 51c5b56.

📒 Files selected for processing (22)
  • scripts/unused_pub_detector.js
  • src/checkpoint_worker_property_test.zig
  • src/checkpoint_worker_test.zig
  • src/config/loader_property_test.zig
  • src/config/loader_test.zig
  • src/logging_test.zig
  • src/message_handler_property_test.zig
  • src/message_handler_test.zig
  • src/migration_detector_test.zig
  • src/migration_executor_property_test.zig
  • src/migration_executor_test.zig
  • src/msgpack_utils_property_test.zig
  • src/msgpack_utils_test.zig
  • src/server_init_test.zig
  • src/storage_engine_error_test.zig
  • src/storage_engine_property_test.zig
  • src/storage_engine_stability_test.zig
  • src/storage_engine_test.zig
  • src/test_all.zig
  • src/uwebsockets_wrapper_property_test.zig
  • src/uwebsockets_wrapper_test.zig
  • tests/e2e/src/harness.ts
💤 Files with no reviewable changes (8)
  • src/message_handler_property_test.zig
  • src/storage_engine_property_test.zig
  • src/checkpoint_worker_property_test.zig
  • src/msgpack_utils_property_test.zig
  • src/uwebsockets_wrapper_property_test.zig
  • src/migration_executor_property_test.zig
  • src/config/loader_property_test.zig
  • tests/e2e/src/harness.ts

Comment thread scripts/unused_pub_detector.js Outdated
Comment thread src/checkpoint_worker_test.zig Outdated
Comment thread src/checkpoint_worker_test.zig
Comment thread src/message_handler_test.zig Outdated
Comment thread src/msgpack_utils_test.zig Outdated
Comment thread src/msgpack_utils_test.zig
Comment thread src/storage_engine_test.zig
Comment thread src/uwebsockets_wrapper_test.zig Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Inline review comments failed to post. This is likely due to GitHub's internal server error or limits when posting large numbers of comments. If you are seeing this consistently it is likely a permissions issue. Please check "Moderation" -> "Code review limits" under your organization settings.

Actionable comments posted: 11

🧹 Nitpick comments (22)
src/checkpoint_worker_test.zig (2)

357-381: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Conditional assertion can silently skip the property check.

The WAL-size property is only checked if (result.success). If performCheckpoint(.truncate) ever returns success == false, the test passes without verifying the stated invariant. The all-modes test (Line 126-143) asserts result.success unconditionally for the same kind of manager, so .truncate succeeds reliably in this context. Assert result.success directly and drop the conditional, so the test fails loudly instead of silently passing.

♻️ Proposed fix
     const result = try manager.performCheckpoint(.truncate);

-    if (result.success) {
-        // WAL size after should be <= WAL size before
-        try testing.expect(result.wal_size_after <= result.wal_size_before);
-        try testing.expect(result.wal_size_before == initial_wal_size);
-    }
+    try testing.expect(result.success);
+    try testing.expect(result.wal_size_after <= result.wal_size_before);
+    try testing.expect(result.wal_size_before == initial_wal_size);
 }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/checkpoint_worker_test.zig` around lines 357 - 381, Update the
“checkpoint: WAL size management - size decreases or stays same after success”
test to assert result.success unconditionally after performCheckpoint(.truncate)
and remove the surrounding conditional; retain both WAL-size invariant
assertions so failures are reported instead of skipped.

487-514: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Duplicate tests introduced by the property-to-standard-test consolidation. Merging property-style tests into these standard test files left several new tests that repeat the exact scenario and assertions of tests already present in the same file. The shared root cause is that the consolidation did not deduplicate against pre-existing coverage.

  • src/checkpoint_worker_test.zig#L487-L514: remove or merge "checkpoint: Prometheus formatting - output contains all required metrics" with "CheckpointWorker: Prometheus metrics format" (Line 190-221); both use identical CheckpointMetrics values and check the same metric names/values.
  • src/checkpoint_worker_test.zig#L431-L460: remove or merge "checkpoint: metrics accuracy - metrics reflect operations accurately" with "CheckpointWorker: performCheckpoint - metrics update" (Line 145-165); keep the extra last_checkpoint_duration_ms >= 0 check in the surviving test if it adds value.
  • src/config/loader_test.zig#L608-L872: remove or merge "config: round-trip - auth config" (644-684), "config: round-trip - security config" (686-725), and "config: round-trip - performance config" (760-795) with the earlier "ConfigLoader parses auth config" (121-149), "ConfigLoader parses security config" (151-179), and the performance section of "ConfigLoader parses valid JSON config" (24-56); keep "config: round-trip - complete config" (797-872) since it verifies all sections together in one load.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/checkpoint_worker_test.zig` around lines 487 - 514, Deduplicate the
consolidated tests: in src/checkpoint_worker_test.zig lines 487-514, remove or
merge the Prometheus formatting test into “CheckpointWorker: Prometheus metrics
format”; in lines 431-460, remove or merge the metrics accuracy test into
“CheckpointWorker: performCheckpoint - metrics update” while preserving the
duration nonnegative assertion if useful; in src/config/loader_test.zig lines
608-872, merge or remove the auth, security, and performance round-trip tests in
favor of the earlier equivalent tests, while retaining the complete-config
round-trip test.
src/uwebsockets_wrapper_test.zig (2)

589-598: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Give CallbackContext field defaults.

Four tests write all nine fields by hand at lines 311-320, 419-428, 481-490, and 527-536. Defaults reduce that to var ctx: CallbackContext = .{}; and stop a new field from silently breaking every initializer.

♻️ Proposed change
 const CallbackContext = struct {
-    open_called: u32,
-    message_called: u32,
-    close_called: u32,
-    last_message: ?[]const u8,
-    last_message_type: ?MessageType,
-    last_close_code: ?i32,
-    last_close_message: ?[]const u8,
-    received_user_data: ?*anyopaque,
+    open_called: u32 = 0,
+    message_called: u32 = 0,
+    close_called: u32 = 0,
+    last_message: ?[]const u8 = null,
+    last_message_type: ?MessageType = null,
+    last_close_code: ?i32 = null,
+    last_close_message: ?[]const u8 = null,
+    received_user_data: ?*anyopaque = null,
 };
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/uwebsockets_wrapper_test.zig` around lines 589 - 598, Update the
CallbackContext struct to provide defaults for all fields, using zero or null
values matching each field type, so tests can initialize it with .{} and future
fields do not require manual initialization.

322-379: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

These tests do not exercise the wrapper dispatch.

The test creates a WebSocketServer, registers handlers, and then calls the handler function pointers directly at lines 351, 361, and 371. The registered handlers are never dispatched by the wrapper, so the server instance has no effect on any assertion. The assertions confirm that the local test callbacks increment their own counters.

The header comment at line 252 also claims that unregistered callbacks are not invoked. The code only calls a handler inside if (tc.register_open), so the "no callbacks registered" case verifies the test's own branch, not wrapper behavior.

Either drop the unused server setup and describe these as callback-contract tests, or drive the events through WebSocketServer so the wrapper dispatch is actually covered. As per coding guidelines, "After Zig protocol-level changes, run npm run test:e2e to verify server-client communication" — the end-to-end suite is the right place for real dispatch coverage.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/uwebsockets_wrapper_test.zig` around lines 322 - 379, Update the property
test around WebSocketServer initialization and handler invocation so it does not
claim wrapper-dispatch coverage: either remove the unused server setup and
relabel the test as direct callback-contract coverage, or route simulated events
through WebSocketServer’s dispatch API instead of invoking handlers.on_open,
handlers.on_message, and handlers.on_close directly. Keep the
unregistered-callback case aligned with the chosen scope, and rely on the
end-to-end suite for real server-client dispatch coverage.

Source: Coding guidelines

src/logging_test.zig (3)

27-68: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

No test in src/logging_test.zig observes log output. LogCapture is never constructed and has no method to record a message, so the file falls back to placeholder assertions where a log assertion belongs. The shared root cause is the missing logFn hook.

  • src/logging_test.zig#L27-L68: install a custom logFn through pub const std_options that appends to a LogCapture instance, or delete LogCapture.
  • src/logging_test.zig#L396-L400: replace try testing.expect(true) with a LogCapture.contains assertion on the expected message, or delete the block. Apply the same change at lines 488-492.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/logging_test.zig` around lines 27 - 68, In src/logging_test.zig lines
27-68, either wire LogCapture into a pub const std_options.logFn that records
emitted messages or remove the unused LogCapture helper. In lines 396-400 and
488-492, replace the placeholder testing.expect(true) assertions with
LogCapture.contains checks for the expected log messages, or remove those blocks
if no log output is intended.

154-168: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Test 4 duplicates Test 2.

The block opens a connection, calls manager.onClose, and expects error.ConnectionNotFound. Test 2 at lines 111-125 performs the same steps and the same assertion. The comment at line 162 also describes an error-handling log path, but the code calls onClose.

Either exercise a real failure path here, for example an onOpen rejection with a missing or empty session as in src/connection/manager.zig lines 101-112, or delete the block.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/logging_test.zig` around lines 154 - 168, The Test 4 block in the logging
test duplicates Test 2 and incorrectly labels an onClose flow as error handling.
Replace it with a genuine failure-path test, such as an onOpen rejection for a
missing or empty session using the manager’s existing behavior, or remove the
block entirely; preserve assertions that match the selected path.

321-389: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Replace the manual service stacks with AppTestContext.

This block builds MemoryStrategy, ViolationTracker, TestContext, schema, SubscriptionEngine, StorageEngine, auth config, StoreService, PresenceService, MessageHandler, and ConnectionManager by hand. Lines 416-486 and 495-565 repeat the same sequence, and only the local names (sm2, sm3, sm4, empty_claims, empty_claims2, empty_claims3) and the directory label differ.

Tests at lines 81 and 220 in this same file already use AppTestContext for the same stack. Use AppTestContext.init in all three blocks. That removes about 200 duplicated lines and keeps the setup in one place when a component signature changes.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/logging_test.zig` around lines 321 - 389, Replace the manual service
initialization in this block and the corresponding repeated blocks with
AppTestContext.init, using each block’s existing directory label and local
context references as needed. Remove the duplicated MemoryStrategy,
ViolationTracker, schema, service, handler, and ConnectionManager setup and rely
on AppTestContext’s lifecycle cleanup, matching the established usage in the
earlier tests.
src/server_init_test.zig (1)

58-65: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

These pointer assertions cannot fail.

&server.memory_strategy is the address of a field inside an allocated struct. It is never null, so each @intFromPtr(...) != 0 check always passes and verifies nothing about initialization.

Assert observable initialized state instead, for example a non-zero schema table count, a configured storage path, or a registered handler count. If no such state is reachable from the test, delete these seven lines and keep the shutdown_requested check at line 68.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/server_init_test.zig` around lines 58 - 65, Remove the seven always-true
pointer assertions in the server initialization test. Replace them with
assertions on observable initialized state such as schema table count,
configured storage path, or registered handler count; if none is accessible,
delete these assertions and retain the shutdown_requested check.
src/message_handler_test.zig (1)

513-538: 🩺 Stability & Availability | 🔵 Trivial | 💤 Low value

Check the payload tag before you read .str.

expectResponseType and expectErrorCode read value.str.value() after only a presence check. If the field is not a string, the union access panics and the test reports a crash instead of a failed assertion. expectResponseId at line 526 already guards with value == .uint.

♻️ Proposed guard
     const value = (try msgpack_helpers.getMapValue(parsed, "type")) orelse return error.TestExpectedError;
+    try testing.expect(value == .str);
     try testing.expectEqualStrings(expected, value.str.value());

Apply the same guard to resp_type and code in expectErrorCode.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/message_handler_test.zig` around lines 513 - 538, Validate the
MessagePack union tag before accessing string payloads in expectResponseType and
expectErrorCode. Add the equivalent .str assertions used by expectResponseId for
value, resp_type, and code, preserving the existing expected-string comparisons
after validation.
src/storage_engine_test.zig (4)

1103-1150: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Move the alias to the top and split the combined test.

Two points on this block:

  1. Line 1103 declares const StorageEngine = sth.StorageEngine; at line 1103, while all other aliases sit at Lines 1-17. Move it up with the rest.
  2. The test bundles three independent scenarios and shares one MemoryStrategy across two failed inits and one successful init. If the first assertion fails, the later scenarios never run. Split into three tests, each with its own MemoryStrategy.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/storage_engine_test.zig` around lines 1103 - 1150, Move the StorageEngine
alias from the test block to the existing alias declarations at the top of the
file. Split “storage: engine initialization errors” into three independent tests
for invalid directory, file-as-directory, and successful initialization, giving
each test its own MemoryStrategy setup and teardown so every scenario runs
independently.

1158-1158: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Update the stale prop- test directory prefixes.

The prefixes do not match the tests. "prop-multi-table" names a thread-safety test. "prop-many-ns" names a connection-pool test. "prop-burst" names a persistence round-trip test. These prefixes appear in temporary directory names and in failure output, so they make triage harder after the property files were merged into this file.

♻️ Proposed rename
-    try sth.setupEngine(&ctx, allocator, "prop-multi-table", table);
+    try sth.setupEngine(&ctx, allocator, "storage-thread-safety", table);
-    try sth.setupEngine(&ctx, allocator, "prop-many-ns", table);
+    try sth.setupEngine(&ctx, allocator, "storage-pool-reuse", table);
-    try sth.setupEngine(&ctx, allocator, "prop-burst", table);
+    try sth.setupEngine(&ctx, allocator, "storage-persistence-types", table);

Also applies to: 1225-1225, 1254-1254

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/storage_engine_test.zig` at line 1158, Update the temporary directory
name arguments in the affected setupEngine calls in storage_engine_test.zig:
rename "prop-multi-table" to reflect the thread-safety test, "prop-many-ns" to
reflect the connection-pool test, and "prop-burst" to reflect the persistence
round-trip test. Keep the test logic unchanged and ensure each identifier is
used consistently in failure output and temporary-directory creation.

1279-1283: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

These tests verify existence, not stored content. Each site knows the exact expected value, but asserts only record != null. A wrong value, a truncated Unicode or escaped string, or an update that never applied still passes. expectFieldString and expectFieldInt are already used elsewhere in this file (Lines 169-170).

  • src/storage_engine_test.zig#L1279-L1283: compare the read value against tc.value for every case, so the Unicode and escaped-character cases actually verify the round trip.
  • src/storage_engine_test.zig#L1357-L1368: assert "updated1", "updated2", and "new3" instead of non-null, so a dropped batched update is detected.
  • src/storage_engine_test.zig#L1505-L1507: assert that val1 still equals "value1" after the field is added, so the schema-evolution property is verified rather than row presence.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/storage_engine_test.zig` around lines 1279 - 1283, Strengthen the
read-back assertions in src/storage_engine_test.zig at lines 1279-1283,
1357-1368, and 1505-1507: use the existing expectFieldString/expectFieldInt
helpers to compare each record’s stored value with tc.value, assert "updated1",
"updated2", and "new3" for the batched updates, and verify val1 remains "value1"
after schema evolution instead of checking only record presence.

1168-1204: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Capture and assert errors from every worker. std.Thread.spawn catches errors from !void entry points, prints them, and does not return them through join(). A worker can stop at its first try while the test still passes when write thread 0 created document 1. Store each worker's error and assert all results after the joins.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/storage_engine_test.zig` around lines 1168 - 1204, Capture each worker’s
error from WriteThread.run and ReadThread.run instead of allowing
std.Thread.spawn to discard it, using per-thread error storage passed through
the worker context or arguments. Ensure each worker records failures before
exiting, then join all write and read threads and assert that every stored
result is successful, so any worker error fails the test.
src/storage_engine_stability_test.zig (1)

9-19: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Trim the header comment to the coverage that exists.

The comment lists error recovery, retry logic, rapid error conditions, and resource cleanup after errors. The file contains one test that runs concurrent insert, read, and delete operations. The comment also calls this a "property test", but the file now holds standard Zig tests. Reduce the list to the concurrent-operation property, or add the missing tests.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/storage_engine_stability_test.zig` around lines 9 - 19, Trim the header
comment in the storage stability test to describe only the coverage implemented:
concurrent insert, read, and delete operations during database errors. Remove
claims about property-test status, recovery or retry logic, rapid errors,
resource cleanup, and other unimplemented scenarios.
src/storage_engine_error_test.zig (2)

88-116: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

The concurrent read test cannot fail.

runRead discards every error with catch return, and the test asserts nothing after join. If readDoc starts to fail under concurrency, or returns null, the test still passes. Only a hard crash is detected.

Collect the per-thread outcome and assert it after the joins.

🧪 Proposed assertion
     const ThreadContext = struct {
         storage: *StorageEngine,
         allocator: std.mem.Allocator,
+        found: *std.atomic.Value(usize),
     };
     const runRead = struct {
         fn run(t_ctx: ThreadContext, table_index: usize) void {
             const record = sth.readDoc(t_ctx.allocator, t_ctx.storage, table_index, 1, 1) catch return; // zwanzig-disable-line: swallowed-error
             defer if (record) |r| r.deinit(t_ctx.allocator);
+            if (record != null) _ = t_ctx.found.fetchAdd(1, .monotonic);
         }
     }.run;
     var threads: [4]std.Thread = undefined;
+    var found = std.atomic.Value(usize).init(0);
     const tbl_md = ctx.schema.table("data_table") orelse return error.UnknownTable;
     for (&threads) |*t| {
-        t.* = try std.Thread.spawn(.{}, runRead, .{ ThreadContext{ .storage = storage, .allocator = allocator }, tbl_md.index });
+        t.* = try std.Thread.spawn(.{}, runRead, .{ ThreadContext{ .storage = storage, .allocator = allocator, .found = &found }, tbl_md.index });
     }
     for (threads) |t| t.join();
+    try testing.expectEqual(`@as`(usize, 4), found.load(.acquire));
 }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/storage_engine_error_test.zig` around lines 88 - 116, Update the
concurrent test around runRead to record each thread’s read result, including
errors and null records, in shared per-thread outcome storage. After joining all
threads, assert every outcome represents a successful non-null read, while
preserving proper record cleanup and avoiding data races.

41-61: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Rename these tests to match what they verify.

The test named "error handling read-only filesystem" does not create a read-only filesystem. It writes a value, flushes, and reads it back on a normal temporary directory. The test named "error handling empty paths" at Lines 117-133 has the same problem; it uses a normal directory and a non-empty value. The names promise error coverage that does not exist, so a future reader can assume the paths are tested.

Either rename both tests to describe the write/read round trip, or add the missing setup (mark the directory read-only, pass an empty field value).

♻️ Rename option
-test "storage: error handling read-only filesystem" {
+test "storage: write and read back on filesystem-backed engine" {
-test "storage: error handling empty paths" {
+test "storage: write and read back with default path setup" {
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/storage_engine_error_test.zig` around lines 41 - 61, Rename the tests
currently labeled “storage: error handling read-only filesystem” and “storage:
error handling empty paths” to describe the write/flush/read round-trip behavior
they actually exercise. Keep the existing normal-directory setup and non-empty
value unchanged; do not retain error-oriented names unless the tests are
expanded with the corresponding read-only and empty-value setup.
src/migration_detector_test.zig (1)

263-268: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Remove the debug print block.

std.testing.expectEqual at line 269 already reports the mismatch. The std.debug.print block writes to stderr on every failing iteration and is a debug artifact.

♻️ Proposed cleanup
-        if (plan.changes.len != 0) {
-            std.debug.print("iter {d}: expected 0 changes, got {d}\n", .{ iter, plan.changes.len });
-            for (plan.changes) |c| {
-                std.debug.print("  change: kind={s} table={s}\n", .{ `@tagName`(c.kind), c.table.name });
-            }
-        }
         try std.testing.expectEqual(`@as`(usize, 0), plan.changes.len);
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/migration_detector_test.zig` around lines 263 - 268, Remove the
conditional std.debug.print block that checks plan.changes.len in the relevant
test, including the per-change diagnostic loop, while preserving the existing
std.testing.expectEqual assertion and surrounding test logic.
src/msgpack_utils_test.zig (3)

236-248: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Drop the toOwnedSlice step.

The reader at line 246 only needs a read-only view of the encoded bytes. list.items provides that. toOwnedSlice adds a second ownership transfer and a second defer free for no benefit.

♻️ Proposed simplification
         var list: std.ArrayListUnmanaged(u8) = .empty;
         defer list.deinit(allocator);
         try msgpack_utils.encode(payload, list.writer(allocator));
 
-        // Get the encoded bytes
-        const encoded = try list.toOwnedSlice(allocator);
-        defer allocator.free(encoded);
-
         // Decode using the project's standard fixed reader
-        var reader: std.Io.Reader = .fixed(encoded);
+        var reader: std.Io.Reader = .fixed(list.items);
         const decoded = try msgpack_utils.decode(allocator, &reader);
         defer decoded.free(allocator);
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/msgpack_utils_test.zig` around lines 236 - 248, Remove the toOwnedSlice
call and its associated allocator.free defer in the test around list and reader;
initialize std.Io.Reader.fixed directly from list.items, while preserving the
existing ArrayList lifetime through decoding.

255-260: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Add boundary coverage for max_map_size, max_bin_length, and max_ext_length.

wire_limits in src/msgpack_utils.zig lines 5-16 defines six limits. The boundary tests cover only max_depth, max_array_length, and max_string_length. The one-over test at lines 322-391 covers the same three.

max_map_size appears only in the bomb test at lines 138-161, and max_bin_length and max_ext_length are not tested at all. Add exact-limit and one-over cases for these three limits so a change to any wire_limits field is caught.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/msgpack_utils_test.zig` around lines 255 - 260, Add exact-boundary and
one-over test cases in the boundary success and boundary rejection tests,
covering wire_limits.max_map_size, wire_limits.max_bin_length, and
wire_limits.max_ext_length alongside the existing depth, array, and string
cases. Ensure exact-limit payloads decode successfully while payloads exceeding
each limit are rejected, using the existing test patterns and payload helpers.

88-189: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Extract the repeated bomb-construction and assertion code.

Add helpers for the shared big-endian header construction and decode/error assertion. testing.expectEqual accepts these error values in Zig 0.15.2; retain explicit branching to free an unexpected payload.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/msgpack_utils_test.zig` around lines 88 - 189, Extract the repeated
MessagePack bomb setup in the test into helpers for writing big-endian length
headers and decoding input while asserting the expected error. Update the depth,
array, map, and string bomb cases to use these helpers, retaining explicit
successful-payload cleanup before reporting an unexpected result; use
testing.expectEqual for the expected error values.
src/migration_executor_test.zig (2)

236-241: 🚀 Performance & Scalability | 🔵 Trivial | ⚡ Quick win

Fixed 100-iteration loops over a small input space repeat work without adding coverage. Every consolidated property test runs exactly 100 iterations, but each iteration draws from at most five table names and a handful of field types, and it opens a fresh in-memory database plus DDL each time. Most iterations are exact duplicates of an earlier one, so the loops raise zig build test runtime without raising coverage.

  • src/migration_executor_test.zig#L236-L241: replace the while (iter < 100) loop with iteration over table_names, or vary column count, column types, and row values per iteration. Apply the same change to the loops at lines 336, 427, and 488.
  • src/migration_detector_test.zig#L52-L54: the loop draws tname from five names and scenario from four values, so at most 20 distinct cases exist. Iterate over the table_names × scenario product instead of sampling 100 times.
  • src/migration_detector_test.zig#L219-L226: n_tables is 1 to 3 and table names are chosen by ti % table_names.len, so table identity never varies. Vary the table-name offset and the field names per iteration, or reduce the iteration count.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/migration_executor_test.zig` around lines 236 - 241, Replace the fixed
100-iteration sampling loops with bounded, distinct case coverage: in
src/migration_executor_test.zig lines 236-241, 336, 427, and 488, iterate over
table_names or vary column counts, types, and row values; in
src/migration_detector_test.zig lines 52-54, iterate over every table_names ×
scenario combination; and in src/migration_detector_test.zig lines 219-226, vary
table-name offsets and field names or reduce the iteration count. Use the
existing test-loop symbols and preserve each test’s assertions and setup.

391-409: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Assert the schema is unchanged, not only the row.

The property states that execute must not modify the database. The check verifies only that the row still exists. It does not verify that col_a still has its original TEXT type after the refused change_type plan.

Add a PRAGMA table_info check like the one at lines 546-577, and assert col_a type is still TEXT.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/migration_executor_test.zig` around lines 391 - 409, Extend the
post-execution validation near the existing row check to verify the schema as
well: query PRAGMA table_info for the migrated table, following the established
pattern around the later table-info check, and assert that col_a still has type
TEXT. Preserve the existing row-identity assertions and ensure the schema check
confirms the refused change_type plan did not alter the column definition.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@scripts/unused_pub_detector.js`:
- Line 6: Replace the broad TEST_RE match in unused_pub_detector.js with
boundary-aware patterns covering _test.zig, test-helper, and test_all.zig paths
without matching ordinary production names such as latest.zig. Add regression
cases for these classifications, rely on canonical()’s relative paths without
absolute-parent handling, then run bunx biome check --write and bun run lint via
zwanzig.

In `@src/checkpoint_worker_test.zig`:
- Around line 462-485: The test “checkpoint: escalation logic - works correctly
when needed” does not verify escalation occurred. After calling
manager.performCheckpointWithEscalation(), assert that result.mode indicates a
mode beyond .passive, while preserving the existing success and duration
assertions.
- Around line 410-429: The test does not exercise a failed checkpoint despite
claiming to verify failure-count increments. Either rename the test to describe
its actual initial-counter assertion, or add failure injection through the
checkpoint manager so a failed checkpoint is executed and
manager.failed_checkpoint_count is verified to increase.

In `@src/message_handler_test.zig`:
- Around line 566-575: Replace the optional-response handling in the StoreQuery
test block with an explicit assertion: use routeBytes when a response is
guaranteed, or assert the expected null outcome when it is valid. Preserve the
existing response type and ID checks for non-null responses, and apply the same
fix to the matching block around the StoreQuery coverage at lines 612-619.

In `@src/migration_detector_test.zig`:
- Around line 227-253: Update the cleanup around the table-construction loop to
track the number of successfully initialized tables and iterate only over those
entries, preventing access to undefined allocations when construction fails.
Also add partial cleanup for the fields slice in the loop so names already
allocated are freed if makeFieldAlloc fails before the table is created.

In `@src/msgpack_utils_test.zig`:
- Around line 74-80: Update the comments in the MessagePack utility tests to
match the existing implementation and test data: remove the stale “must fail,”
fix-name, “Bug confirmed,” and “Counterexample” claims, including the inaccurate
payload-size notes in the blocks around the oversized payload cases, and delete
the outdated line describing a 64KB+1 string near the 1MB+1 test. Preserve the
test logic unchanged.
- Around line 406-416: Update verifyPayloadEquality’s .map branch to iterate
through expected.map, retrieve each corresponding entry with
actual.mapGetGeneric(...), require the key to exist, and recursively compare its
value. Replace the catch-all else => {} branch with a failing assertion so
unsupported payload variants cannot pass silently.

In `@src/server_init_test.zig`:
- Around line 44-48: Update num_cycles in the init/deinit cycle test to a value
of at least 2 so it exercises repeated initialization and cleanup as described
by the test name and documentation, and remove the temporary single-cycle
debugging comment.
- Around line 52-71: Move the data-directory cleanup out of the scope where
server is still alive: wrap server initialization, assertions, and the existing
defer-based server.deinit() in an inner block, then call deleteTree(data_dir)
after that block completes. Preserve the current cleanup behavior while ensuring
deinit finishes before removing files.

In `@src/storage_engine_test.zig`:
- Around line 1547-1550: Update the delete branch in the fuzz operation dispatch
to derive the table index through the existing ctx.tableIndex helper for
"items", matching the other operation branches, and pass that resolved index
into the delete request instead of hardcoding 0.

In `@src/uwebsockets_wrapper_test.zig`:
- Around line 557-584: In the test covering the WebSocket callback counts,
rename the test to reflect that it expects one open, three message, and one
close invocation, and defer destroyMockWebSocket immediately after
createMockWebSocket so cleanup runs on assertion failures. Remove the duplicated
final assertions while preserving the existing count checks.

---

Nitpick comments:
In `@src/checkpoint_worker_test.zig`:
- Around line 357-381: Update the “checkpoint: WAL size management - size
decreases or stays same after success” test to assert result.success
unconditionally after performCheckpoint(.truncate) and remove the surrounding
conditional; retain both WAL-size invariant assertions so failures are reported
instead of skipped.
- Around line 487-514: Deduplicate the consolidated tests: in
src/checkpoint_worker_test.zig lines 487-514, remove or merge the Prometheus
formatting test into “CheckpointWorker: Prometheus metrics format”; in lines
431-460, remove or merge the metrics accuracy test into “CheckpointWorker:
performCheckpoint - metrics update” while preserving the duration nonnegative
assertion if useful; in src/config/loader_test.zig lines 608-872, merge or
remove the auth, security, and performance round-trip tests in favor of the
earlier equivalent tests, while retaining the complete-config round-trip test.

In `@src/logging_test.zig`:
- Around line 27-68: In src/logging_test.zig lines 27-68, either wire LogCapture
into a pub const std_options.logFn that records emitted messages or remove the
unused LogCapture helper. In lines 396-400 and 488-492, replace the placeholder
testing.expect(true) assertions with LogCapture.contains checks for the expected
log messages, or remove those blocks if no log output is intended.
- Around line 154-168: The Test 4 block in the logging test duplicates Test 2
and incorrectly labels an onClose flow as error handling. Replace it with a
genuine failure-path test, such as an onOpen rejection for a missing or empty
session using the manager’s existing behavior, or remove the block entirely;
preserve assertions that match the selected path.
- Around line 321-389: Replace the manual service initialization in this block
and the corresponding repeated blocks with AppTestContext.init, using each
block’s existing directory label and local context references as needed. Remove
the duplicated MemoryStrategy, ViolationTracker, schema, service, handler, and
ConnectionManager setup and rely on AppTestContext’s lifecycle cleanup, matching
the established usage in the earlier tests.

In `@src/message_handler_test.zig`:
- Around line 513-538: Validate the MessagePack union tag before accessing
string payloads in expectResponseType and expectErrorCode. Add the equivalent
.str assertions used by expectResponseId for value, resp_type, and code,
preserving the existing expected-string comparisons after validation.

In `@src/migration_detector_test.zig`:
- Around line 263-268: Remove the conditional std.debug.print block that checks
plan.changes.len in the relevant test, including the per-change diagnostic loop,
while preserving the existing std.testing.expectEqual assertion and surrounding
test logic.

In `@src/migration_executor_test.zig`:
- Around line 236-241: Replace the fixed 100-iteration sampling loops with
bounded, distinct case coverage: in src/migration_executor_test.zig lines
236-241, 336, 427, and 488, iterate over table_names or vary column counts,
types, and row values; in src/migration_detector_test.zig lines 52-54, iterate
over every table_names × scenario combination; and in
src/migration_detector_test.zig lines 219-226, vary table-name offsets and field
names or reduce the iteration count. Use the existing test-loop symbols and
preserve each test’s assertions and setup.
- Around line 391-409: Extend the post-execution validation near the existing
row check to verify the schema as well: query PRAGMA table_info for the migrated
table, following the established pattern around the later table-info check, and
assert that col_a still has type TEXT. Preserve the existing row-identity
assertions and ensure the schema check confirms the refused change_type plan did
not alter the column definition.

In `@src/msgpack_utils_test.zig`:
- Around line 236-248: Remove the toOwnedSlice call and its associated
allocator.free defer in the test around list and reader; initialize
std.Io.Reader.fixed directly from list.items, while preserving the existing
ArrayList lifetime through decoding.
- Around line 255-260: Add exact-boundary and one-over test cases in the
boundary success and boundary rejection tests, covering
wire_limits.max_map_size, wire_limits.max_bin_length, and
wire_limits.max_ext_length alongside the existing depth, array, and string
cases. Ensure exact-limit payloads decode successfully while payloads exceeding
each limit are rejected, using the existing test patterns and payload helpers.
- Around line 88-189: Extract the repeated MessagePack bomb setup in the test
into helpers for writing big-endian length headers and decoding input while
asserting the expected error. Update the depth, array, map, and string bomb
cases to use these helpers, retaining explicit successful-payload cleanup before
reporting an unexpected result; use testing.expectEqual for the expected error
values.

In `@src/server_init_test.zig`:
- Around line 58-65: Remove the seven always-true pointer assertions in the
server initialization test. Replace them with assertions on observable
initialized state such as schema table count, configured storage path, or
registered handler count; if none is accessible, delete these assertions and
retain the shutdown_requested check.

In `@src/storage_engine_error_test.zig`:
- Around line 88-116: Update the concurrent test around runRead to record each
thread’s read result, including errors and null records, in shared per-thread
outcome storage. After joining all threads, assert every outcome represents a
successful non-null read, while preserving proper record cleanup and avoiding
data races.
- Around line 41-61: Rename the tests currently labeled “storage: error handling
read-only filesystem” and “storage: error handling empty paths” to describe the
write/flush/read round-trip behavior they actually exercise. Keep the existing
normal-directory setup and non-empty value unchanged; do not retain
error-oriented names unless the tests are expanded with the corresponding
read-only and empty-value setup.

In `@src/storage_engine_stability_test.zig`:
- Around line 9-19: Trim the header comment in the storage stability test to
describe only the coverage implemented: concurrent insert, read, and delete
operations during database errors. Remove claims about property-test status,
recovery or retry logic, rapid errors, resource cleanup, and other unimplemented
scenarios.

In `@src/storage_engine_test.zig`:
- Around line 1103-1150: Move the StorageEngine alias from the test block to the
existing alias declarations at the top of the file. Split “storage: engine
initialization errors” into three independent tests for invalid directory,
file-as-directory, and successful initialization, giving each test its own
MemoryStrategy setup and teardown so every scenario runs independently.
- Line 1158: Update the temporary directory name arguments in the affected
setupEngine calls in storage_engine_test.zig: rename "prop-multi-table" to
reflect the thread-safety test, "prop-many-ns" to reflect the connection-pool
test, and "prop-burst" to reflect the persistence round-trip test. Keep the test
logic unchanged and ensure each identifier is used consistently in failure
output and temporary-directory creation.
- Around line 1279-1283: Strengthen the read-back assertions in
src/storage_engine_test.zig at lines 1279-1283, 1357-1368, and 1505-1507: use
the existing expectFieldString/expectFieldInt helpers to compare each record’s
stored value with tc.value, assert "updated1", "updated2", and "new3" for the
batched updates, and verify val1 remains "value1" after schema evolution instead
of checking only record presence.
- Around line 1168-1204: Capture each worker’s error from WriteThread.run and
ReadThread.run instead of allowing std.Thread.spawn to discard it, using
per-thread error storage passed through the worker context or arguments. Ensure
each worker records failures before exiting, then join all write and read
threads and assert that every stored result is successful, so any worker error
fails the test.

In `@src/uwebsockets_wrapper_test.zig`:
- Around line 589-598: Update the CallbackContext struct to provide defaults for
all fields, using zero or null values matching each field type, so tests can
initialize it with .{} and future fields do not require manual initialization.
- Around line 322-379: Update the property test around WebSocketServer
initialization and handler invocation so it does not claim wrapper-dispatch
coverage: either remove the unused server setup and relabel the test as direct
callback-contract coverage, or route simulated events through WebSocketServer’s
dispatch API instead of invoking handlers.on_open, handlers.on_message, and
handlers.on_close directly. Keep the unregistered-callback case aligned with the
chosen scope, and rely on the end-to-end suite for real server-client dispatch
coverage.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: daaf7410-bb6f-464b-84e5-6b454c93890c

📥 Commits

Reviewing files that changed from the base of the PR and between 92b6613 and 51c5b56.

📒 Files selected for processing (22)
  • scripts/unused_pub_detector.js
  • src/checkpoint_worker_property_test.zig
  • src/checkpoint_worker_test.zig
  • src/config/loader_property_test.zig
  • src/config/loader_test.zig
  • src/logging_test.zig
  • src/message_handler_property_test.zig
  • src/message_handler_test.zig
  • src/migration_detector_test.zig
  • src/migration_executor_property_test.zig
  • src/migration_executor_test.zig
  • src/msgpack_utils_property_test.zig
  • src/msgpack_utils_test.zig
  • src/server_init_test.zig
  • src/storage_engine_error_test.zig
  • src/storage_engine_property_test.zig
  • src/storage_engine_stability_test.zig
  • src/storage_engine_test.zig
  • src/test_all.zig
  • src/uwebsockets_wrapper_property_test.zig
  • src/uwebsockets_wrapper_test.zig
  • tests/e2e/src/harness.ts
💤 Files with no reviewable changes (8)
  • src/message_handler_property_test.zig
  • src/storage_engine_property_test.zig
  • src/checkpoint_worker_property_test.zig
  • src/msgpack_utils_property_test.zig
  • src/uwebsockets_wrapper_property_test.zig
  • src/migration_executor_property_test.zig
  • src/config/loader_property_test.zig
  • tests/e2e/src/harness.ts
🛑 Comments failed to post (3)
src/migration_detector_test.zig (1)

227-253: 🩺 Stability & Availability | 🟡 Minor | ⚡ Quick win

The cleanup block can free undefined pointers if table construction fails.

allocator.alloc at line 227 returns undefined memory. The defer block at lines 228-239 iterates over all n_tables entries. If any try inside the loop at lines 244-252 fails, the entries after the failing index still hold undefined values, and the cleanup frees undefined pointers.

Track the number of initialized tables, and free only those.

♻️ Proposed fix
         const n_tables = rand.intRangeAtMost(usize, 1, 3);
         const tables = try allocator.alloc(schema_types.Table, n_tables);
+        var initialized: usize = 0;
         defer {
-            for (tables) |t| {
+            for (tables[0..initialized]) |t| {
                 allocator.free(t.name);
                 allocator.free(t.name_quoted);
                 for (t.fields) |f| {
                     allocator.free(f.name);
                     allocator.free(f.name_quoted);
                 }
                 allocator.free(t.fields);
             }
             allocator.free(tables);
         }
 
         for (0..n_tables) |ti| {
@@
             tables[ti] = try schema_helpers.makeTableAlloc(allocator, tname, fields);
+            initialized += 1;
         }

The fields slice itself still leaks if makeFieldAlloc fails mid-loop. Add an errdefer for the partially filled fields slice if you want full coverage.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

        const tables = try allocator.alloc(schema_types.Table, n_tables);
        var initialized: usize = 0;
        defer {
            for (tables[0..initialized]) |t| {
                allocator.free(t.name);
                allocator.free(t.name_quoted);
                for (t.fields) |f| {
                    allocator.free(f.name);
                    allocator.free(f.name_quoted);
                }
                allocator.free(t.fields);
            }
            allocator.free(tables);
        }

        for (0..n_tables) |ti| {
            const tname = table_names[ti % table_names.len];
            const n_fields = rand.intRangeAtMost(usize, 1, 3);
            const fields = try allocator.alloc(schema_types.Field, n_fields);

            for (0..n_fields) |fi| {
                const mf_name = field_names[fi % field_names.len];
                const mf_type = field_types[rand.intRangeAtMost(usize, 0, field_types.len - 1)];
                fields[fi] = try schema_helpers.makeFieldAlloc(allocator, mf_name, mf_type);
            }

            tables[ti] = try schema_helpers.makeTableAlloc(allocator, tname, fields);
            initialized += 1;
        }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/migration_detector_test.zig` around lines 227 - 253, Update the cleanup
around the table-construction loop to track the number of successfully
initialized tables and iterate only over those entries, preventing access to
undefined allocations when construction fails. Also add partial cleanup for the
fields slice in the loop so names already allocated are freed if makeFieldAlloc
fails before the table is created.
src/server_init_test.zig (2)

44-48: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

num_cycles = 1 does not test idempotence.

The test name and the doc comment at lines 11-14 state that several init/deinit cycles run and stay independent. With one cycle, no re-initialization occurs, so the property is not covered. The inline comment also marks this as a temporary debugging value.

Raise num_cycles to at least 2, or rename the test to match the single-cycle behavior.

💚 Proposed change
-    // Property: Multiple init/deinit cycles should not leak memory
-    // Test with 1 cycle first to debug leaks
-    const num_cycles = 1;
+    // Property: Multiple init/deinit cycles should not leak memory
+    const num_cycles = 3;
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

    // Property: Multiple init/deinit cycles should not leak memory
    const num_cycles = 3;
    var i: usize = 0;
    while (i < num_cycles) : (i += 1) {
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/server_init_test.zig` around lines 44 - 48, Update num_cycles in the
init/deinit cycle test to a value of at least 2 so it exercises repeated
initialization and cleanup as described by the test name and documentation, and
remove the temporary single-cycle debugging comment.

52-71: 🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

deleteTree runs before server.deinit().

The defer block at lines 52-56 runs at the end of each loop iteration. Line 71 runs before that. The test therefore removes the data directory while the server still holds it, and server.deinit() then shuts down storage and checkpoint components against deleted files. Per src/server.zig lines 93-145, initDetailed opens storage and checkpoint state under data_dir, so deinit can flush or close files there.

Move the cleanup after the server is destroyed. An inner block makes the order explicit.

🐛 Proposed fix
     while (i < num_cycles) : (i += 1) {
-        // Initialize server with unique data directory and custom schema path
-        const server = try ZyncBaseServer.initDetailed(allocator, null, data_dir, schema_file_path, null);
-        std.log.debug("Server initialized", .{});
-        defer {
-            std.log.debug("About to call server.deinit()", .{});
-            server.deinit();
-            std.log.debug("server.deinit() returned", .{});
-        }
+        {
+            // Initialize server with unique data directory and custom schema path
+            const server = try ZyncBaseServer.initDetailed(allocator, null, data_dir, schema_file_path, null);
+            defer server.deinit();
 
-        // Verify server is properly initialized
-        try testing.expect(`@intFromPtr`(&server.memory_strategy) != 0);
+            // Verify shutdown flag is initialized to false
+            try testing.expect(!server.shutdown_requested.load(.acquire));
+        }
 
-        // Verify shutdown flag is initialized to false
-        try testing.expect(!server.shutdown_requested.load(.acquire));
-
-        // Clean up database file between cycles
+        // Clean up database files between cycles, after the server is destroyed
         std.fs.cwd().deleteTree(data_dir) catch {}; // zwanzig-disable-line: empty-catch-engine
     }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/server_init_test.zig` around lines 52 - 71, Move the data-directory
cleanup out of the scope where server is still alive: wrap server
initialization, assertions, and the existing defer-based server.deinit() in an
inner block, then call deleteTree(data_dir) after that block completes. Preserve
the current cleanup behavior while ensuring deinit finishes before removing
files.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
src/checkpoint_worker_test.zig (1)

325-358: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Test persisted records before and after the checkpoint.

This test does not write data before performCheckpoint or read data after it. It only checks worker metrics. The test can pass without detecting lost persisted records.

Insert representative records, run the checkpoint, then read and compare the records after the checkpoint.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/checkpoint_worker_test.zig` around lines 325 - 358, Update the integrity
test around manager.performCheckpoint to insert representative records through
the checkpoint context before checkpointing, then read them back after the
checkpoint and compare them with the originals. Keep the existing checkpoint
success and metric assertions, but make the test fail if persisted records are
lost.
src/logging_test.zig (1)

34-69: 🎯 Functional Correctness | 🟠 Major | 🏗️ Heavy lift

Capture and assert log records.

These tests only verify connection and message-handler behavior. They do not verify any log record. A removed log call, wrong level, or wrong formatted field will still pass.

Configure a test log sink. Assert the expected level and message fields for each path.

  • src/logging_test.zig#L34-L69: Assert open and close records include the connection ID and close details.
  • src/logging_test.zig#L160-L234: Assert malformed messages produce the expected error records.
  • src/logging_test.zig#L238-L269: Configure distinct thresholds and assert that filtering includes or suppresses each record.
  • src/logging_test.zig#L283-L326: Assert formatted records contain the connection ID, error details, and close parameters.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/logging_test.zig` around lines 34 - 69, Configure a test log sink and
extend the logging tests in src/logging_test.zig:34-69,
src/logging_test.zig:160-234, src/logging_test.zig:238-269, and
src/logging_test.zig:283-326 to capture records and assert expected levels and
fields. Cover connection IDs and close details for open/close paths, error
records for malformed messages, threshold filtering for each level, and
formatted records containing connection IDs, error details, and close
parameters.
🧹 Nitpick comments (2)
src/logging_test.zig (1)

15-136: 📐 Maintainability & Code Quality | 🔵 Trivial

Run the required Zig checks before merge.

The environment lacks zwanzig, bun, and zig, so zwanzig bun run lint and bun run test:safe did not run.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/logging_test.zig` around lines 15 - 136, Run the required Zig checks
before merging the changes: execute zwanzig bun run lint and bun run test:safe
in an environment with zwanzig, bun, and zig available. Apply this validation to
src/logging_test.zig lines 15-136 and src/message_handler_test.zig lines
494-754; no direct code change is requested at either site.

Source: Coding guidelines

src/storage_engine_error_test.zig (1)

41-41: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Add a real read-only filesystem regression test. The existing test changes no permissions and only performs a writable round trip. Create a read-only data directory and assert the expected initialization error.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/storage_engine_error_test.zig` at line 41, Add a separate regression test
alongside “storage: write/flush/read round-trip on file-backed engine” that
creates a data directory, changes it to read-only permissions, and initializes
the file-backed storage engine against it. Assert that initialization returns
the expected read-only filesystem error, while preserving the existing writable
round-trip test.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@scripts/unused_pub_detector.js`:
- Around line 9-31: Update TEST_RE so helper and runner filename matches require
“test” at the basename start or immediately after “-” or “_”, preventing matches
such as contest_helpers.zig and latest_runner.zig. Extend the --selftest cases
with negative entries covering these false positives while preserving the
existing valid test-file classifications.

In `@src/migration_executor_test.zig`:
- Around line 520-521: Update the comment above target_major in the loop to
describe the persisted major version dynamically, reflecting that
persisted_major varies across 1, 2, and 3 rather than claiming a fixed value of
1.

In `@src/storage_engine_error_test.zig`:
- Line 41: Update the test “storage: write/flush/read round-trip on file-backed
engine” to validate the returned field value, not just record existence: after
reading the record, assert that its val field equals “value1” using the existing
tbl.getOne(...).expectFieldString(...) pattern or the equivalent tbl.readDoc
accessor.
- Around line 121-124: Update the thread-spawning loop in the storage error test
to track how many threads were successfully created, and add an errdefer that
joins threads[0..spawned_count] when a later std.Thread.spawn call fails. Keep
the existing final join for successful completion, ensuring ctx.deinit() cannot
run while any spawned runRead thread is still using storage.

---

Outside diff comments:
In `@src/checkpoint_worker_test.zig`:
- Around line 325-358: Update the integrity test around
manager.performCheckpoint to insert representative records through the
checkpoint context before checkpointing, then read them back after the
checkpoint and compare them with the originals. Keep the existing checkpoint
success and metric assertions, but make the test fail if persisted records are
lost.

In `@src/logging_test.zig`:
- Around line 34-69: Configure a test log sink and extend the logging tests in
src/logging_test.zig:34-69, src/logging_test.zig:160-234,
src/logging_test.zig:238-269, and src/logging_test.zig:283-326 to capture
records and assert expected levels and fields. Cover connection IDs and close
details for open/close paths, error records for malformed messages, threshold
filtering for each level, and formatted records containing connection IDs, error
details, and close parameters.

---

Nitpick comments:
In `@src/logging_test.zig`:
- Around line 15-136: Run the required Zig checks before merging the changes:
execute zwanzig bun run lint and bun run test:safe in an environment with
zwanzig, bun, and zig available. Apply this validation to src/logging_test.zig
lines 15-136 and src/message_handler_test.zig lines 494-754; no direct code
change is requested at either site.

In `@src/storage_engine_error_test.zig`:
- Line 41: Add a separate regression test alongside “storage: write/flush/read
round-trip on file-backed engine” that creates a data directory, changes it to
read-only permissions, and initializes the file-backed storage engine against
it. Assert that initialization returns the expected read-only filesystem error,
while preserving the existing writable round-trip test.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 35b00200-197a-4a57-8947-7b96066a0e7a

📥 Commits

Reviewing files that changed from the base of the PR and between 51c5b56 and 0a7ed17.

📒 Files selected for processing (13)
  • scripts/unused_pub_detector.js
  • src/checkpoint_worker_test.zig
  • src/config/loader_test.zig
  • src/logging_test.zig
  • src/message_handler_test.zig
  • src/migration_detector_test.zig
  • src/migration_executor_test.zig
  • src/msgpack_utils_test.zig
  • src/server_init_test.zig
  • src/storage_engine_error_test.zig
  • src/storage_engine_stability_test.zig
  • src/storage_engine_test.zig
  • src/uwebsockets_wrapper_test.zig
💤 Files with no reviewable changes (1)
  • src/config/loader_test.zig
🚧 Files skipped from review as they are similar to previous changes (6)
  • src/migration_detector_test.zig
  • src/storage_engine_stability_test.zig
  • src/msgpack_utils_test.zig
  • src/server_init_test.zig
  • src/uwebsockets_wrapper_test.zig
  • src/storage_engine_test.zig

Comment thread scripts/unused_pub_detector.js Outdated
Comment thread src/migration_executor_test.zig Outdated
Comment thread src/storage_engine_error_test.zig
Comment thread src/storage_engine_error_test.zig
@coderabbitai

coderabbitai Bot commented Aug 2, 2026 •

Copy link
Copy Markdown

@mstdokumaci I will review all changes in this pull request.

✅ Action performed

Full review finished.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/storage_engine_error_test.zig (1)

130-145: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

The renamed test does not cover an empty value.

The name says "with empty value", but Line 139 inserts "value", and Lines 142-144 assert only that the record exists. As written the test duplicates the round-trip test at Line 41. Insert an empty string and assert the round-trip value so the name matches the coverage.

🐛 Proposed fix
-    try ctx.insertText("data_table", 1, 1, "val", "value");
+    try ctx.insertText("data_table", 1, 1, "val", "");
     try storage.flushPendingWrites();
     {
-        const record = try tbl.readDoc(allocator, 1, 1);
-        defer if (record) |r| r.deinit(allocator);
-        try testing.expect(record != null);
+        var doc = try tbl.getOne(allocator, 1, 1);
+        defer doc.deinit();
+        _ = try doc.expectFieldString("val", "");
     }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/storage_engine_error_test.zig` around lines 130 - 145, Update the test
“storage: write/flush/read round-trip with empty value” to insert an empty
string for the val field instead of "value", then assert that the read record
contains the expected empty value, not merely that the record exists. Preserve
the existing setup, flush, and cleanup flow.
♻️ Duplicate comments (1)
src/msgpack_utils_test.zig (1)

412-412: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Replace else => {} with a failing branch.

The switch handles .int, .uint, .bool, .str, and .map. The remaining msgpack.Payload variants, including .nil, .float, .bin, .ext, and .arr, pass without any comparison. If a future payload type is added to the generator at lines 155-186, the round-trip test will report success without verifying the decoded value. The .map key and value comparison from the earlier review is now in place; only this branch remains.

🐛 Proposed fix
-        else => {},
+        else => return error.TestUnsupportedPayloadVariant,
     }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/msgpack_utils_test.zig` at line 412, Replace the fallback else branch in
the payload switch within the round-trip test with a failing assertion or test
failure. Ensure unsupported Payload variants, including nil, float, bin, ext,
and arr, cannot pass without decoded-value verification, while preserving the
existing handling for int, uint, bool, str, and map.
🧹 Nitpick comments (15)
src/msgpack_utils_test.zig (2)

80-85: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Use std.mem.writeInt instead of the hand-written byte shifts.

std.mem.writeInt performs the same big-endian store and removes the manual shift arithmetic.

♻️ Proposed refactor
 fn writeBe32(buf: []u8, offset: usize, value: u32) void {
-    buf[offset + 0] = `@intCast`((value >> 24) & 0xff);
-    buf[offset + 1] = `@intCast`((value >> 16) & 0xff);
-    buf[offset + 2] = `@intCast`((value >> 8) & 0xff);
-    buf[offset + 3] = `@intCast`(value & 0xff);
+    std.mem.writeInt(u32, buf[offset..][0..4], value, .big);
 }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/msgpack_utils_test.zig` around lines 80 - 85, Update the writeBe32 helper
to use std.mem.writeInt for the big-endian u32 store instead of manually
shifting and assigning individual bytes, preserving its existing buffer offset
and value behavior.

111-131: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Remove the array and map cases that the one-over-boundary test already covers.

Lines 113 and 124 use count = 100001. Lines 326 and 338 use the same value with the same opcodes and the same expected errors. The two tests therefore assert the same behaviour twice and allocate roughly 300 KB twice.

Keep the one-over-boundary cases in the test at lines 311-384 and drop the duplicated blocks here, or change the counts here to a clearly-oversized value such as 1_000_000 so the two tests cover distinct magnitudes.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/msgpack_utils_test.zig` around lines 111 - 131, Remove the duplicate
array32 and map32 bomb blocks using count 100001 from the earlier test section,
since the one-over-boundary cases in the later test already cover that behavior.
Keep the later cases unchanged, or update these earlier cases to a clearly
larger count such as 1_000_000 while preserving their expected ArrayTooLarge and
MapTooLarge errors.
src/migration_executor_test.zig (2)

411-432: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Extract the PRAGMA table_info reader into a shared helper.

The PragmaRow struct and the iteration loop are duplicated at lines 411-432 and 571-592. A single helper reduces the duplication and centralises the row-field frees.

♻️ Suggested helper
const PragmaRow = struct {
    cid: i64,
    name: []const u8,
    type: []const u8,
    notnull: i64,
    dflt_value: ?[]const u8,
    pk: i64,
};

/// Returns the declared SQLite type of `column` in `table`, or null when absent.
/// The caller owns the returned slice.
fn columnType(
    db: *sqlite.Db,
    allocator: std.mem.Allocator,
    table: []const u8,
    column: []const u8,
) !?[]const u8 {
    const pragma_sql = try std.fmt.allocPrintSentinel(allocator, "PRAGMA table_info({s})", .{table}, 0);
    defer allocator.free(pragma_sql);

    var stmt = try db.prepareDynamic(pragma_sql);
    defer stmt.deinit();

    var found: ?[]const u8 = null;
    var iter = try stmt.iteratorAlloc(PragmaRow, allocator, .{});
    while (try iter.nextAlloc(allocator, .{})) |row| {
        defer {
            allocator.free(row.name);
            if (row.dflt_value) |dv| allocator.free(dv);
        }
        if (found == null and std.mem.eql(u8, row.name, column)) {
            found = row.type;
        } else {
            allocator.free(row.type);
        }
    }
    return found;
}

Each test then asserts on the result of columnType.

Also applies to: 571-592

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/migration_executor_test.zig` around lines 411 - 432, Extract the
duplicated PragmaRow definition and PRAGMA table_info iteration from the
affected tests into a shared columnType helper near the test utilities. Have it
prepare the table-info query, free every non-returned row field centrally,
return the declared type for the requested column or null when absent, and
update both test sites to assert through this helper.

401-409: 🎯 Functional Correctness | 🔵 Trivial | 💤 Low value

Remove redundant dupeZ calls. prepareDynamic accepts []const u8, so the direct allocPrint results are valid. Remove the dupeZ calls at lines 295 and 387.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/migration_executor_test.zig` around lines 401 - 409, Remove the redundant
dupeZ calls in the SQL preparation paths around prepareDynamic, specifically at
the call sites near lines 295 and 387. Pass the allocPrint result directly to
prepareDynamic, preserving the existing allocation and cleanup behavior.
src/config/loader_test.zig (2)

239-752: 📐 Maintainability & Code Quality | 🔵 Trivial

Run the filtered Zig test suite and lint for this module.

This file adds substantial new configuration-loader test coverage. Run zig build test or the filtered unit test for the config module to confirm these new tests pass, and run bun run lint via zwanzig on this file.

As per coding guidelines, "After core Zig logic changes, run zig build test; for module-specific changes, run the corresponding filtered unit test" and "Run bun run lint via zwanzig to maintain code quality and catch common pitfalls."

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/config/loader_test.zig` around lines 239 - 752, Run the
configuration-loader tests for loader_test.zig using the module-specific
filtered Zig test command, or run zig build test if required, and resolve any
failures. Then run the project lint command via zwanzig (bun run lint) against
this module and fix any reported issues.

Source: Coding guidelines


380-493: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Extract a shared helper for the repeated config/schema file scaffolding.

The four validation tests in this range, and the file-existence and round-trip tests later in this file (lines 495-606, 608-752), all repeat the same sequence: join a temp-file path, join a schema-file path, build content with std.fmt.allocPrint, write both files, call ConfigLoader.load. Extract a helper, for example writeConfigWithSchema(allocator, context, config_content, schema_content) ![]const u8, that returns the temp-file path, and use it across these tests to reduce duplication and keep future edits consistent.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/config/loader_test.zig` around lines 380 - 493, Extract a shared helper
near the existing loader test utilities, such as writeConfigWithSchema, to
create the temporary config and schema paths, write both contents, and return
the allocated config path. Replace the repeated path-joining and file-writing
setup in the four validation tests and the later file-existence and round-trip
tests, preserving each test’s existing config generation, cleanup, schema
content, and ConfigLoader.load behavior.
src/checkpoint_worker_test.zig (1)

319-479: 📐 Maintainability & Code Quality | 🔵 Trivial

Run the filtered Zig test suite and lint for this module.

This file adds new checkpoint-worker test coverage. Run zig build test or the filtered unit test for the checkpoint module to confirm these new tests pass, and run bun run lint via zwanzig on this file.

As per coding guidelines, "After core Zig logic changes, run zig build test; for module-specific changes, run the corresponding filtered unit test" and "Run bun run lint via zwanzig to maintain code quality and catch common pitfalls."

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/checkpoint_worker_test.zig` around lines 319 - 479, Run the
checkpoint-worker filtered Zig tests, or the full zig build test suite if no
filter is available, and resolve any failures in the added tests. Then run bun
run lint through zwanzig against the checkpoint test module and address any
reported issues.

Source: Coding guidelines

src/storage_engine_test.zig (4)

1270-1271: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Use one allocator reference in the read loop.

Line 1270 passes testing.allocator and Line 1271 frees with allocator. Both are the same allocator here, so behavior is correct, but the mismatch is easy to break later. Use allocator in both places.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/storage_engine_test.zig` around lines 1270 - 1271, Update the read loop
around test_table.readDoc so it passes allocator instead of testing.allocator,
matching the allocator used by the record deinit cleanup.

1568-1590: 🚀 Performance & Scalability | 🔵 Trivial | 💤 Low value

The hardcoded delete index is fixed; hoist the table lookup out of the loop.

Line 1583 now resolves the index through ctx.tableIndex("items"), which addresses the earlier review. ctx.table("items") at Line 1587 runs inside the loop on every query iteration. Move it above the while loop next to items_index.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/storage_engine_test.zig` around lines 1568 - 1590, Hoist the
`ctx.table("items")` lookup out of the `while` loop in this test, placing it
alongside `items_index` before the loop. Reuse the resulting `test_table` in the
query branch while preserving the existing `readDoc` behavior.

1139-1160: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Duplicate coverage of database file creation.

The test at Lines 131-145 already asserts that zyncbase.db is created after a file-backed engine init. This test repeats the same assertion with a manual setup. Consider removing one of the two, or keep this one and delete the earlier test, so the file-creation contract has a single owner.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/storage_engine_test.zig` around lines 1139 - 1160, Remove the duplicate
database-file creation test, keeping a single test as the owner of this
contract. Prefer retaining the existing coverage in the earlier test and delete
the manual setup test identified by “storage: engine init creates database
file,” including its setup and file assertion.

1353-1353: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Migrated test names overstate the coverage. Both tests came from property-style suites and kept names that describe concurrency or isolation, but each body runs sequentially on the test thread and only checks final persisted values. Rename both so the names match what they assert.

  • src/storage_engine_test.zig#L1353-L1353: rename "storage: transaction isolation and consistency" to a batch-consistency name, for example "storage: batched writes commit consistently".
  • src/storage_engine_test.zig#L1403-L1403: rename "storage: concurrent batch processing" to a sequential multi-batch name, for example "storage: multi-batch writes all persist".
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/storage_engine_test.zig` at line 1353, Rename the test at
src/storage_engine_test.zig lines 1353-1353 from “storage: transaction isolation
and consistency” to a batch-consistency name such as “storage: batched writes
commit consistently”; rename the test at lines 1403-1403 from “storage:
concurrent batch processing” to a sequential multi-batch name such as “storage:
multi-batch writes all persist”, without changing their test bodies.
src/storage_engine_error_test.zig (1)

41-59: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

The value assertion is now correct; the test directory name is stale.

Lines 57-59 assert val == "value1", which resolves the earlier review. Line 45 still passes "storage-error-readonly", but the test no longer covers a read-only filesystem. Rename it to "storage-error-roundtrip" so the artifact directory matches the test.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/storage_engine_error_test.zig` around lines 41 - 59, Rename the
setupEngineWithOptions test directory argument in “storage: write/flush/read
round-trip on file-backed engine” from “storage-error-readonly” to
“storage-error-roundtrip” so it matches the test’s round-trip behavior.
src/storage_engine_stability_test.zig (1)

9-17: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

The updated comment claims error injection that the test does not perform.

Lines 9-11 state that errors are injected. The test at Lines 21-71 runs concurrent insert, read, and delete operations and swallows any error with catch continue. It does not inject failures. Lines 13-17 also list "Rapid error conditions", "Error recovery and retry logic", and "Resource cleanup after errors", none of which the body exercises. Describe the actual coverage: concurrent mixed operations complete without a panic, and errors are tolerated.

📝 Proposed fix
 // This property test verifies that the storage engine stays stable under
-// concurrent insert/read/delete operations while errors are injected:
-// no panics or crashes occur, and the engine keeps operating.
-//
-// We test various error scenarios to ensure the server never crashes:
-// - Multiple concurrent operations during errors
-// - Rapid error conditions
-// - Error recovery and retry logic
-// - Resource cleanup after errors
+// concurrent insert/read/delete operations from multiple threads:
+// individual operation errors are tolerated, and no panic or crash occurs.
+//
+// Coverage:
+// - Multiple threads issuing mixed operations against one engine
+// - Errors from any single operation do not stop the worker
+// - The engine still accepts a flush after all workers finish
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/storage_engine_stability_test.zig` around lines 9 - 17, Update the
property-test comment above the concurrent operation test to remove claims about
injected failures, error recovery, retries, and cleanup after errors. Describe
only the verified coverage: concurrent mixed insert/read/delete operations
complete without panics or crashes, while operation errors are tolerated via the
existing handling.
src/logging_test.zig (2)

202-210: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Test 3 doesn't verify logging.

This block is labeled "Database errors are logged" inside a test whose docstring says it verifies that "a log entry is written with error details" (Lines 141-142). The code only reads a missing document via sth.readDoc and asserts record == null, a normal not-found result, not an error path, and it never calls manager.onMessage or any code that would emit an error log.

Either route a message through the handler that triggers an actual storage error, or update the comment to state that this block only verifies the null-record path, not error logging.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/logging_test.zig` around lines 202 - 210, Update Test 3 in the logging
test so it actually exercises an error path and verifies that the logging
handler, including manager.onMessage, receives a message with error details;
alternatively, revise the Test 3 comment and enclosing test documentation to
describe only the null-record behavior and remove the claim that database errors
are logged.

21-23: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick win

Check the leak status instead of discarding it.

All four tests in this file call gpa.deinit() and discard the result with _ = (Lines 21-23, 144-146, 245-247, 279-281). This means a memory leak in ConnectionManager, MessageHandler, or the storage engine paths exercised here will not fail the test.

src/server_init_test.zig (Lines 17-24, same PR) checks leaked == .leak and panics on a leak. Apply the same pattern here so these tests actually catch memory-safety regressions, consistent with the project's memory-safety testing goals.

As per coding guidelines, "Run bun run test:safe periodically after Zig changes to detect memory-safety regressions" — discarding the leak-check result in these tests weakens that safety net at the unit-test level.

🔧 Proposed fix (apply to all four occurrences)
     var gpa = std.heap.GeneralPurposeAllocator(.{}){};
-    defer _ = gpa.deinit();
+    defer {
+        const leaked = gpa.deinit();
+        if (leaked == .leak) {
+            std.debug.print("Memory leak detected!\n", .{});
+            `@panic`("Memory leak in logging test");
+        }
+    }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/logging_test.zig` around lines 21 - 23, Update the four
GeneralPurposeAllocator cleanup blocks in the tests of logging_test.zig to
retain the result of gpa.deinit(), check whether it equals .leak, and panic or
otherwise fail the test on a leak, matching the established pattern in
server_init_test.zig. Replace each discarded `_ = gpa.deinit()` while preserving
the existing allocator setup and deferred cleanup.

Source: Coding guidelines

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/storage_engine_error_test.zig`:
- Around line 113-116: Update runErr to assert that sth.readDoc returns a
non-null record for the committed row before deferring its deinitialization,
while preserving the existing cleanup behavior for the returned document.

In `@src/storage_engine_test.zig`:
- Around line 1218-1235: Update the thread-spawning logic around WriteThread.run
and ReadThread.run to track the number of successfully spawned threads and add
an errdefer cleanup that joins every spawned thread if a later spawn fails.
Apply the cleanup pattern to both write_threads and read_threads, ensuring
already-started workers finish before ctx.deinit() or error propagation occurs.
- Around line 1543-1548: In the test flow around readDoc and record2, add an
assertion using expectFieldInt after confirming record2 is non-null, passing
record2.?, test_table.metadata, "val2", and 42 so the test validates the stored
field value rather than only record existence.
- Around line 1469-1500: Update both the second-run EngineTestContext cleanup in
“storage: data persistence across restarts” and the corresponding “storage:
schema update integrity” test to use deinitNoCleanup() instead of deinit(),
preserving the outer TestContext cleanup as the owner of test-directory
deletion.

---

Outside diff comments:
In `@src/storage_engine_error_test.zig`:
- Around line 130-145: Update the test “storage: write/flush/read round-trip
with empty value” to insert an empty string for the val field instead of
"value", then assert that the read record contains the expected empty value, not
merely that the record exists. Preserve the existing setup, flush, and cleanup
flow.

---

Duplicate comments:
In `@src/msgpack_utils_test.zig`:
- Line 412: Replace the fallback else branch in the payload switch within the
round-trip test with a failing assertion or test failure. Ensure unsupported
Payload variants, including nil, float, bin, ext, and arr, cannot pass without
decoded-value verification, while preserving the existing handling for int,
uint, bool, str, and map.

---

Nitpick comments:
In `@src/checkpoint_worker_test.zig`:
- Around line 319-479: Run the checkpoint-worker filtered Zig tests, or the full
zig build test suite if no filter is available, and resolve any failures in the
added tests. Then run bun run lint through zwanzig against the checkpoint test
module and address any reported issues.

In `@src/config/loader_test.zig`:
- Around line 239-752: Run the configuration-loader tests for loader_test.zig
using the module-specific filtered Zig test command, or run zig build test if
required, and resolve any failures. Then run the project lint command via
zwanzig (bun run lint) against this module and fix any reported issues.
- Around line 380-493: Extract a shared helper near the existing loader test
utilities, such as writeConfigWithSchema, to create the temporary config and
schema paths, write both contents, and return the allocated config path. Replace
the repeated path-joining and file-writing setup in the four validation tests
and the later file-existence and round-trip tests, preserving each test’s
existing config generation, cleanup, schema content, and ConfigLoader.load
behavior.

In `@src/logging_test.zig`:
- Around line 202-210: Update Test 3 in the logging test so it actually
exercises an error path and verifies that the logging handler, including
manager.onMessage, receives a message with error details; alternatively, revise
the Test 3 comment and enclosing test documentation to describe only the
null-record behavior and remove the claim that database errors are logged.
- Around line 21-23: Update the four GeneralPurposeAllocator cleanup blocks in
the tests of logging_test.zig to retain the result of gpa.deinit(), check
whether it equals .leak, and panic or otherwise fail the test on a leak,
matching the established pattern in server_init_test.zig. Replace each discarded
`_ = gpa.deinit()` while preserving the existing allocator setup and deferred
cleanup.

In `@src/migration_executor_test.zig`:
- Around line 411-432: Extract the duplicated PragmaRow definition and PRAGMA
table_info iteration from the affected tests into a shared columnType helper
near the test utilities. Have it prepare the table-info query, free every
non-returned row field centrally, return the declared type for the requested
column or null when absent, and update both test sites to assert through this
helper.
- Around line 401-409: Remove the redundant dupeZ calls in the SQL preparation
paths around prepareDynamic, specifically at the call sites near lines 295 and
387. Pass the allocPrint result directly to prepareDynamic, preserving the
existing allocation and cleanup behavior.

In `@src/msgpack_utils_test.zig`:
- Around line 80-85: Update the writeBe32 helper to use std.mem.writeInt for the
big-endian u32 store instead of manually shifting and assigning individual
bytes, preserving its existing buffer offset and value behavior.
- Around line 111-131: Remove the duplicate array32 and map32 bomb blocks using
count 100001 from the earlier test section, since the one-over-boundary cases in
the later test already cover that behavior. Keep the later cases unchanged, or
update these earlier cases to a clearly larger count such as 1_000_000 while
preserving their expected ArrayTooLarge and MapTooLarge errors.

In `@src/storage_engine_error_test.zig`:
- Around line 41-59: Rename the setupEngineWithOptions test directory argument
in “storage: write/flush/read round-trip on file-backed engine” from
“storage-error-readonly” to “storage-error-roundtrip” so it matches the test’s
round-trip behavior.

In `@src/storage_engine_stability_test.zig`:
- Around line 9-17: Update the property-test comment above the concurrent
operation test to remove claims about injected failures, error recovery,
retries, and cleanup after errors. Describe only the verified coverage:
concurrent mixed insert/read/delete operations complete without panics or
crashes, while operation errors are tolerated via the existing handling.

In `@src/storage_engine_test.zig`:
- Around line 1270-1271: Update the read loop around test_table.readDoc so it
passes allocator instead of testing.allocator, matching the allocator used by
the record deinit cleanup.
- Around line 1568-1590: Hoist the `ctx.table("items")` lookup out of the
`while` loop in this test, placing it alongside `items_index` before the loop.
Reuse the resulting `test_table` in the query branch while preserving the
existing `readDoc` behavior.
- Around line 1139-1160: Remove the duplicate database-file creation test,
keeping a single test as the owner of this contract. Prefer retaining the
existing coverage in the earlier test and delete the manual setup test
identified by “storage: engine init creates database file,” including its setup
and file assertion.
- Line 1353: Rename the test at src/storage_engine_test.zig lines 1353-1353 from
“storage: transaction isolation and consistency” to a batch-consistency name
such as “storage: batched writes commit consistently”; rename the test at lines
1403-1403 from “storage: concurrent batch processing” to a sequential
multi-batch name such as “storage: multi-batch writes all persist”, without
changing their test bodies.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: a4f769b8-9c29-42bd-af10-5bf8725bca3c

📥 Commits

Reviewing files that changed from the base of the PR and between 92b6613 and fbadb69.

📒 Files selected for processing (24)
  • scripts/unused_pub_detector.js
  • src/checkpoint_worker_property_test.zig
  • src/checkpoint_worker_test.zig
  • src/config/loader_property_test.zig
  • src/config/loader_test.zig
  • src/logging_property_test.zig
  • src/logging_test.zig
  • src/message_handler_property_test.zig
  • src/message_handler_test.zig
  • src/migration_detector_property_test.zig
  • src/migration_detector_test.zig
  • src/migration_executor_property_test.zig
  • src/migration_executor_test.zig
  • src/msgpack_utils_property_test.zig
  • src/msgpack_utils_test.zig
  • src/server_init_test.zig
  • src/storage_engine_error_test.zig
  • src/storage_engine_property_test.zig
  • src/storage_engine_stability_test.zig
  • src/storage_engine_test.zig
  • src/test_all.zig
  • src/uwebsockets_wrapper_property_test.zig
  • src/uwebsockets_wrapper_test.zig
  • tests/e2e/src/harness.ts
💤 Files with no reviewable changes (10)
  • src/config/loader_property_test.zig
  • src/msgpack_utils_property_test.zig
  • src/uwebsockets_wrapper_property_test.zig
  • src/message_handler_property_test.zig
  • src/storage_engine_property_test.zig
  • src/migration_executor_property_test.zig
  • src/logging_property_test.zig
  • src/checkpoint_worker_property_test.zig
  • src/migration_detector_property_test.zig
  • tests/e2e/src/harness.ts

Comment thread src/storage_engine_error_test.zig
Comment thread src/storage_engine_test.zig
Comment thread src/storage_engine_test.zig
Comment thread src/storage_engine_test.zig

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (3)
src/config/loader_test.zig (3)

734-755: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Assert every field in the complete fixture.

The fixture sets jwt_issuer, jwt_audience, max_messages_per_second, max_connections, and max_message_size. The assertions do not check these fields. Add assertions for all five values.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/config/loader_test.zig` around lines 734 - 755, Add assertions in the
complete-fixture verification block after the existing authentication, security,
and performance checks for the fixture’s jwt_issuer, jwt_audience,
max_messages_per_second, max_connections, and max_message_size fields. Compare
each field against its configured fixture value, preserving the existing
assertion style and coverage of all other fields.

263-273: 🩺 Stability & Availability | 🟡 Minor | ⚡ Quick win

Restore pre-existing environment variables.

The deferred cleanup always calls unsetenv. If the test process already contains one of these variables, the test removes it for later tests. The same issue affects NONEXISTENT_VAR at Line 319.

Save each previous value and restore it after the test instead of always unsetting it.

Also applies to: 318-319, 354-362

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/config/loader_test.zig` around lines 263 - 273, Update the environment
setup and cleanup in the test containing TEST_PORT, TEST_HOST, TEST_JWT_SECRET,
and TEST_DATA_DIR to capture each variable’s pre-test value and restore it
afterward, unsetting only variables that were previously absent. Apply the same
preservation logic to NONEXISTENT_VAR and the variables in the cleanup block
around lines 354-362, using the existing test cleanup flow.

617-620: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Rename the tests and invariant to describe load-only coverage.

The three config: round-trip tests each call ConfigLoader.load once. The repository has no Config serializer, so these tests do not exercise serialization followed by parsing.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/config/loader_test.zig` around lines 617 - 620, Rename the three `config:
round-trip` tests in loader_test.zig to describe `ConfigLoader.load`-only
coverage, and update the nearby “Configuration round-trip” invariant to state
that loading valid configuration produces the expected equivalent configuration.
Remove serialization/parsing wording while preserving the existing test
behavior.
🧹 Nitpick comments (1)
src/config/loader_test.zig (1)

14-14: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Rename the helper to snake_case.

writeConfigWithSchema uses camelCase. Rename it to write_config_with_schema and update all seven call sites.

Proposed rename
-fn writeConfigWithSchema(
+fn write_config_with_schema(

-    const temp_file_path = try writeConfigWithSchema(
+    const temp_file_path = try write_config_with_schema(

As per coding guidelines, functions and variables in src/**/*.zig must use snake_case.

Also applies to: 419-419, 445-445, 471-471, 497-497, 640-640, 671-671, 728-728

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/config/loader_test.zig` at line 14, Rename the helper function
writeConfigWithSchema to write_config_with_schema in loader_test.zig, and update
all seven call sites to use the new snake_case name.

Source: Coding guidelines

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@src/config/loader_test.zig`:
- Around line 734-755: Add assertions in the complete-fixture verification block
after the existing authentication, security, and performance checks for the
fixture’s jwt_issuer, jwt_audience, max_messages_per_second, max_connections,
and max_message_size fields. Compare each field against its configured fixture
value, preserving the existing assertion style and coverage of all other fields.
- Around line 263-273: Update the environment setup and cleanup in the test
containing TEST_PORT, TEST_HOST, TEST_JWT_SECRET, and TEST_DATA_DIR to capture
each variable’s pre-test value and restore it afterward, unsetting only
variables that were previously absent. Apply the same preservation logic to
NONEXISTENT_VAR and the variables in the cleanup block around lines 354-362,
using the existing test cleanup flow.
- Around line 617-620: Rename the three `config: round-trip` tests in
loader_test.zig to describe `ConfigLoader.load`-only coverage, and update the
nearby “Configuration round-trip” invariant to state that loading valid
configuration produces the expected equivalent configuration. Remove
serialization/parsing wording while preserving the existing test behavior.

---

Nitpick comments:
In `@src/config/loader_test.zig`:
- Line 14: Rename the helper function writeConfigWithSchema to
write_config_with_schema in loader_test.zig, and update all seven call sites to
use the new snake_case name.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 4c7ee92e-7b8f-4d47-97f2-89b6cabbd523

📥 Commits

Reviewing files that changed from the base of the PR and between fbadb69 and 6805a29.

📒 Files selected for processing (8)
  • src/config/loader_test.zig
  • src/logging_test.zig
  • src/migration_executor_test.zig
  • src/msgpack_utils_test.zig
  • src/storage_engine_error_test.zig
  • src/storage_engine_stability_test.zig
  • src/storage_engine_test.zig
  • src/test_all.zig
🚧 Files skipped from review as they are similar to previous changes (7)
  • src/storage_engine_stability_test.zig
  • src/test_all.zig
  • src/msgpack_utils_test.zig
  • src/storage_engine_error_test.zig
  • src/logging_test.zig
  • src/migration_executor_test.zig
  • src/storage_engine_test.zig

@coderabbitai

coderabbitai Bot commented Aug 2, 2026

Copy link
Copy Markdown

@mstdokumaci Automatic reviews are resumed.

✅ Action performed

Reviews resumed.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/config/loader_test.zig (1)

553-566: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Use a test-owned absent schema path. Build the path under context.test_dir, assert that it returns error.FileNotFound, and use it in the config and expectations.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/config/loader_test.zig` around lines 553 - 566, Update the test around
ConfigLoader.load to construct the missing schema path beneath context.test_dir
instead of using the hard-coded absolute path. Use that test-owned path in the
config content and expected schema_file value, and assert that loading returns
error.FileNotFound rather than expecting a successful config with null
schema_content.
🧹 Nitpick comments (2)
src/config/loader_test.zig (2)

14-25: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Rename the helper to snake_case.

Rename writeConfigWithSchema to write_config_with_schema. Update its call sites.

As per coding guidelines, src/**/*.zig requires snake_case for functions and variables.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/config/loader_test.zig` around lines 14 - 25, Rename the helper function
writeConfigWithSchema to write_config_with_schema in src/config/loader_test.zig,
and update every call site to use the new snake_case name.

Source: Coding guidelines


441-465: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Remove duplicate validation cases.

Each new test repeats an existing configuration and error assertion. It adds no coverage.

  • src/config/loader_test.zig#L441-L465: Remove this case or change it to a distinct port boundary. Lines 75-94 already test port 70000 and error.InvalidPort.
  • src/config/loader_test.zig#L493-L517: Remove this case or change it to a distinct buffer boundary. Lines 96-115 already test messageBufferSize: 0 and error.InvalidBufferSize.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/config/loader_test.zig` around lines 441 - 465, Remove the duplicate
invalid-port test at src/config/loader_test.zig:441-465, since the existing test
already covers port 70000 with error.InvalidPort. Also remove the duplicate
invalid-buffer test at src/config/loader_test.zig:493-517, or change it to
exercise a distinct buffer-size boundary while preserving the expected error
assertion.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/config/loader_test.zig`:
- Around line 267-271: Update the test setup around TestContext initialization
so the context is created before setting TEST_DATA_DIR, and derive TEST_DATA_DIR
from context.test_dir instead of the shared /tmp/test-isolated-dir path.
Preserve the existing environment setup and ensure ConfigLoader.load creates
data only within the context-managed test directory.
- Around line 264-292: In the environment-isolation setup and cleanup blocks,
immediately duplicate each getenv result into allocator-owned storage before any
subsequent getenv, setenv, or unsetenv call, then restore and free those copies
during deferred cleanup. Apply this to src/config/loader_test.zig lines 264-292,
339-345, and 381-402; update the affected test cleanup logic while preserving
restoration of the original unset/present state.

---

Outside diff comments:
In `@src/config/loader_test.zig`:
- Around line 553-566: Update the test around ConfigLoader.load to construct the
missing schema path beneath context.test_dir instead of using the hard-coded
absolute path. Use that test-owned path in the config content and expected
schema_file value, and assert that loading returns error.FileNotFound rather
than expecting a successful config with null schema_content.

---

Nitpick comments:
In `@src/config/loader_test.zig`:
- Around line 14-25: Rename the helper function writeConfigWithSchema to
write_config_with_schema in src/config/loader_test.zig, and update every call
site to use the new snake_case name.
- Around line 441-465: Remove the duplicate invalid-port test at
src/config/loader_test.zig:441-465, since the existing test already covers port
70000 with error.InvalidPort. Also remove the duplicate invalid-buffer test at
src/config/loader_test.zig:493-517, or change it to exercise a distinct
buffer-size boundary while preserving the expected error assertion.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 657f0ae6-e6b2-4bc3-a5d2-84da5f13e057

📥 Commits

Reviewing files that changed from the base of the PR and between 6805a29 and 546d536.

📒 Files selected for processing (2)
  • src/config/loader_test.zig
  • src/storage_engine/read_worker_perf_test.zig
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/storage_engine/read_worker_perf_test.zig

Comment thread src/config/loader_test.zig Outdated
Comment thread src/config/loader_test.zig Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (2)
src/config/loader_test.zig (2)

688-768: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Cover the remaining configuration fields in the complete test.

The configuration model includes security.violation_threshold and performance.statement_cache_size, but this test neither sets nor checks them. Add non-default violationThreshold and statementCacheSize values, then assert the parsed fields.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/config/loader_test.zig` around lines 688 - 768, The “config: load -
complete config” test is missing coverage for security.violation_threshold and
performance.statement_cache_size. Add non-default violationThreshold and
statementCacheSize entries to config_content, then assert the corresponding
config.security.violation_threshold and config.performance.statement_cache_size
values after loading.

28-32: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Rename dupeEnvZ to dupe_env_z.

dupeEnvZ is a function in src/**/*.zig. Rename it to snake_case and update its call sites.

As per coding guidelines, src/**/*.zig: Follow standard Zig naming conventions: CamelCase for types and snake_case for functions and variables.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/config/loader_test.zig` around lines 28 - 32, Rename the function
dupeEnvZ to dupe_env_z in loader_test.zig and update every call site in
src/**/*.zig to use the new snake_case name, preserving its behavior and
signature.

Source: Coding guidelines

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/config/loader_test.zig`:
- Around line 282-287: In the test setup, ensure environment restoration is
registered before any TEST_PORT, TEST_HOST, or TEST_JWT_SECRET mutations can
occur. Move the test_data_dir_z allocation ahead of the setenv calls or
establish the restoration defer first, while preserving the existing allocator
cleanup and restoring all modified variables if allocation fails.

---

Nitpick comments:
In `@src/config/loader_test.zig`:
- Around line 688-768: The “config: load - complete config” test is missing
coverage for security.violation_threshold and performance.statement_cache_size.
Add non-default violationThreshold and statementCacheSize entries to
config_content, then assert the corresponding
config.security.violation_threshold and config.performance.statement_cache_size
values after loading.
- Around line 28-32: Rename the function dupeEnvZ to dupe_env_z in
loader_test.zig and update every call site in src/**/*.zig to use the new
snake_case name, preserving its behavior and signature.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 8cdba726-7d36-4401-aedc-b218509ac5fb

📥 Commits

Reviewing files that changed from the base of the PR and between 546d536 and a110f0d.

📒 Files selected for processing (1)
  • src/config/loader_test.zig

Comment thread src/config/loader_test.zig Outdated
@mstdokumaci
mstdokumaci merged commit 387a570 into main Aug 2, 2026
8 checks passed
@mstdokumaci
mstdokumaci deleted the organize-tests branch August 2, 2026 12:55
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.

1 participant