@@ -77,4 +77,99 @@ public async Task ExponentialRetryJittered()
7777 public TimeSpan MaxDelay = TimeSpan . FromSeconds ( 1 ) ;
7878 public TimeSpan MinDelay = TimeSpan . FromMilliseconds ( 20 ) ;
7979 }
80+
81+ public class CacheTests : BaseDependencyInjectionTests
82+ {
83+ [ Test ]
84+ public async Task AbsoluteExpiration ( )
85+ {
86+ Instance . Setup ( x => x . WorkWithResultAsync ( It . Is < int > ( i=> i == 1 ) , It . IsAny < CancellationToken > ( ) ) ) . ReturnsAsync ( 1 ) ;
87+ Instance . Setup ( x => x . WorkWithResultAsync ( It . Is < int > ( i=> i == 2 ) , It . IsAny < CancellationToken > ( ) ) ) . ReturnsAsync ( 2 ) ;
88+
89+ var proxy = CreateTestObject ( x => x . AddAbsoluteTimeoutCache ( Expiration , ( method , args ) => args [ 0 ] ) ) ;
90+
91+ //first pass
92+ await Parallel . ForAsync ( 0 , 100 , async ( _ , _ ) =>
93+ {
94+ ( await proxy . WorkWithResultAsync ( 1 , Ct ) ) . Should ( ) . Be ( 1 ) ;
95+ } ) ;
96+ Instance . Verify ( x=> x . WorkWithResultAsync ( It . Is < int > ( i=> i == 1 ) , It . IsAny < CancellationToken > ( ) ) , Times . Exactly ( 1 ) ) ;
97+ Instance . Verify ( x=> x . WorkWithResultAsync ( It . Is < int > ( i=> i == 2 ) , It . IsAny < CancellationToken > ( ) ) , Times . Never ) ;
98+
99+ await Task . Delay ( Expiration ) ;
100+
101+ //second pass
102+ await Parallel . ForAsync ( 0 , 100 , async ( _ , _ ) =>
103+ {
104+ ( await proxy . WorkWithResultAsync ( 1 , Ct ) ) . Should ( ) . Be ( 1 ) ;
105+ } ) ;
106+ Instance . Verify ( x=> x . WorkWithResultAsync ( It . Is < int > ( i=> i == 1 ) , It . IsAny < CancellationToken > ( ) ) , Times . Exactly ( 2 ) ) ;
107+ Instance . Verify ( x=> x . WorkWithResultAsync ( It . Is < int > ( i=> i == 2 ) , It . IsAny < CancellationToken > ( ) ) , Times . Never ) ;
108+ }
109+
110+ [ Test ]
111+ public async Task SlidingExpiration ( )
112+ {
113+ Instance . Setup ( x => x . WorkWithResultAsync ( It . Is < int > ( i=> i == 1 ) , It . IsAny < CancellationToken > ( ) ) ) . ReturnsAsync ( 1 ) ;
114+ Instance . Setup ( x => x . WorkWithResultAsync ( It . Is < int > ( i=> i == 2 ) , It . IsAny < CancellationToken > ( ) ) ) . ReturnsAsync ( 2 ) ;
115+
116+ var proxy = CreateTestObject ( x => x . AddSlidingTimeoutCache ( Expiration , ( method , args ) => args [ 0 ] ) ) ;
117+
118+ //first pass
119+ await Parallel . ForAsync ( 0 , 100 , async ( _ , _ ) =>
120+ {
121+ ( await proxy . WorkWithResultAsync ( 1 , Ct ) ) . Should ( ) . Be ( 1 ) ;
122+ } ) ;
123+ Instance . Verify ( x=> x . WorkWithResultAsync ( It . Is < int > ( i=> i == 1 ) , It . IsAny < CancellationToken > ( ) ) , Times . Exactly ( 1 ) ) ;
124+ Instance . Verify ( x=> x . WorkWithResultAsync ( It . Is < int > ( i=> i == 2 ) , It . IsAny < CancellationToken > ( ) ) , Times . Never ) ;
125+
126+ await Task . Delay ( Expiration ) ;
127+
128+ //second pass
129+ await Parallel . ForAsync ( 0 , 100 , async ( _ , _ ) =>
130+ {
131+ ( await proxy . WorkWithResultAsync ( 1 , Ct ) ) . Should ( ) . Be ( 1 ) ;
132+ } ) ;
133+ Instance . Verify ( x=> x . WorkWithResultAsync ( It . Is < int > ( i=> i == 1 ) , It . IsAny < CancellationToken > ( ) ) , Times . Exactly ( 2 ) ) ;
134+ Instance . Verify ( x=> x . WorkWithResultAsync ( It . Is < int > ( i=> i == 2 ) , It . IsAny < CancellationToken > ( ) ) , Times . Never ) ;
135+ }
136+
137+ [ Test ]
138+ public async Task SlidingExpirationOverlap ( )
139+ {
140+ Instance . Setup ( x => x . WorkWithResultAsync ( It . Is < int > ( i=> i == 1 ) , It . IsAny < CancellationToken > ( ) ) ) . ReturnsAsync ( 1 ) ;
141+ Instance . Setup ( x => x . WorkWithResultAsync ( It . Is < int > ( i=> i == 2 ) , It . IsAny < CancellationToken > ( ) ) ) . ReturnsAsync ( 2 ) ;
142+
143+ var proxy = CreateTestObject ( x => x . AddSlidingTimeoutCache ( Expiration , ( method , args ) => args [ 0 ] ) ) ;
144+
145+ //first pass
146+ await Parallel . ForAsync ( 0 , 100 , async ( _ , _ ) =>
147+ {
148+ ( await proxy . WorkWithResultAsync ( 1 , Ct ) ) . Should ( ) . Be ( 1 ) ;
149+ } ) ;
150+ Instance . Verify ( x=> x . WorkWithResultAsync ( It . Is < int > ( i=> i == 1 ) , It . IsAny < CancellationToken > ( ) ) , Times . Exactly ( 1 ) ) ;
151+ Instance . Verify ( x=> x . WorkWithResultAsync ( It . Is < int > ( i=> i == 2 ) , It . IsAny < CancellationToken > ( ) ) , Times . Never ) ;
152+
153+ await Task . Delay ( Expiration / 2 ) ;
154+
155+ //second pass
156+ await Parallel . ForAsync ( 0 , 100 , async ( _ , _ ) =>
157+ {
158+ ( await proxy . WorkWithResultAsync ( 1 , Ct ) ) . Should ( ) . Be ( 1 ) ;
159+ } ) ;
160+ Instance . Verify ( x=> x . WorkWithResultAsync ( It . Is < int > ( i=> i == 1 ) , It . IsAny < CancellationToken > ( ) ) , Times . Exactly ( 1 ) ) ;
161+ Instance . Verify ( x=> x . WorkWithResultAsync ( It . Is < int > ( i=> i == 2 ) , It . IsAny < CancellationToken > ( ) ) , Times . Never ) ;
162+
163+ await Task . Delay ( Expiration / 2 ) ;
164+
165+ //third pass
166+ await Parallel . ForAsync ( 0 , 100 , async ( _ , _ ) =>
167+ {
168+ ( await proxy . WorkWithResultAsync ( 1 , Ct ) ) . Should ( ) . Be ( 1 ) ;
169+ } ) ;
170+ Instance . Verify ( x=> x . WorkWithResultAsync ( It . Is < int > ( i=> i == 1 ) , It . IsAny < CancellationToken > ( ) ) , Times . Exactly ( 1 ) ) ;
171+ Instance . Verify ( x=> x . WorkWithResultAsync ( It . Is < int > ( i=> i == 2 ) , It . IsAny < CancellationToken > ( ) ) , Times . Never ) ;
172+ }
173+ public TimeSpan Expiration = TimeSpan . FromSeconds ( 3 ) ;
174+ }
80175}
0 commit comments