Skip to content

Commit

Permalink
Add broken test for game support issue
Browse files Browse the repository at this point in the history
  • Loading branch information
rubenwardy committed Jul 8, 2024
1 parent e31433f commit 2a84ec5
Show file tree
Hide file tree
Showing 2 changed files with 79 additions and 1 deletion.
10 changes: 9 additions & 1 deletion app/logic/game_support.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.

import sys
from typing import List, Dict, Optional, Tuple

import sqlalchemy
Expand Down Expand Up @@ -90,6 +90,7 @@ def unsupported_games(self) -> set[str]:
return self.user_unsupported_games

def add_error(self, error: str):
print(f"ERROR {self.name}: {error}")
return self.errors.add(error)


Expand Down Expand Up @@ -135,10 +136,12 @@ def get_all_that_depend_on(self, modname: str) -> List[GSPackage]:
return [package for package in self.packages.values() if modname in package.depends]

def _get_supported_games_for_modname(self, depend: str, visited: list[str]):
print(f"_get_supported_games_for_modname {depend} visited {', '.join(visited)}", file=sys.stderr)
dep_supports_all = False
for_dep = set()
for provider in self.get_all_that_provide(depend):
found_in = self._get_supported_games(provider, visited)
print(f" - provider for {depend}: {provider.name}: {found_in}", file=sys.stderr)
if found_in is None:
# Unsupported, keep going
pass
Expand All @@ -151,6 +154,7 @@ def _get_supported_games_for_modname(self, depend: str, visited: list[str]):
return dep_supports_all, for_dep

def _get_supported_games_for_deps(self, package: GSPackage, visited: list[str]) -> Optional[set[str]]:
print(f"_get_supported_games_for_deps package {package.name} visited {', '.join(visited)}", file=sys.stderr)
ret = set()

for depend in package.depends:
Expand All @@ -173,6 +177,7 @@ def _get_supported_games_for_deps(self, package: GSPackage, visited: list[str])
return ret

def _get_supported_games(self, package: GSPackage, visited: list[str]) -> Optional[set[str]]:
print(f"_get_supported_games package {package.name} visited {', '.join(visited)}", file=sys.stderr)
if package.id_ in visited:
first_idx = visited.index(package.id_)
visited = visited[first_idx:]
Expand All @@ -183,8 +188,10 @@ def _get_supported_games(self, package: GSPackage, visited: list[str]) -> Option
return None

if package.type == PackageType.GAME:
print(f"_get_supported_games package {package.name} is game", file=sys.stderr)
return {package.name}
elif package.is_confirmed:
print(f"_get_supported_games package {package.name} is confirmed", file=sys.stderr)
return package.supported_games

visited = visited.copy()
Expand Down Expand Up @@ -221,6 +228,7 @@ def on_update(self, package: GSPackage, old_provides: Optional[set[str]] = None)

while len(to_update) > 0:
current_package = to_update.pop()
print(f"on_update package {current_package.name}", file=sys.stderr)
if current_package.id_ in self.packages and current_package.type != PackageType.GAME:
self._get_supported_games(current_package, [])

Expand Down
70 changes: 70 additions & 0 deletions app/tests/unit/logic/test_game_support.py
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,14 @@ def test_cycle_fails_safely():
"""
A dependency cycle shouldn't completely break the graph if a mod is
available elsewhere
a -> d
game has d
cycle:
d -> b
b -> c
c -> b
"""
support = GameSupport()
support.add(make_game("game1", ["default", "mod_d"]))
Expand All @@ -241,6 +249,68 @@ def test_cycle_fails_safely():
}


def test_cycle_not_fulfill_with_conflict():
"""
Test that cycles aren't fulfilled by installing a mod multiple times, which would conflict
a -> b -> a
game1 has a
b should be {game1}
a should be unfulfilled
"""
support = GameSupport()
support.add(make_game("game1", ["default", "mod_a"]))
modB = support.add(make_mod("mod_b", ["mod_b"], ["mod_a"]))
modA = support.add(make_mod("mod_a", ["mod_a"], ["mod_b"]))
support.on_first_run()

assert modB.is_confirmed
assert modB.detected_supported_games == {"game1"}

# Can't install mod_a and game1 at the same time
assert not modA.is_confirmed
assert modA.detected_supported_games == {}

assert support.all_errors == {
"author/mod_a: Dependency cycle detected: author/mod_b -> author/mod_a -> author/mod_b",
"author/mod_b: Dependency cycle detected: author/mod_b -> author/mod_a -> author/mod_b",
}


def test_cycle_not_fulfill_with_conflict2():
"""
Test that cycles aren't fulfilled by installing a mod multiple times, which would conflict
a -> b -> a
game1 has a
b should be {game1}
a should be unfulfilled
"""
support = GameSupport()
support.add(make_game("game1", ["default"]))
modB = support.add(make_mod("mod_b", ["mod_b"], ["mod_a"]))
modA2 = support.add(make_mod("mod_a", ["mod_a"], ["default"]))
modA = support.add(make_mod("mod_a", ["mod_a"], ["mod_b"]))
support.on_first_run()

assert modB.is_confirmed
assert modB.detected_supported_games == {"game1"}

assert modA2.is_confirmed
assert modA2.detected_supported_games == {"game1"}

# Can't install modA and modA2 at the same time
assert not modA.is_confirmed
assert modA.detected_supported_games == {}

assert support.all_errors == {
"author/mod_a: Dependency cycle detected: author/mod_b -> author/mod_a -> author/mod_b",
"author/mod_b: Dependency cycle detected: author/mod_b -> author/mod_a -> author/mod_b",
}


def test_update():
"""
Test updating a mod will update mods that depend on it
Expand Down

0 comments on commit 2a84ec5

Please sign in to comment.