Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add broken test for game support issue #549

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading