@@ -389,4 +389,84 @@ mod tests {
389389 // And verify that the underlying allocation hasn't changed.
390390 assert_eq ! ( cache. entries[ 1 ] . data. as_ptr( ) , block123_ptr) ;
391391 }
392+
393+ #[ test]
394+ fn test_get_or_insert_blocks ( ) {
395+ let num_fs_blocks = 8 ;
396+ let mut cache = BlockCache :: with_opts (
397+ CacheOpts {
398+ block_size : get_block_size ( 1024 ) ,
399+ max_blocks_per_read : 2 ,
400+ num_entries : 4 ,
401+ } ,
402+ num_fs_blocks,
403+ )
404+ . unwrap ( ) ;
405+
406+ // Test that an error in the closure is propagated.
407+ assert_eq ! (
408+ cache
409+ . get_or_insert_blocks( 1 , |_| {
410+ Err ( CorruptKind :: TooManyBlocksInFile . into( ) )
411+ } )
412+ . unwrap_err( ) ,
413+ CorruptKind :: TooManyBlocksInFile
414+ ) ;
415+
416+ // Request block 1. This requires reading, so blocks 1 and 2 are
417+ // added to the cache.
418+ let data = cache
419+ . get_or_insert_blocks ( 1 , |buf| {
420+ // Expecting two blocks due to `max_blocks_per_read=2`.
421+ assert_eq ! ( buf. len( ) , 1024 * 2 ) ;
422+
423+ // Block 1:
424+ buf[ 0 ] = 3 ;
425+ // Block 2:
426+ buf[ 1024 ] = 4 ;
427+
428+ Ok ( ( ) )
429+ } )
430+ . unwrap ( ) ;
431+
432+ // Check that block 1's data was returned.
433+ assert_eq ! ( data[ 0 ] , 3 ) ;
434+
435+ // Requested block should be at the front of the cache.
436+ assert_eq ! ( cache. entries[ 0 ] . block_index, 1 ) ;
437+ assert_eq ! ( cache. entries[ 0 ] . data[ 0 ] , 3 ) ;
438+ // Followed by the other blocks read.
439+ assert_eq ! ( cache. entries[ 1 ] . block_index, 2 ) ;
440+ assert_eq ! ( cache. entries[ 1 ] . data[ 0 ] , 4 ) ;
441+
442+ // Request block 2. This is already in the cache, so no read
443+ // should occur.
444+ let data = cache
445+ . get_or_insert_blocks ( 2 , |_| {
446+ panic ! ( "read closure called unexpectedly" ) ;
447+ } )
448+ . unwrap ( ) ;
449+
450+ // Check that block 2's data was returned.
451+ assert_eq ! ( data[ 0 ] , 4 ) ;
452+
453+ // The requested block should now be at the front of the cache.
454+ assert_eq ! ( cache. entries[ 0 ] . block_index, 2 ) ;
455+ assert_eq ! ( cache. entries[ 1 ] . block_index, 1 ) ;
456+
457+ // Add blocks 3 and 4 to the cache.
458+ cache. get_or_insert_blocks ( 3 , |_| Ok ( ( ) ) ) . unwrap ( ) ;
459+ assert_eq ! ( cache. entries[ 0 ] . block_index, 3 ) ;
460+ assert_eq ! ( cache. entries[ 1 ] . block_index, 4 ) ;
461+ assert_eq ! ( cache. entries[ 2 ] . block_index, 2 ) ;
462+ assert_eq ! ( cache. entries[ 3 ] . block_index, 1 ) ;
463+
464+ // Add blocks 5 and 6 to the cache. This causes blocks 1 and 2
465+ // to be evicted.
466+ cache. get_or_insert_blocks ( 5 , |_| Ok ( ( ) ) ) . unwrap ( ) ;
467+ assert_eq ! ( cache. entries[ 0 ] . block_index, 5 ) ;
468+ assert_eq ! ( cache. entries[ 1 ] . block_index, 6 ) ;
469+ assert_eq ! ( cache. entries[ 2 ] . block_index, 3 ) ;
470+ assert_eq ! ( cache. entries[ 3 ] . block_index, 4 ) ;
471+ }
392472}
0 commit comments