130 lines
4.9 KiB
Python
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()
|