mirror of
https://github.com/MarioSpore/Grinch-AP.git
synced 2025-10-21 04:01:32 -06:00
Core: fix some memory leak sources without removing caching (#2400)
* Core: fix some memory leak sources * Core: run gc before detecting memory leaks * Core: restore caching in BaseClasses.MultiWorld * SM: move spheres cache to MultiWorld._sm_spheres to avoid memory leak * Test: add tests for world memory leaks * Test: limit WorldTestBase leak-check to py>=3.11 --------- Co-authored-by: Fabian Dill <fabian.dill@web.de>
This commit is contained in:
66
test/utils/test_caches.py
Normal file
66
test/utils/test_caches.py
Normal file
@@ -0,0 +1,66 @@
|
||||
# Tests for caches in Utils.py
|
||||
|
||||
import unittest
|
||||
from typing import Any
|
||||
|
||||
from Utils import cache_argsless, cache_self1
|
||||
|
||||
|
||||
class TestCacheArgless(unittest.TestCase):
|
||||
def test_cache(self) -> None:
|
||||
@cache_argsless
|
||||
def func_argless() -> object:
|
||||
return object()
|
||||
|
||||
self.assertTrue(func_argless() is func_argless())
|
||||
|
||||
if __debug__: # assert only available with __debug__
|
||||
def test_invalid_decorator(self) -> None:
|
||||
with self.assertRaises(Exception):
|
||||
@cache_argsless # type: ignore[arg-type]
|
||||
def func_with_arg(_: Any) -> None:
|
||||
pass
|
||||
|
||||
|
||||
class TestCacheSelf1(unittest.TestCase):
|
||||
def test_cache(self) -> None:
|
||||
class Cls:
|
||||
@cache_self1
|
||||
def func(self, _: Any) -> object:
|
||||
return object()
|
||||
|
||||
o1 = Cls()
|
||||
o2 = Cls()
|
||||
self.assertTrue(o1.func(1) is o1.func(1))
|
||||
self.assertFalse(o1.func(1) is o1.func(2))
|
||||
self.assertFalse(o1.func(1) is o2.func(1))
|
||||
|
||||
def test_gc(self) -> None:
|
||||
# verify that we don't keep a global reference
|
||||
import gc
|
||||
import weakref
|
||||
|
||||
class Cls:
|
||||
@cache_self1
|
||||
def func(self, _: Any) -> object:
|
||||
return object()
|
||||
|
||||
o = Cls()
|
||||
_ = o.func(o) # keep a hard ref to the result
|
||||
r = weakref.ref(o) # keep weak ref to the cache
|
||||
del o # remove hard ref to the cache
|
||||
gc.collect()
|
||||
self.assertFalse(r()) # weak ref should be dead now
|
||||
|
||||
if __debug__: # assert only available with __debug__
|
||||
def test_no_self(self) -> None:
|
||||
with self.assertRaises(Exception):
|
||||
@cache_self1 # type: ignore[arg-type]
|
||||
def func() -> Any:
|
||||
pass
|
||||
|
||||
def test_too_many_args(self) -> None:
|
||||
with self.assertRaises(Exception):
|
||||
@cache_self1 # type: ignore[arg-type]
|
||||
def func(_1: Any, _2: Any, _3: Any) -> Any:
|
||||
pass
|
Reference in New Issue
Block a user