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
37 changes: 20 additions & 17 deletions .github/workflows/aerorsync-protocol.yml
Original file line number Diff line number Diff line change
Expand Up @@ -83,9 +83,19 @@ jobs:
- name: cargo clippy (strict, -D warnings)
working-directory: src-tauri
run: cargo clippy --lib --features aerorsync --all-targets -- -D warnings
# `aerorsync` is a substring filter over the whole lib, which is the shape
# that prints "test result: ok" and exits 0 when it matches nothing: rename
# the module and this step passes having compiled the crate and run no
# test. 677 is what it executes today (692 selected, 15 of them ignored,
# measured on run 33436715702 and reproduced locally); a floor, because the
# module is meant to grow.
- name: Mock + unit test suite
working-directory: src-tauri
run: cargo test --features aerorsync --lib aerorsync
run: |
set -o pipefail
cargo test --features aerorsync --lib aerorsync | tee /tmp/aerorsync-unit.log
../scripts/assert-tests-ran.sh /tmp/aerorsync-unit.log 677 \
"aerorsync mock + unit suite"
- name: Default build regression (feature off)
working-directory: src-tauri
run: cargo check --no-default-features --lib
Expand Down Expand Up @@ -252,6 +262,7 @@ jobs:
# All filters go after `--`: cargo itself takes a single
# positional TESTNAME, libtest ORs multiple filters.
run: |
set -o pipefail
cargo test --features aerorsync --lib -- \
aerorsync::native_driver::tests::driver_upload_live_lane_3_real_rsync_byte_identical \
aerorsync::native_driver::tests::driver_upload_streaming_live_lane_3_real_rsync_byte_identical \
Expand All @@ -268,7 +279,9 @@ jobs:
aerorsync::delta_transport_impl::tests::delta_upload_symlink_xattr_not_inherited_live_lane_3 \
aerorsync::delta_transport_impl::tests::delta_upload_acl_named_user_live_lane_3 \
aerorsync::delta_transport_impl::tests::delta_download_acl_named_user_live_lane_3 \
--nocapture
--nocapture | tee /tmp/aerorsync-lane3.log
../scripts/assert-tests-ran.sh /tmp/aerorsync-lane3.log 15 \
"lane 3 live tests"
# The RSNP_TEST_REAL lane: eight #[ignore] tests that drive the
# production AerorsyncDeltaTransport upload and download paths against
# the same stock rsync, with each negotiated checksum forced in turn
Expand Down Expand Up @@ -328,25 +341,15 @@ jobs:
# would turn this lane green having executed NOTHING, and the second one
# looks like an improvement while doing it. `set -o pipefail` matters for
# the same reason: without it the exit status would be tee's, not cargo's.
# The check itself now lives in scripts/assert-tests-ran.sh, which is
# where the shell subtleties it needs are written down once instead of
# once per lane.
run: |
set -o pipefail
cargo test --features aerorsync --lib aerorsync::live_tests -- \
--ignored --nocapture --test-threads=1 | tee /tmp/aerorsync-live.log
# `|| true` is load-bearing: GitHub runs a step with no `shell:` as
# `bash -e {0}`, and under -e an assignment from a pipeline that
# matches nothing ends the script right here, silently. The check
# would still fail, but with no message, which is the exact shape
# this step exists to remove. `shell: bash` does NOT fix it: that is
# `bash -eo pipefail`, so -e is still on.
ran=$(grep -oE '^test result: ok\. [0-9]+ passed' /tmp/aerorsync-live.log \
| grep -oE '[0-9]+' | head -1 || true)
echo "aerorsync live tests executed: ${ran:-none}"
if [ -z "${ran}" ] || [ "${ran}" -lt 8 ]; then
echo "::error::this lane executed ${ran:-0} live tests, expected at least 8."
echo "::error::a green here with fewer tests means the filter stopped matching,"
echo "::error::not that the protocol got simpler. Fix the filter, not this check."
exit 1
fi
../scripts/assert-tests-ran.sh /tmp/aerorsync-live.log 8 \
"aerorsync live checksum-matrix tests"
- name: Tear down harness
if: always()
working-directory: src-tauri/src/aerorsync/capture
Expand Down
47 changes: 41 additions & 6 deletions .github/workflows/delta-sync-integration.yml
Original file line number Diff line number Diff line change
Expand Up @@ -205,27 +205,48 @@ jobs:
- name: "Unit tests: delta-sync modules"
timeout-minutes: 25
working-directory: src-tauri
# Five module filters, so a module renamed on one side and not here
# silently narrows what this lane covers, down to nothing in the limit.
# 94 is what the five select today (measured on run 33434171154); it is
# a floor and not a count, because these modules are meant to grow.
run: |
set -o pipefail
cargo test --lib --no-fail-fast -- \
rsync_output:: \
rsync_over_ssh:: \
ssh_exec:: \
delta_transport:: \
delta_sync_rsync::
delta_sync_rsync:: | tee /tmp/delta-unit.log
../scripts/assert-tests-ran.sh /tmp/delta-unit.log 94 \
"delta-sync module unit tests"

# Measured at 3m55s and 4m04s.
- name: "Integration test: delta sync over SSH"
timeout-minutes: 15
working-directory: src-tauri
run: cargo test --test integration_delta_sync -- --ignored --nocapture
# 12 is the ignored set of this binary today. Selecting with `--ignored`
# means removing those attributes empties the lane, so the count is what
# separates "the fixture proved the round-trip" from "nothing ran".
run: |
set -o pipefail
cargo test --test integration_delta_sync -- --ignored --nocapture \
| tee /tmp/delta-integration.log
../scripts/assert-tests-ran.sh /tmp/delta-integration.log 12 \
"delta sync over SSH"

- name: Product-path native delta preserves ACL and xattr
timeout-minutes: 10
working-directory: src-tauri
# `--exact` on one name: the tightest possible filter and therefore the
# one that most easily matches nothing after a rename, with no signal
# that it did. Exactly one, because this step promises one named test.
run: |
set -o pipefail
cargo test --test integration_delta_sync \
product_path_native_delta_preserves_acl_and_xattr -- \
--ignored --nocapture --exact
--ignored --nocapture --exact | tee /tmp/delta-acl-xattr.log
../scripts/assert-tests-ran.sh /tmp/delta-acl-xattr.log =1 \
"Product-path ACL and xattr"

- name: Dump fixture logs on failure
if: failure()
Expand Down Expand Up @@ -369,20 +390,34 @@ jobs:
# here too so a change that breaks the string contract without
# touching the key-auth lane's paths is still caught.
run: |
set -o pipefail
cargo test --test integration_delta_sync -- \
hard_rejection_string_contract_is_pinned_offline \
hard_error_branch_runs_before_classic_fallback_in_bivio \
--nocapture
--nocapture | tee /tmp/delta-hard-rejection.log
../scripts/assert-tests-ran.sh /tmp/delta-hard-rejection.log 2 \
"Offline hard-rejection contract"

# Measured at 3m51s and 4m15s.
#
# The test named here was `product_path_falls_through_silently_when_
# session_not_eligible` until 2026-05-16, when making password-backed
# SFTP eligible for the native leg (host key pinned) inverted what it
# asserts and it was renamed. This line was not updated, so from that day
# the job built the password-only fixture, ran ZERO tests, printed
# "test result: ok" and reported success: 0 executed on run 33434171154,
# which is what the assertion below now makes impossible.
- name: "Fallback integration test: password-only fixture"
timeout-minutes: 15
working-directory: src-tauri
run: |
set -o pipefail
cargo test --test integration_delta_sync -- \
--ignored \
product_path_falls_through_silently_when_session_not_eligible \
--nocapture
product_path_uses_native_delta_for_password_sftp_with_pinned_host_key \
--nocapture | tee /tmp/delta-fallback.log
../scripts/assert-tests-ran.sh /tmp/delta-fallback.log =1 \
"Password-only fixture contract"

- name: Dump fixture logs on failure
if: failure()
Expand Down
27 changes: 16 additions & 11 deletions .github/workflows/ftp-mlsd.yml
Original file line number Diff line number Diff line change
Expand Up @@ -144,10 +144,21 @@ jobs:
# 15 minutes is a warm-cache figure. The first run on a branch compiles
# the Tauri crate from nothing, and a cap that bites once and never again
# reads as an infrastructure problem rather than as a wrong number.
#
# The count is asserted for the reason this whole file exists: the two
# tests are selected with `--ignored`, so the day somebody removes those
# attributes to make them run more often, this lane selects NOTHING,
# prints "test result: ok" and stays green while covering nothing. Two,
# not "exactly two", because the binary is a module meant to grow.
- name: Listing tests against an MLSD server
timeout-minutes: 40
working-directory: src-tauri
run: cargo test --test integration_ftp_mlsd -- --ignored --nocapture
run: |
set -o pipefail
cargo test --test integration_ftp_mlsd -- --ignored --nocapture \
| tee /tmp/ftp-mlsd-listing.log
../scripts/assert-tests-ran.sh /tmp/ftp-mlsd-listing.log 2 \
"MLSD listing tests"

- name: Dump fixture logs on failure
if: failure()
Expand Down Expand Up @@ -264,23 +275,17 @@ jobs:
# that prints "test result: ok" and exits 0 when the filter matches
# nothing. Exactly one, not "at least one": this step promises to run one
# named test, so a second arriving here is a change to what the job does
# and should be said out loud. The sibling aerorsync lane uses `-lt`
# instead, and correctly: it collects a whole module, which may grow.
# and should be said out loud. The sibling aerorsync lane asks for "at
# least", and correctly: it collects a whole module, which may grow.
- name: The session must not survive a timed-out listing
timeout-minutes: 40
working-directory: src-tauri
run: |
set -o pipefail
cargo test --lib providers::ftp::live_listing_timeout -- \
--ignored --nocapture | tee /tmp/listing-timeout.log
ran=$(grep -oE '^test result: ok\. [0-9]+ passed' /tmp/listing-timeout.log \
| grep -oE '[0-9]+' | head -1 || true)
echo "live listing-timeout tests executed: ${ran:-none}"
if [ "${ran:-0}" -ne 1 ]; then
echo "::error::expected exactly 1 test, ran ${ran:-0}: the filter stopped matching,"
echo "::error::which is a green that executed nothing. Fix the filter, not this check."
exit 1
fi
../scripts/assert-tests-ran.sh /tmp/listing-timeout.log =1 \
"Listing-timeout guard"

- name: Fixture log on failure
if: failure()
Expand Down
26 changes: 23 additions & 3 deletions .github/workflows/nightly-telemetry.yml
Original file line number Diff line number Diff line change
Expand Up @@ -65,18 +65,38 @@ jobs:
# transfer_dag_single_file, transfer_dag_sync and the adaptive /
# metrics / engine_stats / ttfb / executor / work_source telemetry
# modules under transfer_dag::.
run: cargo test --lib transfer_dag -- --nocapture
# 358 today (run 33377726369). A substring filter that stops matching
# reports "ok" over an empty run, and a nightly nobody watches is exactly
# where that goes unnoticed.
run: |
set -o pipefail
cargo test --lib transfer_dag -- --nocapture | tee /tmp/telemetry-dag.log
../scripts/assert-tests-ran.sh /tmp/telemetry-dag.log 358 \
"DAG telemetry suites"

- name: Process resource sampler suite
working-directory: ./src-tauri
run: cargo test --lib proc_stats -- --nocapture
run: |
set -o pipefail
cargo test --lib proc_stats -- --nocapture | tee /tmp/telemetry-proc.log
../scripts/assert-tests-ran.sh /tmp/telemetry-proc.log 9 \
"Process resource sampler suite"

- name: Local telemetry benchmark cell (emits JSON)
working-directory: ./src-tauri
env:
AEROFTP_TELEMETRY_JSON: ${{ github.workspace }}/telemetry-nightly.json
AEROFTP_TELEMETRY_BYTES: '16777216'
run: cargo test --test telemetry_nightly -- --ignored --nocapture
# The artifact upload below has `if-no-files-found: error`, which catches
# a cell that ran and wrote nothing. It cannot catch a cell that never
# ran: `--ignored` selecting nothing prints "ok" and writes no JSON, and
# the two failures would then be told apart only by reading the log.
run: |
set -o pipefail
cargo test --test telemetry_nightly -- --ignored --nocapture \
| tee /tmp/telemetry-cell.log
../scripts/assert-tests-ran.sh /tmp/telemetry-cell.log 1 \
"Local telemetry benchmark cell"

- name: Upload telemetry metrics artifact
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
Expand Down
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,9 @@ run-clean.sh
!/scripts/i18n-untranslated-accepted.json
# Exception: single pre-release smoke entrypoint (`npm run smoke`, #408 row 1)
!/scripts/smoke.mjs
# Exception: asserts a CI lane actually executed the tests it selects, called by
# ftp-mlsd, delta-sync-integration, aerorsync-protocol and nightly-telemetry
!/scripts/assert-tests-ran.sh

# Security reports: keep latest snapshot in repo, ignore dated copies
/docs/security/security-report-20*.html
Expand Down
98 changes: 98 additions & 0 deletions scripts/assert-tests-ran.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
#!/usr/bin/env bash
# SPDX-License-Identifier: GPL-3.0-or-later
# Copyright (c) 2024-2026 axpnet: AI-assisted (see AI-TRANSPARENCY.md)
#
# Fail a CI lane that selected no tests, or fewer than it promises to run.
#
# `cargo test` with a filter that matches nothing prints "running 0 tests",
# then "test result: ok." and exits 0. A green lane that executed nothing is
# indistinguishable, from outside, from a green lane that proved something.
# The two ways it happens in practice are a rename nobody propagated to the
# workflow, and somebody removing `#[ignore]` from the tests a lane selects
# with `--ignored`, which switches the lane off while looking like an
# improvement. Neither is hypothetical: the password-only fallback lane in
# delta-sync-integration.yml stood up a Docker fixture and ran zero tests
# from 2026-05-16, when its test was renamed, until this script landed.
#
# Usage:
# assert-tests-ran.sh <log> <count> <what> at least <count> tests ran
# assert-tests-ran.sh <log> =<count> <what> exactly <count> tests ran
#
# `=<count>` is for a step that names ONE test: a second test arriving there
# changes what the step does and should be said out loud. A step that collects
# a whole module or binary takes the plain form, because such a suite is meant
# to grow and an exact match would turn the lane red on the day someone adds a
# legitimate test, which usually gets answered by deleting the check.
#
# The counted number is what libtest REPORTS as passed, summed over every test
# binary in the log, not what the filter looks like it should select. The
# caller pipes cargo through `tee` and must `set -o pipefail` first, or the
# step's status is tee's rather than cargo's, which is the same blindness this
# script exists to remove.
#
# No `set -e` here on purpose: every failure path below ends in an explicit
# exit with a message. `-u` catches a caller that forgot an argument, and
# `-o pipefail` makes the count pipeline honest.
set -uo pipefail

if [ "$#" -ne 3 ]; then
echo "::error::assert-tests-ran.sh needs <log> <count|=count> <what>, got $# argument(s)"
exit 2
fi

log=$1
want=$2
what=$3

case "$want" in
"="*)
exact=1
expected=${want#=}
;;
*)
exact=0
expected=$want
;;
esac

case "$expected" in
'' | *[!0-9]*)
echo "::error::assert-tests-ran.sh: '$want' is not a count"
exit 2
;;
esac

if [ ! -s "$log" ]; then
# An empty or missing log is not "zero tests": it is a run that died before
# libtest printed anything, and it must not be reported as a count.
echo "::error::${what}: no test output at ${log}. cargo produced nothing to count,"
echo "::error::so the step ran no tests and this is not a pass."
exit 1
fi

# Sum every binary's result line: a step may run more than one. A FAILED line
# does not match, which is correct, because a failing run has already taken the
# step down through pipefail before this script is reached.
ran=$(grep -oE '^test result: ok\. [0-9]+ passed' "$log" \
| grep -oE '[0-9]+' \
| awk '{ s += $1 } END { print s + 0 }')

if [ "$exact" -eq 1 ]; then
if [ "$ran" -ne "$expected" ]; then
echo "::error::${what}: executed ${ran} test(s), expected exactly ${expected}."
echo "::error::Either the filter stopped matching, which is a green that proved"
echo "::error::nothing, or the step now runs more than the one test it names."
echo "::error::Fix the filter or say the new number here, do not delete this check."
exit 1
fi
else
if [ "$ran" -lt "$expected" ]; then
echo "::error::${what}: executed ${ran} test(s), expected at least ${expected}."
echo "::error::A green here with fewer tests means the selection stopped matching,"
echo "::error::not that the work got simpler. Fix the filter, not this check; and"
echo "::error::if tests were deliberately removed, lower the number in that commit."
exit 1
fi
fi

echo "${what}: ${ran} test(s) executed (expected ${want})."
18 changes: 17 additions & 1 deletion src-tauri/src/aerorsync/capture/run_deflate_rsync_capture.sh
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,16 @@ stop_stack() {
fi
}

# `mktemp`, not a fixed name under /tmp. This harness runs on developer
# machines as well as on a CI runner, /tmp is world-writable and shared there,
# and a predictable path is one another local user can pre-create as a symlink
# for `tee` to follow into a file this user can write (CWE-377). The template
# carries the directory explicitly so the line behaves the same under GNU and
# BSD mktemp.
ORACLE_LOG="$(mktemp "${TMPDIR:-/tmp}/aerorsync-deflate-oracle.XXXXXX")"

cleanup() {
rm -f "$ORACLE_LOG"
if [[ "$KEEP_STACK" != "1" ]]; then
stop_stack
fi
Expand Down Expand Up @@ -292,11 +301,18 @@ EOF

echo "[deflate-harness] checking captured tokens with AeroRsync real_wire"
(
# The header above promises this harness rules out "zero tests", and every
# guard it lists is on the capture, not on this run: the oracle is selected
# by name over the ignored set, so a rename or a dropped `#[ignore]` leaves
# `cargo test` printing "test result: ok" over an empty run and the harness
# declaring the byte oracle checked. One named test, so exactly one.
cd "$SRC_TAURI_DIR"
AEROFTP_DEFLATE_CAPTURE="$DEST_DIR" \
cargo test --features aerorsync --lib \
rsync_3_1_3_deflate_byte_oracle_matches_real_wire_decoder -- \
--ignored --nocapture
--ignored --nocapture | tee "$ORACLE_LOG"
../scripts/assert-tests-ran.sh "$ORACLE_LOG" =1 \
"rsync 3.1.3 deflate byte oracle"
)

echo "[deflate-harness] byte oracle written to $DEST_DIR"
Loading
Loading