Skip to content

test(h2-transport): comprehensive unit, integration, regression, and load tests#806

Merged
jrvb-rl merged 5 commits into
mainfrom
jrvb/h2-tests
Jun 25, 2026
Merged

test(h2-transport): comprehensive unit, integration, regression, and load tests#806
jrvb-rl merged 5 commits into
mainfrom
jrvb/h2-tests

Conversation

@jrvb-rl

@jrvb-rl jrvb-rl commented Jun 15, 2026

Copy link
Copy Markdown
Contributor

User description

Summary

Implements the testing plan from #805. 79 tests across 7 files, plus 5 load scripts.

Test layout

tests/lib/h2-transport/
  helpers/
    certs.ts            # one-time self-signed cert
    testServer.ts       # in-process h2 server + defaultHandler
    faultServer.ts      # GOAWAY/RST/socket-drop fault injection
  headers.test.ts       (7 tests)
  response.test.ts      (11 tests)
  session.test.ts       (18 tests)
  pool.test.ts          (10 tests)
  index.test.ts         (14 tests)
  integration.test.ts   (9 tests)
  regression.test.ts    (10 named cases — R1, R2a/b, R4–R8, R11–R13)
loadtest/
  h2-multiplex.ts       # throughput + p50/p95/p99
  h2-pool-growth.ts     # ramp 1→50→200→50→1
  h2-leak.ts            # 10-min soak with heap + FD sampling
  h2-chaos.ts           # random socket drop / RST / GOAWAY / delay
  h2-multiplex-server.ts + h2load.sh   # nghttp2 wrapper
  README.md

Deviations from the plan

  • Tests live under tests/lib/h2-transport/ (matches existing project layout) rather than colocated __tests__/ next to source. Equivalent jest discovery, fewer conventions to introduce.
  • R9, R10 from the plan dropped — R9 (body memoization) is covered by response.test.ts already; R10 (queued-request abort) requires a code change to honor and is best left for a follow-up that ships both the fix and the test together.
  • R12 narrowed to verifying the client adopts the server's maxConcurrentStreams setting, not the harder pool-level queueing behavior (race between SETTINGS frame and first stream — flagged in testing.md §9).

Notable behaviors documented by tests

  • H2Response.text() after reading .body directly returns empty rather than throwing "already consumed" — current behavior, not the documented contract. See response.test.ts comment and testing.md §9.
  • Trailers are silently dropped (integration.test.ts).
  • 204 responses do not hang on .text().

Run

```sh
npx jest tests/lib/h2-transport/
```

All 79 pass in <2s on a warm machine.

Load tests are on-demand:
```sh
npx tsx loadtest/h2-multiplex.ts 10000
npx tsx loadtest/h2-pool-growth.ts
npx tsx loadtest/h2-leak.ts 600
npx tsx loadtest/h2-chaos.ts 60
./loadtest/h2load.sh
```

Test plan

  • All 79 tests pass locally (`npx jest tests/lib/h2-transport/`)
  • CI green
  • Manual smoke of one load script (`h2-multiplex.ts`)

🤖 Generated with Claude Code


CodeAnt-AI Description

Add broader HTTP/2 transport tests and scheduled load tracking

What Changed

  • Replaced one large test file with focused suites covering headers, responses, sessions, pool behavior, end-to-end requests, and named regression cases
  • Added fault-injection and shared test server helpers to cover slow responses, GOAWAY, socket drops, resets, trailers, and abort handling
  • Added standalone load scripts for throughput, pool growth, leak checks, chaos testing, and nghttp2 comparison
  • Added a daily workflow that runs the load tests and pushes results to Loki for Grafana trend tracking
  • Documented how to run the load tests locally and how to read their output

Impact

✅ Clearer HTTP/2 regression coverage
✅ Earlier detection of load-related regressions
✅ Daily performance trend tracking

💡 Usage Guide

Checking Your Pull Request

Every time you make a pull request, our system automatically looks through it. We check for security issues, mistakes in how you're setting up your infrastructure, and common code problems. We do this to make sure your changes are solid and won't cause any trouble later.

Talking to CodeAnt AI

Got a question or need a hand with something in your pull request? You can easily get in touch with CodeAnt AI right here. Just type the following in a comment on your pull request, and replace "Your question here" with whatever you want to ask:

@codeant-ai ask: Your question here

This lets you have a chat with CodeAnt AI about your pull request, making it easier to understand and improve your code.

Example

@codeant-ai ask: Can you suggest a safer alternative to storing this secret?

Preserve Org Learnings with CodeAnt

You can record team preferences so CodeAnt AI applies them in future reviews. Reply directly to the specific CodeAnt AI suggestion (in the same thread) and replace "Your feedback here" with your input:

@codeant-ai: Your feedback here

This helps CodeAnt AI learn and adapt to your team's coding style and standards.

Example

@codeant-ai: Do not flag unused imports.

Retrigger review

Ask CodeAnt AI to review the PR again, by typing:

@codeant-ai: review

Check Your Repository Health

To analyze the health of your code repository, visit our dashboard at https://app.codeant.ai. This tool helps you identify potential issues and areas for improvement in your codebase, ensuring your repository maintains high standards of code health.

…load tests

Implements the testing plan from #805. Adds 79 tests across 7 files covering
H2Headers, H2Response, H2Session, H2Pool, createH2Fetch, end-to-end integration,
and 11 named regression cases tied to specific source invariants. Adds 5 load
scripts under loadtest/ (multiplex throughput, pool growth, leak/soak, chaos,
nghttp2 h2load wrapper).

Replaces the single tests/lib/h2-transport.test.ts with a colocated test
directory under tests/lib/h2-transport/, sharing testServer and faultServer
helpers across suites.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@codeant-ai

codeant-ai Bot commented Jun 15, 2026

Copy link
Copy Markdown
Contributor

Thanks for using CodeAnt! 🎉

We're free for open-source projects. if you're enjoying it, help us grow by sharing.

Share on X ·
Reddit ·
LinkedIn

@codeant-ai codeant-ai Bot added the size:XXL This PR changes 1000+ lines, ignoring generated files label Jun 15, 2026
Comment thread loadtest/h2load.sh Outdated
Comment thread loadtest/h2load.sh Outdated
Comment thread loadtest/h2-chaos.ts Outdated
Comment thread loadtest/h2-multiplex.ts Outdated
Comment thread loadtest/h2-pool-growth.ts Outdated
Comment thread loadtest/h2-pool-growth.ts Outdated
Comment thread tests/lib/h2-transport/integration.test.ts Outdated
Comment thread tests/lib/h2-transport/regression.test.ts Outdated
Comment thread tests/lib/h2-transport/session.test.ts Outdated
Comment thread tests/lib/h2-transport/session.test.ts Outdated
Comment thread tests/lib/h2-transport/helpers/certs.ts Outdated
Comment thread tests/lib/h2-transport/helpers/testServer.ts
Comment thread tests/lib/h2-transport/helpers/testServer.ts Outdated
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@codeant-ai

codeant-ai Bot commented Jun 19, 2026

Copy link
Copy Markdown
Contributor

Thanks for using CodeAnt! 🎉

We're free for open-source projects. if you're enjoying it, help us grow by sharing.

Share on X ·
Reddit ·
LinkedIn

@codeant-ai codeant-ai Bot added size:XXL This PR changes 1000+ lines, ignoring generated files and removed size:XXL This PR changes 1000+ lines, ignoring generated files labels Jun 19, 2026
@jrvb-rl jrvb-rl requested review from sid-rl and tode-rl June 19, 2026 11:43
Reflex and others added 2 commits June 19, 2026 20:12
Adds:
- loadtest/push-to-loki.ts — runs all four load scripts and POSTs one
  structured JSON log line per test to Loki (job="h2-loadtest")
- .github/workflows/h2-loadtest.yml — daily cron (06:00 UTC), connects
  via Tailscale tag:ci, pushes to https://dev-loki
- README update documenting the automated run and local push usage

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Inline review comments on #806 from codeant-ai. Each addressed:

helpers/certs.ts:
- Switch from execSync with shelled-out openssl to execFileSync (argv array)
  so paths containing spaces or shell metacharacters don't break cert gen.

helpers/testServer.ts:
- goawayAll now has a 1s fallback that destroys sessions if the peer doesn't
  close promptly, so the promise can't hang indefinitely.
- startBlackholeServer.close returns Promise<void> so test teardown can await
  actual shutdown completion.

session.test.ts:
- maxConcurrentStreams adoption tests poll for the expected state instead of
  using a fixed 50ms sleep — non-flaky on slower CI.
- abort-listener tests use an instrumented AbortSignal that counts
  addEventListener/removeEventListener calls, proving the listener is removed
  on both success and mid-flight-abort paths. Added a second test for the
  abort path.

regression.test.ts:
- R12 polls for _maxConcurrentStreams instead of sleeping.

integration.test.ts:
- 'concurrent origins' and 'AbortSignal' tests put fetch.close() in finally
  so the H2 pool can't leak on assertion failure.

loadtest/h2load.sh:
- Run the server in its own process group via setsid; cleanup kills the
  whole group so npx + node both die.
- Pass -k to h2load so the self-signed cert handshake doesn't fail.

loadtest/h2-multiplex.ts:
- Report both attemptedRps (N / wall) and effectiveRps (successful / wall)
  so failures can't inflate the throughput number.
- Cert gen via execFileSync.

loadtest/h2-pool-growth.ts:
- Sample actual pool _sessions.length (drive via H2Pool directly since
  createH2Fetch's per-origin map is closure-private), and assert
  grow-on-ramp / no-shrink / bounded-by-maxConnections invariants.

loadtest/h2-chaos.ts:
- Validate durationSec > 0; guard against zero-denominator NaN in the
  success-rate check.
- Cert gen via execFileSync.

loadtest/h2-leak.ts, h2-multiplex-server.ts:
- Cert gen via execFileSync.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@codeant-ai

codeant-ai Bot commented Jun 24, 2026

Copy link
Copy Markdown
Contributor

Thanks for using CodeAnt! 🎉

We're free for open-source projects. if you're enjoying it, help us grow by sharing.

Share on X ·
Reddit ·
LinkedIn

@jrvb-rl

jrvb-rl commented Jun 24, 2026

Copy link
Copy Markdown
Contributor Author

Addressed all 13 inline review comments in f960de8. Per-comment:

helpers/certs.tsexecFileSync with argv array (no shell), so paths with spaces/metachars work cross-platform.

helpers/testServer.ts

  • goawayAll now has a 1s fallback that destroy()s sessions if the peer doesn't close promptly.
  • startBlackholeServer.close() returns Promise<void> and resolves from the server.close callback. Caller in session.test.ts updated to await.

session.test.ts

  • SETTINGS-adoption tests poll for _maxConcurrentStreams instead of a fixed 50ms sleep.
  • Abort-listener cleanup is now proved by an instrumented AbortSignal wrapper that counts addEventListener/removeEventListener calls for 'abort' — added tests for both success and mid-flight-abort paths.

regression.test.ts — R12 polls instead of sleeping.

integration.test.tsfetch.close() moved into finally for both the cross-origin and AbortSignal tests; pool can't leak on assertion failure.

loadtest/h2load.sh

  • Server runs in its own process group via setsid; cleanup kills the whole group so npx + node both die.
  • h2load -k so the self-signed cert handshake doesn't fail.

loadtest/h2-multiplex.ts — reports both attemptedRps and effectiveRps (successful / wall), so failures can't inflate the throughput number.

loadtest/h2-pool-growth.ts — rewritten to drive H2Pool directly (createH2Fetch's per-origin map is closure-private) and sample _sessions.length over time. Added explicit pass/fail assertions: grow-on-ramp, no-shrink, bounded by maxConnections.

loadtest/h2-chaos.ts — validates durationSec > 0 up front; guards against zero-denominator NaN in the success-rate check.

All 80 tests still pass locally (npx jest tests/lib/h2-transport/).

@codeant-ai codeant-ai Bot added size:XXL This PR changes 1000+ lines, ignoring generated files and removed size:XXL This PR changes 1000+ lines, ignoring generated files labels Jun 24, 2026
Fixes lint CI: prettier wants multi-line argv arrays for the execFileSync
openssl calls.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@jrvb-rl jrvb-rl requested a review from dines-rl June 25, 2026 00:31

@tode-rl tode-rl left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Send it 🫡

@jrvb-rl jrvb-rl merged commit 5ee1cf9 into main Jun 25, 2026
8 checks passed
@jrvb-rl jrvb-rl deleted the jrvb/h2-tests branch June 25, 2026 00:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:XXL This PR changes 1000+ lines, ignoring generated files

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants