@@ -220,3 +220,244 @@ where
220
220
Ok ( ( ) )
221
221
}
222
222
}
223
+
224
+ #[ cfg( test) ]
225
+ mod tests {
226
+ use super :: super :: tests:: TestContext ;
227
+ use super :: super :: * ;
228
+ use super :: * ;
229
+ use crate :: virtio:: vsock:: defs:: { BACKEND_EVENT , EVQ_EVENT , RXQ_EVENT , TXQ_EVENT } ;
230
+
231
+ #[ test]
232
+ fn test_irq ( ) {
233
+ // Test case: successful IRQ signaling.
234
+ {
235
+ let test_ctx = TestContext :: new ( ) ;
236
+ let ctx = test_ctx. create_epoll_handler_context ( ) ;
237
+
238
+ ctx. handler . signal_used_queue ( ) . unwrap ( ) ;
239
+ assert_eq ! (
240
+ ctx. handler. interrupt_status. load( Ordering :: SeqCst ) ,
241
+ VIRTIO_MMIO_INT_VRING as usize
242
+ ) ;
243
+ assert_eq ! ( ctx. handler. interrupt_evt. read( ) . unwrap( ) , 1 ) ;
244
+ }
245
+
246
+ // Test case: error (a real stretch) - the event counter is full.
247
+ //
248
+ {
249
+ let test_ctx = TestContext :: new ( ) ;
250
+ let ctx = test_ctx. create_epoll_handler_context ( ) ;
251
+
252
+ ctx. handler . interrupt_evt . write ( std:: u64:: MAX - 1 ) . unwrap ( ) ;
253
+ match ctx. handler . signal_used_queue ( ) {
254
+ Err ( DeviceError :: FailedSignalingUsedQueue ( _) ) => ( ) ,
255
+ other => panic ! ( "{:?}" , other) ,
256
+ }
257
+ }
258
+ }
259
+
260
+ #[ test]
261
+ fn test_txq_event ( ) {
262
+ // Test case:
263
+ // - the driver has something to send (there's data in the TX queue); and
264
+ // - the backend has no pending RX data.
265
+ {
266
+ let test_ctx = TestContext :: new ( ) ;
267
+ let mut ctx = test_ctx. create_epoll_handler_context ( ) ;
268
+
269
+ ctx. handler . backend . set_pending_rx ( false ) ;
270
+ ctx. signal_txq_event ( ) ;
271
+
272
+ // The available TX descriptor should have been used.
273
+ assert_eq ! ( ctx. guest_txvq. used. idx. get( ) , 1 ) ;
274
+ // The available RX descriptor should be untouched.
275
+ assert_eq ! ( ctx. guest_rxvq. used. idx. get( ) , 0 ) ;
276
+ }
277
+
278
+ // Test case:
279
+ // - the driver has something to send (there's data in the TX queue); and
280
+ // - the backend also has some pending RX data.
281
+ {
282
+ let test_ctx = TestContext :: new ( ) ;
283
+ let mut ctx = test_ctx. create_epoll_handler_context ( ) ;
284
+
285
+ ctx. handler . backend . set_pending_rx ( true ) ;
286
+ ctx. signal_txq_event ( ) ;
287
+
288
+ // Both available RX and TX descriptors should have been used.
289
+ assert_eq ! ( ctx. guest_txvq. used. idx. get( ) , 1 ) ;
290
+ assert_eq ! ( ctx. guest_rxvq. used. idx. get( ) , 1 ) ;
291
+ }
292
+
293
+ // Test case:
294
+ // - the driver has something to send (there's data in the TX queue); and
295
+ // - the backend errors out and cannot process the TX queue.
296
+ {
297
+ let test_ctx = TestContext :: new ( ) ;
298
+ let mut ctx = test_ctx. create_epoll_handler_context ( ) ;
299
+
300
+ ctx. handler . backend . set_pending_rx ( false ) ;
301
+ ctx. handler . backend . set_tx_err ( Some ( VsockError :: NoData ) ) ;
302
+ ctx. signal_txq_event ( ) ;
303
+
304
+ // Both RX and TX queues should be untouched.
305
+ assert_eq ! ( ctx. guest_txvq. used. idx. get( ) , 0 ) ;
306
+ assert_eq ! ( ctx. guest_rxvq. used. idx. get( ) , 0 ) ;
307
+ }
308
+
309
+ // Test case:
310
+ // - the driver supplied a malformed TX buffer.
311
+ {
312
+ let test_ctx = TestContext :: new ( ) ;
313
+ let mut ctx = test_ctx. create_epoll_handler_context ( ) ;
314
+
315
+ // Invalidate the packet header descriptor, by setting its length to 0.
316
+ ctx. guest_txvq . dtable [ 0 ] . len . set ( 0 ) ;
317
+ ctx. signal_txq_event ( ) ;
318
+
319
+ // The available descriptor should have been consumed, but no packet should have
320
+ // reached the backend.
321
+ assert_eq ! ( ctx. guest_txvq. used. idx. get( ) , 1 ) ;
322
+ assert_eq ! ( ctx. handler. backend. tx_ok_cnt, 0 ) ;
323
+ }
324
+
325
+ // Test case: spurious TXQ_EVENT.
326
+ {
327
+ let test_ctx = TestContext :: new ( ) ;
328
+ let mut ctx = test_ctx. create_epoll_handler_context ( ) ;
329
+
330
+ match ctx. handler . handle_event ( TXQ_EVENT , epoll:: Events :: EPOLLIN ) {
331
+ Err ( DeviceError :: FailedReadingQueue { .. } ) => ( ) ,
332
+ other => panic ! ( "{:?}" , other) ,
333
+ }
334
+ }
335
+ }
336
+
337
+ #[ test]
338
+ fn test_rxq_event ( ) {
339
+ // Test case:
340
+ // - there is pending RX data in the backend; and
341
+ // - the driver makes RX buffers available; and
342
+ // - the backend successfully places its RX data into the queue.
343
+ {
344
+ let test_ctx = TestContext :: new ( ) ;
345
+ let mut ctx = test_ctx. create_epoll_handler_context ( ) ;
346
+
347
+ ctx. handler . backend . set_pending_rx ( true ) ;
348
+ ctx. handler . backend . set_rx_err ( Some ( VsockError :: NoData ) ) ;
349
+ ctx. signal_rxq_event ( ) ;
350
+
351
+ // The available RX buffer should've been left untouched.
352
+ assert_eq ! ( ctx. guest_rxvq. used. idx. get( ) , 0 ) ;
353
+ }
354
+
355
+ // Test case:
356
+ // - there is pending RX data in the backend; and
357
+ // - the driver makes RX buffers available; and
358
+ // - the backend errors out, when attempting to receive data.
359
+ {
360
+ let test_ctx = TestContext :: new ( ) ;
361
+ let mut ctx = test_ctx. create_epoll_handler_context ( ) ;
362
+
363
+ ctx. handler . backend . set_pending_rx ( true ) ;
364
+ ctx. signal_rxq_event ( ) ;
365
+
366
+ // The available RX buffer should have been used.
367
+ assert_eq ! ( ctx. guest_rxvq. used. idx. get( ) , 1 ) ;
368
+ }
369
+
370
+ // Test case: the driver provided a malformed RX descriptor chain.
371
+ {
372
+ let test_ctx = TestContext :: new ( ) ;
373
+ let mut ctx = test_ctx. create_epoll_handler_context ( ) ;
374
+
375
+ // Invalidate the packet header descriptor, by setting its length to 0.
376
+ ctx. guest_rxvq . dtable [ 0 ] . len . set ( 0 ) ;
377
+
378
+ // The chain should've been processed, without employing the backend.
379
+ assert_eq ! ( ctx. handler. process_rx( ) , true ) ;
380
+ assert_eq ! ( ctx. guest_rxvq. used. idx. get( ) , 1 ) ;
381
+ assert_eq ! ( ctx. handler. backend. rx_ok_cnt, 0 ) ;
382
+ }
383
+
384
+ // Test case: spurious RXQ_EVENT.
385
+ {
386
+ let test_ctx = TestContext :: new ( ) ;
387
+ let mut ctx = test_ctx. create_epoll_handler_context ( ) ;
388
+ ctx. handler . backend . set_pending_rx ( false ) ;
389
+ match ctx. handler . handle_event ( RXQ_EVENT , epoll:: Events :: EPOLLIN ) {
390
+ Err ( DeviceError :: FailedReadingQueue { .. } ) => ( ) ,
391
+ other => panic ! ( "{:?}" , other) ,
392
+ }
393
+ }
394
+ }
395
+
396
+ #[ test]
397
+ fn test_evq_event ( ) {
398
+ // Test case: spurious EVQ_EVENT.
399
+ {
400
+ let test_ctx = TestContext :: new ( ) ;
401
+ let mut ctx = test_ctx. create_epoll_handler_context ( ) ;
402
+ ctx. handler . backend . set_pending_rx ( false ) ;
403
+ match ctx. handler . handle_event ( EVQ_EVENT , epoll:: Events :: EPOLLIN ) {
404
+ Err ( DeviceError :: FailedReadingQueue { .. } ) => ( ) ,
405
+ other => panic ! ( "{:?}" , other) ,
406
+ }
407
+ }
408
+ }
409
+
410
+ #[ test]
411
+ fn test_backend_event ( ) {
412
+ // Test case:
413
+ // - a backend event is received; and
414
+ // - the backend has pending RX data.
415
+ {
416
+ let test_ctx = TestContext :: new ( ) ;
417
+ let mut ctx = test_ctx. create_epoll_handler_context ( ) ;
418
+
419
+ ctx. handler . backend . set_pending_rx ( true ) ;
420
+ ctx. handler
421
+ . handle_event ( BACKEND_EVENT , epoll:: Events :: EPOLLIN )
422
+ . unwrap ( ) ;
423
+
424
+ // The backend should've received this event.
425
+ assert_eq ! ( ctx. handler. backend. evset, Some ( epoll:: Events :: EPOLLIN ) ) ;
426
+ // TX queue processing should've been triggered.
427
+ assert_eq ! ( ctx. guest_txvq. used. idx. get( ) , 1 ) ;
428
+ // RX queue processing should've been triggered.
429
+ assert_eq ! ( ctx. guest_rxvq. used. idx. get( ) , 1 ) ;
430
+ }
431
+
432
+ // Test case:
433
+ // - a backend event is received; and
434
+ // - the backend doesn't have any pending RX data.
435
+ {
436
+ let test_ctx = TestContext :: new ( ) ;
437
+ let mut ctx = test_ctx. create_epoll_handler_context ( ) ;
438
+
439
+ ctx. handler . backend . set_pending_rx ( false ) ;
440
+ ctx. handler
441
+ . handle_event ( BACKEND_EVENT , epoll:: Events :: EPOLLIN )
442
+ . unwrap ( ) ;
443
+
444
+ // The backend should've received this event.
445
+ assert_eq ! ( ctx. handler. backend. evset, Some ( epoll:: Events :: EPOLLIN ) ) ;
446
+ // TX queue processing should've been triggered.
447
+ assert_eq ! ( ctx. guest_txvq. used. idx. get( ) , 1 ) ;
448
+ // The RX queue should've been left untouched.
449
+ assert_eq ! ( ctx. guest_rxvq. used. idx. get( ) , 0 ) ;
450
+ }
451
+ }
452
+
453
+ #[ test]
454
+ fn test_unknown_event ( ) {
455
+ let test_ctx = TestContext :: new ( ) ;
456
+ let mut ctx = test_ctx. create_epoll_handler_context ( ) ;
457
+
458
+ match ctx. handler . handle_event ( 0xff , epoll:: Events :: EPOLLIN ) {
459
+ Err ( DeviceError :: UnknownEvent { .. } ) => ( ) ,
460
+ other => panic ! ( "{:?}" , other) ,
461
+ }
462
+ }
463
+ }
0 commit comments