@@ -348,6 +348,58 @@ public void WhenKeysAreContinuouslyRequestedInTheOrderTheyAreAddedCountIsBounded
348
348
testOutputHelper . WriteLine ( $ "Total: { lru . Count } Hot: { lru . HotCount } Warm: { lru . WarmCount } Cold: { lru . ColdCount } ") ;
349
349
lru . Count . Should ( ) . BeLessOrEqualTo ( capacity + 1 ) ;
350
350
}
351
+ }
352
+
353
+ public class KeysInOrderTestDataGenerator : IEnumerable < object [ ] >
354
+ {
355
+ private readonly List < object [ ] > _data = new List < object [ ] >
356
+ {
357
+ new object [ ] { new EqualCapacityPartition ( hotCap + warmCap + coldCap ) } ,
358
+ new object [ ] { new EqualCapacityPartition ( 128 ) } ,
359
+ new object [ ] { new EqualCapacityPartition ( 256 ) } ,
360
+ new object [ ] { new EqualCapacityPartition ( 1024 ) } ,
361
+ new object [ ] { new FavorWarmPartition ( 128 ) } ,
362
+ new object [ ] { new FavorWarmPartition ( 256 ) } ,
363
+ new object [ ] { new FavorWarmPartition ( 1024 ) } ,
364
+ new object [ ] { new FavorWarmPartition ( 128 , 0.6 ) } ,
365
+ new object [ ] { new FavorWarmPartition ( 256 , 0.6 ) } ,
366
+ new object [ ] { new FavorWarmPartition ( 1024 , 0.6 ) } ,
367
+ //new object[] { new FavorWarmPartition(10*1024, 0.6) },
368
+ //new object[] { new FavorWarmPartition(100*1024, 0.6) },
369
+ } ;
370
+
371
+ public IEnumerator < object [ ] > GetEnumerator ( ) => _data . GetEnumerator ( ) ;
372
+
373
+ IEnumerator IEnumerable . GetEnumerator ( ) => GetEnumerator ( ) ;
374
+ }
375
+
376
+ [ Theory ]
377
+ [ ClassData ( typeof ( KeysInOrderTestDataGenerator ) ) ]
378
+ public void WhenKeysAreContinuouslyRequestedInTheOrderTheyAreAddedCountIsBounded2 ( ICapacityPartition p )
379
+ {
380
+ int capacity = p . Hot + p . Cold + p . Warm ;
381
+ lru = new ConcurrentLru < int , string > ( capacity , p , EqualityComparer < int > . Default ) ;
382
+
383
+ testOutputHelper . WriteLine ( $ "Capacity: { lru . Capacity } (Hot: { p . Hot } Warm: { p . Warm } Cold: { p . Cold } )") ;
384
+
385
+ for ( int i = 0 ; i < capacity + 10 ; i ++ )
386
+ {
387
+ lru . GetOrAdd ( i , valueFactory . Create ) ;
388
+
389
+ // Touch all items already cached in hot, warm and cold.
390
+ // This is worst case scenario, since we touch them in the exact order they
391
+ // were added.
392
+ for ( int j = 0 ; j < i ; j ++ )
393
+ {
394
+ lru . GetOrAdd ( j , valueFactory . Create ) ;
395
+ }
396
+ }
397
+
398
+ // For larger cache sizes, I have observed capacity + 5. This is linked to the number of attempts.
399
+ // This is clearly a bug that needs further investigation, but considered not harmful at this point
400
+ // since growth is bounded, we just allow 4 more items than we should in the absolute worst case.
401
+ testOutputHelper . WriteLine ( $ "Total: { lru . Count } Hot: { lru . HotCount } Warm: { lru . WarmCount } Cold: { lru . ColdCount } ") ;
402
+ lru . Count . Should ( ) . BeLessOrEqualTo ( capacity + 1 ) ;
351
403
}
352
404
353
405
[ Fact ]
0 commit comments