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()
114
114
winnerCount . Should ( ) . Be ( 1 ) ;
115
115
}
116
116
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
+
117
159
[ Fact ]
118
160
public void WhenValueNotCreatedHashCodeIsZero ( )
119
161
{
Original file line number Diff line number Diff line change @@ -92,7 +92,7 @@ public void WhenRemovedEventHandlerIsRegisteredItIsFired()
92
92
}
93
93
94
94
// backcompat: remove conditional compile
95
- #if NETCOREAPP3_0_OR_GREATER
95
+ #if NET
96
96
[ Fact ]
97
97
public void WhenUpdatedEventHandlerIsRegisteredItIsFired ( )
98
98
{
@@ -259,7 +259,7 @@ public async Task WhenFactoryThrowsEmptyKeyIsNotEnumerable()
259
259
}
260
260
261
261
// backcompat: remove conditional compile
262
- #if NETCOREAPP3_0_OR_GREATER
262
+ #if NET
263
263
[ Fact ]
264
264
public void WhenRemovedValueIsReturned ( )
265
265
{
Original file line number Diff line number Diff line change @@ -156,6 +156,49 @@ public async Task WhenCallersRunConcurrentlyResultIsFromWinner()
156
156
winnerCount . Should ( ) . Be ( 1 ) ;
157
157
}
158
158
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
+
159
202
[ Fact ]
160
203
public async Task WhenDisposedWhileInitResultIsDisposed ( )
161
204
{
You can’t perform that action at this time.
0 commit comments