---
last_verified: 2026-05-31
verified_version: 0.1.34
owner: qa
freshness_days: 30
---

# Testing Guide — pvtcoms

## Quick Start

```bash
cd core && cargo test
```

## Test Structure

```
core/
├── src/                    # unit tests inline (#[cfg(test)] mod tests)
└── tests/                  # integration tests
    ├── vectors/            # deterministic crypto test vectors (handshake, ratchet)
    └── network/            # adverse-network transport/session tests
```

## Running Tests

| Command | Scope | When |
|---------|-------|------|
| `cargo test -p <crate>` | Unit tests for one crate | Every change |
| `cargo test` | Full workspace | Before push |
| `cargo test --release` + property/fuzz | Vectors + invariants | Before release |

## Writing Tests

- **Test files**: inline `#[cfg(test)] mod tests` for units; `tests/*.rs` for integration.
- **Naming**: `fn test_<what>_<scenario>_<expected>()`.
- **Crypto = deterministic vectors.** Every handshake/ratchet step has committed test vectors; results must be reproducible.
- **Ratchet invariants** (property/fuzz tests): a session MUST survive out-of-order delivery, dropped messages, and
  reconnects without desync or message loss — this is the #1 correctness target (see `../BUILD_PLAN.md` M1).
- **No secrets in test output/logs.**

## Coverage

```bash
cargo llvm-cov --workspace --html   # coverage report
```

Prioritize coverage of the crypto core and the mailbox/rendezvous state machine over UI.

## Demo messenger (`pvtcoms-demo`)

A working CLI messenger: a continuous, full-duplex **Double-Ratchet** chat (fresh key per message)
seeded by the hybrid **X25519 + ML-KEM-768** handshake, which is **identity-authenticated** (each side
signs the transcript with a long-term Ed25519 identity). It runs over two transports and persists
identity, pinned contacts, and message history (all encrypted at rest).

> ⚠️ **Demo, not audited.** First-contact identities are trust-on-first-use (compare the safety emoji
> and `verify`); the at-rest storage key is a hardcoded DEMO constant (a real build uses the OS
> keystore). Do not protect anything real with it yet.

### Build
```bash
cargo build --release -p pvtcoms-demo            # default = fast direct-TCP transport
cargo build --release -p pvtcoms-demo --features tor   # adds the anonymous Tor onion transport
```

### Commands
```
listen <bind-addr>            direct TCP (fast, not anonymous), always-on — serves many peers
connect <peer-addr> [msg]     direct TCP
tor-listen / tor-connect <.onion> [msg]   anonymous via Tor (needs --features tor)
whoami | contacts | history <contact> | verify <contact> | remove <contact>
```
Set `PVTCOMS_PROFILE=<name>` to keep multiple distinct identities on one machine. In-chat, type text
to send, `/file <path>` to send a file, `/help` for help.

### Two-machine / two-profile quickstart
```bash
# Terminal A (Alice listens):
PVTCOMS_PROFILE=alice ./target/release/pvtcoms-demo listen 0.0.0.0:9000
# Terminal B (Bob connects to A's LAN IP):
PVTCOMS_PROFILE=bob   ./target/release/pvtcoms-demo connect 192.168.1.50:9000 "hi alice"
```
Both print `post-quantum session established ✓`, **`verified peer identity: …`** (cross-verified), the
matching **safety emoji**, and pin each other. Type back and forth; send a file with `/file`.
Afterward: `whoami`, `contacts`, `history "<peer>"`, `verify "<peer>"`.

### Two-container quickstart (one host) — verified working
```bash
docker build -t pvtcoms-chat -f demo/Dockerfile .
docker network create pvtnet
docker run -d --name pvt-l --network pvtnet -e PVTCOMS_PROFILE=alice --entrypoint sh pvtcoms-chat \
  -c 'sleep 9 | pvtcoms-demo listen 0.0.0.0:9000'
docker run --rm --network pvtnet -e PVTCOMS_PROFILE=bob --entrypoint sh pvtcoms-chat \
  -c 'sleep 2; sleep 3 | pvtcoms-demo connect pvt-l:9000 "hi from bob"'
docker logs pvt-l    # shows: verified peer identity, pinned contact, peer> hi from bob
docker rm -f pvt-l && docker network rm pvtnet
```
Verified scenarios (container sims): cross-verified identities, contact pin → verify → enforced,
message history replay on reconnect, always-on listener serving multiple peers, and a 50 KiB file
transfer arriving with an identical SHA-256.

### Over the real internet, anonymously
`tor-listen` publishes a `.onion` (reachable anywhere, no port-forwarding, no IP exposure) and stays
warm; `tor-connect <onion>` dials it. Same chat, routed through the embedded Tor — slower to set up.
