name: manual-udp-download-completion-e2e description: Manual end-to-end verification of started -> completed peer lifecycle using tracker_client (unified) and tracker stats API. Use when contributors need to simulate a peer completing a download without running containerized qBittorrent E2E. Triggers on "manual e2e", "simulate peer completion", "udp started completed test", or "verify downloads increment manually". metadata: author: torrust version: "1.0"
Manual UDP Download-Completion E2E
Purpose
This skill verifies, manually and quickly, that a single peer transition from started to
completed updates tracker state correctly:
- seeders/leechers transition as expected
- torrent completed/download count increments
- global completed/download count increments
This workflow is a diagnostic complement to automated E2E (for example, qbittorrent_e2e_runner).
Prerequisites
Run commands from repository root.
- Tracker config:
./share/default/config/tracker.development.sqlite3.toml - UDP tracker endpoint:
127.0.0.1:6969 - Stats API endpoint:
http://127.0.0.1:1212/api/v1/stats?token=MyAccessToken
Optional (recommended for deterministic baseline):
rm -f ./storage/tracker/lib/database/sqlite3.db
1. Start tracker
In terminal A:
cargo run
Expected startup excerpt:
Loading extra configuration from default configuration file: `./share/default/config/tracker.development.sqlite3.toml` ...
... API: Started on: http://0.0.0.0:1212
... UDP TRACKER: Started on: udp://0.0.0.0:6969
2. Define test values
In terminal B:
INFO_HASH=1111111111111111111111111111111111111111
PEER_ID=ABCDEFGHIJKLMNOPQRST
TRACKER=127.0.0.1:6969
STATS_URL='http://127.0.0.1:1212/api/v1/stats?token=MyAccessToken'
3. Capture baseline
3.1 Global stats
curl -s "$STATS_URL"
Example output:
{"torrents":0,"seeders":0,"completed":0,"leechers":0,...}
3.2 Torrent-specific stats (scrape)
cargo run -q -p torrust-tracker-client --bin tracker_client -- udp scrape "$TRACKER" "$INFO_HASH"
Example output:
{
"Scrape": {
"transaction_id": -214458979,
"torrent_stats": [
{
"seeders": 0,
"completed": 0,
"leechers": 0
}
]
}
}
4. Send started announce
cargo run -q -p torrust-tracker-client --bin tracker_client -- udp announce \
"$TRACKER" "$INFO_HASH" \
--event started \
--uploaded 0 \
--downloaded 0 \
--left 1000 \
--port 6881 \
--peer-id "$PEER_ID" \
--key 1 \
--peers-wanted 0
Example output:
{
"AnnounceIpv4": {
"transaction_id": -888840697,
"announce_interval": 120,
"leechers": 1,
"seeders": 0,
"peers": []
}
}
Verify after started:
cargo run -q -p torrust-tracker-client --bin tracker_client -- udp scrape "$TRACKER" "$INFO_HASH"
curl -s "$STATS_URL"
Expected checks:
- scrape
leechersis1 - scrape
seedersis0 - global
leechersincreased by1 - global
completedunchanged
5. Send completed announce
cargo run -q -p torrust-tracker-client --bin tracker_client -- udp announce \
"$TRACKER" "$INFO_HASH" \
--event completed \
--uploaded 0 \
--downloaded 1000 \
--left 0 \
--port 6881 \
--peer-id "$PEER_ID" \
--key 1 \
--peers-wanted 0
Example output:
{
"AnnounceIpv4": {
"transaction_id": -888840697,
"announce_interval": 120,
"leechers": 0,
"seeders": 1,
"peers": []
}
}
Verify after completed:
cargo run -q -p torrust-tracker-client --bin tracker_client -- udp scrape "$TRACKER" "$INFO_HASH"
curl -s "$STATS_URL"
Expected checks:
- scrape
seederschanged0 -> 1 - scrape
completedchanged0 -> 1 - scrape
leecherschanged1 -> 0 - global
seedersincreased by1 - global
completedincreased by1
6. Optional output formatting with jq (human-friendly)
If jq is available, use these helpers:
curl -s "$STATS_URL" | jq '{torrents, seeders, completed, leechers}'
cargo run -q -p torrust-tracker-client --bin tracker_client -- udp scrape "$TRACKER" "$INFO_HASH" \
| jq '.Scrape.torrent_stats[0]'
Troubleshooting
- Peer ID must be exactly 20 bytes.
- Use a fresh
INFO_HASHto avoid contamination from previous runs. - If baseline numbers are non-zero, either reset SQLite DB or compare deltas instead of absolute values.
- Confirm tracker/API are listening on
6969/udpand1212/tcp.
Related
- Automated E2E runner:
src/bin/qbittorrent_e2e_runner.rs - Local tracker run workflow:
.github/skills/dev/environment-setup/run-tracker-locally/SKILL.md