@@ -130,6 +130,87 @@ def test_reset(self):
130
130
cache .save ('cow' , 'crate' )
131
131
self .assertEqual (cache .lookup ('cow' ), 'crate' )
132
132
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
+
133
214
# type checker test
134
215
# confirm that LRUCache matches OptimizelySegmentsCache protocol
135
216
_ : OptimizelySegmentsCache = LRUCache (0 , 0 )
0 commit comments