zapretgui/tests/test_startup_install_path_checks.py
loop-uh c32a06bcba
Some checks failed
Windows-сборка / Dev Dev 21.1.7.33 опубликован
Zapret source guards / validate (push) Has been cancelled
Мягкая остановка движка и перечитывание списков без перезапуска
Движки winws и winws2 теперь собраны без Cygwin и понимают команды Windows:
- остановка: сначала сигнал term (движок выходит сам за десятки миллисекунд,
  код 0), TerminateProcess остаётся запасным путём для зависшего процесса
  и старых сборок движка;
- после сохранения списка профиля и правки белого списка оркестратора
  движок перечитывает списки по сигналу hup, перезапуск не нужен;
- убрано предупреждение о пробелах в пути установки: движки с такими
  путями работают;
- убраны флаги RuntimeFlags, которые никто не читал.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 17:47:04 +03:00

129 lines
5.5 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

from __future__ import annotations
from pathlib import Path
import contextlib
import inspect
import os
import sys
import unittest
from unittest.mock import patch
PUBLIC_ROOT = Path(__file__).resolve().parents[1]
SRC_ROOT = PUBLIC_ROOT / "src"
if str(SRC_ROOT) not in sys.path:
sys.path.insert(0, str(SRC_ROOT))
from startup import check_start # noqa: E402
from config.runtime_layout import ApplicationPaths # noqa: E402
class StartupInstallPathChecksTests(unittest.TestCase):
def _collect_notifications(self, root: str, executable: str | None = None) -> list[dict]:
"""Стартовые уведомления для установки в ``root``; остальные проверки отключены."""
patches = [
patch.object(check_start, "APPLICATION_PATHS", ApplicationPaths.from_root(root)),
patch.object(check_start, "check_windows_version", return_value=(False, "")),
patch.object(check_start, "check_system_commands", return_value=(False, "")),
patch.object(check_start, "check_if_application_root_is_temporary", return_value=False),
patch.object(check_start, "check_path_for_onedrive", return_value=(False, "")),
patch.object(check_start, "build_proxy_notification", return_value=None),
]
if executable is not None:
patches.append(patch.object(check_start.sys, "executable", executable))
with contextlib.ExitStack() as stack:
for item in patches:
stack.enter_context(item)
return check_start.collect_startup_notifications()
@unittest.skipUnless(sys.platform == "win32", "проверка использует семантику Windows-путей")
def test_internal_runtime_path_is_not_treated_as_install_path(self) -> None:
notifications = self._collect_notifications(
r"C:\Zapret\Dev",
executable=r"C:\Zapret\Dev\_INTER~1\python.exe",
)
self.assertEqual(notifications, [])
@unittest.skipUnless(sys.platform == "win32", "проверка использует семантику Windows-путей")
def test_onedrive_check_uses_application_root_only(self) -> None:
with (
patch.object(
check_start,
"APPLICATION_PATHS",
ApplicationPaths.from_root(r"C:\Zapret\Dev"),
),
patch.object(
check_start.sys,
"executable",
r"C:\Users\privacy\OneDrive\_INTER~1\python.exe",
),
patch.dict(
os.environ,
{"ONEDRIVE": r"C:\Users\privacy\OneDrive"},
clear=False,
),
):
in_onedrive, message = check_start.check_path_for_onedrive()
self.assertFalse(in_onedrive)
self.assertEqual(message, "")
def test_spaces_and_non_ascii_in_install_path_are_not_a_problem(self) -> None:
# Оба движка (winws.exe и winws2.exe) — собственные сборки под Windows
# и понимают пробелы и не-ASCII символы в путях: предупреждать не о чем.
for root in (r"C:\Zapret Builds\Dev", r"C:\Программы\Запрет", r"D:\Моя папка (1)\zapret"):
with self.subTest(root=root):
self.assertEqual(self._collect_notifications(root), [])
def test_special_chars_check_is_gone(self) -> None:
self.assertFalse(hasattr(check_start, "contains_special_chars"))
self.assertFalse(hasattr(check_start, "check_path_for_special_chars"))
self.assertNotIn("special_chars_path", inspect.getsource(check_start))
@unittest.skipUnless(sys.platform == "win32", "проверка использует семантику Windows-путей")
def test_temporary_directory_check_uses_application_root(self) -> None:
environment = {
"TEMP": r"C:\Users\privacy\AppData\Local\Temp",
"TMP": r"C:\Users\privacy\AppData\Local\Temp",
"WINDIR": r"C:\Windows",
}
with (
patch.object(
check_start,
"APPLICATION_PATHS",
ApplicationPaths.from_root(
r"C:\Users\privacy\AppData\Local\Temp\Zapret"
),
),
patch.object(check_start.sys, "executable", r"C:\Python314\python.exe"),
patch.dict(os.environ, environment, clear=False),
):
self.assertTrue(check_start.check_if_application_root_is_temporary())
@unittest.skipUnless(sys.platform == "win32", "проверка использует семантику Windows-путей")
def test_similar_directory_prefix_is_not_treated_as_temporary(self) -> None:
environment = {
"TEMP": r"C:\Temp",
"TMP": r"C:\Temp",
"WINDIR": r"C:\Windows",
}
with (
patch.object(
check_start,
"APPLICATION_PATHS",
ApplicationPaths.from_root(r"C:\TempBackup\Zapret"),
),
patch.dict(os.environ, environment, clear=False),
):
self.assertFalse(check_start.check_if_application_root_is_temporary())
def test_path_validation_has_no_dependency_on_runtime_executable(self) -> None:
source = inspect.getsource(check_start)
self.assertNotIn("sys.executable", source)
self.assertNotIn("BIN_FOLDER", source)
if __name__ == "__main__":
unittest.main()