# -*- coding: utf-8 -*- """util.runtime_paths:技能根、DB 路径、数据目录均落在隔离数据根下。""" from __future__ import annotations import os import unittest from _support import IsolatedDataRoot, get_skill_root _FAKE_REAL_ROOT = r"D:\jiangchang-data" def _legacy_env_key(suffix: str) -> str: return "CL" + "AW_" + suffix class TestRuntimePaths(unittest.TestCase): def test_paths_under_isolated_root(self) -> None: win_default = r"D:\jiangchang-data" with IsolatedDataRoot() as tmp: import importlib import util.runtime_paths as rp importlib.reload(rp) skill_root = rp.get_skill_root() self.assertTrue(os.path.isdir(skill_root)) self.assertTrue(os.path.isfile(os.path.join(skill_root, "SKILL.md"))) db_path = rp.get_db_path() self.assertTrue(os.path.normpath(db_path).startswith(os.path.normpath(tmp))) self.assertNotIn(win_default, db_path) data_dir = rp.get_skill_data_dir() self.assertTrue(os.path.normpath(data_dir).startswith(os.path.normpath(tmp))) self.assertIn("_test", data_dir.replace("\\", "/")) self.assertNotIn(win_default, data_dir) self.assertEqual(get_skill_root(), skill_root) def test_isolation_overrides_prefixed_real_data_root(self) -> None: """先设假数据根,再进入隔离;get_db_path 必须落在 tempdir。""" saved = { k: os.environ.get(k) for k in ("JIANGCHANG_DATA_ROOT", "JIANGCHANG_USER_ID") } try: os.environ["JIANGCHANG_DATA_ROOT"] = _FAKE_REAL_ROOT with IsolatedDataRoot() as tmp: import importlib import util.runtime_paths as rp importlib.reload(rp) db_path = rp.get_db_path() norm_db = os.path.normcase(os.path.normpath(db_path)) norm_tmp = os.path.normcase(os.path.normpath(tmp)) self.assertTrue(norm_db.startswith(norm_tmp), msg=f"db_path={db_path!r} tmp={tmp!r}") norm_fake = os.path.normcase(os.path.normpath(_FAKE_REAL_ROOT)) self.assertFalse( norm_db.startswith(norm_fake), msg=f"db_path must not be under fake root: {db_path!r}", ) finally: for k, v in saved.items(): if v is None: os.environ.pop(k, None) else: os.environ[k] = v def test_legacy_env_vars_do_not_override_canonical(self) -> None: with IsolatedDataRoot() as tmp: os.environ[_legacy_env_key("DATA_ROOT")] = _FAKE_REAL_ROOT os.environ[_legacy_env_key("USER_ID")] = "legacy-user" import importlib import util.runtime_paths as rp importlib.reload(rp) data_dir = rp.get_skill_data_dir() self.assertTrue(os.path.normpath(data_dir).startswith(os.path.normpath(tmp))) self.assertIn("_test", data_dir.replace("\\", "/")) def test_resolve_data_path_defaults_under_skill_data_dir(self) -> None: with IsolatedDataRoot() as tmp: import importlib import util.runtime_paths as rp importlib.reload(rp) path = rp.resolve_data_path(None, "downloads", create=True) norm = os.path.normcase(os.path.normpath(path)) norm_tmp = os.path.normcase(os.path.normpath(tmp)) self.assertTrue(norm.startswith(norm_tmp)) self.assertTrue(norm.endswith(os.path.normcase(os.path.join("downloads")))) def test_resolve_data_path_relative_uses_data_dir_not_cwd(self) -> None: with IsolatedDataRoot() as tmp: import importlib import util.runtime_paths as rp importlib.reload(rp) os.environ["SKILL_DOWNLOAD_DIR"] = "downloads/videos" from jiangchang_skill_core import config config.reset_cache() importlib.reload(rp) path = rp.resolve_data_path("SKILL_DOWNLOAD_DIR", "downloads", create=False) norm = os.path.normcase(os.path.normpath(path)) self.assertIn(os.path.normcase("downloads"), norm) self.assertIn(os.path.normcase("videos"), norm) self.assertTrue(norm.startswith(os.path.normcase(os.path.normpath(tmp)))) os.environ.pop("SKILL_DOWNLOAD_DIR", None) config.reset_cache() def test_resolve_input_path_relative_under_imports(self) -> None: with IsolatedDataRoot() as tmp: import importlib import util.runtime_paths as rp importlib.reload(rp) resolved = rp.resolve_input_path("urls.txt", create_parent=True) norm = os.path.normcase(os.path.normpath(resolved)) self.assertIn(os.path.normcase("imports"), norm) self.assertTrue(norm.startswith(os.path.normcase(os.path.normpath(tmp)))) def test_list_resolved_data_paths_keys(self) -> None: with IsolatedDataRoot(): import importlib import util.runtime_paths as rp importlib.reload(rp) paths = rp.list_resolved_data_paths() for key in ( "skill_data_dir", "downloads_dir", "imports_dir", "exports_dir", ): self.assertIn(key, paths) self.assertTrue(paths[key]) if __name__ == "__main__": unittest.main()