mirror of
https://github.com/Abdess/retroarch_system.git
synced 2026-11-06 01:53:56 -06:00
fix: key the arcade sha1 cache by the database
The cache compared id(db), so a database freed and replaced at the same address answered with the first one's Arcade set.
This commit is contained in:
1 parent
55ac3162f5
commit
8c3e653234
2 files changed
+34
-3
No files matched your search
@@ -372,19 +372,21 @@ def _in_arcade(sha1: str, db: dict) -> bool:
|
||||
return sha1 in _arcade_suffix_sha1s(db)
|
||||
|
||||
|
||||
_suffix_cache: list[tuple[int, frozenset[str]] | None] = [None]
|
||||
_suffix_cache: list[tuple[dict, frozenset[str]] | None] = [None]
|
||||
|
||||
|
||||
def _arcade_suffix_sha1s(db: dict) -> frozenset[str]:
|
||||
# Holding the database itself, never id(db): a database freed and
|
||||
# replaced at the same address answered with the first one's set.
|
||||
cached = _suffix_cache[0]
|
||||
if cached is not None and cached[0] == id(db):
|
||||
if cached is not None and cached[0] is db:
|
||||
return cached[1]
|
||||
found = frozenset(
|
||||
sha1s[0]
|
||||
for tail, sha1s in db.get("indexes", {}).get("by_path_suffix", {}).items()
|
||||
if tail.startswith("Arcade/") and len(sha1s) == 1
|
||||
)
|
||||
_suffix_cache[0] = (id(db), found)
|
||||
_suffix_cache[0] = (db, found)
|
||||
return found
|
||||
|
||||
|
||||
|
||||
@@ -503,5 +503,34 @@ class NoTooltipInsideAName(unittest.TestCase):
|
||||
self.assertIn('>BIOS</abbr>', marked)
|
||||
|
||||
|
||||
class TheArcadeCacheHoldsItsDatabase(unittest.TestCase):
|
||||
"""The set of sha1s filed under Arcade/ was cached by id(db): a database
|
||||
freed and replaced at the same address answered with the first one's set,
|
||||
and an arcade card of the second landed in another section."""
|
||||
|
||||
@staticmethod
|
||||
def _db(sha1: str) -> dict:
|
||||
return {"files": {}, "indexes": {"by_path_suffix": {"Arcade/x.zip": [sha1]}}}
|
||||
|
||||
def test_a_new_database_at_a_reused_address_is_read_again(self):
|
||||
saved = siterender._suffix_cache[0]
|
||||
self.addCleanup(siterender._suffix_cache.__setitem__, 0, saved)
|
||||
first = self._db("a" * 40)
|
||||
self.assertTrue(siterender._in_arcade("a" * 40, first))
|
||||
address = id(first)
|
||||
del first
|
||||
# CPython hands a freed dict's address to a later one of its size,
|
||||
# unless the cache still holds the first database.
|
||||
for _ in range(1000):
|
||||
second = self._db("b" * 40)
|
||||
if id(second) == address:
|
||||
break
|
||||
del second
|
||||
else:
|
||||
second = self._db("b" * 40)
|
||||
self.assertTrue(siterender._in_arcade("b" * 40, second))
|
||||
self.assertFalse(siterender._in_arcade("a" * 40, second))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
Reference in new issue
Block a user