Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions eng/Versions.props
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
<SdkBandVersion>8.0.100</SdkBandVersion>
<PackageVersionNet6>6.0.10</PackageVersionNet6>
<!-- problematic until NetCoreAppCurrent is net8.0 <PackageVersionNet7>7.0.0</PackageVersionNet7> -->
<PackageVersionForTemplates7>7.0.0-rtm.22476.8</PackageVersionForTemplates7>
<PreReleaseVersionLabel>alpha</PreReleaseVersionLabel>
<PreReleaseVersionIteration>1</PreReleaseVersionIteration>
<!-- Set assembly version to align with major and minor version,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,11 @@
<_WorkloadManifestValues Include="WorkloadVersion" Value="$(PackageVersion)" />
<_WorkloadManifestValues Include="PackageVersionNet7" Value="$(PackageVersionNet7)" Condition="'$(PackageVersionNet7)' != ''" />
<_WorkloadManifestValues Include="PackageVersionNet7" Value="$(PackageVersion)" Condition="'$(PackageVersionNet7)' == ''" />

<!-- We need to use a different version for net7 templates, to differentiate from net8 ones -->
<_WorkloadManifestValues Include="PackageVersionForTemplates7" Value="$(PackageVersionForTemplates7)" Condition="'$(PackageVersionNet7)' == ''" />
<_WorkloadManifestValues Include="PackageVersionForTemplates7" Value="$(PackageVersionNet7)" Condition="'$(PackageVersionNet7)' != ''" />

<_WorkloadManifestValues Include="EmscriptenVersion" Value="$(MicrosoftNETRuntimeEmscriptenVersion)" />
<_WorkloadManifestValues Include="NetCoreAppCurrent" Value="$(NetCoreAppCurrent)" />
</ItemGroup>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,7 @@
},
"Microsoft.NET.Runtime.WebAssembly.Templates.net7": {
"kind": "template",
"version": "${PackageVersionNet7}",
"version": "${PackageVersionForTemplates7}",
"alias-to": {
"any": "Microsoft.NET.Runtime.WebAssembly.Templates"
}
Expand Down
2 changes: 2 additions & 0 deletions src/mono/wasm/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,8 @@ build-dbg-proxy:
$(DOTNET) build $(TOP)/src/mono/wasm/debugger/BrowserDebugHost $(MSBUILD_ARGS)
build-dbg-testsuite:
$(DOTNET) build $(TOP)/src/mono/wasm/debugger/DebuggerTestSuite $(MSBUILD_ARGS)
build-app-host:
$(DOTNET) build $(TOP)/src/mono/wasm/host $(_MSBUILD_WASM_BUILD_ARGS) $(MSBUILD_ARGS)

patch-deterministic:
cd emsdk/upstream/emscripten/ && patch -p1 < ../../../runtime/deterministic.diff
10 changes: 7 additions & 3 deletions src/mono/wasm/Wasm.Build.Tests/BrowserRunner.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
using System.Threading.Tasks;
using Microsoft.Playwright;
using Wasm.Tests.Internal;
using Xunit.Abstractions;

namespace Wasm.Build.Tests;

Expand All @@ -29,6 +30,9 @@ internal class BrowserRunner : IAsyncDisposable
public Task<CommandResult>? RunTask { get; private set; }
public IList<string> OutputLines { get; private set; } = new List<string>();
private TaskCompletionSource<int> _exited = new();
private readonly ITestOutputHelper _testOutput;

public BrowserRunner(ITestOutputHelper testOutput) => _testOutput = testOutput;

// FIXME: options
public async Task<IPage> RunAsync(ToolCommand cmd, string args, bool headless = true)
Expand Down Expand Up @@ -78,7 +82,7 @@ public async Task<IPage> RunAsync(ToolCommand cmd, string args, bool headless =
var url = new Uri(urlAvailable.Task.Result);
Playwright = await Microsoft.Playwright.Playwright.CreateAsync();
string[] chromeArgs = new[] { $"--explicitly-allowed-ports={url.Port}" };
Console.WriteLine($"Launching chrome ('{s_chromePath.Value}') via playwright with args = {string.Join(',', chromeArgs)}");
_testOutput.WriteLine($"Launching chrome ('{s_chromePath.Value}') via playwright with args = {string.Join(',', chromeArgs)}");
Browser = await Playwright.Chromium.LaunchAsync(new BrowserTypeLaunchOptions{
ExecutablePath = s_chromePath.Value,
Headless = headless,
Expand All @@ -99,7 +103,7 @@ public async Task WaitForExitMessageAsync(TimeSpan timeout)
await Task.WhenAny(RunTask!, _exited.Task, Task.Delay(timeout));
if (_exited.Task.IsCompleted)
{
Console.WriteLine ($"Exited with {await _exited.Task}");
_testOutput.WriteLine ($"Exited with {await _exited.Task}");
return;
}

Expand All @@ -114,7 +118,7 @@ public async Task WaitForProcessExitAsync(TimeSpan timeout)
await Task.WhenAny(RunTask!, _exited.Task, Task.Delay(timeout));
if (RunTask.IsCanceled)
{
Console.WriteLine ($"Exited with {(await RunTask).ExitCode}");
_testOutput.WriteLine ($"Exited with {(await RunTask).ExitCode}");
return;
}

Expand Down
5 changes: 5 additions & 0 deletions src/mono/wasm/Wasm.Build.Tests/BuildEnvironment.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ public class BuildEnvironment
public static readonly string RelativeTestAssetsPath = @"..\testassets\";
public static readonly string TestAssetsPath = Path.Combine(AppContext.BaseDirectory, "testassets");
public static readonly string TestDataPath = Path.Combine(AppContext.BaseDirectory, "data");
public static readonly string TmpPath = Path.Combine(Path.GetTempPath(), "wasmbuildtests");

private static readonly Dictionary<string, string> s_runtimePackVersions = new();

Expand Down Expand Up @@ -141,6 +142,10 @@ public BuildEnvironment()
{
LogRootPath = Environment.CurrentDirectory;
}

if (Directory.Exists(TmpPath))
Directory.Delete(TmpPath, recursive: true);
Directory.CreateDirectory(TmpPath);
}

// FIXME: error checks
Expand Down
22 changes: 17 additions & 5 deletions src/mono/wasm/Wasm.Build.Tests/BuildTestBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -290,13 +290,25 @@ protected void InitPaths(string id)
Directory.CreateDirectory(_logPath);
}

protected static void InitProjectDir(string dir)
protected static void InitProjectDir(string dir, bool addNuGetSourceForLocalPackages = false)
{
Directory.CreateDirectory(dir);
File.WriteAllText(Path.Combine(dir, "Directory.Build.props"), s_buildEnv.DirectoryBuildPropsContents);
File.WriteAllText(Path.Combine(dir, "Directory.Build.targets"), s_buildEnv.DirectoryBuildTargetsContents);

File.Copy(Path.Combine(BuildEnvironment.TestDataPath, NuGetConfigFileNameForDefaultFramework), Path.Combine(dir, "nuget.config"));
string targetNuGetConfigPath = Path.Combine(dir, "nuget.config");
if (addNuGetSourceForLocalPackages)
{
File.WriteAllText(targetNuGetConfigPath,
GetNuGetConfigWithLocalPackagesPath(
Path.Combine(BuildEnvironment.TestDataPath, NuGetConfigFileNameForDefaultFramework),
s_buildEnv.BuiltNuGetsPath));
}
else
{
File.Copy(Path.Combine(BuildEnvironment.TestDataPath, NuGetConfigFileNameForDefaultFramework),
targetNuGetConfigPath);
}
Directory.CreateDirectory(Path.Combine(dir, ".nuget"));
}

Expand Down Expand Up @@ -444,10 +456,10 @@ private static string GetNuGetConfigWithLocalPackagesPath(string templatePath, s
return contents.Replace(s_nugetInsertionTag, $@"<add key=""nuget-local"" value=""{localNuGetsPath}"" />");
}

public string CreateWasmTemplateProject(string id, string template = "wasmbrowser")
public string CreateWasmTemplateProject(string id, string template = "wasmbrowser", string extraArgs = "")
{
InitPaths(id);
InitProjectDir(id);
InitProjectDir(id, addNuGetSourceForLocalPackages: true);

File.WriteAllText(Path.Combine(_projectDir, "Directory.Build.props"), "<Project />");
File.WriteAllText(Path.Combine(_projectDir, "Directory.Build.targets"),
Expand All @@ -464,7 +476,7 @@ public string CreateWasmTemplateProject(string id, string template = "wasmbrowse

new DotNetCommand(s_buildEnv, _testOutput, useDefaultArgs: false)
.WithWorkingDirectory(_projectDir!)
.ExecuteWithCapturedOutput($"new {template}")
.ExecuteWithCapturedOutput($"new {template} {extraArgs}")
.EnsureSuccessful();

return Path.Combine(_projectDir!, $"{id}.csproj");
Expand Down
38 changes: 25 additions & 13 deletions src/mono/wasm/Wasm.Build.Tests/WasmTemplateTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -185,10 +185,19 @@ public void ConsoleBuildThenPublish(string config)
[InlineData("Debug", true)]
[InlineData("Release", false)]
[InlineData("Release", true)]
public void ConsoleBuildAndRun(string config, bool relinking)
public void ConsoleBuildAndRunDefault(string config, bool relinking)
=> ConsoleBuildAndRun(config, relinking, string.Empty);

[ConditionalTheory(typeof(BuildTestBase), nameof(IsUsingWorkloads))]
[InlineData("Debug", "-f net7.0")]
[InlineData("Debug", "-f net8.0")]
public void ConsoleBuildAndRunForSpecificTFM(string config, string extraNewArgs)
=> ConsoleBuildAndRun(config, false, extraNewArgs);

private void ConsoleBuildAndRun(string config, bool relinking, string extraNewArgs)
{
string id = $"{config}_{Path.GetRandomFileName()}";
string projectFile = CreateWasmTemplateProject(id, "wasmconsole");
string projectFile = CreateWasmTemplateProject(id, "wasmconsole", extraNewArgs);
string projectName = Path.GetFileNameWithoutExtension(projectFile);

UpdateProgramCS();
Expand Down Expand Up @@ -234,9 +243,9 @@ void AddTestData(bool forConsole, bool runOutsideProjectDirectory)
//data.Add(runOutsideProjectDirectory, forConsole, string.Empty);

data.Add(runOutsideProjectDirectory, forConsole,
$"<OutputPath>{Path.Combine(Path.GetTempPath(), Path.GetRandomFileName())}</OutputPath>");
$"<OutputPath>{Path.Combine(BuildEnvironment.TmpPath, Path.GetRandomFileName())}</OutputPath>");
data.Add(runOutsideProjectDirectory, forConsole,
$"<WasmAppDir>{Path.Combine(Path.GetTempPath(), Path.GetRandomFileName())}</WasmAppDir>");
$"<WasmAppDir>{Path.Combine(BuildEnvironment.TmpPath, Path.GetRandomFileName())}</WasmAppDir>");
}

return data;
Expand All @@ -259,13 +268,13 @@ private async Task BrowserRunTwiceWithAndThenWithoutBuildAsync(string config, st
if (!string.IsNullOrEmpty(extraProperties))
AddItemsPropertiesToProject(projectFile, extraProperties: extraProperties);

string workingDir = runOutsideProjectDirectory ? Path.GetTempPath() : _projectDir!;
string workingDir = runOutsideProjectDirectory ? BuildEnvironment.TmpPath : _projectDir!;

{
using var runCommand = new RunCommand(s_buildEnv, _testOutput)
.WithWorkingDirectory(workingDir);

await using var runner = new BrowserRunner();
await using var runner = new BrowserRunner(_testOutput);
var page = await runner.RunAsync(runCommand, $"run -c {config} --project {projectFile} --forward-console");
await runner.WaitForExitMessageAsync(TimeSpan.FromMinutes(2));
Assert.Contains("Hello, Browser!", string.Join(Environment.NewLine, runner.OutputLines));
Expand All @@ -275,7 +284,7 @@ private async Task BrowserRunTwiceWithAndThenWithoutBuildAsync(string config, st
using var runCommand = new RunCommand(s_buildEnv, _testOutput)
.WithWorkingDirectory(workingDir);

await using var runner = new BrowserRunner();
await using var runner = new BrowserRunner(_testOutput);
var page = await runner.RunAsync(runCommand, $"run -c {config} --no-build --project {projectFile} --forward-console");
await runner.WaitForExitMessageAsync(TimeSpan.FromMinutes(2));
Assert.Contains("Hello, Browser!", string.Join(Environment.NewLine, runner.OutputLines));
Expand All @@ -293,7 +302,7 @@ private Task ConsoleRunWithAndThenWithoutBuildAsync(string config, string extraP
if (!string.IsNullOrEmpty(extraProperties))
AddItemsPropertiesToProject(projectFile, extraProperties: extraProperties);

string workingDir = runOutsideProjectDirectory ? Path.GetTempPath() : _projectDir!;
string workingDir = runOutsideProjectDirectory ? BuildEnvironment.TmpPath : _projectDir!;

{
string runArgs = $"run -c {config} --project {projectFile}";
Expand Down Expand Up @@ -420,7 +429,7 @@ public async Task BlazorRunTest()
using var runCommand = new RunCommand(s_buildEnv, _testOutput)
.WithWorkingDirectory(_projectDir!);

await using var runner = new BrowserRunner();
await using var runner = new BrowserRunner(_testOutput);
var page = await runner.RunAsync(runCommand, $"run -c {config} --no-build");

await page.Locator("text=Counter").ClickAsync();
Expand All @@ -432,12 +441,15 @@ public async Task BlazorRunTest()
Assert.Equal("Current count: 1", txt);
}

[ConditionalFact(typeof(BuildTestBase), nameof(IsUsingWorkloads))]
public async Task BrowserTest()
[ConditionalTheory(typeof(BuildTestBase), nameof(IsUsingWorkloads))]
[InlineData("")]
[InlineData("-f net7.0")]
[InlineData("-f net8.0")]
public async Task BrowserBuildAndRun(string extraNewArgs)
{
string config = "Debug";
string id = $"browser_{config}_{Path.GetRandomFileName()}";
CreateWasmTemplateProject(id, "wasmbrowser");
CreateWasmTemplateProject(id, "wasmbrowser", extraNewArgs);

UpdateBrowserMainJs(DefaultTargetFramework);

Expand All @@ -449,7 +461,7 @@ public async Task BrowserTest()
using var runCommand = new RunCommand(s_buildEnv, _testOutput)
.WithWorkingDirectory(_projectDir!);

await using var runner = new BrowserRunner();
await using var runner = new BrowserRunner(_testOutput);
var page = await runner.RunAsync(runCommand, $"run -c {config} --no-build -r browser-wasm --forward-console");
await runner.WaitForExitMessageAsync(TimeSpan.FromMinutes(2));
Assert.Contains("Hello, Browser!", string.Join(Environment.NewLine, runner.OutputLines));
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System;
using System.Collections.Generic;
using System.IO;
using System.Runtime.ExceptionServices;
Expand Down
6 changes: 3 additions & 3 deletions src/mono/wasm/host/BrowserHost.cs
Original file line number Diff line number Diff line change
Expand Up @@ -71,9 +71,9 @@ private async Task RunAsync(ILoggerFactory loggerFactory, CancellationToken toke
debugging: _args.CommonConfig.Debugging);
runArgsJson.Save(Path.Combine(_args.CommonConfig.AppPath, "runArgs.json"));

var urls = new string[] { $"http://localhost:{_args.CommonConfig.HostProperties.WebServerPort}", "https://localhost:0" };
if (envVars["ASPNETCORE_URLS"] is not null)
urls = envVars["ASPNETCORE_URLS"].Split(new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries);
string[] urls = envVars.TryGetValue("ASPNETCORE_URLS", out string? aspnetUrls)
? aspnetUrls.Split(new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries)
: new string[] { $"http://127.0.0.1:{_args.CommonConfig.HostProperties.WebServerPort}", "https://127.0.0.1:0" };

(ServerURLs serverURLs, IWebHost host) = await StartWebServerAsync(_args.CommonConfig.AppPath,
_args.ForwardConsoleOutput ?? false,
Expand Down
33 changes: 7 additions & 26 deletions src/mono/wasm/host/WebServer.cs
Original file line number Diff line number Diff line change
@@ -1,13 +1,9 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Hosting.Server.Features;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
Expand All @@ -20,7 +16,7 @@ public class WebServer
{
internal static async Task<(ServerURLs, IWebHost)> StartAsync(WebServerOptions options, ILogger logger, CancellationToken token)
{
string[] urls = options.Urls;
TaskCompletionSource<ServerURLs> realUrlsAvailableTcs = new();

IWebHostBuilder builder = new WebHostBuilder()
.UseKestrel()
Expand All @@ -43,37 +39,22 @@ public class WebServer
}
services.AddSingleton(logger);
services.AddSingleton(Options.Create(options));
services.AddSingleton(realUrlsAvailableTcs);
services.AddRouting();
})
.UseUrls(urls);
.UseUrls(options.Urls);

if (options.ContentRootPath != null)
builder.UseContentRoot(options.ContentRootPath);

IWebHost? host = builder.Build();
await host.StartAsync(token);

ICollection<string>? addresses = host.ServerFeatures
.Get<IServerAddressesFeature>()?
.Addresses;
if (token.CanBeCanceled)
token.Register(async () => await host.StopAsync());

string? ipAddress =
addresses?
.Where(a => a.StartsWith("http:", StringComparison.InvariantCultureIgnoreCase))
.Select(a => new Uri(a))
.Select(uri => uri.ToString())
.FirstOrDefault();

string? ipAddressSecure =
addresses?
.Where(a => a.StartsWith("https:", StringComparison.OrdinalIgnoreCase))
.Select(a => new Uri(a))
.Select(uri => uri.ToString())
.FirstOrDefault();

return ipAddress == null || ipAddressSecure == null
? throw new InvalidOperationException("Failed to determine web server's IP address or port")
: (new ServerURLs(ipAddress, ipAddressSecure), host);
ServerURLs serverUrls = await realUrlsAvailableTcs.Task;
return (serverUrls, host);
}

}
Expand Down
Loading