Skip to content

Commit

Permalink
Ability to run E2E tests on WebAssembly multithreaded runtime (#54351)
Browse files Browse the repository at this point in the history
  • Loading branch information
SteveSandersonMS authored Mar 11, 2024
1 parent 4f9df78 commit 7c60951
Show file tree
Hide file tree
Showing 13 changed files with 75 additions and 6 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using TestServer;
using DevHostServerProgram = Microsoft.AspNetCore.Components.WebAssembly.DevServer.Server.Program;

namespace Microsoft.AspNetCore.Components.E2ETest.Infrastructure.ServerFixtures;
Expand Down Expand Up @@ -60,6 +61,11 @@ protected override IHost CreateWebHost()
args.Add(Environment);
}

if (WebAssemblyTestHelper.MultithreadingIsEnabled())
{
args.Add("--apply-cop-headers");
}

return DevHostServerProgram.BuildWebHost(args.ToArray());
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
// Mount the server-side Blazor app on /subdir
app.Map("/subdir", app =>
{
WebAssemblyTestHelper.ServeCoopHeadersIfWebAssemblyThreadingEnabled(app);
app.UseBlazorFrameworkFiles();
app.UseStaticFiles();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
app.Map("/subdir", app =>
{
// Add it before to ensure it takes priority over files in wwwroot
WebAssemblyTestHelper.ServeCoopHeadersIfWebAssemblyThreadingEnabled(app);
app.UseBlazorFrameworkFiles();
app.UseStaticFiles();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
// Mount the server-side Blazor app on /subdir
app.Map("/subdir", app =>
{
WebAssemblyTestHelper.ServeCoopHeadersIfWebAssemblyThreadingEnabled(app);
app.UseBlazorFrameworkFiles();
app.UseStaticFiles();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
app.UseDeveloperExceptionPage();
}

WebAssemblyTestHelper.ServeCoopHeadersIfWebAssemblyThreadingEnabled(app);
app.UseBlazorFrameworkFiles();
app.UseStaticFiles();
app.UseRouting();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
// Mount the server-side Blazor app on /subdir
app.Map("/subdir", app =>
{
WebAssemblyTestHelper.ServeCoopHeadersIfWebAssemblyThreadingEnabled(app);
app.UseBlazorFrameworkFiles();
app.UseStaticFiles();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ public void Configure(IApplicationBuilder app, IWebHostEnvironment env)

app.Map("/Client/multiple-components", app =>
{
WebAssemblyTestHelper.ServeCoopHeadersIfWebAssemblyThreadingEnabled(app);
app.UseBlazorFrameworkFiles();
app.UseStaticFiles();
app.UseRouting();
Expand Down
19 changes: 13 additions & 6 deletions src/Components/test/testassets/Components.TestServer/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -54,14 +54,21 @@ private static (IHost host, string basePath) CreateDevServerHost(string[] args)
var contentRoot = typeof(Program).Assembly.GetCustomAttributes<AssemblyMetadataAttribute>()
.Single(a => a.Key == "Microsoft.AspNetCore.InternalTesting.BasicTestApp.ContentRoot")
.Value;
var finalArgs = new List<string>();
finalArgs.AddRange(args);
finalArgs.AddRange(
[
"--contentroot", contentRoot,
"--pathbase", "/subdir",
"--applicationpath", typeof(BasicTestApp.Program).Assembly.Location,
]);

var finalArgs = args.Concat(new[]
if (WebAssemblyTestHelper.MultithreadingIsEnabled())
{
"--contentroot", contentRoot,
"--pathbase", "/subdir",
"--applicationpath", typeof(BasicTestApp.Program).Assembly.Location,
}).ToArray();
var host = DevServerProgram.BuildWebHost(finalArgs);
finalArgs.Add("--apply-cop-headers");
}

var host = DevServerProgram.BuildWebHost(finalArgs.ToArray());
return (host, "/subdir");
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,8 @@ public void Configure(IApplicationBuilder app, IWebHostEnvironment env)

app.Map("/subdir", app =>
{
WebAssemblyTestHelper.ServeCoopHeadersIfWebAssemblyThreadingEnabled(app);

if (!env.IsDevelopment())
{
app.UseExceptionHandler("/Error", createScopeForErrors: true);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
app.UseDeveloperExceptionPage();
}

WebAssemblyTestHelper.ServeCoopHeadersIfWebAssemblyThreadingEnabled(app);
app.UseBlazorFrameworkFiles();
app.UseStaticFiles();
app.UseRouting();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
// The client-side files middleware needs to be here because the base href in hardcoded to /subdir/
app.Map("/subdir", subApp =>
{
WebAssemblyTestHelper.ServeCoopHeadersIfWebAssemblyThreadingEnabled(app);
subApp.UseBlazorFrameworkFiles();
subApp.UseStaticFiles();

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System.Reflection;

namespace TestServer;

public static class WebAssemblyTestHelper
{
public static bool MultithreadingIsEnabled()
{
var entrypointAssembly = Assembly.GetExecutingAssembly();
var attribute = entrypointAssembly.GetCustomAttributes<AssemblyMetadataAttribute>()
.FirstOrDefault(x => x.Key.Equals("Microsoft.AspNetCore.InternalTesting.RunWebAssemblyE2ETestsWithMultithreading", StringComparison.Ordinal));
return attribute is not null && bool.Parse(attribute.Value);
}

public static void ServeCoopHeadersIfWebAssemblyThreadingEnabled(IApplicationBuilder app)
{
if (MultithreadingIsEnabled())
{
app.Use(async (ctx, next) =>
{
// Browser multi-threaded runtime requires cross-origin policy headers to enable SharedArrayBuffer.
ctx.Response.Headers.Append("Cross-Origin-Embedder-Policy", "require-corp");
ctx.Response.Headers.Append("Cross-Origin-Opener-Policy", "same-origin");
await next(ctx);
});
}
}
}
15 changes: 15 additions & 0 deletions src/Components/test/testassets/Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,20 @@

<PropertyGroup>
<EnableTypeScriptNuGetTarget>true</EnableTypeScriptNuGetTarget>

<!--
This controls whether the WebAssembly E2E tests run with the multithreaded runtime or not.
It also implicitly sets an assembly metadata attribute so the test servers will serve the COOP
headers if and only if this flag is set. Note that until https://github.com/dotnet/runtime/issues/98502
is fixed, you will have to delete artifacts\obj directories after changing this flag.
-->
<!--<WasmEnableThreads>true</WasmEnableThreads>-->
</PropertyGroup>

<ItemGroup>
<AssemblyAttribute Include="System.Reflection.AssemblyMetadataAttribute" Condition="'$(WasmEnableThreads)' == 'true'">
<_Parameter1>Microsoft.AspNetCore.InternalTesting.RunWebAssemblyE2ETestsWithMultithreading</_Parameter1>
<_Parameter2>true</_Parameter2>
</AssemblyAttribute>
</ItemGroup>
</Project>

0 comments on commit 7c60951

Please sign in to comment.