@@ -130,6 +130,87 @@ def test_reset(self):
130130 cache .save ('cow' , 'crate' )
131131 self .assertEqual (cache .lookup ('cow' ), 'crate' )
132132
133+ def test_remove_non_existent_key (self ):
134+ cache = LRUCache (3 , 1000 )
135+ cache .save ("1" , 100 )
136+ cache .save ("2" , 200 )
137+
138+ cache .remove ("3" ) # Doesn't exist
139+
140+ self .assertEqual (cache .lookup ("1" ), 100 )
141+ self .assertEqual (cache .lookup ("2" ), 200 )
142+ self .assertEqual (len (cache .map ), 2 )
143+
144+ def test_remove_existing_key (self ):
145+ cache = LRUCache (3 , 1000 )
146+
147+ cache .save ("1" , 100 )
148+ cache .save ("2" , 200 )
149+ cache .save ("3" , 300 )
150+
151+ self .assertEqual (cache .lookup ("1" ), 100 )
152+ self .assertEqual (cache .lookup ("2" ), 200 )
153+ self .assertEqual (cache .lookup ("3" ), 300 )
154+ self .assertEqual (len (cache .map ), 3 )
155+
156+ cache .remove ("2" )
157+
158+ self .assertEqual (cache .lookup ("1" ), 100 )
159+ self .assertIsNone (cache .lookup ("2" ))
160+ self .assertEqual (cache .lookup ("3" ), 300 )
161+ self .assertEqual (len (cache .map ), 2 )
162+
163+ def test_remove_from_zero_sized_cache (self ):
164+ cache = LRUCache (0 , 1000 )
165+ cache .save ("1" , 100 )
166+ cache .remove ("1" )
167+
168+ self .assertIsNone (cache .lookup ("1" ))
169+ self .assertEqual (len (cache .map ), 0 )
170+
171+ def test_remove_and_add_back (self ):
172+ cache = LRUCache (3 , 1000 )
173+ cache .save ("1" , 100 )
174+ cache .save ("2" , 200 )
175+ cache .save ("3" , 300 )
176+
177+ cache .remove ("2" )
178+ cache .save ("2" , 201 )
179+
180+ self .assertEqual (cache .lookup ("1" ), 100 )
181+ self .assertEqual (cache .lookup ("2" ), 201 )
182+ self .assertEqual (cache .lookup ("3" ), 300 )
183+ self .assertEqual (len (cache .map ), 3 )
184+
185+ def test_thread_safety (self ):
186+ import threading
187+
188+ max_size = 100
189+ cache = LRUCache (max_size , 1000 )
190+
191+ for i in range (1 , max_size + 1 ):
192+ cache .save (str (i ), i * 100 )
193+
194+ def remove_key (k ):
195+ cache .remove (str (k ))
196+
197+ threads = []
198+ for i in range (1 , (max_size // 2 ) + 1 ):
199+ thread = threading .Thread (target = remove_key , args = (i ,))
200+ threads .append (thread )
201+ thread .start ()
202+
203+ for thread in threads :
204+ thread .join ()
205+
206+ for i in range (1 , max_size + 1 ):
207+ if i <= max_size // 2 :
208+ self .assertIsNone (cache .lookup (str (i )))
209+ else :
210+ self .assertEqual (cache .lookup (str (i )), i * 100 )
211+
212+ self .assertEqual (len (cache .map ), max_size // 2 )
213+
133214 # type checker test
134215 # confirm that LRUCache matches OptimizelySegmentsCache protocol
135216 _ : OptimizelySegmentsCache = LRUCache (0 , 0 )
0 commit comments