diff --git a/tests/util/caches/test_descriptors.py b/tests/util/caches/test_descriptors.py
index 19741ffcda..6a4b17527a 100644
--- a/tests/util/caches/test_descriptors.py
+++ b/tests/util/caches/test_descriptors.py
@@ -141,6 +141,84 @@ class DescriptorTestCase(unittest.TestCase):
self.assertEqual(r, "chips")
obj.mock.assert_not_called()
+ @defer.inlineCallbacks
+ def test_cache_uncached_args(self):
+ """
+ Only the arguments not named in uncached_args should matter to the cache
+
+ Note that this is identical to test_cache_num_args, but provides the
+ arguments differently.
+ """
+
+ class Cls:
+ # Note that it is important that this is not the last argument to
+ # test behaviour of skipping arguments properly.
+ @descriptors.cached(uncached_args=("arg2",))
+ def fn(self, arg1, arg2, arg3):
+ return self.mock(arg1, arg2, arg3)
+
+ def __init__(self):
+ self.mock = mock.Mock()
+
+ obj = Cls()
+ obj.mock.return_value = "fish"
+ r = yield obj.fn(1, 2, 3)
+ self.assertEqual(r, "fish")
+ obj.mock.assert_called_once_with(1, 2, 3)
+ obj.mock.reset_mock()
+
+ # a call with different params should call the mock again
+ obj.mock.return_value = "chips"
+ r = yield obj.fn(2, 3, 4)
+ self.assertEqual(r, "chips")
+ obj.mock.assert_called_once_with(2, 3, 4)
+ obj.mock.reset_mock()
+
+ # the two values should now be cached; we should be able to vary
+ # the second argument and still get the cached result.
+ r = yield obj.fn(1, 4, 3)
+ self.assertEqual(r, "fish")
+ r = yield obj.fn(2, 5, 4)
+ self.assertEqual(r, "chips")
+ obj.mock.assert_not_called()
+
+ @defer.inlineCallbacks
+ def test_cache_kwargs(self):
+ """Test that keyword arguments are treated properly"""
+
+ class Cls:
+ def __init__(self):
+ self.mock = mock.Mock()
+
+ @descriptors.cached()
+ def fn(self, arg1, kwarg1=2):
+ return self.mock(arg1, kwarg1=kwarg1)
+
+ obj = Cls()
+ obj.mock.return_value = "fish"
+ r = yield obj.fn(1, kwarg1=2)
+ self.assertEqual(r, "fish")
+ obj.mock.assert_called_once_with(1, kwarg1=2)
+ obj.mock.reset_mock()
+
+ # a call with different params should call the mock again
+ obj.mock.return_value = "chips"
+ r = yield obj.fn(1, kwarg1=3)
+ self.assertEqual(r, "chips")
+ obj.mock.assert_called_once_with(1, kwarg1=3)
+ obj.mock.reset_mock()
+
+ # the values should now be cached.
+ r = yield obj.fn(1, kwarg1=2)
+ self.assertEqual(r, "fish")
+ # We should be able to not provide kwarg1 and get the cached value back.
+ r = yield obj.fn(1)
+ self.assertEqual(r, "fish")
+ # Keyword arguments can be in any order.
+ r = yield obj.fn(kwarg1=2, arg1=1)
+ self.assertEqual(r, "fish")
+ obj.mock.assert_not_called()
+
def test_cache_with_sync_exception(self):
"""If the wrapped function throws synchronously, things should continue to work"""
@@ -656,7 +734,7 @@ class CachedListDescriptorTestCase(unittest.TestCase):
def fn(self, arg1, arg2):
pass
- @descriptors.cachedList("fn", "args1")
+ @descriptors.cachedList(cached_method_name="fn", list_name="args1")
async def list_fn(self, args1, arg2):
assert current_context().name == "c1"
# we want this to behave like an asynchronous function
@@ -715,7 +793,7 @@ class CachedListDescriptorTestCase(unittest.TestCase):
def fn(self, arg1):
pass
- @descriptors.cachedList("fn", "args1")
+ @descriptors.cachedList(cached_method_name="fn", list_name="args1")
def list_fn(self, args1) -> "Deferred[dict]":
return self.mock(args1)
@@ -758,7 +836,7 @@ class CachedListDescriptorTestCase(unittest.TestCase):
def fn(self, arg1, arg2):
pass
- @descriptors.cachedList("fn", "args1")
+ @descriptors.cachedList(cached_method_name="fn", list_name="args1")
async def list_fn(self, args1, arg2):
# we want this to behave like an asynchronous function
await run_on_reactor()
|