@@ -184,6 +184,111 @@ def test_free_kv_cache_block_queue_operations():
184
184
assert str (e .value ) == "No free blocks available"
185
185
186
186
187
+ def test_free_kv_cache_block_queue_append_n ():
188
+ # Create an empty FreeKVCacheBlockQueue with these blocks
189
+ queue = FreeKVCacheBlockQueue ([])
190
+ blocks = [KVCacheBlock (block_id = i ) for i in range (6 )]
191
+ # Append 0 block
192
+ # fake_head->fake_tail
193
+ queue .append_n ([])
194
+ assert queue .num_free_blocks == 0
195
+ assert (queue .fake_free_list_head .next_free_block
196
+ is queue .fake_free_list_tail )
197
+ assert (queue .fake_free_list_tail .prev_free_block
198
+ is queue .fake_free_list_head )
199
+ # Append 1 block
200
+ # fake_head->b0->fake_tail
201
+ queue .append_n (blocks [0 :1 ])
202
+ assert queue .num_free_blocks == 1
203
+ assert queue .fake_free_list_head .next_free_block is blocks [0 ]
204
+ assert blocks [0 ].prev_free_block is queue .fake_free_list_head
205
+ assert blocks [0 ].next_free_block is queue .fake_free_list_tail
206
+ assert queue .fake_free_list_tail .prev_free_block is blocks [0 ]
207
+ # Append 2 blocks
208
+ # fake_head->b0->b4->b5->fake_tail
209
+ queue .append_n (blocks [4 :6 ])
210
+ assert queue .num_free_blocks == 3
211
+ assert queue .fake_free_list_head .next_free_block is blocks [0 ]
212
+ assert blocks [0 ].prev_free_block is queue .fake_free_list_head
213
+ assert blocks [0 ].next_free_block is blocks [4 ]
214
+ assert blocks [4 ].prev_free_block is blocks [0 ]
215
+ assert blocks [4 ].next_free_block is blocks [5 ]
216
+ assert blocks [5 ].prev_free_block is blocks [4 ]
217
+ assert blocks [5 ].next_free_block is queue .fake_free_list_tail
218
+ assert queue .fake_free_list_tail .prev_free_block is blocks [5 ]
219
+ # Append 3 blocks
220
+ # fake_head->b0->b4->b5->b1->b2->b3->fake_tail
221
+ queue .append_n (blocks [1 :4 ])
222
+ assert queue .num_free_blocks == 6
223
+ assert queue .fake_free_list_head .next_free_block is blocks [0 ]
224
+ assert blocks [0 ].prev_free_block is queue .fake_free_list_head
225
+ assert blocks [0 ].next_free_block is blocks [4 ]
226
+ assert blocks [4 ].prev_free_block is blocks [0 ]
227
+ assert blocks [4 ].next_free_block is blocks [5 ]
228
+ assert blocks [5 ].prev_free_block is blocks [4 ]
229
+ assert blocks [5 ].next_free_block is blocks [1 ]
230
+ assert blocks [1 ].prev_free_block is blocks [5 ]
231
+ assert blocks [1 ].next_free_block is blocks [2 ]
232
+ assert blocks [2 ].prev_free_block is blocks [1 ]
233
+ assert blocks [2 ].next_free_block is blocks [3 ]
234
+ assert blocks [3 ].prev_free_block is blocks [2 ]
235
+ assert blocks [3 ].next_free_block is queue .fake_free_list_tail
236
+ assert queue .fake_free_list_tail .prev_free_block is blocks [3 ]
237
+
238
+
239
+ def test_free_kv_cache_block_queue_popleft_n ():
240
+ blocks = [KVCacheBlock (block_id = i ) for i in range (6 )]
241
+ # Create a empty FreeKVCacheBlockQueue with these blocks
242
+ queue = FreeKVCacheBlockQueue (
243
+ [blocks [1 ], blocks [3 ], blocks [5 ], blocks [4 ], blocks [0 ], blocks [2 ]])
244
+ assert queue .num_free_blocks == 6
245
+ assert queue .fake_free_list_head .next_free_block is blocks [1 ]
246
+ assert blocks [1 ].prev_free_block is queue .fake_free_list_head
247
+ assert blocks [1 ].next_free_block is blocks [3 ]
248
+ assert blocks [3 ].prev_free_block is blocks [1 ]
249
+ assert blocks [3 ].next_free_block is blocks [5 ]
250
+ assert blocks [5 ].prev_free_block is blocks [3 ]
251
+ assert blocks [5 ].next_free_block is blocks [4 ]
252
+ assert blocks [4 ].prev_free_block is blocks [5 ]
253
+ assert blocks [4 ].next_free_block is blocks [0 ]
254
+ assert blocks [0 ].prev_free_block is blocks [4 ]
255
+ assert blocks [0 ].next_free_block is blocks [2 ]
256
+ assert blocks [2 ].prev_free_block is blocks [0 ]
257
+ assert blocks [2 ].next_free_block is queue .fake_free_list_tail
258
+ assert queue .fake_free_list_tail .prev_free_block is blocks [2 ]
259
+
260
+ # Pop 0 block
261
+ # fake_head->b1->b3->b5->b4->b0->b2->fake_tail
262
+ assert len (queue .popleft_n (0 )) == 0
263
+ # Pop 1 block
264
+ # fake_head->b3->b5->b4->b0->b2->fake_tail
265
+ result_blocks = queue .popleft_n (1 )
266
+ assert len (result_blocks ) == 1
267
+ assert result_blocks [0 ] is blocks [1 ]
268
+ for block in result_blocks :
269
+ assert block .prev_free_block is None
270
+ assert block .next_free_block is None
271
+ # Pop 2 blocks
272
+ # fake_head->b4->b0->b2->fake_tail
273
+ result_blocks = queue .popleft_n (2 )
274
+ assert len (result_blocks ) == 2
275
+ assert result_blocks [0 ] is blocks [3 ]
276
+ assert result_blocks [1 ] is blocks [5 ]
277
+ for block in result_blocks :
278
+ assert block .prev_free_block is None
279
+ assert block .next_free_block is None
280
+ # Pop 3 blocks
281
+ # fake_head->fake_tail
282
+ result_blocks = queue .popleft_n (3 )
283
+ assert len (result_blocks ) == 3
284
+ assert result_blocks [0 ] is blocks [4 ]
285
+ assert result_blocks [1 ] is blocks [0 ]
286
+ assert result_blocks [2 ] is blocks [2 ]
287
+ for block in result_blocks :
288
+ assert block .prev_free_block is None
289
+ assert block .next_free_block is None
290
+
291
+
187
292
def test_free_kv_cache_block_queue_get_all_free_blocks ():
188
293
# Create a list of KVCacheBlock objects
189
294
blocks = [KVCacheBlock (block_id = i ) for i in range (5 )]
0 commit comments