5
5
SPDX-License-Identifier: Apache-2.0
6
6
Authors: Mihai Criveti
7
7
8
+ Unit tests for ResourceCache.
8
9
"""
10
+ import asyncio
11
+ import time
12
+ import pytest
13
+
14
+ from mcpgateway .cache .resource_cache import ResourceCache
15
+
16
+ @pytest .fixture
17
+ def cache ():
18
+ """Fixture for a ResourceCache with small TTL and size for testing."""
19
+ return ResourceCache (max_size = 3 , ttl = 1 )
20
+
21
+ def test_set_and_get (cache ):
22
+ """Test setting and getting a cache value."""
23
+ cache .set ("foo" , "bar" )
24
+ assert cache .get ("foo" ) == "bar"
25
+
26
+ def test_get_missing (cache ):
27
+ """Test getting a missing key returns None."""
28
+ assert cache .get ("missing" ) is None
29
+
30
+ def test_expiration (cache ):
31
+ """Test that cache entry expires after TTL."""
32
+ cache .set ("foo" , "bar" )
33
+ time .sleep (1.1 )
34
+ assert cache .get ("foo" ) is None
35
+
36
+ def test_lru_eviction (cache ):
37
+ """Test LRU eviction when max_size is reached."""
38
+ cache .set ("a" , 1 )
39
+ cache .set ("b" , 2 )
40
+ cache .set ("c" , 3 )
41
+ # Access 'a' to update its last_access
42
+ assert cache .get ("a" ) == 1
43
+ # Add another entry, should evict 'b' (least recently used)
44
+ cache .set ("d" , 4 )
45
+ assert cache .get ("b" ) is None
46
+ assert cache .get ("a" ) == 1
47
+ assert cache .get ("c" ) == 3
48
+ assert cache .get ("d" ) == 4
49
+
50
+ def test_delete (cache ):
51
+ """Test deleting a cache entry."""
52
+ cache .set ("foo" , "bar" )
53
+ cache .delete ("foo" )
54
+ assert cache .get ("foo" ) is None
55
+
56
+ def test_clear (cache ):
57
+ """Test clearing the cache."""
58
+ cache .set ("foo" , "bar" )
59
+ cache .set ("baz" , "qux" )
60
+ cache .clear ()
61
+ assert cache .get ("foo" ) is None
62
+ assert cache .get ("baz" ) is None
63
+
64
+ @pytest .mark .asyncio
65
+ async def test_initialize_and_shutdown_logs (monkeypatch ):
66
+ """Test initialize and shutdown log and cleanup."""
67
+ cache = ResourceCache (max_size = 2 , ttl = 1 )
68
+ monkeypatch .setattr ("mcpgateway.cache.resource_cache.logger" , DummyLogger ())
69
+ await cache .initialize ()
70
+ cache .set ("foo" , "bar" )
71
+ await cache .shutdown ()
72
+ assert cache .get ("foo" ) is None
73
+
74
+ @pytest .mark .asyncio
75
+ async def test_cleanup_loop_removes_expired (monkeypatch ):
76
+ """Test that the cleanup loop removes expired entries."""
77
+ cache = ResourceCache (max_size = 2 , ttl = 0.1 )
78
+ cache .set ("foo" , "bar" )
79
+ await asyncio .sleep (0.15 )
80
+ # Manually trigger cleanup for test speed
81
+ async with cache ._lock :
82
+ now = time .time ()
83
+ expired = [key for key , entry in cache ._cache .items () if now > entry .expires_at ]
84
+ for key in expired :
85
+ del cache ._cache [key ]
86
+ assert cache .get ("foo" ) is None
87
+
88
+ class DummyLogger :
89
+ def info (self , msg ): pass
90
+ def debug (self , msg ): pass
91
+ def error (self , msg ): pass
0 commit comments