ci: address review — use --dist=load, per-module teardown, exclude setpriv
CI / lint (pull_request) Failing after 0s
CI / build-and-test (pull_request) Skipped
CI / sanitizers (address) (pull_request) Skipped
CI / sanitizers (undefined) (pull_request) Skipped
CI / fuzz-build (pull_request) Skipped
CI / coverage (pull_request) Skipped
CI / valgrind (pull_request) Skipped

- Replace --dist=loadgroup (a no-op: it only groups by xdist_group marks) with
  --dist=load, and make module teardowns remove only their own SOURCE_DIR/DEST_DIR
  (never the shared worker-keyed TEST_DATA_DIR) so interleaved modules can't wipe
  each other's fixtures. Add a session-scoped cleanup of the per-worker dir.
  (loadfile grouped the whole test_features.py module onto one worker and slowed
  the full suite to 761s vs 224s with load.)
- Mark the two setpriv privilege tests with a 'setpriv' marker and run the full
  merge suite as -m "not setpriv", so the dev/main gate can't go red on the
  env-dependent /root-traversal tests regardless of the runner uid.
- Add a TLS basic test to the ci subset, add workflow_dispatch for on-demand full
  runs, and fix trailing newlines.
- Measured: smoke -m ci = 28 passed/39s; full -n4 = 280 passed/11 skipped/1 xpassed
  in 224s (was 860s serial).
This commit is contained in:
2026-09-08 17:25:56 +02:00
parent 79d965ac11
commit c90b07afcb
8 changed files with 43 additions and 15 deletions
+16 -2
View File
@@ -1,17 +1,31 @@
"""Shared pytest configuration for integration tests."""
import os
import shutil
import sys
import pytest
sys.path.insert(0, os.path.join(os.path.dirname(__file__), "integration"))
from common import ServerManager
from common import ServerManager, TEST_DATA_DIR
@pytest.fixture(scope="session")
def shared_server():
"""One server for the entire test session. Avoids 27+ server start/stop cycles."""
"""One server for the entire test session. Avoids 27+ server start/stop cycles.
Under pytest-xdist this session fixture is instantiated once per worker
process, so each worker gets its own server on an ephemeral port."""
server = ServerManager()
server.start()
yield server
server.stop()
@pytest.fixture(scope="session", autouse=True)
def _cleanup_worker_test_data():
"""Remove this (worker-keyed) TEST_DATA_DIR at the end of the session.
Modules clean only their own rows; this final pass ensures the per-worker
directory never lingers in the working tree."""
yield
shutil.rmtree(TEST_DATA_DIR, ignore_errors=True)
+7 -1
View File
@@ -25,7 +25,11 @@ def setup_test_data():
generate_test_files(SOURCE_DIR, full=False)
clean_dir(DEST_DIR)
yield
shutil.rmtree(TEST_DATA_DIR, ignore_errors=True)
# Remove only this module's own dirs. Under pytest-xdist the whole
# (worker-keyed) TEST_DATA_DIR is shared with concurrently-interleaved
# modules, so never rmtree it here.
shutil.rmtree(SOURCE_DIR, ignore_errors=True)
shutil.rmtree(DEST_DIR, ignore_errors=True)
class TestDryRun:
@@ -2855,6 +2859,7 @@ class TestDeletePolicy:
"--clear-groups"] + cmd, text=True, capture_output=True)
@pytest.mark.parametrize("mt", [False, True])
@pytest.mark.setpriv
def test_ignore_errors_keeps_deletion_active_on_scan_error(self, mt):
"""A source I/O error (unreadable subdirectory) aborts the run so no
deletion happens by default; --ignore-errors continues, still transfers
@@ -2901,6 +2906,7 @@ class TestDeletePolicy:
@pytest.mark.parametrize("mt", [False, True])
@pytest.mark.parametrize("timing", ["--delete", "--delete-before"])
@pytest.mark.setpriv
def test_ignore_errors_unreadable_root_never_deletes(self, mt, timing):
"""An unreadable SOURCE ROOT must never be treated as a skippable scan
error: with --ignore-errors the sequential scanner treats the root as
+2 -1
View File
@@ -60,7 +60,8 @@ def setup_test_data():
generate_test_files(SOURCE_DIR, full=False)
clean_dir(DEST_DIR)
yield
shutil.rmtree(TEST_DATA_DIR, ignore_errors=True)
shutil.rmtree(SOURCE_DIR, ignore_errors=True)
shutil.rmtree(DEST_DIR, ignore_errors=True)
def _run_ssh_test(name, flags, expected_missing=None):
+2 -1
View File
@@ -21,7 +21,8 @@ def setup_test_data():
generate_test_files(SOURCE_DIR, full=False)
clean_dir(DEST_DIR)
yield
shutil.rmtree(TEST_DATA_DIR, ignore_errors=True)
shutil.rmtree(SOURCE_DIR, ignore_errors=True)
shutil.rmtree(DEST_DIR, ignore_errors=True)
def _run_tcp_test(name, port, flags, use_metadata=True, posix=False):
+3 -1
View File
@@ -92,10 +92,12 @@ def setup_test_data():
generate_test_files(SOURCE_DIR, full=False)
clean_dir(DEST_DIR)
yield
shutil.rmtree(TEST_DATA_DIR, ignore_errors=True)
shutil.rmtree(SOURCE_DIR, ignore_errors=True)
shutil.rmtree(DEST_DIR, ignore_errors=True)
class TestTLSBasic:
@pytest.mark.ci
def test_tls_server_client(self, certs):
"""Basic TLS: server with cert/key, client with cert/key + CA."""
clean_dir(DEST_DIR)