Add basic cancellation tests for @cached and @cachedList decorators
This commit is contained in:
@@ -17,7 +17,7 @@ from typing import Set
|
||||
from unittest import mock
|
||||
|
||||
from twisted.internet import defer, reactor
|
||||
from twisted.internet.defer import Deferred
|
||||
from twisted.internet.defer import CancelledError, Deferred
|
||||
|
||||
from synapse.api.errors import SynapseError
|
||||
from synapse.logging.context import (
|
||||
@@ -28,7 +28,7 @@ from synapse.logging.context import (
|
||||
make_deferred_yieldable,
|
||||
)
|
||||
from synapse.util.caches import descriptors
|
||||
from synapse.util.caches.descriptors import cached, lru_cache
|
||||
from synapse.util.caches.descriptors import cached, cachedList, lru_cache
|
||||
|
||||
from tests import unittest
|
||||
from tests.test_utils import get_awaitable_result
|
||||
@@ -415,6 +415,31 @@ class DescriptorTestCase(unittest.TestCase):
|
||||
obj.invalidate()
|
||||
top_invalidate.assert_called_once()
|
||||
|
||||
def test_cancel(self):
|
||||
"""Test that cancelling a lookup does not cancel other lookups"""
|
||||
complete_lookup: "Deferred[None]" = Deferred()
|
||||
|
||||
class Cls:
|
||||
@cached()
|
||||
async def fn(self, arg1):
|
||||
await complete_lookup
|
||||
return str(arg1)
|
||||
|
||||
obj = Cls()
|
||||
|
||||
d1 = obj.fn(123)
|
||||
d2 = obj.fn(123)
|
||||
self.assertFalse(d1.called)
|
||||
self.assertFalse(d2.called)
|
||||
|
||||
# Cancel `d1`, which is the lookup that caused `fn` to run.
|
||||
d1.cancel()
|
||||
|
||||
# `d2` should complete normally.
|
||||
complete_lookup.callback(None)
|
||||
self.failureResultOf(d1, CancelledError)
|
||||
self.assertEqual(d2.result, "123")
|
||||
|
||||
|
||||
class CacheDecoratorTestCase(unittest.HomeserverTestCase):
|
||||
"""More tests for @cached
|
||||
@@ -787,3 +812,31 @@ class CachedListDescriptorTestCase(unittest.TestCase):
|
||||
obj.fn.invalidate((10, 2))
|
||||
invalidate0.assert_called_once()
|
||||
invalidate1.assert_called_once()
|
||||
|
||||
def test_cancel(self):
|
||||
"""Test that cancelling a lookup does not cancel other lookups"""
|
||||
complete_lookup: "Deferred[None]" = Deferred()
|
||||
|
||||
class Cls:
|
||||
@cached()
|
||||
def fn(self, arg1):
|
||||
pass
|
||||
|
||||
@cachedList("fn", "args")
|
||||
async def list_fn(self, args):
|
||||
await complete_lookup
|
||||
return {arg: str(arg) for arg in args}
|
||||
|
||||
obj = Cls()
|
||||
|
||||
d1 = obj.list_fn([123, 456])
|
||||
d2 = obj.list_fn([123, 456, 789])
|
||||
self.assertFalse(d1.called)
|
||||
self.assertFalse(d2.called)
|
||||
|
||||
d1.cancel()
|
||||
|
||||
# `d2` should complete normally.
|
||||
complete_lookup.callback(None)
|
||||
self.failureResultOf(d1, CancelledError)
|
||||
self.assertEqual(d2.result, {123: "123", 456: "456", 789: "789"})
|
||||
|
||||
Reference in New Issue
Block a user