import os import time from pathlib import Path import pytest import tkinter as tk from main import ( BackgroundFileCopyApp, find_latest_file_in_folder, should_copy_file, compute_file_checksum, verify_copy, ) def _touch(path: Path, mtime: float) -> None: path.write_text('data', encoding='utf-8') os.utime(path, (mtime, mtime)) def test_find_latest_file_returns_none_for_missing_folder(tmp_path): missing = tmp_path / 'missing' assert find_latest_file_in_folder(str(missing)) is None def test_find_latest_file_picks_newest(tmp_path): folder = tmp_path / 'src' folder.mkdir() now = time.time() older = folder / 'older.bak' newer = folder / 'newer.bak' other = folder / 'other.sql' _touch(older, now - 10) _touch(newer, now - 5) _touch(other, now - 1) latest = find_latest_file_in_folder(str(folder)) assert latest is not None assert latest.name == 'other.sql' def test_should_copy_file_when_target_missing(tmp_path): src = tmp_path / 'src.bak' src.write_text('x', encoding='utf-8') dst = tmp_path / 'dst.bak' assert should_copy_file(src, dst) is True def test_should_copy_file_when_source_newer(tmp_path): now = time.time() src = tmp_path / 'src.bak' dst = tmp_path / 'dst.bak' _touch(dst, now - 10) _touch(src, now) assert should_copy_file(src, dst) is True def test_should_copy_file_when_target_newer_or_equal(tmp_path): now = time.time() src = tmp_path / 'src.bak' dst = tmp_path / 'dst.bak' _touch(src, now) _touch(dst, now) assert should_copy_file(src, dst) is False def test_compute_file_checksum_stable(tmp_path): src = tmp_path / 'a.bak' src.write_text('hello', encoding='utf-8') c1 = compute_file_checksum(src) c2 = compute_file_checksum(src) assert c1 == c2 def test_verify_copy_true_for_equal_files(tmp_path): src = tmp_path / 'src.bak' dst = tmp_path / 'dst.bak' src.write_text('data', encoding='utf-8') dst.write_text('data', encoding='utf-8') assert verify_copy(src, dst) is True def test_verify_copy_false_for_different_files(tmp_path): src = tmp_path / 'src.bak' dst = tmp_path / 'dst.bak' src.write_text('data1', encoding='utf-8') dst.write_text('data2', encoding='utf-8') assert verify_copy(src, dst) is False def _create_app(): root = tk.Tk() root.withdraw() app = BackgroundFileCopyApp(root) return app, root def test_copy_full_folder(tmp_path): app, root = _create_app() try: src = tmp_path / "src" dst = tmp_path / "dst" (src / "sub").mkdir(parents=True) (src / "a.bak").write_text("a", encoding="utf-8") (src / "sub" / "b.sql").write_text("b", encoding="utf-8") app.min_free_gb_var.set(0) app.include_masks_var.set("*.bak;*.sql") app.exclude_masks_var.set("") copied, skipped, errors = app.copy_full_folder(src, dst) assert errors == 0 assert copied == 2 assert (dst / "a.bak").exists() assert (dst / "sub" / "b.sql").exists() finally: root.destroy() def test_save_and_load_settings(tmp_path, monkeypatch): app, root = _create_app() try: settings_path = tmp_path / "settings.json" monkeypatch.setattr(app, "get_settings_path", lambda: str(settings_path)) app.add_path_pair("C:/src", "D:/dst", False) app.include_masks_var.set("*.bak") app.exclude_masks_var.set("*.tmp") app.min_free_gb_var.set(2) app.max_workers_var.set(4) app.schedules = [{"time": "01:00", "days": ["Mon", "Wed"]}] app.refresh_schedules_tree() app.save_settings() app2, root2 = _create_app() try: monkeypatch.setattr(app2, "get_settings_path", lambda: str(settings_path)) app2.load_settings() profile = app2.profiles.get(app2.active_profile.get()) assert profile is not None assert profile.get("include_masks") == "*.bak" assert profile.get("exclude_masks") == "*.tmp" assert int(profile.get("max_workers")) == 4 assert profile.get("min_free_gb") == 2 assert profile.get("schedules") == [{"time": "01:00", "days": ["Mon", "Wed"]}] assert len(profile.get("pairs")) == 1 finally: root2.destroy() finally: root.destroy()