99using System . Threading . Tasks ;
1010using Xunit ;
1111
12- namespace AsyncMemoryCache . Tests
12+ namespace AsyncMemoryCache . Tests ;
13+
14+ public class CacheItemFactoryInvokerTests
1315{
14- public class CacheItemFactoryInvokerTests
16+ [ Fact ]
17+ public void InvokeFactory_ShouldInvokeObjectFactoryAfterDelay ( )
1518 {
16- [ Fact ]
17- public void InvokeFactory_ShouldInvokeObjectFactoryAfterDelay ( )
19+ using var syncContext = new SingleThreadSynchronizationContext ( ) ;
20+
21+ var manualResetEvent = new ManualResetEvent ( false ) ;
22+
23+ var factory = ( ) =>
1824 {
19- using var syncContext = new SingleThreadSynchronizationContext ( ) ;
25+ manualResetEvent . Set ( ) ;
26+ return Task . FromResult ( Substitute . For < IAsyncDisposable > ( ) ) ;
27+ } ;
2028
21- var manualResetEvent = new ManualResetEvent ( false ) ;
29+ var cacheEntity = new CacheEntity < string , IAsyncDisposable > ( "test" , factory , AsyncLazyFlags . None ) ;
2230
23- var factory = ( ) =>
24- {
25- manualResetEvent . Set ( ) ;
26- return Task . FromResult ( Substitute . For < IAsyncDisposable > ( ) ) ;
27- } ;
31+ var creationTimeProvider = Substitute . For < ICreationTimeProvider > ( ) ;
32+ var timeProvider = new FakeTimeProvider ( ) ;
33+ var expectedCreationTime = timeProvider . GetUtcNow ( ) . AddMilliseconds ( 100 ) ;
34+ creationTimeProvider . GetExpectedCreationTime ( ) . Returns ( expectedCreationTime ) ;
2835
29- var cacheEntity = new CacheEntity < string , IAsyncDisposable > ( "test" , factory , AsyncLazyFlags . None ) ;
36+ CacheItemFactoryInvoker . InvokeFactory ( cacheEntity , creationTimeProvider , timeProvider ) ;
3037
31- var creationTimeProvider = Substitute . For < ICreationTimeProvider > ( ) ;
32- var timeProvider = new FakeTimeProvider ( ) ;
33- var expectedCreationTime = timeProvider . GetUtcNow ( ) . AddMilliseconds ( 100 ) ;
34- creationTimeProvider . GetExpectedCreationTime ( ) . Returns ( expectedCreationTime ) ;
38+ syncContext . RunOnCurrentThread ( ) ;
3539
36- CacheItemFactoryInvoker . InvokeFactory ( cacheEntity , creationTimeProvider , timeProvider ) ;
40+ Assert . False ( cacheEntity . ObjectFactory . IsStarted ) ;
41+ timeProvider . Advance ( TimeSpan . FromMilliseconds ( 99 ) ) ;
42+ Assert . False ( cacheEntity . ObjectFactory . IsStarted ) ;
43+ timeProvider . Advance ( TimeSpan . FromMilliseconds ( 100 ) ) ;
3744
38- syncContext . RunOnCurrentThread ( ) ;
45+ manualResetEvent . WaitOne ( ) ;
46+ Assert . True ( cacheEntity . ObjectFactory . IsStarted ) ;
47+ }
3948
40- Assert . False ( cacheEntity . ObjectFactory . IsStarted ) ;
41- timeProvider . Advance ( TimeSpan . FromMilliseconds ( 99 ) ) ;
42- Assert . False ( cacheEntity . ObjectFactory . IsStarted ) ;
43- timeProvider . Advance ( TimeSpan . FromMilliseconds ( 100 ) ) ;
49+ [ Fact ]
50+ public void InvokeFactory_ShouldInvokeObjectFactoryImmediatelyIfNoDelay ( )
51+ {
52+ using var syncContext = new SingleThreadSynchronizationContext ( ) ;
4453
45- manualResetEvent . WaitOne ( ) ;
46- Assert . True ( cacheEntity . ObjectFactory . IsStarted ) ;
47- }
54+ var manualResetEvent = new ManualResetEvent ( false ) ;
4855
49- [ Fact ]
50- public void InvokeFactory_ShouldInvokeObjectFactoryImmediatelyIfNoDelay ( )
56+ var factory = ( ) =>
5157 {
52- using var syncContext = new SingleThreadSynchronizationContext ( ) ;
58+ manualResetEvent . Set ( ) ;
59+ return Task . FromResult ( Substitute . For < IAsyncDisposable > ( ) ) ;
60+ } ;
5361
54- var manualResetEvent = new ManualResetEvent ( false ) ;
62+ var cacheEntity = new CacheEntity < string , IAsyncDisposable > ( "test" , factory , AsyncLazyFlags . None ) ;
5563
56- var factory = ( ) =>
57- {
58- manualResetEvent . Set ( ) ;
59- return Task . FromResult ( Substitute . For < IAsyncDisposable > ( ) ) ;
60- } ;
64+ var sw = Stopwatch . StartNew ( ) ;
65+ CacheItemFactoryInvoker . InvokeFactory ( cacheEntity , CreationTimeProvider . Default , TimeProvider . System ) ;
6166
62- var cacheEntity = new CacheEntity < string , IAsyncDisposable > ( "test" , factory , AsyncLazyFlags . None ) ;
67+ syncContext . RunOnCurrentThread ( ) ;
6368
64- var sw = Stopwatch . StartNew ( ) ;
65- CacheItemFactoryInvoker . InvokeFactory ( cacheEntity , CreationTimeProvider . Default , TimeProvider . System ) ;
69+ manualResetEvent . WaitOne ( ) ;
70+ Assert . InRange ( sw . ElapsedMilliseconds , 0 , 50 ) ;
71+ }
6672
67- syncContext . RunOnCurrentThread ( ) ;
73+ private class SingleThreadSynchronizationContext : SynchronizationContext , IDisposable
74+ {
75+ private readonly Queue < ( SendOrPostCallback , object ? ) > _queue = new ( ) ;
76+ private readonly SynchronizationContext ? _originalContext ;
6877
69- manualResetEvent . WaitOne ( ) ;
70- Assert . InRange ( sw . ElapsedMilliseconds , 0 , 50 ) ;
78+ public SingleThreadSynchronizationContext ( )
79+ {
80+ _originalContext = Current ;
81+ SetSynchronizationContext ( this ) ;
7182 }
7283
73- private class SingleThreadSynchronizationContext : SynchronizationContext , IDisposable
84+ public override void Post ( SendOrPostCallback d , object ? state )
7485 {
75- private readonly Queue < ( SendOrPostCallback , object ? ) > _queue = new ( ) ;
76- private readonly SynchronizationContext ? _originalContext ;
77-
78- public SingleThreadSynchronizationContext ( )
79- {
80- _originalContext = Current ;
81- SetSynchronizationContext ( this ) ;
82- }
83-
84- public override void Post ( SendOrPostCallback d , object ? state )
85- {
86- _queue . Enqueue ( ( d , state ) ) ;
87- }
86+ _queue . Enqueue ( ( d , state ) ) ;
87+ }
8888
89- public void RunOnCurrentThread ( )
89+ public void RunOnCurrentThread ( )
90+ {
91+ while ( _queue . Count > 0 )
9092 {
91- while ( _queue . Count > 0 )
92- {
93- var ( callback , state ) = _queue . Dequeue ( ) ;
94- callback ( state ) ;
95- }
93+ var ( callback , state ) = _queue . Dequeue ( ) ;
94+ callback ( state ) ;
9695 }
96+ }
9797
98- public void Dispose ( )
99- {
100- SetSynchronizationContext ( _originalContext ) ;
101- }
98+ public void Dispose ( )
99+ {
100+ SetSynchronizationContext ( _originalContext ) ;
102101 }
103102 }
104- }
103+ }
0 commit comments