15
15
using Microsoft . AspNetCore . Server . Kestrel . Internal . Infrastructure ;
16
16
using Microsoft . AspNetCore . Testing ;
17
17
using Microsoft . Extensions . DependencyInjection ;
18
+ using Microsoft . Extensions . Internal ;
18
19
using Microsoft . Extensions . Primitives ;
19
20
using Moq ;
20
21
using Xunit ;
@@ -86,7 +87,7 @@ public async Task IgnoreNullHeaderValues(string headerName, StringValues headerV
86
87
app . Run ( async context =>
87
88
{
88
89
context . Response . Headers . Add ( headerName , headerValue ) ;
89
-
90
+
90
91
await context . Response . WriteAsync ( "" ) ;
91
92
} ) ;
92
93
} ) ;
@@ -176,35 +177,73 @@ public async Task OnStartingThrowsWhenSetAfterResponseHasAlreadyStarted()
176
177
using ( var client = new HttpClient ( ) )
177
178
{
178
179
var response = await client . GetAsync ( $ "http://localhost:{ host . GetPort ( ) } /") ;
179
-
180
+
180
181
// Despite the error, the response had already started
181
182
Assert . Equal ( HttpStatusCode . OK , response . StatusCode ) ;
182
183
Assert . NotNull ( ex ) ;
183
184
}
184
185
}
185
186
}
186
-
187
+
187
188
[ Fact ]
188
- public async Task ResponseStatusCodeSetBeforeHttpContextDispose ( )
189
+ public Task ResponseStatusCodeSetBeforeHttpContextDisposeAppException ( )
190
+ {
191
+ return ResponseStatusCodeSetBeforeHttpContextDispose (
192
+ context =>
193
+ {
194
+ throw new Exception ( ) ;
195
+ } ,
196
+ expectedClientStatusCode : HttpStatusCode . InternalServerError ,
197
+ expectedServerStatusCode : HttpStatusCode . InternalServerError ) ;
198
+ }
199
+
200
+ [ Fact ]
201
+ public Task ResponseStatusCodeSetBeforeHttpContextDisposeRequestAborted ( )
202
+ {
203
+ return ResponseStatusCodeSetBeforeHttpContextDispose (
204
+ context =>
205
+ {
206
+ context . Abort ( ) ;
207
+ return TaskCache . CompletedTask ;
208
+ } ,
209
+ expectedClientStatusCode : null ,
210
+ expectedServerStatusCode : HttpStatusCode . OK ) ;
211
+ }
212
+
213
+ [ Fact ]
214
+ public Task ResponseStatusCodeSetBeforeHttpContextDisposeRequestAbortedAppException ( )
215
+ {
216
+ return ResponseStatusCodeSetBeforeHttpContextDispose (
217
+ context =>
218
+ {
219
+ context . Abort ( ) ;
220
+ throw new Exception ( ) ;
221
+ } ,
222
+ expectedClientStatusCode : null ,
223
+ expectedServerStatusCode : HttpStatusCode . InternalServerError ) ;
224
+ }
225
+
226
+ private static async Task ResponseStatusCodeSetBeforeHttpContextDispose ( RequestDelegate handler ,
227
+ HttpStatusCode ? expectedClientStatusCode , HttpStatusCode expectedServerStatusCode )
189
228
{
190
229
var mockHttpContextFactory = new Mock < IHttpContextFactory > ( ) ;
191
230
mockHttpContextFactory . Setup ( f => f . Create ( It . IsAny < IFeatureCollection > ( ) ) )
192
231
. Returns < IFeatureCollection > ( fc => new DefaultHttpContext ( fc ) ) ;
193
232
194
- int disposedStatusCode = - 1 ;
233
+ var disposedTcs = new TaskCompletionSource < int > ( ) ;
195
234
mockHttpContextFactory . Setup ( f => f . Dispose ( It . IsAny < HttpContext > ( ) ) )
196
- . Callback < HttpContext > ( c => disposedStatusCode = c . Response . StatusCode ) ;
235
+ . Callback < HttpContext > ( c =>
236
+ {
237
+ disposedTcs . TrySetResult ( c . Response . StatusCode ) ;
238
+ } ) ;
197
239
198
240
var hostBuilder = new WebHostBuilder ( )
199
241
. UseKestrel ( )
200
242
. UseUrls ( "http://127.0.0.1:0" )
201
243
. ConfigureServices ( services => services . AddSingleton < IHttpContextFactory > ( mockHttpContextFactory . Object ) )
202
244
. Configure ( app =>
203
245
{
204
- app . Run ( context =>
205
- {
206
- throw new Exception ( ) ;
207
- } ) ;
246
+ app . Run ( handler ) ;
208
247
} ) ;
209
248
210
249
using ( var host = hostBuilder . Build ( ) )
@@ -213,12 +252,24 @@ public async Task ResponseStatusCodeSetBeforeHttpContextDispose()
213
252
214
253
using ( var client = new HttpClient ( ) )
215
254
{
216
- var response = await client . GetAsync ( $ "http://localhost:{ host . GetPort ( ) } /") ;
217
- Assert . Equal ( HttpStatusCode . InternalServerError , response . StatusCode ) ;
255
+ try
256
+ {
257
+ var response = await client . GetAsync ( $ "http://localhost:{ host . GetPort ( ) } /") ;
258
+ Assert . Equal ( expectedClientStatusCode , response . StatusCode ) ;
259
+ }
260
+ catch
261
+ {
262
+ if ( expectedClientStatusCode != null )
263
+ {
264
+ throw ;
265
+ }
266
+ }
218
267
}
219
- }
220
268
221
- Assert . Equal ( HttpStatusCode . InternalServerError , ( HttpStatusCode ) disposedStatusCode ) ;
269
+ var disposedStatusCode = await disposedTcs . Task . TimeoutAfter ( TimeSpan . FromSeconds ( 10 ) ) ;
270
+
271
+ Assert . Equal ( expectedServerStatusCode , ( HttpStatusCode ) disposedStatusCode ) ;
272
+ }
222
273
}
223
274
224
275
// https://github.com/aspnet/KestrelHttpServer/pull/1111/files#r80584475 explains the reason for this test.
0 commit comments