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