oclaw/tests/test_paths_db_migration.py
oliver ba3836f00f 初始化:独立 oclaw 仓库首提交
- 在 oclaw/ 下重新初始化 Git 仓库
- 补齐子仓库 .gitignore,避免提交本地运行态数据(_local、node_modules、logs 等)
- 提交当前工程代码与配置

Made-with: Cursor
2026-04-24 22:31:22 +08:00

66 lines
2.9 KiB
Python

"""Regression: default DB migration must not overwrite canonical DB when session count drops after deletes."""
from __future__ import annotations
from pathlib import Path
from unittest.mock import patch
import oclaw.platform.config.paths as paths_mod
def _legacy_dir(tmp_path: Path) -> Path:
d = tmp_path / "src" / "platform" / "data"
d.mkdir(parents=True)
return d
def test_no_overwrite_when_legacy_has_more_sessions_than_canonical(tmp_path, monkeypatch) -> None:
"""Previously leg_n > can_n triggered a full replace — wrong after user deletes sessions."""
leg_root = _legacy_dir(tmp_path)
monkeypatch.setattr(paths_mod, "PROJECT_ROOT", tmp_path)
canonical = tmp_path / "oclaw" / "data" / "ai_ops.sqlite"
canonical.parent.mkdir(parents=True)
canonical.write_text("current_db", encoding="utf-8")
legacy = leg_root / "ai_ops.sqlite"
legacy.write_text("stale_db", encoding="utf-8")
monkeypatch.delenv("OPS_LEGACY_DB_FORCE_PREMERGE", raising=False)
with patch.object(paths_mod, "_copy_sqlite_bundle") as cp:
with patch.object(paths_mod, "_sqlite_chat_session_count", side_effect=[50, 2]):
paths_mod._run_default_data_migration(canonical.resolve())
cp.assert_not_called()
assert canonical.read_text(encoding="utf-8") == "current_db"
def test_force_premerege_still_overwrites_when_opt_in(tmp_path, monkeypatch) -> None:
leg_root = _legacy_dir(tmp_path)
monkeypatch.setattr(paths_mod, "PROJECT_ROOT", tmp_path)
canonical = tmp_path / "oclaw" / "data" / "ai_ops.sqlite"
canonical.parent.mkdir(parents=True)
canonical.write_text("current_db", encoding="utf-8")
legacy = leg_root / "ai_ops.sqlite"
legacy.write_text("stale_db", encoding="utf-8")
monkeypatch.setenv("OPS_LEGACY_DB_FORCE_PREMERGE", "1")
with patch.object(paths_mod, "_backup_sqlite_bundle_copy"):
with patch.object(paths_mod, "_checkpoint_wal_best_effort"):
with patch.object(paths_mod, "_copy_sqlite_bundle") as cp:
with patch.object(paths_mod, "_sqlite_chat_session_count", side_effect=[50, 2]):
paths_mod._run_default_data_migration(canonical.resolve())
cp.assert_called_once()
def test_seed_from_legacy_when_canonical_missing(tmp_path, monkeypatch) -> None:
leg_root = _legacy_dir(tmp_path)
monkeypatch.setattr(paths_mod, "PROJECT_ROOT", tmp_path)
canonical = tmp_path / "oclaw" / "data" / "ai_ops.sqlite"
canonical.parent.mkdir(parents=True, exist_ok=True)
assert not canonical.exists()
legacy = leg_root / "ai_ops.sqlite"
legacy.write_text("from_legacy", encoding="utf-8")
with patch.object(paths_mod, "_sqlite_chat_session_count", return_value=3):
with patch.object(paths_mod, "_merge_attachment_tree"):
with patch.object(paths_mod, "_cleanup_pre_merge_backups"):
paths_mod._run_default_data_migration(canonical.resolve())
assert canonical.read_text(encoding="utf-8") == "from_legacy"