Add broken test for game support issue

This commit is contained in:
rubenwardy 2024-07-09 00:12:49 +01:00
parent e31433f320
commit 2a84ec5bad
2 changed files with 79 additions and 1 deletions

@ -13,7 +13,7 @@
# #
# You should have received a copy of the GNU Affero General Public License # 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/>. # along with this program. If not, see <https://www.gnu.org/licenses/>.
import sys
from typing import List, Dict, Optional, Tuple from typing import List, Dict, Optional, Tuple
import sqlalchemy import sqlalchemy
@ -90,6 +90,7 @@ class GSPackage:
return self.user_unsupported_games return self.user_unsupported_games
def add_error(self, error: str): def add_error(self, error: str):
print(f"ERROR {self.name}: {error}")
return self.errors.add(error) return self.errors.add(error)
@ -135,10 +136,12 @@ class GameSupport:
return [package for package in self.packages.values() if modname in package.depends] 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]): 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 dep_supports_all = False
for_dep = set() for_dep = set()
for provider in self.get_all_that_provide(depend): for provider in self.get_all_that_provide(depend):
found_in = self._get_supported_games(provider, visited) 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: if found_in is None:
# Unsupported, keep going # Unsupported, keep going
pass pass
@ -151,6 +154,7 @@ class GameSupport:
return dep_supports_all, for_dep return dep_supports_all, for_dep
def _get_supported_games_for_deps(self, package: GSPackage, visited: list[str]) -> Optional[set[str]]: 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() ret = set()
for depend in package.depends: for depend in package.depends:
@ -173,6 +177,7 @@ class GameSupport:
return ret return ret
def _get_supported_games(self, package: GSPackage, visited: list[str]) -> Optional[set[str]]: 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: if package.id_ in visited:
first_idx = visited.index(package.id_) first_idx = visited.index(package.id_)
visited = visited[first_idx:] visited = visited[first_idx:]
@ -183,8 +188,10 @@ class GameSupport:
return None return None
if package.type == PackageType.GAME: if package.type == PackageType.GAME:
print(f"_get_supported_games package {package.name} is game", file=sys.stderr)
return {package.name} return {package.name}
elif package.is_confirmed: elif package.is_confirmed:
print(f"_get_supported_games package {package.name} is confirmed", file=sys.stderr)
return package.supported_games return package.supported_games
visited = visited.copy() visited = visited.copy()
@ -221,6 +228,7 @@ class GameSupport:
while len(to_update) > 0: while len(to_update) > 0:
current_package = to_update.pop() 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: if current_package.id_ in self.packages and current_package.type != PackageType.GAME:
self._get_supported_games(current_package, []) self._get_supported_games(current_package, [])

@ -217,6 +217,14 @@ def test_cycle_fails_safely():
""" """
A dependency cycle shouldn't completely break the graph if a mod is A dependency cycle shouldn't completely break the graph if a mod is
available elsewhere available elsewhere
a -> d
game has d
cycle:
d -> b
b -> c
c -> b
""" """
support = GameSupport() support = GameSupport()
support.add(make_game("game1", ["default", "mod_d"])) support.add(make_game("game1", ["default", "mod_d"]))
@ -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(): def test_update():
""" """
Test updating a mod will update mods that depend on it Test updating a mod will update mods that depend on it