Skip to content

test(quic): add extended coverage tests for crypto module#1002

Merged
kcenon merged 1 commit into
developfrom
feat/issue-993-quic-crypto-coverage
Apr 20, 2026
Merged

test(quic): add extended coverage tests for crypto module#1002
kcenon merged 1 commit into
developfrom
feat/issue-993-quic-crypto-coverage

Conversation

@kcenon

@kcenon kcenon commented Apr 20, 2026

Copy link
Copy Markdown
Owner

What

Summary

Adds 88 new GTest cases in a dedicated quic_crypto_extended_test.cpp translation unit targeting the low-coverage branches in src/protocols/quic/crypto.cpp (line 59.5%, branch 22.5% per #993). Existing 25-case suite is untouched.

Change Type

  • Test (new test coverage, no production code changes)

Affected Components

  • tests/unit/quic_crypto_extended_test.cpp (new, 1288 LOC, 88 tests across 9 suites)
  • tests/CMakeLists.txt (one line to register network_quic_crypto_extended_test)

Why

Problem Solved

Issue #993 names specific weak areas in QUIC crypto coverage: AEAD error paths, HKDF failures, key derivation phases, packet-number encryption edge cases, key update, retry integrity tag validation, header protection. Branch coverage at 22.5% of 1060 branches is a latent security/correctness risk for a TLS/QUIC crypto path.

Related Issues

How

Implementation Highlights

Suites and what each covers:

Suite Branches targeted
HkdfExtractExtendedTest extract with empty salt / empty IKM, deterministic output
HkdfExpandExtendedTest expand at varying lengths (0..255 blocks)
HkdfExpandLabelExtendedTest varying labels, contexts, lengths
InitialKeysExtendedTest QUIC v1, v2, unknown-version fallback to v1; client vs server flag
PacketProtectionExtendedTest AEAD encrypt/decrypt round-trip, corrupt tag/ciphertext/PN/key/IV/AAD, short packet, empty + 4 KiB payloads
HpMaskExtendedTest short-sample rejection, key/sample isolation, 16-byte sample determinism
HeaderProtectionExtendedTest long+short first byte across pn-length 1..4, XOR self-inverse
QuicCryptoExtendedTest set_keys monotonic level, ALPN empty list / too-long, update_keys pre-handshake rejection, session ticket + early data gating, 0-RTT client-side derivation, move semantics preserving keys
QuicKeysUtilityTest is_valid / clear / operator== on quic_keys and key_pair

All cases are deterministic, perform no real network IO, require no server certificates on disk, and use only the public API.

Branches intentionally not reached

Four branches genuinely require real TLS state and cannot be exercised from the public API without handshake simulation:

  1. process_crypto_data completion branch — needs full handshake
  2. update_keys success branch — needs handshake_complete == true
  3. init_server success branch — needs PEM cert+key on disk
  4. Early-data-accepted true branch — server-side acceptance state

These are documented in the test file's header comment.

Testing Done

  • network_quic_crypto_extended_test: 88/88 PASS in 5 ms (clang, macOS arm64, release preset)
  • network_quic_crypto_module_test (original 25 cases): 25/25 PASS in 2 ms — no regression
  • Coverage measurement (gcovr/lcov not installed locally — CI Coverage Analysis verifies 80% line / 70% branch targets)

Test Plan for Reviewers

cmake --preset release
cmake --build build/release --target network_quic_crypto_extended_test
./build/release/bin/network_quic_crypto_extended_test --gtest_brief=1

Breaking Changes

None — test-only addition.

Adds 88 deterministic, public-API-only unit tests targeting the
lower-coverage branches in src/protocols/quic/crypto.cpp. Covers:

- HKDF extract/expand/expand_label edge cases including empty-salt
  and empty-IKM error paths, zero-length expand, and label/context
  isolation
- initial_keys::derive for QUIC v1 and v2 salts, version divergence,
  empty and max-length DCIDs, and secret propagation into keys
- derive_keys with the is_client_keys flag verified as no-op
- Packet protection AEAD round-trip across many packet numbers,
  empty and large payloads, and varying header sizes
- Unprotect failure paths: truncated packet, modified header,
  wrong packet number, wrong key, wrong IV, corrupted tag,
  corrupted ciphertext
- Header protection mask: short-sample rejection, key/sample
  isolation, determinism
- Header protection protect/unprotect round-trip across long and
  short headers with packet number lengths 1-4, self-inverse XOR
- quic_crypto public surface: set_keys monotonic level raising,
  ALPN wire-format rejection of overlong protocols, 0-RTT ticket
  and early-data gates, update_keys pre-handshake rejection, move
  semantics preserving keys
- quic_keys / key_pair is_valid, clear, and equality operators

All tests run in under one second total with no real network IO
and no TLS handshake.

Closes #993
@github-actions

Copy link
Copy Markdown
Contributor

Coverage Report

Metric Value
Line Coverage 65.1%
Branch Coverage 31.1%
Target 80% lines / 70% branches
Coverage Details

Full HTML report is available as a build artifact.

@kcenon kcenon merged commit 190cb11 into develop Apr 20, 2026
15 checks passed
@kcenon kcenon deleted the feat/issue-993-quic-crypto-coverage branch April 20, 2026 09:35
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