"""저장 위치 선택 — 고른 곳에 실제로 쌓이고, 다음 실행 때 그대로 따라가는지.""" from __future__ import annotations import json import pytest from livesub import storage from livesub.config import AppConfig, config_path from livesub.constants import models_dir, user_data_dir @pytest.fixture def os_dir(tmp_path, monkeypatch): """OS 표준 설정 폴더(쪽지가 놓이는 곳)를 임시 폴더로 바꾼다.""" base = tmp_path / "appdata" / "LiveSub" monkeypatch.setattr(storage, "_os_config_dir", lambda: base) return base def test_first_run_is_not_configured(os_dir): assert storage.is_configured() is False assert storage.stored_data_dir() is None def test_choice_is_remembered(os_dir, tmp_path): chosen = tmp_path / "D" / "LiveSub" storage.set_data_dir(chosen) assert storage.is_configured() is True assert storage.stored_data_dir() == chosen.resolve() assert storage.data_dir() == chosen.resolve() def test_everything_lands_in_the_chosen_folder(os_dir, tmp_path): """쪽지만 OS 폴더에 남고 내용물은 고른 곳으로 가야 한다.""" chosen = tmp_path / "games" / "LiveSub" storage.set_data_dir(chosen) assert user_data_dir() == chosen.resolve() assert config_path().parent == chosen.resolve() assert models_dir() == chosen.resolve() / "models" AppConfig().save() assert (chosen / "config.json").is_file() assert not (os_dir / "config.json").exists() assert list(os_dir.iterdir()) == [os_dir / storage.POINTER_NAME] def test_existing_install_is_not_asked_again(os_dir): """위치 선택이 없던 버전에서 올라온 사람에게 다시 묻지 않는다.""" os_dir.mkdir(parents=True) (os_dir / "models").mkdir() assert storage.is_configured() is True assert storage.stored_data_dir() is None # 쪽지는 없지만 assert storage.data_dir() == os_dir # 쓰던 자리를 그대로 쓴다 def test_broken_pointer_falls_back_to_default(os_dir): os_dir.mkdir(parents=True) (os_dir / storage.POINTER_NAME).write_text("{ 깨진 json", encoding="utf-8") assert storage.stored_data_dir() is None assert storage.data_dir() == os_dir def test_unusable_location_falls_back_instead_of_crashing(os_dir, tmp_path): """고른 디스크가 빠졌거나 경로가 막혔을 때 죽지 않고 기본 위치로 물러난다.""" blocker = tmp_path / "blocker" blocker.write_text("파일이라 하위 폴더를 만들 수 없다", encoding="utf-8") os_dir.mkdir(parents=True) (os_dir / storage.POINTER_NAME).write_text( json.dumps({"data_dir": str(blocker / "LiveSub")}), encoding="utf-8" ) assert storage.data_dir() == os_dir def test_check_target_rejects_unusable_choices(tmp_path): current = tmp_path / "current" current.mkdir() assert storage.check_target("") is not None assert storage.check_target(current / "inside", current) is not None # 자기 하위 assert storage.check_target(current, current) is None # 같은 곳은 문제 아님 assert storage.check_target(tmp_path / "new") is None # 아직 없어도 만들 수 있으면 OK def test_move_data_carries_models_and_config(tmp_path): old, new = tmp_path / "old", tmp_path / "new" (old / "models" / "whisper").mkdir(parents=True) (old / "models" / "whisper" / "model.bin").write_bytes(b"x" * 16) (old / "config.json").write_text("{}", encoding="utf-8") (old / "livesub.log").write_text("로그는 안 옮긴다", encoding="utf-8") moved = storage.move_data(old, new) assert sorted(moved) == ["config.json", "models"] assert (new / "models" / "whisper" / "model.bin").read_bytes() == b"x" * 16 assert not (old / "models").exists() assert (old / "livesub.log").is_file() # 실행 중 잠겨 있으므로 제외 대상 def test_move_data_never_overwrites_existing(tmp_path): old, new = tmp_path / "old", tmp_path / "new" old.mkdir() new.mkdir() (old / "config.json").write_text("옛날 것", encoding="utf-8") (new / "config.json").write_text("새 위치에 이미 있던 것", encoding="utf-8") assert storage.move_data(old, new) == [] assert (new / "config.json").read_text(encoding="utf-8") == "새 위치에 이미 있던 것" assert (old / "config.json").is_file() def test_move_data_to_same_place_does_nothing(tmp_path): same = tmp_path / "same" same.mkdir() (same / "config.json").write_text("{}", encoding="utf-8") assert storage.move_data(same, same) == [] assert (same / "config.json").is_file()