Files

130 lines
4.9 KiB
Python

import tempfile
import unittest
from pathlib import Path
from unittest.mock import patch
from PyQt5.QtCore import QSettings
from pgu4_sync import (
APP_VERSION,
UPDATE_EXE_ASSET,
UPDATE_INI_ASSET,
UpdateCheckWorker,
create_updater_script,
is_newer_version,
merge_ini_defaults,
update_release_from_payload,
)
class UpdateTests(unittest.TestCase):
@patch("pgu4_sync.urllib.request.urlopen", side_effect=TimeoutError("offline"))
def test_update_check_is_silent_when_network_fails(self, _urlopen_mock):
worker = UpdateCheckWorker()
checked = []
failed = []
finished = []
worker.checked.connect(checked.append)
worker.failed.connect(failed.append)
worker.finished.connect(lambda: finished.append(True))
worker.run()
self.assertEqual([], checked)
self.assertEqual(["offline"], failed)
self.assertEqual([True], finished)
def test_version_comparison(self):
self.assertTrue(is_newer_version("1.0.7", APP_VERSION))
self.assertTrue(is_newer_version("v1.1.0", "1.0.9"))
self.assertTrue(is_newer_version("1.0.10", "1.0.2"))
self.assertFalse(is_newer_version("v1.0.4", APP_VERSION))
self.assertFalse(is_newer_version("1.0", "1.0.0"))
self.assertFalse(is_newer_version("invalid", APP_VERSION))
def test_release_payload_requires_expected_assets_and_host(self):
payload = {
"tag_name": "v1.0.3",
"draft": False,
"prerelease": False,
"html_url": "http://107.173.157.41:3000/release",
"assets": [
{
"name": UPDATE_EXE_ASSET,
"size": 1234567,
"browser_download_url": (
"http://107.173.157.41:3000/clear/repo/download/app.exe"
),
},
{
"name": UPDATE_INI_ASSET,
"size": 120,
"browser_download_url": (
"http://107.173.157.41:3000/clear/repo/download/app.ini"
),
},
],
}
release = update_release_from_payload(payload)
self.assertIsNotNone(release)
self.assertEqual("1.0.3", release.version)
self.assertEqual(1234567, release.exe_size)
self.assertTrue(release.ini_url.endswith("app.ini"))
payload["assets"][0]["browser_download_url"] = "https://example.com/app.exe"
self.assertIsNone(update_release_from_payload(payload))
def test_merge_ini_adds_missing_keys_without_overwriting_values(self):
with tempfile.TemporaryDirectory() as temp_dir:
temp = Path(temp_dir)
source_path = temp / "new.ini"
target_path = temp / "current.ini"
source = QSettings(str(source_path), QSettings.IniFormat)
source.setValue("host", "new-host")
source.setValue("port", 5922)
source.setValue("update/channel", "stable")
source.setValue("password", "new-plaintext-password")
source.setValue("password_protected", "new-encrypted-password")
source.sync()
target = QSettings(str(target_path), QSettings.IniFormat)
target.setValue("host", "existing-host")
target.setValue("port", 22)
target.setValue("password_protected", "existing-encrypted-password")
target.sync()
added = merge_ini_defaults(source_path, target_path)
merged = QSettings(str(target_path), QSettings.IniFormat)
self.assertEqual("existing-host", merged.value("host"))
self.assertEqual(22, int(merged.value("port")))
self.assertFalse(merged.contains("password"))
self.assertEqual(
"existing-encrypted-password",
merged.value("password_protected"),
)
self.assertEqual("stable", merged.value("update/channel"))
self.assertEqual(["update/channel"], added)
def test_updater_script_contains_wait_replace_rollback_and_restart(self):
with tempfile.TemporaryDirectory() as temp_dir:
temp = Path(temp_dir)
update_exe = temp / "downloaded update.exe"
target_exe = temp / "PGU-NetFileSyncWin.exe"
update_exe.write_bytes(b"MZ")
target_exe.write_bytes(b"MZ-old")
script_path = create_updater_script(update_exe, target_exe, 12345)
script = script_path.read_text(encoding="utf-8-sig")
self.assertIn("Wait-Process -Id 12345", script)
self.assertIn("Move-Item -LiteralPath $update -Destination $target", script)
self.assertIn("Move-Item -LiteralPath $backup -Destination $target", script)
self.assertIn("Start-Process -FilePath $target", script)
self.assertIn("Updated application exited during startup", script)
if __name__ == "__main__":
unittest.main()