28773e7cf1
The frozen baseline image predates two hot-patches made in the running container after build: * utas_server.py: FUT_MODES-gated offlineSeason block in GetHubData's club response (keeps the offline-season summary valid) * test_hub_offline_season_contract.py added to /app/tools Sync fifa17-python/tools to the running container (verified byte-identical, 237 files incl. the redir cert pair) and snapshot the live FS as openfut-fut-backend:python-running-2026-08-10 (docker commit). A fresh build from the committed sources now reproduces the running backend exactly (baked SHA256SUMS.txt diffed against the container manifest: identical).
46 lines
1.7 KiB
Python
46 lines
1.7 KiB
Python
#!/usr/bin/env python3
|
|
"""Regression for the FIFA 17 FUT hub offline-Seasons summary.
|
|
|
|
CardsDLL's hub parser at 0x180139610 recognizes offlineSeason (atom 0x1ec)
|
|
and passes its object to 0x18013c3a0. That nested parser recognizes the
|
|
string-valued divisionId, gamesPlayed, points, totalGames, and
|
|
progressDataVersion fields. Without offlineSeason, the Single Player Season
|
|
UI rejects the otherwise-successful GetHubData response before /season is sent.
|
|
"""
|
|
import os
|
|
import pathlib
|
|
import sys
|
|
import tempfile
|
|
|
|
TOOLS = pathlib.Path(__file__).resolve().parent
|
|
sys.path.insert(0, str(TOOLS))
|
|
|
|
|
|
def main():
|
|
with tempfile.TemporaryDirectory(prefix="openfut-hub-season-test-") as state:
|
|
os.environ["FUT_PROFILE_ROOT"] = os.path.join(state, "accounts")
|
|
os.environ.pop("FUT_PROFILE", None)
|
|
os.environ["FUT_MODES"] = "1"
|
|
|
|
import utas_server
|
|
|
|
body = utas_server.hub_data()
|
|
assert isinstance(body, dict), "hub response root must be an object"
|
|
summary = body.get("offlineSeason")
|
|
assert isinstance(summary, dict), "hub.offlineSeason must be an object"
|
|
|
|
expected = {"divisionId", "gamesPlayed", "points", "totalGames",
|
|
"progressDataVersion"}
|
|
assert set(summary) == expected, repr(summary)
|
|
for key in expected:
|
|
assert isinstance(summary[key], str), "%s must be a string: %r" % (key, summary[key])
|
|
|
|
assert summary["divisionId"] == "10", repr(summary)
|
|
assert summary["gamesPlayed"] == "0", repr(summary)
|
|
assert summary["points"] == "0", repr(summary)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|
|
print("PASS: FUT hub includes the recovered offline-Seasons summary")
|