Files
Michel de Graaf 3ef78c6de1 refactor(tests): share one soulfind fixture across the e2e suites
The TUI suite had grown its own copy of the soulfind spawner the protocol
suite already carried, and its own copy of the CLI suite's in-process
client and settle helpers. All four suites now spawn, log in, settle and
skip through `tests/common`: the CLI suite's own server goes too, and
the fixture checks its child is still alive before calling the port
answered, so a lost port cannot pass another server off as ours.
2026-09-08 13:12:12 +02:00

182 lines
5.6 KiB
YAML

name: CI
# Branch pushes are covered by the pull_request trigger. Listening to both for
# every branch ran the whole matrix twice per PR.
on:
push:
branches: [master]
paths-ignore: ['website/**']
pull_request:
branches: ['**']
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: ${{ github.ref != 'refs/heads/master' }}
env:
CARGO_TERM_COLOR: always
RUST_BACKTRACE: 1
jobs:
lint:
name: Lint
timeout-minutes: 10
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup Rust
uses: dtolnay/rust-toolchain@stable
with:
components: clippy
- uses: Swatinem/rust-cache@v2
- name: Run clippy
run: cargo clippy --workspace --all-targets --all-features -- -D warnings
format:
name: Format Check
timeout-minutes: 5
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup Rust
uses: dtolnay/rust-toolchain@stable
with:
components: rustfmt
- name: Check formatting
run: cargo fmt --all -- --check
test:
name: Test
timeout-minutes: 20
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-latest, macos-latest, windows-latest]
rust: [stable]
steps:
- uses: actions/checkout@v4
- name: Setup Rust
uses: dtolnay/rust-toolchain@master
with:
toolchain: ${{ matrix.rust }}
- uses: Swatinem/rust-cache@v2
- name: Run tests
run: cargo test --verbose
e2e:
name: End-to-end (soulfind)
# The CLI suite runs twice (own login + against a daemon), ~8 minutes per
# pass, plus the library and protocol suites and a soulfind build.
timeout-minutes: 30
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup Rust
uses: dtolnay/rust-toolchain@stable
- uses: Swatinem/rust-cache@v2
- name: Install SQLite runtime/dev libraries
run: sudo apt-get update && sudo apt-get install -y libsqlite3-dev
- name: Install D toolchain (LDC)
uses: dlang-community/setup-dlang@v2
with:
compiler: ldc-latest
- name: Build soulfind server
run: |
git clone --depth 1 https://github.com/soulfind-dev/soulfind.git soulfind
dub build :server --root soulfind
test -x soulfind/bin/soulfind
echo "SOULFIND_BIN=$PWD/soulfind/bin/soulfind" >> "$GITHUB_ENV"
- name: Run library e2e tests (required against soulfind)
env:
SOULSEEK_E2E_REQUIRED: "1"
run: cargo test -p soulseek-rs-lib --test e2e -- --nocapture
- name: Run CLI e2e tests (required against soulfind)
env:
SOULSEEK_E2E_REQUIRED: "1"
run: cargo test -p soulseek-rs --test cli_e2e -- --nocapture
# The window over a real session: keys in, a screen out, a peer on the
# other end. Nothing else opens the TUI against a server.
- name: Run TUI e2e tests (required against soulfind)
env:
SOULSEEK_E2E_REQUIRED: "1"
run: cargo test -p soulseek-rs --test tui_e2e -- --nocapture
# The control protocol as a third party meets it: the TCP transport, the
# token, and the gate. None of it is reachable through the command
# surface, so the CLI suite cannot cover it in either mode.
- name: Run daemon protocol e2e tests (required against soulfind)
env:
SOULSEEK_E2E_REQUIRED: "1"
run: cargo test -p soulseek-rs --test daemon_protocol_e2e -- --nocapture --test-threads=1
# The same suite again, with every session served by a daemon instead of
# the command's own login. Identical records and exit codes both ways is
# what makes daemon mode a routing decision rather than a second
# implementation to keep in step.
- name: Run CLI e2e tests against a daemon
env:
SOULSEEK_E2E_REQUIRED: "1"
SOULSEEK_E2E_MODE: daemon
run: cargo test -p soulseek-rs --test cli_e2e -- --nocapture --test-threads=1
# A mixed load of mock peers around one real client. Every ceiling this
# project has hit only showed under simultaneous searches, downloads,
# uploads and browses, and three of the four lost work silently, so the
# gate is the functional dimensions at 100%, never the throughput number.
stress:
name: Stress (soulfind)
timeout-minutes: 20
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup Rust
uses: dtolnay/rust-toolchain@stable
- uses: Swatinem/rust-cache@v2
- name: Install SQLite runtime/dev libraries
run: sudo apt-get update && sudo apt-get install -y libsqlite3-dev
- name: Install D toolchain (LDC)
uses: dlang-community/setup-dlang@v2
with:
compiler: ldc-latest
- name: Build soulfind server
run: |
git clone --depth 1 https://github.com/soulfind-dev/soulfind.git soulfind
dub build :server --root soulfind
test -x soulfind/bin/soulfind
echo "SOULFIND_BIN=$PWD/soulfind/bin/soulfind" >> "$GITHUB_ENV"
# An eighth of the local profile: soulfind on a four-core runner brings
# about 150 mock logins online, and the point is lost work, not load.
- name: Run the stress benchmark with the functional gate
env:
STRESS_REQUIRE_FUNCTIONAL: "1"
STRESS_PEERS: "128"
STRESS_SEARCHES: "32"
STRESS_DOWNLOADS: "128"
STRESS_LEECHERS: "64"
STRESS_BROWSES: "32"
run: |
ulimit -n 20000
cargo run --release -p soulseek-rs-lib --example stress