Skip to content

Commit f6d9cb1

Browse files
committed
Improve IndividualCache test cases
1 parent e1fd179 commit f6d9cb1

File tree

2 files changed

+24
-6
lines changed

2 files changed

+24
-6
lines changed

msal/individual_cache.py

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,10 @@ def __init__(self, mapping=None, capacity=None, expires_in=None, lock=None,
5959
self._expires_in = expires_in
6060
self._lock = Lock() if lock is None else lock
6161

62+
def _peek(self):
63+
# Returns (sequence, timestamps) without triggering maintenance
64+
return self._mapping.get(self._INDEX, ([], {}))
65+
6266
def _validate_key(self, key):
6367
if key == self._INDEX:
6468
raise ValueError("key {} is a reserved keyword in {}".format(
@@ -85,7 +89,7 @@ def _set(self, key, value, expires_in):
8589
# This internal implementation powers both set() and __setitem__(),
8690
# so that they don't depend on each other.
8791
self._validate_key(key)
88-
sequence, timestamps = self._mapping.get(self._INDEX, ([], {}))
92+
sequence, timestamps = self._peek()
8993
self._maintenance(sequence, timestamps) # O(logN)
9094
now = int(time.time())
9195
expires_at = now + expires_in
@@ -136,7 +140,7 @@ def __getitem__(self, key): # O(1)
136140
self._validate_key(key)
137141
with self._lock:
138142
# Skip self._maintenance(), because it would need O(logN) time
139-
sequence, timestamps = self._mapping.get(self._INDEX, ([], {}))
143+
sequence, timestamps = self._peek()
140144
expires_at, created_at = timestamps[key] # Would raise KeyError accordingly
141145
now = int(time.time())
142146
if not created_at <= now < expires_at:
@@ -155,22 +159,22 @@ def __delitem__(self, key): # O(1)
155159
with self._lock:
156160
# Skip self._maintenance(), because it would need O(logN) time
157161
self._mapping.pop(key, None) # O(1)
158-
sequence, timestamps = self._mapping.get(self._INDEX, ([], {}))
162+
sequence, timestamps = self._peek()
159163
del timestamps[key] # O(1)
160164
self._mapping[self._INDEX] = sequence, timestamps
161165

162166
def __len__(self): # O(logN)
163167
"""Drop all expired items and return the remaining length"""
164168
with self._lock:
165-
sequence, timestamps = self._mapping.get(self._INDEX, ([], {}))
169+
sequence, timestamps = self._peek()
166170
self._maintenance(sequence, timestamps) # O(logN)
167171
self._mapping[self._INDEX] = sequence, timestamps
168172
return len(timestamps) # Faster than iter(self._mapping) when it is on disk
169173

170174
def __iter__(self):
171175
"""Drop all expired items and return an iterator of the remaining items"""
172176
with self._lock:
173-
sequence, timestamps = self._mapping.get(self._INDEX, ([], {}))
177+
sequence, timestamps = self._peek()
174178
self._maintenance(sequence, timestamps) # O(logN)
175179
self._mapping[self._INDEX] = sequence, timestamps
176180
return iter(timestamps) # Faster than iter(self._mapping) when it is on disk

tests/test_individual_cache.py

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,10 @@ def setUp(self):
1010
self.mapping = {}
1111
self.m = ExpiringMapping(mapping=self.mapping, capacity=2, expires_in=1)
1212

13+
def how_many(self):
14+
# This helper checks how many items are in the mapping, WITHOUT triggering purge
15+
return len(self.m._peek()[1])
16+
1317
def test_should_disallow_accessing_reserved_keyword(self):
1418
with self.assertRaises(ValueError):
1519
self.m.get(ExpiringMapping._INDEX)
@@ -40,11 +44,21 @@ def test_iter_should_purge(self):
4044
sleep(1)
4145
self.assertEqual([], list(self.m))
4246

43-
def test_get_should_purge(self):
47+
def test_get_should_not_purge_and_should_return_only_when_the_item_is_still_valid(self):
4448
self.m["thing one"] = "one"
49+
self.m["thing two"] = "two"
4550
sleep(1)
51+
self.assertEqual(2, self.how_many(), "We begin with 2 items")
4652
with self.assertRaises(KeyError):
4753
self.m["thing one"]
54+
self.assertEqual(1, self.how_many(), "get() should not purge the remaining items")
55+
56+
def test_setitem_should_purge(self):
57+
self.m["thing one"] = "one"
58+
sleep(1)
59+
self.m["thing two"] = "two"
60+
self.assertEqual(1, self.how_many(), "setitem() should purge all expired items")
61+
self.assertEqual("two", self.m["thing two"], "The remaining item should be thing two")
4862

4963
def test_various_expiring_time(self):
5064
self.assertEqual(0, len(self.m))

0 commit comments

Comments
 (0)