File tree Expand file tree Collapse file tree 3 files changed +87
-2
lines changed
BitFaster.Caching.UnitTests/Atomic Expand file tree Collapse file tree 3 files changed +87
-2
lines changed Original file line number Diff line number Diff line change @@ -114,6 +114,48 @@ public async Task WhenCallersRunConcurrentlyResultIsFromWinner()
114114 winnerCount . Should ( ) . Be ( 1 ) ;
115115 }
116116
117+ [ Fact ]
118+ public async Task WhenCallersRunConcurrentlyWithFailureSameExceptionIsPropagated ( )
119+ {
120+ var enter = new TaskCompletionSource < bool > ( TaskCreationOptions . RunContinuationsAsynchronously ) ;
121+ var resume = new TaskCompletionSource < bool > ( TaskCreationOptions . RunContinuationsAsynchronously ) ;
122+
123+ var atomicFactory = new AsyncAtomicFactory < int , int > ( ) ;
124+
125+ var first = atomicFactory . GetValueAsync ( 1 , async k =>
126+ {
127+ enter . SetResult ( true ) ;
128+ await resume . Task ;
129+
130+ throw new ArithmeticException ( "1" ) ;
131+ } ) . AsTask ( ) ;
132+
133+ var second = atomicFactory . GetValueAsync ( 1 , async k =>
134+ {
135+ enter . SetResult ( true ) ;
136+ await resume . Task ;
137+
138+ throw new InvalidOperationException ( "2" ) ;
139+ } ) . AsTask ( ) ;
140+
141+ await enter . Task ;
142+ resume . SetResult ( true ) ;
143+
144+ // Both tasks will throw, but the first one to complete will propagate its exception
145+ // Both exceptions should be the same. If they are not, there will be an aggregate exception.
146+ try
147+ {
148+ await Task . WhenAll ( first , second )
149+ . TimeoutAfter ( TimeSpan . FromSeconds ( 5 ) , "Tasks did not complete within the expected time. Exceptions are not propagated between callers correctly." ) ;
150+ }
151+ catch ( ArithmeticException )
152+ {
153+ }
154+ catch ( InvalidOperationException )
155+ {
156+ }
157+ }
158+
117159 [ Fact ]
118160 public void WhenValueNotCreatedHashCodeIsZero ( )
119161 {
Original file line number Diff line number Diff line change @@ -92,7 +92,7 @@ public void WhenRemovedEventHandlerIsRegisteredItIsFired()
9292 }
9393
9494 // backcompat: remove conditional compile
95- #if NETCOREAPP3_0_OR_GREATER
95+ #if NET
9696 [ Fact ]
9797 public void WhenUpdatedEventHandlerIsRegisteredItIsFired ( )
9898 {
@@ -259,7 +259,7 @@ public async Task WhenFactoryThrowsEmptyKeyIsNotEnumerable()
259259 }
260260
261261 // backcompat: remove conditional compile
262- #if NETCOREAPP3_0_OR_GREATER
262+ #if NET
263263 [ Fact ]
264264 public void WhenRemovedValueIsReturned ( )
265265 {
Original file line number Diff line number Diff line change @@ -156,6 +156,49 @@ public async Task WhenCallersRunConcurrentlyResultIsFromWinner()
156156 winnerCount . Should ( ) . Be ( 1 ) ;
157157 }
158158
159+
160+ [ Fact ]
161+ public async Task WhenCallersRunConcurrentlyWithFailureSameExceptionIsPropagated ( )
162+ {
163+ var enter = new TaskCompletionSource < bool > ( TaskCreationOptions . RunContinuationsAsynchronously ) ;
164+ var resume = new TaskCompletionSource < bool > ( TaskCreationOptions . RunContinuationsAsynchronously ) ;
165+
166+ var atomicFactory = new ScopedAsyncAtomicFactory < int , IntHolder > ( ) ;
167+
168+ var first = atomicFactory . TryCreateLifetimeAsync ( 1 , async k =>
169+ {
170+ enter . SetResult ( true ) ;
171+ await resume . Task ;
172+
173+ throw new ArithmeticException ( "1" ) ;
174+ } ) . AsTask ( ) ; ;
175+
176+ var second = atomicFactory . TryCreateLifetimeAsync ( 1 , async k =>
177+ {
178+ enter . SetResult ( true ) ;
179+ await resume . Task ;
180+
181+ throw new InvalidOperationException ( "2" ) ;
182+ } ) . AsTask ( ) ;
183+
184+ await enter . Task ;
185+ resume . SetResult ( true ) ;
186+
187+ // Both tasks will throw, but the first one to complete will propagate its exception
188+ // Both exceptions should be the same. If they are not, there will be an aggregate exception.
189+ try
190+ {
191+ await Task . WhenAll ( first , second )
192+ . TimeoutAfter ( TimeSpan . FromSeconds ( 5 ) , "Tasks did not complete within the expected time. Exceptions are not propagated between callers correctly." ) ;
193+ }
194+ catch ( ArithmeticException )
195+ {
196+ }
197+ catch ( InvalidOperationException )
198+ {
199+ }
200+ }
201+
159202 [ Fact ]
160203 public async Task WhenDisposedWhileInitResultIsDisposed ( )
161204 {
You can’t perform that action at this time.
0 commit comments