Cover the snapshot_now engine gate behaviorally — the last of #2230's three - #2261
Conversation
… three The third dispatch loop, and the one that got neither engine gate in #2213's first round. Its regression is phantom SUCCESS rather than a crash: dispatched SQL Server collectors early-return in their own AppliesTo, yield zero rows, and RunOneAsync then writes SUCCESS to collection_log — so one operator snapshot against a PostgreSQL target produced ~40 rows saying collection worked. Neither of the tricks the other two gates needed applies here, and neither is required: the loop reports collectorsRun in its outcome JSON, and every run it makes writes itself to collection_log, so the gate's effect is a count and a set of rows. Schedule overrides disable everything except wait_stats — SQL-Server-only, and dispatched through the same loop — so the two arms differ in the ENGINE and nothing else: same collector, same overrides, same store, one dispatch decision instead of 49. - PostgreSQL target: collectorsRun is 0 and collection_log is EMPTY. Asserting absence rather than "not SUCCESS" is deliberate — a gate that dispatched and then failed would also avoid SUCCESS while having connected to a PostgreSQL host as SQL Server. - SQL Server target, same overrides: collectorsRun is 1 and the wait_stats row is there. Without this arm the gate assertion passes just as well against a snapshot that stopped dispatching anything, since "ran zero collectors" is also what a broken loop reports. Real DarlingCollectorRunner, not a stand-in: a fake would have to reimplement the dispatch the test exists to observe. Unresolvable hosts with a one-second connect timeout so the dispatched collector fails immediately; the status is not asserted, only that it was dispatched at all. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
Reviewed. This is a test-only change (Darling.Tests), adding the third of the three
Lite/Darling parity: not applicable here — Lite only ever monitors SQL Server targets (no Security: no concerns — parameterized queries throughout ( One minor, non-blocking note left as an inline comment on the SQL Server arm's connection string (DNS-dependent No other findings. |
…tname Review suggestion, and it is the better shape. The connection now goes to 127.0.0.1 port 1 — connection-refused from a loopback port with no listener, which is what ViewerControlPlaneStage3bTests and the MCP DeadStore constants already use. A .invalid name made the timing a property of CI's resolver, which is not something this test should be measuring. The IDENTITY host stays the synthetic .invalid name, because that is what the server_id lookup and the collection_log rows key on and it must not collide with a real server. The two were conflated before; they are now separate on purpose, and the doc says why. SQL auth rather than integrated on the SQL Server arm: the failure under test is the connect, and integrated auth on a Linux runner fails for a platform reason instead — a different thing to be asserting on. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
Taken in The thing worth naming is that the two hosts had been conflated. Identity must stay the synthetic Also switched the SQL Server arm off integrated auth to SQL auth: the failure under test is the connect, and integrated auth on a Linux runner fails for a platform reason instead — same red, different cause, and asserting on it would have been asserting on the wrong thing. Re-running CI. For the record, the previous run did execute both tests rather than skipping them — |
|
Reviewed. This is a test-only change ( Correctness — verified against the current dispatch path, not just the PR's own claims:
Parity: Lite has no multi-engine dispatch (grep shows a single incidental Security: synthetic No bugs, parity drift, or security issues found. Nothing blocking. |
Closes #2230.
The third dispatch loop, and the one that got neither engine gate in #2213's first round. #2237 covered
analyze_now, #2245 covered the reconcile early-return; this issnapshot_now.The regression is phantom SUCCESS, not a crash
Dispatched SQL Server collectors do not fail loudly against a PostgreSQL target — their own
AppliesToearly-returns, yields zero rows, andRunOneAsyncthen writes SUCCESS tocollection_log. One operator snapshot produced ~40 rows saying collection worked, on an engine where those collectors cannot mean anything. That reads as health, which is strictly worse than an error.Neither of the other two tricks was needed
analyze_nowasserts a presence inanalysis_state; the reconcile gate exploits a public precondition that throws when ungated.snapshot_nowneeds neither: the loop reportscollectorsRunin its outcome JSON, and every run it makes writes itself tocollection_log. The gate's effect is a count and a set of rows.One collector, two engines
Schedule overrides disable everything except
wait_stats— SQL-Server-only, dispatched through the same loop — so the two arms differ in the engine and nothing else: same collector, same overrides, same store. One dispatch decision instead of 49, which also makes the SQL Server arm cheap enough to be the non-vacuity proof rather than a second slow test. The overrides go through the shippedStoreConfigProvider.ResolveSchedule, which the loop consults, rather than reaching past it.collectorsRuncollection_logwait_statsWhy absence rather than "not SUCCESS": a gate that dispatched and then failed would also avoid SUCCESS, while having connected to a PostgreSQL host as SQL Server. The row must not exist at all.
Why the SQL Server arm is load-bearing: without it, the gate assertion passes just as well against a snapshot that stopped dispatching anything for some unrelated reason — "ran zero collectors" is also what a broken loop reports.
Notes
DarlingCollectorRunner, not a stand-in: a fake would have to reimplement the dispatch the test exists to observe, and thecollection_logwrite that carries the assertion happens inside the real path..invalid) with a one-second connect timeout, so the dispatched collector fails immediately. The status is not asserted — whether the attempt lands ERROR or a zero-row SUCCESS depends on how far it gets before the connection dies, and the fact under test is that it was dispatched at all.server_idwould make that depend on test ordering.LiveStoreCleanupon its own connection, per The other ~124 live-test finally blocks still clean up on the body's connection, so a failing test can still report its teardown's error #1902.Live-store gated on
DARLING_TEST_PG, which the "Darling PostgreSQL tests" job sets. Test-only — no production code touched. Builds clean (0 warnings) with-p:EnableWindowsTargeting=true; I cannot runnet10.0-windowsxunit locally, so CI is the only place the pass is observable — watching it there rather than claiming it here.🤖 Generated with Claude Code