Skip to content
2 changes: 2 additions & 0 deletions eng/testing/scenarios/BuildWasmAppsJobsList.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ Wasm.Build.Tests.BlazorWasmBuildPublishTests
Wasm.Build.Tests.BlazorWasmTests
Wasm.Build.Tests.BuildPublishTests
Wasm.Build.Tests.CleanTests
Wasm.Build.Tests.ConfigSrcTests
Wasm.Build.Tests.InvariantGlobalizationTests
Wasm.Build.Tests.LocalEMSDKTests
Wasm.Build.Tests.MainWithArgsTests
Expand All @@ -17,4 +18,5 @@ Wasm.Build.Tests.SatelliteAssembliesTests
Wasm.Build.Tests.WasmBuildAppTest
Wasm.Build.Tests.WasmNativeDefaultsTests
Wasm.Build.Tests.WorkloadTests
Wasm.Build.Tests.WasmRunOutOfAppBundleTests
Wasm.Build.Tests.WasmTemplateTests
6 changes: 5 additions & 1 deletion src/mono/wasm/test-main.js
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,7 @@ function initRunArgs() {
runArgs.enableGC = runArgs.enableGC === undefined ? true : runArgs.enableGC;
runArgs.diagnosticTracing = runArgs.diagnosticTracing === undefined ? false : runArgs.diagnosticTracing;
runArgs.debugging = runArgs.debugging === undefined ? false : runArgs.debugging;
runArgs.configSrc = runArgs.configSrc === undefined ? './mono-config.json' : runArgs.configSrc;
// default'ing to true for tests, unless debugging
runArgs.forwardConsole = runArgs.forwardConsole === undefined ? !runArgs.debugging : runArgs.forwardConsole;
}
Expand Down Expand Up @@ -217,6 +218,9 @@ function processQueryArguments(incomingArguments) {
} else {
console.warn("--fetch-random-delay only works on browser")
}
} else if (currentArg.startsWith("--config-src=")) {
const arg = currentArg.substring("--config-src=".length);
runArgs.configSrc = arg;
} else {
break;
}
Expand Down Expand Up @@ -355,7 +359,7 @@ Promise.all([argsPromise, loadDotnetPromise]).then(async ([_, createDotnetRuntim
return createDotnetRuntime(({ MONO, INTERNAL, BINDING, IMPORTS, EXPORTS, Module }) => ({
disableDotnet6Compatibility: true,
config: null,
configSrc: "./mono-config.json",
configSrc: runArgs.configSrc || "./mono-config.json",
onConfigLoaded: (config) => {
if (!Module.config) {
const err = new Error("Could not find ./mono-config.json. Cancelling run");
Expand Down
7 changes: 4 additions & 3 deletions src/tests/BuildWasmApps/Wasm.Build.Tests/BuildTestBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,8 @@ protected string RunAndTestWasmApp(BuildArgs buildArgs,
string? args = null,
Dictionary<string, string>? envVars = null,
string targetFramework = DefaultTargetFramework,
string? extraXHarnessMonoArgs = null)
string? extraXHarnessMonoArgs = null,
string jsRelativePath = "test-main.js")
{
buildDir ??= _projectDir;
envVars ??= new();
Expand All @@ -156,8 +157,8 @@ protected string RunAndTestWasmApp(BuildArgs buildArgs,
// Use wasm-console.log to get the xharness output for non-browser cases
(string testCommand, string extraXHarnessArgs, bool useWasmConsoleOutput) = host switch
{
RunHost.V8 => ("wasm test", "--js-file=test-main.js --engine=V8 -v trace", true),
RunHost.NodeJS => ("wasm test", "--js-file=test-main.js --engine=NodeJS -v trace", true),
RunHost.V8 => ("wasm test", $"--js-file={jsRelativePath} --engine=V8 -v trace", true),
RunHost.NodeJS => ("wasm test", $"--js-file={jsRelativePath} --engine=NodeJS -v trace", true),
_ => ("wasm test-browser", $"-v trace -b {host} --web-server-use-cop", false)
};

Expand Down
38 changes: 38 additions & 0 deletions src/tests/BuildWasmApps/Wasm.Build.Tests/ConfigSrcTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System.IO;
using Xunit;
using Xunit.Abstractions;

#nullable enable

namespace Wasm.Build.Tests
{
public class ConfigSrcTests : BuildTestBase
{
public ConfigSrcTests(ITestOutputHelper output, SharedBuildPerTestClassFixture buildContext) : base(output, buildContext)
{}

// NOTE: port number determinizes dynamically, so could not generate absolute URI
[Theory]
[BuildAndRun(host: RunHost.V8 | RunHost.NodeJS)]
public void ConfigSrcAbsolutePath(BuildArgs buildArgs, RunHost host, string id)
{
buildArgs = buildArgs with { ProjectName = $"configsrcabsolute_{buildArgs.Config}_{buildArgs.AOT}" };
buildArgs = ExpandBuildArgs(buildArgs);

BuildProject(buildArgs,
id: id,
new BuildProjectOptions(
InitProject: () => File.WriteAllText(Path.Combine(_projectDir!, "Program.cs"), s_mainReturns42),
DotnetWasmFromRuntimePack: !(buildArgs.AOT || buildArgs.Config == "Release")));

string binDir = GetBinDir(baseDir: _projectDir!, config: buildArgs.Config);
string bundleDir = Path.Combine(binDir, "AppBundle");
string configSrc = Path.GetFullPath(Path.Combine(bundleDir, "mono-config.json"));

RunAndTestWasmApp(buildArgs, expectedExitCode: 42, host: host, id: id, extraXHarnessMonoArgs: $"--config-src={configSrc}");
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System.IO;
using Xunit;
using Xunit.Abstractions;

#nullable enable

namespace Wasm.Build.Tests
{
public class WasmRunOutOfAppBundleTests : BuildTestBase
{
public WasmRunOutOfAppBundleTests(ITestOutputHelper output, SharedBuildPerTestClassFixture buildContext) : base(output, buildContext)
{}

[Theory]
[BuildAndRun]
public void RunOutOfAppBundle(BuildArgs buildArgs, RunHost host, string id)
{
buildArgs = buildArgs with { ProjectName = $"outofappbundle_{buildArgs.Config}_{buildArgs.AOT}" };
buildArgs = ExpandBuildArgs(buildArgs);

BuildProject(buildArgs,
id: id,
new BuildProjectOptions(
InitProject: () => File.WriteAllText(Path.Combine(_projectDir!, "Program.cs"), s_mainReturns42),
DotnetWasmFromRuntimePack: !(buildArgs.AOT || buildArgs.Config == "Release")));

string binDir = GetBinDir(baseDir: _projectDir!, config: buildArgs.Config);
string appBundleDir = Path.Combine(binDir, "AppBundle");
string tmpBundleDirName = "AppBundleTmp";
string tmpBundleDir = Path.Combine(binDir, tmpBundleDirName);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What do you think of creating this tmpBundleDir in a completely different location, like under Path.GetTempPath()? This would ensure that it isn't dependent on anything in the binDir.
And make sure to add id, and the project name to the dir name, so the different runs don't overlap.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is a good method in Node and V8 environments!
I' ll change that style.

However, browsers like Chrome cannot explore the parent directory, so I would like to keep the current style.


if (host == RunHost.Chrome)
{
Directory.Move(appBundleDir, tmpBundleDir);
Directory.CreateDirectory(appBundleDir);
// Create $binDir/AppBundle/AppBundle
Directory.Move(tmpBundleDir, Path.Combine(appBundleDir, "AppBundle"));

string indexHtmlPath = Path.Combine(appBundleDir, "index.html");
if (!File.Exists(indexHtmlPath))
{
var html = @"<html><body><script type=""module"" src=""./AppBundle/test-main.js""></script></body></html>";
File.WriteAllText(indexHtmlPath, html);
}
} else {
CopyAllFiles(appBundleDir, tmpBundleDir);
}

RunAndTestWasmApp(buildArgs, expectedExitCode: 42, host: host, id: id, jsRelativePath: $"../{tmpBundleDirName}/test-main.js");

// Restore AppBundle Dir
if (host == RunHost.Chrome)
{
Directory.Move(Path.Combine(appBundleDir, "AppBundle"), tmpBundleDir);
Directory.Delete(appBundleDir, true);
Directory.Move(tmpBundleDir, appBundleDir);
} else {
Directory.Delete(tmpBundleDir, true);
}
}

private void CopyAllFiles(string srcDir, string destDir)
{
if (!Directory.Exists(destDir))
{
Directory.CreateDirectory(destDir);
}

foreach (var file in Directory.GetFiles(srcDir))
{
File.Copy(file, Path.Combine(destDir, Path.GetFileName(file)), true);
}

foreach (var directory in Directory.GetDirectories(srcDir))
{
CopyAllFiles(directory, Path.Combine(destDir, Path.GetFileName(directory)));
}
}
}
}