Skip to content

feat(tests): add Python test harness with Docker infrastructure#76

Merged
Ratler merged 13 commits intomainfrom
feat/ircu2-test-harness
Mar 25, 2026
Merged

feat(tests): add Python test harness with Docker infrastructure#76
Ratler merged 13 commits intomainfrom
feat/ircu2-test-harness

Conversation

@Ratler
Copy link
Copy Markdown
Member

@Ratler Ratler commented Mar 24, 2026

Context

Pretty big PR since it adds integration test cases retroactively for a few new features.

Summary

Details

Infrastructure:

Component Description
Dockerfile Multi-stage build using debian:trixie-slim, runs autogen.sh for reliable autotools bootstrapping
docker-compose.yml 3-node topology: hub (6667), leaf1 (6668), leaf2 (6669) on a static IP network
tests/conftest.py Session-scoped fixtures that start/stop containers and wait for server linking
tests/irc_client.py Async IRC client with CAP negotiation, wait_for/collect_until helpers
tests/p10_server.py Fake P10 server — handles full handshake, PING keepalive, user tracking, OPMODE/ACCOUNT

Test server topology:

Server Numeric U:lined Purpose
services.test.net 4 Yes (oper) Fake services for S2S testing
notulined.test.net 5 No Rejection tests
uworldonly.test.net 6 Yes (no oper) CONF_UWORLD without CONF_UWORLD_OPER

Test suites:

  • pr59_part_messages/ — cross-server part message suppression for banned users
  • pr61_uhnames/ — UHNAMES (userhost-in-names) CAP negotiation and NAMES reply format
  • pr62_remote_x/ — remote OPMODE +x, ACCOUNT U:line restriction, privilege tier checks, umode propagation ordering

Each PR directory follows a consistent pattern:

  • test_fix.py — TDD tests that fail on the base branch and pass with the PR applied
  • test_edge_cases.py — adversarial tests for boundary conditions and regressions
  • Additional files for specific concerns (e.g. test_privilege_check.py, test_umode_ordering.py)

Test plan

# Install dependencies
uv sync

# Run all tests
uv run pytest tests/ -v

# Run a specific PR's tests
uv run pytest tests/pr62_remote_x/ -v

# Run only single-server or multi-server tests
uv run pytest -m single_server
uv run pytest -m multi_server

# Tear down
docker compose down

Ratler added 13 commits March 24, 2026 19:45
- Dockerfile with multi-stage build for ircu from working tree
- docker-compose with hub + 2 leaves topology
- Custom async IRC client with CAP negotiation support
- pytest fixtures for container lifecycle management
- PR #59 tests (part message suppression for banned users)
- PR #61 tests (userhost-in-names capability)
- IRC message parser unit tests
- tests/README.md: setup, usage, topology, API reference
- Fixed infinite loop in wait_for where stashed messages were
  re-read from buffer endlessly
- Replaced deprecated asyncio.get_event_loop() with get_running_loop()
- Simplified buffer search using enumerate
- Move dependencies from requirements.txt to pyproject.toml [project.dependencies]
- Remove requirements.txt
- Add uv.lock
- Add .venv and uv.lock to .dockerignore
Add --force-recreate and explicit docker compose down before up to
guarantee tests always run against the currently checked-out code.
This is critical for TDD workflow where you switch branches between runs.
The original test_fix.py tested local part message suppression, which
already worked on the base branch. The actual bug PR #59 fixes is that
part messages leak across server-to-server links for banned users.

Rewrote tests to use ircd_network fixture (multi-server topology):
- Observer on leaf1 sees banned user's part message from hub (bug)
- Fixed docker-compose to use static IPs (10.55.0.x) so ircu's
  built-in DNS resolver can find the other servers
- Control test verifies unbanned part messages work cross-server
Add a lightweight P10 fake server (tests/p10_server.py) that connects
to ircd as a U:lined service, completes the full P10 handshake, and
can send S2S messages like OPMODE and ACCOUNT. This enables testing
server-to-server protocol behavior from the Python test harness.

Add integration tests for PR #62 (Remote +x):
- test_fix.py: 3 TDD tests that verify OPMODE +x from a U:lined
  server sets hidden host (fail on base branch, pass with PR #62)
- test_edge_cases.py: 6 adversarial tests covering remote users,
  unsupported modes, ACCOUNT, -o regression, and rapid sequences

Infrastructure changes:
- Docker configs: add Connect + UWorld blocks for services.test.net
- Dockerfile: clean host-compiled binaries before Linux build to
  fix exec format error on cross-platform Docker builds
PR #62's OPMODE +x handler requires IsAccount(dptr) — it silently
ignores +x on users without an account. Updated the test to verify
this correct behavior instead of expecting a MODE notification.
Extend test_remote_opmode_x_without_account to a two-phase test:
first verifies +x is ignored without an account (IsAccount guard),
then sets the account and verifies +x succeeds and hides the host.
Add test_account_rejected_from_non_ulined_server which connects a
second fake P10 server (notulined.test.net) that has a Connect block
but no UWorld entry. Verifies that ACCOUNT from this server gets
ERR_NOPRIVILEGES (481) and the user's account is not set.

This covers the second half of PR #62: ms_account now requires
CONF_UWORLD before accepting ACCOUNT messages.
- Remove incorrect 481 (ERR_NOPRIVILEGES) expectation from
  test_account_rejected_from_non_ulined_server; protocol_violation()
  only sends a DESYNCH wallops, not a numeric reply
- Rename test_nooper_uworld_cannot_send_plus_x to _can_ and flip
  assertion; PR #62 intentionally only gates +o/-o behind
  CONF_UWORLD_OPER while +x needs only basic CONF_UWORLD
- Rename test_nooper_uworld_unknown_mode_should_be_rejected to
  _silently_ignored; unknown modes fall through without error
- Strengthen test_opmode_minus_o_still_works to verify MODE -o
  notification now that PR #62 adds send_umode_out() to de_oper()
- Add Connect/UWorld blocks for uworldonly.test.net in hub config
- Switch Dockerfile to debian:trixie-slim and use autogen.sh for
  reliable autotools bootstrapping in container builds
@Ratler Ratler force-pushed the feat/ircu2-test-harness branch 2 times, most recently from 1be6217 to 81ab3bd Compare March 24, 2026 19:19
@Ratler Ratler merged commit 49af539 into main Mar 25, 2026
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