test: harden Gloas harness and CI - #313
Draft
AntiD2ta wants to merge 6 commits into
Draft
Conversation
AntiD2ta
force-pushed
the
review/gloas-test-harness-ci
branch
from
August 5, 2026 11:49
192c523 to
803b196
Compare
AntiD2ta
force-pushed
the
review/gloas-test-harness-ci
branch
from
August 5, 2026 12:01
803b196 to
500b9e8
Compare
AntiD2ta
force-pushed
the
review/gloas-test-harness-ci
branch
from
August 5, 2026 12:25
500b9e8 to
4869e14
Compare
Bez625
force-pushed
the
review/gloas-test-harness-ci
branch
from
August 5, 2026 14:51
4869e14 to
f254ad1
Compare
AntiD2ta
marked this pull request as draft
August 5, 2026 15:03
AntiD2ta
force-pushed
the
review/gloas-test-harness-ci
branch
from
August 5, 2026 15:07
f254ad1 to
211a657
Compare
AntiD2ta
force-pushed
the
review/gloas-test-harness-ci
branch
from
August 6, 2026 10:12
211a657 to
4d6f7c4
Compare
AntiD2ta
force-pushed
the
review/gloas-test-harness-ci
branch
from
August 6, 2026 10:19
4d6f7c4 to
9bddf38
Compare
AntiD2ta
force-pushed
the
review/gloas-test-harness-ci
branch
from
August 6, 2026 10:28
9bddf38 to
3d2b53a
Compare
Bez625
force-pushed
the
review/gloas-test-harness-ci
branch
from
August 6, 2026 13:43
3d2b53a to
0634b2b
Compare
AntiD2ta
force-pushed
the
review/gloas-test-harness-ci
branch
from
August 17, 2026 08:37
a64512e to
432c8f8
Compare
Bez625
force-pushed
the
review/gloas-test-harness-ci
branch
from
August 21, 2026 08:24
432c8f8 to
c1cd5cb
Compare
Bez625
force-pushed
the
review/gloas-test-harness-ci
branch
from
August 21, 2026 08:50
c1cd5cb to
79e68a0
Compare
Covers the Gloas HTTP endpoints, and adds the machinery that decides when the live tests among them may run. testclients/forkutil.go holds the three fork probes: whether the node's config knows the Gloas fork, whether the chain head is past it, and a diagnostic name for the head's fork. http/gloasgate_test.go turns those into skips, or into failures when HTTP_REQUIRE_GLOAS is set, so a suite pointed at a Gloas node can assert the gated tests actually ran. The endpoint coverage is split by what it needs. Live tests against HTTP_ADDRESS exercise EPBSProposal, ExecutionPayloadEnvelope and the Gloas SubmitProposal path. Stub tests over httptest cover the request shape of SubmitExecutionPayloadBid and SubmitExecutionPayloadEnvelope, and the request-consistency guards, without needing a node on the fork.
OnGloas read the head fork by fetching the whole head block and reading its version. Every caller passes a service built without custom spec support, so on a minimal-preset devnet the SSZ block is decoded against the mainnet-preset codec and fails. The error was swallowed, HeadVersion returned "unknown", and every Gloas live test skipped with "chain is not on gloas (head is unknown)". Compare the head's fork version from Fork(state: "head") against GLOAS_FORK_VERSION instead. Both are config values, so the answer no longer depends on the compiled-in preset, and no block is downloaded. HeadVersion is now a diagnostic name derived from the spec's *_FORK_VERSION keys, and OnGloas no longer routes through it.
Several of the new live tests used the shared service, which has no custom spec support, for SSZ work that cannot decode on the minimal preset this devnet runs: the SSZ rows of TestEPBSProposal, which contradicted the comment above them, and TestSubmitProposalGloas, which failed before reaching the publish path it exists to exercise. Both now go through a custom-spec service. disagreeingService wrote s.base after New had already handed the service to periodicUpdateConnectionState, an unsynchronised write against a goroutine that reads it every 30s, which go test -race reports whenever HTTP_ADDRESS is set. It now fronts the live node with a reverse proxy and passes WithAddress to New. Other fixes: - TestEPBSProposal re-reads the head slot per subtest, rather than computing it once for four live block productions the head can advance past. - Assertions move out of httptest handler goroutines, where a failure calls runtime.Goexit outside the test's goroutine, abandons the request, and reports as a transport error naming nothing. - The envelope sentinel test skips with the head slot named instead of underflowing phase0.Slot when the head is below slot 100. - The KnowsGloas gate reason no longer claims the fork is absent when the spec may simply have been unreadable.
The harness gates every Gloas live test on the chain being past the fork, and HTTP_REQUIRE_GLOAS turns those skips into failures. Nothing set it, so the gates could only ever skip and the bugs fixed in the preceding commits passed CI unnoticed. Add a second job that points HTTP_ADDRESS at the HTTP_ADDRESS_GLOAS repository variable and sets HTTP_REQUIRE_GLOAS. It is skipped when that variable is empty, so forks and branches with no devnet to point at are unaffected. The run is scoped by name: post-Gloas block production is v4-only, so the v3 rows of the package fail permanently against a Gloas node for reasons this job is not about.
AntiD2ta
force-pushed
the
review/gloas-test-harness-ci
branch
from
August 26, 2026 09:45
8ed628b to
8567ce0
Compare
AntiD2ta
added a commit
that referenced
this pull request
Aug 28, 2026
http/events_internal_test.go drove Service.handleEvent directly with synthetic sse.Event values. This is a pure deletion: 200 lines out, none in. It leaves handleEvent with no test that calls it, including the Gloas dispatch arms the next commit adds. Nothing in this repo replaces that coverage, and neither does the stacked PR #313.
AntiD2ta
added a commit
that referenced
this pull request
Aug 28, 2026
http/events_internal_test.go drove Service.handleEvent directly with synthetic sse.Event values. This is a pure deletion: 200 lines out, none in. It leaves handleEvent with no test that calls it, including the Gloas dispatch arms the next commit adds. Nothing in this repo replaces that coverage, and neither does the stacked PR #313.
This was referenced Aug 28, 2026
Closed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
TL;DR
Live and stub coverage for the Gloas HTTP endpoints, the fork gates that decide when the live tests run, and a CI job that makes those gates fail loudly instead of skipping.
Where to start
testclients/forkutil.go(56 lines). The three fork probes everything else is gated on.OnGloascompares the head's fork version againstGLOAS_FORK_VERSION. Both are config values, so it needs no block download and does not care whether the node's preset matches the compiled-in one.http/gloasgate_test.go. The gate, andHTTP_REQUIRE_GLOASswitching it from skip to fail.http/main_test.go. Harness setup. There is one address knob,HTTP_ADDRESS.HTTP_REQUIRE_GLOASsets severity only and is not a second endpoint.epbsproposal,executionpayloadenvelope,submitproposal,submitexecutionpayloadbid,submitexecutionpayloadenvelope..github/workflows/http-tests.yml(30 lines). The only change outsidetestclients/andhttp/.How to run it
Without
HTTP_ADDRESS,TestMainreturns beforem.Run, so the package reportsokhaving run nothing. Worth knowing when reading a green log.Dependency and review order
Review after the event-forwarding PR. Base is
review/gloas-events-multi-client.Public API
One addition outside a
_test.gofile.testclients/forkutil.goexportsKnowsGloas,OnGloasandHeadVersion, and onlypackage http_testconsumes them. Say if you would rather they lived there.Behaviour-sensitive checks
The Gloas job needs two repository settings before it does anything: the
HTTP_ADDRESS_GLOASvariable, and theHTTP_BEARER_TOKEN_GLOASsecret if the endpoint is authenticated. Without the variable the job is skipped, so forks and branches with no devnet to point at are unaffected. With it, the job maps that variable toHTTP_ADDRESSand setsHTTP_REQUIRE_GLOAS=true, so a gate that skips fails the job.The job's
-runpattern is scoped by name rather than running the whole package. Post-Gloas block production is v4-only, so the v3 tests in./http/...fail permanently against a Gloas node for reasons the job is not about. A new Gloas live test needs a name matching that pattern to be picked up.Validation
go test ./...: 2,510 tests. Seven packages (spec/phase0,spec/bellatrix,spec/capella,spec/deneb,spec/electra,api/v1,api/v1/deneb) fail locally on go1.27 withjsontexterror-string mismatches. None of those files are in this diff, and CI pins go1.25.2.go test -race -p 1 ./http/... ./testclients/...: pass.go vetandgofmt: clean.The
gloasjob has now run against glamsterdam-devnet-8. 25 tests, 0 skips, so the gates resolve and the live tests execute rather than quietly opting out. 24 pass, andTestEPBSProposalfails on 2 of its 4 rows. Neither cause is in this diff:TestEPBSProposal/SSZPayloadExcludedandSSZPayloadIncludedfail with "no Eth-Execution-Payload-Included header in epbs proposal response". Asked with theAccept: application/octet-stream;q=1,application/json;q=0.9header the client sends, the node answers200withcontent-type: application/octet-streamand sendsEth-Consensus-Version,Eth-Consensus-Block-ValueandEth-Execution-Payload-Value, but noEth-Execution-Payload-Included. The SSZ path inepbsProposalFromResponsehas nowhere else to read the flag, so it cannot succeed against this node. Both JSON rows pass, because the JSON path reads the flag from the body.500 no cached P2P bid availablefor roughly 6 requests in 10, whichever valueinclude_payloadtakes.TestSubmitProposalGloasfails on that locally and passed in CI on a luckier slot, so any live production test on a Gloas devnet needs to expect it.Since the last push
OnGloasno longer fetches the head block. Any error on that path was swallowed and made every Gloas live test skip with "head is unknown", so the gate could fail open on a node that does not serve the block endpoint, or whose preset the compiled-in codec cannot decode. Comparing fork versions removes both.TestEPBSProposaland the block production inTestSubmitProposalGloasnow use a custom-spec service, which is what the comments already claimed.disagreeingServicefronts the live node with a reverse proxy and passesWithAddresstoNew, instead of writings.baseafterNewhad already handed the service toperiodicUpdateConnectionState. That write was a data racego test -racereports wheneverHTTP_ADDRESSis set.TestEPBSProposalre-reads the head slot per subtest, so the later rows do not ask a devnet to build for a slot it has passed.httptesthandler goroutines, where a failure callsruntime.Goexitoutside the test's goroutine and surfaces as a transport error naming nothing.phase0.Slotwhen the head is below slot 100.