File Changes for braney
switch to commits view, user indexv504_preview2 to v504_base (2026-09-14 to 2026-09-21) v504
Show details
- src/hg/cgilib/tests/bedItemRgbTester.c
- lines changed 3, context: html, text, full: html, text
c80f2909a9df53021fb01b455b122414ad73c961 Sun Sep 20 06:51:14 2026 -0700
move bedItemRgbTester to hg/cgilib/tests, beside the code it tests
I said in the last commit that hg/cgilib had no tests directory. It does, and
I should have looked rather than inferred. bedCart.c lives in hg/cgilib, so
its test belongs there, and the header comment saying otherwise is fixed.
Worth knowing about that directory: its test target ran nothing. annoGratorTest
is commented out because it needs assemblies and tables the directory cannot
assume, so `make test` there printed "tested all" and did no work -- and
hg/makefile has been running it all along through TEST_EXTRA. bedItemRgbTest
is now the one test it does run.
refs #36212, refs #38391
- src/hg/cgilib/tests/expected/bedItemRgbTest
- lines changed 0, context: html, text, full: html, text
c80f2909a9df53021fb01b455b122414ad73c961 Sun Sep 20 06:51:14 2026 -0700
move bedItemRgbTester to hg/cgilib/tests, beside the code it tests
I said in the last commit that hg/cgilib had no tests directory. It does, and
I should have looked rather than inferred. bedCart.c lives in hg/cgilib, so
its test belongs there, and the header comment saying otherwise is fixed.
Worth knowing about that directory: its test target ran nothing. annoGratorTest
is commented out because it needs assemblies and tables the directory cannot
assume, so `make test` there printed "tested all" and did no work -- and
hg/makefile has been running it all along through TEST_EXTRA. bedItemRgbTest
is now the one test it does run.
refs #36212, refs #38391
- src/hg/cgilib/tests/makefile
- lines changed 15, context: html, text, full: html, text
c80f2909a9df53021fb01b455b122414ad73c961 Sun Sep 20 06:51:14 2026 -0700
move bedItemRgbTester to hg/cgilib/tests, beside the code it tests
I said in the last commit that hg/cgilib had no tests directory. It does, and
I should have looked rather than inferred. bedCart.c lives in hg/cgilib, so
its test belongs there, and the header comment saying otherwise is fixed.
Worth knowing about that directory: its test target ran nothing. annoGratorTest
is commented out because it needs assemblies and tables the directory cannot
assume, so `make test` there printed "tested all" and did no work -- and
hg/makefile has been running it all along through TEST_EXTRA. bedItemRgbTest
is now the one test it does run.
refs #36212, refs #38391
- src/hg/hgTablesTest/hgTablesTest.c
- lines changed 64, context: html, text, full: html, text
59b4888b34803576809588f0f6189d21e8cf6964 Mon Sep 14 15:56:07 2026 -0700
hgTablesTest: one unusable page should not end the whole run, refs #38356
testOneTrack called errAbort whenever hgTables returned a page it could not
parse, which ended the run there and then. quickSubmit has already recorded
that failure in tablesTestList by the time it returns NULL, so the abort was
not preserving information -- it was destroying it, because reportSummary
never ran and the Total line carrying the error counts was never written.
Every log back to v490 has zero Total lines for this reason.
Skip the track instead and keep going. The failure still counts as a hard
error in the summary, so a bad page is now reported rather than fatal. The
same applies to a track page with no main form or no table var, and to the
matching cases in testOneGroup. This subsumes the bigPsl exception added in
2016, and drops a sameString() on a trackDb type that would have crashed had
the lookup returned NULL.
quickSubmit logged the reason a page was unusable only at verbose level 2,
which the robot does not run at, so a failure reached the log as a bare
"Couldn't select track X" with the cause discarded. Log it at level 1. That
is what identified today's two failures as hgTables emitting truncated HTML
rather than anything to do with the tracks themselves.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
- lines changed 138, context: html, text, full: html, text
dcc88beac1cdad270235e85e456adafd5e201ceb Wed Sep 16 12:39:55 2026 -0700
hgTablesTest: catch an abort per test rather than losing the run, refs #38356
The guards added for #38356 covered the three ways a track page could come
back unusable. Fifteen other errAbort calls in this program were left, in the
output tests and in the per-database setup, and any one of them still ended the
run with no summary written.
lib/qa.c has done the right thing all along: qaPageGet and qaPageFromForm
bracket the fetch and the validation in an errCatch and hand back a qaStatus
carrying the message. That is why an unparseable page was already survivable.
The test never applied the same pattern to its own code, though it has included
errCatch.h all along.
So bracket each unit of work: one table, one track, one group, one database,
and each of the three uniProt tests that run at the end. Each body keeps its
code and moves behind a wrapper of the same name, so the diff is the wrapper
and nothing else. recordAbort turns a caught abort into a hard error in the
summary with the organism, database, group, track and table that produced it.
That step is needed because quickSubmit records how the page fetch went, and
nothing recorded what a test then made of a page it did get.
The three guards stay as they are. In those cases quickSubmit has already
recorded the failure, so restoring the errAbort and catching it again would
count one failure twice. The guards are the already-recorded path and the
errCatch is the not-recorded-anywhere path.
The exit code has to carry the same news. main returned zero whatever
happened, which was harmless while the first bad page aborted the process, and
is not harmless now that the run carries on: a caller reading only the exit
code would be told that a run failing on every track had succeeded. Return 1
when any test hit a hard error, or when no test ran at all. Soft errors do not
set it. There the page was read and the answer was wrong, which is a report
about hgTables rather than about this run, and it is still in the summary.
The root page fetch stays fatal. If the front page cannot be read there is
nothing to test.
- lines changed 2, context: html, text, full: html, text
9ec2018c4b216f3c3a8e846e638247d425736c03 Thu Sep 17 09:37:50 2026 -0700
hgTablesTest: end the caught-abort log lines with a newline, refs #38356
recordAbort's two log calls were the only ones in this file with no trailing
newline in the format string. Neither verbose nor fprintf adds one, and none
of the seventeen errAbort calls here end their own message with a newline
either, so errCatch->message->string does not supply the missing one. Every
caught abort ran into the next log line, on stderr and in the log file.
The counts, the exit code and the Total: line the robot greps are unaffected.
- lines changed 22, context: html, text, full: html, text
b14d44f6f6031286fde5318abf67086dd29a1b43 Fri Sep 18 09:52:30 2026 -0700
hgTablesTest: follow the redirect on the starting url instead of failing later
A url with no scheme is fetched over http, and both hgwdev and a sandbox
answer plain http with a 301 to https. The run parsed the redirect page,
found no form in it, and failed several steps later saying "Null form in
htmlPageSetVar", which named neither the url nor the redirect.
rootPageGet() now fetches through htmlPageForwarded(), says at verbose 1
when the url changed, and errAborts naming the code if the final status is
not 200. Every later request is built from this page, so this puts the
whole run on the url the server asked for, not just the first fetch.
The robots were never exposed to this: both doHgTablesTestRobot.csh and
preview2TablesTestRobot.csh already pass https urls.
refs #38356
- src/hg/hgTracks/chainTrack.c
- lines changed 57, context: html, text, full: html, text
e37f19d638c858f249b6b3e84586b6a2a3ca4487 Thu Sep 17 09:53:04 2026 -0700
hgTracks: color a lifted chain track by normScore, the way a native one is
lfFromLiftedChain set grayIx to maxShade and took the raw chain score, so a
quickLifted chain track asked to color by score drew every chain in the darkest
shade, and the dense mode sort by score ordered them differently from the native
track. chainLoadItems reads normScore out of the chain table and uses it for
both.
normScore is a column of the SQL chain table and is in no bigChain file, so only
the SQL side can do this, which is also the only side the native loaders do it
on. chainLoadRange throws the column away and struct chain has nowhere to keep
it, so chainNormScoreHash reads it separately, once per source range, and only
when the track is coloring by score. chainDbNormScoreAvailable only reads a
trackDb setting, so the column count is checked before the row is indexed.
Verified with a trackDb stanza lifting hg19 chainSelf onto hg38: the same 1846
items drew in 7 distinct colors before and 30 after. Note a hub cannot reach
this path, because chain is not a hub track type, so it takes a stanza of ours
carrying quickLiftUrl.
Found in the v504 code review, refs #38349.
refs #38249
- src/hg/hgTracks/hgTracks.h
- lines changed 4, context: html, text, full: html, text
4d36c5c0a9c01a918b9f54ee7e46d6373bfe89f3 Wed Sep 16 11:39:00 2026 -0700
hgTracks: a dense row can have one clickable map box per item, refs #38364
In dense the whole row is covered by a single map box that switches the
track to pack, so nothing inside a dense track points at a details page.
To look at an item you have to expand the track, which reloads the page
and changes the layout you just set up.
With denseClick on, genericDrawItemsFullDense puts down one map box per
item as it draws the row. It does this in the draw pass, where the scale
and x offset for the window are already in hand, so multi-region windows
come out right. The whole draw loop runs before the loop that calls
doTrackMap, and map items print in creation order, so the per-item boxes
come first in the image map and the existing whole-row box still catches
the gaps between items. Clicking empty space in the row, the center
label, or the right-click menu all still change the visibility. Nothing
had to be removed and the drawn image does not change.
A dense row can hold tens of thousands of items, so denseMapItem keeps
one flag per pixel of the row and skips an item whose pixels are all
claimed by an earlier one. Such a box sits under the earlier one and
could never be clicked. That bounds the row at one box per pixel: hg38
simpleRepeat in dense across chr1 at pix=1200 goes from 74,515 map boxes
and an 18.5 MB page to 969 boxes and 525 KB. It also decides what
happens when several items share a pixel, which is that the first one in
the list wins.
Three copies of the same early return, all commented "Don't bother if we
are imageV2 and a dense child", kept composite subtracks out of this.
They now test denseClickEnabled too, which is what lets the hg38
hprcPclai haplotypes work. The fourth copy in wigTrack.c puts down a
whole-track box rather than a per-item one and is left alone.
Off by default. Set denseClick in hg.conf for every dense track, or a
denseClick trackDb setting for one track, which inherits to a container's
subtracks. The trackDb setting is not documented yet.
- src/hg/hgTracks/simpleTracks.c
- lines changed 71, context: html, text, full: html, text
4d36c5c0a9c01a918b9f54ee7e46d6373bfe89f3 Wed Sep 16 11:39:00 2026 -0700
hgTracks: a dense row can have one clickable map box per item, refs #38364
In dense the whole row is covered by a single map box that switches the
track to pack, so nothing inside a dense track points at a details page.
To look at an item you have to expand the track, which reloads the page
and changes the layout you just set up.
With denseClick on, genericDrawItemsFullDense puts down one map box per
item as it draws the row. It does this in the draw pass, where the scale
and x offset for the window are already in hand, so multi-region windows
come out right. The whole draw loop runs before the loop that calls
doTrackMap, and map items print in creation order, so the per-item boxes
come first in the image map and the existing whole-row box still catches
the gaps between items. Clicking empty space in the row, the center
label, or the right-click menu all still change the visibility. Nothing
had to be removed and the drawn image does not change.
A dense row can hold tens of thousands of items, so denseMapItem keeps
one flag per pixel of the row and skips an item whose pixels are all
claimed by an earlier one. Such a box sits under the earlier one and
could never be clicked. That bounds the row at one box per pixel: hg38
simpleRepeat in dense across chr1 at pix=1200 goes from 74,515 map boxes
and an 18.5 MB page to 969 boxes and 525 KB. It also decides what
happens when several items share a pixel, which is that the first one in
the list wins.
Three copies of the same early return, all commented "Don't bother if we
are imageV2 and a dense child", kept composite subtracks out of this.
They now test denseClickEnabled too, which is what lets the hg38
hprcPclai haplotypes work. The fourth copy in wigTrack.c puts down a
whole-track box rather than a per-item one and is left alone.
Off by default. Set denseClick in hg.conf for every dense track, or a
denseClick trackDb setting for one track, which inherits to a container's
subtracks. The trackDb setting is not documented yet.
- lines changed 7, context: html, text, full: html, text
79b7c5730a04d92ca2d917d04752ae6711ff94c7 Thu Sep 17 12:54:22 2026 -0700
hgTracks: put the denseClick feature behind an hg.conf gate, refs #38364
The hg.conf denseClick flag was a tree-wide default that a trackDb
denseClick setting overrode per track. A track carrying denseClick on in
trackDb therefore turned the feature on wherever the code was installed,
and there was no way to hold it back from a machine. hprcPclai and
hprc2annot already carry that line.
Make the flag a gate instead. While it is off, which is the default, no
track gets clickable dense items whatever its trackDb says. With the gate
on, a track opts in for itself with the trackDb setting.
Inheritance is unchanged: trackDbSettingOn calls trackDbSetting, which
walks the parent chain, so one line on a composite still covers its
subtracks.
Measured on hg38 chr2:60,000,000-80,000,000 at pix=1200, with the seven
default-on hprcPclai haplotypes in dense. hprcPclai opts in and holds at
1249 hgc links with the gate on, 0 with it off. simpleRepeat, which does
not opt in, drops from 1024 hgc links to 0 with the gate on, which is the
behavior the gate exists to prevent.
- src/hg/hgc/hgc.c
- lines changed 5, context: html, text, full: html, text
9acfd5f32458e2f9853a48ab631c122523e66bc8 Thu Sep 17 09:52:46 2026 -0700
hgc: gate the alignment details page on both halves of the quickLift pair
quickLiftAliInfo returned early only when quickLiftDb was absent, so a stanza
carrying quickLiftDb and no quickLiftUrl still took the lift path. That left
quickLiftFile NULL, and the native branch of htcCdnaAli and htcCdnaAliInWindow
then resolved the table name against the assembly on screen while running the
query on the source assembly. Nothing unsafe happens, but the reader gets a
missing table error rather than an alignment.
Verified against a track with quickLiftDb hg19 and no quickLiftUrl, on a table
hg38 has and hg19 does not: before, the page ended in "Table
'hg19.altSeqLiftOverPslP11' doesn't exist"; after, the base alignment renders.
quickLiftIsLifted is the predicate the rest of the tree already uses for this,
which cec5ead0547 said was true everywhere and was not true here.
Found in the v504 code review, refs #38349.
refs #38249
- lines changed 14, context: html, text, full: html, text
8449e4fa9d013670193f6af7f416204f75f04a1e Thu Sep 17 09:52:53 2026 -0700
bigNet: say so when the type line names a chain track this assembly lacks
netChainTdb returns NULL when the chain track a bigNet's type line names is not
in trackHash, and the guard on the alignment section then dropped the whole
section without a word. A quickLifted net already explained itself in that
spot; a hub with a typo in its type line got nothing, and there is no other
signal that the name is wrong.
The two cases now share one branch, since only a bigNet with no chain track to
follow can reach it. The name comes from the type line as the hub spelled it,
before the hub prefix is added, and goes out through htmlPrintf because it is a
hub's text.
Found in the v504 code review, refs #38349.
refs #20824
- lines changed 68, context: html, text, full: html, text
f19df2f83650190a467c3b1226b3e8a23f6d48c0 Thu Sep 17 17:04:48 2026 -0700
hgc: build the chain and net details pages with htmlPrintf
The chain, snake, quickLift-chain and net click handlers assembled their
output with plain printf. Route the values they print -- assembly and
organism names, sequence names, positions, the chain id and the quickLiftDb
setting -- through htmlPrintf instead, in the four handlers and in the five
linkToOtherBrowser* anchor helpers they share.
The anchor statements are split rather than converted whole, so that
hgTracksName(), cartSidUrlString() and the genark hubUrl stay in a plain
printf and only the values go through htmlPrintf. Converting a whole
statement rewrites the '/' of ../cgi-bin/hgTracks as an entity on every
chain, net, maf and ortho details page; split this way the output is
unchanged for ordinary data.
Verified against the shared build: the native chainMm39, multiz100way and
quickLift "Alignment Differences" pages are byte-identical, and netMm39
differs only in the label "N's", which renders the same.
refs #20824
- src/hg/htdocs/goldenPath/help/trackDb/changes.html
- lines changed 9, context: html, text, full: html, text
98255f58460415345af88e45ad233599740585e5 Wed Sep 16 11:44:41 2026 -0700
trackDb docs for the denseClick setting, refs #38364
Documents the setting added in the previous commit, in the five places a
new trackDb statement has to appear: tagTypes.tab, trackDbLibrary.shtml,
trackDbDoc.html, trackDbHub.v3.html (level-new, since it works in hubs)
and changes.html.
The type list is bed, bigBed, genePred, bigGenePred, psl and bigPsl,
which is the same list decorator carries and matches what the code
reaches: the setting hooks genericDrawItemsFullDense, so it applies to
anything drawn through the linked-features path. Each type was checked
by hand on hg38 in dense with the setting on, counting details links in
the image map: ccdsGene, mrna, mrnaBig and knownGene all gained one link
per item.
The blurb says what happens when several items share a pixel, which is
that the first one wins, and that a row drawn from summary data rather
than from items is unaffected. That last case is real: linkedFeaturesDraw
calls bigBedDrawDense when tg->items is NULL, so a zoomed-out bigBed never
reaches this code and has nothing to link.
Verified with "make settings", which parses the blurb cleanly, and with
hubCheck -settings against the sandbox copy of trackDbHub.v3.html, which
reports "denseClick new" and no errors.
Regenerating trackDbSettings.yaml and .json also picks up minAc,
vcfDoMinAc and vcfPhasedColorBy, which were documented on 2026-09-09
without rebuilding the generated files. Nothing is removed.
- lines changed 37, context: html, text, full: html, text
00e77db940c6eedba27381201442336ced2676a9 Sat Sep 19 07:20:46 2026 -0700
Merge branch 'master' into denseClick38364
# Conflicts:
# src/hg/htdocs/goldenPath/help/trackDb/changes.html
# src/hg/htdocs/goldenPath/help/trackDb/trackDbSettings.json
# src/hg/htdocs/goldenPath/help/trackDb/trackDbSettings.yaml
- src/hg/htdocs/goldenPath/help/trackDb/trackDbDoc.html
- lines changed 3, context: html, text, full: html, text
98255f58460415345af88e45ad233599740585e5 Wed Sep 16 11:44:41 2026 -0700
trackDb docs for the denseClick setting, refs #38364
Documents the setting added in the previous commit, in the five places a
new trackDb statement has to appear: tagTypes.tab, trackDbLibrary.shtml,
trackDbDoc.html, trackDbHub.v3.html (level-new, since it works in hubs)
and changes.html.
The type list is bed, bigBed, genePred, bigGenePred, psl and bigPsl,
which is the same list decorator carries and matches what the code
reaches: the setting hooks genericDrawItemsFullDense, so it applies to
anything drawn through the linked-features path. Each type was checked
by hand on hg38 in dense with the setting on, counting details links in
the image map: ccdsGene, mrna, mrnaBig and knownGene all gained one link
per item.
The blurb says what happens when several items share a pixel, which is
that the first one wins, and that a row drawn from summary data rather
than from items is unaffected. That last case is real: linkedFeaturesDraw
calls bigBedDrawDense when tg->items is NULL, so a zoomed-out bigBed never
reaches this code and has nothing to link.
Verified with "make settings", which parses the blurb cleanly, and with
hubCheck -settings against the sandbox copy of trackDbHub.v3.html, which
reports "denseClick new" and no errors.
Regenerating trackDbSettings.yaml and .json also picks up minAc,
vcfDoMinAc and vcfPhasedColorBy, which were documented on 2026-09-09
without rebuilding the generated files. Nothing is removed.
- src/hg/htdocs/goldenPath/help/trackDb/trackDbHub.v3.html
- lines changed 3, context: html, text, full: html, text
98255f58460415345af88e45ad233599740585e5 Wed Sep 16 11:44:41 2026 -0700
trackDb docs for the denseClick setting, refs #38364
Documents the setting added in the previous commit, in the five places a
new trackDb statement has to appear: tagTypes.tab, trackDbLibrary.shtml,
trackDbDoc.html, trackDbHub.v3.html (level-new, since it works in hubs)
and changes.html.
The type list is bed, bigBed, genePred, bigGenePred, psl and bigPsl,
which is the same list decorator carries and matches what the code
reaches: the setting hooks genericDrawItemsFullDense, so it applies to
anything drawn through the linked-features path. Each type was checked
by hand on hg38 in dense with the setting on, counting details links in
the image map: ccdsGene, mrna, mrnaBig and knownGene all gained one link
per item.
The blurb says what happens when several items share a pixel, which is
that the first one wins, and that a row drawn from summary data rather
than from items is unaffected. That last case is real: linkedFeaturesDraw
calls bigBedDrawDense when tg->items is NULL, so a zoomed-out bigBed never
reaches this code and has nothing to link.
Verified with "make settings", which parses the blurb cleanly, and with
hubCheck -settings against the sandbox copy of trackDbHub.v3.html, which
reports "denseClick new" and no errors.
Regenerating trackDbSettings.yaml and .json also picks up minAc,
vcfDoMinAc and vcfPhasedColorBy, which were documented on 2026-09-09
without rebuilding the generated files. Nothing is removed.
- src/hg/htdocs/goldenPath/help/trackDb/trackDbLibrary.shtml
- lines changed 22, context: html, text, full: html, text
98255f58460415345af88e45ad233599740585e5 Wed Sep 16 11:44:41 2026 -0700
trackDb docs for the denseClick setting, refs #38364
Documents the setting added in the previous commit, in the five places a
new trackDb statement has to appear: tagTypes.tab, trackDbLibrary.shtml,
trackDbDoc.html, trackDbHub.v3.html (level-new, since it works in hubs)
and changes.html.
The type list is bed, bigBed, genePred, bigGenePred, psl and bigPsl,
which is the same list decorator carries and matches what the code
reaches: the setting hooks genericDrawItemsFullDense, so it applies to
anything drawn through the linked-features path. Each type was checked
by hand on hg38 in dense with the setting on, counting details links in
the image map: ccdsGene, mrna, mrnaBig and knownGene all gained one link
per item.
The blurb says what happens when several items share a pixel, which is
that the first one wins, and that a row drawn from summary data rather
than from items is unaffected. That last case is real: linkedFeaturesDraw
calls bigBedDrawDense when tg->items is NULL, so a zoomed-out bigBed never
reaches this code and has nothing to link.
Verified with "make settings", which parses the blurb cleanly, and with
hubCheck -settings against the sandbox copy of trackDbHub.v3.html, which
reports "denseClick new" and no errors.
Regenerating trackDbSettings.yaml and .json also picks up minAc,
vcfDoMinAc and vcfPhasedColorBy, which were documented on 2026-09-09
without rebuilding the generated files. Nothing is removed.
- src/hg/htdocs/goldenPath/help/trackDb/trackDbSettings.json
- lines changed 65, context: html, text, full: html, text
98255f58460415345af88e45ad233599740585e5 Wed Sep 16 11:44:41 2026 -0700
trackDb docs for the denseClick setting, refs #38364
Documents the setting added in the previous commit, in the five places a
new trackDb statement has to appear: tagTypes.tab, trackDbLibrary.shtml,
trackDbDoc.html, trackDbHub.v3.html (level-new, since it works in hubs)
and changes.html.
The type list is bed, bigBed, genePred, bigGenePred, psl and bigPsl,
which is the same list decorator carries and matches what the code
reaches: the setting hooks genericDrawItemsFullDense, so it applies to
anything drawn through the linked-features path. Each type was checked
by hand on hg38 in dense with the setting on, counting details links in
the image map: ccdsGene, mrna, mrnaBig and knownGene all gained one link
per item.
The blurb says what happens when several items share a pixel, which is
that the first one wins, and that a row drawn from summary data rather
than from items is unaffected. That last case is real: linkedFeaturesDraw
calls bigBedDrawDense when tg->items is NULL, so a zoomed-out bigBed never
reaches this code and has nothing to link.
Verified with "make settings", which parses the blurb cleanly, and with
hubCheck -settings against the sandbox copy of trackDbHub.v3.html, which
reports "denseClick new" and no errors.
Regenerating trackDbSettings.yaml and .json also picks up minAc,
vcfDoMinAc and vcfPhasedColorBy, which were documented on 2026-09-09
without rebuilding the generated files. Nothing is removed.
- src/hg/htdocs/goldenPath/help/trackDb/trackDbSettings.yaml
- lines changed 85, context: html, text, full: html, text
98255f58460415345af88e45ad233599740585e5 Wed Sep 16 11:44:41 2026 -0700
trackDb docs for the denseClick setting, refs #38364
Documents the setting added in the previous commit, in the five places a
new trackDb statement has to appear: tagTypes.tab, trackDbLibrary.shtml,
trackDbDoc.html, trackDbHub.v3.html (level-new, since it works in hubs)
and changes.html.
The type list is bed, bigBed, genePred, bigGenePred, psl and bigPsl,
which is the same list decorator carries and matches what the code
reaches: the setting hooks genericDrawItemsFullDense, so it applies to
anything drawn through the linked-features path. Each type was checked
by hand on hg38 in dense with the setting on, counting details links in
the image map: ccdsGene, mrna, mrnaBig and knownGene all gained one link
per item.
The blurb says what happens when several items share a pixel, which is
that the first one wins, and that a row drawn from summary data rather
than from items is unaffected. That last case is real: linkedFeaturesDraw
calls bigBedDrawDense when tg->items is NULL, so a zoomed-out bigBed never
reaches this code and has nothing to link.
Verified with "make settings", which parses the blurb cleanly, and with
hubCheck -settings against the sandbox copy of trackDbHub.v3.html, which
reports "denseClick new" and no errors.
Regenerating trackDbSettings.yaml and .json also picks up minAc,
vcfDoMinAc and vcfPhasedColorBy, which were documented on 2026-09-09
without rebuilding the generated files. Nothing is removed.
- src/hg/inc/bigChain.h
- lines changed 18, context: html, text, full: html, text
72327e4e2d294b9d2fcb6cbdadd4e628c006345b Fri Sep 18 10:07:40 2026 -0700
bigChain: move the chain to bigChain conversion into the library
chainRecToBigChain() and chainBlockToBigLink() sat in chainToBigChain.c
next to its main(), so a CGI could not link against them. Move both into
hg/lib/bigChain.c, add chainToBigChainOne() for one chain and
chainToBigChainList() for a list, and leave the utility as a thin main().
No behavior change; the chainToBigChain test output is unchanged.
refs #38382
- src/hg/inc/versionInfo.h
- lines changed 1, context: html, text, full: html, text
74623f843857f2254e5327c78b98f00c3f7098ff Mon Sep 21 10:00:48 2026 -0700
New version number v504
- src/hg/lib/bigChain.c
- lines changed 60, context: html, text, full: html, text
72327e4e2d294b9d2fcb6cbdadd4e628c006345b Fri Sep 18 10:07:40 2026 -0700
bigChain: move the chain to bigChain conversion into the library
chainRecToBigChain() and chainBlockToBigLink() sat in chainToBigChain.c
next to its main(), so a CGI could not link against them. Move both into
hg/lib/bigChain.c, add chainToBigChainOne() for one chain and
chainToBigChainList() for a list, and leave the utility as a thin main().
No behavior change; the chainToBigChain test output is unchanged.
refs #38382
- src/hg/lib/cart.c
- lines changed 27, context: html, text, full: html, text
2513833e2a3136be51bb8f849dde30c44fa3a5d2 Thu Sep 17 09:53:14 2026 -0700
cart: the fifth copy of the malformed pair loop, in loadHash
loadHash searched for the '=' across the whole remaining string, so a setting
with a name and no value ran into the setting behind it and renamed it, and the
same pair at the end of the string aborted the CGI. This is the copy
cartParseOverHash uses, which reads namedSessionDb.contents and the cart table,
so it has the widest reach of the five and the reader has no way to clear a
string that is already stored.
It now steps over the separators of an empty pair and confines the search to one
pair, behind skipMalformedCgiPairs like the three the same ticket fixed. With
the flag off the parse is unchanged, including the ampersand winning over the
semicolon DAS uses.
Nothing is broken today. Every pair in the September hgwbeta session dump has an
'=' in it, all 1004 rows, and the cart writer always emits name=value.
Found in the v504 code review, refs #38349.
refs #38340
- src/hg/lib/quickLift.c
- lines changed 13, context: html, text, full: html, text
57f2a4a958e5a6432829e33deaaf7b0475971188 Thu Sep 17 09:52:34 2026 -0700
quickLift: keep the target strand a reverse complemented protein just got
quickLiftPslBackToProtein turns the alignment over when pslTransMap hands back
strand[0] == '-', because a protein psl is only ever "++" or "+-". pslRc does
that and makes the target strand explicit as it goes, so the psl comes out "+-".
The assignment at the end of the function then set strand[1] to '+' regardless
and undid it, leaving "++" over blocks that are in minus strand target
coordinates.
pslIsProtein wants strand[1] plus the three to one relation between the last
block and the target end, so it answered no. pslTrack.c then passed a size
multiplier of one to lfFromPslx and every block was drawn at a third of its
length at a mirrored position, which is the symptom the reverse complement was
added to prevent. The assignment is now the else branch of the same test.
hg/lib/tests/quickLiftTester.c covers this. It goes through the public
quickLiftPsl rather than the static function, builds its chains in memory in the
shape quickLiftSourceRanges leaves them, and needs no database. Six cases: a
protein over a same strand chain and over an opposite strand chain, a chain that
gaps only the reference, a chain that drops a source base and so splits a codon,
an mRNA over both chains, and an alignment with no chain under it. Each one runs
pslCheck2, which is what notices a strand that disagrees with the blocks. With
this fix backed out, only the opposite strand case changes and it reports three
errors placing the blocks outside the target range.
Found in the v504 code review, refs #38349.
refs #38249
- src/hg/lib/tests/asForDbTester.c
- lines changed 97, context: html, text, full: html, text
0f2f66270dcd4603785850ee72d7d883ff68185b Sun Sep 20 07:03:14 2026 -0700
asForDbTester: a GenArk accession must not be looked for in MySQL
asForDb() may need a database connection to fetch a track's autoSql. The name
it is handed is usually an assembly, but on a quickLifted track it is the
SOURCE assembly, and for a GenArk that arrives as a bare accession with no
MySQL database of that name anywhere. Without #38272's isGenArk test the CGI
does not return an empty field list, it dies, and the reader gets an error page
instead of a details page -- only for the combination of a quickLift and a
GenArk source, which is why it went unnoticed.
The last case is the discriminating one: a name that is neither a GenArk
accession nor a real database still aborts, which shows the GenArk case is let
through deliberately rather than by connection failures having stopped
mattering. The abort message carries a MySQL error number and the server's own
wording, so what is pinned is whether the abort was about reaching a database
of that name, not the text.
Two things this test got wrong before it got them right, both recorded in its
header. It has to run against a config that sets genarkHubPrefix, because
isGenArk answers through that prefix and says no when it is unset, so with a
developer's own hg.conf the GenArk case failed for a reason unrelated to the
fix. And the accession is read from the genark table at run time, since naming
an assembly makes the test go red the day that assembly is dropped.
Also fixes the registry row for bedItemRgbTester, which moved to hg/cgilib and
whose row still named the old path -- caught by the registry's own check, which
is the first time it has failed for a real reason.
refs #38272, refs #38391
- src/hg/lib/tests/bedItemRgbTester.c
- lines changed 106, context: html, text, full: html, text
a0a3411bca2fdd6d704ce2be7c9c8fca7682913a Sat Sep 19 18:19:36 2026 -0700
bedItemRgbTester: pin the order of the itemRgb and color tests
bedItemRgb() decides whether a BED track draws its items in the colors its file
carries or in the one color its stanza names. The rule has four steps, and the
order of the first three is the whole of #36212: an explicit "itemRgb off"
wins, then an explicit "itemRgb on" wins, and only then does the presence of a
"color" setting turn item colors off by default. 88d620e6c82 folded those
tests together, so a stanza saying both "itemRgb on" and "color" -- which means
items from the file and labels from color -- lost its item colors.
The pairs are what matter here. Every single-setting case passed while the bug
was live, so a test that exercised one setting at a time would have proved
nothing. A child that says "itemRgb on" under a parent that says "color" is
the same case reached through trackDbSettingClosestToHome.
Two runs, with and without hg.conf's alwaysItemRgb, since the last step of the
rule reads it and a mirror that turns it off must still honour a stanza that
asks for item colors explicitly.
The test lives in hg/lib/tests because hg/cgilib has no tests directory; its
link line adds jkhgapcgi.a.
Watched to fail and then pass: with the color test moved back in front of the
itemRgb test, three lines flip, and they are the three that pair the two
settings. Recorded as sandbox-ab in utils/testRegistry.
refs #36212, refs #38391
- src/hg/lib/tests/dataVersionPathTester.c
- lines changed 85, context: html, text, full: html, text
471b82ec87d4b23b03ec3f3a2a193eb1f88a035c Sat Sep 19 18:24:53 2026 -0700
dataVersionPathTester: pin which local files a hub's dataVersion may read
A track's dataVersion setting is usually a version string, but for otto tracks
it is the path of a local file that hgTrackUi opens and prints. On a hub track
that setting is an instruction from a stranger to read a named file on our
server and put it on the page.
#38268 narrowed it to /gbdb, which is public data mirrored on hgdownload, and
to a plain path, since a ".." component makes the name mean something outside
that tree. The exception is needed: curated-hub assemblies are served as hubs,
so hs1's otto tracks are hub tracks, and a quickLifted track's version file
lives on the source assembly.
Nothing about the failure is visible in the usual way. A refused path and an
accepted one both leave a page that looks reasonable, and the difference shows
only as somebody else's file appearing where a version number belongs.
The test prints a classification and never a file. The three outcomes separate
without looking at any contents: a refused path comes back as the path itself,
an accepted path that does not exist comes back NULL, and an accepted path that
exists comes back as something else.
Watched to fail and then pass: with the /gbdb test dropped, /etc/passwd comes
back read rather than refused, and the two climbing cases come back opened.
Recorded as sandbox-ab in utils/testRegistry.
refs #38268, refs #38391
- src/hg/lib/tests/expected/asForDbTest
- lines changed 5, context: html, text, full: html, text
0f2f66270dcd4603785850ee72d7d883ff68185b Sun Sep 20 07:03:14 2026 -0700
asForDbTester: a GenArk accession must not be looked for in MySQL
asForDb() may need a database connection to fetch a track's autoSql. The name
it is handed is usually an assembly, but on a quickLifted track it is the
SOURCE assembly, and for a GenArk that arrives as a bare accession with no
MySQL database of that name anywhere. Without #38272's isGenArk test the CGI
does not return an empty field list, it dies, and the reader gets an error page
instead of a details page -- only for the combination of a quickLift and a
GenArk source, which is why it went unnoticed.
The last case is the discriminating one: a name that is neither a GenArk
accession nor a real database still aborts, which shows the GenArk case is let
through deliberately rather than by connection failures having stopped
mattering. The abort message carries a MySQL error number and the server's own
wording, so what is pinned is whether the abort was about reaching a database
of that name, not the text.
Two things this test got wrong before it got them right, both recorded in its
header. It has to run against a config that sets genarkHubPrefix, because
isGenArk answers through that prefix and says no when it is unset, so with a
developer's own hg.conf the GenArk case failed for a reason unrelated to the
fix. And the accession is read from the genark table at run time, since naming
an assembly makes the test go red the day that assembly is dropped.
Also fixes the registry row for bedItemRgbTester, which moved to hg/cgilib and
whose row still named the old path -- caught by the registry's own check, which
is the first time it has failed for a real reason.
refs #38272, refs #38391
- src/hg/lib/tests/expected/bedItemRgbTest
- lines changed 38, context: html, text, full: html, text
a0a3411bca2fdd6d704ce2be7c9c8fca7682913a Sat Sep 19 18:19:36 2026 -0700
bedItemRgbTester: pin the order of the itemRgb and color tests
bedItemRgb() decides whether a BED track draws its items in the colors its file
carries or in the one color its stanza names. The rule has four steps, and the
order of the first three is the whole of #36212: an explicit "itemRgb off"
wins, then an explicit "itemRgb on" wins, and only then does the presence of a
"color" setting turn item colors off by default. 88d620e6c82 folded those
tests together, so a stanza saying both "itemRgb on" and "color" -- which means
items from the file and labels from color -- lost its item colors.
The pairs are what matter here. Every single-setting case passed while the bug
was live, so a test that exercised one setting at a time would have proved
nothing. A child that says "itemRgb on" under a parent that says "color" is
the same case reached through trackDbSettingClosestToHome.
Two runs, with and without hg.conf's alwaysItemRgb, since the last step of the
rule reads it and a mirror that turns it off must still honour a stanza that
asks for item colors explicitly.
The test lives in hg/lib/tests because hg/cgilib has no tests directory; its
link line adds jkhgapcgi.a.
Watched to fail and then pass: with the color test moved back in front of the
itemRgb test, three lines flip, and they are the three that pair the two
settings. Recorded as sandbox-ab in utils/testRegistry.
refs #36212, refs #38391
- src/hg/lib/tests/expected/dataVersionPathTest
- lines changed 11, context: html, text, full: html, text
471b82ec87d4b23b03ec3f3a2a193eb1f88a035c Sat Sep 19 18:24:53 2026 -0700
dataVersionPathTester: pin which local files a hub's dataVersion may read
A track's dataVersion setting is usually a version string, but for otto tracks
it is the path of a local file that hgTrackUi opens and prints. On a hub track
that setting is an instruction from a stranger to read a named file on our
server and put it on the page.
#38268 narrowed it to /gbdb, which is public data mirrored on hgdownload, and
to a plain path, since a ".." component makes the name mean something outside
that tree. The exception is needed: curated-hub assemblies are served as hubs,
so hs1's otto tracks are hub tracks, and a quickLifted track's version file
lives on the source assembly.
Nothing about the failure is visible in the usual way. A refused path and an
accepted one both leave a page that looks reasonable, and the difference shows
only as somebody else's file appearing where a version number belongs.
The test prints a classification and never a file. The three outcomes separate
without looking at any contents: a refused path comes back as the path itself,
an accepted path that does not exist comes back NULL, and an accepted path that
exists comes back as something else.
Watched to fail and then pass: with the /gbdb test dropped, /etc/passwd comes
back read rather than refused, and the two climbing cases come back opened.
Recorded as sandbox-ab in utils/testRegistry.
refs #38268, refs #38391
- src/hg/lib/tests/expected/genarkLiftOverTest
- lines changed 11, context: html, text, full: html, text
d58bf9a182cbf4dba142a7028742abf688638829 Sat Sep 19 18:27:02 2026 -0700
genarkLiftOverTester: pin the escaping of the GenArk accession list
Before #38328 the caller pasted its accessions into one string and
genarkLiftOverDbs dropped that string into a query marked NOSQLINJ, which is a
promise that somebody upstream had made it safe. It now takes an slName list
and builds the query itself with sqlDyStringPrintf, so the escaping happens
where the values are, and a name that is not a GC accession never reaches the
database.
Nothing about this is visible. Correct and incorrect escaping give the same
page for every input a browser sends, because the accessions come from our own
chain files. The difference appears only for a value chosen to break out,
which is the value that never turns up in ordinary testing.
The genark table is data and it moves, so the test reads an accession out of it
and asks whether the function returns that one, rather than naming an assembly
that may be dropped later.
Watched to fail and then pass: with the value pasted in unescaped the run dies
instead of coming back with nothing, so the quoted cases turn the test red
rather than quietly querying something else. Recorded as sandbox-ab in
utils/testRegistry.
refs #38328, refs #38391
- src/hg/lib/tests/expected/geoMirrorSelfTest
- lines changed 8, context: html, text, full: html, text
36977d0e699d3c853840f08cec63ab2a2dd5eaa7 Sat Sep 19 18:34:00 2026 -0700
geoMirrorSelfTester: pin which gbNode row a server takes for itself
The browser runs on several machines and each offers the others in a menu, so
it has to know which gbNode row is itself. It used to answer from browser.node
in hg.conf alone, so a machine serving a node other than the one browser.node
names -- a sandbox, or two nodes behind one apache -- took itself for its own
peer and offered the visitor a link to the site they were already on. #27988
made the host the visitor typed decide whenever that host is one of the nodes,
with browser.node as the fallback.
The symptom is invisible in the way that matters: every page renders, and a
menu entry pointing back at itself reads as a mirror being down rather than as
a bug.
No domain is named here. gbNode is configuration data whose rows change, so
the test reads two rows, points browser.node at the first, and asks whether the
second can claim the server. What is printed is which of the two answered, not
what they are called, and the port case is included because HTTP_HOST carries
one whenever it is not 80 or 443.
Also recorded in utils/testRegistry: what blocks a unit test on the fifteen
v504 tickets still waiting for one, each with its own reason rather than a
category, since the reason decides who can unblock it.
Watched to fail and then pass: with the host test removed the server claims no
node at all and offers all three, itself included. Recorded as sandbox-ab.
refs #27988, refs #38391
- src/hg/lib/tests/expected/hVarSubstHtmlTest
- lines changed 24, context: html, text, full: html, text
d898b4820087cccd79e240153bc310856bb89310 Sat Sep 19 18:22:49 2026 -0700
hVarSubstHtmlTester: pin which variables a description page may use
A native description page has been through hgTrackDb already, which resolved
everything it could and deferred only ${hgsid}, so the render pass acts on that
one variable and only in braces: hgTrackDb collapses an escaped $$hgsid to a
literal $hgsid, and acting on the bare form here would expand the very thing
the author escaped.
A hub's page has never been substituted, so the whole hub list is resolved at
render time, and $hgsid is deliberately not on that list. A hub page is only
lightly sanitized -- an <img> with an http src survives -- so a page carrying
<img src="https://example.com/px?s=${hgsid}"> would hand the reader's session
id to the hub's own server, and a session id alone is enough to read and write
that cart. The page renders the same either way and the request goes to
somebody else's host, so nothing about this is visible here.
The test builds a cart by hand rather than opening one. That is not a
shortcut, it is the point: a cartless version of this test was written first,
and adding hgsid back to hubHtmlVars changed not one line of its output,
because the check that recognises a variable also asks whether this call can
resolve it, and with no cart it cannot. cartSessionId reads two fields, so a
struct built in the test is enough and no database is involved.
Watched to fail and then pass: with hgsid back on the hub list, both hub cases
come back with the session id substituted into the img src. Recorded as
sandbox-ab in utils/testRegistry.
refs #38283, refs #38391
- src/hg/lib/tests/expected/hgvs/validTerms.txt
- lines changed 8, context: html, text, full: html, text
814335cde61f999ae23626093306bdb6bf394f5e Sun Sep 20 07:00:39 2026 -0700
hgvs: cover a deprecated protein accession, and say what is not covered
A protein accession that is no longer current resolves through
ncbiRefSeqLinkHistorical, which is what lets a term from an old paper still
find its position. Three such terms are added to the valid-terms list:
NP_000054.2, which has three deprecated transcript versions behind it, and
NP_055615.8, which has versions .8, .9 and .10.
The other half of #38248 is NOT pinned, and the registry row says so rather
than implying otherwise. That half picks the newest deprecated transcript by
sorting on length first, so that .9 does not beat .10 as a string. I could not
build a term that shows it: with the order by removed entirely, and again with
a plain string sort, every term gives identical coordinates. The reason is in
the data -- for the accessions with both a .9 and a .10, the versions differ
only in where the UTR ends, so cdsStart, cdsEnd and exonCount are the same and
a coding residue lands in the same place whichever version is chosen.
Recorded as assertion-only, the honest level, with what was tried written down
so the next person does not repeat it.
refs #38248, refs #38391
- src/hg/lib/tests/expected/mallocTopPadTest
- lines changed 4, context: html, text, full: html, text
a5d42e58d7f8ce1e985cf7422145619122ca5d25 Sat Sep 19 18:16:16 2026 -0700
mallocTopPadTester: check the heap step setting still reaches the library
cfgSetMallocTopPad() asks glibc to grow the heap in steps of mallocTopPad bytes
instead of its 128 kB default, which saves a heavy hgTracks render more than a
hundred thousand system calls that draw nothing.
The failure to catch is backsliding: the mallopt call is dropped in a later
edit, or the setting is renamed, or it stops being read before the first
allocation. Every page still draws correctly and the only symptom is that
renders are slower than they used to be, which nobody attributes to this.
So the test measures the step, not the clock. A timing test here would be red
on a busy hgwdev, green on an idle one, and deleted within a month. sbrk(0)
says where the heap ends and the distance it jumps when malloc extends it is
what M_TOP_PAD sets, so the answer is the same on a loaded machine as an idle
one. It is read in buckets, since glibc may round and may change what it
rounds to; what must not change is the order of magnitude between a configured
step and the default. Allocations stay under the mmap threshold, or the break
never moves and the test measures nothing while appearing to pass.
Two runs, with the setting and without, because the answer is the difference
between them: a single run would pass on a library whose own default happened
to be large.
Watched to fail and then pass: leaving the knob read but never applied gives
the default step under both confs, which is the one line the diff shows.
Recorded as sandbox-ab in utils/testRegistry.
refs #38225, refs #38391
- src/hg/lib/tests/expected/quickLiftTest
- lines changed 49, context: html, text, full: html, text
57f2a4a958e5a6432829e33deaaf7b0475971188 Thu Sep 17 09:52:34 2026 -0700
quickLift: keep the target strand a reverse complemented protein just got
quickLiftPslBackToProtein turns the alignment over when pslTransMap hands back
strand[0] == '-', because a protein psl is only ever "++" or "+-". pslRc does
that and makes the target strand explicit as it goes, so the psl comes out "+-".
The assignment at the end of the function then set strand[1] to '+' regardless
and undid it, leaving "++" over blocks that are in minus strand target
coordinates.
pslIsProtein wants strand[1] plus the three to one relation between the last
block and the target end, so it answered no. pslTrack.c then passed a size
multiplier of one to lfFromPslx and every block was drawn at a third of its
length at a mirrored position, which is the symptom the reverse complement was
added to prevent. The assignment is now the else branch of the same test.
hg/lib/tests/quickLiftTester.c covers this. It goes through the public
quickLiftPsl rather than the static function, builds its chains in memory in the
shape quickLiftSourceRanges leaves them, and needs no database. Six cases: a
protein over a same strand chain and over an opposite strand chain, a chain that
gaps only the reference, a chain that drops a source base and so splits a codon,
an mRNA over both chains, and an alignment with no chain under it. Each one runs
pslCheck2, which is what notices a strand that disagrees with the blocks. With
this fix backed out, only the opposite strand case changes and it reports three
errors placing the blocks outside the target range.
Found in the v504 code review, refs #38349.
refs #38249
- src/hg/lib/tests/expected/sessionDataTest
- lines changed 4, context: html, text, full: html, text
51c0d44065340fbacb9f52bacc3b35e0a1456811 Wed Sep 16 09:06:46 2026 -0700
sessionData: a test for the memory contract of sessionDataSaveTrashFile
133df533c4d made sessionDataSaveTrashFile return kent-allocated memory, since
all three places that release its result do so through kent's own handler stack
and it was handing back a pointer from the system malloc. Nothing failed at the
time because the only program that reaches those release sites is hgSession,
which installs no memory handler. That is the whole guard, and it was written
down nowhere.
sessionDataTester installs the careful handler itself and runs the function
under it: it resolves a relative trash symlink, releases the result with
freeMem, allocates again and checks the heap, then compares the allocated block
count before and after so a leaked link target is caught too. The absolute
symlink and the expired-file cases run alongside. Reverting either half of
133df533c4d fails the test; the plain-file branch that calls moveAndLink is not
covered, since isTrashPath rejects a synthetic path with no trash dir
configured.
No database and no trash directory are needed, so the target runs ahead of
spDbTest and hdbTest in hg/lib/tests.
refs #38318
- src/hg/lib/tests/expected/sessionDirTest
- lines changed 19, context: html, text, full: html, text
751a1f9fff1d6d77c2da690d1369dca64ba04fee Sat Sep 19 18:31:42 2026 -0700
sessionDirTester: pin how a saved session's data directory is named
A saved session's custom tracks and region files are moved to a durable
directory named from the user name and the session name. #10138 widened the
session half of that name from 8 hex characters to 10: 8 characters of md5 is
4 billion values, and the birthday arithmetic over hundreds of thousands of
sessions is not comfortable, since a collision puts one user's files in another
user's session.
Widening a name that is already on disk is the risky half. Directories written
before the change carry the old width and their files are still in use, so the
cleanup code has to be able to name both, which is why the width is a parameter
rather than a constant in the middle of the function.
The property pinned here is not the hash, it is that the short name is a PREFIX
of the long one. That is what lets code holding the new name find a directory
written under the old one, and it holds only because both come from the same
md5 truncated to different lengths. Also pinned: the two-character spreading
directory, the user name appearing as given, and the three calls that must
abort rather than invent a path -- a relative sessionDataDir, and a width of 0
or 33.
None of this is visible. A session whose directory is named differently does
not report an error, it comes back without its custom track.
Watched to fail and then pass: narrowing the width back to 8 turns it red on
the width line. Recorded as sandbox-ab in utils/testRegistry.
refs #10138, refs #38391
- src/hg/lib/tests/expected/snapshotTypeTest
- lines changed 23, context: html, text, full: html, text
89f9ce7bc7c9333c45190074088f5bee377ca1d7 Sat Sep 19 18:30:26 2026 -0700
snapshotTypeTester: check the fast snapshotType reader against raFromString
A saved session is a snapshot when its settings carry a snapshotType line, and
the My Sessions listings hide those rows. #38313 replaced raFromString with a
walk over the lines, because the question is asked once per row in a listing
and the hash costs about 600ns and three allocations per session against about
30ns and none.
A hand written parser that has to agree with a general one is the shape of bug
found a year later, so this is a differential test: every case is read both
ways and the two answers are printed side by side. The claim in the code is
"same line semantics as raFromString", and that claim is what is checked rather
than a list of answers written down once. Reading the tag wrongly is invisible
either way: a snapshot is listed as an ordinary session, or an ordinary session
disappears from the listing, and both look like something the user did.
One case does not agree, and it is recorded rather than hidden. Given two
snapshotType lines the walk returns the first and raFromString returns the
last, because a hash overwrites. Real settings carry the tag once, so nothing
depends on it today, but it is a difference in the semantics the code says it
copies. It is marked as a known difference, and the test also fails if it ever
starts agreeing, so the note cannot go stale in the other direction.
Watched to fail and then pass: dropping the delimiter test after the tag makes
"snapshotTypeExtra view" read as the type "Extra view" while raFromString finds
none. Recorded as sandbox-ab in utils/testRegistry.
refs #38313, refs #38391
- src/hg/lib/tests/expected/trashDirTest
- lines changed 105, context: html, text, full: html, text
859bc749b0593a83e1c8cd7149f956b620a24a73 Sat Sep 19 18:14:15 2026 -0700
trashDirTester: pin which file paths the cart accepts
hg/lib/cart.c screens every cart variable that names a server-made file through
these functions, so they decide whether a saved session still works. Both ways
of being wrong are invisible: a path wrongly refused brings the session back
without its custom track or its region list and says nothing, and a path
wrongly accepted says nothing either.
That is what #38303 cost. A check shipped in v503 discarded the saved region
list from 583 sessions on the RR and 66 on euro, and hgwdev, code review and
hgwbeta were all clean, because the corpus that shows it is only on the
production central.
Four rules pinned, each of which cost a bug or a review round: only the
configured directory is symlink-resolved and never the path from the cart; the
resolved spelling of that directory is accepted as well as the configured one,
since /userdata on the RR is a symlink and saved sessions hold both spellings;
only an absolute directory is resolved, because a relative one would be
resolved against the caller's working directory; and the acceptance runs one
direction only. pathIsUnderDir's own edges are here too, including the sibling
directory that merely starts the same way and the name that begins with "..".
The fixture is a directory, a symlink to it and three confs naming the same
place three ways, since hgConfig caches what it read and one process can only
answer for one spelling. Nothing machine-specific reaches the output.
Watched to fail and then pass: with the pre-#38303 code, which did not resolve
at all, the resolved spelling comes back refused and the diff is that one line.
Recorded as sandbox-ab in utils/testRegistry.
refs #38303, refs #37623, refs #38391
- src/hg/lib/tests/genarkLiftOverTester.c
- lines changed 83, context: html, text, full: html, text
d58bf9a182cbf4dba142a7028742abf688638829 Sat Sep 19 18:27:02 2026 -0700
genarkLiftOverTester: pin the escaping of the GenArk accession list
Before #38328 the caller pasted its accessions into one string and
genarkLiftOverDbs dropped that string into a query marked NOSQLINJ, which is a
promise that somebody upstream had made it safe. It now takes an slName list
and builds the query itself with sqlDyStringPrintf, so the escaping happens
where the values are, and a name that is not a GC accession never reaches the
database.
Nothing about this is visible. Correct and incorrect escaping give the same
page for every input a browser sends, because the accessions come from our own
chain files. The difference appears only for a value chosen to break out,
which is the value that never turns up in ordinary testing.
The genark table is data and it moves, so the test reads an accession out of it
and asks whether the function returns that one, rather than naming an assembly
that may be dropped later.
Watched to fail and then pass: with the value pasted in unescaped the run dies
instead of coming back with nothing, so the quoted cases turn the test red
rather than quietly querying something else. Recorded as sandbox-ab in
utils/testRegistry.
refs #38328, refs #38391
- src/hg/lib/tests/geoMirrorSelfTester.c
- lines changed 101, context: html, text, full: html, text
36977d0e699d3c853840f08cec63ab2a2dd5eaa7 Sat Sep 19 18:34:00 2026 -0700
geoMirrorSelfTester: pin which gbNode row a server takes for itself
The browser runs on several machines and each offers the others in a menu, so
it has to know which gbNode row is itself. It used to answer from browser.node
in hg.conf alone, so a machine serving a node other than the one browser.node
names -- a sandbox, or two nodes behind one apache -- took itself for its own
peer and offered the visitor a link to the site they were already on. #27988
made the host the visitor typed decide whenever that host is one of the nodes,
with browser.node as the fallback.
The symptom is invisible in the way that matters: every page renders, and a
menu entry pointing back at itself reads as a mirror being down rather than as
a bug.
No domain is named here. gbNode is configuration data whose rows change, so
the test reads two rows, points browser.node at the first, and asks whether the
second can claim the server. What is printed is which of the two answered, not
what they are called, and the port case is included because HTTP_HOST carries
one whenever it is not 80 or 443.
Also recorded in utils/testRegistry: what blocks a unit test on the fifteen
v504 tickets still waiting for one, each with its own reason rather than a
category, since the reason decides who can unblock it.
Watched to fail and then pass: with the host test removed the server claims no
node at all and offers all three, itself included. Recorded as sandbox-ab.
refs #27988, refs #38391
- src/hg/lib/tests/hVarSubstHtmlTester.c
- lines changed 138, context: html, text, full: html, text
d898b4820087cccd79e240153bc310856bb89310 Sat Sep 19 18:22:49 2026 -0700
hVarSubstHtmlTester: pin which variables a description page may use
A native description page has been through hgTrackDb already, which resolved
everything it could and deferred only ${hgsid}, so the render pass acts on that
one variable and only in braces: hgTrackDb collapses an escaped $$hgsid to a
literal $hgsid, and acting on the bare form here would expand the very thing
the author escaped.
A hub's page has never been substituted, so the whole hub list is resolved at
render time, and $hgsid is deliberately not on that list. A hub page is only
lightly sanitized -- an <img> with an http src survives -- so a page carrying
<img src="https://example.com/px?s=${hgsid}"> would hand the reader's session
id to the hub's own server, and a session id alone is enough to read and write
that cart. The page renders the same either way and the request goes to
somebody else's host, so nothing about this is visible here.
The test builds a cart by hand rather than opening one. That is not a
shortcut, it is the point: a cartless version of this test was written first,
and adding hgsid back to hubHtmlVars changed not one line of its output,
because the check that recognises a variable also asks whether this call can
resolve it, and with no cart it cannot. cartSessionId reads two fields, so a
struct built in the test is enough and no database is involved.
Watched to fail and then pass: with hgsid back on the hub list, both hub cases
come back with the session id substituted into the img src. Recorded as
sandbox-ab in utils/testRegistry.
refs #38283, refs #38391
- src/hg/lib/tests/hubSpaceKeysTester.c
- lines changed 122, context: html, text, full: html, text
7fc3b3ce76531995f0978618fbb5c5e1fccf31cf Sun Sep 20 06:58:05 2026 -0700
hgcentralregress: a central database that tests may write to
Every hgcentral a developer can reach is shared. hgcentraltest holds thousands
of rows of other people's sandbox sessions, and the production centrals are not
reachable from hgwdev at all, so a test that needs to create a session, a login
or an api key has had nowhere to put it. Every test written for #38391 so far
only reads, and that is the limit this lifts.
makeHgCentralRegress.sh creates the database and its tables, copying each
schema from the central the caller's hg.conf already names, so a column added
to namedSessionDb reaches it on the next run and there is no second copy of the
schema in the tree to forget. It is idempotent and meant to run before a test.
ONE GRANT IS STILL MISSING and no test uses the database yet. The account the
browser uses for the central has global SELECT, INSERT, CREATE and DROP, but
UPDATE and DELETE only on databases it has been granted them on individually.
So a test can create rows here and cannot take them down: the delete comes back
1142. The script says what to ask for. Measured rather than assumed, and one
guess along the way was wrong: the hgcentraltest prefix carries no wildcard
grant, hgcentraltestregress behaves the same as any other new name.
hubSpaceKeysTester is written against it and is deliberately NOT in the test
target, so nothing here goes red while it waits. It covers the rules an api
key lives by -- one key per user, a new key revokes the old, an adopted key
from a peer mirror replaces both, a revoked key names nobody -- and the
signature a peer checks before accepting a sync. refs #38323.
refs #38391
- src/hg/lib/tests/input/hgvs/validTerms.txt
- lines changed 8, context: html, text, full: html, text
814335cde61f999ae23626093306bdb6bf394f5e Sun Sep 20 07:00:39 2026 -0700
hgvs: cover a deprecated protein accession, and say what is not covered
A protein accession that is no longer current resolves through
ncbiRefSeqLinkHistorical, which is what lets a term from an old paper still
find its position. Three such terms are added to the valid-terms list:
NP_000054.2, which has three deprecated transcript versions behind it, and
NP_055615.8, which has versions .8, .9 and .10.
The other half of #38248 is NOT pinned, and the registry row says so rather
than implying otherwise. That half picks the newest deprecated transcript by
sorting on length first, so that .9 does not beat .10 as a string. I could not
build a term that shows it: with the order by removed entirely, and again with
a plain string sort, every term gives identical coordinates. The reason is in
the data -- for the accessions with both a .9 and a .10, the versions differ
only in where the UTR ends, so cdsStart, cdsEnd and exonCount are the same and
a coding residue lands in the same place whichever version is chosen.
Recorded as assertion-only, the honest level, with what was tried written down
so the next person does not repeat it.
refs #38248, refs #38391
- src/hg/lib/tests/makeHgCentralRegress.sh
- lines changed 96, context: html, text, full: html, text
7fc3b3ce76531995f0978618fbb5c5e1fccf31cf Sun Sep 20 06:58:05 2026 -0700
hgcentralregress: a central database that tests may write to
Every hgcentral a developer can reach is shared. hgcentraltest holds thousands
of rows of other people's sandbox sessions, and the production centrals are not
reachable from hgwdev at all, so a test that needs to create a session, a login
or an api key has had nowhere to put it. Every test written for #38391 so far
only reads, and that is the limit this lifts.
makeHgCentralRegress.sh creates the database and its tables, copying each
schema from the central the caller's hg.conf already names, so a column added
to namedSessionDb reaches it on the next run and there is no second copy of the
schema in the tree to forget. It is idempotent and meant to run before a test.
ONE GRANT IS STILL MISSING and no test uses the database yet. The account the
browser uses for the central has global SELECT, INSERT, CREATE and DROP, but
UPDATE and DELETE only on databases it has been granted them on individually.
So a test can create rows here and cannot take them down: the delete comes back
1142. The script says what to ask for. Measured rather than assumed, and one
guess along the way was wrong: the hgcentraltest prefix carries no wildcard
grant, hgcentraltestregress behaves the same as any other new name.
hubSpaceKeysTester is written against it and is deliberately NOT in the test
target, so nothing here goes red while it waits. It covers the rules an api
key lives by -- one key per user, a new key revokes the old, an adopted key
from a peer mirror replaces both, a revoked key names nobody -- and the
signature a peer checks before accepting a sync. refs #38323.
refs #38391
- src/hg/lib/tests/makefile
- lines changed 6, context: html, text, full: html, text
51c0d44065340fbacb9f52bacc3b35e0a1456811 Wed Sep 16 09:06:46 2026 -0700
sessionData: a test for the memory contract of sessionDataSaveTrashFile
133df533c4d made sessionDataSaveTrashFile return kent-allocated memory, since
all three places that release its result do so through kent's own handler stack
and it was handing back a pointer from the system malloc. Nothing failed at the
time because the only program that reaches those release sites is hgSession,
which installs no memory handler. That is the whole guard, and it was written
down nowhere.
sessionDataTester installs the careful handler itself and runs the function
under it: it resolves a relative trash symlink, releases the result with
freeMem, allocates again and checks the heap, then compares the allocated block
count before and after so a leaked link target is caught too. The absolute
symlink and the expired-file cases run alongside. Reverting either half of
133df533c4d fails the test; the plain-file branch that calls moveAndLink is not
covered, since isTrashPath rejects a synthetic path with no trash dir
configured.
No database and no trash directory are needed, so the target runs ahead of
spDbTest and hdbTest in hg/lib/tests.
refs #38318
- lines changed 6, context: html, text, full: html, text
57f2a4a958e5a6432829e33deaaf7b0475971188 Thu Sep 17 09:52:34 2026 -0700
quickLift: keep the target strand a reverse complemented protein just got
quickLiftPslBackToProtein turns the alignment over when pslTransMap hands back
strand[0] == '-', because a protein psl is only ever "++" or "+-". pslRc does
that and makes the target strand explicit as it goes, so the psl comes out "+-".
The assignment at the end of the function then set strand[1] to '+' regardless
and undid it, leaving "++" over blocks that are in minus strand target
coordinates.
pslIsProtein wants strand[1] plus the three to one relation between the last
block and the target end, so it answered no. pslTrack.c then passed a size
multiplier of one to lfFromPslx and every block was drawn at a third of its
length at a mirrored position, which is the symptom the reverse complement was
added to prevent. The assignment is now the else branch of the same test.
hg/lib/tests/quickLiftTester.c covers this. It goes through the public
quickLiftPsl rather than the static function, builds its chains in memory in the
shape quickLiftSourceRanges leaves them, and needs no database. Six cases: a
protein over a same strand chain and over an opposite strand chain, a chain that
gaps only the reference, a chain that drops a source base and so splits a codon,
an mRNA over both chains, and an alignment with no chain under it. Each one runs
pslCheck2, which is what notices a strand that disagrees with the blocks. With
this fix backed out, only the opposite strand case changes and it reports three
errors placing the blocks outside the target range.
Found in the v504 code review, refs #38349.
refs #38249
- lines changed 30, context: html, text, full: html, text
859bc749b0593a83e1c8cd7149f956b620a24a73 Sat Sep 19 18:14:15 2026 -0700
trashDirTester: pin which file paths the cart accepts
hg/lib/cart.c screens every cart variable that names a server-made file through
these functions, so they decide whether a saved session still works. Both ways
of being wrong are invisible: a path wrongly refused brings the session back
without its custom track or its region list and says nothing, and a path
wrongly accepted says nothing either.
That is what #38303 cost. A check shipped in v503 discarded the saved region
list from 583 sessions on the RR and 66 on euro, and hgwdev, code review and
hgwbeta were all clean, because the corpus that shows it is only on the
production central.
Four rules pinned, each of which cost a bug or a review round: only the
configured directory is symlink-resolved and never the path from the cart; the
resolved spelling of that directory is accepted as well as the configured one,
since /userdata on the RR is a symlink and saved sessions hold both spellings;
only an absolute directory is resolved, because a relative one would be
resolved against the caller's working directory; and the acceptance runs one
direction only. pathIsUnderDir's own edges are here too, including the sibling
directory that merely starts the same way and the name that begins with "..".
The fixture is a directory, a symlink to it and three confs naming the same
place three ways, since hgConfig caches what it read and one process can only
answer for one spelling. Nothing machine-specific reaches the output.
Watched to fail and then pass: with the pre-#38303 code, which did not resolve
at all, the resolved spelling comes back refused and the diff is that one line.
Recorded as sandbox-ab in utils/testRegistry.
refs #38303, refs #37623, refs #38391
- lines changed 12, context: html, text, full: html, text
a5d42e58d7f8ce1e985cf7422145619122ca5d25 Sat Sep 19 18:16:16 2026 -0700
mallocTopPadTester: check the heap step setting still reaches the library
cfgSetMallocTopPad() asks glibc to grow the heap in steps of mallocTopPad bytes
instead of its 128 kB default, which saves a heavy hgTracks render more than a
hundred thousand system calls that draw nothing.
The failure to catch is backsliding: the mallopt call is dropped in a later
edit, or the setting is renamed, or it stops being read before the first
allocation. Every page still draws correctly and the only symptom is that
renders are slower than they used to be, which nobody attributes to this.
So the test measures the step, not the clock. A timing test here would be red
on a busy hgwdev, green on an idle one, and deleted within a month. sbrk(0)
says where the heap ends and the distance it jumps when malloc extends it is
what M_TOP_PAD sets, so the answer is the same on a loaded machine as an idle
one. It is read in buckets, since glibc may round and may change what it
rounds to; what must not change is the order of magnitude between a configured
step and the default. Allocations stay under the mmap threshold, or the break
never moves and the test measures nothing while appearing to pass.
Two runs, with the setting and without, because the answer is the difference
between them: a single run would pass on a library whose own default happened
to be large.
Watched to fail and then pass: leaving the knob read but never applied gives
the default step under both confs, which is the one line the diff shows.
Recorded as sandbox-ab in utils/testRegistry.
refs #38225, refs #38391
- lines changed 14, context: html, text, full: html, text
a0a3411bca2fdd6d704ce2be7c9c8fca7682913a Sat Sep 19 18:19:36 2026 -0700
bedItemRgbTester: pin the order of the itemRgb and color tests
bedItemRgb() decides whether a BED track draws its items in the colors its file
carries or in the one color its stanza names. The rule has four steps, and the
order of the first three is the whole of #36212: an explicit "itemRgb off"
wins, then an explicit "itemRgb on" wins, and only then does the presence of a
"color" setting turn item colors off by default. 88d620e6c82 folded those
tests together, so a stanza saying both "itemRgb on" and "color" -- which means
items from the file and labels from color -- lost its item colors.
The pairs are what matter here. Every single-setting case passed while the bug
was live, so a test that exercised one setting at a time would have proved
nothing. A child that says "itemRgb on" under a parent that says "color" is
the same case reached through trackDbSettingClosestToHome.
Two runs, with and without hg.conf's alwaysItemRgb, since the last step of the
rule reads it and a mirror that turns it off must still honour a stanza that
asks for item colors explicitly.
The test lives in hg/lib/tests because hg/cgilib has no tests directory; its
link line adds jkhgapcgi.a.
Watched to fail and then pass: with the color test moved back in front of the
itemRgb test, three lines flip, and they are the three that pair the two
settings. Recorded as sandbox-ab in utils/testRegistry.
refs #36212, refs #38391
- lines changed 7, context: html, text, full: html, text
d898b4820087cccd79e240153bc310856bb89310 Sat Sep 19 18:22:49 2026 -0700
hVarSubstHtmlTester: pin which variables a description page may use
A native description page has been through hgTrackDb already, which resolved
everything it could and deferred only ${hgsid}, so the render pass acts on that
one variable and only in braces: hgTrackDb collapses an escaped $$hgsid to a
literal $hgsid, and acting on the bare form here would expand the very thing
the author escaped.
A hub's page has never been substituted, so the whole hub list is resolved at
render time, and $hgsid is deliberately not on that list. A hub page is only
lightly sanitized -- an <img> with an http src survives -- so a page carrying
<img src="https://example.com/px?s=${hgsid}"> would hand the reader's session
id to the hub's own server, and a session id alone is enough to read and write
that cart. The page renders the same either way and the request goes to
somebody else's host, so nothing about this is visible here.
The test builds a cart by hand rather than opening one. That is not a
shortcut, it is the point: a cartless version of this test was written first,
and adding hgsid back to hubHtmlVars changed not one line of its output,
because the check that recognises a variable also asks whether this call can
resolve it, and with no cart it cannot. cartSessionId reads two fields, so a
struct built in the test is enough and no database is involved.
Watched to fail and then pass: with hgsid back on the hub list, both hub cases
come back with the session id substituted into the img src. Recorded as
sandbox-ab in utils/testRegistry.
refs #38283, refs #38391
- lines changed 6, context: html, text, full: html, text
471b82ec87d4b23b03ec3f3a2a193eb1f88a035c Sat Sep 19 18:24:53 2026 -0700
dataVersionPathTester: pin which local files a hub's dataVersion may read
A track's dataVersion setting is usually a version string, but for otto tracks
it is the path of a local file that hgTrackUi opens and prints. On a hub track
that setting is an instruction from a stranger to read a named file on our
server and put it on the page.
#38268 narrowed it to /gbdb, which is public data mirrored on hgdownload, and
to a plain path, since a ".." component makes the name mean something outside
that tree. The exception is needed: curated-hub assemblies are served as hubs,
so hs1's otto tracks are hub tracks, and a quickLifted track's version file
lives on the source assembly.
Nothing about the failure is visible in the usual way. A refused path and an
accepted one both leave a page that looks reasonable, and the difference shows
only as somebody else's file appearing where a version number belongs.
The test prints a classification and never a file. The three outcomes separate
without looking at any contents: a refused path comes back as the path itself,
an accepted path that does not exist comes back NULL, and an accepted path that
exists comes back as something else.
Watched to fail and then pass: with the /gbdb test dropped, /etc/passwd comes
back read rather than refused, and the two climbing cases come back opened.
Recorded as sandbox-ab in utils/testRegistry.
refs #38268, refs #38391
- lines changed 6, context: html, text, full: html, text
d58bf9a182cbf4dba142a7028742abf688638829 Sat Sep 19 18:27:02 2026 -0700
genarkLiftOverTester: pin the escaping of the GenArk accession list
Before #38328 the caller pasted its accessions into one string and
genarkLiftOverDbs dropped that string into a query marked NOSQLINJ, which is a
promise that somebody upstream had made it safe. It now takes an slName list
and builds the query itself with sqlDyStringPrintf, so the escaping happens
where the values are, and a name that is not a GC accession never reaches the
database.
Nothing about this is visible. Correct and incorrect escaping give the same
page for every input a browser sends, because the accessions come from our own
chain files. The difference appears only for a value chosen to break out,
which is the value that never turns up in ordinary testing.
The genark table is data and it moves, so the test reads an accession out of it
and asks whether the function returns that one, rather than naming an assembly
that may be dropped later.
Watched to fail and then pass: with the value pasted in unescaped the run dies
instead of coming back with nothing, so the quoted cases turn the test red
rather than quietly querying something else. Recorded as sandbox-ab in
utils/testRegistry.
refs #38328, refs #38391
- lines changed 7, context: html, text, full: html, text
89f9ce7bc7c9333c45190074088f5bee377ca1d7 Sat Sep 19 18:30:26 2026 -0700
snapshotTypeTester: check the fast snapshotType reader against raFromString
A saved session is a snapshot when its settings carry a snapshotType line, and
the My Sessions listings hide those rows. #38313 replaced raFromString with a
walk over the lines, because the question is asked once per row in a listing
and the hash costs about 600ns and three allocations per session against about
30ns and none.
A hand written parser that has to agree with a general one is the shape of bug
found a year later, so this is a differential test: every case is read both
ways and the two answers are printed side by side. The claim in the code is
"same line semantics as raFromString", and that claim is what is checked rather
than a list of answers written down once. Reading the tag wrongly is invisible
either way: a snapshot is listed as an ordinary session, or an ordinary session
disappears from the listing, and both look like something the user did.
One case does not agree, and it is recorded rather than hidden. Given two
snapshotType lines the walk returns the first and raFromString returns the
last, because a hash overwrites. Real settings carry the tag once, so nothing
depends on it today, but it is a difference in the semantics the code says it
copies. It is marked as a known difference, and the test also fails if it ever
starts agreeing, so the note cannot go stale in the other direction.
Watched to fail and then pass: dropping the delimiter test after the tag makes
"snapshotTypeExtra view" read as the type "Extra view" while raFromString finds
none. Recorded as sandbox-ab in utils/testRegistry.
refs #38313, refs #38391
- lines changed 6, context: html, text, full: html, text
751a1f9fff1d6d77c2da690d1369dca64ba04fee Sat Sep 19 18:31:42 2026 -0700
sessionDirTester: pin how a saved session's data directory is named
A saved session's custom tracks and region files are moved to a durable
directory named from the user name and the session name. #10138 widened the
session half of that name from 8 hex characters to 10: 8 characters of md5 is
4 billion values, and the birthday arithmetic over hundreds of thousands of
sessions is not comfortable, since a collision puts one user's files in another
user's session.
Widening a name that is already on disk is the risky half. Directories written
before the change carry the old width and their files are still in use, so the
cleanup code has to be able to name both, which is why the width is a parameter
rather than a constant in the middle of the function.
The property pinned here is not the hash, it is that the short name is a PREFIX
of the long one. That is what lets code holding the new name find a directory
written under the old one, and it holds only because both come from the same
md5 truncated to different lengths. Also pinned: the two-character spreading
directory, the user name appearing as given, and the three calls that must
abort rather than invent a path -- a relative sessionDataDir, and a width of 0
or 33.
None of this is visible. A session whose directory is named differently does
not report an error, it comes back without its custom track.
Watched to fail and then pass: narrowing the width back to 8 turns it red on
the width line. Recorded as sandbox-ab in utils/testRegistry.
refs #10138, refs #38391
- lines changed 10, context: html, text, full: html, text
36977d0e699d3c853840f08cec63ab2a2dd5eaa7 Sat Sep 19 18:34:00 2026 -0700
geoMirrorSelfTester: pin which gbNode row a server takes for itself
The browser runs on several machines and each offers the others in a menu, so
it has to know which gbNode row is itself. It used to answer from browser.node
in hg.conf alone, so a machine serving a node other than the one browser.node
names -- a sandbox, or two nodes behind one apache -- took itself for its own
peer and offered the visitor a link to the site they were already on. #27988
made the host the visitor typed decide whenever that host is one of the nodes,
with browser.node as the fallback.
The symptom is invisible in the way that matters: every page renders, and a
menu entry pointing back at itself reads as a mirror being down rather than as
a bug.
No domain is named here. gbNode is configuration data whose rows change, so
the test reads two rows, points browser.node at the first, and asks whether the
second can claim the server. What is printed is which of the two answered, not
what they are called, and the port case is included because HTTP_HOST carries
one whenever it is not 80 or 443.
Also recorded in utils/testRegistry: what blocks a unit test on the fifteen
v504 tickets still waiting for one, each with its own reason rather than a
category, since the reason decides who can unblock it.
Watched to fail and then pass: with the host test removed the server claims no
node at all and offers all three, itself included. Recorded as sandbox-ab.
refs #27988, refs #38391
- lines changed 14, context: html, text, full: html, text
c80f2909a9df53021fb01b455b122414ad73c961 Sun Sep 20 06:51:14 2026 -0700
move bedItemRgbTester to hg/cgilib/tests, beside the code it tests
I said in the last commit that hg/cgilib had no tests directory. It does, and
I should have looked rather than inferred. bedCart.c lives in hg/cgilib, so
its test belongs there, and the header comment saying otherwise is fixed.
Worth knowing about that directory: its test target ran nothing. annoGratorTest
is commented out because it needs assemblies and tables the directory cannot
assume, so `make test` there printed "tested all" and did no work -- and
hg/makefile has been running it all along through TEST_EXTRA. bedItemRgbTest
is now the one test it does run.
refs #36212, refs #38391
- lines changed 16, context: html, text, full: html, text
7fc3b3ce76531995f0978618fbb5c5e1fccf31cf Sun Sep 20 06:58:05 2026 -0700
hgcentralregress: a central database that tests may write to
Every hgcentral a developer can reach is shared. hgcentraltest holds thousands
of rows of other people's sandbox sessions, and the production centrals are not
reachable from hgwdev at all, so a test that needs to create a session, a login
or an api key has had nowhere to put it. Every test written for #38391 so far
only reads, and that is the limit this lifts.
makeHgCentralRegress.sh creates the database and its tables, copying each
schema from the central the caller's hg.conf already names, so a column added
to namedSessionDb reaches it on the next run and there is no second copy of the
schema in the tree to forget. It is idempotent and meant to run before a test.
ONE GRANT IS STILL MISSING and no test uses the database yet. The account the
browser uses for the central has global SELECT, INSERT, CREATE and DROP, but
UPDATE and DELETE only on databases it has been granted them on individually.
So a test can create rows here and cannot take them down: the delete comes back
1142. The script says what to ask for. Measured rather than assumed, and one
guess along the way was wrong: the hgcentraltest prefix carries no wildcard
grant, hgcentraltestregress behaves the same as any other new name.
hubSpaceKeysTester is written against it and is deliberately NOT in the test
target, so nothing here goes red while it waits. It covers the rules an api
key lives by -- one key per user, a new key revokes the old, an adopted key
from a peer mirror replaces both, a revoked key names nobody -- and the
signature a peer checks before accepting a sync. refs #38323.
refs #38391
- lines changed 9, context: html, text, full: html, text
0f2f66270dcd4603785850ee72d7d883ff68185b Sun Sep 20 07:03:14 2026 -0700
asForDbTester: a GenArk accession must not be looked for in MySQL
asForDb() may need a database connection to fetch a track's autoSql. The name
it is handed is usually an assembly, but on a quickLifted track it is the
SOURCE assembly, and for a GenArk that arrives as a bare accession with no
MySQL database of that name anywhere. Without #38272's isGenArk test the CGI
does not return an empty field list, it dies, and the reader gets an error page
instead of a details page -- only for the combination of a quickLift and a
GenArk source, which is why it went unnoticed.
The last case is the discriminating one: a name that is neither a GenArk
accession nor a real database still aborts, which shows the GenArk case is let
through deliberately rather than by connection failures having stopped
mattering. The abort message carries a MySQL error number and the server's own
wording, so what is pinned is whether the abort was about reaching a database
of that name, not the text.
Two things this test got wrong before it got them right, both recorded in its
header. It has to run against a config that sets genarkHubPrefix, because
isGenArk answers through that prefix and says no when it is unset, so with a
developer's own hg.conf the GenArk case failed for a reason unrelated to the
fix. And the accession is read from the genark table at run time, since naming
an assembly makes the test go red the day that assembly is dropped.
Also fixes the registry row for bedItemRgbTester, which moved to hg/cgilib and
whose row still named the old path -- caught by the registry's own check, which
is the first time it has failed for a real reason.
refs #38272, refs #38391
- src/hg/lib/tests/mallocTopPadTester.c
- lines changed 84, context: html, text, full: html, text
a5d42e58d7f8ce1e985cf7422145619122ca5d25 Sat Sep 19 18:16:16 2026 -0700
mallocTopPadTester: check the heap step setting still reaches the library
cfgSetMallocTopPad() asks glibc to grow the heap in steps of mallocTopPad bytes
instead of its 128 kB default, which saves a heavy hgTracks render more than a
hundred thousand system calls that draw nothing.
The failure to catch is backsliding: the mallopt call is dropped in a later
edit, or the setting is renamed, or it stops being read before the first
allocation. Every page still draws correctly and the only symptom is that
renders are slower than they used to be, which nobody attributes to this.
So the test measures the step, not the clock. A timing test here would be red
on a busy hgwdev, green on an idle one, and deleted within a month. sbrk(0)
says where the heap ends and the distance it jumps when malloc extends it is
what M_TOP_PAD sets, so the answer is the same on a loaded machine as an idle
one. It is read in buckets, since glibc may round and may change what it
rounds to; what must not change is the order of magnitude between a configured
step and the default. Allocations stay under the mmap threshold, or the break
never moves and the test measures nothing while appearing to pass.
Two runs, with the setting and without, because the answer is the difference
between them: a single run would pass on a library whose own default happened
to be large.
Watched to fail and then pass: leaving the knob read but never applied gives
the default step under both confs, which is the one line the diff shows.
Recorded as sandbox-ab in utils/testRegistry.
refs #38225, refs #38391
- src/hg/lib/tests/quickLiftTester.c
- lines changed 223, context: html, text, full: html, text
57f2a4a958e5a6432829e33deaaf7b0475971188 Thu Sep 17 09:52:34 2026 -0700
quickLift: keep the target strand a reverse complemented protein just got
quickLiftPslBackToProtein turns the alignment over when pslTransMap hands back
strand[0] == '-', because a protein psl is only ever "++" or "+-". pslRc does
that and makes the target strand explicit as it goes, so the psl comes out "+-".
The assignment at the end of the function then set strand[1] to '+' regardless
and undid it, leaving "++" over blocks that are in minus strand target
coordinates.
pslIsProtein wants strand[1] plus the three to one relation between the last
block and the target end, so it answered no. pslTrack.c then passed a size
multiplier of one to lfFromPslx and every block was drawn at a third of its
length at a mirrored position, which is the symptom the reverse complement was
added to prevent. The assignment is now the else branch of the same test.
hg/lib/tests/quickLiftTester.c covers this. It goes through the public
quickLiftPsl rather than the static function, builds its chains in memory in the
shape quickLiftSourceRanges leaves them, and needs no database. Six cases: a
protein over a same strand chain and over an opposite strand chain, a chain that
gaps only the reference, a chain that drops a source base and so splits a codon,
an mRNA over both chains, and an alignment with no chain under it. Each one runs
pslCheck2, which is what notices a strand that disagrees with the blocks. With
this fix backed out, only the opposite strand case changes and it reports three
errors placing the blocks outside the target range.
Found in the v504 code review, refs #38349.
refs #38249
- src/hg/lib/tests/sessionDataTester.c
- lines changed 140, context: html, text, full: html, text
51c0d44065340fbacb9f52bacc3b35e0a1456811 Wed Sep 16 09:06:46 2026 -0700
sessionData: a test for the memory contract of sessionDataSaveTrashFile
133df533c4d made sessionDataSaveTrashFile return kent-allocated memory, since
all three places that release its result do so through kent's own handler stack
and it was handing back a pointer from the system malloc. Nothing failed at the
time because the only program that reaches those release sites is hgSession,
which installs no memory handler. That is the whole guard, and it was written
down nowhere.
sessionDataTester installs the careful handler itself and runs the function
under it: it resolves a relative trash symlink, releases the result with
freeMem, allocates again and checks the heap, then compares the allocated block
count before and after so a leaked link target is caught too. The absolute
symlink and the expired-file cases run alongside. Reverting either half of
133df533c4d fails the test; the plain-file branch that calls moveAndLink is not
covered, since isTrashPath rejects a synthetic path with no trash dir
configured.
No database and no trash directory are needed, so the target runs ahead of
spDbTest and hdbTest in hg/lib/tests.
refs #38318
- src/hg/lib/tests/sessionDirTester.c
- lines changed 143, context: html, text, full: html, text
751a1f9fff1d6d77c2da690d1369dca64ba04fee Sat Sep 19 18:31:42 2026 -0700
sessionDirTester: pin how a saved session's data directory is named
A saved session's custom tracks and region files are moved to a durable
directory named from the user name and the session name. #10138 widened the
session half of that name from 8 hex characters to 10: 8 characters of md5 is
4 billion values, and the birthday arithmetic over hundreds of thousands of
sessions is not comfortable, since a collision puts one user's files in another
user's session.
Widening a name that is already on disk is the risky half. Directories written
before the change carry the old width and their files are still in use, so the
cleanup code has to be able to name both, which is why the width is a parameter
rather than a constant in the middle of the function.
The property pinned here is not the hash, it is that the short name is a PREFIX
of the long one. That is what lets code holding the new name find a directory
written under the old one, and it holds only because both come from the same
md5 truncated to different lengths. Also pinned: the two-character spreading
directory, the user name appearing as given, and the three calls that must
abort rather than invent a path -- a relative sessionDataDir, and a width of 0
or 33.
None of this is visible. A session whose directory is named differently does
not report an error, it comes back without its custom track.
Watched to fail and then pass: narrowing the width back to 8 turns it red on
the width line. Recorded as sandbox-ab in utils/testRegistry.
refs #10138, refs #38391
- src/hg/lib/tests/snapshotTypeTester.c
- lines changed 110, context: html, text, full: html, text
89f9ce7bc7c9333c45190074088f5bee377ca1d7 Sat Sep 19 18:30:26 2026 -0700
snapshotTypeTester: check the fast snapshotType reader against raFromString
A saved session is a snapshot when its settings carry a snapshotType line, and
the My Sessions listings hide those rows. #38313 replaced raFromString with a
walk over the lines, because the question is asked once per row in a listing
and the hash costs about 600ns and three allocations per session against about
30ns and none.
A hand written parser that has to agree with a general one is the shape of bug
found a year later, so this is a differential test: every case is read both
ways and the two answers are printed side by side. The claim in the code is
"same line semantics as raFromString", and that claim is what is checked rather
than a list of answers written down once. Reading the tag wrongly is invisible
either way: a snapshot is listed as an ordinary session, or an ordinary session
disappears from the listing, and both look like something the user did.
One case does not agree, and it is recorded rather than hidden. Given two
snapshotType lines the walk returns the first and raFromString returns the
last, because a hash overwrites. Real settings carry the tag once, so nothing
depends on it today, but it is a difference in the semantics the code says it
copies. It is marked as a known difference, and the test also fails if it ever
starts agreeing, so the note cannot go stale in the other direction.
Watched to fail and then pass: dropping the delimiter test after the tag makes
"snapshotTypeExtra view" read as the type "Extra view" while raFromString finds
none. Recorded as sandbox-ab in utils/testRegistry.
refs #38313, refs #38391
- src/hg/lib/tests/trashDirTester.c
- lines changed 144, context: html, text, full: html, text
859bc749b0593a83e1c8cd7149f956b620a24a73 Sat Sep 19 18:14:15 2026 -0700
trashDirTester: pin which file paths the cart accepts
hg/lib/cart.c screens every cart variable that names a server-made file through
these functions, so they decide whether a saved session still works. Both ways
of being wrong are invisible: a path wrongly refused brings the session back
without its custom track or its region list and says nothing, and a path
wrongly accepted says nothing either.
That is what #38303 cost. A check shipped in v503 discarded the saved region
list from 583 sessions on the RR and 66 on euro, and hgwdev, code review and
hgwbeta were all clean, because the corpus that shows it is only on the
production central.
Four rules pinned, each of which cost a bug or a review round: only the
configured directory is symlink-resolved and never the path from the cart; the
resolved spelling of that directory is accepted as well as the configured one,
since /userdata on the RR is a symlink and saved sessions hold both spellings;
only an absolute directory is resolved, because a relative one would be
resolved against the caller's working directory; and the acceptance runs one
direction only. pathIsUnderDir's own edges are here too, including the sibling
directory that merely starts the same way and the name that begins with "..".
The fixture is a directory, a symlink to it and three confs naming the same
place three ways, since hgConfig caches what it read and one process can only
answer for one spelling. Nothing machine-specific reaches the output.
Watched to fail and then pass: with the pre-#38303 code, which did not resolve
at all, the resolved spelling comes back refused and the diff is that one line.
Recorded as sandbox-ab in utils/testRegistry.
refs #38303, refs #37623, refs #38391
- src/hg/makeDb/doc/hg38/hprcPclai.txt
- lines changed 40, context: html, text, full: html, text
36b00fae56bc9de09200fd4fe5cfd07ddb4352d8 Wed Sep 16 12:40:10 2026 -0700
hprcPclai: back to dense, with denseClick on, refs #35415, refs #38364
This track was moved to squish a week ago and pinned there with
onlyVisibility, for one reason: dense drew one merged row per subtrack
and emitted no per-item map boxes at all, so there was no hgc link, no
mouseOver, and no way to reach the ancestry scatterplot on the details
page.
denseClick removes that reason. With it, every item on a dense row gets
its own map box, so it carries an hgc link and its own mouseOver while
still being drawn on the single dense row. Measured on a build of this
branch at chr2:60,000,000-80,000,000, the seven default-on haplotypes:
dense, denseClick off 0 hgc links
dense, denseClick on 1249 hgc links
squish 1235 hgc links
The rendered image does not change; only the image map does.
So dense is now the better mode for this data as well as the clickable
one. Dense is always exactly one row per haplotype, where squish spreads
to three or four at whole-chromosome zoom and gets noisy. onlyVisibility
moves to dense rather than going away: its real job is keeping a reader
out of pack, which at 463 subtracks would be enormous.
denseClick is inherited, so the single line on the composite covers every
subtrack, and hgTracks ignores a setting it does not understand, so the
line is inert rather than harmful on an older browser.
The same change goes into the GenArk contrib collection stanza. Worth
knowing about the timing there: hprc2annot is listed in betaGenArk.txt,
and hgwbeta runs the release branch, so that copy will show a dense row
with no clickable items until the hgTracks change reaches beta. The hg38
composite is alpha only and hgwdev CGIs are built from master, so it
picks the behavior up as soon as this lands. Neither copy is in
publicGenArk.txt, so no RR user sees either state.
hprcPclai.ra is generated, so the change is in hprcPclaiMakeTrackDb.py and
the .ra was rebuilt from the same index CSV; the regenerated file differs
only in those three lines.
- src/hg/makeDb/scripts/hprcPclai/hprcPclaiMakeTrackDb.py
- lines changed 12, context: html, text, full: html, text
36b00fae56bc9de09200fd4fe5cfd07ddb4352d8 Wed Sep 16 12:40:10 2026 -0700
hprcPclai: back to dense, with denseClick on, refs #35415, refs #38364
This track was moved to squish a week ago and pinned there with
onlyVisibility, for one reason: dense drew one merged row per subtrack
and emitted no per-item map boxes at all, so there was no hgc link, no
mouseOver, and no way to reach the ancestry scatterplot on the details
page.
denseClick removes that reason. With it, every item on a dense row gets
its own map box, so it carries an hgc link and its own mouseOver while
still being drawn on the single dense row. Measured on a build of this
branch at chr2:60,000,000-80,000,000, the seven default-on haplotypes:
dense, denseClick off 0 hgc links
dense, denseClick on 1249 hgc links
squish 1235 hgc links
The rendered image does not change; only the image map does.
So dense is now the better mode for this data as well as the clickable
one. Dense is always exactly one row per haplotype, where squish spreads
to three or four at whole-chromosome zoom and gets noisy. onlyVisibility
moves to dense rather than going away: its real job is keeping a reader
out of pack, which at 463 subtracks would be enormous.
denseClick is inherited, so the single line on the composite covers every
subtrack, and hgTracks ignores a setting it does not understand, so the
line is inert rather than harmful on an older browser.
The same change goes into the GenArk contrib collection stanza. Worth
knowing about the timing there: hprc2annot is listed in betaGenArk.txt,
and hgwbeta runs the release branch, so that copy will show a dense row
with no clickable items until the hgTracks change reaches beta. The hg38
composite is alpha only and hgwdev CGIs are built from master, so it
picks the behavior up as soon as this lands. Neither copy is in
publicGenArk.txt, so no RR user sees either state.
hprcPclai.ra is generated, so the change is in hprcPclaiMakeTrackDb.py and
the .ra was rebuilt from the same index CSV; the regenerated file differs
only in those three lines.
- src/hg/makeDb/trackDb/contrib/hprc2annot/hprc2annot.trackDb.txt
- lines changed 3, context: html, text, full: html, text
36b00fae56bc9de09200fd4fe5cfd07ddb4352d8 Wed Sep 16 12:40:10 2026 -0700
hprcPclai: back to dense, with denseClick on, refs #35415, refs #38364
This track was moved to squish a week ago and pinned there with
onlyVisibility, for one reason: dense drew one merged row per subtrack
and emitted no per-item map boxes at all, so there was no hgc link, no
mouseOver, and no way to reach the ancestry scatterplot on the details
page.
denseClick removes that reason. With it, every item on a dense row gets
its own map box, so it carries an hgc link and its own mouseOver while
still being drawn on the single dense row. Measured on a build of this
branch at chr2:60,000,000-80,000,000, the seven default-on haplotypes:
dense, denseClick off 0 hgc links
dense, denseClick on 1249 hgc links
squish 1235 hgc links
The rendered image does not change; only the image map does.
So dense is now the better mode for this data as well as the clickable
one. Dense is always exactly one row per haplotype, where squish spreads
to three or four at whole-chromosome zoom and gets noisy. onlyVisibility
moves to dense rather than going away: its real job is keeping a reader
out of pack, which at 463 subtracks would be enormous.
denseClick is inherited, so the single line on the composite covers every
subtrack, and hgTracks ignores a setting it does not understand, so the
line is inert rather than harmful on an older browser.
The same change goes into the GenArk contrib collection stanza. Worth
knowing about the timing there: hprc2annot is listed in betaGenArk.txt,
and hgwbeta runs the release branch, so that copy will show a dense row
with no clickable items until the hgTracks change reaches beta. The hg38
composite is alpha only and hgwdev CGIs are built from master, so it
picks the behavior up as soon as this lands. Neither copy is in
publicGenArk.txt, so no RR user sees either state.
hprcPclai.ra is generated, so the change is in hprcPclaiMakeTrackDb.py and
the .ra was rebuilt from the same index CSV; the regenerated file differs
only in those three lines.
- src/hg/makeDb/trackDb/human/hg38/hprcPclai.ra
- lines changed 3, context: html, text, full: html, text
36b00fae56bc9de09200fd4fe5cfd07ddb4352d8 Wed Sep 16 12:40:10 2026 -0700
hprcPclai: back to dense, with denseClick on, refs #35415, refs #38364
This track was moved to squish a week ago and pinned there with
onlyVisibility, for one reason: dense drew one merged row per subtrack
and emitted no per-item map boxes at all, so there was no hgc link, no
mouseOver, and no way to reach the ancestry scatterplot on the details
page.
denseClick removes that reason. With it, every item on a dense row gets
its own map box, so it carries an hgc link and its own mouseOver while
still being drawn on the single dense row. Measured on a build of this
branch at chr2:60,000,000-80,000,000, the seven default-on haplotypes:
dense, denseClick off 0 hgc links
dense, denseClick on 1249 hgc links
squish 1235 hgc links
The rendered image does not change; only the image map does.
So dense is now the better mode for this data as well as the clickable
one. Dense is always exactly one row per haplotype, where squish spreads
to three or four at whole-chromosome zoom and gets noisy. onlyVisibility
moves to dense rather than going away: its real job is keeping a reader
out of pack, which at 463 subtracks would be enormous.
denseClick is inherited, so the single line on the composite covers every
subtrack, and hgTracks ignores a setting it does not understand, so the
line is inert rather than harmful on an older browser.
The same change goes into the GenArk contrib collection stanza. Worth
knowing about the timing there: hprc2annot is listed in betaGenArk.txt,
and hgwbeta runs the release branch, so that copy will show a dense row
with no clickable items until the hgTracks change reaches beta. The hg38
composite is alpha only and hgwdev CGIs are built from master, so it
picks the behavior up as soon as this lands. Neither copy is in
publicGenArk.txt, so no RR user sees either state.
hprcPclai.ra is generated, so the change is in hprcPclaiMakeTrackDb.py and
the .ra was rebuilt from the same index CSV; the regenerated file differs
only in those three lines.
- src/hg/makeDb/trackDb/tagTypes.tab
- lines changed 1, context: html, text, full: html, text
98255f58460415345af88e45ad233599740585e5 Wed Sep 16 11:44:41 2026 -0700
trackDb docs for the denseClick setting, refs #38364
Documents the setting added in the previous commit, in the five places a
new trackDb statement has to appear: tagTypes.tab, trackDbLibrary.shtml,
trackDbDoc.html, trackDbHub.v3.html (level-new, since it works in hubs)
and changes.html.
The type list is bed, bigBed, genePred, bigGenePred, psl and bigPsl,
which is the same list decorator carries and matches what the code
reaches: the setting hooks genericDrawItemsFullDense, so it applies to
anything drawn through the linked-features path. Each type was checked
by hand on hg38 in dense with the setting on, counting details links in
the image map: ccdsGene, mrna, mrnaBig and knownGene all gained one link
per item.
The blurb says what happens when several items share a pixel, which is
that the first one wins, and that a row drawn from summary data rather
than from items is unaffected. That last case is real: linkedFeaturesDraw
calls bigBedDrawDense when tg->items is NULL, so a zoomed-out bigBed never
reaches this code and has nothing to link.
Verified with "make settings", which parses the blurb cleanly, and with
hubCheck -settings against the sandbox copy of trackDbHub.v3.html, which
reports "denseClick new" and no errors.
Regenerating trackDbSettings.yaml and .json also picks up minAc,
vcfDoMinAc and vcfPhasedColorBy, which were documented on 2026-09-09
without rebuilding the generated files. Nothing is removed.
- src/hg/utils/chainToBigChain/chainToBigChain.c
- lines changed 48, context: html, text, full: html, text
72327e4e2d294b9d2fcb6cbdadd4e628c006345b Fri Sep 18 10:07:40 2026 -0700
bigChain: move the chain to bigChain conversion into the library
chainRecToBigChain() and chainBlockToBigLink() sat in chainToBigChain.c
next to its main(), so a CGI could not link against them. Move both into
hg/lib/bigChain.c, add chainToBigChainOne() for one chain and
chainToBigChainList() for a list, and leave the utility as a thin main().
No behavior change; the chainToBigChain test output is unchanged.
refs #38382
- src/hg/utils/docent/README.md
- lines changed 1, context: html, text, full: html, text
7e89607805cac22b52143b23a45464759e66a957 Wed Sep 16 12:36:15 2026 -0700
docent: a login: step, with the account kept per hgcentral, refs #37892
hgCollection refuses a visitor who is not signed in -- hgCollection.c doMiddle,
"You must be logged in to edit collections" -- and so does the saving half of
hgSession. The suite has never had a logged-in page, and until now could not:
the login cookie is validated against a salted hash (login.cookieSalt,
hg/lib/wikiLink.c), so there is no cookie to hand the browser. A script that
needs one of those pages has to sign in the way a person does.
`login:` does that, through hgLogin's own form, and it takes no credentials and
cannot be given any. They come from ~/.docentLogin (DOCENT_LOGIN_FILE overrides,
DOCENT_LOGIN_USER + DOCENT_LOGIN_PASSWORD override both for one run), which is
refused unless it is mode 0600 -- the rule hg/lib/hgConfig.c applies to hg.conf,
for the same reason. Nothing prints a password.
THE FILE IS KEYED BY HGCENTRAL DATABASE, not by server. An account is a row in
gbMembers in one central, the way a named session is: genome-test, hgwdev, every
hgwdev-<name> sandbox and every ticket park read hgcentraltest and share one
account, while hgwbeta reads hgcentralbeta and the RR reads hgcentral. So the
file is one [hgcentraltest] section rather than a section per sandbox.
Which central a server reads is READ from its hg.conf, following its includes the
way hgConfig.c does, and not guessed from the host -- because a sandbox can point
itself somewhere else and two on hgwdev do today: of the personal confs there, 45
set central.db=hgcentraltest, one sets hgcentralgsid and one hgcentralbeta. A
server whose conf is on another machine falls back to a small table (the RR, the
two mirrors, hgwbeta), and [default] catches the rest. A run redirected with
DOCENT_TARGET looks up the server it is really driving.
Two failures the step has to tell apart, and both cost a run to find:
A WRONG PASSWORD IS A PERFECTLY GOOD PAGE. hgLogin answers one by drawing the
same form again with a red message, so a step that just navigated on would leave
every later step running logged out and the failure would surface somewhere else
entirely. The step fails on #accountLoginForm still being there, and quotes what
the page said.
A RIGHT PASSWORD ARRIVES MID-REDIRECT. hgLogin answers one with a page that
navigates ITSELF a moment later: returnToURL(150) at hgLogin.c:1160 writes
setTimeout(function(){location=...}, 150). Returning while that timer is pending
means the next step's goto: races it and the browser aborts one of the two, which
arrives as a bare net::ERR_ABORTED on a URL that is completely fine. The step now
waits for that redirect to land. The failure path is checked first, since that
page never leaves hgLogin and there is no redirect to wait for.
preflight reports the account as a fixture -- which central it resolved, which
section it came from, and why it is unusable if it is -- so a missing password is
caught before the browser starts. It attempts no login: a wrong password fails
loudly at the step itself, which is the one thing preflight cannot do for it.
The hg.conf reader is now in both docent.js and tests/preflight.js, beside the
resolveTarget each of them already carries. Both say to keep the other in step.
If that second copy is a copy too many, the two of them want a shared module.
- lines changed 7, context: html, text, full: html, text
9b762c146f7a44a3bdc783cdd202356fc163b8fb Wed Sep 16 12:43:32 2026 -0700
docent: one targetConf.js for the target, the hg.conf, the central and the account, refs #37892
docent.js and tests/preflight.js had grown a second and then a third copy of the
same lookups. That is exactly the pair that must not drift: preflight checks the
fixtures for the server the RUN will drive, so a run that resolved its target, its
hg.conf, its hgcentral or its account even slightly differently would be checked
against the wrong machine, and the mismatch would show up as a green preflight in
front of a red suite.
targetConf.js answers the four questions in order, each from the one before:
resolveTarget a `target:` (or DOCENT_TARGET) -> the .../cgi-bin URL to drive
hgConfFor that URL -> the hg.conf it reads, if the server is on this box
centralDbFor that conf -> which hgcentral it uses
loginLookup that central -> the account to sign in with
Nothing in it opens a browser or the network, which is why preflight can ask all
four in the seconds before a run.
loginLookup returns the facts plus, when the account cannot be used, ONE sentence
saying why. That sentence is the substantive half and is now written once: the
step throws it with a `login:` prefix, preflight prints it on the MISSING line.
Each caller still phrases its own success line, since one logs and the other
prints a fixture row. No password crosses that boundary to anything that prints.
248 lines net out of the two programs, 197 into the module.
docent.js is no longer a single file, and three places now say so: its own require,
the Run section of README.md, and docent.mk, whose mp4 rule gains targetConf.js as
a prerequisite -- a change there changes what a tour renders, so it has to rebuild
one. Nothing in the tree or in ~/docentTours copies docent.js; they all reference
it where it sits, with targetConf.js beside it.
Measured before and after, with no other change: preflight resolves the same
account, central and conf for genome-test, hgwdev-braney, a ts park on 48087 and
hgwbeta (which correctly has no section); tests/ is 18 of 18 with the derive
baselines matching; tests/regress preflights 14 fixtures for 67 scripts.
- lines changed 35, context: html, text, full: html, text
b4e78d426dcdb47a20f1979025d5a0969ea79ac4 Thu Sep 17 17:07:49 2026 -0700
docent: a box: check for where an element sits, and lists for text:/noText:, refs #37892
`expect:` could say what was in a page and never where it was on the screen.
has:/noHas: take a CSS selector, which describes the tree; color: reads pixels
but only inside a track's row. #38251 moved the narrow-window menu icon out of
the blue bar with every selector still matching and every word of the page still
there, and nothing in the language could ask about it.
box: takes `inside:` (every edge within another element's box, with `tolerance:`
px of slack), `clear:` (no overlap with anything a selector matches, `gap:` for a
minimum separation) and `height:`/`width:`. Every element `sel:` matches has to
satisfy every clause, so {sel: "ul.nice-menu > li", inside: "#main-menu-whole"}
reads as "every menu item is in the bar". Boxes are read in document
coordinates; an element with no box at all is skipped rather than treated as a
zero-sized box at the origin, which would sit "inside" anything. A failure
prints the measurement:
#topRightLinks is not inside #main-menu-whole: 114px above it
-- it is at 666,0 34x32, #main-menu-whole at 0,114 1000x32
The image height: and box's own height:/width: now share one cmpSize(), so the
two cannot drift into different comparison grammars.
text: and noText: take a list, the way rows:, has: and noHas: always did. They
have to: a list handed to a check that stringifies its argument fails OPEN --
["a", "b"] becomes "a,b", which no page contains, so it passes on anything, and
passes silently. Six scripts in one batch were written that way and all six
looked green.
pagechecks and its .xfail twin cover both, the xfail with one entry aimed wrongly
and one aimed rightly in each list, so it fails only if every entry is really
looked at on its own.
- lines changed 4, context: html, text, full: html, text
4265f36510c9498df6d7b0a8ff9e5251350c133c Sun Sep 20 14:34:09 2026 -0700
docent: read a graph's tooltip, and noTip: for a bare number, refs #37892
hgTracks has two tooltips and their ids differ only in the case of one letter.
hg/js/utils.js hangs an ITEM's tooltip off `#mouseoverContainer`: the text of a
map box's title, an rsID or a gene name. A WIGGLE reports itself the other way.
The `mouseOver` module in hg/js/hgTracks.js writes the value under the cursor
into `#mouseOverText`, read from the per-pixel spans hgTracks leaves in a trash
.json. A track drawn as a coverage graph has no map boxes at all, so its numbers
exist only in the second one, and `tip:` on such a track read an empty string and
then waited out its timeout. Every reader of the live tooltip now takes whichever
is up: `tip:`, the `mouseover:` waits, `pinShot:` and the shot clip.
Two more from the same mistake. `mouseover: {value: ...}` is documented for
wiggles and had never matched anything on any track: it looked in
`window.mapData.spans[...]` for a member called `value`, which is hg/js/mouseOver.js,
an older copy of the module the page does not load, and the member there is `v`
as well. It now reads `mouseOver.items[...]` and places the cursor from
`td_data_<track>`, which is what hgTracks.js itself compares the cursor against.
And asking by value now skips the map boxes entirely, because a track's own center
label is titled "Click to alter the display density of <track>": a probe for the
value 3 hovered the center label of a track called rm38253stairs before any span
was looked at.
`noTip:` is new. `tip:` is a substring test, which is right for an item, whose
tooltip is markup and whose tail can render differently from the title it came
from. It is wrong for a graph, whose tooltip is the number and nothing else:
`tip: "1"` is also satisfied by "1.5" and by "13", and a mean computed with the
wrong divisor is exactly the fraction that would slip through. Naming the other
digits and the decimal point leaves one number. This is the prefix trap #38279
hit with two messages sharing a head, in a place with no closing paren to carry
the delimiter.
- src/hg/utils/docent/docent.js
- lines changed 5, context: html, text, full: html, text
cad0600bd259bae35de7b39e49c2f95af8b624ca Mon Sep 14 16:14:40 2026 -0700
docent: point a whole test directory at another server with TARGET, refs #37892
A script says where it runs with `target:`, and until now that was the only way
to say it, so trying a suite against a branch build meant editing every script in
the directory. DOCENT_TARGET overrides `target:` for the run, and docentTest.mk
turns a TARGET= variable into it for preflight, test, parity and derive:
make test TARGET=hgwdev-demo9
make preflight TARGET=hgwdev-demo9
It takes the same values `target:` does -- a shorthand, a bare hgwdev-<name>
sandbox or demo, or a full .../cgi-bin URL -- so a ts park works too.
preflight.js reads the same variable, so the fixture check names the server that
will actually be driven rather than the one the scripts name. The trackDb cache
already keys on the resolved server, so a redirected run cannot read back a
listing fetched from somewhere else.
The committed scripts keep their own `target:`. Redirecting is for trying a
suite elsewhere, not for moving it: the nightly reads what is in the file. Both
READMEs say so, and say to read a redirected failure with the other server's
trackDb in mind, since a script asserts what its own server draws.
Verified against the ten methbase scripts: all ten pass with
TARGET=hgwdev-demo9, and mbMouse still passes with no TARGET, against the RR.
- lines changed 179, context: html, text, full: html, text
7e89607805cac22b52143b23a45464759e66a957 Wed Sep 16 12:36:15 2026 -0700
docent: a login: step, with the account kept per hgcentral, refs #37892
hgCollection refuses a visitor who is not signed in -- hgCollection.c doMiddle,
"You must be logged in to edit collections" -- and so does the saving half of
hgSession. The suite has never had a logged-in page, and until now could not:
the login cookie is validated against a salted hash (login.cookieSalt,
hg/lib/wikiLink.c), so there is no cookie to hand the browser. A script that
needs one of those pages has to sign in the way a person does.
`login:` does that, through hgLogin's own form, and it takes no credentials and
cannot be given any. They come from ~/.docentLogin (DOCENT_LOGIN_FILE overrides,
DOCENT_LOGIN_USER + DOCENT_LOGIN_PASSWORD override both for one run), which is
refused unless it is mode 0600 -- the rule hg/lib/hgConfig.c applies to hg.conf,
for the same reason. Nothing prints a password.
THE FILE IS KEYED BY HGCENTRAL DATABASE, not by server. An account is a row in
gbMembers in one central, the way a named session is: genome-test, hgwdev, every
hgwdev-<name> sandbox and every ticket park read hgcentraltest and share one
account, while hgwbeta reads hgcentralbeta and the RR reads hgcentral. So the
file is one [hgcentraltest] section rather than a section per sandbox.
Which central a server reads is READ from its hg.conf, following its includes the
way hgConfig.c does, and not guessed from the host -- because a sandbox can point
itself somewhere else and two on hgwdev do today: of the personal confs there, 45
set central.db=hgcentraltest, one sets hgcentralgsid and one hgcentralbeta. A
server whose conf is on another machine falls back to a small table (the RR, the
two mirrors, hgwbeta), and [default] catches the rest. A run redirected with
DOCENT_TARGET looks up the server it is really driving.
Two failures the step has to tell apart, and both cost a run to find:
A WRONG PASSWORD IS A PERFECTLY GOOD PAGE. hgLogin answers one by drawing the
same form again with a red message, so a step that just navigated on would leave
every later step running logged out and the failure would surface somewhere else
entirely. The step fails on #accountLoginForm still being there, and quotes what
the page said.
A RIGHT PASSWORD ARRIVES MID-REDIRECT. hgLogin answers one with a page that
navigates ITSELF a moment later: returnToURL(150) at hgLogin.c:1160 writes
setTimeout(function(){location=...}, 150). Returning while that timer is pending
means the next step's goto: races it and the browser aborts one of the two, which
arrives as a bare net::ERR_ABORTED on a URL that is completely fine. The step now
waits for that redirect to land. The failure path is checked first, since that
page never leaves hgLogin and there is no redirect to wait for.
preflight reports the account as a fixture -- which central it resolved, which
section it came from, and why it is unusable if it is -- so a missing password is
caught before the browser starts. It attempts no login: a wrong password fails
loudly at the step itself, which is the one thing preflight cannot do for it.
The hg.conf reader is now in both docent.js and tests/preflight.js, beside the
resolveTarget each of them already carries. Both say to keep the other in step.
If that second copy is a copy too many, the two of them want a shared module.
- lines changed 157, context: html, text, full: html, text
9b762c146f7a44a3bdc783cdd202356fc163b8fb Wed Sep 16 12:43:32 2026 -0700
docent: one targetConf.js for the target, the hg.conf, the central and the account, refs #37892
docent.js and tests/preflight.js had grown a second and then a third copy of the
same lookups. That is exactly the pair that must not drift: preflight checks the
fixtures for the server the RUN will drive, so a run that resolved its target, its
hg.conf, its hgcentral or its account even slightly differently would be checked
against the wrong machine, and the mismatch would show up as a green preflight in
front of a red suite.
targetConf.js answers the four questions in order, each from the one before:
resolveTarget a `target:` (or DOCENT_TARGET) -> the .../cgi-bin URL to drive
hgConfFor that URL -> the hg.conf it reads, if the server is on this box
centralDbFor that conf -> which hgcentral it uses
loginLookup that central -> the account to sign in with
Nothing in it opens a browser or the network, which is why preflight can ask all
four in the seconds before a run.
loginLookup returns the facts plus, when the account cannot be used, ONE sentence
saying why. That sentence is the substantive half and is now written once: the
step throws it with a `login:` prefix, preflight prints it on the MISSING line.
Each caller still phrases its own success line, since one logs and the other
prints a fixture row. No password crosses that boundary to anything that prints.
248 lines net out of the two programs, 197 into the module.
docent.js is no longer a single file, and three places now say so: its own require,
the Run section of README.md, and docent.mk, whose mp4 rule gains targetConf.js as
a prerequisite -- a change there changes what a tour renders, so it has to rebuild
one. Nothing in the tree or in ~/docentTours copies docent.js; they all reference
it where it sits, with targetConf.js beside it.
Measured before and after, with no other change: preflight resolves the same
account, central and conf for genome-test, hgwdev-braney, a ts park on 48087 and
hgwbeta (which correctly has no section); tests/ is 18 of 18 with the derive
baselines matching; tests/regress preflights 14 fixtures for 67 scripts.
- lines changed 145, context: html, text, full: html, text
b4e78d426dcdb47a20f1979025d5a0969ea79ac4 Thu Sep 17 17:07:49 2026 -0700
docent: a box: check for where an element sits, and lists for text:/noText:, refs #37892
`expect:` could say what was in a page and never where it was on the screen.
has:/noHas: take a CSS selector, which describes the tree; color: reads pixels
but only inside a track's row. #38251 moved the narrow-window menu icon out of
the blue bar with every selector still matching and every word of the page still
there, and nothing in the language could ask about it.
box: takes `inside:` (every edge within another element's box, with `tolerance:`
px of slack), `clear:` (no overlap with anything a selector matches, `gap:` for a
minimum separation) and `height:`/`width:`. Every element `sel:` matches has to
satisfy every clause, so {sel: "ul.nice-menu > li", inside: "#main-menu-whole"}
reads as "every menu item is in the bar". Boxes are read in document
coordinates; an element with no box at all is skipped rather than treated as a
zero-sized box at the origin, which would sit "inside" anything. A failure
prints the measurement:
#topRightLinks is not inside #main-menu-whole: 114px above it
-- it is at 666,0 34x32, #main-menu-whole at 0,114 1000x32
The image height: and box's own height:/width: now share one cmpSize(), so the
two cannot drift into different comparison grammars.
text: and noText: take a list, the way rows:, has: and noHas: always did. They
have to: a list handed to a check that stringifies its argument fails OPEN --
["a", "b"] becomes "a,b", which no page contains, so it passes on anything, and
passes silently. Six scripts in one batch were written that way and all six
looked green.
pagechecks and its .xfail twin cover both, the xfail with one entry aimed wrongly
and one aimed rightly in each list, so it fails only if every entry is really
looked at on its own.
- lines changed 40, context: html, text, full: html, text
7603e0192dd9fdf257f0a57b500d4e936cd42e93 Sat Sep 19 09:45:41 2026 -0700
docent: drop the one-frame screenshot artifact from a recorded tour, refs #37892 #38364
A shot: taken while the video is recording can leave one bad frame in the mp4,
the track image painted on a grey, unpainted page, because Playwright's
screenshot captures from the same surface the recorder reads. It is a race:
four renders of one script gave 2, 1, 1 and 0 of them, and a sweep of the 46
finished tours under ~/docentTours found the frame in 24, 33 frames in all.
Capturing through CDP instead does keep the recorder out of it, but Chromium
then ignores the clip and answers with the whole viewport, so every still would
need cropping and a taller-than-viewport image could not be captured at all.
Preferring page.screenshot({clip}) over an element screenshot does not help
either, and shifts the still by a pixel in each dimension. Both measured.
So the frame is dropped in the transcode that was going to happen anyway: the
time of each shot is remembered, the webm is scanned once for a frame more than
20 luma darker than both its neighbours, and only a dip within half a second of
a shot is cut. One encode, stills untouched, and a tour with no artifact runs
exactly the command it ran before. The shot-time gate is what makes it safe --
an ordinary dark frame in a tour is never next to a capture.
Measured: the #38364 tour twice, found and dropped at 3.68s and 3.72s, mp4
clean afterwards, and its three stills byte-identical to the stock renderer's.
FAST mode is untouched, since it returns before the transcode.
- lines changed 98, context: html, text, full: html, text
4265f36510c9498df6d7b0a8ff9e5251350c133c Sun Sep 20 14:34:09 2026 -0700
docent: read a graph's tooltip, and noTip: for a bare number, refs #37892
hgTracks has two tooltips and their ids differ only in the case of one letter.
hg/js/utils.js hangs an ITEM's tooltip off `#mouseoverContainer`: the text of a
map box's title, an rsID or a gene name. A WIGGLE reports itself the other way.
The `mouseOver` module in hg/js/hgTracks.js writes the value under the cursor
into `#mouseOverText`, read from the per-pixel spans hgTracks leaves in a trash
.json. A track drawn as a coverage graph has no map boxes at all, so its numbers
exist only in the second one, and `tip:` on such a track read an empty string and
then waited out its timeout. Every reader of the live tooltip now takes whichever
is up: `tip:`, the `mouseover:` waits, `pinShot:` and the shot clip.
Two more from the same mistake. `mouseover: {value: ...}` is documented for
wiggles and had never matched anything on any track: it looked in
`window.mapData.spans[...]` for a member called `value`, which is hg/js/mouseOver.js,
an older copy of the module the page does not load, and the member there is `v`
as well. It now reads `mouseOver.items[...]` and places the cursor from
`td_data_<track>`, which is what hgTracks.js itself compares the cursor against.
And asking by value now skips the map boxes entirely, because a track's own center
label is titled "Click to alter the display density of <track>": a probe for the
value 3 hovered the center label of a track called rm38253stairs before any span
was looked at.
`noTip:` is new. `tip:` is a substring test, which is right for an item, whose
tooltip is markup and whose tail can render differently from the title it came
from. It is wrong for a graph, whose tooltip is the number and nothing else:
`tip: "1"` is also satisfied by "1.5" and by "13", and a mean computed with the
wrong divisor is exactly the fraction that would slip through. Naming the other
digits and the decimal point leaves one number. This is the prefix trap #38279
hit with two messages sharing a head, in a place with no closing paren to carry
the delimiter.
- src/hg/utils/docent/docent.mk
- lines changed 4, context: html, text, full: html, text
9b762c146f7a44a3bdc783cdd202356fc163b8fb Wed Sep 16 12:43:32 2026 -0700
docent: one targetConf.js for the target, the hg.conf, the central and the account, refs #37892
docent.js and tests/preflight.js had grown a second and then a third copy of the
same lookups. That is exactly the pair that must not drift: preflight checks the
fixtures for the server the RUN will drive, so a run that resolved its target, its
hg.conf, its hgcentral or its account even slightly differently would be checked
against the wrong machine, and the mismatch would show up as a green preflight in
front of a red suite.
targetConf.js answers the four questions in order, each from the one before:
resolveTarget a `target:` (or DOCENT_TARGET) -> the .../cgi-bin URL to drive
hgConfFor that URL -> the hg.conf it reads, if the server is on this box
centralDbFor that conf -> which hgcentral it uses
loginLookup that central -> the account to sign in with
Nothing in it opens a browser or the network, which is why preflight can ask all
four in the seconds before a run.
loginLookup returns the facts plus, when the account cannot be used, ONE sentence
saying why. That sentence is the substantive half and is now written once: the
step throws it with a `login:` prefix, preflight prints it on the MISSING line.
Each caller still phrases its own success line, since one logs and the other
prints a fixture row. No password crosses that boundary to anything that prints.
248 lines net out of the two programs, 197 into the module.
docent.js is no longer a single file, and three places now say so: its own require,
the Run section of README.md, and docent.mk, whose mp4 rule gains targetConf.js as
a prerequisite -- a change there changes what a tour renders, so it has to rebuild
one. Nothing in the tree or in ~/docentTours copies docent.js; they all reference
it where it sits, with targetConf.js beside it.
Measured before and after, with no other change: preflight resolves the same
account, central and conf for genome-test, hgwdev-braney, a ts park on 48087 and
hgwbeta (which correctly has no section); tests/ is 18 of 18 with the derive
baselines matching; tests/regress preflights 14 fixtures for 67 scripts.
- lines changed 4, context: html, text, full: html, text
e9253ccecb8b2bbfe42f0d1e77b1db7e2a50642e Sat Sep 19 14:10:28 2026 -0700
docent: let FIGDIR really decide where an mp4 lands, refs #37892
docent.mk documents FIGDIR as an override for where videos go, and make looks
for its target there, but the recipe ran `node docent.js <script>` with no
output path, so docent.js fell back to its own default: the script directory's
parent. Make then never saw the file it was waiting for, and rebuilt every
time.
It matters now because the tours moved to the genecats repository while their
output stays in ~/docentTours. Without this the video lands next to the scripts,
inside the repo.
docent.js has taken the path as its third argument all along; the recipe just
never passed it.
- src/hg/utils/docent/targetConf.js
- lines changed 197, context: html, text, full: html, text
9b762c146f7a44a3bdc783cdd202356fc163b8fb Wed Sep 16 12:43:32 2026 -0700
docent: one targetConf.js for the target, the hg.conf, the central and the account, refs #37892
docent.js and tests/preflight.js had grown a second and then a third copy of the
same lookups. That is exactly the pair that must not drift: preflight checks the
fixtures for the server the RUN will drive, so a run that resolved its target, its
hg.conf, its hgcentral or its account even slightly differently would be checked
against the wrong machine, and the mismatch would show up as a green preflight in
front of a red suite.
targetConf.js answers the four questions in order, each from the one before:
resolveTarget a `target:` (or DOCENT_TARGET) -> the .../cgi-bin URL to drive
hgConfFor that URL -> the hg.conf it reads, if the server is on this box
centralDbFor that conf -> which hgcentral it uses
loginLookup that central -> the account to sign in with
Nothing in it opens a browser or the network, which is why preflight can ask all
four in the seconds before a run.
loginLookup returns the facts plus, when the account cannot be used, ONE sentence
saying why. That sentence is the substantive half and is now written once: the
step throws it with a `login:` prefix, preflight prints it on the MISSING line.
Each caller still phrases its own success line, since one logs and the other
prints a fixture row. No password crosses that boundary to anything that prints.
248 lines net out of the two programs, 197 into the module.
docent.js is no longer a single file, and three places now say so: its own require,
the Run section of README.md, and docent.mk, whose mp4 rule gains targetConf.js as
a prerequisite -- a change there changes what a tour renders, so it has to rebuild
one. Nothing in the tree or in ~/docentTours copies docent.js; they all reference
it where it sits, with targetConf.js beside it.
Measured before and after, with no other change: preflight resolves the same
account, central and conf for genome-test, hgwdev-braney, a ts park on 48087 and
hgwbeta (which correctly has no section); tests/ is 18 of 18 with the derive
baselines matching; tests/regress preflights 14 fixtures for 67 scripts.
- src/hg/utils/docent/tests/README.txt
- lines changed 17, context: html, text, full: html, text
cad0600bd259bae35de7b39e49c2f95af8b624ca Mon Sep 14 16:14:40 2026 -0700
docent: point a whole test directory at another server with TARGET, refs #37892
A script says where it runs with `target:`, and until now that was the only way
to say it, so trying a suite against a branch build meant editing every script in
the directory. DOCENT_TARGET overrides `target:` for the run, and docentTest.mk
turns a TARGET= variable into it for preflight, test, parity and derive:
make test TARGET=hgwdev-demo9
make preflight TARGET=hgwdev-demo9
It takes the same values `target:` does -- a shorthand, a bare hgwdev-<name>
sandbox or demo, or a full .../cgi-bin URL -- so a ts park works too.
preflight.js reads the same variable, so the fixture check names the server that
will actually be driven rather than the one the scripts name. The trackDb cache
already keys on the resolved server, so a redirected run cannot read back a
listing fetched from somewhere else.
The committed scripts keep their own `target:`. Redirecting is for trying a
suite elsewhere, not for moving it: the nightly reads what is in the file. Both
READMEs say so, and say to read a redirected failure with the other server's
trackDb in mind, since a script asserts what its own server draws.
Verified against the ten methbase scripts: all ten pass with
TARGET=hgwdev-demo9, and mbMouse still passes with no TARGET, against the RR.
- lines changed 24, context: html, text, full: html, text
d08323bb2ff524e4964a0922ecfb8336ab662007 Wed Sep 16 10:25:56 2026 -0700
docent: two tests for gaps a cart-visibility branch went past, refs #37892
The #37547 branch broke quickLift and nine scripts in tests/regress caught it
without help. Two other things went past the whole suite, and these are the
tests for them.
heavysession is selftest on a cart with weight behind it. selftest saves a
session and loads it back, which is the right shape, but the cart it round-trips
holds two rows. Saving a cart is not a copy of it: outIfNotPresent() in
hg/hgSession/hgSession.c writes a trackDb default for every track that is
deliberately NOT in the cart, so the file says what is hidden as well as what is
shown, and a two-track cart barely reaches that code. A save-and-reload path
that returned a 38-row clinical session as 34 rows left selftest green.
The weight comes from a Recommended Track Set, which is where a clinical user
starts: View/Clinical_SNVs_hg38, out of
DOCUMENT_ROOT/data/recTrackSets/recTrackSets.hg38.tab. It draws 33 tracks and
the ruler, and the file the session: step writes out of that cart is 741
settings, 248 of them visibilities and 154 of those hide. Both halves of the
trip assert the row set with exact: true, because rows: alone would pass on a
reload that lost four of them, and a count cannot say which row went missing.
It is a saved session on the server, so make preflight already checks it is
still there -- a deleted one answers 200 with a page that has no track image, on
which every noText: check passes.
firstrequest is about a bug that lags by exactly one request: the visibility
reaches the cart, the image drawn in reply does not carry the row, and the next
request draws it. A script shaped track: -> go: -> expect: supplies that extra
request itself and passes on the broken build. So this one asserts with no
go:, open: or convert: between the track: step and the check.
Which track it names is the other half, and it is not free choice. A top-level
track passes on a build with the bug, because hgTracks adds every top-level
track as a lightweight stub so the track controls can list it -- microsat,
gtexGene and windowmaskerSdust all drew. A default-visible child passes too,
because its container is in the list already: wgEncodeRegMarkH3k27ac drew while
its sibling wgEncodeRegMarkH3k4me1 did not, same superTrack and same request.
So the script names wgEncodeRegMarkH3k4me1, which is visibility hide under a
superTrack that is itself superTrack on hide, and the hideKids step before it is
what stops the other members coming back at their own trackDb visibility.
expected/firstrequest.derive is committed with it, and it is not decoration.
The test only means anything while the step under test is ONE round:
step 5 track {"wgEncodeRegMarkH3k4me1":"full"}
round 1 (2 vars): wgEncodeRegMarkH3k4me1=full wgEncodeReg=show
If Docent ever splits that the way it splits a container-plus-subtrack-hide, the
browser test would go on passing and stop being able to see the bug. The
baseline says so out loud.
README.txt describes both, and adds hgCollection to "Still to write": no script
in either directory reaches that CGI, and hg/hgCollection/hgCollection.c carries
its own verbatim copy of isParentVisible() from hg/lib/trackHub.c. Nine scripts
caught the trackHub.c copy on the branch; nothing caught this one. Covering it
needs a collection: verb, since tracks go into a collection by dragging between
two jsTrees and drag: is the genomic drag-select on the track image.
Seventeen of seventeen pass in tests/, including the four xfails.
- lines changed 27, context: html, text, full: html, text
3d98068ead92a95ea4b714f31f01119100a3c099 Wed Sep 16 10:26:18 2026 -0700
docent: preflight prints how the target is configured, refs #37892
make test TARGET=hgwdev-you points the whole directory at another server, and a
red script there can be that machine's configuration rather than a bug. A
different curatedHubPrefix genuinely changes what a quickLift hop produces, and
a db.trackDb with a private table in front of the shared one changes what
exact: true counts. Both failures look exactly like a bug. The README already
warned about it, in prose, which arrives after someone has spent an hour.
make preflight now prints the settings that decide it, so a redirected run
carries its own explanation in the log:
target https://hgwdev-braney.gi.ucsc.edu/cgi-bin
/usr/local/apache/cgi-bin-braney/hg.conf
central.db hgcentraltest
db.trackDb trackDb_braney,trackDb
curatedHubPrefix braney
browser.quickLift on
browser.quickLiftAlignments on
browser.recTrackSets on
central.db is on the list because preflight already checks named sessions and
that setting says which hgcentral it looked in.
The value printed is the EFFECTIVE one. The reader follows include and delete
the way hg/lib/hgConfig.c does, with a later assignment winning over an earlier
one, so a sandbox conf that sets nothing still shows what it inherits from the
shared conf it includes. Reading cgi-bin-braney/hg.conf on its own says
browser.quickLiftAlignments is unset; the CGI there sees it on, from the
include on line 2. A ts park is the mirror case: 37547's frozen conf sets
db.trackDb twice and the second one, 114 lines later, wins.
Only the six keys in HG_CONF_KEYS are ever printed. The includes lead to
hg.conf.private, which holds database passwords, so the reader parses whatever
it is pointed at and prints nothing off that list.
There is no way to ask a browser over http what its hg.conf says, so which file
to read is a lookup by convention: genome-test and hgwdev read
/usr/local/apache/cgi-bin/hg.conf, an hgwdev-<name> sandbox or demo reads
cgi-bin-<name>, and a ts park on 127.0.0.1 is found by port in its ports.tsv.
Anything off this machine -- hgwbeta, the RR -- says the conf cannot be read
from here, which is true and better than a guess.
Even with that in the log, a config difference and a code difference can still
look alike. The reliable way to tell them apart is to swap only the binary:
drop a control build's CGIs into the same sandbox, leave its hg.conf alone, and
re-run. If the failures follow the binary they are the code. That experiment
is what turned nine plausible failures on the #37547 branch into nine proven
ones, and both READMEs now say so.
Verified against all three shapes: genome-test, hgwdev-braney, hgwdev-demo9,
and the #37547 park on 127.0.0.1:48087. Both test directories preflight clean.
- lines changed 12, context: html, text, full: html, text
7e89607805cac22b52143b23a45464759e66a957 Wed Sep 16 12:36:15 2026 -0700
docent: a login: step, with the account kept per hgcentral, refs #37892
hgCollection refuses a visitor who is not signed in -- hgCollection.c doMiddle,
"You must be logged in to edit collections" -- and so does the saving half of
hgSession. The suite has never had a logged-in page, and until now could not:
the login cookie is validated against a salted hash (login.cookieSalt,
hg/lib/wikiLink.c), so there is no cookie to hand the browser. A script that
needs one of those pages has to sign in the way a person does.
`login:` does that, through hgLogin's own form, and it takes no credentials and
cannot be given any. They come from ~/.docentLogin (DOCENT_LOGIN_FILE overrides,
DOCENT_LOGIN_USER + DOCENT_LOGIN_PASSWORD override both for one run), which is
refused unless it is mode 0600 -- the rule hg/lib/hgConfig.c applies to hg.conf,
for the same reason. Nothing prints a password.
THE FILE IS KEYED BY HGCENTRAL DATABASE, not by server. An account is a row in
gbMembers in one central, the way a named session is: genome-test, hgwdev, every
hgwdev-<name> sandbox and every ticket park read hgcentraltest and share one
account, while hgwbeta reads hgcentralbeta and the RR reads hgcentral. So the
file is one [hgcentraltest] section rather than a section per sandbox.
Which central a server reads is READ from its hg.conf, following its includes the
way hgConfig.c does, and not guessed from the host -- because a sandbox can point
itself somewhere else and two on hgwdev do today: of the personal confs there, 45
set central.db=hgcentraltest, one sets hgcentralgsid and one hgcentralbeta. A
server whose conf is on another machine falls back to a small table (the RR, the
two mirrors, hgwbeta), and [default] catches the rest. A run redirected with
DOCENT_TARGET looks up the server it is really driving.
Two failures the step has to tell apart, and both cost a run to find:
A WRONG PASSWORD IS A PERFECTLY GOOD PAGE. hgLogin answers one by drawing the
same form again with a red message, so a step that just navigated on would leave
every later step running logged out and the failure would surface somewhere else
entirely. The step fails on #accountLoginForm still being there, and quotes what
the page said.
A RIGHT PASSWORD ARRIVES MID-REDIRECT. hgLogin answers one with a page that
navigates ITSELF a moment later: returnToURL(150) at hgLogin.c:1160 writes
setTimeout(function(){location=...}, 150). Returning while that timer is pending
means the next step's goto: races it and the browser aborts one of the two, which
arrives as a bare net::ERR_ABORTED on a URL that is completely fine. The step now
waits for that redirect to land. The failure path is checked first, since that
page never leaves hgLogin and there is no redirect to wait for.
preflight reports the account as a fixture -- which central it resolved, which
section it came from, and why it is unusable if it is -- so a missing password is
caught before the browser starts. It attempts no login: a wrong password fails
loudly at the step itself, which is the one thing preflight cannot do for it.
The hg.conf reader is now in both docent.js and tests/preflight.js, beside the
resolveTarget each of them already carries. Both say to keep the other in step.
If that second copy is a copy too many, the two of them want a shared module.
- lines changed 20, context: html, text, full: html, text
4d991e3416f4ac769408dfd2f65d8fdb0f7fae9b Wed Sep 16 12:36:41 2026 -0700
docent: a test for hgCollection, the one CGI nothing reached, refs #37892
hgCollection shares visibility logic with hgTracks by COPY rather than by call.
hg/hgCollection/hgCollection.c carries its own isParentVisible() at line 269, a
verbatim copy of the one in hg/lib/trackHub.c. Nine scripts in tests/regress
caught the trackHub.c copy on the #37547 cart-visibility branch; nothing caught
this one, and it was found by grep afterwards. This is the test that would have.
The copy's reach is narrower than it first looks, and the script says so: its only
caller is checkForVisible(), which builds the "Visible Tracks" folder at the top
of the builder's source tree. It is NOT on the save path, so the bug drops a
track you have on in the browser out of that shortcut folder and leaves a saved
collection alone.
The assertion sits on the FOLDER'S OWN jsTree CLASS, which turned out to be a
cleaner statement of the bug than counting what is inside it. addVisibleTracks
writes `,children:true` into the node only when checkForVisible() found
something, so the folder renders jstree-open when the cart has visible tracks and
jstree-leaf when it does not. The leaves inside it are then named as well.
Three things the live page settled, each of which had been a guess:
* The folder arrives OPEN. Clicking it CLOSES it. The first draft clicked.
* A node's id is the track name, and the same id is used for that track under
its group folder, so both selectors are scoped to li#visible. Unscoped, they
would also match the copy under Regulation the moment anyone opened it.
* wgEncodeBroadHistoneGm12878H3k4me1StdSig does not follow its siblings'
naming. It is named in the assertion for that reason: a rename shows up here
rather than quietly halving what this checks.
The track cannot be chosen freely. It has to be a leaf whose container is hidden
by default, or the test passes on a broken build (the rule in regress/README.txt:
a top-level track is added as a stub whatever the cart says, and a default-visible
child has its container in the list already). It also has to be one hgCollection
will show at all -- trackCanBeAdded() at line 141 keeps only wig, bigWig and
bedGraph leaves, which is why this names a cell-line leaf and not the multiWig
container above it. wgEncodeRegMarkH3k4me1H1hesc is both. The noHas: names
wgEncodeRegMarkH3k27acH1hesc, whose container IS visible by default: it says the
hideKids reached hgCollection, so the has: is not passing because the whole
superTrack came up on its own.
The wait had to be restructured, and the reason generalises. Waiting for the
folder's CHILDREN meant that a build with the bug -- where the folder is empty --
timed out after 15 seconds with a Playwright message instead of failing at the
expect: with what it wanted. Waiting for either terminal state (jstree-open or
jstree-leaf) fixes it: measured on genome-test the folder settles about 30ms after
load whichever way it goes, and jstree-open lands about 11ms before the children,
which is why the child check gets its own wait after the class has been asserted.
Measured both ways. The same script with the track hidden fails in about a
second:
step 9 (expect) failed: nothing matches "li#visible.jstree-open";
1 element(s) match "li#visible.jstree-leaf", wanted none
README.txt describes it, drops hgCollection from "Still to write", and records
what that section should now hold instead: a THIRD copy of isParentVisible(), in
hg/lib/hgFind.c at line 2957, feeding isTrackVisible() at 2977. It decides
whether a search result lands under "Visible Tracks" or "Hidden Tracks" on
hgSearch, it is the same bug in the same shape, and it needs no login.
18 of 18 pass in tests/, and preflight resolves all four fixtures.
- lines changed 13, context: html, text, full: html, text
2e5054b09838bacf29b31bb64fbd234471e7cb71 Wed Sep 16 13:00:17 2026 -0700
docent: a test for hgFind's copy of isParentVisible, on hgSearch, refs #37892
The third and last of the three. isParentVisible() exists in the tree character
for character three times -- hg/lib/trackHub.c:1818, hg/hgCollection/hgCollection.c:269
and hg/lib/hgFind.c:2957 -- and each copy asks the same question, are this track's
containers visible, by reading the cart itself rather than going through the
accessor. Nine scripts in regress/ cover the first, collection.docent.yaml covers
the second, and this covers the third. A change to how visibility is stored has to
reach all three, or two of them quietly start answering from the trackDb default.
What this copy decides: isTrackVisible() at hgFind.c:2977 sets
category->visibility, and hgSearch groups its results by it -- "Visible Tracks"
when it is set, "Currently Hidden Tracks" when it is not (hgSearch.c:174,
js/hgSearch.js:44). The symptom is a search result for a track you have on in the
browser filed under the hidden heading, where nobody looking for it will open it.
This one needs NO LOGIN, which is why it is worth having even with the other two
covered: it is the cheap one, about eight seconds.
wgEncodeGencodeBasicV49 is the track because it satisfies both constraints at
once. It is in hgFindSpec, so it has search results at all; and its chain is
wgEncodeGencodeV49ViewGenes -> wgEncodeGencodeV49 (visibility 0) ->
wgEncodeGencodeSuper, which is `superTrack on` with no `show`, so isShow is FALSE
and a build that reads the cart wrongly stops the walk at the superTrack. A
top-level or default-visible track would have passed on the broken build.
The hideKids step is not tidiness. Showing the superTrack brings every other
archived version up at its own visibility -- V50 draws alongside and lands in
Visible Tracks too -- so without it the `exact:` would need rewriting every time
GENCODE ships a version. It costs 31 variables, one per archived composite.
ENST00000297261 rather than a gene symbol: one of SHH's transcripts, it reaches
the GENCODE sets, and it searches 65 categories where SHH searches 319. No count
is asserted anywhere -- every one of those numbers moves when a track is reloaded.
Same wait discipline as collection.docent.yaml, and for the same reason: wait for
EITHER heading, so a build that files the track on the wrong side fails at the
expect: naming the selector it wanted rather than timing out 15 seconds later with
a Playwright message.
Measured both ways. The same script with the track left hidden fails at the
assertion:
step 7 (expect) failed: nothing matches
"li[id="Visible Tracks"] li#wgEncodeGencodeBasicV49"
No derive baseline on purpose: the hideKids expansion is one variable per archived
GENCODE version, so a baseline would go red twice a year for a reason that is not
a bug. views is left out of expected/ for the same reason.
tests/ is 19 of 19 with four fixtures resolved and the derive baselines matching.
- lines changed 14, context: html, text, full: html, text
b4e78d426dcdb47a20f1979025d5a0969ea79ac4 Thu Sep 17 17:07:49 2026 -0700
docent: a box: check for where an element sits, and lists for text:/noText:, refs #37892
`expect:` could say what was in a page and never where it was on the screen.
has:/noHas: take a CSS selector, which describes the tree; color: reads pixels
but only inside a track's row. #38251 moved the narrow-window menu icon out of
the blue bar with every selector still matching and every word of the page still
there, and nothing in the language could ask about it.
box: takes `inside:` (every edge within another element's box, with `tolerance:`
px of slack), `clear:` (no overlap with anything a selector matches, `gap:` for a
minimum separation) and `height:`/`width:`. Every element `sel:` matches has to
satisfy every clause, so {sel: "ul.nice-menu > li", inside: "#main-menu-whole"}
reads as "every menu item is in the bar". Boxes are read in document
coordinates; an element with no box at all is skipped rather than treated as a
zero-sized box at the origin, which would sit "inside" anything. A failure
prints the measurement:
#topRightLinks is not inside #main-menu-whole: 114px above it
-- it is at 666,0 34x32, #main-menu-whole at 0,114 1000x32
The image height: and box's own height:/width: now share one cmpSize(), so the
two cannot drift into different comparison grammars.
text: and noText: take a list, the way rows:, has: and noHas: always did. They
have to: a list handed to a check that stringifies its argument fails OPEN --
["a", "b"] becomes "a,b", which no page contains, so it passes on anything, and
passes silently. Six scripts in one batch were written that way and all six
looked green.
pagechecks and its .xfail twin cover both, the xfail with one entry aimed wrongly
and one aimed rightly in each list, so it fails only if every entry is really
looked at on its own.
- src/hg/utils/docent/tests/collection.docent.yaml
- lines changed 91, context: html, text, full: html, text
4d991e3416f4ac769408dfd2f65d8fdb0f7fae9b Wed Sep 16 12:36:41 2026 -0700
docent: a test for hgCollection, the one CGI nothing reached, refs #37892
hgCollection shares visibility logic with hgTracks by COPY rather than by call.
hg/hgCollection/hgCollection.c carries its own isParentVisible() at line 269, a
verbatim copy of the one in hg/lib/trackHub.c. Nine scripts in tests/regress
caught the trackHub.c copy on the #37547 cart-visibility branch; nothing caught
this one, and it was found by grep afterwards. This is the test that would have.
The copy's reach is narrower than it first looks, and the script says so: its only
caller is checkForVisible(), which builds the "Visible Tracks" folder at the top
of the builder's source tree. It is NOT on the save path, so the bug drops a
track you have on in the browser out of that shortcut folder and leaves a saved
collection alone.
The assertion sits on the FOLDER'S OWN jsTree CLASS, which turned out to be a
cleaner statement of the bug than counting what is inside it. addVisibleTracks
writes `,children:true` into the node only when checkForVisible() found
something, so the folder renders jstree-open when the cart has visible tracks and
jstree-leaf when it does not. The leaves inside it are then named as well.
Three things the live page settled, each of which had been a guess:
* The folder arrives OPEN. Clicking it CLOSES it. The first draft clicked.
* A node's id is the track name, and the same id is used for that track under
its group folder, so both selectors are scoped to li#visible. Unscoped, they
would also match the copy under Regulation the moment anyone opened it.
* wgEncodeBroadHistoneGm12878H3k4me1StdSig does not follow its siblings'
naming. It is named in the assertion for that reason: a rename shows up here
rather than quietly halving what this checks.
The track cannot be chosen freely. It has to be a leaf whose container is hidden
by default, or the test passes on a broken build (the rule in regress/README.txt:
a top-level track is added as a stub whatever the cart says, and a default-visible
child has its container in the list already). It also has to be one hgCollection
will show at all -- trackCanBeAdded() at line 141 keeps only wig, bigWig and
bedGraph leaves, which is why this names a cell-line leaf and not the multiWig
container above it. wgEncodeRegMarkH3k4me1H1hesc is both. The noHas: names
wgEncodeRegMarkH3k27acH1hesc, whose container IS visible by default: it says the
hideKids reached hgCollection, so the has: is not passing because the whole
superTrack came up on its own.
The wait had to be restructured, and the reason generalises. Waiting for the
folder's CHILDREN meant that a build with the bug -- where the folder is empty --
timed out after 15 seconds with a Playwright message instead of failing at the
expect: with what it wanted. Waiting for either terminal state (jstree-open or
jstree-leaf) fixes it: measured on genome-test the folder settles about 30ms after
load whichever way it goes, and jstree-open lands about 11ms before the children,
which is why the child check gets its own wait after the class has been asserted.
Measured both ways. The same script with the track hidden fails in about a
second:
step 9 (expect) failed: nothing matches "li#visible.jstree-open";
1 element(s) match "li#visible.jstree-leaf", wanted none
README.txt describes it, drops hgCollection from "Still to write", and records
what that section should now hold instead: a THIRD copy of isParentVisible(), in
hg/lib/hgFind.c at line 2957, feeding isTrackVisible() at 2977. It decides
whether a search result lands under "Visible Tracks" or "Hidden Tracks" on
hgSearch, it is the same bug in the same shape, and it needs no login.
18 of 18 pass in tests/, and preflight resolves all four fixtures.
- src/hg/utils/docent/tests/docentTest.mk
- lines changed 14, context: html, text, full: html, text
cad0600bd259bae35de7b39e49c2f95af8b624ca Mon Sep 14 16:14:40 2026 -0700
docent: point a whole test directory at another server with TARGET, refs #37892
A script says where it runs with `target:`, and until now that was the only way
to say it, so trying a suite against a branch build meant editing every script in
the directory. DOCENT_TARGET overrides `target:` for the run, and docentTest.mk
turns a TARGET= variable into it for preflight, test, parity and derive:
make test TARGET=hgwdev-demo9
make preflight TARGET=hgwdev-demo9
It takes the same values `target:` does -- a shorthand, a bare hgwdev-<name>
sandbox or demo, or a full .../cgi-bin URL -- so a ts park works too.
preflight.js reads the same variable, so the fixture check names the server that
will actually be driven rather than the one the scripts name. The trackDb cache
already keys on the resolved server, so a redirected run cannot read back a
listing fetched from somewhere else.
The committed scripts keep their own `target:`. Redirecting is for trying a
suite elsewhere, not for moving it: the nightly reads what is in the file. Both
READMEs say so, and say to read a redirected failure with the other server's
trackDb in mind, since a script asserts what its own server draws.
Verified against the ten methbase scripts: all ten pass with
TARGET=hgwdev-demo9, and mbMouse still passes with no TARGET, against the RR.
- src/hg/utils/docent/tests/expected/firstrequest.derive
- lines changed 5, context: html, text, full: html, text
d08323bb2ff524e4964a0922ecfb8336ab662007 Wed Sep 16 10:25:56 2026 -0700
docent: two tests for gaps a cart-visibility branch went past, refs #37892
The #37547 branch broke quickLift and nine scripts in tests/regress caught it
without help. Two other things went past the whole suite, and these are the
tests for them.
heavysession is selftest on a cart with weight behind it. selftest saves a
session and loads it back, which is the right shape, but the cart it round-trips
holds two rows. Saving a cart is not a copy of it: outIfNotPresent() in
hg/hgSession/hgSession.c writes a trackDb default for every track that is
deliberately NOT in the cart, so the file says what is hidden as well as what is
shown, and a two-track cart barely reaches that code. A save-and-reload path
that returned a 38-row clinical session as 34 rows left selftest green.
The weight comes from a Recommended Track Set, which is where a clinical user
starts: View/Clinical_SNVs_hg38, out of
DOCUMENT_ROOT/data/recTrackSets/recTrackSets.hg38.tab. It draws 33 tracks and
the ruler, and the file the session: step writes out of that cart is 741
settings, 248 of them visibilities and 154 of those hide. Both halves of the
trip assert the row set with exact: true, because rows: alone would pass on a
reload that lost four of them, and a count cannot say which row went missing.
It is a saved session on the server, so make preflight already checks it is
still there -- a deleted one answers 200 with a page that has no track image, on
which every noText: check passes.
firstrequest is about a bug that lags by exactly one request: the visibility
reaches the cart, the image drawn in reply does not carry the row, and the next
request draws it. A script shaped track: -> go: -> expect: supplies that extra
request itself and passes on the broken build. So this one asserts with no
go:, open: or convert: between the track: step and the check.
Which track it names is the other half, and it is not free choice. A top-level
track passes on a build with the bug, because hgTracks adds every top-level
track as a lightweight stub so the track controls can list it -- microsat,
gtexGene and windowmaskerSdust all drew. A default-visible child passes too,
because its container is in the list already: wgEncodeRegMarkH3k27ac drew while
its sibling wgEncodeRegMarkH3k4me1 did not, same superTrack and same request.
So the script names wgEncodeRegMarkH3k4me1, which is visibility hide under a
superTrack that is itself superTrack on hide, and the hideKids step before it is
what stops the other members coming back at their own trackDb visibility.
expected/firstrequest.derive is committed with it, and it is not decoration.
The test only means anything while the step under test is ONE round:
step 5 track {"wgEncodeRegMarkH3k4me1":"full"}
round 1 (2 vars): wgEncodeRegMarkH3k4me1=full wgEncodeReg=show
If Docent ever splits that the way it splits a container-plus-subtrack-hide, the
browser test would go on passing and stop being able to see the bug. The
baseline says so out loud.
README.txt describes both, and adds hgCollection to "Still to write": no script
in either directory reaches that CGI, and hg/hgCollection/hgCollection.c carries
its own verbatim copy of isParentVisible() from hg/lib/trackHub.c. Nine scripts
caught the trackHub.c copy on the branch; nothing caught this one. Covering it
needs a collection: verb, since tracks go into a collection by dragging between
two jsTrees and drag: is the genomic drag-select on the track image.
Seventeen of seventeen pass in tests/, including the four xfails.
- src/hg/utils/docent/tests/firstrequest.docent.yaml
- lines changed 52, context: html, text, full: html, text
d08323bb2ff524e4964a0922ecfb8336ab662007 Wed Sep 16 10:25:56 2026 -0700
docent: two tests for gaps a cart-visibility branch went past, refs #37892
The #37547 branch broke quickLift and nine scripts in tests/regress caught it
without help. Two other things went past the whole suite, and these are the
tests for them.
heavysession is selftest on a cart with weight behind it. selftest saves a
session and loads it back, which is the right shape, but the cart it round-trips
holds two rows. Saving a cart is not a copy of it: outIfNotPresent() in
hg/hgSession/hgSession.c writes a trackDb default for every track that is
deliberately NOT in the cart, so the file says what is hidden as well as what is
shown, and a two-track cart barely reaches that code. A save-and-reload path
that returned a 38-row clinical session as 34 rows left selftest green.
The weight comes from a Recommended Track Set, which is where a clinical user
starts: View/Clinical_SNVs_hg38, out of
DOCUMENT_ROOT/data/recTrackSets/recTrackSets.hg38.tab. It draws 33 tracks and
the ruler, and the file the session: step writes out of that cart is 741
settings, 248 of them visibilities and 154 of those hide. Both halves of the
trip assert the row set with exact: true, because rows: alone would pass on a
reload that lost four of them, and a count cannot say which row went missing.
It is a saved session on the server, so make preflight already checks it is
still there -- a deleted one answers 200 with a page that has no track image, on
which every noText: check passes.
firstrequest is about a bug that lags by exactly one request: the visibility
reaches the cart, the image drawn in reply does not carry the row, and the next
request draws it. A script shaped track: -> go: -> expect: supplies that extra
request itself and passes on the broken build. So this one asserts with no
go:, open: or convert: between the track: step and the check.
Which track it names is the other half, and it is not free choice. A top-level
track passes on a build with the bug, because hgTracks adds every top-level
track as a lightweight stub so the track controls can list it -- microsat,
gtexGene and windowmaskerSdust all drew. A default-visible child passes too,
because its container is in the list already: wgEncodeRegMarkH3k27ac drew while
its sibling wgEncodeRegMarkH3k4me1 did not, same superTrack and same request.
So the script names wgEncodeRegMarkH3k4me1, which is visibility hide under a
superTrack that is itself superTrack on hide, and the hideKids step before it is
what stops the other members coming back at their own trackDb visibility.
expected/firstrequest.derive is committed with it, and it is not decoration.
The test only means anything while the step under test is ONE round:
step 5 track {"wgEncodeRegMarkH3k4me1":"full"}
round 1 (2 vars): wgEncodeRegMarkH3k4me1=full wgEncodeReg=show
If Docent ever splits that the way it splits a container-plus-subtrack-hide, the
browser test would go on passing and stop being able to see the bug. The
baseline says so out loud.
README.txt describes both, and adds hgCollection to "Still to write": no script
in either directory reaches that CGI, and hg/hgCollection/hgCollection.c carries
its own verbatim copy of isParentVisible() from hg/lib/trackHub.c. Nine scripts
caught the trackHub.c copy on the branch; nothing caught this one. Covering it
needs a collection: verb, since tracks go into a collection by dragging between
two jsTrees and drag: is the genomic drag-select on the track image.
Seventeen of seventeen pass in tests/, including the four xfails.
- src/hg/utils/docent/tests/heavysession.docent.yaml
- lines changed 72, context: html, text, full: html, text
d08323bb2ff524e4964a0922ecfb8336ab662007 Wed Sep 16 10:25:56 2026 -0700
docent: two tests for gaps a cart-visibility branch went past, refs #37892
The #37547 branch broke quickLift and nine scripts in tests/regress caught it
without help. Two other things went past the whole suite, and these are the
tests for them.
heavysession is selftest on a cart with weight behind it. selftest saves a
session and loads it back, which is the right shape, but the cart it round-trips
holds two rows. Saving a cart is not a copy of it: outIfNotPresent() in
hg/hgSession/hgSession.c writes a trackDb default for every track that is
deliberately NOT in the cart, so the file says what is hidden as well as what is
shown, and a two-track cart barely reaches that code. A save-and-reload path
that returned a 38-row clinical session as 34 rows left selftest green.
The weight comes from a Recommended Track Set, which is where a clinical user
starts: View/Clinical_SNVs_hg38, out of
DOCUMENT_ROOT/data/recTrackSets/recTrackSets.hg38.tab. It draws 33 tracks and
the ruler, and the file the session: step writes out of that cart is 741
settings, 248 of them visibilities and 154 of those hide. Both halves of the
trip assert the row set with exact: true, because rows: alone would pass on a
reload that lost four of them, and a count cannot say which row went missing.
It is a saved session on the server, so make preflight already checks it is
still there -- a deleted one answers 200 with a page that has no track image, on
which every noText: check passes.
firstrequest is about a bug that lags by exactly one request: the visibility
reaches the cart, the image drawn in reply does not carry the row, and the next
request draws it. A script shaped track: -> go: -> expect: supplies that extra
request itself and passes on the broken build. So this one asserts with no
go:, open: or convert: between the track: step and the check.
Which track it names is the other half, and it is not free choice. A top-level
track passes on a build with the bug, because hgTracks adds every top-level
track as a lightweight stub so the track controls can list it -- microsat,
gtexGene and windowmaskerSdust all drew. A default-visible child passes too,
because its container is in the list already: wgEncodeRegMarkH3k27ac drew while
its sibling wgEncodeRegMarkH3k4me1 did not, same superTrack and same request.
So the script names wgEncodeRegMarkH3k4me1, which is visibility hide under a
superTrack that is itself superTrack on hide, and the hideKids step before it is
what stops the other members coming back at their own trackDb visibility.
expected/firstrequest.derive is committed with it, and it is not decoration.
The test only means anything while the step under test is ONE round:
step 5 track {"wgEncodeRegMarkH3k4me1":"full"}
round 1 (2 vars): wgEncodeRegMarkH3k4me1=full wgEncodeReg=show
If Docent ever splits that the way it splits a container-plus-subtrack-hide, the
browser test would go on passing and stop being able to see the bug. The
baseline says so out loud.
README.txt describes both, and adds hgCollection to "Still to write": no script
in either directory reaches that CGI, and hg/hgCollection/hgCollection.c carries
its own verbatim copy of isParentVisible() from hg/lib/trackHub.c. Nine scripts
caught the trackHub.c copy on the branch; nothing caught this one. Covering it
needs a collection: verb, since tracks go into a collection by dragging between
two jsTrees and drag: is the genomic drag-select on the track image.
Seventeen of seventeen pass in tests/, including the four xfails.
- src/hg/utils/docent/tests/methbase/README.txt
- lines changed 111, context: html, text, full: html, text
5f99585c343029387c5a58c7e64063eaf9b72409 Mon Sep 14 12:57:49 2026 -0700
docent: ten tests for MethBase on the RR, refs #37892
MethBase on genome.ucsc.edu is two public hubs, not the Methbase faceted
composite. That composite is on genome-test only: hgTrackUi?g=Methbase
answers "Can't find Methbase in track database hg38" on both the RR and
hgwbeta, and genome-mysql has no matching trackDb row for hg38 or mm39.
What a user of the RR has is MethBase2 from smithlab.usc.edu, and the
frozen v1 hub we serve from hgdownload. Nine of these scripts drive the
first and one drives the second.
The suite is a directory of its own rather than more scripts in
tests/regress. Those are one per fixed bug, named for a ticket, and each
carries a proof: key. These have no bug and no ticket, and they point at
the RR rather than at genome-test, which tests/regress and its nightly
assume throughout. So they carry no proof: key and they are not in the
nightly. README.txt says what each one covers.
Four of them assert a color. A remote hub whose bigDataUrl stops
answering keeps its row, its name, its height and its map boxes: hgTracks
catches the abort and paints the row as a 240,240,180 bar with the message
inside the png, where no text check can reach it. That is the rm38310
lesson, except that here the thing that breaks is a URL on someone else's
web server.
Two constraints shaped the rest. A hub track's cart name carries a
per-hub hub_<n>_ prefix that track: cannot write, so no script here uses
track: and none names a hub number: rows match by suffix, settings pages
are reached through a.trackLink[data-track$="..."], and a visibility is
changed through the matrix buttons, which are named for the subgroup tag.
A view's own dropdown is a select, and Docent has no verb that drives one,
so no script turns on AMR, PMD or CpG reads.
All ten pass against the RR, in 5m17s together.
- lines changed 10, context: html, text, full: html, text
cad0600bd259bae35de7b39e49c2f95af8b624ca Mon Sep 14 16:14:40 2026 -0700
docent: point a whole test directory at another server with TARGET, refs #37892
A script says where it runs with `target:`, and until now that was the only way
to say it, so trying a suite against a branch build meant editing every script in
the directory. DOCENT_TARGET overrides `target:` for the run, and docentTest.mk
turns a TARGET= variable into it for preflight, test, parity and derive:
make test TARGET=hgwdev-demo9
make preflight TARGET=hgwdev-demo9
It takes the same values `target:` does -- a shorthand, a bare hgwdev-<name>
sandbox or demo, or a full .../cgi-bin URL -- so a ts park works too.
preflight.js reads the same variable, so the fixture check names the server that
will actually be driven rather than the one the scripts name. The trackDb cache
already keys on the resolved server, so a redirected run cannot read back a
listing fetched from somewhere else.
The committed scripts keep their own `target:`. Redirecting is for trying a
suite elsewhere, not for moving it: the nightly reads what is in the file. Both
READMEs say so, and say to read a redirected failure with the other server's
trackDb in mind, since a script asserts what its own server draws.
Verified against the ten methbase scripts: all ten pass with
TARGET=hgwdev-demo9, and mbMouse still passes with no TARGET, against the RR.
- src/hg/utils/docent/tests/methbase/makefile
- lines changed 19, context: html, text, full: html, text
5f99585c343029387c5a58c7e64063eaf9b72409 Mon Sep 14 12:57:49 2026 -0700
docent: ten tests for MethBase on the RR, refs #37892
MethBase on genome.ucsc.edu is two public hubs, not the Methbase faceted
composite. That composite is on genome-test only: hgTrackUi?g=Methbase
answers "Can't find Methbase in track database hg38" on both the RR and
hgwbeta, and genome-mysql has no matching trackDb row for hg38 or mm39.
What a user of the RR has is MethBase2 from smithlab.usc.edu, and the
frozen v1 hub we serve from hgdownload. Nine of these scripts drive the
first and one drives the second.
The suite is a directory of its own rather than more scripts in
tests/regress. Those are one per fixed bug, named for a ticket, and each
carries a proof: key. These have no bug and no ticket, and they point at
the RR rather than at genome-test, which tests/regress and its nightly
assume throughout. So they carry no proof: key and they are not in the
nightly. README.txt says what each one covers.
Four of them assert a color. A remote hub whose bigDataUrl stops
answering keeps its row, its name, its height and its map boxes: hgTracks
catches the abort and paints the row as a 240,240,180 bar with the message
inside the png, where no text check can reach it. That is the rm38310
lesson, except that here the thing that breaks is a URL on someone else's
web server.
Two constraints shaped the rest. A hub track's cart name carries a
per-hub hub_<n>_ prefix that track: cannot write, so no script here uses
track: and none names a hub number: rows match by suffix, settings pages
are reached through a.trackLink[data-track$="..."], and a visibility is
changed through the matrix buttons, which are named for the subgroup tag.
A view's own dropdown is a select, and Docent has no verb that drives one,
so no script turns on AMR, PMD or CpG reads.
All ten pass against the RR, in 5m17s together.
- src/hg/utils/docent/tests/methbase/mbContainer.docent.yaml
- lines changed 49, context: html, text, full: html, text
5f99585c343029387c5a58c7e64063eaf9b72409 Mon Sep 14 12:57:49 2026 -0700
docent: ten tests for MethBase on the RR, refs #37892
MethBase on genome.ucsc.edu is two public hubs, not the Methbase faceted
composite. That composite is on genome-test only: hgTrackUi?g=Methbase
answers "Can't find Methbase in track database hg38" on both the RR and
hgwbeta, and genome-mysql has no matching trackDb row for hg38 or mm39.
What a user of the RR has is MethBase2 from smithlab.usc.edu, and the
frozen v1 hub we serve from hgdownload. Nine of these scripts drive the
first and one drives the second.
The suite is a directory of its own rather than more scripts in
tests/regress. Those are one per fixed bug, named for a ticket, and each
carries a proof: key. These have no bug and no ticket, and they point at
the RR rather than at genome-test, which tests/regress and its nightly
assume throughout. So they carry no proof: key and they are not in the
nightly. README.txt says what each one covers.
Four of them assert a color. A remote hub whose bigDataUrl stops
answering keeps its row, its name, its height and its map boxes: hgTracks
catches the abort and paints the row as a 240,240,180 bar with the message
inside the png, where no text check can reach it. That is the rm38310
lesson, except that here the thing that breaks is a URL on someone else's
web server.
Two constraints shaped the rest. A hub track's cart name carries a
per-hub hub_<n>_ prefix that track: cannot write, so no script here uses
track: and none names a hub number: rows match by suffix, settings pages
are reached through a.trackLink[data-track$="..."], and a visibility is
changed through the matrix buttons, which are named for the subgroup tag.
A view's own dropdown is a select, and Docent has no verb that drives one,
so no script turns on AMR, PMD or CpG reads.
All ten pass against the RR, in 5m17s together.
- src/hg/utils/docent/tests/methbase/mbDefaults.docent.yaml
- lines changed 61, context: html, text, full: html, text
5f99585c343029387c5a58c7e64063eaf9b72409 Mon Sep 14 12:57:49 2026 -0700
docent: ten tests for MethBase on the RR, refs #37892
MethBase on genome.ucsc.edu is two public hubs, not the Methbase faceted
composite. That composite is on genome-test only: hgTrackUi?g=Methbase
answers "Can't find Methbase in track database hg38" on both the RR and
hgwbeta, and genome-mysql has no matching trackDb row for hg38 or mm39.
What a user of the RR has is MethBase2 from smithlab.usc.edu, and the
frozen v1 hub we serve from hgdownload. Nine of these scripts drive the
first and one drives the second.
The suite is a directory of its own rather than more scripts in
tests/regress. Those are one per fixed bug, named for a ticket, and each
carries a proof: key. These have no bug and no ticket, and they point at
the RR rather than at genome-test, which tests/regress and its nightly
assume throughout. So they carry no proof: key and they are not in the
nightly. README.txt says what each one covers.
Four of them assert a color. A remote hub whose bigDataUrl stops
answering keeps its row, its name, its height and its map boxes: hgTracks
catches the abort and paints the row as a 240,240,180 bar with the message
inside the png, where no text check can reach it. That is the rm38310
lesson, except that here the thing that breaks is a URL on someone else's
web server.
Two constraints shaped the rest. A hub track's cart name carries a
per-hub hub_<n>_ prefix that track: cannot write, so no script here uses
track: and none names a hub number: rows match by suffix, settings pages
are reached through a.trackLink[data-track$="..."], and a visibility is
changed through the matrix buttons, which are named for the subgroup tag.
A view's own dropdown is a select, and Docent has no verb that drives one,
so no script turns on AMR, PMD or CpG reads.
All ten pass against the RR, in 5m17s together.
- src/hg/utils/docent/tests/methbase/mbDetails.docent.yaml
- lines changed 53, context: html, text, full: html, text
5f99585c343029387c5a58c7e64063eaf9b72409 Mon Sep 14 12:57:49 2026 -0700
docent: ten tests for MethBase on the RR, refs #37892
MethBase on genome.ucsc.edu is two public hubs, not the Methbase faceted
composite. That composite is on genome-test only: hgTrackUi?g=Methbase
answers "Can't find Methbase in track database hg38" on both the RR and
hgwbeta, and genome-mysql has no matching trackDb row for hg38 or mm39.
What a user of the RR has is MethBase2 from smithlab.usc.edu, and the
frozen v1 hub we serve from hgdownload. Nine of these scripts drive the
first and one drives the second.
The suite is a directory of its own rather than more scripts in
tests/regress. Those are one per fixed bug, named for a ticket, and each
carries a proof: key. These have no bug and no ticket, and they point at
the RR rather than at genome-test, which tests/regress and its nightly
assume throughout. So they carry no proof: key and they are not in the
nightly. README.txt says what each one covers.
Four of them assert a color. A remote hub whose bigDataUrl stops
answering keeps its row, its name, its height and its map boxes: hgTracks
catches the abort and paints the row as a 240,240,180 bar with the message
inside the png, where no text check can reach it. That is the rm38310
lesson, except that here the thing that breaks is a URL on someone else's
web server.
Two constraints shaped the rest. A hub track's cart name carries a
per-hub hub_<n>_ prefix that track: cannot write, so no script here uses
track: and none names a hub number: rows match by suffix, settings pages
are reached through a.trackLink[data-track$="..."], and a visibility is
changed through the matrix buttons, which are named for the subgroup tag.
A view's own dropdown is a select, and Docent has no verb that drives one,
so no script turns on AMR, PMD or CpG reads.
All ten pass against the RR, in 5m17s together.
- src/hg/utils/docent/tests/methbase/mbLegacy.docent.yaml
- lines changed 57, context: html, text, full: html, text
5f99585c343029387c5a58c7e64063eaf9b72409 Mon Sep 14 12:57:49 2026 -0700
docent: ten tests for MethBase on the RR, refs #37892
MethBase on genome.ucsc.edu is two public hubs, not the Methbase faceted
composite. That composite is on genome-test only: hgTrackUi?g=Methbase
answers "Can't find Methbase in track database hg38" on both the RR and
hgwbeta, and genome-mysql has no matching trackDb row for hg38 or mm39.
What a user of the RR has is MethBase2 from smithlab.usc.edu, and the
frozen v1 hub we serve from hgdownload. Nine of these scripts drive the
first and one drives the second.
The suite is a directory of its own rather than more scripts in
tests/regress. Those are one per fixed bug, named for a ticket, and each
carries a proof: key. These have no bug and no ticket, and they point at
the RR rather than at genome-test, which tests/regress and its nightly
assume throughout. So they carry no proof: key and they are not in the
nightly. README.txt says what each one covers.
Four of them assert a color. A remote hub whose bigDataUrl stops
answering keeps its row, its name, its height and its map boxes: hgTracks
catches the abort and paints the row as a 240,240,180 bar with the message
inside the png, where no text check can reach it. That is the rm38310
lesson, except that here the thing that breaks is a URL on someone else's
web server.
Two constraints shaped the rest. A hub track's cart name carries a
per-hub hub_<n>_ prefix that track: cannot write, so no script here uses
track: and none names a hub number: rows match by suffix, settings pages
are reached through a.trackLink[data-track$="..."], and a visibility is
changed through the matrix buttons, which are named for the subgroup tag.
A view's own dropdown is a select, and Docent has no verb that drives one,
so no script turns on AMR, PMD or CpG reads.
All ten pass against the RR, in 5m17s together.
- src/hg/utils/docent/tests/methbase/mbMatrix.docent.yaml
- lines changed 63, context: html, text, full: html, text
5f99585c343029387c5a58c7e64063eaf9b72409 Mon Sep 14 12:57:49 2026 -0700
docent: ten tests for MethBase on the RR, refs #37892
MethBase on genome.ucsc.edu is two public hubs, not the Methbase faceted
composite. That composite is on genome-test only: hgTrackUi?g=Methbase
answers "Can't find Methbase in track database hg38" on both the RR and
hgwbeta, and genome-mysql has no matching trackDb row for hg38 or mm39.
What a user of the RR has is MethBase2 from smithlab.usc.edu, and the
frozen v1 hub we serve from hgdownload. Nine of these scripts drive the
first and one drives the second.
The suite is a directory of its own rather than more scripts in
tests/regress. Those are one per fixed bug, named for a ticket, and each
carries a proof: key. These have no bug and no ticket, and they point at
the RR rather than at genome-test, which tests/regress and its nightly
assume throughout. So they carry no proof: key and they are not in the
nightly. README.txt says what each one covers.
Four of them assert a color. A remote hub whose bigDataUrl stops
answering keeps its row, its name, its height and its map boxes: hgTracks
catches the abort and paints the row as a 240,240,180 bar with the message
inside the png, where no text check can reach it. That is the rm38310
lesson, except that here the thing that breaks is a URL on someone else's
web server.
Two constraints shaped the rest. A hub track's cart name carries a
per-hub hub_<n>_ prefix that track: cannot write, so no script here uses
track: and none names a hub number: rows match by suffix, settings pages
are reached through a.trackLink[data-track$="..."], and a visibility is
changed through the matrix buttons, which are named for the subgroup tag.
A view's own dropdown is a select, and Docent has no verb that drives one,
so no script turns on AMR, PMD or CpG reads.
All ten pass against the RR, in 5m17s together.
- src/hg/utils/docent/tests/methbase/mbMouse.docent.yaml
- lines changed 51, context: html, text, full: html, text
5f99585c343029387c5a58c7e64063eaf9b72409 Mon Sep 14 12:57:49 2026 -0700
docent: ten tests for MethBase on the RR, refs #37892
MethBase on genome.ucsc.edu is two public hubs, not the Methbase faceted
composite. That composite is on genome-test only: hgTrackUi?g=Methbase
answers "Can't find Methbase in track database hg38" on both the RR and
hgwbeta, and genome-mysql has no matching trackDb row for hg38 or mm39.
What a user of the RR has is MethBase2 from smithlab.usc.edu, and the
frozen v1 hub we serve from hgdownload. Nine of these scripts drive the
first and one drives the second.
The suite is a directory of its own rather than more scripts in
tests/regress. Those are one per fixed bug, named for a ticket, and each
carries a proof: key. These have no bug and no ticket, and they point at
the RR rather than at genome-test, which tests/regress and its nightly
assume throughout. So they carry no proof: key and they are not in the
nightly. README.txt says what each one covers.
Four of them assert a color. A remote hub whose bigDataUrl stops
answering keeps its row, its name, its height and its map boxes: hgTracks
catches the abort and paints the row as a 240,240,180 bar with the message
inside the png, where no text check can reach it. That is the rm38310
lesson, except that here the thing that breaks is a URL on someone else's
web server.
Two constraints shaped the rest. A hub track's cart name carries a
per-hub hub_<n>_ prefix that track: cannot write, so no script here uses
track: and none names a hub number: rows match by suffix, settings pages
are reached through a.trackLink[data-track$="..."], and a visibility is
changed through the matrix buttons, which are named for the subgroup tag.
A view's own dropdown is a select, and Docent has no verb that drives one,
so no script turns on AMR, PMD or CpG reads.
All ten pass against the RR, in 5m17s together.
- src/hg/utils/docent/tests/methbase/mbPublicHub.docent.yaml
- lines changed 41, context: html, text, full: html, text
5f99585c343029387c5a58c7e64063eaf9b72409 Mon Sep 14 12:57:49 2026 -0700
docent: ten tests for MethBase on the RR, refs #37892
MethBase on genome.ucsc.edu is two public hubs, not the Methbase faceted
composite. That composite is on genome-test only: hgTrackUi?g=Methbase
answers "Can't find Methbase in track database hg38" on both the RR and
hgwbeta, and genome-mysql has no matching trackDb row for hg38 or mm39.
What a user of the RR has is MethBase2 from smithlab.usc.edu, and the
frozen v1 hub we serve from hgdownload. Nine of these scripts drive the
first and one drives the second.
The suite is a directory of its own rather than more scripts in
tests/regress. Those are one per fixed bug, named for a ticket, and each
carries a proof: key. These have no bug and no ticket, and they point at
the RR rather than at genome-test, which tests/regress and its nightly
assume throughout. So they carry no proof: key and they are not in the
nightly. README.txt says what each one covers.
Four of them assert a color. A remote hub whose bigDataUrl stops
answering keeps its row, its name, its height and its map boxes: hgTracks
catches the abort and paints the row as a 240,240,180 bar with the message
inside the png, where no text check can reach it. That is the rm38310
lesson, except that here the thing that breaks is a URL on someone else's
web server.
Two constraints shaped the rest. A hub track's cart name carries a
per-hub hub_<n>_ prefix that track: cannot write, so no script here uses
track: and none names a hub number: rows match by suffix, settings pages
are reached through a.trackLink[data-track$="..."], and a visibility is
changed through the matrix buttons, which are named for the subgroup tag.
A view's own dropdown is a select, and Docent has no verb that drives one,
so no script turns on AMR, PMD or CpG reads.
All ten pass against the RR, in 5m17s together.
- src/hg/utils/docent/tests/methbase/mbSignal.docent.yaml
- lines changed 48, context: html, text, full: html, text
5f99585c343029387c5a58c7e64063eaf9b72409 Mon Sep 14 12:57:49 2026 -0700
docent: ten tests for MethBase on the RR, refs #37892
MethBase on genome.ucsc.edu is two public hubs, not the Methbase faceted
composite. That composite is on genome-test only: hgTrackUi?g=Methbase
answers "Can't find Methbase in track database hg38" on both the RR and
hgwbeta, and genome-mysql has no matching trackDb row for hg38 or mm39.
What a user of the RR has is MethBase2 from smithlab.usc.edu, and the
frozen v1 hub we serve from hgdownload. Nine of these scripts drive the
first and one drives the second.
The suite is a directory of its own rather than more scripts in
tests/regress. Those are one per fixed bug, named for a ticket, and each
carries a proof: key. These have no bug and no ticket, and they point at
the RR rather than at genome-test, which tests/regress and its nightly
assume throughout. So they carry no proof: key and they are not in the
nightly. README.txt says what each one covers.
Four of them assert a color. A remote hub whose bigDataUrl stops
answering keeps its row, its name, its height and its map boxes: hgTracks
catches the abort and paints the row as a 240,240,180 bar with the message
inside the png, where no text check can reach it. That is the rm38310
lesson, except that here the thing that breaks is a URL on someone else's
web server.
Two constraints shaped the rest. A hub track's cart name carries a
per-hub hub_<n>_ prefix that track: cannot write, so no script here uses
track: and none names a hub number: rows match by suffix, settings pages
are reached through a.trackLink[data-track$="..."], and a visibility is
changed through the matrix buttons, which are named for the subgroup tag.
A view's own dropdown is a select, and Docent has no verb that drives one,
so no script turns on AMR, PMD or CpG reads.
All ten pass against the RR, in 5m17s together.
- src/hg/utils/docent/tests/methbase/mbSubtracks.docent.yaml
- lines changed 47, context: html, text, full: html, text
5f99585c343029387c5a58c7e64063eaf9b72409 Mon Sep 14 12:57:49 2026 -0700
docent: ten tests for MethBase on the RR, refs #37892
MethBase on genome.ucsc.edu is two public hubs, not the Methbase faceted
composite. That composite is on genome-test only: hgTrackUi?g=Methbase
answers "Can't find Methbase in track database hg38" on both the RR and
hgwbeta, and genome-mysql has no matching trackDb row for hg38 or mm39.
What a user of the RR has is MethBase2 from smithlab.usc.edu, and the
frozen v1 hub we serve from hgdownload. Nine of these scripts drive the
first and one drives the second.
The suite is a directory of its own rather than more scripts in
tests/regress. Those are one per fixed bug, named for a ticket, and each
carries a proof: key. These have no bug and no ticket, and they point at
the RR rather than at genome-test, which tests/regress and its nightly
assume throughout. So they carry no proof: key and they are not in the
nightly. README.txt says what each one covers.
Four of them assert a color. A remote hub whose bigDataUrl stops
answering keeps its row, its name, its height and its map boxes: hgTracks
catches the abort and paints the row as a 240,240,180 bar with the message
inside the png, where no text check can reach it. That is the rm38310
lesson, except that here the thing that breaks is a URL on someone else's
web server.
Two constraints shaped the rest. A hub track's cart name carries a
per-hub hub_<n>_ prefix that track: cannot write, so no script here uses
track: and none names a hub number: rows match by suffix, settings pages
are reached through a.trackLink[data-track$="..."], and a visibility is
changed through the matrix buttons, which are named for the subgroup tag.
A view's own dropdown is a select, and Docent has no verb that drives one,
so no script turns on AMR, PMD or CpG reads.
All ten pass against the RR, in 5m17s together.
- src/hg/utils/docent/tests/methbase/mbZoomOut.docent.yaml
- lines changed 48, context: html, text, full: html, text
5f99585c343029387c5a58c7e64063eaf9b72409 Mon Sep 14 12:57:49 2026 -0700
docent: ten tests for MethBase on the RR, refs #37892
MethBase on genome.ucsc.edu is two public hubs, not the Methbase faceted
composite. That composite is on genome-test only: hgTrackUi?g=Methbase
answers "Can't find Methbase in track database hg38" on both the RR and
hgwbeta, and genome-mysql has no matching trackDb row for hg38 or mm39.
What a user of the RR has is MethBase2 from smithlab.usc.edu, and the
frozen v1 hub we serve from hgdownload. Nine of these scripts drive the
first and one drives the second.
The suite is a directory of its own rather than more scripts in
tests/regress. Those are one per fixed bug, named for a ticket, and each
carries a proof: key. These have no bug and no ticket, and they point at
the RR rather than at genome-test, which tests/regress and its nightly
assume throughout. So they carry no proof: key and they are not in the
nightly. README.txt says what each one covers.
Four of them assert a color. A remote hub whose bigDataUrl stops
answering keeps its row, its name, its height and its map boxes: hgTracks
catches the abort and paints the row as a 240,240,180 bar with the message
inside the png, where no text check can reach it. That is the rm38310
lesson, except that here the thing that breaks is a URL on someone else's
web server.
Two constraints shaped the rest. A hub track's cart name carries a
per-hub hub_<n>_ prefix that track: cannot write, so no script here uses
track: and none names a hub number: rows match by suffix, settings pages
are reached through a.trackLink[data-track$="..."], and a visibility is
changed through the matrix buttons, which are named for the subgroup tag.
A view's own dropdown is a select, and Docent has no verb that drives one,
so no script turns on AMR, PMD or CpG reads.
All ten pass against the RR, in 5m17s together.
- src/hg/utils/docent/tests/pagechecks.docent.yaml
- lines changed 24, context: html, text, full: html, text
b4e78d426dcdb47a20f1979025d5a0969ea79ac4 Thu Sep 17 17:07:49 2026 -0700
docent: a box: check for where an element sits, and lists for text:/noText:, refs #37892
`expect:` could say what was in a page and never where it was on the screen.
has:/noHas: take a CSS selector, which describes the tree; color: reads pixels
but only inside a track's row. #38251 moved the narrow-window menu icon out of
the blue bar with every selector still matching and every word of the page still
there, and nothing in the language could ask about it.
box: takes `inside:` (every edge within another element's box, with `tolerance:`
px of slack), `clear:` (no overlap with anything a selector matches, `gap:` for a
minimum separation) and `height:`/`width:`. Every element `sel:` matches has to
satisfy every clause, so {sel: "ul.nice-menu > li", inside: "#main-menu-whole"}
reads as "every menu item is in the bar". Boxes are read in document
coordinates; an element with no box at all is skipped rather than treated as a
zero-sized box at the origin, which would sit "inside" anything. A failure
prints the measurement:
#topRightLinks is not inside #main-menu-whole: 114px above it
-- it is at 666,0 34x32, #main-menu-whole at 0,114 1000x32
The image height: and box's own height:/width: now share one cmpSize(), so the
two cannot drift into different comparison grammars.
text: and noText: take a list, the way rows:, has: and noHas: always did. They
have to: a list handed to a check that stringifies its argument fails OPEN --
["a", "b"] becomes "a,b", which no page contains, so it passes on anything, and
passes silently. Six scripts in one batch were written that way and all six
looked green.
pagechecks and its .xfail twin cover both, the xfail with one entry aimed wrongly
and one aimed rightly in each list, so it fails only if every entry is really
looked at on its own.
- src/hg/utils/docent/tests/pagechecks.xfail.docent.yaml
- lines changed 34, context: html, text, full: html, text
b4e78d426dcdb47a20f1979025d5a0969ea79ac4 Thu Sep 17 17:07:49 2026 -0700
docent: a box: check for where an element sits, and lists for text:/noText:, refs #37892
`expect:` could say what was in a page and never where it was on the screen.
has:/noHas: take a CSS selector, which describes the tree; color: reads pixels
but only inside a track's row. #38251 moved the narrow-window menu icon out of
the blue bar with every selector still matching and every word of the page still
there, and nothing in the language could ask about it.
box: takes `inside:` (every edge within another element's box, with `tolerance:`
px of slack), `clear:` (no overlap with anything a selector matches, `gap:` for a
minimum separation) and `height:`/`width:`. Every element `sel:` matches has to
satisfy every clause, so {sel: "ul.nice-menu > li", inside: "#main-menu-whole"}
reads as "every menu item is in the bar". Boxes are read in document
coordinates; an element with no box at all is skipped rather than treated as a
zero-sized box at the origin, which would sit "inside" anything. A failure
prints the measurement:
#topRightLinks is not inside #main-menu-whole: 114px above it
-- it is at 666,0 34x32, #main-menu-whole at 0,114 1000x32
The image height: and box's own height:/width: now share one cmpSize(), so the
two cannot drift into different comparison grammars.
text: and noText: take a list, the way rows:, has: and noHas: always did. They
have to: a list handed to a check that stringifies its argument fails OPEN --
["a", "b"] becomes "a,b", which no page contains, so it passes on anything, and
passes silently. Six scripts in one batch were written that way and all six
looked green.
pagechecks and its .xfail twin cover both, the xfail with one entry aimed wrongly
and one aimed rightly in each list, so it fails only if every entry is really
looked at on its own.
- src/hg/utils/docent/tests/preflight.js
- lines changed 3, context: html, text, full: html, text
cad0600bd259bae35de7b39e49c2f95af8b624ca Mon Sep 14 16:14:40 2026 -0700
docent: point a whole test directory at another server with TARGET, refs #37892
A script says where it runs with `target:`, and until now that was the only way
to say it, so trying a suite against a branch build meant editing every script in
the directory. DOCENT_TARGET overrides `target:` for the run, and docentTest.mk
turns a TARGET= variable into it for preflight, test, parity and derive:
make test TARGET=hgwdev-demo9
make preflight TARGET=hgwdev-demo9
It takes the same values `target:` does -- a shorthand, a bare hgwdev-<name>
sandbox or demo, or a full .../cgi-bin URL -- so a ts park works too.
preflight.js reads the same variable, so the fixture check names the server that
will actually be driven rather than the one the scripts name. The trackDb cache
already keys on the resolved server, so a redirected run cannot read back a
listing fetched from somewhere else.
The committed scripts keep their own `target:`. Redirecting is for trying a
suite elsewhere, not for moving it: the nightly reads what is in the file. Both
READMEs say so, and say to read a redirected failure with the other server's
trackDb in mind, since a script asserts what its own server draws.
Verified against the ten methbase scripts: all ten pass with
TARGET=hgwdev-demo9, and mbMouse still passes with no TARGET, against the RR.
- lines changed 94, context: html, text, full: html, text
3d98068ead92a95ea4b714f31f01119100a3c099 Wed Sep 16 10:26:18 2026 -0700
docent: preflight prints how the target is configured, refs #37892
make test TARGET=hgwdev-you points the whole directory at another server, and a
red script there can be that machine's configuration rather than a bug. A
different curatedHubPrefix genuinely changes what a quickLift hop produces, and
a db.trackDb with a private table in front of the shared one changes what
exact: true counts. Both failures look exactly like a bug. The README already
warned about it, in prose, which arrives after someone has spent an hour.
make preflight now prints the settings that decide it, so a redirected run
carries its own explanation in the log:
target https://hgwdev-braney.gi.ucsc.edu/cgi-bin
/usr/local/apache/cgi-bin-braney/hg.conf
central.db hgcentraltest
db.trackDb trackDb_braney,trackDb
curatedHubPrefix braney
browser.quickLift on
browser.quickLiftAlignments on
browser.recTrackSets on
central.db is on the list because preflight already checks named sessions and
that setting says which hgcentral it looked in.
The value printed is the EFFECTIVE one. The reader follows include and delete
the way hg/lib/hgConfig.c does, with a later assignment winning over an earlier
one, so a sandbox conf that sets nothing still shows what it inherits from the
shared conf it includes. Reading cgi-bin-braney/hg.conf on its own says
browser.quickLiftAlignments is unset; the CGI there sees it on, from the
include on line 2. A ts park is the mirror case: 37547's frozen conf sets
db.trackDb twice and the second one, 114 lines later, wins.
Only the six keys in HG_CONF_KEYS are ever printed. The includes lead to
hg.conf.private, which holds database passwords, so the reader parses whatever
it is pointed at and prints nothing off that list.
There is no way to ask a browser over http what its hg.conf says, so which file
to read is a lookup by convention: genome-test and hgwdev read
/usr/local/apache/cgi-bin/hg.conf, an hgwdev-<name> sandbox or demo reads
cgi-bin-<name>, and a ts park on 127.0.0.1 is found by port in its ports.tsv.
Anything off this machine -- hgwbeta, the RR -- says the conf cannot be read
from here, which is true and better than a guess.
Even with that in the log, a config difference and a code difference can still
look alike. The reliable way to tell them apart is to swap only the binary:
drop a control build's CGIs into the same sandbox, leave its hg.conf alone, and
re-run. If the failures follow the binary they are the code. That experiment
is what turned nine plausible failures on the #37547 branch into nine proven
ones, and both READMEs now say so.
Verified against all three shapes: genome-test, hgwdev-braney, hgwdev-demo9,
and the #37547 park on 127.0.0.1:48087. Both test directories preflight clean.
- lines changed 77, context: html, text, full: html, text
7e89607805cac22b52143b23a45464759e66a957 Wed Sep 16 12:36:15 2026 -0700
docent: a login: step, with the account kept per hgcentral, refs #37892
hgCollection refuses a visitor who is not signed in -- hgCollection.c doMiddle,
"You must be logged in to edit collections" -- and so does the saving half of
hgSession. The suite has never had a logged-in page, and until now could not:
the login cookie is validated against a salted hash (login.cookieSalt,
hg/lib/wikiLink.c), so there is no cookie to hand the browser. A script that
needs one of those pages has to sign in the way a person does.
`login:` does that, through hgLogin's own form, and it takes no credentials and
cannot be given any. They come from ~/.docentLogin (DOCENT_LOGIN_FILE overrides,
DOCENT_LOGIN_USER + DOCENT_LOGIN_PASSWORD override both for one run), which is
refused unless it is mode 0600 -- the rule hg/lib/hgConfig.c applies to hg.conf,
for the same reason. Nothing prints a password.
THE FILE IS KEYED BY HGCENTRAL DATABASE, not by server. An account is a row in
gbMembers in one central, the way a named session is: genome-test, hgwdev, every
hgwdev-<name> sandbox and every ticket park read hgcentraltest and share one
account, while hgwbeta reads hgcentralbeta and the RR reads hgcentral. So the
file is one [hgcentraltest] section rather than a section per sandbox.
Which central a server reads is READ from its hg.conf, following its includes the
way hgConfig.c does, and not guessed from the host -- because a sandbox can point
itself somewhere else and two on hgwdev do today: of the personal confs there, 45
set central.db=hgcentraltest, one sets hgcentralgsid and one hgcentralbeta. A
server whose conf is on another machine falls back to a small table (the RR, the
two mirrors, hgwbeta), and [default] catches the rest. A run redirected with
DOCENT_TARGET looks up the server it is really driving.
Two failures the step has to tell apart, and both cost a run to find:
A WRONG PASSWORD IS A PERFECTLY GOOD PAGE. hgLogin answers one by drawing the
same form again with a red message, so a step that just navigated on would leave
every later step running logged out and the failure would surface somewhere else
entirely. The step fails on #accountLoginForm still being there, and quotes what
the page said.
A RIGHT PASSWORD ARRIVES MID-REDIRECT. hgLogin answers one with a page that
navigates ITSELF a moment later: returnToURL(150) at hgLogin.c:1160 writes
setTimeout(function(){location=...}, 150). Returning while that timer is pending
means the next step's goto: races it and the browser aborts one of the two, which
arrives as a bare net::ERR_ABORTED on a URL that is completely fine. The step now
waits for that redirect to land. The failure path is checked first, since that
page never leaves hgLogin and there is no redirect to wait for.
preflight reports the account as a fixture -- which central it resolved, which
section it came from, and why it is unusable if it is -- so a missing password is
caught before the browser starts. It attempts no login: a wrong password fails
loudly at the step itself, which is the one thing preflight cannot do for it.
The hg.conf reader is now in both docent.js and tests/preflight.js, beside the
resolveTarget each of them already carries. Both say to keep the other in step.
If that second copy is a copy too many, the two of them want a shared module.
- lines changed 139, context: html, text, full: html, text
9b762c146f7a44a3bdc783cdd202356fc163b8fb Wed Sep 16 12:43:32 2026 -0700
docent: one targetConf.js for the target, the hg.conf, the central and the account, refs #37892
docent.js and tests/preflight.js had grown a second and then a third copy of the
same lookups. That is exactly the pair that must not drift: preflight checks the
fixtures for the server the RUN will drive, so a run that resolved its target, its
hg.conf, its hgcentral or its account even slightly differently would be checked
against the wrong machine, and the mismatch would show up as a green preflight in
front of a red suite.
targetConf.js answers the four questions in order, each from the one before:
resolveTarget a `target:` (or DOCENT_TARGET) -> the .../cgi-bin URL to drive
hgConfFor that URL -> the hg.conf it reads, if the server is on this box
centralDbFor that conf -> which hgcentral it uses
loginLookup that central -> the account to sign in with
Nothing in it opens a browser or the network, which is why preflight can ask all
four in the seconds before a run.
loginLookup returns the facts plus, when the account cannot be used, ONE sentence
saying why. That sentence is the substantive half and is now written once: the
step throws it with a `login:` prefix, preflight prints it on the MISSING line.
Each caller still phrases its own success line, since one logs and the other
prints a fixture row. No password crosses that boundary to anything that prints.
248 lines net out of the two programs, 197 into the module.
docent.js is no longer a single file, and three places now say so: its own require,
the Run section of README.md, and docent.mk, whose mp4 rule gains targetConf.js as
a prerequisite -- a change there changes what a tour renders, so it has to rebuild
one. Nothing in the tree or in ~/docentTours copies docent.js; they all reference
it where it sits, with targetConf.js beside it.
Measured before and after, with no other change: preflight resolves the same
account, central and conf for genome-test, hgwdev-braney, a ts park on 48087 and
hgwbeta (which correctly has no section); tests/ is 18 of 18 with the derive
baselines matching; tests/regress preflights 14 fixtures for 67 scripts.
- lines changed 11, context: html, text, full: html, text
6c2ecd053818535194c7845a899bca0ecd3c10d8 Thu Sep 17 17:08:10 2026 -0700
docent: preflight checks a session settings file named inside a goto: URL, refs #38252
`loadSession:` is the verb for a saved state, and preflight already checks the
file it names. But loadSession: builds its own URL, so a test about db= TOGETHER
with a session load has to spell the whole request out in a goto: -- and db= in
front of the load is the entire bug in #38184. The settings file it names rots
the same way any other fixture does, silently, because hgTracks answers a missing
one with a perfectly good page.
Read hgS_loadUrlName out of a goto: the way hubUrl is already read out of one.
- src/hg/utils/docent/tests/proof.js
- lines changed 3, context: html, text, full: html, text
bbe654a9dc89bc7b75d40d1fe197d5376d756580 Thu Sep 17 17:08:10 2026 -0700
docent: 22 regression tests for a QA list, and release-ab evidence from v503, refs #38252
One script per ticket for twenty-two that had none: rm10138, rm36940, rm37969,
rm38171, rm38184, rm38198, rm38200, rm38205, rm38206, rm38223, rm38236, rm38248,
rm38251, rm38257, rm38279, rm38281, rm38283, rm38284, rm38285, rm38302, rm38303
and rm38309. No theme -- they run from a menu-bar color to a SIGSEGV in a
quickLift view. Three fixtures came with them, under
~/public_html/docentFixtures: rm36940 (seven bigBed tracks differing only in the
field count on the type line), rm38283 (one description page full of dollar
variables) and rm38184 (a one-line session settings file).
Every one was then run against v503, which is what the new proof level is for.
v503_branch 707b184e329 went into a ticket sandbox -- CGIs, js and htdocs, since
three of the fixes live in hg/js or htdocs/style -- and twenty-one of the
twenty-four fix commits landed after that branch was cut, so the release has the
bugs. Eighteen scripts failed there on their own check and carry a release-ab
line quoting the failure.
release-ab sits between sandbox-ab and server-flip. It is stronger than
sandbox-ab because anyone can rebuild it from a tag, where a hand-patched tree
lives in one person's home directory and does not survive a rebase.
The four that v503 does not cover are each said in their own header: rm38171's
fix is IN v503 so an older release is its baseline; rm36940's fixture hub draws
nothing there, so the run never reaches the check; rm38257's login: dies against
a park on any baseline; and rm38309 PASSES, which is exactly what its header
claims, since that fix changes no byte of any page.
rm38251 had to be rewritten because of what the sweep said. It PASSED on a build
carrying its own bug, at every width from 390 to 1099px: the icon had slid 312px
left but was still inside the bar, and the clear: check named the links, where
the icon fell in a gap between two of them. Naming the menu list instead has no
gaps. Without the sweep it would have sat here looking green.
make proof: 89 scripts, 33 watched to fail for the reason they exist and then
pass, up from 13.
- src/hg/utils/docent/tests/regress/README.txt
- lines changed 51, context: html, text, full: html, text
9d4c4b4781eb714d844a98faa90a1909af541a80 Wed Sep 16 10:26:38 2026 -0700
docent: the sandbox-ab proof for nine scripts, and the two rules behind it, refs #38252
Nine scripts here went red on the #37547 cart-visibility branch and green on
master, for their own reason, on the same machine with the same hg.conf. That
is the sandbox-ab shape exactly, and it was going to be lost with the run. Each
now carries the line:
sandbox-ab 2026-09-16 -- failed on a #37547 cart-visibility build before the
isParentVisible fix in hg/lib/trackHub.c, passed on the same sandbox with the
fix and with master; the same hg.conf all three times
rm36048, rm36059, rm36061, rm36331, rm37553, rm37562, rm37615, rm37815 and
rm38032. make proof goes from 4 of 67 watched to fail and then pass, to 13.
The cause was one line: isParentVisible() read a container's visibility from the
bare cart key instead of through the accessor, so after migration it read
nothing, fell back to the trackDb default, decided the container was hidden, and
walkTree() left the track out of the lift hub.
Two rules come out of the same session and are now a section in README.txt.
Assert before you navigate. A bug in this area can lag by exactly one request:
the visibility reaches the cart, the image drawn in reply does not carry the row,
and any next request draws it. A script shaped track: -> go: -> expect: supplies
that extra request itself and passes on the broken build.
The exposure here is smaller than it looks, and worth writing down so it is not
re-counted: forty of the sixty-seven scripts have no track: step at all, and of
the twenty-five that do, twenty-three already assert straight after it. The two
that do not are rm36514 and rm37520, and neither can. Both turn on mane at the
ticket's own position, chr7:156,982,676-156,996,015, where mane has no features
on hg38 -- bigBedToBed on /gbdb/hg38/mane/mane.bb returns nothing there -- so
there is no row to name. The track controls read pack on a broken build too,
because the cart really did take the visibility. A comment in each says so, so
the gap is not read as an oversight and closed with a check that passes on
anything. tests/firstrequest.docent.yaml covers the class once, on its own.
Name a child of a container that is hidden by default. Two shapes of track stay
green on a build whose visibility handling is broken. A top-level track is added
as a lightweight stub so the track controls can list it, so it is built whatever
the cart lookup returned -- microsat, gtexGene and windowmaskerSdust all drew on
the broken build. A default-visible child has its container in the list already
-- wgEncodeRegMarkH3k27ac drew while its sibling wgEncodeRegMarkH3k4me1 did not,
same superTrack, same request, opposite verdicts. wgEncodeRegMarkH3k4me1 is the
known-good example. This is the cheapest rule in the file: it changes which
track a script names, not how the script is written, and without it a script
reads as coverage and is not.
The section on reading a redirected run points at make preflight TARGET=, which
now prints the target's central.db, db.trackDb, curatedHubPrefix and quickLift
settings, and says to swap only the binary when that is not enough.
No script's steps changed, so nothing here alters what the nightly measures.
make proof and both preflights are clean.
- lines changed 126, context: html, text, full: html, text
bbe654a9dc89bc7b75d40d1fe197d5376d756580 Thu Sep 17 17:08:10 2026 -0700
docent: 22 regression tests for a QA list, and release-ab evidence from v503, refs #38252
One script per ticket for twenty-two that had none: rm10138, rm36940, rm37969,
rm38171, rm38184, rm38198, rm38200, rm38205, rm38206, rm38223, rm38236, rm38248,
rm38251, rm38257, rm38279, rm38281, rm38283, rm38284, rm38285, rm38302, rm38303
and rm38309. No theme -- they run from a menu-bar color to a SIGSEGV in a
quickLift view. Three fixtures came with them, under
~/public_html/docentFixtures: rm36940 (seven bigBed tracks differing only in the
field count on the type line), rm38283 (one description page full of dollar
variables) and rm38184 (a one-line session settings file).
Every one was then run against v503, which is what the new proof level is for.
v503_branch 707b184e329 went into a ticket sandbox -- CGIs, js and htdocs, since
three of the fixes live in hg/js or htdocs/style -- and twenty-one of the
twenty-four fix commits landed after that branch was cut, so the release has the
bugs. Eighteen scripts failed there on their own check and carry a release-ab
line quoting the failure.
release-ab sits between sandbox-ab and server-flip. It is stronger than
sandbox-ab because anyone can rebuild it from a tag, where a hand-patched tree
lives in one person's home directory and does not survive a rebase.
The four that v503 does not cover are each said in their own header: rm38171's
fix is IN v503 so an older release is its baseline; rm36940's fixture hub draws
nothing there, so the run never reaches the check; rm38257's login: dies against
a park on any baseline; and rm38309 PASSES, which is exactly what its header
claims, since that fix changes no byte of any page.
rm38251 had to be rewritten because of what the sweep said. It PASSED on a build
carrying its own bug, at every width from 390 to 1099px: the icon had slid 312px
left but was still inside the bar, and the clear: check named the links, where
the icon fell in a gap between two of them. Naming the menu list instead has no
gaps. Without the sweep it would have sat here looking green.
make proof: 89 scripts, 33 watched to fail for the reason they exist and then
pass, up from 13.
- lines changed 36, context: html, text, full: html, text
b7fe2f0542ac4a5e182b86ab6f794de34d0ff0d8 Sat Sep 19 10:17:09 2026 -0700
docent: six regression scripts written from the tours, refs #38252
rm38335 rm38298 rm37996 rm38249 rm38268 rm38364, one per ticket that got a
before-and-after tour this week. 95 scripts now, make proof 45 of 95, and the
whole directory is green against genome-test.
Five of the six carry release-ab and the sixth sandbox-ab on their first day,
which is unusual here and is only because the before had already been rendered
and measured for the ticket comment: hgwbeta returns "Mangled CGI input string
bogus" (rm38335), one codon number instead of two (rm38298), the ASCII table
with no banner (rm37996), "not supported by QuickLift" for all four alignment
families (rm38249) and "Can't find strchive in track database hg19" (rm38268).
rm38364's before is ts park 38373, master frozen two days before that feature
merged, since it is newer than any release.
Three things they cost, each also in README.txt:
* where the text lives decides how it is read. rm38309 reads its exon text
out of a map box's data-tooltip, but rm38298's codon tooltip is not in the
served map at all -- the page's own JavaScript builds it on mouseenter --
so that one hovers and asserts tip:. rm38268's item label is in the drawn
PNG and nowhere else, so it asserts the map box's href and tooltip rather
than a text: that can never match.
* a superTrack still does not pass its setting to its members. rm38268 opens
strVar to reach strchive and then cannot use exact: on hg38, because the
sibling repeat tracks come up at their own visibilities.
* an hg.conf gate belongs in the header, loudly. rm38364 fails every check
when denseClick is off, and that is a configuration answer rather than a
regression, so the header carries the grep that settles it.
rm37996 has a date on it. The new hgBlat results page is opt-in while it is
tested and the banner names 2026-10-21 as the day it becomes the default; on
that day the first two steps come out and the goto: gains blatNewPage=1.
- lines changed 77, context: html, text, full: html, text
c52d505f538f7636e48aa5c06b9ad208697471a9 Sun Sep 20 14:34:31 2026 -0700
docent: three regression scripts for tickets nothing was watching, refs #38252
#38391's test registry named four tickets with neither a unit test nor a script
here. These are three of them. They have little else in common, and each needed
a different answer to the same question: what about this bug is steady enough to
assert. 98 scripts now, `make proof` 46 of 98.
rm38253, the coverage-graph rewrite. Its fixture is six features on hg38 chr1,
three nested inside each other in each of two groups, so their coverage is a
staircase with FLAT steps: 1 2 3 2 1 over 20 kb, and the same again over 20 bp.
Flat is the point. Each pixel's value is the mean coverage of the bases it
covers, and the mean of a constant is that constant, so a reading taken in the
middle of a step does not depend on where a pixel boundary falls, on insideWidth,
or on the window being a round number of bases. The two windows take the two
sampling paths on purpose, and the 200 bp one is countsToPixelsUp, which
pixelSweep.sh never reaches because every cell in it is wider than insideWidth.
The script CANNOT flip on its own fix and its header says so: #38253 is a rewrite
required to draw the same picture it replaced, verified with 96 pixel comparisons,
so both builds answer the same and no baseline can tell them apart. What was
proved instead is that the checks discriminate, by pointing each of the twelve
readings at a neighbouring step's value: all twelve went red.
rm38317, the knownGene page that prints an OMIM link built from uninitialised
memory. The link itself is the wrong thing to test for, since it is whatever was
on the stack and comes and goes between loads of the same URL; an earlier probe
of this ticket asked only for its absence and concluded the bug did not reproduce.
The same struct is read a second time further down, and that read is deterministic:
the page stops dead right after "Links to sequence:", with no Translated Protein
link and no Genomic Sequence link, on every load of all three assemblies. Lou
Nassar's note of 2026-09-18 is what identified that; the description does not
mention it. Measured on hgwbeta against genome-test, 2026-09-20: 17,487 to 27,026
bytes on hg19, 17,656 to 27,456 on hg38, 17,484 to 25,616 on mm39. So this one
carries a release-ab line. A RefSeq page is the control, where the OMIM link is
real and must still be there.
rm38086, the BLAT Results track group. It runs a real search, lets the results
page build its own custom track through its ajax to hgc, and then asks for the
group, the Delete all button, the per-track delete icon, the row being DRAWN
(5915dcd2939: a result track used to come up hidden) and both new names. Two
names in full, each a different half of 4fd18ab7854: "102bp SMYD4" for a
nucleotide query and "60aa TP53" for a protein one, where the aa is the point.
The old name "blat YourSeq" is asserted absent. hgwbeta is NOT a baseline for
it: v503_branch already carries these commits, so beta answering with the old
name is almost certainly hg.conf blatResultsGroup being off, and preflight
cannot read beta's hg.conf from here to settle it. Assertion-only, and the
header says why rather than leaving the next reader to try beta again.
The fixture hub is ~/public_html/docentFixtures/rm38253, beside the others.
README.txt gains a section on all of this, including one trap worth repeating:
never assert a title attribute, not even on a button. rm38086's first draft
matched `button#blat_delAll[title=...]`, which is in the served HTML and matches
nothing once hgTracks has copied every title into a mouseoverText attribute.
- src/hg/utils/docent/tests/regress/rm10138.docent.yaml
- lines changed 78, context: html, text, full: html, text
bbe654a9dc89bc7b75d40d1fe197d5376d756580 Thu Sep 17 17:08:10 2026 -0700
docent: 22 regression tests for a QA list, and release-ab evidence from v503, refs #38252
One script per ticket for twenty-two that had none: rm10138, rm36940, rm37969,
rm38171, rm38184, rm38198, rm38200, rm38205, rm38206, rm38223, rm38236, rm38248,
rm38251, rm38257, rm38279, rm38281, rm38283, rm38284, rm38285, rm38302, rm38303
and rm38309. No theme -- they run from a menu-bar color to a SIGSEGV in a
quickLift view. Three fixtures came with them, under
~/public_html/docentFixtures: rm36940 (seven bigBed tracks differing only in the
field count on the type line), rm38283 (one description page full of dollar
variables) and rm38184 (a one-line session settings file).
Every one was then run against v503, which is what the new proof level is for.
v503_branch 707b184e329 went into a ticket sandbox -- CGIs, js and htdocs, since
three of the fixes live in hg/js or htdocs/style -- and twenty-one of the
twenty-four fix commits landed after that branch was cut, so the release has the
bugs. Eighteen scripts failed there on their own check and carry a release-ab
line quoting the failure.
release-ab sits between sandbox-ab and server-flip. It is stronger than
sandbox-ab because anyone can rebuild it from a tag, where a hand-patched tree
lives in one person's home directory and does not survive a rebase.
The four that v503 does not cover are each said in their own header: rm38171's
fix is IN v503 so an older release is its baseline; rm36940's fixture hub draws
nothing there, so the run never reaches the check; rm38257's login: dies against
a park on any baseline; and rm38309 PASSES, which is exactly what its header
claims, since that fix changes no byte of any page.
rm38251 had to be rewritten because of what the sweep said. It PASSED on a build
carrying its own bug, at every width from 390 to 1099px: the icon had slid 312px
left but was still inside the bar, and the clear: check named the links, where
the icon fell in a gap between two of them. Naming the menu list instead has no
gaps. Without the sweep it would have sat here looking green.
make proof: 89 scripts, 33 watched to fail for the reason they exist and then
pass, up from 13.
- src/hg/utils/docent/tests/regress/rm27113.docent.yaml
- lines changed 1, context: html, text, full: html, text
cd13b3b171159247f1d105f650cce2a0726cd67b Fri Sep 18 16:08:59 2026 -0700
docent: release-ab evidence for six scripts, from the released docker images, refs #38252
Six scripts move from assertion-only to release-ab. The baselines are the released
v499 to v503 docker images running on hgwdev, which give what the v503 ticket park
could not: a range of releases rather than a single one.
Three were watched to flip, and each flips at exactly the release its fix first
ships in, which is what says the failure is the ticket's own and not version drift:
rm27113 fails v499 v500, passes v501 94f9b53d3db and b551f6c3ac8 first ship in v501
rm37743 fails v499, passes v500 7b74ff4b43a first ships in v500
rm38108 fails v499 to v502, passes v503 7181c0af889 first ships in v503
Three fail on every released image and pass on genome-test, which is correct rather
than a gap: their fixes are on master only and ship in v504.
rm38126 the descPage- prefix is absent on every release
rm38185 the position after an empty CGI pair is eaten on every release
rm38309 the exon tooltip the fix adds is absent on every release
Each failure was read rather than counted. rm27113 fails on a position with the page
otherwise whole at 10 rows; rm37743 fails on its own error string; rm38108 draws no
ruler at all, which is the crash it covers.
Two candidates were rejected after looking at them, and are worth naming so they are
not re-picked. rm34651 appears to flip at v500, but fa3431cd36b is already in v499 and
the clinvar track simply has no density options there, so the flip is not its own.
rm35333 appeared to flip and did not: it reads an hs1 hub, and hs1 was repaired in the
images midway through the sweep, so the flip was the repair rather than the code.
make proof: 39 of 89, up from 33.
- src/hg/utils/docent/tests/regress/rm36048.docent.yaml
- lines changed 1, context: html, text, full: html, text
9d4c4b4781eb714d844a98faa90a1909af541a80 Wed Sep 16 10:26:38 2026 -0700
docent: the sandbox-ab proof for nine scripts, and the two rules behind it, refs #38252
Nine scripts here went red on the #37547 cart-visibility branch and green on
master, for their own reason, on the same machine with the same hg.conf. That
is the sandbox-ab shape exactly, and it was going to be lost with the run. Each
now carries the line:
sandbox-ab 2026-09-16 -- failed on a #37547 cart-visibility build before the
isParentVisible fix in hg/lib/trackHub.c, passed on the same sandbox with the
fix and with master; the same hg.conf all three times
rm36048, rm36059, rm36061, rm36331, rm37553, rm37562, rm37615, rm37815 and
rm38032. make proof goes from 4 of 67 watched to fail and then pass, to 13.
The cause was one line: isParentVisible() read a container's visibility from the
bare cart key instead of through the accessor, so after migration it read
nothing, fell back to the trackDb default, decided the container was hidden, and
walkTree() left the track out of the lift hub.
Two rules come out of the same session and are now a section in README.txt.
Assert before you navigate. A bug in this area can lag by exactly one request:
the visibility reaches the cart, the image drawn in reply does not carry the row,
and any next request draws it. A script shaped track: -> go: -> expect: supplies
that extra request itself and passes on the broken build.
The exposure here is smaller than it looks, and worth writing down so it is not
re-counted: forty of the sixty-seven scripts have no track: step at all, and of
the twenty-five that do, twenty-three already assert straight after it. The two
that do not are rm36514 and rm37520, and neither can. Both turn on mane at the
ticket's own position, chr7:156,982,676-156,996,015, where mane has no features
on hg38 -- bigBedToBed on /gbdb/hg38/mane/mane.bb returns nothing there -- so
there is no row to name. The track controls read pack on a broken build too,
because the cart really did take the visibility. A comment in each says so, so
the gap is not read as an oversight and closed with a check that passes on
anything. tests/firstrequest.docent.yaml covers the class once, on its own.
Name a child of a container that is hidden by default. Two shapes of track stay
green on a build whose visibility handling is broken. A top-level track is added
as a lightweight stub so the track controls can list it, so it is built whatever
the cart lookup returned -- microsat, gtexGene and windowmaskerSdust all drew on
the broken build. A default-visible child has its container in the list already
-- wgEncodeRegMarkH3k27ac drew while its sibling wgEncodeRegMarkH3k4me1 did not,
same superTrack, same request, opposite verdicts. wgEncodeRegMarkH3k4me1 is the
known-good example. This is the cheapest rule in the file: it changes which
track a script names, not how the script is written, and without it a script
reads as coverage and is not.
The section on reading a redirected run points at make preflight TARGET=, which
now prints the target's central.db, db.trackDb, curatedHubPrefix and quickLift
settings, and says to swap only the binary when that is not enough.
No script's steps changed, so nothing here alters what the nightly measures.
make proof and both preflights are clean.
- src/hg/utils/docent/tests/regress/rm36059.docent.yaml
- lines changed 1, context: html, text, full: html, text
9d4c4b4781eb714d844a98faa90a1909af541a80 Wed Sep 16 10:26:38 2026 -0700
docent: the sandbox-ab proof for nine scripts, and the two rules behind it, refs #38252
Nine scripts here went red on the #37547 cart-visibility branch and green on
master, for their own reason, on the same machine with the same hg.conf. That
is the sandbox-ab shape exactly, and it was going to be lost with the run. Each
now carries the line:
sandbox-ab 2026-09-16 -- failed on a #37547 cart-visibility build before the
isParentVisible fix in hg/lib/trackHub.c, passed on the same sandbox with the
fix and with master; the same hg.conf all three times
rm36048, rm36059, rm36061, rm36331, rm37553, rm37562, rm37615, rm37815 and
rm38032. make proof goes from 4 of 67 watched to fail and then pass, to 13.
The cause was one line: isParentVisible() read a container's visibility from the
bare cart key instead of through the accessor, so after migration it read
nothing, fell back to the trackDb default, decided the container was hidden, and
walkTree() left the track out of the lift hub.
Two rules come out of the same session and are now a section in README.txt.
Assert before you navigate. A bug in this area can lag by exactly one request:
the visibility reaches the cart, the image drawn in reply does not carry the row,
and any next request draws it. A script shaped track: -> go: -> expect: supplies
that extra request itself and passes on the broken build.
The exposure here is smaller than it looks, and worth writing down so it is not
re-counted: forty of the sixty-seven scripts have no track: step at all, and of
the twenty-five that do, twenty-three already assert straight after it. The two
that do not are rm36514 and rm37520, and neither can. Both turn on mane at the
ticket's own position, chr7:156,982,676-156,996,015, where mane has no features
on hg38 -- bigBedToBed on /gbdb/hg38/mane/mane.bb returns nothing there -- so
there is no row to name. The track controls read pack on a broken build too,
because the cart really did take the visibility. A comment in each says so, so
the gap is not read as an oversight and closed with a check that passes on
anything. tests/firstrequest.docent.yaml covers the class once, on its own.
Name a child of a container that is hidden by default. Two shapes of track stay
green on a build whose visibility handling is broken. A top-level track is added
as a lightweight stub so the track controls can list it, so it is built whatever
the cart lookup returned -- microsat, gtexGene and windowmaskerSdust all drew on
the broken build. A default-visible child has its container in the list already
-- wgEncodeRegMarkH3k27ac drew while its sibling wgEncodeRegMarkH3k4me1 did not,
same superTrack, same request, opposite verdicts. wgEncodeRegMarkH3k4me1 is the
known-good example. This is the cheapest rule in the file: it changes which
track a script names, not how the script is written, and without it a script
reads as coverage and is not.
The section on reading a redirected run points at make preflight TARGET=, which
now prints the target's central.db, db.trackDb, curatedHubPrefix and quickLift
settings, and says to swap only the binary when that is not enough.
No script's steps changed, so nothing here alters what the nightly measures.
make proof and both preflights are clean.
- src/hg/utils/docent/tests/regress/rm36061.docent.yaml
- lines changed 1, context: html, text, full: html, text
9d4c4b4781eb714d844a98faa90a1909af541a80 Wed Sep 16 10:26:38 2026 -0700
docent: the sandbox-ab proof for nine scripts, and the two rules behind it, refs #38252
Nine scripts here went red on the #37547 cart-visibility branch and green on
master, for their own reason, on the same machine with the same hg.conf. That
is the sandbox-ab shape exactly, and it was going to be lost with the run. Each
now carries the line:
sandbox-ab 2026-09-16 -- failed on a #37547 cart-visibility build before the
isParentVisible fix in hg/lib/trackHub.c, passed on the same sandbox with the
fix and with master; the same hg.conf all three times
rm36048, rm36059, rm36061, rm36331, rm37553, rm37562, rm37615, rm37815 and
rm38032. make proof goes from 4 of 67 watched to fail and then pass, to 13.
The cause was one line: isParentVisible() read a container's visibility from the
bare cart key instead of through the accessor, so after migration it read
nothing, fell back to the trackDb default, decided the container was hidden, and
walkTree() left the track out of the lift hub.
Two rules come out of the same session and are now a section in README.txt.
Assert before you navigate. A bug in this area can lag by exactly one request:
the visibility reaches the cart, the image drawn in reply does not carry the row,
and any next request draws it. A script shaped track: -> go: -> expect: supplies
that extra request itself and passes on the broken build.
The exposure here is smaller than it looks, and worth writing down so it is not
re-counted: forty of the sixty-seven scripts have no track: step at all, and of
the twenty-five that do, twenty-three already assert straight after it. The two
that do not are rm36514 and rm37520, and neither can. Both turn on mane at the
ticket's own position, chr7:156,982,676-156,996,015, where mane has no features
on hg38 -- bigBedToBed on /gbdb/hg38/mane/mane.bb returns nothing there -- so
there is no row to name. The track controls read pack on a broken build too,
because the cart really did take the visibility. A comment in each says so, so
the gap is not read as an oversight and closed with a check that passes on
anything. tests/firstrequest.docent.yaml covers the class once, on its own.
Name a child of a container that is hidden by default. Two shapes of track stay
green on a build whose visibility handling is broken. A top-level track is added
as a lightweight stub so the track controls can list it, so it is built whatever
the cart lookup returned -- microsat, gtexGene and windowmaskerSdust all drew on
the broken build. A default-visible child has its container in the list already
-- wgEncodeRegMarkH3k27ac drew while its sibling wgEncodeRegMarkH3k4me1 did not,
same superTrack, same request, opposite verdicts. wgEncodeRegMarkH3k4me1 is the
known-good example. This is the cheapest rule in the file: it changes which
track a script names, not how the script is written, and without it a script
reads as coverage and is not.
The section on reading a redirected run points at make preflight TARGET=, which
now prints the target's central.db, db.trackDb, curatedHubPrefix and quickLift
settings, and says to swap only the binary when that is not enough.
No script's steps changed, so nothing here alters what the nightly measures.
make proof and both preflights are clean.
- src/hg/utils/docent/tests/regress/rm36331.docent.yaml
- lines changed 1, context: html, text, full: html, text
9d4c4b4781eb714d844a98faa90a1909af541a80 Wed Sep 16 10:26:38 2026 -0700
docent: the sandbox-ab proof for nine scripts, and the two rules behind it, refs #38252
Nine scripts here went red on the #37547 cart-visibility branch and green on
master, for their own reason, on the same machine with the same hg.conf. That
is the sandbox-ab shape exactly, and it was going to be lost with the run. Each
now carries the line:
sandbox-ab 2026-09-16 -- failed on a #37547 cart-visibility build before the
isParentVisible fix in hg/lib/trackHub.c, passed on the same sandbox with the
fix and with master; the same hg.conf all three times
rm36048, rm36059, rm36061, rm36331, rm37553, rm37562, rm37615, rm37815 and
rm38032. make proof goes from 4 of 67 watched to fail and then pass, to 13.
The cause was one line: isParentVisible() read a container's visibility from the
bare cart key instead of through the accessor, so after migration it read
nothing, fell back to the trackDb default, decided the container was hidden, and
walkTree() left the track out of the lift hub.
Two rules come out of the same session and are now a section in README.txt.
Assert before you navigate. A bug in this area can lag by exactly one request:
the visibility reaches the cart, the image drawn in reply does not carry the row,
and any next request draws it. A script shaped track: -> go: -> expect: supplies
that extra request itself and passes on the broken build.
The exposure here is smaller than it looks, and worth writing down so it is not
re-counted: forty of the sixty-seven scripts have no track: step at all, and of
the twenty-five that do, twenty-three already assert straight after it. The two
that do not are rm36514 and rm37520, and neither can. Both turn on mane at the
ticket's own position, chr7:156,982,676-156,996,015, where mane has no features
on hg38 -- bigBedToBed on /gbdb/hg38/mane/mane.bb returns nothing there -- so
there is no row to name. The track controls read pack on a broken build too,
because the cart really did take the visibility. A comment in each says so, so
the gap is not read as an oversight and closed with a check that passes on
anything. tests/firstrequest.docent.yaml covers the class once, on its own.
Name a child of a container that is hidden by default. Two shapes of track stay
green on a build whose visibility handling is broken. A top-level track is added
as a lightweight stub so the track controls can list it, so it is built whatever
the cart lookup returned -- microsat, gtexGene and windowmaskerSdust all drew on
the broken build. A default-visible child has its container in the list already
-- wgEncodeRegMarkH3k27ac drew while its sibling wgEncodeRegMarkH3k4me1 did not,
same superTrack, same request, opposite verdicts. wgEncodeRegMarkH3k4me1 is the
known-good example. This is the cheapest rule in the file: it changes which
track a script names, not how the script is written, and without it a script
reads as coverage and is not.
The section on reading a redirected run points at make preflight TARGET=, which
now prints the target's central.db, db.trackDb, curatedHubPrefix and quickLift
settings, and says to swap only the binary when that is not enough.
No script's steps changed, so nothing here alters what the nightly measures.
make proof and both preflights are clean.
- src/hg/utils/docent/tests/regress/rm36514.docent.yaml
- lines changed 9, context: html, text, full: html, text
9d4c4b4781eb714d844a98faa90a1909af541a80 Wed Sep 16 10:26:38 2026 -0700
docent: the sandbox-ab proof for nine scripts, and the two rules behind it, refs #38252
Nine scripts here went red on the #37547 cart-visibility branch and green on
master, for their own reason, on the same machine with the same hg.conf. That
is the sandbox-ab shape exactly, and it was going to be lost with the run. Each
now carries the line:
sandbox-ab 2026-09-16 -- failed on a #37547 cart-visibility build before the
isParentVisible fix in hg/lib/trackHub.c, passed on the same sandbox with the
fix and with master; the same hg.conf all three times
rm36048, rm36059, rm36061, rm36331, rm37553, rm37562, rm37615, rm37815 and
rm38032. make proof goes from 4 of 67 watched to fail and then pass, to 13.
The cause was one line: isParentVisible() read a container's visibility from the
bare cart key instead of through the accessor, so after migration it read
nothing, fell back to the trackDb default, decided the container was hidden, and
walkTree() left the track out of the lift hub.
Two rules come out of the same session and are now a section in README.txt.
Assert before you navigate. A bug in this area can lag by exactly one request:
the visibility reaches the cart, the image drawn in reply does not carry the row,
and any next request draws it. A script shaped track: -> go: -> expect: supplies
that extra request itself and passes on the broken build.
The exposure here is smaller than it looks, and worth writing down so it is not
re-counted: forty of the sixty-seven scripts have no track: step at all, and of
the twenty-five that do, twenty-three already assert straight after it. The two
that do not are rm36514 and rm37520, and neither can. Both turn on mane at the
ticket's own position, chr7:156,982,676-156,996,015, where mane has no features
on hg38 -- bigBedToBed on /gbdb/hg38/mane/mane.bb returns nothing there -- so
there is no row to name. The track controls read pack on a broken build too,
because the cart really did take the visibility. A comment in each says so, so
the gap is not read as an oversight and closed with a check that passes on
anything. tests/firstrequest.docent.yaml covers the class once, on its own.
Name a child of a container that is hidden by default. Two shapes of track stay
green on a build whose visibility handling is broken. A top-level track is added
as a lightweight stub so the track controls can list it, so it is built whatever
the cart lookup returned -- microsat, gtexGene and windowmaskerSdust all drew on
the broken build. A default-visible child has its container in the list already
-- wgEncodeRegMarkH3k27ac drew while its sibling wgEncodeRegMarkH3k4me1 did not,
same superTrack, same request, opposite verdicts. wgEncodeRegMarkH3k4me1 is the
known-good example. This is the cheapest rule in the file: it changes which
track a script names, not how the script is written, and without it a script
reads as coverage and is not.
The section on reading a redirected run points at make preflight TARGET=, which
now prints the target's central.db, db.trackDb, curatedHubPrefix and quickLift
settings, and says to swap only the binary when that is not enough.
No script's steps changed, so nothing here alters what the nightly measures.
make proof and both preflights are clean.
- src/hg/utils/docent/tests/regress/rm36888.xfail.docent.yaml
- lines changed 15, context: html, text, full: html, text
38f431f1d75c92d3c0518f60f141008ae72d133b Fri Sep 18 09:56:52 2026 -0700
docent: retranslate the density-label checks after the reword, refs #38252
07f0635fd35 reworded all three density-mode labels on 2026-09-18, and the 04:10
nightly went red on rm38279 four hours later. The code is right; the scripts
asserted wording that no longer exists.
rm38279 covers all three causes, so all four of its label steps move. The two
automatic messages are now "density graph: too many items, zoom in" for a window
past maxWindowCoverage and "density graph: too many items, zoom in or use dense"
for too many features, and the first is a strict PREFIX of the second.
mouseoverText*= is a substring match, so a bare noHas on the shorter one matches
the longer one too and fails on the track it is meant to pass. labelAddNote()
wraps a note as " (%s)", so every check now carries the closing paren and each
message matches itself and nothing else. Verified by pointing each has: at the
wrong message in turn: all three fail, including the prefix case. Step 5 went
from two noHas lines to one, since all three notes now share a prefix.
rm36888.xfail asserts the same old string twice and nobody asked about it,
because it is an xfail and it stayed red. It is still red for its own reason --
the run says `rows not drawn: rm36888Methyl`, with the note check second -- but
the stale string was a trap on a delay: when the bigMethyl fix lands, the row
draws, the note appears with the new wording, the has: still misses, and the
xfail never flips. Both its selectors now match "density graph: too many items",
the prefix the two automatic causes share, which is what the pre-reword string
did as well. The full sentence is the one that bug should produce, but nobody
can see it until the fix lands, and an exact string guessed from the source
would rebuild the trap. Tighten it on the day it goes green.
The release-ab line on rm38279 still stands: v503 carries no density note at
all, so a reword cannot reach it.
- src/hg/utils/docent/tests/regress/rm36940.docent.yaml
- lines changed 113, context: html, text, full: html, text
bbe654a9dc89bc7b75d40d1fe197d5376d756580 Thu Sep 17 17:08:10 2026 -0700
docent: 22 regression tests for a QA list, and release-ab evidence from v503, refs #38252
One script per ticket for twenty-two that had none: rm10138, rm36940, rm37969,
rm38171, rm38184, rm38198, rm38200, rm38205, rm38206, rm38223, rm38236, rm38248,
rm38251, rm38257, rm38279, rm38281, rm38283, rm38284, rm38285, rm38302, rm38303
and rm38309. No theme -- they run from a menu-bar color to a SIGSEGV in a
quickLift view. Three fixtures came with them, under
~/public_html/docentFixtures: rm36940 (seven bigBed tracks differing only in the
field count on the type line), rm38283 (one description page full of dollar
variables) and rm38184 (a one-line session settings file).
Every one was then run against v503, which is what the new proof level is for.
v503_branch 707b184e329 went into a ticket sandbox -- CGIs, js and htdocs, since
three of the fixes live in hg/js or htdocs/style -- and twenty-one of the
twenty-four fix commits landed after that branch was cut, so the release has the
bugs. Eighteen scripts failed there on their own check and carry a release-ab
line quoting the failure.
release-ab sits between sandbox-ab and server-flip. It is stronger than
sandbox-ab because anyone can rebuild it from a tag, where a hand-patched tree
lives in one person's home directory and does not survive a rebase.
The four that v503 does not cover are each said in their own header: rm38171's
fix is IN v503 so an older release is its baseline; rm36940's fixture hub draws
nothing there, so the run never reaches the check; rm38257's login: dies against
a park on any baseline; and rm38309 PASSES, which is exactly what its header
claims, since that fix changes no byte of any page.
rm38251 had to be rewritten because of what the sweep said. It PASSED on a build
carrying its own bug, at every width from 390 to 1099px: the icon had slid 312px
left but was still inside the bar, and the clear: check named the links, where
the icon fell in a gap between two of them. Naming the menu list instead has no
gaps. Without the sweep it would have sat here looking green.
make proof: 89 scripts, 33 watched to fail for the reason they exist and then
pass, up from 13.
- src/hg/utils/docent/tests/regress/rm37520.docent.yaml
- lines changed 9, context: html, text, full: html, text
9d4c4b4781eb714d844a98faa90a1909af541a80 Wed Sep 16 10:26:38 2026 -0700
docent: the sandbox-ab proof for nine scripts, and the two rules behind it, refs #38252
Nine scripts here went red on the #37547 cart-visibility branch and green on
master, for their own reason, on the same machine with the same hg.conf. That
is the sandbox-ab shape exactly, and it was going to be lost with the run. Each
now carries the line:
sandbox-ab 2026-09-16 -- failed on a #37547 cart-visibility build before the
isParentVisible fix in hg/lib/trackHub.c, passed on the same sandbox with the
fix and with master; the same hg.conf all three times
rm36048, rm36059, rm36061, rm36331, rm37553, rm37562, rm37615, rm37815 and
rm38032. make proof goes from 4 of 67 watched to fail and then pass, to 13.
The cause was one line: isParentVisible() read a container's visibility from the
bare cart key instead of through the accessor, so after migration it read
nothing, fell back to the trackDb default, decided the container was hidden, and
walkTree() left the track out of the lift hub.
Two rules come out of the same session and are now a section in README.txt.
Assert before you navigate. A bug in this area can lag by exactly one request:
the visibility reaches the cart, the image drawn in reply does not carry the row,
and any next request draws it. A script shaped track: -> go: -> expect: supplies
that extra request itself and passes on the broken build.
The exposure here is smaller than it looks, and worth writing down so it is not
re-counted: forty of the sixty-seven scripts have no track: step at all, and of
the twenty-five that do, twenty-three already assert straight after it. The two
that do not are rm36514 and rm37520, and neither can. Both turn on mane at the
ticket's own position, chr7:156,982,676-156,996,015, where mane has no features
on hg38 -- bigBedToBed on /gbdb/hg38/mane/mane.bb returns nothing there -- so
there is no row to name. The track controls read pack on a broken build too,
because the cart really did take the visibility. A comment in each says so, so
the gap is not read as an oversight and closed with a check that passes on
anything. tests/firstrequest.docent.yaml covers the class once, on its own.
Name a child of a container that is hidden by default. Two shapes of track stay
green on a build whose visibility handling is broken. A top-level track is added
as a lightweight stub so the track controls can list it, so it is built whatever
the cart lookup returned -- microsat, gtexGene and windowmaskerSdust all drew on
the broken build. A default-visible child has its container in the list already
-- wgEncodeRegMarkH3k27ac drew while its sibling wgEncodeRegMarkH3k4me1 did not,
same superTrack, same request, opposite verdicts. wgEncodeRegMarkH3k4me1 is the
known-good example. This is the cheapest rule in the file: it changes which
track a script names, not how the script is written, and without it a script
reads as coverage and is not.
The section on reading a redirected run points at make preflight TARGET=, which
now prints the target's central.db, db.trackDb, curatedHubPrefix and quickLift
settings, and says to swap only the binary when that is not enough.
No script's steps changed, so nothing here alters what the nightly measures.
make proof and both preflights are clean.
- src/hg/utils/docent/tests/regress/rm37553.docent.yaml
- lines changed 1, context: html, text, full: html, text
9d4c4b4781eb714d844a98faa90a1909af541a80 Wed Sep 16 10:26:38 2026 -0700
docent: the sandbox-ab proof for nine scripts, and the two rules behind it, refs #38252
Nine scripts here went red on the #37547 cart-visibility branch and green on
master, for their own reason, on the same machine with the same hg.conf. That
is the sandbox-ab shape exactly, and it was going to be lost with the run. Each
now carries the line:
sandbox-ab 2026-09-16 -- failed on a #37547 cart-visibility build before the
isParentVisible fix in hg/lib/trackHub.c, passed on the same sandbox with the
fix and with master; the same hg.conf all three times
rm36048, rm36059, rm36061, rm36331, rm37553, rm37562, rm37615, rm37815 and
rm38032. make proof goes from 4 of 67 watched to fail and then pass, to 13.
The cause was one line: isParentVisible() read a container's visibility from the
bare cart key instead of through the accessor, so after migration it read
nothing, fell back to the trackDb default, decided the container was hidden, and
walkTree() left the track out of the lift hub.
Two rules come out of the same session and are now a section in README.txt.
Assert before you navigate. A bug in this area can lag by exactly one request:
the visibility reaches the cart, the image drawn in reply does not carry the row,
and any next request draws it. A script shaped track: -> go: -> expect: supplies
that extra request itself and passes on the broken build.
The exposure here is smaller than it looks, and worth writing down so it is not
re-counted: forty of the sixty-seven scripts have no track: step at all, and of
the twenty-five that do, twenty-three already assert straight after it. The two
that do not are rm36514 and rm37520, and neither can. Both turn on mane at the
ticket's own position, chr7:156,982,676-156,996,015, where mane has no features
on hg38 -- bigBedToBed on /gbdb/hg38/mane/mane.bb returns nothing there -- so
there is no row to name. The track controls read pack on a broken build too,
because the cart really did take the visibility. A comment in each says so, so
the gap is not read as an oversight and closed with a check that passes on
anything. tests/firstrequest.docent.yaml covers the class once, on its own.
Name a child of a container that is hidden by default. Two shapes of track stay
green on a build whose visibility handling is broken. A top-level track is added
as a lightweight stub so the track controls can list it, so it is built whatever
the cart lookup returned -- microsat, gtexGene and windowmaskerSdust all drew on
the broken build. A default-visible child has its container in the list already
-- wgEncodeRegMarkH3k27ac drew while its sibling wgEncodeRegMarkH3k4me1 did not,
same superTrack, same request, opposite verdicts. wgEncodeRegMarkH3k4me1 is the
known-good example. This is the cheapest rule in the file: it changes which
track a script names, not how the script is written, and without it a script
reads as coverage and is not.
The section on reading a redirected run points at make preflight TARGET=, which
now prints the target's central.db, db.trackDb, curatedHubPrefix and quickLift
settings, and says to swap only the binary when that is not enough.
No script's steps changed, so nothing here alters what the nightly measures.
make proof and both preflights are clean.
- src/hg/utils/docent/tests/regress/rm37562.docent.yaml
- lines changed 1, context: html, text, full: html, text
9d4c4b4781eb714d844a98faa90a1909af541a80 Wed Sep 16 10:26:38 2026 -0700
docent: the sandbox-ab proof for nine scripts, and the two rules behind it, refs #38252
Nine scripts here went red on the #37547 cart-visibility branch and green on
master, for their own reason, on the same machine with the same hg.conf. That
is the sandbox-ab shape exactly, and it was going to be lost with the run. Each
now carries the line:
sandbox-ab 2026-09-16 -- failed on a #37547 cart-visibility build before the
isParentVisible fix in hg/lib/trackHub.c, passed on the same sandbox with the
fix and with master; the same hg.conf all three times
rm36048, rm36059, rm36061, rm36331, rm37553, rm37562, rm37615, rm37815 and
rm38032. make proof goes from 4 of 67 watched to fail and then pass, to 13.
The cause was one line: isParentVisible() read a container's visibility from the
bare cart key instead of through the accessor, so after migration it read
nothing, fell back to the trackDb default, decided the container was hidden, and
walkTree() left the track out of the lift hub.
Two rules come out of the same session and are now a section in README.txt.
Assert before you navigate. A bug in this area can lag by exactly one request:
the visibility reaches the cart, the image drawn in reply does not carry the row,
and any next request draws it. A script shaped track: -> go: -> expect: supplies
that extra request itself and passes on the broken build.
The exposure here is smaller than it looks, and worth writing down so it is not
re-counted: forty of the sixty-seven scripts have no track: step at all, and of
the twenty-five that do, twenty-three already assert straight after it. The two
that do not are rm36514 and rm37520, and neither can. Both turn on mane at the
ticket's own position, chr7:156,982,676-156,996,015, where mane has no features
on hg38 -- bigBedToBed on /gbdb/hg38/mane/mane.bb returns nothing there -- so
there is no row to name. The track controls read pack on a broken build too,
because the cart really did take the visibility. A comment in each says so, so
the gap is not read as an oversight and closed with a check that passes on
anything. tests/firstrequest.docent.yaml covers the class once, on its own.
Name a child of a container that is hidden by default. Two shapes of track stay
green on a build whose visibility handling is broken. A top-level track is added
as a lightweight stub so the track controls can list it, so it is built whatever
the cart lookup returned -- microsat, gtexGene and windowmaskerSdust all drew on
the broken build. A default-visible child has its container in the list already
-- wgEncodeRegMarkH3k27ac drew while its sibling wgEncodeRegMarkH3k4me1 did not,
same superTrack, same request, opposite verdicts. wgEncodeRegMarkH3k4me1 is the
known-good example. This is the cheapest rule in the file: it changes which
track a script names, not how the script is written, and without it a script
reads as coverage and is not.
The section on reading a redirected run points at make preflight TARGET=, which
now prints the target's central.db, db.trackDb, curatedHubPrefix and quickLift
settings, and says to swap only the binary when that is not enough.
No script's steps changed, so nothing here alters what the nightly measures.
make proof and both preflights are clean.
- src/hg/utils/docent/tests/regress/rm37615.docent.yaml
- lines changed 1, context: html, text, full: html, text
9d4c4b4781eb714d844a98faa90a1909af541a80 Wed Sep 16 10:26:38 2026 -0700
docent: the sandbox-ab proof for nine scripts, and the two rules behind it, refs #38252
Nine scripts here went red on the #37547 cart-visibility branch and green on
master, for their own reason, on the same machine with the same hg.conf. That
is the sandbox-ab shape exactly, and it was going to be lost with the run. Each
now carries the line:
sandbox-ab 2026-09-16 -- failed on a #37547 cart-visibility build before the
isParentVisible fix in hg/lib/trackHub.c, passed on the same sandbox with the
fix and with master; the same hg.conf all three times
rm36048, rm36059, rm36061, rm36331, rm37553, rm37562, rm37615, rm37815 and
rm38032. make proof goes from 4 of 67 watched to fail and then pass, to 13.
The cause was one line: isParentVisible() read a container's visibility from the
bare cart key instead of through the accessor, so after migration it read
nothing, fell back to the trackDb default, decided the container was hidden, and
walkTree() left the track out of the lift hub.
Two rules come out of the same session and are now a section in README.txt.
Assert before you navigate. A bug in this area can lag by exactly one request:
the visibility reaches the cart, the image drawn in reply does not carry the row,
and any next request draws it. A script shaped track: -> go: -> expect: supplies
that extra request itself and passes on the broken build.
The exposure here is smaller than it looks, and worth writing down so it is not
re-counted: forty of the sixty-seven scripts have no track: step at all, and of
the twenty-five that do, twenty-three already assert straight after it. The two
that do not are rm36514 and rm37520, and neither can. Both turn on mane at the
ticket's own position, chr7:156,982,676-156,996,015, where mane has no features
on hg38 -- bigBedToBed on /gbdb/hg38/mane/mane.bb returns nothing there -- so
there is no row to name. The track controls read pack on a broken build too,
because the cart really did take the visibility. A comment in each says so, so
the gap is not read as an oversight and closed with a check that passes on
anything. tests/firstrequest.docent.yaml covers the class once, on its own.
Name a child of a container that is hidden by default. Two shapes of track stay
green on a build whose visibility handling is broken. A top-level track is added
as a lightweight stub so the track controls can list it, so it is built whatever
the cart lookup returned -- microsat, gtexGene and windowmaskerSdust all drew on
the broken build. A default-visible child has its container in the list already
-- wgEncodeRegMarkH3k27ac drew while its sibling wgEncodeRegMarkH3k4me1 did not,
same superTrack, same request, opposite verdicts. wgEncodeRegMarkH3k4me1 is the
known-good example. This is the cheapest rule in the file: it changes which
track a script names, not how the script is written, and without it a script
reads as coverage and is not.
The section on reading a redirected run points at make preflight TARGET=, which
now prints the target's central.db, db.trackDb, curatedHubPrefix and quickLift
settings, and says to swap only the binary when that is not enough.
No script's steps changed, so nothing here alters what the nightly measures.
make proof and both preflights are clean.
- src/hg/utils/docent/tests/regress/rm37743.docent.yaml
- lines changed 1, context: html, text, full: html, text
cd13b3b171159247f1d105f650cce2a0726cd67b Fri Sep 18 16:08:59 2026 -0700
docent: release-ab evidence for six scripts, from the released docker images, refs #38252
Six scripts move from assertion-only to release-ab. The baselines are the released
v499 to v503 docker images running on hgwdev, which give what the v503 ticket park
could not: a range of releases rather than a single one.
Three were watched to flip, and each flips at exactly the release its fix first
ships in, which is what says the failure is the ticket's own and not version drift:
rm27113 fails v499 v500, passes v501 94f9b53d3db and b551f6c3ac8 first ship in v501
rm37743 fails v499, passes v500 7b74ff4b43a first ships in v500
rm38108 fails v499 to v502, passes v503 7181c0af889 first ships in v503
Three fail on every released image and pass on genome-test, which is correct rather
than a gap: their fixes are on master only and ship in v504.
rm38126 the descPage- prefix is absent on every release
rm38185 the position after an empty CGI pair is eaten on every release
rm38309 the exon tooltip the fix adds is absent on every release
Each failure was read rather than counted. rm27113 fails on a position with the page
otherwise whole at 10 rows; rm37743 fails on its own error string; rm38108 draws no
ruler at all, which is the crash it covers.
Two candidates were rejected after looking at them, and are worth naming so they are
not re-picked. rm34651 appears to flip at v500, but fa3431cd36b is already in v499 and
the clinvar track simply has no density options there, so the flip is not its own.
rm35333 appeared to flip and did not: it reads an hs1 hub, and hs1 was repaired in the
images midway through the sweep, so the flip was the repair rather than the code.
make proof: 39 of 89, up from 33.
- src/hg/utils/docent/tests/regress/rm37815.docent.yaml
- lines changed 1, context: html, text, full: html, text
9d4c4b4781eb714d844a98faa90a1909af541a80 Wed Sep 16 10:26:38 2026 -0700
docent: the sandbox-ab proof for nine scripts, and the two rules behind it, refs #38252
Nine scripts here went red on the #37547 cart-visibility branch and green on
master, for their own reason, on the same machine with the same hg.conf. That
is the sandbox-ab shape exactly, and it was going to be lost with the run. Each
now carries the line:
sandbox-ab 2026-09-16 -- failed on a #37547 cart-visibility build before the
isParentVisible fix in hg/lib/trackHub.c, passed on the same sandbox with the
fix and with master; the same hg.conf all three times
rm36048, rm36059, rm36061, rm36331, rm37553, rm37562, rm37615, rm37815 and
rm38032. make proof goes from 4 of 67 watched to fail and then pass, to 13.
The cause was one line: isParentVisible() read a container's visibility from the
bare cart key instead of through the accessor, so after migration it read
nothing, fell back to the trackDb default, decided the container was hidden, and
walkTree() left the track out of the lift hub.
Two rules come out of the same session and are now a section in README.txt.
Assert before you navigate. A bug in this area can lag by exactly one request:
the visibility reaches the cart, the image drawn in reply does not carry the row,
and any next request draws it. A script shaped track: -> go: -> expect: supplies
that extra request itself and passes on the broken build.
The exposure here is smaller than it looks, and worth writing down so it is not
re-counted: forty of the sixty-seven scripts have no track: step at all, and of
the twenty-five that do, twenty-three already assert straight after it. The two
that do not are rm36514 and rm37520, and neither can. Both turn on mane at the
ticket's own position, chr7:156,982,676-156,996,015, where mane has no features
on hg38 -- bigBedToBed on /gbdb/hg38/mane/mane.bb returns nothing there -- so
there is no row to name. The track controls read pack on a broken build too,
because the cart really did take the visibility. A comment in each says so, so
the gap is not read as an oversight and closed with a check that passes on
anything. tests/firstrequest.docent.yaml covers the class once, on its own.
Name a child of a container that is hidden by default. Two shapes of track stay
green on a build whose visibility handling is broken. A top-level track is added
as a lightweight stub so the track controls can list it, so it is built whatever
the cart lookup returned -- microsat, gtexGene and windowmaskerSdust all drew on
the broken build. A default-visible child has its container in the list already
-- wgEncodeRegMarkH3k27ac drew while its sibling wgEncodeRegMarkH3k4me1 did not,
same superTrack, same request, opposite verdicts. wgEncodeRegMarkH3k4me1 is the
known-good example. This is the cheapest rule in the file: it changes which
track a script names, not how the script is written, and without it a script
reads as coverage and is not.
The section on reading a redirected run points at make preflight TARGET=, which
now prints the target's central.db, db.trackDb, curatedHubPrefix and quickLift
settings, and says to swap only the binary when that is not enough.
No script's steps changed, so nothing here alters what the nightly measures.
make proof and both preflights are clean.
- src/hg/utils/docent/tests/regress/rm37969.docent.yaml
- lines changed 69, context: html, text, full: html, text
bbe654a9dc89bc7b75d40d1fe197d5376d756580 Thu Sep 17 17:08:10 2026 -0700
docent: 22 regression tests for a QA list, and release-ab evidence from v503, refs #38252
One script per ticket for twenty-two that had none: rm10138, rm36940, rm37969,
rm38171, rm38184, rm38198, rm38200, rm38205, rm38206, rm38223, rm38236, rm38248,
rm38251, rm38257, rm38279, rm38281, rm38283, rm38284, rm38285, rm38302, rm38303
and rm38309. No theme -- they run from a menu-bar color to a SIGSEGV in a
quickLift view. Three fixtures came with them, under
~/public_html/docentFixtures: rm36940 (seven bigBed tracks differing only in the
field count on the type line), rm38283 (one description page full of dollar
variables) and rm38184 (a one-line session settings file).
Every one was then run against v503, which is what the new proof level is for.
v503_branch 707b184e329 went into a ticket sandbox -- CGIs, js and htdocs, since
three of the fixes live in hg/js or htdocs/style -- and twenty-one of the
twenty-four fix commits landed after that branch was cut, so the release has the
bugs. Eighteen scripts failed there on their own check and carry a release-ab
line quoting the failure.
release-ab sits between sandbox-ab and server-flip. It is stronger than
sandbox-ab because anyone can rebuild it from a tag, where a hand-patched tree
lives in one person's home directory and does not survive a rebase.
The four that v503 does not cover are each said in their own header: rm38171's
fix is IN v503 so an older release is its baseline; rm36940's fixture hub draws
nothing there, so the run never reaches the check; rm38257's login: dies against
a park on any baseline; and rm38309 PASSES, which is exactly what its header
claims, since that fix changes no byte of any page.
rm38251 had to be rewritten because of what the sweep said. It PASSED on a build
carrying its own bug, at every width from 390 to 1099px: the icon had slid 312px
left but was still inside the bar, and the clear: check named the links, where
the icon fell in a gap between two of them. Naming the menu list instead has no
gaps. Without the sweep it would have sat here looking green.
make proof: 89 scripts, 33 watched to fail for the reason they exist and then
pass, up from 13.
- src/hg/utils/docent/tests/regress/rm37996.docent.yaml
- lines changed 41, context: html, text, full: html, text
b7fe2f0542ac4a5e182b86ab6f794de34d0ff0d8 Sat Sep 19 10:17:09 2026 -0700
docent: six regression scripts written from the tours, refs #38252
rm38335 rm38298 rm37996 rm38249 rm38268 rm38364, one per ticket that got a
before-and-after tour this week. 95 scripts now, make proof 45 of 95, and the
whole directory is green against genome-test.
Five of the six carry release-ab and the sixth sandbox-ab on their first day,
which is unusual here and is only because the before had already been rendered
and measured for the ticket comment: hgwbeta returns "Mangled CGI input string
bogus" (rm38335), one codon number instead of two (rm38298), the ASCII table
with no banner (rm37996), "not supported by QuickLift" for all four alignment
families (rm38249) and "Can't find strchive in track database hg19" (rm38268).
rm38364's before is ts park 38373, master frozen two days before that feature
merged, since it is newer than any release.
Three things they cost, each also in README.txt:
* where the text lives decides how it is read. rm38309 reads its exon text
out of a map box's data-tooltip, but rm38298's codon tooltip is not in the
served map at all -- the page's own JavaScript builds it on mouseenter --
so that one hovers and asserts tip:. rm38268's item label is in the drawn
PNG and nowhere else, so it asserts the map box's href and tooltip rather
than a text: that can never match.
* a superTrack still does not pass its setting to its members. rm38268 opens
strVar to reach strchive and then cannot use exact: on hg38, because the
sibling repeat tracks come up at their own visibilities.
* an hg.conf gate belongs in the header, loudly. rm38364 fails every check
when denseClick is off, and that is a configuration answer rather than a
regression, so the header carries the grep that settles it.
rm37996 has a date on it. The new hgBlat results page is opt-in while it is
tested and the banner names 2026-10-21 as the day it becomes the default; on
that day the first two steps come out and the goto: gains blatNewPage=1.
- src/hg/utils/docent/tests/regress/rm38032.docent.yaml
- lines changed 1, context: html, text, full: html, text
9d4c4b4781eb714d844a98faa90a1909af541a80 Wed Sep 16 10:26:38 2026 -0700
docent: the sandbox-ab proof for nine scripts, and the two rules behind it, refs #38252
Nine scripts here went red on the #37547 cart-visibility branch and green on
master, for their own reason, on the same machine with the same hg.conf. That
is the sandbox-ab shape exactly, and it was going to be lost with the run. Each
now carries the line:
sandbox-ab 2026-09-16 -- failed on a #37547 cart-visibility build before the
isParentVisible fix in hg/lib/trackHub.c, passed on the same sandbox with the
fix and with master; the same hg.conf all three times
rm36048, rm36059, rm36061, rm36331, rm37553, rm37562, rm37615, rm37815 and
rm38032. make proof goes from 4 of 67 watched to fail and then pass, to 13.
The cause was one line: isParentVisible() read a container's visibility from the
bare cart key instead of through the accessor, so after migration it read
nothing, fell back to the trackDb default, decided the container was hidden, and
walkTree() left the track out of the lift hub.
Two rules come out of the same session and are now a section in README.txt.
Assert before you navigate. A bug in this area can lag by exactly one request:
the visibility reaches the cart, the image drawn in reply does not carry the row,
and any next request draws it. A script shaped track: -> go: -> expect: supplies
that extra request itself and passes on the broken build.
The exposure here is smaller than it looks, and worth writing down so it is not
re-counted: forty of the sixty-seven scripts have no track: step at all, and of
the twenty-five that do, twenty-three already assert straight after it. The two
that do not are rm36514 and rm37520, and neither can. Both turn on mane at the
ticket's own position, chr7:156,982,676-156,996,015, where mane has no features
on hg38 -- bigBedToBed on /gbdb/hg38/mane/mane.bb returns nothing there -- so
there is no row to name. The track controls read pack on a broken build too,
because the cart really did take the visibility. A comment in each says so, so
the gap is not read as an oversight and closed with a check that passes on
anything. tests/firstrequest.docent.yaml covers the class once, on its own.
Name a child of a container that is hidden by default. Two shapes of track stay
green on a build whose visibility handling is broken. A top-level track is added
as a lightweight stub so the track controls can list it, so it is built whatever
the cart lookup returned -- microsat, gtexGene and windowmaskerSdust all drew on
the broken build. A default-visible child has its container in the list already
-- wgEncodeRegMarkH3k27ac drew while its sibling wgEncodeRegMarkH3k4me1 did not,
same superTrack, same request, opposite verdicts. wgEncodeRegMarkH3k4me1 is the
known-good example. This is the cheapest rule in the file: it changes which
track a script names, not how the script is written, and without it a script
reads as coverage and is not.
The section on reading a redirected run points at make preflight TARGET=, which
now prints the target's central.db, db.trackDb, curatedHubPrefix and quickLift
settings, and says to swap only the binary when that is not enough.
No script's steps changed, so nothing here alters what the nightly measures.
make proof and both preflights are clean.
- src/hg/utils/docent/tests/regress/rm38086.docent.yaml
- lines changed 96, context: html, text, full: html, text
c52d505f538f7636e48aa5c06b9ad208697471a9 Sun Sep 20 14:34:31 2026 -0700
docent: three regression scripts for tickets nothing was watching, refs #38252
#38391's test registry named four tickets with neither a unit test nor a script
here. These are three of them. They have little else in common, and each needed
a different answer to the same question: what about this bug is steady enough to
assert. 98 scripts now, `make proof` 46 of 98.
rm38253, the coverage-graph rewrite. Its fixture is six features on hg38 chr1,
three nested inside each other in each of two groups, so their coverage is a
staircase with FLAT steps: 1 2 3 2 1 over 20 kb, and the same again over 20 bp.
Flat is the point. Each pixel's value is the mean coverage of the bases it
covers, and the mean of a constant is that constant, so a reading taken in the
middle of a step does not depend on where a pixel boundary falls, on insideWidth,
or on the window being a round number of bases. The two windows take the two
sampling paths on purpose, and the 200 bp one is countsToPixelsUp, which
pixelSweep.sh never reaches because every cell in it is wider than insideWidth.
The script CANNOT flip on its own fix and its header says so: #38253 is a rewrite
required to draw the same picture it replaced, verified with 96 pixel comparisons,
so both builds answer the same and no baseline can tell them apart. What was
proved instead is that the checks discriminate, by pointing each of the twelve
readings at a neighbouring step's value: all twelve went red.
rm38317, the knownGene page that prints an OMIM link built from uninitialised
memory. The link itself is the wrong thing to test for, since it is whatever was
on the stack and comes and goes between loads of the same URL; an earlier probe
of this ticket asked only for its absence and concluded the bug did not reproduce.
The same struct is read a second time further down, and that read is deterministic:
the page stops dead right after "Links to sequence:", with no Translated Protein
link and no Genomic Sequence link, on every load of all three assemblies. Lou
Nassar's note of 2026-09-18 is what identified that; the description does not
mention it. Measured on hgwbeta against genome-test, 2026-09-20: 17,487 to 27,026
bytes on hg19, 17,656 to 27,456 on hg38, 17,484 to 25,616 on mm39. So this one
carries a release-ab line. A RefSeq page is the control, where the OMIM link is
real and must still be there.
rm38086, the BLAT Results track group. It runs a real search, lets the results
page build its own custom track through its ajax to hgc, and then asks for the
group, the Delete all button, the per-track delete icon, the row being DRAWN
(5915dcd2939: a result track used to come up hidden) and both new names. Two
names in full, each a different half of 4fd18ab7854: "102bp SMYD4" for a
nucleotide query and "60aa TP53" for a protein one, where the aa is the point.
The old name "blat YourSeq" is asserted absent. hgwbeta is NOT a baseline for
it: v503_branch already carries these commits, so beta answering with the old
name is almost certainly hg.conf blatResultsGroup being off, and preflight
cannot read beta's hg.conf from here to settle it. Assertion-only, and the
header says why rather than leaving the next reader to try beta again.
The fixture hub is ~/public_html/docentFixtures/rm38253, beside the others.
README.txt gains a section on all of this, including one trap worth repeating:
never assert a title attribute, not even on a button. rm38086's first draft
matched `button#blat_delAll[title=...]`, which is in the served HTML and matches
nothing once hgTracks has copied every title into a mouseoverText attribute.
- src/hg/utils/docent/tests/regress/rm38108.docent.yaml
- lines changed 1, context: html, text, full: html, text
cd13b3b171159247f1d105f650cce2a0726cd67b Fri Sep 18 16:08:59 2026 -0700
docent: release-ab evidence for six scripts, from the released docker images, refs #38252
Six scripts move from assertion-only to release-ab. The baselines are the released
v499 to v503 docker images running on hgwdev, which give what the v503 ticket park
could not: a range of releases rather than a single one.
Three were watched to flip, and each flips at exactly the release its fix first
ships in, which is what says the failure is the ticket's own and not version drift:
rm27113 fails v499 v500, passes v501 94f9b53d3db and b551f6c3ac8 first ship in v501
rm37743 fails v499, passes v500 7b74ff4b43a first ships in v500
rm38108 fails v499 to v502, passes v503 7181c0af889 first ships in v503
Three fail on every released image and pass on genome-test, which is correct rather
than a gap: their fixes are on master only and ship in v504.
rm38126 the descPage- prefix is absent on every release
rm38185 the position after an empty CGI pair is eaten on every release
rm38309 the exon tooltip the fix adds is absent on every release
Each failure was read rather than counted. rm27113 fails on a position with the page
otherwise whole at 10 rows; rm37743 fails on its own error string; rm38108 draws no
ruler at all, which is the crash it covers.
Two candidates were rejected after looking at them, and are worth naming so they are
not re-picked. rm34651 appears to flip at v500, but fa3431cd36b is already in v499 and
the clinvar track simply has no density options there, so the flip is not its own.
rm35333 appeared to flip and did not: it reads an hs1 hub, and hs1 was repaired in the
images midway through the sweep, so the flip was the repair rather than the code.
make proof: 39 of 89, up from 33.
- src/hg/utils/docent/tests/regress/rm38126.docent.yaml
- lines changed 1, context: html, text, full: html, text
cd13b3b171159247f1d105f650cce2a0726cd67b Fri Sep 18 16:08:59 2026 -0700
docent: release-ab evidence for six scripts, from the released docker images, refs #38252
Six scripts move from assertion-only to release-ab. The baselines are the released
v499 to v503 docker images running on hgwdev, which give what the v503 ticket park
could not: a range of releases rather than a single one.
Three were watched to flip, and each flips at exactly the release its fix first
ships in, which is what says the failure is the ticket's own and not version drift:
rm27113 fails v499 v500, passes v501 94f9b53d3db and b551f6c3ac8 first ship in v501
rm37743 fails v499, passes v500 7b74ff4b43a first ships in v500
rm38108 fails v499 to v502, passes v503 7181c0af889 first ships in v503
Three fail on every released image and pass on genome-test, which is correct rather
than a gap: their fixes are on master only and ship in v504.
rm38126 the descPage- prefix is absent on every release
rm38185 the position after an empty CGI pair is eaten on every release
rm38309 the exon tooltip the fix adds is absent on every release
Each failure was read rather than counted. rm27113 fails on a position with the page
otherwise whole at 10 rows; rm37743 fails on its own error string; rm38108 draws no
ruler at all, which is the crash it covers.
Two candidates were rejected after looking at them, and are worth naming so they are
not re-picked. rm34651 appears to flip at v500, but fa3431cd36b is already in v499 and
the clinvar track simply has no density options there, so the flip is not its own.
rm35333 appeared to flip and did not: it reads an hs1 hub, and hs1 was repaired in the
images midway through the sweep, so the flip was the repair rather than the code.
make proof: 39 of 89, up from 33.
- src/hg/utils/docent/tests/regress/rm38171.docent.yaml
- lines changed 73, context: html, text, full: html, text
bbe654a9dc89bc7b75d40d1fe197d5376d756580 Thu Sep 17 17:08:10 2026 -0700
docent: 22 regression tests for a QA list, and release-ab evidence from v503, refs #38252
One script per ticket for twenty-two that had none: rm10138, rm36940, rm37969,
rm38171, rm38184, rm38198, rm38200, rm38205, rm38206, rm38223, rm38236, rm38248,
rm38251, rm38257, rm38279, rm38281, rm38283, rm38284, rm38285, rm38302, rm38303
and rm38309. No theme -- they run from a menu-bar color to a SIGSEGV in a
quickLift view. Three fixtures came with them, under
~/public_html/docentFixtures: rm36940 (seven bigBed tracks differing only in the
field count on the type line), rm38283 (one description page full of dollar
variables) and rm38184 (a one-line session settings file).
Every one was then run against v503, which is what the new proof level is for.
v503_branch 707b184e329 went into a ticket sandbox -- CGIs, js and htdocs, since
three of the fixes live in hg/js or htdocs/style -- and twenty-one of the
twenty-four fix commits landed after that branch was cut, so the release has the
bugs. Eighteen scripts failed there on their own check and carry a release-ab
line quoting the failure.
release-ab sits between sandbox-ab and server-flip. It is stronger than
sandbox-ab because anyone can rebuild it from a tag, where a hand-patched tree
lives in one person's home directory and does not survive a rebase.
The four that v503 does not cover are each said in their own header: rm38171's
fix is IN v503 so an older release is its baseline; rm36940's fixture hub draws
nothing there, so the run never reaches the check; rm38257's login: dies against
a park on any baseline; and rm38309 PASSES, which is exactly what its header
claims, since that fix changes no byte of any page.
rm38251 had to be rewritten because of what the sweep said. It PASSED on a build
carrying its own bug, at every width from 390 to 1099px: the icon had slid 312px
left but was still inside the bar, and the clear: check named the links, where
the icon fell in a gap between two of them. Naming the menu list instead has no
gaps. Without the sweep it would have sat here looking green.
make proof: 89 scripts, 33 watched to fail for the reason they exist and then
pass, up from 13.
- src/hg/utils/docent/tests/regress/rm38184.docent.yaml
- lines changed 60, context: html, text, full: html, text
bbe654a9dc89bc7b75d40d1fe197d5376d756580 Thu Sep 17 17:08:10 2026 -0700
docent: 22 regression tests for a QA list, and release-ab evidence from v503, refs #38252
One script per ticket for twenty-two that had none: rm10138, rm36940, rm37969,
rm38171, rm38184, rm38198, rm38200, rm38205, rm38206, rm38223, rm38236, rm38248,
rm38251, rm38257, rm38279, rm38281, rm38283, rm38284, rm38285, rm38302, rm38303
and rm38309. No theme -- they run from a menu-bar color to a SIGSEGV in a
quickLift view. Three fixtures came with them, under
~/public_html/docentFixtures: rm36940 (seven bigBed tracks differing only in the
field count on the type line), rm38283 (one description page full of dollar
variables) and rm38184 (a one-line session settings file).
Every one was then run against v503, which is what the new proof level is for.
v503_branch 707b184e329 went into a ticket sandbox -- CGIs, js and htdocs, since
three of the fixes live in hg/js or htdocs/style -- and twenty-one of the
twenty-four fix commits landed after that branch was cut, so the release has the
bugs. Eighteen scripts failed there on their own check and carry a release-ab
line quoting the failure.
release-ab sits between sandbox-ab and server-flip. It is stronger than
sandbox-ab because anyone can rebuild it from a tag, where a hand-patched tree
lives in one person's home directory and does not survive a rebase.
The four that v503 does not cover are each said in their own header: rm38171's
fix is IN v503 so an older release is its baseline; rm36940's fixture hub draws
nothing there, so the run never reaches the check; rm38257's login: dies against
a park on any baseline; and rm38309 PASSES, which is exactly what its header
claims, since that fix changes no byte of any page.
rm38251 had to be rewritten because of what the sweep said. It PASSED on a build
carrying its own bug, at every width from 390 to 1099px: the icon had slid 312px
left but was still inside the bar, and the clear: check named the links, where
the icon fell in a gap between two of them. Naming the menu list instead has no
gaps. Without the sweep it would have sat here looking green.
make proof: 89 scripts, 33 watched to fail for the reason they exist and then
pass, up from 13.
- src/hg/utils/docent/tests/regress/rm38185.docent.yaml
- lines changed 1, context: html, text, full: html, text
cd13b3b171159247f1d105f650cce2a0726cd67b Fri Sep 18 16:08:59 2026 -0700
docent: release-ab evidence for six scripts, from the released docker images, refs #38252
Six scripts move from assertion-only to release-ab. The baselines are the released
v499 to v503 docker images running on hgwdev, which give what the v503 ticket park
could not: a range of releases rather than a single one.
Three were watched to flip, and each flips at exactly the release its fix first
ships in, which is what says the failure is the ticket's own and not version drift:
rm27113 fails v499 v500, passes v501 94f9b53d3db and b551f6c3ac8 first ship in v501
rm37743 fails v499, passes v500 7b74ff4b43a first ships in v500
rm38108 fails v499 to v502, passes v503 7181c0af889 first ships in v503
Three fail on every released image and pass on genome-test, which is correct rather
than a gap: their fixes are on master only and ship in v504.
rm38126 the descPage- prefix is absent on every release
rm38185 the position after an empty CGI pair is eaten on every release
rm38309 the exon tooltip the fix adds is absent on every release
Each failure was read rather than counted. rm27113 fails on a position with the page
otherwise whole at 10 rows; rm37743 fails on its own error string; rm38108 draws no
ruler at all, which is the crash it covers.
Two candidates were rejected after looking at them, and are worth naming so they are
not re-picked. rm34651 appears to flip at v500, but fa3431cd36b is already in v499 and
the clinvar track simply has no density options there, so the flip is not its own.
rm35333 appeared to flip and did not: it reads an hs1 hub, and hs1 was repaired in the
images midway through the sweep, so the flip was the repair rather than the code.
make proof: 39 of 89, up from 33.
- src/hg/utils/docent/tests/regress/rm38198.docent.yaml
- lines changed 70, context: html, text, full: html, text
bbe654a9dc89bc7b75d40d1fe197d5376d756580 Thu Sep 17 17:08:10 2026 -0700
docent: 22 regression tests for a QA list, and release-ab evidence from v503, refs #38252
One script per ticket for twenty-two that had none: rm10138, rm36940, rm37969,
rm38171, rm38184, rm38198, rm38200, rm38205, rm38206, rm38223, rm38236, rm38248,
rm38251, rm38257, rm38279, rm38281, rm38283, rm38284, rm38285, rm38302, rm38303
and rm38309. No theme -- they run from a menu-bar color to a SIGSEGV in a
quickLift view. Three fixtures came with them, under
~/public_html/docentFixtures: rm36940 (seven bigBed tracks differing only in the
field count on the type line), rm38283 (one description page full of dollar
variables) and rm38184 (a one-line session settings file).
Every one was then run against v503, which is what the new proof level is for.
v503_branch 707b184e329 went into a ticket sandbox -- CGIs, js and htdocs, since
three of the fixes live in hg/js or htdocs/style -- and twenty-one of the
twenty-four fix commits landed after that branch was cut, so the release has the
bugs. Eighteen scripts failed there on their own check and carry a release-ab
line quoting the failure.
release-ab sits between sandbox-ab and server-flip. It is stronger than
sandbox-ab because anyone can rebuild it from a tag, where a hand-patched tree
lives in one person's home directory and does not survive a rebase.
The four that v503 does not cover are each said in their own header: rm38171's
fix is IN v503 so an older release is its baseline; rm36940's fixture hub draws
nothing there, so the run never reaches the check; rm38257's login: dies against
a park on any baseline; and rm38309 PASSES, which is exactly what its header
claims, since that fix changes no byte of any page.
rm38251 had to be rewritten because of what the sweep said. It PASSED on a build
carrying its own bug, at every width from 390 to 1099px: the icon had slid 312px
left but was still inside the bar, and the clear: check named the links, where
the icon fell in a gap between two of them. Naming the menu list instead has no
gaps. Without the sweep it would have sat here looking green.
make proof: 89 scripts, 33 watched to fail for the reason they exist and then
pass, up from 13.
- src/hg/utils/docent/tests/regress/rm38200.docent.yaml
- lines changed 72, context: html, text, full: html, text
bbe654a9dc89bc7b75d40d1fe197d5376d756580 Thu Sep 17 17:08:10 2026 -0700
docent: 22 regression tests for a QA list, and release-ab evidence from v503, refs #38252
One script per ticket for twenty-two that had none: rm10138, rm36940, rm37969,
rm38171, rm38184, rm38198, rm38200, rm38205, rm38206, rm38223, rm38236, rm38248,
rm38251, rm38257, rm38279, rm38281, rm38283, rm38284, rm38285, rm38302, rm38303
and rm38309. No theme -- they run from a menu-bar color to a SIGSEGV in a
quickLift view. Three fixtures came with them, under
~/public_html/docentFixtures: rm36940 (seven bigBed tracks differing only in the
field count on the type line), rm38283 (one description page full of dollar
variables) and rm38184 (a one-line session settings file).
Every one was then run against v503, which is what the new proof level is for.
v503_branch 707b184e329 went into a ticket sandbox -- CGIs, js and htdocs, since
three of the fixes live in hg/js or htdocs/style -- and twenty-one of the
twenty-four fix commits landed after that branch was cut, so the release has the
bugs. Eighteen scripts failed there on their own check and carry a release-ab
line quoting the failure.
release-ab sits between sandbox-ab and server-flip. It is stronger than
sandbox-ab because anyone can rebuild it from a tag, where a hand-patched tree
lives in one person's home directory and does not survive a rebase.
The four that v503 does not cover are each said in their own header: rm38171's
fix is IN v503 so an older release is its baseline; rm36940's fixture hub draws
nothing there, so the run never reaches the check; rm38257's login: dies against
a park on any baseline; and rm38309 PASSES, which is exactly what its header
claims, since that fix changes no byte of any page.
rm38251 had to be rewritten because of what the sweep said. It PASSED on a build
carrying its own bug, at every width from 390 to 1099px: the icon had slid 312px
left but was still inside the bar, and the clear: check named the links, where
the icon fell in a gap between two of them. Naming the menu list instead has no
gaps. Without the sweep it would have sat here looking green.
make proof: 89 scripts, 33 watched to fail for the reason they exist and then
pass, up from 13.
- src/hg/utils/docent/tests/regress/rm38205.docent.yaml
- lines changed 71, context: html, text, full: html, text
bbe654a9dc89bc7b75d40d1fe197d5376d756580 Thu Sep 17 17:08:10 2026 -0700
docent: 22 regression tests for a QA list, and release-ab evidence from v503, refs #38252
One script per ticket for twenty-two that had none: rm10138, rm36940, rm37969,
rm38171, rm38184, rm38198, rm38200, rm38205, rm38206, rm38223, rm38236, rm38248,
rm38251, rm38257, rm38279, rm38281, rm38283, rm38284, rm38285, rm38302, rm38303
and rm38309. No theme -- they run from a menu-bar color to a SIGSEGV in a
quickLift view. Three fixtures came with them, under
~/public_html/docentFixtures: rm36940 (seven bigBed tracks differing only in the
field count on the type line), rm38283 (one description page full of dollar
variables) and rm38184 (a one-line session settings file).
Every one was then run against v503, which is what the new proof level is for.
v503_branch 707b184e329 went into a ticket sandbox -- CGIs, js and htdocs, since
three of the fixes live in hg/js or htdocs/style -- and twenty-one of the
twenty-four fix commits landed after that branch was cut, so the release has the
bugs. Eighteen scripts failed there on their own check and carry a release-ab
line quoting the failure.
release-ab sits between sandbox-ab and server-flip. It is stronger than
sandbox-ab because anyone can rebuild it from a tag, where a hand-patched tree
lives in one person's home directory and does not survive a rebase.
The four that v503 does not cover are each said in their own header: rm38171's
fix is IN v503 so an older release is its baseline; rm36940's fixture hub draws
nothing there, so the run never reaches the check; rm38257's login: dies against
a park on any baseline; and rm38309 PASSES, which is exactly what its header
claims, since that fix changes no byte of any page.
rm38251 had to be rewritten because of what the sweep said. It PASSED on a build
carrying its own bug, at every width from 390 to 1099px: the icon had slid 312px
left but was still inside the bar, and the clear: check named the links, where
the icon fell in a gap between two of them. Naming the menu list instead has no
gaps. Without the sweep it would have sat here looking green.
make proof: 89 scripts, 33 watched to fail for the reason they exist and then
pass, up from 13.
- src/hg/utils/docent/tests/regress/rm38206.docent.yaml
- lines changed 77, context: html, text, full: html, text
bbe654a9dc89bc7b75d40d1fe197d5376d756580 Thu Sep 17 17:08:10 2026 -0700
docent: 22 regression tests for a QA list, and release-ab evidence from v503, refs #38252
One script per ticket for twenty-two that had none: rm10138, rm36940, rm37969,
rm38171, rm38184, rm38198, rm38200, rm38205, rm38206, rm38223, rm38236, rm38248,
rm38251, rm38257, rm38279, rm38281, rm38283, rm38284, rm38285, rm38302, rm38303
and rm38309. No theme -- they run from a menu-bar color to a SIGSEGV in a
quickLift view. Three fixtures came with them, under
~/public_html/docentFixtures: rm36940 (seven bigBed tracks differing only in the
field count on the type line), rm38283 (one description page full of dollar
variables) and rm38184 (a one-line session settings file).
Every one was then run against v503, which is what the new proof level is for.
v503_branch 707b184e329 went into a ticket sandbox -- CGIs, js and htdocs, since
three of the fixes live in hg/js or htdocs/style -- and twenty-one of the
twenty-four fix commits landed after that branch was cut, so the release has the
bugs. Eighteen scripts failed there on their own check and carry a release-ab
line quoting the failure.
release-ab sits between sandbox-ab and server-flip. It is stronger than
sandbox-ab because anyone can rebuild it from a tag, where a hand-patched tree
lives in one person's home directory and does not survive a rebase.
The four that v503 does not cover are each said in their own header: rm38171's
fix is IN v503 so an older release is its baseline; rm36940's fixture hub draws
nothing there, so the run never reaches the check; rm38257's login: dies against
a park on any baseline; and rm38309 PASSES, which is exactly what its header
claims, since that fix changes no byte of any page.
rm38251 had to be rewritten because of what the sweep said. It PASSED on a build
carrying its own bug, at every width from 390 to 1099px: the icon had slid 312px
left but was still inside the bar, and the clear: check named the links, where
the icon fell in a gap between two of them. Naming the menu list instead has no
gaps. Without the sweep it would have sat here looking green.
make proof: 89 scripts, 33 watched to fail for the reason they exist and then
pass, up from 13.
- src/hg/utils/docent/tests/regress/rm38223.docent.yaml
- lines changed 51, context: html, text, full: html, text
bbe654a9dc89bc7b75d40d1fe197d5376d756580 Thu Sep 17 17:08:10 2026 -0700
docent: 22 regression tests for a QA list, and release-ab evidence from v503, refs #38252
One script per ticket for twenty-two that had none: rm10138, rm36940, rm37969,
rm38171, rm38184, rm38198, rm38200, rm38205, rm38206, rm38223, rm38236, rm38248,
rm38251, rm38257, rm38279, rm38281, rm38283, rm38284, rm38285, rm38302, rm38303
and rm38309. No theme -- they run from a menu-bar color to a SIGSEGV in a
quickLift view. Three fixtures came with them, under
~/public_html/docentFixtures: rm36940 (seven bigBed tracks differing only in the
field count on the type line), rm38283 (one description page full of dollar
variables) and rm38184 (a one-line session settings file).
Every one was then run against v503, which is what the new proof level is for.
v503_branch 707b184e329 went into a ticket sandbox -- CGIs, js and htdocs, since
three of the fixes live in hg/js or htdocs/style -- and twenty-one of the
twenty-four fix commits landed after that branch was cut, so the release has the
bugs. Eighteen scripts failed there on their own check and carry a release-ab
line quoting the failure.
release-ab sits between sandbox-ab and server-flip. It is stronger than
sandbox-ab because anyone can rebuild it from a tag, where a hand-patched tree
lives in one person's home directory and does not survive a rebase.
The four that v503 does not cover are each said in their own header: rm38171's
fix is IN v503 so an older release is its baseline; rm36940's fixture hub draws
nothing there, so the run never reaches the check; rm38257's login: dies against
a park on any baseline; and rm38309 PASSES, which is exactly what its header
claims, since that fix changes no byte of any page.
rm38251 had to be rewritten because of what the sweep said. It PASSED on a build
carrying its own bug, at every width from 390 to 1099px: the icon had slid 312px
left but was still inside the bar, and the clear: check named the links, where
the icon fell in a gap between two of them. Naming the menu list instead has no
gaps. Without the sweep it would have sat here looking green.
make proof: 89 scripts, 33 watched to fail for the reason they exist and then
pass, up from 13.
- src/hg/utils/docent/tests/regress/rm38236.docent.yaml
- lines changed 74, context: html, text, full: html, text
bbe654a9dc89bc7b75d40d1fe197d5376d756580 Thu Sep 17 17:08:10 2026 -0700
docent: 22 regression tests for a QA list, and release-ab evidence from v503, refs #38252
One script per ticket for twenty-two that had none: rm10138, rm36940, rm37969,
rm38171, rm38184, rm38198, rm38200, rm38205, rm38206, rm38223, rm38236, rm38248,
rm38251, rm38257, rm38279, rm38281, rm38283, rm38284, rm38285, rm38302, rm38303
and rm38309. No theme -- they run from a menu-bar color to a SIGSEGV in a
quickLift view. Three fixtures came with them, under
~/public_html/docentFixtures: rm36940 (seven bigBed tracks differing only in the
field count on the type line), rm38283 (one description page full of dollar
variables) and rm38184 (a one-line session settings file).
Every one was then run against v503, which is what the new proof level is for.
v503_branch 707b184e329 went into a ticket sandbox -- CGIs, js and htdocs, since
three of the fixes live in hg/js or htdocs/style -- and twenty-one of the
twenty-four fix commits landed after that branch was cut, so the release has the
bugs. Eighteen scripts failed there on their own check and carry a release-ab
line quoting the failure.
release-ab sits between sandbox-ab and server-flip. It is stronger than
sandbox-ab because anyone can rebuild it from a tag, where a hand-patched tree
lives in one person's home directory and does not survive a rebase.
The four that v503 does not cover are each said in their own header: rm38171's
fix is IN v503 so an older release is its baseline; rm36940's fixture hub draws
nothing there, so the run never reaches the check; rm38257's login: dies against
a park on any baseline; and rm38309 PASSES, which is exactly what its header
claims, since that fix changes no byte of any page.
rm38251 had to be rewritten because of what the sweep said. It PASSED on a build
carrying its own bug, at every width from 390 to 1099px: the icon had slid 312px
left but was still inside the bar, and the clear: check named the links, where
the icon fell in a gap between two of them. Naming the menu list instead has no
gaps. Without the sweep it would have sat here looking green.
make proof: 89 scripts, 33 watched to fail for the reason they exist and then
pass, up from 13.
- src/hg/utils/docent/tests/regress/rm38248.docent.yaml
- lines changed 80, context: html, text, full: html, text
bbe654a9dc89bc7b75d40d1fe197d5376d756580 Thu Sep 17 17:08:10 2026 -0700
docent: 22 regression tests for a QA list, and release-ab evidence from v503, refs #38252
One script per ticket for twenty-two that had none: rm10138, rm36940, rm37969,
rm38171, rm38184, rm38198, rm38200, rm38205, rm38206, rm38223, rm38236, rm38248,
rm38251, rm38257, rm38279, rm38281, rm38283, rm38284, rm38285, rm38302, rm38303
and rm38309. No theme -- they run from a menu-bar color to a SIGSEGV in a
quickLift view. Three fixtures came with them, under
~/public_html/docentFixtures: rm36940 (seven bigBed tracks differing only in the
field count on the type line), rm38283 (one description page full of dollar
variables) and rm38184 (a one-line session settings file).
Every one was then run against v503, which is what the new proof level is for.
v503_branch 707b184e329 went into a ticket sandbox -- CGIs, js and htdocs, since
three of the fixes live in hg/js or htdocs/style -- and twenty-one of the
twenty-four fix commits landed after that branch was cut, so the release has the
bugs. Eighteen scripts failed there on their own check and carry a release-ab
line quoting the failure.
release-ab sits between sandbox-ab and server-flip. It is stronger than
sandbox-ab because anyone can rebuild it from a tag, where a hand-patched tree
lives in one person's home directory and does not survive a rebase.
The four that v503 does not cover are each said in their own header: rm38171's
fix is IN v503 so an older release is its baseline; rm36940's fixture hub draws
nothing there, so the run never reaches the check; rm38257's login: dies against
a park on any baseline; and rm38309 PASSES, which is exactly what its header
claims, since that fix changes no byte of any page.
rm38251 had to be rewritten because of what the sweep said. It PASSED on a build
carrying its own bug, at every width from 390 to 1099px: the icon had slid 312px
left but was still inside the bar, and the clear: check named the links, where
the icon fell in a gap between two of them. Naming the menu list instead has no
gaps. Without the sweep it would have sat here looking green.
make proof: 89 scripts, 33 watched to fail for the reason they exist and then
pass, up from 13.
- src/hg/utils/docent/tests/regress/rm38249.docent.yaml
- lines changed 42, context: html, text, full: html, text
b7fe2f0542ac4a5e182b86ab6f794de34d0ff0d8 Sat Sep 19 10:17:09 2026 -0700
docent: six regression scripts written from the tours, refs #38252
rm38335 rm38298 rm37996 rm38249 rm38268 rm38364, one per ticket that got a
before-and-after tour this week. 95 scripts now, make proof 45 of 95, and the
whole directory is green against genome-test.
Five of the six carry release-ab and the sixth sandbox-ab on their first day,
which is unusual here and is only because the before had already been rendered
and measured for the ticket comment: hgwbeta returns "Mangled CGI input string
bogus" (rm38335), one codon number instead of two (rm38298), the ASCII table
with no banner (rm37996), "not supported by QuickLift" for all four alignment
families (rm38249) and "Can't find strchive in track database hg19" (rm38268).
rm38364's before is ts park 38373, master frozen two days before that feature
merged, since it is newer than any release.
Three things they cost, each also in README.txt:
* where the text lives decides how it is read. rm38309 reads its exon text
out of a map box's data-tooltip, but rm38298's codon tooltip is not in the
served map at all -- the page's own JavaScript builds it on mouseenter --
so that one hovers and asserts tip:. rm38268's item label is in the drawn
PNG and nowhere else, so it asserts the map box's href and tooltip rather
than a text: that can never match.
* a superTrack still does not pass its setting to its members. rm38268 opens
strVar to reach strchive and then cannot use exact: on hg38, because the
sibling repeat tracks come up at their own visibilities.
* an hg.conf gate belongs in the header, loudly. rm38364 fails every check
when denseClick is off, and that is a configuration answer rather than a
regression, so the header carries the grep that settles it.
rm37996 has a date on it. The new hgBlat results page is opt-in while it is
tested and the banner names 2026-10-21 as the day it becomes the default; on
that day the first two steps come out and the goto: gains blatNewPage=1.
- src/hg/utils/docent/tests/regress/rm38251.docent.yaml
- lines changed 129, context: html, text, full: html, text
bbe654a9dc89bc7b75d40d1fe197d5376d756580 Thu Sep 17 17:08:10 2026 -0700
docent: 22 regression tests for a QA list, and release-ab evidence from v503, refs #38252
One script per ticket for twenty-two that had none: rm10138, rm36940, rm37969,
rm38171, rm38184, rm38198, rm38200, rm38205, rm38206, rm38223, rm38236, rm38248,
rm38251, rm38257, rm38279, rm38281, rm38283, rm38284, rm38285, rm38302, rm38303
and rm38309. No theme -- they run from a menu-bar color to a SIGSEGV in a
quickLift view. Three fixtures came with them, under
~/public_html/docentFixtures: rm36940 (seven bigBed tracks differing only in the
field count on the type line), rm38283 (one description page full of dollar
variables) and rm38184 (a one-line session settings file).
Every one was then run against v503, which is what the new proof level is for.
v503_branch 707b184e329 went into a ticket sandbox -- CGIs, js and htdocs, since
three of the fixes live in hg/js or htdocs/style -- and twenty-one of the
twenty-four fix commits landed after that branch was cut, so the release has the
bugs. Eighteen scripts failed there on their own check and carry a release-ab
line quoting the failure.
release-ab sits between sandbox-ab and server-flip. It is stronger than
sandbox-ab because anyone can rebuild it from a tag, where a hand-patched tree
lives in one person's home directory and does not survive a rebase.
The four that v503 does not cover are each said in their own header: rm38171's
fix is IN v503 so an older release is its baseline; rm36940's fixture hub draws
nothing there, so the run never reaches the check; rm38257's login: dies against
a park on any baseline; and rm38309 PASSES, which is exactly what its header
claims, since that fix changes no byte of any page.
rm38251 had to be rewritten because of what the sweep said. It PASSED on a build
carrying its own bug, at every width from 390 to 1099px: the icon had slid 312px
left but was still inside the bar, and the clear: check named the links, where
the icon fell in a gap between two of them. Naming the menu list instead has no
gaps. Without the sweep it would have sat here looking green.
make proof: 89 scripts, 33 watched to fail for the reason they exist and then
pass, up from 13.
- src/hg/utils/docent/tests/regress/rm38253.docent.yaml
- lines changed 100, context: html, text, full: html, text
c52d505f538f7636e48aa5c06b9ad208697471a9 Sun Sep 20 14:34:31 2026 -0700
docent: three regression scripts for tickets nothing was watching, refs #38252
#38391's test registry named four tickets with neither a unit test nor a script
here. These are three of them. They have little else in common, and each needed
a different answer to the same question: what about this bug is steady enough to
assert. 98 scripts now, `make proof` 46 of 98.
rm38253, the coverage-graph rewrite. Its fixture is six features on hg38 chr1,
three nested inside each other in each of two groups, so their coverage is a
staircase with FLAT steps: 1 2 3 2 1 over 20 kb, and the same again over 20 bp.
Flat is the point. Each pixel's value is the mean coverage of the bases it
covers, and the mean of a constant is that constant, so a reading taken in the
middle of a step does not depend on where a pixel boundary falls, on insideWidth,
or on the window being a round number of bases. The two windows take the two
sampling paths on purpose, and the 200 bp one is countsToPixelsUp, which
pixelSweep.sh never reaches because every cell in it is wider than insideWidth.
The script CANNOT flip on its own fix and its header says so: #38253 is a rewrite
required to draw the same picture it replaced, verified with 96 pixel comparisons,
so both builds answer the same and no baseline can tell them apart. What was
proved instead is that the checks discriminate, by pointing each of the twelve
readings at a neighbouring step's value: all twelve went red.
rm38317, the knownGene page that prints an OMIM link built from uninitialised
memory. The link itself is the wrong thing to test for, since it is whatever was
on the stack and comes and goes between loads of the same URL; an earlier probe
of this ticket asked only for its absence and concluded the bug did not reproduce.
The same struct is read a second time further down, and that read is deterministic:
the page stops dead right after "Links to sequence:", with no Translated Protein
link and no Genomic Sequence link, on every load of all three assemblies. Lou
Nassar's note of 2026-09-18 is what identified that; the description does not
mention it. Measured on hgwbeta against genome-test, 2026-09-20: 17,487 to 27,026
bytes on hg19, 17,656 to 27,456 on hg38, 17,484 to 25,616 on mm39. So this one
carries a release-ab line. A RefSeq page is the control, where the OMIM link is
real and must still be there.
rm38086, the BLAT Results track group. It runs a real search, lets the results
page build its own custom track through its ajax to hgc, and then asks for the
group, the Delete all button, the per-track delete icon, the row being DRAWN
(5915dcd2939: a result track used to come up hidden) and both new names. Two
names in full, each a different half of 4fd18ab7854: "102bp SMYD4" for a
nucleotide query and "60aa TP53" for a protein one, where the aa is the point.
The old name "blat YourSeq" is asserted absent. hgwbeta is NOT a baseline for
it: v503_branch already carries these commits, so beta answering with the old
name is almost certainly hg.conf blatResultsGroup being off, and preflight
cannot read beta's hg.conf from here to settle it. Assertion-only, and the
header says why rather than leaving the next reader to try beta again.
The fixture hub is ~/public_html/docentFixtures/rm38253, beside the others.
README.txt gains a section on all of this, including one trap worth repeating:
never assert a title attribute, not even on a button. rm38086's first draft
matched `button#blat_delAll[title=...]`, which is in the served HTML and matches
nothing once hgTracks has copied every title into a mouseoverText attribute.
- src/hg/utils/docent/tests/regress/rm38257.docent.yaml
- lines changed 73, context: html, text, full: html, text
bbe654a9dc89bc7b75d40d1fe197d5376d756580 Thu Sep 17 17:08:10 2026 -0700
docent: 22 regression tests for a QA list, and release-ab evidence from v503, refs #38252
One script per ticket for twenty-two that had none: rm10138, rm36940, rm37969,
rm38171, rm38184, rm38198, rm38200, rm38205, rm38206, rm38223, rm38236, rm38248,
rm38251, rm38257, rm38279, rm38281, rm38283, rm38284, rm38285, rm38302, rm38303
and rm38309. No theme -- they run from a menu-bar color to a SIGSEGV in a
quickLift view. Three fixtures came with them, under
~/public_html/docentFixtures: rm36940 (seven bigBed tracks differing only in the
field count on the type line), rm38283 (one description page full of dollar
variables) and rm38184 (a one-line session settings file).
Every one was then run against v503, which is what the new proof level is for.
v503_branch 707b184e329 went into a ticket sandbox -- CGIs, js and htdocs, since
three of the fixes live in hg/js or htdocs/style -- and twenty-one of the
twenty-four fix commits landed after that branch was cut, so the release has the
bugs. Eighteen scripts failed there on their own check and carry a release-ab
line quoting the failure.
release-ab sits between sandbox-ab and server-flip. It is stronger than
sandbox-ab because anyone can rebuild it from a tag, where a hand-patched tree
lives in one person's home directory and does not survive a rebase.
The four that v503 does not cover are each said in their own header: rm38171's
fix is IN v503 so an older release is its baseline; rm36940's fixture hub draws
nothing there, so the run never reaches the check; rm38257's login: dies against
a park on any baseline; and rm38309 PASSES, which is exactly what its header
claims, since that fix changes no byte of any page.
rm38251 had to be rewritten because of what the sweep said. It PASSED on a build
carrying its own bug, at every width from 390 to 1099px: the icon had slid 312px
left but was still inside the bar, and the clear: check named the links, where
the icon fell in a gap between two of them. Naming the menu list instead has no
gaps. Without the sweep it would have sat here looking green.
make proof: 89 scripts, 33 watched to fail for the reason they exist and then
pass, up from 13.
- src/hg/utils/docent/tests/regress/rm38268.docent.yaml
- lines changed 45, context: html, text, full: html, text
b7fe2f0542ac4a5e182b86ab6f794de34d0ff0d8 Sat Sep 19 10:17:09 2026 -0700
docent: six regression scripts written from the tours, refs #38252
rm38335 rm38298 rm37996 rm38249 rm38268 rm38364, one per ticket that got a
before-and-after tour this week. 95 scripts now, make proof 45 of 95, and the
whole directory is green against genome-test.
Five of the six carry release-ab and the sixth sandbox-ab on their first day,
which is unusual here and is only because the before had already been rendered
and measured for the ticket comment: hgwbeta returns "Mangled CGI input string
bogus" (rm38335), one codon number instead of two (rm38298), the ASCII table
with no banner (rm37996), "not supported by QuickLift" for all four alignment
families (rm38249) and "Can't find strchive in track database hg19" (rm38268).
rm38364's before is ts park 38373, master frozen two days before that feature
merged, since it is newer than any release.
Three things they cost, each also in README.txt:
* where the text lives decides how it is read. rm38309 reads its exon text
out of a map box's data-tooltip, but rm38298's codon tooltip is not in the
served map at all -- the page's own JavaScript builds it on mouseenter --
so that one hovers and asserts tip:. rm38268's item label is in the drawn
PNG and nowhere else, so it asserts the map box's href and tooltip rather
than a text: that can never match.
* a superTrack still does not pass its setting to its members. rm38268 opens
strVar to reach strchive and then cannot use exact: on hg38, because the
sibling repeat tracks come up at their own visibilities.
* an hg.conf gate belongs in the header, loudly. rm38364 fails every check
when denseClick is off, and that is a configuration answer rather than a
regression, so the header carries the grep that settles it.
rm37996 has a date on it. The new hgBlat results page is opt-in while it is
tested and the banner names 2026-10-21 as the day it becomes the default; on
that day the first two steps come out and the goto: gains blatNewPage=1.
- src/hg/utils/docent/tests/regress/rm38279.docent.yaml
- lines changed 95, context: html, text, full: html, text
bbe654a9dc89bc7b75d40d1fe197d5376d756580 Thu Sep 17 17:08:10 2026 -0700
docent: 22 regression tests for a QA list, and release-ab evidence from v503, refs #38252
One script per ticket for twenty-two that had none: rm10138, rm36940, rm37969,
rm38171, rm38184, rm38198, rm38200, rm38205, rm38206, rm38223, rm38236, rm38248,
rm38251, rm38257, rm38279, rm38281, rm38283, rm38284, rm38285, rm38302, rm38303
and rm38309. No theme -- they run from a menu-bar color to a SIGSEGV in a
quickLift view. Three fixtures came with them, under
~/public_html/docentFixtures: rm36940 (seven bigBed tracks differing only in the
field count on the type line), rm38283 (one description page full of dollar
variables) and rm38184 (a one-line session settings file).
Every one was then run against v503, which is what the new proof level is for.
v503_branch 707b184e329 went into a ticket sandbox -- CGIs, js and htdocs, since
three of the fixes live in hg/js or htdocs/style -- and twenty-one of the
twenty-four fix commits landed after that branch was cut, so the release has the
bugs. Eighteen scripts failed there on their own check and carry a release-ab
line quoting the failure.
release-ab sits between sandbox-ab and server-flip. It is stronger than
sandbox-ab because anyone can rebuild it from a tag, where a hand-patched tree
lives in one person's home directory and does not survive a rebase.
The four that v503 does not cover are each said in their own header: rm38171's
fix is IN v503 so an older release is its baseline; rm36940's fixture hub draws
nothing there, so the run never reaches the check; rm38257's login: dies against
a park on any baseline; and rm38309 PASSES, which is exactly what its header
claims, since that fix changes no byte of any page.
rm38251 had to be rewritten because of what the sweep said. It PASSED on a build
carrying its own bug, at every width from 390 to 1099px: the icon had slid 312px
left but was still inside the bar, and the clear: check named the links, where
the icon fell in a gap between two of them. Naming the menu list instead has no
gaps. Without the sweep it would have sat here looking green.
make proof: 89 scripts, 33 watched to fail for the reason they exist and then
pass, up from 13.
- lines changed 32, context: html, text, full: html, text
38f431f1d75c92d3c0518f60f141008ae72d133b Fri Sep 18 09:56:52 2026 -0700
docent: retranslate the density-label checks after the reword, refs #38252
07f0635fd35 reworded all three density-mode labels on 2026-09-18, and the 04:10
nightly went red on rm38279 four hours later. The code is right; the scripts
asserted wording that no longer exists.
rm38279 covers all three causes, so all four of its label steps move. The two
automatic messages are now "density graph: too many items, zoom in" for a window
past maxWindowCoverage and "density graph: too many items, zoom in or use dense"
for too many features, and the first is a strict PREFIX of the second.
mouseoverText*= is a substring match, so a bare noHas on the shorter one matches
the longer one too and fails on the track it is meant to pass. labelAddNote()
wraps a note as " (%s)", so every check now carries the closing paren and each
message matches itself and nothing else. Verified by pointing each has: at the
wrong message in turn: all three fail, including the prefix case. Step 5 went
from two noHas lines to one, since all three notes now share a prefix.
rm36888.xfail asserts the same old string twice and nobody asked about it,
because it is an xfail and it stayed red. It is still red for its own reason --
the run says `rows not drawn: rm36888Methyl`, with the note check second -- but
the stale string was a trap on a delay: when the bigMethyl fix lands, the row
draws, the note appears with the new wording, the has: still misses, and the
xfail never flips. Both its selectors now match "density graph: too many items",
the prefix the two automatic causes share, which is what the pre-reword string
did as well. The full sentence is the one that bug should produce, but nobody
can see it until the fix lands, and an exact string guessed from the source
would rebuild the trap. Tighten it on the day it goes green.
The release-ab line on rm38279 still stands: v503 carries no density note at
all, so a reword cannot reach it.
- src/hg/utils/docent/tests/regress/rm38281.docent.yaml
- lines changed 79, context: html, text, full: html, text
bbe654a9dc89bc7b75d40d1fe197d5376d756580 Thu Sep 17 17:08:10 2026 -0700
docent: 22 regression tests for a QA list, and release-ab evidence from v503, refs #38252
One script per ticket for twenty-two that had none: rm10138, rm36940, rm37969,
rm38171, rm38184, rm38198, rm38200, rm38205, rm38206, rm38223, rm38236, rm38248,
rm38251, rm38257, rm38279, rm38281, rm38283, rm38284, rm38285, rm38302, rm38303
and rm38309. No theme -- they run from a menu-bar color to a SIGSEGV in a
quickLift view. Three fixtures came with them, under
~/public_html/docentFixtures: rm36940 (seven bigBed tracks differing only in the
field count on the type line), rm38283 (one description page full of dollar
variables) and rm38184 (a one-line session settings file).
Every one was then run against v503, which is what the new proof level is for.
v503_branch 707b184e329 went into a ticket sandbox -- CGIs, js and htdocs, since
three of the fixes live in hg/js or htdocs/style -- and twenty-one of the
twenty-four fix commits landed after that branch was cut, so the release has the
bugs. Eighteen scripts failed there on their own check and carry a release-ab
line quoting the failure.
release-ab sits between sandbox-ab and server-flip. It is stronger than
sandbox-ab because anyone can rebuild it from a tag, where a hand-patched tree
lives in one person's home directory and does not survive a rebase.
The four that v503 does not cover are each said in their own header: rm38171's
fix is IN v503 so an older release is its baseline; rm36940's fixture hub draws
nothing there, so the run never reaches the check; rm38257's login: dies against
a park on any baseline; and rm38309 PASSES, which is exactly what its header
claims, since that fix changes no byte of any page.
rm38251 had to be rewritten because of what the sweep said. It PASSED on a build
carrying its own bug, at every width from 390 to 1099px: the icon had slid 312px
left but was still inside the bar, and the clear: check named the links, where
the icon fell in a gap between two of them. Naming the menu list instead has no
gaps. Without the sweep it would have sat here looking green.
make proof: 89 scripts, 33 watched to fail for the reason they exist and then
pass, up from 13.
- src/hg/utils/docent/tests/regress/rm38283.docent.yaml
- lines changed 90, context: html, text, full: html, text
bbe654a9dc89bc7b75d40d1fe197d5376d756580 Thu Sep 17 17:08:10 2026 -0700
docent: 22 regression tests for a QA list, and release-ab evidence from v503, refs #38252
One script per ticket for twenty-two that had none: rm10138, rm36940, rm37969,
rm38171, rm38184, rm38198, rm38200, rm38205, rm38206, rm38223, rm38236, rm38248,
rm38251, rm38257, rm38279, rm38281, rm38283, rm38284, rm38285, rm38302, rm38303
and rm38309. No theme -- they run from a menu-bar color to a SIGSEGV in a
quickLift view. Three fixtures came with them, under
~/public_html/docentFixtures: rm36940 (seven bigBed tracks differing only in the
field count on the type line), rm38283 (one description page full of dollar
variables) and rm38184 (a one-line session settings file).
Every one was then run against v503, which is what the new proof level is for.
v503_branch 707b184e329 went into a ticket sandbox -- CGIs, js and htdocs, since
three of the fixes live in hg/js or htdocs/style -- and twenty-one of the
twenty-four fix commits landed after that branch was cut, so the release has the
bugs. Eighteen scripts failed there on their own check and carry a release-ab
line quoting the failure.
release-ab sits between sandbox-ab and server-flip. It is stronger than
sandbox-ab because anyone can rebuild it from a tag, where a hand-patched tree
lives in one person's home directory and does not survive a rebase.
The four that v503 does not cover are each said in their own header: rm38171's
fix is IN v503 so an older release is its baseline; rm36940's fixture hub draws
nothing there, so the run never reaches the check; rm38257's login: dies against
a park on any baseline; and rm38309 PASSES, which is exactly what its header
claims, since that fix changes no byte of any page.
rm38251 had to be rewritten because of what the sweep said. It PASSED on a build
carrying its own bug, at every width from 390 to 1099px: the icon had slid 312px
left but was still inside the bar, and the clear: check named the links, where
the icon fell in a gap between two of them. Naming the menu list instead has no
gaps. Without the sweep it would have sat here looking green.
make proof: 89 scripts, 33 watched to fail for the reason they exist and then
pass, up from 13.
- src/hg/utils/docent/tests/regress/rm38284.docent.yaml
- lines changed 82, context: html, text, full: html, text
bbe654a9dc89bc7b75d40d1fe197d5376d756580 Thu Sep 17 17:08:10 2026 -0700
docent: 22 regression tests for a QA list, and release-ab evidence from v503, refs #38252
One script per ticket for twenty-two that had none: rm10138, rm36940, rm37969,
rm38171, rm38184, rm38198, rm38200, rm38205, rm38206, rm38223, rm38236, rm38248,
rm38251, rm38257, rm38279, rm38281, rm38283, rm38284, rm38285, rm38302, rm38303
and rm38309. No theme -- they run from a menu-bar color to a SIGSEGV in a
quickLift view. Three fixtures came with them, under
~/public_html/docentFixtures: rm36940 (seven bigBed tracks differing only in the
field count on the type line), rm38283 (one description page full of dollar
variables) and rm38184 (a one-line session settings file).
Every one was then run against v503, which is what the new proof level is for.
v503_branch 707b184e329 went into a ticket sandbox -- CGIs, js and htdocs, since
three of the fixes live in hg/js or htdocs/style -- and twenty-one of the
twenty-four fix commits landed after that branch was cut, so the release has the
bugs. Eighteen scripts failed there on their own check and carry a release-ab
line quoting the failure.
release-ab sits between sandbox-ab and server-flip. It is stronger than
sandbox-ab because anyone can rebuild it from a tag, where a hand-patched tree
lives in one person's home directory and does not survive a rebase.
The four that v503 does not cover are each said in their own header: rm38171's
fix is IN v503 so an older release is its baseline; rm36940's fixture hub draws
nothing there, so the run never reaches the check; rm38257's login: dies against
a park on any baseline; and rm38309 PASSES, which is exactly what its header
claims, since that fix changes no byte of any page.
rm38251 had to be rewritten because of what the sweep said. It PASSED on a build
carrying its own bug, at every width from 390 to 1099px: the icon had slid 312px
left but was still inside the bar, and the clear: check named the links, where
the icon fell in a gap between two of them. Naming the menu list instead has no
gaps. Without the sweep it would have sat here looking green.
make proof: 89 scripts, 33 watched to fail for the reason they exist and then
pass, up from 13.
- src/hg/utils/docent/tests/regress/rm38285.docent.yaml
- lines changed 61, context: html, text, full: html, text
bbe654a9dc89bc7b75d40d1fe197d5376d756580 Thu Sep 17 17:08:10 2026 -0700
docent: 22 regression tests for a QA list, and release-ab evidence from v503, refs #38252
One script per ticket for twenty-two that had none: rm10138, rm36940, rm37969,
rm38171, rm38184, rm38198, rm38200, rm38205, rm38206, rm38223, rm38236, rm38248,
rm38251, rm38257, rm38279, rm38281, rm38283, rm38284, rm38285, rm38302, rm38303
and rm38309. No theme -- they run from a menu-bar color to a SIGSEGV in a
quickLift view. Three fixtures came with them, under
~/public_html/docentFixtures: rm36940 (seven bigBed tracks differing only in the
field count on the type line), rm38283 (one description page full of dollar
variables) and rm38184 (a one-line session settings file).
Every one was then run against v503, which is what the new proof level is for.
v503_branch 707b184e329 went into a ticket sandbox -- CGIs, js and htdocs, since
three of the fixes live in hg/js or htdocs/style -- and twenty-one of the
twenty-four fix commits landed after that branch was cut, so the release has the
bugs. Eighteen scripts failed there on their own check and carry a release-ab
line quoting the failure.
release-ab sits between sandbox-ab and server-flip. It is stronger than
sandbox-ab because anyone can rebuild it from a tag, where a hand-patched tree
lives in one person's home directory and does not survive a rebase.
The four that v503 does not cover are each said in their own header: rm38171's
fix is IN v503 so an older release is its baseline; rm36940's fixture hub draws
nothing there, so the run never reaches the check; rm38257's login: dies against
a park on any baseline; and rm38309 PASSES, which is exactly what its header
claims, since that fix changes no byte of any page.
rm38251 had to be rewritten because of what the sweep said. It PASSED on a build
carrying its own bug, at every width from 390 to 1099px: the icon had slid 312px
left but was still inside the bar, and the clear: check named the links, where
the icon fell in a gap between two of them. Naming the menu list instead has no
gaps. Without the sweep it would have sat here looking green.
make proof: 89 scripts, 33 watched to fail for the reason they exist and then
pass, up from 13.
- src/hg/utils/docent/tests/regress/rm38298.docent.yaml
- lines changed 43, context: html, text, full: html, text
b7fe2f0542ac4a5e182b86ab6f794de34d0ff0d8 Sat Sep 19 10:17:09 2026 -0700
docent: six regression scripts written from the tours, refs #38252
rm38335 rm38298 rm37996 rm38249 rm38268 rm38364, one per ticket that got a
before-and-after tour this week. 95 scripts now, make proof 45 of 95, and the
whole directory is green against genome-test.
Five of the six carry release-ab and the sixth sandbox-ab on their first day,
which is unusual here and is only because the before had already been rendered
and measured for the ticket comment: hgwbeta returns "Mangled CGI input string
bogus" (rm38335), one codon number instead of two (rm38298), the ASCII table
with no banner (rm37996), "not supported by QuickLift" for all four alignment
families (rm38249) and "Can't find strchive in track database hg19" (rm38268).
rm38364's before is ts park 38373, master frozen two days before that feature
merged, since it is newer than any release.
Three things they cost, each also in README.txt:
* where the text lives decides how it is read. rm38309 reads its exon text
out of a map box's data-tooltip, but rm38298's codon tooltip is not in the
served map at all -- the page's own JavaScript builds it on mouseenter --
so that one hovers and asserts tip:. rm38268's item label is in the drawn
PNG and nowhere else, so it asserts the map box's href and tooltip rather
than a text: that can never match.
* a superTrack still does not pass its setting to its members. rm38268 opens
strVar to reach strchive and then cannot use exact: on hg38, because the
sibling repeat tracks come up at their own visibilities.
* an hg.conf gate belongs in the header, loudly. rm38364 fails every check
when denseClick is off, and that is a configuration answer rather than a
regression, so the header carries the grep that settles it.
rm37996 has a date on it. The new hgBlat results page is opt-in while it is
tested and the banner names 2026-10-21 as the day it becomes the default; on
that day the first two steps come out and the goto: gains blatNewPage=1.
- src/hg/utils/docent/tests/regress/rm38302.docent.yaml
- lines changed 50, context: html, text, full: html, text
bbe654a9dc89bc7b75d40d1fe197d5376d756580 Thu Sep 17 17:08:10 2026 -0700
docent: 22 regression tests for a QA list, and release-ab evidence from v503, refs #38252
One script per ticket for twenty-two that had none: rm10138, rm36940, rm37969,
rm38171, rm38184, rm38198, rm38200, rm38205, rm38206, rm38223, rm38236, rm38248,
rm38251, rm38257, rm38279, rm38281, rm38283, rm38284, rm38285, rm38302, rm38303
and rm38309. No theme -- they run from a menu-bar color to a SIGSEGV in a
quickLift view. Three fixtures came with them, under
~/public_html/docentFixtures: rm36940 (seven bigBed tracks differing only in the
field count on the type line), rm38283 (one description page full of dollar
variables) and rm38184 (a one-line session settings file).
Every one was then run against v503, which is what the new proof level is for.
v503_branch 707b184e329 went into a ticket sandbox -- CGIs, js and htdocs, since
three of the fixes live in hg/js or htdocs/style -- and twenty-one of the
twenty-four fix commits landed after that branch was cut, so the release has the
bugs. Eighteen scripts failed there on their own check and carry a release-ab
line quoting the failure.
release-ab sits between sandbox-ab and server-flip. It is stronger than
sandbox-ab because anyone can rebuild it from a tag, where a hand-patched tree
lives in one person's home directory and does not survive a rebase.
The four that v503 does not cover are each said in their own header: rm38171's
fix is IN v503 so an older release is its baseline; rm36940's fixture hub draws
nothing there, so the run never reaches the check; rm38257's login: dies against
a park on any baseline; and rm38309 PASSES, which is exactly what its header
claims, since that fix changes no byte of any page.
rm38251 had to be rewritten because of what the sweep said. It PASSED on a build
carrying its own bug, at every width from 390 to 1099px: the icon had slid 312px
left but was still inside the bar, and the clear: check named the links, where
the icon fell in a gap between two of them. Naming the menu list instead has no
gaps. Without the sweep it would have sat here looking green.
make proof: 89 scripts, 33 watched to fail for the reason they exist and then
pass, up from 13.
- src/hg/utils/docent/tests/regress/rm38303.docent.yaml
- lines changed 72, context: html, text, full: html, text
bbe654a9dc89bc7b75d40d1fe197d5376d756580 Thu Sep 17 17:08:10 2026 -0700
docent: 22 regression tests for a QA list, and release-ab evidence from v503, refs #38252
One script per ticket for twenty-two that had none: rm10138, rm36940, rm37969,
rm38171, rm38184, rm38198, rm38200, rm38205, rm38206, rm38223, rm38236, rm38248,
rm38251, rm38257, rm38279, rm38281, rm38283, rm38284, rm38285, rm38302, rm38303
and rm38309. No theme -- they run from a menu-bar color to a SIGSEGV in a
quickLift view. Three fixtures came with them, under
~/public_html/docentFixtures: rm36940 (seven bigBed tracks differing only in the
field count on the type line), rm38283 (one description page full of dollar
variables) and rm38184 (a one-line session settings file).
Every one was then run against v503, which is what the new proof level is for.
v503_branch 707b184e329 went into a ticket sandbox -- CGIs, js and htdocs, since
three of the fixes live in hg/js or htdocs/style -- and twenty-one of the
twenty-four fix commits landed after that branch was cut, so the release has the
bugs. Eighteen scripts failed there on their own check and carry a release-ab
line quoting the failure.
release-ab sits between sandbox-ab and server-flip. It is stronger than
sandbox-ab because anyone can rebuild it from a tag, where a hand-patched tree
lives in one person's home directory and does not survive a rebase.
The four that v503 does not cover are each said in their own header: rm38171's
fix is IN v503 so an older release is its baseline; rm36940's fixture hub draws
nothing there, so the run never reaches the check; rm38257's login: dies against
a park on any baseline; and rm38309 PASSES, which is exactly what its header
claims, since that fix changes no byte of any page.
rm38251 had to be rewritten because of what the sweep said. It PASSED on a build
carrying its own bug, at every width from 390 to 1099px: the icon had slid 312px
left but was still inside the bar, and the clear: check named the links, where
the icon fell in a gap between two of them. Naming the menu list instead has no
gaps. Without the sweep it would have sat here looking green.
make proof: 89 scripts, 33 watched to fail for the reason they exist and then
pass, up from 13.
- src/hg/utils/docent/tests/regress/rm38309.docent.yaml
- lines changed 75, context: html, text, full: html, text
bbe654a9dc89bc7b75d40d1fe197d5376d756580 Thu Sep 17 17:08:10 2026 -0700
docent: 22 regression tests for a QA list, and release-ab evidence from v503, refs #38252
One script per ticket for twenty-two that had none: rm10138, rm36940, rm37969,
rm38171, rm38184, rm38198, rm38200, rm38205, rm38206, rm38223, rm38236, rm38248,
rm38251, rm38257, rm38279, rm38281, rm38283, rm38284, rm38285, rm38302, rm38303
and rm38309. No theme -- they run from a menu-bar color to a SIGSEGV in a
quickLift view. Three fixtures came with them, under
~/public_html/docentFixtures: rm36940 (seven bigBed tracks differing only in the
field count on the type line), rm38283 (one description page full of dollar
variables) and rm38184 (a one-line session settings file).
Every one was then run against v503, which is what the new proof level is for.
v503_branch 707b184e329 went into a ticket sandbox -- CGIs, js and htdocs, since
three of the fixes live in hg/js or htdocs/style -- and twenty-one of the
twenty-four fix commits landed after that branch was cut, so the release has the
bugs. Eighteen scripts failed there on their own check and carry a release-ab
line quoting the failure.
release-ab sits between sandbox-ab and server-flip. It is stronger than
sandbox-ab because anyone can rebuild it from a tag, where a hand-patched tree
lives in one person's home directory and does not survive a rebase.
The four that v503 does not cover are each said in their own header: rm38171's
fix is IN v503 so an older release is its baseline; rm36940's fixture hub draws
nothing there, so the run never reaches the check; rm38257's login: dies against
a park on any baseline; and rm38309 PASSES, which is exactly what its header
claims, since that fix changes no byte of any page.
rm38251 had to be rewritten because of what the sweep said. It PASSED on a build
carrying its own bug, at every width from 390 to 1099px: the icon had slid 312px
left but was still inside the bar, and the clear: check named the links, where
the icon fell in a gap between two of them. Naming the menu list instead has no
gaps. Without the sweep it would have sat here looking green.
make proof: 89 scripts, 33 watched to fail for the reason they exist and then
pass, up from 13.
- lines changed 1, context: html, text, full: html, text
cd13b3b171159247f1d105f650cce2a0726cd67b Fri Sep 18 16:08:59 2026 -0700
docent: release-ab evidence for six scripts, from the released docker images, refs #38252
Six scripts move from assertion-only to release-ab. The baselines are the released
v499 to v503 docker images running on hgwdev, which give what the v503 ticket park
could not: a range of releases rather than a single one.
Three were watched to flip, and each flips at exactly the release its fix first
ships in, which is what says the failure is the ticket's own and not version drift:
rm27113 fails v499 v500, passes v501 94f9b53d3db and b551f6c3ac8 first ship in v501
rm37743 fails v499, passes v500 7b74ff4b43a first ships in v500
rm38108 fails v499 to v502, passes v503 7181c0af889 first ships in v503
Three fail on every released image and pass on genome-test, which is correct rather
than a gap: their fixes are on master only and ship in v504.
rm38126 the descPage- prefix is absent on every release
rm38185 the position after an empty CGI pair is eaten on every release
rm38309 the exon tooltip the fix adds is absent on every release
Each failure was read rather than counted. rm27113 fails on a position with the page
otherwise whole at 10 rows; rm37743 fails on its own error string; rm38108 draws no
ruler at all, which is the crash it covers.
Two candidates were rejected after looking at them, and are worth naming so they are
not re-picked. rm34651 appears to flip at v500, but fa3431cd36b is already in v499 and
the clinvar track simply has no density options there, so the flip is not its own.
rm35333 appeared to flip and did not: it reads an hs1 hub, and hs1 was repaired in the
images midway through the sweep, so the flip was the repair rather than the code.
make proof: 39 of 89, up from 33.
- src/hg/utils/docent/tests/regress/rm38317.docent.yaml
- lines changed 79, context: html, text, full: html, text
c52d505f538f7636e48aa5c06b9ad208697471a9 Sun Sep 20 14:34:31 2026 -0700
docent: three regression scripts for tickets nothing was watching, refs #38252
#38391's test registry named four tickets with neither a unit test nor a script
here. These are three of them. They have little else in common, and each needed
a different answer to the same question: what about this bug is steady enough to
assert. 98 scripts now, `make proof` 46 of 98.
rm38253, the coverage-graph rewrite. Its fixture is six features on hg38 chr1,
three nested inside each other in each of two groups, so their coverage is a
staircase with FLAT steps: 1 2 3 2 1 over 20 kb, and the same again over 20 bp.
Flat is the point. Each pixel's value is the mean coverage of the bases it
covers, and the mean of a constant is that constant, so a reading taken in the
middle of a step does not depend on where a pixel boundary falls, on insideWidth,
or on the window being a round number of bases. The two windows take the two
sampling paths on purpose, and the 200 bp one is countsToPixelsUp, which
pixelSweep.sh never reaches because every cell in it is wider than insideWidth.
The script CANNOT flip on its own fix and its header says so: #38253 is a rewrite
required to draw the same picture it replaced, verified with 96 pixel comparisons,
so both builds answer the same and no baseline can tell them apart. What was
proved instead is that the checks discriminate, by pointing each of the twelve
readings at a neighbouring step's value: all twelve went red.
rm38317, the knownGene page that prints an OMIM link built from uninitialised
memory. The link itself is the wrong thing to test for, since it is whatever was
on the stack and comes and goes between loads of the same URL; an earlier probe
of this ticket asked only for its absence and concluded the bug did not reproduce.
The same struct is read a second time further down, and that read is deterministic:
the page stops dead right after "Links to sequence:", with no Translated Protein
link and no Genomic Sequence link, on every load of all three assemblies. Lou
Nassar's note of 2026-09-18 is what identified that; the description does not
mention it. Measured on hgwbeta against genome-test, 2026-09-20: 17,487 to 27,026
bytes on hg19, 17,656 to 27,456 on hg38, 17,484 to 25,616 on mm39. So this one
carries a release-ab line. A RefSeq page is the control, where the OMIM link is
real and must still be there.
rm38086, the BLAT Results track group. It runs a real search, lets the results
page build its own custom track through its ajax to hgc, and then asks for the
group, the Delete all button, the per-track delete icon, the row being DRAWN
(5915dcd2939: a result track used to come up hidden) and both new names. Two
names in full, each a different half of 4fd18ab7854: "102bp SMYD4" for a
nucleotide query and "60aa TP53" for a protein one, where the aa is the point.
The old name "blat YourSeq" is asserted absent. hgwbeta is NOT a baseline for
it: v503_branch already carries these commits, so beta answering with the old
name is almost certainly hg.conf blatResultsGroup being off, and preflight
cannot read beta's hg.conf from here to settle it. Assertion-only, and the
header says why rather than leaving the next reader to try beta again.
The fixture hub is ~/public_html/docentFixtures/rm38253, beside the others.
README.txt gains a section on all of this, including one trap worth repeating:
never assert a title attribute, not even on a button. rm38086's first draft
matched `button#blat_delAll[title=...]`, which is in the served HTML and matches
nothing once hgTracks has copied every title into a mouseoverText attribute.
- src/hg/utils/docent/tests/regress/rm38335.docent.yaml
- lines changed 44, context: html, text, full: html, text
b7fe2f0542ac4a5e182b86ab6f794de34d0ff0d8 Sat Sep 19 10:17:09 2026 -0700
docent: six regression scripts written from the tours, refs #38252
rm38335 rm38298 rm37996 rm38249 rm38268 rm38364, one per ticket that got a
before-and-after tour this week. 95 scripts now, make proof 45 of 95, and the
whole directory is green against genome-test.
Five of the six carry release-ab and the sixth sandbox-ab on their first day,
which is unusual here and is only because the before had already been rendered
and measured for the ticket comment: hgwbeta returns "Mangled CGI input string
bogus" (rm38335), one codon number instead of two (rm38298), the ASCII table
with no banner (rm37996), "not supported by QuickLift" for all four alignment
families (rm38249) and "Can't find strchive in track database hg19" (rm38268).
rm38364's before is ts park 38373, master frozen two days before that feature
merged, since it is newer than any release.
Three things they cost, each also in README.txt:
* where the text lives decides how it is read. rm38309 reads its exon text
out of a map box's data-tooltip, but rm38298's codon tooltip is not in the
served map at all -- the page's own JavaScript builds it on mouseenter --
so that one hovers and asserts tip:. rm38268's item label is in the drawn
PNG and nowhere else, so it asserts the map box's href and tooltip rather
than a text: that can never match.
* a superTrack still does not pass its setting to its members. rm38268 opens
strVar to reach strchive and then cannot use exact: on hg38, because the
sibling repeat tracks come up at their own visibilities.
* an hg.conf gate belongs in the header, loudly. rm38364 fails every check
when denseClick is off, and that is a configuration answer rather than a
regression, so the header carries the grep that settles it.
rm37996 has a date on it. The new hgBlat results page is opt-in while it is
tested and the banner names 2026-10-21 as the day it becomes the default; on
that day the first two steps come out and the goto: gains blatNewPage=1.
- src/hg/utils/docent/tests/regress/rm38364.docent.yaml
- lines changed 45, context: html, text, full: html, text
b7fe2f0542ac4a5e182b86ab6f794de34d0ff0d8 Sat Sep 19 10:17:09 2026 -0700
docent: six regression scripts written from the tours, refs #38252
rm38335 rm38298 rm37996 rm38249 rm38268 rm38364, one per ticket that got a
before-and-after tour this week. 95 scripts now, make proof 45 of 95, and the
whole directory is green against genome-test.
Five of the six carry release-ab and the sixth sandbox-ab on their first day,
which is unusual here and is only because the before had already been rendered
and measured for the ticket comment: hgwbeta returns "Mangled CGI input string
bogus" (rm38335), one codon number instead of two (rm38298), the ASCII table
with no banner (rm37996), "not supported by QuickLift" for all four alignment
families (rm38249) and "Can't find strchive in track database hg19" (rm38268).
rm38364's before is ts park 38373, master frozen two days before that feature
merged, since it is newer than any release.
Three things they cost, each also in README.txt:
* where the text lives decides how it is read. rm38309 reads its exon text
out of a map box's data-tooltip, but rm38298's codon tooltip is not in the
served map at all -- the page's own JavaScript builds it on mouseenter --
so that one hovers and asserts tip:. rm38268's item label is in the drawn
PNG and nowhere else, so it asserts the map box's href and tooltip rather
than a text: that can never match.
* a superTrack still does not pass its setting to its members. rm38268 opens
strVar to reach strchive and then cannot use exact: on hg38, because the
sibling repeat tracks come up at their own visibilities.
* an hg.conf gate belongs in the header, loudly. rm38364 fails every check
when denseClick is off, and that is a configuration answer rather than a
regression, so the header carries the grep that settles it.
rm37996 has a date on it. The new hgBlat results page is opt-in while it is
tested and the banner names 2026-10-21 as the day it becomes the default; on
that day the first two steps come out and the goto: gains blatNewPage=1.
- src/hg/utils/docent/tests/search.docent.yaml
- lines changed 69, context: html, text, full: html, text
2e5054b09838bacf29b31bb64fbd234471e7cb71 Wed Sep 16 13:00:17 2026 -0700
docent: a test for hgFind's copy of isParentVisible, on hgSearch, refs #37892
The third and last of the three. isParentVisible() exists in the tree character
for character three times -- hg/lib/trackHub.c:1818, hg/hgCollection/hgCollection.c:269
and hg/lib/hgFind.c:2957 -- and each copy asks the same question, are this track's
containers visible, by reading the cart itself rather than going through the
accessor. Nine scripts in regress/ cover the first, collection.docent.yaml covers
the second, and this covers the third. A change to how visibility is stored has to
reach all three, or two of them quietly start answering from the trackDb default.
What this copy decides: isTrackVisible() at hgFind.c:2977 sets
category->visibility, and hgSearch groups its results by it -- "Visible Tracks"
when it is set, "Currently Hidden Tracks" when it is not (hgSearch.c:174,
js/hgSearch.js:44). The symptom is a search result for a track you have on in the
browser filed under the hidden heading, where nobody looking for it will open it.
This one needs NO LOGIN, which is why it is worth having even with the other two
covered: it is the cheap one, about eight seconds.
wgEncodeGencodeBasicV49 is the track because it satisfies both constraints at
once. It is in hgFindSpec, so it has search results at all; and its chain is
wgEncodeGencodeV49ViewGenes -> wgEncodeGencodeV49 (visibility 0) ->
wgEncodeGencodeSuper, which is `superTrack on` with no `show`, so isShow is FALSE
and a build that reads the cart wrongly stops the walk at the superTrack. A
top-level or default-visible track would have passed on the broken build.
The hideKids step is not tidiness. Showing the superTrack brings every other
archived version up at its own visibility -- V50 draws alongside and lands in
Visible Tracks too -- so without it the `exact:` would need rewriting every time
GENCODE ships a version. It costs 31 variables, one per archived composite.
ENST00000297261 rather than a gene symbol: one of SHH's transcripts, it reaches
the GENCODE sets, and it searches 65 categories where SHH searches 319. No count
is asserted anywhere -- every one of those numbers moves when a track is reloaded.
Same wait discipline as collection.docent.yaml, and for the same reason: wait for
EITHER heading, so a build that files the track on the wrong side fails at the
expect: naming the selector it wanted rather than timing out 15 seconds later with
a Playwright message.
Measured both ways. The same script with the track left hidden fails at the
assertion:
step 7 (expect) failed: nothing matches
"li[id="Visible Tracks"] li#wgEncodeGencodeBasicV49"
No derive baseline on purpose: the hideKids expansion is one variable per archived
GENCODE version, so a baseline would go red twice a year for a reason that is not
a bug. views is left out of expected/ for the same reason.
tests/ is 19 of 19 with four fixtures resolved and the derive baselines matching.
- src/hg/utils/hgConfCatalog/harvestHgConf.py
- lines changed 143, context: html, text, full: html, text
6cf2b25c7f0c34dedf380a38e8833b58f4e078eb Wed Sep 16 09:42:24 2026 -0700
hgConfCatalog: date a setting by the release branch that holds its commit, refs #37925
version_at() mapped a commit's timestamp onto the CGI_VERSION in effect at
the time. That is off by at least one release by construction, because the
version stamped at or before a commit is the release already branched, and it
is off by more when a commit is written before a cut and merged after it. All
28 flips in the age cache were wrong: 25 by one release, two by two, and
storeUserFiles by 22.
The report built on this tells somebody to delete the hg.conf line that a
flipped default made pointless, but only once the release that flipped it is
installed on the machine reading the file. Acting a release early turns the
feature off on hgwbeta or the RR.
Date a commit by the first v*_branch that contains it instead. Checked
against a containment test per branch: exact on all 30 flips and on 422 of the
429 introducing commits, the rest being 2001 settings reported as v10 rather
than v9, since the oldest branch in the tree is v9.
The cut points come from merge-base with master, not from the "New version
number vNNN" commit, which is the branch point for the recent releases but was
not for 163 of the 494 branches, the last of them v409.
Also report a flip that no branch carries yet as "not released yet" rather
than as "since vNNN", and refuse to write an undated cache when a checkout has
no release branches at all.
- src/hg/utils/hgConfCatalog/hgConfAges.json
- lines changed 1683, context: html, text, full: html, text
6cf2b25c7f0c34dedf380a38e8833b58f4e078eb Wed Sep 16 09:42:24 2026 -0700
hgConfCatalog: date a setting by the release branch that holds its commit, refs #37925
version_at() mapped a commit's timestamp onto the CGI_VERSION in effect at
the time. That is off by at least one release by construction, because the
version stamped at or before a commit is the release already branched, and it
is off by more when a commit is written before a cut and merged after it. All
28 flips in the age cache were wrong: 25 by one release, two by two, and
storeUserFiles by 22.
The report built on this tells somebody to delete the hg.conf line that a
flipped default made pointless, but only once the release that flipped it is
installed on the machine reading the file. Acting a release early turns the
feature off on hgwbeta or the RR.
Date a commit by the first v*_branch that contains it instead. Checked
against a containment test per branch: exact on all 30 flips and on 422 of the
429 introducing commits, the rest being 2001 settings reported as v10 rather
than v9, since the oldest branch in the tree is v9.
The cut points come from merge-base with master, not from the "New version
number vNNN" commit, which is the branch point for the recent releases but was
not for 163 of the 494 branches, the last of them v409.
Also report a flip that no branch carries yet as "not released yet" rather
than as "since vNNN", and refuse to write an undated cache when a checkout has
no release branches at all.
- src/hg/utils/hgConfCatalog/hgConfCatalog.py
- lines changed 12, context: html, text, full: html, text
6cf2b25c7f0c34dedf380a38e8833b58f4e078eb Wed Sep 16 09:42:24 2026 -0700
hgConfCatalog: date a setting by the release branch that holds its commit, refs #37925
version_at() mapped a commit's timestamp onto the CGI_VERSION in effect at
the time. That is off by at least one release by construction, because the
version stamped at or before a commit is the release already branched, and it
is off by more when a commit is written before a cut and merged after it. All
28 flips in the age cache were wrong: 25 by one release, two by two, and
storeUserFiles by 22.
The report built on this tells somebody to delete the hg.conf line that a
flipped default made pointless, but only once the release that flipped it is
installed on the machine reading the file. Acting a release early turns the
feature off on hgwbeta or the RR.
Date a commit by the first v*_branch that contains it instead. Checked
against a containment test per branch: exact on all 30 flips and on 422 of the
429 introducing commits, the rest being 2001 settings reported as v10 rather
than v9, since the oldest branch in the tree is v9.
The cut points come from merge-base with master, not from the "New version
number vNNN" commit, which is the branch point for the recent releases but was
not for 163 of the 494 branches, the last of them v409.
Also report a flip that no branch carries yet as "not released yet" rather
than as "since vNNN", and refuse to write an undated cache when a checkout has
no release branches at all.
- lines changed 42, context: html, text, full: html, text
b45b48de3c6266567adf6784a97d71bb47f4fbd0 Fri Sep 18 08:39:32 2026 -0700
hgConfCatalog: a run-time-built name is not a boolean flag to classify, refs #37925
hgLogin's social sign-in now reads login.oauth.<provider>.trustEmail with a
boolean accessor, so the {key} row started failing the rule that every boolean
flag is a gate or a knob. That row stands for a whole family, read elsewhere as
a string and as a credential, so neither answer is true of it and there is no
single default for the sunset report to follow. The Runtime-built names section
is now exempt from that check, and the row's note lists trustEmail as the one
field read as a boolean.
- lines changed 7, context: html, text, full: html, text
91ecf5d0d600ed4117a08a559725e80c8061a264 Sat Sep 19 02:30:57 2026 -0700
hgConfCatalog: register sessionLoadNotice, refs #37925
Written by nightlyRegister.sh, which records the settings the tree
reads that the catalog was missing. Only facts copied off the call
site are filled in. No classification is guessed: a new boolean gets no
role=, because calling a release gate a knob would hide it from the
sunset report for good, and every row lands in the 'Awaiting review'
section until somebody reads the call site.
sessionLoadNotice hg/hgTracks/hgTracks.c:12219 (38157)
wrote 1 row to the 'Awaiting review' section of hgConfCatalog.py; classify it and move it out
- lines changed 28, context: html, text, full: html, text
517996ce766d0a844b5736dc3864db2243e22577 Sat Sep 19 07:17:31 2026 -0700
hgConfCatalog: sessionLoadNotice is a mirror knob, refs #37925
--auto-register wrote the row down on 2026-09-19; this classifies it and moves
it out of Awaiting review. The flag is read with cfgOptionBooleanDefault at
hg/hgTracks/hgTracks.c and decides whether hgTracks shows the note that names
the session just opened and says the configuration the user had before is gone.
It was born TRUE at 3bcf86a0995 and is documented in product/ex.hg.conf as an
off switch, so it never held the feature back, and the off position is for a
site whose users open sessions constantly and do not need telling.
Filed with debatable= rather than quietly: a site-wide off switch born in the
same commit as a user-visible change has the shape of a gate, and if the note
turns out to be uncontroversial the switch should be deleted rather than kept.
- lines changed 8, context: html, text, full: html, text
e7b649e254779c18430f815e205f504c537d66c8 Sun Sep 20 02:31:07 2026 -0700
hgConfCatalog: register denseClick, refs #37925
Written by nightlyRegister.sh, which records the settings the tree
reads that the catalog was missing. Only facts copied off the call
site are filled in. No classification is guessed: a new boolean gets no
role=, because calling a release gate a knob would hide it from the
sunset report for good, and every row lands in the 'Awaiting review'
section until somebody reads the call site.
denseClick hg/hgTracks/simpleTracks.c:5934 (38364)
wrote 1 row to the 'Awaiting review' section of hgConfCatalog.py; classify it and move it out
- src/hg/utils/perfNightly/README.txt
- lines changed 173, context: html, text, full: html, text
cd41fd4fa0efadea0cd412d1a39e9479f3aa9832 Tue Sep 15 14:45:24 2026 -0700
A nightly start-up and pixel check for hgTracks, refs #37547
Two builds of hgTracks, one machine, one moment: how long each takes to
start up and draw, and whether they draw the same pixels. Eight cells --
native and GenArk, few tracks and many, narrow and wide.
compare.sh is the engine and takes any two builds, so the same test that
runs nightly against master also answers "is this branch slower than
genome-test, and does it still draw the same thing?" A build is just a
directory holding hgTracks and hgRenderTracks, which `make compile` in
hg/hgTracks produces without installing anything.
nightly.sh is the cron wrapper, in the same shape as the Docent
regression nightly: its own clone, --update resets it to origin/master,
a mail every night whether or not anything failed, sixty days of logs,
always exit 0. Its baseline is a rolling reference binary from the last
green night rather than a golden image, because two binaries reading the
same data at the same moment cannot disagree about pixels for a data
reason -- ClinVar, GENCODE and the GenArk hubs all move underneath a
saved render.
Five things here were measured rather than assumed, and each one
silently produces a wrong answer if it is left out. README.txt has them
with the numbers; the short version:
- TRACKDB_VERSION is baked into each trackDb cache dump's filename, so
a build that bumped it starts with an empty cache and pays a full
parse per cell. Each side gets its own cache dir and a per-cell
warmup, or a one-time cost reads as a permanent regression.
- Replaying a saved session's variables as a GET does not reproduce
the session: composite _sel state and the default-visibility pass
live in hgSession's load path. Against a 71-track session a flat
replay drew 23 of them and invented four more. The fixtures are
loaded with hgS_doLoadUrl instead.
- Running the binaries directly needs an htdocs symlink beside trash,
or freetype cannot find its font and every render dies.
- Always running side A first is worth 4.5% to side B, from the caches
A just warmed. The order alternates.
- trackLog names every track hgTracks loaded, not the drawn rows -- a
default hg38 view logs 563 and draws 21. Both are checked.
Cold and warm carts are reported separately and deliberately. A
one-shot render gives every request a fresh cart, so it measures only
the first load; on #37547 that reported the branch slower while a
persistent cart showed it faster, on the same binaries.
Nothing is wired into the tree-wide build, for the same reason the
Docent tests are not: these drive a real server and need the network.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
- src/hg/utils/perfNightly/compare.sh
- lines changed 374, context: html, text, full: html, text
cd41fd4fa0efadea0cd412d1a39e9479f3aa9832 Tue Sep 15 14:45:24 2026 -0700
A nightly start-up and pixel check for hgTracks, refs #37547
Two builds of hgTracks, one machine, one moment: how long each takes to
start up and draw, and whether they draw the same pixels. Eight cells --
native and GenArk, few tracks and many, narrow and wide.
compare.sh is the engine and takes any two builds, so the same test that
runs nightly against master also answers "is this branch slower than
genome-test, and does it still draw the same thing?" A build is just a
directory holding hgTracks and hgRenderTracks, which `make compile` in
hg/hgTracks produces without installing anything.
nightly.sh is the cron wrapper, in the same shape as the Docent
regression nightly: its own clone, --update resets it to origin/master,
a mail every night whether or not anything failed, sixty days of logs,
always exit 0. Its baseline is a rolling reference binary from the last
green night rather than a golden image, because two binaries reading the
same data at the same moment cannot disagree about pixels for a data
reason -- ClinVar, GENCODE and the GenArk hubs all move underneath a
saved render.
Five things here were measured rather than assumed, and each one
silently produces a wrong answer if it is left out. README.txt has them
with the numbers; the short version:
- TRACKDB_VERSION is baked into each trackDb cache dump's filename, so
a build that bumped it starts with an empty cache and pays a full
parse per cell. Each side gets its own cache dir and a per-cell
warmup, or a one-time cost reads as a permanent regression.
- Replaying a saved session's variables as a GET does not reproduce
the session: composite _sel state and the default-visibility pass
live in hgSession's load path. Against a 71-track session a flat
replay drew 23 of them and invented four more. The fixtures are
loaded with hgS_doLoadUrl instead.
- Running the binaries directly needs an htdocs symlink beside trash,
or freetype cannot find its font and every render dies.
- Always running side A first is worth 4.5% to side B, from the caches
A just warmed. The order alternates.
- trackLog names every track hgTracks loaded, not the drawn rows -- a
default hg38 view logs 563 and draws 21. Both are checked.
Cold and warm carts are reported separately and deliberately. A
one-shot render gives every request a fresh cart, so it measures only
the first load; on #37547 that reported the branch slower while a
persistent cart showed it faster, on the same binaries.
Nothing is wired into the tree-wide build, for the same reason the
Docent tests are not: these drive a real server and need the network.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
- src/hg/utils/perfNightly/nightly.sh
- lines changed 261, context: html, text, full: html, text
cd41fd4fa0efadea0cd412d1a39e9479f3aa9832 Tue Sep 15 14:45:24 2026 -0700
A nightly start-up and pixel check for hgTracks, refs #37547
Two builds of hgTracks, one machine, one moment: how long each takes to
start up and draw, and whether they draw the same pixels. Eight cells --
native and GenArk, few tracks and many, narrow and wide.
compare.sh is the engine and takes any two builds, so the same test that
runs nightly against master also answers "is this branch slower than
genome-test, and does it still draw the same thing?" A build is just a
directory holding hgTracks and hgRenderTracks, which `make compile` in
hg/hgTracks produces without installing anything.
nightly.sh is the cron wrapper, in the same shape as the Docent
regression nightly: its own clone, --update resets it to origin/master,
a mail every night whether or not anything failed, sixty days of logs,
always exit 0. Its baseline is a rolling reference binary from the last
green night rather than a golden image, because two binaries reading the
same data at the same moment cannot disagree about pixels for a data
reason -- ClinVar, GENCODE and the GenArk hubs all move underneath a
saved render.
Five things here were measured rather than assumed, and each one
silently produces a wrong answer if it is left out. README.txt has them
with the numbers; the short version:
- TRACKDB_VERSION is baked into each trackDb cache dump's filename, so
a build that bumped it starts with an empty cache and pays a full
parse per cell. Each side gets its own cache dir and a per-cell
warmup, or a one-time cost reads as a permanent regression.
- Replaying a saved session's variables as a GET does not reproduce
the session: composite _sel state and the default-visibility pass
live in hgSession's load path. Against a 71-track session a flat
replay drew 23 of them and invented four more. The fixtures are
loaded with hgS_doLoadUrl instead.
- Running the binaries directly needs an htdocs symlink beside trash,
or freetype cannot find its font and every render dies.
- Always running side A first is worth 4.5% to side B, from the caches
A just warmed. The order alternates.
- trackLog names every track hgTracks loaded, not the drawn rows -- a
default hg38 view logs 563 and draws 21. Both are checked.
Cold and warm carts are reported separately and deliberately. A
one-shot render gives every request a fresh cart, so it measures only
the first load; on #37547 that reported the branch slower while a
persistent cart showed it faster, on the same binaries.
Nothing is wired into the tree-wide build, for the same reason the
Docent tests are not: these drive a real server and need the network.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
- lines changed 1, context: html, text, full: html, text
3212c75cbe810013f1c3a0993934b0b70f6d7d2d Wed Sep 16 08:35:38 2026 -0700
perfNightly: build hg/cgilib and optimalLeaf too, refs #37547
The build step ran topLibs plus hg/lib, which leaves jkhgapcgi.a and
optimalLeaf.a alone. hgTracks links both (MYLIBS in hg/hgTracks/makefile)
and has no rule to build them, so make used whatever was already on disk.
A change under hg/cgilib or optimalLeaf would be pulled in by --update and
then silently not relinked into today's binary, which is exactly the kind
of regression this job exists to catch. 'make libs' is topLibs + hgLib +
optLib and covers all four archives.
- src/hg/utils/perfNightly/scenarios.tsv
- lines changed 30, context: html, text, full: html, text
cd41fd4fa0efadea0cd412d1a39e9479f3aa9832 Tue Sep 15 14:45:24 2026 -0700
A nightly start-up and pixel check for hgTracks, refs #37547
Two builds of hgTracks, one machine, one moment: how long each takes to
start up and draw, and whether they draw the same pixels. Eight cells --
native and GenArk, few tracks and many, narrow and wide.
compare.sh is the engine and takes any two builds, so the same test that
runs nightly against master also answers "is this branch slower than
genome-test, and does it still draw the same thing?" A build is just a
directory holding hgTracks and hgRenderTracks, which `make compile` in
hg/hgTracks produces without installing anything.
nightly.sh is the cron wrapper, in the same shape as the Docent
regression nightly: its own clone, --update resets it to origin/master,
a mail every night whether or not anything failed, sixty days of logs,
always exit 0. Its baseline is a rolling reference binary from the last
green night rather than a golden image, because two binaries reading the
same data at the same moment cannot disagree about pixels for a data
reason -- ClinVar, GENCODE and the GenArk hubs all move underneath a
saved render.
Five things here were measured rather than assumed, and each one
silently produces a wrong answer if it is left out. README.txt has them
with the numbers; the short version:
- TRACKDB_VERSION is baked into each trackDb cache dump's filename, so
a build that bumped it starts with an empty cache and pays a full
parse per cell. Each side gets its own cache dir and a per-cell
warmup, or a one-time cost reads as a permanent regression.
- Replaying a saved session's variables as a GET does not reproduce
the session: composite _sel state and the default-visibility pass
live in hgSession's load path. Against a 71-track session a flat
replay drew 23 of them and invented four more. The fixtures are
loaded with hgS_doLoadUrl instead.
- Running the binaries directly needs an htdocs symlink beside trash,
or freetype cannot find its font and every render dies.
- Always running side A first is worth 4.5% to side B, from the caches
A just warmed. The order alternates.
- trackLog names every track hgTracks loaded, not the drawn rows -- a
default hg38 view logs 563 and draws 21. Both are checked.
Cold and warm carts are reported separately and deliberately. A
one-shot render gives every request a fresh cart, so it measures only
the first load; on #37547 that reported the branch slower while a
persistent cart showed it faster, on the same binaries.
Nothing is wired into the tree-wide build, for the same reason the
Docent tests are not: these drive a real server and need the network.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
- src/hg/utils/perfNightly/sessions/hg38-clinical.session
- lines changed 754, context: html, text, full: html, text
cd41fd4fa0efadea0cd412d1a39e9479f3aa9832 Tue Sep 15 14:45:24 2026 -0700
A nightly start-up and pixel check for hgTracks, refs #37547
Two builds of hgTracks, one machine, one moment: how long each takes to
start up and draw, and whether they draw the same pixels. Eight cells --
native and GenArk, few tracks and many, narrow and wide.
compare.sh is the engine and takes any two builds, so the same test that
runs nightly against master also answers "is this branch slower than
genome-test, and does it still draw the same thing?" A build is just a
directory holding hgTracks and hgRenderTracks, which `make compile` in
hg/hgTracks produces without installing anything.
nightly.sh is the cron wrapper, in the same shape as the Docent
regression nightly: its own clone, --update resets it to origin/master,
a mail every night whether or not anything failed, sixty days of logs,
always exit 0. Its baseline is a rolling reference binary from the last
green night rather than a golden image, because two binaries reading the
same data at the same moment cannot disagree about pixels for a data
reason -- ClinVar, GENCODE and the GenArk hubs all move underneath a
saved render.
Five things here were measured rather than assumed, and each one
silently produces a wrong answer if it is left out. README.txt has them
with the numbers; the short version:
- TRACKDB_VERSION is baked into each trackDb cache dump's filename, so
a build that bumped it starts with an empty cache and pays a full
parse per cell. Each side gets its own cache dir and a per-cell
warmup, or a one-time cost reads as a permanent regression.
- Replaying a saved session's variables as a GET does not reproduce
the session: composite _sel state and the default-visibility pass
live in hgSession's load path. Against a 71-track session a flat
replay drew 23 of them and invented four more. The fixtures are
loaded with hgS_doLoadUrl instead.
- Running the binaries directly needs an htdocs symlink beside trash,
or freetype cannot find its font and every render dies.
- Always running side A first is worth 4.5% to side B, from the caches
A just warmed. The order alternates.
- trackLog names every track hgTracks loaded, not the drawn rows -- a
default hg38 view logs 563 and draws 21. Both are checked.
Cold and warm carts are reported separately and deliberately. A
one-shot render gives every request a fresh cart, so it measures only
the first load; on #37547 that reported the branch slower while a
persistent cart showed it faster, on the same binaries.
Nothing is wired into the tree-wide build, for the same reason the
Docent tests are not: these drive a real server and need the network.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
- src/hg/utils/urlCommandCatalog/urlCommandCatalog.py
- lines changed 18, context: html, text, full: html, text
1eaa67ff615dc87804cf22eac3d198ca522d5f97 Fri Sep 18 08:39:39 2026 -0700
urlCommandCatalog: baseline hgLogin's three activation-mail names, and cite a call site the same way every time, refs #37923
hgLogin_actMailProvider, hgLogin_actMailTo and hgLogin_actMailUser are written
by the server and read back a few lines later. dropRequestSuppliedFlowVars()
lists all three, so a copy arriving with the request is dropped before anything
reads it, and none of them can be a browser URL parameter. They belong in the
baseline beside oauth_pending_* and emailLogin_*, which are the same class.
The citation on each baseline line was picked with setdefault over the harvest,
so for a name read in several files it followed the order of the walk and moved
whenever the file was regenerated from a different checkout. That rewrote about
thirty unrelated lines and buried the name that changed. The pick is now the
lowest (path, line), preferring a site under the CGIs the file header tells a
reviewer to look at. Those thirty lines move once here and then stay put.
- lines changed 41, context: html, text, full: html, text
c2208fb9f91473fd3fa5d105d4a46523b374c303 Sat Sep 19 07:17:39 2026 -0700
urlCommandCatalog: catalog the two mirror session endpoints and the session-load marker, refs #37923
All three arrived on 2026-09-18 and the nightly found them.
hgS_doSessionListJson and hgS_doMirrorSessions are answered in main() before
cartNew, so a node asking another node for a session list makes no cart and no
userDb or sessionDb row. They carry nocart=True for that reason, and the rows
name their callers: hgSession.c:2628 builds the first URL when it fans out, and
hg/js/hgSession.js:769 calls the second.
hgS_sessionJustLoaded is described rather than baselined. It is written by
cartNew rather than typed, but it is an ordinary cart variable, so a request can
supply it, and supplying it replays the note. That is the mistake that was made
with hgS_shareAnon. A trackImgOnly render returns before the cartRemove, so the
marker survives an image-only request and is consumed by the next full page.
- src/hg/utils/urlCommandCatalog/urlNamesNotCataloged.txt
- lines changed 34, context: html, text, full: html, text
1eaa67ff615dc87804cf22eac3d198ca522d5f97 Fri Sep 18 08:39:39 2026 -0700
urlCommandCatalog: baseline hgLogin's three activation-mail names, and cite a call site the same way every time, refs #37923
hgLogin_actMailProvider, hgLogin_actMailTo and hgLogin_actMailUser are written
by the server and read back a few lines later. dropRequestSuppliedFlowVars()
lists all three, so a copy arriving with the request is dropped before anything
reads it, and none of them can be a browser URL parameter. They belong in the
baseline beside oauth_pending_* and emailLogin_*, which are the same class.
The citation on each baseline line was picked with setdefault over the harvest,
so for a name read in several files it followed the order of the walk and moved
whenever the file was regenerated from a different checkout. That rewrote about
thirty unrelated lines and buried the name that changed. The pick is now the
lowest (path, line), preferring a site under the CGIs the file header tells a
reviewer to look at. Those thirty lines move once here and then stay put.
- src/inc/srcVersion.h
- lines changed 1, context: html, text, full: html, text
74623f843857f2254e5327c78b98f00c3f7098ff Mon Sep 21 10:00:48 2026 -0700
New version number v504
- src/lib/tests/expected/hmacTest
- lines changed 12, context: html, text, full: html, text
c2e25edbf8c48361a71398664ec0c279d5fc58f5 Sat Sep 19 18:11:31 2026 -0700
hmacTest: pin the signature hgLogin puts on a pending social identity
hgLogin signs a pending social identity with hmacMd5(login.cookieSalt, fields)
and hands the signature to the browser in the account chooser, so a forgeable
signature lets an attacker choose whose account the chooser links to. Nothing
about the page looks different either way.
Before #37984 that signature was a plain MD5 of the salt concatenated in front
of the same fields, and a hash of a secret followed by attacker-chosen text is
the wrong shape for the job. boundaryMoves() is the case that says so: with
concatenation, hmacMd5("a", "bc") and hmacMd5("ab", "c") hash the same bytes
and sign the same, while HMAC keeps them apart.
Known answers are RFC 2202 test case 2 for MD5 and SHA1, cross-checked here
with the openssl command line. Only the string-keyed vectors from the RFC can
be used, since this interface takes key and data as C strings.
Watched to fail and then pass: putting hmacMd5 back to the concatenation shape
turns the known answer red and makes the two boundary cases identical, both of
which the test catches. Recorded as sandbox-ab in utils/testRegistry.
refs #37984, refs #38391
- src/lib/tests/hmacTest.c
- lines changed 134, context: html, text, full: html, text
c2e25edbf8c48361a71398664ec0c279d5fc58f5 Sat Sep 19 18:11:31 2026 -0700
hmacTest: pin the signature hgLogin puts on a pending social identity
hgLogin signs a pending social identity with hmacMd5(login.cookieSalt, fields)
and hands the signature to the browser in the account chooser, so a forgeable
signature lets an attacker choose whose account the chooser links to. Nothing
about the page looks different either way.
Before #37984 that signature was a plain MD5 of the salt concatenated in front
of the same fields, and a hash of a secret followed by attacker-chosen text is
the wrong shape for the job. boundaryMoves() is the case that says so: with
concatenation, hmacMd5("a", "bc") and hmacMd5("ab", "c") hash the same bytes
and sign the same, while HMAC keeps them apart.
Known answers are RFC 2202 test case 2 for MD5 and SHA1, cross-checked here
with the openssl command line. Only the string-keyed vectors from the RFC can
be used, since this interface takes key and data as C strings.
Watched to fail and then pass: putting hmacMd5 back to the concatenation shape
turns the known answer red and makes the two boundary cases identical, both of
which the test catches. Recorded as sandbox-ab in utils/testRegistry.
refs #37984, refs #38391
- src/lib/tests/makefile
- lines changed 9, context: html, text, full: html, text
c2e25edbf8c48361a71398664ec0c279d5fc58f5 Sat Sep 19 18:11:31 2026 -0700
hmacTest: pin the signature hgLogin puts on a pending social identity
hgLogin signs a pending social identity with hmacMd5(login.cookieSalt, fields)
and hands the signature to the browser in the account chooser, so a forgeable
signature lets an attacker choose whose account the chooser links to. Nothing
about the page looks different either way.
Before #37984 that signature was a plain MD5 of the salt concatenated in front
of the same fields, and a hash of a secret followed by attacker-chosen text is
the wrong shape for the job. boundaryMoves() is the case that says so: with
concatenation, hmacMd5("a", "bc") and hmacMd5("ab", "c") hash the same bytes
and sign the same, while HMAC keeps them apart.
Known answers are RFC 2202 test case 2 for MD5 and SHA1, cross-checked here
with the openssl command line. Only the string-keyed vectors from the RFC can
be used, since this interface takes key and data as C strings.
Watched to fail and then pass: putting hmacMd5 back to the concatenation shape
turns the known answer red and makes the two boundary cases identical, both of
which the test catches. Recorded as sandbox-ab in utils/testRegistry.
refs #37984, refs #38391
- src/utils/makefile
- lines changed 4, context: html, text, full: html, text
5011b739391b6a1b6129d473b6c050010baf1f6f Sat Sep 19 17:57:37 2026 -0700
testRegistry: a registry of which unit test defends which ticket
A bug ticket has no way to say whether a test now defends its fix, and a test
has no way to say which bug it came from. The two questions are asked from
opposite ends and neither the tree nor Redmine answers either one.
utils/testRegistry/registry.tsv is that table, hand written, one row per ticket
per test, starting at v504. Unit tests only: the browser-page regression tests
are the docent suite, refs #38252, which already names each script for its
ticket, and a docent column here says which ticket has one of those too.
Each row says why a unit test is the right test, because "the fix is in a
library file" is wrong in both directions. A wording fix in hg/lib needs no
unit test, and a performance rewrite inside hgTracks needs one badly, since
nothing else can tell that the slow path has come back. The three reasons are
invisible, perf and library, and a perf row says what has to be measured --
queries, passes, allocations, bytes -- never wall-clock seconds.
testRegistry reads it: ticket, test, release, why, needed, unwatched, tickets,
check. No network and no database, so the check can run anywhere.
check is why the table is checked in rather than derived. A registry that
quietly names files nobody has, saying a bug is covered when it is not, is
worse than no registry, so check fails the build the day a row rots. Its own
tests are in tests/, with one row of input/bad.tsv per complaint check can
make, and utils/makefile runs the whole thing so it reaches make test from src.
Today: 37 tickets, 12 covered by 11 tests, 25 waiting.
refs #38391
- src/utils/qa/weeklybld/README.dockerTodo
- lines changed 19, context: html, text, full: html, text
dbb8f6e006713f43b7dbd6100d3b5c024dc72766 Fri Sep 18 11:11:15 2026 -0700
weeklybld: let the docker instance scripts run a past release, refs #38377
We could not reproduce a bug against the release a user is actually on.
hgwdev runs tip and the current release, and nothing older. Docker Hub
already has a per-release image, so the missing piece was a way to run one.
The lifecycle scripts now take a release name as well as tip, beta and rel.
run-instance.sh v503 starts the published v503 image as container kent-v503
on port 8503; the port is 8000 plus the release number, so the mapping needs
no table and no allocator. A release instance gets no CGI overlay, for the
same reason rel gets none: it has to be the code that shipped.
refresh-instance.sh, remove-instance.sh and smoke-instance.sh take the same
name. smoke-instance.sh checks a release instance against the version in its
own name, so no --version flag is needed. start-all.sh and stop-all.sh now
read the release containers that exist rather than a fixed list, so the set
of releases we keep can change without editing them.
tunnel-release.sh is one script for every release rather than one per
release, since that set changes.
v499 through v503 are running on hgwdev on ports 8499 through 8503 and pass
smoke-instance.sh. Five instances cost about 1.5 GB of memory, 10 GB of
docker disk, and no measurable CPU. They read tables from
genome-mysql.soe.ucsc.edu and files from hgdownload.soe.ucsc.edu, so they
put no load on the hgwdev MySQL or /gbdb.
- src/utils/qa/weeklybld/buildEnv.csh
- lines changed 3, context: html, text, full: html, text
2be17664d5eab1f5aece82ccc0e4f7afd275f78d Mon Sep 21 10:00:44 2026 -0700
v504 final build (automated)
- src/utils/qa/weeklybld/doHgTablesTestRobot.csh
- lines changed 83, context: html, text, full: html, text
5a34a4caa476493be5efb117dff50073d5637e20 Wed Sep 16 12:40:05 2026 -0700
doHgTablesTestRobot: fail when a run dies instead of reporting success, refs #38356
This is the robot that runs at the final build, against hgwbeta. Its check
looked only for Total lines that carried errors. hgTablesTest writes that line
after a run finishes, so a run that died partway through wrote no Total line at
all, the match came back empty, and the robot mailed "done successfully". Every
log back to v490 is missing the summary line, so this gate had never once fired.
Give it the checks the preview2 robot already got in cf348a83d76: the exit
status of each of the two runs, a count of the Total lines against the number of
runs expected, the existing error-in-Total check, and a grep for crash
signatures over both the report log and a separate file holding the runs' own
output. A missing summary is now itself a failure, and the mail says which of
those conditions tripped.
Also a ROBOT_MAILTO override, so re-running the robot to diagnose something does
not notify the QA list every time.
Tested against a stub hgTablesTest and a stub mail, four ways. A clean run
still passes. A run reporting errors in its Total line still fails. A run that
dies partway, whether it exits nonzero or zero, used to pass and now fails.
- src/utils/qa/weeklybld/refresh-instance.sh
- lines changed 9, context: html, text, full: html, text
dbb8f6e006713f43b7dbd6100d3b5c024dc72766 Fri Sep 18 11:11:15 2026 -0700
weeklybld: let the docker instance scripts run a past release, refs #38377
We could not reproduce a bug against the release a user is actually on.
hgwdev runs tip and the current release, and nothing older. Docker Hub
already has a per-release image, so the missing piece was a way to run one.
The lifecycle scripts now take a release name as well as tip, beta and rel.
run-instance.sh v503 starts the published v503 image as container kent-v503
on port 8503; the port is 8000 plus the release number, so the mapping needs
no table and no allocator. A release instance gets no CGI overlay, for the
same reason rel gets none: it has to be the code that shipped.
refresh-instance.sh, remove-instance.sh and smoke-instance.sh take the same
name. smoke-instance.sh checks a release instance against the version in its
own name, so no --version flag is needed. start-all.sh and stop-all.sh now
read the release containers that exist rather than a fixed list, so the set
of releases we keep can change without editing them.
tunnel-release.sh is one script for every release rather than one per
release, since that set changes.
v499 through v503 are running on hgwdev on ports 8499 through 8503 and pass
smoke-instance.sh. Five instances cost about 1.5 GB of memory, 10 GB of
docker disk, and no measurable CPU. They read tables from
genome-mysql.soe.ucsc.edu and files from hgdownload.soe.ucsc.edu, so they
put no load on the hgwdev MySQL or /gbdb.
- src/utils/qa/weeklybld/remove-instance.sh
- lines changed 9, context: html, text, full: html, text
dbb8f6e006713f43b7dbd6100d3b5c024dc72766 Fri Sep 18 11:11:15 2026 -0700
weeklybld: let the docker instance scripts run a past release, refs #38377
We could not reproduce a bug against the release a user is actually on.
hgwdev runs tip and the current release, and nothing older. Docker Hub
already has a per-release image, so the missing piece was a way to run one.
The lifecycle scripts now take a release name as well as tip, beta and rel.
run-instance.sh v503 starts the published v503 image as container kent-v503
on port 8503; the port is 8000 plus the release number, so the mapping needs
no table and no allocator. A release instance gets no CGI overlay, for the
same reason rel gets none: it has to be the code that shipped.
refresh-instance.sh, remove-instance.sh and smoke-instance.sh take the same
name. smoke-instance.sh checks a release instance against the version in its
own name, so no --version flag is needed. start-all.sh and stop-all.sh now
read the release containers that exist rather than a fixed list, so the set
of releases we keep can change without editing them.
tunnel-release.sh is one script for every release rather than one per
release, since that set changes.
v499 through v503 are running on hgwdev on ports 8499 through 8503 and pass
smoke-instance.sh. Five instances cost about 1.5 GB of memory, 10 GB of
docker disk, and no measurable CPU. They read tables from
genome-mysql.soe.ucsc.edu and files from hgdownload.soe.ucsc.edu, so they
put no load on the hgwdev MySQL or /gbdb.
- src/utils/qa/weeklybld/run-instance.sh
- lines changed 20, context: html, text, full: html, text
dbb8f6e006713f43b7dbd6100d3b5c024dc72766 Fri Sep 18 11:11:15 2026 -0700
weeklybld: let the docker instance scripts run a past release, refs #38377
We could not reproduce a bug against the release a user is actually on.
hgwdev runs tip and the current release, and nothing older. Docker Hub
already has a per-release image, so the missing piece was a way to run one.
The lifecycle scripts now take a release name as well as tip, beta and rel.
run-instance.sh v503 starts the published v503 image as container kent-v503
on port 8503; the port is 8000 plus the release number, so the mapping needs
no table and no allocator. A release instance gets no CGI overlay, for the
same reason rel gets none: it has to be the code that shipped.
refresh-instance.sh, remove-instance.sh and smoke-instance.sh take the same
name. smoke-instance.sh checks a release instance against the version in its
own name, so no --version flag is needed. start-all.sh and stop-all.sh now
read the release containers that exist rather than a fixed list, so the set
of releases we keep can change without editing them.
tunnel-release.sh is one script for every release rather than one per
release, since that set changes.
v499 through v503 are running on hgwdev on ports 8499 through 8503 and pass
smoke-instance.sh. Five instances cost about 1.5 GB of memory, 10 GB of
docker disk, and no measurable CPU. They read tables from
genome-mysql.soe.ucsc.edu and files from hgdownload.soe.ucsc.edu, so they
put no load on the hgwdev MySQL or /gbdb.
- src/utils/qa/weeklybld/smoke-instance.sh
- lines changed 15, context: html, text, full: html, text
dbb8f6e006713f43b7dbd6100d3b5c024dc72766 Fri Sep 18 11:11:15 2026 -0700
weeklybld: let the docker instance scripts run a past release, refs #38377
We could not reproduce a bug against the release a user is actually on.
hgwdev runs tip and the current release, and nothing older. Docker Hub
already has a per-release image, so the missing piece was a way to run one.
The lifecycle scripts now take a release name as well as tip, beta and rel.
run-instance.sh v503 starts the published v503 image as container kent-v503
on port 8503; the port is 8000 plus the release number, so the mapping needs
no table and no allocator. A release instance gets no CGI overlay, for the
same reason rel gets none: it has to be the code that shipped.
refresh-instance.sh, remove-instance.sh and smoke-instance.sh take the same
name. smoke-instance.sh checks a release instance against the version in its
own name, so no --version flag is needed. start-all.sh and stop-all.sh now
read the release containers that exist rather than a fixed list, so the set
of releases we keep can change without editing them.
tunnel-release.sh is one script for every release rather than one per
release, since that set changes.
v499 through v503 are running on hgwdev on ports 8499 through 8503 and pass
smoke-instance.sh. Five instances cost about 1.5 GB of memory, 10 GB of
docker disk, and no measurable CPU. They read tables from
genome-mysql.soe.ucsc.edu and files from hgdownload.soe.ucsc.edu, so they
put no load on the hgwdev MySQL or /gbdb.
- src/utils/qa/weeklybld/start-all.sh
- lines changed 12, context: html, text, full: html, text
dbb8f6e006713f43b7dbd6100d3b5c024dc72766 Fri Sep 18 11:11:15 2026 -0700
weeklybld: let the docker instance scripts run a past release, refs #38377
We could not reproduce a bug against the release a user is actually on.
hgwdev runs tip and the current release, and nothing older. Docker Hub
already has a per-release image, so the missing piece was a way to run one.
The lifecycle scripts now take a release name as well as tip, beta and rel.
run-instance.sh v503 starts the published v503 image as container kent-v503
on port 8503; the port is 8000 plus the release number, so the mapping needs
no table and no allocator. A release instance gets no CGI overlay, for the
same reason rel gets none: it has to be the code that shipped.
refresh-instance.sh, remove-instance.sh and smoke-instance.sh take the same
name. smoke-instance.sh checks a release instance against the version in its
own name, so no --version flag is needed. start-all.sh and stop-all.sh now
read the release containers that exist rather than a fixed list, so the set
of releases we keep can change without editing them.
tunnel-release.sh is one script for every release rather than one per
release, since that set changes.
v499 through v503 are running on hgwdev on ports 8499 through 8503 and pass
smoke-instance.sh. Five instances cost about 1.5 GB of memory, 10 GB of
docker disk, and no measurable CPU. They read tables from
genome-mysql.soe.ucsc.edu and files from hgdownload.soe.ucsc.edu, so they
put no load on the hgwdev MySQL or /gbdb.
- src/utils/qa/weeklybld/stop-all.sh
- lines changed 10, context: html, text, full: html, text
dbb8f6e006713f43b7dbd6100d3b5c024dc72766 Fri Sep 18 11:11:15 2026 -0700
weeklybld: let the docker instance scripts run a past release, refs #38377
We could not reproduce a bug against the release a user is actually on.
hgwdev runs tip and the current release, and nothing older. Docker Hub
already has a per-release image, so the missing piece was a way to run one.
The lifecycle scripts now take a release name as well as tip, beta and rel.
run-instance.sh v503 starts the published v503 image as container kent-v503
on port 8503; the port is 8000 plus the release number, so the mapping needs
no table and no allocator. A release instance gets no CGI overlay, for the
same reason rel gets none: it has to be the code that shipped.
refresh-instance.sh, remove-instance.sh and smoke-instance.sh take the same
name. smoke-instance.sh checks a release instance against the version in its
own name, so no --version flag is needed. start-all.sh and stop-all.sh now
read the release containers that exist rather than a fixed list, so the set
of releases we keep can change without editing them.
tunnel-release.sh is one script for every release rather than one per
release, since that set changes.
v499 through v503 are running on hgwdev on ports 8499 through 8503 and pass
smoke-instance.sh. Five instances cost about 1.5 GB of memory, 10 GB of
docker disk, and no measurable CPU. They read tables from
genome-mysql.soe.ucsc.edu and files from hgdownload.soe.ucsc.edu, so they
put no load on the hgwdev MySQL or /gbdb.
- src/utils/qa/weeklybld/tunnel-release.sh
- lines changed 43, context: html, text, full: html, text
dbb8f6e006713f43b7dbd6100d3b5c024dc72766 Fri Sep 18 11:11:15 2026 -0700
weeklybld: let the docker instance scripts run a past release, refs #38377
We could not reproduce a bug against the release a user is actually on.
hgwdev runs tip and the current release, and nothing older. Docker Hub
already has a per-release image, so the missing piece was a way to run one.
The lifecycle scripts now take a release name as well as tip, beta and rel.
run-instance.sh v503 starts the published v503 image as container kent-v503
on port 8503; the port is 8000 plus the release number, so the mapping needs
no table and no allocator. A release instance gets no CGI overlay, for the
same reason rel gets none: it has to be the code that shipped.
refresh-instance.sh, remove-instance.sh and smoke-instance.sh take the same
name. smoke-instance.sh checks a release instance against the version in its
own name, so no --version flag is needed. start-all.sh and stop-all.sh now
read the release containers that exist rather than a fixed list, so the set
of releases we keep can change without editing them.
tunnel-release.sh is one script for every release rather than one per
release, since that set changes.
v499 through v503 are running on hgwdev on ports 8499 through 8503 and pass
smoke-instance.sh. Five instances cost about 1.5 GB of memory, 10 GB of
docker disk, and no measurable CPU. They read tables from
genome-mysql.soe.ucsc.edu and files from hgdownload.soe.ucsc.edu, so they
put no load on the hgwdev MySQL or /gbdb.
- src/utils/testRegistry/README
- lines changed 120, context: html, text, full: html, text
5011b739391b6a1b6129d473b6c050010baf1f6f Sat Sep 19 17:57:37 2026 -0700
testRegistry: a registry of which unit test defends which ticket
A bug ticket has no way to say whether a test now defends its fix, and a test
has no way to say which bug it came from. The two questions are asked from
opposite ends and neither the tree nor Redmine answers either one.
utils/testRegistry/registry.tsv is that table, hand written, one row per ticket
per test, starting at v504. Unit tests only: the browser-page regression tests
are the docent suite, refs #38252, which already names each script for its
ticket, and a docent column here says which ticket has one of those too.
Each row says why a unit test is the right test, because "the fix is in a
library file" is wrong in both directions. A wording fix in hg/lib needs no
unit test, and a performance rewrite inside hgTracks needs one badly, since
nothing else can tell that the slow path has come back. The three reasons are
invisible, perf and library, and a perf row says what has to be measured --
queries, passes, allocations, bytes -- never wall-clock seconds.
testRegistry reads it: ticket, test, release, why, needed, unwatched, tickets,
check. No network and no database, so the check can run anywhere.
check is why the table is checked in rather than derived. A registry that
quietly names files nobody has, saying a bug is covered when it is not, is
worse than no registry, so check fails the build the day a row rots. Its own
tests are in tests/, with one row of input/bad.tsv per complaint check can
make, and utils/makefile runs the whole thing so it reaches make test from src.
Today: 37 tickets, 12 covered by 11 tests, 25 waiting.
refs #38391
- lines changed 8, context: html, text, full: html, text
eccdddfb22cf35d4e5698f72a4b12707aa43b349 Sun Sep 20 14:27:27 2026 -0700
testRegistry: check the docent column's "-" as well as its names
The docent column says which browser test watches the same ticket, and a named
script was already checked: it has to exist and has to belong to that ticket.
A "-" was checked by nothing, and that was the wrong half to leave out.
`unwatched` -- the list of tickets where nothing anywhere would go red if the
bug came back -- is built entirely out of those "-" values. They were entered
by hand, by reading the docent directory once, so a script written the next day
left the ticket sitting on that queue with nothing to notice. For the four
tickets that are on it because their code lives inside a CGI, somebody writing
the docent script is the expected outcome, which made it the likeliest kind of
row to go stale.
So a row claiming no docent script is now checked against the tree the same way
a named one is: if rm<ticket>.*docent.yaml turns up, the check fails and asks
for the row to be filled in. The failure is somebody doing the right thing and
the table not having heard about it.
Watched to fail and then pass: blanking the docent column of #36212, whose
script is in the tree, turns the real table red with the name of the script it
found.
refs #38391
- src/utils/testRegistry/makefile
- lines changed 15, context: html, text, full: html, text
5011b739391b6a1b6129d473b6c050010baf1f6f Sat Sep 19 17:57:37 2026 -0700
testRegistry: a registry of which unit test defends which ticket
A bug ticket has no way to say whether a test now defends its fix, and a test
has no way to say which bug it came from. The two questions are asked from
opposite ends and neither the tree nor Redmine answers either one.
utils/testRegistry/registry.tsv is that table, hand written, one row per ticket
per test, starting at v504. Unit tests only: the browser-page regression tests
are the docent suite, refs #38252, which already names each script for its
ticket, and a docent column here says which ticket has one of those too.
Each row says why a unit test is the right test, because "the fix is in a
library file" is wrong in both directions. A wording fix in hg/lib needs no
unit test, and a performance rewrite inside hgTracks needs one badly, since
nothing else can tell that the slow path has come back. The three reasons are
invisible, perf and library, and a perf row says what has to be measured --
queries, passes, allocations, bytes -- never wall-clock seconds.
testRegistry reads it: ticket, test, release, why, needed, unwatched, tickets,
check. No network and no database, so the check can run anywhere.
check is why the table is checked in rather than derived. A registry that
quietly names files nobody has, saying a bug is covered when it is not, is
worse than no registry, so check fails the build the day a row rots. Its own
tests are in tests/, with one row of input/bad.tsv per complaint check can
make, and utils/makefile runs the whole thing so it reaches make test from src.
Today: 37 tickets, 12 covered by 11 tests, 25 waiting.
refs #38391
- src/utils/testRegistry/registry.tsv
- lines changed 89, context: html, text, full: html, text
5011b739391b6a1b6129d473b6c050010baf1f6f Sat Sep 19 17:57:37 2026 -0700
testRegistry: a registry of which unit test defends which ticket
A bug ticket has no way to say whether a test now defends its fix, and a test
has no way to say which bug it came from. The two questions are asked from
opposite ends and neither the tree nor Redmine answers either one.
utils/testRegistry/registry.tsv is that table, hand written, one row per ticket
per test, starting at v504. Unit tests only: the browser-page regression tests
are the docent suite, refs #38252, which already names each script for its
ticket, and a docent column here says which ticket has one of those too.
Each row says why a unit test is the right test, because "the fix is in a
library file" is wrong in both directions. A wording fix in hg/lib needs no
unit test, and a performance rewrite inside hgTracks needs one badly, since
nothing else can tell that the slow path has come back. The three reasons are
invisible, perf and library, and a perf row says what has to be measured --
queries, passes, allocations, bytes -- never wall-clock seconds.
testRegistry reads it: ticket, test, release, why, needed, unwatched, tickets,
check. No network and no database, so the check can run anywhere.
check is why the table is checked in rather than derived. A registry that
quietly names files nobody has, saying a bug is covered when it is not, is
worse than no registry, so check fails the build the day a row rots. Its own
tests are in tests/, with one row of input/bad.tsv per complaint check can
make, and utils/makefile runs the whole thing so it reaches make test from src.
Today: 37 tickets, 12 covered by 11 tests, 25 waiting.
refs #38391
- lines changed 1, context: html, text, full: html, text
c2e25edbf8c48361a71398664ec0c279d5fc58f5 Sat Sep 19 18:11:31 2026 -0700
hmacTest: pin the signature hgLogin puts on a pending social identity
hgLogin signs a pending social identity with hmacMd5(login.cookieSalt, fields)
and hands the signature to the browser in the account chooser, so a forgeable
signature lets an attacker choose whose account the chooser links to. Nothing
about the page looks different either way.
Before #37984 that signature was a plain MD5 of the salt concatenated in front
of the same fields, and a hash of a secret followed by attacker-chosen text is
the wrong shape for the job. boundaryMoves() is the case that says so: with
concatenation, hmacMd5("a", "bc") and hmacMd5("ab", "c") hash the same bytes
and sign the same, while HMAC keeps them apart.
Known answers are RFC 2202 test case 2 for MD5 and SHA1, cross-checked here
with the openssl command line. Only the string-keyed vectors from the RFC can
be used, since this interface takes key and data as C strings.
Watched to fail and then pass: putting hmacMd5 back to the concatenation shape
turns the known answer red and makes the two boundary cases identical, both of
which the test catches. Recorded as sandbox-ab in utils/testRegistry.
refs #37984, refs #38391
- lines changed 1, context: html, text, full: html, text
859bc749b0593a83e1c8cd7149f956b620a24a73 Sat Sep 19 18:14:15 2026 -0700
trashDirTester: pin which file paths the cart accepts
hg/lib/cart.c screens every cart variable that names a server-made file through
these functions, so they decide whether a saved session still works. Both ways
of being wrong are invisible: a path wrongly refused brings the session back
without its custom track or its region list and says nothing, and a path
wrongly accepted says nothing either.
That is what #38303 cost. A check shipped in v503 discarded the saved region
list from 583 sessions on the RR and 66 on euro, and hgwdev, code review and
hgwbeta were all clean, because the corpus that shows it is only on the
production central.
Four rules pinned, each of which cost a bug or a review round: only the
configured directory is symlink-resolved and never the path from the cart; the
resolved spelling of that directory is accepted as well as the configured one,
since /userdata on the RR is a symlink and saved sessions hold both spellings;
only an absolute directory is resolved, because a relative one would be
resolved against the caller's working directory; and the acceptance runs one
direction only. pathIsUnderDir's own edges are here too, including the sibling
directory that merely starts the same way and the name that begins with "..".
The fixture is a directory, a symlink to it and three confs naming the same
place three ways, since hgConfig caches what it read and one process can only
answer for one spelling. Nothing machine-specific reaches the output.
Watched to fail and then pass: with the pre-#38303 code, which did not resolve
at all, the resolved spelling comes back refused and the diff is that one line.
Recorded as sandbox-ab in utils/testRegistry.
refs #38303, refs #37623, refs #38391
- lines changed 1, context: html, text, full: html, text
a5d42e58d7f8ce1e985cf7422145619122ca5d25 Sat Sep 19 18:16:16 2026 -0700
mallocTopPadTester: check the heap step setting still reaches the library
cfgSetMallocTopPad() asks glibc to grow the heap in steps of mallocTopPad bytes
instead of its 128 kB default, which saves a heavy hgTracks render more than a
hundred thousand system calls that draw nothing.
The failure to catch is backsliding: the mallopt call is dropped in a later
edit, or the setting is renamed, or it stops being read before the first
allocation. Every page still draws correctly and the only symptom is that
renders are slower than they used to be, which nobody attributes to this.
So the test measures the step, not the clock. A timing test here would be red
on a busy hgwdev, green on an idle one, and deleted within a month. sbrk(0)
says where the heap ends and the distance it jumps when malloc extends it is
what M_TOP_PAD sets, so the answer is the same on a loaded machine as an idle
one. It is read in buckets, since glibc may round and may change what it
rounds to; what must not change is the order of magnitude between a configured
step and the default. Allocations stay under the mmap threshold, or the break
never moves and the test measures nothing while appearing to pass.
Two runs, with the setting and without, because the answer is the difference
between them: a single run would pass on a library whose own default happened
to be large.
Watched to fail and then pass: leaving the knob read but never applied gives
the default step under both confs, which is the one line the diff shows.
Recorded as sandbox-ab in utils/testRegistry.
refs #38225, refs #38391
- lines changed 1, context: html, text, full: html, text
a0a3411bca2fdd6d704ce2be7c9c8fca7682913a Sat Sep 19 18:19:36 2026 -0700
bedItemRgbTester: pin the order of the itemRgb and color tests
bedItemRgb() decides whether a BED track draws its items in the colors its file
carries or in the one color its stanza names. The rule has four steps, and the
order of the first three is the whole of #36212: an explicit "itemRgb off"
wins, then an explicit "itemRgb on" wins, and only then does the presence of a
"color" setting turn item colors off by default. 88d620e6c82 folded those
tests together, so a stanza saying both "itemRgb on" and "color" -- which means
items from the file and labels from color -- lost its item colors.
The pairs are what matter here. Every single-setting case passed while the bug
was live, so a test that exercised one setting at a time would have proved
nothing. A child that says "itemRgb on" under a parent that says "color" is
the same case reached through trackDbSettingClosestToHome.
Two runs, with and without hg.conf's alwaysItemRgb, since the last step of the
rule reads it and a mirror that turns it off must still honour a stanza that
asks for item colors explicitly.
The test lives in hg/lib/tests because hg/cgilib has no tests directory; its
link line adds jkhgapcgi.a.
Watched to fail and then pass: with the color test moved back in front of the
itemRgb test, three lines flip, and they are the three that pair the two
settings. Recorded as sandbox-ab in utils/testRegistry.
refs #36212, refs #38391
- lines changed 1, context: html, text, full: html, text
d898b4820087cccd79e240153bc310856bb89310 Sat Sep 19 18:22:49 2026 -0700
hVarSubstHtmlTester: pin which variables a description page may use
A native description page has been through hgTrackDb already, which resolved
everything it could and deferred only ${hgsid}, so the render pass acts on that
one variable and only in braces: hgTrackDb collapses an escaped $$hgsid to a
literal $hgsid, and acting on the bare form here would expand the very thing
the author escaped.
A hub's page has never been substituted, so the whole hub list is resolved at
render time, and $hgsid is deliberately not on that list. A hub page is only
lightly sanitized -- an <img> with an http src survives -- so a page carrying
<img src="https://example.com/px?s=${hgsid}"> would hand the reader's session
id to the hub's own server, and a session id alone is enough to read and write
that cart. The page renders the same either way and the request goes to
somebody else's host, so nothing about this is visible here.
The test builds a cart by hand rather than opening one. That is not a
shortcut, it is the point: a cartless version of this test was written first,
and adding hgsid back to hubHtmlVars changed not one line of its output,
because the check that recognises a variable also asks whether this call can
resolve it, and with no cart it cannot. cartSessionId reads two fields, so a
struct built in the test is enough and no database is involved.
Watched to fail and then pass: with hgsid back on the hub list, both hub cases
come back with the session id substituted into the img src. Recorded as
sandbox-ab in utils/testRegistry.
refs #38283, refs #38391
- lines changed 1, context: html, text, full: html, text
471b82ec87d4b23b03ec3f3a2a193eb1f88a035c Sat Sep 19 18:24:53 2026 -0700
dataVersionPathTester: pin which local files a hub's dataVersion may read
A track's dataVersion setting is usually a version string, but for otto tracks
it is the path of a local file that hgTrackUi opens and prints. On a hub track
that setting is an instruction from a stranger to read a named file on our
server and put it on the page.
#38268 narrowed it to /gbdb, which is public data mirrored on hgdownload, and
to a plain path, since a ".." component makes the name mean something outside
that tree. The exception is needed: curated-hub assemblies are served as hubs,
so hs1's otto tracks are hub tracks, and a quickLifted track's version file
lives on the source assembly.
Nothing about the failure is visible in the usual way. A refused path and an
accepted one both leave a page that looks reasonable, and the difference shows
only as somebody else's file appearing where a version number belongs.
The test prints a classification and never a file. The three outcomes separate
without looking at any contents: a refused path comes back as the path itself,
an accepted path that does not exist comes back NULL, and an accepted path that
exists comes back as something else.
Watched to fail and then pass: with the /gbdb test dropped, /etc/passwd comes
back read rather than refused, and the two climbing cases come back opened.
Recorded as sandbox-ab in utils/testRegistry.
refs #38268, refs #38391
- lines changed 1, context: html, text, full: html, text
d58bf9a182cbf4dba142a7028742abf688638829 Sat Sep 19 18:27:02 2026 -0700
genarkLiftOverTester: pin the escaping of the GenArk accession list
Before #38328 the caller pasted its accessions into one string and
genarkLiftOverDbs dropped that string into a query marked NOSQLINJ, which is a
promise that somebody upstream had made it safe. It now takes an slName list
and builds the query itself with sqlDyStringPrintf, so the escaping happens
where the values are, and a name that is not a GC accession never reaches the
database.
Nothing about this is visible. Correct and incorrect escaping give the same
page for every input a browser sends, because the accessions come from our own
chain files. The difference appears only for a value chosen to break out,
which is the value that never turns up in ordinary testing.
The genark table is data and it moves, so the test reads an accession out of it
and asks whether the function returns that one, rather than naming an assembly
that may be dropped later.
Watched to fail and then pass: with the value pasted in unescaped the run dies
instead of coming back with nothing, so the quoted cases turn the test red
rather than quietly querying something else. Recorded as sandbox-ab in
utils/testRegistry.
refs #38328, refs #38391
- lines changed 1, context: html, text, full: html, text
89f9ce7bc7c9333c45190074088f5bee377ca1d7 Sat Sep 19 18:30:26 2026 -0700
snapshotTypeTester: check the fast snapshotType reader against raFromString
A saved session is a snapshot when its settings carry a snapshotType line, and
the My Sessions listings hide those rows. #38313 replaced raFromString with a
walk over the lines, because the question is asked once per row in a listing
and the hash costs about 600ns and three allocations per session against about
30ns and none.
A hand written parser that has to agree with a general one is the shape of bug
found a year later, so this is a differential test: every case is read both
ways and the two answers are printed side by side. The claim in the code is
"same line semantics as raFromString", and that claim is what is checked rather
than a list of answers written down once. Reading the tag wrongly is invisible
either way: a snapshot is listed as an ordinary session, or an ordinary session
disappears from the listing, and both look like something the user did.
One case does not agree, and it is recorded rather than hidden. Given two
snapshotType lines the walk returns the first and raFromString returns the
last, because a hash overwrites. Real settings carry the tag once, so nothing
depends on it today, but it is a difference in the semantics the code says it
copies. It is marked as a known difference, and the test also fails if it ever
starts agreeing, so the note cannot go stale in the other direction.
Watched to fail and then pass: dropping the delimiter test after the tag makes
"snapshotTypeExtra view" read as the type "Extra view" while raFromString finds
none. Recorded as sandbox-ab in utils/testRegistry.
refs #38313, refs #38391
- lines changed 1, context: html, text, full: html, text
751a1f9fff1d6d77c2da690d1369dca64ba04fee Sat Sep 19 18:31:42 2026 -0700
sessionDirTester: pin how a saved session's data directory is named
A saved session's custom tracks and region files are moved to a durable
directory named from the user name and the session name. #10138 widened the
session half of that name from 8 hex characters to 10: 8 characters of md5 is
4 billion values, and the birthday arithmetic over hundreds of thousands of
sessions is not comfortable, since a collision puts one user's files in another
user's session.
Widening a name that is already on disk is the risky half. Directories written
before the change carry the old width and their files are still in use, so the
cleanup code has to be able to name both, which is why the width is a parameter
rather than a constant in the middle of the function.
The property pinned here is not the hash, it is that the short name is a PREFIX
of the long one. That is what lets code holding the new name find a directory
written under the old one, and it holds only because both come from the same
md5 truncated to different lengths. Also pinned: the two-character spreading
directory, the user name appearing as given, and the three calls that must
abort rather than invent a path -- a relative sessionDataDir, and a width of 0
or 33.
None of this is visible. A session whose directory is named differently does
not report an error, it comes back without its custom track.
Watched to fail and then pass: narrowing the width back to 8 turns it red on
the width line. Recorded as sandbox-ab in utils/testRegistry.
refs #10138, refs #38391
- lines changed 16, context: html, text, full: html, text
36977d0e699d3c853840f08cec63ab2a2dd5eaa7 Sat Sep 19 18:34:00 2026 -0700
geoMirrorSelfTester: pin which gbNode row a server takes for itself
The browser runs on several machines and each offers the others in a menu, so
it has to know which gbNode row is itself. It used to answer from browser.node
in hg.conf alone, so a machine serving a node other than the one browser.node
names -- a sandbox, or two nodes behind one apache -- took itself for its own
peer and offered the visitor a link to the site they were already on. #27988
made the host the visitor typed decide whenever that host is one of the nodes,
with browser.node as the fallback.
The symptom is invisible in the way that matters: every page renders, and a
menu entry pointing back at itself reads as a mirror being down rather than as
a bug.
No domain is named here. gbNode is configuration data whose rows change, so
the test reads two rows, points browser.node at the first, and asks whether the
second can claim the server. What is printed is which of the two answered, not
what they are called, and the port case is included because HTTP_HOST carries
one whenever it is not 80 or 443.
Also recorded in utils/testRegistry: what blocks a unit test on the fifteen
v504 tickets still waiting for one, each with its own reason rather than a
category, since the reason decides who can unblock it.
Watched to fail and then pass: with the host test removed the server claims no
node at all and offers all three, itself included. Recorded as sandbox-ab.
refs #27988, refs #38391
- lines changed 1, context: html, text, full: html, text
814335cde61f999ae23626093306bdb6bf394f5e Sun Sep 20 07:00:39 2026 -0700
hgvs: cover a deprecated protein accession, and say what is not covered
A protein accession that is no longer current resolves through
ncbiRefSeqLinkHistorical, which is what lets a term from an old paper still
find its position. Three such terms are added to the valid-terms list:
NP_000054.2, which has three deprecated transcript versions behind it, and
NP_055615.8, which has versions .8, .9 and .10.
The other half of #38248 is NOT pinned, and the registry row says so rather
than implying otherwise. That half picks the newest deprecated transcript by
sorting on length first, so that .9 does not beat .10 as a string. I could not
build a term that shows it: with the order by removed entirely, and again with
a plain string sort, every term gives identical coordinates. The reason is in
the data -- for the accessions with both a .9 and a .10, the versions differ
only in where the UTR ends, so cdsStart, cdsEnd and exonCount are the same and
a coding residue lands in the same place whichever version is chosen.
Recorded as assertion-only, the honest level, with what was tried written down
so the next person does not repeat it.
refs #38248, refs #38391
- lines changed 2, context: html, text, full: html, text
0f2f66270dcd4603785850ee72d7d883ff68185b Sun Sep 20 07:03:14 2026 -0700
asForDbTester: a GenArk accession must not be looked for in MySQL
asForDb() may need a database connection to fetch a track's autoSql. The name
it is handed is usually an assembly, but on a quickLifted track it is the
SOURCE assembly, and for a GenArk that arrives as a bare accession with no
MySQL database of that name anywhere. Without #38272's isGenArk test the CGI
does not return an empty field list, it dies, and the reader gets an error page
instead of a details page -- only for the combination of a quickLift and a
GenArk source, which is why it went unnoticed.
The last case is the discriminating one: a name that is neither a GenArk
accession nor a real database still aborts, which shows the GenArk case is let
through deliberately rather than by connection failures having stopped
mattering. The abort message carries a MySQL error number and the server's own
wording, so what is pinned is whether the abort was about reaching a database
of that name, not the text.
Two things this test got wrong before it got them right, both recorded in its
header. It has to run against a config that sets genarkHubPrefix, because
isGenArk answers through that prefix and says no when it is unset, so with a
developer's own hg.conf the GenArk case failed for a reason unrelated to the
fix. And the accession is read from the genark table at run time, since naming
an assembly makes the test go red the day that assembly is dropped.
Also fixes the registry row for bedItemRgbTester, which moved to hg/cgilib and
whose row still named the old path -- caught by the registry's own check, which
is the first time it has failed for a real reason.
refs #38272, refs #38391
- lines changed 7, context: html, text, full: html, text
4fa4bda98feb9c07aa1409b9bd0fb6274b388e31 Sun Sep 20 07:04:16 2026 -0700
registry: record that four of the seven handed to docent have no docent script
The decision on 2026-09-20 was that the tickets whose fix lives inside a CGI
are covered by the docent suite rather than by a unit test. That is true of
three of them. It is not true of #38233, #38253, #38254 and #38317, which have
no docent script either, so nothing watches them at all, and the rows now say
so. They belong on #38252's list.
refs #38391
- lines changed 4, context: html, text, full: html, text
eccdddfb22cf35d4e5698f72a4b12707aa43b349 Sun Sep 20 14:27:27 2026 -0700
testRegistry: check the docent column's "-" as well as its names
The docent column says which browser test watches the same ticket, and a named
script was already checked: it has to exist and has to belong to that ticket.
A "-" was checked by nothing, and that was the wrong half to leave out.
`unwatched` -- the list of tickets where nothing anywhere would go red if the
bug came back -- is built entirely out of those "-" values. They were entered
by hand, by reading the docent directory once, so a script written the next day
left the ticket sitting on that queue with nothing to notice. For the four
tickets that are on it because their code lives inside a CGI, somebody writing
the docent script is the expected outcome, which made it the likeliest kind of
row to go stale.
So a row claiming no docent script is now checked against the tree the same way
a named one is: if rm<ticket>.*docent.yaml turns up, the check fails and asks
for the row to be filled in. The failure is somebody doing the right thing and
the table not having heard about it.
Watched to fail and then pass: blanking the docent column of #36212, whose
script is in the tree, turns the real table red with the name of the script it
found.
refs #38391
- src/utils/testRegistry/testRegistry
- lines changed 374, context: html, text, full: html, text
5011b739391b6a1b6129d473b6c050010baf1f6f Sat Sep 19 17:57:37 2026 -0700
testRegistry: a registry of which unit test defends which ticket
A bug ticket has no way to say whether a test now defends its fix, and a test
has no way to say which bug it came from. The two questions are asked from
opposite ends and neither the tree nor Redmine answers either one.
utils/testRegistry/registry.tsv is that table, hand written, one row per ticket
per test, starting at v504. Unit tests only: the browser-page regression tests
are the docent suite, refs #38252, which already names each script for its
ticket, and a docent column here says which ticket has one of those too.
Each row says why a unit test is the right test, because "the fix is in a
library file" is wrong in both directions. A wording fix in hg/lib needs no
unit test, and a performance rewrite inside hgTracks needs one badly, since
nothing else can tell that the slow path has come back. The three reasons are
invisible, perf and library, and a perf row says what has to be measured --
queries, passes, allocations, bytes -- never wall-clock seconds.
testRegistry reads it: ticket, test, release, why, needed, unwatched, tickets,
check. No network and no database, so the check can run anywhere.
check is why the table is checked in rather than derived. A registry that
quietly names files nobody has, saying a bug is covered when it is not, is
worse than no registry, so check fails the build the day a row rots. Its own
tests are in tests/, with one row of input/bad.tsv per complaint check can
make, and utils/makefile runs the whole thing so it reaches make test from src.
Today: 37 tickets, 12 covered by 11 tests, 25 waiting.
refs #38391
- lines changed 22, context: html, text, full: html, text
eccdddfb22cf35d4e5698f72a4b12707aa43b349 Sun Sep 20 14:27:27 2026 -0700
testRegistry: check the docent column's "-" as well as its names
The docent column says which browser test watches the same ticket, and a named
script was already checked: it has to exist and has to belong to that ticket.
A "-" was checked by nothing, and that was the wrong half to leave out.
`unwatched` -- the list of tickets where nothing anywhere would go red if the
bug came back -- is built entirely out of those "-" values. They were entered
by hand, by reading the docent directory once, so a script written the next day
left the ticket sitting on that queue with nothing to notice. For the four
tickets that are on it because their code lives inside a CGI, somebody writing
the docent script is the expected outcome, which made it the likeliest kind of
row to go stale.
So a row claiming no docent script is now checked against the tree the same way
a named one is: if rm<ticket>.*docent.yaml turns up, the check fails and asks
for the row to be filled in. The failure is somebody doing the right thing and
the table not having heard about it.
Watched to fail and then pass: blanking the docent column of #36212, whose
script is in the tree, turns the real table red with the name of the script it
found.
refs #38391
- src/utils/testRegistry/tests/expected/check.out
- lines changed 12, context: html, text, full: html, text
5011b739391b6a1b6129d473b6c050010baf1f6f Sat Sep 19 17:57:37 2026 -0700
testRegistry: a registry of which unit test defends which ticket
A bug ticket has no way to say whether a test now defends its fix, and a test
has no way to say which bug it came from. The two questions are asked from
opposite ends and neither the tree nor Redmine answers either one.
utils/testRegistry/registry.tsv is that table, hand written, one row per ticket
per test, starting at v504. Unit tests only: the browser-page regression tests
are the docent suite, refs #38252, which already names each script for its
ticket, and a docent column here says which ticket has one of those too.
Each row says why a unit test is the right test, because "the fix is in a
library file" is wrong in both directions. A wording fix in hg/lib needs no
unit test, and a performance rewrite inside hgTracks needs one badly, since
nothing else can tell that the slow path has come back. The three reasons are
invisible, perf and library, and a perf row says what has to be measured --
queries, passes, allocations, bytes -- never wall-clock seconds.
testRegistry reads it: ticket, test, release, why, needed, unwatched, tickets,
check. No network and no database, so the check can run anywhere.
check is why the table is checked in rather than derived. A registry that
quietly names files nobody has, saying a bug is covered when it is not, is
worse than no registry, so check fails the build the day a row rots. Its own
tests are in tests/, with one row of input/bad.tsv per complaint check can
make, and utils/makefile runs the whole thing so it reaches make test from src.
Today: 37 tickets, 12 covered by 11 tests, 25 waiting.
refs #38391
- lines changed 1, context: html, text, full: html, text
eccdddfb22cf35d4e5698f72a4b12707aa43b349 Sun Sep 20 14:27:27 2026 -0700
testRegistry: check the docent column's "-" as well as its names
The docent column says which browser test watches the same ticket, and a named
script was already checked: it has to exist and has to belong to that ticket.
A "-" was checked by nothing, and that was the wrong half to leave out.
`unwatched` -- the list of tickets where nothing anywhere would go red if the
bug came back -- is built entirely out of those "-" values. They were entered
by hand, by reading the docent directory once, so a script written the next day
left the ticket sitting on that queue with nothing to notice. For the four
tickets that are on it because their code lives inside a CGI, somebody writing
the docent script is the expected outcome, which made it the likeliest kind of
row to go stale.
So a row claiming no docent script is now checked against the tree the same way
a named one is: if rm<ticket>.*docent.yaml turns up, the check fails and asks
for the row to be filled in. The failure is somebody doing the right thing and
the table not having heard about it.
Watched to fail and then pass: blanking the docent column of #36212, whose
script is in the tree, turns the real table red with the name of the script it
found.
refs #38391
- src/utils/testRegistry/tests/expected/list.out
- lines changed 17, context: html, text, full: html, text
5011b739391b6a1b6129d473b6c050010baf1f6f Sat Sep 19 17:57:37 2026 -0700
testRegistry: a registry of which unit test defends which ticket
A bug ticket has no way to say whether a test now defends its fix, and a test
has no way to say which bug it came from. The two questions are asked from
opposite ends and neither the tree nor Redmine answers either one.
utils/testRegistry/registry.tsv is that table, hand written, one row per ticket
per test, starting at v504. Unit tests only: the browser-page regression tests
are the docent suite, refs #38252, which already names each script for its
ticket, and a docent column here says which ticket has one of those too.
Each row says why a unit test is the right test, because "the fix is in a
library file" is wrong in both directions. A wording fix in hg/lib needs no
unit test, and a performance rewrite inside hgTracks needs one badly, since
nothing else can tell that the slow path has come back. The three reasons are
invisible, perf and library, and a perf row says what has to be measured --
queries, passes, allocations, bytes -- never wall-clock seconds.
testRegistry reads it: ticket, test, release, why, needed, unwatched, tickets,
check. No network and no database, so the check can run anywhere.
check is why the table is checked in rather than derived. A registry that
quietly names files nobody has, saying a bug is covered when it is not, is
worse than no registry, so check fails the build the day a row rots. Its own
tests are in tests/, with one row of input/bad.tsv per complaint check can
make, and utils/makefile runs the whole thing so it reaches make test from src.
Today: 37 tickets, 12 covered by 11 tests, 25 waiting.
refs #38391
- src/utils/testRegistry/tests/expected/needed.out
- lines changed 5, context: html, text, full: html, text
5011b739391b6a1b6129d473b6c050010baf1f6f Sat Sep 19 17:57:37 2026 -0700
testRegistry: a registry of which unit test defends which ticket
A bug ticket has no way to say whether a test now defends its fix, and a test
has no way to say which bug it came from. The two questions are asked from
opposite ends and neither the tree nor Redmine answers either one.
utils/testRegistry/registry.tsv is that table, hand written, one row per ticket
per test, starting at v504. Unit tests only: the browser-page regression tests
are the docent suite, refs #38252, which already names each script for its
ticket, and a docent column here says which ticket has one of those too.
Each row says why a unit test is the right test, because "the fix is in a
library file" is wrong in both directions. A wording fix in hg/lib needs no
unit test, and a performance rewrite inside hgTracks needs one badly, since
nothing else can tell that the slow path has come back. The three reasons are
invisible, perf and library, and a perf row says what has to be measured --
queries, passes, allocations, bytes -- never wall-clock seconds.
testRegistry reads it: ticket, test, release, why, needed, unwatched, tickets,
check. No network and no database, so the check can run anywhere.
check is why the table is checked in rather than derived. A registry that
quietly names files nobody has, saying a bug is covered when it is not, is
worse than no registry, so check fails the build the day a row rots. Its own
tests are in tests/, with one row of input/bad.tsv per complaint check can
make, and utils/makefile runs the whole thing so it reaches make test from src.
Today: 37 tickets, 12 covered by 11 tests, 25 waiting.
refs #38391
- src/utils/testRegistry/tests/expected/release.out
- lines changed 15, context: html, text, full: html, text
5011b739391b6a1b6129d473b6c050010baf1f6f Sat Sep 19 17:57:37 2026 -0700
testRegistry: a registry of which unit test defends which ticket
A bug ticket has no way to say whether a test now defends its fix, and a test
has no way to say which bug it came from. The two questions are asked from
opposite ends and neither the tree nor Redmine answers either one.
utils/testRegistry/registry.tsv is that table, hand written, one row per ticket
per test, starting at v504. Unit tests only: the browser-page regression tests
are the docent suite, refs #38252, which already names each script for its
ticket, and a docent column here says which ticket has one of those too.
Each row says why a unit test is the right test, because "the fix is in a
library file" is wrong in both directions. A wording fix in hg/lib needs no
unit test, and a performance rewrite inside hgTracks needs one badly, since
nothing else can tell that the slow path has come back. The three reasons are
invisible, perf and library, and a perf row says what has to be measured --
queries, passes, allocations, bytes -- never wall-clock seconds.
testRegistry reads it: ticket, test, release, why, needed, unwatched, tickets,
check. No network and no database, so the check can run anywhere.
check is why the table is checked in rather than derived. A registry that
quietly names files nobody has, saying a bug is covered when it is not, is
worse than no registry, so check fails the build the day a row rots. Its own
tests are in tests/, with one row of input/bad.tsv per complaint check can
make, and utils/makefile runs the whole thing so it reaches make test from src.
Today: 37 tickets, 12 covered by 11 tests, 25 waiting.
refs #38391
- src/utils/testRegistry/tests/expected/test.out
- lines changed 3, context: html, text, full: html, text
5011b739391b6a1b6129d473b6c050010baf1f6f Sat Sep 19 17:57:37 2026 -0700
testRegistry: a registry of which unit test defends which ticket
A bug ticket has no way to say whether a test now defends its fix, and a test
has no way to say which bug it came from. The two questions are asked from
opposite ends and neither the tree nor Redmine answers either one.
utils/testRegistry/registry.tsv is that table, hand written, one row per ticket
per test, starting at v504. Unit tests only: the browser-page regression tests
are the docent suite, refs #38252, which already names each script for its
ticket, and a docent column here says which ticket has one of those too.
Each row says why a unit test is the right test, because "the fix is in a
library file" is wrong in both directions. A wording fix in hg/lib needs no
unit test, and a performance rewrite inside hgTracks needs one badly, since
nothing else can tell that the slow path has come back. The three reasons are
invisible, perf and library, and a perf row says what has to be measured --
queries, passes, allocations, bytes -- never wall-clock seconds.
testRegistry reads it: ticket, test, release, why, needed, unwatched, tickets,
check. No network and no database, so the check can run anywhere.
check is why the table is checked in rather than derived. A registry that
quietly names files nobody has, saying a bug is covered when it is not, is
worse than no registry, so check fails the build the day a row rots. Its own
tests are in tests/, with one row of input/bad.tsv per complaint check can
make, and utils/makefile runs the whole thing so it reaches make test from src.
Today: 37 tickets, 12 covered by 11 tests, 25 waiting.
refs #38391
- src/utils/testRegistry/tests/expected/ticket.out
- lines changed 6, context: html, text, full: html, text
5011b739391b6a1b6129d473b6c050010baf1f6f Sat Sep 19 17:57:37 2026 -0700
testRegistry: a registry of which unit test defends which ticket
A bug ticket has no way to say whether a test now defends its fix, and a test
has no way to say which bug it came from. The two questions are asked from
opposite ends and neither the tree nor Redmine answers either one.
utils/testRegistry/registry.tsv is that table, hand written, one row per ticket
per test, starting at v504. Unit tests only: the browser-page regression tests
are the docent suite, refs #38252, which already names each script for its
ticket, and a docent column here says which ticket has one of those too.
Each row says why a unit test is the right test, because "the fix is in a
library file" is wrong in both directions. A wording fix in hg/lib needs no
unit test, and a performance rewrite inside hgTracks needs one badly, since
nothing else can tell that the slow path has come back. The three reasons are
invisible, perf and library, and a perf row says what has to be measured --
queries, passes, allocations, bytes -- never wall-clock seconds.
testRegistry reads it: ticket, test, release, why, needed, unwatched, tickets,
check. No network and no database, so the check can run anywhere.
check is why the table is checked in rather than derived. A registry that
quietly names files nobody has, saying a bug is covered when it is not, is
worse than no registry, so check fails the build the day a row rots. Its own
tests are in tests/, with one row of input/bad.tsv per complaint check can
make, and utils/makefile runs the whole thing so it reaches make test from src.
Today: 37 tickets, 12 covered by 11 tests, 25 waiting.
refs #38391
- src/utils/testRegistry/tests/expected/tickets.out
- lines changed 3, context: html, text, full: html, text
5011b739391b6a1b6129d473b6c050010baf1f6f Sat Sep 19 17:57:37 2026 -0700
testRegistry: a registry of which unit test defends which ticket
A bug ticket has no way to say whether a test now defends its fix, and a test
has no way to say which bug it came from. The two questions are asked from
opposite ends and neither the tree nor Redmine answers either one.
utils/testRegistry/registry.tsv is that table, hand written, one row per ticket
per test, starting at v504. Unit tests only: the browser-page regression tests
are the docent suite, refs #38252, which already names each script for its
ticket, and a docent column here says which ticket has one of those too.
Each row says why a unit test is the right test, because "the fix is in a
library file" is wrong in both directions. A wording fix in hg/lib needs no
unit test, and a performance rewrite inside hgTracks needs one badly, since
nothing else can tell that the slow path has come back. The three reasons are
invisible, perf and library, and a perf row says what has to be measured --
queries, passes, allocations, bytes -- never wall-clock seconds.
testRegistry reads it: ticket, test, release, why, needed, unwatched, tickets,
check. No network and no database, so the check can run anywhere.
check is why the table is checked in rather than derived. A registry that
quietly names files nobody has, saying a bug is covered when it is not, is
worse than no registry, so check fails the build the day a row rots. Its own
tests are in tests/, with one row of input/bad.tsv per complaint check can
make, and utils/makefile runs the whole thing so it reaches make test from src.
Today: 37 tickets, 12 covered by 11 tests, 25 waiting.
refs #38391
- src/utils/testRegistry/tests/expected/unwatched.out
- lines changed 1, context: html, text, full: html, text
5011b739391b6a1b6129d473b6c050010baf1f6f Sat Sep 19 17:57:37 2026 -0700
testRegistry: a registry of which unit test defends which ticket
A bug ticket has no way to say whether a test now defends its fix, and a test
has no way to say which bug it came from. The two questions are asked from
opposite ends and neither the tree nor Redmine answers either one.
utils/testRegistry/registry.tsv is that table, hand written, one row per ticket
per test, starting at v504. Unit tests only: the browser-page regression tests
are the docent suite, refs #38252, which already names each script for its
ticket, and a docent column here says which ticket has one of those too.
Each row says why a unit test is the right test, because "the fix is in a
library file" is wrong in both directions. A wording fix in hg/lib needs no
unit test, and a performance rewrite inside hgTracks needs one badly, since
nothing else can tell that the slow path has come back. The three reasons are
invisible, perf and library, and a perf row says what has to be measured --
queries, passes, allocations, bytes -- never wall-clock seconds.
testRegistry reads it: ticket, test, release, why, needed, unwatched, tickets,
check. No network and no database, so the check can run anywhere.
check is why the table is checked in rather than derived. A registry that
quietly names files nobody has, saying a bug is covered when it is not, is
worse than no registry, so check fails the build the day a row rots. Its own
tests are in tests/, with one row of input/bad.tsv per complaint check can
make, and utils/makefile runs the whole thing so it reaches make test from src.
Today: 37 tickets, 12 covered by 11 tests, 25 waiting.
refs #38391
- src/utils/testRegistry/tests/expected/why.out
- lines changed 14, context: html, text, full: html, text
5011b739391b6a1b6129d473b6c050010baf1f6f Sat Sep 19 17:57:37 2026 -0700
testRegistry: a registry of which unit test defends which ticket
A bug ticket has no way to say whether a test now defends its fix, and a test
has no way to say which bug it came from. The two questions are asked from
opposite ends and neither the tree nor Redmine answers either one.
utils/testRegistry/registry.tsv is that table, hand written, one row per ticket
per test, starting at v504. Unit tests only: the browser-page regression tests
are the docent suite, refs #38252, which already names each script for its
ticket, and a docent column here says which ticket has one of those too.
Each row says why a unit test is the right test, because "the fix is in a
library file" is wrong in both directions. A wording fix in hg/lib needs no
unit test, and a performance rewrite inside hgTracks needs one badly, since
nothing else can tell that the slow path has come back. The three reasons are
invisible, perf and library, and a perf row says what has to be measured --
queries, passes, allocations, bytes -- never wall-clock seconds.
testRegistry reads it: ticket, test, release, why, needed, unwatched, tickets,
check. No network and no database, so the check can run anywhere.
check is why the table is checked in rather than derived. A registry that
quietly names files nobody has, saying a bug is covered when it is not, is
worse than no registry, so check fails the build the day a row rots. Its own
tests are in tests/, with one row of input/bad.tsv per complaint check can
make, and utils/makefile runs the whole thing so it reaches make test from src.
Today: 37 tickets, 12 covered by 11 tests, 25 waiting.
refs #38391
- src/utils/testRegistry/tests/input/bad.tsv
- lines changed 16, context: html, text, full: html, text
5011b739391b6a1b6129d473b6c050010baf1f6f Sat Sep 19 17:57:37 2026 -0700
testRegistry: a registry of which unit test defends which ticket
A bug ticket has no way to say whether a test now defends its fix, and a test
has no way to say which bug it came from. The two questions are asked from
opposite ends and neither the tree nor Redmine answers either one.
utils/testRegistry/registry.tsv is that table, hand written, one row per ticket
per test, starting at v504. Unit tests only: the browser-page regression tests
are the docent suite, refs #38252, which already names each script for its
ticket, and a docent column here says which ticket has one of those too.
Each row says why a unit test is the right test, because "the fix is in a
library file" is wrong in both directions. A wording fix in hg/lib needs no
unit test, and a performance rewrite inside hgTracks needs one badly, since
nothing else can tell that the slow path has come back. The three reasons are
invisible, perf and library, and a perf row says what has to be measured --
queries, passes, allocations, bytes -- never wall-clock seconds.
testRegistry reads it: ticket, test, release, why, needed, unwatched, tickets,
check. No network and no database, so the check can run anywhere.
check is why the table is checked in rather than derived. A registry that
quietly names files nobody has, saying a bug is covered when it is not, is
worse than no registry, so check fails the build the day a row rots. Its own
tests are in tests/, with one row of input/bad.tsv per complaint check can
make, and utils/makefile runs the whole thing so it reaches make test from src.
Today: 37 tickets, 12 covered by 11 tests, 25 waiting.
refs #38391
- lines changed 1, context: html, text, full: html, text
eccdddfb22cf35d4e5698f72a4b12707aa43b349 Sun Sep 20 14:27:27 2026 -0700
testRegistry: check the docent column's "-" as well as its names
The docent column says which browser test watches the same ticket, and a named
script was already checked: it has to exist and has to belong to that ticket.
A "-" was checked by nothing, and that was the wrong half to leave out.
`unwatched` -- the list of tickets where nothing anywhere would go red if the
bug came back -- is built entirely out of those "-" values. They were entered
by hand, by reading the docent directory once, so a script written the next day
left the ticket sitting on that queue with nothing to notice. For the four
tickets that are on it because their code lives inside a CGI, somebody writing
the docent script is the expected outcome, which made it the likeliest kind of
row to go stale.
So a row claiming no docent script is now checked against the tree the same way
a named one is: if rm<ticket>.*docent.yaml turns up, the check fails and asks
for the row to be filled in. The failure is somebody doing the right thing and
the table not having heard about it.
Watched to fail and then pass: blanking the docent column of #36212, whose
script is in the tree, turns the real table red with the name of the script it
found.
refs #38391
- src/utils/testRegistry/tests/input/good.tsv
- lines changed 8, context: html, text, full: html, text
5011b739391b6a1b6129d473b6c050010baf1f6f Sat Sep 19 17:57:37 2026 -0700
testRegistry: a registry of which unit test defends which ticket
A bug ticket has no way to say whether a test now defends its fix, and a test
has no way to say which bug it came from. The two questions are asked from
opposite ends and neither the tree nor Redmine answers either one.
utils/testRegistry/registry.tsv is that table, hand written, one row per ticket
per test, starting at v504. Unit tests only: the browser-page regression tests
are the docent suite, refs #38252, which already names each script for its
ticket, and a docent column here says which ticket has one of those too.
Each row says why a unit test is the right test, because "the fix is in a
library file" is wrong in both directions. A wording fix in hg/lib needs no
unit test, and a performance rewrite inside hgTracks needs one badly, since
nothing else can tell that the slow path has come back. The three reasons are
invisible, perf and library, and a perf row says what has to be measured --
queries, passes, allocations, bytes -- never wall-clock seconds.
testRegistry reads it: ticket, test, release, why, needed, unwatched, tickets,
check. No network and no database, so the check can run anywhere.
check is why the table is checked in rather than derived. A registry that
quietly names files nobody has, saying a bug is covered when it is not, is
worse than no registry, so check fails the build the day a row rots. Its own
tests are in tests/, with one row of input/bad.tsv per complaint check can
make, and utils/makefile runs the whole thing so it reaches make test from src.
Today: 37 tickets, 12 covered by 11 tests, 25 waiting.
refs #38391
- src/utils/testRegistry/tests/makefile
- lines changed 72, context: html, text, full: html, text
5011b739391b6a1b6129d473b6c050010baf1f6f Sat Sep 19 17:57:37 2026 -0700
testRegistry: a registry of which unit test defends which ticket
A bug ticket has no way to say whether a test now defends its fix, and a test
has no way to say which bug it came from. The two questions are asked from
opposite ends and neither the tree nor Redmine answers either one.
utils/testRegistry/registry.tsv is that table, hand written, one row per ticket
per test, starting at v504. Unit tests only: the browser-page regression tests
are the docent suite, refs #38252, which already names each script for its
ticket, and a docent column here says which ticket has one of those too.
Each row says why a unit test is the right test, because "the fix is in a
library file" is wrong in both directions. A wording fix in hg/lib needs no
unit test, and a performance rewrite inside hgTracks needs one badly, since
nothing else can tell that the slow path has come back. The three reasons are
invisible, perf and library, and a perf row says what has to be measured --
queries, passes, allocations, bytes -- never wall-clock seconds.
testRegistry reads it: ticket, test, release, why, needed, unwatched, tickets,
check. No network and no database, so the check can run anywhere.
check is why the table is checked in rather than derived. A registry that
quietly names files nobody has, saying a bug is covered when it is not, is
worse than no registry, so check fails the build the day a row rots. Its own
tests are in tests/, with one row of input/bad.tsv per complaint check can
make, and utils/makefile runs the whole thing so it reaches make test from src.
Today: 37 tickets, 12 covered by 11 tests, 25 waiting.
refs #38391
switch to commits view, user index