Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 17 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@ jobs:
bash -n ./tests/acceptance/tc_stats_01.sh
bash -n ./tests/acceptance/tc_stats_02.sh
bash -n ./tests/acceptance/tc_recovery_01.sh
bash -n ./tests/acceptance/tc_recovery_05.sh
bash -n ./tests/acceptance/tc_cache_02.sh
bash -n ./tests/acceptance/tc_container_01.sh
bash -n ./tests/acceptance/tc_container_02.sh
Expand Down Expand Up @@ -598,6 +599,15 @@ jobs:
cargo build --locked --release
cargo build --locked --release --example torrentfs-selfseed-env

- name: Create the daemon user
# tc_recovery_05 drives the rootful entrypoint, which drops torrentfs
# to TORRENTFS_UID (1000); fusermount3 resolves that uid through NSS,
# and debian:sid-slim has no uid-1000 user, so the mount would fail
# with "could not determine username".
run: |
groupadd --gid 1000 torrentfs
useradd --uid 1000 --gid 1000 --home-dir /home/torrentfs --create-home --shell /bin/sh torrentfs

- name: Run acceptance FUSE cases
# Case exit codes: 0 = PASS, 1 = FAIL, 2 = SKIP (the case self-gated:
# no /dev/fuse or no fusermount3). A bare `set -e` loop would turn a
Expand All @@ -606,7 +616,7 @@ jobs:
# fuse3 and runs as root with /dev/fuse, so the passing path is real.
run: |
set -euo pipefail
for tc in tc_ingest_01 tc_ingest_03 tc_ingest_06 tc_rofs_01 tc_read_04 tc_stats_01 tc_stats_02 tc_recovery_01 tc_cache_02; do
for tc in tc_ingest_01 tc_ingest_03 tc_ingest_06 tc_rofs_01 tc_read_04 tc_stats_01 tc_stats_02 tc_recovery_01 tc_cache_02 tc_recovery_05; do
rc=0
./tests/acceptance/$tc.sh ./target/release/torrentfs "/tmp/torrentfs_acceptance_$tc" || rc=$?
if [ "$rc" -eq 2 ]; then
Expand All @@ -624,6 +634,12 @@ jobs:
- name: Run negative acceptance carrier (FUSE-dependent half)
run: cargo test --locked --release --test acceptance -- tc_negative_03 --nocapture

- name: Run acceptance recovery cases (FUSE)
# The Rust carriers skip themselves without /dev/fuse, so the plain
# `cargo test` job (no device) never executes them; this is the job
# that has the device and the capability to mount.
run: cargo test --locked --release --test acceptance -- tc_recovery_0

bindings-drift:
name: Bindings Drift (regenerate + diff)
runs-on: ubuntu-24.04
Expand Down
33 changes: 7 additions & 26 deletions ci/tests/session_recovery_e2e.sh
Original file line number Diff line number Diff line change
Expand Up @@ -107,30 +107,11 @@ fail() {
exit 1
}

# Print the FUSE connection minor (the /sys/fs/fuse/connections id) of the FUSE
# mount at $1, or nothing when the path carries no FUSE mount.
fuse_minor() {
awk -v mp="$1" '
$5 == mp {
for (i = 7; i < NF; i++) {
if ($i == "-" && $(i + 1) ~ /^fuse/) {
split($3, a, ":")
print a[2]
exit
}
}
}
' /proc/self/mountinfo
}

wait_for_fuse_mount() {
local target="$1" deadline=$((SECONDS + 30))
while [ "$SECONDS" -lt "$deadline" ]; do
[ -n "$(fuse_minor "$target")" ] && return 0
sleep 0.5
done
return 1
}
# The FUSE mount probe (mountinfo minor + bounded wait) is shared with the
# acceptance cases, so there is one parser for the kernel's mount table.
TORRENTFS_FUSE_HARNESS_LIB_ONLY=1
# shellcheck source=/dev/null
source "$ROOT_DIR/tests/acceptance/lib_fuse_harness.sh"

wait_for_data_file() {
local deadline=$((SECONDS + 60)) found=""
Expand Down Expand Up @@ -165,7 +146,7 @@ PATH="$WORK/bin:$PATH" "$ROOT_DIR/entrypoint.sh" "$MNT" \
--cache "$WORK/cache" --db "$WORK/db/metadata.db" >"$LOG" 2>&1 &
ENTRYPOINT_PID=$!

wait_for_fuse_mount "$MNT" || fail "FUSE mount at $MNT did not appear"
wait_for_fuse "$MNT" 30 || fail "FUSE mount at $MNT did not appear"
cp "$SELFSEED_OUT/selfseed.torrent" "$MNT/metadata/"
DATA_FILE="$(wait_for_data_file)" || fail "data file did not appear under $MNT/data"

Expand All @@ -186,7 +167,7 @@ if umount "$MNT" 2>/dev/null; then
fail "reader did not hold $MNT busy (a plain umount succeeded) — detach policy untested"
fi

MINOR="$(fuse_minor "$INTERNAL_MNT")"
MINOR="$(fuse_minor_at "$INTERNAL_MNT")"
[ -n "$MINOR" ] || fail "no FUSE connection found at $INTERNAL_MNT"
ABORT_FILE="/sys/fs/fuse/connections/$MINOR/abort"
echo "[session_recovery_e2e] severing the FUSE connection (minor=$MINOR)…"
Expand Down
Loading
Loading