From 2739be71692ddf24607a4e839a54115eb5f5d33a Mon Sep 17 00:00:00 2001 From: Ankit Jain Date: Sat, 27 Feb 2021 00:46:57 -0500 Subject: [PATCH 01/19] [wasm] Add Wasm.Build tests, for testing wasm app builds These tests will build wasm test projects, as part of each test method, and run them. Other library tests are run with `xharness`, and the test assembly is run under wasm. But here we want to run them with xunit, outside wasm. So, this has different requirements for the helix payload, eg, the sdk, xunit console runner etc. To make it work, a new Scenario - `BuildWasmApps` is added, which emits it's archives in a `buildwasmapps/` folder, which makes it easy to pick up for the helix test run. The tests are added under `src/tests/BuildWasmApps/Wasm.Build.Tests`, but they use `Directory.Build*` from `src/libraries`, similar to how FunctionalTests do it. Another use case of this kinda scenario are the wasm debugger tests, in which the individual test methods launch wasm apps, and then debug them. (TBD) Tests: - The initial set of tests are just proof-of-concept, and more will be added once this is merged. Note: The individual tests build test projects, and then run them with `xharness`, under `v8`, and Chrome. --- eng/pipelines/runtime.yml | 1 + eng/testing/tests.mobile.targets | 19 +- eng/testing/xunit/xunit.console.targets | 2 +- src/libraries/Directory.Build.props | 3 +- src/libraries/sendtohelixhelp.proj | 24 +- src/libraries/tests.proj | 4 + src/mono/wasm/Makefile | 3 + src/mono/wasm/build/WasmApp.LocalBuild.props | 6 +- src/mono/wasm/build/WasmApp.targets | 3 +- src/tests/BuildWasmApps/Directory.Build.props | 6 + .../BuildWasmApps/Directory.Build.targets | 8 + .../Wasm.Build.Tests/Wasm.Build.Tests.csproj | 29 + .../Wasm.Build.Tests/WasmBuildAppTest.cs | 655 ++++++++++++++++++ src/tests/Common/dirs.proj | 1 + 14 files changed, 754 insertions(+), 10 deletions(-) create mode 100644 src/tests/BuildWasmApps/Directory.Build.props create mode 100644 src/tests/BuildWasmApps/Directory.Build.targets create mode 100644 src/tests/BuildWasmApps/Wasm.Build.Tests/Wasm.Build.Tests.csproj create mode 100644 src/tests/BuildWasmApps/Wasm.Build.Tests/WasmBuildAppTest.cs diff --git a/eng/pipelines/runtime.yml b/eng/pipelines/runtime.yml index 931da897d04d5..621711c32adb0 100644 --- a/eng/pipelines/runtime.yml +++ b/eng/pipelines/runtime.yml @@ -298,6 +298,7 @@ jobs: scenarios: - normal - wasmtestonbrowser + - buildwasmapps condition: >- or( eq(variables['librariesContainsChange'], true), diff --git a/eng/testing/tests.mobile.targets b/eng/testing/tests.mobile.targets index f0d3a15095e7c..5b2d8e8148cea 100644 --- a/eng/testing/tests.mobile.targets +++ b/eng/testing/tests.mobile.targets @@ -220,9 +220,26 @@ PrepareForWasmBuildApp;$(WasmBuildAppDependsOn) + $([MSBuild]::NormalizeDirectory('$(RepoRoot)', 'src', 'mono', 'wasm', 'emsdk')) - + + + + + + + + + + + + + diff --git a/eng/testing/xunit/xunit.console.targets b/eng/testing/xunit/xunit.console.targets index ee700551c76b8..a3e7d2614a4f5 100644 --- a/eng/testing/xunit/xunit.console.targets +++ b/eng/testing/xunit/xunit.console.targets @@ -62,7 +62,7 @@ - + $(ArtifactsDir)helix/ $(TestArchiveRoot)tests/ $(TestArchiveRoot)runonly/ + $(TestArchiveRoot)buildwasmapps/ $(TestArchiveTestsRoot)$(OSPlatformConfig)/ $(TestArchiveRoot)runtime/ @@ -170,7 +171,7 @@ false - + diff --git a/src/libraries/sendtohelixhelp.proj b/src/libraries/sendtohelixhelp.proj index e9ac5fbefbc89..83fbf44266b9c 100644 --- a/src/libraries/sendtohelixhelp.proj +++ b/src/libraries/sendtohelixhelp.proj @@ -98,11 +98,19 @@ - + + + true + true + sdk + $([System.IO.File]::ReadAllText('$(RepoRoot)global.json')) + $([System.Text.RegularExpressions.Regex]::Match($(GlobalJsonContent), '(%3F<="dotnet": ").*(%3F=")')) + + @@ -224,6 +232,8 @@ 768968 https://storage.googleapis.com/chromium-browser-snapshots/Linux_x64/$(ChromiumRevision)/chrome-linux.zip https://storage.googleapis.com/chromium-browser-snapshots/Linux_x64/$(ChromiumRevision)/chromedriver_linux64.zip + $([MSBuild]::NormalizeDirectory('$(RepoRoot)', 'src', 'mono', 'wasm', 'emsdk')) + $([MSBuild]::NormalizeDirectory('$(RepoRoot)', 'src', 'mono', 'wasm', 'build')) @@ -237,6 +247,14 @@ + + + + + + + + @@ -244,7 +262,7 @@ <_WorkItem Include="$(WorkItemArchiveWildCard)" Exclude="$(HelixCorrelationPayload)" /> - <_WorkItem Include="$(TestArchiveRoot)runonly/**/WebAssembly.Console.*.Test.zip" Condition="'$(TargetOS)' == 'Browser' and '$(Scenario)' != 'WasmTestOnBrowser'" /> + <_WorkItem Include="$(TestArchiveRoot)runonly/**/WebAssembly.Console.*.Test.zip" Condition="'$(TargetOS)' == 'Browser' and '$(Scenario)' != 'WasmTestOnBrowser' and '$(Scenario)' != 'BuildWasmApps'" /> <_WorkItem Include="$(TestArchiveRoot)runonly/**/WebAssembly.Browser.*.Test.zip" Condition="'$(TargetOS)' == 'Browser' and '$(Scenario)' == 'WasmTestOnBrowser'" /> @@ -254,7 +272,7 @@ - + <_RunOnlyWorkItem Include="$(TestArchiveRoot)runonly/**/*.Console.Sample.zip" /> diff --git a/src/libraries/tests.proj b/src/libraries/tests.proj index b920de0d7c057..4f841f88249f5 100644 --- a/src/libraries/tests.proj +++ b/src/libraries/tests.proj @@ -266,6 +266,10 @@ Condition="'$(TestTrimming)' == 'true'" AdditionalProperties="%(AdditionalProperties);SkipTrimmingProjectsRestore=true" /> + diff --git a/src/mono/wasm/Makefile b/src/mono/wasm/Makefile index a3e15f8454b0a..cbb7e16251fca 100644 --- a/src/mono/wasm/Makefile +++ b/src/mono/wasm/Makefile @@ -182,6 +182,9 @@ run-tests-jsc-%: run-tests-%: PATH="$(JSVU):$(PATH)" $(DOTNET) build $(TOP)/src/libraries/$*/tests/ /t:Test $(_MSBUILD_WASM_BUILD_ARGS) $(MSBUILD_ARGS) +run-build-tests: + PATH="$(JSVU):$(PATH)" $(DOTNET) build $(TOP)/src/tests/BuildWasmApps/Wasm.Build.Tests/ /t:Test $(_MSBUILD_WASM_BUILD_ARGS) $(MSBUILD_ARGS) + run-browser-tests-%: PATH="$(GECKODRIVER):$(CHROMEDRIVER):$(PATH)" XHARNESS_COMMAND="test-browser --browser=$(XHARNESS_BROWSER)" $(DOTNET) build $(TOP)/src/libraries/$*/tests/ /t:Test $(_MSBUILD_WASM_BUILD_ARGS) $(MSBUILD_ARGS) diff --git a/src/mono/wasm/build/WasmApp.LocalBuild.props b/src/mono/wasm/build/WasmApp.LocalBuild.props index b545e5764d8f8..a56d7137dac89 100644 --- a/src/mono/wasm/build/WasmApp.LocalBuild.props +++ b/src/mono/wasm/build/WasmApp.LocalBuild.props @@ -19,8 +19,10 @@ $(WasmBuildSupportDir) - directory which has all the tasks, targets, and runtimepack --> + + - <_NetCoreAppToolCurrent>net5.0 + <_NetCoreAppToolCurrent>net6.0 @@ -52,6 +54,4 @@ $([MSBuild]::NormalizePath('$(WasmBuildTasksDir)', 'WasmBuildTasks.dll')) $([MSBuild]::NormalizePath('$(MonoAOTCompilerDir)', 'MonoAOTCompiler.dll')) - - diff --git a/src/mono/wasm/build/WasmApp.targets b/src/mono/wasm/build/WasmApp.targets index 0bd700e379a36..3be9b5ba13784 100644 --- a/src/mono/wasm/build/WasmApp.targets +++ b/src/mono/wasm/build/WasmApp.targets @@ -69,6 +69,7 @@ + @@ -323,7 +324,7 @@ EMSCRIPTEN_KEEPALIVE void mono_wasm_load_profiler_aot (const char *desc) { mono_ diff --git a/src/tests/BuildWasmApps/Directory.Build.props b/src/tests/BuildWasmApps/Directory.Build.props new file mode 100644 index 0000000000000..68eaef4190505 --- /dev/null +++ b/src/tests/BuildWasmApps/Directory.Build.props @@ -0,0 +1,6 @@ + + + BuildWasmApps + + + diff --git a/src/tests/BuildWasmApps/Directory.Build.targets b/src/tests/BuildWasmApps/Directory.Build.targets new file mode 100644 index 0000000000000..fa2efe47c0815 --- /dev/null +++ b/src/tests/BuildWasmApps/Directory.Build.targets @@ -0,0 +1,8 @@ + + + + + $(OutDir) + $(OutDir)\RunTests.sh + + diff --git a/src/tests/BuildWasmApps/Wasm.Build.Tests/Wasm.Build.Tests.csproj b/src/tests/BuildWasmApps/Wasm.Build.Tests/Wasm.Build.Tests.csproj new file mode 100644 index 0000000000000..e8899b3f8d70a --- /dev/null +++ b/src/tests/BuildWasmApps/Wasm.Build.Tests/Wasm.Build.Tests.csproj @@ -0,0 +1,29 @@ + + + $(NetCoreAppToolCurrent) + true + true + true + BuildAndRun + xunit + false + + + + + + + + + + + + + + $(OutDir) + $(OutDir)\RunTests.sh + find . ; find %24HELIX_CORRELATION_PAYLOAD -type d; set; WasmBuildSupportDir=%24{HELIX_CORRELATION_PAYLOAD}/build HARNESS_RUNNER=%24HARNESS_RUNNER TEST_LOG_PATH=%24XHARNESS_OUT/logs DOTNET_SYSTEM_GLOBALIZATION_INVARIANT=1 dotnet exec xunit.console.dll $(AssemblyName).dll -xml %24XHARNESS_OUT/testResults.xml -nocolor + HARNESS_RUNNER=%24HARNESS_RUNNER TEST_LOG_PATH=%24XHARNESS_OUT/logs dotnet exec xunit.console.dll $(AssemblyName).dll -xml %24XHARNESS_OUT/testResults.xml + + + diff --git a/src/tests/BuildWasmApps/Wasm.Build.Tests/WasmBuildAppTest.cs b/src/tests/BuildWasmApps/Wasm.Build.Tests/WasmBuildAppTest.cs new file mode 100644 index 0000000000000..9e3f10d9a4aea --- /dev/null +++ b/src/tests/BuildWasmApps/Wasm.Build.Tests/WasmBuildAppTest.cs @@ -0,0 +1,655 @@ +// 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.Diagnostics; +using System.IO; +using System.Linq; +using System.Text; +using Xunit; +using Xunit.Abstractions; + +#nullable enable + +namespace Wasm.Build.Tests +{ + public class WasmBuildAppTest : IDisposable + { + private const string TestLogPathEnvVar = "TEST_LOG_PATH"; + private const string SkipProjectCleanupEnvVar = "SKIP_PROJECT_CLEANUP"; + private const string XHarnessRunnerCommandEnvVar = "XHARNESS_CLI_PATH"; + + private readonly string _tempDir; + private readonly ITestOutputHelper _testOutput; + private readonly string _id; + private readonly string _logPath; + + private const string s_targetFramework = "net5.0"; + private static string s_runtimeConfig = "Release"; + private static string s_runtimePackDir; + private static string s_defaultBuildArgs; + private static readonly string s_logRoot; + private static readonly string s_emsdkPath; + private static readonly bool s_skipProjectCleanup; + private static readonly string s_xharnessRunnerCommand; + + static WasmBuildAppTest() + { + DirectoryInfo? solutionRoot = new (AppContext.BaseDirectory); + while (solutionRoot != null) + { + if (File.Exists(Path.Combine(solutionRoot.FullName, "NuGet.config"))) + { + break; + } + + solutionRoot = solutionRoot.Parent; + } + + if (solutionRoot == null) + { + string? buildDir = Environment.GetEnvironmentVariable("WasmBuildSupportDir"); + + if (buildDir == null || !Directory.Exists(buildDir)) + throw new Exception($"Could not find the solution root, or a build dir: {buildDir}"); + + s_emsdkPath = Path.Combine(buildDir, "emsdk"); + s_runtimePackDir = Path.Combine(buildDir, "microsoft.netcore.app.runtime.browser-wasm"); + s_defaultBuildArgs = $" /p:WasmBuildSupportDir={buildDir} /p:EMSDK_PATH={s_emsdkPath} "; + } + else + { + string artifactsBinDir = Path.Combine(solutionRoot.FullName, "artifacts", "bin"); + s_runtimePackDir = Path.Combine(artifactsBinDir, "microsoft.netcore.app.runtime.browser-wasm", s_runtimeConfig); + + string? emsdk = Environment.GetEnvironmentVariable("EMSDK_PATH"); + if (string.IsNullOrEmpty(emsdk)) + emsdk = Path.Combine(solutionRoot.FullName, "src", "mono", "wasm", "emsdk"); + s_emsdkPath = emsdk; + + s_defaultBuildArgs = $" /p:RuntimeSrcDir={solutionRoot.FullName} /p:RuntimeConfig={s_runtimeConfig} /p:EMSDK_PATH={s_emsdkPath} "; + } + + string? logPathEnvVar = Environment.GetEnvironmentVariable(TestLogPathEnvVar); + if (!string.IsNullOrEmpty(logPathEnvVar)) + { + s_logRoot = logPathEnvVar; + if (!Directory.Exists(s_logRoot)) + { + Directory.CreateDirectory(s_logRoot); + } + } + else + { + s_logRoot = Environment.CurrentDirectory; + } + + string? cleanupVar = Environment.GetEnvironmentVariable(SkipProjectCleanupEnvVar); + s_skipProjectCleanup = !string.IsNullOrEmpty(cleanupVar) && cleanupVar == "1"; + + string? harnessVar = Environment.GetEnvironmentVariable(XHarnessRunnerCommandEnvVar); + if (string.IsNullOrEmpty(harnessVar)) + { + throw new Exception($"{XHarnessRunnerCommandEnvVar} not set"); + } + + s_xharnessRunnerCommand = harnessVar; + } + + public WasmBuildAppTest(ITestOutputHelper output) + { + _testOutput = output; + _id = Path.GetRandomFileName(); + _tempDir = Path.Combine(AppContext.BaseDirectory, _id); + Directory.CreateDirectory(_tempDir); + + _logPath = Path.Combine(s_logRoot, _id); + Directory.CreateDirectory(_logPath); + } + + + /* + * TODO: + - AOT modes + - llvmonly + - aotinterp + - skipped assemblies should get have their pinvoke/icall stuff scanned + + - only buildNative + - aot but no wrapper - check that AppBundle wasn't generated + */ + + + public static TheoryData ConfigWithAOTData = new() + { + { "Debug", false }, + { "Release", false }, + { "Debug", true }, + { "Release", true }, + }; + + public static TheoryData InvariantGlobalizationTestData(string config, bool aot) + { + var data = new TheoryData(); + foreach (var configData in ConfigWithAOTData) + { + data.Add((string)configData[0], (bool)configData[1], null); + data.Add((string)configData[0], (bool)configData[1], true); + data.Add((string)configData[0], (bool)configData[1], false); + } + return data; + } + + // TODO: check that icu bits have been linked out + [Theory] + [MemberData(nameof(InvariantGlobalizationTestData))] + public void InvariantGlobalization(string config, bool aot, bool? invariantGlobalization) + { + File.WriteAllText(Path.Combine(_tempDir, "Program.cs"), @" + using System; + using System.Threading.Tasks; + + public class TestClass { + public static int Main() + { + Console.WriteLine(""Hello, World!""); + return 42; + } + } + "); + + string? extraProperties = null; + if (invariantGlobalization != null) + extraProperties = $"{invariantGlobalization}"; + + string projectName = $"invariant_{(invariantGlobalization?.ToString() ?? "unset")}"; + BuildProject(projectName, config, aot: aot, extraProperties: extraProperties, + hasIcudt: invariantGlobalization == null || invariantGlobalization.Value == false); + + RunAndTestWasmApp(projectName, config, isAOT: aot, expectedExitCode: 42, + test: output => Assert.Contains("Hello, World!", output)); + } + + [Theory] + [MemberData(nameof(ConfigWithAOTData))] + public void TopLevelMain(string config, bool aot) + => TestMain("top_level", + @"System.Console.WriteLine(""Hello, World!""); return await System.Threading.Tasks.Task.FromResult(42);", + config, aot); + + [Theory] + [MemberData(nameof(ConfigWithAOTData))] + public void AsyncMain(string config, bool aot) + => TestMain("async_main", @" + using System; + using System.Threading.Tasks; + + public class TestClass { + public static async Task Main() + { + Console.WriteLine(""Hello, World!""); + return await Task.FromResult(42); + } + }", config, aot); + + [Theory] + [MemberData(nameof(ConfigWithAOTData))] + public void NonAsyncMain(string config, bool aot) + => TestMain("non_async_main", @" + using System; + using System.Threading.Tasks; + + public class TestClass { + public static int Main() + { + Console.WriteLine(""Hello, World!""); + return 42; + } + }", config, aot); + + public static TheoryData MainWithArgsTestData() + { + var data = new TheoryData(); + foreach (var configData in ConfigWithAOTData) + { + data.Add((string)configData[0], (bool)configData[1], new string[] { "abc", "foobar" }); + data.Add((string)configData[0], (bool)configData[1], new string[0]); + } + + return data; + } + + [Theory] + [MemberData(nameof(MainWithArgsTestData))] + public void NonAsyncMainWithArgs(string config, bool aot, string[] args) + => TestMainWithArgs("non_async_main_args", @" + public class TestClass { + public static int Main(string[] args) + { + ##CODE## + return 42 + count; + } + }", config, aot, args); + + [Theory] + [MemberData(nameof(MainWithArgsTestData))] + public void AsyncMainWithArgs(string config, bool aot, string[] args) + => TestMainWithArgs("async_main_args", @" + public class TestClass { + public static async System.Threading.Tasks.Task Main(string[] args) + { + ##CODE## + return await System.Threading.Tasks.Task.FromResult(42 + count); + } + }", config, aot, args); + + [Theory] + [MemberData(nameof(MainWithArgsTestData))] + public void TopLevelWithArgs(string config, bool aot, string[] args) + => TestMainWithArgs("top_level_args", + @"##CODE## return await System.Threading.Tasks.Task.FromResult(42 + count);", + config, aot, args); + + void TestMain(string projectName, string programText, string config, bool aot) + { + File.WriteAllText(Path.Combine(_tempDir, "Program.cs"), programText); + BuildProject(projectName, config, aot: aot); + RunAndTestWasmApp(projectName, config, isAOT: aot, expectedExitCode: 42, + test: output => Assert.Contains("Hello, World!", output)); + } + + void TestMainWithArgs(string projectName, string programFormatString, string config, bool aot, string[] args) + { + string code = @" + int count = args == null ? 0 : args.Length; + System.Console.WriteLine($""args#: {args?.Length}""); + foreach (var arg in args ?? System.Array.Empty()) + System.Console.WriteLine($""arg: {arg}""); + "; + string programText = programFormatString.Replace("##CODE##", code); + + File.WriteAllText(Path.Combine(_tempDir, "Program.cs"), programText); + BuildProject(projectName, config, aot: aot); + RunAndTestWasmApp(projectName, config, isAOT: aot, expectedExitCode: 42 + args.Length, args: string.Join(' ', args), + test: output => + { + Assert.Contains($"args#: {args.Length}", output); + foreach (var arg in args) + Assert.Contains($"arg: {arg}", output); + }); + } + + private void RunAndTestWasmApp(string projectName, string config, bool isAOT, Action test, int expectedExitCode=0, string? args=null) + { + Dictionary? envVars = new(); + envVars["XHARNESS_DISABLE_COLORED_OUTPUT"] = "true"; + if (isAOT) + { + envVars["EMSDK_PATH"] = s_emsdkPath; + envVars["MONO_LOG_LEVEL"] = "debug"; + envVars["MONO_LOG_MASK"] = "aot"; + } + + string bundleDir = Path.Combine(GetBinDir(config: config), "AppBundle"); + string v8output = RunWasmTest(projectName, bundleDir, envVars, expectedExitCode, appArgs: args); + Test(v8output); + + string browserOutput = RunWasmTestBrowser(projectName, bundleDir, envVars, expectedExitCode, appArgs: args); + Test(browserOutput); + + void Test(string output) + { + if (isAOT) + { + Assert.Contains("AOT: image 'System.Private.CoreLib' found.", output); + Assert.Contains($"AOT: image '{projectName}' found.", output); + } + else + { + Assert.DoesNotContain("AOT: image 'System.Private.CoreLib' found.", output); + Assert.DoesNotContain($"AOT: image '{projectName}' found.", output); + } + } + } + + private string RunWithXHarness(string testCommand, string relativeLogPath, string projectName, string bundleDir, IDictionary? envVars=null, + int exepectedAppExitCode=0, int xharnessExitCode=0, string? extraXHarnessArgs=null, string? appArgs=null) + { + _testOutput.WriteLine($"============== {testCommand} ============="); + Console.WriteLine($"============== {testCommand} ============="); + string testLogPath = Path.Combine(_logPath, relativeLogPath); + + StringBuilder args = new(); + args.Append($"exec {s_xharnessRunnerCommand}"); + args.Append($" {testCommand}"); + args.Append($" --app=."); + args.Append($" --output-directory={testLogPath}"); + args.Append($" --expected-exit-code={exepectedAppExitCode}"); + args.Append($" {extraXHarnessArgs ?? string.Empty}"); + + args.Append(" -- "); + // App arguments + + if (envVars != null) + { + var setenv = string.Join(' ', envVars.Select(kvp => $"--setenv={kvp.Key}={kvp.Value}").ToArray()); + args.Append($" {setenv}"); + } + + args.Append($" --run {projectName}.dll"); + args.Append($" {appArgs ?? string.Empty}"); + + var (exitCode, output) = RunProcess("dotnet", + args: args.ToString(), + workingDir: bundleDir, + envVars: envVars, + label: testCommand); + + File.WriteAllText(Path.Combine(testLogPath, $"xharness.log"), output); + + if (exitCode != xharnessExitCode) + { + _testOutput.WriteLine($"Exit code: {exitCode}"); + Assert.True(exitCode == exepectedAppExitCode, $"[{testCommand}] Exit code, expected {exepectedAppExitCode} but got {exitCode}"); + } + + return output; + } + private string RunWasmTest(string projectName, string bundleDir, IDictionary? envVars=null, int expectedAppExitCode=0, int xharnessExitCode=0, string? appArgs=null) + => RunWithXHarness("wasm test", "wasm-test", projectName, bundleDir, + envVars: envVars, + exepectedAppExitCode: expectedAppExitCode, + xharnessExitCode: xharnessExitCode, + extraXHarnessArgs: "--js-file=runtime.js --engine=V8 -v trace", + appArgs: appArgs); + + private string RunWasmTestBrowser(string projectName, string bundleDir, IDictionary? envVars=null, int expectedAppExitCode=0, int xharnessExitCode=0, string? appArgs=null) + => RunWithXHarness("wasm test-browser", "wasm-test-browser", projectName, bundleDir, + envVars: envVars, + exepectedAppExitCode: expectedAppExitCode, + xharnessExitCode: expectedAppExitCode, // FIXME: using a different exitcode here because xharness wasm test-browser doesn't have support for --expected-exitcode + extraXHarnessArgs: "-v trace", // needed to get messages like those for AOT loading + appArgs: appArgs); + + private static void InitProjectDir(string dir) + { + File.WriteAllText(Path.Combine(dir, "Directory.Build.props"), s_directoryBuildProps); + File.WriteAllText(Path.Combine(dir, "Directory.Build.targets"), s_directoryBuildTargets); + } + + private void BuildProject(string projectName, + string config, + string? extraBuildArgs = null, + string? extraProperties = null, + bool aot = false, + bool? dotnetWasmFromRuntimePack = null, + bool hasIcudt = true) + { + if (aot) + extraProperties = $"{extraProperties}\ntrue\n"; + + InitProjectDir(_tempDir); + + File.WriteAllText(Path.Combine(_tempDir, $"{projectName}.csproj"), +@$" + + {s_targetFramework} + Exe + true + runtime-test.js + {extraProperties ?? string.Empty} + +"); + + File.Copy(Path.Combine(AppContext.BaseDirectory, "runtime-test.js"), Path.Combine(_tempDir, "runtime-test.js")); + + StringBuilder sb = new(); + sb.Append("publish"); + sb.Append(s_defaultBuildArgs); + + sb.Append($" /p:Configuration={config}"); + + string logFilePath = Path.Combine(_logPath, $"{projectName}.binlog"); + _testOutput.WriteLine($"Binlog path: {logFilePath}"); + sb.Append($" /bl:\"{logFilePath}\" /v:minimal /nologo"); + if (extraBuildArgs != null) + sb.Append($" {extraBuildArgs} "); + + AssertBuild(sb.ToString()); + + string bundleDir = Path.Combine(GetBinDir(config: config), "AppBundle"); + AssertBasicAppBundle(bundleDir, projectName, config, hasIcudt); + + dotnetWasmFromRuntimePack ??= !aot; + AssertDotNetWasmJs(bundleDir, fromRuntimePack: dotnetWasmFromRuntimePack.Value); + } + + private static void AssertBasicAppBundle(string bundleDir, string projectName, string config, bool hasIcudt=true) + { + AssertFilesExist(bundleDir, new [] + { + "index.html", + "runtime.js", + "dotnet.timezones.blat", + "dotnet.wasm", + "mono-config.js", + "dotnet.js", + "run-v8.sh" + }); + + AssertFilesExist(bundleDir, new[] { "icudt.dat" }, expectToExist: hasIcudt); + + string managedDir = Path.Combine(bundleDir, "managed"); + AssertFilesExist(managedDir, new[] { $"{projectName}.dll" }); + + bool is_debug = config == "Debug"; + if (is_debug) + { + // Use cecil to check embedded pdb? + // AssertFilesExist(managedDir, new[] { $"{projectName}.pdb" }); + + //FIXME: um.. what about these? embedded? why is linker omitting them? + //foreach (string file in Directory.EnumerateFiles(managedDir, "*.dll")) + //{ + //string pdb = Path.ChangeExtension(file, ".pdb"); + //Assert.True(File.Exists(pdb), $"Could not find {pdb} for {file}"); + //} + } + } + + private void AssertDotNetWasmJs(string bundleDir, bool fromRuntimePack) + { + string nativeDir = GetRuntimeNativeDir(); + + AssertFile(Path.Combine(nativeDir, "dotnet.wasm"), Path.Combine(bundleDir, "dotnet.wasm"), "Expected dotnet.wasm to be same as the runtime pack", same: fromRuntimePack); + AssertFile(Path.Combine(nativeDir, "dotnet.js"), Path.Combine(bundleDir, "dotnet.js"), "Expected dotnet.js to be same as the runtime pack", same: fromRuntimePack); + } + + private static void AssertFilesDontExist(string dir, string[] filenames, string? label = null) + => AssertFilesExist(dir, filenames, label, expectToExist: false); + + private static void AssertFilesExist(string dir, string[] filenames, string? label = null, bool expectToExist=true) + { + Assert.True(Directory.Exists(dir), $"{dir} not found"); + foreach (string filename in filenames) + { + string path = Path.Combine(dir, filename); + + if (expectToExist) + { + Assert.True(File.Exists(path), + label != null + ? $"{label}: {path} doesn't exist" + : $"{path} doesn't exist"); + } + else + { + Assert.False(File.Exists(path), + label != null + ? $"{label}: {path} should not exist" + : $"{path} should not exist"); + } + } + } + + private static void AssertSameFile(string file0, string file1, string? label=null) => AssertFile(file0, file1, label, same: true); + private static void AssertNotSameFile(string file0, string file1, string? label=null) => AssertFile(file0, file1, label, same: false); + + private static void AssertFile(string file0, string file1, string? label=null, bool same=true) + { + Assert.True(File.Exists(file0), $"Expected to find {file0}"); + Assert.True(File.Exists(file1), $"Expected to find {file1}"); + + FileInfo finfo0 = new(file0); + FileInfo finfo1 = new(file1); + + if (same) + Assert.True(finfo0.Length == finfo1.Length, $"{label}: File sizes don't match for {file0} ({finfo0.Length}), and {file1} ({finfo1.Length})"); + else + Assert.True(finfo0.Length != finfo1.Length, $"{label}: File sizes should not match for {file0} ({finfo0.Length}), and {file1} ({finfo1.Length})"); + } + + private void AssertBuild(string args) + { + (int exitCode, _) = RunProcess("dotnet", args, workingDir: _tempDir, label: "build"); + Assert.True(0 == exitCode, $"Build process exited with non-zero exit code: {exitCode}"); + } + + private string GetObjDir(string targetFramework=s_targetFramework, string? baseDir=null, string config="Debug") + => Path.Combine(baseDir ?? _tempDir, "obj", config, targetFramework, "browser-wasm", "wasm"); + + private string GetBinDir(string targetFramework=s_targetFramework, string? baseDir=null, string config="Debug") + => Path.Combine(baseDir ?? _tempDir, "bin", config, targetFramework, "browser-wasm"); + + private string GetRuntimePackDir() => s_runtimePackDir; + + private string GetRuntimeNativeDir() + => Path.Combine(GetRuntimePackDir(), "runtimes", "browser-wasm", "native"); + + public void Dispose() + { + if (s_skipProjectCleanup) + return; + + try + { + Directory.Delete(_tempDir, recursive: true); + } + catch + { + Console.Error.WriteLine($"Failed to delete '{_tempDir}' during test cleanup"); + } + } + + private (int, string) RunProcess(string path, + string args = "", + IDictionary? envVars = null, + string? workingDir = null, + string? label = null, + bool logToXUnit = true) + { + _testOutput.WriteLine($"Running: {path} {args}"); + StringBuilder outputBuilder = new (); + var processStartInfo = new ProcessStartInfo + { + FileName = path, + UseShellExecute = false, + CreateNoWindow = true, + RedirectStandardError = true, + RedirectStandardOutput = true, + Arguments = args, + }; + + if (workingDir != null) + processStartInfo.WorkingDirectory = workingDir; + + if (envVars != null) + { + if (envVars.Count > 0) + _testOutput.WriteLine("Setting environment variables for execution:"); + + foreach (KeyValuePair envVar in envVars) + { + processStartInfo.EnvironmentVariables[envVar.Key] = envVar.Value; + _testOutput.WriteLine($"\t{envVar.Key} = {envVar.Value}"); + } + } + + Process? process = Process.Start(processStartInfo); + if (process == null) + throw new ArgumentException($"Process.Start({path} {args}) returned null process"); + + process.ErrorDataReceived += (sender, e) => LogData("[stderr]", e.Data); + process.OutputDataReceived += (sender, e) => LogData("[stdout]", e.Data); + + try + { + process.BeginOutputReadLine(); + process.BeginErrorReadLine(); + process.WaitForExit(); + + return (process.ExitCode, outputBuilder.ToString().Trim('\r', '\n')); + } + catch + { + Console.WriteLine(outputBuilder.ToString()); + throw; + } + + void LogData(string label, string? message) + { + if (logToXUnit && message != null) + { + _testOutput.WriteLine($"{label} {message}"); + Console.WriteLine($"{label} {message}"); + } + outputBuilder.AppendLine($"{label} {message}"); + } + } + + private static string s_directoryBuildProps = @" + + <_WasmTargetsDir Condition=""'$(RuntimeSrcDir)' != ''"">$(RuntimeSrcDir)\src\mono\wasm\build\ + <_WasmTargetsDir Condition=""'$(WasmBuildSupportDir)' != ''"">$(WasmBuildSupportDir)\wasm\ + $(WasmBuildSupportDir)\emsdk\ + + + + + + + PrepareForWasmBuild;$(WasmBuildAppDependsOn) + +"; + + private static string s_directoryBuildTargets = @" + + + + + + + + + + + + + + + + + + +"; + + } + + } diff --git a/src/tests/Common/dirs.proj b/src/tests/Common/dirs.proj index e12d882d1dc67..53a064e6e0e0c 100644 --- a/src/tests/Common/dirs.proj +++ b/src/tests/Common/dirs.proj @@ -10,6 +10,7 @@ + From 25c2340a636be7d8973c09b6808a20466fdcd296 Mon Sep 17 00:00:00 2001 From: Ankit Jain Date: Sat, 27 Feb 2021 00:47:59 -0500 Subject: [PATCH 02/19] [wasm] Disable il stripping completely This uses `mono-cil-strip` from a mono installation. And in it's current form it can cause issues, so disabling it for now. --- src/mono/wasm/build/WasmApp.targets | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/mono/wasm/build/WasmApp.targets b/src/mono/wasm/build/WasmApp.targets index 3be9b5ba13784..a903819357228 100644 --- a/src/mono/wasm/build/WasmApp.targets +++ b/src/mono/wasm/build/WasmApp.targets @@ -58,8 +58,10 @@ --> - false - $(RunAOTCompilation) + false + + + <_ExeExt Condition="$([MSBuild]::IsOSPlatform('WINDOWS'))">.exe From 3af97d1f2b3401bade922b1c7febccf3f1440c3b Mon Sep 17 00:00:00 2001 From: Ankit Jain Date: Wed, 3 Mar 2021 12:07:40 -0500 Subject: [PATCH 03/19] Bump helix timeout for tests from 30m to 60m --- src/libraries/sendtohelixhelp.proj | 1 + 1 file changed, 1 insertion(+) diff --git a/src/libraries/sendtohelixhelp.proj b/src/libraries/sendtohelixhelp.proj index 83fbf44266b9c..825641c736c6c 100644 --- a/src/libraries/sendtohelixhelp.proj +++ b/src/libraries/sendtohelixhelp.proj @@ -28,6 +28,7 @@ <_workItemTimeout Condition="'$(_workItemTimeout)' == '' and ('$(TargetOS)' == 'iOS' or '$(TargetOS)' == 'tvOS' or '$(TargetOS)' == 'Android')">00:30:00 <_workItemTimeout Condition="'$(Scenario)' == '' and '$(_workItemTimeout)' == '' and ('$(TargetArchitecture)' == 'arm64' or '$(TargetArchitecture)' == 'arm')">00:45:00 <_workItemTimeout Condition="'$(Scenario)' != '' and '$(_workItemTimeout)' == '' and ('$(TargetArchitecture)' == 'arm64' or '$(TargetArchitecture)' == 'arm')">01:00:00 + <_workItemTimeout Condition="'$(Scenario)' == 'BuildWasmApps' and '$(_workItemTimeout)' == ''">00:60:00 <_workItemTimeout Condition="'$(Scenario)' == '' and '$(_workItemTimeout)' == ''">00:15:00 <_workItemTimeout Condition="'$(Scenario)' != '' and '$(_workItemTimeout)' == ''">00:30:00 From 8ef0923719e580b24f36c4787341bc96a43026f5 Mon Sep 17 00:00:00 2001 From: Ankit Jain Date: Wed, 3 Mar 2021 13:05:14 -0500 Subject: [PATCH 04/19] [wasm] Cleanup builing RunScriptCommand .. this allows supporting other properties from xunit*targets, eg. to run a particular test `$(XUnitMethodName)`, which adds `-method foobar` to the command line. --- eng/testing/tests.mobile.targets | 2 +- .../Wasm.Build.Tests/Wasm.Build.Tests.csproj | 18 ++++++++++++++---- 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/eng/testing/tests.mobile.targets b/eng/testing/tests.mobile.targets index 5b2d8e8148cea..3d0c0b7fdf5f7 100644 --- a/eng/testing/tests.mobile.targets +++ b/eng/testing/tests.mobile.targets @@ -12,7 +12,7 @@ - $HARNESS_RUNNER wasm $XHARNESS_COMMAND --app=. --engine=$(JSEngine) $(JSEngineArgs) --js-file=runtime.js --output-directory=$XHARNESS_OUT -- $(RunTestsJSArguments) --run WasmTestRunner.dll $(AssemblyName).dll + $HARNESS_RUNNER wasm $XHARNESS_COMMAND --app=. --engine=$(JSEngine) $(JSEngineArgs) --js-file=runtime.js --output-directory=$XHARNESS_OUT -- $(RunTestsJSArguments) --run WasmTestRunner.dll $(AssemblyName).dll $HARNESS_RUNNER wasm $XHARNESS_COMMAND --app=. --engine=$(JSEngine) $(JSEngineArgs) --js-file=runtime.js --output-directory=$XHARNESS_OUT --expected-exit-code=$(ExpectedExitCode) -- $(RunTestsJSArguments) --run $(AssemblyName).dll --testing false true diff --git a/src/tests/BuildWasmApps/Wasm.Build.Tests/Wasm.Build.Tests.csproj b/src/tests/BuildWasmApps/Wasm.Build.Tests/Wasm.Build.Tests.csproj index e8899b3f8d70a..0b7d45b6edbbc 100644 --- a/src/tests/BuildWasmApps/Wasm.Build.Tests/Wasm.Build.Tests.csproj +++ b/src/tests/BuildWasmApps/Wasm.Build.Tests/Wasm.Build.Tests.csproj @@ -12,6 +12,19 @@ + + <_PreCommand>WasmBuildSupportDir=%24{HELIX_CORRELATION_PAYLOAD} + <_PreCommand>$(_PreCommand) DOTNET_SYSTEM_GLOBALIZATION_INVARIANT=1 + + + + <_PreCommand>$(_PreCommand) TEST_LOG_PATH=%24{XHARNESS_OUT}/logs + <_PreCommand>$(_PreCommand) HARNESS_RUNNER=%24{HARNESS_RUNNER} + + $(_PreCommand) dotnet exec xunit.console.dll $(AssemblyName).dll -xml %24XHARNESS_OUT/testResults.xml + $(RunScriptCommand) -nocolor + + @@ -19,11 +32,8 @@ + - $(OutDir) - $(OutDir)\RunTests.sh - find . ; find %24HELIX_CORRELATION_PAYLOAD -type d; set; WasmBuildSupportDir=%24{HELIX_CORRELATION_PAYLOAD}/build HARNESS_RUNNER=%24HARNESS_RUNNER TEST_LOG_PATH=%24XHARNESS_OUT/logs DOTNET_SYSTEM_GLOBALIZATION_INVARIANT=1 dotnet exec xunit.console.dll $(AssemblyName).dll -xml %24XHARNESS_OUT/testResults.xml -nocolor - HARNESS_RUNNER=%24HARNESS_RUNNER TEST_LOG_PATH=%24XHARNESS_OUT/logs dotnet exec xunit.console.dll $(AssemblyName).dll -xml %24XHARNESS_OUT/testResults.xml From 03e8730dce82ffa053ca731981e896f3d22f4675 Mon Sep 17 00:00:00 2001 From: Ankit Jain Date: Wed, 3 Mar 2021 13:14:23 -0500 Subject: [PATCH 05/19] [wasm] Fix timeout string, 00:60:00 to 01:00:00 --- src/libraries/sendtohelixhelp.proj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libraries/sendtohelixhelp.proj b/src/libraries/sendtohelixhelp.proj index 825641c736c6c..878313948ae36 100644 --- a/src/libraries/sendtohelixhelp.proj +++ b/src/libraries/sendtohelixhelp.proj @@ -28,7 +28,7 @@ <_workItemTimeout Condition="'$(_workItemTimeout)' == '' and ('$(TargetOS)' == 'iOS' or '$(TargetOS)' == 'tvOS' or '$(TargetOS)' == 'Android')">00:30:00 <_workItemTimeout Condition="'$(Scenario)' == '' and '$(_workItemTimeout)' == '' and ('$(TargetArchitecture)' == 'arm64' or '$(TargetArchitecture)' == 'arm')">00:45:00 <_workItemTimeout Condition="'$(Scenario)' != '' and '$(_workItemTimeout)' == '' and ('$(TargetArchitecture)' == 'arm64' or '$(TargetArchitecture)' == 'arm')">01:00:00 - <_workItemTimeout Condition="'$(Scenario)' == 'BuildWasmApps' and '$(_workItemTimeout)' == ''">00:60:00 + <_workItemTimeout Condition="'$(Scenario)' == 'BuildWasmApps' and '$(_workItemTimeout)' == ''">01:00:00 <_workItemTimeout Condition="'$(Scenario)' == '' and '$(_workItemTimeout)' == ''">00:15:00 <_workItemTimeout Condition="'$(Scenario)' != '' and '$(_workItemTimeout)' == ''">00:30:00 From 9aee29e2a3c1093df918cef30890291c945d79df Mon Sep 17 00:00:00 2001 From: Ankit Jain Date: Wed, 3 Mar 2021 14:56:01 -0500 Subject: [PATCH 06/19] [wasm] Fix path to build support dir --- .../BuildWasmApps/Wasm.Build.Tests/Wasm.Build.Tests.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tests/BuildWasmApps/Wasm.Build.Tests/Wasm.Build.Tests.csproj b/src/tests/BuildWasmApps/Wasm.Build.Tests/Wasm.Build.Tests.csproj index 0b7d45b6edbbc..9f2b78d0c1daa 100644 --- a/src/tests/BuildWasmApps/Wasm.Build.Tests/Wasm.Build.Tests.csproj +++ b/src/tests/BuildWasmApps/Wasm.Build.Tests/Wasm.Build.Tests.csproj @@ -13,7 +13,7 @@ - <_PreCommand>WasmBuildSupportDir=%24{HELIX_CORRELATION_PAYLOAD} + <_PreCommand>WasmBuildSupportDir=%24{HELIX_CORRELATION_PAYLOAD}/build <_PreCommand>$(_PreCommand) DOTNET_SYSTEM_GLOBALIZATION_INVARIANT=1 From 33f6995b0ef82782240125e72f163e375afa4f10 Mon Sep 17 00:00:00 2001 From: Ankit Jain Date: Wed, 3 Mar 2021 14:56:17 -0500 Subject: [PATCH 07/19] cleanup --- .../Wasm.Build.Tests/WasmBuildAppTest.cs | 20 ++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/src/tests/BuildWasmApps/Wasm.Build.Tests/WasmBuildAppTest.cs b/src/tests/BuildWasmApps/Wasm.Build.Tests/WasmBuildAppTest.cs index 9e3f10d9a4aea..6b67c42c60202 100644 --- a/src/tests/BuildWasmApps/Wasm.Build.Tests/WasmBuildAppTest.cs +++ b/src/tests/BuildWasmApps/Wasm.Build.Tests/WasmBuildAppTest.cs @@ -106,6 +106,8 @@ public WasmBuildAppTest(ITestOutputHelper output) _logPath = Path.Combine(s_logRoot, _id); Directory.CreateDirectory(_logPath); + + _testOutput.WriteLine($"Test Id: {_id}"); } @@ -163,7 +165,7 @@ public static int Main() if (invariantGlobalization != null) extraProperties = $"{invariantGlobalization}"; - string projectName = $"invariant_{(invariantGlobalization?.ToString() ?? "unset")}"; + string projectName = $"invariant_{invariantGlobalization?.ToString() ?? "unset"}"; BuildProject(projectName, config, aot: aot, extraProperties: extraProperties, hasIcudt: invariantGlobalization == null || invariantGlobalization.Value == false); @@ -314,7 +316,7 @@ void Test(string output) } private string RunWithXHarness(string testCommand, string relativeLogPath, string projectName, string bundleDir, IDictionary? envVars=null, - int exepectedAppExitCode=0, int xharnessExitCode=0, string? extraXHarnessArgs=null, string? appArgs=null) + int expectedAppExitCode=0, int xharnessExitCode=0, string? extraXHarnessArgs=null, string? appArgs=null) { _testOutput.WriteLine($"============== {testCommand} ============="); Console.WriteLine($"============== {testCommand} ============="); @@ -325,7 +327,7 @@ private string RunWithXHarness(string testCommand, string relativeLogPath, strin args.Append($" {testCommand}"); args.Append($" --app=."); args.Append($" --output-directory={testLogPath}"); - args.Append($" --expected-exit-code={exepectedAppExitCode}"); + args.Append($" --expected-exit-code={expectedAppExitCode}"); args.Append($" {extraXHarnessArgs ?? string.Empty}"); args.Append(" -- "); @@ -351,7 +353,7 @@ private string RunWithXHarness(string testCommand, string relativeLogPath, strin if (exitCode != xharnessExitCode) { _testOutput.WriteLine($"Exit code: {exitCode}"); - Assert.True(exitCode == exepectedAppExitCode, $"[{testCommand}] Exit code, expected {exepectedAppExitCode} but got {exitCode}"); + Assert.True(exitCode == expectedAppExitCode, $"[{testCommand}] Exit code, expected {expectedAppExitCode} but got {exitCode}"); } return output; @@ -359,7 +361,7 @@ private string RunWithXHarness(string testCommand, string relativeLogPath, strin private string RunWasmTest(string projectName, string bundleDir, IDictionary? envVars=null, int expectedAppExitCode=0, int xharnessExitCode=0, string? appArgs=null) => RunWithXHarness("wasm test", "wasm-test", projectName, bundleDir, envVars: envVars, - exepectedAppExitCode: expectedAppExitCode, + expectedAppExitCode: expectedAppExitCode, xharnessExitCode: xharnessExitCode, extraXHarnessArgs: "--js-file=runtime.js --engine=V8 -v trace", appArgs: appArgs); @@ -367,7 +369,7 @@ private string RunWasmTest(string projectName, string bundleDir, IDictionary? envVars=null, int expectedAppExitCode=0, int xharnessExitCode=0, string? appArgs=null) => RunWithXHarness("wasm test-browser", "wasm-test-browser", projectName, bundleDir, envVars: envVars, - exepectedAppExitCode: expectedAppExitCode, + expectedAppExitCode: expectedAppExitCode, xharnessExitCode: expectedAppExitCode, // FIXME: using a different exitcode here because xharness wasm test-browser doesn't have support for --expected-exitcode extraXHarnessArgs: "-v trace", // needed to get messages like those for AOT loading appArgs: appArgs); @@ -471,7 +473,7 @@ private static void AssertFilesDontExist(string dir, string[] filenames, string? private static void AssertFilesExist(string dir, string[] filenames, string? label = null, bool expectToExist=true) { - Assert.True(Directory.Exists(dir), $"{dir} not found"); + Assert.True(Directory.Exists(dir), $"[{label}] {dir} not found"); foreach (string filename in filenames) { string path = Path.Combine(dir, filename); @@ -498,8 +500,8 @@ private static void AssertFilesExist(string dir, string[] filenames, string? lab private static void AssertFile(string file0, string file1, string? label=null, bool same=true) { - Assert.True(File.Exists(file0), $"Expected to find {file0}"); - Assert.True(File.Exists(file1), $"Expected to find {file1}"); + Assert.True(File.Exists(file0), $"{label}: Expected to find {file0}"); + Assert.True(File.Exists(file1), $"{label}: Expected to find {file1}"); FileInfo finfo0 = new(file0); FileInfo finfo1 = new(file1); From ef0e1044f2bc2d04d85f7ff766120ecdb6f6edcd Mon Sep 17 00:00:00 2001 From: Ankit Jain Date: Wed, 3 Mar 2021 17:03:44 -0500 Subject: [PATCH 08/19] [wasm] fix InvariantGlobalization test --- src/tests/BuildWasmApps/Wasm.Build.Tests/WasmBuildAppTest.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tests/BuildWasmApps/Wasm.Build.Tests/WasmBuildAppTest.cs b/src/tests/BuildWasmApps/Wasm.Build.Tests/WasmBuildAppTest.cs index 6b67c42c60202..e11f8f6c9301c 100644 --- a/src/tests/BuildWasmApps/Wasm.Build.Tests/WasmBuildAppTest.cs +++ b/src/tests/BuildWasmApps/Wasm.Build.Tests/WasmBuildAppTest.cs @@ -131,7 +131,7 @@ public WasmBuildAppTest(ITestOutputHelper output) { "Release", true }, }; - public static TheoryData InvariantGlobalizationTestData(string config, bool aot) + public static TheoryData InvariantGlobalizationTestData() { var data = new TheoryData(); foreach (var configData in ConfigWithAOTData) From b07429757cfc125f66f638cbc30b800de7f94f55 Mon Sep 17 00:00:00 2001 From: Ankit Jain Date: Thu, 4 Mar 2021 14:47:54 -0500 Subject: [PATCH 09/19] [wasm] cleanup Wasm.Build.Tests.csproj --- .../BuildWasmApps/Wasm.Build.Tests/Wasm.Build.Tests.csproj | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/tests/BuildWasmApps/Wasm.Build.Tests/Wasm.Build.Tests.csproj b/src/tests/BuildWasmApps/Wasm.Build.Tests/Wasm.Build.Tests.csproj index 9f2b78d0c1daa..b86fa8f8d873c 100644 --- a/src/tests/BuildWasmApps/Wasm.Build.Tests/Wasm.Build.Tests.csproj +++ b/src/tests/BuildWasmApps/Wasm.Build.Tests/Wasm.Build.Tests.csproj @@ -30,10 +30,4 @@ - - - - - - From e0c5a7c6594c9f11de5906520c3cb14ec521a1e2 Mon Sep 17 00:00:00 2001 From: Ankit Jain Date: Thu, 4 Mar 2021 14:44:40 -0500 Subject: [PATCH 10/19] [wasm] Add `include_aot` param for the test data --- .../Wasm.Build.Tests/WasmBuildAppTest.cs | 25 +++++++++++++------ 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/src/tests/BuildWasmApps/Wasm.Build.Tests/WasmBuildAppTest.cs b/src/tests/BuildWasmApps/Wasm.Build.Tests/WasmBuildAppTest.cs index e11f8f6c9301c..e10efa05be282 100644 --- a/src/tests/BuildWasmApps/Wasm.Build.Tests/WasmBuildAppTest.cs +++ b/src/tests/BuildWasmApps/Wasm.Build.Tests/WasmBuildAppTest.cs @@ -123,18 +123,27 @@ public WasmBuildAppTest(ITestOutputHelper output) */ - public static TheoryData ConfigWithAOTData = new() + public static TheoryData ConfigWithAOTData(bool include_aot=true) { - { "Debug", false }, - { "Release", false }, - { "Debug", true }, - { "Release", true }, - }; + TheoryData data = new() + { + { "Debug", false }, + { "Release", false } + }; + + if (include_aot) + { + data.Add("Debug", true); + data.Add("Release", true); + } + + return data; + } public static TheoryData InvariantGlobalizationTestData() { var data = new TheoryData(); - foreach (var configData in ConfigWithAOTData) + foreach (var configData in ConfigWithAOTData()) { data.Add((string)configData[0], (bool)configData[1], null); data.Add((string)configData[0], (bool)configData[1], true); @@ -213,7 +222,7 @@ public static int Main() public static TheoryData MainWithArgsTestData() { var data = new TheoryData(); - foreach (var configData in ConfigWithAOTData) + foreach (var configData in ConfigWithAOTData()) { data.Add((string)configData[0], (bool)configData[1], new string[] { "abc", "foobar" }); data.Add((string)configData[0], (bool)configData[1], new string[0]); From 9600a13b9e5be3577b879ed7eac53f80be6670bc Mon Sep 17 00:00:00 2001 From: Ankit Jain Date: Thu, 4 Mar 2021 15:02:57 -0500 Subject: [PATCH 11/19] [wasm] Enable verbose output for xunit Instead of writing all the output to stdout also, use `-verbose` which gives output like: ``` Wasm.Build.Tests.WasmBuildAppTest.InvariantGlobalization(config: "Debug", aot: False, invariantGlobalization: null) [STARTING] ============== wasm test ============= ============== wasm test-browser ============= Wasm.Build.Tests.WasmBuildAppTest.InvariantGlobalization(config: "Debug", aot: False, invariantGlobalization: null) [FINISHED] Time: 8.6357275s ``` We log the detailed output to files anyway. --- src/tests/BuildWasmApps/Wasm.Build.Tests/Wasm.Build.Tests.csproj | 1 + src/tests/BuildWasmApps/Wasm.Build.Tests/WasmBuildAppTest.cs | 1 - 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tests/BuildWasmApps/Wasm.Build.Tests/Wasm.Build.Tests.csproj b/src/tests/BuildWasmApps/Wasm.Build.Tests/Wasm.Build.Tests.csproj index b86fa8f8d873c..7124f7ef4e0b2 100644 --- a/src/tests/BuildWasmApps/Wasm.Build.Tests/Wasm.Build.Tests.csproj +++ b/src/tests/BuildWasmApps/Wasm.Build.Tests/Wasm.Build.Tests.csproj @@ -23,6 +23,7 @@ $(_PreCommand) dotnet exec xunit.console.dll $(AssemblyName).dll -xml %24XHARNESS_OUT/testResults.xml $(RunScriptCommand) -nocolor + $(RunScriptCommand) -verbose diff --git a/src/tests/BuildWasmApps/Wasm.Build.Tests/WasmBuildAppTest.cs b/src/tests/BuildWasmApps/Wasm.Build.Tests/WasmBuildAppTest.cs index e10efa05be282..7298ed68ae372 100644 --- a/src/tests/BuildWasmApps/Wasm.Build.Tests/WasmBuildAppTest.cs +++ b/src/tests/BuildWasmApps/Wasm.Build.Tests/WasmBuildAppTest.cs @@ -613,7 +613,6 @@ void LogData(string label, string? message) if (logToXUnit && message != null) { _testOutput.WriteLine($"{label} {message}"); - Console.WriteLine($"{label} {message}"); } outputBuilder.AppendLine($"{label} {message}"); } From 8aeec636ddd1a1a82c63d2f98e95286180c68451 Mon Sep 17 00:00:00 2001 From: Ankit Jain Date: Thu, 4 Mar 2021 17:46:09 -0500 Subject: [PATCH 12/19] [wasm] fix tests --- .../BuildWasmApps/Wasm.Build.Tests/WasmBuildAppTest.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/tests/BuildWasmApps/Wasm.Build.Tests/WasmBuildAppTest.cs b/src/tests/BuildWasmApps/Wasm.Build.Tests/WasmBuildAppTest.cs index 7298ed68ae372..792252541e92c 100644 --- a/src/tests/BuildWasmApps/Wasm.Build.Tests/WasmBuildAppTest.cs +++ b/src/tests/BuildWasmApps/Wasm.Build.Tests/WasmBuildAppTest.cs @@ -183,14 +183,14 @@ public static int Main() } [Theory] - [MemberData(nameof(ConfigWithAOTData))] + [MemberData(nameof(ConfigWithAOTData), parameters: /*aot*/ true)] public void TopLevelMain(string config, bool aot) => TestMain("top_level", @"System.Console.WriteLine(""Hello, World!""); return await System.Threading.Tasks.Task.FromResult(42);", config, aot); [Theory] - [MemberData(nameof(ConfigWithAOTData))] + [MemberData(nameof(ConfigWithAOTData), parameters: /*aot*/ true)] public void AsyncMain(string config, bool aot) => TestMain("async_main", @" using System; @@ -205,7 +205,7 @@ public static async Task Main() }", config, aot); [Theory] - [MemberData(nameof(ConfigWithAOTData))] + [MemberData(nameof(ConfigWithAOTData), parameters: /*aot*/ true)] public void NonAsyncMain(string config, bool aot) => TestMain("non_async_main", @" using System; From b94865f8a429d22495496116ee6894afa8a45cc4 Mon Sep 17 00:00:00 2001 From: Ankit Jain Date: Thu, 4 Mar 2021 18:23:21 -0500 Subject: [PATCH 13/19] [wasm] Really enable verbose output for xunit, this time --- .../BuildWasmApps/Wasm.Build.Tests/Wasm.Build.Tests.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tests/BuildWasmApps/Wasm.Build.Tests/Wasm.Build.Tests.csproj b/src/tests/BuildWasmApps/Wasm.Build.Tests/Wasm.Build.Tests.csproj index 7124f7ef4e0b2..a6fe3e49f375d 100644 --- a/src/tests/BuildWasmApps/Wasm.Build.Tests/Wasm.Build.Tests.csproj +++ b/src/tests/BuildWasmApps/Wasm.Build.Tests/Wasm.Build.Tests.csproj @@ -23,7 +23,7 @@ $(_PreCommand) dotnet exec xunit.console.dll $(AssemblyName).dll -xml %24XHARNESS_OUT/testResults.xml $(RunScriptCommand) -nocolor - $(RunScriptCommand) -verbose + $(RunScriptCommand) -verbose From 33efd200af8e4db430e0620d7d9d777ed7287837 Mon Sep 17 00:00:00 2001 From: Ankit Jain Date: Thu, 4 Mar 2021 22:10:55 -0500 Subject: [PATCH 14/19] [wasm] Update tests to track the xharness fix for expected-exit-code --- src/tests/BuildWasmApps/Wasm.Build.Tests/WasmBuildAppTest.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/tests/BuildWasmApps/Wasm.Build.Tests/WasmBuildAppTest.cs b/src/tests/BuildWasmApps/Wasm.Build.Tests/WasmBuildAppTest.cs index 792252541e92c..c6ff9aa45d312 100644 --- a/src/tests/BuildWasmApps/Wasm.Build.Tests/WasmBuildAppTest.cs +++ b/src/tests/BuildWasmApps/Wasm.Build.Tests/WasmBuildAppTest.cs @@ -371,7 +371,6 @@ private string RunWasmTest(string projectName, string bundleDir, IDictionary RunWithXHarness("wasm test", "wasm-test", projectName, bundleDir, envVars: envVars, expectedAppExitCode: expectedAppExitCode, - xharnessExitCode: xharnessExitCode, extraXHarnessArgs: "--js-file=runtime.js --engine=V8 -v trace", appArgs: appArgs); @@ -379,7 +378,6 @@ private string RunWasmTestBrowser(string projectName, string bundleDir, IDiction => RunWithXHarness("wasm test-browser", "wasm-test-browser", projectName, bundleDir, envVars: envVars, expectedAppExitCode: expectedAppExitCode, - xharnessExitCode: expectedAppExitCode, // FIXME: using a different exitcode here because xharness wasm test-browser doesn't have support for --expected-exitcode extraXHarnessArgs: "-v trace", // needed to get messages like those for AOT loading appArgs: appArgs); From ac147c7892b32fbd512bdc41e3dad78be2f18a4d Mon Sep 17 00:00:00 2001 From: Ankit Jain Date: Fri, 5 Mar 2021 01:11:29 -0500 Subject: [PATCH 15/19] [wasm] Bump browser job's timeout from 120 to 180 mins --- eng/pipelines/runtime.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/eng/pipelines/runtime.yml b/eng/pipelines/runtime.yml index 621711c32adb0..eaaec1b2eb939 100644 --- a/eng/pipelines/runtime.yml +++ b/eng/pipelines/runtime.yml @@ -283,7 +283,7 @@ jobs: testGroup: innerloop nameSuffix: AllSubsets_Mono buildArgs: -s mono+libs+host+packs+libs.tests -c $(_BuildConfig) /p:ArchiveTests=true - timeoutInMinutes: 120 + timeoutInMinutes: 180 condition: >- or( eq(dependencies.evaluate_paths.outputs['SetPathVars_libraries.containsChange'], true), From 2bf3845fbc4a9d1fd298cbceca8dc49729548875 Mon Sep 17 00:00:00 2001 From: Ankit Jain Date: Mon, 8 Mar 2021 13:13:45 -0500 Subject: [PATCH 16/19] Improve comment Co-authored-by: Mitchell Hwang --- eng/testing/tests.mobile.targets | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/eng/testing/tests.mobile.targets b/eng/testing/tests.mobile.targets index 0c79d0e89d20a..7cecd74999be7 100644 --- a/eng/testing/tests.mobile.targets +++ b/eng/testing/tests.mobile.targets @@ -237,11 +237,7 @@ - + From 31d5d2ff018a5657fc4a5880af548d28d89612c6 Mon Sep 17 00:00:00 2001 From: Ankit Jain Date: Mon, 8 Mar 2021 14:09:56 -0500 Subject: [PATCH 17/19] Update eng/testing/tests.mobile.targets Co-authored-by: Mitchell Hwang --- eng/testing/tests.mobile.targets | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/eng/testing/tests.mobile.targets b/eng/testing/tests.mobile.targets index 7cecd74999be7..b2e875f120bb6 100644 --- a/eng/testing/tests.mobile.targets +++ b/eng/testing/tests.mobile.targets @@ -237,7 +237,9 @@ - + From ead13ee3d9c6d53a22b3c3051542057373c77b31 Mon Sep 17 00:00:00 2001 From: Ankit Jain Date: Mon, 8 Mar 2021 17:31:03 -0500 Subject: [PATCH 18/19] Remove unrelated commit Instead, this is moved to a different AOT PR. Revert "[wasm] Disable il stripping completely" This reverts commit 25c2340a636be7d8973c09b6808a20466fdcd296. --- src/mono/wasm/build/WasmApp.targets | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/mono/wasm/build/WasmApp.targets b/src/mono/wasm/build/WasmApp.targets index a903819357228..3be9b5ba13784 100644 --- a/src/mono/wasm/build/WasmApp.targets +++ b/src/mono/wasm/build/WasmApp.targets @@ -58,10 +58,8 @@ --> - false - - - + false + $(RunAOTCompilation) <_ExeExt Condition="$([MSBuild]::IsOSPlatform('WINDOWS'))">.exe From 7be536d440fe5bb4fb7e1e3b89bf60d8e7152a36 Mon Sep 17 00:00:00 2001 From: Ankit Jain Date: Tue, 9 Mar 2021 00:18:22 -0500 Subject: [PATCH 19/19] Revert "Remove unrelated commit" This is needed because `mono-cil-strip` isn't available on helix. And we want to disable cil stripping anyway. This reverts commit ead13ee3d9c6d53a22b3c3051542057373c77b31. --- src/mono/wasm/build/WasmApp.targets | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/mono/wasm/build/WasmApp.targets b/src/mono/wasm/build/WasmApp.targets index 3be9b5ba13784..a903819357228 100644 --- a/src/mono/wasm/build/WasmApp.targets +++ b/src/mono/wasm/build/WasmApp.targets @@ -58,8 +58,10 @@ --> - false - $(RunAOTCompilation) + false + + + <_ExeExt Condition="$([MSBuild]::IsOSPlatform('WINDOWS'))">.exe