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
113 changes: 110 additions & 3 deletions src/mono/wasm/Wasm.Build.Tests/WasmTemplateTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ public WasmTemplateTests(ITestOutputHelper output, SharedBuildPerTestClassFixtur
{
}

private void updateProgramCS()
private void UpdateProgramCS()
{
string programText = """
Console.WriteLine("Hello, Console!");
Expand Down Expand Up @@ -191,7 +191,7 @@ public void ConsoleBuildAndRun(string config, bool relinking)
string projectFile = CreateWasmTemplateProject(id, "wasmconsole");
string projectName = Path.GetFileNameWithoutExtension(projectFile);

updateProgramCS();
UpdateProgramCS();
UpdateConsoleMainJs();
if (relinking)
AddItemsPropertiesToProject(projectFile, "<WasmBuildNative>true</WasmBuildNative>");
Expand Down Expand Up @@ -219,6 +219,113 @@ public void ConsoleBuildAndRun(string config, bool relinking)
Assert.Contains("args[2] = z", output);
}

public static TheoryData<bool, bool, string> TestDataForAppBundleDir()
{
var data = new TheoryData<bool, bool, string>();
AddTestData(forConsole: true, runOutsideProjectDirectory: false);
AddTestData(forConsole: true, runOutsideProjectDirectory: true);

AddTestData(forConsole: false, runOutsideProjectDirectory: false);
AddTestData(forConsole: false, runOutsideProjectDirectory: true);

void AddTestData(bool forConsole, bool runOutsideProjectDirectory)
{
// FIXME: Disabled for `main` right now, till 7.0 gets the fix
//data.Add(runOutsideProjectDirectory, forConsole, string.Empty);

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

return data;
}

[ConditionalTheory(typeof(BuildTestBase), nameof(IsUsingWorkloads))]
[MemberData(nameof(TestDataForAppBundleDir))]
public async Task RunWithDifferentAppBundleLocations(bool forConsole, bool runOutsideProjectDirectory, string extraProperties)
=> await (forConsole
? ConsoleRunWithAndThenWithoutBuildAsync("Release", extraProperties, runOutsideProjectDirectory)
: BrowserRunTwiceWithAndThenWithoutBuildAsync("Release", extraProperties, runOutsideProjectDirectory));

private async Task BrowserRunTwiceWithAndThenWithoutBuildAsync(string config, string extraProperties = "", bool runOutsideProjectDirectory = false)
{
string id = $"browser_{config}_{Path.GetRandomFileName()}";
string projectFile = CreateWasmTemplateProject(id, "wasmbrowser");

UpdateBrowserMainJs(DefaultTargetFramework);

if (!string.IsNullOrEmpty(extraProperties))
AddItemsPropertiesToProject(projectFile, extraProperties: extraProperties);

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

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

await using var runner = new BrowserRunner();
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));
}

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

await using var runner = new BrowserRunner();
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));
}
}

private Task ConsoleRunWithAndThenWithoutBuildAsync(string config, string extraProperties = "", bool runOutsideProjectDirectory = false)
{
string id = $"console_{config}_{Path.GetRandomFileName()}";
string projectFile = CreateWasmTemplateProject(id, "wasmconsole");

UpdateProgramCS();
UpdateConsoleMainJs();

if (!string.IsNullOrEmpty(extraProperties))
AddItemsPropertiesToProject(projectFile, extraProperties: extraProperties);

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

{
string runArgs = $"run -c {config} --project {projectFile}";
runArgs += " x y z";
using var cmd = new RunCommand(s_buildEnv, _testOutput, label: id)
.WithWorkingDirectory(workingDir)
.WithEnvironmentVariables(s_buildEnv.EnvVars);
var res = cmd.ExecuteWithCapturedOutput(runArgs).EnsureExitCode(42);

Assert.Contains("args[0] = x", res.Output);
Assert.Contains("args[1] = y", res.Output);
Assert.Contains("args[2] = z", res.Output);
}

_testOutput.WriteLine($"{Environment.NewLine}[{id}] Running again with --no-build{Environment.NewLine}");

{
// Run with --no-build
string runArgs = $"run -c {config} --project {projectFile} --no-build";
runArgs += " x y z";
using var cmd = new RunCommand(s_buildEnv, _testOutput, label: id)
.WithWorkingDirectory(workingDir);
var res = cmd.ExecuteWithCapturedOutput(runArgs).EnsureExitCode(42);

Assert.Contains("args[0] = x", res.Output);
Assert.Contains("args[1] = y", res.Output);
Assert.Contains("args[2] = z", res.Output);
}

return Task.CompletedTask;
}

public static TheoryData<string, bool, bool> TestDataForConsolePublishAndRun()
{
var data = new TheoryData<string, bool, bool>();
Expand All @@ -245,7 +352,7 @@ public void ConsolePublishAndRun(string config, bool aot, bool relinking)
string projectFile = CreateWasmTemplateProject(id, "wasmconsole");
string projectName = Path.GetFileNameWithoutExtension(projectFile);

updateProgramCS();
UpdateProgramCS();
UpdateConsoleMainJs();

if (aot)
Expand Down
30 changes: 22 additions & 8 deletions src/mono/wasm/build/WasmApp.targets
Original file line number Diff line number Diff line change
Expand Up @@ -113,20 +113,34 @@

<!-- if DebuggerSupport==true, then ensure that WasmDebugLevel isn't disabling debugging -->
<WasmDebugLevel Condition="('$(WasmDebugLevel)' == '' or '$(WasmDebugLevel)' == '0') and ('$(DebuggerSupport)' == 'true' or '$(Configuration)' == 'Debug')">-1</WasmDebugLevel>
</PropertyGroup>

<PropertyGroup Label="Identify app bundle directory to run from">
<!-- Allow running from custom WasmAppDir -->
<_AppBundleDirForRunCommand Condition="'$(WasmAppDir)' != ''">$(WasmAppDir)</_AppBundleDirForRunCommand>

<!--
This is the default path. We have to build it explicitly because
RuntimeIdentifierInference.targets is imported after this file, and
updates OutputPath to include the RID. So, we don't have the correct
final OutputPath here. But we need it for `dotnet run` to work, as it
just reads the RunCommand after evaluation.

<!-- workaround: RuntimeIdentifierInference.targets is imported after this file, and updates OutputPath to include
the RID. So, we don't have the correct final OutputPath here. But we need it for `dotnet run` to work,
as it just reads the RunCommand after evaluation. -->
<_AppBundleDirForRunCommand Condition="Exists('$(WasmAppDir)/$(AssemblyName).runtimeconfig.json')">$(WasmAppDir)</_AppBundleDirForRunCommand>
<_AppBundleDirForRunCommand Condition="'$(_AppBundleDirForRunCommand)' == '' and Exists('$(OutputPath)/AppBundle')">$([MSBuild]::NormalizeDirectory($(OutputPath), 'AppBundle'))</_AppBundleDirForRunCommand>
<_AppBundleDirForRunCommand Condition="'$(_AppBundleDirForRunCommand)' == '' and Exists('$(OutputPath)/browser-wasm/AppBundle')">$([MSBuild]::NormalizeDirectory($(OutputPath), 'browser-wasm', 'AppBundle'))</_AppBundleDirForRunCommand>
<_AppBundleDirForRunCommand Condition="'$(_AppBundleDirForRunCommand)' == ''">OutputPath=$(OutputPath), OutDir=$(OutDir)</_AppBundleDirForRunCommand>
The path might not have been created yet, for example when creating a new project in VS, so don't use an Exists() check
-->
<_AppBundleDirForRunCommand Condition="'$(_AppBundleDirForRunCommand)' == ''">$([System.IO.Path]::Combine($(OutputPath), 'browser-wasm', 'AppBundle'))</_AppBundleDirForRunCommand>

<!-- Ensure the path is absolute. In case of VS, the cwd might not be the correct one, so explicitly
use $(MSBuildProjectDirectory). -->
<_AppBundleDirForRunCommand Condition="'$(_AppBundleDirForRunCommand)' != '' and !$([System.IO.Path]::IsPathRooted($(_AppBundleDirForRunCommand)))">$([System.IO.Path]::Combine($(MSBuildProjectDirectory), $(_AppBundleDirForRunCommand)))</_AppBundleDirForRunCommand>
</PropertyGroup>

<PropertyGroup Condition="'$(WasmGenerateAppBundle)' == 'true'">
<RunCommand Condition="'$(DOTNET_HOST_PATH)' != '' and Exists($(DOTNET_HOST_PATH))">$(DOTNET_HOST_PATH)</RunCommand>
<RunCommand Condition="'$(RunCommand)' == ''">dotnet</RunCommand>
<RunArguments Condition="'$(RunArguments)' == ''">exec &quot;$([MSBuild]::NormalizePath($(WasmAppHostDir), 'WasmAppHost.dll'))&quot; --runtime-config &quot;$(_AppBundleDirForRunCommand)/$(AssemblyName).runtimeconfig.json&quot; $(WasmHostArguments)</RunArguments>

<_RuntimeConfigJsonPath>$([MSBuild]::NormalizePath($(_AppBundleDirForRunCommand), '$(AssemblyName).runtimeconfig.json'))</_RuntimeConfigJsonPath>
<RunArguments Condition="'$(RunArguments)' == ''">exec &quot;$([MSBuild]::NormalizePath($(WasmAppHostDir), 'WasmAppHost.dll'))&quot; --runtime-config &quot;$(_RuntimeConfigJsonPath)&quot; $(WasmHostArguments)</RunArguments>
<RunWorkingDirectory Condition="'$(RunWorkingDirectory)' == ''">$(_AppBundleDirForRunCommand)</RunWorkingDirectory>
</PropertyGroup>

Expand Down