test(http2): expand branch coverage for http2_server.cpp#1056
Merged
Conversation
Adds tests/unit/http2_server_branch_test.cpp exercising public-API surfaces of src/protocols/http2/http2_server.cpp left uncovered after Issue #992: tls_config field round-trips with boundary / binary-byte paths and verify_client toggling, http2_server construction with empty / long / binary-byte server IDs, http2_settings round-trip with zero and UINT32_MAX boundaries plus repeated header_table_size updates exercising HPACK encoder/decoder dynamic-table updates, enable_push toggling, pre-listen state queries (is_running, active_connections, active_streams, server_id, idempotent stop), repeated start/stop cycles on ephemeral port 0, already-running rejection for start() and start_tls(), additional start_tls rejection paths, post-failed-TLS clear-start recovery, destructor-while-running cleanup, wait() completion after stop() on a separate thread, handler registration with default-constructed / move-only-capture / replaced std::function values, concurrent state polling under shared_ptr lifetime, concurrent set_settings writer with get_settings reader, and multi-instance independent lifecycle. Registers network_http2_server_branch_test in tests/CMakeLists.txt and updates both CHANGELOGs. Honest scope: the impl-level frame-handler paths in http2_server_connection (process_frame per-frame_type cases, the handle_*_frame methods, send_frame, send_settings, read_frame_header, read_frame_payload, dispatch_request) and the TLS handshake error path inside handle_accept_tls require a live HTTP/2 client to drive frame I/O end-to-end and remain uncovered without a transport fixture. Closes #1050 Part of #953
std::function requires copyable callables (gcc 13 static_assert and libc++ both reject move-only lambdas). Replace the unique_ptr capture in MoveOnlyCaptureHandlerIsAccepted with a shared_ptr capture, which preserves the test intent (heap-allocated state captured into the handler) while satisfying std::function's copyability requirement. Update CHANGELOG entries to reflect the corrected wording.
Contributor
Coverage Report
Coverage DetailsFull HTML report is available as a build artifact. |
This was referenced Apr 26, 2026
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.
What
Summary
Adds
tests/unit/http2_server_branch_test.cppwith 41 hermetic test cases across 9 suites, exercising public-API surfaces ofsrc/protocols/http2/http2_server.cppthat remained uncovered after Issue #992. Complements the existinghttp2_server_test.cppandhttp2_server_coverage_test.cppby extending boundary-value, concurrency, and lifecycle coverage without requiring a live HTTP/2 client.Change Type
Why
Related Issues
Motivation
src/protocols/http2/http2_server.cpphad a 2026-04-26 baseline of line 38.3% / branch 19.4% ondevelop @ 05c1b7bb. The uncovered surfaces concentrate in boundary handling (zero / max settings values, empty / long server IDs), pre-listen state queries, repeated lifecycle cycles, and concurrent reader/writer interactions on the settings + state-query APIs. Raising hermetic coverage for these surfaces now contributes directly to the #953 ecosystem-wide 80% line / 70% branch goal and follows the same pattern as siblings #1048 (PR #1054) and #1049 (PR #1055).Where
Files Changed
tests/unit/http2_server_branch_test.cpp(new, ~568 lines)tests/CMakeLists.txt(registersnetwork_http2_server_branch_test)CHANGELOG.md,docs/CHANGELOG.md([Unreleased] > Addedentry)How
Implementation Highlights
The test file is organised into 9
TEST_F/TESTsuites, each targeting a distinct surface:Http2ServerTlsConfigRoundTrip(4 tests) —tls_configfield round-trips with empty / 1024-char / binary-byte paths, plusverify_clienttoggle that does not perturb other fields.Http2ServerConstructionIds(5 tests) — construction with empty / 512-char / binary-byte server IDs, multi-instance independence, 16-iteration repeated construction.Http2ServerSettingsRoundTrip(6 tests) — all-zero and all-UINT32_MAXhttp2_settingsround-trips viaset_settings/get_settings, default-value baseline, repeatedheader_table_sizeupdates exercising HPACK encoder / decoder dynamic-table updates,enable_pushtoggle invariance, independent settings across instances.Http2ServerPreListenStateTest(6 tests) — pre-listen state queries (is_running,active_connections,active_streams,server_id) andstop()idempotency before anystart().Http2ServerCycleTest(7 tests) — 4-iteration start / stop cycles on ephemeral port 0,start()already-running rejection,start_tls()already-running rejection (after a successfulstart()), zero counters after stop, destructor-while-running cleanup,wait()completion afterstop()on a separate thread.Http2ServerTlsRejectTest(5 tests) —start_tls()rejection paths (default-empty config, both files missing,verify_client=truewith missing CA, repeated rejection idempotency, post-failed-TLS clear-start recovery).Http2ServerHandlerCoverageTest(5 tests) — handler registration with default-constructedstd::function, move-only-capturedunique_ptr, and triple replacement of both request and error handlers.Http2ServerConcurrentQueries(5 tests) — 8-threadis_runningpolling, 4-threadactive_connections/active_streams/server_idpolling (200 iterations each), concurrent writer/reader pair onset_settings/get_settings.Http2ServerMultiInstance(2 tests) — 4 concurrent servers running on independent ephemeral ports plus stop-one-affects-none.Honest scope statement
The impl-level frame-handler paths in
http2_server_connectioncannot be exercised hermetically and remain at 0 hits in this suite:process_frameper-frame_typeswitch cases (settings / headers / data / rst_stream / ping / goaway / window_update branches)handle_settings_frame+send_settings_ack(peer SETTINGS application + ACK emission)handle_headers_frameHPACK decode + COMPRESSION_ERROR GOAWAY emissionhandle_data_framewindow-update emission and unknown-stream RST_STREAM emissionhandle_rst_stream_framestream closehandle_ping_frameACK replyhandle_goaway_frameshutdown reactionhandle_window_update_frameflow-control accountingget_or_create_stream,close_streamsend_frame,send_settings(frame serialisation + write)read_frame_header,read_frame_payloadsuccess branchesdispatch_request(request-handler invocation + post-handler stream close)handle_accept_tlsDriving these requires either a mock client that speaks the HTTP/2 wire format end-to-end (preface + SETTINGS exchange + per-frame round-trips) or a friend-declared injection point inside
http2_server_connection. Neither is in scope for this hermetic test sub-issue. The existinghttp2_server_coverage_test.cpppartially exercises preface handling via raw TCP clients, but the per-frame branches require a real HTTP/2 client. This same structural blocker was acknowledged honestly in the sibling PRs #1054 (#1048) and #1055 (#1049).Testing Done
Breaking Changes
None — test-only additions.