Skip to content

Contributing

Setup

git clone https://github.com/beaujeant/protopoke.git
cd protopoke
python3 -m venv .venv
source .venv/bin/activate
pip install -e ".[dev]"

Running Tests

# All tests
pytest

# Single file
pytest tests/test_framing.py

# Single test
pytest -k test_length_prefix

# With coverage
pytest --cov=protopoke

Tests use pytest-asyncio with asyncio_mode = "auto" — all async def test_* functions run automatically without needing @pytest.mark.asyncio.

Test Layout

tests/
├── conftest.py                   Shared fixtures
├── test_proxy_integration.py     End-to-end proxy flow
├── test_session.py               Session + SessionRegistry
├── test_framing.py               All four built-in framers
├── test_protocol_parser.py       DefinitionBasedDecoder + Encoder
├── test_protocol_definition.py   YAML/JSON schema loading
├── test_protocol_display.py      Hexdump and tree renderers
├── test_tamper.py                QueuedTamperController
├── test_rules.py                 ReplaceRule + InterceptRule + engines
├── test_forge.py                 ForgeEngine replay
├── test_forge_models.py          Playbook / PlaybookFrame models
├── test_playbook_custom.py       Playbook custom-transport behaviour
├── test_fuzzing.py               FuzzerEngine + mutators
├── test_fuzzing_integration.py   End-to-end fuzzing
├── test_events.py                EventBus pub/sub
├── test_config_serialization.py  ForwarderConfig round-trip
├── test_update_forwarder_config.py  Hot-swap forwarder name/framer/protocol
├── test_project_manager.py       Save/open .pp ZIP files
├── test_models.py                Frame / SessionInfo / TamperedUnit
├── test_tls.py                   TLS MITM
├── test_socks5_handshake.py      SOCKS5 wire-protocol negotiation
├── test_socks5_proxy.py          End-to-end SOCKS5 forwarder
├── test_udp_proxy.py             End-to-end UDP forwarder
├── test_udp_forge.py             Forge/replay over UDP
├── test_udp_session_reuse.py     UDP per-tuple flow reuse
├── test_send_frame.py            api.send_frame()
├── test_inject_to_server.py      api.inject_to_server()
├── test_inject_to_client.py      api.inject_to_client()
├── test_mcp_server.py            MCP tool coverage
├── test_mcp_host.py              MCPHost lifecycle
├── test_segmented_control.py     SegmentedControl widget
└── test_to_dict_serialization.py .to_dict() / .from_dict() round-trips

Code Style

  • Python 3.11+ — use modern type hints and from __future__ import annotations
  • All I/O is async (asyncio); no threads
  • Data classes for all models — no ORM, no metaclasses
  • Dependencies are explicit constructor arguments, not globals
  • Registration (e.g. FRAMER_REGISTRY) is explicit, not auto-discovered

Project Structure

See Architecture for a detailed breakdown of the codebase.