tests: pin pooled-dispatch concurrency; sqlite pins follow THREADSAFE=1

server_http gains the case that caught the live crash: 1000 keep-alive
requests at c=10 against /api/apps (full SQLite load per request, on
the 4-worker pool) must complete with 0 failures and leave the server
answering. sqlite_api's threadsafe pins flip to guard the NEW invariant
— a regression to THREADSAFE=0 reintroduces heap corruption under the
pool (free-of-unallocated inside yy_reduce, caught under ab -c20).
This commit is contained in:
agra
2026-06-12 22:46:12 +03:00
parent 74b41f5c83
commit c734f47952
2 changed files with 17 additions and 4 deletions

View File

@@ -206,6 +206,18 @@ main :: () -> i32 {
"two requests on one connection both answer");
print(" keep-alive reuse ok\n");
// ── concurrent load must not corrupt anything (PLAN-HTTPZ A2) ────
// distd handlers run on a 4-worker pool; /api/apps does a full
// SQLite load per request. 1000 keep-alive requests at c=10 caught
// the SQLITE_THREADSAFE=0 heap corruption live — this pins the
// threadsafe build and the pooled dispatch path end to end.
abr := process.run(concat(concat("ab -q -n 1000 -c 10 -k ", BASE), "/api/apps 2>/dev/null | grep -c 'Failed requests: 0'"));
process.assert(abr != null and abr!.exit_code == 0, "ab spawn failed (concurrency case)");
process.assert(contains(abr!.stdout, "1"), "1000 concurrent requests complete with 0 failures");
alive := process.run(concat(concat("curl -s -m 2 -o /dev/null -w '%{http_code}' ", BASE), "/healthz"));
process.assert(alive != null and alive!.stdout == "200", "server alive after concurrent load");
print(" pooled handlers: 1000 concurrent requests, 0 failures, server alive\n");
// ── freshness: publish B while the server runs ────────────────────
rb := process.run(publish_cmd(path_join(MDIR, "b.json")));
process.assert(rb != null and rb!.exit_code == 0, "publish B must exit 0");