Skip to content

test(http2): expand branch coverage for http2_server.cpp#1056

Merged
kcenon merged 2 commits into
developfrom
test/issue-1050-http2-server-coverage
Apr 26, 2026
Merged

test(http2): expand branch coverage for http2_server.cpp#1056
kcenon merged 2 commits into
developfrom
test/issue-1050-http2-server-coverage

Conversation

@kcenon

@kcenon kcenon commented Apr 26, 2026

Copy link
Copy Markdown
Owner

What

Summary

Adds tests/unit/http2_server_branch_test.cpp with 41 hermetic test cases across 9 suites, exercising public-API surfaces of src/protocols/http2/http2_server.cpp that remained uncovered after Issue #992. Complements the existing http2_server_test.cpp and http2_server_coverage_test.cpp by extending boundary-value, concurrency, and lifecycle coverage without requiring a live HTTP/2 client.

Change Type

  • Test

Why

Related Issues

Motivation

src/protocols/http2/http2_server.cpp had a 2026-04-26 baseline of line 38.3% / branch 19.4% on develop @ 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 (registers network_http2_server_branch_test)
  • CHANGELOG.md, docs/CHANGELOG.md ([Unreleased] > Added entry)

How

Implementation Highlights

The test file is organised into 9 TEST_F / TEST suites, each targeting a distinct surface:

  • Http2ServerTlsConfigRoundTrip (4 tests) — tls_config field round-trips with empty / 1024-char / binary-byte paths, plus verify_client toggle 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_MAX http2_settings round-trips via set_settings / get_settings, default-value baseline, repeated header_table_size updates exercising HPACK encoder / decoder dynamic-table updates, enable_push toggle invariance, independent settings across instances.
  • Http2ServerPreListenStateTest (6 tests) — pre-listen state queries (is_running, active_connections, active_streams, server_id) and stop() idempotency before any start().
  • Http2ServerCycleTest (7 tests) — 4-iteration start / stop cycles on ephemeral port 0, start() already-running rejection, start_tls() already-running rejection (after a successful start()), zero counters after stop, destructor-while-running cleanup, wait() completion after stop() on a separate thread.
  • Http2ServerTlsRejectTest (5 tests) — start_tls() rejection paths (default-empty config, both files missing, verify_client=true with missing CA, repeated rejection idempotency, post-failed-TLS clear-start recovery).
  • Http2ServerHandlerCoverageTest (5 tests) — handler registration with default-constructed std::function, move-only-captured unique_ptr, and triple replacement of both request and error handlers.
  • Http2ServerConcurrentQueries (5 tests) — 8-thread is_running polling, 4-thread active_connections / active_streams / server_id polling (200 iterations each), concurrent writer/reader pair on set_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_connection cannot be exercised hermetically and remain at 0 hits in this suite:

  • process_frame per-frame_type switch cases (settings / headers / data / rst_stream / ping / goaway / window_update branches)
  • handle_settings_frame + send_settings_ack (peer SETTINGS application + ACK emission)
  • handle_headers_frame HPACK decode + COMPRESSION_ERROR GOAWAY emission
  • handle_data_frame window-update emission and unknown-stream RST_STREAM emission
  • handle_rst_stream_frame stream close
  • handle_ping_frame ACK reply
  • handle_goaway_frame shutdown reaction
  • handle_window_update_frame flow-control accounting
  • get_or_create_stream, close_stream
  • send_frame, send_settings (frame serialisation + write)
  • read_frame_header, read_frame_payload success branches
  • dispatch_request (request-handler invocation + post-handler stream close)
  • The TLS handshake error path inside handle_accept_tls

Driving 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 existing http2_server_coverage_test.cpp partially 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

  • Tests added: 45 test cases in 9 test suites
  • Local build: skipped — cmake/ctest not installed in sandbox
  • Will rely on CI (Coverage Analysis + ubuntu/macos x Debug/Release matrix, plus ASAN/TSAN/UBSAN sanitizer jobs)

Breaking Changes

None — test-only additions.

kcenon added 2 commits April 26, 2026 15:37
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.
@github-actions

Copy link
Copy Markdown
Contributor

Coverage Report

Metric Value
Line Coverage 66.4%
Branch Coverage 32.9%
Target 80% lines / 70% branches
Coverage Details

Full HTML report is available as a build artifact.

@kcenon kcenon merged commit c345d30 into develop Apr 26, 2026
9 checks passed
@kcenon kcenon deleted the test/issue-1050-http2-server-coverage branch April 26, 2026 08:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant