1- using System ;
1+ using System ;
22using System . Collections . Generic ;
33using System . Runtime . InteropServices ;
4- using BitFaster . Caching . Lru ;
5- using FluentAssertions ;
6- using Xunit ;
7-
8- namespace BitFaster . Caching . UnitTests . Lru
9- {
10- public class ConcurrentLruAfterAccessTests
11- {
12- private readonly TimeSpan timeToLive = TimeSpan . FromMilliseconds ( 10 ) ;
13- private readonly ICapacityPartition capacity = new EqualCapacityPartition ( 9 ) ;
14- private ICache < int , string > lru ;
15-
16- private ValueFactory valueFactory = new ValueFactory ( ) ;
17-
18- private List < ItemRemovedEventArgs < int , int > > removedItems = new List < ItemRemovedEventArgs < int , int > > ( ) ;
19-
20- // on MacOS time measurement seems to be less stable, give longer pause
21- private int ttlWaitMlutiplier = RuntimeInformation . IsOSPlatform ( OSPlatform . OSX ) ? 8 : 2 ;
22-
23- private void OnLruItemRemoved ( object sender , ItemRemovedEventArgs < int , int > e )
24- {
25- removedItems . Add ( e ) ;
26- }
27-
28- public ConcurrentLruAfterAccessTests ( )
29- {
30- lru = new ConcurrentLruBuilder < int , string > ( )
31- . WithCapacity ( capacity )
32- . WithExpireAfterAccess ( timeToLive )
33- . Build ( ) ;
34- }
35-
36- [ Fact ]
37- public void CanExpireIsTrue ( )
38- {
39- this . lru . Policy . ExpireAfterAccess . HasValue . Should ( ) . BeTrue ( ) ;
40- }
41-
42- [ Fact ]
43- public void TimeToLiveIsCtorArg ( )
44- {
45- this . lru . Policy . ExpireAfterAccess . Value . TimeToLive . Should ( ) . Be ( timeToLive ) ;
46- }
47-
48- [ Fact ]
49- public void WhenItemIsNotExpiredItIsNotRemoved ( )
50- {
51- lru . GetOrAdd ( 1 , valueFactory . Create ) ;
52-
53- lru . TryGet ( 1 , out var value ) . Should ( ) . BeTrue ( ) ;
54- }
55-
56- [ Fact ]
57- public void WhenItemIsExpiredItIsRemoved ( )
4+ using BitFaster . Caching . Lru ;
5+ using FluentAssertions ;
6+ using Xunit ;
7+
8+ namespace BitFaster . Caching . UnitTests . Lru
9+ {
10+ public class ConcurrentLruAfterAccessTests
11+ {
12+ private readonly TimeSpan timeToLive = TimeSpan . FromMilliseconds ( 10 ) ;
13+ private readonly ICapacityPartition capacity = new EqualCapacityPartition ( 9 ) ;
14+ private ICache < int , string > lru ;
15+
16+ private ValueFactory valueFactory = new ValueFactory ( ) ;
17+
18+ private List < ItemRemovedEventArgs < int , int > > removedItems = new List < ItemRemovedEventArgs < int , int > > ( ) ;
19+
20+ // on MacOS time measurement seems to be less stable, give longer pause
21+ private int ttlWaitMlutiplier = RuntimeInformation . IsOSPlatform ( OSPlatform . OSX ) ? 8 : 2 ;
22+
23+ private void OnLruItemRemoved ( object sender , ItemRemovedEventArgs < int , int > e )
24+ {
25+ removedItems . Add ( e ) ;
26+ }
27+
28+ public ConcurrentLruAfterAccessTests ( )
29+ {
30+ lru = new ConcurrentLruBuilder < int , string > ( )
31+ . WithCapacity ( capacity )
32+ . WithExpireAfterAccess ( timeToLive )
33+ . Build ( ) ;
34+ }
35+
36+ [ Fact ]
37+ public void CanExpireIsTrue ( )
38+ {
39+ this . lru . Policy . ExpireAfterAccess . HasValue . Should ( ) . BeTrue ( ) ;
40+ }
41+
42+ [ Fact ]
43+ public void TimeToLiveIsCtorArg ( )
44+ {
45+ this . lru . Policy . ExpireAfterAccess . Value . TimeToLive . Should ( ) . Be ( timeToLive ) ;
46+ }
47+
48+ [ Fact ]
49+ public void WhenItemIsNotExpiredItIsNotRemoved ( )
50+ {
51+ lru . GetOrAdd ( 1 , valueFactory . Create ) ;
52+
53+ lru . TryGet ( 1 , out var value ) . Should ( ) . BeTrue ( ) ;
54+ }
55+
56+ [ Fact ]
57+ public void WhenItemIsExpiredItIsRemoved ( )
5858 {
5959 Timed . Execute (
6060 lru ,
@@ -68,97 +68,97 @@ public void WhenItemIsExpiredItIsRemoved()
6868 {
6969 lru . TryGet ( 1 , out var value ) . Should ( ) . BeFalse ( ) ;
7070 }
71- ) ;
72- }
73-
74- [ Fact ]
75- public void WhenItemIsUpdatedTtlIsExtended ( )
76- {
77- Timed . Execute (
78- lru ,
79- lru =>
71+ ) ;
72+ }
73+
74+ [ Fact ]
75+ public void WhenItemIsUpdatedTtlIsExtended ( )
76+ {
77+ Timed . Execute (
78+ lru ,
79+ lru =>
8080 {
81- lru . GetOrAdd ( 1 , valueFactory . Create ) ;
82- return lru ;
83- } ,
84- timeToLive . MultiplyBy ( ttlWaitMlutiplier ) ,
85- lru =>
81+ lru . GetOrAdd ( 1 , valueFactory . Create ) ;
82+ return lru ;
83+ } ,
84+ timeToLive . MultiplyBy ( ttlWaitMlutiplier ) ,
85+ lru =>
8686 {
8787 lru . TryUpdate ( 1 , "3" ) ;
8888 lru . TryGet ( 1 , out var value ) . Should ( ) . BeTrue ( ) ;
89- }
90- ) ;
91- }
92-
93- // Using async/await makes this very unstable due to xunit
94- // running new tests on the yielding thread. Using sleep
95- // forces the test to stay on the same thread.
96- [ Fact ]
97- public void WhenItemIsReadTtlIsExtended ( )
98- {
99- Timed . Execute (
100- capacity ,
101- cap =>
89+ }
90+ ) ;
91+ }
92+
93+ // Using async/await makes this very unstable due to xunit
94+ // running new tests on the yielding thread. Using sleep
95+ // forces the test to stay on the same thread.
96+ [ Fact ]
97+ public void WhenItemIsReadTtlIsExtended ( )
98+ {
99+ Timed . Execute (
100+ capacity ,
101+ cap =>
102102 {
103103 var lru = new ConcurrentLruBuilder < int , string > ( )
104104 . WithCapacity ( cap )
105105 . WithExpireAfterAccess ( TimeSpan . FromMilliseconds ( 100 ) )
106106 . Build ( ) ;
107107
108- lru . GetOrAdd ( 1 , valueFactory . Create ) ;
109-
110- return lru ;
111- } ,
112- TimeSpan . FromMilliseconds ( 50 ) ,
113- lru =>
108+ lru . GetOrAdd ( 1 , valueFactory . Create ) ;
109+
110+ return lru ;
111+ } ,
112+ TimeSpan . FromMilliseconds ( 50 ) ,
113+ lru =>
114114 {
115- lru . TryGet ( 1 , out _ ) . Should ( ) . BeTrue ( $ "First") ;
116- } ,
117- TimeSpan . FromMilliseconds ( 75 ) ,
118- lru =>
115+ lru . TryGet ( 1 , out _ ) . Should ( ) . BeTrue ( $ "First") ;
116+ } ,
117+ TimeSpan . FromMilliseconds ( 75 ) ,
118+ lru =>
119119 {
120- lru . TryGet ( 1 , out var value ) . Should ( ) . BeTrue ( $ "Second") ;
121- }
122- ) ;
123- }
124-
125- [ Fact ]
126- public void WhenValueEvictedItemRemovedEventIsFired ( )
127- {
128- var lruEvents = new ConcurrentLruBuilder < int , int > ( )
129- . WithCapacity ( new EqualCapacityPartition ( 6 ) )
130- . WithExpireAfterAccess ( TimeSpan . FromSeconds ( 10 ) )
131- . WithMetrics ( )
132- . Build ( ) ;
133-
134- lruEvents . Events . Value . ItemRemoved += OnLruItemRemoved ;
135-
136- // First 6 adds
137- // hot[6, 5], warm[2, 1], cold[4, 3]
138- // =>
139- // hot[8, 7], warm[1, 0], cold[6, 5], evicted[4, 3]
140- for ( int i = 0 ; i < 8 ; i ++ )
141- {
142- lruEvents . GetOrAdd ( i + 1 , i => i + 1 ) ;
143- }
144-
145- removedItems . Count . Should ( ) . Be ( 2 ) ;
146-
147- removedItems [ 0 ] . Key . Should ( ) . Be ( 1 ) ;
148- removedItems [ 0 ] . Value . Should ( ) . Be ( 2 ) ;
149- removedItems [ 0 ] . Reason . Should ( ) . Be ( ItemRemovedReason . Evicted ) ;
150-
151- removedItems [ 1 ] . Key . Should ( ) . Be ( 4 ) ;
152- removedItems [ 1 ] . Value . Should ( ) . Be ( 5 ) ;
153- removedItems [ 1 ] . Reason . Should ( ) . Be ( ItemRemovedReason . Evicted ) ;
154- }
155-
156- [ Fact ]
157- public void WhenItemsAreExpiredExpireRemovesExpiredItems ( )
158- {
159- Timed . Execute (
160- lru ,
161- lru =>
120+ lru . TryGet ( 1 , out var value ) . Should ( ) . BeTrue ( $ "Second") ;
121+ }
122+ ) ;
123+ }
124+
125+ [ Fact ]
126+ public void WhenValueEvictedItemRemovedEventIsFired ( )
127+ {
128+ var lruEvents = new ConcurrentLruBuilder < int , int > ( )
129+ . WithCapacity ( new EqualCapacityPartition ( 6 ) )
130+ . WithExpireAfterAccess ( TimeSpan . FromSeconds ( 10 ) )
131+ . WithMetrics ( )
132+ . Build ( ) ;
133+
134+ lruEvents . Events . Value . ItemRemoved += OnLruItemRemoved ;
135+
136+ // First 6 adds
137+ // hot[6, 5], warm[2, 1], cold[4, 3]
138+ // =>
139+ // hot[8, 7], warm[1, 0], cold[6, 5], evicted[4, 3]
140+ for ( int i = 0 ; i < 8 ; i ++ )
141+ {
142+ lruEvents . GetOrAdd ( i + 1 , i => i + 1 ) ;
143+ }
144+
145+ removedItems . Count . Should ( ) . Be ( 2 ) ;
146+
147+ removedItems [ 0 ] . Key . Should ( ) . Be ( 1 ) ;
148+ removedItems [ 0 ] . Value . Should ( ) . Be ( 2 ) ;
149+ removedItems [ 0 ] . Reason . Should ( ) . Be ( ItemRemovedReason . Evicted ) ;
150+
151+ removedItems [ 1 ] . Key . Should ( ) . Be ( 4 ) ;
152+ removedItems [ 1 ] . Value . Should ( ) . Be ( 5 ) ;
153+ removedItems [ 1 ] . Reason . Should ( ) . Be ( ItemRemovedReason . Evicted ) ;
154+ }
155+
156+ [ Fact ]
157+ public void WhenItemsAreExpiredExpireRemovesExpiredItems ( )
158+ {
159+ Timed . Execute (
160+ lru ,
161+ lru =>
162162 {
163163 lru . AddOrUpdate ( 1 , "1" ) ;
164164 lru . AddOrUpdate ( 2 , "2" ) ;
@@ -175,20 +175,20 @@ public void WhenItemsAreExpiredExpireRemovesExpiredItems()
175175 lru . AddOrUpdate ( 8 , "8" ) ;
176176 lru . AddOrUpdate ( 9 , "9" ) ;
177177
178- return lru ;
179- } ,
180- timeToLive . MultiplyBy ( ttlWaitMlutiplier ) ,
178+ return lru ;
179+ } ,
180+ timeToLive . MultiplyBy ( ttlWaitMlutiplier ) ,
181181 lru =>
182182 {
183183 lru . Policy . ExpireAfterAccess . Value . TrimExpired ( ) ;
184184
185185 lru . Count . Should ( ) . Be ( 0 ) ;
186- }
187- ) ;
188- }
189-
190- [ Fact ]
191- public void WhenCacheHasExpiredAndFreshItemsExpireRemovesOnlyExpiredItems ( )
186+ }
187+ ) ;
188+ }
189+
190+ [ Fact ]
191+ public void WhenCacheHasExpiredAndFreshItemsExpireRemovesOnlyExpiredItems ( )
192192 {
193193 Timed . Execute (
194194 lru ,
@@ -215,11 +215,11 @@ public void WhenCacheHasExpiredAndFreshItemsExpireRemovesOnlyExpiredItems()
215215
216216 lru . Count . Should ( ) . Be ( 3 ) ;
217217 }
218- ) ;
219- }
220-
221- [ Fact ]
222- public void WhenItemsAreExpiredTrimRemovesExpiredItems ( )
218+ ) ;
219+ }
220+
221+ [ Fact ]
222+ public void WhenItemsAreExpiredTrimRemovesExpiredItems ( )
223223 {
224224 Timed . Execute (
225225 lru ,
@@ -238,7 +238,7 @@ public void WhenItemsAreExpiredTrimRemovesExpiredItems()
238238
239239 lru . Count . Should ( ) . Be ( 0 ) ;
240240 }
241- ) ;
242- }
243- }
244- }
241+ ) ;
242+ }
243+ }
244+ }
0 commit comments