"""维护入口使用同一owner,只有明确盘点范围可进入缓存候选。""" import json from contextlib import contextmanager from types import SimpleNamespace import pytest from muse.共享.错误 import 配置错误 from muse.接入.cli.回收命令 import _缓存保护, 运行回收命令 @pytest.mark.case_id("NC-retention-cli-raw-owner") def test_原文预览和具名执行传递配置作者与原请求(tmp_path): 调用 = [] 原文 = SimpleNamespace( 发现到期清理候选=lambda actor, **args: 调用.append((actor, args)) or {"items": []}, 执行到期清理=lambda actor, plan: 调用.append((actor, plan)) or {"receipt_id": "r"}, ) 装配 = SimpleNamespace( 配置=SimpleNamespace(HTTP=SimpleNamespace(作者ID="configured-author")), 要求原文=lambda: 原文, ) request = tmp_path / "request.json" request.write_text(json.dumps({"as_of": "2026-09-17T00:00:00+00:00", "limit": 3})) assert 运行回收命令(装配, "原文回收预览", str(request)) == {"items": []} assert 调用[0][0] == "configured-author" and 调用[0][1]["上限"] == 3 plan = {"lease_id": "known-lease"} request.write_text(json.dumps(plan)) assert 运行回收命令(装配, "原文回收执行", str(request)) == {"receipt_id": "r"} assert 调用[1] == ("configured-author", plan) @pytest.mark.case_id("NC-retention-cli-root-boundary") def test_发布缓存不得包含或复用备份根(tmp_path): request = tmp_path / "request.json" request.write_text( json.dumps( {"cache_root": str(tmp_path), "reference_inventory": str(tmp_path / "inventory")} ) ) 配置 = SimpleNamespace( HTTP=None, 原文暂存=None, 探索草稿=None, 备份目录=str(tmp_path / "backup") ) with pytest.raises(配置错误, match="不能包含"): 运行回收命令(SimpleNamespace(配置=配置), "发布缓存预览", str(request)) @pytest.mark.case_id("NC-retention-cli-authoritative-references") def test_声明盘点仍合入实际两用途任务与当前构建(tmp_path, monkeypatch): 记录 = [] class 连接: def __enter__(self): return self def __exit__(self, *args): pass @contextmanager def transaction(self): yield def execute(self, query): text = query.as_string() if hasattr(query, "as_string") else query 记录.append(text) if "evaluation" in text: rows = [("evaluation-in-use",)] else: rows = [("production-in-use",)] return SimpleNamespace(fetchall=lambda: rows) from muse.共享.调用身份 import 用途 from muse.接入.cli import 回收命令 as 命令模块 monkeypatch.setattr( 命令模块, "数据库工厂", lambda *a: SimpleNamespace(用途=用途.维护, 连接=连接) ) 配置 = SimpleNamespace( 资源发布身份="current-build", 备份目录=None, 数据库=None, 运行用途=用途.维护 ) 装配 = SimpleNamespace(配置=配置, 要求数据库=lambda: SimpleNamespace(连接=连接)) request = tmp_path / "inventory.json" request.write_text( json.dumps( { "scope": str(tmp_path), "complete": True, "running_build_ids": ["another-process"], "backup_build_ids": ["backup-needed"], } ) ) with _缓存保护(装配, request, tmp_path, 执行=True) as protection: assert protection["complete"] is True assert protection["build_ids"] == [ "another-process", "backup-needed", "current-build", "evaluation-in-use", "production-in-use", ] assert sum("LOCK TABLE" in text for text in 记录) == 2 记录.clear() with _缓存保护(装配, request, tmp_path, 执行=False): pass assert not any("LOCK TABLE" in text for text in 记录)