-
Notifications
You must be signed in to change notification settings - Fork 4.8k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[browser][MT] send cancel to abandoned threads with event loop during…
… mono_exit (#97441) Co-authored-by: Marek Fišera <[email protected]>
- Loading branch information
1 parent
742039f
commit fb953cc
Showing
45 changed files
with
1,026 additions
and
801 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
4 changes: 2 additions & 2 deletions
4
...vices.JavaScript.UnitTests/System/Runtime/InteropServices/JavaScript/SecondRuntimeTest.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
93 changes: 93 additions & 0 deletions
93
...ices.JavaScript.UnitTests/System/Runtime/InteropServices/JavaScript/WebWorkerTest.Http.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,93 @@ | ||
// Licensed to the .NET Foundation under one or more agreements. | ||
// The .NET Foundation licenses this file to you under the MIT license. | ||
|
||
using System.Threading.Tasks; | ||
using System.Threading; | ||
using System.Net.Http; | ||
using Xunit; | ||
using System.IO; | ||
using System.Text; | ||
|
||
namespace System.Runtime.InteropServices.JavaScript.Tests | ||
{ | ||
public class WebWorkerHttpTest : WebWorkerTestBase | ||
{ | ||
#region HTTP | ||
|
||
[Theory, MemberData(nameof(GetTargetThreads))] | ||
public async Task HttpClient_ContentInSameThread(Executor executor) | ||
{ | ||
using var cts = CreateTestCaseTimeoutSource(); | ||
var uri = WebWorkerTestHelper.GetOriginUrl() + "/test.json"; | ||
|
||
await executor.Execute(async () => | ||
{ | ||
using var client = new HttpClient(); | ||
using var response = await client.GetAsync(uri); | ||
response.EnsureSuccessStatusCode(); | ||
var body = await response.Content.ReadAsStringAsync(); | ||
Assert.Contains("hello", body); | ||
Assert.Contains("world", body); | ||
}, cts.Token); | ||
} | ||
|
||
private static HttpRequestOptionsKey<bool> WebAssemblyEnableStreamingRequestKey = new("WebAssemblyEnableStreamingRequest"); | ||
private static HttpRequestOptionsKey<bool> WebAssemblyEnableStreamingResponseKey = new("WebAssemblyEnableStreamingResponse"); | ||
private static string HelloJson = "{'hello':'world'}".Replace('\'', '"'); | ||
private static string EchoStart = "{\"Method\":\"POST\",\"Url\":\"/Echo.ashx"; | ||
|
||
private async Task HttpClient_ActionInDifferentThread(string url, Executor executor1, Executor executor2, Func<HttpResponseMessage, Task> e2Job) | ||
{ | ||
using var cts = CreateTestCaseTimeoutSource(); | ||
|
||
var e1Job = async (Task e2done, TaskCompletionSource<HttpResponseMessage> e1State) => | ||
{ | ||
using var ms = new MemoryStream(); | ||
await ms.WriteAsync(Encoding.UTF8.GetBytes(HelloJson)); | ||
|
||
using var req = new HttpRequestMessage(HttpMethod.Post, url); | ||
req.Options.Set(WebAssemblyEnableStreamingResponseKey, true); | ||
req.Content = new StreamContent(ms); | ||
using var client = new HttpClient(); | ||
var pr = client.SendAsync(req, HttpCompletionOption.ResponseHeadersRead); | ||
using var response = await pr; | ||
|
||
// share the state with the E2 continuation | ||
e1State.SetResult(response); | ||
|
||
await e2done; | ||
}; | ||
await ActionsInDifferentThreads<HttpResponseMessage>(executor1, executor2, e1Job, e2Job, cts); | ||
} | ||
|
||
[Theory, MemberData(nameof(GetTargetThreads2x))] | ||
public async Task HttpClient_ContentInDifferentThread(Executor executor1, Executor executor2) | ||
{ | ||
var url = WebWorkerTestHelper.LocalHttpEcho + "?guid=" + Guid.NewGuid(); | ||
await HttpClient_ActionInDifferentThread(url, executor1, executor2, async (HttpResponseMessage response) => | ||
{ | ||
response.EnsureSuccessStatusCode(); | ||
var body = await response.Content.ReadAsStringAsync(); | ||
Assert.StartsWith(EchoStart, body); | ||
}); | ||
} | ||
|
||
[Theory, MemberData(nameof(GetTargetThreads2x))] | ||
public async Task HttpClient_CancelInDifferentThread(Executor executor1, Executor executor2) | ||
{ | ||
var url = WebWorkerTestHelper.LocalHttpEcho + "?delay10sec=true&guid=" + Guid.NewGuid(); | ||
await HttpClient_ActionInDifferentThread(url, executor1, executor2, async (HttpResponseMessage response) => | ||
{ | ||
await Assert.ThrowsAsync<TaskCanceledException>(async () => | ||
{ | ||
CancellationTokenSource cts = new CancellationTokenSource(); | ||
var promise = response.Content.ReadAsStringAsync(cts.Token); | ||
cts.Cancel(); | ||
await promise; | ||
}); | ||
}); | ||
} | ||
|
||
#endregion | ||
} | ||
} |
111 changes: 111 additions & 0 deletions
111
...JavaScript.UnitTests/System/Runtime/InteropServices/JavaScript/WebWorkerTest.WebSocket.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,111 @@ | ||
// Licensed to the .NET Foundation under one or more agreements. | ||
// The .NET Foundation licenses this file to you under the MIT license. | ||
|
||
using System.Threading.Tasks; | ||
using System.Threading; | ||
using Xunit; | ||
using System.Net.WebSockets; | ||
using System.Text; | ||
|
||
namespace System.Runtime.InteropServices.JavaScript.Tests | ||
{ | ||
public class WebWorkerWebSocketTest : WebWorkerTestBase | ||
{ | ||
#region WebSocket | ||
|
||
[Theory, MemberData(nameof(GetTargetThreads))] | ||
public async Task WebSocketClient_ContentInSameThread(Executor executor) | ||
{ | ||
using var cts = CreateTestCaseTimeoutSource(); | ||
|
||
var uri = new Uri(WebWorkerTestHelper.LocalWsEcho + "?guid=" + Guid.NewGuid()); | ||
var message = "hello"; | ||
var send = Encoding.UTF8.GetBytes(message); | ||
var receive = new byte[100]; | ||
|
||
await executor.Execute(async () => | ||
{ | ||
using var client = new ClientWebSocket(); | ||
await client.ConnectAsync(uri, CancellationToken.None); | ||
await client.SendAsync(send, WebSocketMessageType.Text, true, CancellationToken.None); | ||
|
||
var res = await client.ReceiveAsync(receive, CancellationToken.None); | ||
Assert.Equal(WebSocketMessageType.Text, res.MessageType); | ||
Assert.True(res.EndOfMessage); | ||
Assert.Equal(send.Length, res.Count); | ||
Assert.Equal(message, Encoding.UTF8.GetString(receive, 0, res.Count)); | ||
}, cts.Token); | ||
} | ||
|
||
|
||
[Theory, MemberData(nameof(GetTargetThreads2x))] | ||
public async Task WebSocketClient_ResponseCloseInDifferentThread(Executor executor1, Executor executor2) | ||
{ | ||
using var cts = CreateTestCaseTimeoutSource(); | ||
|
||
var uri = new Uri(WebWorkerTestHelper.LocalWsEcho + "?guid=" + Guid.NewGuid()); | ||
var message = "hello"; | ||
var send = Encoding.UTF8.GetBytes(message); | ||
var receive = new byte[100]; | ||
|
||
var e1Job = async (Task e2done, TaskCompletionSource<ClientWebSocket> e1State) => | ||
{ | ||
using var client = new ClientWebSocket(); | ||
await client.ConnectAsync(uri, CancellationToken.None); | ||
await client.SendAsync(send, WebSocketMessageType.Text, true, CancellationToken.None); | ||
|
||
// share the state with the E2 continuation | ||
e1State.SetResult(client); | ||
await e2done; | ||
}; | ||
|
||
var e2Job = async (ClientWebSocket client) => | ||
{ | ||
var res = await client.ReceiveAsync(receive, CancellationToken.None); | ||
Assert.Equal(WebSocketMessageType.Text, res.MessageType); | ||
Assert.True(res.EndOfMessage); | ||
Assert.Equal(send.Length, res.Count); | ||
Assert.Equal(message, Encoding.UTF8.GetString(receive, 0, res.Count)); | ||
|
||
await client.CloseAsync(WebSocketCloseStatus.NormalClosure, "bye", CancellationToken.None); | ||
}; | ||
|
||
await ActionsInDifferentThreads<ClientWebSocket>(executor1, executor2, e1Job, e2Job, cts); | ||
} | ||
|
||
[Theory, MemberData(nameof(GetTargetThreads2x))] | ||
public async Task WebSocketClient_CancelInDifferentThread(Executor executor1, Executor executor2) | ||
{ | ||
using var cts = CreateTestCaseTimeoutSource(); | ||
|
||
var uri = new Uri(WebWorkerTestHelper.LocalWsEcho + "?guid=" + Guid.NewGuid()); | ||
var message = ".delay5sec"; // this will make the loopback server slower | ||
var send = Encoding.UTF8.GetBytes(message); | ||
var receive = new byte[100]; | ||
|
||
var e1Job = async (Task e2done, TaskCompletionSource<ClientWebSocket> e1State) => | ||
{ | ||
using var client = new ClientWebSocket(); | ||
await client.ConnectAsync(uri, CancellationToken.None); | ||
await client.SendAsync(send, WebSocketMessageType.Text, true, CancellationToken.None); | ||
|
||
// share the state with the E2 continuation | ||
e1State.SetResult(client); | ||
await e2done; | ||
}; | ||
|
||
var e2Job = async (ClientWebSocket client) => | ||
{ | ||
CancellationTokenSource cts2 = new CancellationTokenSource(); | ||
var resTask = client.ReceiveAsync(receive, cts2.Token); | ||
cts2.Cancel(); | ||
var ex = await Assert.ThrowsAnyAsync<OperationCanceledException>(() => resTask); | ||
Assert.Equal(cts2.Token, ex.CancellationToken); | ||
}; | ||
|
||
await ActionsInDifferentThreads<ClientWebSocket>(executor1, executor2, e1Job, e2Job, cts); | ||
} | ||
|
||
#endregion | ||
} | ||
} |
Oops, something went wrong.