Skip to content

Commit 63b26d4

Browse files
committed
Replace ManualResetEvent with TaskCompletionSource in TestHost tests
1 parent af8d67f commit 63b26d4

File tree

3 files changed

+74
-51
lines changed

3 files changed

+74
-51
lines changed

src/Hosting/TestHost/test/ClientHandlerTests.cs

Lines changed: 18 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -156,51 +156,50 @@ public async Task BlockingMiddlewareShouldNotBlockClient()
156156
[Fact]
157157
public async Task HeadersAvailableBeforeBodyFinished()
158158
{
159-
ManualResetEvent block = new ManualResetEvent(false);
159+
var block = new TaskCompletionSource<int>(TaskCreationOptions.RunContinuationsAsynchronously);
160160
var handler = new ClientHandler(PathString.Empty, new DummyApplication(async context =>
161161
{
162162
context.Response.Headers["TestHeader"] = "TestValue";
163163
await context.Response.WriteAsync("BodyStarted,");
164-
block.WaitOne();
164+
await block.Task;
165165
await context.Response.WriteAsync("BodyFinished");
166166
}));
167167
var httpClient = new HttpClient(handler);
168168
HttpResponseMessage response = await httpClient.GetAsync("https://example.com/",
169169
HttpCompletionOption.ResponseHeadersRead);
170170
Assert.Equal("TestValue", response.Headers.GetValues("TestHeader").First());
171-
block.Set();
171+
block.SetResult(0);
172172
Assert.Equal("BodyStarted,BodyFinished", await response.Content.ReadAsStringAsync());
173173
}
174174

175175
[Fact]
176176
public async Task FlushSendsHeaders()
177177
{
178-
ManualResetEvent block = new ManualResetEvent(false);
178+
var block = new TaskCompletionSource<int>(TaskCreationOptions.RunContinuationsAsynchronously);
179179
var handler = new ClientHandler(PathString.Empty, new DummyApplication(async context =>
180180
{
181181
context.Response.Headers["TestHeader"] = "TestValue";
182182
context.Response.Body.Flush();
183-
block.WaitOne();
183+
await block.Task;
184184
await context.Response.WriteAsync("BodyFinished");
185185
}));
186186
var httpClient = new HttpClient(handler);
187187
HttpResponseMessage response = await httpClient.GetAsync("https://example.com/",
188188
HttpCompletionOption.ResponseHeadersRead);
189189
Assert.Equal("TestValue", response.Headers.GetValues("TestHeader").First());
190-
block.Set();
190+
block.SetResult(0);
191191
Assert.Equal("BodyFinished", await response.Content.ReadAsStringAsync());
192192
}
193193

194194
[Fact]
195195
public async Task ClientDisposalCloses()
196196
{
197-
ManualResetEvent block = new ManualResetEvent(false);
197+
var block = new TaskCompletionSource<int>(TaskCreationOptions.RunContinuationsAsynchronously);
198198
var handler = new ClientHandler(PathString.Empty, new DummyApplication(context =>
199199
{
200200
context.Response.Headers["TestHeader"] = "TestValue";
201201
context.Response.Body.Flush();
202-
block.WaitOne();
203-
return Task.FromResult(0);
202+
return block.Task;
204203
}));
205204
var httpClient = new HttpClient(handler);
206205
HttpResponseMessage response = await httpClient.GetAsync("https://example.com/",
@@ -210,21 +209,20 @@ public async Task ClientDisposalCloses()
210209
Task<int> readTask = responseStream.ReadAsync(new byte[100], 0, 100);
211210
Assert.False(readTask.IsCompleted);
212211
responseStream.Dispose();
213-
Assert.True(readTask.Wait(TimeSpan.FromSeconds(10)), "Finished");
214-
Assert.Equal(0, readTask.Result);
215-
block.Set();
212+
var read = await readTask.WithTimeout();
213+
Assert.Equal(0, read);
214+
block.SetResult(0);
216215
}
217216

218217
[Fact]
219218
public async Task ClientCancellationAborts()
220219
{
221-
ManualResetEvent block = new ManualResetEvent(false);
220+
var block = new TaskCompletionSource<int>(TaskCreationOptions.RunContinuationsAsynchronously);
222221
var handler = new ClientHandler(PathString.Empty, new DummyApplication(context =>
223222
{
224223
context.Response.Headers["TestHeader"] = "TestValue";
225224
context.Response.Body.Flush();
226-
block.WaitOne();
227-
return Task.FromResult(0);
225+
return block.Task;
228226
}));
229227
var httpClient = new HttpClient(handler);
230228
HttpResponseMessage response = await httpClient.GetAsync("https://example.com/",
@@ -235,9 +233,8 @@ public async Task ClientCancellationAborts()
235233
Task<int> readTask = responseStream.ReadAsync(new byte[100], 0, 100, cts.Token);
236234
Assert.False(readTask.IsCompleted, "Not Completed");
237235
cts.Cancel();
238-
var ex = Assert.Throws<AggregateException>(() => readTask.Wait(TimeSpan.FromSeconds(10)));
239-
Assert.IsAssignableFrom<OperationCanceledException>(ex.GetBaseException());
240-
block.Set();
236+
await Assert.ThrowsAsync<OperationCanceledException>(() => readTask.WithTimeout());
237+
block.SetResult(0);
241238
}
242239

243240
[Fact]
@@ -255,19 +252,19 @@ public Task ExceptionBeforeFirstWriteIsReported()
255252
[Fact]
256253
public async Task ExceptionAfterFirstWriteIsReported()
257254
{
258-
ManualResetEvent block = new ManualResetEvent(false);
255+
var block = new TaskCompletionSource<int>(TaskCreationOptions.RunContinuationsAsynchronously);
259256
var handler = new ClientHandler(PathString.Empty, new DummyApplication(async context =>
260257
{
261258
context.Response.Headers["TestHeader"] = "TestValue";
262259
await context.Response.WriteAsync("BodyStarted");
263-
block.WaitOne();
260+
await block.Task;
264261
throw new InvalidOperationException("Test Exception");
265262
}));
266263
var httpClient = new HttpClient(handler);
267264
HttpResponseMessage response = await httpClient.GetAsync("https://example.com/",
268265
HttpCompletionOption.ResponseHeadersRead);
269266
Assert.Equal("TestValue", response.Headers.GetValues("TestHeader").First());
270-
block.Set();
267+
block.SetResult(0);
271268
var ex = await Assert.ThrowsAsync<HttpRequestException>(() => response.Content.ReadAsStringAsync());
272269
Assert.IsType<InvalidOperationException>(ex.GetBaseException());
273270
}

src/Hosting/TestHost/test/HttpContextBuilderTests.cs

Lines changed: 27 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -102,18 +102,17 @@ public async Task BlockingMiddlewareShouldNotBlockClient()
102102
[Fact]
103103
public async Task HeadersAvailableBeforeSyncBodyFinished()
104104
{
105-
var block = new ManualResetEvent(false);
105+
var block = new TaskCompletionSource<int>(TaskCreationOptions.RunContinuationsAsynchronously);
106106
var builder = new WebHostBuilder().Configure(app =>
107107
{
108-
app.Run(c =>
108+
app.Run(async c =>
109109
{
110110
c.Response.Headers["TestHeader"] = "TestValue";
111111
var bytes = Encoding.UTF8.GetBytes("BodyStarted" + Environment.NewLine);
112112
c.Response.Body.Write(bytes, 0, bytes.Length);
113-
Assert.True(block.WaitOne(TimeSpan.FromSeconds(5)));
113+
await block.Task;
114114
bytes = Encoding.UTF8.GetBytes("BodyFinished");
115115
c.Response.Body.Write(bytes, 0, bytes.Length);
116-
return Task.CompletedTask;
117116
});
118117
});
119118
var server = new TestServer(builder);
@@ -122,21 +121,21 @@ public async Task HeadersAvailableBeforeSyncBodyFinished()
122121
Assert.Equal("TestValue", context.Response.Headers["TestHeader"]);
123122
var reader = new StreamReader(context.Response.Body);
124123
Assert.Equal("BodyStarted", reader.ReadLine());
125-
block.Set();
124+
block.SetResult(0);
126125
Assert.Equal("BodyFinished", reader.ReadToEnd());
127126
}
128127

129128
[Fact]
130129
public async Task HeadersAvailableBeforeAsyncBodyFinished()
131130
{
132-
var block = new ManualResetEvent(false);
131+
var block = new TaskCompletionSource<int>(TaskCreationOptions.RunContinuationsAsynchronously);
133132
var builder = new WebHostBuilder().Configure(app =>
134133
{
135134
app.Run(async c =>
136135
{
137136
c.Response.Headers["TestHeader"] = "TestValue";
138137
await c.Response.WriteAsync("BodyStarted" + Environment.NewLine);
139-
Assert.True(block.WaitOne(TimeSpan.FromSeconds(5)));
138+
await block.Task;
140139
await c.Response.WriteAsync("BodyFinished");
141140
});
142141
});
@@ -146,43 +145,43 @@ public async Task HeadersAvailableBeforeAsyncBodyFinished()
146145
Assert.Equal("TestValue", context.Response.Headers["TestHeader"]);
147146
var reader = new StreamReader(context.Response.Body);
148147
Assert.Equal("BodyStarted", await reader.ReadLineAsync());
149-
block.Set();
148+
block.SetResult(0);
150149
Assert.Equal("BodyFinished", await reader.ReadToEndAsync());
151150
}
152151

153152
[Fact]
154153
public async Task FlushSendsHeaders()
155154
{
156-
var block = new ManualResetEvent(false);
155+
var block = new TaskCompletionSource<int>(TaskCreationOptions.RunContinuationsAsynchronously);
157156
var builder = new WebHostBuilder().Configure(app =>
158157
{
159158
app.Run(async c =>
160159
{
161160
c.Response.Headers["TestHeader"] = "TestValue";
162161
c.Response.Body.Flush();
163-
block.WaitOne();
162+
await block.Task;
164163
await c.Response.WriteAsync("BodyFinished");
165164
});
166165
});
167166
var server = new TestServer(builder);
168167
var context = await server.SendAsync(c => { });
169168

170169
Assert.Equal("TestValue", context.Response.Headers["TestHeader"]);
171-
block.Set();
170+
block.SetResult(0);
172171
Assert.Equal("BodyFinished", new StreamReader(context.Response.Body).ReadToEnd());
173172
}
174173

175174
[Fact]
176175
public async Task ClientDisposalCloses()
177176
{
178-
var block = new ManualResetEvent(false);
177+
var block = new TaskCompletionSource<int>(TaskCreationOptions.RunContinuationsAsynchronously);
179178
var builder = new WebHostBuilder().Configure(app =>
180179
{
181180
app.Run(async c =>
182181
{
183182
c.Response.Headers["TestHeader"] = "TestValue";
184183
c.Response.Body.Flush();
185-
block.WaitOne();
184+
await block.Task;
186185
await c.Response.WriteAsync("BodyFinished");
187186
});
188187
});
@@ -194,20 +193,20 @@ public async Task ClientDisposalCloses()
194193
Task<int> readTask = responseStream.ReadAsync(new byte[100], 0, 100);
195194
Assert.False(readTask.IsCompleted);
196195
responseStream.Dispose();
197-
Assert.True(readTask.Wait(TimeSpan.FromSeconds(10)));
198-
Assert.Equal(0, readTask.Result);
199-
block.Set();
196+
var read = await readTask.WithTimeout();
197+
Assert.Equal(0, read);
198+
block.SetResult(0);
200199
}
201200

202201
[Fact]
203-
public void ClientCancellationAborts()
202+
public async Task ClientCancellationAborts()
204203
{
205-
var block = new ManualResetEvent(false);
204+
var block = new TaskCompletionSource<int>(TaskCreationOptions.RunContinuationsAsynchronously);
206205
var builder = new WebHostBuilder().Configure(app =>
207206
{
208207
app.Run(c =>
209208
{
210-
block.Set();
209+
block.SetResult(0);
211210
Assert.True(c.RequestAborted.WaitHandle.WaitOne(TimeSpan.FromSeconds(10)));
212211
c.RequestAborted.ThrowIfCancellationRequested();
213212
return Task.CompletedTask;
@@ -216,24 +215,23 @@ public void ClientCancellationAborts()
216215
var server = new TestServer(builder);
217216
var cts = new CancellationTokenSource();
218217
var contextTask = server.SendAsync(c => { }, cts.Token);
219-
block.WaitOne();
218+
await block.Task;
220219
cts.Cancel();
221220

222-
var ex = Assert.Throws<AggregateException>(() => contextTask.Wait(TimeSpan.FromSeconds(10)));
223-
Assert.IsAssignableFrom<OperationCanceledException>(ex.GetBaseException());
221+
await Assert.ThrowsAsync<OperationCanceledException>(() => contextTask.WithTimeout());
224222
}
225223

226224
[Fact]
227225
public async Task ClientCancellationAbortsReadAsync()
228226
{
229-
var block = new ManualResetEvent(false);
227+
var block = new TaskCompletionSource<int>(TaskCreationOptions.RunContinuationsAsynchronously);
230228
var builder = new WebHostBuilder().Configure(app =>
231229
{
232230
app.Run(async c =>
233231
{
234232
c.Response.Headers["TestHeader"] = "TestValue";
235233
c.Response.Body.Flush();
236-
block.WaitOne();
234+
await block.Task;
237235
await c.Response.WriteAsync("BodyFinished");
238236
});
239237
});
@@ -246,9 +244,8 @@ public async Task ClientCancellationAbortsReadAsync()
246244
var readTask = responseStream.ReadAsync(new byte[100], 0, 100, cts.Token);
247245
Assert.False(readTask.IsCompleted);
248246
cts.Cancel();
249-
var ex = Assert.Throws<AggregateException>(() => readTask.Wait(TimeSpan.FromSeconds(10)));
250-
Assert.IsAssignableFrom<OperationCanceledException>(ex.GetBaseException());
251-
block.Set();
247+
await Assert.ThrowsAsync<OperationCanceledException>(() => readTask.WithTimeout());
248+
block.SetResult(0);
252249
}
253250

254251
[Fact]
@@ -268,14 +265,14 @@ public Task ExceptionBeforeFirstWriteIsReported()
268265
[Fact]
269266
public async Task ExceptionAfterFirstWriteIsReported()
270267
{
271-
var block = new ManualResetEvent(false);
268+
var block = new TaskCompletionSource<int>(TaskCreationOptions.RunContinuationsAsynchronously);
272269
var builder = new WebHostBuilder().Configure(app =>
273270
{
274271
app.Run(async c =>
275272
{
276273
c.Response.Headers["TestHeader"] = "TestValue";
277274
await c.Response.WriteAsync("BodyStarted");
278-
block.WaitOne();
275+
await block.Task;
279276
throw new InvalidOperationException("Test Exception");
280277
});
281278
});
@@ -284,7 +281,7 @@ public async Task ExceptionAfterFirstWriteIsReported()
284281

285282
Assert.Equal("TestValue", context.Response.Headers["TestHeader"]);
286283
Assert.Equal(11, context.Response.Body.Read(new byte[100], 0, 100));
287-
block.Set();
284+
block.SetResult(0);
288285
var ex = Assert.Throws<IOException>(() => context.Response.Body.Read(new byte[100], 0, 100));
289286
Assert.IsAssignableFrom<InvalidOperationException>(ex.InnerException);
290287
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
// Copyright (c) .NET Foundation. All rights reserved.
2+
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
3+
4+
using System;
5+
using System.Threading.Tasks;
6+
7+
namespace Microsoft.AspNetCore.TestHost
8+
{
9+
internal static class Utilities
10+
{
11+
internal static readonly TimeSpan DefaultTimeout = TimeSpan.FromSeconds(15);
12+
13+
internal static Task<T> WithTimeout<T>(this Task<T> task) => task.WithTimeout(DefaultTimeout);
14+
15+
internal static async Task<T> WithTimeout<T>(this Task<T> task, TimeSpan timeout)
16+
{
17+
var completedTask = await Task.WhenAny(task, Task.Delay(timeout));
18+
19+
if (completedTask == task)
20+
{
21+
return await task;
22+
}
23+
else
24+
{
25+
throw new TimeoutException("The task has timed out.");
26+
}
27+
}
28+
}
29+
}

0 commit comments

Comments
 (0)