fix: resolve hooks_cli.py merge conflict + add mine_global_lock tests
- Resolve UU conflict in hooks_cli.py: take develop/HEAD approach (mine synchronously via _mine_sync, then pass through unconditionally). _mine_sync already catches subprocess.TimeoutExpired — fixes Copilot #1. - Add tests/test_palace_locks.py: 4 tests covering mine_global_lock non-blocking semantics (acquire, second-acquire raises MineAlreadyRunning, reusable after release, release on exception) — fixes Copilot #4. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
committed by
Igor Lins e Silva
parent
91a60263e3
commit
7e18a70796
@@ -0,0 +1,59 @@
|
||||
"""Tests for mine_global_lock: non-blocking cross-process lock semantics."""
|
||||
import threading
|
||||
|
||||
import pytest
|
||||
|
||||
from mempalace.palace import MineAlreadyRunning, mine_global_lock
|
||||
|
||||
|
||||
def test_mine_global_lock_acquired(tmp_path, monkeypatch):
|
||||
"""Lock is acquired and released without error."""
|
||||
monkeypatch.setenv("HOME", str(tmp_path))
|
||||
with mine_global_lock():
|
||||
pass # should not raise
|
||||
|
||||
|
||||
def test_mine_global_lock_second_acquire_raises(tmp_path, monkeypatch):
|
||||
"""Concurrent second acquire raises MineAlreadyRunning."""
|
||||
monkeypatch.setenv("HOME", str(tmp_path))
|
||||
results: list[str] = []
|
||||
|
||||
with mine_global_lock():
|
||||
# While this lock is held, spawn a thread that tries to acquire.
|
||||
def try_acquire():
|
||||
try:
|
||||
with mine_global_lock():
|
||||
results.append("acquired")
|
||||
except MineAlreadyRunning:
|
||||
results.append("blocked")
|
||||
|
||||
t = threading.Thread(target=try_acquire)
|
||||
t.start()
|
||||
t.join(timeout=5)
|
||||
|
||||
assert results == ["blocked"]
|
||||
|
||||
|
||||
def test_mine_global_lock_reusable_after_release(tmp_path, monkeypatch):
|
||||
"""Lock can be re-acquired after the context manager exits."""
|
||||
monkeypatch.setenv("HOME", str(tmp_path))
|
||||
|
||||
with mine_global_lock():
|
||||
pass # first acquire + release
|
||||
|
||||
# Second acquire must succeed; MineAlreadyRunning would propagate as failure.
|
||||
with mine_global_lock():
|
||||
pass
|
||||
|
||||
|
||||
def test_mine_global_lock_exception_still_releases(tmp_path, monkeypatch):
|
||||
"""Lock is released even when the body raises."""
|
||||
monkeypatch.setenv("HOME", str(tmp_path))
|
||||
|
||||
with pytest.raises(ValueError):
|
||||
with mine_global_lock():
|
||||
raise ValueError("boom")
|
||||
|
||||
# Must be acquirable again after the exception.
|
||||
with mine_global_lock():
|
||||
pass
|
||||
Reference in New Issue
Block a user