The PostgreSQL 17 cap tests expect the managed-conf behavior: the old value in darling-managed.conf is capped, and an operator's out-of-range line refuses the start - #4463
Merged
Conversation
The gated PostgreSQL 17 maintenance_work_mem cap test simulated a pre-#3909 build by appending a bare, unmarked line to postgresql.conf after the store's conf had already migrated to the one included darling-managed.conf file (#4336). No build of this service has ever written that setting bare; every write (v3, v7, v8, v14) carries its own marker. So the appended line was, by the migration classifier's own rule, an operator's line below the include -- and the product now correctly refuses to start on it rather than silently absorb it. Two gated facts replace the one: - Postgres17Store_WithTheOldValueInItsManagedConf_StartsWithTheCap_Gated puts the old, uncapped value directly into darling-managed.conf (the shape the file can carry) and asserts the second start comes up with the value capped, exactly one assignment in the managed file, and no maintenance_work_mem line in postgresql.conf itself. - Postgres17Store_OperatorLineBelowIncludeOutOfRange_RefusesToStartNamingTheFix_Gated appends the bare operator line below the include and asserts the second start throws, naming the setting and the fix, and never leaves the store running.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
Postgres17Store_WithTheOldCapInItsConf_StartsThroughTheBootstrap_Gatedsimulated "a build before #3909" byappending a bare, unmarked
maintenance_work_mem = 2048MBline topostgresql.confafter the firstEnsureRunningAsync()call. That first call already migrates the store's conf to the one includeddarling-managed.conffile, so the appended line landed below the include -- the exact position anoperator's own line occupies, per the migration classifier's own rule.
History confirms this: every write of
maintenance_work_memthis service has ever made carries its ownmarker, never a bare line.
History: how maintenance_work_mem was written
16cca99342026-07-09, "Darling managed Postgres: derive a memory-tuning conf block from host RAM" --inside marker v3 (
BuildMemorySizingConfAppend).f4c86ffa32026-07-27, "Raise managed store maintenance_work_mem to the measured compression floor(maintenance_work_mem formula lands too low for compression throughput: +70% measured from raising it, plateaus by 1.5 GB #1777)" -- inside marker v7 (the compression-memory override).
922caa68d2026-07-27, "Record the incremental-allocation constraint the small-host landings rest on(maintenance_work_mem formula lands too low for compression throughput: +70% measured from raising it, plateaus by 1.5 GB #1777)" -- comment-only, no write.
714af66f82026-09-03, "Re-derive managed-store Postgres sizing when the host changes (Fixes Managed-store memory sizing never re-derives after a host resize (effective_cache_size stale at 75% of the OLD RAM) #2845)" --inside marker v8 (
BuildHardwareSizingConfAppend).f04174522026-09-03, "Review: v8 must not act on a non-authoritative RAM reading" -- guards v8's ownappend, no new write.
e507aa2d12026-09-22, "A store still on PostgreSQL 17 no longer fails to start on a 40 GB+ host (Managed store writes maintenance_work_mem = 2048MB, one kB over PostgreSQL 17's Windows maximum: a 17.x store on a 40 GB+ host cannot restart #3909)(A store still on PostgreSQL 17 no longer fails to start on a 40 GB+ host (#3909) #3917)" -- inside marker v14 (
BuildLegacyMaintenanceWorkMemCapConfAppend), the cap block itself.1ae41290a/6dbb22a502026-09-26 (Managed store sizing: make the derivation platform-aware (Windows 487 cap only on Windows, Linux cgroup limits, commit headroom) and write it to one service-owned config file instead of appended blocks #4215/Move the managed store's settings into one included file, darling-managed.conf (#4215) #4336), "Move the managed store's settings into one includedfile, darling-managed.conf" -- confines the v14 heal to a
Legacyconf and moves the setting into therendered
darling-managed.conf; no bare write introduced.12893bc52026-09-26, "A carried maintenance_work_mem is capped for PostgreSQL 17 and earlier when the managedsettings move (A carried maintenance_work_mem is capped for PostgreSQL 17 and earlier when the managed settings move (#4336) #4444)" -- the one-time migration (
ManagedConfMigrationRunner.RunStepA) caps a carried value as itwrites it into the rendered
darling-managed.conf; no bare write topostgresql.conf.88e69c88/421c57cc2026-09-25 (Store host visibility: a cross-platform host profile, a --check-settings verb, and a get_store_host read, so "is this store sized right" has an answer without shell access #4214), the store host profile and--check-settings-- compare the store'slive setting with the value derived for the host; no write.
7b19082d2026-09-18,cbb00d9a/6d629ace2026-09-20 -- the PostgreSQL-target analysis reads a monitoredserver's own settings (
PgTarget*); it never writes the store's conf.maintenance_work_memin service code (DarlingStoreHostProfile.cs,ManagedConfMigration.cs,ManagedConfMigrationRunner.cs) is a reader/classifier/advisory, not apostgresql.confwrite.No commit ever wrote
maintenance_work_membare below the include. The test's setup line was never a shapethis product produces -- confirming this is a stale test (S), not a product defect.
What changes
Test-only, in
Darling/Darling.Tests/DarlingManagedPostgresTests.cs. No product code changed.Postgres17Store_WithTheOldCapInItsConf_StartsThroughTheBootstrap_Gatedis renamed and reworked toPostgres17Store_WithTheOldValueInItsManagedConf_StartsWithTheCap_Gated: after the first start, itreplaces the one
maintenance_work_memassignment inside the rendereddarling-managed.confwith theold, uncapped
2048MB-- the shape the managed file itself can carry -- then recomputes the header's# body-sha256=line over the edited body, the same way the product's own write path would, so the filestill reads as the product's own render (
ManagedConfFile.IsHandEditedis asserted false on it) ratherthan an operator hand edit. A hand edit is never overwritten and would only ever reach the last-good
fallback in
EnsureManagedConfReadyAsync, never the re-render this fact means to pin. It then assertsthe second start:
second.LastManagedConfWriteResultshowsWritten: true, HandEdited: false, andsecond.LastStartUsedLastGoodManagedConfis false;maintenance_work_memassignment indarling-managed.conf, and it isn't the old2048MB;or under the 2047 MB cap.
The rendered value depends on the host's RAM. The first test-only run on this branch expected the cap
itself and failed on a CI runner whose RAM renders 1536 MB, under the cap, so the cap never engaged. The
product has no seam to pin the RAM input, and adding one would be a product change, so the fact now
asserts the host's own render instead.
ManagedConfFileTestspins the cap arithmetic for any RAM without aserver.
postgresql.confcarrying the include and nomaintenance_work_memline of its own.New fact
Postgres17Store_OperatorLineBelowIncludeOutOfRange_RefusesToStartNamingTheFix_Gated: appendsa bare, out-of-range line below the include (the honest shape of an operator edit) and asserts the second
start throws
InvalidOperationExceptionnamingmaintenance_work_memand the fix instruction fromBuildManagedConfValidationFailureMessage, then that the store is not left running (stop is a safeno-op, and a connection attempt fails). Its doc comment no longer claims this data directory has never
had a last-good file -- the first start above already succeeded, so it saved one
(
DarlingManagedPostgres.SaveLastGoodManagedConf), and the test now asserts that file exists before thesecond start. The fallback is tried and still refused, because the rejected line lives in
postgresql.confbelow the include, not indarling-managed.conf: restoring the last-good managed fileleaves the operator's own line in place untouched.
Both facts stay gated on
DARLING_TEST_PGRUNTIME_OLD, Windows, andpg_ctl.exepresent, same as before.Both facts read conf lines as ACTIVE assignments through the product's own parser (
DarlingManagedPostgres.ParseConfText, via a smallActiveValueshelper), never as raw substrings: initdb writes commented sample lines such as#maintenance_work_mem = 64MBintopostgresql.conf, and a substring check on the key name matches them. The non-gated factActiveValues_SkipsInitdbsCommentedSampleLines_AndCountsAnOperatorLinepins that with lines copied from PostgreSQL 17'spostgresql.conf.sample.Gated tests that must pass
These run only on a test-only
nightly.ymlrun (publish=false); PR CI doesn't run them.Postgres17Store_WithTheOldValueInItsManagedConf_StartsWithTheCap_GatedPostgres17Store_OperatorLineBelowIncludeOutOfRange_RefusesToStartNamingTheFix_GatedPostgres17StoreWithTheOldCap_StartsAfterTheHeal_Gated(unchanged; must stay green)Test plan
dotnet build Darling/Darling.Tests/Darling.Tests.csproj -c Release -p:EnableWindowsTargeting=true: 0warnings, 0 errors.
dotnet build Lite.Tests/Lite.Tests.csproj -p:EnableWindowsTargeting=true: 0 warnings, 0 errors.DarlingManagedPostgresTests, noDARLING_TEST_PGRUNTIME_OLDset): both newgated facts SKIP for the expected reason; 181 total, 5 failed -- all five are pre-existing macOS
path-separator failures unrelated to this change (
ResolveDataDirectory_TrimsATrailingSeparator,PathConventions_DefaultDataDirectory_AndCredentialBesideIt,RoleCredentialPaths_BesideTheDataDirectory,McpCredentialPath_BesideTheDataDirectory_AndDistinctFile,EnsureConfAppended_ThreeExistingV8Blocks_CollapseToOneOnTheNextHeal), none in the file this PR touches.DocCommentHygieneTests: 77/77 green.devcover fact 1's cap from two different angles, and are namedhere (not added new) for what each one actually pins:
ManagedConfFileTests.RenderBody_CarriesEveryManagedConfMarkersOwnedKeys(its class summary, ~line 387)pins the RENDER itself:
DeriveMemorySettings's formula capsmaintenance_work_mematMaintenanceWorkMemCapMbfor ANY RAM size a fresh render can derive -- this is the per-start renderfact 1 exercises through the product's own bootstrap.
ManagedConfMigrationRunnerTests.RunStepA_CarriedMaintenanceWorkMemOver2047_Postgres17_Capspins theone-time Move the managed store's settings into one included file, darling-managed.conf (#4215) #4336 Step A migration's carry-over instead: a pre-existing, over-limit value already on disk
from before the render's own cap existed, capped once when Step A runs.
Both ran green (33/33 in
ManagedConfFileTests; the Step A class also green).expected reason (no
DARLING_TEST_PGRUNTIME_OLDset); they are named above for the nightly workflowrun to confirm.
Total
DarlingManagedPostgresTests: Total: 181, Errors: 0, Failed: 5, Skipped: 10, Not Run: 0 (the 5 failuresare the same pre-existing macOS path-separator failures listed above, unrelated to this change and present
identically with this change reverted).
ManagedConfFileTests: Total: 33, Errors: 0, Failed: 0, Skipped: 0, Not Run: 0.DocCommentHygieneTests: Total: 77, Errors: 0, Failed: 0, Skipped: 0, Not Run: 0.CHANGELOG entry
None: a test-only change. The product's managed-conf behavior on PostgreSQL 17 was already correct; only the test's out-of-date expectation changes.
Refs
Refs #4336 (the commit that moved settings into darling-managed.conf and made the old test's setup line an
operator line), #3909 (why the cap exists at all), #4405 (lines below the include are the operator's; across a major upgrade they are carried and probed), #4444 (a different, unrelated fix that this
PR does not touch or depend on).