Skip to content

Commit

Permalink
Make AmmoController check for broken symlinks
Browse files Browse the repository at this point in the history
We use AmmoController as a context manager for ammo in our tests. Add
logic to ensure errors are raised if it detects broken symlinks.

Adjust the couple of tests where we do actually expect to see broken
symlinks so they pass despite this.
  • Loading branch information
cyberrumor committed Jan 31, 2024
1 parent a62834e commit 7249520
Show file tree
Hide file tree
Showing 2 changed files with 26 additions and 18 deletions.
8 changes: 7 additions & 1 deletion test/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,8 @@ class AmmoController:
Ammo's configuration directory will be set up as AMMO_DIR,
if it doesn't already exist.
Removes those folders on exit or error.
Removes those folders on exit or error. Raises AssertionError
after exit logic if there were broken symlinks.
"""

def __init__(self):
Expand All @@ -57,11 +58,14 @@ def __exit__(self, *args, **kwargs):
ammo instance. This ensures no reliance on a state
created by a previous test.
"""
broken_symlinks = {}
# remove symlinks
for dirpath, _dirnames, filenames in os.walk(self.game.directory):
for file in filenames:
full_path = Path(dirpath) / file
if full_path.is_symlink():
if (dest := full_path.resolve()).exists() is False:
broken_symlinks[str(full_path)] = str(dest)
full_path.unlink()

# remove empty directories
Expand All @@ -82,6 +86,8 @@ def remove_empty_dirs(path):
if AMMO_DIR.exists():
shutil.rmtree(AMMO_DIR)

assert {} == broken_symlinks


class FomodContextManager:
def __init__(self, mod: Mod):
Expand Down
36 changes: 19 additions & 17 deletions test/test_controller_instance.py
Original file line number Diff line number Diff line change
Expand Up @@ -152,18 +152,19 @@ def test_controller_enabled_plugin_is_broken_symlink():
Test that when an enabled plugin's symlink points at a non-existing file,
the plugin is not shown.
"""
with AmmoController() as first_launch:
index = install_mod(first_launch, "conflict_1")
mod = first_launch.mods[index]
plugin = first_launch.plugins[0]
with pytest.raises(AssertionError):
with AmmoController() as first_launch:
index = install_mod(first_launch, "conflict_1")
mod = first_launch.mods[index]
plugin = first_launch.plugins[0]

file = [i for i in mod.files if i.name == "mock_plugin.esp"][0]
file.unlink()
file = [i for i in mod.files if i.name == "mock_plugin.esp"][0]
file.unlink()

with AmmoController() as controller:
mod = controller.mods[index]
assert mod.enabled is True
assert len(controller.plugins) == 0
with AmmoController() as controller:
mod = controller.mods[index]
assert mod.enabled is True
assert len(controller.plugins) == 0


def test_controller_disabled_broken_mod_enabled_plugin():
Expand Down Expand Up @@ -206,13 +207,14 @@ def test_controller_missing_mod():
found (because it was deleted from ammo's mod dir) isn't added
to mods.
"""
with AmmoController() as first_launch:
index = install_mod(first_launch, "normal_mod")
mod = first_launch.mods[index]
shutil.rmtree(mod.location)

with AmmoController() as controller:
assert len(controller.mods) == 0
with pytest.raises(AssertionError):
with AmmoController() as first_launch:
index = install_mod(first_launch, "normal_mod")
mod = first_launch.mods[index]
shutil.rmtree(mod.location)

with AmmoController() as controller:
assert len(controller.mods) == 0


def test_controller_plugin_without_mod():
Expand Down

0 comments on commit 7249520

Please sign in to comment.