194 lines
7.4 KiB
Python
194 lines
7.4 KiB
Python
import os
|
|
import tempfile
|
|
import unittest
|
|
from unittest import mock
|
|
|
|
import setup_tool_dynamic as dynamic
|
|
|
|
|
|
class _Var:
|
|
def __init__(self, value):
|
|
self.value = value
|
|
|
|
def get(self):
|
|
return self.value
|
|
|
|
|
|
class _Root:
|
|
def configure(self, **_kwargs):
|
|
return None
|
|
|
|
def update_idletasks(self):
|
|
return None
|
|
|
|
|
|
def _make_runtime_tool(target, events):
|
|
"""Create the minimum state needed to execute the real base run_installation."""
|
|
tool = object.__new__(dynamic.ModernWowSetupTool)
|
|
tool._install_in_progress = False
|
|
tool.wow_dir = _Var(target)
|
|
tool.root = _Root()
|
|
tool._close_download_progress = lambda: None
|
|
|
|
tool.validate_installation_dir = lambda value: (
|
|
events.append(("validate_directory", value)) or True
|
|
)
|
|
tool.validate_limits = lambda: (
|
|
events.append(("validate_limits", target)) or True
|
|
)
|
|
tool.validate_plugin_conflicts = lambda: (
|
|
events.append(("preflight", target)) or True
|
|
)
|
|
|
|
def record_target(name):
|
|
return lambda value: events.append((name, value))
|
|
|
|
tool.copy_base_files = record_target("copy_base_files")
|
|
tool.configure_dxvk = record_target("configure_dxvk")
|
|
tool.configure_plugins = record_target("configure_plugins")
|
|
tool.configure_autologin_encryption = lambda: events.append(
|
|
("configure_autologin_encryption", target)
|
|
)
|
|
tool.configure_visual_audio = record_target("configure_visual_audio")
|
|
tool.configure_script_memory = record_target("configure_script_memory")
|
|
tool.configure_wdb_cache = record_target("configure_wdb_cache")
|
|
tool.apply_process_mitigations = record_target("apply_process_mitigations")
|
|
tool.create_launcher_shortcut = record_target("create_launcher_shortcut")
|
|
tool.cleanup_legacy_outputs = record_target("cleanup_legacy_outputs")
|
|
tool.save_settings = record_target("save_settings")
|
|
return tool
|
|
|
|
|
|
class RealInstallationOrderingTests(unittest.TestCase):
|
|
def test_real_installation_runs_vanilla_tweaks_once_before_every_write(self):
|
|
events = []
|
|
|
|
with tempfile.TemporaryDirectory() as target:
|
|
initial_entries = set(os.listdir(target))
|
|
tool = _make_runtime_tool(target, events)
|
|
|
|
def fake_clean(_instance, value):
|
|
events.append(("clean_unselected_files", value))
|
|
|
|
def fake_vanilla_tweaks(_instance, value):
|
|
events.append(("vanilla_tweaks", value))
|
|
return os.path.join(value, "WoW_Modernized.exe")
|
|
|
|
with mock.patch.object(
|
|
dynamic._ModernWowSetupToolCore,
|
|
"clean_unselected_files",
|
|
fake_clean,
|
|
create=True,
|
|
), mock.patch.object(
|
|
dynamic._ModernWowSetupToolCore,
|
|
"run_vanilla_tweaks",
|
|
fake_vanilla_tweaks,
|
|
create=True,
|
|
), mock.patch(
|
|
"setup_tool.messagebox.showinfo"
|
|
) as showinfo, mock.patch(
|
|
"setup_tool.messagebox.showerror"
|
|
) as showerror:
|
|
self.assertIsNone(tool.run_installation())
|
|
|
|
self.assertEqual(
|
|
events,
|
|
[
|
|
("validate_directory", target),
|
|
("validate_limits", target),
|
|
("preflight", target),
|
|
("vanilla_tweaks", target),
|
|
("clean_unselected_files", target),
|
|
("copy_base_files", target),
|
|
("configure_dxvk", target),
|
|
("configure_plugins", target),
|
|
("configure_autologin_encryption", target),
|
|
("configure_visual_audio", target),
|
|
("configure_script_memory", target),
|
|
("configure_wdb_cache", target),
|
|
("apply_process_mitigations", target),
|
|
("create_launcher_shortcut", target),
|
|
("cleanup_legacy_outputs", target),
|
|
("save_settings", target),
|
|
],
|
|
)
|
|
showinfo.assert_called_once()
|
|
showerror.assert_not_called()
|
|
|
|
# run_installation installs temporary instance wrappers. They
|
|
# must be gone when Apply returns so a later Apply starts clean.
|
|
self.assertNotIn("clean_unselected_files", tool.__dict__)
|
|
self.assertNotIn("run_vanilla_tweaks", tool.__dict__)
|
|
self.assertIs(tool.clean_unselected_files.__func__, fake_clean)
|
|
self.assertIs(tool.run_vanilla_tweaks.__func__, fake_vanilla_tweaks)
|
|
|
|
# All real mutators above were replaced with record-only callbacks.
|
|
# Any newly-added direct filesystem write in run_installation would
|
|
# make this integration-style test visibly change the temp folder.
|
|
self.assertEqual(set(os.listdir(target)), initial_entries)
|
|
self.assertFalse(tool._install_in_progress)
|
|
|
|
def test_real_installation_vanilla_tweaks_failure_blocks_all_writes(self):
|
|
events = []
|
|
|
|
with tempfile.TemporaryDirectory() as target:
|
|
initial_entries = set(os.listdir(target))
|
|
tool = _make_runtime_tool(target, events)
|
|
|
|
def fake_clean(_instance, value):
|
|
events.append(("clean_unselected_files", value))
|
|
|
|
def failing_vanilla_tweaks(_instance, value):
|
|
events.append(("vanilla_tweaks_failed", value))
|
|
raise RuntimeError("patcher failed before install writes")
|
|
|
|
with mock.patch.object(
|
|
dynamic._ModernWowSetupToolCore,
|
|
"clean_unselected_files",
|
|
fake_clean,
|
|
create=True,
|
|
), mock.patch.object(
|
|
dynamic._ModernWowSetupToolCore,
|
|
"run_vanilla_tweaks",
|
|
failing_vanilla_tweaks,
|
|
create=True,
|
|
), mock.patch(
|
|
"setup_tool.messagebox.showinfo"
|
|
) as showinfo, mock.patch(
|
|
"setup_tool.messagebox.showerror"
|
|
) as showerror:
|
|
self.assertIsNone(tool.run_installation())
|
|
|
|
self.assertEqual(
|
|
events,
|
|
[
|
|
("validate_directory", target),
|
|
("validate_limits", target),
|
|
("preflight", target),
|
|
("vanilla_tweaks_failed", target),
|
|
],
|
|
)
|
|
showinfo.assert_not_called()
|
|
showerror.assert_called_once()
|
|
self.assertEqual(showerror.call_args.args[0], "Installation Error")
|
|
self.assertIn(
|
|
"patcher failed before install writes",
|
|
showerror.call_args.args[1],
|
|
)
|
|
|
|
# The temporary wrappers must also be restored on the error path.
|
|
self.assertNotIn("clean_unselected_files", tool.__dict__)
|
|
self.assertNotIn("run_vanilla_tweaks", tool.__dict__)
|
|
self.assertIs(tool.clean_unselected_files.__func__, fake_clean)
|
|
self.assertIs(
|
|
tool.run_vanilla_tweaks.__func__,
|
|
failing_vanilla_tweaks,
|
|
)
|
|
|
|
self.assertEqual(set(os.listdir(target)), initial_entries)
|
|
self.assertFalse(tool._install_in_progress)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
unittest.main()
|