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
5 changes: 5 additions & 0 deletions docs/src/content/docs/contributing/integration-testing.md
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,11 @@ serialized dependency paths with `Path.as_posix()`. For `deployed_file_hashes`,
use `compute_file_hash`, which canonicalizes text CRLF; package-tree integrity
continues to hash raw bytes.

Concurrent fixtures must await every worker before inspecting shared results or
cleaning up resources. Submit both consumers before collecting their futures;
`Thread.join(timeout=...)` can return while a worker is still running. Keep real
parallel materialization and content assertions in cache regression tests.

When adding a registered architecture-owner guard, add its surgical mutation
to `test_architecture_owner_rule_mutations.py` in the same change. The matrix
requires exactly one mutation for every registered guard.
Expand Down
12 changes: 6 additions & 6 deletions tests/unit/deps/test_shared_clone_cache.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

import logging
import threading
from concurrent.futures import ThreadPoolExecutor
from pathlib import Path
from unittest.mock import MagicMock, patch

Expand Down Expand Up @@ -455,6 +456,7 @@ def _make_bare_repo(path: Path) -> None:
class TestBareCacheRaceCondition:
"""6.1: regression test for the parallel sparse-checkout race (#1126)."""

@pytest.mark.windows_compat
def test_parallel_different_subdirs_both_succeed(self, tmp_path: Path) -> None:
"""Two threads request same key, then extract different subdirs from
the shared bare. Both must succeed (the v1 race lost one thread's
Expand Down Expand Up @@ -537,12 +539,10 @@ def thread_b() -> None:
except Exception as e:
results["errors"].append(("b", e))

ta = threading.Thread(target=thread_a)
tb = threading.Thread(target=thread_b)
ta.start()
tb.start()
ta.join(timeout=10)
tb.join(timeout=10)
with ThreadPoolExecutor(max_workers=2) as executor:
futures = [executor.submit(thread_a), executor.submit(thread_b)]
for future in futures:
future.result()

assert results["errors"] == [], f"Errors: {results['errors']}"
assert "X" in results["subdirs_seen"]
Expand Down
Loading